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