Skip to content

Commit

Permalink
Expose the peer cert chain via FFI
Browse files Browse the repository at this point in the history
  • Loading branch information
bwoebi committed Feb 22, 2024
1 parent 45b59aa commit eb0b707
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 0 deletions.
6 changes: 6 additions & 0 deletions quiche/include/quiche.h
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,12 @@ void quiche_conn_application_proto(const quiche_conn *conn, const uint8_t **out,
// Returns the peer's leaf certificate (if any) as a DER-encoded buffer.
void quiche_conn_peer_cert(const quiche_conn *conn, const uint8_t **out, size_t *out_len);

// Returns the nth certificate of the peer's leaf certificate (if any) as a DER-encoded buffer.
void quiche_conn_peer_cert_chain_index(const quiche_conn *conn, size_t index, const uint8_t **out, size_t *out_len);

// Returns the length of the peer's leaf certificate.
size_t quiche_conn_peer_cert_chain_len(const quiche_conn *conn);

// Returns the serialized cryptographic session for the connection.
void quiche_conn_session(const quiche_conn *conn, const uint8_t **out, size_t *out_len);

Expand Down
21 changes: 21 additions & 0 deletions quiche/src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1077,6 +1077,27 @@ pub extern fn quiche_conn_peer_cert(
}
}

#[no_mangle]
pub extern fn quiche_conn_peer_cert_chain_index(
conn: &Connection, index: size_t, out: &mut *const u8, out_len: &mut size_t,
) {
match conn.peer_cert_chain_index(index) {
Some(peer_cert) => {
*out = peer_cert.as_ptr();
*out_len = peer_cert.len();
},

None => *out_len = 0,
}
}

#[no_mangle]
pub extern fn quiche_conn_peer_cert_chain_len(
conn: &Connection
) -> size_t {
conn.peer_cert_chain_len()
}

#[no_mangle]
pub extern fn quiche_conn_session(
conn: &Connection, out: &mut *const u8, out_len: &mut size_t,
Expand Down
19 changes: 19 additions & 0 deletions quiche/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6124,6 +6124,25 @@ impl Connection {
self.handshake.peer_cert_chain()
}

/// Returns the peer's certificate chain length.
///
/// This function supports FFI, enabling reading the certificate chain
/// without extra allocations.
#[inline]
pub(crate) fn peer_cert_chain_len(&self) -> usize {
self.handshake.peer_cert_chain_len()
}

/// Returns the nth certificate of the peer's certificate chain as a
/// DER-encoded buffer.
///
/// This function supports FFI, enabling reading the certificate chain
/// without extra allocations.
#[inline]
pub(crate) fn peer_cert_chain_index(&self, index: usize) -> Option<&[u8]> {
self.handshake.peer_cert_chain_index(index)
}

/// Returns the serialized cryptographic session for the connection.
///
/// This can be used by a client to cache a connection's session, and resume
Expand Down
29 changes: 29 additions & 0 deletions quiche/src/tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,35 @@ impl Handshake {
Some(cert_chain)
}

pub fn peer_cert_chain_index(&self, index: usize) -> Option<&[u8]> {
let cert = unsafe {
let chain =
map_result_ptr(SSL_get0_peer_certificates(self.as_ptr())).ok()?;

let buffer =
map_result_ptr(sk_value(chain, index) as *const CRYPTO_BUFFER)
.ok()?;

let out_len = CRYPTO_BUFFER_len(buffer);
if out_len == 0 {
return None;
}

let out = CRYPTO_BUFFER_data(buffer);
slice::from_raw_parts(out, out_len)
};

Some(cert)
}

pub fn peer_cert_chain_len(&self) -> usize {
unsafe {
let chain =
map_result_ptr(SSL_get0_peer_certificates(self.as_ptr())).ok();
chain.map_or(0, |c| sk_num(c))
}
}

pub fn peer_cert(&self) -> Option<&[u8]> {
let peer_cert = unsafe {
let chain =
Expand Down

0 comments on commit eb0b707

Please sign in to comment.