1
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
/* unit-test-pkix-parser.c: Test PKIX parser
4
Copyright (C) 2007 Stefan Walter
6
The Gnome Keyring Library is free software; you can redistribute it and/or
7
modify it under the terms of the GNU Library General Public License as
8
published by the Free Software Foundation; either version 2 of the
9
License, or (at your option) any later version.
11
The Gnome Keyring Library is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
Library General Public License for more details.
16
You should have received a copy of the GNU Library General Public
17
License along with the Gnome Library; see the file COPYING.LIB. If not,
18
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19
Boston, MA 02111-1307, USA.
21
Author: Stef Walter <stef@memberwebs.com>
26
#include "test-suite.h"
28
#include "gkm/gkm-crypto.h"
29
#include "gkm/gkm-data-asn1.h"
30
#include "gkm/gkm-data-der.h"
31
#include "gkm/gkm-sexp.h"
33
#include "egg/egg-asn1x.h"
34
#include "egg/egg-asn1-defs.h"
35
#include "egg/egg-openssl.h"
36
#include "egg/egg-secure-memory.h"
45
static GNode *certificate = NULL;
46
static guchar *certificate_data = NULL;
47
static gsize n_certificate_data = 0;
49
static GNode *certificate2 = NULL;
50
static guchar *certificate2_data = NULL;
51
static gsize n_certificate2_data = 0;
53
const gchar *rsapub = "(public-key (rsa" \
54
" (n #00AE4B381CF43F7DC24CF90827325E2FB2EB57EDDE29562DF391C8942AA8E6423410E2D3FE26381F9DE0395E74BF2D17621AE46992C72CF895F6FA5FBE98054FBF#)" \
57
const gchar *rsaprv = "(private-key (rsa" \
58
" (n #00B78758D55EBFFAB61D07D0DC49B5309A6F1DA2AE51C275DFC2370959BB81AC0C39093B1C618E396161A0DECEB8768D0FFB14F197B96C3DA14190EE0F20D51315#)" \
60
" (d #108BCAC5FDD35812981E6EC5957D98E2AB76E4064C47B861D27C2CC322C50792313C852B4164A035B42D261F1A09F9FFE8F477F9F78FF2EABBDA6BA875C671D7#)" \
61
" (p #00C357F11B19A18C66573D25D1E466D9AB8BCDDCDFE0B2E80BD46712C4BEC18EB7#)" \
62
" (q #00F0843B90A60EF7034CA4BE80414ED9497CABCC685143B388013FF989CBB0E093#)" \
63
" (u #12F2555F52EB56329A991CF0404B51C68AC921AD370A797860F550415FF987BD#)))";
65
const gchar *dsapub = "(public-key (dsa" \
66
" (p #0090EC0B60735839C754EAF8F64BB03FC35398D69772BFAE540079DEA2D3A61FAFFB27630A038A01A3D0CD62A10745A574A27ECB462F4F0885B79C61BBE954A60A29668AD54BBA5C07A72FD8B1105249670B339DF2C59E64A47064EFCF0B7236C5C72CD55CEB32917430BEC9A003D4E484FBAA84D79571B38D6B5AC95BB73E3F7B#)" \
67
" (q #00FA214A1385C21BFEBAADAB240A2430C607D56271#)" \
68
" (g #2DE05751F5DAEE97F3D43C54595A3E94A080728F0C66C98AEBED5762F6AB155802D8359EAD1DE1EC36A459FBEEEA48E59B9E6A8CB4F5295936B3CC881A5D957C7339175E2CFFE0F30D3711E430DB6648C2EB474AA10A4A3297450531FF2C7C6951220C9D446B6B6B0F00262E1EBEB3CC861476AA518CC555C9ABF9E5F39023FC#)" \
69
" (y #54734451DB79D4EEDF0BBCEBD43BB6CBB7B8584603B957080075DD318EB5B0266D4B20DC5EFF376BDFC4EA2983B1F7F02A39ED4C619ED68712729FFF3B7C696ADD1B6D748F56A4B4BEC5C4385E528423A3B88AE65E6D5500F97839E7A486255982189C3B4FA8D94338C76F0E5CAFC9A30A1ED728BB9F2091D594E3250A09EA00#)))";
71
const gchar *dsaprv = "(private-key (dsa" \
72
" (p #0090EC0B60735839C754EAF8F64BB03FC35398D69772BFAE540079DEA2D3A61FAFFB27630A038A01A3D0CD62A10745A574A27ECB462F4F0885B79C61BBE954A60A29668AD54BBA5C07A72FD8B1105249670B339DF2C59E64A47064EFCF0B7236C5C72CD55CEB32917430BEC9A003D4E484FBAA84D79571B38D6B5AC95BB73E3F7B#)" \
73
" (q #00FA214A1385C21BFEBAADAB240A2430C607D56271#)" \
74
" (g #2DE05751F5DAEE97F3D43C54595A3E94A080728F0C66C98AEBED5762F6AB155802D8359EAD1DE1EC36A459FBEEEA48E59B9E6A8CB4F5295936B3CC881A5D957C7339175E2CFFE0F30D3711E430DB6648C2EB474AA10A4A3297450531FF2C7C6951220C9D446B6B6B0F00262E1EBEB3CC861476AA518CC555C9ABF9E5F39023FC#)" \
75
" (y #54734451DB79D4EEDF0BBCEBD43BB6CBB7B8584603B957080075DD318EB5B0266D4B20DC5EFF376BDFC4EA2983B1F7F02A39ED4C619ED68712729FFF3B7C696ADD1B6D748F56A4B4BEC5C4385E528423A3B88AE65E6D5500F97839E7A486255982189C3B4FA8D94338C76F0E5CAFC9A30A1ED728BB9F2091D594E3250A09EA00#)" \
76
" (x #00876F84F709D51108DFB0CBFA1F1C569C09C413EC#)))";
79
compare_keys (gcry_sexp_t key, gcry_sexp_t sexp)
81
guchar hash1[20], hash2[20];
84
/* Now compare them */
85
p = gcry_pk_get_keygrip (key, hash1);
86
g_assert ("couldn't get key id for private key" && p == hash1);
87
p = gcry_pk_get_keygrip (sexp, hash2);
88
g_assert ("couldn't get key id for parsed private key" && p == hash2);
90
return memcmp (hash1, hash2, 20) == 0;
94
test_der_public (gcry_sexp_t key)
102
data = gkm_data_der_write_public_key (key, &n_data);
103
g_assert ("couldn't encode public key" && data != NULL);
104
g_assert ("encoding is empty" && n_data > 0);
107
ret = gkm_data_der_read_public_key (data, n_data, &sexp);
108
g_assert ("couldn't decode public key" && ret == GKM_DATA_SUCCESS);
109
g_assert ("parsed key is empty" && sexp != NULL);
111
/* Now compare them */
112
g_assert ("key parsed differently" && compare_keys (key, sexp));
115
TESTING_SETUP(preload)
117
certificate_data = testing_data_read ("test-certificate-1.der", &n_certificate_data);
118
certificate = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", certificate_data, n_certificate_data);
119
g_assert (certificate);
121
certificate2_data = testing_data_read ("test-certificate-2.der", &n_certificate2_data);
122
certificate2 = egg_asn1x_create_and_decode (pkix_asn1_tab, "Certificate", certificate2_data, n_certificate2_data);
123
g_assert (certificate2);
126
TESTING_TEARDOWN(preload)
128
egg_asn1x_destroy (certificate);
129
g_free (certificate_data);
130
certificate_data = NULL;
132
egg_asn1x_destroy (certificate2);
133
g_free (certificate2_data);
134
certificate2_data = NULL;
137
TESTING_TEST(der_rsa_public)
142
gcry = gcry_sexp_sscan (&key, NULL, rsapub, strlen (rsapub));
143
g_return_if_fail (gcry == 0);
145
test_der_public (key);
148
TESTING_TEST(der_dsa_public)
153
gcry = gcry_sexp_sscan (&key, NULL, dsapub, strlen (dsapub));
154
g_return_if_fail (gcry == 0);
156
test_der_public (key);
160
test_der_private (gcry_sexp_t key)
168
data = gkm_data_der_write_private_key (key, &n_data);
169
g_assert ("couldn't encode private key" && data != NULL);
170
g_assert ("encoding is empty" && n_data > 0);
173
ret = gkm_data_der_read_private_key (data, n_data, &sexp);
174
g_assert ("couldn't decode private key" && ret == GKM_DATA_SUCCESS);
175
g_assert ("parsed key is empty" && sexp != NULL);
177
/* Now compare them */
178
g_assert ("key parsed differently" && compare_keys (key, sexp));
180
egg_secure_free (data);
183
TESTING_TEST(der_rsa_private)
188
gcry = gcry_sexp_sscan (&key, NULL, rsaprv, strlen (rsaprv));
189
g_return_if_fail (gcry == 0);
191
test_der_private (key);
194
TESTING_TEST(der_dsa_private)
199
gcry = gcry_sexp_sscan (&key, NULL, dsaprv, strlen (dsaprv));
200
g_return_if_fail (gcry == 0);
202
test_der_private (key);
205
TESTING_TEST(der_dsa_private_parts)
207
guchar *params, *key;
208
gsize n_params, n_key;
209
gcry_sexp_t skey, pkey;
211
GkmDataResult result;
213
gcry = gcry_sexp_sscan (&skey, NULL, dsaprv, strlen (dsaprv));
214
g_return_if_fail (gcry == 0);
216
/* Encode the the dsa key by parts */
217
params = gkm_data_der_write_private_key_dsa_params (skey, &n_params);
218
g_assert ("didn't encode dsa params" && params != NULL);
219
key = gkm_data_der_write_private_key_dsa_part (skey, &n_key);
220
g_assert ("didn't encode dsa key" && key != NULL);
222
/* Parse the dsa key by parts */
223
result = gkm_data_der_read_private_key_dsa_parts (key, n_key, params, n_params, &pkey);
224
g_assert ("couldn't parse dsa parts" && result == GKM_DATA_SUCCESS);
225
g_assert ("parsing dsa parts resulted in null key" && pkey != NULL);
227
/* Now compare them */
228
g_assert ("key parsed differently" && compare_keys (skey, pkey));
230
egg_secure_free (params);
231
egg_secure_free (key);
234
const gchar *certpub = "(public-key (rsa " \
235
"(n #00C966D9F80744CFB98C2EF0A1EF13456C05DFDE2716513641116C6C3BEDFE107D129EE59B429AFE6031C366B7733A48AE4ED032379488B50DB6D9F3F244D9D58812DD764DF21AFC6F231E7AF1D898454E0710EF1642D043756D4ADEE2AAC931FF1F00707C66CF102508BAFAEE00E94603662711153BAA5BF298DD3642B2DA8875#) " \
238
TESTING_TEST(read_public_key_info)
244
gcry_sexp_t sexp, match;
247
data = egg_asn1x_get_raw_element (egg_asn1x_node (certificate, "tbsCertificate", "subjectPublicKeyInfo", NULL), &n_data);
250
res = gkm_data_der_read_public_key_info (data, n_data, &sexp);
251
g_assert (res == GKM_DATA_SUCCESS);
252
g_assert (sexp != NULL);
254
if (!gcry_pk_get_keygrip (sexp, hash))
255
g_assert_not_reached ();
257
gcry = gcry_sexp_sscan (&match, NULL, certpub, strlen (certpub));
258
g_assert (gcry == 0);
260
g_assert (compare_keys (sexp, match));
262
gcry_sexp_release (sexp);
263
gcry_sexp_release (match);
266
TESTING_TEST(read_certificate)
271
res = gkm_data_der_read_certificate (certificate_data, n_certificate_data, &asn);
272
g_assert (res == GKM_DATA_SUCCESS);
273
g_assert (asn != NULL);
275
egg_asn1x_destroy (asn);
278
TESTING_TEST(write_certificate)
283
data = gkm_data_der_write_certificate (certificate, &n_data);
285
g_assert (n_data == n_certificate_data);
286
g_assert (memcmp (data, certificate_data, n_data) == 0);
291
on_ca_certificate_public_key_info (GQuark type, const guchar *data, gsize n_data,
292
GHashTable *headers, gpointer user_data)
300
g_assert (g_quark_try_string ("CERTIFICATE") == type);
302
/* Parse the ASN1 data */
303
res = gkm_data_der_read_certificate (data, n_data, &asn1);
304
g_assert (res == GKM_DATA_SUCCESS);
306
/* Generate a raw public key from our certificate */
307
keydata = egg_asn1x_encode (egg_asn1x_node (asn1, "tbsCertificate", "subjectPublicKeyInfo", NULL), NULL, &n_keydata);
310
/* Now create us a nice public key with that identifier */
311
res = gkm_data_der_read_public_key_info (keydata, n_keydata, &sexp);
312
g_assert (res == GKM_DATA_SUCCESS || res == GKM_DATA_UNRECOGNIZED);
314
if (res == GKM_DATA_SUCCESS)
315
gcry_sexp_release (sexp);
319
TESTING_TEST(read_ca_certificates_public_key_info)
324
data = testing_data_read ("ca-certificates.crt", &n_data);
325
egg_openssl_pem_parse (data, n_data, on_ca_certificate_public_key_info, NULL);
330
find_extension (GNode *asn, const guchar *data, gsize n_data, const gchar *oid, gsize *n_extension)
340
for (index = 1; TRUE; ++index) {
342
/* Make sure it is present */
343
node = egg_asn1x_node (asn, "tbsCertificate", "extensions", index, "extnID", NULL);
347
exoid = egg_asn1x_get_oid_as_string (node);
350
if (strcmp (exoid, oid) == 0) {
352
node = egg_asn1x_node (asn, "tbsCertificate", "extensions", index, "extnValue", NULL);
353
value = egg_asn1x_get_raw_value (node, n_extension);
361
g_assert_not_reached ();
364
TESTING_TEST(read_basic_constraints)
366
const guchar *extension;
372
extension = egg_asn1x_get_raw_value (egg_asn1x_node (certificate, "tbsCertificate", "extensions", 1, "extnValue", NULL),
374
g_assert (extension);
376
res = gkm_data_der_read_basic_constraints (extension, n_extension, &is_ca, &path_len);
377
g_assert (res == GKM_DATA_SUCCESS);
378
g_assert (is_ca == TRUE);
379
g_assert (path_len == -1);
382
TESTING_TEST(read_key_usage)
384
const guchar *extension;
389
extension = find_extension (certificate2, certificate2_data, n_certificate2_data, "2.5.29.15", &n_extension);
390
g_assert (extension);
392
res = gkm_data_der_read_key_usage (extension, n_extension, &key_usage);
393
g_assert (res == GKM_DATA_SUCCESS);
394
g_assert_cmpuint (key_usage, ==, 0x01);
397
TESTING_TEST(read_enhanced_usage)
399
const guchar *extension;
404
extension = find_extension (certificate2, certificate2_data, n_certificate2_data, "2.5.29.37", &n_extension);
405
g_assert (extension);
407
res = gkm_data_der_read_enhanced_usage (extension, n_extension, &usages);
408
g_assert (res == GKM_DATA_SUCCESS);
413
TESTING_TEST(read_all_pkcs8)
422
dir = g_dir_open (testing_data_directory (), 0, NULL);
426
name = g_dir_read_name (dir);
430
if (!g_pattern_match_simple ("der-pkcs8-*", name))
433
data = testing_data_read (name, &n_data);
434
res = gkm_data_der_read_private_pkcs8 (data, n_data, "booo", 4, &sexp);
435
g_assert (res == GKM_DATA_SUCCESS);
437
g_assert (gkm_sexp_parse_key (sexp, NULL, NULL, NULL));
438
gcry_sexp_release (sexp);
445
TESTING_TEST(read_pkcs8_bad_password)
452
data = testing_data_read ("der-pkcs8-encrypted-pkcs5.key", &n_data);
453
res = gkm_data_der_read_private_pkcs8 (data, n_data, "wrong password", 4, &sexp);
454
g_assert (res == GKM_DATA_LOCKED);
459
TESTING_TEST(write_pkcs8_plain)
461
gcry_sexp_t sexp, check;
469
gcry = gcry_sexp_sscan (&sexp, NULL, rsaprv, strlen (rsaprv));
470
g_return_if_fail (gcry == 0);
472
data = gkm_data_der_write_private_pkcs8_plain (sexp, &n_data);
476
res = gkm_data_der_read_private_pkcs8_plain (data, n_data, &check);
477
egg_secure_free (data);
478
g_assert (res == GKM_DATA_SUCCESS);
481
g_assert (compare_keys (sexp, check));
482
gcry_sexp_release (sexp);
483
gcry_sexp_release (check);
488
gcry = gcry_sexp_sscan (&sexp, NULL, dsaprv, strlen (dsaprv));
489
g_return_if_fail (gcry == 0);
491
data = gkm_data_der_write_private_pkcs8_plain (sexp, &n_data);
495
res = gkm_data_der_read_private_pkcs8_plain (data, n_data, &check);
496
egg_secure_free (data);
497
g_assert (res == GKM_DATA_SUCCESS);
500
g_assert (compare_keys (sexp, check));
501
gcry_sexp_release (sexp);
502
gcry_sexp_release (check);
506
TESTING_TEST(write_pkcs8_encrypted)
508
gcry_sexp_t sexp, check;
516
gcry = gcry_sexp_sscan (&sexp, NULL, rsaprv, strlen (rsaprv));
517
g_return_if_fail (gcry == 0);
519
data = gkm_data_der_write_private_pkcs8_crypted (sexp, "testo", 5, &n_data);
523
res = gkm_data_der_read_private_pkcs8_crypted (data, n_data, "testo", 5, &check);
525
g_assert (res == GKM_DATA_SUCCESS);
528
g_assert (compare_keys (sexp, check));
529
gcry_sexp_release (sexp);
530
gcry_sexp_release (check);
535
gcry = gcry_sexp_sscan (&sexp, NULL, dsaprv, strlen (dsaprv));
536
g_return_if_fail (gcry == 0);
538
data = gkm_data_der_write_private_pkcs8_crypted (sexp, "testo", 5, &n_data);
542
res = gkm_data_der_read_private_pkcs8_crypted (data, n_data, "testo", 5, &check);
544
g_assert (res == GKM_DATA_SUCCESS);
547
g_assert (compare_keys (sexp, check));
548
gcry_sexp_release (sexp);
549
gcry_sexp_release (check);