Removed W->A from DEFWND_ImmIsUIMessageW.
[wine] / dlls / rsaenh / implossl.c
1 /*
2  * dlls/rsaenh/implossl.c
3  * Encapsulating the OpenSSL dependend parts of RSAENH
4  *
5  * Copyright (c) 2004 Michael Jung
6  *
7  * based on code by Mike McCormack and David Hammerton
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 #include "config.h"
24
25 #include "wine/port.h"
26 #include "wine/library.h"
27 #include "wine/debug.h"
28
29 #include "windef.h"
30 #include "wincrypt.h"
31
32 #include "implossl.h"
33
34 #include <stdio.h>
35
36 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
37
38 #ifndef SONAME_LIBCRYPTO
39 #define SONAME_LIBCRYPTO "libcrypto.so"
40 #endif
41
42 static void *libcrypto;
43
44 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
45
46 /* OpenSSL funtions that we use */
47 #ifdef HAVE_OPENSSL_MD2_H
48 MAKE_FUNCPTR(MD2_Init);
49 MAKE_FUNCPTR(MD2_Update);
50 MAKE_FUNCPTR(MD2_Final);
51 #endif
52 #ifdef HAVE_OPENSSL_RC2_H
53 MAKE_FUNCPTR(RC2_set_key);
54 MAKE_FUNCPTR(RC2_ecb_encrypt);
55 #endif
56 #ifdef HAVE_OPENSSL_RC4_H
57 MAKE_FUNCPTR(RC4_set_key);
58 MAKE_FUNCPTR(RC4);
59 #endif
60 #ifdef HAVE_OPENSSL_DES_H
61 MAKE_FUNCPTR(DES_set_odd_parity);
62 MAKE_FUNCPTR(DES_set_key_unchecked);
63 MAKE_FUNCPTR(DES_ecb_encrypt);
64 MAKE_FUNCPTR(DES_ecb3_encrypt);
65 #endif
66 #ifdef HAVE_OPENSSL_RSA_H
67 MAKE_FUNCPTR(RSA_generate_key);
68 MAKE_FUNCPTR(RSA_free);
69 MAKE_FUNCPTR(RSA_size);
70 MAKE_FUNCPTR(RSA_check_key);
71 MAKE_FUNCPTR(RSA_public_encrypt);
72 MAKE_FUNCPTR(RSA_private_encrypt);
73 MAKE_FUNCPTR(RSAPrivateKey_dup);
74 MAKE_FUNCPTR(BN_bn2bin);
75 MAKE_FUNCPTR(BN_bin2bn);
76 MAKE_FUNCPTR(BN_get_word);
77 MAKE_FUNCPTR(BN_set_word);
78 MAKE_FUNCPTR(BN_num_bits);
79 #endif
80
81 /* Function prototypes copied from dlls/advapi32/crypt_md4.c */
82 VOID WINAPI MD4Init( MD4_CTX *ctx );
83 VOID WINAPI MD4Update( MD4_CTX *ctx, const unsigned char *buf, unsigned int len );
84 VOID WINAPI MD4Final( MD4_CTX *ctx );
85 /* Function prototypes copied from dlls/advapi32/crypt_md5.c */
86 VOID WINAPI MD5Init( MD5_CTX *ctx );
87 VOID WINAPI MD5Update( MD5_CTX *ctx, const unsigned char *buf, unsigned int len );
88 VOID WINAPI MD5Final( MD5_CTX *ctx );
89 /* Function prototypes copied from dlls/advapi32/crypt_sha.c */
90 VOID WINAPI A_SHAInit(PSHA_CTX Context);
91 VOID WINAPI A_SHAUpdate(PSHA_CTX Context, PCHAR Buffer, UINT BufferSize);
92 VOID WINAPI A_SHAFinal(PSHA_CTX Context, PULONG Result);
93         
94
95 BOOL load_lib( void )
96 {
97 /* FIXME: Is this portable? */
98 #if defined HAVE_OPENSSL_MD2_H || defined HAVE_OPENSSL_RC2_H || defined HAVE_OPENSSL_RC4_H || \
99     defined HAVE_OPENSSL_DES_H || defined HAVE_OPENSSL_RSA_H
100     libcrypto = wine_dlopen(SONAME_LIBCRYPTO, RTLD_NOW, NULL, 0);
101     if (!libcrypto)
102     {
103         MESSAGE("Couldn't load %s, RSA encryption not available.\n", SONAME_LIBCRYPTO);
104         MESSAGE("Install the openssl package if you're have problems.\n");
105         SetLastError(NTE_PROVIDER_DLL_FAIL);
106         return FALSE;
107     }
108
109 #define GETFUNC(x) p##x = wine_dlsym(libcrypto, #x, NULL, 0);
110
111 #ifdef HAVE_OPENSSL_MD2_H
112     GETFUNC(MD2_Init);
113     GETFUNC(MD2_Update);
114     GETFUNC(MD2_Final);
115 #endif
116 #ifdef HAVE_OPENSSL_RC2_H
117     GETFUNC(RC2_set_key);
118     GETFUNC(RC2_ecb_encrypt);
119 #endif
120 #ifdef HAVE_OPENSSL_RC4_H
121     GETFUNC(RC4_set_key);
122     GETFUNC(RC4);
123 #endif
124 #ifdef HAVE_OPENSSL_DES_H
125     GETFUNC(DES_set_odd_parity);
126     GETFUNC(DES_set_key_unchecked);
127     GETFUNC(DES_ecb_encrypt);
128     GETFUNC(DES_ecb3_encrypt);
129 #endif
130 #ifdef HAVE_OPENSSL_RSA_H
131     GETFUNC(RSA_generate_key);
132     GETFUNC(RSA_free);
133     GETFUNC(RSA_size);
134     GETFUNC(RSA_check_key);
135     GETFUNC(RSA_public_encrypt);
136     GETFUNC(RSA_private_encrypt);
137     GETFUNC(RSAPrivateKey_dup);
138     GETFUNC(BN_bn2bin);
139     GETFUNC(BN_bin2bn);
140     GETFUNC(BN_get_word);
141     GETFUNC(BN_set_word);
142     GETFUNC(BN_num_bits);
143 #endif
144    
145 #endif /* ifdef have any openssl header */
146     return TRUE;
147 }
148
149 BOOL init_hash_impl(ALG_ID aiAlgid, HASH_CONTEXT *pHashContext) 
150 {
151     switch (aiAlgid) 
152     {
153 #ifdef HAVE_OPENSSL_MD2_H
154         case CALG_MD2:
155             if (!pMD2_Init) 
156             {
157                 SetLastError(NTE_PROVIDER_DLL_FAIL);
158                 return FALSE;
159             }
160             pMD2_Init(&pHashContext->md2);
161             break;
162 #endif
163         case CALG_MD4:
164             MD4Init(&pHashContext->md4);
165             break;
166         
167         case CALG_MD5:
168             MD5Init(&pHashContext->md5);
169             break;
170         
171         case CALG_SHA:
172             A_SHAInit(&pHashContext->sha);
173             break;
174         
175         default:
176             SetLastError(NTE_BAD_ALGID);
177             return FALSE;
178     }
179
180     return TRUE;
181 }
182
183 BOOL update_hash_impl(ALG_ID aiAlgid, HASH_CONTEXT *pHashContext, CONST BYTE *pbData, 
184                       DWORD dwDataLen) 
185 {
186     switch (aiAlgid)
187     {
188 #ifdef HAVE_OPENSSL_MD2_H
189         case CALG_MD2:
190             if (!pMD2_Update)
191             {
192                 SetLastError(NTE_PROVIDER_DLL_FAIL);
193                 return FALSE;
194             }
195             pMD2_Update(&pHashContext->md2, pbData, dwDataLen);
196             break;
197 #endif        
198         case CALG_MD4:
199             MD4Update(&pHashContext->md4, pbData, dwDataLen);
200             break;
201     
202         case CALG_MD5:
203             MD5Update(&pHashContext->md5, pbData, dwDataLen);
204             break;
205         
206         case CALG_SHA:
207             A_SHAUpdate(&pHashContext->sha, (PCHAR)pbData, dwDataLen);
208             break;
209         
210         default:
211             SetLastError(NTE_BAD_ALGID);
212             return FALSE;
213     }
214
215     return TRUE;
216 }
217
218 BOOL finalize_hash_impl(ALG_ID aiAlgid, HASH_CONTEXT *pHashContext, BYTE *pbHashValue) 
219 {
220     switch (aiAlgid)
221     {
222 #ifdef HAVE_OPENSSL_MD2_H
223         case CALG_MD2:
224             if (!pMD2_Final) 
225             {
226                 SetLastError(NTE_PROVIDER_DLL_FAIL);
227                 return FALSE;
228             }
229             pMD2_Final(pbHashValue, &pHashContext->md2);
230             break;
231 #endif
232         case CALG_MD4:
233             MD4Final(&pHashContext->md4);
234             memcpy(pbHashValue, pHashContext->md4.digest, 16);
235             break;
236         
237         case CALG_MD5:
238             MD5Final(&pHashContext->md5);
239             memcpy(pbHashValue, pHashContext->md5.digest, 16);
240             break;
241         
242         case CALG_SHA:
243             A_SHAFinal(&pHashContext->sha, (PULONG)pbHashValue);
244             break;
245         
246         default:
247             SetLastError(NTE_BAD_ALGID);
248             return FALSE;
249     }
250
251     return TRUE;
252 }
253
254 BOOL duplicate_hash_impl(ALG_ID aiAlgid, CONST HASH_CONTEXT *pSrcHashContext, 
255                          HASH_CONTEXT *pDestHashContext) 
256 {
257     memcpy(pDestHashContext, pSrcHashContext, sizeof(HASH_CONTEXT));
258
259     return TRUE;
260 }
261
262 BOOL new_key_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen) 
263 {
264     switch (aiAlgid)
265     {
266 #ifdef HAVE_OPENSSL_RSA_H
267         case CALG_RSA_KEYX:
268         case CALG_RSA_SIGN:
269             if (!pRSA_generate_key) 
270             {
271                 SetLastError(NTE_PROVIDER_DLL_FAIL);
272                 return FALSE;
273             }
274             pKeyContext->rsa = pRSA_generate_key((int)dwKeyLen*8, 65537, NULL, NULL);
275             break;
276 #endif  
277         default:
278             SetLastError(NTE_BAD_ALGID);
279             return FALSE;
280     }
281
282     return TRUE;
283 }
284
285 BOOL free_key_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext)
286 {
287     switch (aiAlgid)
288     {
289 #ifdef HAVE_OPENSSL_RSA_H
290         case CALG_RSA_KEYX:
291         case CALG_RSA_SIGN:
292             if (!pRSA_free) 
293             {
294                 SetLastError(NTE_PROVIDER_DLL_FAIL);
295                 return FALSE;
296             }
297             if (pKeyContext->rsa) pRSA_free(pKeyContext->rsa);
298             break;
299 #endif  
300         default:
301             SetLastError(NTE_BAD_ALGID);
302             return FALSE;
303     }
304
305     return TRUE;
306 }
307
308 BOOL setup_key_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen, DWORD dwSaltLen, 
309                     BYTE *abKeyValue) 
310 {
311     switch (aiAlgid) 
312     {
313 #ifdef HAVE_OPENSSL_RC4_H
314         case CALG_RC4:
315             if (!pRC4_set_key) 
316             {
317                 SetLastError(NTE_PROVIDER_DLL_FAIL);
318                 return FALSE;
319             }
320             pRC4_set_key(&pKeyContext->rc4, dwKeyLen + dwSaltLen, abKeyValue);
321             break;
322 #endif
323 #ifdef HAVE_OPENSSL_RC2_H
324         case CALG_RC2:
325             if (!pRC2_set_key)
326             {
327                 SetLastError(NTE_PROVIDER_DLL_FAIL);
328                 return FALSE;
329             }
330             pRC2_set_key(&pKeyContext->rc2, dwKeyLen + dwSaltLen, abKeyValue, dwKeyLen * 8);
331             break;
332 #endif
333 #ifdef HAVE_OPENSSL_DES_H
334         case CALG_3DES:
335             if (!pDES_set_odd_parity || !pDES_set_key_unchecked)
336             {
337                 SetLastError(NTE_PROVIDER_DLL_FAIL);
338                 return FALSE;
339             }
340             pDES_set_odd_parity(&((DES_cblock*)abKeyValue)[2]);
341             pDES_set_key_unchecked(&((DES_cblock*)abKeyValue)[2], &pKeyContext->des[2]);
342
343         case CALG_3DES_112:
344             if (!pDES_set_odd_parity || !pDES_set_key_unchecked)
345             {
346                 SetLastError(NTE_PROVIDER_DLL_FAIL);
347                 return FALSE;
348             }
349             pDES_set_odd_parity(&((DES_cblock*)abKeyValue)[1]);
350             pDES_set_key_unchecked(&((DES_cblock*)abKeyValue)[1], &pKeyContext->des[1]);
351
352         case CALG_DES:
353             if (!pDES_set_odd_parity || !pDES_set_key_unchecked)
354             {
355                 SetLastError(NTE_PROVIDER_DLL_FAIL);
356                 return FALSE;
357             }
358             pDES_set_odd_parity((DES_cblock*)abKeyValue);
359             pDES_set_key_unchecked((DES_cblock*)abKeyValue, &pKeyContext->des[0]);
360             break;
361 #endif  
362         default:
363             SetLastError(NTE_BAD_ALGID);
364             return FALSE;
365     }
366
367     return TRUE;
368 }
369
370 BOOL duplicate_key_impl(ALG_ID aiAlgid, CONST KEY_CONTEXT *pSrcKeyContext,
371                         KEY_CONTEXT *pDestKeyContext) 
372 {
373     switch (aiAlgid) 
374     {
375         case CALG_RC4:
376         case CALG_RC2:
377         case CALG_3DES:
378         case CALG_3DES_112:
379         case CALG_DES:
380             memcpy(pDestKeyContext, pSrcKeyContext, sizeof(KEY_CONTEXT));
381             break;
382 #ifdef HAVE_OPENSSL_RSA_H
383         case CALG_RSA_KEYX:
384         case CALG_RSA_SIGN:
385             if (!pRSAPrivateKey_dup)
386             {
387                 SetLastError(NTE_PROVIDER_DLL_FAIL);
388                 return FALSE;
389             }
390             pDestKeyContext->rsa = pRSAPrivateKey_dup(pSrcKeyContext->rsa);
391             break;
392 #endif  
393         default:
394             SetLastError(NTE_BAD_ALGID);
395             return FALSE;
396     }
397
398     return TRUE;
399 }
400
401 #ifdef HAVE_OPENSSL_RSA_H
402 static inline void reverse_bytes(BYTE *pbData, DWORD dwLen) {
403     BYTE swap;
404     DWORD i;
405
406     for (i=0; i<dwLen/2; i++) {
407         swap = pbData[i];
408         pbData[i] = pbData[dwLen-i-1];
409         pbData[dwLen-i-1] = swap;
410     }
411 }
412 #endif
413
414 BOOL encrypt_block_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext, CONST BYTE *in, BYTE *out, 
415                         DWORD enc) 
416 {
417 #ifdef HAVE_OPENSSL_RSA_H
418     int cLen;
419 #endif
420         
421     switch (aiAlgid) {
422 #ifdef HAVE_OPENSSL_RC2_H
423         case CALG_RC2:
424             if (!pRC2_ecb_encrypt)
425             {
426                 SetLastError(NTE_PROVIDER_DLL_FAIL);
427                 return FALSE;
428             }
429             pRC2_ecb_encrypt(in, out, &pKeyContext->rc2, enc ? RC2_ENCRYPT : RC2_DECRYPT);
430             break;
431 #endif
432 #ifdef HAVE_OPENSSL_DES_H
433         case CALG_DES:
434             if (!pDES_ecb_encrypt)
435             {
436                 SetLastError(NTE_PROVIDER_DLL_FAIL);
437                 return FALSE;
438             }
439             pDES_ecb_encrypt((const_DES_cblock*)in, (DES_cblock*)out, &pKeyContext->des[0], 
440                              enc ? DES_ENCRYPT : DES_DECRYPT);
441             break;
442         
443         case CALG_3DES_112:
444             if (!pDES_ecb3_encrypt)
445             {
446                 SetLastError(NTE_PROVIDER_DLL_FAIL);
447                 return FALSE;
448             }
449             pDES_ecb3_encrypt((const_DES_cblock*)in, (DES_cblock*)out, 
450                               &pKeyContext->des[0], &pKeyContext->des[1], &pKeyContext->des[0], 
451                               enc ? DES_ENCRYPT : DES_DECRYPT);
452             break;
453         
454         case CALG_3DES:
455             if (!pDES_ecb3_encrypt)
456             {
457                 SetLastError(NTE_PROVIDER_DLL_FAIL);
458                 return FALSE;
459             }
460             pDES_ecb3_encrypt((const_DES_cblock*)in, (DES_cblock*)out, 
461                               &pKeyContext->des[0], &pKeyContext->des[1], &pKeyContext->des[2], 
462                               enc ? DES_ENCRYPT : DES_DECRYPT);
463             break;
464 #endif 
465 #ifdef HAVE_OPENSSL_RSA_H
466         case CALG_RSA_KEYX:
467             if (!pBN_num_bits || !pRSA_public_encrypt || !pRSA_private_encrypt)
468             {
469                 SetLastError(NTE_PROVIDER_DLL_FAIL);
470                 return FALSE;
471             }
472             cLen = pBN_num_bits(pKeyContext->rsa->n)/8;
473             if (enc) {
474                 pRSA_public_encrypt(cLen, in, out, pKeyContext->rsa, RSA_NO_PADDING);
475                 reverse_bytes((BYTE*)in, cLen);
476             } else {
477                 reverse_bytes((BYTE*)in, cLen);
478                 pRSA_private_encrypt(cLen, in, out, pKeyContext->rsa, RSA_NO_PADDING);
479             }
480             break;    
481         
482         case CALG_RSA_SIGN:
483             if (!pBN_num_bits || !pRSA_public_encrypt || !pRSA_private_encrypt)
484             {
485                 SetLastError(NTE_PROVIDER_DLL_FAIL);
486                 return FALSE;
487             }
488             cLen = pBN_num_bits(pKeyContext->rsa->n)/8;
489             if (enc) {
490                 pRSA_private_encrypt(cLen, in, out, pKeyContext->rsa, RSA_NO_PADDING);
491                 reverse_bytes((BYTE*)in, cLen);
492             } else {
493                 reverse_bytes((BYTE*)in, cLen);
494                 pRSA_public_encrypt(cLen, in, out, pKeyContext->rsa, RSA_NO_PADDING);
495             }
496             break;
497 #endif
498         default:
499             SetLastError(NTE_BAD_ALGID);
500             return FALSE;
501     }
502
503     return TRUE;
504 }
505
506 BOOL encrypt_stream_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext, BYTE *stream, DWORD dwLen)
507 {
508     switch (aiAlgid) {
509 #ifdef HAVE_OPENSSL_RC4_H
510         case CALG_RC4:
511             if (!pRC4) 
512             {
513                 SetLastError(NTE_PROVIDER_DLL_FAIL);
514                 return FALSE;
515             }
516             pRC4(&pKeyContext->rc4, (unsigned long)dwLen, stream, stream);
517             break;
518 #endif 
519         default:
520             SetLastError(NTE_BAD_ALGID);
521             return FALSE;
522     }
523
524     return TRUE;
525 }
526
527 BOOL gen_rand_impl(BYTE *pbBuffer, DWORD dwLen)
528 {
529     FILE *dev_random;
530
531     /* FIXME: /dev/urandom does not provide random numbers of a sufficient
532      * quality for cryptographic applications. /dev/random is much better,  
533      * but it blocks if the kernel has not yet collected enough entropy for
534      * the request, which will suspend the calling thread for an indefinite
535      * amount of time. */
536     dev_random = fopen("/dev/urandom", "r");
537     if (dev_random) 
538     {
539         if (fread(pbBuffer, (size_t)dwLen, 1, dev_random) == 1)
540         {
541             fclose(dev_random);
542             return TRUE;
543         }
544         fclose(dev_random);
545     }
546     SetLastError(NTE_FAIL);
547     return FALSE;
548 }
549
550 BOOL export_public_key_impl(BYTE *pbDest, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen,DWORD *pdwPubExp)
551 {
552 #ifdef HAVE_OPENSSL_RSA_H
553     if (!pBN_bn2bin || !pBN_get_word)
554     {
555         SetLastError(NTE_PROVIDER_DLL_FAIL);
556         return FALSE;
557     }
558
559     pBN_bn2bin(pKeyContext->rsa->n, pbDest);
560     reverse_bytes(pbDest, dwKeyLen);
561     *pdwPubExp = (DWORD)pBN_get_word(pKeyContext->rsa->e);
562
563     return TRUE;
564 #else
565     SetLastError(NTE_FAIL);
566     return FALSE;
567 #endif
568 }
569
570 BOOL import_public_key_impl(CONST BYTE *pbSrc, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen, 
571                             DWORD dwPubExp)
572 {
573 #ifdef HAVE_OPENSSL_RSA_H
574     BYTE *pbTemp;
575
576     if (!pBN_bin2bn || !pBN_set_word)
577     {
578         SetLastError(NTE_PROVIDER_DLL_FAIL);
579         return FALSE;
580     }
581
582     pbTemp = (BYTE*)HeapAlloc(GetProcessHeap(), 0, dwKeyLen);
583     if (!pbTemp) return FALSE;
584     memcpy(pbTemp, pbSrc, dwKeyLen);
585     reverse_bytes(pbTemp, dwKeyLen);
586     pBN_bin2bn(pbTemp, dwKeyLen, pKeyContext->rsa->n);
587     HeapFree(GetProcessHeap(), 0, pbTemp);
588     
589     pBN_set_word(pKeyContext->rsa->e, (BN_ULONG)dwPubExp);
590
591     return TRUE;
592 #else
593     SetLastError(NTE_FAIL);
594     return FALSE;
595 #endif
596 }
597
598 BOOL export_private_key_impl(BYTE *pbDest, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen, 
599                              DWORD *pdwPubExp)
600 {
601 #ifdef HAVE_OPENSSL_RSA_H
602     if (!pBN_bn2bin || !pBN_get_word)
603     {
604         SetLastError(NTE_PROVIDER_DLL_FAIL);
605         return FALSE;
606     }
607     
608     pBN_bn2bin(pKeyContext->rsa->n, pbDest);
609     reverse_bytes(pbDest, dwKeyLen);
610     pbDest += dwKeyLen;
611     pBN_bn2bin(pKeyContext->rsa->p, pbDest);
612     reverse_bytes(pbDest, (dwKeyLen+1)>>1);
613     pbDest += (dwKeyLen+1)>>1;
614     pBN_bn2bin(pKeyContext->rsa->q, pbDest);
615     reverse_bytes(pbDest, (dwKeyLen+1)>>1);
616     pbDest += (dwKeyLen+1)>>1;
617     pBN_bn2bin(pKeyContext->rsa->dmp1, pbDest);
618     reverse_bytes(pbDest, (dwKeyLen+1)>>1);
619     pbDest += (dwKeyLen+1)>>1;
620     pBN_bn2bin(pKeyContext->rsa->dmq1, pbDest);
621     reverse_bytes(pbDest, (dwKeyLen+1)>>1);
622     pbDest += (dwKeyLen+1)>>1;
623     pBN_bn2bin(pKeyContext->rsa->iqmp, pbDest);
624     reverse_bytes(pbDest, (dwKeyLen+1)>>1);
625     pbDest += (dwKeyLen+1)>>1;
626     pBN_bn2bin(pKeyContext->rsa->d, pbDest);
627     reverse_bytes(pbDest, dwKeyLen);
628     *pdwPubExp = (DWORD)pBN_get_word(pKeyContext->rsa->e);
629
630     return TRUE;
631 #else
632     SetLastError(NTE_FAIL);
633     return FALSE;
634 #endif
635 }
636
637 BOOL import_private_key_impl(CONST BYTE *pbSrc, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen, 
638                              DWORD dwPubExp)
639 {
640 #ifdef HAVE_OPENSSL_RSA_H
641     BYTE *pbTemp, *pbBigNum;
642         
643     if (!pBN_bin2bn || !pBN_set_word)
644     {
645         SetLastError(NTE_PROVIDER_DLL_FAIL);
646         return FALSE;
647     }
648
649     pbTemp = HeapAlloc(GetProcessHeap(), 0, 2*dwKeyLen+5*((dwKeyLen+1)>>1));
650     if (!pbTemp) return FALSE;
651     memcpy(pbTemp, pbSrc, 2*dwKeyLen+5*((dwKeyLen+1)>>1));
652     pbBigNum = pbTemp;
653     
654     reverse_bytes(pbBigNum, dwKeyLen);
655     pBN_bin2bn(pbBigNum, dwKeyLen, pKeyContext->rsa->n);
656     pbBigNum += dwKeyLen;
657     reverse_bytes(pbBigNum, (dwKeyLen+1)>>1);
658     pBN_bin2bn(pbBigNum, (dwKeyLen+1)>>1, pKeyContext->rsa->p);
659     pbBigNum += (dwKeyLen+1)>>1;
660     reverse_bytes(pbBigNum, (dwKeyLen+1)>>1);
661     pBN_bin2bn(pbBigNum, (dwKeyLen+1)>>1, pKeyContext->rsa->q);
662     pbBigNum += (dwKeyLen+1)>>1;
663     reverse_bytes(pbBigNum, (dwKeyLen+1)>>1);
664     pBN_bin2bn(pbBigNum, (dwKeyLen+1)>>1, pKeyContext->rsa->dmp1);
665     pbBigNum += (dwKeyLen+1)>>1;
666     reverse_bytes(pbBigNum, (dwKeyLen+1)>>1);
667     pBN_bin2bn(pbBigNum, (dwKeyLen+1)>>1, pKeyContext->rsa->dmq1);
668     pbBigNum += (dwKeyLen+1)>>1;
669     reverse_bytes(pbBigNum, (dwKeyLen+1)>>1);
670     pBN_bin2bn(pbBigNum, (dwKeyLen+1)>>1, pKeyContext->rsa->iqmp);
671     pbBigNum += (dwKeyLen+1)>>1;
672     reverse_bytes(pbBigNum, dwKeyLen);
673     pBN_bin2bn(pbBigNum, dwKeyLen, pKeyContext->rsa->d);
674     pBN_set_word(pKeyContext->rsa->e, (BN_ULONG)dwPubExp);
675
676     HeapFree(GetProcessHeap(), 0, pbTemp);
677
678     return TRUE;
679 #else
680     SetLastError(NTE_FAIL);
681     return FALSE;
682 #endif
683 }