1 /* 2 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 #include <k5-int.h> 7 #include <des_int.h> 8 9 krb5_error_code 10 k5_ef_hash(krb5_context context, 11 CK_MECHANISM *mechanism, 12 unsigned int icount, 13 krb5_const krb5_data *input, 14 krb5_data *output) 15 { 16 CK_RV rv; 17 int i; 18 CK_ULONG outlen = output->length; 19 20 if ((rv = C_DigestInit(krb_ctx_hSession(context), mechanism)) != 21 CKR_OK) { 22 KRB5_LOG(KRB5_ERR, "C_DigestInit failed in k5_ef_hash: " 23 "rv = 0x%x.", rv); 24 return (PKCS_ERR); 25 } 26 27 for (i = 0; i < icount; i++) { 28 if ((rv = C_DigestUpdate(krb_ctx_hSession(context), 29 (CK_BYTE_PTR)input[i].data, 30 (CK_ULONG)input[i].length)) != CKR_OK) { 31 KRB5_LOG(KRB5_ERR, "C_DigestUpdate failed in k5_ef_hash: " 32 "rv = 0x%x", rv); 33 return (PKCS_ERR); 34 } 35 } 36 37 if ((rv = C_DigestFinal(krb_ctx_hSession(context), 38 (CK_BYTE_PTR)output->data, &outlen)) != CKR_OK) { 39 KRB5_LOG(KRB5_ERR, "C_DigestFinal failed in k5_ef_hash: " 40 "rv = 0x%x", rv); 41 return (PKCS_ERR); 42 } 43 44 /* Narrowing conversion OK because hashes are much smaller than 2^32 */ 45 output->length = outlen; 46 47 KRB5_LOG0(KRB5_INFO, "k5_ef_hash() end"); 48 return (0); 49 } 50 51 52 /* 53 * Ideally, this would use the PKCS#11 interface 54 * for doing DES_CBC_MAC_* operations, but for now we 55 * can fake it by using the des-cbc crypto operation. 56 * and truncating the output. 57 */ 58 krb5_error_code 59 k5_ef_mac(krb5_context context, 60 krb5_keyblock *key, 61 krb5_data *ivec, 62 krb5_const krb5_data *input, 63 krb5_data *output) 64 { 65 krb5_error_code retval = 0; 66 char *outbuf = NULL; 67 char *inbuf = NULL; 68 int inlen; 69 int outlen; 70 71 /* 72 * This is ugly but necessary until proper PKCS#11 73 * interface is ready. 74 */ 75 inlen = K5ROUNDUP(input->length, 8); 76 outlen = inlen; 77 78 if (inlen != input->length) { 79 inbuf = (char *)malloc(inlen); 80 if (inbuf == NULL) 81 retval = ENOMEM; 82 } 83 else 84 inbuf = input->data; 85 86 outbuf = (char *)malloc(outlen); 87 if (outbuf == NULL) 88 retval = ENOMEM; 89 (void) memset(outbuf, 0, outlen); 90 if (outbuf != NULL && inbuf != NULL) { 91 if (inlen != input->length) { 92 (void) memset(inbuf, 0, inlen); 93 (void) memcpy(inbuf, input->data, input->length); 94 } 95 retval = mit_des_cbc_encrypt(context, 96 (const mit_des_cblock *)inbuf, 97 (mit_des_cblock *)outbuf, 98 inlen, key, 99 (unsigned char *)ivec->data, 1); 100 101 if (retval == 0) { 102 (void) memcpy(output->data, &outbuf[outlen-8], 8); 103 output->length = 8; 104 } 105 } 106 if (inlen != input->length && inbuf != NULL) 107 free(inbuf); 108 if (outbuf != NULL) 109 free(outbuf); 110 return (retval); 111 } 112