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