Home | History | Annotate | Download | only in crypto
      1 /*
      2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
      3  * Use is subject to license terms.
      4  */
      5 
      6 
      7 /*
      8  * Copyright (C) 1998 by the FundsXpress, INC.
      9  *
     10  * All rights reserved.
     11  *
     12  * Export of this software from the United States of America may require
     13  * a specific license from the United States Government.  It is the
     14  * responsibility of any person or organization contemplating export to
     15  * obtain such a license before exporting.
     16  *
     17  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
     18  * distribute this software and its documentation for any purpose and
     19  * without fee is hereby granted, provided that the above copyright
     20  * notice appear in all copies and that both that copyright notice and
     21  * this permission notice appear in supporting documentation, and that
     22  * the name of FundsXpress. not be used in advertising or publicity pertaining
     23  * to distribution of the software without specific, written prior
     24  * permission.  FundsXpress makes no representations about the suitability of
     25  * this software for any purpose.  It is provided "as is" without express
     26  * or implied warranty.
     27  *
     28  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
     29  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
     30  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     31  */
     32 
     33 #include "k5-int.h"
     34 
     35 /*
     36  * Solaris Kerberos
     37  * krb5_string_to_key/krb5_use_enctype are needed by Samba
     38  */
     39 
     40 krb5_error_code KRB5_CALLCONV
     41 krb5_encrypt(krb5_context context, krb5_const_pointer inptr,
     42 	     krb5_pointer outptr, size_t size, krb5_encrypt_block *eblock,
     43 	     krb5_pointer ivec)
     44 {
     45     krb5_data inputd, ivecd;
     46     krb5_enc_data outputd;
     47     size_t blocksize, outlen;
     48     krb5_error_code ret;
     49 
     50     if (ivec) {
     51 	if ((ret = krb5_c_block_size(context, eblock->key->enctype, &blocksize)))
     52 	    return(ret);
     53 
     54 	ivecd.length = blocksize;
     55 	ivecd.data = ivec;
     56     }
     57 
     58     /* size is the length of the input cleartext data */
     59     inputd.length = size;
     60     inputd.data = (char*)inptr;
     61 
     62     /* The size of the output buffer isn't part of the old api.  Not too
     63        safe.  So, we assume here that it's big enough. */
     64     if ((ret = krb5_c_encrypt_length(context, eblock->key->enctype, size,
     65 				     &outlen)))
     66 	return(ret);
     67 
     68     outputd.ciphertext.length = outlen;
     69     outputd.ciphertext.data = outptr;
     70 
     71     return(krb5_c_encrypt(context, eblock->key, 0, ivec?&ivecd:0,
     72 			  &inputd, &outputd));
     73 }
     74 
     75 krb5_error_code KRB5_CALLCONV
     76 krb5_decrypt(krb5_context context, krb5_const_pointer inptr,
     77 	     krb5_pointer outptr, size_t size, krb5_encrypt_block *eblock,
     78 	     krb5_pointer ivec)
     79 {
     80     krb5_enc_data inputd;
     81     krb5_data outputd, ivecd;
     82     size_t blocksize;
     83     krb5_error_code ret;
     84 
     85     if (ivec) {
     86 	if ((ret = krb5_c_block_size(context, eblock->key->enctype, &blocksize)))
     87 	    return(ret);
     88 
     89 	ivecd.length = blocksize;
     90 	ivecd.data = ivec;
     91     }
     92 
     93     /* size is the length of the input ciphertext data */
     94     inputd.enctype = eblock->key->enctype;
     95     inputd.ciphertext.length = size;
     96     /* Solaris Kerberos */
     97     inputd.ciphertext.data = (char*)inptr;
     98 
     99     /* we don't really know how big this is, but the code tends to assume
    100        that the output buffer size should be the same as the input
    101        buffer size */
    102     outputd.length = size;
    103     outputd.data = outptr;
    104 
    105     return(krb5_c_decrypt(context, eblock->key, 0, ivec?&ivecd:0,
    106 			  &inputd, &outputd));
    107 }
    108 
    109 krb5_error_code KRB5_CALLCONV
    110 krb5_process_key(krb5_context context, krb5_encrypt_block *eblock,
    111 		 const krb5_keyblock *key)
    112 {
    113     eblock->key = (krb5_keyblock *) key;
    114 
    115     return(0);
    116 }
    117 
    118 krb5_error_code KRB5_CALLCONV
    119 krb5_finish_key(krb5_context context, krb5_encrypt_block *eblock)
    120 {
    121     return(0);
    122 }
    123 
    124 krb5_error_code KRB5_CALLCONV
    125 krb5_string_to_key(krb5_context context, const krb5_encrypt_block *eblock,
    126 		   krb5_keyblock *keyblock, const krb5_data *data,
    127 		   const krb5_data *salt)
    128 {
    129     return(krb5_c_string_to_key(context, eblock->crypto_entry, data, salt,
    130 				keyblock));
    131 }
    132 
    133 krb5_error_code KRB5_CALLCONV
    134 krb5_init_random_key(krb5_context context, const krb5_encrypt_block *eblock,
    135 		     const krb5_keyblock *keyblock, krb5_pointer *ptr)
    136 {
    137     krb5_data data;
    138 
    139     data.length = keyblock->length;
    140     data.data = (char *) keyblock->contents;
    141 
    142     return(krb5_c_random_seed(context, &data));
    143 }
    144 
    145 krb5_error_code KRB5_CALLCONV
    146 krb5_finish_random_key(krb5_context context, const krb5_encrypt_block *eblock,
    147 		       krb5_pointer *ptr)
    148 {
    149     return(0);
    150 }
    151 
    152 krb5_error_code KRB5_CALLCONV
    153 krb5_random_key(krb5_context context, const krb5_encrypt_block *eblock,
    154 		krb5_pointer ptr, krb5_keyblock **keyblock)
    155 {
    156     krb5_keyblock *key;
    157     krb5_error_code ret;
    158 
    159     if ((key = (krb5_keyblock *) malloc(sizeof(krb5_keyblock))) == NULL)
    160 	return(ENOMEM);
    161 
    162     if ((ret = krb5_c_make_random_key(context, eblock->crypto_entry, key)))
    163 	free(key);
    164 
    165     *keyblock = key;
    166 
    167     return(ret);
    168 }
    169 
    170 krb5_enctype KRB5_CALLCONV
    171 krb5_eblock_enctype(krb5_context context, const krb5_encrypt_block *eblock)
    172 {
    173     return(eblock->crypto_entry);
    174 }
    175 
    176 krb5_error_code KRB5_CALLCONV
    177 krb5_use_enctype(krb5_context context, krb5_encrypt_block *eblock,
    178 		 krb5_enctype enctype)
    179 {
    180     eblock->crypto_entry = enctype;
    181 
    182     return(0);
    183 }
    184 
    185 size_t KRB5_CALLCONV
    186 krb5_encrypt_size(size_t length, krb5_enctype crypto)
    187 {
    188     size_t ret;
    189 
    190     if (krb5_c_encrypt_length(/* XXX */ 0, crypto, length, &ret))
    191 	return(-1); /* XXX */
    192 
    193     return(ret);
    194 }
    195 
    196 size_t KRB5_CALLCONV
    197 krb5_checksum_size(krb5_context context, krb5_cksumtype ctype)
    198 {
    199     size_t ret;
    200 
    201     if (krb5_c_checksum_length(context, ctype, &ret))
    202 	return(-1); /* XXX */
    203 
    204     return(ret);
    205 }
    206 
    207 krb5_error_code KRB5_CALLCONV
    208 krb5_calculate_checksum(krb5_context context, krb5_cksumtype ctype,
    209 			krb5_const_pointer in, size_t in_length,
    210 			krb5_const_pointer seed, size_t seed_length,
    211 			krb5_checksum *outcksum)
    212 {
    213     krb5_data input;
    214     krb5_keyblock key;
    215     krb5_error_code ret;
    216     krb5_checksum cksum;
    217 
    218     /* Solaris Kerberos */
    219     input.data = (char*)in;
    220     input.length = in_length;
    221 
    222     key.length = seed_length;
    223     /* Solaris Kerberos */
    224     key.contents = (unsigned char*)seed;
    225 
    226     if ((ret = krb5_c_make_checksum(context, ctype, &key, 0, &input, &cksum)))
    227 	return(ret);
    228 
    229     if (outcksum->length < cksum.length) {
    230 	memset(cksum.contents, 0, cksum.length);
    231 	free(cksum.contents);
    232 	return(KRB5_BAD_MSIZE);
    233     }
    234 
    235     outcksum->magic = cksum.magic;
    236     outcksum->checksum_type = cksum.checksum_type;
    237     memcpy(outcksum->contents, cksum.contents, cksum.length);
    238     outcksum->length = cksum.length;
    239 
    240     free(cksum.contents);
    241 
    242     return(0);
    243 }
    244 
    245 krb5_error_code KRB5_CALLCONV
    246 krb5_verify_checksum(krb5_context context, krb5_cksumtype ctype,
    247 		     const krb5_checksum *cksum, krb5_const_pointer in,
    248 		     size_t in_length, krb5_const_pointer seed,
    249 		     size_t seed_length)
    250 {
    251     krb5_data input;
    252     krb5_keyblock key;
    253     krb5_error_code ret;
    254     krb5_boolean valid;
    255 
    256     /* Solaris Kerberos */
    257     input.data = (char*)in;
    258     input.length = in_length;
    259 
    260     key.length = seed_length;
    261     /* Solaris Kerberos */
    262     key.contents = (unsigned char*)seed;
    263 
    264     if ((ret = krb5_c_verify_checksum(context, &key, 0, &input, cksum,
    265 				      &valid)))
    266 	return(ret);
    267 
    268     if (!valid)
    269 	return(KRB5KRB_AP_ERR_BAD_INTEGRITY);
    270 
    271     return(0);
    272 }
    273 
    274 krb5_error_code KRB5_CALLCONV
    275 krb5_random_confounder(size_t size, krb5_pointer ptr)
    276 {
    277     krb5_data random_data;
    278 
    279     random_data.length = size;
    280     random_data.data = ptr;
    281 
    282     return(krb5_c_random_make_octets(/* XXX */ 0, &random_data));
    283 }
    284 
    285 krb5_error_code krb5_encrypt_data(krb5_context context, krb5_keyblock *key,
    286 				  krb5_pointer ivec, krb5_data *data,
    287 				  krb5_enc_data *enc_data)
    288 {
    289     krb5_error_code ret;
    290     size_t enclen, blocksize;
    291     krb5_data ivecd;
    292 
    293     if ((ret = krb5_c_encrypt_length(context, key->enctype, data->length,
    294 				     &enclen)))
    295 	return(ret);
    296 
    297     if (ivec) {
    298 	if ((ret = krb5_c_block_size(context, key->enctype, &blocksize)))
    299 	    return(ret);
    300 
    301 	ivecd.length = blocksize;
    302 	ivecd.data = ivec;
    303     }
    304 
    305     enc_data->magic = KV5M_ENC_DATA;
    306     enc_data->kvno = 0;
    307     enc_data->enctype = key->enctype;
    308     enc_data->ciphertext.length = enclen;
    309     if ((enc_data->ciphertext.data = malloc(enclen)) == NULL)
    310 	return(ENOMEM);
    311 
    312     if ((ret = krb5_c_encrypt(context, key, 0, ivec?&ivecd:0, data, enc_data)))
    313 	free(enc_data->ciphertext.data);
    314 
    315     return(ret);
    316 }
    317 
    318 krb5_error_code krb5_decrypt_data(krb5_context context, krb5_keyblock *key,
    319 				  krb5_pointer ivec, krb5_enc_data *enc_data,
    320 				  krb5_data *data)
    321 {
    322     krb5_error_code ret;
    323     krb5_data ivecd;
    324     size_t blocksize;
    325 
    326     if (ivec) {
    327 	if ((ret = krb5_c_block_size(context, key->enctype, &blocksize)))
    328 	    return(ret);
    329 
    330 	ivecd.length = blocksize;
    331 	ivecd.data = ivec;
    332     }
    333 
    334     data->length = enc_data->ciphertext.length;
    335     if ((data->data = (char *) malloc(data->length)) == NULL)
    336 	return(ENOMEM);
    337 
    338     if ((ret = krb5_c_decrypt(context, key, 0, ivec?&ivecd:0, enc_data, data)))
    339 	free(data->data);
    340 
    341     /* Solaris Kerberos */
    342     return(ret);
    343 }
    344