1 /*
2  * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *
10  * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * Neither the name of ARM nor the names of its contributors may be used
15  * to endorse or promote products derived from this software without specific
16  * prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 
35 #include <openssl/conf.h>
36 #include <openssl/err.h>
37 #include <openssl/pem.h>
38 #include <openssl/sha.h>
39 #include <openssl/x509v3.h>
40 
41 #include "cert.h"
42 #include "debug.h"
43 #include "key.h"
44 #include "platform_oid.h"
45 #include "sha.h"
46 
47 #define SERIAL_RAND_BITS	64
48 
rand_serial(BIGNUM * b,ASN1_INTEGER * ai)49 int rand_serial(BIGNUM *b, ASN1_INTEGER *ai)
50 {
51 	BIGNUM *btmp;
52 	int ret = 0;
53 	if (b)
54 		btmp = b;
55 	else
56 		btmp = BN_new();
57 
58 	if (!btmp)
59 		return 0;
60 
61 	if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0))
62 		goto error;
63 	if (ai && !BN_to_ASN1_INTEGER(btmp, ai))
64 		goto error;
65 
66 	ret = 1;
67 
68 error:
69 
70 	if (!b)
71 		BN_free(btmp);
72 
73 	return ret;
74 }
75 
cert_add_ext(X509 * issuer,X509 * subject,int nid,char * value)76 int cert_add_ext(X509 *issuer, X509 *subject, int nid, char *value)
77 {
78 	X509_EXTENSION *ex;
79 	X509V3_CTX ctx;
80 
81 	/* No configuration database */
82 	X509V3_set_ctx_nodb(&ctx);
83 
84 	/* Set issuer and subject certificates in the context */
85 	X509V3_set_ctx(&ctx, issuer, subject, NULL, NULL, 0);
86 	ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
87 	if (!ex) {
88 		ERR_print_errors_fp(stdout);
89 		return 0;
90 	}
91 
92 	X509_add_ext(subject, ex, -1);
93 	X509_EXTENSION_free(ex);
94 
95 	return 1;
96 }
97 
98 
cert_new(cert_t * cert,int days,int ca,STACK_OF (X509_EXTENSION)* sk)99 int cert_new(cert_t *cert, int days, int ca, STACK_OF(X509_EXTENSION) * sk)
100 {
101 	EVP_PKEY *pkey = cert->key->key;
102 	EVP_PKEY *ikey = cert->issuer->key->key;
103 	X509 *issuer = cert->issuer->x;
104 	X509 *x = NULL;
105 	X509_EXTENSION *ex = NULL;
106 	X509_NAME *name = NULL;
107 	ASN1_INTEGER *sno = NULL;
108 	int i, num;
109 
110 	/* Create the certificate structure */
111 	x = X509_new();
112 	if (!x) {
113 		return 0;
114 	}
115 
116 	/* If we do not have a key, use the issuer key (the certificate will
117 	 * become self signed). This happens in content certificates. */
118 	if (!pkey) {
119 		pkey = ikey;
120 	}
121 
122 	/* If we do not have an issuer certificate, use our own (the certificate
123 	 * will become self signed) */
124 	if (!issuer) {
125 		issuer = x;
126 	}
127 
128 	/* x509.v3 */
129 	X509_set_version(x, 2);
130 
131 	/* Random serial number */
132 	sno = ASN1_INTEGER_new();
133 	rand_serial(NULL, sno);
134 	X509_set_serialNumber(x, sno);
135 	ASN1_INTEGER_free(sno);
136 
137 	X509_gmtime_adj(X509_get_notBefore(x), 0);
138 	X509_gmtime_adj(X509_get_notAfter(x), (long)60*60*24*days);
139 	X509_set_pubkey(x, pkey);
140 
141 	/* Subject name */
142 	name = X509_get_subject_name(x);
143 	X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
144 			(const unsigned char *)cert->cn, -1, -1, 0);
145 	X509_set_subject_name(x, name);
146 
147 	/* Issuer name */
148 	name = X509_get_issuer_name(x);
149 	X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
150 			(const unsigned char *)cert->issuer->cn, -1, -1, 0);
151 	X509_set_issuer_name(x, name);
152 
153 	/* Add various extensions: standard extensions */
154 	cert_add_ext(issuer, x, NID_subject_key_identifier, "hash");
155 	cert_add_ext(issuer, x, NID_authority_key_identifier, "keyid:always");
156 	if (ca) {
157 		cert_add_ext(issuer, x, NID_basic_constraints, "CA:TRUE");
158 		cert_add_ext(issuer, x, NID_key_usage, "keyCertSign");
159 	} else {
160 		cert_add_ext(issuer, x, NID_basic_constraints, "CA:FALSE");
161 	}
162 
163 	/* Add custom extensions */
164 	if (sk != NULL) {
165 		num = sk_X509_EXTENSION_num(sk);
166 		for (i = 0; i < num; i++) {
167 			ex = sk_X509_EXTENSION_value(sk, i);
168 			X509_add_ext(x, ex, -1);
169 		}
170 	}
171 
172 	/* Sign the certificate with the issuer key */
173 	if (!X509_sign(x, ikey, EVP_sha1())) {
174 		ERR_print_errors_fp(stdout);
175 		return 0;
176 	}
177 
178 	cert->x = x;
179 	return 1;
180 }
181