summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2015-03-11 14:49:04 +0100
committerNikos Mavrogiannopoulos <nmav@redhat.com>2016-11-29 16:27:41 +0100
commit48bc7fd557356d7dde3060956412bd6019c917f6 (patch)
treeb683e7a480a23daae6e05b1576f5b998b2d68ba9
parentd1c558dc81c9da53dc47f284b81aa4fa22aa3877 (diff)
downloadgnutls-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.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 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,