1 /* 2 * Copyright 2004 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 * Copyright (C) 1998 by the FundsXpress, INC. 10 * 11 * All rights reserved. 12 * 13 * Export of this software from the United States of America may require 14 * a specific license from the United States Government. It is the 15 * responsibility of any person or organization contemplating export to 16 * obtain such a license before exporting. 17 * 18 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 19 * distribute this software and its documentation for any purpose and 20 * without fee is hereby granted, provided that the above copyright 21 * notice appear in all copies and that both that copyright notice and 22 * this permission notice appear in supporting documentation, and that 23 * the name of FundsXpress. not be used in advertising or publicity pertaining 24 * to distribution of the software without specific, written prior 25 * permission. FundsXpress makes no representations about the suitability of 26 * this software for any purpose. It is provided "as is" without express 27 * or implied warranty. 28 * 29 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 30 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 31 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 32 */ 33 34 #include <k5-int.h> 35 #include <cksumtypes.h> 36 #include <etypes.h> 37 38 #include <dk.h> 39 40 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV 41 krb5_c_make_checksum(context, cksumtype, key, usage, input, cksum) 42 krb5_context context; 43 krb5_cksumtype cksumtype; 44 krb5_const krb5_keyblock *key; 45 krb5_keyusage usage; 46 krb5_const krb5_data *input; 47 krb5_checksum *cksum; 48 { 49 int i, e1, e2; 50 krb5_data data; 51 krb5_error_code ret = 0; 52 size_t cksumlen; 53 54 KRB5_LOG0(KRB5_INFO, "krb5_c_make_checksum() start."); 55 56 for (i=0; i<krb5_cksumtypes_length; i++) { 57 if (krb5_cksumtypes_list[i].ctype == cksumtype) 58 break; 59 } 60 61 if (i == krb5_cksumtypes_length) 62 return(KRB5_BAD_ENCTYPE); 63 64 if (krb5_cksumtypes_list[i].keyhash) 65 (*(krb5_cksumtypes_list[i].keyhash->hash_size))(&cksumlen); 66 else 67 (*(krb5_cksumtypes_list[i].hash->hash_size))(&cksumlen); 68 69 #ifdef _KERNEL 70 context->kef_cksum_mt = krb5_cksumtypes_list[i].kef_cksum_mt; 71 #endif 72 cksum->length = cksumlen; 73 74 if ((cksum->contents = (krb5_octet *) MALLOC(cksum->length)) == NULL) 75 return(ENOMEM); 76 77 data.length = cksum->length; 78 data.data = (char *) cksum->contents; 79 80 if (krb5_cksumtypes_list[i].keyhash) { 81 82 /* check if key is compatible */ 83 if (krb5_cksumtypes_list[i].keyed_etype) { 84 for (e1=0; e1<krb5_enctypes_length; e1++) 85 if (krb5_enctypes_list[e1].etype == 86 krb5_cksumtypes_list[i].keyed_etype) 87 break; 88 89 for (e2=0; e2<krb5_enctypes_length; e2++) 90 if (krb5_enctypes_list[e2].etype == key->enctype) 91 break; 92 93 if ((e1 == krb5_enctypes_length) || 94 (e2 == krb5_enctypes_length) || 95 (krb5_enctypes_list[e1].enc != krb5_enctypes_list[e2].enc)) { 96 ret = KRB5_BAD_ENCTYPE; 97 goto cleanup; 98 } 99 } 100 #ifdef _KERNEL 101 context->kef_cipher_mt = krb5_enctypes_list[e1].kef_cipher_mt; 102 context->kef_hash_mt = krb5_enctypes_list[e1].kef_hash_mt; 103 if (key->kef_key.ck_data == NULL) { 104 if ((ret = init_key_kef(context->kef_cipher_mt, 105 (krb5_keyblock *)key))) 106 goto cleanup; 107 } 108 #else 109 if ((ret = init_key_uef(krb_ctx_hSession(context), (krb5_keyblock *)key))) 110 return (ret); 111 #endif /* _KERNEL */ 112 113 ret = (*(krb5_cksumtypes_list[i].keyhash->hash))(context, key, 114 usage, 0, input, &data); 115 } else if (krb5_cksumtypes_list[i].flags & KRB5_CKSUMFLAG_DERIVE) { 116 #ifdef _KERNEL 117 context->kef_cipher_mt = get_cipher_mech_type(context, 118 (krb5_keyblock *)key); 119 context->kef_hash_mt = get_hash_mech_type(context, 120 (krb5_keyblock *)key); 121 /* 122 * If the hash_mt is invalid, try using the cksum_mt 123 * because "hash" and "checksum" are overloaded terms 124 * in some places. 125 */ 126 if (context->kef_hash_mt == CRYPTO_MECH_INVALID) 127 context->kef_hash_mt = context->kef_cksum_mt; 128 #else 129 ret = init_key_uef(krb_ctx_hSession(context), (krb5_keyblock *)key); 130 if (ret) 131 return (ret); 132 #endif /* _KERNEL */ 133 ret = krb5_dk_make_checksum(context, 134 krb5_cksumtypes_list[i].hash, 135 key, usage, input, &data); 136 } else { 137 /* 138 * No key is used, hash and cksum are synonymous 139 * in this case 140 */ 141 #ifdef _KERNEL 142 context->kef_hash_mt = context->kef_cksum_mt; 143 #endif /* _KERNEL */ 144 ret = (*(krb5_cksumtypes_list[i].hash->hash))(context, 1, 145 input, &data); 146 } 147 148 if (!ret) { 149 cksum->magic = KV5M_CHECKSUM; 150 cksum->checksum_type = cksumtype; 151 if (krb5_cksumtypes_list[i].trunc_size) { 152 krb5_octet *trunc; 153 size_t old_len = cksum->length; 154 155 /* 156 * Solaris Kerberos: 157 * The Kernel does not like 'realloc' (which is what 158 * MIT code does here), so we do our own "realloc". 159 */ 160 cksum->length = krb5_cksumtypes_list[i].trunc_size; 161 trunc = (krb5_octet *) MALLOC(cksum->length); 162 if (trunc) { 163 (void) memcpy(trunc, cksum->contents, cksum->length); 164 FREE(cksum->contents, old_len); 165 cksum->contents = trunc; 166 } else { 167 ret = ENOMEM; 168 } 169 } 170 } 171 172 cleanup: 173 if (ret) { 174 (void) memset(cksum->contents, 0, cksum->length); 175 FREE(cksum->contents, cksum->length); 176 cksum->length = 0; 177 cksum->contents = 0; 178 } 179 180 KRB5_LOG(KRB5_INFO, "krb5_c_make_checksum() end ret = %d\n", ret); 181 return(ret); 182 } 183