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