1 /* 2 * Copyright 2005 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 41 krb5_error_code KRB5_CALLCONV 42 krb5_c_make_checksum(krb5_context context, krb5_cksumtype cksumtype, 43 const krb5_keyblock *key, krb5_keyusage usage, 44 const krb5_data *input, krb5_checksum *cksum) 45 { 46 int i, e1, e2; 47 krb5_data data; 48 krb5_error_code ret = 0; 49 size_t cksumlen; 50 51 KRB5_LOG0(KRB5_INFO, "krb5_c_make_checksum() start."); 52 53 for (i=0; i<krb5_cksumtypes_length; i++) { 54 if (krb5_cksumtypes_list[i].ctype == cksumtype) 55 break; 56 } 57 58 if (i == krb5_cksumtypes_length) 59 return(KRB5_BAD_ENCTYPE); 60 61 if (krb5_cksumtypes_list[i].keyhash) 62 cksumlen = krb5_cksumtypes_list[i].keyhash->hashsize; 63 else 64 cksumlen = krb5_cksumtypes_list[i].hash->hashsize; 65 66 #ifdef _KERNEL 67 context->kef_cksum_mt = krb5_cksumtypes_list[i].kef_cksum_mt; 68 #endif 69 cksum->length = cksumlen; 70 71 if ((cksum->contents = (krb5_octet *) MALLOC(cksum->length)) == NULL) 72 return(ENOMEM); 73 74 data.length = cksum->length; 75 data.data = (char *) cksum->contents; 76 77 if (krb5_cksumtypes_list[i].keyhash) { 78 79 /* check if key is compatible */ 80 if (krb5_cksumtypes_list[i].keyed_etype) { 81 for (e1=0; e1<krb5_enctypes_length; e1++) 82 if (krb5_enctypes_list[e1].etype == 83 krb5_cksumtypes_list[i].keyed_etype) 84 break; 85 86 for (e2=0; e2<krb5_enctypes_length; e2++) 87 if (krb5_enctypes_list[e2].etype == key->enctype) 88 break; 89 90 if ((e1 == krb5_enctypes_length) || 91 (e2 == krb5_enctypes_length) || 92 (krb5_enctypes_list[e1].enc != krb5_enctypes_list[e2].enc)) { 93 ret = KRB5_BAD_ENCTYPE; 94 goto cleanup; 95 } 96 } 97 #ifdef _KERNEL 98 context->kef_cipher_mt = krb5_enctypes_list[e1].kef_cipher_mt; 99 context->kef_hash_mt = krb5_enctypes_list[e1].kef_hash_mt; 100 if (key->kef_key.ck_data == NULL) { 101 if ((ret = init_key_kef(context->kef_cipher_mt, 102 (krb5_keyblock *)key))) 103 goto cleanup; 104 } 105 #else 106 if ((ret = init_key_uef(krb_ctx_hSession(context), (krb5_keyblock *)key))) 107 return (ret); 108 #endif /* _KERNEL */ 109 110 ret = (*(krb5_cksumtypes_list[i].keyhash->hash))(context, key, 111 usage, 0, input, &data); 112 } else if (krb5_cksumtypes_list[i].flags & KRB5_CKSUMFLAG_DERIVE) { 113 #ifdef _KERNEL 114 context->kef_cipher_mt = get_cipher_mech_type(context, 115 (krb5_keyblock *)key); 116 context->kef_hash_mt = get_hash_mech_type(context, 117 (krb5_keyblock *)key); 118 /* 119 * If the hash_mt is invalid, try using the cksum_mt 120 * because "hash" and "checksum" are overloaded terms 121 * in some places. 122 */ 123 if (context->kef_hash_mt == CRYPTO_MECH_INVALID) 124 context->kef_hash_mt = context->kef_cksum_mt; 125 #else 126 ret = init_key_uef(krb_ctx_hSession(context), (krb5_keyblock *)key); 127 if (ret) 128 return (ret); 129 #endif /* _KERNEL */ 130 ret = krb5_dk_make_checksum(context, 131 krb5_cksumtypes_list[i].hash, 132 key, usage, input, &data); 133 } else { 134 /* 135 * No key is used, hash and cksum are synonymous 136 * in this case 137 */ 138 #ifdef _KERNEL 139 context->kef_hash_mt = context->kef_cksum_mt; 140 #endif /* _KERNEL */ 141 ret = (*(krb5_cksumtypes_list[i].hash->hash))(context, 1, 142 input, &data); 143 } 144 145 if (!ret) { 146 cksum->magic = KV5M_CHECKSUM; 147 cksum->checksum_type = cksumtype; 148 if (krb5_cksumtypes_list[i].trunc_size) { 149 krb5_octet *trunc; 150 size_t old_len = cksum->length; 151 152 /* 153 * Solaris Kerberos: 154 * The Kernel does not like 'realloc' (which is what 155 * MIT code does here), so we do our own "realloc". 156 */ 157 cksum->length = krb5_cksumtypes_list[i].trunc_size; 158 trunc = (krb5_octet *) MALLOC(cksum->length); 159 if (trunc) { 160 (void) memcpy(trunc, cksum->contents, cksum->length); 161 FREE(cksum->contents, old_len); 162 cksum->contents = trunc; 163 } else { 164 ret = ENOMEM; 165 } 166 } 167 } 168 169 cleanup: 170 if (ret) { 171 (void) memset(cksum->contents, 0, cksum->length); 172 FREE(cksum->contents, cksum->length); 173 cksum->length = 0; 174 cksum->contents = NULL; 175 } 176 177 KRB5_LOG(KRB5_INFO, "krb5_c_make_checksum() end ret = %d\n", ret); 178 return(ret); 179 } 180