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