diff options
-rw-r--r-- | ChangeLog | 17 | ||||
-rw-r--r-- | Makefile.in | 4 | ||||
-rw-r--r-- | PROTOCOL | 7 | ||||
-rw-r--r-- | PROTOCOL.chacha20poly1305 | 105 | ||||
-rw-r--r-- | authfile.c | 6 | ||||
-rw-r--r-- | chacha.c | 219 | ||||
-rw-r--r-- | chacha.h | 35 | ||||
-rw-r--r-- | cipher-chachapoly.c | 114 | ||||
-rw-r--r-- | cipher-chachapoly.h | 41 | ||||
-rw-r--r-- | cipher.c | 65 | ||||
-rw-r--r-- | cipher.h | 11 | ||||
-rw-r--r-- | dh.c | 38 | ||||
-rw-r--r-- | myproposal.h | 3 | ||||
-rw-r--r-- | packet.c | 24 | ||||
-rw-r--r-- | poly1305.c | 158 | ||||
-rw-r--r-- | poly1305.h | 22 | ||||
-rw-r--r-- | servconf.c | 4 | ||||
-rw-r--r-- | ssh.1 | 6 | ||||
-rw-r--r-- | ssh.c | 6 | ||||
-rw-r--r-- | ssh_config.5 | 18 | ||||
-rw-r--r-- | sshd_config.5 | 18 |
21 files changed, 853 insertions, 68 deletions
@@ -19,6 +19,23 @@ | |||
19 | [canohost.c clientloop.c match.c readconf.c sftp.c] | 19 | [canohost.c clientloop.c match.c readconf.c sftp.c] |
20 | unsigned casts for ctype macros where neccessary | 20 | unsigned casts for ctype macros where neccessary |
21 | ok guenther millert markus | 21 | ok guenther millert markus |
22 | - djm@cvs.openbsd.org 2013/11/21 00:45:44 | ||
23 | [Makefile.in PROTOCOL PROTOCOL.chacha20poly1305 authfile.c chacha.c] | ||
24 | [chacha.h cipher-chachapoly.c cipher-chachapoly.h cipher.c cipher.h] | ||
25 | [dh.c myproposal.h packet.c poly1305.c poly1305.h servconf.c ssh.1] | ||
26 | [ssh.c ssh_config.5 sshd_config.5] Add a new protocol 2 transport | ||
27 | cipher "chacha20-poly1305@openssh.com" that combines Daniel | ||
28 | Bernstein's ChaCha20 stream cipher and Poly1305 MAC to build an | ||
29 | authenticated encryption mode. | ||
30 | |||
31 | Inspired by and similar to Adam Langley's proposal for TLS: | ||
32 | http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-03 | ||
33 | but differs in layout used for the MAC calculation and the use of a | ||
34 | second ChaCha20 instance to separately encrypt packet lengths. | ||
35 | Details are in the PROTOCOL.chacha20poly1305 file. | ||
36 | |||
37 | Feedback markus@, naddy@; manpage bits Loganden Velvindron @ AfriNIC | ||
38 | ok markus@ naddy@ | ||
22 | 39 | ||
23 | 20131110 | 40 | 20131110 |
24 | - (dtucker) [regress/keytype.sh] Populate ECDSA key types to be tested by | 41 | - (dtucker) [regress/keytype.sh] Populate ECDSA key types to be tested by |
diff --git a/Makefile.in b/Makefile.in index e1c68c00b..91f39d4f3 100644 --- a/Makefile.in +++ b/Makefile.in | |||
@@ -1,4 +1,4 @@ | |||
1 | # $Id: Makefile.in,v 1.344 2013/11/08 13:17:41 dtucker Exp $ | 1 | # $Id: Makefile.in,v 1.345 2013/11/21 03:12:23 djm Exp $ |
2 | 2 | ||
3 | # uncomment if you run a non bourne compatable shell. Ie. csh | 3 | # uncomment if you run a non bourne compatable shell. Ie. csh |
4 | #SHELL = @SH@ | 4 | #SHELL = @SH@ |
@@ -74,7 +74,7 @@ LIBSSH_OBJS=authfd.o authfile.o bufaux.o bufbn.o buffer.o \ | |||
74 | kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \ | 74 | kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \ |
75 | msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ | 75 | msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ |
76 | jpake.o schnorr.o ssh-pkcs11.o krl.o smult_curve25519_ref.o \ | 76 | jpake.o schnorr.o ssh-pkcs11.o krl.o smult_curve25519_ref.o \ |
77 | kexc25519.o kexc25519c.o | 77 | kexc25519.o kexc25519c.o poly1305.o chacha.o cipher-chachapoly.o |
78 | 78 | ||
79 | SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ | 79 | SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ |
80 | sshconnect.o sshconnect1.o sshconnect2.o mux.o \ | 80 | sshconnect.o sshconnect1.o sshconnect2.o mux.o \ |
@@ -91,6 +91,11 @@ an MAC algorithm. Additionally, if AES-GCM is selected as the cipher | |||
91 | the exchanged MAC algorithms are ignored and there doesn't have to be | 91 | the exchanged MAC algorithms are ignored and there doesn't have to be |
92 | a matching MAC. | 92 | a matching MAC. |
93 | 93 | ||
94 | 1.7 transport: chacha20-poly1305@openssh.com authenticated encryption | ||
95 | |||
96 | OpenSSH supports authenticated encryption using ChaCha20 and Poly1305 | ||
97 | as described in PROTOCOL.chacha20poly1305. | ||
98 | |||
94 | 2. Connection protocol changes | 99 | 2. Connection protocol changes |
95 | 100 | ||
96 | 2.1. connection: Channel write close extension "eow@openssh.com" | 101 | 2.1. connection: Channel write close extension "eow@openssh.com" |
@@ -345,4 +350,4 @@ respond with a SSH_FXP_STATUS message. | |||
345 | This extension is advertised in the SSH_FXP_VERSION hello with version | 350 | This extension is advertised in the SSH_FXP_VERSION hello with version |
346 | "1". | 351 | "1". |
347 | 352 | ||
348 | $OpenBSD: PROTOCOL,v 1.21 2013/10/17 00:30:13 djm Exp $ | 353 | $OpenBSD: PROTOCOL,v 1.22 2013/11/21 00:45:43 djm Exp $ |
diff --git a/PROTOCOL.chacha20poly1305 b/PROTOCOL.chacha20poly1305 new file mode 100644 index 000000000..c4b723aff --- /dev/null +++ b/PROTOCOL.chacha20poly1305 | |||
@@ -0,0 +1,105 @@ | |||
1 | This document describes the chacha20-poly1305@openssh.com authenticated | ||
2 | encryption cipher supported by OpenSSH. | ||
3 | |||
4 | Background | ||
5 | ---------- | ||
6 | |||
7 | ChaCha20 is a stream cipher designed by Daniel Bernstein and described | ||
8 | in [1]. It operates by permuting 128 fixed bits, 128 or 256 bits of key, | ||
9 | a 64 bit nonce and a 64 bit counter into 64 bytes of output. This output | ||
10 | is used as a keystream, with any unused bytes simply discarded. | ||
11 | |||
12 | Poly1305[2], also by Daniel Bernstein, is a one-time Carter-Wegman MAC | ||
13 | that computes a 128 bit integrity tag given a message and a single-use | ||
14 | 256 bit secret key. | ||
15 | |||
16 | The chacha20-poly1305@openssh.com combines these two primitives into an | ||
17 | authenticated encryption mode. The construction used is based on that | ||
18 | proposed for TLS by Adam Langley in [3], but differs in the layout of | ||
19 | data passed to the MAC and in the addition of encyption of the packet | ||
20 | lengths. | ||
21 | |||
22 | Negotiation | ||
23 | ----------- | ||
24 | |||
25 | The chacha20-poly1305@openssh.com offers both encryption and | ||
26 | authentication. As such, no separate MAC is required. If the | ||
27 | chacha20-poly1305@openssh.com cipher is selected in key exchange, | ||
28 | the offered MAC algorithms are ignored and no MAC is required to be | ||
29 | negotiated. | ||
30 | |||
31 | Detailed Construction | ||
32 | --------------------- | ||
33 | |||
34 | The chacha20-poly1305@openssh.com cipher requires 512 bits of key | ||
35 | material as output from the SSH key exchange. This forms two 256 bit | ||
36 | keys (K_1 and K_2), used by two separate instances of chacha20. | ||
37 | |||
38 | The instance keyed by K_1 is a stream cipher that is used only | ||
39 | to encrypt the 4 byte packet length field. The second instance, | ||
40 | keyed by K_2, is used in conjunction with poly1305 to build an AEAD | ||
41 | (Authenticated Encryption with Associated Data) that is used to encrypt | ||
42 | and authenticate the entire packet. | ||
43 | |||
44 | Two separate cipher instances are used here so as to keep the packet | ||
45 | lengths confidential but not create an oracle for the packet payload | ||
46 | cipher by decrypting and using the packet length prior to checking | ||
47 | the MAC. By using an independently-keyed cipher instance to encrypt the | ||
48 | length, an active attacker seeking to exploit the packet input handling | ||
49 | as a decryption oracle can learn nothing about the payload contents or | ||
50 | its MAC (assuming key derivation, ChaCha20 and Poly1306 are secure). | ||
51 | |||
52 | The AEAD is constructed as follows: for each packet, generate a Poly1305 | ||
53 | key by taking the first 256 bits of ChaCha20 stream output generated | ||
54 | using K_2, an IV consisting of the packet sequence number encoded as an | ||
55 | uint64 under the SSH wire encoding rules and a ChaCha20 block counter of | ||
56 | zero. The K_2 ChaCha20 block counter is then set to the little-endian | ||
57 | encoding of 1 (i.e. {1, 0, 0, 0, 0, 0, 0, 0}) and this instance is used | ||
58 | for encryption of the packet payload. | ||
59 | |||
60 | Packet Handling | ||
61 | --------------- | ||
62 | |||
63 | When receiving a packet, the length must be decrypted first. When 4 | ||
64 | bytes of ciphertext length have been received, they may be decrypted | ||
65 | using the K_1 key, a nonce consisting of the packet sequence number | ||
66 | encoded as a uint64 under the usual SSH wire encoding and a zero block | ||
67 | counter to obtain the plaintext length. | ||
68 | |||
69 | Once the entire packet has been received, the MAC MUST be checked | ||
70 | before decryption. A per-packet Poly1305 key is generated as described | ||
71 | above and the MAC tag calculated using Poly1305 with this key over the | ||
72 | ciphertext of the packet length and the payload together. The calculated | ||
73 | MAC is then compared in constant time with the one appended to the | ||
74 | packet and the packet decrypted using ChaCha20 as described above (with | ||
75 | K_2, the packet sequence number as nonce and a starting block counter of | ||
76 | 1). | ||
77 | |||
78 | To send a packet, first encode the 4 byte length and encrypt it using | ||
79 | K_1. Encrypt the packet payload (using K_2) and append it to the | ||
80 | encrypted length. Finally, calculate a MAC tag and append it. | ||
81 | |||
82 | Rekeying | ||
83 | -------- | ||
84 | |||
85 | ChaCha20 must never reuse a {key, nonce} for encryption nor may it be | ||
86 | used to encrypt more than 2^70 bytes under the same {key, nonce}. The | ||
87 | SSH Transport protocol (RFC4253) recommends a far more conservative | ||
88 | rekeying every 1GB of data sent or received. If this recommendation | ||
89 | is followed, then chacha20-poly1305@openssh.com requires no special | ||
90 | handling in this area. | ||
91 | |||
92 | References | ||
93 | ---------- | ||
94 | |||
95 | [1] "ChaCha, a variant of Salsa20", Daniel Bernstein | ||
96 | http://cr.yp.to/chacha/chacha-20080128.pdf | ||
97 | |||
98 | [2] "The Poly1305-AES message-authentication code", Daniel Bernstein | ||
99 | http://cr.yp.to/mac/poly1305-20050329.pdf | ||
100 | |||
101 | [3] "ChaCha20 and Poly1305 based Cipher Suites for TLS", Adam Langley | ||
102 | http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-03 | ||
103 | |||
104 | $OpenBSD: PROTOCOL.chacha20poly1305,v 1.1 2013/11/21 00:45:43 djm Exp $ | ||
105 | |||
diff --git a/authfile.c b/authfile.c index 63ae16bbd..d0c1089eb 100644 --- a/authfile.c +++ b/authfile.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: authfile.c,v 1.97 2013/05/17 00:13:13 djm Exp $ */ | 1 | /* $OpenBSD: authfile.c,v 1.98 2013/11/21 00:45:43 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 |
@@ -149,7 +149,7 @@ key_private_rsa1_to_blob(Key *key, Buffer *blob, const char *passphrase, | |||
149 | 149 | ||
150 | cipher_set_key_string(&ciphercontext, cipher, passphrase, | 150 | cipher_set_key_string(&ciphercontext, cipher, passphrase, |
151 | CIPHER_ENCRYPT); | 151 | CIPHER_ENCRYPT); |
152 | cipher_crypt(&ciphercontext, cp, | 152 | cipher_crypt(&ciphercontext, 0, cp, |
153 | buffer_ptr(&buffer), buffer_len(&buffer), 0, 0); | 153 | buffer_ptr(&buffer), buffer_len(&buffer), 0, 0); |
154 | cipher_cleanup(&ciphercontext); | 154 | cipher_cleanup(&ciphercontext); |
155 | memset(&ciphercontext, 0, sizeof(ciphercontext)); | 155 | memset(&ciphercontext, 0, sizeof(ciphercontext)); |
@@ -473,7 +473,7 @@ key_parse_private_rsa1(Buffer *blob, const char *passphrase, char **commentp) | |||
473 | /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ | 473 | /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ |
474 | cipher_set_key_string(&ciphercontext, cipher, passphrase, | 474 | cipher_set_key_string(&ciphercontext, cipher, passphrase, |
475 | CIPHER_DECRYPT); | 475 | CIPHER_DECRYPT); |
476 | cipher_crypt(&ciphercontext, cp, | 476 | cipher_crypt(&ciphercontext, 0, cp, |
477 | buffer_ptr(©), buffer_len(©), 0, 0); | 477 | buffer_ptr(©), buffer_len(©), 0, 0); |
478 | cipher_cleanup(&ciphercontext); | 478 | cipher_cleanup(&ciphercontext); |
479 | memset(&ciphercontext, 0, sizeof(ciphercontext)); | 479 | memset(&ciphercontext, 0, sizeof(ciphercontext)); |
diff --git a/chacha.c b/chacha.c new file mode 100644 index 000000000..a84c25ea8 --- /dev/null +++ b/chacha.c | |||
@@ -0,0 +1,219 @@ | |||
1 | /* | ||
2 | chacha-merged.c version 20080118 | ||
3 | D. J. Bernstein | ||
4 | Public domain. | ||
5 | */ | ||
6 | |||
7 | #include "includes.h" | ||
8 | |||
9 | #include "chacha.h" | ||
10 | |||
11 | /* $OpenBSD: chacha.c,v 1.1 2013/11/21 00:45:44 djm Exp $ */ | ||
12 | |||
13 | typedef unsigned char u8; | ||
14 | typedef unsigned int u32; | ||
15 | |||
16 | typedef struct chacha_ctx chacha_ctx; | ||
17 | |||
18 | #define U8C(v) (v##U) | ||
19 | #define U32C(v) (v##U) | ||
20 | |||
21 | #define U8V(v) ((u8)(v) & U8C(0xFF)) | ||
22 | #define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF)) | ||
23 | |||
24 | #define ROTL32(v, n) \ | ||
25 | (U32V((v) << (n)) | ((v) >> (32 - (n)))) | ||
26 | |||
27 | #define U8TO32_LITTLE(p) \ | ||
28 | (((u32)((p)[0]) ) | \ | ||
29 | ((u32)((p)[1]) << 8) | \ | ||
30 | ((u32)((p)[2]) << 16) | \ | ||
31 | ((u32)((p)[3]) << 24)) | ||
32 | |||
33 | #define U32TO8_LITTLE(p, v) \ | ||
34 | do { \ | ||
35 | (p)[0] = U8V((v) ); \ | ||
36 | (p)[1] = U8V((v) >> 8); \ | ||
37 | (p)[2] = U8V((v) >> 16); \ | ||
38 | (p)[3] = U8V((v) >> 24); \ | ||
39 | } while (0) | ||
40 | |||
41 | #define ROTATE(v,c) (ROTL32(v,c)) | ||
42 | #define XOR(v,w) ((v) ^ (w)) | ||
43 | #define PLUS(v,w) (U32V((v) + (w))) | ||
44 | #define PLUSONE(v) (PLUS((v),1)) | ||
45 | |||
46 | #define QUARTERROUND(a,b,c,d) \ | ||
47 | a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \ | ||
48 | c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \ | ||
49 | a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \ | ||
50 | c = PLUS(c,d); b = ROTATE(XOR(b,c), 7); | ||
51 | |||
52 | static const char sigma[16] = "expand 32-byte k"; | ||
53 | static const char tau[16] = "expand 16-byte k"; | ||
54 | |||
55 | void | ||
56 | chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits) | ||
57 | { | ||
58 | const char *constants; | ||
59 | |||
60 | x->input[4] = U8TO32_LITTLE(k + 0); | ||
61 | x->input[5] = U8TO32_LITTLE(k + 4); | ||
62 | x->input[6] = U8TO32_LITTLE(k + 8); | ||
63 | x->input[7] = U8TO32_LITTLE(k + 12); | ||
64 | if (kbits == 256) { /* recommended */ | ||
65 | k += 16; | ||
66 | constants = sigma; | ||
67 | } else { /* kbits == 128 */ | ||
68 | constants = tau; | ||
69 | } | ||
70 | x->input[8] = U8TO32_LITTLE(k + 0); | ||
71 | x->input[9] = U8TO32_LITTLE(k + 4); | ||
72 | x->input[10] = U8TO32_LITTLE(k + 8); | ||
73 | x->input[11] = U8TO32_LITTLE(k + 12); | ||
74 | x->input[0] = U8TO32_LITTLE(constants + 0); | ||
75 | x->input[1] = U8TO32_LITTLE(constants + 4); | ||
76 | x->input[2] = U8TO32_LITTLE(constants + 8); | ||
77 | x->input[3] = U8TO32_LITTLE(constants + 12); | ||
78 | } | ||
79 | |||
80 | void | ||
81 | chacha_ivsetup(chacha_ctx *x, const u8 *iv, const u8 *counter) | ||
82 | { | ||
83 | x->input[12] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 0); | ||
84 | x->input[13] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 4); | ||
85 | x->input[14] = U8TO32_LITTLE(iv + 0); | ||
86 | x->input[15] = U8TO32_LITTLE(iv + 4); | ||
87 | } | ||
88 | |||
89 | void | ||
90 | chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes) | ||
91 | { | ||
92 | u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; | ||
93 | u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15; | ||
94 | u8 *ctarget = NULL; | ||
95 | u8 tmp[64]; | ||
96 | u_int i; | ||
97 | |||
98 | if (!bytes) return; | ||
99 | |||
100 | j0 = x->input[0]; | ||
101 | j1 = x->input[1]; | ||
102 | j2 = x->input[2]; | ||
103 | j3 = x->input[3]; | ||
104 | j4 = x->input[4]; | ||
105 | j5 = x->input[5]; | ||
106 | j6 = x->input[6]; | ||
107 | j7 = x->input[7]; | ||
108 | j8 = x->input[8]; | ||
109 | j9 = x->input[9]; | ||
110 | j10 = x->input[10]; | ||
111 | j11 = x->input[11]; | ||
112 | j12 = x->input[12]; | ||
113 | j13 = x->input[13]; | ||
114 | j14 = x->input[14]; | ||
115 | j15 = x->input[15]; | ||
116 | |||
117 | for (;;) { | ||
118 | if (bytes < 64) { | ||
119 | for (i = 0;i < bytes;++i) tmp[i] = m[i]; | ||
120 | m = tmp; | ||
121 | ctarget = c; | ||
122 | c = tmp; | ||
123 | } | ||
124 | x0 = j0; | ||
125 | x1 = j1; | ||
126 | x2 = j2; | ||
127 | x3 = j3; | ||
128 | x4 = j4; | ||
129 | x5 = j5; | ||
130 | x6 = j6; | ||
131 | x7 = j7; | ||
132 | x8 = j8; | ||
133 | x9 = j9; | ||
134 | x10 = j10; | ||
135 | x11 = j11; | ||
136 | x12 = j12; | ||
137 | x13 = j13; | ||
138 | x14 = j14; | ||
139 | x15 = j15; | ||
140 | for (i = 20;i > 0;i -= 2) { | ||
141 | QUARTERROUND( x0, x4, x8,x12) | ||
142 | QUARTERROUND( x1, x5, x9,x13) | ||
143 | QUARTERROUND( x2, x6,x10,x14) | ||
144 | QUARTERROUND( x3, x7,x11,x15) | ||
145 | QUARTERROUND( x0, x5,x10,x15) | ||
146 | QUARTERROUND( x1, x6,x11,x12) | ||
147 | QUARTERROUND( x2, x7, x8,x13) | ||
148 | QUARTERROUND( x3, x4, x9,x14) | ||
149 | } | ||
150 | x0 = PLUS(x0,j0); | ||
151 | x1 = PLUS(x1,j1); | ||
152 | x2 = PLUS(x2,j2); | ||
153 | x3 = PLUS(x3,j3); | ||
154 | x4 = PLUS(x4,j4); | ||
155 | x5 = PLUS(x5,j5); | ||
156 | x6 = PLUS(x6,j6); | ||
157 | x7 = PLUS(x7,j7); | ||
158 | x8 = PLUS(x8,j8); | ||
159 | x9 = PLUS(x9,j9); | ||
160 | x10 = PLUS(x10,j10); | ||
161 | x11 = PLUS(x11,j11); | ||
162 | x12 = PLUS(x12,j12); | ||
163 | x13 = PLUS(x13,j13); | ||
164 | x14 = PLUS(x14,j14); | ||
165 | x15 = PLUS(x15,j15); | ||
166 | |||
167 | x0 = XOR(x0,U8TO32_LITTLE(m + 0)); | ||
168 | x1 = XOR(x1,U8TO32_LITTLE(m + 4)); | ||
169 | x2 = XOR(x2,U8TO32_LITTLE(m + 8)); | ||
170 | x3 = XOR(x3,U8TO32_LITTLE(m + 12)); | ||
171 | x4 = XOR(x4,U8TO32_LITTLE(m + 16)); | ||
172 | x5 = XOR(x5,U8TO32_LITTLE(m + 20)); | ||
173 | x6 = XOR(x6,U8TO32_LITTLE(m + 24)); | ||
174 | x7 = XOR(x7,U8TO32_LITTLE(m + 28)); | ||
175 | x8 = XOR(x8,U8TO32_LITTLE(m + 32)); | ||
176 | x9 = XOR(x9,U8TO32_LITTLE(m + 36)); | ||
177 | x10 = XOR(x10,U8TO32_LITTLE(m + 40)); | ||
178 | x11 = XOR(x11,U8TO32_LITTLE(m + 44)); | ||
179 | x12 = XOR(x12,U8TO32_LITTLE(m + 48)); | ||
180 | x13 = XOR(x13,U8TO32_LITTLE(m + 52)); | ||
181 | x14 = XOR(x14,U8TO32_LITTLE(m + 56)); | ||
182 | x15 = XOR(x15,U8TO32_LITTLE(m + 60)); | ||
183 | |||
184 | j12 = PLUSONE(j12); | ||
185 | if (!j12) { | ||
186 | j13 = PLUSONE(j13); | ||
187 | /* stopping at 2^70 bytes per nonce is user's responsibility */ | ||
188 | } | ||
189 | |||
190 | U32TO8_LITTLE(c + 0,x0); | ||
191 | U32TO8_LITTLE(c + 4,x1); | ||
192 | U32TO8_LITTLE(c + 8,x2); | ||
193 | U32TO8_LITTLE(c + 12,x3); | ||
194 | U32TO8_LITTLE(c + 16,x4); | ||
195 | U32TO8_LITTLE(c + 20,x5); | ||
196 | U32TO8_LITTLE(c + 24,x6); | ||
197 | U32TO8_LITTLE(c + 28,x7); | ||
198 | U32TO8_LITTLE(c + 32,x8); | ||
199 | U32TO8_LITTLE(c + 36,x9); | ||
200 | U32TO8_LITTLE(c + 40,x10); | ||
201 | U32TO8_LITTLE(c + 44,x11); | ||
202 | U32TO8_LITTLE(c + 48,x12); | ||
203 | U32TO8_LITTLE(c + 52,x13); | ||
204 | U32TO8_LITTLE(c + 56,x14); | ||
205 | U32TO8_LITTLE(c + 60,x15); | ||
206 | |||
207 | if (bytes <= 64) { | ||
208 | if (bytes < 64) { | ||
209 | for (i = 0;i < bytes;++i) ctarget[i] = c[i]; | ||
210 | } | ||
211 | x->input[12] = j12; | ||
212 | x->input[13] = j13; | ||
213 | return; | ||
214 | } | ||
215 | bytes -= 64; | ||
216 | c += 64; | ||
217 | m += 64; | ||
218 | } | ||
219 | } | ||
diff --git a/chacha.h b/chacha.h new file mode 100644 index 000000000..4ef42cc70 --- /dev/null +++ b/chacha.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* $OpenBSD: chacha.h,v 1.1 2013/11/21 00:45:44 djm Exp $ */ | ||
2 | |||
3 | /* | ||
4 | chacha-merged.c version 20080118 | ||
5 | D. J. Bernstein | ||
6 | Public domain. | ||
7 | */ | ||
8 | |||
9 | #ifndef CHACHA_H | ||
10 | #define CHACHA_H | ||
11 | |||
12 | #include <sys/types.h> | ||
13 | |||
14 | struct chacha_ctx { | ||
15 | u_int input[16]; | ||
16 | }; | ||
17 | |||
18 | #define CHACHA_MINKEYLEN 16 | ||
19 | #define CHACHA_NONCELEN 8 | ||
20 | #define CHACHA_CTRLEN 8 | ||
21 | #define CHACHA_STATELEN (CHACHA_NONCELEN+CHACHA_CTRLEN) | ||
22 | #define CHACHA_BLOCKLEN 64 | ||
23 | |||
24 | void chacha_keysetup(struct chacha_ctx *x, const u_char *k, u_int kbits) | ||
25 | __attribute__((__bounded__(__minbytes__, 2, CHACHA_MINKEYLEN))); | ||
26 | void chacha_ivsetup(struct chacha_ctx *x, const u_char *iv, const u_char *ctr) | ||
27 | __attribute__((__bounded__(__minbytes__, 2, CHACHA_NONCELEN))) | ||
28 | __attribute__((__bounded__(__minbytes__, 3, CHACHA_CTRLEN))); | ||
29 | void chacha_encrypt_bytes(struct chacha_ctx *x, const u_char *m, | ||
30 | u_char *c, u_int bytes) | ||
31 | __attribute__((__bounded__(__buffer__, 2, 4))) | ||
32 | __attribute__((__bounded__(__buffer__, 3, 4))); | ||
33 | |||
34 | #endif /* CHACHA_H */ | ||
35 | |||
diff --git a/cipher-chachapoly.c b/cipher-chachapoly.c new file mode 100644 index 000000000..20628ab5d --- /dev/null +++ b/cipher-chachapoly.c | |||
@@ -0,0 +1,114 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 Damien Miller <djm@mindrot.org> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | /* $OpenBSD: cipher-chachapoly.c,v 1.2 2013/11/21 02:50:00 djm Exp $ */ | ||
18 | |||
19 | #include "includes.h" | ||
20 | |||
21 | #include <sys/types.h> | ||
22 | #include <stdarg.h> /* needed for log.h */ | ||
23 | #include <string.h> | ||
24 | #include <stdio.h> /* needed for misc.h */ | ||
25 | |||
26 | #include "log.h" | ||
27 | #include "misc.h" | ||
28 | #include "cipher-chachapoly.h" | ||
29 | |||
30 | void chachapoly_init(struct chachapoly_ctx *ctx, | ||
31 | const u_char *key, u_int keylen) | ||
32 | { | ||
33 | if (keylen != (32 + 32)) /* 2 x 256 bit keys */ | ||
34 | fatal("%s: invalid keylen %u", __func__, keylen); | ||
35 | chacha_keysetup(&ctx->main_ctx, key, 256); | ||
36 | chacha_keysetup(&ctx->header_ctx, key + 32, 256); | ||
37 | } | ||
38 | |||
39 | /* | ||
40 | * chachapoly_crypt() operates as following: | ||
41 | * Copy 'aadlen' bytes (without en/decryption) from 'src' to 'dest'. | ||
42 | * Theses bytes are treated as additional authenticated data. | ||
43 | * En/Decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'. | ||
44 | * Use POLY1305_TAGLEN bytes at offset 'len'+'aadlen' as the | ||
45 | * authentication tag. | ||
46 | * This tag is written on encryption and verified on decryption. | ||
47 | * Both 'aadlen' and 'authlen' can be set to 0. | ||
48 | */ | ||
49 | int | ||
50 | chachapoly_crypt(struct chachapoly_ctx *ctx, u_int seqnr, u_char *dest, | ||
51 | const u_char *src, u_int len, u_int aadlen, u_int authlen, int do_encrypt) | ||
52 | { | ||
53 | u_char seqbuf[8]; | ||
54 | u_char one[8] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* NB. little-endian */ | ||
55 | u_char expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN]; | ||
56 | int r = -1; | ||
57 | |||
58 | /* | ||
59 | * Run ChaCha20 once to generate the Poly1305 key. The IV is the | ||
60 | * packet sequence number. | ||
61 | */ | ||
62 | bzero(poly_key, sizeof(poly_key)); | ||
63 | put_u64(seqbuf, seqnr); | ||
64 | chacha_ivsetup(&ctx->main_ctx, seqbuf, NULL); | ||
65 | chacha_encrypt_bytes(&ctx->main_ctx, | ||
66 | poly_key, poly_key, sizeof(poly_key)); | ||
67 | /* Set Chacha's block counter to 1 */ | ||
68 | chacha_ivsetup(&ctx->main_ctx, seqbuf, one); | ||
69 | |||
70 | /* If decrypting, check tag before anything else */ | ||
71 | if (!do_encrypt) { | ||
72 | const u_char *tag = src + aadlen + len; | ||
73 | |||
74 | poly1305_auth(expected_tag, src, aadlen + len, poly_key); | ||
75 | if (timingsafe_bcmp(expected_tag, tag, POLY1305_TAGLEN) != 0) | ||
76 | goto out; | ||
77 | } | ||
78 | /* Crypt additional data */ | ||
79 | if (aadlen) { | ||
80 | chacha_ivsetup(&ctx->header_ctx, seqbuf, NULL); | ||
81 | chacha_encrypt_bytes(&ctx->header_ctx, src, dest, aadlen); | ||
82 | } | ||
83 | chacha_encrypt_bytes(&ctx->main_ctx, src + aadlen, | ||
84 | dest + aadlen, len); | ||
85 | |||
86 | /* If encrypting, calculate and append tag */ | ||
87 | if (do_encrypt) { | ||
88 | poly1305_auth(dest + aadlen + len, dest, aadlen + len, | ||
89 | poly_key); | ||
90 | } | ||
91 | r = 0; | ||
92 | |||
93 | out: | ||
94 | bzero(expected_tag, sizeof(expected_tag)); | ||
95 | bzero(seqbuf, sizeof(seqbuf)); | ||
96 | bzero(poly_key, sizeof(poly_key)); | ||
97 | return r; | ||
98 | } | ||
99 | |||
100 | int | ||
101 | chachapoly_get_length(struct chachapoly_ctx *ctx, | ||
102 | u_int *plenp, u_int seqnr, const u_char *cp, u_int len) | ||
103 | { | ||
104 | u_char buf[4], seqbuf[8]; | ||
105 | |||
106 | if (len < 4) | ||
107 | return -1; /* Insufficient length */ | ||
108 | put_u64(seqbuf, seqnr); | ||
109 | chacha_ivsetup(&ctx->header_ctx, seqbuf, NULL); | ||
110 | chacha_encrypt_bytes(&ctx->header_ctx, cp, buf, 4); | ||
111 | *plenp = get_u32(buf); | ||
112 | return 0; | ||
113 | } | ||
114 | |||
diff --git a/cipher-chachapoly.h b/cipher-chachapoly.h new file mode 100644 index 000000000..1628693b2 --- /dev/null +++ b/cipher-chachapoly.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /* $OpenBSD: cipher-chachapoly.h,v 1.1 2013/11/21 00:45:44 djm Exp $ */ | ||
2 | |||
3 | /* | ||
4 | * Copyright (c) Damien Miller 2013 <djm@mindrot.org> | ||
5 | * | ||
6 | * Permission to use, copy, modify, and distribute this software for any | ||
7 | * purpose with or without fee is hereby granted, provided that the above | ||
8 | * copyright notice and this permission notice appear in all copies. | ||
9 | * | ||
10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
17 | */ | ||
18 | #ifndef CHACHA_POLY_AEAD_H | ||
19 | #define CHACHA_POLY_AEAD_H | ||
20 | |||
21 | #include <sys/types.h> | ||
22 | #include "chacha.h" | ||
23 | #include "poly1305.h" | ||
24 | |||
25 | #define CHACHA_KEYLEN 32 /* Only 256 bit keys used here */ | ||
26 | |||
27 | struct chachapoly_ctx { | ||
28 | struct chacha_ctx main_ctx, header_ctx; | ||
29 | }; | ||
30 | |||
31 | void chachapoly_init(struct chachapoly_ctx *cpctx, | ||
32 | const u_char *key, u_int keylen) | ||
33 | __attribute__((__bounded__(__buffer__, 2, 3))); | ||
34 | int chachapoly_crypt(struct chachapoly_ctx *cpctx, u_int seqnr, | ||
35 | u_char *dest, const u_char *src, u_int len, u_int aadlen, u_int authlen, | ||
36 | int do_encrypt); | ||
37 | int chachapoly_get_length(struct chachapoly_ctx *cpctx, | ||
38 | u_int *plenp, u_int seqnr, const u_char *cp, u_int len) | ||
39 | __attribute__((__bounded__(__buffer__, 4, 5))); | ||
40 | |||
41 | #endif /* CHACHA_POLY_AEAD_H */ | ||
@@ -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: |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: cipher.h,v 1.41 2013/11/07 11:58:27 dtucker Exp $ */ | 1 | /* $OpenBSD: cipher.h,v 1.42 2013/11/21 00:45:44 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -38,6 +38,8 @@ | |||
38 | #define CIPHER_H | 38 | #define CIPHER_H |
39 | 39 | ||
40 | #include <openssl/evp.h> | 40 | #include <openssl/evp.h> |
41 | #include "cipher-chachapoly.h" | ||
42 | |||
41 | /* | 43 | /* |
42 | * Cipher types for SSH-1. New types can be added, but old types should not | 44 | * Cipher types for SSH-1. New types can be added, but old types should not |
43 | * be removed for compatibility. The maximum allowed value is 31. | 45 | * be removed for compatibility. The maximum allowed value is 31. |
@@ -66,6 +68,7 @@ struct CipherContext { | |||
66 | int plaintext; | 68 | int plaintext; |
67 | int encrypt; | 69 | int encrypt; |
68 | EVP_CIPHER_CTX evp; | 70 | EVP_CIPHER_CTX evp; |
71 | struct chachapoly_ctx cp_ctx; /* XXX union with evp? */ | ||
69 | const Cipher *cipher; | 72 | const Cipher *cipher; |
70 | }; | 73 | }; |
71 | 74 | ||
@@ -75,11 +78,13 @@ const Cipher *cipher_by_number(int); | |||
75 | int cipher_number(const char *); | 78 | int cipher_number(const char *); |
76 | char *cipher_name(int); | 79 | char *cipher_name(int); |
77 | int ciphers_valid(const char *); | 80 | int ciphers_valid(const char *); |
78 | char *cipher_alg_list(char); | 81 | char *cipher_alg_list(char, int); |
79 | void cipher_init(CipherContext *, const Cipher *, const u_char *, u_int, | 82 | void cipher_init(CipherContext *, const Cipher *, const u_char *, u_int, |
80 | const u_char *, u_int, int); | 83 | const u_char *, u_int, int); |
81 | void cipher_crypt(CipherContext *, u_char *, const u_char *, | 84 | void cipher_crypt(CipherContext *, u_int, u_char *, const u_char *, |
82 | u_int, u_int, u_int); | 85 | u_int, u_int, u_int); |
86 | int cipher_get_length(CipherContext *, u_int *, u_int, | ||
87 | const u_char *, u_int); | ||
83 | void cipher_cleanup(CipherContext *); | 88 | void cipher_cleanup(CipherContext *); |
84 | void cipher_set_key_string(CipherContext *, const Cipher *, const char *, int); | 89 | void cipher_set_key_string(CipherContext *, const Cipher *, const char *, int); |
85 | u_int cipher_blocksize(const Cipher *); | 90 | u_int cipher_blocksize(const Cipher *); |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: dh.c,v 1.52 2013/10/08 11:42:13 dtucker Exp $ */ | 1 | /* $OpenBSD: dh.c,v 1.53 2013/11/21 00:45:44 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Niels Provos. All rights reserved. | 3 | * Copyright (c) 2000 Niels Provos. All rights reserved. |
4 | * | 4 | * |
@@ -254,33 +254,19 @@ dh_pub_is_valid(DH *dh, BIGNUM *dh_pub) | |||
254 | void | 254 | void |
255 | dh_gen_key(DH *dh, int need) | 255 | dh_gen_key(DH *dh, int need) |
256 | { | 256 | { |
257 | int i, bits_set, tries = 0; | 257 | int pbits; |
258 | 258 | ||
259 | if (need < 0) | 259 | if (need <= 0) |
260 | fatal("dh_gen_key: need < 0"); | 260 | fatal("%s: need <= 0", __func__); |
261 | if (dh->p == NULL) | 261 | if (dh->p == NULL) |
262 | fatal("dh_gen_key: dh->p == NULL"); | 262 | fatal("%s: dh->p == NULL", __func__); |
263 | if (need > INT_MAX / 2 || 2 * need >= BN_num_bits(dh->p)) | 263 | if ((pbits = BN_num_bits(dh->p)) <= 0) |
264 | fatal("dh_gen_key: group too small: %d (2*need %d)", | 264 | fatal("%s: bits(p) <= 0", __func__); |
265 | BN_num_bits(dh->p), 2*need); | 265 | dh->length = MIN(need * 2, pbits - 1); |
266 | do { | 266 | if (DH_generate_key(dh) == 0) |
267 | if (dh->priv_key != NULL) | 267 | fatal("%s: key generation failed", __func__); |
268 | BN_clear_free(dh->priv_key); | 268 | if (!dh_pub_is_valid(dh, dh->pub_key)) |
269 | if ((dh->priv_key = BN_new()) == NULL) | 269 | fatal("%s: generated invalid key", __func__); |
270 | fatal("dh_gen_key: BN_new failed"); | ||
271 | /* generate a 2*need bits random private exponent */ | ||
272 | if (!BN_rand(dh->priv_key, 2*need, 0, 0)) | ||
273 | fatal("dh_gen_key: BN_rand failed"); | ||
274 | if (DH_generate_key(dh) == 0) | ||
275 | fatal("DH_generate_key"); | ||
276 | for (i = 0, bits_set = 0; i <= BN_num_bits(dh->priv_key); i++) | ||
277 | if (BN_is_bit_set(dh->priv_key, i)) | ||
278 | bits_set++; | ||
279 | debug2("dh_gen_key: priv key bits set: %d/%d", | ||
280 | bits_set, BN_num_bits(dh->priv_key)); | ||
281 | if (tries++ > 10) | ||
282 | fatal("dh_gen_key: too many bad keys: giving up"); | ||
283 | } while (!dh_pub_is_valid(dh, dh->pub_key)); | ||
284 | } | 270 | } |
285 | 271 | ||
286 | DH * | 272 | DH * |
diff --git a/myproposal.h b/myproposal.h index 8da2ac91f..71dbc997e 100644 --- a/myproposal.h +++ b/myproposal.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: myproposal.h,v 1.33 2013/11/02 21:59:15 markus Exp $ */ | 1 | /* $OpenBSD: myproposal.h,v 1.34 2013/11/21 00:45:44 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
@@ -104,6 +104,7 @@ | |||
104 | "aes128-ctr,aes192-ctr,aes256-ctr," \ | 104 | "aes128-ctr,aes192-ctr,aes256-ctr," \ |
105 | "arcfour256,arcfour128," \ | 105 | "arcfour256,arcfour128," \ |
106 | AESGCM_CIPHER_MODES \ | 106 | AESGCM_CIPHER_MODES \ |
107 | "chacha20-poly1305@openssh.com," \ | ||
107 | "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc," \ | 108 | "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc," \ |
108 | "aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se" | 109 | "aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se" |
109 | 110 | ||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: packet.c,v 1.189 2013/11/08 00:39:15 djm Exp $ */ | 1 | /* $OpenBSD: packet.c,v 1.190 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 |
@@ -713,7 +713,7 @@ packet_send1(void) | |||
713 | buffer_append(&active_state->output, buf, 4); | 713 | buffer_append(&active_state->output, buf, 4); |
714 | cp = buffer_append_space(&active_state->output, | 714 | cp = buffer_append_space(&active_state->output, |
715 | buffer_len(&active_state->outgoing_packet)); | 715 | buffer_len(&active_state->outgoing_packet)); |
716 | cipher_crypt(&active_state->send_context, cp, | 716 | cipher_crypt(&active_state->send_context, 0, cp, |
717 | buffer_ptr(&active_state->outgoing_packet), | 717 | buffer_ptr(&active_state->outgoing_packet), |
718 | buffer_len(&active_state->outgoing_packet), 0, 0); | 718 | buffer_len(&active_state->outgoing_packet), 0, 0); |
719 | 719 | ||
@@ -946,8 +946,8 @@ packet_send2_wrapped(void) | |||
946 | } | 946 | } |
947 | /* encrypt packet and append to output buffer. */ | 947 | /* encrypt packet and append to output buffer. */ |
948 | cp = buffer_append_space(&active_state->output, len + authlen); | 948 | cp = buffer_append_space(&active_state->output, len + authlen); |
949 | cipher_crypt(&active_state->send_context, cp, | 949 | cipher_crypt(&active_state->send_context, active_state->p_send.seqnr, |
950 | buffer_ptr(&active_state->outgoing_packet), | 950 | cp, buffer_ptr(&active_state->outgoing_packet), |
951 | len - aadlen, aadlen, authlen); | 951 | len - aadlen, aadlen, authlen); |
952 | /* append unencrypted MAC */ | 952 | /* append unencrypted MAC */ |
953 | if (mac && mac->enabled) { | 953 | if (mac && mac->enabled) { |
@@ -1208,7 +1208,7 @@ packet_read_poll1(void) | |||
1208 | /* Decrypt data to incoming_packet. */ | 1208 | /* Decrypt data to incoming_packet. */ |
1209 | buffer_clear(&active_state->incoming_packet); | 1209 | buffer_clear(&active_state->incoming_packet); |
1210 | cp = buffer_append_space(&active_state->incoming_packet, padded_len); | 1210 | cp = buffer_append_space(&active_state->incoming_packet, padded_len); |
1211 | cipher_crypt(&active_state->receive_context, cp, | 1211 | cipher_crypt(&active_state->receive_context, 0, cp, |
1212 | buffer_ptr(&active_state->input), padded_len, 0, 0); | 1212 | buffer_ptr(&active_state->input), padded_len, 0, 0); |
1213 | 1213 | ||
1214 | buffer_consume(&active_state->input, padded_len); | 1214 | buffer_consume(&active_state->input, padded_len); |
@@ -1279,10 +1279,12 @@ packet_read_poll2(u_int32_t *seqnr_p) | |||
1279 | aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0; | 1279 | aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0; |
1280 | 1280 | ||
1281 | if (aadlen && active_state->packlen == 0) { | 1281 | if (aadlen && active_state->packlen == 0) { |
1282 | if (buffer_len(&active_state->input) < 4) | 1282 | if (cipher_get_length(&active_state->receive_context, |
1283 | &active_state->packlen, | ||
1284 | active_state->p_read.seqnr, | ||
1285 | buffer_ptr(&active_state->input), | ||
1286 | buffer_len(&active_state->input)) != 0) | ||
1283 | return SSH_MSG_NONE; | 1287 | return SSH_MSG_NONE; |
1284 | cp = buffer_ptr(&active_state->input); | ||
1285 | active_state->packlen = get_u32(cp); | ||
1286 | if (active_state->packlen < 1 + 4 || | 1288 | if (active_state->packlen < 1 + 4 || |
1287 | active_state->packlen > PACKET_MAX_SIZE) { | 1289 | active_state->packlen > PACKET_MAX_SIZE) { |
1288 | #ifdef PACKET_DEBUG | 1290 | #ifdef PACKET_DEBUG |
@@ -1302,7 +1304,8 @@ packet_read_poll2(u_int32_t *seqnr_p) | |||
1302 | buffer_clear(&active_state->incoming_packet); | 1304 | buffer_clear(&active_state->incoming_packet); |
1303 | cp = buffer_append_space(&active_state->incoming_packet, | 1305 | cp = buffer_append_space(&active_state->incoming_packet, |
1304 | block_size); | 1306 | block_size); |
1305 | cipher_crypt(&active_state->receive_context, cp, | 1307 | cipher_crypt(&active_state->receive_context, |
1308 | active_state->p_read.seqnr, cp, | ||
1306 | buffer_ptr(&active_state->input), block_size, 0, 0); | 1309 | buffer_ptr(&active_state->input), block_size, 0, 0); |
1307 | cp = buffer_ptr(&active_state->incoming_packet); | 1310 | cp = buffer_ptr(&active_state->incoming_packet); |
1308 | active_state->packlen = get_u32(cp); | 1311 | active_state->packlen = get_u32(cp); |
@@ -1357,7 +1360,8 @@ packet_read_poll2(u_int32_t *seqnr_p) | |||
1357 | macbuf = mac_compute(mac, active_state->p_read.seqnr, | 1360 | macbuf = mac_compute(mac, active_state->p_read.seqnr, |
1358 | buffer_ptr(&active_state->input), aadlen + need); | 1361 | buffer_ptr(&active_state->input), aadlen + need); |
1359 | cp = buffer_append_space(&active_state->incoming_packet, aadlen + need); | 1362 | cp = buffer_append_space(&active_state->incoming_packet, aadlen + need); |
1360 | cipher_crypt(&active_state->receive_context, cp, | 1363 | cipher_crypt(&active_state->receive_context, |
1364 | active_state->p_read.seqnr, cp, | ||
1361 | buffer_ptr(&active_state->input), need, aadlen, authlen); | 1365 | buffer_ptr(&active_state->input), need, aadlen, authlen); |
1362 | buffer_consume(&active_state->input, aadlen + need + authlen); | 1366 | buffer_consume(&active_state->input, aadlen + need + authlen); |
1363 | /* | 1367 | /* |
diff --git a/poly1305.c b/poly1305.c new file mode 100644 index 000000000..059cc60f7 --- /dev/null +++ b/poly1305.c | |||
@@ -0,0 +1,158 @@ | |||
1 | /* | ||
2 | * Public Domain poly1305 from Andrew M. | ||
3 | * poly1305-donna-unrolled.c from https://github.com/floodyberry/poly1305-donna | ||
4 | */ | ||
5 | |||
6 | /* $OpenBSD: poly1305.c,v 1.2 2013/11/21 02:50:00 djm Exp $ */ | ||
7 | |||
8 | #include "includes.h" | ||
9 | |||
10 | #include <sys/types.h> | ||
11 | #include <stdint.h> | ||
12 | |||
13 | #include "poly1305.h" | ||
14 | |||
15 | #define mul32x32_64(a,b) ((uint64_t)(a) * (b)) | ||
16 | |||
17 | #define U8TO32_LE(p) \ | ||
18 | (((uint32_t)((p)[0])) | \ | ||
19 | ((uint32_t)((p)[1]) << 8) | \ | ||
20 | ((uint32_t)((p)[2]) << 16) | \ | ||
21 | ((uint32_t)((p)[3]) << 24)) | ||
22 | |||
23 | #define U32TO8_LE(p, v) \ | ||
24 | do { \ | ||
25 | (p)[0] = (uint8_t)((v)); \ | ||
26 | (p)[1] = (uint8_t)((v) >> 8); \ | ||
27 | (p)[2] = (uint8_t)((v) >> 16); \ | ||
28 | (p)[3] = (uint8_t)((v) >> 24); \ | ||
29 | } while (0) | ||
30 | |||
31 | void | ||
32 | poly1305_auth(unsigned char out[POLY1305_TAGLEN], const unsigned char *m, size_t inlen, const unsigned char key[POLY1305_KEYLEN]) { | ||
33 | uint32_t t0,t1,t2,t3; | ||
34 | uint32_t h0,h1,h2,h3,h4; | ||
35 | uint32_t r0,r1,r2,r3,r4; | ||
36 | uint32_t s1,s2,s3,s4; | ||
37 | uint32_t b, nb; | ||
38 | size_t j; | ||
39 | uint64_t t[5]; | ||
40 | uint64_t f0,f1,f2,f3; | ||
41 | uint32_t g0,g1,g2,g3,g4; | ||
42 | uint64_t c; | ||
43 | unsigned char mp[16]; | ||
44 | |||
45 | /* clamp key */ | ||
46 | t0 = U8TO32_LE(key+0); | ||
47 | t1 = U8TO32_LE(key+4); | ||
48 | t2 = U8TO32_LE(key+8); | ||
49 | t3 = U8TO32_LE(key+12); | ||
50 | |||
51 | /* precompute multipliers */ | ||
52 | r0 = t0 & 0x3ffffff; t0 >>= 26; t0 |= t1 << 6; | ||
53 | r1 = t0 & 0x3ffff03; t1 >>= 20; t1 |= t2 << 12; | ||
54 | r2 = t1 & 0x3ffc0ff; t2 >>= 14; t2 |= t3 << 18; | ||
55 | r3 = t2 & 0x3f03fff; t3 >>= 8; | ||
56 | r4 = t3 & 0x00fffff; | ||
57 | |||
58 | s1 = r1 * 5; | ||
59 | s2 = r2 * 5; | ||
60 | s3 = r3 * 5; | ||
61 | s4 = r4 * 5; | ||
62 | |||
63 | /* init state */ | ||
64 | h0 = 0; | ||
65 | h1 = 0; | ||
66 | h2 = 0; | ||
67 | h3 = 0; | ||
68 | h4 = 0; | ||
69 | |||
70 | /* full blocks */ | ||
71 | if (inlen < 16) goto poly1305_donna_atmost15bytes; | ||
72 | poly1305_donna_16bytes: | ||
73 | m += 16; | ||
74 | inlen -= 16; | ||
75 | |||
76 | t0 = U8TO32_LE(m-16); | ||
77 | t1 = U8TO32_LE(m-12); | ||
78 | t2 = U8TO32_LE(m-8); | ||
79 | t3 = U8TO32_LE(m-4); | ||
80 | |||
81 | h0 += t0 & 0x3ffffff; | ||
82 | h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff; | ||
83 | h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff; | ||
84 | h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff; | ||
85 | h4 += (t3 >> 8) | (1 << 24); | ||
86 | |||
87 | |||
88 | poly1305_donna_mul: | ||
89 | t[0] = mul32x32_64(h0,r0) + mul32x32_64(h1,s4) + mul32x32_64(h2,s3) + mul32x32_64(h3,s2) + mul32x32_64(h4,s1); | ||
90 | t[1] = mul32x32_64(h0,r1) + mul32x32_64(h1,r0) + mul32x32_64(h2,s4) + mul32x32_64(h3,s3) + mul32x32_64(h4,s2); | ||
91 | t[2] = mul32x32_64(h0,r2) + mul32x32_64(h1,r1) + mul32x32_64(h2,r0) + mul32x32_64(h3,s4) + mul32x32_64(h4,s3); | ||
92 | t[3] = mul32x32_64(h0,r3) + mul32x32_64(h1,r2) + mul32x32_64(h2,r1) + mul32x32_64(h3,r0) + mul32x32_64(h4,s4); | ||
93 | t[4] = mul32x32_64(h0,r4) + mul32x32_64(h1,r3) + mul32x32_64(h2,r2) + mul32x32_64(h3,r1) + mul32x32_64(h4,r0); | ||
94 | |||
95 | h0 = (uint32_t)t[0] & 0x3ffffff; c = (t[0] >> 26); | ||
96 | t[1] += c; h1 = (uint32_t)t[1] & 0x3ffffff; b = (uint32_t)(t[1] >> 26); | ||
97 | t[2] += b; h2 = (uint32_t)t[2] & 0x3ffffff; b = (uint32_t)(t[2] >> 26); | ||
98 | t[3] += b; h3 = (uint32_t)t[3] & 0x3ffffff; b = (uint32_t)(t[3] >> 26); | ||
99 | t[4] += b; h4 = (uint32_t)t[4] & 0x3ffffff; b = (uint32_t)(t[4] >> 26); | ||
100 | h0 += b * 5; | ||
101 | |||
102 | if (inlen >= 16) goto poly1305_donna_16bytes; | ||
103 | |||
104 | /* final bytes */ | ||
105 | poly1305_donna_atmost15bytes: | ||
106 | if (!inlen) goto poly1305_donna_finish; | ||
107 | |||
108 | for (j = 0; j < inlen; j++) mp[j] = m[j]; | ||
109 | mp[j++] = 1; | ||
110 | for (; j < 16; j++) mp[j] = 0; | ||
111 | inlen = 0; | ||
112 | |||
113 | t0 = U8TO32_LE(mp+0); | ||
114 | t1 = U8TO32_LE(mp+4); | ||
115 | t2 = U8TO32_LE(mp+8); | ||
116 | t3 = U8TO32_LE(mp+12); | ||
117 | |||
118 | h0 += t0 & 0x3ffffff; | ||
119 | h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff; | ||
120 | h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff; | ||
121 | h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff; | ||
122 | h4 += (t3 >> 8); | ||
123 | |||
124 | goto poly1305_donna_mul; | ||
125 | |||
126 | poly1305_donna_finish: | ||
127 | b = h0 >> 26; h0 = h0 & 0x3ffffff; | ||
128 | h1 += b; b = h1 >> 26; h1 = h1 & 0x3ffffff; | ||
129 | h2 += b; b = h2 >> 26; h2 = h2 & 0x3ffffff; | ||
130 | h3 += b; b = h3 >> 26; h3 = h3 & 0x3ffffff; | ||
131 | h4 += b; b = h4 >> 26; h4 = h4 & 0x3ffffff; | ||
132 | h0 += b * 5; b = h0 >> 26; h0 = h0 & 0x3ffffff; | ||
133 | h1 += b; | ||
134 | |||
135 | g0 = h0 + 5; b = g0 >> 26; g0 &= 0x3ffffff; | ||
136 | g1 = h1 + b; b = g1 >> 26; g1 &= 0x3ffffff; | ||
137 | g2 = h2 + b; b = g2 >> 26; g2 &= 0x3ffffff; | ||
138 | g3 = h3 + b; b = g3 >> 26; g3 &= 0x3ffffff; | ||
139 | g4 = h4 + b - (1 << 26); | ||
140 | |||
141 | b = (g4 >> 31) - 1; | ||
142 | nb = ~b; | ||
143 | h0 = (h0 & nb) | (g0 & b); | ||
144 | h1 = (h1 & nb) | (g1 & b); | ||
145 | h2 = (h2 & nb) | (g2 & b); | ||
146 | h3 = (h3 & nb) | (g3 & b); | ||
147 | h4 = (h4 & nb) | (g4 & b); | ||
148 | |||
149 | f0 = ((h0 ) | (h1 << 26)) + (uint64_t)U8TO32_LE(&key[16]); | ||
150 | f1 = ((h1 >> 6) | (h2 << 20)) + (uint64_t)U8TO32_LE(&key[20]); | ||
151 | f2 = ((h2 >> 12) | (h3 << 14)) + (uint64_t)U8TO32_LE(&key[24]); | ||
152 | f3 = ((h3 >> 18) | (h4 << 8)) + (uint64_t)U8TO32_LE(&key[28]); | ||
153 | |||
154 | U32TO8_LE(&out[ 0], f0); f1 += (f0 >> 32); | ||
155 | U32TO8_LE(&out[ 4], f1); f2 += (f1 >> 32); | ||
156 | U32TO8_LE(&out[ 8], f2); f3 += (f2 >> 32); | ||
157 | U32TO8_LE(&out[12], f3); | ||
158 | } | ||
diff --git a/poly1305.h b/poly1305.h new file mode 100644 index 000000000..a31fb7425 --- /dev/null +++ b/poly1305.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /* $OpenBSD: poly1305.h,v 1.1 2013/11/21 00:45:44 djm Exp $ */ | ||
2 | |||
3 | /* | ||
4 | * Public Domain poly1305 from Andrew M. | ||
5 | * poly1305-donna-unrolled.c from https://github.com/floodyberry/poly1305-donna | ||
6 | */ | ||
7 | |||
8 | #ifndef POLY1305_H | ||
9 | #define POLY1305_H | ||
10 | |||
11 | #include <sys/types.h> | ||
12 | |||
13 | #define POLY1305_KEYLEN 32 | ||
14 | #define POLY1305_TAGLEN 16 | ||
15 | |||
16 | void poly1305_auth(u_char out[POLY1305_TAGLEN], const u_char *m, size_t inlen, | ||
17 | const u_char key[POLY1305_KEYLEN]) | ||
18 | __attribute__((__bounded__(__minbytes__, 1, POLY1305_TAGLEN))) | ||
19 | __attribute__((__bounded__(__buffer__, 2, 3))) | ||
20 | __attribute__((__bounded__(__minbytes__, 4, POLY1305_KEYLEN))); | ||
21 | |||
22 | #endif /* POLY1305_H */ | ||
diff --git a/servconf.c b/servconf.c index 3593223f7..cb21bd229 100644 --- a/servconf.c +++ b/servconf.c | |||
@@ -1,5 +1,5 @@ | |||
1 | 1 | ||
2 | /* $OpenBSD: servconf.c,v 1.245 2013/11/07 11:58:27 dtucker Exp $ */ | 2 | /* $OpenBSD: servconf.c,v 1.246 2013/11/21 00:45:44 djm Exp $ */ |
3 | /* | 3 | /* |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
5 | * All rights reserved | 5 | * All rights reserved |
@@ -2038,7 +2038,7 @@ dump_config(ServerOptions *o) | |||
2038 | dump_cfg_string(sPidFile, o->pid_file); | 2038 | dump_cfg_string(sPidFile, o->pid_file); |
2039 | dump_cfg_string(sXAuthLocation, o->xauth_location); | 2039 | dump_cfg_string(sXAuthLocation, o->xauth_location); |
2040 | dump_cfg_string(sCiphers, o->ciphers ? o->ciphers : | 2040 | dump_cfg_string(sCiphers, o->ciphers ? o->ciphers : |
2041 | cipher_alg_list(',')); | 2041 | cipher_alg_list(',', 0)); |
2042 | dump_cfg_string(sMacs, o->macs ? o->macs : mac_alg_list(',')); | 2042 | dump_cfg_string(sMacs, o->macs ? o->macs : mac_alg_list(',')); |
2043 | dump_cfg_string(sBanner, o->banner); | 2043 | dump_cfg_string(sBanner, o->banner); |
2044 | dump_cfg_string(sForceCommand, o->adm_forced_command); | 2044 | dump_cfg_string(sForceCommand, o->adm_forced_command); |
@@ -33,8 +33,8 @@ | |||
33 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 33 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
34 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 34 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
35 | .\" | 35 | .\" |
36 | .\" $OpenBSD: ssh.1,v 1.339 2013/10/16 22:49:38 djm Exp $ | 36 | .\" $OpenBSD: ssh.1,v 1.340 2013/11/21 00:45:44 djm Exp $ |
37 | .Dd $Mdocdate: October 16 2013 $ | 37 | .Dd $Mdocdate: November 21 2013 $ |
38 | .Dt SSH 1 | 38 | .Dt SSH 1 |
39 | .Os | 39 | .Os |
40 | .Sh NAME | 40 | .Sh NAME |
@@ -504,6 +504,8 @@ for the algorithms supported for the specified version 2 | |||
504 | The queriable features are: | 504 | The queriable features are: |
505 | .Dq cipher | 505 | .Dq cipher |
506 | (supported symmetric ciphers), | 506 | (supported symmetric ciphers), |
507 | .Dq cipher-auth | ||
508 | (supported symmetric ciphers that support authenticated encryption), | ||
507 | .Dq MAC | 509 | .Dq MAC |
508 | (supported message integrity codes), | 510 | (supported message integrity codes), |
509 | .Dq KEX | 511 | .Dq KEX |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh.c,v 1.392 2013/11/07 11:58:27 dtucker Exp $ */ | 1 | /* $OpenBSD: ssh.c,v 1.393 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 |
@@ -520,7 +520,9 @@ main(int ac, char **av) | |||
520 | case 'Q': /* deprecated */ | 520 | case 'Q': /* deprecated */ |
521 | cp = NULL; | 521 | cp = NULL; |
522 | if (strcasecmp(optarg, "cipher") == 0) | 522 | if (strcasecmp(optarg, "cipher") == 0) |
523 | cp = cipher_alg_list('\n'); | 523 | cp = cipher_alg_list('\n', 0); |
524 | else if (strcasecmp(optarg, "cipher-auth") == 0) | ||
525 | cp = cipher_alg_list('\n', 1); | ||
524 | else if (strcasecmp(optarg, "mac") == 0) | 526 | else if (strcasecmp(optarg, "mac") == 0) |
525 | cp = mac_alg_list('\n'); | 527 | cp = mac_alg_list('\n'); |
526 | else if (strcasecmp(optarg, "kex") == 0) | 528 | else if (strcasecmp(optarg, "kex") == 0) |
diff --git a/ssh_config.5 b/ssh_config.5 index 8809568a6..9dbc76ca9 100644 --- a/ssh_config.5 +++ b/ssh_config.5 | |||
@@ -33,8 +33,8 @@ | |||
33 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 33 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
34 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 34 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
35 | .\" | 35 | .\" |
36 | .\" $OpenBSD: ssh_config.5,v 1.179 2013/11/02 22:39:19 markus Exp $ | 36 | .\" $OpenBSD: ssh_config.5,v 1.180 2013/11/21 00:45:44 djm Exp $ |
37 | .Dd $Mdocdate: November 2 2013 $ | 37 | .Dd $Mdocdate: November 21 2013 $ |
38 | .Dt SSH_CONFIG 5 | 38 | .Dt SSH_CONFIG 5 |
39 | .Os | 39 | .Os |
40 | .Sh NAME | 40 | .Sh NAME |
@@ -334,7 +334,8 @@ The default is | |||
334 | Specifies the ciphers allowed for protocol version 2 | 334 | Specifies the ciphers allowed for protocol version 2 |
335 | in order of preference. | 335 | in order of preference. |
336 | Multiple ciphers must be comma-separated. | 336 | Multiple ciphers must be comma-separated. |
337 | The supported ciphers are | 337 | The supported ciphers are: |
338 | .Pp | ||
338 | .Dq 3des-cbc , | 339 | .Dq 3des-cbc , |
339 | .Dq aes128-cbc , | 340 | .Dq aes128-cbc , |
340 | .Dq aes192-cbc , | 341 | .Dq aes192-cbc , |
@@ -348,15 +349,24 @@ The supported ciphers are | |||
348 | .Dq arcfour256 , | 349 | .Dq arcfour256 , |
349 | .Dq arcfour , | 350 | .Dq arcfour , |
350 | .Dq blowfish-cbc , | 351 | .Dq blowfish-cbc , |
352 | .Dq cast128-cbc , | ||
351 | and | 353 | and |
352 | .Dq cast128-cbc . | 354 | .Dq chacha20-poly1305@openssh.com . |
355 | .Pp | ||
353 | The default is: | 356 | The default is: |
357 | .Pp | ||
354 | .Bd -literal -offset 3n | 358 | .Bd -literal -offset 3n |
355 | aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128, | 359 | aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128, |
356 | aes128-gcm@openssh.com,aes256-gcm@openssh.com, | 360 | aes128-gcm@openssh.com,aes256-gcm@openssh.com, |
361 | chacha20-poly1305@openssh.com, | ||
357 | aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc, | 362 | aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc, |
358 | aes256-cbc,arcfour | 363 | aes256-cbc,arcfour |
359 | .Ed | 364 | .Ed |
365 | .Pp | ||
366 | The list of available ciphers may also be obtained using the | ||
367 | .Fl Q | ||
368 | option of | ||
369 | .Xr ssh 1 . | ||
360 | .It Cm ClearAllForwardings | 370 | .It Cm ClearAllForwardings |
361 | Specifies that all local, remote, and dynamic port forwardings | 371 | Specifies that all local, remote, and dynamic port forwardings |
362 | specified in the configuration files or on the command line be | 372 | specified in the configuration files or on the command line be |
diff --git a/sshd_config.5 b/sshd_config.5 index 02c45a7df..b9864fff2 100644 --- a/sshd_config.5 +++ b/sshd_config.5 | |||
@@ -33,8 +33,8 @@ | |||
33 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 33 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
34 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 34 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
35 | .\" | 35 | .\" |
36 | .\" $OpenBSD: sshd_config.5,v 1.166 2013/11/02 22:39:19 markus Exp $ | 36 | .\" $OpenBSD: sshd_config.5,v 1.167 2013/11/21 00:45:44 djm Exp $ |
37 | .Dd $Mdocdate: November 2 2013 $ | 37 | .Dd $Mdocdate: November 21 2013 $ |
38 | .Dt SSHD_CONFIG 5 | 38 | .Dt SSHD_CONFIG 5 |
39 | .Os | 39 | .Os |
40 | .Sh NAME | 40 | .Sh NAME |
@@ -335,7 +335,8 @@ The default is not to | |||
335 | .It Cm Ciphers | 335 | .It Cm Ciphers |
336 | Specifies the ciphers allowed for protocol version 2. | 336 | Specifies the ciphers allowed for protocol version 2. |
337 | Multiple ciphers must be comma-separated. | 337 | Multiple ciphers must be comma-separated. |
338 | The supported ciphers are | 338 | The supported ciphers are: |
339 | .Pp | ||
339 | .Dq 3des-cbc , | 340 | .Dq 3des-cbc , |
340 | .Dq aes128-cbc , | 341 | .Dq aes128-cbc , |
341 | .Dq aes192-cbc , | 342 | .Dq aes192-cbc , |
@@ -349,15 +350,24 @@ The supported ciphers are | |||
349 | .Dq arcfour256 , | 350 | .Dq arcfour256 , |
350 | .Dq arcfour , | 351 | .Dq arcfour , |
351 | .Dq blowfish-cbc , | 352 | .Dq blowfish-cbc , |
353 | .Dq cast128-cbc , | ||
352 | and | 354 | and |
353 | .Dq cast128-cbc . | 355 | .Dq chacha20-poly1305@openssh.com . |
356 | .Pp | ||
354 | The default is: | 357 | The default is: |
358 | .Pp | ||
355 | .Bd -literal -offset 3n | 359 | .Bd -literal -offset 3n |
356 | aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128, | 360 | aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128, |
357 | aes128-gcm@openssh.com,aes256-gcm@openssh.com, | 361 | aes128-gcm@openssh.com,aes256-gcm@openssh.com, |
362 | chacha20-poly1305@openssh.com, | ||
358 | aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc, | 363 | aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc, |
359 | aes256-cbc,arcfour | 364 | aes256-cbc,arcfour |
360 | .Ed | 365 | .Ed |
366 | .Pp | ||
367 | The list of available ciphers may also be obtained using the | ||
368 | .Fl Q | ||
369 | option of | ||
370 | .Xr ssh 1 . | ||
361 | .It Cm ClientAliveCountMax | 371 | .It Cm ClientAliveCountMax |
362 | Sets the number of client alive messages (see below) which may be | 372 | Sets the number of client alive messages (see below) which may be |
363 | sent without | 373 | sent without |