diff options
Diffstat (limited to 'cipher.c')
-rw-r--r-- | cipher.c | 105 |
1 files changed, 81 insertions, 24 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: cipher.c,v 1.84 2012/12/12 16:46:10 naddy Exp $ */ | 1 | /* $OpenBSD: cipher.c,v 1.85 2013/01/08 18:49:04 markus 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 |
@@ -71,29 +71,38 @@ struct Cipher { | |||
71 | u_int cbc_mode; | 71 | u_int cbc_mode; |
72 | const EVP_CIPHER *(*evptype)(void); | 72 | const EVP_CIPHER *(*evptype)(void); |
73 | } ciphers[] = { | 73 | } ciphers[] = { |
74 | { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, EVP_enc_null }, | 74 | { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, NULL } |
75 | { "des", SSH_CIPHER_DES, 8, 8, 0, 1, EVP_des_cbc }, | 75 | |
76 | { "3des", SSH_CIPHER_3DES, 8, 16, 0, 1, evp_ssh1_3des }, | 76 | { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null }, |
77 | { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, 1, evp_ssh1_bf }, | 77 | { "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc }, |
78 | 78 | { "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des }, | |
79 | { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 1, EVP_des_ede3_cbc }, | 79 | { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, 0, 0, 1, evp_ssh1_bf }, |
80 | { "blowfish-cbc", SSH_CIPHER_SSH2, 8, 16, 0, 1, EVP_bf_cbc }, | 80 | |
81 | { "cast128-cbc", SSH_CIPHER_SSH2, 8, 16, 0, 1, EVP_cast5_cbc }, | 81 | { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc }, |
82 | { "arcfour", SSH_CIPHER_SSH2, 8, 16, 0, 0, EVP_rc4 }, | 82 | { "blowfish-cbc", |
83 | { "arcfour128", SSH_CIPHER_SSH2, 8, 16, 1536, 0, EVP_rc4 }, | 83 | SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_bf_cbc }, |
84 | { "arcfour256", SSH_CIPHER_SSH2, 8, 32, 1536, 0, EVP_rc4 }, | 84 | { "cast128-cbc", |
85 | { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, 1, EVP_aes_128_cbc }, | 85 | SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_cast5_cbc }, |
86 | { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, 1, EVP_aes_192_cbc }, | 86 | { "arcfour", SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 0, EVP_rc4 }, |
87 | { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc }, | 87 | { "arcfour128", SSH_CIPHER_SSH2, 8, 16, 0, 0, 1536, 0, EVP_rc4 }, |
88 | { "arcfour256", SSH_CIPHER_SSH2, 8, 32, 0, 0, 1536, 0, EVP_rc4 }, | ||
89 | { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 1, EVP_aes_128_cbc }, | ||
90 | { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 1, EVP_aes_192_cbc }, | ||
91 | { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 1, EVP_aes_256_cbc }, | ||
88 | { "rijndael-cbc@lysator.liu.se", | 92 | { "rijndael-cbc@lysator.liu.se", |
89 | SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc }, | 93 | SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 1, EVP_aes_256_cbc }, |
90 | { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, EVP_aes_128_ctr }, | 94 | { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 0, EVP_aes_128_ctr }, |
91 | { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, EVP_aes_192_ctr }, | 95 | { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 0, EVP_aes_192_ctr }, |
92 | { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, EVP_aes_256_ctr }, | 96 | { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 0, EVP_aes_256_ctr }, |
97 | { "aes128-gcm@openssh.com", | ||
98 | SSH_CIPHER_SSH2, 16, 16, 12, 16, 0, 0, EVP_aes_128_gcm }, | ||
99 | { "aes256-gcm@openssh.com", | ||
100 | SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm }, | ||
93 | #ifdef USE_CIPHER_ACSS | 101 | #ifdef USE_CIPHER_ACSS |
94 | { "acss@openssh.org", SSH_CIPHER_SSH2, 16, 5, 0, 0, EVP_acss }, | 102 | { "acss@openssh.org", |
103 | SSH_CIPHER_SSH2, 16, 5, 0, 0, 0, 0, EVP_acss }, | ||
95 | #endif | 104 | #endif |
96 | { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, NULL } | 105 | { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL } |
97 | }; | 106 | }; |
98 | 107 | ||
99 | /*--*/ | 108 | /*--*/ |
@@ -111,6 +120,18 @@ cipher_keylen(const Cipher *c) | |||
111 | } | 120 | } |
112 | 121 | ||
113 | u_int | 122 | u_int |
123 | cipher_authlen(const Cipher *c) | ||
124 | { | ||
125 | return (c->auth_len); | ||
126 | } | ||
127 | |||
128 | u_int | ||
129 | cipher_ivlen(const Cipher *c) | ||
130 | { | ||
131 | return (c->iv_len ? c->iv_len : c->block_size); | ||
132 | } | ||
133 | |||
134 | u_int | ||
114 | cipher_get_number(const Cipher *c) | 135 | cipher_get_number(const Cipher *c) |
115 | { | 136 | { |
116 | return (c->number); | 137 | return (c->number); |
@@ -229,11 +250,12 @@ cipher_init(CipherContext *cc, Cipher *cipher, | |||
229 | keylen = 8; | 250 | keylen = 8; |
230 | } | 251 | } |
231 | cc->plaintext = (cipher->number == SSH_CIPHER_NONE); | 252 | cc->plaintext = (cipher->number == SSH_CIPHER_NONE); |
253 | cc->encrypt = do_encrypt; | ||
232 | 254 | ||
233 | if (keylen < cipher->key_len) | 255 | if (keylen < cipher->key_len) |
234 | fatal("cipher_init: key length %d is insufficient for %s.", | 256 | fatal("cipher_init: key length %d is insufficient for %s.", |
235 | keylen, cipher->name); | 257 | keylen, cipher->name); |
236 | if (iv != NULL && ivlen < cipher->block_size) | 258 | if (iv != NULL && ivlen < cipher_ivlen(cipher)) |
237 | fatal("cipher_init: iv length %d is insufficient for %s.", | 259 | fatal("cipher_init: iv length %d is insufficient for %s.", |
238 | ivlen, cipher->name); | 260 | ivlen, cipher->name); |
239 | cc->cipher = cipher; | 261 | cc->cipher = cipher; |
@@ -254,6 +276,11 @@ cipher_init(CipherContext *cc, Cipher *cipher, | |||
254 | (do_encrypt == CIPHER_ENCRYPT)) == 0) | 276 | (do_encrypt == CIPHER_ENCRYPT)) == 0) |
255 | fatal("cipher_init: EVP_CipherInit failed for %s", | 277 | fatal("cipher_init: EVP_CipherInit failed for %s", |
256 | cipher->name); | 278 | cipher->name); |
279 | if (cipher_authlen(cipher) && | ||
280 | !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_IV_FIXED, | ||
281 | -1, (u_char *)iv)) | ||
282 | fatal("cipher_init: EVP_CTRL_GCM_SET_IV_FIXED failed for %s", | ||
283 | cipher->name); | ||
257 | klen = EVP_CIPHER_CTX_key_length(&cc->evp); | 284 | klen = EVP_CIPHER_CTX_key_length(&cc->evp); |
258 | if (klen > 0 && keylen != (u_int)klen) { | 285 | if (klen > 0 && keylen != (u_int)klen) { |
259 | debug2("cipher_init: set keylen (%d -> %d)", klen, keylen); | 286 | debug2("cipher_init: set keylen (%d -> %d)", klen, keylen); |
@@ -284,19 +311,49 @@ cipher_init(CipherContext *cc, Cipher *cipher, | |||
284 | * Theses bytes are treated as additional authenticated data for | 311 | * Theses bytes are treated as additional authenticated data for |
285 | * authenticated encryption modes. | 312 | * authenticated encryption modes. |
286 | * En/Decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'. | 313 | * En/Decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'. |
314 | * Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag. | ||
315 | * This tag is written on encryption and verified on decryption. | ||
287 | * Both 'aadlen' and 'authlen' can be set to 0. | 316 | * Both 'aadlen' and 'authlen' can be set to 0. |
288 | */ | 317 | */ |
289 | void | 318 | void |
290 | cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src, | 319 | cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src, |
291 | u_int len, u_int aadlen) | 320 | u_int len, u_int aadlen, u_int authlen) |
292 | { | 321 | { |
293 | if (aadlen) | 322 | if (authlen) { |
323 | u_char lastiv[1]; | ||
324 | |||
325 | if (authlen != cipher_authlen(cc->cipher)) | ||
326 | fatal("%s: authlen mismatch %d", __func__, authlen); | ||
327 | /* increment IV */ | ||
328 | if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN, | ||
329 | 1, lastiv)) | ||
330 | fatal("%s: EVP_CTRL_GCM_IV_GEN", __func__); | ||
331 | /* set tag on decyption */ | ||
332 | if (!cc->encrypt && | ||
333 | !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_TAG, | ||
334 | authlen, (u_char *)src + aadlen + len)) | ||
335 | fatal("%s: EVP_CTRL_GCM_SET_TAG", __func__); | ||
336 | } | ||
337 | if (aadlen) { | ||
338 | if (authlen && | ||
339 | EVP_Cipher(&cc->evp, NULL, (u_char *)src, aadlen) < 0) | ||
340 | fatal("%s: EVP_Cipher(aad) failed", __func__); | ||
294 | memcpy(dest, src, aadlen); | 341 | memcpy(dest, src, aadlen); |
342 | } | ||
295 | if (len % cc->cipher->block_size) | 343 | if (len % cc->cipher->block_size) |
296 | fatal("%s: bad plaintext length %d", __func__, len); | 344 | fatal("%s: bad plaintext length %d", __func__, len); |
297 | if (EVP_Cipher(&cc->evp, dest + aadlen, (u_char *)src + aadlen, | 345 | if (EVP_Cipher(&cc->evp, dest + aadlen, (u_char *)src + aadlen, |
298 | len) < 0) | 346 | len) < 0) |
299 | fatal("%s: EVP_Cipher failed", __func__); | 347 | fatal("%s: EVP_Cipher failed", __func__); |
348 | if (authlen) { | ||
349 | /* compute tag (on encrypt) or verify tag (on decrypt) */ | ||
350 | if (EVP_Cipher(&cc->evp, NULL, NULL, 0) < 0) | ||
351 | fatal("%s: EVP_Cipher(finish) failed", __func__); | ||
352 | if (cc->encrypt && | ||
353 | !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_GET_TAG, | ||
354 | authlen, dest + aadlen + len)) | ||
355 | fatal("%s: EVP_CTRL_GCM_GET_TAG", __func__); | ||
356 | } | ||
300 | } | 357 | } |
301 | 358 | ||
302 | void | 359 | void |