libsodium: updated to 1.0.10
[tomato.git] / release / src / router / libsodium / src / libsodium / crypto_pwhash / argon2 / argon2.c
blob9596a8d40660b2abb2a8c20412267689849ac0fb
1 /*
2 * Argon2 source code package
4 * Written by Daniel Dinu and Dmitry Khovratovich, 2015
6 * This work is licensed under a Creative Commons CC0 1.0 License/Waiver.
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/>.
14 #include <stdint.h>
15 #include <string.h>
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <limits.h>
21 #include "utils.h"
23 #include "argon2.h"
24 #include "argon2-encoding.h"
25 #include "argon2-core.h"
27 int argon2_ctx(argon2_context *context, argon2_type type) {
28 /* 1. Validate all inputs */
29 int result = validate_inputs(context);
30 uint32_t memory_blocks, segment_length;
31 argon2_instance_t instance;
33 if (ARGON2_OK != result) {
34 return result;
37 if (Argon2_i != type) {
38 return ARGON2_INCORRECT_TYPE;
41 /* 2. Align memory size */
42 /* Minimum memory_blocks = 8L blocks, where L is the number of lanes */
43 memory_blocks = context->m_cost;
45 if (memory_blocks < 2 * ARGON2_SYNC_POINTS * context->lanes) {
46 memory_blocks = 2 * ARGON2_SYNC_POINTS * context->lanes;
49 segment_length = memory_blocks / (context->lanes * ARGON2_SYNC_POINTS);
50 /* Ensure that all segments have equal length */
51 memory_blocks = segment_length * (context->lanes * ARGON2_SYNC_POINTS);
53 instance.region = NULL;
54 instance.passes = context->t_cost;
55 instance.memory_blocks = memory_blocks;
56 instance.segment_length = segment_length;
57 instance.lane_length = segment_length * ARGON2_SYNC_POINTS;
58 instance.lanes = context->lanes;
59 instance.threads = context->threads;
60 instance.type = type;
62 /* 3. Initialization: Hashing inputs, allocating memory, filling first
63 * blocks
65 result = initialize(&instance, context);
67 if (ARGON2_OK != result) {
68 return result;
71 /* 4. Filling memory */
72 result = fill_memory_blocks(&instance);
74 if (ARGON2_OK != result) {
75 return result;
78 /* 5. Finalization */
79 finalize(context, &instance);
81 return ARGON2_OK;
84 int argon2_hash(const uint32_t t_cost, const uint32_t m_cost,
85 const uint32_t parallelism, const void *pwd,
86 const size_t pwdlen, const void *salt, const size_t saltlen,
87 void *hash, const size_t hashlen, char *encoded,
88 const size_t encodedlen, argon2_type type) {
90 argon2_context context;
91 int result;
92 uint8_t *out;
94 if (pwdlen > ARGON2_MAX_PWD_LENGTH) {
95 return ARGON2_PWD_TOO_LONG;
98 if (hashlen > ARGON2_MAX_OUTLEN) {
99 return ARGON2_OUTPUT_TOO_LONG;
102 if (saltlen > ARGON2_MAX_SALT_LENGTH) {
103 return ARGON2_SALT_TOO_LONG;
106 out = (uint8_t *) malloc(hashlen);
107 if (!out) {
108 return ARGON2_MEMORY_ALLOCATION_ERROR;
111 context.out = (uint8_t *)out;
112 context.outlen = (uint32_t)hashlen;
113 context.pwd = (uint8_t *)pwd;
114 context.pwdlen = (uint32_t)pwdlen;
115 context.salt = (uint8_t *)salt;
116 context.saltlen = (uint32_t)saltlen;
117 context.secret = NULL;
118 context.secretlen = 0;
119 context.ad = NULL;
120 context.adlen = 0;
121 context.t_cost = t_cost;
122 context.m_cost = m_cost;
123 context.lanes = parallelism;
124 context.threads = parallelism;
125 context.flags = ARGON2_DEFAULT_FLAGS;
127 result = argon2_ctx(&context, type);
129 if (result != ARGON2_OK) {
130 sodium_memzero(out, hashlen);
131 free(out);
132 return result;
135 /* if raw hash requested, write it */
136 if (hash) {
137 memcpy(hash, out, hashlen);
140 /* if encoding requested, write it */
141 if (encoded && encodedlen) {
142 if (encode_string(encoded, encodedlen, &context, type) != ARGON2_OK) {
143 sodium_memzero(out, hashlen);
144 sodium_memzero(encoded, encodedlen);
145 free(out);
146 return ARGON2_ENCODING_FAIL;
150 sodium_memzero(out, hashlen);
151 free(out);
153 return ARGON2_OK;
156 int argon2i_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,
157 const uint32_t parallelism, const void *pwd,
158 const size_t pwdlen, const void *salt,
159 const size_t saltlen, const size_t hashlen,
160 char *encoded, const size_t encodedlen) {
162 return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
163 NULL, hashlen, encoded, encodedlen, Argon2_i);
166 int argon2i_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
167 const uint32_t parallelism, const void *pwd,
168 const size_t pwdlen, const void *salt,
169 const size_t saltlen, void *hash, const size_t hashlen) {
171 return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
172 hash, hashlen, NULL, 0, Argon2_i);
175 int argon2_verify(const char *encoded, const void *pwd, const size_t pwdlen,
176 argon2_type type) {
178 argon2_context ctx;
179 uint8_t *out;
180 int decode_result;
181 int ret;
182 uint32_t encoded_len;
184 memset(&ctx, 0, sizeof ctx);
186 ctx.secret = NULL;
187 ctx.secretlen = 0;
189 /* max values, to be updated in decode_string */
190 encoded_len = (uint32_t) strlen(encoded);
191 ctx.adlen = encoded_len;
192 ctx.saltlen = encoded_len;
193 ctx.outlen = encoded_len;
195 ctx.ad = (uint8_t *) malloc(ctx.adlen);
196 ctx.salt = (uint8_t *) malloc(ctx.saltlen);
197 ctx.out = (uint8_t *) malloc(ctx.outlen);
198 if (!ctx.out || !ctx.salt || !ctx.ad) {
199 free(ctx.ad);
200 free(ctx.salt);
201 free(ctx.out);
202 return ARGON2_MEMORY_ALLOCATION_ERROR;
204 out = (uint8_t *) malloc(ctx.outlen);
205 if (!out) {
206 free(ctx.ad);
207 free(ctx.salt);
208 free(ctx.out);
209 return ARGON2_MEMORY_ALLOCATION_ERROR;
212 decode_result = decode_string(&ctx, encoded, type);
213 if (decode_result != ARGON2_OK) {
214 free(ctx.ad);
215 free(ctx.salt);
216 free(ctx.out);
217 free(out);
218 return decode_result;
221 ret = argon2_hash(ctx.t_cost, ctx.m_cost, ctx.threads, pwd, pwdlen, ctx.salt,
222 ctx.saltlen, out, ctx.outlen, NULL, 0, type);
224 free(ctx.ad);
225 free(ctx.salt);
227 if (ret != ARGON2_OK || sodium_memcmp(out, ctx.out, ctx.outlen) != 0) {
228 ret = ARGON2_VERIFY_MISMATCH;
230 free(out);
231 free(ctx.out);
233 return ret;
236 int argon2i_verify(const char *encoded, const void *pwd, const size_t pwdlen) {
237 return argon2_verify(encoded, pwd, pwdlen, Argon2_i);