📄 ca.c
字号:
/* * Copyright (c) 2006 - 2007 Kungliga Tekniska H鰃skolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include "hx_locl.h"#include <pkinit_asn1.h>RCSID("$Id: ca.c 22456 2008-01-15 20:22:53Z lha $");/** * @page page_ca Hx509 CA functions * * See the library functions here: @ref hx509_ca */struct hx509_ca_tbs { hx509_name subject; SubjectPublicKeyInfo spki; ExtKeyUsage eku; GeneralNames san; unsigned key_usage; heim_integer serial; struct { unsigned int proxy:1; unsigned int ca:1; unsigned int key:1; unsigned int serial:1; unsigned int domaincontroller:1; } flags; time_t notBefore; time_t notAfter; int pathLenConstraint; /* both for CA and Proxy */ CRLDistributionPoints crldp;};/** * Allocate an to-be-signed certificate object that will be converted * into an certificate. * * @param context A hx509 context. * @param tbs returned to-be-signed certicate object, free with * hx509_ca_tbs_free(). * * @return An hx509 error code, see hx509_get_error_string(). * * @ingroup hx509_ca */inthx509_ca_tbs_init(hx509_context context, hx509_ca_tbs *tbs){ *tbs = calloc(1, sizeof(**tbs)); if (*tbs == NULL) return ENOMEM; (*tbs)->subject = NULL; (*tbs)->san.len = 0; (*tbs)->san.val = NULL; (*tbs)->eku.len = 0; (*tbs)->eku.val = NULL; (*tbs)->pathLenConstraint = 0; (*tbs)->crldp.len = 0; (*tbs)->crldp.val = NULL; return 0;}/** * Free an To Be Signed object. * * @param tbs object to free. * * @ingroup hx509_ca */voidhx509_ca_tbs_free(hx509_ca_tbs *tbs){ if (tbs == NULL || *tbs == NULL) return; free_SubjectPublicKeyInfo(&(*tbs)->spki); free_GeneralNames(&(*tbs)->san); free_ExtKeyUsage(&(*tbs)->eku); der_free_heim_integer(&(*tbs)->serial); free_CRLDistributionPoints(&(*tbs)->crldp); hx509_name_free(&(*tbs)->subject); memset(*tbs, 0, sizeof(**tbs)); free(*tbs); *tbs = NULL;}/** * Set the absolute time when the certificate is valid from. If not * set the current time will be used. * * @param context A hx509 context. * @param tbs object to be signed. * @param t time the certificated will start to be valid * * @return An hx509 error code, see hx509_get_error_string(). * * @ingroup hx509_ca */inthx509_ca_tbs_set_notBefore(hx509_context context, hx509_ca_tbs tbs, time_t t){ tbs->notBefore = t; return 0;}/** * Set the absolute time when the certificate is valid to. * * @param context A hx509 context. * @param tbs object to be signed. * @param t time when the certificate will expire * * @return An hx509 error code, see hx509_get_error_string(). * * @ingroup hx509_ca */inthx509_ca_tbs_set_notAfter(hx509_context context, hx509_ca_tbs tbs, time_t t){ tbs->notAfter = t; return 0;}/** * Set the relative time when the certificiate is going to expire. * * @param context A hx509 context. * @param tbs object to be signed. * @param delta seconds to the certificate is going to expire. * * @return An hx509 error code, see hx509_get_error_string(). * * @ingroup hx509_ca */inthx509_ca_tbs_set_notAfter_lifetime(hx509_context context, hx509_ca_tbs tbs, time_t delta){ return hx509_ca_tbs_set_notAfter(context, tbs, time(NULL) + delta);}static const struct units templatebits[] = { { "ExtendedKeyUsage", HX509_CA_TEMPLATE_EKU }, { "KeyUsage", HX509_CA_TEMPLATE_KU }, { "SPKI", HX509_CA_TEMPLATE_SPKI }, { "notAfter", HX509_CA_TEMPLATE_NOTAFTER }, { "notBefore", HX509_CA_TEMPLATE_NOTBEFORE }, { "serial", HX509_CA_TEMPLATE_SERIAL }, { "subject", HX509_CA_TEMPLATE_SUBJECT }, { NULL, 0 }};/** * Make of template units, use to build flags argument to * hx509_ca_tbs_set_template() with parse_units(). * * @return an units structure. * * @ingroup hx509_ca */const struct units *hx509_ca_tbs_template_units(void){ return templatebits;}/** * Initialize the to-be-signed certificate object from a template certifiate. * * @param context A hx509 context. * @param tbs object to be signed. * @param flags bit field selecting what to copy from the template * certifiate. * @param cert template certificate. * * @return An hx509 error code, see hx509_get_error_string(). * * @ingroup hx509_ca */inthx509_ca_tbs_set_template(hx509_context context, hx509_ca_tbs tbs, int flags, hx509_cert cert){ int ret; if (flags & HX509_CA_TEMPLATE_SUBJECT) { if (tbs->subject) hx509_name_free(&tbs->subject); ret = hx509_cert_get_subject(cert, &tbs->subject); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to get subject from template"); return ret; } } if (flags & HX509_CA_TEMPLATE_SERIAL) { der_free_heim_integer(&tbs->serial); ret = hx509_cert_get_serialnumber(cert, &tbs->serial); tbs->flags.serial = !ret; if (ret) { hx509_set_error_string(context, 0, ret, "Failed to copy serial number"); return ret; } } if (flags & HX509_CA_TEMPLATE_NOTBEFORE) tbs->notBefore = hx509_cert_get_notBefore(cert); if (flags & HX509_CA_TEMPLATE_NOTAFTER) tbs->notAfter = hx509_cert_get_notAfter(cert); if (flags & HX509_CA_TEMPLATE_SPKI) { free_SubjectPublicKeyInfo(&tbs->spki); ret = hx509_cert_get_SPKI(context, cert, &tbs->spki); tbs->flags.key = !ret; if (ret) return ret; } if (flags & HX509_CA_TEMPLATE_KU) { KeyUsage ku; ret = _hx509_cert_get_keyusage(context, cert, &ku); if (ret) return ret; tbs->key_usage = KeyUsage2int(ku); } if (flags & HX509_CA_TEMPLATE_EKU) { ExtKeyUsage eku; int i; ret = _hx509_cert_get_eku(context, cert, &eku); if (ret) return ret; for (i = 0; i < eku.len; i++) { ret = hx509_ca_tbs_add_eku(context, tbs, &eku.val[i]); if (ret) { free_ExtKeyUsage(&eku); return ret; } } free_ExtKeyUsage(&eku); } return 0;}/** * Make the to-be-signed certificate object a CA certificate. If the * pathLenConstraint is negative path length constraint is used. * * @param context A hx509 context. * @param tbs object to be signed. * @param pathLenConstraint path length constraint, negative, no * constraint. * * @return An hx509 error code, see hx509_get_error_string(). * * @ingroup hx509_ca */inthx509_ca_tbs_set_ca(hx509_context context, hx509_ca_tbs tbs, int pathLenConstraint){ tbs->flags.ca = 1; tbs->pathLenConstraint = pathLenConstraint; return 0;}/** * Make the to-be-signed certificate object a proxy certificate. If the * pathLenConstraint is negative path length constraint is used. * * @param context A hx509 context. * @param tbs object to be signed. * @param pathLenConstraint path length constraint, negative, no * constraint. * * @return An hx509 error code, see hx509_get_error_string(). * * @ingroup hx509_ca */inthx509_ca_tbs_set_proxy(hx509_context context, hx509_ca_tbs tbs, int pathLenConstraint){ tbs->flags.proxy = 1; tbs->pathLenConstraint = pathLenConstraint; return 0;}/** * Make the to-be-signed certificate object a windows domain controller certificate. * * @param context A hx509 context. * @param tbs object to be signed. * * @return An hx509 error code, see hx509_get_error_string(). * * @ingroup hx509_ca */inthx509_ca_tbs_set_domaincontroller(hx509_context context, hx509_ca_tbs tbs){ tbs->flags.domaincontroller = 1; return 0;}/** * Set the subject public key info (SPKI) in the to-be-signed certificate * object. SPKI is the public key and key related parameters in the * certificate. * * @param context A hx509 context. * @param tbs object to be signed. * @param spki subject public key info to use for the to-be-signed certificate object. * * @return An hx509 error code, see hx509_get_error_string(). * * @ingroup hx509_ca */inthx509_ca_tbs_set_spki(hx509_context context, hx509_ca_tbs tbs, const SubjectPublicKeyInfo *spki){ int ret; free_SubjectPublicKeyInfo(&tbs->spki); ret = copy_SubjectPublicKeyInfo(spki, &tbs->spki); tbs->flags.key = !ret; return ret;}/** * Set the serial number to use for to-be-signed certificate object. * * @param context A hx509 context. * @param tbs object to be signed. * @param serialNumber serial number to use for the to-be-signed * certificate object. * * @return An hx509 error code, see hx509_get_error_string(). * * @ingroup hx509_ca */inthx509_ca_tbs_set_serialnumber(hx509_context context, hx509_ca_tbs tbs, const heim_integer *serialNumber){ int ret; der_free_heim_integer(&tbs->serial); ret = der_copy_heim_integer(serialNumber, &tbs->serial); tbs->flags.serial = !ret; return ret;}/** * An an extended key usage to the to-be-signed certificate object. * Duplicates will detected and not added. * * @param context A hx509 context. * @param tbs object to be signed. * @param oid extended key usage to add. * * @return An hx509 error code, see hx509_get_error_string(). * * @ingroup hx509_ca */inthx509_ca_tbs_add_eku(hx509_context context, hx509_ca_tbs tbs, const heim_oid *oid){ void *ptr; int ret; unsigned i; /* search for duplicates */ for (i = 0; i < tbs->eku.len; i++) { if (der_heim_oid_cmp(oid, &tbs->eku.val[i]) == 0) return 0; } ptr = realloc(tbs->eku.val, sizeof(tbs->eku.val[0]) * (tbs->eku.len + 1)); if (ptr == NULL) { hx509_set_error_string(context, 0, ENOMEM, "out of memory"); return ENOMEM; } tbs->eku.val = ptr; ret = der_copy_oid(oid, &tbs->eku.val[tbs->eku.len]); if (ret) { hx509_set_error_string(context, 0, ret, "out of memory"); return ret; } tbs->eku.len += 1; return 0;}/** * Add CRL distribution point URI to the to-be-signed certificate * object. * * @param context A hx509 context. * @param tbs object to be signed. * @param uri uri to the CRL. * @param issuername name of the issuer. * * @return An hx509 error code, see hx509_get_error_string(). * * @ingroup hx509_ca */inthx509_ca_tbs_add_crl_dp_uri(hx509_context context, hx509_ca_tbs tbs, const char *uri, hx509_name issuername){ DistributionPoint dp; int ret; memset(&dp, 0, sizeof(dp)); dp.distributionPoint = ecalloc(1, sizeof(*dp.distributionPoint)); { DistributionPointName name; GeneralName gn; size_t size; name.element = choice_DistributionPointName_fullName; name.u.fullName.len = 1; name.u.fullName.val = &gn; gn.element = choice_GeneralName_uniformResourceIdentifier; gn.u.uniformResourceIdentifier = rk_UNCONST(uri); ASN1_MALLOC_ENCODE(DistributionPointName, dp.distributionPoint->data, dp.distributionPoint->length, &name, &size, ret); if (ret) { hx509_set_error_string(context, 0, ret, "Failed to encoded DistributionPointName"); goto out; } if (dp.distributionPoint->length != size) _hx509_abort("internal ASN.1 encoder error"); } if (issuername) {#if 1 /** * issuername not supported
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -