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