xref: /titanic_51/usr/src/common/net/wanboot/crypt/des3.c (revision 50c83d09652262aba75a6182b3203c80b48b092b)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
23*50c83d09Scarlsonj  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #include <stdlib.h>
307c478bd9Sstevel@tonic-gate #include <strings.h>
317c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #include "des3.h"
347c478bd9Sstevel@tonic-gate #include "des.h"
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate typedef struct keysched_s {
377c478bd9Sstevel@tonic-gate 	uint32_t ksch_encrypt1[16][2];
387c478bd9Sstevel@tonic-gate 	uint32_t ksch_encrypt2[16][2];
397c478bd9Sstevel@tonic-gate 	uint32_t ksch_encrypt3[16][2];
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate 	uint32_t ksch_decrypt1[16][2];
427c478bd9Sstevel@tonic-gate 	uint32_t ksch_decrypt2[16][2];
437c478bd9Sstevel@tonic-gate 	uint32_t ksch_decrypt3[16][2];
447c478bd9Sstevel@tonic-gate } keysched_t;
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate int
477c478bd9Sstevel@tonic-gate des3_init(void **cookie)
487c478bd9Sstevel@tonic-gate {
497c478bd9Sstevel@tonic-gate 	if ((*cookie = malloc(sizeof (keysched_t))) == NULL) {
507c478bd9Sstevel@tonic-gate 		return (-1);
517c478bd9Sstevel@tonic-gate 	}
527c478bd9Sstevel@tonic-gate 	return (0);
537c478bd9Sstevel@tonic-gate }
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate void
567c478bd9Sstevel@tonic-gate des3_fini(void *cookie)
577c478bd9Sstevel@tonic-gate {
587c478bd9Sstevel@tonic-gate 	free(cookie);
597c478bd9Sstevel@tonic-gate }
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate void
627c478bd9Sstevel@tonic-gate des3_encrypt(void *cookie, uint8_t *block)
637c478bd9Sstevel@tonic-gate {
647c478bd9Sstevel@tonic-gate 	keysched_t *ksch = (keysched_t *)cookie;
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate 	des(ksch->ksch_encrypt1, block);
677c478bd9Sstevel@tonic-gate 	des(ksch->ksch_decrypt2, block);
687c478bd9Sstevel@tonic-gate 	des(ksch->ksch_encrypt3, block);
697c478bd9Sstevel@tonic-gate }
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate void
727c478bd9Sstevel@tonic-gate des3_decrypt(void *cookie, uint8_t *block)
737c478bd9Sstevel@tonic-gate {
747c478bd9Sstevel@tonic-gate 	keysched_t *ksch = (keysched_t *)cookie;
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate 	des(ksch->ksch_decrypt3, block);
777c478bd9Sstevel@tonic-gate 	des(ksch->ksch_encrypt2, block);
787c478bd9Sstevel@tonic-gate 	des(ksch->ksch_decrypt1, block);
797c478bd9Sstevel@tonic-gate }
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate /*
827c478bd9Sstevel@tonic-gate  * Generate key schedule for triple DES in E-D-E (or D-E-D) mode.
837c478bd9Sstevel@tonic-gate  *
847c478bd9Sstevel@tonic-gate  * The key argument is taken to be 24 bytes. The first 8 bytes are K1
857c478bd9Sstevel@tonic-gate  * for the first stage, the second 8 bytes are K2 for the middle stage
867c478bd9Sstevel@tonic-gate  * and the third 8 bytes are K3 for the last stage
877c478bd9Sstevel@tonic-gate  */
887c478bd9Sstevel@tonic-gate void
897c478bd9Sstevel@tonic-gate des3_key(void *cookie, const uint8_t *key)
907c478bd9Sstevel@tonic-gate {
917c478bd9Sstevel@tonic-gate 	keysched_t *ks = (keysched_t *)cookie;
927c478bd9Sstevel@tonic-gate 	uint8_t *k1 = (uint8_t *)key;
937c478bd9Sstevel@tonic-gate 	uint8_t *k2 = k1 + DES_KEY_SIZE;
947c478bd9Sstevel@tonic-gate 	uint8_t *k3 = k2 + DES_KEY_SIZE;
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate 	des_key(ks->ksch_decrypt1, k1, B_TRUE);
977c478bd9Sstevel@tonic-gate 	des_key(ks->ksch_encrypt1, k1, B_FALSE);
987c478bd9Sstevel@tonic-gate 	des_key(ks->ksch_decrypt2, k2, B_TRUE);
997c478bd9Sstevel@tonic-gate 	des_key(ks->ksch_encrypt2, k2, B_FALSE);
1007c478bd9Sstevel@tonic-gate 	des_key(ks->ksch_decrypt3, k3, B_TRUE);
1017c478bd9Sstevel@tonic-gate 	des_key(ks->ksch_encrypt3, k3, B_FALSE);
1027c478bd9Sstevel@tonic-gate }
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate boolean_t
1067c478bd9Sstevel@tonic-gate des3_keycheck(const uint8_t *key)
1077c478bd9Sstevel@tonic-gate {
1087c478bd9Sstevel@tonic-gate 	uint64_t key_so_far;
1097c478bd9Sstevel@tonic-gate 	uint64_t scratch;
1107c478bd9Sstevel@tonic-gate 	uint64_t *currentkey;
1117c478bd9Sstevel@tonic-gate 	uint64_t tmpbuf[3];
1127c478bd9Sstevel@tonic-gate 	uint_t parity;
1137c478bd9Sstevel@tonic-gate 	uint_t num_weakkeys = 0;
1147c478bd9Sstevel@tonic-gate 	uint_t i;
1157c478bd9Sstevel@tonic-gate 	uint_t j;
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate 	/*
1187c478bd9Sstevel@tonic-gate 	 * Table of weak and semi-weak keys.  Fortunately, weak keys are
1197c478bd9Sstevel@tonic-gate 	 * endian-independent, and some semi-weak keys can be paired up in
1207c478bd9Sstevel@tonic-gate 	 * endian-opposite order.  Since keys are stored as uint64_t's,
1217c478bd9Sstevel@tonic-gate 	 * use the ifdef _LITTLE_ENDIAN where appropriate.
1227c478bd9Sstevel@tonic-gate 	 */
1237c478bd9Sstevel@tonic-gate 	static uint64_t des_weak_keys[] = {
1247c478bd9Sstevel@tonic-gate 		/* Really weak keys.  Byte-order independent values. */
125*50c83d09Scarlsonj 		0x0101010101010101ULL,
126*50c83d09Scarlsonj 		0x1f1f1f1f0e0e0e0eULL,
127*50c83d09Scarlsonj 		0xe0e0e0e0f1f1f1f1ULL,
128*50c83d09Scarlsonj 		0xfefefefefefefefeULL,
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 		/* Semi-weak (and a few possibly-weak) keys. */
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate 		/* Byte-order independent semi-weak keys. */
133*50c83d09Scarlsonj 		0x01fe01fe01fe01feULL,	0xfe01fe01fe01fe01ULL,
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 		/* Byte-order dependent semi-weak keys. */
1367c478bd9Sstevel@tonic-gate #ifdef _LITTLE_ENDIAN
137*50c83d09Scarlsonj 		0xf10ef10ee01fe01fULL,	0x0ef10ef11fe01fe0ULL,
138*50c83d09Scarlsonj 		0x01f101f101e001e0ULL,	0xf101f101e001e001ULL,
139*50c83d09Scarlsonj 		0x0efe0efe1ffe1ffeULL,	0xfe0efe0efe1ffe1fULL,
140*50c83d09Scarlsonj 		0x010e010e011f011fULL,	0x0e010e011f011f01ULL,
141*50c83d09Scarlsonj 		0xf1fef1fee0fee0feULL,	0xfef1fef1fee0fee0ULL,
1427c478bd9Sstevel@tonic-gate #else	/* Big endian */
143*50c83d09Scarlsonj 		0x1fe01fe00ef10ef1ULL,	0xe01fe01ff10ef10eULL,
144*50c83d09Scarlsonj 		0x01e001e001f101f1ULL,	0xe001e001f101f101ULL,
145*50c83d09Scarlsonj 		0x1ffe1ffe0efe0efeULL,	0xfe1ffe1ffe0efe0eULL,
146*50c83d09Scarlsonj 		0x011f011f010e010eULL,	0x1f011f010e010e01ULL,
147*50c83d09Scarlsonj 		0xe0fee0fef1fef1feULL,	0xfee0fee0fef1fef1ULL,
1487c478bd9Sstevel@tonic-gate #endif
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 		/* We'll save the other possibly-weak keys for the future. */
1517c478bd9Sstevel@tonic-gate 	};
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 	if (IS_P2ALIGNED(key, sizeof (uint64_t))) {
1547c478bd9Sstevel@tonic-gate 		/* LINTED */
1557c478bd9Sstevel@tonic-gate 		currentkey = (uint64_t *)key;
1567c478bd9Sstevel@tonic-gate 	} else {
1577c478bd9Sstevel@tonic-gate 		currentkey = tmpbuf;
1587c478bd9Sstevel@tonic-gate 		bcopy(key, currentkey, 3 * sizeof (uint64_t));
1597c478bd9Sstevel@tonic-gate 	}
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	for (j = 0; j < 3; j++) {
1627c478bd9Sstevel@tonic-gate 		key_so_far = currentkey[j];
1637c478bd9Sstevel@tonic-gate 		scratch = key_so_far;
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 		/* Unroll the loop within each byte. */
1667c478bd9Sstevel@tonic-gate 		for (i = 0; i < 8; i++) {
1677c478bd9Sstevel@tonic-gate 			parity = 1;
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 			/*
1707c478bd9Sstevel@tonic-gate 			 * Start shifting at byte n, right to left.
1717c478bd9Sstevel@tonic-gate 			 * Low bit (0) doesn't count.
1727c478bd9Sstevel@tonic-gate 			 */
1737c478bd9Sstevel@tonic-gate 			scratch >>= 1;
1747c478bd9Sstevel@tonic-gate 			if (scratch & 0x1)	/* bit 1 */
1757c478bd9Sstevel@tonic-gate 				parity++;
1767c478bd9Sstevel@tonic-gate 			scratch >>= 1;
1777c478bd9Sstevel@tonic-gate 			if (scratch & 0x1)	/* bit 2 */
1787c478bd9Sstevel@tonic-gate 				parity++;
1797c478bd9Sstevel@tonic-gate 			scratch >>= 1;
1807c478bd9Sstevel@tonic-gate 			if (scratch & 0x1)	/* bit 3 */
1817c478bd9Sstevel@tonic-gate 				parity++;
1827c478bd9Sstevel@tonic-gate 			scratch >>= 1;
1837c478bd9Sstevel@tonic-gate 			if (scratch & 0x1)	/* bit 4 */
1847c478bd9Sstevel@tonic-gate 				parity++;
1857c478bd9Sstevel@tonic-gate 			scratch >>= 1;
1867c478bd9Sstevel@tonic-gate 			if (scratch & 0x1)	/* bit 5 */
1877c478bd9Sstevel@tonic-gate 				parity++;
1887c478bd9Sstevel@tonic-gate 			scratch >>= 1;
1897c478bd9Sstevel@tonic-gate 			if (scratch & 0x1)	/* bit 6 */
1907c478bd9Sstevel@tonic-gate 			parity++;
1917c478bd9Sstevel@tonic-gate 			scratch >>= 1;
1927c478bd9Sstevel@tonic-gate 			if (scratch & 0x1)	/* bit 7 */
1937c478bd9Sstevel@tonic-gate 				parity++;
1947c478bd9Sstevel@tonic-gate 			scratch >>= 1;
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 			parity &= 1;	/* Mask off other bits. */
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 			/* Will common subexpression elimination help me? */
1997c478bd9Sstevel@tonic-gate 			key_so_far &= ~((uint64_t)1 << (i << 3));
2007c478bd9Sstevel@tonic-gate 			key_so_far |= ((uint64_t)parity << (i << 3));
2017c478bd9Sstevel@tonic-gate 		}
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 		/* Do weak key check itself. */
2047c478bd9Sstevel@tonic-gate 		for (i = 0; i < (sizeof (des_weak_keys) / sizeof (uint64_t));
2057c478bd9Sstevel@tonic-gate 		    i++) {
2067c478bd9Sstevel@tonic-gate 			if (key_so_far == des_weak_keys[i]) {
2077c478bd9Sstevel@tonic-gate 				/* In 3DES, one weak key is OK.  Two is bad. */
2087c478bd9Sstevel@tonic-gate 				if (++num_weakkeys > 1) {
2097c478bd9Sstevel@tonic-gate 					return (B_FALSE);
2107c478bd9Sstevel@tonic-gate 				} else {
2117c478bd9Sstevel@tonic-gate 					/*
2127c478bd9Sstevel@tonic-gate 					 * We found a weak key, but since
2137c478bd9Sstevel@tonic-gate 					 * we've only found one weak key,
2147c478bd9Sstevel@tonic-gate 					 * we can not reject the whole 3DES
2157c478bd9Sstevel@tonic-gate 					 * set of keys as weak.
2167c478bd9Sstevel@tonic-gate 					 *
2177c478bd9Sstevel@tonic-gate 					 * Break from the weak key loop
2187c478bd9Sstevel@tonic-gate 					 * (since this DES key is weak) and
2197c478bd9Sstevel@tonic-gate 					 * continue on.
2207c478bd9Sstevel@tonic-gate 					 */
2217c478bd9Sstevel@tonic-gate 					break;
2227c478bd9Sstevel@tonic-gate 				}
2237c478bd9Sstevel@tonic-gate 			}
2247c478bd9Sstevel@tonic-gate 		}
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 		/*
2277c478bd9Sstevel@tonic-gate 		 * Fix key extension, adjust bits if necessary.
2287c478bd9Sstevel@tonic-gate 		 */
2297c478bd9Sstevel@tonic-gate 		currentkey[j] = key_so_far;
2307c478bd9Sstevel@tonic-gate 	}
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 	/*
2337c478bd9Sstevel@tonic-gate 	 * Perform key equivalence checks, now that parity is properly set.
2347c478bd9Sstevel@tonic-gate 	 * All three keys must be unique.
2357c478bd9Sstevel@tonic-gate 	 */
2367c478bd9Sstevel@tonic-gate 	if (currentkey[0] == currentkey[1] || currentkey[1] == currentkey[2] ||
2377c478bd9Sstevel@tonic-gate 	    currentkey[2] == currentkey[0]) {
2387c478bd9Sstevel@tonic-gate 		return (B_FALSE);
2397c478bd9Sstevel@tonic-gate 	}
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 	return (B_TRUE);
2427c478bd9Sstevel@tonic-gate }
243