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