Sync usage with man page.
[netbsd-mini2440.git] / crypto / external / bsd / netpgp / dist / src / lib / symmetric.c
blobf935cf6c3e3270f009708ec27685f26e66306a44
1 /*-
2 * Copyright (c) 2009 The NetBSD Foundation, Inc.
3 * All rights reserved.
5 * This code is derived from software contributed to The NetBSD Foundation
6 * by Alistair Crooks (agc@NetBSD.org)
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.
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.
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.
36 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
37 * use this file except in compliance with the License.
39 * You may obtain a copy of the License at
40 * http://www.apache.org/licenses/LICENSE-2.0
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.
46 * See the License for the specific language governing permissions and
47 * limitations under the License.
49 #include "config.h"
51 #ifdef HAVE_SYS_CDEFS_H
52 #include <sys/cdefs.h>
53 #endif
55 #if defined(__NetBSD__)
56 __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
57 __RCSID("$NetBSD: symmetric.c,v 1.8 2009/10/07 04:18:47 agc Exp $");
58 #endif
60 #include "crypto.h"
61 #include "packet-show.h"
63 #include <string.h>
65 #ifdef HAVE_OPENSSL_CAST_H
66 #include <openssl/cast.h>
67 #endif
69 #ifdef HAVE_OPENSSL_IDEA_H
70 #include <openssl/idea.h>
71 #endif
73 #ifdef HAVE_OPENSSL_AES_H
74 #include <openssl/aes.h>
75 #endif
77 #ifdef HAVE_OPENSSL_DES_H
78 #include <openssl/des.h>
79 #endif
81 #include "crypto.h"
82 #include "netpgpdefs.h"
85 static void
86 std_set_iv(__ops_crypt_t *crypt, const unsigned char *iv)
88 (void) memcpy(crypt->iv, iv, crypt->blocksize);
89 crypt->num = 0;
92 static void
93 std_set_key(__ops_crypt_t *crypt, const unsigned char *key)
95 (void) memcpy(crypt->key, key, crypt->keysize);
98 static void
99 std_resync(__ops_crypt_t *decrypt)
101 if ((size_t) decrypt->num == decrypt->blocksize) {
102 return;
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;
112 static void
113 std_finish(__ops_crypt_t *crypt)
115 if (crypt->encrypt_key) {
116 free(crypt->encrypt_key);
117 crypt->encrypt_key = NULL;
119 if (crypt->decrypt_key) {
120 free(crypt->decrypt_key);
121 crypt->decrypt_key = NULL;
125 static void
126 cast5_init(__ops_crypt_t *crypt)
128 if (crypt->encrypt_key) {
129 free(crypt->encrypt_key);
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);
137 static void
138 cast5_block_encrypt(__ops_crypt_t *crypt, void *out, const void *in)
140 CAST_ecb_encrypt(in, out, crypt->encrypt_key, CAST_ENCRYPT);
143 static void
144 cast5_block_decrypt(__ops_crypt_t *crypt, void *out, const void *in)
146 CAST_ecb_encrypt(in, out, crypt->encrypt_key, CAST_DECRYPT);
149 static void
150 cast5_cfb_encrypt(__ops_crypt_t *crypt, void *out, const void *in, size_t count)
152 CAST_cfb64_encrypt(in, out, (long)count,
153 crypt->encrypt_key, crypt->iv, &crypt->num,
154 CAST_ENCRYPT);
157 static void
158 cast5_cfb_decrypt(__ops_crypt_t *crypt, void *out, const void *in, size_t count)
160 CAST_cfb64_encrypt(in, out, (long)count,
161 crypt->encrypt_key, crypt->iv, &crypt->num,
162 CAST_DECRYPT);
165 #define TRAILER "","","","",0,NULL,NULL
167 static __ops_crypt_t cast5 =
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
184 #ifndef OPENSSL_NO_IDEA
185 static void
186 idea_init(__ops_crypt_t *crypt)
188 if (crypt->keysize != IDEA_KEY_LENGTH) {
189 (void) fprintf(stderr, "idea_init: keysize wrong\n");
190 return;
193 if (crypt->encrypt_key) {
194 free(crypt->encrypt_key);
196 crypt->encrypt_key = calloc(1, sizeof(IDEA_KEY_SCHEDULE));
198 /* note that we don't invert the key when decrypting for CFB mode */
199 idea_set_encrypt_key(crypt->key, crypt->encrypt_key);
201 if (crypt->decrypt_key) {
202 free(crypt->decrypt_key);
204 crypt->decrypt_key = calloc(1, sizeof(IDEA_KEY_SCHEDULE));
206 idea_set_decrypt_key(crypt->encrypt_key, crypt->decrypt_key);
209 static void
210 idea_block_encrypt(__ops_crypt_t *crypt, void *out, const void *in)
212 idea_ecb_encrypt(in, out, crypt->encrypt_key);
215 static void
216 idea_block_decrypt(__ops_crypt_t *crypt, void *out, const void *in)
218 idea_ecb_encrypt(in, out, crypt->decrypt_key);
221 static void
222 idea_cfb_encrypt(__ops_crypt_t *crypt, void *out, const void *in, size_t count)
224 idea_cfb64_encrypt(in, out, (long)count,
225 crypt->encrypt_key, crypt->iv, &crypt->num,
226 CAST_ENCRYPT);
229 static void
230 idea_cfb_decrypt(__ops_crypt_t *crypt, void *out, const void *in, size_t count)
232 idea_cfb64_encrypt(in, out, (long)count,
233 crypt->decrypt_key, crypt->iv, &crypt->num,
234 CAST_DECRYPT);
237 static const __ops_crypt_t idea =
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
253 #endif /* OPENSSL_NO_IDEA */
255 /* AES with 128-bit key (AES) */
257 #define KEYBITS_AES128 128
259 static void
260 aes128_init(__ops_crypt_t *crypt)
262 if (crypt->encrypt_key) {
263 free(crypt->encrypt_key);
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");
271 if (crypt->decrypt_key) {
272 free(crypt->decrypt_key);
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");
281 static void
282 aes_block_encrypt(__ops_crypt_t *crypt, void *out, const void *in)
284 AES_encrypt(in, out, crypt->encrypt_key);
287 static void
288 aes_block_decrypt(__ops_crypt_t *crypt, void *out, const void *in)
290 AES_decrypt(in, out, crypt->decrypt_key);
293 static void
294 aes_cfb_encrypt(__ops_crypt_t *crypt, void *out, const void *in, size_t count)
296 AES_cfb128_encrypt(in, out, (unsigned)count,
297 crypt->encrypt_key, crypt->iv, &crypt->num,
298 AES_ENCRYPT);
301 static void
302 aes_cfb_decrypt(__ops_crypt_t *crypt, void *out, const void *in, size_t count)
304 AES_cfb128_encrypt(in, out, (unsigned)count,
305 crypt->encrypt_key, crypt->iv, &crypt->num,
306 AES_DECRYPT);
309 static const __ops_crypt_t aes128 =
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
326 /* AES with 256-bit key */
328 #define KEYBITS_AES256 256
330 static void
331 aes256_init(__ops_crypt_t *crypt)
333 if (crypt->encrypt_key) {
334 free(crypt->encrypt_key);
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");
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");
351 static const __ops_crypt_t aes256 =
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
368 /* Triple DES */
370 static void
371 tripledes_init(__ops_crypt_t *crypt)
373 DES_key_schedule *keys;
374 int n;
376 if (crypt->encrypt_key) {
377 free(crypt->encrypt_key);
379 keys = crypt->encrypt_key = calloc(1, 3 * sizeof(DES_key_schedule));
381 for (n = 0; n < 3; ++n) {
382 DES_set_key((DES_cblock *)(void *)(crypt->key + n * 8),
383 &keys[n]);
387 static void
388 tripledes_block_encrypt(__ops_crypt_t *crypt, void *out, const void *in)
390 DES_key_schedule *keys = crypt->encrypt_key;
392 DES_ecb3_encrypt(__UNCONST(in), out, &keys[0], &keys[1], &keys[2],
393 DES_ENCRYPT);
396 static void
397 tripledes_block_decrypt(__ops_crypt_t *crypt, void *out, const void *in)
399 DES_key_schedule *keys = crypt->encrypt_key;
401 DES_ecb3_encrypt(__UNCONST(in), out, &keys[0], &keys[1], &keys[2],
402 DES_DECRYPT);
405 static void
406 tripledes_cfb_encrypt(__ops_crypt_t *crypt, void *out, const void *in,
407 size_t count)
409 DES_key_schedule *keys = crypt->encrypt_key;
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);
416 static void
417 tripledes_cfb_decrypt(__ops_crypt_t *crypt, void *out, const void *in,
418 size_t count)
420 DES_key_schedule *keys = crypt->encrypt_key;
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);
427 static const __ops_crypt_t tripledes =
429 OPS_SA_TRIPLEDES,
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
444 static const __ops_crypt_t *
445 get_proto(__ops_symm_alg_t alg)
447 switch (alg) {
448 case OPS_SA_CAST5:
449 return &cast5;
451 #ifndef OPENSSL_NO_IDEA
452 case OPS_SA_IDEA:
453 return &idea;
454 #endif /* OPENSSL_NO_IDEA */
456 case OPS_SA_AES_128:
457 return &aes128;
459 case OPS_SA_AES_256:
460 return &aes256;
462 case OPS_SA_TRIPLEDES:
463 return &tripledes;
465 default:
466 (void) fprintf(stderr, "Unknown algorithm: %d (%s)\n",
467 alg, __ops_show_symm_alg(alg));
470 return NULL;
473 int
474 __ops_crypt_any(__ops_crypt_t *crypt, __ops_symm_alg_t alg)
476 const __ops_crypt_t *ptr = get_proto(alg);
478 if (ptr) {
479 *crypt = *ptr;
480 return 1;
481 } else {
482 (void) memset(crypt, 0x0, sizeof(*crypt));
483 return 0;
487 unsigned
488 __ops_block_size(__ops_symm_alg_t alg)
490 const __ops_crypt_t *p = get_proto(alg);
492 return (p == NULL) ? 0 : p->blocksize;
495 unsigned
496 __ops_key_size(__ops_symm_alg_t alg)
498 const __ops_crypt_t *p = get_proto(alg);
500 return (p == NULL) ? 0 : p->keysize;
503 void
504 __ops_encrypt_init(__ops_crypt_t *encrypt)
506 /* \todo should there be a separate __ops_encrypt_init? */
507 __ops_decrypt_init(encrypt);
510 void
511 __ops_decrypt_init(__ops_crypt_t *decrypt)
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;
519 size_t
520 __ops_decrypt_se(__ops_crypt_t *decrypt, void *outvoid, const void *invoid,
521 size_t count)
523 unsigned char *out = outvoid;
524 const unsigned char *in = invoid;
525 int saved = count;
528 * in order to support v3's weird resyncing we have to implement CFB
529 * mode ourselves
531 while (count-- > 0) {
532 unsigned char t;
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;
541 t = decrypt->civ[decrypt->num];
542 *out++ = t ^ (decrypt->civ[decrypt->num++] = *in++);
545 return (size_t)saved;
548 size_t
549 __ops_encrypt_se(__ops_crypt_t *encrypt, void *outvoid, const void *invoid,
550 size_t count)
552 unsigned char *out = outvoid;
553 const unsigned char *in = invoid;
554 int saved = count;
557 * in order to support v3's weird resyncing we have to implement CFB
558 * mode ourselves
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;
568 encrypt->civ[encrypt->num] = *out++ =
569 encrypt->civ[encrypt->num] ^ *in++;
570 ++encrypt->num;
573 return (size_t)saved;
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
582 unsigned
583 __ops_is_sa_supported(__ops_symm_alg_t alg)
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;
595 default:
596 fprintf(stderr, "\nWarning: %s not supported\n",
597 __ops_show_symm_alg(alg));
598 return 0;
602 size_t
603 __ops_encrypt_se_ip(__ops_crypt_t *crypt, void *out, const void *in,
604 size_t count)
606 if (!__ops_is_sa_supported(crypt->alg)) {
607 return 0;
610 crypt->cfb_encrypt(crypt, out, in, count);
612 /* \todo test this number was encrypted */
613 return count;
616 size_t
617 __ops_decrypt_se_ip(__ops_crypt_t *crypt, void *out, const void *in,
618 size_t count)
620 if (!__ops_is_sa_supported(crypt->alg)) {
621 return 0;
624 crypt->cfb_decrypt(crypt, out, in, count);
626 /* \todo check this number was in fact decrypted */
627 return count;