1 /*
2 **********************************************************************
3 * Copyright (C) Miroslav Lichvar 2017
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 **********************************************************************
19 */
20
21 #include <config.h>
22 #include "test.h"
23
24 #if defined(FEAT_NTP) || defined(FEAT_CMDMON)
25
26 #include <keys.c>
27
28 #define KEYS 100
29 #define KEYFILE "keys.test-keys"
30
31 static
write_random_key(FILE * f)32 uint32_t write_random_key(FILE *f)
33 {
34 const char *type, *prefix;
35 char key[128];
36 uint32_t id;
37 int i, length;
38
39 length = random() % sizeof (key) + 1;
40 length = MAX(length, 4);
41 prefix = random() % 2 ? "HEX:" : "";
42
43 switch (random() % 8) {
44 #ifdef FEAT_SECHASH
45 case 0:
46 type = "SHA1";
47 break;
48 case 1:
49 type = "SHA256";
50 break;
51 case 2:
52 type = "SHA384";
53 break;
54 case 3:
55 type = "SHA512";
56 break;
57 #endif
58 #ifdef HAVE_CMAC
59 case 4:
60 type = "AES128";
61 length = prefix[0] == '\0' ? 8 : 16;
62 break;
63 case 5:
64 type = "AES256";
65 length = prefix[0] == '\0' ? 16 : 32;
66 break;
67 #endif
68 case 6:
69 type = "MD5";
70 break;
71 default:
72 type = "";
73 }
74
75 UTI_GetRandomBytes(&id, sizeof (id));
76 UTI_GetRandomBytes(key, length);
77
78 fprintf(f, "%u %s %s", id, type, prefix);
79 for (i = 0; i < length; i++)
80 fprintf(f, "%02hhX", key[i]);
81 fprintf(f, "\n");
82
83 return id;
84 }
85
86 static void
generate_key_file(const char * name,uint32_t * keys)87 generate_key_file(const char *name, uint32_t *keys)
88 {
89 FILE *f;
90 int i;
91
92 f = fopen(name, "w");
93 TEST_CHECK(f);
94 for (i = 0; i < KEYS; i++)
95 keys[i] = write_random_key(f);
96 fclose(f);
97 }
98
99 void
test_unit(void)100 test_unit(void)
101 {
102 int i, j, data_len, auth_len, type, bits;
103 uint32_t keys[KEYS], key;
104 unsigned char data[100], auth[MAX_HASH_LENGTH];
105 char conf[][100] = {
106 "keyfile "KEYFILE
107 };
108
109 CNF_Initialise(0, 0);
110 for (i = 0; i < sizeof conf / sizeof conf[0]; i++)
111 CNF_ParseLine(NULL, i + 1, conf[i]);
112
113 generate_key_file(KEYFILE, keys);
114 KEY_Initialise();
115
116 for (i = 0; i < 100; i++) {
117 DEBUG_LOG("iteration %d", i);
118
119 if (i) {
120 generate_key_file(KEYFILE, keys);
121 KEY_Reload();
122 }
123
124 UTI_GetRandomBytes(data, sizeof (data));
125
126 for (j = 0; j < KEYS; j++) {
127 TEST_CHECK(KEY_KeyKnown(keys[j]));
128 TEST_CHECK(KEY_GetAuthLength(keys[j]) >= 16);
129
130 data_len = random() % (sizeof (data) + 1);
131 auth_len = KEY_GenerateAuth(keys[j], data, data_len, auth, sizeof (auth));
132 TEST_CHECK(auth_len >= 16);
133
134 TEST_CHECK(KEY_CheckAuth(keys[j], data, data_len, auth, auth_len, auth_len));
135
136 if (j > 0 && keys[j - 1] != keys[j])
137 TEST_CHECK(!KEY_CheckAuth(keys[j - 1], data, data_len, auth, auth_len, auth_len));
138
139 auth_len = random() % auth_len + 1;
140 if (auth_len < MAX_HASH_LENGTH)
141 auth[auth_len]++;
142 TEST_CHECK(KEY_CheckAuth(keys[j], data, data_len, auth, auth_len, auth_len));
143
144 auth[auth_len - 1]++;
145 TEST_CHECK(!KEY_CheckAuth(keys[j], data, data_len, auth, auth_len, auth_len));
146
147 TEST_CHECK(KEY_GetKeyInfo(keys[j], &type, &bits));
148 TEST_CHECK(type > 0 && bits > 0);
149 }
150
151 for (j = 0; j < 1000; j++) {
152 UTI_GetRandomBytes(&key, sizeof (key));
153 if (KEY_KeyKnown(key))
154 continue;
155 TEST_CHECK(!KEY_GetKeyInfo(key, &type, &bits));
156 TEST_CHECK(!KEY_GenerateAuth(key, data, data_len, auth, sizeof (auth)));
157 TEST_CHECK(!KEY_CheckAuth(key, data, data_len, auth, auth_len, auth_len));
158 }
159 }
160
161 unlink(KEYFILE);
162
163 KEY_Finalise();
164 CNF_Finalise();
165 HSH_Finalise();
166 }
167 #else
168 void
test_unit(void)169 test_unit(void)
170 {
171 TEST_REQUIRE(0);
172 }
173 #endif
174