blob: 0c944cd19071ca4e648aedf01925362bb1548946 [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 Wangbe7a4b12023-12-01 11:53:36 +000020use crate::util::{
21 check_int_result, get_label_value, get_label_value_as_bytes, to_call_failed_error,
22};
Alice Wang0271ee02023-11-15 15:03:42 +000023use alloc::vec;
Alice Wang7b2ab942023-09-12 13:04:42 +000024use alloc::vec::Vec;
Alice Wangb3fcf632023-09-26 08:32:55 +000025use bssl_avf_error::{ApiName, Error, Result};
Alan Stokesb1f64ee2023-09-25 10:38:13 +010026use bssl_ffi::{
Alice Wang0271ee02023-11-15 15:03:42 +000027 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 +000028 ECDSA_verify, EC_GROUP_get_curve_name, EC_GROUP_new_by_curve_name, EC_KEY_check_key,
29 EC_KEY_free, EC_KEY_generate_key, EC_KEY_get0_group, EC_KEY_get0_public_key,
30 EC_KEY_marshal_private_key, EC_KEY_new_by_curve_name, EC_KEY_parse_private_key,
31 EC_KEY_set_public_key_affine_coordinates, EC_POINT_get_affine_coordinates,
32 NID_X9_62_prime256v1, NID_secp384r1, BIGNUM, EC_GROUP, EC_KEY, EC_POINT,
Alan Stokesb1f64ee2023-09-25 10:38:13 +010033};
Alice Wang9bd98092023-11-10 14:08:12 +000034use ciborium::Value;
Alice Wanga78d3f02023-09-13 12:39:16 +000035use core::ptr::{self, NonNull};
Alice Wang9bd98092023-11-10 14:08:12 +000036use coset::{
37 iana::{self, EnumI64},
Alice Wangbe7a4b12023-12-01 11:53:36 +000038 CborSerializable, CoseKey, CoseKeyBuilder, KeyType, Label,
Alice Wang9bd98092023-11-10 14:08:12 +000039};
40use log::error;
Alice Wang7b2ab942023-09-12 13:04:42 +000041use zeroize::{Zeroize, ZeroizeOnDrop, Zeroizing};
42
Alice Wang9bd98092023-11-10 14:08:12 +000043const ES256_ALGO: iana::Algorithm = iana::Algorithm::ES256;
44const P256_CURVE: iana::EllipticCurve = iana::EllipticCurve::P_256;
Alice Wang306c8e22023-11-29 12:40:43 +000045const P384_CURVE: iana::EllipticCurve = iana::EllipticCurve::P_384;
Alice Wanga78d3f02023-09-13 12:39:16 +000046const P256_AFFINE_COORDINATE_SIZE: usize = 32;
Alice Wang306c8e22023-11-29 12:40:43 +000047const P384_AFFINE_COORDINATE_SIZE: usize = 48;
Alice Wang7b2ab942023-09-12 13:04:42 +000048
49/// Wrapper of an `EC_KEY` object, representing a public or private EC key.
Alice Wang600ea5b2023-11-17 15:12:16 +000050pub struct EcKey(pub(crate) NonNull<EC_KEY>);
Alice Wang7b2ab942023-09-12 13:04:42 +000051
52impl Drop for EcKey {
53 fn drop(&mut self) {
54 // SAFETY: It is safe because the key has been allocated by BoringSSL and isn't
55 // used after this.
56 unsafe { EC_KEY_free(self.0.as_ptr()) }
57 }
58}
59
60impl EcKey {
61 /// Creates a new EC P-256 key pair.
62 pub fn new_p256() -> Result<Self> {
63 // SAFETY: The returned pointer is checked below.
Alan Stokesb1f64ee2023-09-25 10:38:13 +010064 let ec_key = unsafe {
65 EC_KEY_new_by_curve_name(NID_X9_62_prime256v1) // EC P-256 CURVE Nid
66 };
Alice Wang9bd98092023-11-10 14:08:12 +000067 NonNull::new(ec_key)
Alice Wangc8f88f52023-09-25 14:02:17 +000068 .map(Self)
Alice Wang9bd98092023-11-10 14:08:12 +000069 .ok_or(to_call_failed_error(ApiName::EC_KEY_new_by_curve_name))
70 }
71
Alice Wang306c8e22023-11-29 12:40:43 +000072 /// Creates a new EC P-384 key pair.
73 pub fn new_p384() -> Result<Self> {
74 // SAFETY: The returned pointer is checked below.
75 let ec_key = unsafe {
76 EC_KEY_new_by_curve_name(NID_secp384r1) // EC P-384 CURVE Nid
77 };
78 NonNull::new(ec_key)
79 .map(Self)
80 .ok_or(to_call_failed_error(ApiName::EC_KEY_new_by_curve_name))
81 }
82
Alice Wang9bd98092023-11-10 14:08:12 +000083 /// Constructs an `EcKey` instance from the provided COSE_Key encoded public key slice.
Alice Wangbe7a4b12023-12-01 11:53:36 +000084 pub fn from_cose_public_key_slice(cose_key: &[u8]) -> Result<Self> {
Alice Wang9bd98092023-11-10 14:08:12 +000085 let cose_key = CoseKey::from_slice(cose_key).map_err(|e| {
86 error!("Failed to deserialize COSE_Key: {e:?}");
87 Error::CoseKeyDecodingFailed
88 })?;
Alice Wangbe7a4b12023-12-01 11:53:36 +000089 Self::from_cose_public_key(&cose_key)
90 }
91
92 /// Constructs an `EcKey` instance from the provided `COSE_Key`.
93 ///
94 /// The lifetime of the returned `EcKey` is not tied to the lifetime of the `cose_key`,
95 /// because the affine coordinates stored in the `cose_key` are copied into the `EcKey`.
96 ///
97 /// Currently, only the EC P-256 and P-384 curves are supported.
98 pub fn from_cose_public_key(cose_key: &CoseKey) -> Result<Self> {
99 if cose_key.kty != KeyType::Assigned(iana::KeyType::EC2) {
100 error!("Only EC2 keys are supported. Key type in the COSE Key: {:?}", cose_key.kty);
101 return Err(Error::Unimplemented);
102 }
Alice Wang306c8e22023-11-29 12:40:43 +0000103 let ec_key =
Alice Wangbe7a4b12023-12-01 11:53:36 +0000104 match get_label_value(cose_key, Label::Int(iana::Ec2KeyParameter::Crv.to_i64()))? {
Alice Wang306c8e22023-11-29 12:40:43 +0000105 crv if crv == &Value::from(P256_CURVE.to_i64()) => EcKey::new_p256()?,
106 crv if crv == &Value::from(P384_CURVE.to_i64()) => EcKey::new_p384()?,
107 crv => {
108 error!(
109 "Only EC P-256 and P-384 curves are supported. \
110 Curve type in the COSE Key: {crv:?}"
111 );
112 return Err(Error::Unimplemented);
113 }
114 };
Alice Wangbe7a4b12023-12-01 11:53:36 +0000115 let x = get_label_value_as_bytes(cose_key, Label::Int(iana::Ec2KeyParameter::X.to_i64()))?;
116 let y = get_label_value_as_bytes(cose_key, Label::Int(iana::Ec2KeyParameter::Y.to_i64()))?;
Alice Wang9bd98092023-11-10 14:08:12 +0000117
Alice Wang306c8e22023-11-29 12:40:43 +0000118 let group = ec_key.ec_group()?;
119 group.check_affine_coordinate_size(x)?;
120 group.check_affine_coordinate_size(y)?;
Alice Wang9bd98092023-11-10 14:08:12 +0000121
122 let x = BigNum::from_slice(x)?;
123 let y = BigNum::from_slice(y)?;
124
Alice Wang9bd98092023-11-10 14:08:12 +0000125 // SAFETY: All the parameters are checked non-null and initialized.
126 // The function only reads the coordinates x and y within their bounds.
127 let ret = unsafe {
128 EC_KEY_set_public_key_affine_coordinates(ec_key.0.as_ptr(), x.as_ref(), y.as_ref())
129 };
130 check_int_result(ret, ApiName::EC_KEY_set_public_key_affine_coordinates)?;
Alice Wangf061e472023-11-21 08:17:16 +0000131 ec_key.check_key()?;
Alice Wang7b2ab942023-09-12 13:04:42 +0000132 Ok(ec_key)
133 }
134
Alice Wang000595b2023-10-02 13:46:45 +0000135 /// Performs several checks on the key. See BoringSSL doc for more details:
136 ///
137 /// https://commondatastorage.googleapis.com/chromium-boringssl-docs/ec_key.h.html#EC_KEY_check_key
138 pub fn check_key(&self) -> Result<()> {
139 // SAFETY: This function only reads the `EC_KEY` pointer, the non-null check is performed
140 // within the function.
141 let ret = unsafe { EC_KEY_check_key(self.0.as_ptr()) };
142 check_int_result(ret, ApiName::EC_KEY_check_key)
143 }
144
Alice Wang0271ee02023-11-15 15:03:42 +0000145 /// Verifies the DER-encoded ECDSA `signature` of the `digest` with the current `EcKey`.
146 ///
147 /// Returns Ok(()) if the verification succeeds, otherwise an error will be returned.
148 pub fn ecdsa_verify(&self, signature: &[u8], digest: &[u8]) -> Result<()> {
149 // The `type` argument should be 0 as required in the BoringSSL spec.
150 const TYPE: i32 = 0;
151
152 // SAFETY: This function only reads the given data within its bounds.
153 // The `EC_KEY` passed to this function has been initialized and checked non-null.
154 let ret = unsafe {
155 ECDSA_verify(
156 TYPE,
157 digest.as_ptr(),
158 digest.len(),
159 signature.as_ptr(),
160 signature.len(),
161 self.0.as_ptr(),
162 )
163 };
164 check_int_result(ret, ApiName::ECDSA_verify)
Alice Wang9bd98092023-11-10 14:08:12 +0000165 }
166
Alice Wang0271ee02023-11-15 15:03:42 +0000167 /// Signs the `digest` with the current `EcKey` using ECDSA.
Alice Wang9bd98092023-11-10 14:08:12 +0000168 ///
169 /// Returns the DER-encoded ECDSA signature.
Alice Wang0271ee02023-11-15 15:03:42 +0000170 pub fn ecdsa_sign(&self, digest: &[u8]) -> Result<Vec<u8>> {
171 // The `type` argument should be 0 as required in the BoringSSL spec.
172 const TYPE: i32 = 0;
173
174 let mut signature = vec![0u8; self.ecdsa_size()?];
175 let mut signature_len = 0;
176 // SAFETY: This function only reads the given data within its bounds.
177 // The `EC_KEY` passed to this function has been initialized and checked non-null.
178 let ret = unsafe {
179 ECDSA_sign(
180 TYPE,
181 digest.as_ptr(),
182 digest.len(),
183 signature.as_mut_ptr(),
184 &mut signature_len,
185 self.0.as_ptr(),
186 )
187 };
188 check_int_result(ret, ApiName::ECDSA_sign)?;
189 if signature.len() < (signature_len as usize) {
190 Err(to_call_failed_error(ApiName::ECDSA_sign))
191 } else {
192 signature.truncate(signature_len as usize);
193 Ok(signature)
194 }
195 }
196
197 /// Returns the maximum size of an ECDSA signature using the current `EcKey`.
198 fn ecdsa_size(&self) -> Result<usize> {
199 // SAFETY: This function only reads the `EC_KEY` that has been initialized
200 // and checked non-null when this instance is created.
201 let size = unsafe { ECDSA_size(self.0.as_ptr()) };
202 if size == 0 {
203 Err(to_call_failed_error(ApiName::ECDSA_size))
204 } else {
205 Ok(size)
206 }
Alice Wang9bd98092023-11-10 14:08:12 +0000207 }
208
Alice Wang7b2ab942023-09-12 13:04:42 +0000209 /// Generates a random, private key, calculates the corresponding public key and stores both
210 /// in the `EC_KEY`.
Alice Wang9bd98092023-11-10 14:08:12 +0000211 pub fn generate_key(&mut self) -> Result<()> {
Alice Wang7b2ab942023-09-12 13:04:42 +0000212 // SAFETY: The non-null pointer is created with `EC_KEY_new_by_curve_name` and should
213 // point to a valid `EC_KEY`.
214 // The randomness is provided by `getentropy()` in `vmbase`.
215 let ret = unsafe { EC_KEY_generate_key(self.0.as_ptr()) };
Alice Wangc8f88f52023-09-25 14:02:17 +0000216 check_int_result(ret, ApiName::EC_KEY_generate_key)
Alice Wang7b2ab942023-09-12 13:04:42 +0000217 }
218
Alice Wanga78d3f02023-09-13 12:39:16 +0000219 /// Returns the `CoseKey` for the public key.
220 pub fn cose_public_key(&self) -> Result<CoseKey> {
Alice Wanga78d3f02023-09-13 12:39:16 +0000221 let (x, y) = self.public_key_coordinates()?;
Alice Wang306c8e22023-11-29 12:40:43 +0000222 let curve = self.ec_group()?.coset_curve()?;
223 let key = CoseKeyBuilder::new_ec2_pub_key(curve, x, y).algorithm(ES256_ALGO).build();
Alice Wanga78d3f02023-09-13 12:39:16 +0000224 Ok(key)
225 }
226
227 /// Returns the x and y coordinates of the public key.
Alice Wang306c8e22023-11-29 12:40:43 +0000228 fn public_key_coordinates(&self) -> Result<(Vec<u8>, Vec<u8>)> {
Alice Wanga78d3f02023-09-13 12:39:16 +0000229 let ec_group = self.ec_group()?;
230 let ec_point = self.public_key_ec_point()?;
231 let mut x = BigNum::new()?;
232 let mut y = BigNum::new()?;
233 let ctx = ptr::null_mut();
234 // SAFETY: All the parameters are checked non-null and initialized when needed.
235 // The last parameter `ctx` is generated when needed inside the function.
236 let ret = unsafe {
Alice Wang306c8e22023-11-29 12:40:43 +0000237 EC_POINT_get_affine_coordinates(
238 ec_group.as_ref(),
239 ec_point,
240 x.as_mut_ptr(),
241 y.as_mut_ptr(),
242 ctx,
243 )
Alice Wanga78d3f02023-09-13 12:39:16 +0000244 };
Alice Wangc8f88f52023-09-25 14:02:17 +0000245 check_int_result(ret, ApiName::EC_POINT_get_affine_coordinates)?;
Alice Wang306c8e22023-11-29 12:40:43 +0000246 let len = ec_group.affine_coordinate_size()?;
247 Ok((x.to_padded_vec(len)?, y.to_padded_vec(len)?))
Alice Wanga78d3f02023-09-13 12:39:16 +0000248 }
249
250 /// Returns a pointer to the public key point inside `EC_KEY`. The memory region pointed
251 /// by the pointer is owned by the `EC_KEY`.
252 fn public_key_ec_point(&self) -> Result<*const EC_POINT> {
253 let ec_point =
254 // SAFETY: It is safe since the key pair has been generated and stored in the
255 // `EC_KEY` pointer.
256 unsafe { EC_KEY_get0_public_key(self.0.as_ptr()) };
257 if ec_point.is_null() {
Alice Wang47287e72023-09-29 13:14:33 +0000258 Err(to_call_failed_error(ApiName::EC_KEY_get0_public_key))
Alice Wanga78d3f02023-09-13 12:39:16 +0000259 } else {
260 Ok(ec_point)
261 }
262 }
263
264 /// Returns a pointer to the `EC_GROUP` object inside `EC_KEY`. The memory region pointed
265 /// by the pointer is owned by the `EC_KEY`.
Alice Wang306c8e22023-11-29 12:40:43 +0000266 fn ec_group(&self) -> Result<EcGroup<'_>> {
Alice Wanga78d3f02023-09-13 12:39:16 +0000267 let group =
268 // SAFETY: It is safe since the key pair has been generated and stored in the
269 // `EC_KEY` pointer.
270 unsafe { EC_KEY_get0_group(self.0.as_ptr()) };
271 if group.is_null() {
Alice Wang47287e72023-09-29 13:14:33 +0000272 Err(to_call_failed_error(ApiName::EC_KEY_get0_group))
Alice Wanga78d3f02023-09-13 12:39:16 +0000273 } else {
Alice Wang306c8e22023-11-29 12:40:43 +0000274 // SAFETY: The pointer should be valid and points to an initialized `EC_GROUP`
275 // since it is read from a valid `EC_KEY`.
276 Ok(EcGroup(unsafe { &*group }))
Alice Wanga78d3f02023-09-13 12:39:16 +0000277 }
278 }
Alice Wang7b2ab942023-09-12 13:04:42 +0000279
Alice Wang000595b2023-10-02 13:46:45 +0000280 /// Constructs an `EcKey` instance from the provided DER-encoded ECPrivateKey slice.
281 ///
282 /// Currently, only the EC P-256 curve is supported.
283 pub fn from_ec_private_key(der_encoded_ec_private_key: &[u8]) -> Result<Self> {
284 // SAFETY: This function only returns a pointer to a static object, and the
285 // return is checked below.
286 let ec_group = unsafe {
287 EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1) // EC P-256 CURVE Nid
288 };
289 if ec_group.is_null() {
290 return Err(to_call_failed_error(ApiName::EC_GROUP_new_by_curve_name));
291 }
292 let mut cbs = Cbs::new(der_encoded_ec_private_key);
293 // SAFETY: The function only reads bytes from the buffer managed by the valid `CBS`
294 // object, and the returned EC_KEY is checked.
295 let ec_key = unsafe { EC_KEY_parse_private_key(cbs.as_mut(), ec_group) };
296
297 let ec_key = NonNull::new(ec_key)
298 .map(Self)
299 .ok_or(to_call_failed_error(ApiName::EC_KEY_parse_private_key))?;
300 ec_key.check_key()?;
301 Ok(ec_key)
302 }
303
Alice Wang7b2ab942023-09-12 13:04:42 +0000304 /// Returns the DER-encoded ECPrivateKey structure described in RFC 5915 Section 3:
305 ///
306 /// https://datatracker.ietf.org/doc/html/rfc5915#section-3
Alice Wang000595b2023-10-02 13:46:45 +0000307 pub fn ec_private_key(&self) -> Result<ZVec> {
Alice Wang7b2ab942023-09-12 13:04:42 +0000308 const CAPACITY: usize = 256;
309 let mut buf = Zeroizing::new([0u8; CAPACITY]);
Alan Stokesb1f64ee2023-09-25 10:38:13 +0100310 let mut cbb = CbbFixed::new(buf.as_mut());
Alice Wang7b2ab942023-09-12 13:04:42 +0000311 let enc_flags = 0;
312 let ret =
313 // SAFETY: The function only write bytes to the buffer managed by the valid `CBB`
314 // object, and the key has been allocated by BoringSSL.
Alan Stokesb1f64ee2023-09-25 10:38:13 +0100315 unsafe { EC_KEY_marshal_private_key(cbb.as_mut(), self.0.as_ptr(), enc_flags) };
Alice Wang7b2ab942023-09-12 13:04:42 +0000316
Alice Wangc8f88f52023-09-25 14:02:17 +0000317 check_int_result(ret, ApiName::EC_KEY_marshal_private_key)?;
Alice Wang7b2ab942023-09-12 13:04:42 +0000318 // SAFETY: This is safe because the CBB pointer is a valid pointer initialized with
319 // `CBB_init_fixed()`.
Alice Wangc8f88f52023-09-25 14:02:17 +0000320 check_int_result(unsafe { CBB_flush(cbb.as_mut()) }, ApiName::CBB_flush)?;
Alice Wang7b2ab942023-09-12 13:04:42 +0000321 // SAFETY: This is safe because the CBB pointer is initialized with `CBB_init_fixed()`,
322 // and it has been flushed, thus it has no active children.
Alan Stokesb1f64ee2023-09-25 10:38:13 +0100323 let len = unsafe { CBB_len(cbb.as_ref()) };
Alice Wang47287e72023-09-29 13:14:33 +0000324 Ok(buf.get(0..len).ok_or(to_call_failed_error(ApiName::CBB_len))?.to_vec().into())
Alice Wang7b2ab942023-09-12 13:04:42 +0000325 }
326}
327
Alice Wang306c8e22023-11-29 12:40:43 +0000328/// Wrapper of an `EC_GROUP` reference.
329struct EcGroup<'a>(&'a EC_GROUP);
330
331impl<'a> EcGroup<'a> {
332 /// Returns the NID that identifies the EC group of the key.
333 fn curve_nid(&self) -> i32 {
334 // SAFETY: It is safe since the inner pointer is valid and points to an initialized
335 // instance of `EC_GROUP`.
336 unsafe { EC_GROUP_get_curve_name(self.as_ref()) }
337 }
338
339 fn coset_curve(&self) -> Result<iana::EllipticCurve> {
340 #[allow(non_upper_case_globals)]
341 match self.curve_nid() {
342 NID_X9_62_prime256v1 => Ok(P256_CURVE),
343 NID_secp384r1 => Ok(P384_CURVE),
344 name => {
345 error!("Unsupported curve NID: {}", name);
346 Err(Error::Unimplemented)
347 }
348 }
349 }
350
351 fn affine_coordinate_size(&self) -> Result<usize> {
352 #[allow(non_upper_case_globals)]
353 match self.curve_nid() {
354 NID_X9_62_prime256v1 => Ok(P256_AFFINE_COORDINATE_SIZE),
355 NID_secp384r1 => Ok(P384_AFFINE_COORDINATE_SIZE),
356 name => {
357 error!("Unsupported curve NID: {}", name);
358 Err(Error::Unimplemented)
359 }
360 }
361 }
362
363 fn check_affine_coordinate_size(&self, coordinate: &[u8]) -> Result<()> {
364 let expected_len = self.affine_coordinate_size()?;
365 if expected_len == coordinate.len() {
366 Ok(())
367 } else {
368 error!(
369 "The size of the affine coordinate '{}' does not match the expected size '{}'",
370 coordinate.len(),
371 expected_len
372 );
373 Err(Error::CoseKeyDecodingFailed)
374 }
375 }
376}
377
378impl<'a> AsRef<EC_GROUP> for EcGroup<'a> {
379 fn as_ref(&self) -> &EC_GROUP {
380 self.0
Alice Wang9bd98092023-11-10 14:08:12 +0000381 }
382}
383
Alice Wang7b2ab942023-09-12 13:04:42 +0000384/// A u8 vector that is zeroed when dropped.
385#[derive(Zeroize, ZeroizeOnDrop)]
386pub struct ZVec(Vec<u8>);
387
388impl ZVec {
389 /// Extracts a slice containing the entire vector.
390 pub fn as_slice(&self) -> &[u8] {
391 &self.0[..]
392 }
393}
394
395impl From<Vec<u8>> for ZVec {
396 fn from(v: Vec<u8>) -> Self {
397 Self(v)
398 }
399}
400
Alice Wanga78d3f02023-09-13 12:39:16 +0000401struct BigNum(NonNull<BIGNUM>);
402
403impl Drop for BigNum {
404 fn drop(&mut self) {
405 // SAFETY: The pointer has been created with `BN_new`.
406 unsafe { BN_clear_free(self.as_mut_ptr()) }
407 }
408}
409
410impl BigNum {
Alice Wang9bd98092023-11-10 14:08:12 +0000411 fn from_slice(x: &[u8]) -> Result<Self> {
412 // SAFETY: The function reads `x` within its bounds, and the returned
413 // pointer is checked below.
414 let bn = unsafe { BN_bin2bn(x.as_ptr(), x.len(), ptr::null_mut()) };
415 NonNull::new(bn).map(Self).ok_or(to_call_failed_error(ApiName::BN_bin2bn))
416 }
417
Alice Wanga78d3f02023-09-13 12:39:16 +0000418 fn new() -> Result<Self> {
419 // SAFETY: The returned pointer is checked below.
420 let bn = unsafe { BN_new() };
Alice Wang47287e72023-09-29 13:14:33 +0000421 NonNull::new(bn).map(Self).ok_or(to_call_failed_error(ApiName::BN_new))
Alice Wanga78d3f02023-09-13 12:39:16 +0000422 }
423
Alice Wang306c8e22023-11-29 12:40:43 +0000424 /// Converts the `BigNum` to a big-endian integer. The integer is padded with leading zeros up
425 /// to size `len`. The conversion fails if `len` is smaller than the size of the integer.
426 fn to_padded_vec(&self, len: usize) -> Result<Vec<u8>> {
427 let mut num = vec![0u8; len];
428 // SAFETY: The `BIGNUM` pointer has been created with `BN_new`.
429 let ret = unsafe { BN_bn2bin_padded(num.as_mut_ptr(), num.len(), self.0.as_ptr()) };
430 check_int_result(ret, ApiName::BN_bn2bin_padded)?;
431 Ok(num)
432 }
433
Alice Wanga78d3f02023-09-13 12:39:16 +0000434 fn as_mut_ptr(&mut self) -> *mut BIGNUM {
435 self.0.as_ptr()
436 }
437}
438
Alice Wang9bd98092023-11-10 14:08:12 +0000439impl AsRef<BIGNUM> for BigNum {
440 fn as_ref(&self) -> &BIGNUM {
441 // SAFETY: The pointer is valid and points to an initialized instance of `BIGNUM`
442 // when the instance was created.
443 unsafe { self.0.as_ref() }
444 }
445}