2 * Copyright (c) 2006 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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
35 #include <pkcs10_asn1.h>
37 struct hx509_request_data
{
39 SubjectPublicKeyInfo key
;
49 _hx509_request_init(hx509_context context
, hx509_request
*req
)
51 *req
= calloc(1, sizeof(**req
));
59 _hx509_request_free(hx509_request
*req
)
62 hx509_name_free(&(*req
)->name
);
63 free_SubjectPublicKeyInfo(&(*req
)->key
);
64 free_ExtKeyUsage(&(*req
)->eku
);
65 free_GeneralNames(&(*req
)->san
);
66 memset(*req
, 0, sizeof(**req
));
72 _hx509_request_set_name(hx509_context context
,
77 hx509_name_free(&req
->name
);
79 int ret
= hx509_name_copy(context
, name
, &req
->name
);
87 _hx509_request_get_name(hx509_context context
,
91 if (req
->name
== NULL
) {
92 hx509_set_error_string(context
, 0, EINVAL
, "Request have no name");
95 return hx509_name_copy(context
, req
->name
, name
);
99 _hx509_request_set_SubjectPublicKeyInfo(hx509_context context
,
101 const SubjectPublicKeyInfo
*key
)
103 free_SubjectPublicKeyInfo(&req
->key
);
104 return copy_SubjectPublicKeyInfo(key
, &req
->key
);
108 _hx509_request_get_SubjectPublicKeyInfo(hx509_context context
,
110 SubjectPublicKeyInfo
*key
)
112 return copy_SubjectPublicKeyInfo(&req
->key
, key
);
116 _hx509_request_add_eku(hx509_context context
,
123 val
= realloc(req
->eku
.val
, sizeof(req
->eku
.val
[0]) * (req
->eku
.len
+ 1));
128 ret
= der_copy_oid(oid
, &req
->eku
.val
[req
->eku
.len
]);
138 _hx509_request_add_dns_name(hx509_context context
,
140 const char *hostname
)
144 memset(&name
, 0, sizeof(name
));
145 name
.element
= choice_GeneralName_dNSName
;
146 name
.u
.dNSName
= rk_UNCONST(hostname
);
148 return add_GeneralNames(&req
->san
, &name
);
152 _hx509_request_add_email(hx509_context context
,
158 memset(&name
, 0, sizeof(name
));
159 name
.element
= choice_GeneralName_rfc822Name
;
160 name
.u
.dNSName
= rk_UNCONST(email
);
162 return add_GeneralNames(&req
->san
, &name
);
168 _hx509_request_to_pkcs10(hx509_context context
,
169 const hx509_request req
,
170 const hx509_private_key signer
,
171 heim_octet_string
*request
)
173 CertificationRequest r
;
174 heim_octet_string data
, os
;
178 if (req
->name
== NULL
) {
179 hx509_set_error_string(context
, 0, EINVAL
,
180 "PKCS10 needs to have a subject");
184 memset(&r
, 0, sizeof(r
));
185 memset(request
, 0, sizeof(*request
));
187 r
.certificationRequestInfo
.version
= pkcs10_v1
;
189 ret
= copy_Name(&req
->name
->der_name
,
190 &r
.certificationRequestInfo
.subject
);
193 ret
= copy_SubjectPublicKeyInfo(&req
->key
,
194 &r
.certificationRequestInfo
.subjectPKInfo
);
197 r
.certificationRequestInfo
.attributes
=
198 calloc(1, sizeof(*r
.certificationRequestInfo
.attributes
));
199 if (r
.certificationRequestInfo
.attributes
== NULL
) {
204 ASN1_MALLOC_ENCODE(CertificationRequestInfo
, data
.data
, data
.length
,
205 &r
.certificationRequestInfo
, &size
, ret
);
208 if (data
.length
!= size
)
211 ret
= _hx509_create_signature(context
,
213 _hx509_crypto_default_sig_alg
,
215 &r
.signatureAlgorithm
,
220 r
.signature
.data
= os
.data
;
221 r
.signature
.length
= os
.length
* 8;
223 ASN1_MALLOC_ENCODE(CertificationRequest
, data
.data
, data
.length
,
227 if (data
.length
!= size
)
233 free_CertificationRequest(&r
);
239 _hx509_request_parse(hx509_context context
,
243 CertificationRequest r
;
244 CertificationRequestInfo
*rinfo
;
250 if (strncmp(path
, "PKCS10:", 7) != 0) {
251 hx509_set_error_string(context
, 0, HX509_UNSUPPORTED_OPERATION
,
252 "unsupport type in %s", path
);
253 return HX509_UNSUPPORTED_OPERATION
;
257 /* XXX PEM request */
259 ret
= rk_undumpdata(path
, &p
, &len
);
261 hx509_set_error_string(context
, 0, ret
, "Failed to map file %s", path
);
265 ret
= decode_CertificationRequest(p
, len
, &r
, &size
);
268 hx509_set_error_string(context
, 0, ret
, "Failed to decode %s", path
);
272 ret
= _hx509_request_init(context
, req
);
274 free_CertificationRequest(&r
);
278 rinfo
= &r
.certificationRequestInfo
;
280 ret
= _hx509_request_set_SubjectPublicKeyInfo(context
, *req
,
281 &rinfo
->subjectPKInfo
);
283 free_CertificationRequest(&r
);
284 _hx509_request_free(req
);
288 ret
= _hx509_name_from_Name(&rinfo
->subject
, &subject
);
290 free_CertificationRequest(&r
);
291 _hx509_request_free(req
);
294 ret
= _hx509_request_set_name(context
, *req
, subject
);
295 hx509_name_free(&subject
);
296 free_CertificationRequest(&r
);
298 _hx509_request_free(req
);
307 _hx509_request_print(hx509_context context
, hx509_request req
, FILE *f
)
313 ret
= hx509_name_to_string(req
->name
, &subject
);
315 hx509_set_error_string(context
, 0, ret
, "Failed to print name");
318 fprintf(f
, "name: %s\n", subject
);