1 2 #include <errno.h> 3 #include <limits.h> 4 #include <stddef.h> 5 #include <stdint.h> 6 #include <string.h> 7 8 #include "argon2-core.h" 9 #include "argon2.h" 10 #include "crypto_pwhash_argon2id.h" 11 #include "private/common.h" 12 #include "randombytes.h" 13 #include "utils.h" 14 15 #define STR_HASHBYTES 32U 16 17 int 18 crypto_pwhash_argon2id_alg_argon2id13(void) 19 { 20 return crypto_pwhash_argon2id_ALG_ARGON2ID13; 21 } 22 23 size_t 24 crypto_pwhash_argon2id_bytes_min(void) 25 { 26 COMPILER_ASSERT(crypto_pwhash_argon2id_BYTES_MIN >= ARGON2_MIN_OUTLEN); 27 return crypto_pwhash_argon2id_BYTES_MIN; 28 } 29 30 size_t 31 crypto_pwhash_argon2id_bytes_max(void) 32 { 33 COMPILER_ASSERT(crypto_pwhash_argon2id_BYTES_MAX <= ARGON2_MAX_OUTLEN); 34 return crypto_pwhash_argon2id_BYTES_MAX; 35 } 36 37 size_t 38 crypto_pwhash_argon2id_passwd_min(void) 39 { 40 COMPILER_ASSERT(crypto_pwhash_argon2id_PASSWD_MIN >= ARGON2_MIN_PWD_LENGTH); 41 return crypto_pwhash_argon2id_PASSWD_MIN; 42 } 43 44 size_t 45 crypto_pwhash_argon2id_passwd_max(void) 46 { 47 COMPILER_ASSERT(crypto_pwhash_argon2id_PASSWD_MAX <= ARGON2_MAX_PWD_LENGTH); 48 return crypto_pwhash_argon2id_PASSWD_MAX; 49 } 50 51 size_t 52 crypto_pwhash_argon2id_saltbytes(void) 53 { 54 COMPILER_ASSERT(crypto_pwhash_argon2id_SALTBYTES >= ARGON2_MIN_SALT_LENGTH); 55 COMPILER_ASSERT(crypto_pwhash_argon2id_SALTBYTES <= ARGON2_MAX_SALT_LENGTH); 56 return crypto_pwhash_argon2id_SALTBYTES; 57 } 58 59 size_t 60 crypto_pwhash_argon2id_strbytes(void) 61 { 62 return crypto_pwhash_argon2id_STRBYTES; 63 } 64 65 const char* 66 crypto_pwhash_argon2id_strprefix(void) 67 { 68 return crypto_pwhash_argon2id_STRPREFIX; 69 } 70 71 size_t 72 crypto_pwhash_argon2id_opslimit_min(void) 73 { 74 COMPILER_ASSERT(crypto_pwhash_argon2id_OPSLIMIT_MIN >= ARGON2_MIN_TIME); 75 return crypto_pwhash_argon2id_OPSLIMIT_MIN; 76 } 77 78 size_t 79 crypto_pwhash_argon2id_opslimit_max(void) 80 { 81 COMPILER_ASSERT(crypto_pwhash_argon2id_OPSLIMIT_MAX <= ARGON2_MAX_TIME); 82 return crypto_pwhash_argon2id_OPSLIMIT_MAX; 83 } 84 85 size_t 86 crypto_pwhash_argon2id_memlimit_min(void) 87 { 88 COMPILER_ASSERT((crypto_pwhash_argon2id_MEMLIMIT_MIN / 1024U) >= ARGON2_MIN_MEMORY); 89 return crypto_pwhash_argon2id_MEMLIMIT_MIN; 90 } 91 92 size_t 93 crypto_pwhash_argon2id_memlimit_max(void) 94 { 95 COMPILER_ASSERT((crypto_pwhash_argon2id_MEMLIMIT_MAX / 1024U) <= ARGON2_MAX_MEMORY); 96 return crypto_pwhash_argon2id_MEMLIMIT_MAX; 97 } 98 99 size_t 100 crypto_pwhash_argon2id_opslimit_interactive(void) 101 { 102 return crypto_pwhash_argon2id_OPSLIMIT_INTERACTIVE; 103 } 104 105 size_t 106 crypto_pwhash_argon2id_memlimit_interactive(void) 107 { 108 return crypto_pwhash_argon2id_MEMLIMIT_INTERACTIVE; 109 } 110 111 size_t 112 crypto_pwhash_argon2id_opslimit_moderate(void) 113 { 114 return crypto_pwhash_argon2id_OPSLIMIT_MODERATE; 115 } 116 117 size_t 118 crypto_pwhash_argon2id_memlimit_moderate(void) 119 { 120 return crypto_pwhash_argon2id_MEMLIMIT_MODERATE; 121 } 122 123 size_t 124 crypto_pwhash_argon2id_opslimit_sensitive(void) 125 { 126 return crypto_pwhash_argon2id_OPSLIMIT_SENSITIVE; 127 } 128 129 size_t 130 crypto_pwhash_argon2id_memlimit_sensitive(void) 131 { 132 return crypto_pwhash_argon2id_MEMLIMIT_SENSITIVE; 133 } 134 135 int 136 crypto_pwhash_argon2id(unsigned char *const out, unsigned long long outlen, 137 const char *const passwd, unsigned long long passwdlen, 138 const unsigned char *const salt, 139 unsigned long long opslimit, size_t memlimit, int alg) 140 { 141 memset(out, 0, outlen); 142 if (outlen > crypto_pwhash_argon2id_BYTES_MAX) { 143 errno = EFBIG; 144 return -1; 145 } 146 if (outlen < crypto_pwhash_argon2id_BYTES_MIN) { 147 errno = EINVAL; 148 return -1; 149 } 150 if (passwdlen > crypto_pwhash_argon2id_PASSWD_MAX || 151 opslimit > crypto_pwhash_argon2id_OPSLIMIT_MAX || 152 memlimit > crypto_pwhash_argon2id_MEMLIMIT_MAX) { 153 errno = EFBIG; 154 return -1; 155 } 156 if (passwdlen < crypto_pwhash_argon2id_PASSWD_MIN || 157 opslimit < crypto_pwhash_argon2id_OPSLIMIT_MIN || 158 memlimit < crypto_pwhash_argon2id_MEMLIMIT_MIN) { 159 errno = EINVAL; 160 return -1; 161 } 162 switch (alg) { 163 case crypto_pwhash_argon2id_ALG_ARGON2ID13: 164 if (argon2id_hash_raw((uint32_t) opslimit, (uint32_t) (memlimit / 1024U), 165 (uint32_t) 1U, passwd, (size_t) passwdlen, salt, 166 (size_t) crypto_pwhash_argon2id_SALTBYTES, out, 167 (size_t) outlen) != ARGON2_OK) { 168 return -1; /* LCOV_EXCL_LINE */ 169 } 170 return 0; 171 default: 172 errno = EINVAL; 173 return -1; 174 } 175 } 176 177 int 178 crypto_pwhash_argon2id_str(char out[crypto_pwhash_argon2id_STRBYTES], 179 const char *const passwd, 180 unsigned long long passwdlen, 181 unsigned long long opslimit, size_t memlimit) 182 { 183 unsigned char salt[crypto_pwhash_argon2id_SALTBYTES]; 184 185 memset(out, 0, crypto_pwhash_argon2id_STRBYTES); 186 if (passwdlen > crypto_pwhash_argon2id_PASSWD_MAX || 187 opslimit > crypto_pwhash_argon2id_OPSLIMIT_MAX || 188 memlimit > crypto_pwhash_argon2id_MEMLIMIT_MAX) { 189 errno = EFBIG; 190 return -1; 191 } 192 if (passwdlen < crypto_pwhash_argon2id_PASSWD_MIN || 193 opslimit < crypto_pwhash_argon2id_OPSLIMIT_MIN || 194 memlimit < crypto_pwhash_argon2id_MEMLIMIT_MIN) { 195 errno = EINVAL; 196 return -1; 197 } 198 randombytes_buf(salt, sizeof salt); 199 if (argon2id_hash_encoded((uint32_t) opslimit, (uint32_t) (memlimit / 1024U), 200 (uint32_t) 1U, passwd, (size_t) passwdlen, salt, 201 sizeof salt, STR_HASHBYTES, out, 202 crypto_pwhash_argon2id_STRBYTES) != ARGON2_OK) { 203 return -1; /* LCOV_EXCL_LINE */ 204 } 205 return 0; 206 } 207 208 int 209 crypto_pwhash_argon2id_str_verify(const char str[crypto_pwhash_argon2id_STRBYTES], 210 const char *const passwd, 211 unsigned long long passwdlen) 212 { 213 int verify_ret; 214 215 if (passwdlen > crypto_pwhash_argon2id_PASSWD_MAX) { 216 errno = EFBIG; 217 return -1; 218 } 219 /* LCOV_EXCL_START */ 220 if (passwdlen < crypto_pwhash_argon2id_PASSWD_MIN) { 221 errno = EINVAL; 222 return -1; 223 } 224 /* LCOV_EXCL_STOP */ 225 226 verify_ret = argon2id_verify(str, passwd, (size_t) passwdlen); 227 if (verify_ret == ARGON2_OK) { 228 return 0; 229 } 230 if (verify_ret == ARGON2_VERIFY_MISMATCH) { 231 errno = EINVAL; 232 } 233 return -1; 234 } 235