From: Nikos Mavrogiannopoulos Date: Mon, 28 Jun 2010 16:07:01 +0000 (+0200) Subject: Allow flags when importing objects from PKCS11 URLs. The only flag supported X-Git-Tag: gnutls_2_11_3~141 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=21e200fdfe407108ff58b8a26a2f827bf0bf38d3;p=thirdparty%2Fgnutls.git Allow flags when importing objects from PKCS11 URLs. The only flag supported now is the PKCS11_OBJ_FLAG_LOGIN, which forces login before accessing object on a token. The reason is that some tokens do not allow access of any data without login. --- diff --git a/doc/examples/ex-cert-select-pkcs11.c b/doc/examples/ex-cert-select-pkcs11.c index 741afd3ed0..8ff4d2ec3b 100644 --- a/doc/examples/ex-cert-select-pkcs11.c +++ b/doc/examples/ex-cert-select-pkcs11.c @@ -50,7 +50,13 @@ load_keys (void) gnutls_x509_crt_init (&crt); - ret = gnutls_x509_crt_import_pkcs11_url (crt, CERT_URL); + ret = gnutls_x509_crt_import_pkcs11_url (crt, CERT_URL, 0); + + /* some tokens require login to read data */ + if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) + ret = gnutls_x509_crt_import_pkcs11_url (crt, CERT_URL, + GNUTLS_PKCS11_OBJ_FLAG_LOGIN); + if (ret < 0) { fprintf (stderr, "*** Error loading key file: %s\n", diff --git a/lib/gnutls_pubkey.c b/lib/gnutls_pubkey.c index 58f93b17a2..46d846963a 100644 --- a/lib/gnutls_pubkey.c +++ b/lib/gnutls_pubkey.c @@ -735,7 +735,21 @@ int gnutls_pubkey_set_key_usage(gnutls_pubkey_t key, unsigned int usage) return 0; } -int gnutls_pubkey_import_pkcs11_url(gnutls_pubkey_t key, const char *url) +/** + * gnutls_pubkey_import_pkcs11_url: + * @key: A key of type #gnutls_pubkey_t + * @url: A PKCS 11 url + * @flags: One of GNUTLS_PKCS11_OBJ_* flags + * + * This function will import a PKCS 11 certificate to a #gnutls_pubkey_t + * structure. + * + * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a + * negative error value. + **/ + +int gnutls_pubkey_import_pkcs11_url(gnutls_pubkey_t key, const char *url, + unsigned int flags) { gnutls_pkcs11_obj_t pcrt; int ret; @@ -746,7 +760,7 @@ int gnutls_pubkey_import_pkcs11_url(gnutls_pubkey_t key, const char *url) return ret; } - ret = gnutls_pkcs11_obj_import_url(pcrt, url); + ret = gnutls_pkcs11_obj_import_url(pcrt, url, flags); if (ret < 0) { gnutls_assert(); goto cleanup; diff --git a/lib/gnutls_x509.c b/lib/gnutls_x509.c index 5d44359b89..996c487edd 100644 --- a/lib/gnutls_x509.c +++ b/lib/gnutls_x509.c @@ -569,7 +569,8 @@ gnutls_x509_crt_t * xcrt_list = NULL; gnutls_pkcs11_obj_t *pcrt_list=NULL; unsigned int pcrt_list_size = 0; - ret = gnutls_pkcs11_obj_list_import_url( NULL, &pcrt_list_size, url, GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED); + /* FIXME: should we use login? */ + ret = gnutls_pkcs11_obj_list_import_url( NULL, &pcrt_list_size, url, GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED, 0); if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) { gnutls_assert(); return ret; @@ -586,7 +587,7 @@ unsigned int pcrt_list_size = 0; return GNUTLS_E_MEMORY_ERROR; } - ret = gnutls_pkcs11_obj_list_import_url( pcrt_list, &pcrt_list_size, url, GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED); + ret = gnutls_pkcs11_obj_list_import_url( pcrt_list, &pcrt_list_size, url, GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED, 0); if (ret < 0) { gnutls_assert(); goto cleanup; @@ -645,7 +646,10 @@ gnutls_cert * ccert; return ret; } - ret = gnutls_x509_crt_import_pkcs11_url(crt, url); + ret = gnutls_x509_crt_import_pkcs11_url(crt, url, 0); + if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) + ret = gnutls_x509_crt_import_pkcs11_url(crt, url, GNUTLS_PKCS11_OBJ_FLAG_LOGIN); + if (ret < 0) { gnutls_assert(); diff --git a/lib/includes/gnutls/abstract.h b/lib/includes/gnutls/abstract.h index 77e7994a5e..6eed91dfce 100644 --- a/lib/includes/gnutls/abstract.h +++ b/lib/includes/gnutls/abstract.h @@ -48,7 +48,8 @@ int gnutls_pubkey_import (gnutls_pubkey_t key, gnutls_x509_crt_fmt_t format); -int gnutls_pubkey_import_pkcs11_url( gnutls_pubkey_t key, const char* url); +int gnutls_pubkey_import_pkcs11_url( gnutls_pubkey_t key, const char* url, + unsigned int flags/* GNUTLS_PKCS11_OBJ_FLAG_* */); int gnutls_pubkey_import_dsa_raw (gnutls_pubkey_t key, const gnutls_datum_t * p, const gnutls_datum_t * q, diff --git a/lib/includes/gnutls/pkcs11.h b/lib/includes/gnutls/pkcs11.h index 80e4b42a11..e7ae57a5b7 100644 --- a/lib/includes/gnutls/pkcs11.h +++ b/lib/includes/gnutls/pkcs11.h @@ -48,19 +48,24 @@ void gnutls_pkcs11_set_pin_function (gnutls_pkcs11_pin_callback_t callback, void int gnutls_pkcs11_add_provider (const char * name, const char * params); int gnutls_pkcs11_obj_init ( gnutls_pkcs11_obj_t *certificate); -int gnutls_pkcs11_obj_import_url (gnutls_pkcs11_obj_t, const char * url); +#define GNUTLS_PKCS11_OBJ_FLAG_LOGIN 1 /* force login in the token for the operation */ + +int gnutls_pkcs11_obj_import_url (gnutls_pkcs11_obj_t, const char * url, + unsigned int flags/* GNUTLS_PKCS11_OBJ_FLAG_* */); int gnutls_pkcs11_obj_export_url (gnutls_pkcs11_obj_t, char** url); void gnutls_pkcs11_obj_deinit ( gnutls_pkcs11_obj_t); int gnutls_pkcs11_obj_export(gnutls_pkcs11_obj_t obj, void *output_data, size_t * output_data_size); -#define GNUTLS_PKCS11_OBJ_FLAG_TRUSTED 1 /* object marked as trusted */ + +#define GNUTLS_PKCS11_COPY_FLAG_MARK_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_* */); + const char* label, unsigned int flags /* GNUTLS_PKCS11_COPY_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_* */); + gnutls_x509_privkey_t crt, const char* label, unsigned int key_usage /*GNUTLS_KEY_* */, + unsigned int flags /* GNUTLS_PKCS11_COPY_FLAG_* */); int gnutls_pkcs11_delete_url(const char* object_url); typedef enum { @@ -107,10 +112,14 @@ int gnutls_pkcs11_token_get_info(const char* url, gnutls_pkcs11_token_info_t, vo #define GNUTLS_PKCS11_TOKEN_HW 1 int gnutls_pkcs11_token_get_flags(const char* url, unsigned int *flags); -int gnutls_pkcs11_obj_list_import_url (gnutls_pkcs11_obj_t * p_list, unsigned int *const n_list, const char* url, gnutls_pkcs11_obj_attr_t flags); +int gnutls_pkcs11_obj_list_import_url (gnutls_pkcs11_obj_t * p_list, + unsigned int *const n_list, const char* url, + gnutls_pkcs11_obj_attr_t attrs, + unsigned int flags/* GNUTLS_PKCS11_OBJ_FLAG_* */); int gnutls_x509_crt_import_pkcs11( gnutls_x509_crt_t crt, gnutls_pkcs11_obj_t pkcs11_crt); -int gnutls_x509_crt_import_pkcs11_url( gnutls_x509_crt_t crt, const char* url); +int gnutls_x509_crt_import_pkcs11_url( gnutls_x509_crt_t crt, const char* url, + unsigned int flags/* GNUTLS_PKCS11_OBJ_FLAG_* */); gnutls_pkcs11_obj_type_t gnutls_pkcs11_obj_get_type (gnutls_pkcs11_obj_t certificate); const char* gnutls_pkcs11_type_get_name (gnutls_pkcs11_obj_type_t); @@ -118,7 +127,7 @@ const char* gnutls_pkcs11_type_get_name (gnutls_pkcs11_obj_type_t); int gnutls_x509_crt_list_import_pkcs11 (gnutls_x509_crt_t * certs, unsigned int cert_max, gnutls_pkcs11_obj_t * const pkcs11_certs, - unsigned int flags); + unsigned int flags/* must be zero */); /* private key functions...*/ diff --git a/lib/pkcs11.c b/lib/pkcs11.c index ebe4846d1b..ed70073df8 100644 --- a/lib/pkcs11.c +++ b/lib/pkcs11.c @@ -37,26 +37,26 @@ #define MAX_CERT_SIZE 8*1024 struct gnutls_pkcs11_provider_s { - pakchois_module_t *module; - unsigned long nslots; - ck_slot_id_t *slots; + pakchois_module_t *module; + unsigned long nslots; + ck_slot_id_t *slots; }; struct flags_find_data_st { - struct pkcs11_url_info info; - unsigned int slot_flags; + struct pkcs11_url_info info; + unsigned int slot_flags; }; struct url_find_data_st { - gnutls_pkcs11_obj_t crt; + gnutls_pkcs11_obj_t crt; }; struct crt_find_data_st { - gnutls_pkcs11_obj_t *p_list; - unsigned int* n_list; - unsigned int current; - gnutls_pkcs11_obj_attr_t flags; - struct pkcs11_url_info info; + gnutls_pkcs11_obj_t *p_list; + unsigned int *n_list; + unsigned int current; + gnutls_pkcs11_obj_attr_t flags; + struct pkcs11_url_info info; }; @@ -64,102 +64,103 @@ static struct gnutls_pkcs11_provider_s providers[MAX_PROVIDERS]; static int active_providers = 0; static gnutls_pkcs11_pin_callback_t pin_func; -static void* pin_data; +static void *pin_data; gnutls_pkcs11_token_callback_t token_func; -void* token_data; +void *token_data; int pkcs11_rv_to_err(ck_rv_t rv) { - switch(rv) { - case CKR_OK: - return 0; - case CKR_HOST_MEMORY: - return GNUTLS_E_MEMORY_ERROR; - case CKR_SLOT_ID_INVALID: - return GNUTLS_E_PKCS11_SLOT_ERROR; - case CKR_ARGUMENTS_BAD: - case CKR_MECHANISM_PARAM_INVALID: - return GNUTLS_E_INVALID_REQUEST; - case CKR_NEED_TO_CREATE_THREADS: - case CKR_CANT_LOCK: - case CKR_FUNCTION_NOT_PARALLEL: - case CKR_MUTEX_BAD: - case CKR_MUTEX_NOT_LOCKED: - return GNUTLS_E_LOCKING_ERROR; - case CKR_ATTRIBUTE_READ_ONLY: - case CKR_ATTRIBUTE_SENSITIVE: - case CKR_ATTRIBUTE_TYPE_INVALID: - case CKR_ATTRIBUTE_VALUE_INVALID: - return GNUTLS_E_PKCS11_ATTRIBUTE_ERROR; - case CKR_DEVICE_ERROR: - case CKR_DEVICE_MEMORY: - case CKR_DEVICE_REMOVED: - return GNUTLS_E_PKCS11_DEVICE_ERROR; - case CKR_DATA_INVALID: - case CKR_DATA_LEN_RANGE: - case CKR_ENCRYPTED_DATA_INVALID: - case CKR_ENCRYPTED_DATA_LEN_RANGE: - case CKR_OBJECT_HANDLE_INVALID: - return GNUTLS_E_PKCS11_DATA_ERROR; - case CKR_FUNCTION_NOT_SUPPORTED: - case CKR_MECHANISM_INVALID: - return GNUTLS_E_PKCS11_UNSUPPORTED_FEATURE_ERROR; - case CKR_KEY_HANDLE_INVALID: - case CKR_KEY_SIZE_RANGE: - case CKR_KEY_TYPE_INCONSISTENT: - case CKR_KEY_NOT_NEEDED: - case CKR_KEY_CHANGED: - case CKR_KEY_NEEDED: - case CKR_KEY_INDIGESTIBLE: - case CKR_KEY_FUNCTION_NOT_PERMITTED: - case CKR_KEY_NOT_WRAPPABLE: - case CKR_KEY_UNEXTRACTABLE: - return GNUTLS_E_PKCS11_KEY_ERROR; - case CKR_PIN_INCORRECT: - case CKR_PIN_INVALID: - case CKR_PIN_LEN_RANGE: - return GNUTLS_E_PKCS11_PIN_ERROR; - case CKR_PIN_EXPIRED: - return GNUTLS_E_PKCS11_PIN_EXPIRED; - case CKR_PIN_LOCKED: - return GNUTLS_E_PKCS11_PIN_LOCKED; - case CKR_SESSION_CLOSED: - case CKR_SESSION_COUNT: - case CKR_SESSION_HANDLE_INVALID: - case CKR_SESSION_PARALLEL_NOT_SUPPORTED: - case CKR_SESSION_READ_ONLY: - case CKR_SESSION_EXISTS: - case CKR_SESSION_READ_ONLY_EXISTS: - case CKR_SESSION_READ_WRITE_SO_EXISTS: - return GNUTLS_E_PKCS11_SESSION_ERROR; - case CKR_SIGNATURE_INVALID: - case CKR_SIGNATURE_LEN_RANGE: - return GNUTLS_E_PKCS11_SIGNATURE_ERROR; - case CKR_TOKEN_NOT_PRESENT: - case CKR_TOKEN_NOT_RECOGNIZED: - case CKR_TOKEN_WRITE_PROTECTED: - return GNUTLS_E_PKCS11_TOKEN_ERROR; - case CKR_USER_ALREADY_LOGGED_IN: - case CKR_USER_NOT_LOGGED_IN: - case CKR_USER_PIN_NOT_INITIALIZED: - case CKR_USER_TYPE_INVALID: - case CKR_USER_ANOTHER_ALREADY_LOGGED_IN: - case CKR_USER_TOO_MANY_TYPES: - return GNUTLS_E_PKCS11_USER_ERROR; - case CKR_BUFFER_TOO_SMALL: - return GNUTLS_E_SHORT_MEMORY_BUFFER; - default: - return GNUTLS_E_PKCS11_ERROR; - } + switch (rv) { + case CKR_OK: + return 0; + case CKR_HOST_MEMORY: + return GNUTLS_E_MEMORY_ERROR; + case CKR_SLOT_ID_INVALID: + return GNUTLS_E_PKCS11_SLOT_ERROR; + case CKR_ARGUMENTS_BAD: + case CKR_MECHANISM_PARAM_INVALID: + return GNUTLS_E_INVALID_REQUEST; + case CKR_NEED_TO_CREATE_THREADS: + case CKR_CANT_LOCK: + case CKR_FUNCTION_NOT_PARALLEL: + case CKR_MUTEX_BAD: + case CKR_MUTEX_NOT_LOCKED: + return GNUTLS_E_LOCKING_ERROR; + case CKR_ATTRIBUTE_READ_ONLY: + case CKR_ATTRIBUTE_SENSITIVE: + case CKR_ATTRIBUTE_TYPE_INVALID: + case CKR_ATTRIBUTE_VALUE_INVALID: + return GNUTLS_E_PKCS11_ATTRIBUTE_ERROR; + case CKR_DEVICE_ERROR: + case CKR_DEVICE_MEMORY: + case CKR_DEVICE_REMOVED: + return GNUTLS_E_PKCS11_DEVICE_ERROR; + case CKR_DATA_INVALID: + case CKR_DATA_LEN_RANGE: + case CKR_ENCRYPTED_DATA_INVALID: + case CKR_ENCRYPTED_DATA_LEN_RANGE: + case CKR_OBJECT_HANDLE_INVALID: + return GNUTLS_E_PKCS11_DATA_ERROR; + case CKR_FUNCTION_NOT_SUPPORTED: + case CKR_MECHANISM_INVALID: + return GNUTLS_E_PKCS11_UNSUPPORTED_FEATURE_ERROR; + case CKR_KEY_HANDLE_INVALID: + case CKR_KEY_SIZE_RANGE: + case CKR_KEY_TYPE_INCONSISTENT: + case CKR_KEY_NOT_NEEDED: + case CKR_KEY_CHANGED: + case CKR_KEY_NEEDED: + case CKR_KEY_INDIGESTIBLE: + case CKR_KEY_FUNCTION_NOT_PERMITTED: + case CKR_KEY_NOT_WRAPPABLE: + case CKR_KEY_UNEXTRACTABLE: + return GNUTLS_E_PKCS11_KEY_ERROR; + case CKR_PIN_INCORRECT: + case CKR_PIN_INVALID: + case CKR_PIN_LEN_RANGE: + return GNUTLS_E_PKCS11_PIN_ERROR; + case CKR_PIN_EXPIRED: + return GNUTLS_E_PKCS11_PIN_EXPIRED; + case CKR_PIN_LOCKED: + return GNUTLS_E_PKCS11_PIN_LOCKED; + case CKR_SESSION_CLOSED: + case CKR_SESSION_COUNT: + case CKR_SESSION_HANDLE_INVALID: + case CKR_SESSION_PARALLEL_NOT_SUPPORTED: + case CKR_SESSION_READ_ONLY: + case CKR_SESSION_EXISTS: + case CKR_SESSION_READ_ONLY_EXISTS: + case CKR_SESSION_READ_WRITE_SO_EXISTS: + return GNUTLS_E_PKCS11_SESSION_ERROR; + case CKR_SIGNATURE_INVALID: + case CKR_SIGNATURE_LEN_RANGE: + return GNUTLS_E_PKCS11_SIGNATURE_ERROR; + case CKR_TOKEN_NOT_PRESENT: + case CKR_TOKEN_NOT_RECOGNIZED: + case CKR_TOKEN_WRITE_PROTECTED: + return GNUTLS_E_PKCS11_TOKEN_ERROR; + case CKR_USER_ALREADY_LOGGED_IN: + case CKR_USER_NOT_LOGGED_IN: + case CKR_USER_PIN_NOT_INITIALIZED: + case CKR_USER_TYPE_INVALID: + case CKR_USER_ANOTHER_ALREADY_LOGGED_IN: + case CKR_USER_TOO_MANY_TYPES: + return GNUTLS_E_PKCS11_USER_ERROR; + case CKR_BUFFER_TOO_SMALL: + return GNUTLS_E_SHORT_MEMORY_BUFFER; + default: + return GNUTLS_E_PKCS11_ERROR; + } } /* Fake scan */ void pkcs11_rescan_slots(void) { -unsigned long slots; + unsigned long slots; - pakchois_get_slot_list(providers[active_providers-1].module, 0, NULL, &slots); + pakchois_get_slot_list(providers[active_providers - 1].module, 0, + NULL, &slots); } /** @@ -174,48 +175,58 @@ unsigned long slots; * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. **/ -int gnutls_pkcs11_add_provider (const char * name, const char * params) +int gnutls_pkcs11_add_provider(const char *name, const char *params) { - if (active_providers >= MAX_PROVIDERS) { - gnutls_assert(); - return GNUTLS_E_CONSTRAINT_ERROR; - } - - active_providers++; - if (pakchois_module_load_abs(&providers[active_providers-1].module, name) != CKR_OK) { - gnutls_assert(); - _gnutls_debug_log("p11: Cannot load provider %s\n", name); - active_providers--; - return GNUTLS_E_PKCS11_LOAD_ERROR; - } - - /* cache the number of slots in this module */ - if (pakchois_get_slot_list(providers[active_providers-1].module, 0, NULL, &providers[active_providers-1].nslots) != CKR_OK) { - gnutls_assert(); - goto fail; - } - - providers[active_providers-1].slots = gnutls_malloc(sizeof(*providers[active_providers-1].slots)*providers[active_providers-1].nslots); - if (providers[active_providers-1].slots==NULL) { - gnutls_assert(); - goto fail; - } - - if (pakchois_get_slot_list(providers[active_providers-1].module, 0, providers[active_providers-1].slots, &providers[active_providers-1].nslots) != CKR_OK) { - gnutls_assert(); - gnutls_free(providers[active_providers-1].slots); - goto fail; - } - - _gnutls_debug_log("p11: loaded provider '%s' with %d slots\n", name, (int)providers[active_providers-1].nslots); - - return 0; - -fail: - pakchois_module_destroy(providers[active_providers-1].module); - active_providers--; - return GNUTLS_E_PKCS11_LOAD_ERROR; + if (active_providers >= MAX_PROVIDERS) { + gnutls_assert(); + return GNUTLS_E_CONSTRAINT_ERROR; + } + + active_providers++; + if (pakchois_module_load_abs + (&providers[active_providers - 1].module, name) != CKR_OK) { + gnutls_assert(); + _gnutls_debug_log("p11: Cannot load provider %s\n", name); + active_providers--; + return GNUTLS_E_PKCS11_LOAD_ERROR; + } + + /* cache the number of slots in this module */ + if (pakchois_get_slot_list + (providers[active_providers - 1].module, 0, NULL, + &providers[active_providers - 1].nslots) != CKR_OK) { + gnutls_assert(); + goto fail; + } + + providers[active_providers - 1].slots = + gnutls_malloc(sizeof(*providers[active_providers - 1].slots) * + providers[active_providers - 1].nslots); + if (providers[active_providers - 1].slots == NULL) { + gnutls_assert(); + goto fail; + } + + if (pakchois_get_slot_list + (providers[active_providers - 1].module, 0, + providers[active_providers - 1].slots, + &providers[active_providers - 1].nslots) != CKR_OK) { + gnutls_assert(); + gnutls_free(providers[active_providers - 1].slots); + goto fail; + } + + _gnutls_debug_log("p11: loaded provider '%s' with %d slots\n", + name, + (int) providers[active_providers - 1].nslots); + + return 0; + + fail: + pakchois_module_destroy(providers[active_providers - 1].module); + active_providers--; + return GNUTLS_E_PKCS11_LOAD_ERROR; } @@ -234,63 +245,67 @@ fail: * * Returns: zero on success or a negative value on error. **/ -int gnutls_pkcs11_obj_get_info(gnutls_pkcs11_obj_t crt, gnutls_pkcs11_obj_info_t itype, - void* output, size_t* output_size) +int gnutls_pkcs11_obj_get_info(gnutls_pkcs11_obj_t crt, + gnutls_pkcs11_obj_info_t itype, + void *output, size_t * output_size) { - return pkcs11_get_info(&crt->info, itype, output, output_size); + return pkcs11_get_info(&crt->info, itype, output, output_size); } -int pkcs11_get_info(struct pkcs11_url_info *info, gnutls_pkcs11_obj_info_t itype, - void* output, size_t* output_size) +int pkcs11_get_info(struct pkcs11_url_info *info, + gnutls_pkcs11_obj_info_t itype, void *output, + size_t * output_size) { - const char* str = NULL; - size_t len; - - switch(itype) { - case GNUTLS_PKCS11_OBJ_ID: - if (*output_size < info->certid_raw_size) { - *output_size = info->certid_raw_size; - return GNUTLS_E_SHORT_MEMORY_BUFFER; - } - if (output) memcpy(output, info->certid_raw, info->certid_raw_size); - *output_size = info->certid_raw_size; - - return 0; - case GNUTLS_PKCS11_OBJ_ID_HEX: - str = info->id; - break; - case GNUTLS_PKCS11_OBJ_LABEL: - str = info->label; - break; - case GNUTLS_PKCS11_OBJ_TOKEN_LABEL: - str = info->token; - break; - case GNUTLS_PKCS11_OBJ_TOKEN_SERIAL: - str = info->serial; - break; - case GNUTLS_PKCS11_OBJ_TOKEN_MANUFACTURER: - str = info->manufacturer; - break; - case GNUTLS_PKCS11_OBJ_TOKEN_MODEL: - str = info->model; - break; - default: - gnutls_assert(); - return GNUTLS_E_INVALID_REQUEST; - } - - len = strlen(str); - - if (len+1>*output_size) { - *output_size = len+1; - return GNUTLS_E_SHORT_MEMORY_BUFFER; - } - - strcpy(output, str); - - *output_size = len; - - return 0; + const char *str = NULL; + size_t len; + + switch (itype) { + case GNUTLS_PKCS11_OBJ_ID: + if (*output_size < info->certid_raw_size) { + *output_size = info->certid_raw_size; + return GNUTLS_E_SHORT_MEMORY_BUFFER; + } + if (output) + memcpy(output, info->certid_raw, + info->certid_raw_size); + *output_size = info->certid_raw_size; + + return 0; + case GNUTLS_PKCS11_OBJ_ID_HEX: + str = info->id; + break; + case GNUTLS_PKCS11_OBJ_LABEL: + str = info->label; + break; + case GNUTLS_PKCS11_OBJ_TOKEN_LABEL: + str = info->token; + break; + case GNUTLS_PKCS11_OBJ_TOKEN_SERIAL: + str = info->serial; + break; + case GNUTLS_PKCS11_OBJ_TOKEN_MANUFACTURER: + str = info->manufacturer; + break; + case GNUTLS_PKCS11_OBJ_TOKEN_MODEL: + str = info->model; + break; + default: + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + len = strlen(str); + + if (len + 1 > *output_size) { + *output_size = len + 1; + return GNUTLS_E_SHORT_MEMORY_BUFFER; + } + + strcpy(output, str); + + *output_size = len; + + return 0; } static int init = 0; @@ -312,57 +327,62 @@ static int init = 0; * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. **/ -int gnutls_pkcs11_init(unsigned int flags, const char* configfile) +int gnutls_pkcs11_init(unsigned int flags, const char *configfile) { - int ret; - - if (init != 0) { - init++; - return 0; - } - init++; - - if (flags == GNUTLS_PKCS11_FLAG_MANUAL) - return 0; - else { - FILE *fp; - char line[512]; - const char* library; - - if (configfile == NULL) - configfile = "/etc/gnutls/pkcs11.conf"; - - fp = fopen(configfile, "r"); - if (fp == NULL) { - gnutls_assert(); - _gnutls_debug_log("Cannot load %s\n", configfile); - return GNUTLS_E_FILE_ERROR; - } - - while (fgets (line, sizeof (line), fp) != NULL) { - if (strncmp(line, "load", sizeof("load")-1) == 0) { - char* p; - p = strchr(line, '='); - if (p==NULL) continue; - - library = ++p; - - p = strchr(line, '\n'); - if (p!=NULL) { - *p=0; - } - - ret = gnutls_pkcs11_add_provider(library, NULL); - if (ret < 0) { - gnutls_assert(); - _gnutls_debug_log("Cannot load provider: %s\n", library); - continue; - } - } - } - } - - return 0; + int ret; + + if (init != 0) { + init++; + return 0; + } + init++; + + if (flags == GNUTLS_PKCS11_FLAG_MANUAL) + return 0; + else { + FILE *fp; + char line[512]; + const char *library; + + if (configfile == NULL) + configfile = "/etc/gnutls/pkcs11.conf"; + + fp = fopen(configfile, "r"); + if (fp == NULL) { + gnutls_assert(); + _gnutls_debug_log("Cannot load %s\n", configfile); + return GNUTLS_E_FILE_ERROR; + } + + while (fgets(line, sizeof(line), fp) != NULL) { + if (strncmp(line, "load", sizeof("load") - 1) == 0) { + char *p; + p = strchr(line, '='); + if (p == NULL) + continue; + + library = ++p; + + p = strchr(line, '\n'); + if (p != NULL) { + *p = 0; + } + + ret = + gnutls_pkcs11_add_provider(library, + NULL); + if (ret < 0) { + gnutls_assert(); + _gnutls_debug_log + ("Cannot load provider: %s\n", + library); + continue; + } + } + } + } + + return 0; } /** @@ -371,23 +391,22 @@ int gnutls_pkcs11_init(unsigned int flags, const char* configfile) * This function will deinitialize the PKCS 11 subsystem in gnutls. * **/ -void gnutls_pkcs11_deinit (void) +void gnutls_pkcs11_deinit(void) { - int i; - - init--; - if (init > 0) - return; - if (init < 0) - { - init = 0; - return; - } - - for (i=0;i 0) + return; + if (init < 0) { + init = 0; + return; + } + + for (i = 0; i < active_providers; i++) { + pakchois_module_destroy(providers[i].module); + } + active_providers = 0; } /** @@ -424,10 +443,10 @@ void gnutls_pkcs11_deinit (void) * negative error value. **/ void gnutls_pkcs11_set_pin_function(gnutls_pkcs11_pin_callback_t fn, - void *userdata) + void *userdata) { - pin_func = fn; - pin_data = userdata; + pin_func = fn; + pin_data = userdata; } /** @@ -442,283 +461,292 @@ void gnutls_pkcs11_set_pin_function(gnutls_pkcs11_pin_callback_t fn, * negative error value. **/ void gnutls_pkcs11_set_token_function(gnutls_pkcs11_token_callback_t fn, - void *userdata) + void *userdata) { - token_func = fn; - token_data = userdata; + token_func = fn; + token_data = userdata; } -static int unescape_string (char* output, const char* input, size_t* size, char terminator) +static int unescape_string(char *output, const char *input, size_t * size, + char terminator) { - gnutls_buffer_st str; - int ret = 0; - char* p; - int len; - - _gnutls_buffer_init(&str); - - /* find terminator */ - p = strchr(input, terminator); - if (p!=NULL) - len = p-input; - else - len = strlen(input); - - ret = _gnutls_buffer_append_data(&str, input, len); - if (ret < 0) { - gnutls_assert(); - return ret; - } - - ret = _gnutls_buffer_unescape(&str); - if (ret < 0) { - gnutls_assert(); - return ret; - } - - ret = _gnutls_buffer_append_data(&str, "", 1); - if (ret < 0) { - gnutls_assert(); - return ret; - } - - _gnutls_buffer_pop_data(&str, output, size); - - _gnutls_buffer_clear(&str); - - return ret; -} + gnutls_buffer_st str; + int ret = 0; + char *p; + int len; + + _gnutls_buffer_init(&str); + + /* find terminator */ + p = strchr(input, terminator); + if (p != NULL) + len = p - input; + else + len = strlen(input); + + ret = _gnutls_buffer_append_data(&str, input, len); + if (ret < 0) { + gnutls_assert(); + return ret; + } -int pkcs11_url_to_info(const char* url, struct pkcs11_url_info* info) -{ -int ret; -char* p1, *p2; -size_t l; + ret = _gnutls_buffer_unescape(&str); + if (ret < 0) { + gnutls_assert(); + return ret; + } - memset( info, 0, sizeof(*info)); + ret = _gnutls_buffer_append_data(&str, "", 1); + if (ret < 0) { + gnutls_assert(); + return ret; + } - if (strstr(url, "pkcs11:")==NULL) { - ret = GNUTLS_E_PARSING_ERROR; - goto cleanup; - } + _gnutls_buffer_pop_data(&str, output, size); - if ((p1=strstr(url, "manufacturer="))!= NULL) { - p1+=sizeof("manufacturer=")-1; - l=sizeof (info->manufacturer); + _gnutls_buffer_clear(&str); - ret = unescape_string(info->manufacturer, p1, &l, ';'); - if (ret < 0) { - goto cleanup; - } - } + return ret; +} - if ((p1=strstr(url, "token="))!= NULL) { - p1+=sizeof("token=")-1; - l=sizeof (info->token); +int pkcs11_url_to_info(const char *url, struct pkcs11_url_info *info) +{ + int ret; + char *p1, *p2; + size_t l; - ret = unescape_string(info->token, p1, &l, ';'); - if (ret < 0) { - goto cleanup; - } - } + memset(info, 0, sizeof(*info)); - if ((p1=strstr(url, "object="))!= NULL) { - p1+=sizeof("object=")-1; - l=sizeof (info->label); + if (strstr(url, "pkcs11:") == NULL) { + ret = GNUTLS_E_PARSING_ERROR; + goto cleanup; + } - ret = unescape_string(info->label, p1, &l, ';'); - if (ret < 0) { - goto cleanup; - } - } + if ((p1 = strstr(url, "manufacturer=")) != NULL) { + p1 += sizeof("manufacturer=") - 1; + l = sizeof(info->manufacturer); - if ((p1=strstr(url, "serial="))!= NULL) { - p1+=sizeof("serial=")-1; - l=sizeof (info->serial); + ret = unescape_string(info->manufacturer, p1, &l, ';'); + if (ret < 0) { + goto cleanup; + } + } - ret = unescape_string (info->serial, p1, &l, ';'); - if (ret < 0) { - goto cleanup; - } - } + if ((p1 = strstr(url, "token=")) != NULL) { + p1 += sizeof("token=") - 1; + l = sizeof(info->token); - if ((p1=strstr(url, "model="))!= NULL) { - p1+=sizeof("model=")-1; - l=sizeof (info->model); + ret = unescape_string(info->token, p1, &l, ';'); + if (ret < 0) { + goto cleanup; + } + } - ret = unescape_string (info->model, - p1, &l, ';'); - if (ret < 0) { - goto cleanup; - } - } + if ((p1 = strstr(url, "object=")) != NULL) { + p1 += sizeof("object=") - 1; + l = sizeof(info->label); - if ((p1=strstr(url, "objecttype="))!= NULL) { - p1+=sizeof("objecttype=")-1; - l=sizeof (info->model); + ret = unescape_string(info->label, p1, &l, ';'); + if (ret < 0) { + goto cleanup; + } + } - ret = unescape_string (info->type, - p1, &l, ';'); - if (ret < 0) { - goto cleanup; - } - } + if ((p1 = strstr(url, "serial=")) != NULL) { + p1 += sizeof("serial=") - 1; + l = sizeof(info->serial); - if (((p1=strstr(url, ";id="))!= NULL) || ((p1=strstr(url, ":id="))!= NULL)) { - p1+=sizeof(";id=")-1; + ret = unescape_string(info->serial, p1, &l, ';'); + if (ret < 0) { + goto cleanup; + } + } - if ((p2=strchr(p1, ';'))== NULL) { - l = strlen(p1); - } else { - l = p2 - p1; - } + if ((p1 = strstr(url, "model=")) != NULL) { + p1 += sizeof("model=") - 1; + l = sizeof(info->model); - if (l > sizeof(info->id)-1) { - gnutls_assert(); - ret = GNUTLS_E_PARSING_ERROR; - } + ret = unescape_string(info->model, p1, &l, ';'); + if (ret < 0) { + goto cleanup; + } + } - memcpy(info->id, p1, l); - info->id[l] = 0; + if ((p1 = strstr(url, "objecttype=")) != NULL) { + p1 += sizeof("objecttype=") - 1; + l = sizeof(info->model); - /* convert to raw */ - info->certid_raw_size = sizeof(info->certid_raw); - ret = _gnutls_hex2bin(info->id, strlen(info->id), info->certid_raw, &info->certid_raw_size); - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } - } - - ret = 0; - -cleanup: + ret = unescape_string(info->type, p1, &l, ';'); + if (ret < 0) { + goto cleanup; + } + } - return ret; + if (((p1 = strstr(url, ";id=")) != NULL) + || ((p1 = strstr(url, ":id=")) != NULL)) { + p1 += sizeof(";id=") - 1; + + if ((p2 = strchr(p1, ';')) == NULL) { + l = strlen(p1); + } else { + l = p2 - p1; + } + + if (l > sizeof(info->id) - 1) { + gnutls_assert(); + ret = GNUTLS_E_PARSING_ERROR; + } + + memcpy(info->id, p1, l); + info->id[l] = 0; + + /* convert to raw */ + info->certid_raw_size = sizeof(info->certid_raw); + ret = + _gnutls_hex2bin(info->id, strlen(info->id), + info->certid_raw, + &info->certid_raw_size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + } + + ret = 0; + + cleanup: + + return ret; } #define INVALID_CHARS "\\/\"'%&#@!?$* <>{}[]()`|:;,.+-" -static int append(gnutls_buffer_st* dest, const char* tname, const char* p11name, int init) +static int append(gnutls_buffer_st * dest, const char *tname, + const char *p11name, int init) { - gnutls_buffer_st tmpstr; - int ret; + gnutls_buffer_st tmpstr; + int ret; - _gnutls_buffer_init(&tmpstr); - if ((ret=_gnutls_buffer_append_str(&tmpstr, tname))<0) { - gnutls_assert(); - goto cleanup; - } + _gnutls_buffer_init(&tmpstr); + if ((ret = _gnutls_buffer_append_str(&tmpstr, tname)) < 0) { + gnutls_assert(); + goto cleanup; + } - ret = _gnutls_buffer_escape(&tmpstr, INVALID_CHARS); - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } + ret = _gnutls_buffer_escape(&tmpstr, INVALID_CHARS); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } - if ((ret=_gnutls_buffer_append_data(&tmpstr, "", 1)) < 0) { - gnutls_assert(); - goto cleanup; - } + if ((ret = _gnutls_buffer_append_data(&tmpstr, "", 1)) < 0) { + gnutls_assert(); + goto cleanup; + } - if ((ret=_gnutls_buffer_append_printf(dest, "%s%s=%s", (init!=0)?";":"", p11name, tmpstr.data)) < 0) { - gnutls_assert(); - goto cleanup; - } + if ((ret = + _gnutls_buffer_append_printf(dest, "%s%s=%s", + (init != 0) ? ";" : "", p11name, + tmpstr.data)) < 0) { + gnutls_assert(); + goto cleanup; + } - ret = 0; + ret = 0; -cleanup: - _gnutls_buffer_clear(&tmpstr); + cleanup: + _gnutls_buffer_clear(&tmpstr); - return ret; + return ret; } -int pkcs11_info_to_url(const struct pkcs11_url_info* info, char** url) +int pkcs11_info_to_url(const struct pkcs11_url_info *info, char **url) { - gnutls_buffer_st str; - int init = 0; - int ret; - - _gnutls_buffer_init (&str); - - _gnutls_buffer_append_str(&str, "pkcs11:"); - - if (info->token[0]) { - ret = append(&str, info->token, "token", init); - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } - init = 1; - } - - if (info->serial[0]) { - ret = append(&str, info->serial, "serial", init); - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } - init = 1; - } - - if (info->model[0]) { - ret = append(&str, info->model, "model", init); - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } - init = 1; - } + gnutls_buffer_st str; + int init = 0; + int ret; + _gnutls_buffer_init(&str); - if (info->manufacturer[0]) { - ret = append(&str, info->manufacturer, "manufacturer", init); - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } - init = 1; - } - - if (info->label[0]) { - ret = append(&str, info->label, "object", init); - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } - init = 1; - } - - if (info->type[0]) { - ret = append(&str, info->type, "objecttype", init); - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } - init = 1; - } - - if (info->id[0] != 0) { - ret = _gnutls_buffer_append_printf(&str, ";id=%s", info->id); - if (ret < 0) { - gnutls_assert(); - return ret; - } - } - - _gnutls_buffer_append_data(&str, "", 1); + _gnutls_buffer_append_str(&str, "pkcs11:"); + + if (info->token[0]) { + ret = append(&str, info->token, "token", init); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + init = 1; + } + + if (info->serial[0]) { + ret = append(&str, info->serial, "serial", init); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + init = 1; + } + + if (info->model[0]) { + ret = append(&str, info->model, "model", init); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + init = 1; + } + + + if (info->manufacturer[0]) { + ret = + append(&str, info->manufacturer, "manufacturer", init); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + init = 1; + } + + if (info->label[0]) { + ret = append(&str, info->label, "object", init); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + init = 1; + } + + if (info->type[0]) { + ret = append(&str, info->type, "objecttype", init); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + init = 1; + } + + if (info->id[0] != 0) { + ret = + _gnutls_buffer_append_printf(&str, ";id=%s", info->id); + if (ret < 0) { + gnutls_assert(); + return ret; + } + } + + _gnutls_buffer_append_data(&str, "", 1); - *url = str.data; - - return 0; + *url = str.data; -cleanup: - _gnutls_buffer_clear(&str); - return ret; + return 0; + + cleanup: + _gnutls_buffer_clear(&str); + return ret; } /** @@ -732,13 +760,13 @@ cleanup: **/ int gnutls_pkcs11_obj_init(gnutls_pkcs11_obj_t * crt) { - *crt = gnutls_calloc(1, sizeof(struct gnutls_pkcs11_obj_st)); - if (*crt == NULL) { - gnutls_assert(); - return GNUTLS_E_MEMORY_ERROR; - } - - return 0; + *crt = gnutls_calloc(1, sizeof(struct gnutls_pkcs11_obj_st)); + if (*crt == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + return 0; } /** @@ -749,8 +777,8 @@ int gnutls_pkcs11_obj_init(gnutls_pkcs11_obj_t * crt) **/ void gnutls_pkcs11_obj_deinit(gnutls_pkcs11_obj_t crt) { - _gnutls_free_datum(&crt->raw); - free(crt); + _gnutls_free_datum(&crt->raw); + free(crt); } /** @@ -776,75 +804,78 @@ void gnutls_pkcs11_obj_deinit(gnutls_pkcs11_obj_t crt) **/ int gnutls_pkcs11_obj_export(gnutls_pkcs11_obj_t obj, - void *output_data, - size_t * output_data_size) + void *output_data, + size_t * output_data_size) { if (obj == NULL || obj->raw.data == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } - if (output_data==NULL || *output_data_size < obj->raw.size) { - *output_data_size = obj->raw.size; - gnutls_assert(); - return GNUTLS_E_SHORT_MEMORY_BUFFER; - } - *output_data_size = obj->raw.size; + if (output_data == NULL || *output_data_size < obj->raw.size) { + *output_data_size = obj->raw.size; + gnutls_assert(); + return GNUTLS_E_SHORT_MEMORY_BUFFER; + } + *output_data_size = obj->raw.size; - memcpy(output_data, obj->raw.data, obj->raw.size); - return 0; + memcpy(output_data, obj->raw.data, obj->raw.size); + return 0; } static void terminate_string(unsigned char *str, size_t len) { - unsigned char *ptr = str + len - 1; + unsigned char *ptr = str + len - 1; - while ((*ptr == ' ' || *ptr == '\t' || *ptr == '\0') && ptr >= str) - ptr--; + while ((*ptr == ' ' || *ptr == '\t' || *ptr == '\0') && ptr >= str) + ptr--; - if (ptr == str - 1) - str[0] = '\0'; - else if (ptr == str + len - 1) - str[len-1] = '\0'; - else - ptr[1] = '\0'; + if (ptr == str - 1) + str[0] = '\0'; + else if (ptr == str + len - 1) + str[len - 1] = '\0'; + else + ptr[1] = '\0'; } -int pkcs11_find_object (pakchois_session_t** _pks, ck_object_handle_t* _obj, - struct pkcs11_url_info *info, token_creds_st* creds, unsigned int flags) +int pkcs11_find_object(pakchois_session_t ** _pks, + ck_object_handle_t * _obj, + struct pkcs11_url_info *info, + token_creds_st * creds, unsigned int flags) { -int ret; -pakchois_session_t *pks; -ck_object_handle_t obj; -ck_object_class_t class; -struct ck_attribute a[4]; -int a_vals = 0; -unsigned long count; -ck_rv_t rv; - - class = pkcs11_strtype_to_class(info->type); - if (class == -1) { - gnutls_assert(); - return GNUTLS_E_INVALID_REQUEST; - } - - ret = pkcs11_open_session (&pks, info, creds, flags); - if (ret < 0) { - gnutls_assert(); - return ret; - } + int ret; + pakchois_session_t *pks; + ck_object_handle_t obj; + ck_object_class_t class; + struct ck_attribute a[4]; + int a_vals = 0; + unsigned long count; + ck_rv_t rv; + + class = pkcs11_strtype_to_class(info->type); + if (class == -1) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + ret = + pkcs11_open_session(&pks, info, creds, flags & SESSION_LOGIN); + if (ret < 0) { + gnutls_assert(); + return ret; + } a[a_vals].type = CKA_CLASS; a[a_vals].value = &class; a[a_vals].value_len = sizeof class; - a_vals++; + a_vals++; - if (info->certid_raw_size > 0) { - a[a_vals].type = CKA_ID; - a[a_vals].value = info->certid_raw; - a[a_vals].value_len = info->certid_raw_size; - a_vals++; - } + if (info->certid_raw_size > 0) { + a[a_vals].type = CKA_ID; + a[a_vals].value = info->certid_raw; + a[a_vals].value_len = info->certid_raw_size; + a_vals++; + } rv = pakchois_find_objects_init(pks, a, a_vals); if (rv != CKR_OK) { @@ -854,540 +885,653 @@ ck_rv_t rv; goto fail; } - if (pakchois_find_objects(pks, &obj, 1, &count) == CKR_OK - && count == 1) { - *_obj = obj; - *_pks = pks; - pakchois_find_objects_final(pks); - return 0; + if (pakchois_find_objects(pks, &obj, 1, &count) == CKR_OK + && count == 1) { + *_obj = obj; + *_pks = pks; + pakchois_find_objects_final(pks); + return 0; - } + } - pakchois_find_objects_final(pks); -fail: - pakchois_close_session(pks); + pakchois_find_objects_final(pks); + fail: + pakchois_close_session(pks); - return ret; + return ret; } -int pkcs11_open_session (pakchois_session_t** _pks, struct pkcs11_url_info *info, - token_creds_st* creds, unsigned int flags) +int pkcs11_open_session(pakchois_session_t ** _pks, + struct pkcs11_url_info *info, + token_creds_st * creds, unsigned int flags) { - ck_rv_t rv; - int x, z, ret; - pakchois_session_t *pks = NULL; - - for (x=0;xtype = GNUTLS_PKCS11_OBJ_X509_CRT; - break; - case CKO_PUBLIC_KEY: - crt->type = GNUTLS_PKCS11_OBJ_PUBKEY; - break; - case CKO_PRIVATE_KEY: - crt->type = GNUTLS_PKCS11_OBJ_PRIVKEY; - break; - case CKO_SECRET_KEY: - crt->type = GNUTLS_PKCS11_OBJ_SECRET_KEY; - break; - case CKO_DATA: - crt->type = GNUTLS_PKCS11_OBJ_DATA; - break; - default: - crt->type = GNUTLS_PKCS11_OBJ_UNKNOWN; - } - - if (crt->type != GNUTLS_PKCS11_OBJ_UNKNOWN) - strcpy(crt->info.type, pkcs11_obj_type_to_str(crt->type)); - - if (data && data->data) { - ret = _gnutls_set_datum(&crt->raw, data->data, data->size); - if (ret < 0) { - gnutls_assert(); - return ret; - } - } - - terminate_string(tinfo->manufacturer_id, sizeof tinfo->manufacturer_id); - terminate_string(tinfo->label, sizeof tinfo->label); - terminate_string(tinfo->model, sizeof tinfo->model); - terminate_string(tinfo->serial_number, sizeof tinfo->serial_number); - - /* write data */ - snprintf(crt->info.manufacturer, sizeof(crt->info.manufacturer), "%s", tinfo->manufacturer_id); - snprintf(crt->info.token, sizeof(crt->info.token), "%s", tinfo->label); - snprintf(crt->info.model, sizeof(crt->info.model), "%s", tinfo->model); - snprintf(crt->info.serial, sizeof(crt->info.serial), "%s", tinfo->serial_number); - - if (label && label->data) { - memcpy(crt->info.label, label->data, label->size); - crt->info.label[label->size] = 0; - } - - if (id && id->data) { - s = _gnutls_bin2hex(id->data, id->size, crt->info.id, sizeof(crt->info.id), ":"); - if (s == NULL) { - gnutls_assert(); - return GNUTLS_E_PKCS11_ERROR; - } - - memmove(crt->info.certid_raw, id->data, id->size); - crt->info.certid_raw_size = id->size; - } + char *s; + int ret; + + switch (class) { + case CKO_CERTIFICATE: + crt->type = GNUTLS_PKCS11_OBJ_X509_CRT; + break; + case CKO_PUBLIC_KEY: + crt->type = GNUTLS_PKCS11_OBJ_PUBKEY; + break; + case CKO_PRIVATE_KEY: + crt->type = GNUTLS_PKCS11_OBJ_PRIVKEY; + break; + case CKO_SECRET_KEY: + crt->type = GNUTLS_PKCS11_OBJ_SECRET_KEY; + break; + case CKO_DATA: + crt->type = GNUTLS_PKCS11_OBJ_DATA; + break; + default: + crt->type = GNUTLS_PKCS11_OBJ_UNKNOWN; + } + + if (crt->type != GNUTLS_PKCS11_OBJ_UNKNOWN) + strcpy(crt->info.type, pkcs11_obj_type_to_str(crt->type)); - return 0; + if (data && data->data) { + ret = _gnutls_set_datum(&crt->raw, data->data, data->size); + if (ret < 0) { + gnutls_assert(); + return ret; + } + } + + terminate_string(tinfo->manufacturer_id, + sizeof tinfo->manufacturer_id); + terminate_string(tinfo->label, sizeof tinfo->label); + terminate_string(tinfo->model, sizeof tinfo->model); + terminate_string(tinfo->serial_number, + sizeof tinfo->serial_number); + + /* write data */ + snprintf(crt->info.manufacturer, sizeof(crt->info.manufacturer), + "%s", tinfo->manufacturer_id); + snprintf(crt->info.token, sizeof(crt->info.token), "%s", + tinfo->label); + snprintf(crt->info.model, sizeof(crt->info.model), "%s", + tinfo->model); + snprintf(crt->info.serial, sizeof(crt->info.serial), "%s", + tinfo->serial_number); + + if (label && label->data) { + memcpy(crt->info.label, label->data, label->size); + crt->info.label[label->size] = 0; + } + + if (id && id->data) { + s = _gnutls_bin2hex(id->data, id->size, crt->info.id, + sizeof(crt->info.id), ":"); + if (s == NULL) { + gnutls_assert(); + return GNUTLS_E_PKCS11_ERROR; + } + + memmove(crt->info.certid_raw, id->data, id->size); + crt->info.certid_raw_size = id->size; + } + + return 0; } -static int pkcs11_obj_import_pubkey(pakchois_session_t *pks, ck_object_handle_t obj, - gnutls_pkcs11_obj_t crt, const gnutls_datum_t * id, - const gnutls_datum_t* label, struct ck_token_info* tinfo) +static int pkcs11_obj_import_pubkey(pakchois_session_t * pks, + ck_object_handle_t obj, + gnutls_pkcs11_obj_t crt, + const gnutls_datum_t * id, + const gnutls_datum_t * label, + struct ck_token_info *tinfo) { - struct ck_attribute a[4]; - ck_key_type_t key_type; - opaque tmp1[2048]; - opaque tmp2[2048]; - int ret; - unsigned int tval; - - a[0].type = CKA_KEY_TYPE; - a[0].value = &key_type; - a[0].value_len = sizeof(key_type); - - if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) { - switch(key_type) { - case CKK_RSA: - a[0].type = CKA_MODULUS; - a[0].value = tmp1; - a[0].value_len = sizeof(tmp1); - a[1].type = CKA_PUBLIC_EXPONENT; - a[1].value = tmp2; - a[1].value_len = sizeof(tmp2); - - if (pakchois_get_attribute_value(pks, obj, a, 2) == CKR_OK) { - - ret = _gnutls_set_datum(&crt->pubkey[0], a[0].value, a[0].value_len); - - if (ret >= 0) - ret = _gnutls_set_datum(&crt->pubkey[1], a[1].value, a[1].value_len); - - if (ret < 0) { - gnutls_assert(); - _gnutls_free_datum(&crt->pubkey[1]); - _gnutls_free_datum(&crt->pubkey[0]); - return GNUTLS_E_MEMORY_ERROR; - } - } else { - gnutls_assert(); - return GNUTLS_E_PKCS11_ERROR; - } - crt->pk_algorithm = GNUTLS_PK_RSA; - break; - case CKK_DSA: - a[0].type = CKA_PRIME; - a[0].value = tmp1; - a[0].value_len = sizeof(tmp1); - a[1].type = CKA_SUBPRIME; - a[1].value = tmp2; - a[1].value_len = sizeof(tmp2); - - if (pakchois_get_attribute_value(pks, obj, a, 2) == CKR_OK) { - ret = _gnutls_set_datum(&crt->pubkey[0], a[0].value, a[0].value_len); - - if (ret >= 0) - ret = _gnutls_set_datum(&crt->pubkey[1], a[1].value, a[1].value_len); - - if (ret < 0) { - gnutls_assert(); - _gnutls_free_datum(&crt->pubkey[1]); - _gnutls_free_datum(&crt->pubkey[0]); - return GNUTLS_E_MEMORY_ERROR; - } - } else { - gnutls_assert(); - return GNUTLS_E_PKCS11_ERROR; - } - - a[0].type = CKA_BASE; - a[0].value = tmp1; - a[0].value_len = sizeof(tmp1); - a[1].type = CKA_VALUE; - a[1].value = tmp2; - a[1].value_len = sizeof(tmp2); - - if (pakchois_get_attribute_value(pks, obj, a, 2) == CKR_OK) { - ret = _gnutls_set_datum(&crt->pubkey[2], a[0].value, a[0].value_len); - - if (ret >= 0) - ret = _gnutls_set_datum(&crt->pubkey[3], a[1].value, a[1].value_len); - - if (ret < 0) { - gnutls_assert(); - _gnutls_free_datum(&crt->pubkey[0]); - _gnutls_free_datum(&crt->pubkey[1]); - _gnutls_free_datum(&crt->pubkey[2]); - _gnutls_free_datum(&crt->pubkey[3]); - return GNUTLS_E_MEMORY_ERROR; - } - } else { - gnutls_assert(); - return GNUTLS_E_PKCS11_ERROR; - } - crt->pk_algorithm = GNUTLS_PK_RSA; - break; - default: - gnutls_assert(); - return GNUTLS_E_UNIMPLEMENTED_FEATURE; - } - } + struct ck_attribute a[4]; + ck_key_type_t key_type; + opaque tmp1[2048]; + opaque tmp2[2048]; + int ret; + unsigned int tval; + + a[0].type = CKA_KEY_TYPE; + a[0].value = &key_type; + a[0].value_len = sizeof(key_type); + + if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) { + switch (key_type) { + case CKK_RSA: + a[0].type = CKA_MODULUS; + a[0].value = tmp1; + a[0].value_len = sizeof(tmp1); + a[1].type = CKA_PUBLIC_EXPONENT; + a[1].value = tmp2; + a[1].value_len = sizeof(tmp2); + + if (pakchois_get_attribute_value(pks, obj, a, 2) == + CKR_OK) { + + ret = + _gnutls_set_datum(&crt->pubkey[0], + a[0].value, + a[0].value_len); + + if (ret >= 0) + ret = + _gnutls_set_datum(&crt-> + pubkey[1], + a[1].value, + a[1]. + value_len); + + if (ret < 0) { + gnutls_assert(); + _gnutls_free_datum(&crt-> + pubkey[1]); + _gnutls_free_datum(&crt-> + pubkey[0]); + return GNUTLS_E_MEMORY_ERROR; + } + } else { + gnutls_assert(); + return GNUTLS_E_PKCS11_ERROR; + } + crt->pk_algorithm = GNUTLS_PK_RSA; + break; + case CKK_DSA: + a[0].type = CKA_PRIME; + a[0].value = tmp1; + a[0].value_len = sizeof(tmp1); + a[1].type = CKA_SUBPRIME; + a[1].value = tmp2; + a[1].value_len = sizeof(tmp2); + + if (pakchois_get_attribute_value(pks, obj, a, 2) == + CKR_OK) { + ret = + _gnutls_set_datum(&crt->pubkey[0], + a[0].value, + a[0].value_len); + + if (ret >= 0) + ret = + _gnutls_set_datum(&crt-> + pubkey[1], + a[1].value, + a[1]. + value_len); + + if (ret < 0) { + gnutls_assert(); + _gnutls_free_datum(&crt-> + pubkey[1]); + _gnutls_free_datum(&crt-> + pubkey[0]); + return GNUTLS_E_MEMORY_ERROR; + } + } else { + gnutls_assert(); + return GNUTLS_E_PKCS11_ERROR; + } + + a[0].type = CKA_BASE; + a[0].value = tmp1; + a[0].value_len = sizeof(tmp1); + a[1].type = CKA_VALUE; + a[1].value = tmp2; + a[1].value_len = sizeof(tmp2); + + if (pakchois_get_attribute_value(pks, obj, a, 2) == + CKR_OK) { + ret = + _gnutls_set_datum(&crt->pubkey[2], + a[0].value, + a[0].value_len); + + if (ret >= 0) + ret = + _gnutls_set_datum(&crt-> + pubkey[3], + a[1].value, + a[1]. + value_len); + + if (ret < 0) { + gnutls_assert(); + _gnutls_free_datum(&crt-> + pubkey[0]); + _gnutls_free_datum(&crt-> + pubkey[1]); + _gnutls_free_datum(&crt-> + pubkey[2]); + _gnutls_free_datum(&crt-> + pubkey[3]); + return GNUTLS_E_MEMORY_ERROR; + } + } else { + gnutls_assert(); + return GNUTLS_E_PKCS11_ERROR; + } + crt->pk_algorithm = GNUTLS_PK_RSA; + break; + default: + gnutls_assert(); + return GNUTLS_E_UNIMPLEMENTED_FEATURE; + } + } - /* read key usage flags */ - a[0].type = CKA_ENCRYPT; - a[0].value = &tval; - a[0].value_len = sizeof(tval); + /* read key usage flags */ + a[0].type = CKA_ENCRYPT; + a[0].value = &tval; + a[0].value_len = sizeof(tval); - if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) { - if (tval != 0) { - crt->key_usage |= GNUTLS_KEY_DATA_ENCIPHERMENT; - } - } + if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) { + if (tval != 0) { + crt->key_usage |= GNUTLS_KEY_DATA_ENCIPHERMENT; + } + } - a[0].type = CKA_VERIFY; - a[0].value = &tval; - a[0].value_len = sizeof(tval); + a[0].type = CKA_VERIFY; + a[0].value = &tval; + a[0].value_len = sizeof(tval); - if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) { - if (tval != 0) { - crt->key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE| \ - GNUTLS_KEY_KEY_CERT_SIGN|GNUTLS_KEY_CRL_SIGN|GNUTLS_KEY_NON_REPUDIATION; - } - } + if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) { + if (tval != 0) { + crt->key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE | + GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN + | GNUTLS_KEY_NON_REPUDIATION; + } + } - a[0].type = CKA_VERIFY_RECOVER; - a[0].value = &tval; - a[0].value_len = sizeof(tval); + a[0].type = CKA_VERIFY_RECOVER; + a[0].value = &tval; + a[0].value_len = sizeof(tval); - if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) { - if (tval != 0) { - crt->key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE| \ - GNUTLS_KEY_KEY_CERT_SIGN|GNUTLS_KEY_CRL_SIGN|GNUTLS_KEY_NON_REPUDIATION; - } - } + if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) { + if (tval != 0) { + crt->key_usage |= GNUTLS_KEY_DIGITAL_SIGNATURE | + GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN + | GNUTLS_KEY_NON_REPUDIATION; + } + } - a[0].type = CKA_DERIVE; - a[0].value = &tval; - a[0].value_len = sizeof(tval); + a[0].type = CKA_DERIVE; + a[0].value = &tval; + a[0].value_len = sizeof(tval); - if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) { - if (tval != 0) { - crt->key_usage |= GNUTLS_KEY_KEY_AGREEMENT; - } - } + if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) { + if (tval != 0) { + crt->key_usage |= GNUTLS_KEY_KEY_AGREEMENT; + } + } - a[0].type = CKA_WRAP; - a[0].value = &tval; - a[0].value_len = sizeof(tval); + a[0].type = CKA_WRAP; + a[0].value = &tval; + a[0].value_len = sizeof(tval); - if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) { - if (tval != 0) { - crt->key_usage |= GNUTLS_KEY_KEY_ENCIPHERMENT; - } - } + if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) { + if (tval != 0) { + crt->key_usage |= GNUTLS_KEY_KEY_ENCIPHERMENT; + } + } - return pkcs11_obj_import(CKO_PUBLIC_KEY, crt, NULL, id, label, tinfo); + 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 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; + 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) +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 = -1; - ck_certificate_type_t type = -1; - ck_rv_t rv; - ck_object_handle_t obj; - unsigned long count, a_vals; - int found = 0, ret; - opaque* cert_data = NULL; - char label_tmp[PKCS11_LABEL_SIZE]; - - 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->crt->info, &info->tinfo) < 0) { + struct url_find_data_st *find_data = input; + struct ck_attribute a[4]; + ck_object_class_t class = -1; + ck_certificate_type_t type = -1; + ck_rv_t rv; + ck_object_handle_t obj; + unsigned long count, a_vals; + int found = 0, ret; + opaque *cert_data = NULL; + char label_tmp[PKCS11_LABEL_SIZE]; + + if (info == NULL) { /* we don't support multiple calls */ gnutls_assert(); return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } - if (find_data->crt->info.type[0] != 0) { - class = pkcs11_strtype_to_class(find_data->crt->info.type); - if (class == CKO_CERTIFICATE) - type = CKC_X_509; + /* do not bother reading the token if basic fields do not match + */ + if (pkcs11_token_matches_info(&find_data->crt->info, &info->tinfo) + < 0) { + gnutls_assert(); + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + } - if (class == -1) { - gnutls_assert(); - return GNUTLS_E_INVALID_REQUEST; - } - } - - /* search the token for the id */ - - cert_data = gnutls_malloc(MAX_CERT_SIZE); - if (cert_data == NULL) { - gnutls_assert(); - return GNUTLS_E_MEMORY_ERROR; - } - - /* Find objects with given class and type */ - - 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[a_vals].type = CKA_CERTIFICATE_TYPE; - a[a_vals].value = &type; - a[a_vals].value_len = sizeof type; - a_vals++; - } - - rv = pakchois_find_objects_init(pks, a, a_vals); - if (rv != CKR_OK) { - gnutls_assert(); - _gnutls_debug_log("pk11: FindObjectsInit failed.\n"); - ret = pkcs11_rv_to_err(rv); - goto cleanup; - } - - while (pakchois_find_objects(pks, &obj, 1, &count) == CKR_OK - && count == 1) { - - a[0].type = CKA_VALUE; - a[0].value = cert_data; - a[0].value_len = MAX_CERT_SIZE; - a[1].type = CKA_LABEL; - a[1].value = label_tmp; - a[1].value_len = sizeof(label_tmp); - - if (pakchois_get_attribute_value(pks, obj, a, 2) == CKR_OK) { - gnutls_datum_t id = { find_data->crt->info.certid_raw, find_data->crt->info.certid_raw_size }; - gnutls_datum_t data = { a[0].value, a[0].value_len }; - gnutls_datum_t label = { a[1].value, a[1].value_len }; - - if (class == CKO_PUBLIC_KEY) { - ret = pkcs11_obj_import_pubkey(pks, obj, find_data->crt, &id, &label, &info->tinfo); - } else { - ret = pkcs11_obj_import(class, find_data->crt, &data, &id, &label, &info->tinfo); - } - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } - - found = 1; - break; - } - else { - _gnutls_debug_log("pk11: Skipped cert, missing attrs.\n"); + if (find_data->crt->info.type[0] != 0) { + class = pkcs11_strtype_to_class(find_data->crt->info.type); + if (class == CKO_CERTIFICATE) + type = CKC_X_509; + + if (class == -1) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + } + + /* search the token for the id */ + + cert_data = gnutls_malloc(MAX_CERT_SIZE); + if (cert_data == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + /* Find objects with given class and type */ + + 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[a_vals].type = CKA_CERTIFICATE_TYPE; + a[a_vals].value = &type; + a[a_vals].value_len = sizeof type; + a_vals++; + } + + rv = pakchois_find_objects_init(pks, a, a_vals); + if (rv != CKR_OK) { + gnutls_assert(); + _gnutls_debug_log("pk11: FindObjectsInit failed.\n"); + ret = pkcs11_rv_to_err(rv); + goto cleanup; + } + + while (pakchois_find_objects(pks, &obj, 1, &count) == CKR_OK + && count == 1) { + + a[0].type = CKA_VALUE; + a[0].value = cert_data; + a[0].value_len = MAX_CERT_SIZE; + a[1].type = CKA_LABEL; + a[1].value = label_tmp; + a[1].value_len = sizeof(label_tmp); + + if (pakchois_get_attribute_value(pks, obj, a, 2) == CKR_OK) { + gnutls_datum_t id = + { find_data->crt->info.certid_raw, + find_data->crt->info.certid_raw_size }; + gnutls_datum_t data = + { a[0].value, a[0].value_len }; + gnutls_datum_t label = + { a[1].value, a[1].value_len }; + + if (class == CKO_PUBLIC_KEY) { + ret = + pkcs11_obj_import_pubkey(pks, obj, + find_data-> + crt, &id, + &label, + &info->tinfo); + } else { + ret = + pkcs11_obj_import(class, + find_data->crt, + &data, &id, &label, + &info->tinfo); + } + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + found = 1; + break; + } else { + _gnutls_debug_log + ("pk11: Skipped cert, missing attrs.\n"); + } + } + + if (found == 0) { + gnutls_assert(); + ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + } else { + ret = 0; + } + + cleanup: + gnutls_free(cert_data); + pakchois_find_objects_final(pks); + + return ret; +} + +inline static unsigned int pkcs11_obj_flags_to_int(unsigned int flags) +{ + switch(flags) { + case GNUTLS_PKCS11_OBJ_FLAG_LOGIN: + return SESSION_LOGIN; + default: + return 0; } - } - - if (found == 0) { - gnutls_assert(); - ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; - } else { - ret = 0; - } - -cleanup: - gnutls_free(cert_data); - pakchois_find_objects_final(pks); - - return ret; } /** * gnutls_pkcs11_privkey_import_url: * @cert: The structure to store the parsed certificate * @url: a PKCS 11 url identifying the key + * @flags: One of GNUTLS_PKCS11_OBJ_* flags * * This function will "import" a PKCS 11 URL identifying a certificate * key to the #gnutls_pkcs11_obj_t structure. This does not involve any @@ -1397,58 +1541,62 @@ cleanup: * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. **/ -int gnutls_pkcs11_obj_import_url (gnutls_pkcs11_obj_t cert, const char * url) +int gnutls_pkcs11_obj_import_url(gnutls_pkcs11_obj_t cert, const char *url, + unsigned int flags) { - int ret; - struct url_find_data_st find_data; - - /* fill in the find data structure */ - find_data.crt = cert; - - ret = pkcs11_url_to_info(url, &cert->info); - if (ret < 0) { - gnutls_assert(); - return ret; - } - - ret = _pkcs11_traverse_tokens(find_obj_url, &find_data, 0); - if (ret < 0) { - gnutls_assert(); - return ret; - } - - return 0; + int ret; + struct url_find_data_st find_data; + + /* fill in the find data structure */ + find_data.crt = cert; + + ret = pkcs11_url_to_info(url, &cert->info); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + ret = _pkcs11_traverse_tokens(find_obj_url, &find_data, pkcs11_obj_flags_to_int(flags)); + + if (ret < 0) { + gnutls_assert(); + return ret; + } + + return 0; } struct token_num { - struct pkcs11_url_info info; - unsigned int seq; /* which one we are looking for */ - unsigned int current; /* which one are we now */ + struct pkcs11_url_info info; + unsigned int seq; /* which one we are looking for */ + unsigned int current; /* which one are we now */ }; -static int find_token_num(pakchois_session_t *pks, struct token_info *tinfo, void* input) +static int find_token_num(pakchois_session_t * pks, + struct token_info *tinfo, void *input) { - struct token_num* find_data = input; + struct token_num *find_data = input; - if (tinfo == NULL) { /* we don't support multiple calls */ - gnutls_assert(); - return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; - } + if (tinfo == NULL) { /* we don't support multiple calls */ + gnutls_assert(); + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + } - if (find_data->current == find_data->seq) { - strcpy(find_data->info.manufacturer, tinfo->tinfo.manufacturer_id); - strcpy(find_data->info.token, tinfo->tinfo.label); - strcpy(find_data->info.model, tinfo->tinfo.model); - strcpy(find_data->info.serial, tinfo->tinfo.serial_number); + if (find_data->current == find_data->seq) { + strcpy(find_data->info.manufacturer, + tinfo->tinfo.manufacturer_id); + strcpy(find_data->info.token, tinfo->tinfo.label); + strcpy(find_data->info.model, tinfo->tinfo.model); + strcpy(find_data->info.serial, tinfo->tinfo.serial_number); - return 0; - } + return 0; + } - find_data->current++; - /* search the token for the id */ + find_data->current++; + /* search the token for the id */ - return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; /* non zero is enough */ + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; /* non zero is enough */ } /** @@ -1463,27 +1611,27 @@ static int find_token_num(pakchois_session_t *pks, struct token_info *tinfo, voi * if the sequence number exceeds the available tokens, otherwise a negative error value. **/ -int gnutls_pkcs11_token_get_url (unsigned int seq, char** url) +int gnutls_pkcs11_token_get_url(unsigned int seq, char **url) { - int ret; - struct token_num tn; - - memset(&tn, 0, sizeof(tn)); - tn.seq = seq; - - ret = _pkcs11_traverse_tokens(find_token_num, &tn, 0); - if (ret < 0) { - gnutls_assert(); - return ret; - } - - ret = pkcs11_info_to_url(&tn.info, url); - if (ret < 0) { - gnutls_assert(); - return ret; - } - - return 0; + int ret; + struct token_num tn; + + memset(&tn, 0, sizeof(tn)); + tn.seq = seq; + + ret = _pkcs11_traverse_tokens(find_token_num, &tn, 0); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + ret = pkcs11_info_to_url(&tn.info, url); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + return 0; } @@ -1499,49 +1647,51 @@ int gnutls_pkcs11_token_get_url (unsigned int seq, char** url) * * Returns: zero on success or a negative value on error. **/ -int gnutls_pkcs11_token_get_info(const char* url, gnutls_pkcs11_token_info_t ttype, void* output, size_t *output_size) +int gnutls_pkcs11_token_get_info(const char *url, + gnutls_pkcs11_token_info_t ttype, + void *output, size_t * output_size) { - const char* str; - size_t len; - struct pkcs11_url_info info; - int ret; - - ret = pkcs11_url_to_info(url, &info); - if (ret < 0) { - gnutls_assert(); - return ret; - } - - switch(ttype) { - case GNUTLS_PKCS11_TOKEN_LABEL: - str = info.token; - break; - case GNUTLS_PKCS11_TOKEN_SERIAL: - str = info.serial; - break; - case GNUTLS_PKCS11_TOKEN_MANUFACTURER: - str = info.manufacturer; - break; - case GNUTLS_PKCS11_TOKEN_MODEL: - str = info.model; - break; - default: - gnutls_assert(); - return GNUTLS_E_INVALID_REQUEST; - } - - len = strlen(str); - - if (len+1>*output_size) { - *output_size = len+1; - return GNUTLS_E_SHORT_MEMORY_BUFFER; - } - - strcpy(output, str); - - *output_size = len; - - return 0; + const char *str; + size_t len; + struct pkcs11_url_info info; + int ret; + + ret = pkcs11_url_to_info(url, &info); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + switch (ttype) { + case GNUTLS_PKCS11_TOKEN_LABEL: + str = info.token; + break; + case GNUTLS_PKCS11_TOKEN_SERIAL: + str = info.serial; + break; + case GNUTLS_PKCS11_TOKEN_MANUFACTURER: + str = info.manufacturer; + break; + case GNUTLS_PKCS11_TOKEN_MODEL: + str = info.model; + break; + default: + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + len = strlen(str); + + if (len + 1 > *output_size) { + *output_size = len + 1; + return GNUTLS_E_SHORT_MEMORY_BUFFER; + } + + strcpy(output, str); + + *output_size = len; + + return 0; } /** @@ -1554,17 +1704,17 @@ int gnutls_pkcs11_token_get_info(const char* url, gnutls_pkcs11_token_info_t tty * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. **/ -int gnutls_pkcs11_obj_export_url (gnutls_pkcs11_obj_t cert, char ** url) +int gnutls_pkcs11_obj_export_url(gnutls_pkcs11_obj_t cert, char **url) { -int ret; - - ret = pkcs11_info_to_url(&cert->info, url); - if (ret < 0) { - gnutls_assert(); - return ret; - } - - return 0; + int ret; + + ret = pkcs11_info_to_url(&cert->info, url); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + return 0; } /** @@ -1576,510 +1726,559 @@ int ret; * * Returns: The type of the certificate. **/ -gnutls_pkcs11_obj_type_t gnutls_pkcs11_obj_get_type (gnutls_pkcs11_obj_t obj) +gnutls_pkcs11_obj_type_t gnutls_pkcs11_obj_get_type(gnutls_pkcs11_obj_t + obj) { - return obj->type; + return obj->type; } struct pkey_list { - gnutls_buffer_st *key_ids; - size_t key_ids_size; + gnutls_buffer_st *key_ids; + size_t key_ids_size; }; -int pkcs11_login(pakchois_session_t *pks, struct token_info *info, token_creds_st* creds) +int pkcs11_login(pakchois_session_t * pks, struct token_info *info, + token_creds_st * creds) { - int attempt = 0, ret; - ck_rv_t rv; - int pin_len; - - if (pakchois_get_token_info(info->prov->module, info->sid, &info->tinfo) != CKR_OK) { - gnutls_assert(); - _gnutls_debug_log( "pk11: GetTokenInfo failed\n"); - return GNUTLS_E_PKCS11_ERROR; - } - - if ((info->tinfo.flags & CKF_LOGIN_REQUIRED) == 0) { - gnutls_assert(); - _gnutls_debug_log( "pk11: No login required.\n"); - return 0; - } - - /* For a token with a "protected" (out-of-band) authentication - * path, calling login with a NULL username is all that is - * required. */ - if (info->tinfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) { - if (pakchois_login(pks, CKU_USER, NULL, 0) == CKR_OK) { - return 0; - } - else { - gnutls_assert(); - _gnutls_debug_log( "pk11: Protected login failed.\n"); - return GNUTLS_E_PKCS11_ERROR; - } - } - - /* Otherwise, PIN entry is necessary for login, so fail if there's - * no callback. */ - if (!pin_func && !creds) { - gnutls_assert(); - _gnutls_debug_log("pk11: No pin callback but login required.\n"); - return GNUTLS_E_PKCS11_ERROR; - } - - terminate_string(info->sinfo.slot_description, sizeof info->sinfo.slot_description); - - do { - char pin[GNUTLS_PKCS11_MAX_PIN_LEN]; - unsigned int flags = 0; - - /* If login has been attempted once already, check the token - * status again, the flags might change. */ - if (attempt) { - if (pakchois_get_token_info(info->prov->module, info->sid, - &info->tinfo) != CKR_OK) { - gnutls_assert(); - _gnutls_debug_log( "pk11: GetTokenInfo failed\n"); - return GNUTLS_E_PKCS11_ERROR; - } - } - - if (creds != NULL && creds->pin_size > 0 && - !(info->tinfo.flags & CKF_USER_PIN_FINAL_TRY)) { - - memcpy(pin, creds->pin, creds->pin_size); - pin_len = creds->pin_size; - - ret = 0; - } else { - if (info->tinfo.flags & CKF_USER_PIN_COUNT_LOW) - flags |= GNUTLS_PKCS11_PIN_COUNT_LOW; - if (info->tinfo.flags & CKF_USER_PIN_FINAL_TRY) - flags |= GNUTLS_PKCS11_PIN_FINAL_TRY; - - terminate_string(info->tinfo.label, sizeof info->tinfo.label); - - ret = pin_func(pin_data, attempt++, - (char *)info->sinfo.slot_description, - (char *)info->tinfo.label, flags, pin, sizeof(pin)); - if (ret < 0 && ret != GNUTLS_E_PKCS11_PIN_SAVE) { - gnutls_assert(); - return GNUTLS_E_PKCS11_PIN_ERROR; - } - pin_len = strlen(pin); - - } + int attempt = 0, ret; + ck_rv_t rv; + int pin_len; - rv = pakchois_login(pks, CKU_USER, (unsigned char *)pin, pin_len); + if (pakchois_get_token_info + (info->prov->module, info->sid, &info->tinfo) != CKR_OK) { + gnutls_assert(); + _gnutls_debug_log("pk11: GetTokenInfo failed\n"); + return GNUTLS_E_PKCS11_ERROR; + } - if (ret == GNUTLS_E_PKCS11_PIN_SAVE && creds && (rv==CKR_OK||rv==CKR_USER_ALREADY_LOGGED_IN)) { - memcpy(creds->pin, pin, pin_len); - creds->pin_size = pin_len; - } + if ((info->tinfo.flags & CKF_LOGIN_REQUIRED) == 0) { + gnutls_assert(); + _gnutls_debug_log("pk11: No login required.\n"); + return 0; + } - /* Try to scrub the pin off the stack. Clever compilers will - * probably optimize this away, oh well. */ - memset(pin, 0, sizeof pin); - } while (rv == CKR_PIN_INCORRECT); + /* For a token with a "protected" (out-of-band) authentication + * path, calling login with a NULL username is all that is + * required. */ + if (info->tinfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) { + if (pakchois_login(pks, CKU_USER, NULL, 0) == CKR_OK) { + return 0; + } else { + gnutls_assert(); + _gnutls_debug_log + ("pk11: Protected login failed.\n"); + return GNUTLS_E_PKCS11_ERROR; + } + } - _gnutls_debug_log("pk11: Login result = %lu\n", rv); + /* Otherwise, PIN entry is necessary for login, so fail if there's + * no callback. */ + if (!pin_func && !creds) { + gnutls_assert(); + _gnutls_debug_log + ("pk11: No pin callback but login required.\n"); + return GNUTLS_E_PKCS11_ERROR; + } - return (rv == CKR_OK || rv == CKR_USER_ALREADY_LOGGED_IN) ? 0 : pkcs11_rv_to_err(rv); + terminate_string(info->sinfo.slot_description, + sizeof info->sinfo.slot_description); + + do { + char pin[GNUTLS_PKCS11_MAX_PIN_LEN]; + unsigned int flags = 0; + + /* If login has been attempted once already, check the token + * status again, the flags might change. */ + if (attempt) { + if (pakchois_get_token_info + (info->prov->module, info->sid, + &info->tinfo) != CKR_OK) { + gnutls_assert(); + _gnutls_debug_log + ("pk11: GetTokenInfo failed\n"); + return GNUTLS_E_PKCS11_ERROR; + } + } + + if (creds != NULL && creds->pin_size > 0 && + !(info->tinfo.flags & CKF_USER_PIN_FINAL_TRY)) { + + memcpy(pin, creds->pin, creds->pin_size); + pin_len = creds->pin_size; + + ret = 0; + } else { + if (info->tinfo.flags & CKF_USER_PIN_COUNT_LOW) + flags |= GNUTLS_PKCS11_PIN_COUNT_LOW; + if (info->tinfo.flags & CKF_USER_PIN_FINAL_TRY) + flags |= GNUTLS_PKCS11_PIN_FINAL_TRY; + + terminate_string(info->tinfo.label, + sizeof info->tinfo.label); + + ret = pin_func(pin_data, attempt++, + (char *) info->sinfo. + slot_description, + (char *) info->tinfo.label, flags, + pin, sizeof(pin)); + if (ret < 0 && ret != GNUTLS_E_PKCS11_PIN_SAVE) { + gnutls_assert(); + return GNUTLS_E_PKCS11_PIN_ERROR; + } + pin_len = strlen(pin); + + } + + rv = pakchois_login(pks, CKU_USER, (unsigned char *) pin, + pin_len); + + if (ret == GNUTLS_E_PKCS11_PIN_SAVE && creds + && (rv == CKR_OK + || rv == CKR_USER_ALREADY_LOGGED_IN)) { + memcpy(creds->pin, pin, pin_len); + creds->pin_size = pin_len; + } + + /* Try to scrub the pin off the stack. Clever compilers will + * probably optimize this away, oh well. */ + memset(pin, 0, sizeof pin); + } while (rv == CKR_PIN_INCORRECT); + + _gnutls_debug_log("pk11: Login result = %lu\n", rv); + + return (rv == CKR_OK + || rv == + CKR_USER_ALREADY_LOGGED_IN) ? 0 : pkcs11_rv_to_err(rv); } -static int find_privkeys(pakchois_session_t *pks, struct token_info* info, struct pkey_list *list) +static int find_privkeys(pakchois_session_t * pks, struct token_info *info, + struct pkey_list *list) { - struct ck_attribute a[3]; - ck_object_class_t class; - ck_rv_t rv; - ck_object_handle_t obj; - unsigned long count, current; - char certid_tmp[PKCS11_ID_SIZE]; - - class = CKO_PRIVATE_KEY; - - /* Find an object with private key class and a certificate ID - * which matches the certificate. */ - /* FIXME: also match the cert subject. */ - a[0].type = CKA_CLASS; - a[0].value = &class; - a[0].value_len = sizeof class; - - rv = pakchois_find_objects_init(pks, a, 1); - if (rv != CKR_OK) { - gnutls_assert(); - return pkcs11_rv_to_err(rv); - } - - list->key_ids_size = 0; - while (pakchois_find_objects(pks, &obj, 1, &count) == CKR_OK - && count == 1) { - list->key_ids_size++; - } - - pakchois_find_objects_final(pks); - - if (list->key_ids_size == 0) { - gnutls_assert(); - return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; - } - - list->key_ids = gnutls_malloc(sizeof(gnutls_buffer_st)*list->key_ids_size); - if (list->key_ids == NULL) { - gnutls_assert(); - return GNUTLS_E_MEMORY_ERROR; - } - - /* actual search */ - a[0].type = CKA_CLASS; - a[0].value = &class; - a[0].value_len = sizeof class; - - rv = pakchois_find_objects_init(pks, a, 1); - if (rv != CKR_OK) { - gnutls_assert(); - return pkcs11_rv_to_err(rv); - } - - current = 0; - while (pakchois_find_objects(pks, &obj, 1, &count) == CKR_OK - && count == 1) { - - a[0].type = CKA_ID; - a[0].value = certid_tmp; - a[0].value_len = sizeof(certid_tmp); - - _gnutls_buffer_init(&list->key_ids[current]); - - if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) { - _gnutls_buffer_append_data(&list->key_ids[current], a[0].value, a[0].value_len); - current++; - } + struct ck_attribute a[3]; + ck_object_class_t class; + ck_rv_t rv; + ck_object_handle_t obj; + unsigned long count, current; + char certid_tmp[PKCS11_ID_SIZE]; + + class = CKO_PRIVATE_KEY; + + /* Find an object with private key class and a certificate ID + * which matches the certificate. */ + /* FIXME: also match the cert subject. */ + a[0].type = CKA_CLASS; + a[0].value = &class; + a[0].value_len = sizeof class; + + rv = pakchois_find_objects_init(pks, a, 1); + if (rv != CKR_OK) { + gnutls_assert(); + return pkcs11_rv_to_err(rv); + } + + list->key_ids_size = 0; + while (pakchois_find_objects(pks, &obj, 1, &count) == CKR_OK + && count == 1) { + list->key_ids_size++; + } + + pakchois_find_objects_final(pks); + + if (list->key_ids_size == 0) { + gnutls_assert(); + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + } + + list->key_ids = + gnutls_malloc(sizeof(gnutls_buffer_st) * list->key_ids_size); + if (list->key_ids == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + /* actual search */ + a[0].type = CKA_CLASS; + a[0].value = &class; + a[0].value_len = sizeof class; + + rv = pakchois_find_objects_init(pks, a, 1); + if (rv != CKR_OK) { + gnutls_assert(); + return pkcs11_rv_to_err(rv); + } + + current = 0; + while (pakchois_find_objects(pks, &obj, 1, &count) == CKR_OK + && count == 1) { + + a[0].type = CKA_ID; + a[0].value = certid_tmp; + a[0].value_len = sizeof(certid_tmp); - if (current > list->key_ids_size) - break; - } + _gnutls_buffer_init(&list->key_ids[current]); - pakchois_find_objects_final(pks); + if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) { + _gnutls_buffer_append_data(&list->key_ids[current], + a[0].value, + a[0].value_len); + current++; + } - list->key_ids_size = current-1; + if (current > list->key_ids_size) + break; + } - return 0; + pakchois_find_objects_final(pks); + + list->key_ids_size = current - 1; + + return 0; } /* Recover certificate list from tokens */ -static int find_objs(pakchois_session_t *pks, struct token_info *info, void* input) +static int find_objs(pakchois_session_t * pks, struct token_info *info, + void *input) { - struct crt_find_data_st* find_data = input; - struct ck_attribute a[4]; - 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; - opaque *cert_data; - char certid_tmp[PKCS11_ID_SIZE]; - char label_tmp[PKCS11_LABEL_SIZE]; - int ret, i; - struct pkey_list plist; /* private key holder */ - int tot_values = 0; - - if (info == NULL) { /* final call */ - if (find_data->current <= *find_data->n_list) - ret = 0; - else - ret = GNUTLS_E_SHORT_MEMORY_BUFFER; - - *find_data->n_list = find_data->current; - - return ret; - } - - /* do not bother reading the token if basic fields do not match - */ - if (pkcs11_token_matches_info( &find_data->info, &info->tinfo) < 0) { + struct crt_find_data_st *find_data = input; + struct ck_attribute a[4]; + 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; + opaque *cert_data; + char certid_tmp[PKCS11_ID_SIZE]; + char label_tmp[PKCS11_LABEL_SIZE]; + int ret, i; + struct pkey_list plist; /* private key holder */ + int tot_values = 0; + + if (info == NULL) { /* final call */ + if (find_data->current <= *find_data->n_list) + ret = 0; + else + ret = GNUTLS_E_SHORT_MEMORY_BUFFER; + + *find_data->n_list = find_data->current; + + return ret; + } + + /* 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; } - 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.type[0] != 0) { + class = pkcs11_strtype_to_class(find_data->info.type); + if (class == CKO_CERTIFICATE) + type = CKC_X_509; + else + type = -1; + + if (class == -1) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + } - if (class == -1) { - gnutls_assert(); - return GNUTLS_E_INVALID_REQUEST; - } - } - - memset(&plist, 0, sizeof(plist)); + memset(&plist, 0, sizeof(plist)); + + if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY) { + ret = pkcs11_login(pks, info, NULL); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + ret = find_privkeys(pks, info, &plist); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + if (plist.key_ids_size == 0) { + gnutls_assert(); + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + } + } else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_ALL || + find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_PRIVKEY) { + ret = pkcs11_login(pks, info, NULL); + if (ret < 0) { + gnutls_assert(); + return ret; + } + } - if (find_data->flags==GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY) { - ret = pkcs11_login(pks, info, NULL); - if (ret < 0) { - gnutls_assert(); - return ret; - } + cert_data = gnutls_malloc(MAX_CERT_SIZE); + if (cert_data == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } - ret = find_privkeys(pks, info, &plist); - if (ret < 0) { - gnutls_assert(); - return ret; - } + /* 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[tot_values].type = CKA_CLASS; + a[tot_values].value = &class; + a[tot_values].value_len = sizeof class; + tot_values++; + + a[tot_values].type = CKA_CERTIFICATE_TYPE; + a[tot_values].value = &type; + a[tot_values].value_len = sizeof type; + tot_values++; + + } else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED) { + class = CKO_CERTIFICATE; + type = CKC_X_509; + trusted = 1; + + 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++; + + } else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_PUBKEY) { + class = CKO_PUBLIC_KEY; + + 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_PRIVKEY) { + class = CKO_PRIVATE_KEY; + + 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) { + 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(); + ret = GNUTLS_E_INVALID_REQUEST; + goto fail; + } - if (plist.key_ids_size == 0) { - gnutls_assert(); - return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; - } - } else if (find_data->flags==GNUTLS_PKCS11_OBJ_ATTR_ALL || - find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_PRIVKEY) { - ret = pkcs11_login(pks, info, NULL); - if (ret < 0) { - gnutls_assert(); - return ret; - } - } - - cert_data = gnutls_malloc(MAX_CERT_SIZE); - if (cert_data == NULL) { - gnutls_assert(); - return GNUTLS_E_MEMORY_ERROR; - } - - /* 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[tot_values].type = CKA_CLASS; - a[tot_values].value = &class; - a[tot_values].value_len = sizeof class; - tot_values++; - - a[tot_values].type = CKA_CERTIFICATE_TYPE; - a[tot_values].value = &type; - a[tot_values].value_len = sizeof type; - tot_values++; - - } else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED) { - class = CKO_CERTIFICATE; - type = CKC_X_509; - trusted = 1; - - 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++; - - } else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_PUBKEY) { - class = CKO_PUBLIC_KEY; - - 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_PRIVKEY) { - class = CKO_PRIVATE_KEY; - - 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) { - 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(); - 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); - if (rv != CKR_OK) { - gnutls_assert(); - _gnutls_debug_log("pk11: FindObjectsInit failed.\n"); - return pkcs11_rv_to_err(rv); - } - - while (pakchois_find_objects(pks, &obj, 1, &count) == CKR_OK - && count == 1) { - gnutls_datum_t label, id, value; - - a[0].type = CKA_LABEL; - a[0].value = label_tmp; - a[0].value_len = sizeof label_tmp; - - if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) { - label.data = a[0].value; - label.size = a[0].value_len; - } else { - label.data = NULL; - label.size = 0; - } + 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++; + } - 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; - } else { - id.data = NULL; - id.size = 0; - } - - a[0].type = CKA_VALUE; - a[0].value = cert_data; - a[0].value_len = MAX_CERT_SIZE; - if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) { - value.data = a[0].value; - value.size = a[0].value_len; - } else { - value.data = NULL; - value.size = 0; - } - - if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_ALL) { - a[0].type = CKA_CLASS; - a[0].value = &class; - a[0].value_len = sizeof class; - - pakchois_get_attribute_value(pks, obj, a, 1); - } + rv = pakchois_find_objects_init(pks, a, tot_values); + if (rv != CKR_OK) { + gnutls_assert(); + _gnutls_debug_log("pk11: FindObjectsInit failed.\n"); + return pkcs11_rv_to_err(rv); + } - if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY) { - for (i=0;iflags == GNUTLS_PKCS11_OBJ_ATTR_ALL) { + a[0].type = CKA_CLASS; + a[0].value = &class; + a[0].value_len = sizeof class; + + pakchois_get_attribute_value(pks, obj, a, 1); + } + + if (find_data->flags == + GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY) { + for (i = 0; i < plist.key_ids_size; i++) { + if (plist.key_ids[i].length != + a[1].value_len + || memcmp(plist.key_ids[i].data, + a[1].value, + a[1].value_len) != 0) { + /* not found */ + continue; + } + } + } + + if (find_data->current < *find_data->n_list) { + ret = + gnutls_pkcs11_obj_init(&find_data-> + p_list[find_data-> + current]); + if (ret < 0) { + gnutls_assert(); + goto fail; + } + + if (class == CKO_PUBLIC_KEY) { + ret = + pkcs11_obj_import_pubkey(pks, obj, + find_data-> + p_list + [find_data-> + current], + &id, &label, + &info->tinfo); + } else { + ret = + pkcs11_obj_import(class, + find_data-> + p_list[find_data-> + current], + &value, &id, &label, + &info->tinfo); + } + if (ret < 0) { + gnutls_assert(); + goto fail; + } + } + + find_data->current++; - if (find_data->current < *find_data->n_list) { - ret = gnutls_pkcs11_obj_init(&find_data->p_list[find_data->current]); - if (ret < 0) { - gnutls_assert(); - goto fail; - } - - if (class == CKO_PUBLIC_KEY) { - ret = pkcs11_obj_import_pubkey(pks, obj, find_data->p_list[find_data->current], &id, &label, &info->tinfo); - } else { - ret = pkcs11_obj_import(class, find_data->p_list[find_data->current], &value, &id, &label, &info->tinfo); - } - if (ret < 0) { - gnutls_assert(); - goto fail; - } - } - - find_data->current++; - - } - - gnutls_free(cert_data); - pakchois_find_objects_final(pks); - - return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; /* continue until all tokens have been checked */ - -fail: - gnutls_free(cert_data); - pakchois_find_objects_final(pks); - if (plist.key_ids != NULL) { - for (i=0;icurrent;i++) { - gnutls_pkcs11_obj_deinit(find_data->p_list[i]); - } - find_data->current = 0; - - return ret; + } + + gnutls_free(cert_data); + pakchois_find_objects_final(pks); + + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; /* continue until all tokens have been checked */ + + fail: + gnutls_free(cert_data); + pakchois_find_objects_final(pks); + if (plist.key_ids != NULL) { + for (i = 0; i < plist.key_ids_size; i++) { + _gnutls_buffer_clear(&plist.key_ids[i]); + } + gnutls_free(plist.key_ids); + } + for (i = 0; i < find_data->current; i++) { + gnutls_pkcs11_obj_deinit(find_data->p_list[i]); + } + find_data->current = 0; + + return ret; } /** * gnutls_pkcs11_obj_list_import_url: - * @p_list: An uninitialized certificate list (may be NULL) + * @p_list: An uninitialized object list (may be NULL) * @n_list: initially should hold the maximum size of the list. Will contain the actual size. - * @url: A PKCS 11 url identifying a set of certificates - * @flags: Attributes of type #gnutls_pkcs11_obj_attr_t that can be used to limit output + * @url: A PKCS 11 url identifying a set of objects + * @attrs: Attributes of type #gnutls_pkcs11_obj_attr_t that can be used to limit output + * @flags: One of GNUTLS_PKCS11_OBJ_* flags * - * This function will initialize and set value to a certificate list - * specified by a PKCS 11 URL. + * This function will initialize and set values to an object list + * by using all objects identified by a PKCS 11 URL. * * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. **/ -int gnutls_pkcs11_obj_list_import_url (gnutls_pkcs11_obj_t * p_list, unsigned int *n_list, const char* url, gnutls_pkcs11_obj_attr_t flags) +int gnutls_pkcs11_obj_list_import_url(gnutls_pkcs11_obj_t * p_list, + unsigned int *n_list, + const char *url, + gnutls_pkcs11_obj_attr_t attrs, + unsigned int flags) { - int ret; - struct crt_find_data_st find_data; - - /* fill in the find data structure */ - find_data.p_list = p_list; - find_data.n_list = n_list; - find_data.flags = flags; - find_data.current = 0; - - if (url == NULL || url[0] == 0) { - url = "pkcs11:"; - } - - ret = pkcs11_url_to_info(url, &find_data.info); - if (ret < 0) { - gnutls_assert(); - return ret; - } - - ret = _pkcs11_traverse_tokens(find_objs, &find_data, 0); - if (ret < 0) { - gnutls_assert(); - return ret; - } - - return 0; + int ret; + struct crt_find_data_st find_data; + + /* fill in the find data structure */ + find_data.p_list = p_list; + find_data.n_list = n_list; + find_data.flags = attrs; + find_data.current = 0; + + if (url == NULL || url[0] == 0) { + url = "pkcs11:"; + } + + ret = pkcs11_url_to_info(url, &find_data.info); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + ret = _pkcs11_traverse_tokens(find_objs, &find_data, pkcs11_obj_flags_to_int(flags)); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + return 0; } /** * gnutls_x509_crt_import_pkcs11_url: * @crt: A certificate of type #gnutls_x509_crt_t * @url: A PKCS 11 url + * @flags: One of GNUTLS_PKCS11_OBJ_* flags * * This function will import a PKCS 11 certificate directly from a token * without involving the #gnutls_pkcs11_obj_t structure. This function will @@ -2088,35 +2287,36 @@ int gnutls_pkcs11_obj_list_import_url (gnutls_pkcs11_obj_t * p_list, unsigned in * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. **/ -int gnutls_x509_crt_import_pkcs11_url( gnutls_x509_crt_t crt, const char* url) +int gnutls_x509_crt_import_pkcs11_url(gnutls_x509_crt_t crt, + const char *url, unsigned int flags) { - gnutls_pkcs11_obj_t pcrt; - int ret; - - ret = gnutls_pkcs11_obj_init ( &pcrt); - if (ret < 0) { - gnutls_assert(); - return ret; - } - - ret = gnutls_pkcs11_obj_import_url (pcrt, url); - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } - - ret = gnutls_x509_crt_import(crt, &pcrt->raw, GNUTLS_X509_FMT_DER); - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } - - ret = 0; -cleanup: - - gnutls_pkcs11_obj_deinit(pcrt); - - return ret; + gnutls_pkcs11_obj_t pcrt; + int ret; + + ret = gnutls_pkcs11_obj_init(&pcrt); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + ret = gnutls_pkcs11_obj_import_url(pcrt, url, flags); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = gnutls_x509_crt_import(crt, &pcrt->raw, GNUTLS_X509_FMT_DER); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = 0; + cleanup: + + gnutls_pkcs11_obj_deinit(pcrt); + + return ret; } @@ -2131,9 +2331,11 @@ cleanup: * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. **/ -int gnutls_x509_crt_import_pkcs11( gnutls_x509_crt_t crt, gnutls_pkcs11_obj_t pkcs11_crt) +int gnutls_x509_crt_import_pkcs11(gnutls_x509_crt_t crt, + gnutls_pkcs11_obj_t pkcs11_crt) { - return gnutls_x509_crt_import(crt, &pkcs11_crt->raw, GNUTLS_X509_FMT_DER); + return gnutls_x509_crt_import(crt, &pkcs11_crt->raw, + GNUTLS_X509_FMT_DER); } /** @@ -2141,6 +2343,7 @@ int gnutls_x509_crt_import_pkcs11( gnutls_x509_crt_t crt, gnutls_pkcs11_obj_t pk * @cert: A list of certificates of type #gnutls_x509_crt_t * @cert_max: The maximum size of the list * @objs: A list of PKCS 11 objects + * @flags: 0 for now * * This function will import a PKCS 11 certificate list to a list of * #gnutls_x509_crt_t structure. These must not be initialized. @@ -2148,58 +2351,60 @@ int gnutls_x509_crt_import_pkcs11( gnutls_x509_crt_t crt, gnutls_pkcs11_obj_t pk * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. **/ -int gnutls_x509_crt_list_import_pkcs11 (gnutls_x509_crt_t * certs, - unsigned int cert_max, gnutls_pkcs11_obj_t * const objs, - unsigned int flags) +int gnutls_x509_crt_list_import_pkcs11(gnutls_x509_crt_t * certs, + unsigned int cert_max, + gnutls_pkcs11_obj_t * const objs, + unsigned int flags) { - int i, j; - int ret; - - for (i=0;iinfo, &info->tinfo) < 0) { + /* 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; } - /* found token! */ + /* found token! */ - find_data->slot_flags = info->sinfo.flags; + find_data->slot_flags = info->sinfo.flags; - return 0; + return 0; } /** @@ -2211,72 +2416,74 @@ static int find_flags(pakchois_session_t *pks, struct token_info *info, void* in * * Returns: zero on success or a negative value on error. **/ -int gnutls_pkcs11_token_get_flags(const char* url, unsigned int *flags) +int gnutls_pkcs11_token_get_flags(const char *url, unsigned int *flags) { - struct flags_find_data_st find_data; - int ret; + struct flags_find_data_st find_data; + int ret; - ret = pkcs11_url_to_info(url, &find_data.info); - if (ret < 0) { - gnutls_assert(); - return ret; - } + ret = pkcs11_url_to_info(url, &find_data.info); + if (ret < 0) { + gnutls_assert(); + return ret; + } - ret = _pkcs11_traverse_tokens(find_flags, &find_data, 0); - if (ret < 0) { - gnutls_assert(); - return ret; - } + ret = _pkcs11_traverse_tokens(find_flags, &find_data, 0); + if (ret < 0) { + gnutls_assert(); + return ret; + } - *flags = 0; - if (find_data.slot_flags & CKF_HW_SLOT) - *flags |= GNUTLS_PKCS11_TOKEN_HW; + *flags = 0; + if (find_data.slot_flags & CKF_HW_SLOT) + *flags |= GNUTLS_PKCS11_TOKEN_HW; - return 0; + return 0; } -const char* gnutls_pkcs11_type_get_name (gnutls_pkcs11_obj_type_t type) +const char *gnutls_pkcs11_type_get_name(gnutls_pkcs11_obj_type_t type) { - switch(type) { - case GNUTLS_PKCS11_OBJ_X509_CRT: - return "X.509 Certificate"; - case GNUTLS_PKCS11_OBJ_PUBKEY: - return "Public key"; - case GNUTLS_PKCS11_OBJ_PRIVKEY: - return "Private key"; - case GNUTLS_PKCS11_OBJ_SECRET_KEY: - return "Secret key"; - case GNUTLS_PKCS11_OBJ_DATA: - return "Data"; - case GNUTLS_PKCS11_OBJ_UNKNOWN: - default: - return "Unknown"; - } + switch (type) { + case GNUTLS_PKCS11_OBJ_X509_CRT: + return "X.509 Certificate"; + case GNUTLS_PKCS11_OBJ_PUBKEY: + return "Public key"; + case GNUTLS_PKCS11_OBJ_PRIVKEY: + return "Private key"; + case GNUTLS_PKCS11_OBJ_SECRET_KEY: + return "Secret key"; + case GNUTLS_PKCS11_OBJ_DATA: + return "Data"; + case GNUTLS_PKCS11_OBJ_UNKNOWN: + default: + return "Unknown"; + } } -int pkcs11_token_matches_info( struct pkcs11_url_info* info, struct ck_token_info* tinfo) +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; + 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_write.c b/lib/pkcs11_write.c index b93623ab1c..b41f9bbff8 100644 --- a/lib/pkcs11_write.c +++ b/lib/pkcs11_write.c @@ -33,7 +33,7 @@ * @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_* + * @flags: One of GNUTLS_PKCS11_COPY_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. @@ -127,7 +127,7 @@ int gnutls_pkcs11_copy_x509_crt(const char* token_url, gnutls_x509_crt_t crt, a_val++; } - if (flags & GNUTLS_PKCS11_OBJ_FLAG_TRUSTED) { + if (flags & GNUTLS_PKCS11_COPY_FLAG_MARK_TRUSTED) { a[a_val].type = CKA_TRUSTED; a[a_val].value = &tval; a[a_val].value_len = sizeof(tval); @@ -161,6 +161,7 @@ cleanup: * @key: A private key * @label: A name to be used for the stored data * @key_usage: One of GNUTLS_KEY_* + * @flags: One of GNUTLS_PKCS11_COPY_* flags * * This function will copy a private key into a PKCS #11 token specified by * a URL. @@ -169,7 +170,8 @@ cleanup: * 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) + gnutls_x509_privkey_t key, const char* label, unsigned int key_usage, + unsigned int flags) { int ret; pakchois_session_t *pks; diff --git a/src/certtool-common.h b/src/certtool-common.h index 95ff5dc67b..010eac0142 100644 --- a/src/certtool-common.h +++ b/src/certtool-common.h @@ -38,8 +38,8 @@ enum #define TYPE_CRQ 2 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_list( FILE*outfile, const char* url, int type, unsigned int login); +void pkcs11_export(FILE* outfile, const char *pkcs11_url, unsigned int login); 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); diff --git a/src/certtool-gaa.c b/src/certtool-gaa.c index 535ac4c9fe..3d5bda8059 100644 --- a/src/certtool-gaa.c +++ b/src/certtool-gaa.c @@ -186,6 +186,7 @@ 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-login", "", "Force login to token"); __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."); @@ -207,12 +208,14 @@ typedef struct _gaainfo gaainfo; struct _gaainfo { -#line 160 "certtool.gaa" +#line 163 "certtool.gaa" int debug; -#line 155 "certtool.gaa" +#line 158 "certtool.gaa" int pkcs11_trusted; -#line 152 "certtool.gaa" +#line 155 "certtool.gaa" char* pkcs11_label; +#line 152 "certtool.gaa" + int pkcs11_login; #line 144 "certtool.gaa" int pkcs11_type; #line 141 "certtool.gaa" @@ -323,7 +326,7 @@ static int gaa_error = 0; #define GAA_MULTIPLE_OPTION 3 #define GAA_REST 0 -#define GAA_NB_OPTION 64 +#define GAA_NB_OPTION 65 #define GAAOPTID_version 1 #define GAAOPTID_help 2 #define GAAOPTID_debug 3 @@ -331,63 +334,64 @@ static int gaa_error = 0; #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_privkeys 12 -#define GAAOPTID_pkcs11_list_certs 13 -#define GAAOPTID_pkcs11_export_url 14 -#define GAAOPTID_pkcs11_provider 15 -#define GAAOPTID_pkcs_cipher 16 -#define GAAOPTID_template 17 -#define GAAOPTID_infile 18 -#define GAAOPTID_outfile 19 -#define GAAOPTID_disable_quick_random 20 -#define GAAOPTID_sec_param 21 -#define GAAOPTID_bits 22 -#define GAAOPTID_outraw 23 -#define GAAOPTID_outder 24 -#define GAAOPTID_inraw 25 -#define GAAOPTID_inder 26 -#define GAAOPTID_export_ciphers 27 -#define GAAOPTID_hash 28 -#define GAAOPTID_dsa 29 -#define GAAOPTID_pkcs8 30 -#define GAAOPTID_to_p8 31 -#define GAAOPTID_to_p12 32 -#define GAAOPTID_v1 33 -#define GAAOPTID_fix_key 34 -#define GAAOPTID_pubkey_info 35 -#define GAAOPTID_pgp_key_info 36 -#define GAAOPTID_key_info 37 -#define GAAOPTID_smime_to_p7 38 -#define GAAOPTID_p7_info 39 -#define GAAOPTID_p12_info 40 -#define GAAOPTID_no_crq_extensions 41 -#define GAAOPTID_crq_info 42 -#define GAAOPTID_crl_info 43 -#define GAAOPTID_pgp_ring_info 44 -#define GAAOPTID_pgp_certificate_info 45 -#define GAAOPTID_certificate_info 46 -#define GAAOPTID_password 47 -#define GAAOPTID_load_ca_certificate 48 -#define GAAOPTID_load_ca_privkey 49 -#define GAAOPTID_load_certificate 50 -#define GAAOPTID_load_request 51 -#define GAAOPTID_load_pubkey 52 -#define GAAOPTID_load_privkey 53 -#define GAAOPTID_get_dh_params 54 -#define GAAOPTID_generate_dh_params 55 -#define GAAOPTID_verify_crl 56 -#define GAAOPTID_verify_chain 57 -#define GAAOPTID_generate_request 58 -#define GAAOPTID_generate_privkey 59 -#define GAAOPTID_update_certificate 60 -#define GAAOPTID_generate_crl 61 -#define GAAOPTID_generate_proxy 62 -#define GAAOPTID_generate_certificate 63 -#define GAAOPTID_generate_self_signed 64 +#define GAAOPTID_pkcs11_login 8 +#define GAAOPTID_pkcs11_list_tokens 9 +#define GAAOPTID_pkcs11_list_all 10 +#define GAAOPTID_pkcs11_list_all_certs 11 +#define GAAOPTID_pkcs11_list_trusted 12 +#define GAAOPTID_pkcs11_list_privkeys 13 +#define GAAOPTID_pkcs11_list_certs 14 +#define GAAOPTID_pkcs11_export_url 15 +#define GAAOPTID_pkcs11_provider 16 +#define GAAOPTID_pkcs_cipher 17 +#define GAAOPTID_template 18 +#define GAAOPTID_infile 19 +#define GAAOPTID_outfile 20 +#define GAAOPTID_disable_quick_random 21 +#define GAAOPTID_sec_param 22 +#define GAAOPTID_bits 23 +#define GAAOPTID_outraw 24 +#define GAAOPTID_outder 25 +#define GAAOPTID_inraw 26 +#define GAAOPTID_inder 27 +#define GAAOPTID_export_ciphers 28 +#define GAAOPTID_hash 29 +#define GAAOPTID_dsa 30 +#define GAAOPTID_pkcs8 31 +#define GAAOPTID_to_p8 32 +#define GAAOPTID_to_p12 33 +#define GAAOPTID_v1 34 +#define GAAOPTID_fix_key 35 +#define GAAOPTID_pubkey_info 36 +#define GAAOPTID_pgp_key_info 37 +#define GAAOPTID_key_info 38 +#define GAAOPTID_smime_to_p7 39 +#define GAAOPTID_p7_info 40 +#define GAAOPTID_p12_info 41 +#define GAAOPTID_no_crq_extensions 42 +#define GAAOPTID_crq_info 43 +#define GAAOPTID_crl_info 44 +#define GAAOPTID_pgp_ring_info 45 +#define GAAOPTID_pgp_certificate_info 46 +#define GAAOPTID_certificate_info 47 +#define GAAOPTID_password 48 +#define GAAOPTID_load_ca_certificate 49 +#define GAAOPTID_load_ca_privkey 50 +#define GAAOPTID_load_certificate 51 +#define GAAOPTID_load_request 52 +#define GAAOPTID_load_pubkey 53 +#define GAAOPTID_load_privkey 54 +#define GAAOPTID_get_dh_params 55 +#define GAAOPTID_generate_dh_params 56 +#define GAAOPTID_verify_crl 57 +#define GAAOPTID_verify_chain 58 +#define GAAOPTID_generate_request 59 +#define GAAOPTID_generate_privkey 60 +#define GAAOPTID_update_certificate 61 +#define GAAOPTID_generate_crl 62 +#define GAAOPTID_generate_proxy 63 +#define GAAOPTID_generate_certificate 64 +#define GAAOPTID_generate_self_signed 65 #line 168 "gaa.skel" @@ -748,6 +752,7 @@ static int gaa_get_option_num(char *str, int status) GAA_CHECK1STR("v", GAAOPTID_version); GAA_CHECK1STR("h", GAAOPTID_help); GAA_CHECK1STR("", GAAOPTID_pkcs11_write_trusted); + GAA_CHECK1STR("", GAAOPTID_pkcs11_login); GAA_CHECK1STR("", GAAOPTID_pkcs11_list_tokens); GAA_CHECK1STR("", GAAOPTID_pkcs11_list_all); GAA_CHECK1STR("", GAAOPTID_pkcs11_list_all_certs); @@ -800,6 +805,7 @@ static int gaa_get_option_num(char *str, int status) 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-login", GAAOPTID_pkcs11_login); 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); @@ -911,14 +917,14 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) { case GAAOPTID_version: OK = 0; -#line 165 "certtool.gaa" +#line 168 "certtool.gaa" { certtool_version(); exit(0); ;}; return GAA_OK; break; case GAAOPTID_help: OK = 0; -#line 163 "certtool.gaa" +#line 166 "certtool.gaa" { gaa_help(); exit(0); ;}; return GAA_OK; @@ -928,7 +934,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_debug.arg1, gaa_getint, GAATMP_debug.size1); gaa_index++; -#line 161 "certtool.gaa" +#line 164 "certtool.gaa" { gaaval->debug = GAATMP_debug.arg1 ;}; return GAA_OK; @@ -938,14 +944,14 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_pkcs11_delete_url.arg1, gaa_getstr, GAATMP_pkcs11_delete_url.size1); gaa_index++; -#line 158 "certtool.gaa" +#line 161 "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 156 "certtool.gaa" +#line 159 "certtool.gaa" { gaaval->pkcs11_trusted = 1; ;}; return GAA_OK; @@ -955,7 +961,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_pkcs11_write_label.arg1, gaa_getstr, GAATMP_pkcs11_write_label.size1); gaa_index++; -#line 154 "certtool.gaa" +#line 157 "certtool.gaa" { gaaval->pkcs11_label = GAATMP_pkcs11_write_label.arg1; ;}; return GAA_OK; @@ -965,9 +971,16 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_pkcs11_write.arg1, gaa_getstr, GAATMP_pkcs11_write.size1); gaa_index++; -#line 153 "certtool.gaa" +#line 156 "certtool.gaa" { gaaval->action = ACTION_PKCS11_WRITE_URL; gaaval->pkcs11_url = GAATMP_pkcs11_write.arg1; ;}; + return GAA_OK; + break; + case GAAOPTID_pkcs11_login: + OK = 0; +#line 153 "certtool.gaa" +{ gaaval->pkcs11_login = 1; ;}; + return GAA_OK; break; case GAAOPTID_pkcs11_list_tokens: @@ -1441,14 +1454,14 @@ int gaa(int argc, char **argv, gaainfo *gaaval) if(inited == 0) { -#line 167 "certtool.gaa" +#line 170 "certtool.gaa" { gaaval->bits = 0; 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_label = NULL; - gaaval->pkcs11_trusted=0; gaaval->sec_param = NULL; ;}; + gaaval->pkcs11_trusted=0; gaaval->sec_param = NULL; gaaval->pkcs11_login = 0; ;}; } inited = 1; diff --git a/src/certtool-gaa.h b/src/certtool-gaa.h index 8e9f2ff8ff..c64ffb3bd1 100644 --- a/src/certtool-gaa.h +++ b/src/certtool-gaa.h @@ -8,12 +8,14 @@ typedef struct _gaainfo gaainfo; struct _gaainfo { -#line 160 "certtool.gaa" +#line 163 "certtool.gaa" int debug; -#line 155 "certtool.gaa" +#line 158 "certtool.gaa" int pkcs11_trusted; -#line 152 "certtool.gaa" +#line 155 "certtool.gaa" char* pkcs11_label; +#line 152 "certtool.gaa" + int pkcs11_login; #line 144 "certtool.gaa" int pkcs11_type; #line 141 "certtool.gaa" diff --git a/src/certtool.c b/src/certtool.c index 962268a5bd..02a44173ce 100644 --- a/src/certtool.c +++ b/src/certtool.c @@ -1127,13 +1127,13 @@ gaa_parser (int argc, char **argv) generate_pkcs8 (); break; case ACTION_PKCS11_LIST: - pkcs11_list(outfile, info.pkcs11_url, info.pkcs11_type); + pkcs11_list(outfile, info.pkcs11_url, info.pkcs11_type, info.pkcs11_login); break; case ACTION_PKCS11_TOKENS: pkcs11_token_list(outfile); break; case ACTION_PKCS11_EXPORT_URL: - pkcs11_export(outfile, info.pkcs11_url); + pkcs11_export(outfile, info.pkcs11_url, info.pkcs11_login); break; case ACTION_PKCS11_WRITE_URL: pkcs11_write(outfile, info.pkcs11_url, info.pkcs11_label, info.pkcs11_trusted); diff --git a/src/certtool.gaa b/src/certtool.gaa index 0f7be24d4a..1fcdc20f21 100644 --- a/src/certtool.gaa +++ b/src/certtool.gaa @@ -149,6 +149,9 @@ 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" +#int pkcs11_login; +option (pkcs11-login) { $pkcs11_login = 1; } "Force login to token" + #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." @@ -170,4 +173,4 @@ init { $bits = 0; $pkcs8 = 0; $privkey = NULL; $ca=NULL; $ca_privkey = NULL; $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_label = NULL; - $pkcs11_trusted=0; $sec_param = NULL; } + $pkcs11_trusted=0; $sec_param = NULL; $pkcs11_login = 0; } diff --git a/src/cli.c b/src/cli.c index bab94c2dce..34bdf7812a 100644 --- a/src/cli.c +++ b/src/cli.c @@ -187,7 +187,11 @@ load_keys (void) gnutls_x509_crt_init (&x509_crt[0]); ret = - gnutls_x509_crt_import_pkcs11_url (x509_crt[0], x509_certfile); + gnutls_x509_crt_import_pkcs11_url (x509_crt[0], x509_certfile, 0); + + if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) + ret = gnutls_x509_crt_import_pkcs11_url (x509_crt[0], x509_certfile, GNUTLS_PKCS11_OBJ_FLAG_LOGIN); + if (ret < 0) { fprintf (stderr, "*** Error loading cert file.\n"); diff --git a/src/pkcs11.c b/src/pkcs11.c index d092136599..f4275b940a 100644 --- a/src/pkcs11.c +++ b/src/pkcs11.c @@ -48,7 +48,7 @@ void pkcs11_delete(FILE* outfile, const char* url, int batch) { int ret; if (!batch) { - pkcs11_list(outfile, url, PKCS11_TYPE_ALL); + pkcs11_list(outfile, url, PKCS11_TYPE_ALL, 1/*login*/); ret = read_yesno("Are you sure you want to delete those objects? (Y/N): "); if (ret == 0) { exit(1); @@ -68,14 +68,18 @@ int ret; /* lists certificates from a token */ -void pkcs11_list( FILE* outfile, const char* url, int type) +void pkcs11_list( FILE* outfile, const char* url, int type, unsigned int login) { gnutls_pkcs11_obj_t *crt_list; gnutls_x509_crt_t xcrt; unsigned int crt_list_size = 0; int ret; char* output; -int i, flags; +int i, attrs; +unsigned int obj_flags = 0; + + if (login) + obj_flags = GNUTLS_PKCS11_OBJ_FLAG_LOGIN; pkcs11_common(); @@ -83,15 +87,15 @@ int i, flags; url = "pkcs11:"; if (type == PKCS11_TYPE_TRUSTED) { - flags = GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED; + attrs = GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED; } else if (type == PKCS11_TYPE_PK) { - flags = GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY; + attrs = GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY; } else if (type == PKCS11_TYPE_CRT_ALL) { - flags = GNUTLS_PKCS11_OBJ_ATTR_CRT_ALL; + attrs = GNUTLS_PKCS11_OBJ_ATTR_CRT_ALL; } else if (type == PKCS11_TYPE_PRIVKEY) { - flags = GNUTLS_PKCS11_OBJ_ATTR_PRIVKEY; + attrs = GNUTLS_PKCS11_OBJ_ATTR_PRIVKEY; } else { - flags = GNUTLS_PKCS11_OBJ_ATTR_ALL; + attrs = GNUTLS_PKCS11_OBJ_ATTR_ALL; } /* give some initial value to avoid asking for the pkcs11 pin twice. @@ -103,7 +107,8 @@ int i, flags; exit(1); } - ret = gnutls_pkcs11_obj_list_import_url( crt_list, &crt_list_size, url, flags); + ret = gnutls_pkcs11_obj_list_import_url( crt_list, &crt_list_size, url, + attrs, obj_flags); if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) { fprintf(stderr, "Error in crt_list_import (1): %s\n", gnutls_strerror(ret)); exit(1); @@ -121,7 +126,7 @@ int i, flags; exit(1); } - ret = gnutls_pkcs11_obj_list_import_url( crt_list, &crt_list_size, url, flags); + ret = gnutls_pkcs11_obj_list_import_url( crt_list, &crt_list_size, url, attrs, obj_flags); if (ret < 0) { fprintf(stderr, "Error in crt_list_import: %s\n", gnutls_strerror(ret)); exit(1); @@ -160,7 +165,7 @@ int i, flags; - if (flags == GNUTLS_PKCS11_OBJ_ATTR_ALL || flags == GNUTLS_PKCS11_OBJ_ATTR_PRIVKEY) + if (attrs == GNUTLS_PKCS11_OBJ_ATTR_ALL || attrs == GNUTLS_PKCS11_OBJ_ATTR_PRIVKEY) continue; ret = gnutls_x509_crt_init(&xcrt); @@ -195,13 +200,17 @@ int i, flags; return; } -void pkcs11_export(FILE* outfile, const char* url) +void pkcs11_export(FILE* outfile, const char* url, unsigned int login) { gnutls_pkcs11_obj_t crt; gnutls_x509_crt_t xcrt; gnutls_pubkey_t pubkey; int ret; size_t size; +unsigned int obj_flags = 0; + + if (login) + obj_flags = GNUTLS_PKCS11_OBJ_FLAG_LOGIN; pkcs11_common(); @@ -214,7 +223,7 @@ size_t size; exit(1); } - ret = gnutls_pkcs11_obj_import_url( crt, url); + ret = gnutls_pkcs11_obj_import_url( crt, url, obj_flags); if (ret < 0) { fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror(ret)); exit(1); @@ -382,7 +391,7 @@ unsigned int key_usage; xcrt = load_cert(0); if (xcrt != NULL) { if (trusted) - flags |= GNUTLS_PKCS11_OBJ_FLAG_TRUSTED; + flags |= GNUTLS_PKCS11_COPY_FLAG_MARK_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)); @@ -394,7 +403,7 @@ unsigned int key_usage; xkey = load_private_key(0); if (xkey != NULL) { - ret = gnutls_pkcs11_copy_x509_privkey(url, xkey, label, key_usage); + ret = gnutls_pkcs11_copy_x509_privkey(url, xkey, label, key_usage, flags); if (ret < 0) { fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror(ret)); exit(1);