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