mscrypto.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  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. void fatalbox(char *fmt, ...);
  8. static HCRYPTKEY create_des_key(unsigned char *key);
  9. HCRYPTPROV hCryptProv;
  10. HCRYPTKEY hDESKey[2][3] = {{0,0,0},{0,0,0}}; /* global for now */
  11. /* use Microsoft Enhanced Cryptographic Service Provider */
  12. #define CSP MS_ENHANCED_PROV
  13. static BYTE PrivateKeyWithExponentOfOne[] =
  14. {
  15. 0x07, 0x02, 0x00, 0x00, 0x00, 0xA4, 0x00, 0x00,
  16. 0x52, 0x53, 0x41, 0x32, 0x00, 0x02, 0x00, 0x00,
  17. 0x01, 0x00, 0x00, 0x00, 0xAB, 0xEF, 0xFA, 0xC6,
  18. 0x7D, 0xE8, 0xDE, 0xFB, 0x68, 0x38, 0x09, 0x92,
  19. 0xD9, 0x42, 0x7E, 0x6B, 0x89, 0x9E, 0x21, 0xD7,
  20. 0x52, 0x1C, 0x99, 0x3C, 0x17, 0x48, 0x4E, 0x3A,
  21. 0x44, 0x02, 0xF2, 0xFA, 0x74, 0x57, 0xDA, 0xE4,
  22. 0xD3, 0xC0, 0x35, 0x67, 0xFA, 0x6E, 0xDF, 0x78,
  23. 0x4C, 0x75, 0x35, 0x1C, 0xA0, 0x74, 0x49, 0xE3,
  24. 0x20, 0x13, 0x71, 0x35, 0x65, 0xDF, 0x12, 0x20,
  25. 0xF5, 0xF5, 0xF5, 0xC1, 0xED, 0x5C, 0x91, 0x36,
  26. 0x75, 0xB0, 0xA9, 0x9C, 0x04, 0xDB, 0x0C, 0x8C,
  27. 0xBF, 0x99, 0x75, 0x13, 0x7E, 0x87, 0x80, 0x4B,
  28. 0x71, 0x94, 0xB8, 0x00, 0xA0, 0x7D, 0xB7, 0x53,
  29. 0xDD, 0x20, 0x63, 0xEE, 0xF7, 0x83, 0x41, 0xFE,
  30. 0x16, 0xA7, 0x6E, 0xDF, 0x21, 0x7D, 0x76, 0xC0,
  31. 0x85, 0xD5, 0x65, 0x7F, 0x00, 0x23, 0x57, 0x45,
  32. 0x52, 0x02, 0x9D, 0xEA, 0x69, 0xAC, 0x1F, 0xFD,
  33. 0x3F, 0x8C, 0x4A, 0xD0,
  34. 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  35. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  36. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  37. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  38. 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  39. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  40. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  41. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  42. 0x64, 0xD5, 0xAA, 0xB1,
  43. 0xA6, 0x03, 0x18, 0x92, 0x03, 0xAA, 0x31, 0x2E,
  44. 0x48, 0x4B, 0x65, 0x20, 0x99, 0xCD, 0xC6, 0x0C,
  45. 0x15, 0x0C, 0xBF, 0x3E, 0xFF, 0x78, 0x95, 0x67,
  46. 0xB1, 0x74, 0x5B, 0x60,
  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,
  51. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  52. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  53. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  54. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  55. };
  56. /* ---------------------------------------------------------*
  57. * Utility functions *
  58. * ---------------------------------------------------------*/
  59. int crypto_startup() {
  60. if(CryptAcquireContext(&hCryptProv, "Putty", CSP, PROV_RSA_FULL,
  61. CRYPT_NEWKEYSET) == 0) {
  62. if(GetLastError() == NTE_EXISTS) {
  63. if(CryptAcquireContext(&hCryptProv, "Putty", CSP,
  64. PROV_RSA_FULL, 0) == 0) {
  65. return FALSE; /* failed to acquire context - probably
  66. * don't have high encryption installed! */
  67. }
  68. } else
  69. return FALSE; /* failed to acquire context - probably
  70. * don't have high encryption installed! */
  71. }
  72. return TRUE;
  73. }
  74. void crypto_wrapup() {
  75. int i, j;
  76. for(i=0; i<2; i++) {
  77. for(j=0; j<3; j++) {
  78. if(hDESKey[i][j])
  79. CryptDestroyKey(hDESKey[i][j]);
  80. hDESKey[i][j] = 0;
  81. }
  82. }
  83. if(hCryptProv)
  84. CryptReleaseContext(hCryptProv, 0);
  85. hCryptProv = 0;
  86. }
  87. /* ---------------------------------------------------------*
  88. * Random number functions *
  89. * ---------------------------------------------------------*/
  90. int random_byte(void) {
  91. unsigned char b;
  92. if(!CryptGenRandom(hCryptProv, 1, &b))
  93. fatalbox("random number generator failure!");
  94. return b;
  95. }
  96. void random_add_noise(void *noise, int length) {
  97. /* do nothing */
  98. }
  99. void random_init(void) {
  100. /* do nothing */
  101. }
  102. void random_get_savedata(void **data, int *len) {
  103. /* do nothing */
  104. }
  105. void noise_get_heavy(void (*func) (void *, int)) {
  106. /* do nothing */
  107. }
  108. void noise_get_light(void (*func) (void *, int)) {
  109. /* do nothing */
  110. }
  111. void noise_ultralight(DWORD data) {
  112. /* do nothing */
  113. }
  114. void random_save_seed(void) {
  115. /* do nothing */
  116. }
  117. /* ---------------------------------------------------------*
  118. * MD5 hash functions *
  119. * ---------------------------------------------------------*/
  120. void MD5Init(struct MD5Context *ctx) {
  121. if(!CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &ctx->hHash))
  122. fatalbox("Error during CryptBeginHash!\n");
  123. }
  124. void MD5Update(struct MD5Context *ctx,
  125. unsigned char const *buf, unsigned len) {
  126. if(CryptHashData(ctx->hHash, buf, len, 0) == 0)
  127. fatalbox("Error during CryptHashSessionKey!\n");
  128. }
  129. void MD5Final(unsigned char digest[16], struct MD5Context *ctx) {
  130. DWORD cb = 16;
  131. if(CryptGetHashParam(ctx->hHash, HP_HASHVAL, digest, &cb, 0) == 0)
  132. fatalbox("Error during CryptGetHashParam!\n");
  133. if(ctx->hHash)
  134. CryptDestroyHash(ctx->hHash);
  135. ctx->hHash = 0;
  136. }
  137. /* ---------------------------------------------------------*
  138. * RSA public key functions *
  139. * ---------------------------------------------------------*/
  140. int makekey(unsigned char *data, struct RSAKey *result,
  141. unsigned char **keystr) {
  142. unsigned char *p = data;
  143. int i;
  144. int w, b;
  145. /* get size (bits) of modulus */
  146. result->bits = 0;
  147. for(i=0; i<4; i++)
  148. result->bits = (result->bits << 8) + *p++;
  149. /* get size (bits) of public exponent */
  150. w = 0;
  151. for (i=0; i<2; i++)
  152. w = (w << 8) + *p++;
  153. b = (w+7)/8; /* bits -> bytes */
  154. /* convert exponent to DWORD */
  155. result->exponent = 0;
  156. for (i=0; i<b; i++)
  157. result->exponent = (result->exponent << 8) + *p++;
  158. /* get size (bits) of modulus */
  159. w = 0;
  160. for (i=0; i<2; i++)
  161. w = (w << 8) + *p++;
  162. result->bytes = b = (w+7)/8; /* bits -> bytes */
  163. /* allocate buffer for modulus & copy it */
  164. result->modulus = malloc(b);
  165. memcpy(result->modulus, p, b);
  166. /* update callers pointer */
  167. if (keystr) *keystr = p; /* point at key string, second time */
  168. return (p - data) + b;
  169. }
  170. void rsaencrypt(unsigned char *data, int length, struct RSAKey *rsakey) {
  171. int i;
  172. unsigned char *pKeybuf, *pKeyin;
  173. HCRYPTKEY hRsaKey;
  174. PUBLICKEYSTRUC *pBlob;
  175. RSAPUBKEY *pRPK;
  176. unsigned char *buf;
  177. DWORD dlen;
  178. DWORD bufsize;
  179. /* allocate buffer for public key blob */
  180. if((pBlob = malloc(sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) +
  181. rsakey->bytes)) == NULL)
  182. fatalbox("Out of memory");
  183. /* allocate buffer for message encryption block */
  184. bufsize = (length + rsakey->bytes) << 1;
  185. if((buf = malloc(bufsize)) == NULL)
  186. fatalbox("Out of memory");
  187. /* construct public key blob from host public key */
  188. pKeybuf = ((unsigned char*)pBlob) + sizeof(PUBLICKEYSTRUC) +
  189. sizeof(RSAPUBKEY);
  190. pKeyin = ((unsigned char*)rsakey->modulus);
  191. /* change big endian to little endian */
  192. for(i=0; i<rsakey->bytes; i++)
  193. pKeybuf[i] = pKeyin[rsakey->bytes-i-1];
  194. pBlob->bType = PUBLICKEYBLOB;
  195. pBlob->bVersion = 0x02;
  196. pBlob->reserved = 0;
  197. pBlob->aiKeyAlg = CALG_RSA_KEYX;
  198. pRPK = (RSAPUBKEY*)(((unsigned char*)pBlob) + sizeof(PUBLICKEYSTRUC));
  199. pRPK->magic = 0x31415352; /* "RSA1" */
  200. pRPK->bitlen = rsakey->bits;
  201. pRPK->pubexp = rsakey->exponent;
  202. /* import public key blob into key container */
  203. if(CryptImportKey(hCryptProv, (void*)pBlob,
  204. sizeof(PUBLICKEYSTRUC)+sizeof(RSAPUBKEY)+rsakey->bytes,
  205. 0, 0, &hRsaKey) == 0)
  206. fatalbox("Error importing RSA key!");
  207. /* copy message into buffer */
  208. memcpy(buf, data, length);
  209. dlen = length;
  210. /* using host public key, encrypt the message */
  211. if(CryptEncrypt(hRsaKey, 0, TRUE, 0, buf, &dlen, bufsize) == 0)
  212. fatalbox("Error encrypting using RSA key!");
  213. /*
  214. * For some strange reason, Microsoft CryptEncrypt using public
  215. * key, returns the cyphertext in backwards (little endian)
  216. * order, so reverse it!
  217. */
  218. for(i = 0; i < (int)dlen; i++)
  219. data[i] = buf[dlen - i - 1]; /* make it big endian */
  220. CryptDestroyKey(hRsaKey);
  221. free(buf);
  222. free(pBlob);
  223. }
  224. int rsastr_len(struct RSAKey *key) {
  225. return 2 * (sizeof(DWORD) + key->bytes) + 10;
  226. }
  227. void rsastr_fmt(char *str, struct RSAKey *key) {
  228. int len = 0, i;
  229. sprintf(str+len, "%04x", key->exponent);
  230. len += strlen(str+len);
  231. str[len++] = '/';
  232. for (i=1; i<key->bytes; i++) {
  233. sprintf(str+len, "%02x", key->modulus[i]);
  234. len += strlen(str+len);
  235. }
  236. str[len] = '\0';
  237. }
  238. /* ---------------------------------------------------------*
  239. * DES encryption / decryption functions *
  240. * ---------------------------------------------------------*/
  241. void des3_sesskey(unsigned char *key) {
  242. int i, j;
  243. for(i = 0; i < 2; i++) {
  244. for(j = 0; j < 3; j++) {
  245. hDESKey[i][j] = create_des_key(key + (j * 8));
  246. }
  247. }
  248. }
  249. void des3_encrypt_blk(unsigned char *blk, int len) {
  250. DWORD dlen;
  251. dlen = len;
  252. if(CryptEncrypt(hDESKey[0][0], 0, FALSE, 0, blk, &dlen, len + 8) == 0)
  253. fatalbox("Error encrypting block!\n");
  254. if(CryptDecrypt(hDESKey[0][1], 0, FALSE, 0, blk, &dlen) == 0)
  255. fatalbox("Error encrypting block!\n");
  256. if(CryptEncrypt(hDESKey[0][2], 0, FALSE, 0, blk, &dlen, len + 8) == 0)
  257. fatalbox("Error encrypting block!\n");
  258. }
  259. void des3_decrypt_blk(unsigned char *blk, int len) {
  260. DWORD dlen;
  261. dlen = len;
  262. if(CryptDecrypt(hDESKey[1][2], 0, FALSE, 0, blk, &dlen) == 0)
  263. fatalbox("Error decrypting block!\n");
  264. if(CryptEncrypt(hDESKey[1][1], 0, FALSE, 0, blk, &dlen, len + 8) == 0)
  265. fatalbox("Error decrypting block!\n");
  266. if(CryptDecrypt(hDESKey[1][0], 0, FALSE, 0, blk, &dlen) == 0)
  267. fatalbox("Error decrypting block!\n");
  268. }
  269. struct ssh_cipher ssh_3des = {
  270. des3_sesskey,
  271. des3_encrypt_blk,
  272. des3_decrypt_blk
  273. };
  274. void des_sesskey(unsigned char *key) {
  275. int i;
  276. for(i = 0; i < 2; i++) {
  277. hDESKey[i][0] = create_des_key(key);
  278. }
  279. }
  280. void des_encrypt_blk(unsigned char *blk, int len) {
  281. DWORD dlen;
  282. dlen = len;
  283. if(CryptEncrypt(hDESKey[0][0], 0, FALSE, 0, blk, &dlen, len + 8) == 0)
  284. fatalbox("Error encrypting block!\n");
  285. }
  286. void des_decrypt_blk(unsigned char *blk, int len) {
  287. DWORD dlen;
  288. dlen = len;
  289. if(CryptDecrypt(hDESKey[1][0], 0, FALSE, 0, blk, &dlen) == 0)
  290. fatalbox("Error decrypting block!\n");
  291. }
  292. struct ssh_cipher ssh_des = {
  293. des_sesskey,
  294. des_encrypt_blk,
  295. des_decrypt_blk
  296. };
  297. static HCRYPTKEY create_des_key(unsigned char *key) {
  298. HCRYPTKEY hSessionKey, hPrivateKey;
  299. DWORD dlen = 8;
  300. BLOBHEADER *pbh;
  301. char buf[sizeof(BLOBHEADER) + sizeof(ALG_ID) + 256];
  302. /*
  303. * Need special private key to encrypt session key so we can
  304. * import session key, since only encrypted session keys can be
  305. * imported
  306. */
  307. if(CryptImportKey(hCryptProv, PrivateKeyWithExponentOfOne,
  308. sizeof(PrivateKeyWithExponentOfOne),
  309. 0, 0, &hPrivateKey) == 0)
  310. return 0;
  311. /* now encrypt session key using special private key */
  312. memcpy(buf + sizeof(BLOBHEADER) + sizeof(ALG_ID), key, 8);
  313. if(CryptEncrypt(hPrivateKey, 0, TRUE, 0,
  314. buf + sizeof(BLOBHEADER) + sizeof(ALG_ID),
  315. &dlen, 256) == 0)
  316. return 0;
  317. /* build session key blob */
  318. pbh = (BLOBHEADER*)buf;
  319. pbh->bType = SIMPLEBLOB;
  320. pbh->bVersion = 0x02;
  321. pbh->reserved = 0;
  322. pbh->aiKeyAlg = CALG_DES;
  323. *((ALG_ID*)(buf+sizeof(BLOBHEADER))) = CALG_RSA_KEYX;
  324. /* import session key into key container */
  325. if(CryptImportKey(hCryptProv, buf,
  326. dlen + sizeof(BLOBHEADER) + sizeof(ALG_ID),
  327. hPrivateKey, 0, &hSessionKey) == 0)
  328. return 0;
  329. if(hPrivateKey)
  330. CryptDestroyKey(hPrivateKey);
  331. return hSessionKey;
  332. }