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