blob: 28821238fc536d17889f4586884d89161ae5fc6d [file] [log] [blame]
Juan Castillo11abdcd2014-10-21 11:30:42 +01001/*
Pankaj Guptadd906e62020-12-09 14:02:38 +05302 * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
Juan Castillo11abdcd2014-10-21 11:30:42 +01003 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Juan Castillo11abdcd2014-10-21 11:30:42 +01005 */
6
7#include <stddef.h>
8#include <stdio.h>
9#include <string.h>
Juan Castilloac402932015-03-05 14:30:00 +000010#include <openssl/asn1.h>
11#include <openssl/asn1t.h>
Juan Castillo11abdcd2014-10-21 11:30:42 +010012#include <openssl/err.h>
13#include <openssl/x509v3.h>
Juan Castillo1218dd52015-07-03 16:23:16 +010014
15#include "cmd_opt.h"
Pankaj Guptadd906e62020-12-09 14:02:38 +053016#include "debug.h"
Juan Castillo11abdcd2014-10-21 11:30:42 +010017#include "ext.h"
18
Pankaj Guptadd906e62020-12-09 14:02:38 +053019ext_t *extensions;
20unsigned int num_extensions;
21
Juan Castillo11abdcd2014-10-21 11:30:42 +010022DECLARE_ASN1_ITEM(ASN1_INTEGER)
Juan Castilloac402932015-03-05 14:30:00 +000023DECLARE_ASN1_ITEM(X509_ALGOR)
Juan Castillo11abdcd2014-10-21 11:30:42 +010024DECLARE_ASN1_ITEM(ASN1_OCTET_STRING)
25
Juan Castilloac402932015-03-05 14:30:00 +000026typedef struct {
27 X509_ALGOR *hashAlgorithm;
28 ASN1_OCTET_STRING *dataHash;
29} HASH;
30
31ASN1_SEQUENCE(HASH) = {
32 ASN1_SIMPLE(HASH, hashAlgorithm, X509_ALGOR),
33 ASN1_SIMPLE(HASH, dataHash, ASN1_OCTET_STRING),
34} ASN1_SEQUENCE_END(HASH)
35
36DECLARE_ASN1_FUNCTIONS(HASH)
37IMPLEMENT_ASN1_FUNCTIONS(HASH)
38
Juan Castillo11abdcd2014-10-21 11:30:42 +010039/*
Sandrine Bailleux0d11b482020-01-15 11:01:25 +010040 * This function adds the CoT extensions to the internal extension list
Juan Castillo11abdcd2014-10-21 11:30:42 +010041 * maintained by OpenSSL so they can be used later.
42 *
43 * It also initializes the methods to print the contents of the extension. If an
Sandrine Bailleux0d11b482020-01-15 11:01:25 +010044 * alias is specified in the CoT extension, we reuse the methods of the alias.
Juan Castillo11abdcd2014-10-21 11:30:42 +010045 * Otherwise, only methods for V_ASN1_INTEGER and V_ASN1_OCTET_STRING are
46 * provided. Any other type will be printed as a raw ascii string.
47 *
48 * Return: 0 = success, Otherwise: error
49 */
Juan Castillo1218dd52015-07-03 16:23:16 +010050int ext_init(void)
Juan Castillo11abdcd2014-10-21 11:30:42 +010051{
Juan Castillo212f7382015-12-15 16:37:57 +000052 cmd_opt_t cmd_opt;
Juan Castillo11abdcd2014-10-21 11:30:42 +010053 ext_t *ext;
54 X509V3_EXT_METHOD *m;
Juan Castillo1218dd52015-07-03 16:23:16 +010055 int nid, ret;
56 unsigned int i;
Juan Castillo11abdcd2014-10-21 11:30:42 +010057
Pankaj Guptadd906e62020-12-09 14:02:38 +053058 extensions = malloc((num_def_extensions * sizeof(def_extensions[0]))
59#ifdef PDEF_EXTS
60 + (num_pdef_extensions * sizeof(pdef_extensions[0]))
61#endif
62 );
63 if (extensions == NULL) {
64 ERROR("%s:%d Failed to allocate memory.\n", __func__, __LINE__);
65 return 1;
66 }
67
68 memcpy(&extensions[0], &def_extensions[0],
69 (num_def_extensions * sizeof(def_extensions[0])));
70#ifdef PDEF_EXTS
71 memcpy(&extensions[num_def_extensions], &pdef_extensions[0],
72 (num_pdef_extensions * sizeof(pdef_extensions[0])));
73 num_extensions = num_def_extensions + num_pdef_extensions;
74#else
75 num_extensions = num_def_extensions;
76#endif
77
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{
Masahiro Yamada48cb5e52017-02-06 19:47:44 +0900184 X509_EXTENSION *ex;
Masahiro Yamada48cb5e52017-02-06 19:47:44 +0900185 HASH *hash;
186 ASN1_OBJECT *algorithm;
Juan Castillo11abdcd2014-10-21 11:30:42 +0100187 unsigned char *p = NULL;
Masahiro Yamada48cb5e52017-02-06 19:47:44 +0900188 int sz;
Juan Castillo11abdcd2014-10-21 11:30:42 +0100189
Jimmy Brissonbec47e12020-07-27 13:22:42 -0500190 /* HASH structure containing algorithm + hash */
191 hash = HASH_new();
192 if (hash == NULL) {
193 return NULL;
194 }
195
Juan Castilloac402932015-03-05 14:30:00 +0000196 /* OBJECT_IDENTIFIER with hash algorithm */
Michalis Pappas38628942017-10-06 16:11:44 +0800197 algorithm = OBJ_nid2obj(EVP_MD_type(md));
Juan Castilloac402932015-03-05 14:30:00 +0000198 if (algorithm == NULL) {
Jimmy Brissonbec47e12020-07-27 13:22:42 -0500199 HASH_free(hash);
Juan Castilloac402932015-03-05 14:30:00 +0000200 return NULL;
201 }
202
203 /* Create X509_ALGOR */
Jimmy Brissonbec47e12020-07-27 13:22:42 -0500204 hash->hashAlgorithm->algorithm = algorithm;
205 hash->hashAlgorithm->parameter = ASN1_TYPE_new();
206 ASN1_TYPE_set(hash->hashAlgorithm->parameter, V_ASN1_NULL, NULL);
Juan Castilloac402932015-03-05 14:30:00 +0000207
208 /* OCTET_STRING with the actual hash */
Jimmy Brissonbec47e12020-07-27 13:22:42 -0500209 ASN1_OCTET_STRING_set(hash->dataHash, buf, len);
Juan Castilloac402932015-03-05 14:30:00 +0000210
211 /* DER encoded HASH */
212 sz = i2d_HASH(hash, &p);
213 if ((sz <= 0) || (p == NULL)) {
214 HASH_free(hash);
Juan Castilloac402932015-03-05 14:30:00 +0000215 return NULL;
216 }
Juan Castillo11abdcd2014-10-21 11:30:42 +0100217
218 /* Create the extension */
219 ex = ext_new(nid, crit, p, sz);
220
221 /* Clean up */
222 OPENSSL_free(p);
Juan Castilloac402932015-03-05 14:30:00 +0000223 HASH_free(hash);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100224
225 return ex;
226}
227
228/*
229 * Creates a x509v3 extension containing a nvcounter encapsulated in an ASN1
230 * Integer
231 *
232 * Parameters:
233 * pex: OpenSSL extension pointer (output parameter)
234 * nid: extension identifier
235 * crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
236 * value: nvcounter value
237 *
238 * Return: Extension address, NULL if error
239 */
240X509_EXTENSION *ext_new_nvcounter(int nid, int crit, int value)
241{
Masahiro Yamada48cb5e52017-02-06 19:47:44 +0900242 X509_EXTENSION *ex;
243 ASN1_INTEGER *counter;
Juan Castillo11abdcd2014-10-21 11:30:42 +0100244 unsigned char *p = NULL;
Masahiro Yamada48cb5e52017-02-06 19:47:44 +0900245 int sz;
Juan Castillo11abdcd2014-10-21 11:30:42 +0100246
247 /* Encode counter */
248 counter = ASN1_INTEGER_new();
249 ASN1_INTEGER_set(counter, value);
Masahiro Yamadad54cfa92017-02-06 19:00:11 +0900250 sz = i2d_ASN1_INTEGER(counter, &p);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100251
252 /* Create the extension */
253 ex = ext_new(nid, crit, p, sz);
254
255 /* Free objects */
256 OPENSSL_free(p);
257 ASN1_INTEGER_free(counter);
258
259 return ex;
260}
261
262/*
263 * Creates a x509v3 extension containing a public key in DER format:
264 *
265 * SubjectPublicKeyInfo ::= SEQUENCE {
266 * algorithm AlgorithmIdentifier,
267 * subjectPublicKey BIT STRING }
268 *
269 * Parameters:
270 * pex: OpenSSL extension pointer (output parameter)
271 * nid: extension identifier
272 * crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
273 * k: key
274 *
275 * Return: Extension address, NULL if error
276 */
277X509_EXTENSION *ext_new_key(int nid, int crit, EVP_PKEY *k)
278{
Masahiro Yamada48cb5e52017-02-06 19:47:44 +0900279 X509_EXTENSION *ex;
280 unsigned char *p;
281 int sz;
Juan Castillo11abdcd2014-10-21 11:30:42 +0100282
283 /* Encode key */
284 BIO *mem = BIO_new(BIO_s_mem());
285 if (i2d_PUBKEY_bio(mem, k) <= 0) {
286 ERR_print_errors_fp(stderr);
287 return NULL;
288 }
289 p = (unsigned char *)OPENSSL_malloc(4096);
290 sz = BIO_read(mem, p, 4096);
291
292 /* Create the extension */
293 ex = ext_new(nid, crit, p, sz);
294
295 /* Clean up */
Justin Chadwellfa3ec4c2019-08-12 12:19:21 +0100296 BIO_free(mem);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100297 OPENSSL_free(p);
298
299 return ex;
300}
Juan Castillo1218dd52015-07-03 16:23:16 +0100301
302ext_t *ext_get_by_opt(const char *opt)
303{
Masahiro Yamada48cb5e52017-02-06 19:47:44 +0900304 ext_t *ext;
Juan Castillo1218dd52015-07-03 16:23:16 +0100305 unsigned int i;
306
307 /* Sequential search. This is not a performance concern since the number
308 * of extensions is bounded and the code runs on a host machine */
309 for (i = 0; i < num_extensions; i++) {
310 ext = &extensions[i];
311 if (ext->opt && !strcmp(ext->opt, opt)) {
312 return ext;
313 }
314 }
315
316 return NULL;
317}