17c478bd9Sstevel@tonic-gate /*
2*0275604fSmp  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate /*
77c478bd9Sstevel@tonic-gate  * lib/crypto/des/string2key.c
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * Copyright 1990,1991 by the Massachusetts Institute of Technology.
107c478bd9Sstevel@tonic-gate  * All Rights Reserved.
117c478bd9Sstevel@tonic-gate  *
127c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
137c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
147c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
157c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
167c478bd9Sstevel@tonic-gate  *
177c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
187c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
197c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
207c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
217c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
227c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
237c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
247c478bd9Sstevel@tonic-gate  * permission.  M.I.T. makes no representations about the suitability of
257c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
267c478bd9Sstevel@tonic-gate  * or implied warranty.
277c478bd9Sstevel@tonic-gate  */
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #include <k5-int.h>
307c478bd9Sstevel@tonic-gate #include <des_int.h>
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate /*
337c478bd9Sstevel@tonic-gate 	converts the string pointed to by "data" into an encryption key
347c478bd9Sstevel@tonic-gate 	of type "enctype".  *keyblock is filled in with the key info;
357c478bd9Sstevel@tonic-gate 	in particular, keyblock->contents is to be set to allocated storage.
367c478bd9Sstevel@tonic-gate 	It is the responsibility of the caller to release this storage
377c478bd9Sstevel@tonic-gate 	when the generated key no longer needed.
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate 	The routine may use "salt" to seed or alter the conversion
407c478bd9Sstevel@tonic-gate 	algorithm.
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate 	If the particular function called does not know how to make a
437c478bd9Sstevel@tonic-gate 	key of type "enctype", an error may be returned.
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate 	returns: errors
467c478bd9Sstevel@tonic-gate  */
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@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)497c478bd9Sstevel@tonic-gate mit_des_string_to_key_int (krb5_context context,
507c478bd9Sstevel@tonic-gate 	krb5_keyblock *keyblock,
517c478bd9Sstevel@tonic-gate 	const krb5_data *data,
527c478bd9Sstevel@tonic-gate 	const krb5_data *salt)
537c478bd9Sstevel@tonic-gate {
547c478bd9Sstevel@tonic-gate     krb5_error_code retval = KRB5_PROG_ETYPE_NOSUPP;
557c478bd9Sstevel@tonic-gate     register char *str, *copystr;
567c478bd9Sstevel@tonic-gate     register krb5_octet *key;
577c478bd9Sstevel@tonic-gate     register unsigned temp;
587c478bd9Sstevel@tonic-gate     register long i;
597c478bd9Sstevel@tonic-gate     register int j;
607c478bd9Sstevel@tonic-gate     register long length;
617c478bd9Sstevel@tonic-gate     unsigned char *k_p;
627c478bd9Sstevel@tonic-gate     int forward;
637c478bd9Sstevel@tonic-gate     register char *p_char;
647c478bd9Sstevel@tonic-gate     char k_char[64];
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate #ifndef min
677c478bd9Sstevel@tonic-gate #define min(A, B) ((A) < (B) ? (A): (B))
687c478bd9Sstevel@tonic-gate #endif
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate     keyblock->magic = KV5M_KEYBLOCK;
717c478bd9Sstevel@tonic-gate     keyblock->length = sizeof(mit_des_cblock);
727c478bd9Sstevel@tonic-gate     key = keyblock->contents;
737c478bd9Sstevel@tonic-gate 
74*0275604fSmp     if (salt
75*0275604fSmp 	&& (salt->length == SALT_TYPE_AFS_LENGTH
76*0275604fSmp 	    /* XXX  Yuck!  Aren't we done with this yet?  */
77*0275604fSmp 	    || salt->length == (unsigned) -1)) {
78*0275604fSmp 	krb5_data afssalt;
79*0275604fSmp 	char *at;
80*0275604fSmp 
81*0275604fSmp 	afssalt.data = salt->data;
82*0275604fSmp 	at = strchr(afssalt.data, '@');
83*0275604fSmp 	if (at) {
84*0275604fSmp 	    *at = 0;
85*0275604fSmp 	    afssalt.length = at - afssalt.data;
86*0275604fSmp 	} else
87*0275604fSmp 	    afssalt.length = strlen(afssalt.data);
88*0275604fSmp 	return mit_afs_string_to_key(context, keyblock, data, &afssalt);
89*0275604fSmp     }
90*0275604fSmp 
91*0275604fSmp     length = data->length + (salt ? salt->length : 0);
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate     copystr = malloc((size_t) length);
947c478bd9Sstevel@tonic-gate     if (!copystr) {
957c478bd9Sstevel@tonic-gate 	return ENOMEM;
967c478bd9Sstevel@tonic-gate     }
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate     (void) memcpy(copystr, (char *) data->data, data->length);
997c478bd9Sstevel@tonic-gate     if (salt)
1007c478bd9Sstevel@tonic-gate 	(void) memcpy(copystr + data->length, (char *)salt->data, salt->length);
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate     /* convert to des key */
1037c478bd9Sstevel@tonic-gate     forward = 1;
1047c478bd9Sstevel@tonic-gate     p_char = k_char;
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate     /* init key array for bits */
1077c478bd9Sstevel@tonic-gate     (void) memset(k_char,0,sizeof(k_char));
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate #if 0
1107c478bd9Sstevel@tonic-gate     if (mit_des_debug)
1117c478bd9Sstevel@tonic-gate 	fprintf(stdout,
1127c478bd9Sstevel@tonic-gate 		"\n\ninput str length = %d  string = %*s\nstring = 0x ",
1137c478bd9Sstevel@tonic-gate 		length,length,str);
1147c478bd9Sstevel@tonic-gate #endif
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate     str = copystr;
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate     /* get next 8 bytes, strip parity, xor */
1197c478bd9Sstevel@tonic-gate     for (i = 1; i <= length; i++) {
1207c478bd9Sstevel@tonic-gate 	/* get next input key byte */
1217c478bd9Sstevel@tonic-gate 	temp = (unsigned int) *str++;
1227c478bd9Sstevel@tonic-gate #if 0
1237c478bd9Sstevel@tonic-gate 	if (mit_des_debug)
1247c478bd9Sstevel@tonic-gate 	    fprintf(stdout,"%02x ",temp & 0xff);
1257c478bd9Sstevel@tonic-gate #endif
1267c478bd9Sstevel@tonic-gate 	/* loop through bits within byte, ignore parity */
1277c478bd9Sstevel@tonic-gate 	for (j = 0; j <= 6; j++) {
1287c478bd9Sstevel@tonic-gate 	    if (forward)
1297c478bd9Sstevel@tonic-gate 		*p_char++ ^= (int) temp & 01;
1307c478bd9Sstevel@tonic-gate 	    else
1317c478bd9Sstevel@tonic-gate 		*--p_char ^= (int) temp & 01;
1327c478bd9Sstevel@tonic-gate 	    temp = temp >> 1;
1337c478bd9Sstevel@tonic-gate 	}
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	/* check and flip direction */
1367c478bd9Sstevel@tonic-gate 	if ((i%8) == 0)
1377c478bd9Sstevel@tonic-gate 	    forward = !forward;
1387c478bd9Sstevel@tonic-gate     }
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate     /* now stuff into the key mit_des_cblock, and force odd parity */
1417c478bd9Sstevel@tonic-gate     p_char = k_char;
1427c478bd9Sstevel@tonic-gate     k_p = (unsigned char *) key;
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate     for (i = 0; i <= 7; i++) {
1457c478bd9Sstevel@tonic-gate 	temp = 0;
1467c478bd9Sstevel@tonic-gate 	for (j = 0; j <= 6; j++)
1477c478bd9Sstevel@tonic-gate 	    temp |= *p_char++ << (1+j);
1487c478bd9Sstevel@tonic-gate 	*k_p++ = (unsigned char) temp;
1497c478bd9Sstevel@tonic-gate     }
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate     /* fix key parity */
1527c478bd9Sstevel@tonic-gate     mit_des_fixup_key_parity(key);
1537c478bd9Sstevel@tonic-gate     if (mit_des_is_weak_key(key))
1547c478bd9Sstevel@tonic-gate 	((krb5_octet *)key)[7] ^= 0xf0;
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate     retval = mit_des_cbc_cksum(context, (unsigned char*)copystr, key,
1577c478bd9Sstevel@tonic-gate 	length, keyblock, key);
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate     /* clean & free the input string */
1607c478bd9Sstevel@tonic-gate     (void) memset(copystr, 0, (size_t) length);
1617c478bd9Sstevel@tonic-gate     krb5_xfree(copystr);
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate     /* now fix up key parity again */
1647c478bd9Sstevel@tonic-gate     mit_des_fixup_key_parity(key);
1657c478bd9Sstevel@tonic-gate     if (mit_des_is_weak_key(key))
1667c478bd9Sstevel@tonic-gate 	((krb5_octet *)key)[7] ^= 0xf0;
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate     /*
1697c478bd9Sstevel@tonic-gate      * Because this routine actually modifies the original keyblock
1707c478bd9Sstevel@tonic-gate      * in place we cannot use the PKCS#11 key object handle created earlier.
1717c478bd9Sstevel@tonic-gate      * Destroy the existing object handle associated with the key,
1727c478bd9Sstevel@tonic-gate      * a correct handle will get created when the key is actually
1737c478bd9Sstevel@tonic-gate      * used for the first time.
1747c478bd9Sstevel@tonic-gate      */
1757c478bd9Sstevel@tonic-gate      if (keyblock->hKey != CK_INVALID_HANDLE) {
1767c478bd9Sstevel@tonic-gate 	(void)C_DestroyObject(krb_ctx_hSession(context), keyblock->hKey);
1777c478bd9Sstevel@tonic-gate 	keyblock->hKey = CK_INVALID_HANDLE;
1787c478bd9Sstevel@tonic-gate      }
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate     return retval;
1817c478bd9Sstevel@tonic-gate }
182