xref: /illumos-gate/usr/src/uts/common/gssapi/mechs/krb5/crypto/hash_provider/hash_kef_generic.c (revision a4955f4fa65e38d70c07d38e657a9aff43fa155f)
1 /*
2  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 #include <k5-int.h>
7 
8 #include <sys/crypto/api.h>
9 
10 #include <sys/callb.h>
11 #include <sys/uio.h>
12 
13 int
14 k5_ef_hash(krb5_context context, int icount,
15 	const krb5_data *input,
16 	krb5_data *output)
17 {
18 	int i;
19 	int rv = CRYPTO_FAILED;
20 	iovec_t v1, v2;
21 	crypto_data_t d1, d2;
22 	crypto_mechanism_t mech;
23 	crypto_context_t ctxp;
24 
25 	KRB5_LOG0(KRB5_INFO, "k5_ef_hash() start");
26 
27 	bzero(&d1, sizeof (d1));
28 	bzero(&d2, sizeof (d2));
29 
30 	v2.iov_base = (void *)output->data;
31 	v2.iov_len = output->length;
32 
33 	d2.cd_format = CRYPTO_DATA_RAW;
34 	d2.cd_offset = 0;
35 	d2.cd_length = output->length;
36 	d2.cd_raw = v2;
37 
38 	mech.cm_type = context->kef_cksum_mt;
39 	if (mech.cm_type == CRYPTO_MECH_INVALID) {
40 		KRB5_LOG(KRB5_ERR,
41 			"k5_ef_hash() invalid mech specified: 0x%llx",
42 			(long long)context->kef_hash_mt);
43 		return (CRYPTO_FAILED);
44 	}
45 	mech.cm_param = 0;
46 	mech.cm_param_len = 0;
47 
48 	rv = crypto_digest_init(&mech, &ctxp, NULL);
49 	if (rv != CRYPTO_SUCCESS) {
50 		KRB5_LOG(KRB5_ERR, "crypto_digest_init error: %0x", rv);
51 		return (rv);
52 	}
53 
54 	for (i = 0; i < icount; i++) {
55 		v1.iov_base = (void *)input[i].data;
56 		v1.iov_len = input[i].length;
57 		d1.cd_length = input[i].length;
58 		d1.cd_format = CRYPTO_DATA_RAW;
59 		d1.cd_offset = 0;
60 		d1.cd_raw = v1;
61 
62 		rv = crypto_digest_update(ctxp, &d1, NULL);
63 		if (rv != CRYPTO_SUCCESS) {
64 			KRB5_LOG(KRB5_ERR,
65 				"crypto_digest_update error: %0x", rv);
66 			crypto_cancel_ctx(ctxp);
67 			return (rv);
68 		}
69 	}
70 
71 	rv = crypto_digest_final(ctxp, &d2, NULL);
72 	/*
73 	 * crypto_digest_final() internally destroys the context. So, we
74 	 * do not use the context any more. This means we do not call
75 	 * crypto_cancel_ctx() for the failure case here unlike the failure
76 	 * case of crypto_digest_update() where we do.
77 	 */
78 	if (rv != CRYPTO_SUCCESS) {
79 		KRB5_LOG(KRB5_ERR, "crypto_digest_final error: %0x", rv);
80 	}
81 
82 	return (rv);
83 }
84 
85 int
86 k5_ef_mac(krb5_context context,
87 	krb5_keyblock *key,
88 	krb5_data *ivec,
89 	const krb5_data *input,
90 	krb5_data *output)
91 {
92 	int rv;
93 	iovec_t v1, v2;
94 	crypto_data_t d1, d2;
95 	crypto_mechanism_t mech;
96 
97 	KRB5_LOG0(KRB5_INFO, "k5_ef_mac() start");
98 
99 	ASSERT(input != NULL);
100 	ASSERT(ivec != NULL);
101 	ASSERT(output != NULL);
102 
103 	v2.iov_base = (void *)output->data;
104 	v2.iov_len = output->length;
105 
106 	bzero(&d1, sizeof (d1));
107 	bzero(&d2, sizeof (d2));
108 
109 	d2.cd_format = CRYPTO_DATA_RAW;
110 	d2.cd_offset = 0;
111 	d2.cd_length = output->length;
112 	d2.cd_raw = v2;
113 
114 	mech.cm_type = context->kef_hash_mt;
115 	if (mech.cm_type == CRYPTO_MECH_INVALID) {
116 		KRB5_LOG(KRB5_ERR,
117 			"k5_ef_mac() invalid mech specified: 0x%llx",
118 			(long long)context->kef_hash_mt);
119 		return (CRYPTO_FAILED);
120 	}
121 
122 	mech.cm_param = ivec->data;
123 	mech.cm_param_len = ivec->length;
124 
125 	v1.iov_base = (void *)input->data;
126 	v1.iov_len = input->length;
127 
128 	d1.cd_format = CRYPTO_DATA_RAW;
129 	d1.cd_offset = 0;
130 	d1.cd_length = input->length;
131 	d1.cd_raw = v1;
132 
133 	rv = crypto_mac(&mech, &d1, &key->kef_key, key->key_tmpl, &d2, NULL);
134 	if (rv != CRYPTO_SUCCESS) {
135 		KRB5_LOG(KRB5_ERR,
136 			"k5_ef_mac(): crypto_mac error: %0x", rv);
137 	}
138 
139 	return (rv);
140 }
141