[gcr/ecc: 8/12] Implement support for parsing ecdsa OpenSSH keys



commit 4f01742f5c1ee4cc0dd362842eebf47d2d406cd6
Author: Stef Walter <stefw redhat com>
Date:   Thu Apr 17 07:14:41 2014 +0200

    Implement support for parsing ecdsa OpenSSH keys

 gcr/gcr-openssh.c                |   68 ++++++++++++++++++++++++++++++++++++++
 gcr/test-openssh.c               |   25 +++++++++++++-
 testing/ssh-example/id_ecdsa     |    8 ++++
 testing/ssh-example/id_ecdsa.pub |    1 +
 4 files changed, 101 insertions(+), 1 deletions(-)
---
diff --git a/gcr/gcr-openssh.c b/gcr/gcr-openssh.c
index b8a0b39..06e3263 100644
--- a/gcr/gcr-openssh.c
+++ b/gcr/gcr-openssh.c
@@ -25,6 +25,10 @@
 #include "gcr-internal.h"
 #include "gcr-types.h"
 
+#include "gcr/gcr-oids.h"
+
+#include "egg/egg-asn1x.h"
+#include "egg/egg-asn1-defs.h"
 #include "egg/egg-buffer.h"
 #include "egg/egg-decimal.h"
 
@@ -116,6 +120,8 @@ keytype_to_algo (const gchar *algo,
                return CKK_RSA;
        else if (match_word (algo, length, "ssh-dss"))
                return CKK_DSA;
+       else if (length >= 6 && strncmp (algo, "ecdsa-", 6) == 0)
+               return CKK_ECDSA;
        return G_MAXULONG;
 }
 
@@ -291,6 +297,65 @@ read_v2_public_rsa (EggBuffer *buffer,
 }
 
 static gboolean
