2
2
/*
3
3
* Turris Mox rWTM firmware driver
4
4
*
5
- * Copyright (C) 2019, 2024 Marek Behún <[email protected] >
5
+ * Copyright (C) 2019, 2024, 2025 Marek Behún <[email protected] >
6
6
*/
7
7
8
+ #include <crypto/sha2.h>
8
9
#include <linux/align.h>
9
10
#include <linux/armada-37xx-rwtm-mailbox.h>
11
+ #include <linux/cleanup.h>
10
12
#include <linux/completion.h>
11
13
#include <linux/container_of.h>
12
14
#include <linux/device.h>
13
15
#include <linux/dma-mapping.h>
14
16
#include <linux/err.h>
15
17
#include <linux/hw_random.h>
16
18
#include <linux/if_ether.h>
19
+ #include <linux/key.h>
17
20
#include <linux/kobject.h>
18
21
#include <linux/mailbox_client.h>
22
+ #include <linux/math.h>
19
23
#include <linux/minmax.h>
20
24
#include <linux/module.h>
21
25
#include <linux/mutex.h>
22
26
#include <linux/platform_device.h>
23
27
#include <linux/sizes.h>
24
28
#include <linux/sysfs.h>
29
+ #include <linux/turris-signing-key.h>
25
30
#include <linux/types.h>
26
31
27
32
#define DRIVER_NAME "turris-mox-rwtm"
34
39
* https://gitlab.labs.nic.cz/turris/mox-boot-builder/tree/master/wtmi.
35
40
*/
36
41
42
+ enum {
43
+ MOX_ECC_NUM_BITS = 521 ,
44
+ MOX_ECC_NUM_LEN = DIV_ROUND_UP (MOX_ECC_NUM_BITS , 8 ),
45
+ MOX_ECC_NUM_WORDS = DIV_ROUND_UP (MOX_ECC_NUM_BITS , 32 ),
46
+ MOX_ECC_SIG_LEN = 2 * MOX_ECC_NUM_LEN ,
47
+ MOX_ECC_PUBKEY_LEN = 1 + MOX_ECC_NUM_LEN ,
48
+ };
49
+
37
50
#define MBOX_STS_SUCCESS (0 << 30)
38
51
#define MBOX_STS_FAIL (1 << 30)
39
52
#define MBOX_STS_BADCMD (2 << 30)
@@ -69,6 +82,7 @@ enum mbox_cmd {
69
82
* @ram_size: RAM size of the device
70
83
* @mac_address1: first MAC address of the device
71
84
* @mac_address2: second MAC address of the device
85
+ * @pubkey: board ECDSA public key
72
86
*/
73
87
struct mox_rwtm {
74
88
struct mbox_client mbox_client ;
@@ -87,6 +101,10 @@ struct mox_rwtm {
87
101
u64 serial_number ;
88
102
int board_version , ram_size ;
89
103
u8 mac_address1 [ETH_ALEN ], mac_address2 [ETH_ALEN ];
104
+
105
+ #ifdef CONFIG_TURRIS_MOX_RWTM_KEYCTL
106
+ u8 pubkey [MOX_ECC_PUBKEY_LEN ];
107
+ #endif
90
108
};
91
109
92
110
static inline struct device * rwtm_dev (struct mox_rwtm * rwtm )
@@ -260,6 +278,140 @@ static int mox_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait)
260
278
return ret ;
261
279
}
262
280
281
+ #ifdef CONFIG_TURRIS_MOX_RWTM_KEYCTL
282
+
283
+ static void mox_ecc_number_to_bin (void * dst , const u32 * src )
284
+ {
285
+ __be32 tmp [MOX_ECC_NUM_WORDS ];
286
+
287
+ cpu_to_be32_array (tmp , src , MOX_ECC_NUM_WORDS );
288
+
289
+ memcpy (dst , (void * )tmp + 2 , MOX_ECC_NUM_LEN );
290
+ }
291
+
292
+ static void mox_ecc_public_key_to_bin (void * dst , u32 src_first ,
293
+ const u32 * src_rest )
294
+ {
295
+ __be32 tmp [MOX_ECC_NUM_WORDS - 1 ];
296
+ u8 * p = dst ;
297
+
298
+ /* take 3 bytes from the first word */
299
+ * p ++ = src_first >> 16 ;
300
+ * p ++ = src_first >> 8 ;
301
+ * p ++ = src_first ;
302
+
303
+ /* take the rest of the words */
304
+ cpu_to_be32_array (tmp , src_rest , MOX_ECC_NUM_WORDS - 1 );
305
+ memcpy (p , tmp , sizeof (tmp ));
306
+ }
307
+
308
+ static int mox_rwtm_sign (const struct key * key , const void * data , void * signature )
309
+ {
310
+ struct mox_rwtm * rwtm = dev_get_drvdata (turris_signing_key_get_dev (key ));
311
+ struct armada_37xx_rwtm_tx_msg msg = {};
312
+ u32 offset_r , offset_s ;
313
+ int ret ;
314
+
315
+ guard (mutex )(& rwtm -> busy );
316
+
317
+ /*
318
+ * For MBOX_CMD_SIGN command:
319
+ * args[0] - must be 1
320
+ * args[1] - address of message M to sign; message is a 521-bit number
321
+ * args[2] - address where the R part of the signature will be stored
322
+ * args[3] - address where the S part of the signature will be stored
323
+ *
324
+ * M, R and S are 521-bit numbers encoded as seventeen 32-bit words,
325
+ * most significat word first.
326
+ * Since the message in @data is a sha512 digest, the most significat
327
+ * word is always zero.
328
+ */
329
+
330
+ offset_r = MOX_ECC_NUM_WORDS * sizeof (u32 );
331
+ offset_s = 2 * MOX_ECC_NUM_WORDS * sizeof (u32 );
332
+
333
+ memset (rwtm -> buf , 0 , sizeof (u32 ));
334
+ memcpy (rwtm -> buf + sizeof (u32 ), data , SHA512_DIGEST_SIZE );
335
+ be32_to_cpu_array (rwtm -> buf , rwtm -> buf , MOX_ECC_NUM_WORDS );
336
+
337
+ msg .args [0 ] = 1 ;
338
+ msg .args [1 ] = rwtm -> buf_phys ;
339
+ msg .args [2 ] = rwtm -> buf_phys + offset_r ;
340
+ msg .args [3 ] = rwtm -> buf_phys + offset_s ;
341
+
342
+ ret = mox_rwtm_exec (rwtm , MBOX_CMD_SIGN , & msg , true);
343
+ if (ret < 0 )
344
+ return ret ;
345
+
346
+ /* convert R and S parts of the signature */
347
+ mox_ecc_number_to_bin (signature , rwtm -> buf + offset_r );
348
+ mox_ecc_number_to_bin (signature + MOX_ECC_NUM_LEN , rwtm -> buf + offset_s );
349
+
350
+ return 0 ;
351
+ }
352
+
353
+ static const void * mox_rwtm_get_public_key (const struct key * key )
354
+ {
355
+ struct mox_rwtm * rwtm = dev_get_drvdata (turris_signing_key_get_dev (key ));
356
+
357
+ return rwtm -> pubkey ;
358
+ }
359
+
360
+ static const struct turris_signing_key_subtype mox_signing_key_subtype = {
361
+ .key_size = MOX_ECC_NUM_BITS ,
362
+ .data_size = SHA512_DIGEST_SIZE ,
363
+ .sig_size = MOX_ECC_SIG_LEN ,
364
+ .public_key_size = MOX_ECC_PUBKEY_LEN ,
365
+ .hash_algo = "sha512" ,
366
+ .get_public_key = mox_rwtm_get_public_key ,
367
+ .sign = mox_rwtm_sign ,
368
+ };
369
+
370
+ static int mox_register_signing_key (struct mox_rwtm * rwtm )
371
+ {
372
+ struct armada_37xx_rwtm_rx_msg * reply = & rwtm -> reply ;
373
+ struct device * dev = rwtm_dev (rwtm );
374
+ int ret ;
375
+
376
+ ret = mox_rwtm_exec (rwtm , MBOX_CMD_ECDSA_PUB_KEY , NULL , false);
377
+ if (ret == - ENODATA ) {
378
+ dev_warn (dev , "Board has no public key burned!\n" );
379
+ } else if (ret == - EOPNOTSUPP ) {
380
+ dev_notice (dev ,
381
+ "Firmware does not support the ECDSA_PUB_KEY command\n" );
382
+ } else if (ret < 0 ) {
383
+ return ret ;
384
+ } else {
385
+ char sn [17 ] = "unknown" ;
386
+ char desc [46 ];
387
+
388
+ if (rwtm -> has_board_info )
389
+ sprintf (sn , "%016llX" , rwtm -> serial_number );
390
+
391
+ sprintf (desc , "Turris MOX SN %s rWTM ECDSA key" , sn );
392
+
393
+ mox_ecc_public_key_to_bin (rwtm -> pubkey , ret , reply -> status );
394
+
395
+ ret = devm_turris_signing_key_create (dev ,
396
+ & mox_signing_key_subtype ,
397
+ desc );
398
+ if (ret )
399
+ return dev_err_probe (dev , ret ,
400
+ "Cannot create signing key\n" );
401
+ }
402
+
403
+ return 0 ;
404
+ }
405
+
406
+ #else /* CONFIG_TURRIS_MOX_RWTM_KEYCTL */
407
+
408
+ static inline int mox_register_signing_key (struct mox_rwtm * rwtm )
409
+ {
410
+ return 0 ;
411
+ }
412
+
413
+ #endif /* !CONFIG_TURRIS_MOX_RWTM_KEYCTL */
414
+
263
415
static void rwtm_devm_mbox_release (void * mbox )
264
416
{
265
417
mbox_free_channel (mbox );
@@ -309,6 +461,10 @@ static int turris_mox_rwtm_probe(struct platform_device *pdev)
309
461
if (ret < 0 )
310
462
dev_warn (dev , "Cannot read board information: %i\n" , ret );
311
463
464
+ ret = mox_register_signing_key (rwtm );
465
+ if (ret < 0 )
466
+ return ret ;
467
+
312
468
ret = check_get_random_support (rwtm );
313
469
if (ret < 0 ) {
314
470
dev_notice (dev ,
0 commit comments