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/err.h>
35 #include <openssl/x509v3.h>
36 #include "ext.h"
37 
38 DECLARE_ASN1_ITEM(ASN1_INTEGER)
DECLARE_ASN1_ITEM(ASN1_OCTET_STRING)39 DECLARE_ASN1_ITEM(ASN1_OCTET_STRING)
40 
41 /*
42  * This function adds the TBB extensions to the internal extension list
43  * maintained by OpenSSL so they can be used later.
44  *
45  * It also initializes the methods to print the contents of the extension. If an
46  * alias is specified in the TBB extension, we reuse the methods of the alias.
47  * Otherwise, only methods for V_ASN1_INTEGER and V_ASN1_OCTET_STRING are
48  * provided. Any other type will be printed as a raw ascii string.
49  *
50  * Return: 0 = success, Otherwise: error
51  */
52 int ext_init(ext_t *tbb_ext)
53 {
54 	ext_t *ext;
55 	X509V3_EXT_METHOD *m;
56 	int i = 0, nid, ret;
57 
58 	while ((ext = &tbb_ext[i++]) && ext->oid) {
59 		nid = OBJ_create(ext->oid, ext->sn, ext->ln);
60 		if (ext->alias) {
61 			X509V3_EXT_add_alias(nid, ext->alias);
62 		} else {
63 			m = &ext->method;
64 			memset(m, 0x0, sizeof(X509V3_EXT_METHOD));
65 			switch (ext->type) {
66 			case V_ASN1_INTEGER:
67 				m->it = ASN1_ITEM_ref(ASN1_INTEGER);
68 				m->i2s = (X509V3_EXT_I2S)i2s_ASN1_INTEGER;
69 				m->s2i = (X509V3_EXT_S2I)s2i_ASN1_INTEGER;
70 				break;
71 			case V_ASN1_OCTET_STRING:
72 				m->it = ASN1_ITEM_ref(ASN1_OCTET_STRING);
73 				m->i2s = (X509V3_EXT_I2S)i2s_ASN1_OCTET_STRING;
74 				m->s2i = (X509V3_EXT_S2I)s2i_ASN1_OCTET_STRING;
75 				break;
76 			default:
77 				continue;
78 			}
79 			m->ext_nid = nid;
80 			ret = X509V3_EXT_add(m);
81 			if (!ret) {
82 				ERR_print_errors_fp(stdout);
83 				return 1;
84 			}
85 		}
86 	}
87 	return 0;
88 }
89 
90 /*
91  * Create a new extension
92  *
93  * Extension  ::=  SEQUENCE  {
94  *      id          OBJECT IDENTIFIER,
95  *      critical    BOOLEAN DEFAULT FALSE,
96  *      value       OCTET STRING  }
97  *
98  * Parameters:
99  *   pex: OpenSSL extension pointer (output parameter)
100  *   nid: extension identifier
101  *   crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
102  *   data: extension data. This data will be encapsulated in an Octet String
103  *
104  * Return: Extension address, NULL if error
105  */
106 static
ext_new(int nid,int crit,unsigned char * data,int len)107 X509_EXTENSION *ext_new(int nid, int crit, unsigned char *data, int len)
108 {
109 	X509_EXTENSION *ex;
110 	ASN1_OCTET_STRING *ext_data;
111 
112 	/* Octet string containing the extension data */
113 	ext_data = ASN1_OCTET_STRING_new();
114 	ASN1_OCTET_STRING_set(ext_data, data, len);
115 
116 	/* Create the extension */
117 	ex = X509_EXTENSION_create_by_NID(NULL, nid, crit, ext_data);
118 
119 	/* The extension makes a copy of the data, so we can free this object */
120 	ASN1_OCTET_STRING_free(ext_data);
121 
122 	return ex;
123 }
124 
125 /*
126  * Creates a x509v3 extension containing a hash encapsulated in an ASN1 Octet
127  * 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  *   buf: pointer to the buffer that contains the hash
134  *   len: size of the hash in bytes
135  *
136  * Return: Extension address, NULL if error
137  */
ext_new_hash(int nid,int crit,unsigned char * buf,size_t len)138 X509_EXTENSION *ext_new_hash(int nid, int crit, unsigned char *buf, size_t len)
139 {
140 	X509_EXTENSION *ex = NULL;
141 	ASN1_OCTET_STRING *hash = NULL;
142 	unsigned char *p = NULL;
143 	int sz = -1;
144 
145 	/* Encode Hash */
146 	hash = ASN1_OCTET_STRING_new();
147 	ASN1_OCTET_STRING_set(hash, buf, len);
148 	sz = i2d_ASN1_OCTET_STRING(hash, NULL);
149 	i2d_ASN1_OCTET_STRING(hash, &p);
150 
151 	/* Create the extension */
152 	ex = ext_new(nid, crit, p, sz);
153 
154 	/* Clean up */
155 	OPENSSL_free(p);
156 	ASN1_OCTET_STRING_free(hash);
157 
158 	return ex;
159 }
160 
161 /*
162  * Creates a x509v3 extension containing a nvcounter encapsulated in an ASN1
163  * Integer
164  *
165  * Parameters:
166  *   pex: OpenSSL extension pointer (output parameter)
167  *   nid: extension identifier
168  *   crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
169  *   value: nvcounter value
170  *
171  * Return: Extension address, NULL if error
172  */
ext_new_nvcounter(int nid,int crit,int value)173 X509_EXTENSION *ext_new_nvcounter(int nid, int crit, int value)
174 {
175 	X509_EXTENSION *ex = NULL;
176 	ASN1_INTEGER *counter = NULL;
177 	unsigned char *p = NULL;
178 	int sz = -1;
179 
180 	/* Encode counter */
181 	counter = ASN1_INTEGER_new();
182 	ASN1_INTEGER_set(counter, value);
183 	sz = i2d_ASN1_INTEGER(counter, NULL);
184 	i2d_ASN1_INTEGER(counter, &p);
185 
186 	/* Create the extension */
187 	ex = ext_new(nid, crit, p, sz);
188 
189 	/* Free objects */
190 	OPENSSL_free(p);
191 	ASN1_INTEGER_free(counter);
192 
193 	return ex;
194 }
195 
196 /*
197  * Creates a x509v3 extension containing a public key in DER format:
198  *
199  *  SubjectPublicKeyInfo  ::=  SEQUENCE  {
200  *       algorithm            AlgorithmIdentifier,
201  *       subjectPublicKey     BIT STRING }
202  *
203  * Parameters:
204  *   pex: OpenSSL extension pointer (output parameter)
205  *   nid: extension identifier
206  *   crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
207  *   k: key
208  *
209  * Return: Extension address, NULL if error
210  */
ext_new_key(int nid,int crit,EVP_PKEY * k)211 X509_EXTENSION *ext_new_key(int nid, int crit, EVP_PKEY *k)
212 {
213 	X509_EXTENSION *ex = NULL;
214 	unsigned char *p = NULL;
215 	int sz = -1;
216 
217 	/* Encode key */
218 	BIO *mem = BIO_new(BIO_s_mem());
219 	if (i2d_PUBKEY_bio(mem, k) <= 0) {
220 		ERR_print_errors_fp(stderr);
221 		return NULL;
222 	}
223 	p = (unsigned char *)OPENSSL_malloc(4096);
224 	sz = BIO_read(mem, p, 4096);
225 
226 	/* Create the extension */
227 	ex = ext_new(nid, crit, p, sz);
228 
229 	/* Clean up */
230 	OPENSSL_free(p);
231 
232 	return ex;
233 }
234