+read_v2_public_ecdsa (EggBuffer *buffer,
+                      gsize *offset,
+                      GckBuilder *builder)
+{
+       gconstpointer data;
+       GBytes *bytes;
+       GNode *asn;
+       GNode *node;
+       gchar *curve;
+       GQuark oid;
+       gsize len;
+
+       /* The named curve */
+       if (!egg_buffer_get_string (buffer, *offset, offset,
+                                   &curve, (EggBufferAllocator)g_realloc))
+               return FALSE;
+
+       if (g_strcmp0 (curve, "nistp256") == 0) {
+               oid = GCR_OID_EC_SECP256R1;
+       } else if (g_strcmp0 (curve, "nistp384") == 0) {
+               oid = GCR_OID_EC_SECP384R1;
+       } else if (g_strcmp0 (curve, "nistp521") == 0) {
+               oid = GCR_OID_EC_SECP521R1;
+       } else {
+               g_free (curve);
+               g_message ("unknown or unsupported curve in ssh public key");
+               return FALSE;
+       }
+
+       g_free (curve);
+
+       asn = egg_asn1x_create (pkix_asn1_tab, "ECParameters");
+       g_return_val_if_fail (asn != NULL, FALSE);
+
+       node = egg_asn1x_node (asn, "namedCurve", NULL);
+       if (!egg_asn1x_set_choice (asn, node))
+               g_return_val_if_reached (FALSE);
+
+       if (!egg_asn1x_set_oid_as_quark (node, oid))
+               g_return_val_if_reached (FALSE);
+
+       bytes = egg_asn1x_encode (asn, g_realloc);
+       g_return_val_if_fail (bytes != NULL, FALSE);
+       egg_asn1x_destroy (asn);
+
+       data = g_bytes_get_data (bytes, &len);
+       gck_builder_add_data (builder, CKA_EC_PARAMS, data, len);
+       g_bytes_unref (bytes);
+
+       if (!read_buffer_mpi (buffer, offset, builder, CKA_EC_POINT))
+               return FALSE;
+
+       gck_builder_add_ulong (builder, CKA_KEY_TYPE, CKK_ECDSA);
+       gck_builder_add_ulong (builder, CKA_CLASS, CKO_PUBLIC_KEY);
+
+       return TRUE;
+}
+
+static gboolean
 read_v2_public_key (gulong algo,
                     gconstpointer data,
                     gsize n_data,
@@ -326,6 +391,9 @@ read_v2_public_key (gulong algo,
        case CKK_DSA:
                ret = read_v2_public_dsa (&buffer, &offset, builder);
                break;
+       case CKK_ECDSA:
+               ret = read_v2_public_ecdsa (&buffer, &offset, builder);
+               break;
        default:
                g_assert_not_reached ();
                break;
diff --git a/gcr/test-openssh.c b/gcr/test-openssh.c
index bde412a..a48e282 100644
--- a/gcr/test-openssh.c
+++ b/gcr/test-openssh.c
@@ -67,6 +67,11 @@ typedef struct {
        "U9Dy2N8Sch/Ngtg2E/FBo5geljWobJXd1jxmPtF2WAliYJXDdIt6RBVPGL9H/KSjDmBMsV" \
        "d42wxVJywawzypklVZjSUuWuBMI= dsa-key example com \n"
 
+#define OPENSSH_PUBLIC_ECDSA \
+       "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAA" \
+       "BBBMKWn4nDF3IVAB2XKK8MdlMV0r1PkwHWemNuNkKnDSLy1CA17IEBXzEFX0yDEaC/8cFG" \
+       "Bc0VblrySYCYKvJc+is= ecdsa-key example com \n"
+
 #define EXTRA_LINES_WITHOUT_KEY \
        "\n# Comment\n\n" \
        "20aa3\n" \
@@ -158,6 +163,23 @@ test_parse_v2_dsa (Test *test,
 }
 
 static void
+test_parse_v2_ecdsa (Test *test,
+                    gconstpointer unused)
+{
+       const gchar *data = OPENSSH_PUBLIC_ECDSA EXTRA_LINES_WITHOUT_KEY;
+       GBytes *bytes;
+       gint keys;
+
+       test->expected_label = "ecdsa-key example com";
+
+       bytes = g_bytes_new_static (data, strlen (data));
+       keys = _gcr_openssh_pub_parse (bytes, on_openssh_pub_parse, test);
+       g_assert_cmpint (keys, ==, 1);
+
+       g_bytes_unref (bytes);
+}
+
+static void
 test_parse_v1_options (Test *test,
                        gconstpointer unused)
 {
@@ -198,11 +220,12 @@ main (int argc, char **argv)
        g_type_init ();
 #endif
        g_test_init (&argc, &argv, NULL);
-       g_set_prgname ("test-gnupg-process");
+       g_set_prgname ("test-openssh");
 
        g_test_add ("/gcr/openssh/parse_v1_rsa", Test, NULL, setup, test_parse_v1_rsa, teardown);
        g_test_add ("/gcr/openssh/parse_v2_rsa", Test, NULL, setup, test_parse_v2_rsa, teardown);
        g_test_add ("/gcr/openssh/parse_v2_dsa", Test, NULL, setup, test_parse_v2_dsa, teardown);
+       g_test_add ("/gcr/openssh/parse_v2_ecdsa", Test, NULL, setup, test_parse_v2_ecdsa, teardown);
        g_test_add ("/gcr/openssh/parse_v1_options", Test, NULL, setup, test_parse_v1_options, teardown);
        g_test_add ("/gcr/openssh/parse_v2_options", Test, NULL, setup, test_parse_v2_options, teardown);
 
diff --git a/testing/ssh-example/id_ecdsa b/testing/ssh-example/id_ecdsa
new file mode 100644
index 0000000..fdfbb3c
--- /dev/null
+++ b/testing/ssh-example/id_ecdsa
@@ -0,0 +1,8 @@
+-----BEGIN EC PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,90D5DC6AEE85FE9929F112F5E22E8295
+
+2SlRUDeauO04UsLRZMfma2vQwzv2l16l/LEyWx325JNOdEjlGAuYiycJr0b2qr7u
+vAv0pc71Re8Jg6nSVSy9O4werYnkQcb6E6MTaZCCUgqRqtGfmHtHvhIDxSqybPv7
+iCjTfzLtuJ6C6TiLH9h7OVfDW/tcWg08MJ5VP1iMHhA=
+-----END EC PRIVATE KEY-----
diff --git a/testing/ssh-example/id_ecdsa.pub b/testing/ssh-example/id_ecdsa.pub
new file mode 100644
index 0000000..119a4ad
--- /dev/null
+++ b/testing/ssh-example/id_ecdsa.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256 
AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMKWn4nDF3IVAB2XKK8MdlMV0r1PkwHWemNuNkKnDSLy1CA17IEBXzEFX0yDEaC/8cFGBc0VblrySYCYKvJc+is=
 stef stef thewalter lan


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