@@ -13,6 +13,12 @@ Abstract:
13
13
--*/
14
14
15
15
use caliptra_image_gen:: ImageGeneratorCrypto ;
16
+ use caliptra_image_types:: {
17
+ ImageDigest512 , ImageMldsaPrivKey , ImageMldsaSignature , MLDSA87_MSG_BYTE_SIZE ,
18
+ MLDSA87_PRIV_KEY_BYTE_SIZE ,
19
+ } ;
20
+ use fips204:: ml_dsa_87:: { PrivateKey , SIG_LEN } ;
21
+ use fips204:: traits:: { SerDes , Signer } ;
16
22
use zerocopy:: IntoBytes ;
17
23
18
24
use crate :: * ;
@@ -56,7 +62,21 @@ impl<Crypto: ImageGeneratorCrypto> AuthManifestGenerator<Crypto> {
56
62
auth_manifest. preamble . flags = config. flags . bits ( ) ;
57
63
58
64
// Sign the vendor manifest public keys.
59
- auth_manifest. preamble . vendor_pub_keys = config. vendor_man_key_info . pub_keys ;
65
+ auth_manifest. preamble . vendor_pub_keys . ecc_pub_key =
66
+ config. vendor_man_key_info . pub_keys . ecc_pub_key ;
67
+ let pqc_pub_key = match config. pqc_key_type {
68
+ FwVerificationPqcKeyType :: LMS => {
69
+ config. vendor_man_key_info . pub_keys . lms_pub_key . as_bytes ( )
70
+ }
71
+ FwVerificationPqcKeyType :: MLDSA => config
72
+ . vendor_man_key_info
73
+ . pub_keys
74
+ . mldsa_pub_key
75
+ . 0
76
+ . as_bytes ( ) ,
77
+ } ;
78
+ auth_manifest. preamble . vendor_pub_keys . pqc_pub_key . 0 [ ..pqc_pub_key. len ( ) ]
79
+ . copy_from_slice ( pqc_pub_key) ;
60
80
61
81
let range = AuthManifestPreamble :: vendor_signed_data_range ( ) ;
62
82
@@ -70,25 +90,53 @@ impl<Crypto: ImageGeneratorCrypto> AuthManifestGenerator<Crypto> {
70
90
"Failed to get vendor signed data range length"
71
91
) ) ?;
72
92
73
- let digest = self . crypto . sha384_digest ( data) ?;
93
+ let digest_sha384 = self . crypto . sha384_digest ( data) ?;
94
+ let digest_sha512 = if config. pqc_key_type == FwVerificationPqcKeyType :: MLDSA {
95
+ let digest = self . crypto . sha512_digest ( data) ?;
96
+ Some ( digest)
97
+ } else {
98
+ None
99
+ } ;
74
100
75
101
if let Some ( priv_keys) = config. vendor_fw_key_info . priv_keys {
76
102
let sig = self . crypto . ecdsa384_sign (
77
- & digest ,
103
+ & digest_sha384 ,
78
104
& priv_keys. ecc_priv_key ,
79
105
& config. vendor_fw_key_info . pub_keys . ecc_pub_key ,
80
106
) ?;
81
107
auth_manifest. preamble . vendor_pub_keys_signatures . ecc_sig = sig;
82
108
83
- let lms_sig = self . crypto . lms_sign ( & digest, & priv_keys. lms_priv_key ) ?;
84
- auth_manifest. preamble . vendor_pub_keys_signatures . lms_sig = lms_sig;
109
+ if config. pqc_key_type == FwVerificationPqcKeyType :: LMS {
110
+ let lms_sig = self
111
+ . crypto
112
+ . lms_sign ( & digest_sha384, & priv_keys. lms_priv_key ) ?;
113
+ let sig = lms_sig. as_bytes ( ) ;
114
+ auth_manifest. preamble . vendor_pub_keys_signatures . pqc_sig . 0 [ ..sig. len ( ) ]
115
+ . copy_from_slice ( sig) ;
116
+ } else {
117
+ let mldsa_sig =
118
+ self . mldsa_sign ( & digest_sha512. unwrap ( ) , & priv_keys. mldsa_priv_key ) ?;
119
+
120
+ let sig = mldsa_sig. as_bytes ( ) ;
121
+ auth_manifest. preamble . vendor_pub_keys_signatures . pqc_sig . 0 [ ..sig. len ( ) ]
122
+ . copy_from_slice ( sig) ;
123
+ }
85
124
}
86
125
87
126
// Sign the owner manifest public keys.
88
127
if let ( Some ( owner_fw_config) , Some ( owner_man_config) ) =
89
128
( & config. owner_fw_key_info , & config. owner_man_key_info )
90
129
{
91
- auth_manifest. preamble . owner_pub_keys = owner_man_config. pub_keys ;
130
+ auth_manifest. preamble . owner_pub_keys . ecc_pub_key =
131
+ owner_man_config. pub_keys . ecc_pub_key ;
132
+ let pqc_pub_key = match config. pqc_key_type {
133
+ FwVerificationPqcKeyType :: LMS => owner_man_config. pub_keys . lms_pub_key . as_bytes ( ) ,
134
+ FwVerificationPqcKeyType :: MLDSA => {
135
+ owner_man_config. pub_keys . mldsa_pub_key . 0 . as_bytes ( )
136
+ }
137
+ } ;
138
+ auth_manifest. preamble . owner_pub_keys . pqc_pub_key . 0 [ ..pqc_pub_key. len ( ) ]
139
+ . copy_from_slice ( pqc_pub_key) ;
92
140
93
141
let digest = self
94
142
. crypto
@@ -101,10 +149,24 @@ impl<Crypto: ImageGeneratorCrypto> AuthManifestGenerator<Crypto> {
101
149
& owner_fw_config. pub_keys . ecc_pub_key ,
102
150
) ?;
103
151
auth_manifest. preamble . owner_pub_keys_signatures . ecc_sig = sig;
104
- let lms_sig = self
105
- . crypto
106
- . lms_sign ( & digest, & owner_fw_priv_keys. lms_priv_key ) ?;
107
- auth_manifest. preamble . owner_pub_keys_signatures . lms_sig = lms_sig;
152
+
153
+ if config. pqc_key_type == FwVerificationPqcKeyType :: LMS {
154
+ let lms_sig = self
155
+ . crypto
156
+ . lms_sign ( & digest, & owner_fw_priv_keys. lms_priv_key ) ?;
157
+ let sig = lms_sig. as_bytes ( ) ;
158
+ auth_manifest. preamble . owner_pub_keys_signatures . pqc_sig . 0 [ ..sig. len ( ) ]
159
+ . copy_from_slice ( sig) ;
160
+ } else {
161
+ let digest = self
162
+ . crypto
163
+ . sha512_digest ( auth_manifest. preamble . owner_pub_keys . as_bytes ( ) ) ?;
164
+
165
+ let mldsa_sig = self . mldsa_sign ( & digest, & owner_fw_priv_keys. mldsa_priv_key ) ?;
166
+ let sig = mldsa_sig. as_bytes ( ) ;
167
+ auth_manifest. preamble . owner_pub_keys_signatures . pqc_sig . 0 [ ..sig. len ( ) ]
168
+ . copy_from_slice ( sig) ;
169
+ }
108
170
}
109
171
}
110
172
@@ -129,13 +191,32 @@ impl<Crypto: ImageGeneratorCrypto> AuthManifestGenerator<Crypto> {
129
191
. vendor_image_metdata_signatures
130
192
. ecc_sig = sig;
131
193
132
- let lms_sig = self
133
- . crypto
134
- . lms_sign ( & digest, & vendor_man_priv_keys. lms_priv_key ) ?;
135
- auth_manifest
136
- . preamble
137
- . vendor_image_metdata_signatures
138
- . lms_sig = lms_sig;
194
+ if config. pqc_key_type == FwVerificationPqcKeyType :: LMS {
195
+ let lms_sig = self
196
+ . crypto
197
+ . lms_sign ( & digest, & vendor_man_priv_keys. lms_priv_key ) ?;
198
+ let sig = lms_sig. as_bytes ( ) ;
199
+ auth_manifest
200
+ . preamble
201
+ . vendor_image_metdata_signatures
202
+ . pqc_sig
203
+ . 0 [ ..sig. len ( ) ]
204
+ . copy_from_slice ( sig) ;
205
+ } else {
206
+ let digest = self
207
+ . crypto
208
+ . sha512_digest ( auth_manifest. image_metadata_col . as_bytes ( ) ) ?;
209
+
210
+ let mldsa_sig =
211
+ self . mldsa_sign ( & digest, & vendor_man_priv_keys. mldsa_priv_key ) ?;
212
+ let sig = mldsa_sig. as_bytes ( ) ;
213
+ auth_manifest
214
+ . preamble
215
+ . vendor_image_metdata_signatures
216
+ . pqc_sig
217
+ . 0 [ ..sig. len ( ) ]
218
+ . copy_from_slice ( sig) ;
219
+ }
139
220
}
140
221
}
141
222
@@ -152,16 +233,75 @@ impl<Crypto: ImageGeneratorCrypto> AuthManifestGenerator<Crypto> {
152
233
. owner_image_metdata_signatures
153
234
. ecc_sig = sig;
154
235
155
- let lms_sig = self
156
- . crypto
157
- . lms_sign ( & digest, & owner_man_priv_keys. lms_priv_key ) ?;
158
- auth_manifest
159
- . preamble
160
- . owner_image_metdata_signatures
161
- . lms_sig = lms_sig;
236
+ if config. pqc_key_type == FwVerificationPqcKeyType :: LMS {
237
+ let lms_sig = self
238
+ . crypto
239
+ . lms_sign ( & digest, & owner_man_priv_keys. lms_priv_key ) ?;
240
+
241
+ let sig = lms_sig. as_bytes ( ) ;
242
+ auth_manifest
243
+ . preamble
244
+ . owner_image_metdata_signatures
245
+ . pqc_sig
246
+ . 0 [ ..sig. len ( ) ]
247
+ . copy_from_slice ( sig) ;
248
+ } else {
249
+ let digest = self
250
+ . crypto
251
+ . sha512_digest ( auth_manifest. image_metadata_col . as_bytes ( ) ) ?;
252
+
253
+ let mldsa_sig =
254
+ self . mldsa_sign ( & digest, & owner_man_priv_keys. mldsa_priv_key ) ?;
255
+ let sig = mldsa_sig. as_bytes ( ) ;
256
+ auth_manifest
257
+ . preamble
258
+ . owner_image_metdata_signatures
259
+ . pqc_sig
260
+ . 0 [ ..sig. len ( ) ]
261
+ . copy_from_slice ( sig) ;
262
+ }
162
263
}
163
264
}
164
265
165
266
Ok ( auth_manifest)
166
267
}
268
+
269
+ // [TODO][CAP2] Make this a common function in the crypto library.
270
+ fn mldsa_sign (
271
+ & self ,
272
+ digest : & ImageDigest512 ,
273
+ priv_key : & ImageMldsaPrivKey ,
274
+ ) -> anyhow:: Result < ImageMldsaSignature > {
275
+ // Private key is received in hw format which is also the library format.
276
+ // Unlike ECC, no reversal of the DWORD endianess needed.
277
+ let priv_key_bytes: [ u8 ; MLDSA87_PRIV_KEY_BYTE_SIZE ] = priv_key
278
+ . 0
279
+ . as_bytes ( )
280
+ . try_into ( )
281
+ . map_err ( |_| anyhow:: anyhow!( "Invalid private key size" ) ) ?;
282
+ let priv_key = { PrivateKey :: try_from_bytes ( priv_key_bytes) . unwrap ( ) } ;
283
+
284
+ // Digest is received in hw format. Since the library and hardware format are the same, no endianess conversion needed.
285
+ let digest: [ u8 ; MLDSA87_MSG_BYTE_SIZE ] = digest
286
+ . as_bytes ( )
287
+ . try_into ( )
288
+ . map_err ( |_| anyhow:: anyhow!( "Invalid digest size" ) ) ?;
289
+
290
+ let signature = priv_key
291
+ . try_sign_with_seed ( & [ 0u8 ; 32 ] , & digest, & [ ] )
292
+ . unwrap ( ) ;
293
+ let signature_extended = {
294
+ let mut sig = [ 0u8 ; SIG_LEN + 1 ] ;
295
+ sig[ ..SIG_LEN ] . copy_from_slice ( & signature) ;
296
+ sig
297
+ } ;
298
+
299
+ // Return the signature in hw format (which is also the library format)
300
+ // Unlike ECC, no reversal of the DWORD endianess needed.
301
+ let mut sig: ImageMldsaSignature = ImageMldsaSignature :: default ( ) ;
302
+ for ( i, chunk) in signature_extended. chunks ( 4 ) . enumerate ( ) {
303
+ sig. 0 [ i] = u32:: from_le_bytes ( chunk. try_into ( ) . unwrap ( ) ) ;
304
+ }
305
+ Ok ( sig)
306
+ }
167
307
}
0 commit comments