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 return krb5_enomem(context
);
77 memset(loiv
, 0, len2
);
78 EVP_CipherInit_ex(c
, NULL
, NULL
, NULL
, loiv
, -1);
81 EVP_CipherInit_ex(c
, NULL
, NULL
, NULL
, ivec
, -1);
82 EVP_Cipher(c
, data
, data
, len
);
86 static const unsigned char zero_ivec
[EVP_MAX_BLOCK_LENGTH
] = { 0 };
89 _krb5_evp_encrypt_cts(krb5_context context
,
90 struct _krb5_key_data
*key
,
93 krb5_boolean encryptp
,
98 struct _krb5_evp_schedule
*ctx
= key
->schedule
->data
;
99 unsigned char tmp
[EVP_MAX_BLOCK_LENGTH
], ivec2
[EVP_MAX_BLOCK_LENGTH
];
103 c
= encryptp
? &ctx
->ectx
: &ctx
->dctx
;
105 blocksize
= EVP_CIPHER_CTX_block_size(c
);
107 if (len
< blocksize
) {
108 krb5_set_error_message(context
, EINVAL
,
109 "message block too short");
111 } else if (len
== blocksize
) {
112 EVP_CipherInit_ex(c
, NULL
, NULL
, NULL
, zero_ivec
, -1);
113 EVP_Cipher(c
, data
, data
, len
);
118 EVP_CipherInit_ex(c
, NULL
, NULL
, NULL
, ivec
, -1);
120 EVP_CipherInit_ex(c
, NULL
, NULL
, NULL
, zero_ivec
, -1);
125 i
= ((len
- 1) / blocksize
) * blocksize
;
126 EVP_Cipher(c
, p
, p
, i
);
129 memcpy(ivec2
, p
, blocksize
);
131 for (i
= 0; i
< len
; i
++)
132 tmp
[i
] = p
[i
+ blocksize
] ^ ivec2
[i
];
133 for (; i
< blocksize
; i
++)
134 tmp
[i
] = 0 ^ ivec2
[i
];
136 EVP_CipherInit_ex(c
, NULL
, NULL
, NULL
, zero_ivec
, -1);
137 EVP_Cipher(c
, p
, tmp
, blocksize
);
139 memcpy(p
+ blocksize
, ivec2
, len
);
141 memcpy(ivec
, p
, blocksize
);
143 unsigned char tmp2
[EVP_MAX_BLOCK_LENGTH
], tmp3
[EVP_MAX_BLOCK_LENGTH
];
146 if (len
> blocksize
* 2) {
147 /* remove last two blocks and round up, decrypt this with cbc, then do cts dance */
148 i
= ((((len
- blocksize
* 2) + blocksize
- 1) / blocksize
) * blocksize
);
149 memcpy(ivec2
, p
+ i
- blocksize
, blocksize
);
150 EVP_Cipher(c
, p
, p
, i
);
152 len
-= i
+ blocksize
;
155 memcpy(ivec2
, ivec
, blocksize
);
157 memcpy(ivec2
, zero_ivec
, blocksize
);
161 memcpy(tmp
, p
, blocksize
);
162 EVP_CipherInit_ex(c
, NULL
, NULL
, NULL
, zero_ivec
, -1);
163 EVP_Cipher(c
, tmp2
, p
, blocksize
);
165 memcpy(tmp3
, p
+ blocksize
, len
);
166 memcpy(tmp3
+ len
, tmp2
+ len
, blocksize
- len
); /* xor 0 */
168 for (i
= 0; i
< len
; i
++)
169 p
[i
+ blocksize
] = tmp2
[i
] ^ tmp3
[i
];
171 EVP_CipherInit_ex(c
, NULL
, NULL
, NULL
, zero_ivec
, -1);
172 EVP_Cipher(c
, p
, tmp3
, blocksize
);
174 for (i
= 0; i
< blocksize
; i
++)
177 memcpy(ivec
, tmp
, blocksize
);