]>
Commit | Line | Data |
---|---|---|
dd030860 BM |
1 | /* crypto/evp/e_camellia.c -*- mode:C; c-file-style: "eay" -*- */ |
2 | /* ==================================================================== | |
3 | * Copyright (c) 2006 The OpenSSL Project. All rights reserved. | |
4 | * | |
5 | * Redistribution and use in source and binary forms, with or without | |
6 | * modification, are permitted provided that the following conditions | |
7 | * are met: | |
8 | * | |
9 | * 1. Redistributions of source code must retain the above copyright | |
ae5c8664 | 10 | * notice, this list of conditions and the following disclaimer. |
dd030860 BM |
11 | * |
12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in | |
14 | * the documentation and/or other materials provided with the | |
15 | * distribution. | |
16 | * | |
17 | * 3. All advertising materials mentioning features or use of this | |
18 | * software must display the following acknowledgment: | |
19 | * "This product includes software developed by the OpenSSL Project | |
20 | * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" | |
21 | * | |
22 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |
23 | * endorse or promote products derived from this software without | |
24 | * prior written permission. For written permission, please contact | |
25 | * openssl-core@openssl.org. | |
26 | * | |
27 | * 5. Products derived from this software may not be called "OpenSSL" | |
28 | * nor may "OpenSSL" appear in their names without prior written | |
29 | * permission of the OpenSSL Project. | |
30 | * | |
31 | * 6. Redistributions of any form whatsoever must retain the following | |
32 | * acknowledgment: | |
33 | * "This product includes software developed by the OpenSSL Project | |
34 | * for use in the OpenSSL Toolkit (http://www.openssl.org/)" | |
35 | * | |
36 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |
37 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
38 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
39 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |
40 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
41 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
42 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
43 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
44 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
45 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
46 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |
47 | * OF THE POSSIBILITY OF SUCH DAMAGE. | |
48 | * ==================================================================== | |
49 | * | |
50 | * This product includes cryptographic software written by Eric Young | |
51 | * (eay@cryptsoft.com). This product includes software written by Tim | |
52 | * Hudson (tjh@cryptsoft.com). | |
53 | * | |
54 | */ | |
55 | ||
56 | #include <openssl/opensslconf.h> | |
57 | #ifndef OPENSSL_NO_CAMELLIA | |
ae5c8664 MC |
58 | # include <openssl/evp.h> |
59 | # include <openssl/err.h> | |
60 | # include <string.h> | |
61 | # include <assert.h> | |
62 | # include <openssl/camellia.h> | |
63 | # include "evp_locl.h" | |
64 | # include "modes_lcl.h" | |
dd030860 BM |
65 | |
66 | static int camellia_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, | |
ae5c8664 | 67 | const unsigned char *iv, int enc); |
dd030860 BM |
68 | |
69 | /* Camellia subkey Structure */ | |
ae5c8664 MC |
70 | typedef struct { |
71 | CAMELLIA_KEY ks; | |
72 | block128_f block; | |
73 | union { | |
74 | cbc128_f cbc; | |
75 | ctr128_f ctr; | |
76 | } stream; | |
77 | } EVP_CAMELLIA_KEY; | |
78 | ||
79 | # define MAXBITCHUNK ((size_t)1<<(sizeof(size_t)*8-4)) | |
a1bf7de5 | 80 | |
dd030860 | 81 | /* Attribute operation for Camellia */ |
ae5c8664 | 82 | # define data(ctx) EVP_C_DATA(EVP_CAMELLIA_KEY,ctx) |
dd030860 | 83 | |
ae5c8664 | 84 | # if defined(AES_ASM) && (defined(__sparc) || defined(__sparc__)) |
a1bf7de5 AP |
85 | /* ---------^^^ this is not a typo, just a way to detect that |
86 | * assembler support was in general requested... */ | |
ae5c8664 | 87 | # include "sparc_arch.h" |
a1bf7de5 AP |
88 | |
89 | extern unsigned int OPENSSL_sparcv9cap_P[]; | |
90 | ||
ae5c8664 MC |
91 | # define SPARC_CMLL_CAPABLE (OPENSSL_sparcv9cap_P[1] & CFR_CAMELLIA) |
92 | ||
93 | void cmll_t4_set_key(const unsigned char *key, int bits, CAMELLIA_KEY *ks); | |
94 | void cmll_t4_encrypt(const unsigned char *in, unsigned char *out, | |
95 | const CAMELLIA_KEY *key); | |
96 | void cmll_t4_decrypt(const unsigned char *in, unsigned char *out, | |
97 | const CAMELLIA_KEY *key); | |
98 | ||
99 | void cmll128_t4_cbc_encrypt(const unsigned char *in, unsigned char *out, | |
100 | size_t len, const CAMELLIA_KEY *key, | |
101 | unsigned char *ivec); | |
102 | void cmll128_t4_cbc_decrypt(const unsigned char *in, unsigned char *out, | |
103 | size_t len, const CAMELLIA_KEY *key, | |
104 | unsigned char *ivec); | |
105 | void cmll256_t4_cbc_encrypt(const unsigned char *in, unsigned char *out, | |
106 | size_t len, const CAMELLIA_KEY *key, | |
107 | unsigned char *ivec); | |
108 | void cmll256_t4_cbc_decrypt(const unsigned char *in, unsigned char *out, | |
109 | size_t len, const CAMELLIA_KEY *key, | |
110 | unsigned char *ivec); | |
111 | void cmll128_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out, | |
112 | size_t blocks, const CAMELLIA_KEY *key, | |
113 | unsigned char *ivec); | |
114 | void cmll256_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out, | |
115 | size_t blocks, const CAMELLIA_KEY *key, | |
116 | unsigned char *ivec); | |
a1bf7de5 AP |
117 | |
118 | static int cmll_t4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, | |
ae5c8664 MC |
119 | const unsigned char *iv, int enc) |
120 | { | |
121 | int ret, mode, bits; | |
122 | EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *) ctx->cipher_data; | |
123 | ||
124 | mode = ctx->cipher->flags & EVP_CIPH_MODE; | |
125 | bits = ctx->key_len * 8; | |
126 | ||
127 | cmll_t4_set_key(key, bits, &dat->ks); | |
128 | ||
129 | if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) | |
130 | && !enc) { | |
131 | ret = 0; | |
132 | dat->block = (block128_f) cmll_t4_decrypt; | |
133 | switch (bits) { | |
134 | case 128: | |
135 | dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? | |
136 | (cbc128_f) cmll128_t4_cbc_decrypt : NULL; | |
137 | break; | |
138 | case 192: | |
139 | case 256: | |
140 | dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? | |
141 | (cbc128_f) cmll256_t4_cbc_decrypt : NULL; | |
142 | break; | |
143 | default: | |
144 | ret = -1; | |
145 | } | |
146 | } else { | |
147 | ret = 0; | |
148 | dat->block = (block128_f) cmll_t4_encrypt; | |
149 | switch (bits) { | |
150 | case 128: | |
151 | if (mode == EVP_CIPH_CBC_MODE) | |
152 | dat->stream.cbc = (cbc128_f) cmll128_t4_cbc_encrypt; | |
153 | else if (mode == EVP_CIPH_CTR_MODE) | |
154 | dat->stream.ctr = (ctr128_f) cmll128_t4_ctr32_encrypt; | |
155 | else | |
156 | dat->stream.cbc = NULL; | |
157 | break; | |
158 | case 192: | |
159 | case 256: | |
160 | if (mode == EVP_CIPH_CBC_MODE) | |
161 | dat->stream.cbc = (cbc128_f) cmll256_t4_cbc_encrypt; | |
162 | else if (mode == EVP_CIPH_CTR_MODE) | |
163 | dat->stream.ctr = (ctr128_f) cmll256_t4_ctr32_encrypt; | |
164 | else | |
165 | dat->stream.cbc = NULL; | |
166 | break; | |
167 | default: | |
168 | ret = -1; | |
169 | } | |
170 | } | |
171 | ||
172 | if (ret < 0) { | |
173 | EVPerr(EVP_F_CMLL_T4_INIT_KEY, EVP_R_CAMELLIA_KEY_SETUP_FAILED); | |
174 | return 0; | |
175 | } | |
176 | ||
177 | return 1; | |
178 | } | |
179 | ||
180 | # define cmll_t4_cbc_cipher camellia_cbc_cipher | |
181 | static int cmll_t4_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, | |
182 | const unsigned char *in, size_t len); | |
183 | ||
184 | # define cmll_t4_ecb_cipher camellia_ecb_cipher | |
185 | static int cmll_t4_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, | |
186 | const unsigned char *in, size_t len); | |
187 | ||
188 | # define cmll_t4_ofb_cipher camellia_ofb_cipher | |
189 | static int cmll_t4_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, | |
190 | const unsigned char *in, size_t len); | |
191 | ||
192 | # define cmll_t4_cfb_cipher camellia_cfb_cipher | |
193 | static int cmll_t4_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, | |
194 | const unsigned char *in, size_t len); | |
195 | ||
196 | # define cmll_t4_cfb8_cipher camellia_cfb8_cipher | |
197 | static int cmll_t4_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, | |
198 | const unsigned char *in, size_t len); | |
199 | ||
200 | # define cmll_t4_cfb1_cipher camellia_cfb1_cipher | |
201 | static int cmll_t4_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, | |
202 | const unsigned char *in, size_t len); | |
203 | ||
204 | # define cmll_t4_ctr_cipher camellia_ctr_cipher | |
a1bf7de5 | 205 | static int cmll_t4_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, |
ae5c8664 | 206 | const unsigned char *in, size_t len); |
a1bf7de5 | 207 | |
ae5c8664 | 208 | # define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \ |
a1bf7de5 | 209 | static const EVP_CIPHER cmll_t4_##keylen##_##mode = { \ |
ae5c8664 MC |
210 | nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \ |
211 | flags|EVP_CIPH_##MODE##_MODE, \ | |
212 | cmll_t4_init_key, \ | |
213 | cmll_t4_##mode##_cipher, \ | |
214 | NULL, \ | |
215 | sizeof(EVP_CAMELLIA_KEY), \ | |
216 | NULL,NULL,NULL,NULL }; \ | |
a1bf7de5 | 217 | static const EVP_CIPHER camellia_##keylen##_##mode = { \ |
ae5c8664 MC |
218 | nid##_##keylen##_##nmode,blocksize, \ |
219 | keylen/8,ivlen, \ | |
220 | flags|EVP_CIPH_##MODE##_MODE, \ | |
221 | camellia_init_key, \ | |
222 | camellia_##mode##_cipher, \ | |
223 | NULL, \ | |
224 | sizeof(EVP_CAMELLIA_KEY), \ | |
225 | NULL,NULL,NULL,NULL }; \ | |
a1bf7de5 AP |
226 | const EVP_CIPHER *EVP_camellia_##keylen##_##mode(void) \ |
227 | { return SPARC_CMLL_CAPABLE?&cmll_t4_##keylen##_##mode:&camellia_##keylen##_##mode; } | |
228 | ||
ae5c8664 | 229 | # else |
a1bf7de5 | 230 | |
ae5c8664 | 231 | # define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \ |
a1bf7de5 | 232 | static const EVP_CIPHER camellia_##keylen##_##mode = { \ |
ae5c8664 MC |
233 | nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \ |
234 | flags|EVP_CIPH_##MODE##_MODE, \ | |
235 | camellia_init_key, \ | |
236 | camellia_##mode##_cipher, \ | |
237 | NULL, \ | |
238 | sizeof(EVP_CAMELLIA_KEY), \ | |
239 | NULL,NULL,NULL,NULL }; \ | |
a1bf7de5 AP |
240 | const EVP_CIPHER *EVP_camellia_##keylen##_##mode(void) \ |
241 | { return &camellia_##keylen##_##mode; } | |
242 | ||
ae5c8664 | 243 | # endif |
dd030860 | 244 | |
ae5c8664 MC |
245 | # define BLOCK_CIPHER_generic_pack(nid,keylen,flags) \ |
246 | BLOCK_CIPHER_generic(nid,keylen,16,16,cbc,cbc,CBC,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \ | |
247 | BLOCK_CIPHER_generic(nid,keylen,16,0,ecb,ecb,ECB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \ | |
248 | BLOCK_CIPHER_generic(nid,keylen,1,16,ofb128,ofb,OFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \ | |
249 | BLOCK_CIPHER_generic(nid,keylen,1,16,cfb128,cfb,CFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \ | |
250 | BLOCK_CIPHER_generic(nid,keylen,1,16,cfb1,cfb1,CFB,flags) \ | |
251 | BLOCK_CIPHER_generic(nid,keylen,1,16,cfb8,cfb8,CFB,flags) | |
252 | # if 0 /* not yet, missing NID */ | |
253 | BLOCK_CIPHER_generic(nid, keylen, 1, 16, ctr, ctr, CTR, flags) | |
254 | # endif | |
255 | /* The subkey for Camellia is generated. */ | |
dd030860 | 256 | static int camellia_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, |
ae5c8664 | 257 | const unsigned char *iv, int enc) |
a1bf7de5 | 258 | { |
ae5c8664 MC |
259 | int ret, mode; |
260 | EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *) ctx->cipher_data; | |
261 | ||
262 | ret = Camellia_set_key(key, ctx->key_len * 8, &dat->ks); | |
263 | if (ret < 0) { | |
264 | EVPerr(EVP_F_CAMELLIA_INIT_KEY, EVP_R_CAMELLIA_KEY_SETUP_FAILED); | |
265 | return 0; | |
266 | } | |
267 | ||
268 | mode = ctx->cipher->flags & EVP_CIPH_MODE; | |
269 | if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) | |
270 | && !enc) { | |
271 | dat->block = (block128_f) Camellia_decrypt; | |
272 | dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? | |
273 | (cbc128_f) Camellia_cbc_encrypt : NULL; | |
274 | } else { | |
275 | dat->block = (block128_f) Camellia_encrypt; | |
276 | dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? | |
277 | (cbc128_f) Camellia_cbc_encrypt : NULL; | |
278 | } | |
279 | ||
280 | return 1; | |
281 | } | |
a1bf7de5 | 282 | |
ae5c8664 MC |
283 | static int camellia_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, |
284 | const unsigned char *in, size_t len) | |
285 | { | |
286 | EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *) ctx->cipher_data; | |
287 | ||
288 | if (dat->stream.cbc) | |
289 | (*dat->stream.cbc) (in, out, len, &dat->ks, ctx->iv, ctx->encrypt); | |
290 | else if (ctx->encrypt) | |
291 | CRYPTO_cbc128_encrypt(in, out, len, &dat->ks, ctx->iv, dat->block); | |
292 | else | |
293 | CRYPTO_cbc128_decrypt(in, out, len, &dat->ks, ctx->iv, dat->block); | |
a1bf7de5 | 294 | |
ae5c8664 | 295 | return 1; |
a1bf7de5 AP |
296 | } |
297 | ||
ae5c8664 MC |
298 | static int camellia_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, |
299 | const unsigned char *in, size_t len) | |
a1bf7de5 | 300 | { |
ae5c8664 MC |
301 | size_t bl = ctx->cipher->block_size; |
302 | size_t i; | |
303 | EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *) ctx->cipher_data; | |
a1bf7de5 | 304 | |
ae5c8664 MC |
305 | if (len < bl) |
306 | return 1; | |
a1bf7de5 | 307 | |
ae5c8664 MC |
308 | for (i = 0, len -= bl; i <= len; i += bl) |
309 | (*dat->block) (in + i, out + i, &dat->ks); | |
a1bf7de5 | 310 | |
ae5c8664 | 311 | return 1; |
a1bf7de5 AP |
312 | } |
313 | ||
ae5c8664 MC |
314 | static int camellia_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, |
315 | const unsigned char *in, size_t len) | |
a1bf7de5 | 316 | { |
ae5c8664 | 317 | EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *) ctx->cipher_data; |
a1bf7de5 | 318 | |
ae5c8664 MC |
319 | CRYPTO_ofb128_encrypt(in, out, len, &dat->ks, |
320 | ctx->iv, &ctx->num, dat->block); | |
321 | return 1; | |
a1bf7de5 AP |
322 | } |
323 | ||
ae5c8664 MC |
324 | static int camellia_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, |
325 | const unsigned char *in, size_t len) | |
a1bf7de5 | 326 | { |
ae5c8664 | 327 | EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *) ctx->cipher_data; |
a1bf7de5 | 328 | |
ae5c8664 MC |
329 | CRYPTO_cfb128_encrypt(in, out, len, &dat->ks, |
330 | ctx->iv, &ctx->num, ctx->encrypt, dat->block); | |
331 | return 1; | |
a1bf7de5 AP |
332 | } |
333 | ||
ae5c8664 MC |
334 | static int camellia_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, |
335 | const unsigned char *in, size_t len) | |
a1bf7de5 | 336 | { |
ae5c8664 | 337 | EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *) ctx->cipher_data; |
a1bf7de5 | 338 | |
ae5c8664 MC |
339 | CRYPTO_cfb128_8_encrypt(in, out, len, &dat->ks, |
340 | ctx->iv, &ctx->num, ctx->encrypt, dat->block); | |
341 | return 1; | |
a1bf7de5 AP |
342 | } |
343 | ||
ae5c8664 MC |
344 | static int camellia_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, |
345 | const unsigned char *in, size_t len) | |
a1bf7de5 | 346 | { |
ae5c8664 MC |
347 | EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *) ctx->cipher_data; |
348 | ||
349 | if (ctx->flags & EVP_CIPH_FLAG_LENGTH_BITS) { | |
350 | CRYPTO_cfb128_1_encrypt(in, out, len, &dat->ks, | |
351 | ctx->iv, &ctx->num, ctx->encrypt, dat->block); | |
352 | return 1; | |
353 | } | |
354 | ||
355 | while (len >= MAXBITCHUNK) { | |
356 | CRYPTO_cfb128_1_encrypt(in, out, MAXBITCHUNK * 8, &dat->ks, | |
357 | ctx->iv, &ctx->num, ctx->encrypt, dat->block); | |
358 | len -= MAXBITCHUNK; | |
359 | } | |
360 | if (len) | |
361 | CRYPTO_cfb128_1_encrypt(in, out, len * 8, &dat->ks, | |
362 | ctx->iv, &ctx->num, ctx->encrypt, dat->block); | |
363 | ||
364 | return 1; | |
a1bf7de5 AP |
365 | } |
366 | ||
ae5c8664 MC |
367 | # if 0 /* not yet, missing NID */ |
368 | static int camellia_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, | |
369 | const unsigned char *in, size_t len) | |
a1bf7de5 | 370 | { |
ae5c8664 MC |
371 | unsigned int num = ctx->num; |
372 | EVP_CAMELLIA_KEY *dat = (EVP_CAMELLIA_KEY *) ctx->cipher_data; | |
373 | ||
374 | if (dat->stream.ctr) | |
375 | CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks, | |
376 | ctx->iv, ctx->buf, &num, dat->stream.ctr); | |
377 | else | |
378 | CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, | |
379 | ctx->iv, ctx->buf, &num, dat->block); | |
380 | ctx->num = (size_t)num; | |
381 | return 1; | |
a1bf7de5 | 382 | } |
ae5c8664 | 383 | # endif |
a1bf7de5 | 384 | |
ae5c8664 MC |
385 | BLOCK_CIPHER_generic_pack(NID_camellia, 128, 0) |
386 | BLOCK_CIPHER_generic_pack(NID_camellia, 192, 0) | |
387 | BLOCK_CIPHER_generic_pack(NID_camellia, 256, 0) | |
02c9b66a DSH |
388 | #else |
389 | ||
390 | # ifdef PEDANTIC | |
ae5c8664 | 391 | static void *dummy = &dummy; |
02c9b66a DSH |
392 | # endif |
393 | ||
dd030860 | 394 | #endif |