1*e9778795SPeter Avalos /* $OpenBSD: ssh-rsa.c,v 1.59 2016/04/21 06:08:02 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 20*e9778795SPeter Avalos #ifdef WITH_OPENSSL 21*e9778795SPeter 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 39*e9778795SPeter Avalos static const char * 40*e9778795SPeter Avalos rsa_hash_alg_ident(int hash_alg) 41*e9778795SPeter Avalos { 42*e9778795SPeter Avalos switch (hash_alg) { 43*e9778795SPeter Avalos case SSH_DIGEST_SHA1: 44*e9778795SPeter Avalos return "ssh-rsa"; 45*e9778795SPeter Avalos case SSH_DIGEST_SHA256: 46*e9778795SPeter Avalos return "rsa-sha2-256"; 47*e9778795SPeter Avalos case SSH_DIGEST_SHA512: 48*e9778795SPeter Avalos return "rsa-sha2-512"; 49*e9778795SPeter Avalos } 50*e9778795SPeter Avalos return NULL; 51*e9778795SPeter Avalos } 52*e9778795SPeter Avalos 53*e9778795SPeter Avalos static int 54*e9778795SPeter Avalos rsa_hash_alg_from_ident(const char *ident) 55*e9778795SPeter Avalos { 56*e9778795SPeter Avalos if (strcmp(ident, "ssh-rsa") == 0) 57*e9778795SPeter Avalos return SSH_DIGEST_SHA1; 58*e9778795SPeter Avalos if (strcmp(ident, "rsa-sha2-256") == 0) 59*e9778795SPeter Avalos return SSH_DIGEST_SHA256; 60*e9778795SPeter Avalos if (strcmp(ident, "rsa-sha2-512") == 0) 61*e9778795SPeter Avalos return SSH_DIGEST_SHA512; 62*e9778795SPeter Avalos return -1; 63*e9778795SPeter Avalos } 64*e9778795SPeter Avalos 65*e9778795SPeter Avalos static int 66*e9778795SPeter Avalos rsa_hash_alg_nid(int type) 67*e9778795SPeter Avalos { 68*e9778795SPeter Avalos switch (type) { 69*e9778795SPeter Avalos case SSH_DIGEST_SHA1: 70*e9778795SPeter Avalos return NID_sha1; 71*e9778795SPeter Avalos case SSH_DIGEST_SHA256: 72*e9778795SPeter Avalos return NID_sha256; 73*e9778795SPeter Avalos case SSH_DIGEST_SHA512: 74*e9778795SPeter Avalos return NID_sha512; 75*e9778795SPeter Avalos default: 76*e9778795SPeter Avalos return -1; 77*e9778795SPeter Avalos } 78*e9778795SPeter Avalos } 79*e9778795SPeter Avalos 8018de8d7fSPeter Avalos /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ 8118de8d7fSPeter Avalos int 8236e94dc5SPeter Avalos ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, 83*e9778795SPeter Avalos const u_char *data, size_t datalen, const char *alg_ident) 8418de8d7fSPeter Avalos { 8536e94dc5SPeter Avalos u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL; 8636e94dc5SPeter Avalos size_t slen; 8736e94dc5SPeter Avalos u_int dlen, len; 88*e9778795SPeter Avalos int nid, hash_alg, ret = SSH_ERR_INTERNAL_ERROR; 8936e94dc5SPeter Avalos struct sshbuf *b = NULL; 9018de8d7fSPeter Avalos 9136e94dc5SPeter Avalos if (lenp != NULL) 9236e94dc5SPeter Avalos *lenp = 0; 9336e94dc5SPeter Avalos if (sigp != NULL) 9436e94dc5SPeter Avalos *sigp = NULL; 9518de8d7fSPeter Avalos 96*e9778795SPeter Avalos if (alg_ident == NULL || strlen(alg_ident) == 0 || 97*e9778795SPeter Avalos strncmp(alg_ident, "ssh-rsa-cert", strlen("ssh-rsa-cert")) == 0) 98*e9778795SPeter Avalos hash_alg = SSH_DIGEST_SHA1; 99*e9778795SPeter Avalos else 100*e9778795SPeter Avalos hash_alg = rsa_hash_alg_from_ident(alg_ident); 101*e9778795SPeter Avalos if (key == NULL || key->rsa == NULL || hash_alg == -1 || 102*e9778795SPeter Avalos sshkey_type_plain(key->type) != KEY_RSA || 103*e9778795SPeter Avalos BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) 10436e94dc5SPeter Avalos return SSH_ERR_INVALID_ARGUMENT; 10518de8d7fSPeter Avalos slen = RSA_size(key->rsa); 10636e94dc5SPeter Avalos if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM) 10736e94dc5SPeter Avalos return SSH_ERR_INVALID_ARGUMENT; 10818de8d7fSPeter Avalos 10936e94dc5SPeter Avalos /* hash the data */ 110*e9778795SPeter Avalos nid = rsa_hash_alg_nid(hash_alg); 11136e94dc5SPeter Avalos if ((dlen = ssh_digest_bytes(hash_alg)) == 0) 11236e94dc5SPeter Avalos return SSH_ERR_INTERNAL_ERROR; 11336e94dc5SPeter Avalos if ((ret = ssh_digest_memory(hash_alg, data, datalen, 11436e94dc5SPeter Avalos digest, sizeof(digest))) != 0) 11536e94dc5SPeter Avalos goto out; 11618de8d7fSPeter Avalos 11736e94dc5SPeter Avalos if ((sig = malloc(slen)) == NULL) { 11836e94dc5SPeter Avalos ret = SSH_ERR_ALLOC_FAIL; 11936e94dc5SPeter Avalos goto out; 12036e94dc5SPeter Avalos } 12118de8d7fSPeter Avalos 12236e94dc5SPeter Avalos if (RSA_sign(nid, digest, dlen, sig, &len, key->rsa) != 1) { 12336e94dc5SPeter Avalos ret = SSH_ERR_LIBCRYPTO_ERROR; 12436e94dc5SPeter Avalos goto out; 12518de8d7fSPeter Avalos } 12618de8d7fSPeter Avalos if (len < slen) { 12736e94dc5SPeter Avalos size_t diff = slen - len; 12818de8d7fSPeter Avalos memmove(sig + diff, sig, len); 12936e94dc5SPeter Avalos explicit_bzero(sig, diff); 13018de8d7fSPeter Avalos } else if (len > slen) { 13136e94dc5SPeter Avalos ret = SSH_ERR_INTERNAL_ERROR; 13236e94dc5SPeter Avalos goto out; 13318de8d7fSPeter Avalos } 13418de8d7fSPeter Avalos /* encode signature */ 13536e94dc5SPeter Avalos if ((b = sshbuf_new()) == NULL) { 13636e94dc5SPeter Avalos ret = SSH_ERR_ALLOC_FAIL; 13736e94dc5SPeter Avalos goto out; 13836e94dc5SPeter Avalos } 139*e9778795SPeter Avalos if ((ret = sshbuf_put_cstring(b, rsa_hash_alg_ident(hash_alg))) != 0 || 14036e94dc5SPeter Avalos (ret = sshbuf_put_string(b, sig, slen)) != 0) 14136e94dc5SPeter Avalos goto out; 14236e94dc5SPeter Avalos len = sshbuf_len(b); 14336e94dc5SPeter Avalos if (sigp != NULL) { 14436e94dc5SPeter Avalos if ((*sigp = malloc(len)) == NULL) { 14536e94dc5SPeter Avalos ret = SSH_ERR_ALLOC_FAIL; 14636e94dc5SPeter Avalos goto out; 14736e94dc5SPeter Avalos } 14836e94dc5SPeter Avalos memcpy(*sigp, sshbuf_ptr(b), len); 14936e94dc5SPeter Avalos } 15018de8d7fSPeter Avalos if (lenp != NULL) 15118de8d7fSPeter Avalos *lenp = len; 15236e94dc5SPeter Avalos ret = 0; 15336e94dc5SPeter Avalos out: 15436e94dc5SPeter Avalos explicit_bzero(digest, sizeof(digest)); 15536e94dc5SPeter Avalos if (sig != NULL) { 15636e94dc5SPeter Avalos explicit_bzero(sig, slen); 15736e94dc5SPeter Avalos free(sig); 15818de8d7fSPeter Avalos } 15936e94dc5SPeter Avalos sshbuf_free(b); 160*e9778795SPeter Avalos return ret; 16118de8d7fSPeter Avalos } 16218de8d7fSPeter Avalos 16318de8d7fSPeter Avalos int 16436e94dc5SPeter Avalos ssh_rsa_verify(const struct sshkey *key, 165*e9778795SPeter Avalos const u_char *sig, size_t siglen, const u_char *data, size_t datalen) 16618de8d7fSPeter Avalos { 16736e94dc5SPeter Avalos char *ktype = NULL; 16836e94dc5SPeter Avalos int hash_alg, ret = SSH_ERR_INTERNAL_ERROR; 16936e94dc5SPeter Avalos size_t len, diff, modlen, dlen; 17036e94dc5SPeter Avalos struct sshbuf *b = NULL; 17136e94dc5SPeter Avalos u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL; 17218de8d7fSPeter Avalos 17336e94dc5SPeter Avalos if (key == NULL || key->rsa == NULL || 17436e94dc5SPeter Avalos sshkey_type_plain(key->type) != KEY_RSA || 175*e9778795SPeter Avalos BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE || 176*e9778795SPeter Avalos sig == NULL || siglen == 0) 17736e94dc5SPeter Avalos return SSH_ERR_INVALID_ARGUMENT; 17836e94dc5SPeter Avalos 179*e9778795SPeter Avalos if ((b = sshbuf_from(sig, siglen)) == NULL) 18036e94dc5SPeter Avalos return SSH_ERR_ALLOC_FAIL; 18136e94dc5SPeter Avalos if (sshbuf_get_cstring(b, &ktype, NULL) != 0) { 18236e94dc5SPeter Avalos ret = SSH_ERR_INVALID_FORMAT; 18336e94dc5SPeter Avalos goto out; 18418de8d7fSPeter Avalos } 185*e9778795SPeter Avalos if ((hash_alg = rsa_hash_alg_from_ident(ktype)) == -1) { 18636e94dc5SPeter Avalos ret = SSH_ERR_KEY_TYPE_MISMATCH; 18736e94dc5SPeter Avalos goto out; 18818de8d7fSPeter Avalos } 18936e94dc5SPeter Avalos if (sshbuf_get_string(b, &sigblob, &len) != 0) { 19036e94dc5SPeter Avalos ret = SSH_ERR_INVALID_FORMAT; 19136e94dc5SPeter Avalos goto out; 19236e94dc5SPeter Avalos } 19336e94dc5SPeter Avalos if (sshbuf_len(b) != 0) { 19436e94dc5SPeter Avalos ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; 19536e94dc5SPeter Avalos goto out; 19618de8d7fSPeter Avalos } 19718de8d7fSPeter Avalos /* RSA_verify expects a signature of RSA_size */ 19818de8d7fSPeter Avalos modlen = RSA_size(key->rsa); 19918de8d7fSPeter Avalos if (len > modlen) { 20036e94dc5SPeter Avalos ret = SSH_ERR_KEY_BITS_MISMATCH; 20136e94dc5SPeter Avalos goto out; 20218de8d7fSPeter Avalos } else if (len < modlen) { 20336e94dc5SPeter Avalos diff = modlen - len; 20436e94dc5SPeter Avalos osigblob = sigblob; 20536e94dc5SPeter Avalos if ((sigblob = realloc(sigblob, modlen)) == NULL) { 20636e94dc5SPeter Avalos sigblob = osigblob; /* put it back for clear/free */ 20736e94dc5SPeter Avalos ret = SSH_ERR_ALLOC_FAIL; 20836e94dc5SPeter Avalos goto out; 20936e94dc5SPeter Avalos } 21018de8d7fSPeter Avalos memmove(sigblob + diff, sigblob, len); 21136e94dc5SPeter Avalos explicit_bzero(sigblob, diff); 21218de8d7fSPeter Avalos len = modlen; 21318de8d7fSPeter Avalos } 21436e94dc5SPeter Avalos if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { 21536e94dc5SPeter Avalos ret = SSH_ERR_INTERNAL_ERROR; 21636e94dc5SPeter Avalos goto out; 21718de8d7fSPeter Avalos } 21836e94dc5SPeter Avalos if ((ret = ssh_digest_memory(hash_alg, data, datalen, 21936e94dc5SPeter Avalos digest, sizeof(digest))) != 0) 22036e94dc5SPeter Avalos goto out; 22118de8d7fSPeter Avalos 22236e94dc5SPeter Avalos ret = openssh_RSA_verify(hash_alg, digest, dlen, sigblob, len, 22336e94dc5SPeter Avalos key->rsa); 22436e94dc5SPeter Avalos out: 22536e94dc5SPeter Avalos if (sigblob != NULL) { 22636e94dc5SPeter Avalos explicit_bzero(sigblob, len); 22736e94dc5SPeter Avalos free(sigblob); 22836e94dc5SPeter Avalos } 22936e94dc5SPeter Avalos free(ktype); 23036e94dc5SPeter Avalos sshbuf_free(b); 23136e94dc5SPeter Avalos explicit_bzero(digest, sizeof(digest)); 23218de8d7fSPeter Avalos return ret; 23318de8d7fSPeter Avalos } 23418de8d7fSPeter Avalos 23518de8d7fSPeter Avalos /* 23618de8d7fSPeter Avalos * See: 23718de8d7fSPeter Avalos * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/ 23818de8d7fSPeter Avalos * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn 23918de8d7fSPeter Avalos */ 240*e9778795SPeter Avalos 24118de8d7fSPeter Avalos /* 24218de8d7fSPeter Avalos * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) 24318de8d7fSPeter Avalos * oiw(14) secsig(3) algorithms(2) 26 } 24418de8d7fSPeter Avalos */ 24518de8d7fSPeter Avalos static const u_char id_sha1[] = { 24618de8d7fSPeter Avalos 0x30, 0x21, /* type Sequence, length 0x21 (33) */ 24718de8d7fSPeter Avalos 0x30, 0x09, /* type Sequence, length 0x09 */ 24818de8d7fSPeter Avalos 0x06, 0x05, /* type OID, length 0x05 */ 24918de8d7fSPeter Avalos 0x2b, 0x0e, 0x03, 0x02, 0x1a, /* id-sha1 OID */ 25018de8d7fSPeter Avalos 0x05, 0x00, /* NULL */ 25118de8d7fSPeter Avalos 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */ 25218de8d7fSPeter Avalos }; 25318de8d7fSPeter Avalos 254*e9778795SPeter Avalos /* 255*e9778795SPeter Avalos * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html 256*e9778795SPeter Avalos * id-sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) 257*e9778795SPeter Avalos * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) 258*e9778795SPeter Avalos * id-sha256(1) } 259*e9778795SPeter Avalos */ 260*e9778795SPeter Avalos static const u_char id_sha256[] = { 261*e9778795SPeter Avalos 0x30, 0x31, /* type Sequence, length 0x31 (49) */ 262*e9778795SPeter Avalos 0x30, 0x0d, /* type Sequence, length 0x0d (13) */ 263*e9778795SPeter Avalos 0x06, 0x09, /* type OID, length 0x09 */ 264*e9778795SPeter Avalos 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, /* id-sha256 */ 265*e9778795SPeter Avalos 0x05, 0x00, /* NULL */ 266*e9778795SPeter Avalos 0x04, 0x20 /* Octet string, length 0x20 (32), followed by sha256 hash */ 267*e9778795SPeter Avalos }; 268*e9778795SPeter Avalos 269*e9778795SPeter Avalos /* 270*e9778795SPeter Avalos * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html 271*e9778795SPeter Avalos * id-sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) 272*e9778795SPeter Avalos * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) 273*e9778795SPeter Avalos * id-sha256(3) } 274*e9778795SPeter Avalos */ 275*e9778795SPeter Avalos static const u_char id_sha512[] = { 276*e9778795SPeter Avalos 0x30, 0x51, /* type Sequence, length 0x51 (81) */ 277*e9778795SPeter Avalos 0x30, 0x0d, /* type Sequence, length 0x0d (13) */ 278*e9778795SPeter Avalos 0x06, 0x09, /* type OID, length 0x09 */ 279*e9778795SPeter Avalos 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, /* id-sha512 */ 280*e9778795SPeter Avalos 0x05, 0x00, /* NULL */ 281*e9778795SPeter Avalos 0x04, 0x40 /* Octet string, length 0x40 (64), followed by sha512 hash */ 282*e9778795SPeter Avalos }; 283*e9778795SPeter Avalos 284*e9778795SPeter Avalos static int 285*e9778795SPeter Avalos rsa_hash_alg_oid(int hash_alg, const u_char **oidp, size_t *oidlenp) 286*e9778795SPeter Avalos { 287*e9778795SPeter Avalos switch (hash_alg) { 288*e9778795SPeter Avalos case SSH_DIGEST_SHA1: 289*e9778795SPeter Avalos *oidp = id_sha1; 290*e9778795SPeter Avalos *oidlenp = sizeof(id_sha1); 291*e9778795SPeter Avalos break; 292*e9778795SPeter Avalos case SSH_DIGEST_SHA256: 293*e9778795SPeter Avalos *oidp = id_sha256; 294*e9778795SPeter Avalos *oidlenp = sizeof(id_sha256); 295*e9778795SPeter Avalos break; 296*e9778795SPeter Avalos case SSH_DIGEST_SHA512: 297*e9778795SPeter Avalos *oidp = id_sha512; 298*e9778795SPeter Avalos *oidlenp = sizeof(id_sha512); 299*e9778795SPeter Avalos break; 300*e9778795SPeter Avalos default: 301*e9778795SPeter Avalos return SSH_ERR_INVALID_ARGUMENT; 302*e9778795SPeter Avalos } 303*e9778795SPeter Avalos return 0; 304*e9778795SPeter Avalos } 305*e9778795SPeter Avalos 30618de8d7fSPeter Avalos static int 30736e94dc5SPeter Avalos openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen, 30836e94dc5SPeter Avalos u_char *sigbuf, size_t siglen, RSA *rsa) 30918de8d7fSPeter Avalos { 310*e9778795SPeter Avalos size_t rsasize = 0, oidlen = 0, hlen = 0; 311*e9778795SPeter Avalos int ret, len, oidmatch, hashmatch; 31218de8d7fSPeter Avalos const u_char *oid = NULL; 31318de8d7fSPeter Avalos u_char *decrypted = NULL; 31418de8d7fSPeter Avalos 315*e9778795SPeter Avalos if ((ret = rsa_hash_alg_oid(hash_alg, &oid, &oidlen)) != 0) 316*e9778795SPeter Avalos return ret; 31736e94dc5SPeter Avalos ret = SSH_ERR_INTERNAL_ERROR; 318*e9778795SPeter Avalos hlen = ssh_digest_bytes(hash_alg); 31918de8d7fSPeter Avalos if (hashlen != hlen) { 32036e94dc5SPeter Avalos ret = SSH_ERR_INVALID_ARGUMENT; 32118de8d7fSPeter Avalos goto done; 32218de8d7fSPeter Avalos } 32318de8d7fSPeter Avalos rsasize = RSA_size(rsa); 32436e94dc5SPeter Avalos if (rsasize <= 0 || rsasize > SSHBUF_MAX_BIGNUM || 32536e94dc5SPeter Avalos siglen == 0 || siglen > rsasize) { 32636e94dc5SPeter Avalos ret = SSH_ERR_INVALID_ARGUMENT; 32718de8d7fSPeter Avalos goto done; 32818de8d7fSPeter Avalos } 32936e94dc5SPeter Avalos if ((decrypted = malloc(rsasize)) == NULL) { 33036e94dc5SPeter Avalos ret = SSH_ERR_ALLOC_FAIL; 33136e94dc5SPeter Avalos goto done; 33236e94dc5SPeter Avalos } 33318de8d7fSPeter Avalos if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa, 33418de8d7fSPeter Avalos RSA_PKCS1_PADDING)) < 0) { 33536e94dc5SPeter Avalos ret = SSH_ERR_LIBCRYPTO_ERROR; 33618de8d7fSPeter Avalos goto done; 33718de8d7fSPeter Avalos } 33836e94dc5SPeter Avalos if (len < 0 || (size_t)len != hlen + oidlen) { 33936e94dc5SPeter Avalos ret = SSH_ERR_INVALID_FORMAT; 34018de8d7fSPeter Avalos goto done; 34118de8d7fSPeter Avalos } 342856ea928SPeter Avalos oidmatch = timingsafe_bcmp(decrypted, oid, oidlen) == 0; 343856ea928SPeter Avalos hashmatch = timingsafe_bcmp(decrypted + oidlen, hash, hlen) == 0; 34436e94dc5SPeter Avalos if (!oidmatch || !hashmatch) { 34536e94dc5SPeter Avalos ret = SSH_ERR_SIGNATURE_INVALID; 34618de8d7fSPeter Avalos goto done; 34718de8d7fSPeter Avalos } 34836e94dc5SPeter Avalos ret = 0; 34918de8d7fSPeter Avalos done: 35036e94dc5SPeter Avalos if (decrypted) { 35136e94dc5SPeter Avalos explicit_bzero(decrypted, rsasize); 35236e94dc5SPeter Avalos free(decrypted); 35336e94dc5SPeter Avalos } 35418de8d7fSPeter Avalos return ret; 35518de8d7fSPeter Avalos } 356*e9778795SPeter Avalos #endif /* WITH_OPENSSL */ 357