1 #error "This file is no longer part of PuTTY, it will not compile."
2 #define _WIN32_WINNT 0x0400
9 void fatalbox(char *fmt
, ...);
11 static HCRYPTKEY
create_des_key(unsigned char *key
);
14 HCRYPTPROV hCryptProv
;
15 HCRYPTKEY hDESKey
[2][3] = { {0, 0, 0}, {0, 0, 0} }; /* global for now */
18 /* use Microsoft Enhanced Cryptographic Service Provider */
19 #define CSP MS_ENHANCED_PROV
22 static BYTE PrivateKeyWithExponentOfOne
[] = {
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,
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,
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,
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,
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,
71 /* ---------------------------------------------------------*
73 * ---------------------------------------------------------*/
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! */
87 return FALSE
; /* failed to acquire context - probably
88 * don't have high encryption installed! */
97 for (i
= 0; i
< 2; i
++) {
98 for (j
= 0; j
< 3; j
++) {
100 CryptDestroyKey(hDESKey
[i
][j
]);
105 CryptReleaseContext(hCryptProv
, 0);
110 /* ---------------------------------------------------------*
111 * Random number functions *
112 * ---------------------------------------------------------*/
114 int random_byte(void)
117 if (!CryptGenRandom(hCryptProv
, 1, &b
))
118 fatalbox("random number generator failure!");
122 void random_add_noise(void *noise
, int length
)
126 void random_init(void)
130 void random_get_savedata(void **data
, int *len
)
134 void noise_get_heavy(void (*func
) (void *, int))
138 void noise_get_light(void (*func
) (void *, int))
142 void noise_ultralight(DWORD data
)
146 void random_save_seed(void)
152 /* ---------------------------------------------------------*
153 * MD5 hash functions *
154 * ---------------------------------------------------------*/
157 void MD5Init(struct MD5Context
*ctx
)
159 if (!CryptCreateHash(hCryptProv
, CALG_MD5
, 0, 0, &ctx
->hHash
))
160 fatalbox("Error during CryptBeginHash!\n");
164 void MD5Update(struct MD5Context
*ctx
,
165 unsigned char const *buf
, unsigned len
)
167 if (CryptHashData(ctx
->hHash
, buf
, len
, 0) == 0)
168 fatalbox("Error during CryptHashSessionKey!\n");
172 void MD5Final(unsigned char digest
[16], struct MD5Context
*ctx
)
175 if (CryptGetHashParam(ctx
->hHash
, HP_HASHVAL
, digest
, &cb
, 0) == 0)
176 fatalbox("Error during CryptGetHashParam!\n");
178 CryptDestroyHash(ctx
->hHash
);
183 /* ---------------------------------------------------------*
184 * RSA public key functions *
185 * ---------------------------------------------------------*/
187 int makekey(unsigned char *data
, struct RSAKey
*result
,
188 unsigned char **keystr
)
191 unsigned char *p
= data
;
195 /* get size (bits) of modulus */
197 for (i
= 0; i
< 4; i
++)
198 result
->bits
= (result
->bits
<< 8) + *p
++;
200 /* get size (bits) of public exponent */
202 for (i
= 0; i
< 2; i
++)
204 b
= (w
+ 7) / 8; /* bits -> bytes */
206 /* convert exponent to DWORD */
207 result
->exponent
= 0;
208 for (i
= 0; i
< b
; i
++)
209 result
->exponent
= (result
->exponent
<< 8) + *p
++;
211 /* get size (bits) of modulus */
213 for (i
= 0; i
< 2; i
++)
215 result
->bytes
= b
= (w
+ 7) / 8; /* bits -> bytes */
217 /* allocate buffer for modulus & copy it */
218 result
->modulus
= malloc(b
);
219 memcpy(result
->modulus
, p
, b
);
221 /* update callers pointer */
223 *keystr
= p
; /* point at key string, second time */
225 return (p
- data
) + b
;
229 void rsaencrypt(unsigned char *data
, int length
, struct RSAKey
*rsakey
)
233 unsigned char *pKeybuf
, *pKeyin
;
235 PUBLICKEYSTRUC
*pBlob
;
241 /* allocate buffer for public key blob */
242 if ((pBlob
= malloc(sizeof(PUBLICKEYSTRUC
) + sizeof(RSAPUBKEY
) +
243 rsakey
->bytes
)) == NULL
)
244 fatalbox("Out of memory");
246 /* allocate buffer for message encryption block */
247 bufsize
= (length
+ rsakey
->bytes
) << 1;
248 if ((buf
= malloc(bufsize
)) == NULL
)
249 fatalbox("Out of memory");
251 /* construct public key blob from host public key */
252 pKeybuf
= ((unsigned char *) pBlob
) + sizeof(PUBLICKEYSTRUC
) +
254 pKeyin
= ((unsigned char *) rsakey
->modulus
);
255 /* change big endian to little endian */
256 for (i
= 0; i
< rsakey
->bytes
; i
++)
257 pKeybuf
[i
] = pKeyin
[rsakey
->bytes
- i
- 1];
258 pBlob
->bType
= PUBLICKEYBLOB
;
259 pBlob
->bVersion
= 0x02;
261 pBlob
->aiKeyAlg
= CALG_RSA_KEYX
;
263 (RSAPUBKEY
*) (((unsigned char *) pBlob
) + sizeof(PUBLICKEYSTRUC
));
264 pRPK
->magic
= 0x31415352; /* "RSA1" */
265 pRPK
->bitlen
= rsakey
->bits
;
266 pRPK
->pubexp
= rsakey
->exponent
;
268 /* import public key blob into key container */
269 if (CryptImportKey(hCryptProv
, (void *) pBlob
,
270 sizeof(PUBLICKEYSTRUC
) + sizeof(RSAPUBKEY
) +
271 rsakey
->bytes
, 0, 0, &hRsaKey
) == 0)
272 fatalbox("Error importing RSA key!");
274 /* copy message into buffer */
275 memcpy(buf
, data
, length
);
278 /* using host public key, encrypt the message */
279 if (CryptEncrypt(hRsaKey
, 0, TRUE
, 0, buf
, &dlen
, bufsize
) == 0)
280 fatalbox("Error encrypting using RSA key!");
283 * For some strange reason, Microsoft CryptEncrypt using public
284 * key, returns the cyphertext in backwards (little endian)
285 * order, so reverse it!
287 for (i
= 0; i
< (int) dlen
; i
++)
288 data
[i
] = buf
[dlen
- i
- 1]; /* make it big endian */
290 CryptDestroyKey(hRsaKey
);
297 int rsastr_len(struct RSAKey
*key
)
299 return 2 * (sizeof(DWORD
) + key
->bytes
) + 10;
303 void rsastr_fmt(char *str
, struct RSAKey
*key
)
308 sprintf(str
+ len
, "%04x", key
->exponent
);
309 len
+= strlen(str
+ len
);
312 for (i
= 1; i
< key
->bytes
; i
++) {
313 sprintf(str
+ len
, "%02x", key
->modulus
[i
]);
314 len
+= strlen(str
+ len
);
321 /* ---------------------------------------------------------*
322 * DES encryption / decryption functions *
323 * ---------------------------------------------------------*/
326 void des3_sesskey(unsigned char *key
)
329 for (i
= 0; i
< 2; i
++) {
330 for (j
= 0; j
< 3; j
++) {
331 hDESKey
[i
][j
] = create_des_key(key
+ (j
* 8));
337 void des3_encrypt_blk(unsigned char *blk
, int len
)
343 if (CryptEncrypt(hDESKey
[0][0], 0, FALSE
, 0, blk
, &dlen
, len
+ 8) == 0)
344 fatalbox("Error encrypting block!\n");
345 if (CryptDecrypt(hDESKey
[0][1], 0, FALSE
, 0, blk
, &dlen
) == 0)
346 fatalbox("Error encrypting block!\n");
347 if (CryptEncrypt(hDESKey
[0][2], 0, FALSE
, 0, blk
, &dlen
, len
+ 8) == 0)
348 fatalbox("Error encrypting block!\n");
352 void des3_decrypt_blk(unsigned char *blk
, int len
)
357 if (CryptDecrypt(hDESKey
[1][2], 0, FALSE
, 0, blk
, &dlen
) == 0)
358 fatalbox("Error decrypting block!\n");
359 if (CryptEncrypt(hDESKey
[1][1], 0, FALSE
, 0, blk
, &dlen
, len
+ 8) == 0)
360 fatalbox("Error decrypting block!\n");
361 if (CryptDecrypt(hDESKey
[1][0], 0, FALSE
, 0, blk
, &dlen
) == 0)
362 fatalbox("Error decrypting block!\n");
366 struct ssh_cipher ssh_3des
= {
373 void des_sesskey(unsigned char *key
)
376 for (i
= 0; i
< 2; i
++) {
377 hDESKey
[i
][0] = create_des_key(key
);
382 void des_encrypt_blk(unsigned char *blk
, int len
)
386 if (CryptEncrypt(hDESKey
[0][0], 0, FALSE
, 0, blk
, &dlen
, len
+ 8) == 0)
387 fatalbox("Error encrypting block!\n");
391 void des_decrypt_blk(unsigned char *blk
, int len
)
395 if (CryptDecrypt(hDESKey
[1][0], 0, FALSE
, 0, blk
, &dlen
) == 0)
396 fatalbox("Error decrypting block!\n");
399 struct ssh_cipher ssh_des
= {
406 static HCRYPTKEY
create_des_key(unsigned char *key
)
409 HCRYPTKEY hSessionKey
, hPrivateKey
;
412 char buf
[sizeof(BLOBHEADER
) + sizeof(ALG_ID
) + 256];
415 * Need special private key to encrypt session key so we can
416 * import session key, since only encrypted session keys can be
419 if (CryptImportKey(hCryptProv
, PrivateKeyWithExponentOfOne
,
420 sizeof(PrivateKeyWithExponentOfOne
),
421 0, 0, &hPrivateKey
) == 0)
424 /* now encrypt session key using special private key */
425 memcpy(buf
+ sizeof(BLOBHEADER
) + sizeof(ALG_ID
), key
, 8);
426 if (CryptEncrypt(hPrivateKey
, 0, TRUE
, 0,
427 buf
+ sizeof(BLOBHEADER
) + sizeof(ALG_ID
),
431 /* build session key blob */
432 pbh
= (BLOBHEADER
*) buf
;
433 pbh
->bType
= SIMPLEBLOB
;
434 pbh
->bVersion
= 0x02;
436 pbh
->aiKeyAlg
= CALG_DES
;
437 *((ALG_ID
*) (buf
+ sizeof(BLOBHEADER
))) = CALG_RSA_KEYX
;
439 /* import session key into key container */
440 if (CryptImportKey(hCryptProv
, buf
,
441 dlen
+ sizeof(BLOBHEADER
) + sizeof(ALG_ID
),
442 hPrivateKey
, 0, &hSessionKey
) == 0)
446 CryptDestroyKey(hPrivateKey
);