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
rand_serial(BIGNUM * b,ASN1_INTEGER * ai)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
cert_add_ext(X509 * issuer,X509 * subject,int nid,char * value)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
cert_new(int key_alg,cert_t * cert,int days,int ca,STACK_OF (X509_EXTENSION)* sk)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 mdCtx = EVP_MD_CTX_create();
115 if (mdCtx == NULL) {
116 ERR_print_errors_fp(stdout);
117 goto END;
118 }
119
120 /* Sign the certificate with the issuer key */
121 if (!EVP_DigestSignInit(mdCtx, &pKeyCtx, EVP_sha256(), NULL, ikey)) {
122 ERR_print_errors_fp(stdout);
123 goto END;
124 }
125
126 /*
127 * Set additional parameters if algorithm is RSA PSS. This is not
128 * required for RSA 1.5 or ECDSA.
129 */
130 if (key_alg == KEY_ALG_RSA) {
131 if (!EVP_PKEY_CTX_set_rsa_padding(pKeyCtx, RSA_PKCS1_PSS_PADDING)) {
132 ERR_print_errors_fp(stdout);
133 goto END;
134 }
135
136 if (!EVP_PKEY_CTX_set_rsa_pss_saltlen(pKeyCtx, RSA_SALT_LEN)) {
137 ERR_print_errors_fp(stdout);
138 goto END;
139 }
140
141 if (!EVP_PKEY_CTX_set_rsa_mgf1_md(pKeyCtx, EVP_sha256())) {
142 ERR_print_errors_fp(stdout);
143 goto END;
144 }
145 }
146
147 /* x509.v3 */
148 X509_set_version(x, 2);
149
150 /* Random serial number */
151 sno = ASN1_INTEGER_new();
152 rand_serial(NULL, sno);
153 X509_set_serialNumber(x, sno);
154 ASN1_INTEGER_free(sno);
155
156 X509_gmtime_adj(X509_get_notBefore(x), 0);
157 X509_gmtime_adj(X509_get_notAfter(x), (long)60*60*24*days);
158 X509_set_pubkey(x, pkey);
159
160 /* Subject name */
161 name = X509_get_subject_name(x);
162 X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
163 (const unsigned char *)cert->cn, -1, -1, 0);
164 X509_set_subject_name(x, name);
165
166 /* Issuer name */
167 name = X509_get_issuer_name(x);
168 X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
169 (const unsigned char *)issuer_cert->cn, -1, -1, 0);
170 X509_set_issuer_name(x, name);
171
172 /* Add various extensions: standard extensions */
173 cert_add_ext(issuer, x, NID_subject_key_identifier, "hash");
174 cert_add_ext(issuer, x, NID_authority_key_identifier, "keyid:always");
175 if (ca) {
176 cert_add_ext(issuer, x, NID_basic_constraints, "CA:TRUE");
177 cert_add_ext(issuer, x, NID_key_usage, "keyCertSign");
178 } else {
179 cert_add_ext(issuer, x, NID_basic_constraints, "CA:FALSE");
180 }
181
182 /* Add custom extensions */
183 if (sk != NULL) {
184 num = sk_X509_EXTENSION_num(sk);
185 for (i = 0; i < num; i++) {
186 ex = sk_X509_EXTENSION_value(sk, i);
187 X509_add_ext(x, ex, -1);
188 }
189 }
190
191 if (!X509_sign_ctx(x, mdCtx)) {
192 ERR_print_errors_fp(stdout);
193 goto END;
194 }
195
196 /* X509 certificate signed successfully */
197 rc = 1;
198 cert->x = x;
199
200 END:
201 EVP_MD_CTX_destroy(mdCtx);
202 return rc;
203 }
204
cert_init(void)205 int cert_init(void)
206 {
207 cmd_opt_t cmd_opt;
208 cert_t *cert;
209 unsigned int i;
210
211 for (i = 0; i < num_certs; i++) {
212 cert = &certs[i];
213 cmd_opt.long_opt.name = cert->opt;
214 cmd_opt.long_opt.has_arg = required_argument;
215 cmd_opt.long_opt.flag = NULL;
216 cmd_opt.long_opt.val = CMD_OPT_CERT;
217 cmd_opt.help_msg = cert->help_msg;
218 cmd_opt_add(&cmd_opt);
219 }
220
221 return 0;
222 }
223
cert_get_by_opt(const char * opt)224 cert_t *cert_get_by_opt(const char *opt)
225 {
226 cert_t *cert;
227 unsigned int i;
228
229 for (i = 0; i < num_certs; i++) {
230 cert = &certs[i];
231 if (0 == strcmp(cert->opt, opt)) {
232 return cert;
233 }
234 }
235
236 return NULL;
237 }
238