Line data Source code
1 : /*
2 : * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
3 : * (Royal Institute of Technology, Stockholm, Sweden).
4 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions
8 : * are met:
9 : *
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : *
13 : * 2. Redistributions in binary form must reproduce the above copyright
14 : * notice, this list of conditions and the following disclaimer in the
15 : * documentation and/or other materials provided with the distribution.
16 : *
17 : * 3. Neither the name of the Institute nor the names of its contributors
18 : * may be used to endorse or promote products derived from this software
19 : * without specific prior written permission.
20 : *
21 : * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 : * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 : * SUCH DAMAGE.
32 : */
33 :
34 : #include "krb5_locl.h"
35 :
36 : #include <pkinit_asn1.h>
37 :
38 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
39 37 : _krb5_pk_octetstring2key(krb5_context context,
40 : krb5_enctype type,
41 : const void *dhdata,
42 : size_t dhsize,
43 : const heim_octet_string *c_n,
44 : const heim_octet_string *k_n,
45 : krb5_keyblock *key)
46 : {
47 37 : struct _krb5_encryption_type *et = _krb5_find_enctype(type);
48 0 : krb5_error_code ret;
49 0 : size_t keylen, offset;
50 0 : void *keydata;
51 0 : unsigned char counter;
52 0 : unsigned char shaoutput[SHA_DIGEST_LENGTH];
53 0 : EVP_MD_CTX *m;
54 :
55 37 : if(et == NULL) {
56 0 : krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
57 0 : N_("encryption type %d not supported", ""),
58 : type);
59 0 : return KRB5_PROG_ETYPE_NOSUPP;
60 : }
61 37 : keylen = (et->keytype->bits + 7) / 8;
62 :
63 37 : keydata = malloc(keylen);
64 37 : if (keydata == NULL)
65 0 : return krb5_enomem(context);
66 :
67 37 : m = EVP_MD_CTX_create();
68 37 : if (m == NULL) {
69 0 : free(keydata);
70 0 : return krb5_enomem(context);
71 : }
72 :
73 37 : counter = 0;
74 37 : offset = 0;
75 0 : do {
76 :
77 74 : EVP_DigestInit_ex(m, EVP_sha1(), NULL);
78 74 : EVP_DigestUpdate(m, &counter, 1);
79 74 : EVP_DigestUpdate(m, dhdata, dhsize);
80 :
81 74 : if (c_n)
82 0 : EVP_DigestUpdate(m, c_n->data, c_n->length);
83 74 : if (k_n)
84 0 : EVP_DigestUpdate(m, k_n->data, k_n->length);
85 :
86 74 : EVP_DigestFinal_ex(m, shaoutput, NULL);
87 :
88 74 : memcpy((unsigned char *)keydata + offset,
89 : shaoutput,
90 74 : min(keylen - offset, sizeof(shaoutput)));
91 :
92 74 : offset += sizeof(shaoutput);
93 74 : counter++;
94 74 : } while(offset < keylen);
95 37 : memset_s(shaoutput, sizeof(shaoutput), 0, sizeof(shaoutput));
96 :
97 37 : EVP_MD_CTX_destroy(m);
98 :
99 37 : ret = krb5_random_to_key(context, type, keydata, keylen, key);
100 37 : memset_s(keydata, sizeof(keylen), 0, sizeof(keylen));
101 37 : free(keydata);
102 37 : return ret;
103 : }
104 :
105 : static krb5_error_code
106 0 : encode_uvinfo(krb5_context context, krb5_const_principal p, krb5_data *data)
107 : {
108 0 : KRB5PrincipalName pn;
109 0 : krb5_error_code ret;
110 0 : size_t size = 0;
111 :
112 0 : pn.principalName = p->name;
113 0 : pn.realm = p->realm;
114 :
115 0 : ASN1_MALLOC_ENCODE(KRB5PrincipalName, data->data, data->length,
116 : &pn, &size, ret);
117 0 : if (ret) {
118 0 : krb5_data_zero(data);
119 0 : krb5_set_error_message(context, ret,
120 0 : N_("Failed to encode KRB5PrincipalName", ""));
121 0 : return ret;
122 : }
123 0 : if (data->length != size)
124 0 : krb5_abortx(context, "asn1 compiler internal error");
125 0 : return 0;
126 : }
127 :
128 : static krb5_error_code
129 0 : encode_otherinfo(krb5_context context,
130 : const AlgorithmIdentifier *ai,
131 : krb5_const_principal client,
132 : krb5_const_principal server,
133 : krb5_enctype enctype,
134 : const krb5_data *as_req,
135 : const krb5_data *pk_as_rep,
136 : const Ticket *ticket,
137 : krb5_data *other)
138 : {
139 0 : PkinitSP80056AOtherInfo otherinfo;
140 0 : PkinitSuppPubInfo pubinfo;
141 0 : krb5_error_code ret;
142 0 : krb5_data pub;
143 0 : size_t size = 0;
144 :
145 0 : krb5_data_zero(other);
146 0 : memset(&otherinfo, 0, sizeof(otherinfo));
147 0 : memset(&pubinfo, 0, sizeof(pubinfo));
148 :
149 0 : pubinfo.enctype = enctype;
150 0 : pubinfo.as_REQ = *as_req;
151 0 : pubinfo.pk_as_rep = *pk_as_rep;
152 0 : pubinfo.ticket = *ticket;
153 0 : ASN1_MALLOC_ENCODE(PkinitSuppPubInfo, pub.data, pub.length,
154 : &pubinfo, &size, ret);
155 0 : if (ret) {
156 0 : krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
157 0 : return ret;
158 : }
159 0 : if (pub.length != size)
160 0 : krb5_abortx(context, "asn1 compiler internal error");
161 :
162 0 : ret = encode_uvinfo(context, client, &otherinfo.partyUInfo);
163 0 : if (ret) {
164 0 : free(pub.data);
165 0 : return ret;
166 : }
167 0 : ret = encode_uvinfo(context, server, &otherinfo.partyVInfo);
168 0 : if (ret) {
169 0 : free(otherinfo.partyUInfo.data);
170 0 : free(pub.data);
171 0 : return ret;
172 : }
173 :
174 0 : otherinfo.algorithmID = *ai;
175 0 : otherinfo.suppPubInfo = &pub;
176 :
177 0 : ASN1_MALLOC_ENCODE(PkinitSP80056AOtherInfo, other->data, other->length,
178 : &otherinfo, &size, ret);
179 0 : free(otherinfo.partyUInfo.data);
180 0 : free(otherinfo.partyVInfo.data);
181 0 : free(pub.data);
182 0 : if (ret) {
183 0 : krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
184 0 : return ret;
185 : }
186 0 : if (other->length != size)
187 0 : krb5_abortx(context, "asn1 compiler internal error");
188 :
189 0 : return 0;
190 : }
191 :
192 :
193 :
194 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
195 0 : _krb5_pk_kdf(krb5_context context,
196 : const struct AlgorithmIdentifier *ai,
197 : const void *dhdata,
198 : size_t dhsize,
199 : krb5_const_principal client,
200 : krb5_const_principal server,
201 : krb5_enctype enctype,
202 : const krb5_data *as_req,
203 : const krb5_data *pk_as_rep,
204 : const Ticket *ticket,
205 : krb5_keyblock *key)
206 : {
207 0 : struct _krb5_encryption_type *et;
208 0 : krb5_error_code ret;
209 0 : krb5_data other;
210 0 : size_t keylen, offset;
211 0 : uint32_t counter;
212 0 : unsigned char *keydata;
213 0 : unsigned char shaoutput[SHA512_DIGEST_LENGTH];
214 0 : const EVP_MD *md;
215 0 : EVP_MD_CTX *m;
216 :
217 0 : if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha1, &ai->algorithm) == 0) {
218 0 : md = EVP_sha1();
219 0 : } else if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha256, &ai->algorithm) == 0) {
220 0 : md = EVP_sha256();
221 0 : } else if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha512, &ai->algorithm) == 0) {
222 0 : md = EVP_sha512();
223 : } else {
224 0 : krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
225 0 : N_("KDF not supported", ""));
226 0 : return KRB5_PROG_ETYPE_NOSUPP;
227 : }
228 0 : if (ai->parameters != NULL &&
229 0 : (ai->parameters->length != 2 ||
230 0 : memcmp(ai->parameters->data, "\x05\x00", 2) != 0))
231 : {
232 0 : krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
233 0 : N_("kdf params not NULL or the NULL-type",
234 : ""));
235 0 : return KRB5_PROG_ETYPE_NOSUPP;
236 : }
237 :
238 0 : et = _krb5_find_enctype(enctype);
239 0 : if(et == NULL) {
240 0 : krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
241 0 : N_("encryption type %d not supported", ""),
242 : enctype);
243 0 : return KRB5_PROG_ETYPE_NOSUPP;
244 : }
245 0 : keylen = (et->keytype->bits + 7) / 8;
246 :
247 0 : keydata = malloc(keylen);
248 0 : if (keydata == NULL)
249 0 : return krb5_enomem(context);
250 :
251 0 : ret = encode_otherinfo(context, ai, client, server,
252 : enctype, as_req, pk_as_rep, ticket, &other);
253 0 : if (ret) {
254 0 : free(keydata);
255 0 : return ret;
256 : }
257 :
258 0 : m = EVP_MD_CTX_create();
259 0 : if (m == NULL) {
260 0 : free(keydata);
261 0 : free(other.data);
262 0 : return krb5_enomem(context);
263 : }
264 :
265 0 : offset = 0;
266 0 : counter = 1;
267 0 : do {
268 0 : unsigned char cdata[4];
269 :
270 0 : EVP_DigestInit_ex(m, md, NULL);
271 0 : _krb5_put_int(cdata, counter, 4);
272 0 : EVP_DigestUpdate(m, cdata, 4);
273 0 : EVP_DigestUpdate(m, dhdata, dhsize);
274 0 : EVP_DigestUpdate(m, other.data, other.length);
275 :
276 0 : EVP_DigestFinal_ex(m, shaoutput, NULL);
277 :
278 0 : memcpy((unsigned char *)keydata + offset,
279 : shaoutput,
280 0 : min(keylen - offset, EVP_MD_CTX_size(m)));
281 :
282 0 : offset += EVP_MD_CTX_size(m);
283 0 : counter++;
284 0 : } while(offset < keylen);
285 0 : memset_s(shaoutput, sizeof(shaoutput), 0, sizeof(shaoutput));
286 :
287 0 : EVP_MD_CTX_destroy(m);
288 0 : free(other.data);
289 :
290 0 : ret = krb5_random_to_key(context, enctype, keydata, keylen, key);
291 0 : memset_s(keydata, sizeof(keylen), 0, sizeof(keylen));
292 0 : free(keydata);
293 :
294 0 : return ret;
295 : }
|