3
3
// Modifications copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4
4
// SPDX-License-Identifier: Apache-2.0 OR ISC
5
5
6
- use core:: fmt;
7
- use core:: fmt:: { Debug , Formatter } ;
6
+ use crate :: ec:: signature:: AlgorithmID ;
8
7
use core:: mem:: MaybeUninit ;
9
- use core:: ops:: Deref ;
10
8
use core:: ptr:: null;
11
9
use core:: ptr:: null_mut;
12
10
// TODO: Uncomment when MSRV >= 1.64
13
11
// use core::ffi::c_int;
14
12
use std:: os:: raw:: c_int;
15
13
16
- #[ cfg( feature = "ring-sig-verify" ) ]
17
- use untrusted:: Input ;
18
-
19
14
#[ cfg( feature = "fips" ) ]
20
15
use aws_lc:: EC_KEY_check_fips ;
21
16
#[ cfg( not( feature = "fips" ) ) ]
22
17
use aws_lc:: EC_KEY_check_key ;
23
18
use aws_lc:: {
24
19
d2i_PrivateKey, point_conversion_form_t, BN_bn2bin_padded , BN_num_bytes , CBS_init ,
25
- ECDSA_SIG_from_bytes , ECDSA_SIG_get0_r , ECDSA_SIG_get0_s , ECDSA_SIG_new , ECDSA_SIG_set0 ,
26
- ECDSA_SIG_to_bytes , EC_GROUP_get_curve_name , EC_GROUP_new_by_curve_name , EC_KEY_get0_group ,
27
- EC_KEY_get0_private_key , EC_KEY_get0_public_key , EC_KEY_new , EC_KEY_set_group ,
28
- EC_KEY_set_private_key , EC_KEY_set_public_key , EC_POINT_mul , EC_POINT_new , EC_POINT_oct2point ,
29
- EC_POINT_point2oct , EVP_DigestVerify , EVP_DigestVerifyInit , EVP_PKEY_CTX_new_id ,
20
+ ECDSA_SIG_from_bytes , ECDSA_SIG_get0_r , ECDSA_SIG_get0_s , EC_GROUP_get_curve_name ,
21
+ EC_GROUP_new_by_curve_name , EC_KEY_get0_group , EC_KEY_get0_private_key , EC_KEY_get0_public_key ,
22
+ EC_KEY_new , EC_KEY_set_group , EC_KEY_set_private_key , EC_KEY_set_public_key , EC_POINT_mul ,
23
+ EC_POINT_new , EC_POINT_oct2point , EC_POINT_point2oct , EVP_PKEY_CTX_new_id ,
30
24
EVP_PKEY_CTX_set_ec_paramgen_curve_nid , EVP_PKEY_assign_EC_KEY , EVP_PKEY_get0_EC_KEY ,
31
- EVP_PKEY_keygen , EVP_PKEY_keygen_init , EVP_PKEY_new , EVP_parse_public_key ,
32
- NID_X9_62_prime256v1 , NID_secp256k1 , NID_secp384r1 , NID_secp521r1 , BIGNUM , CBS , ECDSA_SIG ,
25
+ EVP_PKEY_keygen , EVP_PKEY_keygen_init , EVP_PKEY_new , EVP_parse_public_key , BIGNUM , CBS ,
33
26
EC_GROUP , EC_KEY , EC_POINT , EVP_PKEY , EVP_PKEY_EC ,
34
27
} ;
35
28
36
- use crate :: digest:: digest_ctx:: DigestContext ;
37
- use crate :: encoding:: {
38
- AsBigEndian , AsDer , EcPublicKeyCompressedBin , EcPublicKeyUncompressedBin , PublicKeyX509Der ,
39
- } ;
40
29
use crate :: error:: { KeyRejected , Unspecified } ;
41
30
use crate :: fips:: indicator_check;
42
31
use crate :: ptr:: { ConstPointer , DetachableLcPtr , LcPtr } ;
43
- use crate :: signature:: { Signature , VerificationAlgorithm } ;
44
- use crate :: { digest, hex, sealed} ;
32
+ use crate :: signature:: Signature ;
45
33
46
34
pub ( crate ) mod key_pair;
35
+ pub ( crate ) mod signature;
47
36
48
37
const ELEM_MAX_BITS : usize = 521 ;
49
38
pub ( crate ) const ELEM_MAX_BYTES : usize = ( ELEM_MAX_BITS + 7 ) / 8 ;
@@ -64,256 +53,6 @@ pub(crate) const PUBLIC_KEY_MAX_LEN: usize = 1 + (2 * ELEM_MAX_BYTES);
64
53
/// `42` is the length of the P-521 template.
65
54
pub const PKCS8_DOCUMENT_MAX_LEN : usize = 42 + SCALAR_MAX_BYTES + PUBLIC_KEY_MAX_LEN ;
66
55
67
- /// An ECDSA verification algorithm.
68
- #[ derive( Debug , Eq , PartialEq ) ]
69
- pub struct EcdsaVerificationAlgorithm {
70
- pub ( super ) id : & ' static AlgorithmID ,
71
- pub ( super ) digest : & ' static digest:: Algorithm ,
72
- pub ( super ) sig_format : EcdsaSignatureFormat ,
73
- }
74
-
75
- /// An ECDSA signing algorithm.
76
- #[ derive( Debug , Eq , PartialEq ) ]
77
- pub struct EcdsaSigningAlgorithm ( pub ( crate ) & ' static EcdsaVerificationAlgorithm ) ;
78
-
79
- impl Deref for EcdsaSigningAlgorithm {
80
- type Target = EcdsaVerificationAlgorithm ;
81
- #[ inline]
82
- fn deref ( & self ) -> & Self :: Target {
83
- self . 0
84
- }
85
- }
86
-
87
- impl sealed:: Sealed for EcdsaVerificationAlgorithm { }
88
- impl sealed:: Sealed for EcdsaSigningAlgorithm { }
89
-
90
- #[ derive( Debug , Eq , PartialEq ) ]
91
- pub ( crate ) enum EcdsaSignatureFormat {
92
- ASN1 ,
93
- Fixed ,
94
- }
95
-
96
- #[ derive( Debug , Eq , PartialEq ) ]
97
- #[ allow( non_camel_case_types) ]
98
- pub ( crate ) enum AlgorithmID {
99
- ECDSA_P256 ,
100
- ECDSA_P384 ,
101
- ECDSA_P521 ,
102
- ECDSA_P256K1 ,
103
- }
104
-
105
- impl AlgorithmID {
106
- #[ inline]
107
- pub ( crate ) fn nid ( & ' static self ) -> i32 {
108
- match self {
109
- AlgorithmID :: ECDSA_P256 => NID_X9_62_prime256v1 ,
110
- AlgorithmID :: ECDSA_P384 => NID_secp384r1 ,
111
- AlgorithmID :: ECDSA_P521 => NID_secp521r1 ,
112
- AlgorithmID :: ECDSA_P256K1 => NID_secp256k1 ,
113
- }
114
- }
115
- pub ( crate ) fn private_key_size ( & self ) -> usize {
116
- match self {
117
- AlgorithmID :: ECDSA_P256 | AlgorithmID :: ECDSA_P256K1 => 32 ,
118
- AlgorithmID :: ECDSA_P384 => 48 ,
119
- AlgorithmID :: ECDSA_P521 => 66 ,
120
- }
121
- }
122
- // Compressed public key length in bytes
123
- #[ inline]
124
- const fn compressed_pub_key_len ( & self ) -> usize {
125
- match self {
126
- AlgorithmID :: ECDSA_P256 | AlgorithmID :: ECDSA_P256K1 => {
127
- compressed_public_key_size_bytes ( 256 )
128
- }
129
- AlgorithmID :: ECDSA_P384 => compressed_public_key_size_bytes ( 384 ) ,
130
- AlgorithmID :: ECDSA_P521 => compressed_public_key_size_bytes ( 521 ) ,
131
- }
132
- }
133
- }
134
-
135
- /// Elliptic curve public key.
136
- #[ derive( Clone ) ]
137
- pub struct PublicKey {
138
- algorithm : & ' static EcdsaSigningAlgorithm ,
139
- evp_pkey : LcPtr < EVP_PKEY > ,
140
- octets : Box < [ u8 ] > ,
141
- }
142
-
143
- impl AsDer < PublicKeyX509Der < ' static > > for PublicKey {
144
- /// Provides the public key as a DER-encoded (X.509) `SubjectPublicKeyInfo` structure.
145
- /// # Errors
146
- /// Returns an error if the public key fails to marshal to X.509.
147
- fn as_der ( & self ) -> Result < PublicKeyX509Der < ' static > , Unspecified > {
148
- let ec_group = LcPtr :: new ( unsafe { EC_GROUP_new_by_curve_name ( self . algorithm . id . nid ( ) ) } ) ?;
149
- let ec_point = ec_point_from_bytes ( & ec_group, self . as_ref ( ) ) ?;
150
- let mut ec_key = LcPtr :: new ( unsafe { EC_KEY_new ( ) } ) ?;
151
- if 1 != unsafe { EC_KEY_set_group ( * ec_key. as_mut ( ) , * ec_group. as_const ( ) ) } {
152
- return Err ( Unspecified ) ;
153
- }
154
- if 1 != unsafe { EC_KEY_set_public_key ( * ec_key. as_mut ( ) , * ec_point. as_const ( ) ) } {
155
- return Err ( Unspecified ) ;
156
- }
157
- let mut buffer = null_mut :: < u8 > ( ) ;
158
- let len = unsafe { aws_lc:: i2d_EC_PUBKEY ( * ec_key. as_const ( ) , & mut buffer) } ;
159
- if len < 0 || buffer. is_null ( ) {
160
- return Err ( Unspecified ) ;
161
- }
162
- let buffer = LcPtr :: new ( buffer) ?;
163
- let der =
164
- unsafe { core:: slice:: from_raw_parts ( * buffer. as_const ( ) , len. try_into ( ) ?) } . to_owned ( ) ;
165
-
166
- Ok ( PublicKeyX509Der :: new ( der) )
167
- }
168
- }
169
-
170
- impl AsBigEndian < EcPublicKeyCompressedBin < ' static > > for PublicKey {
171
- /// Provides the public key elliptic curve point to a compressed point bytes format.
172
- /// # Errors
173
- /// Returns an error if the public key fails to marshal.
174
- fn as_be_bytes ( & self ) -> Result < EcPublicKeyCompressedBin < ' static > , crate :: error:: Unspecified > {
175
- let ec_key = ConstPointer :: new ( unsafe { EVP_PKEY_get0_EC_KEY ( * self . evp_pkey . as_const ( ) ) } ) ?;
176
-
177
- let mut buffer = vec ! [ 0u8 ; self . algorithm. 0 . id. compressed_pub_key_len( ) ] ;
178
-
179
- let out_len = marshal_ec_public_key_to_buffer ( & mut buffer, & ec_key, true ) ?;
180
-
181
- debug_assert_eq ! ( buffer. len( ) , out_len) ;
182
-
183
- buffer. truncate ( out_len) ;
184
-
185
- Ok ( EcPublicKeyCompressedBin :: new ( buffer) )
186
- }
187
- }
188
-
189
- impl AsBigEndian < EcPublicKeyUncompressedBin < ' static > > for PublicKey {
190
- /// Provides the public key elliptic curve point to an uncompressed point bytes format.
191
- /// # Errors
192
- /// Returns an error if the public key fails to marshal.
193
- fn as_be_bytes (
194
- & self ,
195
- ) -> Result < EcPublicKeyUncompressedBin < ' static > , crate :: error:: Unspecified > {
196
- let mut uncompressed_bytes = vec ! [ 0u8 ; self . octets. len( ) ] ;
197
- uncompressed_bytes. copy_from_slice ( & self . octets ) ;
198
- Ok ( EcPublicKeyUncompressedBin :: new ( uncompressed_bytes) )
199
- }
200
- }
201
-
202
- impl Debug for PublicKey {
203
- fn fmt ( & self , f : & mut Formatter < ' _ > ) -> Result < ( ) , fmt:: Error > {
204
- f. write_str ( & format ! (
205
- "EcdsaPublicKey(\" {}\" )" ,
206
- hex:: encode( self . octets. as_ref( ) )
207
- ) )
208
- }
209
- }
210
-
211
- impl AsRef < [ u8 ] > for PublicKey {
212
- #[ inline]
213
- /// Serializes the public key in an uncompressed form (X9.62) using the
214
- /// Octet-String-to-Elliptic-Curve-Point algorithm in
215
- /// [SEC 1: Elliptic Curve Cryptography, Version 2.0].
216
- fn as_ref ( & self ) -> & [ u8 ] {
217
- self . octets . as_ref ( )
218
- }
219
- }
220
-
221
- unsafe impl Send for PublicKey { }
222
- unsafe impl Sync for PublicKey { }
223
-
224
- impl VerificationAlgorithm for EcdsaVerificationAlgorithm {
225
- #[ inline]
226
- #[ cfg( feature = "ring-sig-verify" ) ]
227
- fn verify (
228
- & self ,
229
- public_key : Input < ' _ > ,
230
- msg : Input < ' _ > ,
231
- signature : Input < ' _ > ,
232
- ) -> Result < ( ) , Unspecified > {
233
- self . verify_sig (
234
- public_key. as_slice_less_safe ( ) ,
235
- msg. as_slice_less_safe ( ) ,
236
- signature. as_slice_less_safe ( ) ,
237
- )
238
- }
239
-
240
- fn verify_sig (
241
- & self ,
242
- public_key : & [ u8 ] ,
243
- msg : & [ u8 ] ,
244
- signature : & [ u8 ] ,
245
- ) -> Result < ( ) , Unspecified > {
246
- match self . sig_format {
247
- EcdsaSignatureFormat :: ASN1 => {
248
- verify_asn1_signature ( self . id , self . digest , public_key, msg, signature)
249
- }
250
- EcdsaSignatureFormat :: Fixed => {
251
- verify_fixed_signature ( self . id , self . digest , public_key, msg, signature)
252
- }
253
- }
254
- }
255
- }
256
-
257
- fn verify_fixed_signature (
258
- alg : & ' static AlgorithmID ,
259
- digest : & ' static digest:: Algorithm ,
260
- public_key : & [ u8 ] ,
261
- msg : & [ u8 ] ,
262
- signature : & [ u8 ] ,
263
- ) -> Result < ( ) , Unspecified > {
264
- let mut out_bytes = null_mut :: < u8 > ( ) ;
265
- let mut out_bytes_len = MaybeUninit :: < usize > :: uninit ( ) ;
266
- let sig = unsafe { ecdsa_sig_from_fixed ( alg, signature) ? } ;
267
- if 1 != unsafe {
268
- ECDSA_SIG_to_bytes ( & mut out_bytes, out_bytes_len. as_mut_ptr ( ) , * sig. as_const ( ) )
269
- } {
270
- return Err ( Unspecified ) ;
271
- }
272
- let out_bytes = LcPtr :: new ( out_bytes) ?;
273
- let signature = unsafe { out_bytes. as_slice ( out_bytes_len. assume_init ( ) ) } ;
274
- verify_asn1_signature ( alg, digest, public_key, msg, signature)
275
- }
276
-
277
- fn verify_asn1_signature (
278
- alg : & ' static AlgorithmID ,
279
- digest : & ' static digest:: Algorithm ,
280
- public_key : & [ u8 ] ,
281
- msg : & [ u8 ] ,
282
- signature : & [ u8 ] ,
283
- ) -> Result < ( ) , Unspecified > {
284
- let mut pkey = try_parse_public_key_bytes ( public_key, alg. nid ( ) ) ?;
285
-
286
- let mut md_ctx = DigestContext :: new_uninit ( ) ;
287
-
288
- let digest = digest:: match_digest_type ( & digest. id ) ;
289
-
290
- if 1 != unsafe {
291
- EVP_DigestVerifyInit (
292
- md_ctx. as_mut_ptr ( ) ,
293
- null_mut ( ) ,
294
- * digest,
295
- null_mut ( ) ,
296
- * pkey. as_mut ( ) ,
297
- )
298
- } {
299
- return Err ( Unspecified ) ;
300
- }
301
-
302
- if 1 != indicator_check ! ( unsafe {
303
- EVP_DigestVerify (
304
- md_ctx. as_mut_ptr( ) ,
305
- signature. as_ptr( ) ,
306
- signature. len( ) ,
307
- msg. as_ptr( ) ,
308
- msg. len( ) ,
309
- )
310
- } ) {
311
- return Err ( Unspecified ) ;
312
- }
313
-
314
- Ok ( ( ) )
315
- }
316
-
317
56
fn verify_ec_key_nid (
318
57
ec_key : & ConstPointer < EC_KEY > ,
319
58
expected_curve_nid : i32 ,
@@ -432,20 +171,6 @@ pub(crate) fn marshal_ec_public_key_to_buffer(
432
171
Ok ( out_len)
433
172
}
434
173
435
- pub ( crate ) fn public_key_from_evp_pkey (
436
- evp_pkey : & LcPtr < EVP_PKEY > ,
437
- algorithm : & ' static EcdsaSigningAlgorithm ,
438
- ) -> Result < PublicKey , Unspecified > {
439
- let mut pub_key_bytes = [ 0u8 ; PUBLIC_KEY_MAX_LEN ] ;
440
- let key_len = marshal_public_key_to_buffer ( & mut pub_key_bytes, evp_pkey, false ) ?;
441
-
442
- Ok ( PublicKey {
443
- evp_pkey : evp_pkey. clone ( ) ,
444
- algorithm,
445
- octets : pub_key_bytes[ 0 ..key_len] . into ( ) ,
446
- } )
447
- }
448
-
449
174
pub ( crate ) fn try_parse_public_key_bytes (
450
175
key_bytes : & [ u8 ] ,
451
176
expected_curve_nid : i32 ,
@@ -687,29 +412,6 @@ fn ecdsa_asn1_to_fixed(alg_id: &'static AlgorithmID, sig: &[u8]) -> Result<Signa
687
412
} ) )
688
413
}
689
414
690
- #[ inline]
691
- unsafe fn ecdsa_sig_from_fixed (
692
- alg_id : & ' static AlgorithmID ,
693
- signature : & [ u8 ] ,
694
- ) -> Result < LcPtr < ECDSA_SIG > , ( ) > {
695
- let num_size_bytes = alg_id. private_key_size ( ) ;
696
- if signature. len ( ) != 2 * num_size_bytes {
697
- return Err ( ( ) ) ;
698
- }
699
- let mut r_bn = DetachableLcPtr :: < BIGNUM > :: try_from ( & signature[ ..num_size_bytes] ) ?;
700
- let mut s_bn = DetachableLcPtr :: < BIGNUM > :: try_from ( & signature[ num_size_bytes..] ) ?;
701
-
702
- let mut ecdsa_sig = LcPtr :: new ( ECDSA_SIG_new ( ) ) ?;
703
-
704
- if 1 != ECDSA_SIG_set0 ( * ecdsa_sig. as_mut ( ) , * r_bn. as_mut ( ) , * s_bn. as_mut ( ) ) {
705
- return Err ( ( ) ) ;
706
- }
707
- r_bn. detach ( ) ;
708
- s_bn. detach ( ) ;
709
-
710
- Ok ( ecdsa_sig)
711
- }
712
-
713
415
#[ inline]
714
416
pub ( crate ) const fn compressed_public_key_size_bytes ( curve_field_bits : usize ) -> usize {
715
417
1 + ( curve_field_bits + 7 ) / 8
0 commit comments