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