Annotation of src/usr.bin/ssh/cipher.c, Revision 1.47.2.1
1.1 deraadt 1: /*
1.30 deraadt 2: * Author: Tatu Ylonen <ylo@cs.hut.fi>
3: * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4: * All rights reserved
1.26 markus 5: *
1.30 deraadt 6: * As far as I am concerned, the code I have written for this software
7: * can be used freely for any purpose. Any derived versions of this
8: * software must be clearly marked as such, and if the derived work is
9: * incompatible with the protocol description in the RFC file, it must be
10: * called by a name other than "ssh" or "Secure Shell".
1.26 markus 11: *
12: *
1.30 deraadt 13: * Copyright (c) 1999 Niels Provos. All rights reserved.
1.46 markus 14: * Copyright (c) 1999, 2000 Markus Friedl. All rights reserved.
1.26 markus 15: *
1.30 deraadt 16: * Redistribution and use in source and binary forms, with or without
17: * modification, are permitted provided that the following conditions
18: * are met:
19: * 1. Redistributions of source code must retain the above copyright
20: * notice, this list of conditions and the following disclaimer.
21: * 2. Redistributions in binary form must reproduce the above copyright
22: * notice, this list of conditions and the following disclaimer in the
23: * documentation and/or other materials provided with the distribution.
1.26 markus 24: *
1.30 deraadt 25: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
1.17 deraadt 35: */
1.1 deraadt 36:
37: #include "includes.h"
1.47.2.1! jason 38: RCSID("$OpenBSD: cipher.c,v 1.52 2002/02/18 13:05:32 markus Exp $");
1.1 deraadt 39:
1.24 markus 40: #include "xmalloc.h"
1.42 markus 41: #include "log.h"
42: #include "cipher.h"
1.8 deraadt 43:
1.25 markus 44: #include <openssl/md5.h>
1.47.2.1! jason 45: #include "rijndael.h"
1.1 deraadt 46:
1.47.2.1! jason 47: static EVP_CIPHER *evp_ssh1_3des(void);
! 48: static EVP_CIPHER *evp_ssh1_bf(void);
! 49: static EVP_CIPHER *evp_rijndael(void);
! 50:
! 51: struct Cipher {
! 52: char *name;
! 53: int number; /* for ssh1 only */
! 54: u_int block_size;
! 55: u_int key_len;
! 56: EVP_CIPHER *(*evptype)(void);
! 57: } ciphers[] = {
! 58: { "none", SSH_CIPHER_NONE, 8, 0, EVP_enc_null },
! 59: { "des", SSH_CIPHER_DES, 8, 8, EVP_des_cbc },
! 60: { "3des", SSH_CIPHER_3DES, 8, 16, evp_ssh1_3des },
! 61: { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, evp_ssh1_bf },
! 62:
! 63: { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, EVP_des_ede3_cbc },
! 64: { "blowfish-cbc", SSH_CIPHER_SSH2, 8, 16, EVP_bf_cbc },
! 65: { "cast128-cbc", SSH_CIPHER_SSH2, 8, 16, EVP_cast5_cbc },
! 66: { "arcfour", SSH_CIPHER_SSH2, 8, 16, EVP_rc4 },
! 67: { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, evp_rijndael },
! 68: { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, evp_rijndael },
! 69: { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, evp_rijndael },
1.1 deraadt 70:
1.47.2.1! jason 71: { NULL, SSH_CIPHER_ILLEGAL, 0, 0, NULL }
! 72: };
1.1 deraadt 73:
1.47.2.1! jason 74: /*--*/
1.35 markus 75:
1.47.2.1! jason 76: u_int
! 77: cipher_blocksize(Cipher *c)
1.35 markus 78: {
1.47.2.1! jason 79: return (c->block_size);
1.35 markus 80: }
1.47.2.1! jason 81: u_int
! 82: cipher_keylen(Cipher *c)
1.35 markus 83: {
1.47.2.1! jason 84: return (c->key_len);
1.35 markus 85: }
1.1 deraadt 86:
1.41 markus 87: u_int
1.34 markus 88: cipher_mask_ssh1(int client)
1.1 deraadt 89: {
1.41 markus 90: u_int mask = 0;
1.47.2.1! jason 91: mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */
1.34 markus 92: mask |= 1 << SSH_CIPHER_BLOWFISH;
93: if (client) {
94: mask |= 1 << SSH_CIPHER_DES;
1.32 markus 95: }
96: return mask;
1.1 deraadt 97: }
98:
1.32 markus 99: Cipher *
100: cipher_by_name(const char *name)
101: {
102: Cipher *c;
103: for (c = ciphers; c->name != NULL; c++)
104: if (strcasecmp(c->name, name) == 0)
105: return c;
106: return NULL;
107: }
108:
109: Cipher *
110: cipher_by_number(int id)
111: {
112: Cipher *c;
113: for (c = ciphers; c->name != NULL; c++)
114: if (c->number == id)
115: return c;
116: return NULL;
117: }
1.24 markus 118:
119: #define CIPHER_SEP ","
120: int
121: ciphers_valid(const char *names)
122: {
1.32 markus 123: Cipher *c;
1.29 ho 124: char *ciphers, *cp;
1.24 markus 125: char *p;
126:
1.27 markus 127: if (names == NULL || strcmp(names, "") == 0)
1.24 markus 128: return 0;
1.29 ho 129: ciphers = cp = xstrdup(names);
1.32 markus 130: for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
1.47.2.1! jason 131: (p = strsep(&cp, CIPHER_SEP))) {
1.32 markus 132: c = cipher_by_name(p);
133: if (c == NULL || c->number != SSH_CIPHER_SSH2) {
134: debug("bad cipher %s [%s]", p, names);
1.24 markus 135: xfree(ciphers);
136: return 0;
1.32 markus 137: } else {
1.36 markus 138: debug3("cipher ok: %s [%s]", p, names);
1.24 markus 139: }
140: }
1.36 markus 141: debug3("ciphers ok: [%s]", names);
1.24 markus 142: xfree(ciphers);
143: return 1;
144: }
145:
1.18 markus 146: /*
147: * Parses the name of the cipher. Returns the number of the corresponding
148: * cipher, or -1 on error.
149: */
1.1 deraadt 150:
1.4 provos 151: int
152: cipher_number(const char *name)
1.1 deraadt 153: {
1.32 markus 154: Cipher *c;
1.27 markus 155: if (name == NULL)
156: return -1;
1.32 markus 157: c = cipher_by_name(name);
158: return (c==NULL) ? -1 : c->number;
1.1 deraadt 159: }
160:
1.32 markus 161: char *
162: cipher_name(int id)
1.1 deraadt 163: {
1.32 markus 164: Cipher *c = cipher_by_number(id);
165: return (c==NULL) ? "<unknown>" : c->name;
1.1 deraadt 166: }
167:
1.26 markus 168: void
1.32 markus 169: cipher_init(CipherContext *cc, Cipher *cipher,
1.47.2.1! jason 170: const u_char *key, u_int keylen, const u_char *iv, u_int ivlen,
! 171: int encrypt)
1.16 markus 172: {
1.47.2.1! jason 173: static int dowarn = 1;
! 174: const EVP_CIPHER *type;
! 175: int klen;
! 176:
! 177: if (cipher->number == SSH_CIPHER_DES) {
! 178: if (dowarn) {
! 179: error("Warning: use of DES is strongly discouraged "
! 180: "due to cryptographic weaknesses");
! 181: dowarn = 0;
! 182: }
! 183: if (keylen > 8)
! 184: keylen = 8;
! 185: }
! 186: cc->plaintext = (cipher->number == SSH_CIPHER_NONE);
! 187:
1.32 markus 188: if (keylen < cipher->key_len)
189: fatal("cipher_init: key length %d is insufficient for %s.",
190: keylen, cipher->name);
191: if (iv != NULL && ivlen < cipher->block_size)
192: fatal("cipher_init: iv length %d is insufficient for %s.",
193: ivlen, cipher->name);
194: cc->cipher = cipher;
1.47.2.1! jason 195:
! 196: type = (*cipher->evptype)();
! 197:
! 198: EVP_CIPHER_CTX_init(&cc->evp);
! 199: if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv,
! 200: (encrypt == CIPHER_ENCRYPT)) == 0)
! 201: fatal("cipher_init: EVP_CipherInit failed for %s",
! 202: cipher->name);
! 203: klen = EVP_CIPHER_CTX_key_length(&cc->evp);
! 204: if (klen > 0 && keylen != klen) {
! 205: debug("cipher_init: set keylen (%d -> %d)", klen, keylen);
! 206: if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0)
! 207: fatal("cipher_init: set keylen failed (%d -> %d)",
! 208: klen, keylen);
! 209: }
! 210: if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0)
! 211: fatal("cipher_init: EVP_CipherInit: set key failed for %s",
! 212: cipher->name);
1.1 deraadt 213: }
1.21 markus 214:
1.26 markus 215: void
1.47.2.1! jason 216: cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
1.32 markus 217: {
218: if (len % cc->cipher->block_size)
219: fatal("cipher_encrypt: bad plaintext length %d", len);
1.47.2.1! jason 220: if (EVP_Cipher(&cc->evp, dest, (u_char *)src, len) == 0)
! 221: fatal("evp_crypt: EVP_Cipher failed");
1.21 markus 222: }
223:
1.26 markus 224: void
1.47.2.1! jason 225: cipher_cleanup(CipherContext *cc)
1.16 markus 226: {
1.47.2.1! jason 227: if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0)
! 228: error("cipher_cleanup: EVP_CIPHER_CTX_cleanup failed");
1.16 markus 229: }
1.1 deraadt 230:
1.32 markus 231: /*
232: * Selects the cipher, and keys if by computing the MD5 checksum of the
233: * passphrase and using the resulting 16 bytes as the key.
234: */
1.1 deraadt 235:
1.26 markus 236: void
1.32 markus 237: cipher_set_key_string(CipherContext *cc, Cipher *cipher,
1.47.2.1! jason 238: const char *passphrase, int encrypt)
1.16 markus 239: {
1.32 markus 240: MD5_CTX md;
1.41 markus 241: u_char digest[16];
1.32 markus 242:
243: MD5_Init(&md);
244: MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase));
245: MD5_Final(digest, &md);
1.16 markus 246:
1.47.2.1! jason 247: cipher_init(cc, cipher, digest, 16, NULL, 0, encrypt);
1.16 markus 248:
1.32 markus 249: memset(digest, 0, sizeof(digest));
250: memset(&md, 0, sizeof(md));
1.47.2.1! jason 251: }
! 252:
! 253: /* Implementations for other non-EVP ciphers */
! 254:
! 255: /*
! 256: * This is used by SSH1:
! 257: *
! 258: * What kind of triple DES are these 2 routines?
! 259: *
! 260: * Why is there a redundant initialization vector?
! 261: *
! 262: * If only iv3 was used, then, this would till effect have been
! 263: * outer-cbc. However, there is also a private iv1 == iv2 which
! 264: * perhaps makes differential analysis easier. On the other hand, the
! 265: * private iv1 probably makes the CRC-32 attack ineffective. This is a
! 266: * result of that there is no longer any known iv1 to use when
! 267: * choosing the X block.
! 268: */
! 269: struct ssh1_3des_ctx
! 270: {
! 271: EVP_CIPHER_CTX k1, k2, k3;
! 272: };
! 273: static int
! 274: ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
! 275: int enc)
! 276: {
! 277: struct ssh1_3des_ctx *c;
! 278: u_char *k1, *k2, *k3;
! 279:
! 280: if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
! 281: c = xmalloc(sizeof(*c));
! 282: EVP_CIPHER_CTX_set_app_data(ctx, c);
! 283: }
! 284: if (key == NULL)
! 285: return (1);
! 286: if (enc == -1)
! 287: enc = ctx->encrypt;
! 288: k1 = k2 = k3 = (u_char *) key;
! 289: k2 += 8;
! 290: if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) {
! 291: if (enc)
! 292: k3 += 16;
! 293: else
! 294: k1 += 16;
! 295: }
! 296: EVP_CIPHER_CTX_init(&c->k1);
! 297: EVP_CIPHER_CTX_init(&c->k2);
! 298: EVP_CIPHER_CTX_init(&c->k3);
! 299: if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
! 300: EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
! 301: EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
! 302: memset(c, 0, sizeof(*c));
! 303: xfree(c);
! 304: EVP_CIPHER_CTX_set_app_data(ctx, NULL);
! 305: return (0);
! 306: }
! 307: return (1);
! 308: }
! 309: static int
! 310: ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len)
! 311: {
! 312: struct ssh1_3des_ctx *c;
! 313:
! 314: if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
! 315: error("ssh1_3des_cbc: no context");
! 316: return (0);
! 317: }
! 318: if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 ||
! 319: EVP_Cipher(&c->k2, dest, dest, len) == 0 ||
! 320: EVP_Cipher(&c->k3, dest, dest, len) == 0)
! 321: return (0);
! 322: return (1);
! 323: }
! 324: static int
! 325: ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
! 326: {
! 327: struct ssh1_3des_ctx *c;
! 328:
! 329: if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
! 330: memset(c, 0, sizeof(*c));
! 331: xfree(c);
! 332: EVP_CIPHER_CTX_set_app_data(ctx, NULL);
! 333: }
! 334: return (1);
! 335: }
! 336: static EVP_CIPHER *
! 337: evp_ssh1_3des(void)
! 338: {
! 339: static EVP_CIPHER ssh1_3des;
! 340:
! 341: memset(&ssh1_3des, 0, sizeof(EVP_CIPHER));
! 342: ssh1_3des.nid = NID_undef;
! 343: ssh1_3des.block_size = 8;
! 344: ssh1_3des.iv_len = 0;
! 345: ssh1_3des.key_len = 16;
! 346: ssh1_3des.init = ssh1_3des_init;
! 347: ssh1_3des.cleanup = ssh1_3des_cleanup;
! 348: ssh1_3des.do_cipher = ssh1_3des_cbc;
! 349: ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
! 350: return (&ssh1_3des);
! 351: }
! 352:
! 353: /*
! 354: * SSH1 uses a variation on Blowfish, all bytes must be swapped before
! 355: * and after encryption/decryption. Thus the swap_bytes stuff (yuk).
! 356: */
! 357: static void
! 358: swap_bytes(const u_char *src, u_char *dst, int n)
! 359: {
! 360: u_char c[4];
! 361:
! 362: /* Process 4 bytes every lap. */
! 363: for (n = n / 4; n > 0; n--) {
! 364: c[3] = *src++;
! 365: c[2] = *src++;
! 366: c[1] = *src++;
! 367: c[0] = *src++;
! 368:
! 369: *dst++ = c[0];
! 370: *dst++ = c[1];
! 371: *dst++ = c[2];
! 372: *dst++ = c[3];
! 373: }
! 374: }
! 375: static int (*orig_bf)(EVP_CIPHER_CTX *, u_char *, const u_char *, u_int) = NULL;
! 376: static int
! 377: bf_ssh1_cipher(EVP_CIPHER_CTX *ctx, u_char *out, const u_char *in, u_int len)
! 378: {
! 379: int ret;
! 380:
! 381: swap_bytes(in, out, len);
! 382: ret = (*orig_bf)(ctx, out, out, len);
! 383: swap_bytes(out, out, len);
! 384: return (ret);
! 385: }
! 386: static EVP_CIPHER *
! 387: evp_ssh1_bf(void)
! 388: {
! 389: static EVP_CIPHER ssh1_bf;
! 390:
! 391: memcpy(&ssh1_bf, EVP_bf_cbc(), sizeof(EVP_CIPHER));
! 392: orig_bf = ssh1_bf.do_cipher;
! 393: ssh1_bf.nid = NID_undef;
! 394: ssh1_bf.do_cipher = bf_ssh1_cipher;
! 395: ssh1_bf.key_len = 32;
! 396: return (&ssh1_bf);
! 397: }
! 398:
! 399: /* RIJNDAEL */
! 400: #define RIJNDAEL_BLOCKSIZE 16
! 401: struct ssh_rijndael_ctx
! 402: {
! 403: rijndael_ctx r_ctx;
! 404: u_char r_iv[RIJNDAEL_BLOCKSIZE];
! 405: };
! 406:
! 407: static int
! 408: ssh_rijndael_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
! 409: int enc)
! 410: {
! 411: struct ssh_rijndael_ctx *c;
! 412:
! 413: if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
! 414: c = xmalloc(sizeof(*c));
! 415: EVP_CIPHER_CTX_set_app_data(ctx, c);
! 416: }
! 417: if (key != NULL) {
! 418: if (enc == -1)
! 419: enc = ctx->encrypt;
! 420: rijndael_set_key(&c->r_ctx, (u_char *)key,
! 421: 8*EVP_CIPHER_CTX_key_length(ctx), enc);
! 422: }
! 423: if (iv != NULL)
! 424: memcpy(c->r_iv, iv, RIJNDAEL_BLOCKSIZE);
! 425: return (1);
! 426: }
! 427: static int
! 428: ssh_rijndael_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src,
! 429: u_int len)
! 430: {
! 431: struct ssh_rijndael_ctx *c;
! 432: u_char buf[RIJNDAEL_BLOCKSIZE];
! 433: u_char *cprev, *cnow, *plain, *ivp;
! 434: int i, j, blocks = len / RIJNDAEL_BLOCKSIZE;
! 435:
! 436: if (len == 0)
! 437: return (1);
! 438: if (len % RIJNDAEL_BLOCKSIZE)
! 439: fatal("ssh_rijndael_cbc: bad len %d", len);
! 440: if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
! 441: error("ssh_rijndael_cbc: no context");
! 442: return (0);
! 443: }
! 444: if (ctx->encrypt) {
! 445: cnow = dest;
! 446: plain = (u_char *)src;
! 447: cprev = c->r_iv;
! 448: for (i = 0; i < blocks; i++, plain+=RIJNDAEL_BLOCKSIZE,
! 449: cnow+=RIJNDAEL_BLOCKSIZE) {
! 450: for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++)
! 451: buf[j] = plain[j] ^ cprev[j];
! 452: rijndael_encrypt(&c->r_ctx, buf, cnow);
! 453: cprev = cnow;
! 454: }
! 455: memcpy(c->r_iv, cprev, RIJNDAEL_BLOCKSIZE);
! 456: } else {
! 457: cnow = (u_char *) (src+len-RIJNDAEL_BLOCKSIZE);
! 458: plain = dest+len-RIJNDAEL_BLOCKSIZE;
! 459:
! 460: memcpy(buf, cnow, RIJNDAEL_BLOCKSIZE);
! 461: for (i = blocks; i > 0; i--, cnow-=RIJNDAEL_BLOCKSIZE,
! 462: plain-=RIJNDAEL_BLOCKSIZE) {
! 463: rijndael_decrypt(&c->r_ctx, cnow, plain);
! 464: ivp = (i == 1) ? c->r_iv : cnow-RIJNDAEL_BLOCKSIZE;
! 465: for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++)
! 466: plain[j] ^= ivp[j];
! 467: }
! 468: memcpy(c->r_iv, buf, RIJNDAEL_BLOCKSIZE);
! 469: }
! 470: return (1);
! 471: }
! 472: static int
! 473: ssh_rijndael_cleanup(EVP_CIPHER_CTX *ctx)
! 474: {
! 475: struct ssh_rijndael_ctx *c;
! 476:
! 477: if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
! 478: memset(c, 0, sizeof(*c));
! 479: xfree(c);
! 480: EVP_CIPHER_CTX_set_app_data(ctx, NULL);
! 481: }
! 482: return (1);
! 483: }
! 484: static EVP_CIPHER *
! 485: evp_rijndael(void)
! 486: {
! 487: static EVP_CIPHER rijndal_cbc;
! 488:
! 489: memset(&rijndal_cbc, 0, sizeof(EVP_CIPHER));
! 490: rijndal_cbc.nid = NID_undef;
! 491: rijndal_cbc.block_size = RIJNDAEL_BLOCKSIZE;
! 492: rijndal_cbc.iv_len = RIJNDAEL_BLOCKSIZE;
! 493: rijndal_cbc.key_len = 16;
! 494: rijndal_cbc.init = ssh_rijndael_init;
! 495: rijndal_cbc.cleanup = ssh_rijndael_cleanup;
! 496: rijndal_cbc.do_cipher = ssh_rijndael_cbc;
! 497: rijndal_cbc.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH |
! 498: EVP_CIPH_ALWAYS_CALL_INIT;
! 499: return (&rijndal_cbc);
1.1 deraadt 500: }