--- /dev/null
+/*
+ * 'bcrypt' password hash function, for PuTTY's import/export of
+ * OpenSSH encrypted private key files.
+ *
+ * This is not really the same as the original bcrypt; OpenSSH has
+ * modified it in various ways, and of course we have to do the same.
+ */
+
+#include <stddef.h>
+#include <string.h>
+#include "ssh.h"
+#include "sshblowf.h"
+
+BlowfishContext *bcrypt_setup(const unsigned char *key, int keybytes,
+ const unsigned char *salt, int saltbytes)
+{
+ int i;
+ BlowfishContext *ctx;
+
+ ctx = blowfish_make_context();
+ blowfish_initkey(ctx);
+ blowfish_expandkey(ctx, key, keybytes, salt, saltbytes);
+
+ /* Original bcrypt replaces this fixed loop count with the
+ * variable cost. OpenSSH instead iterates the whole thing more
+ * than once if it wants extra rounds. */
+ for (i = 0; i < 64; i++) {
+ blowfish_expandkey(ctx, salt, saltbytes, NULL, 0);
+ blowfish_expandkey(ctx, key, keybytes, NULL, 0);
+ }
+
+ return ctx;
+}
+
+void bcrypt_hash(const unsigned char *key, int keybytes,
+ const unsigned char *salt, int saltbytes,
+ unsigned char output[32])
+{
+ BlowfishContext *ctx;
+ int i;
+
+ ctx = bcrypt_setup(key, keybytes, salt, saltbytes);
+ /* This was quite a nice starting string until it ran into
+ * little-endian Blowfish :-/ */
+ memcpy(output, "cyxOmorhcitawolBhsiftawSanyDetim", 32);
+ for (i = 0; i < 64; i++) {
+ blowfish_lsb_encrypt_ecb(output, 32, ctx);
+ }
+ blowfish_free_context(ctx);
+}
+
+void bcrypt_genblock(int counter,
+ const unsigned char hashed_passphrase[64],
+ const unsigned char *salt, int saltbytes,
+ unsigned char output[32])
+{
+ SHA512_State shastate;
+ unsigned char hashed_salt[64];
+ unsigned char countbuf[4];
+
+ /* Hash the input salt with the counter value optionally suffixed
+ * to get our real 32-byte salt */
+ SHA512_Init(&shastate);
+ SHA512_Bytes(&shastate, salt, saltbytes);
+ if (counter) {
+ PUT_32BIT_MSB_FIRST(countbuf, counter);
+ SHA512_Bytes(&shastate, countbuf, 4);
+ }
+ SHA512_Final(&shastate, hashed_salt);
+
+ bcrypt_hash(hashed_passphrase, 64, hashed_salt, 64, output);
+
+ smemclr(&shastate, sizeof(shastate));
+ smemclr(&hashed_salt, sizeof(hashed_salt));
+}
+
+void openssh_bcrypt(const char *passphrase,
+ const unsigned char *salt, int saltbytes,
+ int rounds, unsigned char *out, int outbytes)
+{
+ unsigned char hashed_passphrase[64];
+ unsigned char block[32], outblock[32];
+ const unsigned char *thissalt;
+ int thissaltbytes;
+ int modulus, residue, i, j, round;
+
+ /* Hash the passphrase to get the bcrypt key material */
+ SHA512_Simple(passphrase, strlen(passphrase), hashed_passphrase);
+
+ /* We output key bytes in a scattered fashion to meld all output
+ * key blocks into all parts of the output. To do this, we pick a
+ * modulus, and we output the key bytes to indices of out[] in the
+ * following order: first the indices that are multiples of the
+ * modulus, then the ones congruent to 1 mod modulus, etc. Each of
+ * those passes consumes exactly one block output from
+ * bcrypt_genblock, so we must pick a modulus large enough that at
+ * most 32 bytes are used in the pass. */
+ modulus = (outbytes + 31) / 32;
+
+ for (residue = 0; residue < modulus; residue++) {
+ /* Our output block of data is the XOR of all blocks generated
+ * by bcrypt in the following loop */
+ memset(outblock, 0, sizeof(outblock));
+
+ thissalt = salt;
+ thissaltbytes = saltbytes;
+ for (round = 0; round < rounds; round++) {
+ bcrypt_genblock(round == 0 ? residue+1 : 0,
+ hashed_passphrase,
+ thissalt, thissaltbytes, block);
+ /* Each subsequent bcrypt call reuses the previous one's
+ * output as its salt */
+ thissalt = block;
+ thissaltbytes = 32;
+
+ for (i = 0; i < 32; i++)
+ outblock[i] ^= block[i];
+ }
+
+ for (i = residue, j = 0; i < outbytes; i += modulus, j++)
+ out[i] = outblock[j];
+ }
+ smemclr(&hashed_passphrase, sizeof(hashed_passphrase));
+}