blob: 62ff2555b61f271919f2c01272f08b88b21972ae [file] [log] [blame]
Juan Castillo11abdcd2014-10-21 11:30:42 +01001/*
2 * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
3 *
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
17#include "cert.h"
Juan Castillo1218dd52015-07-03 16:23:16 +010018#include "cmd_opt.h"
Juan Castillo11abdcd2014-10-21 11:30:42 +010019#include "debug.h"
20#include "key.h"
21#include "platform_oid.h"
22#include "sha.h"
23
24#define SERIAL_RAND_BITS 64
25
26int 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
45error:
46
47 if (!b)
48 BN_free(btmp);
49
50 return ret;
51}
52
53int 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
76int cert_new(cert_t *cert, int days, int ca, STACK_OF(X509_EXTENSION) * sk)
77{
Juan Castilloe6d30e92015-06-12 11:27:59 +010078 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;
Masahiro Yamada48cb5e52017-02-06 19:47:44 +090082 X509 *x;
83 X509_EXTENSION *ex;
84 X509_NAME *name;
85 ASN1_INTEGER *sno;
Juan Castillo11abdcd2014-10-21 11:30:42 +010086 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,
Juan Castilloe6d30e92015-06-12 11:27:59 +0100128 (const unsigned char *)issuer_cert->cn, -1, -1, 0);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100129 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 */
Juan Castillo271a5ac2015-02-16 10:34:28 +0000151 if (!X509_sign(x, ikey, EVP_sha256())) {
Juan Castillo11abdcd2014-10-21 11:30:42 +0100152 ERR_print_errors_fp(stdout);
153 return 0;
154 }
155
156 cert->x = x;
157 return 1;
158}
Juan Castillo1218dd52015-07-03 16:23:16 +0100159
160int cert_init(void)
161{
Juan Castillo212f7382015-12-15 16:37:57 +0000162 cmd_opt_t cmd_opt;
Juan Castillo1218dd52015-07-03 16:23:16 +0100163 cert_t *cert;
Juan Castillo1218dd52015-07-03 16:23:16 +0100164 unsigned int i;
165
166 for (i = 0; i < num_certs; i++) {
167 cert = &certs[i];
Juan Castillo212f7382015-12-15 16:37:57 +0000168 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);
Juan Castillo1218dd52015-07-03 16:23:16 +0100174 }
175
Juan Castillo212f7382015-12-15 16:37:57 +0000176 return 0;
Juan Castillo1218dd52015-07-03 16:23:16 +0100177}
178
179cert_t *cert_get_by_opt(const char *opt)
180{
Masahiro Yamada48cb5e52017-02-06 19:47:44 +0900181 cert_t *cert;
Juan Castillo1218dd52015-07-03 16:23:16 +0100182 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}