1294332Sdes/* $OpenBSD: cipher-3des1.c,v 1.12 2015/01/14 10:24:42 markus Exp $ */ 2124208Sdes/* 3124208Sdes * Copyright (c) 2003 Markus Friedl. All rights reserved. 4124208Sdes * 5294332Sdes * Permission to use, copy, modify, and distribute this software for any 6294332Sdes * purpose with or without fee is hereby granted, provided that the above 7294332Sdes * copyright notice and this permission notice appear in all copies. 8124208Sdes * 9124208Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 10124208Sdes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 11124208Sdes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 12124208Sdes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 13124208Sdes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 14124208Sdes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 15124208Sdes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 16124208Sdes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 17124208Sdes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 18124208Sdes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 19124208Sdes */ 20124208Sdes 21124208Sdes#include "includes.h" 22124208Sdes 23323134Sdes#ifdef WITH_SSH1 24323134Sdes 25162852Sdes#include <sys/types.h> 26294332Sdes#include <string.h> 27124208Sdes#include <openssl/evp.h> 28162852Sdes 29294328Sdes#include "ssherr.h" 30124208Sdes 31124208Sdes/* 32124208Sdes * This is used by SSH1: 33124208Sdes * 34124208Sdes * What kind of triple DES are these 2 routines? 35124208Sdes * 36124208Sdes * Why is there a redundant initialization vector? 37124208Sdes * 38124208Sdes * If only iv3 was used, then, this would till effect have been 39124208Sdes * outer-cbc. However, there is also a private iv1 == iv2 which 40124208Sdes * perhaps makes differential analysis easier. On the other hand, the 41124208Sdes * private iv1 probably makes the CRC-32 attack ineffective. This is a 42124208Sdes * result of that there is no longer any known iv1 to use when 43124208Sdes * choosing the X block. 44124208Sdes */ 45124208Sdesstruct ssh1_3des_ctx 46124208Sdes{ 47124208Sdes EVP_CIPHER_CTX k1, k2, k3; 48124208Sdes}; 49124208Sdes 50124208Sdesconst EVP_CIPHER * evp_ssh1_3des(void); 51294328Sdesint ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); 52124208Sdes 53124208Sdesstatic int 54124208Sdesssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, 55124208Sdes int enc) 56124208Sdes{ 57124208Sdes struct ssh1_3des_ctx *c; 58124208Sdes u_char *k1, *k2, *k3; 59124208Sdes 60124208Sdes if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { 61294328Sdes if ((c = calloc(1, sizeof(*c))) == NULL) 62294328Sdes return 0; 63124208Sdes EVP_CIPHER_CTX_set_app_data(ctx, c); 64124208Sdes } 65124208Sdes if (key == NULL) 66294328Sdes return 1; 67124208Sdes if (enc == -1) 68124208Sdes enc = ctx->encrypt; 69124208Sdes k1 = k2 = k3 = (u_char *) key; 70124208Sdes k2 += 8; 71124208Sdes if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) { 72124208Sdes if (enc) 73124208Sdes k3 += 16; 74124208Sdes else 75124208Sdes k1 += 16; 76124208Sdes } 77124208Sdes EVP_CIPHER_CTX_init(&c->k1); 78124208Sdes EVP_CIPHER_CTX_init(&c->k2); 79124208Sdes EVP_CIPHER_CTX_init(&c->k3); 80124208Sdes if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 || 81124208Sdes EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 || 82124208Sdes EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) { 83263712Sdes explicit_bzero(c, sizeof(*c)); 84255767Sdes free(c); 85124208Sdes EVP_CIPHER_CTX_set_app_data(ctx, NULL); 86294328Sdes return 0; 87124208Sdes } 88294328Sdes return 1; 89124208Sdes} 90124208Sdes 91124208Sdesstatic int 92294328Sdesssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, size_t len) 93124208Sdes{ 94124208Sdes struct ssh1_3des_ctx *c; 95124208Sdes 96294328Sdes if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) 97294328Sdes return 0; 98124208Sdes if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 || 99124208Sdes EVP_Cipher(&c->k2, dest, dest, len) == 0 || 100124208Sdes EVP_Cipher(&c->k3, dest, dest, len) == 0) 101294328Sdes return 0; 102294328Sdes return 1; 103124208Sdes} 104124208Sdes 105124208Sdesstatic int 106124208Sdesssh1_3des_cleanup(EVP_CIPHER_CTX *ctx) 107124208Sdes{ 108124208Sdes struct ssh1_3des_ctx *c; 109124208Sdes 110124208Sdes if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) { 111126274Sdes EVP_CIPHER_CTX_cleanup(&c->k1); 112126274Sdes EVP_CIPHER_CTX_cleanup(&c->k2); 113126274Sdes EVP_CIPHER_CTX_cleanup(&c->k3); 114263712Sdes explicit_bzero(c, sizeof(*c)); 115255767Sdes free(c); 116124208Sdes EVP_CIPHER_CTX_set_app_data(ctx, NULL); 117124208Sdes } 118294328Sdes return 1; 119124208Sdes} 120124208Sdes 121294328Sdesint 122124208Sdesssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len) 123124208Sdes{ 124124208Sdes struct ssh1_3des_ctx *c; 125124208Sdes 126124208Sdes if (len != 24) 127294328Sdes return SSH_ERR_INVALID_ARGUMENT; 128124208Sdes if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL) 129294328Sdes return SSH_ERR_INTERNAL_ERROR; 130124208Sdes if (doset) { 131124208Sdes memcpy(c->k1.iv, iv, 8); 132124208Sdes memcpy(c->k2.iv, iv + 8, 8); 133124208Sdes memcpy(c->k3.iv, iv + 16, 8); 134124208Sdes } else { 135124208Sdes memcpy(iv, c->k1.iv, 8); 136124208Sdes memcpy(iv + 8, c->k2.iv, 8); 137124208Sdes memcpy(iv + 16, c->k3.iv, 8); 138124208Sdes } 139294328Sdes return 0; 140124208Sdes} 141124208Sdes 142124208Sdesconst EVP_CIPHER * 143124208Sdesevp_ssh1_3des(void) 144124208Sdes{ 145124208Sdes static EVP_CIPHER ssh1_3des; 146124208Sdes 147294332Sdes memset(&ssh1_3des, 0, sizeof(ssh1_3des)); 148124208Sdes ssh1_3des.nid = NID_undef; 149124208Sdes ssh1_3des.block_size = 8; 150124208Sdes ssh1_3des.iv_len = 0; 151124208Sdes ssh1_3des.key_len = 16; 152124208Sdes ssh1_3des.init = ssh1_3des_init; 153124208Sdes ssh1_3des.cleanup = ssh1_3des_cleanup; 154124208Sdes ssh1_3des.do_cipher = ssh1_3des_cbc; 155124208Sdes ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH; 156294328Sdes return &ssh1_3des; 157124208Sdes} 158323134Sdes#endif /* WITH_SSH1 */ 159