summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2010-05-23 14:05:32 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2010-05-23 17:26:45 +0200
commitcf57c9558c93011ede4d337bc2e36858eb4f4118 (patch)
treeffbeb93008aa3f75a6754d91dfbb860aafa4ff04
parentad6cea0c5177e2dd4913380c7c1c128348a09887 (diff)
downloadgnutls-cf57c9558c93011ede4d337bc2e36858eb4f4118.tar.gz
Added support to copy certificates and private keys to tokens.
New functions: gnutls_pkcs11_copy_x509_crt() gnutls_pkcs11_copy_x509_privkey() gnutls_pkcs11_delete_url() Certtool was updated to allow copying certificates and private keys to tokens. Deleting an object has issues (segfault) but it seems to be related with libopensc and its pkcs11 API.
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/gcrypt/mpi.c1
-rw-r--r--lib/gcrypt/pk.c37
-rw-r--r--lib/includes/gnutls/crypto.h8
-rw-r--r--lib/includes/gnutls/pkcs11.h11
-rw-r--r--lib/includes/gnutls/x509.h14
-rw-r--r--lib/libgnutls.map3
-rw-r--r--lib/nettle/pk.c16
-rw-r--r--lib/pkcs11.c328
-rw-r--r--lib/pkcs11_int.h9
-rw-r--r--lib/pkcs11_privkey.c37
-rw-r--r--lib/pkcs11_write.c508
-rw-r--r--lib/x509/privkey.c246
-rw-r--r--lib/x509/x509_int.h8
-rw-r--r--src/certtool-common.h14
-rw-r--r--src/certtool-gaa.c203
-rw-r--r--src/certtool-gaa.h6
-rw-r--r--src/certtool.c12
-rw-r--r--src/certtool.gaa11
-rw-r--r--src/crypt-gaa.c64
-rw-r--r--src/pkcs11.c62
21 files changed, 1269 insertions, 331 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 475b25c5f7..0ccb5e06ad 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -82,7 +82,7 @@ COBJECTS = gnutls_record.c gnutls_compress.c debug.c gnutls_cipher.c \
auth_dh_common.c gnutls_helper.c gnutls_supplemental.c \
crypto.c random.c ext_signature.c cryptodev.c \
crypto-api.c ext_safe_renegotiation.c gnutls_privkey.c \
- pkcs11.c pkcs11_privkey.c gnutls_pubkey.c
+ pkcs11.c pkcs11_privkey.c gnutls_pubkey.c pkcs11_write.c
if ENABLE_NETTLE
SUBDIRS += nettle
diff --git a/lib/gcrypt/mpi.c b/lib/gcrypt/mpi.c
index d45f023514..6adbb1bc9c 100644
--- a/lib/gcrypt/mpi.c
+++ b/lib/gcrypt/mpi.c
@@ -78,6 +78,7 @@ wrap_gcry_mpi_print (const bigint_t a, void *buffer, size_t * nbytes,
ret = gcry_mpi_print (format, buffer, *nbytes, nbytes, a);
if (!ret) {
if (buffer==NULL || init_bytes < *nbytes) {
+ (*nbytes)++;
return GNUTLS_E_SHORT_MEMORY_BUFFER;
}
return 0;
diff --git a/lib/gcrypt/pk.c b/lib/gcrypt/pk.c
index 5e0b159be6..84fedfe4aa 100644
--- a/lib/gcrypt/pk.c
+++ b/lib/gcrypt/pk.c
@@ -625,8 +625,9 @@ static int
_rsa_generate_params (bigint_t * resarr, int *resarr_len, int bits)
{
- int ret;
+ int ret, i;
gcry_sexp_t parms, key, list;
+ bigint_t tmp;
ret = gcry_sexp_build (&parms, NULL, "(genkey(rsa(nbits %d)))", bits);
if (ret != 0)
@@ -722,9 +723,43 @@ _rsa_generate_params (bigint_t * resarr, int *resarr_len, int bits)
_gnutls_mpi_log ("q: ", resarr[4]);
_gnutls_mpi_log ("u: ", resarr[5]);
+ /* generate e1 and e2 */
+
*resarr_len = 6;
+
+ tmp = _gnutls_mpi_alloc_like(resarr[0]);
+ if (tmp == NULL)
+ {
+ gnutls_assert ();
+ ret = GNUTLS_E_MEMORY_ERROR;
+ goto cleanup;
+ }
+
+ /* [6] = d % p-1, [7] = d % q-1 */
+ _gnutls_mpi_sub_ui(tmp, resarr[3], 1);
+ resarr[6] = _gnutls_mpi_mod(resarr[2]/*d*/, tmp);
+
+ _gnutls_mpi_sub_ui(tmp, resarr[4], 1);
+ resarr[7] = _gnutls_mpi_mod(resarr[2]/*d*/, tmp);
+
+ _gnutls_mpi_release(&tmp);
+
+ if (resarr[6] == NULL || resarr[7] == NULL)
+ {
+ gnutls_assert();
+ ret= GNUTLS_E_MEMORY_ERROR;
+ goto cleanup;
+ }
+
+ (*resarr_len)+=2;
return 0;
+
+cleanup:
+ for (i=0;i<*resarr_len;i++)
+ _gnutls_mpi_release(&resarr[i]);
+
+ return ret;
}
diff --git a/lib/includes/gnutls/crypto.h b/lib/includes/gnutls/crypto.h
index e2cb8f821e..64cf7a6a19 100644
--- a/lib/includes/gnutls/crypto.h
+++ b/lib/includes/gnutls/crypto.h
@@ -214,7 +214,7 @@ typedef struct gnutls_crypto_bigint
gnutls_bigint_format_t format);
} gnutls_crypto_bigint_st;
-#define GNUTLS_MAX_PK_PARAMS 6
+#define GNUTLS_MAX_PK_PARAMS 16
typedef struct
{
@@ -234,9 +234,11 @@ void gnutls_pk_params_init (gnutls_pk_params_st * p);
* [3] is prime1 (p) (private key only)
* [4] is prime2 (q) (private key only)
* [5] is coefficient (u == inverse of p mod q) (private key only)
+ * [6] e1 == d mod (p-1)
+ * [7] e2 == d mod (q-1)
*
- * note that other packages use inverse of q mod p,
- * so we need to perform conversions using fixup_params().
+ * note that for libgcrypt that does not use the inverse of q mod p,
+ * we need to perform conversions using fixup_params().
*
* DSA:
* [0] is p
diff --git a/lib/includes/gnutls/pkcs11.h b/lib/includes/gnutls/pkcs11.h
index cc2f861cd1..a0a5dfc294 100644
--- a/lib/includes/gnutls/pkcs11.h
+++ b/lib/includes/gnutls/pkcs11.h
@@ -141,6 +141,14 @@ 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);
+#define GNUTLS_PKCS11_OBJ_FLAG_TRUSTED 1 /* object marked as trusted */
+
+int gnutls_pkcs11_copy_x509_crt(const char* token_url, gnutls_x509_crt_t crt,
+ const char* label, unsigned int flags /* GNUTLS_PKCS11_OBJ_FLAG_* */);
+int gnutls_pkcs11_copy_x509_privkey(const char* token_url,
+ gnutls_x509_privkey_t crt, const char* label, unsigned int key_usage /*GNUTLS_KEY_* */);
+int gnutls_pkcs11_delete_url(const char* object_url);
+
/**
* @brief Release array of certificate references.
* @param certificates Array to free.
@@ -214,8 +222,7 @@ int gnutls_pkcs11_privkey_get_info(gnutls_pkcs11_privkey_t crt, gnutls_pkcs11_ob
int gnutls_pkcs11_privkey_import_url (gnutls_pkcs11_privkey_t key,
const char* url);
-int
-gnutls_pkcs11_privkey_sign_data(gnutls_pkcs11_privkey_t signer,
+int gnutls_pkcs11_privkey_sign_data(gnutls_pkcs11_privkey_t signer,
gnutls_digest_algorithm_t hash,
unsigned int flags,
const gnutls_datum_t * data,
diff --git a/lib/includes/gnutls/x509.h b/lib/includes/gnutls/x509.h
index 54ba9e2793..308e7057be 100644
--- a/lib/includes/gnutls/x509.h
+++ b/lib/includes/gnutls/x509.h
@@ -633,6 +633,15 @@ extern "C"
const gnutls_datum_t * p,
const gnutls_datum_t * q,
const gnutls_datum_t * u);
+ int gnutls_x509_privkey_import_rsa_raw2 (gnutls_x509_privkey_t key,
+ const gnutls_datum_t * m,
+ const gnutls_datum_t * e,
+ const gnutls_datum_t * d,
+ const gnutls_datum_t * p,
+ const gnutls_datum_t * q,
+ const gnutls_datum_t * u,
+ const gnutls_datum_t *exp1,
+ const gnutls_datum_t *exp2);
int gnutls_x509_privkey_fix (gnutls_x509_privkey_t key);
int gnutls_x509_privkey_export_dsa_raw (gnutls_x509_privkey_t key,
@@ -668,6 +677,11 @@ extern "C"
unsigned int flags,
void *output_data,
size_t * output_data_size);
+ int gnutls_x509_privkey_export_rsa_raw2 (gnutls_x509_privkey_t key,
+ gnutls_datum_t * m, gnutls_datum_t * e,
+ gnutls_datum_t * d, gnutls_datum_t * p,
+ gnutls_datum_t * q, gnutls_datum_t * u,
+ gnutls_datum_t* e1, gnutls_datum_t* e2);
int gnutls_x509_privkey_export_rsa_raw (gnutls_x509_privkey_t key,
gnutls_datum_t * m,
gnutls_datum_t * e,
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index 256d01664c..950ac59590 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -669,6 +669,9 @@ GNUTLS_2_11
gnutls_pubkey_import;
gnutls_x509_crt_set_pubkey;
gnutls_x509_crq_set_pubkey;
+ gnutls_pkcs11_copy_x509_crt;
+ gnutls_pkcs11_copy_x509_privkey;
+ gnutls_pkcs11_delete_url;
} GNUTLS_2_10;
GNUTLS_PRIVATE {
diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c
index 081c08c34c..e028d9b49e 100644
--- a/lib/nettle/pk.c
+++ b/lib/nettle/pk.c
@@ -72,17 +72,8 @@ mpz_t q_1;
memcpy(&priv->q, pk_params->params[4], sizeof(mpz_t));
memcpy(&priv->c, pk_params->params[5], sizeof(mpz_t));
- /* FIXME: possibly move it to fixup to avoid those calculations here */
-
- /* b = d % q-1 */
- mpz_init(q_1);
- mpz_sub_ui(q_1, priv->q, 1);
-
- mpz_fdiv_r(priv->b, priv->d, q_1);
-
- /* a = d % p-1 */
- mpz_sub_ui(q_1, priv->p, 1);
- mpz_fdiv_r(priv->a, priv->d, q_1);
+ memcpy(&priv->a, pk_params->params[6], sizeof(mpz_t));
+ memcpy(&priv->b, pk_params->params[7], sizeof(mpz_t));
}
static int
@@ -425,7 +416,8 @@ int ret, i;
_gnutls_mpi_set(params->params[3], priv.p);
_gnutls_mpi_set(params->params[4], priv.q);
_gnutls_mpi_set(params->params[5], priv.c);
-
+ _gnutls_mpi_set(params->params[6], priv.a);
+ _gnutls_mpi_set(params->params[7], priv.b);
rsa_private_key_clear(&priv);
rsa_public_key_clear(&pub);
diff --git a/lib/pkcs11.c b/lib/pkcs11.c
index 5121e9178e..640984ac40 100644
--- a/lib/pkcs11.c
+++ b/lib/pkcs11.c
@@ -26,7 +26,6 @@
#include <gnutls_int.h>
#include <gnutls/pkcs11.h>
#include <stdio.h>
-#include <stdbool.h>
#include <string.h>
#include <gnutls_errors.h>
#include <gnutls_datum.h>
@@ -43,15 +42,15 @@ struct gnutls_pkcs11_provider_s {
ck_slot_id_t *slots;
};
-struct url_find_data_st {
- gnutls_pkcs11_obj_t crt;
-};
-
struct flags_find_data_st {
struct pkcs11_url_info info;
unsigned int slot_flags;
};
+struct url_find_data_st {
+ gnutls_pkcs11_obj_t crt;
+};
+
struct crt_find_data_st {
gnutls_pkcs11_obj_t *p_list;
unsigned int* n_list;
@@ -704,8 +703,66 @@ static void terminate_string(unsigned char *str, size_t len)
ptr[1] = '\0';
}
+int pkcs11_open_session (pakchois_session_t** _pks, struct pkcs11_url_info *info, unsigned int flags)
+{
+ ck_rv_t rv;
+ int x, z, ret;
+ pakchois_session_t *pks = NULL;
+
+ for (x=0;x<active_providers;x++) {
+ for (z=0;z<providers[x].nslots;z++) {
+ struct token_info tinfo;
+
+ rv = pakchois_open_session(providers[x].module, providers[x].slots[z],
+ ((flags&SESSION_WRITE)?CKF_RW_SESSION:0)|CKF_SERIAL_SESSION, NULL, NULL, &pks);
+ if (rv != CKR_OK) {
+ continue;
+ }
+
+ if (pakchois_get_token_info(providers[x].module, providers[x].slots[z], &tinfo.tinfo) != CKR_OK) {
+ goto next;
+ }
+ tinfo.sid = providers[x].slots[z];
+ tinfo.prov = &providers[x];
+
+ if (pakchois_get_slot_info(providers[x].module, providers[x].slots[z], &tinfo.sinfo) != CKR_OK) {
+ goto next;
+ }
+
+ /* XXX make wrapper for token_info? */
+ terminate_string(tinfo.tinfo.manufacturer_id, sizeof tinfo.tinfo.manufacturer_id);
+ terminate_string(tinfo.tinfo.label, sizeof tinfo.tinfo.label);
+ terminate_string(tinfo.tinfo.model, sizeof tinfo.tinfo.model);
+ terminate_string(tinfo.tinfo.serial_number, sizeof tinfo.tinfo.serial_number);
+
+ if (pkcs11_token_matches_info( info, &tinfo.tinfo) < 0) {
+ goto next;
+ }
+
+ if (flags&SESSION_LOGIN) {
+ ret = pkcs11_login(pks, &tinfo);
+ if (ret < 0) {
+ gnutls_assert();
+ pakchois_close_session(pks);
+ return ret;
+ }
+ }
+
+ /* ok found */
+ *_pks = pks;
+ return 0;
+
+next:
+ pakchois_close_session(pks);
+ }
+ }
+
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+}
+
-int _pkcs11_traverse_tokens (find_func_t find_func, void* input, int leave_session)
+int _pkcs11_traverse_tokens (find_func_t find_func, void* input,
+ int leave_session, unsigned int flags)
{
ck_rv_t rv;
int found = 0, x, z, ret;
@@ -715,20 +772,22 @@ int _pkcs11_traverse_tokens (find_func_t find_func, void* input, int leave_sessi
for (z=0;z<providers[x].nslots;z++) {
struct token_info info;
+ ret = GNUTLS_E_PKCS11_ERROR;
+
rv = pakchois_open_session(providers[x].module, providers[x].slots[z],
- CKF_SERIAL_SESSION, NULL, NULL, &pks);
+ ((flags&SESSION_WRITE)?CKF_RW_SESSION:0)|CKF_SERIAL_SESSION, NULL, NULL, &pks);
if (rv != CKR_OK) {
continue;
}
if (pakchois_get_token_info(providers[x].module, providers[x].slots[z], &info.tinfo) != CKR_OK) {
- continue;
+ goto next;
}
info.sid = providers[x].slots[z];
info.prov = &providers[x];
if (pakchois_get_slot_info(providers[x].module, providers[x].slots[z], &info.sinfo) != CKR_OK) {
- continue;
+ goto next;
}
/* XXX make wrapper for token_info? */
@@ -739,6 +798,8 @@ int _pkcs11_traverse_tokens (find_func_t find_func, void* input, int leave_sessi
ret = find_func(pks, &info, input);
+ next:
+
if (ret == 0) {
found = 1;
goto finish;
@@ -1014,13 +1075,33 @@ static int pkcs11_obj_import_pubkey(pakchois_session_t *pks, ck_object_handle_t
return pkcs11_obj_import(CKO_PUBLIC_KEY, crt, NULL, id, label, tinfo);
}
+ck_object_class_t pkcs11_strtype_to_class(const char* type)
+{
+ ck_object_class_t class;
+
+ if (strcmp(type, "cert") == 0) {
+ class = CKO_CERTIFICATE;
+ } else if (strcmp(type, "public") == 0) {
+ class = CKO_PUBLIC_KEY;
+ } else if (strcmp(type, "private") == 0) {
+ class = CKO_PRIVATE_KEY;
+ } else if (strcmp(type, "secretkey") == 0) {
+ class = CKO_SECRET_KEY;
+ } else if (strcmp(type, "data") == 0) {
+ class = CKO_DATA;
+ } else {
+ class = -1;
+ }
+
+ return class;
+}
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_object_class_t class = -1;
ck_certificate_type_t type = -1;
ck_rv_t rv;
ck_object_handle_t obj;
@@ -1036,40 +1117,19 @@ static int find_obj_url(pakchois_session_t *pks, struct token_info *info, void*
/* do not bother reading the token if basic fields do not match
*/
- if (find_data->crt->info.manufacturer[0] != 0) {
- if (strcmp(find_data->crt->info.manufacturer, info->tinfo.manufacturer_id) != 0)
- return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
- }
-
- if (find_data->crt->info.token[0] != 0) {
- if (strcmp(find_data->crt->info.token, info->tinfo.label) != 0)
- return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
- }
-
- if (find_data->crt->info.model[0] != 0) {
- if (strcmp(find_data->crt->info.model, info->tinfo.model) != 0)
- return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
- }
-
- if (find_data->crt->info.serial[0] != 0) {
- if (strcmp(find_data->crt->info.serial, info->tinfo.serial_number) != 0)
- return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
- }
-
- class = CKO_CERTIFICATE; /* default */
+ if (pkcs11_token_matches_info( &find_data->crt->info, &info->tinfo) < 0) {
+ gnutls_assert();
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ }
if (find_data->crt->info.type[0] != 0) {
- if (strcmp(find_data->crt->info.type, "cert") == 0) {
- class = CKO_CERTIFICATE;
+ class = pkcs11_strtype_to_class(find_data->crt->info.type);
+ if (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;
+
+ if (class == -1) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
}
}
@@ -1083,20 +1143,23 @@ static int find_obj_url(pakchois_session_t *pks, struct token_info *info, void*
/* 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_ID;
- a[1].value = find_data->crt->info.certid_raw;
- a[1].value_len = find_data->crt->info.certid_raw_size;
+ a[0].type = CKA_ID;
+ a[0].value = find_data->crt->info.certid_raw;
+ a[0].value_len = find_data->crt->info.certid_raw_size;
- a_vals = 2;
+ a_vals = 1;
+
+ if (class != -1) {
+ a[a_vals].type = CKA_CLASS;
+ a[a_vals].value = &class;
+ a[a_vals].value_len = sizeof class;
+ a_vals++;
+ }
if (type != -1) {
- a[2].type = CKA_CERTIFICATE_TYPE;
- a[2].value = &type;
- a[2].value_len = sizeof type;
+ a[a_vals].type = CKA_CERTIFICATE_TYPE;
+ a[a_vals].value = &type;
+ a[a_vals].value_len = sizeof type;
a_vals++;
}
@@ -1182,7 +1245,7 @@ int gnutls_pkcs11_obj_import_url (gnutls_pkcs11_obj_t cert, const char * url)
return ret;
}
- ret = _pkcs11_traverse_tokens(find_obj_url, &find_data, 0);
+ ret = _pkcs11_traverse_tokens(find_obj_url, &find_data, 0, 0);
if (ret < 0) {
gnutls_assert();
return ret;
@@ -1242,7 +1305,7 @@ int gnutls_pkcs11_token_get_url (unsigned int seq, char** url)
memset(&tn, 0, sizeof(tn));
tn.seq = seq;
- ret = _pkcs11_traverse_tokens(find_token_num, &tn, 0);
+ ret = _pkcs11_traverse_tokens(find_token_num, &tn, 0, 0);
if (ret < 0) {
gnutls_assert();
return ret;
@@ -1528,9 +1591,9 @@ static int find_objs(pakchois_session_t *pks, struct token_info *info, void* inp
{
struct crt_find_data_st* find_data = input;
struct ck_attribute a[4];
- ck_object_class_t class;
- ck_certificate_type_t type;
- bool trusted;
+ ck_object_class_t class=-1;
+ ck_certificate_type_t type=-1;
+ unsigned int trusted;
ck_rv_t rv;
ck_object_handle_t obj;
unsigned long count;
@@ -1554,27 +1617,27 @@ static int find_objs(pakchois_session_t *pks, struct token_info *info, void* inp
/* do not bother reading the token if basic fields do not match
*/
- if (find_data->info.manufacturer[0] != 0) {
- if (strcmp(find_data->info.manufacturer, info->tinfo.manufacturer_id) != 0)
- return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
- }
-
- if (find_data->info.token[0] != 0) {
- if (strcmp(find_data->info.token, info->tinfo.label) != 0)
- return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
- }
+ if (pkcs11_token_matches_info( &find_data->info, &info->tinfo) < 0) {
+ gnutls_assert();
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ }
- if (find_data->info.model[0] != 0) {
- if (strcmp(find_data->info.model, info->tinfo.model) != 0)
- return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
- }
+ if (find_data->info.type[0] != 0) {
+ class = pkcs11_strtype_to_class(find_data->info.type);
+ if (class == CKO_CERTIFICATE)
+ type = CKC_X_509;
+ else
+ type = -1;
- if (find_data->info.serial[0] != 0) {
- if (strcmp(find_data->info.serial, info->tinfo.serial_number) != 0)
- return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ if (class == -1) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
}
+
memset(&plist, 0, sizeof(plist));
+
if (find_data->flags==GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY) {
ret = pkcs11_login(pks, info);
if (ret < 0) {
@@ -1608,47 +1671,69 @@ static int find_objs(pakchois_session_t *pks, struct token_info *info, void* inp
/* Find objects with cert class and X.509 cert type. */
+ tot_values = 0;
+
if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_ALL || find_data->flags==GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY) {
class = CKO_CERTIFICATE;
type = CKC_X_509;
trusted = 1;
- a[0].type = CKA_CLASS;
- a[0].value = &class;
- a[0].value_len = sizeof class;
+ a[tot_values].type = CKA_CLASS;
+ a[tot_values].value = &class;
+ a[tot_values].value_len = sizeof class;
+ tot_values++;
- a[1].type = CKA_CERTIFICATE_TYPE;
- a[1].value = &type;
- a[1].value_len = sizeof type;
+ a[tot_values].type = CKA_CERTIFICATE_TYPE;
+ a[tot_values].value = &type;
+ a[tot_values].value_len = sizeof type;
+ tot_values++;
- tot_values = 2;
} else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED) {
class = CKO_CERTIFICATE;
type = CKC_X_509;
trusted = 1;
- a[0].type = CKA_CLASS;
- a[0].value = &class;
- a[0].value_len = sizeof class;
-
- a[1].type = CKA_TRUSTED;
- a[1].value = &trusted;
- a[1].value_len = sizeof trusted;
+ a[tot_values].type = CKA_CLASS;
+ a[tot_values].value = &class;
+ a[tot_values].value_len = sizeof class;
+ tot_values++;
+
+ a[tot_values].type = CKA_TRUSTED;
+ a[tot_values].value = &trusted;
+ a[tot_values].value_len = sizeof trusted;
+ tot_values++;
- tot_values = 2;
} else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_PUBKEY) {
class = CKO_PUBLIC_KEY;
- a[0].type = CKA_CLASS;
- a[0].value = &class;
- a[0].value_len = sizeof class;
-
- tot_values = 1;
+ a[tot_values].type = CKA_CLASS;
+ a[tot_values].value = &class;
+ a[tot_values].value_len = sizeof class;
+ tot_values++;
} else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_ALL) {
- tot_values = 0;
+ if (class != -1) {
+ a[tot_values].type = CKA_CLASS;
+ a[tot_values].value = &class;
+ a[tot_values].value_len = sizeof class;
+ tot_values++;
+ }
+ if (type != -1) {
+ a[tot_values].type = CKA_CERTIFICATE_TYPE;
+ a[tot_values].value = &type;
+ a[tot_values].value_len = sizeof type;
+ tot_values++;
+ }
} else {
gnutls_assert();
- return GNUTLS_E_INVALID_REQUEST;
+ ret = GNUTLS_E_INVALID_REQUEST;
+ goto fail;
+ }
+
+ if (find_data->info.certid_raw_size != 0) {
+ a[tot_values].type = CKA_ID;
+ a[tot_values].value = find_data->info.certid_raw;
+ a[tot_values].value_len = find_data->info.certid_raw_size;
+ tot_values++;
}
rv = pakchois_find_objects_init(pks, a, tot_values);
@@ -1677,6 +1762,7 @@ static int find_objs(pakchois_session_t *pks, struct token_info *info, void* inp
a[0].type = CKA_ID;
a[0].value = certid_tmp;
a[0].value_len = sizeof certid_tmp;
+
if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) {
id.data = a[0].value;
id.size = a[0].value_len;
@@ -1791,7 +1877,7 @@ int gnutls_pkcs11_obj_list_import_url (gnutls_pkcs11_obj_t * p_list, unsigned in
return ret;
}
- ret = _pkcs11_traverse_tokens(find_objs, &find_data, 0);
+ ret = _pkcs11_traverse_tokens(find_objs, &find_data, 0, 0);
if (ret < 0) {
gnutls_assert();
return ret;
@@ -1902,25 +1988,10 @@ static int find_flags(pakchois_session_t *pks, struct token_info *info, void* in
/* do not bother reading the token if basic fields do not match
*/
- if (find_data->info.manufacturer[0] != 0) {
- if (strcmp(find_data->info.manufacturer, info->tinfo.manufacturer_id) != 0)
- return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
- }
-
- if (find_data->info.token[0] != 0) {
- if (strcmp(find_data->info.token, info->tinfo.label) != 0)
- return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
- }
-
- if (find_data->info.model[0] != 0) {
- if (strcmp(find_data->info.model, info->tinfo.model) != 0)
- return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
- }
-
- if (find_data->info.serial[0] != 0) {
- if (strcmp(find_data->info.serial, info->tinfo.serial_number) != 0)
- return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
- }
+ if (pkcs11_token_matches_info( &find_data->info, &info->tinfo) < 0) {
+ gnutls_assert();
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ }
/* found token! */
@@ -1949,7 +2020,7 @@ int gnutls_pkcs11_token_get_flags(const char* url, unsigned int *flags)
return ret;
}
- ret = _pkcs11_traverse_tokens(find_flags, &find_data, 0);
+ ret = _pkcs11_traverse_tokens(find_flags, &find_data, 0, 0);
if (ret < 0) {
gnutls_assert();
return ret;
@@ -1982,3 +2053,28 @@ const char* gnutls_pkcs11_type_get_name (gnutls_pkcs11_obj_type_t type)
return "Unknown";
}
}
+
+int pkcs11_token_matches_info( struct pkcs11_url_info* info, struct ck_token_info* tinfo)
+{
+ if (info->manufacturer[0] != 0) {
+ if (strcmp(info->manufacturer, tinfo->manufacturer_id) != 0)
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ }
+
+ if (info->token[0] != 0) {
+ if (strcmp(info->token, tinfo->label) != 0)
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ }
+
+ if (info->model[0] != 0) {
+ if (strcmp(info->model, tinfo->model) != 0)
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ }
+
+ if (info->serial[0] != 0) {
+ if (strcmp(info->serial, tinfo->serial_number) != 0)
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ }
+
+ return 0;
+}
diff --git a/lib/pkcs11_int.h b/lib/pkcs11_int.h
index 6e1b3acb0b..81c2ba7ca1 100644
--- a/lib/pkcs11_int.h
+++ b/lib/pkcs11_int.h
@@ -46,7 +46,7 @@ struct gnutls_pkcs11_obj_st {
*/
typedef int (*find_func_t)(pakchois_session_t *pks, struct token_info* tinfo, void* input);
-int _pkcs11_traverse_tokens (find_func_t find_func, void* input, int leave_session);
+
int pkcs11_url_to_info(const char* url, struct pkcs11_url_info* info);
int pkcs11_get_info(struct pkcs11_url_info *info, gnutls_pkcs11_obj_info_t itype,
@@ -59,5 +59,12 @@ extern void* token_data;
void pkcs11_rescan_slots(void);
int pkcs11_info_to_url(const struct pkcs11_url_info* info, char** url);
+#define SESSION_WRITE 1
+#define SESSION_LOGIN 2
+int pkcs11_open_session (pakchois_session_t** _pks, struct pkcs11_url_info *info, unsigned int flags);
+int _pkcs11_traverse_tokens (find_func_t find_func, void* input, int leave_session, unsigned int flags);
+ck_object_class_t pkcs11_strtype_to_class(const char* type);
+
+int pkcs11_token_matches_info( struct pkcs11_url_info* info, struct ck_token_info* tinfo);
#endif
diff --git a/lib/pkcs11_privkey.c b/lib/pkcs11_privkey.c
index 913b11d55e..3fd54f9a55 100644
--- a/lib/pkcs11_privkey.c
+++ b/lib/pkcs11_privkey.c
@@ -134,7 +134,7 @@ int gnutls_pkcs11_privkey_get_info(gnutls_pkcs11_privkey_t pkey,
key->pks = NULL; \
ret = token_func(token_data, label, retries++); \
if (ret == 0) { \
- _pkcs11_traverse_tokens(find_privkey_url, &find_data, 1); \
+ _pkcs11_traverse_tokens(find_privkey_url, &find_data, 1, 0); \
goto retry; \
} \
} \
@@ -287,36 +287,13 @@ static int find_privkey_url(pakchois_session_t * pks,
/* do not bother reading the token if basic fields do not match
*/
- if (find_data->privkey->info.manufacturer[0] != 0) {
- if (strcmp
- (find_data->privkey->info.manufacturer,
- info->tinfo.manufacturer_id) != 0)
- return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
- }
-
- if (find_data->privkey->info.token[0] != 0) {
- if (strcmp
- (find_data->privkey->info.token,
- info->tinfo.label) != 0)
- return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
- }
-
- if (find_data->privkey->info.model[0] != 0) {
- if (strcmp
- (find_data->privkey->info.model,
- info->tinfo.model) != 0)
- return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
- }
-
- if (find_data->privkey->info.serial[0] != 0) {
- if (strcmp
- (find_data->privkey->info.serial,
- info->tinfo.serial_number) != 0)
- return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ if (pkcs11_token_matches_info( &find_data->privkey->info, &info->tinfo) < 0) {
+ gnutls_assert();
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
}
-
+
if (find_data->privkey->info.type[0] != 0) {
- if (strcmp(find_data->privkey->info.type, "cert") != 0) {
+ if (strcmp(find_data->privkey->info.type, "private") != 0) {
gnutls_assert();
return GNUTLS_E_UNIMPLEMENTED_FEATURE;
}
@@ -422,7 +399,7 @@ int gnutls_pkcs11_privkey_import_url(gnutls_pkcs11_privkey_t pkey,
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
}
- ret = _pkcs11_traverse_tokens(find_privkey_url, &find_data, 1);
+ ret = _pkcs11_traverse_tokens(find_privkey_url, &find_data, 1, 0);
if (ret < 0) {
gnutls_assert();
return ret;
diff --git a/lib/pkcs11_write.c b/lib/pkcs11_write.c
new file mode 100644
index 0000000000..a8ed760435
--- /dev/null
+++ b/lib/pkcs11_write.c
@@ -0,0 +1,508 @@
+/*
+ * GnuTLS PKCS#11 support
+ * Copyright (C) 2010 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA
+*/
+
+#include <gnutls_int.h>
+#include <gnutls/pkcs11.h>
+#include <stdio.h>
+#include <string.h>
+#include <gnutls_errors.h>
+#include <gnutls_datum.h>
+#include <pkcs11_int.h>
+
+/**
+ * gnutls_pkcs11_copy_x509_crt:
+ * @token_url: A PKCS #11 URL specifying a token
+ * @crt: A certificate
+ * @label: A name to be used for the stored data
+ * @flags: One of GNUTLS_PKCS11_OBJ_FLAG_*
+ *
+ * This function will copy a certificate into a PKCS #11 token specified by
+ * a URL. The certificate can be marked as trusted or not.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
+ * negative error value.
+ **/
+int gnutls_pkcs11_copy_x509_crt(const char* token_url, gnutls_x509_crt_t crt,
+ const char* label, unsigned int flags)
+{
+ int ret;
+ pakchois_session_t *pks;
+ struct pkcs11_url_info info;
+ ck_rv_t rv;
+ size_t der_size, id_size;
+ opaque* der = NULL;
+ opaque id[20];
+ struct ck_attribute a[8];
+ ck_object_class_t class = CKO_CERTIFICATE;
+ ck_certificate_type_t type = CKC_X_509;
+ ck_object_handle_t obj;
+ unsigned int tval = 1;
+ int a_val;
+
+ ret = pkcs11_url_to_info(token_url, &info);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ ret = pkcs11_open_session (&pks, &info, SESSION_WRITE|SESSION_LOGIN);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ ret = gnutls_x509_crt_export (crt,
+ GNUTLS_X509_FMT_DER, NULL,
+ &der_size);
+ if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ der = gnutls_malloc(der_size);
+ if (der == NULL) {
+ gnutls_assert();
+ ret = GNUTLS_E_MEMORY_ERROR;
+ goto cleanup;
+ }
+
+ ret = gnutls_x509_crt_export (crt,
+ GNUTLS_X509_FMT_DER, der,
+ &der_size);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ id_size = sizeof(id);
+ ret = gnutls_x509_crt_get_key_id (crt, 0, id, &id_size);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+
+ a[0].type = CKA_CLASS;
+ a[0].value = &class;
+ a[0].value_len = sizeof(class);
+ a[1].type = CKA_ID;
+ a[1].value = id;
+ a[1].value_len = id_size;
+ a[2].type = CKA_VALUE;
+ a[2].value = der;
+ a[2].value_len = der_size;
+ a[3].type = CKA_TOKEN;
+ a[3].value = &tval;
+ a[3].value_len = sizeof(tval);
+ a[4].type = CKA_CERTIFICATE_TYPE;
+ a[4].value = &type;
+ a[4].value_len = sizeof(type);
+
+ a_val = 5;
+
+ if (label) {
+ 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_TRUSTED) {
+ a[a_val].type = CKA_TRUSTED;
+ a[a_val].value = &tval;
+ a[a_val].value_len = sizeof(tval);
+ a_val++;
+ }
+
+ rv = pakchois_create_object(pks, a, a_val, &obj);
+ if (rv != CKR_OK) {
+ gnutls_assert();
+ _gnutls_debug_log("pkcs11: %s\n", pakchois_error(rv));
+ ret = GNUTLS_E_PKCS11_ERROR;
+ goto cleanup;
+ }
+
+ /* generated!
+ */
+
+ ret = 0;
+
+cleanup:
+ gnutls_free(der);
+ pakchois_close_session(pks);
+
+ return ret;
+
+}
+
+/**
+ * gnutls_pkcs11_copy_x509_privkey:
+ * @token_url: A PKCS #11 URL specifying a token
+ * @key: A private key
+ * @label: A name to be used for the stored data
+ * @key_usage: One of GNUTLS_KEY_*
+ *
+ * This function will copy a private key into a PKCS #11 token specified by
+ * a URL.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
+ * negative error value.
+ **/
+int gnutls_pkcs11_copy_x509_privkey(const char* token_url,
+ gnutls_x509_privkey_t key, const char* label, unsigned int key_usage)
+{
+ int ret;
+ pakchois_session_t *pks;
+ struct pkcs11_url_info info;
+ ck_rv_t rv;
+ size_t id_size;
+ opaque id[20];
+ struct ck_attribute a[16];
+ ck_object_class_t class = CKO_PRIVATE_KEY;
+ ck_object_handle_t obj;
+ ck_key_type_t type;
+ unsigned int tval = 1;
+ int a_val;
+ gnutls_pk_algorithm_t pk;
+ gnutls_datum_t p, q, g, y, x;
+ gnutls_datum_t m, e, d, u, exp1, exp2;
+
+
+ ret = pkcs11_url_to_info(token_url, &info);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ id_size = sizeof(id);
+ ret = gnutls_x509_privkey_get_key_id (key, 0, id, &id_size);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret = pkcs11_open_session (&pks, &info, SESSION_WRITE|SESSION_LOGIN);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ a[0].type = CKA_CLASS;
+ a[0].value = &class;
+ a[0].value_len = sizeof(class);
+ a[1].type = CKA_ID;
+ a[1].value = id;
+ a[1].value_len = id_size;
+ a[2].type = CKA_KEY_TYPE;
+ a[2].value = &type;
+ a[2].value_len = sizeof(type);
+ a[3].type = CKA_SENSITIVE;
+ a[3].value = &tval;
+ a[3].value_len = sizeof(tval);
+
+ a_val = 4;
+
+ pk = gnutls_x509_privkey_get_pk_algorithm(key);
+ switch(pk) {
+ case GNUTLS_PK_RSA: {
+
+ ret = gnutls_x509_privkey_export_rsa_raw2(key, &m, &e,
+ &d, &p, &q, &u, &exp1, &exp2);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ type = CKK_RSA;
+
+ a[a_val].type = CKA_MODULUS;
+ a[a_val].value = m.data;
+ a[a_val].value_len = m.size;
+ a_val++;
+
+ a[a_val].type = CKA_PUBLIC_EXPONENT;
+ a[a_val].value = e.data;
+ a[a_val].value_len = e.size;
+ a_val++;
+
+ a[a_val].type = CKA_PRIVATE_EXPONENT;
+ a[a_val].value = d.data;
+ a[a_val].value_len = d.size;
+ a_val++;
+
+ a[a_val].type = CKA_PRIME_1;
+ a[a_val].value = p.data;
+ a[a_val].value_len = p.size;
+ a_val++;
+
+ a[a_val].type = CKA_PRIME_2;
+ a[a_val].value = q.data;
+ a[a_val].value_len = q.size;
+ a_val++;
+
+ a[a_val].type = CKA_COEFFICIENT;
+ a[a_val].value = u.data;
+ a[a_val].value_len = u.size;
+ a_val++;
+
+ a[a_val].type = CKA_EXPONENT_1;
+ a[a_val].value = exp1.data;
+ a[a_val].value_len = exp1.size;
+ a_val++;
+
+ a[a_val].type = CKA_EXPONENT_2;
+ a[a_val].value = exp2.data;
+ a[a_val].value_len = exp2.size;
+ a_val++;
+
+ break;
+ }
+ case GNUTLS_PK_DSA: {
+ ret = gnutls_x509_privkey_export_dsa_raw(key, &p, &q,
+ &g, &y, &x);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ type = CKK_DSA;
+
+ a[a_val].type = CKA_PRIME;
+ a[a_val].value = p.data;
+ a[a_val].value_len = p.size;
+ a_val++;
+
+ a[a_val].type = CKA_SUBPRIME;
+ a[a_val].value = q.data;
+ a[a_val].value_len = q.size;
+ a_val++;
+
+ a[a_val].type = CKA_BASE;
+ a[a_val].value = g.data;
+ a[a_val].value_len = g.size;
+ a_val++;
+
+ a[a_val].type = CKA_VALUE;
+ a[a_val].value = x.data;
+ a[a_val].value_len = x.size;
+ a_val++;
+
+ break;
+ }
+ default:
+ gnutls_assert();
+ ret = GNUTLS_E_INVALID_REQUEST;
+ goto cleanup;
+ }
+
+ rv = pakchois_create_object(pks, a, a_val, &obj);
+ if (rv != CKR_OK) {
+ gnutls_assert();
+ _gnutls_debug_log("pkcs11: %s\n", pakchois_error(rv));
+ ret = GNUTLS_E_PKCS11_ERROR;
+ goto cleanup;
+ }
+
+ /* generated!
+ */
+
+ switch(pk) {
+ case GNUTLS_PK_RSA: {
+ gnutls_free(m.data);
+ gnutls_free(e.data);
+ gnutls_free(d.data);
+ gnutls_free(p.data);
+ gnutls_free(q.data);
+ gnutls_free(u.data);
+ gnutls_free(exp1.data);
+ gnutls_free(exp2.data);
+ break;
+ }
+ case GNUTLS_PK_DSA: {
+ gnutls_free(p.data);
+ gnutls_free(q.data);
+ gnutls_free(g.data);
+ gnutls_free(y.data);
+ gnutls_free(x.data);
+ break;
+ }
+ default:
+ gnutls_assert();
+ ret = GNUTLS_E_INVALID_REQUEST;
+ goto cleanup;
+ }
+
+ ret = 0;
+
+cleanup:
+ pakchois_close_session(pks);
+
+ return ret;
+
+}
+
+struct delete_data_st {
+ struct pkcs11_url_info info;
+ unsigned int deleted; /* how many */
+};
+
+static int delete_obj_url(pakchois_session_t *pks, struct token_info *info, void* input)
+{
+ struct delete_data_st* find_data = input;
+ struct ck_attribute a[4];
+ ck_object_class_t class;
+ ck_certificate_type_t type = -1;
+ ck_rv_t rv;
+ ck_object_handle_t obj;
+ unsigned long count, a_vals;
+ int found = 0, ret;
+
+
+ if (info == NULL) { /* we don't support multiple calls */
+ gnutls_assert();
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ }
+
+ /* do not bother reading the token if basic fields do not match
+ */
+ if (pkcs11_token_matches_info( &find_data->info, &info->tinfo) < 0) {
+ gnutls_assert();
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ }
+
+ class = CKO_CERTIFICATE; /* default */
+
+ if (find_data->info.type[0] != 0) {
+ class = pkcs11_strtype_to_class(find_data->info.type);
+ if (class == CKO_CERTIFICATE)
+ type = CKC_X_509;
+
+ if (class == -1) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+ }
+
+ ret = pkcs11_login(pks, info);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ a_vals = 0;
+
+ /* Find objects with given class and type */
+ if (find_data->info.certid_raw_size > 0) {
+ a[a_vals].type = CKA_ID;
+ a[a_vals].value = find_data->info.certid_raw;
+ a[a_vals].value_len = find_data->info.certid_raw_size;
+ a_vals++;
+ }
+
+ if (class != -1) {
+ a[a_vals].type = CKA_CLASS;
+ a[a_vals].value = &class;
+ a[a_vals].value_len = sizeof class;
+ a_vals++;
+ }
+
+ if (type != -1) {
+ a[a_vals].type = CKA_CERTIFICATE_TYPE;
+ a[a_vals].value = &type;
+ a[a_vals].value_len = sizeof type;
+ a_vals++;
+ }
+
+ if (find_data->info.label[0] != 0) {
+ a[a_vals].type = CKA_LABEL;
+ a[a_vals].value = find_data->info.label;
+ a[a_vals].value_len = strlen(find_data->info.label);
+ a_vals++;
+ }
+
+ rv = pakchois_find_objects_init(pks, a, a_vals);
+ if (rv != CKR_OK) {
+ gnutls_assert();
+ _gnutls_debug_log("pk11: FindObjectsInit failed.\n");
+ ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ goto cleanup;
+ }
+
+ while (pakchois_find_objects(pks, &obj, 1, &count) == CKR_OK
+ && count == 1) {
+
+ rv = pakchois_destroy_object(pks, obj);
+ if (rv != CKR_OK) {
+ _gnutls_debug_log("pkcs11: Cannot destroy object: %s\n", pakchois_error(rv));
+ } else {
+ find_data->deleted++;
+ }
+
+ found = 1;
+ }
+
+ if (found == 0) {
+ gnutls_assert();
+ ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ } else {
+ ret = 0;
+ }
+
+cleanup:
+ pakchois_find_objects_final(pks);
+
+ return ret;
+}
+
+
+/**
+ * gnutls_pkcs11_delete_url:
+ * @object_url: The URL of the object to delete.
+ *
+ * This function will delete objects matching the given URL.
+ *
+ * Returns: On success, the number of objects deleted is returned, otherwise a
+ * negative error value.
+ **/
+int gnutls_pkcs11_delete_url(const char* object_url)
+{
+ int ret;
+ struct delete_data_st find_data;
+
+ memset(&find_data, 0, sizeof(find_data));
+
+ ret = pkcs11_url_to_info(object_url, &find_data.info);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ ret = _pkcs11_traverse_tokens(delete_obj_url, &find_data, 0, SESSION_WRITE);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ return find_data.deleted;
+
+}
+
diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c
index c81e67a161..6d47a6504d 100644
--- a/lib/x509/privkey.c
+++ b/lib/x509/privkey.c
@@ -35,6 +35,7 @@
#include <x509_int.h>
#include <gnutls_pk.h>
#include <sign.h>
+#include <gnutls_mpi.h>
static int _gnutls_asn1_encode_rsa (ASN1_TYPE * c2, bigint_t * params);
@@ -218,6 +219,20 @@ _gnutls_privkey_decode_pkcs1_rsa_key (const gnutls_datum_t * raw_key,
goto error;
}
+ if ((result = _gnutls_x509_read_int (pkey_asn, "exponent1",
+ &pk_params.params[6])) < 0)
+ {
+ gnutls_assert ();
+ goto error;
+ }
+
+ if ((result = _gnutls_x509_read_int (pkey_asn, "exponent2",
+ &pk_params.params[7])) < 0)
+ {
+ gnutls_assert ();
+ goto error;
+ }
+
result = _gnutls_pk_fixup (GNUTLS_PK_RSA, GNUTLS_IMPORT, &pk_params);
if (result < 0)
@@ -232,6 +247,8 @@ _gnutls_privkey_decode_pkcs1_rsa_key (const gnutls_datum_t * raw_key,
pkey->params[3] = pk_params.params[3];
pkey->params[4] = pk_params.params[4];
pkey->params[5] = pk_params.params[5];
+ pkey->params[6] = pk_params.params[6];
+ pkey->params[7] = pk_params.params[7];
pkey->params_size = pk_params.params_nr;
return pkey_asn;
@@ -465,6 +482,37 @@ gnutls_x509_privkey_import_rsa_raw (gnutls_x509_privkey_t key,
const gnutls_datum_t * q,
const gnutls_datum_t * u)
{
+ return gnutls_x509_privkey_import_rsa_raw2( key, m, e, d, p, q, u, NULL, NULL);
+}
+
+/**
+ * gnutls_x509_privkey_import_rsa_raw2:
+ * @key: The structure to store the parsed key
+ * @m: holds the modulus
+ * @e: holds the public exponent
+ * @d: holds the private exponent
+ * @p: holds the first prime (p)
+ * @q: holds the second prime (q)
+ * @u: holds the coefficient
+ *
+ * This function will convert the given RSA raw parameters to the
+ * native #gnutls_x509_privkey_t format. The output will be stored in
+ * @key.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
+ * negative error value.
+ **/
+int
+gnutls_x509_privkey_import_rsa_raw2 (gnutls_x509_privkey_t key,
+ const gnutls_datum_t * m,
+ const gnutls_datum_t * e,
+ const gnutls_datum_t * d,
+ const gnutls_datum_t * p,
+ const gnutls_datum_t * q,
+ const gnutls_datum_t * u,
+ const gnutls_datum_t * e1,
+ const gnutls_datum_t * e2)
+{
int i = 0, ret;
size_t siz = 0;
@@ -522,15 +570,61 @@ gnutls_x509_privkey_import_rsa_raw (gnutls_x509_privkey_t key,
return GNUTLS_E_MPI_SCAN_FAILED;
}
+ if (e1 && e2)
+ {
+ siz = e1->size;
+ if (_gnutls_mpi_scan_nz (&key->params[6], e1->data, siz))
+ {
+ gnutls_assert ();
+ FREE_RSA_PRIVATE_PARAMS;
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ siz = e2->size;
+ if (_gnutls_mpi_scan_nz (&key->params[7], e2->data, siz))
+ {
+ gnutls_assert ();
+ FREE_RSA_PRIVATE_PARAMS;
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+ }
+ else /* calculate e1 and e2 */
+ {
+ bigint_t tmp = _gnutls_mpi_alloc_like(key->params[0]);
+ if (tmp == NULL)
+ {
+ gnutls_assert ();
+ FREE_RSA_PRIVATE_PARAMS;
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ /* [6] = d % p-1, [7] = d % q-1 */
+ _gnutls_mpi_sub_ui(tmp, key->params[3], 1);
+ key->params[6] = _gnutls_mpi_mod(key->params[2]/*d*/, tmp);
+
+ _gnutls_mpi_sub_ui(tmp, key->params[4], 1);
+ key->params[7] = _gnutls_mpi_mod(key->params[2]/*d*/, tmp);
+
+ _gnutls_mpi_release(&tmp);
+
+ if (key->params[7] == NULL || key->params[6] == NULL)
+ {
+ gnutls_assert ();
+ FREE_RSA_PRIVATE_PARAMS;
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ }
+
+
if (!key->crippled)
{
ret = _gnutls_asn1_encode_rsa (&key->key, key->params);
if (ret < 0)
- {
- gnutls_assert ();
- FREE_RSA_PRIVATE_PARAMS;
- return ret;
- }
+ {
+ gnutls_assert ();
+ FREE_RSA_PRIVATE_PARAMS;
+ return ret;
+ }
}
key->params_size = RSA_PRIVATE_PARAMS;
@@ -751,6 +845,36 @@ gnutls_x509_privkey_export_rsa_raw (gnutls_x509_privkey_t key,
gnutls_datum_t * d, gnutls_datum_t * p,
gnutls_datum_t * q, gnutls_datum_t * u)
{
+
+ return gnutls_x509_privkey_export_rsa_raw2(key, m, e, d, p, q, u, NULL, NULL);
+}
+
+/**
+ * gnutls_x509_privkey_export_rsa_raw2:
+ * @key: a structure that holds the rsa parameters
+ * @m: will hold the modulus
+ * @e: will hold the public exponent
+ * @d: will hold the private exponent
+ * @p: will hold the first prime (p)
+ * @q: will hold the second prime (q)
+ * @u: will hold the coefficient
+ * @e1: will hold the exponent 1
+ * @e2: will hold the exponent 2
+ *
+ * This function will export the RSA private key's parameters found
+ * in the given structure. The new parameters will be allocated using
+ * gnutls_malloc() and will be stored in the appropriate datum.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a
+ * negative error value.
+ **/
+int
+gnutls_x509_privkey_export_rsa_raw2 (gnutls_x509_privkey_t key,
+ gnutls_datum_t * m, gnutls_datum_t * e,
+ gnutls_datum_t * d, gnutls_datum_t * p,
+ gnutls_datum_t * q, gnutls_datum_t * u,
+ gnutls_datum_t* e1, gnutls_datum_t* e2)
+{
int ret;
gnutls_pk_params_st pk_params;
@@ -824,6 +948,28 @@ gnutls_x509_privkey_export_rsa_raw (gnutls_x509_privkey_t key,
goto error;
}
+ /* E1 */
+ if (e1)
+ {
+ ret = _gnutls_mpi_dprint (key->params[6], e1);
+ if (ret < 0)
+ {
+ gnutls_assert ();
+ goto error;
+ }
+ }
+
+ /* E2 */
+ if (e2)
+ {
+ ret = _gnutls_mpi_dprint (key->params[7], e2);
+ if (ret < 0)
+ {
+ gnutls_assert ();
+ goto error;
+ }
+ }
+
gnutls_pk_params_release (&pk_params);
return 0;
@@ -935,7 +1081,6 @@ _gnutls_asn1_encode_rsa (ASN1_TYPE * c2, bigint_t * params)
opaque *m_data, *pube_data, *prie_data;
opaque *p1_data, *p2_data, *u_data, *exp1_data, *exp2_data;
opaque *all_data = NULL, *p;
- bigint_t exp1 = NULL, exp2 = NULL, q1 = NULL, p1 = NULL;
opaque null = '\0';
gnutls_pk_params_st pk_params;
@@ -961,52 +1106,6 @@ _gnutls_asn1_encode_rsa (ASN1_TYPE * c2, bigint_t * params)
goto cleanup;
}
- q1 = _gnutls_mpi_alloc_like (pk_params.params[4]);
- if (q1 == NULL)
- {
- gnutls_assert ();
- result = GNUTLS_E_MEMORY_ERROR;
- goto cleanup;
- }
-
- p1 = _gnutls_mpi_alloc_like (pk_params.params[3]);
- if (p1 == NULL)
- {
- gnutls_assert ();
- result = GNUTLS_E_MEMORY_ERROR;
- goto cleanup;
- }
-
- /* inverse of q mod p */
- _gnutls_mpi_print_lz (pk_params.params[5], NULL, &size[5]);
- total += size[5];
-
- _gnutls_mpi_sub_ui (p1, pk_params.params[3], 1);
- _gnutls_mpi_sub_ui (q1, pk_params.params[4], 1);
-
- exp1 = _gnutls_mpi_mod (pk_params.params[2], p1);
- if (exp1 == NULL)
- {
- gnutls_assert ();
- result = GNUTLS_E_MEMORY_ERROR;
- goto cleanup;
- }
-
- exp2 = _gnutls_mpi_mod (pk_params.params[2], q1);
- if (exp2 == NULL)
- {
- gnutls_assert ();
- result = GNUTLS_E_MEMORY_ERROR;
- goto cleanup;
- }
-
- /* calculate exp's size */
- _gnutls_mpi_print_lz (exp1, NULL, &size[6]);
- total += size[6];
-
- _gnutls_mpi_print_lz (exp2, NULL, &size[7]);
- total += size[7];
-
/* Encoding phase.
* allocate data enough to hold everything
*/
@@ -1021,18 +1120,25 @@ _gnutls_asn1_encode_rsa (ASN1_TYPE * c2, bigint_t * params)
p = all_data;
m_data = p;
p += size[0];
+
pube_data = p;
p += size[1];
+
prie_data = p;
p += size[2];
+
p1_data = p;
p += size[3];
+
p2_data = p;
p += size[4];
+
u_data = p;
p += size[5];
+
exp1_data = p;
p += size[6];
+
exp2_data = p;
_gnutls_mpi_print_lz (pk_params.params[0], m_data, &size[0]);
@@ -1041,8 +1147,8 @@ _gnutls_asn1_encode_rsa (ASN1_TYPE * c2, bigint_t * params)
_gnutls_mpi_print_lz (pk_params.params[3], p1_data, &size[3]);
_gnutls_mpi_print_lz (pk_params.params[4], p2_data, &size[4]);
_gnutls_mpi_print_lz (pk_params.params[5], u_data, &size[5]);
- _gnutls_mpi_print_lz (exp1, exp1_data, &size[6]);
- _gnutls_mpi_print_lz (exp2, exp2_data, &size[7]);
+ _gnutls_mpi_print_lz (pk_params.params[6], exp1_data, &size[6]);
+ _gnutls_mpi_print_lz (pk_params.params[7], exp2_data, &size[7]);
/* Ok. Now we have the data. Create the asn1 structures
*/
@@ -1105,34 +1211,31 @@ _gnutls_asn1_encode_rsa (ASN1_TYPE * c2, bigint_t * params)
goto cleanup;
}
- if ((result = asn1_write_value (*c2, "exponent1",
- exp1_data, size[6])) != ASN1_SUCCESS)
+ if ((result = asn1_write_value (*c2, "coefficient",
+ u_data, size[5])) != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
+
goto cleanup;
}
- if ((result = asn1_write_value (*c2, "exponent2",
- exp2_data, size[7])) != ASN1_SUCCESS)
+ if ((result = asn1_write_value (*c2, "exponent1",
+ exp1_data, size[6])) != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto cleanup;
}
- if ((result = asn1_write_value (*c2, "coefficient",
- u_data, size[5])) != ASN1_SUCCESS)
+ if ((result = asn1_write_value (*c2, "exponent2",
+ exp2_data, size[7])) != ASN1_SUCCESS)
{
gnutls_assert ();
result = _gnutls_asn2err (result);
goto cleanup;
}
- _gnutls_mpi_release (&exp1);
- _gnutls_mpi_release (&exp2);
- _gnutls_mpi_release (&q1);
- _gnutls_mpi_release (&p1);
gnutls_pk_params_release (&pk_params);
gnutls_free (all_data);
@@ -1154,10 +1257,6 @@ _gnutls_asn1_encode_rsa (ASN1_TYPE * c2, bigint_t * params)
return 0;
cleanup:
- _gnutls_mpi_release (&exp1);
- _gnutls_mpi_release (&exp2);
- _gnutls_mpi_release (&q1);
- _gnutls_mpi_release (&p1);
gnutls_pk_params_release (&pk_params);
asn1_delete_structure (c2);
gnutls_free (all_data);
@@ -1320,6 +1419,12 @@ gnutls_x509_privkey_generate (gnutls_x509_privkey_t key,
{
case GNUTLS_PK_DSA:
ret = _gnutls_dsa_generate_params (key->params, &params_len, bits);
+ if (params_len != DSA_PRIVATE_PARAMS)
+ {
+ gnutls_assert();
+ ret = GNUTLS_E_INTERNAL_ERROR;
+ }
+
if (ret < 0)
{
gnutls_assert ();
@@ -1341,6 +1446,11 @@ gnutls_x509_privkey_generate (gnutls_x509_privkey_t key,
break;
case GNUTLS_PK_RSA:
ret = _gnutls_rsa_generate_params (key->params, &params_len, bits);
+ if (params_len != RSA_PRIVATE_PARAMS)
+ {
+ gnutls_assert();
+ ret = GNUTLS_E_INTERNAL_ERROR;
+ }
if (ret < 0)
{
gnutls_assert ();
diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h
index 6d6a91411e..00960a310e 100644
--- a/lib/x509/x509_int.h
+++ b/lib/x509/x509_int.h
@@ -72,12 +72,12 @@ typedef struct gnutls_pkcs7_int
ASN1_TYPE pkcs7;
} gnutls_pkcs7_int;
-#define MAX_PRIV_PARAMS_SIZE GNUTLS_MAX_PK_PARAMS /* ok for RSA and DSA */
+#define MAX_PRIV_PARAMS_SIZE GNUTLS_MAX_PK_PARAMS /* ok for RSA and DSA */
/* parameters should not be larger than this limit */
#define DSA_PRIVATE_PARAMS 5
#define DSA_PUBLIC_PARAMS 4
-#define RSA_PRIVATE_PARAMS 6
+#define RSA_PRIVATE_PARAMS 8
#define RSA_PUBLIC_PARAMS 2
#if MAX_PRIV_PARAMS_SIZE - RSA_PRIVATE_PARAMS < 0
@@ -103,7 +103,9 @@ typedef struct gnutls_x509_privkey_int
* [4] is prime2 (q)
* [5] is coefficient (u == inverse of p mod q)
* note that other packages used inverse of q mod p,
- * so we need to perform conversions.
+ * so we need to perform conversions (for libgcrypt only)
+ * [6] e1 == d mod (p-1)
+ * [7] e2 == d mod (q-1)
* DSA: [0] is p
* [1] is q
* [2] is g
diff --git a/src/certtool-common.h b/src/certtool-common.h
index f5db0abd80..79d2300471 100644
--- a/src/certtool-common.h
+++ b/src/certtool-common.h
@@ -29,6 +29,8 @@ enum
ACTION_PKCS11_LIST,
ACTION_PKCS11_TOKENS,
ACTION_PKCS11_EXPORT_URL,
+ ACTION_PKCS11_WRITE_URL,
+ ACTION_PKCS11_DELETE_URL,
ACTION_PUBKEY_INFO,
};
@@ -39,6 +41,8 @@ void certtool_version (void);
void pkcs11_list( FILE*outfile, const char* url, int type);
void pkcs11_export(FILE* outfile, const char *pkcs11_url);
void pkcs11_token_list(FILE* outfile);
+void pkcs11_write(FILE* outfile, const char *pkcs11_url, const char* label, int trusted);
+void pkcs11_delete(FILE* outfile, const char *pkcs11_url, int batch);
#define PKCS11_TYPE_CRT_ALL 1
#define PKCS11_TYPE_TRUSTED 2
@@ -47,3 +51,13 @@ void pkcs11_token_list(FILE* outfile);
extern unsigned char buffer[];
extern const int buffer_size;
+
+#include <gnutls/x509.h>
+#include <gnutls/abstract.h>
+
+gnutls_x509_privkey_t load_private_key (int mand);
+gnutls_x509_crq_t load_request (void);
+gnutls_x509_privkey_t load_ca_private_key (void);
+gnutls_x509_crt_t load_ca_cert (void);
+gnutls_x509_crt_t load_cert (int mand);
+gnutls_pubkey_t load_pubkey (int mand);
diff --git a/src/certtool-gaa.c b/src/certtool-gaa.c
index 538c502761..97e2bcd6fd 100644
--- a/src/certtool-gaa.c
+++ b/src/certtool-gaa.c
@@ -184,6 +184,10 @@ void gaa_help(void)
__gaa_helpsingle(0, "pkcs11-list-all-certs", "", "List all certificates specified by a PKCS#11 URL");
__gaa_helpsingle(0, "pkcs11-list-all", "", "List all objects specified by a PKCS#11 URL");
__gaa_helpsingle(0, "pkcs11-list-tokens", "", "List all available tokens");
+ __gaa_helpsingle(0, "pkcs11-write", "URL ", "Writes loaded certificates or private keys to a PKCS11 token.");
+ __gaa_helpsingle(0, "pkcs11-write-label", "label ", "Sets a label for the write operation.");
+ __gaa_helpsingle(0, "pkcs11-write-trusted", "", "Marks the certificate to be imported as trusted.");
+ __gaa_helpsingle(0, "pkcs11-delete-url", "URL ", "Deletes objects matching the URL.");
__gaa_helpsingle('d', "debug", "LEVEL ", "specify the debug level. Default is 1.");
__gaa_helpsingle('h', "help", "", "shows this help text");
__gaa_helpsingle('v', "version", "", "shows the program's version");
@@ -201,8 +205,12 @@ typedef struct _gaainfo gaainfo;
struct _gaainfo
{
-#line 149 "certtool.gaa"
+#line 157 "certtool.gaa"
int debug;
+#line 152 "certtool.gaa"
+ int pkcs11_trusted;
+#line 149 "certtool.gaa"
+ char* pkcs11_label;
#line 142 "certtool.gaa"
int pkcs11_type;
#line 139 "certtool.gaa"
@@ -311,65 +319,69 @@ static int gaa_error = 0;
#define GAA_MULTIPLE_OPTION 3
#define GAA_REST 0
-#define GAA_NB_OPTION 58
+#define GAA_NB_OPTION 62
#define GAAOPTID_version 1
#define GAAOPTID_help 2
#define GAAOPTID_debug 3
-#define GAAOPTID_pkcs11_list_tokens 4
-#define GAAOPTID_pkcs11_list_all 5
-#define GAAOPTID_pkcs11_list_all_certs 6
-#define GAAOPTID_pkcs11_list_trusted 7
-#define GAAOPTID_pkcs11_list_certs 8
-#define GAAOPTID_pkcs11_export_url 9
-#define GAAOPTID_pkcs11_provider 10
-#define GAAOPTID_pkcs_cipher 11
-#define GAAOPTID_template 12
-#define GAAOPTID_infile 13
-#define GAAOPTID_outfile 14
-#define GAAOPTID_disable_quick_random 15
-#define GAAOPTID_bits 16
-#define GAAOPTID_outraw 17
-#define GAAOPTID_outder 18
-#define GAAOPTID_inraw 19
-#define GAAOPTID_inder 20
-#define GAAOPTID_export_ciphers 21
-#define GAAOPTID_hash 22
-#define GAAOPTID_dsa 23
-#define GAAOPTID_pkcs8 24
-#define GAAOPTID_to_p8 25
-#define GAAOPTID_to_p12 26
-#define GAAOPTID_v1 27
-#define GAAOPTID_fix_key 28
-#define GAAOPTID_pubkey_info 29
-#define GAAOPTID_pgp_key_info 30
-#define GAAOPTID_key_info 31
-#define GAAOPTID_smime_to_p7 32
-#define GAAOPTID_p7_info 33
-#define GAAOPTID_p12_info 34
-#define GAAOPTID_no_crq_extensions 35
-#define GAAOPTID_crq_info 36
-#define GAAOPTID_crl_info 37
-#define GAAOPTID_pgp_ring_info 38
-#define GAAOPTID_pgp_certificate_info 39
-#define GAAOPTID_certificate_info 40
-#define GAAOPTID_password 41
-#define GAAOPTID_load_ca_certificate 42
-#define GAAOPTID_load_ca_privkey 43
-#define GAAOPTID_load_certificate 44
-#define GAAOPTID_load_request 45
-#define GAAOPTID_load_pubkey 46
-#define GAAOPTID_load_privkey 47
-#define GAAOPTID_get_dh_params 48
-#define GAAOPTID_generate_dh_params 49
-#define GAAOPTID_verify_crl 50
-#define GAAOPTID_verify_chain 51
-#define GAAOPTID_generate_request 52
-#define GAAOPTID_generate_privkey 53
-#define GAAOPTID_update_certificate 54
-#define GAAOPTID_generate_crl 55
-#define GAAOPTID_generate_proxy 56
-#define GAAOPTID_generate_certificate 57
-#define GAAOPTID_generate_self_signed 58
+#define GAAOPTID_pkcs11_delete_url 4
+#define GAAOPTID_pkcs11_write_trusted 5
+#define GAAOPTID_pkcs11_write_label 6
+#define GAAOPTID_pkcs11_write 7
+#define GAAOPTID_pkcs11_list_tokens 8
+#define GAAOPTID_pkcs11_list_all 9
+#define GAAOPTID_pkcs11_list_all_certs 10
+#define GAAOPTID_pkcs11_list_trusted 11
+#define GAAOPTID_pkcs11_list_certs 12
+#define GAAOPTID_pkcs11_export_url 13
+#define GAAOPTID_pkcs11_provider 14
+#define GAAOPTID_pkcs_cipher 15
+#define GAAOPTID_template 16
+#define GAAOPTID_infile 17
+#define GAAOPTID_outfile 18
+#define GAAOPTID_disable_quick_random 19
+#define GAAOPTID_bits 20
+#define GAAOPTID_outraw 21
+#define GAAOPTID_outder 22
+#define GAAOPTID_inraw 23
+#define GAAOPTID_inder 24
+#define GAAOPTID_export_ciphers 25
+#define GAAOPTID_hash 26
+#define GAAOPTID_dsa 27
+#define GAAOPTID_pkcs8 28
+#define GAAOPTID_to_p8 29
+#define GAAOPTID_to_p12 30
+#define GAAOPTID_v1 31
+#define GAAOPTID_fix_key 32
+#define GAAOPTID_pubkey_info 33
+#define GAAOPTID_pgp_key_info 34
+#define GAAOPTID_key_info 35
+#define GAAOPTID_smime_to_p7 36
+#define GAAOPTID_p7_info 37
+#define GAAOPTID_p12_info 38
+#define GAAOPTID_no_crq_extensions 39
+#define GAAOPTID_crq_info 40
+#define GAAOPTID_crl_info 41
+#define GAAOPTID_pgp_ring_info 42
+#define GAAOPTID_pgp_certificate_info 43
+#define GAAOPTID_certificate_info 44
+#define GAAOPTID_password 45
+#define GAAOPTID_load_ca_certificate 46
+#define GAAOPTID_load_ca_privkey 47
+#define GAAOPTID_load_certificate 48
+#define GAAOPTID_load_request 49
+#define GAAOPTID_load_pubkey 50
+#define GAAOPTID_load_privkey 51
+#define GAAOPTID_get_dh_params 52
+#define GAAOPTID_generate_dh_params 53
+#define GAAOPTID_verify_crl 54
+#define GAAOPTID_verify_chain 55
+#define GAAOPTID_generate_request 56
+#define GAAOPTID_generate_privkey 57
+#define GAAOPTID_update_certificate 58
+#define GAAOPTID_generate_crl 59
+#define GAAOPTID_generate_proxy 60
+#define GAAOPTID_generate_certificate 61
+#define GAAOPTID_generate_self_signed 62
#line 168 "gaa.skel"
@@ -562,6 +574,24 @@ struct GAAOPTION_debug
int size1;
};
+struct GAAOPTION_pkcs11_delete_url
+{
+ char* arg1;
+ int size1;
+};
+
+struct GAAOPTION_pkcs11_write_label
+{
+ char* arg1;
+ int size1;
+};
+
+struct GAAOPTION_pkcs11_write
+{
+ char* arg1;
+ int size1;
+};
+
struct GAAOPTION_pkcs11_export_url
{
char* arg1;
@@ -682,6 +712,9 @@ static int gaa_get_option_num(char *str, int status)
{
case GAA_LETTER_OPTION:
GAA_CHECK1STR("d", GAAOPTID_debug);
+ GAA_CHECK1STR("", GAAOPTID_pkcs11_delete_url);
+ GAA_CHECK1STR("", GAAOPTID_pkcs11_write_label);
+ GAA_CHECK1STR("", GAAOPTID_pkcs11_write);
GAA_CHECK1STR("", GAAOPTID_pkcs11_export_url);
GAA_CHECK1STR("", GAAOPTID_pkcs11_provider);
GAA_CHECK1STR("", GAAOPTID_pkcs_cipher);
@@ -701,6 +734,7 @@ static int gaa_get_option_num(char *str, int status)
#line 375 "gaa.skel"
GAA_CHECK1STR("v", GAAOPTID_version);
GAA_CHECK1STR("h", GAAOPTID_help);
+ GAA_CHECK1STR("", GAAOPTID_pkcs11_write_trusted);
GAA_CHECK1STR("", GAAOPTID_pkcs11_list_tokens);
GAA_CHECK1STR("", GAAOPTID_pkcs11_list_all);
GAA_CHECK1STR("", GAAOPTID_pkcs11_list_all_certs);
@@ -748,6 +782,10 @@ static int gaa_get_option_num(char *str, int status)
GAA_CHECKSTR("version", GAAOPTID_version);
GAA_CHECKSTR("help", GAAOPTID_help);
GAA_CHECKSTR("debug", GAAOPTID_debug);
+ GAA_CHECKSTR("pkcs11-delete-url", GAAOPTID_pkcs11_delete_url);
+ GAA_CHECKSTR("pkcs11-write-trusted", GAAOPTID_pkcs11_write_trusted);
+ GAA_CHECKSTR("pkcs11-write-label", GAAOPTID_pkcs11_write_label);
+ GAA_CHECKSTR("pkcs11-write", GAAOPTID_pkcs11_write);
GAA_CHECKSTR("pkcs11-list-tokens", GAAOPTID_pkcs11_list_tokens);
GAA_CHECKSTR("pkcs11-list-all", GAAOPTID_pkcs11_list_all);
GAA_CHECKSTR("pkcs11-list-all-certs", GAAOPTID_pkcs11_list_all_certs);
@@ -816,6 +854,9 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
int OK = 0;
int gaa_last_non_option;
struct GAAOPTION_debug GAATMP_debug;
+ struct GAAOPTION_pkcs11_delete_url GAATMP_pkcs11_delete_url;
+ struct GAAOPTION_pkcs11_write_label GAATMP_pkcs11_write_label;
+ struct GAAOPTION_pkcs11_write GAATMP_pkcs11_write;
struct GAAOPTION_pkcs11_export_url GAATMP_pkcs11_export_url;
struct GAAOPTION_pkcs11_provider GAATMP_pkcs11_provider;
struct GAAOPTION_pkcs_cipher GAATMP_pkcs_cipher;
@@ -853,14 +894,14 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
{
case GAAOPTID_version:
OK = 0;
-#line 154 "certtool.gaa"
+#line 162 "certtool.gaa"
{ certtool_version(); exit(0); ;};
return GAA_OK;
break;
case GAAOPTID_help:
OK = 0;
-#line 152 "certtool.gaa"
+#line 160 "certtool.gaa"
{ gaa_help(); exit(0); ;};
return GAA_OK;
@@ -870,11 +911,48 @@ 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 150 "certtool.gaa"
+#line 158 "certtool.gaa"
{ gaaval->debug = GAATMP_debug.arg1 ;};
return GAA_OK;
break;
+ case GAAOPTID_pkcs11_delete_url:
+ OK = 0;
+ GAA_TESTMOREARGS;
+ GAA_FILL(GAATMP_pkcs11_delete_url.arg1, gaa_getstr, GAATMP_pkcs11_delete_url.size1);
+ gaa_index++;
+#line 155 "certtool.gaa"
+{ gaaval->action = ACTION_PKCS11_DELETE_URL; gaaval->pkcs11_url = GAATMP_pkcs11_delete_url.arg1; ;};
+
+ return GAA_OK;
+ break;
+ case GAAOPTID_pkcs11_write_trusted:
+ OK = 0;
+#line 153 "certtool.gaa"
+{ gaaval->pkcs11_trusted = 1; ;};
+
+ return GAA_OK;
+ break;
+ case GAAOPTID_pkcs11_write_label:
+ OK = 0;
+ GAA_TESTMOREARGS;
+ GAA_FILL(GAATMP_pkcs11_write_label.arg1, gaa_getstr, GAATMP_pkcs11_write_label.size1);
+ gaa_index++;
+#line 151 "certtool.gaa"
+{ gaaval->pkcs11_label = GAATMP_pkcs11_write_label.arg1; ;};
+
+ return GAA_OK;
+ break;
+ case GAAOPTID_pkcs11_write:
+ OK = 0;
+ GAA_TESTMOREARGS;
+ GAA_FILL(GAATMP_pkcs11_write.arg1, gaa_getstr, GAATMP_pkcs11_write.size1);
+ gaa_index++;
+#line 150 "certtool.gaa"
+{ gaaval->action = ACTION_PKCS11_WRITE_URL; gaaval->pkcs11_url = GAATMP_pkcs11_write.arg1; ;};
+
+ return GAA_OK;
+ break;
case GAAOPTID_pkcs11_list_tokens:
OK = 0;
#line 147 "certtool.gaa"
@@ -1329,13 +1407,14 @@ int gaa(int argc, char **argv, gaainfo *gaaval)
if(inited == 0)
{
-#line 156 "certtool.gaa"
+#line 164 "certtool.gaa"
{ gaaval->bits = 2048; gaaval->pkcs8 = 0; gaaval->privkey = NULL; gaaval->ca=NULL; gaaval->ca_privkey = NULL;
gaaval->debug=1; gaaval->request = NULL; gaaval->infile = NULL; gaaval->outfile = NULL; gaaval->cert = NULL;
gaaval->incert_format = 0; gaaval->outcert_format = 0; gaaval->action=-1; gaaval->pass = NULL; gaaval->v1_cert = 0;
gaaval->export = 0; gaaval->template = NULL; gaaval->hash=NULL; gaaval->fix_key = 0; gaaval->quick_random=1;
gaaval->privkey_op = 0; gaaval->pkcs_cipher = "3des"; gaaval->crq_extensions=1; gaaval->pkcs11_provider= NULL;
- gaaval->pkcs11_url = NULL; gaaval->pkcs11_type = PKCS11_TYPE_PK; gaaval->pubkey=NULL; ;};
+ gaaval->pkcs11_url = NULL; gaaval->pkcs11_type = PKCS11_TYPE_PK; gaaval->pubkey=NULL; gaaval->pkcs11_label = NULL;
+ gaaval->pkcs11_trusted=0; ;};
}
inited = 1;
diff --git a/src/certtool-gaa.h b/src/certtool-gaa.h
index 80b022a1bb..2757a71e2b 100644
--- a/src/certtool-gaa.h
+++ b/src/certtool-gaa.h
@@ -8,8 +8,12 @@ typedef struct _gaainfo gaainfo;
struct _gaainfo
{
-#line 149 "certtool.gaa"
+#line 157 "certtool.gaa"
int debug;
+#line 152 "certtool.gaa"
+ int pkcs11_trusted;
+#line 149 "certtool.gaa"
+ char* pkcs11_label;
#line 142 "certtool.gaa"
int pkcs11_type;
#line 139 "certtool.gaa"
diff --git a/src/certtool.c b/src/certtool.c
index 075f19c840..b646453c50 100644
--- a/src/certtool.c
+++ b/src/certtool.c
@@ -64,12 +64,6 @@ void verify_crl (void);
void pubkey_info (void);
void pgp_privkey_info (void);
void pgp_ring_info (void);
-gnutls_x509_privkey_t load_private_key (int mand);
-gnutls_x509_crq_t load_request (void);
-gnutls_x509_privkey_t load_ca_private_key (void);
-gnutls_x509_crt_t load_ca_cert (void);
-gnutls_x509_crt_t load_cert (int mand);
-gnutls_pubkey_t load_pubkey (int mand);
void certificate_info (void);
void pgp_certificate_info (void);
void crl_info (void);
@@ -1028,6 +1022,12 @@ gaa_parser (int argc, char **argv)
case ACTION_PKCS11_EXPORT_URL:
pkcs11_export(outfile, info.pkcs11_url);
break;
+ case ACTION_PKCS11_WRITE_URL:
+ pkcs11_write(outfile, info.pkcs11_url, info.pkcs11_label, info.pkcs11_trusted);
+ break;
+ case ACTION_PKCS11_DELETE_URL:
+ pkcs11_delete(outfile, info.pkcs11_url, batch);
+ break;
#ifdef ENABLE_OPENPGP
case ACTION_PGP_INFO:
pgp_certificate_info ();
diff --git a/src/certtool.gaa b/src/certtool.gaa
index 7ad13a114a..04b2eac695 100644
--- a/src/certtool.gaa
+++ b/src/certtool.gaa
@@ -146,6 +146,14 @@ option (pkcs11-list-all-certs) { $action = ACTION_PKCS11_LIST; $pkcs11_type=PKCS
option (pkcs11-list-all) { $action = ACTION_PKCS11_LIST; $pkcs11_type=PKCS11_TYPE_ALL; } "List all objects specified by a PKCS#11 URL"
option (pkcs11-list-tokens) { $action = ACTION_PKCS11_TOKENS; } "List all available tokens"
+#char* pkcs11_label;
+option (pkcs11-write) STR "URL" { $action = ACTION_PKCS11_WRITE_URL; $pkcs11_url = $1; } "Writes loaded certificates or private keys to a PKCS11 token."
+option (pkcs11-write-label) STR "label" { $pkcs11_label = $1; } "Sets a label for the write operation."
+#int pkcs11_trusted;
+option (pkcs11-write-trusted) { $pkcs11_trusted = 1; } "Marks the certificate to be imported as trusted."
+
+option (pkcs11-delete-url) STR "URL" { $action = ACTION_PKCS11_DELETE_URL; $pkcs11_url = $1; } "Deletes objects matching the URL."
+
#int debug;
option (d, debug) INT "LEVEL" { $debug = $1 } "specify the debug level. Default is 1."
@@ -158,4 +166,5 @@ init { $bits = 2048; $pkcs8 = 0; $privkey = NULL; $ca=NULL; $ca_privkey = 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 = "3des"; $crq_extensions=1; $pkcs11_provider= NULL;
- $pkcs11_url = NULL; $pkcs11_type = PKCS11_TYPE_PK; $pubkey=NULL; }
+ $pkcs11_url = NULL; $pkcs11_type = PKCS11_TYPE_PK; $pubkey=NULL; $pkcs11_label = NULL;
+ $pkcs11_trusted=0; }
diff --git a/src/crypt-gaa.c b/src/crypt-gaa.c
index 8ec3b033ed..3375cf9988 100644
--- a/src/crypt-gaa.c
+++ b/src/crypt-gaa.c
@@ -389,12 +389,31 @@ static int gaa_getint(char *arg)
return tmp;
}
+static char gaa_getchar(char *arg)
+{
+ if(strlen(arg) != 1)
+ {
+ printf("Option %s: '%s' isn't an character\n", gaa_current_option, arg);
+ GAAERROR(-1);
+ }
+ return arg[0];
+}
static char* gaa_getstr(char *arg)
{
return arg;
}
-
+static float gaa_getfloat(char *arg)
+{
+ float tmp;
+ char a;
+ if(sscanf(arg, "%f%c", &tmp, &a) < 1)
+ {
+ printf("Option %s: '%s' isn't a float number\n", gaa_current_option, arg);
+ GAAERROR(-1);
+ }
+ return tmp;
+}
/* option structures */
struct GAAOPTION_create_conf
@@ -615,19 +634,16 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list)
int gaa(int argc, char **argv, gaainfo *gaaval)
{
int tmp1, tmp2;
- int l;
- size_t i, j;
+ int i, j;
char *opt_list;
- i = 0;
-
GAAargv = argv;
GAAargc = argc;
opt_list = (char*) gaa_malloc(GAA_NB_OPTION + 1);
- for(l = 0; l < GAA_NB_OPTION + 1; l++)
- opt_list[l] = 0;
+ for(i = 0; i < GAA_NB_OPTION + 1; i++)
+ opt_list[i] = 0;
/* initialization */
if(inited == 0)
{
@@ -646,27 +662,27 @@ int gaa(int argc, char **argv, gaainfo *gaaval)
gaa_arg_used = gaa_malloc(argc * sizeof(char));
}
- for(l = 1; l < argc; l++)
- gaa_arg_used[l] = 0;
- for(l = 1; l < argc; l++)
+ for(i = 1; i < argc; i++)
+ gaa_arg_used[i] = 0;
+ for(i = 1; i < argc; i++)
{
- if(gaa_arg_used[l] == 0)
+ if(gaa_arg_used[i] == 0)
{
j = 0;
- tmp1 = gaa_is_an_argument(GAAargv[l]);
+ tmp1 = gaa_is_an_argument(GAAargv[i]);
switch(tmp1)
{
case GAA_WORD_OPTION:
j++;
case GAA_LETTER_OPTION:
j++;
- tmp2 = gaa_get_option_num(argv[l]+j, tmp1);
+ tmp2 = gaa_get_option_num(argv[i]+j, tmp1);
if(tmp2 == GAA_ERROR_NOMATCH)
{
- printf("Invalid option '%s'\n", argv[l]+j);
+ printf("Invalid option '%s'\n", argv[i]+j);
return 0;
}
- switch(gaa_try(tmp2, l+1, gaaval, opt_list))
+ switch(gaa_try(tmp2, i+1, gaaval, opt_list))
{
case GAA_ERROR_NOTENOUGH_ARGS:
printf("'%s': not enough arguments\n",gaa_current_option);
@@ -679,18 +695,18 @@ int gaa(int argc, char **argv, gaainfo *gaaval)
default:
printf("Unknown error\n");
}
- gaa_arg_used[l] = 1;
+ gaa_arg_used[i] = 1;
break;
case GAA_MULTIPLE_OPTION:
- for(j = 1; j < strlen(argv[l]); j++)
+ for(j = 1; j < strlen(argv[i]); j++)
{
- tmp2 = gaa_get_option_num(argv[l]+j, tmp1);
+ tmp2 = gaa_get_option_num(argv[i]+j, tmp1);
if(tmp2 == GAA_ERROR_NOMATCH)
{
- printf("Invalid option '%c'\n", *(argv[l]+j));
+ printf("Invalid option '%c'\n", *(argv[i]+j));
return 0;
}
- switch(gaa_try(tmp2, l+1, gaaval, opt_list))
+ switch(gaa_try(tmp2, i+1, gaaval, opt_list))
{
case GAA_ERROR_NOTENOUGH_ARGS:
printf("'%s': not enough arguments\n",gaa_current_option);
@@ -704,7 +720,7 @@ int gaa(int argc, char **argv, gaainfo *gaaval)
printf("Unknown error\n");
}
}
- gaa_arg_used[l] = 1;
+ gaa_arg_used[i] = 1;
break;
default: break;
}
@@ -730,9 +746,9 @@ if(gaa_processing_file == 0)
}
#endif
}
- for(l = 1; l < argc; l++)
+ for(i = 1; i < argc; i++)
{
- if(gaa_arg_used[l] == 0)
+ if(gaa_arg_used[i] == 0)
{
printf("Too many arguments\n");
return 0;
@@ -783,7 +799,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; //a = ' ';
}
len += 1;
diff --git a/src/pkcs11.c b/src/pkcs11.c
index 500aaa3e8f..f143a87f2f 100644
--- a/src/pkcs11.c
+++ b/src/pkcs11.c
@@ -42,6 +42,28 @@ static void pkcs11_common(void)
gnutls_pkcs11_set_pin_function (pin_callback, NULL);
}
+
+void pkcs11_delete(FILE* outfile, const char* url, int batch)
+{
+int ret;
+ if (!batch) {
+ pkcs11_list(outfile, url, PKCS11_TYPE_ALL);
+ ret = read_yesno("Are you sure you want to delete those objects? (Y/N): ");
+ if (ret == 0) {
+ exit(1);
+ }
+ }
+
+ ret = gnutls_pkcs11_delete_url(url);
+ if (ret < 0) {
+ fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ fprintf(outfile, "\n%d objects deleted\n", ret);
+
+ return;
+}
/* lists certificates from a token
*/
@@ -340,7 +362,47 @@ size_t size;
}
return;
+}
+
+void pkcs11_write(FILE* outfile, const char* url, const char* label, int trusted)
+{
+gnutls_x509_crt_t xcrt;
+gnutls_x509_privkey_t xkey;
+int ret;
+unsigned int flags = 0;
+unsigned int key_usage;
+ pkcs11_common();
+
+ if (url == NULL)
+ url = "pkcs11:";
+
+ xcrt = load_cert(0);
+ if (xcrt != NULL) {
+ if (trusted)
+ flags |= GNUTLS_PKCS11_OBJ_FLAG_TRUSTED;
+ ret = gnutls_pkcs11_copy_x509_crt(url, xcrt, label, flags);
+ if (ret < 0) {
+ fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ gnutls_x509_crt_get_key_usage(xcrt, &key_usage, NULL);
+ }
+
+ xkey = load_private_key(0);
+ if (xkey != NULL) {
+ ret = gnutls_pkcs11_copy_x509_privkey(url, xkey, label, key_usage);
+ if (ret < 0) {
+ fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror(ret));
+ exit(1);
+ }
+ }
+ if (xkey == NULL && xcrt == NULL) {
+ fprintf(stderr, "You must use --load-privkey or --load-certificate to load the file to be copied\n");
+ exit (1);
+ }
+ return;
}