agent: Add support for RSA signatures with SHA256 and SHA512
authorTobias Brunner <tobias@strongswan.org>
Fri, 19 Oct 2018 07:17:39 +0000 (09:17 +0200)
committerTobias Brunner <tobias@strongswan.org>
Fri, 26 Oct 2018 07:55:07 +0000 (09:55 +0200)
src/libstrongswan/plugins/agent/agent_private_key.c

index 77c2991..70bee69 100644 (file)
@@ -82,6 +82,14 @@ enum agent_msg_type_t {
 };
 
 /**
+ * Flags for signatures
+ */
+enum agent_signature_flags_t {
+       SSH_AGENT_FLAG_SHA2_256 = 2,
+       SSH_AGENT_FLAG_SHA2_512 = 4,
+};
+
+/**
  * read a byte from a blob
  */
 static u_char read_byte(chunk_t *blob)
@@ -217,12 +225,29 @@ static bool read_key(private_agent_private_key_t *this, public_key_t *pubkey)
 }
 
 static bool scheme_supported(private_agent_private_key_t *this,
-                                                       signature_scheme_t scheme)
+                                                        signature_scheme_t scheme, uint32_t *flags,
+                                                        char **prefix)
 {
        switch (this->pubkey->get_type(this->pubkey))
        {
                case KEY_RSA:
-                       return scheme == SIGN_RSA_EMSA_PKCS1_SHA1;
+                       switch (scheme)
+                       {
+                               case SIGN_RSA_EMSA_PKCS1_SHA1:
+                                       *prefix = "ssh-rsa";
+                                       return TRUE;
+                               case SIGN_RSA_EMSA_PKCS1_SHA2_256:
+                                       *flags |= SSH_AGENT_FLAG_SHA2_256;
+                                       *prefix = "rsa-sha2-256";
+                                       return TRUE;
+                               case SIGN_RSA_EMSA_PKCS1_SHA2_512:
+                                       *flags |= SSH_AGENT_FLAG_SHA2_512;
+                                       *prefix = "rsa-sha2-512";
+                                       return TRUE;
+                               default:
+                                       break;
+                       }
+                       return FALSE;
                case KEY_ECDSA:
                        return scheme == SIGN_ECDSA_256 ||
                                   scheme == SIGN_ECDSA_384 ||
@@ -236,11 +261,11 @@ METHOD(private_key_t, sign, bool,
        private_agent_private_key_t *this, signature_scheme_t scheme, void *params,
        chunk_t data, chunk_t *signature)
 {
-       uint32_t len, flags;
-       char buf[2048];
+       uint32_t len, flags = 0;
+       char buf[2048], *prefix = NULL;
        chunk_t blob;
 
-       if (!scheme_supported(this, scheme))
+       if (!scheme_supported(this, scheme, &flags, &prefix))
        {
                DBG1(DBG_LIB, "signature scheme %N not supported by ssh-agent",
                         signature_scheme_names, scheme);
@@ -272,7 +297,7 @@ METHOD(private_key_t, sign, bool,
                return FALSE;
        }
 
-       flags = htonl(0);
+       flags = htonl(flags);
        if (write(this->socket, &flags, sizeof(flags)) != sizeof(flags))
        {
                DBG1(DBG_LIB, "writing to ssh-agent failed");
@@ -290,9 +315,15 @@ METHOD(private_key_t, sign, bool,
        }
        /* parse length */
        blob = read_string(&blob);
-       /* check sig type */
-       if (chunk_equals(read_string(&blob), chunk_from_str("ssh-rsa")))
-       {       /* for RSA the signature has no special encoding */
+       /* verify type */
+       if (prefix && !chunk_equals(read_string(&blob), chunk_from_str(prefix)))
+       {
+               DBG1(DBG_LIB, "ssh-agent didn't return requested %s signature", prefix);
+               return FALSE;
+       }
+
+       if (this->pubkey->get_type(this->pubkey) == KEY_RSA)
+       {       /* for RSA, the signature has no special encoding */
                blob = read_string(&blob);
                if (blob.len)
                {
@@ -301,7 +332,7 @@ METHOD(private_key_t, sign, bool,
                }
        }
        else
-       {       /* anything else is treated as ECSDA for now */
+       {       /* parse ECDSA signatures */
                blob = read_string(&blob);
                if (blob.len)
                {