GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/ssh/lib/../cipher.c Lines: 0 174 0.0 %
Date: 2017-11-13 Branches: 0 154 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: cipher.c,v 1.108 2017/11/03 02:22:41 djm Exp $ */
2
/*
3
 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4
 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5
 *                    All rights reserved
6
 *
7
 * As far as I am concerned, the code I have written for this software
8
 * can be used freely for any purpose.  Any derived versions of this
9
 * software must be clearly marked as such, and if the derived work is
10
 * incompatible with the protocol description in the RFC file, it must be
11
 * called by a name other than "ssh" or "Secure Shell".
12
 *
13
 *
14
 * Copyright (c) 1999 Niels Provos.  All rights reserved.
15
 * Copyright (c) 1999, 2000 Markus Friedl.  All rights reserved.
16
 *
17
 * Redistribution and use in source and binary forms, with or without
18
 * modification, are permitted provided that the following conditions
19
 * are met:
20
 * 1. Redistributions of source code must retain the above copyright
21
 *    notice, this list of conditions and the following disclaimer.
22
 * 2. Redistributions in binary form must reproduce the above copyright
23
 *    notice, this list of conditions and the following disclaimer in the
24
 *    documentation and/or other materials provided with the distribution.
25
 *
26
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
 */
37
38
#include <sys/types.h>
39
40
#include <string.h>
41
#include <stdarg.h>
42
#include <stdio.h>
43
44
#include "cipher.h"
45
#include "misc.h"
46
#include "sshbuf.h"
47
#include "ssherr.h"
48
#include "digest.h"
49
50
51
struct sshcipher_ctx {
52
	int	plaintext;
53
	int	encrypt;
54
	EVP_CIPHER_CTX *evp;
55
	struct chachapoly_ctx cp_ctx; /* XXX union with evp? */
56
	struct aesctr_ctx ac_ctx; /* XXX union with evp? */
57
	const struct sshcipher *cipher;
58
};
59
60
struct sshcipher {
61
	char	*name;
62
	u_int	block_size;
63
	u_int	key_len;
64
	u_int	iv_len;		/* defaults to block_size */
65
	u_int	auth_len;
66
	u_int	flags;
67
#define CFLAG_CBC		(1<<0)
68
#define CFLAG_CHACHAPOLY	(1<<1)
69
#define CFLAG_AESCTR		(1<<2)
70
#define CFLAG_NONE		(1<<3)
71
#define CFLAG_INTERNAL		CFLAG_NONE /* Don't use "none" for packets */
72
#ifdef WITH_OPENSSL
73
	const EVP_CIPHER	*(*evptype)(void);
74
#else
75
	void	*ignored;
76
#endif
77
};
78
79
static const struct sshcipher ciphers[] = {
80
#ifdef WITH_OPENSSL
81
	{ "3des-cbc",		8, 24, 0, 0, CFLAG_CBC, EVP_des_ede3_cbc },
82
	{ "aes128-cbc",		16, 16, 0, 0, CFLAG_CBC, EVP_aes_128_cbc },
83
	{ "aes192-cbc",		16, 24, 0, 0, CFLAG_CBC, EVP_aes_192_cbc },
84
	{ "aes256-cbc",		16, 32, 0, 0, CFLAG_CBC, EVP_aes_256_cbc },
85
	{ "rijndael-cbc@lysator.liu.se",
86
				16, 32, 0, 0, CFLAG_CBC, EVP_aes_256_cbc },
87
	{ "aes128-ctr",		16, 16, 0, 0, 0, EVP_aes_128_ctr },
88
	{ "aes192-ctr",		16, 24, 0, 0, 0, EVP_aes_192_ctr },
89
	{ "aes256-ctr",		16, 32, 0, 0, 0, EVP_aes_256_ctr },
90
	{ "aes128-gcm@openssh.com",
91
				16, 16, 12, 16, 0, EVP_aes_128_gcm },
92
	{ "aes256-gcm@openssh.com",
93
				16, 32, 12, 16, 0, EVP_aes_256_gcm },
94
#else
95
	{ "aes128-ctr",		16, 16, 0, 0, CFLAG_AESCTR, NULL },
96
	{ "aes192-ctr",		16, 24, 0, 0, CFLAG_AESCTR, NULL },
97
	{ "aes256-ctr",		16, 32, 0, 0, CFLAG_AESCTR, NULL },
98
#endif
99
	{ "chacha20-poly1305@openssh.com",
100
				8, 64, 0, 16, CFLAG_CHACHAPOLY, NULL },
101
	{ "none",		8, 0, 0, 0, CFLAG_NONE, NULL },
102
103
	{ NULL,			0, 0, 0, 0, 0, NULL }
104
};
105
106
/*--*/
107
108
/* Returns a comma-separated list of supported ciphers. */
109
char *
110
cipher_alg_list(char sep, int auth_only)
111
{
112
	char *tmp, *ret = NULL;
113
	size_t nlen, rlen = 0;
114
	const struct sshcipher *c;
115
116
	for (c = ciphers; c->name != NULL; c++) {
117
		if ((c->flags & CFLAG_INTERNAL) != 0)
118
			continue;
119
		if (auth_only && c->auth_len == 0)
120
			continue;
121
		if (ret != NULL)
122
			ret[rlen++] = sep;
123
		nlen = strlen(c->name);
124
		if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) {
125
			free(ret);
126
			return NULL;
127
		}
128
		ret = tmp;
129
		memcpy(ret + rlen, c->name, nlen + 1);
130
		rlen += nlen;
131
	}
