blob: 3f56edb756c25f910b19f9ed35b90e1003c93f9e [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>
Juan Castillo1218dd52015-07-03 16:23:16 +010038
39#include "cmd_opt.h"
Juan Castillo11abdcd2014-10-21 11:30:42 +010040#include "ext.h"
41
42DECLARE_ASN1_ITEM(ASN1_INTEGER)
Juan Castilloac402932015-03-05 14:30:00 +000043DECLARE_ASN1_ITEM(X509_ALGOR)
Juan Castillo11abdcd2014-10-21 11:30:42 +010044DECLARE_ASN1_ITEM(ASN1_OCTET_STRING)
45
Juan Castilloac402932015-03-05 14:30:00 +000046typedef struct {
47 X509_ALGOR *hashAlgorithm;
48 ASN1_OCTET_STRING *dataHash;
49} HASH;
50
51ASN1_SEQUENCE(HASH) = {
52 ASN1_SIMPLE(HASH, hashAlgorithm, X509_ALGOR),
53 ASN1_SIMPLE(HASH, dataHash, ASN1_OCTET_STRING),
54} ASN1_SEQUENCE_END(HASH)
55
56DECLARE_ASN1_FUNCTIONS(HASH)
57IMPLEMENT_ASN1_FUNCTIONS(HASH)
58
Juan Castillo11abdcd2014-10-21 11:30:42 +010059/*
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 */
Juan Castillo1218dd52015-07-03 16:23:16 +010070int ext_init(void)
Juan Castillo11abdcd2014-10-21 11:30:42 +010071{
Juan Castillo212f7382015-12-15 16:37:57 +000072 cmd_opt_t cmd_opt;
Juan Castillo11abdcd2014-10-21 11:30:42 +010073 ext_t *ext;
74 X509V3_EXT_METHOD *m;
Juan Castillo1218dd52015-07-03 16:23:16 +010075 int nid, ret;
76 unsigned int i;
Juan Castillo11abdcd2014-10-21 11:30:42 +010077
Juan Castillo1218dd52015-07-03 16:23:16 +010078 for (i = 0; i < num_extensions; i++) {
79 ext = &extensions[i];
80 /* Register command line option */
81 if (ext->opt) {
Juan Castillo212f7382015-12-15 16:37:57 +000082 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);
Juan Castillo1218dd52015-07-03 16:23:16 +010088 }
89 /* Register the extension OID in OpenSSL */
90 if (ext->oid == NULL) {
91 continue;
92 }
Juan Castillo11abdcd2014-10-21 11:30:42 +010093 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));
Juan Castilloe6d30e92015-06-12 11:27:59 +010099 switch (ext->asn1_type) {
Juan Castillo11abdcd2014-10-21 11:30:42 +0100100 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 */
140static
141X509_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/*
Juan Castilloac402932015-03-05 14:30:00 +0000160 * 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 * }
Juan Castillo11abdcd2014-10-21 11:30:42 +0100171 *
172 * Parameters:
Juan Castillo11abdcd2014-10-21 11:30:42 +0100173 * nid: extension identifier
174 * crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
Juan Castilloac402932015-03-05 14:30:00 +0000175 * md: hash algorithm
Juan Castillo11abdcd2014-10-21 11:30:42 +0100176 * 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 */
Juan Castilloac402932015-03-05 14:30:00 +0000181X509_EXTENSION *ext_new_hash(int nid, int crit, const EVP_MD *md,
182 unsigned char *buf, size_t len)
Juan Castillo11abdcd2014-10-21 11:30:42 +0100183{
184 X509_EXTENSION *ex = NULL;
Juan Castilloac402932015-03-05 14:30:00 +0000185 ASN1_OCTET_STRING *octet = NULL;
186 HASH *hash = NULL;
187 ASN1_OBJECT *algorithm = NULL;
188 X509_ALGOR *x509_algor = NULL;
Juan Castillo11abdcd2014-10-21 11:30:42 +0100189 unsigned char *p = NULL;
190 int sz = -1;
191
Juan Castilloac402932015-03-05 14:30:00 +0000192 /* 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 }
Juan Castillo11abdcd2014-10-21 11:30:42 +0100232
233 /* Create the extension */
234 ex = ext_new(nid, crit, p, sz);
235
236 /* Clean up */
237 OPENSSL_free(p);
Juan Castilloac402932015-03-05 14:30:00 +0000238 HASH_free(hash);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100239
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 */
255X509_EXTENSION *ext_new_nvcounter(int nid, int crit, int value)
256{
257 X509_EXTENSION *ex = NULL;
258 ASN1_INTEGER *counter = NULL;
259 unsigned char *p = NULL;
260 int sz = -1;
261
262 /* Encode counter */
263 counter = ASN1_INTEGER_new();
264 ASN1_INTEGER_set(counter, value);
265 sz = i2d_ASN1_INTEGER(counter, NULL);
266 i2d_ASN1_INTEGER(counter, &p);
267
268 /* Create the extension */
269 ex = ext_new(nid, crit, p, sz);
270
271 /* Free objects */
272 OPENSSL_free(p);
273 ASN1_INTEGER_free(counter);
274
275 return ex;
276}
277
278/*
279 * Creates a x509v3 extension containing a public key in DER format:
280 *
281 * SubjectPublicKeyInfo ::= SEQUENCE {
282 * algorithm AlgorithmIdentifier,
283 * subjectPublicKey BIT STRING }
284 *
285 * Parameters:
286 * pex: OpenSSL extension pointer (output parameter)
287 * nid: extension identifier
288 * crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
289 * k: key
290 *
291 * Return: Extension address, NULL if error
292 */
293X509_EXTENSION *ext_new_key(int nid, int crit, EVP_PKEY *k)
294{
295 X509_EXTENSION *ex = NULL;
296 unsigned char *p = NULL;
297 int sz = -1;
298
299 /* Encode key */
300 BIO *mem = BIO_new(BIO_s_mem());
301 if (i2d_PUBKEY_bio(mem, k) <= 0) {
302 ERR_print_errors_fp(stderr);
303 return NULL;
304 }
305 p = (unsigned char *)OPENSSL_malloc(4096);
306 sz = BIO_read(mem, p, 4096);
307
308 /* Create the extension */
309 ex = ext_new(nid, crit, p, sz);
310
311 /* Clean up */
312 OPENSSL_free(p);
313
314 return ex;
315}
Juan Castillo1218dd52015-07-03 16:23:16 +0100316
317ext_t *ext_get_by_opt(const char *opt)
318{
319 ext_t *ext = NULL;
320 unsigned int i;
321
322 /* Sequential search. This is not a performance concern since the number
323 * of extensions is bounded and the code runs on a host machine */
324 for (i = 0; i < num_extensions; i++) {
325 ext = &extensions[i];
326 if (ext->opt && !strcmp(ext->opt, opt)) {
327 return ext;
328 }
329 }
330
331 return NULL;
332}