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 "argon2.h"
22#include "core.h"
23
24void initial_kat(const uint8_t *blockhash, const argon2_context *context,
25                 argon2_type type) {
26    unsigned i;
27
28    if (blockhash != NULL && context != NULL) {
29        printf("=======================================\n");
30
31        printf("%s version number %d\n", argon2_type2string(type, 1),
32               context->version);
33
34        printf("=======================================\n");
35
36
37        printf("Memory: %u KiB, Iterations: %u, Parallelism: %u lanes, Tag "
38               "length: %u bytes\n",
39               context->m_cost, context->t_cost, context->lanes,
40               context->outlen);
41
42        printf("Password[%u]: ", context->pwdlen);
43
44        if (context->flags & ARGON2_FLAG_CLEAR_PASSWORD) {
45            printf("CLEARED\n");
46        } else {
47            for (i = 0; i < context->pwdlen; ++i) {
48                printf("%2.2x ", ((unsigned char *)context->pwd)[i]);
49            }
50
51            printf("\n");
52        }
53
54        printf("Salt[%u]: ", context->saltlen);
55
56        for (i = 0; i < context->saltlen; ++i) {
57            printf("%2.2x ", ((unsigned char *)context->salt)[i]);
58        }
59
60        printf("\n");
61
62        printf("Secret[%u]: ", context->secretlen);
63
64        if (context->flags & ARGON2_FLAG_CLEAR_SECRET) {
65            printf("CLEARED\n");
66        } else {
67            for (i = 0; i < context->secretlen; ++i) {
68                printf("%2.2x ", ((unsigned char *)context->secret)[i]);
69            }
70
71            printf("\n");
72        }
73
74        printf("Associated data[%u]: ", context->adlen);
75
76        for (i = 0; i < context->adlen; ++i) {
77            printf("%2.2x ", ((unsigned char *)context->ad)[i]);
78        }
79
80        printf("\n");
81
82        printf("Pre-hashing digest: ");
83
84        for (i = 0; i < ARGON2_PREHASH_DIGEST_LENGTH; ++i) {
85            printf("%2.2x ", ((unsigned char *)blockhash)[i]);
86        }
87
88        printf("\n");
89    }
90}
91
92void print_tag(const void *out, uint32_t outlen) {
93    unsigned i;
94    if (out != NULL) {
95        printf("Tag: ");
96
97        for (i = 0; i < outlen; ++i) {
98            printf("%2.2x ", ((uint8_t *)out)[i]);
99        }
100
101        printf("\n");
102    }
103}
104
105void internal_kat(const argon2_instance_t *instance, uint32_t pass) {
106
107    if (instance != NULL) {
108        uint32_t i, j;
109        printf("\n After pass %u:\n", pass);
110
111        for (i = 0; i < instance->memory_blocks; ++i) {
112            uint32_t how_many_words =
113                (instance->memory_blocks > ARGON2_QWORDS_IN_BLOCK)
114                    ? 1
115                    : ARGON2_QWORDS_IN_BLOCK;
116
117            for (j = 0; j < how_many_words; ++j)
118                printf("Block %.4u [%3u]: %016llx\n", i, j,
119                       (unsigned long long)instance->memory[i].v[j]);
120        }
121    }
122}
123
124static void fatal(const char *error) {
125    fprintf(stderr, "Error: %s\n", error);
126    exit(1);
127}
128
129static void generate_testvectors(argon2_type type, const uint32_t version) {
130#define TEST_OUTLEN 32
131#define TEST_PWDLEN 32
132#define TEST_SALTLEN 16
133#define TEST_SECRETLEN 8
134#define TEST_ADLEN 12
135    argon2_context context;
136
137    unsigned char out[TEST_OUTLEN];
138    unsigned char pwd[TEST_PWDLEN];
139    unsigned char salt[TEST_SALTLEN];
140    unsigned char secret[TEST_SECRETLEN];
141    unsigned char ad[TEST_ADLEN];
142    const allocate_fptr myown_allocator = NULL;
143    const deallocate_fptr myown_deallocator = NULL;
144
145    unsigned t_cost = 3;
146    unsigned m_cost = 32;
147    unsigned lanes = 4;
148
149    memset(pwd, 1, TEST_OUTLEN);
150    memset(salt, 2, TEST_SALTLEN);
151    memset(secret, 3, TEST_SECRETLEN);
152    memset(ad, 4, TEST_ADLEN);
153
154    context.out = out;
155    context.outlen = TEST_OUTLEN;
156    context.version = version;
157    context.pwd = pwd;
158    context.pwdlen = TEST_PWDLEN;
159    context.salt = salt;
160    context.saltlen = TEST_SALTLEN;
161    context.secret = secret;
162    context.secretlen = TEST_SECRETLEN;
163    context.ad = ad;
164    context.adlen = TEST_ADLEN;
165    context.t_cost = t_cost;
166    context.m_cost = m_cost;
167    context.lanes = lanes;
168    context.threads = lanes;
169    context.allocate_cbk = myown_allocator;
170    context.free_cbk = myown_deallocator;
171    context.flags = ARGON2_DEFAULT_FLAGS;
172
173#undef TEST_OUTLEN
174#undef TEST_PWDLEN
175#undef TEST_SALTLEN
176#undef TEST_SECRETLEN
177#undef TEST_ADLEN
178
179    argon2_ctx(&context, type);
180}
181
182int main(int argc, char *argv[]) {
183    /* Get and check Argon2 type */
184    const char *type_str = (argc > 1) ? argv[1] : "i";
185    argon2_type type = Argon2_i;
186    uint32_t version = ARGON2_VERSION_NUMBER;
187    if (!strcmp(type_str, "d")) {
188        type = Argon2_d;
189    } else if (!strcmp(type_str, "i")) {
190        type = Argon2_i;
191    } else if (!strcmp(type_str, "id")) {
192        type = Argon2_id;
193    } else {
194        fatal("wrong Argon2 type");
195    }
196
197    /* Get and check Argon2 version number */
198    if (argc > 2) {
199        version = strtoul(argv[2], NULL, 10);
200    }
201    if (ARGON2_VERSION_10 != version && ARGON2_VERSION_NUMBER != version) {
202        fatal("wrong Argon2 version number");
203    }
204
205    generate_testvectors(type, version);
206    return ARGON2_OK;
207}
208