bcrypt.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /*
  2. * 'bcrypt' password hash function, for PuTTY's import/export of
  3. * OpenSSH encrypted private key files.
  4. *
  5. * This is not really the same as the original bcrypt; OpenSSH has
  6. * modified it in various ways, and of course we have to do the same.
  7. */
  8. #include <stddef.h>
  9. #include <string.h>
  10. #include "ssh.h"
  11. #include "blowfish.h"
  12. static BlowfishContext *bcrypt_setup(const unsigned char *key, int keybytes,
  13. const unsigned char *salt, int saltbytes)
  14. {
  15. int i;
  16. BlowfishContext *ctx;
  17. ctx = blowfish_make_context();
  18. blowfish_initkey(ctx);
  19. blowfish_expandkey(ctx, key, keybytes, salt, saltbytes);
  20. /* Original bcrypt replaces this fixed loop count with the
  21. * variable cost. OpenSSH instead iterates the whole thing more
  22. * than once if it wants extra rounds. */
  23. for (i = 0; i < 64; i++) {
  24. blowfish_expandkey(ctx, salt, saltbytes, NULL, 0);
  25. blowfish_expandkey(ctx, key, keybytes, NULL, 0);
  26. }
  27. return ctx;
  28. }
  29. static void bcrypt_hash(const unsigned char *key, int keybytes,
  30. const unsigned char *salt, int saltbytes,
  31. unsigned char output[32])
  32. {
  33. BlowfishContext *ctx;
  34. int i;
  35. ctx = bcrypt_setup(key, keybytes, salt, saltbytes);
  36. /* This was quite a nice starting string until it ran into
  37. * little-endian Blowfish :-/ */
  38. memcpy(output, "cyxOmorhcitawolBhsiftawSanyDetim", 32);
  39. for (i = 0; i < 64; i++) {
  40. blowfish_lsb_encrypt_ecb(output, 32, ctx);
  41. }
  42. blowfish_free_context(ctx);
  43. }
  44. static void bcrypt_genblock(int counter,
  45. const unsigned char hashed_passphrase[64],
  46. const unsigned char *salt, int saltbytes,
  47. unsigned char output[32])
  48. {
  49. unsigned char hashed_salt[64];
  50. /* Hash the input salt with the counter value optionally suffixed
  51. * to get our real 32-byte salt */
  52. ssh_hash *h = ssh_hash_new(&ssh_sha512);
  53. put_data(h, salt, saltbytes);
  54. if (counter)
  55. put_uint32(h, counter);
  56. ssh_hash_final(h, hashed_salt);
  57. bcrypt_hash(hashed_passphrase, 64, hashed_salt, 64, output);
  58. smemclr(&hashed_salt, sizeof(hashed_salt));
  59. }
  60. void openssh_bcrypt(ptrlen passphrase, ptrlen salt,
  61. int rounds, unsigned char *out, int outbytes)
  62. {
  63. unsigned char hashed_passphrase[64];
  64. unsigned char block[32], outblock[32];
  65. const unsigned char *thissalt;
  66. int thissaltbytes;
  67. int modulus, residue, i, j, round;
  68. /* Hash the passphrase to get the bcrypt key material */
  69. hash_simple(&ssh_sha512, passphrase, hashed_passphrase);
  70. /* We output key bytes in a scattered fashion to meld all output
  71. * key blocks into all parts of the output. To do this, we pick a
  72. * modulus, and we output the key bytes to indices of out[] in the
  73. * following order: first the indices that are multiples of the
  74. * modulus, then the ones congruent to 1 mod modulus, etc. Each of
  75. * those passes consumes exactly one block output from
  76. * bcrypt_genblock, so we must pick a modulus large enough that at
  77. * most 32 bytes are used in the pass. */
  78. modulus = (outbytes + 31) / 32;
  79. for (residue = 0; residue < modulus; residue++) {
  80. /* Our output block of data is the XOR of all blocks generated
  81. * by bcrypt in the following loop */
  82. memset(outblock, 0, sizeof(outblock));
  83. thissalt = salt.ptr;
  84. thissaltbytes = salt.len;
  85. for (round = 0; round < rounds; round++) {
  86. bcrypt_genblock(round == 0 ? residue+1 : 0,
  87. hashed_passphrase,
  88. thissalt, thissaltbytes, block);
  89. /* Each subsequent bcrypt call reuses the previous one's
  90. * output as its salt */
  91. thissalt = block;
  92. thissaltbytes = 32;
  93. for (i = 0; i < 32; i++)
  94. outblock[i] ^= block[i];
  95. }
  96. for (i = residue, j = 0; i < outbytes; i += modulus, j++)
  97. out[i] = outblock[j];
  98. }
  99. smemclr(&hashed_passphrase, sizeof(hashed_passphrase));
  100. }