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  * modified by Agnieszka Bielec <bielecagnieszka8 at gmail.com>
13  */
14 
15 #include <string.h>
16 #include <stdlib.h>
17 #include <stdio.h>
18 
19 #include "argon2.h"
20 #include "argon2_encoding.h"
21 #include "argon2_core.h"
22 
argon2_ctx(argon2_context * context,argon2_type type)23 int argon2_ctx(argon2_context *context, argon2_type type) {
24     /* 1. Validate all inputs */
25     int result = argon2_validate_inputs(context);
26     uint32_t memory_blocks, segment_length;
27     argon2_instance_t instance;
28 
29     if (ARGON2_OK != result) {
30         return result;
31     }
32 
33     if (Argon2_d != type && Argon2_i != type) {
34         return ARGON2_INCORRECT_TYPE;
35     }
36 
37     /* 2. Align memory size */
38     /* Minimum memory_blocks = 8L blocks, where L is the number of lanes */
39     memory_blocks = context->m_cost;
40 
41     if (memory_blocks < 2 * ARGON2_SYNC_POINTS * context->lanes) {
42         memory_blocks = 2 * ARGON2_SYNC_POINTS * context->lanes;
43     }
44 
45     segment_length = memory_blocks / (context->lanes * ARGON2_SYNC_POINTS);
46     /* Ensure that all segments have equal length */
47     memory_blocks = segment_length * (context->lanes * ARGON2_SYNC_POINTS);
48 
49     instance.version = context->version;
50     instance.memory = context->memory;
51     instance.passes = context->t_cost;
52     instance.memory_blocks = memory_blocks;
53     instance.segment_length = segment_length;
54     instance.lane_length = segment_length * ARGON2_SYNC_POINTS;
55     instance.lanes = context->lanes;
56     instance.threads = context->threads;
57     instance.type = type;
58     instance.memory = context->memory;
59     instance.pseudo_rands = context->pseudo_rands;
60 
61     /* 3. Initialization: Hashing inputs, allocating memory, filling first
62      * blocks
63      */
64     result = argon2_initialize(&instance, context);
65 
66     if (ARGON2_OK != result) {
67         return result;
68     }
69 
70     /* 4. Filling memory */
71     result = argon2_fill_memory_blocks(&instance);
72 
73     if (ARGON2_OK != result) {
74         return result;
75     }
76     /* 5. Finalization */
77     argon2_finalize(context, &instance);
78 
79     return ARGON2_OK;
80 }
81 
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,const uint32_t version,void * memory,void * pseudo_rands)82 int argon2_hash(const uint32_t t_cost, const uint32_t m_cost,
83                 const uint32_t parallelism, const void *pwd,
84                 const size_t pwdlen, const void *salt, const size_t saltlen,
85                 void *hash, const size_t hashlen, char *encoded,
86                 const size_t encodedlen, argon2_type type,
87                 const uint32_t version, void *memory, void *pseudo_rands){
88 
89     argon2_context context;
90     int result;
91     //uint8_t *out;
92 
93     if (hashlen > ARGON2_MAX_OUTLEN) {
94         return ARGON2_OUTPUT_TOO_LONG;
95     }
96 
97     if (hashlen < ARGON2_MIN_OUTLEN) {
98         return ARGON2_OUTPUT_TOO_SHORT;
99     }
100 
101     context.out = (uint8_t *)hash;
102     context.outlen = (uint32_t)hashlen;
103     context.pwd = CONST_CAST(uint8_t *)pwd;
104     context.pwdlen = (uint32_t)pwdlen;
105     context.salt = CONST_CAST(uint8_t *)salt;
106     context.saltlen = (uint32_t)saltlen;
107     context.secret = NULL;
108     context.secretlen = 0;
109     context.ad = NULL;
110     context.adlen = 0;
111     context.t_cost = t_cost;
112     context.m_cost = m_cost;
113     context.lanes = parallelism;
114     context.threads = parallelism;
115     context.flags = ARGON2_DEFAULT_FLAGS;
116     context.version = version;
117     context.memory = memory;
118     context.pseudo_rands=pseudo_rands;
119 
120     result = argon2_ctx(&context, type);
121 
122     if (result != ARGON2_OK) {
123         //free(out);
124         return result;
125     }
126 
127     /* if encoding requested, write it */
128     if (encoded && encodedlen) {
129         if (argon2_encode_string(encoded, encodedlen, &context, type) != ARGON2_OK) {
130             //free(out);
131             return ARGON2_ENCODING_FAIL;
132         }
133     }
134 
135     return ARGON2_OK;
136 }
137 
138 
argon2d_ctx(argon2_context * context)139 int argon2d_ctx(argon2_context *context) {
140     return argon2_ctx(context, Argon2_d);
141 }
142 
argon2i_ctx(argon2_context * context)143 int argon2i_ctx(argon2_context *context) {
144     return argon2_ctx(context, Argon2_i);
145 }
146 
argon2_verify_ctx(argon2_context * context,const char * hash,argon2_type type)147 int argon2_verify_ctx(argon2_context *context, const char *hash,
148                       argon2_type type) {
149     int result;
150     if (0 == context->outlen || NULL == hash) {
151         return ARGON2_OUT_PTR_MISMATCH;
152     }
153 
154     result = argon2_ctx(context, type);
155 
156     if (ARGON2_OK != result) {
157         return result;
158     }
159 
160     return 0 == memcmp(hash, context->out, context->outlen);
161 }
162 
argon2d_verify_ctx(argon2_context * context,const char * hash)163 int argon2d_verify_ctx(argon2_context *context, const char *hash) {
164     return argon2_verify_ctx(context, hash, Argon2_d);
165 }
166 
argon2i_verify_ctx(argon2_context * context,const char * hash)167 int argon2i_verify_ctx(argon2_context *context, const char *hash) {
168     return argon2_verify_ctx(context, hash, Argon2_i);
169 }
170 
argon2_error_message(int error_code)171 const char *argon2_error_message(int error_code) {
172     switch (error_code) {
173     case ARGON2_OK:
174         return "OK";
175     case ARGON2_OUTPUT_PTR_NULL:
176         return "Output pointer is NULL";
177     case ARGON2_OUTPUT_TOO_SHORT:
178         return "Output is too short";
179     case ARGON2_OUTPUT_TOO_LONG:
180         return "Output is too long";
181     case ARGON2_PWD_TOO_SHORT:
182         return "Password is too short";
183     case ARGON2_PWD_TOO_LONG:
184         return "Password is too long";
185     case ARGON2_SALT_TOO_SHORT:
186         return "Salt is too short";
187     case ARGON2_SALT_TOO_LONG:
188         return "Salt is too long";
189     case ARGON2_AD_TOO_SHORT:
190         return "Associated data is too short";
191     case ARGON2_AD_TOO_LONG:
192         return "Associated data is too long";
193     case ARGON2_SECRET_TOO_SHORT:
194         return "Secret is too short";
195     case ARGON2_SECRET_TOO_LONG:
196         return "Secret is too long";
197     case ARGON2_TIME_TOO_SMALL:
198         return "Time cost is too small";
199     case ARGON2_TIME_TOO_LARGE:
200         return "Time cost is too large";
201     case ARGON2_MEMORY_TOO_LITTLE:
202         return "Memory cost is too small";
203     case ARGON2_MEMORY_TOO_MUCH:
204         return "Memory cost is too large";
205     case ARGON2_LANES_TOO_FEW:
206         return "Too few lanes";
207     case ARGON2_LANES_TOO_MANY:
208         return "Too many lanes";
209     case ARGON2_PWD_PTR_MISMATCH:
210         return "Password pointer is NULL, but password length is not 0";
211     case ARGON2_SALT_PTR_MISMATCH:
212         return "Salt pointer is NULL, but salt length is not 0";
213     case ARGON2_SECRET_PTR_MISMATCH:
214         return "Secret pointer is NULL, but secret length is not 0";
215     case ARGON2_AD_PTR_MISMATCH:
216         return "Associated data pointer is NULL, but ad length is not 0";
217     case ARGON2_MEMORY_ALLOCATION_ERROR:
218         return "Memory allocation error";
219     case ARGON2_FREE_MEMORY_CBK_NULL:
220         return "The free memory callback is NULL";
221     case ARGON2_ALLOCATE_MEMORY_CBK_NULL:
222         return "The allocate memory callback is NULL";
223     case ARGON2_INCORRECT_PARAMETER:
224         return "Argon2_Context context is NULL";
225     case ARGON2_INCORRECT_TYPE:
226         return "There is no such version of Argon2";
227     case ARGON2_OUT_PTR_MISMATCH:
228         return "Output pointer mismatch";
229     case ARGON2_THREADS_TOO_FEW:
230         return "Not enough threads";
231     case ARGON2_THREADS_TOO_MANY:
232         return "Too many threads";
233     case ARGON2_MISSING_ARGS:
234         return "Missing arguments";
235     case ARGON2_ENCODING_FAIL:
236         return "Encoding failed";
237     case ARGON2_DECODING_FAIL:
238         return "Decoding failed";
239     case ARGON2_THREAD_FAIL:
240         return "Threading failure";
241     case ARGON2_DECODING_LENGTH_FAIL:
242         return "Some of encoded parameters are too long or too short";
243     case ARGON2_VERIFY_MISMATCH:
244         return "The password does not match the supplied hash";
245     default:
246         return "Unknown error code";
247     }
248 }
249 
argon2_encodedlen(uint32_t t_cost,uint32_t m_cost,uint32_t parallelism,uint32_t saltlen,uint32_t hashlen)250 size_t argon2_encodedlen(uint32_t t_cost, uint32_t m_cost, uint32_t parallelism,
251                          uint32_t saltlen, uint32_t hashlen) {
252     return strlen("$argon2x$v=$m=,t=,p=$$") + argon2_numlen(t_cost) + argon2_numlen(m_cost)
253         + argon2_numlen(parallelism) + argon2_b64len(saltlen) + argon2_b64len(hashlen)
254         + argon2_numlen(ARGON2_VERSION_NUMBER);
255 }
256