[gcr] gcr: GcrParser support for EC private and public keys



commit 85363fa6107d7a7485e2c42b1fdce7e552bf4479
Author: Stef Walter <stefw redhat com>
Date:   Thu Apr 17 07:15:47 2014 +0200

    gcr: GcrParser support for EC private and public keys

 gcr/fixtures/cert-ecc521.pem |   19 +++++++
 gcr/fixtures/der-ec-256.key  |  Bin 0 -> 121 bytes
 gcr/fixtures/ecc256.pem      |   37 ++++++++++++++
 gcr/gcr-parser.c             |  111 ++++++++++++++++++++++++++++++++++++++++++
 gcr/gcr-types.h              |    2 +
 5 files changed, 169 insertions(+), 0 deletions(-)
---
diff --git a/gcr/fixtures/cert-ecc521.pem b/gcr/fixtures/cert-ecc521.pem
new file mode 100644
index 0000000..3fc1778
--- /dev/null
+++ b/gcr/fixtures/cert-ecc521.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDJDCCAsmgAwIBAgIBBzAKBggqhkjOPQQDAjB9MQswCQYDVQQGEwJCRTEPMA0G
+A1UEChMGR251VExTMSUwIwYDVQQLExxHbnVUTFMgY2VydGlmaWNhdGUgYXV0aG9y
+aXR5MQ8wDQYDVQQIEwZMZXV2ZW4xJTAjBgNVBAMTHEdudVRMUyBjZXJ0aWZpY2F0
+ZSBhdXRob3JpdHkwIhgPMjAxMjA5MDEwOTIyMjRaGA8yMDE5MTAwNTA5MjIyNFow
+gbgxCzAJBgNVBAYTAkdSMRIwEAYDVQQKEwlLb2tvIGluYy4xFzAVBgNVBAsTDnNs
+ZWVwaW5nIGRlcHQuMQ8wDQYDVQQIEwZBdHRpa2kxFTATBgNVBAMTDENpbmR5IExh
+dXBlcjEXMBUGCgmSJomT8ixkAQETB2NsYXVwZXIxDDAKBgNVBAwTA0RyLjEPMA0G
+A1UEQRMGamFja2FsMRwwGgYJKoZIhvcNAQkBFg1ub25lQG5vbmUub3JnMIGbMBAG
+ByqGSM49AgEGBSuBBAAjA4GGAAQAoapA9bLQHQiI8V2mIzs9sq80VR4FBB0TBOSx
+GqBOE3FSzHAejQkIKc/1pW0v0wKvapYMq/RrfhPJxPkjTPtztUsAkU//9E0/aoEW
+VC6Rqf+VX3wIhe7+RS8JXdBh9SM0+Z9MCRUiM8K9qPMtpNgB2ks7T5BGFHSMlNKm
+uLW1agWPy5CjgbYwgbMwDAYDVR0TAQH/BAIwADA9BgNVHREENjA0ggx3d3cubm9u
+ZS5vcmeCE3d3dy5tb3JldGhhbm9uZS5vcmeCCWxvY2FsaG9zdIcEwKgBATATBgNV
+HSUEDDAKBggrBgEFBQcDATAPBgNVHQ8BAf8EBQMDB4AAMB0GA1UdDgQWBBTagKMW
+kYyqTJk/RRjg++gqz6xX6zAfBgNVHSMEGDAWgBTwtIH+mBK/tSi5ZEADy8wfZk4o
+AzAKBggqhkjOPQQDAgNJADBGAiEAoj/ZB98cG/FaA7VVU+R6+TT3icF+De61rfim
+R43VMlUCIQCXjG9gRp0x+/8vCRL0/nr0a32SRPruKVDqbHnNiWchsg==
+-----END CERTIFICATE-----
diff --git a/gcr/fixtures/der-ec-256.key b/gcr/fixtures/der-ec-256.key
new file mode 100644
index 0000000..6486af6
Binary files /dev/null and b/gcr/fixtures/der-ec-256.key differ
diff --git a/gcr/fixtures/ecc256.pem b/gcr/fixtures/ecc256.pem
new file mode 100644
index 0000000..75a2cfa
--- /dev/null
+++ b/gcr/fixtures/ecc256.pem
@@ -0,0 +1,37 @@
+Public Key Info:
+       Public Key Algorithm: EC
+       Key Security Level: High
+
+curve: SECP256R1
+private key:
+       00:fd:2b:00:80:f3:36:5f:11:32:65:e3:8d:30:33:
+       3b:47:f5:ce:f8:13:e5:4c:c2:cf:fd:e8:05:6a:ca:
+       c9:41:b1:
+x:
+       3c:15:6f:1d:48:3e:64:59:13:2c:6d:04:1a:38:0d:
+       30:5c:e4:3f:55:cb:d9:17:15:46:72:71:92:c1:f8:
+       c6:33:
+y:
+       3d:04:2e:c8:c1:0f:c0:50:04:7b:9f:c9:48:b5:40:
+       fa:6f:93:82:59:61:5e:72:57:cb:83:06:bd:cc:82:
+       94:c1:
+
+Public Key ID: AC:FA:47:67:C6:1B:41:79:12:57:F7:AC:05:C1:50:E2:8E:D0:0E:5B
+Public key's random art:
++--[  EC  256]----+
+|          .o+==..|
+|         .+o...+.|
+|        o.Eo.   +|
+|       . *.o   o |
+|        S.o.. .  |
+|       .. *      |
+|      .. + o     |
+|     .  . .      |
+|    ....         |
++-----------------+
+
+-----BEGIN EC PRIVATE KEY-----
+MHgCAQEEIQD9KwCA8zZfETJl440wMztH9c74E+VMws/96AVqyslBsaAKBggqhkjO
+PQMBB6FEA0IABDwVbx1IPmRZEyxtBBo4DTBc5D9Vy9kXFUZycZLB+MYzPQQuyMEP
+wFAEe5/JSLVA+m+TgllhXnJXy4MGvcyClME=
+-----END EC PRIVATE KEY-----
diff --git a/gcr/gcr-parser.c b/gcr/gcr-parser.c
index 4c39a1a..5bb4b99 100644
--- a/gcr/gcr-parser.c
+++ b/gcr/gcr-parser.c
@@ -171,6 +171,7 @@ EGG_SECURE_DECLARE (parser);
 static GQuark PEM_CERTIFICATE;
 static GQuark PEM_RSA_PRIVATE_KEY;
 static GQuark PEM_DSA_PRIVATE_KEY;
