summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/includes/gnutls/pkcs11.h4
-rw-r--r--lib/libgnutls.map1
-rw-r--r--lib/pkcs11.c161
-rw-r--r--lib/pkcs11_int.c10
-rw-r--r--lib/pkcs11_int.h7
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,