diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2010-05-22 20:15:22 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2010-05-23 11:13:50 +0200 |
commit | 16aa3673a3d7d5070fbf43d1aa46059bc9a42266 (patch) | |
tree | d81d0299413b9760419ff767051d7b951561d65c | |
parent | e6369864af00a519f4a38ced7cbb6878e3c248c4 (diff) | |
download | gnutls-16aa3673a3d7d5070fbf43d1aa46059bc9a42266.tar.gz |
Added gnutls_pubkey_import_pkcs11(), gnutls_pubkey_import_rsa_raw(),
gnutls_pubkey_import_dsa_raw(), gnutls_pkcs11_obj_export().
-rw-r--r-- | NEWS | 6 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | lib/gnutls_pubkey.c | 310 | ||||
-rw-r--r-- | lib/includes/gnutls/abstract.h | 10 | ||||
-rw-r--r-- | lib/includes/gnutls/pkcs11.h | 3 | ||||
-rw-r--r-- | lib/libgnutls.map | 8 | ||||
-rw-r--r-- | lib/pkcs11.c | 281 | ||||
-rw-r--r-- | lib/pkcs11_int.h | 5 | ||||
-rw-r--r-- | lib/x509/x509.c | 6 | ||||
-rw-r--r-- | src/pkcs11.c | 94 |
10 files changed, 591 insertions, 134 deletions
@@ -34,6 +34,7 @@ pkcs11:token=Root%20CA%20Certificates;serial=1%3AROOTS%3ADEFAULT;model=1%2E0;man gnutls_certificate_set_server_retrieve_function: DEPRECATED gnutls_certificate_set_client_retrieve_function: DEPRECATED gnutls_sign_callback_set: DEPRECATED +gnutls_pkcs11_type_get_name: ADDED gnutls_certificate_set_retrieve_function: ADDED gnutls_pkcs11_init: ADDED gnutls_pkcs11_deinit: ADDED @@ -45,7 +46,9 @@ gnutls_pkcs11_obj_import_url: ADDED gnutls_pkcs11_obj_export_url: ADDED gnutls_pkcs11_obj_deinit: ADDED gnutls_pkcs11_obj_list_deinit: ADDED +gnutls_pkcs11_obj_export: ADDED gnutls_pkcs11_obj_list_import_url: ADDED +gnutls_pkcs11_obj_export: ADDED gnutls_x509_crt_import_pkcs11: ADDED gnutls_pkcs11_obj_get_type: ADDED gnutls_x509_crt_list_import_pkcs11: ADDED @@ -88,6 +91,9 @@ gnutls_pubkey_get_key_usage: ADDED gnutls_pkcs11_type_get_name: ADDED gnutls_pubkey_import_pkcs11_url: ADDED gnutls_pubkey_import: ADDED +gnutls_pubkey_import_pkcs11: ADDED +gnutls_pubkey_import_dsa_raw: ADDED +gnutls_pubkey_import_rsa_raw: ADDED gnutls_x509_crt_set_pubkey: ADDED gnutls_x509_crq_set_pubkey: ADDED diff --git a/configure.ac b/configure.ac index 050c0a7365..5e4155b7a0 100644 --- a/configure.ac +++ b/configure.ac @@ -205,7 +205,7 @@ AC_ARG_ENABLE([gcc-warnings], if test "$gl_gcc_warnings" = yes; then gl_WARN_ADD([-Werror], [WERROR_CFLAGS]) - gl_WARN_ADD([-Wframe-larger-than=2100], [WSTACK_CFLAGS]) + gl_WARN_ADD([-Wframe-larger-than=5120], [WSTACK_CFLAGS]) nw="$nw -Wsystem-headers" # Don't let system headers trigger warnings nw="$nw -Wc++-compat" # We don't care about C++ compilers diff --git a/lib/gnutls_pubkey.c b/lib/gnutls_pubkey.c index 985f4733ea..67dc916a6d 100644 --- a/lib/gnutls_pubkey.c +++ b/lib/gnutls_pubkey.c @@ -35,6 +35,9 @@ #include <x509_int.h> #include <openpgp/openpgp_int.h> #include <pkcs11_int.h> +#include <gnutls_num.h> +#include <x509/common.h> +#include <x509_b64.h> #define PK_PEM_HEADER "PUBLIC KEY" @@ -181,6 +184,56 @@ int gnutls_pubkey_import_x509(gnutls_pubkey_t key, gnutls_x509_crt_t crt, } /** + * gnutls_pubkey_import_pkcs11: + * @key: The public key + * @obj: The parameters to be imported + * @flags: should be zero + * + * This function will import the given public key to the abstract + * #gnutls_pubkey_t structure. + * + * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a + * negative error value. + **/ +int gnutls_pubkey_import_pkcs11(gnutls_pubkey_t key, + gnutls_pkcs11_obj_t obj, + unsigned int flags) +{ + int ret; + + ret = gnutls_pkcs11_obj_get_type(obj); + if (ret != GNUTLS_PKCS11_OBJ_PUBKEY) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + key->key_usage = obj->key_usage; + + switch (obj->pk_algorithm) { + case GNUTLS_PK_RSA: + ret = gnutls_pubkey_import_rsa_raw(key, &obj->pubkey[0], + &obj->pubkey[1]); + break; + case GNUTLS_PK_DSA: + ret = gnutls_pubkey_import_dsa_raw(key, &obj->pubkey[0], + &obj->pubkey[1], + &obj->pubkey[2], + &obj->pubkey[3]); + break; + default: + gnutls_assert(); + return GNUTLS_E_UNIMPLEMENTED_FEATURE; + } + + if (ret < 0) { + gnutls_assert(); + return ret; + } + + return 0; +} + +/** * gnutls_pubkey_import_openpgp: * @key: The public key * @crt: The certificate to be imported @@ -371,7 +424,6 @@ gnutls_pubkey_get_pk_rsa_raw(gnutls_pubkey_t key, gnutls_datum_t * m, gnutls_datum_t * e) { int ret; - int i; if (key == NULL) { gnutls_assert(); @@ -419,9 +471,6 @@ gnutls_pubkey_get_pk_dsa_raw(gnutls_pubkey_t key, gnutls_datum_t * g, gnutls_datum_t * y) { int ret; - bigint_t params[MAX_PUBLIC_PARAMS_SIZE]; - int params_size = MAX_PUBLIC_PARAMS_SIZE; - int i; if (key == NULL) { gnutls_assert(); @@ -486,8 +535,8 @@ gnutls_pubkey_get_pk_dsa_raw(gnutls_pubkey_t key, * negative error value. **/ int gnutls_pubkey_import(gnutls_pubkey_t key, - const gnutls_datum_t * data, - gnutls_x509_crt_fmt_t format) + const gnutls_datum_t * data, + gnutls_x509_crt_fmt_t format) { int result = 0, need_free = 0; gnutls_datum_t _data; @@ -532,10 +581,10 @@ int gnutls_pubkey_import(gnutls_pubkey_t key, goto cleanup; } - result = asn1_der_decoding (&spk, _data.data, _data.size, NULL); + result = asn1_der_decoding(&spk, _data.data, _data.size, NULL); if (result != ASN1_SUCCESS) { - gnutls_assert (); - result = _gnutls_asn2err (result); + gnutls_assert(); + result = _gnutls_asn2err(result); goto cleanup; } @@ -546,15 +595,15 @@ int gnutls_pubkey_import(gnutls_pubkey_t key, gnutls_assert(); goto cleanup; } - + /* this has already been called by get_asn_mpis() thus it cannot * fail. */ - key->pk_algorithm = _gnutls_x509_get_pk_algorithm (spk, "", NULL); + key->pk_algorithm = _gnutls_x509_get_pk_algorithm(spk, "", NULL); result = 0; -cleanup: + cleanup: asn1_delete_structure(&spk); if (need_free) @@ -562,61 +611,55 @@ cleanup: return result; } -int gnutls_x509_crt_set_pubkey (gnutls_x509_crt_t crt, - gnutls_pubkey_t key) +int gnutls_x509_crt_set_pubkey(gnutls_x509_crt_t crt, gnutls_pubkey_t key) { - int result; + int result; - if (crt == NULL) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } + if (crt == NULL) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } - result = _gnutls_x509_encode_and_copy_PKI_params (crt->cert, - "tbsCertificate.subjectPublicKeyInfo", - key->pk_algorithm, - key->params, - key->params_size); + result = _gnutls_x509_encode_and_copy_PKI_params(crt->cert, + "tbsCertificate.subjectPublicKeyInfo", + key->pk_algorithm, + key->params, + key->params_size); - if (result < 0) - { - gnutls_assert (); - return result; - } + if (result < 0) { + gnutls_assert(); + return result; + } if (key->key_usage) gnutls_x509_crt_set_key_usage(crt, key->key_usage); - return 0; + return 0; } -int gnutls_x509_crq_set_pubkey (gnutls_x509_crq_t crq, - gnutls_pubkey_t key) +int gnutls_x509_crq_set_pubkey(gnutls_x509_crq_t crq, gnutls_pubkey_t key) { - int result; + int result; - if (crq == NULL) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } + if (crq == NULL) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } - result = _gnutls_x509_encode_and_copy_PKI_params - (crq->crq, - "certificationRequestInfo.subjectPKInfo", - key->pk_algorithm, key->params, key->params_size); + result = _gnutls_x509_encode_and_copy_PKI_params + (crq->crq, + "certificationRequestInfo.subjectPKInfo", + key->pk_algorithm, key->params, key->params_size); - if (result < 0) - { - gnutls_assert (); - return result; - } + if (result < 0) { + gnutls_assert(); + return result; + } if (key->key_usage) gnutls_x509_crq_set_key_usage(crq, key->key_usage); - return 0; + return 0; } /** @@ -629,42 +672,149 @@ int gnutls_x509_crq_set_pubkey (gnutls_x509_crq_t crq, * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. **/ -int -gnutls_pubkey_set_key_usage (gnutls_pubkey_t key, unsigned int usage) +int gnutls_pubkey_set_key_usage(gnutls_pubkey_t key, unsigned int usage) { key->key_usage = usage; - + return 0; } -int gnutls_pubkey_import_pkcs11_url( gnutls_pubkey_t key, const char* url) +int gnutls_pubkey_import_pkcs11_url(gnutls_pubkey_t key, const char *url) +{ + gnutls_pkcs11_obj_t pcrt; + int ret; + + ret = gnutls_pkcs11_obj_init(&pcrt); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + ret = gnutls_pkcs11_obj_import_url(pcrt, url); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = gnutls_pubkey_import_pkcs11(key, pcrt, 0); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = 0; + cleanup: + + gnutls_pkcs11_obj_deinit(pcrt); + + return ret; +} + +/** + * gnutls_pubkey_import_rsa_raw: + * @key: Is a structure will hold the parameters + * @m: holds the modulus + * @e: holds the public exponent + * + * This function will replace the parameters in the given structure. + * The new parameters should be stored in the appropriate + * gnutls_datum. + * + * Returns: %GNUTLS_E_SUCCESS on success, or an negative error code. + **/ +int +gnutls_pubkey_import_rsa_raw(gnutls_pubkey_t key, + const gnutls_datum_t * m, + const gnutls_datum_t * e) { - gnutls_pkcs11_obj_t pcrt; - int ret; - - ret = gnutls_pkcs11_obj_init ( &pcrt); - if (ret < 0) { - gnutls_assert(); - return ret; - } - - ret = gnutls_pkcs11_obj_import_url (pcrt, url); - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } - - ret = gnutls_pubkey_import(key, &pcrt->raw, GNUTLS_X509_FMT_DER); - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } - - ret = 0; -cleanup: - - gnutls_pkcs11_obj_deinit(pcrt); - - return ret; + size_t siz = 0; + + if (key == NULL) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + siz = m->size; + if (_gnutls_mpi_scan_nz(&key->params[0], m->data, siz)) { + gnutls_assert(); + return GNUTLS_E_MPI_SCAN_FAILED; + } + + siz = e->size; + if (_gnutls_mpi_scan_nz(&key->params[1], e->data, siz)) { + gnutls_assert(); + _gnutls_mpi_release(&key->params[0]); + return GNUTLS_E_MPI_SCAN_FAILED; + } + + key->params_size = RSA_PUBLIC_PARAMS; + key->pk_algorithm = GNUTLS_PK_RSA; + + return 0; } +/** + * gnutls_pubkey_import_dsa_raw: + * @key: The structure to store the parsed key + * @p: holds the p + * @q: holds the q + * @g: holds the g + * @y: holds the y + * + * This function will convert the given DSA raw parameters to the + * native #gnutls_pubkey_t format. The output will be stored + * in @key. + * + * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a + * negative error value. + **/ +int +gnutls_pubkey_import_dsa_raw(gnutls_pubkey_t key, + const gnutls_datum_t * p, + const gnutls_datum_t * q, + const gnutls_datum_t * g, + const gnutls_datum_t * y) +{ + size_t siz = 0; + + if (key == NULL) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + siz = p->size; + if (_gnutls_mpi_scan_nz(&key->params[0], p->data, siz)) { + gnutls_assert(); + return GNUTLS_E_MPI_SCAN_FAILED; + } + + siz = q->size; + if (_gnutls_mpi_scan_nz(&key->params[1], q->data, siz)) { + gnutls_assert(); + _gnutls_mpi_release(&key->params[0]); + return GNUTLS_E_MPI_SCAN_FAILED; + } + + siz = g->size; + if (_gnutls_mpi_scan_nz(&key->params[2], g->data, siz)) { + gnutls_assert(); + _gnutls_mpi_release(&key->params[1]); + _gnutls_mpi_release(&key->params[0]); + return GNUTLS_E_MPI_SCAN_FAILED; + } + + siz = y->size; + if (_gnutls_mpi_scan_nz(&key->params[3], y->data, siz)) { + gnutls_assert(); + _gnutls_mpi_release(&key->params[2]); + _gnutls_mpi_release(&key->params[1]); + _gnutls_mpi_release(&key->params[0]); + return GNUTLS_E_MPI_SCAN_FAILED; + } + + key->params_size = DSA_PUBLIC_PARAMS; + key->pk_algorithm = GNUTLS_PK_DSA; + + return 0; + +} diff --git a/lib/includes/gnutls/abstract.h b/lib/includes/gnutls/abstract.h index 8305f9cddd..a02e9c475f 100644 --- a/lib/includes/gnutls/abstract.h +++ b/lib/includes/gnutls/abstract.h @@ -17,6 +17,7 @@ void gnutls_pubkey_deinit (gnutls_pubkey_t key); int gnutls_pubkey_get_pk_algorithm (gnutls_pubkey_t key, unsigned int* bits); int gnutls_pubkey_import_x509(gnutls_pubkey_t pkey, gnutls_x509_crt_t crt, unsigned int flags); +int gnutls_pubkey_import_pkcs11(gnutls_pubkey_t pkey, gnutls_pkcs11_obj_t crt, unsigned int flags); int gnutls_pubkey_import_openpgp(gnutls_pubkey_t pkey, gnutls_openpgp_crt_t crt, gnutls_openpgp_keyid_t keyid, @@ -45,7 +46,14 @@ int gnutls_pubkey_import (gnutls_pubkey_t key, int gnutls_pubkey_import_pkcs11_url( gnutls_pubkey_t key, const char* url); - +int gnutls_pubkey_import_dsa_raw (gnutls_pubkey_t key, + const gnutls_datum_t * p, + const gnutls_datum_t * q, + const gnutls_datum_t * g, + const gnutls_datum_t * y); +int gnutls_pubkey_import_rsa_raw (gnutls_pubkey_t pubkey, + const gnutls_datum_t * m, + const gnutls_datum_t * e); int gnutls_x509_crt_set_pubkey (gnutls_x509_crt_t crt, gnutls_pubkey_t key); diff --git a/lib/includes/gnutls/pkcs11.h b/lib/includes/gnutls/pkcs11.h index b5d1d6ef73..cc2f861cd1 100644 --- a/lib/includes/gnutls/pkcs11.h +++ b/lib/includes/gnutls/pkcs11.h @@ -138,6 +138,9 @@ int gnutls_pkcs11_obj_import_url (gnutls_pkcs11_obj_t, const char * url); int gnutls_pkcs11_obj_export_url (gnutls_pkcs11_obj_t, char** url); void gnutls_pkcs11_obj_deinit ( gnutls_pkcs11_obj_t); +int gnutls_pkcs11_obj_export(gnutls_pkcs11_obj_t obj, + void *output_data, size_t * output_data_size); + /** * @brief Release array of certificate references. * @param certificates Array to free. diff --git a/lib/libgnutls.map b/lib/libgnutls.map index 503cf2f430..de2533cbac 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -632,6 +632,8 @@ GNUTLS_2_11 gnutls_pkcs11_privkey_sign_data; gnutls_pkcs11_privkey_sign_hash; gnutls_pkcs11_privkey_decrypt_data; + gnutls_pkcs11_obj_export; + gnutls_pkcs11_type_get_name; gnutls_privkey_init; gnutls_privkey_deinit; @@ -657,9 +659,11 @@ GNUTLS_2_11 gnutls_pubkey_export; gnutls_pubkey_get_key_id; gnutls_pubkey_get_key_usage; - gnutls_pkcs11_type_get_name; - + gnutls_pubkey_import_pkcs11; + gnutls_pubkey_import_dsa_raw; + gnutls_pubkey_import_rsa_raw; gnutls_pubkey_import_pkcs11_url; + gnutls_pkcs11_obj_export; gnutls_pubkey_import; gnutls_x509_crt_set_pubkey; gnutls_x509_crq_set_pubkey; diff --git a/lib/pkcs11.c b/lib/pkcs11.c index 9eaeab6e7d..5121e9178e 100644 --- a/lib/pkcs11.c +++ b/lib/pkcs11.c @@ -447,6 +447,16 @@ size_t l; } } + if ((p1=strstr(url, "objecttype="))!= NULL) { + p1+=sizeof("objecttype=")-1; + l=sizeof (info->model); + + ret = unescape_string (info->type, + p1, &l, ';'); + if (ret < 0) { + goto cleanup; + } + } if (((p1=strstr(url, ";id="))!= NULL) || ((p1=strstr(url, ":id="))!= NULL)) { p1+=sizeof(";id=")-1; @@ -633,9 +643,52 @@ int gnutls_pkcs11_obj_init(gnutls_pkcs11_obj_t * crt) **/ void gnutls_pkcs11_obj_deinit(gnutls_pkcs11_obj_t crt) { + _gnutls_free_datum(&crt->raw); free(crt); } +/** + * gnutls_pkcs11_obj_export: + * @key: Holds the object + * @output_data: will contain a certificate PEM or DER encoded + * @output_data_size: holds the size of output_data (and will be + * replaced by the actual size of parameters) + * + * This function will export the pkcs11 object data. It is normal + * for PKCS #11 data to be inaccesible and in that case %GNUTLS_E_INVALID_REQUEST + * will be returned. + * + * If the buffer provided is not long enough to hold the output, then + * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will + * be returned. + * + * If the structure is PEM encoded, it will have a header + * of "BEGIN CERTIFICATE". + * + * Return value: In case of failure a negative value will be + * returned, and 0 on success. + **/ +int +gnutls_pkcs11_obj_export(gnutls_pkcs11_obj_t obj, + void *output_data, + size_t * output_data_size) +{ + if (obj == NULL || obj->raw.data == NULL) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + if (output_data==NULL || *output_data_size < obj->raw.size) { + *output_data_size = obj->raw.size; + gnutls_assert(); + return GNUTLS_E_SHORT_MEMORY_BUFFER; + } + *output_data_size = obj->raw.size; + + memcpy(output_data, obj->raw.data, obj->raw.size); + return 0; +} + static void terminate_string(unsigned char *str, size_t len) { unsigned char *ptr = str + len - 1; @@ -740,7 +793,7 @@ static int pkcs11_obj_import(unsigned int class, gnutls_pkcs11_obj_t crt, const { char *s; int ret; - + switch(class) { case CKO_CERTIFICATE: crt->type = GNUTLS_PKCS11_OBJ_X509_CRT; @@ -802,16 +855,176 @@ static int pkcs11_obj_import(unsigned int class, gnutls_pkcs11_obj_t crt, const return 0; } +static int pkcs11_obj_import_pubkey(pakchois_session_t *pks, ck_object_handle_t obj, + gnutls_pkcs11_obj_t crt, const gnutls_datum_t * id, + const gnutls_datum_t* label, struct ck_token_info* tinfo) +{ + + struct ck_attribute a[4]; + ck_key_type_t key_type; + opaque tmp1[2048]; + opaque tmp2[2048]; + int ret; + unsigned int tval; + + a[0].type = CKA_KEY_TYPE; + a[0].value = &key_type; + a[0].value_len = sizeof(key_type); + + if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) { + switch(key_type) { + case CKK_RSA: + a[0].type = CKA_MODULUS; + a[0].value = tmp1; + a[0].value_len = sizeof(tmp1); + a[1].type = CKA_PUBLIC_EXPONENT; + a[1].value = tmp2; + a[1].value_len = sizeof(tmp2); + + if (pakchois_get_attribute_value(pks, obj, a, 2) == CKR_OK) { + + ret = _gnutls_set_datum(&crt->pubkey[0], a[0].value, a[0].value_len); + + if (ret >= 0) + ret = _gnutls_set_datum(&crt->pubkey[1], a[1].value, a[1].value_len); + + if (ret < 0) { + gnutls_assert(); + _gnutls_free_datum(&crt->pubkey[1]); + _gnutls_free_datum(&crt->pubkey[0]); + return GNUTLS_E_MEMORY_ERROR; + } + } else { + gnutls_assert(); + return GNUTLS_E_PKCS11_ERROR; + } + crt->pk_algorithm = GNUTLS_PK_RSA; + break; + case CKK_DSA: + a[0].type = CKA_PRIME; + a[0].value = tmp1; + a[0].value_len = sizeof(tmp1); + a[1].type = CKA_SUBPRIME; + a[1].value = tmp2; + a[1].value_len = sizeof(tmp2); + + if (pakchois_get_attribute_value(pks, obj, a, 2) == CKR_OK) { + ret = _gnutls_set_datum(&crt->pubkey[0], a[0].value, a[0].value_len); + + if (ret >= 0) + ret = _gnutls_set_datum(&crt->pubkey[1], a[1].value, a[1].value_len); + + if (ret < 0) { + gnutls_assert(); + _gnutls_free_datum(&crt->pubkey[1]); + _gnutls_free_datum(&crt->pubkey[0]); + return GNUTLS_E_MEMORY_ERROR; + } + } else { + gnutls_assert(); + return GNUTLS_E_PKCS11_ERROR; + } + + a[0].type = CKA_BASE; + a[0].value = tmp1; + a[0].value_len = sizeof(tmp1); + a[1].type = CKA_VALUE; + a[1].value = tmp2; + a[1].value_len = sizeof(tmp2); + + if (pakchois_get_attribute_value(pks, obj, a, 2) == CKR_OK) { + ret = _gnutls_set_datum(&crt->pubkey[2], a[0].value, a[0].value_len); + + if (ret >= 0) + ret = _gnutls_set_datum(&crt->pubkey[3], a[1].value, a[1].value_len); + + if (ret < 0) { + gnutls_assert(); + _gnutls_free_datum(&crt->pubkey[0]); + _gnutls_free_datum(&crt->pubkey[1]); + _gnutls_free_datum(&crt->pubkey[2]); + _gnutls_free_datum(&crt->pubkey[3]); + return GNUTLS_E_MEMORY_ERROR; + } + } else { + gnutls_assert(); + return GNUTLS_E_PKCS11_ERROR; + } + crt->pk_algorithm = GNUTLS_PK_RSA; + break; + default: + gnutls_assert(); + return GNUTLS_E_UNIMPLEMENTED_FEATURE; + } + } + + /* read key usage flags */ + a[0].type = CKA_ENCRYPT; + a[0].value = &tval; + a[0].value_len = sizeof(tval); + + if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) { + if (tval != 0) { + crt->key_usage |= GNUTLS_KEY_DATA_ENCIPHERMENT; + } + } + + a[0].type = CKA_VERIFY; + a[0].value = &tval; + a[0].value_len = sizeof(tval); + + if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) { + if (tval != 0) { + crt->key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE| \ + GNUTLS_KEY_KEY_CERT_SIGN|GNUTLS_KEY_CRL_SIGN|GNUTLS_KEY_NON_REPUDIATION; + } + } + + a[0].type = CKA_VERIFY_RECOVER; + a[0].value = &tval; + a[0].value_len = sizeof(tval); + + if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) { + if (tval != 0) { + crt->key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE| \ + GNUTLS_KEY_KEY_CERT_SIGN|GNUTLS_KEY_CRL_SIGN|GNUTLS_KEY_NON_REPUDIATION; + } + } + + a[0].type = CKA_DERIVE; + a[0].value = &tval; + a[0].value_len = sizeof(tval); + + if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) { + if (tval != 0) { + crt->key_usage |= GNUTLS_KEY_KEY_AGREEMENT; + } + } + + a[0].type = CKA_WRAP; + a[0].value = &tval; + a[0].value_len = sizeof(tval); + + if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) { + if (tval != 0) { + crt->key_usage |= GNUTLS_KEY_KEY_ENCIPHERMENT; + } + } + + return pkcs11_obj_import(CKO_PUBLIC_KEY, crt, NULL, id, label, tinfo); +} + + -static int find_cert_url(pakchois_session_t *pks, struct token_info *info, void* input) +static int find_obj_url(pakchois_session_t *pks, struct token_info *info, void* input) { struct url_find_data_st* find_data = input; struct ck_attribute a[4]; ck_object_class_t class; - ck_certificate_type_t type; + ck_certificate_type_t type = -1; ck_rv_t rv; ck_object_handle_t obj; - unsigned long count; + unsigned long count, a_vals; int found = 0, ret; opaque* cert_data = NULL; char label_tmp[PKCS11_LABEL_SIZE]; @@ -843,10 +1056,20 @@ static int find_cert_url(pakchois_session_t *pks, struct token_info *info, void* return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } + class = CKO_CERTIFICATE; /* default */ + if (find_data->crt->info.type[0] != 0) { - if (strcmp(find_data->crt->info.type, "cert") != 0) { - gnutls_assert(); - return GNUTLS_E_UNIMPLEMENTED_FEATURE; + if (strcmp(find_data->crt->info.type, "cert") == 0) { + class = CKO_CERTIFICATE; + type = CKC_X_509; + } else if (strcmp(find_data->crt->info.type, "public") == 0) { + class = CKO_PUBLIC_KEY; + } else if (strcmp(find_data->crt->info.type, "private") == 0) { + class = CKO_PRIVATE_KEY; + } else if (strcmp(find_data->crt->info.type, "secretkey") == 0) { + class = CKO_SECRET_KEY; + } else if (strcmp(find_data->crt->info.type, "data") == 0) { + class = CKO_DATA; } } @@ -858,22 +1081,26 @@ static int find_cert_url(pakchois_session_t *pks, struct token_info *info, void* return GNUTLS_E_MEMORY_ERROR; } - /* Find objects with cert class and X.509 cert type. */ - class = CKO_CERTIFICATE; - type = CKC_X_509; + /* Find objects with given class and type */ a[0].type = CKA_CLASS; a[0].value = &class; a[0].value_len = sizeof class; - a[1].type = CKA_CERTIFICATE_TYPE; - a[1].value = &type; - a[1].value_len = sizeof type; - a[2].type = CKA_ID; - a[2].value = find_data->crt->info.certid_raw; - a[2].value_len = find_data->crt->info.certid_raw_size; - - rv = pakchois_find_objects_init(pks, a, 3); + a[1].type = CKA_ID; + a[1].value = find_data->crt->info.certid_raw; + a[1].value_len = find_data->crt->info.certid_raw_size; + + a_vals = 2; + + if (type != -1) { + a[2].type = CKA_CERTIFICATE_TYPE; + a[2].value = &type; + a[2].value_len = sizeof type; + a_vals++; + } + + rv = pakchois_find_objects_init(pks, a, a_vals); if (rv != CKR_OK) { gnutls_assert(); _gnutls_debug_log("pk11: FindObjectsInit failed.\n"); @@ -896,7 +1123,11 @@ static int find_cert_url(pakchois_session_t *pks, struct token_info *info, void* gnutls_datum_t data = { a[0].value, a[0].value_len }; gnutls_datum_t label = { a[1].value, a[1].value_len }; - ret = pkcs11_obj_import(CKO_CERTIFICATE, find_data->crt, &data, &id, &label, &info->tinfo); + if (class == CKO_PUBLIC_KEY) { + ret = pkcs11_obj_import_pubkey(pks, obj, find_data->crt, &id, &label, &info->tinfo); + } else { + ret = pkcs11_obj_import(class, find_data->crt, &data, &id, &label, &info->tinfo); + } if (ret < 0) { gnutls_assert(); goto cleanup; @@ -951,7 +1182,7 @@ int gnutls_pkcs11_obj_import_url (gnutls_pkcs11_obj_t cert, const char * url) return ret; } - ret = _pkcs11_traverse_tokens(find_cert_url, &find_data, 0); + ret = _pkcs11_traverse_tokens(find_obj_url, &find_data, 0); if (ret < 0) { gnutls_assert(); return ret; @@ -1218,7 +1449,6 @@ static int find_privkeys(pakchois_session_t *pks, struct token_info* info, struc ck_object_handle_t obj; unsigned long count, current; char certid_tmp[PKCS11_ID_SIZE]; - int ret; class = CKO_PRIVATE_KEY; @@ -1490,7 +1720,11 @@ static int find_objs(pakchois_session_t *pks, struct token_info *info, void* inp goto fail; } - ret = pkcs11_obj_import(class, find_data->p_list[find_data->current], &value, &id, &label, &info->tinfo); + if (class == CKO_PUBLIC_KEY) { + ret = pkcs11_obj_import_pubkey(pks, obj, find_data->p_list[find_data->current], &id, &label, &info->tinfo); + } else { + ret = pkcs11_obj_import(class, find_data->p_list[find_data->current], &value, &id, &label, &info->tinfo); + } if (ret < 0) { gnutls_assert(); goto fail; @@ -1706,9 +1940,6 @@ static int find_flags(pakchois_session_t *pks, struct token_info *info, void* in **/ int gnutls_pkcs11_token_get_flags(const char* url, unsigned int *flags) { - const char* str; - size_t len; - struct flags_find_data_st find_data; int ret; diff --git a/lib/pkcs11_int.h b/lib/pkcs11_int.h index 86cbba1ce4..6e1b3acb0b 100644 --- a/lib/pkcs11_int.h +++ b/lib/pkcs11_int.h @@ -33,6 +33,11 @@ struct gnutls_pkcs11_obj_st { gnutls_datum_t raw; gnutls_pkcs11_obj_type_t type; struct pkcs11_url_info info; + + /* only when pubkey */ + gnutls_datum_t pubkey[MAX_PUBLIC_PARAMS_SIZE]; + gnutls_pk_algorithm pk_algorithm; + unsigned int key_usage; }; /* thus function is called for every token in the traverse_tokens diff --git a/lib/x509/x509.c b/lib/x509/x509.c index 9c22ada3f0..c2914f5ade 100644 --- a/lib/x509/x509.c +++ b/lib/x509/x509.c @@ -2188,11 +2188,11 @@ int _gnutls_get_key_id (gnutls_pk_algorithm_t pk, bigint_t* params, int params_size, unsigned char *output_data, size_t * output_data_size) { - int i, result = 0; + int result = 0; gnutls_datum_t der = { NULL, 0 }; digest_hd_st hd; - if (output_data==NULL || *output_data_size < 0) + if (output_data==NULL || *output_data_size < 20) { gnutls_assert(); *output_data_size = 20; @@ -2248,8 +2248,6 @@ rsadsa_get_key_id (gnutls_x509_crt_t crt, int pk, bigint_t params[MAX_PUBLIC_PARAMS_SIZE]; int params_size = MAX_PUBLIC_PARAMS_SIZE; int i, result = 0; - gnutls_datum_t der = { NULL, 0 }; - digest_hd_st hd; result = _gnutls_x509_crt_get_mpis (crt, params, ¶ms_size); if (result < 0) diff --git a/src/pkcs11.c b/src/pkcs11.c index a9f1605fe1..500aaa3e8f 100644 --- a/src/pkcs11.c +++ b/src/pkcs11.c @@ -3,6 +3,7 @@ #include <gnutls/gnutls.h> #include <gnutls/extra.h> #include <gnutls/pkcs11.h> +#include <gnutls/abstract.h> #include <stdio.h> #include <stdlib.h> #include "certtool-common.h" @@ -174,6 +175,7 @@ void pkcs11_export(FILE* outfile, const char* url) { gnutls_pkcs11_obj_t crt; gnutls_x509_crt_t xcrt; +gnutls_pubkey_t pubkey; int ret; size_t size; @@ -194,34 +196,84 @@ size_t size; exit(1); } - ret = gnutls_x509_crt_init(&xcrt); - if (ret < 0) { - fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror(ret)); - exit(1); - } - - ret = gnutls_x509_crt_import_pkcs11(xcrt, crt); - if (ret < 0) { - fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror(ret)); - exit(1); - } - - size = buffer_size; - ret = gnutls_x509_crt_export (xcrt, GNUTLS_X509_FMT_PEM, buffer, &size); - if (ret < 0) { - fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror(ret)); - exit(1); + switch(gnutls_pkcs11_obj_get_type(crt)) { + case GNUTLS_PKCS11_OBJ_X509_CRT: + ret = gnutls_x509_crt_init(&xcrt); + if (ret < 0) { + fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror(ret)); + exit(1); + } + + ret = gnutls_x509_crt_import_pkcs11(xcrt, crt); + if (ret < 0) { + fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror(ret)); + exit(1); + } + + size = buffer_size; + ret = gnutls_x509_crt_export (xcrt, GNUTLS_X509_FMT_PEM, buffer, &size); + if (ret < 0) { + fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror(ret)); + exit(1); + } + fwrite (buffer, 1, size, outfile); + + gnutls_x509_crt_deinit(xcrt); + break; + case GNUTLS_PKCS11_OBJ_PUBKEY: + ret = gnutls_pubkey_init(&pubkey); + if (ret < 0) { + fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror(ret)); + exit(1); + } + + ret = gnutls_pubkey_import_pkcs11(pubkey, crt, 0); + if (ret < 0) { + fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror(ret)); + exit(1); + } + + size = buffer_size; + ret = gnutls_pubkey_export (pubkey, GNUTLS_X509_FMT_PEM, buffer, &size); + if (ret < 0) { + fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror(ret)); + exit(1); + } + fwrite (buffer, 1, size, outfile); + + gnutls_pubkey_deinit(pubkey); + break; + default: { + gnutls_datum data, enc; + + size = buffer_size; + ret = gnutls_pkcs11_obj_export (crt, buffer, &size); + if (ret < 0) { + break; + } + + data.data = buffer; + data.size = size; + + ret = gnutls_pem_base64_encode_alloc("DATA", &data, &enc); + if (ret < 0) { + fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror(ret)); + exit(1); + } + + fwrite (enc.data, 1, enc.size, outfile); + + gnutls_free(enc.data); + break; + } } - fwrite (buffer, 1, size, outfile); fputs("\n\n", outfile); - gnutls_x509_crt_deinit(xcrt); + gnutls_pkcs11_obj_deinit(crt); return; - - } void pkcs11_token_list(FILE* outfile) |