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.
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.
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.
16 xrdp: A Remote Desktop Protocol server.
17 Copyright (C) Jay Sorg 2004-2005
25 /*****************************************************************************/
26 static void * g_malloc(int size
, int zero
)
30 p
= CryptMemAlloc(size
);
38 /*****************************************************************************/
39 static void g_free(void * in
)
46 HCRYPTPROV hCryptProv
;
49 /*****************************************************************************/
51 rdssl_rc4_info_create(void)
53 struct rc4_state
*info
= g_malloc(sizeof(struct rc4_state
), 1);
58 error("rdssl_rc4_info_create no memory\n");
61 ret
= CryptAcquireContext(&info
->hCryptProv
,
68 dwErr
= GetLastError();
69 error("CryptAcquireContext failed with %lx\n", dwErr
);
76 /*****************************************************************************/
78 rdssl_rc4_info_delete(void* rc4_info
)
80 struct rc4_state
*info
= rc4_info
;
85 //error("rdssl_rc4_info_delete rc4_info is null\n");
90 ret
= CryptDestroyKey(info
->hKey
);
93 dwErr
= GetLastError();
94 error("CryptDestroyKey failed with %lx\n", dwErr
);
99 ret
= CryptReleaseContext(info
->hCryptProv
, 0);
102 dwErr
= GetLastError();
103 error("CryptReleaseContext failed with %lx\n", dwErr
);
109 /*****************************************************************************/
111 rdssl_rc4_set_key(void* rc4_info
, char* key
, int len
)
113 struct rc4_state
*info
= rc4_info
;
117 PUBLICKEYSTRUC
*desc
;
120 if (!rc4_info
|| !key
|| !len
|| !info
->hCryptProv
)
122 error("rdssl_rc4_set_key %p %p %d\n", rc4_info
, key
, len
);
125 blob
= g_malloc(sizeof(PUBLICKEYSTRUC
) + sizeof(DWORD
) + len
, 0);
128 error("rdssl_rc4_set_key no memory\n");
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
;
139 memcpy(keyBuf
, key
, len
);
142 CryptDestroyKey(info
->hKey
);
145 ret
= CryptImportKey(info
->hCryptProv
,
147 sizeof(PUBLICKEYSTRUC
) + sizeof(DWORD
) + len
,
154 dwErr
= GetLastError();
155 error("CryptImportKey failed with %lx\n", dwErr
);
159 /*****************************************************************************/
161 rdssl_rc4_crypt(void* rc4_info
, char* in_data
, char* out_data
, int len
)
163 struct rc4_state
*info
= rc4_info
;
166 BYTE
* intermediate_data
;
168 if (!rc4_info
|| !in_data
|| !out_data
|| !len
|| !info
->hKey
)
170 error("rdssl_rc4_crypt %p %p %p %d\n", rc4_info
, in_data
, out_data
, len
);
173 intermediate_data
= g_malloc(len
, 0);
174 if (!intermediate_data
)
176 error("rdssl_rc4_set_key no memory\n");
179 memcpy(intermediate_data
, in_data
, len
);
180 ret
= CryptEncrypt(info
->hKey
,
189 dwErr
= GetLastError();
190 g_free(intermediate_data
);
191 error("CryptEncrypt failed with %lx\n", dwErr
);
194 memcpy(out_data
, intermediate_data
, len
);
195 g_free(intermediate_data
);
200 HCRYPTPROV hCryptProv
;
204 /*****************************************************************************/
206 rdssl_hash_info_create(ALG_ID id
)
208 struct hash_context
*info
= g_malloc(sizeof(struct hash_context
), 1);
213 error("rdssl_hash_info_create %d no memory\n", id
);
216 ret
= CryptAcquireContext(&info
->hCryptProv
,
223 dwErr
= GetLastError();
225 error("CryptAcquireContext failed with %lx\n", dwErr
);
228 ret
= CryptCreateHash(info
->hCryptProv
,
235 dwErr
= GetLastError();
236 CryptReleaseContext(info
->hCryptProv
, 0);
238 error("CryptCreateHash failed with %lx\n", dwErr
);
244 /*****************************************************************************/
246 rdssl_hash_info_delete(void* hash_info
)
248 struct hash_context
*info
= hash_info
;
251 //error("ssl_hash_info_delete hash_info is null\n");
256 CryptDestroyHash(info
->hHash
);
258 if (info
->hCryptProv
)
260 CryptReleaseContext(info
->hCryptProv
, 0);
265 /*****************************************************************************/
267 rdssl_hash_clear(void* hash_info
, ALG_ID id
)
269 struct hash_context
*info
= hash_info
;
272 if (!info
|| !info
->hHash
|| !info
->hCryptProv
)
274 error("rdssl_hash_clear %p\n", info
);
277 ret
= CryptDestroyHash(info
->hHash
);
280 dwErr
= GetLastError();
281 error("CryptDestroyHash failed with %lx\n", dwErr
);
284 ret
= CryptCreateHash(info
->hCryptProv
,
291 dwErr
= GetLastError();
292 error("CryptCreateHash failed with %lx\n", dwErr
);
297 rdssl_hash_transform(void* hash_info
, char* data
, int len
)
299 struct hash_context
*info
= hash_info
;
302 if (!info
|| !info
->hHash
|| !info
->hCryptProv
|| !data
|| !len
)
304 error("rdssl_hash_transform %p %p %d\n", hash_info
, data
, len
);
307 ret
= CryptHashData(info
->hHash
,
313 dwErr
= GetLastError();
314 error("CryptHashData failed with %lx\n", dwErr
);
318 /*****************************************************************************/
320 rdssl_hash_complete(void* hash_info
, char* data
)
322 struct hash_context
*info
= hash_info
;
324 DWORD dwErr
, dwDataLen
;
325 if (!info
|| !info
->hHash
|| !info
->hCryptProv
|| !data
)
327 error("rdssl_hash_complete %p %p\n", hash_info
, data
);
330 ret
= CryptGetHashParam(info
->hHash
,
337 dwErr
= GetLastError();
338 error("CryptGetHashParam failed with %lx\n", dwErr
);
341 ret
= CryptGetHashParam(info
->hHash
,
348 dwErr
= GetLastError();
349 error("CryptGetHashParam failed with %lx\n", dwErr
);
353 /*****************************************************************************/
355 rdssl_sha1_info_create(void)
357 return rdssl_hash_info_create(CALG_SHA1
);
360 /*****************************************************************************/
362 rdssl_sha1_info_delete(void* sha1_info
)
364 rdssl_hash_info_delete(sha1_info
);
367 /*****************************************************************************/
369 rdssl_sha1_clear(void* sha1_info
)
371 rdssl_hash_clear(sha1_info
, CALG_SHA1
);
374 /*****************************************************************************/
376 rdssl_sha1_transform(void* sha1_info
, char* data
, int len
)
378 rdssl_hash_transform(sha1_info
, data
, len
);
381 /*****************************************************************************/
383 rdssl_sha1_complete(void* sha1_info
, char* data
)
385 rdssl_hash_complete(sha1_info
, data
);
388 /*****************************************************************************/
390 rdssl_md5_info_create(void)
392 return rdssl_hash_info_create(CALG_MD5
);
395 /*****************************************************************************/
397 rdssl_md5_info_delete(void* md5_info
)
399 rdssl_hash_info_delete(md5_info
);
402 /*****************************************************************************/
404 rdssl_md5_clear(void* md5_info
)
406 rdssl_hash_clear(md5_info
, CALG_MD5
);
409 /*****************************************************************************/
411 rdssl_md5_transform(void* md5_info
, char* data
, int len
)
413 rdssl_hash_transform(md5_info
, data
, len
);
416 /*****************************************************************************/
418 rdssl_md5_complete(void* md5_info
, char* data
)
420 rdssl_hash_complete(md5_info
, data
);
423 /*****************************************************************************/
425 rdssl_hmac_md5(char* key
, int keylen
, char* data
, int len
, char* output
)
427 HCRYPTPROV hCryptProv
;
431 DWORD dwErr
, dwDataLen
;
434 PUBLICKEYSTRUC
*desc
;
439 if (!key
|| !keylen
|| !data
|| !len
||!output
)
441 error("rdssl_hmac_md5 %p %d %p %d %p\n", key
, keylen
, data
, len
, output
);
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
);
450 error("rdssl_hmac_md5 %d no memory\n");
453 ret
= CryptAcquireContext(&hCryptProv
,
460 dwErr
= GetLastError();
462 error("CryptAcquireContext failed with %lx\n", dwErr
);
465 desc
->aiKeyAlg
= CALG_RC4
;
466 desc
->bType
= PLAINTEXTKEYBLOB
;
467 desc
->bVersion
= CUR_BLOB_VERSION
;
472 ret
= CryptCreateHash(hCryptProv
,
479 dwErr
= GetLastError();
481 error("CryptCreateHash failed with %lx\n", dwErr
);
484 ret
= CryptHashData(hHash
,
490 dwErr
= GetLastError();
492 error("CryptHashData failed with %lx\n", dwErr
);
495 ret
= CryptGetHashParam(hHash
,
502 dwErr
= GetLastError();
504 error("CryptGetHashParam failed with %lx\n", dwErr
);
507 ret
= CryptGetHashParam(hHash
,
514 dwErr
= GetLastError();
516 error("CryptGetHashParam failed with %lx\n", dwErr
);
523 memcpy(keyBuf
, key
, keylen
);
524 ret
= CryptImportKey(hCryptProv
,
526 sizeof(PUBLICKEYSTRUC
) + sizeof(DWORD
) + keylen
,
533 dwErr
= GetLastError();
534 error("CryptImportKey failed with %lx\n", dwErr
);
537 ret
= CryptCreateHash(hCryptProv
,
544 dwErr
= GetLastError();
545 error("CryptCreateHash failed with %lx\n", dwErr
);
548 info
.HashAlgid
= CALG_MD5
;
549 info
.cbInnerString
= 0;
550 info
.cbOuterString
= 0;
551 ret
= CryptSetHashParam(hHash
,
557 dwErr
= GetLastError();
558 error("CryptSetHashParam failed with %lx\n", dwErr
);
561 ret
= CryptHashData(hHash
,
567 dwErr
= GetLastError();
568 error("CryptHashData failed with %lx\n", dwErr
);
571 ret
= CryptGetHashParam(hHash
,
578 dwErr
= GetLastError();
579 error("CryptGetHashParam failed with %lx\n", dwErr
);
582 ret
= CryptGetHashParam(hHash
,
589 dwErr
= GetLastError();
590 error("CryptGetHashParam failed with %lx\n", dwErr
);
593 CryptDestroyHash(hHash
);
594 ret
= CryptReleaseContext(hCryptProv
, 0);
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:
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."
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
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*************************/
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))
648 #define mpNEXTBITMASK(mask, n) \
661 /*****************************************************************************/
663 mpAdd(DIGIT_T
* w
, DIGIT_T
* u
, DIGIT_T
* v
, unsigned int ndigits
)
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.
669 Ref: Knuth Vol 2 Ch 4.3.1 p 266 Algorithm A. */
673 /* Step A1. Initialise */
675 for (j
= 0; j
< ndigits
; j
++)
677 /* Step A2. Add digits w_j = (u_j + v_j + k)
678 Set k = 1 if carry (overflow) occurs */
693 } /* Step A3. Loop on j */
694 return k
; /* w_n = k */
697 /*****************************************************************************/
699 mpSetDigit(DIGIT_T
* a
, DIGIT_T d
, unsigned int ndigits
)
700 { /* Sets a = d where d is a single digit */
703 for (i
= 1; i
< ndigits
; i
++)
710 /*****************************************************************************/
712 mpCompare(DIGIT_T
* a
, DIGIT_T
* b
, unsigned int ndigits
)
714 /* Returns sign of (a - b) */
721 if (a
[ndigits
] > b
[ndigits
])
725 if (a
[ndigits
] < b
[ndigits
])
733 /*****************************************************************************/
735 mpSetZero(DIGIT_T
* a
, unsigned int ndigits
)
739 for (i
= 0; i
< ndigits
; i
++)
745 /*****************************************************************************/
747 mpSetEqual(DIGIT_T
* a
, DIGIT_T
* b
, unsigned int ndigits
)
751 for (i
= 0; i
< ndigits
; i
++)
757 /*****************************************************************************/
759 mpSizeof(DIGIT_T
* a
, unsigned int ndigits
)
760 { /* Returns size of significant digits in a */
771 /*****************************************************************************/
773 mpShiftLeft(DIGIT_T
* a
, DIGIT_T
* b
, unsigned int x
, unsigned int ndigits
)
774 { /* Computes a = b << x */
781 /* Check input - NB unspecified result */
782 if (x
>= BITS_PER_DIGIT
)
788 for (i
= 1; i
< x
; i
++)
790 mask
= (mask
>> 1) | mask
;
796 y
= BITS_PER_DIGIT
- x
;
798 for (i
= 0; i
< ndigits
; i
++)
800 nextcarry
= (b
[i
] & mask
) >> y
;
801 a
[i
] = b
[i
] << x
| carry
;
807 /*****************************************************************************/
809 mpShiftRight(DIGIT_T
* a
, DIGIT_T
* b
, unsigned int x
, unsigned int ndigits
)
810 { /* Computes a = b >> x */
817 /* Check input - NB unspecified result */
818 if (x
>= BITS_PER_DIGIT
)
824 for (i
= 1; i
< x
; i
++)
826 mask
= (mask
<< 1) | mask
;
832 y
= BITS_PER_DIGIT
- x
;
837 nextcarry
= (b
[i
] & mask
) << y
;
838 a
[i
] = b
[i
] >> x
| carry
;
844 /*****************************************************************************/
846 spMultSub(DIGIT_T
* uu
, DIGIT_T qhat
, DIGIT_T v1
, DIGIT_T v0
)
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. */
858 t
= p0
+ TOHIGH(LOHALF(p1
));
860 if (uu
[0] > MAX_DIGIT
- t
)
862 uu
[1]--; /* Borrow */
867 /*****************************************************************************/
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
875 +--------+--------+--------+--------+
877 +--------+--------+--------+--------+
878 +-+--------+--------+
879 |1| (x0*y1 + x1*y1) |
880 +-+--------+--------+
881 ^carry from adding (x0*y1+x1*y1) together
883 |1|< carry from adding LOHALF t
884 +-+ to high half of p0 */
893 /* Split each x,y into two halves
896 where B = 2^16, half the digit size
898 xy = x0y0 + B(x0y1 + x1y0) + B^2(x1y1) */
905 /* Calc low part - no carry */
908 /* Calc middle part */
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
);
924 /* Add low half of t to high half of p[0] */
938 /*****************************************************************************/
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
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
954 We set q = (q1q0) and return q2 as "overflow' */
967 /* Check for normalisation */
968 if (!(v
& HIBITMASK
))
974 /* Split up into half-digits */
982 /* Do three rounds of Knuth Algorithm D Vol 2 p272 */
984 /* ROUND 1. Set j = 2 and calculate q2 */
985 /* Estimate qhat = (u4u3)/v1 = 0 or 1
986 then set (u4u3u2) -= qhat(v1v0)
991 rhat
= u3
- qhat
* v1
;
992 t
= TOHIGH(rhat
) | u2
;
998 uu
[1] = 0; /* (u4) */
999 uu
[0] = u
[1]; /* (u3u2) */
1002 /* (u4u3u2) -= qhat(v1v0) where u4 = 0 */
1003 spMultSub(uu
, qhat
, v1
, v0
);
1004 if (HIHALF(uu
[1]) != 0)
1012 /* ROUND 2. Set j = 1 and calculate q1 */
1013 /* Estimate qhat = (u3u2) / v1
1014 then set (u3u2u1) -= qhat(v1v0) */
1017 rhat
= t
- qhat
* v1
;
1019 t
= TOHIGH(rhat
) | u1
;
1020 if ((qhat
== B_J
) || (qhat
* v0
> t
))
1024 t
= TOHIGH(rhat
) | u1
;
1025 if ((rhat
< B_J
) && (qhat
* v0
> t
))
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)
1043 /* ROUND 3. Set j = 0 and calculate q0 */
1044 /* Estimate qhat = (u2u1) / v1
1045 then set (u2u1u0) -= qhat(v1v0) */
1048 rhat
= t
- qhat
* v1
;
1050 t
= TOHIGH(rhat
) | u0
;
1051 if ((qhat
== B_J
) || (qhat
* v0
> t
))
1055 t
= TOHIGH(rhat
) | u0
;
1056 if ((rhat
< B_J
) && (qhat
* v0
> t
))
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)
1074 /* Remainder is in (u1u0) i.e. uu[0] */
1079 /*****************************************************************************/
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) */
1086 spMultiply(t
, qhat
, vn2
);
1091 else if (t
[1] > rhat
)
1095 else if (t
[0] > ujn2
)
1102 /*****************************************************************************/
1104 mpShortDiv(DIGIT_T
* q
, DIGIT_T
* u
, DIGIT_T v
, unsigned int ndigits
)
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.
1111 Makes no assumptions about normalisation.
1113 Ref: Knuth Vol 2 Ch 4.3.1 Exercise 16 p625 */
1128 return 0; /* Divide by zero error */
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
++)
1144 overflow
= mpShiftLeft(q
, u
, shift
, ndigits
);
1146 /* Step S1 - modified for extra digit. */
1147 r
= overflow
; /* New digit Un */
1154 overflow
= spDivide(&q
[j
], &r
, t
, v
);
1161 /*****************************************************************************/
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. */
1171 if (q
== 0) /* No change */
1176 for (i
= 0; i
< n
; i
++)
1178 spMultiply(t
, q
, v
[i
]);
1180 if (w
[i
] > MAX_DIGIT
- k
)
1189 if (w
[i
] > MAX_DIGIT
- t
[0])
1195 /* Cope with Wn not stored in array w[0..n-1] */
1200 /*****************************************************************************/
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.
1208 Ref: Knuth Vol 2 Ch 4.3.1 p 272 Algorithm D.
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.
1214 WARNING: this trashes q and r first, so cannot do
1215 u = u / v or v = u mod v. */
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
);
1237 /* Catch special cases */
1240 return -1; /* Error: divide by zero */
1243 { /* Use short division instead */
1244 r
[0] = mpShortDiv(q
, u
, v
[0], udigits
);
1248 { /* v > u, so just set q = 0 and r = u */
1249 mpSetEqual(r
, u
, udigits
);
1253 { /* u and v are the same length */
1254 cmp
= mpCompare(u
, v
, (unsigned int)n
);
1256 { /* v > u, as above */
1257 mpSetEqual(r
, u
, udigits
);
1261 { /* v == u, so set q = 1 and r = 0 */
1262 mpSetDigit(q
, 1, udigits
);
1266 /* In Knuth notation, we have:
1268 u = (Um+n-1 ... U1U0)
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
++)
1280 if (v
[n
- 1] & bitmask
)
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
--)
1295 /* Step D3. Calculate Qhat = (b.Uj+n + Uj+n-1)/Vn-1 */
1297 t
[1] = t
[0]; /* This is Uj+n */
1299 overflow
= spDivide(&qhat
, &rhat
, t
, v
[n
- 1]);
1304 rhat
= uu
[j
+ n
- 1];
1306 if (rhat
< v
[n
- 1]) /* Overflow */
1311 if (!qhatOK
&& QhatTooBig(qhat
, rhat
, v
[n
- 2], uu
[j
+ n
- 2]))
1312 { /* Qhat.Vn-2 > b.Rhat + Uj+n-2 */
1315 if (!(rhat
< v
[n
- 1]))
1317 if (QhatTooBig(qhat
, rhat
, v
[n
- 2], uu
[j
+ n
- 2]))
1323 /* Step D4. Multiply and subtract */
1325 overflow
= mpMultSub(t
[1], ww
, v
, qhat
, (unsigned int)n
);
1326 /* Step D5. Test remainder. Set Qj = Qhat */
1329 { /* Step D6. Add back if D4 was negative */
1331 overflow
= mpAdd(ww
, ww
, v
, (unsigned int)n
);
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
++)
1340 /* Step D8. Unnormalise. */
1341 mpShiftRight(r
, r
, shift
, n
);
1342 mpShiftRight(v
, v
, shift
, n
);
1346 /*****************************************************************************/
1348 mpModulo(DIGIT_T
* r
, DIGIT_T
* u
, unsigned int udigits
,
1349 DIGIT_T
* v
, unsigned int vdigits
)
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.
1356 Note that r here is only vdigits long,
1357 whereas in mpDivide it is udigits long.
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];
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
);
1373 /*****************************************************************************/
1375 mpMultiply(DIGIT_T
* w
, DIGIT_T
* u
, DIGIT_T
* v
, unsigned int ndigits
)
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. */
1390 /* Step M1. Initialise */
1391 for (i
= 0; i
< 2 * m
; i
++)
1395 for (j
= 0; j
< n
; j
++)
1397 /* Step M2. Zero multiplier? */
1404 /* Step M3. Initialise i */
1406 for (i
= 0; i
< m
; i
++)
1408 /* Step M4. Multiply and add */
1409 /* t = u_i * v_j + w_(i+j) + k */
1410 spMultiply(t
, u
[i
], v
[j
]);
1424 /* Step M5. Loop on i, set w_(j+m) = k */
1427 } /* Step M6. Loop on j */
1431 /*****************************************************************************/
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];
1439 /* Calc p[2n] = x * y */
1440 mpMultiply(p
, x
, y
, ndigits
);
1442 mpModulo(a
, p
, ndigits
* 2, m
, ndigits
);
1443 mpSetZero(p
, ndigits
* 2);
1447 /*****************************************************************************/
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
)
1452 /* Computes y = x ^ e mod m */
1453 /* Binary left-to-right method */
1466 if (in_len
> out_len
|| in_len
== 0 ||
1467 out_len
== 0 || mod_len
== 0 || exp_len
== 0)
1472 if (in_len
> max_size
)
1476 if (mod_len
> max_size
)
1480 if (exp_len
> max_size
)
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
;
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)
1499 if (e
[n
- 1] & mask
)
1504 mpNEXTBITMASK(mask
, n
);
1506 mpSetEqual(y
, x
, max_size
/ 4);
1507 /* For bit j = k - 2 downto 0 step -1 */
1510 mpModMult(y
, y
, y
, m
, max_size
/ 4); /* Square */
1511 if (e
[n
- 1] & mask
)
1513 mpModMult(y
, y
, x
, m
, max_size
/ 4); /* Multiply */
1515 /* Move to next bit */
1516 mpNEXTBITMASK(mask
, n
);
1518 memcpy(out
, l_out
, out_len
);
1526 static uint8 g_ppk_n
[72] =
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
1539 static uint8 g_ppk_d
[108] =
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
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
)
1565 if ((e_len
!= 4) || (n_len
!= 64) || (sign_len
!= 64) || (sign_len2
!= 64))
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);
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);
1583 rdssl_md5_complete(md5
, md5_final
);
1584 // set non 0xff array items
1589 rdssl_mod_exp(sign_data
, 64, md5_final
, 64, (char*)g_ppk_n
, 64,
1590 (char*)g_ppk_d
, 64);
1592 rdssl_md5_info_delete(md5
);
1595 return memcmp(sign_data
, sign_data2
, sign_len2
);
1598 /*****************************************************************************/
1599 PCCERT_CONTEXT
rdssl_cert_read(uint8
* data
, uint32 len
)
1604 error("rdssl_cert_read %p %ld\n", data
, len
);
1607 res
= CertCreateCertificateContext(X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
, data
, len
);
1610 error("CertCreateCertificateContext call failed with %lx\n", GetLastError());
1615 /*****************************************************************************/
1616 void rdssl_cert_free(PCCERT_CONTEXT context
)
1619 CertFreeCertificateContext(context
);
1622 /*****************************************************************************/
1623 uint8
*rdssl_cert_to_rkey(PCCERT_CONTEXT cert
, uint32
* key_len
)
1625 HCRYPTPROV hCryptProv
;
1629 DWORD dwSize
, dwErr
;
1630 ret
= CryptAcquireContext(&hCryptProv
,
1637 dwErr
= GetLastError();
1638 error("CryptAcquireContext call failed with %lx\n", dwErr
);
1641 ret
= CryptImportPublicKeyInfoEx(hCryptProv
,
1642 X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
,
1643 &(cert
->pCertInfo
->SubjectPublicKeyInfo
),
1650 dwErr
= GetLastError();
1651 CryptReleaseContext(hCryptProv
, 0);
1652 error("CryptImportPublicKeyInfoEx call failed with %lx\n", dwErr
);
1655 ret
= CryptExportKey(hKey
,
1663 dwErr
= GetLastError();
1664 CryptDestroyKey(hKey
);
1665 CryptReleaseContext(hCryptProv
, 0);
1666 error("CryptExportKey call failed with %lx\n", dwErr
);
1669 rkey
= g_malloc(dwSize
, 0);
1670 ret
= CryptExportKey(hKey
,
1678 dwErr
= GetLastError();
1680 CryptDestroyKey(hKey
);
1681 CryptReleaseContext(hCryptProv
, 0);
1682 error("CryptExportKey call failed with %lx\n", dwErr
);
1685 CryptDestroyKey(hKey
);
1686 CryptReleaseContext(hCryptProv
, 0);
1690 /*****************************************************************************/
1691 RD_BOOL
rdssl_certs_ok(PCCERT_CONTEXT server_cert
, PCCERT_CONTEXT cacert
)
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
,
1700 error("CertVerifySubjectCertificateContext call failed with %lx\n", GetLastError());
1704 error("CertVerifySubjectCertificateContext check failed %lx\n", dwFlags
);
1706 return (dwFlags
== 0);
1709 /*****************************************************************************/
1710 int rdssl_rkey_get_exp_mod(uint8
* rkey
, uint8
* exponent
, uint32 max_exp_len
, uint8
* modulus
,
1713 RSAPUBKEY
*desc
= (RSAPUBKEY
*)(rkey
+ sizeof(PUBLICKEYSTRUC
));
1714 if (!rkey
|| !exponent
|| !max_exp_len
|| !modulus
|| !max_mod_len
)
1716 error("rdssl_rkey_get_exp_mod %p %p %ld %p %ld\n", rkey
, exponent
, max_exp_len
, modulus
, max_mod_len
);
1719 memcpy (exponent
, &desc
->pubexp
, max_exp_len
);
1720 memcpy (modulus
, rkey
+ sizeof(PUBLICKEYSTRUC
) + sizeof(RSAPUBKEY
), max_mod_len
);
1724 /*****************************************************************************/
1725 void rdssl_rkey_free(uint8
* rkey
)
1729 error("rdssl_rkey_free rkey is null\n");