Skip to content

Commit

Permalink
implement SSL_get_negotiated_group
Browse files Browse the repository at this point in the history
Rustls 0.23.11 added a `negotiated_key_exchange_group()` to connections
that exposes the `&dyn SupportedKxGroup` used by the connection. This
allows us to implement `SSL_get_negotiated_group()`.

Our implementation differs slightly from the upstream w.r.t what NID we
return for resumed connections. Rustls will return `None` (which we
translate to `NID_undef`) for connections that are still handshaking, or
for resumed TLS 1.2 handshakes. In contrast, OpenSSL returns the
negotiated group of the original connection in that latter case.
  • Loading branch information
cpu committed Jul 19, 2024
1 parent a1b855e commit 4eebe9c
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 7 deletions.
35 changes: 33 additions & 2 deletions rustls-libssl/src/constants.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use core::ffi::{c_int, CStr};
use openssl_sys::{
NID_X9_62_prime256v1, NID_rsaEncryption, NID_rsassaPss, NID_secp384r1, NID_secp521r1,
NID_ED25519, NID_ED448,
NID_ED25519, NID_ED448, NID_X25519, NID_X448,
};

use rustls::{AlertDescription, SignatureScheme};
use rustls::{AlertDescription, NamedGroup, SignatureScheme};

pub fn alert_desc_to_long_string(value: c_int) -> &'static CStr {
match AlertDescription::from(value as u8) {
Expand Down Expand Up @@ -102,3 +102,34 @@ pub fn sig_scheme_to_nid(scheme: SignatureScheme) -> Option<c_int> {
_ => None,
}
}

pub fn named_group_to_nid(group: NamedGroup) -> Option<c_int> {
use NamedGroup::*;

// See NID_ffhdhe* from obj_mac.h - openssl-sys does not have
// constants for these to import.
const NID_FFDHE2048: c_int = 1126;
const NID_FFDHE3072: c_int = 1127;
const NID_FFDHE4096: c_int = 1128;
const NID_FFDHE6144: c_int = 1129;
const NID_FFDHE8192: c_int = 1130;

// See TLSEXT_nid_unknown from tls1.h - openssl-sys does not
// have a constant for this to import.
const TLSEXT_NID_UNKNOWN: c_int = 0x1000000;

match group {
secp256r1 => Some(NID_X9_62_prime256v1),
secp384r1 => Some(NID_secp384r1),
secp521r1 => Some(NID_secp521r1),
X25519 => Some(NID_X25519),
X448 => Some(NID_X448),
FFDHE2048 => Some(NID_FFDHE2048),
FFDHE3072 => Some(NID_FFDHE3072),
FFDHE4096 => Some(NID_FFDHE4096),
FFDHE6144 => Some(NID_FFDHE6144),
FFDHE8192 => Some(NID_FFDHE8192),
Unknown(id) => Some(TLSEXT_NID_UNKNOWN | id as c_int),
_ => None,
}
}
15 changes: 11 additions & 4 deletions rustls-libssl/src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ use std::sync::Arc;
use std::{fs, path::PathBuf};

use openssl_sys::{
stack_st_X509, stack_st_X509_NAME, OPENSSL_malloc, TLSEXT_NAMETYPE_host_name, EVP_PKEY,
OPENSSL_NPN_NEGOTIATED, OPENSSL_NPN_NO_OVERLAP, X509, X509_STORE, X509_STORE_CTX,
stack_st_X509, stack_st_X509_NAME, NID_undef, OPENSSL_malloc, TLSEXT_NAMETYPE_host_name,
EVP_PKEY, OPENSSL_NPN_NEGOTIATED, OPENSSL_NPN_NO_OVERLAP, X509, X509_STORE, X509_STORE_CTX,
};
use rustls::pki_types::{CertificateDer, PrivatePkcs8KeyDer};

use crate::bio::{Bio, BIO, BIO_METHOD};
use crate::callbacks::SslCallbackContext;
use crate::constants::sig_scheme_to_nid;
use crate::constants::{named_group_to_nid, sig_scheme_to_nid};
use crate::error::{ffi_panic_boundary, Error, MysteriouslyOppositeReturnValue};
use crate::evp_pkey::EvpPkey;
use crate::ex_data::ExData;
Expand Down Expand Up @@ -221,7 +221,8 @@ entry! {
Ok(SslCtrl::GetMaxProtoVersion) => ctx.get().get_max_protocol_version().into(),
Ok(SslCtrl::SetTlsExtHostname)
| Ok(SslCtrl::SetTlsExtServerNameCallback)
| Ok(SslCtrl::SetTlsExtTicketKeyCallback) => {
| Ok(SslCtrl::SetTlsExtTicketKeyCallback)
| Ok(SslCtrl::GetNegotiatedGroup) => {
// not a defined operation in the OpenSSL API
0
}
Expand Down Expand Up @@ -860,6 +861,11 @@ entry! {
ssl.get_mut().stage_certificate_chain(chain);
C_INT_SUCCESS as i64
}
Ok(SslCtrl::GetNegotiatedGroup) => ssl
.get()
.get_negotiated_key_exchange_group()
.and_then(|group| named_group_to_nid(group.name()))
.unwrap_or(NID_undef) as c_long,
// not a defined operation in the OpenSSL API
Ok(SslCtrl::SetTlsExtServerNameCallback)
| Ok(SslCtrl::SetTlsExtTicketKeyCallback)
Expand Down Expand Up @@ -1920,6 +1926,7 @@ num_enum! {
SetMaxProtoVersion = 124,
GetMinProtoVersion = 130,
GetMaxProtoVersion = 131,
GetNegotiatedGroup = 134,
}
}

Expand Down
7 changes: 6 additions & 1 deletion rustls-libssl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use openssl_sys::{
X509_STORE, X509_V_ERR_UNSPECIFIED,
};
use rustls::client::Resumption;
use rustls::crypto::aws_lc_rs as provider;
use rustls::crypto::{aws_lc_rs as provider, SupportedKxGroup};
use rustls::pki_types::{CertificateDer, ServerName};
use rustls::server::{Accepted, Acceptor, ProducesTickets};
use rustls::{
Expand Down Expand Up @@ -1378,6 +1378,11 @@ impl Ssl {
.map(|suite| suite.suite())
}

fn get_negotiated_key_exchange_group(&self) -> Option<&'static dyn SupportedKxGroup> {
self.conn()
.and_then(|conn| conn.negotiated_key_exchange_group())
}

fn get_last_verification_result(&self) -> i64 {
match &self.conn {
ConnState::Client(_, verifier) => verifier.last_result(),
Expand Down
1 change: 1 addition & 0 deletions rustls-libssl/tests/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ int main(int argc, char **argv) {
TRACE(SSL_get_peer_signature_type_nid(ssl, &cipher_nid));
dump_openssl_error_stack();
printf("cipher NID: %d\n", cipher_nid);
printf("negotiated group NID: %ld\n", SSL_get_negotiated_group(ssl));

show_peer_certificate("server", ssl);

Expand Down
1 change: 1 addition & 0 deletions rustls-libssl/tests/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ int main(int argc, char **argv) {
TRACE(SSL_get_peer_signature_type_nid(ssl, &cipher_nid));
dump_openssl_error_stack();
printf("cipher NID: %d\n", cipher_nid);
printf("negotiated group NID: %ld\n", SSL_get_negotiated_group(ssl));

printf("SSL_get_servername: %s (%d)\n",
SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name),
Expand Down

0 comments on commit 4eebe9c

Please sign in to comment.