xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/lib/symmetric.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
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.11 2010/08/15 07:52:27 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 #include "crypto.h"
82 #include "netpgpdefs.h"
83 
84 
85 static void
86 std_set_iv(__ops_crypt_t *crypt, const uint8_t *iv)
87 {
88 	(void) memcpy(crypt->iv, iv, crypt->blocksize);
89 	crypt->num = 0;
90 }
91 
92 static void
93 std_set_key(__ops_crypt_t *crypt, const uint8_t *key)
94 {
95 	(void) memcpy(crypt->key, key, crypt->keysize);
96 }
97 
98 static void
99 std_resync(__ops_crypt_t *decrypt)
100 {
101 	if ((size_t) decrypt->num == decrypt->blocksize) {
102 		return;
103 	}
104 
105 	memmove(decrypt->civ + decrypt->blocksize - decrypt->num, decrypt->civ,
106 		(unsigned)decrypt->num);
107 	(void) memcpy(decrypt->civ, decrypt->siv + decrypt->num,
108 	       decrypt->blocksize - decrypt->num);
109 	decrypt->num = 0;
110 }
111 
112 static void
113 std_finish(__ops_crypt_t *crypt)
114 {
115 	if (crypt->encrypt_key) {
116 		free(crypt->encrypt_key);
117 		crypt->encrypt_key = NULL;
118 	}
119 	if (crypt->decrypt_key) {
120 		free(crypt->decrypt_key);
121 		crypt->decrypt_key = NULL;
122 	}
123 }
124 
125 static void
126 cast5_init(__ops_crypt_t *crypt)
127 {
128 	if (crypt->encrypt_key) {
129 		free(crypt->encrypt_key);
130 	}
131 	crypt->encrypt_key = calloc(1, sizeof(CAST_KEY));
132 	CAST_set_key(crypt->encrypt_key, (int)crypt->keysize, crypt->key);
133 	crypt->decrypt_key = calloc(1, sizeof(CAST_KEY));
134 	CAST_set_key(crypt->decrypt_key, (int)crypt->keysize, crypt->key);
135 }
136 
137 static void
138 cast5_block_encrypt(__ops_crypt_t *crypt, void *out, const void *in)
139 {
140 	CAST_ecb_encrypt(in, out, crypt->encrypt_key, CAST_ENCRYPT);
141 }
142 
143 static void
144 cast5_block_decrypt(__ops_crypt_t *crypt, void *out, const void *in)
145 {
146 	CAST_ecb_encrypt(in, out, crypt->encrypt_key, CAST_DECRYPT);
147 }
148 
149 static void
150 cast5_cfb_encrypt(__ops_crypt_t *crypt, void *out, const void *in, size_t count)
151 {
152 	CAST_cfb64_encrypt(in, out, (long)count,
153 			   crypt->encrypt_key, crypt->iv, &crypt->num,
154 			   CAST_ENCRYPT);
155 }
156 
157 static void
158 cast5_cfb_decrypt(__ops_crypt_t *crypt, void *out, const void *in, size_t count)
159 {
160 	CAST_cfb64_encrypt(in, out, (long)count,
161 			   crypt->encrypt_key, crypt->iv, &crypt->num,
162 			   CAST_DECRYPT);
163 }
164 
165 #define TRAILER		"","","","",0,NULL,NULL
166 
167 static __ops_crypt_t cast5 =
168 {
169 	OPS_SA_CAST5,
170 	CAST_BLOCK,
171 	CAST_KEY_LENGTH,
172 	std_set_iv,
173 	std_set_key,
174 	cast5_init,
175 	std_resync,
176 	cast5_block_encrypt,
177 	cast5_block_decrypt,
178 	cast5_cfb_encrypt,
179 	cast5_cfb_decrypt,
180 	std_finish,
181 	TRAILER
182 };
183 
184 #ifndef OPENSSL_NO_IDEA
185 static void
186 idea_init(__ops_crypt_t *crypt)
187 {
188 	if (crypt->keysize != IDEA_KEY_LENGTH) {
189 		(void) fprintf(stderr, "idea_init: keysize wrong\n");
190 		return;
191 	}
192 
193 	if (crypt->encrypt_key) {
194 		free(crypt->encrypt_key);
195 	}
196 	crypt->encrypt_key = calloc(1, sizeof(IDEA_KEY_SCHEDULE));
197 
198 	/* note that we don't invert the key when decrypting for CFB mode */
199 	idea_set_encrypt_key(crypt->key, crypt->encrypt_key);
200 
201 	if (crypt->decrypt_key) {
202 		free(crypt->decrypt_key);
203 	}
204 	crypt->decrypt_key = calloc(1, sizeof(IDEA_KEY_SCHEDULE));
205 
206 	idea_set_decrypt_key(crypt->encrypt_key, crypt->decrypt_key);
207 }
208 
209 static void
210 idea_block_encrypt(__ops_crypt_t *crypt, void *out, const void *in)
211 {
212 	idea_ecb_encrypt(in, out, crypt->encrypt_key);
213 }
214 
215 static void
216 idea_block_decrypt(__ops_crypt_t *crypt, void *out, const void *in)
217 {
218 	idea_ecb_encrypt(in, out, crypt->decrypt_key);
219 }
220 
221 static void
222 idea_cfb_encrypt(__ops_crypt_t *crypt, void *out, const void *in, size_t count)
223 {
224 	idea_cfb64_encrypt(in, out, (long)count,
225 			   crypt->encrypt_key, crypt->iv, &crypt->num,
226 			   CAST_ENCRYPT);
227 }
228 
229 static void
230 idea_cfb_decrypt(__ops_crypt_t *crypt, void *out, const void *in, size_t count)
231 {
232 	idea_cfb64_encrypt(in, out, (long)count,
233 			   crypt->decrypt_key, crypt->iv, &crypt->num,
234 			   CAST_DECRYPT);
235 }
236 
237 static const __ops_crypt_t idea =
238 {
239 	OPS_SA_IDEA,
240 	IDEA_BLOCK,
241 	IDEA_KEY_LENGTH,
242 	std_set_iv,
243 	std_set_key,
244 	idea_init,
245 	std_resync,
246 	idea_block_encrypt,
247 	idea_block_decrypt,
248 	idea_cfb_encrypt,
249 	idea_cfb_decrypt,
250 	std_finish,
251 	TRAILER
252 };
253 #endif				/* OPENSSL_NO_IDEA */
254 
255 /* AES with 128-bit key (AES) */
256 
257 #define KEYBITS_AES128 128
258 
259 static void
260 aes128_init(__ops_crypt_t *crypt)
261 {
262 	if (crypt->encrypt_key) {
263 		free(crypt->encrypt_key);
264 	}
265 	crypt->encrypt_key = calloc(1, sizeof(AES_KEY));
266 	if (AES_set_encrypt_key(crypt->key, KEYBITS_AES128,
267 			crypt->encrypt_key)) {
268 		fprintf(stderr, "aes128_init: Error setting encrypt_key\n");
269 	}
270 
271 	if (crypt->decrypt_key) {
272 		free(crypt->decrypt_key);
273 	}
274 	crypt->decrypt_key = calloc(1, sizeof(AES_KEY));
275 	if (AES_set_decrypt_key(crypt->key, KEYBITS_AES128,
276 				crypt->decrypt_key)) {
277 		fprintf(stderr, "aes128_init: Error setting decrypt_key\n");
278 	}
279 }
280 
281 static void
282 aes_block_encrypt(__ops_crypt_t *crypt, void *out, const void *in)
283 {
284 	AES_encrypt(in, out, crypt->encrypt_key);
285 }
286 
287 static void
288 aes_block_decrypt(__ops_crypt_t *crypt, void *out, const void *in)
289 {
290 	AES_decrypt(in, out, crypt->decrypt_key);
291 }
292 
293 static void
294 aes_cfb_encrypt(__ops_crypt_t *crypt, void *out, const void *in, size_t count)
295 {
296 	AES_cfb128_encrypt(in, out, (unsigned)count,
297 			   crypt->encrypt_key, crypt->iv, &crypt->num,
298 			   AES_ENCRYPT);
299 }
300 
301 static void
302 aes_cfb_decrypt(__ops_crypt_t *crypt, void *out, const void *in, size_t count)
303 {
304 	AES_cfb128_encrypt(in, out, (unsigned)count,
305 			   crypt->encrypt_key, crypt->iv, &crypt->num,
306 			   AES_DECRYPT);
307 }
308 
309 static const __ops_crypt_t aes128 =
310 {
311 	OPS_SA_AES_128,
312 	AES_BLOCK_SIZE,
313 	KEYBITS_AES128 / 8,
314 	std_set_iv,
315 	std_set_key,
316 	aes128_init,
317 	std_resync,
318 	aes_block_encrypt,
319 	aes_block_decrypt,
320 	aes_cfb_encrypt,
321 	aes_cfb_decrypt,
322 	std_finish,
323 	TRAILER
324 };
325 
326 /* AES with 256-bit key */
327 
328 #define KEYBITS_AES256 256
329 
330 static void
331 aes256_init(__ops_crypt_t *crypt)
332 {
333 	if (crypt->encrypt_key) {
334 		free(crypt->encrypt_key);
335 	}
336 	crypt->encrypt_key = calloc(1, sizeof(AES_KEY));
337 	if (AES_set_encrypt_key(crypt->key, KEYBITS_AES256,
338 			crypt->encrypt_key)) {
339 		fprintf(stderr, "aes256_init: Error setting encrypt_key\n");
340 	}
341 
342 	if (crypt->decrypt_key)
343 		free(crypt->decrypt_key);
344 	crypt->decrypt_key = calloc(1, sizeof(AES_KEY));
345 	if (AES_set_decrypt_key(crypt->key, KEYBITS_AES256,
346 			crypt->decrypt_key)) {
347 		fprintf(stderr, "aes256_init: Error setting decrypt_key\n");
348 	}
349 }
350 
351 static const __ops_crypt_t aes256 =
352 {
353 	OPS_SA_AES_256,
354 	AES_BLOCK_SIZE,
355 	KEYBITS_AES256 / 8,
356 	std_set_iv,
357 	std_set_key,
358 	aes256_init,
359 	std_resync,
360 	aes_block_encrypt,
361 	aes_block_decrypt,
362 	aes_cfb_encrypt,
363 	aes_cfb_decrypt,
364 	std_finish,
365 	TRAILER
366 };
367 
368 /* Triple DES */
369 
370 static void
371 tripledes_init(__ops_crypt_t *crypt)
372 {
373 	DES_key_schedule *keys;
374 	int             n;
375 
376 	if (crypt->encrypt_key) {
377 		free(crypt->encrypt_key);
378 	}
379 	keys = crypt->encrypt_key = calloc(1, 3 * sizeof(DES_key_schedule));
380 
381 	for (n = 0; n < 3; ++n) {
382 		DES_set_key((DES_cblock *)(void *)(crypt->key + n * 8),
383 			&keys[n]);
384 	}
385 }
386 
387 static void
388 tripledes_block_encrypt(__ops_crypt_t *crypt, void *out, const void *in)
389 {
390 	DES_key_schedule *keys = crypt->encrypt_key;
391 
392 	DES_ecb3_encrypt(__UNCONST(in), out, &keys[0], &keys[1], &keys[2],
393 			DES_ENCRYPT);
394 }
395 
396 static void
397 tripledes_block_decrypt(__ops_crypt_t *crypt, void *out, const void *in)
398 {
399 	DES_key_schedule *keys = crypt->encrypt_key;
400 
401 	DES_ecb3_encrypt(__UNCONST(in), out, &keys[0], &keys[1], &keys[2],
402 			DES_DECRYPT);
403 }
404 
405 static void
406 tripledes_cfb_encrypt(__ops_crypt_t *crypt, void *out, const void *in,
407 			size_t count)
408 {
409 	DES_key_schedule *keys = crypt->encrypt_key;
410 
411 	DES_ede3_cfb64_encrypt(in, out, (long)count,
412 		&keys[0], &keys[1], &keys[2], (DES_cblock *)(void *)crypt->iv,
413 		&crypt->num, DES_ENCRYPT);
414 }
415 
416 static void
417 tripledes_cfb_decrypt(__ops_crypt_t *crypt, void *out, const void *in,
418 			size_t count)
419 {
420 	DES_key_schedule *keys = crypt->encrypt_key;
421 
422 	DES_ede3_cfb64_encrypt(in, out, (long)count,
423 		&keys[0], &keys[1], &keys[2], (DES_cblock *)(void *)crypt->iv,
424 		&crypt->num, DES_DECRYPT);
425 }
426 
427 static const __ops_crypt_t tripledes =
428 {
429 	OPS_SA_TRIPLEDES,
430 	8,
431 	24,
432 	std_set_iv,
433 	std_set_key,
434 	tripledes_init,
435 	std_resync,
436 	tripledes_block_encrypt,
437 	tripledes_block_decrypt,
438 	tripledes_cfb_encrypt,
439 	tripledes_cfb_decrypt,
440 	std_finish,
441 	TRAILER
442 };
443 
444 static const __ops_crypt_t *
445 get_proto(__ops_symm_alg_t alg)
446 {
447 	switch (alg) {
448 	case OPS_SA_CAST5:
449 		return &cast5;
450 
451 #ifndef OPENSSL_NO_IDEA
452 	case OPS_SA_IDEA:
453 		return &idea;
454 #endif				/* OPENSSL_NO_IDEA */
455 
456 	case OPS_SA_AES_128:
457 		return &aes128;
458 
459 	case OPS_SA_AES_256:
460 		return &aes256;
461 
462 	case OPS_SA_TRIPLEDES:
463 		return &tripledes;
464 
465 	default:
466 		(void) fprintf(stderr, "Unknown algorithm: %d (%s)\n",
467 			alg, __ops_show_symm_alg(alg));
468 	}
469 
470 	return NULL;
471 }
472 
473 int
474 __ops_crypt_any(__ops_crypt_t *crypt, __ops_symm_alg_t alg)
475 {
476 	const __ops_crypt_t *ptr = get_proto(alg);
477 
478 	if (ptr) {
479 		*crypt = *ptr;
480 		return 1;
481 	} else {
482 		(void) memset(crypt, 0x0, sizeof(*crypt));
483 		return 0;
484 	}
485 }
486 
487 unsigned
488 __ops_block_size(__ops_symm_alg_t alg)
489 {
490 	const __ops_crypt_t *p = get_proto(alg);
491 
492 	return (p == NULL) ? 0 : (unsigned)p->blocksize;
493 }
494 
495 unsigned
496 __ops_key_size(__ops_symm_alg_t alg)
497 {
498 	const __ops_crypt_t *p = get_proto(alg);
499 
500 	return (p == NULL) ? 0 : (unsigned)p->keysize;
501 }
502 
503 void
504 __ops_encrypt_init(__ops_crypt_t *encrypt)
505 {
506 	/* \todo should there be a separate __ops_encrypt_init? */
507 	__ops_decrypt_init(encrypt);
508 }
509 
510 void
511 __ops_decrypt_init(__ops_crypt_t *decrypt)
512 {
513 	decrypt->base_init(decrypt);
514 	decrypt->block_encrypt(decrypt, decrypt->siv, decrypt->iv);
515 	(void) memcpy(decrypt->civ, decrypt->siv, decrypt->blocksize);
516 	decrypt->num = 0;
517 }
518 
519 size_t
520 __ops_decrypt_se(__ops_crypt_t *decrypt, void *outvoid, const void *invoid,
521 		size_t count)
522 {
523 	const uint8_t	*in = invoid;
524 	uint8_t		*out = outvoid;
525 	int              saved = (int)count;
526 
527 	/*
528 	 * in order to support v3's weird resyncing we have to implement CFB
529 	 * mode ourselves
530 	 */
531 	while (count-- > 0) {
532 		uint8_t   t;
533 
534 		if ((size_t) decrypt->num == decrypt->blocksize) {
535 			(void) memcpy(decrypt->siv, decrypt->civ,
536 					decrypt->blocksize);
537 			decrypt->block_decrypt(decrypt, decrypt->civ,
538 					decrypt->civ);
539 			decrypt->num = 0;
540 		}
541 		t = decrypt->civ[decrypt->num];
542 		*out++ = t ^ (decrypt->civ[decrypt->num++] = *in++);
543 	}
544 
545 	return (size_t)saved;
546 }
547 
548 size_t
549 __ops_encrypt_se(__ops_crypt_t *encrypt, void *outvoid, const void *invoid,
550 	       size_t count)
551 {
552 	const uint8_t	*in = invoid;
553 	uint8_t		*out = outvoid;
554 	int              saved = (int)count;
555 
556 	/*
557 	 * in order to support v3's weird resyncing we have to implement CFB
558 	 * mode ourselves
559 	 */
560 	while (count-- > 0) {
561 		if ((size_t) encrypt->num == encrypt->blocksize) {
562 			(void) memcpy(encrypt->siv, encrypt->civ,
563 					encrypt->blocksize);
564 			encrypt->block_encrypt(encrypt, encrypt->civ,
565 					encrypt->civ);
566 			encrypt->num = 0;
567 		}
568 		encrypt->civ[encrypt->num] = *out++ =
569 				encrypt->civ[encrypt->num] ^ *in++;
570 		++encrypt->num;
571 	}
572 
573 	return (size_t)saved;
574 }
575 
576 /**
577 \ingroup HighLevel_Supported
578 \brief Is this Symmetric Algorithm supported?
579 \param alg Symmetric Algorithm to check
580 \return 1 if supported; else 0
581 */
582 unsigned
583 __ops_is_sa_supported(__ops_symm_alg_t alg)
584 {
585 	switch (alg) {
586 	case OPS_SA_AES_128:
587 	case OPS_SA_AES_256:
588 	case OPS_SA_CAST5:
589 	case OPS_SA_TRIPLEDES:
590 #ifndef OPENSSL_NO_IDEA
591 	case OPS_SA_IDEA:
592 #endif
593 		return 1;
594 
595 	default:
596 		fprintf(stderr, "\nWarning: %s not supported\n",
597 			__ops_show_symm_alg(alg));
598 		return 0;
599 	}
600 }
601 
602 size_t
603 __ops_encrypt_se_ip(__ops_crypt_t *crypt, void *out, const void *in,
604 		  size_t count)
605 {
606 	if (!__ops_is_sa_supported(crypt->alg)) {
607 		return 0;
608 	}
609 
610 	crypt->cfb_encrypt(crypt, out, in, count);
611 
612 	/* \todo test this number was encrypted */
613 	return count;
614 }
615 
616 size_t
617 __ops_decrypt_se_ip(__ops_crypt_t *crypt, void *out, const void *in,
618 		  size_t count)
619 {
620 	if (!__ops_is_sa_supported(crypt->alg)) {
621 		return 0;
622 	}
623 
624 	crypt->cfb_decrypt(crypt, out, in, count);
625 
626 	/* \todo check this number was in fact decrypted */
627 	return count;
628 }
629