10Sstevel@tonic-gate /*
2*5826Smp153739 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
30Sstevel@tonic-gate * Use is subject to license terms.
40Sstevel@tonic-gate */
50Sstevel@tonic-gate
60Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
70Sstevel@tonic-gate
80Sstevel@tonic-gate /*
90Sstevel@tonic-gate * lib/crypto/des/string2key.c
100Sstevel@tonic-gate *
110Sstevel@tonic-gate * Copyright 1990,1991 by the Massachusetts Institute of Technology.
120Sstevel@tonic-gate * All Rights Reserved.
130Sstevel@tonic-gate *
140Sstevel@tonic-gate * Export of this software from the United States of America may
150Sstevel@tonic-gate * require a specific license from the United States Government.
160Sstevel@tonic-gate * It is the responsibility of any person or organization contemplating
170Sstevel@tonic-gate * export to obtain such a license before exporting.
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
200Sstevel@tonic-gate * distribute this software and its documentation for any purpose and
210Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright
220Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and
230Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that
240Sstevel@tonic-gate * the name of M.I.T. not be used in advertising or publicity pertaining
250Sstevel@tonic-gate * to distribution of the software without specific, written prior
260Sstevel@tonic-gate * permission. M.I.T. makes no representations about the suitability of
270Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express
280Sstevel@tonic-gate * or implied warranty.
290Sstevel@tonic-gate */
300Sstevel@tonic-gate
310Sstevel@tonic-gate #include <k5-int.h>
320Sstevel@tonic-gate #include <des_int.h>
330Sstevel@tonic-gate
340Sstevel@tonic-gate /*
350Sstevel@tonic-gate converts the string pointed to by "data" into an encryption key
360Sstevel@tonic-gate of type "enctype". *keyblock is filled in with the key info;
370Sstevel@tonic-gate in particular, keyblock->contents is to be set to allocated storage.
380Sstevel@tonic-gate It is the responsibility of the caller to release this storage
390Sstevel@tonic-gate when the generated key no longer needed.
400Sstevel@tonic-gate
410Sstevel@tonic-gate The routine may use "salt" to seed or alter the conversion
420Sstevel@tonic-gate algorithm.
430Sstevel@tonic-gate
440Sstevel@tonic-gate If the particular function called does not know how to make a
450Sstevel@tonic-gate key of type "enctype", an error may be returned.
460Sstevel@tonic-gate
470Sstevel@tonic-gate returns: errors
480Sstevel@tonic-gate */
490Sstevel@tonic-gate
500Sstevel@tonic-gate krb5_error_code
mit_des_string_to_key_int(krb5_context context,krb5_keyblock * keyblock,const krb5_data * data,const krb5_data * salt)510Sstevel@tonic-gate mit_des_string_to_key_int (krb5_context context,
520Sstevel@tonic-gate krb5_keyblock *keyblock,
530Sstevel@tonic-gate const krb5_data *data,
540Sstevel@tonic-gate const krb5_data *salt)
550Sstevel@tonic-gate {
560Sstevel@tonic-gate krb5_error_code retval = KRB5_PROG_ETYPE_NOSUPP;
570Sstevel@tonic-gate /* EXPORT DELETE START */
580Sstevel@tonic-gate register char *str, *copystr;
590Sstevel@tonic-gate register krb5_octet *key;
600Sstevel@tonic-gate register unsigned temp;
610Sstevel@tonic-gate register long i;
620Sstevel@tonic-gate register int j;
630Sstevel@tonic-gate register long length;
640Sstevel@tonic-gate unsigned char *k_p;
650Sstevel@tonic-gate int forward;
660Sstevel@tonic-gate register char *p_char;
670Sstevel@tonic-gate char k_char[64];
680Sstevel@tonic-gate
690Sstevel@tonic-gate #ifndef min
700Sstevel@tonic-gate #define min(A, B) ((A) < (B) ? (A): (B))
710Sstevel@tonic-gate #endif
720Sstevel@tonic-gate
730Sstevel@tonic-gate keyblock->magic = KV5M_KEYBLOCK;
740Sstevel@tonic-gate keyblock->length = sizeof(mit_des_cblock);
750Sstevel@tonic-gate key = keyblock->contents;
760Sstevel@tonic-gate
77*5826Smp153739 if (salt
78*5826Smp153739 && (salt->length == SALT_TYPE_AFS_LENGTH
79*5826Smp153739 /* XXX Yuck! Aren't we done with this yet? */
80*5826Smp153739 || salt->length == (unsigned) -1)) {
81*5826Smp153739 krb5_data afssalt;
82*5826Smp153739 char *at;
83*5826Smp153739
84*5826Smp153739 afssalt.data = salt->data;
85*5826Smp153739 at = strchr(afssalt.data, '@');
86*5826Smp153739 if (at) {
87*5826Smp153739 *at = 0;
88*5826Smp153739 afssalt.length = at - afssalt.data;
89*5826Smp153739 } else
90*5826Smp153739 afssalt.length = strlen(afssalt.data);
91*5826Smp153739 return mit_afs_string_to_key(context, keyblock, data, &afssalt);
92*5826Smp153739 }
93*5826Smp153739
94*5826Smp153739 length = data->length + (salt ? salt->length : 0);
950Sstevel@tonic-gate
960Sstevel@tonic-gate copystr = malloc((size_t) length);
970Sstevel@tonic-gate if (!copystr) {
980Sstevel@tonic-gate return ENOMEM;
990Sstevel@tonic-gate }
1000Sstevel@tonic-gate
1010Sstevel@tonic-gate (void) memcpy(copystr, (char *) data->data, data->length);
1020Sstevel@tonic-gate if (salt)
1030Sstevel@tonic-gate (void) memcpy(copystr + data->length, (char *)salt->data, salt->length);
1040Sstevel@tonic-gate
1050Sstevel@tonic-gate /* convert to des key */
1060Sstevel@tonic-gate forward = 1;
1070Sstevel@tonic-gate p_char = k_char;
1080Sstevel@tonic-gate
1090Sstevel@tonic-gate /* init key array for bits */
1100Sstevel@tonic-gate (void) memset(k_char,0,sizeof(k_char));
1110Sstevel@tonic-gate
1120Sstevel@tonic-gate #if 0
1130Sstevel@tonic-gate if (mit_des_debug)
1140Sstevel@tonic-gate fprintf(stdout,
1150Sstevel@tonic-gate "\n\ninput str length = %d string = %*s\nstring = 0x ",
1160Sstevel@tonic-gate length,length,str);
1170Sstevel@tonic-gate #endif
1180Sstevel@tonic-gate
1190Sstevel@tonic-gate str = copystr;
1200Sstevel@tonic-gate
1210Sstevel@tonic-gate /* get next 8 bytes, strip parity, xor */
1220Sstevel@tonic-gate for (i = 1; i <= length; i++) {
1230Sstevel@tonic-gate /* get next input key byte */
1240Sstevel@tonic-gate temp = (unsigned int) *str++;
1250Sstevel@tonic-gate #if 0
1260Sstevel@tonic-gate if (mit_des_debug)
1270Sstevel@tonic-gate fprintf(stdout,"%02x ",temp & 0xff);
1280Sstevel@tonic-gate #endif
1290Sstevel@tonic-gate /* loop through bits within byte, ignore parity */
1300Sstevel@tonic-gate for (j = 0; j <= 6; j++) {
1310Sstevel@tonic-gate if (forward)
1320Sstevel@tonic-gate *p_char++ ^= (int) temp & 01;
1330Sstevel@tonic-gate else
1340Sstevel@tonic-gate *--p_char ^= (int) temp & 01;
1350Sstevel@tonic-gate temp = temp >> 1;
1360Sstevel@tonic-gate }
1370Sstevel@tonic-gate
1380Sstevel@tonic-gate /* check and flip direction */
1390Sstevel@tonic-gate if ((i%8) == 0)
1400Sstevel@tonic-gate forward = !forward;
1410Sstevel@tonic-gate }
1420Sstevel@tonic-gate
1430Sstevel@tonic-gate /* now stuff into the key mit_des_cblock, and force odd parity */
1440Sstevel@tonic-gate p_char = k_char;
1450Sstevel@tonic-gate k_p = (unsigned char *) key;
1460Sstevel@tonic-gate
1470Sstevel@tonic-gate for (i = 0; i <= 7; i++) {
1480Sstevel@tonic-gate temp = 0;
1490Sstevel@tonic-gate for (j = 0; j <= 6; j++)
1500Sstevel@tonic-gate temp |= *p_char++ << (1+j);
1510Sstevel@tonic-gate *k_p++ = (unsigned char) temp;
1520Sstevel@tonic-gate }
1530Sstevel@tonic-gate
1540Sstevel@tonic-gate /* fix key parity */
1550Sstevel@tonic-gate mit_des_fixup_key_parity(key);
1560Sstevel@tonic-gate if (mit_des_is_weak_key(key))
1570Sstevel@tonic-gate ((krb5_octet *)key)[7] ^= 0xf0;
1580Sstevel@tonic-gate
1590Sstevel@tonic-gate retval = mit_des_cbc_cksum(context, (unsigned char*)copystr, key,
1600Sstevel@tonic-gate length, keyblock, key);
1610Sstevel@tonic-gate
1620Sstevel@tonic-gate /* clean & free the input string */
1630Sstevel@tonic-gate (void) memset(copystr, 0, (size_t) length);
1640Sstevel@tonic-gate krb5_xfree(copystr);
1650Sstevel@tonic-gate
1660Sstevel@tonic-gate /* now fix up key parity again */
1670Sstevel@tonic-gate mit_des_fixup_key_parity(key);
1680Sstevel@tonic-gate if (mit_des_is_weak_key(key))
1690Sstevel@tonic-gate ((krb5_octet *)key)[7] ^= 0xf0;
1700Sstevel@tonic-gate
1710Sstevel@tonic-gate /*
1720Sstevel@tonic-gate * Because this routine actually modifies the original keyblock
1730Sstevel@tonic-gate * in place we cannot use the PKCS#11 key object handle created earlier.
1740Sstevel@tonic-gate * Destroy the existing object handle associated with the key,
1750Sstevel@tonic-gate * a correct handle will get created when the key is actually
1760Sstevel@tonic-gate * used for the first time.
1770Sstevel@tonic-gate */
1780Sstevel@tonic-gate if (keyblock->hKey != CK_INVALID_HANDLE) {
1790Sstevel@tonic-gate (void)C_DestroyObject(krb_ctx_hSession(context), keyblock->hKey);
1800Sstevel@tonic-gate keyblock->hKey = CK_INVALID_HANDLE;
1810Sstevel@tonic-gate }
1820Sstevel@tonic-gate
1830Sstevel@tonic-gate /* EXPORT DELETE END */
1840Sstevel@tonic-gate return retval;
1850Sstevel@tonic-gate }
186