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