xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/lib/symmetric.c (revision 93bf6008f8b7982c1d1a9486e4a4a0e687fe36eb)
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 		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, crypt->keysize, crypt->key);
98 	crypt->decrypt_key = calloc(1, sizeof(CAST_KEY));
99 	CAST_set_key(crypt->decrypt_key, 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, 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, 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, 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, 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, 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, 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 *) (crypt->key + n * 8), &keys[n]);
331 }
332 
333 static void
334 tripledes_block_encrypt(__ops_crypt_t * crypt, void *out,
335 			const void *in)
336 {
337 	DES_key_schedule *keys = crypt->encrypt_key;
338 
339 	DES_ecb3_encrypt(__UNCONST(in), out, &keys[0], &keys[1], &keys[2], DES_ENCRYPT);
340 }
341 
342 static void
343 tripledes_block_decrypt(__ops_crypt_t * crypt, void *out,
344 			const void *in)
345 {
346 	DES_key_schedule *keys = crypt->encrypt_key;
347 
348 	DES_ecb3_encrypt(__UNCONST(in), out, &keys[0], &keys[1], &keys[2], DES_DECRYPT);
349 }
350 
351 static void
352 tripledes_cfb_encrypt(__ops_crypt_t * crypt, void *out, const void *in, size_t count)
353 {
354 	DES_key_schedule *keys = crypt->encrypt_key;
355 
356 	DES_ede3_cfb64_encrypt(in, out, count,
357 		&keys[0], &keys[1], &keys[2], (DES_cblock *) crypt->iv,
358 		&crypt->num, DES_ENCRYPT);
359 }
360 
361 static void
362 tripledes_cfb_decrypt(__ops_crypt_t * crypt, void *out, const void *in, size_t count)
363 {
364 	DES_key_schedule *keys = crypt->encrypt_key;
365 
366 	DES_ede3_cfb64_encrypt(in, out, count,
367 		&keys[0], &keys[1], &keys[2], (DES_cblock *) crypt->iv,
368 		&crypt->num, DES_DECRYPT);
369 }
370 
371 static const __ops_crypt_t tripledes =
372 {
373 	OPS_SA_TRIPLEDES,
374 	8,
375 	24,
376 	std_set_iv,
377 	std_set_key,
378 	tripledes_init,
379 	std_resync,
380 	tripledes_block_encrypt,
381 	tripledes_block_decrypt,
382 	tripledes_cfb_encrypt,
383 	tripledes_cfb_decrypt,
384 	std_finish,
385 	TRAILER
386 };
387 
388 static const __ops_crypt_t *
389 get_proto(__ops_symmetric_algorithm_t alg)
390 {
391 	switch (alg) {
392 	case OPS_SA_CAST5:
393 		return &cast5;
394 
395 #ifndef OPENSSL_NO_IDEA
396 	case OPS_SA_IDEA:
397 		return &idea;
398 #endif				/* OPENSSL_NO_IDEA */
399 
400 	case OPS_SA_AES_128:
401 		return &aes128;
402 
403 	case OPS_SA_AES_256:
404 		return &aes256;
405 
406 	case OPS_SA_TRIPLEDES:
407 		return &tripledes;
408 
409 	default:
410 		fprintf(stderr, "Unknown algorithm: %d (%s)\n", alg, __ops_show_symmetric_algorithm(alg));
411 		/* assert(0); */
412 	}
413 
414 	return NULL;
415 }
416 
417 int
418 __ops_crypt_any(__ops_crypt_t * crypt, __ops_symmetric_algorithm_t alg)
419 {
420 	const __ops_crypt_t *ptr = get_proto(alg);
421 	if (ptr) {
422 		*crypt = *ptr;
423 		return 1;
424 	} else {
425 		(void) memset(crypt, 0x0, sizeof(*crypt));
426 		return 0;
427 	}
428 }
429 
430 unsigned
431 __ops_block_size(__ops_symmetric_algorithm_t alg)
432 {
433 	const __ops_crypt_t *p = get_proto(alg);
434 
435 	if (!p)
436 		return 0;
437 
438 	return p->blocksize;
439 }
440 
441 unsigned
442 __ops_key_size(__ops_symmetric_algorithm_t alg)
443 {
444 	const __ops_crypt_t *p = get_proto(alg);
445 
446 	if (!p)
447 		return 0;
448 
449 	return p->keysize;
450 }
451 
452 void
453 __ops_encrypt_init(__ops_crypt_t * encrypt)
454 {
455 	/* \todo should there be a separate __ops_encrypt_init? */
456 	__ops_decrypt_init(encrypt);
457 }
458 
459 void
460 __ops_decrypt_init(__ops_crypt_t * decrypt)
461 {
462 	decrypt->base_init(decrypt);
463 	decrypt->block_encrypt(decrypt, decrypt->siv, decrypt->iv);
464 	(void) memcpy(decrypt->civ, decrypt->siv, decrypt->blocksize);
465 	decrypt->num = 0;
466 }
467 
468 size_t
469 __ops_decrypt_se(__ops_crypt_t * decrypt, void *outvoid, const void *invoid, size_t count)
470 {
471 	unsigned char  *out = outvoid;
472 	const unsigned char *in = invoid;
473 	int             saved = count;
474 
475 	/*
476 	 * in order to support v3's weird resyncing we have to implement CFB
477 	 * mode ourselves
478 	 */
479 	while (count-- > 0) {
480 		unsigned char   t;
481 
482 		if ((size_t) decrypt->num == decrypt->blocksize) {
483 			(void) memcpy(decrypt->siv, decrypt->civ, decrypt->blocksize);
484 			decrypt->block_decrypt(decrypt, decrypt->civ, decrypt->civ);
485 			decrypt->num = 0;
486 		}
487 		t = decrypt->civ[decrypt->num];
488 		*out++ = t ^ (decrypt->civ[decrypt->num++] = *in++);
489 	}
490 
491 	return saved;
492 }
493 
494 size_t
495 __ops_encrypt_se(__ops_crypt_t * encrypt, void *outvoid, const void *invoid,
496 	       size_t count)
497 {
498 	unsigned char  *out = outvoid;
499 	const unsigned char *in = invoid;
500 	int             saved = count;
501 
502 	/*
503 	 * in order to support v3's weird resyncing we have to implement CFB
504 	 * mode ourselves
505 	 */
506 	while (count-- > 0) {
507 		if ((size_t) encrypt->num == encrypt->blocksize) {
508 			(void) memcpy(encrypt->siv, encrypt->civ, encrypt->blocksize);
509 			encrypt->block_encrypt(encrypt, encrypt->civ, encrypt->civ);
510 			encrypt->num = 0;
511 		}
512 		encrypt->civ[encrypt->num] = *out++ = encrypt->civ[encrypt->num] ^ *in++;
513 		++encrypt->num;
514 	}
515 
516 	return saved;
517 }
518 
519 /**
520 \ingroup HighLevel_Supported
521 \brief Is this Symmetric Algorithm supported?
522 \param alg Symmetric Algorithm to check
523 \return true if supported; else false
524 */
525 bool
526 __ops_is_sa_supported(__ops_symmetric_algorithm_t alg)
527 {
528 	switch (alg) {
529 	case OPS_SA_AES_128:
530 	case OPS_SA_AES_256:
531 	case OPS_SA_CAST5:
532 	case OPS_SA_TRIPLEDES:
533 #ifndef OPENSSL_NO_IDEA
534 	case OPS_SA_IDEA:
535 #endif
536 		return true;
537 		break;
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 		return -1;
552 
553 	crypt->cfb_encrypt(crypt, out, in, count);
554 
555 	/* \todo test this number was encrypted */
556 	return count;
557 }
558 
559 size_t
560 __ops_decrypt_se_ip(__ops_crypt_t * crypt, void *out, const void *in,
561 		  size_t count)
562 {
563 	if (!__ops_is_sa_supported(crypt->algorithm))
564 		return -1;
565 
566 	crypt->cfb_decrypt(crypt, out, in, count);
567 
568 	/* \todo check this number was in fact decrypted */
569 	return count;
570 }
571