xref: /freebsd/crypto/openssh/ssh-rsa.c (revision af23369a6deaaeb612ab266eb88b8bb8d560c322)
1 /* $OpenBSD: ssh-rsa.c,v 1.78 2022/10/28 02:47:04 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 "compat.h"
32 #include "ssherr.h"
33 #define SSHKEY_INTERNAL
34 #include "sshkey.h"
35 #include "digest.h"
36 #include "log.h"
37 
38 #include "openbsd-compat/openssl-compat.h"
39 
40 static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *);
41 
42 static u_int
43 ssh_rsa_size(const struct sshkey *key)
44 {
45 	const BIGNUM *rsa_n;
46 
47 	if (key->rsa == NULL)
48 		return 0;
49 	RSA_get0_key(key->rsa, &rsa_n, NULL, NULL);
50 	return BN_num_bits(rsa_n);
51 }
52 
53 static int
54 ssh_rsa_alloc(struct sshkey *k)
55 {
56 	if ((k->rsa = RSA_new()) == NULL)
57 		return SSH_ERR_ALLOC_FAIL;
58 	return 0;
59 }
60 
61 static void
62 ssh_rsa_cleanup(struct sshkey *k)
63 {
64 	RSA_free(k->rsa);
65 	k->rsa = NULL;
66 }
67 
68 static int
69 ssh_rsa_equal(const struct sshkey *a, const struct sshkey *b)
70 {
71 	const BIGNUM *rsa_e_a, *rsa_n_a;
72 	const BIGNUM *rsa_e_b, *rsa_n_b;
73 
74 	if (a->rsa == NULL || b->rsa == NULL)
75 		return 0;
76 	RSA_get0_key(a->rsa, &rsa_n_a, &rsa_e_a, NULL);
77 	RSA_get0_key(b->rsa, &rsa_n_b, &rsa_e_b, NULL);
78 	if (rsa_e_a == NULL || rsa_e_b == NULL)
79 		return 0;
80 	if (rsa_n_a == NULL || rsa_n_b == NULL)
81 		return 0;
82 	if (BN_cmp(rsa_e_a, rsa_e_b) != 0)
83 		return 0;
84 	if (BN_cmp(rsa_n_a, rsa_n_b) != 0)
85 		return 0;
86 	return 1;
87 }
88 
89 static int
90 ssh_rsa_serialize_public(const struct sshkey *key, struct sshbuf *b,
91     enum sshkey_serialize_rep opts)
92 {
93 	int r;
94 	const BIGNUM *rsa_n, *rsa_e;
95 
96 	if (key->rsa == NULL)
97 		return SSH_ERR_INVALID_ARGUMENT;
98 	RSA_get0_key(key->rsa, &rsa_n, &rsa_e, NULL);
99 	if ((r = sshbuf_put_bignum2(b, rsa_e)) != 0 ||
100 	    (r = sshbuf_put_bignum2(b, rsa_n)) != 0)
101 		return r;
102 
103 	return 0;
104 }
105 
106 static int
107 ssh_rsa_serialize_private(const struct sshkey *key, struct sshbuf *b,
108     enum sshkey_serialize_rep opts)
109 {
110 	int r;
111 	const BIGNUM *rsa_n, *rsa_e, *rsa_d, *rsa_iqmp, *rsa_p, *rsa_q;
112 
113 	RSA_get0_key(key->rsa, &rsa_n, &rsa_e, &rsa_d);
114 	RSA_get0_factors(key->rsa, &rsa_p, &rsa_q);
115 	RSA_get0_crt_params(key->rsa, NULL, NULL, &rsa_iqmp);
116 
117 	if (!sshkey_is_cert(key)) {
118 		/* Note: can't reuse ssh_rsa_serialize_public: e, n vs. n, e */
119 		if ((r = sshbuf_put_bignum2(b, rsa_n)) != 0 ||
120 		    (r = sshbuf_put_bignum2(b, rsa_e)) != 0)
121 			return r;
122 	}
123 	if ((r = sshbuf_put_bignum2(b, rsa_d)) != 0 ||
124 	    (r = sshbuf_put_bignum2(b, rsa_iqmp)) != 0 ||
125 	    (r = sshbuf_put_bignum2(b, rsa_p)) != 0 ||
126 	    (r = sshbuf_put_bignum2(b, rsa_q)) != 0)
127 		return r;
128 
129 	return 0;
130 }
131 
132 static int
133 ssh_rsa_generate(struct sshkey *k, int bits)
134 {
135 	RSA *private = NULL;
136 	BIGNUM *f4 = NULL;
137 	int ret = SSH_ERR_INTERNAL_ERROR;
138 
139 	if (bits < SSH_RSA_MINIMUM_MODULUS_SIZE ||
140 	    bits > SSHBUF_MAX_BIGNUM * 8)
141 		return SSH_ERR_KEY_LENGTH;
142 	if ((private = RSA_new()) == NULL || (f4 = BN_new()) == NULL) {
143 		ret = SSH_ERR_ALLOC_FAIL;
144 		goto out;
145 	}
146 	if (!BN_set_word(f4, RSA_F4) ||
147 	    !RSA_generate_key_ex(private, bits, f4, NULL)) {
148 		ret = SSH_ERR_LIBCRYPTO_ERROR;
149 		goto out;
150 	}
151 	k->rsa = private;
152 	private = NULL;
153 	ret = 0;
154  out:
155 	RSA_free(private);
156 	BN_free(f4);
157 	return ret;
158 }
159 
160 static int
161 ssh_rsa_copy_public(const struct sshkey *from, struct sshkey *to)
162 {
163 	const BIGNUM *rsa_n, *rsa_e;
164 	BIGNUM *rsa_n_dup = NULL, *rsa_e_dup = NULL;
165 	int r = SSH_ERR_INTERNAL_ERROR;
166 
167 	RSA_get0_key(from->rsa, &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(to->rsa, 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 	/* success */
179 	r = 0;
180  out:
181 	BN_clear_free(rsa_n_dup);
182 	BN_clear_free(rsa_e_dup);
183 	return r;
184 }
185 
186 static int
187 ssh_rsa_deserialize_public(const char *ktype, struct sshbuf *b,
188     struct sshkey *key)
189 {
190 	int ret = SSH_ERR_INTERNAL_ERROR;
191 	BIGNUM *rsa_n = NULL, *rsa_e = NULL;
192 
193 	if (sshbuf_get_bignum2(b, &rsa_e) != 0 ||
194 	    sshbuf_get_bignum2(b, &rsa_n) != 0) {
195 		ret = SSH_ERR_INVALID_FORMAT;
196 		goto out;
197 	}
198 	if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, NULL)) {
199 		ret = SSH_ERR_LIBCRYPTO_ERROR;
200 		goto out;
201 	}
202 	rsa_n = rsa_e = NULL; /* transferred */
203 	if ((ret = sshkey_check_rsa_length(key, 0)) != 0)
204 		goto out;
205 #ifdef DEBUG_PK
206 	RSA_print_fp(stderr, key->rsa, 8);
207 #endif
208 	/* success */
209 	ret = 0;
210  out:
211 	BN_clear_free(rsa_n);
212 	BN_clear_free(rsa_e);
213 	return ret;
214 }
215 
216 static int
217 ssh_rsa_deserialize_private(const char *ktype, struct sshbuf *b,
218     struct sshkey *key)
219 {
220 	int r;
221 	BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL;
222 	BIGNUM *rsa_iqmp = NULL, *rsa_p = NULL, *rsa_q = NULL;
223 
224 	/* Note: can't reuse ssh_rsa_deserialize_public: e, n vs. n, e */
225 	if (!sshkey_is_cert(key)) {
226 		if ((r = sshbuf_get_bignum2(b, &rsa_n)) != 0 ||
227 		    (r = sshbuf_get_bignum2(b, &rsa_e)) != 0)
228 			goto out;
229 		if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, NULL)) {
230 			r = SSH_ERR_LIBCRYPTO_ERROR;
231 			goto out;
232 		}
233 		rsa_n = rsa_e = NULL; /* transferred */
234 	}
235 	if ((r = sshbuf_get_bignum2(b, &rsa_d)) != 0 ||
236 	    (r = sshbuf_get_bignum2(b, &rsa_iqmp)) != 0 ||
237 	    (r = sshbuf_get_bignum2(b, &rsa_p)) != 0 ||
238 	    (r = sshbuf_get_bignum2(b, &rsa_q)) != 0)
239 		goto out;
240 	if (!RSA_set0_key(key->rsa, NULL, NULL, rsa_d)) {
241 		r = SSH_ERR_LIBCRYPTO_ERROR;
242 		goto out;
243 	}
244 	rsa_d = NULL; /* transferred */
245 	if (!RSA_set0_factors(key->rsa, rsa_p, rsa_q)) {
246 		r = SSH_ERR_LIBCRYPTO_ERROR;
247 		goto out;
248 	}
249 	rsa_p = rsa_q = NULL; /* transferred */
250 	if ((r = sshkey_check_rsa_length(key, 0)) != 0)
251 		goto out;
252 	if ((r = ssh_rsa_complete_crt_parameters(key, rsa_iqmp)) != 0)
253 		goto out;
254 	if (RSA_blinding_on(key->rsa, NULL) != 1) {
255 		r = SSH_ERR_LIBCRYPTO_ERROR;
256 		goto out;
257 	}
258 	/* success */
259 	r = 0;
260  out:
261 	BN_clear_free(rsa_n);
262 	BN_clear_free(rsa_e);
263 	BN_clear_free(rsa_d);
264 	BN_clear_free(rsa_p);
265 	BN_clear_free(rsa_q);
266 	BN_clear_free(rsa_iqmp);
267 	return r;
268 }
269 
270 static const char *
271 rsa_hash_alg_ident(int hash_alg)
272 {
273 	switch (hash_alg) {
274 	case SSH_DIGEST_SHA1:
275 		return "ssh-rsa";
276 	case SSH_DIGEST_SHA256:
277 		return "rsa-sha2-256";
278 	case SSH_DIGEST_SHA512:
279 		return "rsa-sha2-512";
280 	}
281 	return NULL;
282 }
283 
284 /*
285  * Returns the hash algorithm ID for a given algorithm identifier as used
286  * inside the signature blob,
287  */
288 static int
289 rsa_hash_id_from_ident(const char *ident)
290 {
291 	if (strcmp(ident, "ssh-rsa") == 0)
292 		return SSH_DIGEST_SHA1;
293 	if (strcmp(ident, "rsa-sha2-256") == 0)
294 		return SSH_DIGEST_SHA256;
295 	if (strcmp(ident, "rsa-sha2-512") == 0)
296 		return SSH_DIGEST_SHA512;
297 	return -1;
298 }
299 
300 /*
301  * Return the hash algorithm ID for the specified key name. This includes
302  * all the cases of rsa_hash_id_from_ident() but also the certificate key
303  * types.
304  */
305 static int
306 rsa_hash_id_from_keyname(const char *alg)
307 {
308 	int r;
309 
310 	if ((r = rsa_hash_id_from_ident(alg)) != -1)
311 		return r;
312 	if (strcmp(alg, "ssh-rsa-cert-v01@openssh.com") == 0)
313 		return SSH_DIGEST_SHA1;
314 	if (strcmp(alg, "rsa-sha2-256-cert-v01@openssh.com") == 0)
315 		return SSH_DIGEST_SHA256;
316 	if (strcmp(alg, "rsa-sha2-512-cert-v01@openssh.com") == 0)
317 		return SSH_DIGEST_SHA512;
318 	return -1;
319 }
320 
321 static int
322 rsa_hash_alg_nid(int type)
323 {
324 	switch (type) {
325 	case SSH_DIGEST_SHA1:
326 		return NID_sha1;
327 	case SSH_DIGEST_SHA256:
328 		return NID_sha256;
329 	case SSH_DIGEST_SHA512:
330 		return NID_sha512;
331 	default:
332 		return -1;
333 	}
334 }
335 
336 int
337 ssh_rsa_complete_crt_parameters(struct sshkey *key, const BIGNUM *iqmp)
338 {
339 	const BIGNUM *rsa_p, *rsa_q, *rsa_d;
340 	BIGNUM *aux = NULL, *d_consttime = NULL;
341 	BIGNUM *rsa_dmq1 = NULL, *rsa_dmp1 = NULL, *rsa_iqmp = NULL;
342 	BN_CTX *ctx = NULL;
343 	int r;
344 
345 	if (key == NULL || key->rsa == NULL ||
346 	    sshkey_type_plain(key->type) != KEY_RSA)
347 		return SSH_ERR_INVALID_ARGUMENT;
348 
349 	RSA_get0_key(key->rsa, NULL, NULL, &rsa_d);
350 	RSA_get0_factors(key->rsa, &rsa_p, &rsa_q);
351 
352 	if ((ctx = BN_CTX_new()) == NULL)
353 		return SSH_ERR_ALLOC_FAIL;
354 	if ((aux = BN_new()) == NULL ||
355 	    (rsa_dmq1 = BN_new()) == NULL ||
356 	    (rsa_dmp1 = BN_new()) == NULL)
357 		return SSH_ERR_ALLOC_FAIL;
358 	if ((d_consttime = BN_dup(rsa_d)) == NULL ||
359 	    (rsa_iqmp = BN_dup(iqmp)) == NULL) {
360 		r = SSH_ERR_ALLOC_FAIL;
361 		goto out;
362 	}
363 	BN_set_flags(aux, BN_FLG_CONSTTIME);
364 	BN_set_flags(d_consttime, BN_FLG_CONSTTIME);
365 
366 	if ((BN_sub(aux, rsa_q, BN_value_one()) == 0) ||
367 	    (BN_mod(rsa_dmq1, d_consttime, aux, ctx) == 0) ||
368 	    (BN_sub(aux, rsa_p, BN_value_one()) == 0) ||
369 	    (BN_mod(rsa_dmp1, d_consttime, aux, ctx) == 0)) {
370 		r = SSH_ERR_LIBCRYPTO_ERROR;
371 		goto out;
372 	}
373 	if (!RSA_set0_crt_params(key->rsa, rsa_dmp1, rsa_dmq1, rsa_iqmp)) {
374 		r = SSH_ERR_LIBCRYPTO_ERROR;
375 		goto out;
376 	}
377 	rsa_dmp1 = rsa_dmq1 = rsa_iqmp = NULL; /* transferred */
378 	/* success */
379 	r = 0;
380  out:
381 	BN_clear_free(aux);
382 	BN_clear_free(d_consttime);
383 	BN_clear_free(rsa_dmp1);
384 	BN_clear_free(rsa_dmq1);
385 	BN_clear_free(rsa_iqmp);
386 	BN_CTX_free(ctx);
387 	return r;
388 }
389 
390 /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */
391 static int
392 ssh_rsa_sign(struct sshkey *key,
393     u_char **sigp, size_t *lenp,
394     const u_char *data, size_t datalen,
395     const char *alg, const char *sk_provider, const char *sk_pin, u_int compat)
396 {
397 	const BIGNUM *rsa_n;
398 	u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL;
399 	size_t slen = 0;
400 	u_int hlen, len;
401 	int nid, hash_alg, ret = SSH_ERR_INTERNAL_ERROR;
402 	struct sshbuf *b = NULL;
403 
404 	if (lenp != NULL)
405 		*lenp = 0;
406 	if (sigp != NULL)
407 		*sigp = NULL;
408 
409 	if (alg == NULL || strlen(alg) == 0)
410 		hash_alg = SSH_DIGEST_SHA1;
411 	else
412 		hash_alg = rsa_hash_id_from_keyname(alg);
413 	if (key == NULL || key->rsa == NULL || hash_alg == -1 ||
414 	    sshkey_type_plain(key->type) != KEY_RSA)
415 		return SSH_ERR_INVALID_ARGUMENT;
416 	RSA_get0_key(key->rsa, &rsa_n, NULL, NULL);
417 	if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
418 		return SSH_ERR_KEY_LENGTH;
419 	slen = RSA_size(key->rsa);
420 	if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM)
421 		return SSH_ERR_INVALID_ARGUMENT;
422 
423 	/* hash the data */
424 	nid = rsa_hash_alg_nid(hash_alg);
425 	if ((hlen = ssh_digest_bytes(hash_alg)) == 0)
426 		return SSH_ERR_INTERNAL_ERROR;
427 	if ((ret = ssh_digest_memory(hash_alg, data, datalen,
428 	    digest, sizeof(digest))) != 0)
429 		goto out;
430 
431 	if ((sig = malloc(slen)) == NULL) {
432 		ret = SSH_ERR_ALLOC_FAIL;
433 		goto out;
434 	}
435 
436 	if (RSA_sign(nid, digest, hlen, sig, &len, key->rsa) != 1) {
437 		ret = SSH_ERR_LIBCRYPTO_ERROR;
438 		goto out;
439 	}
440 	if (len < slen) {
441 		size_t diff = slen - len;
442 		memmove(sig + diff, sig, len);
443 		explicit_bzero(sig, diff);
444 	} else if (len > slen) {
445 		ret = SSH_ERR_INTERNAL_ERROR;
446 		goto out;
447 	}
448 	/* encode signature */
449 	if ((b = sshbuf_new()) == NULL) {
450 		ret = SSH_ERR_ALLOC_FAIL;
451 		goto out;
452 	}
453 	if ((ret = sshbuf_put_cstring(b, rsa_hash_alg_ident(hash_alg))) != 0 ||
454 	    (ret = sshbuf_put_string(b, sig, slen)) != 0)
455 		goto out;
456 	len = sshbuf_len(b);
457 	if (sigp != NULL) {
458 		if ((*sigp = malloc(len)) == NULL) {
459 			ret = SSH_ERR_ALLOC_FAIL;
460 			goto out;
461 		}
462 		memcpy(*sigp, sshbuf_ptr(b), len);
463 	}
464 	if (lenp != NULL)
465 		*lenp = len;
466 	ret = 0;
467  out:
468 	explicit_bzero(digest, sizeof(digest));
469 	freezero(sig, slen);
470 	sshbuf_free(b);
471 	return ret;
472 }
473 
474 static int
475 ssh_rsa_verify(const struct sshkey *key,
476     const u_char *sig, size_t siglen,
477     const u_char *data, size_t dlen, const char *alg, u_int compat,
478     struct sshkey_sig_details **detailsp)
479 {
480 	const BIGNUM *rsa_n;
481 	char *sigtype = NULL;
482 	int hash_alg, want_alg, ret = SSH_ERR_INTERNAL_ERROR;
483 	size_t len = 0, diff, modlen, hlen;
484 	struct sshbuf *b = NULL;
485 	u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL;
486 
487 	if (key == NULL || key->rsa == NULL ||
488 	    sshkey_type_plain(key->type) != KEY_RSA ||
489 	    sig == NULL || siglen == 0)
490 		return SSH_ERR_INVALID_ARGUMENT;
491 	RSA_get0_key(key->rsa, &rsa_n, NULL, NULL);
492 	if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
493 		return SSH_ERR_KEY_LENGTH;
494 
495 	if ((b = sshbuf_from(sig, siglen)) == NULL)
496 		return SSH_ERR_ALLOC_FAIL;
497 	if (sshbuf_get_cstring(b, &sigtype, NULL) != 0) {
498 		ret = SSH_ERR_INVALID_FORMAT;
499 		goto out;
500 	}
501 	if ((hash_alg = rsa_hash_id_from_ident(sigtype)) == -1) {
502 		ret = SSH_ERR_KEY_TYPE_MISMATCH;
503 		goto out;
504 	}
505 	/*
506 	 * Allow ssh-rsa-cert-v01 certs to generate SHA2 signatures for
507 	 * legacy reasons, but otherwise the signature type should match.
508 	 */
509 	if (alg != NULL && strcmp(alg, "ssh-rsa-cert-v01@openssh.com") != 0) {
510 		if ((want_alg = rsa_hash_id_from_keyname(alg)) == -1) {
511 			ret = SSH_ERR_INVALID_ARGUMENT;
512 			goto out;
513 		}
514 		if (hash_alg != want_alg) {
515 			ret = SSH_ERR_SIGNATURE_INVALID;
516 			goto out;
517 		}
518 	}
519 	if (sshbuf_get_string(b, &sigblob, &len) != 0) {
520 		ret = SSH_ERR_INVALID_FORMAT;
521 		goto out;
522 	}
523 	if (sshbuf_len(b) != 0) {
524 		ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
525 		goto out;
526 	}
527 	/* RSA_verify expects a signature of RSA_size */
528 	modlen = RSA_size(key->rsa);
529 	if (len > modlen) {
530 		ret = SSH_ERR_KEY_BITS_MISMATCH;
531 		goto out;
532 	} else if (len < modlen) {
533 		diff = modlen - len;
534 		osigblob = sigblob;
535 		if ((sigblob = realloc(sigblob, modlen)) == NULL) {
536 			sigblob = osigblob; /* put it back for clear/free */
537 			ret = SSH_ERR_ALLOC_FAIL;
538 			goto out;
539 		}
540 		memmove(sigblob + diff, sigblob, len);
541 		explicit_bzero(sigblob, diff);
542 		len = modlen;
543 	}
544 	if ((hlen = ssh_digest_bytes(hash_alg)) == 0) {
545 		ret = SSH_ERR_INTERNAL_ERROR;
546 		goto out;
547 	}
548 	if ((ret = ssh_digest_memory(hash_alg, data, dlen,
549 	    digest, sizeof(digest))) != 0)
550 		goto out;
551 
552 	ret = openssh_RSA_verify(hash_alg, digest, hlen, sigblob, len,
553 	    key->rsa);
554  out:
555 	freezero(sigblob, len);
556 	free(sigtype);
557 	sshbuf_free(b);
558 	explicit_bzero(digest, sizeof(digest));
559 	return ret;
560 }
561 
562 /*
563  * See:
564  * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/
565  * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn
566  */
567 
568 /*
569  * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
570  *	oiw(14) secsig(3) algorithms(2) 26 }
571  */
572 static const u_char id_sha1[] = {
573 	0x30, 0x21, /* type Sequence, length 0x21 (33) */
574 	0x30, 0x09, /* type Sequence, length 0x09 */
575 	0x06, 0x05, /* type OID, length 0x05 */
576 	0x2b, 0x0e, 0x03, 0x02, 0x1a, /* id-sha1 OID */
577 	0x05, 0x00, /* NULL */
578 	0x04, 0x14  /* Octet string, length 0x14 (20), followed by sha1 hash */
579 };
580 
581 /*
582  * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html
583  * id-sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840)
584  *      organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2)
585  *      id-sha256(1) }
586  */
587 static const u_char id_sha256[] = {
588 	0x30, 0x31, /* type Sequence, length 0x31 (49) */
589 	0x30, 0x0d, /* type Sequence, length 0x0d (13) */
590 	0x06, 0x09, /* type OID, length 0x09 */
591 	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, /* id-sha256 */
592 	0x05, 0x00, /* NULL */
593 	0x04, 0x20  /* Octet string, length 0x20 (32), followed by sha256 hash */
594 };
595 
596 /*
597  * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html
598  * id-sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840)
599  *      organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2)
600  *      id-sha256(3) }
601  */
602 static const u_char id_sha512[] = {
603 	0x30, 0x51, /* type Sequence, length 0x51 (81) */
604 	0x30, 0x0d, /* type Sequence, length 0x0d (13) */
605 	0x06, 0x09, /* type OID, length 0x09 */
606 	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, /* id-sha512 */
607 	0x05, 0x00, /* NULL */
608 	0x04, 0x40  /* Octet string, length 0x40 (64), followed by sha512 hash */
609 };
610 
611 static int
612 rsa_hash_alg_oid(int hash_alg, const u_char **oidp, size_t *oidlenp)
613 {
614 	switch (hash_alg) {
615 	case SSH_DIGEST_SHA1:
616 		*oidp = id_sha1;
617 		*oidlenp = sizeof(id_sha1);
618 		break;
619 	case SSH_DIGEST_SHA256:
620 		*oidp = id_sha256;
621 		*oidlenp = sizeof(id_sha256);
622 		break;
623 	case SSH_DIGEST_SHA512:
624 		*oidp = id_sha512;
625 		*oidlenp = sizeof(id_sha512);
626 		break;
627 	default:
628 		return SSH_ERR_INVALID_ARGUMENT;
629 	}
630 	return 0;
631 }
632 
633 static int
634 openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen,
635     u_char *sigbuf, size_t siglen, RSA *rsa)
636 {
637 	size_t rsasize = 0, oidlen = 0, hlen = 0;
638 	int ret, len, oidmatch, hashmatch;
639 	const u_char *oid = NULL;
640 	u_char *decrypted = NULL;
641 
642 	if ((ret = rsa_hash_alg_oid(hash_alg, &oid, &oidlen)) != 0)
643 		return ret;
644 	ret = SSH_ERR_INTERNAL_ERROR;
645 	hlen = ssh_digest_bytes(hash_alg);
646 	if (hashlen != hlen) {
647 		ret = SSH_ERR_INVALID_ARGUMENT;
648 		goto done;
649 	}
650 	rsasize = RSA_size(rsa);
651 	if (rsasize <= 0 || rsasize > SSHBUF_MAX_BIGNUM ||
652 	    siglen == 0 || siglen > rsasize) {
653 		ret = SSH_ERR_INVALID_ARGUMENT;
654 		goto done;
655 	}
656 	if ((decrypted = malloc(rsasize)) == NULL) {
657 		ret = SSH_ERR_ALLOC_FAIL;
658 		goto done;
659 	}
660 	if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa,
661 	    RSA_PKCS1_PADDING)) < 0) {
662 		ret = SSH_ERR_LIBCRYPTO_ERROR;
663 		goto done;
664 	}
665 	if (len < 0 || (size_t)len != hlen + oidlen) {
666 		ret = SSH_ERR_INVALID_FORMAT;
667 		goto done;
668 	}
669 	oidmatch = timingsafe_bcmp(decrypted, oid, oidlen) == 0;
670 	hashmatch = timingsafe_bcmp(decrypted + oidlen, hash, hlen) == 0;
671 	if (!oidmatch || !hashmatch) {
672 		ret = SSH_ERR_SIGNATURE_INVALID;
673 		goto done;
674 	}
675 	ret = 0;
676 done:
677 	freezero(decrypted, rsasize);
678 	return ret;
679 }
680 
681 static const struct sshkey_impl_funcs sshkey_rsa_funcs = {
682 	/* .size = */		ssh_rsa_size,
683 	/* .alloc = */		ssh_rsa_alloc,
684 	/* .cleanup = */	ssh_rsa_cleanup,
685 	/* .equal = */		ssh_rsa_equal,
686 	/* .ssh_serialize_public = */ ssh_rsa_serialize_public,
687 	/* .ssh_deserialize_public = */ ssh_rsa_deserialize_public,
688 	/* .ssh_serialize_private = */ ssh_rsa_serialize_private,
689 	/* .ssh_deserialize_private = */ ssh_rsa_deserialize_private,
690 	/* .generate = */	ssh_rsa_generate,
691 	/* .copy_public = */	ssh_rsa_copy_public,
692 	/* .sign = */		ssh_rsa_sign,
693 	/* .verify = */		ssh_rsa_verify,
694 };
695 
696 const struct sshkey_impl sshkey_rsa_impl = {
697 	/* .name = */		"ssh-rsa",
698 	/* .shortname = */	"RSA",
699 	/* .sigalg = */		NULL,
700 	/* .type = */		KEY_RSA,
701 	/* .nid = */		0,
702 	/* .cert = */		0,
703 	/* .sigonly = */	0,
704 	/* .keybits = */	0,
705 	/* .funcs = */		&sshkey_rsa_funcs,
706 };
707 
708 const struct sshkey_impl sshkey_rsa_cert_impl = {
709 	/* .name = */		"ssh-rsa-cert-v01@openssh.com",
710 	/* .shortname = */	"RSA-CERT",
711 	/* .sigalg = */		NULL,
712 	/* .type = */		KEY_RSA_CERT,
713 	/* .nid = */		0,
714 	/* .cert = */		1,
715 	/* .sigonly = */	0,
716 	/* .keybits = */	0,
717 	/* .funcs = */		&sshkey_rsa_funcs,
718 };
719 
720 /* SHA2 signature algorithms */
721 
722 const struct sshkey_impl sshkey_rsa_sha256_impl = {
723 	/* .name = */		"rsa-sha2-256",
724 	/* .shortname = */	"RSA",
725 	/* .sigalg = */		NULL,
726 	/* .type = */		KEY_RSA,
727 	/* .nid = */		0,
728 	/* .cert = */		0,
729 	/* .sigonly = */	1,
730 	/* .keybits = */	0,
731 	/* .funcs = */		&sshkey_rsa_funcs,
732 };
733 
734 const struct sshkey_impl sshkey_rsa_sha512_impl = {
735 	/* .name = */		"rsa-sha2-512",
736 	/* .shortname = */	"RSA",
737 	/* .sigalg = */		NULL,
738 	/* .type = */		KEY_RSA,
739 	/* .nid = */		0,
740 	/* .cert = */		0,
741 	/* .sigonly = */	1,
742 	/* .keybits = */	0,
743 	/* .funcs = */		&sshkey_rsa_funcs,
744 };
745 
746 const struct sshkey_impl sshkey_rsa_sha256_cert_impl = {
747 	/* .name = */		"rsa-sha2-256-cert-v01@openssh.com",
748 	/* .shortname = */	"RSA-CERT",
749 	/* .sigalg = */		"rsa-sha2-256",
750 	/* .type = */		KEY_RSA_CERT,
751 	/* .nid = */		0,
752 	/* .cert = */		1,
753 	/* .sigonly = */	1,
754 	/* .keybits = */	0,
755 	/* .funcs = */		&sshkey_rsa_funcs,
756 };
757 
758 const struct sshkey_impl sshkey_rsa_sha512_cert_impl = {
759 	/* .name = */		"rsa-sha2-512-cert-v01@openssh.com",
760 	/* .shortname = */	"RSA-CERT",
761 	/* .sigalg = */		"rsa-sha2-512",
762 	/* .type = */		KEY_RSA_CERT,
763 	/* .nid = */		0,
764 	/* .cert = */		1,
765 	/* .sigonly = */	1,
766 	/* .keybits = */	0,
767 	/* .funcs = */		&sshkey_rsa_funcs,
768 };
769 #endif /* WITH_OPENSSL */
770