1*acc1a9efSDag-Erling Smørgrav /* $OpenBSD: ssh-rsa.c,v 1.58 2015/12/11 04:21:12 mmcc Exp $ */ 21e8db6e2SBrian Feldman /* 3d95e11bfSDag-Erling Smørgrav * Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org> 41e8db6e2SBrian Feldman * 5d95e11bfSDag-Erling Smørgrav * Permission to use, copy, modify, and distribute this software for any 6d95e11bfSDag-Erling Smørgrav * purpose with or without fee is hereby granted, provided that the above 7d95e11bfSDag-Erling Smørgrav * copyright notice and this permission notice appear in all copies. 81e8db6e2SBrian Feldman * 9d95e11bfSDag-Erling Smørgrav * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10d95e11bfSDag-Erling Smørgrav * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11d95e11bfSDag-Erling Smørgrav * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12d95e11bfSDag-Erling Smørgrav * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13d95e11bfSDag-Erling Smørgrav * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14d95e11bfSDag-Erling Smørgrav * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15d95e11bfSDag-Erling Smørgrav * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 161e8db6e2SBrian Feldman */ 17761efaa7SDag-Erling Smørgrav 181e8db6e2SBrian Feldman #include "includes.h" 19761efaa7SDag-Erling Smørgrav 20bc5531deSDag-Erling Smørgrav #ifdef WITH_OPENSSL 21bc5531deSDag-Erling Smørgrav 22761efaa7SDag-Erling Smørgrav #include <sys/types.h> 231e8db6e2SBrian Feldman 241e8db6e2SBrian Feldman #include <openssl/evp.h> 251e8db6e2SBrian Feldman #include <openssl/err.h> 261e8db6e2SBrian Feldman 27761efaa7SDag-Erling Smørgrav #include <stdarg.h> 28761efaa7SDag-Erling Smørgrav #include <string.h> 29761efaa7SDag-Erling Smørgrav 30a0ee8cc6SDag-Erling Smørgrav #include "sshbuf.h" 311e8db6e2SBrian Feldman #include "compat.h" 32a0ee8cc6SDag-Erling Smørgrav #include "ssherr.h" 33a0ee8cc6SDag-Erling Smørgrav #define SSHKEY_INTERNAL 34a0ee8cc6SDag-Erling Smørgrav #include "sshkey.h" 35f7167e0eSDag-Erling Smørgrav #include "digest.h" 361e8db6e2SBrian Feldman 37a0ee8cc6SDag-Erling Smørgrav static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *); 384b17dab0SDag-Erling Smørgrav 39*acc1a9efSDag-Erling Smørgrav static const char * 40*acc1a9efSDag-Erling Smørgrav rsa_hash_alg_ident(int hash_alg) 41*acc1a9efSDag-Erling Smørgrav { 42*acc1a9efSDag-Erling Smørgrav switch (hash_alg) { 43*acc1a9efSDag-Erling Smørgrav case SSH_DIGEST_SHA1: 44*acc1a9efSDag-Erling Smørgrav return "ssh-rsa"; 45*acc1a9efSDag-Erling Smørgrav case SSH_DIGEST_SHA256: 46*acc1a9efSDag-Erling Smørgrav return "rsa-sha2-256"; 47*acc1a9efSDag-Erling Smørgrav case SSH_DIGEST_SHA512: 48*acc1a9efSDag-Erling Smørgrav return "rsa-sha2-512"; 49*acc1a9efSDag-Erling Smørgrav } 50*acc1a9efSDag-Erling Smørgrav return NULL; 51*acc1a9efSDag-Erling Smørgrav } 52*acc1a9efSDag-Erling Smørgrav 53*acc1a9efSDag-Erling Smørgrav static int 54*acc1a9efSDag-Erling Smørgrav rsa_hash_alg_from_ident(const char *ident) 55*acc1a9efSDag-Erling Smørgrav { 56*acc1a9efSDag-Erling Smørgrav if (strcmp(ident, "ssh-rsa") == 0) 57*acc1a9efSDag-Erling Smørgrav return SSH_DIGEST_SHA1; 58*acc1a9efSDag-Erling Smørgrav if (strcmp(ident, "rsa-sha2-256") == 0) 59*acc1a9efSDag-Erling Smørgrav return SSH_DIGEST_SHA256; 60*acc1a9efSDag-Erling Smørgrav if (strcmp(ident, "rsa-sha2-512") == 0) 61*acc1a9efSDag-Erling Smørgrav return SSH_DIGEST_SHA512; 62*acc1a9efSDag-Erling Smørgrav return -1; 63*acc1a9efSDag-Erling Smørgrav } 64*acc1a9efSDag-Erling Smørgrav 65*acc1a9efSDag-Erling Smørgrav static int 66*acc1a9efSDag-Erling Smørgrav rsa_hash_alg_nid(int type) 67*acc1a9efSDag-Erling Smørgrav { 68*acc1a9efSDag-Erling Smørgrav switch (type) { 69*acc1a9efSDag-Erling Smørgrav case SSH_DIGEST_SHA1: 70*acc1a9efSDag-Erling Smørgrav return NID_sha1; 71*acc1a9efSDag-Erling Smørgrav case SSH_DIGEST_SHA256: 72*acc1a9efSDag-Erling Smørgrav return NID_sha256; 73*acc1a9efSDag-Erling Smørgrav case SSH_DIGEST_SHA512: 74*acc1a9efSDag-Erling Smørgrav return NID_sha512; 75*acc1a9efSDag-Erling Smørgrav default: 76*acc1a9efSDag-Erling Smørgrav return -1; 77*acc1a9efSDag-Erling Smørgrav } 78*acc1a9efSDag-Erling Smørgrav } 79*acc1a9efSDag-Erling Smørgrav 801e8db6e2SBrian Feldman /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ 811e8db6e2SBrian Feldman int 82a0ee8cc6SDag-Erling Smørgrav ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, 83*acc1a9efSDag-Erling Smørgrav const u_char *data, size_t datalen, const char *alg_ident) 841e8db6e2SBrian Feldman { 85a0ee8cc6SDag-Erling Smørgrav u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL; 86a0ee8cc6SDag-Erling Smørgrav size_t slen; 87a0ee8cc6SDag-Erling Smørgrav u_int dlen, len; 88*acc1a9efSDag-Erling Smørgrav int nid, hash_alg, ret = SSH_ERR_INTERNAL_ERROR; 89a0ee8cc6SDag-Erling Smørgrav struct sshbuf *b = NULL; 901e8db6e2SBrian Feldman 91a0ee8cc6SDag-Erling Smørgrav if (lenp != NULL) 92a0ee8cc6SDag-Erling Smørgrav *lenp = 0; 93a0ee8cc6SDag-Erling Smørgrav if (sigp != NULL) 94a0ee8cc6SDag-Erling Smørgrav *sigp = NULL; 95a0ee8cc6SDag-Erling Smørgrav 96*acc1a9efSDag-Erling Smørgrav if (alg_ident == NULL || strlen(alg_ident) == 0 || 97*acc1a9efSDag-Erling Smørgrav strncmp(alg_ident, "ssh-rsa-cert", strlen("ssh-rsa-cert")) == 0) 98*acc1a9efSDag-Erling Smørgrav hash_alg = SSH_DIGEST_SHA1; 99*acc1a9efSDag-Erling Smørgrav else 100*acc1a9efSDag-Erling Smørgrav hash_alg = rsa_hash_alg_from_ident(alg_ident); 101*acc1a9efSDag-Erling Smørgrav if (key == NULL || key->rsa == NULL || hash_alg == -1 || 102*acc1a9efSDag-Erling Smørgrav sshkey_type_plain(key->type) != KEY_RSA || 103*acc1a9efSDag-Erling Smørgrav BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) 104a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_INVALID_ARGUMENT; 105a0ee8cc6SDag-Erling Smørgrav slen = RSA_size(key->rsa); 106a0ee8cc6SDag-Erling Smørgrav if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM) 107a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_INVALID_ARGUMENT; 108f7167e0eSDag-Erling Smørgrav 109f7167e0eSDag-Erling Smørgrav /* hash the data */ 110*acc1a9efSDag-Erling Smørgrav nid = rsa_hash_alg_nid(hash_alg); 111a0ee8cc6SDag-Erling Smørgrav if ((dlen = ssh_digest_bytes(hash_alg)) == 0) 112a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_INTERNAL_ERROR; 113a0ee8cc6SDag-Erling Smørgrav if ((ret = ssh_digest_memory(hash_alg, data, datalen, 114a0ee8cc6SDag-Erling Smørgrav digest, sizeof(digest))) != 0) 115a0ee8cc6SDag-Erling Smørgrav goto out; 116a0ee8cc6SDag-Erling Smørgrav 117a0ee8cc6SDag-Erling Smørgrav if ((sig = malloc(slen)) == NULL) { 118a0ee8cc6SDag-Erling Smørgrav ret = SSH_ERR_ALLOC_FAIL; 119a0ee8cc6SDag-Erling Smørgrav goto out; 120f7167e0eSDag-Erling Smørgrav } 1211e8db6e2SBrian Feldman 122a0ee8cc6SDag-Erling Smørgrav if (RSA_sign(nid, digest, dlen, sig, &len, key->rsa) != 1) { 123a0ee8cc6SDag-Erling Smørgrav ret = SSH_ERR_LIBCRYPTO_ERROR; 124a0ee8cc6SDag-Erling Smørgrav goto out; 1251e8db6e2SBrian Feldman } 1261e8db6e2SBrian Feldman if (len < slen) { 127a0ee8cc6SDag-Erling Smørgrav size_t diff = slen - len; 1281e8db6e2SBrian Feldman memmove(sig + diff, sig, len); 129b83788ffSDag-Erling Smørgrav explicit_bzero(sig, diff); 1301e8db6e2SBrian Feldman } else if (len > slen) { 131a0ee8cc6SDag-Erling Smørgrav ret = SSH_ERR_INTERNAL_ERROR; 132a0ee8cc6SDag-Erling Smørgrav goto out; 1331e8db6e2SBrian Feldman } 1341e8db6e2SBrian Feldman /* encode signature */ 135a0ee8cc6SDag-Erling Smørgrav if ((b = sshbuf_new()) == NULL) { 136a0ee8cc6SDag-Erling Smørgrav ret = SSH_ERR_ALLOC_FAIL; 137a0ee8cc6SDag-Erling Smørgrav goto out; 138a0ee8cc6SDag-Erling Smørgrav } 139*acc1a9efSDag-Erling Smørgrav if ((ret = sshbuf_put_cstring(b, rsa_hash_alg_ident(hash_alg))) != 0 || 140a0ee8cc6SDag-Erling Smørgrav (ret = sshbuf_put_string(b, sig, slen)) != 0) 141a0ee8cc6SDag-Erling Smørgrav goto out; 142a0ee8cc6SDag-Erling Smørgrav len = sshbuf_len(b); 143a0ee8cc6SDag-Erling Smørgrav if (sigp != NULL) { 144a0ee8cc6SDag-Erling Smørgrav if ((*sigp = malloc(len)) == NULL) { 145a0ee8cc6SDag-Erling Smørgrav ret = SSH_ERR_ALLOC_FAIL; 146a0ee8cc6SDag-Erling Smørgrav goto out; 147a0ee8cc6SDag-Erling Smørgrav } 148a0ee8cc6SDag-Erling Smørgrav memcpy(*sigp, sshbuf_ptr(b), len); 149a0ee8cc6SDag-Erling Smørgrav } 1504b17dab0SDag-Erling Smørgrav if (lenp != NULL) 1514b17dab0SDag-Erling Smørgrav *lenp = len; 152a0ee8cc6SDag-Erling Smørgrav ret = 0; 153a0ee8cc6SDag-Erling Smørgrav out: 154a0ee8cc6SDag-Erling Smørgrav explicit_bzero(digest, sizeof(digest)); 155a0ee8cc6SDag-Erling Smørgrav if (sig != NULL) { 156b83788ffSDag-Erling Smørgrav explicit_bzero(sig, slen); 157e4a9863fSDag-Erling Smørgrav free(sig); 158a0ee8cc6SDag-Erling Smørgrav } 159a0ee8cc6SDag-Erling Smørgrav sshbuf_free(b); 160557f75e5SDag-Erling Smørgrav return ret; 1611e8db6e2SBrian Feldman } 1621e8db6e2SBrian Feldman 1631e8db6e2SBrian Feldman int 164a0ee8cc6SDag-Erling Smørgrav ssh_rsa_verify(const struct sshkey *key, 165*acc1a9efSDag-Erling Smørgrav const u_char *sig, size_t siglen, const u_char *data, size_t datalen) 1661e8db6e2SBrian Feldman { 167a0ee8cc6SDag-Erling Smørgrav char *ktype = NULL; 168a0ee8cc6SDag-Erling Smørgrav int hash_alg, ret = SSH_ERR_INTERNAL_ERROR; 169a0ee8cc6SDag-Erling Smørgrav size_t len, diff, modlen, dlen; 170a0ee8cc6SDag-Erling Smørgrav struct sshbuf *b = NULL; 171a0ee8cc6SDag-Erling Smørgrav u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL; 1721e8db6e2SBrian Feldman 173a0ee8cc6SDag-Erling Smørgrav if (key == NULL || key->rsa == NULL || 174a0ee8cc6SDag-Erling Smørgrav sshkey_type_plain(key->type) != KEY_RSA || 175a0ee8cc6SDag-Erling Smørgrav BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) 176a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_INVALID_ARGUMENT; 177f7167e0eSDag-Erling Smørgrav 178*acc1a9efSDag-Erling Smørgrav if ((b = sshbuf_from(sig, siglen)) == NULL) 179a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_ALLOC_FAIL; 180a0ee8cc6SDag-Erling Smørgrav if (sshbuf_get_cstring(b, &ktype, NULL) != 0) { 181a0ee8cc6SDag-Erling Smørgrav ret = SSH_ERR_INVALID_FORMAT; 182a0ee8cc6SDag-Erling Smørgrav goto out; 1831e8db6e2SBrian Feldman } 184*acc1a9efSDag-Erling Smørgrav if ((hash_alg = rsa_hash_alg_from_ident(ktype)) == -1) { 185a0ee8cc6SDag-Erling Smørgrav ret = SSH_ERR_KEY_TYPE_MISMATCH; 186a0ee8cc6SDag-Erling Smørgrav goto out; 1871e8db6e2SBrian Feldman } 188a0ee8cc6SDag-Erling Smørgrav if (sshbuf_get_string(b, &sigblob, &len) != 0) { 189a0ee8cc6SDag-Erling Smørgrav ret = SSH_ERR_INVALID_FORMAT; 190a0ee8cc6SDag-Erling Smørgrav goto out; 191a0ee8cc6SDag-Erling Smørgrav } 192a0ee8cc6SDag-Erling Smørgrav if (sshbuf_len(b) != 0) { 193a0ee8cc6SDag-Erling Smørgrav ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; 194a0ee8cc6SDag-Erling Smørgrav goto out; 1951e8db6e2SBrian Feldman } 196545d5ecaSDag-Erling Smørgrav /* RSA_verify expects a signature of RSA_size */ 197545d5ecaSDag-Erling Smørgrav modlen = RSA_size(key->rsa); 198545d5ecaSDag-Erling Smørgrav if (len > modlen) { 199a0ee8cc6SDag-Erling Smørgrav ret = SSH_ERR_KEY_BITS_MISMATCH; 200a0ee8cc6SDag-Erling Smørgrav goto out; 201545d5ecaSDag-Erling Smørgrav } else if (len < modlen) { 202a0ee8cc6SDag-Erling Smørgrav diff = modlen - len; 203a0ee8cc6SDag-Erling Smørgrav osigblob = sigblob; 204a0ee8cc6SDag-Erling Smørgrav if ((sigblob = realloc(sigblob, modlen)) == NULL) { 205a0ee8cc6SDag-Erling Smørgrav sigblob = osigblob; /* put it back for clear/free */ 206a0ee8cc6SDag-Erling Smørgrav ret = SSH_ERR_ALLOC_FAIL; 207a0ee8cc6SDag-Erling Smørgrav goto out; 208a0ee8cc6SDag-Erling Smørgrav } 209545d5ecaSDag-Erling Smørgrav memmove(sigblob + diff, sigblob, len); 210b83788ffSDag-Erling Smørgrav explicit_bzero(sigblob, diff); 211545d5ecaSDag-Erling Smørgrav len = modlen; 212545d5ecaSDag-Erling Smørgrav } 213f7167e0eSDag-Erling Smørgrav if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { 214a0ee8cc6SDag-Erling Smørgrav ret = SSH_ERR_INTERNAL_ERROR; 215a0ee8cc6SDag-Erling Smørgrav goto out; 2161e8db6e2SBrian Feldman } 217a0ee8cc6SDag-Erling Smørgrav if ((ret = ssh_digest_memory(hash_alg, data, datalen, 218a0ee8cc6SDag-Erling Smørgrav digest, sizeof(digest))) != 0) 219a0ee8cc6SDag-Erling Smørgrav goto out; 2201e8db6e2SBrian Feldman 221f7167e0eSDag-Erling Smørgrav ret = openssh_RSA_verify(hash_alg, digest, dlen, sigblob, len, 222f7167e0eSDag-Erling Smørgrav key->rsa); 223a0ee8cc6SDag-Erling Smørgrav out: 224a0ee8cc6SDag-Erling Smørgrav if (sigblob != NULL) { 225b83788ffSDag-Erling Smørgrav explicit_bzero(sigblob, len); 226e4a9863fSDag-Erling Smørgrav free(sigblob); 227a0ee8cc6SDag-Erling Smørgrav } 228a0ee8cc6SDag-Erling Smørgrav free(ktype); 229a0ee8cc6SDag-Erling Smørgrav sshbuf_free(b); 230a0ee8cc6SDag-Erling Smørgrav explicit_bzero(digest, sizeof(digest)); 2311e8db6e2SBrian Feldman return ret; 2321e8db6e2SBrian Feldman } 2334b17dab0SDag-Erling Smørgrav 2344b17dab0SDag-Erling Smørgrav /* 2354b17dab0SDag-Erling Smørgrav * See: 2364b17dab0SDag-Erling Smørgrav * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/ 2374b17dab0SDag-Erling Smørgrav * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn 2384b17dab0SDag-Erling Smørgrav */ 239*acc1a9efSDag-Erling Smørgrav 2404b17dab0SDag-Erling Smørgrav /* 2414b17dab0SDag-Erling Smørgrav * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) 2424b17dab0SDag-Erling Smørgrav * oiw(14) secsig(3) algorithms(2) 26 } 2434b17dab0SDag-Erling Smørgrav */ 2444b17dab0SDag-Erling Smørgrav static const u_char id_sha1[] = { 2454b17dab0SDag-Erling Smørgrav 0x30, 0x21, /* type Sequence, length 0x21 (33) */ 2464b17dab0SDag-Erling Smørgrav 0x30, 0x09, /* type Sequence, length 0x09 */ 2474b17dab0SDag-Erling Smørgrav 0x06, 0x05, /* type OID, length 0x05 */ 2484b17dab0SDag-Erling Smørgrav 0x2b, 0x0e, 0x03, 0x02, 0x1a, /* id-sha1 OID */ 2494b17dab0SDag-Erling Smørgrav 0x05, 0x00, /* NULL */ 2504b17dab0SDag-Erling Smørgrav 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */ 2514b17dab0SDag-Erling Smørgrav }; 2524b17dab0SDag-Erling Smørgrav 253*acc1a9efSDag-Erling Smørgrav /* 254*acc1a9efSDag-Erling Smørgrav * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html 255*acc1a9efSDag-Erling Smørgrav * id-sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) 256*acc1a9efSDag-Erling Smørgrav * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) 257*acc1a9efSDag-Erling Smørgrav * id-sha256(1) } 258*acc1a9efSDag-Erling Smørgrav */ 259*acc1a9efSDag-Erling Smørgrav static const u_char id_sha256[] = { 260*acc1a9efSDag-Erling Smørgrav 0x30, 0x31, /* type Sequence, length 0x31 (49) */ 261*acc1a9efSDag-Erling Smørgrav 0x30, 0x0d, /* type Sequence, length 0x0d (13) */ 262*acc1a9efSDag-Erling Smørgrav 0x06, 0x09, /* type OID, length 0x09 */ 263*acc1a9efSDag-Erling Smørgrav 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, /* id-sha256 */ 264*acc1a9efSDag-Erling Smørgrav 0x05, 0x00, /* NULL */ 265*acc1a9efSDag-Erling Smørgrav 0x04, 0x20 /* Octet string, length 0x20 (32), followed by sha256 hash */ 266*acc1a9efSDag-Erling Smørgrav }; 267*acc1a9efSDag-Erling Smørgrav 268*acc1a9efSDag-Erling Smørgrav /* 269*acc1a9efSDag-Erling Smørgrav * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html 270*acc1a9efSDag-Erling Smørgrav * id-sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) 271*acc1a9efSDag-Erling Smørgrav * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) 272*acc1a9efSDag-Erling Smørgrav * id-sha256(3) } 273*acc1a9efSDag-Erling Smørgrav */ 274*acc1a9efSDag-Erling Smørgrav static const u_char id_sha512[] = { 275*acc1a9efSDag-Erling Smørgrav 0x30, 0x51, /* type Sequence, length 0x51 (81) */ 276*acc1a9efSDag-Erling Smørgrav 0x30, 0x0d, /* type Sequence, length 0x0d (13) */ 277*acc1a9efSDag-Erling Smørgrav 0x06, 0x09, /* type OID, length 0x09 */ 278*acc1a9efSDag-Erling Smørgrav 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, /* id-sha512 */ 279*acc1a9efSDag-Erling Smørgrav 0x05, 0x00, /* NULL */ 280*acc1a9efSDag-Erling Smørgrav 0x04, 0x40 /* Octet string, length 0x40 (64), followed by sha512 hash */ 281*acc1a9efSDag-Erling Smørgrav }; 282*acc1a9efSDag-Erling Smørgrav 283*acc1a9efSDag-Erling Smørgrav static int 284*acc1a9efSDag-Erling Smørgrav rsa_hash_alg_oid(int hash_alg, const u_char **oidp, size_t *oidlenp) 285*acc1a9efSDag-Erling Smørgrav { 286*acc1a9efSDag-Erling Smørgrav switch (hash_alg) { 287*acc1a9efSDag-Erling Smørgrav case SSH_DIGEST_SHA1: 288*acc1a9efSDag-Erling Smørgrav *oidp = id_sha1; 289*acc1a9efSDag-Erling Smørgrav *oidlenp = sizeof(id_sha1); 290*acc1a9efSDag-Erling Smørgrav break; 291*acc1a9efSDag-Erling Smørgrav case SSH_DIGEST_SHA256: 292*acc1a9efSDag-Erling Smørgrav *oidp = id_sha256; 293*acc1a9efSDag-Erling Smørgrav *oidlenp = sizeof(id_sha256); 294*acc1a9efSDag-Erling Smørgrav break; 295*acc1a9efSDag-Erling Smørgrav case SSH_DIGEST_SHA512: 296*acc1a9efSDag-Erling Smørgrav *oidp = id_sha512; 297*acc1a9efSDag-Erling Smørgrav *oidlenp = sizeof(id_sha512); 298*acc1a9efSDag-Erling Smørgrav break; 299*acc1a9efSDag-Erling Smørgrav default: 300*acc1a9efSDag-Erling Smørgrav return SSH_ERR_INVALID_ARGUMENT; 301*acc1a9efSDag-Erling Smørgrav } 302*acc1a9efSDag-Erling Smørgrav return 0; 303*acc1a9efSDag-Erling Smørgrav } 304*acc1a9efSDag-Erling Smørgrav 3054b17dab0SDag-Erling Smørgrav static int 306a0ee8cc6SDag-Erling Smørgrav openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen, 307a0ee8cc6SDag-Erling Smørgrav u_char *sigbuf, size_t siglen, RSA *rsa) 3084b17dab0SDag-Erling Smørgrav { 309*acc1a9efSDag-Erling Smørgrav size_t rsasize = 0, oidlen = 0, hlen = 0; 310*acc1a9efSDag-Erling Smørgrav int ret, len, oidmatch, hashmatch; 3114b17dab0SDag-Erling Smørgrav const u_char *oid = NULL; 3124b17dab0SDag-Erling Smørgrav u_char *decrypted = NULL; 3134b17dab0SDag-Erling Smørgrav 314*acc1a9efSDag-Erling Smørgrav if ((ret = rsa_hash_alg_oid(hash_alg, &oid, &oidlen)) != 0) 315*acc1a9efSDag-Erling Smørgrav return ret; 316a0ee8cc6SDag-Erling Smørgrav ret = SSH_ERR_INTERNAL_ERROR; 317*acc1a9efSDag-Erling Smørgrav hlen = ssh_digest_bytes(hash_alg); 3184b17dab0SDag-Erling Smørgrav if (hashlen != hlen) { 319a0ee8cc6SDag-Erling Smørgrav ret = SSH_ERR_INVALID_ARGUMENT; 3204b17dab0SDag-Erling Smørgrav goto done; 3214b17dab0SDag-Erling Smørgrav } 3224b17dab0SDag-Erling Smørgrav rsasize = RSA_size(rsa); 323a0ee8cc6SDag-Erling Smørgrav if (rsasize <= 0 || rsasize > SSHBUF_MAX_BIGNUM || 324a0ee8cc6SDag-Erling Smørgrav siglen == 0 || siglen > rsasize) { 325a0ee8cc6SDag-Erling Smørgrav ret = SSH_ERR_INVALID_ARGUMENT; 3264b17dab0SDag-Erling Smørgrav goto done; 3274b17dab0SDag-Erling Smørgrav } 328a0ee8cc6SDag-Erling Smørgrav if ((decrypted = malloc(rsasize)) == NULL) { 329a0ee8cc6SDag-Erling Smørgrav ret = SSH_ERR_ALLOC_FAIL; 330a0ee8cc6SDag-Erling Smørgrav goto done; 331a0ee8cc6SDag-Erling Smørgrav } 3324b17dab0SDag-Erling Smørgrav if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa, 3334b17dab0SDag-Erling Smørgrav RSA_PKCS1_PADDING)) < 0) { 334a0ee8cc6SDag-Erling Smørgrav ret = SSH_ERR_LIBCRYPTO_ERROR; 3354b17dab0SDag-Erling Smørgrav goto done; 3364b17dab0SDag-Erling Smørgrav } 337a0ee8cc6SDag-Erling Smørgrav if (len < 0 || (size_t)len != hlen + oidlen) { 338a0ee8cc6SDag-Erling Smørgrav ret = SSH_ERR_INVALID_FORMAT; 3394b17dab0SDag-Erling Smørgrav goto done; 3404b17dab0SDag-Erling Smørgrav } 341e2f6069cSDag-Erling Smørgrav oidmatch = timingsafe_bcmp(decrypted, oid, oidlen) == 0; 342e2f6069cSDag-Erling Smørgrav hashmatch = timingsafe_bcmp(decrypted + oidlen, hash, hlen) == 0; 343a0ee8cc6SDag-Erling Smørgrav if (!oidmatch || !hashmatch) { 344a0ee8cc6SDag-Erling Smørgrav ret = SSH_ERR_SIGNATURE_INVALID; 3454b17dab0SDag-Erling Smørgrav goto done; 3464b17dab0SDag-Erling Smørgrav } 347a0ee8cc6SDag-Erling Smørgrav ret = 0; 3484b17dab0SDag-Erling Smørgrav done: 349a0ee8cc6SDag-Erling Smørgrav if (decrypted) { 350a0ee8cc6SDag-Erling Smørgrav explicit_bzero(decrypted, rsasize); 351e4a9863fSDag-Erling Smørgrav free(decrypted); 352a0ee8cc6SDag-Erling Smørgrav } 3534b17dab0SDag-Erling Smørgrav return ret; 3544b17dab0SDag-Erling Smørgrav } 355bc5531deSDag-Erling Smørgrav #endif /* WITH_OPENSSL */ 356