From d34f540e57394de22a1599c3c5d852519d388d6c Mon Sep 17 00:00:00 2001 From: Cindy Lin Date: Tue, 7 May 2024 23:31:40 -0700 Subject: [PATCH 1/2] Add HPKE secret export and implement Send for EvpHpkeCtx. Change-Id: I929b31f996c8b67b77286fe9f8eb1af73d2bbc72 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/68307 Commit-Queue: Adam Langley Reviewed-by: Adam Langley --- rust/bssl-crypto/src/hpke.rs | 88 ++++++++++++++++++++++++++++++++++ rust/bssl-crypto/src/scoped.rs | 3 ++ 2 files changed, 91 insertions(+) diff --git a/rust/bssl-crypto/src/hpke.rs b/rust/bssl-crypto/src/hpke.rs index 2725b3f34..e3a61bc63 100644 --- a/rust/bssl-crypto/src/hpke.rs +++ b/rust/bssl-crypto/src/hpke.rs @@ -65,6 +65,12 @@ //! //! let received_plaintext2 = recipient_ctx.open(&msg2, aad); //! assert!(received_plaintext2.is_none()); +//! +//! // There is also an interface for exporting secrets from both sender +//! // and recipient contexts. +//! let sender_export = sender_ctx.export(b"ctx", 32); +//! let recipient_export = recipient_ctx.export(b"ctx", 32); +//! assert_eq!(sender_export, recipient_export); //! ``` use crate::{scoped, with_output_vec, with_output_vec_fallible, FfiSlice}; @@ -294,6 +300,28 @@ impl SenderContext { }) } } + + /// Exports a secret of length `out_len` from the HPKE context using `context` as the context + /// string. + pub fn export(&mut self, context: &[u8], out_len: usize) -> Vec { + unsafe { + with_output_vec(out_len, |out_buf| { + // Safety: EVP_HPKE_CTX_export + // - is called with context created from EVP_HPKE_CTX_new, + // - is called with valid buffers with corresponding pointer and length, and + // - returns 0 on error, which only occurs when OOM. + let ret = bssl_sys::EVP_HPKE_CTX_export( + self.0.as_mut_ffi_ptr(), + out_buf, + out_len, + context.as_ffi_ptr(), + context.len(), + ); + assert_eq!(ret, 1); + out_len + }) + } + } } /// HPKE recipient context. Callers may use `open()` to decrypt messages from the sender. @@ -385,6 +413,28 @@ impl RecipientContext { }) } } + + /// Exports a secret of length `out_len` from the HPKE context using `context` as the context + /// string. + pub fn export(&mut self, context: &[u8], out_len: usize) -> Vec { + unsafe { + with_output_vec(out_len, |out_buf| { + // Safety: EVP_HPKE_CTX_export + // - is called with context created from EVP_HPKE_CTX_new, + // - is called with valid buffers with corresponding pointer and length, and + // - returns 0 on error, which only occurs when OOM. + let ret = bssl_sys::EVP_HPKE_CTX_export( + self.0.as_mut_ffi_ptr(), + out_buf, + out_len, + context.as_ffi_ptr(), + context.len(), + ); + assert_eq!(ret, 1); + out_len + }) + } + } } #[cfg(test)] @@ -404,6 +454,8 @@ mod test { plaintext: [u8; 29], // pt associated_data: [u8; 7], // aad ciphertext: [u8; 45], // ct + exporter_context: [u8; 11], + exported_value: [u8; 32], } // https://www.rfc-editor.org/rfc/rfc9180.html#appendix-A.1 @@ -420,6 +472,8 @@ mod test { plaintext: decode_hex("4265617574792069732074727574682c20747275746820626561757479"), associated_data: decode_hex("436f756e742d30"), ciphertext: decode_hex("f938558b5d72f1a23810b4be2ab4f84331acc02fc97babc53a52ae8218a355a96d8770ac83d07bea87e13c512a"), + exporter_context: decode_hex("54657374436f6e74657874"), + exported_value: decode_hex("e9e43065102c3836401bed8c3c3c75ae46be1639869391d62c61f1ec7af54931"), } } @@ -437,6 +491,8 @@ mod test { plaintext: decode_hex("4265617574792069732074727574682c20747275746820626561757479"), associated_data: decode_hex("436f756e742d30"), ciphertext: decode_hex("1c5250d8034ec2b784ba2cfd69dbdb8af406cfe3ff938e131f0def8c8b60b4db21993c62ce81883d2dd1b51a28"), + exporter_context: decode_hex("54657374436f6e74657874"), + exported_value: decode_hex("5acb09211139c43b3090489a9da433e8a30ee7188ba8b0a9a1ccf0c229283e53"), } } @@ -562,6 +618,38 @@ mod test { } } + #[test] + fn export_with_vector() { + for test in vec![ + x25519_hkdf_sha256_hkdf_sha256_aes_128_gcm(), + x25519_hkdf_sha256_hkdf_sha256_chacha20_poly1305(), + ] { + let params = Params::new_from_rfc_ids(test.kem_id, test.kdf_id, test.aead_id).unwrap(); + + let (mut sender_ctx, _encapsulated_key) = new_sender_context_for_testing( + ¶ms, + &test.recipient_pub_key, + &test.info, + &test.seed_for_testing, + ); + assert_eq!( + test.exported_value.as_ref(), + sender_ctx.export(&test.exporter_context, test.exported_value.len()) + ); + + let mut recipient_ctx = RecipientContext::new( + ¶ms, + &test.recipient_priv_key, + &test.encapsulated_key, + &test.info, + ).unwrap(); + assert_eq!( + test.exported_value.as_ref(), + recipient_ctx.export(&test.exporter_context, test.exported_value.len()) + ); + } + } + #[test] fn disallowed_params_fail() { let vec: TestVector = x25519_hkdf_sha256_hkdf_sha256_aes_128_gcm(); diff --git a/rust/bssl-crypto/src/scoped.rs b/rust/bssl-crypto/src/scoped.rs index 8c6b21b56..67bf30106 100644 --- a/rust/bssl-crypto/src/scoped.rs +++ b/rust/bssl-crypto/src/scoped.rs @@ -69,6 +69,9 @@ impl Drop for EcKey { /// A scoped `EVP_HPKE_CTX`. pub struct EvpHpkeCtx(*mut bssl_sys::EVP_HPKE_CTX); +// bssl_sys::EVP_HPKE_CTX is heap-allocated and safe to transfer +// between threads. +unsafe impl Send for EvpHpkeCtx {} impl EvpHpkeCtx { pub fn new() -> Self { From 4d50a595b49a2e7b7017060a4d402c4ee9fe28a2 Mon Sep 17 00:00:00 2001 From: Ellen Arteca Date: Wed, 8 May 2024 22:15:14 +0000 Subject: [PATCH 2/2] Add re-exports for making inline functions available This CL adds a re-export for `CBS_init` and `CBS_len`, since these are declared as `OPENSSL_INLINE` and are thus unavailable currently since inline support is not yet merged. It also changes the existing wrappers for inline functions to re-exports too. Note: this is required to land the boringssl update in AOSP. Test: m checkbuild Change-Id: Ic6e2927d7a79b788a4ed0380cf27b3557b6f6f64 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/68327 Reviewed-by: David Benjamin Reviewed-by: Matthew Maurer Commit-Queue: Ellen Arteca Commit-Queue: David Benjamin --- rust/bssl-sys/rust_wrapper.c | 8 ++++++++ rust/bssl-sys/rust_wrapper.h | 4 +++- rust/bssl-sys/src/lib.rs | 21 +++++---------------- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/rust/bssl-sys/rust_wrapper.c b/rust/bssl-sys/rust_wrapper.c index d5419a9a6..d77bc34f3 100644 --- a/rust/bssl-sys/rust_wrapper.c +++ b/rust/bssl-sys/rust_wrapper.c @@ -26,3 +26,11 @@ int ERR_GET_REASON_RUST(uint32_t packed_error) { int ERR_GET_FUNC_RUST(uint32_t packed_error) { return ERR_GET_FUNC(packed_error); } + +void CBS_init_RUST(CBS *cbs, const uint8_t *data, size_t len) { + CBS_init(cbs, data, len); +} + +size_t CBS_len_RUST(const CBS *cbs) { + return CBS_len(cbs); +} diff --git a/rust/bssl-sys/rust_wrapper.h b/rust/bssl-sys/rust_wrapper.h index 55d5a6f25..060bf7e73 100644 --- a/rust/bssl-sys/rust_wrapper.h +++ b/rust/bssl-sys/rust_wrapper.h @@ -16,6 +16,7 @@ #define OPENSSL_HEADER_RUST_WRAPPER_H #include +#include #if defined(__cplusplus) extern "C" { @@ -30,7 +31,8 @@ extern "C" { int ERR_GET_LIB_RUST(uint32_t packed_error); int ERR_GET_REASON_RUST(uint32_t packed_error); int ERR_GET_FUNC_RUST(uint32_t packed_error); - +void CBS_init_RUST(CBS *cbs, const uint8_t *data, size_t len); +size_t CBS_len_RUST(const CBS *cbs); #if defined(__cplusplus) } // extern C diff --git a/rust/bssl-sys/src/lib.rs b/rust/bssl-sys/src/lib.rs index e7f5fc48d..1d43e14eb 100644 --- a/rust/bssl-sys/src/lib.rs +++ b/rust/bssl-sys/src/lib.rs @@ -48,22 +48,11 @@ pub const XN_FLAG_ONELINE: c_ulong = bindgen::XN_FLAG_ONELINE as c_ulong; // TODO(crbug.com/boringssl/596): Remove these wrappers. #[cfg(unsupported_inline_wrappers)] -pub fn ERR_GET_LIB(packed_error: u32) -> i32 { - // Safety: This is safe for all inputs. bindgen conservatively marks everything unsafe. - unsafe { ERR_GET_LIB_RUST(packed_error) } -} - -#[cfg(unsupported_inline_wrappers)] -pub fn ERR_GET_REASON(packed_error: u32) -> i32 { - // Safety: This is safe for all inputs. bindgen conservatively marks everything unsafe. - unsafe { ERR_GET_REASON_RUST(packed_error) } -} - -#[cfg(unsupported_inline_wrappers)] -pub fn ERR_GET_FUNC(packed_error: u32) -> i32 { - // Safety: This is safe for all inputs. bindgen conservatively marks everything unsafe. - unsafe { ERR_GET_FUNC_RUST(packed_error) } -} +pub use { ERR_GET_LIB_RUST as ERR_GET_LIB, + ERR_GET_REASON_RUST as ERR_GET_REASON, + ERR_GET_FUNC_RUST as ERR_GET_FUNC, + CBS_init_RUST as CBS_init, + CBS_len_RUST as CBS_len }; pub fn init() { // Safety: `CRYPTO_library_init` may be called multiple times and concurrently.