]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Added support to copy certificates and private keys to tokens.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 23 May 2010 12:05:32 +0000 (14:05 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Thu, 3 Jun 2010 17:54:31 +0000 (19:54 +0200)
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.

21 files changed:
lib/Makefile.am
lib/gcrypt/mpi.c
lib/gcrypt/pk.c
lib/includes/gnutls/crypto.h
lib/includes/gnutls/pkcs11.h
lib/includes/gnutls/x509.h
lib/libgnutls.map
lib/nettle/pk.c
lib/pkcs11.c
lib/pkcs11_int.h
lib/pkcs11_privkey.c
lib/pkcs11_write.c [new file with mode: 0644]
lib/x509/privkey.c
lib/x509/x509_int.h
src/certtool-common.h
src/certtool-gaa.c
src/certtool-gaa.h
src/certtool.c
src/certtool.gaa
src/crypt-gaa.c
src/pkcs11.c

index 061184035bf5640a6d8954ba4b14bf61112d95e4..12b686bb03335f52b46fdaf8a8542955b246c71d 100644 (file)
@@ -80,10 +80,9 @@ COBJECTS = gnutls_record.c gnutls_compress.c debug.c gnutls_cipher.c \
        gnutls_str.c gnutls_state.c gnutls_x509.c ext_cert_type.c       \
        gnutls_rsa_export.c auth_rsa_export.c ext_server_name.c         \
        auth_dh_common.c gnutls_helper.c gnutls_supplemental.c          \
-       crypto.c random.c pk-libgcrypt.c mpi-libgcrypt.c cryptodev.c    \
-       rnd-libgcrypt.c cipher-libgcrypt.c ext_signature.c \
-       crypto-api.c ext_safe_renegotiation.c gnutls_mbuffers.c \
-       gnutls_privkey.c pkcs11.c pkcs11_privkey.c gnutls_pubkey.c
+       crypto.c random.c cryptodev.c ext_signature.c crypto-api.c \
+       ext_safe_renegotiation.c gnutls_mbuffers.c gnutls_privkey.c pkcs11.c \
+       pkcs11_privkey.c gnutls_pubkey.c pkcs11_write.c
 
 if ENABLE_PKCS11
 COBJECTS += pkcs11.c pkcs11_privkey.c
index d45f023514fb07ce21485e14d19ee1088e71c3fb..6adbb1bc9c4d6688c1ffb48f54d33543b6aa2f59 100644 (file)
@@ -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;
index 5e0b159be60b36df6016f6fcc0d987c87e625ce1..84fedfe4aa64367e5e91a0dfcd65b7ac72ba3560 100644 (file)
@@ -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;
 }
 
 
index e2cb8f821e084071fc83444ed87d2116f27e2273..64cf7a6a198b83fd84015bca3413925c6e756200 100644 (file)
@@ -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
index c1f83bf2b09e03e6c1f51069261724089ad86848..1064c5e2ccb5c06d4b890a8dbf4ebcc2e8dc3f3a 100644 (file)
@@ -139,6 +139,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.
@@ -212,8 +220,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,
index 54ba9e27931de2755d0a86fcb75472660760bdd4..308e7057be7d771cce53d09a372f0b698233731e 100644 (file)
@@ -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,
index 256d01664c14860801873263bfa6762f0ce0f5ed..950ac595908e7d96cba42ed95320f1f1f962a319 100644 (file)
@@ -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 {
index 081c08c34c822cb72649edb9112d9fbd5f265de7..e028d9b49e02fd613af8183f840b82d4779670bc 100644 (file)
@@ -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);
                
index 21ddae53d37c0603488184571338fc29cea4d444..6b658b9b4f31ef92e0d9ef8c1e311d2c663fddde 100644 (file)
@@ -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,10 +42,6 @@ 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;
@@ -154,11 +149,7 @@ fail:
  *
  * Returns: zero on success or a negative value on error.
  **/
-<<<<<<< HEAD:lib/pkcs11.c
-int gnutls_pkcs11_crt_get_info(gnutls_pkcs11_crt_t crt, gnutls_pkcs11_cert_info_t itype,
-=======
 int gnutls_pkcs11_obj_get_info(gnutls_pkcs11_obj_t crt, gnutls_pkcs11_obj_info_t itype, 
->>>>>>> Added gnutls_pubkey_t abstract type to handle public keys. It can currently:lib/pkcs11.c
     void* output, size_t* output_size)
 {
     return pkcs11_get_info(&crt->info, itype, output, output_size);
@@ -715,8 +706,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;
+            }
 
-int _pkcs11_traverse_tokens (find_func_t find_func, void* input, int leave_session)
+            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, unsigned int flags)
 {
     ck_rv_t rv;
     int found = 0, x, z, ret;
@@ -726,20 +775,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? */
@@ -750,6 +801,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;
@@ -1046,13 +1099,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;
@@ -1068,40 +1141,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;
         }
     }
 
@@ -1115,20 +1167,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_vals = 2;
+    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 = 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++;
     }
 
@@ -1214,7 +1269,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;
@@ -1274,7 +1329,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;
@@ -1729,9 +1784,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;
@@ -1755,27 +1810,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) {
@@ -1809,47 +1864,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);
@@ -1878,6 +1955,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;
@@ -1993,7 +2071,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;
@@ -2104,25 +2182,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! */
 
