@@ -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
@@ -188,6 +190,44 @@ fn ssl_get_default_verify_paths() -> (String, String, String, String) {
188
190
}
189
191
}
190
192
193
+ fn ssl_rand_status ( ) -> i32 {
194
+ unsafe { sys:: RAND_status ( ) }
195
+ }
196
+
197
+ fn ssl_rand_add ( string : Either < PyStringRef , PyBytesLike > , entropy : f64 ) {
198
+ let f = |b : & [ u8 ] | {
199
+ for buf in b. chunks ( libc:: c_int:: max_value ( ) as usize ) {
200
+ unsafe { sys:: RAND_add ( buf. as_ptr ( ) as * const _ , buf. len ( ) as _ , entropy) }
201
+ }
202
+ } ;
203
+ match string {
204
+ Either :: A ( s) => f ( s. as_str ( ) . as_bytes ( ) ) ,
205
+ Either :: B ( b) => b. with_ref ( f) ,
206
+ }
207
+ }
208
+
209
+ fn ssl_rand_bytes ( n : i32 , vm : & VirtualMachine ) -> PyResult < Vec < u8 > > {
210
+ if n < 0 {
211
+ return Err ( vm. new_value_error ( "num must be positive" . to_owned ( ) ) ) ;
212
+ }
213
+ let mut buf = vec ! [ 0 ; n as usize ] ;
214
+ openssl:: rand:: rand_bytes ( & mut buf)
215
+ . map ( |( ) | buf)
216
+ . map_err ( |e| convert_openssl_error ( vm, e) )
217
+ }
218
+
219
+ fn ssl_rand_pseudo_bytes ( n : i32 , vm : & VirtualMachine ) -> PyResult < ( Vec < u8 > , bool ) > {
220
+ if n < 0 {
221
+ return Err ( vm. new_value_error ( "num must be positive" . to_owned ( ) ) ) ;
222
+ }
223
+ let mut buf = vec ! [ 0 ; n as usize ] ;
224
+ let ret = unsafe { sys:: RAND_pseudo_bytes ( buf. as_mut_ptr ( ) , n) } ;
225
+ match ret {
226
+ 0 | 1 => Ok ( ( buf, ret == 1 ) ) ,
227
+ _ => Err ( convert_openssl_error ( vm, openssl:: error:: ErrorStack :: get ( ) ) ) ,
228
+ }
229
+ }
230
+
191
231
#[ pyclass( name = "_SSLContext" ) ]
192
232
struct PySslContext {
193
233
ctx : RefCell < SslContextBuilder > ,
@@ -500,7 +540,6 @@ impl PySslSocket {
500
540
501
541
#[ pymethod]
502
542
fn do_handshake ( & self , vm : & VirtualMachine ) -> PyResult < ( ) > {
503
- use crate :: pyobject:: Either ;
504
543
// Either a stream builder or a mid-handshake stream from WANT_READ or WANT_WRITE
505
544
let mut handshaker: Either < _ , ssl:: MidHandshakeSslStream < _ > > =
506
545
Either :: A ( self . stream_builder ( ) ) ;
@@ -605,6 +644,10 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
605
644
"txt2obj" => ctx. new_function( ssl_txt2obj) ,
606
645
"nid2obj" => ctx. new_function( ssl_nid2obj) ,
607
646
"get_default_verify_paths" => ctx. new_function( ssl_get_default_verify_paths) ,
647
+ "RAND_status" => ctx. new_function( ssl_rand_status) ,
648
+ "RAND_add" => ctx. new_function( ssl_rand_add) ,
649
+ "RAND_bytes" => ctx. new_function( ssl_rand_bytes) ,
650
+ "RAND_pseudo_bytes" => ctx. new_function( ssl_rand_pseudo_bytes) ,
608
651
609
652
// Constants
610
653
"OPENSSL_VERSION" => ctx. new_str( openssl:: version:: version( ) . to_owned( ) ) ,
0 commit comments