xref: /rk3399_ARM-atf/tools/cert_create/src/cert.c (revision 2972247cb4ae84ed660532cac426259a4f17c816)
16f971622SJuan Castillo /*
2bb41eb7aSMasahiro Yamada  * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
36f971622SJuan Castillo  *
482cb2c1aSdp-arm  * SPDX-License-Identifier: BSD-3-Clause
56f971622SJuan Castillo  */
66f971622SJuan Castillo 
76f971622SJuan Castillo #include <stdio.h>
86f971622SJuan Castillo #include <stdlib.h>
96f971622SJuan Castillo #include <string.h>
106f971622SJuan Castillo 
116f971622SJuan Castillo #include <openssl/conf.h>
126f971622SJuan Castillo #include <openssl/err.h>
131f33ad4eSSoby Mathew #include <openssl/opensslv.h>
146f971622SJuan Castillo #include <openssl/pem.h>
156f971622SJuan Castillo #include <openssl/sha.h>
166f971622SJuan Castillo #include <openssl/x509v3.h>
176f971622SJuan Castillo 
18bb41eb7aSMasahiro Yamada #if USE_TBBR_DEFS
19bb41eb7aSMasahiro Yamada #include <tbbr_oid.h>
20bb41eb7aSMasahiro Yamada #else
21bb41eb7aSMasahiro Yamada #include <platform_oid.h>
22bb41eb7aSMasahiro Yamada #endif
23bb41eb7aSMasahiro Yamada 
246f971622SJuan Castillo #include "cert.h"
25ad2c1a9aSJuan Castillo #include "cmd_opt.h"
266f971622SJuan Castillo #include "debug.h"
276f971622SJuan Castillo #include "key.h"
286f971622SJuan Castillo #include "sha.h"
296f971622SJuan Castillo 
306f971622SJuan Castillo #define SERIAL_RAND_BITS	64
311f33ad4eSSoby Mathew #define RSA_SALT_LEN		32
326f971622SJuan Castillo 
336f971622SJuan Castillo int rand_serial(BIGNUM *b, ASN1_INTEGER *ai)
346f971622SJuan Castillo {
356f971622SJuan Castillo 	BIGNUM *btmp;
366f971622SJuan Castillo 	int ret = 0;
376f971622SJuan Castillo 	if (b)
386f971622SJuan Castillo 		btmp = b;
396f971622SJuan Castillo 	else
406f971622SJuan Castillo 		btmp = BN_new();
416f971622SJuan Castillo 
426f971622SJuan Castillo 	if (!btmp)
436f971622SJuan Castillo 		return 0;
446f971622SJuan Castillo 
456f971622SJuan Castillo 	if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0))
466f971622SJuan Castillo 		goto error;
476f971622SJuan Castillo 	if (ai && !BN_to_ASN1_INTEGER(btmp, ai))
486f971622SJuan Castillo 		goto error;
496f971622SJuan Castillo 
506f971622SJuan Castillo 	ret = 1;
516f971622SJuan Castillo 
526f971622SJuan Castillo error:
536f971622SJuan Castillo 
546f971622SJuan Castillo 	if (!b)
556f971622SJuan Castillo 		BN_free(btmp);
566f971622SJuan Castillo 
576f971622SJuan Castillo 	return ret;
586f971622SJuan Castillo }
59*2972247cSQixiang Xu const EVP_MD *get_digest(int alg)
60*2972247cSQixiang Xu {
61*2972247cSQixiang Xu 	switch (alg) {
62*2972247cSQixiang Xu 	case HASH_ALG_SHA256:
63*2972247cSQixiang Xu 		return EVP_sha256();
64*2972247cSQixiang Xu 	case HASH_ALG_SHA384:
65*2972247cSQixiang Xu 		return EVP_sha384();
66*2972247cSQixiang Xu 	case HASH_ALG_SHA512:
67*2972247cSQixiang Xu 		return EVP_sha512();
68*2972247cSQixiang Xu 	default:
69*2972247cSQixiang Xu 		return NULL;
70*2972247cSQixiang Xu 	}
71*2972247cSQixiang Xu }
726f971622SJuan Castillo 
736f971622SJuan Castillo int cert_add_ext(X509 *issuer, X509 *subject, int nid, char *value)
746f971622SJuan Castillo {
756f971622SJuan Castillo 	X509_EXTENSION *ex;
766f971622SJuan Castillo 	X509V3_CTX ctx;
776f971622SJuan Castillo 
786f971622SJuan Castillo 	/* No configuration database */
796f971622SJuan Castillo 	X509V3_set_ctx_nodb(&ctx);
806f971622SJuan Castillo 
816f971622SJuan Castillo 	/* Set issuer and subject certificates in the context */
826f971622SJuan Castillo 	X509V3_set_ctx(&ctx, issuer, subject, NULL, NULL, 0);
836f971622SJuan Castillo 	ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
846f971622SJuan Castillo 	if (!ex) {
856f971622SJuan Castillo 		ERR_print_errors_fp(stdout);
866f971622SJuan Castillo 		return 0;
876f971622SJuan Castillo 	}
886f971622SJuan Castillo 
896f971622SJuan Castillo 	X509_add_ext(subject, ex, -1);
906f971622SJuan Castillo 	X509_EXTENSION_free(ex);
916f971622SJuan Castillo 
926f971622SJuan Castillo 	return 1;
936f971622SJuan Castillo }
946f971622SJuan Castillo 
95*2972247cSQixiang Xu int cert_new(
96*2972247cSQixiang Xu 	int key_alg,
97*2972247cSQixiang Xu 	int md_alg,
98*2972247cSQixiang Xu 	cert_t *cert,
99*2972247cSQixiang Xu 	int days,
100*2972247cSQixiang Xu 	int ca,
101*2972247cSQixiang Xu 	STACK_OF(X509_EXTENSION) * sk)
1026f971622SJuan Castillo {
10355e291a4SJuan Castillo 	EVP_PKEY *pkey = keys[cert->key].key;
10455e291a4SJuan Castillo 	cert_t *issuer_cert = &certs[cert->issuer];
10555e291a4SJuan Castillo 	EVP_PKEY *ikey = keys[issuer_cert->key].key;
10655e291a4SJuan Castillo 	X509 *issuer = issuer_cert->x;
107c893c733SMasahiro Yamada 	X509 *x;
108c893c733SMasahiro Yamada 	X509_EXTENSION *ex;
109c893c733SMasahiro Yamada 	X509_NAME *name;
110c893c733SMasahiro Yamada 	ASN1_INTEGER *sno;
1111f33ad4eSSoby Mathew 	int i, num, rc = 0;
112742c4e14SMichalis Pappas 	EVP_MD_CTX *mdCtx;
1131f33ad4eSSoby Mathew 	EVP_PKEY_CTX *pKeyCtx = NULL;
1146f971622SJuan Castillo 
1156f971622SJuan Castillo 	/* Create the certificate structure */
1166f971622SJuan Castillo 	x = X509_new();
1176f971622SJuan Castillo 	if (!x) {
1186f971622SJuan Castillo 		return 0;
1196f971622SJuan Castillo 	}
1206f971622SJuan Castillo 
1216f971622SJuan Castillo 	/* If we do not have a key, use the issuer key (the certificate will
1226f971622SJuan Castillo 	 * become self signed). This happens in content certificates. */
1236f971622SJuan Castillo 	if (!pkey) {
1246f971622SJuan Castillo 		pkey = ikey;
1256f971622SJuan Castillo 	}
1266f971622SJuan Castillo 
1276f971622SJuan Castillo 	/* If we do not have an issuer certificate, use our own (the certificate
1286f971622SJuan Castillo 	 * will become self signed) */
1296f971622SJuan Castillo 	if (!issuer) {
1306f971622SJuan Castillo 		issuer = x;
1316f971622SJuan Castillo 	}
1326f971622SJuan Castillo 
133742c4e14SMichalis Pappas 	mdCtx = EVP_MD_CTX_create();
134742c4e14SMichalis Pappas 	if (mdCtx == NULL) {
135742c4e14SMichalis Pappas 		ERR_print_errors_fp(stdout);
136742c4e14SMichalis Pappas 		goto END;
137742c4e14SMichalis Pappas 	}
138a8eb286aSSoby Mathew 
139a8eb286aSSoby Mathew 	/* Sign the certificate with the issuer key */
140*2972247cSQixiang Xu 	if (!EVP_DigestSignInit(mdCtx, &pKeyCtx, get_digest(md_alg), NULL, ikey)) {
1411f33ad4eSSoby Mathew 		ERR_print_errors_fp(stdout);
1421f33ad4eSSoby Mathew 		goto END;
1431f33ad4eSSoby Mathew 	}
1441f33ad4eSSoby Mathew 
145a8eb286aSSoby Mathew 	/*
146a8eb286aSSoby Mathew 	 * Set additional parameters if algorithm is RSA PSS. This is not
147a8eb286aSSoby Mathew 	 * required for RSA 1.5 or ECDSA.
148a8eb286aSSoby Mathew 	 */
149a8eb286aSSoby Mathew 	if (key_alg == KEY_ALG_RSA) {
1501f33ad4eSSoby Mathew 		if (!EVP_PKEY_CTX_set_rsa_padding(pKeyCtx, RSA_PKCS1_PSS_PADDING)) {
1511f33ad4eSSoby Mathew 			ERR_print_errors_fp(stdout);
1521f33ad4eSSoby Mathew 			goto END;
1531f33ad4eSSoby Mathew 		}
1541f33ad4eSSoby Mathew 
1551f33ad4eSSoby Mathew 		if (!EVP_PKEY_CTX_set_rsa_pss_saltlen(pKeyCtx, RSA_SALT_LEN)) {
1561f33ad4eSSoby Mathew 			ERR_print_errors_fp(stdout);
1571f33ad4eSSoby Mathew 			goto END;
1581f33ad4eSSoby Mathew 		}
1591f33ad4eSSoby Mathew 
160*2972247cSQixiang Xu 		if (!EVP_PKEY_CTX_set_rsa_mgf1_md(pKeyCtx, get_digest(md_alg))) {
1611f33ad4eSSoby Mathew 			ERR_print_errors_fp(stdout);
1621f33ad4eSSoby Mathew 			goto END;
1631f33ad4eSSoby Mathew 		}
164a8eb286aSSoby Mathew 	}
1651f33ad4eSSoby Mathew 
1666f971622SJuan Castillo 	/* x509.v3 */
1676f971622SJuan Castillo 	X509_set_version(x, 2);
1686f971622SJuan Castillo 
1696f971622SJuan Castillo 	/* Random serial number */
1706f971622SJuan Castillo 	sno = ASN1_INTEGER_new();
1716f971622SJuan Castillo 	rand_serial(NULL, sno);
1726f971622SJuan Castillo 	X509_set_serialNumber(x, sno);
1736f971622SJuan Castillo 	ASN1_INTEGER_free(sno);
1746f971622SJuan Castillo 
1756f971622SJuan Castillo 	X509_gmtime_adj(X509_get_notBefore(x), 0);
1766f971622SJuan Castillo 	X509_gmtime_adj(X509_get_notAfter(x), (long)60*60*24*days);
1776f971622SJuan Castillo 	X509_set_pubkey(x, pkey);
1786f971622SJuan Castillo 
1796f971622SJuan Castillo 	/* Subject name */
1806f971622SJuan Castillo 	name = X509_get_subject_name(x);
1816f971622SJuan Castillo 	X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
1826f971622SJuan Castillo 			(const unsigned char *)cert->cn, -1, -1, 0);
1836f971622SJuan Castillo 	X509_set_subject_name(x, name);
1846f971622SJuan Castillo 
1856f971622SJuan Castillo 	/* Issuer name */
1866f971622SJuan Castillo 	name = X509_get_issuer_name(x);
1876f971622SJuan Castillo 	X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
18855e291a4SJuan Castillo 			(const unsigned char *)issuer_cert->cn, -1, -1, 0);
1896f971622SJuan Castillo 	X509_set_issuer_name(x, name);
1906f971622SJuan Castillo 
1916f971622SJuan Castillo 	/* Add various extensions: standard extensions */
1926f971622SJuan Castillo 	cert_add_ext(issuer, x, NID_subject_key_identifier, "hash");
1936f971622SJuan Castillo 	cert_add_ext(issuer, x, NID_authority_key_identifier, "keyid:always");
1946f971622SJuan Castillo 	if (ca) {
1956f971622SJuan Castillo 		cert_add_ext(issuer, x, NID_basic_constraints, "CA:TRUE");
1966f971622SJuan Castillo 		cert_add_ext(issuer, x, NID_key_usage, "keyCertSign");
1976f971622SJuan Castillo 	} else {
1986f971622SJuan Castillo 		cert_add_ext(issuer, x, NID_basic_constraints, "CA:FALSE");
1996f971622SJuan Castillo 	}
2006f971622SJuan Castillo 
2016f971622SJuan Castillo 	/* Add custom extensions */
2026f971622SJuan Castillo 	if (sk != NULL) {
2036f971622SJuan Castillo 		num = sk_X509_EXTENSION_num(sk);
2046f971622SJuan Castillo 		for (i = 0; i < num; i++) {
2056f971622SJuan Castillo 			ex = sk_X509_EXTENSION_value(sk, i);
2066f971622SJuan Castillo 			X509_add_ext(x, ex, -1);
2076f971622SJuan Castillo 		}
2086f971622SJuan Castillo 	}
2096f971622SJuan Castillo 
210742c4e14SMichalis Pappas 	if (!X509_sign_ctx(x, mdCtx)) {
2116f971622SJuan Castillo 		ERR_print_errors_fp(stdout);
2121f33ad4eSSoby Mathew 		goto END;
2136f971622SJuan Castillo 	}
2146f971622SJuan Castillo 
2151f33ad4eSSoby Mathew 	/* X509 certificate signed successfully */
2161f33ad4eSSoby Mathew 	rc = 1;
2176f971622SJuan Castillo 	cert->x = x;
2181f33ad4eSSoby Mathew 
2191f33ad4eSSoby Mathew END:
220742c4e14SMichalis Pappas 	EVP_MD_CTX_destroy(mdCtx);
2211f33ad4eSSoby Mathew 	return rc;
2226f971622SJuan Castillo }
223ad2c1a9aSJuan Castillo 
224ad2c1a9aSJuan Castillo int cert_init(void)
225ad2c1a9aSJuan Castillo {
226159807e2SJuan Castillo 	cmd_opt_t cmd_opt;
227ad2c1a9aSJuan Castillo 	cert_t *cert;
228ad2c1a9aSJuan Castillo 	unsigned int i;
229ad2c1a9aSJuan Castillo 
230ad2c1a9aSJuan Castillo 	for (i = 0; i < num_certs; i++) {
231ad2c1a9aSJuan Castillo 		cert = &certs[i];
232159807e2SJuan Castillo 		cmd_opt.long_opt.name = cert->opt;
233159807e2SJuan Castillo 		cmd_opt.long_opt.has_arg = required_argument;
234159807e2SJuan Castillo 		cmd_opt.long_opt.flag = NULL;
235159807e2SJuan Castillo 		cmd_opt.long_opt.val = CMD_OPT_CERT;
236159807e2SJuan Castillo 		cmd_opt.help_msg = cert->help_msg;
237159807e2SJuan Castillo 		cmd_opt_add(&cmd_opt);
238ad2c1a9aSJuan Castillo 	}
239ad2c1a9aSJuan Castillo 
240159807e2SJuan Castillo 	return 0;
241ad2c1a9aSJuan Castillo }
242ad2c1a9aSJuan Castillo 
243ad2c1a9aSJuan Castillo cert_t *cert_get_by_opt(const char *opt)
244ad2c1a9aSJuan Castillo {
245c893c733SMasahiro Yamada 	cert_t *cert;
246ad2c1a9aSJuan Castillo 	unsigned int i;
247ad2c1a9aSJuan Castillo 
248ad2c1a9aSJuan Castillo 	for (i = 0; i < num_certs; i++) {
249ad2c1a9aSJuan Castillo 		cert = &certs[i];
250ad2c1a9aSJuan Castillo 		if (0 == strcmp(cert->opt, opt)) {
251ad2c1a9aSJuan Castillo 			return cert;
252ad2c1a9aSJuan Castillo 		}
253ad2c1a9aSJuan Castillo 	}
254ad2c1a9aSJuan Castillo 
255ad2c1a9aSJuan Castillo 	return NULL;
256ad2c1a9aSJuan Castillo }
257