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
10 * this software. If not, see
11 * <http://creativecommons.org/publicdomain/zero/1.0/>.
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
) {
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
;
62 /* 3. Initialization: Hashing inputs, allocating memory, filling first
65 result
= initialize(&instance
, context
);
67 if (ARGON2_OK
!= result
) {
71 /* 4. Filling memory */
72 result
= fill_memory_blocks(&instance
);
74 if (ARGON2_OK
!= result
) {
79 finalize(context
, &instance
);
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
;
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
);
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;
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
);
135 /* if raw hash requested, write it */
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
);
146 return ARGON2_ENCODING_FAIL
;
150 sodium_memzero(out
, hashlen
);
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
,
182 uint32_t encoded_len
;
184 memset(&ctx
, 0, sizeof ctx
);
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
) {
202 return ARGON2_MEMORY_ALLOCATION_ERROR
;
204 out
= (uint8_t *) malloc(ctx
.outlen
);
209 return ARGON2_MEMORY_ALLOCATION_ERROR
;
212 decode_result
= decode_string(&ctx
, encoded
, type
);
213 if (decode_result
!= ARGON2_OK
) {
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
);
227 if (ret
!= ARGON2_OK
|| sodium_memcmp(out
, ctx
.out
, ctx
.outlen
) != 0) {
228 ret
= ARGON2_VERIFY_MISMATCH
;
236 int argon2i_verify(const char *encoded
, const void *pwd
, const size_t pwdlen
) {
237 return argon2_verify(encoded
, pwd
, pwdlen
, Argon2_i
);