1193323Sed/* $NetBSD$ */ 2193323Sed 3193323Sed/* 4193323Sed * Copyright (c) 2006 - 2010 Kungliga Tekniska H��gskolan 5193323Sed * (Royal Institute of Technology, Stockholm, Sweden). 6193323Sed * All rights reserved. 7193323Sed * 8193323Sed * Redistribution and use in source and binary forms, with or without 9193323Sed * modification, are permitted provided that the following conditions 10193323Sed * are met: 11193323Sed * 12193323Sed * 1. Redistributions of source code must retain the above copyright 13193323Sed * notice, this list of conditions and the following disclaimer. 14193323Sed * 15193323Sed * 2. Redistributions in binary form must reproduce the above copyright 16193323Sed * notice, this list of conditions and the following disclaimer in the 17193323Sed * documentation and/or other materials provided with the distribution. 18193323Sed * 19224145Sdim * 3. Neither the name of the Institute nor the names of its contributors 20221345Sdim * may be used to endorse or promote products derived from this software 21193323Sed * without specific prior written permission. 22193323Sed * 23193323Sed * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24210299Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25193323Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26193323Sed * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27203954Srdivacky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28218893Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29203954Srdivacky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30198090Srdivacky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31224145Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32193323Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33193323Sed * SUCH DAMAGE. 34193323Sed */ 35193323Sed 36198090Srdivacky#include "hx_locl.h" 37193323Sed#include <krb5/pkinit_asn1.h> 38193323Sed 39193323Sed/** 40193323Sed * @page page_ca Hx509 CA functions 41193323Sed * 42193323Sed * See the library functions here: @ref hx509_ca 43193323Sed */ 44193323Sed 45193323Sedstruct hx509_ca_tbs { 46193323Sed hx509_name subject; 47193323Sed SubjectPublicKeyInfo spki; 48193323Sed ExtKeyUsage eku; 49193323Sed GeneralNames san; 50193323Sed unsigned key_usage; 51193323Sed heim_integer serial; 52193323Sed struct { 53193323Sed unsigned int proxy:1; 54193323Sed unsigned int ca:1; 55193323Sed unsigned int key:1; 56193323Sed unsigned int serial:1; 57193323Sed unsigned int domaincontroller:1; 58193323Sed unsigned int xUniqueID:1; 59193323Sed } flags; 60193323Sed time_t notBefore; 61193323Sed time_t notAfter; 62193323Sed int pathLenConstraint; /* both for CA and Proxy */ 63193323Sed CRLDistributionPoints crldp; 64193323Sed heim_bit_string subjectUniqueID; 65193323Sed heim_bit_string issuerUniqueID; 66193323Sed 67193323Sed}; 68224145Sdim 69193323Sed/** 70193323Sed * Allocate an to-be-signed certificate object that will be converted 71193323Sed * into an certificate. 72193323Sed * 73193323Sed * @param context A hx509 context. 74224145Sdim * @param tbs returned to-be-signed certicate object, free with 75224145Sdim * hx509_ca_tbs_free(). 76224145Sdim * 77224145Sdim * @return An hx509 error code, see hx509_get_error_string(). 78224145Sdim * 79224145Sdim * @ingroup hx509_ca 80234353Sdim */ 81224145Sdim 82193323Sedint 83193323Sedhx509_ca_tbs_init(hx509_context context, hx509_ca_tbs *tbs) 84193323Sed{ 85193323Sed *tbs = calloc(1, sizeof(**tbs)); 86193323Sed if (*tbs == NULL) 87193323Sed return ENOMEM; 88234353Sdim 89193323Sed return 0; 90234353Sdim} 91193323Sed 92193323Sed/** 93193323Sed * Free an To Be Signed object. 94193323Sed * 95198892Srdivacky * @param tbs object to free. 96198892Srdivacky * 97198892Srdivacky * @ingroup hx509_ca 98198892Srdivacky */ 99193323Sed 100193323Sedvoid 101193323Sedhx509_ca_tbs_free(hx509_ca_tbs *tbs) 102193323Sed{ 103193323Sed if (tbs == NULL || *tbs == NULL) 104193323Sed return; 105193323Sed 106193323Sed free_SubjectPublicKeyInfo(&(*tbs)->spki); 107193323Sed free_GeneralNames(&(*tbs)->san); 108193323Sed free_ExtKeyUsage(&(*tbs)->eku); 109193323Sed der_free_heim_integer(&(*tbs)->serial); 110193323Sed free_CRLDistributionPoints(&(*tbs)->crldp); 111199989Srdivacky der_free_bit_string(&(*tbs)->subjectUniqueID); 112199989Srdivacky der_free_bit_string(&(*tbs)->issuerUniqueID); 113193323Sed hx509_name_free(&(*tbs)->subject); 114193323Sed 115193323Sed memset(*tbs, 0, sizeof(**tbs)); 116199989Srdivacky free(*tbs); 117199989Srdivacky *tbs = NULL; 118199989Srdivacky} 119199989Srdivacky 120234353Sdim/** 121234353Sdim * Set the absolute time when the certificate is valid from. If not 122234353Sdim * set the current time will be used. 123234353Sdim * 124198892Srdivacky * @param context A hx509 context. 125198892Srdivacky * @param tbs object to be signed. 126198892Srdivacky * @param t time the certificated will start to be valid 127198892Srdivacky * 128198892Srdivacky * @return An hx509 error code, see hx509_get_error_string(). 129198892Srdivacky * 130198892Srdivacky * @ingroup hx509_ca 131198892Srdivacky */ 132193323Sed 133193323Sedint 134193323Sedhx509_ca_tbs_set_notBefore(hx509_context context, 135193323Sed hx509_ca_tbs tbs, 136193323Sed time_t t) 137193323Sed{ 138234353Sdim tbs->notBefore = t; 139234353Sdim return 0; 140234353Sdim} 141234353Sdim 142234353Sdim/** 143234353Sdim * Set the absolute time when the certificate is valid to. 144234353Sdim * 145234353Sdim * @param context A hx509 context. 146239462Sdim * @param tbs object to be signed. 147234353Sdim * @param t time when the certificate will expire 148234353Sdim * 149234353Sdim * @return An hx509 error code, see hx509_get_error_string(). 150234353Sdim * 151234353Sdim * @ingroup hx509_ca 152234353Sdim */ 153234353Sdim 154234353Sdimint 155234353Sdimhx509_ca_tbs_set_notAfter(hx509_context context, 156239462Sdim hx509_ca_tbs tbs, 157239462Sdim time_t t) 158239462Sdim{ 159239462Sdim tbs->notAfter = t; 160234353Sdim return 0; 161234353Sdim} 162234353Sdim 163234353Sdim/** 164234353Sdim * Set the relative time when the certificiate is going to expire. 165234353Sdim * 166234353Sdim * @param context A hx509 context. 167234353Sdim * @param tbs object to be signed. 168234353Sdim * @param delta seconds to the certificate is going to expire. 169234353Sdim * 170234353Sdim * @return An hx509 error code, see hx509_get_error_string(). 171234353Sdim * 172234353Sdim * @ingroup hx509_ca 173234353Sdim */ 174234353Sdim 175234353Sdimint 176239462Sdimhx509_ca_tbs_set_notAfter_lifetime(hx509_context context, 177239462Sdim hx509_ca_tbs tbs, 178234353Sdim time_t delta) 179234353Sdim{ 180234353Sdim return hx509_ca_tbs_set_notAfter(context, tbs, time(NULL) + delta); 181239462Sdim} 182239462Sdim 183239462Sdimstatic const struct units templatebits[] = { 184234353Sdim { "ExtendedKeyUsage", HX509_CA_TEMPLATE_EKU }, 185234353Sdim { "KeyUsage", HX509_CA_TEMPLATE_KU }, 186234353Sdim { "SPKI", HX509_CA_TEMPLATE_SPKI }, 187234353Sdim { "notAfter", HX509_CA_TEMPLATE_NOTAFTER }, 188239462Sdim { "notBefore", HX509_CA_TEMPLATE_NOTBEFORE }, 189234353Sdim { "serial", HX509_CA_TEMPLATE_SERIAL }, 190234353Sdim { "subject", HX509_CA_TEMPLATE_SUBJECT }, 191234353Sdim { NULL, 0 } 192234353Sdim}; 193239462Sdim 194234353Sdim/** 195234353Sdim * Make of template units, use to build flags argument to 196234353Sdim * hx509_ca_tbs_set_template() with parse_units(). 197234353Sdim * 198234353Sdim * @return an units structure. 199234353Sdim * 200234353Sdim * @ingroup hx509_ca 201234353Sdim */ 202234353Sdim 203234353Sdimconst struct units * 204234353Sdimhx509_ca_tbs_template_units(void) 205234353Sdim{ 206234353Sdim return templatebits; 207234353Sdim} 208234353Sdim 209234353Sdim/** 210234353Sdim * Initialize the to-be-signed certificate object from a template certifiate. 211234353Sdim * 212234353Sdim * @param context A hx509 context. 213234353Sdim * @param tbs object to be signed. 214234353Sdim * @param flags bit field selecting what to copy from the template 215234353Sdim * certifiate. 216193323Sed * @param cert template certificate. 217193323Sed * 218193323Sed * @return An hx509 error code, see hx509_get_error_string(). 219193323Sed * 220193323Sed * @ingroup hx509_ca 221193323Sed */ 222193323Sed 223193323Sedint 224234353Sdimhx509_ca_tbs_set_template(hx509_context context, 225234353Sdim hx509_ca_tbs tbs, 226234353Sdim int flags, 227234353Sdim hx509_cert cert) 228234353Sdim{ 229234353Sdim int ret; 230234353Sdim 231234353Sdim if (flags & HX509_CA_TEMPLATE_SUBJECT) { 232234353Sdim if (tbs->subject) 233239462Sdim hx509_name_free(&tbs->subject); 234239462Sdim ret = hx509_cert_get_subject(cert, &tbs->subject); 235239462Sdim if (ret) { 236239462Sdim hx509_set_error_string(context, 0, ret, 237239462Sdim "Failed to get subject from template"); 238239462Sdim return ret; 239239462Sdim } 240239462Sdim } 241193323Sed if (flags & HX509_CA_TEMPLATE_SERIAL) { 242234353Sdim der_free_heim_integer(&tbs->serial); 243193323Sed ret = hx509_cert_get_serialnumber(cert, &tbs->serial); 244193323Sed tbs->flags.serial = !ret; 245193323Sed if (ret) { 246193323Sed hx509_set_error_string(context, 0, ret, 247193323Sed "Failed to copy serial number"); 248193323Sed return ret; 249193323Sed } 250193323Sed } 251193323Sed if (flags & HX509_CA_TEMPLATE_NOTBEFORE) 252193323Sed tbs->notBefore = hx509_cert_get_notBefore(cert); 253193323Sed if (flags & HX509_CA_TEMPLATE_NOTAFTER) 254193323Sed tbs->notAfter = hx509_cert_get_notAfter(cert); 255193323Sed if (flags & HX509_CA_TEMPLATE_SPKI) { 256193323Sed free_SubjectPublicKeyInfo(&tbs->spki); 257193323Sed ret = hx509_cert_get_SPKI(context, cert, &tbs->spki); 258193323Sed tbs->flags.key = !ret; 259193323Sed if (ret) 260193323Sed return ret; 261193323Sed } 262193323Sed if (flags & HX509_CA_TEMPLATE_KU) { 263193323Sed KeyUsage ku; 264193323Sed ret = _hx509_cert_get_keyusage(context, cert, &ku); 265193323Sed if (ret) 266193323Sed return ret; 267193323Sed tbs->key_usage = KeyUsage2int(ku); 268193323Sed } 269193323Sed if (flags & HX509_CA_TEMPLATE_EKU) { 270193323Sed ExtKeyUsage eku; 271193323Sed int i; 272193323Sed ret = _hx509_cert_get_eku(context, cert, &eku); 273193323Sed if (ret) 274193323Sed return ret; 275193323Sed for (i = 0; i < eku.len; i++) { 276193323Sed ret = hx509_ca_tbs_add_eku(context, tbs, &eku.val[i]); 277193323Sed if (ret) { 278193323Sed free_ExtKeyUsage(&eku); 279193323Sed return ret; 280193323Sed } 281193323Sed } 282193323Sed free_ExtKeyUsage(&eku); 283193323Sed } 284193323Sed return 0; 285193323Sed} 286193323Sed 287193323Sed/** 288193323Sed * Make the to-be-signed certificate object a CA certificate. If the 289193323Sed * pathLenConstraint is negative path length constraint is used. 290193323Sed * 291193323Sed * @param context A hx509 context. 292193323Sed * @param tbs object to be signed. 293193323Sed * @param pathLenConstraint path length constraint, negative, no 294193323Sed * constraint. 295193323Sed * 296193323Sed * @return An hx509 error code, see hx509_get_error_string(). 297193323Sed * 298193323Sed * @ingroup hx509_ca 299193323Sed */ 300193323Sed 301193323Sedint 302193323Sedhx509_ca_tbs_set_ca(hx509_context context, 303193323Sed hx509_ca_tbs tbs, 304193323Sed int pathLenConstraint) 305193323Sed{ 306207618Srdivacky tbs->flags.ca = 1; 307207618Srdivacky tbs->pathLenConstraint = pathLenConstraint; 308207618Srdivacky return 0; 309193323Sed} 310193323Sed 311193323Sed/** 312234353Sdim * Make the to-be-signed certificate object a proxy certificate. If the 313193323Sed * pathLenConstraint is negative path length constraint is used. 314193323Sed * 315193323Sed * @param context A hx509 context. 316193323Sed * @param tbs object to be signed. 317234353Sdim * @param pathLenConstraint path length constraint, negative, no 318193323Sed * constraint. 319193323Sed * 320193323Sed * @return An hx509 error code, see hx509_get_error_string(). 321193323Sed * 322193323Sed * @ingroup hx509_ca 323193323Sed */ 324193323Sed 325193323Sedint 326193323Sedhx509_ca_tbs_set_proxy(hx509_context context, 327226633Sdim hx509_ca_tbs tbs, 328193323Sed int pathLenConstraint) 329218893Sdim{ 330218893Sdim tbs->flags.proxy = 1; 331218893Sdim tbs->pathLenConstraint = pathLenConstraint; 332218893Sdim return 0; 333193323Sed} 334234353Sdim 335193323Sed 336193323Sed/** 337193323Sed * Make the to-be-signed certificate object a windows domain controller certificate. 338193323Sed * 339193323Sed * @param context A hx509 context. 340199481Srdivacky * @param tbs object to be signed. 341199481Srdivacky * 342199481Srdivacky * @return An hx509 error code, see hx509_get_error_string(). 343199481Srdivacky * 344199481Srdivacky * @ingroup hx509_ca 345199481Srdivacky */ 346199481Srdivacky 347193323Sedint 348224145Sdimhx509_ca_tbs_set_domaincontroller(hx509_context context, 349193323Sed hx509_ca_tbs tbs) 350224145Sdim{ 351224145Sdim tbs->flags.domaincontroller = 1; 352224145Sdim return 0; 353193323Sed} 354243830Sdim 355243830Sdim/** 356224145Sdim * Set the subject public key info (SPKI) in the to-be-signed certificate 357193323Sed * object. SPKI is the public key and key related parameters in the 358193323Sed * certificate. 359193323Sed * 360193323Sed * @param context A hx509 context. 361193323Sed * @param tbs object to be signed. 362193323Sed * @param spki subject public key info to use for the to-be-signed certificate object. 363193323Sed * 364193323Sed * @return An hx509 error code, see hx509_get_error_string(). 365193323Sed * 366193323Sed * @ingroup hx509_ca 367193323Sed */ 368224145Sdim 369224145Sdimint 370224145Sdimhx509_ca_tbs_set_spki(hx509_context context, 371224145Sdim hx509_ca_tbs tbs, 372224145Sdim const SubjectPublicKeyInfo *spki) 373224145Sdim{ 374193323Sed int ret; 375193323Sed free_SubjectPublicKeyInfo(&tbs->spki); 376199481Srdivacky ret = copy_SubjectPublicKeyInfo(spki, &tbs->spki); 377193323Sed tbs->flags.key = !ret; 378210299Sed return ret; 379210299Sed} 380210299Sed 381210299Sed/** 382210299Sed * Set the serial number to use for to-be-signed certificate object. 383234353Sdim * 384239462Sdim * @param context A hx509 context. 385239462Sdim * @param tbs object to be signed. 386239462Sdim * @param serialNumber serial number to use for the to-be-signed 387239462Sdim * certificate object. 388193323Sed * 389193323Sed * @return An hx509 error code, see hx509_get_error_string(). 390193323Sed * 391193323Sed * @ingroup hx509_ca 392193323Sed */ 393193323Sed 394193323Sedint 395193323Sedhx509_ca_tbs_set_serialnumber(hx509_context context, 396193323Sed hx509_ca_tbs tbs, 397193323Sed const heim_integer *serialNumber) 398193323Sed{ 399199989Srdivacky int ret; 400199989Srdivacky der_free_heim_integer(&tbs->serial); 401199989Srdivacky ret = der_copy_heim_integer(serialNumber, &tbs->serial); 402199989Srdivacky tbs->flags.serial = !ret; 403199989Srdivacky return ret; 404199989Srdivacky} 405234353Sdim 406210299Sed/** 407210299Sed * An an extended key usage to the to-be-signed certificate object. 408210299Sed * Duplicates will detected and not added. 409210299Sed * 410210299Sed * @param context A hx509 context. 411210299Sed * @param tbs object to be signed. 412218893Sdim * @param oid extended key usage to add. 413218893Sdim * 414218893Sdim * @return An hx509 error code, see hx509_get_error_string(). 415218893Sdim * 416218893Sdim * @ingroup hx509_ca 417193323Sed */ 418193323Sed 419193323Sedint 420193323Sedhx509_ca_tbs_add_eku(hx509_context context, 421234353Sdim hx509_ca_tbs tbs, 422193323Sed const heim_oid *oid) 423234353Sdim{ 424234353Sdim void *ptr; 425234353Sdim int ret; 426221345Sdim unsigned i; 427218893Sdim 428218893Sdim /* search for duplicates */ 429218893Sdim for (i = 0; i < tbs->eku.len; i++) { 430234353Sdim if (der_heim_oid_cmp(oid, &tbs->eku.val[i]) == 0) 431218893Sdim return 0; 432210299Sed } 433210299Sed 434210299Sed ptr = realloc(tbs->eku.val, sizeof(tbs->eku.val[0]) * (tbs->eku.len + 1)); 435210299Sed if (ptr == NULL) { 436210299Sed hx509_set_error_string(context, 0, ENOMEM, "out of memory"); 437210299Sed return ENOMEM; 438210299Sed } 439210299Sed tbs->eku.val = ptr; 440193323Sed ret = der_copy_oid(oid, &tbs->eku.val[tbs->eku.len]); 441193323Sed if (ret) { 442193323Sed hx509_set_error_string(context, 0, ret, "out of memory"); 443234353Sdim return ret; 444193323Sed } 445234353Sdim tbs->eku.len += 1; 446234353Sdim return 0; 447218893Sdim} 448234353Sdim 449234353Sdim/** 450234353Sdim * Add CRL distribution point URI to the to-be-signed certificate 451234353Sdim * object. 452234353Sdim * 453234353Sdim * @param context A hx509 context. 454193323Sed * @param tbs object to be signed. 455234353Sdim * @param uri uri to the CRL. 456234353Sdim * @param issuername name of the issuer. 457234353Sdim * 458234353Sdim * @return An hx509 error code, see hx509_get_error_string(). 459234353Sdim * 460234353Sdim * @ingroup hx509_ca 461234353Sdim */ 462234353Sdim 463234353Sdimint 464234353Sdimhx509_ca_tbs_add_crl_dp_uri(hx509_context context, 465193323Sed hx509_ca_tbs tbs, 466234353Sdim const char *uri, 467234353Sdim hx509_name issuername) 468234353Sdim{ 469234353Sdim DistributionPoint dp; 470234353Sdim int ret; 471234353Sdim 472234353Sdim memset(&dp, 0, sizeof(dp)); 473234353Sdim 474234353Sdim dp.distributionPoint = ecalloc(1, sizeof(*dp.distributionPoint)); 475234353Sdim 476234353Sdim { 477234353Sdim DistributionPointName name; 478234353Sdim GeneralName gn; 479234353Sdim size_t size; 480234353Sdim 481234353Sdim name.element = choice_DistributionPointName_fullName; 482234353Sdim name.u.fullName.len = 1; 483234353Sdim name.u.fullName.val = &gn; 484234353Sdim 485234353Sdim gn.element = choice_GeneralName_uniformResourceIdentifier; 486234353Sdim gn.u.uniformResourceIdentifier.data = rk_UNCONST(uri); 487234353Sdim gn.u.uniformResourceIdentifier.length = strlen(uri); 488234353Sdim 489234353Sdim ASN1_MALLOC_ENCODE(DistributionPointName, 490234353Sdim dp.distributionPoint->data, 491234353Sdim dp.distributionPoint->length, 492234353Sdim &name, &size, ret); 493234353Sdim if (ret) { 494234353Sdim hx509_set_error_string(context, 0, ret, 495234353Sdim "Failed to encoded DistributionPointName"); 496234353Sdim goto out; 497234353Sdim } 498234353Sdim if (dp.distributionPoint->length != size) 499234353Sdim _hx509_abort("internal ASN.1 encoder error"); 500234353Sdim } 501193323Sed 502193323Sed if (issuername) { 503234353Sdim#if 1 504234353Sdim /** 505193323Sed * issuername not supported 506193323Sed */ 507234353Sdim hx509_set_error_string(context, 0, EINVAL, 508193323Sed "CRLDistributionPoints.name.issuername not yet supported"); 509193323Sed return EINVAL; 510193323Sed#else 511234353Sdim GeneralNames *crlissuer; 512234353Sdim GeneralName gn; 513234353Sdim Name n; 514234353Sdim 515193323Sed crlissuer = calloc(1, sizeof(*crlissuer)); 516193323Sed if (crlissuer == NULL) { 517234353Sdim return ENOMEM; 518234353Sdim } 519193323Sed memset(&gn, 0, sizeof(gn)); 520193323Sed 521193323Sed gn.element = choice_GeneralName_directoryName; 522193323Sed ret = hx509_name_to_Name(issuername, &n); 523193323Sed if (ret) { 524234353Sdim hx509_set_error_string(context, 0, ret, "out of memory"); 525193323Sed goto out; 526193323Sed } 527193323Sed 528193323Sed gn.u.directoryName.element = n.element; 529193323Sed gn.u.directoryName.u.rdnSequence = n.u.rdnSequence; 530193323Sed 531193323Sed ret = add_GeneralNames(&crlissuer, &gn); 532193323Sed free_Name(&n); 533193323Sed if (ret) { 534193323Sed hx509_set_error_string(context, 0, ret, "out of memory"); 535193323Sed goto out; 536193323Sed } 537193323Sed 538193323Sed dp.cRLIssuer = &crlissuer; 539193323Sed#endif 540193323Sed } 541193323Sed 542193323Sed ret = add_CRLDistributionPoints(&tbs->crldp, &dp); 543202878Srdivacky if (ret) { 544203954Srdivacky hx509_set_error_string(context, 0, ret, "out of memory"); 545234353Sdim goto out; 546234353Sdim } 547234353Sdim 548234353Sdimout: 549202878Srdivacky free_DistributionPoint(&dp); 550243830Sdim 551243830Sdim return ret; 552243830Sdim} 553243830Sdim 554243830Sdim/** 555243830Sdim * Add Subject Alternative Name otherName to the to-be-signed 556243830Sdim * certificate object. 557243830Sdim * 558243830Sdim * @param context A hx509 context. 559243830Sdim * @param tbs object to be signed. 560243830Sdim * @param oid the oid of the OtherName. 561243830Sdim * @param os data in the other name. 562243830Sdim * 563243830Sdim * @return An hx509 error code, see hx509_get_error_string(). 564243830Sdim * 565243830Sdim * @ingroup hx509_ca 566243830Sdim */ 567243830Sdim 568243830Sdimint 569243830Sdimhx509_ca_tbs_add_san_otherName(hx509_context context, 570243830Sdim hx509_ca_tbs tbs, 571243830Sdim const heim_oid *oid, 572193323Sed const heim_octet_string *os) 573193323Sed{ 574218893Sdim GeneralName gn; 575193323Sed 576193323Sed memset(&gn, 0, sizeof(gn)); 577193323Sed gn.element = choice_GeneralName_otherName; 578193323Sed gn.u.otherName.type_id = *oid; 579193323Sed gn.u.otherName.value = *os; 580193323Sed 581193323Sed return add_GeneralNames(&tbs->san, &gn); 582193323Sed} 583203954Srdivacky 584203954Srdivacky/** 585205218Srdivacky * Add Kerberos Subject Alternative Name to the to-be-signed 586224145Sdim * certificate object. The principal string is a UTF8 string. 587224145Sdim * 588224145Sdim * @param context A hx509 context. 589224145Sdim * @param tbs object to be signed. 590224145Sdim * @param principal Kerberos principal to add to the certificate. 591224145Sdim * 592234353Sdim * @return An hx509 error code, see hx509_get_error_string(). 593224145Sdim * 594224145Sdim * @ingroup hx509_ca 595224145Sdim */ 596224145Sdim 597224145Sdimint 598224145Sdimhx509_ca_tbs_add_san_pkinit(hx509_context context, 599243830Sdim hx509_ca_tbs tbs, 600224145Sdim const char *principal) 601224145Sdim{ 602224145Sdim heim_octet_string os; 603193323Sed KRB5PrincipalName p; 604193323Sed size_t size; 605193323Sed int ret; 606193323Sed char *s = NULL; 607193323Sed 608193323Sed memset(&p, 0, sizeof(p)); 609193323Sed 610193323Sed /* parse principal */ 611193323Sed { 612193323Sed const char *str; 613193323Sed char *q; 614193323Sed int n; 615193323Sed 616193323Sed /* count number of component */ 617193323Sed n = 1; 618193323Sed for(str = principal; *str != '\0' && *str != '@'; str++){ 619193323Sed if(*str=='\\'){ 620193323Sed if(str[1] == '\0' || str[1] == '@') { 621198090Srdivacky ret = HX509_PARSING_NAME_FAILED; 622193323Sed hx509_set_error_string(context, 0, ret, 623199481Srdivacky "trailing \\ in principal name"); 624199481Srdivacky goto out; 625221345Sdim } 626221345Sdim str++; 627221345Sdim } else if(*str == '/') 628221345Sdim n++; 629221345Sdim } 630221345Sdim p.principalName.name_string.val = 631221345Sdim calloc(n, sizeof(*p.principalName.name_string.val)); 632221345Sdim if (p.principalName.name_string.val == NULL) { 633193323Sed ret = ENOMEM; 634193323Sed hx509_set_error_string(context, 0, ret, "malloc: out of memory"); 635193323Sed goto out; 636193323Sed } 637193323Sed p.principalName.name_string.len = n; 638193323Sed 639193323Sed p.principalName.name_type = KRB5_NT_PRINCIPAL; 640193323Sed q = s = strdup(principal); 641193323Sed if (q == NULL) { 642193323Sed ret = ENOMEM; 643193323Sed hx509_set_error_string(context, 0, ret, "malloc: out of memory"); 644193323Sed goto out; 645193323Sed } 646193323Sed p.realm = strrchr(q, '@'); 647193323Sed if (p.realm == NULL) { 648193323Sed ret = HX509_PARSING_NAME_FAILED; 649193323Sed hx509_set_error_string(context, 0, ret, "Missing @ in principal"); 650193323Sed goto out; 651193323Sed }; 652193323Sed *p.realm++ = '\0'; 653193323Sed 654193323Sed n = 0; 655193323Sed while (q) { 656193323Sed p.principalName.name_string.val[n++] = q; 657193323Sed q = strchr(q, '/'); 658193323Sed if (q) 659193323Sed *q++ = '\0'; 660193323Sed } 661193323Sed } 662193323Sed 663193323Sed ASN1_MALLOC_ENCODE(KRB5PrincipalName, os.data, os.length, &p, &size, ret); 664193323Sed if (ret) { 665193323Sed hx509_set_error_string(context, 0, ret, "Out of memory"); 666193323Sed goto out; 667193323Sed } 668193323Sed if (size != os.length) 669193323Sed _hx509_abort("internal ASN.1 encoder error"); 670193323Sed 671193323Sed ret = hx509_ca_tbs_add_san_otherName(context, 672193323Sed tbs, 673193323Sed &asn1_oid_id_pkinit_san, 674193323Sed &os); 675193323Sed free(os.data); 676193323Sedout: 677193323Sed if (p.principalName.name_string.val) 678193323Sed free (p.principalName.name_string.val); 679193323Sed if (s) 680193323Sed free(s); 681193323Sed return ret; 682193323Sed} 683193323Sed 684193323Sed/* 685193323Sed * 686193323Sed */ 687193323Sed 688193323Sedstatic int 689193323Sedadd_utf8_san(hx509_context context, 690193323Sed hx509_ca_tbs tbs, 691193323Sed const heim_oid *oid, 692193323Sed const char *string) 693193323Sed{ 694193323Sed const PKIXXmppAddr ustring = (const PKIXXmppAddr)string; 695193323Sed heim_octet_string os; 696193323Sed size_t size; 697193323Sed int ret; 698193323Sed 699193323Sed os.length = 0; 700193323Sed os.data = NULL; 701193323Sed 702193323Sed ASN1_MALLOC_ENCODE(PKIXXmppAddr, os.data, os.length, &ustring, &size, ret); 703193323Sed if (ret) { 704 hx509_set_error_string(context, 0, ret, "Out of memory"); 705 goto out; 706 } 707 if (size != os.length) 708 _hx509_abort("internal ASN.1 encoder error"); 709 710 ret = hx509_ca_tbs_add_san_otherName(context, 711 tbs, 712 oid, 713 &os); 714 free(os.data); 715out: 716 return ret; 717} 718 719/** 720 * Add Microsoft UPN Subject Alternative Name to the to-be-signed 721 * certificate object. The principal string is a UTF8 string. 722 * 723 * @param context A hx509 context. 724 * @param tbs object to be signed. 725 * @param principal Microsoft UPN string. 726 * 727 * @return An hx509 error code, see hx509_get_error_string(). 728 * 729 * @ingroup hx509_ca 730 */ 731 732int 733hx509_ca_tbs_add_san_ms_upn(hx509_context context, 734 hx509_ca_tbs tbs, 735 const char *principal) 736{ 737 return add_utf8_san(context, tbs, &asn1_oid_id_pkinit_ms_san, principal); 738} 739 740/** 741 * Add a Jabber/XMPP jid Subject Alternative Name to the to-be-signed 742 * certificate object. The jid is an UTF8 string. 743 * 744 * @param context A hx509 context. 745 * @param tbs object to be signed. 746 * @param jid string of an a jabber id in UTF8. 747 * 748 * @return An hx509 error code, see hx509_get_error_string(). 749 * 750 * @ingroup hx509_ca 751 */ 752 753int 754hx509_ca_tbs_add_san_jid(hx509_context context, 755 hx509_ca_tbs tbs, 756 const char *jid) 757{ 758 return add_utf8_san(context, tbs, &asn1_oid_id_pkix_on_xmppAddr, jid); 759} 760 761 762/** 763 * Add a Subject Alternative Name hostname to to-be-signed certificate 764 * object. A domain match starts with ., an exact match does not. 765 * 766 * Example of a an domain match: .domain.se matches the hostname 767 * host.domain.se. 768 * 769 * @param context A hx509 context. 770 * @param tbs object to be signed. 771 * @param dnsname a hostame. 772 * 773 * @return An hx509 error code, see hx509_get_error_string(). 774 * 775 * @ingroup hx509_ca 776 */ 777 778int 779hx509_ca_tbs_add_san_hostname(hx509_context context, 780 hx509_ca_tbs tbs, 781 const char *dnsname) 782{ 783 GeneralName gn; 784 785 memset(&gn, 0, sizeof(gn)); 786 gn.element = choice_GeneralName_dNSName; 787 gn.u.dNSName.data = rk_UNCONST(dnsname); 788 gn.u.dNSName.length = strlen(dnsname); 789 790 return add_GeneralNames(&tbs->san, &gn); 791} 792 793/** 794 * Add a Subject Alternative Name rfc822 (email address) to 795 * to-be-signed certificate object. 796 * 797 * @param context A hx509 context. 798 * @param tbs object to be signed. 799 * @param rfc822Name a string to a email address. 800 * 801 * @return An hx509 error code, see hx509_get_error_string(). 802 * 803 * @ingroup hx509_ca 804 */ 805 806int 807hx509_ca_tbs_add_san_rfc822name(hx509_context context, 808 hx509_ca_tbs tbs, 809 const char *rfc822Name) 810{ 811 GeneralName gn; 812 813 memset(&gn, 0, sizeof(gn)); 814 gn.element = choice_GeneralName_rfc822Name; 815 gn.u.rfc822Name.data = rk_UNCONST(rfc822Name); 816 gn.u.rfc822Name.length = strlen(rfc822Name); 817 818 return add_GeneralNames(&tbs->san, &gn); 819} 820 821/** 822 * Set the subject name of a to-be-signed certificate object. 823 * 824 * @param context A hx509 context. 825 * @param tbs object to be signed. 826 * @param subject the name to set a subject. 827 * 828 * @return An hx509 error code, see hx509_get_error_string(). 829 * 830 * @ingroup hx509_ca 831 */ 832 833int 834hx509_ca_tbs_set_subject(hx509_context context, 835 hx509_ca_tbs tbs, 836 hx509_name subject) 837{ 838 if (tbs->subject) 839 hx509_name_free(&tbs->subject); 840 return hx509_name_copy(context, subject, &tbs->subject); 841} 842 843/** 844 * Set the issuerUniqueID and subjectUniqueID 845 * 846 * These are only supposed to be used considered with version 2 847 * certificates, replaced by the two extensions SubjectKeyIdentifier 848 * and IssuerKeyIdentifier. This function is to allow application 849 * using legacy protocol to issue them. 850 * 851 * @param context A hx509 context. 852 * @param tbs object to be signed. 853 * @param issuerUniqueID to be set 854 * @param subjectUniqueID to be set 855 * 856 * @return An hx509 error code, see hx509_get_error_string(). 857 * 858 * @ingroup hx509_ca 859 */ 860 861int 862hx509_ca_tbs_set_unique(hx509_context context, 863 hx509_ca_tbs tbs, 864 const heim_bit_string *subjectUniqueID, 865 const heim_bit_string *issuerUniqueID) 866{ 867 int ret; 868 869 der_free_bit_string(&tbs->subjectUniqueID); 870 der_free_bit_string(&tbs->issuerUniqueID); 871 872 if (subjectUniqueID) { 873 ret = der_copy_bit_string(subjectUniqueID, &tbs->subjectUniqueID); 874 if (ret) 875 return ret; 876 } 877 878 if (issuerUniqueID) { 879 ret = der_copy_bit_string(issuerUniqueID, &tbs->issuerUniqueID); 880 if (ret) 881 return ret; 882 } 883 884 return 0; 885} 886 887/** 888 * Expand the the subject name in the to-be-signed certificate object 889 * using hx509_name_expand(). 890 * 891 * @param context A hx509 context. 892 * @param tbs object to be signed. 893 * @param env enviroment variable to expand variables in the subject 894 * name, see hx509_env_init(). 895 * 896 * @return An hx509 error code, see hx509_get_error_string(). 897 * 898 * @ingroup hx509_ca 899 */ 900 901int 902hx509_ca_tbs_subject_expand(hx509_context context, 903 hx509_ca_tbs tbs, 904 hx509_env env) 905{ 906 return hx509_name_expand(context, tbs->subject, env); 907} 908 909/* 910 * 911 */ 912 913static int 914add_extension(hx509_context context, 915 TBSCertificate *tbsc, 916 int critical_flag, 917 const heim_oid *oid, 918 const heim_octet_string *data) 919{ 920 Extension ext; 921 int ret; 922 923 memset(&ext, 0, sizeof(ext)); 924 925 if (critical_flag) { 926 ext.critical = malloc(sizeof(*ext.critical)); 927 if (ext.critical == NULL) { 928 ret = ENOMEM; 929 hx509_set_error_string(context, 0, ret, "Out of memory"); 930 goto out; 931 } 932 *ext.critical = TRUE; 933 } 934 935 ret = der_copy_oid(oid, &ext.extnID); 936 if (ret) { 937 hx509_set_error_string(context, 0, ret, "Out of memory"); 938 goto out; 939 } 940 ret = der_copy_octet_string(data, &ext.extnValue); 941 if (ret) { 942 hx509_set_error_string(context, 0, ret, "Out of memory"); 943 goto out; 944 } 945 ret = add_Extensions(tbsc->extensions, &ext); 946 if (ret) { 947 hx509_set_error_string(context, 0, ret, "Out of memory"); 948 goto out; 949 } 950out: 951 free_Extension(&ext); 952 return ret; 953} 954 955static int 956build_proxy_prefix(hx509_context context, const Name *issuer, Name *subject) 957{ 958 char *tstr; 959 time_t t; 960 int ret; 961 962 ret = copy_Name(issuer, subject); 963 if (ret) { 964 hx509_set_error_string(context, 0, ret, 965 "Failed to copy subject name"); 966 return ret; 967 } 968 969 t = time(NULL); 970 asprintf(&tstr, "ts-%lu", (unsigned long)t); 971 if (tstr == NULL) { 972 hx509_set_error_string(context, 0, ENOMEM, 973 "Failed to copy subject name"); 974 return ENOMEM; 975 } 976 /* prefix with CN=<ts>,...*/ 977 ret = _hx509_name_modify(context, subject, 1, &asn1_oid_id_at_commonName, tstr); 978 free(tstr); 979 if (ret) 980 free_Name(subject); 981 return ret; 982} 983 984static int 985ca_sign(hx509_context context, 986 hx509_ca_tbs tbs, 987 hx509_private_key signer, 988 const AuthorityKeyIdentifier *ai, 989 const Name *issuername, 990 hx509_cert *certificate) 991{ 992 heim_octet_string data; 993 Certificate c; 994 TBSCertificate *tbsc; 995 size_t size; 996 int ret; 997 const AlgorithmIdentifier *sigalg; 998 time_t notBefore; 999 time_t notAfter; 1000 unsigned key_usage; 1001 1002 sigalg = _hx509_crypto_default_sig_alg; 1003 1004 memset(&c, 0, sizeof(c)); 1005 1006 /* 1007 * Default values are: Valid since 24h ago, valid one year into 1008 * the future, KeyUsage digitalSignature and keyEncipherment set, 1009 * and keyCertSign for CA certificates. 1010 */ 1011 notBefore = tbs->notBefore; 1012 if (notBefore == 0) 1013 notBefore = time(NULL) - 3600 * 24; 1014 notAfter = tbs->notAfter; 1015 if (notAfter == 0) 1016 notAfter = time(NULL) + 3600 * 24 * 365; 1017 1018 key_usage = tbs->key_usage; 1019 if (key_usage == 0) { 1020 KeyUsage ku; 1021 memset(&ku, 0, sizeof(ku)); 1022 ku.digitalSignature = 1; 1023 ku.keyEncipherment = 1; 1024 key_usage = KeyUsage2int(ku); 1025 } 1026 1027 if (tbs->flags.ca) { 1028 KeyUsage ku; 1029 memset(&ku, 0, sizeof(ku)); 1030 ku.keyCertSign = 1; 1031 ku.cRLSign = 1; 1032 key_usage |= KeyUsage2int(ku); 1033 } 1034 1035 /* 1036 * 1037 */ 1038 1039 tbsc = &c.tbsCertificate; 1040 1041 if (tbs->flags.key == 0) { 1042 ret = EINVAL; 1043 hx509_set_error_string(context, 0, ret, "No public key set"); 1044 return ret; 1045 } 1046 /* 1047 * Don't put restrictions on proxy certificate's subject name, it 1048 * will be generated below. 1049 */ 1050 if (!tbs->flags.proxy) { 1051 if (tbs->subject == NULL) { 1052 hx509_set_error_string(context, 0, EINVAL, "No subject name set"); 1053 return EINVAL; 1054 } 1055 if (hx509_name_is_null_p(tbs->subject) && tbs->san.len == 0) { 1056 hx509_set_error_string(context, 0, EINVAL, 1057 "NULL subject and no SubjectAltNames"); 1058 return EINVAL; 1059 } 1060 } 1061 if (tbs->flags.ca && tbs->flags.proxy) { 1062 hx509_set_error_string(context, 0, EINVAL, "Can't be proxy and CA " 1063 "at the same time"); 1064 return EINVAL; 1065 } 1066 if (tbs->flags.proxy) { 1067 if (tbs->san.len > 0) { 1068 hx509_set_error_string(context, 0, EINVAL, 1069 "Proxy certificate is not allowed " 1070 "to have SubjectAltNames"); 1071 return EINVAL; 1072 } 1073 } 1074 1075 /* version [0] Version OPTIONAL, -- EXPLICIT nnn DEFAULT 1, */ 1076 tbsc->version = calloc(1, sizeof(*tbsc->version)); 1077 if (tbsc->version == NULL) { 1078 ret = ENOMEM; 1079 hx509_set_error_string(context, 0, ret, "Out of memory"); 1080 goto out; 1081 } 1082 *tbsc->version = rfc3280_version_3; 1083 /* serialNumber CertificateSerialNumber, */ 1084 if (tbs->flags.serial) { 1085 ret = der_copy_heim_integer(&tbs->serial, &tbsc->serialNumber); 1086 if (ret) { 1087 hx509_set_error_string(context, 0, ret, "Out of memory"); 1088 goto out; 1089 } 1090 } else { 1091 tbsc->serialNumber.length = 20; 1092 tbsc->serialNumber.data = malloc(tbsc->serialNumber.length); 1093 if (tbsc->serialNumber.data == NULL){ 1094 ret = ENOMEM; 1095 hx509_set_error_string(context, 0, ret, "Out of memory"); 1096 goto out; 1097 } 1098 /* XXX diffrent */ 1099 RAND_bytes(tbsc->serialNumber.data, tbsc->serialNumber.length); 1100 ((unsigned char *)tbsc->serialNumber.data)[0] &= 0x7f; 1101 } 1102 /* signature AlgorithmIdentifier, */ 1103 ret = copy_AlgorithmIdentifier(sigalg, &tbsc->signature); 1104 if (ret) { 1105 hx509_set_error_string(context, 0, ret, "Failed to copy sigature alg"); 1106 goto out; 1107 } 1108 /* issuer Name, */ 1109 if (issuername) 1110 ret = copy_Name(issuername, &tbsc->issuer); 1111 else 1112 ret = hx509_name_to_Name(tbs->subject, &tbsc->issuer); 1113 if (ret) { 1114 hx509_set_error_string(context, 0, ret, "Failed to copy issuer name"); 1115 goto out; 1116 } 1117 /* validity Validity, */ 1118 tbsc->validity.notBefore.element = choice_Time_generalTime; 1119 tbsc->validity.notBefore.u.generalTime = notBefore; 1120 tbsc->validity.notAfter.element = choice_Time_generalTime; 1121 tbsc->validity.notAfter.u.generalTime = notAfter; 1122 /* subject Name, */ 1123 if (tbs->flags.proxy) { 1124 ret = build_proxy_prefix(context, &tbsc->issuer, &tbsc->subject); 1125 if (ret) 1126 goto out; 1127 } else { 1128 ret = hx509_name_to_Name(tbs->subject, &tbsc->subject); 1129 if (ret) { 1130 hx509_set_error_string(context, 0, ret, 1131 "Failed to copy subject name"); 1132 goto out; 1133 } 1134 } 1135 /* subjectPublicKeyInfo SubjectPublicKeyInfo, */ 1136 ret = copy_SubjectPublicKeyInfo(&tbs->spki, &tbsc->subjectPublicKeyInfo); 1137 if (ret) { 1138 hx509_set_error_string(context, 0, ret, "Failed to copy spki"); 1139 goto out; 1140 } 1141 /* issuerUniqueID [1] IMPLICIT BIT STRING OPTIONAL */ 1142 if (tbs->issuerUniqueID.length) { 1143 tbsc->issuerUniqueID = calloc(1, sizeof(*tbsc->issuerUniqueID)); 1144 if (tbsc->issuerUniqueID == NULL) { 1145 ret = ENOMEM; 1146 hx509_set_error_string(context, 0, ret, "Out of memory"); 1147 goto out; 1148 } 1149 ret = der_copy_bit_string(&tbs->issuerUniqueID, tbsc->issuerUniqueID); 1150 if (ret) { 1151 hx509_set_error_string(context, 0, ret, "Out of memory"); 1152 goto out; 1153 } 1154 } 1155 /* subjectUniqueID [2] IMPLICIT BIT STRING OPTIONAL */ 1156 if (tbs->subjectUniqueID.length) { 1157 tbsc->subjectUniqueID = calloc(1, sizeof(*tbsc->subjectUniqueID)); 1158 if (tbsc->subjectUniqueID == NULL) { 1159 ret = ENOMEM; 1160 hx509_set_error_string(context, 0, ret, "Out of memory"); 1161 goto out; 1162 } 1163 1164 ret = der_copy_bit_string(&tbs->subjectUniqueID, tbsc->subjectUniqueID); 1165 if (ret) { 1166 hx509_set_error_string(context, 0, ret, "Out of memory"); 1167 goto out; 1168 } 1169 } 1170 1171 /* extensions [3] EXPLICIT Extensions OPTIONAL */ 1172 tbsc->extensions = calloc(1, sizeof(*tbsc->extensions)); 1173 if (tbsc->extensions == NULL) { 1174 ret = ENOMEM; 1175 hx509_set_error_string(context, 0, ret, "Out of memory"); 1176 goto out; 1177 } 1178 1179 /* Add the text BMP string Domaincontroller to the cert */ 1180 if (tbs->flags.domaincontroller) { 1181 data.data = rk_UNCONST("\x1e\x20\x00\x44\x00\x6f\x00\x6d" 1182 "\x00\x61\x00\x69\x00\x6e\x00\x43" 1183 "\x00\x6f\x00\x6e\x00\x74\x00\x72" 1184 "\x00\x6f\x00\x6c\x00\x6c\x00\x65" 1185 "\x00\x72"); 1186 data.length = 34; 1187 1188 ret = add_extension(context, tbsc, 0, 1189 &asn1_oid_id_ms_cert_enroll_domaincontroller, 1190 &data); 1191 if (ret) 1192 goto out; 1193 } 1194 1195 /* add KeyUsage */ 1196 { 1197 KeyUsage ku; 1198 1199 ku = int2KeyUsage(key_usage); 1200 ASN1_MALLOC_ENCODE(KeyUsage, data.data, data.length, &ku, &size, ret); 1201 if (ret) { 1202 hx509_set_error_string(context, 0, ret, "Out of memory"); 1203 goto out; 1204 } 1205 if (size != data.length) 1206 _hx509_abort("internal ASN.1 encoder error"); 1207 ret = add_extension(context, tbsc, 1, 1208 &asn1_oid_id_x509_ce_keyUsage, &data); 1209 free(data.data); 1210 if (ret) 1211 goto out; 1212 } 1213 1214 /* add ExtendedKeyUsage */ 1215 if (tbs->eku.len > 0) { 1216 ASN1_MALLOC_ENCODE(ExtKeyUsage, data.data, data.length, 1217 &tbs->eku, &size, ret); 1218 if (ret) { 1219 hx509_set_error_string(context, 0, ret, "Out of memory"); 1220 goto out; 1221 } 1222 if (size != data.length) 1223 _hx509_abort("internal ASN.1 encoder error"); 1224 ret = add_extension(context, tbsc, 0, 1225 &asn1_oid_id_x509_ce_extKeyUsage, &data); 1226 free(data.data); 1227 if (ret) 1228 goto out; 1229 } 1230 1231 /* add Subject Alternative Name */ 1232 if (tbs->san.len > 0) { 1233 ASN1_MALLOC_ENCODE(GeneralNames, data.data, data.length, 1234 &tbs->san, &size, ret); 1235 if (ret) { 1236 hx509_set_error_string(context, 0, ret, "Out of memory"); 1237 goto out; 1238 } 1239 if (size != data.length) 1240 _hx509_abort("internal ASN.1 encoder error"); 1241 ret = add_extension(context, tbsc, 0, 1242 &asn1_oid_id_x509_ce_subjectAltName, 1243 &data); 1244 free(data.data); 1245 if (ret) 1246 goto out; 1247 } 1248 1249 /* Add Authority Key Identifier */ 1250 if (ai) { 1251 ASN1_MALLOC_ENCODE(AuthorityKeyIdentifier, data.data, data.length, 1252 ai, &size, ret); 1253 if (ret) { 1254 hx509_set_error_string(context, 0, ret, "Out of memory"); 1255 goto out; 1256 } 1257 if (size != data.length) 1258 _hx509_abort("internal ASN.1 encoder error"); 1259 ret = add_extension(context, tbsc, 0, 1260 &asn1_oid_id_x509_ce_authorityKeyIdentifier, 1261 &data); 1262 free(data.data); 1263 if (ret) 1264 goto out; 1265 } 1266 1267 /* Add Subject Key Identifier */ 1268 { 1269 SubjectKeyIdentifier si; 1270 unsigned char hash[SHA_DIGEST_LENGTH]; 1271 1272 { 1273 EVP_MD_CTX *ctx; 1274 1275 ctx = EVP_MD_CTX_create(); 1276 EVP_DigestInit_ex(ctx, EVP_sha1(), NULL); 1277 EVP_DigestUpdate(ctx, tbs->spki.subjectPublicKey.data, 1278 tbs->spki.subjectPublicKey.length / 8); 1279 EVP_DigestFinal_ex(ctx, hash, NULL); 1280 EVP_MD_CTX_destroy(ctx); 1281 } 1282 1283 si.data = hash; 1284 si.length = sizeof(hash); 1285 1286 ASN1_MALLOC_ENCODE(SubjectKeyIdentifier, data.data, data.length, 1287 &si, &size, ret); 1288 if (ret) { 1289 hx509_set_error_string(context, 0, ret, "Out of memory"); 1290 goto out; 1291 } 1292 if (size != data.length) 1293 _hx509_abort("internal ASN.1 encoder error"); 1294 ret = add_extension(context, tbsc, 0, 1295 &asn1_oid_id_x509_ce_subjectKeyIdentifier, 1296 &data); 1297 free(data.data); 1298 if (ret) 1299 goto out; 1300 } 1301 1302 /* Add BasicConstraints */ 1303 { 1304 BasicConstraints bc; 1305 int aCA = 1; 1306 unsigned int path; 1307 1308 memset(&bc, 0, sizeof(bc)); 1309 1310 if (tbs->flags.ca) { 1311 bc.cA = &aCA; 1312 if (tbs->pathLenConstraint >= 0) { 1313 path = tbs->pathLenConstraint; 1314 bc.pathLenConstraint = &path; 1315 } 1316 } 1317 1318 ASN1_MALLOC_ENCODE(BasicConstraints, data.data, data.length, 1319 &bc, &size, ret); 1320 if (ret) { 1321 hx509_set_error_string(context, 0, ret, "Out of memory"); 1322 goto out; 1323 } 1324 if (size != data.length) 1325 _hx509_abort("internal ASN.1 encoder error"); 1326 /* Critical if this is a CA */ 1327 ret = add_extension(context, tbsc, tbs->flags.ca, 1328 &asn1_oid_id_x509_ce_basicConstraints, 1329 &data); 1330 free(data.data); 1331 if (ret) 1332 goto out; 1333 } 1334 1335 /* add Proxy */ 1336 if (tbs->flags.proxy) { 1337 ProxyCertInfo info; 1338 1339 memset(&info, 0, sizeof(info)); 1340 1341 if (tbs->pathLenConstraint >= 0) { 1342 info.pCPathLenConstraint = 1343 malloc(sizeof(*info.pCPathLenConstraint)); 1344 if (info.pCPathLenConstraint == NULL) { 1345 ret = ENOMEM; 1346 hx509_set_error_string(context, 0, ret, "Out of memory"); 1347 goto out; 1348 } 1349 *info.pCPathLenConstraint = tbs->pathLenConstraint; 1350 } 1351 1352 ret = der_copy_oid(&asn1_oid_id_pkix_ppl_inheritAll, 1353 &info.proxyPolicy.policyLanguage); 1354 if (ret) { 1355 free_ProxyCertInfo(&info); 1356 hx509_set_error_string(context, 0, ret, "Out of memory"); 1357 goto out; 1358 } 1359 1360 ASN1_MALLOC_ENCODE(ProxyCertInfo, data.data, data.length, 1361 &info, &size, ret); 1362 free_ProxyCertInfo(&info); 1363 if (ret) { 1364 hx509_set_error_string(context, 0, ret, "Out of memory"); 1365 goto out; 1366 } 1367 if (size != data.length) 1368 _hx509_abort("internal ASN.1 encoder error"); 1369 ret = add_extension(context, tbsc, 0, 1370 &asn1_oid_id_pkix_pe_proxyCertInfo, 1371 &data); 1372 free(data.data); 1373 if (ret) 1374 goto out; 1375 } 1376 1377 if (tbs->crldp.len) { 1378 1379 ASN1_MALLOC_ENCODE(CRLDistributionPoints, data.data, data.length, 1380 &tbs->crldp, &size, ret); 1381 if (ret) { 1382 hx509_set_error_string(context, 0, ret, "Out of memory"); 1383 goto out; 1384 } 1385 if (size != data.length) 1386 _hx509_abort("internal ASN.1 encoder error"); 1387 ret = add_extension(context, tbsc, FALSE, 1388 &asn1_oid_id_x509_ce_cRLDistributionPoints, 1389 &data); 1390 free(data.data); 1391 if (ret) 1392 goto out; 1393 } 1394 1395 ASN1_MALLOC_ENCODE(TBSCertificate, data.data, data.length,tbsc, &size, ret); 1396 if (ret) { 1397 hx509_set_error_string(context, 0, ret, "malloc out of memory"); 1398 goto out; 1399 } 1400 if (data.length != size) 1401 _hx509_abort("internal ASN.1 encoder error"); 1402 1403 ret = _hx509_create_signature_bitstring(context, 1404 signer, 1405 sigalg, 1406 &data, 1407 &c.signatureAlgorithm, 1408 &c.signatureValue); 1409 free(data.data); 1410 if (ret) 1411 goto out; 1412 1413 ret = hx509_cert_init(context, &c, certificate); 1414 if (ret) 1415 goto out; 1416 1417 free_Certificate(&c); 1418 1419 return 0; 1420 1421out: 1422 free_Certificate(&c); 1423 return ret; 1424} 1425 1426static int 1427get_AuthorityKeyIdentifier(hx509_context context, 1428 const Certificate *certificate, 1429 AuthorityKeyIdentifier *ai) 1430{ 1431 SubjectKeyIdentifier si; 1432 int ret; 1433 1434 ret = _hx509_find_extension_subject_key_id(certificate, &si); 1435 if (ret == 0) { 1436 ai->keyIdentifier = calloc(1, sizeof(*ai->keyIdentifier)); 1437 if (ai->keyIdentifier == NULL) { 1438 free_SubjectKeyIdentifier(&si); 1439 ret = ENOMEM; 1440 hx509_set_error_string(context, 0, ret, "Out of memory"); 1441 goto out; 1442 } 1443 ret = der_copy_octet_string(&si, ai->keyIdentifier); 1444 free_SubjectKeyIdentifier(&si); 1445 if (ret) { 1446 hx509_set_error_string(context, 0, ret, "Out of memory"); 1447 goto out; 1448 } 1449 } else { 1450 GeneralNames gns; 1451 GeneralName gn; 1452 Name name; 1453 1454 memset(&gn, 0, sizeof(gn)); 1455 memset(&gns, 0, sizeof(gns)); 1456 memset(&name, 0, sizeof(name)); 1457 1458 ai->authorityCertIssuer = 1459 calloc(1, sizeof(*ai->authorityCertIssuer)); 1460 if (ai->authorityCertIssuer == NULL) { 1461 ret = ENOMEM; 1462 hx509_set_error_string(context, 0, ret, "Out of memory"); 1463 goto out; 1464 } 1465 ai->authorityCertSerialNumber = 1466 calloc(1, sizeof(*ai->authorityCertSerialNumber)); 1467 if (ai->authorityCertSerialNumber == NULL) { 1468 ret = ENOMEM; 1469 hx509_set_error_string(context, 0, ret, "Out of memory"); 1470 goto out; 1471 } 1472 1473 /* 1474 * XXX unbreak when asn1 compiler handle IMPLICIT 1475 * 1476 * This is so horrible. 1477 */ 1478 1479 ret = copy_Name(&certificate->tbsCertificate.subject, &name); 1480 if (ret) { 1481 hx509_set_error_string(context, 0, ret, "Out of memory"); 1482 goto out; 1483 } 1484 1485 memset(&gn, 0, sizeof(gn)); 1486 gn.element = choice_GeneralName_directoryName; 1487 gn.u.directoryName.element = 1488 choice_GeneralName_directoryName_rdnSequence; 1489 gn.u.directoryName.u.rdnSequence = name.u.rdnSequence; 1490 1491 ret = add_GeneralNames(&gns, &gn); 1492 if (ret) { 1493 hx509_set_error_string(context, 0, ret, "Out of memory"); 1494 goto out; 1495 } 1496 1497 ai->authorityCertIssuer->val = gns.val; 1498 ai->authorityCertIssuer->len = gns.len; 1499 1500 ret = der_copy_heim_integer(&certificate->tbsCertificate.serialNumber, 1501 ai->authorityCertSerialNumber); 1502 if (ai->authorityCertSerialNumber == NULL) { 1503 ret = ENOMEM; 1504 hx509_set_error_string(context, 0, ret, "Out of memory"); 1505 goto out; 1506 } 1507 } 1508out: 1509 if (ret) 1510 free_AuthorityKeyIdentifier(ai); 1511 return ret; 1512} 1513 1514 1515/** 1516 * Sign a to-be-signed certificate object with a issuer certificate. 1517 * 1518 * The caller needs to at least have called the following functions on the 1519 * to-be-signed certificate object: 1520 * - hx509_ca_tbs_init() 1521 * - hx509_ca_tbs_set_subject() 1522 * - hx509_ca_tbs_set_spki() 1523 * 1524 * When done the to-be-signed certificate object should be freed with 1525 * hx509_ca_tbs_free(). 1526 * 1527 * When creating self-signed certificate use hx509_ca_sign_self() instead. 1528 * 1529 * @param context A hx509 context. 1530 * @param tbs object to be signed. 1531 * @param signer the CA certificate object to sign with (need private key). 1532 * @param certificate return cerificate, free with hx509_cert_free(). 1533 * 1534 * @return An hx509 error code, see hx509_get_error_string(). 1535 * 1536 * @ingroup hx509_ca 1537 */ 1538 1539int 1540hx509_ca_sign(hx509_context context, 1541 hx509_ca_tbs tbs, 1542 hx509_cert signer, 1543 hx509_cert *certificate) 1544{ 1545 const Certificate *signer_cert; 1546 AuthorityKeyIdentifier ai; 1547 int ret; 1548 1549 memset(&ai, 0, sizeof(ai)); 1550 1551 signer_cert = _hx509_get_cert(signer); 1552 1553 ret = get_AuthorityKeyIdentifier(context, signer_cert, &ai); 1554 if (ret) 1555 goto out; 1556 1557 ret = ca_sign(context, 1558 tbs, 1559 _hx509_cert_private_key(signer), 1560 &ai, 1561 &signer_cert->tbsCertificate.subject, 1562 certificate); 1563 1564out: 1565 free_AuthorityKeyIdentifier(&ai); 1566 1567 return ret; 1568} 1569 1570/** 1571 * Work just like hx509_ca_sign() but signs it-self. 1572 * 1573 * @param context A hx509 context. 1574 * @param tbs object to be signed. 1575 * @param signer private key to sign with. 1576 * @param certificate return cerificate, free with hx509_cert_free(). 1577 * 1578 * @return An hx509 error code, see hx509_get_error_string(). 1579 * 1580 * @ingroup hx509_ca 1581 */ 1582 1583int 1584hx509_ca_sign_self(hx509_context context, 1585 hx509_ca_tbs tbs, 1586 hx509_private_key signer, 1587 hx509_cert *certificate) 1588{ 1589 return ca_sign(context, 1590 tbs, 1591 signer, 1592 NULL, 1593 NULL, 1594 certificate); 1595} 1596