xref: /rk3399_ARM-atf/tools/cert_create/src/ext.c (revision 108e4df7f167bccc2c9ccef87bdd62d15c3aa74b)
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 <stddef.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <openssl/asn1.h>
35 #include <openssl/asn1t.h>
36 #include <openssl/err.h>
37 #include <openssl/x509v3.h>
38 
39 #include "cmd_opt.h"
40 #include "ext.h"
41 
42 DECLARE_ASN1_ITEM(ASN1_INTEGER)
43 DECLARE_ASN1_ITEM(X509_ALGOR)
44 DECLARE_ASN1_ITEM(ASN1_OCTET_STRING)
45 
46 typedef struct {
47 	X509_ALGOR *hashAlgorithm;
48 	ASN1_OCTET_STRING *dataHash;
49 } HASH;
50 
51 ASN1_SEQUENCE(HASH) = {
52 	ASN1_SIMPLE(HASH, hashAlgorithm, X509_ALGOR),
53 	ASN1_SIMPLE(HASH, dataHash, ASN1_OCTET_STRING),
54 } ASN1_SEQUENCE_END(HASH)
55 
56 DECLARE_ASN1_FUNCTIONS(HASH)
57 IMPLEMENT_ASN1_FUNCTIONS(HASH)
58 
59 /*
60  * This function adds the TBB extensions to the internal extension list
61  * maintained by OpenSSL so they can be used later.
62  *
63  * It also initializes the methods to print the contents of the extension. If an
64  * alias is specified in the TBB extension, we reuse the methods of the alias.
65  * Otherwise, only methods for V_ASN1_INTEGER and V_ASN1_OCTET_STRING are
66  * provided. Any other type will be printed as a raw ascii string.
67  *
68  * Return: 0 = success, Otherwise: error
69  */
70 int ext_init(void)
71 {
72 	cmd_opt_t cmd_opt;
73 	ext_t *ext;
74 	X509V3_EXT_METHOD *m;
75 	int nid, ret;
76 	unsigned int i;
77 
78 	for (i = 0; i < num_extensions; i++) {
79 		ext = &extensions[i];
80 		/* Register command line option */
81 		if (ext->opt) {
82 			cmd_opt.long_opt.name = ext->opt;
83 			cmd_opt.long_opt.has_arg = required_argument;
84 			cmd_opt.long_opt.flag = NULL;
85 			cmd_opt.long_opt.val = CMD_OPT_EXT;
86 			cmd_opt.help_msg = ext->help_msg;
87 			cmd_opt_add(&cmd_opt);
88 		}
89 		/* Register the extension OID in OpenSSL */
90 		if (ext->oid == NULL) {
91 			continue;
92 		}
93 		nid = OBJ_create(ext->oid, ext->sn, ext->ln);
94 		if (ext->alias) {
95 			X509V3_EXT_add_alias(nid, ext->alias);
96 		} else {
97 			m = &ext->method;
98 			memset(m, 0x0, sizeof(X509V3_EXT_METHOD));
99 			switch (ext->asn1_type) {
100 			case V_ASN1_INTEGER:
101 				m->it = ASN1_ITEM_ref(ASN1_INTEGER);
102 				m->i2s = (X509V3_EXT_I2S)i2s_ASN1_INTEGER;
103 				m->s2i = (X509V3_EXT_S2I)s2i_ASN1_INTEGER;
104 				break;
105 			case V_ASN1_OCTET_STRING:
106 				m->it = ASN1_ITEM_ref(ASN1_OCTET_STRING);
107 				m->i2s = (X509V3_EXT_I2S)i2s_ASN1_OCTET_STRING;
108 				m->s2i = (X509V3_EXT_S2I)s2i_ASN1_OCTET_STRING;
109 				break;
110 			default:
111 				continue;
112 			}
113 			m->ext_nid = nid;
114 			ret = X509V3_EXT_add(m);
115 			if (!ret) {
116 				ERR_print_errors_fp(stdout);
117 				return 1;
118 			}
119 		}
120 	}
121 	return 0;
122 }
123 
124 /*
125  * Create a new extension
126  *
127  * Extension  ::=  SEQUENCE  {
128  *      id          OBJECT IDENTIFIER,
129  *      critical    BOOLEAN DEFAULT FALSE,
130  *      value       OCTET STRING  }
131  *
132  * Parameters:
133  *   pex: OpenSSL extension pointer (output parameter)
134  *   nid: extension identifier
135  *   crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
136  *   data: extension data. This data will be encapsulated in an Octet String
137  *
138  * Return: Extension address, NULL if error
139  */
140 static
141 X509_EXTENSION *ext_new(int nid, int crit, unsigned char *data, int len)
142 {
143 	X509_EXTENSION *ex;
144 	ASN1_OCTET_STRING *ext_data;
145 
146 	/* Octet string containing the extension data */
147 	ext_data = ASN1_OCTET_STRING_new();
148 	ASN1_OCTET_STRING_set(ext_data, data, len);
149 
150 	/* Create the extension */
151 	ex = X509_EXTENSION_create_by_NID(NULL, nid, crit, ext_data);
152 
153 	/* The extension makes a copy of the data, so we can free this object */
154 	ASN1_OCTET_STRING_free(ext_data);
155 
156 	return ex;
157 }
158 
159 /*
160  * Creates a x509v3 extension containing a hash
161  *
162  * DigestInfo ::= SEQUENCE {
163  *     digestAlgorithm  AlgorithmIdentifier,
164  *     digest           OCTET STRING
165  * }
166  *
167  * AlgorithmIdentifier ::=  SEQUENCE  {
168  *     algorithm        OBJECT IDENTIFIER,
169  *     parameters       ANY DEFINED BY algorithm OPTIONAL
170  * }
171  *
172  * Parameters:
173  *   nid: extension identifier
174  *   crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
175  *   md: hash algorithm
176  *   buf: pointer to the buffer that contains the hash
177  *   len: size of the hash in bytes
178  *
179  * Return: Extension address, NULL if error
180  */
181 X509_EXTENSION *ext_new_hash(int nid, int crit, const EVP_MD *md,
182 		unsigned char *buf, size_t len)
183 {
184 	X509_EXTENSION *ex;
185 	ASN1_OCTET_STRING *octet;
186 	HASH *hash;
187 	ASN1_OBJECT *algorithm;
188 	X509_ALGOR *x509_algor;
189 	unsigned char *p = NULL;
190 	int sz;
191 
192 	/* OBJECT_IDENTIFIER with hash algorithm */
193 	algorithm = OBJ_nid2obj(md->type);
194 	if (algorithm == NULL) {
195 		return NULL;
196 	}
197 
198 	/* Create X509_ALGOR */
199 	x509_algor = X509_ALGOR_new();
200 	if (x509_algor == NULL) {
201 		return NULL;
202 	}
203 	x509_algor->algorithm = algorithm;
204 	x509_algor->parameter = ASN1_TYPE_new();
205 	ASN1_TYPE_set(x509_algor->parameter, V_ASN1_NULL, NULL);
206 
207 	/* OCTET_STRING with the actual hash */
208 	octet = ASN1_OCTET_STRING_new();
209 	if (octet == NULL) {
210 		X509_ALGOR_free(x509_algor);
211 		return NULL;
212 	}
213 	ASN1_OCTET_STRING_set(octet, buf, len);
214 
215 	/* HASH structure containing algorithm + hash */
216 	hash = HASH_new();
217 	if (hash == NULL) {
218 		ASN1_OCTET_STRING_free(octet);
219 		X509_ALGOR_free(x509_algor);
220 		return NULL;
221 	}
222 	hash->hashAlgorithm = x509_algor;
223 	hash->dataHash = octet;
224 
225 	/* DER encoded HASH */
226 	sz = i2d_HASH(hash, &p);
227 	if ((sz <= 0) || (p == NULL)) {
228 		HASH_free(hash);
229 		X509_ALGOR_free(x509_algor);
230 		return NULL;
231 	}
232 
233 	/* Create the extension */
234 	ex = ext_new(nid, crit, p, sz);
235 
236 	/* Clean up */
237 	OPENSSL_free(p);
238 	HASH_free(hash);
239 
240 	return ex;
241 }
242 
243 /*
244  * Creates a x509v3 extension containing a nvcounter encapsulated in an ASN1
245  * Integer
246  *
247  * Parameters:
248  *   pex: OpenSSL extension pointer (output parameter)
249  *   nid: extension identifier
250  *   crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
251  *   value: nvcounter value
252  *
253  * Return: Extension address, NULL if error
254  */
255 X509_EXTENSION *ext_new_nvcounter(int nid, int crit, int value)
256 {
257 	X509_EXTENSION *ex;
258 	ASN1_INTEGER *counter;
259 	unsigned char *p = NULL;
260 	int sz;
261 
262 	/* Encode counter */
263 	counter = ASN1_INTEGER_new();
264 	ASN1_INTEGER_set(counter, value);
265 	sz = i2d_ASN1_INTEGER(counter, &p);
266 
267 	/* Create the extension */
268 	ex = ext_new(nid, crit, p, sz);
269 
270 	/* Free objects */
271 	OPENSSL_free(p);
272 	ASN1_INTEGER_free(counter);
273 
274 	return ex;
275 }
276 
277 /*
278  * Creates a x509v3 extension containing a public key in DER format:
279  *
280  *  SubjectPublicKeyInfo  ::=  SEQUENCE  {
281  *       algorithm            AlgorithmIdentifier,
282  *       subjectPublicKey     BIT STRING }
283  *
284  * Parameters:
285  *   pex: OpenSSL extension pointer (output parameter)
286  *   nid: extension identifier
287  *   crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
288  *   k: key
289  *
290  * Return: Extension address, NULL if error
291  */
292 X509_EXTENSION *ext_new_key(int nid, int crit, EVP_PKEY *k)
293 {
294 	X509_EXTENSION *ex;
295 	unsigned char *p;
296 	int sz;
297 
298 	/* Encode key */
299 	BIO *mem = BIO_new(BIO_s_mem());
300 	if (i2d_PUBKEY_bio(mem, k) <= 0) {
301 		ERR_print_errors_fp(stderr);
302 		return NULL;
303 	}
304 	p = (unsigned char *)OPENSSL_malloc(4096);
305 	sz = BIO_read(mem, p, 4096);
306 
307 	/* Create the extension */
308 	ex = ext_new(nid, crit, p, sz);
309 
310 	/* Clean up */
311 	OPENSSL_free(p);
312 
313 	return ex;
314 }
315 
316 ext_t *ext_get_by_opt(const char *opt)
317 {
318 	ext_t *ext;
319 	unsigned int i;
320 
321 	/* Sequential search. This is not a performance concern since the number
322 	 * of extensions is bounded and the code runs on a host machine */
323 	for (i = 0; i < num_extensions; i++) {
324 		ext = &extensions[i];
325 		if (ext->opt && !strcmp(ext->opt, opt)) {
326 			return ext;
327 		}
328 	}
329 
330 	return NULL;
331 }
332