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