@@ -2151,7 +2214,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;
index 7b8c120e9d7942df44e19346c06c01f2b19987fe..2eea03cb78512de53230faa27a0a5f6d5590ddd7 100644 (file)
@@ -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
index 2ead5ab8fbdaa3e518d2240bf503a188e85dd010..608b6e97c0fa07e02c2954204e1f694da426f4ab 100644 (file)
@@ -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 (file)
index 0000000..a8ed760
--- /dev/null
@@ -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;
+       
+}
+    
index c81e67a1617dc4e6fee4724d8146c4b8fef7470b..6d47a6504d7b4751d0863f9ad91177f6436cdbba 100644 (file)
@@ -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;
@@ -464,6 +481,37 @@ gnutls_x509_privkey_import_rsa_raw (gnutls_x509_privkey_t key,
                                    const gnutls_datum_t * p,
                                    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 ();
index f75a92479d93c30102ddbf50e332e5599093aac4..f4f17adb5f8e9b9e148e9eafc58aca38e6d560ea 100644 (file)
@@ -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
index f5db0abd80f4c46f6ff3b2febf8e5803465cacd7..79d2300471ebd1aaf78fe452bfa50d80f86f015d 100644 (file)
@@ -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);
index d353489fec42a79c0d3db7ada7242280e6cba175..fae02faa53feaced88c79874f66ef46db6f0d24d 100644 (file)
@@ -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 148 "certtool.gaa"
+#line 156 "certtool.gaa"
        int debug;
+#line 151 "certtool.gaa"
+       int pkcs11_trusted;
+#line 148 "certtool.gaa"
+       char* pkcs11_label;
 #line 141 "certtool.gaa"
        int pkcs11_type;
 #line 138 "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,49 +574,67 @@ struct GAAOPTION_debug
        int size1;
 };
 
-struct GAAOPTION_pkcs11_export_url
+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_provider
+struct GAAOPTION_pkcs11_export_url 
 {
        char* arg1;
        int size1;
 };
 
-struct GAAOPTION_pkcs_cipher
+struct GAAOPTION_pkcs11_provider 
 {
        char* arg1;
        int size1;
 };
 
-struct GAAOPTION_template
+struct GAAOPTION_pkcs_cipher 
 {
        char* arg1;
        int size1;
 };
 
-struct GAAOPTION_infile
+struct GAAOPTION_template 
 {
        char* arg1;
        int size1;
 };
 
-struct GAAOPTION_outfile
+struct GAAOPTION_infile 
 {
        char* arg1;
        int size1;
 };
 
-struct GAAOPTION_bits
+struct GAAOPTION_outfile 
+{
+       char* arg1;
+       int size1;
+};
+
+struct GAAOPTION_bits 
 {
        int arg1;
        int size1;
 };
 
-struct GAAOPTION_hash
+struct GAAOPTION_hash 
 {
        char* arg1;
        int size1;
@@ -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 153 "certtool.gaa"
+#line 161 "certtool.gaa"
 { certtool_version(); exit(0); ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_help:
        OK = 0;
-#line 151 "certtool.gaa"
+#line 159 "certtool.gaa"
 { gaa_help(); exit(0); ;};
 
                return GAA_OK;
@@ -870,9 +911,46 @@ 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 149 "certtool.gaa"
+#line 157 "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 154 "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 152 "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 150 "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 149 "certtool.gaa"
+{ gaaval->action = ACTION_PKCS11_WRITE_URL; gaaval->pkcs11_url = GAATMP_pkcs11_write.arg1; ;};
+
                return GAA_OK;
                break;
        case GAAOPTID_pkcs11_list_tokens:
@@ -1329,13 +1407,14 @@ int gaa(int argc, char **argv, gaainfo *gaaval)
     if(inited == 0)
     {
 
-#line 155 "certtool.gaa"
+#line 163 "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;
index b96924aa61c2ccb03e2400ed994446b608ab5a9a..8cda5acc1b2f0891fe3fcc856c09430eb811c9a2 100644 (file)
@@ -8,8 +8,12 @@ typedef struct _gaainfo gaainfo;
 
 struct _gaainfo
 {
-#line 148 "certtool.gaa"
+#line 156 "certtool.gaa"
        int debug;
+#line 151 "certtool.gaa"
+       int pkcs11_trusted;
+#line 148 "certtool.gaa"
+       char* pkcs11_label;
 #line 141 "certtool.gaa"
        int pkcs11_type;
 #line 138 "certtool.gaa"
index 075f19c8402d97c1abe79a6f6826db28545e65d1..b646453c50b4ca40836fdacdd2f6a851cf0d30be 100644 (file)
@@ -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 ();
index 0ce49aaea5b4309595ed44655002bf8c6237e7f1..9a835ad3ab427fb11cf797e95b23f35749d73cb4 100644 (file)
@@ -145,6 +145,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."
 
@@ -157,4 +165,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; }
index 8ec3b033ed3269625d93e1853dfa11cf17d0653f..3375cf998870e3ca77cfa10da00fb5f6e68fd8dd 100644 (file)
@@ -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;
index be996417777b9a94750e46cb8f2b8250493c5edc..c27dd03e252bd8c09e8504d81e55b7db76200b5c 100644 (file)
@@ -44,6 +44,28 @@ static void pkcs11_common(void)
 
 }
 
+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
  */
 void pkcs11_list( FILE* outfile, const char* url, int type)
@@ -340,6 +362,15 @@ 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;
 
 }
 
@@ -512,6 +543,10 @@ size_t size;
 
        return;
 
+       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;
 }