2 * Copyright (c) 2009 The NetBSD Foundation, Inc.
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
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.
51 #ifdef HAVE_SYS_CDEFS_H
52 #include <sys/cdefs.h>
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 $");
61 #include "packet-show.h"
65 #ifdef HAVE_OPENSSL_CAST_H
66 #include <openssl/cast.h>
69 #ifdef HAVE_OPENSSL_IDEA_H
70 #include <openssl/idea.h>
73 #ifdef HAVE_OPENSSL_AES_H
74 #include <openssl/aes.h>
77 #ifdef HAVE_OPENSSL_DES_H
78 #include <openssl/des.h>
82 #include "netpgpdefs.h"
86 std_set_iv(__ops_crypt_t
*crypt
, const unsigned char *iv
)
88 (void) memcpy(crypt
->iv
, iv
, crypt
->blocksize
);
93 std_set_key(__ops_crypt_t
*crypt
, const unsigned char *key
)
95 (void) memcpy(crypt
->key
, key
, crypt
->keysize
);
99 std_resync(__ops_crypt_t
*decrypt
)
101 if ((size_t) decrypt
->num
== decrypt
->blocksize
) {
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
);
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
;
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
);
138 cast5_block_encrypt(__ops_crypt_t
*crypt
, void *out
, const void *in
)
140 CAST_ecb_encrypt(in
, out
, crypt
->encrypt_key
, CAST_ENCRYPT
);
144 cast5_block_decrypt(__ops_crypt_t
*crypt
, void *out
, const void *in
)
146 CAST_ecb_encrypt(in
, out
, crypt
->encrypt_key
, CAST_DECRYPT
);
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
,
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
,
165 #define TRAILER "","","","",0,NULL,NULL
167 static __ops_crypt_t cast5
=
184 #ifndef OPENSSL_NO_IDEA
186 idea_init(__ops_crypt_t
*crypt
)
188 if (crypt
->keysize
!= IDEA_KEY_LENGTH
) {
189 (void) fprintf(stderr
, "idea_init: keysize wrong\n");
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
);
210 idea_block_encrypt(__ops_crypt_t
*crypt
, void *out
, const void *in
)
212 idea_ecb_encrypt(in
, out
, crypt
->encrypt_key
);
216 idea_block_decrypt(__ops_crypt_t
*crypt
, void *out
, const void *in
)
218 idea_ecb_encrypt(in
, out
, crypt
->decrypt_key
);
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
,
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
,
237 static const __ops_crypt_t idea
=
253 #endif /* OPENSSL_NO_IDEA */
255 /* AES with 128-bit key (AES) */
257 #define KEYBITS_AES128 128
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");
282 aes_block_encrypt(__ops_crypt_t
*crypt
, void *out
, const void *in
)
284 AES_encrypt(in
, out
, crypt
->encrypt_key
);
288 aes_block_decrypt(__ops_crypt_t
*crypt
, void *out
, const void *in
)
290 AES_decrypt(in
, out
, crypt
->decrypt_key
);
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
,
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
,
309 static const __ops_crypt_t aes128
=
326 /* AES with 256-bit key */
328 #define KEYBITS_AES256 256
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
=
371 tripledes_init(__ops_crypt_t
*crypt
)
373 DES_key_schedule
*keys
;
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),
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],
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],
406 tripledes_cfb_encrypt(__ops_crypt_t
*crypt
, void *out
, const void *in
,
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
);
417 tripledes_cfb_decrypt(__ops_crypt_t
*crypt
, void *out
, const void *in
,
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
=
436 tripledes_block_encrypt
,
437 tripledes_block_decrypt
,
438 tripledes_cfb_encrypt
,
439 tripledes_cfb_decrypt
,
444 static const __ops_crypt_t
*
445 get_proto(__ops_symm_alg_t alg
)
451 #ifndef OPENSSL_NO_IDEA
454 #endif /* OPENSSL_NO_IDEA */
462 case OPS_SA_TRIPLEDES
:
466 (void) fprintf(stderr
, "Unknown algorithm: %d (%s)\n",
467 alg
, __ops_show_symm_alg(alg
));
474 __ops_crypt_any(__ops_crypt_t
*crypt
, __ops_symm_alg_t alg
)
476 const __ops_crypt_t
*ptr
= get_proto(alg
);
482 (void) memset(crypt
, 0x0, sizeof(*crypt
));
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
;
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
;
504 __ops_encrypt_init(__ops_crypt_t
*encrypt
)
506 /* \todo should there be a separate __ops_encrypt_init? */
507 __ops_decrypt_init(encrypt
);
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
);
520 __ops_decrypt_se(__ops_crypt_t
*decrypt
, void *outvoid
, const void *invoid
,
523 unsigned char *out
= outvoid
;
524 const unsigned char *in
= invoid
;
528 * in order to support v3's weird resyncing we have to implement CFB
531 while (count
-- > 0) {
534 if ((size_t) decrypt
->num
== decrypt
->blocksize
) {
535 (void) memcpy(decrypt
->siv
, decrypt
->civ
,
537 decrypt
->block_decrypt(decrypt
, decrypt
->civ
,
541 t
= decrypt
->civ
[decrypt
->num
];
542 *out
++ = t
^ (decrypt
->civ
[decrypt
->num
++] = *in
++);
545 return (size_t)saved
;
549 __ops_encrypt_se(__ops_crypt_t
*encrypt
, void *outvoid
, const void *invoid
,
552 unsigned char *out
= outvoid
;
553 const unsigned char *in
= invoid
;
557 * in order to support v3's weird resyncing we have to implement CFB
560 while (count
-- > 0) {
561 if ((size_t) encrypt
->num
== encrypt
->blocksize
) {
562 (void) memcpy(encrypt
->siv
, encrypt
->civ
,
564 encrypt
->block_encrypt(encrypt
, encrypt
->civ
,
568 encrypt
->civ
[encrypt
->num
] = *out
++ =
569 encrypt
->civ
[encrypt
->num
] ^ *in
++;
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
583 __ops_is_sa_supported(__ops_symm_alg_t alg
)
589 case OPS_SA_TRIPLEDES
:
590 #ifndef OPENSSL_NO_IDEA
596 fprintf(stderr
, "\nWarning: %s not supported\n",
597 __ops_show_symm_alg(alg
));
603 __ops_encrypt_se_ip(__ops_crypt_t
*crypt
, void *out
, const void *in
,
606 if (!__ops_is_sa_supported(crypt
->alg
)) {
610 crypt
->cfb_encrypt(crypt
, out
, in
, count
);
612 /* \todo test this number was encrypted */
617 __ops_decrypt_se_ip(__ops_crypt_t
*crypt
, void *out
, const void *in
,
620 if (!__ops_is_sa_supported(crypt
->alg
)) {
624 crypt
->cfb_decrypt(crypt
, out
, in
, count
);
626 /* \todo check this number was in fact decrypted */