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
argon2_ctx(argon2_context * context,argon2_type type)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
argon2_hash(const uint32_t t_cost,const uint32_t m_cost,const uint32_t parallelism,const void * pwd,const size_t pwdlen,const void * salt,const size_t saltlen,void * hash,const size_t hashlen,char * encoded,const size_t encodedlen,argon2_type type)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
argon2i_hash_encoded(const uint32_t t_cost,const uint32_t m_cost,const uint32_t parallelism,const void * pwd,const size_t pwdlen,const void * salt,const size_t saltlen,const size_t hashlen,char * encoded,const size_t encodedlen)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
argon2i_hash_raw(const uint32_t t_cost,const uint32_t m_cost,const uint32_t parallelism,const void * pwd,const size_t pwdlen,const void * salt,const size_t saltlen,void * hash,const size_t hashlen)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
argon2id_hash_encoded(const uint32_t t_cost,const uint32_t m_cost,const uint32_t parallelism,const void * pwd,const size_t pwdlen,const void * salt,const size_t saltlen,const size_t hashlen,char * encoded,const size_t encodedlen)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
argon2id_hash_raw(const uint32_t t_cost,const uint32_t m_cost,const uint32_t parallelism,const void * pwd,const size_t pwdlen,const void * salt,const size_t saltlen,void * hash,const size_t hashlen)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
argon2_verify(const char * encoded,const void * pwd,const size_t pwdlen,argon2_type type)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
argon2i_verify(const char * encoded,const void * pwd,const size_t pwdlen)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
argon2id_verify(const char * encoded,const void * pwd,const size_t pwdlen)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