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 
bcrypt_setup(const unsigned char * key,int keybytes,const unsigned char * salt,int saltbytes)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 
bcrypt_hash(const unsigned char * key,int keybytes,const unsigned char * salt,int saltbytes,unsigned char output[32])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 
bcrypt_genblock(int counter,const unsigned char hashed_passphrase[64],const unsigned char * salt,int saltbytes,unsigned char output[32])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     unsigned char hashed_salt[64];
58 
59     /* Hash the input salt with the counter value optionally suffixed
60      * to get our real 32-byte salt */
61     ssh_hash *h = ssh_hash_new(&ssh_sha512);
62     put_data(h, salt, saltbytes);
63     if (counter)
64         put_uint32(h, counter);
65     ssh_hash_final(h, hashed_salt);
66 
67     bcrypt_hash(hashed_passphrase, 64, hashed_salt, 64, output);
68 
69     smemclr(&hashed_salt, sizeof(hashed_salt));
70 }
71 
openssh_bcrypt(const char * passphrase,const unsigned char * salt,int saltbytes,int rounds,unsigned char * out,int outbytes)72 void openssh_bcrypt(const char *passphrase,
73                     const unsigned char *salt, int saltbytes,
74                     int rounds, unsigned char *out, int outbytes)
75 {
76     unsigned char hashed_passphrase[64];
77     unsigned char block[32], outblock[32];
78     const unsigned char *thissalt;
79     int thissaltbytes;
80     int modulus, residue, i, j, round;
81 
82     /* Hash the passphrase to get the bcrypt key material */
83     hash_simple(&ssh_sha512, ptrlen_from_asciz(passphrase), hashed_passphrase);
84 
85     /* We output key bytes in a scattered fashion to meld all output
86      * key blocks into all parts of the output. To do this, we pick a
87      * modulus, and we output the key bytes to indices of out[] in the
88      * following order: first the indices that are multiples of the
89      * modulus, then the ones congruent to 1 mod modulus, etc. Each of
90      * those passes consumes exactly one block output from
91      * bcrypt_genblock, so we must pick a modulus large enough that at
92      * most 32 bytes are used in the pass. */
93     modulus = (outbytes + 31) / 32;
94 
95     for (residue = 0; residue < modulus; residue++) {
96         /* Our output block of data is the XOR of all blocks generated
97          * by bcrypt in the following loop */
98         memset(outblock, 0, sizeof(outblock));
99 
100         thissalt = salt;
101         thissaltbytes = saltbytes;
102         for (round = 0; round < rounds; round++) {
103             bcrypt_genblock(round == 0 ? residue+1 : 0,
104                             hashed_passphrase,
105                             thissalt, thissaltbytes, block);
106             /* Each subsequent bcrypt call reuses the previous one's
107              * output as its salt */
108             thissalt = block;
109             thissaltbytes = 32;
110 
111             for (i = 0; i < 32; i++)
112                 outblock[i] ^= block[i];
113         }
114 
115         for (i = residue, j = 0; i < outbytes; i += modulus, j++)
116             out[i] = outblock[j];
117     }
118     smemclr(&hashed_passphrase, sizeof(hashed_passphrase));
119 }
120