static int find_object(struct pkcs11_session_info *sinfo, struct pin_info_st *pin_info, ck_object_handle_t * _ctx, struct p11_kit_uri *info, unsigned int flags) { int ret; ck_object_handle_t ctx; struct ck_attribute *attrs; unsigned long attr_count; unsigned long count; ck_rv_t rv; ret = pkcs11_open_session(sinfo, pin_info, info, flags & SESSION_LOGIN); if (ret < 0) { gnutls_assert(); return ret; } attrs = p11_kit_uri_get_attributes(info, &attr_count); rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, attrs, attr_count); if (rv != CKR_OK) { gnutls_assert(); _gnutls_debug_log("p11: FindObjectsInit failed.\n"); ret = pkcs11_rv_to_err(rv); goto fail; } if (pkcs11_find_objects(sinfo->module, sinfo->pks, &ctx, 1, &count) == CKR_OK && count == 1) { *_ctx = ctx; pkcs11_find_objects_final(sinfo); return 0; } ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; pkcs11_find_objects_final(sinfo); fail: pkcs11_close_session(sinfo); return ret; }
int pkcs11_override_cert_exts(struct pkcs11_session_info *sinfo, gnutls_datum_t *spki, gnutls_datum_t *der) { int ret; gnutls_datum_t new_der = {NULL, 0}; struct ck_attribute a[2]; struct ck_attribute b[1]; unsigned long count; unsigned ext_data_size = der->size; uint8_t *ext_data = NULL; ck_object_class_t class = -1; gnutls_x509_crt_t crt = NULL; unsigned finalize = 0; ck_rv_t rv; ck_object_handle_t obj; /* retrieve the extensions */ class = CKO_X_CERTIFICATE_EXTENSION; a[0].type = CKA_CLASS; a[0].value = &class; a[0].value_len = sizeof class; a[1].type = CKA_PUBLIC_KEY_INFO; a[1].value = spki->data; a[1].value_len = spki->size; rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a, 2); if (rv != CKR_OK) { gnutls_assert(); _gnutls_debug_log ("p11: FindObjectsInit failed for cert extensions.\n"); ret = pkcs11_rv_to_err(rv); goto cleanup; } finalize = 1; rv = pkcs11_find_objects(sinfo->module, sinfo->pks, &obj, 1, &count); if (rv == CKR_OK && count == 1) { ext_data = gnutls_malloc(ext_data_size); if (ext_data == NULL) { gnutls_assert(); ret = GNUTLS_E_MEMORY_ERROR; goto cleanup; } ret = gnutls_x509_crt_init(&crt); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_x509_crt_import(crt, der, GNUTLS_X509_FMT_DER); if (ret < 0) { gnutls_assert(); goto cleanup; } do { b[0].type = CKA_VALUE; b[0].value = ext_data; b[0].value_len = ext_data_size; if (pkcs11_get_attribute_value (sinfo->module, sinfo->pks, obj, b, 1) == CKR_OK) { gnutls_datum_t data = { b[0].value, b[0].value_len }; ret = override_ext(crt, &data); if (ret < 0) { gnutls_assert(); goto cleanup; } } } while (pkcs11_find_objects(sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK && count == 1); /* overwrite the old certificate with the new */ ret = gnutls_x509_crt_export2(crt, GNUTLS_X509_FMT_DER, &new_der); if (ret < 0) { gnutls_assert(); goto cleanup; } gnutls_free(der->data); der->data = new_der.data; der->size = new_der.size; } ret = 0; cleanup: if (crt != NULL) gnutls_x509_crt_deinit(crt); if (finalize != 0) pkcs11_find_objects_final(sinfo); gnutls_free(ext_data); return ret; }
static int find_ext_cb(struct pkcs11_session_info *sinfo, struct token_info *info, struct ck_info *lib_info, void *input) { struct find_ext_data_st *find_data = input; struct ck_attribute a[4]; ck_object_class_t class = -1; unsigned long count; ck_rv_t rv; ck_object_handle_t obj; int ret; gnutls_datum_t ext; 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 (!p11_kit_uri_match_token_info (find_data->obj->info, &info->tinfo) || !p11_kit_uri_match_module_info(find_data->obj->info, lib_info)) { gnutls_assert(); return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } /* retrieve the extensions */ class = CKO_X_CERTIFICATE_EXTENSION; a[0].type = CKA_CLASS; a[0].value = &class; a[0].value_len = sizeof class; a[1].type = CKA_PUBLIC_KEY_INFO; a[1].value = find_data->spki.data; a[1].value_len = find_data->spki.size; rv = pkcs11_find_objects_init(sinfo->module, sinfo->pks, a, 2); if (rv != CKR_OK) { gnutls_assert(); _gnutls_debug_log ("p11: FindObjectsInit failed for cert extensions.\n"); return pkcs11_rv_to_err(rv); } while(pkcs11_find_objects(sinfo->module, sinfo->pks, &obj, 1, &count) == CKR_OK && count == 1) { rv = pkcs11_get_attribute_avalue(sinfo->module, sinfo->pks, obj, CKA_VALUE, &ext); if (rv == CKR_OK) { find_data->exts = gnutls_realloc_fast(find_data->exts, (1+find_data->exts_size)*sizeof(find_data->exts[0])); if (find_data->exts == NULL) { gnutls_assert(); ret = pkcs11_rv_to_err(rv); goto cleanup; } if (_gnutls_x509_decode_ext(&ext, &find_data->exts[find_data->exts_size]) == 0) { find_data->exts_size++; } } } ret = 0; cleanup: pkcs11_find_objects_final(sinfo); return ret; }