/* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #include #include krb5_error_code k5_ef_hash(krb5_context context, CK_MECHANISM *mechanism, unsigned int icount, krb5_const krb5_data *input, krb5_data *output) { CK_RV rv; int i; CK_ULONG outlen = output->length; if ((rv = C_DigestInit(krb_ctx_hSession(context), mechanism)) != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_DigestInit failed in k5_ef_hash: " "rv = 0x%x.", rv); return (PKCS_ERR); } for (i = 0; i < icount; i++) { if ((rv = C_DigestUpdate(krb_ctx_hSession(context), (CK_BYTE_PTR)input[i].data, (CK_ULONG)input[i].length)) != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_DigestUpdate failed in k5_ef_hash: " "rv = 0x%x", rv); return (PKCS_ERR); } } if ((rv = C_DigestFinal(krb_ctx_hSession(context), (CK_BYTE_PTR)output->data, &outlen)) != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_DigestFinal failed in k5_ef_hash: " "rv = 0x%x", rv); return (PKCS_ERR); } /* Narrowing conversion OK because hashes are much smaller than 2^32 */ output->length = outlen; KRB5_LOG0(KRB5_INFO, "k5_ef_hash() end"); return (0); } /* * Ideally, this would use the PKCS#11 interface * for doing DES_CBC_MAC_* operations, but for now we * can fake it by using the des-cbc crypto operation. * and truncating the output. */ krb5_error_code k5_ef_mac(krb5_context context, krb5_keyblock *key, krb5_data *ivec, krb5_const krb5_data *input, krb5_data *output) { krb5_error_code retval = 0; char *outbuf = NULL; char *inbuf = NULL; int inlen; int outlen; /* * This is ugly but necessary until proper PKCS#11 * interface is ready. */ inlen = K5ROUNDUP(input->length, 8); outlen = inlen; if (inlen != input->length) { inbuf = (char *)malloc(inlen); if (inbuf == NULL) retval = ENOMEM; } else inbuf = input->data; outbuf = (char *)malloc(outlen); if (outbuf == NULL) retval = ENOMEM; (void) memset(outbuf, 0, outlen); if (outbuf != NULL && inbuf != NULL) { if (inlen != input->length) { (void) memset(inbuf, 0, inlen); (void) memcpy(inbuf, input->data, input->length); } retval = mit_des_cbc_encrypt(context, (const mit_des_cblock *)inbuf, (mit_des_cblock *)outbuf, inlen, key, (unsigned char *)ivec->data, 1); if (retval == 0) { (void) memcpy(output->data, &outbuf[outlen-8], 8); output->length = 8; } } if (inlen != input->length && inbuf != NULL) free(inbuf); if (outbuf != NULL) free(outbuf); return (retval); }