2 * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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
34 #include "krb5_locl.h"
37 _krb5_evp_schedule(krb5_context context
,
38 struct _krb5_key_type
*kt
,
39 struct _krb5_key_data
*kd
)
41 struct _krb5_evp_schedule
*key
= kd
->schedule
->data
;
42 const EVP_CIPHER
*c
= (*kt
->evp
)();
44 EVP_CIPHER_CTX_init(&key
->ectx
);
45 EVP_CIPHER_CTX_init(&key
->dctx
);
47 EVP_CipherInit_ex(&key
->ectx
, c
, NULL
, kd
->key
->keyvalue
.data
, NULL
, 1);
48 EVP_CipherInit_ex(&key
->dctx
, c
, NULL
, kd
->key
->keyvalue
.data
, NULL
, 0);
52 _krb5_evp_cleanup(krb5_context context
, struct _krb5_key_data
*kd
)
54 struct _krb5_evp_schedule
*key
= kd
->schedule
->data
;
55 EVP_CIPHER_CTX_cleanup(&key
->ectx
);
56 EVP_CIPHER_CTX_cleanup(&key
->dctx
);
60 _krb5_evp_encrypt(krb5_context context
,
61 struct _krb5_key_data
*key
,
64 krb5_boolean encryptp
,
68 struct _krb5_evp_schedule
*ctx
= key
->schedule
->data
;
70 c
= encryptp
? &ctx
->ectx
: &ctx
->dctx
;
73 size_t len2
= EVP_CIPHER_CTX_iv_length(c
);
74 void *loiv
= malloc(len2
);
76 krb5_clear_error_message(context
);
79 memset(loiv
, 0, len2
);
80 EVP_CipherInit_ex(c
, NULL
, NULL
, NULL
, loiv
, -1);
83 EVP_CipherInit_ex(c
, NULL
, NULL
, NULL
, ivec
, -1);
84 EVP_Cipher(c
, data
, data
, len
);
88 static const unsigned char zero_ivec
[EVP_MAX_BLOCK_LENGTH
] = { 0 };
91 _krb5_evp_encrypt_cts(krb5_context context
,
92 struct _krb5_key_data
*key
,
95 krb5_boolean encryptp
,
100 struct _krb5_evp_schedule
*ctx
= key
->schedule
->data
;
101 unsigned char tmp
[EVP_MAX_BLOCK_LENGTH
], ivec2
[EVP_MAX_BLOCK_LENGTH
];
105 c
= encryptp
? &ctx
->ectx
: &ctx
->dctx
;
107 blocksize
= EVP_CIPHER_CTX_block_size(c
);
109 if (len
< blocksize
) {
110 krb5_set_error_message(context
, EINVAL
,
111 "message block too short");
113 } else if (len
== blocksize
) {
114 EVP_CipherInit_ex(c
, NULL
, NULL
, NULL
, zero_ivec
, -1);
115 EVP_Cipher(c
, data
, data
, len
);
120 EVP_CipherInit_ex(c
, NULL
, NULL
, NULL
, ivec
, -1);
122 EVP_CipherInit_ex(c
, NULL
, NULL
, NULL
, zero_ivec
, -1);
127 i
= ((len
- 1) / blocksize
) * blocksize
;
128 EVP_Cipher(c
, p
, p
, i
);
131 memcpy(ivec2
, p
, blocksize
);
133 for (i
= 0; i
< len
; i
++)
134 tmp
[i
] = p
[i
+ blocksize
] ^ ivec2
[i
];
135 for (; i
< blocksize
; i
++)
136 tmp
[i
] = 0 ^ ivec2
[i
];
138 EVP_CipherInit_ex(c
, NULL
, NULL
, NULL
, zero_ivec
, -1);
139 EVP_Cipher(c
, p
, tmp
, blocksize
);
141 memcpy(p
+ blocksize
, ivec2
, len
);
143 memcpy(ivec
, p
, blocksize
);
145 unsigned char tmp2
[EVP_MAX_BLOCK_LENGTH
], tmp3
[EVP_MAX_BLOCK_LENGTH
];
148 if (len
> blocksize
* 2) {
149 /* remove last two blocks and round up, decrypt this with cbc, then do cts dance */
150 i
= ((((len
- blocksize
* 2) + blocksize
- 1) / blocksize
) * blocksize
);
151 memcpy(ivec2
, p
+ i
- blocksize
, blocksize
);
152 EVP_Cipher(c
, p
, p
, i
);
154 len
-= i
+ blocksize
;
157 memcpy(ivec2
, ivec
, blocksize
);
159 memcpy(ivec2
, zero_ivec
, blocksize
);
163 memcpy(tmp
, p
, blocksize
);
164 EVP_CipherInit_ex(c
, NULL
, NULL
, NULL
, zero_ivec
, -1);
165 EVP_Cipher(c
, tmp2
, p
, blocksize
);
167 memcpy(tmp3
, p
+ blocksize
, len
);
168 memcpy(tmp3
+ len
, tmp2
+ len
, blocksize
- len
); /* xor 0 */
170 for (i
= 0; i
< len
; i
++)
171 p
[i
+ blocksize
] = tmp2
[i
] ^ tmp3
[i
];
173 EVP_CipherInit_ex(c
, NULL
, NULL
, NULL
, zero_ivec
, -1);
174 EVP_Cipher(c
, p
, tmp3
, blocksize
);
176 for (i
= 0; i
< blocksize
; i
++)
179 memcpy(ivec
, tmp
, blocksize
);