+static GQuark PEM_EC_PRIVATE_KEY;
 static GQuark PEM_ANY_PRIVATE_KEY;
 static GQuark PEM_ENCRYPTED_PRIVATE_KEY;
 static GQuark PEM_PRIVATE_KEY;
@@ -195,6 +196,7 @@ init_quarks (void)
                QUARK (PEM_PRIVATE_KEY, "PRIVATE KEY");
                QUARK (PEM_RSA_PRIVATE_KEY, "RSA PRIVATE KEY");
                QUARK (PEM_DSA_PRIVATE_KEY, "DSA PRIVATE KEY");
+               QUARK (PEM_EC_PRIVATE_KEY, "EC PRIVATE KEY");
                QUARK (PEM_ANY_PRIVATE_KEY, "ANY PRIVATE KEY");
                QUARK (PEM_ENCRYPTED_PRIVATE_KEY, "ENCRYPTED PRIVATE KEY");
                QUARK (PEM_PKCS7, "PKCS7");
@@ -609,6 +611,70 @@ done:
        pop_parsed (self, parsed);
        return ret;
 }
+/* -----------------------------------------------------------------------------
+ * EC PRIVATE KEY
+ */
+
+static gint
+parse_der_private_key_ec (GcrParser *self,
+                          GBytes *data)
+{
+       gint ret = GCR_ERROR_UNRECOGNIZED;
+       GNode *asn = NULL;
+       GBytes *value = NULL;
+       GBytes *pub = NULL;
+       GcrParsed *parsed;
+       guint bits;
+       gulong version;
+
+       parsed = push_parsed (self, TRUE);
+
+       asn = egg_asn1x_create_and_decode (pk_asn1_tab, "ECPrivateKey", data);
+       if (!asn)
+               goto done;
+
+       if (!egg_asn1x_get_integer_as_ulong (egg_asn1x_node (asn, "version", NULL), &version))
+               goto done;
+
+       /* We only support simple version */
+       if (version != 1) {
+               g_message ("unsupported version of EC key: %lu", version);
+               goto done;
+       }
+
+       parsing_block (parsed, GCR_FORMAT_DER_PRIVATE_KEY_EC, data);
+       parsing_object (parsed, CKO_PRIVATE_KEY);
+       parsed_ulong_attribute (parsed, CKA_KEY_TYPE, CKK_EC);
+       parsed_boolean_attribute (parsed, CKA_PRIVATE, CK_TRUE);
+       ret = GCR_ERROR_FAILURE;
+
+       if (!parsed_asn1_element (parsed, asn, "parameters", CKA_EC_PARAMS))
+               goto done;
+
+       value = egg_asn1x_get_string_as_usg (egg_asn1x_node (asn, "privateKey", NULL), egg_secure_realloc);
+       if (!value)
+               goto done;
+
+       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);
+       parsed_fire (self, parsed);
+       ret = SUCCESS;
+
+done:
+       if (pub)
+               g_bytes_unref (pub);
+       if (value)
+               g_bytes_unref (value);
+       egg_asn1x_destroy (asn);
+       if (ret == GCR_ERROR_FAILURE)
+               g_message ("invalid EC key");
+
+       pop_parsed (self, parsed);
+       return ret;
+}
 
 /* -----------------------------------------------------------------------------
  * PRIVATE KEY
@@ -623,6 +689,8 @@ parse_der_private_key (GcrParser *self,
        res = parse_der_private_key_rsa (self, data);
        if (res == GCR_ERROR_UNRECOGNIZED)
                res = parse_der_private_key_dsa (self, data);
+       if (res == GCR_ERROR_UNRECOGNIZED)
+               res = parse_der_private_key_ec (self, data);
 
        return res;
 }
@@ -692,6 +760,25 @@ done:
 }
 
 static gint
+handle_subject_public_key_ec (GcrParser *self,
+                              GcrParsed *parsed,
+                              GBytes *key,
+                              GNode *params)
+{
+       GBytes *bytes;
+
+       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;
+}
+
+static gint
 parse_der_subject_public_key (GcrParser *self,
                               GBytes *data)
 {
@@ -725,6 +812,9 @@ parse_der_subject_public_key (GcrParser *self,
        else if (oid == GCR_OID_PKIX1_DSA)
                ret = handle_subject_public_key_dsa (self, parsed, key, params);
 
+       else if (oid == GCR_OID_PKIX1_EC)
+               ret = handle_subject_public_key_ec (self, parsed, key, params);
+
        else
                ret = GCR_ERROR_UNRECOGNIZED;
 
@@ -773,6 +863,8 @@ parse_der_pkcs8_plain (GcrParser *self,
                key_type = CKK_RSA;
        else if (key_algo == GCR_OID_PKIX1_DSA)
                key_type = CKK_DSA;
+       else if (key_algo == GCR_OID_PKIX1_EC)
+               key_type = CKK_EC;
 
        if (key_type == GCK_INVALID) {
                ret = GCR_ERROR_UNRECOGNIZED;
@@ -801,6 +893,10 @@ done:
                        if (ret == GCR_ERROR_UNRECOGNIZED && params)
                                ret = parse_der_private_key_dsa_parts (self, keydata, params);
                        break;
+               case CKK_EC:
+                       ret = parse_der_private_key_ec (self, keydata);
+                       break;
+
                default:
                        g_message ("invalid or unsupported key type in PKCS#8 key");
                        ret = GCR_ERROR_UNRECOGNIZED;
@@ -1723,6 +1819,9 @@ formats_for_armor_type (GQuark armor_type,
        } else if (armor_type == PEM_DSA_PRIVATE_KEY) {
                *inner_format = GCR_FORMAT_DER_PRIVATE_KEY_DSA;
                *outer_format = GCR_FORMAT_PEM_PRIVATE_KEY_DSA;
+       } else if (armor_type == PEM_EC_PRIVATE_KEY) {
+               *inner_format = GCR_FORMAT_DER_PRIVATE_KEY_EC;
+               *outer_format = GCR_FORMAT_PEM_PRIVATE_KEY_EC;
        } else if (armor_type == PEM_ANY_PRIVATE_KEY) {
                *inner_format = GCR_FORMAT_DER_PRIVATE_KEY;
                *outer_format = GCR_FORMAT_PEM_PRIVATE_KEY;
@@ -1934,6 +2033,13 @@ parse_pem_private_key_dsa (GcrParser *self,
 }
 
 static gint
+parse_pem_private_key_ec (GcrParser *self,
+                         GBytes *data)
+{
+       return handle_pem_format (self, GCR_FORMAT_DER_PRIVATE_KEY_EC, data);
+}
+
+static gint
 parse_pem_certificate (GcrParser *self,
                        GBytes *data)
 {
@@ -2028,6 +2134,7 @@ parse_openssh_public (GcrParser *self,
  * @GCR_FORMAT_DER_PRIVATE_KEY: DER encoded private key
  * @GCR_FORMAT_DER_PRIVATE_KEY_RSA: DER encoded RSA private key
  * @GCR_FORMAT_DER_PRIVATE_KEY_DSA: DER encoded DSA private key
+ * @GCR_FORMAT_DER_PRIVATE_KEY_EC: DER encoded EC private key
  * @GCR_FORMAT_DER_SUBJECT_PUBLIC_KEY: DER encoded SubjectPublicKeyInfo
  * @GCR_FORMAT_DER_CERTIFICATE_X509: DER encoded X.509 certificate
  * @GCR_FORMAT_DER_PKCS7: DER encoded PKCS\#7 container file which can contain certificates
@@ -2043,6 +2150,7 @@ parse_openssh_public (GcrParser *self,
  * @GCR_FORMAT_PEM_PRIVATE_KEY: An OpenSSL style PEM file with a private key
  * @GCR_FORMAT_PEM_PRIVATE_KEY_RSA: An OpenSSL style PEM file with a private RSA key
  * @GCR_FORMAT_PEM_PRIVATE_KEY_DSA: An OpenSSL style PEM file with a private DSA key
+ * @GCR_FORMAT_PEM_PRIVATE_KEY_EC: An OpenSSL style PEM file with a private EC key
  * @GCR_FORMAT_PEM_CERTIFICATE_X509: An OpenSSL style PEM file with an X.509 certificate
  * @GCR_FORMAT_PEM_PKCS7: An OpenSSL style PEM file containing PKCS\#7
  * @GCR_FORMAT_PEM_PKCS8_PLAIN: Unencrypted OpenSSL style PEM file containing PKCS\#8
@@ -2065,6 +2173,7 @@ static const ParserFormat parser_normal[] = {
        { GCR_FORMAT_BASE64_SPKAC, parse_base64_spkac },
        { GCR_FORMAT_DER_PRIVATE_KEY_RSA, parse_der_private_key_rsa },
        { GCR_FORMAT_DER_PRIVATE_KEY_DSA, parse_der_private_key_dsa },
+       { GCR_FORMAT_DER_PRIVATE_KEY_EC, parse_der_private_key_ec },
        { GCR_FORMAT_DER_SUBJECT_PUBLIC_KEY, parse_der_subject_public_key },
        { GCR_FORMAT_DER_CERTIFICATE_X509, parse_der_certificate },
        { GCR_FORMAT_DER_PKCS7, parse_der_pkcs7 },
@@ -2083,6 +2192,7 @@ static const ParserFormat parser_formats[] = {
        { GCR_FORMAT_DER_PRIVATE_KEY, parse_der_private_key },
        { GCR_FORMAT_DER_PRIVATE_KEY_RSA, parse_der_private_key_rsa },
        { GCR_FORMAT_DER_PRIVATE_KEY_DSA, parse_der_private_key_dsa },
+       { GCR_FORMAT_DER_PRIVATE_KEY_EC, parse_der_private_key_ec },
        { GCR_FORMAT_DER_SUBJECT_PUBLIC_KEY, parse_der_subject_public_key },
        { GCR_FORMAT_DER_CERTIFICATE_X509, parse_der_certificate },
        { GCR_FORMAT_DER_PKCS7, parse_der_pkcs7 },
@@ -2105,6 +2215,7 @@ static const ParserFormat parser_formats[] = {
        { GCR_FORMAT_PEM_PKCS8_ENCRYPTED, parse_pem_pkcs8_encrypted },
        { GCR_FORMAT_PEM_PKCS12, parse_pem_pkcs12 },
        { GCR_FORMAT_PEM_PKCS10, parse_pem_pkcs10 },
+       { GCR_FORMAT_PEM_PRIVATE_KEY_EC, parse_pem_private_key_ec },
 };
 
 static int
diff --git a/gcr/gcr-types.h b/gcr/gcr-types.h
index f600454..3711380 100644
--- a/gcr/gcr-types.h
+++ b/gcr/gcr-types.h
@@ -63,6 +63,7 @@ typedef enum {
        GCR_FORMAT_DER_PRIVATE_KEY = 100,
        GCR_FORMAT_DER_PRIVATE_KEY_RSA,
        GCR_FORMAT_DER_PRIVATE_KEY_DSA,
+       GCR_FORMAT_DER_PRIVATE_KEY_EC,
 
        GCR_FORMAT_DER_SUBJECT_PUBLIC_KEY = 150,
 
@@ -95,6 +96,7 @@ typedef enum {
        GCR_FORMAT_PEM_PKCS12,
        GCR_FORMAT_PEM_PRIVATE_KEY,
        GCR_FORMAT_PEM_PKCS10,
+       GCR_FORMAT_PEM_PRIVATE_KEY_EC,
 } GcrDataFormat;
 
 /*


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