blob: 6c9910ca30768750aae68388bf6d16c1e2920fa1 [file] [log] [blame]
Alice Wang7b2ab942023-09-12 13:04:42 +00001// 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
Alice Wangb3fcf632023-09-26 08:32:55 +000018use crate::cbb::CbbFixed;
Alice Wang000595b2023-10-02 13:46:45 +000019use crate::cbs::Cbs;
Alice Wangdd29c5d2023-12-07 09:56:23 +000020use crate::util::{check_int_result, to_call_failed_error};
Alice Wang0271ee02023-11-15 15:03:42 +000021use alloc::vec;
Alice Wang7b2ab942023-09-12 13:04:42 +000022use alloc::vec::Vec;
Alice Wangb3fcf632023-09-26 08:32:55 +000023use bssl_avf_error::{ApiName, Error, Result};
Maurice Lam0322b8c2023-12-18 22:13:48 +000024use bssl_sys::{
Alice Wang0271ee02023-11-15 15:03:42 +000025 BN_bin2bn, BN_bn2bin_padded, BN_clear_free, BN_new, CBB_flush, CBB_len, ECDSA_sign, ECDSA_size,
Alice Wang306c8e22023-11-29 12:40:43 +000026 ECDSA_verify, EC_GROUP_get_curve_name, EC_GROUP_new_by_curve_name, EC_KEY_check_key,
27 EC_KEY_free, EC_KEY_generate_key, EC_KEY_get0_group, EC_KEY_get0_public_key,
28 EC_KEY_marshal_private_key, EC_KEY_new_by_curve_name, EC_KEY_parse_private_key,
29 EC_KEY_set_public_key_affine_coordinates, EC_POINT_get_affine_coordinates,
30 NID_X9_62_prime256v1, NID_secp384r1, BIGNUM, EC_GROUP, EC_KEY, EC_POINT,
Alan Stokesb1f64ee2023-09-25 10:38:13 +010031};
Alice Wangdd29c5d2023-12-07 09:56:23 +000032use cbor_util::{get_label_value, get_label_value_as_bytes};
Alice Wang9bd98092023-11-10 14:08:12 +000033use ciborium::Value;
Alice Wanga78d3f02023-09-13 12:39:16 +000034use core::ptr::{self, NonNull};
Alice Wang9bd98092023-11-10 14:08:12 +000035use coset::{
36 iana::{self, EnumI64},
Alice Wangbe7a4b12023-12-01 11:53:36 +000037 CborSerializable, CoseKey, CoseKeyBuilder, KeyType, Label,
Alice Wang9bd98092023-11-10 14:08:12 +000038};
39use log::error;
Alice Wang7b2ab942023-09-12 13:04:42 +000040use zeroize::{Zeroize, ZeroizeOnDrop, Zeroizing};
41
Alice Wang9bd98092023-11-10 14:08:12 +000042const ES256_ALGO: iana::Algorithm = iana::Algorithm::ES256;
43const P256_CURVE: iana::EllipticCurve = iana::EllipticCurve::P_256;
Alice Wang306c8e22023-11-29 12:40:43 +000044const P384_CURVE: iana::EllipticCurve = iana::EllipticCurve::P_384;
Alice Wanga78d3f02023-09-13 12:39:16 +000045const P256_AFFINE_COORDINATE_SIZE: usize = 32;
Alice Wang306c8e22023-11-29 12:40:43 +000046const P384_AFFINE_COORDINATE_SIZE: usize = 48;
Alice Wang7b2ab942023-09-12 13:04:42 +000047
48/// Wrapper of an `EC_KEY` object, representing a public or private EC key.
Alice Wang600ea5b2023-11-17 15:12:16 +000049pub struct EcKey(pub(crate) NonNull<EC_KEY>);
Alice Wang7b2ab942023-09-12 13:04:42 +000050
51impl Drop for EcKey {
52 fn drop(&mut self) {
53 // SAFETY: It is safe because the key has been allocated by BoringSSL and isn't
54 // used after this.
55 unsafe { EC_KEY_free(self.0.as_ptr()) }
56 }
57}
58
59impl EcKey {
60 /// Creates a new EC P-256 key pair.
61 pub fn new_p256() -> Result<Self> {
62 // SAFETY: The returned pointer is checked below.
Alan Stokesb1f64ee2023-09-25 10:38:13 +010063 let ec_key = unsafe {
64 EC_KEY_new_by_curve_name(NID_X9_62_prime256v1) // EC P-256 CURVE Nid
65 };
Alice Wang9bd98092023-11-10 14:08:12 +000066 NonNull::new(ec_key)
Alice Wangc8f88f52023-09-25 14:02:17 +000067 .map(Self)
Alice Wang9bd98092023-11-10 14:08:12 +000068 .ok_or(to_call_failed_error(ApiName::EC_KEY_new_by_curve_name))
69 }
70
Alice Wang306c8e22023-11-29 12:40:43 +000071 /// Creates a new EC P-384 key pair.
72 pub fn new_p384() -> Result<Self> {
73 // SAFETY: The returned pointer is checked below.
74 let ec_key = unsafe {
75 EC_KEY_new_by_curve_name(NID_secp384r1) // EC P-384 CURVE Nid
76 };
77 NonNull::new(ec_key)
78 .map(Self)
79 .ok_or(to_call_failed_error(ApiName::EC_KEY_new_by_curve_name))
80 }
81
Alice Wang9bd98092023-11-10 14:08:12 +000082 /// Constructs an `EcKey` instance from the provided COSE_Key encoded public key slice.
Alice Wangbe7a4b12023-12-01 11:53:36 +000083 pub fn from_cose_public_key_slice(cose_key: &[u8]) -> Result<Self> {
Alice Wang9bd98092023-11-10 14:08:12 +000084 let cose_key = CoseKey::from_slice(cose_key).map_err(|e| {
85 error!("Failed to deserialize COSE_Key: {e:?}");
86 Error::CoseKeyDecodingFailed
87 })?;
Alice Wangbe7a4b12023-12-01 11:53:36 +000088 Self::from_cose_public_key(&cose_key)
89 }
90
91 /// Constructs an `EcKey` instance from the provided `COSE_Key`.
92 ///
93 /// The lifetime of the returned `EcKey` is not tied to the lifetime of the `cose_key`,
94 /// because the affine coordinates stored in the `cose_key` are copied into the `EcKey`.
95 ///
96 /// Currently, only the EC P-256 and P-384 curves are supported.
97 pub fn from_cose_public_key(cose_key: &CoseKey) -> Result<Self> {
98 if cose_key.kty != KeyType::Assigned(iana::KeyType::EC2) {
99 error!("Only EC2 keys are supported. Key type in the COSE Key: {:?}", cose_key.kty);
100 return Err(Error::Unimplemented);
101 }
Alice Wang306c8e22023-11-29 12:40:43 +0000102 let ec_key =
Alice Wangbe7a4b12023-12-01 11:53:36 +0000103 match get_label_value(cose_key, Label::Int(iana::Ec2KeyParameter::Crv.to_i64()))? {
Alice Wang306c8e22023-11-29 12:40:43 +0000104 crv if crv == &Value::from(P256_CURVE.to_i64()) => EcKey::new_p256()?,
105 crv if crv == &Value::from(P384_CURVE.to_i64()) => EcKey::new_p384()?,
106 crv => {
107 error!(
108 "Only EC P-256 and P-384 curves are supported. \
109 Curve type in the COSE Key: {crv:?}"
110 );
111 return Err(Error::Unimplemented);
112 }
113 };
Alice Wangbe7a4b12023-12-01 11:53:36 +0000114 let x = get_label_value_as_bytes(cose_key, Label::Int(iana::Ec2KeyParameter::X.to_i64()))?;
115 let y = get_label_value_as_bytes(cose_key, Label::Int(iana::Ec2KeyParameter::Y.to_i64()))?;
Alice Wang9bd98092023-11-10 14:08:12 +0000116
Alice Wang306c8e22023-11-29 12:40:43 +0000117 let group = ec_key.ec_group()?;
118 group.check_affine_coordinate_size(x)?;
119 group.check_affine_coordinate_size(y)?;
Alice Wang9bd98092023-11-10 14:08:12 +0000120
121 let x = BigNum::from_slice(x)?;
122 let y = BigNum::from_slice(y)?;
123
Alice Wang9bd98092023-11-10 14:08:12 +0000124 // SAFETY: All the parameters are checked non-null and initialized.
125 // The function only reads the coordinates x and y within their bounds.
126 let ret = unsafe {
127 EC_KEY_set_public_key_affine_coordinates(ec_key.0.as_ptr(), x.as_ref(), y.as_ref())
128 };
129 check_int_result(ret, ApiName::EC_KEY_set_public_key_affine_coordinates)?;
Alice Wangf061e472023-11-21 08:17:16 +0000130 ec_key.check_key()?;
Alice Wang7b2ab942023-09-12 13:04:42 +0000131 Ok(ec_key)
132 }
133
Alice Wang000595b2023-10-02 13:46:45 +0000134 /// Performs several checks on the key. See BoringSSL doc for more details:
135 ///
136 /// https://commondatastorage.googleapis.com/chromium-boringssl-docs/ec_key.h.html#EC_KEY_check_key
137 pub fn check_key(&self) -> Result<()> {
138 // SAFETY: This function only reads the `EC_KEY` pointer, the non-null check is performed
139 // within the function.
140 let ret = unsafe { EC_KEY_check_key(self.0.as_ptr()) };
141 check_int_result(ret, ApiName::EC_KEY_check_key)
142 }
143
Alice Wang0271ee02023-11-15 15:03:42 +0000144 /// Verifies the DER-encoded ECDSA `signature` of the `digest` with the current `EcKey`.
145 ///
146 /// Returns Ok(()) if the verification succeeds, otherwise an error will be returned.
147 pub fn ecdsa_verify(&self, signature: &[u8], digest: &[u8]) -> Result<()> {
148 // The `type` argument should be 0 as required in the BoringSSL spec.
149 const TYPE: i32 = 0;
150
151 // SAFETY: This function only reads the given data within its bounds.
152 // The `EC_KEY` passed to this function has been initialized and checked non-null.
153 let ret = unsafe {
154 ECDSA_verify(
155 TYPE,
156 digest.as_ptr(),
157 digest.len(),
158 signature.as_ptr(),
159 signature.len(),
160 self.0.as_ptr(),
161 )
162 };
163 check_int_result(ret, ApiName::ECDSA_verify)
Alice Wang9bd98092023-11-10 14:08:12 +0000164 }
165
Alice Wang0271ee02023-11-15 15:03:42 +0000166 /// Signs the `digest` with the current `EcKey` using ECDSA.
Alice Wang9bd98092023-11-10 14:08:12 +0000167 ///
168 /// Returns the DER-encoded ECDSA signature.
Alice Wang0271ee02023-11-15 15:03:42 +0000169 pub fn ecdsa_sign(&self, digest: &[u8]) -> Result<Vec<u8>> {
170 // The `type` argument should be 0 as required in the BoringSSL spec.
171 const TYPE: i32 = 0;
172
173 let mut signature = vec![0u8; self.ecdsa_size()?];
174 let mut signature_len = 0;
175 // SAFETY: This function only reads the given data within its bounds.
176 // The `EC_KEY` passed to this function has been initialized and checked non-null.
177 let ret = unsafe {
178 ECDSA_sign(
179 TYPE,
180 digest.as_ptr(),
181 digest.len(),
182 signature.as_mut_ptr(),
183 &mut signature_len,
184 self.0.as_ptr(),
185 )
186 };
187 check_int_result(ret, ApiName::ECDSA_sign)?;
188 if signature.len() < (signature_len as usize) {
189 Err(to_call_failed_error(ApiName::ECDSA_sign))
190 } else {
191 signature.truncate(signature_len as usize);
192 Ok(signature)
193 }
194 }
195
196 /// Returns the maximum size of an ECDSA signature using the current `EcKey`.
197 fn ecdsa_size(&self) -> Result<usize> {
198 // SAFETY: This function only reads the `EC_KEY` that has been initialized
199 // and checked non-null when this instance is created.
200 let size = unsafe { ECDSA_size(self.0.as_ptr()) };
201 if size == 0 {
202 Err(to_call_failed_error(ApiName::ECDSA_size))
203 } else {
204 Ok(size)
205 }
Alice Wang9bd98092023-11-10 14:08:12 +0000206 }
207
Alice Wang7b2ab942023-09-12 13:04:42 +0000208 /// Generates a random, private key, calculates the corresponding public key and stores both
209 /// in the `EC_KEY`.
Alice Wang9bd98092023-11-10 14:08:12 +0000210 pub fn generate_key(&mut self) -> Result<()> {
Alice Wang7b2ab942023-09-12 13:04:42 +0000211 // SAFETY: The non-null pointer is created with `EC_KEY_new_by_curve_name` and should
212 // point to a valid `EC_KEY`.
213 // The randomness is provided by `getentropy()` in `vmbase`.
214 let ret = unsafe { EC_KEY_generate_key(self.0.as_ptr()) };
Alice Wangc8f88f52023-09-25 14:02:17 +0000215 check_int_result(ret, ApiName::EC_KEY_generate_key)
Alice Wang7b2ab942023-09-12 13:04:42 +0000216 }
217
Alice Wanga78d3f02023-09-13 12:39:16 +0000218 /// Returns the `CoseKey` for the public key.
219 pub fn cose_public_key(&self) -> Result<CoseKey> {
Alice Wanga78d3f02023-09-13 12:39:16 +0000220 let (x, y) = self.public_key_coordinates()?;
Alice Wang306c8e22023-11-29 12:40:43 +0000221 let curve = self.ec_group()?.coset_curve()?;
222 let key = CoseKeyBuilder::new_ec2_pub_key(curve, x, y).algorithm(ES256_ALGO).build();
Alice Wanga78d3f02023-09-13 12:39:16 +0000223 Ok(key)
224 }
225
226 /// Returns the x and y coordinates of the public key.
Alice Wang306c8e22023-11-29 12:40:43 +0000227 fn public_key_coordinates(&self) -> Result<(Vec<u8>, Vec<u8>)> {
Alice Wanga78d3f02023-09-13 12:39:16 +0000228 let ec_group = self.ec_group()?;
229 let ec_point = self.public_key_ec_point()?;
230 let mut x = BigNum::new()?;
231 let mut y = BigNum::new()?;
232 let ctx = ptr::null_mut();
233 // SAFETY: All the parameters are checked non-null and initialized when needed.
234 // The last parameter `ctx` is generated when needed inside the function.
235 let ret = unsafe {
Alice Wang306c8e22023-11-29 12:40:43 +0000236 EC_POINT_get_affine_coordinates(
237 ec_group.as_ref(),
238 ec_point,
239 x.as_mut_ptr(),
240 y.as_mut_ptr(),
241 ctx,
242 )
Alice Wanga78d3f02023-09-13 12:39:16 +0000243 };
Alice Wangc8f88f52023-09-25 14:02:17 +0000244 check_int_result(ret, ApiName::EC_POINT_get_affine_coordinates)?;
Alice Wang306c8e22023-11-29 12:40:43 +0000245 let len = ec_group.affine_coordinate_size()?;
246 Ok((x.to_padded_vec(len)?, y.to_padded_vec(len)?))
Alice Wanga78d3f02023-09-13 12:39:16 +0000247 }
248
249 /// Returns a pointer to the public key point inside `EC_KEY`. The memory region pointed
250 /// by the pointer is owned by the `EC_KEY`.
251 fn public_key_ec_point(&self) -> Result<*const EC_POINT> {
252 let ec_point =
253 // SAFETY: It is safe since the key pair has been generated and stored in the
254 // `EC_KEY` pointer.
255 unsafe { EC_KEY_get0_public_key(self.0.as_ptr()) };
256 if ec_point.is_null() {
Alice Wang47287e72023-09-29 13:14:33 +0000257 Err(to_call_failed_error(ApiName::EC_KEY_get0_public_key))
Alice Wanga78d3f02023-09-13 12:39:16 +0000258 } else {
259 Ok(ec_point)
260 }
261 }
262
263 /// Returns a pointer to the `EC_GROUP` object inside `EC_KEY`. The memory region pointed
264 /// by the pointer is owned by the `EC_KEY`.
Alice Wang306c8e22023-11-29 12:40:43 +0000265 fn ec_group(&self) -> Result<EcGroup<'_>> {
Alice Wanga78d3f02023-09-13 12:39:16 +0000266 let group =
267 // SAFETY: It is safe since the key pair has been generated and stored in the
268 // `EC_KEY` pointer.
269 unsafe { EC_KEY_get0_group(self.0.as_ptr()) };
270 if group.is_null() {
Alice Wang47287e72023-09-29 13:14:33 +0000271 Err(to_call_failed_error(ApiName::EC_KEY_get0_group))
Alice Wanga78d3f02023-09-13 12:39:16 +0000272 } else {
Alice Wang306c8e22023-11-29 12:40:43 +0000273 // SAFETY: The pointer should be valid and points to an initialized `EC_GROUP`
274 // since it is read from a valid `EC_KEY`.
275 Ok(EcGroup(unsafe { &*group }))
Alice Wanga78d3f02023-09-13 12:39:16 +0000276 }
277 }
Alice Wang7b2ab942023-09-12 13:04:42 +0000278
Alice Wang000595b2023-10-02 13:46:45 +0000279 /// Constructs an `EcKey` instance from the provided DER-encoded ECPrivateKey slice.
280 ///
281 /// Currently, only the EC P-256 curve is supported.
282 pub fn from_ec_private_key(der_encoded_ec_private_key: &[u8]) -> Result<Self> {
283 // SAFETY: This function only returns a pointer to a static object, and the
284 // return is checked below.
285 let ec_group = unsafe {
286 EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1) // EC P-256 CURVE Nid
287 };
288 if ec_group.is_null() {
289 return Err(to_call_failed_error(ApiName::EC_GROUP_new_by_curve_name));
290 }
291 let mut cbs = Cbs::new(der_encoded_ec_private_key);
292 // SAFETY: The function only reads bytes from the buffer managed by the valid `CBS`
293 // object, and the returned EC_KEY is checked.
294 let ec_key = unsafe { EC_KEY_parse_private_key(cbs.as_mut(), ec_group) };
295
296 let ec_key = NonNull::new(ec_key)
297 .map(Self)
298 .ok_or(to_call_failed_error(ApiName::EC_KEY_parse_private_key))?;
299 ec_key.check_key()?;
300 Ok(ec_key)
301 }
302
Alice Wang7b2ab942023-09-12 13:04:42 +0000303 /// Returns the DER-encoded ECPrivateKey structure described in RFC 5915 Section 3:
304 ///
305 /// https://datatracker.ietf.org/doc/html/rfc5915#section-3
Alice Wang000595b2023-10-02 13:46:45 +0000306 pub fn ec_private_key(&self) -> Result<ZVec> {
Alice Wang7b2ab942023-09-12 13:04:42 +0000307 const CAPACITY: usize = 256;
308 let mut buf = Zeroizing::new([0u8; CAPACITY]);
Alan Stokesb1f64ee2023-09-25 10:38:13 +0100309 let mut cbb = CbbFixed::new(buf.as_mut());
Alice Wang7b2ab942023-09-12 13:04:42 +0000310 let enc_flags = 0;
311 let ret =
312 // SAFETY: The function only write bytes to the buffer managed by the valid `CBB`
313 // object, and the key has been allocated by BoringSSL.
Alan Stokesb1f64ee2023-09-25 10:38:13 +0100314 unsafe { EC_KEY_marshal_private_key(cbb.as_mut(), self.0.as_ptr(), enc_flags) };
Alice Wang7b2ab942023-09-12 13:04:42 +0000315
Alice Wangc8f88f52023-09-25 14:02:17 +0000316 check_int_result(ret, ApiName::EC_KEY_marshal_private_key)?;
Alice Wang7b2ab942023-09-12 13:04:42 +0000317 // SAFETY: This is safe because the CBB pointer is a valid pointer initialized with
318 // `CBB_init_fixed()`.
Alice Wangc8f88f52023-09-25 14:02:17 +0000319 check_int_result(unsafe { CBB_flush(cbb.as_mut()) }, ApiName::CBB_flush)?;
Alice Wang7b2ab942023-09-12 13:04:42 +0000320 // SAFETY: This is safe because the CBB pointer is initialized with `CBB_init_fixed()`,
321 // and it has been flushed, thus it has no active children.
Alan Stokesb1f64ee2023-09-25 10:38:13 +0100322 let len = unsafe { CBB_len(cbb.as_ref()) };
Alice Wang47287e72023-09-29 13:14:33 +0000323 Ok(buf.get(0..len).ok_or(to_call_failed_error(ApiName::CBB_len))?.to_vec().into())
Alice Wang7b2ab942023-09-12 13:04:42 +0000324 }
325}
326
Alice Wang306c8e22023-11-29 12:40:43 +0000327/// Wrapper of an `EC_GROUP` reference.
328struct EcGroup<'a>(&'a EC_GROUP);
329
330impl<'a> EcGroup<'a> {
331 /// Returns the NID that identifies the EC group of the key.
332 fn curve_nid(&self) -> i32 {
333 // SAFETY: It is safe since the inner pointer is valid and points to an initialized
334 // instance of `EC_GROUP`.
335 unsafe { EC_GROUP_get_curve_name(self.as_ref()) }
336 }
337
338 fn coset_curve(&self) -> Result<iana::EllipticCurve> {
339 #[allow(non_upper_case_globals)]
340 match self.curve_nid() {
341 NID_X9_62_prime256v1 => Ok(P256_CURVE),
342 NID_secp384r1 => Ok(P384_CURVE),
343 name => {
344 error!("Unsupported curve NID: {}", name);
345 Err(Error::Unimplemented)
346 }
347 }
348 }
349
350 fn affine_coordinate_size(&self) -> Result<usize> {
351 #[allow(non_upper_case_globals)]
352 match self.curve_nid() {
353 NID_X9_62_prime256v1 => Ok(P256_AFFINE_COORDINATE_SIZE),
354 NID_secp384r1 => Ok(P384_AFFINE_COORDINATE_SIZE),
355 name => {
356 error!("Unsupported curve NID: {}", name);
357 Err(Error::Unimplemented)
358 }
359 }
360 }
361
362 fn check_affine_coordinate_size(&self, coordinate: &[u8]) -> Result<()> {
363 let expected_len = self.affine_coordinate_size()?;
364 if expected_len == coordinate.len() {
365 Ok(())
366 } else {
367 error!(
368 "The size of the affine coordinate '{}' does not match the expected size '{}'",
369 coordinate.len(),
370 expected_len
371 );
372 Err(Error::CoseKeyDecodingFailed)
373 }
374 }
375}
376
377impl<'a> AsRef<EC_GROUP> for EcGroup<'a> {
378 fn as_ref(&self) -> &EC_GROUP {
379 self.0
Alice Wang9bd98092023-11-10 14:08:12 +0000380 }
381}
382
Alice Wang7b2ab942023-09-12 13:04:42 +0000383/// A u8 vector that is zeroed when dropped.
384#[derive(Zeroize, ZeroizeOnDrop)]
385pub struct ZVec(Vec<u8>);
386
387impl ZVec {
388 /// Extracts a slice containing the entire vector.
389 pub fn as_slice(&self) -> &[u8] {
390 &self.0[..]
391 }
392}
393
394impl From<Vec<u8>> for ZVec {
395 fn from(v: Vec<u8>) -> Self {
396 Self(v)
397 }
398}
399
Alice Wanga78d3f02023-09-13 12:39:16 +0000400struct BigNum(NonNull<BIGNUM>);
401
402impl Drop for BigNum {
403 fn drop(&mut self) {
404 // SAFETY: The pointer has been created with `BN_new`.
405 unsafe { BN_clear_free(self.as_mut_ptr()) }
406 }
407}
408
409impl BigNum {
Alice Wang9bd98092023-11-10 14:08:12 +0000410 fn from_slice(x: &[u8]) -> Result<Self> {
411 // SAFETY: The function reads `x` within its bounds, and the returned
412 // pointer is checked below.
413 let bn = unsafe { BN_bin2bn(x.as_ptr(), x.len(), ptr::null_mut()) };
414 NonNull::new(bn).map(Self).ok_or(to_call_failed_error(ApiName::BN_bin2bn))
415 }
416
Alice Wanga78d3f02023-09-13 12:39:16 +0000417 fn new() -> Result<Self> {
418 // SAFETY: The returned pointer is checked below.
419 let bn = unsafe { BN_new() };
Alice Wang47287e72023-09-29 13:14:33 +0000420 NonNull::new(bn).map(Self).ok_or(to_call_failed_error(ApiName::BN_new))
Alice Wanga78d3f02023-09-13 12:39:16 +0000421 }
422
Alice Wang306c8e22023-11-29 12:40:43 +0000423 /// Converts the `BigNum` to a big-endian integer. The integer is padded with leading zeros up
424 /// to size `len`. The conversion fails if `len` is smaller than the size of the integer.
425 fn to_padded_vec(&self, len: usize) -> Result<Vec<u8>> {
426 let mut num = vec![0u8; len];
427 // SAFETY: The `BIGNUM` pointer has been created with `BN_new`.
428 let ret = unsafe { BN_bn2bin_padded(num.as_mut_ptr(), num.len(), self.0.as_ptr()) };
429 check_int_result(ret, ApiName::BN_bn2bin_padded)?;
430 Ok(num)
431 }
432
Alice Wanga78d3f02023-09-13 12:39:16 +0000433 fn as_mut_ptr(&mut self) -> *mut BIGNUM {
434 self.0.as_ptr()
435 }
436}
437
Alice Wang9bd98092023-11-10 14:08:12 +0000438impl AsRef<BIGNUM> for BigNum {
439 fn as_ref(&self) -> &BIGNUM {
440 // SAFETY: The pointer is valid and points to an initialized instance of `BIGNUM`
441 // when the instance was created.
442 unsafe { self.0.as_ref() }
443 }
444}