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