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 /* Solaris Kerberos: 34 * this code is based on the 35 * usr/src/lib/gss_mechs/mech_krb5/crypto/keyhash_provider/k5_md5des.c 36 * file, but has been modified to use the Solaris resident md5.o kernel 37 * module and associated header /usr/include/sys/md5.o. 38 * This means that the MD5* functions are called instead of krb5_MD5*. 39 */ 40 41 #include <des_int.h> 42 #include <krb5.h> 43 #include <keyhash_provider.h> 44 #include <sys/kmem.h> 45 #include <sys/crypto/api.h> 46 47 #define CONFLENGTH 8 48 49 /* Force acceptance of krb5-beta5 md5des checksum for now. */ 50 #define KRB5_MD5DES_BETA5_COMPAT 51 52 /* des-cbc(xorkey, conf | rsa-md5(conf | data)) */ 53 54 /* this could be done in terms of the md5 and des providers, but 55 that's less efficient, and there's no need for this to be generic */ 56 57 /*ARGSUSED*/ 58 static krb5_error_code 59 k5_md5des_hash(krb5_context context, 60 krb5_const krb5_keyblock *key, 61 krb5_keyusage usage, 62 krb5_const krb5_data *ivec, 63 krb5_const krb5_data *input, krb5_data *output) 64 { 65 krb5_error_code ret = 0; 66 krb5_data data; 67 unsigned char conf[CONFLENGTH]; 68 unsigned char xorkey[MIT_DES_KEYSIZE]; 69 int i; 70 krb5_data *hash_input; 71 char *outptr; 72 krb5_keyblock newkey; 73 74 if (key->length != MIT_DES_KEYSIZE) 75 return(KRB5_BAD_KEYSIZE); 76 if (ivec) 77 return(KRB5_CRYPTO_INTERNAL); 78 if (output->length != (CONFLENGTH + MD5_CKSUM_LENGTH)) 79 return(KRB5_CRYPTO_INTERNAL); 80 81 /* create the confounder */ 82 data.length = CONFLENGTH; 83 data.data = (char *) conf; 84 if ((ret = krb5_c_random_make_octets(context, &data))) 85 return(ret); 86 87 /* hash the confounder, then the input data */ 88 hash_input = (krb5_data *)MALLOC(sizeof(krb5_data) * 2); 89 if (hash_input == NULL) 90 return(KRB5_RC_MALLOC); 91 92 hash_input[0].data = (char *)conf; 93 hash_input[0].length = CONFLENGTH; 94 hash_input[1].data = input->data; 95 hash_input[1].length = input->length; 96 97 /* Save the pointer to the beginning of the output buffer */ 98 outptr = (char *)output->data; 99 100 /* 101 * Move the output ptr ahead so we can write the hash 102 * digest directly into the buffer. 103 */ 104 output->data = output->data + CONFLENGTH; 105 106 /* Use generic hash function that calls to kEF */ 107 if (k5_ef_hash(context, 2, hash_input, output)) { 108 FREE(hash_input, sizeof(krb5_data) * 2); 109 return(KRB5_KEF_ERROR); 110 } 111 112 /* restore the original ptr to the output data */ 113 output->data = outptr; 114 115 /* 116 * Put the confounder in the beginning of the buffer to be 117 * encrypted. 118 */ 119 bcopy(conf, output->data, CONFLENGTH); 120 121 bcopy(key->contents, xorkey, sizeof(xorkey)); 122 for (i=0; i<sizeof(xorkey); i++) 123 xorkey[i] ^= 0xf0; 124 125 /* 126 * Solaris Kerberos: 127 * Encryption Framework checks for parity and weak keys. 128 */ 129 bzero(&newkey, sizeof(krb5_keyblock)); 130 newkey.enctype = key->enctype; 131 newkey.contents = xorkey; 132 newkey.length = sizeof(xorkey); 133 newkey.dk_list = NULL; 134 newkey.kef_key.ck_data = NULL; 135 ret = init_key_kef(context->kef_cipher_mt, &newkey); 136 if (ret) { 137 FREE(hash_input, sizeof(krb5_data) * 2); 138 return (ret); 139 } 140 141 /* encrypt it, in place. this has a return value, but it's 142 always zero. */ 143 ret = mit_des_cbc_encrypt(context, (krb5_pointer) output->data, 144 (krb5_pointer) output->data, output->length, 145 &newkey, (unsigned char*) mit_des_zeroblock, 1); 146 147 FREE(hash_input, sizeof(krb5_data) * 2); 148 (void)crypto_destroy_ctx_template(newkey.key_tmpl); 149 return(ret); 150 } 151 152 /*ARGSUSED*/ 153 static krb5_error_code 154 k5_md5des_verify(krb5_context context, 155 krb5_const krb5_keyblock *key, 156 krb5_keyusage usage, 157 krb5_const krb5_data *ivec, 158 krb5_const krb5_data *input, 159 krb5_const krb5_data *hash, 160 krb5_boolean *valid) 161 { 162 krb5_error_code ret = 0; 163 unsigned char plaintext[CONFLENGTH + MD5_CKSUM_LENGTH]; 164 unsigned char xorkey[8]; 165 int i; 166 int compathash = 0; 167 krb5_octet outtmp[MD5_CKSUM_LENGTH]; 168 size_t hisize; 169 krb5_data *hash_input; 170 krb5_data hash_output; 171 krb5_keyblock newkey; 172 173 if (key->length != MIT_DES_KEYSIZE) 174 return(KRB5_BAD_KEYSIZE); 175 if (ivec) 176 return(KRB5_CRYPTO_INTERNAL); 177 if (hash->length != (CONFLENGTH + MD5_CKSUM_LENGTH)) { 178 #ifdef KRB5_MD5DES_BETA5_COMPAT 179 if (hash->length != MD5_CKSUM_LENGTH) 180 return(KRB5_CRYPTO_INTERNAL); 181 else 182 compathash = 1; 183 #else 184 return(KRB5_CRYPTO_INTERNAL); 185 #endif 186 } 187 188 /* create and schedule the encryption key */ 189 (void) bcopy(key->contents, xorkey, sizeof(xorkey)); 190 if (!compathash) { 191 for (i=0; i<sizeof(xorkey); i++) 192 xorkey[i] ^= 0xf0; 193 } 194 195 /* 196 * Solaris Kerberos: 197 * Encryption Framework checks for parity and weak keys 198 */ 199 bzero(&newkey, sizeof(krb5_keyblock)); 200 newkey.enctype = key->enctype; 201 newkey.contents = xorkey; 202 newkey.length = sizeof(xorkey); 203 newkey.dk_list = NULL; 204 newkey.kef_key.ck_data = NULL; 205 ret = init_key_kef(context->kef_cipher_mt, &newkey); 206 207 /* decrypt it. this has a return value, but it's always zero. */ 208 if (!compathash) { 209 ret = mit_des_cbc_encrypt(context, (krb5_pointer) hash->data, 210 (krb5_pointer) plaintext, hash->length, 211 &newkey, (unsigned char*) mit_des_zeroblock, 0); 212 } else { 213 ret = mit_des_cbc_encrypt(context, (krb5_pointer) hash->data, 214 (krb5_pointer) plaintext, hash->length, 215 &newkey, xorkey, 0); 216 } 217 if (ret) goto cleanup; 218 219 /* hash the confounder, then the input data */ 220 i = 1; 221 if (!compathash) 222 i++; 223 224 hisize = sizeof(krb5_data) * i; 225 hash_input = (krb5_data *)MALLOC(hisize); 226 if (hash_input == NULL) 227 return(KRB5_RC_MALLOC); 228 229 i=0; 230 if (!compathash) { 231 hash_input[i].data = (char *)plaintext; 232 hash_input[i].length = CONFLENGTH; 233 i++; 234 } 235 hash_input[i].data = input->data; 236 hash_input[i].length = input->length; 237 238 hash_output.data = (char *)outtmp; 239 hash_output.length = sizeof(outtmp); 240 241 if (k5_ef_hash(context, 1, hash_input, &hash_output)) { 242 ret = KRB5_KEF_ERROR; 243 goto cleanup; 244 } 245 246 /* compare the decrypted hash to the computed one */ 247 if (!compathash) { 248 *valid = !bcmp((const void *)(plaintext+CONFLENGTH), 249 (void *)outtmp, MD5_CKSUM_LENGTH); 250 } else { 251 *valid = !bcmp((const void *)plaintext, 252 (void *)outtmp, MD5_CKSUM_LENGTH); 253 } 254 bzero((void *)plaintext, sizeof(plaintext)); 255 256 cleanup: 257 if (hash_input != NULL && hisize > 0) 258 FREE(hash_input, hisize); 259 (void)crypto_destroy_ctx_template(newkey.key_tmpl); 260 261 return(ret); 262 } 263 264 const struct krb5_keyhash_provider krb5int_keyhash_md5des = { 265 CONFLENGTH+MD5_CKSUM_LENGTH, 266 k5_md5des_hash, 267 k5_md5des_verify 268 }; 269