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