xref: /rk3399_ARM-atf/tools/cert_create/src/cert.c (revision d4c596be87e0b04404fc10ee49544eda33c0f625)
1 /*
2  * Copyright (c) 2015-2017, 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 #if USE_TBBR_DEFS
19 #include <tbbr_oid.h>
20 #else
21 #include <platform_oid.h>
22 #endif
23 
24 #include "cert.h"
25 #include "cmd_opt.h"
26 #include "debug.h"
27 #include "key.h"
28 #include "sha.h"
29 
30 #define SERIAL_RAND_BITS	64
31 #define RSA_SALT_LEN		32
32 
33 int rand_serial(BIGNUM *b, ASN1_INTEGER *ai)
34 {
35 	BIGNUM *btmp;
36 	int ret = 0;
37 	if (b)
38 		btmp = b;
39 	else
40 		btmp = BN_new();
41 
42 	if (!btmp)
43 		return 0;
44 
45 	if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0))
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 
60 int cert_add_ext(X509 *issuer, X509 *subject, int nid, char *value)
61 {
62 	X509_EXTENSION *ex;
63 	X509V3_CTX ctx;
64 
65 	/* No configuration database */
66 	X509V3_set_ctx_nodb(&ctx);
67 
68 	/* Set issuer and subject certificates in the context */
69 	X509V3_set_ctx(&ctx, issuer, subject, NULL, NULL, 0);
70 	ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
71 	if (!ex) {
72 		ERR_print_errors_fp(stdout);
73 		return 0;
74 	}
75 
76 	X509_add_ext(subject, ex, -1);
77 	X509_EXTENSION_free(ex);
78 
79 	return 1;
80 }
81 
82 int cert_new(int key_alg, cert_t *cert, int days, int ca, STACK_OF(X509_EXTENSION) * sk)
83 {
84 	EVP_PKEY *pkey = keys[cert->key].key;
85 	cert_t *issuer_cert = &certs[cert->issuer];
86 	EVP_PKEY *ikey = keys[issuer_cert->key].key;
87 	X509 *issuer = issuer_cert->x;
88 	X509 *x;
89 	X509_EXTENSION *ex;
90 	X509_NAME *name;
91 	ASN1_INTEGER *sno;
92 	int i, num, rc = 0;
93 	EVP_MD_CTX mdCtx;
94 	EVP_PKEY_CTX *pKeyCtx = NULL;
95 
96 	/* Create the certificate structure */
97 	x = X509_new();
98 	if (!x) {
99 		return 0;
100 	}
101 
102 	/* If we do not have a key, use the issuer key (the certificate will
103 	 * become self signed). This happens in content certificates. */
104 	if (!pkey) {
105 		pkey = ikey;
106 	}
107 
108 	/* If we do not have an issuer certificate, use our own (the certificate
109 	 * will become self signed) */
110 	if (!issuer) {
111 		issuer = x;
112 	}
113 
114 	EVP_MD_CTX_init(&mdCtx);
115 
116 	/* Sign the certificate with the issuer key */
117 	if (!EVP_DigestSignInit(&mdCtx, &pKeyCtx, EVP_sha256(), NULL, ikey)) {
118 		ERR_print_errors_fp(stdout);
119 		goto END;
120 	}
121 
122 	/*
123 	 * Set additional parameters if algorithm is RSA PSS. This is not
124 	 * required for RSA 1.5 or ECDSA.
125 	 */
126 	if (key_alg == KEY_ALG_RSA) {
127 		if (!EVP_PKEY_CTX_set_rsa_padding(pKeyCtx, RSA_PKCS1_PSS_PADDING)) {
128 			ERR_print_errors_fp(stdout);
129 			goto END;
130 		}
131 
132 		if (!EVP_PKEY_CTX_set_rsa_pss_saltlen(pKeyCtx, RSA_SALT_LEN)) {
133 			ERR_print_errors_fp(stdout);
134 			goto END;
135 		}
136 
137 		if (!EVP_PKEY_CTX_set_rsa_mgf1_md(pKeyCtx, EVP_sha256())) {
138 			ERR_print_errors_fp(stdout);
139 			goto END;
140 		}
141 	}
142 
143 	/* x509.v3 */
144 	X509_set_version(x, 2);
145 
146 	/* Random serial number */
147 	sno = ASN1_INTEGER_new();
148 	rand_serial(NULL, sno);
149 	X509_set_serialNumber(x, sno);
150 	ASN1_INTEGER_free(sno);
151 
152 	X509_gmtime_adj(X509_get_notBefore(x), 0);
153 	X509_gmtime_adj(X509_get_notAfter(x), (long)60*60*24*days);
154 	X509_set_pubkey(x, pkey);
155 
156 	/* Subject name */
157 	name = X509_get_subject_name(x);
158 	X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
159 			(const unsigned char *)cert->cn, -1, -1, 0);
160 	X509_set_subject_name(x, name);
161 
162 	/* Issuer name */
163 	name = X509_get_issuer_name(x);
164 	X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
165 			(const unsigned char *)issuer_cert->cn, -1, -1, 0);
166 	X509_set_issuer_name(x, name);
167 
168 	/* Add various extensions: standard extensions */
169 	cert_add_ext(issuer, x, NID_subject_key_identifier, "hash");
170 	cert_add_ext(issuer, x, NID_authority_key_identifier, "keyid:always");
171 	if (ca) {
172 		cert_add_ext(issuer, x, NID_basic_constraints, "CA:TRUE");
173 		cert_add_ext(issuer, x, NID_key_usage, "keyCertSign");
174 	} else {
175 		cert_add_ext(issuer, x, NID_basic_constraints, "CA:FALSE");
176 	}
177 
178 	/* Add custom extensions */
179 	if (sk != NULL) {
180 		num = sk_X509_EXTENSION_num(sk);
181 		for (i = 0; i < num; i++) {
182 			ex = sk_X509_EXTENSION_value(sk, i);
183 			X509_add_ext(x, ex, -1);
184 		}
185 	}
186 
187 	if (!X509_sign_ctx(x, &mdCtx)) {
188 		ERR_print_errors_fp(stdout);
189 		goto END;
190 	}
191 
192 	/* X509 certificate signed successfully */
193 	rc = 1;
194 	cert->x = x;
195 
196 END:
197 	EVP_MD_CTX_cleanup(&mdCtx);
198 	return rc;
199 }
200 
201 int cert_init(void)
202 {
203 	cmd_opt_t cmd_opt;
204 	cert_t *cert;
205 	unsigned int i;
206 
207 	for (i = 0; i < num_certs; i++) {
208 		cert = &certs[i];
209 		cmd_opt.long_opt.name = cert->opt;
210 		cmd_opt.long_opt.has_arg = required_argument;
211 		cmd_opt.long_opt.flag = NULL;
212 		cmd_opt.long_opt.val = CMD_OPT_CERT;
213 		cmd_opt.help_msg = cert->help_msg;
214 		cmd_opt_add(&cmd_opt);
215 	}
216 
217 	return 0;
218 }
219 
220 cert_t *cert_get_by_opt(const char *opt)
221 {
222 	cert_t *cert;
223 	unsigned int i;
224 
225 	for (i = 0; i < num_certs; i++) {
226 		cert = &certs[i];
227 		if (0 == strcmp(cert->opt, opt)) {
228 			return cert;
229 		}
230 	}
231 
232 	return NULL;
233 }
234