summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2010-05-22 20:15:22 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2010-05-23 11:13:50 +0200
commit16aa3673a3d7d5070fbf43d1aa46059bc9a42266 (patch)
treed81d0299413b9760419ff767051d7b951561d65c
parente6369864af00a519f4a38ced7cbb6878e3c248c4 (diff)
downloadgnutls-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--NEWS6
-rw-r--r--configure.ac2
-rw-r--r--lib/gnutls_pubkey.c310
-rw-r--r--lib/includes/gnutls/abstract.h10
-rw-r--r--lib/includes/gnutls/pkcs11.h3
-rw-r--r--lib/libgnutls.map8
-rw-r--r--lib/pkcs11.c281
-rw-r--r--lib/pkcs11_int.h5
-rw-r--r--lib/x509/x509.c6
-rw-r--r--src/pkcs11.c94
10 files changed, 591 insertions, 134 deletions
diff --git a/NEWS b/NEWS
index 3069970fec..e1e66f515e 100644
--- a/NEWS
+++ b/NEWS
@@ -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, &params_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)