1 /* 2 * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <string.h> 10 11 #include <openssl/conf.h> 12 #include <openssl/err.h> 13 #include <openssl/opensslv.h> 14 #include <openssl/pem.h> 15 #include <openssl/sha.h> 16 #include <openssl/x509v3.h> 17 18 #include "cert.h" 19 #include "cmd_opt.h" 20 #include "debug.h" 21 #include "key.h" 22 #include "sha.h" 23 24 #define SERIAL_RAND_BITS 64 25 #define RSA_SALT_LEN 32 26 27 int rand_serial(BIGNUM *b, ASN1_INTEGER *ai) 28 { 29 BIGNUM *btmp; 30 int ret = 0; 31 if (b) 32 btmp = b; 33 else 34 btmp = BN_new(); 35 36 if (!btmp) 37 return 0; 38 39 if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0)) 40 goto error; 41 if (ai && !BN_to_ASN1_INTEGER(btmp, ai)) 42 goto error; 43 44 ret = 1; 45 46 error: 47 48 if (!b) 49 BN_free(btmp); 50 51 return ret; 52 } 53 const EVP_MD *get_digest(int alg) 54 { 55 switch (alg) { 56 case HASH_ALG_SHA256: 57 return EVP_sha256(); 58 case HASH_ALG_SHA384: 59 return EVP_sha384(); 60 case HASH_ALG_SHA512: 61 return EVP_sha512(); 62 default: 63 return NULL; 64 } 65 } 66 67 int cert_add_ext(X509 *issuer, X509 *subject, int nid, char *value) 68 { 69 X509_EXTENSION *ex; 70 X509V3_CTX ctx; 71 72 /* No configuration database */ 73 X509V3_set_ctx_nodb(&ctx); 74 75 /* Set issuer and subject certificates in the context */ 76 X509V3_set_ctx(&ctx, issuer, subject, NULL, NULL, 0); 77 ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value); 78 if (!ex) { 79 ERR_print_errors_fp(stdout); 80 return 0; 81 } 82 83 X509_add_ext(subject, ex, -1); 84 X509_EXTENSION_free(ex); 85 86 return 1; 87 } 88 89 int cert_new( 90 int md_alg, 91 cert_t *cert, 92 int days, 93 int ca, 94 STACK_OF(X509_EXTENSION) * sk) 95 { 96 EVP_PKEY *pkey = keys[cert->key].key; 97 cert_t *issuer_cert = &certs[cert->issuer]; 98 EVP_PKEY *ikey = keys[issuer_cert->key].key; 99 X509 *issuer = issuer_cert->x; 100 X509 *x; 101 X509_EXTENSION *ex; 102 X509_NAME *name; 103 ASN1_INTEGER *sno; 104 int i, num, rc = 0; 105 EVP_MD_CTX *mdCtx; 106 EVP_PKEY_CTX *pKeyCtx = NULL; 107 108 /* Create the certificate structure */ 109 x = X509_new(); 110 if (!x) { 111 return 0; 112 } 113 114 /* If we do not have a key, use the issuer key (the certificate will 115 * become self signed). This happens in content certificates. */ 116 if (!pkey) { 117 pkey = ikey; 118 } 119 120 /* If we do not have an issuer certificate, use our own (the certificate 121 * will become self signed) */ 122 if (!issuer) { 123 issuer = x; 124 } 125 126 mdCtx = EVP_MD_CTX_create(); 127 if (mdCtx == NULL) { 128 ERR_print_errors_fp(stdout); 129 goto END; 130 } 131 132 /* Sign the certificate with the issuer key */ 133 if (!EVP_DigestSignInit(mdCtx, &pKeyCtx, get_digest(md_alg), NULL, ikey)) { 134 ERR_print_errors_fp(stdout); 135 goto END; 136 } 137 138 /* 139 * Set additional parameters if issuing public key algorithm is RSA. 140 * This is not required for ECDSA. 141 */ 142 if (EVP_PKEY_base_id(ikey) == EVP_PKEY_RSA) { 143 if (!EVP_PKEY_CTX_set_rsa_padding(pKeyCtx, RSA_PKCS1_PSS_PADDING)) { 144 ERR_print_errors_fp(stdout); 145 goto END; 146 } 147 148 if (!EVP_PKEY_CTX_set_rsa_pss_saltlen(pKeyCtx, RSA_SALT_LEN)) { 149 ERR_print_errors_fp(stdout); 150 goto END; 151 } 152 153 if (!EVP_PKEY_CTX_set_rsa_mgf1_md(pKeyCtx, get_digest(md_alg))) { 154 ERR_print_errors_fp(stdout); 155 goto END; 156 } 157 } 158 159 /* x509.v3 */ 160 X509_set_version(x, 2); 161 162 /* Random serial number */ 163 sno = ASN1_INTEGER_new(); 164 rand_serial(NULL, sno); 165 X509_set_serialNumber(x, sno); 166 ASN1_INTEGER_free(sno); 167 168 X509_gmtime_adj(X509_get_notBefore(x), 0); 169 X509_gmtime_adj(X509_get_notAfter(x), (long)60*60*24*days); 170 X509_set_pubkey(x, pkey); 171 172 /* Subject name */ 173 name = X509_get_subject_name(x); 174 X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, 175 (const unsigned char *)cert->cn, -1, -1, 0); 176 X509_set_subject_name(x, name); 177 178 /* Issuer name */ 179 name = X509_get_issuer_name(x); 180 X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, 181 (const unsigned char *)issuer_cert->cn, -1, -1, 0); 182 X509_set_issuer_name(x, name); 183 184 /* Add various extensions: standard extensions */ 185 cert_add_ext(issuer, x, NID_subject_key_identifier, "hash"); 186 cert_add_ext(issuer, x, NID_authority_key_identifier, "keyid:always"); 187 if (ca) { 188 cert_add_ext(issuer, x, NID_basic_constraints, "CA:TRUE"); 189 cert_add_ext(issuer, x, NID_key_usage, "keyCertSign"); 190 } else { 191 cert_add_ext(issuer, x, NID_basic_constraints, "CA:FALSE"); 192 } 193 194 /* Add custom extensions */ 195 if (sk != NULL) { 196 num = sk_X509_EXTENSION_num(sk); 197 for (i = 0; i < num; i++) { 198 ex = sk_X509_EXTENSION_value(sk, i); 199 X509_add_ext(x, ex, -1); 200 } 201 } 202 203 if (!X509_sign_ctx(x, mdCtx)) { 204 ERR_print_errors_fp(stdout); 205 goto END; 206 } 207 208 /* X509 certificate signed successfully */ 209 rc = 1; 210 cert->x = x; 211 212 END: 213 EVP_MD_CTX_destroy(mdCtx); 214 return rc; 215 } 216 217 int cert_init(void) 218 { 219 cmd_opt_t cmd_opt; 220 cert_t *cert; 221 unsigned int i; 222 223 for (i = 0; i < num_certs; i++) { 224 cert = &certs[i]; 225 cmd_opt.long_opt.name = cert->opt; 226 cmd_opt.long_opt.has_arg = required_argument; 227 cmd_opt.long_opt.flag = NULL; 228 cmd_opt.long_opt.val = CMD_OPT_CERT; 229 cmd_opt.help_msg = cert->help_msg; 230 cmd_opt_add(&cmd_opt); 231 } 232 233 return 0; 234 } 235 236 cert_t *cert_get_by_opt(const char *opt) 237 { 238 cert_t *cert; 239 unsigned int i; 240 241 for (i = 0; i < num_certs; i++) { 242 cert = &certs[i]; 243 if (0 == strcmp(cert->opt, opt)) { 244 return cert; 245 } 246 } 247 248 return NULL; 249 } 250