1
- use std:: { cmp:: min, slice} ;
2
-
3
- use crate :: error:: rustls_result;
4
- use crate :: {
5
- ffi_panic_boundary, ffi_panic_boundary_generic, ffi_panic_boundary_unit, try_ref_from_ptr,
6
- } ;
7
1
use libc:: { c_char, size_t} ;
8
2
use std:: io:: Cursor ;
9
3
use std:: os:: raw:: c_ushort;
10
4
use std:: sync:: Arc ;
5
+ use std:: { cmp:: min, slice} ;
11
6
7
+ use rustls:: sign:: CertifiedKey ;
12
8
use rustls:: { Certificate , PrivateKey } ;
13
9
use rustls_pemfile:: { certs, pkcs8_private_keys, rsa_private_keys} ;
14
10
15
- use rustls:: sign:: CertifiedKey ;
11
+ use crate :: error:: rustls_result;
12
+ use crate :: {
13
+ ffi_panic_boundary, ffi_panic_boundary_generic, ffi_panic_boundary_unit, try_ref_from_ptr,
14
+ } ;
16
15
use rustls_result:: NullParameter ;
17
16
18
17
/// All SignatureScheme currently defined in rustls.
@@ -49,12 +48,11 @@ fn signature_scheme_name(n: u16) -> String {
49
48
50
49
/// Get the name of a SignatureScheme, represented by the `scheme` short value,
51
50
/// if known by the rustls library. For unknown schemes, this returns a string
52
- /// with the scheme value in hex notation.
53
- /// Mainly useful for debugging output.
51
+ /// with the scheme value in hex notation. Mainly useful for debugging output.
52
+ ///
54
53
/// The caller provides `buf` for holding the string and gives its size as `len`
55
54
/// bytes. On return `out_n` carries the number of bytes copied into `buf`. The
56
55
/// `buf` is not NUL-terminated.
57
- ///
58
56
#[ no_mangle]
59
57
pub extern "C" fn rustls_cipher_get_signature_scheme_name (
60
58
scheme : c_ushort ,
@@ -63,36 +61,46 @@ pub extern "C" fn rustls_cipher_get_signature_scheme_name(
63
61
out_n : * mut size_t ,
64
62
) {
65
63
ffi_panic_boundary_unit ! {
64
+ if buf. is_null( ) {
65
+ return ;
66
+ }
66
67
let write_buf: & mut [ u8 ] = unsafe {
67
- let out_n: & mut size_t = match out_n. as_mut( ) {
68
- Some ( out_n) => out_n,
69
- None => return ,
70
- } ;
71
- * out_n = 0 ;
72
- if buf. is_null( ) {
73
- return ;
74
- }
75
68
slice:: from_raw_parts_mut( buf as * mut u8 , len as usize )
76
69
} ;
70
+ let out_n: & mut size_t = try_ref_from_ptr!( out_n, & mut size_t, ( ) ) ;
77
71
let name = signature_scheme_name( scheme) ;
78
72
let len: usize = min( write_buf. len( ) - 1 , name. len( ) ) ;
79
73
write_buf[ ..len] . copy_from_slice( & name. as_bytes( ) [ ..len] ) ;
80
- unsafe {
81
- * out_n = len;
82
- }
74
+ * out_n = len;
83
75
}
84
76
}
85
77
86
- /// The complete chain of certificates plus private key for
87
- /// being certified against someones list of trust anchors (commonly
88
- /// called root store). Corresponds to `CertifiedKey` in the Rust API.
78
+ /// The complete chain of certificates to send during a TLS handshake,
79
+ /// plus a private key that matches the end-entity (leaf) certificate.
80
+ /// Corresponds to `CertifiedKey` in the Rust API.
81
+ /// https://docs.rs/rustls/0.19.0/rustls/sign/struct.CertifiedKey.html
89
82
pub struct rustls_certified_key {
90
83
// We use the opaque struct pattern to tell C about our types without
91
84
// telling them what's inside.
92
85
// https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs
93
86
_private : [ u8 ; 0 ] ,
94
87
}
95
88
89
+ /// Build a `rustls_certified_key` from a certificate chain and a private key.
90
+ /// `cert_chain` must point to a buffer of `cert_chain_len` bytes, containing
91
+ /// a series of PEM-encoded certificates, with the end-entity (leaf)
92
+ /// certificate first.
93
+ ///
94
+ /// `private_key` must point to a buffer of `private_key_len` bytes, containing
95
+ /// a PEM-encoded private key in either PKCS#1 or PKCS#8 format.
96
+ ///
97
+ /// On success, this writes a pointer to the newly created
98
+ /// `rustls_certified_key` in `certified_key_out`. That pointer must later
99
+ /// be freed with `rustls_certified_key_free` to avoid memory leaks. Note that
100
+ /// internally, this is an atomically reference-counted pointer, so even after
101
+ /// the original caller has called `rustls_certified_key_free`, other objects
102
+ /// may retain a pointer to the object. The memory will be freed when all
103
+ /// references are gone.
96
104
#[ no_mangle]
97
105
pub extern "C" fn rustls_certified_key_build (
98
106
cert_chain : * const u8 ,
@@ -102,14 +110,15 @@ pub extern "C" fn rustls_certified_key_build(
102
110
certified_key_out : * mut * const rustls_certified_key ,
103
111
) -> rustls_result {
104
112
ffi_panic_boundary ! {
113
+ let certified_key_out: & mut * const rustls_certified_key =
114
+ try_ref_from_ptr!( certified_key_out, & mut * const rustls_certified_key) ;
105
115
let certified_key = match certified_key_build(
106
116
cert_chain, cert_chain_len, private_key, private_key_len) {
107
117
Ok ( key) => Box :: new( key) ,
108
118
Err ( rr) => return rr,
109
119
} ;
110
- unsafe {
111
- * certified_key_out = Arc :: into_raw( Arc :: new( * certified_key) ) as * const _;
112
- }
120
+ let certified_key = Arc :: into_raw( Arc :: new( * certified_key) ) as * const _;
121
+ * certified_key_out = certified_key;
113
122
return rustls_result:: Ok
114
123
}
115
124
}
@@ -127,19 +136,11 @@ pub extern "C" fn rustls_certified_key_free(config: *const rustls_certified_key)
127
136
// To free the certified_key, we reconstruct the Arc. It should have a refcount of 1,
128
137
// representing the C code's copy. When it drops, that refcount will go down to 0
129
138
// and the inner ServerConfig will be dropped.
130
- let arc: Arc <CertifiedKey > = unsafe { Arc :: from_raw( key) } ;
131
- let strong_count = Arc :: strong_count( & arc) ;
132
- if strong_count < 1 {
133
- eprintln!(
134
- "rustls_certified_key_free: invariant failed: arc.strong_count was < 1: {}. \
135
- You must not free the same certified_key multiple times.",
136
- strong_count
137
- ) ;
138
- }
139
+ unsafe { drop( Arc :: from_raw( key) ) } ;
139
140
}
140
141
}
141
142
142
- pub ( crate ) fn certified_key_build (
143
+ fn certified_key_build (
143
144
cert_chain : * const u8 ,
144
145
cert_chain_len : size_t ,
145
146
private_key : * const u8 ,
0 commit comments