1*18de8d7fSPeter Avalos /* $OpenBSD: ssh-rsa.c,v 1.39 2006/08/03 03:34:42 deraadt Exp $ */ 2*18de8d7fSPeter Avalos /* 3*18de8d7fSPeter Avalos * Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org> 4*18de8d7fSPeter Avalos * 5*18de8d7fSPeter Avalos * Permission to use, copy, modify, and distribute this software for any 6*18de8d7fSPeter Avalos * purpose with or without fee is hereby granted, provided that the above 7*18de8d7fSPeter Avalos * copyright notice and this permission notice appear in all copies. 8*18de8d7fSPeter Avalos * 9*18de8d7fSPeter Avalos * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10*18de8d7fSPeter Avalos * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11*18de8d7fSPeter Avalos * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12*18de8d7fSPeter Avalos * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13*18de8d7fSPeter Avalos * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14*18de8d7fSPeter Avalos * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15*18de8d7fSPeter Avalos * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16*18de8d7fSPeter Avalos */ 17*18de8d7fSPeter Avalos 18*18de8d7fSPeter Avalos #include "includes.h" 19*18de8d7fSPeter Avalos 20*18de8d7fSPeter Avalos #include <sys/types.h> 21*18de8d7fSPeter Avalos 22*18de8d7fSPeter Avalos #include <openssl/evp.h> 23*18de8d7fSPeter Avalos #include <openssl/err.h> 24*18de8d7fSPeter Avalos 25*18de8d7fSPeter Avalos #include <stdarg.h> 26*18de8d7fSPeter Avalos #include <string.h> 27*18de8d7fSPeter Avalos 28*18de8d7fSPeter Avalos #include "xmalloc.h" 29*18de8d7fSPeter Avalos #include "log.h" 30*18de8d7fSPeter Avalos #include "buffer.h" 31*18de8d7fSPeter Avalos #include "key.h" 32*18de8d7fSPeter Avalos #include "compat.h" 33*18de8d7fSPeter Avalos #include "ssh.h" 34*18de8d7fSPeter Avalos 35*18de8d7fSPeter Avalos static int openssh_RSA_verify(int, u_char *, u_int, u_char *, u_int, RSA *); 36*18de8d7fSPeter Avalos 37*18de8d7fSPeter Avalos /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ 38*18de8d7fSPeter Avalos int 39*18de8d7fSPeter Avalos ssh_rsa_sign(const Key *key, u_char **sigp, u_int *lenp, 40*18de8d7fSPeter Avalos const u_char *data, u_int datalen) 41*18de8d7fSPeter Avalos { 42*18de8d7fSPeter Avalos const EVP_MD *evp_md; 43*18de8d7fSPeter Avalos EVP_MD_CTX md; 44*18de8d7fSPeter Avalos u_char digest[EVP_MAX_MD_SIZE], *sig; 45*18de8d7fSPeter Avalos u_int slen, dlen, len; 46*18de8d7fSPeter Avalos int ok, nid; 47*18de8d7fSPeter Avalos Buffer b; 48*18de8d7fSPeter Avalos 49*18de8d7fSPeter Avalos if (key == NULL || key->type != KEY_RSA || key->rsa == NULL) { 50*18de8d7fSPeter Avalos error("ssh_rsa_sign: no RSA key"); 51*18de8d7fSPeter Avalos return -1; 52*18de8d7fSPeter Avalos } 53*18de8d7fSPeter Avalos nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1; 54*18de8d7fSPeter Avalos if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { 55*18de8d7fSPeter Avalos error("ssh_rsa_sign: EVP_get_digestbynid %d failed", nid); 56*18de8d7fSPeter Avalos return -1; 57*18de8d7fSPeter Avalos } 58*18de8d7fSPeter Avalos EVP_DigestInit(&md, evp_md); 59*18de8d7fSPeter Avalos EVP_DigestUpdate(&md, data, datalen); 60*18de8d7fSPeter Avalos EVP_DigestFinal(&md, digest, &dlen); 61*18de8d7fSPeter Avalos 62*18de8d7fSPeter Avalos slen = RSA_size(key->rsa); 63*18de8d7fSPeter Avalos sig = xmalloc(slen); 64*18de8d7fSPeter Avalos 65*18de8d7fSPeter Avalos ok = RSA_sign(nid, digest, dlen, sig, &len, key->rsa); 66*18de8d7fSPeter Avalos memset(digest, 'd', sizeof(digest)); 67*18de8d7fSPeter Avalos 68*18de8d7fSPeter Avalos if (ok != 1) { 69*18de8d7fSPeter Avalos int ecode = ERR_get_error(); 70*18de8d7fSPeter Avalos 71*18de8d7fSPeter Avalos error("ssh_rsa_sign: RSA_sign failed: %s", 72*18de8d7fSPeter Avalos ERR_error_string(ecode, NULL)); 73*18de8d7fSPeter Avalos xfree(sig); 74*18de8d7fSPeter Avalos return -1; 75*18de8d7fSPeter Avalos } 76*18de8d7fSPeter Avalos if (len < slen) { 77*18de8d7fSPeter Avalos u_int diff = slen - len; 78*18de8d7fSPeter Avalos debug("slen %u > len %u", slen, len); 79*18de8d7fSPeter Avalos memmove(sig + diff, sig, len); 80*18de8d7fSPeter Avalos memset(sig, 0, diff); 81*18de8d7fSPeter Avalos } else if (len > slen) { 82*18de8d7fSPeter Avalos error("ssh_rsa_sign: slen %u slen2 %u", slen, len); 83*18de8d7fSPeter Avalos xfree(sig); 84*18de8d7fSPeter Avalos return -1; 85*18de8d7fSPeter Avalos } 86*18de8d7fSPeter Avalos /* encode signature */ 87*18de8d7fSPeter Avalos buffer_init(&b); 88*18de8d7fSPeter Avalos buffer_put_cstring(&b, "ssh-rsa"); 89*18de8d7fSPeter Avalos buffer_put_string(&b, sig, slen); 90*18de8d7fSPeter Avalos len = buffer_len(&b); 91*18de8d7fSPeter Avalos if (lenp != NULL) 92*18de8d7fSPeter Avalos *lenp = len; 93*18de8d7fSPeter Avalos if (sigp != NULL) { 94*18de8d7fSPeter Avalos *sigp = xmalloc(len); 95*18de8d7fSPeter Avalos memcpy(*sigp, buffer_ptr(&b), len); 96*18de8d7fSPeter Avalos } 97*18de8d7fSPeter Avalos buffer_free(&b); 98*18de8d7fSPeter Avalos memset(sig, 's', slen); 99*18de8d7fSPeter Avalos xfree(sig); 100*18de8d7fSPeter Avalos 101*18de8d7fSPeter Avalos return 0; 102*18de8d7fSPeter Avalos } 103*18de8d7fSPeter Avalos 104*18de8d7fSPeter Avalos int 105*18de8d7fSPeter Avalos ssh_rsa_verify(const Key *key, const u_char *signature, u_int signaturelen, 106*18de8d7fSPeter Avalos const u_char *data, u_int datalen) 107*18de8d7fSPeter Avalos { 108*18de8d7fSPeter Avalos Buffer b; 109*18de8d7fSPeter Avalos const EVP_MD *evp_md; 110*18de8d7fSPeter Avalos EVP_MD_CTX md; 111*18de8d7fSPeter Avalos char *ktype; 112*18de8d7fSPeter Avalos u_char digest[EVP_MAX_MD_SIZE], *sigblob; 113*18de8d7fSPeter Avalos u_int len, dlen, modlen; 114*18de8d7fSPeter Avalos int rlen, ret, nid; 115*18de8d7fSPeter Avalos 116*18de8d7fSPeter Avalos if (key == NULL || key->type != KEY_RSA || key->rsa == NULL) { 117*18de8d7fSPeter Avalos error("ssh_rsa_verify: no RSA key"); 118*18de8d7fSPeter Avalos return -1; 119*18de8d7fSPeter Avalos } 120*18de8d7fSPeter Avalos if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { 121*18de8d7fSPeter Avalos error("ssh_rsa_verify: RSA modulus too small: %d < minimum %d bits", 122*18de8d7fSPeter Avalos BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE); 123*18de8d7fSPeter Avalos return -1; 124*18de8d7fSPeter Avalos } 125*18de8d7fSPeter Avalos buffer_init(&b); 126*18de8d7fSPeter Avalos buffer_append(&b, signature, signaturelen); 127*18de8d7fSPeter Avalos ktype = buffer_get_string(&b, NULL); 128*18de8d7fSPeter Avalos if (strcmp("ssh-rsa", ktype) != 0) { 129*18de8d7fSPeter Avalos error("ssh_rsa_verify: cannot handle type %s", ktype); 130*18de8d7fSPeter Avalos buffer_free(&b); 131*18de8d7fSPeter Avalos xfree(ktype); 132*18de8d7fSPeter Avalos return -1; 133*18de8d7fSPeter Avalos } 134*18de8d7fSPeter Avalos xfree(ktype); 135*18de8d7fSPeter Avalos sigblob = buffer_get_string(&b, &len); 136*18de8d7fSPeter Avalos rlen = buffer_len(&b); 137*18de8d7fSPeter Avalos buffer_free(&b); 138*18de8d7fSPeter Avalos if (rlen != 0) { 139*18de8d7fSPeter Avalos error("ssh_rsa_verify: remaining bytes in signature %d", rlen); 140*18de8d7fSPeter Avalos xfree(sigblob); 141*18de8d7fSPeter Avalos return -1; 142*18de8d7fSPeter Avalos } 143*18de8d7fSPeter Avalos /* RSA_verify expects a signature of RSA_size */ 144*18de8d7fSPeter Avalos modlen = RSA_size(key->rsa); 145*18de8d7fSPeter Avalos if (len > modlen) { 146*18de8d7fSPeter Avalos error("ssh_rsa_verify: len %u > modlen %u", len, modlen); 147*18de8d7fSPeter Avalos xfree(sigblob); 148*18de8d7fSPeter Avalos return -1; 149*18de8d7fSPeter Avalos } else if (len < modlen) { 150*18de8d7fSPeter Avalos u_int diff = modlen - len; 151*18de8d7fSPeter Avalos debug("ssh_rsa_verify: add padding: modlen %u > len %u", 152*18de8d7fSPeter Avalos modlen, len); 153*18de8d7fSPeter Avalos sigblob = xrealloc(sigblob, 1, modlen); 154*18de8d7fSPeter Avalos memmove(sigblob + diff, sigblob, len); 155*18de8d7fSPeter Avalos memset(sigblob, 0, diff); 156*18de8d7fSPeter Avalos len = modlen; 157*18de8d7fSPeter Avalos } 158*18de8d7fSPeter Avalos nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1; 159*18de8d7fSPeter Avalos if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { 160*18de8d7fSPeter Avalos error("ssh_rsa_verify: EVP_get_digestbynid %d failed", nid); 161*18de8d7fSPeter Avalos xfree(sigblob); 162*18de8d7fSPeter Avalos return -1; 163*18de8d7fSPeter Avalos } 164*18de8d7fSPeter Avalos EVP_DigestInit(&md, evp_md); 165*18de8d7fSPeter Avalos EVP_DigestUpdate(&md, data, datalen); 166*18de8d7fSPeter Avalos EVP_DigestFinal(&md, digest, &dlen); 167*18de8d7fSPeter Avalos 168*18de8d7fSPeter Avalos ret = openssh_RSA_verify(nid, digest, dlen, sigblob, len, key->rsa); 169*18de8d7fSPeter Avalos memset(digest, 'd', sizeof(digest)); 170*18de8d7fSPeter Avalos memset(sigblob, 's', len); 171*18de8d7fSPeter Avalos xfree(sigblob); 172*18de8d7fSPeter Avalos debug("ssh_rsa_verify: signature %scorrect", (ret==0) ? "in" : ""); 173*18de8d7fSPeter Avalos return ret; 174*18de8d7fSPeter Avalos } 175*18de8d7fSPeter Avalos 176*18de8d7fSPeter Avalos /* 177*18de8d7fSPeter Avalos * See: 178*18de8d7fSPeter Avalos * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/ 179*18de8d7fSPeter Avalos * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn 180*18de8d7fSPeter Avalos */ 181*18de8d7fSPeter Avalos /* 182*18de8d7fSPeter Avalos * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) 183*18de8d7fSPeter Avalos * oiw(14) secsig(3) algorithms(2) 26 } 184*18de8d7fSPeter Avalos */ 185*18de8d7fSPeter Avalos static const u_char id_sha1[] = { 186*18de8d7fSPeter Avalos 0x30, 0x21, /* type Sequence, length 0x21 (33) */ 187*18de8d7fSPeter Avalos 0x30, 0x09, /* type Sequence, length 0x09 */ 188*18de8d7fSPeter Avalos 0x06, 0x05, /* type OID, length 0x05 */ 189*18de8d7fSPeter Avalos 0x2b, 0x0e, 0x03, 0x02, 0x1a, /* id-sha1 OID */ 190*18de8d7fSPeter Avalos 0x05, 0x00, /* NULL */ 191*18de8d7fSPeter Avalos 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */ 192*18de8d7fSPeter Avalos }; 193*18de8d7fSPeter Avalos /* 194*18de8d7fSPeter Avalos * id-md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) 195*18de8d7fSPeter Avalos * rsadsi(113549) digestAlgorithm(2) 5 } 196*18de8d7fSPeter Avalos */ 197*18de8d7fSPeter Avalos static const u_char id_md5[] = { 198*18de8d7fSPeter Avalos 0x30, 0x20, /* type Sequence, length 0x20 (32) */ 199*18de8d7fSPeter Avalos 0x30, 0x0c, /* type Sequence, length 0x09 */ 200*18de8d7fSPeter Avalos 0x06, 0x08, /* type OID, length 0x05 */ 201*18de8d7fSPeter Avalos 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* id-md5 */ 202*18de8d7fSPeter Avalos 0x05, 0x00, /* NULL */ 203*18de8d7fSPeter Avalos 0x04, 0x10 /* Octet string, length 0x10 (16), followed by md5 hash */ 204*18de8d7fSPeter Avalos }; 205*18de8d7fSPeter Avalos 206*18de8d7fSPeter Avalos static int 207*18de8d7fSPeter Avalos openssh_RSA_verify(int type, u_char *hash, u_int hashlen, 208*18de8d7fSPeter Avalos u_char *sigbuf, u_int siglen, RSA *rsa) 209*18de8d7fSPeter Avalos { 210*18de8d7fSPeter Avalos u_int ret, rsasize, oidlen = 0, hlen = 0; 211*18de8d7fSPeter Avalos int len; 212*18de8d7fSPeter Avalos const u_char *oid = NULL; 213*18de8d7fSPeter Avalos u_char *decrypted = NULL; 214*18de8d7fSPeter Avalos 215*18de8d7fSPeter Avalos ret = 0; 216*18de8d7fSPeter Avalos switch (type) { 217*18de8d7fSPeter Avalos case NID_sha1: 218*18de8d7fSPeter Avalos oid = id_sha1; 219*18de8d7fSPeter Avalos oidlen = sizeof(id_sha1); 220*18de8d7fSPeter Avalos hlen = 20; 221*18de8d7fSPeter Avalos break; 222*18de8d7fSPeter Avalos case NID_md5: 223*18de8d7fSPeter Avalos oid = id_md5; 224*18de8d7fSPeter Avalos oidlen = sizeof(id_md5); 225*18de8d7fSPeter Avalos hlen = 16; 226*18de8d7fSPeter Avalos break; 227*18de8d7fSPeter Avalos default: 228*18de8d7fSPeter Avalos goto done; 229*18de8d7fSPeter Avalos } 230*18de8d7fSPeter Avalos if (hashlen != hlen) { 231*18de8d7fSPeter Avalos error("bad hashlen"); 232*18de8d7fSPeter Avalos goto done; 233*18de8d7fSPeter Avalos } 234*18de8d7fSPeter Avalos rsasize = RSA_size(rsa); 235*18de8d7fSPeter Avalos if (siglen == 0 || siglen > rsasize) { 236*18de8d7fSPeter Avalos error("bad siglen"); 237*18de8d7fSPeter Avalos goto done; 238*18de8d7fSPeter Avalos } 239*18de8d7fSPeter Avalos decrypted = xmalloc(rsasize); 240*18de8d7fSPeter Avalos if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa, 241*18de8d7fSPeter Avalos RSA_PKCS1_PADDING)) < 0) { 242*18de8d7fSPeter Avalos error("RSA_public_decrypt failed: %s", 243*18de8d7fSPeter Avalos ERR_error_string(ERR_get_error(), NULL)); 244*18de8d7fSPeter Avalos goto done; 245*18de8d7fSPeter Avalos } 246*18de8d7fSPeter Avalos if (len < 0 || (u_int)len != hlen + oidlen) { 247*18de8d7fSPeter Avalos error("bad decrypted len: %d != %d + %d", len, hlen, oidlen); 248*18de8d7fSPeter Avalos goto done; 249*18de8d7fSPeter Avalos } 250*18de8d7fSPeter Avalos if (memcmp(decrypted, oid, oidlen) != 0) { 251*18de8d7fSPeter Avalos error("oid mismatch"); 252*18de8d7fSPeter Avalos goto done; 253*18de8d7fSPeter Avalos } 254*18de8d7fSPeter Avalos if (memcmp(decrypted + oidlen, hash, hlen) != 0) { 255*18de8d7fSPeter Avalos error("hash mismatch"); 256*18de8d7fSPeter Avalos goto done; 257*18de8d7fSPeter Avalos } 258*18de8d7fSPeter Avalos ret = 1; 259*18de8d7fSPeter Avalos done: 260*18de8d7fSPeter Avalos if (decrypted) 261*18de8d7fSPeter Avalos xfree(decrypted); 262*18de8d7fSPeter Avalos return ret; 263*18de8d7fSPeter Avalos } 264