1/* 2 * Copyright (c) 2006 - 2007 Kungliga Tekniska H��gskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#include <config.h> 35 36#define HC_DEPRECATED 37 38#include <sys/types.h> 39#include <stdio.h> 40#include <stdlib.h> 41#include <string.h> 42#include <assert.h> 43 44 45#include <krb5-types.h> 46 47#if defined(BUILD_KRB5_LIB) && defined(HAVE_OPENSSL) 48#include <openssl/evp.h> 49#include <openssl/aes.h> 50 51#define _hc_EVP_hcrypto_aes_128_cts _krb5_EVP_hcrypto_aes_128_cts 52#define _hc_EVP_hcrypto_aes_192_cts _krb5_EVP_hcrypto_aes_192_cts 53#define _hc_EVP_hcrypto_aes_256_cts _krb5_EVP_hcrypto_aes_256_cts 54 55const EVP_CIPHER * _krb5_EVP_hcrypto_aes_128_cts(void); 56const EVP_CIPHER * _krb5_EVP_hcrypto_aes_192_cts(void); 57const EVP_CIPHER * _krb5_EVP_hcrypto_aes_256_cts(void); 58 59#else 60#include <evp.h> 61#include <aes.h> 62 63#define _hc_EVP_hcrypto_aes_128_cts hc_EVP_hcrypto_aes_128_cts 64#define _hc_EVP_hcrypto_aes_192_cts hc_EVP_hcrypto_aes_192_cts 65#define _hc_EVP_hcrypto_aes_256_cts hc_EVP_hcrypto_aes_256_cts 66 67#endif 68 69/* 70 * 71 */ 72 73static int 74aes_cts_init(EVP_CIPHER_CTX *ctx, 75 const unsigned char * key, 76 const unsigned char * iv, 77 int encp) 78{ 79 AES_KEY *k = ctx->cipher_data; 80 if (ctx->encrypt) 81 AES_set_encrypt_key(key, ctx->cipher->key_len * 8, k); 82 else 83 AES_set_decrypt_key(key, ctx->cipher->key_len * 8, k); 84 return 1; 85} 86 87static void 88_krb5_aes_cts_encrypt(const unsigned char *in, unsigned char *out, 89 size_t len, const AES_KEY *key, 90 unsigned char *ivec, const int encryptp) 91{ 92 unsigned char tmp[AES_BLOCK_SIZE]; 93 int i; 94 95 /* 96 * In the framework of kerberos, the length can never be shorter 97 * then at least one blocksize. 98 */ 99 100 if (encryptp) { 101 102 while(len > AES_BLOCK_SIZE) { 103 for (i = 0; i < AES_BLOCK_SIZE; i++) 104 tmp[i] = in[i] ^ ivec[i]; 105 AES_encrypt(tmp, out, key); 106 memcpy(ivec, out, AES_BLOCK_SIZE); 107 len -= AES_BLOCK_SIZE; 108 in += AES_BLOCK_SIZE; 109 out += AES_BLOCK_SIZE; 110 } 111 112 for (i = 0; i < len; i++) 113 tmp[i] = in[i] ^ ivec[i]; 114 for (; i < AES_BLOCK_SIZE; i++) 115 tmp[i] = 0 ^ ivec[i]; 116 117 AES_encrypt(tmp, out - AES_BLOCK_SIZE, key); 118 119 memcpy(out, ivec, len); 120 memcpy(ivec, out - AES_BLOCK_SIZE, AES_BLOCK_SIZE); 121 122 } else { 123 unsigned char tmp2[AES_BLOCK_SIZE]; 124 unsigned char tmp3[AES_BLOCK_SIZE]; 125 126 while(len > AES_BLOCK_SIZE * 2) { 127 memcpy(tmp, in, AES_BLOCK_SIZE); 128 AES_decrypt(in, out, key); 129 for (i = 0; i < AES_BLOCK_SIZE; i++) 130 out[i] ^= ivec[i]; 131 memcpy(ivec, tmp, AES_BLOCK_SIZE); 132 len -= AES_BLOCK_SIZE; 133 in += AES_BLOCK_SIZE; 134 out += AES_BLOCK_SIZE; 135 } 136 137 len -= AES_BLOCK_SIZE; 138 139 memcpy(tmp, in, AES_BLOCK_SIZE); /* save last iv */ 140 AES_decrypt(in, tmp2, key); 141 142 memcpy(tmp3, in + AES_BLOCK_SIZE, len); 143 memcpy(tmp3 + len, tmp2 + len, AES_BLOCK_SIZE - len); /* xor 0 */ 144 145 for (i = 0; i < len; i++) 146 out[i + AES_BLOCK_SIZE] = tmp2[i] ^ tmp3[i]; 147 148 AES_decrypt(tmp3, out, key); 149 for (i = 0; i < AES_BLOCK_SIZE; i++) 150 out[i] ^= ivec[i]; 151 memcpy(ivec, tmp, AES_BLOCK_SIZE); 152 } 153} 154 155static int 156aes_cts_do_cipher(EVP_CIPHER_CTX *ctx, 157 unsigned char *out, 158 const unsigned char *in, 159 unsigned int len) 160{ 161 AES_KEY *k = ctx->cipher_data; 162 163 if (len < AES_BLOCK_SIZE) 164 abort(); /* krb5_abortx(context, "invalid use of AES_CTS_encrypt"); */ 165 if (len == AES_BLOCK_SIZE) { 166 if (ctx->encrypt) 167 AES_encrypt(in, out, k); 168 else 169 AES_decrypt(in, out, k); 170 } else { 171 _krb5_aes_cts_encrypt(in, out, len, k, ctx->iv, ctx->encrypt); 172 } 173 174 return 1; 175} 176 177 178static int 179aes_cts_cleanup(EVP_CIPHER_CTX *ctx) 180{ 181 memset(ctx->cipher_data, 0, sizeof(AES_KEY)); 182 return 1; 183} 184 185/** 186 * The AES-128 cts cipher type (hcrypto) 187 * 188 * @return the AES-128 EVP_CIPHER pointer. 189 * 190 * @ingroup hcrypto_evp 191 */ 192 193const EVP_CIPHER * 194_hc_EVP_hcrypto_aes_128_cts(void) 195{ 196 static const EVP_CIPHER aes_128_cts = { 197 0, 198 1, 199 16, 200 16, 201 EVP_CIPH_CBC_MODE, 202 aes_cts_init, 203 aes_cts_do_cipher, 204 aes_cts_cleanup, 205 sizeof(AES_KEY), 206 NULL, 207 NULL, 208 NULL, 209 NULL 210 }; 211 212 return &aes_128_cts; 213} 214 215/** 216 * The AES-192 cts cipher type (hcrypto) 217 * 218 * @return the AES-192 EVP_CIPHER pointer. 219 * 220 * @ingroup hcrypto_evp 221 */ 222 223const EVP_CIPHER * 224_hc_EVP_hcrypto_aes_192_cts(void) 225{ 226 static const EVP_CIPHER aes_192_cts = { 227 0, 228 1, 229 24, 230 16, 231 EVP_CIPH_CBC_MODE, 232 aes_cts_init, 233 aes_cts_do_cipher, 234 aes_cts_cleanup, 235 sizeof(AES_KEY), 236 NULL, 237 NULL, 238 NULL, 239 NULL 240 }; 241 242 return &aes_192_cts; 243} 244 245/** 246 * The AES-256 cts cipher type (hcrypto) 247 * 248 * @return the AES-256 EVP_CIPHER pointer. 249 * 250 * @ingroup hcrypto_evp 251 */ 252 253const EVP_CIPHER * 254_hc_EVP_hcrypto_aes_256_cts(void) 255{ 256 static const EVP_CIPHER aes_256_cts = { 257 0, 258 1, 259 32, 260 16, 261 EVP_CIPH_CBC_MODE, 262 aes_cts_init, 263 aes_cts_do_cipher, 264 aes_cts_cleanup, 265 sizeof(AES_KEY), 266 NULL, 267 NULL, 268 NULL, 269 NULL 270 }; 271 272 return &aes_256_cts; 273} 274