@@ -7,7 +7,7 @@ use crate::obj::objbytes::PyBytesRef;
7
7
use crate :: obj:: objstr:: { PyString , PyStringRef } ;
8
8
use crate :: obj:: { objtype:: PyClassRef , objweakref:: PyWeak } ;
9
9
use crate :: pyobject:: {
10
- IntoPyObject , PyClassImpl , PyObjectRef , PyRef , PyResult , PyValue , TryFromObject ,
10
+ Either , IntoPyObject , PyClassImpl , PyObjectRef , PyRef , PyResult , PyValue , TryFromObject ,
11
11
} ;
12
12
use crate :: types:: create_type;
13
13
use crate :: VirtualMachine ;
@@ -25,7 +25,7 @@ use openssl::{
25
25
} ;
26
26
27
27
mod sys {
28
- use libc:: { c_char, c_int} ;
28
+ use libc:: { c_char, c_double , c_int, c_void } ;
29
29
pub use openssl_sys:: * ;
30
30
extern "C" {
31
31
pub fn OBJ_txt2obj ( s : * const c_char , no_name : c_int ) -> * mut ASN1_OBJECT ;
@@ -38,6 +38,8 @@ mod sys {
38
38
pub fn X509_get_default_cert_dir_env ( ) -> * const c_char ;
39
39
pub fn X509_get_default_cert_dir ( ) -> * const c_char ;
40
40
pub fn SSL_CTX_set_post_handshake_auth ( ctx : * mut SSL_CTX , val : c_int ) ;
41
+ pub fn RAND_add ( buf : * const c_void , num : c_int , randomness : c_double ) ;
42
+ pub fn RAND_pseudo_bytes ( buf : * const u8 , num : c_int ) -> c_int ;
41
43
}
42
44
}
43
45
@@ -190,6 +192,44 @@ fn ssl_get_default_verify_paths() -> (String, String, String, String) {
190
192
}
191
193
}
192
194
195
+ fn ssl_rand_status ( ) -> i32 {
196
+ unsafe { sys:: RAND_status ( ) }
197
+ }
198
+
199
+ fn ssl_rand_add ( string : Either < PyStringRef , PyBytesLike > , entropy : f64 ) {
200
+ let f = |b : & [ u8 ] | {
201
+ for buf in b. chunks ( libc:: c_int:: max_value ( ) as usize ) {
202
+ unsafe { sys:: RAND_add ( buf. as_ptr ( ) as * const _ , buf. len ( ) as _ , entropy) }
203
+ }
204
+ } ;
205
+ match string {
206
+ Either :: A ( s) => f ( s. as_str ( ) . as_bytes ( ) ) ,
207
+ Either :: B ( b) => b. with_ref ( f) ,
208
+ }
209
+ }
210
+
211
+ fn ssl_rand_bytes ( n : i32 , vm : & VirtualMachine ) -> PyResult < Vec < u8 > > {
212
+ if n < 0 {
213
+ return Err ( vm. new_value_error ( "num must be positive" . to_owned ( ) ) ) ;
214
+ }
215
+ let mut buf = vec ! [ 0 ; n as usize ] ;
216
+ openssl:: rand:: rand_bytes ( & mut buf)
217
+ . map ( |( ) | buf)
218
+ . map_err ( |e| convert_openssl_error ( vm, e) )
219
+ }
220
+
221
+ fn ssl_rand_pseudo_bytes ( n : i32 , vm : & VirtualMachine ) -> PyResult < ( Vec < u8 > , bool ) > {
222
+ if n < 0 {
223
+ return Err ( vm. new_value_error ( "num must be positive" . to_owned ( ) ) ) ;
224
+ }
225
+ let mut buf = vec ! [ 0 ; n as usize ] ;
226
+ let ret = unsafe { sys:: RAND_pseudo_bytes ( buf. as_mut_ptr ( ) , n) } ;
227
+ match ret {
228
+ 0 | 1 => Ok ( ( buf, ret == 1 ) ) ,
229
+ _ => Err ( convert_openssl_error ( vm, openssl:: error:: ErrorStack :: get ( ) ) ) ,
230
+ }
231
+ }
232
+
193
233
#[ pyclass( name = "_SSLContext" ) ]
194
234
struct PySslContext {
195
235
ctx : RefCell < SslContextBuilder > ,
@@ -502,7 +542,6 @@ impl PySslSocket {
502
542
503
543
#[ pymethod]
504
544
fn do_handshake ( & self , vm : & VirtualMachine ) -> PyResult < ( ) > {
505
- use crate :: pyobject:: Either ;
506
545
// Either a stream builder or a mid-handshake stream from WANT_READ or WANT_WRITE
507
546
let mut handshaker: Either < _ , ssl:: MidHandshakeSslStream < _ > > =
508
547
Either :: A ( self . stream_builder ( ) ) ;
@@ -607,6 +646,10 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
607
646
"txt2obj" => ctx. new_function( ssl_txt2obj) ,
608
647
"nid2obj" => ctx. new_function( ssl_nid2obj) ,
609
648
"get_default_verify_paths" => ctx. new_function( ssl_get_default_verify_paths) ,
649
+ "RAND_status" => ctx. new_function( ssl_rand_status) ,
650
+ "RAND_add" => ctx. new_function( ssl_rand_add) ,
651
+ "RAND_bytes" => ctx. new_function( ssl_rand_bytes) ,
652
+ "RAND_pseudo_bytes" => ctx. new_function( ssl_rand_pseudo_bytes) ,
610
653
611
654
// Constants
612
655
"OPENSSL_VERSION" => ctx. new_str( openssl:: version:: version( ) . to_owned( ) ) ,
0 commit comments