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 static size_t 56 sodium_strnlen(const char *str, size_t maxlen) 57 { 58 size_t i = 0U; 59 60 while (i < maxlen && str[i] != 0) { 61 i++; 62 } 63 return i; 64 } 65 66 size_t 67 crypto_pwhash_scryptsalsa208sha256_bytes_min(void) 68 { 69 return crypto_pwhash_scryptsalsa208sha256_BYTES_MIN; 70 } 71 72 size_t 73 crypto_pwhash_scryptsalsa208sha256_bytes_max(void) 74 { 75 return crypto_pwhash_scryptsalsa208sha256_BYTES_MAX; 76 } 77 78 size_t 79 crypto_pwhash_scryptsalsa208sha256_passwd_min(void) 80 { 81 return crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN; 82 } 83 84 size_t 85 crypto_pwhash_scryptsalsa208sha256_passwd_max(void) 86 { 87 return crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX; 88 } 89 90 size_t 91 crypto_pwhash_scryptsalsa208sha256_saltbytes(void) 92 { 93 return crypto_pwhash_scryptsalsa208sha256_SALTBYTES; 94 } 95 96 size_t 97 crypto_pwhash_scryptsalsa208sha256_strbytes(void) 98 { 99 return crypto_pwhash_scryptsalsa208sha256_STRBYTES; 100 } 101 102 const char * 103 crypto_pwhash_scryptsalsa208sha256_strprefix(void) 104 { 105 return crypto_pwhash_scryptsalsa208sha256_STRPREFIX; 106 } 107 108 size_t 109 crypto_pwhash_scryptsalsa208sha256_opslimit_min(void) 110 { 111 return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN; 112 } 113 114 size_t 115 crypto_pwhash_scryptsalsa208sha256_opslimit_max(void) 116 { 117 return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MAX; 118 } 119 120 size_t 121 crypto_pwhash_scryptsalsa208sha256_memlimit_min(void) 122 { 123 return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN; 124 } 125 126 size_t 127 crypto_pwhash_scryptsalsa208sha256_memlimit_max(void) 128 { 129 return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MAX; 130 } 131 132 size_t 133 crypto_pwhash_scryptsalsa208sha256_opslimit_interactive(void) 134 { 135 return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE; 136 } 137 138 size_t 139 crypto_pwhash_scryptsalsa208sha256_memlimit_interactive(void) 140 { 141 return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE; 142 } 143 144 size_t 145 crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive(void) 146 { 147 return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE; 148 } 149 150 size_t 151 crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive(void) 152 { 153 return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE; 154 } 155 156 int 157 crypto_pwhash_scryptsalsa208sha256(unsigned char *const out, 158 unsigned long long outlen, 159 const char *const passwd, 160 unsigned long long passwdlen, 161 const unsigned char *const salt, 162 unsigned long long opslimit, size_t memlimit) 163 { 164 uint32_t N_log2; 165 uint32_t p; 166 uint32_t r; 167 168 memset(out, 0, outlen); 169 if (passwdlen > crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX || 170 outlen > crypto_pwhash_scryptsalsa208sha256_BYTES_MAX) { 171 errno = EFBIG; /* LCOV_EXCL_LINE */ 172 return -1; /* LCOV_EXCL_LINE */ 173 } 174 if (outlen < crypto_pwhash_scryptsalsa208sha256_BYTES_MIN || 175 pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) { 176 errno = EINVAL; /* LCOV_EXCL_LINE */ 177 return -1; /* LCOV_EXCL_LINE */ 178 } 179 return crypto_pwhash_scryptsalsa208sha256_ll( 180 (const uint8_t *) passwd, (size_t) passwdlen, (const uint8_t *) salt, 181 crypto_pwhash_scryptsalsa208sha256_SALTBYTES, (uint64_t)(1) << N_log2, 182 r, p, out, (size_t) outlen); 183 } 184 185 int 186 crypto_pwhash_scryptsalsa208sha256_str( 187 char out[crypto_pwhash_scryptsalsa208sha256_STRBYTES], 188 const char *const passwd, unsigned long long passwdlen, 189 unsigned long long opslimit, size_t memlimit) 190 { 191 uint8_t salt[crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES]; 192 char setting[crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES + 1U]; 193 escrypt_local_t escrypt_local; 194 uint32_t N_log2; 195 uint32_t p; 196 uint32_t r; 197 198 memset(out, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES); 199 if (passwdlen > crypto_pwhash_scryptsalsa208sha256_PASSWD_MAX) { 200 errno = EFBIG; /* LCOV_EXCL_LINE */ 201 return -1; /* LCOV_EXCL_LINE */ 202 } 203 if (passwdlen < crypto_pwhash_scryptsalsa208sha256_PASSWD_MIN || 204 pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) { 205 errno = EINVAL; /* LCOV_EXCL_LINE */ 206 return -1; /* LCOV_EXCL_LINE */ 207 } 208 randombytes_buf(salt, sizeof salt); 209 if (escrypt_gensalt_r(N_log2, r, p, salt, sizeof salt, (uint8_t *) setting, 210 sizeof setting) == NULL) { 211 errno = EINVAL; /* LCOV_EXCL_LINE */ 212 return -1; /* LCOV_EXCL_LINE */ 213 } 214 if (escrypt_init_local(&escrypt_local) != 0) { 215 return -1; /* LCOV_EXCL_LINE */ 216 } 217 if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen, 218 (const uint8_t *) setting, (uint8_t *) out, 219 crypto_pwhash_scryptsalsa208sha256_STRBYTES) == NULL) { 220 /* LCOV_EXCL_START */ 221 escrypt_free_local(&escrypt_local); 222 errno = EINVAL; 223 return -1; 224 /* LCOV_EXCL_STOP */ 225 } 226 escrypt_free_local(&escrypt_local); 227 228 COMPILER_ASSERT( 229 SETTING_SIZE(crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES) == 230 crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES); 231 COMPILER_ASSERT( 232 crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES + 1U + 233 crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED + 1U == 234 crypto_pwhash_scryptsalsa208sha256_STRBYTES); 235 236 return 0; 237 } 238 239 int 240 crypto_pwhash_scryptsalsa208sha256_str_verify( 241 const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES], 242 const char *const passwd, unsigned long long passwdlen) 243 { 244 char wanted[crypto_pwhash_scryptsalsa208sha256_STRBYTES]; 245 escrypt_local_t escrypt_local; 246 int ret = -1; 247 248 if (sodium_strnlen(str, crypto_pwhash_scryptsalsa208sha256_STRBYTES) != 249 crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1U) { 250 return -1; 251 } 252 if (escrypt_init_local(&escrypt_local) != 0) { 253 return -1; /* LCOV_EXCL_LINE */ 254 } 255 memset(wanted, 0, sizeof wanted); 256 if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen, 257 (const uint8_t *) str, (uint8_t *) wanted, 258 sizeof wanted) == NULL) { 259 escrypt_free_local(&escrypt_local); 260 return -1; 261 } 262 escrypt_free_local(&escrypt_local); 263 ret = sodium_memcmp(wanted, str, sizeof wanted); 264 sodium_memzero(wanted, sizeof wanted); 265 266 return ret; 267 } 268 269 int 270 crypto_pwhash_scryptsalsa208sha256_str_needs_rehash( 271 const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES], 272 unsigned long long opslimit, size_t memlimit) 273 { 274 uint32_t N_log2, N_log2_; 275 uint32_t p, p_; 276 uint32_t r, r_; 277 278 if (pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) { 279 errno = EINVAL; 280 return -1; 281 } 282 if (sodium_strnlen(str, crypto_pwhash_scryptsalsa208sha256_STRBYTES) != 283 crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1U) { 284 errno = EINVAL; 285 return -1; 286 } 287 if (escrypt_parse_setting((const uint8_t *) str, 288 &N_log2_, &r_, &p_) == NULL) { 289 errno = EINVAL; 290 return -1; 291 } 292 if (N_log2 != N_log2_ || r != r_ || p != p_) { 293 return 1; 294 } 295 return 0; 296 } 297