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