mundane/boringssl/mod.rs
1// Copyright 2020 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! The BoringSSL API.
6//!
7//! This module provides a safe access to the BoringSSL API.
8//!
9//! It accomplishes this using the following structure:
10//! - The internal `raw` module provides nearly-raw access to the BoringSSL API.
11//! For each function in the BoringSSL API, it exposes an equivalent Rust
12//! function which performs error checking. Functions which return pointers
13//! return `Result<NonNull<T>, BoringError>`, functions which return status
14//! codes return `Result<(), BoringError>`, etc. This API makes it less likely
15//! to accidentally forget to check for null pointers or error status codes.
16//! - The internal `wrapper` module provides types which wrap C objects and
17//! handle many of the details of their lifecycles. These include
18//! `CStackWrapper`, which handles initializing and destructing
19//! stack-allocated C objects; `CHeapWrapper`, which is analogous to Rust's
20//! `Box` or `Rc`, and handles allocation, reference counting, and freeing;
21//! and `CRef`, which is analogous to a Rust reference.
22//! - This module builds on top of the `raw` and `wrapper` modules to provide a
23//! safe API. This allows us to `#![forbid(unsafe_code)]` in the rest of the
24//! crate, which in turn means that this is the only module whose memory
25//! safety needs to be manually verified.
26//!
27//! # Usage
28//!
29//! Each type, `T`, from the BoringSSL API is exposed as either a
30//! `CStackWrapper<T>`, a `CHeapWrapper<T>`, or a `CRef<T>`. Each function from
31//! the BoringSSL API which operates on a particular type is exposed as a method
32//! on the wrapped version of that type. For example, the BoringSSL `CBS_len`
33//! function operates on a `CBS`; we provide the `cbs_len` method on the
34//! `CStackWrapper<CBS>` type. While BoringSSL functions that operate on a
35//! particular type take the form `TYPE_method`, the Rust equivalents are all
36//! lower-case - `type_method`.
37//!
38//! Some functions which do not make sense as methods are exposed as bare
39//! functions. For example, the BoringSSL `ECDSA_sign` function is exposed as a
40//! bare function as `ecdsa_sign`.
41//!
42//! Types which can be constructed without arguments implement `Default`. Types
43//! which require arguments to be constructed provide associated functions which
44//! take those arguments and return a new instance of that type. For example,
45//! the `CHeapWrapper<EC_KEY>::ec_key_parse_private_key` function parses a
46//! private key from an input stream and returns a new `CHeapWrapper<EC_KEY>`.
47//!
48//! # API Guidelines
49//!
50//! This module is meant to be as close as possible to a direct set of FFI
51//! bindings while still providing a safe API. While memory safety is handled
52//! internally, and certain error conditions which could affect memory safety
53//! are checked internally (and cause the process to abort if they fail), most
54//! errors are returned from the API, as they are considered business logic,
55//! which is outside the scope of this module.
56
57// NOTES on safety requirements of the BoringSSL API:
58// - Though it may not be explicitly documented, calling methods on uinitialized
59// values is UB. Remember, this is C! Always initialize (usually via XXX_init
60// or a similarly-named function) before calling any methods or functions.
61// - Any BoringSSL documentation that says "x property must hold" means that, if
62// that property doesn't hold, it may cause UB - you are not guaranteed that
63// it will be detected and an error will be returned.
64// - If a pointer parameter is const, the function does NOT take ownership of
65// the object and does NOT retain a reference to the object (in Rust
66// terminology, the object need only live as long as the function call). If
67// the pointer parameter is not const, it MAY take ownership or hold a
68// reference depending on the documentation. Generally, ownership is only
69// taken if explicitly documented, but documentation bugs may exist, so be
70// careful.
71
72#[macro_use]
73mod abort;
74#[macro_use]
75mod wrapper;
76mod raw;
77
78// C types
79pub use bssl_sys::{
80 BIGNUM, CBB, CBS, EC_GROUP, EC_KEY, EVP_MD, EVP_PKEY, HMAC_CTX, MD5_CTX, RC4_KEY, RSA, RSA_F4,
81 SHA256_CTX, SHA512_CTX, SHA_CTX,
82};
83// C constants
84pub use bssl_sys::{
85 NID_X9_62_prime256v1, NID_md5, NID_secp384r1, NID_secp521r1, NID_sha1, NID_sha256, NID_sha384,
86 NID_sha512, ED25519_PRIVATE_KEY_LEN, ED25519_PUBLIC_KEY_LEN, ED25519_SIGNATURE_LEN,
87 MD5_DIGEST_LENGTH, SHA256_DIGEST_LENGTH, SHA384_DIGEST_LENGTH, SHA512_DIGEST_LENGTH,
88 SHA_DIGEST_LENGTH,
89};
90// wrapper types
91pub use boringssl::wrapper::{CHeapWrapper, CRef, CStackWrapper};
92
93use std::convert::TryInto;
94use std::ffi::CStr;
95use std::fmt::{self, Debug, Display, Formatter};
96use std::mem::MaybeUninit;
97use std::num::NonZeroUsize;
98use std::os::raw::{c_char, c_int, c_uint, c_void};
99use std::{cmp, ptr, slice};
100
101use boringssl::abort::UnwrapAbort;
102use boringssl::raw::{
103 BN_set_u64, CBB_data, CBB_init, CBB_len, CBS_init, CBS_len, CRYPTO_memcmp, ECDSA_sign,
104 ECDSA_size, ECDSA_verify, EC_GROUP_get_curve_name, EC_GROUP_new_by_curve_name,
105 EC_KEY_generate_key, EC_KEY_get0_group, EC_KEY_marshal_private_key, EC_KEY_parse_private_key,
106 EC_KEY_set_group, EC_curve_nid2nist, ED25519_keypair, ED25519_keypair_from_seed, ED25519_sign,
107 ED25519_verify, ERR_print_errors_cb, EVP_PBE_scrypt, EVP_PKEY_assign_EC_KEY,
108 EVP_PKEY_assign_RSA, EVP_PKEY_get1_EC_KEY, EVP_PKEY_get1_RSA, EVP_marshal_public_key,
109 EVP_parse_public_key, HMAC_CTX_copy, HMAC_CTX_init, HMAC_Final, HMAC_Init_ex, HMAC_Update,
110 HMAC_size, RAND_bytes, RC4_set_key, RSA_bits, RSA_generate_key_ex, RSA_marshal_private_key,
111 RSA_parse_private_key, RSA_sign_pss_mgf1, RSA_size, RSA_verify_pss_mgf1, SHA384_Init, RC4,
112};
113#[cfg(feature = "rsa-pkcs1v15")]
114use boringssl::raw::{RSA_sign, RSA_verify};
115
116impl CStackWrapper<BIGNUM> {
117 /// The `BN_set_u64` function.
118 #[must_use]
119 pub fn bn_set_u64(&mut self, value: u64) -> Result<(), BoringError> {
120 unsafe { BN_set_u64(self.as_mut(), value) }
121 }
122}
123
124impl CStackWrapper<CBB> {
125 /// Creates a new `CBB` and initializes it with `CBB_init`.
126 ///
127 /// `cbb_new` can only fail due to OOM.
128 #[must_use]
129 pub fn cbb_new(initial_capacity: usize) -> Result<CStackWrapper<CBB>, BoringError> {
130 unsafe {
131 let mut cbb = MaybeUninit::uninit();
132 CBB_init(cbb.as_mut_ptr(), initial_capacity)?;
133 Ok(CStackWrapper::new(cbb.assume_init()))
134 }
135 }
136
137 /// Invokes a callback on the contents of a `CBB`.
138 ///
139 /// `cbb_with_data` accepts a callback, and invokes that callback, passing a
140 /// slice of the current contents of this `CBB`.
141 #[must_use]
142 pub fn cbb_with_data<O, F: Fn(&[u8]) -> O>(&self, with_data: F) -> O {
143 unsafe {
144 // NOTE: The return value of CBB_data is only valid until the next
145 // operation on the CBB. This method is safe because the slice
146 // reference cannot outlive this function body, and thus cannot live
147 // beyond another method call that could invalidate the buffer.
148 let len = CBB_len(self.as_const());
149 if len == 0 {
150 // If len is 0, then CBB_data could technically return a null
151 // pointer. Constructing a slice from a null pointer is likely
152 // invalid, so we do this instead.
153 with_data(&[])
154 } else {
155 // Since the length is non-zero, CBB_data should not return a
156 // null pointer.
157 let ptr = CBB_data(self.as_const()).unwrap_abort();
158 // TODO(joshlf): Can with_data use this to smuggle out the
159 // reference, outliving the lifetime of self?
160 with_data(slice::from_raw_parts(ptr.as_ptr(), len))
161 }
162 }
163 }
164}
165
166impl CStackWrapper<CBS> {
167 /// The `CBS_len` function.
168 #[must_use]
169 pub fn cbs_len(&self) -> usize {
170 unsafe { CBS_len(self.as_const()) }
171 }
172
173 /// Invokes a callback on a temporary `CBS`.
174 ///
175 /// `cbs_with_temp_buffer` constructs a `CBS` from the provided byte slice,
176 /// and invokes a callback on the `CBS`. The `CBS` is destructed before
177 /// `cbs_with_temp_buffer` returns.
178 // TODO(joshlf): Holdover until we figure out how to put lifetimes in CStackWrappers.
179 #[must_use]
180 pub fn cbs_with_temp_buffer<O, F: Fn(&mut CStackWrapper<CBS>) -> O>(
181 bytes: &[u8],
182 with_cbs: F,
183 ) -> O {
184 unsafe {
185 let mut cbs = MaybeUninit::uninit();
186 CBS_init(cbs.as_mut_ptr(), bytes.as_ptr(), bytes.len());
187 let mut cbs = CStackWrapper::new(cbs.assume_init());
188 with_cbs(&mut cbs)
189 }
190 }
191}
192
193impl CRef<'static, EC_GROUP> {
194 /// The `EC_GROUP_new_by_curve_name` function.
195 #[must_use]
196 pub fn ec_group_new_by_curve_name(nid: c_int) -> Result<CRef<'static, EC_GROUP>, BoringError> {
197 unsafe { Ok(CRef::new(EC_GROUP_new_by_curve_name(nid)?)) }
198 }
199}
200
201impl<'a> CRef<'a, EC_GROUP> {
202 /// The `EC_GROUP_get_curve_name` function.
203 #[must_use]
204 pub fn ec_group_get_curve_name(&self) -> c_int {
205 unsafe { EC_GROUP_get_curve_name(self.as_const()) }
206 }
207}
208
209/// The `EC_curve_nid2nist` function.
210#[must_use]
211pub fn ec_curve_nid2nist(nid: c_int) -> Result<&'static CStr, BoringError> {
212 unsafe { Ok(CStr::from_ptr(EC_curve_nid2nist(nid)?.as_ptr())) }
213}
214
215impl CHeapWrapper<EC_KEY> {
216 /// The `EC_KEY_generate_key` function.
217 #[must_use]
218 pub fn ec_key_generate_key(&mut self) -> Result<(), BoringError> {
219 unsafe { EC_KEY_generate_key(self.as_mut()) }
220 }
221
222 /// The `EC_KEY_parse_private_key` function.
223 ///
224 /// If `group` is `None`, then the group pointer argument to
225 /// `EC_KEY_parse_private_key` will be NULL.
226 #[must_use]
227 pub fn ec_key_parse_private_key(
228 cbs: &mut CStackWrapper<CBS>,
229 group: Option<CRef<'static, EC_GROUP>>,
230 ) -> Result<CHeapWrapper<EC_KEY>, BoringError> {
231 unsafe {
232 Ok(CHeapWrapper::new_from(EC_KEY_parse_private_key(
233 cbs.as_mut(),
234 group.map(|g| g.as_const()).unwrap_or(ptr::null()),
235 )?))
236 }
237 }
238
239 /// The `EC_KEY_get0_group` function.
240 #[must_use]
241 #[allow(clippy::needless_lifetimes)] // to be more explicit
242 pub fn ec_key_get0_group<'a>(&'a self) -> Result<CRef<'a, EC_GROUP>, BoringError> {
243 // get0 doesn't increment the refcount; the lifetimes ensure that the
244 // returned CRef can't outlive self
245 unsafe { Ok(CRef::new(EC_KEY_get0_group(self.as_const())?)) }
246 }
247
248 /// The `EC_KEY_set_group` function.
249 #[must_use]
250 pub fn ec_key_set_group(&mut self, group: &CRef<'static, EC_GROUP>) -> Result<(), BoringError> {
251 unsafe { EC_KEY_set_group(self.as_mut(), group.as_const()) }
252 }
253
254 /// The `EC_KEY_marshal_private_key` function.
255 #[must_use]
256 pub fn ec_key_marshal_private_key(
257 &self,
258 cbb: &mut CStackWrapper<CBB>,
259 ) -> Result<(), BoringError> {
260 unsafe { EC_KEY_marshal_private_key(cbb.as_mut(), self.as_const(), 0) }
261 }
262}
263
264/// The `ECDSA_sign` function.
265///
266/// `ecdsa_sign` returns the number of bytes written to `sig`.
267///
268/// # Aborts
269///
270/// `ecdsa_sign` aborts if `sig` is shorter than the minimum required signature
271/// size given by `ecdsa_size`, or if `key` doesn't have a group set.
272#[must_use]
273pub fn ecdsa_sign(
274 digest: &[u8],
275 sig: &mut [u8],
276 key: &CHeapWrapper<EC_KEY>,
277) -> Result<usize, BoringError> {
278 unsafe {
279 // If we call ECDSA_sign with sig.len() < min_size, it will invoke UB.
280 // ECDSA_size fails if the key doesn't have a group set.
281 let min_size = ecdsa_size(key).unwrap_abort();
282 assert_abort!(sig.len() >= min_size.get());
283
284 let mut sig_len: c_uint = 0;
285 ECDSA_sign(
286 0,
287 digest.as_ptr(),
288 digest.len(),
289 sig.as_mut_ptr(),
290 &mut sig_len,
291 key.as_const(),
292 )?;
293 // ECDSA_sign guarantees that it only needs ECDSA_size bytes for the
294 // signature.
295 let sig_len = sig_len.try_into().unwrap_abort();
296 assert_abort!(sig_len <= min_size.get());
297 Ok(sig_len)
298 }
299}
300
301/// The `ECDSA_verify` function.
302#[must_use]
303pub fn ecdsa_verify(digest: &[u8], sig: &[u8], key: &CHeapWrapper<EC_KEY>) -> bool {
304 unsafe {
305 ECDSA_verify(0, digest.as_ptr(), digest.len(), sig.as_ptr(), sig.len(), key.as_const())
306 }
307}
308
309/// The `ECDSA_size` function.
310#[must_use]
311pub fn ecdsa_size(key: &CHeapWrapper<EC_KEY>) -> Result<NonZeroUsize, BoringError> {
312 unsafe { ECDSA_size(key.as_const()) }
313}
314
315/// The `ED25519_keypair` function.
316#[must_use]
317pub fn ed25519_keypair() -> [u8; ED25519_PRIVATE_KEY_LEN as usize] {
318 let mut public_unused = [0u8; ED25519_PUBLIC_KEY_LEN as usize];
319 let mut private = [0u8; ED25519_PRIVATE_KEY_LEN as usize];
320 unsafe {
321 ED25519_keypair((&mut public_unused[..]).as_mut_ptr(), (&mut private[..]).as_mut_ptr())
322 };
323 private
324}
325
326/// The `ED25519_sign` function.
327#[must_use]
328pub fn ed25519_sign(message: &[u8], private_key: &[u8; 64]) -> Result<[u8; 64], BoringError> {
329 let mut sig = [0u8; 64];
330 unsafe { ED25519_sign(&mut sig, message.as_ptr(), message.len(), private_key)? };
331 Ok(sig)
332}
333
334/// The `ED25519_keypair_from_seed` function.
335#[must_use]
336pub fn ed25519_keypair_from_seed(seed: &[u8; 32]) -> ([u8; 32], [u8; 64]) {
337 let mut public = [0u8; 32];
338 let mut private = [0u8; 64];
339 unsafe {
340 ED25519_keypair_from_seed(
341 (&mut public[..]).as_mut_ptr(),
342 (&mut private[..]).as_mut_ptr(),
343 (&seed[..]).as_ptr(),
344 )
345 };
346 (public, private)
347}
348
349/// The `ED25519_verify` function.
350#[must_use]
351pub fn ed25519_verify(message: &[u8], signature: &[u8; 64], public_key: &[u8; 32]) -> bool {
352 unsafe { ED25519_verify(message.as_ptr(), message.len(), signature, public_key) }
353}
354
355impl CHeapWrapper<EVP_PKEY> {
356 /// The `EVP_parse_public_key` function.
357 #[must_use]
358 pub fn evp_parse_public_key(
359 cbs: &mut CStackWrapper<CBS>,
360 ) -> Result<CHeapWrapper<EVP_PKEY>, BoringError> {
361 unsafe { Ok(CHeapWrapper::new_from(EVP_parse_public_key(cbs.as_mut())?)) }
362 }
363
364 /// The `EVP_marshal_public_key` function.
365 #[must_use]
366 pub fn evp_marshal_public_key(&self, cbb: &mut CStackWrapper<CBB>) -> Result<(), BoringError> {
367 unsafe { EVP_marshal_public_key(cbb.as_mut(), self.as_const()) }
368 }
369
370 /// The `EVP_PKEY_assign_EC_KEY` function.
371 pub fn evp_pkey_assign_ec_key(&mut self, ec_key: CHeapWrapper<EC_KEY>) {
372 unsafe {
373 // NOTE: It's very important that we use 'into_mut' here so that
374 // ec_key's refcount is not decremented. That's because
375 // EVP_PKEY_assign_EC_KEY doesn't increment the refcount of its
376 // argument.
377 let key = ec_key.into_mut();
378 // EVP_PKEY_assign_EC_KEY only fails if key is NULL.
379 EVP_PKEY_assign_EC_KEY(self.as_mut(), key).unwrap_abort()
380 }
381 }
382
383 /// The `EVP_PKEY_assign_RSA` function.
384 pub fn evp_pkey_assign_rsa(&mut self, rsa: CHeapWrapper<RSA>) {
385 unsafe {
386 // NOTE: It's very important that we use 'into_mut' here so that
387 // rsa's refcount is not decremented. That's because
388 // EVP_PKEY_assign_RSA doesn't increment the refcount of its
389 // argument.
390 let key = rsa.into_mut();
391 // EVP_PKEY_assign_RSA only fails if key is NULL.
392 EVP_PKEY_assign_RSA(self.as_mut(), key).unwrap_abort()
393 }
394 }
395
396 /// The `EVP_PKEY_get1_EC_KEY` function.
397 #[must_use]
398 pub fn evp_pkey_get1_ec_key(&mut self) -> Result<CHeapWrapper<EC_KEY>, BoringError> {
399 // NOTE: It's important that we use get1 here, as it increments the
400 // refcount of the EC_KEY before returning a pointer to it.
401 unsafe { Ok(CHeapWrapper::new_from(EVP_PKEY_get1_EC_KEY(self.as_mut())?)) }
402 }
403
404 /// The `EVP_PKEY_get1_RSA` function.
405 #[must_use]
406 pub fn evp_pkey_get1_rsa(&mut self) -> Result<CHeapWrapper<RSA>, BoringError> {
407 // NOTE: It's important that we use get1 here, as it increments the
408 // refcount of the RSA key before returning a pointer to it.
409 unsafe { Ok(CHeapWrapper::new_from(EVP_PKEY_get1_RSA(self.as_mut())?)) }
410 }
411}
412
413/// The `EVP_PBE_scrypt` function.
414#[allow(non_snake_case)]
415#[must_use]
416pub fn evp_pbe_scrypt(
417 password: &[u8],
418 salt: &[u8],
419 N: u64,
420 r: u64,
421 p: u64,
422 max_mem: usize,
423 out_key: &mut [u8],
424) -> Result<(), BoringError> {
425 unsafe {
426 EVP_PBE_scrypt(
427 password.as_ptr() as *const c_char,
428 password.len(),
429 salt.as_ptr(),
430 salt.len(),
431 N,
432 r,
433 p,
434 max_mem,
435 out_key.as_mut_ptr(),
436 out_key.len(),
437 )
438 }
439}
440
441/// The `PKCS5_PBKDF2_HMAC` function.
442#[cfg(feature = "kdf")]
443#[must_use]
444pub fn pkcs5_pbkdf2_hmac(
445 password: &[u8],
446 salt: &[u8],
447 iterations: c_uint,
448 digest: &CRef<'static, EVP_MD>,
449 out_key: &mut [u8],
450) -> Result<(), BoringError> {
451 unsafe {
452 raw::PKCS5_PBKDF2_HMAC(
453 password.as_ptr() as *const c_char,
454 password.len(),
455 salt.as_ptr(),
456 salt.len(),
457 iterations,
458 digest.as_const(),
459 out_key.len(),
460 out_key.as_mut_ptr(),
461 )
462 }
463}
464
465impl CStackWrapper<SHA512_CTX> {
466 /// Initializes a new `CStackWrapper<SHA512_CTX>` as a SHA-384 hash.
467 ///
468 /// The BoringSSL `SHA512_CTX` is used for both the SHA-512 and SHA-384 hash
469 /// functions. The implementation of `Default` for
470 /// `CStackWrapper<SHA512_CTX>` produces a context initialized for a SHA-512
471 /// hash. In order to produce a context for a SHA-384 hash, use this
472 /// constructor instead.
473 #[must_use]
474 pub fn sha384_new() -> CStackWrapper<SHA512_CTX> {
475 unsafe {
476 let mut ctx = MaybeUninit::uninit();
477 SHA384_Init(ctx.as_mut_ptr());
478 CStackWrapper::new(ctx.assume_init())
479 }
480 }
481}
482
483macro_rules! impl_evp_digest {
484 (#[$doc:meta] $name:ident, $raw_name:ident) => {
485 #[$doc]
486 #[must_use]
487 pub fn $name() -> CRef<'static, EVP_MD> {
488 unsafe { CRef::new(::boringssl::raw::$raw_name()) }
489 }
490 };
491}
492
493impl CRef<'static, EVP_MD> {
494 impl_evp_digest!(
495 /// The `EVP_md5` function.
496 evp_md5,
497 EVP_md5
498 );
499 impl_evp_digest!(
500 /// The `EVP_sha1` function.
501 evp_sha1,
502 EVP_sha1
503 );
504 impl_evp_digest!(
505 /// The `EVP_sha256` function.
506 evp_sha256,
507 EVP_sha256
508 );
509 impl_evp_digest!(
510 /// The `EVP_sha384` function.
511 evp_sha384,
512 EVP_sha384
513 );
514 impl_evp_digest!(
515 /// The `EVP_sha512` function.
516 evp_sha512,
517 EVP_sha512
518 );
519}
520
521impl CStackWrapper<HMAC_CTX> {
522 /// Initializes a new `HMAC_CTX`.
523 ///
524 /// `hmac_ctx_new` initializes a new `HMAC_CTX` using `HMAC_CTX_init` and
525 /// then further initializes it with `HMAC_CTX_Init_ex`. It can only fail
526 /// due to OOM.
527 #[must_use]
528 pub fn hmac_ctx_new(
529 key: &[u8],
530 md: &CRef<'static, EVP_MD>,
531 ) -> Result<CStackWrapper<HMAC_CTX>, BoringError> {
532 unsafe {
533 let mut ctx = MaybeUninit::uninit();
534 HMAC_CTX_init(ctx.as_mut_ptr());
535 HMAC_Init_ex(
536 ctx.as_mut_ptr(),
537 key.as_ptr() as *const c_void,
538 key.len(),
539 md.as_const(),
540 )?;
541 Ok(CStackWrapper::new(ctx.assume_init()))
542 }
543 }
544
545 /// The `HMAC_Update` function.
546 pub fn hmac_update(&mut self, data: &[u8]) {
547 unsafe { HMAC_Update(self.as_mut(), data.as_ptr(), data.len()) }
548 }
549
550 // NOTE(joshlf): We require exactly the right length (as opposed to just
551 // long enough) so that we don't have to have hmac_final return a length.
552
553 /// The `HMAC_Final` function.
554 ///
555 /// # Aborts
556 ///
557 /// `hmac_final` aborts if `out` is not exactly the right length (as defined
558 /// by `HMAC_size`).
559 pub fn hmac_final(&mut self, out: &mut [u8]) {
560 unsafe {
561 let hmac_size = HMAC_size(self.as_const());
562 assert_abort_eq!(out.len(), hmac_size);
563 let mut hmac_final_size: u32 = 0;
564 // HMAC_Final is documented to fail on allocation failure, but an
565 // internal comment states that it's infallible. In either case, we
566 // want to panic. Normally, for allocation failure, we'd put the
567 // unwrap higher in the stack, but since this is supposed to be
568 // infallible anyway, we put it here.
569 //
570 // TODO(joshlf): Remove this comment once HMAC_Final is documented
571 // as being infallible.
572 HMAC_Final(self.as_mut(), out.as_mut_ptr(), &mut hmac_final_size).unwrap_abort();
573 // `HMAC_Final` guarantees that it will set its out argument to the
574 // same value returned by `HMAC_size`. If the conversion from `u32`
575 // to `usize` fails, that means that a) we are on a 16-bit platform
576 // and b) that `HMAC_Final` failed to uphold its contract.
577 assert_abort_eq!(
578 hmac_size,
579 hmac_final_size
580 .try_into()
581 .expect("`HMAC_Final` returned size out of range of `usize`")
582 );
583 assert_abort_eq!(out.len(), hmac_size);
584 }
585 }
586
587 /// The `HMAC_CTX_copy` function.
588 pub fn hmac_ctx_copy(&self) -> Result<Self, BoringError> {
589 unsafe {
590 let mut ctx = MaybeUninit::uninit();
591 HMAC_CTX_copy(ctx.as_mut_ptr(), self.as_const())?;
592 Ok(CStackWrapper::new(ctx.assume_init()))
593 }
594 }
595}
596
597impl CStackWrapper<RC4_KEY> {
598 /// The `RC4_set_key` function.
599 ///
600 /// # Aborts
601 ///
602 /// `RC4_set_key` encodes the key length with `u32`, which may differ from
603 /// the target platform's word size (`usize`). This function aborts if the
604 /// length of the `key` slice exceeds `u32::MAX`.
605 pub fn rc4_set_key(key: &[u8]) -> Self {
606 let mut rc4 = RC4_KEY { x: 0, y: 0, data: [0; 256] };
607 unsafe {
608 // `RC4_set_key` reads `key` and writes into `rc4`. It does not take
609 // ownership of `key` and `key` need not live as long as `rc4`.
610 RC4_set_key(&mut rc4, key.len().try_into().unwrap_abort(), key.as_ptr());
611 CStackWrapper::new(rc4)
612 }
613 }
614
615 /// The `RC4` function.
616 pub fn rc4(&mut self, input: &[u8], output: &mut [u8]) {
617 let len = cmp::min(input.len(), output.len());
618 let input = &input[..len];
619 let output = &mut output[..len];
620 unsafe {
621 RC4(self.as_mut(), len, input.as_ptr(), output.as_mut_ptr());
622 }
623 }
624}
625
626impl CHeapWrapper<RSA> {
627 /// The `RSA_bits` function.
628 #[must_use]
629 pub fn rsa_bits(&self) -> c_uint {
630 // RSA_bits does not mutate its argument but, for
631 // backwards-compatibility reasons, continues to take a normal
632 // (non-const) pointer.
633 unsafe { RSA_bits(self.as_const() as *mut _) }
634 }
635
636 /// The `RSA_generate_key_ex` function.
637 #[must_use]
638 pub fn rsa_generate_key_ex(
639 &mut self,
640 bits: c_int,
641 e: &CRef<'_, BIGNUM>,
642 ) -> Result<(), BoringError> {
643 unsafe {
644 // NOTE: It's very important that we use 'into_mut' here so that e's
645 // refcount is not decremented. That's because RSA_generate_key_ex
646 // takes ownership of e, and thus doesn't increment its refcount.
647 RSA_generate_key_ex(self.as_mut(), bits, e.as_const(), ptr::null_mut())
648 }
649 }
650
651 /// The `RSA_marshal_private_key` function.
652 #[must_use]
653 pub fn rsa_marshal_private_key(&self, cbb: &mut CStackWrapper<CBB>) -> Result<(), BoringError> {
654 unsafe { RSA_marshal_private_key(cbb.as_mut(), self.as_const()) }
655 }
656
657 /// The `RSA_parse_private_key` function.
658 #[must_use]
659 pub fn rsa_parse_private_key(
660 cbs: &mut CStackWrapper<CBS>,
661 ) -> Result<CHeapWrapper<RSA>, BoringError> {
662 unsafe { Ok(CHeapWrapper::new_from(RSA_parse_private_key(cbs.as_mut())?)) }
663 }
664
665 /// The `RSA_size` function.
666 #[must_use]
667 pub fn rsa_size(&self) -> Result<NonZeroUsize, BoringError> {
668 unsafe { RSA_size(self.as_const()) }
669 }
670}
671
672/// The `RSA_sign` function.
673///
674/// # Aborts
675///
676/// `rsa_sign` aborts if `sig` is shorter than the minimum required signature
677/// size given by `rsa_size`.
678#[cfg(feature = "rsa-pkcs1v15")]
679pub fn rsa_sign(
680 hash_nid: c_int,
681 digest: &[u8],
682 sig: &mut [u8],
683 key: &CHeapWrapper<RSA>,
684) -> Result<usize, BoringError> {
685 unsafe {
686 // If we call RSA_sign with sig.len() < min_size, it will invoke UB.
687 let min_size = key.rsa_size().unwrap_abort();
688 assert_abort!(sig.len() >= min_size.get());
689
690 let mut sig_len: c_uint = 0;
691 RSA_sign(
692 hash_nid,
693 digest.as_ptr(),
694 digest.len().try_into().unwrap_abort(),
695 sig.as_mut_ptr(),
696 &mut sig_len,
697 // RSA_sign does not mutate its argument but, for
698 // backwards-compatibility reasons, continues to take a normal
699 // (non-const) pointer.
700 key.as_const() as *mut _,
701 )?;
702
703 // RSA_sign guarantees that it only needs RSA_size bytes for the
704 // signature.
705 let sig_len = sig_len.try_into().unwrap_abort();
706 assert_abort!(sig_len <= min_size.get());
707 Ok(sig_len)
708 }
709}
710
711/// The `rsa_sign_pss_mgf1` function.
712#[must_use]
713pub fn rsa_sign_pss_mgf1(
714 key: &CHeapWrapper<RSA>,
715 sig: &mut [u8],
716 digest: &[u8],
717 md: &CRef<'static, EVP_MD>,
718 mgf1_md: Option<&CRef<'static, EVP_MD>>,
719 salt_len: c_int,
720) -> Result<usize, BoringError> {
721 unsafe {
722 let mut sig_len: usize = 0;
723 RSA_sign_pss_mgf1(
724 // RSA_sign_pss_mgf1 does not mutate its argument but, for
725 // backwards-compatibility reasons, continues to take a normal
726 // (non-const) pointer.
727 key.as_const() as *mut _,
728 &mut sig_len,
729 sig.as_mut_ptr(),
730 sig.len(),
731 digest.as_ptr(),
732 digest.len(),
733 md.as_const(),
734 mgf1_md.map(CRef::as_const).unwrap_or(ptr::null()),
735 salt_len,
736 )?;
737
738 // RSA_sign_pss_mgf1 guarantees that it only needs RSA_size bytes for
739 // the signature.
740 let rsa_size = key.rsa_size().unwrap_abort();
741 let sig_len = sig_len;
742 assert_abort!(sig_len <= rsa_size.get());
743 Ok(sig_len)
744 }
745}
746
747/// The `RSA_verify` function.
748#[must_use]
749#[cfg(feature = "rsa-pkcs1v15")]
750pub fn rsa_verify(hash_nid: c_int, digest: &[u8], sig: &[u8], key: &CHeapWrapper<RSA>) -> bool {
751 unsafe {
752 RSA_verify(
753 hash_nid,
754 digest.as_ptr(),
755 digest.len(),
756 sig.as_ptr(),
757 sig.len(),
758 // RSA_verify does not mutate its argument but, for
759 // backwards-compatibility reasons, continues to take a normal
760 // (non-const) pointer.
761 key.as_const() as *mut _,
762 )
763 }
764}
765
766/// The `RSA_verify_pss_mgf1` function.
767#[must_use]
768pub fn rsa_verify_pss_mgf1(
769 key: &CHeapWrapper<RSA>,
770 digest: &[u8],
771 md: &CRef<'static, EVP_MD>,
772 mgf1_md: Option<&CRef<'static, EVP_MD>>,
773 salt_len: c_int,
774 sig: &[u8],
775) -> bool {
776 unsafe {
777 RSA_verify_pss_mgf1(
778 // RSA_verify_pss_mgf1 does not mutate its argument but, for
779 // backwards-compatibility reasons, continues to take a normal
780 // (non-const) pointer.
781 key.as_const() as *mut _,
782 digest.as_ptr(),
783 digest.len(),
784 md.as_const(),
785 mgf1_md.map(CRef::as_const).unwrap_or(ptr::null()),
786 salt_len,
787 sig.as_ptr(),
788 sig.len(),
789 )
790 }
791}
792
793/// Implements `CStackWrapper` for a hash context type.
794///
795/// The caller provides doc comments, a public method name, and a private
796/// function name (from the `raw` module) for an update function and a final
797/// function (e.g., `SHA256_Update` and `SHA256_Final`). Note that, as multiple
798/// impl blocks are allowed for a particular type, the same context type may be
799/// used multiple times. This is useful because both SHA-384 and SHA-512 use the
800/// `SHA512_CTX` context type.
801macro_rules! impl_hash {
802 ($ctx:ident, $digest_len:ident, #[$update_doc:meta] $update:ident, $update_raw:ident, #[$final_doc:meta] $final:ident, $final_raw:ident) => {
803 impl CStackWrapper<$ctx> {
804 #[$update_doc]
805 pub fn $update(&mut self, data: &[u8]) {
806 unsafe {
807 ::boringssl::raw::$update_raw(
808 self.as_mut(),
809 data.as_ptr() as *const c_void,
810 data.len(),
811 )
812 }
813 }
814
815 #[$final_doc]
816 #[must_use]
817 pub fn $final(
818 &mut self,
819 ) -> [u8; ::bssl_sys::$digest_len as usize] {
820 unsafe {
821 let mut md = MaybeUninit::<[u8; ::bssl_sys::$digest_len as usize]>::uninit();
822 // SHA1_Final promises to return 1. SHA256_Final,
823 // SHA384_Final, and SHA512_Final all document that they
824 // only fail due to programmer error. The only input to the
825 // function which could cause this is the context. I suspect
826 // that the error condition is that XXX_Final is called
827 // twice without resetting, but I'm not sure. Until we
828 // figure it out, let's err on the side of caution and abort
829 // here.
830 //
831 // TODO(joshlf): Figure out how XXX_Final can fail.
832 ::boringssl::raw::$final_raw(md.as_mut_ptr() as _, self.as_mut()).unwrap_abort();
833 md.assume_init()
834 }
835 }
836 }
837 };
838 (@doc_string $s:expr) => (#[doc="The `"] #[doc=$s] #[doc="` function."]);
839}
840
841/// Implements `Clone` for a `CStackWrapper<T>`.
842///
843/// Unsound for types without no-op `CDestruct` impls, or which
844/// capture `!Sync` shared state.
845macro_rules! impl_clone {
846 ($ty: ty) => {
847 impl Clone for CStackWrapper<$ty> {
848 fn clone(&self) -> Self {
849 unsafe { CStackWrapper::new(*self.as_const()) }
850 }
851 }
852 };
853}
854
855impl_hash!(
856 MD5_CTX,
857 MD5_DIGEST_LENGTH,
858 /// The `MD5_Update` function.
859 md5_update,
860 MD5_Update,
861 /// The `MD5_Final` function.
862 md5_final,
863 MD5_Final
864);
865impl_clone!(MD5_CTX);
866impl_hash!(
867 SHA_CTX,
868 SHA_DIGEST_LENGTH,
869 /// The `SHA1_Update` function.
870 sha1_update,
871 SHA1_Update,
872 /// The `SHA1_Final` function.
873 sha1_final,
874 SHA1_Final
875);
876impl_clone!(SHA_CTX);
877impl_hash!(
878 SHA256_CTX,
879 SHA256_DIGEST_LENGTH,
880 /// The `SHA256_Update` function.
881 sha256_update,
882 SHA256_Update,
883 /// The `SHA256_Final` function.
884 sha256_final,
885 SHA256_Final
886);
887impl_clone!(SHA256_CTX);
888impl_hash!(
889 SHA512_CTX,
890 SHA384_DIGEST_LENGTH,
891 /// The `SHA384_Update` function.
892 sha384_update,
893 SHA384_Update,
894 /// The `SHA384_Final` function.
895 sha384_final,
896 SHA384_Final
897);
898impl_hash!(
899 SHA512_CTX,
900 SHA512_DIGEST_LENGTH,
901 /// The `SHA512_Update` function.
902 sha512_update,
903 SHA512_Update,
904 /// The `SHA512_Final` function.
905 sha512_final,
906 SHA512_Final
907);
908impl_clone!(SHA512_CTX);
909
910/// The `CRYPTO_memcmp` function.
911///
912/// `crypto_memcmp` first verifies that `a.len() == b.len()` before calling
913/// `CRYPTO_memcmp`.
914#[must_use]
915pub fn crypto_memcmp(a: &[u8], b: &[u8]) -> bool {
916 if a.len() != b.len() {
917 return false;
918 }
919 unsafe { CRYPTO_memcmp(a.as_ptr() as *const c_void, b.as_ptr() as *const c_void, a.len()) == 0 }
920}
921
922/// The `RAND_bytes` function.
923pub fn rand_bytes(buf: &mut [u8]) {
924 unsafe { RAND_bytes(buf.as_mut_ptr(), buf.len()) }
925}
926
927/// An error generated by BoringSSL.
928///
929/// The `Debug` impl prints a stack trace. Each element of the trace corresponds
930/// to a function within BoringSSL which voluntarily pushed itself onto the
931/// stack. In this sense, it is not the same as a normal stack trace. Each
932/// element of the trace is of the form `[thread id]:error:[error code]:[library
933/// name]:OPENSSL_internal:[reason string]:[file]:[line number]:[optional string
934/// data]`.
935///
936/// The `Display` impl prints the first element of the stack trace.
937///
938/// Some BoringSSL functions do not record any error in the error stack. Errors
939/// generated from such functions are printed as `error calling <function name>`
940/// for both `Debug` and `Display` impls.
941pub struct BoringError {
942 stack_trace: Vec<String>,
943}
944
945impl BoringError {
946 /// Consumes the error stack.
947 ///
948 /// `f` is the name of the function that failed. If the error stack is empty
949 /// (some BoringSSL functions do not push errors onto the stack when
950 /// returning errors), the returned `BoringError` will simply note that the
951 /// named function failed; both the `Debug` and `Display` implementations
952 /// will return `error calling f`, where `f` is the value of the `f`
953 /// argument.
954 #[must_use]
955 fn consume_stack(f: &str) -> BoringError {
956 let stack_trace = {
957 let trace = get_error_stack_trace();
958 if trace.is_empty() {
959 vec![format!("error calling {}", f)]
960 } else {
961 trace
962 }
963 };
964 BoringError { stack_trace }
965 }
966
967 /// The number of frames in the stack trace.
968 ///
969 /// Guaranteed to be at least 1.
970 #[must_use]
971 pub fn stack_depth(&self) -> usize {
972 self.stack_trace.len()
973 }
974}
975
976fn get_error_stack_trace() -> Vec<String> {
977 // Credit to agl@google.com for this implementation.
978
979 unsafe extern "C" fn error_callback(s: *const c_char, s_len: usize, ctx: *mut c_void) -> c_int {
980 let stack_trace = ctx as *mut Vec<String>;
981 let s = ::std::slice::from_raw_parts(s as *const u8, s_len - 1);
982 (*stack_trace).push(String::from_utf8_lossy(s).to_string());
983 1
984 }
985
986 let mut stack_trace = Vec::new();
987 unsafe { ERR_print_errors_cb(Some(error_callback), &mut stack_trace as *mut _ as *mut c_void) };
988 stack_trace
989}
990
991impl Display for BoringError {
992 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
993 write!(f, "{}", self.stack_trace[0])
994 }
995}
996
997impl Debug for BoringError {
998 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
999 for elem in &self.stack_trace {
1000 writeln!(f, "{}", elem)?;
1001 }
1002 Ok(())
1003 }
1004}
1005
1006#[cfg(test)]
1007mod tests {
1008 use super::*;
1009 use util::should_fail;
1010
1011 #[test]
1012 fn test_boring_error() {
1013 let _ = CStackWrapper::cbs_with_temp_buffer(&[], |cbs| {
1014 should_fail(
1015 CHeapWrapper::evp_parse_public_key(cbs),
1016 "boringssl::EVP_parse_public_key",
1017 "public key routines:OPENSSL_internal:DECODE_ERROR",
1018 );
1019 });
1020 }
1021}