/rust/registry/src/index.crates.io-6f17d22bba15001f/aws-lc-rs-1.13.0/src/ec/encoding.rs
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. |
2 | | // SPDX-License-Identifier: Apache-2.0 OR ISC |
3 | | |
4 | | use crate::aws_lc::{EVP_PKEY, EVP_PKEY_EC}; |
5 | | use crate::ec::encoding::sec1::parse_sec1_public_point; |
6 | | use crate::ec::validate_ec_evp_key; |
7 | | |
8 | | use crate::error::KeyRejected; |
9 | | use crate::ptr::LcPtr; |
10 | | |
11 | | // [SEC 1](https://secg.org/sec1-v2.pdf) |
12 | | // |
13 | | // SEC 1: Elliptic Curve Cryptography, Version 2.0 |
14 | | pub(crate) mod sec1 { |
15 | | use crate::aws_lc::{ |
16 | | point_conversion_form_t, BN_bn2cbb_padded, EC_GROUP_get_curve_name, EC_KEY_get0_group, |
17 | | EC_KEY_get0_private_key, EC_KEY_get0_public_key, EC_KEY_new, EC_KEY_set_group, |
18 | | EC_KEY_set_private_key, EC_KEY_set_public_key, EC_POINT_mul, EC_POINT_new, |
19 | | EC_POINT_oct2point, EC_POINT_point2cbb, EVP_PKEY_assign_EC_KEY, EVP_PKEY_get0_EC_KEY, |
20 | | EVP_PKEY_new, NID_X9_62_prime256v1, NID_secp256k1, NID_secp384r1, NID_secp521r1, BIGNUM, |
21 | | EC_GROUP, EC_POINT, EVP_PKEY, |
22 | | }; |
23 | | use crate::cbb::LcCBB; |
24 | | use crate::ec::{ |
25 | | compressed_public_key_size_bytes, ec_group_from_nid, uncompressed_public_key_size_bytes, |
26 | | validate_ec_evp_key, KeyRejected, |
27 | | }; |
28 | | use crate::error::Unspecified; |
29 | | use crate::ptr::{ConstPointer, DetachableLcPtr, LcPtr}; |
30 | | use std::ptr::{null, null_mut}; |
31 | | |
32 | 0 | pub(crate) fn parse_sec1_public_point( |
33 | 0 | key_bytes: &[u8], |
34 | 0 | expected_curve_nid: i32, |
35 | 0 | ) -> Result<LcPtr<EVP_PKEY>, KeyRejected> { |
36 | 0 | let ec_group = ec_group_from_nid(expected_curve_nid)?; |
37 | 0 | let mut ec_point = LcPtr::new(unsafe { EC_POINT_new(*ec_group) })?; |
38 | | |
39 | 0 | if 1 != unsafe { |
40 | 0 | EC_POINT_oct2point( |
41 | 0 | *ec_group, |
42 | 0 | *ec_point.as_mut(), |
43 | 0 | key_bytes.as_ptr(), |
44 | 0 | key_bytes.len(), |
45 | 0 | null_mut(), |
46 | 0 | ) |
47 | 0 | } { |
48 | 0 | return Err(KeyRejected::invalid_encoding()); |
49 | 0 | } |
50 | 0 | from_ec_public_point(&ec_group, &ec_point) |
51 | 0 | } |
52 | | |
53 | | #[inline] |
54 | 0 | fn from_ec_public_point( |
55 | 0 | ec_group: &ConstPointer<EC_GROUP>, |
56 | 0 | public_ec_point: &LcPtr<EC_POINT>, |
57 | 0 | ) -> Result<LcPtr<EVP_PKEY>, KeyRejected> { |
58 | 0 | let nid = unsafe { EC_GROUP_get_curve_name(**ec_group) }; |
59 | 0 | let ec_key = DetachableLcPtr::new(unsafe { EC_KEY_new() })?; |
60 | 0 | if 1 != unsafe { EC_KEY_set_group(*ec_key, **ec_group) } { |
61 | 0 | return Err(KeyRejected::unexpected_error()); |
62 | 0 | } |
63 | 0 | if 1 != unsafe { EC_KEY_set_public_key(*ec_key, *public_ec_point.as_const()) } { |
64 | 0 | return Err(KeyRejected::inconsistent_components()); |
65 | 0 | } |
66 | | |
67 | 0 | let mut pkey = LcPtr::new(unsafe { EVP_PKEY_new() })?; |
68 | | |
69 | 0 | if 1 != unsafe { EVP_PKEY_assign_EC_KEY(*pkey.as_mut(), *ec_key) } { |
70 | 0 | return Err(KeyRejected::unexpected_error()); |
71 | 0 | } |
72 | 0 |
|
73 | 0 | ec_key.detach(); |
74 | 0 |
|
75 | 0 | validate_ec_evp_key(&pkey.as_const(), nid)?; |
76 | | |
77 | 0 | Ok(pkey) |
78 | 0 | } |
79 | | |
80 | 0 | pub(crate) fn parse_sec1_private_bn( |
81 | 0 | priv_key: &[u8], |
82 | 0 | nid: i32, |
83 | 0 | ) -> Result<LcPtr<EVP_PKEY>, KeyRejected> { |
84 | 0 | let ec_group = ec_group_from_nid(nid)?; |
85 | 0 | let priv_key = LcPtr::<BIGNUM>::try_from(priv_key)?; |
86 | | |
87 | 0 | let pkey = from_ec_private_bn(&ec_group, &priv_key.as_const())?; |
88 | | |
89 | 0 | Ok(pkey) |
90 | 0 | } |
91 | | |
92 | 0 | fn from_ec_private_bn( |
93 | 0 | ec_group: &ConstPointer<EC_GROUP>, |
94 | 0 | private_big_num: &ConstPointer<BIGNUM>, |
95 | 0 | ) -> Result<LcPtr<EVP_PKEY>, KeyRejected> { |
96 | 0 | let ec_key = DetachableLcPtr::new(unsafe { EC_KEY_new() })?; |
97 | 0 | if 1 != unsafe { EC_KEY_set_group(*ec_key, **ec_group) } { |
98 | 0 | return Err(KeyRejected::unexpected_error()); |
99 | 0 | } |
100 | 0 | if 1 != unsafe { EC_KEY_set_private_key(*ec_key, **private_big_num) } { |
101 | 0 | return Err(KeyRejected::invalid_encoding()); |
102 | 0 | } |
103 | 0 | let mut pub_key = LcPtr::new(unsafe { EC_POINT_new(**ec_group) })?; |
104 | 0 | if 1 != unsafe { |
105 | 0 | EC_POINT_mul( |
106 | 0 | **ec_group, |
107 | 0 | *pub_key.as_mut(), |
108 | 0 | **private_big_num, |
109 | 0 | null(), |
110 | 0 | null(), |
111 | 0 | null_mut(), |
112 | 0 | ) |
113 | 0 | } { |
114 | 0 | return Err(KeyRejected::unexpected_error()); |
115 | 0 | } |
116 | 0 | if 1 != unsafe { EC_KEY_set_public_key(*ec_key, *pub_key.as_const()) } { |
117 | 0 | return Err(KeyRejected::unexpected_error()); |
118 | 0 | } |
119 | 0 | let expected_curve_nid = unsafe { EC_GROUP_get_curve_name(**ec_group) }; |
120 | | |
121 | 0 | let mut pkey = LcPtr::new(unsafe { EVP_PKEY_new() })?; |
122 | | |
123 | 0 | if 1 != unsafe { EVP_PKEY_assign_EC_KEY(*pkey.as_mut(), *ec_key) } { |
124 | 0 | return Err(KeyRejected::unexpected_error()); |
125 | 0 | } |
126 | 0 | ec_key.detach(); |
127 | 0 |
|
128 | 0 | // Validate the EC_KEY before returning it. |
129 | 0 | validate_ec_evp_key(&pkey.as_const(), expected_curve_nid)?; |
130 | | |
131 | 0 | Ok(pkey) |
132 | 0 | } |
133 | 0 | pub(crate) fn marshal_sec1_public_point( |
134 | 0 | evp_pkey: &LcPtr<EVP_PKEY>, |
135 | 0 | compressed: bool, |
136 | 0 | ) -> Result<Vec<u8>, Unspecified> { |
137 | 0 | let pub_key_size = if compressed { |
138 | 0 | compressed_public_key_size_bytes(evp_pkey.key_size_bits()) |
139 | | } else { |
140 | 0 | uncompressed_public_key_size_bytes(evp_pkey.key_size_bits()) |
141 | | }; |
142 | 0 | let mut cbb = LcCBB::new(pub_key_size); |
143 | 0 | marshal_sec1_public_point_into_cbb(&mut cbb, evp_pkey, compressed)?; |
144 | 0 | cbb.into_vec() |
145 | 0 | } |
146 | | |
147 | 0 | pub(crate) fn marshal_sec1_public_point_into_buffer( |
148 | 0 | buffer: &mut [u8], |
149 | 0 | evp_pkey: &LcPtr<EVP_PKEY>, |
150 | 0 | compressed: bool, |
151 | 0 | ) -> Result<usize, Unspecified> { |
152 | 0 | let mut cbb = LcCBB::new_from_slice(buffer); |
153 | 0 | marshal_sec1_public_point_into_cbb(&mut cbb, evp_pkey, compressed)?; |
154 | 0 | cbb.finish() |
155 | 0 | } |
156 | | |
157 | 0 | fn marshal_sec1_public_point_into_cbb( |
158 | 0 | cbb: &mut LcCBB, |
159 | 0 | evp_pkey: &LcPtr<EVP_PKEY>, |
160 | 0 | compressed: bool, |
161 | 0 | ) -> Result<(), Unspecified> { |
162 | 0 | let ec_key = ConstPointer::new(unsafe { EVP_PKEY_get0_EC_KEY(*evp_pkey.as_const()) })?; |
163 | 0 | let ec_group = ConstPointer::new(unsafe { EC_KEY_get0_group(*ec_key) })?; |
164 | 0 | let ec_point = ConstPointer::new(unsafe { EC_KEY_get0_public_key(*ec_key) })?; |
165 | | |
166 | 0 | let point_conversion_form = if compressed { |
167 | 0 | point_conversion_form_t::POINT_CONVERSION_COMPRESSED |
168 | | } else { |
169 | 0 | point_conversion_form_t::POINT_CONVERSION_UNCOMPRESSED |
170 | | }; |
171 | | |
172 | 0 | if 1 != unsafe { |
173 | 0 | EC_POINT_point2cbb( |
174 | 0 | cbb.as_mut_ptr(), |
175 | 0 | *ec_group, |
176 | 0 | *ec_point, |
177 | 0 | point_conversion_form, |
178 | 0 | null_mut(), |
179 | 0 | ) |
180 | 0 | } { |
181 | 0 | return Err(Unspecified); |
182 | 0 | } |
183 | 0 | Ok(()) |
184 | 0 | } |
185 | | |
186 | 0 | pub(crate) fn marshal_sec1_private_key( |
187 | 0 | evp_pkey: &LcPtr<EVP_PKEY>, |
188 | 0 | ) -> Result<Vec<u8>, Unspecified> { |
189 | 0 | let ec_key = ConstPointer::new(unsafe { EVP_PKEY_get0_EC_KEY(*evp_pkey.as_const()) })?; |
190 | 0 | let ec_group = ConstPointer::new(unsafe { EC_KEY_get0_group(*ec_key) })?; |
191 | 0 | let nid = unsafe { EC_GROUP_get_curve_name(*ec_group) }; |
192 | | #[allow(non_upper_case_globals)] |
193 | 0 | let key_size: usize = match nid { |
194 | 0 | NID_X9_62_prime256v1 | NID_secp256k1 => Ok(32usize), |
195 | 0 | NID_secp384r1 => Ok(48usize), |
196 | 0 | NID_secp521r1 => Ok(66usize), |
197 | 0 | _ => Err(Unspecified), |
198 | 0 | }?; |
199 | 0 | let private_bn = ConstPointer::new(unsafe { EC_KEY_get0_private_key(*ec_key) })?; |
200 | | |
201 | 0 | let mut cbb = LcCBB::new(key_size); |
202 | 0 | if 1 != unsafe { BN_bn2cbb_padded(cbb.as_mut_ptr(), key_size, *private_bn) } { |
203 | 0 | return Err(Unspecified); |
204 | 0 | } |
205 | 0 | cbb.into_vec() |
206 | 0 | } |
207 | | } |
208 | | |
209 | | pub(crate) mod rfc5915 { |
210 | | use crate::aws_lc::{ |
211 | | EC_KEY_get_enc_flags, EC_KEY_marshal_private_key, EC_KEY_parse_private_key, |
212 | | EVP_PKEY_get0_EC_KEY, EVP_PKEY_new, EVP_PKEY_set1_EC_KEY, EVP_PKEY, |
213 | | }; |
214 | | use crate::cbb::LcCBB; |
215 | | use crate::cbs::build_CBS; |
216 | | use crate::ec::ec_group_from_nid; |
217 | | use crate::error::{KeyRejected, Unspecified}; |
218 | | use crate::ptr::{ConstPointer, LcPtr}; |
219 | | |
220 | 0 | pub(crate) fn parse_rfc5915_private_key( |
221 | 0 | key_bytes: &[u8], |
222 | 0 | expected_curve_nid: i32, |
223 | 0 | ) -> Result<LcPtr<EVP_PKEY>, KeyRejected> { |
224 | 0 | let ec_group = ec_group_from_nid(expected_curve_nid)?; |
225 | 0 | let mut cbs = build_CBS(key_bytes); |
226 | 0 | let mut ec_key = LcPtr::new(unsafe { EC_KEY_parse_private_key(&mut cbs, *ec_group) })?; |
227 | 0 | let mut evp_pkey = LcPtr::new(unsafe { EVP_PKEY_new() })?; |
228 | 0 | if 1 != unsafe { EVP_PKEY_set1_EC_KEY(*evp_pkey.as_mut(), *ec_key.as_mut()) } { |
229 | 0 | return Err(KeyRejected::unexpected_error()); |
230 | 0 | } |
231 | 0 | Ok(evp_pkey) |
232 | 0 | } |
233 | | |
234 | 0 | pub(crate) fn marshal_rfc5915_private_key( |
235 | 0 | evp_pkey: &LcPtr<EVP_PKEY>, |
236 | 0 | ) -> Result<Vec<u8>, Unspecified> { |
237 | 0 | let ec_key = ConstPointer::new(unsafe { EVP_PKEY_get0_EC_KEY(*evp_pkey.as_const()) })?; |
238 | 0 | let mut cbb = LcCBB::new(evp_pkey.key_size_bytes()); |
239 | 0 | let enc_flags = unsafe { EC_KEY_get_enc_flags(*ec_key) }; |
240 | 0 | if 1 != unsafe { EC_KEY_marshal_private_key(cbb.as_mut_ptr(), *ec_key, enc_flags) } { |
241 | 0 | return Err(Unspecified); |
242 | 0 | } |
243 | 0 | cbb.into_vec() |
244 | 0 | } |
245 | | } |
246 | | |
247 | 0 | pub(crate) fn parse_ec_public_key( |
248 | 0 | key_bytes: &[u8], |
249 | 0 | expected_curve_nid: i32, |
250 | 0 | ) -> Result<LcPtr<EVP_PKEY>, KeyRejected> { |
251 | 0 | LcPtr::<EVP_PKEY>::parse_rfc5280_public_key(key_bytes, EVP_PKEY_EC) |
252 | 0 | .or(parse_sec1_public_point(key_bytes, expected_curve_nid)) |
253 | 0 | .and_then(|key| validate_ec_evp_key(&key.as_const(), expected_curve_nid).map(|()| key)) |
254 | 0 | } |