diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2007-11-11 10:21:23 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2007-11-11 10:21:23 +0200 |
commit | ee785274bd7dd27c01d9efc5f8c1135317face81 (patch) | |
tree | 51dcae6a43cc0a32fb4ec9bb4d509a8b84470802 | |
parent | 19079c1ae445c6c8d465ac0d963bf338dcbb5071 (diff) | |
download | gnutls-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-- | NEWS | 8 | ||||
-rw-r--r-- | doc/credentials/x509/key.pem | 31 | ||||
-rw-r--r-- | includes/gnutls/gnutls.h.in | 2 | ||||
-rw-r--r-- | lib/gnutls_errors.c | 2 | ||||
-rw-r--r-- | lib/gnutls_x509.c | 5 | ||||
-rw-r--r-- | lib/x509/privkey.c | 38 | ||||
-rw-r--r-- | lib/x509_b64.c | 2 | ||||
-rw-r--r-- | src/certtool-gaa.c | 119 | ||||
-rw-r--r-- | src/certtool-gaa.h | 24 | ||||
-rw-r--r-- | src/certtool.c | 64 | ||||
-rw-r--r-- | src/certtool.gaa | 2 |
11 files changed, 188 insertions, 109 deletions
@@ -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." |