Line data Source code
1 : /**
2 : * @file
3 : *
4 : * @brief test suite for the fcrypt plugin
5 : *
6 : * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
7 : *
8 : */
9 :
10 : #include <kdb.h>
11 : #include <kdbinternal.h>
12 : #include <stdio.h>
13 : #include <stdlib.h>
14 : #include <string.h>
15 : #include <tests_internal.h>
16 : #include <tests_plugin.h>
17 :
18 : #include <gpg.h>
19 : #include <test_key.h>
20 :
21 : #include "../crypto/common_gpg_tests.c"
22 : #include "../crypto/gpgagent_teardown.h"
23 : #include "fcrypt.h"
24 :
25 : #define PLUGIN_NAME "fcrypt"
26 : #define TEST_KEY_ID "DDEBEF9EE2DC931701338212DAF635B17F230E8D"
27 : #define TEST_FILE "fcrypt_testfile"
28 : #define BUFFER_SIZE 2048
29 :
30 : #define FAULTY_SIGNATURE_FILE \
31 : "-----BEGIN PGP SIGNED MESSAGE-----\n\
32 : Hash: SHA512\n\
33 : \n\
34 : test (modified)\n\
35 : -----BEGIN PGP SIGNATURE-----\n\
36 : \n\
37 : iJwEAQEKAAYFAlmqZsMACgkQ2vY1sX8jDo2etAP/UA4s7e+SR38wa+AqQbWXKrPp\n\
38 : i3hoYLPP9lIz5ypedFBlNjcJRjv47wvGc0Z2C1Q6pMtTNcI+is2X9zJNucv9aMeA\n\
39 : nghsNiEgaIARzOFIe13QTevCg/HEFnq48gFSYNyeVgcsPmVP6tu3xWoEUkVEu6Vf\n\
40 : XRrYPw+gFVq5zeOAI4A=\n\
41 : =MjjB\n\
42 : -----END PGP SIGNATURE-----\n"
43 :
44 : static const kdb_octet_t testContent[] = { 0x01, 0x02, 0xCA, 0xFE, 0xBA, 0xBE, 0x03, 0x04 };
45 :
46 0 : static KeySet * newPluginConfiguration (void)
47 : {
48 : // clang-format off
49 0 : return ksNew (3,
50 : keyNew (ELEKTRA_RECIPIENT_KEY, KEY_VALUE, TEST_KEY_ID, KEY_END),
51 : keyNew (ELEKTRA_CRYPTO_PARAM_GPG_UNIT_TEST, KEY_VALUE, "1", KEY_END),
52 : keyNew (ELEKTRA_SIGNATURE_KEY, KEY_VALUE, TEST_KEY_ID, KEY_END),
53 : keyNew (ELEKTRA_FCRYPT_CONFIG_TEXTMODE, KEY_VALUE, "0", KEY_END),
54 : KS_END);
55 : // clang-format on
56 : }
57 :
58 0 : static KeySet * newPluginConfigurationWithTextmodeEnabled (void)
59 : {
60 : // clang-format off
61 0 : return ksNew (3,
62 : keyNew (ELEKTRA_RECIPIENT_KEY, KEY_VALUE, TEST_KEY_ID, KEY_END),
63 : keyNew (ELEKTRA_CRYPTO_PARAM_GPG_UNIT_TEST, KEY_VALUE, "1", KEY_END),
64 : keyNew (ELEKTRA_SIGNATURE_KEY, KEY_VALUE, TEST_KEY_ID, KEY_END),
65 : keyNew (ELEKTRA_FCRYPT_CONFIG_TEXTMODE, KEY_VALUE, "1", KEY_END),
66 : KS_END);
67 : // clang-format on
68 : }
69 :
70 0 : static void writeTestFile (const char * file)
71 : {
72 0 : FILE * f = fopen (file, "wb");
73 0 : succeed_if (f, "can not write to temporary file");
74 0 : if (!f) return;
75 0 : succeed_if (fwrite (testContent, 1, sizeof (testContent), f) == sizeof (testContent), "test file preparation failed");
76 0 : fclose (f);
77 : }
78 :
79 0 : static void writeFaultySignatureFile (const char * file)
80 : {
81 0 : FILE * f = fopen (file, "w");
82 0 : succeed_if (f, "can not write to temporary file");
83 0 : if (!f) return;
84 0 : succeed_if (fwrite (FAULTY_SIGNATURE_FILE, 1, strlen (FAULTY_SIGNATURE_FILE), f) == strlen (FAULTY_SIGNATURE_FILE),
85 : "test file preparation failed");
86 0 : fclose (f);
87 : }
88 :
89 : /**
90 : * @brief read in the content stored in file and compare it to the test vector.
91 : * @retval 1 if the file content is equal to the test vector.
92 : * @retval -1 if the file content is not equal to the test vector or an error occurred.
93 : */
94 0 : static int isTestFileCorrect (const char * file)
95 : {
96 0 : int returnValue = -1;
97 0 : kdb_octet_t readBuffer[2 * sizeof (testContent)] = { 0 };
98 0 : size_t readCount = 0;
99 :
100 0 : FILE * f = fopen (file, "rb");
101 0 : succeed_if (f, "can not read from temporary file");
102 0 : if (!f) return -1;
103 :
104 0 : readCount = fread (readBuffer, 1, sizeof (readBuffer), f);
105 0 : succeed_if (readCount > 0, "temporary file is empty.");
106 :
107 0 : if (readCount == sizeof (testContent))
108 : {
109 0 : if (memcmp (readBuffer, testContent, sizeof (testContent)) == 0)
110 : {
111 0 : returnValue = 1;
112 : }
113 : }
114 :
115 0 : fclose (f);
116 0 : return returnValue;
117 : }
118 :
119 0 : static void test_init (void)
120 : {
121 0 : Plugin * plugin = NULL;
122 0 : Key * parentKey = keyNew ("system", KEY_END);
123 0 : KeySet * modules = ksNew (0, KS_END);
124 0 : KeySet * configKs = newPluginConfiguration ();
125 0 : elektraModulesInit (modules, 0);
126 :
127 0 : plugin = elektraPluginOpen (PLUGIN_NAME, modules, configKs, 0);
128 0 : succeed_if (plugin != 0, "failed to open the plugin");
129 0 : if (plugin)
130 : {
131 0 : succeed_if (!strcmp (plugin->name, PLUGIN_NAME), "got wrong name");
132 :
133 0 : KeySet * config = elektraPluginGetConfig (plugin);
134 0 : succeed_if (config != 0, "there should be a config");
135 :
136 0 : succeed_if (plugin->kdbOpen != 0, "no open pointer");
137 0 : succeed_if (plugin->kdbClose != 0, "no close pointer");
138 0 : succeed_if (plugin->kdbGet != 0, "no get pointer");
139 0 : succeed_if (plugin->kdbSet != 0, "no set pointer");
140 :
141 0 : elektraPluginClose (plugin, 0);
142 : }
143 :
144 0 : elektraModulesClose (modules, 0);
145 0 : ksDel (modules);
146 0 : keyDel (parentKey);
147 0 : }
148 :
149 0 : static void test_gpg (void)
150 : {
151 : // Plugin configuration
152 0 : KeySet * conf = newPluginConfiguration ();
153 0 : Key * errorKey = keyNew (0);
154 :
155 : // install the gpg key
156 0 : char * argv[] = { "", "-a", "--import", NULL };
157 0 : const size_t argc = 4;
158 0 : Key * msg = keyNew (0);
159 0 : keySetBinary (msg, test_key_asc, test_key_asc_len);
160 :
161 0 : succeed_if (ELEKTRA_PLUGIN_FUNCTION (gpgCall) (conf, errorKey, msg, argv, argc) == 1, "failed to install the GPG test key");
162 :
163 0 : keyDel (msg);
164 0 : keyDel (errorKey);
165 0 : ksDel (conf);
166 0 : }
167 :
168 0 : static void test_file_crypto_operations (void)
169 : {
170 0 : Plugin * plugin = NULL;
171 0 : Key * parentKey = keyNew ("system", KEY_END);
172 0 : KeySet * modules = ksNew (0, KS_END);
173 0 : KeySet * config = newPluginConfiguration ();
174 :
175 0 : elektraModulesInit (modules, 0);
176 0 : plugin = elektraPluginOpen (PLUGIN_NAME, modules, config, 0);
177 0 : succeed_if (plugin, "failed to open plugin handle");
178 0 : if (plugin)
179 : {
180 0 : KeySet * data = ksNew (0, KS_END);
181 0 : const char * tmpFile = elektraFilename ();
182 0 : if (tmpFile)
183 : {
184 : // prepare test file to be encrypted
185 0 : writeTestFile (tmpFile);
186 0 : keySetString (parentKey, tmpFile);
187 :
188 : // try to encrypt the file
189 0 : succeed_if (plugin->kdbSet (plugin, data, parentKey) == 1, "kdb set failed");
190 0 : succeed_if (isTestFileCorrect (tmpFile) == -1, "file content did not change during encryption");
191 :
192 : // try to decrypt the file again (simulating the pregetstorage call)
193 0 : succeed_if (plugin->kdbGet (plugin, data, parentKey) == 1, "kdb get (pregetstorage) failed");
194 0 : succeed_if (isTestFileCorrect (keyString (parentKey)) == 1, "file content could not be restored during decryption");
195 :
196 : // a second call to kdb get (the postgetstorage call) should re-encrypt the file again
197 0 : succeed_if (plugin->kdbGet (plugin, data, parentKey) == 1, "kdb get (postgetstorage) failed");
198 0 : succeed_if (isTestFileCorrect (tmpFile) == -1, "postgetstorage did not encrypt the file again");
199 :
200 0 : remove (tmpFile);
201 : }
202 :
203 0 : ksDel (data);
204 0 : elektraPluginClose (plugin, 0);
205 : }
206 :
207 0 : elektraModulesClose (modules, 0);
208 0 : ksDel (modules);
209 0 : keyDel (parentKey);
210 0 : }
211 :
212 0 : static void test_file_signature_operations (void)
213 : {
214 0 : Plugin * plugin = NULL;
215 0 : Key * parentKey = keyNew ("system", KEY_END);
216 0 : KeySet * modules = ksNew (0, KS_END);
217 0 : KeySet * config = newPluginConfiguration ();
218 :
219 0 : elektraModulesInit (modules, 0);
220 0 : plugin = elektraPluginOpen (PLUGIN_NAME, modules, config, 0);
221 0 : succeed_if (plugin, "failed to open plugin handle");
222 0 : if (plugin)
223 : {
224 0 : KeySet * data = ksNew (0, KS_END);
225 0 : const char * tmpFile = elektraFilename ();
226 0 : if (tmpFile)
227 : {
228 : // prepare test file to be encrypted
229 0 : writeTestFile (tmpFile);
230 0 : keySetString (parentKey, tmpFile);
231 :
232 : // try to encrypt the file
233 0 : succeed_if (plugin->kdbSet (plugin, data, parentKey) == 1, "kdb set failed");
234 0 : succeed_if (isTestFileCorrect (tmpFile) == -1, "file content did not change during encryption");
235 :
236 : // try to decrypt/verify the file
237 0 : succeed_if (plugin->kdbGet (plugin, data, parentKey) == 1, "kdb get failed");
238 :
239 0 : remove (tmpFile);
240 : }
241 :
242 0 : ksDel (data);
243 0 : elektraPluginClose (plugin, 0);
244 : }
245 :
246 0 : elektraModulesClose (modules, 0);
247 0 : ksDel (modules);
248 0 : keyDel (parentKey);
249 0 : }
250 :
251 0 : static void test_file_faulty_signature (void)
252 : {
253 0 : Plugin * plugin = NULL;
254 0 : Key * parentKey = keyNew ("system", KEY_END);
255 0 : KeySet * modules = ksNew (0, KS_END);
256 0 : KeySet * config = newPluginConfigurationWithTextmodeEnabled ();
257 :
258 0 : elektraModulesInit (modules, 0);
259 0 : plugin = elektraPluginOpen (PLUGIN_NAME, modules, config, 0);
260 0 : succeed_if (plugin, "failed to open plugin handle");
261 0 : if (plugin)
262 : {
263 0 : KeySet * data = ksNew (0, KS_END);
264 0 : const char * tmpFile = elektraFilename ();
265 0 : if (tmpFile)
266 : {
267 : // prepare test file to be encrypted
268 0 : writeFaultySignatureFile (tmpFile);
269 0 : keySetString (parentKey, tmpFile);
270 :
271 : // try to decrypt/verify the file -- should fail
272 0 : succeed_if (plugin->kdbGet (plugin, data, parentKey) == -1, "kdb get succeeded on a faulty signature");
273 :
274 0 : remove (tmpFile);
275 : }
276 :
277 0 : ksDel (data);
278 0 : elektraPluginClose (plugin, 0);
279 : }
280 :
281 0 : elektraModulesClose (modules, 0);
282 0 : ksDel (modules);
283 0 : keyDel (parentKey);
284 0 : }
285 :
286 0 : int main (int argc, char ** argv)
287 : {
288 0 : printf ("FCRYPT TESTS\n");
289 0 : printf ("==================\n\n");
290 :
291 0 : init (argc, argv);
292 :
293 0 : if (!gpg_available (newPluginConfiguration ()))
294 : {
295 0 : printf ("The test was disabled because gpg could not be found on the system.\n");
296 0 : return nbError;
297 : }
298 :
299 0 : test_gpg ();
300 0 : test_init ();
301 0 : test_file_crypto_operations ();
302 0 : test_file_signature_operations ();
303 0 : test_file_faulty_signature ();
304 0 : test_teardown ();
305 :
306 0 : print_result (ELEKTRA_PLUGIN_NAME);
307 0 : return nbError;
308 : }
|