J
Jamis Buck
--------------030406090703080608070607
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit
I think I've nailed down all the issues that were preventing Net::SSH
from being fully SSH2 compliant. I had to add two new methods to
OpenSSL:Key:SA, to allow processing of raw sigs (since that's what
the SSH server is sending, and expecting).
I've attached a patch. With the addition of the DSA#do_verify method
that this patch exposes, Net::SSH can now successfully handle ssh-dss
server keys.
Please let me know if you need anything further to apply this patch
before the freeze on the 7th.
--
Jamis Buck
(e-mail address removed)
http://www.jamisbuck.org/jamis
ruby -ropenssl
-e'k="01234567";p((c,c.padding,c.iv,c.key=OpenSSL::Cipher::BF.new,0,k,k*2)[0].decrypt.update("1A81803C452C324619D319F980D5B84DBB45FC0FE2BAA045".scan(/../).map{|n|n.to_i(16).chr}.join))'
--------------030406090703080608070607
Content-Type: text/x-patch;
name="dsa.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="dsa.patch"
diff --exclude='*.o' --exclude='*.so' --exclude=dep --exclude=mkmf.log --exclude='*akefile*' -ur ruby.orig/ext/openssl/ossl_pkey_dsa.c ruby/ext/openssl/ossl_pkey_dsa.c
--- ruby.orig/ext/openssl/ossl_pkey_dsa.c 2004-07-01 11:24:44.388960264 -0600
+++ ruby/ext/openssl/ossl_pkey_dsa.c 2004-07-01 12:03:10.877320736 -0600
@@ -372,6 +372,109 @@
return Qfalse;
}
+/* The code for ossl_dsa_do_sign and ossl_dsa_do_verify borrows heavily from
+ * the ssh_dss_sign and ssh_dss_verify functions in the ssh-dss.c file that is
+ * part of OpenSSH distribution. The original code bears the following copyright,
+ * terms, and disclaimer:
+ *
+ * Copyright (c) 2000 Markus Friedl. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define INTBLOB_LEN 20
+#define SIGBLOB_LEN (2*INTBLOB_LEN)
+
+static VALUE
+ossl_dsa_do_sign(VALUE self, VALUE data)
+{
+ DSA_SIG *sig;
+ EVP_MD_CTX md;
+ u_char digest[EVP_MAX_MD_SIZE];
+ u_int dlen, rlen, slen;
+ EVP_PKEY *pkey;
+ VALUE signature;
+
+ GetPKeyDSA(self, pkey);
+ StringValue(data);
+
+ EVP_DigestInit(&md, EVP_sha1());
+ EVP_DigestUpdate(&md, RSTRING(data)->ptr, RSTRING(data)->len);
+ EVP_DigestFinal(&md, digest, &dlen);
+
+ sig = DSA_do_sign(digest, dlen, pkey->pkey.dsa);
+ memset(digest, 0, sizeof(digest));
+
+ rlen = BN_num_bytes(sig->r);
+ slen = BN_num_bytes(sig->s);
+ if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN)
+ {
+ DSA_SIG_free(sig);
+ rb_raise(eDSAError, "bad sig size %u %u", rlen, slen);
+ }
+
+ signature = rb_str_new(0, SIGBLOB_LEN);
+ BN_bn2bin(sig->r, RSTRING(signature)->ptr+SIGBLOB_LEN-INTBLOB_LEN-rlen);
+ BN_bn2bin(sig->s, RSTRING(signature)->ptr+SIGBLOB_LEN-slen);
+ DSA_SIG_free(sig);
+
+ return signature;
+}
+
+static VALUE
+ossl_dsa_do_verify(VALUE self, VALUE signature, VALUE data)
+{
+ DSA_SIG *sig;
+ EVP_MD_CTX md;
+ u_char digest[EVP_MAX_MD_SIZE];
+ u_int dlen;
+ int ret;
+ EVP_PKEY *pkey;
+
+ GetPKeyDSA(self, pkey);
+ StringValue(signature);
+ StringValue(data);
+
+ if (RSTRING(signature)->len != SIGBLOB_LEN)
+ rb_raise(rb_eArgError, "signature must be exactly %d bytes long", SIGBLOB_LEN );
+
+ sig = DSA_SIG_new();
+ sig->r = BN_new();
+ sig->s = BN_new();
+
+ BN_bin2bn(RSTRING(signature)->ptr, INTBLOB_LEN, sig->r);
+ BN_bin2bn(RSTRING(signature)->ptr+INTBLOB_LEN, INTBLOB_LEN, sig->s);
+
+ EVP_DigestInit(&md, EVP_sha1());
+ EVP_DigestUpdate(&md, RSTRING(data)->ptr, RSTRING(data)->len);
+ EVP_DigestFinal(&md, digest, &dlen);
+
+ ret = DSA_do_verify(digest, dlen, sig, pkey->pkey.dsa);
+ memset(digest, 0, sizeof(digest));
+
+ DSA_SIG_free(sig);
+
+ return (ret ? Qtrue : Qfalse);
+}
+
OSSL_PKEY_BN(dsa, p);
OSSL_PKEY_BN(dsa, q);
OSSL_PKEY_BN(dsa, g);
@@ -401,6 +504,8 @@
rb_define_method(cDSA, "public_key", ossl_dsa_to_public_key, 0);
rb_define_method(cDSA, "syssign", ossl_dsa_sign, 1);
rb_define_method(cDSA, "sysverify", ossl_dsa_verify, 2);
+ rb_define_method(cDSA, "do_sign", ossl_dsa_do_sign, 1);
+ rb_define_method(cDSA, "do_verify", ossl_dsa_do_verify, 2);
DEF_OSSL_PKEY_BN(cDSA, dsa, p);
DEF_OSSL_PKEY_BN(cDSA, dsa, q);
--------------030406090703080608070607--
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit
I think I've nailed down all the issues that were preventing Net::SSH
from being fully SSH2 compliant. I had to add two new methods to
OpenSSL:Key:SA, to allow processing of raw sigs (since that's what
the SSH server is sending, and expecting).
I've attached a patch. With the addition of the DSA#do_verify method
that this patch exposes, Net::SSH can now successfully handle ssh-dss
server keys.
Please let me know if you need anything further to apply this patch
before the freeze on the 7th.
--
Jamis Buck
(e-mail address removed)
http://www.jamisbuck.org/jamis
ruby -ropenssl
-e'k="01234567";p((c,c.padding,c.iv,c.key=OpenSSL::Cipher::BF.new,0,k,k*2)[0].decrypt.update("1A81803C452C324619D319F980D5B84DBB45FC0FE2BAA045".scan(/../).map{|n|n.to_i(16).chr}.join))'
--------------030406090703080608070607
Content-Type: text/x-patch;
name="dsa.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="dsa.patch"
diff --exclude='*.o' --exclude='*.so' --exclude=dep --exclude=mkmf.log --exclude='*akefile*' -ur ruby.orig/ext/openssl/ossl_pkey_dsa.c ruby/ext/openssl/ossl_pkey_dsa.c
--- ruby.orig/ext/openssl/ossl_pkey_dsa.c 2004-07-01 11:24:44.388960264 -0600
+++ ruby/ext/openssl/ossl_pkey_dsa.c 2004-07-01 12:03:10.877320736 -0600
@@ -372,6 +372,109 @@
return Qfalse;
}
+/* The code for ossl_dsa_do_sign and ossl_dsa_do_verify borrows heavily from
+ * the ssh_dss_sign and ssh_dss_verify functions in the ssh-dss.c file that is
+ * part of OpenSSH distribution. The original code bears the following copyright,
+ * terms, and disclaimer:
+ *
+ * Copyright (c) 2000 Markus Friedl. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define INTBLOB_LEN 20
+#define SIGBLOB_LEN (2*INTBLOB_LEN)
+
+static VALUE
+ossl_dsa_do_sign(VALUE self, VALUE data)
+{
+ DSA_SIG *sig;
+ EVP_MD_CTX md;
+ u_char digest[EVP_MAX_MD_SIZE];
+ u_int dlen, rlen, slen;
+ EVP_PKEY *pkey;
+ VALUE signature;
+
+ GetPKeyDSA(self, pkey);
+ StringValue(data);
+
+ EVP_DigestInit(&md, EVP_sha1());
+ EVP_DigestUpdate(&md, RSTRING(data)->ptr, RSTRING(data)->len);
+ EVP_DigestFinal(&md, digest, &dlen);
+
+ sig = DSA_do_sign(digest, dlen, pkey->pkey.dsa);
+ memset(digest, 0, sizeof(digest));
+
+ rlen = BN_num_bytes(sig->r);
+ slen = BN_num_bytes(sig->s);
+ if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN)
+ {
+ DSA_SIG_free(sig);
+ rb_raise(eDSAError, "bad sig size %u %u", rlen, slen);
+ }
+
+ signature = rb_str_new(0, SIGBLOB_LEN);
+ BN_bn2bin(sig->r, RSTRING(signature)->ptr+SIGBLOB_LEN-INTBLOB_LEN-rlen);
+ BN_bn2bin(sig->s, RSTRING(signature)->ptr+SIGBLOB_LEN-slen);
+ DSA_SIG_free(sig);
+
+ return signature;
+}
+
+static VALUE
+ossl_dsa_do_verify(VALUE self, VALUE signature, VALUE data)
+{
+ DSA_SIG *sig;
+ EVP_MD_CTX md;
+ u_char digest[EVP_MAX_MD_SIZE];
+ u_int dlen;
+ int ret;
+ EVP_PKEY *pkey;
+
+ GetPKeyDSA(self, pkey);
+ StringValue(signature);
+ StringValue(data);
+
+ if (RSTRING(signature)->len != SIGBLOB_LEN)
+ rb_raise(rb_eArgError, "signature must be exactly %d bytes long", SIGBLOB_LEN );
+
+ sig = DSA_SIG_new();
+ sig->r = BN_new();
+ sig->s = BN_new();
+
+ BN_bin2bn(RSTRING(signature)->ptr, INTBLOB_LEN, sig->r);
+ BN_bin2bn(RSTRING(signature)->ptr+INTBLOB_LEN, INTBLOB_LEN, sig->s);
+
+ EVP_DigestInit(&md, EVP_sha1());
+ EVP_DigestUpdate(&md, RSTRING(data)->ptr, RSTRING(data)->len);
+ EVP_DigestFinal(&md, digest, &dlen);
+
+ ret = DSA_do_verify(digest, dlen, sig, pkey->pkey.dsa);
+ memset(digest, 0, sizeof(digest));
+
+ DSA_SIG_free(sig);
+
+ return (ret ? Qtrue : Qfalse);
+}
+
OSSL_PKEY_BN(dsa, p);
OSSL_PKEY_BN(dsa, q);
OSSL_PKEY_BN(dsa, g);
@@ -401,6 +504,8 @@
rb_define_method(cDSA, "public_key", ossl_dsa_to_public_key, 0);
rb_define_method(cDSA, "syssign", ossl_dsa_sign, 1);
rb_define_method(cDSA, "sysverify", ossl_dsa_verify, 2);
+ rb_define_method(cDSA, "do_sign", ossl_dsa_do_sign, 1);
+ rb_define_method(cDSA, "do_verify", ossl_dsa_do_verify, 2);
DEF_OSSL_PKEY_BN(cDSA, dsa, p);
DEF_OSSL_PKEY_BN(cDSA, dsa, q);
--------------030406090703080608070607--