ERROR_ENTRY (N_("Error interfacing with /dev/crypto"),
GNUTLS_E_CRYPTODEV_IOCTL_ERROR, 1),
+ ERROR_ENTRY (N_("PKCS #11 error."),
+ GNUTLS_E_PKCS11_ERROR, 1),
+ ERROR_ENTRY (N_("PKCS #11 initialization error."),
+ GNUTLS_E_PKCS11_LOAD_ERROR, 1),
+ ERROR_ENTRY (N_("Error in parsing."),
+ GNUTLS_E_PARSING_ERROR, 1),
+ ERROR_ENTRY (N_("PKCS #11 error in PIN."),
+ GNUTLS_E_PKCS11_PIN_ERROR, 1),
+ ERROR_ENTRY (N_("PKCS #11 error"),
+ GNUTLS_E_PKCS11_ERROR, 1),
+
{NULL, NULL, 0, 0}
};
opaque hex2_data[3];
unsigned long val;
- /* FIXME: we don't handle whitespace.
- */
- hex_size /= 2;
+ hex2_data[2] = 0;
- if (*bin_size < (size_t) hex_size)
+ for (i = j = 0; i < hex_size;)
{
- gnutls_assert ();
- return GNUTLS_E_SHORT_MEMORY_BUFFER;
- }
+ if (!isxdigit(hex_data[i])) /* skip non-hex such as the ':' in 00:FF */
+ {
+ i++;
+ continue;
+ }
+
+ if (j > *bin_size) {
+ gnutls_assert();
+ return GNUTLS_E_SHORT_MEMORY_BUFFER;
+ }
- for (i = j = 0; j < hex_size; j++)
- {
-
- if (!isxdigit(hex_data[i])) /* skip non-hex such as the ':' in 00:FF */
- continue;
-
- hex2_data[0] = hex_data[i];
- hex2_data[1] = hex_data[i + 1];
- hex2_data[2] = 0;
- i+=2;
- val = strtoul ((char *) hex2_data, NULL, 16);
- if (val == ULONG_MAX)
- {
- gnutls_assert ();
- return GNUTLS_E_SRP_PWD_PARSING_ERROR;
- }
- bin_data[j] = val;
+ hex2_data[0] = hex_data[i];
+ hex2_data[1] = hex_data[i + 1];
+ i+=2;
+
+ val = strtoul ((char *) hex2_data, NULL, 16);
+ if (val == ULONG_MAX) {
+ gnutls_assert ();
+ return GNUTLS_E_PARSING_ERROR;
+ }
+ bin_data[j] = val;
+ j++;
}
+ *bin_size = j;
return 0;
}
#define GNUTLS_E_CRYPTODEV_IOCTL_ERROR -211
#define GNUTLS_E_CRYPTODEV_DEVICE_ERROR -212
+/* PKCS11 related */
+#define GNUTLS_E_PKCS11_ERROR -300
+#define GNUTLS_E_PKCS11_LOAD_ERROR -301
+#define GNUTLS_E_PARSING_ERROR -302
+#define GNUTLS_E_PKCS11_PIN_ERROR -303
+
#define GNUTLS_E_UNIMPLEMENTED_FEATURE -1250
+
+
#define GNUTLS_E_APPLICATION_ERROR_MAX -65000
#define GNUTLS_E_APPLICATION_ERROR_MIN -65500
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
-/**
- * @brief PKCS#11 error
- */
-#define GNUTLS_E_PKCS11_ERROR (GNUTLS_E_APPLICATION_ERROR_MIN+529)
-#define GNUTLS_E_PKCS11_LOAD_ERROR 1821
-#define GNUTLS_E_PARSING_ERROR 1822
-#define GNUTLS_E_PKCS11_PIN_ERROR 1823
#define GNUTLS_PKCS11_MAX_PIN_LEN 32
* @param data Data to use when calling callback.
* @return gnutls status.
*/
-void gnutls_pkcs11_set_pin_function (const gnutls_pkcs11_pin_callback_t callback, void * const data);
+void gnutls_pkcs11_set_pin_function (gnutls_pkcs11_pin_callback_t callback, void * const data);
/**
* @brief Add PKCS#11 provider.
#define MAX_PROVIDERS 16
#define ID_SIZE 128
+#define LABEL_SIZE 128
-typedef int (*find_func_t)(pakchois_session_t *pks, struct ck_token_info* tinfo, void* input);
struct gnutls_pkcs11_provider_s {
pakchois_module_t *module;
ck_slot_id_t *slots;
};
+
struct pkcs11_url_info
{
/* everything here is null terminated strings */
- opaque id[ID_SIZE];
+ opaque id[ID_SIZE*3+1]; /* hex with delimiters */
opaque type[16]; /* cert/key etc. */
opaque manufacturer[sizeof (((struct ck_token_info *)NULL)->manufacturer_id)+1];
opaque token[sizeof (((struct ck_token_info *)NULL)->label)+1];
opaque serial[sizeof (((struct ck_token_info *)NULL)->serial_number)+1];
opaque model[sizeof (((struct ck_token_info *)NULL)->model)+1];
+ opaque label[LABEL_SIZE+1];
};
struct gnutls_pkcs11_crt_st {
struct url_find_data_st {
gnutls_pkcs11_crt_t crt;
- char certid_raw[ID_SIZE/2];
+ char certid_raw[ID_SIZE];
size_t certid_raw_size;
};
struct pkcs11_url_info info;
};
+struct token_info {
+ struct ck_token_info tinfo;
+ struct ck_slot_info sinfo;
+ ck_slot_id_t sid;
+ struct gnutls_pkcs11_provider_s* prov;
+};
+
+typedef int (*find_func_t)(pakchois_session_t *pks, struct token_info* tinfo, void* input);
+
static struct gnutls_pkcs11_provider_s providers[MAX_PROVIDERS];
static int active_providers = 0;
goto fail;
}
- _gnutls_debug_log("p11: loaded provider '%s' with %d slots\n", name, providers[active_providers-1].nslots);
+ _gnutls_debug_log("p11: loaded provider '%s' with %d slots\n", name, (int)providers[active_providers-1].nslots);
return 0;
static int pkcs11_url_to_info(const char* url, struct pkcs11_url_info* info)
{
int ret;
-char* p1;
-char* hexid = NULL;
+char* p1, *p2;
size_t l;
memset( info, 0, sizeof(*info));
}
}
+ if ((p1=strstr(url, "object="))!= NULL) {
+ p1+=sizeof("object=")-1;
+ l=sizeof (info->label);
+
+ ret = unescape_string(info->label, 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;
- hexid = gnutls_strdup(p1);
- if (hexid == NULL) {
- goto cleanup;
- }
- if ((p1=strchr(hexid, ';'))!= NULL) {
- *p1 = 0;
+ if ((p2=strchr(p1, ';'))== NULL) {
+ l = strlen(p1);
} else {
- ret = GNUTLS_E_PARSING_ERROR;
- goto cleanup;
+ l = p2 - p1;
}
-
- l = sizeof(info->id);
- ret = _gnutls_hex2bin(hexid, strlen(hexid), info->id, &l);
- if (ret < 0) {
+
+ if (l > sizeof(info->id)-1) {
gnutls_assert();
- return ret;
+ ret = GNUTLS_E_PARSING_ERROR;
}
+
+ memcpy(info->id, p1, l);
+ info->id[l] = 0;
}
ret = 0;
cleanup:
- gnutls_free(hexid);
return ret;
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) {
init = 1;
}
+
if (info->manufacturer[0]) {
ret = append(&str, info->manufacturer, "manufacturer", init);
if (ret < 0) {
init = 1;
}
- if (info->serial[0]) {
- ret = append(&str, info->serial, "serial", init);
+ if (info->label[0]) {
+ ret = append(&str, info->label, "object", init);
if (ret < 0) {
gnutls_assert();
goto cleanup;
}
init = 1;
}
-
+
ret = _gnutls_string_append_printf(&str, ";id=%s", info->id);
if (ret < 0) {
gnutls_assert();
ptr[1] = '\0';
}
-static int pk11_login(struct gnutls_pkcs11_provider_s *prov, ck_slot_id_t slot_id,
- pakchois_session_t *pks, struct ck_slot_info *sinfo, struct ck_token_info* tinfo)
-{
- int attempt = 0;
- ck_rv_t rv;
-
- if (pakchois_get_token_info(prov->module, slot_id, tinfo) != CKR_OK) {
- gnutls_assert();
- _gnutls_debug_log("pk11: GetTokenInfo failed\n");
- return GNUTLS_E_PKCS11_ERROR;
- }
-
- if ((tinfo->flags & CKF_LOGIN_REQUIRED) == 0) {
- _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 (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) {
- gnutls_assert();
- _gnutls_debug_log("pk11: No pin callback but login required.\n");
- return GNUTLS_E_PKCS11_PIN_ERROR;
- }
-
- terminate_string(sinfo->slot_description, sizeof 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(prov->module, slot_id,
- tinfo) != CKR_OK) {
- _gnutls_debug_log("pk11: GetTokenInfo failed\n");
- gnutls_assert();
- return GNUTLS_E_PKCS11_ERROR;
- }
- }
-
- if (tinfo->flags & CKF_USER_PIN_COUNT_LOW)
- flags |= GNUTLS_PKCS11_PIN_COUNT_LOW;
- if (tinfo->flags & CKF_USER_PIN_FINAL_TRY)
- flags |= GNUTLS_PKCS11_PIN_FINAL_TRY;
-
- terminate_string(tinfo->label, sizeof tinfo->label);
-
- if (pin_func(pin_data, attempt++,
- (char *)sinfo->slot_description,
- (char *)tinfo->label, flags, pin, sizeof(pin))) {
- return GNUTLS_E_PKCS11_PIN_ERROR;
- }
-
- rv = pakchois_login(pks, CKU_USER, (unsigned char *)pin, strlen(pin));
-
- /* 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 : GNUTLS_E_PKCS11_ERROR;
-}
static int traverse_tokens (find_func_t find_func, void* input)
{
for (x=0;x<active_providers;x++) {
for (z=0;z<providers[x].nslots;z++) {
- struct ck_token_info tinfo;
+ struct token_info info;
+
rv = pakchois_open_session(providers[x].module, providers[x].slots[z],
CKF_SERIAL_SESSION, NULL, NULL, &pks);
if (rv != CKR_OK) {
continue;
}
- if (pakchois_get_token_info(providers[x].module, providers[x].slots[z], &tinfo) != CKR_OK) {
+ if (pakchois_get_token_info(providers[x].module, providers[x].slots[z], &info.tinfo) != CKR_OK) {
+ continue;
+ }
+ info.sid = providers[x].slots[z];
+ info.prov = &providers[x];
+
+ if (pakchois_get_slot_info(providers[x].module, providers[x].slots[z], &info.sinfo) != CKR_OK) {
continue;
}
/* XXX make wrapper for token_info? */
- 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);
+ terminate_string(info.tinfo.manufacturer_id, sizeof info.tinfo.manufacturer_id);
+ terminate_string(info.tinfo.label, sizeof info.tinfo.label);
+ terminate_string(info.tinfo.model, sizeof info.tinfo.model);
+ terminate_string(info.tinfo.serial_number, sizeof info.tinfo.serial_number);
- ret = find_func(pks, &tinfo, input);
+ ret = find_func(pks, &info, input);
pakchois_close_session(pks);
pks = NULL;
/* imports a raw certificate from a token to a pkcs11_crt_t structure.
*/
static int pkcs11_crt_import(gnutls_pkcs11_crt_t crt, const gnutls_datum_t* data,
- const gnutls_datum_t * id, struct ck_token_info* tinfo)
+ const gnutls_datum_t * id, const gnutls_datum_t * label, struct ck_token_info* tinfo)
{
char *s;
int ret;
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);
+
+ memcpy(crt->info.label, label->data, label->size);
+ crt->info.label[label->size] = 0;
+
strcpy(crt->info.type, "cert");
s = _gnutls_bin2hex(id->data, id->size, crt->info.id, sizeof(crt->info.id), ":");
}
-static int find_url(pakchois_session_t *pks, struct ck_token_info *tinfo, void* input)
+static int find_cert_url(pakchois_session_t *pks, struct token_info *info, void* input)
{
struct url_find_data_st* find_data = input;
- struct ck_attribute a[3];
+ struct ck_attribute a[4];
ck_object_class_t class;
ck_certificate_type_t type;
ck_rv_t rv;
unsigned long count;
int found = 0, ret;
unsigned char value[8192], subject[8192];
- char certid_tmp[ID_SIZE/2];
+ char certid_tmp[ID_SIZE];
+ char label_tmp[LABEL_SIZE];
- if (tinfo == NULL) { /* we don't support multiple calls */
+ 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 (find_data->crt->info.manufacturer[0] != 0) {
- if (strcmp(find_data->crt->info.manufacturer, tinfo->manufacturer_id) != 0)
+ if (strcmp(find_data->crt->info.manufacturer, info->tinfo.manufacturer_id) != 0)
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
}
if (find_data->crt->info.token[0] != 0) {
- if (strcmp(find_data->crt->info.token, tinfo->label) != 0)
+ if (strcmp(find_data->crt->info.token, info->tinfo.label) != 0)
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
}
if (find_data->crt->info.model[0] != 0) {
- if (strcmp(find_data->crt->info.model, tinfo->model) != 0)
+ if (strcmp(find_data->crt->info.model, info->tinfo.model) != 0)
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
}
if (find_data->crt->info.serial[0] != 0) {
- if (strcmp(find_data->crt->info.serial, tinfo->serial_number) != 0)
+ if (strcmp(find_data->crt->info.serial, info->tinfo.serial_number) != 0)
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
}
a[1].type = CKA_ID;
a[1].value = certid_tmp;
a[1].value_len = sizeof(certid_tmp);
- a[2].type = CKA_SUBJECT;
- a[2].value = subject;
- a[2].value_len = sizeof subject;
+ a[2].type = CKA_LABEL;
+ a[2].value = label_tmp;
+ a[2].value_len = sizeof(label_tmp);
if (pakchois_get_attribute_value(pks, obj, a, 3) == CKR_OK) {
+char buf[512];
+char buf2[512];
+fprintf(stderr, "val: %d, certid: %d\n", a[1].value_len, find_data->certid_raw_size);
+fprintf(stderr, "fcertid: %s, gcertid: %s\n", _gnutls_bin2hex (a[1].value, a[1].value_len, buf,
+ sizeof (buf), NULL), _gnutls_bin2hex (a[1].value, a[1].value_len, buf2,
+ sizeof (buf2), NULL));
if (a[1].value_len == find_data->certid_raw_size &&
memcmp(certid_tmp, find_data->certid_raw, find_data->certid_raw_size)==0) {
gnutls_datum_t id = { a[1].value, a[1].value_len };
gnutls_datum_t data = { a[0].value, a[0].value_len };
+ gnutls_datum_t label = { a[2].value, a[2].value_len };
- ret = pkcs11_crt_import(find_data->crt, &data, &id, tinfo);
+ ret = pkcs11_crt_import(find_data->crt, &data, &id, &label, &info->tinfo);
if (ret < 0) {
gnutls_assert();
goto cleanup;
{
int ret;
struct url_find_data_st find_data;
- size_t size;
/* fill in the find data structure */
find_data.crt = cert;
find_data.certid_raw_size = sizeof(find_data.certid_raw);
- size = find_data.certid_raw_size;
- ret = _gnutls_hex2bin(cert->info.id, sizeof cert->info.id, find_data.certid_raw, &size);
+ ret = _gnutls_hex2bin(cert->info.id, strlen(cert->info.id), find_data.certid_raw, &find_data.certid_raw_size);
if (ret < 0) {
gnutls_assert();
return ret;
}
-
- ret = traverse_tokens(find_url, &find_data);
+fprintf(stderr, "hex2bin: %d, %d\n", ret, find_data.certid_raw_size);
+ ret = traverse_tokens(find_cert_url, &find_data);
if (ret < 0) {
gnutls_assert();
return ret;
return certificate->type;
}
+struct pkey_list {
+ gnutls_string *key_ids;
+ size_t key_ids_size;
+};
+
+static int pk11_login(pakchois_session_t *pks, struct token_info *info)
+{
+ struct ck_token_info tinfo;
+ int attempt = 0;
+ ck_rv_t rv;
+
+ 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;
+ }
+
+ /* force login on HW tokens. Some tokens will not list private keys
+ * if login has not been performed.
+ */
+ if (!(info->sinfo.flags & CKF_HW_SLOT) && (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 (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) {
+ 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 (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);
+
+ if (pin_func(pin_data, attempt++,
+ (char *)info->sinfo.slot_description,
+ (char *)info->tinfo.label, flags, pin, sizeof(pin))) {
+ gnutls_assert();
+ return GNUTLS_E_PKCS11_PIN_ERROR;
+ }
+
+ rv = pakchois_login(pks, CKU_USER, (unsigned char *)pin, strlen(pin));
+
+ /* 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 : GNUTLS_E_PKCS11_ERROR;
+}
+
+
+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[ID_SIZE];
+ int ret;
+
+ class = CKO_PRIVATE_KEY;
+
+ ret = pk11_login(pks, info);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ /* 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 GNUTLS_E_PKCS11_ERROR;
+ }
+
+ 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_string)*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 GNUTLS_E_PKCS11_ERROR;
+ }
+
+ 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_string_init(&list->key_ids[current], gnutls_malloc, gnutls_realloc, gnutls_free);
+
+ if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) {
+ _gnutls_string_append_data(&list->key_ids[current], a[0].value, a[0].value_len);
+ current++;
+ }
+
+ if (current > list->key_ids_size)
+ break;
+ }
+
+ pakchois_find_objects_final(pks);
+
+ list->key_ids_size = current-1;
+
+ return 0;
+}
+
/* Recover certificate list from tokens */
-static int find_crts(pakchois_session_t *pks, struct ck_token_info *tinfo, void* input)
+
+static int find_crts(pakchois_session_t *pks, struct token_info *info, void* input)
{
struct crt_find_data_st* find_data = input;
- struct ck_attribute a[3];
+ struct ck_attribute a[4];
ck_object_class_t class;
ck_certificate_type_t type;
bool trusted;
ck_object_handle_t obj;
unsigned long count;
unsigned char value[8192], subject[8192];
- char certid_tmp[ID_SIZE/2];
+ char certid_tmp[ID_SIZE];
+ char label_tmp[LABEL_SIZE];
int ret, i;
+ struct pkey_list plist; /* private key holder */
- if (tinfo == NULL) { /* final call */
+ if (info == NULL) { /* final call */
if (find_data->current <= *find_data->n_list)
ret = 0;
else
/* do not bother reading the token if basic fields do not match
*/
if (find_data->info.manufacturer[0] != 0) {
- if (strcmp(find_data->info.manufacturer, tinfo->manufacturer_id) != 0)
+ if (strcmp(find_data->info.manufacturer, info->tinfo.manufacturer_id) != 0)
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
}
if (find_data->info.token[0] != 0) {
- if (strcmp(find_data->info.token, tinfo->label) != 0)
+ if (strcmp(find_data->info.token, info->tinfo.label) != 0)
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
}
if (find_data->info.model[0] != 0) {
- if (strcmp(find_data->info.model, tinfo->model) != 0)
+ if (strcmp(find_data->info.model, info->tinfo.model) != 0)
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
}
if (find_data->info.serial[0] != 0) {
- if (strcmp(find_data->info.serial, tinfo->serial_number) != 0)
+ if (strcmp(find_data->info.serial, info->tinfo.serial_number) != 0)
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
}
}
}
+ memset(&plist, 0, sizeof(plist));
+ if (find_data->flags==GNUTLS_PKCS11_CRT_ATTR_WITH_PK) {
+ 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;
+ }
+ }
+
/* Find objects with cert class and X.509 cert type. */
class = CKO_CERTIFICATE;
type = CKC_X_509;
a[1].type = CKA_ID;
a[1].value = certid_tmp;
a[1].value_len = sizeof(certid_tmp);
- a[2].type = CKA_SUBJECT;
- a[2].value = subject;
- a[2].value_len = sizeof subject;
+ a[2].type = CKA_LABEL;
+ a[2].value = label_tmp;
+ a[2].value_len = sizeof label_tmp;
if (pakchois_get_attribute_value(pks, obj, a, 3) == CKR_OK) {
gnutls_datum_t data = { a[0].value, a[0].value_len };
gnutls_datum_t id = { a[1].value, a[1].value_len };
-
+ gnutls_datum_t label = { a[2].value, a[2].value_len };
+
/* XXX check also ID with find_data->info.id */
if (find_data->flags == GNUTLS_PKCS11_CRT_ATTR_WITH_PK) {
- gnutls_assert();
- /* XXX verify that certificate has a corresponding private key */
- //not yet
+ 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) {
gnutls_assert();
goto fail;
}
-
- ret = pkcs11_crt_import(find_data->p_list[find_data->current], &data, &id, tinfo);
+
+ ret = pkcs11_crt_import(find_data->p_list[find_data->current], &data, &id, &label, &info->tinfo);
if (ret < 0) {
gnutls_assert();
goto fail;
fail:
pakchois_find_objects_final(pks);
+ if (plist.key_ids != NULL) {
+ for (i=0;i<plist.key_ids_size;i++) {
+ _gnutls_string_clear(&plist.key_ids[i]);
+ }
+ gnutls_free( plist.key_ids);
+ }
for (i=0;i<find_data->current;i++) {
gnutls_pkcs11_crt_deinit(find_data->p_list[i]);
}
#if 0
#define KEYTYPE_IS_DSA(kt) (kt == CKK_DSA)
-static int pk11_find_pkey(ne_ssl_pkcs11_provider *prov,
- pakchois_session_t *pks,
- unsigned char *certid, unsigned long cid_len)
-{
- struct ck_attribute a[3];
- ck_object_class_t class;
- ck_rv_t rv;
- ck_object_handle_t obj;
- unsigned long count;
- int found = 0;
-
- 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;
- a[1].type = CKA_ID;
- a[1].value = certid;
- a[1].value_len = cid_len;
-
- rv = pakchois_find_objects_init(pks, a, 2);
- if (rv != CKR_OK) {
- NE_DEBUG(NE_DBG_SSL, "pk11: FindObjectsInit failed.\n");
- /* TODO: error propagation */
- return 0;
- }
-
- rv = pakchois_find_objects(pks, &obj, 1, &count);
- if (rv == CKR_OK && count == 1) {
- NE_DEBUG(NE_DBG_SSL, "pk11: Found private key.\n");
-
- a[0].type = CKA_KEY_TYPE;
- a[0].value = &prov->keytype;
- a[0].value_len = sizeof prov->keytype;
-
- if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK
- && (prov->keytype == CKK_RSA || KEYTYPE_IS_DSA(prov->keytype))) {
- found = 1;
- prov->privkey = obj;
- }
- else {
- NE_DEBUG(NE_DBG_SSL, "pk11: Could not determine key type.\n");
- }
- }
-
- pakchois_find_objects_final(pks);
-
- return found;
-}
static int find_client_cert(ne_ssl_pkcs11_provider *prov,
pakchois_session_t *pks)
+#include <gnutls/x509.h>
+#include <stdio.h>
+
enum
{
ACTION_SELF_SIGNED,
ACTION_RING_INFO,
ACTION_REQUEST,
ACTION_PKCS11_LIST,
+ ACTION_PKCS11_EXPORT_URL,
};
#define TYPE_CRT 1
#define TYPE_CRQ 2
void certtool_version (void);
-void pkcs11_list( const char* url);
+void pkcs11_list( const char* url, int type);
+void pkcs11_export(FILE* outfile, const char *pkcs11_url);
+void print_certificate_info (gnutls_x509_crt_t crt, FILE * out,
+ unsigned int);
+#define PKCS11_TYPE_ALL 1
+#define PKCS11_TYPE_TRUSTED 2
+#define PKCS11_TYPE_PK 3
__gaa_helpsingle(0, "v1", "", "Generate an X.509 version 1 certificate (no extensions).");
__gaa_helpsingle(0, "to-p12", "", "Generate a PKCS #12 structure.");
__gaa_helpsingle(0, "to-p8", "", "Generate a PKCS #8 key structure.");
- __gaa_helpsingle(0, "pkcs11-provider", "Library ", "Specify the pkcs11 provider library");
- __gaa_helpsingle(0, "pkcs11-url", "URL ", "Specify a pkcs11 URL");
- __gaa_helpsingle(0, "pkcs11-list", "", "List objects specified by a PKCS#11 URL");
__gaa_helpsingle('8', "pkcs8", "", "Use PKCS #8 format for private keys.");
__gaa_helpsingle(0, "dsa", "", "Use DSA keys.");
__gaa_helpsingle(0, "hash", "STR ", "Hash algorithm to use for signing (MD5,SHA1,RMD160,SHA256,SHA384,SHA512).");
__gaa_helpsingle(0, "infile", "FILE ", "Input file.");
__gaa_helpsingle(0, "template", "FILE ", "Template file to use for non interactive operation.");
__gaa_helpsingle(0, "pkcs-cipher", "CIPHER ", "Cipher to use for pkcs operations (3des,aes-128,aes-192,aes-256,rc2-40).");
+ __gaa_helpsingle(0, "pkcs11-provider", "Library ", "Specify the pkcs11 provider library");
+ __gaa_helpsingle(0, "pkcs11-export-url", "URL ", "Export data specified a pkcs11 URL");
+ __gaa_helpsingle(0, "pkcs11-list", "", "List objects specified by a PKCS#11 URL");
+ __gaa_helpsingle(0, "pkcs11-list-trusted", "", "List objects marked as trusted, specified by a PKCS#11 URL");
+ __gaa_helpsingle(0, "pkcs11-list-all", "", "List all objects specified by a PKCS#11 URL");
__gaa_helpsingle('d', "debug", "LEVEL ", "specify the debug level. Default is 1.");
__gaa_helpsingle('h', "help", "", "shows this help text");
__gaa_helpsingle('v', "version", "", "shows the program's version");
struct _gaainfo
{
-#line 139 "certtool.gaa"
+#line 142 "certtool.gaa"
int debug;
-#line 135 "certtool.gaa"
+#line 137 "certtool.gaa"
+ int pkcs11_type;
+#line 134 "certtool.gaa"
+ char* pkcs11_url;
+#line 131 "certtool.gaa"
+ char* pkcs11_provider;
+#line 128 "certtool.gaa"
char *pkcs_cipher;
-#line 132 "certtool.gaa"
+#line 125 "certtool.gaa"
char *template;
-#line 129 "certtool.gaa"
+#line 122 "certtool.gaa"
char *infile;
-#line 126 "certtool.gaa"
+#line 119 "certtool.gaa"
char *outfile;
-#line 123 "certtool.gaa"
+#line 116 "certtool.gaa"
int quick_random;
-#line 120 "certtool.gaa"
+#line 113 "certtool.gaa"
int bits;
-#line 116 "certtool.gaa"
+#line 109 "certtool.gaa"
int outcert_format;
-#line 112 "certtool.gaa"
+#line 105 "certtool.gaa"
int incert_format;
-#line 109 "certtool.gaa"
+#line 102 "certtool.gaa"
int export;
-#line 106 "certtool.gaa"
+#line 99 "certtool.gaa"
char *hash;
-#line 103 "certtool.gaa"
+#line 96 "certtool.gaa"
int dsa;
-#line 100 "certtool.gaa"
+#line 93 "certtool.gaa"
int pkcs8;
-#line 95 "certtool.gaa"
- char* pkcs11_url;
-#line 92 "certtool.gaa"
- char* pkcs11_provider;
#line 85 "certtool.gaa"
int v1_cert;
#line 82 "certtool.gaa"
#define GAA_MULTIPLE_OPTION 3
#define GAA_REST 0
-#define GAA_NB_OPTION 52
+#define GAA_NB_OPTION 54
#define GAAOPTID_version 1
#define GAAOPTID_help 2
#define GAAOPTID_debug 3
-#define GAAOPTID_pkcs_cipher 4
-#define GAAOPTID_template 5
-#define GAAOPTID_infile 6
-#define GAAOPTID_outfile 7
-#define GAAOPTID_disable_quick_random 8
-#define GAAOPTID_bits 9
-#define GAAOPTID_outraw 10
-#define GAAOPTID_outder 11
-#define GAAOPTID_inraw 12
-#define GAAOPTID_inder 13
-#define GAAOPTID_export_ciphers 14
-#define GAAOPTID_hash 15
-#define GAAOPTID_dsa 16
-#define GAAOPTID_pkcs8 17
-#define GAAOPTID_pkcs11_list 18
-#define GAAOPTID_pkcs11_url 19
-#define GAAOPTID_pkcs11_provider 20
-#define GAAOPTID_to_p8 21
-#define GAAOPTID_to_p12 22
-#define GAAOPTID_v1 23
-#define GAAOPTID_fix_key 24
-#define GAAOPTID_pgp_key_info 25
-#define GAAOPTID_key_info 26
-#define GAAOPTID_smime_to_p7 27
-#define GAAOPTID_p7_info 28
-#define GAAOPTID_p12_info 29
-#define GAAOPTID_no_crq_extensions 30
-#define GAAOPTID_crq_info 31
-#define GAAOPTID_crl_info 32
-#define GAAOPTID_pgp_ring_info 33
-#define GAAOPTID_pgp_certificate_info 34
-#define GAAOPTID_certificate_info 35
-#define GAAOPTID_password 36
-#define GAAOPTID_load_ca_certificate 37
-#define GAAOPTID_load_ca_privkey 38
-#define GAAOPTID_load_certificate 39
-#define GAAOPTID_load_request 40
-#define GAAOPTID_load_privkey 41
-#define GAAOPTID_get_dh_params 42
-#define GAAOPTID_generate_dh_params 43
-#define GAAOPTID_verify_crl 44
-#define GAAOPTID_verify_chain 45
-#define GAAOPTID_generate_request 46
-#define GAAOPTID_generate_privkey 47
-#define GAAOPTID_update_certificate 48
-#define GAAOPTID_generate_crl 49
-#define GAAOPTID_generate_proxy 50
-#define GAAOPTID_generate_certificate 51
-#define GAAOPTID_generate_self_signed 52
+#define GAAOPTID_pkcs11_list_all 4
+#define GAAOPTID_pkcs11_list_trusted 5
+#define GAAOPTID_pkcs11_list 6
+#define GAAOPTID_pkcs11_export_url 7
+#define GAAOPTID_pkcs11_provider 8
+#define GAAOPTID_pkcs_cipher 9
+#define GAAOPTID_template 10
+#define GAAOPTID_infile 11
+#define GAAOPTID_outfile 12
+#define GAAOPTID_disable_quick_random 13
+#define GAAOPTID_bits 14
+#define GAAOPTID_outraw 15
+#define GAAOPTID_outder 16
+#define GAAOPTID_inraw 17
+#define GAAOPTID_inder 18
+#define GAAOPTID_export_ciphers 19
+#define GAAOPTID_hash 20
+#define GAAOPTID_dsa 21
+#define GAAOPTID_pkcs8 22
+#define GAAOPTID_to_p8 23
+#define GAAOPTID_to_p12 24
+#define GAAOPTID_v1 25
+#define GAAOPTID_fix_key 26
+#define GAAOPTID_pgp_key_info 27
+#define GAAOPTID_key_info 28
+#define GAAOPTID_smime_to_p7 29
+#define GAAOPTID_p7_info 30
+#define GAAOPTID_p12_info 31
+#define GAAOPTID_no_crq_extensions 32
+#define GAAOPTID_crq_info 33
+#define GAAOPTID_crl_info 34
+#define GAAOPTID_pgp_ring_info 35
+#define GAAOPTID_pgp_certificate_info 36
+#define GAAOPTID_certificate_info 37
+#define GAAOPTID_password 38
+#define GAAOPTID_load_ca_certificate 39
+#define GAAOPTID_load_ca_privkey 40
+#define GAAOPTID_load_certificate 41
+#define GAAOPTID_load_request 42
+#define GAAOPTID_load_privkey 43
+#define GAAOPTID_get_dh_params 44
+#define GAAOPTID_generate_dh_params 45
+#define GAAOPTID_verify_crl 46
+#define GAAOPTID_verify_chain 47
+#define GAAOPTID_generate_request 48
+#define GAAOPTID_generate_privkey 49
+#define GAAOPTID_update_certificate 50
+#define GAAOPTID_generate_crl 51
+#define GAAOPTID_generate_proxy 52
+#define GAAOPTID_generate_certificate 53
+#define GAAOPTID_generate_self_signed 54
#line 168 "gaa.skel"
int size1;
};
-struct GAAOPTION_pkcs_cipher
+struct GAAOPTION_pkcs11_export_url
{
char* arg1;
int size1;
};
-struct GAAOPTION_template
+struct GAAOPTION_pkcs11_provider
{
char* arg1;
int size1;
};
-struct GAAOPTION_infile
+struct GAAOPTION_pkcs_cipher
{
char* arg1;
int size1;
};
-struct GAAOPTION_outfile
+struct GAAOPTION_template
{
char* arg1;
int size1;
};
-struct GAAOPTION_bits
+struct GAAOPTION_infile
{
- int arg1;
+ char* arg1;
int size1;
};
-struct GAAOPTION_hash
+struct GAAOPTION_outfile
{
char* arg1;
int size1;
};
-struct GAAOPTION_pkcs11_url
+struct GAAOPTION_bits
{
- char* arg1;
+ int arg1;
int size1;
};
-struct GAAOPTION_pkcs11_provider
+struct GAAOPTION_hash
{
char* arg1;
int size1;
{
case GAA_LETTER_OPTION:
GAA_CHECK1STR("d", GAAOPTID_debug);
+ GAA_CHECK1STR("", GAAOPTID_pkcs11_export_url);
+ GAA_CHECK1STR("", GAAOPTID_pkcs11_provider);
GAA_CHECK1STR("", GAAOPTID_pkcs_cipher);
GAA_CHECK1STR("", GAAOPTID_template);
GAA_CHECK1STR("", GAAOPTID_infile);
GAA_CHECK1STR("", GAAOPTID_outfile);
GAA_CHECK1STR("", GAAOPTID_bits);
GAA_CHECK1STR("", GAAOPTID_hash);
- GAA_CHECK1STR("", GAAOPTID_pkcs11_url);
- GAA_CHECK1STR("", GAAOPTID_pkcs11_provider);
GAA_CHECK1STR("", GAAOPTID_password);
GAA_CHECK1STR("", GAAOPTID_load_ca_certificate);
GAA_CHECK1STR("", GAAOPTID_load_ca_privkey);
#line 375 "gaa.skel"
GAA_CHECK1STR("v", GAAOPTID_version);
GAA_CHECK1STR("h", GAAOPTID_help);
+ GAA_CHECK1STR("", GAAOPTID_pkcs11_list_all);
+ GAA_CHECK1STR("", GAAOPTID_pkcs11_list_trusted);
+ GAA_CHECK1STR("", GAAOPTID_pkcs11_list);
GAA_CHECK1STR("", GAAOPTID_disable_quick_random);
GAA_CHECK1STR("", GAAOPTID_outraw);
GAA_CHECK1STR("", GAAOPTID_outder);
GAA_CHECK1STR("", GAAOPTID_export_ciphers);
GAA_CHECK1STR("", GAAOPTID_dsa);
GAA_CHECK1STR("8", GAAOPTID_pkcs8);
- GAA_CHECK1STR("", GAAOPTID_pkcs11_list);
GAA_CHECK1STR("", GAAOPTID_to_p8);
GAA_CHECK1STR("", GAAOPTID_to_p12);
GAA_CHECK1STR("", GAAOPTID_v1);
GAA_CHECKSTR("version", GAAOPTID_version);
GAA_CHECKSTR("help", GAAOPTID_help);
GAA_CHECKSTR("debug", GAAOPTID_debug);
+ GAA_CHECKSTR("pkcs11-list-all", GAAOPTID_pkcs11_list_all);
+ GAA_CHECKSTR("pkcs11-list-trusted", GAAOPTID_pkcs11_list_trusted);
+ GAA_CHECKSTR("pkcs11-list", GAAOPTID_pkcs11_list);
+ GAA_CHECKSTR("pkcs11-export-url", GAAOPTID_pkcs11_export_url);
+ GAA_CHECKSTR("pkcs11-provider", GAAOPTID_pkcs11_provider);
GAA_CHECKSTR("pkcs-cipher", GAAOPTID_pkcs_cipher);
GAA_CHECKSTR("template", GAAOPTID_template);
GAA_CHECKSTR("infile", GAAOPTID_infile);
GAA_CHECKSTR("hash", GAAOPTID_hash);
GAA_CHECKSTR("dsa", GAAOPTID_dsa);
GAA_CHECKSTR("pkcs8", GAAOPTID_pkcs8);
- GAA_CHECKSTR("pkcs11-list", GAAOPTID_pkcs11_list);
- GAA_CHECKSTR("pkcs11-url", GAAOPTID_pkcs11_url);
- GAA_CHECKSTR("pkcs11-provider", GAAOPTID_pkcs11_provider);
GAA_CHECKSTR("to-p8", GAAOPTID_to_p8);
GAA_CHECKSTR("to-p12", GAAOPTID_to_p12);
GAA_CHECKSTR("v1", GAAOPTID_v1);
int OK = 0;
int gaa_last_non_option;
struct GAAOPTION_debug GAATMP_debug;
+ struct GAAOPTION_pkcs11_export_url GAATMP_pkcs11_export_url;
+ struct GAAOPTION_pkcs11_provider GAATMP_pkcs11_provider;
struct GAAOPTION_pkcs_cipher GAATMP_pkcs_cipher;
struct GAAOPTION_template GAATMP_template;
struct GAAOPTION_infile GAATMP_infile;
struct GAAOPTION_outfile GAATMP_outfile;
struct GAAOPTION_bits GAATMP_bits;
struct GAAOPTION_hash GAATMP_hash;
- struct GAAOPTION_pkcs11_url GAATMP_pkcs11_url;
- struct GAAOPTION_pkcs11_provider GAATMP_pkcs11_provider;
struct GAAOPTION_password GAATMP_password;
struct GAAOPTION_load_ca_certificate GAATMP_load_ca_certificate;
struct GAAOPTION_load_ca_privkey GAATMP_load_ca_privkey;
{
case GAAOPTID_version:
OK = 0;
-#line 144 "certtool.gaa"
+#line 147 "certtool.gaa"
{ certtool_version(); exit(0); ;};
return GAA_OK;
break;
case GAAOPTID_help:
OK = 0;
-#line 142 "certtool.gaa"
+#line 145 "certtool.gaa"
{ gaa_help(); exit(0); ;};
return GAA_OK;
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_debug.arg1, gaa_getint, GAATMP_debug.size1);
gaa_index++;
-#line 140 "certtool.gaa"
+#line 143 "certtool.gaa"
{ gaaval->debug = GAATMP_debug.arg1 ;};
+ return GAA_OK;
+ break;
+ case GAAOPTID_pkcs11_list_all:
+ OK = 0;
+#line 140 "certtool.gaa"
+{ gaaval->action = ACTION_PKCS11_LIST; gaaval->pkcs11_type=PKCS11_TYPE_ALL; ;};
+
+ return GAA_OK;
+ break;
+ case GAAOPTID_pkcs11_list_trusted:
+ OK = 0;
+#line 139 "certtool.gaa"
+{ gaaval->action = ACTION_PKCS11_LIST; gaaval->pkcs11_type=PKCS11_TYPE_TRUSTED; ;};
+
+ return GAA_OK;
+ break;
+ case GAAOPTID_pkcs11_list:
+ OK = 0;
+#line 138 "certtool.gaa"
+{ gaaval->action = ACTION_PKCS11_LIST; gaaval->pkcs11_type=PKCS11_TYPE_PK; ;};
+
+ return GAA_OK;
+ break;
+ case GAAOPTID_pkcs11_export_url:
+ OK = 0;
+ GAA_TESTMOREARGS;
+ GAA_FILL(GAATMP_pkcs11_export_url.arg1, gaa_getstr, GAATMP_pkcs11_export_url.size1);
+ gaa_index++;
+#line 135 "certtool.gaa"
+{ gaaval->action = ACTION_PKCS11_EXPORT_URL; gaaval->pkcs11_url = GAATMP_pkcs11_export_url.arg1; ;};
+
+ return GAA_OK;
+ break;
+ case GAAOPTID_pkcs11_provider:
+ OK = 0;
+ GAA_TESTMOREARGS;
+ GAA_FILL(GAATMP_pkcs11_provider.arg1, gaa_getstr, GAATMP_pkcs11_provider.size1);
+ gaa_index++;
+#line 132 "certtool.gaa"
+{ gaaval->pkcs11_provider = GAATMP_pkcs11_provider.arg1 ;};
+
return GAA_OK;
break;
case GAAOPTID_pkcs_cipher:
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_pkcs_cipher.arg1, gaa_getstr, GAATMP_pkcs_cipher.size1);
gaa_index++;
-#line 136 "certtool.gaa"
+#line 129 "certtool.gaa"
{ gaaval->pkcs_cipher = GAATMP_pkcs_cipher.arg1 ;};
return GAA_OK;
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_template.arg1, gaa_getstr, GAATMP_template.size1);
gaa_index++;
-#line 133 "certtool.gaa"
+#line 126 "certtool.gaa"
{ gaaval->template = GAATMP_template.arg1 ;};
return GAA_OK;
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_infile.arg1, gaa_getstr, GAATMP_infile.size1);
gaa_index++;
-#line 130 "certtool.gaa"
+#line 123 "certtool.gaa"
{ gaaval->infile = GAATMP_infile.arg1 ;};
return GAA_OK;
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_outfile.arg1, gaa_getstr, GAATMP_outfile.size1);
gaa_index++;
-#line 127 "certtool.gaa"
+#line 120 "certtool.gaa"
{ gaaval->outfile = GAATMP_outfile.arg1 ;};
return GAA_OK;
break;
case GAAOPTID_disable_quick_random:
OK = 0;
-#line 124 "certtool.gaa"
+#line 117 "certtool.gaa"
{ gaaval->quick_random = 0; ;};
return GAA_OK;
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_bits.arg1, gaa_getint, GAATMP_bits.size1);
gaa_index++;
-#line 121 "certtool.gaa"
+#line 114 "certtool.gaa"
{ gaaval->bits = GAATMP_bits.arg1 ;};
return GAA_OK;
break;
case GAAOPTID_outraw:
OK = 0;
-#line 118 "certtool.gaa"
+#line 111 "certtool.gaa"
{ gaaval->outcert_format=1 ;};
return GAA_OK;
break;
case GAAOPTID_outder:
OK = 0;
-#line 117 "certtool.gaa"
+#line 110 "certtool.gaa"
{ gaaval->outcert_format=1 ;};
return GAA_OK;
break;
case GAAOPTID_inraw:
OK = 0;
-#line 114 "certtool.gaa"
+#line 107 "certtool.gaa"
{ gaaval->incert_format=1 ;};
return GAA_OK;
break;
case GAAOPTID_inder:
OK = 0;
-#line 113 "certtool.gaa"
+#line 106 "certtool.gaa"
{ gaaval->incert_format=1 ;};
return GAA_OK;
break;
case GAAOPTID_export_ciphers:
OK = 0;
-#line 110 "certtool.gaa"
+#line 103 "certtool.gaa"
{ gaaval->export=1 ;};
return GAA_OK;
GAA_TESTMOREARGS;
GAA_FILL(GAATMP_hash.arg1, gaa_getstr, GAATMP_hash.size1);
gaa_index++;
-#line 107 "certtool.gaa"
+#line 100 "certtool.gaa"
{ gaaval->hash = GAATMP_hash.arg1 ;};
return GAA_OK;
break;
case GAAOPTID_dsa:
OK = 0;
-#line 104 "certtool.gaa"
+#line 97 "certtool.gaa"
{ gaaval->dsa=1 ;};
return GAA_OK;
break;
case GAAOPTID_pkcs8:
OK = 0;
-#line 101 "certtool.gaa"
+#line 94 "certtool.gaa"
{ gaaval->pkcs8=1 ;};
- return GAA_OK;
- break;
- case GAAOPTID_pkcs11_list:
- OK = 0;
-#line 98 "certtool.gaa"
-{ gaaval->action = ACTION_PKCS11_LIST ;};
-
- return GAA_OK;
- break;
- case GAAOPTID_pkcs11_url:
- OK = 0;
- GAA_TESTMOREARGS;
- GAA_FILL(GAATMP_pkcs11_url.arg1, gaa_getstr, GAATMP_pkcs11_url.size1);
- gaa_index++;
-#line 96 "certtool.gaa"
-{ gaaval->pkcs11_url = GAATMP_pkcs11_url.arg1 ;};
-
- return GAA_OK;
- break;
- case GAAOPTID_pkcs11_provider:
- OK = 0;
- GAA_TESTMOREARGS;
- GAA_FILL(GAATMP_pkcs11_provider.arg1, gaa_getstr, GAATMP_pkcs11_provider.size1);
- gaa_index++;
-#line 93 "certtool.gaa"
-{ gaaval->pkcs11_provider = GAATMP_pkcs11_provider.arg1 ;};
-
return GAA_OK;
break;
case GAAOPTID_to_p8:
if(inited == 0)
{
-#line 146 "certtool.gaa"
+#line 149 "certtool.gaa"
{ gaaval->bits = 2048; gaaval->pkcs8 = 0; gaaval->privkey = NULL; gaaval->ca=NULL; gaaval->ca_privkey = NULL;
gaaval->debug=1; gaaval->request = NULL; gaaval->infile = NULL; gaaval->outfile = NULL; gaaval->cert = NULL;
gaaval->incert_format = 0; gaaval->outcert_format = 0; gaaval->action=-1; gaaval->pass = NULL; gaaval->v1_cert = 0;
gaaval->export = 0; gaaval->template = NULL; gaaval->hash=NULL; gaaval->fix_key = 0; gaaval->quick_random=1;
gaaval->privkey_op = 0; gaaval->pkcs_cipher = "3des"; gaaval->crq_extensions=1; gaaval->pkcs11_provider= NULL;
- gaaval->pkcs11_url = NULL; ;};
+ gaaval->pkcs11_url = NULL; gaaval->pkcs11_type = PKCS11_TYPE_PK; ;};
}
inited = 1;
struct _gaainfo
{
-#line 139 "certtool.gaa"
+#line 142 "certtool.gaa"
int debug;
-#line 135 "certtool.gaa"
+#line 137 "certtool.gaa"
+ int pkcs11_type;
+#line 134 "certtool.gaa"
+ char* pkcs11_url;
+#line 131 "certtool.gaa"
+ char* pkcs11_provider;
+#line 128 "certtool.gaa"
char *pkcs_cipher;
-#line 132 "certtool.gaa"
+#line 125 "certtool.gaa"
char *template;
-#line 129 "certtool.gaa"
+#line 122 "certtool.gaa"
char *infile;
-#line 126 "certtool.gaa"
+#line 119 "certtool.gaa"
char *outfile;
-#line 123 "certtool.gaa"
+#line 116 "certtool.gaa"
int quick_random;
-#line 120 "certtool.gaa"
+#line 113 "certtool.gaa"
int bits;
-#line 116 "certtool.gaa"
+#line 109 "certtool.gaa"
int outcert_format;
-#line 112 "certtool.gaa"
+#line 105 "certtool.gaa"
int incert_format;
-#line 109 "certtool.gaa"
+#line 102 "certtool.gaa"
int export;
-#line 106 "certtool.gaa"
+#line 99 "certtool.gaa"
char *hash;
-#line 103 "certtool.gaa"
+#line 96 "certtool.gaa"
int dsa;
-#line 100 "certtool.gaa"
+#line 93 "certtool.gaa"
int pkcs8;
-#line 95 "certtool.gaa"
- char* pkcs11_url;
-#line 92 "certtool.gaa"
- char* pkcs11_provider;
#line 85 "certtool.gaa"
int v1_cert;
#line 82 "certtool.gaa"
void pgp_certificate_info (void);
void crl_info (void);
void privkey_info (void);
-static void print_certificate_info (gnutls_x509_crt_t crt, FILE * out,
- unsigned int);
static void gaa_parser (int argc, char **argv);
void generate_self_signed (void);
void generate_request (void);
generate_pkcs8 ();
break;
case ACTION_PKCS11_LIST:
- pkcs11_list(info.pkcs11_url);
+ pkcs11_list(info.pkcs11_url, info.pkcs11_type);
+ break;
+ case ACTION_PKCS11_EXPORT_URL:
+ pkcs11_export(outfile, info.pkcs11_url);
break;
#ifdef ENABLE_OPENPGP
case ACTION_PGP_INFO:
}
-static void
+void
print_certificate_info (gnutls_x509_crt_t crt, FILE * out, unsigned int all)
{
gnutls_datum_t cinfo;
option (to-p8) { $action = ACTION_GENERATE_PKCS8; } "Generate a PKCS #8 key structure."
-#char* pkcs11_provider;
-option (pkcs11-provider) STR "Library" { $pkcs11_provider = $1 } "Specify the pkcs11 provider library"
-
-#char* pkcs11_url;
-option (pkcs11-url) STR "URL" { $pkcs11_url = $1 } "Specify a pkcs11 URL"
-
-option (pkcs11-list) { $action = ACTION_PKCS11_LIST } "List objects specified by a PKCS#11 URL"
#int pkcs8;
option (8, pkcs8) { $pkcs8=1 } "Use PKCS #8 format for private keys."
#char *pkcs_cipher;
option (pkcs-cipher) STR "CIPHER" { $pkcs_cipher = $1 } "Cipher to use for pkcs operations (3des,aes-128,aes-192,aes-256,rc2-40)."
+#char* pkcs11_provider;
+option (pkcs11-provider) STR "Library" { $pkcs11_provider = $1 } "Specify the pkcs11 provider library"
+
+#char* pkcs11_url;
+option (pkcs11-export-url) STR "URL" { $action = ACTION_PKCS11_EXPORT_URL; $pkcs11_url = $1; } "Export data specified a pkcs11 URL"
+
+#int pkcs11_type;
+option (pkcs11-list) { $action = ACTION_PKCS11_LIST; $pkcs11_type=PKCS11_TYPE_PK; } "List objects specified by a PKCS#11 URL"
+option (pkcs11-list-trusted) { $action = ACTION_PKCS11_LIST; $pkcs11_type=PKCS11_TYPE_TRUSTED; } "List objects marked as trusted, specified by a PKCS#11 URL"
+option (pkcs11-list-all) { $action = ACTION_PKCS11_LIST; $pkcs11_type=PKCS11_TYPE_ALL; } "List all objects specified by a PKCS#11 URL"
#int debug;
option (d, debug) INT "LEVEL" { $debug = $1 } "specify the debug level. Default is 1."
$incert_format = 0; $outcert_format = 0; $action=-1; $pass = NULL; $v1_cert = 0;
$export = 0; $template = NULL; $hash=NULL; $fix_key = 0; $quick_random=1;
$privkey_op = 0; $pkcs_cipher = "3des"; $crq_extensions=1; $pkcs11_provider= NULL;
- $pkcs11_url = NULL; }
+ $pkcs11_url = NULL; $pkcs11_type = PKCS11_TYPE_PK; }
#include <stdio.h>
#include <stdlib.h>
#include "certtool-common.h"
+#include "certtool-cfg.h"
+#include <string.h>
-void pkcs11_list( const char* url)
+#define MIN(x,y) ((x)<(y))?(x):(y)
+
+static int pin_callback(void* user, int attempt, const char *slot_descr,
+ const char *token_label, unsigned int flags, char* pin, size_t pin_max)
+{
+const char* password;
+
+ printf("PIN required for token '%s' in slot '%s'\n", token_label, slot_descr);
+ if (flags & GNUTLS_PKCS11_PIN_FINAL_TRY)
+ printf("*** This is the final try before locking!\n");
+ if (flags & GNUTLS_PKCS11_PIN_COUNT_LOW)
+ printf("*** Only few tries left before locking!\n");
+
+ password = get_pass();
+ if (password==NULL) {
+ fprintf(stderr, "No password given\n");
+ exit(1);
+ }
+ memcpy(pin, password, MIN(pin_max,strlen(password)));
+
+ return 0;
+}
+
+static void pkcs11_common(void)
+{
+
+ gnutls_pkcs11_set_pin_function (pin_callback, NULL);
+
+}
+
+/* lists certificates from a token
+ */
+void pkcs11_list( const char* url, int type)
{
gnutls_pkcs11_crt_t *crt_list;
unsigned int crt_list_size = 0;
int ret;
char* output;
-int i;
+int i, flags;
+
+ pkcs11_common();
if (url == NULL)
url = "pkcs11:";
ret = gnutls_pkcs11_crt_list_import( NULL, &crt_list_size, url, GNUTLS_PKCS11_CRT_ATTR_ALL);
- if (ret != 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) {
+ if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) {
fprintf(stderr, "Error in crt_list_import (1): %s\n", gnutls_strerror(ret));
exit(1);
}
exit(1);
}
- ret = gnutls_pkcs11_crt_list_import( crt_list, &crt_list_size, url, GNUTLS_PKCS11_CRT_ATTR_ALL);
+ if (type == PKCS11_TYPE_TRUSTED) {
+ flags = GNUTLS_PKCS11_CRT_ATTR_TRUSTED;
+ } else if (type == PKCS11_TYPE_PK) {
+ flags = GNUTLS_PKCS11_CRT_ATTR_WITH_PK;
+ } else {
+ flags = GNUTLS_PKCS11_CRT_ATTR_ALL;
+ }
+
+ ret = gnutls_pkcs11_crt_list_import( crt_list, &crt_list_size, url, flags);
if (ret < 0) {
fprintf(stderr, "Error in crt_list_import: %s\n", gnutls_strerror(ret));
exit(1);
return;
}
+
+void pkcs11_export(FILE* outfile, const char* url)
+{
+gnutls_pkcs11_crt_t crt;
+gnutls_x509_crt_t xcrt;
+int ret;
+
+ pkcs11_common();
+
+ if (url == NULL)
+ url = "pkcs11:";
+
+ ret = gnutls_pkcs11_crt_init(&crt);
+ if (ret < 0) {
+ fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_pkcs11_crt_import_url( crt, url);
+ if (ret < 0) {
+ fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_x509_crt_init(&xcrt);
+ if (ret < 0) {
+ fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ ret = gnutls_x509_crt_import_pkcs11(xcrt, crt);
+ if (ret < 0) {
+ fprintf(stderr, "Error in %s:%d: %s\n", __func__, __LINE__, gnutls_strerror(ret));
+ exit(1);
+ }
+
+ print_certificate_info(xcrt, outfile, 1);
+
+ gnutls_x509_crt_deinit(xcrt);
+ gnutls_pkcs11_crt_deinit(crt);
+
+ return;
+
+
+
+}