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