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