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 typedef struct abitstring_s
{
42 struct hx509_request_data
{
43 hx509_context context
;
45 SubjectPublicKeyInfo key
;
49 struct abitstring_s authorized_EKUs
;
50 struct abitstring_s authorized_SANs
;
51 uint32_t nunsupported
; /* Count of unsupported features requested */
52 uint32_t nauthorized
; /* Count of supported features authorized */
53 uint32_t ku_are_authorized
:1;
57 * Allocate and initialize an hx509_request structure representing a PKCS#10
58 * certificate signing request.
60 * @param context An hx509 context.
61 * @param req Where to put the new hx509_request object.
63 * @return An hx509 error code, see hx509_get_error_string().
65 * @ingroup hx509_request
67 HX509_LIB_FUNCTION
int HX509_LIB_CALL
68 hx509_request_init(hx509_context context
, hx509_request
*req
)
70 *req
= calloc(1, sizeof(**req
));
74 (*req
)->context
= context
;
79 * Free a certificate signing request object.
81 * @param req A pointer to the hx509_request to free.
83 * @ingroup hx509_request
85 HX509_LIB_FUNCTION
void HX509_LIB_CALL
86 hx509_request_free(hx509_request
*reqp
)
88 hx509_request req
= *reqp
;
94 hx509_name_free(&req
->name
);
95 free(req
->authorized_EKUs
.feats
);
96 free(req
->authorized_SANs
.feats
);
97 free_SubjectPublicKeyInfo(&req
->key
);
98 free_ExtKeyUsage(&req
->eku
);
99 free_GeneralNames(&req
->san
);
100 memset(req
, 0, sizeof(*req
));
105 * Set the subjectName of the CSR.
107 * @param context An hx509 context.
108 * @param req The hx509_request to alter.
109 * @param name The subjectName.
111 * @return An hx509 error code, see hx509_get_error_string().
113 * @ingroup hx509_request
115 HX509_LIB_FUNCTION
int HX509_LIB_CALL
116 hx509_request_set_name(hx509_context context
,
121 hx509_name_free(&req
->name
);
123 int ret
= hx509_name_copy(context
, name
, &req
->name
);
131 * Get the subject name requested by a CSR.
133 * @param context An hx509 context.
134 * @param req The hx509_request object.
135 * @param name Where to put the name.
137 * @return An hx509 error code, see hx509_get_error_string().
139 * @ingroup hx509_request
141 HX509_LIB_FUNCTION
int HX509_LIB_CALL
142 hx509_request_get_name(hx509_context context
,
146 if (req
->name
== NULL
) {
147 hx509_set_error_string(context
, 0, EINVAL
, "Request have no name");
150 return hx509_name_copy(context
, req
->name
, name
);
154 * Set the subject public key requested by a CSR.
156 * @param context An hx509 context.
157 * @param req The hx509_request object.
158 * @param key The public key.
160 * @return An hx509 error code, see hx509_get_error_string().
162 * @ingroup hx509_request
164 HX509_LIB_FUNCTION
int HX509_LIB_CALL
165 hx509_request_set_SubjectPublicKeyInfo(hx509_context context
,
167 const SubjectPublicKeyInfo
*key
)
169 free_SubjectPublicKeyInfo(&req
->key
);
170 return copy_SubjectPublicKeyInfo(key
, &req
->key
);
174 * Get the subject public key requested by a CSR.
176 * @param context An hx509 context.
177 * @param req The hx509_request object.
178 * @param key Where to put the key.
180 * @return An hx509 error code, see hx509_get_error_string().
182 * @ingroup hx509_request
184 HX509_LIB_FUNCTION
int HX509_LIB_CALL
185 hx509_request_get_SubjectPublicKeyInfo(hx509_context context
,
187 SubjectPublicKeyInfo
*key
)
189 return copy_SubjectPublicKeyInfo(&req
->key
, key
);
193 * Set the key usage requested by a CSR.
195 * @param context An hx509 context.
196 * @param req The hx509_request object.
197 * @param ku The key usage.
199 * @return An hx509 error code, see hx509_get_error_string().
201 * @ingroup hx509_request
203 HX509_LIB_FUNCTION
int HX509_LIB_CALL
204 hx509_request_set_ku(hx509_context context
, hx509_request req
, KeyUsage ku
)
206 uint64_t n
= KeyUsage2int(ku
);
208 if ((KeyUsage2int(req
->ku
) & n
) != n
)
209 req
->ku_are_authorized
= 0;
215 * Get the key usage requested by a CSR.
217 * @param context An hx509 context.
218 * @param req The hx509_request object.
219 * @param ku Where to put the key usage.
221 * @return An hx509 error code, see hx509_get_error_string().
223 * @ingroup hx509_request
225 HX509_LIB_FUNCTION
int HX509_LIB_CALL
226 hx509_request_get_ku(hx509_context context
, hx509_request req
, KeyUsage
*ku
)
233 * Add an extended key usage OID to a CSR.
235 * @param context An hx509 context.
236 * @param req The hx509_request object.
237 * @param oid The EKU OID.
239 * @return An hx509 error code, see hx509_get_error_string().
241 * @ingroup hx509_request
243 HX509_LIB_FUNCTION
int HX509_LIB_CALL
244 hx509_request_add_eku(hx509_context context
,
251 val
= realloc(req
->eku
.val
, sizeof(req
->eku
.val
[0]) * (req
->eku
.len
+ 1));
256 ret
= der_copy_oid(oid
, &req
->eku
.val
[req
->eku
.len
]);
266 * Add a GeneralName (Jabber ID) subject alternative name to a CSR.
268 * XXX Make this take a heim_octet_string, not a GeneralName*.
270 * @param context An hx509 context.
271 * @param req The hx509_request object.
272 * @param gn The GeneralName object.
274 * @return An hx509 error code, see hx509_get_error_string().
276 * @ingroup hx509_request
278 HX509_LIB_FUNCTION
int HX509_LIB_CALL
279 hx509_request_add_GeneralName(hx509_context context
,
281 const GeneralName
*gn
)
283 return add_GeneralNames(&req
->san
, gn
);
287 add_utf8_other_san(hx509_context context
,
292 const PKIXXmppAddr us
= (const PKIXXmppAddr
)(uintptr_t)s
;
297 gn
.element
= choice_GeneralName_otherName
;
298 gn
.u
.otherName
.type_id
.length
= 0;
299 gn
.u
.otherName
.type_id
.components
= 0;
300 gn
.u
.otherName
.value
.data
= NULL
;
301 gn
.u
.otherName
.value
.length
= 0;
302 ret
= der_copy_oid(oid
, &gn
.u
.otherName
.type_id
);
304 ASN1_MALLOC_ENCODE(PKIXXmppAddr
, gn
.u
.otherName
.value
.data
,
305 gn
.u
.otherName
.value
.length
, &us
, &size
, ret
);
306 if (ret
== 0 && size
!= gn
.u
.otherName
.value
.length
)
307 _hx509_abort("internal ASN.1 encoder error");
309 ret
= add_GeneralNames(gns
, &gn
);
310 free_GeneralName(&gn
);
312 hx509_set_error_string(context
, 0, ret
, "Out of memory");
317 * Add an xmppAddr (Jabber ID) subject alternative name to a CSR.
319 * @param context An hx509 context.
320 * @param req The hx509_request object.
321 * @param jid The XMPP address.
323 * @return An hx509 error code, see hx509_get_error_string().
325 * @ingroup hx509_request
327 HX509_LIB_FUNCTION
int HX509_LIB_CALL
328 hx509_request_add_xmpp_name(hx509_context context
,
332 return add_utf8_other_san(context
, &req
->san
,
333 &asn1_oid_id_pkix_on_xmppAddr
, jid
);
337 * Add a Microsoft UPN subject alternative name to a CSR.
339 * @param context An hx509 context.
340 * @param req The hx509_request object.
341 * @param hostname The XMPP address.
343 * @return An hx509 error code, see hx509_get_error_string().
345 * @ingroup hx509_request
347 HX509_LIB_FUNCTION
int HX509_LIB_CALL
348 hx509_request_add_ms_upn_name(hx509_context context
,
352 return add_utf8_other_san(context
, &req
->san
, &asn1_oid_id_pkinit_ms_san
,
357 * Add a dNSName (hostname) subject alternative name to a CSR.
359 * @param context An hx509 context.
360 * @param req The hx509_request object.
361 * @param hostname The fully-qualified hostname.
363 * @return An hx509 error code, see hx509_get_error_string().
365 * @ingroup hx509_request
367 HX509_LIB_FUNCTION
int HX509_LIB_CALL
368 hx509_request_add_dns_name(hx509_context context
,
370 const char *hostname
)
374 memset(&name
, 0, sizeof(name
));
375 name
.element
= choice_GeneralName_dNSName
;
376 name
.u
.dNSName
.data
= rk_UNCONST(hostname
);
377 name
.u
.dNSName
.length
= strlen(hostname
);
379 return add_GeneralNames(&req
->san
, &name
);
383 * Add a dnsSRV (_service.hostname) subject alternative name to a CSR.
385 * @param context An hx509 context.
386 * @param req The hx509_request object.
387 * @param dnssrv The DNS SRV name.
389 * @return An hx509 error code, see hx509_get_error_string().
391 * @ingroup hx509_request
393 HX509_LIB_FUNCTION
int HX509_LIB_CALL
394 hx509_request_add_dns_srv(hx509_context context
,
403 memset(&n
, 0, sizeof(n
));
404 memset(&gn
, 0, sizeof(gn
));
405 gn
.element
= choice_GeneralName_otherName
;
406 gn
.u
.otherName
.type_id
.length
= 0;
407 gn
.u
.otherName
.type_id
.components
= 0;
408 gn
.u
.otherName
.value
.data
= NULL
;
409 gn
.u
.otherName
.value
.length
= 0;
410 n
.length
= strlen(dnssrv
);
411 n
.data
= (void *)(uintptr_t)dnssrv
;
412 ASN1_MALLOC_ENCODE(SRVName
,
413 gn
.u
.otherName
.value
.data
,
414 gn
.u
.otherName
.value
.length
, &n
, &size
, ret
);
416 ret
= der_copy_oid(&asn1_oid_id_pkix_on_dnsSRV
, &gn
.u
.otherName
.type_id
);
418 ret
= add_GeneralNames(&req
->san
, &gn
);
419 free_GeneralName(&gn
);
424 * Add an rfc822Name (e-mail address) subject alternative name to a CSR.
426 * @param context An hx509 context.
427 * @param req The hx509_request object.
428 * @param email The e-mail address.
430 * @return An hx509 error code, see hx509_get_error_string().
432 * @ingroup hx509_request
434 HX509_LIB_FUNCTION
int HX509_LIB_CALL
435 hx509_request_add_email(hx509_context context
,
441 memset(&name
, 0, sizeof(name
));
442 name
.element
= choice_GeneralName_rfc822Name
;
443 name
.u
.rfc822Name
.data
= rk_UNCONST(email
);
444 name
.u
.rfc822Name
.length
= strlen(email
);
446 return add_GeneralNames(&req
->san
, &name
);
450 * Add a registeredID (OID) subject alternative name to a CSR.
452 * @param context An hx509 context.
453 * @param req The hx509_request object.
454 * @param oid The OID.
456 * @return An hx509 error code, see hx509_get_error_string().
458 * @ingroup hx509_request
460 HX509_LIB_FUNCTION
int HX509_LIB_CALL
461 hx509_request_add_registered(hx509_context context
,
468 memset(&name
, 0, sizeof(name
));
469 name
.element
= choice_GeneralName_registeredID
;
470 ret
= der_copy_oid(oid
, &name
.u
.registeredID
);
473 ret
= add_GeneralNames(&req
->san
, &name
);
474 free_GeneralName(&name
);
479 * Add a Kerberos V5 principal subject alternative name to a CSR.
481 * @param context An hx509 context.
482 * @param req The hx509_request object.
483 * @param princ The Kerberos principal name.
485 * @return An hx509 error code, see hx509_get_error_string().
487 * @ingroup hx509_request
489 HX509_LIB_FUNCTION
int HX509_LIB_CALL
490 hx509_request_add_pkinit(hx509_context context
,
494 KRB5PrincipalName kn
;
498 memset(&kn
, 0, sizeof(kn
));
499 memset(&gn
, 0, sizeof(gn
));
500 gn
.element
= choice_GeneralName_otherName
;
501 gn
.u
.otherName
.type_id
.length
= 0;
502 gn
.u
.otherName
.type_id
.components
= 0;
503 gn
.u
.otherName
.value
.data
= NULL
;
504 gn
.u
.otherName
.value
.length
= 0;
505 ret
= der_copy_oid(&asn1_oid_id_pkinit_san
, &gn
.u
.otherName
.type_id
);
507 ret
= _hx509_make_pkinit_san(context
, princ
, &gn
.u
.otherName
.value
);
509 ret
= add_GeneralNames(&req
->san
, &gn
);
510 free_GeneralName(&gn
);
514 /* XXX Add DNSSRV and other SANs */
517 get_exts(hx509_context context
,
518 const hx509_request req
,
528 if ((ku_num
= KeyUsage2int(req
->ku
))) {
531 memset(&e
, 0, sizeof(e
));
532 /* The critical field needs to be made DEFAULT FALSE... */
535 ASN1_MALLOC_ENCODE(KeyUsage
, e
.extnValue
.data
, e
.extnValue
.length
,
536 &req
->ku
, &size
, ret
);
538 ret
= der_copy_oid(&asn1_oid_id_x509_ce_keyUsage
, &e
.extnID
);
540 ret
= add_Extensions(exts
, &e
);
543 if (ret
== 0 && req
->eku
.len
) {
546 memset(&e
, 0, sizeof(e
));
549 ASN1_MALLOC_ENCODE(ExtKeyUsage
,
550 e
.extnValue
.data
, e
.extnValue
.length
,
551 &req
->eku
, &size
, ret
);
553 ret
= der_copy_oid(&asn1_oid_id_x509_ce_extKeyUsage
, &e
.extnID
);
555 ret
= add_Extensions(exts
, &e
);
558 if (ret
== 0 && req
->san
.len
) {
561 memset(&e
, 0, sizeof(e
));
563 * SANs are critical when the subject Name is empty.
565 * The empty DN check could probably stand to be a function we export.
569 req
->name
->der_name
.element
== choice_Name_rdnSequence
&&
570 req
->name
->der_name
.u
.rdnSequence
.len
== 0)
573 ASN1_MALLOC_ENCODE(GeneralNames
,
574 e
.extnValue
.data
, e
.extnValue
.length
,
578 ret
= der_copy_oid(&asn1_oid_id_x509_ce_subjectAltName
, &e
.extnID
);
580 ret
= add_Extensions(exts
, &e
);
588 * Get the KU/EKUs/SANs set on a request as a DER-encoding of Extensions.
590 * @param context An hx509 context.
591 * @param req The hx509_request object.
592 * @param exts_der Where to put the DER-encoded Extensions.
594 * @return An hx509 error code, see hx509_get_error_string().
596 * @ingroup hx509_request
598 HX509_LIB_FUNCTION
int HX509_LIB_CALL
599 hx509_request_get_exts(hx509_context context
,
600 const hx509_request req
,
601 heim_octet_string
*exts_der
)
607 exts_der
->data
= NULL
;
608 exts_der
->length
= 0;
609 ret
= get_exts(context
, req
, &exts
);
610 if (ret
== 0 && exts
.len
/* Extensions has a min size constraint of 1 */)
611 ASN1_MALLOC_ENCODE(Extensions
, exts_der
->data
, exts_der
->length
,
613 free_Extensions(&exts
);
622 * @param context An hx509 context.
623 * @param req The hx509_request object.
624 * @param signer The private key corresponding to the CSR's subject public key.
625 * @param request Where to put the DER-encoded CSR.
627 * @return An hx509 error code, see hx509_get_error_string().
629 * @ingroup hx509_request
631 HX509_LIB_FUNCTION
int HX509_LIB_CALL
632 hx509_request_to_pkcs10(hx509_context context
,
633 const hx509_request req
,
634 const hx509_private_key signer
,
635 heim_octet_string
*request
)
637 CertificationRequest r
;
639 heim_octet_string data
;
643 request
->data
= NULL
;
649 if (req
->name
== NULL
) {
650 hx509_set_error_string(context
, 0, EINVAL
,
651 "PKCS10 needs to have a subject");
655 memset(&r
, 0, sizeof(r
));
658 r
.certificationRequestInfo
.version
= pkcs10_v1
;
659 ret
= copy_Name(&req
->name
->der_name
,
660 &r
.certificationRequestInfo
.subject
);
662 ret
= copy_SubjectPublicKeyInfo(&req
->key
,
663 &r
.certificationRequestInfo
.subjectPKInfo
);
665 /* Encode extReq attribute with requested Certificate Extensions */
668 ret
= get_exts(context
, req
, &exts
);
669 if (ret
== 0 && exts
.len
) {
670 Attribute
*a
= NULL
; /* Quiet VC */
673 r
.certificationRequestInfo
.attributes
=
674 calloc(1, sizeof(r
.certificationRequestInfo
.attributes
[0]));
675 if (r
.certificationRequestInfo
.attributes
== NULL
)
678 r
.certificationRequestInfo
.attributes
[0].len
= 1;
679 r
.certificationRequestInfo
.attributes
[0].val
=
680 calloc(1, sizeof(r
.certificationRequestInfo
.attributes
[0].val
[0]));
681 if (r
.certificationRequestInfo
.attributes
[0].val
== NULL
)
684 a
= r
.certificationRequestInfo
.attributes
[0].val
;
687 ASN1_MALLOC_ENCODE(Extensions
, extns
.data
, extns
.length
,
690 ret
= der_copy_oid(&asn1_oid_id_pkcs9_extReq
, &a
->type
);
692 ret
= add_AttributeValues(&a
->value
, &extns
);
693 free_heim_any(&extns
);
696 /* Encode CSR body for signing */
698 ASN1_MALLOC_ENCODE(CertificationRequestInfo
, data
.data
, data
.length
,
699 &r
.certificationRequestInfo
, &size
, ret
);
700 if (ret
== 0 && data
.length
!= size
)
703 /* Self-sign CSR body */
705 ret
= _hx509_create_signature_bitstring(context
, signer
,
706 _hx509_crypto_default_sig_alg
,
708 &r
.signatureAlgorithm
,
715 ASN1_MALLOC_ENCODE(CertificationRequest
, request
->data
, request
->length
,
717 if (ret
== 0 && request
->length
!= size
)
720 free_CertificationRequest(&r
);
725 * Parse an encoded CSR and verify its self-signature.
727 * @param context An hx509 context.
728 * @param der The DER-encoded CSR.
729 * @param req Where to put request object.
731 * @return An hx509 error code, see hx509_get_error_string().
733 * @ingroup hx509_request
735 HX509_LIB_FUNCTION
int HX509_LIB_CALL
736 hx509_request_parse_der(hx509_context context
,
737 heim_octet_string
*der
,
740 CertificationRequestInfo
*rinfo
= NULL
;
741 CertificationRequest r
;
742 hx509_cert signer
= NULL
;
747 memset(&exts
, 0, sizeof(exts
));
749 /* Initial setup and decoding of CSR */
750 ret
= hx509_request_init(context
, req
);
753 ret
= decode_CertificationRequest(der
->data
, der
->length
, &r
, &size
);
755 hx509_set_error_string(context
, 0, ret
, "Failed to decode CSR");
760 rinfo
= &r
.certificationRequestInfo
;
763 * Setup a 'signer' for verifying the self-signature for proof of
766 * Sadly we need a "certificate" here because _hx509_verify_signature_*()
767 * functions want one as a signer even though all the verification
768 * functions that use the signer argument only ever use the spki of the
769 * signer certificate.
771 * FIXME Change struct signature_alg's verify_signature's prototype to use
772 * an spki instead of an hx509_cert as the signer! The we won't have
777 memset(&c
, 0, sizeof(c
));
778 c
.tbsCertificate
.subjectPublicKeyInfo
= rinfo
->subjectPKInfo
;
779 if ((signer
= hx509_cert_init(context
, &c
, NULL
)) == NULL
)
783 /* Verify the signature */
785 ret
= _hx509_verify_signature_bitstring(context
, signer
,
786 &r
.signatureAlgorithm
,
790 hx509_set_error_string(context
, 0, ret
,
791 "CSR signature verification failed");
792 hx509_cert_free(signer
);
794 /* Populate the hx509_request */
796 ret
= hx509_request_set_SubjectPublicKeyInfo(context
, *req
,
797 &rinfo
->subjectPKInfo
);
799 ret
= _hx509_name_from_Name(&rinfo
->subject
, &(*req
)->name
);
801 /* Extract KUs, EKUs, and SANs from the CSR's attributes */
802 if (ret
|| !rinfo
->attributes
|| !rinfo
->attributes
[0].len
)
805 for (i
= 0; ret
== 0 && i
< rinfo
->attributes
[0].len
; i
++) {
806 Attribute
*a
= &rinfo
->attributes
[0].val
[i
];
809 /* We only support Extensions request attributes */
810 if (der_heim_oid_cmp(&a
->type
, &asn1_oid_id_pkcs9_extReq
) != 0) {
814 * We need an HX509_TRACE facility for this sort of warning.
816 * We'd put the warning in the context and then allow the caller to
817 * extract and reset the warning.
821 der_print_heim_oid(&a
->type
, '.', &oidstr
);
822 warnx("Unknown or unsupported CSR attribute %s",
823 oidstr
? oidstr
: "<error decoding OID>");
831 ret
= decode_Extensions(av
->data
, av
->length
, &exts
, NULL
);
833 hx509_set_error_string(context
, 0, ret
,
834 "CSR signature verification failed "
835 "due to invalid extReq attribute");
839 for (i
= 0; ret
== 0 && i
< exts
.len
; i
++) {
840 const char *what
= "";
841 Extension
*e
= &exts
.val
[i
];
843 if (der_heim_oid_cmp(&e
->extnID
,
844 &asn1_oid_id_x509_ce_keyUsage
) == 0) {
845 ret
= decode_KeyUsage(e
->extnValue
.data
, e
->extnValue
.length
,
849 * Count all KUs as one requested extension to be authorized,
850 * though the caller will have to check the KU values individually.
852 if (KeyUsage2int((*req
)->ku
) & ~KeyUsage2int(int2KeyUsage(~0)))
853 (*req
)->nunsupported
++;
854 } else if (der_heim_oid_cmp(&e
->extnID
,
855 &asn1_oid_id_x509_ce_extKeyUsage
) == 0) {
856 ret
= decode_ExtKeyUsage(e
->extnValue
.data
, e
->extnValue
.length
,
858 what
= "extKeyUsage";
861 * Count each EKU as a separate requested extension to be
864 } else if (der_heim_oid_cmp(&e
->extnID
,
865 &asn1_oid_id_x509_ce_subjectAltName
) == 0) {
866 ret
= decode_GeneralNames(e
->extnValue
.data
, e
->extnValue
.length
,
868 what
= "subjectAlternativeName";
871 * Count each SAN as a separate requested extension to be
877 (*req
)->nunsupported
++;
880 * We need an HX509_TRACE facility for this sort of warning.
882 * We'd put the warning in the context and then allow the caller to
883 * extract and reset the warning.
887 der_print_heim_oid(&e
->extnID
, '.', &oidstr
);
888 warnx("Unknown or unsupported CSR extension request %s",
889 oidstr
? oidstr
: "<error decoding OID>");
893 hx509_set_error_string(context
, 0, ret
,
894 "CSR signature verification failed "
895 "due to invalid %s extension", what
);
901 free_CertificationRequest(&r
);
903 hx509_request_free(req
);
904 free_CertificationRequest(&r
);
909 * Parse an encoded CSR and verify its self-signature.
911 * @param context An hx509 context.
912 * @param csr The name of a store containing the CSR ("PKCS10:/path/to/file")
913 * @param req Where to put request object.
915 * @return An hx509 error code, see hx509_get_error_string().
917 * @ingroup hx509_request
919 HX509_LIB_FUNCTION
int HX509_LIB_CALL
920 hx509_request_parse(hx509_context context
,
927 /* XXX Add support for PEM */
928 if (strncmp(csr
, "PKCS10:", 7) != 0) {
929 hx509_set_error_string(context
, 0, HX509_UNSUPPORTED_OPERATION
,
930 "CSR location does not start with \"PKCS10:\": %s",
932 return HX509_UNSUPPORTED_OPERATION
;
935 ret
= rk_undumpdata(csr
+ 7, &d
.data
, &d
.length
);
937 hx509_set_error_string(context
, 0, ret
, "Could not read %s", csr
);
941 ret
= hx509_request_parse_der(context
, &d
, req
);
944 hx509_set_error_string(context
, HX509_ERROR_APPEND
, ret
,
945 " (while parsing CSR from %s)", csr
);
950 * Get some EKU from a CSR. Usable as an iterator.
952 * @param context An hx509 context.
953 * @param req The hx509_request object.
954 * @param idx The index of the EKU (0 for the first) to return
955 * @param out A pointer to a char * variable where the OID will be placed
956 * (caller must free with free())
958 * @return Zero on success, HX509_NO_ITEM if no such item exists (denoting
959 * iteration end), or an error.
961 * @ingroup hx509_request
963 HX509_LIB_FUNCTION
int HX509_LIB_CALL
964 hx509_request_get_eku(hx509_request req
,
969 if (idx
>= req
->eku
.len
)
970 return HX509_NO_ITEM
;
971 return der_print_heim_oid(&req
->eku
.val
[idx
], '.', out
);
975 abitstring_check(abitstring a
, size_t n
, int idx
)
982 bytes
= (idx
+ 1) / CHAR_BIT
+ (((idx
+ 1) % CHAR_BIT
) ? 1 : 0);
983 if (a
->feat_bytes
< bytes
)
986 return !!(a
->feats
[idx
/ CHAR_BIT
] & (1UL<<(idx
% CHAR_BIT
)));
990 * Sets and returns 0 if not already set, -1 if already set. Positive return
991 * values are system errors.
994 abitstring_set(abitstring a
, size_t n
, int idx
)
1001 bytes
= n
/ CHAR_BIT
+ ((n
% CHAR_BIT
) ? 1 : 0);
1002 if (a
->feat_bytes
< bytes
) {
1005 if ((tmp
= realloc(a
->feats
, bytes
)) == NULL
)
1007 memset(tmp
+ a
->feat_bytes
, 0, bytes
- a
->feat_bytes
);
1009 a
->feat_bytes
= bytes
;
1012 if (!(a
->feats
[idx
/ CHAR_BIT
] & (1UL<<(idx
% CHAR_BIT
)))) {
1013 a
->feats
[idx
/ CHAR_BIT
] |= 1UL<<(idx
% CHAR_BIT
);
1020 * Resets and returns 0 if not already reset, -1 if already reset. Positive
1021 * return values are system errors.
1024 abitstring_reset(abitstring a
, size_t n
, int idx
)
1031 bytes
= (idx
+ 1) / CHAR_BIT
+ (((idx
+ 1) % CHAR_BIT
) ? 1 : 0);
1032 if (a
->feat_bytes
>= bytes
&&
1033 (a
->feats
[idx
/ CHAR_BIT
] & (1UL<<(idx
% CHAR_BIT
)))) {
1034 a
->feats
[idx
/ CHAR_BIT
] &= ~(1UL<<(idx
% CHAR_BIT
));
1041 authorize_feat(hx509_request req
, abitstring a
, size_t n
, int idx
)
1045 ret
= abitstring_set(a
, n
, idx
);
1058 reject_feat(hx509_request req
, abitstring a
, size_t n
, int idx
)
1062 ret
= abitstring_reset(a
, n
, idx
);
1075 * Filter the requested KeyUsage and mark it authorized.
1077 * @param req The hx509_request object.
1078 * @param ku Permitted KeyUsage
1080 * @ingroup hx509_request
1082 HX509_LIB_FUNCTION
void HX509_LIB_CALL
1083 hx509_request_authorize_ku(hx509_request req
, KeyUsage ku
)
1085 (void) hx509_request_set_ku(NULL
, req
, ku
);
1086 req
->ku
= int2KeyUsage(KeyUsage2int(req
->ku
) & KeyUsage2int(ku
));
1087 if (KeyUsage2int(ku
))
1088 req
->ku_are_authorized
= 1;
1092 * Mark a requested EKU as authorized.
1094 * @param req The hx509_request object.
1095 * @param idx The index of an EKU that can be fetched with
1096 * hx509_request_get_eku()
1098 * @return Zero on success, an error otherwise.
1100 * @ingroup hx509_request
1102 HX509_LIB_FUNCTION
int HX509_LIB_CALL
1103 hx509_request_authorize_eku(hx509_request req
, size_t idx
)
1105 return authorize_feat(req
, &req
->authorized_EKUs
, req
->eku
.len
, idx
);
1109 * Mark a requested EKU as not authorized.
1111 * @param req The hx509_request object.
1112 * @param idx The index of an EKU that can be fetched with
1113 * hx509_request_get_eku()
1115 * @return Zero on success, an error otherwise.
1117 * @ingroup hx509_request
1119 HX509_LIB_FUNCTION
int HX509_LIB_CALL
1120 hx509_request_reject_eku(hx509_request req
, size_t idx
)
1122 return reject_feat(req
, &req
->authorized_EKUs
, req
->eku
.len
, idx
);
1126 * Check if an EKU has been marked authorized.
1128 * @param req The hx509_request object.
1129 * @param idx The index of an EKU that can be fetched with
1130 * hx509_request_get_eku()
1132 * @return Non-zero if authorized, zero if not.
1134 * @ingroup hx509_request
1136 HX509_LIB_FUNCTION
int HX509_LIB_CALL
1137 hx509_request_eku_authorized_p(hx509_request req
, size_t idx
)
1139 return abitstring_check(&req
->authorized_EKUs
, req
->eku
.len
, idx
);
1143 * Mark a requested SAN as authorized.
1145 * @param req The hx509_request object.
1146 * @param idx The cursor as modified by a SAN iterator.
1148 * @return Zero on success, an error otherwise.
1150 * @ingroup hx509_request
1152 HX509_LIB_FUNCTION
int HX509_LIB_CALL
1153 hx509_request_authorize_san(hx509_request req
, size_t idx
)
1155 return authorize_feat(req
, &req
->authorized_SANs
, req
->san
.len
, idx
);
1159 * Mark a requested SAN as not authorized.
1161 * @param req The hx509_request object.
1162 * @param idx The cursor as modified by a SAN iterator.
1164 * @return Zero on success, an error otherwise.
1166 * @ingroup hx509_request
1168 HX509_LIB_FUNCTION
int HX509_LIB_CALL
1169 hx509_request_reject_san(hx509_request req
, size_t idx
)
1171 return reject_feat(req
, &req
->authorized_SANs
, req
->san
.len
, idx
);
1175 * Check if a SAN has been marked authorized.
1177 * @param req The hx509_request object.
1178 * @param idx The index of a SAN that can be fetched with
1179 * hx509_request_get_san()
1181 * @return Non-zero if authorized, zero if not.
1183 * @ingroup hx509_request
1185 HX509_LIB_FUNCTION
int HX509_LIB_CALL
1186 hx509_request_san_authorized_p(hx509_request req
, size_t idx
)
1188 return abitstring_check(&req
->authorized_SANs
, req
->san
.len
, idx
);
1192 * Return the count of unsupported requested certificate extensions.
1194 * @param req The hx509_request object.
1195 * @return The number of unsupported certificate extensions requested.
1197 * @ingroup hx509_request
1199 HX509_LIB_FUNCTION
size_t HX509_LIB_CALL
1200 hx509_request_count_unsupported(hx509_request req
)
1202 return req
->nunsupported
;
1206 * Return the count of as-yet unauthorized certificate extensions requested.
1208 * @param req The hx509_request object.
1209 * @return The number of as-yet unauthorized certificate extensions requested.
1211 * @ingroup hx509_request
1213 HX509_LIB_FUNCTION
size_t HX509_LIB_CALL
1214 hx509_request_count_unauthorized(hx509_request req
)
1216 size_t nrequested
= req
->eku
.len
+ req
->san
.len
+
1217 (KeyUsage2int(req
->ku
) ? 1 : 0) + req
->nunsupported
;
1219 return nrequested
- (req
->nauthorized
+ req
->ku_are_authorized
);
1222 static hx509_san_type
1223 san_map_type(GeneralName
*san
)
1225 static const struct {
1226 const heim_oid
*oid
;
1227 hx509_san_type type
;
1229 { &asn1_oid_id_pkix_on_dnsSRV
, HX509_SAN_TYPE_DNSSRV
},
1230 { &asn1_oid_id_pkinit_san
, HX509_SAN_TYPE_PKINIT
},
1231 { &asn1_oid_id_pkix_on_xmppAddr
, HX509_SAN_TYPE_XMPP
},
1232 { &asn1_oid_id_pkinit_ms_san
, HX509_SAN_TYPE_MS_UPN
},
1233 { &asn1_oid_id_pkix_on_permanentIdentifier
, HX509_SAN_TYPE_PERMANENT_ID
},
1234 { &asn1_oid_id_on_hardwareModuleName
, HX509_SAN_TYPE_HW_MODULE
},
1238 switch (san
->element
) {
1239 case choice_GeneralName_rfc822Name
: return HX509_SAN_TYPE_EMAIL
;
1240 case choice_GeneralName_dNSName
: return HX509_SAN_TYPE_DNSNAME
;
1241 case choice_GeneralName_directoryName
: return HX509_SAN_TYPE_DN
;
1242 case choice_GeneralName_registeredID
: return HX509_SAN_TYPE_REGISTERED_ID
;
1243 case choice_GeneralName_otherName
: {
1244 for (i
= 0; i
< sizeof(map
)/sizeof(map
[0]); i
++)
1245 if (der_heim_oid_cmp(&san
->u
.otherName
.type_id
, map
[i
].oid
) == 0)
1249 default: return HX509_SAN_TYPE_UNSUPPORTED
;
1254 * Return the count of as-yet unauthorized certificate extensions requested.
1256 * @param req The hx509_request object.
1258 * @ingroup hx509_request
1260 HX509_LIB_FUNCTION
size_t HX509_LIB_CALL
1261 hx509_request_get_san(hx509_request req
,
1263 hx509_san_type
*type
,
1266 struct rk_strpool
*pool
= NULL
;
1270 if (idx
>= req
->san
.len
)
1271 return HX509_NO_ITEM
;
1273 san
= &req
->san
.val
[idx
];
1274 switch ((*type
= san_map_type(san
))) {
1275 case HX509_SAN_TYPE_UNSUPPORTED
: return 0;
1276 case HX509_SAN_TYPE_EMAIL
:
1277 *out
= strndup(san
->u
.rfc822Name
.data
,
1278 san
->u
.rfc822Name
.length
);
1280 case HX509_SAN_TYPE_DNSNAME
:
1281 *out
= strndup(san
->u
.dNSName
.data
,
1282 san
->u
.dNSName
.length
);
1284 case HX509_SAN_TYPE_DNSSRV
: {
1289 ret
= decode_SRVName(san
->u
.otherName
.value
.data
,
1290 san
->u
.otherName
.value
.length
, &name
, &size
);
1293 *out
= strndup(name
.data
, name
.length
);
1296 case HX509_SAN_TYPE_PERMANENT_ID
: {
1297 PermanentIdentifier pi
;
1302 ret
= decode_PermanentIdentifier(san
->u
.otherName
.value
.data
,
1303 san
->u
.otherName
.value
.length
,
1305 if (ret
== 0 && pi
.assigner
) {
1306 ret
= der_print_heim_oid(pi
.assigner
, '.', &s
);
1308 (pool
= rk_strpoolprintf(NULL
, "%s", s
)) == NULL
)
1310 } else if (ret
== 0) {
1311 pool
= rk_strpoolprintf(NULL
, "-");
1314 (pool
= rk_strpoolprintf(pool
, "%s%s",
1315 *pi
.identifierValue
? " " : "",
1316 *pi
.identifierValue
? *pi
.identifierValue
: "")) == NULL
)
1318 if (ret
== 0 && (*out
= rk_strpoolcollect(pool
)) == NULL
)
1320 free_PermanentIdentifier(&pi
);
1324 case HX509_SAN_TYPE_HW_MODULE
: {
1325 HardwareModuleName hn
;
1330 ret
= decode_HardwareModuleName(san
->u
.otherName
.value
.data
,
1331 san
->u
.otherName
.value
.length
,
1333 if (ret
== 0 && hn
.hwSerialNum
.length
> 256)
1334 hn
.hwSerialNum
.length
= 256;
1336 ret
= der_print_heim_oid(&hn
.hwType
, '.', &s
);
1338 pool
= rk_strpoolprintf(NULL
, "%s", s
);
1339 if (ret
== 0 && pool
)
1340 pool
= rk_strpoolprintf(pool
, " %.*s",
1341 (int)hn
.hwSerialNum
.length
,
1342 (char *)hn
.hwSerialNum
.data
);
1344 (pool
== NULL
|| (*out
= rk_strpoolcollect(pool
)) == NULL
))
1346 free_HardwareModuleName(&hn
);
1349 case HX509_SAN_TYPE_DN
: {
1352 if (san
->u
.directoryName
.element
== choice_Name_rdnSequence
) {
1353 name
.element
= choice_Name_rdnSequence
;
1354 name
.u
.rdnSequence
= san
->u
.directoryName
.u
.rdnSequence
;
1355 return _hx509_Name_to_string(&name
, out
);
1357 *type
= HX509_SAN_TYPE_UNSUPPORTED
;
1360 case HX509_SAN_TYPE_REGISTERED_ID
:
1361 return der_print_heim_oid(&san
->u
.registeredID
, '.', out
);
1362 case HX509_SAN_TYPE_XMPP
:
1364 case HX509_SAN_TYPE_MS_UPN
: {
1367 ret
= _hx509_unparse_utf8_string_name(req
->context
, &pool
,
1368 &san
->u
.otherName
.value
);
1370 (*out
= rk_strpoolcollect(pool
)) == NULL
)
1371 return hx509_enomem(req
->context
);
1374 case HX509_SAN_TYPE_PKINIT
: {
1377 ret
= _hx509_unparse_KRB5PrincipalName(req
->context
, &pool
,
1378 &san
->u
.otherName
.value
);
1380 (*out
= rk_strpoolcollect(pool
)) == NULL
)
1381 return hx509_enomem(req
->context
);
1385 *type
= HX509_SAN_TYPE_UNSUPPORTED
;
1396 * @param context An hx509 context.
1397 * @param req The hx509_request object.
1398 * @param f A FILE * to print the CSR to.
1400 * @return An hx509 error code, see hx509_get_error_string().
1402 * @ingroup hx509_request
1404 HX509_LIB_FUNCTION
int HX509_LIB_CALL
1405 hx509_request_print(hx509_context context
, hx509_request req
, FILE *f
)
1413 * It's really unformatunate that we can't reuse more of the
1414 * lib/hx509/print.c infrastructure here, as it's too focused on
1417 * For that matter, it's really annoying that CSRs don't more resemble
1418 * Certificates. Indeed, an ideal CSR would look like this:
1421 * desiredTbsCertificate TBSCertificate,
1422 * attributes [1] SEQUENCE OF Attribute OPTIONAL,
1426 * sigAlg AlgorithmIdentifier,
1427 * signature BIT STRING
1430 * with everything related to the desired certificate in
1431 * desiredTbsCertificate and anything not related to the CSR's contents in
1432 * the 'attributes' field.
1434 * That wouldn't allow one to have optional desired TBSCertificate
1435 * features, but hey. One could express "gimme all or gimme nothing" as an
1436 * attribute, or "gimme what you can", then check what one got.
1438 fprintf(f
, "PKCS#10 CertificationRequest:\n");
1442 ret
= hx509_name_to_string(req
->name
, &subject
);
1444 hx509_set_error_string(context
, 0, ret
, "Failed to print name");
1447 fprintf(f
, " name: %s\n", subject
);
1450 /* XXX Use hx509_request_get_ku() accessor */
1451 if ((ku_num
= KeyUsage2int(req
->ku
))) {
1452 const struct units
*u
;
1453 const char *first
= " ";
1455 fprintf(f
, " key usage:");
1456 for (u
= asn1_KeyUsage_units(); u
->name
; ++u
) {
1457 if ((ku_num
& u
->mult
)) {
1458 fprintf(f
, "%s%s", first
, u
->name
);
1464 fprintf(f
, "%s<unknown-KeyUsage-value(s)>", first
);
1468 const char *first
= " ";
1470 fprintf(f
, " eku:");
1471 for (i
= 0; ret
== 0; i
++) {
1473 ret
= hx509_request_get_eku(req
, i
, &s
);
1476 fprintf(f
, "%s{%s}", first
, s
);
1482 if (ret
== HX509_NO_ITEM
)
1484 for (i
= 0; ret
== 0; i
++) {
1485 hx509_san_type san_type
;
1488 ret
= hx509_request_get_san(req
, i
, &san_type
, &s
);
1492 case HX509_SAN_TYPE_EMAIL
:
1493 fprintf(f
, " san: rfc822Name: %s\n", s
);
1495 case HX509_SAN_TYPE_DNSNAME
:
1496 fprintf(f
, " san: dNSName: %s\n", s
);
1498 case HX509_SAN_TYPE_DN
:
1499 fprintf(f
, " san: dn: %s\n", s
);
1501 case HX509_SAN_TYPE_REGISTERED_ID
:
1502 fprintf(f
, " san: registeredID: %s\n", s
);
1504 case HX509_SAN_TYPE_XMPP
:
1505 fprintf(f
, " san: xmpp: %s\n", s
);
1507 case HX509_SAN_TYPE_PKINIT
:
1508 fprintf(f
, " san: pkinit: %s\n", s
);
1510 case HX509_SAN_TYPE_MS_UPN
:
1511 fprintf(f
, " san: ms-upn: %s\n", s
);
1514 fprintf(f
, " san: <SAN type not supported>\n");
1519 if (ret
== HX509_NO_ITEM
)