diff options
-rw-r--r-- | NEWS | 12 | ||||
-rw-r--r-- | lib/includes/gnutls/pkcs11.h | 5 | ||||
-rw-r--r-- | lib/libgnutls.map | 1 | ||||
-rw-r--r-- | lib/pkcs11.c | 15 | ||||
-rw-r--r-- | lib/pkcs11_int.h | 31 | ||||
-rw-r--r-- | lib/pkcs11_privkey.c | 203 | ||||
-rw-r--r-- | lib/pkcs11_write.c | 1 | ||||
-rw-r--r-- | src/certtool-common.c | 58 | ||||
-rw-r--r-- | src/certtool-common.h | 5 | ||||
-rw-r--r-- | src/certtool-gaa.c | 5 | ||||
-rw-r--r-- | src/certtool.c | 63 | ||||
-rw-r--r-- | src/certtool.gaa | 3 | ||||
-rw-r--r-- | src/p11common.c | 1 | ||||
-rw-r--r-- | src/p11tool-gaa.c | 232 | ||||
-rw-r--r-- | src/p11tool-gaa.h | 34 | ||||
-rw-r--r-- | src/p11tool.c | 5 | ||||
-rw-r--r-- | src/p11tool.gaa | 15 | ||||
-rw-r--r-- | src/p11tool.h | 6 | ||||
-rw-r--r-- | src/pkcs11.c | 33 |
19 files changed, 580 insertions, 148 deletions
@@ -2,10 +2,22 @@ GnuTLS NEWS -- History of user-visible changes. -*- outline -*- Copyright (C) 2000-2011 Free Software Foundation, Inc. See the end for copying conditions. +* Version 3.0.3 (unreleased) + ** libgnutls: Allow CA importing of 0 certificates to succeed. Reported by Jonathan Nieder <jrnieder@gmail.com> in <http://bugs.debian.org/640639>. +** libgnutls: Added gnutls_pkcs11_privkey_generate() +to allow generating a key in a token. + +** p11tool: Added generate-rsa, generate-dsa and +generate-ecc options. + +** API and ABI modifications: +gnutls_pkcs11_privkey_generate: Added + + * Version 3.0.2 (released 2011-09-01) ** libgnutls: OpenPGP certificate type is not enabled diff --git a/lib/includes/gnutls/pkcs11.h b/lib/includes/gnutls/pkcs11.h index 6dca20f4e0..7db5d9e575 100644 --- a/lib/includes/gnutls/pkcs11.h +++ b/lib/includes/gnutls/pkcs11.h @@ -338,4 +338,9 @@ int gnutls_pkcs11_privkey_export_url (gnutls_pkcs11_privkey_t key, gnutls_pkcs11_url_type_t detailed, char **url); +int +gnutls_pkcs11_privkey_generate (const char* url, + gnutls_pk_algorithm_t pk, unsigned int bits, + const char* label, unsigned int flags); + #endif diff --git a/lib/libgnutls.map b/lib/libgnutls.map index 33305330fd..f2d57aa83b 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -713,6 +713,7 @@ GNUTLS_3_0_0 { gnutls_x509_trust_list_add_named_crt; gnutls_alert_get_strname; gnutls_pcert_list_import_x509_raw; + gnutls_pkcs11_privkey_generate; } GNUTLS_2_12; GNUTLS_PRIVATE { diff --git a/lib/pkcs11.c b/lib/pkcs11.c index 91db86c7d7..e08d6937ae 100644 --- a/lib/pkcs11.c +++ b/lib/pkcs11.c @@ -2849,6 +2849,21 @@ pkcs11_sign (struct ck_function_list *module, } ck_rv_t +pkcs11_generate_key_pair (struct ck_function_list *module, + ck_session_handle_t sess, + struct ck_mechanism *mechanism, + struct ck_attribute *pub_templ, + unsigned long pub_templ_count, + struct ck_attribute *priv_templ, + unsigned long priv_templ_count, + ck_object_handle_t *pub, + ck_object_handle_t *priv) +{ + return (module)->C_GenerateKeyPair (sess, mechanism, pub_templ, pub_templ_count, + priv_templ, priv_templ_count, pub, priv); +} + +ck_rv_t pkcs11_decrypt_init (struct ck_function_list *module, ck_session_handle_t sess, struct ck_mechanism *mechanism, diff --git a/lib/pkcs11_int.h b/lib/pkcs11_int.h index cd62904889..2a8fc8bf80 100644 --- a/lib/pkcs11_int.h +++ b/lib/pkcs11_int.h @@ -96,6 +96,37 @@ _gnutls_pkcs11_privkey_decrypt_data (gnutls_pkcs11_privkey_t key, const gnutls_datum_t * ciphertext, gnutls_datum_t * plaintext); +static inline int pk_to_mech(gnutls_pk_algorithm_t pk) +{ + if (pk == GNUTLS_PK_DSA) + return CKM_DSA; + else if (pk == GNUTLS_PK_ECC) + return CKM_ECDSA; + else + return CKM_RSA_PKCS; +} + +static inline int pk_to_genmech(gnutls_pk_algorithm_t pk) +{ + if (pk == GNUTLS_PK_DSA) + return CKM_DSA_KEY_PAIR_GEN; + else if (pk == GNUTLS_PK_ECC) + return CKM_ECDSA_KEY_PAIR_GEN; + else + return CKM_RSA_PKCS_KEY_PAIR_GEN; +} + +ck_rv_t +pkcs11_generate_key_pair (struct ck_function_list *module, + ck_session_handle_t sess, + struct ck_mechanism *mechanism, + struct ck_attribute *pub_templ, + unsigned long pub_templ_count, + struct ck_attribute *priv_templ, + unsigned long priv_templ_count, + ck_object_handle_t *pub, + ck_object_handle_t *priv); + ck_rv_t pkcs11_get_slot_list (struct ck_function_list * module, unsigned char token_present, diff --git a/lib/pkcs11_privkey.c b/lib/pkcs11_privkey.c index c1ba8fbc95..193fddf460 100644 --- a/lib/pkcs11_privkey.c +++ b/lib/pkcs11_privkey.c @@ -169,8 +169,7 @@ _gnutls_pkcs11_privkey_sign_hash (gnutls_pkcs11_privkey_t key, FIND_OBJECT (module, pks, obj, key); - mech.mechanism = - key->pk_algorithm == GNUTLS_PK_DSA ? CKM_DSA : CKM_RSA_PKCS; + mech.mechanism = pk_to_mech(key->pk_algorithm); mech.parameter = NULL; mech.parameter_len = 0; @@ -324,8 +323,10 @@ _gnutls_pkcs11_privkey_decrypt_data (gnutls_pkcs11_privkey_t key, FIND_OBJECT (module, pks, obj, key); - mech.mechanism = - key->pk_algorithm == GNUTLS_PK_DSA ? CKM_DSA : CKM_RSA_PKCS; + if (key->pk_algorithm != GNUTLS_PK_RSA) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + mech.mechanism = CKM_RSA_PKCS; mech.parameter = NULL; mech.parameter_len = 0; @@ -399,3 +400,197 @@ gnutls_pkcs11_privkey_export_url (gnutls_pkcs11_privkey_t key, return 0; } + + +/** + * gnutls_pkcs11_privkey_generate: + * @url: a token URL + * @pk: the public key algorithm + * @bits: the security bits + * @label: a label + * @flags: should be zero + * + * This function will generate a private key in the specified + * by the @url token. The pivate key will be generate within + * the token and will not be exportable. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a + * negative error value. + **/ +int +gnutls_pkcs11_privkey_generate (const char* url, + gnutls_pk_algorithm_t pk, unsigned int bits, + const char* label, unsigned int flags) +{ + int ret; + const ck_bool_t tval = 1; + const ck_bool_t fval = 0; + struct ck_function_list *module; + ck_session_handle_t pks = 0; + struct p11_kit_uri *info = NULL; + ck_rv_t rv; + size_t id_size; + opaque id[20]; + struct ck_attribute a[10], p[10]; + ck_object_handle_t pub, priv; + unsigned long _bits = bits; + int a_val, p_val; + struct ck_mechanism mech; + + ret = pkcs11_url_to_info (url, &info); + if (ret < 0) + { + gnutls_assert (); + return ret; + } + + ret = + pkcs11_open_session (&module, &pks, info, + SESSION_WRITE | pkcs11_obj_flags_to_int (flags)); + p11_kit_uri_free (info); + + if (ret < 0) + { + gnutls_assert (); + goto cleanup; + } + + /* a holds the public key template + * and p the private key */ + a_val = p_val = 0; + mech.parameter = NULL; + mech.parameter_len = 0; + mech.mechanism = pk_to_genmech(pk); + + switch(pk) + { + case GNUTLS_PK_RSA: + p[p_val].type = CKA_DECRYPT; + p[p_val].value = (void*)&tval; + p[p_val].value_len = sizeof (tval); + p_val++; + + p[p_val].type = CKA_SIGN; + p[p_val].value = (void*)&tval; + p[p_val].value_len = sizeof (tval); + p_val++; + + a[a_val].type = CKA_ENCRYPT; + a[a_val].value = (void*)&tval; + a[a_val].value_len = sizeof (tval); + a_val++; + + a[a_val].type = CKA_VERIFY; + a[a_val].value = (void*)&tval; + a[a_val].value_len = sizeof (tval); + a_val++; + + a[a_val].type = CKA_MODULUS_BITS; + a[a_val].value = &_bits; + a[a_val].value_len = sizeof (_bits); + a_val++; + break; + case GNUTLS_PK_DSA: + p[p_val].type = CKA_SIGN; + p[p_val].value = (void*)&tval; + p[p_val].value_len = sizeof (tval); + p_val++; + + a[a_val].type = CKA_VERIFY; + a[a_val].value = (void*)&tval; + a[a_val].value_len = sizeof (tval); + a_val++; + + a[a_val].type = CKA_MODULUS_BITS; + a[a_val].value = &_bits; + a[a_val].value_len = sizeof (_bits); + a_val++; + break; + case GNUTLS_PK_ECC: + p[p_val].type = CKA_SIGN; + p[p_val].value = (void*)&tval; + p[p_val].value_len = sizeof (tval); + p_val++; + + a[a_val].type = CKA_VERIFY; + a[a_val].value = (void*)&tval; + a[a_val].value_len = sizeof (tval); + a_val++; + + a[a_val].type = CKA_MODULUS_BITS; + a[a_val].value = &_bits; + a[a_val].value_len = sizeof (_bits); + a_val++; + break; + default: + ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + goto cleanup; + } + + /* a private key is set always as private unless + * requested otherwise + */ + if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE) + { + p[p_val].type = CKA_PRIVATE; + p[p_val].value = (void*)&fval; + p[p_val].value_len = sizeof(fval); + p_val++; + } + else + { + p[p_val].type = CKA_PRIVATE; + p[p_val].value = (void*)&tval; + p[p_val].value_len = sizeof (tval); + p_val++; + } + + p[p_val].type = CKA_TOKEN; + p[p_val].value = (void *)&tval; + p[p_val].value_len = sizeof (tval); + p_val++; + + if (label) + { + p[p_val].type = CKA_LABEL; + p[p_val].value = (void*)label; + p[p_val].value_len = strlen (label); + p_val++; + + a[a_val].type = CKA_LABEL; + a[a_val].value = (void*)label; + a[a_val].value_len = strlen (label); + a_val++; + } + + if (flags & GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE) + { + p[p_val].type = CKA_SENSITIVE; + p[p_val].value = (void*)&tval; + p[p_val].value_len = sizeof (tval); + p_val++; + } + else + { + p[p_val].type = CKA_SENSITIVE; + p[p_val].value = (void*)&fval; + p[p_val].value_len = sizeof (fval); + p_val++; + } + + rv = pkcs11_generate_key_pair( module, pks, &mech, a, a_val, p, p_val, &pub, &priv); + if (rv != CKR_OK) + { + gnutls_assert (); + _gnutls_debug_log ("pkcs11: %s\n", pkcs11_strerror (rv)); + ret = pkcs11_rv_to_err (rv); + goto cleanup; + } + + +cleanup: + if (pks != 0) + pkcs11_close_session (module, pks); + + return ret; +} diff --git a/lib/pkcs11_write.c b/lib/pkcs11_write.c index e5226a4e09..834194da7a 100644 --- a/lib/pkcs11_write.c +++ b/lib/pkcs11_write.c @@ -786,3 +786,4 @@ finish: return ret; } + diff --git a/src/certtool-common.c b/src/certtool-common.c index 1482d34b68..5ad9934ed3 100644 --- a/src/certtool-common.c +++ b/src/certtool-common.c @@ -607,3 +607,61 @@ int ret; return pubkey; } +int +get_bits (gnutls_pk_algorithm_t key_type, int info_bits, const char* info_sec_param) +{ + int bits; + + if (info_bits != 0) + { + static int warned = 0; + + if (warned == 0) + { + warned = 1; + fprintf (stderr, + "** Note: Please use the --sec-param instead of --bits\n"); + } + bits = info_bits; + } + else + { + if (info_sec_param) + { + bits = + gnutls_sec_param_to_pk_bits (key_type, + str_to_sec_param (info_sec_param)); + } + else + bits = + gnutls_sec_param_to_pk_bits (key_type, GNUTLS_SEC_PARAM_NORMAL); + } + + return bits; +} + +gnutls_sec_param_t str_to_sec_param (const char *str) +{ + if (strcasecmp (str, "low") == 0) + { + return GNUTLS_SEC_PARAM_LOW; + } + else if (strcasecmp (str, "normal") == 0) + { + return GNUTLS_SEC_PARAM_NORMAL; + } + else if (strcasecmp (str, "high") == 0) + { + return GNUTLS_SEC_PARAM_HIGH; + } + else if (strcasecmp (str, "ultra") == 0) + { + return GNUTLS_SEC_PARAM_ULTRA; + } + else + { + fprintf (stderr, "Unknown security parameter string: %s\n", str); + exit (1); + } + +} diff --git a/src/certtool-common.h b/src/certtool-common.h index e8ed9c7bac..add8a69bbb 100644 --- a/src/certtool-common.h +++ b/src/certtool-common.h @@ -67,9 +67,8 @@ gnutls_datum_t *load_secret_key (int mand, common_info_st * info); gnutls_pubkey_t load_pubkey (int mand, common_info_st * info); gnutls_x509_crt_t *load_cert_list (int mand, size_t * size, common_info_st * info); - -/* returns the bits specified in cmd */ -int get_bits (gnutls_pk_algorithm_t); +int get_bits (gnutls_pk_algorithm_t key_type, int info_bits, const char* info_sec_param); +gnutls_sec_param_t str_to_sec_param (const char *str); /* prime.c */ int generate_prime (int how); diff --git a/src/certtool-gaa.c b/src/certtool-gaa.c index 67ba16bf4c..01aebc4c6e 100644 --- a/src/certtool-gaa.c +++ b/src/certtool-gaa.c @@ -1289,7 +1289,8 @@ int gaa(int argc, char **argv, gaainfo *gaaval) 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; gaaval->export = 0; gaaval->template = NULL; gaaval->hash=NULL; gaaval->fix_key = 0; gaaval->quick_random=1; - gaaval->privkey_op = 0; gaaval->pkcs_cipher = "aes-128"; gaaval->crq_extensions=1; gaaval->ecc=0; ;}; + gaaval->privkey_op = 0; gaaval->pkcs_cipher = "aes-128"; gaaval->crq_extensions=1; gaaval->ecc=0; + gaaval->sec_param = NULL; ;}; } inited = 1; @@ -1437,7 +1438,7 @@ static int gaa_internal_get_next_str(FILE *file, gaa_str_node *tmp_str, int argc len++; a = fgetc( file); - if(a==EOF) return 0; //a = ' '; + if(a==EOF) return 0; } len += 1; diff --git a/src/certtool.c b/src/certtool.c index acdc8d74ec..e8fc37d05e 100644 --- a/src/certtool.c +++ b/src/certtool.c @@ -188,67 +188,6 @@ print_rsa_pkey (gnutls_datum_t * m, gnutls_datum_t * e, gnutls_datum_t * d, } } -static gnutls_sec_param_t -str_to_sec_param (const char *str) -{ - if (strcasecmp (str, "low") == 0) - { - return GNUTLS_SEC_PARAM_LOW; - } - else if (strcasecmp (str, "normal") == 0) - { - return GNUTLS_SEC_PARAM_NORMAL; - } - else if (strcasecmp (str, "high") == 0) - { - return GNUTLS_SEC_PARAM_HIGH; - } - else if (strcasecmp (str, "ultra") == 0) - { - return GNUTLS_SEC_PARAM_ULTRA; - } - else - { - fprintf (stderr, "Unknown security parameter string: %s\n", str); - exit (1); - } - -} - -int -get_bits (gnutls_pk_algorithm_t key_type) -{ - int bits; - - if (info.bits != 0) - { - static int warned = 0; - - if (warned == 0) - { - warned = 1; - fprintf (stderr, - "** Note: Please use the --sec-param instead of --bits\n"); - } - bits = info.bits; - } - else - { - if (info.sec_param) - { - bits = - gnutls_sec_param_to_pk_bits (key_type, - str_to_sec_param (info.sec_param)); - } - else - bits = - gnutls_sec_param_to_pk_bits (key_type, GNUTLS_SEC_PARAM_NORMAL); - } - - return bits; -} - - static gnutls_x509_privkey_t generate_private_key_int (void) { @@ -266,7 +205,7 @@ generate_private_key_int (void) if (ret < 0) error (EXIT_FAILURE, 0, "privkey_init: %s", gnutls_strerror (ret)); - bits = get_bits (key_type); + bits = get_bits (key_type, info.bits, info.sec_param); fprintf (stderr, "Generating a %d bit %s private key...\n", bits, gnutls_pk_algorithm_get_name (key_type)); diff --git a/src/certtool.gaa b/src/certtool.gaa index 078a5e8d86..4834d60a24 100644 --- a/src/certtool.gaa +++ b/src/certtool.gaa @@ -153,4 +153,5 @@ init { $bits = 0; $pkcs8 = 0; $privkey = NULL; $ca=NULL; $ca_privkey = NULL; $debug=1; $request = NULL; $infile = NULL; $outfile = NULL; $cert = NULL; $incert_format = 0; $outcert_format = 0; $action=-1; $pass = NULL; $v1_cert = 0; $export = 0; $template = NULL; $hash=NULL; $fix_key = 0; $quick_random=1; - $privkey_op = 0; $pkcs_cipher = "aes-128"; $crq_extensions=1; $ecc=0; } + $privkey_op = 0; $pkcs_cipher = "aes-128"; $crq_extensions=1; $ecc=0; + $sec_param = NULL; } diff --git a/src/p11common.c b/src/p11common.c index 4c7df1e1b7..0a8cf85299 100644 --- a/src/p11common.c +++ b/src/p11common.c @@ -129,3 +129,4 @@ pkcs11_common (void) gnutls_pkcs11_set_token_function (token_callback, NULL); } + diff --git a/src/p11tool-gaa.c b/src/p11tool-gaa.c index 18162402e8..8938e33d1b 100644 --- a/src/p11tool-gaa.c +++ b/src/p11tool-gaa.c @@ -145,6 +145,9 @@ void gaa_help(void) __gaa_helpsingle(0, "initialize", "URL ", "Initializes a PKCS11 token."); __gaa_helpsingle(0, "write", "URL ", "Writes loaded certificates, private or secret keys to a PKCS11 token."); __gaa_helpsingle(0, "delete", "URL ", "Deletes objects matching the URL."); + __gaa_helpsingle(0, "generate-rsa", "URL ", "Generates an RSA private key on the specified token."); + __gaa_helpsingle(0, "generate-dsa", "URL ", "Generates a DSA private key on the specified token."); + __gaa_helpsingle(0, "generate-ecc", "URL ", "Generates an ECDSA private key on the specified token."); __gaa_helpsingle(0, "label", "label ", "Sets a label for the write operation."); __gaa_helpsingle(0, "trusted", "", "Marks the certificate to be written as trusted."); __gaa_helpsingle(0, "private", "", "Marks the object to be written as private (requires PIN)."); @@ -157,6 +160,8 @@ void gaa_help(void) __gaa_helpsingle(0, "load-pubkey", "FILE ", "Private key file to use."); __gaa_helpsingle(0, "load-certificate", "FILE ", "Certificate file to use."); __gaa_helpsingle('8', "pkcs8", "", "Use PKCS #8 format for private keys."); + __gaa_helpsingle(0, "bits", "BITS ", "specify the number of bits for key generation."); + __gaa_helpsingle(0, "sec-param", "PARAM ", "specify the security level [low|normal|high|ultra]."); __gaa_helpsingle(0, "inder", "", "Use DER format for input certificates and private keys."); __gaa_helpsingle(0, "inraw", "", "Use RAW/DER format for input certificates and private keys."); __gaa_helpsingle(0, "provider", "Library ", "Specify the pkcs11 provider library"); @@ -177,34 +182,40 @@ typedef struct _gaainfo gaainfo; struct _gaainfo { -#line 84 "p11tool.gaa" +#line 94 "p11tool.gaa" int debug; -#line 79 "p11tool.gaa" +#line 89 "p11tool.gaa" char *outfile; -#line 76 "p11tool.gaa" +#line 86 "p11tool.gaa" int action; -#line 75 "p11tool.gaa" +#line 85 "p11tool.gaa" char* pkcs11_provider; -#line 71 "p11tool.gaa" +#line 81 "p11tool.gaa" int incert_format; -#line 68 "p11tool.gaa" +#line 78 "p11tool.gaa" + char* sec_param; +#line 75 "p11tool.gaa" + int bits; +#line 72 "p11tool.gaa" int pkcs8; -#line 65 "p11tool.gaa" +#line 69 "p11tool.gaa" char *cert; -#line 62 "p11tool.gaa" +#line 66 "p11tool.gaa" char *pubkey; -#line 59 "p11tool.gaa" +#line 63 "p11tool.gaa" char *privkey; -#line 56 "p11tool.gaa" +#line 60 "p11tool.gaa" char* secret_key; -#line 52 "p11tool.gaa" +#line 56 "p11tool.gaa" int pkcs11_detailed_url; -#line 49 "p11tool.gaa" +#line 53 "p11tool.gaa" int pkcs11_login; -#line 45 "p11tool.gaa" +#line 49 "p11tool.gaa" int pkcs11_private; -#line 42 "p11tool.gaa" +#line 46 "p11tool.gaa" int pkcs11_trusted; +#line 40 "p11tool.gaa" + int key_type; #line 35 "p11tool.gaa" char* pkcs11_label; #line 24 "p11tool.gaa" @@ -265,36 +276,41 @@ static int gaa_error = 0; #define GAA_MULTIPLE_OPTION 3 #define GAA_REST 0 -#define GAA_NB_OPTION 29 +#define GAA_NB_OPTION 34 #define GAAOPTID_help 1 #define GAAOPTID_debug 2 #define GAAOPTID_outfile 3 #define GAAOPTID_provider 4 #define GAAOPTID_inraw 5 #define GAAOPTID_inder 6 -#define GAAOPTID_pkcs8 7 -#define GAAOPTID_load_certificate 8 -#define GAAOPTID_load_pubkey 9 -#define GAAOPTID_load_privkey 10 -#define GAAOPTID_secret_key 11 -#define GAAOPTID_no_detailed_url 12 -#define GAAOPTID_detailed_url 13 -#define GAAOPTID_login 14 -#define GAAOPTID_no_private 15 -#define GAAOPTID_private 16 -#define GAAOPTID_trusted 17 -#define GAAOPTID_label 18 -#define GAAOPTID_delete 19 -#define GAAOPTID_write 20 -#define GAAOPTID_initialize 21 -#define GAAOPTID_list_trusted 22 -#define GAAOPTID_list_privkeys 23 -#define GAAOPTID_list_certs 24 -#define GAAOPTID_list_all_certs 25 -#define GAAOPTID_list_all 26 -#define GAAOPTID_list_mechanisms 27 -#define GAAOPTID_list_tokens 28 -#define GAAOPTID_export 29 +#define GAAOPTID_sec_param 7 +#define GAAOPTID_bits 8 +#define GAAOPTID_pkcs8 9 +#define GAAOPTID_load_certificate 10 +#define GAAOPTID_load_pubkey 11 +#define GAAOPTID_load_privkey 12 +#define GAAOPTID_secret_key 13 +#define GAAOPTID_no_detailed_url 14 +#define GAAOPTID_detailed_url 15 +#define GAAOPTID_login 16 +#define GAAOPTID_no_private 17 +#define GAAOPTID_private 18 +#define GAAOPTID_trusted 19 +#define GAAOPTID_label 20 +#define GAAOPTID_generate_ecc 21 +#define GAAOPTID_generate_dsa 22 +#define GAAOPTID_generate_rsa 23 +#define GAAOPTID_delete 24 +#define GAAOPTID_write 25 +#define GAAOPTID_initialize 26 +#define GAAOPTID_list_trusted 27 +#define GAAOPTID_list_privkeys 28 +#define GAAOPTID_list_certs 29 +#define GAAOPTID_list_all_certs 30 +#define GAAOPTID_list_all 31 +#define GAAOPTID_list_mechanisms 32 +#define GAAOPTID_list_tokens 33 +#define GAAOPTID_export 34 #line 168 "gaa.skel" @@ -499,6 +515,18 @@ struct GAAOPTION_provider int size1; }; +struct GAAOPTION_sec_param +{ + char* arg1; + int size1; +}; + +struct GAAOPTION_bits +{ + int arg1; + int size1; +}; + struct GAAOPTION_load_certificate { char* arg1; @@ -529,6 +557,24 @@ struct GAAOPTION_label int size1; }; +struct GAAOPTION_generate_ecc +{ + char* arg1; + int size1; +}; + +struct GAAOPTION_generate_dsa +{ + char* arg1; + int size1; +}; + +struct GAAOPTION_generate_rsa +{ + char* arg1; + int size1; +}; + struct GAAOPTION_delete { char* arg1; @@ -591,11 +637,16 @@ static int gaa_get_option_num(char *str, int status) GAA_CHECK1STR("d", GAAOPTID_debug); GAA_CHECK1STR("", GAAOPTID_outfile); GAA_CHECK1STR("", GAAOPTID_provider); + GAA_CHECK1STR("", GAAOPTID_sec_param); + GAA_CHECK1STR("", GAAOPTID_bits); GAA_CHECK1STR("", GAAOPTID_load_certificate); GAA_CHECK1STR("", GAAOPTID_load_pubkey); GAA_CHECK1STR("", GAAOPTID_load_privkey); GAA_CHECK1STR("", GAAOPTID_secret_key); GAA_CHECK1STR("", GAAOPTID_label); + GAA_CHECK1STR("", GAAOPTID_generate_ecc); + GAA_CHECK1STR("", GAAOPTID_generate_dsa); + GAA_CHECK1STR("", GAAOPTID_generate_rsa); GAA_CHECK1STR("", GAAOPTID_delete); GAA_CHECK1STR("", GAAOPTID_write); GAA_CHECK1STR("", GAAOPTID_initialize); @@ -629,6 +680,8 @@ static int gaa_get_option_num(char *str, int status) GAA_CHECKSTR("provider", GAAOPTID_provider); GAA_CHECKSTR("inraw", GAAOPTID_inraw); GAA_CHECKSTR("inder", GAAOPTID_inder); + GAA_CHECKSTR("sec-param", GAAOPTID_sec_param); + GAA_CHECKSTR("bits", GAAOPTID_bits); GAA_CHECKSTR("pkcs8", GAAOPTID_pkcs8); GAA_CHECKSTR("load-certificate", GAAOPTID_load_certificate); GAA_CHECKSTR("load-pubkey", GAAOPTID_load_pubkey); @@ -641,6 +694,9 @@ static int gaa_get_option_num(char *str, int status) GAA_CHECKSTR("private", GAAOPTID_private); GAA_CHECKSTR("trusted", GAAOPTID_trusted); GAA_CHECKSTR("label", GAAOPTID_label); + GAA_CHECKSTR("generate-ecc", GAAOPTID_generate_ecc); + GAA_CHECKSTR("generate-dsa", GAAOPTID_generate_dsa); + GAA_CHECKSTR("generate-rsa", GAAOPTID_generate_rsa); GAA_CHECKSTR("delete", GAAOPTID_delete); GAA_CHECKSTR("write", GAAOPTID_write); GAA_CHECKSTR("initialize", GAAOPTID_initialize); @@ -667,11 +723,16 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) struct GAAOPTION_debug GAATMP_debug; struct GAAOPTION_outfile GAATMP_outfile; struct GAAOPTION_provider GAATMP_provider; + struct GAAOPTION_sec_param GAATMP_sec_param; + struct GAAOPTION_bits GAATMP_bits; struct GAAOPTION_load_certificate GAATMP_load_certificate; struct GAAOPTION_load_pubkey GAATMP_load_pubkey; struct GAAOPTION_load_privkey GAATMP_load_privkey; struct GAAOPTION_secret_key GAATMP_secret_key; struct GAAOPTION_label GAATMP_label; + struct GAAOPTION_generate_ecc GAATMP_generate_ecc; + struct GAAOPTION_generate_dsa GAATMP_generate_dsa; + struct GAAOPTION_generate_rsa GAATMP_generate_rsa; struct GAAOPTION_delete GAATMP_delete; struct GAAOPTION_write GAATMP_write; struct GAAOPTION_initialize GAATMP_initialize; @@ -699,7 +760,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) { case GAAOPTID_help: OK = 0; -#line 87 "p11tool.gaa" +#line 97 "p11tool.gaa" { gaa_help(); exit(0); ;}; return GAA_OK; @@ -709,7 +770,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 85 "p11tool.gaa" +#line 95 "p11tool.gaa" { gaaval->debug = GAATMP_debug.arg1 ;}; return GAA_OK; @@ -719,7 +780,7 @@ 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 80 "p11tool.gaa" +#line 90 "p11tool.gaa" { gaaval->outfile = GAATMP_outfile.arg1 ;}; return GAA_OK; @@ -729,28 +790,48 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_provider.arg1, gaa_getstr, GAATMP_provider.size1); gaa_index++; -#line 77 "p11tool.gaa" +#line 87 "p11tool.gaa" { gaaval->pkcs11_provider = GAATMP_provider.arg1 ;}; return GAA_OK; break; case GAAOPTID_inraw: OK = 0; -#line 73 "p11tool.gaa" +#line 83 "p11tool.gaa" { gaaval->incert_format=GNUTLS_X509_FMT_DER ;}; return GAA_OK; break; case GAAOPTID_inder: OK = 0; -#line 72 "p11tool.gaa" +#line 82 "p11tool.gaa" { gaaval->incert_format=GNUTLS_X509_FMT_DER ;}; return GAA_OK; break; + case GAAOPTID_sec_param: + OK = 0; + GAA_TESTMOREARGS; + GAA_FILL(GAATMP_sec_param.arg1, gaa_getstr, GAATMP_sec_param.size1); + gaa_index++; +#line 79 "p11tool.gaa" +{ gaaval->sec_param = GAATMP_sec_param.arg1 ;}; + + return GAA_OK; + break; + case GAAOPTID_bits: + OK = 0; + GAA_TESTMOREARGS; + GAA_FILL(GAATMP_bits.arg1, gaa_getint, GAATMP_bits.size1); + gaa_index++; +#line 76 "p11tool.gaa" +{ gaaval->bits = GAATMP_bits.arg1 ;}; + + return GAA_OK; + break; case GAAOPTID_pkcs8: OK = 0; -#line 69 "p11tool.gaa" +#line 73 "p11tool.gaa" { gaaval->pkcs8=1 ;}; return GAA_OK; @@ -760,7 +841,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_load_certificate.arg1, gaa_getstr, GAATMP_load_certificate.size1); gaa_index++; -#line 66 "p11tool.gaa" +#line 70 "p11tool.gaa" { gaaval->cert = GAATMP_load_certificate.arg1 ;}; return GAA_OK; @@ -770,7 +851,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_load_pubkey.arg1, gaa_getstr, GAATMP_load_pubkey.size1); gaa_index++; -#line 63 "p11tool.gaa" +#line 67 "p11tool.gaa" { gaaval->pubkey = GAATMP_load_pubkey.arg1 ;}; return GAA_OK; @@ -780,7 +861,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_load_privkey.arg1, gaa_getstr, GAATMP_load_privkey.size1); gaa_index++; -#line 60 "p11tool.gaa" +#line 64 "p11tool.gaa" { gaaval->privkey = GAATMP_load_privkey.arg1 ;}; return GAA_OK; @@ -790,49 +871,49 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_secret_key.arg1, gaa_getstr, GAATMP_secret_key.size1); gaa_index++; -#line 57 "p11tool.gaa" +#line 61 "p11tool.gaa" { gaaval->secret_key = GAATMP_secret_key.arg1; ;}; return GAA_OK; break; case GAAOPTID_no_detailed_url: OK = 0; -#line 54 "p11tool.gaa" +#line 58 "p11tool.gaa" { gaaval->pkcs11_detailed_url = 0; ;}; return GAA_OK; break; case GAAOPTID_detailed_url: OK = 0; -#line 53 "p11tool.gaa" +#line 57 "p11tool.gaa" { gaaval->pkcs11_detailed_url = GNUTLS_PKCS11_URL_LIB; ;}; return GAA_OK; break; case GAAOPTID_login: OK = 0; -#line 50 "p11tool.gaa" +#line 54 "p11tool.gaa" { gaaval->pkcs11_login = 1; ;}; return GAA_OK; break; case GAAOPTID_no_private: OK = 0; -#line 47 "p11tool.gaa" +#line 51 "p11tool.gaa" { gaaval->pkcs11_private = 0; ;}; return GAA_OK; break; case GAAOPTID_private: OK = 0; -#line 46 "p11tool.gaa" +#line 50 "p11tool.gaa" { gaaval->pkcs11_private = 1; ;}; return GAA_OK; break; case GAAOPTID_trusted: OK = 0; -#line 43 "p11tool.gaa" +#line 47 "p11tool.gaa" { gaaval->pkcs11_trusted = 1; ;}; return GAA_OK; @@ -842,11 +923,41 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_label.arg1, gaa_getstr, GAATMP_label.size1); gaa_index++; -#line 41 "p11tool.gaa" +#line 45 "p11tool.gaa" { gaaval->pkcs11_label = GAATMP_label.arg1; ;}; return GAA_OK; break; + case GAAOPTID_generate_ecc: + OK = 0; + GAA_TESTMOREARGS; + GAA_FILL(GAATMP_generate_ecc.arg1, gaa_getstr, GAATMP_generate_ecc.size1); + gaa_index++; +#line 43 "p11tool.gaa" +{ gaaval->action = ACTION_PKCS11_GENERATE; gaaval->key_type = GNUTLS_PK_ECC; gaaval->pkcs11_url = GAATMP_generate_ecc.arg1; ;}; + + return GAA_OK; + break; + case GAAOPTID_generate_dsa: + OK = 0; + GAA_TESTMOREARGS; + GAA_FILL(GAATMP_generate_dsa.arg1, gaa_getstr, GAATMP_generate_dsa.size1); + gaa_index++; +#line 42 "p11tool.gaa" +{ gaaval->action = ACTION_PKCS11_GENERATE; gaaval->key_type = GNUTLS_PK_DSA; gaaval->pkcs11_url = GAATMP_generate_dsa.arg1; ;}; + + return GAA_OK; + break; + case GAAOPTID_generate_rsa: + OK = 0; + GAA_TESTMOREARGS; + GAA_FILL(GAATMP_generate_rsa.arg1, gaa_getstr, GAATMP_generate_rsa.size1); + gaa_index++; +#line 41 "p11tool.gaa" +{ gaaval->action = ACTION_PKCS11_GENERATE; gaaval->key_type = GNUTLS_PK_RSA; gaaval->pkcs11_url = GAATMP_generate_rsa.arg1; ;}; + + return GAA_OK; + break; case GAAOPTID_delete: OK = 0; GAA_TESTMOREARGS; @@ -963,12 +1074,13 @@ int gaa(int argc, char **argv, gaainfo *gaaval) if(inited == 0) { -#line 89 "p11tool.gaa" +#line 99 "p11tool.gaa" { gaaval->action = -1; gaaval->pkcs11_provider= NULL; gaaval->outfile = NULL; gaaval->pubkey = NULL; gaaval->privkey = NULL; gaaval->pkcs11_url = NULL; gaaval->pkcs11_type = PKCS11_TYPE_PK; gaaval->pubkey=NULL; gaaval->pkcs11_label = NULL; - gaaval->pkcs11_trusted=0; gaaval->pkcs11_login = 0; gaaval->pkcs11_detailed_url = GNUTLS_PKCS11_URL_LIB; - gaaval->secret_key = NULL; gaaval->cert = NULL; gaaval->incert_format = GNUTLS_X509_FMT_PEM; gaaval->pkcs11_private = -1; ;}; + gaaval->pkcs11_trusted=0; gaaval->pkcs11_login = 0; gaaval->pkcs11_detailed_url = 0; + gaaval->secret_key = NULL; gaaval->cert = NULL; gaaval->incert_format = GNUTLS_X509_FMT_PEM; gaaval->pkcs11_private = -1; + gaaval->key_type = 0; gaaval->bits = 0; gaaval->sec_param = NULL; ;}; } inited = 1; @@ -1116,7 +1228,7 @@ static int gaa_internal_get_next_str(FILE *file, gaa_str_node *tmp_str, int argc len++; a = fgetc( file); - if(a==EOF) return 0; //a = ' '; + if(a==EOF) return 0; } len += 1; diff --git a/src/p11tool-gaa.h b/src/p11tool-gaa.h index bc5871f5e6..7fec01a0ae 100644 --- a/src/p11tool-gaa.h +++ b/src/p11tool-gaa.h @@ -8,34 +8,40 @@ typedef struct _gaainfo gaainfo; struct _gaainfo { -#line 84 "p11tool.gaa" +#line 94 "p11tool.gaa" int debug; -#line 79 "p11tool.gaa" +#line 89 "p11tool.gaa" char *outfile; -#line 76 "p11tool.gaa" +#line 86 "p11tool.gaa" int action; -#line 75 "p11tool.gaa" +#line 85 "p11tool.gaa" char* pkcs11_provider; -#line 71 "p11tool.gaa" +#line 81 "p11tool.gaa" int incert_format; -#line 68 "p11tool.gaa" +#line 78 "p11tool.gaa" + char* sec_param; +#line 75 "p11tool.gaa" + int bits; +#line 72 "p11tool.gaa" int pkcs8; -#line 65 "p11tool.gaa" +#line 69 "p11tool.gaa" char *cert; -#line 62 "p11tool.gaa" +#line 66 "p11tool.gaa" char *pubkey; -#line 59 "p11tool.gaa" +#line 63 "p11tool.gaa" char *privkey; -#line 56 "p11tool.gaa" +#line 60 "p11tool.gaa" char* secret_key; -#line 52 "p11tool.gaa" +#line 56 "p11tool.gaa" int pkcs11_detailed_url; -#line 49 "p11tool.gaa" +#line 53 "p11tool.gaa" int pkcs11_login; -#line 45 "p11tool.gaa" +#line 49 "p11tool.gaa" int pkcs11_private; -#line 42 "p11tool.gaa" +#line 46 "p11tool.gaa" int pkcs11_trusted; +#line 40 "p11tool.gaa" + int key_type; #line 35 "p11tool.gaa" char* pkcs11_label; #line 24 "p11tool.gaa" diff --git a/src/p11tool.c b/src/p11tool.c index ebaa6fd4b0..2df036b55c 100644 --- a/src/p11tool.c +++ b/src/p11tool.c @@ -155,6 +155,11 @@ gaa_parser (int argc, char **argv) case ACTION_PKCS11_DELETE_URL: pkcs11_delete (outfile, info.pkcs11_url, 0, info.pkcs11_login, &cinfo); break; + case ACTION_PKCS11_GENERATE: + pkcs11_generate (outfile, info.pkcs11_url, info.key_type, get_bits(info.key_type, info.bits, info.sec_param), + info.pkcs11_label, info.pkcs11_private, info.pkcs11_detailed_url, info.pkcs11_login, + &cinfo); + break; default: gaa_help (); exit (0); diff --git a/src/p11tool.gaa b/src/p11tool.gaa index 9c2e4ae174..3c3cdfc411 100644 --- a/src/p11tool.gaa +++ b/src/p11tool.gaa @@ -37,6 +37,10 @@ option (initialize) STR "URL" { $action = ACTION_PKCS11_TOKEN_INIT; $pkcs11_url option (write) STR "URL" { $action = ACTION_PKCS11_WRITE_URL; $pkcs11_url = $1; } "Writes loaded certificates, private or secret keys to a PKCS11 token." option (delete) STR "URL" { $action = ACTION_PKCS11_DELETE_URL; $pkcs11_url = $1; } "Deletes objects matching the URL." +#int key_type; +option (generate-rsa) STR "URL" { $action = ACTION_PKCS11_GENERATE; $key_type = GNUTLS_PK_RSA; $pkcs11_url = $1; } "Generates an RSA private key on the specified token." +option (generate-dsa) STR "URL" { $action = ACTION_PKCS11_GENERATE; $key_type = GNUTLS_PK_DSA; $pkcs11_url = $1; } "Generates a DSA private key on the specified token." +option (generate-ecc) STR "URL" { $action = ACTION_PKCS11_GENERATE; $key_type = GNUTLS_PK_ECC; $pkcs11_url = $1; } "Generates an ECDSA private key on the specified token." option (label) STR "label" { $pkcs11_label = $1; } "Sets a label for the write operation." #int pkcs11_trusted; @@ -68,6 +72,12 @@ option (load-certificate) STR "FILE" { $cert = $1 } "Certificate file to use." #int pkcs8; option (8, pkcs8) { $pkcs8=1 } "Use PKCS #8 format for private keys." +#int bits; +option (bits) INT "BITS" { $bits = $1 } "specify the number of bits for key generation." + +#char* sec_param; +option (sec-param) STR "PARAM" { $sec_param = $1 } "specify the security level [low|normal|high|ultra]." + #int incert_format; option (inder) { $incert_format=GNUTLS_X509_FMT_DER } "Use DER format for input certificates and private keys." option (inraw) { $incert_format=GNUTLS_X509_FMT_DER } "Use RAW/DER format for input certificates and private keys." @@ -89,5 +99,6 @@ option (h, help) { gaa_help(); exit(0); } "shows this help text" init { $action = -1; $pkcs11_provider= NULL; $outfile = NULL; $pubkey = NULL; $privkey = NULL; $pkcs11_url = NULL; $pkcs11_type = PKCS11_TYPE_PK; $pubkey=NULL; $pkcs11_label = NULL; - $pkcs11_trusted=0; $pkcs11_login = 0; $pkcs11_detailed_url = GNUTLS_PKCS11_URL_LIB; - $secret_key = NULL; $cert = NULL; $incert_format = GNUTLS_X509_FMT_PEM; $pkcs11_private = -1; } + $pkcs11_trusted=0; $pkcs11_login = 0; $pkcs11_detailed_url = 0; + $secret_key = NULL; $cert = NULL; $incert_format = GNUTLS_X509_FMT_PEM; $pkcs11_private = -1; + $key_type = 0; $bits = 0; $sec_param = NULL; } diff --git a/src/p11tool.h b/src/p11tool.h index 3682fb15ad..7506751adc 100644 --- a/src/p11tool.h +++ b/src/p11tool.h @@ -18,6 +18,11 @@ void pkcs11_delete (FILE * outfile, const char *pkcs11_url, int batch, unsigned int login, common_info_st *); void pkcs11_init (FILE * outfile, const char *pkcs11_url, const char *label, common_info_st *); +void +pkcs11_generate (FILE * outfile, const char *url, gnutls_pk_algorithm_t type, + unsigned int bits, + const char *label, int private, int detailed, + unsigned int login, common_info_st * info); #define PKCS11_TYPE_CRT_ALL 1 #define PKCS11_TYPE_TRUSTED 2 @@ -35,6 +40,7 @@ enum ACTION_PKCS11_DELETE_URL, ACTION_PKCS11_TOKEN_INIT, ACTION_PKCS11_MECHANISMS, + ACTION_PKCS11_GENERATE, }; #endif diff --git a/src/pkcs11.c b/src/pkcs11.c index 8a7420440b..b0693da214 100644 --- a/src/pkcs11.c +++ b/src/pkcs11.c @@ -546,6 +546,39 @@ pkcs11_write (FILE * outfile, const char *url, const char *label, } void +pkcs11_generate (FILE * outfile, const char *url, gnutls_pk_algorithm_t pk, + unsigned int bits, + const char *label, int private, int detailed, + unsigned int login, common_info_st * info) +{ + int ret; + unsigned int flags = 0; + + if (login) + flags = GNUTLS_PKCS11_OBJ_FLAG_LOGIN; + + pkcs11_common (); + + if (url == NULL) + url = "pkcs11:"; + + if (private == 1) + flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE; + else if (private == 0) + flags |= GNUTLS_PKCS11_OBJ_FLAG_MARK_NOT_PRIVATE; + + ret = gnutls_pkcs11_privkey_generate(url, pk, bits, label, flags); + if (ret < 0) + { + fprintf (stderr, "Error in %s:%d: %s\n", __func__, __LINE__, + gnutls_strerror (ret)); + exit(1); + } + + return; +} + +void pkcs11_init (FILE * outfile, const char *url, const char *label, common_info_st * info) { |