diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2015-03-11 14:49:04 +0100 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2016-11-29 16:27:41 +0100 |
commit | 48bc7fd557356d7dde3060956412bd6019c917f6 (patch) | |
tree | b683e7a480a23daae6e05b1576f5b998b2d68ba9 | |
parent | d1c558dc81c9da53dc47f284b81aa4fa22aa3877 (diff) | |
download | gnutls-48bc7fd557356d7dde3060956412bd6019c917f6.tar.gz |
added gnutls_pkcs11_obj_set_info()
This function allows setting information such as the CKA_ID
and the CKA_LABEL of an object.
-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 ccb4c5ceab..67e681370a 100644 --- a/lib/includes/gnutls/pkcs11.h +++ b/lib/includes/gnutls/pkcs11.h @@ -242,6 +242,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); /** * gnutls_pkcs11_obj_attr_t: diff --git a/lib/libgnutls.map b/lib/libgnutls.map index aa3e9fda44..eb047e6730 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -1030,6 +1030,7 @@ GNUTLS_3_1_0 { gnutls_pkcs11_copy_x509_crt2; gnutls_pkcs11_copy_x509_privkey2; gnutls_pkcs11_privkey_generate3; + gnutls_pkcs11_obj_set_info; } GNUTLS_3_0_0; GNUTLS_FIPS140 { diff --git a/lib/pkcs11.c b/lib/pkcs11.c index ebc1e36364..d99dedff62 100644 --- a/lib/pkcs11.c +++ b/lib/pkcs11.c @@ -348,6 +348,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.3.26 + **/ +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 6ac4929a65..cc23ec67c3 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 f4b46481f5..fa994fe88d 100644 --- a/lib/pkcs11_int.h +++ b/lib/pkcs11_int.h @@ -235,6 +235,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, |