Annotation of src/usr.bin/ssh/cipher-3des1.c, Revision 1.1
1.1 ! markus 1: /*
! 2: * Copyright (c) 2003 Markus Friedl. All rights reserved.
! 3: *
! 4: * Redistribution and use in source and binary forms, with or without
! 5: * modification, are permitted provided that the following conditions
! 6: * are met:
! 7: * 1. Redistributions of source code must retain the above copyright
! 8: * notice, this list of conditions and the following disclaimer.
! 9: * 2. Redistributions in binary form must reproduce the above copyright
! 10: * notice, this list of conditions and the following disclaimer in the
! 11: * documentation and/or other materials provided with the distribution.
! 12: *
! 13: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 14: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 15: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 16: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 17: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 18: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 19: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 20: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 21: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 22: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 23: */
! 24:
! 25: #include "includes.h"
! 26: RCSID("$OpenBSD: $");
! 27:
! 28: #include <openssl/evp.h>
! 29: #include "xmalloc.h"
! 30: #include "log.h"
! 31:
! 32: /*
! 33: * This is used by SSH1:
! 34: *
! 35: * What kind of triple DES are these 2 routines?
! 36: *
! 37: * Why is there a redundant initialization vector?
! 38: *
! 39: * If only iv3 was used, then, this would till effect have been
! 40: * outer-cbc. However, there is also a private iv1 == iv2 which
! 41: * perhaps makes differential analysis easier. On the other hand, the
! 42: * private iv1 probably makes the CRC-32 attack ineffective. This is a
! 43: * result of that there is no longer any known iv1 to use when
! 44: * choosing the X block.
! 45: */
! 46: struct ssh1_3des_ctx
! 47: {
! 48: EVP_CIPHER_CTX k1, k2, k3;
! 49: };
! 50:
! 51: const EVP_CIPHER * evp_ssh1_3des(void);
! 52: void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
! 53:
! 54: static int
! 55: ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
! 56: int enc)
! 57: {
! 58: struct ssh1_3des_ctx *c;
! 59: u_char *k1, *k2, *k3;
! 60:
! 61: if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
! 62: c = xmalloc(sizeof(*c));
! 63: EVP_CIPHER_CTX_set_app_data(ctx, c);
! 64: }
! 65: if (key == NULL)
! 66: return (1);
! 67: if (enc == -1)
! 68: enc = ctx->encrypt;
! 69: k1 = k2 = k3 = (u_char *) key;
! 70: k2 += 8;
! 71: if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) {
! 72: if (enc)
! 73: k3 += 16;
! 74: else
! 75: k1 += 16;
! 76: }
! 77: EVP_CIPHER_CTX_init(&c->k1);
! 78: EVP_CIPHER_CTX_init(&c->k2);
! 79: EVP_CIPHER_CTX_init(&c->k3);
! 80: if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
! 81: EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
! 82: EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
! 83: memset(c, 0, sizeof(*c));
! 84: xfree(c);
! 85: EVP_CIPHER_CTX_set_app_data(ctx, NULL);
! 86: return (0);
! 87: }
! 88: return (1);
! 89: }
! 90:
! 91: static int
! 92: ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len)
! 93: {
! 94: struct ssh1_3des_ctx *c;
! 95:
! 96: if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
! 97: error("ssh1_3des_cbc: no context");
! 98: return (0);
! 99: }
! 100: if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 ||
! 101: EVP_Cipher(&c->k2, dest, dest, len) == 0 ||
! 102: EVP_Cipher(&c->k3, dest, dest, len) == 0)
! 103: return (0);
! 104: return (1);
! 105: }
! 106:
! 107: static int
! 108: ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
! 109: {
! 110: struct ssh1_3des_ctx *c;
! 111:
! 112: if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
! 113: memset(c, 0, sizeof(*c));
! 114: xfree(c);
! 115: EVP_CIPHER_CTX_set_app_data(ctx, NULL);
! 116: }
! 117: return (1);
! 118: }
! 119:
! 120: void
! 121: ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len)
! 122: {
! 123: struct ssh1_3des_ctx *c;
! 124:
! 125: if (len != 24)
! 126: fatal("%s: bad 3des iv length: %d", __func__, len);
! 127: if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
! 128: fatal("%s: no 3des context", __func__);
! 129: if (doset) {
! 130: debug3("%s: Installed 3DES IV", __func__);
! 131: memcpy(c->k1.iv, iv, 8);
! 132: memcpy(c->k2.iv, iv + 8, 8);
! 133: memcpy(c->k3.iv, iv + 16, 8);
! 134: } else {
! 135: debug3("%s: Copying 3DES IV", __func__);
! 136: memcpy(iv, c->k1.iv, 8);
! 137: memcpy(iv + 8, c->k2.iv, 8);
! 138: memcpy(iv + 16, c->k3.iv, 8);
! 139: }
! 140: }
! 141:
! 142: const EVP_CIPHER *
! 143: evp_ssh1_3des(void)
! 144: {
! 145: static EVP_CIPHER ssh1_3des;
! 146:
! 147: memset(&ssh1_3des, 0, sizeof(EVP_CIPHER));
! 148: ssh1_3des.nid = NID_undef;
! 149: ssh1_3des.block_size = 8;
! 150: ssh1_3des.iv_len = 0;
! 151: ssh1_3des.key_len = 16;
! 152: ssh1_3des.init = ssh1_3des_init;
! 153: ssh1_3des.cleanup = ssh1_3des_cleanup;
! 154: ssh1_3des.do_cipher = ssh1_3des_cbc;
! 155: ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
! 156: return (&ssh1_3des);
! 157: }