]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - mscrypto.c
RDB's Unicode patch. Fonts are now used in Unicode mode where
[PuTTY.git] / mscrypto.c
1 #define _WIN32_WINNT 0x0400
2 #include <windows.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <wincrypt.h>
6 #include "ssh.h"
7
8 void fatalbox(char *fmt, ...);
9
10 static HCRYPTKEY create_des_key(unsigned char *key);
11
12
13 HCRYPTPROV hCryptProv;
14 HCRYPTKEY hDESKey[2][3] = { {0, 0, 0}, {0, 0, 0} };     /* global for now */
15
16
17 /* use Microsoft Enhanced Cryptographic Service Provider */
18 #define CSP MS_ENHANCED_PROV
19
20
21 static BYTE PrivateKeyWithExponentOfOne[] = {
22     0x07, 0x02, 0x00, 0x00, 0x00, 0xA4, 0x00, 0x00,
23     0x52, 0x53, 0x41, 0x32, 0x00, 0x02, 0x00, 0x00,
24     0x01, 0x00, 0x00, 0x00, 0xAB, 0xEF, 0xFA, 0xC6,
25     0x7D, 0xE8, 0xDE, 0xFB, 0x68, 0x38, 0x09, 0x92,
26     0xD9, 0x42, 0x7E, 0x6B, 0x89, 0x9E, 0x21, 0xD7,
27     0x52, 0x1C, 0x99, 0x3C, 0x17, 0x48, 0x4E, 0x3A,
28     0x44, 0x02, 0xF2, 0xFA, 0x74, 0x57, 0xDA, 0xE4,
29     0xD3, 0xC0, 0x35, 0x67, 0xFA, 0x6E, 0xDF, 0x78,
30     0x4C, 0x75, 0x35, 0x1C, 0xA0, 0x74, 0x49, 0xE3,
31     0x20, 0x13, 0x71, 0x35, 0x65, 0xDF, 0x12, 0x20,
32     0xF5, 0xF5, 0xF5, 0xC1, 0xED, 0x5C, 0x91, 0x36,
33     0x75, 0xB0, 0xA9, 0x9C, 0x04, 0xDB, 0x0C, 0x8C,
34     0xBF, 0x99, 0x75, 0x13, 0x7E, 0x87, 0x80, 0x4B,
35     0x71, 0x94, 0xB8, 0x00, 0xA0, 0x7D, 0xB7, 0x53,
36     0xDD, 0x20, 0x63, 0xEE, 0xF7, 0x83, 0x41, 0xFE,
37     0x16, 0xA7, 0x6E, 0xDF, 0x21, 0x7D, 0x76, 0xC0,
38     0x85, 0xD5, 0x65, 0x7F, 0x00, 0x23, 0x57, 0x45,
39     0x52, 0x02, 0x9D, 0xEA, 0x69, 0xAC, 0x1F, 0xFD,
40     0x3F, 0x8C, 0x4A, 0xD0,
41
42     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
43     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
44     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
45     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
46
47     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
48     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
50     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51
52     0x64, 0xD5, 0xAA, 0xB1,
53     0xA6, 0x03, 0x18, 0x92, 0x03, 0xAA, 0x31, 0x2E,
54     0x48, 0x4B, 0x65, 0x20, 0x99, 0xCD, 0xC6, 0x0C,
55     0x15, 0x0C, 0xBF, 0x3E, 0xFF, 0x78, 0x95, 0x67,
56     0xB1, 0x74, 0x5B, 0x60,
57
58     0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66 };
67
68
69
70 /* ---------------------------------------------------------*
71  * Utility functions                                        *
72  * ---------------------------------------------------------*/
73
74
75 int crypto_startup()
76 {
77     if (CryptAcquireContext(&hCryptProv, "Putty", CSP, PROV_RSA_FULL,
78                             CRYPT_NEWKEYSET) == 0) {
79         if (GetLastError() == NTE_EXISTS) {
80             if (CryptAcquireContext(&hCryptProv, "Putty", CSP,
81                                     PROV_RSA_FULL, 0) == 0) {
82                 return FALSE;          /* failed to acquire context - probably
83                                         * don't have high encryption installed! */
84             }
85         } else
86             return FALSE;              /* failed to acquire context - probably
87                                         * don't have high encryption installed! */
88     }
89     return TRUE;
90 }
91
92
93 void crypto_wrapup()
94 {
95     int i, j;
96     for (i = 0; i < 2; i++) {
97         for (j = 0; j < 3; j++) {
98             if (hDESKey[i][j])
99                 CryptDestroyKey(hDESKey[i][j]);
100             hDESKey[i][j] = 0;
101         }
102     }
103     if (hCryptProv)
104         CryptReleaseContext(hCryptProv, 0);
105     hCryptProv = 0;
106 }
107
108
109 /* ---------------------------------------------------------*
110  * Random number functions                                  *
111  * ---------------------------------------------------------*/
112
113 int random_byte(void)
114 {
115     unsigned char b;
116     if (!CryptGenRandom(hCryptProv, 1, &b))
117         fatalbox("random number generator failure!");
118     return b;
119 }
120
121 void random_add_noise(void *noise, int length)
122 {
123     /* do nothing */
124 }
125 void random_init(void)
126 {
127     /* do nothing */
128 }
129 void random_get_savedata(void **data, int *len)
130 {
131     /* do nothing */
132 }
133 void noise_get_heavy(void (*func) (void *, int))
134 {
135     /* do nothing */
136 }
137 void noise_get_light(void (*func) (void *, int))
138 {
139     /* do nothing */
140 }
141 void noise_ultralight(DWORD data)
142 {
143     /* do nothing */
144 }
145 void random_save_seed(void)
146 {
147     /* do nothing */
148 }
149
150
151 /* ---------------------------------------------------------*
152  * MD5 hash functions                                       *
153  * ---------------------------------------------------------*/
154
155
156 void MD5Init(struct MD5Context *ctx)
157 {
158     if (!CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &ctx->hHash))
159         fatalbox("Error during CryptBeginHash!\n");
160 }
161
162
163 void MD5Update(struct MD5Context *ctx,
164                unsigned char const *buf, unsigned len)
165 {
166     if (CryptHashData(ctx->hHash, buf, len, 0) == 0)
167         fatalbox("Error during CryptHashSessionKey!\n");
168 }
169
170
171 void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
172 {
173     DWORD cb = 16;
174     if (CryptGetHashParam(ctx->hHash, HP_HASHVAL, digest, &cb, 0) == 0)
175         fatalbox("Error during CryptGetHashParam!\n");
176     if (ctx->hHash)
177         CryptDestroyHash(ctx->hHash);
178     ctx->hHash = 0;
179 }
180
181
182 /* ---------------------------------------------------------*
183  * RSA public key functions                                 *
184  * ---------------------------------------------------------*/
185
186 int makekey(unsigned char *data, struct RSAKey *result,
187             unsigned char **keystr)
188 {
189
190     unsigned char *p = data;
191     int i;
192     int w, b;
193
194     /* get size (bits) of modulus */
195     result->bits = 0;
196     for (i = 0; i < 4; i++)
197         result->bits = (result->bits << 8) + *p++;
198
199     /* get size (bits) of public exponent */
200     w = 0;
201     for (i = 0; i < 2; i++)
202         w = (w << 8) + *p++;
203     b = (w + 7) / 8;                   /* bits -> bytes */
204
205     /* convert exponent to DWORD */
206     result->exponent = 0;
207     for (i = 0; i < b; i++)
208         result->exponent = (result->exponent << 8) + *p++;
209
210     /* get size (bits) of modulus */
211     w = 0;
212     for (i = 0; i < 2; i++)
213         w = (w << 8) + *p++;
214     result->bytes = b = (w + 7) / 8;   /* bits -> bytes */
215
216     /* allocate buffer for modulus & copy it */
217     result->modulus = malloc(b);
218     memcpy(result->modulus, p, b);
219
220     /* update callers pointer */
221     if (keystr)
222         *keystr = p;                   /* point at key string, second time */
223
224     return (p - data) + b;
225 }
226
227
228 void rsaencrypt(unsigned char *data, int length, struct RSAKey *rsakey)
229 {
230
231     int i;
232     unsigned char *pKeybuf, *pKeyin;
233     HCRYPTKEY hRsaKey;
234     PUBLICKEYSTRUC *pBlob;
235     RSAPUBKEY *pRPK;
236     unsigned char *buf;
237     DWORD dlen;
238     DWORD bufsize;
239
240     /* allocate buffer for public key blob */
241     if ((pBlob = malloc(sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) +
242                         rsakey->bytes)) == NULL)
243         fatalbox("Out of memory");
244
245     /* allocate buffer for message encryption block */
246     bufsize = (length + rsakey->bytes) << 1;
247     if ((buf = malloc(bufsize)) == NULL)
248         fatalbox("Out of memory");
249
250     /* construct public key blob from host public key */
251     pKeybuf = ((unsigned char *) pBlob) + sizeof(PUBLICKEYSTRUC) +
252         sizeof(RSAPUBKEY);
253     pKeyin = ((unsigned char *) rsakey->modulus);
254     /* change big endian to little endian */
255     for (i = 0; i < rsakey->bytes; i++)
256         pKeybuf[i] = pKeyin[rsakey->bytes - i - 1];
257     pBlob->bType = PUBLICKEYBLOB;
258     pBlob->bVersion = 0x02;
259     pBlob->reserved = 0;
260     pBlob->aiKeyAlg = CALG_RSA_KEYX;
261     pRPK =
262         (RSAPUBKEY *) (((unsigned char *) pBlob) + sizeof(PUBLICKEYSTRUC));
263     pRPK->magic = 0x31415352;          /* "RSA1" */
264     pRPK->bitlen = rsakey->bits;
265     pRPK->pubexp = rsakey->exponent;
266
267     /* import public key blob into key container */
268     if (CryptImportKey(hCryptProv, (void *) pBlob,
269                        sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) +
270                        rsakey->bytes, 0, 0, &hRsaKey) == 0)
271         fatalbox("Error importing RSA key!");
272
273     /* copy message into buffer */
274     memcpy(buf, data, length);
275     dlen = length;
276
277     /* using host public key, encrypt the message */
278     if (CryptEncrypt(hRsaKey, 0, TRUE, 0, buf, &dlen, bufsize) == 0)
279         fatalbox("Error encrypting using RSA key!");
280
281     /*
282      * For some strange reason, Microsoft CryptEncrypt using public
283      * key, returns the cyphertext in backwards (little endian)
284      * order, so reverse it!
285      */
286     for (i = 0; i < (int) dlen; i++)
287         data[i] = buf[dlen - i - 1];   /* make it big endian */
288
289     CryptDestroyKey(hRsaKey);
290     free(buf);
291     free(pBlob);
292
293 }
294
295
296 int rsastr_len(struct RSAKey *key)
297 {
298     return 2 * (sizeof(DWORD) + key->bytes) + 10;
299 }
300
301
302 void rsastr_fmt(char *str, struct RSAKey *key)
303 {
304
305     int len = 0, i;
306
307     sprintf(str + len, "%04x", key->exponent);
308     len += strlen(str + len);
309
310     str[len++] = '/';
311     for (i = 1; i < key->bytes; i++) {
312         sprintf(str + len, "%02x", key->modulus[i]);
313         len += strlen(str + len);
314     }
315     str[len] = '\0';
316 }
317
318
319
320 /* ---------------------------------------------------------*
321  * DES encryption / decryption functions                    *
322  * ---------------------------------------------------------*/
323
324
325 void des3_sesskey(unsigned char *key)
326 {
327     int i, j;
328     for (i = 0; i < 2; i++) {
329         for (j = 0; j < 3; j++) {
330             hDESKey[i][j] = create_des_key(key + (j * 8));
331         }
332     }
333 }
334
335
336 void des3_encrypt_blk(unsigned char *blk, int len)
337 {
338
339     DWORD dlen;
340     dlen = len;
341
342     if (CryptEncrypt(hDESKey[0][0], 0, FALSE, 0, blk, &dlen, len + 8) == 0)
343         fatalbox("Error encrypting block!\n");
344     if (CryptDecrypt(hDESKey[0][1], 0, FALSE, 0, blk, &dlen) == 0)
345         fatalbox("Error encrypting block!\n");
346     if (CryptEncrypt(hDESKey[0][2], 0, FALSE, 0, blk, &dlen, len + 8) == 0)
347         fatalbox("Error encrypting block!\n");
348 }
349
350
351 void des3_decrypt_blk(unsigned char *blk, int len)
352 {
353     DWORD dlen;
354     dlen = len;
355
356     if (CryptDecrypt(hDESKey[1][2], 0, FALSE, 0, blk, &dlen) == 0)
357         fatalbox("Error decrypting block!\n");
358     if (CryptEncrypt(hDESKey[1][1], 0, FALSE, 0, blk, &dlen, len + 8) == 0)
359         fatalbox("Error decrypting block!\n");
360     if (CryptDecrypt(hDESKey[1][0], 0, FALSE, 0, blk, &dlen) == 0)
361         fatalbox("Error decrypting block!\n");
362 }
363
364
365 struct ssh_cipher ssh_3des = {
366     des3_sesskey,
367     des3_encrypt_blk,
368     des3_decrypt_blk
369 };
370
371
372 void des_sesskey(unsigned char *key)
373 {
374     int i;
375     for (i = 0; i < 2; i++) {
376         hDESKey[i][0] = create_des_key(key);
377     }
378 }
379
380
381 void des_encrypt_blk(unsigned char *blk, int len)
382 {
383     DWORD dlen;
384     dlen = len;
385     if (CryptEncrypt(hDESKey[0][0], 0, FALSE, 0, blk, &dlen, len + 8) == 0)
386         fatalbox("Error encrypting block!\n");
387 }
388
389
390 void des_decrypt_blk(unsigned char *blk, int len)
391 {
392     DWORD dlen;
393     dlen = len;
394     if (CryptDecrypt(hDESKey[1][0], 0, FALSE, 0, blk, &dlen) == 0)
395         fatalbox("Error decrypting block!\n");
396 }
397
398 struct ssh_cipher ssh_des = {
399     des_sesskey,
400     des_encrypt_blk,
401     des_decrypt_blk
402 };
403
404
405 static HCRYPTKEY create_des_key(unsigned char *key)
406 {
407
408     HCRYPTKEY hSessionKey, hPrivateKey;
409     DWORD dlen = 8;
410     BLOBHEADER *pbh;
411     char buf[sizeof(BLOBHEADER) + sizeof(ALG_ID) + 256];
412
413     /*
414      * Need special private key to encrypt session key so we can
415      * import session key, since only encrypted session keys can be
416      * imported
417      */
418     if (CryptImportKey(hCryptProv, PrivateKeyWithExponentOfOne,
419                        sizeof(PrivateKeyWithExponentOfOne),
420                        0, 0, &hPrivateKey) == 0)
421         return 0;
422
423     /* now encrypt session key using special private key */
424     memcpy(buf + sizeof(BLOBHEADER) + sizeof(ALG_ID), key, 8);
425     if (CryptEncrypt(hPrivateKey, 0, TRUE, 0,
426                      buf + sizeof(BLOBHEADER) + sizeof(ALG_ID),
427                      &dlen, 256) == 0)
428         return 0;
429
430     /* build session key blob */
431     pbh = (BLOBHEADER *) buf;
432     pbh->bType = SIMPLEBLOB;
433     pbh->bVersion = 0x02;
434     pbh->reserved = 0;
435     pbh->aiKeyAlg = CALG_DES;
436     *((ALG_ID *) (buf + sizeof(BLOBHEADER))) = CALG_RSA_KEYX;
437
438     /* import session key into key container */
439     if (CryptImportKey(hCryptProv, buf,
440                        dlen + sizeof(BLOBHEADER) + sizeof(ALG_ID),
441                        hPrivateKey, 0, &hSessionKey) == 0)
442         return 0;
443
444     if (hPrivateKey)
445         CryptDestroyKey(hPrivateKey);
446
447     return hSessionKey;
448
449 }