1 // Copyright 2023, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! Contains struct and functions that wraps the API related to EC_KEY in
16 //! BoringSSL.
17 
18 use crate::cbb::CbbFixed;
19 use crate::cbs::Cbs;
20 use crate::util::{check_int_result, to_call_failed_error};
21 use alloc::vec;
22 use alloc::vec::Vec;
23 use bssl_avf_error::{ApiName, Error, Result};
24 use bssl_sys::{
25     i2d_ECDSA_SIG, BN_bin2bn, BN_bn2bin_padded, BN_clear_free, BN_new, CBB_flush, CBB_len,
26     ECDSA_SIG_free, ECDSA_SIG_from_bytes, ECDSA_SIG_get0_r, ECDSA_SIG_get0_s, ECDSA_SIG_new,
27     ECDSA_SIG_set0, ECDSA_sign, ECDSA_size, ECDSA_verify, EC_GROUP_get_curve_name,
28     EC_GROUP_new_by_curve_name, EC_KEY_check_key, EC_KEY_free, EC_KEY_generate_key,
29     EC_KEY_get0_group, EC_KEY_get0_public_key, EC_KEY_marshal_private_key,
30     EC_KEY_new_by_curve_name, EC_KEY_parse_private_key, EC_KEY_set_public_key_affine_coordinates,
31     EC_POINT_get_affine_coordinates, NID_X9_62_prime256v1, NID_secp384r1, BIGNUM, ECDSA_SIG,
32     EC_GROUP, EC_KEY, EC_POINT,
33 };
34 use cbor_util::{get_label_value, get_label_value_as_bytes};
35 use ciborium::Value;
36 use core::mem;
37 use core::ptr::{self, NonNull};
38 use coset::{
39     iana::{self, EnumI64},
40     CborSerializable, CoseKey, CoseKeyBuilder, KeyType, Label,
41 };
42 use log::error;
43 use zeroize::{Zeroize, ZeroizeOnDrop, Zeroizing};
44 
45 const ES256_ALGO: iana::Algorithm = iana::Algorithm::ES256;
46 const P256_CURVE: iana::EllipticCurve = iana::EllipticCurve::P_256;
47 const P384_CURVE: iana::EllipticCurve = iana::EllipticCurve::P_384;
48 const P256_AFFINE_COORDINATE_SIZE: usize = 32;
49 const P384_AFFINE_COORDINATE_SIZE: usize = 48;
50 
51 /// Wrapper of an `EC_KEY` object, representing a public or private EC key.
52 pub struct EcKey(pub(crate) NonNull<EC_KEY>);
53 
54 impl Drop for EcKey {
drop(&mut self)55     fn drop(&mut self) {
56         // SAFETY: It is safe because the key has been allocated by BoringSSL and isn't
57         // used after this.
58         unsafe { EC_KEY_free(self.0.as_ptr()) }
59     }
60 }
61 
62 impl EcKey {
63     /// Creates a new EC P-256 key pair.
new_p256() -> Result<Self>64     pub fn new_p256() -> Result<Self> {
65         // SAFETY: The returned pointer is checked below.
66         let ec_key = unsafe {
67             EC_KEY_new_by_curve_name(NID_X9_62_prime256v1) // EC P-256 CURVE Nid
68         };
69         NonNull::new(ec_key)
70             .map(Self)
71             .ok_or_else(|| to_call_failed_error(ApiName::EC_KEY_new_by_curve_name))
72     }
73 
74     /// Creates a new EC P-384 key pair.
new_p384() -> Result<Self>75     pub fn new_p384() -> Result<Self> {
76         // SAFETY: The returned pointer is checked below.
77         let ec_key = unsafe {
78             EC_KEY_new_by_curve_name(NID_secp384r1) // EC P-384 CURVE Nid
79         };
80         NonNull::new(ec_key)
81             .map(Self)
82             .ok_or_else(|| to_call_failed_error(ApiName::EC_KEY_new_by_curve_name))
83     }
84 
85     /// Constructs an `EcKey` instance from the provided COSE_Key encoded public key slice.
from_cose_public_key_slice(cose_key: &[u8]) -> Result<Self>86     pub fn from_cose_public_key_slice(cose_key: &[u8]) -> Result<Self> {
87         let cose_key = CoseKey::from_slice(cose_key).map_err(|e| {
88             error!("Failed to deserialize COSE_Key: {e:?}");
89             Error::CoseKeyDecodingFailed
90         })?;
91         Self::from_cose_public_key(&cose_key)
92     }
93 
94     /// Constructs an `EcKey` instance from the provided `COSE_Key`.
95     ///
96     /// The lifetime of the returned `EcKey` is not tied to the lifetime of the `cose_key`,
97     /// because the affine coordinates stored in the `cose_key` are copied into the `EcKey`.
98     ///
99     /// Currently, only the EC P-256 and P-384 curves are supported.
from_cose_public_key(cose_key: &CoseKey) -> Result<Self>100     pub fn from_cose_public_key(cose_key: &CoseKey) -> Result<Self> {
101         if cose_key.kty != KeyType::Assigned(iana::KeyType::EC2) {
102             error!("Only EC2 keys are supported. Key type in the COSE Key: {:?}", cose_key.kty);
103             return Err(Error::Unimplemented);
104         }
105         let ec_key =
106             match get_label_value(cose_key, Label::Int(iana::Ec2KeyParameter::Crv.to_i64()))? {
107                 crv if crv == &Value::from(P256_CURVE.to_i64()) => EcKey::new_p256()?,
108                 crv if crv == &Value::from(P384_CURVE.to_i64()) => EcKey::new_p384()?,
109                 crv => {
110                     error!(
111                         "Only EC P-256 and P-384 curves are supported. \
112                          Curve type in the COSE Key: {crv:?}"
113                     );
114                     return Err(Error::Unimplemented);
115                 }
116             };
117         let x = get_label_value_as_bytes(cose_key, Label::Int(iana::Ec2KeyParameter::X.to_i64()))?;
118         let y = get_label_value_as_bytes(cose_key, Label::Int(iana::Ec2KeyParameter::Y.to_i64()))?;
119 
120         let group = ec_key.ec_group()?;
121         group.check_affine_coordinate_size(x)?;
122         group.check_affine_coordinate_size(y)?;
123 
124         let x = BigNum::from_slice(x)?;
125         let y = BigNum::from_slice(y)?;
126 
127         // SAFETY: All the parameters are checked non-null and initialized.
128         // The function only reads the coordinates x and y within their bounds.
129         let ret = unsafe {
130             EC_KEY_set_public_key_affine_coordinates(ec_key.0.as_ptr(), x.as_ref(), y.as_ref())
131         };
132         check_int_result(ret, ApiName::EC_KEY_set_public_key_affine_coordinates)?;
133         ec_key.check_key()?;
134         Ok(ec_key)
135     }
136 
137     /// Performs several checks on the key. See BoringSSL doc for more details:
138     ///
139     /// https://commondatastorage.googleapis.com/chromium-boringssl-docs/ec_key.h.html#EC_KEY_check_key
check_key(&self) -> Result<()>140     pub fn check_key(&self) -> Result<()> {
141         // SAFETY: This function only reads the `EC_KEY` pointer, the non-null check is performed
142         // within the function.
143         let ret = unsafe { EC_KEY_check_key(self.0.as_ptr()) };
144         check_int_result(ret, ApiName::EC_KEY_check_key)
145     }
146 
147     /// Verifies the DER-encoded ECDSA `signature` of the `digest` with the current `EcKey`.
148     ///
149     /// Returns Ok(()) if the verification succeeds, otherwise an error will be returned.
ecdsa_verify_der(&self, signature: &[u8], digest: &[u8]) -> Result<()>150     pub fn ecdsa_verify_der(&self, signature: &[u8], digest: &[u8]) -> Result<()> {
151         // The `type` argument should be 0 as required in the BoringSSL spec.
152         const TYPE: i32 = 0;
153 
154         // SAFETY: This function only reads the given data within its bounds.
155         // The `EC_KEY` passed to this function has been initialized and checked non-null.
156         let ret = unsafe {
157             ECDSA_verify(
158                 TYPE,
159                 digest.as_ptr(),
160                 digest.len(),
161                 signature.as_ptr(),
162                 signature.len(),
163                 self.0.as_ptr(),
164             )
165         };
166         check_int_result(ret, ApiName::ECDSA_verify)
167     }
168 
169     /// Verifies the COSE-encoded (R | S, see RFC8152) ECDSA `signature` of the `digest` with the
170     /// current `EcKey`.
171     ///
172     /// Returns Ok(()) if the verification succeeds, otherwise an error will be returned.
ecdsa_verify_cose(&self, signature: &[u8], digest: &[u8]) -> Result<()>173     pub fn ecdsa_verify_cose(&self, signature: &[u8], digest: &[u8]) -> Result<()> {
174         let signature = ec_cose_signature_to_der(signature)?;
175         self.ecdsa_verify_der(&signature, digest)
176     }
177 
178     /// Signs the `digest` with the current `EcKey` using ECDSA.
179     ///
180     /// Returns the DER-encoded ECDSA signature.
ecdsa_sign_der(&self, digest: &[u8]) -> Result<Vec<u8>>181     pub fn ecdsa_sign_der(&self, digest: &[u8]) -> Result<Vec<u8>> {
182         // The `type` argument should be 0 as required in the BoringSSL spec.
183         const TYPE: i32 = 0;
184 
185         let mut signature = vec![0u8; self.ecdsa_size()?];
186         let mut signature_len = 0;
187         // SAFETY: This function only reads the given data within its bounds.
188         // The `EC_KEY` passed to this function has been initialized and checked non-null.
189         let ret = unsafe {
190             ECDSA_sign(
191                 TYPE,
192                 digest.as_ptr(),
193                 digest.len(),
194                 signature.as_mut_ptr(),
195                 &mut signature_len,
196                 self.0.as_ptr(),
197             )
198         };
199         check_int_result(ret, ApiName::ECDSA_sign)?;
200         if signature.len() < (signature_len as usize) {
201             Err(to_call_failed_error(ApiName::ECDSA_sign))
202         } else {
203             signature.truncate(signature_len as usize);
204             Ok(signature)
205         }
206     }
207 
208     /// Signs the `digest` with the current `EcKey` using ECDSA.
209     ///
210     /// Returns the COSE-encoded (R | S, see RFC8152) ECDSA signature.
ecdsa_sign_cose(&self, digest: &[u8]) -> Result<Vec<u8>>211     pub fn ecdsa_sign_cose(&self, digest: &[u8]) -> Result<Vec<u8>> {
212         let signature = self.ecdsa_sign_der(digest)?;
213         let coord_bytes = self.ec_group()?.affine_coordinate_size()?;
214         ec_der_signature_to_cose(&signature, coord_bytes)
215     }
216 
217     /// Returns the maximum size of an ECDSA signature using the current `EcKey`.
ecdsa_size(&self) -> Result<usize>218     fn ecdsa_size(&self) -> Result<usize> {
219         // SAFETY: This function only reads the `EC_KEY` that has been initialized
220         // and checked non-null when this instance is created.
221         let size = unsafe { ECDSA_size(self.0.as_ptr()) };
222         if size == 0 {
223             Err(to_call_failed_error(ApiName::ECDSA_size))
224         } else {
225             Ok(size)
226         }
227     }
228 
229     /// Generates a random, private key, calculates the corresponding public key and stores both
230     /// in the `EC_KEY`.
generate_key(&mut self) -> Result<()>231     pub fn generate_key(&mut self) -> Result<()> {
232         // SAFETY: The non-null pointer is created with `EC_KEY_new_by_curve_name` and should
233         // point to a valid `EC_KEY`.
234         // The randomness is provided by `getentropy()` in `vmbase`.
235         let ret = unsafe { EC_KEY_generate_key(self.0.as_ptr()) };
236         check_int_result(ret, ApiName::EC_KEY_generate_key)
237     }
238 
239     /// Returns the `CoseKey` for the public key.
cose_public_key(&self) -> Result<CoseKey>240     pub fn cose_public_key(&self) -> Result<CoseKey> {
241         let (x, y) = self.public_key_coordinates()?;
242         let curve = self.ec_group()?.coset_curve()?;
243         let key = CoseKeyBuilder::new_ec2_pub_key(curve, x, y).algorithm(ES256_ALGO).build();
244         Ok(key)
245     }
246 
247     /// Returns the x and y coordinates of the public key.
public_key_coordinates(&self) -> Result<(Vec<u8>, Vec<u8>)>248     fn public_key_coordinates(&self) -> Result<(Vec<u8>, Vec<u8>)> {
249         let ec_group = self.ec_group()?;
250         let ec_point = self.public_key_ec_point()?;
251         let mut x = BigNum::new()?;
252         let mut y = BigNum::new()?;
253         let ctx = ptr::null_mut();
254         // SAFETY: All the parameters are checked non-null and initialized when needed.
255         // The last parameter `ctx` is generated when needed inside the function.
256         let ret = unsafe {
257             EC_POINT_get_affine_coordinates(
258                 ec_group.as_ref(),
259                 ec_point,
260                 x.as_mut_ptr(),
261                 y.as_mut_ptr(),
262                 ctx,
263             )
264         };
265         check_int_result(ret, ApiName::EC_POINT_get_affine_coordinates)?;
266         let len = ec_group.affine_coordinate_size()?;
267         Ok((x.to_padded_vec(len)?, y.to_padded_vec(len)?))
268     }
269 
270     /// Returns a pointer to the public key point inside `EC_KEY`. The memory region pointed
271     /// by the pointer is owned by the `EC_KEY`.
public_key_ec_point(&self) -> Result<*const EC_POINT>272     fn public_key_ec_point(&self) -> Result<*const EC_POINT> {
273         let ec_point =
274            // SAFETY: It is safe since the key pair has been generated and stored in the
275            // `EC_KEY` pointer.
276            unsafe { EC_KEY_get0_public_key(self.0.as_ptr()) };
277         if ec_point.is_null() {
278             Err(to_call_failed_error(ApiName::EC_KEY_get0_public_key))
279         } else {
280             Ok(ec_point)
281         }
282     }
283 
284     /// Returns a pointer to the `EC_GROUP` object inside `EC_KEY`. The memory region pointed
285     /// by the pointer is owned by the `EC_KEY`.
ec_group(&self) -> Result<EcGroup<'_>>286     fn ec_group(&self) -> Result<EcGroup<'_>> {
287         let group =
288            // SAFETY: It is safe since the key pair has been generated and stored in the
289            // `EC_KEY` pointer.
290            unsafe { EC_KEY_get0_group(self.0.as_ptr()) };
291         if group.is_null() {
292             Err(to_call_failed_error(ApiName::EC_KEY_get0_group))
293         } else {
294             // SAFETY: The pointer should be valid and points to an initialized `EC_GROUP`
295             // since it is read from a valid `EC_KEY`.
296             Ok(EcGroup(unsafe { &*group }))
297         }
298     }
299 
300     /// Constructs an `EcKey` instance from the provided DER-encoded ECPrivateKey slice.
301     ///
302     /// Currently, only the EC P-256 curve is supported.
from_ec_private_key(der_encoded_ec_private_key: &[u8]) -> Result<Self>303     pub fn from_ec_private_key(der_encoded_ec_private_key: &[u8]) -> Result<Self> {
304         // SAFETY: This function only returns a pointer to a static object, and the
305         // return is checked below.
306         let ec_group = unsafe {
307             EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1) // EC P-256 CURVE Nid
308         };
309         if ec_group.is_null() {
310             return Err(to_call_failed_error(ApiName::EC_GROUP_new_by_curve_name));
311         }
312         let mut cbs = Cbs::new(der_encoded_ec_private_key);
313         // SAFETY: The function only reads bytes from the buffer managed by the valid `CBS`
314         // object, and the returned EC_KEY is checked.
315         let ec_key = unsafe { EC_KEY_parse_private_key(cbs.as_mut(), ec_group) };
316 
317         let ec_key = NonNull::new(ec_key)
318             .map(Self)
319             .ok_or_else(|| to_call_failed_error(ApiName::EC_KEY_parse_private_key))?;
320         ec_key.check_key()?;
321         Ok(ec_key)
322     }
323 
324     /// Returns the DER-encoded ECPrivateKey structure described in RFC 5915 Section 3:
325     ///
326     /// https://datatracker.ietf.org/doc/html/rfc5915#section-3
ec_private_key(&self) -> Result<ZVec>327     pub fn ec_private_key(&self) -> Result<ZVec> {
328         const CAPACITY: usize = 256;
329         let mut buf = Zeroizing::new([0u8; CAPACITY]);
330         let mut cbb = CbbFixed::new(buf.as_mut());
331         let enc_flags = 0;
332         let ret =
333             // SAFETY: The function only write bytes to the buffer managed by the valid `CBB`
334             // object, and the key has been allocated by BoringSSL.
335             unsafe { EC_KEY_marshal_private_key(cbb.as_mut(), self.0.as_ptr(), enc_flags) };
336 
337         check_int_result(ret, ApiName::EC_KEY_marshal_private_key)?;
338         // SAFETY: This is safe because the CBB pointer is a valid pointer initialized with
339         // `CBB_init_fixed()`.
340         check_int_result(unsafe { CBB_flush(cbb.as_mut()) }, ApiName::CBB_flush)?;
341         // SAFETY: This is safe because the CBB pointer is initialized with `CBB_init_fixed()`,
342         // and it has been flushed, thus it has no active children.
343         let len = unsafe { CBB_len(cbb.as_ref()) };
344         Ok(buf.get(0..len).ok_or_else(|| to_call_failed_error(ApiName::CBB_len))?.to_vec().into())
345     }
346 }
347 
348 /// Convert a COSE format (R | S) ECDSA signature to a DER-encoded form.
ec_cose_signature_to_der(signature: &[u8]) -> Result<Vec<u8>>349 fn ec_cose_signature_to_der(signature: &[u8]) -> Result<Vec<u8>> {
350     let mut ec_sig = EcSignature::new()?;
351     ec_sig.load_from_cose(signature)?;
352     ec_sig.to_der()
353 }
354 
355 /// Convert a DER-encoded signature to COSE format (R | S).
ec_der_signature_to_cose(signature: &[u8], coord_bytes: usize) -> Result<Vec<u8>>356 fn ec_der_signature_to_cose(signature: &[u8], coord_bytes: usize) -> Result<Vec<u8>> {
357     let ec_sig = EcSignature::new_from_der(signature)?;
358     ec_sig.to_cose(coord_bytes)
359 }
360 
361 /// Wrapper for an `ECDSA_SIG` object representing an EC signature.
362 struct EcSignature(NonNull<ECDSA_SIG>);
363 
364 impl EcSignature {
365     /// Allocate a signature object.
new() -> Result<Self>366     fn new() -> Result<Self> {
367         // SAFETY: We take ownership of the returned pointer if it is non-null.
368         let signature = unsafe { ECDSA_SIG_new() };
369 
370         let signature =
371             NonNull::new(signature).ok_or_else(|| to_call_failed_error(ApiName::ECDSA_SIG_new))?;
372         Ok(Self(signature))
373     }
374 
375     /// Populate the signature parameters from a COSE encoding (R | S).
load_from_cose(&mut self, signature: &[u8]) -> Result<()>376     fn load_from_cose(&mut self, signature: &[u8]) -> Result<()> {
377         let coord_bytes = signature.len() / 2;
378         if signature.len() != 2 * coord_bytes {
379             return Err(Error::InternalError);
380         }
381         let mut r = BigNum::from_slice(&signature[..coord_bytes])?;
382         let mut s = BigNum::from_slice(&signature[coord_bytes..])?;
383 
384         check_int_result(
385             // SAFETY: The ECDSA_SIG was properly allocated and not yet freed. We have ownership
386             // of the two BigNums and they are not null.
387             unsafe { ECDSA_SIG_set0(self.0.as_mut(), r.as_mut_ptr(), s.as_mut_ptr()) },
388             ApiName::ECDSA_SIG_set0,
389         )?;
390 
391         // On success, the ECDSA_SIG has taken ownership of the BigNums.
392         mem::forget(r);
393         mem::forget(s);
394 
395         Ok(())
396     }
397 
to_cose(&self, coord_bytes: usize) -> Result<Vec<u8>>398     fn to_cose(&self, coord_bytes: usize) -> Result<Vec<u8>> {
399         let mut result = vec![0u8; coord_bytes.checked_mul(2).unwrap()];
400         let (r_bytes, s_bytes) = result.split_at_mut(coord_bytes);
401 
402         // SAFETY: The ECDSA_SIG was properly allocated and not yet freed. Always returns a valid
403         // non-null, non-owning pointer.
404         let r = unsafe { ECDSA_SIG_get0_r(self.0.as_ptr()) };
405         check_int_result(
406             // SAFETY: The r pointer is known to be valid. Only writes within the destination
407             // slice.
408             unsafe { BN_bn2bin_padded(r_bytes.as_mut_ptr(), r_bytes.len(), r) },
409             ApiName::BN_bn2bin_padded,
410         )?;
411 
412         // SAFETY: The ECDSA_SIG was properly allocated and not yet freed. Always returns a valid
413         // non-null, non-owning pointer.
414         let s = unsafe { ECDSA_SIG_get0_s(self.0.as_ptr()) };
415         check_int_result(
416             // SAFETY: The r pointer is known to be valid. Only writes within the destination
417             // slice.
418             unsafe { BN_bn2bin_padded(s_bytes.as_mut_ptr(), s_bytes.len(), s) },
419             ApiName::BN_bn2bin_padded,
420         )?;
421 
422         Ok(result)
423     }
424 
425     /// Populate the signature parameters from a DER encoding
new_from_der(signature: &[u8]) -> Result<Self>426     fn new_from_der(signature: &[u8]) -> Result<Self> {
427         // SAFETY: Only reads within the bounds of the slice. Returns a pointer to a new ECDSA_SIG
428         // which we take ownership of, or null on error which we check.
429         let signature = unsafe { ECDSA_SIG_from_bytes(signature.as_ptr(), signature.len()) };
430 
431         let signature = NonNull::new(signature)
432             .ok_or_else(|| to_call_failed_error(ApiName::ECDSA_SIG_from_bytes))?;
433         Ok(Self(signature))
434     }
435 
436     /// Return the signature encoded as DER.
to_der(&self) -> Result<Vec<u8>>437     fn to_der(&self) -> Result<Vec<u8>> {
438         // SAFETY: The ECDSA_SIG was properly allocated and not yet freed. Null is a valid
439         // value for `outp`; no output is written.
440         let len = unsafe { i2d_ECDSA_SIG(self.0.as_ptr(), ptr::null_mut()) };
441         if len < 0 {
442             return Err(to_call_failed_error(ApiName::i2d_ECDSA_SIG));
443         }
444 
445         let mut buf = vec![0; len.try_into().map_err(|_| Error::InternalError)?];
446         let outp = &mut buf.as_mut_ptr();
447         // SAFETY: The ECDSA_SIG was properly allocated and not yet freed. `outp` is a non-null
448         // pointer to a mutable buffer of the right size to which the result will be written.
449         let final_len = unsafe { i2d_ECDSA_SIG(self.0.as_ptr(), outp) };
450         if final_len < 0 {
451             return Err(to_call_failed_error(ApiName::i2d_ECDSA_SIG));
452         }
453         // The input hasn't changed, so the length of the output shouldn't have. If it has we
454         // already have potentially undefined behavior so panic.
455         assert_eq!(
456             len, final_len,
457             "i2d_ECDSA_SIG returned inconsistent lengths: {len}, {final_len}"
458         );
459 
460         Ok(buf)
461     }
462 }
463 
464 impl Drop for EcSignature {
drop(&mut self)465     fn drop(&mut self) {
466         // SAFETY: The pointer was allocated by `ECDSA_SIG_new`.
467         unsafe { ECDSA_SIG_free(self.0.as_mut()) };
468     }
469 }
470 
471 /// Wrapper of an `EC_GROUP` reference.
472 struct EcGroup<'a>(&'a EC_GROUP);
473 
474 impl<'a> EcGroup<'a> {
475     /// Returns the NID that identifies the EC group of the key.
curve_nid(&self) -> i32476     fn curve_nid(&self) -> i32 {
477         // SAFETY: It is safe since the inner pointer is valid and points to an initialized
478         // instance of `EC_GROUP`.
479         unsafe { EC_GROUP_get_curve_name(self.as_ref()) }
480     }
481 
coset_curve(&self) -> Result<iana::EllipticCurve>482     fn coset_curve(&self) -> Result<iana::EllipticCurve> {
483         #[allow(non_upper_case_globals)]
484         match self.curve_nid() {
485             NID_X9_62_prime256v1 => Ok(P256_CURVE),
486             NID_secp384r1 => Ok(P384_CURVE),
487             name => {
488                 error!("Unsupported curve NID: {}", name);
489                 Err(Error::Unimplemented)
490             }
491         }
492     }
493 
affine_coordinate_size(&self) -> Result<usize>494     fn affine_coordinate_size(&self) -> Result<usize> {
495         #[allow(non_upper_case_globals)]
496         match self.curve_nid() {
497             NID_X9_62_prime256v1 => Ok(P256_AFFINE_COORDINATE_SIZE),
498             NID_secp384r1 => Ok(P384_AFFINE_COORDINATE_SIZE),
499             name => {
500                 error!("Unsupported curve NID: {}", name);
501                 Err(Error::Unimplemented)
502             }
503         }
504     }
505 
check_affine_coordinate_size(&self, coordinate: &[u8]) -> Result<()>506     fn check_affine_coordinate_size(&self, coordinate: &[u8]) -> Result<()> {
507         let expected_len = self.affine_coordinate_size()?;
508         if expected_len == coordinate.len() {
509             Ok(())
510         } else {
511             error!(
512                 "The size of the affine coordinate '{}' does not match the expected size '{}'",
513                 coordinate.len(),
514                 expected_len
515             );
516             Err(Error::CoseKeyDecodingFailed)
517         }
518     }
519 }
520 
521 impl<'a> AsRef<EC_GROUP> for EcGroup<'a> {
as_ref(&self) -> &EC_GROUP522     fn as_ref(&self) -> &EC_GROUP {
523         self.0
524     }
525 }
526 
527 /// A u8 vector that is zeroed when dropped.
528 #[derive(Zeroize, ZeroizeOnDrop)]
529 pub struct ZVec(Vec<u8>);
530 
531 impl ZVec {
532     /// Extracts a slice containing the entire vector.
as_slice(&self) -> &[u8]533     pub fn as_slice(&self) -> &[u8] {
534         &self.0[..]
535     }
536 }
537 
538 impl From<Vec<u8>> for ZVec {
from(v: Vec<u8>) -> Self539     fn from(v: Vec<u8>) -> Self {
540         Self(v)
541     }
542 }
543 
544 struct BigNum(NonNull<BIGNUM>);
545 
546 impl Drop for BigNum {
drop(&mut self)547     fn drop(&mut self) {
548         // SAFETY: The pointer has been created with `BN_new`.
549         unsafe { BN_clear_free(self.as_mut_ptr()) }
550     }
551 }
552 
553 impl BigNum {
from_slice(x: &[u8]) -> Result<Self>554     fn from_slice(x: &[u8]) -> Result<Self> {
555         // SAFETY: The function reads `x` within its bounds, and the returned
556         // pointer is checked below.
557         let bn = unsafe { BN_bin2bn(x.as_ptr(), x.len(), ptr::null_mut()) };
558         NonNull::new(bn).map(Self).ok_or_else(|| to_call_failed_error(ApiName::BN_bin2bn))
559     }
560 
new() -> Result<Self>561     fn new() -> Result<Self> {
562         // SAFETY: The returned pointer is checked below.
563         let bn = unsafe { BN_new() };
564         NonNull::new(bn).map(Self).ok_or_else(|| to_call_failed_error(ApiName::BN_new))
565     }
566 
567     /// Converts the `BigNum` to a big-endian integer. The integer is padded with leading zeros up
568     /// to size `len`. The conversion fails if `len` is smaller than the size of the integer.
to_padded_vec(&self, len: usize) -> Result<Vec<u8>>569     fn to_padded_vec(&self, len: usize) -> Result<Vec<u8>> {
570         let mut num = vec![0u8; len];
571         // SAFETY: The `BIGNUM` pointer has been created with `BN_new`.
572         let ret = unsafe { BN_bn2bin_padded(num.as_mut_ptr(), num.len(), self.0.as_ptr()) };
573         check_int_result(ret, ApiName::BN_bn2bin_padded)?;
574         Ok(num)
575     }
576 
as_mut_ptr(&mut self) -> *mut BIGNUM577     fn as_mut_ptr(&mut self) -> *mut BIGNUM {
578         self.0.as_ptr()
579     }
580 }
581 
582 impl AsRef<BIGNUM> for BigNum {
as_ref(&self) -> &BIGNUM583     fn as_ref(&self) -> &BIGNUM {
584         // SAFETY: The pointer is valid and points to an initialized instance of `BIGNUM`
585         // when the instance was created.
586         unsafe { self.0.as_ref() }
587     }
588 }
589