]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - sshbcrypt.c
first pass
[PuTTY.git] / sshbcrypt.c
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
9 #include <stddef.h>
10 #include <string.h>
11 #include "ssh.h"
12 #include "sshblowf.h"
13
14 BlowfishContext *bcrypt_setup(const unsigned char *key, int keybytes,
15                               const unsigned char *salt, int saltbytes)
16 {
17     int i;
18     BlowfishContext *ctx;
19
20     ctx = blowfish_make_context();
21     blowfish_initkey(ctx);
22     blowfish_expandkey(ctx, key, keybytes, salt, saltbytes);
23
24     /* Original bcrypt replaces this fixed loop count with the
25      * variable cost. OpenSSH instead iterates the whole thing more
26      * than once if it wants extra rounds. */
27     for (i = 0; i < 64; i++) {
28         blowfish_expandkey(ctx, salt, saltbytes, NULL, 0);
29         blowfish_expandkey(ctx, key, keybytes, NULL, 0);
30     }
31
32     return ctx;
33 }
34
35 void bcrypt_hash(const unsigned char *key, int keybytes,
36                  const unsigned char *salt, int saltbytes,
37                  unsigned char output[32])
38 {
39     BlowfishContext *ctx;
40     int i;
41
42     ctx = bcrypt_setup(key, keybytes, salt, saltbytes);
43     /* This was quite a nice starting string until it ran into
44      * little-endian Blowfish :-/ */
45     memcpy(output, "cyxOmorhcitawolBhsiftawSanyDetim", 32);
46     for (i = 0; i < 64; i++) {
47         blowfish_lsb_encrypt_ecb(output, 32, ctx);
48     }
49     blowfish_free_context(ctx);
50 }
51
52 void bcrypt_genblock(int counter,
53                      const unsigned char hashed_passphrase[64],
54                      const unsigned char *salt, int saltbytes,
55                      unsigned char output[32])
56 {
57     SHA512_State shastate;
58     unsigned char hashed_salt[64];
59     unsigned char countbuf[4];
60
61     /* Hash the input salt with the counter value optionally suffixed
62      * to get our real 32-byte salt */
63     SHA512_Init(&shastate);
64     SHA512_Bytes(&shastate, salt, saltbytes);
65     if (counter) {
66         PUT_32BIT_MSB_FIRST(countbuf, counter);
67         SHA512_Bytes(&shastate, countbuf, 4);
68     }
69     SHA512_Final(&shastate, hashed_salt);
70
71     bcrypt_hash(hashed_passphrase, 64, hashed_salt, 64, output);
72
73     smemclr(&shastate, sizeof(shastate));
74     smemclr(&hashed_salt, sizeof(hashed_salt));
75 }
76
77 void openssh_bcrypt(const char *passphrase,
78                     const unsigned char *salt, int saltbytes,
79                     int rounds, unsigned char *out, int outbytes)
80 {
81     unsigned char hashed_passphrase[64];
82     unsigned char block[32], outblock[32];
83     const unsigned char *thissalt;
84     int thissaltbytes;
85     int modulus, residue, i, j, round;
86
87     /* Hash the passphrase to get the bcrypt key material */
88     SHA512_Simple(passphrase, strlen(passphrase), hashed_passphrase);
89
90     /* We output key bytes in a scattered fashion to meld all output
91      * key blocks into all parts of the output. To do this, we pick a
92      * modulus, and we output the key bytes to indices of out[] in the
93      * following order: first the indices that are multiples of the
94      * modulus, then the ones congruent to 1 mod modulus, etc. Each of
95      * those passes consumes exactly one block output from
96      * bcrypt_genblock, so we must pick a modulus large enough that at
97      * most 32 bytes are used in the pass. */
98     modulus = (outbytes + 31) / 32;
99
100     for (residue = 0; residue < modulus; residue++) {
101         /* Our output block of data is the XOR of all blocks generated
102          * by bcrypt in the following loop */
103         memset(outblock, 0, sizeof(outblock));
104
105         thissalt = salt;
106         thissaltbytes = saltbytes;
107         for (round = 0; round < rounds; round++) {
108             bcrypt_genblock(round == 0 ? residue+1 : 0,
109                             hashed_passphrase,
110                             thissalt, thissaltbytes, block);
111             /* Each subsequent bcrypt call reuses the previous one's
112              * output as its salt */
113             thissalt = block;
114             thissaltbytes = 32;
115
116             for (i = 0; i < 32; i++)
117                 outblock[i] ^= block[i];
118         }
119
120         for (i = residue, j = 0; i < outbytes; i += modulus, j++)
121             out[i] = outblock[j];
122     }
123     smemclr(&hashed_passphrase, sizeof(hashed_passphrase));
124 }