2
* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
3
* 2011 Free Software Foundation, Inc.
5
* This file is part of GnuTLS.
7
* GnuTLS is free software: you can redistribute it and/or modify it
8
* under the terms of the GNU General Public License as published by
9
* the Free Software Foundation, either version 3 of the License, or
10
* (at your option) any later version.
12
* GnuTLS is distributed in the hope that it will be useful, but
13
* WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program. If not, see
19
* <http://www.gnu.org/licenses/>.
24
#include <gnutls/gnutls.h>
25
#include <gnutls/extra.h>
26
#include <gnutls/x509.h>
27
#include <gnutls/openpgp.h>
28
#include <gnutls/pkcs12.h>
29
#include <gnutls/pkcs11.h>
30
#include <gnutls/abstract.h>
39
#include <sys/types.h>
43
#include "certtool-common.h"
44
#include "certtool-cfg.h"
46
/* Gnulib portability files. */
47
#include <read-file.h>
49
unsigned char buffer[64 * 1024];
50
const int buffer_size = sizeof (buffer);
54
safe_open_rw (const char *file, int privkey_op)
61
omask = umask (S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
64
fh = fopen (file, "wb");
75
load_secret_key (int mand, common_info_st * info)
77
unsigned char raw_key[64];
78
size_t raw_key_size = sizeof (raw_key);
79
static gnutls_datum_t key;
80
gnutls_datum_t hex_key;
83
fprintf (stderr, "Loading secret key...\n");
85
if (info->secret_key == NULL)
88
error (EXIT_FAILURE, 0, "missing --secret-key");
93
hex_key.data = (char *) info->secret_key;
94
hex_key.size = strlen (info->secret_key);
96
ret = gnutls_hex_decode (&hex_key, raw_key, &raw_key_size);
98
error (EXIT_FAILURE, 0, "hex_decode: %s", gnutls_strerror (ret));
101
key.size = raw_key_size;
106
static gnutls_privkey_t _load_privkey(gnutls_datum_t *dat, common_info_st * info)
109
gnutls_privkey_t key;
110
gnutls_x509_privkey_t xkey;
112
ret = gnutls_x509_privkey_init (&xkey);
114
error (EXIT_FAILURE, 0, "x509_privkey_init: %s", gnutls_strerror (ret));
116
ret = gnutls_privkey_init (&key);
118
error (EXIT_FAILURE, 0, "privkey_init: %s", gnutls_strerror (ret));
122
const char *pass = get_pass ();
124
gnutls_x509_privkey_import_pkcs8 (xkey, dat, info->incert_format,
128
ret = gnutls_x509_privkey_import (xkey, dat, info->incert_format);
130
if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR)
132
error (EXIT_FAILURE, 0,
133
"import error: could not find a valid PEM header; "
134
"check if your key is PKCS #8 or PKCS #12 encoded");
138
error (EXIT_FAILURE, 0, "importing --load-privkey: %s: %s",
139
info->privkey, gnutls_strerror (ret));
141
ret = gnutls_privkey_import_x509(key, xkey, GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
143
error (EXIT_FAILURE, 0, "gnutls_privkey_import_x509: %s",
144
gnutls_strerror (ret));
151
static gnutls_privkey_t _load_pkcs11_privkey(const char* url)
154
gnutls_pkcs11_privkey_t p11key;
155
gnutls_privkey_t key;
157
ret = gnutls_privkey_init (&key);
159
error (EXIT_FAILURE, 0, "privkey_init: %s", gnutls_strerror (ret));
161
ret = gnutls_pkcs11_privkey_init (&p11key);
163
error (EXIT_FAILURE, 0, "pkcs11_privkey_init: %s", gnutls_strerror (ret));
165
ret = gnutls_pkcs11_privkey_import_url(p11key, url, 0);
167
error (EXIT_FAILURE, 0, "importing PKCS #11 key: %s: %s",
168
url, gnutls_strerror (ret));
170
ret = gnutls_privkey_import_pkcs11(key, p11key, GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
172
error (EXIT_FAILURE, 0, "gnutls_privkey_import_pkcs11: %s",
173
gnutls_strerror (ret));
178
static gnutls_pubkey_t _load_pkcs11_pubkey(const char* url)
181
gnutls_pkcs11_obj_t obj;
182
gnutls_x509_crt_t xcrt;
183
gnutls_pubkey_t pubkey;
184
unsigned int obj_flags = 0;
186
ret = gnutls_pubkey_init (&pubkey);
189
fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__,
190
gnutls_strerror (ret));
194
ret = gnutls_pkcs11_obj_init (&obj);
197
fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__,
198
gnutls_strerror (ret));
202
ret = gnutls_pkcs11_obj_import_url (obj, url, obj_flags);
205
fprintf (stderr, "Error in %s:%d: %s: %s\n", __func__, __LINE__,
206
gnutls_strerror (ret), url);
210
switch (gnutls_pkcs11_obj_get_type (obj))
212
case GNUTLS_PKCS11_OBJ_X509_CRT:
213
ret = gnutls_x509_crt_init (&xcrt);
216
fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__,
217
gnutls_strerror (ret));
221
ret = gnutls_x509_crt_import_pkcs11 (xcrt, obj);
224
fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__,
225
gnutls_strerror (ret));
229
ret = gnutls_pubkey_import_x509 (pubkey, xcrt, 0);
232
fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__,
233
gnutls_strerror (ret));
237
gnutls_x509_crt_deinit (xcrt);
239
case GNUTLS_PKCS11_OBJ_PUBKEY:
241
ret = gnutls_pubkey_import_pkcs11 (pubkey, obj, 0);
244
fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__,
245
gnutls_strerror (ret));
252
fprintf(stderr, "Unsupported PKCS #11 object\n");
258
gnutls_pkcs11_obj_deinit (obj);
262
#endif /* ENABLE_PKCS11 */
264
/* Load the private key.
265
* @mand should be non zero if it is required to read a private key.
268
load_private_key (int mand, common_info_st * info)
270
gnutls_privkey_t key;
274
if (!info->privkey && !mand)
277
if (info->privkey == NULL)
278
error (EXIT_FAILURE, 0, "missing --load-privkey");
281
if (strncmp(info->privkey, "pkcs11:", 7) == 0)
282
return _load_pkcs11_privkey(info->privkey);
285
dat.data = read_binary_file (info->privkey, &size);
289
error (EXIT_FAILURE, errno, "reading --load-privkey: %s", info->privkey);
291
key = _load_privkey(&dat, info);
298
/* Load the private key.
299
* @mand should be non zero if it is required to read a private key.
301
gnutls_x509_privkey_t
302
load_x509_private_key (int mand, common_info_st * info)
304
gnutls_x509_privkey_t key;
309
if (!info->privkey && !mand)
312
if (info->privkey == NULL)
313
error (EXIT_FAILURE, 0, "missing --load-privkey");
315
ret = gnutls_x509_privkey_init (&key);
317
error (EXIT_FAILURE, 0, "privkey_init: %s", gnutls_strerror (ret));
319
dat.data = read_binary_file (info->privkey, &size);
323
error (EXIT_FAILURE, errno, "reading --load-privkey: %s", info->privkey);
327
const char *pass = get_pass ();
329
gnutls_x509_privkey_import_pkcs8 (key, &dat, info->incert_format,
333
ret = gnutls_x509_privkey_import (key, &dat, info->incert_format);
337
if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR)
339
error (EXIT_FAILURE, 0,
340
"import error: could not find a valid PEM header; "
341
"check if your key is PKCS #8 or PKCS #12 encoded");
345
error (EXIT_FAILURE, 0, "importing --load-privkey: %s: %s",
346
info->privkey, gnutls_strerror (ret));
351
/* Loads the certificate
352
* If mand is non zero then a certificate is mandatory. Otherwise
353
* null will be returned if the certificate loading fails.
356
load_cert (int mand, common_info_st * info)
358
gnutls_x509_crt_t *crt;
361
crt = load_cert_list (mand, &size, info);
363
return crt ? crt[0] : NULL;
366
#define MAX_CERTS 256
368
/* Loads a certificate list
371
load_cert_list (int mand, size_t * crt_size, common_info_st * info)
374
static gnutls_x509_crt_t crt[MAX_CERTS];
382
fprintf (stderr, "Loading certificate list...\n");
384
if (info->cert == NULL)
387
error (EXIT_FAILURE, 0, "missing --load-certificate");
392
fd = fopen (info->cert, "r");
394
error (EXIT_FAILURE, errno, "%s", info->cert);
396
size = fread (buffer, 1, sizeof (buffer) - 1, fd);
404
for (i = 0; i < MAX_CERTS; i++)
406
ret = gnutls_x509_crt_init (&crt[i]);
408
error (EXIT_FAILURE, 0, "crt_init: %s", gnutls_strerror (ret));
413
ret = gnutls_x509_crt_import (crt[i], &dat, info->incert_format);
414
if (ret < 0 && *crt_size > 0)
417
error (EXIT_FAILURE, 0, "crt_import: %s", gnutls_strerror (ret));
419
ptr = strstr (ptr, "---END");
426
(unsigned int) ((unsigned char *) ptr - (unsigned char *) buffer);
433
fprintf (stderr, "Loaded %d certificates.\n", (int) *crt_size);
438
/* Load the Certificate Request.
441
load_request (common_info_st * info)
443
gnutls_x509_crq_t crq;
451
ret = gnutls_x509_crq_init (&crq);
453
error (EXIT_FAILURE, 0, "crq_init: %s", gnutls_strerror (ret));
455
dat.data = read_binary_file (info->request, &size);
459
error (EXIT_FAILURE, errno, "reading --load-request: %s", info->request);
461
ret = gnutls_x509_crq_import (crq, &dat, info->incert_format);
462
if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR)
464
error (EXIT_FAILURE, 0,
465
"import error: could not find a valid PEM header");
470
error (EXIT_FAILURE, 0, "importing --load-request: %s: %s",
471
info->request, gnutls_strerror (ret));
476
/* Load the CA's private key.
479
load_ca_private_key (common_info_st * info)
481
gnutls_privkey_t key;
485
if (info->ca_privkey == NULL)
486
error (EXIT_FAILURE, 0, "missing --load-ca-privkey");
489
if (strncmp(info->ca_privkey, "pkcs11:", 7) == 0)
490
return _load_pkcs11_privkey(info->ca_privkey);
493
dat.data = read_binary_file (info->ca_privkey, &size);
497
error (EXIT_FAILURE, errno, "reading --load-ca-privkey: %s",
500
key = _load_privkey(&dat, info);
507
/* Loads the CA's certificate
510
load_ca_cert (common_info_st * info)
512
gnutls_x509_crt_t crt;
517
if (info->ca == NULL)
518
error (EXIT_FAILURE, 0, "missing --load-ca-certificate");
520
ret = gnutls_x509_crt_init (&crt);
522
error (EXIT_FAILURE, 0, "crt_init: %s", gnutls_strerror (ret));
524
dat.data = read_binary_file (info->ca, &size);
528
error (EXIT_FAILURE, errno, "reading --load-ca-certificate: %s",
531
ret = gnutls_x509_crt_import (crt, &dat, info->incert_format);
534
error (EXIT_FAILURE, 0, "importing --load-ca-certificate: %s: %s",
535
info->ca, gnutls_strerror (ret));
540
/* Load a public key.
541
* @mand should be non zero if it is required to read a public key.
544
load_pubkey (int mand, common_info_st * info)
551
if (!info->pubkey && !mand)
554
if (info->pubkey == NULL)
555
error (EXIT_FAILURE, 0, "missing --load-pubkey");
558
if (strncmp(info->pubkey, "pkcs11:", 7) == 0)
559
return _load_pkcs11_pubkey(info->pubkey);
562
ret = gnutls_pubkey_init (&key);
564
error (EXIT_FAILURE, 0, "privkey_init: %s", gnutls_strerror (ret));
566
dat.data = read_binary_file (info->pubkey, &size);
570
error (EXIT_FAILURE, errno, "reading --load-pubkey: %s", info->pubkey);
572
ret = gnutls_pubkey_import (key, &dat, info->incert_format);
576
if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR)
578
error (EXIT_FAILURE, 0,
579
"import error: could not find a valid PEM header; "
580
"check if your key has the PUBLIC KEY header");
584
error (EXIT_FAILURE, 0, "importing --load-pubkey: %s: %s",
585
info->pubkey, gnutls_strerror (ret));
590
gnutls_pubkey_t load_public_key_or_import(int mand, gnutls_privkey_t privkey, common_info_st * info)
592
gnutls_pubkey_t pubkey;
595
ret = gnutls_pubkey_init(&pubkey);
597
error (EXIT_FAILURE, 0, "gnutls_pubkey_init: %s",
598
gnutls_strerror (ret));
600
ret = gnutls_pubkey_import_privkey(pubkey, privkey, 0, 0);
601
if (ret < 0) /* could not get (e.g. on PKCS #11 */
603
gnutls_pubkey_deinit(pubkey);
604
return load_pubkey(mand, info);