1*ce74bacaSMatthew Dillon /* $OpenBSD: ssh-rsa.c,v 1.62 2017/07/01 13:50:45 djm Exp $ */ 218de8d7fSPeter Avalos /* 318de8d7fSPeter Avalos * Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org> 418de8d7fSPeter Avalos * 518de8d7fSPeter Avalos * Permission to use, copy, modify, and distribute this software for any 618de8d7fSPeter Avalos * purpose with or without fee is hereby granted, provided that the above 718de8d7fSPeter Avalos * copyright notice and this permission notice appear in all copies. 818de8d7fSPeter Avalos * 918de8d7fSPeter Avalos * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1018de8d7fSPeter Avalos * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1118de8d7fSPeter Avalos * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1218de8d7fSPeter Avalos * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1318de8d7fSPeter Avalos * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1418de8d7fSPeter Avalos * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1518de8d7fSPeter Avalos * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1618de8d7fSPeter Avalos */ 1718de8d7fSPeter Avalos 1818de8d7fSPeter Avalos #include "includes.h" 1918de8d7fSPeter Avalos 20e9778795SPeter Avalos #ifdef WITH_OPENSSL 21e9778795SPeter Avalos 2218de8d7fSPeter Avalos #include <sys/types.h> 2318de8d7fSPeter Avalos 2418de8d7fSPeter Avalos #include <openssl/evp.h> 2518de8d7fSPeter Avalos #include <openssl/err.h> 2618de8d7fSPeter Avalos 2718de8d7fSPeter Avalos #include <stdarg.h> 2818de8d7fSPeter Avalos #include <string.h> 2918de8d7fSPeter Avalos 3036e94dc5SPeter Avalos #include "sshbuf.h" 3118de8d7fSPeter Avalos #include "compat.h" 3236e94dc5SPeter Avalos #include "ssherr.h" 3336e94dc5SPeter Avalos #define SSHKEY_INTERNAL 3436e94dc5SPeter Avalos #include "sshkey.h" 3536e94dc5SPeter Avalos #include "digest.h" 3618de8d7fSPeter Avalos 3736e94dc5SPeter Avalos static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *); 3818de8d7fSPeter Avalos 39e9778795SPeter Avalos static const char * 40e9778795SPeter Avalos rsa_hash_alg_ident(int hash_alg) 41e9778795SPeter Avalos { 42e9778795SPeter Avalos switch (hash_alg) { 43e9778795SPeter Avalos case SSH_DIGEST_SHA1: 44e9778795SPeter Avalos return "ssh-rsa"; 45e9778795SPeter Avalos case SSH_DIGEST_SHA256: 46e9778795SPeter Avalos return "rsa-sha2-256"; 47e9778795SPeter Avalos case SSH_DIGEST_SHA512: 48e9778795SPeter Avalos return "rsa-sha2-512"; 49e9778795SPeter Avalos } 50e9778795SPeter Avalos return NULL; 51e9778795SPeter Avalos } 52e9778795SPeter Avalos 53e9778795SPeter Avalos static int 54e9778795SPeter Avalos rsa_hash_alg_from_ident(const char *ident) 55e9778795SPeter Avalos { 56*ce74bacaSMatthew Dillon if (strcmp(ident, "ssh-rsa") == 0 || 57*ce74bacaSMatthew Dillon strcmp(ident, "ssh-rsa-cert-v01@openssh.com") == 0) 58e9778795SPeter Avalos return SSH_DIGEST_SHA1; 59e9778795SPeter Avalos if (strcmp(ident, "rsa-sha2-256") == 0) 60e9778795SPeter Avalos return SSH_DIGEST_SHA256; 61e9778795SPeter Avalos if (strcmp(ident, "rsa-sha2-512") == 0) 62e9778795SPeter Avalos return SSH_DIGEST_SHA512; 63e9778795SPeter Avalos return -1; 64e9778795SPeter Avalos } 65e9778795SPeter Avalos 66e9778795SPeter Avalos static int 67e9778795SPeter Avalos rsa_hash_alg_nid(int type) 68e9778795SPeter Avalos { 69e9778795SPeter Avalos switch (type) { 70e9778795SPeter Avalos case SSH_DIGEST_SHA1: 71e9778795SPeter Avalos return NID_sha1; 72e9778795SPeter Avalos case SSH_DIGEST_SHA256: 73e9778795SPeter Avalos return NID_sha256; 74e9778795SPeter Avalos case SSH_DIGEST_SHA512: 75e9778795SPeter Avalos return NID_sha512; 76e9778795SPeter Avalos default: 77e9778795SPeter Avalos return -1; 78e9778795SPeter Avalos } 79e9778795SPeter Avalos } 80e9778795SPeter Avalos 81*ce74bacaSMatthew Dillon /* calculate p-1 and q-1 */ 82*ce74bacaSMatthew Dillon int 83*ce74bacaSMatthew Dillon ssh_rsa_generate_additional_parameters(struct sshkey *key) 84*ce74bacaSMatthew Dillon { 85*ce74bacaSMatthew Dillon RSA *rsa; 86*ce74bacaSMatthew Dillon BIGNUM *aux = NULL; 87*ce74bacaSMatthew Dillon BN_CTX *ctx = NULL; 88*ce74bacaSMatthew Dillon int r; 89*ce74bacaSMatthew Dillon 90*ce74bacaSMatthew Dillon if (key == NULL || key->rsa == NULL || 91*ce74bacaSMatthew Dillon sshkey_type_plain(key->type) != KEY_RSA) 92*ce74bacaSMatthew Dillon return SSH_ERR_INVALID_ARGUMENT; 93*ce74bacaSMatthew Dillon 94*ce74bacaSMatthew Dillon if ((ctx = BN_CTX_new()) == NULL) 95*ce74bacaSMatthew Dillon return SSH_ERR_ALLOC_FAIL; 96*ce74bacaSMatthew Dillon if ((aux = BN_new()) == NULL) { 97*ce74bacaSMatthew Dillon r = SSH_ERR_ALLOC_FAIL; 98*ce74bacaSMatthew Dillon goto out; 99*ce74bacaSMatthew Dillon } 100*ce74bacaSMatthew Dillon rsa = key->rsa; 101*ce74bacaSMatthew Dillon 102*ce74bacaSMatthew Dillon if ((BN_sub(aux, rsa->q, BN_value_one()) == 0) || 103*ce74bacaSMatthew Dillon (BN_mod(rsa->dmq1, rsa->d, aux, ctx) == 0) || 104*ce74bacaSMatthew Dillon (BN_sub(aux, rsa->p, BN_value_one()) == 0) || 105*ce74bacaSMatthew Dillon (BN_mod(rsa->dmp1, rsa->d, aux, ctx) == 0)) { 106*ce74bacaSMatthew Dillon r = SSH_ERR_LIBCRYPTO_ERROR; 107*ce74bacaSMatthew Dillon goto out; 108*ce74bacaSMatthew Dillon } 109*ce74bacaSMatthew Dillon r = 0; 110*ce74bacaSMatthew Dillon out: 111*ce74bacaSMatthew Dillon BN_clear_free(aux); 112*ce74bacaSMatthew Dillon BN_CTX_free(ctx); 113*ce74bacaSMatthew Dillon return r; 114*ce74bacaSMatthew Dillon } 115*ce74bacaSMatthew Dillon 11618de8d7fSPeter Avalos /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ 11718de8d7fSPeter Avalos int 11836e94dc5SPeter Avalos ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, 119e9778795SPeter Avalos const u_char *data, size_t datalen, const char *alg_ident) 12018de8d7fSPeter Avalos { 12136e94dc5SPeter Avalos u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL; 12236e94dc5SPeter Avalos size_t slen; 12336e94dc5SPeter Avalos u_int dlen, len; 124e9778795SPeter Avalos int nid, hash_alg, ret = SSH_ERR_INTERNAL_ERROR; 12536e94dc5SPeter Avalos struct sshbuf *b = NULL; 12618de8d7fSPeter Avalos 12736e94dc5SPeter Avalos if (lenp != NULL) 12836e94dc5SPeter Avalos *lenp = 0; 12936e94dc5SPeter Avalos if (sigp != NULL) 13036e94dc5SPeter Avalos *sigp = NULL; 13118de8d7fSPeter Avalos 132*ce74bacaSMatthew Dillon if (alg_ident == NULL || strlen(alg_ident) == 0) 133e9778795SPeter Avalos hash_alg = SSH_DIGEST_SHA1; 134e9778795SPeter Avalos else 135e9778795SPeter Avalos hash_alg = rsa_hash_alg_from_ident(alg_ident); 136e9778795SPeter Avalos if (key == NULL || key->rsa == NULL || hash_alg == -1 || 137*ce74bacaSMatthew Dillon sshkey_type_plain(key->type) != KEY_RSA) 13836e94dc5SPeter Avalos return SSH_ERR_INVALID_ARGUMENT; 139*ce74bacaSMatthew Dillon if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) 140*ce74bacaSMatthew Dillon return SSH_ERR_KEY_LENGTH; 14118de8d7fSPeter Avalos slen = RSA_size(key->rsa); 14236e94dc5SPeter Avalos if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM) 14336e94dc5SPeter Avalos return SSH_ERR_INVALID_ARGUMENT; 14418de8d7fSPeter Avalos 14536e94dc5SPeter Avalos /* hash the data */ 146e9778795SPeter Avalos nid = rsa_hash_alg_nid(hash_alg); 14736e94dc5SPeter Avalos if ((dlen = ssh_digest_bytes(hash_alg)) == 0) 14836e94dc5SPeter Avalos return SSH_ERR_INTERNAL_ERROR; 14936e94dc5SPeter Avalos if ((ret = ssh_digest_memory(hash_alg, data, datalen, 15036e94dc5SPeter Avalos digest, sizeof(digest))) != 0) 15136e94dc5SPeter Avalos goto out; 15218de8d7fSPeter Avalos 15336e94dc5SPeter Avalos if ((sig = malloc(slen)) == NULL) { 15436e94dc5SPeter Avalos ret = SSH_ERR_ALLOC_FAIL; 15536e94dc5SPeter Avalos goto out; 15636e94dc5SPeter Avalos } 15718de8d7fSPeter Avalos 15836e94dc5SPeter Avalos if (RSA_sign(nid, digest, dlen, sig, &len, key->rsa) != 1) { 15936e94dc5SPeter Avalos ret = SSH_ERR_LIBCRYPTO_ERROR; 16036e94dc5SPeter Avalos goto out; 16118de8d7fSPeter Avalos } 16218de8d7fSPeter Avalos if (len < slen) { 16336e94dc5SPeter Avalos size_t diff = slen - len; 16418de8d7fSPeter Avalos memmove(sig + diff, sig, len); 16536e94dc5SPeter Avalos explicit_bzero(sig, diff); 16618de8d7fSPeter Avalos } else if (len > slen) { 16736e94dc5SPeter Avalos ret = SSH_ERR_INTERNAL_ERROR; 16836e94dc5SPeter Avalos goto out; 16918de8d7fSPeter Avalos } 17018de8d7fSPeter Avalos /* encode signature */ 17136e94dc5SPeter Avalos if ((b = sshbuf_new()) == NULL) { 17236e94dc5SPeter Avalos ret = SSH_ERR_ALLOC_FAIL; 17336e94dc5SPeter Avalos goto out; 17436e94dc5SPeter Avalos } 175e9778795SPeter Avalos if ((ret = sshbuf_put_cstring(b, rsa_hash_alg_ident(hash_alg))) != 0 || 17636e94dc5SPeter Avalos (ret = sshbuf_put_string(b, sig, slen)) != 0) 17736e94dc5SPeter Avalos goto out; 17836e94dc5SPeter Avalos len = sshbuf_len(b); 17936e94dc5SPeter Avalos if (sigp != NULL) { 18036e94dc5SPeter Avalos if ((*sigp = malloc(len)) == NULL) { 18136e94dc5SPeter Avalos ret = SSH_ERR_ALLOC_FAIL; 18236e94dc5SPeter Avalos goto out; 18336e94dc5SPeter Avalos } 18436e94dc5SPeter Avalos memcpy(*sigp, sshbuf_ptr(b), len); 18536e94dc5SPeter Avalos } 18618de8d7fSPeter Avalos if (lenp != NULL) 18718de8d7fSPeter Avalos *lenp = len; 18836e94dc5SPeter Avalos ret = 0; 18936e94dc5SPeter Avalos out: 19036e94dc5SPeter Avalos explicit_bzero(digest, sizeof(digest)); 19136e94dc5SPeter Avalos if (sig != NULL) { 19236e94dc5SPeter Avalos explicit_bzero(sig, slen); 19336e94dc5SPeter Avalos free(sig); 19418de8d7fSPeter Avalos } 19536e94dc5SPeter Avalos sshbuf_free(b); 196e9778795SPeter Avalos return ret; 19718de8d7fSPeter Avalos } 19818de8d7fSPeter Avalos 19918de8d7fSPeter Avalos int 20036e94dc5SPeter Avalos ssh_rsa_verify(const struct sshkey *key, 201e9778795SPeter Avalos const u_char *sig, size_t siglen, const u_char *data, size_t datalen) 20218de8d7fSPeter Avalos { 20336e94dc5SPeter Avalos char *ktype = NULL; 20436e94dc5SPeter Avalos int hash_alg, ret = SSH_ERR_INTERNAL_ERROR; 20536e94dc5SPeter Avalos size_t len, diff, modlen, dlen; 20636e94dc5SPeter Avalos struct sshbuf *b = NULL; 20736e94dc5SPeter Avalos u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL; 20818de8d7fSPeter Avalos 20936e94dc5SPeter Avalos if (key == NULL || key->rsa == NULL || 21036e94dc5SPeter Avalos sshkey_type_plain(key->type) != KEY_RSA || 211e9778795SPeter Avalos sig == NULL || siglen == 0) 21236e94dc5SPeter Avalos return SSH_ERR_INVALID_ARGUMENT; 213*ce74bacaSMatthew Dillon if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) 214*ce74bacaSMatthew Dillon return SSH_ERR_KEY_LENGTH; 21536e94dc5SPeter Avalos 216e9778795SPeter Avalos if ((b = sshbuf_from(sig, siglen)) == NULL) 21736e94dc5SPeter Avalos return SSH_ERR_ALLOC_FAIL; 21836e94dc5SPeter Avalos if (sshbuf_get_cstring(b, &ktype, NULL) != 0) { 21936e94dc5SPeter Avalos ret = SSH_ERR_INVALID_FORMAT; 22036e94dc5SPeter Avalos goto out; 22118de8d7fSPeter Avalos } 222e9778795SPeter Avalos if ((hash_alg = rsa_hash_alg_from_ident(ktype)) == -1) { 22336e94dc5SPeter Avalos ret = SSH_ERR_KEY_TYPE_MISMATCH; 22436e94dc5SPeter Avalos goto out; 22518de8d7fSPeter Avalos } 22636e94dc5SPeter Avalos if (sshbuf_get_string(b, &sigblob, &len) != 0) { 22736e94dc5SPeter Avalos ret = SSH_ERR_INVALID_FORMAT; 22836e94dc5SPeter Avalos goto out; 22936e94dc5SPeter Avalos } 23036e94dc5SPeter Avalos if (sshbuf_len(b) != 0) { 23136e94dc5SPeter Avalos ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; 23236e94dc5SPeter Avalos goto out; 23318de8d7fSPeter Avalos } 23418de8d7fSPeter Avalos /* RSA_verify expects a signature of RSA_size */ 23518de8d7fSPeter Avalos modlen = RSA_size(key->rsa); 23618de8d7fSPeter Avalos if (len > modlen) { 23736e94dc5SPeter Avalos ret = SSH_ERR_KEY_BITS_MISMATCH; 23836e94dc5SPeter Avalos goto out; 23918de8d7fSPeter Avalos } else if (len < modlen) { 24036e94dc5SPeter Avalos diff = modlen - len; 24136e94dc5SPeter Avalos osigblob = sigblob; 24236e94dc5SPeter Avalos if ((sigblob = realloc(sigblob, modlen)) == NULL) { 24336e94dc5SPeter Avalos sigblob = osigblob; /* put it back for clear/free */ 24436e94dc5SPeter Avalos ret = SSH_ERR_ALLOC_FAIL; 24536e94dc5SPeter Avalos goto out; 24636e94dc5SPeter Avalos } 24718de8d7fSPeter Avalos memmove(sigblob + diff, sigblob, len); 24836e94dc5SPeter Avalos explicit_bzero(sigblob, diff); 24918de8d7fSPeter Avalos len = modlen; 25018de8d7fSPeter Avalos } 25136e94dc5SPeter Avalos if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { 25236e94dc5SPeter Avalos ret = SSH_ERR_INTERNAL_ERROR; 25336e94dc5SPeter Avalos goto out; 25418de8d7fSPeter Avalos } 25536e94dc5SPeter Avalos if ((ret = ssh_digest_memory(hash_alg, data, datalen, 25636e94dc5SPeter Avalos digest, sizeof(digest))) != 0) 25736e94dc5SPeter Avalos goto out; 25818de8d7fSPeter Avalos 25936e94dc5SPeter Avalos ret = openssh_RSA_verify(hash_alg, digest, dlen, sigblob, len, 26036e94dc5SPeter Avalos key->rsa); 26136e94dc5SPeter Avalos out: 26236e94dc5SPeter Avalos if (sigblob != NULL) { 26336e94dc5SPeter Avalos explicit_bzero(sigblob, len); 26436e94dc5SPeter Avalos free(sigblob); 26536e94dc5SPeter Avalos } 26636e94dc5SPeter Avalos free(ktype); 26736e94dc5SPeter Avalos sshbuf_free(b); 26836e94dc5SPeter Avalos explicit_bzero(digest, sizeof(digest)); 26918de8d7fSPeter Avalos return ret; 27018de8d7fSPeter Avalos } 27118de8d7fSPeter Avalos 27218de8d7fSPeter Avalos /* 27318de8d7fSPeter Avalos * See: 27418de8d7fSPeter Avalos * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/ 27518de8d7fSPeter Avalos * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn 27618de8d7fSPeter Avalos */ 277e9778795SPeter Avalos 27818de8d7fSPeter Avalos /* 27918de8d7fSPeter Avalos * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) 28018de8d7fSPeter Avalos * oiw(14) secsig(3) algorithms(2) 26 } 28118de8d7fSPeter Avalos */ 28218de8d7fSPeter Avalos static const u_char id_sha1[] = { 28318de8d7fSPeter Avalos 0x30, 0x21, /* type Sequence, length 0x21 (33) */ 28418de8d7fSPeter Avalos 0x30, 0x09, /* type Sequence, length 0x09 */ 28518de8d7fSPeter Avalos 0x06, 0x05, /* type OID, length 0x05 */ 28618de8d7fSPeter Avalos 0x2b, 0x0e, 0x03, 0x02, 0x1a, /* id-sha1 OID */ 28718de8d7fSPeter Avalos 0x05, 0x00, /* NULL */ 28818de8d7fSPeter Avalos 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */ 28918de8d7fSPeter Avalos }; 29018de8d7fSPeter Avalos 291e9778795SPeter Avalos /* 292e9778795SPeter Avalos * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html 293e9778795SPeter Avalos * id-sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) 294e9778795SPeter Avalos * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) 295e9778795SPeter Avalos * id-sha256(1) } 296e9778795SPeter Avalos */ 297e9778795SPeter Avalos static const u_char id_sha256[] = { 298e9778795SPeter Avalos 0x30, 0x31, /* type Sequence, length 0x31 (49) */ 299e9778795SPeter Avalos 0x30, 0x0d, /* type Sequence, length 0x0d (13) */ 300e9778795SPeter Avalos 0x06, 0x09, /* type OID, length 0x09 */ 301e9778795SPeter Avalos 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, /* id-sha256 */ 302e9778795SPeter Avalos 0x05, 0x00, /* NULL */ 303e9778795SPeter Avalos 0x04, 0x20 /* Octet string, length 0x20 (32), followed by sha256 hash */ 304e9778795SPeter Avalos }; 305e9778795SPeter Avalos 306e9778795SPeter Avalos /* 307e9778795SPeter Avalos * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html 308e9778795SPeter Avalos * id-sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) 309e9778795SPeter Avalos * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) 310e9778795SPeter Avalos * id-sha256(3) } 311e9778795SPeter Avalos */ 312e9778795SPeter Avalos static const u_char id_sha512[] = { 313e9778795SPeter Avalos 0x30, 0x51, /* type Sequence, length 0x51 (81) */ 314e9778795SPeter Avalos 0x30, 0x0d, /* type Sequence, length 0x0d (13) */ 315e9778795SPeter Avalos 0x06, 0x09, /* type OID, length 0x09 */ 316e9778795SPeter Avalos 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, /* id-sha512 */ 317e9778795SPeter Avalos 0x05, 0x00, /* NULL */ 318e9778795SPeter Avalos 0x04, 0x40 /* Octet string, length 0x40 (64), followed by sha512 hash */ 319e9778795SPeter Avalos }; 320e9778795SPeter Avalos 321e9778795SPeter Avalos static int 322e9778795SPeter Avalos rsa_hash_alg_oid(int hash_alg, const u_char **oidp, size_t *oidlenp) 323e9778795SPeter Avalos { 324e9778795SPeter Avalos switch (hash_alg) { 325e9778795SPeter Avalos case SSH_DIGEST_SHA1: 326e9778795SPeter Avalos *oidp = id_sha1; 327e9778795SPeter Avalos *oidlenp = sizeof(id_sha1); 328e9778795SPeter Avalos break; 329e9778795SPeter Avalos case SSH_DIGEST_SHA256: 330e9778795SPeter Avalos *oidp = id_sha256; 331e9778795SPeter Avalos *oidlenp = sizeof(id_sha256); 332e9778795SPeter Avalos break; 333e9778795SPeter Avalos case SSH_DIGEST_SHA512: 334e9778795SPeter Avalos *oidp = id_sha512; 335e9778795SPeter Avalos *oidlenp = sizeof(id_sha512); 336e9778795SPeter Avalos break; 337e9778795SPeter Avalos default: 338e9778795SPeter Avalos return SSH_ERR_INVALID_ARGUMENT; 339e9778795SPeter Avalos } 340e9778795SPeter Avalos return 0; 341e9778795SPeter Avalos } 342e9778795SPeter Avalos 34318de8d7fSPeter Avalos static int 34436e94dc5SPeter Avalos openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen, 34536e94dc5SPeter Avalos u_char *sigbuf, size_t siglen, RSA *rsa) 34618de8d7fSPeter Avalos { 347e9778795SPeter Avalos size_t rsasize = 0, oidlen = 0, hlen = 0; 348e9778795SPeter Avalos int ret, len, oidmatch, hashmatch; 34918de8d7fSPeter Avalos const u_char *oid = NULL; 35018de8d7fSPeter Avalos u_char *decrypted = NULL; 35118de8d7fSPeter Avalos 352e9778795SPeter Avalos if ((ret = rsa_hash_alg_oid(hash_alg, &oid, &oidlen)) != 0) 353e9778795SPeter Avalos return ret; 35436e94dc5SPeter Avalos ret = SSH_ERR_INTERNAL_ERROR; 355e9778795SPeter Avalos hlen = ssh_digest_bytes(hash_alg); 35618de8d7fSPeter Avalos if (hashlen != hlen) { 35736e94dc5SPeter Avalos ret = SSH_ERR_INVALID_ARGUMENT; 35818de8d7fSPeter Avalos goto done; 35918de8d7fSPeter Avalos } 36018de8d7fSPeter Avalos rsasize = RSA_size(rsa); 36136e94dc5SPeter Avalos if (rsasize <= 0 || rsasize > SSHBUF_MAX_BIGNUM || 36236e94dc5SPeter Avalos siglen == 0 || siglen > rsasize) { 36336e94dc5SPeter Avalos ret = SSH_ERR_INVALID_ARGUMENT; 36418de8d7fSPeter Avalos goto done; 36518de8d7fSPeter Avalos } 36636e94dc5SPeter Avalos if ((decrypted = malloc(rsasize)) == NULL) { 36736e94dc5SPeter Avalos ret = SSH_ERR_ALLOC_FAIL; 36836e94dc5SPeter Avalos goto done; 36936e94dc5SPeter Avalos } 37018de8d7fSPeter Avalos if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa, 37118de8d7fSPeter Avalos RSA_PKCS1_PADDING)) < 0) { 37236e94dc5SPeter Avalos ret = SSH_ERR_LIBCRYPTO_ERROR; 37318de8d7fSPeter Avalos goto done; 37418de8d7fSPeter Avalos } 37536e94dc5SPeter Avalos if (len < 0 || (size_t)len != hlen + oidlen) { 37636e94dc5SPeter Avalos ret = SSH_ERR_INVALID_FORMAT; 37718de8d7fSPeter Avalos goto done; 37818de8d7fSPeter Avalos } 379856ea928SPeter Avalos oidmatch = timingsafe_bcmp(decrypted, oid, oidlen) == 0; 380856ea928SPeter Avalos hashmatch = timingsafe_bcmp(decrypted + oidlen, hash, hlen) == 0; 38136e94dc5SPeter Avalos if (!oidmatch || !hashmatch) { 38236e94dc5SPeter Avalos ret = SSH_ERR_SIGNATURE_INVALID; 38318de8d7fSPeter Avalos goto done; 38418de8d7fSPeter Avalos } 38536e94dc5SPeter Avalos ret = 0; 38618de8d7fSPeter Avalos done: 38736e94dc5SPeter Avalos if (decrypted) { 38836e94dc5SPeter Avalos explicit_bzero(decrypted, rsasize); 38936e94dc5SPeter Avalos free(decrypted); 39036e94dc5SPeter Avalos } 39118de8d7fSPeter Avalos return ret; 39218de8d7fSPeter Avalos } 393e9778795SPeter Avalos #endif /* WITH_OPENSSL */ 394