[MSTSC] Switch most MSTSC from internal "ssl" functions to CryptoAPI and implement...
[reactos.git] / reactos / base / applications / mstsc / ssl_calls.c
1 /*
2 This program is free software; you can redistribute it and/or modify
3 it under the terms of the GNU General Public License as published by
4 the Free Software Foundation; either version 2 of the License, or
5 (at your option) any later version.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11
12 You should have received a copy of the GNU General Public License along
13 with this program; if not, write to the Free Software Foundation, Inc.,
14 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
15
16 xrdp: A Remote Desktop Protocol server.
17 Copyright (C) Jay Sorg 2004-2005
18
19 ssl calls
20
21 */
22
23 #include "precomp.h"
24
25 /*****************************************************************************/
26 static void * g_malloc(int size, int zero)
27 {
28 void * p;
29
30 p = CryptMemAlloc(size);
31 if (zero)
32 {
33 memset(p, 0, size);
34 }
35 return p;
36 }
37
38 /*****************************************************************************/
39 static void g_free(void * in)
40 {
41 CryptMemFree(in);
42 }
43
44 struct rc4_state
45 {
46 HCRYPTPROV hCryptProv;
47 HCRYPTKEY hKey;
48 };
49 /*****************************************************************************/
50 void*
51 rdssl_rc4_info_create(void)
52 {
53 struct rc4_state *info = g_malloc(sizeof(struct rc4_state), 1);
54 BOOL ret;
55 DWORD dwErr;
56 if (!info)
57 {
58 error("rdssl_rc4_info_create no memory\n");
59 return NULL;
60 }
61 ret = CryptAcquireContext(&info->hCryptProv,
62 NULL,
63 MS_ENHANCED_PROV,
64 PROV_RSA_FULL,
65 0);
66 if (!ret)
67 {
68 dwErr = GetLastError();
69 error("CryptAcquireContext failed with %lx\n", dwErr);
70 g_free(info);
71 return NULL;
72 }
73 return info;
74 }
75
76 /*****************************************************************************/
77 void
78 rdssl_rc4_info_delete(void* rc4_info)
79 {
80 struct rc4_state *info = rc4_info;
81 BOOL ret = TRUE;
82 DWORD dwErr;
83 if (!info)
84 {
85 //error("rdssl_rc4_info_delete rc4_info is null\n");
86 return;
87 }
88 if (info->hKey)
89 {
90 ret = CryptDestroyKey(info->hKey);
91 if (!ret)
92 {
93 dwErr = GetLastError();
94 error("CryptDestroyKey failed with %lx\n", dwErr);
95 }
96 }
97 if (info->hCryptProv)
98 {
99 ret = CryptReleaseContext(info->hCryptProv, 0);
100 if (!ret)
101 {
102 dwErr = GetLastError();
103 error("CryptReleaseContext failed with %lx\n", dwErr);
104 }
105 }
106 g_free(rc4_info);
107 }
108
109 /*****************************************************************************/
110 void
111 rdssl_rc4_set_key(void* rc4_info, char* key, int len)
112 {
113 struct rc4_state *info = rc4_info;
114 BOOL ret;
115 DWORD dwErr;
116 BYTE * blob;
117 PUBLICKEYSTRUC *desc;
118 DWORD * keySize;
119 BYTE * keyBuf;
120 if (!rc4_info || !key || !len || !info->hCryptProv)
121 {
122 error("rdssl_rc4_set_key %p %p %d\n", rc4_info, key, len);
123 return;
124 }
125 blob = g_malloc(sizeof(PUBLICKEYSTRUC) + sizeof(DWORD) + len, 0);
126 if (!blob)
127 {
128 error("rdssl_rc4_set_key no memory\n");
129 return;
130 }
131 desc = (PUBLICKEYSTRUC *)blob;
132 keySize = (DWORD *)(blob + sizeof(PUBLICKEYSTRUC));
133 keyBuf = blob + sizeof(PUBLICKEYSTRUC) + sizeof(DWORD);
134 desc->aiKeyAlg = CALG_RC4;
135 desc->bType = PLAINTEXTKEYBLOB;
136 desc->bVersion = CUR_BLOB_VERSION;
137 desc->reserved = 0;
138 *keySize = len;
139 memcpy(keyBuf, key, len);
140 if (info->hKey)
141 {
142 CryptDestroyKey(info->hKey);
143 info->hKey = 0;
144 }
145 ret = CryptImportKey(info->hCryptProv,
146 blob,
147 sizeof(PUBLICKEYSTRUC) + sizeof(DWORD) + len,
148 0,
149 CRYPT_EXPORTABLE,
150 &info->hKey);
151 g_free(blob);
152 if (!ret)
153 {
154 dwErr = GetLastError();
155 error("CryptImportKey failed with %lx\n", dwErr);
156 }
157 }
158
159 /*****************************************************************************/
160 void
161 rdssl_rc4_crypt(void* rc4_info, char* in_data, char* out_data, int len)
162 {
163 struct rc4_state *info = rc4_info;
164 BOOL ret;
165 DWORD dwErr;
166 BYTE * intermediate_data;
167 DWORD dwLen = len;
168 if (!rc4_info || !in_data || !out_data || !len || !info->hKey)
169 {
170 error("rdssl_rc4_crypt %p %p %p %d\n", rc4_info, in_data, out_data, len);
171 return;
172 }
173 intermediate_data = g_malloc(len, 0);
174 if (!intermediate_data)
175 {
176 error("rdssl_rc4_set_key no memory\n");
177 return;
178 }
179 memcpy(intermediate_data, in_data, len);
180 ret = CryptEncrypt(info->hKey,
181 0,
182 FALSE,
183 0,
184 intermediate_data,
185 &dwLen,
186 dwLen);
187 if (!ret)
188 {
189 dwErr = GetLastError();
190 g_free(intermediate_data);
191 error("CryptEncrypt failed with %lx\n", dwErr);
192 return;
193 }
194 memcpy(out_data, intermediate_data, len);
195 g_free(intermediate_data);
196 }
197
198 struct hash_context
199 {
200 HCRYPTPROV hCryptProv;
201 HCRYPTKEY hHash;
202 };
203
204 /*****************************************************************************/
205 void*
206 rdssl_hash_info_create(ALG_ID id)
207 {
208 struct hash_context *info = g_malloc(sizeof(struct hash_context), 1);
209 BOOL ret;
210 DWORD dwErr;
211 if (!info)
212 {
213 error("rdssl_hash_info_create %d no memory\n", id);
214 return NULL;
215 }
216 ret = CryptAcquireContext(&info->hCryptProv,
217 NULL,
218 MS_ENHANCED_PROV,
219 PROV_RSA_FULL,
220 0);
221 if (!ret)
222 {
223 dwErr = GetLastError();
224 g_free(info);
225 error("CryptAcquireContext failed with %lx\n", dwErr);
226 return NULL;
227 }
228 ret = CryptCreateHash(info->hCryptProv,
229 id,
230 0,
231 0,
232 &info->hHash);
233 if (!ret)
234 {
235 dwErr = GetLastError();
236 CryptReleaseContext(info->hCryptProv, 0);
237 g_free(info);
238 error("CryptCreateHash failed with %lx\n", dwErr);
239 return NULL;
240 }
241 return info;
242 }
243
244 /*****************************************************************************/
245 void
246 rdssl_hash_info_delete(void* hash_info)
247 {
248 struct hash_context *info = hash_info;
249 if (!info)
250 {
251 //error("ssl_hash_info_delete hash_info is null\n");
252 return;
253 }
254 if (info->hHash)
255 {
256 CryptDestroyHash(info->hHash);
257 }
258 if (info->hCryptProv)
259 {
260 CryptReleaseContext(info->hCryptProv, 0);
261 }
262 g_free(hash_info);
263 }
264
265 /*****************************************************************************/
266 void
267 rdssl_hash_clear(void* hash_info, ALG_ID id)
268 {
269 struct hash_context *info = hash_info;
270 BOOL ret;
271 DWORD dwErr;
272 if (!info || !info->hHash || !info->hCryptProv)
273 {
274 error("rdssl_hash_clear %p\n", info);
275 return;
276 }
277 ret = CryptDestroyHash(info->hHash);
278 if (!ret)
279 {
280 dwErr = GetLastError();
281 error("CryptDestroyHash failed with %lx\n", dwErr);
282 return;
283 }
284 ret = CryptCreateHash(info->hCryptProv,
285 id,
286 0,
287 0,
288 &info->hHash);
289 if (!ret)
290 {
291 dwErr = GetLastError();
292 error("CryptCreateHash failed with %lx\n", dwErr);
293 }
294 }
295
296 void
297 rdssl_hash_transform(void* hash_info, char* data, int len)
298 {
299 struct hash_context *info = hash_info;
300 BOOL ret;
301 DWORD dwErr;
302 if (!info || !info->hHash || !info->hCryptProv || !data || !len)
303 {
304 error("rdssl_hash_transform %p %p %d\n", hash_info, data, len);
305 return;
306 }
307 ret = CryptHashData(info->hHash,
308 (BYTE *)data,
309 len,
310 0);
311 if (!ret)
312 {
313 dwErr = GetLastError();
314 error("CryptHashData failed with %lx\n", dwErr);
315 }
316 }
317
318 /*****************************************************************************/
319 void
320 rdssl_hash_complete(void* hash_info, char* data)
321 {
322 struct hash_context *info = hash_info;
323 BOOL ret;
324 DWORD dwErr, dwDataLen;
325 if (!info || !info->hHash || !info->hCryptProv || !data)
326 {
327 error("rdssl_hash_complete %p %p\n", hash_info, data);
328 return;
329 }
330 ret = CryptGetHashParam(info->hHash,
331 HP_HASHVAL,
332 NULL,
333 &dwDataLen,
334 0);
335 if (!ret)
336 {
337 dwErr = GetLastError();
338 error("CryptGetHashParam failed with %lx\n", dwErr);
339 return;
340 }
341 ret = CryptGetHashParam(info->hHash,
342 HP_HASHVAL,
343 (BYTE *)data,
344 &dwDataLen,
345 0);
346 if (!ret)
347 {
348 dwErr = GetLastError();
349 error("CryptGetHashParam failed with %lx\n", dwErr);
350 }
351 }
352
353 /*****************************************************************************/
354 void*
355 rdssl_sha1_info_create(void)
356 {
357 return rdssl_hash_info_create(CALG_SHA1);
358 }
359
360 /*****************************************************************************/
361 void
362 rdssl_sha1_info_delete(void* sha1_info)
363 {
364 rdssl_hash_info_delete(sha1_info);
365 }
366
367 /*****************************************************************************/
368 void
369 rdssl_sha1_clear(void* sha1_info)
370 {
371 rdssl_hash_clear(sha1_info, CALG_SHA1);
372 }
373
374 /*****************************************************************************/
375 void
376 rdssl_sha1_transform(void* sha1_info, char* data, int len)
377 {
378 rdssl_hash_transform(sha1_info, data, len);
379 }
380
381 /*****************************************************************************/
382 void
383 rdssl_sha1_complete(void* sha1_info, char* data)
384 {
385 rdssl_hash_complete(sha1_info, data);
386 }
387
388 /*****************************************************************************/
389 void*
390 rdssl_md5_info_create(void)
391 {
392 return rdssl_hash_info_create(CALG_MD5);
393 }
394
395 /*****************************************************************************/
396 void
397 rdssl_md5_info_delete(void* md5_info)
398 {
399 rdssl_hash_info_delete(md5_info);
400 }
401
402 /*****************************************************************************/
403 void
404 rdssl_md5_clear(void* md5_info)
405 {
406 rdssl_hash_clear(md5_info, CALG_MD5);
407 }
408
409 /*****************************************************************************/
410 void
411 rdssl_md5_transform(void* md5_info, char* data, int len)
412 {
413 rdssl_hash_transform(md5_info, data, len);
414 }
415
416 /*****************************************************************************/
417 void
418 rdssl_md5_complete(void* md5_info, char* data)
419 {
420 rdssl_hash_complete(md5_info, data);
421 }
422
423 /*****************************************************************************/
424 void
425 rdssl_hmac_md5(char* key, int keylen, char* data, int len, char* output)
426 {
427 HCRYPTPROV hCryptProv;
428 HCRYPTKEY hKey;
429 HCRYPTKEY hHash;
430 BOOL ret;
431 DWORD dwErr, dwDataLen;
432 HMAC_INFO info;
433 BYTE * blob;
434 PUBLICKEYSTRUC *desc;
435 DWORD * keySize;
436 BYTE * keyBuf;
437 BYTE sum[16];
438
439 if (!key || !keylen || !data || !len ||!output)
440 {
441 error("rdssl_hmac_md5 %p %d %p %d %p\n", key, keylen, data, len, output);
442 return;
443 }
444 blob = g_malloc(sizeof(PUBLICKEYSTRUC) + sizeof(DWORD) + keylen, 0);
445 desc = (PUBLICKEYSTRUC *)blob;
446 keySize = (DWORD *)(blob + sizeof(PUBLICKEYSTRUC));
447 keyBuf = blob + sizeof(PUBLICKEYSTRUC) + sizeof(DWORD);
448 if (!blob)
449 {
450 error("rdssl_hmac_md5 %d no memory\n");
451 return;
452 }
453 ret = CryptAcquireContext(&hCryptProv,
454 NULL,
455 MS_ENHANCED_PROV,
456 PROV_RSA_FULL,
457 0);
458 if (!ret)
459 {
460 dwErr = GetLastError();
461 g_free(blob);
462 error("CryptAcquireContext failed with %lx\n", dwErr);
463 return;
464 }
465 desc->aiKeyAlg = CALG_RC4;
466 desc->bType = PLAINTEXTKEYBLOB;
467 desc->bVersion = CUR_BLOB_VERSION;
468 desc->reserved = 0;
469 if (keylen > 64)
470 {
471 HCRYPTKEY hHash;
472 ret = CryptCreateHash(hCryptProv,
473 CALG_MD5,
474 0,
475 0,
476 &hHash);
477 if (!ret)
478 {
479 dwErr = GetLastError();
480 g_free(blob);
481 error("CryptCreateHash failed with %lx\n", dwErr);
482 return;
483 }
484 ret = CryptHashData(hHash,
485 (BYTE *)key,
486 keylen,
487 0);
488 if (!ret)
489 {
490 dwErr = GetLastError();
491 g_free(blob);
492 error("CryptHashData failed with %lx\n", dwErr);
493 return;
494 }
495 ret = CryptGetHashParam(hHash,
496 HP_HASHVAL,
497 NULL,
498 &dwDataLen,
499 0);
500 if (!ret)
501 {
502 dwErr = GetLastError();
503 g_free(blob);
504 error("CryptGetHashParam failed with %lx\n", dwErr);
505 return;
506 }
507 ret = CryptGetHashParam(hHash,
508 HP_HASHVAL,
509 sum,
510 &dwDataLen,
511 0);
512 if (!ret)
513 {
514 dwErr = GetLastError();
515 g_free(blob);
516 error("CryptGetHashParam failed with %lx\n", dwErr);
517 return;
518 }
519 keylen = dwDataLen;
520 key = (char *)sum;
521 }
522 *keySize = keylen;
523 memcpy(keyBuf, key, keylen);
524 ret = CryptImportKey(hCryptProv,
525 blob,
526 sizeof(PUBLICKEYSTRUC) + sizeof(DWORD) + keylen,
527 0,
528 CRYPT_EXPORTABLE,
529 &hKey);
530 g_free(blob);
531 if (!ret)
532 {
533 dwErr = GetLastError();
534 error("CryptImportKey failed with %lx\n", dwErr);
535 return;
536 }
537 ret = CryptCreateHash(hCryptProv,
538 CALG_HMAC,
539 hKey,
540 0,
541 &hHash);
542 if (!ret)
543 {
544 dwErr = GetLastError();
545 error("CryptCreateHash failed with %lx\n", dwErr);
546 return;
547 }
548 info.HashAlgid = CALG_MD5;
549 info.cbInnerString = 0;
550 info.cbOuterString = 0;
551 ret = CryptSetHashParam(hHash,
552 HP_HMAC_INFO,
553 (BYTE *)&info,
554 0);
555 if (!ret)
556 {
557 dwErr = GetLastError();
558 error("CryptSetHashParam failed with %lx\n", dwErr);
559 return;
560 }
561 ret = CryptHashData(hHash,
562 (BYTE *)data,
563 len,
564 0);
565 if (!ret)
566 {
567 dwErr = GetLastError();
568 error("CryptHashData failed with %lx\n", dwErr);
569 return;
570 }
571 ret = CryptGetHashParam(hHash,
572 HP_HASHVAL,
573 NULL,
574 &dwDataLen,
575 0);
576 if (!ret)
577 {
578 dwErr = GetLastError();
579 error("CryptGetHashParam failed with %lx\n", dwErr);
580 return;
581 }
582 ret = CryptGetHashParam(hHash,
583 HP_HASHVAL,
584 (BYTE *)output,
585 &dwDataLen,
586 0);
587 if (!ret)
588 {
589 dwErr = GetLastError();
590 error("CryptGetHashParam failed with %lx\n", dwErr);
591 return;
592 }
593 CryptDestroyHash(hHash);
594 ret = CryptReleaseContext(hCryptProv, 0);
595 }
596
597 /*****************************************************************************/
598 /*****************************************************************************/
599 /* big number stuff */
600 /******************* SHORT COPYRIGHT NOTICE*************************
601 This source code is part of the BigDigits multiple-precision
602 arithmetic library Version 1.0 originally written by David Ireland,
603 copyright (c) 2001 D.I. Management Services Pty Limited, all rights
604 reserved. It is provided "as is" with no warranties. You may use
605 this software under the terms of the full copyright notice
606 "bigdigitsCopyright.txt" that should have been included with
607 this library. To obtain a copy send an email to
608 <code@di-mgt.com.au> or visit <www.di-mgt.com.au/crypto.html>.
609 This notice must be retained in any copy.
610 ****************** END OF COPYRIGHT NOTICE*************************/
611 /************************* COPYRIGHT NOTICE*************************
612 This source code is part of the BigDigits multiple-precision
613 arithmetic library Version 1.0 originally written by David Ireland,
614 copyright (c) 2001 D.I. Management Services Pty Limited, all rights
615 reserved. You are permitted to use compiled versions of this code as
616 part of your own executable files and to distribute unlimited copies
617 of such executable files for any purposes including commercial ones
618 provided you keep the copyright notices intact in the source code
619 and that you ensure that the following characters remain in any
620 object or executable files you distribute:
621
622 "Contains multiple-precision arithmetic code originally written
623 by David Ireland, copyright (c) 2001 by D.I. Management Services
624 Pty Limited <www.di-mgt.com.au>, and is used with permission."
625
626 David Ireland and DI Management Services Pty Limited make no
627 representations concerning either the merchantability of this
628 software or the suitability of this software for any particular
629 purpose. It is provided "as is" without express or implied warranty
630 of any kind.
631
632 Please forward any comments and bug reports to <code@di-mgt.com.au>.
633 The latest version of the source code can be downloaded from
634 www.di-mgt.com.au/crypto.html.
635 ****************** END OF COPYRIGHT NOTICE*************************/
636
637 typedef unsigned int DIGIT_T;
638 #define HIBITMASK 0x80000000
639 #define MAX_DIG_LEN 51
640 #define MAX_DIGIT 0xffffffff
641 #define BITS_PER_DIGIT 32
642 #define MAX_HALF_DIGIT 0xffff
643 #define B_J (MAX_HALF_DIGIT + 1)
644 #define LOHALF(x) ((DIGIT_T)((x) & 0xffff))
645 #define HIHALF(x) ((DIGIT_T)((x) >> 16 & 0xffff))
646 #define TOHIGH(x) ((DIGIT_T)((x) << 16))
647
648 #define mpNEXTBITMASK(mask, n) \
649 { \
650 if (mask == 1) \
651 { \
652 mask = HIBITMASK; \
653 n--; \
654 } \
655 else \
656 { \
657 mask >>= 1; \
658 } \
659 }
660
661 /*****************************************************************************/
662 static DIGIT_T
663 mpAdd(DIGIT_T* w, DIGIT_T* u, DIGIT_T* v, unsigned int ndigits)
664 {
665 /* Calculates w = u + v
666 where w, u, v are multiprecision integers of ndigits each
667 Returns carry if overflow. Carry = 0 or 1.
668
669 Ref: Knuth Vol 2 Ch 4.3.1 p 266 Algorithm A. */
670 DIGIT_T k;
671 unsigned int j;
672
673 /* Step A1. Initialise */
674 k = 0;
675 for (j = 0; j < ndigits; j++)
676 {
677 /* Step A2. Add digits w_j = (u_j + v_j + k)
678 Set k = 1 if carry (overflow) occurs */
679 w[j] = u[j] + k;
680 if (w[j] < k)
681 {
682 k = 1;
683 }
684 else
685 {
686 k = 0;
687 }
688 w[j] += v[j];
689 if (w[j] < v[j])
690 {
691 k++;
692 }
693 } /* Step A3. Loop on j */
694 return k; /* w_n = k */
695 }
696
697 /*****************************************************************************/
698 static void
699 mpSetDigit(DIGIT_T* a, DIGIT_T d, unsigned int ndigits)
700 { /* Sets a = d where d is a single digit */
701 unsigned int i;
702
703 for (i = 1; i < ndigits; i++)
704 {
705 a[i] = 0;
706 }
707 a[0] = d;
708 }
709
710 /*****************************************************************************/
711 static int
712 mpCompare(DIGIT_T* a, DIGIT_T* b, unsigned int ndigits)
713 {
714 /* Returns sign of (a - b) */
715 if (ndigits == 0)
716 {
717 return 0;
718 }
719 while (ndigits--)
720 {
721 if (a[ndigits] > b[ndigits])
722 {
723 return 1; /* GT */
724 }
725 if (a[ndigits] < b[ndigits])
726 {
727 return -1; /* LT */
728 }
729 }
730 return 0; /* EQ */
731 }
732
733 /*****************************************************************************/
734 static void
735 mpSetZero(DIGIT_T* a, unsigned int ndigits)
736 { /* Sets a = 0 */
737 unsigned int i;
738
739 for (i = 0; i < ndigits; i++)
740 {
741 a[i] = 0;
742 }
743 }
744
745 /*****************************************************************************/
746 static void
747 mpSetEqual(DIGIT_T* a, DIGIT_T* b, unsigned int ndigits)
748 { /* Sets a = b */
749 unsigned int i;
750
751 for (i = 0; i < ndigits; i++)
752 {
753 a[i] = b[i];
754 }
755 }
756
757 /*****************************************************************************/
758 static unsigned int
759 mpSizeof(DIGIT_T* a, unsigned int ndigits)
760 { /* Returns size of significant digits in a */
761 while (ndigits--)
762 {
763 if (a[ndigits] != 0)
764 {
765 return (++ndigits);
766 }
767 }
768 return 0;
769 }
770
771 /*****************************************************************************/
772 static DIGIT_T
773 mpShiftLeft(DIGIT_T* a, DIGIT_T* b, unsigned int x, unsigned int ndigits)
774 { /* Computes a = b << x */
775 unsigned int i;
776 unsigned int y;
777 DIGIT_T mask;
778 DIGIT_T carry;
779 DIGIT_T nextcarry;
780
781 /* Check input - NB unspecified result */
782 if (x >= BITS_PER_DIGIT)
783 {
784 return 0;
785 }
786 /* Construct mask */
787 mask = HIBITMASK;
788 for (i = 1; i < x; i++)
789 {
790 mask = (mask >> 1) | mask;
791 }
792 if (x == 0)
793 {
794 mask = 0x0;
795 }
796 y = BITS_PER_DIGIT - x;
797 carry = 0;
798 for (i = 0; i < ndigits; i++)
799 {
800 nextcarry = (b[i] & mask) >> y;
801 a[i] = b[i] << x | carry;
802 carry = nextcarry;
803 }
804 return carry;
805 }
806
807 /*****************************************************************************/
808 static DIGIT_T
809 mpShiftRight(DIGIT_T* a, DIGIT_T* b, unsigned int x, unsigned int ndigits)
810 { /* Computes a = b >> x */
811 unsigned int i;
812 unsigned int y;
813 DIGIT_T mask;
814 DIGIT_T carry;
815 DIGIT_T nextcarry;
816
817 /* Check input - NB unspecified result */
818 if (x >= BITS_PER_DIGIT)
819 {
820 return 0;
821 }
822 /* Construct mask */
823 mask = 0x1;
824 for (i = 1; i < x; i++)
825 {
826 mask = (mask << 1) | mask;
827 }
828 if (x == 0)
829 {
830 mask = 0x0;
831 }
832 y = BITS_PER_DIGIT - x;
833 carry = 0;
834 i = ndigits;
835 while (i--)
836 {
837 nextcarry = (b[i] & mask) << y;
838 a[i] = b[i] >> x | carry;
839 carry = nextcarry;
840 }
841 return carry;
842 }
843
844 /*****************************************************************************/
845 static void
846 spMultSub(DIGIT_T* uu, DIGIT_T qhat, DIGIT_T v1, DIGIT_T v0)
847 {
848 /* Compute uu = uu - q(v1v0)
849 where uu = u3u2u1u0, u3 = 0
850 and u_n, v_n are all half-digits
851 even though v1, v2 are passed as full digits. */
852 DIGIT_T p0;
853 DIGIT_T p1;
854 DIGIT_T t;
855
856 p0 = qhat * v0;
857 p1 = qhat * v1;
858 t = p0 + TOHIGH(LOHALF(p1));
859 uu[0] -= t;
860 if (uu[0] > MAX_DIGIT - t)
861 {
862 uu[1]--; /* Borrow */
863 }
864 uu[1] -= HIHALF(p1);
865 }
866
867 /*****************************************************************************/
868 static int
869 spMultiply(DIGIT_T* p, DIGIT_T x, DIGIT_T y)
870 { /* Computes p = x * y */
871 /* Ref: Arbitrary Precision Computation
872 http://numbers.computation.free.fr/Constants/constants.html
873
874 high p1 p0 low
875 +--------+--------+--------+--------+
876 | x1*y1 | x0*y0 |
877 +--------+--------+--------+--------+
878 +-+--------+--------+
879 |1| (x0*y1 + x1*y1) |
880 +-+--------+--------+
881 ^carry from adding (x0*y1+x1*y1) together
882 +-+
883 |1|< carry from adding LOHALF t
884 +-+ to high half of p0 */
885 DIGIT_T x0;
886 DIGIT_T y0;
887 DIGIT_T x1;
888 DIGIT_T y1;
889 DIGIT_T t;
890 DIGIT_T u;
891 DIGIT_T carry;
892
893 /* Split each x,y into two halves
894 x = x0 + B * x1
895 y = y0 + B * y1
896 where B = 2^16, half the digit size
897 Product is
898 xy = x0y0 + B(x0y1 + x1y0) + B^2(x1y1) */
899
900 x0 = LOHALF(x);
901 x1 = HIHALF(x);
902 y0 = LOHALF(y);
903 y1 = HIHALF(y);
904
905 /* Calc low part - no carry */
906 p[0] = x0 * y0;
907
908 /* Calc middle part */
909 t = x0 * y1;
910 u = x1 * y0;
911 t += u;
912 if (t < u)
913 {
914 carry = 1;
915 }
916 else
917 {
918 carry = 0;
919 }
920 /* This carry will go to high half of p[1]
921 + high half of t into low half of p[1] */
922 carry = TOHIGH(carry) + HIHALF(t);
923
924 /* Add low half of t to high half of p[0] */
925 t = TOHIGH(t);
926 p[0] += t;
927 if (p[0] < t)
928 {
929 carry++;
930 }
931
932 p[1] = x1 * y1;
933 p[1] += carry;
934
935 return 0;
936 }
937
938 /*****************************************************************************/
939 static DIGIT_T
940 spDivide(DIGIT_T* q, DIGIT_T* r, DIGIT_T* u, DIGIT_T v)
941 { /* Computes quotient q = u / v, remainder r = u mod v
942 where u is a double digit
943 and q, v, r are single precision digits.
944 Returns high digit of quotient (max value is 1)
945 Assumes normalised such that v1 >= b/2
946 where b is size of HALF_DIGIT
947 i.e. the most significant bit of v should be one
948
949 In terms of half-digits in Knuth notation:
950 (q2q1q0) = (u4u3u2u1u0) / (v1v0)
951 (r1r0) = (u4u3u2u1u0) mod (v1v0)
952 for m = 2, n = 2 where u4 = 0
953 q2 is either 0 or 1.
954 We set q = (q1q0) and return q2 as "overflow' */
955 DIGIT_T qhat;
956 DIGIT_T rhat;
957 DIGIT_T t;
958 DIGIT_T v0;
959 DIGIT_T v1;
960 DIGIT_T u0;
961 DIGIT_T u1;
962 DIGIT_T u2;
963 DIGIT_T u3;
964 DIGIT_T uu[2];
965 DIGIT_T q2;
966
967 /* Check for normalisation */
968 if (!(v & HIBITMASK))
969 {
970 *q = *r = 0;
971 return MAX_DIGIT;
972 }
973
974 /* Split up into half-digits */
975 v0 = LOHALF(v);
976 v1 = HIHALF(v);
977 u0 = LOHALF(u[0]);
978 u1 = HIHALF(u[0]);
979 u2 = LOHALF(u[1]);
980 u3 = HIHALF(u[1]);
981
982 /* Do three rounds of Knuth Algorithm D Vol 2 p272 */
983
984 /* ROUND 1. Set j = 2 and calculate q2 */
985 /* Estimate qhat = (u4u3)/v1 = 0 or 1
986 then set (u4u3u2) -= qhat(v1v0)
987 where u4 = 0. */
988 qhat = u3 / v1;
989 if (qhat > 0)
990 {
991 rhat = u3 - qhat * v1;
992 t = TOHIGH(rhat) | u2;
993 if (qhat * v0 > t)
994 {
995 qhat--;
996 }
997 }
998 uu[1] = 0; /* (u4) */
999 uu[0] = u[1]; /* (u3u2) */
1000 if (qhat > 0)
1001 {
1002 /* (u4u3u2) -= qhat(v1v0) where u4 = 0 */
1003 spMultSub(uu, qhat, v1, v0);
1004 if (HIHALF(uu[1]) != 0)
1005 { /* Add back */
1006 qhat--;
1007 uu[0] += v;
1008 uu[1] = 0;
1009 }
1010 }
1011 q2 = qhat;
1012 /* ROUND 2. Set j = 1 and calculate q1 */
1013 /* Estimate qhat = (u3u2) / v1
1014 then set (u3u2u1) -= qhat(v1v0) */
1015 t = uu[0];
1016 qhat = t / v1;
1017 rhat = t - qhat * v1;
1018 /* Test on v0 */
1019 t = TOHIGH(rhat) | u1;
1020 if ((qhat == B_J) || (qhat * v0 > t))
1021 {
1022 qhat--;
1023 rhat += v1;
1024 t = TOHIGH(rhat) | u1;
1025 if ((rhat < B_J) && (qhat * v0 > t))
1026 {
1027 qhat--;
1028 }
1029 }
1030 /* Multiply and subtract
1031 (u3u2u1)' = (u3u2u1) - qhat(v1v0) */
1032 uu[1] = HIHALF(uu[0]); /* (0u3) */
1033 uu[0] = TOHIGH(LOHALF(uu[0])) | u1; /* (u2u1) */
1034 spMultSub(uu, qhat, v1, v0);
1035 if (HIHALF(uu[1]) != 0)
1036 { /* Add back */
1037 qhat--;
1038 uu[0] += v;
1039 uu[1] = 0;
1040 }
1041 /* q1 = qhat */
1042 *q = TOHIGH(qhat);
1043 /* ROUND 3. Set j = 0 and calculate q0 */
1044 /* Estimate qhat = (u2u1) / v1
1045 then set (u2u1u0) -= qhat(v1v0) */
1046 t = uu[0];
1047 qhat = t / v1;
1048 rhat = t - qhat * v1;
1049 /* Test on v0 */
1050 t = TOHIGH(rhat) | u0;
1051 if ((qhat == B_J) || (qhat * v0 > t))
1052 {
1053 qhat--;
1054 rhat += v1;
1055 t = TOHIGH(rhat) | u0;
1056 if ((rhat < B_J) && (qhat * v0 > t))
1057 {
1058 qhat--;
1059 }
1060 }
1061 /* Multiply and subtract
1062 (u2u1u0)" = (u2u1u0)' - qhat(v1v0) */
1063 uu[1] = HIHALF(uu[0]); /* (0u2) */
1064 uu[0] = TOHIGH(LOHALF(uu[0])) | u0; /* (u1u0) */
1065 spMultSub(uu, qhat, v1, v0);
1066 if (HIHALF(uu[1]) != 0)
1067 { /* Add back */
1068 qhat--;
1069 uu[0] += v;
1070 uu[1] = 0;
1071 }
1072 /* q0 = qhat */
1073 *q |= LOHALF(qhat);
1074 /* Remainder is in (u1u0) i.e. uu[0] */
1075 *r = uu[0];
1076 return q2;
1077 }
1078
1079 /*****************************************************************************/
1080 static int
1081 QhatTooBig(DIGIT_T qhat, DIGIT_T rhat, DIGIT_T vn2, DIGIT_T ujn2)
1082 { /* Returns true if Qhat is too big
1083 i.e. if (Qhat * Vn-2) > (b.Rhat + Uj+n-2) */
1084 DIGIT_T t[2];
1085
1086 spMultiply(t, qhat, vn2);
1087 if (t[1] < rhat)
1088 {
1089 return 0;
1090 }
1091 else if (t[1] > rhat)
1092 {
1093 return 1;
1094 }
1095 else if (t[0] > ujn2)
1096 {
1097 return 1;
1098 }
1099 return 0;
1100 }
1101
1102 /*****************************************************************************/
1103 static DIGIT_T
1104 mpShortDiv(DIGIT_T* q, DIGIT_T* u, DIGIT_T v, unsigned int ndigits)
1105 {
1106 /* Calculates quotient q = u div v
1107 Returns remainder r = u mod v
1108 where q, u are multiprecision integers of ndigits each
1109 and d, v are single precision digits.
1110
1111 Makes no assumptions about normalisation.
1112
1113 Ref: Knuth Vol 2 Ch 4.3.1 Exercise 16 p625 */
1114 unsigned int j;
1115 unsigned int shift;
1116 DIGIT_T t[2];
1117 DIGIT_T r;
1118 DIGIT_T bitmask;
1119 DIGIT_T overflow;
1120 DIGIT_T* uu;
1121
1122 if (ndigits == 0)
1123 {
1124 return 0;
1125 }
1126 if (v == 0)
1127 {
1128 return 0; /* Divide by zero error */
1129 }
1130 /* Normalise first */
1131 /* Requires high bit of V
1132 to be set, so find most signif. bit then shift left,
1133 i.e. d = 2^shift, u' = u * d, v' = v * d. */
1134 bitmask = HIBITMASK;
1135 for (shift = 0; shift < BITS_PER_DIGIT; shift++)
1136 {
1137 if (v & bitmask)
1138 {
1139 break;
1140 }
1141 bitmask >>= 1;
1142 }
1143 v <<= shift;
1144 overflow = mpShiftLeft(q, u, shift, ndigits);
1145 uu = q;
1146 /* Step S1 - modified for extra digit. */
1147 r = overflow; /* New digit Un */
1148 j = ndigits;
1149 while (j--)
1150 {
1151 /* Step S2. */
1152 t[1] = r;
1153 t[0] = uu[j];
1154 overflow = spDivide(&q[j], &r, t, v);
1155 }
1156 /* Unnormalise */
1157 r >>= shift;
1158 return r;
1159 }
1160
1161 /*****************************************************************************/
1162 static DIGIT_T
1163 mpMultSub(DIGIT_T wn, DIGIT_T* w, DIGIT_T* v, DIGIT_T q, unsigned int n)
1164 { /* Compute w = w - qv
1165 where w = (WnW[n-1]...W[0])
1166 return modified Wn. */
1167 DIGIT_T k;
1168 DIGIT_T t[2];
1169 unsigned int i;
1170
1171 if (q == 0) /* No change */
1172 {
1173 return wn;
1174 }
1175 k = 0;
1176 for (i = 0; i < n; i++)
1177 {
1178 spMultiply(t, q, v[i]);
1179 w[i] -= k;
1180 if (w[i] > MAX_DIGIT - k)
1181 {
1182 k = 1;
1183 }
1184 else
1185 {
1186 k = 0;
1187 }
1188 w[i] -= t[0];
1189 if (w[i] > MAX_DIGIT - t[0])
1190 {
1191 k++;
1192 }
1193 k += t[1];
1194 }
1195 /* Cope with Wn not stored in array w[0..n-1] */
1196 wn -= k;
1197 return wn;
1198 }
1199
1200 /*****************************************************************************/
1201 static int
1202 mpDivide(DIGIT_T* q, DIGIT_T* r, DIGIT_T* u, unsigned int udigits,
1203 DIGIT_T* v, unsigned int vdigits)
1204 { /* Computes quotient q = u / v and remainder r = u mod v
1205 where q, r, u are multiple precision digits
1206 all of udigits and the divisor v is vdigits.
1207
1208 Ref: Knuth Vol 2 Ch 4.3.1 p 272 Algorithm D.
1209
1210 Do without extra storage space, i.e. use r[] for
1211 normalised u[], unnormalise v[] at end, and cope with
1212 extra digit Uj+n added to u after normalisation.
1213
1214 WARNING: this trashes q and r first, so cannot do
1215 u = u / v or v = u mod v. */
1216 unsigned int shift;
1217 int n;
1218 int m;
1219 int j;
1220 int qhatOK;
1221 int cmp;
1222 DIGIT_T bitmask;
1223 DIGIT_T overflow;
1224 DIGIT_T qhat;
1225 DIGIT_T rhat;
1226 DIGIT_T t[2];
1227 DIGIT_T* uu;
1228 DIGIT_T* ww;
1229
1230 /* Clear q and r */
1231 mpSetZero(q, udigits);
1232 mpSetZero(r, udigits);
1233 /* Work out exact sizes of u and v */
1234 n = (int)mpSizeof(v, vdigits);
1235 m = (int)mpSizeof(u, udigits);
1236 m -= n;
1237 /* Catch special cases */
1238 if (n == 0)
1239 {
1240 return -1; /* Error: divide by zero */
1241 }
1242 if (n == 1)
1243 { /* Use short division instead */
1244 r[0] = mpShortDiv(q, u, v[0], udigits);
1245 return 0;
1246 }
1247 if (m < 0)
1248 { /* v > u, so just set q = 0 and r = u */
1249 mpSetEqual(r, u, udigits);
1250 return 0;
1251 }
1252 if (m == 0)
1253 { /* u and v are the same length */
1254 cmp = mpCompare(u, v, (unsigned int)n);
1255 if (cmp < 0)
1256 { /* v > u, as above */
1257 mpSetEqual(r, u, udigits);
1258 return 0;
1259 }
1260 else if (cmp == 0)
1261 { /* v == u, so set q = 1 and r = 0 */
1262 mpSetDigit(q, 1, udigits);
1263 return 0;
1264 }
1265 }
1266 /* In Knuth notation, we have:
1267 Given
1268 u = (Um+n-1 ... U1U0)
1269 v = (Vn-1 ... V1V0)
1270 Compute
1271 q = u/v = (QmQm-1 ... Q0)
1272 r = u mod v = (Rn-1 ... R1R0) */
1273 /* Step D1. Normalise */
1274 /* Requires high bit of Vn-1
1275 to be set, so find most signif. bit then shift left,
1276 i.e. d = 2^shift, u' = u * d, v' = v * d. */
1277 bitmask = HIBITMASK;
1278 for (shift = 0; shift < BITS_PER_DIGIT; shift++)
1279 {
1280 if (v[n - 1] & bitmask)
1281 {
1282 break;
1283 }
1284 bitmask >>= 1;
1285 }
1286 /* Normalise v in situ - NB only shift non-zero digits */
1287 overflow = mpShiftLeft(v, v, shift, n);
1288 /* Copy normalised dividend u*d into r */
1289 overflow = mpShiftLeft(r, u, shift, n + m);
1290 uu = r; /* Use ptr to keep notation constant */
1291 t[0] = overflow; /* New digit Um+n */
1292 /* Step D2. Initialise j. Set j = m */
1293 for (j = m; j >= 0; j--)
1294 {
1295 /* Step D3. Calculate Qhat = (b.Uj+n + Uj+n-1)/Vn-1 */
1296 qhatOK = 0;
1297 t[1] = t[0]; /* This is Uj+n */
1298 t[0] = uu[j+n-1];
1299 overflow = spDivide(&qhat, &rhat, t, v[n - 1]);
1300 /* Test Qhat */
1301 if (overflow)
1302 { /* Qhat = b */
1303 qhat = MAX_DIGIT;
1304 rhat = uu[j + n - 1];
1305 rhat += v[n - 1];
1306 if (rhat < v[n - 1]) /* Overflow */
1307 {
1308 qhatOK = 1;
1309 }
1310 }
1311 if (!qhatOK && QhatTooBig(qhat, rhat, v[n - 2], uu[j + n - 2]))
1312 { /* Qhat.Vn-2 > b.Rhat + Uj+n-2 */
1313 qhat--;
1314 rhat += v[n - 1];
1315 if (!(rhat < v[n - 1]))
1316 {
1317 if (QhatTooBig(qhat, rhat, v[n - 2], uu[j + n - 2]))
1318 {
1319 qhat--;
1320 }
1321 }
1322 }
1323 /* Step D4. Multiply and subtract */
1324 ww = &uu[j];
1325 overflow = mpMultSub(t[1], ww, v, qhat, (unsigned int)n);
1326 /* Step D5. Test remainder. Set Qj = Qhat */
1327 q[j] = qhat;
1328 if (overflow)
1329 { /* Step D6. Add back if D4 was negative */
1330 q[j]--;
1331 overflow = mpAdd(ww, ww, v, (unsigned int)n);
1332 }
1333 t[0] = uu[j + n - 1]; /* Uj+n on next round */
1334 } /* Step D7. Loop on j */
1335 /* Clear high digits in uu */
1336 for (j = n; j < m+n; j++)
1337 {
1338 uu[j] = 0;
1339 }
1340 /* Step D8. Unnormalise. */
1341 mpShiftRight(r, r, shift, n);
1342 mpShiftRight(v, v, shift, n);
1343 return 0;
1344 }
1345
1346 /*****************************************************************************/
1347 static int
1348 mpModulo(DIGIT_T* r, DIGIT_T* u, unsigned int udigits,
1349 DIGIT_T* v, unsigned int vdigits)
1350 {
1351 /* Calculates r = u mod v
1352 where r, v are multiprecision integers of length vdigits
1353 and u is a multiprecision integer of length udigits.
1354 r may overlap v.
1355
1356 Note that r here is only vdigits long,
1357 whereas in mpDivide it is udigits long.
1358
1359 Use remainder from mpDivide function. */
1360 /* Double-length temp variable for divide fn */
1361 DIGIT_T qq[MAX_DIG_LEN * 2];
1362 /* Use a double-length temp for r to allow overlap of r and v */
1363 DIGIT_T rr[MAX_DIG_LEN * 2];
1364
1365 /* rr[2n] = u[2n] mod v[n] */
1366 mpDivide(qq, rr, u, udigits, v, vdigits);
1367 mpSetEqual(r, rr, vdigits);
1368 mpSetZero(rr, udigits);
1369 mpSetZero(qq, udigits);
1370 return 0;
1371 }
1372
1373 /*****************************************************************************/
1374 static int
1375 mpMultiply(DIGIT_T* w, DIGIT_T* u, DIGIT_T* v, unsigned int ndigits)
1376 {
1377 /* Computes product w = u * v
1378 where u, v are multiprecision integers of ndigits each
1379 and w is a multiprecision integer of 2*ndigits
1380 Ref: Knuth Vol 2 Ch 4.3.1 p 268 Algorithm M. */
1381 DIGIT_T k;
1382 DIGIT_T t[2];
1383 unsigned int i;
1384 unsigned int j;
1385 unsigned int m;
1386 unsigned int n;
1387
1388 n = ndigits;
1389 m = n;
1390 /* Step M1. Initialise */
1391 for (i = 0; i < 2 * m; i++)
1392 {
1393 w[i] = 0;
1394 }
1395 for (j = 0; j < n; j++)
1396 {
1397 /* Step M2. Zero multiplier? */
1398 if (v[j] == 0)
1399 {
1400 w[j + m] = 0;
1401 }
1402 else
1403 {
1404 /* Step M3. Initialise i */
1405 k = 0;
1406 for (i = 0; i < m; i++)
1407 {
1408 /* Step M4. Multiply and add */
1409 /* t = u_i * v_j + w_(i+j) + k */
1410 spMultiply(t, u[i], v[j]);
1411 t[0] += k;
1412 if (t[0] < k)
1413 {
1414 t[1]++;
1415 }
1416 t[0] += w[i + j];
1417 if (t[0] < w[i+j])
1418 {
1419 t[1]++;
1420 }
1421 w[i + j] = t[0];
1422 k = t[1];
1423 }
1424 /* Step M5. Loop on i, set w_(j+m) = k */
1425 w[j + m] = k;
1426 }
1427 } /* Step M6. Loop on j */
1428 return 0;
1429 }
1430
1431 /*****************************************************************************/
1432 static int
1433 mpModMult(DIGIT_T* a, DIGIT_T* x, DIGIT_T* y,
1434 DIGIT_T* m, unsigned int ndigits)
1435 { /* Computes a = (x * y) mod m */
1436 /* Double-length temp variable */
1437 DIGIT_T p[MAX_DIG_LEN * 2];
1438
1439 /* Calc p[2n] = x * y */
1440 mpMultiply(p, x, y, ndigits);
1441 /* Then modulo */
1442 mpModulo(a, p, ndigits * 2, m, ndigits);
1443 mpSetZero(p, ndigits * 2);
1444 return 0;
1445 }
1446
1447 /*****************************************************************************/
1448 int
1449 rdssl_mod_exp(char* out, int out_len, char* in, int in_len,
1450 char* mod, int mod_len, char* exp, int exp_len)
1451 {
1452 /* Computes y = x ^ e mod m */
1453 /* Binary left-to-right method */
1454 DIGIT_T mask;
1455 DIGIT_T* e;
1456 DIGIT_T* x;
1457 DIGIT_T* y;
1458 DIGIT_T* m;
1459 unsigned int n;
1460 int max_size;
1461 char* l_out;
1462 char* l_in;
1463 char* l_mod;
1464 char* l_exp;
1465
1466 if (in_len > out_len || in_len == 0 ||
1467 out_len == 0 || mod_len == 0 || exp_len == 0)
1468 {
1469 return 0;
1470 }
1471 max_size = out_len;
1472 if (in_len > max_size)
1473 {
1474 max_size = in_len;
1475 }
1476 if (mod_len > max_size)
1477 {
1478 max_size = mod_len;
1479 }
1480 if (exp_len > max_size)
1481 {
1482 max_size = exp_len;
1483 }
1484 l_out = (char*)g_malloc(max_size, 1);
1485 l_in = (char*)g_malloc(max_size, 1);
1486 l_mod = (char*)g_malloc(max_size, 1);
1487 l_exp = (char*)g_malloc(max_size, 1);
1488 memcpy(l_in, in, in_len);
1489 memcpy(l_mod, mod, mod_len);
1490 memcpy(l_exp, exp, exp_len);
1491 e = (DIGIT_T*)l_exp;
1492 x = (DIGIT_T*)l_in;
1493 y = (DIGIT_T*)l_out;
1494 m = (DIGIT_T*)l_mod;
1495 /* Find second-most significant bit in e */
1496 n = mpSizeof(e, max_size / 4);
1497 for (mask = HIBITMASK; mask > 0; mask >>= 1)
1498 {
1499 if (e[n - 1] & mask)
1500 {
1501 break;
1502 }
1503 }
1504 mpNEXTBITMASK(mask, n);
1505 /* Set y = x */
1506 mpSetEqual(y, x, max_size / 4);
1507 /* For bit j = k - 2 downto 0 step -1 */
1508 while (n)
1509 {
1510 mpModMult(y, y, y, m, max_size / 4); /* Square */
1511 if (e[n - 1] & mask)
1512 {
1513 mpModMult(y, y, x, m, max_size / 4); /* Multiply */
1514 }
1515 /* Move to next bit */
1516 mpNEXTBITMASK(mask, n);
1517 }
1518 memcpy(out, l_out, out_len);
1519 g_free(l_out);
1520 g_free(l_in);
1521 g_free(l_mod);
1522 g_free(l_exp);
1523 return out_len;
1524 }
1525
1526 static uint8 g_ppk_n[72] =
1527 {
1528 0x3D, 0x3A, 0x5E, 0xBD, 0x72, 0x43, 0x3E, 0xC9,
1529 0x4D, 0xBB, 0xC1, 0x1E, 0x4A, 0xBA, 0x5F, 0xCB,
1530 0x3E, 0x88, 0x20, 0x87, 0xEF, 0xF5, 0xC1, 0xE2,
1531 0xD7, 0xB7, 0x6B, 0x9A, 0xF2, 0x52, 0x45, 0x95,
1532 0xCE, 0x63, 0x65, 0x6B, 0x58, 0x3A, 0xFE, 0xEF,
1533 0x7C, 0xE7, 0xBF, 0xFE, 0x3D, 0xF6, 0x5C, 0x7D,
1534 0x6C, 0x5E, 0x06, 0x09, 0x1A, 0xF5, 0x61, 0xBB,
1535 0x20, 0x93, 0x09, 0x5F, 0x05, 0x6D, 0xEA, 0x87,
1536 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1537 };
1538
1539 static uint8 g_ppk_d[108] =
1540 {
1541 0x87, 0xA7, 0x19, 0x32, 0xDA, 0x11, 0x87, 0x55,
1542 0x58, 0x00, 0x16, 0x16, 0x25, 0x65, 0x68, 0xF8,
1543 0x24, 0x3E, 0xE6, 0xFA, 0xE9, 0x67, 0x49, 0x94,
1544 0xCF, 0x92, 0xCC, 0x33, 0x99, 0xE8, 0x08, 0x60,
1545 0x17, 0x9A, 0x12, 0x9F, 0x24, 0xDD, 0xB1, 0x24,
1546 0x99, 0xC7, 0x3A, 0xB8, 0x0A, 0x7B, 0x0D, 0xDD,
1547 0x35, 0x07, 0x79, 0x17, 0x0B, 0x51, 0x9B, 0xB3,
1548 0xC7, 0x10, 0x01, 0x13, 0xE7, 0x3F, 0xF3, 0x5F,
1549 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1550 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1551 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1552 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1553 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1554 0x00, 0x00, 0x00, 0x00
1555 };
1556
1557 int
1558 rdssl_sign_ok(char* e_data, int e_len, char* n_data, int n_len,
1559 char* sign_data, int sign_len, char* sign_data2, int sign_len2, char* testkey)
1560 {
1561 char* key;
1562 char* md5_final;
1563 void* md5;
1564
1565 if ((e_len != 4) || (n_len != 64) || (sign_len != 64) || (sign_len2 != 64))
1566 {
1567 return 1;
1568 }
1569 key = (char*)xmalloc(176);
1570 md5_final = (char*)xmalloc(64);
1571 md5 = rdssl_md5_info_create();
1572 // copy the test key
1573 memcpy(key, testkey, 176);
1574 // replace e and n
1575 memcpy(key + 32, e_data, 4);
1576 memcpy(key + 36, n_data, 64);
1577 rdssl_md5_clear(md5);
1578 // the first 108 bytes
1579 rdssl_md5_transform(md5, key, 108);
1580 // set the whole thing with 0xff
1581 memset(md5_final, 0xff, 64);
1582 // digest 16 bytes
1583 rdssl_md5_complete(md5, md5_final);
1584 // set non 0xff array items
1585 md5_final[16] = 0;
1586 md5_final[62] = 1;
1587 md5_final[63] = 0;
1588 // encrypt
1589 rdssl_mod_exp(sign_data, 64, md5_final, 64, (char*)g_ppk_n, 64,
1590 (char*)g_ppk_d, 64);
1591 // cleanup
1592 rdssl_md5_info_delete(md5);
1593 xfree(key);
1594 xfree(md5_final);
1595 return memcmp(sign_data, sign_data2, sign_len2);
1596 }
1597
1598 /*****************************************************************************/
1599 PCCERT_CONTEXT rdssl_cert_read(uint8 * data, uint32 len)
1600 {
1601 PCCERT_CONTEXT res;
1602 if (!data || !len)
1603 {
1604 error("rdssl_cert_read %p %ld\n", data, len);
1605 return NULL;
1606 }
1607 res = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, data, len);
1608 if (!res)
1609 {
1610 error("CertCreateCertificateContext call failed with %lx\n", GetLastError());
1611 }
1612 return res;
1613 }
1614
1615 /*****************************************************************************/
1616 void rdssl_cert_free(PCCERT_CONTEXT context)
1617 {
1618 if (context)
1619 CertFreeCertificateContext(context);
1620 }
1621
1622 /*****************************************************************************/
1623 uint8 *rdssl_cert_to_rkey(PCCERT_CONTEXT cert, uint32 * key_len)
1624 {
1625 HCRYPTPROV hCryptProv;
1626 HCRYPTKEY hKey;
1627 BOOL ret;
1628 BYTE * rkey;
1629 DWORD dwSize, dwErr;
1630 ret = CryptAcquireContext(&hCryptProv,
1631 NULL,
1632 MS_ENHANCED_PROV,
1633 PROV_RSA_FULL,
1634 0);
1635 if (!ret)
1636 {
1637 dwErr = GetLastError();
1638 error("CryptAcquireContext call failed with %lx\n", dwErr);
1639 return NULL;
1640 }
1641 ret = CryptImportPublicKeyInfoEx(hCryptProv,
1642 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
1643 &(cert->pCertInfo->SubjectPublicKeyInfo),
1644 0,
1645 0,
1646 NULL,
1647 &hKey);
1648 if (!ret)
1649 {
1650 dwErr = GetLastError();
1651 CryptReleaseContext(hCryptProv, 0);
1652 error("CryptImportPublicKeyInfoEx call failed with %lx\n", dwErr);
1653 return NULL;
1654 }
1655 ret = CryptExportKey(hKey,
1656 0,
1657 PUBLICKEYBLOB,
1658 0,
1659 NULL,
1660 &dwSize);
1661 if (!ret)
1662 {
1663 dwErr = GetLastError();
1664 CryptDestroyKey(hKey);
1665 CryptReleaseContext(hCryptProv, 0);
1666 error("CryptExportKey call failed with %lx\n", dwErr);
1667 return NULL;
1668 }
1669 rkey = g_malloc(dwSize, 0);
1670 ret = CryptExportKey(hKey,
1671 0,
1672 PUBLICKEYBLOB,
1673 0,
1674 rkey,
1675 &dwSize);
1676 if (!ret)
1677 {
1678 dwErr = GetLastError();
1679 g_free(rkey);
1680 CryptDestroyKey(hKey);
1681 CryptReleaseContext(hCryptProv, 0);
1682 error("CryptExportKey call failed with %lx\n", dwErr);
1683 return NULL;
1684 }
1685 CryptDestroyKey(hKey);
1686 CryptReleaseContext(hCryptProv, 0);
1687 return rkey;
1688 }
1689
1690 /*****************************************************************************/
1691 RD_BOOL rdssl_certs_ok(PCCERT_CONTEXT server_cert, PCCERT_CONTEXT cacert)
1692 {
1693 /* FIXME should we check for expired certificates??? */
1694 DWORD dwFlags = CERT_STORE_SIGNATURE_FLAG; /* CERT_STORE_TIME_VALIDITY_FLAG */
1695 BOOL ret = CertVerifySubjectCertificateContext(server_cert,
1696 cacert,
1697 &dwFlags);
1698 if (!ret)
1699 {
1700 error("CertVerifySubjectCertificateContext call failed with %lx\n", GetLastError());
1701 }
1702 if (dwFlags)
1703 {
1704 error("CertVerifySubjectCertificateContext check failed %lx\n", dwFlags);
1705 }
1706 return (dwFlags == 0);
1707 }
1708
1709 /*****************************************************************************/
1710 int rdssl_rkey_get_exp_mod(uint8 * rkey, uint8 * exponent, uint32 max_exp_len, uint8 * modulus,
1711 uint32 max_mod_len)
1712 {
1713 RSAPUBKEY *desc = (RSAPUBKEY *)(rkey + sizeof(PUBLICKEYSTRUC));
1714 if (!rkey || !exponent || !max_exp_len || !modulus || !max_mod_len)
1715 {
1716 error("rdssl_rkey_get_exp_mod %p %p %ld %p %ld\n", rkey, exponent, max_exp_len, modulus, max_mod_len);
1717 return -1;
1718 }
1719 memcpy (exponent, &desc->pubexp, max_exp_len);
1720 memcpy (modulus, rkey + sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY), max_mod_len);
1721 return 0;
1722 }
1723
1724 /*****************************************************************************/
1725 void rdssl_rkey_free(uint8 * rkey)
1726 {
1727 if (!rkey)
1728 {
1729 error("rdssl_rkey_free rkey is null\n");
1730 return;
1731 }
1732 g_free(rkey);
1733 }