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
k5_ef_hash(krb5_context context,CK_MECHANISM * mechanism,unsigned int icount,krb5_const krb5_data * input,krb5_data * output)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
k5_ef_mac(krb5_context context,krb5_keyblock * key,krb5_data * ivec,krb5_const krb5_data * input,krb5_data * output)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