diff options
Diffstat (limited to 'cipher.c')
-rw-r--r-- | cipher.c | 407 |
1 files changed, 242 insertions, 165 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: cipher.c,v 1.97 2014/02/07 06:55:54 djm Exp $ */ | 1 | /* $OpenBSD: cipher.c,v 1.99 2014/06/24 01:13:21 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,21 +43,21 @@ | |||
43 | #include <stdarg.h> | 43 | #include <stdarg.h> |
44 | #include <stdio.h> | 44 | #include <stdio.h> |
45 | 45 | ||
46 | #include "xmalloc.h" | ||
47 | #include "log.h" | ||
48 | #include "misc.h" | ||
49 | #include "cipher.h" | 46 | #include "cipher.h" |
50 | #include "buffer.h" | 47 | #include "misc.h" |
48 | #include "sshbuf.h" | ||
49 | #include "ssherr.h" | ||
51 | #include "digest.h" | 50 | #include "digest.h" |
52 | 51 | ||
53 | /* compatibility with old or broken OpenSSL versions */ | ||
54 | #include "openbsd-compat/openssl-compat.h" | 52 | #include "openbsd-compat/openssl-compat.h" |
55 | 53 | ||
54 | #ifdef WITH_SSH1 | ||
56 | extern const EVP_CIPHER *evp_ssh1_bf(void); | 55 | extern const EVP_CIPHER *evp_ssh1_bf(void); |
57 | extern const EVP_CIPHER *evp_ssh1_3des(void); | 56 | extern const EVP_CIPHER *evp_ssh1_3des(void); |
58 | extern void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); | 57 | extern int ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); |
58 | #endif | ||
59 | 59 | ||
60 | struct Cipher { | 60 | struct sshcipher { |
61 | char *name; | 61 | char *name; |
62 | int number; /* for ssh1 only */ | 62 | int number; /* for ssh1 only */ |
63 | u_int block_size; | 63 | u_int block_size; |
@@ -68,15 +68,23 @@ struct Cipher { | |||
68 | u_int flags; | 68 | u_int flags; |
69 | #define CFLAG_CBC (1<<0) | 69 | #define CFLAG_CBC (1<<0) |
70 | #define CFLAG_CHACHAPOLY (1<<1) | 70 | #define CFLAG_CHACHAPOLY (1<<1) |
71 | #define CFLAG_AESCTR (1<<2) | ||
72 | #define CFLAG_NONE (1<<3) | ||
73 | #ifdef WITH_OPENSSL | ||
71 | const EVP_CIPHER *(*evptype)(void); | 74 | const EVP_CIPHER *(*evptype)(void); |
75 | #else | ||
76 | void *ignored; | ||
77 | #endif | ||
72 | }; | 78 | }; |
73 | 79 | ||
74 | static const struct Cipher ciphers[] = { | 80 | static const struct sshcipher ciphers[] = { |
75 | { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null }, | 81 | #ifdef WITH_SSH1 |
76 | { "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc }, | 82 | { "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc }, |
77 | { "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des }, | 83 | { "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des }, |
78 | { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, 0, 0, 1, evp_ssh1_bf }, | 84 | { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, 0, 0, 1, evp_ssh1_bf }, |
79 | 85 | #endif /* WITH_SSH1 */ | |
86 | #ifdef WITH_OPENSSL | ||
87 | { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null }, | ||
80 | { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc }, | 88 | { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc }, |
81 | { "blowfish-cbc", | 89 | { "blowfish-cbc", |
82 | SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_bf_cbc }, | 90 | SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_bf_cbc }, |
@@ -93,26 +101,33 @@ static const struct Cipher ciphers[] = { | |||
93 | { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 0, EVP_aes_128_ctr }, | 101 | { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 0, EVP_aes_128_ctr }, |
94 | { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 0, EVP_aes_192_ctr }, | 102 | { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 0, EVP_aes_192_ctr }, |
95 | { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 0, EVP_aes_256_ctr }, | 103 | { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 0, EVP_aes_256_ctr }, |
96 | #ifdef OPENSSL_HAVE_EVPGCM | 104 | # ifdef OPENSSL_HAVE_EVPGCM |
97 | { "aes128-gcm@openssh.com", | 105 | { "aes128-gcm@openssh.com", |
98 | SSH_CIPHER_SSH2, 16, 16, 12, 16, 0, 0, EVP_aes_128_gcm }, | 106 | SSH_CIPHER_SSH2, 16, 16, 12, 16, 0, 0, EVP_aes_128_gcm }, |
99 | { "aes256-gcm@openssh.com", | 107 | { "aes256-gcm@openssh.com", |
100 | SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm }, | 108 | SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm }, |
101 | #endif | 109 | # endif /* OPENSSL_HAVE_EVPGCM */ |
110 | #else /* WITH_OPENSSL */ | ||
111 | { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, CFLAG_AESCTR, NULL }, | ||
112 | { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, CFLAG_AESCTR, NULL }, | ||
113 | { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, CFLAG_AESCTR, NULL }, | ||
114 | { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, CFLAG_NONE, NULL }, | ||
115 | #endif /* WITH_OPENSSL */ | ||
102 | { "chacha20-poly1305@openssh.com", | 116 | { "chacha20-poly1305@openssh.com", |
103 | SSH_CIPHER_SSH2, 8, 64, 0, 16, 0, CFLAG_CHACHAPOLY, NULL }, | 117 | SSH_CIPHER_SSH2, 8, 64, 0, 16, 0, CFLAG_CHACHAPOLY, NULL }, |
118 | |||
104 | { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL } | 119 | { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL } |
105 | }; | 120 | }; |
106 | 121 | ||
107 | /*--*/ | 122 | /*--*/ |
108 | 123 | ||
109 | /* Returns a list of supported ciphers separated by the specified char. */ | 124 | /* Returns a comma-separated list of supported ciphers. */ |
110 | char * | 125 | char * |
111 | cipher_alg_list(char sep, int auth_only) | 126 | cipher_alg_list(char sep, int auth_only) |
112 | { | 127 | { |
113 | char *ret = NULL; | 128 | char *tmp, *ret = NULL; |
114 | size_t nlen, rlen = 0; | 129 | size_t nlen, rlen = 0; |
115 | const Cipher *c; | 130 | const struct sshcipher *c; |
116 | 131 | ||
117 | for (c = ciphers; c->name != NULL; c++) { | 132 | for (c = ciphers; c->name != NULL; c++) { |
118 | if (c->number != SSH_CIPHER_SSH2) | 133 | if (c->number != SSH_CIPHER_SSH2) |
@@ -122,7 +137,11 @@ cipher_alg_list(char sep, int auth_only) | |||
122 | if (ret != NULL) | 137 | if (ret != NULL) |
123 | ret[rlen++] = sep; | 138 | ret[rlen++] = sep; |
124 | nlen = strlen(c->name); | 139 | nlen = strlen(c->name); |
125 | ret = xrealloc(ret, 1, rlen + nlen + 2); | 140 | if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) { |
141 | free(ret); | ||
142 | return NULL; | ||
143 | } | ||
144 | ret = tmp; | ||
126 | memcpy(ret + rlen, c->name, nlen + 1); | 145 | memcpy(ret + rlen, c->name, nlen + 1); |
127 | rlen += nlen; | 146 | rlen += nlen; |
128 | } | 147 | } |
@@ -130,19 +149,19 @@ cipher_alg_list(char sep, int auth_only) | |||
130 | } | 149 | } |
131 | 150 | ||
132 | u_int | 151 | u_int |
133 | cipher_blocksize(const Cipher *c) | 152 | cipher_blocksize(const struct sshcipher *c) |
134 | { | 153 | { |
135 | return (c->block_size); | 154 | return (c->block_size); |
136 | } | 155 | } |
137 | 156 | ||
138 | u_int | 157 | u_int |
139 | cipher_keylen(const Cipher *c) | 158 | cipher_keylen(const struct sshcipher *c) |
140 | { | 159 | { |
141 | return (c->key_len); | 160 | return (c->key_len); |
142 | } | 161 | } |
143 | 162 | ||
144 | u_int | 163 | u_int |
145 | cipher_seclen(const Cipher *c) | 164 | cipher_seclen(const struct sshcipher *c) |
146 | { | 165 | { |
147 | if (strcmp("3des-cbc", c->name) == 0) | 166 | if (strcmp("3des-cbc", c->name) == 0) |
148 | return 14; | 167 | return 14; |
@@ -150,13 +169,13 @@ cipher_seclen(const Cipher *c) | |||
150 | } | 169 | } |
151 | 170 | ||
152 | u_int | 171 | u_int |
153 | cipher_authlen(const Cipher *c) | 172 | cipher_authlen(const struct sshcipher *c) |
154 | { | 173 | { |
155 | return (c->auth_len); | 174 | return (c->auth_len); |
156 | } | 175 | } |
157 | 176 | ||
158 | u_int | 177 | u_int |
159 | cipher_ivlen(const Cipher *c) | 178 | cipher_ivlen(const struct sshcipher *c) |
160 | { | 179 | { |
161 | /* | 180 | /* |
162 | * Default is cipher block size, except for chacha20+poly1305 that | 181 | * Default is cipher block size, except for chacha20+poly1305 that |
@@ -167,13 +186,13 @@ cipher_ivlen(const Cipher *c) | |||
167 | } | 186 | } |
168 | 187 | ||
169 | u_int | 188 | u_int |
170 | cipher_get_number(const Cipher *c) | 189 | cipher_get_number(const struct sshcipher *c) |
171 | { | 190 | { |
172 | return (c->number); | 191 | return (c->number); |
173 | } | 192 | } |
174 | 193 | ||
175 | u_int | 194 | u_int |
176 | cipher_is_cbc(const Cipher *c) | 195 | cipher_is_cbc(const struct sshcipher *c) |
177 | { | 196 | { |
178 | return (c->flags & CFLAG_CBC) != 0; | 197 | return (c->flags & CFLAG_CBC) != 0; |
179 | } | 198 | } |
@@ -190,20 +209,20 @@ cipher_mask_ssh1(int client) | |||
190 | return mask; | 209 | return mask; |
191 | } | 210 | } |
192 | 211 | ||
193 | const Cipher * | 212 | const struct sshcipher * |
194 | cipher_by_name(const char *name) | 213 | cipher_by_name(const char *name) |
195 | { | 214 | { |
196 | const Cipher *c; | 215 | const struct sshcipher *c; |
197 | for (c = ciphers; c->name != NULL; c++) | 216 | for (c = ciphers; c->name != NULL; c++) |
198 | if (strcmp(c->name, name) == 0) | 217 | if (strcmp(c->name, name) == 0) |
199 | return c; | 218 | return c; |
200 | return NULL; | 219 | return NULL; |
201 | } | 220 | } |
202 | 221 | ||
203 | const Cipher * | 222 | const struct sshcipher * |
204 | cipher_by_number(int id) | 223 | cipher_by_number(int id) |
205 | { | 224 | { |
206 | const Cipher *c; | 225 | const struct sshcipher *c; |
207 | for (c = ciphers; c->name != NULL; c++) | 226 | for (c = ciphers; c->name != NULL; c++) |
208 | if (c->number == id) | 227 | if (c->number == id) |
209 | return c; | 228 | return c; |
@@ -214,23 +233,22 @@ cipher_by_number(int id) | |||
214 | int | 233 | int |
215 | ciphers_valid(const char *names) | 234 | ciphers_valid(const char *names) |
216 | { | 235 | { |
217 | const Cipher *c; | 236 | const struct sshcipher *c; |
218 | char *cipher_list, *cp; | 237 | char *cipher_list, *cp; |
219 | char *p; | 238 | char *p; |
220 | 239 | ||
221 | if (names == NULL || strcmp(names, "") == 0) | 240 | if (names == NULL || strcmp(names, "") == 0) |
222 | return 0; | 241 | return 0; |
223 | cipher_list = cp = xstrdup(names); | 242 | if ((cipher_list = cp = strdup(names)) == NULL) |
243 | return 0; | ||
224 | for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0'; | 244 | for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0'; |
225 | (p = strsep(&cp, CIPHER_SEP))) { | 245 | (p = strsep(&cp, CIPHER_SEP))) { |
226 | c = cipher_by_name(p); | 246 | c = cipher_by_name(p); |
227 | if (c == NULL || c->number != SSH_CIPHER_SSH2) { | 247 | if (c == NULL || c->number != SSH_CIPHER_SSH2) { |
228 | debug("bad cipher %s [%s]", p, names); | ||
229 | free(cipher_list); | 248 | free(cipher_list); |
230 | return 0; | 249 | return 0; |
231 | } | 250 | } |
232 | } | 251 | } |
233 | debug3("ciphers ok: [%s]", names); | ||
234 | free(cipher_list); | 252 | free(cipher_list); |
235 | return 1; | 253 | return 1; |
236 | } | 254 | } |
@@ -243,7 +261,7 @@ ciphers_valid(const char *names) | |||
243 | int | 261 | int |
244 | cipher_number(const char *name) | 262 | cipher_number(const char *name) |
245 | { | 263 | { |
246 | const Cipher *c; | 264 | const struct sshcipher *c; |
247 | if (name == NULL) | 265 | if (name == NULL) |
248 | return -1; | 266 | return -1; |
249 | for (c = ciphers; c->name != NULL; c++) | 267 | for (c = ciphers; c->name != NULL; c++) |
@@ -255,90 +273,104 @@ cipher_number(const char *name) | |||
255 | char * | 273 | char * |
256 | cipher_name(int id) | 274 | cipher_name(int id) |
257 | { | 275 | { |
258 | const Cipher *c = cipher_by_number(id); | 276 | const struct sshcipher *c = cipher_by_number(id); |
259 | return (c==NULL) ? "<unknown>" : c->name; | 277 | return (c==NULL) ? "<unknown>" : c->name; |
260 | } | 278 | } |
261 | 279 | ||
262 | void | 280 | const char * |
263 | cipher_init(CipherContext *cc, const Cipher *cipher, | 281 | cipher_warning_message(const struct sshcipher_ctx *cc) |
282 | { | ||
283 | if (cc == NULL || cc->cipher == NULL) | ||
284 | return NULL; | ||
285 | if (cc->cipher->number == SSH_CIPHER_DES) | ||
286 | return "use of DES is strongly discouraged due to " | ||
287 | "cryptographic weaknesses"; | ||
288 | return NULL; | ||
289 | } | ||
290 | |||
291 | int | ||
292 | cipher_init(struct sshcipher_ctx *cc, const struct sshcipher *cipher, | ||
264 | const u_char *key, u_int keylen, const u_char *iv, u_int ivlen, | 293 | const u_char *key, u_int keylen, const u_char *iv, u_int ivlen, |
265 | int do_encrypt) | 294 | int do_encrypt) |
266 | { | 295 | { |
267 | static int dowarn = 1; | 296 | #ifdef WITH_OPENSSL |
268 | #ifdef SSH_OLD_EVP | 297 | int ret = SSH_ERR_INTERNAL_ERROR; |
269 | EVP_CIPHER *type; | ||
270 | #else | ||
271 | const EVP_CIPHER *type; | 298 | const EVP_CIPHER *type; |
272 | int klen; | 299 | int klen; |
273 | #endif | ||
274 | u_char *junk, *discard; | 300 | u_char *junk, *discard; |
275 | 301 | ||
276 | if (cipher->number == SSH_CIPHER_DES) { | 302 | if (cipher->number == SSH_CIPHER_DES) { |
277 | if (dowarn) { | ||
278 | error("Warning: use of DES is strongly discouraged " | ||
279 | "due to cryptographic weaknesses"); | ||
280 | dowarn = 0; | ||
281 | } | ||
282 | if (keylen > 8) | 303 | if (keylen > 8) |
283 | keylen = 8; | 304 | keylen = 8; |
284 | } | 305 | } |
306 | #endif | ||
285 | cc->plaintext = (cipher->number == SSH_CIPHER_NONE); | 307 | cc->plaintext = (cipher->number == SSH_CIPHER_NONE); |
286 | cc->encrypt = do_encrypt; | 308 | cc->encrypt = do_encrypt; |
287 | 309 | ||
288 | if (keylen < cipher->key_len) | 310 | if (keylen < cipher->key_len || |
289 | fatal("cipher_init: key length %d is insufficient for %s.", | 311 | (iv != NULL && ivlen < cipher_ivlen(cipher))) |
290 | keylen, cipher->name); | 312 | return SSH_ERR_INVALID_ARGUMENT; |
291 | if (iv != NULL && ivlen < cipher_ivlen(cipher)) | ||
292 | fatal("cipher_init: iv length %d is insufficient for %s.", | ||
293 | ivlen, cipher->name); | ||
294 | cc->cipher = cipher; | ||
295 | 313 | ||
314 | cc->cipher = cipher; | ||
296 | if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { | 315 | if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { |
297 | chachapoly_init(&cc->cp_ctx, key, keylen); | 316 | return chachapoly_init(&cc->cp_ctx, key, keylen); |
298 | return; | ||
299 | } | 317 | } |
300 | type = (*cipher->evptype)(); | 318 | #ifndef WITH_OPENSSL |
301 | EVP_CIPHER_CTX_init(&cc->evp); | 319 | if ((cc->cipher->flags & CFLAG_AESCTR) != 0) { |
302 | #ifdef SSH_OLD_EVP | 320 | aesctr_keysetup(&cc->ac_ctx, key, 8 * keylen, 8 * ivlen); |
303 | if (type->key_len > 0 && type->key_len != keylen) { | 321 | aesctr_ivsetup(&cc->ac_ctx, iv); |
304 | debug("cipher_init: set keylen (%d -> %d)", | 322 | return 0; |
305 | type->key_len, keylen); | ||
306 | type->key_len = keylen; | ||
307 | } | 323 | } |
308 | EVP_CipherInit(&cc->evp, type, (u_char *)key, (u_char *)iv, | 324 | if ((cc->cipher->flags & CFLAG_NONE) != 0) |
309 | (do_encrypt == CIPHER_ENCRYPT)); | 325 | return 0; |
326 | return SSH_ERR_INVALID_ARGUMENT; | ||
310 | #else | 327 | #else |
328 | type = (*cipher->evptype)(); | ||
329 | EVP_CIPHER_CTX_init(&cc->evp); | ||
311 | if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv, | 330 | if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv, |
312 | (do_encrypt == CIPHER_ENCRYPT)) == 0) | 331 | (do_encrypt == CIPHER_ENCRYPT)) == 0) { |
313 | fatal("cipher_init: EVP_CipherInit failed for %s", | 332 | ret = SSH_ERR_LIBCRYPTO_ERROR; |
314 | cipher->name); | 333 | goto bad; |
334 | } | ||
315 | if (cipher_authlen(cipher) && | 335 | if (cipher_authlen(cipher) && |
316 | !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_IV_FIXED, | 336 | !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_IV_FIXED, |
317 | -1, (u_char *)iv)) | 337 | -1, (u_char *)iv)) { |
318 | fatal("cipher_init: EVP_CTRL_GCM_SET_IV_FIXED failed for %s", | 338 | ret = SSH_ERR_LIBCRYPTO_ERROR; |
319 | cipher->name); | 339 | goto bad; |
340 | } | ||
320 | klen = EVP_CIPHER_CTX_key_length(&cc->evp); | 341 | klen = EVP_CIPHER_CTX_key_length(&cc->evp); |
321 | if (klen > 0 && keylen != (u_int)klen) { | 342 | if (klen > 0 && keylen != (u_int)klen) { |
322 | debug2("cipher_init: set keylen (%d -> %d)", klen, keylen); | 343 | if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0) { |
323 | if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0) | 344 | ret = SSH_ERR_LIBCRYPTO_ERROR; |
324 | fatal("cipher_init: set keylen failed (%d -> %d)", | 345 | goto bad; |
325 | klen, keylen); | 346 | } |
347 | } | ||
348 | if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0) { | ||
349 | ret = SSH_ERR_LIBCRYPTO_ERROR; | ||
350 | goto bad; | ||
326 | } | 351 | } |
327 | if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0) | ||
328 | fatal("cipher_init: EVP_CipherInit: set key failed for %s", | ||
329 | cipher->name); | ||
330 | #endif | ||
331 | 352 | ||
332 | if (cipher->discard_len > 0) { | 353 | if (cipher->discard_len > 0) { |
333 | junk = xmalloc(cipher->discard_len); | 354 | if ((junk = malloc(cipher->discard_len)) == NULL || |
334 | discard = xmalloc(cipher->discard_len); | 355 | (discard = malloc(cipher->discard_len)) == NULL) { |
335 | if (EVP_Cipher(&cc->evp, discard, junk, | 356 | if (junk != NULL) |
336 | cipher->discard_len) == 0) | 357 | free(junk); |
337 | fatal("evp_crypt: EVP_Cipher failed during discard"); | 358 | ret = SSH_ERR_ALLOC_FAIL; |
359 | goto bad; | ||
360 | } | ||
361 | ret = EVP_Cipher(&cc->evp, discard, junk, cipher->discard_len); | ||
338 | explicit_bzero(discard, cipher->discard_len); | 362 | explicit_bzero(discard, cipher->discard_len); |
339 | free(junk); | 363 | free(junk); |
340 | free(discard); | 364 | free(discard); |
365 | if (ret != 1) { | ||
366 | ret = SSH_ERR_LIBCRYPTO_ERROR; | ||
367 | bad: | ||
368 | EVP_CIPHER_CTX_cleanup(&cc->evp); | ||
369 | return ret; | ||
370 | } | ||
341 | } | 371 | } |
372 | #endif | ||
373 | return 0; | ||
342 | } | 374 | } |
343 | 375 | ||
344 | /* | 376 | /* |
@@ -350,204 +382,244 @@ cipher_init(CipherContext *cc, const Cipher *cipher, | |||
350 | * Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag. | 382 | * Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag. |
351 | * This tag is written on encryption and verified on decryption. | 383 | * This tag is written on encryption and verified on decryption. |
352 | * Both 'aadlen' and 'authlen' can be set to 0. | 384 | * Both 'aadlen' and 'authlen' can be set to 0. |
353 | * cipher_crypt() returns 0 on success and -1 if the decryption integrity | ||
354 | * check fails. | ||
355 | */ | 385 | */ |
356 | int | 386 | int |
357 | cipher_crypt(CipherContext *cc, u_int seqnr, u_char *dest, const u_char *src, | 387 | cipher_crypt(struct sshcipher_ctx *cc, u_int seqnr, u_char *dest, |
358 | u_int len, u_int aadlen, u_int authlen) | 388 | const u_char *src, u_int len, u_int aadlen, u_int authlen) |
359 | { | 389 | { |
360 | if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) | 390 | if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { |
361 | return chachapoly_crypt(&cc->cp_ctx, seqnr, dest, src, len, | 391 | return chachapoly_crypt(&cc->cp_ctx, seqnr, dest, src, |
362 | aadlen, authlen, cc->encrypt); | 392 | len, aadlen, authlen, cc->encrypt); |
393 | } | ||
394 | #ifndef WITH_OPENSSL | ||
395 | if ((cc->cipher->flags & CFLAG_AESCTR) != 0) { | ||
396 | if (aadlen) | ||
397 | memcpy(dest, src, aadlen); | ||
398 | aesctr_encrypt_bytes(&cc->ac_ctx, src + aadlen, | ||
399 | dest + aadlen, len); | ||
400 | return 0; | ||
401 | } | ||
402 | if ((cc->cipher->flags & CFLAG_NONE) != 0) { | ||
403 | memcpy(dest, src, aadlen + len); | ||
404 | return 0; | ||
405 | } | ||
406 | return SSH_ERR_INVALID_ARGUMENT; | ||
407 | #else | ||
363 | if (authlen) { | 408 | if (authlen) { |
364 | u_char lastiv[1]; | 409 | u_char lastiv[1]; |
365 | 410 | ||
366 | if (authlen != cipher_authlen(cc->cipher)) | 411 | if (authlen != cipher_authlen(cc->cipher)) |
367 | fatal("%s: authlen mismatch %d", __func__, authlen); | 412 | return SSH_ERR_INVALID_ARGUMENT; |
368 | /* increment IV */ | 413 | /* increment IV */ |
369 | if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN, | 414 | if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN, |
370 | 1, lastiv)) | 415 | 1, lastiv)) |
371 | fatal("%s: EVP_CTRL_GCM_IV_GEN", __func__); | 416 | return SSH_ERR_LIBCRYPTO_ERROR; |
372 | /* set tag on decyption */ | 417 | /* set tag on decyption */ |
373 | if (!cc->encrypt && | 418 | if (!cc->encrypt && |
374 | !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_TAG, | 419 | !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_TAG, |
375 | authlen, (u_char *)src + aadlen + len)) | 420 | authlen, (u_char *)src + aadlen + len)) |
376 | fatal("%s: EVP_CTRL_GCM_SET_TAG", __func__); | 421 | return SSH_ERR_LIBCRYPTO_ERROR; |
377 | } | 422 | } |
378 | if (aadlen) { | 423 | if (aadlen) { |
379 | if (authlen && | 424 | if (authlen && |
380 | EVP_Cipher(&cc->evp, NULL, (u_char *)src, aadlen) < 0) | 425 | EVP_Cipher(&cc->evp, NULL, (u_char *)src, aadlen) < 0) |
381 | fatal("%s: EVP_Cipher(aad) failed", __func__); | 426 | return SSH_ERR_LIBCRYPTO_ERROR; |
382 | memcpy(dest, src, aadlen); | 427 | memcpy(dest, src, aadlen); |
383 | } | 428 | } |
384 | if (len % cc->cipher->block_size) | 429 | if (len % cc->cipher->block_size) |
385 | fatal("%s: bad plaintext length %d", __func__, len); | 430 | return SSH_ERR_INVALID_ARGUMENT; |
386 | if (EVP_Cipher(&cc->evp, dest + aadlen, (u_char *)src + aadlen, | 431 | if (EVP_Cipher(&cc->evp, dest + aadlen, (u_char *)src + aadlen, |
387 | len) < 0) | 432 | len) < 0) |
388 | fatal("%s: EVP_Cipher failed", __func__); | 433 | return SSH_ERR_LIBCRYPTO_ERROR; |
389 | if (authlen) { | 434 | if (authlen) { |
390 | /* compute tag (on encrypt) or verify tag (on decrypt) */ | 435 | /* compute tag (on encrypt) or verify tag (on decrypt) */ |
391 | if (EVP_Cipher(&cc->evp, NULL, NULL, 0) < 0) { | 436 | if (EVP_Cipher(&cc->evp, NULL, NULL, 0) < 0) |
392 | if (cc->encrypt) | 437 | return cc->encrypt ? |
393 | fatal("%s: EVP_Cipher(final) failed", __func__); | 438 | SSH_ERR_LIBCRYPTO_ERROR : SSH_ERR_MAC_INVALID; |
394 | else | ||
395 | return -1; | ||
396 | } | ||
397 | if (cc->encrypt && | 439 | if (cc->encrypt && |
398 | !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_GET_TAG, | 440 | !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_GET_TAG, |
399 | authlen, dest + aadlen + len)) | 441 | authlen, dest + aadlen + len)) |
400 | fatal("%s: EVP_CTRL_GCM_GET_TAG", __func__); | 442 | return SSH_ERR_LIBCRYPTO_ERROR; |
401 | } | 443 | } |
402 | return 0; | 444 | return 0; |
445 | #endif | ||
403 | } | 446 | } |
404 | 447 | ||
405 | /* Extract the packet length, including any decryption necessary beforehand */ | 448 | /* Extract the packet length, including any decryption necessary beforehand */ |
406 | int | 449 | int |
407 | cipher_get_length(CipherContext *cc, u_int *plenp, u_int seqnr, | 450 | cipher_get_length(struct sshcipher_ctx *cc, u_int *plenp, u_int seqnr, |
408 | const u_char *cp, u_int len) | 451 | const u_char *cp, u_int len) |
409 | { | 452 | { |
410 | if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) | 453 | if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) |
411 | return chachapoly_get_length(&cc->cp_ctx, plenp, seqnr, | 454 | return chachapoly_get_length(&cc->cp_ctx, plenp, seqnr, |
412 | cp, len); | 455 | cp, len); |
413 | if (len < 4) | 456 | if (len < 4) |
414 | return -1; | 457 | return SSH_ERR_MESSAGE_INCOMPLETE; |
415 | *plenp = get_u32(cp); | 458 | *plenp = get_u32(cp); |
416 | return 0; | 459 | return 0; |
417 | } | 460 | } |
418 | 461 | ||
419 | void | 462 | int |
420 | cipher_cleanup(CipherContext *cc) | 463 | cipher_cleanup(struct sshcipher_ctx *cc) |
421 | { | 464 | { |
465 | if (cc == NULL || cc->cipher == NULL) | ||
466 | return 0; | ||
422 | if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) | 467 | if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) |
423 | explicit_bzero(&cc->cp_ctx, sizeof(cc->cp_ctx)); | 468 | explicit_bzero(&cc->cp_ctx, sizeof(cc->cp_ctx)); |
469 | else if ((cc->cipher->flags & CFLAG_AESCTR) != 0) | ||
470 | explicit_bzero(&cc->ac_ctx, sizeof(cc->ac_ctx)); | ||
471 | #ifdef WITH_OPENSSL | ||
424 | else if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0) | 472 | else if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0) |
425 | error("cipher_cleanup: EVP_CIPHER_CTX_cleanup failed"); | 473 | return SSH_ERR_LIBCRYPTO_ERROR; |
474 | #endif | ||
475 | return 0; | ||
426 | } | 476 | } |
427 | 477 | ||
428 | /* | 478 | /* |
429 | * Selects the cipher, and keys if by computing the MD5 checksum of the | 479 | * Selects the cipher, and keys if by computing the MD5 checksum of the |
430 | * passphrase and using the resulting 16 bytes as the key. | 480 | * passphrase and using the resulting 16 bytes as the key. |
431 | */ | 481 | */ |
432 | 482 | int | |
433 | void | 483 | cipher_set_key_string(struct sshcipher_ctx *cc, const struct sshcipher *cipher, |
434 | cipher_set_key_string(CipherContext *cc, const Cipher *cipher, | ||
435 | const char *passphrase, int do_encrypt) | 484 | const char *passphrase, int do_encrypt) |
436 | { | 485 | { |
437 | u_char digest[16]; | 486 | u_char digest[16]; |
487 | int r = SSH_ERR_INTERNAL_ERROR; | ||
438 | 488 | ||
439 | if (ssh_digest_memory(SSH_DIGEST_MD5, passphrase, strlen(passphrase), | 489 | if ((r = ssh_digest_memory(SSH_DIGEST_MD5, |
440 | digest, sizeof(digest)) < 0) | 490 | passphrase, strlen(passphrase), |
441 | fatal("%s: md5 failed", __func__); | 491 | digest, sizeof(digest))) != 0) |
442 | 492 | goto out; | |
443 | cipher_init(cc, cipher, digest, 16, NULL, 0, do_encrypt); | ||
444 | 493 | ||
494 | r = cipher_init(cc, cipher, digest, 16, NULL, 0, do_encrypt); | ||
495 | out: | ||
445 | explicit_bzero(digest, sizeof(digest)); | 496 | explicit_bzero(digest, sizeof(digest)); |
497 | return r; | ||
446 | } | 498 | } |
447 | 499 | ||
448 | /* | 500 | /* |
449 | * Exports an IV from the CipherContext required to export the key | 501 | * Exports an IV from the sshcipher_ctx required to export the key |
450 | * state back from the unprivileged child to the privileged parent | 502 | * state back from the unprivileged child to the privileged parent |
451 | * process. | 503 | * process. |
452 | */ | 504 | */ |
453 | |||
454 | int | 505 | int |
455 | cipher_get_keyiv_len(const CipherContext *cc) | 506 | cipher_get_keyiv_len(const struct sshcipher_ctx *cc) |
456 | { | 507 | { |
457 | const Cipher *c = cc->cipher; | 508 | const struct sshcipher *c = cc->cipher; |
458 | int ivlen; | 509 | int ivlen = 0; |
459 | 510 | ||
460 | if (c->number == SSH_CIPHER_3DES) | 511 | if (c->number == SSH_CIPHER_3DES) |
461 | ivlen = 24; | 512 | ivlen = 24; |
462 | else if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) | 513 | else if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) |
463 | ivlen = 0; | 514 | ivlen = 0; |
515 | #ifdef WITH_OPENSSL | ||
464 | else | 516 | else |
465 | ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp); | 517 | ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp); |
518 | #endif /* WITH_OPENSSL */ | ||
466 | return (ivlen); | 519 | return (ivlen); |
467 | } | 520 | } |
468 | 521 | ||
469 | void | 522 | int |
470 | cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len) | 523 | cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, u_int len) |
471 | { | 524 | { |
472 | const Cipher *c = cc->cipher; | 525 | const struct sshcipher *c = cc->cipher; |
473 | int evplen; | 526 | #ifdef WITH_OPENSSL |
527 | int evplen; | ||
528 | #endif | ||
474 | 529 | ||
475 | if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { | 530 | if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { |
476 | if (len != 0) | 531 | if (len != 0) |
477 | fatal("%s: wrong iv length %d != %d", __func__, len, 0); | 532 | return SSH_ERR_INVALID_ARGUMENT; |
478 | return; | 533 | return 0; |
479 | } | 534 | } |
535 | if ((cc->cipher->flags & CFLAG_NONE) != 0) | ||
536 | return 0; | ||
480 | 537 | ||
481 | switch (c->number) { | 538 | switch (c->number) { |
539 | #ifdef WITH_OPENSSL | ||
482 | case SSH_CIPHER_SSH2: | 540 | case SSH_CIPHER_SSH2: |
483 | case SSH_CIPHER_DES: | 541 | case SSH_CIPHER_DES: |
484 | case SSH_CIPHER_BLOWFISH: | 542 | case SSH_CIPHER_BLOWFISH: |
485 | evplen = EVP_CIPHER_CTX_iv_length(&cc->evp); | 543 | evplen = EVP_CIPHER_CTX_iv_length(&cc->evp); |
486 | if (evplen <= 0) | 544 | if (evplen == 0) |
487 | return; | 545 | return 0; |
546 | else if (evplen < 0) | ||
547 | return SSH_ERR_LIBCRYPTO_ERROR; | ||
488 | if ((u_int)evplen != len) | 548 | if ((u_int)evplen != len) |
489 | fatal("%s: wrong iv length %d != %d", __func__, | 549 | return SSH_ERR_INVALID_ARGUMENT; |
490 | evplen, len); | ||
491 | #ifdef USE_BUILTIN_RIJNDAEL | ||
492 | if (c->evptype == evp_rijndael) | ||
493 | ssh_rijndael_iv(&cc->evp, 0, iv, len); | ||
494 | else | ||
495 | #endif | ||
496 | #ifndef OPENSSL_HAVE_EVPCTR | 550 | #ifndef OPENSSL_HAVE_EVPCTR |
497 | if (c->evptype == evp_aes_128_ctr) | 551 | if (c->evptype == evp_aes_128_ctr) |
498 | ssh_aes_ctr_iv(&cc->evp, 0, iv, len); | 552 | ssh_aes_ctr_iv(&cc->evp, 0, iv, len); |
499 | else | 553 | else |
500 | #endif | 554 | #endif |
501 | memcpy(iv, cc->evp.iv, len); | 555 | if (cipher_authlen(c)) { |
556 | if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN, | ||
557 | len, iv)) | ||
558 | return SSH_ERR_LIBCRYPTO_ERROR; | ||
559 | } else | ||
560 | memcpy(iv, cc->evp.iv, len); | ||
502 | break; | 561 | break; |
562 | #endif | ||
563 | #ifdef WITH_SSH1 | ||
503 | case SSH_CIPHER_3DES: | 564 | case SSH_CIPHER_3DES: |
504 | ssh1_3des_iv(&cc->evp, 0, iv, 24); | 565 | return ssh1_3des_iv(&cc->evp, 0, iv, 24); |
505 | break; | 566 | #endif |
506 | default: | 567 | default: |
507 | fatal("%s: bad cipher %d", __func__, c->number); | 568 | return SSH_ERR_INVALID_ARGUMENT; |
508 | } | 569 | } |
570 | return 0; | ||
509 | } | 571 | } |
510 | 572 | ||
511 | void | 573 | int |
512 | cipher_set_keyiv(CipherContext *cc, u_char *iv) | 574 | cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv) |
513 | { | 575 | { |
514 | const Cipher *c = cc->cipher; | 576 | const struct sshcipher *c = cc->cipher; |
515 | int evplen = 0; | 577 | #ifdef WITH_OPENSSL |
578 | int evplen = 0; | ||
579 | #endif | ||
516 | 580 | ||
517 | if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) | 581 | if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) |
518 | return; | 582 | return 0; |
583 | if ((cc->cipher->flags & CFLAG_NONE) != 0) | ||
584 | return 0; | ||
519 | 585 | ||
520 | switch (c->number) { | 586 | switch (c->number) { |
587 | #ifdef WITH_OPENSSL | ||
521 | case SSH_CIPHER_SSH2: | 588 | case SSH_CIPHER_SSH2: |
522 | case SSH_CIPHER_DES: | 589 | case SSH_CIPHER_DES: |
523 | case SSH_CIPHER_BLOWFISH: | 590 | case SSH_CIPHER_BLOWFISH: |
524 | evplen = EVP_CIPHER_CTX_iv_length(&cc->evp); | 591 | evplen = EVP_CIPHER_CTX_iv_length(&cc->evp); |
525 | if (evplen == 0) | 592 | if (evplen <= 0) |
526 | return; | 593 | return SSH_ERR_LIBCRYPTO_ERROR; |
527 | #ifdef USE_BUILTIN_RIJNDAEL | 594 | if (cipher_authlen(c)) { |
528 | if (c->evptype == evp_rijndael) | 595 | /* XXX iv arg is const, but EVP_CIPHER_CTX_ctrl isn't */ |
529 | ssh_rijndael_iv(&cc->evp, 1, iv, evplen); | 596 | if (!EVP_CIPHER_CTX_ctrl(&cc->evp, |
530 | else | 597 | EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv)) |
531 | #endif | 598 | return SSH_ERR_LIBCRYPTO_ERROR; |
532 | #ifndef OPENSSL_HAVE_EVPCTR | 599 | } else |
533 | if (c->evptype == evp_aes_128_ctr) | 600 | memcpy(cc->evp.iv, iv, evplen); |
534 | ssh_aes_ctr_iv(&cc->evp, 1, iv, evplen); | ||
535 | else | ||
536 | #endif | ||
537 | memcpy(cc->evp.iv, iv, evplen); | ||
538 | break; | 601 | break; |
602 | #endif | ||
603 | #ifdef WITH_SSH1 | ||
539 | case SSH_CIPHER_3DES: | 604 | case SSH_CIPHER_3DES: |
540 | ssh1_3des_iv(&cc->evp, 1, iv, 24); | 605 | return ssh1_3des_iv(&cc->evp, 1, (u_char *)iv, 24); |
541 | break; | 606 | #endif |
542 | default: | 607 | default: |
543 | fatal("%s: bad cipher %d", __func__, c->number); | 608 | return SSH_ERR_INVALID_ARGUMENT; |
544 | } | 609 | } |
610 | return 0; | ||
545 | } | 611 | } |
546 | 612 | ||
613 | #ifdef WITH_OPENSSL | ||
614 | #define EVP_X_STATE(evp) (evp).cipher_data | ||
615 | #define EVP_X_STATE_LEN(evp) (evp).cipher->ctx_size | ||
616 | #endif | ||
617 | |||
547 | int | 618 | int |
548 | cipher_get_keycontext(const CipherContext *cc, u_char *dat) | 619 | cipher_get_keycontext(const struct sshcipher_ctx *cc, u_char *dat) |
549 | { | 620 | { |
550 | const Cipher *c = cc->cipher; | 621 | #ifdef WITH_OPENSSL |
622 | const struct sshcipher *c = cc->cipher; | ||
551 | int plen = 0; | 623 | int plen = 0; |
552 | 624 | ||
553 | if (c->evptype == EVP_rc4) { | 625 | if (c->evptype == EVP_rc4) { |
@@ -557,16 +629,21 @@ cipher_get_keycontext(const CipherContext *cc, u_char *dat) | |||
557 | memcpy(dat, EVP_X_STATE(cc->evp), plen); | 629 | memcpy(dat, EVP_X_STATE(cc->evp), plen); |
558 | } | 630 | } |
559 | return (plen); | 631 | return (plen); |
632 | #else | ||
633 | return 0; | ||
634 | #endif | ||
560 | } | 635 | } |
561 | 636 | ||
562 | void | 637 | void |
563 | cipher_set_keycontext(CipherContext *cc, u_char *dat) | 638 | cipher_set_keycontext(struct sshcipher_ctx *cc, const u_char *dat) |
564 | { | 639 | { |
565 | const Cipher *c = cc->cipher; | 640 | #ifdef WITH_OPENSSL |
641 | const struct sshcipher *c = cc->cipher; | ||
566 | int plen; | 642 | int plen; |
567 | 643 | ||
568 | if (c->evptype == EVP_rc4) { | 644 | if (c->evptype == EVP_rc4) { |
569 | plen = EVP_X_STATE_LEN(cc->evp); | 645 | plen = EVP_X_STATE_LEN(cc->evp); |
570 | memcpy(EVP_X_STATE(cc->evp), dat, plen); | 646 | memcpy(EVP_X_STATE(cc->evp), dat, plen); |
571 | } | 647 | } |
648 | #endif | ||
572 | } | 649 | } |