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