132
	return ret;
133
}
134
135
u_int
136
cipher_blocksize(const struct sshcipher *c)
137
{
138
	return (c->block_size);
139
}
140
141
u_int
142
cipher_keylen(const struct sshcipher *c)
143
{
144
	return (c->key_len);
145
}
146
147
u_int
148
cipher_seclen(const struct sshcipher *c)
149
{
150
	if (strcmp("3des-cbc", c->name) == 0)
151
		return 14;
152
	return cipher_keylen(c);
153
}
154
155
u_int
156
cipher_authlen(const struct sshcipher *c)
157
{
158
	return (c->auth_len);
159
}
160
161
u_int
162
cipher_ivlen(const struct sshcipher *c)
163
{
164
	/*
165
	 * Default is cipher block size, except for chacha20+poly1305 that
166
	 * needs no IV. XXX make iv_len == -1 default?
167
	 */
168
	return (c->iv_len != 0 || (c->flags & CFLAG_CHACHAPOLY) != 0) ?
169
	    c->iv_len : c->block_size;
170
}
171
172
u_int
173
cipher_is_cbc(const struct sshcipher *c)
174
{
175
	return (c->flags & CFLAG_CBC) != 0;
176
}
177
178
u_int
179
cipher_ctx_is_plaintext(struct sshcipher_ctx *cc)
180
{
181
	return cc->plaintext;
182
}
183
184
const struct sshcipher *
185
cipher_by_name(const char *name)
186
{
187
	const struct sshcipher *c;
188
	for (c = ciphers; c->name != NULL; c++)
189
		if (strcmp(c->name, name) == 0)
190
			return c;
191
	return NULL;
192
}
193
194
#define	CIPHER_SEP	","
195
int
196
ciphers_valid(const char *names)
197
{
198
	const struct sshcipher *c;
199
	char *cipher_list, *cp;
200
	char *p;
201
202
	if (names == NULL || strcmp(names, "") == 0)
203
		return 0;
204
	if ((cipher_list = cp = strdup(names)) == NULL)
205
		return 0;
206
	for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
207
	    (p = strsep(&cp, CIPHER_SEP))) {
208
		c = cipher_by_name(p);
209
		if (c == NULL || (c->flags & CFLAG_INTERNAL) != 0) {
210
			free(cipher_list);
211
			return 0;
212
		}
213
	}
