1 /* Copyright (C) 2018 vt@altlinux.org
2 * Copyright (C) 2018 Björn Esser besser82@fedoraproject.org
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted.
6 *
7 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
8 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
9 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
10 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
11 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
12 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
15 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
16 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
17 * SUCH DAMAGE.
18 */
19
20 #include "crypt-port.h"
21
22 #if INCLUDE_gost_yescrypt
23
24 #include "alg-gost3411-2012-hmac.h"
25
26 #include <stdio.h>
27
28 /* redefine outer hmac to this function to test entropy bypass */
29 static void
30 test_outer_hmac (const uint8_t *k, size_t n, const uint8_t *t, size_t len,
31 uint8_t *out32, gost_hmac_256_t *gostbuf);
32 #define outer_gost_hmac256 test_outer_hmac
33 #include "../lib/crypt-gost-yescrypt.c"
34
35 static int test_mode = 0;
36
37 static void
38 test_outer_hmac (const uint8_t *k, size_t n, const uint8_t *t, size_t len,
39 uint8_t *out32, gost_hmac_256_t *gostbuf)
40 {
41 const uint8_t zero[32] = {0};
42
43 /* Zero one of arguments to outer hmac. */
44 if (test_mode & 1)
45 {
46 k = zero;
47 n = sizeof (zero);
48 }
49 if (test_mode & 2)
50 {
51 t = zero;
52 len = sizeof (zero);
53 }
54 gost_hmac256 (k, n, t, len, out32, gostbuf);
55 }
56
57 static int
58 test_crypt_raw (int m, int p, int s, char **a, size_t *a_size)
59 {
60 char output[CRYPT_OUTPUT_SIZE];
61 char pass[CRYPT_MAX_PASSPHRASE_SIZE];
62 char pref[CRYPT_GENSALT_OUTPUT_SIZE];
63 char scratch[ALG_SPECIFIC_SIZE];
64 char *salt;
65
66 test_mode = m;
67 fprintf (stderr, ".");
68 snprintf (pass, sizeof (pass), "%d", p);
69 snprintf (pref, sizeof (pref), "%15d", s);
70 salt = crypt_gensalt ("$gy$", 0, pref, (int) strlen(pref) + 1);
71 if (!salt || salt[0] == '*')
72 {
73 fprintf(stderr, "ERROR: entropy test (gensalt) [%s]\n", pref);
74 return 1;
75 }
76 crypt_gost_yescrypt_rn (pass, strlen (pass), salt, strlen (salt),
77 (uint8_t *) output, sizeof (output),
78 scratch, sizeof (scratch));
79 if (output[0] == '*')
80 {
81 fprintf(stderr, "ERROR: entropy test (crypt)\n");
82 return 1;
83 }
84 char *h = strrchr (output, '$') + 1;
85 if (*a && strstr (*a, h))
86 {
87 fprintf (stderr, "ERROR: duplicated hash %s\n", output);
88 return 1;
89 }
90 size_t len = strlen(h);
91 *a = realloc (*a, *a_size + len + 1);
92 strcpy (*a + *a_size, h);
93 *a_size += len;
94 (*a)[*a_size] = '\0';
95
96 return 0;
97 }
98
99 int
100 main (void)
101 {
102 int result = 0;
103
104 /* Entropy tests
105 * Replace left then right argument of outer hmac() with constant
106 * and do hashing, verifying that output hashes are still different
107 * when password or salt are changing.
108 * Thus, we prove that entropy is still passing to the output not
109 * depending on yescrypt. */
110
111 int m, pp, ss;
112 int etest = 0;
113 char **a = malloc (sizeof (char*));
114 size_t *a_size = malloc (sizeof (size_t));
115
116 *a = malloc (sizeof (char));
117 (*a)[0] = '\0';
118 *a_size = 0;
119
120 for (m = 1; m < 3; m++)
121 {
122 for (pp = 0; pp < 22; pp++)
123 etest |= test_crypt_raw (m, pp, 0, a, a_size);
124 for (ss = 0; ss < 22; ss++)
125 etest |= test_crypt_raw (m, pp, ss, a, a_size);
126 }
127 fprintf (stderr, "\n");
128 if (etest)
129 fprintf (stderr, "ERROR: entropy test failed.\n");
130 else
131 fprintf (stderr, " ok: entropy test\n");
132 result |= etest;
133
134 free (*a);
135 free (a);
136 free (a_size);
137
138 return result;
139 }
140
141 #else
142
143 int
144 main (void)
145 {
146 return 77; /* UNSUPPORTED */
147 }
148
149 #endif /* INCLUDE_gost_yescrypt */