xref: /rk3399_ARM-atf/tools/cert_create/src/cert.c (revision 4df2246943af8568564b4732de02794b2fd8bd39)
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/pem.h>
14 #include <openssl/sha.h>
15 #include <openssl/x509v3.h>
16 
17 #if USE_TBBR_DEFS
18 #include <tbbr_oid.h>
19 #else
20 #include <platform_oid.h>
21 #endif
22 
23 #include "cert.h"
24 #include "cmd_opt.h"
25 #include "debug.h"
26 #include "key.h"
27 #include "sha.h"
28 
29 #define SERIAL_RAND_BITS	64
30 
31 int rand_serial(BIGNUM *b, ASN1_INTEGER *ai)
32 {
33 	BIGNUM *btmp;
34 	int ret = 0;
35 	if (b)
36 		btmp = b;
37 	else
38 		btmp = BN_new();
39 
40 	if (!btmp)
41 		return 0;
42 
43 	if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0))
44 		goto error;
45 	if (ai && !BN_to_ASN1_INTEGER(btmp, ai))
46 		goto error;
47 
48 	ret = 1;
49 
50 error:
51 
52 	if (!b)
53 		BN_free(btmp);
54 
55 	return ret;
56 }
57 
58 int cert_add_ext(X509 *issuer, X509 *subject, int nid, char *value)
59 {
60 	X509_EXTENSION *ex;
61 	X509V3_CTX ctx;
62 
63 	/* No configuration database */
64 	X509V3_set_ctx_nodb(&ctx);
65 
66 	/* Set issuer and subject certificates in the context */
67 	X509V3_set_ctx(&ctx, issuer, subject, NULL, NULL, 0);
68 	ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
69 	if (!ex) {
70 		ERR_print_errors_fp(stdout);
71 		return 0;
72 	}
73 
74 	X509_add_ext(subject, ex, -1);
75 	X509_EXTENSION_free(ex);
76 
77 	return 1;
78 }
79 
80 
81 int cert_new(cert_t *cert, int days, int ca, STACK_OF(X509_EXTENSION) * sk)
82 {
83 	EVP_PKEY *pkey = keys[cert->key].key;
84 	cert_t *issuer_cert = &certs[cert->issuer];
85 	EVP_PKEY *ikey = keys[issuer_cert->key].key;
86 	X509 *issuer = issuer_cert->x;
87 	X509 *x;
88 	X509_EXTENSION *ex;
89 	X509_NAME *name;
90 	ASN1_INTEGER *sno;
91 	int i, num;
92 
93 	/* Create the certificate structure */
94 	x = X509_new();
95 	if (!x) {
96 		return 0;
97 	}
98 
99 	/* If we do not have a key, use the issuer key (the certificate will
100 	 * become self signed). This happens in content certificates. */
101 	if (!pkey) {
102 		pkey = ikey;
103 	}
104 
105 	/* If we do not have an issuer certificate, use our own (the certificate
106 	 * will become self signed) */
107 	if (!issuer) {
108 		issuer = x;
109 	}
110 
111 	/* x509.v3 */
112 	X509_set_version(x, 2);
113 
114 	/* Random serial number */
115 	sno = ASN1_INTEGER_new();
116 	rand_serial(NULL, sno);
117 	X509_set_serialNumber(x, sno);
118 	ASN1_INTEGER_free(sno);
119 
120 	X509_gmtime_adj(X509_get_notBefore(x), 0);
121 	X509_gmtime_adj(X509_get_notAfter(x), (long)60*60*24*days);
122 	X509_set_pubkey(x, pkey);
123 
124 	/* Subject name */
125 	name = X509_get_subject_name(x);
126 	X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
127 			(const unsigned char *)cert->cn, -1, -1, 0);
128 	X509_set_subject_name(x, name);
129 
130 	/* Issuer name */
131 	name = X509_get_issuer_name(x);
132 	X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
133 			(const unsigned char *)issuer_cert->cn, -1, -1, 0);
134 	X509_set_issuer_name(x, name);
135 
136 	/* Add various extensions: standard extensions */
137 	cert_add_ext(issuer, x, NID_subject_key_identifier, "hash");
138 	cert_add_ext(issuer, x, NID_authority_key_identifier, "keyid:always");
139 	if (ca) {
140 		cert_add_ext(issuer, x, NID_basic_constraints, "CA:TRUE");
141 		cert_add_ext(issuer, x, NID_key_usage, "keyCertSign");
142 	} else {
143 		cert_add_ext(issuer, x, NID_basic_constraints, "CA:FALSE");
144 	}
145 
146 	/* Add custom extensions */
147 	if (sk != NULL) {
148 		num = sk_X509_EXTENSION_num(sk);
149 		for (i = 0; i < num; i++) {
150 			ex = sk_X509_EXTENSION_value(sk, i);
151 			X509_add_ext(x, ex, -1);
152 		}
153 	}
154 
155 	/* Sign the certificate with the issuer key */
156 	if (!X509_sign(x, ikey, EVP_sha256())) {
157 		ERR_print_errors_fp(stdout);
158 		return 0;
159 	}
160 
161 	cert->x = x;
162 	return 1;
163 }
164 
165 int cert_init(void)
166 {
167 	cmd_opt_t cmd_opt;
168 	cert_t *cert;
169 	unsigned int i;
170 
171 	for (i = 0; i < num_certs; i++) {
172 		cert = &certs[i];
173 		cmd_opt.long_opt.name = cert->opt;
174 		cmd_opt.long_opt.has_arg = required_argument;
175 		cmd_opt.long_opt.flag = NULL;
176 		cmd_opt.long_opt.val = CMD_OPT_CERT;
177 		cmd_opt.help_msg = cert->help_msg;
178 		cmd_opt_add(&cmd_opt);
179 	}
180 
181 	return 0;
182 }
183 
184 cert_t *cert_get_by_opt(const char *opt)
185 {
186 	cert_t *cert;
187 	unsigned int i;
188 
189 	for (i = 0; i < num_certs; i++) {
190 		cert = &certs[i];
191 		if (0 == strcmp(cert->opt, opt)) {
192 			return cert;
193 		}
194 	}
195 
196 	return NULL;
197 }
198