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