From 0deb5d958a6bd93fc3a021adb946e19cde4fd4bd Mon Sep 17 00:00:00 2001 From: Ben Lindstrom Date: Tue, 20 Aug 2002 18:40:03 +0000 Subject: [PATCH] - markus@cvs.openbsd.org 2002/08/02 22:20:30 [ssh-rsa.c] replace RSA_verify with our own version and avoid the OpenSSL ASN.1 parser for authentication; ok deraadt/djm --- ChangeLog | 6 +++- ssh-rsa.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 98 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 43ca2df91..13ecbc4d6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -13,6 +13,10 @@ - markus@cvs.openbsd.org 2002/08/02 21:23:41 [ssh-rsa.c] diff is u_int (2x); ok deraadt/provos + - markus@cvs.openbsd.org 2002/08/02 22:20:30 + [ssh-rsa.c] + replace RSA_verify with our own version and avoid the OpenSSL ASN.1 parser + for authentication; ok deraadt/djm 20020813 - (tim) [configure.ac] Display OpenSSL header/library version. @@ -1510,4 +1514,4 @@ - (stevesk) entropy.c: typo in debug message - (djm) ssh-keygen -i needs seeded RNG; report from markus@ -$Id: ChangeLog,v 1.2417 2002/08/20 18:39:14 mouring Exp $ +$Id: ChangeLog,v 1.2418 2002/08/20 18:40:03 mouring Exp $ diff --git a/ssh-rsa.c b/ssh-rsa.c index 8271af42b..44287fa26 100644 --- a/ssh-rsa.c +++ b/ssh-rsa.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: ssh-rsa.c,v 1.24 2002/08/02 21:23:41 markus Exp $"); +RCSID("$OpenBSD: ssh-rsa.c,v 1.25 2002/08/02 22:20:30 markus Exp $"); #include #include @@ -37,6 +37,8 @@ RCSID("$OpenBSD: ssh-rsa.c,v 1.24 2002/08/02 21:23:41 markus Exp $"); #include "compat.h" #include "ssh.h" +static int openssh_RSA_verify(int, u_char *, u_int, u_char *, u_int , RSA *); + /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ int ssh_rsa_sign(Key *key, u_char **sigp, u_int *lenp, @@ -167,15 +169,99 @@ ssh_rsa_verify(Key *key, u_char *signature, u_int signaturelen, EVP_DigestUpdate(&md, data, datalen); EVP_DigestFinal(&md, digest, &dlen); - ret = RSA_verify(nid, digest, dlen, sigblob, len, key->rsa); + ret = openssh_RSA_verify(nid, digest, dlen, sigblob, len, key->rsa); memset(digest, 'd', sizeof(digest)); memset(sigblob, 's', len); xfree(sigblob); - if (ret == 0) { - int ecode = ERR_get_error(); - error("ssh_rsa_verify: RSA_verify failed: %s", - ERR_error_string(ecode, NULL)); - } debug("ssh_rsa_verify: signature %scorrect", (ret==0) ? "in" : ""); return ret; } + +/* + * See: + * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/ + * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn + */ +/* + * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) + * oiw(14) secsig(3) algorithms(2) 26 } + */ +static const u_char id_sha1[] = { + 0x30, 0x21, /* type Sequence, length 0x21 (33) */ + 0x30, 0x09, /* type Sequence, length 0x09 */ + 0x06, 0x05, /* type OID, length 0x05 */ + 0x2b, 0x0e, 0x03, 0x02, 0x1a, /* id-sha1 OID */ + 0x05, 0x00, /* NULL */ + 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */ +}; +/* + * id-md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) + * rsadsi(113549) digestAlgorithm(2) 5 } + */ +static const u_char id_md5[] = { + 0x30, 0x20, /* type Sequence, length 0x20 (32) */ + 0x30, 0x0c, /* type Sequence, length 0x09 */ + 0x06, 0x08, /* type OID, length 0x05 */ + 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* id-md5 */ + 0x05, 0x00, /* NULL */ + 0x04, 0x10 /* Octet string, length 0x10 (16), followed by md5 hash */ +}; + +static int +openssh_RSA_verify(int type, u_char *hash, u_int hashlen, + u_char *sigbuf, u_int siglen, RSA *rsa) +{ + u_int ret, rsasize, len, oidlen = 0, hlen = 0; + const u_char *oid = NULL; + u_char *decrypted = NULL; + + ret = 0; + switch (type) { + case NID_sha1: + oid = id_sha1; + oidlen = sizeof(id_sha1); + hlen = 20; + break; + case NID_md5: + oid = id_md5; + oidlen = sizeof(id_md5); + hlen = 16; + break; + default: + goto done; + break; + } + if (hashlen != hlen) { + error("bad hashlen"); + goto done; + } + rsasize = RSA_size(rsa); + if (siglen == 0 || siglen > rsasize) { + error("bad siglen"); + goto done; + } + decrypted = xmalloc(rsasize); + if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa, + RSA_PKCS1_PADDING)) < 0) { + error("RSA_public_decrypt failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto done; + } + if (len != hlen + oidlen) { + error("bad decrypted len: %d != %d + %d", len, hlen, oidlen); + goto done; + } + if (memcmp(decrypted, oid, oidlen) != 0) { + error("oid mismatch"); + goto done; + } + if (memcmp(decrypted + oidlen, hash, hlen) != 0) { + error("hash mismatch"); + goto done; + } + ret = 1; +done: + if (decrypted) + xfree(decrypted); + return ret; +}