1 /* $NetBSD: crypto-evp.c,v 1.3 2018/02/05 16:00:53 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include "krb5_locl.h" 37 38 void 39 _krb5_evp_schedule(krb5_context context, 40 struct _krb5_key_type *kt, 41 struct _krb5_key_data *kd) 42 { 43 struct _krb5_evp_schedule *key = kd->schedule->data; 44 const EVP_CIPHER *c = (*kt->evp)(); 45 46 #if OPENSSL_VERSION_NUMBER < 0x10100000UL 47 key->ectx = malloc(sizeof(*key->ectx)); 48 key->dctx = malloc(sizeof(*key->dctx)); 49 EVP_CIPHER_CTX_init(key->ectx); 50 EVP_CIPHER_CTX_init(key->dctx); 51 #else 52 key->ectx = EVP_CIPHER_CTX_new(); 53 key->dctx = EVP_CIPHER_CTX_new(); 54 #endif 55 56 EVP_CipherInit_ex(key->ectx, c, NULL, kd->key->keyvalue.data, NULL, 1); 57 EVP_CipherInit_ex(key->dctx, c, NULL, kd->key->keyvalue.data, NULL, 0); 58 } 59 60 void 61 _krb5_evp_cleanup(krb5_context context, struct _krb5_key_data *kd) 62 { 63 struct _krb5_evp_schedule *key = kd->schedule->data; 64 #if OPENSSL_VERSION_NUMBER < 0x10100000UL 65 EVP_CIPHER_CTX_cleanup(key->ectx); 66 EVP_CIPHER_CTX_cleanup(key->dctx); 67 free(key->ectx); 68 free(key->dctx); 69 #else 70 EVP_CIPHER_CTX_free(key->ectx); 71 EVP_CIPHER_CTX_free(key->dctx); 72 #endif 73 } 74 75 krb5_error_code 76 _krb5_evp_encrypt(krb5_context context, 77 struct _krb5_key_data *key, 78 void *data, 79 size_t len, 80 krb5_boolean encryptp, 81 int usage, 82 void *ivec) 83 { 84 struct _krb5_evp_schedule *ctx = key->schedule->data; 85 EVP_CIPHER_CTX *c; 86 c = encryptp ? ctx->ectx : ctx->dctx; 87 if (ivec == NULL) { 88 /* alloca ? */ 89 size_t len2 = EVP_CIPHER_CTX_iv_length(c); 90 void *loiv = malloc(len2); 91 if (loiv == NULL) 92 return krb5_enomem(context); 93 memset(loiv, 0, len2); 94 EVP_CipherInit_ex(c, NULL, NULL, NULL, loiv, -1); 95 free(loiv); 96 } else 97 EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1); 98 EVP_Cipher(c, data, data, len); 99 return 0; 100 } 101 102 static const unsigned char zero_ivec[EVP_MAX_BLOCK_LENGTH] = { 0 }; 103 104 krb5_error_code 105 _krb5_evp_encrypt_cts(krb5_context context, 106 struct _krb5_key_data *key, 107 void *data, 108 size_t len, 109 krb5_boolean encryptp, 110 int usage, 111 void *ivec) 112 { 113 size_t i, blocksize; 114 struct _krb5_evp_schedule *ctx = key->schedule->data; 115 unsigned char tmp[EVP_MAX_BLOCK_LENGTH], ivec2[EVP_MAX_BLOCK_LENGTH]; 116 EVP_CIPHER_CTX *c; 117 unsigned char *p; 118 119 c = encryptp ? ctx->ectx : ctx->dctx; 120 121 blocksize = EVP_CIPHER_CTX_block_size(c); 122 123 if (len < blocksize) { 124 krb5_set_error_message(context, EINVAL, 125 "message block too short"); 126 return EINVAL; 127 } else if (len == blocksize) { 128 EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1); 129 EVP_Cipher(c, data, data, len); 130 return 0; 131 } 132 133 if (ivec) 134 EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1); 135 else 136 EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1); 137 138 if (encryptp) { 139 140 p = data; 141 i = ((len - 1) / blocksize) * blocksize; 142 EVP_Cipher(c, p, p, i); 143 p += i - blocksize; 144 len -= i; 145 memcpy(ivec2, p, blocksize); 146 147 for (i = 0; i < len; i++) 148 tmp[i] = p[i + blocksize] ^ ivec2[i]; 149 for (; i < blocksize; i++) 150 tmp[i] = 0 ^ ivec2[i]; 151 152 EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1); 153 EVP_Cipher(c, p, tmp, blocksize); 154 155 memcpy(p + blocksize, ivec2, len); 156 if (ivec) 157 memcpy(ivec, p, blocksize); 158 } else { 159 unsigned char tmp2[EVP_MAX_BLOCK_LENGTH], tmp3[EVP_MAX_BLOCK_LENGTH]; 160 161 p = data; 162 if (len > blocksize * 2) { 163 /* remove last two blocks and round up, decrypt this with cbc, then do cts dance */ 164 i = ((((len - blocksize * 2) + blocksize - 1) / blocksize) * blocksize); 165 memcpy(ivec2, p + i - blocksize, blocksize); 166 EVP_Cipher(c, p, p, i); 167 p += i; 168 len -= i + blocksize; 169 } else { 170 if (ivec) 171 memcpy(ivec2, ivec, blocksize); 172 else 173 memcpy(ivec2, zero_ivec, blocksize); 174 len -= blocksize; 175 } 176 177 memcpy(tmp, p, blocksize); 178 EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1); 179 EVP_Cipher(c, tmp2, p, blocksize); 180 181 memcpy(tmp3, p + blocksize, len); 182 memcpy(tmp3 + len, tmp2 + len, blocksize - len); /* xor 0 */ 183 184 for (i = 0; i < len; i++) 185 p[i + blocksize] = tmp2[i] ^ tmp3[i]; 186 187 EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1); 188 EVP_Cipher(c, p, tmp3, blocksize); 189 190 for (i = 0; i < blocksize; i++) 191 p[i] ^= ivec2[i]; 192 if (ivec) 193 memcpy(ivec, tmp, blocksize); 194 } 195 return 0; 196 } 197