argon2id 0.8.0.rc1-x86_64-linux-musl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +142 -0
- data/Gemfile +9 -0
- data/LICENSE +11 -0
- data/README.md +371 -0
- data/Rakefile +70 -0
- data/argon2id.gemspec +59 -0
- data/ext/argon2id/argon2id.c +76 -0
- data/ext/argon2id/extconf.rb +17 -0
- data/ext/argon2id/libargon2/LICENSE +314 -0
- data/ext/argon2id/libargon2/argon2.c +452 -0
- data/ext/argon2id/libargon2/argon2.h +437 -0
- data/ext/argon2id/libargon2/blake2/blake2-impl.h +156 -0
- data/ext/argon2id/libargon2/blake2/blake2.h +89 -0
- data/ext/argon2id/libargon2/blake2/blake2b.c +390 -0
- data/ext/argon2id/libargon2/blake2/blamka-round-opt.h +471 -0
- data/ext/argon2id/libargon2/blake2/blamka-round-ref.h +56 -0
- data/ext/argon2id/libargon2/core.c +648 -0
- data/ext/argon2id/libargon2/core.h +228 -0
- data/ext/argon2id/libargon2/encoding.c +463 -0
- data/ext/argon2id/libargon2/encoding.h +57 -0
- data/ext/argon2id/libargon2/ref.c +194 -0
- data/ext/argon2id/libargon2/thread.c +57 -0
- data/ext/argon2id/libargon2/thread.h +67 -0
- data/lib/argon2id/3.1/argon2id.so +0 -0
- data/lib/argon2id/3.2/argon2id.so +0 -0
- data/lib/argon2id/3.3/argon2id.so +0 -0
- data/lib/argon2id/3.4/argon2id.so +0 -0
- data/lib/argon2id/extension.rb +71 -0
- data/lib/argon2id/password.rb +142 -0
- data/lib/argon2id/version.rb +5 -0
- data/lib/argon2id.rb +45 -0
- data/test/argon2id/test_password.rb +554 -0
- data/test/test_argon2id.rb +66 -0
- metadata +132 -0
@@ -0,0 +1,228 @@
|
|
1
|
+
/*
|
2
|
+
* Argon2 reference source code package - reference C implementations
|
3
|
+
*
|
4
|
+
* Copyright 2015
|
5
|
+
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
6
|
+
*
|
7
|
+
* You may use this work under the terms of a Creative Commons CC0 1.0
|
8
|
+
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
9
|
+
* these licenses can be found at:
|
10
|
+
*
|
11
|
+
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
12
|
+
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
*
|
14
|
+
* You should have received a copy of both of these licenses along with this
|
15
|
+
* software. If not, they may be obtained at the above URLs.
|
16
|
+
*/
|
17
|
+
|
18
|
+
#ifndef ARGON2_CORE_H
|
19
|
+
#define ARGON2_CORE_H
|
20
|
+
|
21
|
+
#include "argon2.h"
|
22
|
+
|
23
|
+
#define CONST_CAST(x) (x)(uintptr_t)
|
24
|
+
|
25
|
+
/**********************Argon2 internal constants*******************************/
|
26
|
+
|
27
|
+
enum argon2_core_constants {
|
28
|
+
/* Memory block size in bytes */
|
29
|
+
ARGON2_BLOCK_SIZE = 1024,
|
30
|
+
ARGON2_QWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 8,
|
31
|
+
ARGON2_OWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 16,
|
32
|
+
ARGON2_HWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 32,
|
33
|
+
ARGON2_512BIT_WORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 64,
|
34
|
+
|
35
|
+
/* Number of pseudo-random values generated by one call to Blake in Argon2i
|
36
|
+
to
|
37
|
+
generate reference block positions */
|
38
|
+
ARGON2_ADDRESSES_IN_BLOCK = 128,
|
39
|
+
|
40
|
+
/* Pre-hashing digest length and its extension*/
|
41
|
+
ARGON2_PREHASH_DIGEST_LENGTH = 64,
|
42
|
+
ARGON2_PREHASH_SEED_LENGTH = 72
|
43
|
+
};
|
44
|
+
|
45
|
+
/*************************Argon2 internal data types***********************/
|
46
|
+
|
47
|
+
/*
|
48
|
+
* Structure for the (1KB) memory block implemented as 128 64-bit words.
|
49
|
+
* Memory blocks can be copied, XORed. Internal words can be accessed by [] (no
|
50
|
+
* bounds checking).
|
51
|
+
*/
|
52
|
+
typedef struct block_ { uint64_t v[ARGON2_QWORDS_IN_BLOCK]; } block;
|
53
|
+
|
54
|
+
/*****************Functions that work with the block******************/
|
55
|
+
|
56
|
+
/* Initialize each byte of the block with @in */
|
57
|
+
void init_block_value(block *b, uint8_t in);
|
58
|
+
|
59
|
+
/* Copy block @src to block @dst */
|
60
|
+
void copy_block(block *dst, const block *src);
|
61
|
+
|
62
|
+
/* XOR @src onto @dst bytewise */
|
63
|
+
void xor_block(block *dst, const block *src);
|
64
|
+
|
65
|
+
/*
|
66
|
+
* Argon2 instance: memory pointer, number of passes, amount of memory, type,
|
67
|
+
* and derived values.
|
68
|
+
* Used to evaluate the number and location of blocks to construct in each
|
69
|
+
* thread
|
70
|
+
*/
|
71
|
+
typedef struct Argon2_instance_t {
|
72
|
+
block *memory; /* Memory pointer */
|
73
|
+
uint32_t version;
|
74
|
+
uint32_t passes; /* Number of passes */
|
75
|
+
uint32_t memory_blocks; /* Number of blocks in memory */
|
76
|
+
uint32_t segment_length;
|
77
|
+
uint32_t lane_length;
|
78
|
+
uint32_t lanes;
|
79
|
+
uint32_t threads;
|
80
|
+
argon2_type type;
|
81
|
+
int print_internals; /* whether to print the memory blocks */
|
82
|
+
argon2_context *context_ptr; /* points back to original context */
|
83
|
+
} argon2_instance_t;
|
84
|
+
|
85
|
+
/*
|
86
|
+
* Argon2 position: where we construct the block right now. Used to distribute
|
87
|
+
* work between threads.
|
88
|
+
*/
|
89
|
+
typedef struct Argon2_position_t {
|
90
|
+
uint32_t pass;
|
91
|
+
uint32_t lane;
|
92
|
+
uint8_t slice;
|
93
|
+
uint32_t index;
|
94
|
+
} argon2_position_t;
|
95
|
+
|
96
|
+
/*Struct that holds the inputs for thread handling FillSegment*/
|
97
|
+
typedef struct Argon2_thread_data {
|
98
|
+
argon2_instance_t *instance_ptr;
|
99
|
+
argon2_position_t pos;
|
100
|
+
} argon2_thread_data;
|
101
|
+
|
102
|
+
/*************************Argon2 core functions********************************/
|
103
|
+
|
104
|
+
/* Allocates memory to the given pointer, uses the appropriate allocator as
|
105
|
+
* specified in the context. Total allocated memory is num*size.
|
106
|
+
* @param context argon2_context which specifies the allocator
|
107
|
+
* @param memory pointer to the pointer to the memory
|
108
|
+
* @param size the size in bytes for each element to be allocated
|
109
|
+
* @param num the number of elements to be allocated
|
110
|
+
* @return ARGON2_OK if @memory is a valid pointer and memory is allocated
|
111
|
+
*/
|
112
|
+
int allocate_memory(const argon2_context *context, uint8_t **memory,
|
113
|
+
size_t num, size_t size);
|
114
|
+
|
115
|
+
/*
|
116
|
+
* Frees memory at the given pointer, uses the appropriate deallocator as
|
117
|
+
* specified in the context. Also cleans the memory using clear_internal_memory.
|
118
|
+
* @param context argon2_context which specifies the deallocator
|
119
|
+
* @param memory pointer to buffer to be freed
|
120
|
+
* @param size the size in bytes for each element to be deallocated
|
121
|
+
* @param num the number of elements to be deallocated
|
122
|
+
*/
|
123
|
+
void free_memory(const argon2_context *context, uint8_t *memory,
|
124
|
+
size_t num, size_t size);
|
125
|
+
|
126
|
+
/* Function that securely cleans the memory. This ignores any flags set
|
127
|
+
* regarding clearing memory. Usually one just calls clear_internal_memory.
|
128
|
+
* @param mem Pointer to the memory
|
129
|
+
* @param s Memory size in bytes
|
130
|
+
*/
|
131
|
+
void secure_wipe_memory(void *v, size_t n);
|
132
|
+
|
133
|
+
/* Function that securely clears the memory if FLAG_clear_internal_memory is
|
134
|
+
* set. If the flag isn't set, this function does nothing.
|
135
|
+
* @param mem Pointer to the memory
|
136
|
+
* @param s Memory size in bytes
|
137
|
+
*/
|
138
|
+
void clear_internal_memory(void *v, size_t n);
|
139
|
+
|
140
|
+
/*
|
141
|
+
* Computes absolute position of reference block in the lane following a skewed
|
142
|
+
* distribution and using a pseudo-random value as input
|
143
|
+
* @param instance Pointer to the current instance
|
144
|
+
* @param position Pointer to the current position
|
145
|
+
* @param pseudo_rand 32-bit pseudo-random value used to determine the position
|
146
|
+
* @param same_lane Indicates if the block will be taken from the current lane.
|
147
|
+
* If so we can reference the current segment
|
148
|
+
* @pre All pointers must be valid
|
149
|
+
*/
|
150
|
+
uint32_t index_alpha(const argon2_instance_t *instance,
|
151
|
+
const argon2_position_t *position, uint32_t pseudo_rand,
|
152
|
+
int same_lane);
|
153
|
+
|
154
|
+
/*
|
155
|
+
* Function that validates all inputs against predefined restrictions and return
|
156
|
+
* an error code
|
157
|
+
* @param context Pointer to current Argon2 context
|
158
|
+
* @return ARGON2_OK if everything is all right, otherwise one of error codes
|
159
|
+
* (all defined in <argon2.h>
|
160
|
+
*/
|
161
|
+
int validate_inputs(const argon2_context *context);
|
162
|
+
|
163
|
+
/*
|
164
|
+
* Hashes all the inputs into @a blockhash[PREHASH_DIGEST_LENGTH], clears
|
165
|
+
* password and secret if needed
|
166
|
+
* @param context Pointer to the Argon2 internal structure containing memory
|
167
|
+
* pointer, and parameters for time and space requirements.
|
168
|
+
* @param blockhash Buffer for pre-hashing digest
|
169
|
+
* @param type Argon2 type
|
170
|
+
* @pre @a blockhash must have at least @a PREHASH_DIGEST_LENGTH bytes
|
171
|
+
* allocated
|
172
|
+
*/
|
173
|
+
void initial_hash(uint8_t *blockhash, argon2_context *context,
|
174
|
+
argon2_type type);
|
175
|
+
|
176
|
+
/*
|
177
|
+
* Function creates first 2 blocks per lane
|
178
|
+
* @param instance Pointer to the current instance
|
179
|
+
* @param blockhash Pointer to the pre-hashing digest
|
180
|
+
* @pre blockhash must point to @a PREHASH_SEED_LENGTH allocated values
|
181
|
+
*/
|
182
|
+
void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance);
|
183
|
+
|
184
|
+
/*
|
185
|
+
* Function allocates memory, hashes the inputs with Blake, and creates first
|
186
|
+
* two blocks. Returns the pointer to the main memory with 2 blocks per lane
|
187
|
+
* initialized
|
188
|
+
* @param context Pointer to the Argon2 internal structure containing memory
|
189
|
+
* pointer, and parameters for time and space requirements.
|
190
|
+
* @param instance Current Argon2 instance
|
191
|
+
* @return Zero if successful, -1 if memory failed to allocate. @context->state
|
192
|
+
* will be modified if successful.
|
193
|
+
*/
|
194
|
+
int initialize(argon2_instance_t *instance, argon2_context *context);
|
195
|
+
|
196
|
+
/*
|
197
|
+
* XORing the last block of each lane, hashing it, making the tag. Deallocates
|
198
|
+
* the memory.
|
199
|
+
* @param context Pointer to current Argon2 context (use only the out parameters
|
200
|
+
* from it)
|
201
|
+
* @param instance Pointer to current instance of Argon2
|
202
|
+
* @pre instance->state must point to necessary amount of memory
|
203
|
+
* @pre context->out must point to outlen bytes of memory
|
204
|
+
* @pre if context->free_cbk is not NULL, it should point to a function that
|
205
|
+
* deallocates memory
|
206
|
+
*/
|
207
|
+
void finalize(const argon2_context *context, argon2_instance_t *instance);
|
208
|
+
|
209
|
+
/*
|
210
|
+
* Function that fills the segment using previous segments also from other
|
211
|
+
* threads
|
212
|
+
* @param context current context
|
213
|
+
* @param instance Pointer to the current instance
|
214
|
+
* @param position Current position
|
215
|
+
* @pre all block pointers must be valid
|
216
|
+
*/
|
217
|
+
void fill_segment(const argon2_instance_t *instance,
|
218
|
+
argon2_position_t position);
|
219
|
+
|
220
|
+
/*
|
221
|
+
* Function that fills the entire memory t_cost times based on the first two
|
222
|
+
* blocks in each lane
|
223
|
+
* @param instance Pointer to the current instance
|
224
|
+
* @return ARGON2_OK if successful, @context->state
|
225
|
+
*/
|
226
|
+
int fill_memory_blocks(argon2_instance_t *instance);
|
227
|
+
|
228
|
+
#endif
|
@@ -0,0 +1,463 @@
|
|
1
|
+
/*
|
2
|
+
* Argon2 reference source code package - reference C implementations
|
3
|
+
*
|
4
|
+
* Copyright 2015
|
5
|
+
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
6
|
+
*
|
7
|
+
* You may use this work under the terms of a Creative Commons CC0 1.0
|
8
|
+
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
9
|
+
* these licenses can be found at:
|
10
|
+
*
|
11
|
+
* - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
12
|
+
* - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
13
|
+
*
|
14
|
+
* You should have received a copy of both of these licenses along with this
|
15
|
+
* software. If not, they may be obtained at the above URLs.
|
16
|
+
*/
|
17
|
+
|
18
|
+
#include <stdio.h>
|
19
|
+
#include <stdlib.h>
|
20
|
+
#include <string.h>
|
21
|
+
#include <limits.h>
|
22
|
+
#include "encoding.h"
|
23
|
+
#include "core.h"
|
24
|
+
|
25
|
+
/*
|
26
|
+
* Example code for a decoder and encoder of "hash strings", with Argon2
|
27
|
+
* parameters.
|
28
|
+
*
|
29
|
+
* This code comprises three sections:
|
30
|
+
*
|
31
|
+
* -- The first section contains generic Base64 encoding and decoding
|
32
|
+
* functions. It is conceptually applicable to any hash function
|
33
|
+
* implementation that uses Base64 to encode and decode parameters,
|
34
|
+
* salts and outputs. It could be made into a library, provided that
|
35
|
+
* the relevant functions are made public (non-static) and be given
|
36
|
+
* reasonable names to avoid collisions with other functions.
|
37
|
+
*
|
38
|
+
* -- The second section is specific to Argon2. It encodes and decodes
|
39
|
+
* the parameters, salts and outputs. It does not compute the hash
|
40
|
+
* itself.
|
41
|
+
*
|
42
|
+
* The code was originally written by Thomas Pornin <pornin@bolet.org>,
|
43
|
+
* to whom comments and remarks may be sent. It is released under what
|
44
|
+
* should amount to Public Domain or its closest equivalent; the
|
45
|
+
* following mantra is supposed to incarnate that fact with all the
|
46
|
+
* proper legal rituals:
|
47
|
+
*
|
48
|
+
* ---------------------------------------------------------------------
|
49
|
+
* This file is provided under the terms of Creative Commons CC0 1.0
|
50
|
+
* Public Domain Dedication. To the extent possible under law, the
|
51
|
+
* author (Thomas Pornin) has waived all copyright and related or
|
52
|
+
* neighboring rights to this file. This work is published from: Canada.
|
53
|
+
* ---------------------------------------------------------------------
|
54
|
+
*
|
55
|
+
* Copyright (c) 2015 Thomas Pornin
|
56
|
+
*/
|
57
|
+
|
58
|
+
/* ==================================================================== */
|
59
|
+
/*
|
60
|
+
* Common code; could be shared between different hash functions.
|
61
|
+
*
|
62
|
+
* Note: the Base64 functions below assume that uppercase letters (resp.
|
63
|
+
* lowercase letters) have consecutive numerical codes, that fit on 8
|
64
|
+
* bits. All modern systems use ASCII-compatible charsets, where these
|
65
|
+
* properties are true. If you are stuck with a dinosaur of a system
|
66
|
+
* that still defaults to EBCDIC then you already have much bigger
|
67
|
+
* interoperability issues to deal with.
|
68
|
+
*/
|
69
|
+
|
70
|
+
/*
|
71
|
+
* Some macros for constant-time comparisons. These work over values in
|
72
|
+
* the 0..255 range. Returned value is 0x00 on "false", 0xFF on "true".
|
73
|
+
*/
|
74
|
+
#define EQ(x, y) ((((0U - ((unsigned)(x) ^ (unsigned)(y))) >> 8) & 0xFF) ^ 0xFF)
|
75
|
+
#define GT(x, y) ((((unsigned)(y) - (unsigned)(x)) >> 8) & 0xFF)
|
76
|
+
#define GE(x, y) (GT(y, x) ^ 0xFF)
|
77
|
+
#define LT(x, y) GT(y, x)
|
78
|
+
#define LE(x, y) GE(y, x)
|
79
|
+
|
80
|
+
/*
|
81
|
+
* Convert value x (0..63) to corresponding Base64 character.
|
82
|
+
*/
|
83
|
+
static int b64_byte_to_char(unsigned x) {
|
84
|
+
return (LT(x, 26) & (x + 'A')) |
|
85
|
+
(GE(x, 26) & LT(x, 52) & (x + ('a' - 26))) |
|
86
|
+
(GE(x, 52) & LT(x, 62) & (x + ('0' - 52))) | (EQ(x, 62) & '+') |
|
87
|
+
(EQ(x, 63) & '/');
|
88
|
+
}
|
89
|
+
|
90
|
+
/*
|
91
|
+
* Convert character c to the corresponding 6-bit value. If character c
|
92
|
+
* is not a Base64 character, then 0xFF (255) is returned.
|
93
|
+
*/
|
94
|
+
static unsigned b64_char_to_byte(int c) {
|
95
|
+
unsigned x;
|
96
|
+
|
97
|
+
x = (GE(c, 'A') & LE(c, 'Z') & (c - 'A')) |
|
98
|
+
(GE(c, 'a') & LE(c, 'z') & (c - ('a' - 26))) |
|
99
|
+
(GE(c, '0') & LE(c, '9') & (c - ('0' - 52))) | (EQ(c, '+') & 62) |
|
100
|
+
(EQ(c, '/') & 63);
|
101
|
+
return x | (EQ(x, 0) & (EQ(c, 'A') ^ 0xFF));
|
102
|
+
}
|
103
|
+
|
104
|
+
/*
|
105
|
+
* Convert some bytes to Base64. 'dst_len' is the length (in characters)
|
106
|
+
* of the output buffer 'dst'; if that buffer is not large enough to
|
107
|
+
* receive the result (including the terminating 0), then (size_t)-1
|
108
|
+
* is returned. Otherwise, the zero-terminated Base64 string is written
|
109
|
+
* in the buffer, and the output length (counted WITHOUT the terminating
|
110
|
+
* zero) is returned.
|
111
|
+
*/
|
112
|
+
static size_t to_base64(char *dst, size_t dst_len, const void *src,
|
113
|
+
size_t src_len) {
|
114
|
+
size_t olen;
|
115
|
+
const unsigned char *buf;
|
116
|
+
unsigned acc, acc_len;
|
117
|
+
|
118
|
+
olen = (src_len / 3) << 2;
|
119
|
+
switch (src_len % 3) {
|
120
|
+
case 2:
|
121
|
+
olen++;
|
122
|
+
/* fall through */
|
123
|
+
case 1:
|
124
|
+
olen += 2;
|
125
|
+
break;
|
126
|
+
}
|
127
|
+
if (dst_len <= olen) {
|
128
|
+
return (size_t)-1;
|
129
|
+
}
|
130
|
+
acc = 0;
|
131
|
+
acc_len = 0;
|
132
|
+
buf = (const unsigned char *)src;
|
133
|
+
while (src_len-- > 0) {
|
134
|
+
acc = (acc << 8) + (*buf++);
|
135
|
+
acc_len += 8;
|
136
|
+
while (acc_len >= 6) {
|
137
|
+
acc_len -= 6;
|
138
|
+
*dst++ = (char)b64_byte_to_char((acc >> acc_len) & 0x3F);
|
139
|
+
}
|
140
|
+
}
|
141
|
+
if (acc_len > 0) {
|
142
|
+
*dst++ = (char)b64_byte_to_char((acc << (6 - acc_len)) & 0x3F);
|
143
|
+
}
|
144
|
+
*dst++ = 0;
|
145
|
+
return olen;
|
146
|
+
}
|
147
|
+
|
148
|
+
/*
|
149
|
+
* Decode Base64 chars into bytes. The '*dst_len' value must initially
|
150
|
+
* contain the length of the output buffer '*dst'; when the decoding
|
151
|
+
* ends, the actual number of decoded bytes is written back in
|
152
|
+
* '*dst_len'.
|
153
|
+
*
|
154
|
+
* Decoding stops when a non-Base64 character is encountered, or when
|
155
|
+
* the output buffer capacity is exceeded. If an error occurred (output
|
156
|
+
* buffer is too small, invalid last characters leading to unprocessed
|
157
|
+
* buffered bits), then NULL is returned; otherwise, the returned value
|
158
|
+
* points to the first non-Base64 character in the source stream, which
|
159
|
+
* may be the terminating zero.
|
160
|
+
*/
|
161
|
+
static const char *from_base64(void *dst, size_t *dst_len, const char *src) {
|
162
|
+
size_t len;
|
163
|
+
unsigned char *buf;
|
164
|
+
unsigned acc, acc_len;
|
165
|
+
|
166
|
+
buf = (unsigned char *)dst;
|
167
|
+
len = 0;
|
168
|
+
acc = 0;
|
169
|
+
acc_len = 0;
|
170
|
+
for (;;) {
|
171
|
+
unsigned d;
|
172
|
+
|
173
|
+
d = b64_char_to_byte(*src);
|
174
|
+
if (d == 0xFF) {
|
175
|
+
break;
|
176
|
+
}
|
177
|
+
src++;
|
178
|
+
acc = (acc << 6) + d;
|
179
|
+
acc_len += 6;
|
180
|
+
if (acc_len >= 8) {
|
181
|
+
acc_len -= 8;
|
182
|
+
if ((len++) >= *dst_len) {
|
183
|
+
return NULL;
|
184
|
+
}
|
185
|
+
*buf++ = (acc >> acc_len) & 0xFF;
|
186
|
+
}
|
187
|
+
}
|
188
|
+
|
189
|
+
/*
|
190
|
+
* If the input length is equal to 1 modulo 4 (which is
|
191
|
+
* invalid), then there will remain 6 unprocessed bits;
|
192
|
+
* otherwise, only 0, 2 or 4 bits are buffered. The buffered
|
193
|
+
* bits must also all be zero.
|
194
|
+
*/
|
195
|
+
if (acc_len > 4 || (acc & (((unsigned)1 << acc_len) - 1)) != 0) {
|
196
|
+
return NULL;
|
197
|
+
}
|
198
|
+
*dst_len = len;
|
199
|
+
return src;
|
200
|
+
}
|
201
|
+
|
202
|
+
/*
|
203
|
+
* Decode decimal integer from 'str'; the value is written in '*v'.
|
204
|
+
* Returned value is a pointer to the next non-decimal character in the
|
205
|
+
* string. If there is no digit at all, or the value encoding is not
|
206
|
+
* minimal (extra leading zeros), or the value does not fit in an
|
207
|
+
* 'unsigned long', then NULL is returned.
|
208
|
+
*/
|
209
|
+
static const char *decode_decimal(const char *str, unsigned long *v) {
|
210
|
+
const char *orig;
|
211
|
+
unsigned long acc;
|
212
|
+
|
213
|
+
acc = 0;
|
214
|
+
for (orig = str;; str++) {
|
215
|
+
int c;
|
216
|
+
|
217
|
+
c = *str;
|
218
|
+
if (c < '0' || c > '9') {
|
219
|
+
break;
|
220
|
+
}
|
221
|
+
c -= '0';
|
222
|
+
if (acc > (ULONG_MAX / 10)) {
|
223
|
+
return NULL;
|
224
|
+
}
|
225
|
+
acc *= 10;
|
226
|
+
if ((unsigned long)c > (ULONG_MAX - acc)) {
|
227
|
+
return NULL;
|
228
|
+
}
|
229
|
+
acc += (unsigned long)c;
|
230
|
+
}
|
231
|
+
if (str == orig || (*orig == '0' && str != (orig + 1))) {
|
232
|
+
return NULL;
|
233
|
+
}
|
234
|
+
*v = acc;
|
235
|
+
return str;
|
236
|
+
}
|
237
|
+
|
238
|
+
/* ==================================================================== */
|
239
|
+
/*
|
240
|
+
* Code specific to Argon2.
|
241
|
+
*
|
242
|
+
* The code below applies the following format:
|
243
|
+
*
|
244
|
+
* $argon2<T>[$v=<num>]$m=<num>,t=<num>,p=<num>$<bin>$<bin>
|
245
|
+
*
|
246
|
+
* where <T> is either 'd', 'id', or 'i', <num> is a decimal integer (positive,
|
247
|
+
* fits in an 'unsigned long'), and <bin> is Base64-encoded data (no '=' padding
|
248
|
+
* characters, no newline or whitespace).
|
249
|
+
*
|
250
|
+
* The last two binary chunks (encoded in Base64) are, in that order,
|
251
|
+
* the salt and the output. Both are required. The binary salt length and the
|
252
|
+
* output length must be in the allowed ranges defined in argon2.h.
|
253
|
+
*
|
254
|
+
* The ctx struct must contain buffers large enough to hold the salt and pwd
|
255
|
+
* when it is fed into decode_string.
|
256
|
+
*/
|
257
|
+
|
258
|
+
int decode_string(argon2_context *ctx, const char *str, argon2_type type) {
|
259
|
+
|
260
|
+
/* check for prefix */
|
261
|
+
#define CC(prefix) \
|
262
|
+
do { \
|
263
|
+
size_t cc_len = strlen(prefix); \
|
264
|
+
if (strncmp(str, prefix, cc_len) != 0) { \
|
265
|
+
return ARGON2_DECODING_FAIL; \
|
266
|
+
} \
|
267
|
+
str += cc_len; \
|
268
|
+
} while ((void)0, 0)
|
269
|
+
|
270
|
+
/* optional prefix checking with supplied code */
|
271
|
+
#define CC_opt(prefix, code) \
|
272
|
+
do { \
|
273
|
+
size_t cc_len = strlen(prefix); \
|
274
|
+
if (strncmp(str, prefix, cc_len) == 0) { \
|
275
|
+
str += cc_len; \
|
276
|
+
{ code; } \
|
277
|
+
} \
|
278
|
+
} while ((void)0, 0)
|
279
|
+
|
280
|
+
/* Decoding prefix into decimal */
|
281
|
+
#define DECIMAL(x) \
|
282
|
+
do { \
|
283
|
+
unsigned long dec_x; \
|
284
|
+
str = decode_decimal(str, &dec_x); \
|
285
|
+
if (str == NULL) { \
|
286
|
+
return ARGON2_DECODING_FAIL; \
|
287
|
+
} \
|
288
|
+
(x) = dec_x; \
|
289
|
+
} while ((void)0, 0)
|
290
|
+
|
291
|
+
|
292
|
+
/* Decoding prefix into uint32_t decimal */
|
293
|
+
#define DECIMAL_U32(x) \
|
294
|
+
do { \
|
295
|
+
unsigned long dec_x; \
|
296
|
+
str = decode_decimal(str, &dec_x); \
|
297
|
+
if (str == NULL || dec_x > UINT32_MAX) { \
|
298
|
+
return ARGON2_DECODING_FAIL; \
|
299
|
+
} \
|
300
|
+
(x) = (uint32_t)dec_x; \
|
301
|
+
} while ((void)0, 0)
|
302
|
+
|
303
|
+
|
304
|
+
/* Decoding base64 into a binary buffer */
|
305
|
+
#define BIN(buf, max_len, len) \
|
306
|
+
do { \
|
307
|
+
size_t bin_len = (max_len); \
|
308
|
+
str = from_base64(buf, &bin_len, str); \
|
309
|
+
if (str == NULL || bin_len > UINT32_MAX) { \
|
310
|
+
return ARGON2_DECODING_FAIL; \
|
311
|
+
} \
|
312
|
+
(len) = (uint32_t)bin_len; \
|
313
|
+
} while ((void)0, 0)
|
314
|
+
|
315
|
+
size_t maxsaltlen = ctx->saltlen;
|
316
|
+
size_t maxoutlen = ctx->outlen;
|
317
|
+
int validation_result;
|
318
|
+
const char* type_string;
|
319
|
+
|
320
|
+
/* We should start with the argon2_type we are using */
|
321
|
+
type_string = argon2_type2string(type, 0);
|
322
|
+
if (!type_string) {
|
323
|
+
return ARGON2_INCORRECT_TYPE;
|
324
|
+
}
|
325
|
+
|
326
|
+
CC("$");
|
327
|
+
CC(type_string);
|
328
|
+
|
329
|
+
/* Reading the version number if the default is suppressed */
|
330
|
+
ctx->version = ARGON2_VERSION_10;
|
331
|
+
CC_opt("$v=", DECIMAL_U32(ctx->version));
|
332
|
+
|
333
|
+
CC("$m=");
|
334
|
+
DECIMAL_U32(ctx->m_cost);
|
335
|
+
CC(",t=");
|
336
|
+
DECIMAL_U32(ctx->t_cost);
|
337
|
+
CC(",p=");
|
338
|
+
DECIMAL_U32(ctx->lanes);
|
339
|
+
ctx->threads = ctx->lanes;
|
340
|
+
|
341
|
+
CC("$");
|
342
|
+
BIN(ctx->salt, maxsaltlen, ctx->saltlen);
|
343
|
+
CC("$");
|
344
|
+
BIN(ctx->out, maxoutlen, ctx->outlen);
|
345
|
+
|
346
|
+
/* The rest of the fields get the default values */
|
347
|
+
ctx->secret = NULL;
|
348
|
+
ctx->secretlen = 0;
|
349
|
+
ctx->ad = NULL;
|
350
|
+
ctx->adlen = 0;
|
351
|
+
ctx->allocate_cbk = NULL;
|
352
|
+
ctx->free_cbk = NULL;
|
353
|
+
ctx->flags = ARGON2_DEFAULT_FLAGS;
|
354
|
+
|
355
|
+
/* On return, must have valid context */
|
356
|
+
validation_result = validate_inputs(ctx);
|
357
|
+
if (validation_result != ARGON2_OK) {
|
358
|
+
return validation_result;
|
359
|
+
}
|
360
|
+
|
361
|
+
/* Can't have any additional characters */
|
362
|
+
if (*str == 0) {
|
363
|
+
return ARGON2_OK;
|
364
|
+
} else {
|
365
|
+
return ARGON2_DECODING_FAIL;
|
366
|
+
}
|
367
|
+
#undef CC
|
368
|
+
#undef CC_opt
|
369
|
+
#undef DECIMAL
|
370
|
+
#undef BIN
|
371
|
+
}
|
372
|
+
|
373
|
+
int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
|
374
|
+
argon2_type type) {
|
375
|
+
#define SS(str) \
|
376
|
+
do { \
|
377
|
+
size_t pp_len = strlen(str); \
|
378
|
+
if (pp_len >= dst_len) { \
|
379
|
+
return ARGON2_ENCODING_FAIL; \
|
380
|
+
} \
|
381
|
+
memcpy(dst, str, pp_len + 1); \
|
382
|
+
dst += pp_len; \
|
383
|
+
dst_len -= pp_len; \
|
384
|
+
} while ((void)0, 0)
|
385
|
+
|
386
|
+
#define SX(x) \
|
387
|
+
do { \
|
388
|
+
char tmp[30]; \
|
389
|
+
sprintf(tmp, "%lu", (unsigned long)(x)); \
|
390
|
+
SS(tmp); \
|
391
|
+
} while ((void)0, 0)
|
392
|
+
|
393
|
+
#define SB(buf, len) \
|
394
|
+
do { \
|
395
|
+
size_t sb_len = to_base64(dst, dst_len, buf, len); \
|
396
|
+
if (sb_len == (size_t)-1) { \
|
397
|
+
return ARGON2_ENCODING_FAIL; \
|
398
|
+
} \
|
399
|
+
dst += sb_len; \
|
400
|
+
dst_len -= sb_len; \
|
401
|
+
} while ((void)0, 0)
|
402
|
+
|
403
|
+
const char* type_string = argon2_type2string(type, 0);
|
404
|
+
int validation_result = validate_inputs(ctx);
|
405
|
+
|
406
|
+
if (!type_string) {
|
407
|
+
return ARGON2_ENCODING_FAIL;
|
408
|
+
}
|
409
|
+
|
410
|
+
if (validation_result != ARGON2_OK) {
|
411
|
+
return validation_result;
|
412
|
+
}
|
413
|
+
|
414
|
+
|
415
|
+
SS("$");
|
416
|
+
SS(type_string);
|
417
|
+
|
418
|
+
SS("$v=");
|
419
|
+
SX(ctx->version);
|
420
|
+
|
421
|
+
SS("$m=");
|
422
|
+
SX(ctx->m_cost);
|
423
|
+
SS(",t=");
|
424
|
+
SX(ctx->t_cost);
|
425
|
+
SS(",p=");
|
426
|
+
SX(ctx->lanes);
|
427
|
+
|
428
|
+
SS("$");
|
429
|
+
SB(ctx->salt, ctx->saltlen);
|
430
|
+
|
431
|
+
SS("$");
|
432
|
+
SB(ctx->out, ctx->outlen);
|
433
|
+
return ARGON2_OK;
|
434
|
+
|
435
|
+
#undef SS
|
436
|
+
#undef SX
|
437
|
+
#undef SB
|
438
|
+
}
|
439
|
+
|
440
|
+
size_t b64len(uint32_t len) {
|
441
|
+
size_t olen = ((size_t)len / 3) << 2;
|
442
|
+
|
443
|
+
switch (len % 3) {
|
444
|
+
case 2:
|
445
|
+
olen++;
|
446
|
+
/* fall through */
|
447
|
+
case 1:
|
448
|
+
olen += 2;
|
449
|
+
break;
|
450
|
+
}
|
451
|
+
|
452
|
+
return olen;
|
453
|
+
}
|
454
|
+
|
455
|
+
size_t numlen(uint32_t num) {
|
456
|
+
size_t len = 1;
|
457
|
+
while (num >= 10) {
|
458
|
+
++len;
|
459
|
+
num = num / 10;
|
460
|
+
}
|
461
|
+
return len;
|
462
|
+
}
|
463
|
+
|