1*0a6a1f1dSLionel Sambuc /* $NetBSD: ca.c,v 1.1.1.2 2014/04/24 12:45:41 pettai Exp $ */
2ebfedea0SLionel Sambuc
3ebfedea0SLionel Sambuc /*
4ebfedea0SLionel Sambuc * Copyright (c) 2006 - 2010 Kungliga Tekniska Högskolan
5ebfedea0SLionel Sambuc * (Royal Institute of Technology, Stockholm, Sweden).
6ebfedea0SLionel Sambuc * All rights reserved.
7ebfedea0SLionel Sambuc *
8ebfedea0SLionel Sambuc * Redistribution and use in source and binary forms, with or without
9ebfedea0SLionel Sambuc * modification, are permitted provided that the following conditions
10ebfedea0SLionel Sambuc * are met:
11ebfedea0SLionel Sambuc *
12ebfedea0SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
13ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer.
14ebfedea0SLionel Sambuc *
15ebfedea0SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
16ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer in the
17ebfedea0SLionel Sambuc * documentation and/or other materials provided with the distribution.
18ebfedea0SLionel Sambuc *
19ebfedea0SLionel Sambuc * 3. Neither the name of the Institute nor the names of its contributors
20ebfedea0SLionel Sambuc * may be used to endorse or promote products derived from this software
21ebfedea0SLionel Sambuc * without specific prior written permission.
22ebfedea0SLionel Sambuc *
23ebfedea0SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24ebfedea0SLionel Sambuc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25ebfedea0SLionel Sambuc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ebfedea0SLionel Sambuc * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27ebfedea0SLionel Sambuc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28ebfedea0SLionel Sambuc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29ebfedea0SLionel Sambuc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30ebfedea0SLionel Sambuc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31ebfedea0SLionel Sambuc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32ebfedea0SLionel Sambuc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33ebfedea0SLionel Sambuc * SUCH DAMAGE.
34ebfedea0SLionel Sambuc */
35ebfedea0SLionel Sambuc
36ebfedea0SLionel Sambuc #include "hx_locl.h"
37ebfedea0SLionel Sambuc #include <krb5/pkinit_asn1.h>
38ebfedea0SLionel Sambuc
39ebfedea0SLionel Sambuc /**
40ebfedea0SLionel Sambuc * @page page_ca Hx509 CA functions
41ebfedea0SLionel Sambuc *
42ebfedea0SLionel Sambuc * See the library functions here: @ref hx509_ca
43ebfedea0SLionel Sambuc */
44ebfedea0SLionel Sambuc
45ebfedea0SLionel Sambuc struct hx509_ca_tbs {
46ebfedea0SLionel Sambuc hx509_name subject;
47ebfedea0SLionel Sambuc SubjectPublicKeyInfo spki;
48ebfedea0SLionel Sambuc ExtKeyUsage eku;
49ebfedea0SLionel Sambuc GeneralNames san;
50ebfedea0SLionel Sambuc unsigned key_usage;
51ebfedea0SLionel Sambuc heim_integer serial;
52ebfedea0SLionel Sambuc struct {
53ebfedea0SLionel Sambuc unsigned int proxy:1;
54ebfedea0SLionel Sambuc unsigned int ca:1;
55ebfedea0SLionel Sambuc unsigned int key:1;
56ebfedea0SLionel Sambuc unsigned int serial:1;
57ebfedea0SLionel Sambuc unsigned int domaincontroller:1;
58ebfedea0SLionel Sambuc unsigned int xUniqueID:1;
59ebfedea0SLionel Sambuc } flags;
60ebfedea0SLionel Sambuc time_t notBefore;
61ebfedea0SLionel Sambuc time_t notAfter;
62ebfedea0SLionel Sambuc int pathLenConstraint; /* both for CA and Proxy */
63ebfedea0SLionel Sambuc CRLDistributionPoints crldp;
64ebfedea0SLionel Sambuc heim_bit_string subjectUniqueID;
65ebfedea0SLionel Sambuc heim_bit_string issuerUniqueID;
66ebfedea0SLionel Sambuc
67ebfedea0SLionel Sambuc };
68ebfedea0SLionel Sambuc
69ebfedea0SLionel Sambuc /**
70ebfedea0SLionel Sambuc * Allocate an to-be-signed certificate object that will be converted
71ebfedea0SLionel Sambuc * into an certificate.
72ebfedea0SLionel Sambuc *
73ebfedea0SLionel Sambuc * @param context A hx509 context.
74ebfedea0SLionel Sambuc * @param tbs returned to-be-signed certicate object, free with
75ebfedea0SLionel Sambuc * hx509_ca_tbs_free().
76ebfedea0SLionel Sambuc *
77ebfedea0SLionel Sambuc * @return An hx509 error code, see hx509_get_error_string().
78ebfedea0SLionel Sambuc *
79ebfedea0SLionel Sambuc * @ingroup hx509_ca
80ebfedea0SLionel Sambuc */
81ebfedea0SLionel Sambuc
82ebfedea0SLionel Sambuc int
hx509_ca_tbs_init(hx509_context context,hx509_ca_tbs * tbs)83ebfedea0SLionel Sambuc hx509_ca_tbs_init(hx509_context context, hx509_ca_tbs *tbs)
84ebfedea0SLionel Sambuc {
85ebfedea0SLionel Sambuc *tbs = calloc(1, sizeof(**tbs));
86ebfedea0SLionel Sambuc if (*tbs == NULL)
87ebfedea0SLionel Sambuc return ENOMEM;
88ebfedea0SLionel Sambuc
89ebfedea0SLionel Sambuc return 0;
90ebfedea0SLionel Sambuc }
91ebfedea0SLionel Sambuc
92ebfedea0SLionel Sambuc /**
93ebfedea0SLionel Sambuc * Free an To Be Signed object.
94ebfedea0SLionel Sambuc *
95ebfedea0SLionel Sambuc * @param tbs object to free.
96ebfedea0SLionel Sambuc *
97ebfedea0SLionel Sambuc * @ingroup hx509_ca
98ebfedea0SLionel Sambuc */
99ebfedea0SLionel Sambuc
100ebfedea0SLionel Sambuc void
hx509_ca_tbs_free(hx509_ca_tbs * tbs)101ebfedea0SLionel Sambuc hx509_ca_tbs_free(hx509_ca_tbs *tbs)
102ebfedea0SLionel Sambuc {
103ebfedea0SLionel Sambuc if (tbs == NULL || *tbs == NULL)
104ebfedea0SLionel Sambuc return;
105ebfedea0SLionel Sambuc
106ebfedea0SLionel Sambuc free_SubjectPublicKeyInfo(&(*tbs)->spki);
107ebfedea0SLionel Sambuc free_GeneralNames(&(*tbs)->san);
108ebfedea0SLionel Sambuc free_ExtKeyUsage(&(*tbs)->eku);
109ebfedea0SLionel Sambuc der_free_heim_integer(&(*tbs)->serial);
110ebfedea0SLionel Sambuc free_CRLDistributionPoints(&(*tbs)->crldp);
111ebfedea0SLionel Sambuc der_free_bit_string(&(*tbs)->subjectUniqueID);
112ebfedea0SLionel Sambuc der_free_bit_string(&(*tbs)->issuerUniqueID);
113ebfedea0SLionel Sambuc hx509_name_free(&(*tbs)->subject);
114ebfedea0SLionel Sambuc
115ebfedea0SLionel Sambuc memset(*tbs, 0, sizeof(**tbs));
116ebfedea0SLionel Sambuc free(*tbs);
117ebfedea0SLionel Sambuc *tbs = NULL;
118ebfedea0SLionel Sambuc }
119ebfedea0SLionel Sambuc
120ebfedea0SLionel Sambuc /**
121ebfedea0SLionel Sambuc * Set the absolute time when the certificate is valid from. If not
122ebfedea0SLionel Sambuc * set the current time will be used.
123ebfedea0SLionel Sambuc *
124ebfedea0SLionel Sambuc * @param context A hx509 context.
125ebfedea0SLionel Sambuc * @param tbs object to be signed.
126ebfedea0SLionel Sambuc * @param t time the certificated will start to be valid
127ebfedea0SLionel Sambuc *
128ebfedea0SLionel Sambuc * @return An hx509 error code, see hx509_get_error_string().
129ebfedea0SLionel Sambuc *
130ebfedea0SLionel Sambuc * @ingroup hx509_ca
131ebfedea0SLionel Sambuc */
132ebfedea0SLionel Sambuc
133ebfedea0SLionel Sambuc int
hx509_ca_tbs_set_notBefore(hx509_context context,hx509_ca_tbs tbs,time_t t)134ebfedea0SLionel Sambuc hx509_ca_tbs_set_notBefore(hx509_context context,
135ebfedea0SLionel Sambuc hx509_ca_tbs tbs,
136ebfedea0SLionel Sambuc time_t t)
137ebfedea0SLionel Sambuc {
138ebfedea0SLionel Sambuc tbs->notBefore = t;
139ebfedea0SLionel Sambuc return 0;
140ebfedea0SLionel Sambuc }
141ebfedea0SLionel Sambuc
142ebfedea0SLionel Sambuc /**
143ebfedea0SLionel Sambuc * Set the absolute time when the certificate is valid to.
144ebfedea0SLionel Sambuc *
145ebfedea0SLionel Sambuc * @param context A hx509 context.
146ebfedea0SLionel Sambuc * @param tbs object to be signed.
147ebfedea0SLionel Sambuc * @param t time when the certificate will expire
148ebfedea0SLionel Sambuc *
149ebfedea0SLionel Sambuc * @return An hx509 error code, see hx509_get_error_string().
150ebfedea0SLionel Sambuc *
151ebfedea0SLionel Sambuc * @ingroup hx509_ca
152ebfedea0SLionel Sambuc */
153ebfedea0SLionel Sambuc
154ebfedea0SLionel Sambuc int
hx509_ca_tbs_set_notAfter(hx509_context context,hx509_ca_tbs tbs,time_t t)155ebfedea0SLionel Sambuc hx509_ca_tbs_set_notAfter(hx509_context context,
156ebfedea0SLionel Sambuc hx509_ca_tbs tbs,
157ebfedea0SLionel Sambuc time_t t)
158ebfedea0SLionel Sambuc {
159ebfedea0SLionel Sambuc tbs->notAfter = t;
160ebfedea0SLionel Sambuc return 0;
161ebfedea0SLionel Sambuc }
162ebfedea0SLionel Sambuc
163ebfedea0SLionel Sambuc /**
164ebfedea0SLionel Sambuc * Set the relative time when the certificiate is going to expire.
165ebfedea0SLionel Sambuc *
166ebfedea0SLionel Sambuc * @param context A hx509 context.
167ebfedea0SLionel Sambuc * @param tbs object to be signed.
168ebfedea0SLionel Sambuc * @param delta seconds to the certificate is going to expire.
169ebfedea0SLionel Sambuc *
170ebfedea0SLionel Sambuc * @return An hx509 error code, see hx509_get_error_string().
171ebfedea0SLionel Sambuc *
172ebfedea0SLionel Sambuc * @ingroup hx509_ca
173ebfedea0SLionel Sambuc */
174ebfedea0SLionel Sambuc
175ebfedea0SLionel Sambuc int
hx509_ca_tbs_set_notAfter_lifetime(hx509_context context,hx509_ca_tbs tbs,time_t delta)176ebfedea0SLionel Sambuc hx509_ca_tbs_set_notAfter_lifetime(hx509_context context,
177ebfedea0SLionel Sambuc hx509_ca_tbs tbs,
178ebfedea0SLionel Sambuc time_t delta)
179ebfedea0SLionel Sambuc {
180ebfedea0SLionel Sambuc return hx509_ca_tbs_set_notAfter(context, tbs, time(NULL) + delta);
181ebfedea0SLionel Sambuc }
182ebfedea0SLionel Sambuc
183ebfedea0SLionel Sambuc static const struct units templatebits[] = {
184ebfedea0SLionel Sambuc { "ExtendedKeyUsage", HX509_CA_TEMPLATE_EKU },
185ebfedea0SLionel Sambuc { "KeyUsage", HX509_CA_TEMPLATE_KU },
186ebfedea0SLionel Sambuc { "SPKI", HX509_CA_TEMPLATE_SPKI },
187ebfedea0SLionel Sambuc { "notAfter", HX509_CA_TEMPLATE_NOTAFTER },
188ebfedea0SLionel Sambuc { "notBefore", HX509_CA_TEMPLATE_NOTBEFORE },
189ebfedea0SLionel Sambuc { "serial", HX509_CA_TEMPLATE_SERIAL },
190ebfedea0SLionel Sambuc { "subject", HX509_CA_TEMPLATE_SUBJECT },
191ebfedea0SLionel Sambuc { NULL, 0 }
192ebfedea0SLionel Sambuc };
193ebfedea0SLionel Sambuc
194ebfedea0SLionel Sambuc /**
195ebfedea0SLionel Sambuc * Make of template units, use to build flags argument to
196ebfedea0SLionel Sambuc * hx509_ca_tbs_set_template() with parse_units().
197ebfedea0SLionel Sambuc *
198ebfedea0SLionel Sambuc * @return an units structure.
199ebfedea0SLionel Sambuc *
200ebfedea0SLionel Sambuc * @ingroup hx509_ca
201ebfedea0SLionel Sambuc */
202ebfedea0SLionel Sambuc
203ebfedea0SLionel Sambuc const struct units *
hx509_ca_tbs_template_units(void)204ebfedea0SLionel Sambuc hx509_ca_tbs_template_units(void)
205ebfedea0SLionel Sambuc {
206ebfedea0SLionel Sambuc return templatebits;
207ebfedea0SLionel Sambuc }
208ebfedea0SLionel Sambuc
209ebfedea0SLionel Sambuc /**
210ebfedea0SLionel Sambuc * Initialize the to-be-signed certificate object from a template certifiate.
211ebfedea0SLionel Sambuc *
212ebfedea0SLionel Sambuc * @param context A hx509 context.
213ebfedea0SLionel Sambuc * @param tbs object to be signed.
214ebfedea0SLionel Sambuc * @param flags bit field selecting what to copy from the template
215ebfedea0SLionel Sambuc * certifiate.
216ebfedea0SLionel Sambuc * @param cert template certificate.
217ebfedea0SLionel Sambuc *
218ebfedea0SLionel Sambuc * @return An hx509 error code, see hx509_get_error_string().
219ebfedea0SLionel Sambuc *
220ebfedea0SLionel Sambuc * @ingroup hx509_ca
221ebfedea0SLionel Sambuc */
222ebfedea0SLionel Sambuc
223ebfedea0SLionel Sambuc int
hx509_ca_tbs_set_template(hx509_context context,hx509_ca_tbs tbs,int flags,hx509_cert cert)224ebfedea0SLionel Sambuc hx509_ca_tbs_set_template(hx509_context context,
225ebfedea0SLionel Sambuc hx509_ca_tbs tbs,
226ebfedea0SLionel Sambuc int flags,
227ebfedea0SLionel Sambuc hx509_cert cert)
228ebfedea0SLionel Sambuc {
229ebfedea0SLionel Sambuc int ret;
230ebfedea0SLionel Sambuc
231ebfedea0SLionel Sambuc if (flags & HX509_CA_TEMPLATE_SUBJECT) {
232ebfedea0SLionel Sambuc if (tbs->subject)
233ebfedea0SLionel Sambuc hx509_name_free(&tbs->subject);
234ebfedea0SLionel Sambuc ret = hx509_cert_get_subject(cert, &tbs->subject);
235ebfedea0SLionel Sambuc if (ret) {
236ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret,
237ebfedea0SLionel Sambuc "Failed to get subject from template");
238ebfedea0SLionel Sambuc return ret;
239ebfedea0SLionel Sambuc }
240ebfedea0SLionel Sambuc }
241ebfedea0SLionel Sambuc if (flags & HX509_CA_TEMPLATE_SERIAL) {
242ebfedea0SLionel Sambuc der_free_heim_integer(&tbs->serial);
243ebfedea0SLionel Sambuc ret = hx509_cert_get_serialnumber(cert, &tbs->serial);
244ebfedea0SLionel Sambuc tbs->flags.serial = !ret;
245ebfedea0SLionel Sambuc if (ret) {
246ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret,
247ebfedea0SLionel Sambuc "Failed to copy serial number");
248ebfedea0SLionel Sambuc return ret;
249ebfedea0SLionel Sambuc }
250ebfedea0SLionel Sambuc }
251ebfedea0SLionel Sambuc if (flags & HX509_CA_TEMPLATE_NOTBEFORE)
252ebfedea0SLionel Sambuc tbs->notBefore = hx509_cert_get_notBefore(cert);
253ebfedea0SLionel Sambuc if (flags & HX509_CA_TEMPLATE_NOTAFTER)
254ebfedea0SLionel Sambuc tbs->notAfter = hx509_cert_get_notAfter(cert);
255ebfedea0SLionel Sambuc if (flags & HX509_CA_TEMPLATE_SPKI) {
256ebfedea0SLionel Sambuc free_SubjectPublicKeyInfo(&tbs->spki);
257ebfedea0SLionel Sambuc ret = hx509_cert_get_SPKI(context, cert, &tbs->spki);
258ebfedea0SLionel Sambuc tbs->flags.key = !ret;
259ebfedea0SLionel Sambuc if (ret)
260ebfedea0SLionel Sambuc return ret;
261ebfedea0SLionel Sambuc }
262ebfedea0SLionel Sambuc if (flags & HX509_CA_TEMPLATE_KU) {
263ebfedea0SLionel Sambuc KeyUsage ku;
264ebfedea0SLionel Sambuc ret = _hx509_cert_get_keyusage(context, cert, &ku);
265ebfedea0SLionel Sambuc if (ret)
266ebfedea0SLionel Sambuc return ret;
267ebfedea0SLionel Sambuc tbs->key_usage = KeyUsage2int(ku);
268ebfedea0SLionel Sambuc }
269ebfedea0SLionel Sambuc if (flags & HX509_CA_TEMPLATE_EKU) {
270ebfedea0SLionel Sambuc ExtKeyUsage eku;
271*0a6a1f1dSLionel Sambuc size_t i;
272ebfedea0SLionel Sambuc ret = _hx509_cert_get_eku(context, cert, &eku);
273ebfedea0SLionel Sambuc if (ret)
274ebfedea0SLionel Sambuc return ret;
275ebfedea0SLionel Sambuc for (i = 0; i < eku.len; i++) {
276ebfedea0SLionel Sambuc ret = hx509_ca_tbs_add_eku(context, tbs, &eku.val[i]);
277ebfedea0SLionel Sambuc if (ret) {
278ebfedea0SLionel Sambuc free_ExtKeyUsage(&eku);
279ebfedea0SLionel Sambuc return ret;
280ebfedea0SLionel Sambuc }
281ebfedea0SLionel Sambuc }
282ebfedea0SLionel Sambuc free_ExtKeyUsage(&eku);
283ebfedea0SLionel Sambuc }
284ebfedea0SLionel Sambuc return 0;
285ebfedea0SLionel Sambuc }
286ebfedea0SLionel Sambuc
287ebfedea0SLionel Sambuc /**
288ebfedea0SLionel Sambuc * Make the to-be-signed certificate object a CA certificate. If the
289ebfedea0SLionel Sambuc * pathLenConstraint is negative path length constraint is used.
290ebfedea0SLionel Sambuc *
291ebfedea0SLionel Sambuc * @param context A hx509 context.
292ebfedea0SLionel Sambuc * @param tbs object to be signed.
293ebfedea0SLionel Sambuc * @param pathLenConstraint path length constraint, negative, no
294ebfedea0SLionel Sambuc * constraint.
295ebfedea0SLionel Sambuc *
296ebfedea0SLionel Sambuc * @return An hx509 error code, see hx509_get_error_string().
297ebfedea0SLionel Sambuc *
298ebfedea0SLionel Sambuc * @ingroup hx509_ca
299ebfedea0SLionel Sambuc */
300ebfedea0SLionel Sambuc
301ebfedea0SLionel Sambuc int
hx509_ca_tbs_set_ca(hx509_context context,hx509_ca_tbs tbs,int pathLenConstraint)302ebfedea0SLionel Sambuc hx509_ca_tbs_set_ca(hx509_context context,
303ebfedea0SLionel Sambuc hx509_ca_tbs tbs,
304ebfedea0SLionel Sambuc int pathLenConstraint)
305ebfedea0SLionel Sambuc {
306ebfedea0SLionel Sambuc tbs->flags.ca = 1;
307ebfedea0SLionel Sambuc tbs->pathLenConstraint = pathLenConstraint;
308ebfedea0SLionel Sambuc return 0;
309ebfedea0SLionel Sambuc }
310ebfedea0SLionel Sambuc
311ebfedea0SLionel Sambuc /**
312ebfedea0SLionel Sambuc * Make the to-be-signed certificate object a proxy certificate. If the
313ebfedea0SLionel Sambuc * pathLenConstraint is negative path length constraint is used.
314ebfedea0SLionel Sambuc *
315ebfedea0SLionel Sambuc * @param context A hx509 context.
316ebfedea0SLionel Sambuc * @param tbs object to be signed.
317ebfedea0SLionel Sambuc * @param pathLenConstraint path length constraint, negative, no
318ebfedea0SLionel Sambuc * constraint.
319ebfedea0SLionel Sambuc *
320ebfedea0SLionel Sambuc * @return An hx509 error code, see hx509_get_error_string().
321ebfedea0SLionel Sambuc *
322ebfedea0SLionel Sambuc * @ingroup hx509_ca
323ebfedea0SLionel Sambuc */
324ebfedea0SLionel Sambuc
325ebfedea0SLionel Sambuc int
hx509_ca_tbs_set_proxy(hx509_context context,hx509_ca_tbs tbs,int pathLenConstraint)326ebfedea0SLionel Sambuc hx509_ca_tbs_set_proxy(hx509_context context,
327ebfedea0SLionel Sambuc hx509_ca_tbs tbs,
328ebfedea0SLionel Sambuc int pathLenConstraint)
329ebfedea0SLionel Sambuc {
330ebfedea0SLionel Sambuc tbs->flags.proxy = 1;
331ebfedea0SLionel Sambuc tbs->pathLenConstraint = pathLenConstraint;
332ebfedea0SLionel Sambuc return 0;
333ebfedea0SLionel Sambuc }
334ebfedea0SLionel Sambuc
335ebfedea0SLionel Sambuc
336ebfedea0SLionel Sambuc /**
337ebfedea0SLionel Sambuc * Make the to-be-signed certificate object a windows domain controller certificate.
338ebfedea0SLionel Sambuc *
339ebfedea0SLionel Sambuc * @param context A hx509 context.
340ebfedea0SLionel Sambuc * @param tbs object to be signed.
341ebfedea0SLionel Sambuc *
342ebfedea0SLionel Sambuc * @return An hx509 error code, see hx509_get_error_string().
343ebfedea0SLionel Sambuc *
344ebfedea0SLionel Sambuc * @ingroup hx509_ca
345ebfedea0SLionel Sambuc */
346ebfedea0SLionel Sambuc
347ebfedea0SLionel Sambuc int
hx509_ca_tbs_set_domaincontroller(hx509_context context,hx509_ca_tbs tbs)348ebfedea0SLionel Sambuc hx509_ca_tbs_set_domaincontroller(hx509_context context,
349ebfedea0SLionel Sambuc hx509_ca_tbs tbs)
350ebfedea0SLionel Sambuc {
351ebfedea0SLionel Sambuc tbs->flags.domaincontroller = 1;
352ebfedea0SLionel Sambuc return 0;
353ebfedea0SLionel Sambuc }
354ebfedea0SLionel Sambuc
355ebfedea0SLionel Sambuc /**
356ebfedea0SLionel Sambuc * Set the subject public key info (SPKI) in the to-be-signed certificate
357ebfedea0SLionel Sambuc * object. SPKI is the public key and key related parameters in the
358ebfedea0SLionel Sambuc * certificate.
359ebfedea0SLionel Sambuc *
360ebfedea0SLionel Sambuc * @param context A hx509 context.
361ebfedea0SLionel Sambuc * @param tbs object to be signed.
362ebfedea0SLionel Sambuc * @param spki subject public key info to use for the to-be-signed certificate object.
363ebfedea0SLionel Sambuc *
364ebfedea0SLionel Sambuc * @return An hx509 error code, see hx509_get_error_string().
365ebfedea0SLionel Sambuc *
366ebfedea0SLionel Sambuc * @ingroup hx509_ca
367ebfedea0SLionel Sambuc */
368ebfedea0SLionel Sambuc
369ebfedea0SLionel Sambuc int
hx509_ca_tbs_set_spki(hx509_context context,hx509_ca_tbs tbs,const SubjectPublicKeyInfo * spki)370ebfedea0SLionel Sambuc hx509_ca_tbs_set_spki(hx509_context context,
371ebfedea0SLionel Sambuc hx509_ca_tbs tbs,
372ebfedea0SLionel Sambuc const SubjectPublicKeyInfo *spki)
373ebfedea0SLionel Sambuc {
374ebfedea0SLionel Sambuc int ret;
375ebfedea0SLionel Sambuc free_SubjectPublicKeyInfo(&tbs->spki);
376ebfedea0SLionel Sambuc ret = copy_SubjectPublicKeyInfo(spki, &tbs->spki);
377ebfedea0SLionel Sambuc tbs->flags.key = !ret;
378ebfedea0SLionel Sambuc return ret;
379ebfedea0SLionel Sambuc }
380ebfedea0SLionel Sambuc
381ebfedea0SLionel Sambuc /**
382ebfedea0SLionel Sambuc * Set the serial number to use for to-be-signed certificate object.
383ebfedea0SLionel Sambuc *
384ebfedea0SLionel Sambuc * @param context A hx509 context.
385ebfedea0SLionel Sambuc * @param tbs object to be signed.
386ebfedea0SLionel Sambuc * @param serialNumber serial number to use for the to-be-signed
387ebfedea0SLionel Sambuc * certificate object.
388ebfedea0SLionel Sambuc *
389ebfedea0SLionel Sambuc * @return An hx509 error code, see hx509_get_error_string().
390ebfedea0SLionel Sambuc *
391ebfedea0SLionel Sambuc * @ingroup hx509_ca
392ebfedea0SLionel Sambuc */
393ebfedea0SLionel Sambuc
394ebfedea0SLionel Sambuc int
hx509_ca_tbs_set_serialnumber(hx509_context context,hx509_ca_tbs tbs,const heim_integer * serialNumber)395ebfedea0SLionel Sambuc hx509_ca_tbs_set_serialnumber(hx509_context context,
396ebfedea0SLionel Sambuc hx509_ca_tbs tbs,
397ebfedea0SLionel Sambuc const heim_integer *serialNumber)
398ebfedea0SLionel Sambuc {
399ebfedea0SLionel Sambuc int ret;
400ebfedea0SLionel Sambuc der_free_heim_integer(&tbs->serial);
401ebfedea0SLionel Sambuc ret = der_copy_heim_integer(serialNumber, &tbs->serial);
402ebfedea0SLionel Sambuc tbs->flags.serial = !ret;
403ebfedea0SLionel Sambuc return ret;
404ebfedea0SLionel Sambuc }
405ebfedea0SLionel Sambuc
406ebfedea0SLionel Sambuc /**
407ebfedea0SLionel Sambuc * An an extended key usage to the to-be-signed certificate object.
408ebfedea0SLionel Sambuc * Duplicates will detected and not added.
409ebfedea0SLionel Sambuc *
410ebfedea0SLionel Sambuc * @param context A hx509 context.
411ebfedea0SLionel Sambuc * @param tbs object to be signed.
412ebfedea0SLionel Sambuc * @param oid extended key usage to add.
413ebfedea0SLionel Sambuc *
414ebfedea0SLionel Sambuc * @return An hx509 error code, see hx509_get_error_string().
415ebfedea0SLionel Sambuc *
416ebfedea0SLionel Sambuc * @ingroup hx509_ca
417ebfedea0SLionel Sambuc */
418ebfedea0SLionel Sambuc
419ebfedea0SLionel Sambuc int
hx509_ca_tbs_add_eku(hx509_context context,hx509_ca_tbs tbs,const heim_oid * oid)420ebfedea0SLionel Sambuc hx509_ca_tbs_add_eku(hx509_context context,
421ebfedea0SLionel Sambuc hx509_ca_tbs tbs,
422ebfedea0SLionel Sambuc const heim_oid *oid)
423ebfedea0SLionel Sambuc {
424ebfedea0SLionel Sambuc void *ptr;
425ebfedea0SLionel Sambuc int ret;
426ebfedea0SLionel Sambuc unsigned i;
427ebfedea0SLionel Sambuc
428ebfedea0SLionel Sambuc /* search for duplicates */
429ebfedea0SLionel Sambuc for (i = 0; i < tbs->eku.len; i++) {
430ebfedea0SLionel Sambuc if (der_heim_oid_cmp(oid, &tbs->eku.val[i]) == 0)
431ebfedea0SLionel Sambuc return 0;
432ebfedea0SLionel Sambuc }
433ebfedea0SLionel Sambuc
434ebfedea0SLionel Sambuc ptr = realloc(tbs->eku.val, sizeof(tbs->eku.val[0]) * (tbs->eku.len + 1));
435ebfedea0SLionel Sambuc if (ptr == NULL) {
436ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ENOMEM, "out of memory");
437ebfedea0SLionel Sambuc return ENOMEM;
438ebfedea0SLionel Sambuc }
439ebfedea0SLionel Sambuc tbs->eku.val = ptr;
440ebfedea0SLionel Sambuc ret = der_copy_oid(oid, &tbs->eku.val[tbs->eku.len]);
441ebfedea0SLionel Sambuc if (ret) {
442ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "out of memory");
443ebfedea0SLionel Sambuc return ret;
444ebfedea0SLionel Sambuc }
445ebfedea0SLionel Sambuc tbs->eku.len += 1;
446ebfedea0SLionel Sambuc return 0;
447ebfedea0SLionel Sambuc }
448ebfedea0SLionel Sambuc
449ebfedea0SLionel Sambuc /**
450ebfedea0SLionel Sambuc * Add CRL distribution point URI to the to-be-signed certificate
451ebfedea0SLionel Sambuc * object.
452ebfedea0SLionel Sambuc *
453ebfedea0SLionel Sambuc * @param context A hx509 context.
454ebfedea0SLionel Sambuc * @param tbs object to be signed.
455ebfedea0SLionel Sambuc * @param uri uri to the CRL.
456ebfedea0SLionel Sambuc * @param issuername name of the issuer.
457ebfedea0SLionel Sambuc *
458ebfedea0SLionel Sambuc * @return An hx509 error code, see hx509_get_error_string().
459ebfedea0SLionel Sambuc *
460ebfedea0SLionel Sambuc * @ingroup hx509_ca
461ebfedea0SLionel Sambuc */
462ebfedea0SLionel Sambuc
463ebfedea0SLionel Sambuc int
hx509_ca_tbs_add_crl_dp_uri(hx509_context context,hx509_ca_tbs tbs,const char * uri,hx509_name issuername)464ebfedea0SLionel Sambuc hx509_ca_tbs_add_crl_dp_uri(hx509_context context,
465ebfedea0SLionel Sambuc hx509_ca_tbs tbs,
466ebfedea0SLionel Sambuc const char *uri,
467ebfedea0SLionel Sambuc hx509_name issuername)
468ebfedea0SLionel Sambuc {
469ebfedea0SLionel Sambuc DistributionPoint dp;
470ebfedea0SLionel Sambuc int ret;
471ebfedea0SLionel Sambuc
472ebfedea0SLionel Sambuc memset(&dp, 0, sizeof(dp));
473ebfedea0SLionel Sambuc
474ebfedea0SLionel Sambuc dp.distributionPoint = ecalloc(1, sizeof(*dp.distributionPoint));
475ebfedea0SLionel Sambuc
476ebfedea0SLionel Sambuc {
477ebfedea0SLionel Sambuc DistributionPointName name;
478ebfedea0SLionel Sambuc GeneralName gn;
479ebfedea0SLionel Sambuc size_t size;
480ebfedea0SLionel Sambuc
481ebfedea0SLionel Sambuc name.element = choice_DistributionPointName_fullName;
482ebfedea0SLionel Sambuc name.u.fullName.len = 1;
483ebfedea0SLionel Sambuc name.u.fullName.val = &gn;
484ebfedea0SLionel Sambuc
485ebfedea0SLionel Sambuc gn.element = choice_GeneralName_uniformResourceIdentifier;
486ebfedea0SLionel Sambuc gn.u.uniformResourceIdentifier.data = rk_UNCONST(uri);
487ebfedea0SLionel Sambuc gn.u.uniformResourceIdentifier.length = strlen(uri);
488ebfedea0SLionel Sambuc
489ebfedea0SLionel Sambuc ASN1_MALLOC_ENCODE(DistributionPointName,
490ebfedea0SLionel Sambuc dp.distributionPoint->data,
491ebfedea0SLionel Sambuc dp.distributionPoint->length,
492ebfedea0SLionel Sambuc &name, &size, ret);
493ebfedea0SLionel Sambuc if (ret) {
494ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret,
495ebfedea0SLionel Sambuc "Failed to encoded DistributionPointName");
496ebfedea0SLionel Sambuc goto out;
497ebfedea0SLionel Sambuc }
498ebfedea0SLionel Sambuc if (dp.distributionPoint->length != size)
499ebfedea0SLionel Sambuc _hx509_abort("internal ASN.1 encoder error");
500ebfedea0SLionel Sambuc }
501ebfedea0SLionel Sambuc
502ebfedea0SLionel Sambuc if (issuername) {
503ebfedea0SLionel Sambuc #if 1
504ebfedea0SLionel Sambuc /**
505ebfedea0SLionel Sambuc * issuername not supported
506ebfedea0SLionel Sambuc */
507ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, EINVAL,
508ebfedea0SLionel Sambuc "CRLDistributionPoints.name.issuername not yet supported");
509ebfedea0SLionel Sambuc return EINVAL;
510ebfedea0SLionel Sambuc #else
511ebfedea0SLionel Sambuc GeneralNames *crlissuer;
512ebfedea0SLionel Sambuc GeneralName gn;
513ebfedea0SLionel Sambuc Name n;
514ebfedea0SLionel Sambuc
515ebfedea0SLionel Sambuc crlissuer = calloc(1, sizeof(*crlissuer));
516ebfedea0SLionel Sambuc if (crlissuer == NULL) {
517ebfedea0SLionel Sambuc return ENOMEM;
518ebfedea0SLionel Sambuc }
519ebfedea0SLionel Sambuc memset(&gn, 0, sizeof(gn));
520ebfedea0SLionel Sambuc
521ebfedea0SLionel Sambuc gn.element = choice_GeneralName_directoryName;
522ebfedea0SLionel Sambuc ret = hx509_name_to_Name(issuername, &n);
523ebfedea0SLionel Sambuc if (ret) {
524ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "out of memory");
525ebfedea0SLionel Sambuc goto out;
526ebfedea0SLionel Sambuc }
527ebfedea0SLionel Sambuc
528ebfedea0SLionel Sambuc gn.u.directoryName.element = n.element;
529ebfedea0SLionel Sambuc gn.u.directoryName.u.rdnSequence = n.u.rdnSequence;
530ebfedea0SLionel Sambuc
531ebfedea0SLionel Sambuc ret = add_GeneralNames(&crlissuer, &gn);
532ebfedea0SLionel Sambuc free_Name(&n);
533ebfedea0SLionel Sambuc if (ret) {
534ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "out of memory");
535ebfedea0SLionel Sambuc goto out;
536ebfedea0SLionel Sambuc }
537ebfedea0SLionel Sambuc
538ebfedea0SLionel Sambuc dp.cRLIssuer = &crlissuer;
539ebfedea0SLionel Sambuc #endif
540ebfedea0SLionel Sambuc }
541ebfedea0SLionel Sambuc
542ebfedea0SLionel Sambuc ret = add_CRLDistributionPoints(&tbs->crldp, &dp);
543ebfedea0SLionel Sambuc if (ret) {
544ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "out of memory");
545ebfedea0SLionel Sambuc goto out;
546ebfedea0SLionel Sambuc }
547ebfedea0SLionel Sambuc
548ebfedea0SLionel Sambuc out:
549ebfedea0SLionel Sambuc free_DistributionPoint(&dp);
550ebfedea0SLionel Sambuc
551ebfedea0SLionel Sambuc return ret;
552ebfedea0SLionel Sambuc }
553ebfedea0SLionel Sambuc
554ebfedea0SLionel Sambuc /**
555ebfedea0SLionel Sambuc * Add Subject Alternative Name otherName to the to-be-signed
556ebfedea0SLionel Sambuc * certificate object.
557ebfedea0SLionel Sambuc *
558ebfedea0SLionel Sambuc * @param context A hx509 context.
559ebfedea0SLionel Sambuc * @param tbs object to be signed.
560ebfedea0SLionel Sambuc * @param oid the oid of the OtherName.
561ebfedea0SLionel Sambuc * @param os data in the other name.
562ebfedea0SLionel Sambuc *
563ebfedea0SLionel Sambuc * @return An hx509 error code, see hx509_get_error_string().
564ebfedea0SLionel Sambuc *
565ebfedea0SLionel Sambuc * @ingroup hx509_ca
566ebfedea0SLionel Sambuc */
567ebfedea0SLionel Sambuc
568ebfedea0SLionel Sambuc int
hx509_ca_tbs_add_san_otherName(hx509_context context,hx509_ca_tbs tbs,const heim_oid * oid,const heim_octet_string * os)569ebfedea0SLionel Sambuc hx509_ca_tbs_add_san_otherName(hx509_context context,
570ebfedea0SLionel Sambuc hx509_ca_tbs tbs,
571ebfedea0SLionel Sambuc const heim_oid *oid,
572ebfedea0SLionel Sambuc const heim_octet_string *os)
573ebfedea0SLionel Sambuc {
574ebfedea0SLionel Sambuc GeneralName gn;
575ebfedea0SLionel Sambuc
576ebfedea0SLionel Sambuc memset(&gn, 0, sizeof(gn));
577ebfedea0SLionel Sambuc gn.element = choice_GeneralName_otherName;
578ebfedea0SLionel Sambuc gn.u.otherName.type_id = *oid;
579ebfedea0SLionel Sambuc gn.u.otherName.value = *os;
580ebfedea0SLionel Sambuc
581ebfedea0SLionel Sambuc return add_GeneralNames(&tbs->san, &gn);
582ebfedea0SLionel Sambuc }
583ebfedea0SLionel Sambuc
584ebfedea0SLionel Sambuc /**
585ebfedea0SLionel Sambuc * Add Kerberos Subject Alternative Name to the to-be-signed
586ebfedea0SLionel Sambuc * certificate object. The principal string is a UTF8 string.
587ebfedea0SLionel Sambuc *
588ebfedea0SLionel Sambuc * @param context A hx509 context.
589ebfedea0SLionel Sambuc * @param tbs object to be signed.
590ebfedea0SLionel Sambuc * @param principal Kerberos principal to add to the certificate.
591ebfedea0SLionel Sambuc *
592ebfedea0SLionel Sambuc * @return An hx509 error code, see hx509_get_error_string().
593ebfedea0SLionel Sambuc *
594ebfedea0SLionel Sambuc * @ingroup hx509_ca
595ebfedea0SLionel Sambuc */
596ebfedea0SLionel Sambuc
597ebfedea0SLionel Sambuc int
hx509_ca_tbs_add_san_pkinit(hx509_context context,hx509_ca_tbs tbs,const char * principal)598ebfedea0SLionel Sambuc hx509_ca_tbs_add_san_pkinit(hx509_context context,
599ebfedea0SLionel Sambuc hx509_ca_tbs tbs,
600ebfedea0SLionel Sambuc const char *principal)
601ebfedea0SLionel Sambuc {
602ebfedea0SLionel Sambuc heim_octet_string os;
603ebfedea0SLionel Sambuc KRB5PrincipalName p;
604ebfedea0SLionel Sambuc size_t size;
605ebfedea0SLionel Sambuc int ret;
606ebfedea0SLionel Sambuc char *s = NULL;
607ebfedea0SLionel Sambuc
608ebfedea0SLionel Sambuc memset(&p, 0, sizeof(p));
609ebfedea0SLionel Sambuc
610ebfedea0SLionel Sambuc /* parse principal */
611ebfedea0SLionel Sambuc {
612ebfedea0SLionel Sambuc const char *str;
613ebfedea0SLionel Sambuc char *q;
614ebfedea0SLionel Sambuc int n;
615ebfedea0SLionel Sambuc
616ebfedea0SLionel Sambuc /* count number of component */
617ebfedea0SLionel Sambuc n = 1;
618ebfedea0SLionel Sambuc for(str = principal; *str != '\0' && *str != '@'; str++){
619ebfedea0SLionel Sambuc if(*str=='\\'){
620ebfedea0SLionel Sambuc if(str[1] == '\0' || str[1] == '@') {
621ebfedea0SLionel Sambuc ret = HX509_PARSING_NAME_FAILED;
622ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret,
623ebfedea0SLionel Sambuc "trailing \\ in principal name");
624ebfedea0SLionel Sambuc goto out;
625ebfedea0SLionel Sambuc }
626ebfedea0SLionel Sambuc str++;
627ebfedea0SLionel Sambuc } else if(*str == '/')
628ebfedea0SLionel Sambuc n++;
629ebfedea0SLionel Sambuc }
630ebfedea0SLionel Sambuc p.principalName.name_string.val =
631ebfedea0SLionel Sambuc calloc(n, sizeof(*p.principalName.name_string.val));
632ebfedea0SLionel Sambuc if (p.principalName.name_string.val == NULL) {
633ebfedea0SLionel Sambuc ret = ENOMEM;
634ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "malloc: out of memory");
635ebfedea0SLionel Sambuc goto out;
636ebfedea0SLionel Sambuc }
637ebfedea0SLionel Sambuc p.principalName.name_string.len = n;
638ebfedea0SLionel Sambuc
639ebfedea0SLionel Sambuc p.principalName.name_type = KRB5_NT_PRINCIPAL;
640ebfedea0SLionel Sambuc q = s = strdup(principal);
641ebfedea0SLionel Sambuc if (q == NULL) {
642ebfedea0SLionel Sambuc ret = ENOMEM;
643ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "malloc: out of memory");
644ebfedea0SLionel Sambuc goto out;
645ebfedea0SLionel Sambuc }
646ebfedea0SLionel Sambuc p.realm = strrchr(q, '@');
647ebfedea0SLionel Sambuc if (p.realm == NULL) {
648ebfedea0SLionel Sambuc ret = HX509_PARSING_NAME_FAILED;
649ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Missing @ in principal");
650ebfedea0SLionel Sambuc goto out;
651ebfedea0SLionel Sambuc };
652ebfedea0SLionel Sambuc *p.realm++ = '\0';
653ebfedea0SLionel Sambuc
654ebfedea0SLionel Sambuc n = 0;
655ebfedea0SLionel Sambuc while (q) {
656ebfedea0SLionel Sambuc p.principalName.name_string.val[n++] = q;
657ebfedea0SLionel Sambuc q = strchr(q, '/');
658ebfedea0SLionel Sambuc if (q)
659ebfedea0SLionel Sambuc *q++ = '\0';
660ebfedea0SLionel Sambuc }
661ebfedea0SLionel Sambuc }
662ebfedea0SLionel Sambuc
663ebfedea0SLionel Sambuc ASN1_MALLOC_ENCODE(KRB5PrincipalName, os.data, os.length, &p, &size, ret);
664ebfedea0SLionel Sambuc if (ret) {
665ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
666ebfedea0SLionel Sambuc goto out;
667ebfedea0SLionel Sambuc }
668ebfedea0SLionel Sambuc if (size != os.length)
669ebfedea0SLionel Sambuc _hx509_abort("internal ASN.1 encoder error");
670ebfedea0SLionel Sambuc
671ebfedea0SLionel Sambuc ret = hx509_ca_tbs_add_san_otherName(context,
672ebfedea0SLionel Sambuc tbs,
673ebfedea0SLionel Sambuc &asn1_oid_id_pkinit_san,
674ebfedea0SLionel Sambuc &os);
675ebfedea0SLionel Sambuc free(os.data);
676ebfedea0SLionel Sambuc out:
677ebfedea0SLionel Sambuc if (p.principalName.name_string.val)
678ebfedea0SLionel Sambuc free (p.principalName.name_string.val);
679ebfedea0SLionel Sambuc if (s)
680ebfedea0SLionel Sambuc free(s);
681ebfedea0SLionel Sambuc return ret;
682ebfedea0SLionel Sambuc }
683ebfedea0SLionel Sambuc
684ebfedea0SLionel Sambuc /*
685ebfedea0SLionel Sambuc *
686ebfedea0SLionel Sambuc */
687ebfedea0SLionel Sambuc
688ebfedea0SLionel Sambuc static int
add_utf8_san(hx509_context context,hx509_ca_tbs tbs,const heim_oid * oid,const char * string)689ebfedea0SLionel Sambuc add_utf8_san(hx509_context context,
690ebfedea0SLionel Sambuc hx509_ca_tbs tbs,
691ebfedea0SLionel Sambuc const heim_oid *oid,
692ebfedea0SLionel Sambuc const char *string)
693ebfedea0SLionel Sambuc {
694*0a6a1f1dSLionel Sambuc const PKIXXmppAddr ustring = (const PKIXXmppAddr)(intptr_t)string;
695ebfedea0SLionel Sambuc heim_octet_string os;
696ebfedea0SLionel Sambuc size_t size;
697ebfedea0SLionel Sambuc int ret;
698ebfedea0SLionel Sambuc
699ebfedea0SLionel Sambuc os.length = 0;
700ebfedea0SLionel Sambuc os.data = NULL;
701ebfedea0SLionel Sambuc
702ebfedea0SLionel Sambuc ASN1_MALLOC_ENCODE(PKIXXmppAddr, os.data, os.length, &ustring, &size, ret);
703ebfedea0SLionel Sambuc if (ret) {
704ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
705ebfedea0SLionel Sambuc goto out;
706ebfedea0SLionel Sambuc }
707ebfedea0SLionel Sambuc if (size != os.length)
708ebfedea0SLionel Sambuc _hx509_abort("internal ASN.1 encoder error");
709ebfedea0SLionel Sambuc
710ebfedea0SLionel Sambuc ret = hx509_ca_tbs_add_san_otherName(context,
711ebfedea0SLionel Sambuc tbs,
712ebfedea0SLionel Sambuc oid,
713ebfedea0SLionel Sambuc &os);
714ebfedea0SLionel Sambuc free(os.data);
715ebfedea0SLionel Sambuc out:
716ebfedea0SLionel Sambuc return ret;
717ebfedea0SLionel Sambuc }
718ebfedea0SLionel Sambuc
719ebfedea0SLionel Sambuc /**
720ebfedea0SLionel Sambuc * Add Microsoft UPN Subject Alternative Name to the to-be-signed
721ebfedea0SLionel Sambuc * certificate object. The principal string is a UTF8 string.
722ebfedea0SLionel Sambuc *
723ebfedea0SLionel Sambuc * @param context A hx509 context.
724ebfedea0SLionel Sambuc * @param tbs object to be signed.
725ebfedea0SLionel Sambuc * @param principal Microsoft UPN string.
726ebfedea0SLionel Sambuc *
727ebfedea0SLionel Sambuc * @return An hx509 error code, see hx509_get_error_string().
728ebfedea0SLionel Sambuc *
729ebfedea0SLionel Sambuc * @ingroup hx509_ca
730ebfedea0SLionel Sambuc */
731ebfedea0SLionel Sambuc
732ebfedea0SLionel Sambuc int
hx509_ca_tbs_add_san_ms_upn(hx509_context context,hx509_ca_tbs tbs,const char * principal)733ebfedea0SLionel Sambuc hx509_ca_tbs_add_san_ms_upn(hx509_context context,
734ebfedea0SLionel Sambuc hx509_ca_tbs tbs,
735ebfedea0SLionel Sambuc const char *principal)
736ebfedea0SLionel Sambuc {
737ebfedea0SLionel Sambuc return add_utf8_san(context, tbs, &asn1_oid_id_pkinit_ms_san, principal);
738ebfedea0SLionel Sambuc }
739ebfedea0SLionel Sambuc
740ebfedea0SLionel Sambuc /**
741ebfedea0SLionel Sambuc * Add a Jabber/XMPP jid Subject Alternative Name to the to-be-signed
742ebfedea0SLionel Sambuc * certificate object. The jid is an UTF8 string.
743ebfedea0SLionel Sambuc *
744ebfedea0SLionel Sambuc * @param context A hx509 context.
745ebfedea0SLionel Sambuc * @param tbs object to be signed.
746ebfedea0SLionel Sambuc * @param jid string of an a jabber id in UTF8.
747ebfedea0SLionel Sambuc *
748ebfedea0SLionel Sambuc * @return An hx509 error code, see hx509_get_error_string().
749ebfedea0SLionel Sambuc *
750ebfedea0SLionel Sambuc * @ingroup hx509_ca
751ebfedea0SLionel Sambuc */
752ebfedea0SLionel Sambuc
753ebfedea0SLionel Sambuc int
hx509_ca_tbs_add_san_jid(hx509_context context,hx509_ca_tbs tbs,const char * jid)754ebfedea0SLionel Sambuc hx509_ca_tbs_add_san_jid(hx509_context context,
755ebfedea0SLionel Sambuc hx509_ca_tbs tbs,
756ebfedea0SLionel Sambuc const char *jid)
757ebfedea0SLionel Sambuc {
758ebfedea0SLionel Sambuc return add_utf8_san(context, tbs, &asn1_oid_id_pkix_on_xmppAddr, jid);
759ebfedea0SLionel Sambuc }
760ebfedea0SLionel Sambuc
761ebfedea0SLionel Sambuc
762ebfedea0SLionel Sambuc /**
763ebfedea0SLionel Sambuc * Add a Subject Alternative Name hostname to to-be-signed certificate
764ebfedea0SLionel Sambuc * object. A domain match starts with ., an exact match does not.
765ebfedea0SLionel Sambuc *
766ebfedea0SLionel Sambuc * Example of a an domain match: .domain.se matches the hostname
767ebfedea0SLionel Sambuc * host.domain.se.
768ebfedea0SLionel Sambuc *
769ebfedea0SLionel Sambuc * @param context A hx509 context.
770ebfedea0SLionel Sambuc * @param tbs object to be signed.
771ebfedea0SLionel Sambuc * @param dnsname a hostame.
772ebfedea0SLionel Sambuc *
773ebfedea0SLionel Sambuc * @return An hx509 error code, see hx509_get_error_string().
774ebfedea0SLionel Sambuc *
775ebfedea0SLionel Sambuc * @ingroup hx509_ca
776ebfedea0SLionel Sambuc */
777ebfedea0SLionel Sambuc
778ebfedea0SLionel Sambuc int
hx509_ca_tbs_add_san_hostname(hx509_context context,hx509_ca_tbs tbs,const char * dnsname)779ebfedea0SLionel Sambuc hx509_ca_tbs_add_san_hostname(hx509_context context,
780ebfedea0SLionel Sambuc hx509_ca_tbs tbs,
781ebfedea0SLionel Sambuc const char *dnsname)
782ebfedea0SLionel Sambuc {
783ebfedea0SLionel Sambuc GeneralName gn;
784ebfedea0SLionel Sambuc
785ebfedea0SLionel Sambuc memset(&gn, 0, sizeof(gn));
786ebfedea0SLionel Sambuc gn.element = choice_GeneralName_dNSName;
787ebfedea0SLionel Sambuc gn.u.dNSName.data = rk_UNCONST(dnsname);
788ebfedea0SLionel Sambuc gn.u.dNSName.length = strlen(dnsname);
789ebfedea0SLionel Sambuc
790ebfedea0SLionel Sambuc return add_GeneralNames(&tbs->san, &gn);
791ebfedea0SLionel Sambuc }
792ebfedea0SLionel Sambuc
793ebfedea0SLionel Sambuc /**
794ebfedea0SLionel Sambuc * Add a Subject Alternative Name rfc822 (email address) to
795ebfedea0SLionel Sambuc * to-be-signed certificate object.
796ebfedea0SLionel Sambuc *
797ebfedea0SLionel Sambuc * @param context A hx509 context.
798ebfedea0SLionel Sambuc * @param tbs object to be signed.
799ebfedea0SLionel Sambuc * @param rfc822Name a string to a email address.
800ebfedea0SLionel Sambuc *
801ebfedea0SLionel Sambuc * @return An hx509 error code, see hx509_get_error_string().
802ebfedea0SLionel Sambuc *
803ebfedea0SLionel Sambuc * @ingroup hx509_ca
804ebfedea0SLionel Sambuc */
805ebfedea0SLionel Sambuc
806ebfedea0SLionel Sambuc int
hx509_ca_tbs_add_san_rfc822name(hx509_context context,hx509_ca_tbs tbs,const char * rfc822Name)807ebfedea0SLionel Sambuc hx509_ca_tbs_add_san_rfc822name(hx509_context context,
808ebfedea0SLionel Sambuc hx509_ca_tbs tbs,
809ebfedea0SLionel Sambuc const char *rfc822Name)
810ebfedea0SLionel Sambuc {
811ebfedea0SLionel Sambuc GeneralName gn;
812ebfedea0SLionel Sambuc
813ebfedea0SLionel Sambuc memset(&gn, 0, sizeof(gn));
814ebfedea0SLionel Sambuc gn.element = choice_GeneralName_rfc822Name;
815ebfedea0SLionel Sambuc gn.u.rfc822Name.data = rk_UNCONST(rfc822Name);
816ebfedea0SLionel Sambuc gn.u.rfc822Name.length = strlen(rfc822Name);
817ebfedea0SLionel Sambuc
818ebfedea0SLionel Sambuc return add_GeneralNames(&tbs->san, &gn);
819ebfedea0SLionel Sambuc }
820ebfedea0SLionel Sambuc
821ebfedea0SLionel Sambuc /**
822ebfedea0SLionel Sambuc * Set the subject name of a to-be-signed certificate object.
823ebfedea0SLionel Sambuc *
824ebfedea0SLionel Sambuc * @param context A hx509 context.
825ebfedea0SLionel Sambuc * @param tbs object to be signed.
826ebfedea0SLionel Sambuc * @param subject the name to set a subject.
827ebfedea0SLionel Sambuc *
828ebfedea0SLionel Sambuc * @return An hx509 error code, see hx509_get_error_string().
829ebfedea0SLionel Sambuc *
830ebfedea0SLionel Sambuc * @ingroup hx509_ca
831ebfedea0SLionel Sambuc */
832ebfedea0SLionel Sambuc
833ebfedea0SLionel Sambuc int
hx509_ca_tbs_set_subject(hx509_context context,hx509_ca_tbs tbs,hx509_name subject)834ebfedea0SLionel Sambuc hx509_ca_tbs_set_subject(hx509_context context,
835ebfedea0SLionel Sambuc hx509_ca_tbs tbs,
836ebfedea0SLionel Sambuc hx509_name subject)
837ebfedea0SLionel Sambuc {
838ebfedea0SLionel Sambuc if (tbs->subject)
839ebfedea0SLionel Sambuc hx509_name_free(&tbs->subject);
840ebfedea0SLionel Sambuc return hx509_name_copy(context, subject, &tbs->subject);
841ebfedea0SLionel Sambuc }
842ebfedea0SLionel Sambuc
843ebfedea0SLionel Sambuc /**
844ebfedea0SLionel Sambuc * Set the issuerUniqueID and subjectUniqueID
845ebfedea0SLionel Sambuc *
846ebfedea0SLionel Sambuc * These are only supposed to be used considered with version 2
847ebfedea0SLionel Sambuc * certificates, replaced by the two extensions SubjectKeyIdentifier
848ebfedea0SLionel Sambuc * and IssuerKeyIdentifier. This function is to allow application
849ebfedea0SLionel Sambuc * using legacy protocol to issue them.
850ebfedea0SLionel Sambuc *
851ebfedea0SLionel Sambuc * @param context A hx509 context.
852ebfedea0SLionel Sambuc * @param tbs object to be signed.
853ebfedea0SLionel Sambuc * @param issuerUniqueID to be set
854ebfedea0SLionel Sambuc * @param subjectUniqueID to be set
855ebfedea0SLionel Sambuc *
856ebfedea0SLionel Sambuc * @return An hx509 error code, see hx509_get_error_string().
857ebfedea0SLionel Sambuc *
858ebfedea0SLionel Sambuc * @ingroup hx509_ca
859ebfedea0SLionel Sambuc */
860ebfedea0SLionel Sambuc
861ebfedea0SLionel Sambuc int
hx509_ca_tbs_set_unique(hx509_context context,hx509_ca_tbs tbs,const heim_bit_string * subjectUniqueID,const heim_bit_string * issuerUniqueID)862ebfedea0SLionel Sambuc hx509_ca_tbs_set_unique(hx509_context context,
863ebfedea0SLionel Sambuc hx509_ca_tbs tbs,
864ebfedea0SLionel Sambuc const heim_bit_string *subjectUniqueID,
865ebfedea0SLionel Sambuc const heim_bit_string *issuerUniqueID)
866ebfedea0SLionel Sambuc {
867ebfedea0SLionel Sambuc int ret;
868ebfedea0SLionel Sambuc
869ebfedea0SLionel Sambuc der_free_bit_string(&tbs->subjectUniqueID);
870ebfedea0SLionel Sambuc der_free_bit_string(&tbs->issuerUniqueID);
871ebfedea0SLionel Sambuc
872ebfedea0SLionel Sambuc if (subjectUniqueID) {
873ebfedea0SLionel Sambuc ret = der_copy_bit_string(subjectUniqueID, &tbs->subjectUniqueID);
874ebfedea0SLionel Sambuc if (ret)
875ebfedea0SLionel Sambuc return ret;
876ebfedea0SLionel Sambuc }
877ebfedea0SLionel Sambuc
878ebfedea0SLionel Sambuc if (issuerUniqueID) {
879ebfedea0SLionel Sambuc ret = der_copy_bit_string(issuerUniqueID, &tbs->issuerUniqueID);
880ebfedea0SLionel Sambuc if (ret)
881ebfedea0SLionel Sambuc return ret;
882ebfedea0SLionel Sambuc }
883ebfedea0SLionel Sambuc
884ebfedea0SLionel Sambuc return 0;
885ebfedea0SLionel Sambuc }
886ebfedea0SLionel Sambuc
887ebfedea0SLionel Sambuc /**
888ebfedea0SLionel Sambuc * Expand the the subject name in the to-be-signed certificate object
889ebfedea0SLionel Sambuc * using hx509_name_expand().
890ebfedea0SLionel Sambuc *
891ebfedea0SLionel Sambuc * @param context A hx509 context.
892ebfedea0SLionel Sambuc * @param tbs object to be signed.
893ebfedea0SLionel Sambuc * @param env enviroment variable to expand variables in the subject
894ebfedea0SLionel Sambuc * name, see hx509_env_init().
895ebfedea0SLionel Sambuc *
896ebfedea0SLionel Sambuc * @return An hx509 error code, see hx509_get_error_string().
897ebfedea0SLionel Sambuc *
898ebfedea0SLionel Sambuc * @ingroup hx509_ca
899ebfedea0SLionel Sambuc */
900ebfedea0SLionel Sambuc
901ebfedea0SLionel Sambuc int
hx509_ca_tbs_subject_expand(hx509_context context,hx509_ca_tbs tbs,hx509_env env)902ebfedea0SLionel Sambuc hx509_ca_tbs_subject_expand(hx509_context context,
903ebfedea0SLionel Sambuc hx509_ca_tbs tbs,
904ebfedea0SLionel Sambuc hx509_env env)
905ebfedea0SLionel Sambuc {
906ebfedea0SLionel Sambuc return hx509_name_expand(context, tbs->subject, env);
907ebfedea0SLionel Sambuc }
908ebfedea0SLionel Sambuc
909ebfedea0SLionel Sambuc /*
910ebfedea0SLionel Sambuc *
911ebfedea0SLionel Sambuc */
912ebfedea0SLionel Sambuc
913ebfedea0SLionel Sambuc static int
add_extension(hx509_context context,TBSCertificate * tbsc,int critical_flag,const heim_oid * oid,const heim_octet_string * data)914ebfedea0SLionel Sambuc add_extension(hx509_context context,
915ebfedea0SLionel Sambuc TBSCertificate *tbsc,
916ebfedea0SLionel Sambuc int critical_flag,
917ebfedea0SLionel Sambuc const heim_oid *oid,
918ebfedea0SLionel Sambuc const heim_octet_string *data)
919ebfedea0SLionel Sambuc {
920ebfedea0SLionel Sambuc Extension ext;
921ebfedea0SLionel Sambuc int ret;
922ebfedea0SLionel Sambuc
923ebfedea0SLionel Sambuc memset(&ext, 0, sizeof(ext));
924ebfedea0SLionel Sambuc
925ebfedea0SLionel Sambuc if (critical_flag) {
926ebfedea0SLionel Sambuc ext.critical = malloc(sizeof(*ext.critical));
927ebfedea0SLionel Sambuc if (ext.critical == NULL) {
928ebfedea0SLionel Sambuc ret = ENOMEM;
929ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
930ebfedea0SLionel Sambuc goto out;
931ebfedea0SLionel Sambuc }
932ebfedea0SLionel Sambuc *ext.critical = TRUE;
933ebfedea0SLionel Sambuc }
934ebfedea0SLionel Sambuc
935ebfedea0SLionel Sambuc ret = der_copy_oid(oid, &ext.extnID);
936ebfedea0SLionel Sambuc if (ret) {
937ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
938ebfedea0SLionel Sambuc goto out;
939ebfedea0SLionel Sambuc }
940ebfedea0SLionel Sambuc ret = der_copy_octet_string(data, &ext.extnValue);
941ebfedea0SLionel Sambuc if (ret) {
942ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
943ebfedea0SLionel Sambuc goto out;
944ebfedea0SLionel Sambuc }
945ebfedea0SLionel Sambuc ret = add_Extensions(tbsc->extensions, &ext);
946ebfedea0SLionel Sambuc if (ret) {
947ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
948ebfedea0SLionel Sambuc goto out;
949ebfedea0SLionel Sambuc }
950ebfedea0SLionel Sambuc out:
951ebfedea0SLionel Sambuc free_Extension(&ext);
952ebfedea0SLionel Sambuc return ret;
953ebfedea0SLionel Sambuc }
954ebfedea0SLionel Sambuc
955ebfedea0SLionel Sambuc static int
build_proxy_prefix(hx509_context context,const Name * issuer,Name * subject)956ebfedea0SLionel Sambuc build_proxy_prefix(hx509_context context, const Name *issuer, Name *subject)
957ebfedea0SLionel Sambuc {
958ebfedea0SLionel Sambuc char *tstr;
959ebfedea0SLionel Sambuc time_t t;
960ebfedea0SLionel Sambuc int ret;
961ebfedea0SLionel Sambuc
962ebfedea0SLionel Sambuc ret = copy_Name(issuer, subject);
963ebfedea0SLionel Sambuc if (ret) {
964ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret,
965ebfedea0SLionel Sambuc "Failed to copy subject name");
966ebfedea0SLionel Sambuc return ret;
967ebfedea0SLionel Sambuc }
968ebfedea0SLionel Sambuc
969ebfedea0SLionel Sambuc t = time(NULL);
970ebfedea0SLionel Sambuc asprintf(&tstr, "ts-%lu", (unsigned long)t);
971ebfedea0SLionel Sambuc if (tstr == NULL) {
972ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ENOMEM,
973ebfedea0SLionel Sambuc "Failed to copy subject name");
974ebfedea0SLionel Sambuc return ENOMEM;
975ebfedea0SLionel Sambuc }
976ebfedea0SLionel Sambuc /* prefix with CN=<ts>,...*/
977ebfedea0SLionel Sambuc ret = _hx509_name_modify(context, subject, 1, &asn1_oid_id_at_commonName, tstr);
978ebfedea0SLionel Sambuc free(tstr);
979ebfedea0SLionel Sambuc if (ret)
980ebfedea0SLionel Sambuc free_Name(subject);
981ebfedea0SLionel Sambuc return ret;
982ebfedea0SLionel Sambuc }
983ebfedea0SLionel Sambuc
984ebfedea0SLionel Sambuc static int
ca_sign(hx509_context context,hx509_ca_tbs tbs,hx509_private_key signer,const AuthorityKeyIdentifier * ai,const Name * issuername,hx509_cert * certificate)985ebfedea0SLionel Sambuc ca_sign(hx509_context context,
986ebfedea0SLionel Sambuc hx509_ca_tbs tbs,
987ebfedea0SLionel Sambuc hx509_private_key signer,
988ebfedea0SLionel Sambuc const AuthorityKeyIdentifier *ai,
989ebfedea0SLionel Sambuc const Name *issuername,
990ebfedea0SLionel Sambuc hx509_cert *certificate)
991ebfedea0SLionel Sambuc {
992ebfedea0SLionel Sambuc heim_octet_string data;
993ebfedea0SLionel Sambuc Certificate c;
994ebfedea0SLionel Sambuc TBSCertificate *tbsc;
995ebfedea0SLionel Sambuc size_t size;
996ebfedea0SLionel Sambuc int ret;
997ebfedea0SLionel Sambuc const AlgorithmIdentifier *sigalg;
998ebfedea0SLionel Sambuc time_t notBefore;
999ebfedea0SLionel Sambuc time_t notAfter;
1000ebfedea0SLionel Sambuc unsigned key_usage;
1001ebfedea0SLionel Sambuc
1002ebfedea0SLionel Sambuc sigalg = _hx509_crypto_default_sig_alg;
1003ebfedea0SLionel Sambuc
1004ebfedea0SLionel Sambuc memset(&c, 0, sizeof(c));
1005ebfedea0SLionel Sambuc
1006ebfedea0SLionel Sambuc /*
1007ebfedea0SLionel Sambuc * Default values are: Valid since 24h ago, valid one year into
1008ebfedea0SLionel Sambuc * the future, KeyUsage digitalSignature and keyEncipherment set,
1009ebfedea0SLionel Sambuc * and keyCertSign for CA certificates.
1010ebfedea0SLionel Sambuc */
1011ebfedea0SLionel Sambuc notBefore = tbs->notBefore;
1012ebfedea0SLionel Sambuc if (notBefore == 0)
1013ebfedea0SLionel Sambuc notBefore = time(NULL) - 3600 * 24;
1014ebfedea0SLionel Sambuc notAfter = tbs->notAfter;
1015ebfedea0SLionel Sambuc if (notAfter == 0)
1016ebfedea0SLionel Sambuc notAfter = time(NULL) + 3600 * 24 * 365;
1017ebfedea0SLionel Sambuc
1018ebfedea0SLionel Sambuc key_usage = tbs->key_usage;
1019ebfedea0SLionel Sambuc if (key_usage == 0) {
1020ebfedea0SLionel Sambuc KeyUsage ku;
1021ebfedea0SLionel Sambuc memset(&ku, 0, sizeof(ku));
1022ebfedea0SLionel Sambuc ku.digitalSignature = 1;
1023ebfedea0SLionel Sambuc ku.keyEncipherment = 1;
1024ebfedea0SLionel Sambuc key_usage = KeyUsage2int(ku);
1025ebfedea0SLionel Sambuc }
1026ebfedea0SLionel Sambuc
1027ebfedea0SLionel Sambuc if (tbs->flags.ca) {
1028ebfedea0SLionel Sambuc KeyUsage ku;
1029ebfedea0SLionel Sambuc memset(&ku, 0, sizeof(ku));
1030ebfedea0SLionel Sambuc ku.keyCertSign = 1;
1031ebfedea0SLionel Sambuc ku.cRLSign = 1;
1032ebfedea0SLionel Sambuc key_usage |= KeyUsage2int(ku);
1033ebfedea0SLionel Sambuc }
1034ebfedea0SLionel Sambuc
1035ebfedea0SLionel Sambuc /*
1036ebfedea0SLionel Sambuc *
1037ebfedea0SLionel Sambuc */
1038ebfedea0SLionel Sambuc
1039ebfedea0SLionel Sambuc tbsc = &c.tbsCertificate;
1040ebfedea0SLionel Sambuc
1041ebfedea0SLionel Sambuc if (tbs->flags.key == 0) {
1042ebfedea0SLionel Sambuc ret = EINVAL;
1043ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "No public key set");
1044ebfedea0SLionel Sambuc return ret;
1045ebfedea0SLionel Sambuc }
1046ebfedea0SLionel Sambuc /*
1047ebfedea0SLionel Sambuc * Don't put restrictions on proxy certificate's subject name, it
1048ebfedea0SLionel Sambuc * will be generated below.
1049ebfedea0SLionel Sambuc */
1050ebfedea0SLionel Sambuc if (!tbs->flags.proxy) {
1051ebfedea0SLionel Sambuc if (tbs->subject == NULL) {
1052ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, EINVAL, "No subject name set");
1053ebfedea0SLionel Sambuc return EINVAL;
1054ebfedea0SLionel Sambuc }
1055ebfedea0SLionel Sambuc if (hx509_name_is_null_p(tbs->subject) && tbs->san.len == 0) {
1056ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, EINVAL,
1057ebfedea0SLionel Sambuc "NULL subject and no SubjectAltNames");
1058ebfedea0SLionel Sambuc return EINVAL;
1059ebfedea0SLionel Sambuc }
1060ebfedea0SLionel Sambuc }
1061ebfedea0SLionel Sambuc if (tbs->flags.ca && tbs->flags.proxy) {
1062ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, EINVAL, "Can't be proxy and CA "
1063ebfedea0SLionel Sambuc "at the same time");
1064ebfedea0SLionel Sambuc return EINVAL;
1065ebfedea0SLionel Sambuc }
1066ebfedea0SLionel Sambuc if (tbs->flags.proxy) {
1067ebfedea0SLionel Sambuc if (tbs->san.len > 0) {
1068ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, EINVAL,
1069ebfedea0SLionel Sambuc "Proxy certificate is not allowed "
1070ebfedea0SLionel Sambuc "to have SubjectAltNames");
1071ebfedea0SLionel Sambuc return EINVAL;
1072ebfedea0SLionel Sambuc }
1073ebfedea0SLionel Sambuc }
1074ebfedea0SLionel Sambuc
1075ebfedea0SLionel Sambuc /* version [0] Version OPTIONAL, -- EXPLICIT nnn DEFAULT 1, */
1076ebfedea0SLionel Sambuc tbsc->version = calloc(1, sizeof(*tbsc->version));
1077ebfedea0SLionel Sambuc if (tbsc->version == NULL) {
1078ebfedea0SLionel Sambuc ret = ENOMEM;
1079ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
1080ebfedea0SLionel Sambuc goto out;
1081ebfedea0SLionel Sambuc }
1082ebfedea0SLionel Sambuc *tbsc->version = rfc3280_version_3;
1083ebfedea0SLionel Sambuc /* serialNumber CertificateSerialNumber, */
1084ebfedea0SLionel Sambuc if (tbs->flags.serial) {
1085ebfedea0SLionel Sambuc ret = der_copy_heim_integer(&tbs->serial, &tbsc->serialNumber);
1086ebfedea0SLionel Sambuc if (ret) {
1087ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
1088ebfedea0SLionel Sambuc goto out;
1089ebfedea0SLionel Sambuc }
1090ebfedea0SLionel Sambuc } else {
1091ebfedea0SLionel Sambuc tbsc->serialNumber.length = 20;
1092ebfedea0SLionel Sambuc tbsc->serialNumber.data = malloc(tbsc->serialNumber.length);
1093ebfedea0SLionel Sambuc if (tbsc->serialNumber.data == NULL){
1094ebfedea0SLionel Sambuc ret = ENOMEM;
1095ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
1096ebfedea0SLionel Sambuc goto out;
1097ebfedea0SLionel Sambuc }
1098ebfedea0SLionel Sambuc /* XXX diffrent */
1099ebfedea0SLionel Sambuc RAND_bytes(tbsc->serialNumber.data, tbsc->serialNumber.length);
1100ebfedea0SLionel Sambuc ((unsigned char *)tbsc->serialNumber.data)[0] &= 0x7f;
1101ebfedea0SLionel Sambuc }
1102ebfedea0SLionel Sambuc /* signature AlgorithmIdentifier, */
1103ebfedea0SLionel Sambuc ret = copy_AlgorithmIdentifier(sigalg, &tbsc->signature);
1104ebfedea0SLionel Sambuc if (ret) {
1105ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Failed to copy sigature alg");
1106ebfedea0SLionel Sambuc goto out;
1107ebfedea0SLionel Sambuc }
1108ebfedea0SLionel Sambuc /* issuer Name, */
1109ebfedea0SLionel Sambuc if (issuername)
1110ebfedea0SLionel Sambuc ret = copy_Name(issuername, &tbsc->issuer);
1111ebfedea0SLionel Sambuc else
1112ebfedea0SLionel Sambuc ret = hx509_name_to_Name(tbs->subject, &tbsc->issuer);
1113ebfedea0SLionel Sambuc if (ret) {
1114ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Failed to copy issuer name");
1115ebfedea0SLionel Sambuc goto out;
1116ebfedea0SLionel Sambuc }
1117ebfedea0SLionel Sambuc /* validity Validity, */
1118ebfedea0SLionel Sambuc tbsc->validity.notBefore.element = choice_Time_generalTime;
1119ebfedea0SLionel Sambuc tbsc->validity.notBefore.u.generalTime = notBefore;
1120ebfedea0SLionel Sambuc tbsc->validity.notAfter.element = choice_Time_generalTime;
1121ebfedea0SLionel Sambuc tbsc->validity.notAfter.u.generalTime = notAfter;
1122ebfedea0SLionel Sambuc /* subject Name, */
1123ebfedea0SLionel Sambuc if (tbs->flags.proxy) {
1124ebfedea0SLionel Sambuc ret = build_proxy_prefix(context, &tbsc->issuer, &tbsc->subject);
1125ebfedea0SLionel Sambuc if (ret)
1126ebfedea0SLionel Sambuc goto out;
1127ebfedea0SLionel Sambuc } else {
1128ebfedea0SLionel Sambuc ret = hx509_name_to_Name(tbs->subject, &tbsc->subject);
1129ebfedea0SLionel Sambuc if (ret) {
1130ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret,
1131ebfedea0SLionel Sambuc "Failed to copy subject name");
1132ebfedea0SLionel Sambuc goto out;
1133ebfedea0SLionel Sambuc }
1134ebfedea0SLionel Sambuc }
1135ebfedea0SLionel Sambuc /* subjectPublicKeyInfo SubjectPublicKeyInfo, */
1136ebfedea0SLionel Sambuc ret = copy_SubjectPublicKeyInfo(&tbs->spki, &tbsc->subjectPublicKeyInfo);
1137ebfedea0SLionel Sambuc if (ret) {
1138ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Failed to copy spki");
1139ebfedea0SLionel Sambuc goto out;
1140ebfedea0SLionel Sambuc }
1141ebfedea0SLionel Sambuc /* issuerUniqueID [1] IMPLICIT BIT STRING OPTIONAL */
1142ebfedea0SLionel Sambuc if (tbs->issuerUniqueID.length) {
1143ebfedea0SLionel Sambuc tbsc->issuerUniqueID = calloc(1, sizeof(*tbsc->issuerUniqueID));
1144ebfedea0SLionel Sambuc if (tbsc->issuerUniqueID == NULL) {
1145ebfedea0SLionel Sambuc ret = ENOMEM;
1146ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
1147ebfedea0SLionel Sambuc goto out;
1148ebfedea0SLionel Sambuc }
1149ebfedea0SLionel Sambuc ret = der_copy_bit_string(&tbs->issuerUniqueID, tbsc->issuerUniqueID);
1150ebfedea0SLionel Sambuc if (ret) {
1151ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
1152ebfedea0SLionel Sambuc goto out;
1153ebfedea0SLionel Sambuc }
1154ebfedea0SLionel Sambuc }
1155ebfedea0SLionel Sambuc /* subjectUniqueID [2] IMPLICIT BIT STRING OPTIONAL */
1156ebfedea0SLionel Sambuc if (tbs->subjectUniqueID.length) {
1157ebfedea0SLionel Sambuc tbsc->subjectUniqueID = calloc(1, sizeof(*tbsc->subjectUniqueID));
1158ebfedea0SLionel Sambuc if (tbsc->subjectUniqueID == NULL) {
1159ebfedea0SLionel Sambuc ret = ENOMEM;
1160ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
1161ebfedea0SLionel Sambuc goto out;
1162ebfedea0SLionel Sambuc }
1163ebfedea0SLionel Sambuc
1164ebfedea0SLionel Sambuc ret = der_copy_bit_string(&tbs->subjectUniqueID, tbsc->subjectUniqueID);
1165ebfedea0SLionel Sambuc if (ret) {
1166ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
1167ebfedea0SLionel Sambuc goto out;
1168ebfedea0SLionel Sambuc }
1169ebfedea0SLionel Sambuc }
1170ebfedea0SLionel Sambuc
1171ebfedea0SLionel Sambuc /* extensions [3] EXPLICIT Extensions OPTIONAL */
1172ebfedea0SLionel Sambuc tbsc->extensions = calloc(1, sizeof(*tbsc->extensions));
1173ebfedea0SLionel Sambuc if (tbsc->extensions == NULL) {
1174ebfedea0SLionel Sambuc ret = ENOMEM;
1175ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
1176ebfedea0SLionel Sambuc goto out;
1177ebfedea0SLionel Sambuc }
1178ebfedea0SLionel Sambuc
1179ebfedea0SLionel Sambuc /* Add the text BMP string Domaincontroller to the cert */
1180ebfedea0SLionel Sambuc if (tbs->flags.domaincontroller) {
1181ebfedea0SLionel Sambuc data.data = rk_UNCONST("\x1e\x20\x00\x44\x00\x6f\x00\x6d"
1182ebfedea0SLionel Sambuc "\x00\x61\x00\x69\x00\x6e\x00\x43"
1183ebfedea0SLionel Sambuc "\x00\x6f\x00\x6e\x00\x74\x00\x72"
1184ebfedea0SLionel Sambuc "\x00\x6f\x00\x6c\x00\x6c\x00\x65"
1185ebfedea0SLionel Sambuc "\x00\x72");
1186ebfedea0SLionel Sambuc data.length = 34;
1187ebfedea0SLionel Sambuc
1188ebfedea0SLionel Sambuc ret = add_extension(context, tbsc, 0,
1189ebfedea0SLionel Sambuc &asn1_oid_id_ms_cert_enroll_domaincontroller,
1190ebfedea0SLionel Sambuc &data);
1191ebfedea0SLionel Sambuc if (ret)
1192ebfedea0SLionel Sambuc goto out;
1193ebfedea0SLionel Sambuc }
1194ebfedea0SLionel Sambuc
1195ebfedea0SLionel Sambuc /* add KeyUsage */
1196ebfedea0SLionel Sambuc {
1197ebfedea0SLionel Sambuc KeyUsage ku;
1198ebfedea0SLionel Sambuc
1199ebfedea0SLionel Sambuc ku = int2KeyUsage(key_usage);
1200ebfedea0SLionel Sambuc ASN1_MALLOC_ENCODE(KeyUsage, data.data, data.length, &ku, &size, ret);
1201ebfedea0SLionel Sambuc if (ret) {
1202ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
1203ebfedea0SLionel Sambuc goto out;
1204ebfedea0SLionel Sambuc }
1205ebfedea0SLionel Sambuc if (size != data.length)
1206ebfedea0SLionel Sambuc _hx509_abort("internal ASN.1 encoder error");
1207ebfedea0SLionel Sambuc ret = add_extension(context, tbsc, 1,
1208ebfedea0SLionel Sambuc &asn1_oid_id_x509_ce_keyUsage, &data);
1209ebfedea0SLionel Sambuc free(data.data);
1210ebfedea0SLionel Sambuc if (ret)
1211ebfedea0SLionel Sambuc goto out;
1212ebfedea0SLionel Sambuc }
1213ebfedea0SLionel Sambuc
1214ebfedea0SLionel Sambuc /* add ExtendedKeyUsage */
1215ebfedea0SLionel Sambuc if (tbs->eku.len > 0) {
1216ebfedea0SLionel Sambuc ASN1_MALLOC_ENCODE(ExtKeyUsage, data.data, data.length,
1217ebfedea0SLionel Sambuc &tbs->eku, &size, ret);
1218ebfedea0SLionel Sambuc if (ret) {
1219ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
1220ebfedea0SLionel Sambuc goto out;
1221ebfedea0SLionel Sambuc }
1222ebfedea0SLionel Sambuc if (size != data.length)
1223ebfedea0SLionel Sambuc _hx509_abort("internal ASN.1 encoder error");
1224ebfedea0SLionel Sambuc ret = add_extension(context, tbsc, 0,
1225ebfedea0SLionel Sambuc &asn1_oid_id_x509_ce_extKeyUsage, &data);
1226ebfedea0SLionel Sambuc free(data.data);
1227ebfedea0SLionel Sambuc if (ret)
1228ebfedea0SLionel Sambuc goto out;
1229ebfedea0SLionel Sambuc }
1230ebfedea0SLionel Sambuc
1231ebfedea0SLionel Sambuc /* add Subject Alternative Name */
1232ebfedea0SLionel Sambuc if (tbs->san.len > 0) {
1233ebfedea0SLionel Sambuc ASN1_MALLOC_ENCODE(GeneralNames, data.data, data.length,
1234ebfedea0SLionel Sambuc &tbs->san, &size, ret);
1235ebfedea0SLionel Sambuc if (ret) {
1236ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
1237ebfedea0SLionel Sambuc goto out;
1238ebfedea0SLionel Sambuc }
1239ebfedea0SLionel Sambuc if (size != data.length)
1240ebfedea0SLionel Sambuc _hx509_abort("internal ASN.1 encoder error");
1241ebfedea0SLionel Sambuc ret = add_extension(context, tbsc, 0,
1242ebfedea0SLionel Sambuc &asn1_oid_id_x509_ce_subjectAltName,
1243ebfedea0SLionel Sambuc &data);
1244ebfedea0SLionel Sambuc free(data.data);
1245ebfedea0SLionel Sambuc if (ret)
1246ebfedea0SLionel Sambuc goto out;
1247ebfedea0SLionel Sambuc }
1248ebfedea0SLionel Sambuc
1249ebfedea0SLionel Sambuc /* Add Authority Key Identifier */
1250ebfedea0SLionel Sambuc if (ai) {
1251ebfedea0SLionel Sambuc ASN1_MALLOC_ENCODE(AuthorityKeyIdentifier, data.data, data.length,
1252ebfedea0SLionel Sambuc ai, &size, ret);
1253ebfedea0SLionel Sambuc if (ret) {
1254ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
1255ebfedea0SLionel Sambuc goto out;
1256ebfedea0SLionel Sambuc }
1257ebfedea0SLionel Sambuc if (size != data.length)
1258ebfedea0SLionel Sambuc _hx509_abort("internal ASN.1 encoder error");
1259ebfedea0SLionel Sambuc ret = add_extension(context, tbsc, 0,
1260ebfedea0SLionel Sambuc &asn1_oid_id_x509_ce_authorityKeyIdentifier,
1261ebfedea0SLionel Sambuc &data);
1262ebfedea0SLionel Sambuc free(data.data);
1263ebfedea0SLionel Sambuc if (ret)
1264ebfedea0SLionel Sambuc goto out;
1265ebfedea0SLionel Sambuc }
1266ebfedea0SLionel Sambuc
1267ebfedea0SLionel Sambuc /* Add Subject Key Identifier */
1268ebfedea0SLionel Sambuc {
1269ebfedea0SLionel Sambuc SubjectKeyIdentifier si;
1270ebfedea0SLionel Sambuc unsigned char hash[SHA_DIGEST_LENGTH];
1271ebfedea0SLionel Sambuc
1272ebfedea0SLionel Sambuc {
1273ebfedea0SLionel Sambuc EVP_MD_CTX *ctx;
1274ebfedea0SLionel Sambuc
1275ebfedea0SLionel Sambuc ctx = EVP_MD_CTX_create();
1276ebfedea0SLionel Sambuc EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
1277ebfedea0SLionel Sambuc EVP_DigestUpdate(ctx, tbs->spki.subjectPublicKey.data,
1278ebfedea0SLionel Sambuc tbs->spki.subjectPublicKey.length / 8);
1279ebfedea0SLionel Sambuc EVP_DigestFinal_ex(ctx, hash, NULL);
1280ebfedea0SLionel Sambuc EVP_MD_CTX_destroy(ctx);
1281ebfedea0SLionel Sambuc }
1282ebfedea0SLionel Sambuc
1283ebfedea0SLionel Sambuc si.data = hash;
1284ebfedea0SLionel Sambuc si.length = sizeof(hash);
1285ebfedea0SLionel Sambuc
1286ebfedea0SLionel Sambuc ASN1_MALLOC_ENCODE(SubjectKeyIdentifier, data.data, data.length,
1287ebfedea0SLionel Sambuc &si, &size, ret);
1288ebfedea0SLionel Sambuc if (ret) {
1289ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
1290ebfedea0SLionel Sambuc goto out;
1291ebfedea0SLionel Sambuc }
1292ebfedea0SLionel Sambuc if (size != data.length)
1293ebfedea0SLionel Sambuc _hx509_abort("internal ASN.1 encoder error");
1294ebfedea0SLionel Sambuc ret = add_extension(context, tbsc, 0,
1295ebfedea0SLionel Sambuc &asn1_oid_id_x509_ce_subjectKeyIdentifier,
1296ebfedea0SLionel Sambuc &data);
1297ebfedea0SLionel Sambuc free(data.data);
1298ebfedea0SLionel Sambuc if (ret)
1299ebfedea0SLionel Sambuc goto out;
1300ebfedea0SLionel Sambuc }
1301ebfedea0SLionel Sambuc
1302ebfedea0SLionel Sambuc /* Add BasicConstraints */
1303ebfedea0SLionel Sambuc {
1304ebfedea0SLionel Sambuc BasicConstraints bc;
1305ebfedea0SLionel Sambuc int aCA = 1;
1306ebfedea0SLionel Sambuc unsigned int path;
1307ebfedea0SLionel Sambuc
1308ebfedea0SLionel Sambuc memset(&bc, 0, sizeof(bc));
1309ebfedea0SLionel Sambuc
1310ebfedea0SLionel Sambuc if (tbs->flags.ca) {
1311ebfedea0SLionel Sambuc bc.cA = &aCA;
1312ebfedea0SLionel Sambuc if (tbs->pathLenConstraint >= 0) {
1313ebfedea0SLionel Sambuc path = tbs->pathLenConstraint;
1314ebfedea0SLionel Sambuc bc.pathLenConstraint = &path;
1315ebfedea0SLionel Sambuc }
1316ebfedea0SLionel Sambuc }
1317ebfedea0SLionel Sambuc
1318ebfedea0SLionel Sambuc ASN1_MALLOC_ENCODE(BasicConstraints, data.data, data.length,
1319ebfedea0SLionel Sambuc &bc, &size, ret);
1320ebfedea0SLionel Sambuc if (ret) {
1321ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
1322ebfedea0SLionel Sambuc goto out;
1323ebfedea0SLionel Sambuc }
1324ebfedea0SLionel Sambuc if (size != data.length)
1325ebfedea0SLionel Sambuc _hx509_abort("internal ASN.1 encoder error");
1326ebfedea0SLionel Sambuc /* Critical if this is a CA */
1327ebfedea0SLionel Sambuc ret = add_extension(context, tbsc, tbs->flags.ca,
1328ebfedea0SLionel Sambuc &asn1_oid_id_x509_ce_basicConstraints,
1329ebfedea0SLionel Sambuc &data);
1330ebfedea0SLionel Sambuc free(data.data);
1331ebfedea0SLionel Sambuc if (ret)
1332ebfedea0SLionel Sambuc goto out;
1333ebfedea0SLionel Sambuc }
1334ebfedea0SLionel Sambuc
1335ebfedea0SLionel Sambuc /* add Proxy */
1336ebfedea0SLionel Sambuc if (tbs->flags.proxy) {
1337ebfedea0SLionel Sambuc ProxyCertInfo info;
1338ebfedea0SLionel Sambuc
1339ebfedea0SLionel Sambuc memset(&info, 0, sizeof(info));
1340ebfedea0SLionel Sambuc
1341ebfedea0SLionel Sambuc if (tbs->pathLenConstraint >= 0) {
1342ebfedea0SLionel Sambuc info.pCPathLenConstraint =
1343ebfedea0SLionel Sambuc malloc(sizeof(*info.pCPathLenConstraint));
1344ebfedea0SLionel Sambuc if (info.pCPathLenConstraint == NULL) {
1345ebfedea0SLionel Sambuc ret = ENOMEM;
1346ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
1347ebfedea0SLionel Sambuc goto out;
1348ebfedea0SLionel Sambuc }
1349ebfedea0SLionel Sambuc *info.pCPathLenConstraint = tbs->pathLenConstraint;
1350ebfedea0SLionel Sambuc }
1351ebfedea0SLionel Sambuc
1352ebfedea0SLionel Sambuc ret = der_copy_oid(&asn1_oid_id_pkix_ppl_inheritAll,
1353ebfedea0SLionel Sambuc &info.proxyPolicy.policyLanguage);
1354ebfedea0SLionel Sambuc if (ret) {
1355ebfedea0SLionel Sambuc free_ProxyCertInfo(&info);
1356ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
1357ebfedea0SLionel Sambuc goto out;
1358ebfedea0SLionel Sambuc }
1359ebfedea0SLionel Sambuc
1360ebfedea0SLionel Sambuc ASN1_MALLOC_ENCODE(ProxyCertInfo, data.data, data.length,
1361ebfedea0SLionel Sambuc &info, &size, ret);
1362ebfedea0SLionel Sambuc free_ProxyCertInfo(&info);
1363ebfedea0SLionel Sambuc if (ret) {
1364ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
1365ebfedea0SLionel Sambuc goto out;
1366ebfedea0SLionel Sambuc }
1367ebfedea0SLionel Sambuc if (size != data.length)
1368ebfedea0SLionel Sambuc _hx509_abort("internal ASN.1 encoder error");
1369ebfedea0SLionel Sambuc ret = add_extension(context, tbsc, 0,
1370ebfedea0SLionel Sambuc &asn1_oid_id_pkix_pe_proxyCertInfo,
1371ebfedea0SLionel Sambuc &data);
1372ebfedea0SLionel Sambuc free(data.data);
1373ebfedea0SLionel Sambuc if (ret)
1374ebfedea0SLionel Sambuc goto out;
1375ebfedea0SLionel Sambuc }
1376ebfedea0SLionel Sambuc
1377ebfedea0SLionel Sambuc if (tbs->crldp.len) {
1378ebfedea0SLionel Sambuc
1379ebfedea0SLionel Sambuc ASN1_MALLOC_ENCODE(CRLDistributionPoints, data.data, data.length,
1380ebfedea0SLionel Sambuc &tbs->crldp, &size, ret);
1381ebfedea0SLionel Sambuc if (ret) {
1382ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
1383ebfedea0SLionel Sambuc goto out;
1384ebfedea0SLionel Sambuc }
1385ebfedea0SLionel Sambuc if (size != data.length)
1386ebfedea0SLionel Sambuc _hx509_abort("internal ASN.1 encoder error");
1387ebfedea0SLionel Sambuc ret = add_extension(context, tbsc, FALSE,
1388ebfedea0SLionel Sambuc &asn1_oid_id_x509_ce_cRLDistributionPoints,
1389ebfedea0SLionel Sambuc &data);
1390ebfedea0SLionel Sambuc free(data.data);
1391ebfedea0SLionel Sambuc if (ret)
1392ebfedea0SLionel Sambuc goto out;
1393ebfedea0SLionel Sambuc }
1394ebfedea0SLionel Sambuc
1395ebfedea0SLionel Sambuc ASN1_MALLOC_ENCODE(TBSCertificate, data.data, data.length,tbsc, &size, ret);
1396ebfedea0SLionel Sambuc if (ret) {
1397ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "malloc out of memory");
1398ebfedea0SLionel Sambuc goto out;
1399ebfedea0SLionel Sambuc }
1400ebfedea0SLionel Sambuc if (data.length != size)
1401ebfedea0SLionel Sambuc _hx509_abort("internal ASN.1 encoder error");
1402ebfedea0SLionel Sambuc
1403ebfedea0SLionel Sambuc ret = _hx509_create_signature_bitstring(context,
1404ebfedea0SLionel Sambuc signer,
1405ebfedea0SLionel Sambuc sigalg,
1406ebfedea0SLionel Sambuc &data,
1407ebfedea0SLionel Sambuc &c.signatureAlgorithm,
1408ebfedea0SLionel Sambuc &c.signatureValue);
1409ebfedea0SLionel Sambuc free(data.data);
1410ebfedea0SLionel Sambuc if (ret)
1411ebfedea0SLionel Sambuc goto out;
1412ebfedea0SLionel Sambuc
1413ebfedea0SLionel Sambuc ret = hx509_cert_init(context, &c, certificate);
1414ebfedea0SLionel Sambuc if (ret)
1415ebfedea0SLionel Sambuc goto out;
1416ebfedea0SLionel Sambuc
1417ebfedea0SLionel Sambuc free_Certificate(&c);
1418ebfedea0SLionel Sambuc
1419ebfedea0SLionel Sambuc return 0;
1420ebfedea0SLionel Sambuc
1421ebfedea0SLionel Sambuc out:
1422ebfedea0SLionel Sambuc free_Certificate(&c);
1423ebfedea0SLionel Sambuc return ret;
1424ebfedea0SLionel Sambuc }
1425ebfedea0SLionel Sambuc
1426ebfedea0SLionel Sambuc static int
get_AuthorityKeyIdentifier(hx509_context context,const Certificate * certificate,AuthorityKeyIdentifier * ai)1427ebfedea0SLionel Sambuc get_AuthorityKeyIdentifier(hx509_context context,
1428ebfedea0SLionel Sambuc const Certificate *certificate,
1429ebfedea0SLionel Sambuc AuthorityKeyIdentifier *ai)
1430ebfedea0SLionel Sambuc {
1431ebfedea0SLionel Sambuc SubjectKeyIdentifier si;
1432ebfedea0SLionel Sambuc int ret;
1433ebfedea0SLionel Sambuc
1434ebfedea0SLionel Sambuc ret = _hx509_find_extension_subject_key_id(certificate, &si);
1435ebfedea0SLionel Sambuc if (ret == 0) {
1436ebfedea0SLionel Sambuc ai->keyIdentifier = calloc(1, sizeof(*ai->keyIdentifier));
1437ebfedea0SLionel Sambuc if (ai->keyIdentifier == NULL) {
1438ebfedea0SLionel Sambuc free_SubjectKeyIdentifier(&si);
1439ebfedea0SLionel Sambuc ret = ENOMEM;
1440ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
1441ebfedea0SLionel Sambuc goto out;
1442ebfedea0SLionel Sambuc }
1443ebfedea0SLionel Sambuc ret = der_copy_octet_string(&si, ai->keyIdentifier);
1444ebfedea0SLionel Sambuc free_SubjectKeyIdentifier(&si);
1445ebfedea0SLionel Sambuc if (ret) {
1446ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
1447ebfedea0SLionel Sambuc goto out;
1448ebfedea0SLionel Sambuc }
1449ebfedea0SLionel Sambuc } else {
1450ebfedea0SLionel Sambuc GeneralNames gns;
1451ebfedea0SLionel Sambuc GeneralName gn;
1452ebfedea0SLionel Sambuc Name name;
1453ebfedea0SLionel Sambuc
1454ebfedea0SLionel Sambuc memset(&gn, 0, sizeof(gn));
1455ebfedea0SLionel Sambuc memset(&gns, 0, sizeof(gns));
1456ebfedea0SLionel Sambuc memset(&name, 0, sizeof(name));
1457ebfedea0SLionel Sambuc
1458ebfedea0SLionel Sambuc ai->authorityCertIssuer =
1459ebfedea0SLionel Sambuc calloc(1, sizeof(*ai->authorityCertIssuer));
1460ebfedea0SLionel Sambuc if (ai->authorityCertIssuer == NULL) {
1461ebfedea0SLionel Sambuc ret = ENOMEM;
1462ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
1463ebfedea0SLionel Sambuc goto out;
1464ebfedea0SLionel Sambuc }
1465ebfedea0SLionel Sambuc ai->authorityCertSerialNumber =
1466ebfedea0SLionel Sambuc calloc(1, sizeof(*ai->authorityCertSerialNumber));
1467ebfedea0SLionel Sambuc if (ai->authorityCertSerialNumber == NULL) {
1468ebfedea0SLionel Sambuc ret = ENOMEM;
1469ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
1470ebfedea0SLionel Sambuc goto out;
1471ebfedea0SLionel Sambuc }
1472ebfedea0SLionel Sambuc
1473ebfedea0SLionel Sambuc /*
1474ebfedea0SLionel Sambuc * XXX unbreak when asn1 compiler handle IMPLICIT
1475ebfedea0SLionel Sambuc *
1476ebfedea0SLionel Sambuc * This is so horrible.
1477ebfedea0SLionel Sambuc */
1478ebfedea0SLionel Sambuc
1479ebfedea0SLionel Sambuc ret = copy_Name(&certificate->tbsCertificate.subject, &name);
1480ebfedea0SLionel Sambuc if (ret) {
1481ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
1482ebfedea0SLionel Sambuc goto out;
1483ebfedea0SLionel Sambuc }
1484ebfedea0SLionel Sambuc
1485ebfedea0SLionel Sambuc memset(&gn, 0, sizeof(gn));
1486ebfedea0SLionel Sambuc gn.element = choice_GeneralName_directoryName;
1487ebfedea0SLionel Sambuc gn.u.directoryName.element =
1488ebfedea0SLionel Sambuc choice_GeneralName_directoryName_rdnSequence;
1489ebfedea0SLionel Sambuc gn.u.directoryName.u.rdnSequence = name.u.rdnSequence;
1490ebfedea0SLionel Sambuc
1491ebfedea0SLionel Sambuc ret = add_GeneralNames(&gns, &gn);
1492ebfedea0SLionel Sambuc if (ret) {
1493ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
1494ebfedea0SLionel Sambuc goto out;
1495ebfedea0SLionel Sambuc }
1496ebfedea0SLionel Sambuc
1497ebfedea0SLionel Sambuc ai->authorityCertIssuer->val = gns.val;
1498ebfedea0SLionel Sambuc ai->authorityCertIssuer->len = gns.len;
1499ebfedea0SLionel Sambuc
1500ebfedea0SLionel Sambuc ret = der_copy_heim_integer(&certificate->tbsCertificate.serialNumber,
1501ebfedea0SLionel Sambuc ai->authorityCertSerialNumber);
1502ebfedea0SLionel Sambuc if (ai->authorityCertSerialNumber == NULL) {
1503ebfedea0SLionel Sambuc ret = ENOMEM;
1504ebfedea0SLionel Sambuc hx509_set_error_string(context, 0, ret, "Out of memory");
1505ebfedea0SLionel Sambuc goto out;
1506ebfedea0SLionel Sambuc }
1507ebfedea0SLionel Sambuc }
1508ebfedea0SLionel Sambuc out:
1509ebfedea0SLionel Sambuc if (ret)
1510ebfedea0SLionel Sambuc free_AuthorityKeyIdentifier(ai);
1511ebfedea0SLionel Sambuc return ret;
1512ebfedea0SLionel Sambuc }
1513ebfedea0SLionel Sambuc
1514ebfedea0SLionel Sambuc
1515ebfedea0SLionel Sambuc /**
1516ebfedea0SLionel Sambuc * Sign a to-be-signed certificate object with a issuer certificate.
1517ebfedea0SLionel Sambuc *
1518ebfedea0SLionel Sambuc * The caller needs to at least have called the following functions on the
1519ebfedea0SLionel Sambuc * to-be-signed certificate object:
1520ebfedea0SLionel Sambuc * - hx509_ca_tbs_init()
1521ebfedea0SLionel Sambuc * - hx509_ca_tbs_set_subject()
1522ebfedea0SLionel Sambuc * - hx509_ca_tbs_set_spki()
1523ebfedea0SLionel Sambuc *
1524ebfedea0SLionel Sambuc * When done the to-be-signed certificate object should be freed with
1525ebfedea0SLionel Sambuc * hx509_ca_tbs_free().
1526ebfedea0SLionel Sambuc *
1527ebfedea0SLionel Sambuc * When creating self-signed certificate use hx509_ca_sign_self() instead.
1528ebfedea0SLionel Sambuc *
1529ebfedea0SLionel Sambuc * @param context A hx509 context.
1530ebfedea0SLionel Sambuc * @param tbs object to be signed.
1531ebfedea0SLionel Sambuc * @param signer the CA certificate object to sign with (need private key).
1532ebfedea0SLionel Sambuc * @param certificate return cerificate, free with hx509_cert_free().
1533ebfedea0SLionel Sambuc *
1534ebfedea0SLionel Sambuc * @return An hx509 error code, see hx509_get_error_string().
1535ebfedea0SLionel Sambuc *
1536ebfedea0SLionel Sambuc * @ingroup hx509_ca
1537ebfedea0SLionel Sambuc */
1538ebfedea0SLionel Sambuc
1539ebfedea0SLionel Sambuc int
hx509_ca_sign(hx509_context context,hx509_ca_tbs tbs,hx509_cert signer,hx509_cert * certificate)1540ebfedea0SLionel Sambuc hx509_ca_sign(hx509_context context,
1541ebfedea0SLionel Sambuc hx509_ca_tbs tbs,
1542ebfedea0SLionel Sambuc hx509_cert signer,
1543ebfedea0SLionel Sambuc hx509_cert *certificate)
1544ebfedea0SLionel Sambuc {
1545ebfedea0SLionel Sambuc const Certificate *signer_cert;
1546ebfedea0SLionel Sambuc AuthorityKeyIdentifier ai;
1547ebfedea0SLionel Sambuc int ret;
1548ebfedea0SLionel Sambuc
1549ebfedea0SLionel Sambuc memset(&ai, 0, sizeof(ai));
1550ebfedea0SLionel Sambuc
1551ebfedea0SLionel Sambuc signer_cert = _hx509_get_cert(signer);
1552ebfedea0SLionel Sambuc
1553ebfedea0SLionel Sambuc ret = get_AuthorityKeyIdentifier(context, signer_cert, &ai);
1554ebfedea0SLionel Sambuc if (ret)
1555ebfedea0SLionel Sambuc goto out;
1556ebfedea0SLionel Sambuc
1557ebfedea0SLionel Sambuc ret = ca_sign(context,
1558ebfedea0SLionel Sambuc tbs,
1559ebfedea0SLionel Sambuc _hx509_cert_private_key(signer),
1560ebfedea0SLionel Sambuc &ai,
1561ebfedea0SLionel Sambuc &signer_cert->tbsCertificate.subject,
1562ebfedea0SLionel Sambuc certificate);
1563ebfedea0SLionel Sambuc
1564ebfedea0SLionel Sambuc out:
1565ebfedea0SLionel Sambuc free_AuthorityKeyIdentifier(&ai);
1566ebfedea0SLionel Sambuc
1567ebfedea0SLionel Sambuc return ret;
1568ebfedea0SLionel Sambuc }
1569ebfedea0SLionel Sambuc
1570ebfedea0SLionel Sambuc /**
1571ebfedea0SLionel Sambuc * Work just like hx509_ca_sign() but signs it-self.
1572ebfedea0SLionel Sambuc *
1573ebfedea0SLionel Sambuc * @param context A hx509 context.
1574ebfedea0SLionel Sambuc * @param tbs object to be signed.
1575ebfedea0SLionel Sambuc * @param signer private key to sign with.
1576ebfedea0SLionel Sambuc * @param certificate return cerificate, free with hx509_cert_free().
1577ebfedea0SLionel Sambuc *
1578ebfedea0SLionel Sambuc * @return An hx509 error code, see hx509_get_error_string().
1579ebfedea0SLionel Sambuc *
1580ebfedea0SLionel Sambuc * @ingroup hx509_ca
1581ebfedea0SLionel Sambuc */
1582ebfedea0SLionel Sambuc
1583ebfedea0SLionel Sambuc int
hx509_ca_sign_self(hx509_context context,hx509_ca_tbs tbs,hx509_private_key signer,hx509_cert * certificate)1584ebfedea0SLionel Sambuc hx509_ca_sign_self(hx509_context context,
1585ebfedea0SLionel Sambuc hx509_ca_tbs tbs,
1586ebfedea0SLionel Sambuc hx509_private_key signer,
1587ebfedea0SLionel Sambuc hx509_cert *certificate)
1588ebfedea0SLionel Sambuc {
1589ebfedea0SLionel Sambuc return ca_sign(context,
1590ebfedea0SLionel Sambuc tbs,
1591ebfedea0SLionel Sambuc signer,
1592ebfedea0SLionel Sambuc NULL,
1593ebfedea0SLionel Sambuc NULL,
1594ebfedea0SLionel Sambuc certificate);
1595ebfedea0SLionel Sambuc }
1596