blob: 1b84e36d35ac020e86d3e58f24a67fca443f7c59 [file] [log] [blame]
Juan Castillo11abdcd2014-10-21 11:30:42 +01001/*
Masahiro Yamadaa27c1662017-05-22 12:11:24 +09002 * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
Juan Castillo11abdcd2014-10-21 11:30:42 +01003 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Juan Castillo11abdcd2014-10-21 11:30:42 +01005 */
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10
11#include <openssl/conf.h>
12#include <openssl/err.h>
Soby Mathewd5b22d32017-05-22 16:12:33 +010013#include <openssl/opensslv.h>
Juan Castillo11abdcd2014-10-21 11:30:42 +010014#include <openssl/pem.h>
15#include <openssl/sha.h>
16#include <openssl/x509v3.h>
17
Masahiro Yamadaa27c1662017-05-22 12:11:24 +090018#if USE_TBBR_DEFS
19#include <tbbr_oid.h>
20#else
21#include <platform_oid.h>
22#endif
23
Juan Castillo11abdcd2014-10-21 11:30:42 +010024#include "cert.h"
Juan Castillo1218dd52015-07-03 16:23:16 +010025#include "cmd_opt.h"
Juan Castillo11abdcd2014-10-21 11:30:42 +010026#include "debug.h"
27#include "key.h"
Juan Castillo11abdcd2014-10-21 11:30:42 +010028#include "sha.h"
29
30#define SERIAL_RAND_BITS 64
Soby Mathewd5b22d32017-05-22 16:12:33 +010031#define RSA_SALT_LEN 32
Juan Castillo11abdcd2014-10-21 11:30:42 +010032
33int 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
52error:
53
54 if (!b)
55 BN_free(btmp);
56
57 return ret;
58}
59
60int 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
Soby Mathew2fd70f62017-08-31 11:50:29 +010082int cert_new(int key_alg, cert_t *cert, int days, int ca, STACK_OF(X509_EXTENSION) * sk)
Juan Castillo11abdcd2014-10-21 11:30:42 +010083{
Juan Castilloe6d30e92015-06-12 11:27:59 +010084 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;
Masahiro Yamada48cb5e52017-02-06 19:47:44 +090088 X509 *x;
89 X509_EXTENSION *ex;
90 X509_NAME *name;
91 ASN1_INTEGER *sno;
Soby Mathewd5b22d32017-05-22 16:12:33 +010092 int i, num, rc = 0;
Soby Mathew2fd70f62017-08-31 11:50:29 +010093 EVP_MD_CTX mdCtx;
Soby Mathewd5b22d32017-05-22 16:12:33 +010094 EVP_PKEY_CTX *pKeyCtx = NULL;
Juan Castillo11abdcd2014-10-21 11:30:42 +010095
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
Soby Mathewd5b22d32017-05-22 16:12:33 +0100114 EVP_MD_CTX_init(&mdCtx);
Soby Mathew2fd70f62017-08-31 11:50:29 +0100115
116 /* Sign the certificate with the issuer key */
Soby Mathewd5b22d32017-05-22 16:12:33 +0100117 if (!EVP_DigestSignInit(&mdCtx, &pKeyCtx, EVP_sha256(), NULL, ikey)) {
118 ERR_print_errors_fp(stdout);
119 goto END;
120 }
121
Soby Mathew2fd70f62017-08-31 11:50:29 +0100122 /*
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 }
Soby Mathewd5b22d32017-05-22 16:12:33 +0100131
Soby Mathew2fd70f62017-08-31 11:50:29 +0100132 if (!EVP_PKEY_CTX_set_rsa_pss_saltlen(pKeyCtx, RSA_SALT_LEN)) {
133 ERR_print_errors_fp(stdout);
134 goto END;
135 }
Soby Mathewd5b22d32017-05-22 16:12:33 +0100136
Soby Mathew2fd70f62017-08-31 11:50:29 +0100137 if (!EVP_PKEY_CTX_set_rsa_mgf1_md(pKeyCtx, EVP_sha256())) {
138 ERR_print_errors_fp(stdout);
139 goto END;
140 }
Soby Mathewd5b22d32017-05-22 16:12:33 +0100141 }
142
Juan Castillo11abdcd2014-10-21 11:30:42 +0100143 /* 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,
Juan Castilloe6d30e92015-06-12 11:27:59 +0100165 (const unsigned char *)issuer_cert->cn, -1, -1, 0);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100166 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
Soby Mathewd5b22d32017-05-22 16:12:33 +0100187 if (!X509_sign_ctx(x, &mdCtx)) {
Juan Castillo11abdcd2014-10-21 11:30:42 +0100188 ERR_print_errors_fp(stdout);
Soby Mathewd5b22d32017-05-22 16:12:33 +0100189 goto END;
Juan Castillo11abdcd2014-10-21 11:30:42 +0100190 }
191
Soby Mathewd5b22d32017-05-22 16:12:33 +0100192 /* X509 certificate signed successfully */
193 rc = 1;
Juan Castillo11abdcd2014-10-21 11:30:42 +0100194 cert->x = x;
Soby Mathewd5b22d32017-05-22 16:12:33 +0100195
196END:
197 EVP_MD_CTX_cleanup(&mdCtx);
198 return rc;
Juan Castillo11abdcd2014-10-21 11:30:42 +0100199}
Juan Castillo1218dd52015-07-03 16:23:16 +0100200
201int cert_init(void)
202{
Juan Castillo212f7382015-12-15 16:37:57 +0000203 cmd_opt_t cmd_opt;
Juan Castillo1218dd52015-07-03 16:23:16 +0100204 cert_t *cert;
Juan Castillo1218dd52015-07-03 16:23:16 +0100205 unsigned int i;
206
207 for (i = 0; i < num_certs; i++) {
208 cert = &certs[i];
Juan Castillo212f7382015-12-15 16:37:57 +0000209 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);
Juan Castillo1218dd52015-07-03 16:23:16 +0100215 }
216
Juan Castillo212f7382015-12-15 16:37:57 +0000217 return 0;
Juan Castillo1218dd52015-07-03 16:23:16 +0100218}
219
220cert_t *cert_get_by_opt(const char *opt)
221{
Masahiro Yamada48cb5e52017-02-06 19:47:44 +0900222 cert_t *cert;
Juan Castillo1218dd52015-07-03 16:23:16 +0100223 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}