1 /* 2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * Copyright (C) 1998 by the FundsXpress, INC. 8 * 9 * All rights reserved. 10 * 11 * Export of this software from the United States of America may require 12 * a specific license from the United States Government. It is the 13 * responsibility of any person or organization contemplating export to 14 * obtain such a license before exporting. 15 * 16 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 17 * distribute this software and its documentation for any purpose and 18 * without fee is hereby granted, provided that the above copyright 19 * notice appear in all copies and that both that copyright notice and 20 * this permission notice appear in supporting documentation, and that 21 * the name of FundsXpress. not be used in advertising or publicity pertaining 22 * to distribution of the software without specific, written prior 23 * permission. FundsXpress makes no representations about the suitability of 24 * this software for any purpose. It is provided "as is" without express 25 * or implied warranty. 26 * 27 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 28 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 29 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 30 */ 31 32 #include "k5-int.h" 33 #include "etypes.h" 34 #include "dk.h" 35 36 #define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */ 37 38 /* 39 * Derive the key for checksum calculation. 40 * This is only called (currently) for SHA1-DES3 41 * checksum types. 42 * 43 * The primary benefit here is that a KEF template 44 * is created for use when doing the HMAC operation which 45 * saves ALOT of computation cycles and improves performance. 46 */ 47 static krb5_error_code 48 derive_cksum_key(krb5_context context, 49 struct krb5_enc_provider *enc, 50 const krb5_keyblock *key, 51 krb5_keyusage usage, 52 krb5_keyblock **outkey) 53 { 54 krb5_error_code ret = 0; 55 krb5_keyblock *cached_key = NULL; 56 krb5_data d1; 57 unsigned char constantdata[K5CLENGTH]; 58 59 cached_key = find_derived_key(usage, DK_CKSUM_KEY_BYTE, 60 (krb5_keyblock *)key); 61 if (cached_key) 62 *outkey = cached_key; 63 else { 64 *outkey = krb5_create_derived_keyblock(key->length); 65 if (*outkey == NULL) 66 return (ENOMEM); 67 68 constantdata[0] = (usage>>24)&0xff; 69 constantdata[1] = (usage>>16)&0xff; 70 constantdata[2] = (usage>>8)&0xff; 71 constantdata[3] = usage&0xff; 72 constantdata[4] = DK_CKSUM_KEY_BYTE; 73 74 d1.data = (char *)constantdata; 75 d1.length = sizeof(constantdata); 76 77 ret = krb5_derive_key(context, enc, key, 78 *outkey, &d1); 79 if (ret) { 80 krb5_free_keyblock(context, *outkey); 81 *outkey = NULL; 82 return (ret); 83 } 84 #ifdef _KERNEL 85 /* 86 * By default, derived keys get the "mech_type" 87 * that was associated with their parent. 88 * we need to switch the mech_type to correspond 89 * to the checksum mech type. 90 */ 91 if (ret == 0 && 92 (*outkey)->kef_mt != context->kef_cksum_mt) { 93 (*outkey)->kef_mt = context->kef_cksum_mt; 94 if ((*outkey)->key_tmpl != NULL) { 95 crypto_destroy_ctx_template((*outkey)->key_tmpl); 96 (*outkey)->key_tmpl = NULL; 97 } 98 ret = update_key_template(*outkey); 99 } 100 #endif /* _KERNEL */ 101 if (ret == 0) 102 ret = add_derived_key((krb5_keyblock *)key, usage, 103 DK_CKSUM_KEY_BYTE, 104 *outkey); 105 } 106 finish: 107 KRB5_LOG0(KRB5_INFO, "derive_cksum_key() end."); 108 return (ret); 109 } 110 111 /* ARGSUSED */ 112 krb5_error_code 113 krb5_dk_make_checksum(context, hash, key, usage, input, output) 114 krb5_context context; 115 krb5_const struct krb5_hash_provider *hash; 116 krb5_const krb5_keyblock *key; 117 krb5_keyusage usage; 118 krb5_const krb5_data *input; 119 krb5_data *output; 120 { 121 int i; 122 krb5_error_code ret; 123 krb5_keyblock *cksum_key = NULL; 124 struct krb5_enc_provider *enc = NULL; 125 126 KRB5_LOG0(KRB5_INFO, "krb5_dk_make_checksum() start"); 127 128 for (i=0; i<krb5_enctypes_length; i++) { 129 if (krb5_enctypes_list[i].etype == key->enctype) 130 break; 131 } 132 133 if (i == krb5_enctypes_length) { 134 KRB5_LOG(KRB5_ERR, "krb5_ck_make_checksum bad enctype: %d", 135 key->enctype); 136 return(KRB5_BAD_ENCTYPE); 137 } 138 enc = (struct krb5_enc_provider *)krb5_enctypes_list[i].enc; 139 140 #ifdef _KERNEL 141 if (key->kef_key.ck_data == NULL && 142 (ret = init_key_kef(krb5_enctypes_list[i].kef_cipher_mt, 143 (krb5_keyblock *)key))) 144 goto cleanup; 145 #endif 146 ret = derive_cksum_key(context, enc, key, usage, &cksum_key); 147 if (ret != 0) 148 goto cleanup; 149 150 #ifdef _KERNEL 151 if ((ret = krb5_hmac(context, (krb5_keyblock *)cksum_key, 152 input, output))) { 153 KRB5_LOG(KRB5_ERR, "krb5_hmac error: %0x", ret); 154 (void) memset(output->data, 0, output->length); 155 } 156 #else 157 if ((ret = krb5_hmac(context, hash, cksum_key, 1, input, output)) != 0) { 158 KRB5_LOG(KRB5_ERR, "krb5_hmac error: %0x", ret); 159 (void) memset(output->data, 0, output->length); 160 } 161 #endif /* _KERNEL */ 162 cleanup: 163 164 KRB5_LOG0(KRB5_INFO, "krb5_dk_make_checksum() end"); 165 return(ret); 166 } 167 168