1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4
5 /**
6 @file bcrypt.c
7 bcrypt pbkdf, Steffen Jaeckel
8 */
9 #ifdef LTC_BCRYPT
10
11 #define BCRYPT_WORDS 8
12 #define BCRYPT_HASHSIZE (BCRYPT_WORDS * 4)
13
s_bcrypt_hash(const unsigned char * pt,const unsigned char * pass,unsigned long passlen,const unsigned char * salt,unsigned long saltlen,unsigned char * out,unsigned long * outlen)14 static int s_bcrypt_hash(const unsigned char *pt,
15 const unsigned char *pass, unsigned long passlen,
16 const unsigned char *salt, unsigned long saltlen,
17 unsigned char *out, unsigned long *outlen)
18 {
19 symmetric_key key;
20 int err, n;
21 ulong32 ct[BCRYPT_WORDS];
22
23 if ((err = blowfish_setup_with_data(pass, passlen, salt, saltlen, &key)) != CRYPT_OK) {
24 return err;
25 }
26 for (n = 0; n < 64; ++n) {
27 if ((err = blowfish_expand(salt, saltlen, NULL, 0, &key)) != CRYPT_OK) {
28 return err;
29 }
30 if ((err = blowfish_expand(pass, passlen, NULL, 0, &key)) != CRYPT_OK) {
31 return err;
32 }
33 }
34
35 for (n = 0; n < BCRYPT_WORDS; ++n) {
36 LOAD32H(ct[n], &pt[n*4]);
37 }
38
39 for (n = 0; n < 64; ++n) {
40 blowfish_enc(ct, BCRYPT_WORDS/2, &key);
41 }
42
43 for (n = 0; n < BCRYPT_WORDS; ++n) {
44 STORE32L(ct[n], &out[4 * n]);
45 }
46 *outlen = sizeof(ct);
47 #ifdef LTC_CLEAN_STACK
48 zeromem(&key, sizeof(key));
49 zeromem(ct, sizeof(ct));
50 #endif
51
52 return CRYPT_OK;
53 }
54
s_bcrypt_pbkdf_hash(const unsigned char * pass,unsigned long passlen,const unsigned char * salt,unsigned long saltlen,unsigned char * out,unsigned long * outlen)55 static int s_bcrypt_pbkdf_hash(const unsigned char *pass, unsigned long passlen,
56 const unsigned char *salt, unsigned long saltlen,
57 unsigned char *out, unsigned long *outlen)
58 {
59 const unsigned char pt[] = "OxychromaticBlowfishSwatDynamite";
60 return s_bcrypt_hash(pt, pass, passlen, salt, saltlen, out, outlen);
61 }
62
63 /**
64 Compatible to bcrypt_pbkdf() as provided in OpenBSD
65 @param password The input password (or key)
66 @param password_len The length of the password (octets)
67 @param salt The salt (or nonce)
68 @param salt_len The length of the salt (octets)
69 @param rounds # of iterations desired [read specs for more]
70 @param hash_idx The index of the hash desired
71 @param out [out] The destination for this algorithm
72 @param outlen [in/out] The desired size of the algorithm output
73 @return CRYPT_OK if successful
74 */
bcrypt_pbkdf_openbsd(const void * secret,unsigned long secret_len,const unsigned char * salt,unsigned long salt_len,unsigned int rounds,int hash_idx,unsigned char * out,unsigned long * outlen)75 int bcrypt_pbkdf_openbsd(const void *secret, unsigned long secret_len,
76 const unsigned char *salt, unsigned long salt_len,
77 unsigned int rounds, int hash_idx,
78 unsigned char *out, unsigned long *outlen)
79 {
80 int err;
81 ulong32 blkno;
82 unsigned long left, itts, x, y, hashed_pass_len, step_size, steps, dest, used_rounds;
83 unsigned char *buf[3], blkbuf[4];
84 unsigned char *hashed_pass;
85
86 LTC_ARGCHK(secret != NULL);
87 LTC_ARGCHK(salt != NULL);
88 LTC_ARGCHK(out != NULL);
89 LTC_ARGCHK(outlen != NULL);
90
91 if ((secret_len == 0) || (salt_len == 0) || (*outlen == 0)) {
92 return CRYPT_INVALID_ARG;
93 }
94 /* test hash IDX */
95 if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
96 return err;
97 }
98 /* set default value for rounds if not given */
99 if (rounds == 0) {
100 used_rounds = LTC_BCRYPT_DEFAULT_ROUNDS;
101 } else {
102 used_rounds = rounds;
103 }
104
105 buf[0] = XMALLOC(MAXBLOCKSIZE * 3);
106 hashed_pass = XMALLOC(MAXBLOCKSIZE);
107 if (buf[0] == NULL || hashed_pass == NULL) {
108 if (hashed_pass != NULL) {
109 XFREE(hashed_pass);
110 }
111 if (buf[0] != NULL) {
112 XFREE(buf[0]);
113 }
114 return CRYPT_MEM;
115 }
116 /* buf[1] points to the second block of MAXBLOCKSIZE bytes */
117 buf[1] = buf[0] + MAXBLOCKSIZE;
118 buf[2] = buf[1] + MAXBLOCKSIZE;
119
120 step_size = (*outlen + BCRYPT_HASHSIZE - 1) / BCRYPT_HASHSIZE;
121 steps = (*outlen + step_size - 1) / step_size;
122
123 hashed_pass_len = MAXBLOCKSIZE;
124 if ((err = hash_memory(hash_idx, (unsigned char*)secret, secret_len, hashed_pass, &hashed_pass_len)) != CRYPT_OK) {
125 goto LBL_ERR;
126 }
127
128 left = *outlen;
129 blkno = 0;
130 while (left != 0) {
131 /* increment and store current block number */
132 ++blkno;
133 STORE32H(blkno, blkbuf);
134
135 /* process block number blkno */
136 zeromem(buf[0], MAXBLOCKSIZE*2);
137
138 x = MAXBLOCKSIZE;
139 if ((err = hash_memory_multi(hash_idx, buf[0], &x,
140 salt, salt_len,
141 blkbuf, 4uL,
142 LTC_NULL)) != CRYPT_OK) {
143 goto LBL_ERR;
144 }
145 y = MAXBLOCKSIZE;
146 if ((err = s_bcrypt_pbkdf_hash(hashed_pass, hashed_pass_len, buf[0], x, buf[1], &y)) != CRYPT_OK) {
147 goto LBL_ERR;
148 }
149 XMEMCPY(buf[2], buf[1], y);
150
151 /* now compute repeated and XOR it in buf[2] */
152 for (itts = 1; itts < used_rounds; ++itts) {
153 x = MAXBLOCKSIZE;
154 if ((err = hash_memory(hash_idx, buf[1], y, buf[0], &x)) != CRYPT_OK) {
155 goto LBL_ERR;
156 }
157 y = MAXBLOCKSIZE;
158 if ((err = s_bcrypt_pbkdf_hash(hashed_pass, hashed_pass_len, buf[0], x, buf[1], &y)) != CRYPT_OK) {
159 goto LBL_ERR;
160 }
161 for (x = 0; x < y; x++) {
162 buf[2][x] ^= buf[1][x];
163 }
164 }
165
166 /* now emit upto `steps` bytes of buf[2] to output */
167 steps = MIN(steps, left);
168 for (y = 0; y < steps; ++y) {
169 dest = y * step_size + (blkno - 1);
170 if (dest >= *outlen)
171 break;
172 out[dest] = buf[2][y];
173 }
174 left -= y;
175 }
176
177 err = CRYPT_OK;
178 LBL_ERR:
179 #ifdef LTC_CLEAN_STACK
180 zeromem(buf[0], MAXBLOCKSIZE*3);
181 zeromem(hashed_pass, MAXBLOCKSIZE);
182 #endif
183
184 XFREE(hashed_pass);
185 XFREE(buf[0]);
186
187 return err;
188 }
189
190 #endif
191
192