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