From 2df620406d66f9dd37522902814ca9c5f2903ec3 Mon Sep 17 00:00:00 2001 From: Kornel Date: Fri, 27 Mar 2026 04:33:37 +0000 Subject: [PATCH 01/10] BN_is_odd --- boring/src/bn.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/boring/src/bn.rs b/boring/src/bn.rs index 545eb3487..07f65da94 100644 --- a/boring/src/bn.rs +++ b/boring/src/bn.rs @@ -292,6 +292,18 @@ impl BigNumRef { unsafe { BN_is_negative(self.as_ptr()) == 1 } } + #[corresponds(BN_is_odd)] + #[must_use] + pub fn is_odd(&self) -> bool { + unsafe { ffi::BN_is_odd(self.as_ptr()) == 1 } + } + + #[corresponds(BN_is_even)] + #[must_use] + pub fn is_even(&self) -> bool { + !self.is_odd() + } + /// Returns the number of significant bits in `self`. #[corresponds(BN_num_bits)] #[must_use] From 4b23555159c6a5accf6ec0a1ebc4514ce720953a Mon Sep 17 00:00:00 2001 From: Kornel Date: Fri, 27 Mar 2026 12:22:29 +0000 Subject: [PATCH 02/10] BN_mod_sqrt --- boring/src/bn.rs | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/boring/src/bn.rs b/boring/src/bn.rs index 07f65da94..f25047f78 100644 --- a/boring/src/bn.rs +++ b/boring/src/bn.rs @@ -807,6 +807,32 @@ impl BigNumRef { } } + /// Places into `self` the modular square root of `a` such that `self^2 = a (mod p)`. + /// + /// Returns an error or if `a` is not a square mod `p`. In the latter case, it will add + /// `BN_R_NOT_A_SQUARE` to the error queue. If `a` is a square and `p` > 2, there are two + /// possible square roots; this function may return either. + /// + /// This function only works if `p` is a prime. If `p` is composite, it may fail or return an + /// arbitrary value. Callers should not pass attacker-controlled values of `p`. + #[corresponds(BN_mod_sqrt)] + pub fn mod_sqrt( + &mut self, + a: &BigNumRef, + p: &BigNumRef, + ctx: &mut BigNumContextRef, + ) -> Result<(), ErrorStack> { + unsafe { + cvt_p(ffi::BN_mod_sqrt( + self.as_ptr(), + a.as_ptr(), + p.as_ptr(), + ctx.as_ptr(), + )) + .map(|_| ()) + } + } + /// Returns an `Asn1Integer` containing the value of `self`. #[corresponds(BN_to_ASN1_INTEGER)] pub fn to_asn1_integer(&self) -> Result { @@ -1189,4 +1215,25 @@ mod tests { assert!(p.is_prime(100, &mut ctx).unwrap()); assert!(p.is_prime_fasttest(100, &mut ctx, true).unwrap()); } + + #[test] + fn test_mod_sqrt() { + let mut ctx = BigNumContext::new().unwrap(); + + // 2 is a quadratic residue mod 0x7DEB1 (a prime) + let s = BigNum::from_hex_str("2").unwrap(); + let p = BigNum::from_hex_str("7DEB1").unwrap(); + let mut sqrt = BigNum::new().unwrap(); + let mut out = BigNum::new().unwrap(); + + // Square the root since there are two possible roots; verify the square equals s mod p + sqrt.mod_sqrt(&s, &p, &mut ctx).unwrap(); + out.mod_sqr(&sqrt, &p, &mut ctx).unwrap(); + assert_eq!(out, s); + + // 3 is not a quadratic residue mod 5, so mod_sqrt must fail + let non_residue = BigNum::from_hex_str("3").unwrap(); + let p5 = BigNum::from_hex_str("5").unwrap(); + assert!(out.mod_sqrt(&non_residue, &p5, &mut ctx).is_err()); + } } From 7ef7d1b4c161f99c15107750edba326eedb68e76 Mon Sep 17 00:00:00 2001 From: Kornel Date: Fri, 27 Mar 2026 12:22:58 +0000 Subject: [PATCH 03/10] BN_bin2bn --- boring/src/bn.rs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/boring/src/bn.rs b/boring/src/bn.rs index f25047f78..d4d77c33d 100644 --- a/boring/src/bn.rs +++ b/boring/src/bn.rs @@ -888,10 +888,6 @@ impl BigNum { /// Creates a new `BigNum` from an unsigned, big-endian encoded number of arbitrary length. /// - /// OpenSSL documentation at [`BN_bin2bn`] - /// - /// [`BN_bin2bn`]: https://www.openssl.org/docs/man1.1.0/crypto/BN_bin2bn.html - /// /// ``` /// # use boring::bn::BigNum; /// let bignum = BigNum::from_slice(&[0x12, 0x00, 0x34]).unwrap(); @@ -906,6 +902,15 @@ impl BigNum { cvt_p(ffi::BN_bin2bn(n.as_ptr(), n.len(), ptr::null_mut())).map(|p| BigNum::from_ptr(p)) } } + + /// Copies data from a big-endian byte slice into `self`, overwriting its current value. + #[corresponds(BN_bin2bn)] + pub fn copy_from_slice(&mut self, n: &[u8]) -> Result<(), ErrorStack> { + unsafe { + cvt_p(ffi::BN_bin2bn(n.as_ptr(), n.len(), self.as_ptr()))?; + Ok(()) + } + } } impl fmt::Debug for BigNumRef { @@ -1167,11 +1172,15 @@ mod tests { #[test] fn test_to_from_slice() { - let v0 = BigNum::from_u32(10_203_004).unwrap(); + let mut v0 = BigNum::from_u32(10_203_004).unwrap(); let vec = v0.to_vec(); let v1 = BigNum::from_slice(&vec).unwrap(); - assert_eq!(v0, v1); + + v0.copy_from_slice(&[0x12, 0, 0x34]).unwrap(); + assert_eq!(v0, BigNum::from_u32(0x12_0034).unwrap()); + v0.copy_from_slice(&[0xff]).unwrap(); + assert_eq!(v0, BigNum::from_u32(0xff).unwrap()); } #[test] From 3345fbeda656e067516469046fbdbd0114313575 Mon Sep 17 00:00:00 2001 From: Kornel Date: Fri, 27 Mar 2026 04:33:32 +0000 Subject: [PATCH 04/10] ASN1_INTEGER_cmp/dup --- boring/src/asn1.rs | 122 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 110 insertions(+), 12 deletions(-) diff --git a/boring/src/asn1.rs b/boring/src/asn1.rs index 8acc2c40e..5ccb4aea0 100644 --- a/boring/src/asn1.rs +++ b/boring/src/asn1.rs @@ -450,6 +450,7 @@ impl fmt::Debug for Asn1StringRef { foreign_type_and_impl_send_sync! { type CType = ffi::ASN1_INTEGER; fn drop = ffi::ASN1_INTEGER_free; + fn clone = ffi::ASN1_INTEGER_dup; /// Numeric representation /// @@ -476,24 +477,88 @@ impl Asn1Integer { } } +impl Ord for Asn1IntegerRef { + #[corresponds(ASN1_INTEGER_cmp)] + fn cmp(&self, other: &Self) -> Ordering { + let res = unsafe { ffi::ASN1_INTEGER_cmp(self.as_ptr(), other.as_ptr()) }; + res.cmp(&0) + } +} + +impl PartialOrd for Asn1IntegerRef { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl PartialOrd for Asn1IntegerRef { + fn partial_cmp(&self, other: &Asn1Integer) -> Option { + Some(self.cmp(&**other)) + } +} + +impl Eq for Asn1IntegerRef {} + +impl PartialEq for Asn1IntegerRef { + #[corresponds(ASN1_INTEGER_cmp)] + fn eq(&self, other: &Self) -> bool { + self.cmp(other) == Ordering::Equal + } +} + +impl PartialEq for Asn1IntegerRef { + fn eq(&self, other: &Asn1Integer) -> bool { + self.eq(&**other) + } +} + +impl Ord for Asn1Integer { + fn cmp(&self, other: &Self) -> Ordering { + Asn1IntegerRef::cmp(self, other) + } +} + +impl PartialOrd for Asn1Integer { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl PartialOrd for Asn1Integer { + fn partial_cmp(&self, other: &Asn1IntegerRef) -> Option { + (**self).partial_cmp(other) + } +} + +impl Eq for Asn1Integer {} + +impl PartialEq for Asn1Integer { + fn eq(&self, other: &Self) -> bool { + Asn1IntegerRef::eq(self, other) + } +} + +impl PartialEq for Asn1Integer { + fn eq(&self, other: &Asn1IntegerRef) -> bool { + Asn1IntegerRef::eq(self, other) + } +} + impl Asn1IntegerRef { #[allow(clippy::unnecessary_cast)] #[allow(missing_docs)] #[deprecated(since = "0.10.6", note = "use to_bn instead")] #[must_use] pub fn get(&self) -> i64 { - unsafe { crate::ffi::ASN1_INTEGER_get(self.as_ptr()) as i64 } + unsafe { ffi::ASN1_INTEGER_get(self.as_ptr()) as i64 } } /// Converts the integer to a `BigNum`. #[corresponds(ASN1_INTEGER_to_BN)] pub fn to_bn(&self) -> Result { unsafe { - cvt_p(crate::ffi::ASN1_INTEGER_to_BN( - self.as_ptr(), - ptr::null_mut(), - )) - .map(|p| BigNum::from_ptr(p)) + cvt_p(ffi::ASN1_INTEGER_to_BN(self.as_ptr(), ptr::null_mut())) + .map(|p| BigNum::from_ptr(p)) } } @@ -503,12 +568,7 @@ impl Asn1IntegerRef { /// [`bn`]: ../bn/struct.BigNumRef.html#method.to_asn1_integer #[corresponds(ASN1_INTEGER_set)] pub fn set(&mut self, value: i32) -> Result<(), ErrorStack> { - unsafe { - cvt(crate::ffi::ASN1_INTEGER_set( - self.as_ptr(), - c_long::from(value), - )) - } + unsafe { cvt(ffi::ASN1_INTEGER_set(self.as_ptr(), c_long::from(value))) } } } @@ -723,4 +783,42 @@ mod tests { .map(|object| object.to_string()) .expect_err("parsing invalid OID should fail"); } + + #[test] + fn integer_eq_ord() { + let make = |n: u32| Asn1Integer::from_bn(&BigNum::from_u32(n).unwrap()).unwrap(); + + let a = make(1); + let b = make(1); + let c = make(2); + + assert!(a == b); + assert!(a.as_ref() == b.as_ref()); + assert!(a != c); + assert!(*a == *b); + assert!(*a != *c); + assert!(a == *b); + assert!(*a == b); + assert!(a <= b); + assert!(a >= b); + assert!(a < c); + assert!(c > a); + assert!(*a <= *b); + assert!(*a >= *b); + assert!(*a < *c); + assert!(*c > *a); + assert!(*a <= b); + assert!(*c > a); + } + + #[test] + fn integer_to_owned() { + let bn = BigNum::from_dec_str("1234567890").unwrap(); + let orig = Asn1Integer::from_bn(&bn).unwrap(); + let copy = orig.clone(); + assert!( + orig == copy, + "duplicated Asn1Integer should be equal to the original" + ); + } } From 5e5dbc6534aff16136d80727ccc333dcfd279c3d Mon Sep 17 00:00:00 2001 From: Kornel Date: Fri, 27 Mar 2026 11:21:06 +0000 Subject: [PATCH 05/10] ASN1_GENERALIZEDTIME_set_string + FromStr --- boring/src/asn1.rs | 125 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 111 insertions(+), 14 deletions(-) diff --git a/boring/src/asn1.rs b/boring/src/asn1.rs index 5ccb4aea0..6001902d8 100644 --- a/boring/src/asn1.rs +++ b/boring/src/asn1.rs @@ -61,6 +61,40 @@ foreign_type_and_impl_send_sync! { pub struct Asn1GeneralizedTime; } +impl Asn1GeneralizedTime { + #[corresponds(ASN1_GENERALIZEDTIME_new)] + fn new() -> Result { + ffi::init(); + + unsafe { + let handle = cvt_p(ffi::ASN1_GENERALIZEDTIME_new())?; + Ok(Self::from_ptr(handle)) + } + } +} + +impl str::FromStr for Asn1GeneralizedTime { + type Err = ErrorStack; + + /// Creates a new `Asn1GeneralizedTime` corresponding to the specified ASN1 + /// time string. + /// + /// The string must be a valid GeneralizedTime. Returns an error if the + /// string is not valid. + #[corresponds(ASN1_GENERALIZEDTIME_set_string)] + fn from_str(s: &str) -> Result { + let time = Asn1GeneralizedTime::new()?; + let s = CString::new(s).map_err(ErrorStack::internal_error)?; + unsafe { + cvt(ffi::ASN1_GENERALIZEDTIME_set_string( + time.as_ptr(), + s.as_ptr(), + ))?; + Ok(time) + } + } +} + impl fmt::Display for Asn1GeneralizedTimeRef { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let bio = MemBio::new().ok(); @@ -323,18 +357,41 @@ impl Asn1Time { } } + /// Creates a new time corresponding to the specified X509 time string. + /// + /// Behaves like [`Asn1Time::from_str`] except it additionally converts + /// GeneralizedTime to UTCTime if it is in the range where UTCTime is used. + /// See RFC 5280, section 4.1.2.5. + #[corresponds(ASN1_TIME_set_string_X509)] + pub fn from_str_x509(s: &str) -> Result { + let time = Asn1Time::new()?; + let s = CString::new(s).map_err(ErrorStack::internal_error)?; + unsafe { + cvt(ffi::ASN1_TIME_set_string_X509(time.as_ptr(), s.as_ptr()))?; + } + Ok(time) + } + /// Creates a new time corresponding to the specified ASN1 time string. #[corresponds(ASN1_TIME_set_string)] #[allow(clippy::should_implement_trait)] pub fn from_str(s: &str) -> Result { - unsafe { - let s = CString::new(s).map_err(ErrorStack::internal_error)?; + s.parse() + } +} - let time = Asn1Time::new()?; - cvt(ffi::ASN1_TIME_set_string(time.as_ptr(), s.as_ptr()))?; +impl str::FromStr for Asn1Time { + type Err = ErrorStack; - Ok(time) + /// Creates a new time corresponding to the specified ASN1 time string. + #[corresponds(ASN1_TIME_set_string)] + fn from_str(s: &str) -> Result { + let time = Asn1Time::new()?; + let s = CString::new(s).map_err(ErrorStack::internal_error)?; + unsafe { + cvt(ffi::ASN1_TIME_set_string(time.as_ptr(), s.as_ptr()))?; } + Ok(time) } } @@ -421,7 +478,13 @@ impl Asn1StringRef { #[corresponds(ASN1_STRING_get0_data)] #[must_use] pub fn as_slice(&self) -> &[u8] { - unsafe { slice::from_raw_parts(ASN1_STRING_get0_data(self.as_ptr()), self.len()) } + unsafe { + let ptr = ffi::ASN1_STRING_get0_data(self.as_ptr().cast()); + if ptr.is_null() { + return &[]; + } + slice::from_raw_parts(ptr, self.len()) + } } /// Returns the number of bytes in the string. @@ -590,7 +653,7 @@ impl Asn1BitStringRef { #[must_use] pub fn as_slice(&self) -> &[u8] { unsafe { - let ptr = ASN1_STRING_get0_data(self.as_ptr().cast()); + let ptr = ffi::ASN1_STRING_get0_data(self.as_ptr().cast()); if ptr.is_null() { return &[]; } @@ -648,10 +711,21 @@ impl Asn1Object { #[corresponds(OBJ_txt2obj)] #[allow(clippy::should_implement_trait)] pub fn from_str(txt: &str) -> Result { + txt.parse() + } +} + +impl str::FromStr for Asn1Object { + type Err = ErrorStack; + + /// Constructs an ASN.1 Object Identifier from a string representation of the OID. + #[corresponds(OBJ_txt2obj)] + fn from_str(txt: &str) -> Result { + ffi::init(); + + let txt = CString::new(txt).map_err(ErrorStack::internal_error)?; unsafe { - ffi::init(); - let txt = CString::new(txt).map_err(ErrorStack::internal_error)?; - let obj: *mut ffi::ASN1_OBJECT = cvt_p(ffi::OBJ_txt2obj(txt.as_ptr(), 0))?; + let obj = cvt_p(ffi::OBJ_txt2obj(txt.as_ptr(), 0))?; Ok(Asn1Object::from_ptr(obj)) } } @@ -690,8 +764,6 @@ impl fmt::Debug for Asn1ObjectRef { } } -use crate::ffi::ASN1_STRING_get0_data; - #[cfg(test)] mod tests { use super::*; @@ -716,6 +788,31 @@ mod tests { #[test] fn time_from_str() { Asn1Time::from_str("99991231235959Z").unwrap(); + + let time: Asn1GeneralizedTime = "20250101120000Z".parse().unwrap(); + let display = time.to_string(); + assert!( + display.contains("2025"), + "expected year in display: {display}" + ); + + assert!( + ::from_str("not a time").is_err(), + "should fail for invalid input", + ); + + // GeneralizedTime that falls in UTCTime range should be accepted + let time = Asn1Time::from_str_x509("20250101120000Z").unwrap(); + let display = time.to_string(); + assert!( + display.contains("2025"), + "expected year in display: {display}" + ); + + assert!( + Asn1Time::from_str_x509("not a time").is_err(), + "should fail for invalid input", + ); } #[test] @@ -728,7 +825,7 @@ mod tests { fn time_eq() { let a = Asn1Time::from_str("99991231235959Z").unwrap(); let b = Asn1Time::from_str("99991231235959Z").unwrap(); - let c = Asn1Time::from_str("99991231235958Z").unwrap(); + let c = "99991231235958Z".parse::().unwrap(); let a_ref = a.as_ref(); let b_ref = b.as_ref(); let c_ref = c.as_ref(); @@ -745,7 +842,7 @@ mod tests { #[test] fn time_ord() { let a = Asn1Time::from_str("99991231235959Z").unwrap(); - let b = Asn1Time::from_str("99991231235959Z").unwrap(); + let b = ::from_str("99991231235959Z").unwrap(); let c = Asn1Time::from_str("99991231235958Z").unwrap(); let a_ref = a.as_ref(); let b_ref = b.as_ref(); From d58efbc2a63e52ca13154f621af8c9d8b6c6c2e5 Mon Sep 17 00:00:00 2001 From: Kornel Date: Fri, 27 Mar 2026 04:33:20 +0000 Subject: [PATCH 06/10] X509_NAME_cmp --- boring/src/x509/mod.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/boring/src/x509/mod.rs b/boring/src/x509/mod.rs index 7a6d1d2db..feb754d7c 100644 --- a/boring/src/x509/mod.rs +++ b/boring/src/x509/mod.rs @@ -1192,6 +1192,16 @@ impl X509NameRef { to_der, ffi::i2d_X509_NAME } + + /// Compares `self` and `other`'s canonicalized forms. + #[corresponds(X509_NAME_cmp)] + pub fn try_cmp(&self, other: &X509NameRef) -> Result { + let r = unsafe { ffi::X509_NAME_cmp(self.as_ptr(), other.as_ptr()) }; + if r == -2 { + return Err(ErrorStack::get()); + } + Ok(r.cmp(&0)) + } } impl fmt::Debug for X509NameRef { From c4302c785bf6eb09c5911b9a8717ee2574957d5b Mon Sep 17 00:00:00 2001 From: Kornel Date: Fri, 27 Mar 2026 04:37:00 +0000 Subject: [PATCH 07/10] EC_GROUP_get_asn1_flag --- boring/src/ec.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/boring/src/ec.rs b/boring/src/ec.rs index aac0230fa..d7a49db0a 100644 --- a/boring/src/ec.rs +++ b/boring/src/ec.rs @@ -204,11 +204,19 @@ impl EcGroupRef { } } - /// Sets the flag determining if the group corresponds to a named curve or must be explicitly - /// parameterized. - /// - /// This defaults to `EXPLICIT_CURVE` in OpenSSL 1.0.1 and 1.0.2, but `NAMED_CURVE` in OpenSSL - /// 1.1.0. + /// Returns [`Asn1Flag::NAMED_CURVE`]. + #[doc(hidden)] + #[deprecated(note = "BoringSSL always returns `OPENSSL_EC_NAMED_CURVE`")] + #[corresponds(EC_GROUP_get_asn1_flag)] + #[must_use] + pub fn asn1_flag(&self) -> Asn1Flag { + unsafe { Asn1Flag(ffi::EC_GROUP_get_asn1_flag(self.as_ptr())) } + } + + /// No-op + #[doc(hidden)] + #[deprecated(note = "Ignored in BoringSSL")] + #[corresponds(EC_GROUP_set_asn1_flag)] pub fn set_asn1_flag(&mut self, flag: Asn1Flag) { unsafe { ffi::EC_GROUP_set_asn1_flag(self.as_ptr(), flag.0); From b215e0410cf3ba84af971e1cdbf1b3f042a81160 Mon Sep 17 00:00:00 2001 From: Kornel Date: Fri, 27 Mar 2026 04:39:01 +0000 Subject: [PATCH 08/10] EC_POINT_get_affine_coordinates --- boring/src/ec.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/boring/src/ec.rs b/boring/src/ec.rs index d7a49db0a..81313b16b 100644 --- a/boring/src/ec.rs +++ b/boring/src/ec.rs @@ -411,6 +411,7 @@ impl EcPointRef { /// Place affine coordinates of a curve over a prime field in the provided /// `x` and `y` `BigNum`s + #[doc(alias = "affine_coordinates")] #[corresponds(EC_POINT_get_affine_coordinates_GFp)] pub fn affine_coordinates_gfp( &self, @@ -429,6 +430,28 @@ impl EcPointRef { )) } } + + /// An alias for [`affine_coordinates_gfp`](Self::affine_coordinates_gfp). + #[corresponds(EC_POINT_get_affine_coordinates)] + #[doc(hidden)] + pub fn affine_coordinates( + &self, + group: &EcGroupRef, + x: &mut BigNumRef, + y: &mut BigNumRef, + ctx: &mut BigNumContextRef, + ) -> Result<(), ErrorStack> { + unsafe { + cvt(ffi::EC_POINT_get_affine_coordinates( + group.as_ptr(), + self.as_ptr(), + x.as_ptr(), + y.as_ptr(), + ctx.as_ptr(), + )) + } + } + } impl EcPoint { From ead34d49e09e9c0482ffd17c4f12b65a617fcdb1 Mon Sep 17 00:00:00 2001 From: Kornel Date: Fri, 27 Mar 2026 04:39:25 +0000 Subject: [PATCH 09/10] EC_POINT_is_at_infinity --- boring/src/ec.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/boring/src/ec.rs b/boring/src/ec.rs index 81313b16b..e224ef0f0 100644 --- a/boring/src/ec.rs +++ b/boring/src/ec.rs @@ -452,6 +452,31 @@ impl EcPointRef { } } + /// Returns `true` if `self` is the point at infinity and `false` otherwise. + #[corresponds(EC_POINT_is_at_infinity)] + #[must_use] + pub fn is_infinity(&self, group: &EcGroupRef) -> bool { + unsafe { ffi::EC_POINT_is_at_infinity(group.as_ptr(), self.as_ptr()) == 1 } + } + + /// Returns `Ok(true)` if `self` is an element of `group` and `Ok(false)` otherwise. + /// `ctx` is ignored. This method exists for rust-openssl interoperability. + #[corresponds(EC_POINT_is_on_curve)] + #[doc(hidden)] + pub fn is_on_curve( + &self, + group: &EcGroupRef, + ctx: &mut BigNumContextRef, + ) -> Result { + unsafe { + let res = cvt_n(ffi::EC_POINT_is_on_curve( + group.as_ptr(), + self.as_ptr(), + ctx.as_ptr(), + ))?; + Ok(res == 1) + } + } } impl EcPoint { From 7df672e18986fce24d7349fdf22cb179ca1529d5 Mon Sep 17 00:00:00 2001 From: Kornel Date: Fri, 27 Mar 2026 11:56:36 +0000 Subject: [PATCH 10/10] Constants for rust-openssl --- boring/src/nid.rs | 9 +++++++++ boring/src/pkey.rs | 6 ++++++ boring/src/srtp.rs | 2 ++ 3 files changed, 17 insertions(+) diff --git a/boring/src/nid.rs b/boring/src/nid.rs index 15cfe4eb9..9dc0bee74 100644 --- a/boring/src/nid.rs +++ b/boring/src/nid.rs @@ -1057,6 +1057,15 @@ impl Nid { pub const AUTH_ECDSA: Nid = Nid(ffi::NID_auth_ecdsa); pub const AUTH_PSK: Nid = Nid(ffi::NID_auth_psk); pub const AUTH_ANY: Nid = Nid(ffi::NID_auth_any); + pub const BRAINPOOL_P256R1: Nid = Nid(ffi::NID_brainpoolP256r1); + pub const BRAINPOOL_P256T1: Nid = Nid(ffi::NID_brainpoolP256t1); + pub const BRAINPOOL_P320R1: Nid = Nid(ffi::NID_brainpoolP320r1); + pub const BRAINPOOL_P320T1: Nid = Nid(ffi::NID_brainpoolP320t1); + pub const BRAINPOOL_P384R1: Nid = Nid(ffi::NID_brainpoolP384r1); + pub const BRAINPOOL_P384T1: Nid = Nid(ffi::NID_brainpoolP384t1); + pub const BRAINPOOL_P512R1: Nid = Nid(ffi::NID_brainpoolP512r1); + pub const BRAINPOOL_P512T1: Nid = Nid(ffi::NID_brainpoolP512t1); + pub const CHACHA20_POLY1305: Nid = Nid(ffi::NID_chacha20_poly1305); } #[cfg(test)] diff --git a/boring/src/pkey.rs b/boring/src/pkey.rs index bc5214e3a..97b8134dc 100644 --- a/boring/src/pkey.rs +++ b/boring/src/pkey.rs @@ -74,7 +74,12 @@ pub struct Id(c_int); impl Id { pub const RSA: Id = Id(ffi::EVP_PKEY_RSA); + /// RSA-PSS key type + #[doc(alias = "RSA_PSS")] pub const RSAPSS: Id = Id(ffi::EVP_PKEY_RSA_PSS); + /// rust-openssl alias + #[doc(hidden)] + pub const RSA_PSS: Id = Self::RSAPSS; pub const DSA: Id = Id(ffi::EVP_PKEY_DSA); pub const DH: Id = Id(ffi::EVP_PKEY_DH); pub const EC: Id = Id(ffi::EVP_PKEY_EC); @@ -82,6 +87,7 @@ impl Id { pub const ED448: Id = Id(ffi::EVP_PKEY_ED448); pub const X25519: Id = Id(ffi::EVP_PKEY_X25519); pub const X448: Id = Id(ffi::EVP_PKEY_X448); + pub const HKDF: Id = Id(ffi::EVP_PKEY_HKDF); /// Creates a `Id` from an integer representation. #[must_use] diff --git a/boring/src/srtp.rs b/boring/src/srtp.rs index 7dffc436e..1508b26ce 100644 --- a/boring/src/srtp.rs +++ b/boring/src/srtp.rs @@ -48,6 +48,8 @@ impl SrtpProfileId { SrtpProfileId(ffi::SRTP_AES128_F8_SHA1_32 as _); pub const SRTP_NULL_SHA1_80: SrtpProfileId = SrtpProfileId(ffi::SRTP_NULL_SHA1_80 as _); pub const SRTP_NULL_SHA1_32: SrtpProfileId = SrtpProfileId(ffi::SRTP_NULL_SHA1_32 as _); + pub const SRTP_AEAD_AES_128_GCM: SrtpProfileId = SrtpProfileId(ffi::SRTP_AEAD_AES_128_GCM as _); + pub const SRTP_AEAD_AES_256_GCM: SrtpProfileId = SrtpProfileId(ffi::SRTP_AEAD_AES_256_GCM as _); /// Creates a `SrtpProfileId` from an integer representation. #[must_use]