1 /*******************************************************************************
2 
3         copyright:      Copyright (c) 2008 Jeff Davey. All rights reserved
4 
5         license:        BSD style: $(LICENSE)
6 
7         author:         Jeff Davey <j@submersion.com>
8 
9 *******************************************************************************/
10 
11 module tango.net.util.c.OpenSSL;
12 
13 private import tango.sys.SharedLib;
14 private import tango.sys.Environment;
15 
16 private import tango.stdc.stdio;
17 private import tango.stdc.stringz;
18 private import tango.stdc.config: c_long,c_ulong;
19 
20 private import tango.io.FilePath;
21 
22 private import tango.core.Thread;
23 private import tango.core.sync.Mutex;
24 private import tango.core.sync.ReadWriteMutex;
25 
26 private import tango.text.convert.Format;
27 private import Integer = tango.text.convert.Integer;
28 
29 /*******************************************************************************
30 
31     This module contains all of the dynamic bindings needed to the
32     OpenSSL libraries (libssl.so/libssl32.dll and libcrypto.so/libeay32.dll) 
33 
34 *******************************************************************************/
35 
36 /*
37    XXX TODO XXX
38 
39    A lot of unsigned longs and longs were converted to uint and int
40 
41    These will need to be reversed to support 64bit tango
42    (should use c_long and c_ulong from tango.stdc.config)
43 
44    XXX TODO XXX
45 */
46 
47 
48 version(linux)
49 {
50     version(build)
51     {
52         pragma(link, "dl");
53     }
54 }
55 
56 enum uint BYTES_ENTROPY = 2048; // default bytes of entropy to load on startup.
57 __gshared private CRYPTO_dynlock_value *last = null;
58 __gshared Mutex _dynLocksMutex = null;
59 extern (C)
60 {
61     enum int NID_sha1 = 64;
62     enum int NID_md5 = 4;
63     enum int RSA_PKCS1_OAEP_PADDING = 4;
64     enum int RSA_PKCS1_PADDING = 1;
65     enum int BIO_C_SET_NBIO = 102;
66     enum int SHA_DIGEST_LENGTH = 20;
67     enum int SSL_CTRL_SET_SESS_CACHE_MODE = 44;
68     enum int MBSTRING_FLAG = 0x1000;
69     enum int MBSTRING_ASC = MBSTRING_FLAG | 1;
70     enum int EVP_PKEY_RSA = 6;
71     enum int RSA_F4 = 0x1001;
72     enum int SSL_SENT_SHUTDOWN = 1;
73     enum int SSL_RECEIVED_SHUTDOWN = 2;
74     enum int BIO_C_GET_SSL = 110;
75     enum int BIO_CTRL_RESET = 1;
76     enum int BIO_CTRL_INFO = 3;
77     enum int BIO_FLAGS_READ = 0x01;
78     enum int BIO_FLAGS_WRITE = 0x02;
79     enum int BIO_FLAGS_IO_SPECIAL = 0x04;
80     enum int BIO_FLAGS_SHOULD_RETRY = 0x08;
81     enum int BIO_CLOSE = 0x00;
82     enum int BIO_NOCLOSE = 0x01;
83     enum int ASN1_STRFLGS_ESC_CTRL = 2;
84     enum int ASN1_STRFLGS_ESC_MSB = 4;
85     enum int XN_FLAG_SEP_MULTILINE = (4 << 16);
86     enum int XN_FLAG_SPC_EQ = (1 << 23);
87     enum int XN_FLAG_FN_LN = (1 << 21);
88     enum int XN_FLAG_FN_ALIGN = (1 << 25);
89     enum int XN_FLAG_MULTILINE = ASN1_STRFLGS_ESC_CTRL | ASN1_STRFLGS_ESC_MSB | XN_FLAG_SEP_MULTILINE | XN_FLAG_SPC_EQ | XN_FLAG_FN_LN | XN_FLAG_FN_ALIGN;
90 
91     enum immutable(char)* PEM_STRING_EVP_PKEY = "ANY PRIVATE KEY";
92     enum immutable(char)* PEM_STRING_X509 = "CERTIFICATE";   
93     enum immutable(char)* PEM_STRING_RSA_PUBLIC = "RSA PUBLIC KEY";    
94 
95     enum int SSL_CTRL_OPTIONS = 32;
96 
97     enum int SSL_OP_ALL = 0x00000FFFL;
98     enum int SSL_OP_NO_SSLv2 = 0x01000000L;
99 
100     enum int CRYPTO_LOCK = 1;
101     enum int CRYPTO_UNLOCK = 2;
102     enum int CRYPTO_READ = 4;
103     enum int CRYPTO_WRITE = 8;
104 
105     enum int ERR_TXT_STRING = 0x02;
106 
107     enum int MD5_CBLOCK = 64;
108     enum int MD5_LBLOCK = MD5_CBLOCK / 4;
109     enum int MD5_DIGEST_LENGTH = 16;
110 
111     enum int EVP_MAX_BLOCK_LENGTH = 32;
112     enum int EVP_MAX_IV_LENGTH = 16;
113 
114     struct MD5_CTX
115     {
116         uint A;
117         uint B;
118         uint C;
119         uint D;
120         uint Nl;
121         uint Nh;
122         uint[MD5_LBLOCK] data;
123         uint num;
124     };
125 
126     struct EVP_CIPHER_CTX
127     {
128         void *cipher;
129         void *engine;
130         int encrypt;
131         int buf_len;
132 
133         ubyte[EVP_MAX_IV_LENGTH] oiv;
134         ubyte[EVP_MAX_IV_LENGTH] iv;
135         ubyte buf[EVP_MAX_BLOCK_LENGTH];
136         int num;
137 
138         void *ap_data;
139         int key_len;
140         c_ulong flags;
141         void *cipher_data;
142         int final_used;
143         int block_mask;
144         ubyte[EVP_MAX_BLOCK_LENGTH] finalv;
145     };
146     
147     // fallback for OpenSSL 0.9.7l 28 Sep 2006 that defines only macros
148     int EVP_CIPHER_CTX_block_size_097l(EVP_CIPHER_CTX *e){
149         return *((cast(int*)e.cipher)+1);
150     }
151 
152     struct BIO 
153     {
154         BIO_METHOD *method;
155         int function(BIO *b, int a, char *c, int d, int e, int f) callback;
156         char *cb_arg;
157         int init;
158         int shutdown;
159         int flags;
160         // yadda yadda
161     };
162 
163     alias BIO* function(int sock, int close_flag) tBIO_new_socket;
164     alias BIO* function(SSL_CTX *ctx, int client) tBIO_new_ssl;
165     alias void function(BIO *bio) tBIO_free_all;
166     alias BIO* function(BIO *b, BIO *append) tBIO_push;
167 
168     struct SSL_CTX {};
169     struct SSL {};
170     struct SSL_METHOD {};
171     struct EVP_PKEY 
172     {
173         int type;
174         int save_type;
175         int references;
176         void *ameth;
177         void *engine;
178         union Pkey
179         {
180                 void *ptr;
181                 RSA *rsa;
182                 DSA *dsa;
183                 DH *dh;
184         };
185         Pkey pkey;
186         
187         
188         // yadda yadda ...        
189     };
190     struct X509_STORE_CTX {};
191     struct EVP_CIPHER {};
192     struct X509_ALGOR {};
193     struct ASN1_INTEGER {};
194     struct EVP_MD {};
195 
196     struct ASN1_STRING
197     {
198         int length;
199         int type;
200         char *data;
201         int flags;
202     }
203 
204     alias ASN1_STRING ASN1_GENERALIZEDTIME;
205     alias ASN1_STRING ASN1_TIME;
206 
207     struct X509_STORE {};
208     struct X509_VAL
209     {
210         ASN1_TIME *notBefore;
211         ASN1_TIME *notAfter;
212     }
213     struct X509_CINF  // being lazy here, only doing the first peices up to what I need
214     {
215         ASN1_INTEGER *vers;
216         ASN1_INTEGER *serialNumber;
217         X509_ALGOR *signature;
218         X509_NAME *issuer;
219         X509_VAL *validity;
220         // yadda yadda
221     }
222 
223     struct X509  // ditto X509_CINF
224     {
225         X509_CINF *cert_info; 
226         // yadda yadda
227     };
228     struct X509_NAME {};
229     struct RSA {};
230     struct DSA {};
231     struct DH {};
232     struct BIO_METHOD {};
233     struct EVP_PKEY_CTX {};
234     
235     alias int function(char *buf, int size, int rwflag, void *userdata) pem_password_cb;
236     alias char *function() d2i_of_void;
237     alias int function() i2d_of_void;
238     alias SSL_CTX* function(SSL_METHOD *meth) tSSL_CTX_new;
239     alias SSL_METHOD* function() tSSLv23_method;
240     alias EVP_PKEY* function(int type, EVP_PKEY **a, ubyte **pp, int length) td2i_PrivateKey;
241     alias int function(SSL_CTX *ctx, EVP_PKEY *pkey) tSSL_CTX_use_PrivateKey;
242     alias void function(SSL_CTX *ctx, int mode, int function(int, X509_STORE_CTX *) callback) tSSL_CTX_set_verify;
243     alias void function(EVP_PKEY *pkey) tEVP_PKEY_free;
244     alias int function(SSL_CTX *ctx, int cmd, int larg, void *parg) tSSL_CTX_ctrl;
245     alias int function(SSL_CTX *ctx, const(char) *str) tSSL_CTX_set_cipher_list;
246     alias void function(SSL_CTX *) tSSL_CTX_free;
247     alias void function() tSSL_load_error_strings;
248     alias void function() tSSL_library_init;
249     alias void function() tOpenSSL_add_all_digests;
250     alias int function(const(char) *file, int max_bytes) tRAND_load_file;
251     alias int function() tCRYPTO_num_locks;
252     alias void function(uint function() cb) tCRYPTO_set_id_callback;
253     alias void function(void function(int mode, int type, const(char) *file, int line) cb) tCRYPTO_set_locking_callback;
254     alias void function(CRYPTO_dynlock_value *function(const(char) *file, int line) cb) tCRYPTO_set_dynlock_create_callback;    
255     alias void function(void function(int mode, CRYPTO_dynlock_value *lock, const(char) *file, int lineNo) cb) tCRYPTO_set_dynlock_lock_callback;
256     alias void function(void function(CRYPTO_dynlock_value *lock, const(char) *file, int line) cb) tCRYPTO_set_dynlock_destroy_callback;
257     alias uint function(const(char) **file, int *line, const(char) **data, int *flags) tERR_get_error_line_data;
258     alias void function(uint pid) tERR_remove_state;
259     alias void function() tRAND_cleanup;
260     alias void function() tERR_free_strings;
261     alias void function() tEVP_cleanup;
262     alias void function() tOBJ_cleanup;
263     alias void function() tX509V3_EXT_cleanup;
264     alias void function() tCRYPTO_cleanup_all_ex_data;
265     alias int function(BIO *b, void *data, int len) tBIO_write;
266     alias int function(BIO *b, void *data, int len) tBIO_read;
267     alias int function(SSL_CTX *ctx) tSSL_CTX_check_private_key;
268     alias EVP_PKEY* function(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, in void *u) tPEM_read_bio_PrivateKey;
269     alias EVP_PKEY* function(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, in void *u) tPEM_read_bio_PUBKEY;
270     alias BIO* function(const(char) *filename, const(char) *mode) tBIO_new_file;
271     alias int function() tERR_peek_error;
272     alias int function(BIO *b, int flags) tBIO_test_flags;
273     alias int function(BIO *b, int cmd, int larg, void *parg) tBIO_ctrl; 
274     alias void function(SSL *ssl, int mode) tSSL_set_shutdown;
275     alias int function(SSL *ssl) tSSL_get_shutdown;
276     alias int function(SSL_CTX *ctx, X509 *x) tSSL_CTX_use_certificate;
277     alias void function(SSL_CTX *CTX, X509_STORE *store) tSSL_CTX_set_cert_store;
278     alias int function(SSL_CTX *ctx, const(char) *CAfile, const(char) *CApath) tSSL_CTX_load_verify_locations;
279     alias X509* function(X509_STORE_CTX *ctx) tX509_STORE_CTX_get_current_cert;
280     alias int function(X509_STORE_CTX *ctx) tX509_STORE_CTX_get_error;
281     alias int function(X509_STORE_CTX *ctx) tX509_STORE_CTX_get_error_depth;
282     alias X509_STORE* function() tX509_STORE_new;
283     alias void function(X509_STORE *v) tX509_STORE_free;
284     alias int function(X509_STORE *store, X509 *x) tX509_STORE_add_cert;
285 //    alias int function(X509_STORE *store, int depth) tX509_STORE_set_depth;
286     alias BIO* function(void *buff, int len) tBIO_new_mem_buf;
287     alias RSA* function(int bits, uint e, void function(int a, int b, void *c) callback, void *cb_arg) tRSA_generate_key;
288     alias EVP_PKEY* function() tEVP_PKEY_new;
289     alias int function(EVP_PKEY *pkey, int type, char *key) tEVP_PKEY_assign;
290     alias void function(RSA *r) tRSA_free;
291     alias BIO* function(BIO_METHOD *type) tBIO_new;
292     alias BIO_METHOD* function() tBIO_s_mem;
293     alias int function(BIO *bp, EVP_PKEY *x, const(EVP_CIPHER) *cipher, char *kstr, int klen, pem_password_cb, in void *) tPEM_write_bio_PKCS8PrivateKey;
294     alias int function(BIO *bp, EVP_PKEY *x) tPEM_write_bio_PUBKEY;
295     alias EVP_CIPHER* function() tEVP_aes_256_cbc;
296     alias void* function(d2i_of_void d2i, const(char) *name, BIO *bp, void **x, pem_password_cb cb, void *u) tPEM_ASN1_read_bio;
297     alias X509* function() tX509_new;
298     alias void function(X509 *x) tX509_free;
299     alias int function(X509 *x, int ver) tX509_set_version;
300     alias int function(ASN1_INTEGER *a, int v) tASN1_INTEGER_set;
301     alias ASN1_INTEGER* function(X509 *x) tX509_get_serialNumber;
302     alias int function(ASN1_INTEGER *a) tASN1_INTEGER_get;
303     alias ASN1_TIME* function(ASN1_TIME *s, int adj) tX509_gmtime_adj;
304     alias int function(X509 *x, EVP_PKEY *pkey) tX509_set_pubkey;
305     alias X509_NAME* function(X509 *x) tX509_get_subject_name;
306     alias int function(BIO *b, X509_NAME *nm, int indent, uint flags) tX509_NAME_print_ex;
307     alias int function(X509 *x, X509_NAME *name) tX509_set_issuer_name;
308     alias int function(X509 *x, EVP_PKEY *pkey, EVP_MD *md) tX509_sign;
309     alias EVP_MD* function() tEVP_sha1;
310     alias X509_STORE_CTX* function() tX509_STORE_CTX_new;
311     alias int function(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, void *shizzle) tX509_STORE_CTX_init;
312     alias int function(X509_STORE_CTX *ctx) tX509_verify_cert;
313     alias void function(X509_STORE_CTX *ctx) tX509_STORE_CTX_free;
314     alias int function(i2d_of_void i2d, const(char) *name, BIO *bp, char *x, const(EVP_CIPHER) *enc, char *kstr, int klen, pem_password_cb cb, void *u) tPEM_ASN1_write_bio;
315     alias int function(X509_NAME *name, in char* field, int type, const(char) *bytes, int len, int loc, int set) tX509_NAME_add_entry_by_txt;
316     alias int function(SSL_CTX *ctx, ubyte *id, uint len) tSSL_CTX_set_session_id_context;
317     alias int function(EVP_PKEY *a, EVP_PKEY *b) tEVP_PKEY_cmp_parameters;
318     alias int function(X509 *a, X509 *b) tX509_cmp;
319     alias void function() tOPENSSL_add_all_algorithms_noconf;
320     alias ASN1_GENERALIZEDTIME *function(ASN1_TIME *t, ASN1_GENERALIZEDTIME **outTime) tASN1_TIME_to_generalizedtime;
321     alias void function(ASN1_STRING *a) tASN1_STRING_free;
322     alias int function() tRAND_poll;
323     alias int function(RSA *rsa) tRSA_size;
324     alias int function(int flen, ubyte *from, ubyte *to, RSA *rsa, int padding) tRSA_public_encrypt;
325     alias int function(int flen, ubyte *from, ubyte *to, RSA *rsa, int padding) tRSA_private_decrypt;
326     alias int function(int flen, ubyte *from, ubyte *to, RSA *rsa, int padding) tRSA_private_encrypt;
327     alias int function(int flen, ubyte *from, ubyte *to, RSA *rsa, int padding) tRSA_public_decrypt;
328     alias int function(int type, ubyte *m, uint m_length, ubyte *sigret, uint *siglen, RSA *rsa) tRSA_sign;
329     alias int function(int type, ubyte *m, uint m_length, ubyte *sigbuf, uint siglen, RSA *rsa) tRSA_verify;
330     alias void function(MD5_CTX *c) tMD5_Init;
331     alias void function(MD5_CTX *c, in void *data, size_t len) tMD5_Update;
332     alias void function(ubyte *md, MD5_CTX *c) tMD5_Final;
333     alias int function(EVP_CIPHER_CTX *ctx, EVP_CIPHER *type, void *impl, ubyte *key, ubyte *iv) tEVP_EncryptInit_ex;
334     alias int function(EVP_CIPHER_CTX *ctx, EVP_CIPHER *type, void *impl, ubyte *key, ubyte*iv) tEVP_DecryptInit_ex;
335     alias int function(EVP_CIPHER_CTX *ctx, ubyte *outv, int *outl, ubyte *inv, int inl) tEVP_EncryptUpdate;
336     alias int function(EVP_CIPHER_CTX *ctx, ubyte *outv, int *outl, ubyte *inv, int inl) tEVP_DecryptUpdate;
337     alias int function(EVP_CIPHER_CTX *ctx, ubyte *outv, int *outl) tEVP_EncryptFinal_ex;
338     alias int function(EVP_CIPHER_CTX *ctx, ubyte *outv, int *outl) tEVP_DecryptFinal_ex;
339     alias int function(EVP_CIPHER_CTX *ctx) tEVP_CIPHER_CTX_block_size;
340     alias EVP_CIPHER *function() tEVP_aes_128_cbc;
341     alias int function(EVP_CIPHER_CTX *ctx) tEVP_CIPHER_CTX_cleanup;
342     
343     alias int function(int) tEVP_PKEY_type;
344     alias RSA* function(EVP_PKEY *pkey) tEVP_PKEY_get1_RSA;
345     alias DSA* function(EVP_PKEY *pkey) tEVP_PKEY_get1_DSA;
346     
347     
348     alias EVP_PKEY_CTX* function(EVP_PKEY *pkey, void *e) tEVP_PKEY_CTX_new;
349     alias void function(EVP_PKEY_CTX *ctx) tEVP_PKEY_CTX_free;   
350     
351     
352     alias int function(EVP_PKEY_CTX *ctx) tEVP_PKEY_sign_init;
353     alias int function(EVP_PKEY_CTX *ctx, ubyte *sig, size_t *siglen, const ubyte *tbs, size_t tbslen) tEVP_PKEY_sign;
354     
355     alias int function(EVP_PKEY_CTX *ctx) tEVP_PKEY_verify_init;
356     alias int function(EVP_PKEY_CTX *ctx, const ubyte *sig, size_t siglen, const ubyte *tbs, size_t tbslen) tEVP_PKEY_verify;
357     
358     alias int function(EVP_PKEY_CTX *ctx) tEVP_PKEY_encrypt_init;
359     alias int function(EVP_PKEY_CTX *ctx, ubyte *outdata, size_t *outlen, const ubyte *indata, size_t inlen) tEVP_PKEY_encrypt;
360     
361     alias int function(EVP_PKEY_CTX *ctx) tEVP_PKEY_decrypt_init;
362     alias int function(EVP_PKEY_CTX *ctx, ubyte *outdata, size_t *outlen, const ubyte *indata, size_t inlen) tEVP_PKEY_decrypt;
363     
364     struct CRYPTO_dynlock_value
365     {
366         ReadWriteMutex lock;
367         CRYPTO_dynlock_value *next;
368         CRYPTO_dynlock_value *prev;
369     }
370 
371     uint sslThreadId()
372     {
373         return cast(uint)cast(void*)Thread.getThis();
374     }
375     void sslStaticLock(int mode, int index, const(char) *sourceFile, int lineNo)
376     {
377         if (_locks)
378         {
379             if (mode & CRYPTO_LOCK)
380             {
381                 if (mode & CRYPTO_READ)
382                     _locks[index].reader.lock();
383                 else
384                     _locks[index].writer.lock();
385             }
386             else
387             {
388                 if (mode & CRYPTO_READ)
389                     _locks[index].reader.unlock();
390                 else
391                     _locks[index].writer.unlock();
392             }
393 
394         } 
395     }
396     uint ablah = 0;
397     CRYPTO_dynlock_value *sslDynamicLockCreate(const(char) *sourceFile, int lineNo)
398     {
399         auto rtn = new CRYPTO_dynlock_value;
400         rtn.lock = new ReadWriteMutex;
401         synchronized
402         {
403             if (last is null)
404                 last = rtn;
405             else
406             {
407                 rtn.prev = last;
408                 last.next = rtn;
409                 last = rtn;
410             }        
411         }
412         return rtn; 
413     }
414 
415     void sslDynamicLockLock(int mode, CRYPTO_dynlock_value *lock, const(char) *sourceFile, int lineNo)
416     {
417         if (lock && lock.lock)
418         {
419             if (mode & CRYPTO_LOCK)
420             {
421                 if (mode & CRYPTO_READ)
422                     lock.lock.reader.lock();
423                 else
424                     lock.lock.writer.lock();
425             }
426             else
427             {
428                 if (mode & CRYPTO_READ)
429                     lock.lock.reader.unlock();
430                 else
431                     lock.lock.writer.unlock();
432             }
433         } 
434     }
435 
436     void sslDynamicLockDestroy(CRYPTO_dynlock_value *lock, const(char) *sourceFile, int lineNo)
437     {
438         synchronized
439         {
440             if (lock.prev)
441                 lock.prev.next = lock.next;
442             if (lock.next)
443                 lock.next.prev = lock.prev;    
444             if (lock is last)
445                 last = lock.prev;
446             lock = lock.next = lock.prev = null;
447         }
448     }
449 
450 }
451 private bool _bioTestFlags = true;
452 __gshared
453 {
454 tBIO_test_flags BIO_test_flags;
455 tBIO_new_socket BIO_new_socket;
456 tBIO_new_ssl BIO_new_ssl;
457 tBIO_free_all BIO_free_all;
458 tBIO_push BIO_push;
459 tBIO_read BIO_read;
460 tBIO_write BIO_write;
461 tSSL_CTX_new SSL_CTX_new;
462 tSSLv23_method SSLv23_method;
463 td2i_PrivateKey d2i_PrivateKey;
464 tSSL_CTX_use_PrivateKey SSL_CTX_use_PrivateKey;
465 tSSL_CTX_set_verify SSL_CTX_set_verify;
466 tEVP_PKEY_free EVP_PKEY_free;
467 tSSL_CTX_ctrl SSL_CTX_ctrl;
468 tSSL_CTX_set_cipher_list SSL_CTX_set_cipher_list;
469 tSSL_CTX_free SSL_CTX_free;
470 tSSL_load_error_strings SSL_load_error_strings;
471 tSSL_library_init SSL_library_init;
472 tRAND_load_file RAND_load_file;
473 tCRYPTO_num_locks CRYPTO_num_locks;
474 tCRYPTO_set_id_callback CRYPTO_set_id_callback;
475 tCRYPTO_set_locking_callback CRYPTO_set_locking_callback;
476 tCRYPTO_set_dynlock_create_callback CRYPTO_set_dynlock_create_callback;
477 tCRYPTO_set_dynlock_lock_callback CRYPTO_set_dynlock_lock_callback;
478 tCRYPTO_set_dynlock_destroy_callback CRYPTO_set_dynlock_destroy_callback;
479 tERR_get_error_line_data ERR_get_error_line_data;
480 tERR_remove_state ERR_remove_state;
481 tRAND_cleanup RAND_cleanup;
482 tERR_free_strings ERR_free_strings;
483 tEVP_cleanup EVP_cleanup;
484 tOBJ_cleanup OBJ_cleanup;
485 tX509V3_EXT_cleanup X509V3_EXT_cleanup;
486 tCRYPTO_cleanup_all_ex_data CRYPTO_cleanup_all_ex_data;
487 tSSL_CTX_check_private_key SSL_CTX_check_private_key;
488 tPEM_read_bio_PrivateKey PEM_read_bio_PrivateKey;
489 tPEM_read_bio_PUBKEY PEM_read_bio_PUBKEY;
490 tBIO_new_file BIO_new_file;
491 tERR_peek_error ERR_peek_error;
492 tBIO_ctrl BIO_ctrl;
493 tSSL_get_shutdown SSL_get_shutdown;
494 tSSL_set_shutdown SSL_set_shutdown;
495 tSSL_CTX_use_certificate SSL_CTX_use_certificate;
496 tSSL_CTX_set_cert_store SSL_CTX_set_cert_store;
497 tSSL_CTX_load_verify_locations SSL_CTX_load_verify_locations;
498 tX509_STORE_CTX_get_current_cert X509_STORE_CTX_get_current_cert;
499 tX509_STORE_CTX_get_error_depth X509_STORE_CTX_get_error_depth;
500 tX509_STORE_CTX_get_error X509_STORE_CTX_get_error;
501 tX509_STORE_new X509_STORE_new;
502 tX509_STORE_free X509_STORE_free;
503 tX509_STORE_add_cert X509_STORE_add_cert;
504 //tX509_STORE_set_depth X509_STORE_set_depth;
505 tBIO_new_mem_buf BIO_new_mem_buf;
506 tRSA_generate_key RSA_generate_key;
507 tEVP_PKEY_new EVP_PKEY_new;
508 tEVP_PKEY_assign EVP_PKEY_assign;
509 tRSA_free RSA_free;
510 tBIO_new BIO_new;
511 tBIO_s_mem BIO_s_mem;
512 tPEM_write_bio_PKCS8PrivateKey PEM_write_bio_PKCS8PrivateKey;
513 tPEM_write_bio_PUBKEY PEM_write_bio_PUBKEY;
514 tEVP_aes_256_cbc EVP_aes_256_cbc;
515 tPEM_ASN1_read_bio PEM_ASN1_read_bio;
516 d2i_of_void d2i_X509;
517 d2i_of_void d2i_RSAPublicKey;
518 tX509_new X509_new;
519 tX509_free X509_free;
520 tX509_set_version X509_set_version;
521 tASN1_INTEGER_set ASN1_INTEGER_set;
522 tX509_get_serialNumber X509_get_serialNumber;
523 tASN1_INTEGER_get ASN1_INTEGER_get;
524 tX509_gmtime_adj X509_gmtime_adj;
525 tX509_set_pubkey X509_set_pubkey;
526 tX509_get_subject_name X509_get_subject_name;
527 tX509_NAME_print_ex X509_NAME_print_ex;
528 tX509_set_issuer_name X509_set_issuer_name;
529 tX509_sign X509_sign;
530 tEVP_sha1 EVP_sha1;
531 tX509_STORE_CTX_new X509_STORE_CTX_new;
532 tX509_STORE_CTX_init X509_STORE_CTX_init;
533 tX509_verify_cert X509_verify_cert;
534 tX509_STORE_CTX_free X509_STORE_CTX_free;
535 tPEM_ASN1_write_bio PEM_ASN1_write_bio;
536 i2d_of_void i2d_X509;
537 i2d_of_void i2d_RSAPublicKey;
538 tX509_NAME_add_entry_by_txt X509_NAME_add_entry_by_txt;
539 tSSL_CTX_set_session_id_context SSL_CTX_set_session_id_context;
540 tEVP_PKEY_cmp_parameters EVP_PKEY_cmp_parameters;
541 tX509_cmp X509_cmp;
542 tOPENSSL_add_all_algorithms_noconf OPENSSL_add_all_algorithms_noconf;
543 tASN1_TIME_to_generalizedtime ASN1_TIME_to_generalizedtime;
544 tASN1_STRING_free ASN1_STRING_free;
545 tRAND_poll RAND_poll;
546 tRSA_size RSA_size;
547 tRSA_public_encrypt RSA_public_encrypt;
548 tRSA_private_decrypt RSA_private_decrypt;
549 tRSA_private_encrypt RSA_private_encrypt;
550 tRSA_public_decrypt RSA_public_decrypt;
551 tRSA_sign RSA_sign;
552 tRSA_verify RSA_verify;
553 tMD5_Init MD5_Init;
554 tMD5_Update MD5_Update;
555 tMD5_Final MD5_Final;
556 tEVP_EncryptInit_ex EVP_EncryptInit_ex;
557 tEVP_DecryptInit_ex EVP_DecryptInit_ex;
558 tEVP_EncryptUpdate EVP_EncryptUpdate;
559 tEVP_DecryptUpdate EVP_DecryptUpdate;
560 tEVP_EncryptFinal_ex EVP_EncryptFinal_ex;
561 tEVP_DecryptFinal_ex EVP_DecryptFinal_ex;
562 tEVP_aes_128_cbc EVP_aes_128_cbc;
563 tEVP_CIPHER_CTX_block_size EVP_CIPHER_CTX_block_size;
564 tEVP_CIPHER_CTX_cleanup EVP_CIPHER_CTX_cleanup;
565 
566 tEVP_PKEY_type EVP_PKEY_type;
567 tEVP_PKEY_get1_RSA EVP_PKEY_get1_RSA;
568 tEVP_PKEY_get1_DSA EVP_PKEY_get1_DSA;
569 
570 tEVP_PKEY_CTX_new EVP_PKEY_CTX_new;
571 tEVP_PKEY_CTX_free EVP_PKEY_CTX_free;
572 tEVP_PKEY_sign_init EVP_PKEY_sign_init;
573 tEVP_PKEY_sign EVP_PKEY_sign;
574 tEVP_PKEY_verify_init EVP_PKEY_verify_init;
575 tEVP_PKEY_verify EVP_PKEY_verify;
576 
577 tEVP_PKEY_encrypt_init EVP_PKEY_encrypt_init;
578 tEVP_PKEY_encrypt EVP_PKEY_encrypt;
579 tEVP_PKEY_decrypt_init EVP_PKEY_decrypt_init;
580 tEVP_PKEY_decrypt EVP_PKEY_decrypt;
581 }
582 int PEM_write_bio_RSAPublicKey(BIO *bp, RSA *x)
583 {
584     return PEM_ASN1_write_bio(i2d_RSAPublicKey, PEM_STRING_RSA_PUBLIC, bp, cast(char*)x, null, null, 0, null, null);
585 }
586 
587 RSA *PEM_read_bio_RSAPublicKey(BIO *bp, RSA **x, pem_password_cb cb, void *u)
588 {
589     return cast(RSA *)PEM_ASN1_read_bio(d2i_RSAPublicKey, PEM_STRING_RSA_PUBLIC, bp, cast(void **)x, cb, u);
590 }
591 
592 int PEM_write_bio_X509(BIO *b, X509 *x)
593 {
594     return PEM_ASN1_write_bio(i2d_X509, PEM_STRING_X509, b,cast(char *)x, null, null, 0, null, null);
595 }
596 
597 ASN1_TIME *X509_get_notBefore(X509 *x)
598 {
599     return x.cert_info.validity.notBefore;
600 }
601 
602 ASN1_TIME *X509_get_notAfter(X509 *x)
603 {
604     return x.cert_info.validity.notAfter;
605 }
606 
607 int EVP_PKEY_assign_RSA(EVP_PKEY *key, RSA *rsa)
608 {
609     return EVP_PKEY_assign(key, EVP_PKEY_RSA, cast(char*)rsa);
610 }
611 
612 int BIO_get_mem_data(BIO *b, char **data)
613 {
614     return BIO_ctrl(b, BIO_CTRL_INFO, 0, data);
615 }
616 
617 void BIO_get_ssl(BIO *b, SSL **obj)
618 {
619     BIO_ctrl(b, BIO_C_GET_SSL, 0, obj);
620 }
621 
622 int SSL_CTX_set_options(SSL_CTX *ctx, int larg)
623 {
624     return SSL_CTX_ctrl(ctx, SSL_CTRL_OPTIONS, larg, null);
625 }
626 
627 int SSL_CTX_set_session_cache_mode(SSL_CTX *ctx, int mode)
628 {
629     return SSL_CTX_ctrl(ctx, SSL_CTRL_SET_SESS_CACHE_MODE, mode, null);
630 }
631 
632 int BIO_reset(BIO *b)
633 {
634     return BIO_ctrl(b, BIO_CTRL_RESET, 0, null);
635 }
636 
637 bool BIO_should_retry(BIO *b)
638 {
639     if (_bioTestFlags)
640         return cast(bool)BIO_test_flags(b, BIO_FLAGS_SHOULD_RETRY);
641     return cast(bool)(b.flags & BIO_FLAGS_SHOULD_RETRY);
642 }
643 
644 bool BIO_should_io_special(BIO *b)
645 {
646     if (_bioTestFlags)
647         return cast(bool)BIO_test_flags(b, BIO_FLAGS_IO_SPECIAL);
648     return cast(bool)(b.flags & BIO_FLAGS_IO_SPECIAL);
649 }
650 
651 bool BIO_should_read(BIO *b)
652 {
653     if (_bioTestFlags)
654         return cast(bool)BIO_test_flags(b, BIO_FLAGS_READ);
655     return cast(bool)(b.flags & BIO_FLAGS_READ);
656 }
657 
658 bool BIO_should_write(BIO *b)
659 {
660     if (_bioTestFlags)
661         return cast(bool)BIO_test_flags(b, BIO_FLAGS_WRITE);
662     return cast(bool)(b.flags & BIO_FLAGS_WRITE);
663 }
664 
665 X509* PEM_read_bio_X509(BIO *b, X509 **x, pem_password_cb cb, void *u)
666 {
667     return cast(X509 *)PEM_ASN1_read_bio(d2i_X509, PEM_STRING_X509, b, cast(void**)x, cb, u);
668 }
669 
670 
671 private void bindFunc(T)(ref T func, const(char)[] funcName, SharedLib lib)
672 in
673 {
674     assert(funcName);
675     assert(lib);
676 }
677 body
678 {
679     void *funcPtr = lib.getSymbol(toStringz(funcName));
680     if (funcPtr)
681     {
682         void **point = cast(void **)&func;
683         *point = funcPtr;
684     }
685     else
686         throw new Exception("Could not load symbol: " ~ funcName.idup);
687 }
688 
689 static __gshared SharedLib ssllib = null;
690 version(Win32)
691 {
692     static __gshared SharedLib eaylib = null;
693 }
694 version(darwin){
695     static __gshared SharedLib cryptolib = null;
696 }
697 static __gshared ReadWriteMutex[] _locks = null;
698 
699 
700 void throwOpenSSLError()
701 {
702     if (ERR_peek_error())
703     {
704         char[] exceptionString;
705 
706         int flags, line;
707         const(char) *data;
708         const(char) *file;
709         uint code;
710 
711         code = ERR_get_error_line_data(&file, &line, &data, &flags);
712         while (code != 0)
713         {
714             if (data && (flags & ERR_TXT_STRING))
715                 exceptionString ~= Format.convert("ssl error code: {} {}:{} - {}\r\n", code, fromStringz(file), line, fromStringz(data));
716             else
717                 exceptionString ~= Format.convert("ssl error code: {} {}:{}\r\n", code, fromStringz(file), line); 
718             code = ERR_get_error_line_data(&file, &line, &data, &flags);
719         }
720         throw new Exception(exceptionString.idup);
721     }
722     else
723         throw new Exception("Unknown OpenSSL error.");
724 }
725 
726 void _initOpenSSL()
727 {
728     SSL_load_error_strings();
729     SSL_library_init();
730     OPENSSL_add_all_algorithms_noconf();
731     version(Posix)
732         RAND_load_file("/dev/urandom", BYTES_ENTROPY);
733     version(Win32)
734     {
735         RAND_poll();
736     }
737 
738     uint numLocks = CRYPTO_num_locks();
739     if ((_locks = new ReadWriteMutex[numLocks]) !is null)
740     {
741         uint i = 0;
742         for (; i < numLocks; i++)
743         {
744             if((_locks[i] = new ReadWriteMutex()) is null)
745                 break;
746         }
747         if (i == numLocks)
748         {
749             CRYPTO_set_id_callback(&sslThreadId);
750             CRYPTO_set_locking_callback(&sslStaticLock);
751 
752             CRYPTO_set_dynlock_create_callback(&sslDynamicLockCreate);
753             CRYPTO_set_dynlock_lock_callback(&sslDynamicLockLock);
754             CRYPTO_set_dynlock_destroy_callback(&sslDynamicLockDestroy);
755 
756         }
757     } 
758 }
759 
760 shared static this()
761 {
762     version(Win32)
763         loadEAY32();
764     loadOpenSSL();
765 }
766 // Though it would be nice to do this, it can't be closed until all the sockets and etc have been collected.. not sure how to do that.
767 /*static ~this()
768 {
769     closeOpenSSL();
770 }*/
771 
772 
773 SharedLib loadLib(const(char[])[] loadPath)
774 {
775     SharedLib rtn;
776     foreach(path; loadPath)
777     {
778         try
779             rtn = SharedLib.load(path);
780         catch (SharedLibException ex)
781         {
782             scope fp = new FilePath(path.dup);
783             try
784                 rtn = SharedLib.load(fp.absolute(Environment.cwd()).toString());
785             catch (SharedLibException ex)
786             {}
787         }
788     }
789     return rtn;
790 }
791 
792 version (Win32)
793 {
794     void loadEAY32()
795     {
796         const(char[])[] loadPath = [ "libeay32.dll" ];
797         if ((eaylib = loadLib(loadPath)) !is null)
798         {
799             bindCrypto(eaylib);    
800         }
801     }
802 
803 }
804 
805 void bindCrypto(SharedLib ssllib)
806 {
807     if (ssllib)
808     {
809         bindFunc(X509_cmp, "X509_cmp", ssllib);
810         bindFunc(OPENSSL_add_all_algorithms_noconf, "OPENSSL_add_all_algorithms_noconf", ssllib);
811         bindFunc(ASN1_TIME_to_generalizedtime, "ASN1_TIME_to_generalizedtime", ssllib);
812         bindFunc(ASN1_STRING_free, "ASN1_STRING_free", ssllib);
813         bindFunc(EVP_PKEY_cmp_parameters, "EVP_PKEY_cmp_parameters", ssllib);
814         bindFunc(X509_STORE_CTX_get_current_cert, "X509_STORE_CTX_get_current_cert", ssllib);
815         bindFunc(X509_STORE_CTX_get_error_depth, "X509_STORE_CTX_get_error_depth", ssllib);
816         bindFunc(X509_STORE_CTX_get_error, "X509_STORE_CTX_get_error", ssllib);
817         bindFunc(X509_STORE_new, "X509_STORE_new", ssllib);
818         bindFunc(X509_STORE_free, "X509_STORE_free", ssllib);
819         bindFunc(X509_STORE_add_cert, "X509_STORE_add_cert", ssllib);
820 //        bindFunc(X509_STORE_set_depth, "X509_STORE_set_depth", ssllib);
821         bindFunc(BIO_new_mem_buf, "BIO_new_mem_buf", ssllib);
822         bindFunc(RSA_generate_key, "RSA_generate_key", ssllib);
823         bindFunc(EVP_PKEY_new, "EVP_PKEY_new", ssllib);
824         bindFunc(EVP_PKEY_assign, "EVP_PKEY_assign", ssllib);
825         bindFunc(RSA_free, "RSA_free", ssllib);
826         bindFunc(BIO_new, "BIO_new", ssllib);
827         bindFunc(BIO_s_mem, "BIO_s_mem", ssllib);
828         bindFunc(PEM_write_bio_PKCS8PrivateKey, "PEM_write_bio_PKCS8PrivateKey", ssllib);
829         bindFunc(PEM_write_bio_PUBKEY, "PEM_write_bio_PUBKEY", ssllib);
830         bindFunc(EVP_aes_256_cbc, "EVP_aes_256_cbc", ssllib);
831         bindFunc(PEM_ASN1_read_bio, "PEM_ASN1_read_bio", ssllib);
832         bindFunc(d2i_X509, "d2i_X509", ssllib);
833         bindFunc(d2i_RSAPublicKey, "d2i_RSAPublicKey", ssllib);
834         bindFunc(X509_new, "X509_new", ssllib);
835         bindFunc(X509_free, "X509_free", ssllib);
836         bindFunc(X509_set_version, "X509_set_version", ssllib);
837         bindFunc(ASN1_INTEGER_set, "ASN1_INTEGER_set", ssllib);
838         bindFunc(X509_get_serialNumber, "X509_get_serialNumber", ssllib);
839         bindFunc(ASN1_INTEGER_get, "ASN1_INTEGER_get", ssllib);
840         bindFunc(X509_gmtime_adj, "X509_gmtime_adj", ssllib);
841         bindFunc(X509_set_pubkey, "X509_set_pubkey", ssllib);
842         bindFunc(X509_get_subject_name, "X509_get_subject_name", ssllib);
843         bindFunc(X509_NAME_print_ex, "X509_NAME_print_ex", ssllib);
844         bindFunc(X509_set_issuer_name, "X509_set_issuer_name", ssllib);
845         bindFunc(X509_sign, "X509_sign", ssllib);
846         bindFunc(EVP_sha1, "EVP_sha1", ssllib);
847         bindFunc(X509_STORE_CTX_new, "X509_STORE_CTX_new", ssllib);
848         bindFunc(X509_STORE_CTX_init, "X509_STORE_CTX_init", ssllib);
849         bindFunc(X509_verify_cert, "X509_verify_cert", ssllib);
850         bindFunc(X509_STORE_CTX_free, "X509_STORE_CTX_free", ssllib);
851         bindFunc(PEM_ASN1_write_bio, "PEM_ASN1_write_bio", ssllib);
852         bindFunc(i2d_X509, "i2d_X509", ssllib);
853         bindFunc(i2d_RSAPublicKey, "i2d_RSAPublicKey", ssllib);
854         bindFunc(X509_NAME_add_entry_by_txt, "X509_NAME_add_entry_by_txt", ssllib);
855         bindFunc(PEM_read_bio_PrivateKey, "PEM_read_bio_PrivateKey", ssllib);
856         bindFunc(PEM_read_bio_PUBKEY, "PEM_read_bio_PUBKEY", ssllib);
857         bindFunc(BIO_new_file, "BIO_new_file", ssllib);
858         bindFunc(ERR_peek_error, "ERR_peek_error", ssllib);
859         try
860             bindFunc(BIO_test_flags, "BIO_test_flags", ssllib); // 0.9.7 doesn't have this function, it access the struct directly
861         catch (Exception ex)
862             _bioTestFlags = false;
863         bindFunc(BIO_ctrl, "BIO_ctrl", ssllib);
864         bindFunc(RAND_load_file, "RAND_load_file", ssllib);
865         bindFunc(CRYPTO_num_locks, "CRYPTO_num_locks", ssllib);
866         bindFunc(CRYPTO_set_id_callback, "CRYPTO_set_id_callback", ssllib);
867         bindFunc(CRYPTO_set_locking_callback, "CRYPTO_set_locking_callback", ssllib);
868         bindFunc(CRYPTO_set_dynlock_create_callback, "CRYPTO_set_dynlock_create_callback", ssllib);
869         bindFunc(CRYPTO_set_dynlock_lock_callback, "CRYPTO_set_dynlock_lock_callback", ssllib);
870         bindFunc(CRYPTO_set_dynlock_lock_callback, "CRYPTO_set_dynlock_lock_callback", ssllib);
871         bindFunc(CRYPTO_set_dynlock_destroy_callback, "CRYPTO_set_dynlock_destroy_callback", ssllib);
872         bindFunc(ERR_get_error_line_data, "ERR_get_error_line_data", ssllib);
873         bindFunc(ERR_remove_state, "ERR_remove_state", ssllib);
874         bindFunc(RAND_cleanup, "RAND_cleanup", ssllib);
875         bindFunc(ERR_free_strings, "ERR_free_strings", ssllib);
876         bindFunc(EVP_cleanup, "EVP_cleanup", ssllib);
877         bindFunc(OBJ_cleanup, "OBJ_cleanup", ssllib);
878         bindFunc(X509V3_EXT_cleanup, "X509V3_EXT_cleanup", ssllib);
879         bindFunc(CRYPTO_cleanup_all_ex_data, "CRYPTO_cleanup_all_ex_data", ssllib);
880         bindFunc(BIO_read, "BIO_read", ssllib);
881         bindFunc(BIO_write, "BIO_write", ssllib);
882         bindFunc(EVP_PKEY_free, "EVP_PKEY_free", ssllib);
883         bindFunc(d2i_PrivateKey, "d2i_PrivateKey", ssllib);    
884         bindFunc(BIO_free_all, "BIO_free_all", ssllib);
885         bindFunc(BIO_push, "BIO_push", ssllib);    
886         bindFunc(BIO_new_socket, "BIO_new_socket", ssllib);
887         bindFunc(RAND_poll, "RAND_poll", ssllib);
888         bindFunc(RSA_size, "RSA_size", ssllib);
889         bindFunc(RSA_public_encrypt, "RSA_public_encrypt", ssllib);
890         bindFunc(RSA_private_decrypt, "RSA_private_decrypt", ssllib);
891         bindFunc(RSA_private_encrypt, "RSA_private_encrypt", ssllib);
892         bindFunc(RSA_public_decrypt, "RSA_public_decrypt", ssllib);
893         bindFunc(RSA_sign, "RSA_sign", ssllib);
894         bindFunc(RSA_verify, "RSA_verify", ssllib);
895         bindFunc(MD5_Init, "MD5_Init", ssllib);
896         bindFunc(MD5_Update, "MD5_Update", ssllib);
897         bindFunc(MD5_Final, "MD5_Final", ssllib);
898         bindFunc(EVP_EncryptInit_ex, "EVP_EncryptInit_ex", ssllib);
899         bindFunc(EVP_DecryptInit_ex, "EVP_DecryptInit_ex", ssllib);
900         bindFunc(EVP_EncryptUpdate, "EVP_EncryptUpdate", ssllib);
901         bindFunc(EVP_DecryptUpdate,  "EVP_DecryptUpdate", ssllib);
902         bindFunc(EVP_EncryptFinal_ex, "EVP_EncryptFinal_ex", ssllib);
903         bindFunc(EVP_DecryptFinal_ex, "EVP_DecryptFinal_ex", ssllib);
904         bindFunc(EVP_aes_128_cbc, "EVP_aes_128_cbc", ssllib);
905         try {
906             bindFunc(EVP_CIPHER_CTX_block_size, "EVP_CIPHER_CTX_block_size", ssllib);
907         } catch (Exception e){
908             // openSSL 0.9.7l defines only macros, not the function
909             EVP_CIPHER_CTX_block_size=&EVP_CIPHER_CTX_block_size_097l;
910         }
911         bindFunc(EVP_CIPHER_CTX_cleanup, "EVP_CIPHER_CTX_cleanup", ssllib);
912         
913         bindFunc(EVP_PKEY_type, "EVP_PKEY_type", ssllib);
914         bindFunc(EVP_PKEY_get1_RSA, "EVP_PKEY_get1_RSA", ssllib);
915         bindFunc(EVP_PKEY_get1_DSA, "EVP_PKEY_get1_DSA", ssllib);
916        
917         bindFunc(EVP_PKEY_CTX_new, "EVP_PKEY_CTX_new", ssllib);
918         bindFunc(EVP_PKEY_CTX_free, "EVP_PKEY_CTX_free", ssllib);
919         
920         bindFunc(EVP_PKEY_sign_init, "EVP_PKEY_sign_init", ssllib);
921         bindFunc(EVP_PKEY_sign, "EVP_PKEY_sign", ssllib);
922         
923         bindFunc(EVP_PKEY_verify_init, "EVP_PKEY_verify_init", ssllib);
924         bindFunc(EVP_PKEY_verify, "EVP_PKEY_verify", ssllib);
925         
926         bindFunc(EVP_PKEY_encrypt_init, "EVP_PKEY_encrypt_init", ssllib);
927         bindFunc(EVP_PKEY_encrypt, "EVP_PKEY_encrypt", ssllib);
928         
929         bindFunc(EVP_PKEY_decrypt_init, "EVP_PKEY_decrypt_init", ssllib);
930         bindFunc(EVP_PKEY_decrypt, "EVP_PKEY_decrypt", ssllib);
931 
932 
933         /*EVP_PKEY_CTX_new
934         EVP_PKEY_CTX_free
935         int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx);
936     int EVP_PKEY_sign(EVP_PKEY_CTX *ctx,
937                 unsigned char *sig, size_t *siglen,
938                 const unsigned char *tbs, size_t tbslen);
939     int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx);
940     int EVP_PKEY_verify(EVP_PKEY_CTX *ctx,
941                 const unsigned char *sig, size_t siglen,
942                 const unsigned char *tbs, size_t tbslen);
943 
944     int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx);
945     int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx,
946                 unsigned char *out, size_t *outlen,
947                 const unsigned char *in, size_t inlen);
948     int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx);
949     int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx,
950                 unsigned char *out, size_t *outlen,
951                 const unsigned char *in, size_t inlen);*/
952         
953     }
954 }
955 
956 void loadOpenSSL()
957 {
958     version (linux)
959     {
960         const(char[])[] loadPath = [ "libssl.so.0.9.8", "libssl.so.1.0.0", "libssl.so" ];
961     }
962     version (Windows)
963     {
964         const(char[])[] loadPath = [ "libssl32.dll" ];
965     }
966     version (darwin)
967     {
968         const(char[])[] loadPath = [ "/usr/lib/libssl.dylib", "libssl.dylib" ];
969     }
970     version (FreeBSD)
971     {
972         const(char[])[] loadPath = [ "libssl.so.5", "libssl.so" ];
973     }
974     version (solaris)
975     {
976         const(char[])[] loadPath = [ "libssl.so.0.9.8", "libssl.so.1.0.0", "libssl.so" ];
977     }
978     if ((ssllib = loadLib(loadPath)) !is null)
979     {
980 
981         bindFunc(BIO_new_ssl, "BIO_new_ssl", ssllib);
982         bindFunc(SSL_CTX_free, "SSL_CTX_free", ssllib);
983         bindFunc(SSL_CTX_new, "SSL_CTX_new", ssllib);
984         bindFunc(SSLv23_method, "SSLv23_method", ssllib);
985         bindFunc(SSL_CTX_use_PrivateKey, "SSL_CTX_use_PrivateKey", ssllib);
986         bindFunc(SSL_CTX_set_verify, "SSL_CTX_set_verify", ssllib);
987         bindFunc(SSL_CTX_ctrl, "SSL_CTX_ctrl", ssllib);
988         bindFunc(SSL_CTX_set_cipher_list, "SSL_CTX_set_cipher_list", ssllib);
989         bindFunc(SSL_load_error_strings, "SSL_load_error_strings", ssllib);
990         bindFunc(SSL_library_init, "SSL_library_init", ssllib);
991         bindFunc(SSL_CTX_check_private_key, "SSL_CTX_check_private_key", ssllib);
992         bindFunc(SSL_get_shutdown, "SSL_get_shutdown", ssllib);
993         bindFunc(SSL_set_shutdown, "SSL_set_shutdown", ssllib);
994         bindFunc(SSL_CTX_use_certificate, "SSL_CTX_use_certificate", ssllib);
995         bindFunc(SSL_CTX_set_cert_store, "SSL_CTX_set_cert_store", ssllib);
996         bindFunc(SSL_CTX_load_verify_locations, "SSL_CTX_load_verify_locations", ssllib);
997         bindFunc(SSL_CTX_set_session_id_context, "SSL_CTX_set_session_id_context", ssllib);
998         version(Posix)
999         {
1000             version(darwin){
1001                 string[] loadPathCrypto = [ "/usr/lib/libcrypto.dylib", "libcrypto.dylib" ];
1002                 cryptolib = loadLib(loadPathCrypto);
1003                 if (cryptolib !is null) bindCrypto(cryptolib);
1004             } else {
1005                 bindCrypto(ssllib);
1006             }
1007         }
1008 
1009         _initOpenSSL();
1010     }
1011     else
1012         throw new Exception("Could not load OpenSSL library.");
1013 }
1014 
1015 void closeOpenSSL()
1016 {
1017     CRYPTO_set_id_callback(null);
1018     CRYPTO_set_locking_callback(null);
1019     CRYPTO_set_dynlock_create_callback(null);
1020     CRYPTO_set_dynlock_lock_callback(null);
1021     CRYPTO_set_dynlock_destroy_callback(null);
1022     ERR_remove_state(0);
1023     RAND_cleanup();
1024     ERR_free_strings();
1025     EVP_cleanup();
1026     OBJ_cleanup();
1027     X509V3_EXT_cleanup();
1028     CRYPTO_cleanup_all_ex_data();
1029     if (ssllib)
1030         ssllib.unload();
1031     version(darwin){
1032         if (cryptolib)
1033             cryptolib.unload();
1034     }
1035     version(Win32)
1036     {
1037         if (eaylib)
1038             eaylib.unload();
1039     }
1040 }