Line data Source code
1 : /*
2 : * Copyright (c) 1997 - 2008 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 "krb5_locl.h"
35 :
36 : void
37 3306830 : _krb5_evp_schedule(krb5_context context,
38 : struct _krb5_key_type *kt,
39 : struct _krb5_key_data *kd)
40 : {
41 3306830 : struct _krb5_evp_schedule *key = kd->schedule->data;
42 3306830 : const EVP_CIPHER *c = (*kt->evp)();
43 :
44 3306830 : EVP_CIPHER_CTX_init(&key->ectx);
45 3306830 : EVP_CIPHER_CTX_init(&key->dctx);
46 :
47 3306830 : EVP_CipherInit_ex(&key->ectx, c, NULL, kd->key->keyvalue.data, NULL, 1);
48 3306830 : EVP_CipherInit_ex(&key->dctx, c, NULL, kd->key->keyvalue.data, NULL, 0);
49 3306830 : }
50 :
51 : void
52 3306796 : _krb5_evp_cleanup(krb5_context context, struct _krb5_key_data *kd)
53 : {
54 3306796 : struct _krb5_evp_schedule *key = kd->schedule->data;
55 3306796 : EVP_CIPHER_CTX_cleanup(&key->ectx);
56 3306796 : EVP_CIPHER_CTX_cleanup(&key->dctx);
57 3306796 : }
58 :
59 : krb5_error_code
60 0 : _krb5_evp_encrypt(krb5_context context,
61 : struct _krb5_key_data *key,
62 : void *data,
63 : size_t len,
64 : krb5_boolean encryptp,
65 : int usage,
66 : void *ivec)
67 : {
68 0 : struct _krb5_evp_schedule *ctx = key->schedule->data;
69 : EVP_CIPHER_CTX *c;
70 0 : c = encryptp ? &ctx->ectx : &ctx->dctx;
71 0 : if (ivec == NULL) {
72 : /* alloca ? */
73 0 : size_t len2 = EVP_CIPHER_CTX_iv_length(c);
74 0 : void *loiv = malloc(len2);
75 0 : if (loiv == NULL) {
76 0 : krb5_clear_error_message(context);
77 0 : return ENOMEM;
78 : }
79 0 : memset(loiv, 0, len2);
80 0 : EVP_CipherInit_ex(c, NULL, NULL, NULL, loiv, -1);
81 0 : free(loiv);
82 : } else
83 0 : EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1);
84 0 : EVP_Cipher(c, data, data, len);
85 0 : return 0;
86 : }
87 :
88 : static const unsigned char zero_ivec[EVP_MAX_BLOCK_LENGTH] = { 0 };
89 :
90 : krb5_error_code
91 5391111 : _krb5_evp_encrypt_cts(krb5_context context,
92 : struct _krb5_key_data *key,
93 : void *data,
94 : size_t len,
95 : krb5_boolean encryptp,
96 : int usage,
97 : void *ivec)
98 : {
99 : size_t i, blocksize;
100 5391111 : struct _krb5_evp_schedule *ctx = key->schedule->data;
101 : unsigned char tmp[EVP_MAX_BLOCK_LENGTH], ivec2[EVP_MAX_BLOCK_LENGTH];
102 : EVP_CIPHER_CTX *c;
103 : unsigned char *p;
104 :
105 5391111 : c = encryptp ? &ctx->ectx : &ctx->dctx;
106 :
107 5391111 : blocksize = EVP_CIPHER_CTX_block_size(c);
108 :
109 5391111 : if (len < blocksize) {
110 0 : krb5_set_error_message(context, EINVAL,
111 : "message block too short");
112 0 : return EINVAL;
113 5391111 : } else if (len == blocksize) {
114 3217031 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
115 3217031 : EVP_Cipher(c, data, data, len);
116 3217031 : return 0;
117 : }
118 :
119 2174080 : if (ivec)
120 0 : EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1);
121 : else
122 2174080 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
123 :
124 2174080 : if (encryptp) {
125 :
126 1362616 : p = data;
127 1362616 : i = ((len - 1) / blocksize) * blocksize;
128 1362616 : EVP_Cipher(c, p, p, i);
129 1362616 : p += i - blocksize;
130 1362616 : len -= i;
131 1362616 : memcpy(ivec2, p, blocksize);
132 :
133 19702389 : for (i = 0; i < len; i++)
134 18339773 : tmp[i] = p[i + blocksize] ^ ivec2[i];
135 4817362 : for (; i < blocksize; i++)
136 3462083 : tmp[i] = 0 ^ ivec2[i];
137 :
138 1362616 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
139 1362616 : EVP_Cipher(c, p, tmp, blocksize);
140 :
141 1369953 : memcpy(p + blocksize, ivec2, len);
142 1362616 : if (ivec)
143 0 : memcpy(ivec, p, blocksize);
144 : } else {
145 : unsigned char tmp2[EVP_MAX_BLOCK_LENGTH], tmp3[EVP_MAX_BLOCK_LENGTH];
146 :
147 811464 : p = data;
148 811464 : if (len > blocksize * 2) {
149 : /* remove last two blocks and round up, decrypt this with cbc, then do cts dance */
150 811464 : i = ((((len - blocksize * 2) + blocksize - 1) / blocksize) * blocksize);
151 818940 : memcpy(ivec2, p + i - blocksize, blocksize);
152 811464 : EVP_Cipher(c, p, p, i);
153 811464 : p += i;
154 811464 : len -= i + blocksize;
155 : } else {
156 0 : if (ivec)
157 0 : memcpy(ivec2, ivec, blocksize);
158 : else
159 0 : memcpy(ivec2, zero_ivec, blocksize);
160 0 : len -= blocksize;
161 : }
162 :
163 811464 : memcpy(tmp, p, blocksize);
164 811464 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
165 811464 : EVP_Cipher(c, tmp2, p, blocksize);
166 :
167 818940 : memcpy(tmp3, p + blocksize, len);
168 818940 : memcpy(tmp3 + len, tmp2 + len, blocksize - len); /* xor 0 */
169 :
170 10196651 : for (i = 0; i < len; i++)
171 9385187 : p[i + blocksize] = tmp2[i] ^ tmp3[i];
172 :
173 811464 : EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
174 811464 : EVP_Cipher(c, p, tmp3, blocksize);
175 :
176 13794888 : for (i = 0; i < blocksize; i++)
177 12983424 : p[i] ^= ivec2[i];
178 811464 : if (ivec)
179 0 : memcpy(ivec, tmp, blocksize);
180 : }
181 2159267 : return 0;
182 : }
|