Pedantry patch from RDB: sanitise header use, correct one comment
[u/mdw/putty] / mscrypto.c
CommitLineData
dc3c8261 1#error "This file is no longer part of PuTTY, it will not compile."
8f203108 2#define _WIN32_WINNT 0x0400
3#include <windows.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <wincrypt.h>
7#include "ssh.h"
8
9void fatalbox(char *fmt, ...);
10
11static HCRYPTKEY create_des_key(unsigned char *key);
12
13
14HCRYPTPROV hCryptProv;
32874aea 15HCRYPTKEY hDESKey[2][3] = { {0, 0, 0}, {0, 0, 0} }; /* global for now */
8f203108 16
17
18/* use Microsoft Enhanced Cryptographic Service Provider */
19#define CSP MS_ENHANCED_PROV
20
21
32874aea 22static BYTE PrivateKeyWithExponentOfOne[] = {
8f203108 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
32874aea 76int crypto_startup()
77{
78 if (CryptAcquireContext(&hCryptProv, "Putty", CSP, PROV_RSA_FULL,
79 CRYPT_NEWKEYSET) == 0) {
80 if (GetLastError() == NTE_EXISTS) {
81 if (CryptAcquireContext(&hCryptProv, "Putty", CSP,
82 PROV_RSA_FULL, 0) == 0) {
83 return FALSE; /* failed to acquire context - probably
84 * don't have high encryption installed! */
8f203108 85 }
86 } else
32874aea 87 return FALSE; /* failed to acquire context - probably
88 * don't have high encryption installed! */
8f203108 89 }
90 return TRUE;
91}
92
93
32874aea 94void crypto_wrapup()
95{
8f203108 96 int i, j;
32874aea 97 for (i = 0; i < 2; i++) {
98 for (j = 0; j < 3; j++) {
99 if (hDESKey[i][j])
8f203108 100 CryptDestroyKey(hDESKey[i][j]);
101 hDESKey[i][j] = 0;
102 }
103 }
32874aea 104 if (hCryptProv)
8f203108 105 CryptReleaseContext(hCryptProv, 0);
106 hCryptProv = 0;
107}
108
109
110/* ---------------------------------------------------------*
111 * Random number functions *
112 * ---------------------------------------------------------*/
113
32874aea 114int random_byte(void)
115{
8f203108 116 unsigned char b;
32874aea 117 if (!CryptGenRandom(hCryptProv, 1, &b))
8f203108 118 fatalbox("random number generator failure!");
119 return b;
120}
121
32874aea 122void random_add_noise(void *noise, int length)
123{
8f203108 124 /* do nothing */
125}
32874aea 126void random_init(void)
127{
8f203108 128 /* do nothing */
129}
32874aea 130void random_get_savedata(void **data, int *len)
131{
8f203108 132 /* do nothing */
133}
32874aea 134void noise_get_heavy(void (*func) (void *, int))
135{
8f203108 136 /* do nothing */
137}
32874aea 138void noise_get_light(void (*func) (void *, int))
139{
8f203108 140 /* do nothing */
141}
32874aea 142void noise_ultralight(DWORD data)
143{
8f203108 144 /* do nothing */
145}
32874aea 146void random_save_seed(void)
147{
8f203108 148 /* do nothing */
149}
150
151
152/* ---------------------------------------------------------*
153 * MD5 hash functions *
154 * ---------------------------------------------------------*/
155
156
32874aea 157void MD5Init(struct MD5Context *ctx)
158{
159 if (!CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &ctx->hHash))
8f203108 160 fatalbox("Error during CryptBeginHash!\n");
161}
162
163
164void MD5Update(struct MD5Context *ctx,
32874aea 165 unsigned char const *buf, unsigned len)
166{
167 if (CryptHashData(ctx->hHash, buf, len, 0) == 0)
8f203108 168 fatalbox("Error during CryptHashSessionKey!\n");
169}
170
171
32874aea 172void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
173{
8f203108 174 DWORD cb = 16;
32874aea 175 if (CryptGetHashParam(ctx->hHash, HP_HASHVAL, digest, &cb, 0) == 0)
8f203108 176 fatalbox("Error during CryptGetHashParam!\n");
32874aea 177 if (ctx->hHash)
8f203108 178 CryptDestroyHash(ctx->hHash);
179 ctx->hHash = 0;
180}
181
182
183/* ---------------------------------------------------------*
184 * RSA public key functions *
185 * ---------------------------------------------------------*/
186
187int makekey(unsigned char *data, struct RSAKey *result,
32874aea 188 unsigned char **keystr)
189{
8f203108 190
191 unsigned char *p = data;
192 int i;
193 int w, b;
194
195 /* get size (bits) of modulus */
196 result->bits = 0;
32874aea 197 for (i = 0; i < 4; i++)
8f203108 198 result->bits = (result->bits << 8) + *p++;
199
200 /* get size (bits) of public exponent */
201 w = 0;
32874aea 202 for (i = 0; i < 2; i++)
8f203108 203 w = (w << 8) + *p++;
32874aea 204 b = (w + 7) / 8; /* bits -> bytes */
8f203108 205
206 /* convert exponent to DWORD */
207 result->exponent = 0;
32874aea 208 for (i = 0; i < b; i++)
8f203108 209 result->exponent = (result->exponent << 8) + *p++;
210
211 /* get size (bits) of modulus */
212 w = 0;
32874aea 213 for (i = 0; i < 2; i++)
8f203108 214 w = (w << 8) + *p++;
32874aea 215 result->bytes = b = (w + 7) / 8; /* bits -> bytes */
8f203108 216
217 /* allocate buffer for modulus & copy it */
218 result->modulus = malloc(b);
219 memcpy(result->modulus, p, b);
220
221 /* update callers pointer */
32874aea 222 if (keystr)
223 *keystr = p; /* point at key string, second time */
8f203108 224
225 return (p - data) + b;
226}
227
228
32874aea 229void rsaencrypt(unsigned char *data, int length, struct RSAKey *rsakey)
230{
8f203108 231
232 int i;
233 unsigned char *pKeybuf, *pKeyin;
234 HCRYPTKEY hRsaKey;
235 PUBLICKEYSTRUC *pBlob;
236 RSAPUBKEY *pRPK;
237 unsigned char *buf;
238 DWORD dlen;
239 DWORD bufsize;
240
241 /* allocate buffer for public key blob */
32874aea 242 if ((pBlob = malloc(sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) +
243 rsakey->bytes)) == NULL)
8f203108 244 fatalbox("Out of memory");
245
246 /* allocate buffer for message encryption block */
247 bufsize = (length + rsakey->bytes) << 1;
32874aea 248 if ((buf = malloc(bufsize)) == NULL)
8f203108 249 fatalbox("Out of memory");
250
251 /* construct public key blob from host public key */
32874aea 252 pKeybuf = ((unsigned char *) pBlob) + sizeof(PUBLICKEYSTRUC) +
8f203108 253 sizeof(RSAPUBKEY);
32874aea 254 pKeyin = ((unsigned char *) rsakey->modulus);
8f203108 255 /* change big endian to little endian */
32874aea 256 for (i = 0; i < rsakey->bytes; i++)
257 pKeybuf[i] = pKeyin[rsakey->bytes - i - 1];
8f203108 258 pBlob->bType = PUBLICKEYBLOB;
259 pBlob->bVersion = 0x02;
260 pBlob->reserved = 0;
261 pBlob->aiKeyAlg = CALG_RSA_KEYX;
32874aea 262 pRPK =
263 (RSAPUBKEY *) (((unsigned char *) pBlob) + sizeof(PUBLICKEYSTRUC));
264 pRPK->magic = 0x31415352; /* "RSA1" */
8f203108 265 pRPK->bitlen = rsakey->bits;
266 pRPK->pubexp = rsakey->exponent;
267
268 /* import public key blob into key container */
32874aea 269 if (CryptImportKey(hCryptProv, (void *) pBlob,
270 sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) +
271 rsakey->bytes, 0, 0, &hRsaKey) == 0)
8f203108 272 fatalbox("Error importing RSA key!");
273
274 /* copy message into buffer */
275 memcpy(buf, data, length);
276 dlen = length;
277
278 /* using host public key, encrypt the message */
32874aea 279 if (CryptEncrypt(hRsaKey, 0, TRUE, 0, buf, &dlen, bufsize) == 0)
8f203108 280 fatalbox("Error encrypting using RSA key!");
281
282 /*
283 * For some strange reason, Microsoft CryptEncrypt using public
284 * key, returns the cyphertext in backwards (little endian)
285 * order, so reverse it!
286 */
32874aea 287 for (i = 0; i < (int) dlen; i++)
288 data[i] = buf[dlen - i - 1]; /* make it big endian */
8f203108 289
290 CryptDestroyKey(hRsaKey);
291 free(buf);
292 free(pBlob);
293
294}
295
296
32874aea 297int rsastr_len(struct RSAKey *key)
298{
8f203108 299 return 2 * (sizeof(DWORD) + key->bytes) + 10;
300}
301
302
32874aea 303void rsastr_fmt(char *str, struct RSAKey *key)
304{
8f203108 305
306 int len = 0, i;
307
32874aea 308 sprintf(str + len, "%04x", key->exponent);
309 len += strlen(str + len);
8f203108 310
311 str[len++] = '/';
32874aea 312 for (i = 1; i < key->bytes; i++) {
313 sprintf(str + len, "%02x", key->modulus[i]);
314 len += strlen(str + len);
8f203108 315 }
316 str[len] = '\0';
317}
318
319
320
321/* ---------------------------------------------------------*
322 * DES encryption / decryption functions *
323 * ---------------------------------------------------------*/
324
325
32874aea 326void des3_sesskey(unsigned char *key)
327{
8f203108 328 int i, j;
32874aea 329 for (i = 0; i < 2; i++) {
330 for (j = 0; j < 3; j++) {
8f203108 331 hDESKey[i][j] = create_des_key(key + (j * 8));
332 }
333 }
334}
335
336
32874aea 337void des3_encrypt_blk(unsigned char *blk, int len)
338{
8f203108 339
340 DWORD dlen;
341 dlen = len;
342
32874aea 343 if (CryptEncrypt(hDESKey[0][0], 0, FALSE, 0, blk, &dlen, len + 8) == 0)
8f203108 344 fatalbox("Error encrypting block!\n");
32874aea 345 if (CryptDecrypt(hDESKey[0][1], 0, FALSE, 0, blk, &dlen) == 0)
8f203108 346 fatalbox("Error encrypting block!\n");
32874aea 347 if (CryptEncrypt(hDESKey[0][2], 0, FALSE, 0, blk, &dlen, len + 8) == 0)
8f203108 348 fatalbox("Error encrypting block!\n");
349}
350
351
32874aea 352void des3_decrypt_blk(unsigned char *blk, int len)
353{
8f203108 354 DWORD dlen;
355 dlen = len;
356
32874aea 357 if (CryptDecrypt(hDESKey[1][2], 0, FALSE, 0, blk, &dlen) == 0)
8f203108 358 fatalbox("Error decrypting block!\n");
32874aea 359 if (CryptEncrypt(hDESKey[1][1], 0, FALSE, 0, blk, &dlen, len + 8) == 0)
8f203108 360 fatalbox("Error decrypting block!\n");
32874aea 361 if (CryptDecrypt(hDESKey[1][0], 0, FALSE, 0, blk, &dlen) == 0)
8f203108 362 fatalbox("Error decrypting block!\n");
363}
364
365
366struct ssh_cipher ssh_3des = {
367 des3_sesskey,
368 des3_encrypt_blk,
369 des3_decrypt_blk
370};
371
372
32874aea 373void des_sesskey(unsigned char *key)
374{
8f203108 375 int i;
32874aea 376 for (i = 0; i < 2; i++) {
8f203108 377 hDESKey[i][0] = create_des_key(key);
378 }
379}
380
381
32874aea 382void des_encrypt_blk(unsigned char *blk, int len)
383{
8f203108 384 DWORD dlen;
385 dlen = len;
32874aea 386 if (CryptEncrypt(hDESKey[0][0], 0, FALSE, 0, blk, &dlen, len + 8) == 0)
8f203108 387 fatalbox("Error encrypting block!\n");
388}
389
390
32874aea 391void des_decrypt_blk(unsigned char *blk, int len)
392{
8f203108 393 DWORD dlen;
394 dlen = len;
32874aea 395 if (CryptDecrypt(hDESKey[1][0], 0, FALSE, 0, blk, &dlen) == 0)
8f203108 396 fatalbox("Error decrypting block!\n");
397}
398
399struct ssh_cipher ssh_des = {
400 des_sesskey,
401 des_encrypt_blk,
402 des_decrypt_blk
403};
404
405
32874aea 406static HCRYPTKEY create_des_key(unsigned char *key)
407{
8f203108 408
409 HCRYPTKEY hSessionKey, hPrivateKey;
410 DWORD dlen = 8;
411 BLOBHEADER *pbh;
412 char buf[sizeof(BLOBHEADER) + sizeof(ALG_ID) + 256];
413
414 /*
415 * Need special private key to encrypt session key so we can
416 * import session key, since only encrypted session keys can be
417 * imported
418 */
32874aea 419 if (CryptImportKey(hCryptProv, PrivateKeyWithExponentOfOne,
420 sizeof(PrivateKeyWithExponentOfOne),
421 0, 0, &hPrivateKey) == 0)
8f203108 422 return 0;
423
424 /* now encrypt session key using special private key */
425 memcpy(buf + sizeof(BLOBHEADER) + sizeof(ALG_ID), key, 8);
32874aea 426 if (CryptEncrypt(hPrivateKey, 0, TRUE, 0,
427 buf + sizeof(BLOBHEADER) + sizeof(ALG_ID),
428 &dlen, 256) == 0)
8f203108 429 return 0;
430
431 /* build session key blob */
32874aea 432 pbh = (BLOBHEADER *) buf;
8f203108 433 pbh->bType = SIMPLEBLOB;
434 pbh->bVersion = 0x02;
435 pbh->reserved = 0;
436 pbh->aiKeyAlg = CALG_DES;
32874aea 437 *((ALG_ID *) (buf + sizeof(BLOBHEADER))) = CALG_RSA_KEYX;
8f203108 438
439 /* import session key into key container */
32874aea 440 if (CryptImportKey(hCryptProv, buf,
441 dlen + sizeof(BLOBHEADER) + sizeof(ALG_ID),
442 hPrivateKey, 0, &hSessionKey) == 0)
8f203108 443 return 0;
444
32874aea 445 if (hPrivateKey)
8f203108 446 CryptDestroyKey(hPrivateKey);
447
448 return hSessionKey;
449
450}