/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ #pragma weak _des_crypt = des_crypt #pragma weak _des_encrypt = des_encrypt #pragma weak _des_setkey = des_setkey #include #include #include "des_soft.h" #include #include #include #include /* * This program implements the * Proposed Federal Information Processing * Data Encryption Standard. * See Federal Register, March 17, 1975 (40FR12134) */ /* * Initial permutation, */ static char IP[] = { 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7, }; /* * Final permutation, FP = IP^(-1) */ static char FP[] = { 40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31, 38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29, 36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27, 34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25, }; /* * Permuted-choice 1 from the key bits * to yield C and D. * Note that bits 8, 16... are left out: * They are intended for a parity check. */ static char PC1_C[] = { 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, }; static char PC1_D[] = { 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4, }; /* * Sequence of shifts used for the key schedule. */ static char shifts[] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, }; /* * Permuted-choice 2, to pick out the bits from * the CD array that generate the key schedule. */ static char PC2_C[] = { 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, }; static char PC2_D[] = { 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32, }; /* * The C and D arrays used to calculate the key schedule. */ static char C[28]; static char D[28]; /* * The key schedule. * Generated from the key. */ static char KS[16][48]; /* * The E bit-selection table. */ static char E[48]; static char e2[] = { 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17, 16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25, 24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1, }; /* * Set up the key schedule from the key. */ static mutex_t lock = DEFAULTMUTEX; static void des_setkey_nolock(const char *key) { int i, j, k; char t; /* * First, generate C and D by permuting * the key. The low order bit of each * 8-bit char is not used, so C and D are only 28 * bits apiece. */ for (i = 0; i < 28; i++) { C[i] = key[PC1_C[i]-1]; D[i] = key[PC1_D[i]-1]; } /* * To generate Ki, rotate C and D according * to schedule and pick up a permutation * using PC2. */ for (i = 0; i < 16; i++) { /* * rotate. */ for (k = 0; k < shifts[i]; k++) { t = C[0]; for (j = 0; j < 28-1; j++) C[j] = C[j+1]; C[27] = (char)t; t = D[0]; for (j = 0; j < 28-1; j++) D[j] = D[j+1]; D[27] = (char)t; } /* * get Ki. Note C and D are concatenated. */ for (j = 0; j < 24; j++) { KS[i][j] = C[PC2_C[j]-1]; KS[i][j+24] = D[PC2_D[j]-28-1]; } } for (i = 0; i < 48; i++) E[i] = e2[i]; } void des_setkey(const char *key) { (void) mutex_lock(&lock); des_setkey_nolock(key); (void) mutex_unlock(&lock); } /* * The 8 selection functions. * For some reason, they give a 0-origin * index, unlike everything else. */ static char S[8][64] = { 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13, 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9, 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12, 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14, 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3, 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13, 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12, 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11, }; /* * P is a permutation on the selected combination * of the current L and key. */ static char P[] = { 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25, }; /* * The current block, divided into 2 halves. */ static char L[64]; static char tempL[32]; static char f[32]; /* * The combination of the key and the input, before selection. */ static char preS[48]; /* * The payoff: encrypt a block. */ static void des_encrypt_nolock(char *block, int edflag) { if (edflag) (void) _des_decrypt1(block, L, IP, &L[32], preS, E, KS, S, f, tempL, P, FP); else (void) des_encrypt1(block, L, IP, &L[32], preS, E, KS, S, f, tempL, P, FP); } void des_encrypt(char *block, int edflag) { (void) mutex_lock(&lock); des_encrypt_nolock(block, edflag); (void) mutex_unlock(&lock); } #define IOBUF_SIZE 16 static char * _get_iobuf(thread_key_t *keyp, unsigned size) { char *iobuf; if (thr_keycreate_once(keyp, free) != 0) return (NULL); iobuf = pthread_getspecific(*keyp); if (iobuf == NULL) { if (thr_setspecific(*keyp, (iobuf = malloc(size))) != 0) { if (iobuf) (void) free(iobuf); iobuf = NULL; } } return (iobuf); } char * des_crypt(const char *pw, const char *salt) { int i, j; char c, temp; char block[66]; static thread_key_t key = THR_ONCE_KEY; char *iobuf = _get_iobuf(&key, IOBUF_SIZE); (void) mutex_lock(&lock); for (i = 0; i < 66; i++) block[i] = 0; for (i = 0; (c = *pw) && (i < 64); pw++) { for (j = 0; j < 7; j++, i++) block[i] = (c>>(6-j)) & 01; i++; } des_setkey_nolock(block); for (i = 0; i < 66; i++) block[i] = 0; for (i = 0; i < 2; i++) { c = *salt++; iobuf[i] = (char)c; if (c > 'Z') c -= 6; if (c > '9') c -= 7; c -= '.'; for (j = 0; j < 6; j++) { if ((c>>j) & 01) { temp = E[6*i+j]; E[6*i+j] = E[6*i+j+24]; E[6*i+j+24] = (char)temp; } } } for (i = 0; i < 25; i++) (void) des_encrypt_nolock(block, 0); for (i = 0; i < 11; i++) { c = 0; for (j = 0; j < 6; j++) { c <<= 1; c |= block[6*i+j]; } c += '.'; if (c > '9') c += 7; if (c > 'Z') c += 6; iobuf[i+2] = (char)c; } iobuf[i+2] = 0; if (iobuf[1] == 0) iobuf[1] = iobuf[0]; (void) mutex_unlock(&lock); return (iobuf); }