xref: /onnv-gate/usr/src/lib/gss_mechs/mech_krb5/crypto/des/string2key.c (revision 5826:0bfa56468300)
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