summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStef Walter <stefw@redhat.com>2014-04-17 07:16:13 +0200
committerStef Walter <stefw@redhat.com>2014-04-19 22:29:49 +0200
commit600981f4b3c25ade07ec886b7aa53dd169a5b133 (patch)
tree43eada54a4a3d866ca6188b77f1b2378ddc7701b
parentf6173cd11ba0b8f07687ffd575ac9b7488f47e46 (diff)
gcr: Add gcr-subject-public-key.c support for EC keys and certs
-rw-r--r--gcr/fixtures/ecc-strong.crtbin0 -> 808 bytes
-rw-r--r--gcr/fixtures/ecc-strong.keybin0 -> 223 bytes
-rw-r--r--gcr/fixtures/ecc-strong.spkbin0 -> 158 bytes
-rw-r--r--gcr/gcr-subject-public-key.c196
-rw-r--r--gcr/test-subject-public-key.c12
5 files changed, 204 insertions, 4 deletions
diff --git a/gcr/fixtures/ecc-strong.crt b/gcr/fixtures/ecc-strong.crt
new file mode 100644
index 0000000..7c61572
--- /dev/null
+++ b/gcr/fixtures/ecc-strong.crt
Binary files differ
diff --git a/gcr/fixtures/ecc-strong.key b/gcr/fixtures/ecc-strong.key
new file mode 100644
index 0000000..6395df3
--- /dev/null
+++ b/gcr/fixtures/ecc-strong.key
Binary files differ
diff --git a/gcr/fixtures/ecc-strong.spk b/gcr/fixtures/ecc-strong.spk
new file mode 100644
index 0000000..5a495d8
--- /dev/null
+++ b/gcr/fixtures/ecc-strong.spk
Binary files differ
diff --git a/gcr/gcr-subject-public-key.c b/gcr/gcr-subject-public-key.c
index 359307c..9a27d54 100644
--- a/gcr/gcr-subject-public-key.c
+++ b/gcr/gcr-subject-public-key.c
@@ -293,6 +293,66 @@ load_dsa_attributes (GckObject *object,
}
static gboolean
+check_ec_attributes (GckBuilder *builder)
+{
+ const GckAttribute *ec_params;
+ const GckAttribute *ec_point;
+
+ ec_params = gck_builder_find (builder, CKA_EC_PARAMS);
+ ec_point = gck_builder_find (builder, CKA_EC_POINT);
+
+ return (ec_params && !gck_attribute_is_invalid (ec_params) &&
+ ec_point && !gck_attribute_is_invalid (ec_point));
+}
+
+
+static gboolean
+load_ec_attributes (GckObject *object,
+ GckBuilder *builder,
+ GCancellable *cancellable,
+ GError **lerror)
+{
+ gulong attr_types[] = { CKA_EC_PARAMS, CKA_EC_POINT };
+ GckAttributes *attrs;
+ GError *error = NULL;
+ GckObject *publi;
+ gulong klass;
+
+ if (check_ec_attributes (builder)) {
+ _gcr_debug ("ec attributes already loaded");
+ return TRUE;
+ }
+
+ if (!gck_builder_find_ulong (builder, CKA_CLASS, &klass))
+ g_return_val_if_reached (FALSE);
+
+ /* If it's a private key, find the public one */
+ if (klass == CKO_PRIVATE_KEY)
+ publi = lookup_public_key (object, cancellable, lerror);
+
+ else
+ publi = g_object_ref (object);
+
+ if (!publi)
+ return FALSE;
+
+ attrs = gck_object_cache_lookup (publi, attr_types, G_N_ELEMENTS (attr_types),
+ cancellable, &error);
+ g_object_unref (publi);
+
+ if (error != NULL) {
+ _gcr_debug ("couldn't load ec attributes: %s", error->message);
+ g_propagate_error (lerror, error);
+ return FALSE;
+ }
+
+ gck_builder_set_all (builder, attrs);
+ gck_attributes_unref (attrs);
+
+ return check_ec_attributes (builder);
+}
+
+static gboolean
load_attributes (GckObject *object,
GckBuilder *builder,
GCancellable *cancellable,
@@ -328,6 +388,9 @@ load_attributes (GckObject *object,
case CKK_DSA:
ret = load_dsa_attributes (object, builder, cancellable, lerror);
break;
+ case CKK_EC:
+ ret = load_ec_attributes (object, builder, cancellable, lerror);
+ break;
default:
_gcr_debug ("unsupported key type: %lu", type);
break;
@@ -373,6 +436,8 @@ check_attributes (GckBuilder *builder)
return check_rsa_attributes (builder);
case CKK_DSA:
return check_dsa_attributes (builder);
+ case CKK_EC:
+ return check_ec_attributes (builder);
default:
return FALSE;
}
@@ -681,6 +746,44 @@ dsa_subject_public_key_from_attributes (GckAttributes *attrs,
return TRUE;
}
+static gboolean
+ec_subject_public_key_from_attributes (GckAttributes *attrs,
+ gulong klass,
+ GNode *info_asn)
+{
+ const GckAttribute *ec_params, *ec_point;
+ GNode *params_asn;
+ GBytes *bytes;
+
+ ec_params = gck_attributes_find (attrs, CKA_EC_PARAMS);
+ ec_point = gck_attributes_find (attrs, CKA_EC_POINT);
+
+ if (ec_params == NULL || gck_attribute_is_invalid (ec_params) ||
+ ec_point == NULL || gck_attribute_is_invalid (ec_point))
+ return FALSE;
+
+ bytes = g_bytes_new_with_free_func (ec_params->value, ec_params->length,
+ gck_attributes_unref, gck_attributes_ref (attrs));
+ params_asn = egg_asn1x_create_and_decode (pk_asn1_tab, "ECParameters", bytes);
+ g_bytes_unref (bytes);
+
+ if (params_asn == NULL)
+ return FALSE;
+
+ bytes = g_bytes_new_with_free_func (ec_point->value, ec_point->length,
+ gck_attributes_unref, gck_attributes_ref (attrs));
+
+ egg_asn1x_set_bits_as_raw (egg_asn1x_node (info_asn, "subjectPublicKey", NULL),
+ bytes, g_bytes_get_size (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);
+ egg_asn1x_destroy (params_asn);
+ return TRUE;
+}
+
static GNode *
cert_subject_public_key_from_attributes (GckAttributes *attributes)
{
@@ -747,6 +850,9 @@ _gcr_subject_public_key_for_attributes (GckAttributes *attributes)
} else if (key_type == CKK_DSA) {
ret = dsa_subject_public_key_from_attributes (attributes, klass, asn);
+ } else if (key_type == CKK_ECDSA) {
+ ret = ec_subject_public_key_from_attributes (attributes, klass, asn);
+
} else {
_gcr_debug ("unsupported key type: %lu", key_type);
ret = FALSE;
@@ -844,6 +950,90 @@ attributes_dsa_key_size (GckAttributes *attrs)
return 0;
}
+static guint
+named_curve_size (GNode *params)
+{
+ GQuark oid;
+ guint size;
+
+ oid = egg_asn1x_get_oid_as_quark (egg_asn1x_node (params, "namedCurve", NULL));
+ if (oid == GCR_OID_EC_SECP192R1)
+ size = 192;
+ else if (oid == GCR_OID_EC_SECT163K1)
+ size = 163;
+ else if (oid == GCR_OID_EC_SECT163R2)
+ size = 163;
+ else if (oid == GCR_OID_EC_SECP224R1)
+ size = 224;
+ else if (oid == GCR_OID_EC_SECT233K1)
+ size = 233;
+ else if (oid == GCR_OID_EC_SECT233R1)
+ size = 233;
+ else if (oid == GCR_OID_EC_SECP256R1)
+ size = 256;
+ else if (oid == GCR_OID_EC_SECT283K1)
+ size = 283;
+ else if (oid == GCR_OID_EC_SECT283R1)
+ size = 283;
+ else if (oid == GCR_OID_EC_SECP384R1)
+ size = 384;
+ else if (oid == GCR_OID_EC_SECT409K1)
+ size = 409;
+ else if (oid == GCR_OID_EC_SECT409R1)
+ size = 409;
+ else if (oid == GCR_OID_EC_SECP521R1)
+ size = 521;
+ else if (oid == GCR_OID_EC_SECP571K1)
+ size = 571;
+ else if (oid == GCR_OID_EC_SECT571R1)
+ size = 571;
+ else
+ size = 0;
+ return size;
+
+}
+
+static guint
+calculate_ec_params_size (GNode *params)
+{
+ GNode *asn;
+ guint size;
+
+ asn = egg_asn1x_get_any_as (params, pk_asn1_tab, "ECParameters");
+ g_return_val_if_fail (asn, 0);
+
+ size = named_curve_size (asn);
+ egg_asn1x_destroy (asn);
+
+ return size;
+}
+
+static guint
+attributes_ec_params_size (GckAttributes *attrs)
+{
+ GNode *asn;
+ const GckAttribute *attr;
+ GBytes *bytes;
+ guint size = 0;
+
+ attr = gck_attributes_find (attrs, CKA_EC_PARAMS);
+
+ /* Calculate the bit length, and remove the complement */
+ if (attr && !gck_attribute_is_invalid (attr)) {
+ bytes = g_bytes_new_with_free_func (attr->value, attr->length,
+ gck_attributes_unref,
+ gck_attributes_ref (attrs));
+ asn = egg_asn1x_create_and_decode (pk_asn1_tab, "ECParameters", bytes);
+ g_bytes_unref (bytes);
+
+ if (asn)
+ size = named_curve_size (asn);
+ egg_asn1x_destroy (asn);
+ }
+
+ return size;
+}
+
guint
_gcr_subject_public_key_calculate_size (GNode *subject_public_key)
{
@@ -870,6 +1060,10 @@ _gcr_subject_public_key_calculate_size (GNode *subject_public_key)
params = egg_asn1x_node (subject_public_key, "algorithm", "parameters", NULL);
key_size = calculate_dsa_params_size (params);
+ } else if (oid == GCR_OID_PKIX1_EC) {
+ params = egg_asn1x_node (subject_public_key, "algorithm", "parameters", NULL);
+ key_size = calculate_ec_params_size (params);
+
} else {
g_message ("unsupported key algorithm: %s", g_quark_to_string (oid));
}
@@ -890,6 +1084,8 @@ _gcr_subject_public_key_attributes_size (GckAttributes *attrs)
return attributes_rsa_key_size (attrs);
case CKK_DSA:
return attributes_dsa_key_size (attrs);
+ case CKK_EC:
+ return attributes_ec_params_size (attrs);
default:
g_message ("unsupported key algorithm: %lu", key_type);
return 0;
diff --git a/gcr/test-subject-public-key.c b/gcr/test-subject-public-key.c
index 3f84df6..c4e7c4d 100644
--- a/gcr/test-subject-public-key.c
+++ b/gcr/test-subject-public-key.c
@@ -62,13 +62,16 @@ on_parser_parsed (GcrParser *parser,
}
static GckAttributes *
-parse_attributes (GBytes *data)
+parse_attributes (GBytes *data,
+ GcrDataFormat format)
{
GcrParser *parser;
GckAttributes *attrs = NULL;
GError *error = NULL;
parser = gcr_parser_new ();
+ gcr_parser_format_disable (parser, GCR_FORMAT_ALL);
+ gcr_parser_format_enable (parser, format);
g_signal_connect (parser, "parsed", G_CALLBACK (on_parser_parsed), &attrs);
gcr_parser_parse_bytes (parser, data, &error);
g_assert_no_error (error);
@@ -93,7 +96,7 @@ setup_attributes (TestAttributes *test,
g_file_get_contents (filename, &contents, &length, &error);
g_assert_no_error (error);
test->crt_data = g_bytes_new_take (contents, length);
- test->crt_attrs = parse_attributes (test->crt_data);
+ test->crt_attrs = parse_attributes (test->crt_data, GCR_FORMAT_DER_CERTIFICATE_X509);
g_assert (gck_attributes_find_ulong (test->crt_attrs, CKA_CLASS, &klass));
gck_assert_cmpulong (klass, ==, CKO_CERTIFICATE);
g_free (filename);
@@ -102,7 +105,7 @@ setup_attributes (TestAttributes *test,
g_file_get_contents (filename, &contents, &length, &error);
g_assert_no_error (error);
test->key_data = g_bytes_new_take (contents, length);
- test->prv_attrs = parse_attributes (test->key_data);
+ test->prv_attrs = parse_attributes (test->key_data, GCR_FORMAT_ALL);
g_assert (gck_attributes_find_ulong (test->prv_attrs, CKA_CLASS, &klass));
gck_assert_cmpulong (klass, ==, CKO_PRIVATE_KEY);
g_free (filename);
@@ -111,7 +114,7 @@ setup_attributes (TestAttributes *test,
g_file_get_contents (filename, &contents, &length, &error);
g_assert_no_error (error);
test->spk_data = g_bytes_new_take (contents, length);
- test->pub_attrs = parse_attributes (test->spk_data);
+ test->pub_attrs = parse_attributes (test->spk_data, GCR_FORMAT_DER_SUBJECT_PUBLIC_KEY);
g_assert (gck_attributes_find_ulong (test->pub_attrs, CKA_CLASS, &klass));
gck_assert_cmpulong (klass, ==, CKO_PUBLIC_KEY);
g_free (filename);
@@ -665,6 +668,7 @@ test_load_failure_build (TestModule *test,
static const TestFixture FIXTURES[] = {
{ "rsa", "client", 2048 },
{ "dsa", "generic-dsa", 1024 },
+ { "ec", "ecc-strong", 521 },
};
static GPtrArray *test_names = NULL;