xref: /reactos/dll/win32/rsaenh/implglue.c (revision c2c66aff)
1 /*
2  * dlls/rsaenh/implglue.c
3  * Glueing the RSAENH specific code to the crypto library
4  *
5  * Copyright (c) 2004, 2005 Michael Jung
6  * Copyright (c) 2007 Vijay Kiran Kamuju
7  *
8  * based on code by Mike McCormack and David Hammerton
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 #define WIN32_NO_STATUS
25 #define WIN32_LEAN_AND_MEAN
26 
27 #include <config.h>
28 
29 //#include "wine/port.h"
30 #include <wine/library.h>
31 
32 //#include "windef.h"
33 #include <wincrypt.h>
34 
35 #include "implglue.h"
36 
37 //#include <stdio.h>
38 
39 /* Function prototypes copied from dlls/advapi32/crypt_md4.c */
40 VOID WINAPI MD4Init( MD4_CTX *ctx );
41 VOID WINAPI MD4Update( MD4_CTX *ctx, const unsigned char *buf, unsigned int len );
42 VOID WINAPI MD4Final( MD4_CTX *ctx );
43 /* Function prototypes copied from dlls/advapi32/crypt_md5.c */
44 VOID WINAPI MD5Init( MD5_CTX *ctx );
45 VOID WINAPI MD5Update( MD5_CTX *ctx, const unsigned char *buf, unsigned int len );
46 VOID WINAPI MD5Final( MD5_CTX *ctx );
47 /* Function prototypes copied from dlls/advapi32/crypt_sha.c */
48 VOID WINAPI A_SHAInit(PSHA_CTX Context);
49 VOID WINAPI A_SHAUpdate(PSHA_CTX Context, const unsigned char *Buffer, UINT BufferSize);
50 VOID WINAPI A_SHAFinal(PSHA_CTX Context, PULONG Result);
51 /* Function prototype copied from dlls/advapi32/crypt.c */
52 BOOL WINAPI SystemFunction036(PVOID pbBuffer, ULONG dwLen);
53 
init_hash_impl(ALG_ID aiAlgid,HASH_CONTEXT * pHashContext)54 BOOL init_hash_impl(ALG_ID aiAlgid, HASH_CONTEXT *pHashContext)
55 {
56     switch (aiAlgid)
57     {
58         case CALG_MD2:
59             md2_init(&pHashContext->md2);
60             break;
61 
62         case CALG_MD4:
63             MD4Init(&pHashContext->md4);
64             break;
65 
66         case CALG_MD5:
67             MD5Init(&pHashContext->md5);
68             break;
69 
70         case CALG_SHA:
71             A_SHAInit(&pHashContext->sha);
72             break;
73 
74         case CALG_SHA_256:
75             SHA256_Init(&pHashContext->sha256);
76             break;
77 
78         case CALG_SHA_384:
79             SHA384_Init(&pHashContext->sha384);
80             break;
81 
82         case CALG_SHA_512:
83             SHA512_Init(&pHashContext->sha512);
84             break;
85     }
86 
87     return TRUE;
88 }
89 
update_hash_impl(ALG_ID aiAlgid,HASH_CONTEXT * pHashContext,const BYTE * pbData,DWORD dwDataLen)90 BOOL update_hash_impl(ALG_ID aiAlgid, HASH_CONTEXT *pHashContext, const BYTE *pbData,
91                       DWORD dwDataLen)
92 {
93     switch (aiAlgid)
94     {
95         case CALG_MD2:
96             md2_process(&pHashContext->md2, pbData, dwDataLen);
97             break;
98 
99         case CALG_MD4:
100             MD4Update(&pHashContext->md4, pbData, dwDataLen);
101             break;
102 
103         case CALG_MD5:
104             MD5Update(&pHashContext->md5, pbData, dwDataLen);
105             break;
106 
107         case CALG_SHA:
108             A_SHAUpdate(&pHashContext->sha, pbData, dwDataLen);
109             break;
110 
111         case CALG_SHA_256:
112             SHA256_Update(&pHashContext->sha256, pbData, dwDataLen);
113             break;
114 
115         case CALG_SHA_384:
116             SHA384_Update(&pHashContext->sha384, pbData, dwDataLen);
117             break;
118 
119         case CALG_SHA_512:
120             SHA512_Update(&pHashContext->sha512, pbData, dwDataLen);
121             break;
122 
123         default:
124             SetLastError(NTE_BAD_ALGID);
125             return FALSE;
126     }
127 
128     return TRUE;
129 }
130 
finalize_hash_impl(ALG_ID aiAlgid,HASH_CONTEXT * pHashContext,BYTE * pbHashValue)131 BOOL finalize_hash_impl(ALG_ID aiAlgid, HASH_CONTEXT *pHashContext, BYTE *pbHashValue)
132 {
133     switch (aiAlgid)
134     {
135         case CALG_MD2:
136             md2_done(&pHashContext->md2, pbHashValue);
137             break;
138 
139         case CALG_MD4:
140             MD4Final(&pHashContext->md4);
141             memcpy(pbHashValue, pHashContext->md4.digest, 16);
142             break;
143 
144         case CALG_MD5:
145             MD5Final(&pHashContext->md5);
146             memcpy(pbHashValue, pHashContext->md5.digest, 16);
147             break;
148 
149         case CALG_SHA:
150             A_SHAFinal(&pHashContext->sha, (PULONG)pbHashValue);
151             break;
152 
153         case CALG_SHA_256:
154             SHA256_Final(pbHashValue, &pHashContext->sha256);
155             break;
156 
157         case CALG_SHA_384:
158             SHA384_Final(pbHashValue, &pHashContext->sha384);
159             break;
160 
161         case CALG_SHA_512:
162             SHA512_Final(pbHashValue, &pHashContext->sha512);
163             break;
164 
165         default:
166             SetLastError(NTE_BAD_ALGID);
167             return FALSE;
168     }
169 
170     return TRUE;
171 }
172 
duplicate_hash_impl(ALG_ID aiAlgid,const HASH_CONTEXT * pSrcHashContext,HASH_CONTEXT * pDestHashContext)173 BOOL duplicate_hash_impl(ALG_ID aiAlgid, const HASH_CONTEXT *pSrcHashContext,
174                          HASH_CONTEXT *pDestHashContext)
175 {
176     *pDestHashContext = *pSrcHashContext;
177 
178     return TRUE;
179 }
180 
new_key_impl(ALG_ID aiAlgid,KEY_CONTEXT * pKeyContext,DWORD dwKeyLen)181 BOOL new_key_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen)
182 {
183     switch (aiAlgid)
184     {
185         case CALG_RSA_KEYX:
186         case CALG_RSA_SIGN:
187             if (rsa_make_key((int)dwKeyLen, 65537, &pKeyContext->rsa) != CRYPT_OK) {
188                 SetLastError(NTE_FAIL);
189                 return FALSE;
190             }
191             return TRUE;
192     }
193 
194     return TRUE;
195 }
196 
free_key_impl(ALG_ID aiAlgid,KEY_CONTEXT * pKeyContext)197 BOOL free_key_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext)
198 {
199     switch (aiAlgid)
200     {
201         case CALG_RSA_KEYX:
202         case CALG_RSA_SIGN:
203             rsa_free(&pKeyContext->rsa);
204     }
205 
206     return TRUE;
207 }
208 
setup_key_impl(ALG_ID aiAlgid,KEY_CONTEXT * pKeyContext,DWORD dwKeyLen,DWORD dwEffectiveKeyLen,DWORD dwSaltLen,BYTE * abKeyValue)209 BOOL setup_key_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen,
210                     DWORD dwEffectiveKeyLen, DWORD dwSaltLen, BYTE *abKeyValue)
211 {
212     switch (aiAlgid)
213     {
214         case CALG_RC4:
215             rc4_start(&pKeyContext->rc4);
216             rc4_add_entropy(abKeyValue, dwKeyLen + dwSaltLen, &pKeyContext->rc4);
217             rc4_ready(&pKeyContext->rc4);
218             break;
219 
220         case CALG_RC2:
221             rc2_setup(abKeyValue, dwKeyLen + dwSaltLen, dwEffectiveKeyLen ?
222                       dwEffectiveKeyLen : dwKeyLen << 3, 0, &pKeyContext->rc2);
223             break;
224 
225         case CALG_3DES:
226             des3_setup(abKeyValue, 24, 0, &pKeyContext->des3);
227             break;
228 
229         case CALG_3DES_112:
230             memcpy(abKeyValue+16, abKeyValue, 8);
231             des3_setup(abKeyValue, 24, 0, &pKeyContext->des3);
232             break;
233 
234         case CALG_DES:
235             des_setup(abKeyValue, 8, 0, &pKeyContext->des);
236             break;
237 
238         case CALG_AES:
239         case CALG_AES_128:
240             aes_setup(abKeyValue, 16, 0, &pKeyContext->aes);
241             break;
242 
243         case CALG_AES_192:
244             aes_setup(abKeyValue, 24, 0, &pKeyContext->aes);
245             break;
246 
247         case CALG_AES_256:
248             aes_setup(abKeyValue, 32, 0, &pKeyContext->aes);
249             break;
250     }
251 
252     return TRUE;
253 }
254 
duplicate_key_impl(ALG_ID aiAlgid,const KEY_CONTEXT * pSrcKeyContext,KEY_CONTEXT * pDestKeyContext)255 BOOL duplicate_key_impl(ALG_ID aiAlgid, const KEY_CONTEXT *pSrcKeyContext,
256                         KEY_CONTEXT *pDestKeyContext)
257 {
258     switch (aiAlgid)
259     {
260         case CALG_RC4:
261         case CALG_RC2:
262         case CALG_3DES:
263         case CALG_3DES_112:
264         case CALG_DES:
265         case CALG_AES:
266         case CALG_AES_128:
267         case CALG_AES_192:
268         case CALG_AES_256:
269             *pDestKeyContext = *pSrcKeyContext;
270             break;
271         case CALG_RSA_KEYX:
272         case CALG_RSA_SIGN:
273             pDestKeyContext->rsa.type = pSrcKeyContext->rsa.type;
274             mp_init_copy(&pDestKeyContext->rsa.e, &pSrcKeyContext->rsa.e);
275             mp_init_copy(&pDestKeyContext->rsa.d, &pSrcKeyContext->rsa.d);
276             mp_init_copy(&pDestKeyContext->rsa.N, &pSrcKeyContext->rsa.N);
277             mp_init_copy(&pDestKeyContext->rsa.p, &pSrcKeyContext->rsa.p);
278             mp_init_copy(&pDestKeyContext->rsa.q, &pSrcKeyContext->rsa.q);
279             mp_init_copy(&pDestKeyContext->rsa.qP, &pSrcKeyContext->rsa.qP);
280             mp_init_copy(&pDestKeyContext->rsa.dP, &pSrcKeyContext->rsa.dP);
281             mp_init_copy(&pDestKeyContext->rsa.dQ, &pSrcKeyContext->rsa.dQ);
282             break;
283 
284         default:
285             SetLastError(NTE_BAD_ALGID);
286             return FALSE;
287     }
288 
289     return TRUE;
290 }
291 
reverse_bytes(BYTE * pbData,DWORD dwLen)292 static inline void reverse_bytes(BYTE *pbData, DWORD dwLen) {
293     BYTE swap;
294     DWORD i;
295 
296     for (i=0; i<dwLen/2; i++) {
297         swap = pbData[i];
298         pbData[i] = pbData[dwLen-i-1];
299         pbData[dwLen-i-1] = swap;
300     }
301 }
302 
encrypt_block_impl(ALG_ID aiAlgid,DWORD dwKeySpec,KEY_CONTEXT * pKeyContext,const BYTE * in,BYTE * out,DWORD enc)303 BOOL encrypt_block_impl(ALG_ID aiAlgid, DWORD dwKeySpec, KEY_CONTEXT *pKeyContext, const BYTE *in,
304                         BYTE *out, DWORD enc)
305 {
306     unsigned long inlen, outlen;
307     BYTE *in_reversed = NULL;
308 
309     switch (aiAlgid) {
310         case CALG_RC2:
311             if (enc) {
312                 rc2_ecb_encrypt(in, out, &pKeyContext->rc2);
313             } else {
314                 rc2_ecb_decrypt(in, out, &pKeyContext->rc2);
315             }
316             break;
317 
318         case CALG_3DES:
319         case CALG_3DES_112:
320             if (enc) {
321                 des3_ecb_encrypt(in, out, &pKeyContext->des3);
322             } else {
323                 des3_ecb_decrypt(in, out, &pKeyContext->des3);
324             }
325             break;
326 
327         case CALG_DES:
328             if (enc) {
329                 des_ecb_encrypt(in, out, &pKeyContext->des);
330             } else {
331                 des_ecb_decrypt(in, out, &pKeyContext->des);
332             }
333             break;
334 
335         case CALG_AES:
336         case CALG_AES_128:
337         case CALG_AES_192:
338         case CALG_AES_256:
339             if (enc) {
340                 aes_ecb_encrypt(in, out, &pKeyContext->aes);
341             } else {
342                 aes_ecb_decrypt(in, out, &pKeyContext->aes);
343             }
344             break;
345 
346         case CALG_RSA_KEYX:
347         case CALG_RSA_SIGN:
348         case CALG_SSL3_SHAMD5:
349             outlen = inlen = (mp_count_bits(&pKeyContext->rsa.N)+7)/8;
350             if (enc) {
351                 if (rsa_exptmod(in, inlen, out, &outlen, dwKeySpec, &pKeyContext->rsa) != CRYPT_OK) {
352                     SetLastError(NTE_FAIL);
353                     return FALSE;
354                 }
355                 reverse_bytes(out, outlen);
356             } else {
357                 in_reversed = HeapAlloc(GetProcessHeap(), 0, inlen);
358                 if (!in_reversed) {
359                     SetLastError(NTE_NO_MEMORY);
360                     return FALSE;
361                 }
362                 memcpy(in_reversed, in, inlen);
363                 reverse_bytes(in_reversed, inlen);
364                 if (rsa_exptmod(in_reversed, inlen, out, &outlen, dwKeySpec, &pKeyContext->rsa) != CRYPT_OK) {
365                     HeapFree(GetProcessHeap(), 0, in_reversed);
366                     SetLastError(NTE_FAIL);
367                     return FALSE;
368                 }
369                 HeapFree(GetProcessHeap(), 0, in_reversed);
370             }
371             break;
372 
373         default:
374             SetLastError(NTE_BAD_ALGID);
375             return FALSE;
376     }
377 
378     return TRUE;
379 }
380 
encrypt_stream_impl(ALG_ID aiAlgid,KEY_CONTEXT * pKeyContext,BYTE * stream,DWORD dwLen)381 BOOL encrypt_stream_impl(ALG_ID aiAlgid, KEY_CONTEXT *pKeyContext, BYTE *stream, DWORD dwLen)
382 {
383     switch (aiAlgid) {
384         case CALG_RC4:
385             rc4_read(stream, dwLen, &pKeyContext->rc4);
386             break;
387 
388         default:
389             SetLastError(NTE_BAD_ALGID);
390             return FALSE;
391     }
392 
393     return TRUE;
394 }
395 
gen_rand_impl(BYTE * pbBuffer,DWORD dwLen)396 BOOL gen_rand_impl(BYTE *pbBuffer, DWORD dwLen)
397 {
398     return SystemFunction036(pbBuffer, dwLen);
399 }
400 
export_public_key_impl(BYTE * pbDest,const KEY_CONTEXT * pKeyContext,DWORD dwKeyLen,DWORD * pdwPubExp)401 BOOL export_public_key_impl(BYTE *pbDest, const KEY_CONTEXT *pKeyContext, DWORD dwKeyLen,DWORD *pdwPubExp)
402 {
403     mp_to_unsigned_bin(&pKeyContext->rsa.N, pbDest);
404     reverse_bytes(pbDest, mp_unsigned_bin_size(&pKeyContext->rsa.N));
405     if (mp_unsigned_bin_size(&pKeyContext->rsa.N) < dwKeyLen)
406         memset(pbDest + mp_unsigned_bin_size(&pKeyContext->rsa.N), 0,
407                dwKeyLen - mp_unsigned_bin_size(&pKeyContext->rsa.N));
408     *pdwPubExp = (DWORD)mp_get_int(&pKeyContext->rsa.e);
409     return TRUE;
410 }
411 
import_public_key_impl(const BYTE * pbSrc,KEY_CONTEXT * pKeyContext,DWORD dwKeyLen,DWORD dwPubExp)412 BOOL import_public_key_impl(const BYTE *pbSrc, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen,
413                             DWORD dwPubExp)
414 {
415     BYTE *pbTemp;
416 
417     if (mp_init_multi(&pKeyContext->rsa.e, &pKeyContext->rsa.d, &pKeyContext->rsa.N,
418                       &pKeyContext->rsa.dQ,&pKeyContext->rsa.dP,&pKeyContext->rsa.qP,
419                       &pKeyContext->rsa.p, &pKeyContext->rsa.q, NULL) != MP_OKAY)
420     {
421         SetLastError(NTE_FAIL);
422         return FALSE;
423     }
424 
425     pbTemp = HeapAlloc(GetProcessHeap(), 0, dwKeyLen);
426     if (!pbTemp) return FALSE;
427     memcpy(pbTemp, pbSrc, dwKeyLen);
428 
429     pKeyContext->rsa.type = PK_PUBLIC;
430     reverse_bytes(pbTemp, dwKeyLen);
431     mp_read_unsigned_bin(&pKeyContext->rsa.N, pbTemp, dwKeyLen);
432     HeapFree(GetProcessHeap(), 0, pbTemp);
433     mp_set_int(&pKeyContext->rsa.e, dwPubExp);
434 
435     return TRUE;
436 }
437 
export_private_key_impl(BYTE * pbDest,const KEY_CONTEXT * pKeyContext,DWORD dwKeyLen,DWORD * pdwPubExp)438 BOOL export_private_key_impl(BYTE *pbDest, const KEY_CONTEXT *pKeyContext, DWORD dwKeyLen,
439                              DWORD *pdwPubExp)
440 {
441     mp_to_unsigned_bin(&pKeyContext->rsa.N, pbDest);
442     reverse_bytes(pbDest, mp_unsigned_bin_size(&pKeyContext->rsa.N));
443     if (mp_unsigned_bin_size(&pKeyContext->rsa.N) < dwKeyLen)
444         memset(pbDest + mp_unsigned_bin_size(&pKeyContext->rsa.N), 0,
445                dwKeyLen - mp_unsigned_bin_size(&pKeyContext->rsa.N));
446     pbDest += dwKeyLen;
447     mp_to_unsigned_bin(&pKeyContext->rsa.p, pbDest);
448     reverse_bytes(pbDest, mp_unsigned_bin_size(&pKeyContext->rsa.p));
449     if (mp_unsigned_bin_size(&pKeyContext->rsa.p) < (dwKeyLen+1)>>1)
450         memset(pbDest + mp_unsigned_bin_size(&pKeyContext->rsa.p), 0,
451                ((dwKeyLen+1)>>1) - mp_unsigned_bin_size(&pKeyContext->rsa.p));
452     pbDest += (dwKeyLen+1)>>1;
453     mp_to_unsigned_bin(&pKeyContext->rsa.q, pbDest);
454     reverse_bytes(pbDest, mp_unsigned_bin_size(&pKeyContext->rsa.q));
455     if (mp_unsigned_bin_size(&pKeyContext->rsa.q) < (dwKeyLen+1)>>1)
456         memset(pbDest + mp_unsigned_bin_size(&pKeyContext->rsa.q), 0,
457                ((dwKeyLen+1)>>1) - mp_unsigned_bin_size(&pKeyContext->rsa.q));
458     pbDest += (dwKeyLen+1)>>1;
459     mp_to_unsigned_bin(&pKeyContext->rsa.dP, pbDest);
460     reverse_bytes(pbDest, mp_unsigned_bin_size(&pKeyContext->rsa.dP));
461     if (mp_unsigned_bin_size(&pKeyContext->rsa.dP) < (dwKeyLen+1)>>1)
462         memset(pbDest + mp_unsigned_bin_size(&pKeyContext->rsa.dP), 0,
463                ((dwKeyLen+1)>>1) - mp_unsigned_bin_size(&pKeyContext->rsa.dP));
464     pbDest += (dwKeyLen+1)>>1;
465     mp_to_unsigned_bin(&pKeyContext->rsa.dQ, pbDest);
466     reverse_bytes(pbDest, mp_unsigned_bin_size(&pKeyContext->rsa.dQ));
467     if (mp_unsigned_bin_size(&pKeyContext->rsa.dQ) < (dwKeyLen+1)>>1)
468         memset(pbDest + mp_unsigned_bin_size(&pKeyContext->rsa.dQ), 0,
469                ((dwKeyLen+1)>>1) - mp_unsigned_bin_size(&pKeyContext->rsa.dQ));
470     pbDest += (dwKeyLen+1)>>1;
471     mp_to_unsigned_bin(&pKeyContext->rsa.qP, pbDest);
472     reverse_bytes(pbDest, mp_unsigned_bin_size(&pKeyContext->rsa.qP));
473     if (mp_unsigned_bin_size(&pKeyContext->rsa.qP) < (dwKeyLen+1)>>1)
474         memset(pbDest + mp_unsigned_bin_size(&pKeyContext->rsa.qP), 0,
475                ((dwKeyLen+1)>>1) - mp_unsigned_bin_size(&pKeyContext->rsa.qP));
476     pbDest += (dwKeyLen+1)>>1;
477     mp_to_unsigned_bin(&pKeyContext->rsa.d, pbDest);
478     reverse_bytes(pbDest, mp_unsigned_bin_size(&pKeyContext->rsa.d));
479     if (mp_unsigned_bin_size(&pKeyContext->rsa.d) < dwKeyLen)
480         memset(pbDest + mp_unsigned_bin_size(&pKeyContext->rsa.d), 0,
481                dwKeyLen - mp_unsigned_bin_size(&pKeyContext->rsa.d));
482     *pdwPubExp = (DWORD)mp_get_int(&pKeyContext->rsa.e);
483 
484     return TRUE;
485 }
486 
import_private_key_impl(const BYTE * pbSrc,KEY_CONTEXT * pKeyContext,DWORD dwKeyLen,DWORD dwDataLen,DWORD dwPubExp)487 BOOL import_private_key_impl(const BYTE *pbSrc, KEY_CONTEXT *pKeyContext, DWORD dwKeyLen,
488                              DWORD dwDataLen, DWORD dwPubExp)
489 {
490     BYTE *pbTemp, *pbBigNum;
491 
492     if (mp_init_multi(&pKeyContext->rsa.e, &pKeyContext->rsa.d, &pKeyContext->rsa.N,
493                       &pKeyContext->rsa.dQ,&pKeyContext->rsa.dP,&pKeyContext->rsa.qP,
494                       &pKeyContext->rsa.p, &pKeyContext->rsa.q, NULL) != MP_OKAY)
495     {
496         SetLastError(NTE_FAIL);
497         return FALSE;
498     }
499 
500     pbTemp = HeapAlloc(GetProcessHeap(), 0, 2*dwKeyLen+5*((dwKeyLen+1)>>1));
501     if (!pbTemp) return FALSE;
502     memcpy(pbTemp, pbSrc, min(dwDataLen, 2*dwKeyLen+5*((dwKeyLen+1)>>1)));
503     pbBigNum = pbTemp;
504 
505     pKeyContext->rsa.type = PK_PRIVATE;
506     reverse_bytes(pbBigNum, dwKeyLen);
507     mp_read_unsigned_bin(&pKeyContext->rsa.N, pbBigNum, dwKeyLen);
508     pbBigNum += dwKeyLen;
509     reverse_bytes(pbBigNum, (dwKeyLen+1)>>1);
510     mp_read_unsigned_bin(&pKeyContext->rsa.p, pbBigNum, (dwKeyLen+1)>>1);
511     pbBigNum += (dwKeyLen+1)>>1;
512     reverse_bytes(pbBigNum, (dwKeyLen+1)>>1);
513     mp_read_unsigned_bin(&pKeyContext->rsa.q, pbBigNum, (dwKeyLen+1)>>1);
514     pbBigNum += (dwKeyLen+1)>>1;
515     reverse_bytes(pbBigNum, (dwKeyLen+1)>>1);
516     mp_read_unsigned_bin(&pKeyContext->rsa.dP, pbBigNum, (dwKeyLen+1)>>1);
517     pbBigNum += (dwKeyLen+1)>>1;
518     reverse_bytes(pbBigNum, (dwKeyLen+1)>>1);
519     mp_read_unsigned_bin(&pKeyContext->rsa.dQ, pbBigNum, (dwKeyLen+1)>>1);
520     pbBigNum += (dwKeyLen+1)>>1;
521     reverse_bytes(pbBigNum, (dwKeyLen+1)>>1);
522     mp_read_unsigned_bin(&pKeyContext->rsa.qP, pbBigNum, (dwKeyLen+1)>>1);
523     pbBigNum += (dwKeyLen+1)>>1;
524     /* The size of the private exponent d is inferred from the remaining
525      * data length.
526      */
527     dwKeyLen = min(dwKeyLen, dwDataLen - (pbBigNum - pbTemp));
528     reverse_bytes(pbBigNum, dwKeyLen);
529     mp_read_unsigned_bin(&pKeyContext->rsa.d, pbBigNum, dwKeyLen);
530     mp_set_int(&pKeyContext->rsa.e, dwPubExp);
531 
532     HeapFree(GetProcessHeap(), 0, pbTemp);
533     return TRUE;
534 }
535