1 /*
   2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
   3  * Use is subject to license terms.
   4  */
   5 
   6 #pragma ident   "%Z%%M% %I%     %E% SMI"
   7 
   8 /*
   9  * lib/crypto/des/string2key.c
  10  *
  11  * Copyright 1990,1991 by the Massachusetts Institute of Technology.
  12  * All Rights Reserved.
  13  *
  14  * Export of this software from the United States of America may
  15  *   require a specific license from the United States Government.
  16  *   It is the responsibility of any person or organization contemplating
  17  *   export to obtain such a license before exporting.
  18  *
  19  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
  20  * distribute this software and its documentation for any purpose and
  21  * without fee is hereby granted, provided that the above copyright
  22  * notice appear in all copies and that both that copyright notice and
  23  * this permission notice appear in supporting documentation, and that
  24  * the name of M.I.T. not be used in advertising or publicity pertaining
  25  * to distribution of the software without specific, written prior
  26  * permission.  M.I.T. makes no representations about the suitability of
  27  * this software for any purpose.  It is provided "as is" without express
  28  * or implied warranty.
  29  */
  30 
  31 #include <k5-int.h>
  32 #include <des_int.h>
  33 
  34 /*
  35         converts the string pointed to by "data" into an encryption key
  36         of type "enctype".  *keyblock is filled in with the key info;
  37         in particular, keyblock->contents is to be set to allocated storage.
  38         It is the responsibility of the caller to release this storage
  39         when the generated key no longer needed.
  40 
  41         The routine may use "salt" to seed or alter the conversion
  42         algorithm.
  43 
  44         If the particular function called does not know how to make a
  45         key of type "enctype", an error may be returned.
  46 
  47         returns: errors
  48  */
  49 
  50 krb5_error_code
  51 mit_des_string_to_key_int (krb5_context context,
  52         krb5_keyblock *keyblock,
  53         const krb5_data *data,
  54         const krb5_data *salt)
  55 {
  56     krb5_error_code retval = KRB5_PROG_ETYPE_NOSUPP;
  57 /* EXPORT DELETE START */
  58     register char *str, *copystr;
  59     register krb5_octet *key;
  60     register unsigned temp;
  61     register long i;
  62     register int j;
  63     register long length;
  64     unsigned char *k_p;
  65     int forward;
  66     register char *p_char;
  67     char k_char[64];
  68 
  69 #ifndef min
  70 #define min(A, B) ((A) < (B) ? (A): (B))
  71 #endif
  72 
  73     keyblock->magic = KV5M_KEYBLOCK;
  74     keyblock->length = sizeof(mit_des_cblock);
  75     key = keyblock->contents;
  76 
  77     if (salt
  78         && (salt->length == SALT_TYPE_AFS_LENGTH
  79             /* XXX  Yuck!  Aren't we done with this yet?  */
  80             || salt->length == (unsigned) -1)) {
  81         krb5_data afssalt;
  82         char *at;
  83 
  84         afssalt.data = salt->data;
  85         at = strchr(afssalt.data, '@');
  86         if (at) {
  87             *at = 0;
  88             afssalt.length = at - afssalt.data;
  89         } else
  90             afssalt.length = strlen(afssalt.data);
  91         return mit_afs_string_to_key(context, keyblock, data, &afssalt);
  92     }
  93 
  94     length = data->length + (salt ? salt->length : 0);
  95 
  96     copystr = malloc((size_t) length);
  97     if (!copystr) {
  98         return ENOMEM;
  99     }
 100 
 101     (void) memcpy(copystr, (char *) data->data, data->length);
 102     if (salt)
 103         (void) memcpy(copystr + data->length, (char *)salt->data, salt->length);
 104 
 105     /* convert to des key */
 106     forward = 1;
 107     p_char = k_char;
 108 
 109     /* init key array for bits */
 110     (void) memset(k_char,0,sizeof(k_char));
 111 
 112 #if 0
 113     if (mit_des_debug)
 114         fprintf(stdout,
 115                 "\n\ninput str length = %d  string = %*s\nstring = 0x ",
 116                 length,length,str);
 117 #endif
 118 
 119     str = copystr;
 120 
 121     /* get next 8 bytes, strip parity, xor */
 122     for (i = 1; i <= length; i++) {
 123         /* get next input key byte */
 124         temp = (unsigned int) *str++;
 125 #if 0
 126         if (mit_des_debug)
 127             fprintf(stdout,"%02x ",temp & 0xff);
 128 #endif
 129         /* loop through bits within byte, ignore parity */
 130         for (j = 0; j <= 6; j++) {
 131             if (forward)
 132                 *p_char++ ^= (int) temp & 01;
 133             else
 134                 *--p_char ^= (int) temp & 01;
 135             temp = temp >> 1;
 136         }
 137 
 138         /* check and flip direction */
 139         if ((i%8) == 0)
 140             forward = !forward;
 141     }
 142 
 143     /* now stuff into the key mit_des_cblock, and force odd parity */
 144     p_char = k_char;
 145     k_p = (unsigned char *) key;
 146 
 147     for (i = 0; i <= 7; i++) {
 148         temp = 0;
 149         for (j = 0; j <= 6; j++)
 150             temp |= *p_char++ << (1+j);
 151         *k_p++ = (unsigned char) temp;
 152     }
 153 
 154     /* fix key parity */
 155     mit_des_fixup_key_parity(key);
 156     if (mit_des_is_weak_key(key))
 157         ((krb5_octet *)key)[7] ^= 0xf0;
 158 
 159     retval = mit_des_cbc_cksum(context, (unsigned char*)copystr, key,
 160         length, keyblock, key);
 161 
 162     /* clean & free the input string */
 163     (void) memset(copystr, 0, (size_t) length);
 164     krb5_xfree(copystr);
 165 
 166     /* now fix up key parity again */
 167     mit_des_fixup_key_parity(key);
 168     if (mit_des_is_weak_key(key))
 169         ((krb5_octet *)key)[7] ^= 0xf0;
 170 
 171     /*
 172      * Because this routine actually modifies the original keyblock
 173      * in place we cannot use the PKCS#11 key object handle created earlier.
 174      * Destroy the existing object handle associated with the key,
 175      * a correct handle will get created when the key is actually
 176      * used for the first time.
 177      */
 178      if (keyblock->hKey != CK_INVALID_HANDLE) {
 179         (void)C_DestroyObject(krb_ctx_hSession(context), keyblock->hKey);
 180         keyblock->hKey = CK_INVALID_HANDLE;
 181      }
 182 
 183 /* EXPORT DELETE END */
 184     return retval;
 185 }