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