1 /* $NetBSD: crypto-evp.c,v 1.1.1.2 2014/04/24 12:45:49 pettai Exp $ */
4 * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
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.
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.
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
36 #include "krb5_locl.h"
39 _krb5_evp_schedule(krb5_context context
,
40 struct _krb5_key_type
*kt
,
41 struct _krb5_key_data
*kd
)
43 struct _krb5_evp_schedule
*key
= kd
->schedule
->data
;
44 const EVP_CIPHER
*c
= (*kt
->evp
)();
46 EVP_CIPHER_CTX_init(&key
->ectx
);
47 EVP_CIPHER_CTX_init(&key
->dctx
);
49 EVP_CipherInit_ex(&key
->ectx
, c
, NULL
, kd
->key
->keyvalue
.data
, NULL
, 1);
50 EVP_CipherInit_ex(&key
->dctx
, c
, NULL
, kd
->key
->keyvalue
.data
, NULL
, 0);
54 _krb5_evp_cleanup(krb5_context context
, struct _krb5_key_data
*kd
)
56 struct _krb5_evp_schedule
*key
= kd
->schedule
->data
;
57 EVP_CIPHER_CTX_cleanup(&key
->ectx
);
58 EVP_CIPHER_CTX_cleanup(&key
->dctx
);
62 _krb5_evp_encrypt(krb5_context context
,
63 struct _krb5_key_data
*key
,
66 krb5_boolean encryptp
,
70 struct _krb5_evp_schedule
*ctx
= key
->schedule
->data
;
72 c
= encryptp
? &ctx
->ectx
: &ctx
->dctx
;
75 size_t len2
= EVP_CIPHER_CTX_iv_length(c
);
76 void *loiv
= malloc(len2
);
78 krb5_clear_error_message(context
);
81 memset(loiv
, 0, len2
);
82 EVP_CipherInit_ex(c
, NULL
, NULL
, NULL
, loiv
, -1);
85 EVP_CipherInit_ex(c
, NULL
, NULL
, NULL
, ivec
, -1);
86 EVP_Cipher(c
, data
, data
, len
);
90 static const unsigned char zero_ivec
[EVP_MAX_BLOCK_LENGTH
] = { 0 };
93 _krb5_evp_encrypt_cts(krb5_context context
,
94 struct _krb5_key_data
*key
,
97 krb5_boolean encryptp
,
102 struct _krb5_evp_schedule
*ctx
= key
->schedule
->data
;
103 unsigned char tmp
[EVP_MAX_BLOCK_LENGTH
], ivec2
[EVP_MAX_BLOCK_LENGTH
];
107 c
= encryptp
? &ctx
->ectx
: &ctx
->dctx
;
109 blocksize
= EVP_CIPHER_CTX_block_size(c
);
111 if (len
< blocksize
) {
112 krb5_set_error_message(context
, EINVAL
,
113 "message block too short");
115 } else if (len
== blocksize
) {
116 EVP_CipherInit_ex(c
, NULL
, NULL
, NULL
, zero_ivec
, -1);
117 EVP_Cipher(c
, data
, data
, len
);
122 EVP_CipherInit_ex(c
, NULL
, NULL
, NULL
, ivec
, -1);
124 EVP_CipherInit_ex(c
, NULL
, NULL
, NULL
, zero_ivec
, -1);
129 i
= ((len
- 1) / blocksize
) * blocksize
;
130 EVP_Cipher(c
, p
, p
, i
);
133 memcpy(ivec2
, p
, blocksize
);
135 for (i
= 0; i
< len
; i
++)
136 tmp
[i
] = p
[i
+ blocksize
] ^ ivec2
[i
];
137 for (; i
< blocksize
; i
++)
138 tmp
[i
] = 0 ^ ivec2
[i
];
140 EVP_CipherInit_ex(c
, NULL
, NULL
, NULL
, zero_ivec
, -1);
141 EVP_Cipher(c
, p
, tmp
, blocksize
);
143 memcpy(p
+ blocksize
, ivec2
, len
);
145 memcpy(ivec
, p
, blocksize
);
147 unsigned char tmp2
[EVP_MAX_BLOCK_LENGTH
], tmp3
[EVP_MAX_BLOCK_LENGTH
];
150 if (len
> blocksize
* 2) {
151 /* remove last two blocks and round up, decrypt this with cbc, then do cts dance */
152 i
= ((((len
- blocksize
* 2) + blocksize
- 1) / blocksize
) * blocksize
);
153 memcpy(ivec2
, p
+ i
- blocksize
, blocksize
);
154 EVP_Cipher(c
, p
, p
, i
);
156 len
-= i
+ blocksize
;
159 memcpy(ivec2
, ivec
, blocksize
);
161 memcpy(ivec2
, zero_ivec
, blocksize
);
165 memcpy(tmp
, p
, blocksize
);
166 EVP_CipherInit_ex(c
, NULL
, NULL
, NULL
, zero_ivec
, -1);
167 EVP_Cipher(c
, tmp2
, p
, blocksize
);
169 memcpy(tmp3
, p
+ blocksize
, len
);
170 memcpy(tmp3
+ len
, tmp2
+ len
, blocksize
- len
); /* xor 0 */
172 for (i
= 0; i
< len
; i
++)
173 p
[i
+ blocksize
] = tmp2
[i
] ^ tmp3
[i
];
175 EVP_CipherInit_ex(c
, NULL
, NULL
, NULL
, zero_ivec
, -1);
176 EVP_Cipher(c
, p
, tmp3
, blocksize
);
178 for (i
= 0; i
< blocksize
; i
++)
181 memcpy(ivec
, tmp
, blocksize
);