Home | History | Annotate | Download | only in mech
      1 /*
      2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
      3  * Use is subject to license terms.
      4  */
      5 
      6 
      7 /*
      8   * Copyright2001 by the Massachusetts Institute of Technology.
      9  * Copyright 1993 by OpenVision Technologies, Inc.
     10  *
     11  * Permission to use, copy, modify, distribute, and sell this software
     12  * and its documentation for any purpose is hereby granted without fee,
     13  * provided that the above copyright notice appears in all copies and
     14  * that both that copyright notice and this permission notice appear in
     15  * supporting documentation, and that the name of OpenVision not be used
     16  * in advertising or publicity pertaining to distribution of the software
     17  * without specific, written prior permission. OpenVision makes no
     18  * representations about the suitability of this software for any
     19  * purpose.  It is provided "as is" without express or implied warranty.
     20  *
     21  * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     22  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     23  * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     24  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
     25  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
     26  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     27  * PERFORMANCE OF THIS SOFTWARE.
     28  */
     29 
     30 /*
     31  * Copyright (C) 1998 by the FundsXpress, INC.
     32  *
     33  * All rights reserved.
     34  *
     35  * Export of this software from the United States of America may require
     36  * a specific license from the United States Government.  It is the
     37  * responsibility of any person or organization contemplating export to
     38  * obtain such a license before exporting.
     39  *
     40  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
     41  * distribute this software and its documentation for any purpose and
     42  * without fee is hereby granted, provided that the above copyright
     43  * notice appear in all copies and that both that copyright notice and
     44  * this permission notice appear in supporting documentation, and that
     45  * the name of FundsXpress. not be used in advertising or publicity pertaining
     46  * to distribution of the software without specific, written prior
     47  * permission.  FundsXpress makes no representations about the suitability of
     48  * this software for any purpose.  It is provided "as is" without express
     49  * or implied warranty.
     50  *
     51  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
     52  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
     53  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     54  */
     55 
     56 /* Solaris Kerberos:  order is important here.  include gssapiP_krb5.h
     57  * before all others, otherwise we get a LINT error from MALLOC macro
     58  * being redefined in mechglueP.h */
     59 #include <gssapiP_krb5.h>
     60 #include <k5-int.h>
     61 
     62 /* Solaris Kerberos defines memory management macros in <krb5.h> */
     63 /* #include <memory.h> */
     64 
     65 /*
     66  * $Id: util_crypt.c,v 1.11.6.3 2000/06/03 06:09:45 tlyu Exp $
     67  */
     68 
     69 int
     70 kg_confounder_size(context, key)
     71      krb5_context context;
     72      krb5_keyblock *key;
     73 {
     74    krb5_error_code code;
     75    size_t blocksize;
     76    /* We special case rc4*/
     77    if (key->enctype == ENCTYPE_ARCFOUR_HMAC)
     78      return 8;
     79    code = krb5_c_block_size(context, key->enctype, &blocksize);
     80    if (code)
     81       return(-1); /* XXX */
     82 
     83    return(blocksize);
     84 }
     85 
     86 krb5_error_code
     87 kg_make_confounder(context, key, buf)
     88      krb5_context context;
     89      krb5_keyblock *key;
     90      unsigned char *buf;
     91 {
     92    krb5_error_code code;
     93    size_t blocksize;
     94    krb5_data lrandom;
     95 
     96    code = krb5_c_block_size(context, key->enctype, &blocksize);
     97    if (code)
     98        return(code);
     99 
    100    lrandom.length = blocksize;
    101    lrandom.data = (char *) buf;
    102 
    103    return(krb5_c_random_make_octets(context, &lrandom));
    104 }
    105 
    106 int
    107 kg_encrypt_size(context, key, n)
    108      krb5_context context;
    109      krb5_keyblock *key;
    110      int n;
    111 {
    112    size_t enclen;
    113 
    114    if (krb5_c_encrypt_length(context, key->enctype, n, &enclen) != 0)
    115       return(-1); /* XXX */
    116 
    117    return(enclen);
    118 }
    119 
    120 krb5_error_code
    121 kg_encrypt(context, key, usage, iv, in, out, length)
    122      krb5_context context;
    123      krb5_keyblock *key;
    124      int usage;
    125      krb5_pointer iv;
    126      krb5_const_pointer in;
    127      krb5_pointer out;
    128      unsigned int length;
    129 {
    130    krb5_error_code code;
    131    size_t blocksize;
    132    krb5_data ivd, *pivd, inputd;
    133    krb5_enc_data outputd;
    134 
    135    KRB5_LOG0(KRB5_INFO, "kg_encrypt() start.");
    136 
    137    if (iv) {
    138        code = krb5_c_block_size(context, key->enctype, &blocksize);
    139        if (code)
    140 	   return(code);
    141 
    142        ivd.length = blocksize;
    143        ivd.data = MALLOC(ivd.length);
    144        if (ivd.data == NULL)
    145 	   return ENOMEM;
    146        (void) memcpy(ivd.data, iv, ivd.length);
    147        pivd = &ivd;
    148    } else {
    149        pivd = NULL;
    150    }
    151 
    152    inputd.length = length;
    153    inputd.data = (char *)in; /* Solaris Kerberos */
    154 
    155    outputd.ciphertext.length = length;
    156    outputd.ciphertext.data = out;
    157 
    158    code = krb5_c_encrypt(context, key, usage, pivd, &inputd, &outputd);
    159    if (pivd != NULL)
    160        krb5_free_data_contents(context, pivd);
    161 
    162    KRB5_LOG(KRB5_INFO, "kg_encrypt() end. code = %d", code);
    163    return code;
    164 }
    165 
    166 /* length is the length of the cleartext. */
    167 
    168 krb5_error_code
    169 kg_decrypt(context, key, usage, iv, in, out, length)
    170      krb5_context context;
    171      krb5_keyblock *key;
    172      int usage;
    173      krb5_pointer iv;
    174      krb5_const_pointer in;
    175      krb5_pointer out;
    176      unsigned int length;
    177 {
    178    krb5_error_code code;
    179    size_t blocksize;
    180    krb5_data ivd, *pivd, outputd;
    181    krb5_enc_data inputd;
    182    KRB5_LOG0(KRB5_INFO, "kg_decrypt() start.");
    183 
    184    if (iv) {
    185        code = krb5_c_block_size(context, key->enctype, &blocksize);
    186        if (code)
    187 	   return(code);
    188 
    189        ivd.length = blocksize;
    190        ivd.data = MALLOC(ivd.length);
    191        if (ivd.data == NULL)
    192 	   return ENOMEM;
    193        (void) memcpy(ivd.data, iv, ivd.length);
    194        pivd = &ivd;
    195    } else {
    196        pivd = NULL;
    197    }
    198 
    199    inputd.enctype = ENCTYPE_UNKNOWN;
    200    inputd.ciphertext.length = length;
    201    inputd.ciphertext.data = (char *)in; /* Solaris Kerberos */
    202 
    203    outputd.length = length;
    204    outputd.data = out;
    205 
    206    code = krb5_c_decrypt(context, key, usage, pivd, &inputd, &outputd);
    207    if (pivd != NULL)
    208        krb5_free_data_contents(context, pivd);
    209 
    210    KRB5_LOG(KRB5_INFO, "kg_decrypt() end. code = %d", code);
    211    return code;
    212 }
    213 
    214 krb5_error_code
    215 kg_arcfour_docrypt (krb5_context context,
    216 		const krb5_keyblock *longterm_key , int ms_usage,
    217 		const unsigned char *kd_data, size_t kd_data_len,
    218 		const unsigned char *input_buf, size_t input_len,
    219 		unsigned char *output_buf)
    220 {
    221   krb5_error_code code;
    222   krb5_data input, output;
    223   krb5_keyblock seq_enc_key, usage_key;
    224   unsigned char t[4];
    225 
    226   KRB5_LOG0(KRB5_INFO, "kg_arcfour_docrypt() start");
    227 
    228   bzero(&usage_key, sizeof(krb5_keyblock));
    229   bzero(&seq_enc_key, sizeof(krb5_keyblock));
    230 
    231   usage_key.length = longterm_key->length;
    232   usage_key.contents = MALLOC(usage_key.length);
    233   usage_key.enctype = longterm_key->enctype;
    234   usage_key.dk_list = NULL;
    235 #ifdef _KERNEL
    236 
    237   usage_key.kef_mt  = longterm_key->kef_mt;
    238   code = init_key_kef(longterm_key->kef_mt, &usage_key);
    239   if (code)
    240 	return (code);
    241 #endif /* _KERNEL */
    242   if (usage_key.contents == NULL)
    243     return (ENOMEM);
    244   seq_enc_key.length = longterm_key->length;
    245   seq_enc_key.contents = MALLOC(seq_enc_key.length);
    246   seq_enc_key.enctype = longterm_key->enctype;
    247   seq_enc_key.dk_list = NULL;
    248 #ifdef _KERNEL
    249   seq_enc_key.kef_mt  = longterm_key->kef_mt;
    250   code = init_key_kef(longterm_key->kef_mt, &seq_enc_key);
    251   if (code)
    252 	return (code);
    253 #endif /* _KERNEL */
    254   if (seq_enc_key.contents == NULL) {
    255     FREE ((void *) usage_key.contents, usage_key.length);
    256     return (ENOMEM);
    257   }
    258 
    259   t[0] = ms_usage &0xff;
    260   t[1] = (ms_usage>>8) & 0xff;
    261   t[2] = (ms_usage>>16) & 0xff;
    262   t[3] = (ms_usage>>24) & 0xff;
    263   input.data = (void *) &t;
    264   input.length = 4;
    265   output.data = (void *) usage_key.contents;
    266   output.length = usage_key.length;
    267 #ifdef _KERNEL
    268   code = krb5_hmac(context, longterm_key, &input, &output);
    269 #else
    270   code = krb5_hmac(context, &krb5int_hash_md5,
    271 		longterm_key, 1, &input, &output);
    272 #endif /* _KERNEL */
    273   if (code)
    274     goto cleanup_arcfour;
    275 
    276   input.data = ( void *) kd_data;
    277   input.length = kd_data_len;
    278   output.data = (void *) seq_enc_key.contents;
    279 #ifdef _KERNEL
    280   code = krb5_hmac(context, &usage_key, &input, &output);
    281 #else
    282   code = krb5_hmac(context, &krb5int_hash_md5,
    283 		&usage_key, 1, &input, &output);
    284 #endif /* _KERNEL */
    285 
    286   if (code)
    287     goto cleanup_arcfour;
    288   input.data = ( void * ) input_buf;
    289   input.length = input_len;
    290   output.data = (void * ) output_buf;
    291   output.length = input_len;
    292 
    293   /*
    294    * Call the arcfour encryption method directly here, we cannot
    295    * use the standard "krb5_c_encrypt" interface because we just
    296    * want the arcfour algorithm applied and not the additional MD5-HMAC
    297    * which are applied when using the standard interface.
    298    */
    299   code = krb5int_enc_arcfour.encrypt(context, &seq_enc_key, 0, &input, &output);
    300 
    301  cleanup_arcfour:
    302   bzero ((void *) seq_enc_key.contents, seq_enc_key.length);
    303   bzero ((void *) usage_key.contents, usage_key.length);
    304   FREE ((void *) usage_key.contents, usage_key.length);
    305   FREE ((void *) seq_enc_key.contents, seq_enc_key.length);
    306 
    307   KRB5_LOG(KRB5_INFO, "kg_arcfour_docrypt() end code = %d", code);
    308   return (code);
    309 }
    310 
    311