123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- /*
- * '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 "blowfish.h"
- static 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;
- }
- static 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);
- }
- static void bcrypt_genblock(int counter,
- const unsigned char hashed_passphrase[64],
- const unsigned char *salt, int saltbytes,
- unsigned char output[32])
- {
- unsigned char hashed_salt[64];
- /* Hash the input salt with the counter value optionally suffixed
- * to get our real 32-byte salt */
- ssh_hash *h = ssh_hash_new(&ssh_sha512);
- put_data(h, salt, saltbytes);
- if (counter)
- put_uint32(h, counter);
- ssh_hash_final(h, hashed_salt);
- bcrypt_hash(hashed_passphrase, 64, hashed_salt, 64, output);
- smemclr(&hashed_salt, sizeof(hashed_salt));
- }
- void openssh_bcrypt(ptrlen passphrase, ptrlen salt,
- 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 */
- hash_simple(&ssh_sha512, 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.ptr;
- thissaltbytes = salt.len;
- 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));
- }
|