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