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