@@ -22,7 +22,7 @@ use crate::hash::Type as MdType;
22
22
use byteorder:: { BigEndian , ByteOrder } ;
23
23
24
24
pub ( crate ) mod dhparam;
25
- mod ec;
25
+ pub mod ec;
26
26
mod rfc6979;
27
27
28
28
use self :: rfc6979:: Rfc6979Rng ;
@@ -132,6 +132,7 @@ const CUSTOM_PK_INFO: pk_info_t = {
132
132
}
133
133
} ;
134
134
135
+ // If this changes then certificate.rs unsafe code in public_key needs to also change.
135
136
define ! (
136
137
#[ c_ty( pk_context) ]
137
138
#[ repr( C ) ]
@@ -142,6 +143,97 @@ define!(
142
143
impl <' a> UnsafeFrom <ptr> { }
143
144
) ;
144
145
146
+ impl Into < * mut mbedtls_sys:: pk_context > for & Pk {
147
+ fn into ( self ) -> * mut mbedtls_sys:: pk_context {
148
+ & self . inner as * const _ as * mut _
149
+ }
150
+ }
151
+
152
+
153
+ //
154
+ // Thread safety analysis for Pk.
155
+ //
156
+ // A. Usage example of Pk.
157
+ //
158
+ // 1.1. Common use case is to to pass it as parameter to the SSL Config class.
159
+ // 1.2. SSL Config class is then used by multiple Context classes (one for each connection)
160
+ // 1.3. Context classes, handled by different threads will do calls towards Pk.
161
+ //
162
+ // Since this is a common use case for MbedTLS it should be thread safe if threading is enabled.
163
+ //
164
+ // B. Verifying thread safety.
165
+ //
166
+ // 1. Calls towards the specific Pk implementation are done via function pointers.
167
+ //
168
+ // - Example call towards Pk:
169
+ // ../../../mbedtls-sys/vendor/library/ssl_srv.c:3707 - mbedtls_pk_decrypt( private_key, p, len, ...
170
+ // - This calls a generic function pointer via:
171
+ // ../../../mbedtls-sys/vendor/crypto/library/pk.c:475 - return( ctx->pk_info->decrypt_func( ctx->pk_ctx, input, ilen,
172
+ //
173
+ // 2. Pk implementation types.
174
+ //
175
+ // - The function pointers are defined via function:
176
+ // ../../../mbedtls-sys/vendor/crypto/library/pk.c:115 - mbedtls_pk_info_from_type
177
+ // - They are as follows: mbedtls_rsa_info / mbedtls_eckey_info / mbedtls_ecdsa_info
178
+ // - These are defined in:
179
+ // ../../../mbedtls-sys/vendor/crypto/library/pk_wrap.c:196
180
+ //
181
+ // C. Checking types one by one.
182
+ //
183
+ // 1. RSA: mbedtls_rsa_info at ../../../mbedtls-sys/vendor/crypto/library/pk_wrap.c:196
184
+ // This uses internal locks in: ../../../mbedtls-sys/vendor/crypto/library/rsa.c:718
185
+ //
186
+ // 2. ECKEY: mbedtls_eckey_info at ../../../mbedtls-sys/vendor/crypto/library/pk_wrap.c:418
187
+ // This does not use internal locks but avoids interior mutability.
188
+ //
189
+ // Function checks one by one:
190
+ // - Only const access to context: eckey_check_pair, eckey_get_bitlen, eckey_can_do, eckey_check_pair
191
+ //
192
+ // - Const acccess / copies context to a stack based variable
193
+ // eckey_verify_wrap, eckey_sign_wrap: ../../../mbedtls-sys/vendor/crypto/library/pk_wrap.c:251
194
+ // creates a stack ecdsa variable and uses ctx to initialize it.
195
+ // ctx is passed as 'key', a const pointer to mbedtls_ecdsa_from_keypair( &ecdsa, ctx )
196
+ // ../../../mbedtls-sys/vendor/crypto/library/ecdsa.c:819
197
+ // int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key )
198
+ // key does not mutate.
199
+ //
200
+ // - Ignored due to not defined: eckey_verify_rs_wrap, eckey_sign_rs_wrap
201
+ // (Undefined - MBEDTLS_ECP_RESTARTABLE - ../../../mbedtls-sys/build/config.rs:173)
202
+ //
203
+ // - Only used when creating/freeing - which is safe by design - eckey_alloc_wrap / eckey_free_wrap
204
+ //
205
+ // 3. ECDSA: mbedtls_ecdsa_info at ../../../mbedtls-sys/vendor/crypto/library/pk_wrap.c:729
206
+ // This does not use internal locks but avoids interior mutability.
207
+ //
208
+ // - Const access / copies context to stack based variables:
209
+ // ecdsa_verify_wrap: ../../../mbedtls-sys/vendor/crypto/library/pk_wrap.c:544
210
+ // This copies the public key on the stack - in buf[] and copies the group id and nbits.
211
+ // That is done via: mbedtls_pk_write_pubkey( &p, buf, &key ) where key.pk_ctx = ctx;
212
+ // And the key is a const parameter to mbedtls_pk_write_pubkey - ../../../mbedtls-sys/vendor/crypto/library/pkwrite.c:158
213
+ //
214
+ // - Const access with additional notes due to call stacks involved.
215
+ //
216
+ // ecdsa_sign_wrap: ../../../mbedtls-sys/vendor/crypto/library/pk_wrap.c:657
217
+ // mbedtls_ecdsa_write_signature ../../../mbedtls-sys/vendor/crypto/library/ecdsa.c:688
218
+ // mbedtls_ecdsa_write_signature_restartable ../../../mbedtls-sys/vendor/crypto/library/ecdsa.c:640
219
+ // MBEDTLS_ECDSA_DETERMINISTIC is not defined.
220
+ // MBEDTLS_ECDSA_SIGN_ALT is not defined.
221
+ // Passes grp to: ecdsa_sign_restartable: ../../../mbedtls-sys/vendor/crypto/library/ecdsa.c:253
222
+ // Const access to group - reads parameters, passed as const to mbedtls_ecp_gen_privkey,
223
+ // mbedtls_ecp_mul_restartable: ../../../mbedtls-sys/vendor/crypto/library/ecp.c:2351
224
+ // MBEDTLS_ECP_INTERNAL_ALT is not defined. (otherwise it might not be safe depending on ecp_init/ecp_free) ../../../mbedtls-sys/build/config.rs:131
225
+ // Passes as const to: mbedtls_ecp_check_privkey / mbedtls_ecp_check_pubkey / mbedtls_ecp_get_type( grp
226
+ //
227
+ // - Ignored due to not defined: ecdsa_verify_rs_wrap, ecdsa_sign_rs_wrap, ecdsa_rs_alloc, ecdsa_rs_free
228
+ // (Undefined - MBEDTLS_ECP_RESTARTABLE - ../../../mbedtls-sys/build/config.rs:173)
229
+ //
230
+ // - Only const access to context: eckey_check_pair
231
+ //
232
+ // - Only used when creating/freeing - which is safe by design: ecdsa_alloc_wrap, ecdsa_free_wrap
233
+ //
234
+ #[ cfg( feature = "threading" ) ]
235
+ unsafe impl Sync for Pk { }
236
+
145
237
impl Pk {
146
238
/// Takes both DER and PEM forms of PKCS#1 or PKCS#8 encoded keys.
147
239
///
@@ -323,11 +415,13 @@ impl Pk {
323
415
. is_ok ( )
324
416
}
325
417
326
- getter ! (
327
- /// Key length in bits
328
- len( ) -> usize = fn pk_get_bitlen
329
- ) ;
330
- getter ! ( pk_type( ) -> Type = fn pk_get_type) ;
418
+ pub fn len ( & self ) -> usize {
419
+ unsafe { pk_get_bitlen ( & self . inner ) }
420
+ }
421
+
422
+ pub fn pk_type ( & self ) -> Type {
423
+ unsafe { pk_get_type ( & self . inner ) . into ( ) }
424
+ }
331
425
332
426
pub fn curve ( & self ) -> Result < EcGroupId > {
333
427
match self . pk_type ( ) {
@@ -692,7 +786,7 @@ impl Pk {
692
786
sig : & mut [ u8 ] ,
693
787
rng : & mut F ,
694
788
) -> Result < usize > {
695
- use crate :: rng:: RngCallback ;
789
+ use crate :: rng:: RngCallbackMut ;
696
790
697
791
if self . pk_type ( ) == Type :: Ecdsa || self . pk_type ( ) == Type :: Eckey {
698
792
if sig. len ( ) < ECDSA_MAX_LEN {
@@ -717,8 +811,8 @@ impl Pk {
717
811
hash. len ( ) ,
718
812
sig. as_mut_ptr ( ) ,
719
813
& mut ret,
720
- Some ( Rfc6979Rng :: call ) ,
721
- rng. data_ptr ( ) ,
814
+ Some ( Rfc6979Rng :: call_mut ) ,
815
+ rng. data_ptr_mut ( ) ,
722
816
) . into_result ( ) ?;
723
817
} ;
724
818
Ok ( ret)
0 commit comments