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