sshauxcrypt.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /*
  2. * sshauxcrypt.c: wrapper functions on crypto primitives for use in
  3. * other contexts than the main SSH packet protocol, such as
  4. * encrypting private key files and performing XDM-AUTHORIZATION-1.
  5. *
  6. * These all work through the standard cipher/hash/MAC APIs, so they
  7. * don't need to live in the same actual source files as the ciphers
  8. * they wrap, and I think it keeps things tidier to have them out of
  9. * the way here instead.
  10. */
  11. #include "ssh.h"
  12. static ssh_cipher *aes256_pubkey_cipher(const void *key)
  13. {
  14. /*
  15. * PuTTY's own .PPK format for SSH-2 private key files is
  16. * encrypted with 256-bit AES in CBC mode.
  17. */
  18. char iv[16];
  19. memset(iv, 0, 16);
  20. { // WINSCP
  21. ssh_cipher *cipher = ssh_cipher_new(&ssh_aes256_cbc);
  22. ssh_cipher_setkey(cipher, key);
  23. ssh_cipher_setiv(cipher, iv);
  24. return cipher;
  25. } // WINSCP
  26. }
  27. void aes256_encrypt_pubkey(const void *key, void *blk, int len)
  28. {
  29. ssh_cipher *c = aes256_pubkey_cipher(key);
  30. ssh_cipher_encrypt(c, blk, len);
  31. ssh_cipher_free(c);
  32. }
  33. void aes256_decrypt_pubkey(const void *key, void *blk, int len)
  34. {
  35. ssh_cipher *c = aes256_pubkey_cipher(key);
  36. ssh_cipher_decrypt(c, blk, len);
  37. ssh_cipher_free(c);
  38. }
  39. static ssh_cipher *des3_pubkey_cipher(const void *vkey)
  40. {
  41. /*
  42. * SSH-1 private key files are encrypted with triple-DES in SSH-1
  43. * style (three separate CBC layers), but the same key is used for
  44. * the first and third layers.
  45. */
  46. ssh_cipher *c = ssh_cipher_new(&ssh_3des_ssh1);
  47. uint8_t keys3[24], iv[8];
  48. memcpy(keys3, vkey, 16);
  49. memcpy(keys3 + 16, vkey, 8);
  50. ssh_cipher_setkey(c, keys3);
  51. smemclr(keys3, sizeof(keys3));
  52. memset(iv, 0, 8);
  53. ssh_cipher_setiv(c, iv);
  54. return c;
  55. }
  56. void des3_decrypt_pubkey(const void *vkey, void *vblk, int len)
  57. {
  58. ssh_cipher *c = des3_pubkey_cipher(vkey);
  59. ssh_cipher_decrypt(c, vblk, len);
  60. ssh_cipher_free(c);
  61. }
  62. void des3_encrypt_pubkey(const void *vkey, void *vblk, int len)
  63. {
  64. ssh_cipher *c = des3_pubkey_cipher(vkey);
  65. ssh_cipher_encrypt(c, vblk, len);
  66. ssh_cipher_free(c);
  67. }
  68. static ssh_cipher *des3_pubkey_ossh_cipher(const void *vkey, const void *viv)
  69. {
  70. /*
  71. * OpenSSH PEM private key files are encrypted with triple-DES in
  72. * SSH-2 style (one CBC layer), with three distinct keys, and an
  73. * IV also generated from the passphrase.
  74. */
  75. ssh_cipher *c = ssh_cipher_new(&ssh_3des_ssh2);
  76. ssh_cipher_setkey(c, vkey);
  77. ssh_cipher_setiv(c, viv);
  78. return c;
  79. }
  80. void des3_decrypt_pubkey_ossh(const void *vkey, const void *viv,
  81. void *vblk, int len)
  82. {
  83. ssh_cipher *c = des3_pubkey_ossh_cipher(vkey, viv);
  84. ssh_cipher_decrypt(c, vblk, len);
  85. ssh_cipher_free(c);
  86. }
  87. void des3_encrypt_pubkey_ossh(const void *vkey, const void *viv,
  88. void *vblk, int len)
  89. {
  90. ssh_cipher *c = des3_pubkey_ossh_cipher(vkey, viv);
  91. ssh_cipher_encrypt(c, vblk, len);
  92. ssh_cipher_free(c);
  93. }
  94. static ssh_cipher *des_xdmauth_cipher(const void *vkeydata)
  95. {
  96. /*
  97. * XDM-AUTHORIZATION-1 uses single-DES, but packs the key into 7
  98. * bytes, so here we have to repack it manually into the canonical
  99. * form where it occupies 8 bytes each with the low bit unused.
  100. */
  101. const unsigned char *keydata = (const unsigned char *)vkeydata;
  102. unsigned char key[8];
  103. int i, nbits, j;
  104. unsigned int bits;
  105. bits = 0;
  106. nbits = 0;
  107. j = 0;
  108. for (i = 0; i < 8; i++) {
  109. if (nbits < 7) {
  110. bits = (bits << 8) | keydata[j];
  111. nbits += 8;
  112. j++;
  113. }
  114. key[i] = (bits >> (nbits - 7)) << 1;
  115. bits &= ~(0x7F << (nbits - 7));
  116. nbits -= 7;
  117. }
  118. { // WINSCP
  119. ssh_cipher *c = ssh_cipher_new(&ssh_des);
  120. ssh_cipher_setkey(c, key);
  121. smemclr(key, sizeof(key));
  122. ssh_cipher_setiv(c, key);
  123. return c;
  124. } // WINSCP
  125. }
  126. void des_encrypt_xdmauth(const void *keydata, void *blk, int len)
  127. {
  128. ssh_cipher *c = des_xdmauth_cipher(keydata);
  129. ssh_cipher_encrypt(c, blk, len);
  130. ssh_cipher_free(c);
  131. }
  132. void des_decrypt_xdmauth(const void *keydata, void *blk, int len)
  133. {
  134. ssh_cipher *c = des_xdmauth_cipher(keydata);
  135. ssh_cipher_decrypt(c, blk, len);
  136. ssh_cipher_free(c);
  137. }
  138. void hash_simple(const ssh_hashalg *alg, ptrlen data, void *output)
  139. {
  140. ssh_hash *hash = ssh_hash_new(alg);
  141. put_datapl(hash, data);
  142. ssh_hash_final(hash, output);
  143. }
  144. void mac_simple(const ssh2_macalg *alg, ptrlen key, ptrlen data, void *output)
  145. {
  146. ssh2_mac *mac = ssh2_mac_new(alg, NULL);
  147. ssh2_mac_setkey(mac, key);
  148. ssh2_mac_start(mac);
  149. put_datapl(mac, data);
  150. ssh2_mac_genresult(mac, output);
  151. ssh2_mac_free(mac);
  152. }