1 2 #include <errno.h> 3 #include <limits.h> 4 #include <stddef.h> 5 #include <stdint.h> 6 #include <string.h> 7 8 #include "crypto_pwhash_scryptsalsa208sha256.h" 9 #include "crypto_scrypt.h" 10 #include "private/common.h" 11 #include "randombytes.h" 12 #include "utils.h" 13 14 #define SETTING_SIZE(saltbytes) \ 15 ((sizeof "$7$" - 1U) + (1U /* N_log2 */) + (5U /* r */) + (5U /* p */) + \ 16 BYTES2CHARS(saltbytes)) 17 18 static int 19 pickparams(unsigned long long opslimit, const size_t memlimit, 20 uint32_t *const N_log2, uint32_t *const p, uint32_t *const r) 21 { 22 unsigned long long maxN; 23 unsigned long long maxrp; 24 25 if (opslimit < 32768) { 26 opslimit = 32768; 27 } 28 *r = 8; 29 if (opslimit < memlimit / 32) { 30 *p = 1; 31 maxN = opslimit / (*r * 4); 32 for (*N_log2 = 1; *N_log2 < 63; *N_log2 += 1) { 33 if ((uint64_t)(1) << *N_log2 > maxN / 2) { 34 break; 35 } 36 } 37 } else { 38 maxN = memlimit / ((size_t) *r * 128); 39 for (*N_log2 = 1; *N_log2 < 63; *N_log2 += 1) { 40 if ((uint64_t)(1) << *N_log2 > maxN / 2) { 41 break; 42 } 43 } 44 maxrp = (opslimit / 4) / ((uint64_t)(1) << *N_log2); 45 /* LCOV_EXCL_START */ 46 if (maxrp > 0x3fffffff) { 47 maxrp = 0x3fffffff; 48 } 49 /* LCOV_EXCL_STOP */ 50 *p = (uint32_t)(maxrp) / *r; 51 } 52 return 0; 53 } 54 55 size_t 56 crypto_pwhash_scryptsalsa208sha256_bytes_min(void) 57 { 58 return crypto_pwhash_scryptsalsa208sha256_BYTES_MIN; 59 } 60 61 size_t 62 crypto_pwhash_scryptsalsa208sha256_bytes_max(void) 63 { 64 return crypto_pwhash_scryptsalsa208sha256_BYTES_MAX; 65 } 66 67 size_t 68 crypto_pwhash_scryptsalsa208sha256_passwd_min(void) 69 { 70 return crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN; 71 } 72 73 size_t 74 crypto_pwhash_scryptsalsa208sha256_passwd_max(void) 75 { 76 return crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX; 77 } 78 79 size_t 80 crypto_pwhash_scryptsalsa208sha256_saltbytes(void) 81 { 82 return crypto_pwhash_scryptsalsa208sha256_SALTBYTES; 83 } 84 85 size_t 86 crypto_pwhash_scryptsalsa208sha256_strbytes(void) 87 { 88 return crypto_pwhash_scryptsalsa208sha256_STRBYTES; 89 } 90 91 const char * 92 crypto_pwhash_scryptsalsa208sha256_strprefix(void) 93 { 94 return crypto_pwhash_scryptsalsa208sha256_STRPREFIX; 95 } 96 97 size_t 98 crypto_pwhash_scryptsalsa208sha256_opslimit_min(void) 99 { 100 return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN; 101 } 102 103 size_t 104 crypto_pwhash_scryptsalsa208sha256_opslimit_max(void) 105 { 106 return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX; 107 } 108 109 size_t 110 crypto_pwhash_scryptsalsa208sha256_memlimit_min(void) 111 { 112 return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN; 113 } 114 115 size_t 116 crypto_pwhash_scryptsalsa208sha256_memlimit_max(void) 117 { 118 return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX; 119 } 120 121 size_t 122 crypto_pwhash_scryptsalsa208sha256_opslimit_interactive(void) 123 { 124 return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE; 125 } 126 127 size_t 128 crypto_pwhash_scryptsalsa208sha256_memlimit_interactive(void) 129 { 130 return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE; 131 } 132 133 size_t 134 crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive(void) 135 { 136 return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE; 137 } 138 139 size_t 140 crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive(void) 141 { 142 return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE; 143 } 144 145 int 146 crypto_pwhash_scryptsalsa208sha256(unsigned char *const out, 147 unsigned long long outlen, 148 const char *const passwd, 149 unsigned long long passwdlen, 150 const unsigned char *const salt, 151 unsigned long long opslimit, size_t memlimit) 152 { 153 uint32_t N_log2; 154 uint32_t p; 155 uint32_t r; 156 157 memset(out, 0, outlen); 158 if (passwdlen > crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX || 159 outlen > crypto_pwhash_scryptsalsa208sha256_BYTES_MAX) { 160 errno = EFBIG; /* LCOV_EXCL_LINE */ 161 return -1; /* LCOV_EXCL_LINE */ 162 } 163 if (outlen < crypto_pwhash_scryptsalsa208sha256_BYTES_MIN || 164 pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) { 165 errno = EINVAL; /* LCOV_EXCL_LINE */ 166 return -1; /* LCOV_EXCL_LINE */ 167 } 168 return crypto_pwhash_scryptsalsa208sha256_ll( 169 (const uint8_t *) passwd, (size_t) passwdlen, (const uint8_t *) salt, 170 crypto_pwhash_scryptsalsa208sha256_SALTBYTES, (uint64_t)(1) << N_log2, 171 r, p, out, (size_t) outlen); 172 } 173 174 int 175 crypto_pwhash_scryptsalsa208sha256_str( 176 char out[crypto_pwhash_scryptsalsa208sha256_STRBYTES], 177 const char *const passwd, unsigned long long passwdlen, 178 unsigned long long opslimit, size_t memlimit) 179 { 180 uint8_t salt[crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES]; 181 char setting[crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES + 1U]; 182 escrypt_local_t escrypt_local; 183 uint32_t N_log2; 184 uint32_t p; 185 uint32_t r; 186 187 memset(out, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES); 188 if (passwdlen > crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX) { 189 errno = EFBIG; /* LCOV_EXCL_LINE */ 190 return -1; /* LCOV_EXCL_LINE */ 191 } 192 if (passwdlen < crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN || 193 pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) { 194 errno = EINVAL; /* LCOV_EXCL_LINE */ 195 return -1; /* LCOV_EXCL_LINE */ 196 } 197 randombytes_buf(salt, sizeof salt); 198 if (escrypt_gensalt_r(N_log2, r, p, salt, sizeof salt, (uint8_t *) setting, 199 sizeof setting) == NULL) { 200 errno = EINVAL; /* LCOV_EXCL_LINE */ 201 return -1; /* LCOV_EXCL_LINE */ 202 } 203 if (escrypt_init_local(&escrypt_local) != 0) { 204 return -1; /* LCOV_EXCL_LINE */ 205 } 206 if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen, 207 (const uint8_t *) setting, (uint8_t *) out, 208 crypto_pwhash_scryptsalsa208sha256_STRBYTES) == NULL) { 209 /* LCOV_EXCL_START */ 210 escrypt_free_local(&escrypt_local); 211 errno = EINVAL; 212 return -1; 213 /* LCOV_EXCL_STOP */ 214 } 215 escrypt_free_local(&escrypt_local); 216 217 COMPILER_ASSERT( 218 SETTING_SIZE(crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES) == 219 crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES); 220 COMPILER_ASSERT( 221 crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES + 1U + 222 crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED + 1U == 223 crypto_pwhash_scryptsalsa208sha256_STRBYTES); 224 225 return 0; 226 } 227 228 int 229 crypto_pwhash_scryptsalsa208sha256_str_verify( 230 const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES], 231 const char *const passwd, unsigned long long passwdlen) 232 { 233 char wanted[crypto_pwhash_scryptsalsa208sha256_STRBYTES]; 234 escrypt_local_t escrypt_local; 235 int ret = -1; 236 237 if (memchr(str, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES) != 238 &str[crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1U]) { 239 return -1; 240 } 241 if (escrypt_init_local(&escrypt_local) != 0) { 242 return -1; /* LCOV_EXCL_LINE */ 243 } 244 memset(wanted, 0, sizeof wanted); 245 if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen, 246 (const uint8_t *) str, (uint8_t *) wanted, 247 sizeof wanted) == NULL) { 248 escrypt_free_local(&escrypt_local); 249 return -1; 250 } 251 escrypt_free_local(&escrypt_local); 252 ret = sodium_memcmp(wanted, str, sizeof wanted); 253 sodium_memzero(wanted, sizeof wanted); 254 255 return ret; 256 } 257 258 int 259 crypto_pwhash_scryptsalsa208sha256_str_needs_rehash( 260 const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES], 261 unsigned long long opslimit, size_t memlimit) 262 { 263 uint32_t N_log2, N_log2_; 264 uint32_t p, p_; 265 uint32_t r, r_; 266 267 if (pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) { 268 errno = EINVAL; 269 return -1; 270 } 271 if (memchr(str, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES) != 272 &str[crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1U]) { 273 errno = EINVAL; 274 return -1; 275 } 276 if (escrypt_parse_setting((const uint8_t *) str, 277 &N_log2_, &r_, &p_) == NULL) { 278 errno = EINVAL; 279 return -1; 280 } 281 if (N_log2 != N_log2_ || r != r_ || p != p_) { 282 return 1; 283 } 284 return 0; 285 } 286