[gcr/ecc: 8/10] WIP subject pulbic key support for EC



commit e06e8b088c025ab54617a1fa4414d9398a2862ee
Author: Stef Walter <stefw redhat com>
Date:   Thu Apr 17 07:16:13 2014 +0200

    WIP subject pulbic key support for EC

 gcr/gcr-subject-public-key.c |  193 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 193 insertions(+), 0 deletions(-)
---
diff --git a/gcr/gcr-subject-public-key.c b/gcr/gcr-subject-public-key.c
index 359307c..e0c9e9d 100644
--- a/gcr/gcr-subject-public-key.c
+++ b/gcr/gcr-subject-public-key.c
@@ -293,6 +293,45 @@ load_dsa_attributes (GckObject *object,
 }
 
 static gboolean
+check_ec_attributes (GckBuilder *builder)
+{
+       const GckAttribute *ec_params;
+
+       ec_params = gck_builder_find (builder, CKA_EC_PARAMS);
+       return (ec_params && !gck_attribute_is_invalid (ec_params));
+}
+
+
+static gboolean
+load_ec_attributes (GckObject *object,
+                    GckBuilder *builder,
+                    GCancellable *cancellable,
+                    GError **lerror)
+{
+       gulong attr_types[] = { CKA_MODULUS, CKA_PUBLIC_EXPONENT };
+       GckAttributes *attrs;
+       GError *error = NULL;
+
+       if (check_rsa_attributes (builder)) {
+               _gcr_debug ("rsa attributes already loaded");
+               return TRUE;
+       }
+
+       attrs = gck_object_cache_lookup (object, attr_types, G_N_ELEMENTS (attr_types),
+                                        cancellable, &error);
+       if (error != NULL) {
+               _gcr_debug ("couldn't load rsa attributes: %s", error->message);
+               g_propagate_error (lerror, error);
+               return FALSE;
+       }
+
+       gck_builder_set_all (builder, attrs);
+       gck_attributes_unref (attrs);
+
+       return check_rsa_attributes (builder);
+}
+
+static gboolean
 load_attributes (GckObject *object,
                  GckBuilder *builder,
                  GCancellable *cancellable,
@@ -328,6 +367,14 @@ load_attributes (GckObject *object,
                case CKK_DSA:
                        ret = load_dsa_attributes (object, builder, cancellable, lerror);
                        break;
+               case CKK_EC:
+                       if (klass == CKO_PRIVATE_KEY) {
+                               _gcr_debug ("cannot convert elliptic curve private key to public");
+                               ret = FALSE;
+                       } else {
+                               ret = load_ec_attributes (object, builder, cancellable, lerror);
+                       }
+                       break;
                default:
                        _gcr_debug ("unsupported key type: %lu", type);
                        break;
@@ -373,6 +420,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 +730,55 @@ 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 *key_asn, *params_asn;
+       GBytes *bytes;
+
+       if (klass == CKO_PRIVATE_KEY)
+               return FALSE;
+
+       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;
+
+       key_asn = egg_asn1x_create (pk_asn1_tab, "ECPoint");
+       g_return_val_if_fail (key_asn, FALSE);
+
+       bytes = g_bytes_new_with_free_func (ec_point->value, ec_point->length,
+                                           gck_attributes_unref, gck_attributes_ref (attrs));
+       egg_asn1x_set_string_as_bytes (key_asn, bytes);
+       g_bytes_unref (bytes);
+
+       bytes = egg_asn1x_encode (key_asn, NULL);
+       egg_asn1x_destroy (key_asn);
+
+       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 +845,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 +945,92 @@ 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 (GCR_OID_EC_SECP224R1)
+               size = 224;
+       else if (GCR_OID_EC_SECT233K1)
+               size = 233;
+       else if (GCR_OID_EC_SECT233R1)
+               size = 233;
+       else if (GCR_OID_EC_SECP256R1)
+               size = 256;
+       else if (GCR_OID_EC_SECT283K1)
+               size = 283;
+       else if (GCR_OID_EC_SECT283R1)
+               size = 283;
+       else if (GCR_OID_EC_SECP384R1)
+               size = 384;
+       else if (GCR_OID_EC_SECT409K1)
+               size = 409;
+       else if (GCR_OID_EC_SECT409R1)
+               size = 409;
+       else if (GCR_OID_EC_SECP521R1)
+               size = 521;
+       else if (GCR_OID_EC_SECP571K1)
+               size = 571;
+       else if (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 +1057,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 +1081,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;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]