1 2 #include <errno.h> 3 #include <limits.h> 4 #include <stddef.h> 5 #include <stdint.h> 6 #include <stdlib.h> 7 #include <string.h> 8 9 #include "argon2-core.h" 10 #include "argon2-encoding.h" 11 #include "argon2.h" 12 #include "crypto_pwhash.h" 13 #include "crypto_pwhash_argon2i.h" 14 #include "crypto_pwhash_argon2id.h" 15 #include "private/common.h" 16 #include "randombytes.h" 17 #include "utils.h" 18 19 #define STR_HASHBYTES 32U 20 21 int 22 crypto_pwhash_argon2i_alg_argon2i13(void) 23 { 24 return crypto_pwhash_argon2i_ALG_ARGON2I13; 25 } 26 27 size_t 28 crypto_pwhash_argon2i_bytes_min(void) 29 { 30 COMPILER_ASSERT(crypto_pwhash_argon2i_BYTES_MIN >= ARGON2_MIN_OUTLEN); 31 return crypto_pwhash_argon2i_BYTES_MIN; 32 } 33 34 size_t 35 crypto_pwhash_argon2i_bytes_max(void) 36 { 37 COMPILER_ASSERT(crypto_pwhash_argon2i_BYTES_MAX <= ARGON2_MAX_OUTLEN); 38 return crypto_pwhash_argon2i_BYTES_MAX; 39 } 40 41 size_t 42 crypto_pwhash_argon2i_passwd_min(void) 43 { 44 COMPILER_ASSERT(crypto_pwhash_argon2i_PASSWD_MIN >= ARGON2_MIN_PWD_LENGTH); 45 return crypto_pwhash_argon2i_PASSWD_MIN; 46 } 47 48 size_t 49 crypto_pwhash_argon2i_passwd_max(void) 50 { 51 COMPILER_ASSERT(crypto_pwhash_argon2i_PASSWD_MAX <= ARGON2_MAX_PWD_LENGTH); 52 return crypto_pwhash_argon2i_PASSWD_MAX; 53 } 54 55 size_t 56 crypto_pwhash_argon2i_saltbytes(void) 57 { 58 COMPILER_ASSERT(crypto_pwhash_argon2i_SALTBYTES >= ARGON2_MIN_SALT_LENGTH); 59 COMPILER_ASSERT(crypto_pwhash_argon2i_SALTBYTES <= ARGON2_MAX_SALT_LENGTH); 60 return crypto_pwhash_argon2i_SALTBYTES; 61 } 62 63 size_t 64 crypto_pwhash_argon2i_strbytes(void) 65 { 66 return crypto_pwhash_argon2i_STRBYTES; 67 } 68 69 const char* 70 crypto_pwhash_argon2i_strprefix(void) 71 { 72 return crypto_pwhash_argon2i_STRPREFIX; 73 } 74 75 size_t 76 crypto_pwhash_argon2i_opslimit_min(void) 77 { 78 COMPILER_ASSERT(crypto_pwhash_argon2i_OPSLIMIT_MIN >= ARGON2_MIN_TIME); 79 return crypto_pwhash_argon2i_OPSLIMIT_MIN; 80 } 81 82 size_t 83 crypto_pwhash_argon2i_opslimit_max(void) 84 { 85 COMPILER_ASSERT(crypto_pwhash_argon2i_OPSLIMIT_MAX <= ARGON2_MAX_TIME); 86 return crypto_pwhash_argon2i_OPSLIMIT_MAX; 87 } 88 89 size_t 90 crypto_pwhash_argon2i_memlimit_min(void) 91 { 92 COMPILER_ASSERT((crypto_pwhash_argon2i_MEMLIMIT_MIN / 1024U) >= ARGON2_MIN_MEMORY); 93 return crypto_pwhash_argon2i_MEMLIMIT_MIN; 94 } 95 96 size_t 97 crypto_pwhash_argon2i_memlimit_max(void) 98 { 99 COMPILER_ASSERT((crypto_pwhash_argon2i_MEMLIMIT_MAX / 1024U) <= ARGON2_MAX_MEMORY); 100 return crypto_pwhash_argon2i_MEMLIMIT_MAX; 101 } 102 103 size_t 104 crypto_pwhash_argon2i_opslimit_interactive(void) 105 { 106 return crypto_pwhash_argon2i_OPSLIMIT_INTERACTIVE; 107 } 108 109 size_t 110 crypto_pwhash_argon2i_memlimit_interactive(void) 111 { 112 return crypto_pwhash_argon2i_MEMLIMIT_INTERACTIVE; 113 } 114 115 size_t 116 crypto_pwhash_argon2i_opslimit_moderate(void) 117 { 118 return crypto_pwhash_argon2i_OPSLIMIT_MODERATE; 119 } 120 121 size_t 122 crypto_pwhash_argon2i_memlimit_moderate(void) 123 { 124 return crypto_pwhash_argon2i_MEMLIMIT_MODERATE; 125 } 126 127 size_t 128 crypto_pwhash_argon2i_opslimit_sensitive(void) 129 { 130 return crypto_pwhash_argon2i_OPSLIMIT_SENSITIVE; 131 } 132 133 size_t 134 crypto_pwhash_argon2i_memlimit_sensitive(void) 135 { 136 return crypto_pwhash_argon2i_MEMLIMIT_SENSITIVE; 137 } 138 139 int 140 crypto_pwhash_argon2i(unsigned char *const out, unsigned long long outlen, 141 const char *const passwd, unsigned long long passwdlen, 142 const unsigned char *const salt, 143 unsigned long long opslimit, size_t memlimit, int alg) 144 { 145 memset(out, 0, outlen); 146 if (outlen > crypto_pwhash_argon2i_BYTES_MAX) { 147 errno = EFBIG; 148 return -1; 149 } 150 if (outlen < crypto_pwhash_argon2i_BYTES_MIN) { 151 errno = EINVAL; 152 return -1; 153 } 154 if (passwdlen > crypto_pwhash_argon2i_PASSWD_MAX || 155 opslimit > crypto_pwhash_argon2i_OPSLIMIT_MAX || 156 memlimit > crypto_pwhash_argon2i_MEMLIMIT_MAX) { 157 errno = EFBIG; 158 return -1; 159 } 160 if (passwdlen < crypto_pwhash_argon2i_PASSWD_MIN || 161 opslimit < crypto_pwhash_argon2i_OPSLIMIT_MIN || 162 memlimit < crypto_pwhash_argon2i_MEMLIMIT_MIN) { 163 errno = EINVAL; 164 return -1; 165 } 166 switch (alg) { 167 case crypto_pwhash_argon2i_ALG_ARGON2I13: 168 if (argon2i_hash_raw((uint32_t) opslimit, (uint32_t) (memlimit / 1024U), 169 (uint32_t) 1U, passwd, (size_t) passwdlen, salt, 170 (size_t) crypto_pwhash_argon2i_SALTBYTES, out, 171 (size_t) outlen) != ARGON2_OK) { 172 return -1; /* LCOV_EXCL_LINE */ 173 } 174 return 0; 175 default: 176 errno = EINVAL; 177 return -1; 178 } 179 } 180 181 int 182 crypto_pwhash_argon2i_str(char out[crypto_pwhash_argon2i_STRBYTES], 183 const char *const passwd, 184 unsigned long long passwdlen, 185 unsigned long long opslimit, size_t memlimit) 186 { 187 unsigned char salt[crypto_pwhash_argon2i_SALTBYTES]; 188 189 memset(out, 0, crypto_pwhash_argon2i_STRBYTES); 190 if (passwdlen > crypto_pwhash_argon2i_PASSWD_MAX || 191 opslimit > crypto_pwhash_argon2i_OPSLIMIT_MAX || 192 memlimit > crypto_pwhash_argon2i_MEMLIMIT_MAX) { 193 errno = EFBIG; 194 return -1; 195 } 196 if (passwdlen < crypto_pwhash_argon2i_PASSWD_MIN || 197 opslimit < crypto_pwhash_argon2i_OPSLIMIT_MIN || 198 memlimit < crypto_pwhash_argon2i_MEMLIMIT_MIN) { 199 errno = EINVAL; 200 return -1; 201 } 202 randombytes_buf(salt, sizeof salt); 203 if (argon2i_hash_encoded((uint32_t) opslimit, (uint32_t) (memlimit / 1024U), 204 (uint32_t) 1U, passwd, (size_t) passwdlen, salt, 205 sizeof salt, STR_HASHBYTES, out, 206 crypto_pwhash_argon2i_STRBYTES) != ARGON2_OK) { 207 return -1; /* LCOV_EXCL_LINE */ 208 } 209 return 0; 210 } 211 212 int 213 crypto_pwhash_argon2i_str_verify(const char str[crypto_pwhash_argon2i_STRBYTES], 214 const char *const passwd, 215 unsigned long long passwdlen) 216 { 217 int verify_ret; 218 219 if (passwdlen > crypto_pwhash_argon2i_PASSWD_MAX) { 220 errno = EFBIG; 221 return -1; 222 } 223 /* LCOV_EXCL_START */ 224 if (passwdlen < crypto_pwhash_argon2i_PASSWD_MIN) { 225 errno = EINVAL; 226 return -1; 227 } 228 /* LCOV_EXCL_STOP */ 229 230 verify_ret = argon2i_verify(str, passwd, (size_t) passwdlen); 231 if (verify_ret == ARGON2_OK) { 232 return 0; 233 } 234 if (verify_ret == ARGON2_VERIFY_MISMATCH) { 235 errno = EINVAL; 236 } 237 return -1; 238 } 239 240 static int 241 _needs_rehash(const char *str, unsigned long long opslimit, size_t memlimit, 242 argon2_type type) 243 { 244 unsigned char *fodder; 245 argon2_context ctx; 246 size_t fodder_len; 247 int ret = -1; 248 249 fodder_len = strlen(str); 250 memlimit /= 1024U; 251 if (opslimit > UINT32_MAX || memlimit > UINT32_MAX || 252 fodder_len >= crypto_pwhash_STRBYTES) { 253 errno = EINVAL; 254 return -1; 255 } 256 memset(&ctx, 0, sizeof ctx); 257 if ((fodder = (unsigned char *) calloc(fodder_len, 1U)) == NULL) { 258 return -1; /* LCOV_EXCL_LINE */ 259 } 260 ctx.out = ctx.pwd = ctx.salt = fodder; 261 ctx.outlen = ctx.pwdlen = ctx.saltlen = (uint32_t) fodder_len; 262 ctx.ad = ctx.secret = NULL; 263 ctx.adlen = ctx.secretlen = 0U; 264 if (decode_string(&ctx, str, type) != 0) { 265 errno = EINVAL; 266 ret = -1; 267 } else if (ctx.t_cost != (uint32_t) opslimit || 268 ctx.m_cost != (uint32_t) memlimit) { 269 ret = 1; 270 } else { 271 ret = 0; 272 } 273 free(fodder); 274 275 return ret; 276 } 277 278 int 279 crypto_pwhash_argon2i_str_needs_rehash(const char str[crypto_pwhash_argon2i_STRBYTES], 280 unsigned long long opslimit, size_t memlimit) 281 { 282 return _needs_rehash(str, opslimit, memlimit, Argon2_i); 283 } 284 285 int 286 crypto_pwhash_argon2id_str_needs_rehash(const char str[crypto_pwhash_argon2id_STRBYTES], 287 unsigned long long opslimit, size_t memlimit) 288 { 289 return _needs_rehash(str, opslimit, memlimit, Argon2_id); 290 } 291