1 #define _WIN32_WINNT 0x0400
8 void fatalbox(char *fmt, ...);
10 static HCRYPTKEY create_des_key(unsigned char *key);
13 HCRYPTPROV hCryptProv;
14 HCRYPTKEY hDESKey[2][3] = { {0, 0, 0}, {0, 0, 0} }; /* global for now */
17 /* use Microsoft Enhanced Cryptographic Service Provider */
18 #define CSP MS_ENHANCED_PROV
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,
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,
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,
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,
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,
70 /* ---------------------------------------------------------*
72 * ---------------------------------------------------------*/
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! */
86 return FALSE; /* failed to acquire context - probably
87 * don't have high encryption installed! */
96 for (i = 0; i < 2; i++) {
97 for (j = 0; j < 3; j++) {
99 CryptDestroyKey(hDESKey[i][j]);
104 CryptReleaseContext(hCryptProv, 0);
109 /* ---------------------------------------------------------*
110 * Random number functions *
111 * ---------------------------------------------------------*/
113 int random_byte(void)
116 if (!CryptGenRandom(hCryptProv, 1, &b))
117 fatalbox("random number generator failure!");
121 void random_add_noise(void *noise, int length)
125 void random_init(void)
129 void random_get_savedata(void **data, int *len)
133 void noise_get_heavy(void (*func) (void *, int))
137 void noise_get_light(void (*func) (void *, int))
141 void noise_ultralight(DWORD data)
145 void random_save_seed(void)
151 /* ---------------------------------------------------------*
152 * MD5 hash functions *
153 * ---------------------------------------------------------*/
156 void MD5Init(struct MD5Context *ctx)
158 if (!CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &ctx->hHash))
159 fatalbox("Error during CryptBeginHash!\n");
163 void MD5Update(struct MD5Context *ctx,
164 unsigned char const *buf, unsigned len)
166 if (CryptHashData(ctx->hHash, buf, len, 0) == 0)
167 fatalbox("Error during CryptHashSessionKey!\n");
171 void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
174 if (CryptGetHashParam(ctx->hHash, HP_HASHVAL, digest, &cb, 0) == 0)
175 fatalbox("Error during CryptGetHashParam!\n");
177 CryptDestroyHash(ctx->hHash);
182 /* ---------------------------------------------------------*
183 * RSA public key functions *
184 * ---------------------------------------------------------*/
186 int makekey(unsigned char *data, struct RSAKey *result,
187 unsigned char **keystr)
190 unsigned char *p = data;
194 /* get size (bits) of modulus */
196 for (i = 0; i < 4; i++)
197 result->bits = (result->bits << 8) + *p++;
199 /* get size (bits) of public exponent */
201 for (i = 0; i < 2; i++)
203 b = (w + 7) / 8; /* bits -> bytes */
205 /* convert exponent to DWORD */
206 result->exponent = 0;
207 for (i = 0; i < b; i++)
208 result->exponent = (result->exponent << 8) + *p++;
210 /* get size (bits) of modulus */
212 for (i = 0; i < 2; i++)
214 result->bytes = b = (w + 7) / 8; /* bits -> bytes */
216 /* allocate buffer for modulus & copy it */
217 result->modulus = malloc(b);
218 memcpy(result->modulus, p, b);
220 /* update callers pointer */
222 *keystr = p; /* point at key string, second time */
224 return (p - data) + b;
228 void rsaencrypt(unsigned char *data, int length, struct RSAKey *rsakey)
232 unsigned char *pKeybuf, *pKeyin;
234 PUBLICKEYSTRUC *pBlob;
240 /* allocate buffer for public key blob */
241 if ((pBlob = malloc(sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) +
242 rsakey->bytes)) == NULL)
243 fatalbox("Out of memory");
245 /* allocate buffer for message encryption block */
246 bufsize = (length + rsakey->bytes) << 1;
247 if ((buf = malloc(bufsize)) == NULL)
248 fatalbox("Out of memory");
250 /* construct public key blob from host public key */
251 pKeybuf = ((unsigned char *) pBlob) + sizeof(PUBLICKEYSTRUC) +
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;
260 pBlob->aiKeyAlg = CALG_RSA_KEYX;
262 (RSAPUBKEY *) (((unsigned char *) pBlob) + sizeof(PUBLICKEYSTRUC));
263 pRPK->magic = 0x31415352; /* "RSA1" */
264 pRPK->bitlen = rsakey->bits;
265 pRPK->pubexp = rsakey->exponent;
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!");
273 /* copy message into buffer */
274 memcpy(buf, data, length);
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!");
282 * For some strange reason, Microsoft CryptEncrypt using public
283 * key, returns the cyphertext in backwards (little endian)
284 * order, so reverse it!
286 for (i = 0; i < (int) dlen; i++)
287 data[i] = buf[dlen - i - 1]; /* make it big endian */
289 CryptDestroyKey(hRsaKey);
296 int rsastr_len(struct RSAKey *key)
298 return 2 * (sizeof(DWORD) + key->bytes) + 10;
302 void rsastr_fmt(char *str, struct RSAKey *key)
307 sprintf(str + len, "%04x", key->exponent);
308 len += strlen(str + len);
311 for (i = 1; i < key->bytes; i++) {
312 sprintf(str + len, "%02x", key->modulus[i]);
313 len += strlen(str + len);
320 /* ---------------------------------------------------------*
321 * DES encryption / decryption functions *
322 * ---------------------------------------------------------*/
325 void des3_sesskey(unsigned char *key)
328 for (i = 0; i < 2; i++) {
329 for (j = 0; j < 3; j++) {
330 hDESKey[i][j] = create_des_key(key + (j * 8));
336 void des3_encrypt_blk(unsigned char *blk, int len)
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");
351 void des3_decrypt_blk(unsigned char *blk, int len)
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");
365 struct ssh_cipher ssh_3des = {
372 void des_sesskey(unsigned char *key)
375 for (i = 0; i < 2; i++) {
376 hDESKey[i][0] = create_des_key(key);
381 void des_encrypt_blk(unsigned char *blk, int len)
385 if (CryptEncrypt(hDESKey[0][0], 0, FALSE, 0, blk, &dlen, len + 8) == 0)
386 fatalbox("Error encrypting block!\n");
390 void des_decrypt_blk(unsigned char *blk, int len)
394 if (CryptDecrypt(hDESKey[1][0], 0, FALSE, 0, blk, &dlen) == 0)
395 fatalbox("Error decrypting block!\n");
398 struct ssh_cipher ssh_des = {
405 static HCRYPTKEY create_des_key(unsigned char *key)
408 HCRYPTKEY hSessionKey, hPrivateKey;
411 char buf[sizeof(BLOBHEADER) + sizeof(ALG_ID) + 256];
414 * Need special private key to encrypt session key so we can
415 * import session key, since only encrypted session keys can be
418 if (CryptImportKey(hCryptProv, PrivateKeyWithExponentOfOne,
419 sizeof(PrivateKeyWithExponentOfOne),
420 0, 0, &hPrivateKey) == 0)
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),
430 /* build session key blob */
431 pbh = (BLOBHEADER *) buf;
432 pbh->bType = SIMPLEBLOB;
433 pbh->bVersion = 0x02;
435 pbh->aiKeyAlg = CALG_DES;
436 *((ALG_ID *) (buf + sizeof(BLOBHEADER))) = CALG_RSA_KEYX;
438 /* import session key into key container */
439 if (CryptImportKey(hCryptProv, buf,
440 dlen + sizeof(BLOBHEADER) + sizeof(ALG_ID),
441 hPrivateKey, 0, &hSessionKey) == 0)
445 CryptDestroyKey(hPrivateKey);