summaryrefslogtreecommitdiff
path: root/cipher.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2013-11-21 14:12:23 +1100
committerDamien Miller <djm@mindrot.org>2013-11-21 14:12:23 +1100
commit0fde8acdad78a4d20cadae974376cc0165f645ee (patch)
tree6e6aa82b73163bcb412920050d98f82ca9f4e86e /cipher.c
parentfdb2306acdc3eb2bc46b6dfdaaf6005c650af22a (diff)
- djm@cvs.openbsd.org 2013/11/21 00:45:44
[Makefile.in PROTOCOL PROTOCOL.chacha20poly1305 authfile.c chacha.c] [chacha.h cipher-chachapoly.c cipher-chachapoly.h cipher.c cipher.h] [dh.c myproposal.h packet.c poly1305.c poly1305.h servconf.c ssh.1] [ssh.c ssh_config.5 sshd_config.5] Add a new protocol 2 transport cipher "chacha20-poly1305@openssh.com" that combines Daniel Bernstein's ChaCha20 stream cipher and Poly1305 MAC to build an authenticated encryption mode. Inspired by and similar to Adam Langley's proposal for TLS: http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-03 but differs in layout used for the MAC calculation and the use of a second ChaCha20 instance to separately encrypt packet lengths. Details are in the PROTOCOL.chacha20poly1305 file. Feedback markus@, naddy@; manpage bits Loganden Velvindron @ AfriNIC ok markus@ naddy@
Diffstat (limited to 'cipher.c')
-rw-r--r--cipher.c65
1 files changed, 57 insertions, 8 deletions
diff --git a/cipher.c b/cipher.c
index 54315f488..c4aec3923 100644
--- a/cipher.c
+++ b/cipher.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: cipher.c,v 1.90 2013/11/07 11:58:27 dtucker Exp $ */ 1/* $OpenBSD: cipher.c,v 1.91 2013/11/21 00:45:44 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -43,9 +43,11 @@
43 43
44#include <string.h> 44#include <string.h>
45#include <stdarg.h> 45#include <stdarg.h>
46#include <stdio.h>
46 47
47#include "xmalloc.h" 48#include "xmalloc.h"
48#include "log.h" 49#include "log.h"
50#include "misc.h"
49#include "cipher.h" 51#include "cipher.h"
50 52
51/* compatibility with old or broken OpenSSL versions */ 53/* compatibility with old or broken OpenSSL versions */
@@ -63,7 +65,9 @@ struct Cipher {
63 u_int iv_len; /* defaults to block_size */ 65 u_int iv_len; /* defaults to block_size */
64 u_int auth_len; 66 u_int auth_len;
65 u_int discard_len; 67 u_int discard_len;
66 u_int cbc_mode; 68 u_int flags;
69#define CFLAG_CBC (1<<0)
70#define CFLAG_CHACHAPOLY (1<<1)
67 const EVP_CIPHER *(*evptype)(void); 71 const EVP_CIPHER *(*evptype)(void);
68}; 72};
69 73
@@ -95,6 +99,8 @@ static const struct Cipher ciphers[] = {
95 { "aes256-gcm@openssh.com", 99 { "aes256-gcm@openssh.com",
96 SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm }, 100 SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm },
97#endif 101#endif
102 { "chacha20-poly1305@openssh.com",
103 SSH_CIPHER_SSH2, 8, 64, 0, 16, 0, CFLAG_CHACHAPOLY, NULL },
98 { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL } 104 { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL }
99}; 105};
100 106
@@ -102,7 +108,7 @@ static const struct Cipher ciphers[] = {
102 108
103/* Returns a list of supported ciphers separated by the specified char. */ 109/* Returns a list of supported ciphers separated by the specified char. */
104char * 110char *
105cipher_alg_list(char sep) 111cipher_alg_list(char sep, int auth_only)
106{ 112{
107 char *ret = NULL; 113 char *ret = NULL;
108 size_t nlen, rlen = 0; 114 size_t nlen, rlen = 0;
@@ -111,6 +117,8 @@ cipher_alg_list(char sep)
111 for (c = ciphers; c->name != NULL; c++) { 117 for (c = ciphers; c->name != NULL; c++) {
112 if (c->number != SSH_CIPHER_SSH2) 118 if (c->number != SSH_CIPHER_SSH2)
113 continue; 119 continue;
120 if (auth_only && c->auth_len == 0)
121 continue;
114 if (ret != NULL) 122 if (ret != NULL)
115 ret[rlen++] = sep; 123 ret[rlen++] = sep;
116 nlen = strlen(c->name); 124 nlen = strlen(c->name);
@@ -142,7 +150,12 @@ cipher_authlen(const Cipher *c)
142u_int 150u_int
143cipher_ivlen(const Cipher *c) 151cipher_ivlen(const Cipher *c)
144{ 152{
145 return (c->iv_len ? c->iv_len : c->block_size); 153 /*
154 * Default is cipher block size, except for chacha20+poly1305 that
155 * needs no IV. XXX make iv_len == -1 default?
156 */
157 return (c->iv_len != 0 || (c->flags & CFLAG_CHACHAPOLY) != 0) ?
158 c->iv_len : c->block_size;
146} 159}
147 160
148u_int 161u_int
@@ -154,7 +167,7 @@ cipher_get_number(const Cipher *c)
154u_int 167u_int
155cipher_is_cbc(const Cipher *c) 168cipher_is_cbc(const Cipher *c)
156{ 169{
157 return (c->cbc_mode); 170 return (c->flags & CFLAG_CBC) != 0;
158} 171}
159 172
160u_int 173u_int
@@ -274,8 +287,11 @@ cipher_init(CipherContext *cc, const Cipher *cipher,
274 ivlen, cipher->name); 287 ivlen, cipher->name);
275 cc->cipher = cipher; 288 cc->cipher = cipher;
276 289
290 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
291 chachapoly_init(&cc->cp_ctx, key, keylen);
292 return;
293 }
277 type = (*cipher->evptype)(); 294 type = (*cipher->evptype)();
278
279 EVP_CIPHER_CTX_init(&cc->evp); 295 EVP_CIPHER_CTX_init(&cc->evp);
280#ifdef SSH_OLD_EVP 296#ifdef SSH_OLD_EVP
281 if (type->key_len > 0 && type->key_len != keylen) { 297 if (type->key_len > 0 && type->key_len != keylen) {
@@ -330,9 +346,15 @@ cipher_init(CipherContext *cc, const Cipher *cipher,
330 * Both 'aadlen' and 'authlen' can be set to 0. 346 * Both 'aadlen' and 'authlen' can be set to 0.
331 */ 347 */
332void 348void
333cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src, 349cipher_crypt(CipherContext *cc, u_int seqnr, u_char *dest, const u_char *src,
334 u_int len, u_int aadlen, u_int authlen) 350 u_int len, u_int aadlen, u_int authlen)
335{ 351{
352 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
353 if (chachapoly_crypt(&cc->cp_ctx, seqnr, dest, src, len, aadlen,
354 authlen, cc->encrypt) != 0)
355 fatal("Decryption integrity check failed");
356 return;
357 }
336 if (authlen) { 358 if (authlen) {
337 u_char lastiv[1]; 359 u_char lastiv[1];
338 360
@@ -374,10 +396,26 @@ cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src,
374 } 396 }
375} 397}
376 398
399/* Extract the packet length, including any decryption necessary beforehand */
400int
401cipher_get_length(CipherContext *cc, u_int *plenp, u_int seqnr,
402 const u_char *cp, u_int len)
403{
404 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
405 return chachapoly_get_length(&cc->cp_ctx, plenp, seqnr,
406 cp, len);
407 if (len < 4)
408 return -1;
409 *plenp = get_u32(cp);
410 return 0;
411}
412
377void 413void
378cipher_cleanup(CipherContext *cc) 414cipher_cleanup(CipherContext *cc)
379{ 415{
380 if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0) 416 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
417 bzero(&cc->cp_ctx, sizeof(&cc->cp_ctx));
418 else if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0)
381 error("cipher_cleanup: EVP_CIPHER_CTX_cleanup failed"); 419 error("cipher_cleanup: EVP_CIPHER_CTX_cleanup failed");
382} 420}
383 421
@@ -417,6 +455,8 @@ cipher_get_keyiv_len(const CipherContext *cc)
417 455
418 if (c->number == SSH_CIPHER_3DES) 456 if (c->number == SSH_CIPHER_3DES)
419 ivlen = 24; 457 ivlen = 24;
458 else if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
459 ivlen = 0;
420 else 460 else
421 ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp); 461 ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp);
422 return (ivlen); 462 return (ivlen);
@@ -428,6 +468,12 @@ cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len)
428 const Cipher *c = cc->cipher; 468 const Cipher *c = cc->cipher;
429 int evplen; 469 int evplen;
430 470
471 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
472 if (len != 0)
473 fatal("%s: wrong iv length %d != %d", __func__, len, 0);
474 return;
475 }
476
431 switch (c->number) { 477 switch (c->number) {
432 case SSH_CIPHER_SSH2: 478 case SSH_CIPHER_SSH2:
433 case SSH_CIPHER_DES: 479 case SSH_CIPHER_DES:
@@ -464,6 +510,9 @@ cipher_set_keyiv(CipherContext *cc, u_char *iv)
464 const Cipher *c = cc->cipher; 510 const Cipher *c = cc->cipher;
465 int evplen = 0; 511 int evplen = 0;
466 512
513 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
514 return;
515
467 switch (c->number) { 516 switch (c->number) {
468 case SSH_CIPHER_SSH2: 517 case SSH_CIPHER_SSH2:
469 case SSH_CIPHER_DES: 518 case SSH_CIPHER_DES: