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_error_code
39 52 : _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 52 : struct _krb5_encryption_type *et = _krb5_find_enctype(type);
48 : krb5_error_code ret;
49 : size_t keylen, offset;
50 : void *keydata;
51 : unsigned char counter;
52 : unsigned char shaoutput[SHA_DIGEST_LENGTH];
53 : EVP_MD_CTX *m;
54 :
55 52 : 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 52 : keylen = (et->keytype->bits + 7) / 8;
62 :
63 52 : keydata = malloc(keylen);
64 52 : if (keydata == NULL) {
65 0 : krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
66 0 : return ENOMEM;
67 : }
68 :
69 52 : m = EVP_MD_CTX_create();
70 52 : if (m == NULL) {
71 0 : free(keydata);
72 0 : krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
73 0 : return ENOMEM;
74 : }
75 :
76 52 : counter = 0;
77 52 : offset = 0;
78 : do {
79 :
80 104 : EVP_DigestInit_ex(m, EVP_sha1(), NULL);
81 104 : EVP_DigestUpdate(m, &counter, 1);
82 104 : EVP_DigestUpdate(m, dhdata, dhsize);
83 :
84 104 : if (c_n)
85 0 : EVP_DigestUpdate(m, c_n->data, c_n->length);
86 104 : if (k_n)
87 0 : EVP_DigestUpdate(m, k_n->data, k_n->length);
88 :
89 104 : EVP_DigestFinal_ex(m, shaoutput, NULL);
90 :
91 104 : memcpy((unsigned char *)keydata + offset,
92 : shaoutput,
93 104 : min(keylen - offset, sizeof(shaoutput)));
94 :
95 104 : offset += sizeof(shaoutput);
96 104 : counter++;
97 104 : } while(offset < keylen);
98 52 : memset(shaoutput, 0, sizeof(shaoutput));
99 :
100 52 : EVP_MD_CTX_destroy(m);
101 :
102 52 : ret = krb5_random_to_key(context, type, keydata, keylen, key);
103 52 : memset(keydata, 0, sizeof(keylen));
104 52 : free(keydata);
105 52 : return ret;
106 : }
107 :
108 : static krb5_error_code
109 0 : encode_uvinfo(krb5_context context, krb5_const_principal p, krb5_data *data)
110 : {
111 : KRB5PrincipalName pn;
112 : krb5_error_code ret;
113 0 : size_t size = 0;
114 :
115 0 : pn.principalName = p->name;
116 0 : pn.realm = p->realm;
117 :
118 0 : ASN1_MALLOC_ENCODE(KRB5PrincipalName, data->data, data->length,
119 : &pn, &size, ret);
120 0 : if (ret) {
121 0 : krb5_data_zero(data);
122 0 : krb5_set_error_message(context, ret,
123 0 : N_("Failed to encode KRB5PrincipalName", ""));
124 0 : return ret;
125 : }
126 0 : if (data->length != size)
127 0 : krb5_abortx(context, "asn1 compiler internal error");
128 0 : return 0;
129 : }
130 :
131 : static krb5_error_code
132 0 : encode_otherinfo(krb5_context context,
133 : const AlgorithmIdentifier *ai,
134 : krb5_const_principal client,
135 : krb5_const_principal server,
136 : krb5_enctype enctype,
137 : const krb5_data *as_req,
138 : const krb5_data *pk_as_rep,
139 : const Ticket *ticket,
140 : krb5_data *other)
141 : {
142 : PkinitSP80056AOtherInfo otherinfo;
143 : PkinitSuppPubInfo pubinfo;
144 : krb5_error_code ret;
145 : krb5_data pub;
146 0 : size_t size = 0;
147 :
148 0 : krb5_data_zero(other);
149 0 : memset(&otherinfo, 0, sizeof(otherinfo));
150 0 : memset(&pubinfo, 0, sizeof(pubinfo));
151 :
152 0 : pubinfo.enctype = enctype;
153 0 : pubinfo.as_REQ = *as_req;
154 0 : pubinfo.pk_as_rep = *pk_as_rep;
155 0 : pubinfo.ticket = *ticket;
156 0 : ASN1_MALLOC_ENCODE(PkinitSuppPubInfo, pub.data, pub.length,
157 : &pubinfo, &size, ret);
158 0 : if (ret) {
159 0 : krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
160 0 : return ret;
161 : }
162 0 : if (pub.length != size)
163 0 : krb5_abortx(context, "asn1 compiler internal error");
164 :
165 0 : ret = encode_uvinfo(context, client, &otherinfo.partyUInfo);
166 0 : if (ret) {
167 0 : free(pub.data);
168 0 : return ret;
169 : }
170 0 : ret = encode_uvinfo(context, server, &otherinfo.partyVInfo);
171 0 : if (ret) {
172 0 : free(otherinfo.partyUInfo.data);
173 0 : free(pub.data);
174 0 : return ret;
175 : }
176 :
177 0 : otherinfo.algorithmID = *ai;
178 0 : otherinfo.suppPubInfo = &pub;
179 :
180 0 : ASN1_MALLOC_ENCODE(PkinitSP80056AOtherInfo, other->data, other->length,
181 : &otherinfo, &size, ret);
182 0 : free(otherinfo.partyUInfo.data);
183 0 : free(otherinfo.partyVInfo.data);
184 0 : free(pub.data);
185 0 : if (ret) {
186 0 : krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
187 0 : return ret;
188 : }
189 0 : if (other->length != size)
190 0 : krb5_abortx(context, "asn1 compiler internal error");
191 :
192 0 : return 0;
193 : }
194 :
195 :
196 :
197 : krb5_error_code
198 0 : _krb5_pk_kdf(krb5_context context,
199 : const struct AlgorithmIdentifier *ai,
200 : const void *dhdata,
201 : size_t dhsize,
202 : krb5_const_principal client,
203 : krb5_const_principal server,
204 : krb5_enctype enctype,
205 : const krb5_data *as_req,
206 : const krb5_data *pk_as_rep,
207 : const Ticket *ticket,
208 : krb5_keyblock *key)
209 : {
210 : struct _krb5_encryption_type *et;
211 : krb5_error_code ret;
212 : krb5_data other;
213 : size_t keylen, offset;
214 : uint32_t counter;
215 : unsigned char *keydata;
216 : unsigned char shaoutput[SHA512_DIGEST_LENGTH];
217 : const EVP_MD *md;
218 : EVP_MD_CTX *m;
219 :
220 0 : if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha1, &ai->algorithm) == 0) {
221 0 : md = EVP_sha1();
222 0 : } else if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha256, &ai->algorithm) == 0) {
223 0 : md = EVP_sha256();
224 0 : } else if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha512, &ai->algorithm) == 0) {
225 0 : md = EVP_sha512();
226 : } else {
227 0 : krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
228 0 : N_("KDF not supported", ""));
229 0 : return KRB5_PROG_ETYPE_NOSUPP;
230 : }
231 0 : if (ai->parameters != NULL &&
232 0 : (ai->parameters->length != 2 ||
233 0 : memcmp(ai->parameters->data, "\x05\x00", 2) != 0))
234 : {
235 0 : krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
236 0 : N_("kdf params not NULL or the NULL-type",
237 : ""));
238 0 : return KRB5_PROG_ETYPE_NOSUPP;
239 : }
240 :
241 0 : et = _krb5_find_enctype(enctype);
242 0 : if(et == NULL) {
243 0 : krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
244 0 : N_("encryption type %d not supported", ""),
245 : enctype);
246 0 : return KRB5_PROG_ETYPE_NOSUPP;
247 : }
248 0 : keylen = (et->keytype->bits + 7) / 8;
249 :
250 0 : keydata = malloc(keylen);
251 0 : if (keydata == NULL) {
252 0 : krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
253 0 : return ENOMEM;
254 : }
255 :
256 0 : ret = encode_otherinfo(context, ai, client, server,
257 : enctype, as_req, pk_as_rep, ticket, &other);
258 0 : if (ret) {
259 0 : free(keydata);
260 0 : return ret;
261 : }
262 :
263 0 : m = EVP_MD_CTX_create();
264 0 : if (m == NULL) {
265 0 : free(keydata);
266 0 : free(other.data);
267 0 : krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
268 0 : return ENOMEM;
269 : }
270 :
271 0 : offset = 0;
272 0 : counter = 1;
273 : do {
274 : unsigned char cdata[4];
275 :
276 0 : EVP_DigestInit_ex(m, md, NULL);
277 0 : _krb5_put_int(cdata, counter, 4);
278 0 : EVP_DigestUpdate(m, cdata, 4);
279 0 : EVP_DigestUpdate(m, dhdata, dhsize);
280 0 : EVP_DigestUpdate(m, other.data, other.length);
281 :
282 0 : EVP_DigestFinal_ex(m, shaoutput, NULL);
283 :
284 0 : memcpy((unsigned char *)keydata + offset,
285 : shaoutput,
286 0 : min(keylen - offset, EVP_MD_CTX_size(m)));
287 :
288 0 : offset += EVP_MD_CTX_size(m);
289 0 : counter++;
290 0 : } while(offset < keylen);
291 0 : memset(shaoutput, 0, sizeof(shaoutput));
292 :
293 0 : EVP_MD_CTX_destroy(m);
294 0 : free(other.data);
295 :
296 0 : ret = krb5_random_to_key(context, enctype, keydata, keylen, key);
297 0 : memset(keydata, 0, sizeof(keylen));
298 0 : free(keydata);
299 :
300 0 : return ret;
301 : }
|