Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/heimdal/lib/krb5/crypto-pk.c
34890 views
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
_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
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
if(et == NULL) {
56
krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
57
N_("encryption type %d not supported", ""),
58
type);
59
return KRB5_PROG_ETYPE_NOSUPP;
60
}
61
keylen = (et->keytype->bits + 7) / 8;
62
63
keydata = malloc(keylen);
64
if (keydata == NULL) {
65
krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
66
return ENOMEM;
67
}
68
69
m = EVP_MD_CTX_create();
70
if (m == NULL) {
71
free(keydata);
72
krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
73
return ENOMEM;
74
}
75
76
counter = 0;
77
offset = 0;
78
do {
79
80
EVP_DigestInit_ex(m, EVP_sha1(), NULL);
81
EVP_DigestUpdate(m, &counter, 1);
82
EVP_DigestUpdate(m, dhdata, dhsize);
83
84
if (c_n)
85
EVP_DigestUpdate(m, c_n->data, c_n->length);
86
if (k_n)
87
EVP_DigestUpdate(m, k_n->data, k_n->length);
88
89
EVP_DigestFinal_ex(m, shaoutput, NULL);
90
91
memcpy((unsigned char *)keydata + offset,
92
shaoutput,
93
min(keylen - offset, sizeof(shaoutput)));
94
95
offset += sizeof(shaoutput);
96
counter++;
97
} while(offset < keylen);
98
memset(shaoutput, 0, sizeof(shaoutput));
99
100
EVP_MD_CTX_destroy(m);
101
102
ret = krb5_random_to_key(context, type, keydata, keylen, key);
103
memset(keydata, 0, sizeof(keylen));
104
free(keydata);
105
return ret;
106
}
107
108
static krb5_error_code
109
encode_uvinfo(krb5_context context, krb5_const_principal p, krb5_data *data)
110
{
111
KRB5PrincipalName pn;
112
krb5_error_code ret;
113
size_t size = 0;
114
115
pn.principalName = p->name;
116
pn.realm = p->realm;
117
118
ASN1_MALLOC_ENCODE(KRB5PrincipalName, data->data, data->length,
119
&pn, &size, ret);
120
if (ret) {
121
krb5_data_zero(data);
122
krb5_set_error_message(context, ret,
123
N_("Failed to encode KRB5PrincipalName", ""));
124
return ret;
125
}
126
if (data->length != size)
127
krb5_abortx(context, "asn1 compiler internal error");
128
return 0;
129
}
130
131
static krb5_error_code
132
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
size_t size = 0;
147
148
krb5_data_zero(other);
149
memset(&otherinfo, 0, sizeof(otherinfo));
150
memset(&pubinfo, 0, sizeof(pubinfo));
151
152
pubinfo.enctype = enctype;
153
pubinfo.as_REQ = *as_req;
154
pubinfo.pk_as_rep = *pk_as_rep;
155
pubinfo.ticket = *ticket;
156
ASN1_MALLOC_ENCODE(PkinitSuppPubInfo, pub.data, pub.length,
157
&pubinfo, &size, ret);
158
if (ret) {
159
krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
160
return ret;
161
}
162
if (pub.length != size)
163
krb5_abortx(context, "asn1 compiler internal error");
164
165
ret = encode_uvinfo(context, client, &otherinfo.partyUInfo);
166
if (ret) {
167
free(pub.data);
168
return ret;
169
}
170
ret = encode_uvinfo(context, server, &otherinfo.partyVInfo);
171
if (ret) {
172
free(otherinfo.partyUInfo.data);
173
free(pub.data);
174
return ret;
175
}
176
177
otherinfo.algorithmID = *ai;
178
otherinfo.suppPubInfo = &pub;
179
180
ASN1_MALLOC_ENCODE(PkinitSP80056AOtherInfo, other->data, other->length,
181
&otherinfo, &size, ret);
182
free(otherinfo.partyUInfo.data);
183
free(otherinfo.partyVInfo.data);
184
free(pub.data);
185
if (ret) {
186
krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
187
return ret;
188
}
189
if (other->length != size)
190
krb5_abortx(context, "asn1 compiler internal error");
191
192
return 0;
193
}
194
195
196
197
krb5_error_code
198
_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
if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha1, &ai->algorithm) == 0) {
221
md = EVP_sha1();
222
} else if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha256, &ai->algorithm) == 0) {
223
md = EVP_sha256();
224
} else if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha512, &ai->algorithm) == 0) {
225
md = EVP_sha512();
226
} else {
227
krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
228
N_("KDF not supported", ""));
229
return KRB5_PROG_ETYPE_NOSUPP;
230
}
231
if (ai->parameters != NULL &&
232
(ai->parameters->length != 2 ||
233
memcmp(ai->parameters->data, "\x05\x00", 2) != 0))
234
{
235
krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
236
N_("kdf params not NULL or the NULL-type",
237
""));
238
return KRB5_PROG_ETYPE_NOSUPP;
239
}
240
241
et = _krb5_find_enctype(enctype);
242
if(et == NULL) {
243
krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
244
N_("encryption type %d not supported", ""),
245
enctype);
246
return KRB5_PROG_ETYPE_NOSUPP;
247
}
248
keylen = (et->keytype->bits + 7) / 8;
249
250
keydata = malloc(keylen);
251
if (keydata == NULL) {
252
krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
253
return ENOMEM;
254
}
255
256
ret = encode_otherinfo(context, ai, client, server,
257
enctype, as_req, pk_as_rep, ticket, &other);
258
if (ret) {
259
free(keydata);
260
return ret;
261
}
262
263
m = EVP_MD_CTX_create();
264
if (m == NULL) {
265
free(keydata);
266
free(other.data);
267
krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
268
return ENOMEM;
269
}
270
271
offset = 0;
272
counter = 1;
273
do {
274
unsigned char cdata[4];
275
276
EVP_DigestInit_ex(m, md, NULL);
277
_krb5_put_int(cdata, counter, 4);
278
EVP_DigestUpdate(m, cdata, 4);
279
EVP_DigestUpdate(m, dhdata, dhsize);
280
EVP_DigestUpdate(m, other.data, other.length);
281
282
EVP_DigestFinal_ex(m, shaoutput, NULL);
283
284
memcpy((unsigned char *)keydata + offset,
285
shaoutput,
286
min(keylen - offset, EVP_MD_CTX_size(m)));
287
288
offset += EVP_MD_CTX_size(m);
289
counter++;
290
} while(offset < keylen);
291
memset(shaoutput, 0, sizeof(shaoutput));
292
293
EVP_MD_CTX_destroy(m);
294
free(other.data);
295
296
ret = krb5_random_to_key(context, enctype, keydata, keylen, key);
297
memset(keydata, 0, sizeof(keylen));
298
free(keydata);
299
300
return ret;
301
}
302
303