diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/includes/gnutls/pkcs11.h | 4 | ||||
-rw-r--r-- | lib/libgnutls.map | 1 | ||||
-rw-r--r-- | lib/pkcs11.c | 161 | ||||
-rw-r--r-- | lib/pkcs11_int.c | 10 | ||||
-rw-r--r-- | lib/pkcs11_int.h | 7 |
5 files changed, 183 insertions, 0 deletions
diff --git a/lib/includes/gnutls/pkcs11.h b/lib/includes/gnutls/pkcs11.h index ba981ba50a..3a2edcd559 100644 --- a/lib/includes/gnutls/pkcs11.h +++ b/lib/includes/gnutls/pkcs11.h @@ -247,6 +247,10 @@ typedef enum { 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_set_info(gnutls_pkcs11_obj_t crt, + gnutls_pkcs11_obj_info_t itype, + const void *data, size_t data_size, + unsigned flags); #define GNUTLS_PKCS11_OBJ_ATTR_CRT_ALL GNUTLS_PKCS11_OBJ_FLAG_CRT #define GNUTLS_PKCS11_OBJ_ATTR_MATCH 0 /* always match the given URL */ diff --git a/lib/libgnutls.map b/lib/libgnutls.map index 343b11a226..84e304a7bb 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -1014,6 +1014,7 @@ GNUTLS_3_4 gnutls_system_recv_timeout; gnutls_record_set_state; gnutls_record_get_state; + gnutls_pkcs11_obj_set_info; local: *; }; diff --git a/lib/pkcs11.c b/lib/pkcs11.c index 1c9f6dfea3..936a56d1be 100644 --- a/lib/pkcs11.c +++ b/lib/pkcs11.c @@ -335,6 +335,167 @@ int gnutls_pkcs11_add_provider(const char *name, const char *params) /** + * gnutls_pkcs11_obj_set_info: + * @obj: should contain a #gnutls_pkcs11_obj_t structure + * @itype: Denotes the type of information to be set + * @data: the data to set + * @data_size: the size of data + * @flags: Or sequence of GNUTLS_PKCS11_OBJ_* flags + * + * This function will set attributes on the provided object. + * Available options for @itype are %GNUTLS_PKCS11_OBJ_LABEL, + * %GNUTLS_PKCS11_OBJ_ID_HEX, and %GNUTLS_PKCS11_OBJ_ID. + * + * Returns: %GNUTLS_E_SUCCESS (0) on success or a negative error code on error. + * + * Since: 3.4.0 + **/ +int +gnutls_pkcs11_obj_set_info(gnutls_pkcs11_obj_t obj, + gnutls_pkcs11_obj_info_t itype, + const void *data, size_t data_size, + unsigned flags) +{ + struct p11_kit_uri *info = obj->info; + struct pkcs11_session_info sinfo; + struct ck_attribute *attr; + struct ck_attribute a[4]; + ck_certificate_type_t type = -1; + ck_object_class_t class = CKO_CERTIFICATE; + ck_object_handle_t pkobj[2]; + unsigned long count; + size_t size; + unsigned a_vals; + char tmp[128]; + ck_rv_t rv; + int ret; + + PKCS11_CHECK_INIT; + + ret = + pkcs11_open_session(&sinfo, NULL, info, + SESSION_WRITE | + pkcs11_obj_flags_to_int(flags)); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + /* find the object that matches the URL */ + a_vals = 0; + attr = p11_kit_uri_get_attribute(info, CKA_ID); + if (attr) { + memcpy(a + a_vals, attr, sizeof(struct ck_attribute)); + a_vals++; + } + + attr = p11_kit_uri_get_attribute(info, CKA_LABEL); + if (attr) { + memcpy(a + a_vals, attr, sizeof(struct ck_attribute)); + a_vals++; + } + + if (!a_vals) { + gnutls_assert(); + ret = GNUTLS_E_INVALID_REQUEST; + goto cleanup; + } + + /* Find objects with given class and type */ + attr = p11_kit_uri_get_attribute(info, CKA_CLASS); + if (attr) { + if (attr->value + && attr->value_len == sizeof(ck_object_class_t)) + class = *((ck_object_class_t *) attr->value); + if (class == CKO_CERTIFICATE) + type = CKC_X_509; + memcpy(a + a_vals, attr, sizeof(struct ck_attribute)); + a_vals++; + } + + if (type != (ck_certificate_type_t) - 1) { + a[a_vals].type = CKA_CERTIFICATE_TYPE; + a[a_vals].value = &type; + a[a_vals].value_len = sizeof type; + a_vals++; + } + + rv = pkcs11_find_objects_init(sinfo.module, sinfo.pks, a, + a_vals); + if (rv != CKR_OK) { + gnutls_assert(); + _gnutls_debug_log("p11: FindObjectsInit failed.\n"); + ret = pkcs11_rv_to_err(rv); + goto cleanup; + } + + rv = pkcs11_find_objects(sinfo.module, sinfo.pks, pkobj, 2, &count); + if (rv != CKR_OK) { + gnutls_assert(); + _gnutls_debug_log("p11: FindObjects failed.\n"); + ret = pkcs11_rv_to_err(rv); + goto cleanup; + } + + if (count > 1 || count == 0) { + gnutls_assert(); + if (count > 1) + _gnutls_debug_log("p11: More than one objects match (%d)\n", (int)count); + ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + goto cleanup; + } + + switch (itype) { + case GNUTLS_PKCS11_OBJ_ID_HEX: + size = sizeof(tmp); + ret = _gnutls_hex2bin(data, data_size, (uint8_t*)tmp, &size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + data = tmp; + data_size = size; + /* fallthrough */ + case GNUTLS_PKCS11_OBJ_ID: + a[0].type = CKA_ID; + a[0].value = (void*)data; + a[0].value_len = data_size; + + rv = pkcs11_set_attribute_value(sinfo.module, sinfo.pks, pkobj[0], a, 1); + if (rv != CKR_OK) { + gnutls_assert(); + _gnutls_debug_log("p11: set_attribute_value failed.\n"); + ret = pkcs11_rv_to_err(rv); + goto cleanup; + } + + break; + case GNUTLS_PKCS11_OBJ_LABEL: + a[0].type = CKA_LABEL; + a[0].value = (void*)data; + a[0].value_len = data_size; + + rv = pkcs11_set_attribute_value(sinfo.module, sinfo.pks, pkobj[0], a, 1); + if (rv != CKR_OK) { + gnutls_assert(); + _gnutls_debug_log("p11: set_attribute_value failed.\n"); + ret = pkcs11_rv_to_err(rv); + goto cleanup; + } + + break; + default: + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + ret = 0; + cleanup: + pkcs11_close_session(&sinfo); + return ret; +} + +/** * gnutls_pkcs11_obj_get_info: * @obj: should contain a #gnutls_pkcs11_obj_t structure * @itype: Denotes the type of information requested diff --git a/lib/pkcs11_int.c b/lib/pkcs11_int.c index 9ff2d98bcf..848b8b94b0 100644 --- a/lib/pkcs11_int.c +++ b/lib/pkcs11_int.c @@ -96,6 +96,16 @@ ck_rv_t pkcs11_close_session(struct pkcs11_session_info * sinfo) } ck_rv_t +pkcs11_set_attribute_value(struct ck_function_list * module, + ck_session_handle_t sess, + ck_object_handle_t object, + struct ck_attribute * templ, + unsigned long count) +{ + return (module)->C_SetAttributeValue(sess, object, templ, count); +} + +ck_rv_t pkcs11_get_attribute_value(struct ck_function_list * module, ck_session_handle_t sess, ck_object_handle_t object, diff --git a/lib/pkcs11_int.h b/lib/pkcs11_int.h index 7cec42bd8a..1ba8215710 100644 --- a/lib/pkcs11_int.h +++ b/lib/pkcs11_int.h @@ -237,6 +237,13 @@ ck_rv_t pkcs11_find_objects_final(struct pkcs11_session_info *); ck_rv_t pkcs11_close_session(struct pkcs11_session_info *); ck_rv_t +pkcs11_set_attribute_value(struct ck_function_list * module, + ck_session_handle_t sess, + ck_object_handle_t object, + struct ck_attribute * templ, + unsigned long count); + +ck_rv_t pkcs11_get_attribute_value(struct ck_function_list *module, ck_session_handle_t sess, ck_object_handle_t object, |