214
	free(cipher_list);
215
	return 1;
216
}
217
218
const char *
219
cipher_warning_message(const struct sshcipher_ctx *cc)
220
{
221
	if (cc == NULL || cc->cipher == NULL)
222
		return NULL;
223
	/* XXX repurpose for CBC warning */
224
	return NULL;
225
}
226
227
int
228
cipher_init(struct sshcipher_ctx **ccp, const struct sshcipher *cipher,
229
    const u_char *key, u_int keylen, const u_char *iv, u_int ivlen,
230
    int do_encrypt)
231
{
232
	struct sshcipher_ctx *cc = NULL;
233
	int ret = SSH_ERR_INTERNAL_ERROR;
234
#ifdef WITH_OPENSSL
235
	const EVP_CIPHER *type;
236
	int klen;
237
#endif
238
239
	*ccp = NULL;
240
	if ((cc = calloc(sizeof(*cc), 1)) == NULL)
241
		return SSH_ERR_ALLOC_FAIL;
242
243
	cc->plaintext = (cipher->flags & CFLAG_NONE) != 0;
244
	cc->encrypt = do_encrypt;
245
246
	if (keylen < cipher->key_len ||
247
	    (iv != NULL && ivlen < cipher_ivlen(cipher))) {
248
		ret = SSH_ERR_INVALID_ARGUMENT;
249
		goto out;
250
	}
251
252
	cc->cipher = cipher;
253
	if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
254
		ret = chachapoly_init(&cc->cp_ctx, key, keylen);
255
		goto out;
256
	}
257
	if ((cc->cipher->flags & CFLAG_NONE) != 0) {
258
		ret = 0;
259
		goto out;
260
	}
261
#ifndef WITH_OPENSSL
262
	if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
263
		aesctr_keysetup(&cc->ac_ctx, key, 8 * keylen, 8 * ivlen);
264
		aesctr_ivsetup(&cc->ac_ctx, iv);
265
		ret = 0;
266
		goto out;
267
	}
268
	ret = SSH_ERR_INVALID_ARGUMENT;
269
	goto out;
270
#else /* WITH_OPENSSL */
271
	type = (*cipher->evptype)();
272
	if ((cc->evp = EVP_CIPHER_CTX_new()) == NULL) {
273
		ret = SSH_ERR_ALLOC_FAIL;
274
		goto out;
275
	}
276
	if (EVP_CipherInit(cc->evp, type, NULL, (u_char *)iv,
277
	    (do_encrypt == CIPHER_ENCRYPT)) == 0) {
278
		ret = SSH_ERR_LIBCRYPTO_ERROR;
279
		goto out;
280
	}
281
	if (cipher_authlen(cipher) &&
282
	    !EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_SET_IV_FIXED,
283
	    -1, (u_char *)iv)) {
284
		ret = SSH_ERR_LIBCRYPTO_ERROR;
285
		goto out;
286
	}
287
	klen = EVP_CIPHER_CTX_key_length(cc->evp);
288
	if (klen > 0 && keylen != (u_int)klen) {
289
		if (EVP_CIPHER_CTX_set_key_length(cc->evp, keylen) == 0) {
290
			ret = SSH_ERR_LIBCRYPTO_ERROR;
291
			goto out;
292
		}
293
	}
294
	if (EVP_CipherInit(cc->evp, NULL, (u_char *)key, NULL, -1) == 0) {
295
		ret = SSH_ERR_LIBCRYPTO_ERROR;
296
		goto out;
297
	}
298
	ret = 0;
299
#endif /* WITH_OPENSSL */
300
 out:
301
	if (ret == 0) {
302
		/* success */
303
		*ccp = cc;
304
	} else {
305
		if (cc != NULL) {
306
#ifdef WITH_OPENSSL
307
			if (cc->evp != NULL)
308
				EVP_CIPHER_CTX_free(cc->evp);
309
#endif /* WITH_OPENSSL */
310
			explicit_bzero(cc, sizeof(*cc));
311
			free(cc);
312
		}
313
	}
