Home | History | Annotate | Line # | Download | only in lib
      1 /*-
      2  * Copyright (c) 2009 The NetBSD Foundation, Inc.
      3  * All rights reserved.
      4  *
      5  * This code is derived from software contributed to The NetBSD Foundation
      6  * by Alistair Crooks (agc (at) NetBSD.org)
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    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.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     20  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     27  * POSSIBILITY OF SUCH DAMAGE.
     28  */
     29 /*
     30  * Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
     31  * All rights reserved.
     32  * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
     33  * their moral rights under the UK Copyright Design and Patents Act 1988 to
     34  * be recorded as the authors of this copyright work.
     35  *
     36  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
     37  * use this file except in compliance with the License.
     38  *
     39  * You may obtain a copy of the License at
     40  *     http://www.apache.org/licenses/LICENSE-2.0
     41  *
     42  * Unless required by applicable law or agreed to in writing, software
     43  * distributed under the License is distributed on an "AS IS" BASIS,
     44  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     45  *
     46  * See the License for the specific language governing permissions and
     47  * limitations under the License.
     48  */
     49 #include "config.h"
     50 
     51 #ifdef HAVE_SYS_CDEFS_H
     52 #include <sys/cdefs.h>
     53 #endif
     54 
     55 #if defined(__NetBSD__)
     56 __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
     57 __RCSID("$NetBSD: symmetric.c,v 1.19 2020/04/18 19:27:48 jhigh Exp $");
     58 #endif
     59 
     60 #include "crypto.h"
     61 #include "packet-show.h"
     62 
     63 #include <string.h>
     64 
     65 #ifdef HAVE_OPENSSL_CAST_H
     66 #include <openssl/cast.h>
     67 #endif
     68 
     69 #ifdef HAVE_OPENSSL_IDEA_H
     70 #include <openssl/idea.h>
     71 #endif
     72 
     73 #ifdef HAVE_OPENSSL_AES_H
     74 #include <openssl/aes.h>
     75 #endif
     76 
     77 #ifdef HAVE_OPENSSL_DES_H
     78 #include <openssl/des.h>
     79 #endif
     80 
     81 #ifdef HAVE_OPENSSL_CAMELLIA_H
     82 #include <openssl/camellia.h>
     83 #endif
     84 
     85 #ifdef HAVE_OPENSSL_BLOWFISH_H
     86 #include <openssl/blowfish.h>
     87 #endif
     88 
     89 #include "crypto.h"
     90 #include "netpgpdefs.h"
     91 
     92 
     93 static void
     94 std_set_iv(pgp_crypt_t *crypt, const uint8_t *iv)
     95 {
     96 	(void) memcpy(crypt->iv, iv, crypt->blocksize);
     97 	crypt->num = 0;
     98 }
     99 
    100 static void
    101 std_set_key(pgp_crypt_t *crypt, const uint8_t *key)
    102 {
    103 	(void) memcpy(crypt->key, key, crypt->keysize);
    104 }
    105 
    106 static void
    107 std_resync(pgp_crypt_t *decrypt)
    108 {
    109 	if ((size_t) decrypt->num == decrypt->blocksize) {
    110 		return;
    111 	}
    112 
    113 	memmove(decrypt->civ + decrypt->blocksize - decrypt->num, decrypt->civ,
    114 		(unsigned)decrypt->num);
    115 	(void) memcpy(decrypt->civ, decrypt->siv + decrypt->num,
    116 	       decrypt->blocksize - decrypt->num);
    117 	decrypt->num = 0;
    118 }
    119 
    120 static void
    121 std_finish(pgp_crypt_t *crypt)
    122 {
    123 	if (crypt->encrypt_key) {
    124 		free(crypt->encrypt_key);
    125 		crypt->encrypt_key = NULL;
    126 	}
    127 	if (crypt->decrypt_key) {
    128 		free(crypt->decrypt_key);
    129 		crypt->decrypt_key = NULL;
    130 	}
    131 }
    132 
    133 static int
    134 cast5_init(pgp_crypt_t *crypt)
    135 {
    136 	if (crypt->encrypt_key) {
    137 		free(crypt->encrypt_key);
    138 	}
    139 	if ((crypt->encrypt_key = calloc(1, sizeof(CAST_KEY))) == NULL) {
    140 		(void) fprintf(stderr, "cast5_init: alloc failure\n");
    141 		return 0;
    142 	}
    143 	CAST_set_key(crypt->encrypt_key, (int)crypt->keysize, crypt->key);
    144 	if ((crypt->decrypt_key = calloc(1, sizeof(CAST_KEY))) == NULL) {
    145 		(void) fprintf(stderr, "cast5_init: alloc failure\n");
    146 		return 0;
    147 	}
    148 	CAST_set_key(crypt->decrypt_key, (int)crypt->keysize, crypt->key);
    149 	return 1;
    150 }
    151 
    152 static void
    153 cast5_block_encrypt(pgp_crypt_t *crypt, void *out, const void *in)
    154 {
    155 	CAST_ecb_encrypt(in, out, crypt->encrypt_key, CAST_ENCRYPT);
    156 }
    157 
    158 static void
    159 cast5_block_decrypt(pgp_crypt_t *crypt, void *out, const void *in)
    160 {
    161 	CAST_ecb_encrypt(in, out, crypt->encrypt_key, CAST_DECRYPT);
    162 }
    163 
    164 static void
    165 cast5_cfb_encrypt(pgp_crypt_t *crypt, void *out, const void *in, size_t count)
    166 {
    167 	CAST_cfb64_encrypt(in, out, (long)count,
    168 			   crypt->encrypt_key, crypt->iv, &crypt->num,
    169 			   CAST_ENCRYPT);
    170 }
    171 
    172 static void
    173 cast5_cfb_decrypt(pgp_crypt_t *crypt, void *out, const void *in, size_t count)
    174 {
    175 	CAST_cfb64_encrypt(in, out, (long)count,
    176 			   crypt->encrypt_key, crypt->iv, &crypt->num,
    177 			   CAST_DECRYPT);
    178 }
    179 
    180 #define TRAILER		"","","","",0,NULL,NULL
    181 
    182 static pgp_crypt_t cast5 =
    183 {
    184 	PGP_SA_CAST5,
    185 	CAST_BLOCK,
    186 	CAST_KEY_LENGTH,
    187 	std_set_iv,
    188 	std_set_key,
    189 	cast5_init,
    190 	std_resync,
    191 	cast5_block_encrypt,
    192 	cast5_block_decrypt,
    193 	cast5_cfb_encrypt,
    194 	cast5_cfb_decrypt,
    195 	std_finish,
    196 	TRAILER
    197 };
    198 
    199 #ifdef HAVE_OPENSSL_BLOWFISH_H
    200 
    201 /* RFC 4880 9.2 Blowfish 128 */
    202 #define BLOWFISH_KEY_LENGTH	16
    203 
    204 static int
    205 blowfish_init(pgp_crypt_t *crypt)
    206 {
    207         if (crypt->encrypt_key) {
    208                 free(crypt->encrypt_key);
    209         }
    210         if (crypt->keysize != BLOWFISH_KEY_LENGTH) {
    211                (void) fprintf(stderr, "blowfish_init: keysize wrong\n");
    212                return 0;
    213         }
    214         if ((crypt->encrypt_key = calloc(1, sizeof(BF_KEY))) == NULL) {
    215                 (void) fprintf(stderr, "blowfish_init: alloc failure\n");
    216                 return 0;
    217         }
    218         BF_set_key(crypt->encrypt_key, (int)crypt->keysize, crypt->key);
    219         if ((crypt->decrypt_key = calloc(1, sizeof(BF_KEY))) == NULL) {
    220                 (void) fprintf(stderr, "blowfish_init: alloc failure\n");
    221                 return 0;
    222         }
    223         BF_set_key(crypt->decrypt_key, (int)crypt->keysize, crypt->key);
    224         return 1;
    225 }
    226 
    227 static void
    228 blowfish_block_encrypt(pgp_crypt_t *crypt, void *out, const void *in)
    229 {
    230         BF_ecb_encrypt(in, out, crypt->encrypt_key, BF_ENCRYPT);
    231 }
    232 
    233 static void
    234 blowfish_block_decrypt(pgp_crypt_t *crypt, void *out, const void *in)
    235 {
    236         BF_ecb_encrypt(in, out, crypt->encrypt_key, BF_DECRYPT);
    237 }
    238 
    239 static void
    240 blowfish_cfb_encrypt(pgp_crypt_t *crypt, void *out, const void *in, size_t count)
    241 {
    242         BF_cfb64_encrypt(in, out, (long)count,
    243                          crypt->encrypt_key, crypt->iv, &crypt->num,
    244                          BF_ENCRYPT);
    245 }
    246 
    247 static void
    248 blowfish_cfb_decrypt(pgp_crypt_t *crypt, void *out, const void *in, size_t count)
    249 {
    250         BF_cfb64_encrypt(in, out, (long)count,
    251                          crypt->encrypt_key, crypt->iv, &crypt->num,
    252                          BF_DECRYPT);
    253 }
    254 
    255 static pgp_crypt_t blowfish =
    256 {
    257         PGP_SA_BLOWFISH,
    258         BF_BLOCK,
    259         BLOWFISH_KEY_LENGTH,
    260         std_set_iv,
    261         std_set_key,
    262         blowfish_init,
    263         std_resync,
    264         blowfish_block_encrypt,
    265         blowfish_block_decrypt,
    266         blowfish_cfb_encrypt,
    267         blowfish_cfb_decrypt,
    268         std_finish,
    269         TRAILER
    270 };
    271 
    272 #endif /* HAVE_OPENSSL_BLOWFISH_H */
    273 
    274 #ifndef OPENSSL_NO_IDEA
    275 static int
    276 idea_init(pgp_crypt_t *crypt)
    277 {
    278 	if (crypt->keysize != IDEA_KEY_LENGTH) {
    279 		(void) fprintf(stderr, "idea_init: keysize wrong\n");
    280 		return 0;
    281 	}
    282 
    283 	if (crypt->encrypt_key) {
    284 		free(crypt->encrypt_key);
    285 	}
    286 	if ((crypt->encrypt_key = calloc(1, sizeof(IDEA_KEY_SCHEDULE))) == NULL) {
    287 		(void) fprintf(stderr, "idea_init: alloc failure\n");
    288 		return 0;
    289 	}
    290 
    291 	/* note that we don't invert the key when decrypting for CFB mode */
    292 	idea_set_encrypt_key(crypt->key, crypt->encrypt_key);
    293 
    294 	if (crypt->decrypt_key) {
    295 		free(crypt->decrypt_key);
    296 	}
    297 	if ((crypt->decrypt_key = calloc(1, sizeof(IDEA_KEY_SCHEDULE))) == NULL) {
    298 		(void) fprintf(stderr, "idea_init: alloc failure\n");
    299 		return 0;
    300 	}
    301 
    302 	idea_set_decrypt_key(crypt->encrypt_key, crypt->decrypt_key);
    303 	return 1;
    304 }
    305 
    306 static void
    307 idea_block_encrypt(pgp_crypt_t *crypt, void *out, const void *in)
    308 {
    309 	idea_ecb_encrypt(in, out, crypt->encrypt_key);
    310 }
    311 
    312 static void
    313 idea_block_decrypt(pgp_crypt_t *crypt, void *out, const void *in)
    314 {
    315 	idea_ecb_encrypt(in, out, crypt->decrypt_key);
    316 }
    317 
    318 static void
    319 idea_cfb_encrypt(pgp_crypt_t *crypt, void *out, const void *in, size_t count)
    320 {
    321 	idea_cfb64_encrypt(in, out, (long)count,
    322 			   crypt->encrypt_key, crypt->iv, &crypt->num,
    323 			   CAST_ENCRYPT);
    324 }
    325 
    326 static void
    327 idea_cfb_decrypt(pgp_crypt_t *crypt, void *out, const void *in, size_t count)
    328 {
    329 	idea_cfb64_encrypt(in, out, (long)count,
    330 			   crypt->decrypt_key, crypt->iv, &crypt->num,
    331 			   CAST_DECRYPT);
    332 }
    333 
    334 static const pgp_crypt_t idea =
    335 {
    336 	PGP_SA_IDEA,
    337 	IDEA_BLOCK,
    338 	IDEA_KEY_LENGTH,
    339 	std_set_iv,
    340 	std_set_key,
    341 	idea_init,
    342 	std_resync,
    343 	idea_block_encrypt,
    344 	idea_block_decrypt,
    345 	idea_cfb_encrypt,
    346 	idea_cfb_decrypt,
    347 	std_finish,
    348 	TRAILER
    349 };
    350 #endif				/* OPENSSL_NO_IDEA */
    351 
    352 /* AES with 128-bit key (AES) */
    353 
    354 #define KEYBITS_AES128 128
    355 
    356 static int
    357 aes128_init(pgp_crypt_t *crypt)
    358 {
    359 	if (crypt->encrypt_key) {
    360 		free(crypt->encrypt_key);
    361 	}
    362 	if ((crypt->encrypt_key = calloc(1, sizeof(AES_KEY))) == NULL) {
    363 		(void) fprintf(stderr, "aes128_init: alloc failure\n");
    364 		return 0;
    365 	}
    366 	if (AES_set_encrypt_key(crypt->key, KEYBITS_AES128,
    367 			crypt->encrypt_key)) {
    368 		fprintf(stderr, "aes128_init: Error setting encrypt_key\n");
    369 	}
    370 
    371 	if (crypt->decrypt_key) {
    372 		free(crypt->decrypt_key);
    373 	}
    374 	if ((crypt->decrypt_key = calloc(1, sizeof(AES_KEY))) == NULL) {
    375 		(void) fprintf(stderr, "aes128_init: alloc failure\n");
    376 		return 0;
    377 	}
    378 	if (AES_set_decrypt_key(crypt->key, KEYBITS_AES128,
    379 				crypt->decrypt_key)) {
    380 		fprintf(stderr, "aes128_init: Error setting decrypt_key\n");
    381 	}
    382 	return 1;
    383 }
    384 
    385 static void
    386 aes_block_encrypt(pgp_crypt_t *crypt, void *out, const void *in)
    387 {
    388 	AES_encrypt(in, out, crypt->encrypt_key);
    389 }
    390 
    391 static void
    392 aes_block_decrypt(pgp_crypt_t *crypt, void *out, const void *in)
    393 {
    394 	AES_decrypt(in, out, crypt->decrypt_key);
    395 }
    396 
    397 static void
    398 aes_cfb_encrypt(pgp_crypt_t *crypt, void *out, const void *in, size_t count)
    399 {
    400 	AES_cfb128_encrypt(in, out, (unsigned)count,
    401 			   crypt->encrypt_key, crypt->iv, &crypt->num,
    402 			   AES_ENCRYPT);
    403 }
    404 
    405 static void
    406 aes_cfb_decrypt(pgp_crypt_t *crypt, void *out, const void *in, size_t count)
    407 {
    408 	AES_cfb128_encrypt(in, out, (unsigned)count,
    409 			   crypt->encrypt_key, crypt->iv, &crypt->num,
    410 			   AES_DECRYPT);
    411 }
    412 
    413 static const pgp_crypt_t aes128 =
    414 {
    415 	PGP_SA_AES_128,
    416 	AES_BLOCK_SIZE,
    417 	KEYBITS_AES128 / 8,
    418 	std_set_iv,
    419 	std_set_key,
    420 	aes128_init,
    421 	std_resync,
    422 	aes_block_encrypt,
    423 	aes_block_decrypt,
    424 	aes_cfb_encrypt,
    425 	aes_cfb_decrypt,
    426 	std_finish,
    427 	TRAILER
    428 };
    429 
    430 /* AES with 256-bit key */
    431 
    432 #define KEYBITS_AES256 256
    433 
    434 static int
    435 aes256_init(pgp_crypt_t *crypt)
    436 {
    437 	if (crypt->encrypt_key) {
    438 		free(crypt->encrypt_key);
    439 	}
    440 	if ((crypt->encrypt_key = calloc(1, sizeof(AES_KEY))) == NULL) {
    441 		(void) fprintf(stderr, "aes256_init: alloc failure\n");
    442 		return 0;
    443 	}
    444 	if (AES_set_encrypt_key(crypt->key, KEYBITS_AES256,
    445 			crypt->encrypt_key)) {
    446 		fprintf(stderr, "aes256_init: Error setting encrypt_key\n");
    447 		free(crypt->encrypt_key);
    448 		crypt->encrypt_key = NULL;
    449 		return 0;
    450 	}
    451 	if (crypt->decrypt_key) {
    452 		free(crypt->decrypt_key);
    453 	}
    454 	if ((crypt->decrypt_key = calloc(1, sizeof(AES_KEY))) == NULL) {
    455 		(void) fprintf(stderr, "aes256_init: alloc failure\n");
    456 		free(crypt->encrypt_key);
    457 		crypt->encrypt_key = NULL;
    458 		return 0;
    459 	}
    460 	if (AES_set_decrypt_key(crypt->key, KEYBITS_AES256,
    461 			crypt->decrypt_key)) {
    462 		fprintf(stderr, "aes256_init: Error setting decrypt_key\n");
    463 		free(crypt->encrypt_key);
    464 		crypt->encrypt_key = NULL;
    465 		free(crypt->decrypt_key);
    466 		crypt->decrypt_key = NULL;
    467 		return 0;
    468 	}
    469 	return 1;
    470 }
    471 
    472 static const pgp_crypt_t aes256 =
    473 {
    474 	PGP_SA_AES_256,
    475 	AES_BLOCK_SIZE,
    476 	KEYBITS_AES256 / 8,
    477 	std_set_iv,
    478 	std_set_key,
    479 	aes256_init,
    480 	std_resync,
    481 	aes_block_encrypt,
    482 	aes_block_decrypt,
    483 	aes_cfb_encrypt,
    484 	aes_cfb_decrypt,
    485 	std_finish,
    486 	TRAILER
    487 };
    488 
    489 /* Triple DES */
    490 
    491 static int
    492 tripledes_init(pgp_crypt_t *crypt)
    493 {
    494 	DES_key_schedule *keys;
    495 	int             n;
    496 
    497 	if (crypt->encrypt_key) {
    498 		free(crypt->encrypt_key);
    499 	}
    500 	if ((keys = crypt->encrypt_key = calloc(1, 3 * sizeof(DES_key_schedule))) == NULL) {
    501 		(void) fprintf(stderr, "tripledes_init: alloc failure\n");
    502 		return 0;
    503 	}
    504 	for (n = 0; n < 3; ++n) {
    505 		DES_set_key((DES_cblock *)(void *)(crypt->key + n * 8),
    506 			&keys[n]);
    507 	}
    508 	return 1;
    509 }
    510 
    511 static void
    512 tripledes_block_encrypt(pgp_crypt_t *crypt, void *out, const void *in)
    513 {
    514 	DES_key_schedule *keys = crypt->encrypt_key;
    515 
    516 	DES_ecb3_encrypt(__UNCONST(in), out, &keys[0], &keys[1], &keys[2],
    517 			DES_ENCRYPT);
    518 }
    519 
    520 static void
    521 tripledes_block_decrypt(pgp_crypt_t *crypt, void *out, const void *in)
    522 {
    523 	DES_key_schedule *keys = crypt->encrypt_key;
    524 
    525 	DES_ecb3_encrypt(__UNCONST(in), out, &keys[0], &keys[1], &keys[2],
    526 			DES_DECRYPT);
    527 }
    528 
    529 static void
    530 tripledes_cfb_encrypt(pgp_crypt_t *crypt, void *out, const void *in,
    531 			size_t count)
    532 {
    533 	DES_key_schedule *keys = crypt->encrypt_key;
    534 
    535 	DES_ede3_cfb64_encrypt(in, out, (long)count,
    536 		&keys[0], &keys[1], &keys[2], (DES_cblock *)(void *)crypt->iv,
    537 		&crypt->num, DES_ENCRYPT);
    538 }
    539 
    540 static void
    541 tripledes_cfb_decrypt(pgp_crypt_t *crypt, void *out, const void *in,
    542 			size_t count)
    543 {
    544 	DES_key_schedule *keys = crypt->encrypt_key;
    545 
    546 	DES_ede3_cfb64_encrypt(in, out, (long)count,
    547 		&keys[0], &keys[1], &keys[2], (DES_cblock *)(void *)crypt->iv,
    548 		&crypt->num, DES_DECRYPT);
    549 }
    550 
    551 static const pgp_crypt_t tripledes =
    552 {
    553 	PGP_SA_TRIPLEDES,
    554 	8,
    555 	24,
    556 	std_set_iv,
    557 	std_set_key,
    558 	tripledes_init,
    559 	std_resync,
    560 	tripledes_block_encrypt,
    561 	tripledes_block_decrypt,
    562 	tripledes_cfb_encrypt,
    563 	tripledes_cfb_decrypt,
    564 	std_finish,
    565 	TRAILER
    566 };
    567 
    568 #if defined(HAVE_OPENSSL_CAMELLIA_H) && !defined(OPENSSL_NO_CAMELLIA)
    569 /* Camellia with 128-bit key (CAMELLIA) */
    570 
    571 #define KEYBITS_CAMELLIA128 128
    572 
    573 static int
    574 camellia128_init(pgp_crypt_t *crypt)
    575 {
    576 	if (crypt->encrypt_key) {
    577 		free(crypt->encrypt_key);
    578 	}
    579 	if ((crypt->encrypt_key = calloc(1, sizeof(CAMELLIA_KEY))) == NULL) {
    580 		(void) fprintf(stderr, "camellia128_init: alloc failure\n");
    581 		return 0;
    582 	}
    583 	if (Camellia_set_key(crypt->key, KEYBITS_CAMELLIA128, crypt->encrypt_key)) {
    584 		fprintf(stderr, "camellia128_init: Error setting encrypt_key\n");
    585 	}
    586 	if (crypt->decrypt_key) {
    587 		free(crypt->decrypt_key);
    588 	}
    589 	if ((crypt->decrypt_key = calloc(1, sizeof(CAMELLIA_KEY))) == NULL) {
    590 		(void) fprintf(stderr, "camellia128_init: alloc failure\n");
    591 		return 0;
    592 	}
    593 	if (Camellia_set_key(crypt->key, KEYBITS_CAMELLIA128, crypt->decrypt_key)) {
    594 		fprintf(stderr, "camellia128_init: Error setting decrypt_key\n");
    595 	}
    596 	return 1;
    597 }
    598 
    599 static void
    600 camellia_block_encrypt(pgp_crypt_t *crypt, void *out, const void *in)
    601 {
    602 	Camellia_encrypt(in, out, crypt->encrypt_key);
    603 }
    604 
    605 static void
    606 camellia_block_decrypt(pgp_crypt_t *crypt, void *out, const void *in)
    607 {
    608 	Camellia_decrypt(in, out, crypt->decrypt_key);
    609 }
    610 
    611 static void
    612 camellia_cfb_encrypt(pgp_crypt_t *crypt, void *out, const void *in, size_t count)
    613 {
    614 	Camellia_cfb128_encrypt(in, out, (unsigned)count,
    615 			   crypt->encrypt_key, crypt->iv, &crypt->num,
    616 			   CAMELLIA_ENCRYPT);
    617 }
    618 
    619 static void
    620 camellia_cfb_decrypt(pgp_crypt_t *crypt, void *out, const void *in, size_t count)
    621 {
    622 	Camellia_cfb128_encrypt(in, out, (unsigned)count,
    623 			   crypt->encrypt_key, crypt->iv, &crypt->num,
    624 			   CAMELLIA_DECRYPT);
    625 }
    626 
    627 static const pgp_crypt_t camellia128 =
    628 {
    629 	PGP_SA_CAMELLIA_128,
    630 	CAMELLIA_BLOCK_SIZE,
    631 	KEYBITS_CAMELLIA128 / 8,
    632 	std_set_iv,
    633 	std_set_key,
    634 	camellia128_init,
    635 	std_resync,
    636 	camellia_block_encrypt,
    637 	camellia_block_decrypt,
    638 	camellia_cfb_encrypt,
    639 	camellia_cfb_decrypt,
    640 	std_finish,
    641 	TRAILER
    642 };
    643 
    644 /* Camellia with 256-bit key (CAMELLIA) */
    645 
    646 #define KEYBITS_CAMELLIA256 256
    647 
    648 static int
    649 camellia256_init(pgp_crypt_t *crypt)
    650 {
    651 	if (crypt->encrypt_key) {
    652 		free(crypt->encrypt_key);
    653 	}
    654 	if ((crypt->encrypt_key = calloc(1, sizeof(CAMELLIA_KEY))) == NULL) {
    655 		(void) fprintf(stderr, "camellia256_init: alloc failure\n");
    656 		return 0;
    657 	}
    658 	if (Camellia_set_key(crypt->key, KEYBITS_CAMELLIA256, crypt->encrypt_key)) {
    659 		fprintf(stderr, "camellia256_init: Error setting encrypt_key\n");
    660 	}
    661 	if (crypt->decrypt_key) {
    662 		free(crypt->decrypt_key);
    663 	}
    664 	if ((crypt->decrypt_key = calloc(1, sizeof(CAMELLIA_KEY))) == NULL) {
    665 		(void) fprintf(stderr, "camellia256_init: alloc failure\n");
    666 		return 0;
    667 	}
    668 	if (Camellia_set_key(crypt->key, KEYBITS_CAMELLIA256, crypt->decrypt_key)) {
    669 		fprintf(stderr, "camellia256_init: Error setting decrypt_key\n");
    670 	}
    671 	return 1;
    672 }
    673 
    674 static const pgp_crypt_t camellia256 =
    675 {
    676 	PGP_SA_CAMELLIA_256,
    677 	CAMELLIA_BLOCK_SIZE,
    678 	KEYBITS_CAMELLIA256 / 8,
    679 	std_set_iv,
    680 	std_set_key,
    681 	camellia256_init,
    682 	std_resync,
    683 	camellia_block_encrypt,
    684 	camellia_block_decrypt,
    685 	camellia_cfb_encrypt,
    686 	camellia_cfb_decrypt,
    687 	std_finish,
    688 	TRAILER
    689 };
    690 #endif
    691 
    692 
    693 static const pgp_crypt_t *
    694 get_proto(pgp_symm_alg_t alg)
    695 {
    696 	switch (alg) {
    697 	case PGP_SA_CAST5:
    698 		return &cast5;
    699 #ifndef OPENSSL_NO_IDEA
    700 	case PGP_SA_IDEA:
    701 		return &idea;
    702 #endif				/* OPENSSL_NO_IDEA */
    703 	case PGP_SA_AES_128:
    704 		return &aes128;
    705 	case PGP_SA_AES_256:
    706 		return &aes256;
    707 #if defined(HAVE_OPENSSL_CAMELLIA_H) && !defined(OPENSSL_NO_CAMELLIA)
    708 	case PGP_SA_CAMELLIA_128:
    709 		return &camellia128;
    710 	case PGP_SA_CAMELLIA_256:
    711 		return &camellia256;
    712 #endif
    713 	case PGP_SA_TRIPLEDES:
    714 		return &tripledes;
    715 #if defined HAVE_OPENSSL_BLOWFISH_H
    716 	case PGP_SA_BLOWFISH:
    717 		return &blowfish;
    718 #endif
    719 
    720 	default:
    721 		(void) fprintf(stderr, "Unknown algorithm: %d (%s)\n",
    722 			alg, pgp_show_symm_alg(alg));
    723 	}
    724 	return NULL;
    725 }
    726 
    727 int
    728 pgp_crypt_any(pgp_crypt_t *crypt, pgp_symm_alg_t alg)
    729 {
    730 	const pgp_crypt_t *ptr = get_proto(alg);
    731 
    732 	if (ptr) {
    733 		*crypt = *ptr;
    734 		return 1;
    735 	} else {
    736 		(void) memset(crypt, 0x0, sizeof(*crypt));
    737 		return 0;
    738 	}
    739 }
    740 
    741 unsigned
    742 pgp_block_size(pgp_symm_alg_t alg)
    743 {
    744 	const pgp_crypt_t *p = get_proto(alg);
    745 
    746 	return (p == NULL) ? 0 : (unsigned)p->blocksize;
    747 }
    748 
    749 unsigned
    750 pgp_key_size(pgp_symm_alg_t alg)
    751 {
    752 	const pgp_crypt_t *p = get_proto(alg);
    753 
    754 	return (p == NULL) ? 0 : (unsigned)p->keysize;
    755 }
    756 
    757 void
    758 pgp_encrypt_init(pgp_crypt_t *encrypt)
    759 {
    760 	/* \todo should there be a separate pgp_encrypt_init? */
    761 	pgp_decrypt_init(encrypt);
    762 }
    763 
    764 void
    765 pgp_decrypt_init(pgp_crypt_t *decrypt)
    766 {
    767 	decrypt->base_init(decrypt);
    768 	decrypt->block_encrypt(decrypt, decrypt->siv, decrypt->iv);
    769 	(void) memcpy(decrypt->civ, decrypt->siv, decrypt->blocksize);
    770 	decrypt->num = 0;
    771 }
    772 
    773 size_t
    774 pgp_decrypt_se(pgp_crypt_t *decrypt, void *outvoid, const void *invoid,
    775 		size_t count)
    776 {
    777 	const uint8_t	*in = invoid;
    778 	uint8_t		*out = outvoid;
    779 	int              saved = (int)count;
    780 
    781 	/*
    782 	 * in order to support v3's weird resyncing we have to implement CFB
    783 	 * mode ourselves
    784 	 */
    785 	while (count-- > 0) {
    786 		uint8_t   t;
    787 
    788 		if ((size_t) decrypt->num == decrypt->blocksize) {
    789 			(void) memcpy(decrypt->siv, decrypt->civ,
    790 					decrypt->blocksize);
    791 			decrypt->block_decrypt(decrypt, decrypt->civ,
    792 					decrypt->civ);
    793 			decrypt->num = 0;
    794 		}
    795 		t = decrypt->civ[decrypt->num];
    796 		*out++ = t ^ (decrypt->civ[decrypt->num++] = *in++);
    797 	}
    798 
    799 	return (size_t)saved;
    800 }
    801 
    802 size_t
    803 pgp_encrypt_se(pgp_crypt_t *encrypt, void *outvoid, const void *invoid,
    804 	       size_t count)
    805 {
    806 	const uint8_t	*in = invoid;
    807 	uint8_t		*out = outvoid;
    808 	int              saved = (int)count;
    809 
    810 	/*
    811 	 * in order to support v3's weird resyncing we have to implement CFB
    812 	 * mode ourselves
    813 	 */
    814 	while (count-- > 0) {
    815 		if ((size_t) encrypt->num == encrypt->blocksize) {
    816 			(void) memcpy(encrypt->siv, encrypt->civ,
    817 					encrypt->blocksize);
    818 			encrypt->block_encrypt(encrypt, encrypt->civ,
    819 					encrypt->civ);
    820 			encrypt->num = 0;
    821 		}
    822 		encrypt->civ[encrypt->num] = *out++ =
    823 				encrypt->civ[encrypt->num] ^ *in++;
    824 		++encrypt->num;
    825 	}
    826 
    827 	return (size_t)saved;
    828 }
    829 
    830 /**
    831 \ingroup HighLevel_Supported
    832 \brief Is this Symmetric Algorithm supported?
    833 \param alg Symmetric Algorithm to check
    834 \return 1 if supported; else 0
    835 */
    836 unsigned
    837 pgp_is_sa_supported(pgp_symm_alg_t alg)
    838 {
    839 	switch (alg) {
    840 	case PGP_SA_AES_128:
    841 	case PGP_SA_AES_256:
    842 	case PGP_SA_CAST5:
    843 #if defined(HAVE_OPENSSL_BLOWFISH_H)
    844 	case PGP_SA_BLOWFISH:
    845 #endif
    846 	case PGP_SA_TRIPLEDES:
    847 #if defined(HAVE_OPENSSL_CAMELLIA_H) && !defined(OPENSSL_NO_CAMELLIA)
    848 	case PGP_SA_CAMELLIA_128:
    849 	case PGP_SA_CAMELLIA_256:
    850 #endif
    851 #ifndef OPENSSL_NO_IDEA
    852 	case PGP_SA_IDEA:
    853 #endif
    854 		return 1;
    855 
    856 	default:
    857 		fprintf(stderr, "\nWarning: %s not supported\n",
    858 			pgp_show_symm_alg(alg));
    859 		return 0;
    860 	}
    861 }
    862 
    863 size_t
    864 pgp_encrypt_se_ip(pgp_crypt_t *crypt, void *out, const void *in,
    865 		  size_t count)
    866 {
    867 	if (!pgp_is_sa_supported(crypt->alg)) {
    868 		return 0;
    869 	}
    870 
    871 	crypt->cfb_encrypt(crypt, out, in, count);
    872 
    873 	/* \todo test this number was encrypted */
    874 	return count;
    875 }
    876 
    877 size_t
    878 pgp_decrypt_se_ip(pgp_crypt_t *crypt, void *out, const void *in,
    879 		  size_t count)
    880 {
    881 	if (!pgp_is_sa_supported(crypt->alg)) {
    882 		return 0;
    883 	}
    884 
    885 	crypt->cfb_decrypt(crypt, out, in, count);
    886 
    887 	/* \todo check this number was in fact decrypted */
    888 	return count;
    889 }
    890