[gcr] Properly DER encode CKA_EC_POINT
- From: Daiki Ueno <dueno src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gcr] Properly DER encode CKA_EC_POINT
- Date: Mon, 27 Nov 2017 14:56:08 +0000 (UTC)
commit a0c9b6ee5dbc4b7df77672ef2db02d16ecc779c5
Author: Jakub Jelen <jjelen redhat com>
Date: Fri Jul 21 16:28:31 2017 +0200
Properly DER encode CKA_EC_POINT
* The PKCS#11 specification described this attribute as DER encoded and
existing tools expect the value as an OCTET STRING
Signed-off-by: Jakub Jelen <jjelen redhat com>
https://bugzilla.gnome.org/show_bug.cgi?id=785234
gcr/gcr-openssh.c | 36 ++++++++++++++++++++++++++++++-
gcr/gcr-parser.c | 48 +++++++++++++++++++++++++++++++++++++----
gcr/gcr-subject-public-key.c | 21 ++++++++++++++---
3 files changed, 95 insertions(+), 10 deletions(-)
---
diff --git a/gcr/gcr-openssh.c b/gcr/gcr-openssh.c
index 0219f0e..75a196c 100644
--- a/gcr/gcr-openssh.c
+++ b/gcr/gcr-openssh.c
@@ -247,6 +247,39 @@ parse_v1_public_line (const gchar *line,
}
static gboolean
+read_buffer_mpi_to_der (EggBuffer *buffer,
+ gsize *offset,
+ GckBuilder *builder,
+ gulong attribute_type)
+{
+ const guchar *data, *data_value;
+ GBytes *der_data = NULL;
+ gsize len, data_len;
+ GNode *asn = NULL;
+ gboolean rv = FALSE;
+
+ if (!egg_buffer_get_byte_array (buffer, *offset, offset, &data, &len))
+ return FALSE;
+
+ asn = egg_asn1x_create (pk_asn1_tab, "ECPoint");
+ if (!asn)
+ return FALSE;
+
+ egg_asn1x_set_string_as_raw (asn, data, len, NULL);
+ der_data = egg_asn1x_encode (asn, g_realloc);
+ if (!der_data)
+ goto out;
+
+ data_value = g_bytes_get_data (der_data, &data_len);
+ gck_builder_add_data (builder, attribute_type, data_value, data_len);
+ rv = TRUE;
+out:
+ g_bytes_unref (der_data);
+ egg_asn1x_destroy (asn);
+ return rv;
+}
+
+static gboolean
read_buffer_mpi (EggBuffer *buffer,
gsize *offset,
GckBuilder *builder,
@@ -346,7 +379,8 @@ read_v2_public_ecdsa (EggBuffer *buffer,
gck_builder_add_data (builder, CKA_EC_PARAMS, data, len);
g_bytes_unref (bytes);
- if (!read_buffer_mpi (buffer, offset, builder, CKA_EC_POINT))
+ /* need to convert to DER encoded OCTET STRING */
+ if (!read_buffer_mpi_to_der (buffer, offset, builder, CKA_EC_POINT))
return FALSE;
gck_builder_add_ulong (builder, CKA_KEY_TYPE, CKK_ECDSA);
diff --git a/gcr/gcr-parser.c b/gcr/gcr-parser.c
index cbea784..cf5c44e 100644
--- a/gcr/gcr-parser.c
+++ b/gcr/gcr-parser.c
@@ -279,6 +279,25 @@ parsed_asn1_element (GcrParsed *parsed,
return TRUE;
}
+static gboolean
+parsed_asn1_structure (GcrParsed *parsed,
+ GNode *asn,
+ CK_ATTRIBUTE_TYPE type)
+{
+ GBytes *value;
+
+ g_assert (asn);
+ g_assert (parsed);
+
+ value = egg_asn1x_encode (asn, g_realloc);
+ if (value == NULL)
+ return FALSE;
+
+ parsed_attribute_bytes (parsed, type, value);
+ g_bytes_unref (value);
+ return TRUE;
+}
+
static void
parsed_ulong_attribute (GcrParsed *parsed,
CK_ATTRIBUTE_TYPE type,
@@ -625,6 +644,7 @@ parse_der_private_key_ec (GcrParser *self,
GNode *asn = NULL;
GBytes *value = NULL;
GBytes *pub = NULL;
+ GNode *asn_q = NULL;
GcrParsed *parsed;
guint bits;
gulong version;
@@ -660,8 +680,16 @@ parse_der_private_key_ec (GcrParser *self,
parsed_attribute_bytes (parsed, CKA_VALUE, value);
pub = egg_asn1x_get_bits_as_raw (egg_asn1x_node (asn, "publicKey", NULL), &bits);
- if (pub && bits == 8 * g_bytes_get_size (pub))
- parsed_attribute_bytes (parsed, CKA_EC_POINT, pub);
+ if (!pub || bits != 8 * g_bytes_get_size (pub))
+ goto done;
+ asn_q = egg_asn1x_create (pk_asn1_tab, "ECPoint");
+ if (!asn_q)
+ goto done;
+ egg_asn1x_set_string_as_bytes (asn_q, pub);
+
+ if (!parsed_asn1_structure (parsed, asn_q, CKA_EC_POINT))
+ goto done;
+
parsed_fire (self, parsed);
ret = SUCCESS;
@@ -671,6 +699,7 @@ done:
if (value)
g_bytes_unref (value);
egg_asn1x_destroy (asn);
+ egg_asn1x_destroy (asn_q);
if (ret == GCR_ERROR_FAILURE)
g_message ("invalid EC key");
@@ -767,17 +796,26 @@ handle_subject_public_key_ec (GcrParser *self,
GBytes *key,
GNode *params)
{
- GBytes *bytes;
+ gint ret = GCR_ERROR_FAILURE;
+ GBytes *bytes = NULL;
+ GNode *asn = NULL;
parsing_object (parsed, CKO_PUBLIC_KEY);
parsed_ulong_attribute (parsed, CKA_KEY_TYPE, CKK_EC);
bytes = egg_asn1x_encode (params, g_realloc);
parsed_attribute_bytes (parsed, CKA_EC_PARAMS, bytes);
- parsed_attribute_bytes (parsed, CKA_EC_POINT, key);
g_bytes_unref (bytes);
- return SUCCESS;
+ asn = egg_asn1x_create (pk_asn1_tab, "ECPoint");
+ if (!asn)
+ goto done;
+ egg_asn1x_set_string_as_bytes (asn, key);
+ parsed_asn1_structure (parsed, asn, CKA_EC_POINT);
+ ret = SUCCESS;
+done:
+ egg_asn1x_destroy (asn);
+ return ret;
}
static gint
diff --git a/gcr/gcr-subject-public-key.c b/gcr/gcr-subject-public-key.c
index 0335dc0..1621d95 100644
--- a/gcr/gcr-subject-public-key.c
+++ b/gcr/gcr-subject-public-key.c
@@ -750,8 +750,8 @@ ec_subject_public_key_from_attributes (GckAttributes *attrs,
GNode *info_asn)
{
const GckAttribute *ec_params, *ec_point;
- GNode *params_asn;
- GBytes *bytes;
+ GNode *params_asn, *point_asn;
+ GBytes *bytes, *key_bytes;
ec_params = gck_attributes_find (attrs, CKA_EC_PARAMS);
ec_point = gck_attributes_find (attrs, CKA_EC_POINT);
@@ -770,14 +770,27 @@ ec_subject_public_key_from_attributes (GckAttributes *attrs,
bytes = g_bytes_new_with_free_func (ec_point->value, ec_point->length,
gck_attributes_unref, gck_attributes_ref (attrs));
+ point_asn = egg_asn1x_create_and_decode (pk_asn1_tab, "ECPoint", bytes);
+ g_bytes_unref (bytes);
+
+ if (point_asn == NULL) {
+ egg_asn1x_destroy (params_asn);
+ return FALSE;
+ }
+ key_bytes = egg_asn1x_get_string_as_bytes (point_asn);
+ egg_asn1x_destroy (point_asn);
+ if (key_bytes == NULL) {
+ egg_asn1x_destroy (params_asn);
+ return FALSE;
+ }
egg_asn1x_set_bits_as_raw (egg_asn1x_node (info_asn, "subjectPublicKey", NULL),
- bytes, g_bytes_get_size (bytes) * 8);
+ key_bytes, g_bytes_get_size (key_bytes) * 8);
egg_asn1x_set_any_from (egg_asn1x_node (info_asn, "algorithm", "parameters", NULL), params_asn);
egg_asn1x_set_oid_as_quark (egg_asn1x_node (info_asn, "algorithm", "algorithm", NULL),
GCR_OID_PKIX1_EC);
- g_bytes_unref (bytes);
+ g_bytes_unref (key_bytes);
egg_asn1x_destroy (params_asn);
return TRUE;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]