314
	return ret;
315
}
316
317
/*
318
 * cipher_crypt() operates as following:
319
 * Copy 'aadlen' bytes (without en/decryption) from 'src' to 'dest'.
320
 * Theses bytes are treated as additional authenticated data for
321
 * authenticated encryption modes.
322
 * En/Decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'.
323
 * Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag.
324
 * This tag is written on encryption and verified on decryption.
325
 * Both 'aadlen' and 'authlen' can be set to 0.
326
 */
327
int
328
cipher_crypt(struct sshcipher_ctx *cc, u_int seqnr, u_char *dest,
329
   const u_char *src, u_int len, u_int aadlen, u_int authlen)
330
{
331
	if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
332
		return chachapoly_crypt(&cc->cp_ctx, seqnr, dest, src,
333
		    len, aadlen, authlen, cc->encrypt);
334
	}
335
	if ((cc->cipher->flags & CFLAG_NONE) != 0) {
336
		memcpy(dest, src, aadlen + len);
337
		return 0;
338
	}
339
#ifndef WITH_OPENSSL
340
	if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
341
		if (aadlen)
342
			memcpy(dest, src, aadlen);
343
		aesctr_encrypt_bytes(&cc->ac_ctx, src + aadlen,
344
		    dest + aadlen, len);
345
		return 0;
346
	}
347
	return SSH_ERR_INVALID_ARGUMENT;
348
#else
349
	if (authlen) {
350
		u_char lastiv[1];
351
352
		if (authlen != cipher_authlen(cc->cipher))
353
			return SSH_ERR_INVALID_ARGUMENT;
354
		/* increment IV */
355
		if (!EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN,
356
		    1, lastiv))
357
			return SSH_ERR_LIBCRYPTO_ERROR;
358
		/* set tag on decyption */
359
		if (!cc->encrypt &&
360
		    !EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_SET_TAG,
361
		    authlen, (u_char *)src + aadlen + len))
362
			return SSH_ERR_LIBCRYPTO_ERROR;
363
	}
364
	if (aadlen) {
365
		if (authlen &&
366
		    EVP_Cipher(cc->evp, NULL, (u_char *)src, aadlen) < 0)
367
			return SSH_ERR_LIBCRYPTO_ERROR;
368
		memcpy(dest, src, aadlen);
369
	}
370
	if (len % cc->cipher->block_size)
371
		return SSH_ERR_INVALID_ARGUMENT;
372
	if (EVP_Cipher(cc->evp, dest + aadlen, (u_char *)src + aadlen,
373
	    len) < 0)
374
		return SSH_ERR_LIBCRYPTO_ERROR;
375
	if (authlen) {
376
		/* compute tag (on encrypt) or verify tag (on decrypt) */
377
		if (EVP_Cipher(cc->evp, NULL, NULL, 0) < 0)
378
			return cc->encrypt ?
379
			    SSH_ERR_LIBCRYPTO_ERROR : SSH_ERR_MAC_INVALID;
380
		if (cc->encrypt &&
381
		    !EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_GET_TAG,
382
		    authlen, dest + aadlen + len))
383
			return SSH_ERR_LIBCRYPTO_ERROR;
384
	}
385
	return 0;
386
#endif
387
}
388
389
/* Extract the packet length, including any decryption necessary beforehand */
390
int
391
cipher_get_length(struct sshcipher_ctx *cc, u_int *plenp, u_int seqnr,
392
    const u_char *cp, u_int len)
