xref: /dflybsd-src/crypto/openssh/ssh-rsa.c (revision e9778795382169f8c6fde18d0565a1acef2cac8b)
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