summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2007-11-11 10:21:23 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2007-11-11 10:21:23 +0200
commitee785274bd7dd27c01d9efc5f8c1135317face81 (patch)
tree51dcae6a43cc0a32fb4ec9bb4d509a8b84470802
parent19079c1ae445c6c8d465ac0d963bf338dcbb5071 (diff)
downloadgnutls-ee785274bd7dd27c01d9efc5f8c1135317face81.tar.gz
** Added the --to-p8 option to certtool to convert private keys
to PKCS #8 keys. ** Introduced the GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR error code. ** gnutls_certificate_set_x509_key_* can now read PKCS #8 unencrypted private keys.
-rw-r--r--NEWS8
-rw-r--r--doc/credentials/x509/key.pem31
-rw-r--r--includes/gnutls/gnutls.h.in2
-rw-r--r--lib/gnutls_errors.c2
-rw-r--r--lib/gnutls_x509.c5
-rw-r--r--lib/x509/privkey.c38
-rw-r--r--lib/x509_b64.c2
-rw-r--r--src/certtool-gaa.c119
-rw-r--r--src/certtool-gaa.h24
-rw-r--r--src/certtool.c64
-rw-r--r--src/certtool.gaa2
11 files changed, 188 insertions, 109 deletions
diff --git a/NEWS b/NEWS
index 94a015a17d..6ac4fae377 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,14 @@ See the end for copying conditions.
* Version 2.1.6 (unreleased)
+** Added the --to-p8 option to certtool to convert private keys
+to PKCS #8 keys.
+
+** Introduced the GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR error code.
+
+** gnutls_certificate_set_x509_key_* can now read PKCS #8 unencrypted
+private keys.
+
** API and ABI modifications:
No changes since last version.
diff --git a/doc/credentials/x509/key.pem b/doc/credentials/x509/key.pem
index 1e80b2e55e..1d8521f7b2 100644
--- a/doc/credentials/x509/key.pem
+++ b/doc/credentials/x509/key.pem
@@ -1,15 +1,16 @@
------BEGIN RSA PRIVATE KEY-----
-MIICWwIBAAKBgQDVyFSoD2JvxLkYp3b0H13WvCBSdwWEk+7T5EryQ7I6xXeoF211
-Z4FKIZZKjVEeRyZX0GVtS2a4eKgBSRk9KjyC2gTLcmlJ6ZbbbUGyPAhOMZ5nFmxv
-7gL9TZcdQiU76OoErlVhuk1eQ//ah8yRZYBnIqcj48wh8W+/9wBKwjSTjwIDAQAB
-AoGAAn2Ueua++1Vb4K0mxh5NbhCAAeXwEwTULfTFaMAgJe4iADvRoyIDEBWHFjRC
-QyuKB1DetaDAwBprvqQW3q8MyGYD7P9h85Wfu/hpIYKTw9hNeph420aE8WXw2ygl
-TkJz3bzkMrXe/WjdhS1kTt8avCNQR/p0jM/UHvNze4oLc1ECQQDfammiczQFtj+F
-uf3CNcYwp5XNumF+pubdGb+UHUiHyCuVQxvm+LXgq8wXV/uXFLrp7FQFLCDQf0ji
-KDB2YQvRAkEA9PY/2AaGsU7j8ePwQbxCkwuj3hY6O6aNLIGxKxwZrzbob26c+tQk
-/++e0IXusIscBvcRV1Kg8Ff6fnw7/AdhXwJAG8qVbOuRmGk0BkwuFmPoeW3vNQgR
-X96O7po0qPBqVdRAU2rvzYtkCFxYqq0ilI0ekZtAfKxbeykaQaRkkKPaoQJAcifP
-yWJ/tu8z4DM7Ka+pFqTMwIllM1U3vFtv3LXezDE7AGDCyHKdB7MXcPXqj6nmCLMi
-swwiLLahAOBnUqk6xwJAJQ4pGcFFlCiIiVsq0wYSYmZUcRpSIInEQ0f8/xN6J22Z
-siP5vnJM3F7R6ciYTt2gzNci/W9cdZI2HxskkO5lbQ==
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+MIICcwIBADALBgkqhkiG9w0BAQEEggJfMIICWwIBAAKBgQDVyFSoD2JvxLkYp3b0
+H13WvCBSdwWEk+7T5EryQ7I6xXeoF211Z4FKIZZKjVEeRyZX0GVtS2a4eKgBSRk9
+KjyC2gTLcmlJ6ZbbbUGyPAhOMZ5nFmxv7gL9TZcdQiU76OoErlVhuk1eQ//ah8yR
+ZYBnIqcj48wh8W+/9wBKwjSTjwIDAQABAoGAAn2Ueua++1Vb4K0mxh5NbhCAAeXw
+EwTULfTFaMAgJe4iADvRoyIDEBWHFjRCQyuKB1DetaDAwBprvqQW3q8MyGYD7P9h
+85Wfu/hpIYKTw9hNeph420aE8WXw2yglTkJz3bzkMrXe/WjdhS1kTt8avCNQR/p0
+jM/UHvNze4oLc1ECQQDfammiczQFtj+Fuf3CNcYwp5XNumF+pubdGb+UHUiHyCuV
+Qxvm+LXgq8wXV/uXFLrp7FQFLCDQf0jiKDB2YQvRAkEA9PY/2AaGsU7j8ePwQbxC
+kwuj3hY6O6aNLIGxKxwZrzbob26c+tQk/++e0IXusIscBvcRV1Kg8Ff6fnw7/Adh
+XwJAG8qVbOuRmGk0BkwuFmPoeW3vNQgRX96O7po0qPBqVdRAU2rvzYtkCFxYqq0i
+lI0ekZtAfKxbeykaQaRkkKPaoQJAcifPyWJ/tu8z4DM7Ka+pFqTMwIllM1U3vFtv
+3LXezDE7AGDCyHKdB7MXcPXqj6nmCLMiswwiLLahAOBnUqk6xwJAJQ4pGcFFlCiI
+iVsq0wYSYmZUcRpSIInEQ0f8/xN6J22ZsiP5vnJM3F7R6ciYTt2gzNci/W9cdZI2
+HxskkO5lbQ==
+-----END PRIVATE KEY-----
diff --git a/includes/gnutls/gnutls.h.in b/includes/gnutls/gnutls.h.in
index 14e1e34483..e4a2363ea0 100644
--- a/includes/gnutls/gnutls.h.in
+++ b/includes/gnutls/gnutls.h.in
@@ -1280,6 +1280,8 @@ extern "C"
#define GNUTLS_E_X509_UNSUPPORTED_OID -205
#define GNUTLS_E_RANDOM_FAILED -206
+#define GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR -207
+
#define GNUTLS_E_UNIMPLEMENTED_FEATURE -1250
diff --git a/lib/gnutls_errors.c b/lib/gnutls_errors.c
index 97fcd69bac..e0405674aa 100644
--- a/lib/gnutls_errors.c
+++ b/lib/gnutls_errors.c
@@ -127,6 +127,8 @@ static const gnutls_error_entry error_algorithms[] = {
ERROR_ENTRY (N_("Hashing has failed."), GNUTLS_E_HASH_FAILED, 1),
ERROR_ENTRY (N_("Base64 decoding error."), GNUTLS_E_BASE64_DECODING_ERROR,
1),
+ ERROR_ENTRY (N_("Base64 unexpected header error."), GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR,
+ 1),
ERROR_ENTRY (N_("Base64 encoding error."), GNUTLS_E_BASE64_ENCODING_ERROR,
1),
ERROR_ENTRY (N_("Parsing error in password file."),
diff --git a/lib/gnutls_x509.c b/lib/gnutls_x509.c
index 858a42c4ef..c34ab69972 100644
--- a/lib/gnutls_x509.c
+++ b/lib/gnutls_x509.c
@@ -682,6 +682,11 @@ _gnutls_x509_raw_privkey_to_gkey (gnutls_privkey * privkey,
}
ret = gnutls_x509_privkey_import (tmpkey, raw_key, type);
+
+ /* If normal key decoding doesn't work try decoding a plain PKCS #8 key */
+ if (ret < 0)
+ ret = gnutls_x509_privkey_import_pkcs8( tmpkey, raw_key, type, NULL, GNUTLS_PKCS_PLAIN);
+
if (ret < 0)
{
gnutls_assert ();
diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c
index 9adf65b2f6..0488ff48d0 100644
--- a/lib/x509/privkey.c
+++ b/lib/x509/privkey.c
@@ -383,7 +383,7 @@ gnutls_x509_privkey_import (gnutls_x509_privkey_t key,
_gnutls_fbase64_decode (PEM_KEY_RSA, data->data, data->size, &out);
key->pk_algorithm = GNUTLS_PK_RSA;
- if (result <= 0)
+ if (result == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR)
{
/* try for the second header */
result =
@@ -409,44 +409,36 @@ gnutls_x509_privkey_import (gnutls_x509_privkey_t key,
if (key->pk_algorithm == GNUTLS_PK_RSA)
{
key->key = _gnutls_privkey_decode_pkcs1_rsa_key (&_data, key);
- if (key->key == NULL)
- {
- gnutls_assert ();
- result = GNUTLS_E_ASN1_DER_ERROR;
- goto cleanup;
- }
+ if (key->key == NULL) gnutls_assert();
}
else if (key->pk_algorithm == GNUTLS_PK_DSA)
{
key->key = decode_dsa_key (&_data, key);
- if (key->key == NULL)
- {
- gnutls_assert ();
- result = GNUTLS_E_ASN1_DER_ERROR;
- goto cleanup;
- }
+ if (key->key == NULL) gnutls_assert();
}
else
{
/* Try decoding with both, and accept the one that
* succeeds.
*/
- key->pk_algorithm = GNUTLS_PK_DSA;
- key->key = decode_dsa_key (&_data, key);
+ key->pk_algorithm = GNUTLS_PK_RSA;
+ key->key = _gnutls_privkey_decode_pkcs1_rsa_key (&_data, key);
if (key->key == NULL)
{
- key->pk_algorithm = GNUTLS_PK_RSA;
- key->key = _gnutls_privkey_decode_pkcs1_rsa_key (&_data, key);
- if (key->key == NULL)
- {
- gnutls_assert ();
- result = GNUTLS_E_ASN1_DER_ERROR;
- goto cleanup;
- }
+ key->pk_algorithm = GNUTLS_PK_DSA;
+ key->key = decode_dsa_key (&_data, key);
+ if (key->key == NULL) gnutls_assert();
}
}
+ if (key->key == NULL)
+ {
+ gnutls_assert ();
+ result = GNUTLS_E_ASN1_DER_ERROR;
+ goto cleanup;
+ }
+
if (need_free)
_gnutls_free_datum (&_data);
diff --git a/lib/x509_b64.c b/lib/x509_b64.c
index f0b00c2f28..1dc816d048 100644
--- a/lib/x509_b64.c
+++ b/lib/x509_b64.c
@@ -446,7 +446,7 @@ _gnutls_fbase64_decode (const char *header, const opaque * data,
{
gnutls_assert ();
_gnutls_debug_log ("Could not find '%s'\n", pem_header);
- return GNUTLS_E_BASE64_DECODING_ERROR;
+ return GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR;
}
data_size -= (unsigned long int) rdata - (unsigned long int) data;
diff --git a/src/certtool-gaa.c b/src/certtool-gaa.c
index e84706a098..d6835e2c38 100644
--- a/src/certtool-gaa.c
+++ b/src/certtool-gaa.c
@@ -155,6 +155,7 @@ void gaa_help(void)
__gaa_helpsingle(0, "fix-key", "", "Regenerate the parameters in a private key.");
__gaa_helpsingle(0, "v1", "", "Generate an X.509 version 1 certificate (no extensions).");
__gaa_helpsingle(0, "to-p12", "", "Generate a PKCS #12 structure.");
+ __gaa_helpsingle(0, "to-p8", "", "Generate a PKCS #8 structure.");
__gaa_helpsingle('8', "pkcs8", "", "Use PKCS #8 format for private keys.");
__gaa_helpsingle(0, "dsa", "", "Use DSA keys.");
__gaa_helpsingle(0, "hash", "STR ", "Hash algorithm to use for signing (MD5,SHA1,RMD160,SHA256,SHA384,SHA512).");
@@ -183,29 +184,29 @@ typedef struct _gaainfo gaainfo;
struct _gaainfo
{
-#line 110 "certtool.gaa"
+#line 112 "certtool.gaa"
int debug;
-#line 106 "certtool.gaa"
+#line 108 "certtool.gaa"
char *template;
-#line 103 "certtool.gaa"
+#line 105 "certtool.gaa"
char *infile;
-#line 100 "certtool.gaa"
+#line 102 "certtool.gaa"
char *outfile;
-#line 97 "certtool.gaa"
+#line 99 "certtool.gaa"
int quick_random;
-#line 94 "certtool.gaa"
+#line 96 "certtool.gaa"
int bits;
-#line 91 "certtool.gaa"
+#line 93 "certtool.gaa"
int outcert_format;
-#line 88 "certtool.gaa"
+#line 90 "certtool.gaa"
int incert_format;
-#line 85 "certtool.gaa"
+#line 87 "certtool.gaa"
int export;
-#line 82 "certtool.gaa"
+#line 84 "certtool.gaa"
char *hash;
-#line 79 "certtool.gaa"
+#line 81 "certtool.gaa"
int dsa;
-#line 76 "certtool.gaa"
+#line 78 "certtool.gaa"
int pkcs8;
#line 71 "certtool.gaa"
int v1_cert;
@@ -279,7 +280,7 @@ static int gaa_error = 0;
#define GAA_MULTIPLE_OPTION 3
#define GAA_REST 0
-#define GAA_NB_OPTION 40
+#define GAA_NB_OPTION 41
#define GAAOPTID_version 1
#define GAAOPTID_help 2
#define GAAOPTID_debug 3
@@ -294,32 +295,33 @@ static int gaa_error = 0;
#define GAAOPTID_hash 12
#define GAAOPTID_dsa 13
#define GAAOPTID_pkcs8 14
-#define GAAOPTID_to_p12 15
-#define GAAOPTID_v1 16
-#define GAAOPTID_fix_key 17
-#define GAAOPTID_key_info 18
-#define GAAOPTID_smime_to_p7 19
-#define GAAOPTID_p7_info 20
-#define GAAOPTID_p12_info 21
-#define GAAOPTID_crl_info 22
-#define GAAOPTID_certificate_info 23
-#define GAAOPTID_password 24
-#define GAAOPTID_load_ca_certificate 25
-#define GAAOPTID_load_ca_privkey 26
-#define GAAOPTID_load_certificate 27
-#define GAAOPTID_load_request 28
-#define GAAOPTID_load_privkey 29
-#define GAAOPTID_get_dh_params 30
-#define GAAOPTID_generate_dh_params 31
-#define GAAOPTID_verify_crl 32
-#define GAAOPTID_verify_chain 33
-#define GAAOPTID_generate_request 34
-#define GAAOPTID_generate_privkey 35
-#define GAAOPTID_update_certificate 36
-#define GAAOPTID_generate_crl 37
-#define GAAOPTID_generate_proxy 38
-#define GAAOPTID_generate_certificate 39
-#define GAAOPTID_generate_self_signed 40
+#define GAAOPTID_to_p8 15
+#define GAAOPTID_to_p12 16
+#define GAAOPTID_v1 17
+#define GAAOPTID_fix_key 18
+#define GAAOPTID_key_info 19
+#define GAAOPTID_smime_to_p7 20
+#define GAAOPTID_p7_info 21
+#define GAAOPTID_p12_info 22
+#define GAAOPTID_crl_info 23
+#define GAAOPTID_certificate_info 24
+#define GAAOPTID_password 25
+#define GAAOPTID_load_ca_certificate 26
+#define GAAOPTID_load_ca_privkey 27
+#define GAAOPTID_load_certificate 28
+#define GAAOPTID_load_request 29
+#define GAAOPTID_load_privkey 30
+#define GAAOPTID_get_dh_params 31
+#define GAAOPTID_generate_dh_params 32
+#define GAAOPTID_verify_crl 33
+#define GAAOPTID_verify_chain 34
+#define GAAOPTID_generate_request 35
+#define GAAOPTID_generate_privkey 36
+#define GAAOPTID_update_certificate 37
+#define GAAOPTID_generate_crl 38
+#define GAAOPTID_generate_proxy 39
+#define GAAOPTID_generate_certificate 40
+#define GAAOPTID_generate_self_signed 41
#line 168 "gaa.skel"
@@ -629,6 +631,7 @@ static int gaa_get_option_num(char *str, int status)
GAA_CHECK1STR("", GAAOPTID_export_ciphers);
GAA_CHECK1STR("", GAAOPTID_dsa);
GAA_CHECK1STR("8", GAAOPTID_pkcs8);
+ GAA_CHECK1STR("", GAAOPTID_to_p8);
GAA_CHECK1STR("", GAAOPTID_to_p12);
GAA_CHECK1STR("", GAAOPTID_v1);
GAA_CHECK1STR("", GAAOPTID_fix_key);
@@ -667,6 +670,7 @@ static int gaa_get_option_num(char *str, int status)
GAA_CHECKSTR("hash", GAAOPTID_hash);
GAA_CHECKSTR("dsa", GAAOPTID_dsa);
GAA_CHECKSTR("pkcs8", GAAOPTID_pkcs8);
+ GAA_CHECKSTR("to-p8", GAAOPTID_to_p8);
GAA_CHECKSTR("to-p12", GAAOPTID_to_p12);
GAA_CHECKSTR("v1", GAAOPTID_v1);
GAA_CHECKSTR("fix-key", GAAOPTID_fix_key);
@@ -739,14 +743,14 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
{
case GAAOPTID_version:
OK = 0;
-#line 115 "certtool.gaa"
+#line 117 "certtool.gaa"
{ certtool_version(); exit(0); ;};
return GAA_OK;
break;
case GAAOPTID_help:
OK = 0;
-#line 113 "certtool.gaa"
+#line 115 "certtool.gaa"
{ gaa_help(); exit(0); ;};
return GAA_OK;
@@ -756,7 +760,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_debug.arg1, gaa_getint, GAATMP_debug.size1);
gaa_index++;
-#line 111 "certtool.gaa"
+#line 113 "certtool.gaa"
{ gaaval->debug = GAATMP_debug.arg1 ;};
return GAA_OK;
@@ -766,7 +770,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_template.arg1, gaa_getstr, GAATMP_template.size1);
gaa_index++;
-#line 107 "certtool.gaa"
+#line 109 "certtool.gaa"
{ gaaval->template = GAATMP_template.arg1 ;};
return GAA_OK;
@@ -776,7 +780,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_infile.arg1, gaa_getstr, GAATMP_infile.size1);
gaa_index++;
-#line 104 "certtool.gaa"
+#line 106 "certtool.gaa"
{ gaaval->infile = GAATMP_infile.arg1 ;};
return GAA_OK;
@@ -786,14 +790,14 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_outfile.arg1, gaa_getstr, GAATMP_outfile.size1);
gaa_index++;
-#line 101 "certtool.gaa"
+#line 103 "certtool.gaa"
{ gaaval->outfile = GAATMP_outfile.arg1 ;};
return GAA_OK;
break;
case GAAOPTID_disable_quick_random:
OK = 0;
-#line 98 "certtool.gaa"
+#line 100 "certtool.gaa"
{ gaaval->quick_random = 0; ;};
return GAA_OK;
@@ -803,28 +807,28 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_bits.arg1, gaa_getint, GAATMP_bits.size1);
gaa_index++;
-#line 95 "certtool.gaa"
+#line 97 "certtool.gaa"
{ gaaval->bits = GAATMP_bits.arg1 ;};
return GAA_OK;
break;
case GAAOPTID_outder:
OK = 0;
-#line 92 "certtool.gaa"
+#line 94 "certtool.gaa"
{ gaaval->outcert_format=1 ;};
return GAA_OK;
break;
case GAAOPTID_inder:
OK = 0;
-#line 89 "certtool.gaa"
+#line 91 "certtool.gaa"
{ gaaval->incert_format=1 ;};
return GAA_OK;
break;
case GAAOPTID_export_ciphers:
OK = 0;
-#line 86 "certtool.gaa"
+#line 88 "certtool.gaa"
{ gaaval->export=1 ;};
return GAA_OK;
@@ -834,25 +838,32 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_hash.arg1, gaa_getstr, GAATMP_hash.size1);
gaa_index++;
-#line 83 "certtool.gaa"
+#line 85 "certtool.gaa"
{ gaaval->hash = GAATMP_hash.arg1 ;};
return GAA_OK;
break;
case GAAOPTID_dsa:
OK = 0;
-#line 80 "certtool.gaa"
+#line 82 "certtool.gaa"
{ gaaval->dsa=1 ;};
return GAA_OK;
break;
case GAAOPTID_pkcs8:
OK = 0;
-#line 77 "certtool.gaa"
+#line 79 "certtool.gaa"
{ gaaval->pkcs8=1 ;};
return GAA_OK;
break;
+ case GAAOPTID_to_p8:
+ OK = 0;
+#line 76 "certtool.gaa"
+{ gaaval->action = 18; ;};
+
+ return GAA_OK;
+ break;
case GAAOPTID_to_p12:
OK = 0;
#line 74 "certtool.gaa"
@@ -1077,7 +1088,7 @@ int gaa(int argc, char **argv, gaainfo *gaaval)
if(inited == 0)
{
-#line 117 "certtool.gaa"
+#line 119 "certtool.gaa"
{ gaaval->bits = 2048; gaaval->pkcs8 = 0; gaaval->privkey = NULL; gaaval->ca=NULL; gaaval->ca_privkey = NULL;
gaaval->debug=1; gaaval->request = NULL; gaaval->infile = NULL; gaaval->outfile = NULL; gaaval->cert = NULL;
gaaval->incert_format = 0; gaaval->outcert_format = 0; gaaval->action=-1; gaaval->pass = NULL; gaaval->v1_cert = 0;
diff --git a/src/certtool-gaa.h b/src/certtool-gaa.h
index abda1a0c17..2965344059 100644
--- a/src/certtool-gaa.h
+++ b/src/certtool-gaa.h
@@ -8,29 +8,29 @@ typedef struct _gaainfo gaainfo;
struct _gaainfo
{
-#line 110 "certtool.gaa"
+#line 112 "certtool.gaa"
int debug;
-#line 106 "certtool.gaa"
+#line 108 "certtool.gaa"
char *template;
-#line 103 "certtool.gaa"
+#line 105 "certtool.gaa"
char *infile;
-#line 100 "certtool.gaa"
+#line 102 "certtool.gaa"
char *outfile;
-#line 97 "certtool.gaa"
+#line 99 "certtool.gaa"
int quick_random;
-#line 94 "certtool.gaa"
+#line 96 "certtool.gaa"
int bits;
-#line 91 "certtool.gaa"
+#line 93 "certtool.gaa"
int outcert_format;
-#line 88 "certtool.gaa"
+#line 90 "certtool.gaa"
int incert_format;
-#line 85 "certtool.gaa"
+#line 87 "certtool.gaa"
int export;
-#line 82 "certtool.gaa"
+#line 84 "certtool.gaa"
char *hash;
-#line 79 "certtool.gaa"
+#line 81 "certtool.gaa"
int dsa;
-#line 76 "certtool.gaa"
+#line 78 "certtool.gaa"
int pkcs8;
#line 71 "certtool.gaa"
int v1_cert;
diff --git a/src/certtool.c b/src/certtool.c
index 52bd61f726..d58ff291ad 100644
--- a/src/certtool.c
+++ b/src/certtool.c
@@ -47,6 +47,7 @@ void pkcs7_info (void);
void smime_to_pkcs7 (void);
void pkcs12_info (void);
void generate_pkcs12 (void);
+void generate_pkcs8 (void);
void verify_chain (void);
void verify_crl (void);
gnutls_x509_privkey_t load_private_key (int mand);
@@ -889,6 +890,9 @@ gaa_parser (int argc, char **argv)
case 17:
generate_proxy_certificate ();
break;
+ case 18:
+ generate_pkcs8 ();
+ break;
default:
gaa_help ();
exit (0);
@@ -1033,6 +1037,7 @@ crl_info (void)
"standard input");
ret = gnutls_x509_crl_import (crl, &pem, info.incert_format);
+
free (pem.data);
if (ret < 0)
error (EXIT_FAILURE, 0, "Import error: %s", gnutls_strerror (ret));
@@ -1058,12 +1063,12 @@ privkey_info (void)
pem.data = buffer;
pem.size = size;
-
+ ret = 0;
if (!info.pkcs8)
- {
ret = gnutls_x509_privkey_import (key, &pem, info.incert_format);
- }
- else
+
+ /* If we failed to import the certificate previously try PKCS #8 */
+ if (info.pkcs8 || ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR)
{
if (info.pass)
pass = info.pass;
@@ -1199,7 +1204,13 @@ load_private_key (int mand)
}
else
ret = gnutls_x509_privkey_import (key, &dat, info.incert_format);
+
free (dat.data);
+
+ if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR) {
+ error (EXIT_FAILURE, 0, "Import error: Could not find a valid PEM header. Check if your key is PKCS #8 or PKCS #12 encoded.");
+ }
+
if (ret < 0)
error (EXIT_FAILURE, 0, "importing --load-privkey: %s: %s",
info.privkey, gnutls_strerror (ret));
@@ -1231,6 +1242,10 @@ load_request (void)
error (EXIT_FAILURE, errno, "reading --load-request: %s", info.request);
ret = gnutls_x509_crq_import (crq, &dat, info.incert_format);
+ if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR) {
+ error (EXIT_FAILURE, 0, "Import error: Could not find a valid PEM header.");
+ }
+
free (dat.data);
if (ret < 0)
error (EXIT_FAILURE, 0, "importing --load-request: %s: %s",
@@ -1856,6 +1871,47 @@ verify_crl (void)
fprintf (outfile, "\n");
}
+void
+generate_pkcs8 (void)
+{
+ gnutls_x509_privkey_t key;
+ int result;
+ size_t size;
+ int flags = 0;
+ const char* password;
+
+ fprintf (stderr, "Generating a PKCS #8 key structure...\n");
+
+ key = load_private_key (1);
+
+ if (info.pass)
+ password = info.pass;
+ else
+ password = get_pass ();
+
+ if (info.export)
+ flags = GNUTLS_PKCS_USE_PKCS12_RC2_40;
+ else
+ flags = GNUTLS_PKCS_USE_PKCS12_3DES;
+
+ if (password == NULL || password[0] == 0) {
+ flags = GNUTLS_PKCS_PLAIN;
+ }
+
+
+ size = sizeof (buffer);
+ result =
+ gnutls_x509_privkey_export_pkcs8 (key, info.outcert_format,
+ password, flags, buffer, &size);
+
+ if (result < 0)
+ error (EXIT_FAILURE, 0, "key_export: %s", gnutls_strerror (result));
+
+ fwrite (buffer, 1, size, outfile);
+
+}
+
+
#include <gnutls/pkcs12.h>
#include <unistd.h>
diff --git a/src/certtool.gaa b/src/certtool.gaa
index c9cf6ac75c..77ade5504d 100644
--- a/src/certtool.gaa
+++ b/src/certtool.gaa
@@ -73,6 +73,8 @@ option (v1) { $v1_cert = 1; } "Generate an X.509 version 1 certificate (no exten
option (to-p12) { $action = 8; } "Generate a PKCS #12 structure."
+option (to-p8) { $action = 18; } "Generate a PKCS #8 structure."
+
#int pkcs8;
option (8, pkcs8) { $pkcs8=1 } "Use PKCS #8 format for private keys."