diff options
Diffstat (limited to 'cipher.c')
-rw-r--r-- | cipher.c | 65 |
1 files changed, 57 insertions, 8 deletions
@@ -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. */ |
104 | char * | 110 | char * |
105 | cipher_alg_list(char sep) | 111 | cipher_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) | |||
142 | u_int | 150 | u_int |
143 | cipher_ivlen(const Cipher *c) | 151 | cipher_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 | ||
148 | u_int | 161 | u_int |
@@ -154,7 +167,7 @@ cipher_get_number(const Cipher *c) | |||
154 | u_int | 167 | u_int |
155 | cipher_is_cbc(const Cipher *c) | 168 | cipher_is_cbc(const Cipher *c) |
156 | { | 169 | { |
157 | return (c->cbc_mode); | 170 | return (c->flags & CFLAG_CBC) != 0; |
158 | } | 171 | } |
159 | 172 | ||
160 | u_int | 173 | u_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 | */ |
332 | void | 348 | void |
333 | cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src, | 349 | cipher_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 */ | ||
400 | int | ||
401 | cipher_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 | |||
377 | void | 413 | void |
378 | cipher_cleanup(CipherContext *cc) | 414 | cipher_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: |