1 /* $NetBSD: crypto-pk.c,v 1.1.1.2 2014/04/24 12:45:49 pettai Exp $ */
4 * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #include "krb5_locl.h"
38 #include <krb5/pkinit_asn1.h>
41 _krb5_pk_octetstring2key(krb5_context context
,
45 const heim_octet_string
*c_n
,
46 const heim_octet_string
*k_n
,
49 struct _krb5_encryption_type
*et
= _krb5_find_enctype(type
);
51 size_t keylen
, offset
;
53 unsigned char counter
;
54 unsigned char shaoutput
[SHA_DIGEST_LENGTH
];
58 krb5_set_error_message(context
, KRB5_PROG_ETYPE_NOSUPP
,
59 N_("encryption type %d not supported", ""),
61 return KRB5_PROG_ETYPE_NOSUPP
;
63 keylen
= (et
->keytype
->bits
+ 7) / 8;
65 keydata
= malloc(keylen
);
66 if (keydata
== NULL
) {
67 krb5_set_error_message(context
, ENOMEM
, N_("malloc: out of memory", ""));
71 m
= EVP_MD_CTX_create();
74 krb5_set_error_message(context
, ENOMEM
, N_("malloc: out of memory", ""));
82 EVP_DigestInit_ex(m
, EVP_sha1(), NULL
);
83 EVP_DigestUpdate(m
, &counter
, 1);
84 EVP_DigestUpdate(m
, dhdata
, dhsize
);
87 EVP_DigestUpdate(m
, c_n
->data
, c_n
->length
);
89 EVP_DigestUpdate(m
, k_n
->data
, k_n
->length
);
91 EVP_DigestFinal_ex(m
, shaoutput
, NULL
);
93 memcpy((unsigned char *)keydata
+ offset
,
95 min(keylen
- offset
, sizeof(shaoutput
)));
97 offset
+= sizeof(shaoutput
);
99 } while(offset
< keylen
);
100 memset(shaoutput
, 0, sizeof(shaoutput
));
102 EVP_MD_CTX_destroy(m
);
104 ret
= krb5_random_to_key(context
, type
, keydata
, keylen
, key
);
105 memset(keydata
, 0, sizeof(keylen
));
110 static krb5_error_code
111 encode_uvinfo(krb5_context context
, krb5_const_principal p
, krb5_data
*data
)
113 KRB5PrincipalName pn
;
117 pn
.principalName
= p
->name
;
120 ASN1_MALLOC_ENCODE(KRB5PrincipalName
, data
->data
, data
->length
,
123 krb5_data_zero(data
);
124 krb5_set_error_message(context
, ret
,
125 N_("Failed to encode KRB5PrincipalName", ""));
128 if (data
->length
!= size
)
129 krb5_abortx(context
, "asn1 compiler internal error");
133 static krb5_error_code
134 encode_otherinfo(krb5_context context
,
135 const AlgorithmIdentifier
*ai
,
136 krb5_const_principal client
,
137 krb5_const_principal server
,
138 krb5_enctype enctype
,
139 const krb5_data
*as_req
,
140 const krb5_data
*pk_as_rep
,
141 const Ticket
*ticket
,
144 PkinitSP80056AOtherInfo otherinfo
;
145 PkinitSuppPubInfo pubinfo
;
150 krb5_data_zero(other
);
151 memset(&otherinfo
, 0, sizeof(otherinfo
));
152 memset(&pubinfo
, 0, sizeof(pubinfo
));
154 pubinfo
.enctype
= enctype
;
155 pubinfo
.as_REQ
= *as_req
;
156 pubinfo
.pk_as_rep
= *pk_as_rep
;
157 pubinfo
.ticket
= *ticket
;
158 ASN1_MALLOC_ENCODE(PkinitSuppPubInfo
, pub
.data
, pub
.length
,
159 &pubinfo
, &size
, ret
);
161 krb5_set_error_message(context
, ret
, N_("malloc: out of memory", ""));
164 if (pub
.length
!= size
)
165 krb5_abortx(context
, "asn1 compiler internal error");
167 ret
= encode_uvinfo(context
, client
, &otherinfo
.partyUInfo
);
172 ret
= encode_uvinfo(context
, server
, &otherinfo
.partyVInfo
);
174 free(otherinfo
.partyUInfo
.data
);
179 otherinfo
.algorithmID
= *ai
;
180 otherinfo
.suppPubInfo
= &pub
;
182 ASN1_MALLOC_ENCODE(PkinitSP80056AOtherInfo
, other
->data
, other
->length
,
183 &otherinfo
, &size
, ret
);
184 free(otherinfo
.partyUInfo
.data
);
185 free(otherinfo
.partyVInfo
.data
);
188 krb5_set_error_message(context
, ret
, N_("malloc: out of memory", ""));
191 if (other
->length
!= size
)
192 krb5_abortx(context
, "asn1 compiler internal error");
200 _krb5_pk_kdf(krb5_context context
,
201 const struct AlgorithmIdentifier
*ai
,
204 krb5_const_principal client
,
205 krb5_const_principal server
,
206 krb5_enctype enctype
,
207 const krb5_data
*as_req
,
208 const krb5_data
*pk_as_rep
,
209 const Ticket
*ticket
,
212 struct _krb5_encryption_type
*et
;
215 size_t keylen
, offset
;
217 unsigned char *keydata
;
218 unsigned char shaoutput
[SHA512_DIGEST_LENGTH
];
222 if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha1
, &ai
->algorithm
) == 0) {
224 } else if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha256
, &ai
->algorithm
) == 0) {
226 } else if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha512
, &ai
->algorithm
) == 0) {
229 krb5_set_error_message(context
, KRB5_PROG_ETYPE_NOSUPP
,
230 N_("KDF not supported", ""));
231 return KRB5_PROG_ETYPE_NOSUPP
;
233 if (ai
->parameters
!= NULL
&&
234 (ai
->parameters
->length
!= 2 ||
235 memcmp(ai
->parameters
->data
, "\x05\x00", 2) != 0))
237 krb5_set_error_message(context
, KRB5_PROG_ETYPE_NOSUPP
,
238 N_("kdf params not NULL or the NULL-type",
240 return KRB5_PROG_ETYPE_NOSUPP
;
243 et
= _krb5_find_enctype(enctype
);
245 krb5_set_error_message(context
, KRB5_PROG_ETYPE_NOSUPP
,
246 N_("encryption type %d not supported", ""),
248 return KRB5_PROG_ETYPE_NOSUPP
;
250 keylen
= (et
->keytype
->bits
+ 7) / 8;
252 keydata
= malloc(keylen
);
253 if (keydata
== NULL
) {
254 krb5_set_error_message(context
, ENOMEM
, N_("malloc: out of memory", ""));
258 ret
= encode_otherinfo(context
, ai
, client
, server
,
259 enctype
, as_req
, pk_as_rep
, ticket
, &other
);
265 m
= EVP_MD_CTX_create();
269 krb5_set_error_message(context
, ENOMEM
, N_("malloc: out of memory", ""));
276 unsigned char cdata
[4];
278 EVP_DigestInit_ex(m
, md
, NULL
);
279 _krb5_put_int(cdata
, counter
, 4);
280 EVP_DigestUpdate(m
, cdata
, 4);
281 EVP_DigestUpdate(m
, dhdata
, dhsize
);
282 EVP_DigestUpdate(m
, other
.data
, other
.length
);
284 EVP_DigestFinal_ex(m
, shaoutput
, NULL
);
286 memcpy((unsigned char *)keydata
+ offset
,
288 min(keylen
- offset
, EVP_MD_CTX_size(m
)));
290 offset
+= EVP_MD_CTX_size(m
);
292 } while(offset
< keylen
);
293 memset(shaoutput
, 0, sizeof(shaoutput
));
295 EVP_MD_CTX_destroy(m
);
298 ret
= krb5_random_to_key(context
, enctype
, keydata
, keylen
, key
);
299 memset(keydata
, 0, sizeof(keylen
));