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