e477781c4e8235dc023f89fbeae113e39785477e
[u/mdw/putty] / 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 }