Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

Ticket #857: OpenSSL.d

File OpenSSL.d, 34.1 kB (added by Wazar, 2 years ago)
Line 
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 const uint BYTES_ENTROPY = 2048; // default bytes of entropy to load on startup.
57 private CRYPTO_dynlock_value *last = null;
58 Mutex _dynLocksMutex = null;
59 extern (C)
60 {
61     const int NID_sha1 = 64;
62     const int NID_md5 = 4;
63     const int RSA_PKCS1_OAEP_PADDING = 4;
64     const int RSA_PKCS1_PADDING = 1;
65     const int BIO_C_SET_NBIO = 102;
66     const int SHA_DIGEST_LENGTH = 20;
67     const int SSL_CTRL_SET_SESS_CACHE_MODE = 44;
68     const int MBSTRING_FLAG = 0x1000;
69     const int MBSTRING_ASC = MBSTRING_FLAG | 1;
70     const int EVP_PKEY_RSA = 6;
71     const int RSA_F4 = 0x1001;
72     const int SSL_SENT_SHUTDOWN = 1;
73     const int SSL_RECEIVED_SHUTDOWN = 2;
74     const int BIO_C_GET_SSL = 110;
75     const int BIO_CTRL_RESET = 1;
76     const int BIO_CTRL_INFO = 3;
77     const int BIO_FLAGS_READ = 0x01;
78     const int BIO_FLAGS_WRITE = 0x02;
79     const int BIO_FLAGS_IO_SPECIAL = 0x04;
80     const int BIO_FLAGS_SHOULD_RETRY = 0x08;
81     const int BIO_CLOSE = 0x00;
82     const int BIO_NOCLOSE = 0x01;
83     const int ASN1_STRFLGS_ESC_CTRL = 2;
84     const int ASN1_STRFLGS_ESC_MSB = 4;
85     const int XN_FLAG_SEP_MULTILINE = (4 << 16);
86     const int XN_FLAG_SPC_EQ = (1 << 23);
87     const int XN_FLAG_FN_LN = (1 << 21);
88     const int XN_FLAG_FN_ALIGN = (1 << 25);
89     const 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     const char* PEM_STRING_EVP_PKEY = "ANY PRIVATE KEY";
92     const char* PEM_STRING_X509 = "CERTIFICATE";   
93     const char* PEM_STRING_RSA_PUBLIC = "RSA PUBLIC KEY";   
94
95     const int SSL_CTRL_OPTIONS = 32;
96
97     const int SSL_OP_ALL = 0x00000FFFL;
98     const int SSL_OP_NO_SSLv2 = 0x01000000L;
99
100     const int CRYPTO_LOCK = 1;
101     const int CRYPTO_UNLOCK = 2;
102     const int CRYPTO_READ = 4;
103     const int CRYPTO_WRITE = 8;
104
105     const int ERR_TXT_STRING = 0x02;
106
107     const int MD5_CBLOCK = 64;
108     const int MD5_LBLOCK = MD5_CBLOCK / 4;
109     const int MD5_DIGEST_LENGTH = 16;
110
111     const int EVP_MAX_BLOCK_LENGTH = 32;
112     const 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     typedef BIO* function(int sock, int close_flag) tBIO_new_socket;
164     typedef BIO* function(SSL_CTX *ctx, int client) tBIO_new_ssl;
165     typedef void function(BIO *bio) tBIO_free_all;
166     typedef 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 *pkey;
177         // yadda yadda ...       
178     };
179     struct X509_STORE_CTX {};
180     struct EVP_CIPHER {};
181     struct X509_ALGOR {};
182     struct ASN1_INTEGER {};
183     struct EVP_MD {};
184
185     struct ASN1_STRING
186     {
187         int length;
188         int type;
189         char *data;
190         int flags;
191     }
192
193     typedef ASN1_STRING ASN1_GENERALIZEDTIME;
194     typedef ASN1_STRING ASN1_TIME;
195
196     struct X509_STORE {};
197     struct X509_VAL
198     {
199         ASN1_TIME *notBefore;
200         ASN1_TIME *notAfter;
201     }
202     struct X509_CINF  // being lazy here, only doing the first peices up to what I need
203     {
204         ASN1_INTEGER *vers;
205         ASN1_INTEGER *serialNumber;
206         X509_ALGOR *signature;
207         X509_NAME *issuer;
208         X509_VAL *validity;
209         // yadda yadda
210     }
211
212     struct X509  // ditto X509_CINF
213     {
214         X509_CINF *cert_info;
215         // yadda yadda
216     };
217     struct X509_NAME {};
218     struct RSA {};
219     struct BIO_METHOD {};
220
221     typedef int function(char *buf, int size, int rwflag, void *userdata) pem_password_cb;
222     typedef char *function() d2i_of_void;
223     typedef int function() i2d_of_void;
224     typedef SSL_CTX* function(SSL_METHOD *meth) tSSL_CTX_new;
225     typedef SSL_METHOD* function() tSSLv23_method;
226     typedef EVP_PKEY* function(int type, EVP_PKEY **a, ubyte **pp, int length) td2i_PrivateKey;
227     typedef int function(SSL_CTX *ctx, EVP_PKEY *pkey) tSSL_CTX_use_PrivateKey;
228     typedef void function(SSL_CTX *ctx, int mode, int function(int, X509_STORE_CTX *) callback) tSSL_CTX_set_verify;
229     typedef void function(EVP_PKEY *pkey) tEVP_PKEY_free;
230     typedef int function(SSL_CTX *ctx, int cmd, int larg, void *parg) tSSL_CTX_ctrl;
231     typedef int function(SSL_CTX *ctx, char *str) tSSL_CTX_set_cipher_list;
232     typedef void function(SSL_CTX *) tSSL_CTX_free;
233     typedef void function() tSSL_load_error_strings;
234     typedef void function() tSSL_library_init;
235     typedef void function() tOpenSSL_add_all_digests;
236     typedef int function(char *file, int max_bytes) tRAND_load_file;
237     typedef int function() tCRYPTO_num_locks;
238     typedef void function(uint function() cb) tCRYPTO_set_id_callback;
239     typedef void function(void function(int mode, int type, char *file, int line) cb) tCRYPTO_set_locking_callback;
240     typedef void function(CRYPTO_dynlock_value *function(char *file, int line) cb) tCRYPTO_set_dynlock_create_callback;   
241     typedef void function(void function(int mode, CRYPTO_dynlock_value *lock, char *file, int lineNo) cb) tCRYPTO_set_dynlock_lock_callback;
242     typedef void function(void function(CRYPTO_dynlock_value *lock, char *file, int line) cb) tCRYPTO_set_dynlock_destroy_callback;
243     typedef uint function(char **file, int *line, char **data, int *flags) tERR_get_error_line_data;
244     typedef void function(uint pid) tERR_remove_state;
245     typedef void function() tRAND_cleanup;
246     typedef void function() tERR_free_strings;
247     typedef void function() tEVP_cleanup;
248     typedef void function() tOBJ_cleanup;
249     typedef void function() tX509V3_EXT_cleanup;
250     typedef void function() tCRYPTO_cleanup_all_ex_data;
251     typedef int function(BIO *b, void *data, int len) tBIO_write;
252     typedef int function(BIO *b, void *data, int len) tBIO_read;
253     typedef int function(SSL_CTX *ctx) tSSL_CTX_check_private_key;
254     typedef EVP_PKEY* function(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, void *u) tPEM_read_bio_PrivateKey;
255     typedef BIO* function(char *filename, char *mode) tBIO_new_file;
256     typedef int function() tERR_peek_error;
257     typedef int function(BIO *b, int flags) tBIO_test_flags;
258     typedef int function(BIO *b, int cmd, int larg, void *parg) tBIO_ctrl;
259     typedef void function(SSL *ssl, int mode) tSSL_set_shutdown;
260     typedef int function(SSL *ssl) tSSL_get_shutdown;
261     typedef int function(SSL_CTX *ctx, X509 *x) tSSL_CTX_use_certificate;
262     typedef void function(SSL_CTX *CTX, X509_STORE *store) tSSL_CTX_set_cert_store;
263     typedef int function(SSL_CTX *ctx, char *CAfile, char *CApath) tSSL_CTX_load_verify_locations;
264     typedef X509* function(X509_STORE_CTX *ctx) tX509_STORE_CTX_get_current_cert;
265     typedef int function(X509_STORE_CTX *ctx) tX509_STORE_CTX_get_error;
266     typedef int function(X509_STORE_CTX *ctx) tX509_STORE_CTX_get_error_depth;
267     typedef X509_STORE* function() tX509_STORE_new;
268     typedef void function(X509_STORE *v) tX509_STORE_free;
269     typedef int function(X509_STORE *store, X509 *x) tX509_STORE_add_cert;
270 //    typedef int function(X509_STORE *store, int depth) tX509_STORE_set_depth;
271     typedef BIO* function(void *buff, int len) tBIO_new_mem_buf;
272     typedef RSA* function(int bits, uint e, void function(int a, int b, void *c) callback, void *cb_arg) tRSA_generate_key;
273     typedef EVP_PKEY* function() tEVP_PKEY_new;
274     typedef int function(EVP_PKEY *pkey, int type, char *key) tEVP_PKEY_assign;
275     typedef void function(RSA *r) tRSA_free;
276     typedef BIO* function(BIO_METHOD *type) tBIO_new;
277     typedef BIO_METHOD* function() tBIO_s_mem;
278     typedef int function(BIO *bp, EVP_PKEY *x, EVP_CIPHER *cipher, char *kstr, int klen, pem_password_cb, void *) tPEM_write_bio_PKCS8PrivateKey;
279     typedef EVP_CIPHER* function() tEVP_aes_256_cbc;
280     typedef void* function(d2i_of_void d2i, char *name, BIO *bp, void **x, pem_password_cb cb, void *u) tPEM_ASN1_read_bio;
281     typedef X509* function() tX509_new;
282     typedef void function(X509 *x) tX509_free;
283     typedef int function(X509 *x, int ver) tX509_set_version;
284     typedef int function(ASN1_INTEGER *a, int v) tASN1_INTEGER_set;
285     typedef ASN1_INTEGER* function(X509 *x) tX509_get_serialNumber;
286     typedef int function(ASN1_INTEGER *a) tASN1_INTEGER_get;
287     typedef ASN1_TIME* function(ASN1_TIME *s, int adj) tX509_gmtime_adj;
288     typedef int function(X509 *x, EVP_PKEY *pkey) tX509_set_pubkey;
289     typedef X509_NAME* function(X509 *x) tX509_get_subject_name;
290     typedef int function(BIO *b, X509_NAME *nm, int indent, uint flags) tX509_NAME_print_ex;
291     typedef int function(X509 *x, X509_NAME *name) tX509_set_issuer_name;
292     typedef int function(X509 *x, EVP_PKEY *pkey, EVP_MD *md) tX509_sign;
293     typedef EVP_MD* function() tEVP_sha1;
294     typedef X509_STORE_CTX* function() tX509_STORE_CTX_new;
295     typedef int function(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, void *shizzle) tX509_STORE_CTX_init;
296     typedef int function(X509_STORE_CTX *ctx) tX509_verify_cert;
297     typedef void function(X509_STORE_CTX *ctx) tX509_STORE_CTX_free;
298     typedef int function(i2d_of_void i2d, char *name, BIO *bp, char *x, EVP_CIPHER *enc, char *kstr, int klen, pem_password_cb cb, void *u) tPEM_ASN1_write_bio;
299     typedef int function(X509_NAME *name, char* field, int type, char *bytes, int len, int loc, int set) tX509_NAME_add_entry_by_txt;
300     typedef int function(SSL_CTX *ctx, ubyte *id, uint len) tSSL_CTX_set_session_id_context;
301     typedef int function(EVP_PKEY *a, EVP_PKEY *b) tEVP_PKEY_cmp_parameters;
302     typedef int function(X509 *a, X509 *b) tX509_cmp;
303     typedef void function() tOPENSSL_add_all_algorithms_noconf;
304     typedef ASN1_GENERALIZEDTIME *function(ASN1_TIME *t, ASN1_GENERALIZEDTIME **outTime) tASN1_TIME_to_generalizedtime;
305     typedef void function(ASN1_STRING *a) tASN1_STRING_free;
306     typedef int function() tRAND_poll;
307     typedef int function(RSA *rsa) tRSA_size;
308     typedef int function(int flen, ubyte *from, ubyte *to, RSA *rsa, int padding) tRSA_public_encrypt;
309     typedef int function(int flen, ubyte *from, ubyte *to, RSA *rsa, int padding) tRSA_private_decrypt;
310     typedef int function(int flen, ubyte *from, ubyte *to, RSA *rsa, int padding) tRSA_private_encrypt;
311     typedef int function(int flen, ubyte *from, ubyte *to, RSA *rsa, int padding) tRSA_public_decrypt;
312     typedef int function(int type, ubyte *m, uint m_length, ubyte *sigret, uint *siglen, RSA *rsa) tRSA_sign;
313     typedef int function(int type, ubyte *m, uint m_length, ubyte *sigbuf, uint siglen, RSA *rsa) tRSA_verify;
314     typedef void function(MD5_CTX *c) tMD5_Init;
315     typedef void function(MD5_CTX *c, void *data, size_t len) tMD5_Update;
316     typedef void function(ubyte *md, MD5_CTX *c) tMD5_Final;
317     typedef int function(EVP_CIPHER_CTX *ctx, EVP_CIPHER *type, void *impl, ubyte *key, ubyte *iv) tEVP_EncryptInit_ex;
318     typedef int function(EVP_CIPHER_CTX *ctx, EVP_CIPHER *type, void *impl, ubyte *key, ubyte*iv) tEVP_DecryptInit_ex;
319     typedef int function(EVP_CIPHER_CTX *ctx, ubyte *outv, int *outl, ubyte *inv, int inl) tEVP_EncryptUpdate;
320     typedef int function(EVP_CIPHER_CTX *ctx, ubyte *outv, int *outl, ubyte *inv, int inl) tEVP_DecryptUpdate;
321     typedef int function(EVP_CIPHER_CTX *ctx, ubyte *outv, int *outl) tEVP_EncryptFinal_ex;
322     typedef int function(EVP_CIPHER_CTX *ctx, ubyte *outv, int *outl) tEVP_DecryptFinal_ex;
323     typedef int function(EVP_CIPHER_CTX *ctx) tEVP_CIPHER_CTX_block_size;
324     typedef EVP_CIPHER *function() tEVP_aes_128_cbc;
325     typedef int function(EVP_CIPHER_CTX *ctx) tEVP_CIPHER_CTX_cleanup;
326
327     struct CRYPTO_dynlock_value
328     {
329         ReadWriteMutex lock;
330         CRYPTO_dynlock_value *next;
331         CRYPTO_dynlock_value *prev;
332     }
333
334     uint sslThreadId()
335     {
336         return cast(uint)cast(void*)Thread.getThis;
337     }
338     void sslStaticLock(int mode, int index, char *sourceFile, int lineNo)
339     {
340         if (_locks)
341         {
342             if (mode & CRYPTO_LOCK)
343             {
344                 if (mode & CRYPTO_READ)
345                     _locks[index].reader.lock();
346                 else
347                     _locks[index].writer.lock();
348             }
349             else
350             {
351                 if (mode & CRYPTO_READ)
352                     _locks[index].reader.unlock();
353                 else
354                     _locks[index].writer.unlock();
355             }
356
357         }
358     }
359     uint ablah = 0;
360     CRYPTO_dynlock_value *sslDynamicLockCreate(char *sourceFile, int lineNo)
361     {
362         auto rtn = new CRYPTO_dynlock_value;
363         rtn.lock = new ReadWriteMutex;
364         synchronized
365         {
366             if (last is null)
367                 last = rtn;
368             else
369             {
370                 rtn.prev = last;
371                 last.next = rtn;
372                 last = rtn;
373             }       
374         }
375         return rtn;
376     }
377
378     void sslDynamicLockLock(int mode, CRYPTO_dynlock_value *lock, char *sourceFile, int lineNo)
379     {
380         if (lock && lock.lock)
381         {
382             if (mode & CRYPTO_LOCK)
383             {
384                 if (mode & CRYPTO_READ)
385                     lock.lock.reader.lock();
386                 else
387                     lock.lock.writer.lock();
388             }
389             else
390             {
391                 if (mode & CRYPTO_READ)
392                     lock.lock.reader.unlock();
393                 else
394                     lock.lock.writer.unlock();
395             }
396         }
397     }
398
399     void sslDynamicLockDestroy(CRYPTO_dynlock_value *lock, char *sourceFile, int lineNo)
400     {
401         synchronized
402         {
403             if (lock.prev)
404                 lock.prev.next = lock.next;
405             if (lock.next)
406                 lock.next.prev = lock.prev;   
407             if (lock is last)
408                 last = lock.prev;
409             lock = lock.next = lock.prev = null;
410         }
411     }
412
413 }
414 private bool _bioTestFlags = true;
415 tBIO_test_flags BIO_test_flags;
416 tBIO_new_socket BIO_new_socket;
417 tBIO_new_ssl BIO_new_ssl;
418 tBIO_free_all BIO_free_all;
419 tBIO_push BIO_push;
420 tBIO_read BIO_read;
421 tBIO_write BIO_write;
422 tSSL_CTX_new SSL_CTX_new;
423 tSSLv23_method SSLv23_method;
424 td2i_PrivateKey d2i_PrivateKey;
425 tSSL_CTX_use_PrivateKey SSL_CTX_use_PrivateKey;
426 tSSL_CTX_set_verify SSL_CTX_set_verify;
427 tEVP_PKEY_free EVP_PKEY_free;
428 tSSL_CTX_ctrl SSL_CTX_ctrl;
429 tSSL_CTX_set_cipher_list SSL_CTX_set_cipher_list;
430 tSSL_CTX_free SSL_CTX_free;
431 tSSL_load_error_strings SSL_load_error_strings;
432 tSSL_library_init SSL_library_init;
433 tRAND_load_file RAND_load_file;
434 tCRYPTO_num_locks CRYPTO_num_locks;
435 tCRYPTO_set_id_callback CRYPTO_set_id_callback;
436 tCRYPTO_set_locking_callback CRYPTO_set_locking_callback;
437 tCRYPTO_set_dynlock_create_callback CRYPTO_set_dynlock_create_callback;
438 tCRYPTO_set_dynlock_lock_callback CRYPTO_set_dynlock_lock_callback;
439 tCRYPTO_set_dynlock_destroy_callback CRYPTO_set_dynlock_destroy_callback;
440 tERR_get_error_line_data ERR_get_error_line_data;
441 tERR_remove_state ERR_remove_state;
442 tRAND_cleanup RAND_cleanup;
443 tERR_free_strings ERR_free_strings;
444 tEVP_cleanup EVP_cleanup;
445 tOBJ_cleanup OBJ_cleanup;
446 tX509V3_EXT_cleanup X509V3_EXT_cleanup;
447 tCRYPTO_cleanup_all_ex_data CRYPTO_cleanup_all_ex_data;
448 tSSL_CTX_check_private_key SSL_CTX_check_private_key;
449 tPEM_read_bio_PrivateKey PEM_read_bio_PrivateKey;
450 tBIO_new_file BIO_new_file;
451 tERR_peek_error ERR_peek_error;
452 tBIO_ctrl BIO_ctrl;
453 tSSL_get_shutdown SSL_get_shutdown;
454 tSSL_set_shutdown SSL_set_shutdown;
455 tSSL_CTX_use_certificate SSL_CTX_use_certificate;
456 tSSL_CTX_set_cert_store SSL_CTX_set_cert_store;
457 tSSL_CTX_load_verify_locations SSL_CTX_load_verify_locations;
458 tX509_STORE_CTX_get_current_cert X509_STORE_CTX_get_current_cert;
459 tX509_STORE_CTX_get_error_depth X509_STORE_CTX_get_error_depth;
460 tX509_STORE_CTX_get_error X509_STORE_CTX_get_error;
461 tX509_STORE_new X509_STORE_new;
462 tX509_STORE_free X509_STORE_free;
463 tX509_STORE_add_cert X509_STORE_add_cert;
464 //tX509_STORE_set_depth X509_STORE_set_depth;
465 tBIO_new_mem_buf BIO_new_mem_buf;
466 tRSA_generate_key RSA_generate_key;
467 tEVP_PKEY_new EVP_PKEY_new;
468 tEVP_PKEY_assign EVP_PKEY_assign;
469 tRSA_free RSA_free;
470 tBIO_new BIO_new;
471 tBIO_s_mem BIO_s_mem;
472 tPEM_write_bio_PKCS8PrivateKey PEM_write_bio_PKCS8PrivateKey;
473 tEVP_aes_256_cbc EVP_aes_256_cbc;
474 tPEM_ASN1_read_bio PEM_ASN1_read_bio;
475 d2i_of_void d2i_X509;
476 d2i_of_void d2i_RSAPublicKey;
477 tX509_new X509_new;
478 tX509_free X509_free;
479 tX509_set_version X509_set_version;
480 tASN1_INTEGER_set ASN1_INTEGER_set;
481 tX509_get_serialNumber X509_get_serialNumber;
482 tASN1_INTEGER_get ASN1_INTEGER_get;
483 tX509_gmtime_adj X509_gmtime_adj;
484 tX509_set_pubkey X509_set_pubkey;
485 tX509_get_subject_name X509_get_subject_name;
486 tX509_NAME_print_ex X509_NAME_print_ex;
487 tX509_set_issuer_name X509_set_issuer_name;
488 tX509_sign X509_sign;
489 tEVP_sha1 EVP_sha1;
490 tX509_STORE_CTX_new X509_STORE_CTX_new;
491 tX509_STORE_CTX_init X509_STORE_CTX_init;
492 tX509_verify_cert X509_verify_cert;
493 tX509_STORE_CTX_free X509_STORE_CTX_free;
494 tPEM_ASN1_write_bio PEM_ASN1_write_bio;
495 i2d_of_void i2d_X509;
496 i2d_of_void i2d_RSAPublicKey;
497 tX509_NAME_add_entry_by_txt X509_NAME_add_entry_by_txt;
498 tSSL_CTX_set_session_id_context SSL_CTX_set_session_id_context;
499 tEVP_PKEY_cmp_parameters EVP_PKEY_cmp_parameters;
500 tX509_cmp X509_cmp;
501 tOPENSSL_add_all_algorithms_noconf OPENSSL_add_all_algorithms_noconf;
502 tASN1_TIME_to_generalizedtime ASN1_TIME_to_generalizedtime;
503 tASN1_STRING_free ASN1_STRING_free;
504 tRAND_poll RAND_poll;
505 tRSA_size RSA_size;
506 tRSA_public_encrypt RSA_public_encrypt;
507 tRSA_private_decrypt RSA_private_decrypt;
508 tRSA_private_encrypt RSA_private_encrypt;
509 tRSA_public_decrypt RSA_public_decrypt;
510 tRSA_sign RSA_sign;
511 tRSA_verify RSA_verify;
512 tMD5_Init MD5_Init;
513 tMD5_Update MD5_Update;
514 tMD5_Final MD5_Final;
515 tEVP_EncryptInit_ex EVP_EncryptInit_ex;
516 tEVP_DecryptInit_ex EVP_DecryptInit_ex;
517 tEVP_EncryptUpdate EVP_EncryptUpdate;
518 tEVP_DecryptUpdate EVP_DecryptUpdate;
519 tEVP_EncryptFinal_ex EVP_EncryptFinal_ex;
520 tEVP_DecryptFinal_ex EVP_DecryptFinal_ex;
521 tEVP_aes_128_cbc EVP_aes_128_cbc;
522 tEVP_CIPHER_CTX_block_size EVP_CIPHER_CTX_block_size;
523 tEVP_CIPHER_CTX_cleanup EVP_CIPHER_CTX_cleanup;
524
525 int PEM_write_bio_RSAPublicKey(BIO *bp, RSA *x)
526 {
527     return PEM_ASN1_write_bio(i2d_RSAPublicKey, PEM_STRING_RSA_PUBLIC, bp, cast(char*)x, null, null, 0, null, null);
528 }
529
530 RSA *PEM_read_bio_RSAPublicKey(BIO *bp, RSA **x, pem_password_cb cb, void *u)
531 {
532     return cast(RSA *)PEM_ASN1_read_bio(d2i_RSAPublicKey, PEM_STRING_RSA_PUBLIC, bp, cast(void **)x, cb, u);
533 }
534
535 int PEM_write_bio_X509(BIO *b, X509 *x)
536 {
537     return PEM_ASN1_write_bio(i2d_X509, PEM_STRING_X509, b,cast(char *)x, null, null, 0, null, null);
538 }
539
540 ASN1_TIME *X509_get_notBefore(X509 *x)
541 {
542     return x.cert_info.validity.notBefore;
543 }
544
545 ASN1_TIME *X509_get_notAfter(X509 *x)
546 {
547     return x.cert_info.validity.notAfter;
548 }
549
550 int EVP_PKEY_assign_RSA(EVP_PKEY *key, RSA *rsa)
551 {
552     return EVP_PKEY_assign(key, EVP_PKEY_RSA, cast(char*)rsa);
553 }
554
555 int BIO_get_mem_data(BIO *b, char **data)
556 {
557     return BIO_ctrl(b, BIO_CTRL_INFO, 0, data);
558 }
559
560 void BIO_get_ssl(BIO *b, SSL **obj)
561 {
562     BIO_ctrl(b, BIO_C_GET_SSL, 0, obj);
563 }
564
565 int SSL_CTX_set_options(SSL_CTX *ctx, int larg)
566 {
567     return SSL_CTX_ctrl(ctx, SSL_CTRL_OPTIONS, larg, null);
568 }
569
570 int SSL_CTX_set_session_cache_mode(SSL_CTX *ctx, int mode)
571 {
572     return SSL_CTX_ctrl(ctx, SSL_CTRL_SET_SESS_CACHE_MODE, mode, null);
573 }
574
575 int BIO_reset(BIO *b)
576 {
577     return BIO_ctrl(b, BIO_CTRL_RESET, 0, null);
578 }
579
580 bool BIO_should_retry(BIO *b)
581 {
582     if (_bioTestFlags)
583         return cast(bool)BIO_test_flags(b, BIO_FLAGS_SHOULD_RETRY);
584     return cast(bool)(b.flags & BIO_FLAGS_SHOULD_RETRY);
585 }
586
587 bool BIO_should_io_special(BIO *b)
588 {
589     if (_bioTestFlags)
590         return cast(bool)BIO_test_flags(b, BIO_FLAGS_IO_SPECIAL);
591     return cast(bool)(b.flags & BIO_FLAGS_IO_SPECIAL);
592 }
593
594 bool BIO_should_read(BIO *b)
595 {
596     if (_bioTestFlags)
597         return cast(bool)BIO_test_flags(b, BIO_FLAGS_READ);
598     return cast(bool)(b.flags & BIO_FLAGS_READ);
599 }
600
601 bool BIO_should_write(BIO *b)
602 {
603     if (_bioTestFlags)
604         return cast(bool)BIO_test_flags(b, BIO_FLAGS_WRITE);
605     return cast(bool)(b.flags & BIO_FLAGS_WRITE);
606 }
607
608 X509* PEM_read_bio_X509(BIO *b, X509 **x, pem_password_cb cb, void *u)
609 {
610     return cast(X509 *)PEM_ASN1_read_bio(d2i_X509, PEM_STRING_X509, b, cast(void**)x, cb, u);
611 }
612
613
614 private void bindFunc(T)(ref T func, char[] funcName, SharedLib lib)
615 in
616 {
617     assert(funcName);
618     assert(lib);
619 }
620 body
621 {
622        
623     void *funcPtr = lib.getSymbol(toStringz(funcName));
624     if (funcPtr)
625     {
626         void **point = cast(void **)&func;
627         *point = funcPtr;
628     }
629     else
630         throw new Exception("Could not load symbol: " ~ funcName);
631 }
632
633 static SharedLib ssllib = null;
634 version(Win32)
635 {
636     static SharedLib eaylib = null;
637 }
638 version(darwin){
639     static SharedLib cryptolib = null;
640 }
641 static ReadWriteMutex[] _locks = null;
642
643
644 void throwOpenSSLError()
645 {
646     if (ERR_peek_error())
647     {
648         char[] exceptionString;
649
650         int flags, line;
651         char *data;
652         char *file;
653         uint code;
654
655         code = ERR_get_error_line_data(&file, &line, &data, &flags);
656         while (code != 0)
657         {
658             if (data && (flags & ERR_TXT_STRING))
659                 exceptionString ~= Format.convert("ssl error code: {} {}:{} - {}\r\n", code, fromStringz(file), line, fromStringz(data));
660             else
661                 exceptionString ~= Format.convert("ssl error code: {} {}:{}\r\n", code, fromStringz(file), line);
662             code = ERR_get_error_line_data(&file, &line, &data, &flags);
663         }
664         throw new Exception(exceptionString);
665     }
666     else
667         throw new Exception("Unknown OpenSSL error.");
668 }
669
670 void _initOpenSSL()
671 {
672     SSL_load_error_strings();
673     SSL_library_init();
674     OPENSSL_add_all_algorithms_noconf();
675     version(Posix)
676         RAND_load_file("/dev/urandom", BYTES_ENTROPY);
677     version(Win32)
678     {
679         RAND_poll();
680     }
681
682     uint numLocks = CRYPTO_num_locks();
683     if ((_locks = new ReadWriteMutex[numLocks]) !is null)
684     {
685         uint i = 0;
686         for (; i < numLocks; i++)
687         {
688             if((_locks[i] = new ReadWriteMutex()) is null)
689                 break;
690         }
691         if (i == numLocks)
692         {
693             CRYPTO_set_id_callback(&sslThreadId);
694             CRYPTO_set_locking_callback(&sslStaticLock);
695
696             CRYPTO_set_dynlock_create_callback(&sslDynamicLockCreate);
697             CRYPTO_set_dynlock_lock_callback(&sslDynamicLockLock);
698             CRYPTO_set_dynlock_destroy_callback(&sslDynamicLockDestroy);
699
700         }
701     }
702 }
703
704 static this()
705 {
706     version(Win32)
707         loadEAY32();
708     loadOpenSSL();
709 }
710 // 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.
711 /*static ~this()
712 {
713     closeOpenSSL();
714 }*/
715
716
717 SharedLib loadLib(char[][] loadPath)
718 {
719     SharedLib rtn;
720     foreach(path; loadPath)
721     {
722         try
723             rtn = SharedLib.load(path);
724         catch (SharedLibException ex)
725         {
726             scope fp = new FilePath(path);
727             try
728                 rtn = SharedLib.load(fp.absolute(Environment.cwd()).toString);
729             catch (SharedLibException ex)
730             {}
731         }
732     }
733     return rtn;
734 }
735
736 version (Win32)
737 {
738     void loadEAY32()
739     {
740         char[][] loadPath = [ "libeay32.dll" ];
741         if ((eaylib = loadLib(loadPath)) !is null)
742         {
743             bindCrypto(eaylib);   
744         }
745     }
746
747 }
748
749 void bindCrypto(SharedLib ssllib)
750 {
751    
752     if (ssllib)
753     {
754         bindFunc(X509_cmp, "X509_cmp", ssllib);
755         bindFunc(OPENSSL_add_all_algorithms_noconf, "OPENSSL_add_all_algorithms_noconf", ssllib);
756         bindFunc(ASN1_TIME_to_generalizedtime, "ASN1_TIME_to_generalizedtime", ssllib);
757         bindFunc(ASN1_STRING_free, "ASN1_STRING_free", ssllib);
758         bindFunc(EVP_PKEY_cmp_parameters, "EVP_PKEY_cmp_parameters", ssllib);
759         bindFunc(X509_STORE_CTX_get_current_cert, "X509_STORE_CTX_get_current_cert", ssllib);
760         bindFunc(X509_STORE_CTX_get_error_depth, "X509_STORE_CTX_get_error_depth", ssllib);
761         bindFunc(X509_STORE_CTX_get_error, "X509_STORE_CTX_get_error", ssllib);
762         bindFunc(X509_STORE_new, "X509_STORE_new", ssllib);
763         bindFunc(X509_STORE_free, "X509_STORE_free", ssllib);
764         bindFunc(X509_STORE_add_cert, "X509_STORE_add_cert", ssllib);
765 //        bindFunc(X509_STORE_set_depth, "X509_STORE_set_depth", ssllib);
766         bindFunc(BIO_new_mem_buf, "BIO_new_mem_buf", ssllib);
767         bindFunc(RSA_generate_key, "RSA_generate_key", ssllib);
768         bindFunc(EVP_PKEY_new, "EVP_PKEY_new", ssllib);
769         bindFunc(EVP_PKEY_assign, "EVP_PKEY_assign", ssllib);
770         bindFunc(RSA_free, "RSA_free", ssllib);
771         bindFunc(BIO_new, "BIO_new", ssllib);
772         bindFunc(BIO_s_mem, "BIO_s_mem", ssllib);
773         bindFunc(PEM_write_bio_PKCS8PrivateKey, "PEM_write_bio_PKCS8PrivateKey", ssllib);
774         bindFunc(EVP_aes_256_cbc, "EVP_aes_256_cbc", ssllib);
775         bindFunc(PEM_ASN1_read_bio, "PEM_ASN1_read_bio", ssllib);
776         bindFunc(d2i_X509, "d2i_X509", ssllib);
777         bindFunc(d2i_RSAPublicKey, "d2i_RSAPublicKey", ssllib);
778         bindFunc(X509_new, "X509_new", ssllib);
779         bindFunc(X509_free, "X509_free", ssllib);
780         bindFunc(X509_set_version, "X509_set_version", ssllib);
781         bindFunc(ASN1_INTEGER_set, "ASN1_INTEGER_set", ssllib);
782         bindFunc(X509_get_serialNumber, "X509_get_serialNumber", ssllib);
783         bindFunc(ASN1_INTEGER_get, "ASN1_INTEGER_get", ssllib);
784         bindFunc(X509_gmtime_adj, "X509_gmtime_adj", ssllib);
785         bindFunc(X509_set_pubkey, "X509_set_pubkey", ssllib);
786         bindFunc(X509_get_subject_name, "X509_get_subject_name", ssllib);
787         bindFunc(X509_NAME_print_ex, "X509_NAME_print_ex", ssllib);
788         bindFunc(X509_set_issuer_name, "X509_set_issuer_name", ssllib);
789         bindFunc(X509_sign, "X509_sign", ssllib);
790         bindFunc(EVP_sha1, "EVP_sha1", ssllib);
791         bindFunc(X509_STORE_CTX_new, "X509_STORE_CTX_new", ssllib);
792         bindFunc(X509_STORE_CTX_init, "X509_STORE_CTX_init", ssllib);
793         bindFunc(X509_verify_cert, "X509_verify_cert", ssllib);
794         bindFunc(X509_STORE_CTX_free, "X509_STORE_CTX_free", ssllib);
795         bindFunc(PEM_ASN1_write_bio, "PEM_ASN1_write_bio", ssllib);
796         bindFunc(i2d_X509, "i2d_X509", ssllib);
797         bindFunc(i2d_RSAPublicKey, "i2d_RSAPublicKey", ssllib);
798         bindFunc(X509_NAME_add_entry_by_txt, "X509_NAME_add_entry_by_txt", ssllib);
799         bindFunc(PEM_read_bio_PrivateKey, "PEM_read_bio_PrivateKey", ssllib);
800         bindFunc(BIO_new_file, "BIO_new_file", ssllib);
801         bindFunc(ERR_peek_error, "ERR_peek_error", ssllib);
802                
803         try
804             bindFunc(BIO_test_flags, "BIO_test_flags", ssllib); // 0.9.7 doesn't have this function, it access the struct directly
805         catch (Exception ex)
806             _bioTestFlags = false;
807                    
808         bindFunc(BIO_ctrl, "BIO_ctrl", ssllib);
809                
810         bindFunc(RAND_load_file, "RAND_load_file", ssllib);
811         bindFunc(CRYPTO_num_locks, "CRYPTO_num_locks", ssllib);
812         bindFunc(CRYPTO_set_id_callback, "CRYPTO_set_id_callback", ssllib);
813                
814         bindFunc(CRYPTO_set_locking_callback, "CRYPTO_set_locking_callback", ssllib);
815         bindFunc(CRYPTO_set_dynlock_create_callback, "CRYPTO_set_dynlock_create_callback", ssllib);
816         bindFunc(CRYPTO_set_dynlock_lock_callback, "CRYPTO_set_dynlock_lock_callback", ssllib);
817         bindFunc(CRYPTO_set_dynlock_lock_callback, "CRYPTO_set_dynlock_lock_callback", ssllib);
818         bindFunc(CRYPTO_set_dynlock_destroy_callback, "CRYPTO_set_dynlock_destroy_callback", ssllib);
819                
820         //bindFunc(ERR_get_error_line_data, "ERR_get_error_line_data", ssllib);
821                
822         bindFunc(ERR_remove_state, "ERR_remove_state", ssllib);
823         bindFunc(RAND_cleanup, "RAND_cleanup", ssllib);
824         bindFunc(ERR_free_strings, "ERR_free_strings", ssllib);
825         bindFunc(EVP_cleanup, "EVP_cleanup", ssllib);
826         bindFunc(OBJ_cleanup, "OBJ_cleanup", ssllib);
827         bindFunc(X509V3_EXT_cleanup, "X509V3_EXT_cleanup", ssllib);
828         bindFunc(CRYPTO_cleanup_all_ex_data, "CRYPTO_cleanup_all_ex_data", ssllib);
829         bindFunc(BIO_read, "BIO_read", ssllib);
830         bindFunc(BIO_write, "BIO_write", ssllib);
831         bindFunc(EVP_PKEY_free, "EVP_PKEY_free", ssllib);
832         bindFunc(d2i_PrivateKey, "d2i_PrivateKey", ssllib);   
833         bindFunc(BIO_free_all, "BIO_free_all", ssllib);
834         bindFunc(BIO_push, "BIO_push", ssllib);   
835         bindFunc(BIO_new_socket, "BIO_new_socket", ssllib);
836         bindFunc(RAND_poll, "RAND_poll", ssllib);
837         bindFunc(RSA_size, "RSA_size", ssllib);
838
839         bindFunc(RSA_public_encrypt, "RSA_public_encrypt", ssllib);
840         bindFunc(RSA_private_decrypt, "RSA_private_decrypt", ssllib);
841         bindFunc(RSA_private_encrypt, "RSA_private_encrypt", ssllib);
842         bindFunc(RSA_public_decrypt, "RSA_public_decrypt", ssllib);
843         bindFunc(RSA_sign, "RSA_sign", ssllib);
844         bindFunc(RSA_verify, "RSA_verify", ssllib);
845         bindFunc(MD5_Init, "MD5_Init", ssllib);
846         bindFunc(MD5_Update, "MD5_Update", ssllib);
847         bindFunc(MD5_Final, "MD5_Final", ssllib);
848         bindFunc(EVP_EncryptInit_ex, "EVP_EncryptInit_ex", ssllib);
849         bindFunc(EVP_DecryptInit_ex, "EVP_DecryptInit_ex", ssllib);
850         bindFunc(EVP_EncryptUpdate, "EVP_EncryptUpdate", ssllib);
851         bindFunc(EVP_DecryptUpdate,  "EVP_DecryptUpdate", ssllib);
852         bindFunc(EVP_EncryptFinal_ex, "EVP_EncryptFinal_ex", ssllib);
853         bindFunc(EVP_DecryptFinal_ex, "EVP_DecryptFinal_ex", ssllib);
854         bindFunc(EVP_aes_128_cbc, "EVP_aes_128_cbc", ssllib);
855            
856         try {
857             bindFunc(EVP_CIPHER_CTX_block_size, "EVP_CIPHER_CTX_block_size", ssllib);
858         } catch (Exception e){
859             // openSSL 0.9.7l defines only macros, not the function
860             EVP_CIPHER_CTX_block_size=&EVP_CIPHER_CTX_block_size_097l;
861         }
862         bindFunc(EVP_CIPHER_CTX_cleanup, "EVP_CIPHER_CTX_cleanup", ssllib);
863     }
864 }
865
866 void loadOpenSSL()
867 {
868     version (linux)
869     {
870         char[][] loadPath = [ "libssl.so.0.9.8", "libssl.so" ];
871     }
872     version (Win32)
873     {
874         char[][] loadPath = [ "libssl32.dll" ];
875     }
876     version (darwin)
877     {
878         char[][] loadPath = [ "/usr/lib/libssl.dylib", "libssl.dylib" ];
879     }
880     version (freebsd)
881     {
882         char[][] loadPath = [ "libssl.so.5", "libssl.so" ];
883     }
884     version (solaris)
885     {
886         char[][] loadPath = [ "libssl.so.0.9.8", "libssl.so" ];
887     }
888     if ((ssllib = loadLib(loadPath)) !is null)
889     {
890
891         bindFunc(BIO_new_ssl, "BIO_new_ssl", ssllib);
892         bindFunc(SSL_CTX_free, "SSL_CTX_free", ssllib);
893         bindFunc(SSL_CTX_new, "SSL_CTX_new", ssllib);
894         bindFunc(SSLv23_method, "SSLv23_method", ssllib);
895         bindFunc(SSL_CTX_use_PrivateKey, "SSL_CTX_use_PrivateKey", ssllib);
896         bindFunc(SSL_CTX_set_verify, "SSL_CTX_set_verify", ssllib);
897         bindFunc(SSL_CTX_ctrl, "SSL_CTX_ctrl", ssllib);
898         bindFunc(SSL_CTX_set_cipher_list, "SSL_CTX_set_cipher_list", ssllib);
899         bindFunc(SSL_load_error_strings, "SSL_load_error_strings", ssllib);
900         bindFunc(SSL_library_init, "SSL_library_init", ssllib);
901         bindFunc(SSL_CTX_check_private_key, "SSL_CTX_check_private_key", ssllib);
902         bindFunc(SSL_get_shutdown, "SSL_get_shutdown", ssllib);
903         bindFunc(SSL_set_shutdown, "SSL_set_shutdown", ssllib);
904         bindFunc(SSL_CTX_use_certificate, "SSL_CTX_use_certificate", ssllib);
905         bindFunc(SSL_CTX_set_cert_store, "SSL_CTX_set_cert_store", ssllib);
906         bindFunc(SSL_CTX_load_verify_locations, "SSL_CTX_load_verify_locations", ssllib);
907         bindFunc(SSL_CTX_set_session_id_context, "SSL_CTX_set_session_id_context", ssllib);
908         version(Posix)
909         {
910             version(darwin){
911                 char[][] loadPathCrypto = [ "/usr/lib/libcrypto.dylib", "libcrypto.dylib" ];
912                 cryptolib = loadLib(loadPathCrypto);
913                 if (cryptolib !is null) bindCrypto(cryptolib);
914             } else {
915                 bindCrypto(ssllib);
916             }
917         }
918
919         _initOpenSSL();
920     }
921     else
922         throw new Exception("Could not load OpenSSL library.");
923 }
924
925 void closeOpenSSL()
926 {
927     CRYPTO_set_id_callback(null);
928     CRYPTO_set_locking_callback(null);
929     CRYPTO_set_dynlock_create_callback(null);
930     CRYPTO_set_dynlock_lock_callback(null);
931     CRYPTO_set_dynlock_destroy_callback(null);
932     ERR_remove_state(0);
933     RAND_cleanup();
934     ERR_free_strings();
935     EVP_cleanup();
936     OBJ_cleanup();
937     X509V3_EXT_cleanup();
938     CRYPTO_cleanup_all_ex_data();
939     if (ssllib)
940         ssllib.unload();
941     version(darwin){
942         if (cryptolib)
943             cryptolib.unload();
944     }
945     version(Win32)
946     {
947         if (eaylib)
948             eaylib.unload();
949     }
950 }