File Coverage

src/argon2.c
Criterion Covered Total %
statement 96 173 55.4
branch 30 56 53.5
condition n/a
subroutine n/a
pod n/a
total 126 229 55.0


line stmt bran cond sub pod time code
1             /*
2             * Argon2 reference source code package - reference C implementations
3             *
4             * Copyright 2015
5             * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
6             *
7             * You may use this work under the terms of a Creative Commons CC0 1.0
8             * License/Waiver or the Apache Public License 2.0, at your option. The terms of
9             * these licenses can be found at:
10             *
11             * - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
12             * - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
13             *
14             * You should have received a copy of both of these licenses along with this
15             * software. If not, they may be obtained at the above URLs.
16             */
17              
18             #include
19             #include
20             #include
21              
22             #include "argon2.h"
23             #include "encoding.h"
24             #include "core.h"
25              
26 29           const char *argon2_type2string(argon2_type type, int uppercase) {
27 29           switch (type) {
28             case Argon2_d:
29 0 0         return uppercase ? "Argon2d" : "argon2d";
30             case Argon2_i:
31 27 50         return uppercase ? "Argon2i" : "argon2i";
32             case Argon2_id:
33 2 50         return uppercase ? "Argon2id" : "argon2id";
34             }
35              
36             return NULL;
37             }
38              
39 28           int argon2_ctx(argon2_context *context, argon2_type type) {
40             /* 1. Validate all inputs */
41 28           int result = validate_inputs(context);
42             uint32_t memory_blocks, segment_length;
43             argon2_instance_t instance;
44              
45 28 50         if (ARGON2_OK != result) {
46             return result;
47             }
48              
49 28 50         if (Argon2_d != type && Argon2_i != type && Argon2_id != type) {
50             return ARGON2_INCORRECT_TYPE;
51             }
52              
53             /* 2. Align memory size */
54             /* Minimum memory_blocks = 8L blocks, where L is the number of lanes */
55 28           memory_blocks = context->m_cost;
56              
57 28 50         if (memory_blocks < 2 * ARGON2_SYNC_POINTS * context->lanes) {
58             memory_blocks = 2 * ARGON2_SYNC_POINTS * context->lanes;
59             }
60              
61 28           segment_length = memory_blocks / (context->lanes * ARGON2_SYNC_POINTS);
62             /* Ensure that all segments have equal length */
63 28           memory_blocks = segment_length * (context->lanes * ARGON2_SYNC_POINTS);
64              
65 28           instance.version = context->version;
66 28           instance.memory = NULL;
67 28           instance.passes = context->t_cost;
68 28           instance.memory_blocks = memory_blocks;
69 28           instance.segment_length = segment_length;
70 28           instance.lane_length = segment_length * ARGON2_SYNC_POINTS;
71 28           instance.lanes = context->lanes;
72 28           instance.threads = context->threads;
73 28           instance.type = type;
74              
75 28 50         if (instance.threads > instance.lanes) {
76 0           instance.threads = instance.lanes;
77             }
78              
79             /* 3. Initialization: Hashing inputs, allocating memory, filling first
80             * blocks
81             */
82 28           result = initialize(&instance, context);
83              
84 28 50         if (ARGON2_OK != result) {
85             return result;
86             }
87              
88             /* 4. Filling memory */
89 28           result = fill_memory_blocks(&instance);
90              
91 28 50         if (ARGON2_OK != result) {
92             return result;
93             }
94             /* 5. Finalization */
95 28           finalize(context, &instance);
96              
97 28           return ARGON2_OK;
98             }
99              
100 19           int argon2_hash(const uint32_t t_cost, const uint32_t m_cost,
101             const uint32_t parallelism, const void *pwd,
102             const size_t pwdlen, const void *salt, const size_t saltlen,
103             void *hash, const size_t hashlen, char *encoded,
104             const size_t encodedlen, argon2_type type,
105             const uint32_t version){
106              
107             argon2_context context;
108             int result;
109             uint8_t *out;
110              
111 19 50         if (pwdlen > ARGON2_MAX_PWD_LENGTH) {
112             return ARGON2_PWD_TOO_LONG;
113             }
114              
115 19 50         if (saltlen > ARGON2_MAX_SALT_LENGTH) {
116             return ARGON2_SALT_TOO_LONG;
117             }
118              
119 19 50         if (hashlen > ARGON2_MAX_OUTLEN) {
120             return ARGON2_OUTPUT_TOO_LONG;
121             }
122              
123 19 50         if (hashlen < ARGON2_MIN_OUTLEN) {
124             return ARGON2_OUTPUT_TOO_SHORT;
125             }
126              
127 19           out = malloc(hashlen);
128 19 50         if (!out) {
129             return ARGON2_MEMORY_ALLOCATION_ERROR;
130             }
131              
132 19           context.out = (uint8_t *)out;
133 19           context.outlen = (uint32_t)hashlen;
134 19           context.pwd = CONST_CAST(uint8_t *)pwd;
135 19           context.pwdlen = (uint32_t)pwdlen;
136 19           context.salt = CONST_CAST(uint8_t *)salt;
137 19           context.saltlen = (uint32_t)saltlen;
138 19           context.secret = NULL;
139 19           context.secretlen = 0;
140 19           context.ad = NULL;
141 19           context.adlen = 0;
142 19           context.t_cost = t_cost;
143 19           context.m_cost = m_cost;
144 19           context.lanes = parallelism;
145 19           context.threads = parallelism;
146 19           context.allocate_cbk = NULL;
147 19           context.free_cbk = NULL;
148 19           context.flags = ARGON2_DEFAULT_FLAGS;
149 19           context.version = version;
150              
151 19           result = argon2_ctx(&context, type);
152              
153 19 50         if (result != ARGON2_OK) {
154 0           clear_internal_memory(out, hashlen);
155 0           free(out);
156 0           return result;
157             }
158              
159             /* if raw hash requested, write it */
160 19 100         if (hash) {
161             memcpy(hash, out, hashlen);
162             }
163              
164             /* if encoding requested, write it */
165 19 100         if (encoded && encodedlen) {
166 10 50         if (encode_string(encoded, encodedlen, &context, type) != ARGON2_OK) {
167 0           clear_internal_memory(out, hashlen); /* wipe buffers if error */
168 0           clear_internal_memory(encoded, encodedlen);
169 0           free(out);
170 0           return ARGON2_ENCODING_FAIL;
171             }
172             }
173 19           clear_internal_memory(out, hashlen);
174 19           free(out);
175              
176 19           return ARGON2_OK;
177             }
178              
179 0           int argon2i_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,
180             const uint32_t parallelism, const void *pwd,
181             const size_t pwdlen, const void *salt,
182             const size_t saltlen, const size_t hashlen,
183             char *encoded, const size_t encodedlen) {
184              
185 0           return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
186             NULL, hashlen, encoded, encodedlen, Argon2_i,
187             ARGON2_VERSION_NUMBER);
188             }
189              
190 0           int argon2i_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
191             const uint32_t parallelism, const void *pwd,
192             const size_t pwdlen, const void *salt,
193             const size_t saltlen, void *hash, const size_t hashlen) {
194              
195 0           return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
196             hash, hashlen, NULL, 0, Argon2_i, ARGON2_VERSION_NUMBER);
197             }
198              
199 0           int argon2d_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,
200             const uint32_t parallelism, const void *pwd,
201             const size_t pwdlen, const void *salt,
202             const size_t saltlen, const size_t hashlen,
203             char *encoded, const size_t encodedlen) {
204              
205 0           return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
206             NULL, hashlen, encoded, encodedlen, Argon2_d,
207             ARGON2_VERSION_NUMBER);
208             }
209              
210 0           int argon2d_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
211             const uint32_t parallelism, const void *pwd,
212             const size_t pwdlen, const void *salt,
213             const size_t saltlen, void *hash, const size_t hashlen) {
214              
215 0           return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
216             hash, hashlen, NULL, 0, Argon2_d, ARGON2_VERSION_NUMBER);
217             }
218              
219 0           int argon2id_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,
220             const uint32_t parallelism, const void *pwd,
221             const size_t pwdlen, const void *salt,
222             const size_t saltlen, const size_t hashlen,
223             char *encoded, const size_t encodedlen) {
224              
225 0           return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
226             NULL, hashlen, encoded, encodedlen, Argon2_id,
227             ARGON2_VERSION_NUMBER);
228             }
229              
230 0           int argon2id_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
231             const uint32_t parallelism, const void *pwd,
232             const size_t pwdlen, const void *salt,
233             const size_t saltlen, void *hash, const size_t hashlen) {
234 0           return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
235             hash, hashlen, NULL, 0, Argon2_id,
236             ARGON2_VERSION_NUMBER);
237             }
238              
239             static int argon2_compare(const uint8_t *b1, const uint8_t *b2, size_t len) {
240             size_t i;
241             uint8_t d = 0U;
242              
243 297 100         for (i = 0U; i < len; i++) {
244 288           d |= b1[i] ^ b2[i];
245             }
246 9           return (int)((1 & ((d - 1) >> 8)) - 1);
247             }
248              
249 9           int argon2_verify(const char *encoded, const void *pwd, const size_t pwdlen,
250             argon2_type type) {
251              
252             argon2_context ctx;
253             uint8_t *desired_result = NULL;
254              
255             int ret = ARGON2_OK;
256              
257             size_t encoded_len;
258             uint32_t max_field_len;
259              
260 9 50         if (pwdlen > ARGON2_MAX_PWD_LENGTH) {
261             return ARGON2_PWD_TOO_LONG;
262             }
263              
264 9 50         if (encoded == NULL) {
265             return ARGON2_DECODING_FAIL;
266             }
267              
268 9           encoded_len = strlen(encoded);
269 9 50         if (encoded_len > UINT32_MAX) {
270             return ARGON2_DECODING_FAIL;
271             }
272              
273             /* No field can be longer than the encoded length */
274 9           max_field_len = (uint32_t)encoded_len;
275              
276 9           ctx.saltlen = max_field_len;
277 9           ctx.outlen = max_field_len;
278              
279 9           ctx.salt = malloc(ctx.saltlen);
280 9           ctx.out = malloc(ctx.outlen);
281 9 50         if (!ctx.salt || !ctx.out) {
    50          
282             ret = ARGON2_MEMORY_ALLOCATION_ERROR;
283             goto fail;
284             }
285              
286 9           ctx.pwd = (uint8_t *)pwd;
287 9           ctx.pwdlen = (uint32_t)pwdlen;
288              
289 9           ret = decode_string(&ctx, encoded, type);
290 9 50         if (ret != ARGON2_OK) {
291             goto fail;
292             }
293              
294             /* Set aside the desired result, and get a new buffer. */
295 9           desired_result = ctx.out;
296 9           ctx.out = malloc(ctx.outlen);
297 9 50         if (!ctx.out) {
298             ret = ARGON2_MEMORY_ALLOCATION_ERROR;
299             goto fail;
300             }
301              
302 9           ret = argon2_verify_ctx(&ctx, (char *)desired_result, type);
303             if (ret != ARGON2_OK) {
304             goto fail;
305             }
306              
307             fail:
308 9           free(ctx.salt);
309 9           free(ctx.out);
310 9           free(desired_result);
311              
312 9           return ret;
313             }
314              
315 0           int argon2i_verify(const char *encoded, const void *pwd, const size_t pwdlen) {
316              
317 0           return argon2_verify(encoded, pwd, pwdlen, Argon2_i);
318             }
319              
320 0           int argon2d_verify(const char *encoded, const void *pwd, const size_t pwdlen) {
321              
322 0           return argon2_verify(encoded, pwd, pwdlen, Argon2_d);
323             }
324              
325 0           int argon2id_verify(const char *encoded, const void *pwd, const size_t pwdlen) {
326              
327 0           return argon2_verify(encoded, pwd, pwdlen, Argon2_id);
328             }
329              
330 0           int argon2d_ctx(argon2_context *context) {
331 0           return argon2_ctx(context, Argon2_d);
332             }
333              
334 0           int argon2i_ctx(argon2_context *context) {
335 0           return argon2_ctx(context, Argon2_i);
336             }
337              
338 0           int argon2id_ctx(argon2_context *context) {
339 0           return argon2_ctx(context, Argon2_id);
340             }
341              
342 9           int argon2_verify_ctx(argon2_context *context, const char *hash,
343             argon2_type type) {
344 9           int ret = argon2_ctx(context, type);
345 9 50         if (ret != ARGON2_OK) {
346             return ret;
347             }
348              
349 18 50         if (argon2_compare((uint8_t *)hash, context->out, context->outlen)) {
350             return ARGON2_VERIFY_MISMATCH;
351             }
352              
353 9           return ARGON2_OK;
354             }
355              
356 0           int argon2d_verify_ctx(argon2_context *context, const char *hash) {
357 0           return argon2_verify_ctx(context, hash, Argon2_d);
358             }
359              
360 0           int argon2i_verify_ctx(argon2_context *context, const char *hash) {
361 0           return argon2_verify_ctx(context, hash, Argon2_i);
362             }
363              
364 0           int argon2id_verify_ctx(argon2_context *context, const char *hash) {
365 0           return argon2_verify_ctx(context, hash, Argon2_id);
366             }
367              
368 0           const char *argon2_error_message(int error_code) {
369 0           switch (error_code) {
370             case ARGON2_OK:
371             return "OK";
372             case ARGON2_OUTPUT_PTR_NULL:
373 0           return "Output pointer is NULL";
374             case ARGON2_OUTPUT_TOO_SHORT:
375 0           return "Output is too short";
376             case ARGON2_OUTPUT_TOO_LONG:
377 0           return "Output is too long";
378             case ARGON2_PWD_TOO_SHORT:
379 0           return "Password is too short";
380             case ARGON2_PWD_TOO_LONG:
381 0           return "Password is too long";
382             case ARGON2_SALT_TOO_SHORT:
383 0           return "Salt is too short";
384             case ARGON2_SALT_TOO_LONG:
385 0           return "Salt is too long";
386             case ARGON2_AD_TOO_SHORT:
387 0           return "Associated data is too short";
388             case ARGON2_AD_TOO_LONG:
389 0           return "Associated data is too long";
390             case ARGON2_SECRET_TOO_SHORT:
391 0           return "Secret is too short";
392             case ARGON2_SECRET_TOO_LONG:
393 0           return "Secret is too long";
394             case ARGON2_TIME_TOO_SMALL:
395 0           return "Time cost is too small";
396             case ARGON2_TIME_TOO_LARGE:
397 0           return "Time cost is too large";
398             case ARGON2_MEMORY_TOO_LITTLE:
399 0           return "Memory cost is too small";
400             case ARGON2_MEMORY_TOO_MUCH:
401 0           return "Memory cost is too large";
402             case ARGON2_LANES_TOO_FEW:
403 0           return "Too few lanes";
404             case ARGON2_LANES_TOO_MANY:
405 0           return "Too many lanes";
406             case ARGON2_PWD_PTR_MISMATCH:
407 0           return "Password pointer is NULL, but password length is not 0";
408             case ARGON2_SALT_PTR_MISMATCH:
409 0           return "Salt pointer is NULL, but salt length is not 0";
410             case ARGON2_SECRET_PTR_MISMATCH:
411 0           return "Secret pointer is NULL, but secret length is not 0";
412             case ARGON2_AD_PTR_MISMATCH:
413 0           return "Associated data pointer is NULL, but ad length is not 0";
414             case ARGON2_MEMORY_ALLOCATION_ERROR:
415 0           return "Memory allocation error";
416             case ARGON2_FREE_MEMORY_CBK_NULL:
417 0           return "The free memory callback is NULL";
418             case ARGON2_ALLOCATE_MEMORY_CBK_NULL:
419 0           return "The allocate memory callback is NULL";
420             case ARGON2_INCORRECT_PARAMETER:
421 0           return "Argon2_Context context is NULL";
422             case ARGON2_INCORRECT_TYPE:
423 0           return "There is no such version of Argon2";
424             case ARGON2_OUT_PTR_MISMATCH:
425 0           return "Output pointer mismatch";
426             case ARGON2_THREADS_TOO_FEW:
427 0           return "Not enough threads";
428             case ARGON2_THREADS_TOO_MANY:
429 0           return "Too many threads";
430             case ARGON2_MISSING_ARGS:
431 0           return "Missing arguments";
432             case ARGON2_ENCODING_FAIL:
433 0           return "Encoding failed";
434             case ARGON2_DECODING_FAIL:
435 0           return "Decoding failed";
436             case ARGON2_THREAD_FAIL:
437 0           return "Threading failure";
438             case ARGON2_DECODING_LENGTH_FAIL:
439 0           return "Some of encoded parameters are too long or too short";
440             case ARGON2_VERIFY_MISMATCH:
441 0           return "The password does not match the supplied hash";
442             default:
443 0           return "Unknown error code";
444             }
445             }
446              
447 10           size_t argon2_encodedlen(uint32_t t_cost, uint32_t m_cost, uint32_t parallelism,
448             uint32_t saltlen, uint32_t hashlen, argon2_type type) {
449 10           return strlen("$$v=$m=,t=,p=$$") + strlen(argon2_type2string(type, 0)) +
450 10           numlen(t_cost) + numlen(m_cost) + numlen(parallelism) +
451 10           b64len(saltlen) + b64len(hashlen) + numlen(ARGON2_VERSION_NUMBER) + 1;
452             }