393
{
394
	if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
395
		return chachapoly_get_length(&cc->cp_ctx, plenp, seqnr,
396
		    cp, len);
397
	if (len < 4)
398
		return SSH_ERR_MESSAGE_INCOMPLETE;
399
	*plenp = get_u32(cp);
400
	return 0;
401
}
402
403
void
404
cipher_free(struct sshcipher_ctx *cc)
405
{
406
	if (cc == NULL)
407
		return;
408
	if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
409
		explicit_bzero(&cc->cp_ctx, sizeof(cc->cp_ctx));
410
	else if ((cc->cipher->flags & CFLAG_AESCTR) != 0)
411
		explicit_bzero(&cc->ac_ctx, sizeof(cc->ac_ctx));
412
#ifdef WITH_OPENSSL
413
	if (cc->evp != NULL) {
414
		EVP_CIPHER_CTX_free(cc->evp);
415
		cc->evp = NULL;
416
	}
417
#endif
418
	explicit_bzero(cc, sizeof(*cc));
419
	free(cc);
420
}
421
422
/*
423
 * Exports an IV from the sshcipher_ctx required to export the key
424
 * state back from the unprivileged child to the privileged parent
425
 * process.
426
 */
427
int
428
cipher_get_keyiv_len(const struct sshcipher_ctx *cc)
429
{
430
	const struct sshcipher *c = cc->cipher;
431
432
	if ((c->flags & CFLAG_CHACHAPOLY) != 0)
433
		return 0;
434
	else if ((c->flags & CFLAG_AESCTR) != 0)
435
		return sizeof(cc->ac_ctx.ctr);
436
#ifdef WITH_OPENSSL
437
	return EVP_CIPHER_CTX_iv_length(cc->evp);
438
#else
439
	return 0;
440
#endif
441
}
442
443
int
444
cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, u_int len)
445
{
446
#ifdef WITH_OPENSSL
447
	const struct sshcipher *c = cc->cipher;
448
 	int evplen;
449
#endif
450
451
	if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
452
		if (len != 0)
453
			return SSH_ERR_INVALID_ARGUMENT;
454
		return 0;
455
	}
456
	if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
457
		if (len != sizeof(cc->ac_ctx.ctr))
458
			return SSH_ERR_INVALID_ARGUMENT;
459
		memcpy(iv, cc->ac_ctx.ctr, len);
460
		return 0;
461
	}
462
	if ((cc->cipher->flags & CFLAG_NONE) != 0)
463
		return 0;
464
465
#ifdef WITH_OPENSSL
466
	evplen = EVP_CIPHER_CTX_iv_length(cc->evp);
467
	if (evplen == 0)
468
		return 0;
469
	else if (evplen < 0)
470
		return SSH_ERR_LIBCRYPTO_ERROR;
471
	if ((u_int)evplen != len)
472
		return SSH_ERR_INVALID_ARGUMENT;
473
	if (cipher_authlen(c)) {
474
		if (!EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN,
475
		   len, iv))
476
		       return SSH_ERR_LIBCRYPTO_ERROR;
477
	} else
478
		memcpy(iv, cc->evp->iv, len);
479
#endif
480
	return 0;
481
}
482
483
int
484
cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv)
485
{
486
#ifdef WITH_OPENSSL
487
	const struct sshcipher *c = cc->cipher;
488
 	int evplen = 0;
489
#endif
490
491
	if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
492
		return 0;
493
	if ((cc->cipher->flags & CFLAG_NONE) != 0)
494
		return 0;
495
496
#ifdef WITH_OPENSSL
497
	evplen = EVP_CIPHER_CTX_iv_length(cc->evp);
498
	if (evplen <= 0)
499
		return SSH_ERR_LIBCRYPTO_ERROR;
500
	if (cipher_authlen(c)) {
501
		/* XXX iv arg is const, but EVP_CIPHER_CTX_ctrl isn't */
502
		if (!EVP_CIPHER_CTX_ctrl(cc->evp,
503
		    EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv))
504
			return SSH_ERR_LIBCRYPTO_ERROR;
505
	} else
506
		memcpy(cc->evp->iv, iv, evplen);
507
#endif
508
	return 0;
509
}
510