xref: /freebsd/crypto/openssh/ssh-rsa.c (revision 2c77ec54190294415c52a8da0c0d9c5a957c03a3)
1 /* $OpenBSD: ssh-rsa.c,v 1.66 2018/02/14 16:27:24 jsing 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 static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *);
39 
40 static const char *
41 rsa_hash_alg_ident(int hash_alg)
42 {
43 	switch (hash_alg) {
44 	case SSH_DIGEST_SHA1:
45 		return "ssh-rsa";
46 	case SSH_DIGEST_SHA256:
47 		return "rsa-sha2-256";
48 	case SSH_DIGEST_SHA512:
49 		return "rsa-sha2-512";
50 	}
51 	return NULL;
52 }
53 
54 static int
55 rsa_hash_alg_from_ident(const char *ident)
56 {
57 	if (strcmp(ident, "ssh-rsa") == 0 ||
58 	    strcmp(ident, "ssh-rsa-cert-v01@openssh.com") == 0)
59 		return SSH_DIGEST_SHA1;
60 	if (strcmp(ident, "rsa-sha2-256") == 0)
61 		return SSH_DIGEST_SHA256;
62 	if (strcmp(ident, "rsa-sha2-512") == 0)
63 		return SSH_DIGEST_SHA512;
64 	return -1;
65 }
66 
67 static int
68 rsa_hash_alg_nid(int type)
69 {
70 	switch (type) {
71 	case SSH_DIGEST_SHA1:
72 		return NID_sha1;
73 	case SSH_DIGEST_SHA256:
74 		return NID_sha256;
75 	case SSH_DIGEST_SHA512:
76 		return NID_sha512;
77 	default:
78 		return -1;
79 	}
80 }
81 
82 int
83 ssh_rsa_generate_additional_parameters(struct sshkey *key)
84 {
85 	BIGNUM *aux = NULL;
86 	BN_CTX *ctx = NULL;
87 	BIGNUM d;
88 	int r;
89 
90 	if (key == NULL || key->rsa == NULL ||
91 	    sshkey_type_plain(key->type) != KEY_RSA)
92 		return SSH_ERR_INVALID_ARGUMENT;
93 
94 	if ((ctx = BN_CTX_new()) == NULL)
95 		return SSH_ERR_ALLOC_FAIL;
96 	if ((aux = BN_new()) == NULL) {
97 		r = SSH_ERR_ALLOC_FAIL;
98 		goto out;
99 	}
100 	BN_set_flags(aux, BN_FLG_CONSTTIME);
101 
102 	BN_init(&d);
103 	BN_with_flags(&d, key->rsa->d, BN_FLG_CONSTTIME);
104 
105 	if ((BN_sub(aux, key->rsa->q, BN_value_one()) == 0) ||
106 	    (BN_mod(key->rsa->dmq1, &d, aux, ctx) == 0) ||
107 	    (BN_sub(aux, key->rsa->p, BN_value_one()) == 0) ||
108 	    (BN_mod(key->rsa->dmp1, &d, aux, ctx) == 0)) {
109 		r = SSH_ERR_LIBCRYPTO_ERROR;
110 		goto out;
111 	}
112 	r = 0;
113  out:
114 	BN_clear_free(aux);
115 	BN_CTX_free(ctx);
116 	return r;
117 }
118 
119 /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */
120 int
121 ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
122     const u_char *data, size_t datalen, const char *alg_ident)
123 {
124 	u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL;
125 	size_t slen = 0;
126 	u_int dlen, len;
127 	int nid, hash_alg, ret = SSH_ERR_INTERNAL_ERROR;
128 	struct sshbuf *b = NULL;
129 
130 	if (lenp != NULL)
131 		*lenp = 0;
132 	if (sigp != NULL)
133 		*sigp = NULL;
134 
135 	if (alg_ident == NULL || strlen(alg_ident) == 0)
136 		hash_alg = SSH_DIGEST_SHA1;
137 	else
138 		hash_alg = rsa_hash_alg_from_ident(alg_ident);
139 	if (key == NULL || key->rsa == NULL || hash_alg == -1 ||
140 	    sshkey_type_plain(key->type) != KEY_RSA)
141 		return SSH_ERR_INVALID_ARGUMENT;
142 	if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
143 		return SSH_ERR_KEY_LENGTH;
144 	slen = RSA_size(key->rsa);
145 	if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM)
146 		return SSH_ERR_INVALID_ARGUMENT;
147 
148 	/* hash the data */
149 	nid = rsa_hash_alg_nid(hash_alg);
150 	if ((dlen = ssh_digest_bytes(hash_alg)) == 0)
151 		return SSH_ERR_INTERNAL_ERROR;
152 	if ((ret = ssh_digest_memory(hash_alg, data, datalen,
153 	    digest, sizeof(digest))) != 0)
154 		goto out;
155 
156 	if ((sig = malloc(slen)) == NULL) {
157 		ret = SSH_ERR_ALLOC_FAIL;
158 		goto out;
159 	}
160 
161 	if (RSA_sign(nid, digest, dlen, sig, &len, key->rsa) != 1) {
162 		ret = SSH_ERR_LIBCRYPTO_ERROR;
163 		goto out;
164 	}
165 	if (len < slen) {
166 		size_t diff = slen - len;
167 		memmove(sig + diff, sig, len);
168 		explicit_bzero(sig, diff);
169 	} else if (len > slen) {
170 		ret = SSH_ERR_INTERNAL_ERROR;
171 		goto out;
172 	}
173 	/* encode signature */
174 	if ((b = sshbuf_new()) == NULL) {
175 		ret = SSH_ERR_ALLOC_FAIL;
176 		goto out;
177 	}
178 	if ((ret = sshbuf_put_cstring(b, rsa_hash_alg_ident(hash_alg))) != 0 ||
179 	    (ret = sshbuf_put_string(b, sig, slen)) != 0)
180 		goto out;
181 	len = sshbuf_len(b);
182 	if (sigp != NULL) {
183 		if ((*sigp = malloc(len)) == NULL) {
184 			ret = SSH_ERR_ALLOC_FAIL;
185 			goto out;
186 		}
187 		memcpy(*sigp, sshbuf_ptr(b), len);
188 	}
189 	if (lenp != NULL)
190 		*lenp = len;
191 	ret = 0;
192  out:
193 	explicit_bzero(digest, sizeof(digest));
194 	freezero(sig, slen);
195 	sshbuf_free(b);
196 	return ret;
197 }
198 
199 int
200 ssh_rsa_verify(const struct sshkey *key,
201     const u_char *sig, size_t siglen, const u_char *data, size_t datalen,
202     const char *alg)
203 {
204 	char *sigtype = NULL;
205 	int hash_alg, ret = SSH_ERR_INTERNAL_ERROR;
206 	size_t len = 0, diff, modlen, dlen;
207 	struct sshbuf *b = NULL;
208 	u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL;
209 
210 	if (key == NULL || key->rsa == NULL ||
211 	    sshkey_type_plain(key->type) != KEY_RSA ||
212 	    sig == NULL || siglen == 0)
213 		return SSH_ERR_INVALID_ARGUMENT;
214 	if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
215 		return SSH_ERR_KEY_LENGTH;
216 
217 	if ((b = sshbuf_from(sig, siglen)) == NULL)
218 		return SSH_ERR_ALLOC_FAIL;
219 	if (sshbuf_get_cstring(b, &sigtype, NULL) != 0) {
220 		ret = SSH_ERR_INVALID_FORMAT;
221 		goto out;
222 	}
223 	/* XXX djm: need cert types that reliably yield SHA-2 signatures */
224 	if (alg != NULL && strcmp(alg, sigtype) != 0 &&
225 	    strcmp(alg, "ssh-rsa-cert-v01@openssh.com") != 0) {
226 		error("%s: RSA signature type mismatch: "
227 		    "expected %s received %s", __func__, alg, sigtype);
228 		ret = SSH_ERR_SIGNATURE_INVALID;
229 		goto out;
230 	}
231 	if ((hash_alg = rsa_hash_alg_from_ident(sigtype)) == -1) {
232 		ret = SSH_ERR_KEY_TYPE_MISMATCH;
233 		goto out;
234 	}
235 	if (sshbuf_get_string(b, &sigblob, &len) != 0) {
236 		ret = SSH_ERR_INVALID_FORMAT;
237 		goto out;
238 	}
239 	if (sshbuf_len(b) != 0) {
240 		ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
241 		goto out;
242 	}
243 	/* RSA_verify expects a signature of RSA_size */
244 	modlen = RSA_size(key->rsa);
245 	if (len > modlen) {
246 		ret = SSH_ERR_KEY_BITS_MISMATCH;
247 		goto out;
248 	} else if (len < modlen) {
249 		diff = modlen - len;
250 		osigblob = sigblob;
251 		if ((sigblob = realloc(sigblob, modlen)) == NULL) {
252 			sigblob = osigblob; /* put it back for clear/free */
253 			ret = SSH_ERR_ALLOC_FAIL;
254 			goto out;
255 		}
256 		memmove(sigblob + diff, sigblob, len);
257 		explicit_bzero(sigblob, diff);
258 		len = modlen;
259 	}
260 	if ((dlen = ssh_digest_bytes(hash_alg)) == 0) {
261 		ret = SSH_ERR_INTERNAL_ERROR;
262 		goto out;
263 	}
264 	if ((ret = ssh_digest_memory(hash_alg, data, datalen,
265 	    digest, sizeof(digest))) != 0)
266 		goto out;
267 
268 	ret = openssh_RSA_verify(hash_alg, digest, dlen, sigblob, len,
269 	    key->rsa);
270  out:
271 	freezero(sigblob, len);
272 	free(sigtype);
273 	sshbuf_free(b);
274 	explicit_bzero(digest, sizeof(digest));
275 	return ret;
276 }
277 
278 /*
279  * See:
280  * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/
281  * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn
282  */
283 
284 /*
285  * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
286  *	oiw(14) secsig(3) algorithms(2) 26 }
287  */
288 static const u_char id_sha1[] = {
289 	0x30, 0x21, /* type Sequence, length 0x21 (33) */
290 	0x30, 0x09, /* type Sequence, length 0x09 */
291 	0x06, 0x05, /* type OID, length 0x05 */
292 	0x2b, 0x0e, 0x03, 0x02, 0x1a, /* id-sha1 OID */
293 	0x05, 0x00, /* NULL */
294 	0x04, 0x14  /* Octet string, length 0x14 (20), followed by sha1 hash */
295 };
296 
297 /*
298  * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html
299  * id-sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840)
300  *      organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2)
301  *      id-sha256(1) }
302  */
303 static const u_char id_sha256[] = {
304 	0x30, 0x31, /* type Sequence, length 0x31 (49) */
305 	0x30, 0x0d, /* type Sequence, length 0x0d (13) */
306 	0x06, 0x09, /* type OID, length 0x09 */
307 	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, /* id-sha256 */
308 	0x05, 0x00, /* NULL */
309 	0x04, 0x20  /* Octet string, length 0x20 (32), followed by sha256 hash */
310 };
311 
312 /*
313  * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html
314  * id-sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840)
315  *      organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2)
316  *      id-sha256(3) }
317  */
318 static const u_char id_sha512[] = {
319 	0x30, 0x51, /* type Sequence, length 0x51 (81) */
320 	0x30, 0x0d, /* type Sequence, length 0x0d (13) */
321 	0x06, 0x09, /* type OID, length 0x09 */
322 	0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, /* id-sha512 */
323 	0x05, 0x00, /* NULL */
324 	0x04, 0x40  /* Octet string, length 0x40 (64), followed by sha512 hash */
325 };
326 
327 static int
328 rsa_hash_alg_oid(int hash_alg, const u_char **oidp, size_t *oidlenp)
329 {
330 	switch (hash_alg) {
331 	case SSH_DIGEST_SHA1:
332 		*oidp = id_sha1;
333 		*oidlenp = sizeof(id_sha1);
334 		break;
335 	case SSH_DIGEST_SHA256:
336 		*oidp = id_sha256;
337 		*oidlenp = sizeof(id_sha256);
338 		break;
339 	case SSH_DIGEST_SHA512:
340 		*oidp = id_sha512;
341 		*oidlenp = sizeof(id_sha512);
342 		break;
343 	default:
344 		return SSH_ERR_INVALID_ARGUMENT;
345 	}
346 	return 0;
347 }
348 
349 static int
350 openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen,
351     u_char *sigbuf, size_t siglen, RSA *rsa)
352 {
353 	size_t rsasize = 0, oidlen = 0, hlen = 0;
354 	int ret, len, oidmatch, hashmatch;
355 	const u_char *oid = NULL;
356 	u_char *decrypted = NULL;
357 
358 	if ((ret = rsa_hash_alg_oid(hash_alg, &oid, &oidlen)) != 0)
359 		return ret;
360 	ret = SSH_ERR_INTERNAL_ERROR;
361 	hlen = ssh_digest_bytes(hash_alg);
362 	if (hashlen != hlen) {
363 		ret = SSH_ERR_INVALID_ARGUMENT;
364 		goto done;
365 	}
366 	rsasize = RSA_size(rsa);
367 	if (rsasize <= 0 || rsasize > SSHBUF_MAX_BIGNUM ||
368 	    siglen == 0 || siglen > rsasize) {
369 		ret = SSH_ERR_INVALID_ARGUMENT;
370 		goto done;
371 	}
372 	if ((decrypted = malloc(rsasize)) == NULL) {
373 		ret = SSH_ERR_ALLOC_FAIL;
374 		goto done;
375 	}
376 	if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa,
377 	    RSA_PKCS1_PADDING)) < 0) {
378 		ret = SSH_ERR_LIBCRYPTO_ERROR;
379 		goto done;
380 	}
381 	if (len < 0 || (size_t)len != hlen + oidlen) {
382 		ret = SSH_ERR_INVALID_FORMAT;
383 		goto done;
384 	}
385 	oidmatch = timingsafe_bcmp(decrypted, oid, oidlen) == 0;
386 	hashmatch = timingsafe_bcmp(decrypted + oidlen, hash, hlen) == 0;
387 	if (!oidmatch || !hashmatch) {
388 		ret = SSH_ERR_SIGNATURE_INVALID;
389 		goto done;
390 	}
391 	ret = 0;
392 done:
393 	freezero(decrypted, rsasize);
394 	return ret;
395 }
396 #endif /* WITH_OPENSSL */
397