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@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.18 2010/11/07 08:39:59 agc 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#include "crypto.h"
86#include "netpgpdefs.h"
87
88
89static void
90std_set_iv(pgp_crypt_t *crypt, const uint8_t *iv)
91{
92	(void) memcpy(crypt->iv, iv, crypt->blocksize);
93	crypt->num = 0;
94}
95
96static void
97std_set_key(pgp_crypt_t *crypt, const uint8_t *key)
98{
99	(void) memcpy(crypt->key, key, crypt->keysize);
100}
101
102static void
103std_resync(pgp_crypt_t *decrypt)
104{
105	if ((size_t) decrypt->num == decrypt->blocksize) {
106		return;
107	}
108
109	memmove(decrypt->civ + decrypt->blocksize - decrypt->num, decrypt->civ,
110		(unsigned)decrypt->num);
111	(void) memcpy(decrypt->civ, decrypt->siv + decrypt->num,
112	       decrypt->blocksize - decrypt->num);
113	decrypt->num = 0;
114}
115
116static void
117std_finish(pgp_crypt_t *crypt)
118{
119	if (crypt->encrypt_key) {
120		free(crypt->encrypt_key);
121		crypt->encrypt_key = NULL;
122	}
123	if (crypt->decrypt_key) {
124		free(crypt->decrypt_key);
125		crypt->decrypt_key = NULL;
126	}
127}
128
129static int
130cast5_init(pgp_crypt_t *crypt)
131{
132	if (crypt->encrypt_key) {
133		free(crypt->encrypt_key);
134	}
135	if ((crypt->encrypt_key = calloc(1, sizeof(CAST_KEY))) == NULL) {
136		(void) fprintf(stderr, "cast5_init: alloc failure\n");
137		return 0;
138	}
139	CAST_set_key(crypt->encrypt_key, (int)crypt->keysize, crypt->key);
140	if ((crypt->decrypt_key = calloc(1, sizeof(CAST_KEY))) == NULL) {
141		(void) fprintf(stderr, "cast5_init: alloc failure\n");
142		return 0;
143	}
144	CAST_set_key(crypt->decrypt_key, (int)crypt->keysize, crypt->key);
145	return 1;
146}
147
148static void
149cast5_block_encrypt(pgp_crypt_t *crypt, void *out, const void *in)
150{
151	CAST_ecb_encrypt(in, out, crypt->encrypt_key, CAST_ENCRYPT);
152}
153
154static void
155cast5_block_decrypt(pgp_crypt_t *crypt, void *out, const void *in)
156{
157	CAST_ecb_encrypt(in, out, crypt->encrypt_key, CAST_DECRYPT);
158}
159
160static void
161cast5_cfb_encrypt(pgp_crypt_t *crypt, void *out, const void *in, size_t count)
162{
163	CAST_cfb64_encrypt(in, out, (long)count,
164			   crypt->encrypt_key, crypt->iv, &crypt->num,
165			   CAST_ENCRYPT);
166}
167
168static void
169cast5_cfb_decrypt(pgp_crypt_t *crypt, void *out, const void *in, size_t count)
170{
171	CAST_cfb64_encrypt(in, out, (long)count,
172			   crypt->encrypt_key, crypt->iv, &crypt->num,
173			   CAST_DECRYPT);
174}
175
176#define TRAILER		"","","","",0,NULL,NULL
177
178static pgp_crypt_t cast5 =
179{
180	PGP_SA_CAST5,
181	CAST_BLOCK,
182	CAST_KEY_LENGTH,
183	std_set_iv,
184	std_set_key,
185	cast5_init,
186	std_resync,
187	cast5_block_encrypt,
188	cast5_block_decrypt,
189	cast5_cfb_encrypt,
190	cast5_cfb_decrypt,
191	std_finish,
192	TRAILER
193};
194
195#ifndef OPENSSL_NO_IDEA
196static int
197idea_init(pgp_crypt_t *crypt)
198{
199	if (crypt->keysize != IDEA_KEY_LENGTH) {
200		(void) fprintf(stderr, "idea_init: keysize wrong\n");
201		return 0;
202	}
203
204	if (crypt->encrypt_key) {
205		free(crypt->encrypt_key);
206	}
207	if ((crypt->encrypt_key = calloc(1, sizeof(IDEA_KEY_SCHEDULE))) == NULL) {
208		(void) fprintf(stderr, "idea_init: alloc failure\n");
209		return 0;
210	}
211
212	/* note that we don't invert the key when decrypting for CFB mode */
213	idea_set_encrypt_key(crypt->key, crypt->encrypt_key);
214
215	if (crypt->decrypt_key) {
216		free(crypt->decrypt_key);
217	}
218	if ((crypt->decrypt_key = calloc(1, sizeof(IDEA_KEY_SCHEDULE))) == NULL) {
219		(void) fprintf(stderr, "idea_init: alloc failure\n");
220		return 0;
221	}
222
223	idea_set_decrypt_key(crypt->encrypt_key, crypt->decrypt_key);
224	return 1;
225}
226
227static void
228idea_block_encrypt(pgp_crypt_t *crypt, void *out, const void *in)
229{
230	idea_ecb_encrypt(in, out, crypt->encrypt_key);
231}
232
233static void
234idea_block_decrypt(pgp_crypt_t *crypt, void *out, const void *in)
235{
236	idea_ecb_encrypt(in, out, crypt->decrypt_key);
237}
238
239static void
240idea_cfb_encrypt(pgp_crypt_t *crypt, void *out, const void *in, size_t count)
241{
242	idea_cfb64_encrypt(in, out, (long)count,
243			   crypt->encrypt_key, crypt->iv, &crypt->num,
244			   CAST_ENCRYPT);
245}
246
247static void
248idea_cfb_decrypt(pgp_crypt_t *crypt, void *out, const void *in, size_t count)
249{
250	idea_cfb64_encrypt(in, out, (long)count,
251			   crypt->decrypt_key, crypt->iv, &crypt->num,
252			   CAST_DECRYPT);
253}
254
255static const pgp_crypt_t idea =
256{
257	PGP_SA_IDEA,
258	IDEA_BLOCK,
259	IDEA_KEY_LENGTH,
260	std_set_iv,
261	std_set_key,
262	idea_init,
263	std_resync,
264	idea_block_encrypt,
265	idea_block_decrypt,
266	idea_cfb_encrypt,
267	idea_cfb_decrypt,
268	std_finish,
269	TRAILER
270};
271#endif				/* OPENSSL_NO_IDEA */
272
273/* AES with 128-bit key (AES) */
274
275#define KEYBITS_AES128 128
276
277static int
278aes128_init(pgp_crypt_t *crypt)
279{
280	if (crypt->encrypt_key) {
281		free(crypt->encrypt_key);
282	}
283	if ((crypt->encrypt_key = calloc(1, sizeof(AES_KEY))) == NULL) {
284		(void) fprintf(stderr, "aes128_init: alloc failure\n");
285		return 0;
286	}
287	if (AES_set_encrypt_key(crypt->key, KEYBITS_AES128,
288			crypt->encrypt_key)) {
289		fprintf(stderr, "aes128_init: Error setting encrypt_key\n");
290	}
291
292	if (crypt->decrypt_key) {
293		free(crypt->decrypt_key);
294	}
295	if ((crypt->decrypt_key = calloc(1, sizeof(AES_KEY))) == NULL) {
296		(void) fprintf(stderr, "aes128_init: alloc failure\n");
297		return 0;
298	}
299	if (AES_set_decrypt_key(crypt->key, KEYBITS_AES128,
300				crypt->decrypt_key)) {
301		fprintf(stderr, "aes128_init: Error setting decrypt_key\n");
302	}
303	return 1;
304}
305
306static void
307aes_block_encrypt(pgp_crypt_t *crypt, void *out, const void *in)
308{
309	AES_encrypt(in, out, crypt->encrypt_key);
310}
311
312static void
313aes_block_decrypt(pgp_crypt_t *crypt, void *out, const void *in)
314{
315	AES_decrypt(in, out, crypt->decrypt_key);
316}
317
318static void
319aes_cfb_encrypt(pgp_crypt_t *crypt, void *out, const void *in, size_t count)
320{
321	AES_cfb128_encrypt(in, out, (unsigned)count,
322			   crypt->encrypt_key, crypt->iv, &crypt->num,
323			   AES_ENCRYPT);
324}
325
326static void
327aes_cfb_decrypt(pgp_crypt_t *crypt, void *out, const void *in, size_t count)
328{
329	AES_cfb128_encrypt(in, out, (unsigned)count,
330			   crypt->encrypt_key, crypt->iv, &crypt->num,
331			   AES_DECRYPT);
332}
333
334static const pgp_crypt_t aes128 =
335{
336	PGP_SA_AES_128,
337	AES_BLOCK_SIZE,
338	KEYBITS_AES128 / 8,
339	std_set_iv,
340	std_set_key,
341	aes128_init,
342	std_resync,
343	aes_block_encrypt,
344	aes_block_decrypt,
345	aes_cfb_encrypt,
346	aes_cfb_decrypt,
347	std_finish,
348	TRAILER
349};
350
351/* AES with 256-bit key */
352
353#define KEYBITS_AES256 256
354
355static int
356aes256_init(pgp_crypt_t *crypt)
357{
358	if (crypt->encrypt_key) {
359		free(crypt->encrypt_key);
360	}
361	if ((crypt->encrypt_key = calloc(1, sizeof(AES_KEY))) == NULL) {
362		(void) fprintf(stderr, "aes256_init: alloc failure\n");
363		return 0;
364	}
365	if (AES_set_encrypt_key(crypt->key, KEYBITS_AES256,
366			crypt->encrypt_key)) {
367		fprintf(stderr, "aes256_init: Error setting encrypt_key\n");
368		free(crypt->encrypt_key);
369		crypt->encrypt_key = NULL;
370		return 0;
371	}
372	if (crypt->decrypt_key) {
373		free(crypt->decrypt_key);
374	}
375	if ((crypt->decrypt_key = calloc(1, sizeof(AES_KEY))) == NULL) {
376		(void) fprintf(stderr, "aes256_init: alloc failure\n");
377		free(crypt->encrypt_key);
378		crypt->encrypt_key = NULL;
379		return 0;
380	}
381	if (AES_set_decrypt_key(crypt->key, KEYBITS_AES256,
382			crypt->decrypt_key)) {
383		fprintf(stderr, "aes256_init: Error setting decrypt_key\n");
384		free(crypt->encrypt_key);
385		crypt->encrypt_key = NULL;
386		free(crypt->decrypt_key);
387		crypt->decrypt_key = NULL;
388		return 0;
389	}
390	return 1;
391}
392
393static const pgp_crypt_t aes256 =
394{
395	PGP_SA_AES_256,
396	AES_BLOCK_SIZE,
397	KEYBITS_AES256 / 8,
398	std_set_iv,
399	std_set_key,
400	aes256_init,
401	std_resync,
402	aes_block_encrypt,
403	aes_block_decrypt,
404	aes_cfb_encrypt,
405	aes_cfb_decrypt,
406	std_finish,
407	TRAILER
408};
409
410/* Triple DES */
411
412static int
413tripledes_init(pgp_crypt_t *crypt)
414{
415	DES_key_schedule *keys;
416	int             n;
417
418	if (crypt->encrypt_key) {
419		free(crypt->encrypt_key);
420	}
421	if ((keys = crypt->encrypt_key = calloc(1, 3 * sizeof(DES_key_schedule))) == NULL) {
422		(void) fprintf(stderr, "tripledes_init: alloc failure\n");
423		return 0;
424	}
425	for (n = 0; n < 3; ++n) {
426		DES_set_key((DES_cblock *)(void *)(crypt->key + n * 8),
427			&keys[n]);
428	}
429	return 1;
430}
431
432static void
433tripledes_block_encrypt(pgp_crypt_t *crypt, void *out, const void *in)
434{
435	DES_key_schedule *keys = crypt->encrypt_key;
436
437	DES_ecb3_encrypt(__UNCONST(in), out, &keys[0], &keys[1], &keys[2],
438			DES_ENCRYPT);
439}
440
441static void
442tripledes_block_decrypt(pgp_crypt_t *crypt, void *out, const void *in)
443{
444	DES_key_schedule *keys = crypt->encrypt_key;
445
446	DES_ecb3_encrypt(__UNCONST(in), out, &keys[0], &keys[1], &keys[2],
447			DES_DECRYPT);
448}
449
450static void
451tripledes_cfb_encrypt(pgp_crypt_t *crypt, void *out, const void *in,
452			size_t count)
453{
454	DES_key_schedule *keys = crypt->encrypt_key;
455
456	DES_ede3_cfb64_encrypt(in, out, (long)count,
457		&keys[0], &keys[1], &keys[2], (DES_cblock *)(void *)crypt->iv,
458		&crypt->num, DES_ENCRYPT);
459}
460
461static void
462tripledes_cfb_decrypt(pgp_crypt_t *crypt, void *out, const void *in,
463			size_t count)
464{
465	DES_key_schedule *keys = crypt->encrypt_key;
466
467	DES_ede3_cfb64_encrypt(in, out, (long)count,
468		&keys[0], &keys[1], &keys[2], (DES_cblock *)(void *)crypt->iv,
469		&crypt->num, DES_DECRYPT);
470}
471
472static const pgp_crypt_t tripledes =
473{
474	PGP_SA_TRIPLEDES,
475	8,
476	24,
477	std_set_iv,
478	std_set_key,
479	tripledes_init,
480	std_resync,
481	tripledes_block_encrypt,
482	tripledes_block_decrypt,
483	tripledes_cfb_encrypt,
484	tripledes_cfb_decrypt,
485	std_finish,
486	TRAILER
487};
488
489#if defined(HAVE_OPENSSL_CAMELLIA_H) && !defined(OPENSSL_NO_CAMELLIA)
490/* Camellia with 128-bit key (CAMELLIA) */
491
492#define KEYBITS_CAMELLIA128 128
493
494static int
495camellia128_init(pgp_crypt_t *crypt)
496{
497	if (crypt->encrypt_key) {
498		free(crypt->encrypt_key);
499	}
500	if ((crypt->encrypt_key = calloc(1, sizeof(CAMELLIA_KEY))) == NULL) {
501		(void) fprintf(stderr, "camellia128_init: alloc failure\n");
502		return 0;
503	}
504	if (Camellia_set_key(crypt->key, KEYBITS_CAMELLIA128, crypt->encrypt_key)) {
505		fprintf(stderr, "camellia128_init: Error setting encrypt_key\n");
506	}
507	if (crypt->decrypt_key) {
508		free(crypt->decrypt_key);
509	}
510	if ((crypt->decrypt_key = calloc(1, sizeof(CAMELLIA_KEY))) == NULL) {
511		(void) fprintf(stderr, "camellia128_init: alloc failure\n");
512		return 0;
513	}
514	if (Camellia_set_key(crypt->key, KEYBITS_CAMELLIA128, crypt->decrypt_key)) {
515		fprintf(stderr, "camellia128_init: Error setting decrypt_key\n");
516	}
517	return 1;
518}
519
520static void
521camellia_block_encrypt(pgp_crypt_t *crypt, void *out, const void *in)
522{
523	Camellia_encrypt(in, out, crypt->encrypt_key);
524}
525
526static void
527camellia_block_decrypt(pgp_crypt_t *crypt, void *out, const void *in)
528{
529	Camellia_decrypt(in, out, crypt->decrypt_key);
530}
531
532static void
533camellia_cfb_encrypt(pgp_crypt_t *crypt, void *out, const void *in, size_t count)
534{
535	Camellia_cfb128_encrypt(in, out, (unsigned)count,
536			   crypt->encrypt_key, crypt->iv, &crypt->num,
537			   CAMELLIA_ENCRYPT);
538}
539
540static void
541camellia_cfb_decrypt(pgp_crypt_t *crypt, void *out, const void *in, size_t count)
542{
543	Camellia_cfb128_encrypt(in, out, (unsigned)count,
544			   crypt->encrypt_key, crypt->iv, &crypt->num,
545			   CAMELLIA_DECRYPT);
546}
547
548static const pgp_crypt_t camellia128 =
549{
550	PGP_SA_CAMELLIA_128,
551	CAMELLIA_BLOCK_SIZE,
552	KEYBITS_CAMELLIA128 / 8,
553	std_set_iv,
554	std_set_key,
555	camellia128_init,
556	std_resync,
557	camellia_block_encrypt,
558	camellia_block_decrypt,
559	camellia_cfb_encrypt,
560	camellia_cfb_decrypt,
561	std_finish,
562	TRAILER
563};
564
565/* Camellia with 256-bit key (CAMELLIA) */
566
567#define KEYBITS_CAMELLIA256 256
568
569static int
570camellia256_init(pgp_crypt_t *crypt)
571{
572	if (crypt->encrypt_key) {
573		free(crypt->encrypt_key);
574	}
575	if ((crypt->encrypt_key = calloc(1, sizeof(CAMELLIA_KEY))) == NULL) {
576		(void) fprintf(stderr, "camellia256_init: alloc failure\n");
577		return 0;
578	}
579	if (Camellia_set_key(crypt->key, KEYBITS_CAMELLIA256, crypt->encrypt_key)) {
580		fprintf(stderr, "camellia256_init: Error setting encrypt_key\n");
581	}
582	if (crypt->decrypt_key) {
583		free(crypt->decrypt_key);
584	}
585	if ((crypt->decrypt_key = calloc(1, sizeof(CAMELLIA_KEY))) == NULL) {
586		(void) fprintf(stderr, "camellia256_init: alloc failure\n");
587		return 0;
588	}
589	if (Camellia_set_key(crypt->key, KEYBITS_CAMELLIA256, crypt->decrypt_key)) {
590		fprintf(stderr, "camellia256_init: Error setting decrypt_key\n");
591	}
592	return 1;
593}
594
595static const pgp_crypt_t camellia256 =
596{
597	PGP_SA_CAMELLIA_256,
598	CAMELLIA_BLOCK_SIZE,
599	KEYBITS_CAMELLIA256 / 8,
600	std_set_iv,
601	std_set_key,
602	camellia256_init,
603	std_resync,
604	camellia_block_encrypt,
605	camellia_block_decrypt,
606	camellia_cfb_encrypt,
607	camellia_cfb_decrypt,
608	std_finish,
609	TRAILER
610};
611#endif
612
613
614static const pgp_crypt_t *
615get_proto(pgp_symm_alg_t alg)
616{
617	switch (alg) {
618	case PGP_SA_CAST5:
619		return &cast5;
620#ifndef OPENSSL_NO_IDEA
621	case PGP_SA_IDEA:
622		return &idea;
623#endif				/* OPENSSL_NO_IDEA */
624	case PGP_SA_AES_128:
625		return &aes128;
626	case PGP_SA_AES_256:
627		return &aes256;
628#if defined(HAVE_OPENSSL_CAMELLIA_H) && !defined(OPENSSL_NO_CAMELLIA)
629	case PGP_SA_CAMELLIA_128:
630		return &camellia128;
631	case PGP_SA_CAMELLIA_256:
632		return &camellia256;
633#endif
634	case PGP_SA_TRIPLEDES:
635		return &tripledes;
636	default:
637		(void) fprintf(stderr, "Unknown algorithm: %d (%s)\n",
638			alg, pgp_show_symm_alg(alg));
639	}
640	return NULL;
641}
642
643int
644pgp_crypt_any(pgp_crypt_t *crypt, pgp_symm_alg_t alg)
645{
646	const pgp_crypt_t *ptr = get_proto(alg);
647
648	if (ptr) {
649		*crypt = *ptr;
650		return 1;
651	} else {
652		(void) memset(crypt, 0x0, sizeof(*crypt));
653		return 0;
654	}
655}
656
657unsigned
658pgp_block_size(pgp_symm_alg_t alg)
659{
660	const pgp_crypt_t *p = get_proto(alg);
661
662	return (p == NULL) ? 0 : (unsigned)p->blocksize;
663}
664
665unsigned
666pgp_key_size(pgp_symm_alg_t alg)
667{
668	const pgp_crypt_t *p = get_proto(alg);
669
670	return (p == NULL) ? 0 : (unsigned)p->keysize;
671}
672
673void
674pgp_encrypt_init(pgp_crypt_t *encrypt)
675{
676	/* \todo should there be a separate pgp_encrypt_init? */
677	pgp_decrypt_init(encrypt);
678}
679
680void
681pgp_decrypt_init(pgp_crypt_t *decrypt)
682{
683	decrypt->base_init(decrypt);
684	decrypt->block_encrypt(decrypt, decrypt->siv, decrypt->iv);
685	(void) memcpy(decrypt->civ, decrypt->siv, decrypt->blocksize);
686	decrypt->num = 0;
687}
688
689size_t
690pgp_decrypt_se(pgp_crypt_t *decrypt, void *outvoid, const void *invoid,
691		size_t count)
692{
693	const uint8_t	*in = invoid;
694	uint8_t		*out = outvoid;
695	int              saved = (int)count;
696
697	/*
698	 * in order to support v3's weird resyncing we have to implement CFB
699	 * mode ourselves
700	 */
701	while (count-- > 0) {
702		uint8_t   t;
703
704		if ((size_t) decrypt->num == decrypt->blocksize) {
705			(void) memcpy(decrypt->siv, decrypt->civ,
706					decrypt->blocksize);
707			decrypt->block_decrypt(decrypt, decrypt->civ,
708					decrypt->civ);
709			decrypt->num = 0;
710		}
711		t = decrypt->civ[decrypt->num];
712		*out++ = t ^ (decrypt->civ[decrypt->num++] = *in++);
713	}
714
715	return (size_t)saved;
716}
717
718size_t
719pgp_encrypt_se(pgp_crypt_t *encrypt, void *outvoid, const void *invoid,
720	       size_t count)
721{
722	const uint8_t	*in = invoid;
723	uint8_t		*out = outvoid;
724	int              saved = (int)count;
725
726	/*
727	 * in order to support v3's weird resyncing we have to implement CFB
728	 * mode ourselves
729	 */
730	while (count-- > 0) {
731		if ((size_t) encrypt->num == encrypt->blocksize) {
732			(void) memcpy(encrypt->siv, encrypt->civ,
733					encrypt->blocksize);
734			encrypt->block_encrypt(encrypt, encrypt->civ,
735					encrypt->civ);
736			encrypt->num = 0;
737		}
738		encrypt->civ[encrypt->num] = *out++ =
739				encrypt->civ[encrypt->num] ^ *in++;
740		++encrypt->num;
741	}
742
743	return (size_t)saved;
744}
745
746/**
747\ingroup HighLevel_Supported
748\brief Is this Symmetric Algorithm supported?
749\param alg Symmetric Algorithm to check
750\return 1 if supported; else 0
751*/
752unsigned
753pgp_is_sa_supported(pgp_symm_alg_t alg)
754{
755	switch (alg) {
756	case PGP_SA_AES_128:
757	case PGP_SA_AES_256:
758	case PGP_SA_CAST5:
759	case PGP_SA_TRIPLEDES:
760#if defined(HAVE_OPENSSL_CAMELLIA_H) && !defined(OPENSSL_NO_CAMELLIA)
761	case PGP_SA_CAMELLIA_128:
762	case PGP_SA_CAMELLIA_256:
763#endif
764#ifndef OPENSSL_NO_IDEA
765	case PGP_SA_IDEA:
766#endif
767		return 1;
768
769	default:
770		fprintf(stderr, "\nWarning: %s not supported\n",
771			pgp_show_symm_alg(alg));
772		return 0;
773	}
774}
775
776size_t
777pgp_encrypt_se_ip(pgp_crypt_t *crypt, void *out, const void *in,
778		  size_t count)
779{
780	if (!pgp_is_sa_supported(crypt->alg)) {
781		return 0;
782	}
783
784	crypt->cfb_encrypt(crypt, out, in, count);
785
786	/* \todo test this number was encrypted */
787	return count;
788}
789
790size_t
791pgp_decrypt_se_ip(pgp_crypt_t *crypt, void *out, const void *in,
792		  size_t count)
793{
794	if (!pgp_is_sa_supported(crypt->alg)) {
795		return 0;
796	}
797
798	crypt->cfb_decrypt(crypt, out, in, count);
799
800	/* \todo check this number was in fact decrypted */
801	return count;
802}
803