diff options
author | Stef Walter <stefw@redhat.com> | 2014-04-17 07:16:13 +0200 |
---|---|---|
committer | Stef Walter <stefw@redhat.com> | 2014-04-19 22:29:49 +0200 |
commit | 600981f4b3c25ade07ec886b7aa53dd169a5b133 (patch) | |
tree | 43eada54a4a3d866ca6188b77f1b2378ddc7701b | |
parent | f6173cd11ba0b8f07687ffd575ac9b7488f47e46 (diff) |
gcr: Add gcr-subject-public-key.c support for EC keys and certs
-rw-r--r-- | gcr/fixtures/ecc-strong.crt | bin | 0 -> 808 bytes | |||
-rw-r--r-- | gcr/fixtures/ecc-strong.key | bin | 0 -> 223 bytes | |||
-rw-r--r-- | gcr/fixtures/ecc-strong.spk | bin | 0 -> 158 bytes | |||
-rw-r--r-- | gcr/gcr-subject-public-key.c | 196 | ||||
-rw-r--r-- | gcr/test-subject-public-key.c | 12 |
5 files changed, 204 insertions, 4 deletions
diff --git a/gcr/fixtures/ecc-strong.crt b/gcr/fixtures/ecc-strong.crt Binary files differnew file mode 100644 index 0000000..7c61572 --- /dev/null +++ b/gcr/fixtures/ecc-strong.crt diff --git a/gcr/fixtures/ecc-strong.key b/gcr/fixtures/ecc-strong.key Binary files differnew file mode 100644 index 0000000..6395df3 --- /dev/null +++ b/gcr/fixtures/ecc-strong.key diff --git a/gcr/fixtures/ecc-strong.spk b/gcr/fixtures/ecc-strong.spk Binary files differnew file mode 100644 index 0000000..5a495d8 --- /dev/null +++ b/gcr/fixtures/ecc-strong.spk 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; |