From 64106c4d3d4ddba8c7bc2af75376e6d3d3d75601 Mon Sep 17 00:00:00 2001
From:
Date: Mon, 29 Jun 2015 20:16:15 +0000
Subject: Update documentation
---
src/openssl/asn1/mod.rs.html | 195 ++++
src/openssl/bio/mod.rs.html | 309 ++++++
src/openssl/bn/mod.rs.html | 1305 +++++++++++++++++++++++
src/openssl/crypto/hash.rs.html | 773 ++++++++++++++
src/openssl/crypto/hmac.rs.html | 1053 +++++++++++++++++++
src/openssl/crypto/memcmp.rs.html | 175 ++++
src/openssl/crypto/mod.rs.html | 145 +++
src/openssl/crypto/pkcs5.rs.html | 335 ++++++
src/openssl/crypto/pkey.rs.html | 1103 ++++++++++++++++++++
src/openssl/crypto/rand.rs.html | 151 +++
src/openssl/crypto/symm.rs.html | 721 +++++++++++++
src/openssl/lib.rs.html | 147 +++
src/openssl/nid.rs.html | 437 ++++++++
src/openssl/ssl/error.rs.html | 373 +++++++
src/openssl/ssl/mod.rs.html | 2079 +++++++++++++++++++++++++++++++++++++
src/openssl/x509/mod.rs.html | 1461 ++++++++++++++++++++++++++
16 files changed, 10762 insertions(+)
create mode 100644 src/openssl/asn1/mod.rs.html
create mode 100644 src/openssl/bio/mod.rs.html
create mode 100644 src/openssl/bn/mod.rs.html
create mode 100644 src/openssl/crypto/hash.rs.html
create mode 100644 src/openssl/crypto/hmac.rs.html
create mode 100644 src/openssl/crypto/memcmp.rs.html
create mode 100644 src/openssl/crypto/mod.rs.html
create mode 100644 src/openssl/crypto/pkcs5.rs.html
create mode 100644 src/openssl/crypto/pkey.rs.html
create mode 100644 src/openssl/crypto/rand.rs.html
create mode 100644 src/openssl/crypto/symm.rs.html
create mode 100644 src/openssl/lib.rs.html
create mode 100644 src/openssl/nid.rs.html
create mode 100644 src/openssl/ssl/error.rs.html
create mode 100644 src/openssl/ssl/mod.rs.html
create mode 100644 src/openssl/x509/mod.rs.html
(limited to 'src/openssl')
diff --git a/src/openssl/asn1/mod.rs.html b/src/openssl/asn1/mod.rs.html
new file mode 100644
index 0000000..5d7d165
--- /dev/null
+++ b/src/openssl/asn1/mod.rs.html
@@ -0,0 +1,195 @@
+
+
+
+
+
+
+
+
+
+ mod.rs.html -- source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+
+use libc ::{c_long };
+use std ::ptr ;
+
+use ffi ;
+use ssl ::error ::{SslError };
+
+
+pub struct Asn1Time {
+ handle : * mut ffi ::ASN1_TIME ,
+ owned : bool
+}
+
+impl Asn1Time {
+
+ pub fn new (handle : * mut ffi ::ASN1_TIME ) -> Asn1Time {
+ Asn1Time {
+ handle : handle ,
+ owned : true
+ }
+ }
+
+ fn new_with_period (period : u64 ) -> Result < Asn1Time , SslError > {
+ ffi ::init ();
+
+ let handle = unsafe {
+ try_ssl_null ! (ffi ::X509_gmtime_adj (ptr ::null_mut (),
+ period as c_long ))
+ };
+ Ok (Asn1Time ::new (handle ))
+ }
+
+
+ pub fn days_from_now (days : u32 ) -> Result < Asn1Time , SslError > {
+ Asn1Time ::new_with_period (days as u64 * 60 * 60 * 24 )
+ }
+
+
+ pub unsafe fn get_handle (& self ) -> * mut ffi ::ASN1_TIME {
+ return self .handle
+ }
+}
+
+impl Drop for Asn1Time {
+ fn drop (& mut self ) {
+ if self .owned {
+ unsafe { ffi ::ASN1_TIME_free (self .handle ) };
+ }
+ }
+}
+
+
+
+
+
+
+
+
+
Keyboard shortcuts
+
+ ?
+ Show this help dialog
+ S
+ Focus the search field
+ ⇤
+ Move up in search results
+ ⇥
+ Move down in search results
+ ⏎
+ Go to active search result
+
+
+
+
Search tricks
+
+ Prefix searches with a type followed by a colon (e.g.
+ fn:
) to restrict the search to a given type.
+
+
+ Accepted types are: fn
, mod
,
+ struct
, enum
,
+ trait
, typedef
(or
+ tdef
).
+
+
+ Search functions by type signature (e.g.
+ vec -> usize
)
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/openssl/bio/mod.rs.html b/src/openssl/bio/mod.rs.html
new file mode 100644
index 0000000..0d8a555
--- /dev/null
+++ b/src/openssl/bio/mod.rs.html
@@ -0,0 +1,309 @@
+
+
+
+
+
+
+
+
+
+ mod.rs.html -- source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+
+use libc ::{c_void , c_int };
+use std ::io ;
+use std ::io ::prelude ::* ;
+use std ::ptr ;
+use std ::cmp ;
+
+use ffi ;
+use ssl ::error ::{SslError };
+
+pub struct MemBio {
+ bio : * mut ffi ::BIO ,
+ owned : bool
+}
+
+impl Drop for MemBio {
+ fn drop (& mut self ) {
+ if self .owned {
+ unsafe {
+ ffi ::BIO_free_all (self .bio );
+ }
+ }
+ }
+}
+
+impl MemBio {
+
+ pub fn new () -> Result < MemBio , SslError > {
+ ffi ::init ();
+
+ let bio = unsafe { ffi ::BIO_new (ffi ::BIO_s_mem ()) };
+ try_ssl_null ! (bio );
+
+ Ok (MemBio {
+ bio : bio ,
+ owned : true
+ })
+ }
+
+
+ pub fn borrowed (bio : * mut ffi ::BIO ) -> MemBio {
+ MemBio {
+ bio : bio ,
+ owned : false
+ }
+ }
+
+
+
+
+ pub unsafe fn unwrap (mut self ) -> * mut ffi ::BIO {
+ self .owned = false ;
+ self .bio
+ }
+
+
+ pub unsafe fn get_handle (& self ) -> * mut ffi ::BIO {
+ self .bio
+ }
+
+
+ pub fn set_eof (& self , eof : bool ) {
+ let v = if eof { 0 } else { - 1 };
+ unsafe { ffi ::BIO_set_mem_eof_return (self .bio , v ); }
+ }
+}
+
+impl Read for MemBio {
+ fn read (& mut self , buf : & mut [u8 ]) -> io ::Result < usize > {
+ let len = cmp ::min (c_int ::max_value () as usize , buf .len ()) as c_int ;
+ let ret = unsafe {
+ ffi ::BIO_read (self .bio , buf .as_ptr () as * mut c_void , len )
+ };
+
+ if ret <= 0 {
+ let is_eof = unsafe { ffi ::BIO_eof (self .bio ) };
+ if is_eof {
+ Ok (0 )
+ } else {
+ Err (io ::Error ::new (io ::ErrorKind ::Other ,
+ SslError ::get ()))
+ }
+ } else {
+ Ok (ret as usize )
+ }
+ }
+}
+
+impl Write for MemBio {
+ fn write (& mut self , buf : & [u8 ]) -> io ::Result < usize > {
+ let len = cmp ::min (c_int ::max_value () as usize , buf .len ()) as c_int ;
+ let ret = unsafe {
+ ffi ::BIO_write (self .bio , buf .as_ptr () as * const c_void , len )
+ };
+
+ if ret < 0 {
+ Err (io ::Error ::new (io ::ErrorKind ::Other ,
+ SslError ::get ()))
+ } else {
+ Ok (ret as usize )
+ }
+ }
+
+ fn flush (& mut self ) -> io ::Result < ()> {
+ Ok (())
+ }
+}
+
+
+
+
+
+
+
+
+
Keyboard shortcuts
+
+ ?
+ Show this help dialog
+ S
+ Focus the search field
+ ⇤
+ Move up in search results
+ ⇥
+ Move down in search results
+ ⏎
+ Go to active search result
+
+
+
+
Search tricks
+
+ Prefix searches with a type followed by a colon (e.g.
+ fn:
) to restrict the search to a given type.
+
+
+ Accepted types are: fn
, mod
,
+ struct
, enum
,
+ trait
, typedef
(or
+ tdef
).
+
+
+ Search functions by type signature (e.g.
+ vec -> usize
)
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/openssl/bn/mod.rs.html b/src/openssl/bn/mod.rs.html
new file mode 100644
index 0000000..f57f83e
--- /dev/null
+++ b/src/openssl/bn/mod.rs.html
@@ -0,0 +1,1305 @@
+
+
+
+
+
+
+
+
+
+ mod.rs.html -- source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+
+use libc ::{c_int , c_ulong , c_void };
+use std ::ffi ::{CStr , CString };
+use std ::cmp ::Ordering ;
+use std ::{fmt , ptr };
+
+use ffi ;
+use ssl ::error ::SslError ;
+
+pub struct BigNum (* mut ffi ::BIGNUM );
+
+#[derive (Copy , Clone )]
+#[repr (C )]
+pub enum RNGProperty {
+ MsbMaybeZero = - 1 ,
+ MsbOne = 0 ,
+ TwoMsbOne = 1 ,
+}
+
+macro_rules ! with_ctx (
+ ($ name :ident , $ action :block ) => ({
+ let $ name = ffi ::BN_CTX_new ();
+ if ($ name ).is_null () {
+ Err (SslError ::get ())
+ } else {
+ let r = $ action ;
+ ffi ::BN_CTX_free ($ name );
+ r
+ }
+ });
+);
+
+macro_rules ! with_bn (
+ ($ name :ident , $ action :block ) => ({
+ let tmp = BigNum ::new ();
+ match tmp {
+ Ok ($ name ) => {
+ if $ action {
+ Ok ($ name )
+ } else {
+ Err (SslError ::get ())
+ }
+ },
+ Err (err ) => Err (err ),
+ }
+ });
+);
+
+macro_rules ! with_bn_in_ctx (
+ ($ name :ident , $ ctx_name :ident , $ action :block ) => ({
+ let tmp = BigNum ::new ();
+ match tmp {
+ Ok ($ name ) => {
+ let $ ctx_name = ffi ::BN_CTX_new ();
+ if ($ ctx_name ).is_null () {
+ Err (SslError ::get ())
+ } else {
+ let r =
+ if $ action {
+ Ok ($ name )
+ } else {
+ Err (SslError ::get ())
+ };
+ ffi ::BN_CTX_free ($ ctx_name );
+ r
+ }
+ },
+ Err (err ) => Err (err ),
+ }
+ });
+);
+
+impl BigNum {
+ pub fn new () -> Result < BigNum , SslError > {
+ unsafe {
+ ffi ::init ();
+
+ let v = try_ssl_null ! (ffi ::BN_new ());
+ Ok (BigNum (v ))
+ }
+ }
+
+ pub fn new_from (n : u64 ) -> Result < BigNum , SslError > {
+ BigNum ::new ().and_then (| v | unsafe {
+ try_ssl ! (ffi ::BN_set_word (v .raw (), n as c_ulong ));
+ Ok (v )
+ })
+ }
+
+ pub fn from_dec_str (s : & str ) -> Result < BigNum , SslError > {
+ BigNum ::new ().and_then (| v | unsafe {
+ let c_str = CString ::new (s .as_bytes ()).unwrap ();
+ try_ssl ! (ffi ::BN_dec2bn (v .raw_ptr (), c_str .as_ptr ()));
+ Ok (v )
+ })
+ }
+
+ pub fn from_hex_str (s : & str ) -> Result < BigNum , SslError > {
+ BigNum ::new ().and_then (| v | unsafe {
+ let c_str = CString ::new (s .as_bytes ()).unwrap ();
+ try_ssl ! (ffi ::BN_hex2bn (v .raw_ptr (), c_str .as_ptr ()));
+ Ok (v )
+ })
+ }
+
+ pub fn new_from_slice (n : & [u8 ]) -> Result < BigNum , SslError > {
+ BigNum ::new ().and_then (| v | unsafe {
+ try_ssl_null ! (ffi ::BN_bin2bn (n .as_ptr (), n .len () as c_int , v .raw ()));
+ Ok (v )
+ })
+ }
+
+ pub fn checked_sqr (& self ) -> Result < BigNum , SslError > {
+ unsafe {
+ with_bn_in_ctx ! (r , ctx , { ffi ::BN_sqr (r .raw (), self .raw (), ctx ) == 1 })
+ }
+ }
+
+ pub fn checked_nnmod (& self , n : & BigNum ) -> Result < BigNum , SslError > {
+ unsafe {
+ with_bn_in_ctx ! (r , ctx , { ffi ::BN_nnmod (r .raw (), self .raw (), n .raw (), ctx ) == 1 })
+ }
+ }
+
+ pub fn checked_mod_add (& self , a : & BigNum , n : & BigNum ) -> Result < BigNum , SslError > {
+ unsafe {
+ with_bn_in_ctx ! (r , ctx , { ffi ::BN_mod_add (r .raw (), self .raw (), a .raw (), n .raw (), ctx ) == 1 })
+ }
+ }
+
+ pub fn checked_mod_sub (& self , a : & BigNum , n : & BigNum ) -> Result < BigNum , SslError > {
+ unsafe {
+ with_bn_in_ctx ! (r , ctx , { ffi ::BN_mod_sub (r .raw (), self .raw (), a .raw (), n .raw (), ctx ) == 1 })
+ }
+ }
+
+ pub fn checked_mod_mul (& self , a : & BigNum , n : & BigNum ) -> Result < BigNum , SslError > {
+ unsafe {
+ with_bn_in_ctx ! (r , ctx , { ffi ::BN_mod_mul (r .raw (), self .raw (), a .raw (), n .raw (), ctx ) == 1 })
+ }
+ }
+
+ pub fn checked_mod_sqr (& self , n : & BigNum ) -> Result < BigNum , SslError > {
+ unsafe {
+ with_bn_in_ctx ! (r , ctx , { ffi ::BN_mod_sqr (r .raw (), self .raw (), n .raw (), ctx ) == 1 })
+ }
+ }
+
+ pub fn checked_exp (& self , p : & BigNum ) -> Result < BigNum , SslError > {
+ unsafe {
+ with_bn_in_ctx ! (r , ctx , { ffi ::BN_exp (r .raw (), self .raw (), p .raw (), ctx ) == 1 })
+ }
+ }
+
+ pub fn checked_mod_exp (& self , p : & BigNum , n : & BigNum ) -> Result < BigNum , SslError > {
+ unsafe {
+ with_bn_in_ctx ! (r , ctx , { ffi ::BN_mod_exp (r .raw (), self .raw (), p .raw (), n .raw (), ctx ) == 1 })
+ }
+ }
+
+ pub fn checked_mod_inv (& self , n : & BigNum ) -> Result < BigNum , SslError > {
+ unsafe {
+ with_bn_in_ctx ! (r , ctx , { ! ffi ::BN_mod_inverse (r .raw (), self .raw (), n .raw (), ctx ).is_null () })
+ }
+ }
+
+ pub fn add_word (& mut self , w : c_ulong ) -> Result < (), SslError > {
+ unsafe {
+ if ffi ::BN_add_word (self .raw (), w ) == 1 {
+ Ok (())
+ } else {
+ Err (SslError ::get ())
+ }
+ }
+ }
+
+ pub fn sub_word (& mut self , w : c_ulong ) -> Result < (), SslError > {
+ unsafe {
+ if ffi ::BN_sub_word (self .raw (), w ) == 1 {
+ Ok (())
+ } else {
+ Err (SslError ::get ())
+ }
+ }
+ }
+
+ pub fn mul_word (& mut self , w : c_ulong ) -> Result < (), SslError > {
+ unsafe {
+ if ffi ::BN_mul_word (self .raw (), w ) == 1 {
+ Ok (())
+ } else {
+ Err (SslError ::get ())
+ }
+ }
+ }
+
+ pub fn div_word (& mut self , w : c_ulong ) -> Result < c_ulong , SslError > {
+ unsafe {
+ let result = ffi ::BN_div_word (self .raw (), w );
+ if result != ! 0 as c_ulong {
+ Ok (result )
+ } else {
+ Err (SslError ::get ())
+ }
+ }
+ }
+
+ pub fn mod_word (& self , w : c_ulong ) -> Result < c_ulong , SslError > {
+ unsafe {
+ let result = ffi ::BN_mod_word (self .raw (), w );
+ if result != ! 0 as c_ulong {
+ Ok (result )
+ } else {
+ Err (SslError ::get ())
+ }
+ }
+ }
+
+ pub fn checked_gcd (& self , a : & BigNum ) -> Result < BigNum , SslError > {
+ unsafe {
+ with_bn_in_ctx ! (r , ctx , { ffi ::BN_gcd (r .raw (), self .raw (), a .raw (), ctx ) == 1 })
+ }
+ }
+
+ pub fn checked_generate_prime (bits : i32 , safe : bool , add : Option < & BigNum > , rem : Option < & BigNum > ) -> Result < BigNum , SslError > {
+ unsafe {
+ with_bn_in_ctx ! (r , ctx , {
+ let add_arg = add .map (| a | a .raw ()).unwrap_or (ptr ::null_mut ());
+ let rem_arg = rem .map (| r | r .raw ()).unwrap_or (ptr ::null_mut ());
+
+ ffi ::BN_generate_prime_ex (r .raw (), bits as c_int , safe as c_int , add_arg , rem_arg , ptr ::null ()) == 1
+ })
+ }
+ }
+
+ pub fn is_prime (& self , checks : i32 ) -> Result < bool , SslError > {
+ unsafe {
+ with_ctx ! (ctx , {
+ Ok (ffi ::BN_is_prime_ex (self .raw (), checks as c_int , ctx , ptr ::null ()) == 1 )
+ })
+ }
+ }
+
+ pub fn is_prime_fast (& self , checks : i32 , do_trial_division : bool ) -> Result < bool , SslError > {
+ unsafe {
+ with_ctx ! (ctx , {
+ Ok (ffi ::BN_is_prime_fasttest_ex (self .raw (), checks as c_int , ctx , do_trial_division as c_int , ptr ::null ()) == 1 )
+ })
+ }
+ }
+
+ pub fn checked_new_random (bits : i32 , prop : RNGProperty , odd : bool ) -> Result < BigNum , SslError > {
+ unsafe {
+ with_bn_in_ctx ! (r , ctx , { ffi ::BN_rand (r .raw (), bits as c_int , prop as c_int , odd as c_int ) == 1 })
+ }
+ }
+
+ pub fn checked_new_pseudo_random (bits : i32 , prop : RNGProperty , odd : bool ) -> Result < BigNum , SslError > {
+ unsafe {
+ with_bn_in_ctx ! (r , ctx , { ffi ::BN_pseudo_rand (r .raw (), bits as c_int , prop as c_int , odd as c_int ) == 1 })
+ }
+ }
+
+ pub fn checked_rand_in_range (& self ) -> Result < BigNum , SslError > {
+ unsafe {
+ with_bn_in_ctx ! (r , ctx , { ffi ::BN_rand_range (r .raw (), self .raw ()) == 1 })
+ }
+ }
+
+ pub fn checked_pseudo_rand_in_range (& self ) -> Result < BigNum , SslError > {
+ unsafe {
+ with_bn_in_ctx ! (r , ctx , { ffi ::BN_pseudo_rand_range (r .raw (), self .raw ()) == 1 })
+ }
+ }
+
+ pub fn set_bit (& mut self , n : i32 ) -> Result < (), SslError > {
+ unsafe {
+ if ffi ::BN_set_bit (self .raw (), n as c_int ) == 1 {
+ Ok (())
+ } else {
+ Err (SslError ::get ())
+ }
+ }
+ }
+
+ pub fn clear_bit (& mut self , n : i32 ) -> Result < (), SslError > {
+ unsafe {
+ if ffi ::BN_clear_bit (self .raw (), n as c_int ) == 1 {
+ Ok (())
+ } else {
+ Err (SslError ::get ())
+ }
+ }
+ }
+
+ pub fn is_bit_set (& self , n : i32 ) -> bool {
+ unsafe {
+ ffi ::BN_is_bit_set (self .raw (), n as c_int ) == 1
+ }
+ }
+
+ pub fn mask_bits (& mut self , n : i32 ) -> Result < (), SslError > {
+ unsafe {
+ if ffi ::BN_mask_bits (self .raw (), n as c_int ) == 1 {
+ Ok (())
+ } else {
+ Err (SslError ::get ())
+ }
+ }
+ }
+
+ pub fn checked_shl1 (& self ) -> Result < BigNum , SslError > {
+ unsafe {
+ with_bn ! (r , { ffi ::BN_lshift1 (r .raw (), self .raw ()) == 1 })
+ }
+ }
+
+ pub fn checked_shr1 (& self ) -> Result < BigNum , SslError > {
+ unsafe {
+ with_bn ! (r , { ffi ::BN_rshift1 (r .raw (), self .raw ()) == 1 })
+ }
+ }
+
+ pub fn checked_add (& self , a : & BigNum ) -> Result < BigNum , SslError > {
+ unsafe {
+ with_bn ! (r , { ffi ::BN_add (r .raw (), self .raw (), a .raw ()) == 1 })
+ }
+ }
+
+ pub fn checked_sub (& self , a : & BigNum ) -> Result < BigNum , SslError > {
+ unsafe {
+ with_bn ! (r , { ffi ::BN_sub (r .raw (), self .raw (), a .raw ()) == 1 })
+ }
+ }
+
+ pub fn checked_mul (& self , a : & BigNum ) -> Result < BigNum , SslError > {
+ unsafe {
+ with_bn_in_ctx ! (r , ctx , { ffi ::BN_mul (r .raw (), self .raw (), a .raw (), ctx ) == 1 })
+ }
+ }
+
+ pub fn checked_div (& self , a : & BigNum ) -> Result < BigNum , SslError > {
+ unsafe {
+ with_bn_in_ctx ! (r , ctx , { ffi ::BN_div (r .raw (), ptr ::null_mut (), self .raw (), a .raw (), ctx ) == 1 })
+ }
+ }
+
+ pub fn checked_mod (& self , a : & BigNum ) -> Result < BigNum , SslError > {
+ unsafe {
+ with_bn_in_ctx ! (r , ctx , { ffi ::BN_div (ptr ::null_mut (), r .raw (), self .raw (), a .raw (), ctx ) == 1 })
+ }
+ }
+
+ pub fn checked_shl (& self , a : & i32 ) -> Result < BigNum , SslError > {
+ unsafe {
+ with_bn ! (r , { ffi ::BN_lshift (r .raw (), self .raw (), * a as c_int ) == 1 })
+ }
+ }
+
+ pub fn checked_shr (& self , a : & i32 ) -> Result < BigNum , SslError > {
+ unsafe {
+ with_bn ! (r , { ffi ::BN_rshift (r .raw (), self .raw (), * a as c_int ) == 1 })
+ }
+ }
+
+ pub fn negate (& mut self ) {
+ unsafe {
+ ffi ::BN_set_negative (self .raw (), ! self .is_negative () as c_int )
+ }
+ }
+
+ pub fn abs_cmp (& self , oth : BigNum ) -> Ordering {
+ unsafe {
+ let res = ffi ::BN_ucmp (self .raw (), oth .raw ()) as i32 ;
+ if res < 0 {
+ Ordering ::Less
+ } else if res > 0 {
+ Ordering ::Greater
+ } else {
+ Ordering ::Equal
+ }
+ }
+ }
+
+ pub fn is_negative (& self ) -> bool {
+ unsafe {
+ (* self .raw ()).neg == 1
+ }
+ }
+
+ pub fn num_bits (& self ) -> i32 {
+ unsafe {
+ ffi ::BN_num_bits (self .raw ()) as i32
+ }
+ }
+
+ pub fn num_bytes (& self ) -> i32 {
+ (self .num_bits () + 7 ) / 8
+ }
+
+ unsafe fn raw (& self ) -> * mut ffi ::BIGNUM {
+ let BigNum (n ) = * self ;
+ n
+ }
+
+ unsafe fn raw_ptr (& self ) -> * const * mut ffi ::BIGNUM {
+ let BigNum (ref n ) = * self ;
+ n
+ }
+
+ pub fn to_vec (& self ) -> Vec < u8 > {
+ let size = self .num_bytes () as usize ;
+ let mut v = Vec ::with_capacity (size );
+ unsafe {
+ ffi ::BN_bn2bin (self .raw (), v .as_mut_ptr ());
+ v .set_len (size );
+ }
+ v
+ }
+
+ pub fn to_dec_str (& self ) -> String {
+ unsafe {
+ let buf = ffi ::BN_bn2dec (self .raw ());
+ assert ! (! buf .is_null ());
+ let str = String ::from_utf8 (CStr ::from_ptr (buf ).to_bytes ().to_vec ()).unwrap ();
+ ffi ::CRYPTO_free (buf as * mut c_void );
+ str
+ }
+ }
+
+ pub fn to_hex_str (& self ) -> String {
+ unsafe {
+ let buf = ffi ::BN_bn2hex (self .raw ());
+ assert ! (! buf .is_null ());
+ let str = String ::from_utf8 (CStr ::from_ptr (buf ).to_bytes ().to_vec ()).unwrap ();
+ ffi ::CRYPTO_free (buf as * mut c_void );
+ str
+ }
+ }
+}
+
+impl fmt ::Debug for BigNum {
+ fn fmt (& self , f : & mut fmt ::Formatter ) -> fmt ::Result {
+ write ! (f , "{}" , self .to_dec_str ())
+ }
+}
+
+impl Eq for BigNum { }
+impl PartialEq for BigNum {
+ fn eq (& self , oth : & BigNum ) -> bool {
+ unsafe {
+ ffi ::BN_cmp (self .raw (), oth .raw ()) == 0
+ }
+ }
+}
+
+impl Ord for BigNum {
+ fn cmp (& self , oth : & BigNum ) -> Ordering {
+ self .partial_cmp (oth ).unwrap ()
+ }
+}
+
+impl PartialOrd for BigNum {
+ fn partial_cmp (& self , oth : & BigNum ) -> Option < Ordering > {
+ unsafe {
+ let v = ffi ::BN_cmp (self .raw (), oth .raw ());
+ let ret =
+ if v == 0 {
+ Ordering ::Equal
+ } else if v < 0 {
+ Ordering ::Less
+ } else {
+ Ordering ::Greater
+ };
+ Some (ret )
+ }
+ }
+}
+
+impl Drop for BigNum {
+ fn drop (& mut self ) {
+ unsafe {
+ if ! self .raw ().is_null () {
+ ffi ::BN_clear_free (self .raw ());
+ }
+ }
+ }
+}
+
+pub mod unchecked {
+ use std ::ops ::{Add , Div , Mul , Neg , Rem , Shl , Shr , Sub };
+ use ffi ;
+ use super ::{BigNum };
+
+ impl < 'a > Add < & 'a BigNum > for & 'a BigNum {
+ type Output = BigNum ;
+
+ fn add (self , oth : & 'a BigNum ) -> BigNum {
+ self .checked_add (oth ).unwrap ()
+ }
+ }
+
+ impl < 'a > Sub < & 'a BigNum > for & 'a BigNum {
+ type Output = BigNum ;
+
+ fn sub (self , oth : & 'a BigNum ) -> BigNum {
+ self .checked_sub (oth ).unwrap ()
+ }
+ }
+
+ impl < 'a > Mul < & 'a BigNum > for & 'a BigNum {
+ type Output = BigNum ;
+
+ fn mul (self , oth : & 'a BigNum ) -> BigNum {
+ self .checked_mul (oth ).unwrap ()
+ }
+ }
+
+ impl < 'a > Div < & 'a BigNum > for & 'a BigNum {
+ type Output = BigNum ;
+
+ fn div (self , oth : & 'a BigNum ) -> BigNum {
+ self .checked_div (oth ).unwrap ()
+ }
+ }
+
+ impl < 'a > Rem < & 'a BigNum > for & 'a BigNum {
+ type Output = BigNum ;
+
+ fn rem (self , oth : & 'a BigNum ) -> BigNum {
+ self .checked_mod (oth ).unwrap ()
+ }
+ }
+
+ impl < 'a > Shl < i32 > for & 'a BigNum {
+ type Output = BigNum ;
+
+ fn shl (self , n : i32 ) -> BigNum {
+ self .checked_shl (& n ).unwrap ()
+ }
+ }
+
+ impl < 'a > Shr < i32 > for & 'a BigNum {
+ type Output = BigNum ;
+
+ fn shr (self , n : i32 ) -> BigNum {
+ self .checked_shr (& n ).unwrap ()
+ }
+ }
+
+ impl Clone for BigNum {
+ fn clone (& self ) -> BigNum {
+ unsafe {
+ let r = ffi ::BN_dup (self .raw ());
+ if r .is_null () {
+ panic ! ("Unexpected null pointer from BN_dup(..)" )
+ } else {
+ BigNum (r )
+ }
+ }
+ }
+ }
+
+ impl Neg for BigNum {
+ type Output = BigNum ;
+
+ fn neg (self ) -> BigNum {
+ let mut n = self .clone ();
+ n .negate ();
+ n
+ }
+ }
+}
+
+#[cfg (test )]
+mod tests {
+ use bn ::BigNum ;
+
+ #[test ]
+ fn test_to_from_slice () {
+ let v0 = BigNum ::new_from (10203004_u64 ).unwrap ();
+ let vec = v0 .to_vec ();
+ let v1 = BigNum ::new_from_slice (& vec ).unwrap ();
+
+ assert ! (v0 == v1 );
+ }
+
+ #[test ]
+ fn test_negation () {
+ let a = BigNum ::new_from (909829283_u64 ).unwrap ();
+
+ assert ! (! a .is_negative ());
+ assert ! ((- a ).is_negative ());
+ }
+
+
+ #[test ]
+ fn test_prime_numbers () {
+ let a = BigNum ::new_from (19029017_u64 ).unwrap ();
+ let p = BigNum ::checked_generate_prime (128 , true , None , Some (& a )).unwrap ();
+
+ assert ! (p .is_prime (100 ).unwrap ());
+ assert ! (p .is_prime_fast (100 , true ).unwrap ());
+ }
+}
+
+
+
+
+
+
+
+
+
Keyboard shortcuts
+
+ ?
+ Show this help dialog
+ S
+ Focus the search field
+ ⇤
+ Move up in search results
+ ⇥
+ Move down in search results
+ ⏎
+ Go to active search result
+
+
+
+
Search tricks
+
+ Prefix searches with a type followed by a colon (e.g.
+ fn:
) to restrict the search to a given type.
+
+
+ Accepted types are: fn
, mod
,
+ struct
, enum
,
+ trait
, typedef
(or
+ tdef
).
+
+
+ Search functions by type signature (e.g.
+ vec -> usize
)
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/openssl/crypto/hash.rs.html b/src/openssl/crypto/hash.rs.html
new file mode 100644
index 0000000..3acc27b
--- /dev/null
+++ b/src/openssl/crypto/hash.rs.html
@@ -0,0 +1,773 @@
+
+
+
+
+
+
+
+
+
+ hash.rs.html -- source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+
+use libc ::c_uint ;
+use std ::iter ::repeat ;
+use std ::io ::prelude ::* ;
+use std ::io ;
+
+use ffi ;
+
+
+#[derive (Copy , Clone )]
+pub enum Type {
+ MD5 ,
+ SHA1 ,
+ SHA224 ,
+ SHA256 ,
+ SHA384 ,
+ SHA512 ,
+ RIPEMD160
+}
+
+impl Type {
+
+ #[inline ]
+ pub fn md_len (& self ) -> usize {
+ use self ::Type ::* ;
+ match * self {
+ MD5 => 16 ,
+ SHA1 => 20 ,
+ SHA224 => 28 ,
+ SHA256 => 32 ,
+ SHA384 => 48 ,
+ SHA512 => 64 ,
+ RIPEMD160 => 20 ,
+ }
+ }
+
+
+ #[inline ]
+ pub fn evp_md (& self ) -> * const ffi ::EVP_MD {
+ unsafe {
+ use self ::Type ::* ;
+ match * self {
+ MD5 => ffi ::EVP_md5 (),
+ SHA1 => ffi ::EVP_sha1 (),
+ SHA224 => ffi ::EVP_sha224 (),
+ SHA256 => ffi ::EVP_sha256 (),
+ SHA384 => ffi ::EVP_sha384 (),
+ SHA512 => ffi ::EVP_sha512 (),
+ RIPEMD160 => ffi ::EVP_ripemd160 (),
+ }
+ }
+ }
+}
+
+#[derive (PartialEq , Copy , Clone )]
+enum State {
+ Reset ,
+ Updated ,
+ Finalized ,
+}
+
+use self ::State ::* ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+pub struct Hasher {
+ ctx : * mut ffi ::EVP_MD_CTX ,
+ md : * const ffi ::EVP_MD ,
+ type_ : Type ,
+ state : State ,
+}
+
+impl Hasher {
+
+ pub fn new (ty : Type ) -> Hasher {
+ ffi ::init ();
+
+ let ctx = unsafe {
+ let r = ffi ::EVP_MD_CTX_create ();
+ assert ! (! r .is_null ());
+ r
+ };
+ let md = ty .evp_md ();
+
+ let mut h = Hasher { ctx : ctx , md : md , type_ : ty , state : Finalized };
+ h .init ();
+ h
+ }
+
+ #[inline ]
+ fn init (& mut self ) {
+ match self .state {
+ Reset => return ,
+ Updated => { self .finalize (); },
+ Finalized => (),
+ }
+ unsafe {
+ let r = ffi ::EVP_DigestInit_ex (self .ctx , self .md , 0 as * const _);
+ assert_eq ! (r , 1 );
+ }
+ self .state = Reset ;
+ }
+
+ #[inline ]
+ fn update (& mut self , data : & [u8 ]) {
+ if self .state == Finalized {
+ self .init ();
+ }
+ unsafe {
+ let r = ffi ::EVP_DigestUpdate (self .ctx , data .as_ptr (),
+ data .len () as c_uint );
+ assert_eq ! (r , 1 );
+ }
+ self .state = Updated ;
+ }
+
+ #[inline ]
+ fn finalize (& mut self ) -> Vec < u8 > {
+ if self .state == Finalized {
+ self .init ();
+ }
+ let md_len = self .type_ .md_len ();
+ let mut res : Vec < u8 > = repeat (0 ).take (md_len ).collect ();
+ unsafe {
+ let mut len = 0 ;
+ let r = ffi ::EVP_DigestFinal_ex (self .ctx , res .as_mut_ptr (), & mut len );
+ self .state = Finalized ;
+ assert_eq ! (len as usize , md_len );
+ assert_eq ! (r , 1 );
+ }
+ res
+ }
+
+
+
+ #[inline ]
+ pub fn finish (& mut self ) -> Vec < u8 > {
+ self .finalize ()
+ }
+}
+
+impl Write for Hasher {
+ #[inline ]
+ fn write (& mut self , buf : & [u8 ]) -> io ::Result < usize > {
+ self .update (buf );
+ Ok (buf .len ())
+ }
+
+ fn flush (& mut self ) -> io ::Result < ()> {
+ Ok (())
+ }
+}
+
+impl Clone for Hasher {
+ fn clone (& self ) -> Hasher {
+ let ctx = unsafe {
+ let ctx = ffi ::EVP_MD_CTX_create ();
+ assert ! (! ctx .is_null ());
+ let r = ffi ::EVP_MD_CTX_copy_ex (ctx , self .ctx );
+ assert_eq ! (r , 1 );
+ ctx
+ };
+ Hasher { ctx : ctx , md : self .md , type_ : self .type_ , state : self .state }
+ }
+}
+
+impl Drop for Hasher {
+ fn drop (& mut self ) {
+ unsafe {
+ if self .state != Finalized {
+ let mut buf : Vec < u8 > = repeat (0 ).take (self .type_ .md_len ()).collect ();
+ let mut len = 0 ;
+ ffi ::EVP_DigestFinal_ex (self .ctx , buf .as_mut_ptr (), & mut len );
+ }
+ ffi ::EVP_MD_CTX_destroy (self .ctx );
+ }
+ }
+}
+
+
+pub fn hash (t : Type , data : & [u8 ]) -> Vec < u8 > {
+ let mut h = Hasher ::new (t );
+ let _ = h .write_all (data );
+ h .finish ()
+}
+
+#[cfg (test )]
+mod tests {
+ use serialize ::hex ::{FromHex , ToHex };
+ use super ::{hash , Hasher , Type };
+ use std ::io ::prelude ::* ;
+
+ fn hash_test (hashtype : Type , hashtest : & (& str , & str )) {
+ let res = hash (hashtype , & * hashtest .0 .from_hex ().unwrap ());
+ assert_eq ! (res .to_hex (), hashtest .1 );
+ }
+
+ fn hash_recycle_test (h : & mut Hasher , hashtest : & (& str , & str )) {
+ let _ = h .write_all (& * hashtest .0 .from_hex ().unwrap ());
+ let res = h .finish ();
+ assert_eq ! (res .to_hex (), hashtest .1 );
+ }
+
+
+ #[allow (non_upper_case_globals )]
+ const md5_tests : [(& 'static str , & 'static str ); 13 ] = [
+ ("" , "d41d8cd98f00b204e9800998ecf8427e" ),
+ ("7F" , "83acb6e67e50e31db6ed341dd2de1595" ),
+ ("EC9C" , "0b07f0d4ca797d8ac58874f887cb0b68" ),
+ ("FEE57A" , "e0d583171eb06d56198fc0ef22173907" ),
+ ("42F497E0" , "7c430f178aefdf1487fee7144e9641e2" ),
+ ("C53B777F1C" , "75ef141d64cb37ec423da2d9d440c925" ),
+ ("89D5B576327B" , "ebbaf15eb0ed784c6faa9dc32831bf33" ),
+ ("5D4CCE781EB190" , "ce175c4b08172019f05e6b5279889f2c" ),
+ ("81901FE94932D7B9" , "cd4d2f62b8cdb3a0cf968a735a239281" ),
+ ("C9FFDEE7788EFB4EC9" , "e0841a231ab698db30c6c0f3f246c014" ),
+ ("66AC4B7EBA95E53DC10B" , "a3b3cea71910d9af56742aa0bb2fe329" ),
+ ("A510CD18F7A56852EB0319" , "577e216843dd11573574d3fb209b97d8" ),
+ ("AAED18DBE8938C19ED734A8D" , "6f80fb775f27e0a4ce5c2f42fc72c5f1" )
+ ];
+
+ #[test ]
+ fn test_md5 () {
+ for test in md5_tests .iter () {
+ hash_test (Type ::MD5 , test );
+ }
+ }
+
+ #[test ]
+ fn test_md5_recycle () {
+ let mut h = Hasher ::new (Type ::MD5 );
+ for test in md5_tests .iter () {
+ hash_recycle_test (& mut h , test );
+ }
+ }
+
+ #[test ]
+ fn test_finish_twice () {
+ let mut h = Hasher ::new (Type ::MD5 );
+ let _ = h .write_all (& * md5_tests [6 ].0 .from_hex ().unwrap ());
+ let _ = h .finish ();
+ let res = h .finish ();
+ let null = hash (Type ::MD5 , & []);
+ assert_eq ! (res , null );
+ }
+
+ #[test ]
+ fn test_clone () {
+ let i = 7 ;
+ let inp = md5_tests [i ].0 .from_hex ().unwrap ();
+ assert ! (inp .len () > 2 );
+ let p = inp .len () / 2 ;
+ let h0 = Hasher ::new (Type ::MD5 );
+
+ println ! ("Clone a new hasher" );
+ let mut h1 = h0 .clone ();
+ let _ = h1 .write_all (& inp [..p ]);
+ {
+ println ! ("Clone an updated hasher" );
+ let mut h2 = h1 .clone ();
+ let _ = h2 .write_all (& inp [p ..]);
+ let res = h2 .finish ();
+ assert_eq ! (res .to_hex (), md5_tests [i ].1 );
+ }
+ let _ = h1 .write_all (& inp [p ..]);
+ let res = h1 .finish ();
+ assert_eq ! (res .to_hex (), md5_tests [i ].1 );
+
+ println ! ("Clone a finished hasher" );
+ let mut h3 = h1 .clone ();
+ let _ = h3 .write_all (& * md5_tests [i + 1 ].0 .from_hex ().unwrap ());
+ let res = h3 .finish ();
+ assert_eq ! (res .to_hex (), md5_tests [i + 1 ].1 );
+ }
+
+ #[test ]
+ fn test_sha1 () {
+ let tests = [
+ ("616263" , "a9993e364706816aba3e25717850c26c9cd0d89d" ),
+ ];
+
+ for test in tests .iter () {
+ hash_test (Type ::SHA1 , test );
+ }
+ }
+
+ #[test ]
+ fn test_sha256 () {
+ let tests = [
+ ("616263" , "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" )
+ ];
+
+ for test in tests .iter () {
+ hash_test (Type ::SHA256 , test );
+ }
+ }
+
+ #[test ]
+ fn test_ripemd160 () {
+ let tests = [
+ ("616263" , "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc" )
+ ];
+
+ for test in tests .iter () {
+ hash_test (Type ::RIPEMD160 , test );
+ }
+ }
+}
+
+
+
+
+
+
+
+
+
Keyboard shortcuts
+
+ ?
+ Show this help dialog
+ S
+ Focus the search field
+ ⇤
+ Move up in search results
+ ⇥
+ Move down in search results
+ ⏎
+ Go to active search result
+
+
+
+
Search tricks
+
+ Prefix searches with a type followed by a colon (e.g.
+ fn:
) to restrict the search to a given type.
+
+
+ Accepted types are: fn
, mod
,
+ struct
, enum
,
+ trait
, typedef
(or
+ tdef
).
+
+
+ Search functions by type signature (e.g.
+ vec -> usize
)
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/openssl/crypto/hmac.rs.html b/src/openssl/crypto/hmac.rs.html
new file mode 100644
index 0000000..e63ec32
--- /dev/null
+++ b/src/openssl/crypto/hmac.rs.html
@@ -0,0 +1,1053 @@
+
+
+
+
+
+
+
+
+
+ hmac.rs.html -- source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+
+
+
+use libc ::{c_int , c_uint };
+use std ::iter ::repeat ;
+use std ::io ;
+use std ::io ::prelude ::* ;
+
+use crypto ::hash ::Type ;
+use ffi ;
+
+#[derive (PartialEq , Copy , Clone )]
+enum State {
+ Reset ,
+ Updated ,
+ Finalized ,
+}
+
+use self ::State ::* ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+pub struct HMAC {
+ ctx : ffi ::HMAC_CTX ,
+ type_ : Type ,
+ state : State ,
+}
+
+impl HMAC {
+
+ pub fn new (ty : Type , key : & [u8 ]) -> HMAC {
+ ffi ::init ();
+
+ let ctx = unsafe {
+ let mut ctx = ::std ::mem ::uninitialized ();
+ ffi ::HMAC_CTX_init (& mut ctx );
+ ctx
+ };
+ let md = ty .evp_md ();
+
+ let mut h = HMAC { ctx : ctx , type_ : ty , state : Finalized };
+ h .init_once (md , key );
+ h
+ }
+
+ #[inline ]
+ fn init_once (& mut self , md : * const ffi ::EVP_MD , key : & [u8 ]) {
+ unsafe {
+ let r = ffi ::HMAC_Init_ex_shim (& mut self .ctx ,
+ key .as_ptr (), key .len () as c_int ,
+ md , 0 as * const _);
+ assert_eq ! (r , 1 );
+ }
+ self .state = Reset ;
+ }
+
+ #[inline ]
+ fn init (& mut self ) {
+ match self .state {
+ Reset => return ,
+ Updated => { self .finalize (); },
+ Finalized => (),
+ }
+
+
+ unsafe {
+ let r = ffi ::HMAC_Init_ex_shim (& mut self .ctx ,
+ 0 as * const _, 0 ,
+ 0 as * const _, 0 as * const _);
+ assert_eq ! (r , 1 );
+ }
+ self .state = Reset ;
+ }
+
+ #[inline ]
+ fn update (& mut self , data : & [u8 ]) {
+ if self .state == Finalized {
+ self .init ();
+ }
+ unsafe {
+ let r = ffi ::HMAC_Update_shim (& mut self .ctx , data .as_ptr (), data .len () as c_uint );
+ assert_eq ! (r , 1 );
+ }
+ self .state = Updated ;
+ }
+
+ #[inline ]
+ fn finalize (& mut self ) -> Vec < u8 > {
+ if self .state == Finalized {
+ self .init ();
+ }
+ let md_len = self .type_ .md_len ();
+ let mut res : Vec < u8 > = repeat (0 ).take (md_len ).collect ();
+ unsafe {
+ let mut len = 0 ;
+ let r = ffi ::HMAC_Final_shim (& mut self .ctx , res .as_mut_ptr (), & mut len );
+ self .state = Finalized ;
+ assert_eq ! (len as usize , md_len );
+ assert_eq ! (r , 1 );
+ }
+ res
+ }
+
+
+
+ #[inline ]
+ pub fn finish (& mut self ) -> Vec < u8 > {
+ self .finalize ()
+ }
+}
+
+impl Write for HMAC {
+ #[inline ]
+ fn write (& mut self , buf : & [u8 ]) -> io ::Result < usize > {
+ self .update (buf );
+ Ok (buf .len ())
+ }
+
+ fn flush (& mut self ) -> io ::Result < ()> {
+ Ok (())
+ }
+}
+
+impl Clone for HMAC {
+ fn clone (& self ) -> HMAC {
+ let mut ctx : ffi ::HMAC_CTX ;
+ unsafe {
+ ctx = ::std ::mem ::uninitialized ();
+ let r = ffi ::HMAC_CTX_copy (& mut ctx , & self .ctx );
+ assert_eq ! (r , 1 );
+ }
+ HMAC { ctx : ctx , type_ : self .type_ , state : self .state }
+ }
+}
+
+impl Drop for HMAC {
+ fn drop (& mut self ) {
+ unsafe {
+ if self .state != Finalized {
+ let mut buf : Vec < u8 > = repeat (0 ).take (self .type_ .md_len ()).collect ();
+ let mut len = 0 ;
+ ffi ::HMAC_Final_shim (& mut self .ctx , buf .as_mut_ptr (), & mut len );
+ }
+ ffi ::HMAC_CTX_cleanup (& mut self .ctx );
+ }
+ }
+}
+
+
+pub fn hmac (t : Type , key : & [u8 ], data : & [u8 ]) -> Vec < u8 > {
+ let mut h = HMAC ::new (t , key );
+ let _ = h .write_all (data );
+ h .finish ()
+}
+
+#[cfg (test )]
+mod tests {
+ use std ::iter ::repeat ;
+ use serialize ::hex ::FromHex ;
+ use crypto ::hash ::Type ;
+ use crypto ::hash ::Type ::* ;
+ use super ::{hmac , HMAC };
+ use std ::io ::prelude ::* ;
+
+ fn test_hmac (ty : Type , tests : & [(Vec < u8 > , Vec < u8 > , Vec < u8 > )]) {
+ for & (ref key , ref data , ref res ) in tests .iter () {
+ assert_eq ! (hmac (ty , & * * key , & * * data ), * res );
+ }
+ }
+
+ fn test_hmac_recycle (h : & mut HMAC , test : & (Vec < u8 > , Vec < u8 > , Vec < u8 > )) {
+ let & (_, ref data , ref res ) = test ;
+ let _ = h .write_all (& * * data );
+ assert_eq ! (h .finish (), * res );
+ }
+
+ #[test ]
+ fn test_hmac_md5 () {
+
+ let tests : [(Vec < u8 > , Vec < u8 > , Vec < u8 > ); 7 ] = [
+ (repeat (0x0b_u8 ).take (16 ).collect (), b"Hi There" .to_vec (),
+ "9294727a3638bb1c13f48ef8158bfc9d" .from_hex ().unwrap ()),
+ (b"Jefe" .to_vec (),
+ b"what do ya want for nothing?" .to_vec (),
+ "750c783e6ab0b503eaa86e310a5db738" .from_hex ().unwrap ()),
+ (repeat (0xaa_u8 ).take (16 ).collect (), repeat (0xdd_u8 ).take (50 ).collect (),
+ "56be34521d144c88dbb8c733f0e8b3f6" .from_hex ().unwrap ()),
+ ("0102030405060708090a0b0c0d0e0f10111213141516171819" .from_hex ().unwrap (),
+ repeat (0xcd_u8 ).take (50 ).collect (),
+ "697eaf0aca3a3aea3a75164746ffaa79" .from_hex ().unwrap ()),
+ (repeat (0x0c_u8 ).take (16 ).collect (),
+ b"Test With Truncation" .to_vec (),
+ "56461ef2342edc00f9bab995690efd4c" .from_hex ().unwrap ()),
+ (repeat (0xaa_u8 ).take (80 ).collect (),
+ b"Test Using Larger Than Block-Size Key - Hash Key First" .to_vec (),
+ "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd" .from_hex ().unwrap ()),
+ (repeat (0xaa_u8 ).take (80 ).collect (),
+ b"Test Using Larger Than Block-Size Key \
+ and Larger Than One Block-Size Data" .to_vec (),
+ "6f630fad67cda0ee1fb1f562db3aa53e" .from_hex ().unwrap ())
+ ];
+
+ test_hmac (MD5 , & tests );
+ }
+
+ #[test ]
+ fn test_hmac_md5_recycle () {
+ let tests : [(Vec < u8 > , Vec < u8 > , Vec < u8 > ); 2 ] = [
+ (repeat (0xaa_u8 ).take (80 ).collect (),
+ b"Test Using Larger Than Block-Size Key - Hash Key First" .to_vec (),
+ "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd" .from_hex ().unwrap ()),
+ (repeat (0xaa_u8 ).take (80 ).collect (),
+ b"Test Using Larger Than Block-Size Key \
+ and Larger Than One Block-Size Data" .to_vec (),
+ "6f630fad67cda0ee1fb1f562db3aa53e" .from_hex ().unwrap ())
+ ];
+
+ let mut h = HMAC ::new (MD5 , & * tests [0 ].0 );
+ for i in 0 ..100usize {
+ let test = & tests [i % 2 ];
+ test_hmac_recycle (& mut h , test );
+ }
+ }
+
+ #[test ]
+ fn test_finish_twice () {
+ let test : (Vec < u8 > , Vec < u8 > , Vec < u8 > ) =
+ (repeat (0xaa_u8 ).take (80 ).collect (),
+ b"Test Using Larger Than Block-Size Key - Hash Key First" .to_vec (),
+ "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd" .from_hex ().unwrap ());
+
+ let mut h = HMAC ::new (Type ::MD5 , & * test .0 );
+ let _ = h .write_all (& * test .1 );
+ let _ = h .finish ();
+ let res = h .finish ();
+ let null = hmac (Type ::MD5 , & * test .0 , & []);
+ assert_eq ! (res , null );
+ }
+
+ #[test ]
+ fn test_clone () {
+ let tests : [(Vec < u8 > , Vec < u8 > , Vec < u8 > ); 2 ] = [
+ (repeat (0xaa_u8 ).take (80 ).collect (),
+ b"Test Using Larger Than Block-Size Key - Hash Key First" .to_vec (),
+ "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd" .from_hex ().unwrap ()),
+ (repeat (0xaa_u8 ).take (80 ).collect (),
+ b"Test Using Larger Than Block-Size Key \
+ and Larger Than One Block-Size Data" .to_vec (),
+ "6f630fad67cda0ee1fb1f562db3aa53e" .from_hex ().unwrap ()),
+ ];
+ let p = tests [0 ].0 .len () / 2 ;
+ let h0 = HMAC ::new (Type ::MD5 , & * tests [0 ].0 );
+
+ println ! ("Clone a new hmac" );
+ let mut h1 = h0 .clone ();
+ let _ = h1 .write_all (& tests [0 ].1 [..p ]);
+ {
+ println ! ("Clone an updated hmac" );
+ let mut h2 = h1 .clone ();
+ let _ = h2 .write_all (& tests [0 ].1 [p ..]);
+ let res = h2 .finish ();
+ assert_eq ! (res , tests [0 ].2 );
+ }
+ let _ = h1 .write_all (& tests [0 ].1 [p ..]);
+ let res = h1 .finish ();
+ assert_eq ! (res , tests [0 ].2 );
+
+ println ! ("Clone a finished hmac" );
+ let mut h3 = h1 .clone ();
+ let _ = h3 .write_all (& * tests [1 ].1 );
+ let res = h3 .finish ();
+ assert_eq ! (res , tests [1 ].2 );
+ }
+
+ #[test ]
+ fn test_hmac_sha1 () {
+
+ let tests : [(Vec < u8 > , Vec < u8 > , Vec < u8 > ); 7 ] = [
+ (repeat (0x0b_u8 ).take (20 ).collect (), b"Hi There" .to_vec (),
+ "b617318655057264e28bc0b6fb378c8ef146be00" .from_hex ().unwrap ()),
+ (b"Jefe" .to_vec (),
+ b"what do ya want for nothing?" .to_vec (),
+ "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79" .from_hex ().unwrap ()),
+ (repeat (0xaa_u8 ).take (20 ).collect (), repeat (0xdd_u8 ).take (50 ).collect (),
+ "125d7342b9ac11cd91a39af48aa17b4f63f175d3" .from_hex ().unwrap ()),
+ ("0102030405060708090a0b0c0d0e0f10111213141516171819" .from_hex ().unwrap (),
+ repeat (0xcd_u8 ).take (50 ).collect (),
+ "4c9007f4026250c6bc8414f9bf50c86c2d7235da" .from_hex ().unwrap ()),
+ (repeat (0x0c_u8 ).take (20 ).collect (),
+ b"Test With Truncation" .to_vec (),
+ "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04" .from_hex ().unwrap ()),
+ (repeat (0xaa_u8 ).take (80 ).collect (),
+ b"Test Using Larger Than Block-Size Key - Hash Key First" .to_vec (),
+ "aa4ae5e15272d00e95705637ce8a3b55ed402112" .from_hex ().unwrap ()),
+ (repeat (0xaa_u8 ).take (80 ).collect (),
+ b"Test Using Larger Than Block-Size Key \
+ and Larger Than One Block-Size Data" .to_vec (),
+ "e8e99d0f45237d786d6bbaa7965c7808bbff1a91" .from_hex ().unwrap ())
+ ];
+
+ test_hmac (SHA1 , & tests );
+ }
+
+ #[test ]
+ fn test_hmac_sha1_recycle () {
+ let tests : [(Vec < u8 > , Vec < u8 > , Vec < u8 > ); 2 ] = [
+ (repeat (0xaa_u8 ).take (80 ).collect (),
+ b"Test Using Larger Than Block-Size Key - Hash Key First" .to_vec (),
+ "aa4ae5e15272d00e95705637ce8a3b55ed402112" .from_hex ().unwrap ()),
+ (repeat (0xaa_u8 ).take (80 ).collect (),
+ b"Test Using Larger Than Block-Size Key \
+ and Larger Than One Block-Size Data" .to_vec (),
+ "e8e99d0f45237d786d6bbaa7965c7808bbff1a91" .from_hex ().unwrap ())
+ ];
+
+ let mut h = HMAC ::new (SHA1 , & * tests [0 ].0 );
+ for i in 0 ..100usize {
+ let test = & tests [i % 2 ];
+ test_hmac_recycle (& mut h , test );
+ }
+ }
+
+
+
+ fn test_sha2 (ty : Type , results : & [Vec < u8 > ]) {
+
+ let tests : [(Vec < u8 > , Vec < u8 > ); 6 ] = [
+ (repeat (0xb_u8 ).take (20 ).collect (), b"Hi There" .to_vec ()),
+ (b"Jefe" .to_vec (),
+ b"what do ya want for nothing?" .to_vec ()),
+ (repeat (0xaa_u8 ).take (20 ).collect (), repeat (0xdd_u8 ).take (50 ).collect ()),
+ ("0102030405060708090a0b0c0d0e0f10111213141516171819" .from_hex ().unwrap (),
+ repeat (0xcd_u8 ).take (50 ).collect ()),
+ (repeat (0xaa_u8 ).take (131 ).collect (),
+ b"Test Using Larger Than Block-Size Key - Hash Key First" .to_vec ()),
+ (repeat (0xaa_u8 ).take (131 ).collect (),
+ b"This is a test using a larger than block-size key and a \
+ larger than block-size data. The key needs to be hashed \
+ before being used by the HMAC algorithm." .to_vec ())
+ ];
+
+ for (& (ref key , ref data ), res ) in tests .iter ().zip (results .iter ()) {
+ assert_eq ! (hmac (ty , & * * key , & * * data ), * res );
+ }
+
+
+ let mut h = HMAC ::new (ty , & * tests [5 ].0 );
+ for i in 0 ..100usize {
+ let test = & tests [4 + i % 2 ];
+ let tup = (test .0 .clone (), test .1 .clone (), results [4 + i % 2 ].clone ());
+ test_hmac_recycle (& mut h , & tup );
+ }
+ }
+
+ #[test ]
+ fn test_hmac_sha224 () {
+ let results = [
+ "896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22" .from_hex ().unwrap (),
+ "a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44" .from_hex ().unwrap (),
+ "7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea" .from_hex ().unwrap (),
+ "6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a" .from_hex ().unwrap (),
+ "95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e" .from_hex ().unwrap (),
+ "3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1" .from_hex ().unwrap ()
+ ];
+ test_sha2 (SHA224 , & results );
+ }
+
+ #[test ]
+ fn test_hmac_sha256 () {
+ let results = [
+ "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7" .from_hex ().unwrap (),
+ "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843" .from_hex ().unwrap (),
+ "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe" .from_hex ().unwrap (),
+ "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b" .from_hex ().unwrap (),
+ "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54" .from_hex ().unwrap (),
+ "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2" .from_hex ().unwrap ()
+ ];
+ test_sha2 (SHA256 , & results );
+ }
+
+ #[test ]
+ fn test_hmac_sha384 () {
+ let results = [
+ "afd03944d84895626b0825f4ab46907f\
+ 15f9dadbe4101ec682aa034c7cebc59c\
+ faea9ea9076ede7f4af152e8b2fa9cb6" .from_hex ().unwrap (),
+ "af45d2e376484031617f78d2b58a6b1b\
+ 9c7ef464f5a01b47e42ec3736322445e\
+ 8e2240ca5e69e2c78b3239ecfab21649" .from_hex ().unwrap (),
+ "88062608d3e6ad8a0aa2ace014c8a86f\
+ 0aa635d947ac9febe83ef4e55966144b\
+ 2a5ab39dc13814b94e3ab6e101a34f27" .from_hex ().unwrap (),
+ "3e8a69b7783c25851933ab6290af6ca7\
+ 7a9981480850009cc5577c6e1f573b4e\
+ 6801dd23c4a7d679ccf8a386c674cffb" .from_hex ().unwrap (),
+ "4ece084485813e9088d2c63a041bc5b4\
+ 4f9ef1012a2b588f3cd11f05033ac4c6\
+ 0c2ef6ab4030fe8296248df163f44952" .from_hex ().unwrap (),
+ "6617178e941f020d351e2f254e8fd32c\
+ 602420feb0b8fb9adccebb82461e99c5\
+ a678cc31e799176d3860e6110c46523e" .from_hex ().unwrap ()
+ ];
+ test_sha2 (SHA384 , & results );
+ }
+
+ #[test ]
+ fn test_hmac_sha512 () {
+ let results = [
+ "87aa7cdea5ef619d4ff0b4241a1d6cb0\
+ 2379f4e2ce4ec2787ad0b30545e17cde\
+ daa833b7d6b8a702038b274eaea3f4e4\
+ be9d914eeb61f1702e696c203a126854" .from_hex ().unwrap (),
+ "164b7a7bfcf819e2e395fbe73b56e0a3\
+ 87bd64222e831fd610270cd7ea250554\
+ 9758bf75c05a994a6d034f65f8f0e6fd\
+ caeab1a34d4a6b4b636e070a38bce737" .from_hex ().unwrap (),
+ "fa73b0089d56a284efb0f0756c890be9\
+ b1b5dbdd8ee81a3655f83e33b2279d39\
+ bf3e848279a722c806b485a47e67c807\
+ b946a337bee8942674278859e13292fb" .from_hex ().unwrap (),
+ "b0ba465637458c6990e5a8c5f61d4af7\
+ e576d97ff94b872de76f8050361ee3db\
+ a91ca5c11aa25eb4d679275cc5788063\
+ a5f19741120c4f2de2adebeb10a298dd" .from_hex ().unwrap (),
+ "80b24263c7c1a3ebb71493c1dd7be8b4\
+ 9b46d1f41b4aeec1121b013783f8f352\
+ 6b56d037e05f2598bd0fd2215d6a1e52\
+ 95e64f73f63f0aec8b915a985d786598" .from_hex ().unwrap (),
+ "e37b6a775dc87dbaa4dfa9f96e5e3ffd\
+ debd71f8867289865df5a32d20cdc944\
+ b6022cac3c4982b10d5eeb55c3e4de15\
+ 134676fb6de0446065c97440fa8c6a58" .from_hex ().unwrap ()
+ ];
+ test_sha2 (SHA512 , & results );
+ }
+}
+
+
+
+
+
+
+
+
+
Keyboard shortcuts
+
+ ?
+ Show this help dialog
+ S
+ Focus the search field
+ ⇤
+ Move up in search results
+ ⇥
+ Move down in search results
+ ⏎
+ Go to active search result
+
+
+
+
Search tricks
+
+ Prefix searches with a type followed by a colon (e.g.
+ fn:
) to restrict the search to a given type.
+
+
+ Accepted types are: fn
, mod
,
+ struct
, enum
,
+ trait
, typedef
(or
+ tdef
).
+
+
+ Search functions by type signature (e.g.
+ vec -> usize
)
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/openssl/crypto/memcmp.rs.html b/src/openssl/crypto/memcmp.rs.html
new file mode 100644
index 0000000..ecc2b6d
--- /dev/null
+++ b/src/openssl/crypto/memcmp.rs.html
@@ -0,0 +1,175 @@
+
+
+
+
+
+
+
+
+
+ memcmp.rs.html -- source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+
+use libc ::size_t ;
+use ffi ;
+
+
+
+
+
+
+
+
+
+
+pub fn eq (a : & [u8 ], b : & [u8 ]) -> bool {
+ assert ! (a .len () == b .len ());
+ let ret = unsafe {
+ ffi ::CRYPTO_memcmp (a .as_ptr () as * const _,
+ b .as_ptr () as * const _,
+ a .len () as size_t )
+ };
+ ret == 0
+}
+
+#[cfg (test )]
+mod tests {
+ use super ::eq ;
+
+ #[test ]
+ fn test_eq () {
+ assert ! (eq (& [], & []));
+ assert ! (eq (& [1 ], & [1 ]));
+ assert ! (! eq (& [1 , 2 , 3 ], & [1 , 2 , 4 ]));
+ }
+
+ #[test ]
+ #[should_panic ]
+ fn test_diff_lens () {
+ eq (& [], & [1 ]);
+ }
+}
+
+
+
+
+
+
+
+
+
Keyboard shortcuts
+
+ ?
+ Show this help dialog
+ S
+ Focus the search field
+ ⇤
+ Move up in search results
+ ⇥
+ Move down in search results
+ ⏎
+ Go to active search result
+
+
+
+
Search tricks
+
+ Prefix searches with a type followed by a colon (e.g.
+ fn:
) to restrict the search to a given type.
+
+
+ Accepted types are: fn
, mod
,
+ struct
, enum
,
+ trait
, typedef
(or
+ tdef
).
+
+
+ Search functions by type signature (e.g.
+ vec -> usize
)
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/openssl/crypto/mod.rs.html b/src/openssl/crypto/mod.rs.html
new file mode 100644
index 0000000..47e1c77
--- /dev/null
+++ b/src/openssl/crypto/mod.rs.html
@@ -0,0 +1,145 @@
+
+
+
+
+
+
+
+
+
+ mod.rs.html -- source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+
+
+
+pub mod hash ;
+pub mod hmac ;
+pub mod pkcs5 ;
+pub mod pkey ;
+pub mod rand ;
+pub mod symm ;
+pub mod memcmp ;
+
+
+
+
+
+
+
+
+
Keyboard shortcuts
+
+ ?
+ Show this help dialog
+ S
+ Focus the search field
+ ⇤
+ Move up in search results
+ ⇥
+ Move down in search results
+ ⏎
+ Go to active search result
+
+
+
+
Search tricks
+
+ Prefix searches with a type followed by a colon (e.g.
+ fn:
) to restrict the search to a given type.
+
+
+ Accepted types are: fn
, mod
,
+ struct
, enum
,
+ trait
, typedef
(or
+ tdef
).
+
+
+ Search functions by type signature (e.g.
+ vec -> usize
)
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/openssl/crypto/pkcs5.rs.html b/src/openssl/crypto/pkcs5.rs.html
new file mode 100644
index 0000000..5ac11c1
--- /dev/null
+++ b/src/openssl/crypto/pkcs5.rs.html
@@ -0,0 +1,335 @@
+
+
+
+
+
+
+
+
+
+ pkcs5.rs.html -- source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+
+use libc ::c_int ;
+use ffi ;
+
+
+pub fn pbkdf2_hmac_sha1 (pass : & str , salt : & [u8 ], iter : usize , keylen : usize ) -> Vec < u8 > {
+ unsafe {
+ assert ! (iter >= 1 );
+ assert ! (keylen >= 1 );
+
+ let mut out = Vec ::with_capacity (keylen );
+
+ ffi ::init ();
+
+ let r = ffi ::PKCS5_PBKDF2_HMAC_SHA1 (
+ pass .as_ptr (), pass .len () as c_int ,
+ salt .as_ptr (), salt .len () as c_int ,
+ iter as c_int , keylen as c_int ,
+ out .as_mut_ptr ());
+
+ if r != 1 { panic ! (); }
+
+ out .set_len (keylen );
+
+ out
+ }
+}
+
+#[cfg (test )]
+mod tests {
+
+
+ #[test ]
+ fn test_pbkdf2_hmac_sha1 () {
+ assert_eq ! (
+ super ::pbkdf2_hmac_sha1 (
+ "password" ,
+ "salt" .as_bytes (),
+ 1 ,
+ 20
+ ),
+ vec ! (
+ 0x0c_u8 , 0x60_u8 , 0xc8_u8 , 0x0f_u8 , 0x96_u8 , 0x1f_u8 , 0x0e_u8 ,
+ 0x71_u8 , 0xf3_u8 , 0xa9_u8 , 0xb5_u8 , 0x24_u8 , 0xaf_u8 , 0x60_u8 ,
+ 0x12_u8 , 0x06_u8 , 0x2f_u8 , 0xe0_u8 , 0x37_u8 , 0xa6_u8
+ )
+ );
+
+ assert_eq ! (
+ super ::pbkdf2_hmac_sha1 (
+ "password" ,
+ "salt" .as_bytes (),
+ 2 ,
+ 20
+ ),
+ vec ! (
+ 0xea_u8 , 0x6c_u8 , 0x01_u8 , 0x4d_u8 , 0xc7_u8 , 0x2d_u8 , 0x6f_u8 ,
+ 0x8c_u8 , 0xcd_u8 , 0x1e_u8 , 0xd9_u8 , 0x2a_u8 , 0xce_u8 , 0x1d_u8 ,
+ 0x41_u8 , 0xf0_u8 , 0xd8_u8 , 0xde_u8 , 0x89_u8 , 0x57_u8
+ )
+ );
+
+ assert_eq ! (
+ super ::pbkdf2_hmac_sha1 (
+ "password" ,
+ "salt" .as_bytes (),
+ 4096 ,
+ 20
+ ),
+ vec ! (
+ 0x4b_u8 , 0x00_u8 , 0x79_u8 , 0x01_u8 , 0xb7_u8 , 0x65_u8 , 0x48_u8 ,
+ 0x9a_u8 , 0xbe_u8 , 0xad_u8 , 0x49_u8 , 0xd9_u8 , 0x26_u8 , 0xf7_u8 ,
+ 0x21_u8 , 0xd0_u8 , 0x65_u8 , 0xa4_u8 , 0x29_u8 , 0xc1_u8
+ )
+ );
+
+ assert_eq ! (
+ super ::pbkdf2_hmac_sha1 (
+ "password" ,
+ "salt" .as_bytes (),
+ 16777216 ,
+ 20
+ ),
+ vec ! (
+ 0xee_u8 , 0xfe_u8 , 0x3d_u8 , 0x61_u8 , 0xcd_u8 , 0x4d_u8 , 0xa4_u8 ,
+ 0xe4_u8 , 0xe9_u8 , 0x94_u8 , 0x5b_u8 , 0x3d_u8 , 0x6b_u8 , 0xa2_u8 ,
+ 0x15_u8 , 0x8c_u8 , 0x26_u8 , 0x34_u8 , 0xe9_u8 , 0x84_u8
+ )
+ );
+
+ assert_eq ! (
+ super ::pbkdf2_hmac_sha1 (
+ "passwordPASSWORDpassword" ,
+ "saltSALTsaltSALTsaltSALTsaltSALTsalt" .as_bytes (),
+ 4096 ,
+ 25
+ ),
+ vec ! (
+ 0x3d_u8 , 0x2e_u8 , 0xec_u8 , 0x4f_u8 , 0xe4_u8 , 0x1c_u8 , 0x84_u8 ,
+ 0x9b_u8 , 0x80_u8 , 0xc8_u8 , 0xd8_u8 , 0x36_u8 , 0x62_u8 , 0xc0_u8 ,
+ 0xe4_u8 , 0x4a_u8 , 0x8b_u8 , 0x29_u8 , 0x1a_u8 , 0x96_u8 , 0x4c_u8 ,
+ 0xf2_u8 , 0xf0_u8 , 0x70_u8 , 0x38_u8
+ )
+ );
+
+ assert_eq ! (
+ super ::pbkdf2_hmac_sha1 (
+ "pass\x00word" ,
+ "sa\x00lt" .as_bytes (),
+ 4096 ,
+ 16
+ ),
+ vec ! (
+ 0x56_u8 , 0xfa_u8 , 0x6a_u8 , 0xa7_u8 , 0x55_u8 , 0x48_u8 , 0x09_u8 ,
+ 0x9d_u8 , 0xcc_u8 , 0x37_u8 , 0xd7_u8 , 0xf0_u8 , 0x34_u8 , 0x25_u8 ,
+ 0xe0_u8 , 0xc3_u8
+ )
+ );
+ }
+}
+
+
+
+
+
+
+
+
+
Keyboard shortcuts
+
+ ?
+ Show this help dialog
+ S
+ Focus the search field
+ ⇤
+ Move up in search results
+ ⇥
+ Move down in search results
+ ⏎
+ Go to active search result
+
+
+
+
Search tricks
+
+ Prefix searches with a type followed by a colon (e.g.
+ fn:
) to restrict the search to a given type.
+
+
+ Accepted types are: fn
, mod
,
+ struct
, enum
,
+ trait
, typedef
(or
+ tdef
).
+
+
+ Search functions by type signature (e.g.
+ vec -> usize
)
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/openssl/crypto/pkey.rs.html b/src/openssl/crypto/pkey.rs.html
new file mode 100644
index 0000000..4b93f74
--- /dev/null
+++ b/src/openssl/crypto/pkey.rs.html
@@ -0,0 +1,1103 @@
+
+
+
+
+
+
+
+
+
+ pkey.rs.html -- source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+
+use libc ::{c_int , c_uint , c_ulong };
+use std ::io ;
+use std ::io ::prelude ::* ;
+use std ::iter ::repeat ;
+use std ::mem ;
+use std ::ptr ;
+use bio ::{MemBio };
+use crypto ::hash ;
+use crypto ::hash ::Type as HashType ;
+use ffi ;
+use ssl ::error ::{SslError , StreamError };
+
+#[derive (Copy , Clone )]
+pub enum Parts {
+ Neither ,
+ Public ,
+ Both
+}
+
+
+#[derive (Copy , Clone )]
+pub enum Role {
+ Encrypt ,
+ Decrypt ,
+ Sign ,
+ Verify
+}
+
+
+#[derive (Copy , Clone )]
+pub enum EncryptionPadding {
+ OAEP ,
+ PKCS1v15
+}
+
+fn openssl_padding_code (padding : EncryptionPadding ) -> c_int {
+ match padding {
+ EncryptionPadding ::OAEP => 4 ,
+ EncryptionPadding ::PKCS1v15 => 1
+ }
+}
+
+fn openssl_hash_nid (hash : HashType ) -> c_int {
+ match hash {
+ HashType ::MD5 => 4 ,
+ HashType ::SHA1 => 64 ,
+ HashType ::SHA224 => 675 ,
+ HashType ::SHA256 => 672 ,
+ HashType ::SHA384 => 673 ,
+ HashType ::SHA512 => 674 ,
+ HashType ::RIPEMD160 => 117 ,
+ }
+}
+
+pub struct PKey {
+ evp : * mut ffi ::EVP_PKEY ,
+ parts : Parts ,
+}
+
+
+impl PKey {
+ pub fn new () -> PKey {
+ unsafe {
+ ffi ::init ();
+
+ PKey {
+ evp : ffi ::EVP_PKEY_new (),
+ parts : Parts ::Neither ,
+ }
+ }
+ }
+
+ pub fn from_handle (handle : * mut ffi ::EVP_PKEY , parts : Parts ) -> PKey {
+ ffi ::init ();
+ assert ! (! handle .is_null ());
+
+ PKey {
+ evp : handle ,
+ parts : parts ,
+ }
+ }
+
+
+ pub fn private_key_from_pem < R > (reader : & mut R ) -> Result < PKey , SslError > where R : Read {
+ let mut mem_bio = try ! (MemBio ::new ());
+ try ! (io ::copy (reader , & mut mem_bio ).map_err (StreamError ));
+
+ unsafe {
+ let evp = try_ssl_null ! (ffi ::PEM_read_bio_PrivateKey (mem_bio .get_handle (),
+ ptr ::null_mut (),
+ None , ptr ::null_mut ()));
+ Ok (PKey {
+ evp : evp ,
+ parts : Parts ::Both ,
+ })
+ }
+ }
+
+ fn _tostr (& self , f : unsafe extern "C" fn (* mut ffi ::RSA , * const * mut u8 ) -> c_int ) -> Vec < u8 > {
+ unsafe {
+ let rsa = ffi ::EVP_PKEY_get1_RSA (self .evp );
+ let len = f (rsa , ptr ::null ());
+ if len < 0 as c_int { return vec ! (); }
+ let mut s = repeat (0u8 ).take (len as usize ).collect ::< Vec < _>> ();
+
+ let r = f (rsa , & s .as_mut_ptr ());
+
+ s .truncate (r as usize );
+ s
+ }
+ }
+
+ fn _fromstr (& mut self , s : & [u8 ], f : unsafe extern "C" fn (* const * mut ffi ::RSA , * const * const u8 , c_uint ) -> * mut ffi ::RSA ) {
+ unsafe {
+ let rsa = ptr ::null_mut ();
+ f (& rsa , & s .as_ptr (), s .len () as c_uint );
+ ffi ::EVP_PKEY_set1_RSA (self .evp , rsa );
+ }
+ }
+
+ pub fn gen (& mut self , keysz : usize ) {
+ unsafe {
+ let rsa = ffi ::RSA_generate_key (
+ keysz as c_int ,
+ 65537 as c_ulong ,
+ ptr ::null (),
+ ptr ::null ()
+ );
+
+
+ ffi ::EVP_PKEY_assign (
+ self .evp ,
+ 6 as c_int ,
+ mem ::transmute (rsa ));
+
+ self .parts = Parts ::Both ;
+ }
+ }
+
+
+ pub fn save_pub (& self ) -> Vec < u8 > {
+ self ._tostr (ffi ::i2d_RSA_PUBKEY )
+ }
+
+
+ pub fn load_pub (& mut self , s : & [u8 ]) {
+ self ._fromstr (s , ffi ::d2i_RSA_PUBKEY );
+ self .parts = Parts ::Public ;
+ }
+
+
+ pub fn save_priv (& self ) -> Vec < u8 > {
+ self ._tostr (ffi ::i2d_RSAPrivateKey )
+ }
+
+ pub fn load_priv (& mut self , s : & [u8 ]) {
+ self ._fromstr (s , ffi ::d2i_RSAPrivateKey );
+ self .parts = Parts ::Both ;
+ }
+
+
+
+ pub fn write_pem < W : Write > (& self , writer : & mut W ) -> Result < (), SslError > {
+ let mut mem_bio = try ! (MemBio ::new ());
+ unsafe {
+ try_ssl ! (ffi ::PEM_write_bio_PrivateKey (mem_bio .get_handle (), self .evp , ptr ::null (),
+ ptr ::null_mut (), - 1 , None , ptr ::null_mut ()));
+
+ }
+ let mut buf = vec ! [];
+ try ! (mem_bio .read_to_end (& mut buf ).map_err (StreamError ));
+ writer .write_all (& buf ).map_err (StreamError )
+ }
+
+
+ pub fn size (& self ) -> usize {
+ unsafe {
+ ffi ::RSA_size (ffi ::EVP_PKEY_get1_RSA (self .evp )) as usize
+ }
+ }
+
+
+ pub fn can (& self , r : Role ) -> bool {
+ match r {
+ Role ::Encrypt =>
+ match self .parts {
+ Parts ::Neither => false ,
+ _ => true ,
+ },
+ Role ::Verify =>
+ match self .parts {
+ Parts ::Neither => false ,
+ _ => true ,
+ },
+ Role ::Decrypt =>
+ match self .parts {
+ Parts ::Both => true ,
+ _ => false ,
+ },
+ Role ::Sign =>
+ match self .parts {
+ Parts ::Both => true ,
+ _ => false ,
+ },
+ }
+ }
+
+
+ pub fn max_data (& self ) -> usize {
+ unsafe {
+ let rsa = ffi ::EVP_PKEY_get1_RSA (self .evp );
+ let len = ffi ::RSA_size (rsa );
+
+
+ len as usize - 41
+ }
+ }
+
+ pub fn encrypt_with_padding (& self , s : & [u8 ], padding : EncryptionPadding ) -> Vec < u8 > {
+ unsafe {
+ let rsa = ffi ::EVP_PKEY_get1_RSA (self .evp );
+ let len = ffi ::RSA_size (rsa );
+
+ assert ! (s .len () < self .max_data ());
+
+ let mut r = repeat (0u8 ).take (len as usize + 1 ).collect ::< Vec < _>> ();
+
+ let rv = ffi ::RSA_public_encrypt (
+ s .len () as c_int ,
+ s .as_ptr (),
+ r .as_mut_ptr (),
+ rsa ,
+ openssl_padding_code (padding ));
+
+ if rv < 0 as c_int {
+ vec ! ()
+ } else {
+ r .truncate (rv as usize );
+ r
+ }
+ }
+ }
+
+ pub fn decrypt_with_padding (& self , s : & [u8 ], padding : EncryptionPadding ) -> Vec < u8 > {
+ unsafe {
+ let rsa = ffi ::EVP_PKEY_get1_RSA (self .evp );
+ let len = ffi ::RSA_size (rsa );
+
+ assert_eq ! (s .len () as c_int , ffi ::RSA_size (rsa ));
+
+ let mut r = repeat (0u8 ).take (len as usize + 1 ).collect ::< Vec < _>> ();
+
+ let rv = ffi ::RSA_private_decrypt (
+ s .len () as c_int ,
+ s .as_ptr (),
+ r .as_mut_ptr (),
+ rsa ,
+ openssl_padding_code (padding ));
+
+ if rv < 0 as c_int {
+ vec ! ()
+ } else {
+ r .truncate (rv as usize );
+ r
+ }
+ }
+ }
+
+
+ pub fn encrypt (& self , s : & [u8 ]) -> Vec < u8 > { self .encrypt_with_padding (s , EncryptionPadding ::OAEP ) }
+
+
+ pub fn decrypt (& self , s : & [u8 ]) -> Vec < u8 > { self .decrypt_with_padding (s , EncryptionPadding ::OAEP ) }
+
+
+ pub fn sign (& self , s : & [u8 ]) -> Vec < u8 > { self .sign_with_hash (s , HashType ::SHA256 ) }
+
+
+ pub fn verify (& self , h : & [u8 ], s : & [u8 ]) -> bool { self .verify_with_hash (h , s , HashType ::SHA256 ) }
+
+
+ pub fn sign_with_hash (& self , s : & [u8 ], hash : hash ::Type ) -> Vec < u8 > {
+ unsafe {
+ let rsa = ffi ::EVP_PKEY_get1_RSA (self .evp );
+ let len = ffi ::RSA_size (rsa );
+ let mut r = repeat (0u8 ).take (len as usize + 1 ).collect ::< Vec < _>> ();
+
+ let mut len = 0 ;
+ let rv = ffi ::RSA_sign (
+ openssl_hash_nid (hash ),
+ s .as_ptr (),
+ s .len () as c_uint ,
+ r .as_mut_ptr (),
+ & mut len ,
+ rsa );
+
+ if rv < 0 as c_int {
+ vec ! ()
+ } else {
+ r .truncate (len as usize );
+ r
+ }
+ }
+ }
+
+ pub fn verify_with_hash (& self , h : & [u8 ], s : & [u8 ], hash : hash ::Type ) -> bool {
+ unsafe {
+ let rsa = ffi ::EVP_PKEY_get1_RSA (self .evp );
+
+ let rv = ffi ::RSA_verify (
+ openssl_hash_nid (hash ),
+ h .as_ptr (),
+ h .len () as c_uint ,
+ s .as_ptr (),
+ s .len () as c_uint ,
+ rsa
+ );
+
+ rv == 1 as c_int
+ }
+ }
+
+ pub unsafe fn get_handle (& self ) -> * mut ffi ::EVP_PKEY {
+ return self .evp
+ }
+
+ pub fn public_eq (& self , other : & PKey ) -> bool {
+ unsafe { ffi ::EVP_PKEY_cmp (self .evp , other .evp ) == 1 }
+ }
+}
+
+impl Drop for PKey {
+ fn drop (& mut self ) {
+ unsafe {
+ ffi ::EVP_PKEY_free (self .evp );
+ }
+ }
+}
+
+#[cfg (test )]
+mod tests {
+ use std ::path ::Path ;
+ use std ::fs ::File ;
+ use crypto ::hash ::Type ::{MD5 , SHA1 };
+
+ #[test ]
+ fn test_gen_pub () {
+ let mut k0 = super ::PKey ::new ();
+ let mut k1 = super ::PKey ::new ();
+ k0 .gen (512 );
+ k1 .load_pub (& k0 .save_pub ());
+ assert_eq ! (k0 .save_pub (), k1 .save_pub ());
+ assert ! (k0 .public_eq (& k1 ));
+ assert_eq ! (k0 .size (), k1 .size ());
+ assert ! (k0 .can (super ::Role ::Encrypt ));
+ assert ! (k0 .can (super ::Role ::Decrypt ));
+ assert ! (k0 .can (super ::Role ::Verify ));
+ assert ! (k0 .can (super ::Role ::Sign ));
+ assert ! (k1 .can (super ::Role ::Encrypt ));
+ assert ! (! k1 .can (super ::Role ::Decrypt ));
+ assert ! (k1 .can (super ::Role ::Verify ));
+ assert ! (! k1 .can (super ::Role ::Sign ));
+ }
+
+ #[test ]
+ fn test_gen_priv () {
+ let mut k0 = super ::PKey ::new ();
+ let mut k1 = super ::PKey ::new ();
+ k0 .gen (512 );
+ k1 .load_priv (& k0 .save_priv ());
+ assert_eq ! (k0 .save_priv (), k1 .save_priv ());
+ assert ! (k0 .public_eq (& k1 ));
+ assert_eq ! (k0 .size (), k1 .size ());
+ assert ! (k0 .can (super ::Role ::Encrypt ));
+ assert ! (k0 .can (super ::Role ::Decrypt ));
+ assert ! (k0 .can (super ::Role ::Verify ));
+ assert ! (k0 .can (super ::Role ::Sign ));
+ assert ! (k1 .can (super ::Role ::Encrypt ));
+ assert ! (k1 .can (super ::Role ::Decrypt ));
+ assert ! (k1 .can (super ::Role ::Verify ));
+ assert ! (k1 .can (super ::Role ::Sign ));
+ }
+
+ #[test ]
+ fn test_private_key_from_pem () {
+ let key_path = Path ::new ("test/key.pem" );
+ let mut file = File ::open (& key_path )
+ .ok ()
+ .expect ("Failed to open `test/key.pem`" );
+
+ super ::PKey ::private_key_from_pem (& mut file ).unwrap ();
+ }
+
+ #[test ]
+ fn test_encrypt () {
+ let mut k0 = super ::PKey ::new ();
+ let mut k1 = super ::PKey ::new ();
+ let msg = vec ! (0xdeu8 , 0xadu8 , 0xd0u8 , 0x0du8 );
+ k0 .gen (512 );
+ k1 .load_pub (& k0 .save_pub ());
+ let emsg = k1 .encrypt (& msg );
+ let dmsg = k0 .decrypt (& emsg );
+ assert ! (msg == dmsg );
+ }
+
+ #[test ]
+ fn test_encrypt_pkcs () {
+ let mut k0 = super ::PKey ::new ();
+ let mut k1 = super ::PKey ::new ();
+ let msg = vec ! (0xdeu8 , 0xadu8 , 0xd0u8 , 0x0du8 );
+ k0 .gen (512 );
+ k1 .load_pub (& k0 .save_pub ());
+ let emsg = k1 .encrypt_with_padding (& msg , super ::EncryptionPadding ::PKCS1v15 );
+ let dmsg = k0 .decrypt_with_padding (& emsg , super ::EncryptionPadding ::PKCS1v15 );
+ assert ! (msg == dmsg );
+ }
+
+ #[test ]
+ fn test_sign () {
+ let mut k0 = super ::PKey ::new ();
+ let mut k1 = super ::PKey ::new ();
+ let msg = vec ! (0xdeu8 , 0xadu8 , 0xd0u8 , 0x0du8 );
+ k0 .gen (512 );
+ k1 .load_pub (& k0 .save_pub ());
+ let sig = k0 .sign (& msg );
+ let rv = k1 .verify (& msg , & sig );
+ assert ! (rv == true );
+ }
+
+ #[test ]
+ fn test_sign_hashes () {
+ let mut k0 = super ::PKey ::new ();
+ let mut k1 = super ::PKey ::new ();
+ let msg = vec ! (0xdeu8 , 0xadu8 , 0xd0u8 , 0x0du8 );
+ k0 .gen (512 );
+ k1 .load_pub (& k0 .save_pub ());
+
+ let sig = k0 .sign_with_hash (& msg , MD5 );
+
+ assert ! (k1 .verify_with_hash (& msg , & sig , MD5 ));
+ assert ! (! k1 .verify_with_hash (& msg , & sig , SHA1 ));
+ }
+
+ #[test ]
+ fn test_eq () {
+ let mut k0 = super ::PKey ::new ();
+ let mut p0 = super ::PKey ::new ();
+ let mut k1 = super ::PKey ::new ();
+ let mut p1 = super ::PKey ::new ();
+ k0 .gen (512 );
+ k1 .gen (512 );
+ p0 .load_pub (& k0 .save_pub ());
+ p1 .load_pub (& k1 .save_pub ());
+
+ assert ! (k0 .public_eq (& k0 ));
+ assert ! (k1 .public_eq (& k1 ));
+ assert ! (p0 .public_eq (& p0 ));
+ assert ! (p1 .public_eq (& p1 ));
+ assert ! (k0 .public_eq (& p0 ));
+ assert ! (k1 .public_eq (& p1 ));
+
+ assert ! (! k0 .public_eq (& k1 ));
+ assert ! (! p0 .public_eq (& p1 ));
+ assert ! (! k0 .public_eq (& p1 ));
+ assert ! (! p0 .public_eq (& k1 ));
+ }
+}
+
+
+
+
+
+
+
+
+
Keyboard shortcuts
+
+ ?
+ Show this help dialog
+ S
+ Focus the search field
+ ⇤
+ Move up in search results
+ ⇥
+ Move down in search results
+ ⏎
+ Go to active search result
+
+
+
+
Search tricks
+
+ Prefix searches with a type followed by a colon (e.g.
+ fn:
) to restrict the search to a given type.
+
+
+ Accepted types are: fn
, mod
,
+ struct
, enum
,
+ trait
, typedef
(or
+ tdef
).
+
+
+ Search functions by type signature (e.g.
+ vec -> usize
)
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/openssl/crypto/rand.rs.html b/src/openssl/crypto/rand.rs.html
new file mode 100644
index 0000000..fd6f00a
--- /dev/null
+++ b/src/openssl/crypto/rand.rs.html
@@ -0,0 +1,151 @@
+
+
+
+
+
+
+
+
+
+ rand.rs.html -- source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+
+use libc ::c_int ;
+use ffi ;
+
+pub fn rand_bytes (len : usize ) -> Vec < u8 > {
+ unsafe {
+ let mut out = Vec ::with_capacity (len );
+
+ ffi ::init ();
+ let r = ffi ::RAND_bytes (out .as_mut_ptr (), len as c_int );
+ if r != 1 as c_int { panic ! () }
+
+ out .set_len (len );
+
+ out
+ }
+}
+
+#[cfg (test )]
+mod tests {
+ use super ::rand_bytes ;
+
+ #[test ]
+ fn test_rand_bytes () {
+ let bytes = rand_bytes (32 );
+ println ! ("{:?}" , bytes );
+ }
+}
+
+
+
+
+
+
+
+
+
Keyboard shortcuts
+
+ ?
+ Show this help dialog
+ S
+ Focus the search field
+ ⇤
+ Move up in search results
+ ⇥
+ Move down in search results
+ ⏎
+ Go to active search result
+
+
+
+
Search tricks
+
+ Prefix searches with a type followed by a colon (e.g.
+ fn:
) to restrict the search to a given type.
+
+
+ Accepted types are: fn
, mod
,
+ struct
, enum
,
+ trait
, typedef
(or
+ tdef
).
+
+
+ Search functions by type signature (e.g.
+ vec -> usize
)
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/openssl/crypto/symm.rs.html b/src/openssl/crypto/symm.rs.html
new file mode 100644
index 0000000..5cbd394
--- /dev/null
+++ b/src/openssl/crypto/symm.rs.html
@@ -0,0 +1,721 @@
+
+
+
+
+
+
+
+
+
+ symm.rs.html -- source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+
+use std ::iter ::repeat ;
+use std ::convert ::AsRef ;
+use libc ::{c_int };
+
+use ffi ;
+
+#[derive (Copy , Clone )]
+pub enum Mode {
+ Encrypt ,
+ Decrypt ,
+}
+
+#[allow (non_camel_case_types )]
+#[derive (Copy , Clone )]
+pub enum Type {
+ AES_128_ECB ,
+ AES_128_CBC ,
+
+ #[cfg (feature = "aes_xts" )]
+ AES_128_XTS ,
+
+
+
+ AES_256_ECB ,
+ AES_256_CBC ,
+
+ #[cfg (feature = "aes_xts" )]
+ AES_256_XTS ,
+
+
+
+ RC4_128 ,
+}
+
+fn evpc (t : Type ) -> (* const ffi ::EVP_CIPHER , u32 , u32 ) {
+ unsafe {
+ match t {
+ Type ::AES_128_ECB => (ffi ::EVP_aes_128_ecb (), 16 , 16 ),
+ Type ::AES_128_CBC => (ffi ::EVP_aes_128_cbc (), 16 , 16 ),
+ #[cfg (feature = "aes_xts" )]
+ Type ::AES_128_XTS => (ffi ::EVP_aes_128_xts (), 32 , 16 ),
+
+
+
+ Type ::AES_256_ECB => (ffi ::EVP_aes_256_ecb (), 32 , 16 ),
+ Type ::AES_256_CBC => (ffi ::EVP_aes_256_cbc (), 32 , 16 ),
+ #[cfg (feature = "aes_xts" )]
+ Type ::AES_256_XTS => (ffi ::EVP_aes_256_xts (), 64 , 16 ),
+
+
+
+ Type ::RC4_128 => (ffi ::EVP_rc4 (), 16 , 0 ),
+ }
+ }
+}
+
+
+pub struct Crypter {
+ evp : * const ffi ::EVP_CIPHER ,
+ ctx : * mut ffi ::EVP_CIPHER_CTX ,
+ keylen : u32 ,
+ blocksize : u32 ,
+}
+
+impl Crypter {
+ pub fn new (t : Type ) -> Crypter {
+ ffi ::init ();
+
+ let ctx = unsafe { ffi ::EVP_CIPHER_CTX_new () };
+ let (evp , keylen , blocksz ) = evpc (t );
+ Crypter { evp : evp , ctx : ctx , keylen : keylen , blocksize : blocksz }
+ }
+
+
+ pub fn pad (& self , padding : bool ) {
+ if self .blocksize > 0 {
+ unsafe {
+ let v = if padding { 1 as c_int } else { 0 };
+ ffi ::EVP_CIPHER_CTX_set_padding (self .ctx , v );
+ }
+ }
+ }
+
+
+ pub fn init < T : AsRef < [u8 ]>> (& self , mode : Mode , key : & [u8 ], iv : T ) {
+ unsafe {
+ let mode = match mode {
+ Mode ::Encrypt => 1 as c_int ,
+ Mode ::Decrypt => 0 as c_int ,
+ };
+ assert_eq ! (key .len (), self .keylen as usize );
+
+ ffi ::EVP_CipherInit (
+ self .ctx ,
+ self .evp ,
+ key .as_ptr (),
+ iv .as_ref ().as_ptr (),
+ mode
+ );
+ }
+ }
+
+
+ pub fn update (& self , data : & [u8 ]) -> Vec < u8 > {
+ unsafe {
+ let sum = data .len () + (self .blocksize as usize );
+ let mut res = repeat (0u8 ).take (sum ).collect ::< Vec < _>> ();
+ let mut reslen = sum as c_int ;
+
+ ffi ::EVP_CipherUpdate (
+ self .ctx ,
+ res .as_mut_ptr (),
+ & mut reslen ,
+ data .as_ptr (),
+ data .len () as c_int
+ );
+
+ res .truncate (reslen as usize );
+ res
+ }
+ }
+
+
+ pub fn finalize (& self ) -> Vec < u8 > {
+ unsafe {
+ let mut res = repeat (0u8 ).take (self .blocksize as usize ).collect ::< Vec < _>> ();
+ let mut reslen = self .blocksize as c_int ;
+
+ ffi ::EVP_CipherFinal (self .ctx ,
+ res .as_mut_ptr (),
+ & mut reslen );
+
+ res .truncate (reslen as usize );
+ res
+ }
+ }
+}
+
+impl Drop for Crypter {
+ fn drop (& mut self ) {
+ unsafe {
+ ffi ::EVP_CIPHER_CTX_free (self .ctx );
+ }
+ }
+}
+
+
+pub fn encrypt < T : AsRef < [u8 ]>> (t : Type , key : & [u8 ], iv : T , data : & [u8 ]) -> Vec < u8 > {
+ let c = Crypter ::new (t );
+ c .init (Mode ::Encrypt , key , iv );
+ let mut r = c .update (data );
+ let rest = c .finalize ();
+ r .extend (rest .into_iter ());
+ r
+}
+
+
+pub fn decrypt < T : AsRef < [u8 ]>> (t : Type , key : & [u8 ], iv : T , data : & [u8 ]) -> Vec < u8 > {
+ let c = Crypter ::new (t );
+ c .init (Mode ::Decrypt , key , iv );
+ let mut r = c .update (data );
+ let rest = c .finalize ();
+ r .extend (rest .into_iter ());
+ r
+}
+
+#[cfg (test )]
+mod tests {
+ use serialize ::hex ::FromHex ;
+
+
+
+ #[test ]
+ fn test_aes_256_ecb () {
+ let k0 =
+ [0x00u8 , 0x01u8 , 0x02u8 , 0x03u8 , 0x04u8 , 0x05u8 , 0x06u8 , 0x07u8 ,
+ 0x08u8 , 0x09u8 , 0x0au8 , 0x0bu8 , 0x0cu8 , 0x0du8 , 0x0eu8 , 0x0fu8 ,
+ 0x10u8 , 0x11u8 , 0x12u8 , 0x13u8 , 0x14u8 , 0x15u8 , 0x16u8 , 0x17u8 ,
+ 0x18u8 , 0x19u8 , 0x1au8 , 0x1bu8 , 0x1cu8 , 0x1du8 , 0x1eu8 , 0x1fu8 ];
+ let p0 =
+ [0x00u8 , 0x11u8 , 0x22u8 , 0x33u8 , 0x44u8 , 0x55u8 , 0x66u8 , 0x77u8 ,
+ 0x88u8 , 0x99u8 , 0xaau8 , 0xbbu8 , 0xccu8 , 0xddu8 , 0xeeu8 , 0xffu8 ];
+ let c0 =
+ [0x8eu8 , 0xa2u8 , 0xb7u8 , 0xcau8 , 0x51u8 , 0x67u8 , 0x45u8 , 0xbfu8 ,
+ 0xeau8 , 0xfcu8 , 0x49u8 , 0x90u8 , 0x4bu8 , 0x49u8 , 0x60u8 , 0x89u8 ];
+ let c = super ::Crypter ::new (super ::Type ::AES_256_ECB );
+ c .init (super ::Mode ::Encrypt , & k0 , & []);
+ c .pad (false );
+ let mut r0 = c .update (& p0 );
+ r0 .extend (c .finalize ().into_iter ());
+ assert ! (r0 == c0 );
+ c .init (super ::Mode ::Decrypt , & k0 , & []);
+ c .pad (false );
+ let mut p1 = c .update (& r0 );
+ p1 .extend (c .finalize ().into_iter ());
+ assert ! (p1 == p0 );
+ }
+
+ #[test ]
+ fn test_aes_256_cbc_decrypt () {
+ let cr = super ::Crypter ::new (super ::Type ::AES_256_CBC );
+ let iv = [
+ 4_u8 , 223_u8 , 153_u8 , 219_u8 , 28_u8 , 142_u8 , 234_u8 , 68_u8 , 227_u8 ,
+ 69_u8 , 98_u8 , 107_u8 , 208_u8 , 14_u8 , 236_u8 , 60_u8 , 0_u8 , 0_u8 ,
+ 0_u8 , 0_u8 , 0_u8 , 0_u8 , 0_u8 , 0_u8 , 0_u8 , 0_u8 , 0_u8 , 0_u8 , 0_u8 ,
+ 0_u8 , 0_u8 , 0_u8
+ ];
+ let data = [
+ 143_u8 , 210_u8 , 75_u8 , 63_u8 , 214_u8 , 179_u8 , 155_u8 ,
+ 241_u8 , 242_u8 , 31_u8 , 154_u8 , 56_u8 , 198_u8 , 145_u8 , 192_u8 , 64_u8 ,
+ 2_u8 , 245_u8 , 167_u8 , 220_u8 , 55_u8 , 119_u8 , 233_u8 , 136_u8 , 139_u8 ,
+ 27_u8 , 71_u8 , 242_u8 , 119_u8 , 175_u8 , 65_u8 , 207_u8
+ ];
+ let ciphered_data = [
+ 0x4a_u8 , 0x2e_u8 , 0xe5_u8 , 0x6_u8 , 0xbf_u8 , 0xcf_u8 , 0xf2_u8 , 0xd7_u8 ,
+ 0xea_u8 , 0x2d_u8 , 0xb1_u8 , 0x85_u8 , 0x6c_u8 , 0x93_u8 , 0x65_u8 , 0x6f_u8
+ ];
+ cr .init (super ::Mode ::Decrypt , & data , & iv );
+ cr .pad (false );
+ let unciphered_data_1 = cr .update (& ciphered_data );
+ let unciphered_data_2 = cr .finalize ();
+
+ let expected_unciphered_data = b"I love turtles.\x01" ;
+
+ assert ! (unciphered_data_2 .len () == 0 );
+
+ assert_eq ! (& unciphered_data_1 , expected_unciphered_data );
+ }
+
+ fn cipher_test (ciphertype : super ::Type , pt : & str , ct : & str , key : & str , iv : & str ) {
+ use serialize ::hex ::ToHex ;
+
+ let cipher = super ::Crypter ::new (ciphertype );
+ cipher .init (super ::Mode ::Encrypt , & key .from_hex ().unwrap (), & iv .from_hex ().unwrap ());
+
+ let expected = ct .from_hex ().unwrap ();
+ let mut computed = cipher .update (& pt .from_hex ().unwrap ());
+ computed .extend (cipher .finalize ().into_iter ());
+
+ if computed != expected {
+ println ! ("Computed: {}" , computed .to_hex ());
+ println ! ("Expected: {}" , expected .to_hex ());
+ if computed .len () != expected .len () {
+ println ! ("Lengths differ: {} in computed vs {} expected" ,
+ computed .len (), expected .len ());
+ }
+ panic ! ("test failure" );
+ }
+ }
+
+ #[test ]
+ fn test_rc4 () {
+
+ let pt = "0000000000000000000000000000000000000000000000000000000000000000000000000000" ;
+ let ct = "A68686B04D686AA107BD8D4CAB191A3EEC0A6294BC78B60F65C25CB47BD7BB3A48EFC4D26BE4" ;
+ let key = "97CD440324DA5FD1F7955C1C13B6B466" ;
+ let iv = "" ;
+
+ cipher_test (super ::Type ::RC4_128 , pt , ct , key , iv );
+ }
+
+ #[test ]
+ #[cfg (feature = "aes_xts" )]
+ fn test_aes256_xts () {
+
+
+ let pt = "77f4ef63d734ebd028508da66c22cdebdd52ecd6ee2ab0a50bc8ad0cfd692ca5fcd4e6dedc45df7f6503f462611dc542" ;
+ let ct = "ce7d905a7776ac72f240d22aafed5e4eb7566cdc7211220e970da634ce015f131a5ecb8d400bc9e84f0b81d8725dbbc7" ;
+ let key = "b6bfef891f83b5ff073f2231267be51eb084b791fa19a154399c0684c8b2dfcb37de77d28bbda3b4180026ad640b74243b3133e7b9fae629403f6733423dae28" ;
+ let iv = "db200efb7eaaa737dbdf40babb68953f" ;
+
+ cipher_test (super ::Type ::AES_256_XTS , pt , ct , key , iv );
+ }
+
+
+
+
+}
+
+
+
+
+
+
+
+
+
Keyboard shortcuts
+
+ ?
+ Show this help dialog
+ S
+ Focus the search field
+ ⇤
+ Move up in search results
+ ⇥
+ Move down in search results
+ ⏎
+ Go to active search result
+
+
+
+
Search tricks
+
+ Prefix searches with a type followed by a colon (e.g.
+ fn:
) to restrict the search to a given type.
+
+
+ Accepted types are: fn
, mod
,
+ struct
, enum
,
+ trait
, typedef
(or
+ tdef
).
+
+
+ Search functions by type signature (e.g.
+ vec -> usize
)
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/openssl/lib.rs.html b/src/openssl/lib.rs.html
new file mode 100644
index 0000000..e8ad872
--- /dev/null
+++ b/src/openssl/lib.rs.html
@@ -0,0 +1,147 @@
+
+
+
+
+
+
+
+
+
+ lib.rs.html -- source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+
+#! [doc (html_root_url = "https://sfackler.github.io/rust-openssl/doc/v0.6.3" )]
+
+#[macro_use ]
+extern crate bitflags ;
+extern crate libc ;
+#[macro_use ]
+extern crate lazy_static ;
+extern crate openssl_sys as ffi ;
+
+#[cfg (test )]
+extern crate rustc_serialize as serialize ;
+
+#[cfg (test )]
+#[cfg (any (feature = "dtlsv1" , feature = "dtlsv1_2" ))]
+extern crate connected_socket ;
+
+mod macros ;
+
+pub mod asn1 ;
+pub mod bn ;
+pub mod bio ;
+pub mod crypto ;
+pub mod ssl ;
+pub mod x509 ;
+pub mod nid ;
+
+
+
+
+
+
+
+
+
Keyboard shortcuts
+
+ ?
+ Show this help dialog
+ S
+ Focus the search field
+ ⇤
+ Move up in search results
+ ⇥
+ Move down in search results
+ ⏎
+ Go to active search result
+
+
+
+
Search tricks
+
+ Prefix searches with a type followed by a colon (e.g.
+ fn:
) to restrict the search to a given type.
+
+
+ Accepted types are: fn
, mod
,
+ struct
, enum
,
+ trait
, typedef
(or
+ tdef
).
+
+
+ Search functions by type signature (e.g.
+ vec -> usize
)
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/openssl/nid.rs.html b/src/openssl/nid.rs.html
new file mode 100644
index 0000000..857ab9d
--- /dev/null
+++ b/src/openssl/nid.rs.html
@@ -0,0 +1,437 @@
+
+
+
+
+
+
+
+
+
+ nid.rs.html -- source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+
+#[allow (non_camel_case_types )]
+#[derive (Copy , Clone )]
+#[repr (usize )]
+pub enum Nid {
+ Undefined ,
+ Rsadsi ,
+ Pkcs ,
+ MD2 ,
+ MD4 ,
+ MD5 ,
+ RC4 ,
+ RsaEncryption ,
+ RSA_MD2 ,
+ RSA_MD5 ,
+ PBE_MD2_DES ,
+ X500 ,
+ x509 ,
+ CN ,
+ C ,
+ L ,
+ ST ,
+ O ,
+ OU ,
+ RSA ,
+ Pkcs7 ,
+ Pkcs7_data ,
+ Pkcs7_signedData ,
+ Pkcs7_envelopedData ,
+ Pkcs7_signedAndEnvelopedData ,
+ Pkcs7_digestData ,
+ Pkcs7_encryptedData ,
+ Pkcs3 ,
+ DhKeyAgreement ,
+ DES_ECB ,
+ DES_CFB ,
+ DES_CBC ,
+ DES_EDE ,
+ DES_EDE3 ,
+ IDEA_CBC ,
+ IDEA_ECB ,
+ RC2_CBC ,
+ RC2_ECB ,
+ RC2_CFB ,
+ RC2_OFB ,
+ SHA ,
+ RSA_SHA ,
+ DES_EDE_CBC ,
+ DES_EDE3_CBC ,
+ DES_OFB ,
+ IDEA_OFB ,
+ Pkcs9 ,
+ Email ,
+ UnstructuredName ,
+ ContentType ,
+ MessageDigest ,
+ SigningTime ,
+ CounterSignature ,
+ UnstructuredAddress ,
+ ExtendedCertificateAttributes ,
+ Netscape ,
+ NetscapeCertExtention ,
+ NetscapeDatatype ,
+ DES_EDE_CFB64 ,
+ DES_EDE3_CFB64 ,
+ DES_EDE_OFB64 ,
+ DES_EDE3_OFB64 ,
+ SHA1 ,
+ RSA_SHA1 ,
+ DSA_SHA ,
+ DSA_OLD ,
+ PBE_SHA1_RC2_64 ,
+ PBKDF2 ,
+ DSA_SHA1_OLD ,
+ NetscapeCertType ,
+ NetscapeBaseUrl ,
+ NetscapeRevocationUrl ,
+ NetscapeCARevocationUrl ,
+ NetscapeRenewalUrl ,
+ NetscapeCAPolicyUrl ,
+ NetscapeSSLServerName ,
+ NetscapeComment ,
+ NetscapeCertSequence ,
+ DESX_CBC ,
+ ID_CE ,
+ SubjectKeyIdentifier ,
+ KeyUsage ,
+ PrivateKeyUsagePeriod ,
+ SubjectAltName ,
+ IssuerAltName ,
+ BasicConstraints ,
+ CrlNumber ,
+ CertificatePolicies ,
+ AuthorityKeyIdentifier ,
+ BF_CBC ,
+ BF_ECB ,
+ BF_OFB ,
+ MDC2 ,
+ RSA_MDC2 ,
+ RC4_40 ,
+ RC2_40_CBC ,
+ G ,
+ S ,
+ I ,
+ UID ,
+ CrlDistributionPoints ,
+ RSA_NP_MD5 ,
+ SN ,
+ T ,
+ D ,
+ CAST5_CBC ,
+ CAST5_ECB ,
+ CAST5_CFB ,
+ CAST5_OFB ,
+ PbeWithMD5AndCast5CBC ,
+ DSA_SHA1 ,
+ MD5_SHA1 ,
+ RSA_SHA1_2 ,
+ DSA ,
+ RIPEMD160 ,
+ RSA_RIPEMD160 ,
+ RC5_CBC ,
+ RC5_ECB ,
+ RC5_CFB ,
+ RC5_OFB ,
+ RLE ,
+ ZLIB ,
+ ExtendedKeyUsage ,
+ PKIX ,
+ ID_KP ,
+ ServerAuth ,
+ ClientAuth ,
+ CodeSigning ,
+ EmailProtection ,
+ TimeStamping ,
+ MsCodeInd ,
+ MsCodeCom ,
+ MsCtlSigh ,
+ MsSGC ,
+ MsEFS ,
+ NsSGC ,
+ DeltaCRL ,
+ CRLReason ,
+ InvalidityDate ,
+ SXNetID ,
+ Pkcs12 ,
+ PBE_SHA1_RC4_128 ,
+ PBE_SHA1_RC4_40 ,
+ PBE_SHA1_3DES ,
+ PBE_SHA1_2DES ,
+ PBE_SHA1_RC2_128 ,
+ PBE_SHA1_RC2_40 ,
+ KeyBag ,
+ Pkcs8ShroudedKeyBag ,
+ CertBag ,
+ CrlBag ,
+ SecretBag ,
+ SafeContentsBag ,
+ FriendlyName ,
+ LocalKeyID ,
+ X509Certificate ,
+ SdsiCertificate ,
+ X509Crl ,
+ PBES2 ,
+ PBMAC1 ,
+ HmacWithSha1 ,
+ ID_QT_CPS ,
+ ID_QT_UNOTICE ,
+ RC2_64_CBC ,
+ SMIMECaps
+}
+
+
+
+
+
+
+
+
+
Keyboard shortcuts
+
+ ?
+ Show this help dialog
+ S
+ Focus the search field
+ ⇤
+ Move up in search results
+ ⇥
+ Move down in search results
+ ⏎
+ Go to active search result
+
+
+
+
Search tricks
+
+ Prefix searches with a type followed by a colon (e.g.
+ fn:
) to restrict the search to a given type.
+
+
+ Accepted types are: fn
, mod
,
+ struct
, enum
,
+ trait
, typedef
(or
+ tdef
).
+
+
+ Search functions by type signature (e.g.
+ vec -> usize
)
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/openssl/ssl/error.rs.html b/src/openssl/ssl/error.rs.html
new file mode 100644
index 0000000..683c375
--- /dev/null
+++ b/src/openssl/ssl/error.rs.html
@@ -0,0 +1,373 @@
+
+
+
+
+
+
+
+
+
+ error.rs.html -- source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+
+pub use self ::SslError ::* ;
+pub use self ::OpensslError ::* ;
+
+use libc ::c_ulong ;
+use std ::error ;
+use std ::fmt ;
+use std ::ffi ::CStr ;
+use std ::io ;
+
+use ffi ;
+
+
+#[derive (Debug )]
+pub enum SslError {
+
+ StreamError (io ::Error ),
+
+ SslSessionClosed ,
+
+ OpenSslErrors (Vec < OpensslError > )
+}
+
+impl fmt ::Display for SslError {
+ fn fmt (& self , fmt : & mut fmt ::Formatter ) -> fmt ::Result {
+ try ! (fmt .write_str (error ::Error ::description (self )));
+ if let OpenSslErrors (ref errs ) = * self {
+ let mut first = true ;
+ for err in errs {
+ if first {
+ try ! (fmt .write_str (": " ));
+ first = false ;
+ } else {
+ try ! (fmt .write_str (", " ));
+ }
+ match * err {
+ UnknownError { ref reason , .. } => try ! (fmt .write_str (reason )),
+ }
+ }
+ }
+
+ Ok (())
+ }
+}
+
+impl error ::Error for SslError {
+ fn description (& self ) -> & str {
+ match * self {
+ StreamError (_) => "The underlying stream reported an error" ,
+ SslSessionClosed => "The SSL session has been closed by the other end" ,
+ OpenSslErrors (_) => "An error in the OpenSSL library" ,
+ }
+ }
+
+ fn cause (& self ) -> Option < & error ::Error > {
+ match * self {
+ StreamError (ref err ) => Some (err as & error ::Error ),
+ _ => None
+ }
+ }
+}
+
+
+#[derive (Debug , Clone , PartialEq , Eq )]
+pub enum OpensslError {
+
+ UnknownError {
+
+ library : String ,
+
+ function : String ,
+
+ reason : String
+ }
+}
+
+fn get_lib (err : c_ulong ) -> String {
+ unsafe {
+ let bytes = CStr ::from_ptr (ffi ::ERR_lib_error_string (err )).to_bytes ().to_vec ();
+ String ::from_utf8 (bytes ).unwrap ()
+ }
+}
+
+fn get_func (err : c_ulong ) -> String {
+ unsafe {
+ let bytes = CStr ::from_ptr (ffi ::ERR_func_error_string (err )).to_bytes ().to_vec ();
+ String ::from_utf8 (bytes ).unwrap ()
+ }
+}
+
+fn get_reason (err : c_ulong ) -> String {
+ unsafe {
+ let bytes = CStr ::from_ptr (ffi ::ERR_reason_error_string (err )).to_bytes ().to_vec ();
+ String ::from_utf8 (bytes ).unwrap ()
+ }
+}
+
+impl SslError {
+
+
+ pub fn get () -> SslError {
+ let mut errs = vec ! ();
+ loop {
+ match unsafe { ffi ::ERR_get_error () } {
+ 0 => break ,
+ err => errs .push (SslError ::from_error_code (err ))
+ }
+ }
+ OpenSslErrors (errs )
+ }
+
+
+ pub fn from_error (err : c_ulong ) -> SslError {
+ OpenSslErrors (vec ! [SslError ::from_error_code (err )])
+ }
+
+ fn from_error_code (err : c_ulong ) -> OpensslError {
+ ffi ::init ();
+ UnknownError {
+ library : get_lib (err ),
+ function : get_func (err ),
+ reason : get_reason (err )
+ }
+ }
+}
+
+#[test ]
+fn test_uknown_error_should_have_correct_messages () {
+ let errs = match SslError ::from_error (336032784 ) {
+ OpenSslErrors (errs ) => errs ,
+ _ => panic ! ("This should always be an `OpenSslErrors` variant." )
+ };
+
+ let UnknownError { ref library , ref function , ref reason } = errs [0 ];
+
+ assert_eq ! (& library [..], "SSL routines" );
+ assert_eq ! (& function [..], "SSL23_GET_SERVER_HELLO" );
+ assert_eq ! (& reason [..], "sslv3 alert handshake failure" );
+}
+
+
+
+
+
+
+
+
+
Keyboard shortcuts
+
+ ?
+ Show this help dialog
+ S
+ Focus the search field
+ ⇤
+ Move up in search results
+ ⇥
+ Move down in search results
+ ⏎
+ Go to active search result
+
+
+
+
Search tricks
+
+ Prefix searches with a type followed by a colon (e.g.
+ fn:
) to restrict the search to a given type.
+
+
+ Accepted types are: fn
, mod
,
+ struct
, enum
,
+ trait
, typedef
(or
+ tdef
).
+
+
+ Search functions by type signature (e.g.
+ vec -> usize
)
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/openssl/ssl/mod.rs.html b/src/openssl/ssl/mod.rs.html
new file mode 100644
index 0000000..40cd850
--- /dev/null
+++ b/src/openssl/ssl/mod.rs.html
@@ -0,0 +1,2079 @@
+
+
+
+
+
+
+
+
+
+ mod.rs.html -- source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+796
+797
+798
+799
+800
+801
+802
+803
+804
+805
+806
+807
+808
+809
+810
+811
+812
+813
+814
+815
+816
+817
+818
+819
+820
+821
+822
+823
+824
+825
+826
+827
+828
+829
+830
+831
+832
+833
+834
+835
+836
+837
+838
+839
+840
+841
+842
+843
+844
+845
+846
+847
+848
+849
+850
+851
+852
+853
+854
+855
+856
+857
+858
+859
+860
+861
+862
+863
+864
+865
+866
+867
+868
+869
+870
+871
+872
+873
+874
+875
+876
+877
+878
+879
+880
+881
+882
+883
+884
+885
+886
+887
+888
+889
+890
+891
+892
+893
+894
+895
+896
+897
+898
+899
+900
+901
+902
+903
+904
+905
+906
+907
+908
+909
+910
+911
+912
+913
+914
+915
+916
+917
+918
+919
+920
+921
+922
+923
+924
+925
+926
+927
+928
+929
+930
+931
+932
+933
+934
+935
+936
+937
+938
+939
+940
+941
+942
+943
+944
+945
+946
+947
+948
+949
+950
+951
+952
+953
+954
+955
+956
+957
+958
+959
+960
+961
+962
+963
+964
+965
+966
+967
+968
+969
+970
+971
+972
+973
+974
+975
+976
+977
+978
+979
+980
+981
+982
+983
+984
+985
+986
+987
+988
+989
+990
+991
+
+use libc ::{c_int , c_void , c_long };
+use std ::any ::TypeId ;
+use std ::collections ::HashMap ;
+use std ::ffi ::{CStr , CString };
+use std ::fmt ;
+use std ::io ;
+use std ::io ::prelude ::* ;
+use std ::mem ;
+use std ::net ;
+use std ::path ::Path ;
+use std ::ptr ;
+use std ::sync ::{Once , ONCE_INIT , Arc , Mutex };
+use std ::ops ::{Deref , DerefMut };
+use std ::cmp ;
+use std ::any ::Any ;
+#[cfg (feature = "npn" )]
+use libc ::{c_uchar , c_uint };
+#[cfg (feature = "npn" )]
+use std ::slice ;
+
+use bio ::{MemBio };
+use ffi ;
+use ssl ::error ::{SslError , SslSessionClosed , StreamError , OpenSslErrors };
+use x509 ::{X509StoreContext , X509FileType , X509 };
+use crypto ::pkey ::PKey ;
+
+pub mod error ;
+#[cfg (test )]
+mod tests ;
+
+static mut VERIFY_IDX : c_int = - 1 ;
+
+fn init () {
+ static mut INIT : Once = ONCE_INIT ;
+
+ unsafe {
+ INIT .call_once (|| {
+ ffi ::init ();
+
+ let verify_idx = ffi ::SSL_CTX_get_ex_new_index (0 , ptr ::null (), None ,
+ None , None );
+ assert ! (verify_idx >= 0 );
+ VERIFY_IDX = verify_idx ;
+ });
+ }
+}
+
+bitflags ! {
+ flags SslContextOptions : c_long {
+ const SSL_OP_LEGACY_SERVER_CONNECT = 0x00000004 ,
+ const SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = 0x00000008 ,
+ const SSL_OP_TLSEXT_PADDING = 0x00000010 ,
+ const SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER = 0x00000020 ,
+ const SSL_OP_SAFARI_ECDHE_ECDSA_BUG = 0x00000040 ,
+ const SSL_OP_SSLEAY_080_CLIENT_DH_BUG = 0x00000080 ,
+ const SSL_OP_TLS_D5_BUG = 0x00000100 ,
+ const SSL_OP_TLS_BLOCK_PADDING_BUG = 0x00000200 ,
+ const SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = 0x00000800 ,
+ const SSL_OP_ALL = 0x80000BFF ,
+ const SSL_OP_NO_QUERY_MTU = 0x00001000 ,
+ const SSL_OP_COOKIE_EXCHANGE = 0x00002000 ,
+ const SSL_OP_NO_TICKET = 0x00004000 ,
+ const SSL_OP_CISCO_ANYCONNECT = 0x00008000 ,
+ const SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION = 0x00010000 ,
+ const SSL_OP_NO_COMPRESSION = 0x00020000 ,
+ const SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION = 0x00040000 ,
+ const SSL_OP_SINGLE_ECDH_USE = 0x00080000 ,
+ const SSL_OP_SINGLE_DH_USE = 0x00100000 ,
+ const SSL_OP_CIPHER_SERVER_PREFERENCE = 0x00400000 ,
+ const SSL_OP_TLS_ROLLBACK_BUG = 0x00800000 ,
+ const SSL_OP_NO_SSLV2 = 0x00000000 ,
+ const SSL_OP_NO_SSLV3 = 0x02000000 ,
+ const SSL_OP_NO_TLSV1 = 0x04000000 ,
+ const SSL_OP_NO_TLSV1_2 = 0x08000000 ,
+ const SSL_OP_NO_TLSV1_1 = 0x10000000 ,
+ const SSL_OP_NO_DTLSV1 = 0x04000000 ,
+ const SSL_OP_NO_DTLSV1_2 = 0x08000000
+ }
+}
+
+
+#[allow (non_camel_case_types )]
+#[derive (Copy , Clone , Debug , Hash , PartialEq , Eq )]
+pub enum SslMethod {
+ #[cfg (feature = "sslv2" )]
+
+ Sslv2 ,
+
+ Sslv23 ,
+
+ Sslv3 ,
+
+ Tlsv1 ,
+ #[cfg (feature = "tlsv1_1" )]
+
+ Tlsv1_1 ,
+ #[cfg (feature = "tlsv1_2" )]
+
+ Tlsv1_2 ,
+ #[cfg (feature = "dtlsv1" )]
+
+ Dtlsv1 ,
+ #[cfg (feature = "dtlsv1_2" )]
+
+ Dtlsv1_2 ,
+}
+
+impl SslMethod {
+ unsafe fn to_raw (& self ) -> * const ffi ::SSL_METHOD {
+ match * self {
+ #[cfg (feature = "sslv2" )]
+ SslMethod ::Sslv2 => ffi ::SSLv2_method (),
+ SslMethod ::Sslv3 => ffi ::SSLv3_method (),
+ SslMethod ::Tlsv1 => ffi ::TLSv1_method (),
+ SslMethod ::Sslv23 => ffi ::SSLv23_method (),
+ #[cfg (feature = "tlsv1_1" )]
+ SslMethod ::Tlsv1_1 => ffi ::TLSv1_1_method (),
+ #[cfg (feature = "tlsv1_2" )]
+ SslMethod ::Tlsv1_2 => ffi ::TLSv1_2_method (),
+ #[cfg (feature = "dtlsv1" )]
+ SslMethod ::Dtlsv1 => ffi ::DTLSv1_method (),
+ #[cfg (feature = "dtlsv1_2" )]
+ SslMethod ::Dtlsv1_2 => ffi ::DTLSv1_2_method (),
+ }
+ }
+
+ #[cfg (feature = "dtlsv1" )]
+ pub fn is_dtlsv1 (& self ) -> bool {
+ * self == SslMethod ::Dtlsv1
+ }
+
+ #[cfg (feature = "dtlsv1_2" )]
+ pub fn is_dtlsv1_2 (& self ) -> bool {
+ * self == SslMethod ::Dtlsv1_2
+ }
+
+ pub fn is_dtls (& self ) -> bool {
+ self .is_dtlsv1 () || self .is_dtlsv1_2 ()
+ }
+
+ #[cfg (not (feature = "dtlsv1" ))]
+ pub fn is_dtlsv1 (& self ) -> bool {
+ false
+ }
+
+ #[cfg (not (feature = "dtlsv1_2" ))]
+ pub fn is_dtlsv1_2 (& self ) -> bool {
+ false
+ }
+}
+
+
+bitflags ! {
+ flags SslVerifyMode : i32 {
+
+ const SSL_VERIFY_PEER = ffi ::SSL_VERIFY_PEER ,
+
+ const SSL_VERIFY_NONE = ffi ::SSL_VERIFY_NONE ,
+
+
+ const SSL_VERIFY_FAIL_IF_NO_PEER_CERT = ffi ::SSL_VERIFY_FAIL_IF_NO_PEER_CERT ,
+ }
+}
+
+lazy_static ! {
+ static ref INDEXES : Mutex < HashMap < TypeId , c_int >> = Mutex ::new (HashMap ::new ());
+}
+
+
+
+
+fn get_verify_data_idx < T : Any + 'static > () -> c_int {
+ extern fn free_data_box < T > (_parent : * mut c_void , ptr : * mut c_void ,
+ _ad : * mut ffi ::CRYPTO_EX_DATA , _idx : c_int ,
+ _argl : c_long , _argp : * mut c_void ) {
+ if ptr != 0 as * mut _ {
+ let _: Box < T > = unsafe { mem ::transmute (ptr ) };
+ }
+ }
+
+ * INDEXES .lock ().unwrap ().entry (TypeId ::of ::< T > ()).or_insert_with (|| {
+ unsafe {
+ let f : ffi ::CRYPTO_EX_free = free_data_box ::< T > ;
+ let idx = ffi ::SSL_CTX_get_ex_new_index (0 , ptr ::null (), None , None , Some (f ));
+ assert ! (idx >= 0 );
+ idx
+ }
+ })
+}
+
+
+
+
+#[cfg (feature = "npn" )]
+fn get_npn_protos_idx () -> c_int {
+ static mut NPN_PROTOS_IDX : c_int = - 1 ;
+ static mut INIT : Once = ONCE_INIT ;
+
+ extern fn free_data_box (_parent : * mut c_void , ptr : * mut c_void ,
+ _ad : * mut ffi ::CRYPTO_EX_DATA , _idx : c_int ,
+ _argl : c_long , _argp : * mut c_void ) {
+ if ! ptr .is_null () {
+ let _: Box < Vec < u8 >> = unsafe { mem ::transmute (ptr ) };
+ }
+ }
+
+ unsafe {
+ INIT .call_once (|| {
+ let f : ffi ::CRYPTO_EX_free = free_data_box ;
+ let idx = ffi ::SSL_CTX_get_ex_new_index (0 , ptr ::null (), None ,
+ None , Some (f ));
+ assert ! (idx >= 0 );
+ NPN_PROTOS_IDX = idx ;
+ });
+ NPN_PROTOS_IDX
+ }
+}
+
+extern fn raw_verify (preverify_ok : c_int , x509_ctx : * mut ffi ::X509_STORE_CTX )
+ -> c_int {
+ unsafe {
+ let idx = ffi ::SSL_get_ex_data_X509_STORE_CTX_idx ();
+ let ssl = ffi ::X509_STORE_CTX_get_ex_data (x509_ctx , idx );
+ let ssl_ctx = ffi ::SSL_get_SSL_CTX (ssl );
+ let verify = ffi ::SSL_CTX_get_ex_data (ssl_ctx , VERIFY_IDX );
+ let verify : Option < VerifyCallback > = mem ::transmute (verify );
+
+ let ctx = X509StoreContext ::new (x509_ctx );
+
+ match verify {
+ None => preverify_ok ,
+ Some (verify ) => verify (preverify_ok != 0 , & ctx ) as c_int
+ }
+ }
+}
+
+extern fn raw_verify_with_data < T > (preverify_ok : c_int ,
+ x509_ctx : * mut ffi ::X509_STORE_CTX ) -> c_int
+ where T : Any + 'static {
+ unsafe {
+ let idx = ffi ::SSL_get_ex_data_X509_STORE_CTX_idx ();
+ let ssl = ffi ::X509_STORE_CTX_get_ex_data (x509_ctx , idx );
+ let ssl_ctx = ffi ::SSL_get_SSL_CTX (ssl );
+
+ let verify = ffi ::SSL_CTX_get_ex_data (ssl_ctx , VERIFY_IDX );
+ let verify : Option < VerifyCallbackData < T >> = mem ::transmute (verify );
+
+ let data = ffi ::SSL_CTX_get_ex_data (ssl_ctx , get_verify_data_idx ::< T > ());
+ let data : Box < T > = mem ::transmute (data );
+
+ let ctx = X509StoreContext ::new (x509_ctx );
+
+ let res = match verify {
+ None => preverify_ok ,
+ Some (verify ) => verify (preverify_ok != 0 , & ctx , & * data ) as c_int
+ };
+
+
+
+
+
+ mem ::forget (data );
+ res
+ }
+}
+
+
+
+
+
+
+
+#[cfg (feature = "npn" )]
+extern fn raw_next_proto_select_cb (ssl : * mut ffi ::SSL ,
+ out : * mut * mut c_uchar , outlen : * mut c_uchar ,
+ inbuf : * const c_uchar , inlen : c_uint ,
+ _arg : * mut c_void ) -> c_int {
+ unsafe {
+
+
+ let ssl_ctx = ffi ::SSL_get_SSL_CTX (ssl );
+ let protocols = ffi ::SSL_CTX_get_ex_data (ssl_ctx , get_npn_protos_idx ());
+ let protocols : & Vec < u8 > = mem ::transmute (protocols );
+
+ let client = protocols .as_ptr ();
+ let client_len = protocols .len () as c_uint ;
+
+
+ ffi ::SSL_select_next_proto (out , outlen , inbuf , inlen , client , client_len );
+ }
+
+ ffi ::SSL_TLSEXT_ERR_OK
+}
+
+
+
+
+
+
+
+
+#[cfg (feature = "npn" )]
+extern fn raw_next_protos_advertise_cb (ssl : * mut ffi ::SSL ,
+ out : * mut * const c_uchar , outlen : * mut c_uint ,
+ _arg : * mut c_void ) -> c_int {
+ unsafe {
+
+ let ssl_ctx = ffi ::SSL_get_SSL_CTX (ssl );
+ let protocols = ffi ::SSL_CTX_get_ex_data (ssl_ctx , get_npn_protos_idx ());
+ if protocols .is_null () {
+ * out = b"" .as_ptr ();
+ * outlen = 0 ;
+ } else {
+
+
+ let protocols : & Vec < u8 > = mem ::transmute (protocols );
+ * out = protocols .as_ptr ();
+ * outlen = protocols .len () as c_uint ;
+ }
+ }
+
+ ffi ::SSL_TLSEXT_ERR_OK
+}
+
+
+pub type VerifyCallback = fn (preverify_ok : bool ,
+ x509_ctx : & X509StoreContext ) -> bool ;
+
+
+
+pub type VerifyCallbackData < T > = fn (preverify_ok : bool ,
+ x509_ctx : & X509StoreContext ,
+ data : & T ) -> bool ;
+
+
+#[inline ]
+fn wrap_ssl_result (res : c_int ) -> Result < (),SslError > {
+ if res == 0 {
+ Err (SslError ::get ())
+ } else {
+ Ok (())
+ }
+}
+
+
+pub struct SslContext {
+ ctx : * mut ffi ::SSL_CTX
+}
+
+unsafe impl Send for SslContext {}
+unsafe impl Sync for SslContext {}
+
+
+impl fmt ::Debug for SslContext {
+ fn fmt (& self , fmt : & mut fmt ::Formatter ) -> fmt ::Result {
+ write ! (fmt , "SslContext" )
+ }
+}
+
+impl Drop for SslContext {
+ fn drop (& mut self ) {
+ unsafe { ffi ::SSL_CTX_free (self .ctx ) }
+ }
+}
+
+impl SslContext {
+
+ pub fn new (method : SslMethod ) -> Result < SslContext , SslError > {
+ init ();
+
+ let ctx = unsafe { ffi ::SSL_CTX_new (method .to_raw ()) };
+ if ctx == ptr ::null_mut () {
+ return Err (SslError ::get ());
+ }
+
+ let ctx = SslContext { ctx : ctx };
+
+ if method .is_dtls () {
+ ctx .set_read_ahead (1 );
+ }
+
+ Ok (ctx )
+ }
+
+
+ pub fn set_verify (& mut self , mode : SslVerifyMode ,
+ verify : Option < VerifyCallback > ) {
+ unsafe {
+ ffi ::SSL_CTX_set_ex_data (self .ctx , VERIFY_IDX ,
+ mem ::transmute (verify ));
+ let f : extern fn (c_int , * mut ffi ::X509_STORE_CTX ) -> c_int =
+ raw_verify ;
+
+ ffi ::SSL_CTX_set_verify (self .ctx , mode .bits as c_int , Some (f ));
+ }
+ }
+
+
+
+
+
+ pub fn set_verify_with_data < T > (& mut self , mode : SslVerifyMode ,
+ verify : VerifyCallbackData < T > ,
+ data : T )
+ where T : Any + 'static {
+ let data = Box ::new (data );
+ unsafe {
+ ffi ::SSL_CTX_set_ex_data (self .ctx , VERIFY_IDX ,
+ mem ::transmute (Some (verify )));
+ ffi ::SSL_CTX_set_ex_data (self .ctx , get_verify_data_idx ::< T > (),
+ mem ::transmute (data ));
+ let f : extern fn (c_int , * mut ffi ::X509_STORE_CTX ) -> c_int =
+ raw_verify_with_data ::< T > ;
+
+ ffi ::SSL_CTX_set_verify (self .ctx , mode .bits as c_int , Some (f ));
+ }
+ }
+
+
+ pub fn set_verify_depth (& mut self , depth : u32 ) {
+ unsafe {
+ ffi ::SSL_CTX_set_verify_depth (self .ctx , depth as c_int );
+ }
+ }
+
+ pub fn set_read_ahead (& self , m : u32 ) {
+ unsafe {
+ ffi ::SSL_CTX_set_read_ahead (self .ctx , m as c_long );
+ }
+ }
+
+ #[allow (non_snake_case )]
+
+ pub fn set_CA_file < P : AsRef < Path >> (& mut self , file : P ) -> Result < (),SslError > {
+ let file = CString ::new (file .as_ref ().as_os_str ().to_str ().expect ("invalid utf8" )).unwrap ();
+ wrap_ssl_result (
+ unsafe {
+ ffi ::SSL_CTX_load_verify_locations (self .ctx , file .as_ptr (), ptr ::null ())
+ })
+ }
+
+
+ pub fn set_certificate_file < P : AsRef < Path >> (& mut self , file : P , file_type : X509FileType )
+ -> Result < (),SslError > {
+ let file = CString ::new (file .as_ref ().as_os_str ().to_str ().expect ("invalid utf8" )).unwrap ();
+ wrap_ssl_result (
+ unsafe {
+ ffi ::SSL_CTX_use_certificate_file (self .ctx , file .as_ptr (), file_type as c_int )
+ })
+ }
+
+
+ pub fn set_certificate (& mut self , cert : & X509 ) -> Result < (),SslError > {
+ wrap_ssl_result (
+ unsafe {
+ ffi ::SSL_CTX_use_certificate (self .ctx , cert .get_handle ())
+ })
+ }
+
+
+
+ pub fn add_extra_chain_cert (& mut self , cert : & X509 ) -> Result < (),SslError > {
+ wrap_ssl_result (
+ unsafe {
+ ffi ::SSL_CTX_add_extra_chain_cert (self .ctx , cert .get_handle ()) as c_int
+ })
+ }
+
+
+ pub fn set_private_key_file < P : AsRef < Path >> (& mut self , file : P ,
+ file_type : X509FileType ) -> Result < (),SslError > {
+ let file = CString ::new (file .as_ref ().as_os_str ().to_str ().expect ("invalid utf8" )).unwrap ();
+ wrap_ssl_result (
+ unsafe {
+ ffi ::SSL_CTX_use_PrivateKey_file (self .ctx , file .as_ptr (), file_type as c_int )
+ })
+ }
+
+
+ pub fn set_private_key (& mut self , key : & PKey ) -> Result < (),SslError > {
+ wrap_ssl_result (
+ unsafe {
+ ffi ::SSL_CTX_use_PrivateKey (self .ctx , key .get_handle ())
+ })
+ }
+
+
+ pub fn check_private_key (& mut self ) -> Result < (),SslError > {
+ wrap_ssl_result (
+ unsafe {
+ ffi ::SSL_CTX_check_private_key (self .ctx )
+ })
+ }
+
+ pub fn set_cipher_list (& mut self , cipher_list : & str ) -> Result < (),SslError > {
+ wrap_ssl_result (
+ unsafe {
+ let cipher_list = CString ::new (cipher_list .as_bytes ()).unwrap ();
+ ffi ::SSL_CTX_set_cipher_list (self .ctx , cipher_list .as_ptr ())
+ })
+ }
+
+ pub fn set_options (& mut self , option : SslContextOptions ) -> SslContextOptions {
+ let raw_bits = option .bits ();
+ let ret = unsafe {
+ ffi ::SSL_CTX_set_options (self .ctx , raw_bits )
+ };
+ SslContextOptions ::from_bits (ret ).unwrap ()
+ }
+
+ pub fn get_options (& mut self ) -> SslContextOptions {
+ let ret = unsafe {
+ ffi ::SSL_CTX_get_options (self .ctx )
+ };
+ SslContextOptions ::from_bits (ret ).unwrap ()
+ }
+
+ pub fn clear_options (& mut self , option : SslContextOptions ) -> SslContextOptions {
+ let raw_bits = option .bits ();
+ let ret = unsafe {
+ ffi ::SSL_CTX_clear_options (self .ctx , raw_bits )
+ };
+ SslContextOptions ::from_bits (ret ).unwrap ()
+ }
+
+
+
+
+
+ #[cfg (feature = "npn" )]
+ pub fn set_npn_protocols (& mut self , protocols : & [& [u8 ]]) {
+
+
+ let mut npn_protocols = Vec ::new ();
+ for protocol in protocols {
+ let len = protocol .len () as u8 ;
+ npn_protocols .push (len );
+
+ npn_protocols .extend (protocol [..len as usize ].to_vec ());
+ }
+ let protocols : Box < Vec < u8 >> = Box ::new (npn_protocols );
+
+ unsafe {
+
+
+ ffi ::SSL_CTX_set_ex_data (self .ctx , get_npn_protos_idx (),
+ mem ::transmute (protocols ));
+
+
+
+ ffi ::SSL_CTX_set_next_proto_select_cb (self .ctx , raw_next_proto_select_cb , ptr ::null_mut ());
+
+
+ ffi ::SSL_CTX_set_next_protos_advertised_cb (self .ctx , raw_next_protos_advertise_cb , ptr ::null_mut ());
+ }
+ }
+}
+
+#[allow (dead_code )]
+struct MemBioRef < 'ssl > {
+ ssl : & 'ssl Ssl ,
+ bio : MemBio ,
+}
+
+impl < 'ssl > Deref for MemBioRef < 'ssl > {
+ type Target = MemBio ;
+
+ fn deref (& self ) -> & MemBio {
+ & self .bio
+ }
+}
+
+impl < 'ssl > DerefMut for MemBioRef < 'ssl > {
+ fn deref_mut (& mut self ) -> & mut MemBio {
+ & mut self .bio
+ }
+}
+
+pub struct Ssl {
+ ssl : * mut ffi ::SSL
+}
+
+unsafe impl Send for Ssl {}
+unsafe impl Sync for Ssl {}
+
+
+impl fmt ::Debug for Ssl {
+ fn fmt (& self , fmt : & mut fmt ::Formatter ) -> fmt ::Result {
+ write ! (fmt , "Ssl" )
+ }
+}
+
+impl Drop for Ssl {
+ fn drop (& mut self ) {
+ unsafe { ffi ::SSL_free (self .ssl ) }
+ }
+}
+
+impl Ssl {
+ pub fn new (ctx : & SslContext ) -> Result < Ssl , SslError > {
+ let ssl = unsafe { ffi ::SSL_new (ctx .ctx ) };
+ if ssl == ptr ::null_mut () {
+ return Err (SslError ::get ());
+ }
+ let ssl = Ssl { ssl : ssl };
+
+ let rbio = try ! (MemBio ::new ());
+ let wbio = try ! (MemBio ::new ());
+
+ unsafe { ffi ::SSL_set_bio (ssl .ssl , rbio .unwrap (), wbio .unwrap ()) }
+ Ok (ssl )
+ }
+
+ fn get_rbio < 'a > (& 'a self ) -> MemBioRef < 'a > {
+ unsafe { self .wrap_bio (ffi ::SSL_get_rbio (self .ssl )) }
+ }
+
+ fn get_wbio < 'a > (& 'a self ) -> MemBioRef < 'a > {
+ unsafe { self .wrap_bio (ffi ::SSL_get_wbio (self .ssl )) }
+ }
+
+ fn wrap_bio < 'a > (& 'a self , bio : * mut ffi ::BIO ) -> MemBioRef < 'a > {
+ assert ! (bio != ptr ::null_mut ());
+ MemBioRef {
+ ssl : self ,
+ bio : MemBio ::borrowed (bio )
+ }
+ }
+
+ fn connect (& self ) -> c_int {
+ unsafe { ffi ::SSL_connect (self .ssl ) }
+ }
+
+ fn accept (& self ) -> c_int {
+ unsafe { ffi ::SSL_accept (self .ssl ) }
+ }
+
+ fn read (& self , buf : & mut [u8 ]) -> c_int {
+ let len = cmp ::min (c_int ::max_value () as usize , buf .len ()) as c_int ;
+ unsafe { ffi ::SSL_read (self .ssl , buf .as_ptr () as * mut c_void , len ) }
+ }
+
+ fn write (& self , buf : & [u8 ]) -> c_int {
+ let len = cmp ::min (c_int ::max_value () as usize , buf .len ()) as c_int ;
+ unsafe { ffi ::SSL_write (self .ssl , buf .as_ptr () as * const c_void , len ) }
+ }
+
+ fn get_error (& self , ret : c_int ) -> LibSslError {
+ let err = unsafe { ffi ::SSL_get_error (self .ssl , ret ) };
+ match LibSslError ::from_i32 (err as i32 ) {
+ Some (err ) => err ,
+ None => unreachable ! ()
+ }
+ }
+
+
+ pub fn set_hostname (& self , hostname : & str ) -> Result < (), SslError > {
+ let ret = unsafe {
+
+
+
+
+ let hostname = CString ::new (hostname .as_bytes ()).unwrap ();
+ ffi ::SSL_ctrl (self .ssl , ffi ::SSL_CTRL_SET_TLSEXT_HOSTNAME ,
+ ffi ::TLSEXT_NAMETYPE_host_name ,
+ hostname .as_ptr () as * mut c_void )
+ };
+
+
+ if ret == 0 {
+ Err (SslError ::get ())
+ } else {
+ Ok (())
+ }
+ }
+
+ pub fn get_peer_certificate (& self ) -> Option < X509 > {
+ unsafe {
+ let ptr = ffi ::SSL_get_peer_certificate (self .ssl );
+ if ptr .is_null () {
+ None
+ } else {
+ Some (X509 ::new (ptr , true ))
+ }
+ }
+ }
+
+
+
+
+
+
+
+ #[cfg (feature = "npn" )]
+ pub fn get_selected_npn_protocol (& self ) -> Option < & [u8 ]> {
+ unsafe {
+ let mut data : * const c_uchar = ptr ::null ();
+ let mut len : c_uint = 0 ;
+
+
+ ffi ::SSL_get0_next_proto_negotiated (self .ssl , & mut data , & mut len );
+
+ if data .is_null () {
+ None
+ } else {
+ Some (slice ::from_raw_parts (data , len as usize ))
+ }
+ }
+ }
+
+
+ pub fn pending (& self ) -> usize {
+ unsafe {
+ ffi ::SSL_pending (self .ssl ) as usize
+ }
+ }
+}
+
+macro_rules ! make_LibSslError {
+ ($($ variant :ident = $ value :ident ),+ ) => {
+ #[derive (Debug )]
+ #[repr (i32 )]
+ enum LibSslError {
+ $($ variant = ffi ::$ value ),+
+ }
+
+ impl LibSslError {
+ fn from_i32 (val : i32 ) -> Option < LibSslError > {
+ match val {
+ $(ffi ::$ value => Some (LibSslError ::$ variant ),)+
+ _ => None
+ }
+ }
+ }
+ }
+}
+
+make_LibSslError ! {
+ ErrorNone = SSL_ERROR_NONE ,
+ ErrorSsl = SSL_ERROR_SSL ,
+ ErrorWantRead = SSL_ERROR_WANT_READ ,
+ ErrorWantWrite = SSL_ERROR_WANT_WRITE ,
+ ErrorWantX509Lookup = SSL_ERROR_WANT_X509_LOOKUP ,
+ ErrorSyscall = SSL_ERROR_SYSCALL ,
+ ErrorZeroReturn = SSL_ERROR_ZERO_RETURN ,
+ ErrorWantConnect = SSL_ERROR_WANT_CONNECT ,
+ ErrorWantAccept = SSL_ERROR_WANT_ACCEPT
+}
+
+
+#[derive (Clone )]
+pub struct SslStream < S > {
+ stream : S ,
+ ssl : Arc < Ssl > ,
+ buf : Vec < u8 >
+}
+
+impl SslStream < net ::TcpStream > {
+
+ pub fn try_clone (& self ) -> io ::Result < SslStream < net ::TcpStream >> {
+ Ok (SslStream {
+ stream : try ! (self .stream .try_clone ()),
+ ssl : self .ssl .clone (),
+ buf : self .buf .clone (),
+ })
+ }
+}
+
+impl < S > fmt ::Debug for SslStream < S > where S : fmt ::Debug {
+ fn fmt (& self , fmt : & mut fmt ::Formatter ) -> fmt ::Result {
+ write ! (fmt , "SslStream {{ stream: {:?}, ssl: {:?} }}" , self .stream , self .ssl )
+ }
+}
+
+impl < S : Read + Write > SslStream < S > {
+ fn new_base (ssl :Ssl , stream : S ) -> SslStream < S > {
+ SslStream {
+ stream : stream ,
+ ssl : Arc ::new (ssl ),
+
+
+
+ buf : {
+ const CAP : usize = 16 * 1024 ;
+ let mut v = Vec ::with_capacity (CAP );
+ unsafe { v .set_len (CAP ); }
+ v
+ }
+ }
+ }
+
+ pub fn new_server_from (ssl : Ssl , stream : S ) -> Result < SslStream < S > , SslError > {
+ let mut ssl = SslStream ::new_base (ssl , stream );
+ ssl .in_retry_wrapper (| ssl | { ssl .accept () }).and (Ok (ssl ))
+ }
+
+
+ pub fn new_from (ssl : Ssl , stream : S ) -> Result < SslStream < S > , SslError > {
+ let mut ssl = SslStream ::new_base (ssl , stream );
+ ssl .in_retry_wrapper (| ssl | { ssl .connect () }).and (Ok (ssl ))
+ }
+
+
+ pub fn new (ctx : & SslContext , stream : S ) -> Result < SslStream < S > , SslError > {
+ let ssl = try ! (Ssl ::new (ctx ));
+ SslStream ::new_from (ssl , stream )
+ }
+
+
+ pub fn new_server (ctx : & SslContext , stream : S ) -> Result < SslStream < S > , SslError > {
+ let ssl = try ! (Ssl ::new (ctx ));
+ SslStream ::new_server_from (ssl , stream )
+ }
+
+ #[doc (hidden )]
+ pub fn get_inner (& mut self ) -> & mut S {
+ self .get_mut ()
+ }
+
+
+ pub fn get_ref (& self ) -> & S {
+ & self .stream
+ }
+
+
+ pub fn get_peer_certificate (& self ) -> Option < X509 > {
+ self .ssl .get_peer_certificate ()
+ }
+
+
+
+
+
+
+
+ pub fn get_mut (& mut self ) -> & mut S {
+ & mut self .stream
+ }
+
+ fn in_retry_wrapper < F > (& mut self , mut blk : F )
+ -> Result < c_int , SslError > where F : FnMut (& Ssl ) -> c_int {
+ loop {
+ let ret = blk (& self .ssl );
+ if ret > 0 {
+ return Ok (ret );
+ }
+
+ let e = self .ssl .get_error (ret );
+ match e {
+ LibSslError ::ErrorWantRead => {
+ try_ssl_stream ! (self .flush ());
+ let len = try_ssl_stream ! (self .stream .read (& mut self .buf [..]));
+ if len == 0 {
+ self .ssl .get_rbio ().set_eof (true );
+ } else {
+ try_ssl_stream ! (self .ssl .get_rbio ().write_all (& self .buf [..len ]));
+ }
+ }
+ LibSslError ::ErrorWantWrite => { try_ssl_stream ! (self .flush ()) }
+ LibSslError ::ErrorZeroReturn => return Err (SslSessionClosed ),
+ LibSslError ::ErrorSsl => return Err (SslError ::get ()),
+ LibSslError ::ErrorSyscall if ret == 0 => return Ok (0 ),
+ err => panic ! ("unexpected error {:?} with ret {}" , err , ret ),
+ }
+ }
+ }
+
+ fn write_through (& mut self ) -> io ::Result < ()> {
+ io ::copy (& mut * self .ssl .get_wbio (), & mut self .stream ).map (| _| ())
+ }
+
+
+
+
+ pub fn get_compression (& self ) -> Option < String > {
+ let ptr = unsafe { ffi ::SSL_get_current_compression (self .ssl .ssl ) };
+ if ptr == ptr ::null () {
+ return None ;
+ }
+
+ let meth = unsafe { ffi ::SSL_COMP_get_name (ptr ) };
+ let s = unsafe {
+ String ::from_utf8 (CStr ::from_ptr (meth ).to_bytes ().to_vec ()).unwrap ()
+ };
+
+ Some (s )
+ }
+
+
+
+
+
+
+
+ #[cfg (feature = "npn" )]
+ pub fn get_selected_npn_protocol (& self ) -> Option < & [u8 ]> {
+ self .ssl .get_selected_npn_protocol ()
+ }
+
+
+ pub fn pending (& self ) -> usize {
+ self .ssl .pending ()
+ }
+}
+
+impl < S : Read + Write > Read for SslStream < S > {
+ fn read (& mut self , buf : & mut [u8 ]) -> io ::Result < usize > {
+ match self .in_retry_wrapper (| ssl | { ssl .read (buf ) }) {
+ Ok (len ) => Ok (len as usize ),
+ Err (SslSessionClosed ) => Ok (0 ),
+ Err (StreamError (e )) => Err (e ),
+ Err (e @ OpenSslErrors (_)) => {
+ Err (io ::Error ::new (io ::ErrorKind ::Other , e ))
+ }
+ }
+ }
+}
+
+impl < S : Read + Write > Write for SslStream < S > {
+ fn write (& mut self , buf : & [u8 ]) -> io ::Result < usize > {
+ let count = match self .in_retry_wrapper (| ssl | ssl .write (buf )) {
+ Ok (len ) => len as usize ,
+ Err (SslSessionClosed ) => 0 ,
+ Err (StreamError (e )) => return Err (e ),
+ Err (e @ OpenSslErrors (_)) => return Err (io ::Error ::new (io ::ErrorKind ::Other , e )),
+ };
+ try ! (self .write_through ());
+ Ok (count )
+ }
+
+ fn flush (& mut self ) -> io ::Result < ()> {
+ try ! (self .write_through ());
+ self .stream .flush ()
+ }
+}
+
+
+#[derive (Debug )]
+pub enum MaybeSslStream < S > where S : Read + Write {
+
+ Ssl (SslStream < S > ),
+
+ Normal (S ),
+}
+
+impl < S > Read for MaybeSslStream < S > where S : Read + Write {
+ fn read (& mut self , buf : & mut [u8 ]) -> io ::Result < usize > {
+ match * self {
+ MaybeSslStream ::Ssl (ref mut s ) => s .read (buf ),
+ MaybeSslStream ::Normal (ref mut s ) => s .read (buf ),
+ }
+ }
+}
+
+impl < S > Write for MaybeSslStream < S > where S : Read + Write {
+ fn write (& mut self , buf : & [u8 ]) -> io ::Result < usize > {
+ match * self {
+ MaybeSslStream ::Ssl (ref mut s ) => s .write (buf ),
+ MaybeSslStream ::Normal (ref mut s ) => s .write (buf ),
+ }
+ }
+
+ fn flush (& mut self ) -> io ::Result < ()> {
+ match * self {
+ MaybeSslStream ::Ssl (ref mut s ) => s .flush (),
+ MaybeSslStream ::Normal (ref mut s ) => s .flush (),
+ }
+ }
+}
+
+impl < S > MaybeSslStream < S > where S : Read + Write {
+
+ pub fn get_ref (& self ) -> & S {
+ match * self {
+ MaybeSslStream ::Ssl (ref s ) => s .get_ref (),
+ MaybeSslStream ::Normal (ref s ) => s ,
+ }
+ }
+
+
+
+
+
+
+ pub fn get_mut (& mut self ) -> & mut S {
+ match * self {
+ MaybeSslStream ::Ssl (ref mut s ) => s .get_mut (),
+ MaybeSslStream ::Normal (ref mut s ) => s ,
+ }
+ }
+}
+
+
+
+
+
+
+
+
+
Keyboard shortcuts
+
+ ?
+ Show this help dialog
+ S
+ Focus the search field
+ ⇤
+ Move up in search results
+ ⇥
+ Move down in search results
+ ⏎
+ Go to active search result
+
+
+
+
Search tricks
+
+ Prefix searches with a type followed by a colon (e.g.
+ fn:
) to restrict the search to a given type.
+
+
+ Accepted types are: fn
, mod
,
+ struct
, enum
,
+ trait
, typedef
(or
+ tdef
).
+
+
+ Search functions by type signature (e.g.
+ vec -> usize
)
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/openssl/x509/mod.rs.html b/src/openssl/x509/mod.rs.html
new file mode 100644
index 0000000..ea45241
--- /dev/null
+++ b/src/openssl/x509/mod.rs.html
@@ -0,0 +1,1461 @@
+
+
+
+
+
+
+
+
+
+ mod.rs.html -- source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+
+use libc ::{c_char , c_int , c_long , c_ulong , c_uint , c_void };
+use std ::io ;
+use std ::io ::prelude ::* ;
+use std ::cmp ::Ordering ;
+use std ::ffi ::{CString , CStr };
+use std ::iter ::repeat ;
+use std ::mem ;
+use std ::ptr ;
+use std ::ops ::Deref ;
+use std ::fmt ;
+use std ::str ;
+
+use asn1 ::{Asn1Time };
+use bio ::{MemBio };
+use crypto ::hash ;
+use crypto ::hash ::Type as HashType ;
+use crypto ::pkey ::{PKey ,Parts };
+use crypto ::rand ::rand_bytes ;
+use ffi ;
+use ssl ::error ::{SslError , StreamError };
+use nid ;
+
+
+#[cfg (test )]
+mod tests ;
+
+pub struct SslString {
+ s : & 'static str
+}
+
+impl < 's > Drop for SslString {
+ fn drop (& mut self ) {
+ unsafe { ffi ::CRYPTO_free (self .s .as_ptr () as * mut c_void ); }
+ }
+}
+
+impl Deref for SslString {
+ type Target = str ;
+
+ fn deref (& self ) -> & str {
+ self .s
+ }
+}
+
+impl SslString {
+ unsafe fn new (buf : * const c_char ) -> SslString {
+ SslString {
+ s : str ::from_utf8 (CStr ::from_ptr (buf ).to_bytes ()).unwrap ()
+ }
+ }
+}
+
+impl fmt ::Display for SslString {
+ fn fmt (& self , f : & mut fmt ::Formatter ) -> fmt ::Result {
+ fmt ::Display ::fmt (self .s , f )
+ }
+}
+
+impl fmt ::Debug for SslString {
+ fn fmt (& self , f : & mut fmt ::Formatter ) -> fmt ::Result {
+ fmt ::Debug ::fmt (self .s , f )
+ }
+}
+
+#[derive (Copy , Clone )]
+#[repr (i32 )]
+pub enum X509FileType {
+ PEM = ffi ::X509_FILETYPE_PEM ,
+ ASN1 = ffi ::X509_FILETYPE_ASN1 ,
+ Default = ffi ::X509_FILETYPE_DEFAULT
+}
+
+#[allow (missing_copy_implementations )]
+pub struct X509StoreContext {
+ ctx : * mut ffi ::X509_STORE_CTX
+}
+
+impl X509StoreContext {
+ pub fn new (ctx : * mut ffi ::X509_STORE_CTX ) -> X509StoreContext {
+ X509StoreContext {
+ ctx : ctx
+ }
+ }
+
+ pub fn get_error (& self ) -> Option < X509ValidationError > {
+ let err = unsafe { ffi ::X509_STORE_CTX_get_error (self .ctx ) };
+ X509ValidationError ::from_raw (err )
+ }
+
+ pub fn get_current_cert < 'a > (& 'a self ) -> Option < X509 < 'a >> {
+ let ptr = unsafe { ffi ::X509_STORE_CTX_get_current_cert (self .ctx ) };
+
+ if ptr .is_null () {
+ None
+ } else {
+ Some (X509 { ctx : Some (self ), handle : ptr , owned : false })
+ }
+ }
+}
+
+#[doc (hidden )]
+trait AsStr < 'a > {
+ fn as_str (& self ) -> & 'a str ;
+}
+
+#[derive (Clone , Copy )]
+pub enum KeyUsage {
+ DigitalSignature ,
+ NonRepudiation ,
+ KeyEncipherment ,
+ DataEncipherment ,
+ KeyAgreement ,
+ KeyCertSign ,
+ CRLSign ,
+ EncipherOnly ,
+ DecipherOnly
+}
+
+impl AsStr < 'static > for KeyUsage {
+ fn as_str (& self ) -> & 'static str {
+ match self {
+ & KeyUsage ::DigitalSignature => "digitalSignature" ,
+ & KeyUsage ::NonRepudiation => "nonRepudiation" ,
+ & KeyUsage ::KeyEncipherment => "keyEncipherment" ,
+ & KeyUsage ::DataEncipherment => "dataEncipherment" ,
+ & KeyUsage ::KeyAgreement => "keyAgreement" ,
+ & KeyUsage ::KeyCertSign => "keyCertSign" ,
+ & KeyUsage ::CRLSign => "cRLSign" ,
+ & KeyUsage ::EncipherOnly => "encipherOnly" ,
+ & KeyUsage ::DecipherOnly => "decipherOnly"
+ }
+ }
+}
+
+
+#[derive (Clone , Copy )]
+pub enum ExtKeyUsage {
+ ServerAuth ,
+ ClientAuth ,
+ CodeSigning ,
+ EmailProtection ,
+ TimeStamping ,
+ MsCodeInd ,
+ MsCodeCom ,
+ MsCtlSign ,
+ MsSgc ,
+ MsEfs ,
+ NsSgc
+}
+
+impl AsStr < 'static > for ExtKeyUsage {
+ fn as_str (& self ) -> & 'static str {
+ match self {
+ & ExtKeyUsage ::ServerAuth => "serverAuth" ,
+ & ExtKeyUsage ::ClientAuth => "clientAuth" ,
+ & ExtKeyUsage ::CodeSigning => "codeSigning" ,
+ & ExtKeyUsage ::EmailProtection => "emailProtection" ,
+ & ExtKeyUsage ::TimeStamping => "timeStamping" ,
+ & ExtKeyUsage ::MsCodeInd => "msCodeInd" ,
+ & ExtKeyUsage ::MsCodeCom => "msCodeCom" ,
+ & ExtKeyUsage ::MsCtlSign => "msCTLSign" ,
+ & ExtKeyUsage ::MsSgc => "msSGC" ,
+ & ExtKeyUsage ::MsEfs => "msEFS" ,
+ & ExtKeyUsage ::NsSgc => "nsSGC"
+ }
+ }
+}
+
+
+
+
+
+#[doc (hidden )]
+trait ToStr {
+ fn to_str (& self ) -> String ;
+}
+
+impl < 'a , T : AsStr < 'a >> ToStr for Vec < T > {
+ fn to_str (& self ) -> String {
+ self .iter ().enumerate ().fold (String ::new (), | mut acc , (idx , v )| {
+ if idx > 0 { acc .push (',' ) };
+ acc .push_str (v .as_str ());
+ acc
+ })
+ }
+}
+
+#[allow (non_snake_case )]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+pub struct X509Generator {
+ bits : u32 ,
+ days : u32 ,
+ CN : String ,
+ key_usage : Vec < KeyUsage > ,
+ ext_key_usage : Vec < ExtKeyUsage > ,
+ hash_type : HashType ,
+}
+
+impl X509Generator {
+
+
+
+
+
+
+
+
+
+ pub fn new () -> X509Generator {
+ X509Generator {
+ bits : 1024 ,
+ days : 365 ,
+ CN : "rust-openssl" .to_string (),
+ key_usage : Vec ::new (),
+ ext_key_usage : Vec ::new (),
+ hash_type : HashType ::SHA1
+ }
+ }
+
+
+ pub fn set_bitlength (mut self , bits : u32 ) -> X509Generator {
+ self .bits = bits ;
+ self
+ }
+
+
+ pub fn set_valid_period (mut self , days : u32 ) -> X509Generator {
+ self .days = days ;
+ self
+ }
+
+ #[allow (non_snake_case )]
+
+ pub fn set_CN (mut self , CN : & str ) -> X509Generator {
+ self .CN = CN .to_string ();
+ self
+ }
+
+
+ pub fn set_usage (mut self , purposes : & [KeyUsage ]) -> X509Generator {
+ self .key_usage = purposes .to_vec ();
+ self
+ }
+
+
+ pub fn set_ext_usage (mut self , purposes : & [ExtKeyUsage ]) -> X509Generator {
+ self .ext_key_usage = purposes .to_vec ();
+ self
+ }
+
+ pub fn set_sign_hash (mut self , hash_type : hash ::Type ) -> X509Generator {
+ self .hash_type = hash_type ;
+ self
+ }
+
+ fn add_extension (x509 : * mut ffi ::X509 , extension : c_int , value : & str ) -> Result < (), SslError > {
+ unsafe {
+ let mut ctx : ffi ::X509V3_CTX = mem ::zeroed ();
+ ffi ::X509V3_set_ctx (& mut ctx , x509 , x509 ,
+ ptr ::null_mut (), ptr ::null_mut (), 0 );
+ let value = CString ::new (value .as_bytes ()).unwrap ();
+ let ext = ffi ::X509V3_EXT_conf_nid (ptr ::null_mut (),
+ mem ::transmute (& ctx ),
+ extension ,
+ value .as_ptr () as * mut c_char );
+
+ let mut success = false ;
+ if ext != ptr ::null_mut () {
+ success = ffi ::X509_add_ext (x509 , ext , - 1 ) != 0 ;
+ ffi ::X509_EXTENSION_free (ext );
+ }
+ lift_ssl_if ! (! success )
+ }
+ }
+
+ fn add_name (name : * mut ffi ::X509_NAME , key : & str , value : & str ) -> Result < (), SslError > {
+ let value_len = value .len () as c_int ;
+ lift_ssl ! (unsafe {
+ let key = CString ::new (key .as_bytes ()).unwrap ();
+ let value = CString ::new (value .as_bytes ()).unwrap ();
+ ffi ::X509_NAME_add_entry_by_txt (name , key .as_ptr (), ffi ::MBSTRING_UTF8 ,
+ value .as_ptr (), value_len , - 1 , 0 )
+ })
+ }
+
+ fn random_serial () -> c_long {
+ let len = mem ::size_of ::< c_long > ();
+ let bytes = rand_bytes (len );
+ let mut res = 0 ;
+ for b in bytes .iter () {
+ res = res << 8 ;
+ res |= (* b as c_long ) & 0xff ;
+ }
+
+
+
+
+ ((res as c_ulong ) >> 1 ) as c_long
+ }
+
+
+ pub fn generate < 'a > (& self ) -> Result < (X509 < 'a > , PKey ), SslError > {
+ ffi ::init ();
+
+ let mut p_key = PKey ::new ();
+ p_key .gen (self .bits as usize );
+
+ let x509 = try ! (self .sign (& p_key ));
+ Ok ((x509 , p_key ))
+ }
+
+
+
+ pub fn sign < 'a > (& self , p_key : & PKey ) -> Result < X509 < 'a > , SslError > {
+ ffi ::init ();
+
+ unsafe {
+ let x509 = ffi ::X509_new ();
+ try_ssl_null ! (x509 );
+
+ let x509 = X509 { handle : x509 , ctx : None , owned : true };
+
+ try_ssl ! (ffi ::X509_set_version (x509 .handle , 2 ));
+ try_ssl ! (ffi ::ASN1_INTEGER_set (ffi ::X509_get_serialNumber (x509 .handle ), X509Generator ::random_serial ()));
+
+ let not_before = try ! (Asn1Time ::days_from_now (0 ));
+ let not_after = try ! (Asn1Time ::days_from_now (self .days ));
+
+ try_ssl ! (ffi ::X509_set_notBefore (x509 .handle , mem ::transmute (not_before .get_handle ())));
+
+ mem ::forget (not_before );
+
+ try_ssl ! (ffi ::X509_set_notAfter (x509 .handle , mem ::transmute (not_after .get_handle ())));
+
+ mem ::forget (not_after );
+
+ try_ssl ! (ffi ::X509_set_pubkey (x509 .handle , p_key .get_handle ()));
+
+ let name = ffi ::X509_get_subject_name (x509 .handle );
+ try_ssl_null ! (name );
+
+ try ! (X509Generator ::add_name (name , "CN" , & self .CN ));
+ ffi ::X509_set_issuer_name (x509 .handle , name );
+
+ if self .key_usage .len () > 0 {
+ try ! (X509Generator ::add_extension (x509 .handle , ffi ::NID_key_usage ,
+ & self .key_usage .to_str ()));
+ }
+
+ if self .ext_key_usage .len () > 0 {
+ try ! (X509Generator ::add_extension (x509 .handle , ffi ::NID_ext_key_usage ,
+ & self .ext_key_usage .to_str ()));
+ }
+
+ let hash_fn = self .hash_type .evp_md ();
+ try_ssl ! (ffi ::X509_sign (x509 .handle , p_key .get_handle (), hash_fn ));
+ Ok (x509 )
+ }
+ }
+
+
+ pub fn request (& self , p_key : & PKey ) -> Result < X509Req , SslError > {
+ let cert = match self .sign (p_key ) {
+ Ok (c ) => c ,
+ Err (x ) => return Err (x )
+ };
+
+ let hash_fn = self .hash_type .evp_md ();
+ let req = unsafe { ffi ::X509_to_X509_REQ (cert .handle , p_key .get_handle (), hash_fn ) };
+ try_ssl_null ! (req );
+
+ Ok (X509Req ::new (req ))
+ }
+}
+
+
+#[allow (dead_code )]
+
+pub struct X509 < 'ctx > {
+ ctx : Option < & 'ctx X509StoreContext > ,
+ handle : * mut ffi ::X509 ,
+ owned : bool
+}
+
+impl < 'ctx > X509 < 'ctx > {
+
+ pub fn new (handle : * mut ffi ::X509 , owned : bool ) -> X509 < 'ctx > {
+ X509 {
+ ctx : None ,
+ handle : handle ,
+ owned : owned ,
+ }
+ }
+
+
+
+ pub fn new_in_ctx (handle : * mut ffi ::X509 , ctx : & 'ctx X509StoreContext ) -> X509 < 'ctx > {
+ X509 {
+ ctx : Some (ctx ),
+ handle : handle ,
+ owned : false
+ }
+ }
+
+
+ pub fn from_pem < R > (reader : & mut R ) -> Result < X509 < 'ctx > , SslError > where R : Read {
+ let mut mem_bio = try ! (MemBio ::new ());
+ try ! (io ::copy (reader , & mut mem_bio ).map_err (StreamError ));
+
+ unsafe {
+ let handle = try_ssl_null ! (ffi ::PEM_read_bio_X509 (mem_bio .get_handle (),
+ ptr ::null_mut (),
+ None , ptr ::null_mut ()));
+ Ok (X509 ::new (handle , true ))
+ }
+ }
+
+ pub fn get_handle (& self ) -> * mut ffi ::X509 {
+ self .handle
+ }
+
+ pub fn subject_name < 'a > (& 'a self ) -> X509Name < 'a > {
+ let name = unsafe { ffi ::X509_get_subject_name (self .handle ) };
+ X509Name { x509 : self , name : name }
+ }
+
+ pub fn public_key (& self ) -> PKey {
+ let pkey = unsafe { ffi ::X509_get_pubkey (self .handle ) };
+ assert ! (! pkey .is_null ());
+
+ PKey ::from_handle (pkey , Parts ::Public )
+ }
+
+
+ pub fn fingerprint (& self , hash_type : hash ::Type ) -> Option < Vec < u8 >> {
+ let evp = hash_type .evp_md ();
+ let len = hash_type .md_len ();
+ let v : Vec < u8 > = repeat (0 ).take (len as usize ).collect ();
+ let act_len : c_uint = 0 ;
+ let res = unsafe {
+ ffi ::X509_digest (self .handle , evp , mem ::transmute (v .as_ptr ()),
+ mem ::transmute (& act_len ))
+ };
+
+ match res {
+ 0 => None ,
+ _ => {
+ let act_len = act_len as usize ;
+ match len .cmp (& act_len ) {
+ Ordering ::Greater => None ,
+ Ordering ::Equal => Some (v ),
+ Ordering ::Less => panic ! ("Fingerprint buffer was corrupted!" )
+ }
+ }
+ }
+ }
+
+
+ pub fn write_pem < W > (& self , writer : & mut W ) -> Result < (), SslError > where W : Write {
+ let mut mem_bio = try ! (MemBio ::new ());
+ unsafe {
+ try_ssl ! (ffi ::PEM_write_bio_X509 (mem_bio .get_handle (),
+ self .handle ));
+ }
+ io ::copy (& mut mem_bio , writer ).map_err (StreamError ).map (| _| ())
+ }
+}
+
+impl < 'ctx > Drop for X509 < 'ctx > {
+ fn drop (& mut self ) {
+ if self .owned {
+ unsafe { ffi ::X509_free (self .handle ) };
+ }
+ }
+}
+
+#[allow (dead_code )]
+pub struct X509Name < 'x > {
+ x509 : & 'x X509 < 'x > ,
+ name : * mut ffi ::X509_NAME
+}
+
+#[allow (dead_code )]
+pub struct X509NameEntry < 'x > {
+ x509_name : & 'x X509Name < 'x > ,
+ ne : * mut ffi ::X509_NAME_ENTRY
+}
+
+impl < 'x > X509Name < 'x > {
+ pub fn text_by_nid (& self , nid : nid ::Nid ) -> Option < SslString > {
+ unsafe {
+ let loc = ffi ::X509_NAME_get_index_by_NID (self .name , nid as c_int , - 1 );
+ if loc == - 1 {
+ return None ;
+ }
+
+ let ne = ffi ::X509_NAME_get_entry (self .name , loc );
+ if ne .is_null () {
+ return None ;
+ }
+
+ let asn1_str = ffi ::X509_NAME_ENTRY_get_data (ne );
+ if asn1_str .is_null () {
+ return None ;
+ }
+
+ let mut str_from_asn1 : * mut c_char = ptr ::null_mut ();
+ let len = ffi ::ASN1_STRING_to_UTF8 (& mut str_from_asn1 , asn1_str );
+
+ if len < 0 {
+ return None
+ }
+
+ assert ! (! str_from_asn1 .is_null ());
+
+ Some (SslString ::new (str_from_asn1 ))
+ }
+ }
+}
+
+
+pub struct X509Req {
+ handle : * mut ffi ::X509_REQ ,
+}
+
+impl X509Req {
+
+ pub fn new (handle : * mut ffi ::X509_REQ ) -> X509Req {
+ X509Req {
+ handle : handle ,
+ }
+ }
+
+
+ pub fn from_pem < R > (reader : & mut R ) -> Result < X509Req , SslError > where R : Read {
+ let mut mem_bio = try ! (MemBio ::new ());
+ try ! (io ::copy (reader , & mut mem_bio ).map_err (StreamError ));
+
+ unsafe {
+ let handle = try_ssl_null ! (ffi ::PEM_read_bio_X509_REQ (mem_bio .get_handle (),
+ ptr ::null_mut (),
+ None , ptr ::null_mut ()));
+ Ok (X509Req ::new (handle ))
+ }
+ }
+
+
+ pub fn write_pem < W > (& self , writer : & mut W ) -> Result < (), SslError > where W : Write {
+ let mut mem_bio = try ! (MemBio ::new ());
+ unsafe {
+ try_ssl ! (ffi ::PEM_write_bio_X509_REQ (mem_bio .get_handle (),
+ self .handle ));
+ }
+ io ::copy (& mut mem_bio , writer ).map_err (StreamError ).map (| _| ())
+ }
+}
+
+impl Drop for X509Req {
+ fn drop (& mut self ) {
+ unsafe { ffi ::X509_REQ_free (self .handle ) };
+ }
+}
+
+macro_rules ! make_validation_error (
+ ($ ok_val :ident , $($ name :ident = $ val :ident ,)+ ) => (
+ #[derive (Copy , Clone )]
+ pub enum X509ValidationError {
+ $($ name ,)+
+ X509UnknownError (c_int )
+ }
+
+ impl X509ValidationError {
+ #[doc (hidden )]
+ pub fn from_raw (err : c_int ) -> Option < X509ValidationError > {
+ match err {
+ ffi ::$ ok_val => None ,
+ $(ffi ::$ val => Some (X509ValidationError ::$ name ),)+
+ err => Some (X509ValidationError ::X509UnknownError (err ))
+ }
+ }
+ }
+ )
+);
+
+make_validation_error ! (X509_V_OK ,
+ X509UnableToGetIssuerCert = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT ,
+ X509UnableToGetCrl = X509_V_ERR_UNABLE_TO_GET_CRL ,
+ X509UnableToDecryptCertSignature = X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE ,
+ X509UnableToDecryptCrlSignature = X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE ,
+ X509UnableToDecodeIssuerPublicKey = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY ,
+ X509CertSignatureFailure = X509_V_ERR_CERT_SIGNATURE_FAILURE ,
+ X509CrlSignatureFailure = X509_V_ERR_CRL_SIGNATURE_FAILURE ,
+ X509CertNotYetValid = X509_V_ERR_CERT_NOT_YET_VALID ,
+ X509CertHasExpired = X509_V_ERR_CERT_HAS_EXPIRED ,
+ X509CrlNotYetValid = X509_V_ERR_CRL_NOT_YET_VALID ,
+ X509CrlHasExpired = X509_V_ERR_CRL_HAS_EXPIRED ,
+ X509ErrorInCertNotBeforeField = X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD ,
+ X509ErrorInCertNotAfterField = X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD ,
+ X509ErrorInCrlLastUpdateField = X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD ,
+ X509ErrorInCrlNextUpdateField = X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD ,
+ X509OutOfMem = X509_V_ERR_OUT_OF_MEM ,
+ X509DepthZeroSelfSignedCert = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ,
+ X509SelfSignedCertInChain = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN ,
+ X509UnableToGetIssuerCertLocally = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY ,
+ X509UnableToVerifyLeafSignature = X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE ,
+ X509CertChainTooLong = X509_V_ERR_CERT_CHAIN_TOO_LONG ,
+ X509CertRevoked = X509_V_ERR_CERT_REVOKED ,
+ X509InvalidCA = X509_V_ERR_INVALID_CA ,
+ X509PathLengthExceeded = X509_V_ERR_PATH_LENGTH_EXCEEDED ,
+ X509InvalidPurpose = X509_V_ERR_INVALID_PURPOSE ,
+ X509CertUntrusted = X509_V_ERR_CERT_UNTRUSTED ,
+ X509CertRejected = X509_V_ERR_CERT_REJECTED ,
+ X509SubjectIssuerMismatch = X509_V_ERR_SUBJECT_ISSUER_MISMATCH ,
+ X509AkidSkidMismatch = X509_V_ERR_AKID_SKID_MISMATCH ,
+ X509AkidIssuerSerialMismatch = X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH ,
+ X509KeyusageNoCertsign = X509_V_ERR_KEYUSAGE_NO_CERTSIGN ,
+ X509UnableToGetCrlIssuer = X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER ,
+ X509UnhandledCriticalExtension = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION ,
+ X509KeyusageNoCrlSign = X509_V_ERR_KEYUSAGE_NO_CRL_SIGN ,
+ X509UnhandledCriticalCrlExtension = X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION ,
+ X509InvalidNonCA = X509_V_ERR_INVALID_NON_CA ,
+ X509ProxyPathLengthExceeded = X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED ,
+ X509KeyusageNoDigitalSignature = X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE ,
+ X509ProxyCertificatesNotAllowed = X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED ,
+ X509InvalidExtension = X509_V_ERR_INVALID_EXTENSION ,
+ X509InavlidPolicyExtension = X509_V_ERR_INVALID_POLICY_EXTENSION ,
+ X509NoExplicitPolicy = X509_V_ERR_NO_EXPLICIT_POLICY ,
+ X509DifferentCrlScope = X509_V_ERR_DIFFERENT_CRL_SCOPE ,
+ X509UnsupportedExtensionFeature = X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE ,
+ X509UnnestedResource = X509_V_ERR_UNNESTED_RESOURCE ,
+ X509PermittedVolation = X509_V_ERR_PERMITTED_VIOLATION ,
+ X509ExcludedViolation = X509_V_ERR_EXCLUDED_VIOLATION ,
+ X509SubtreeMinmax = X509_V_ERR_SUBTREE_MINMAX ,
+ X509UnsupportedConstraintType = X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE ,
+ X509UnsupportedConstraintSyntax = X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX ,
+ X509UnsupportedNameSyntax = X509_V_ERR_UNSUPPORTED_NAME_SYNTAX ,
+ X509CrlPathValidationError = X509_V_ERR_CRL_PATH_VALIDATION_ERROR ,
+ X509ApplicationVerification = X509_V_ERR_APPLICATION_VERIFICATION ,
+);
+
+
+#[test ]
+fn test_negative_serial () {
+
+ for _ in 0 ..1000 {
+ assert ! (X509Generator ::random_serial () > 0 , "All serials should be positive" );
+ }
+}
+
+
+
+
+
+
+
+
+
Keyboard shortcuts
+
+ ?
+ Show this help dialog
+ S
+ Focus the search field
+ ⇤
+ Move up in search results
+ ⇥
+ Move down in search results
+ ⏎
+ Go to active search result
+
+
+
+
Search tricks
+
+ Prefix searches with a type followed by a colon (e.g.
+ fn:
) to restrict the search to a given type.
+
+
+ Accepted types are: fn
, mod
,
+ struct
, enum
,
+ trait
, typedef
(or
+ tdef
).
+
+
+ Search functions by type signature (e.g.
+ vec -> usize
)
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
--
cgit v1.2.3