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 17int 18crypto_pwhash_argon2id_alg_argon2id13(void) 19{ 20 return crypto_pwhash_argon2id_ALG_ARGON2ID13; 21} 22 23size_t 24crypto_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 30size_t 31crypto_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 37size_t 38crypto_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 44size_t 45crypto_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 51size_t 52crypto_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 59size_t 60crypto_pwhash_argon2id_strbytes(void) 61{ 62 return crypto_pwhash_argon2id_STRBYTES; 63} 64 65const char* 66crypto_pwhash_argon2id_strprefix(void) 67{ 68 return crypto_pwhash_argon2id_STRPREFIX; 69} 70 71size_t 72crypto_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 78size_t 79crypto_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 85size_t 86crypto_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 92size_t 93crypto_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 99size_t 100crypto_pwhash_argon2id_opslimit_interactive(void) 101{ 102 return crypto_pwhash_argon2id_OPSLIMIT_INTERACTIVE; 103} 104 105size_t 106crypto_pwhash_argon2id_memlimit_interactive(void) 107{ 108 return crypto_pwhash_argon2id_MEMLIMIT_INTERACTIVE; 109} 110 111size_t 112crypto_pwhash_argon2id_opslimit_moderate(void) 113{ 114 return crypto_pwhash_argon2id_OPSLIMIT_MODERATE; 115} 116 117size_t 118crypto_pwhash_argon2id_memlimit_moderate(void) 119{ 120 return crypto_pwhash_argon2id_MEMLIMIT_MODERATE; 121} 122 123size_t 124crypto_pwhash_argon2id_opslimit_sensitive(void) 125{ 126 return crypto_pwhash_argon2id_OPSLIMIT_SENSITIVE; 127} 128 129size_t 130crypto_pwhash_argon2id_memlimit_sensitive(void) 131{ 132 return crypto_pwhash_argon2id_MEMLIMIT_SENSITIVE; 133} 134 135int 136crypto_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 177int 178crypto_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 208int 209crypto_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