blob: 80ccfe93181aa4ac94ab31b6fa08cdad8dc78580 [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>
13#include <openssl/pem.h>
14#include <openssl/sha.h>
15#include <openssl/x509v3.h>
16
Masahiro Yamadaa27c1662017-05-22 12:11:24 +090017#if USE_TBBR_DEFS
18#include <tbbr_oid.h>
19#else
20#include <platform_oid.h>
21#endif
22
Juan Castillo11abdcd2014-10-21 11:30:42 +010023#include "cert.h"
Juan Castillo1218dd52015-07-03 16:23:16 +010024#include "cmd_opt.h"
Juan Castillo11abdcd2014-10-21 11:30:42 +010025#include "debug.h"
26#include "key.h"
Juan Castillo11abdcd2014-10-21 11:30:42 +010027#include "sha.h"
28
29#define SERIAL_RAND_BITS 64
30
31int 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
50error:
51
52 if (!b)
53 BN_free(btmp);
54
55 return ret;
56}
57
58int 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
81int cert_new(cert_t *cert, int days, int ca, STACK_OF(X509_EXTENSION) * sk)
82{
Juan Castilloe6d30e92015-06-12 11:27:59 +010083 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;
Masahiro Yamada48cb5e52017-02-06 19:47:44 +090087 X509 *x;
88 X509_EXTENSION *ex;
89 X509_NAME *name;
90 ASN1_INTEGER *sno;
Juan Castillo11abdcd2014-10-21 11:30:42 +010091 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,
Juan Castilloe6d30e92015-06-12 11:27:59 +0100133 (const unsigned char *)issuer_cert->cn, -1, -1, 0);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100134 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 */
Juan Castillo271a5ac2015-02-16 10:34:28 +0000156 if (!X509_sign(x, ikey, EVP_sha256())) {
Juan Castillo11abdcd2014-10-21 11:30:42 +0100157 ERR_print_errors_fp(stdout);
158 return 0;
159 }
160
161 cert->x = x;
162 return 1;
163}
Juan Castillo1218dd52015-07-03 16:23:16 +0100164
165int cert_init(void)
166{
Juan Castillo212f7382015-12-15 16:37:57 +0000167 cmd_opt_t cmd_opt;
Juan Castillo1218dd52015-07-03 16:23:16 +0100168 cert_t *cert;
Juan Castillo1218dd52015-07-03 16:23:16 +0100169 unsigned int i;
170
171 for (i = 0; i < num_certs; i++) {
172 cert = &certs[i];
Juan Castillo212f7382015-12-15 16:37:57 +0000173 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);
Juan Castillo1218dd52015-07-03 16:23:16 +0100179 }
180
Juan Castillo212f7382015-12-15 16:37:57 +0000181 return 0;
Juan Castillo1218dd52015-07-03 16:23:16 +0100182}
183
184cert_t *cert_get_by_opt(const char *opt)
185{
Masahiro Yamada48cb5e52017-02-06 19:47:44 +0900186 cert_t *cert;
Juan Castillo1218dd52015-07-03 16:23:16 +0100187 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}