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

[PATCH] Fix ability to use ECDSA host keys


Hi folks,

After our previous discussion on the inability to enable ECDSA keys, I
found some bugs in how they are actually used in libssh (even if one
were able to enable them).  With these changes, and some version of
changes to allow ECDSA host keys to be enabled (I used my prior patch
for testing and added an option to samplesshd), I was able to
successfully get examples sample and samplesshd to communicate, as
well as an OpenSSH client and samplesshd.

There were two issues:
- ecdsa_nid was not copied to duplicated ECDSA private keys
- SHA-2 hashing was not used for sessionid generation for ECDSA keys
(instead SHA-1 was being used)

Thanks,
- Alan
From 894cf7e77e392570f7df1b26aff0be50a0a3e99b Mon Sep 17 00:00:00 2001
From: Alan Dunn <amdunn@xxxxxxxxx>
Date: Fri, 14 Feb 2014 10:36:29 -0600
Subject: [PATCH] pki: Fix ability to use ECDSA host keys

- Ensure ecdsa_nid is copied into duplicated private keys
- Use SHA-2 for sessionid generation with ECDSA keys (was SHA-1)

Signed-off-by: Alan Dunn <amdunn@xxxxxxxxx>
---
 src/pki.c        |   54 ++++++++++++++++++++++++++++++++++++++++++------------
 src/pki_crypto.c |    4 ++--
 2 files changed, 44 insertions(+), 14 deletions(-)

diff --git a/src/pki.c b/src/pki.c
index b8d0d6b..27fe53f 100644
--- a/src/pki.c
+++ b/src/pki.c
@@ -1299,6 +1299,11 @@ int ssh_pki_signature_verify_blob(ssh_session session,
 
         evp(key->ecdsa_nid, digest, dlen, ehash, &elen);
 
+#ifdef DEBUG_CRYPTO
+        ssh_print_hexa("Hash to be verified with ecdsa",
+                       ehash, elen);
+#endif
+
         rc = pki_signature_verify(session,
                                   sig,
                                   key,
@@ -1365,6 +1370,10 @@ ssh_string ssh_pki_do_sign(ssh_session session,
         evp_update(ctx, buffer_get_rest(sigbuf), buffer_get_rest_len(sigbuf));
         evp_final(ctx, ehash, &elen);
 
+#ifdef DEBUG_CRYPTO
+        ssh_print_hexa("Hash being signed", ehash, elen);
+#endif
+
         sig = pki_do_sign(privkey, ehash, elen);
 #endif
     } else {
@@ -1458,10 +1467,8 @@ ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session,
                                          const ssh_key privkey)
 {
     struct ssh_crypto_struct *crypto;
-    unsigned char hash[SHA_DIGEST_LEN] = {0};
     ssh_signature sig;
     ssh_string sig_blob;
-    SHACTX ctx;
     int rc;
 
     if (session == NULL || privkey == NULL || !ssh_key_is_private(privkey)) {
@@ -1470,24 +1477,47 @@ ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session,
     crypto = session->next_crypto ? session->next_crypto :
                                        session->current_crypto;
 
-    ctx = sha1_init();
-    if (ctx == NULL) {
-        return NULL;
-    }
     if (crypto->secret_hash == NULL){
         ssh_set_error(session,SSH_FATAL,"Missing secret_hash");
         return NULL;
     }
-    sha1_update(ctx, crypto->secret_hash, crypto->digest_len);
-    sha1_final(hash, ctx);
+
+    if (privkey->type == SSH_KEYTYPE_ECDSA) {
+#ifdef HAVE_ECC
+        unsigned char ehash[EVP_DIGEST_LEN] = {0};
+        uint32_t elen;
+
+        evp(privkey->ecdsa_nid, crypto->secret_hash, crypto->digest_len,
+            ehash, &elen);
 
 #ifdef DEBUG_CRYPTO
-    ssh_print_hexa("Hash being signed", hash, SHA_DIGEST_LEN);
+        ssh_print_hexa("Hash being signed", ehash, elen);
 #endif
 
-    sig = pki_do_sign_sessionid(privkey, hash, SHA_DIGEST_LEN);
-    if (sig == NULL) {
-        return NULL;
+        sig = pki_do_sign_sessionid(privkey, ehash, elen);
+        if (sig == NULL) {
+            return NULL;
+        }
+#endif
+    } else {
+        unsigned char hash[SHA_DIGEST_LEN] = {0};
+        SHACTX ctx;
+
+        ctx = sha1_init();
+        if (ctx == NULL) {
+            return NULL;
+        }
+        sha1_update(ctx, crypto->secret_hash, crypto->digest_len);
+        sha1_final(hash, ctx);
+
+#ifdef DEBUG_CRYPTO
+        ssh_print_hexa("Hash being signed", hash, SHA_DIGEST_LEN);
+#endif
+
+        sig = pki_do_sign_sessionid(privkey, hash, SHA_DIGEST_LEN);
+        if (sig == NULL) {
+            return NULL;
+        }
     }
 
     rc = ssh_pki_export_signature_blob(sig, &sig_blob);
diff --git a/src/pki_crypto.c b/src/pki_crypto.c
index b5a48a4..73bced3 100644
--- a/src/pki_crypto.c
+++ b/src/pki_crypto.c
@@ -346,12 +346,12 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
     case SSH_KEYTYPE_ECDSA:
 #ifdef HAVE_OPENSSL_ECC
         /* privkey -> pubkey */
+        new->ecdsa_nid = key->ecdsa_nid;
+
         if (demote && ssh_key_is_private(key)) {
             const EC_POINT *p;
             int ok;
 
-            new->ecdsa_nid = key->ecdsa_nid;
-
             new->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid);
             if (new->ecdsa == NULL) {
                 goto fail;
-- 
1.7.9.5


Follow-Ups:
Re: [PATCH] Fix ability to use ECDSA host keysDustin Oprea <myselfasunder@xxxxxxxxx>
Re: [PATCH] Fix ability to use ECDSA host keysAris Adamantiadis <aris@xxxxxxxxxxxx>
Re: [PATCH] Fix ability to use ECDSA host keysAndreas Schneider <asn@xxxxxxxxxxxxxx>
Archive administrator: postmaster@lists.cynapses.org