Skip to content

Commit 893ce6a

Browse files
committed
Add a NegotiatedGroup wrapper struct
1 parent 3f4308f commit 893ce6a

File tree

2 files changed

+71
-2
lines changed

2 files changed

+71
-2
lines changed

openssl/src/nid.rs

+64
Original file line numberDiff line numberDiff line change
@@ -1096,6 +1096,70 @@ impl Nid {
10961096
pub const CHACHA20_POLY1305: Nid = Nid(ffi::NID_chacha20_poly1305);
10971097
}
10981098

1099+
/// An abstract type wrapping a numerical identifier for a negotiated group.
1100+
///
1101+
/// This is most similar to a `Nid` (when it represents a known group)
1102+
/// but can also represent a specific "unknown shared group".
1103+
/// If the NID for the shared group is unknown then the value is set to the bitwise OR of TLSEXT_nid_unknown (0x1000000) and the id of the group.
1104+
///
1105+
/// # Examples
1106+
///
1107+
/// To view the integer representation of a `NegotiatedGroup`:
1108+
///
1109+
/// ```
1110+
/// use openssl::nid::Nid;
1111+
/// use openssl::nid::NegotiatedGroup;
1112+
///
1113+
/// assert!(Nid::AES_256_GCM.as_raw() == 901);
1114+
/// assert!(NegotiatedGroup::from_raw(901).nid() == Some(Nid::AES_256_GCM));
1115+
/// ```
1116+
///
1117+
/// # External Documentation
1118+
///
1119+
/// The following documentation provides context about returned numeric identifiers
1120+
/// for negotiated groups in OpenSSL.
1121+
///
1122+
/// - [SSL_get_negotiated_group](https://www.openssl.org/docs/manmaster/man3/SSL_get_negotiated_group.html)
1123+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1124+
#[cfg(ossl300)]
1125+
pub struct NegotiatedGroup(c_int);
1126+
1127+
#[cfg(ossl300)]
1128+
impl NegotiatedGroup {
1129+
#[allow(non_upper_case_globals)]
1130+
pub const TLSEXT_nid_unknown: i32 = 0x1000000;
1131+
1132+
/// Create a `NegotiatedGroup` from an integer representation.
1133+
pub const fn from_raw(raw: c_int) -> Self {
1134+
Self(raw)
1135+
}
1136+
1137+
/// Return the integer representation of a `NegotiatedGroup`.
1138+
#[allow(clippy::trivially_copy_pass_by_ref)]
1139+
pub const fn as_raw(&self) -> c_int {
1140+
self.0
1141+
}
1142+
1143+
/// Return a `Nid` for the known negotiated group or `None``.
1144+
pub fn nid(self) -> Option<Nid> {
1145+
if (self.0 & Self::TLSEXT_nid_unknown) == 0 {
1146+
Some(Nid::from_raw(self.0))
1147+
} else {
1148+
None
1149+
}
1150+
}
1151+
1152+
/// Return a `i32` id for the unknown negotiated group or `None`.
1153+
pub fn unknown_group_id(self) -> Option<i32> {
1154+
if (self.0 & Self::TLSEXT_nid_unknown) != 0 {
1155+
let id = self.0 ^ Self::TLSEXT_nid_unknown;
1156+
Some(id)
1157+
} else {
1158+
None
1159+
}
1160+
}
1161+
}
1162+
10991163
#[cfg(test)]
11001164
mod test {
11011165
use super::Nid;

openssl/src/ssl/mod.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ use crate::error::ErrorStack;
6969
use crate::ex_data::Index;
7070
#[cfg(ossl111)]
7171
use crate::hash::MessageDigest;
72+
#[cfg(ossl300)]
73+
use crate::nid::NegotiatedGroup;
7274
#[cfg(any(ossl110, libressl270))]
7375
use crate::nid::Nid;
7476
use crate::pkey::{HasPrivate, PKeyRef, Params, Private};
@@ -3501,8 +3503,11 @@ impl SslRef {
35013503
/// bitwise OR of TLSEXT_nid_unknown (0x1000000) and the id of the group.
35023504
#[corresponds(SSL_get_negotiated_group)]
35033505
#[cfg(ossl300)]
3504-
pub fn negotiated_group(&self) -> Result<c_int, ErrorStack> {
3505-
unsafe { cvt(ffi::SSL_get_negotiated_group(self.as_ptr())) }
3506+
pub fn negotiated_group(&self) -> Result<NegotiatedGroup, ErrorStack> {
3507+
use crate::nid::NegotiatedGroup;
3508+
3509+
let raw = unsafe { cvt(ffi::SSL_get_negotiated_group(self.as_ptr())) };
3510+
raw.map(NegotiatedGroup::from_raw)
35063511
}
35073512

35083513
/// Return the TLS group name associated with a given TLS group ID, as

0 commit comments

Comments
 (0)