blob: 21b90db17a2eb1649d19ec8b76d585f6414cee29 [file] [log] [blame]
Juan Castillo11abdcd2014-10-21 11:30:42 +01001/*
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>
Juan Castilloac402932015-03-05 14:30:00 +000034#include <openssl/asn1.h>
35#include <openssl/asn1t.h>
Juan Castillo11abdcd2014-10-21 11:30:42 +010036#include <openssl/err.h>
37#include <openssl/x509v3.h>
38#include "ext.h"
39
40DECLARE_ASN1_ITEM(ASN1_INTEGER)
Juan Castilloac402932015-03-05 14:30:00 +000041DECLARE_ASN1_ITEM(X509_ALGOR)
Juan Castillo11abdcd2014-10-21 11:30:42 +010042DECLARE_ASN1_ITEM(ASN1_OCTET_STRING)
43
Juan Castilloac402932015-03-05 14:30:00 +000044typedef struct {
45 X509_ALGOR *hashAlgorithm;
46 ASN1_OCTET_STRING *dataHash;
47} HASH;
48
49ASN1_SEQUENCE(HASH) = {
50 ASN1_SIMPLE(HASH, hashAlgorithm, X509_ALGOR),
51 ASN1_SIMPLE(HASH, dataHash, ASN1_OCTET_STRING),
52} ASN1_SEQUENCE_END(HASH)
53
54DECLARE_ASN1_FUNCTIONS(HASH)
55IMPLEMENT_ASN1_FUNCTIONS(HASH)
56
Juan Castillo11abdcd2014-10-21 11:30:42 +010057/*
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 */
68int ext_init(ext_t *tbb_ext)
69{
70 ext_t *ext;
71 X509V3_EXT_METHOD *m;
72 int i = 0, nid, ret;
73
74 while ((ext = &tbb_ext[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->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 */
122static
123X509_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/*
Juan Castilloac402932015-03-05 14:30:00 +0000142 * 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 * }
Juan Castillo11abdcd2014-10-21 11:30:42 +0100153 *
154 * Parameters:
Juan Castillo11abdcd2014-10-21 11:30:42 +0100155 * nid: extension identifier
156 * crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
Juan Castilloac402932015-03-05 14:30:00 +0000157 * md: hash algorithm
Juan Castillo11abdcd2014-10-21 11:30:42 +0100158 * 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 */
Juan Castilloac402932015-03-05 14:30:00 +0000163X509_EXTENSION *ext_new_hash(int nid, int crit, const EVP_MD *md,
164 unsigned char *buf, size_t len)
Juan Castillo11abdcd2014-10-21 11:30:42 +0100165{
166 X509_EXTENSION *ex = NULL;
Juan Castilloac402932015-03-05 14:30:00 +0000167 ASN1_OCTET_STRING *octet = NULL;
168 HASH *hash = NULL;
169 ASN1_OBJECT *algorithm = NULL;
170 X509_ALGOR *x509_algor = NULL;
Juan Castillo11abdcd2014-10-21 11:30:42 +0100171 unsigned char *p = NULL;
172 int sz = -1;
173
Juan Castilloac402932015-03-05 14:30:00 +0000174 /* 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 }
Juan Castillo11abdcd2014-10-21 11:30:42 +0100214
215 /* Create the extension */
216 ex = ext_new(nid, crit, p, sz);
217
218 /* Clean up */
219 OPENSSL_free(p);
Juan Castilloac402932015-03-05 14:30:00 +0000220 HASH_free(hash);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100221
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 */
237X509_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 */
275X509_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}