xref: /freebsd/crypto/openssh/ssh-rsa.c (revision 3d9fd9fcb432750f3716b28f6ccb0104cd9d351a)
1 /* $OpenBSD: ssh-rsa.c,v 1.80 2024/08/15 00:51:51 djm Exp $ */
2 /*
3  * Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include "includes.h"
19 
20 #ifdef WITH_OPENSSL
21 
22 #include <sys/types.h>
23 
24 #include <openssl/evp.h>
25 #include <openssl/err.h>
26 
27 #include <stdarg.h>
28 #include <string.h>
29 
30 #include "sshbuf.h"
31 #include "ssherr.h"
32 #define SSHKEY_INTERNAL
33 #include "sshkey.h"
34 #include "digest.h"
35 #include "log.h"
36 
37 #include "openbsd-compat/openssl-compat.h"
38 
39 static u_int
ssh_rsa_size(const struct sshkey * k)40 ssh_rsa_size(const struct sshkey *k)
41 {
42 	if (k->pkey == NULL)
43 		return 0;
44 	return EVP_PKEY_bits(k->pkey);
45 }
46 
47 static int
ssh_rsa_alloc(struct sshkey * k)48 ssh_rsa_alloc(struct sshkey *k)
49 {
50 	if ((k->pkey = EVP_PKEY_new()) == NULL)
51 		return SSH_ERR_ALLOC_FAIL;
52 	return 0;
53 }
54 
55 static void
ssh_rsa_cleanup(struct sshkey * k)56 ssh_rsa_cleanup(struct sshkey *k)
57 {
58 	EVP_PKEY_free(k->pkey);
59 	k->pkey = NULL;
60 }
61 
62 static int
ssh_rsa_equal(const struct sshkey * a,const struct sshkey * b)63 ssh_rsa_equal(const struct sshkey *a, const struct sshkey *b)
64 {
65 	if (a->pkey == NULL || b->pkey == NULL)
66 		return 0;
67 	return EVP_PKEY_cmp(a->pkey, b->pkey) == 1;
68 }
69 
70 static int
ssh_rsa_serialize_public(const struct sshkey * key,struct sshbuf * b,enum sshkey_serialize_rep opts)71 ssh_rsa_serialize_public(const struct sshkey *key, struct sshbuf *b,
72     enum sshkey_serialize_rep opts)
73 {
74 	int r;
75 	const BIGNUM *rsa_n, *rsa_e;
76 	const RSA *rsa;
77 
78 	if (key->pkey == NULL)
79 		return SSH_ERR_INVALID_ARGUMENT;
80 	if ((rsa = EVP_PKEY_get0_RSA(key->pkey)) == NULL)
81 		return SSH_ERR_LIBCRYPTO_ERROR;
82 
83 	RSA_get0_key(rsa, &rsa_n, &rsa_e, NULL);
84 	if ((r = sshbuf_put_bignum2(b, rsa_e)) != 0 ||
85 	    (r = sshbuf_put_bignum2(b, rsa_n)) != 0)
86 		return r;
87 
88 	return 0;
89 }
90 
91 static int
ssh_rsa_serialize_private(const struct sshkey * key,struct sshbuf * b,enum sshkey_serialize_rep opts)92 ssh_rsa_serialize_private(const struct sshkey *key, struct sshbuf *b,
93     enum sshkey_serialize_rep opts)
94 {
95 	int r;
96 	const BIGNUM *rsa_n, *rsa_e, *rsa_d, *rsa_iqmp, *rsa_p, *rsa_q;
97 	const RSA *rsa;
98 
99 	if ((rsa = EVP_PKEY_get0_RSA(key->pkey)) == NULL)
100 		return SSH_ERR_LIBCRYPTO_ERROR;
101 	RSA_get0_key(rsa, &rsa_n, &rsa_e, &rsa_d);
102 	RSA_get0_factors(rsa, &rsa_p, &rsa_q);
103 	RSA_get0_crt_params(rsa, NULL, NULL, &rsa_iqmp);
104 
105 	if (!sshkey_is_cert(key)) {
106 		/* Note: can't reuse ssh_rsa_serialize_public: e, n vs. n, e */
107 		if ((r = sshbuf_put_bignum2(b, rsa_n)) != 0 ||
108 		    (r = sshbuf_put_bignum2(b, rsa_e)) != 0)
109 			return r;
110 	}
111 	if ((r = sshbuf_put_bignum2(b, rsa_d)) != 0 ||
112 	    (r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 ||
113 	    (r = sshbuf_put_bignum2(b, rsa_p)) != 0 ||
114 	    (r = sshbuf_put_bignum2(b, rsa_q)) != 0)
115 		return r;
116 
117 	return 0;
118 }
119 
120 static int
ssh_rsa_generate(struct sshkey * k,int bits)121 ssh_rsa_generate(struct sshkey *k, int bits)
122 {
123 	EVP_PKEY_CTX *ctx = NULL;
124 	EVP_PKEY *res = NULL;
125 
126 	int ret = SSH_ERR_INTERNAL_ERROR;
127 
128 	if (bits < SSH_RSA_MINIMUM_MODULUS_SIZE ||
129 	    bits > SSHBUF_MAX_BIGNUM * 8)
130 		return SSH_ERR_KEY_LENGTH;
131 
132 	if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)) == NULL) {
133 		ret = SSH_ERR_ALLOC_FAIL;
134 		goto out;
135 	}
136 	if (EVP_PKEY_keygen_init(ctx) <= 0) {
137 		ret = SSH_ERR_LIBCRYPTO_ERROR;
138 		goto out;
139 	}
140 	if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) <= 0) {
141 		ret = SSH_ERR_KEY_LENGTH;
142 		goto out;
143 	}
144 	if (EVP_PKEY_keygen(ctx, &res) <= 0 || res == NULL) {
145 		ret = SSH_ERR_LIBCRYPTO_ERROR;
146 		goto out;
147 	}
148 	/* success */
149 	k->pkey = res;
150 	ret = 0;
151  out:
152 	EVP_PKEY_CTX_free(ctx);
153 	return ret;
154 }
155 
156 static int
ssh_rsa_copy_public(const struct sshkey * from,struct sshkey * to)157 ssh_rsa_copy_public(const struct sshkey *from, struct sshkey *to)
158 {
159 	const BIGNUM *rsa_n, *rsa_e;
160 	BIGNUM *rsa_n_dup = NULL, *rsa_e_dup = NULL;
161 	int r = SSH_ERR_INTERNAL_ERROR;
162 	const RSA *rsa_from;
163 	RSA *rsa_to = NULL;
164 
165 	if ((rsa_from = EVP_PKEY_get0_RSA(from->pkey)) == NULL ||
166 	    (rsa_to = RSA_new()) == NULL)
167 		return SSH_ERR_LIBCRYPTO_ERROR;
168 
169 	RSA_get0_key(rsa_from, &rsa_n, &rsa_e, NULL);
170 	if ((rsa_n_dup = BN_dup(rsa_n)) == NULL ||
171 	    (rsa_e_dup = BN_dup(rsa_e)) == NULL) {
172 		r = SSH_ERR_ALLOC_FAIL;
173 		goto out;
174 	}
175 	if (!RSA_set0_key(rsa_to, rsa_n_dup, rsa_e_dup, NULL)) {
176 		r = SSH_ERR_LIBCRYPTO_ERROR;
177 		goto out;
178 	}
179 	rsa_n_dup = rsa_e_dup = NULL; /* transferred */
180 
181 	if (EVP_PKEY_set1_RSA(to->pkey, rsa_to) != 1) {
182 		r = SSH_ERR_LIBCRYPTO_ERROR;
183 		goto out;
184 	}
185 	/* success */
186 	r = 0;
187  out:
188 	RSA_free(rsa_to);
189 	BN_clear_free(rsa_n_dup);
190 	BN_clear_free(rsa_e_dup);
191 	return r;
192 }
193 
194 static int
ssh_rsa_deserialize_public(const char * ktype,struct sshbuf * b,struct sshkey * key)195 ssh_rsa_deserialize_public(const char *ktype, struct sshbuf *b,
196     struct sshkey *key)
197 {
198 	int ret = SSH_ERR_INTERNAL_ERROR;
199 	BIGNUM *rsa_n = NULL, *rsa_e = NULL;
200 	RSA *rsa = NULL;
201 
202 	if ((rsa = RSA_new()) == NULL)
203 		return SSH_ERR_LIBCRYPTO_ERROR;
204 
205 	if (sshbuf_get_bignum2(b, &rsa_e) != 0 ||
206 	    sshbuf_get_bignum2(b, &rsa_n) != 0) {
207 		ret = SSH_ERR_INVALID_FORMAT;
208 		goto out;
209 	}
210 	if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL)) {
211 		ret = SSH_ERR_LIBCRYPTO_ERROR;
212 		goto out;
213 	}
214 	rsa_n = rsa_e = NULL; /* transferred */
215 	if (EVP_PKEY_set1_RSA(key->pkey, rsa) != 1) {
216 		ret = SSH_ERR_LIBCRYPTO_ERROR;
217 		goto out;
218 	}
219 	if ((ret = sshkey_check_rsa_length(key, 0)) != 0)
220 		goto out;
221 #ifdef DEBUG_PK
222 	RSA_print_fp(stderr, rsa, 8);
223 #endif
224 	/* success */
225 	ret = 0;
226  out:
227 	RSA_free(rsa);
228 	BN_clear_free(rsa_n);
229 	BN_clear_free(rsa_e);
230 	return ret;
231 }
232 
233 static int
ssh_rsa_deserialize_private(const char * ktype,struct sshbuf * b,struct sshkey * key)234 ssh_rsa_deserialize_private(const char *ktype, struct sshbuf *b,
235     struct sshkey *key)
236 {
237 	int r;
238 	BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL;
239 	BIGNUM *rsa_iqmp = NULL, *rsa_p = NULL, *rsa_q = NULL;
240 	BIGNUM *rsa_dmp1 = NULL, *rsa_dmq1 = NULL;
241 	RSA *rsa = NULL;
242 
243 	if (sshkey_is_cert(key)) {
244 		/* sshkey_private_deserialize already has pubkey from cert */
245 		if ((rsa = EVP_PKEY_get1_RSA(key->pkey)) == NULL) {
246 			r = SSH_ERR_LIBCRYPTO_ERROR;
247 			goto out;
248 		}
249 	} else {
250 		if ((rsa = RSA_new()) == NULL) {
251 			r = SSH_ERR_LIBCRYPTO_ERROR;
252 			goto out;
253 		}
254 		/* Note: can't reuse ssh_rsa_deserialize_public: e,n vs. n,e */
255 		if ((r = sshbuf_get_bignum2(b, &rsa_n)) != 0 ||
256 		    (r = sshbuf_get_bignum2(b, &rsa_e)) != 0)
257 			goto out;
258 		if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL)) {
259 			r = SSH_ERR_LIBCRYPTO_ERROR;
260 			goto out;
261 		}
262 		rsa_n = rsa_e = NULL; /* transferred */
263 	}
264 	if ((r = sshbuf_get_bignum2(b, &rsa_d)) != 0 ||
265 	    (r = sshbuf_get_bignum2(b, &rsa_iqmp)) != 0 ||
266 	    (r = sshbuf_get_bignum2(b, &rsa_p)) != 0 ||
267 	    (r = sshbuf_get_bignum2(b, &rsa_q)) != 0)
268 		goto out;
269 	if ((r = ssh_rsa_complete_crt_parameters(rsa_d, rsa_p, rsa_q,
270 	    rsa_iqmp, &rsa_dmp1, &rsa_dmq1)) != 0)
271 		goto out;
272 	if (!RSA_set0_key(rsa, NULL, NULL, rsa_d)) {
273 		r = SSH_ERR_LIBCRYPTO_ERROR;
274 		goto out;
275 	}
276 	rsa_d = NULL; /* transferred */
277 	if (!RSA_set0_factors(rsa, rsa_p, rsa_q)) {
278 		r = SSH_ERR_LIBCRYPTO_ERROR;
279 		goto out;
280 	}
281 	rsa_p = rsa_q = NULL; /* transferred */
282 	if (!RSA_set0_crt_params(rsa, rsa_dmp1, rsa_dmq1, rsa_iqmp)) {
283 		r = SSH_ERR_LIBCRYPTO_ERROR;
284 		goto out;
285 	}
286 	rsa_dmp1 = rsa_dmq1 = rsa_iqmp = NULL;
287 	if (RSA_blinding_on(rsa, NULL) != 1) {
288 		r = SSH_ERR_LIBCRYPTO_ERROR;
289 		goto out;
290 	}
291 	if (EVP_PKEY_set1_RSA(key->pkey, rsa) != 1) {
292 		r = SSH_ERR_LIBCRYPTO_ERROR;
293 		goto out;
294 	}
295 	if ((r = sshkey_check_rsa_length(key, 0)) != 0)
296 		goto out;
297 	/* success */
298 	r = 0;
299  out:
300 	RSA_free(rsa);
301 	BN_clear_free(rsa_n);
302 	BN_clear_free(rsa_e);
303 	BN_clear_free(rsa_d);
304 	BN_clear_free(rsa_p);
305 	BN_clear_free(rsa_q);
306 	BN_clear_free(rsa_iqmp);
307 	BN_clear_free(rsa_dmp1);
308 	BN_clear_free(rsa_dmq1);
309 	return r;
310 }
311 
312 static const char *
rsa_hash_alg_ident(int hash_alg)313 rsa_hash_alg_ident(int hash_alg)
314 {
315 	switch (hash_alg) {
316 	case SSH_DIGEST_SHA1:
317 		return "ssh-rsa";
318 	case SSH_DIGEST_SHA256:
319 		return "rsa-sha2-256";
320 	case SSH_DIGEST_SHA512:
321 		return "rsa-sha2-512";
322 	}
323 	return NULL;
324 }
325 
326 /*
327  * Returns the hash algorithm ID for a given algorithm identifier as used
328  * inside the signature blob,
329  */
330 static int
rsa_hash_id_from_ident(const char * ident)331 rsa_hash_id_from_ident(const char *ident)
332 {
333 	if (strcmp(ident, "ssh-rsa") == 0)
334 		return SSH_DIGEST_SHA1;
335 	if (strcmp(ident, "rsa-sha2-256") == 0)
336 		return SSH_DIGEST_SHA256;
337 	if (strcmp(ident, "rsa-sha2-512") == 0)
338 		return SSH_DIGEST_SHA512;
339 	return -1;
340 }
341 
342 /*
343  * Return the hash algorithm ID for the specified key name. This includes
344  * all the cases of rsa_hash_id_from_ident() but also the certificate key
345  * types.
346  */
347 static int
rsa_hash_id_from_keyname(const char * alg)348 rsa_hash_id_from_keyname(const char *alg)
349 {
350 	int r;
351 
352 	if ((r = rsa_hash_id_from_ident(alg)) != -1)
353 		return r;
354 	if (strcmp(alg, "ssh-rsa-cert-v01@openssh.com") == 0)
355 		return SSH_DIGEST_SHA1;
356 	if (strcmp(alg, "rsa-sha2-256-cert-v01@openssh.com") == 0)
357 		return SSH_DIGEST_SHA256;
358 	if (strcmp(alg, "rsa-sha2-512-cert-v01@openssh.com") == 0)
359 		return SSH_DIGEST_SHA512;
360 	return -1;
361 }
362 
363 int
ssh_rsa_complete_crt_parameters(const BIGNUM * rsa_d,const BIGNUM * rsa_p,const BIGNUM * rsa_q,const BIGNUM * rsa_iqmp,BIGNUM ** rsa_dmp1,BIGNUM ** rsa_dmq1)364 ssh_rsa_complete_crt_parameters(const BIGNUM *rsa_d, const BIGNUM *rsa_p,
365     const BIGNUM *rsa_q, const BIGNUM *rsa_iqmp, BIGNUM **rsa_dmp1,
366     BIGNUM **rsa_dmq1)
367 {
368 	BIGNUM *aux = NULL, *d_consttime = NULL;
369 	BN_CTX *ctx = NULL;
370 	int r;
371 
372 	*rsa_dmq1 = *rsa_dmp1 = NULL;
373 	if ((ctx = BN_CTX_new()) == NULL)
374 		return SSH_ERR_ALLOC_FAIL;
375 	if ((aux = BN_new()) == NULL ||
376 	    (*rsa_dmq1 = BN_new()) == NULL ||
377 	    (*rsa_dmp1 = BN_new()) == NULL)
378 		return SSH_ERR_ALLOC_FAIL;
379 	if ((d_consttime = BN_dup(rsa_d)) == NULL) {
380 		r = SSH_ERR_ALLOC_FAIL;
381 		goto out;
382 	}
383 	BN_set_flags(aux, BN_FLG_CONSTTIME);
384 	BN_set_flags(d_consttime, BN_FLG_CONSTTIME);
385 
386 	if ((BN_sub(aux, rsa_q, BN_value_one()) == 0) ||
387 	    (BN_mod(*rsa_dmq1, d_consttime, aux, ctx) == 0) ||
388 	    (BN_sub(aux, rsa_p, BN_value_one()) == 0) ||
389 	    (BN_mod(*rsa_dmp1, d_consttime, aux, ctx) == 0)) {
390 		r = SSH_ERR_LIBCRYPTO_ERROR;
391 		goto out;
392 	}
393 	/* success */
394 	r = 0;
395  out:
396 	BN_clear_free(aux);
397 	BN_clear_free(d_consttime);
398 	BN_CTX_free(ctx);
399 	return r;
400 }
401 
402 /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */
403 static int
ssh_rsa_sign(struct sshkey * key,u_char ** sigp,size_t * lenp,const u_char * data,size_t datalen,const char * alg,const char * sk_provider,const char * sk_pin,u_int compat)404 ssh_rsa_sign(struct sshkey *key,
405     u_char **sigp, size_t *lenp,
406     const u_char *data, size_t datalen,
407     const char *alg, const char *sk_provider, const char *sk_pin, u_int compat)
408 {
409 	u_char *sig = NULL;
410 	size_t diff, len = 0;
411 	int slen = 0;
412 	int hash_alg, ret = SSH_ERR_INTERNAL_ERROR;
413 	struct sshbuf *b = NULL;
414 
415 	if (lenp != NULL)
416 		*lenp = 0;
417 	if (sigp != NULL)
418 		*sigp = NULL;
419 
420 	if (alg == NULL || strlen(alg) == 0)
421 		hash_alg = SSH_DIGEST_SHA1;
422 	else
423 		hash_alg = rsa_hash_id_from_keyname(alg);
424 
425 	if (key == NULL || key->pkey == NULL || hash_alg == -1 ||
426 	    sshkey_type_plain(key->type) != KEY_RSA)
427 		return SSH_ERR_INVALID_ARGUMENT;
428 	slen = EVP_PKEY_size(key->pkey);
429 	if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM)
430 		return SSH_ERR_INVALID_ARGUMENT;
431 	if (EVP_PKEY_bits(key->pkey) < SSH_RSA_MINIMUM_MODULUS_SIZE)
432 		return SSH_ERR_KEY_LENGTH;
433 
434 	if ((ret = sshkey_pkey_digest_sign(key->pkey, hash_alg, &sig, &len,
435 	    data, datalen)) < 0)
436 		goto out;
437 	if (len < (size_t)slen) {
438 		diff = slen - len;
439 		memmove(sig + diff, sig, len);
440 		explicit_bzero(sig, diff);
441 	} else if (len > (size_t)slen) {
442 		ret = SSH_ERR_INTERNAL_ERROR;
443 		goto out;
444 	}
445 
446 	/* encode signature */
447 	if ((b = sshbuf_new()) == NULL) {
448 		ret = SSH_ERR_ALLOC_FAIL;
449 		goto out;
450 	}
451 	if ((ret = sshbuf_put_cstring(b, rsa_hash_alg_ident(hash_alg))) != 0 ||
452 	    (ret = sshbuf_put_string(b, sig, slen)) != 0)
453 		goto out;
454 	len = sshbuf_len(b);
455 	if (sigp != NULL) {
456 		if ((*sigp = malloc(len)) == NULL) {
457 			ret = SSH_ERR_ALLOC_FAIL;
458 			goto out;
459 		}
460 		memcpy(*sigp, sshbuf_ptr(b), len);
461 	}
462 	if (lenp != NULL)
463 		*lenp = len;
464 	ret = 0;
465  out:
466 	freezero(sig, slen);
467 	sshbuf_free(b);
468 	return ret;
469 }
470 
471 static int
ssh_rsa_verify(const struct sshkey * key,const u_char * sig,size_t siglen,const u_char * data,size_t dlen,const char * alg,u_int compat,struct sshkey_sig_details ** detailsp)472 ssh_rsa_verify(const struct sshkey *key,
473     const u_char *sig, size_t siglen,
474     const u_char *data, size_t dlen, const char *alg, u_int compat,
475     struct sshkey_sig_details **detailsp)
476 {
477 	char *sigtype = NULL;
478 	int hash_alg, want_alg, ret = SSH_ERR_INTERNAL_ERROR;
479 	size_t len = 0, diff, modlen, rsasize;
480 	struct sshbuf *b = NULL;
481 	u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL;
482 
483 	if (key == NULL || key->pkey == NULL ||
484 	    sshkey_type_plain(key->type) != KEY_RSA ||
485 	    sig == NULL || siglen == 0)
486 		return SSH_ERR_INVALID_ARGUMENT;
487 	if (EVP_PKEY_bits(key->pkey) < SSH_RSA_MINIMUM_MODULUS_SIZE)
488 		return SSH_ERR_KEY_LENGTH;
489 
490 	if ((b = sshbuf_from(sig, siglen)) == NULL)
491 		return SSH_ERR_ALLOC_FAIL;
492 	if (sshbuf_get_cstring(b, &sigtype, NULL) != 0) {
493 		ret = SSH_ERR_INVALID_FORMAT;
494 		goto out;
495 	}
496 	if ((hash_alg = rsa_hash_id_from_ident(sigtype)) == -1) {
497 		ret = SSH_ERR_KEY_TYPE_MISMATCH;
498 		goto out;
499 	}
500 	/*
501 	 * Allow ssh-rsa-cert-v01 certs to generate SHA2 signatures for
502 	 * legacy reasons, but otherwise the signature type should match.
503 	 */
504 	if (alg != NULL && strcmp(alg, "ssh-rsa-cert-v01@openssh.com") != 0) {
505 		if ((want_alg = rsa_hash_id_from_keyname(alg)) == -1) {
506 			ret = SSH_ERR_INVALID_ARGUMENT;
507 			goto out;
508 		}
509 		if (hash_alg != want_alg) {
510 			ret = SSH_ERR_SIGNATURE_INVALID;
511 			goto out;
512 		}
513 	}
514 	if (sshbuf_get_string(b, &sigblob, &len) != 0) {
515 		ret = SSH_ERR_INVALID_FORMAT;
516 		goto out;
517 	}
518 	if (sshbuf_len(b) != 0) {
519 		ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
520 		goto out;
521 	}
522 	/* RSA_verify expects a signature of RSA_size */
523 	modlen = EVP_PKEY_size(key->pkey);
524 	if (len > modlen) {
525 		ret = SSH_ERR_KEY_BITS_MISMATCH;
526 		goto out;
527 	} else if (len < modlen) {
528 		diff = modlen - len;
529 		osigblob = sigblob;
530 		if ((sigblob = realloc(sigblob, modlen)) == NULL) {
531 			sigblob = osigblob; /* put it back for clear/free */
532 			ret = SSH_ERR_ALLOC_FAIL;
533 			goto out;
534 		}
535 		memmove(sigblob + diff, sigblob, len);
536 		explicit_bzero(sigblob, diff);
537 		len = modlen;
538 	}
539 
540 	rsasize = EVP_PKEY_size(key->pkey);
541 	if (rsasize <= 0 || rsasize > SSHBUF_MAX_BIGNUM ||
542 	    len == 0 || len > rsasize) {
543 		ret = SSH_ERR_INVALID_ARGUMENT;
544 		goto out;
545 	}
546 	ret = sshkey_pkey_digest_verify(key->pkey, hash_alg, data, dlen,
547 	    sigblob, len);
548 
549  out:
550 	freezero(sigblob, len);
551 	free(sigtype);
552 	sshbuf_free(b);
553 	explicit_bzero(digest, sizeof(digest));
554 	return ret;
555 }
556 
557 static const struct sshkey_impl_funcs sshkey_rsa_funcs = {
558 	/* .size = */		ssh_rsa_size,
559 	/* .alloc = */		ssh_rsa_alloc,
560 	/* .cleanup = */	ssh_rsa_cleanup,
561 	/* .equal = */		ssh_rsa_equal,
562 	/* .ssh_serialize_public = */ ssh_rsa_serialize_public,
563 	/* .ssh_deserialize_public = */ ssh_rsa_deserialize_public,
564 	/* .ssh_serialize_private = */ ssh_rsa_serialize_private,
565 	/* .ssh_deserialize_private = */ ssh_rsa_deserialize_private,
566 	/* .generate = */	ssh_rsa_generate,
567 	/* .copy_public = */	ssh_rsa_copy_public,
568 	/* .sign = */		ssh_rsa_sign,
569 	/* .verify = */		ssh_rsa_verify,
570 };
571 
572 const struct sshkey_impl sshkey_rsa_impl = {
573 	/* .name = */		"ssh-rsa",
574 	/* .shortname = */	"RSA",
575 	/* .sigalg = */		NULL,
576 	/* .type = */		KEY_RSA,
577 	/* .nid = */		0,
578 	/* .cert = */		0,
579 	/* .sigonly = */	0,
580 	/* .keybits = */	0,
581 	/* .funcs = */		&sshkey_rsa_funcs,
582 };
583 
584 const struct sshkey_impl sshkey_rsa_cert_impl = {
585 	/* .name = */		"ssh-rsa-cert-v01@openssh.com",
586 	/* .shortname = */	"RSA-CERT",
587 	/* .sigalg = */		NULL,
588 	/* .type = */		KEY_RSA_CERT,
589 	/* .nid = */		0,
590 	/* .cert = */		1,
591 	/* .sigonly = */	0,
592 	/* .keybits = */	0,
593 	/* .funcs = */		&sshkey_rsa_funcs,
594 };
595 
596 /* SHA2 signature algorithms */
597 
598 const struct sshkey_impl sshkey_rsa_sha256_impl = {
599 	/* .name = */		"rsa-sha2-256",
600 	/* .shortname = */	"RSA",
601 	/* .sigalg = */		NULL,
602 	/* .type = */		KEY_RSA,
603 	/* .nid = */		0,
604 	/* .cert = */		0,
605 	/* .sigonly = */	1,
606 	/* .keybits = */	0,
607 	/* .funcs = */		&sshkey_rsa_funcs,
608 };
609 
610 const struct sshkey_impl sshkey_rsa_sha512_impl = {
611 	/* .name = */		"rsa-sha2-512",
612 	/* .shortname = */	"RSA",
613 	/* .sigalg = */		NULL,
614 	/* .type = */		KEY_RSA,
615 	/* .nid = */		0,
616 	/* .cert = */		0,
617 	/* .sigonly = */	1,
618 	/* .keybits = */	0,
619 	/* .funcs = */		&sshkey_rsa_funcs,
620 };
621 
622 const struct sshkey_impl sshkey_rsa_sha256_cert_impl = {
623 	/* .name = */		"rsa-sha2-256-cert-v01@openssh.com",
624 	/* .shortname = */	"RSA-CERT",
625 	/* .sigalg = */		"rsa-sha2-256",
626 	/* .type = */		KEY_RSA_CERT,
627 	/* .nid = */		0,
628 	/* .cert = */		1,
629 	/* .sigonly = */	1,
630 	/* .keybits = */	0,
631 	/* .funcs = */		&sshkey_rsa_funcs,
632 };
633 
634 const struct sshkey_impl sshkey_rsa_sha512_cert_impl = {
635 	/* .name = */		"rsa-sha2-512-cert-v01@openssh.com",
636 	/* .shortname = */	"RSA-CERT",
637 	/* .sigalg = */		"rsa-sha2-512",
638 	/* .type = */		KEY_RSA_CERT,
639 	/* .nid = */		0,
640 	/* .cert = */		1,
641 	/* .sigonly = */	1,
642 	/* .keybits = */	0,
643 	/* .funcs = */		&sshkey_rsa_funcs,
644 };
645 #endif /* WITH_OPENSSL */
646