1 /* 2 * Copyright (c) 2015-2022, 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 26 cert_t *certs; 27 unsigned int num_certs; 28 29 int rand_serial(BIGNUM *b, ASN1_INTEGER *ai) 30 { 31 BIGNUM *btmp; 32 int ret = 0; 33 if (b) 34 btmp = b; 35 else 36 btmp = BN_new(); 37 38 if (!btmp) 39 return 0; 40 41 #if USING_OPENSSL3 42 if (!BN_rand(btmp, SERIAL_RAND_BITS, 0, 0)) 43 #else 44 if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0)) 45 #endif 46 goto error; 47 if (ai && !BN_to_ASN1_INTEGER(btmp, ai)) 48 goto error; 49 50 ret = 1; 51 52 error: 53 54 if (!b) 55 BN_free(btmp); 56 57 return ret; 58 } 59 const EVP_MD *get_digest(int alg) 60 { 61 switch (alg) { 62 case HASH_ALG_SHA256: 63 return EVP_sha256(); 64 case HASH_ALG_SHA384: 65 return EVP_sha384(); 66 case HASH_ALG_SHA512: 67 return EVP_sha512(); 68 default: 69 return NULL; 70 } 71 } 72 73 int cert_add_ext(X509 *issuer, X509 *subject, int nid, char *value) 74 { 75 X509_EXTENSION *ex; 76 X509V3_CTX ctx; 77 78 /* No configuration database */ 79 X509V3_set_ctx_nodb(&ctx); 80 81 /* Set issuer and subject certificates in the context */ 82 X509V3_set_ctx(&ctx, issuer, subject, NULL, NULL, 0); 83 ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value); 84 if (!ex) { 85 ERR_print_errors_fp(stdout); 86 return 0; 87 } 88 89 X509_add_ext(subject, ex, -1); 90 X509_EXTENSION_free(ex); 91 92 return 1; 93 } 94 95 int cert_new( 96 int md_alg, 97 cert_t *cert, 98 int days, 99 int ca, 100 STACK_OF(X509_EXTENSION) * sk) 101 { 102 EVP_PKEY *pkey = keys[cert->key].key; 103 cert_t *issuer_cert = &certs[cert->issuer]; 104 EVP_PKEY *ikey = keys[issuer_cert->key].key; 105 X509 *issuer = issuer_cert->x; 106 X509 *x; 107 X509_EXTENSION *ex; 108 X509_NAME *name; 109 ASN1_INTEGER *sno; 110 int i, num, rc = 0; 111 EVP_MD_CTX *mdCtx; 112 EVP_PKEY_CTX *pKeyCtx = NULL; 113 114 /* Create the certificate structure */ 115 x = X509_new(); 116 if (!x) { 117 return 0; 118 } 119 120 /* If we do not have a key, use the issuer key (the certificate will 121 * become self signed). This happens in content certificates. */ 122 if (!pkey) { 123 pkey = ikey; 124 } 125 126 /* If we do not have an issuer certificate, use our own (the certificate 127 * will become self signed) */ 128 if (!issuer) { 129 issuer = x; 130 } 131 132 mdCtx = EVP_MD_CTX_create(); 133 if (mdCtx == NULL) { 134 ERR_print_errors_fp(stdout); 135 goto END; 136 } 137 138 /* Sign the certificate with the issuer key */ 139 if (!EVP_DigestSignInit(mdCtx, &pKeyCtx, get_digest(md_alg), NULL, ikey)) { 140 ERR_print_errors_fp(stdout); 141 goto END; 142 } 143 144 /* 145 * Set additional parameters if issuing public key algorithm is RSA. 146 * This is not required for ECDSA. 147 */ 148 if (EVP_PKEY_base_id(ikey) == EVP_PKEY_RSA) { 149 if (!EVP_PKEY_CTX_set_rsa_padding(pKeyCtx, RSA_PKCS1_PSS_PADDING)) { 150 ERR_print_errors_fp(stdout); 151 goto END; 152 } 153 154 if (!EVP_PKEY_CTX_set_rsa_pss_saltlen(pKeyCtx, EVP_MD_size(get_digest(md_alg)))) { 155 ERR_print_errors_fp(stdout); 156 goto END; 157 } 158 159 if (!EVP_PKEY_CTX_set_rsa_mgf1_md(pKeyCtx, get_digest(md_alg))) { 160 ERR_print_errors_fp(stdout); 161 goto END; 162 } 163 } 164 165 /* x509.v3 */ 166 X509_set_version(x, 2); 167 168 /* Random serial number */ 169 sno = ASN1_INTEGER_new(); 170 rand_serial(NULL, sno); 171 X509_set_serialNumber(x, sno); 172 ASN1_INTEGER_free(sno); 173 174 X509_gmtime_adj(X509_get_notBefore(x), 0); 175 X509_gmtime_adj(X509_get_notAfter(x), (long)60*60*24*days); 176 X509_set_pubkey(x, pkey); 177 178 /* Subject name */ 179 name = X509_get_subject_name(x); 180 X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, 181 (const unsigned char *)cert->cn, -1, -1, 0); 182 X509_set_subject_name(x, name); 183 184 /* Issuer name */ 185 name = X509_get_issuer_name(x); 186 X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, 187 (const unsigned char *)issuer_cert->cn, -1, -1, 0); 188 X509_set_issuer_name(x, name); 189 190 /* Add various extensions: standard extensions */ 191 cert_add_ext(issuer, x, NID_subject_key_identifier, "hash"); 192 cert_add_ext(issuer, x, NID_authority_key_identifier, "keyid:always"); 193 if (ca) { 194 cert_add_ext(issuer, x, NID_basic_constraints, "CA:TRUE"); 195 cert_add_ext(issuer, x, NID_key_usage, "keyCertSign"); 196 } else { 197 cert_add_ext(issuer, x, NID_basic_constraints, "CA:FALSE"); 198 } 199 200 /* Add custom extensions */ 201 if (sk != NULL) { 202 num = sk_X509_EXTENSION_num(sk); 203 for (i = 0; i < num; i++) { 204 ex = sk_X509_EXTENSION_value(sk, i); 205 X509_add_ext(x, ex, -1); 206 } 207 } 208 209 if (!X509_sign_ctx(x, mdCtx)) { 210 ERR_print_errors_fp(stdout); 211 goto END; 212 } 213 214 /* X509 certificate signed successfully */ 215 rc = 1; 216 cert->x = x; 217 218 END: 219 EVP_MD_CTX_destroy(mdCtx); 220 return rc; 221 } 222 223 int cert_init(void) 224 { 225 cmd_opt_t cmd_opt; 226 cert_t *cert; 227 unsigned int i; 228 229 certs = malloc((num_def_certs * sizeof(def_certs[0])) 230 #ifdef PDEF_CERTS 231 + (num_pdef_certs * sizeof(pdef_certs[0])) 232 #endif 233 ); 234 if (certs == NULL) { 235 ERROR("%s:%d Failed to allocate memory.\n", __func__, __LINE__); 236 return 1; 237 } 238 239 memcpy(&certs[0], &def_certs[0], 240 (num_def_certs * sizeof(def_certs[0]))); 241 242 #ifdef PDEF_CERTS 243 memcpy(&certs[num_def_certs], &pdef_certs[0], 244 (num_pdef_certs * sizeof(pdef_certs[0]))); 245 246 num_certs = num_def_certs + num_pdef_certs; 247 #else 248 num_certs = num_def_certs; 249 #endif 250 251 for (i = 0; i < num_certs; i++) { 252 cert = &certs[i]; 253 cmd_opt.long_opt.name = cert->opt; 254 cmd_opt.long_opt.has_arg = required_argument; 255 cmd_opt.long_opt.flag = NULL; 256 cmd_opt.long_opt.val = CMD_OPT_CERT; 257 cmd_opt.help_msg = cert->help_msg; 258 cmd_opt_add(&cmd_opt); 259 } 260 261 return 0; 262 } 263 264 cert_t *cert_get_by_opt(const char *opt) 265 { 266 cert_t *cert; 267 unsigned int i; 268 269 for (i = 0; i < num_certs; i++) { 270 cert = &certs[i]; 271 if (0 == strcmp(cert->opt, opt)) { 272 return cert; 273 } 274 } 275 276 return NULL; 277 } 278 279 void cert_cleanup(void) 280 { 281 unsigned int i; 282 283 for (i = 0; i < num_certs; i++) { 284 if (certs[i].fn != NULL) { 285 void *ptr = (void *)certs[i].fn; 286 287 certs[i].fn = NULL; 288 free(ptr); 289 } 290 } 291 free(certs); 292 } 293 294