1*6f971622SJuan Castillo /* 2*6f971622SJuan Castillo * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. 3*6f971622SJuan Castillo * 4*6f971622SJuan Castillo * Redistribution and use in source and binary forms, with or without 5*6f971622SJuan Castillo * modification, are permitted provided that the following conditions are met: 6*6f971622SJuan Castillo * 7*6f971622SJuan Castillo * Redistributions of source code must retain the above copyright notice, this 8*6f971622SJuan Castillo * list of conditions and the following disclaimer. 9*6f971622SJuan Castillo * 10*6f971622SJuan Castillo * Redistributions in binary form must reproduce the above copyright notice, 11*6f971622SJuan Castillo * this list of conditions and the following disclaimer in the documentation 12*6f971622SJuan Castillo * and/or other materials provided with the distribution. 13*6f971622SJuan Castillo * 14*6f971622SJuan Castillo * Neither the name of ARM nor the names of its contributors may be used 15*6f971622SJuan Castillo * to endorse or promote products derived from this software without specific 16*6f971622SJuan Castillo * prior written permission. 17*6f971622SJuan Castillo * 18*6f971622SJuan Castillo * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19*6f971622SJuan Castillo * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20*6f971622SJuan Castillo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21*6f971622SJuan Castillo * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22*6f971622SJuan Castillo * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23*6f971622SJuan Castillo * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24*6f971622SJuan Castillo * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25*6f971622SJuan Castillo * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26*6f971622SJuan Castillo * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27*6f971622SJuan Castillo * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28*6f971622SJuan Castillo * POSSIBILITY OF SUCH DAMAGE. 29*6f971622SJuan Castillo */ 30*6f971622SJuan Castillo 31*6f971622SJuan Castillo #include <stdio.h> 32*6f971622SJuan Castillo #include <stdlib.h> 33*6f971622SJuan Castillo #include <string.h> 34*6f971622SJuan Castillo 35*6f971622SJuan Castillo #include <openssl/conf.h> 36*6f971622SJuan Castillo #include <openssl/err.h> 37*6f971622SJuan Castillo #include <openssl/pem.h> 38*6f971622SJuan Castillo #include <openssl/sha.h> 39*6f971622SJuan Castillo #include <openssl/x509v3.h> 40*6f971622SJuan Castillo 41*6f971622SJuan Castillo #include "cert.h" 42*6f971622SJuan Castillo #include "debug.h" 43*6f971622SJuan Castillo #include "key.h" 44*6f971622SJuan Castillo #include "platform_oid.h" 45*6f971622SJuan Castillo #include "sha.h" 46*6f971622SJuan Castillo 47*6f971622SJuan Castillo #define SERIAL_RAND_BITS 64 48*6f971622SJuan Castillo 49*6f971622SJuan Castillo int rand_serial(BIGNUM *b, ASN1_INTEGER *ai) 50*6f971622SJuan Castillo { 51*6f971622SJuan Castillo BIGNUM *btmp; 52*6f971622SJuan Castillo int ret = 0; 53*6f971622SJuan Castillo if (b) 54*6f971622SJuan Castillo btmp = b; 55*6f971622SJuan Castillo else 56*6f971622SJuan Castillo btmp = BN_new(); 57*6f971622SJuan Castillo 58*6f971622SJuan Castillo if (!btmp) 59*6f971622SJuan Castillo return 0; 60*6f971622SJuan Castillo 61*6f971622SJuan Castillo if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0)) 62*6f971622SJuan Castillo goto error; 63*6f971622SJuan Castillo if (ai && !BN_to_ASN1_INTEGER(btmp, ai)) 64*6f971622SJuan Castillo goto error; 65*6f971622SJuan Castillo 66*6f971622SJuan Castillo ret = 1; 67*6f971622SJuan Castillo 68*6f971622SJuan Castillo error: 69*6f971622SJuan Castillo 70*6f971622SJuan Castillo if (!b) 71*6f971622SJuan Castillo BN_free(btmp); 72*6f971622SJuan Castillo 73*6f971622SJuan Castillo return ret; 74*6f971622SJuan Castillo } 75*6f971622SJuan Castillo 76*6f971622SJuan Castillo int cert_add_ext(X509 *issuer, X509 *subject, int nid, char *value) 77*6f971622SJuan Castillo { 78*6f971622SJuan Castillo X509_EXTENSION *ex; 79*6f971622SJuan Castillo X509V3_CTX ctx; 80*6f971622SJuan Castillo 81*6f971622SJuan Castillo /* No configuration database */ 82*6f971622SJuan Castillo X509V3_set_ctx_nodb(&ctx); 83*6f971622SJuan Castillo 84*6f971622SJuan Castillo /* Set issuer and subject certificates in the context */ 85*6f971622SJuan Castillo X509V3_set_ctx(&ctx, issuer, subject, NULL, NULL, 0); 86*6f971622SJuan Castillo ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value); 87*6f971622SJuan Castillo if (!ex) { 88*6f971622SJuan Castillo ERR_print_errors_fp(stdout); 89*6f971622SJuan Castillo return 0; 90*6f971622SJuan Castillo } 91*6f971622SJuan Castillo 92*6f971622SJuan Castillo X509_add_ext(subject, ex, -1); 93*6f971622SJuan Castillo X509_EXTENSION_free(ex); 94*6f971622SJuan Castillo 95*6f971622SJuan Castillo return 1; 96*6f971622SJuan Castillo } 97*6f971622SJuan Castillo 98*6f971622SJuan Castillo 99*6f971622SJuan Castillo int cert_new(cert_t *cert, int days, int ca, STACK_OF(X509_EXTENSION) * sk) 100*6f971622SJuan Castillo { 101*6f971622SJuan Castillo EVP_PKEY *pkey = cert->key->key; 102*6f971622SJuan Castillo EVP_PKEY *ikey = cert->issuer->key->key; 103*6f971622SJuan Castillo X509 *issuer = cert->issuer->x; 104*6f971622SJuan Castillo X509 *x = NULL; 105*6f971622SJuan Castillo X509_EXTENSION *ex = NULL; 106*6f971622SJuan Castillo X509_NAME *name = NULL; 107*6f971622SJuan Castillo ASN1_INTEGER *sno = NULL; 108*6f971622SJuan Castillo int i, num; 109*6f971622SJuan Castillo 110*6f971622SJuan Castillo /* Create the certificate structure */ 111*6f971622SJuan Castillo x = X509_new(); 112*6f971622SJuan Castillo if (!x) { 113*6f971622SJuan Castillo return 0; 114*6f971622SJuan Castillo } 115*6f971622SJuan Castillo 116*6f971622SJuan Castillo /* If we do not have a key, use the issuer key (the certificate will 117*6f971622SJuan Castillo * become self signed). This happens in content certificates. */ 118*6f971622SJuan Castillo if (!pkey) { 119*6f971622SJuan Castillo pkey = ikey; 120*6f971622SJuan Castillo } 121*6f971622SJuan Castillo 122*6f971622SJuan Castillo /* If we do not have an issuer certificate, use our own (the certificate 123*6f971622SJuan Castillo * will become self signed) */ 124*6f971622SJuan Castillo if (!issuer) { 125*6f971622SJuan Castillo issuer = x; 126*6f971622SJuan Castillo } 127*6f971622SJuan Castillo 128*6f971622SJuan Castillo /* x509.v3 */ 129*6f971622SJuan Castillo X509_set_version(x, 2); 130*6f971622SJuan Castillo 131*6f971622SJuan Castillo /* Random serial number */ 132*6f971622SJuan Castillo sno = ASN1_INTEGER_new(); 133*6f971622SJuan Castillo rand_serial(NULL, sno); 134*6f971622SJuan Castillo X509_set_serialNumber(x, sno); 135*6f971622SJuan Castillo ASN1_INTEGER_free(sno); 136*6f971622SJuan Castillo 137*6f971622SJuan Castillo X509_gmtime_adj(X509_get_notBefore(x), 0); 138*6f971622SJuan Castillo X509_gmtime_adj(X509_get_notAfter(x), (long)60*60*24*days); 139*6f971622SJuan Castillo X509_set_pubkey(x, pkey); 140*6f971622SJuan Castillo 141*6f971622SJuan Castillo /* Subject name */ 142*6f971622SJuan Castillo name = X509_get_subject_name(x); 143*6f971622SJuan Castillo X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, 144*6f971622SJuan Castillo (const unsigned char *)cert->cn, -1, -1, 0); 145*6f971622SJuan Castillo X509_set_subject_name(x, name); 146*6f971622SJuan Castillo 147*6f971622SJuan Castillo /* Issuer name */ 148*6f971622SJuan Castillo name = X509_get_issuer_name(x); 149*6f971622SJuan Castillo X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, 150*6f971622SJuan Castillo (const unsigned char *)cert->issuer->cn, -1, -1, 0); 151*6f971622SJuan Castillo X509_set_issuer_name(x, name); 152*6f971622SJuan Castillo 153*6f971622SJuan Castillo /* Add various extensions: standard extensions */ 154*6f971622SJuan Castillo cert_add_ext(issuer, x, NID_subject_key_identifier, "hash"); 155*6f971622SJuan Castillo cert_add_ext(issuer, x, NID_authority_key_identifier, "keyid:always"); 156*6f971622SJuan Castillo if (ca) { 157*6f971622SJuan Castillo cert_add_ext(issuer, x, NID_basic_constraints, "CA:TRUE"); 158*6f971622SJuan Castillo cert_add_ext(issuer, x, NID_key_usage, "keyCertSign"); 159*6f971622SJuan Castillo } else { 160*6f971622SJuan Castillo cert_add_ext(issuer, x, NID_basic_constraints, "CA:FALSE"); 161*6f971622SJuan Castillo } 162*6f971622SJuan Castillo 163*6f971622SJuan Castillo /* Add custom extensions */ 164*6f971622SJuan Castillo if (sk != NULL) { 165*6f971622SJuan Castillo num = sk_X509_EXTENSION_num(sk); 166*6f971622SJuan Castillo for (i = 0; i < num; i++) { 167*6f971622SJuan Castillo ex = sk_X509_EXTENSION_value(sk, i); 168*6f971622SJuan Castillo X509_add_ext(x, ex, -1); 169*6f971622SJuan Castillo } 170*6f971622SJuan Castillo } 171*6f971622SJuan Castillo 172*6f971622SJuan Castillo /* Sign the certificate with the issuer key */ 173*6f971622SJuan Castillo if (!X509_sign(x, ikey, EVP_sha1())) { 174*6f971622SJuan Castillo ERR_print_errors_fp(stdout); 175*6f971622SJuan Castillo return 0; 176*6f971622SJuan Castillo } 177*6f971622SJuan Castillo 178*6f971622SJuan Castillo cert->x = x; 179*6f971622SJuan Castillo return 1; 180*6f971622SJuan Castillo } 181