argon2.c (8241B)
1 /* 2 * Argon2 source code package 3 * 4 * Written by Daniel Dinu and Dmitry Khovratovich, 2015 5 * 6 * This work is licensed under a Creative Commons CC0 1.0 License/Waiver. 7 * 8 * You should have received a copy of the CC0 Public Domain Dedication along 9 * with 10 * this software. If not, see 11 * <http://creativecommons.org/publicdomain/zero/1.0/>. 12 */ 13 14 #include <limits.h> 15 #include <stdint.h> 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <string.h> 19 20 #include "randombytes.h" 21 #include "utils.h" 22 23 #include "argon2-core.h" 24 #include "argon2-encoding.h" 25 #include "argon2.h" 26 27 int 28 argon2_ctx(argon2_context *context, argon2_type type) 29 { 30 /* 1. Validate all inputs */ 31 int result = argon2_validate_inputs(context); 32 uint32_t memory_blocks, segment_length; 33 uint32_t pass; 34 argon2_instance_t instance; 35 36 if (ARGON2_OK != result) { 37 return result; 38 } 39 40 if (type != Argon2_id && type != Argon2_i) { 41 return ARGON2_INCORRECT_TYPE; 42 } 43 44 /* 2. Align memory size */ 45 /* Minimum memory_blocks = 8L blocks, where L is the number of lanes */ 46 memory_blocks = context->m_cost; 47 48 if (memory_blocks < 2 * ARGON2_SYNC_POINTS * context->lanes) { 49 memory_blocks = 2 * ARGON2_SYNC_POINTS * context->lanes; 50 } 51 52 segment_length = memory_blocks / (context->lanes * ARGON2_SYNC_POINTS); 53 /* Ensure that all segments have equal length */ 54 memory_blocks = segment_length * (context->lanes * ARGON2_SYNC_POINTS); 55 56 instance.region = NULL; 57 instance.passes = context->t_cost; 58 instance.current_pass = ~ 0U; 59 instance.memory_blocks = memory_blocks; 60 instance.segment_length = segment_length; 61 instance.lane_length = segment_length * ARGON2_SYNC_POINTS; 62 instance.lanes = context->lanes; 63 instance.threads = context->threads; 64 instance.type = type; 65 66 /* 3. Initialization: Hashing inputs, allocating memory, filling first 67 * blocks 68 */ 69 result = argon2_initialize(&instance, context); 70 71 if (ARGON2_OK != result) { 72 return result; 73 } 74 75 /* 4. Filling memory */ 76 for (pass = 0; pass < instance.passes; pass++) { 77 argon2_fill_memory_blocks(&instance, pass); 78 } 79 80 /* 5. Finalization */ 81 argon2_finalize(context, &instance); 82 83 return ARGON2_OK; 84 } 85 86 int 87 argon2_hash(const uint32_t t_cost, const uint32_t m_cost, 88 const uint32_t parallelism, const void *pwd, const size_t pwdlen, 89 const void *salt, const size_t saltlen, void *hash, 90 const size_t hashlen, char *encoded, const size_t encodedlen, 91 argon2_type type) 92 { 93 argon2_context context; 94 int result; 95 uint8_t *out; 96 97 if (hash != NULL) { 98 randombytes_buf(hash, hashlen); 99 } 100 101 if (pwdlen > ARGON2_MAX_PWD_LENGTH) { 102 return ARGON2_PWD_TOO_LONG; 103 } 104 105 if (hashlen > ARGON2_MAX_OUTLEN) { 106 return ARGON2_OUTPUT_TOO_LONG; 107 } 108 109 if (saltlen > ARGON2_MAX_SALT_LENGTH) { 110 return ARGON2_SALT_TOO_LONG; 111 } 112 113 out = (uint8_t *) malloc(hashlen); 114 if (!out) { 115 return ARGON2_MEMORY_ALLOCATION_ERROR; 116 } 117 118 context.out = (uint8_t *) out; 119 context.outlen = (uint32_t) hashlen; 120 context.pwd = (uint8_t *) pwd; 121 context.pwdlen = (uint32_t) pwdlen; 122 context.salt = (uint8_t *) salt; 123 context.saltlen = (uint32_t) saltlen; 124 context.secret = NULL; 125 context.secretlen = 0; 126 context.ad = NULL; 127 context.adlen = 0; 128 context.t_cost = t_cost; 129 context.m_cost = m_cost; 130 context.lanes = parallelism; 131 context.threads = parallelism; 132 context.flags = ARGON2_DEFAULT_FLAGS; 133 134 result = argon2_ctx(&context, type); 135 136 if (result != ARGON2_OK) { 137 sodium_memzero(out, hashlen); 138 free(out); 139 return result; 140 } 141 142 /* if encoding requested, write it */ 143 if (encoded && encodedlen) { 144 if (argon2_encode_string(encoded, encodedlen, 145 &context, type) != ARGON2_OK) { 146 sodium_memzero(out, hashlen); 147 sodium_memzero(encoded, encodedlen); 148 free(out); 149 return ARGON2_ENCODING_FAIL; 150 } 151 } 152 153 /* if raw hash requested, write it */ 154 if (hash) { 155 memcpy(hash, out, hashlen); 156 } 157 158 sodium_memzero(out, hashlen); 159 free(out); 160 161 return ARGON2_OK; 162 } 163 164 int 165 argon2i_hash_encoded(const uint32_t t_cost, const uint32_t m_cost, 166 const uint32_t parallelism, const void *pwd, 167 const size_t pwdlen, const void *salt, 168 const size_t saltlen, const size_t hashlen, char *encoded, 169 const size_t encodedlen) 170 { 171 return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen, 172 NULL, hashlen, encoded, encodedlen, Argon2_i); 173 } 174 175 int 176 argon2i_hash_raw(const uint32_t t_cost, const uint32_t m_cost, 177 const uint32_t parallelism, const void *pwd, 178 const size_t pwdlen, const void *salt, const size_t saltlen, 179 void *hash, const size_t hashlen) 180 { 181 return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen, 182 hash, hashlen, NULL, 0, Argon2_i); 183 } 184 185 int 186 argon2id_hash_encoded(const uint32_t t_cost, const uint32_t m_cost, 187 const uint32_t parallelism, const void *pwd, 188 const size_t pwdlen, const void *salt, 189 const size_t saltlen, const size_t hashlen, char *encoded, 190 const size_t encodedlen) 191 { 192 return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen, 193 NULL, hashlen, encoded, encodedlen, Argon2_id); 194 } 195 196 int 197 argon2id_hash_raw(const uint32_t t_cost, const uint32_t m_cost, 198 const uint32_t parallelism, const void *pwd, 199 const size_t pwdlen, const void *salt, const size_t saltlen, 200 void *hash, const size_t hashlen) 201 { 202 return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen, 203 hash, hashlen, NULL, 0, Argon2_id); 204 } 205 206 int 207 argon2_verify(const char *encoded, const void *pwd, const size_t pwdlen, 208 argon2_type type) 209 { 210 argon2_context ctx; 211 uint8_t *out; 212 int decode_result; 213 int ret; 214 size_t encoded_len; 215 216 memset(&ctx, 0, sizeof ctx); 217 218 ctx.pwd = NULL; 219 ctx.pwdlen = 0; 220 ctx.secret = NULL; 221 ctx.secretlen = 0; 222 223 /* max values, to be updated in argon2_decode_string */ 224 encoded_len = strlen(encoded); 225 if (encoded_len > UINT32_MAX) { 226 return ARGON2_DECODING_LENGTH_FAIL; 227 } 228 ctx.adlen = (uint32_t) encoded_len; 229 ctx.saltlen = (uint32_t) encoded_len; 230 ctx.outlen = (uint32_t) encoded_len; 231 232 ctx.ad = (uint8_t *) malloc(ctx.adlen); 233 ctx.salt = (uint8_t *) malloc(ctx.saltlen); 234 ctx.out = (uint8_t *) malloc(ctx.outlen); 235 if (!ctx.out || !ctx.salt || !ctx.ad) { 236 free(ctx.ad); 237 free(ctx.salt); 238 free(ctx.out); 239 return ARGON2_MEMORY_ALLOCATION_ERROR; 240 } 241 out = (uint8_t *) malloc(ctx.outlen); 242 if (!out) { 243 free(ctx.ad); 244 free(ctx.salt); 245 free(ctx.out); 246 return ARGON2_MEMORY_ALLOCATION_ERROR; 247 } 248 249 decode_result = argon2_decode_string(&ctx, encoded, type); 250 if (decode_result != ARGON2_OK) { 251 free(ctx.ad); 252 free(ctx.salt); 253 free(ctx.out); 254 free(out); 255 return decode_result; 256 } 257 258 ret = argon2_hash(ctx.t_cost, ctx.m_cost, ctx.threads, pwd, pwdlen, 259 ctx.salt, ctx.saltlen, out, ctx.outlen, NULL, 0, type); 260 261 free(ctx.ad); 262 free(ctx.salt); 263 264 if (ret == ARGON2_OK && sodium_memcmp(out, ctx.out, ctx.outlen) != 0) { 265 ret = ARGON2_VERIFY_MISMATCH; 266 } 267 free(out); 268 free(ctx.out); 269 270 return ret; 271 } 272 273 int 274 argon2i_verify(const char *encoded, const void *pwd, const size_t pwdlen) 275 { 276 return argon2_verify(encoded, pwd, pwdlen, Argon2_i); 277 } 278 279 int 280 argon2id_verify(const char *encoded, const void *pwd, const size_t pwdlen) 281 { 282 return argon2_verify(encoded, pwd, pwdlen, Argon2_id); 283 }