blob: 65dd3e583dba71e164d802bf3b0b83473dbc4a15 [file] [log] [blame]
Juan Castillo11abdcd2014-10-21 11:30:42 +01001/*
Sandrine Bailleux0d11b482020-01-15 11:01:25 +01002 * Copyright (c) 2015-2020, 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"
Juan Castillo11abdcd2014-10-21 11:30:42 +010016#include "ext.h"
17
18DECLARE_ASN1_ITEM(ASN1_INTEGER)
Juan Castilloac402932015-03-05 14:30:00 +000019DECLARE_ASN1_ITEM(X509_ALGOR)
Juan Castillo11abdcd2014-10-21 11:30:42 +010020DECLARE_ASN1_ITEM(ASN1_OCTET_STRING)
21
Juan Castilloac402932015-03-05 14:30:00 +000022typedef struct {
23 X509_ALGOR *hashAlgorithm;
24 ASN1_OCTET_STRING *dataHash;
25} HASH;
26
27ASN1_SEQUENCE(HASH) = {
28 ASN1_SIMPLE(HASH, hashAlgorithm, X509_ALGOR),
29 ASN1_SIMPLE(HASH, dataHash, ASN1_OCTET_STRING),
30} ASN1_SEQUENCE_END(HASH)
31
32DECLARE_ASN1_FUNCTIONS(HASH)
33IMPLEMENT_ASN1_FUNCTIONS(HASH)
34
Juan Castillo11abdcd2014-10-21 11:30:42 +010035/*
Sandrine Bailleux0d11b482020-01-15 11:01:25 +010036 * This function adds the CoT extensions to the internal extension list
Juan Castillo11abdcd2014-10-21 11:30:42 +010037 * maintained by OpenSSL so they can be used later.
38 *
39 * It also initializes the methods to print the contents of the extension. If an
Sandrine Bailleux0d11b482020-01-15 11:01:25 +010040 * alias is specified in the CoT extension, we reuse the methods of the alias.
Juan Castillo11abdcd2014-10-21 11:30:42 +010041 * Otherwise, only methods for V_ASN1_INTEGER and V_ASN1_OCTET_STRING are
42 * provided. Any other type will be printed as a raw ascii string.
43 *
44 * Return: 0 = success, Otherwise: error
45 */
Juan Castillo1218dd52015-07-03 16:23:16 +010046int ext_init(void)
Juan Castillo11abdcd2014-10-21 11:30:42 +010047{
Juan Castillo212f7382015-12-15 16:37:57 +000048 cmd_opt_t cmd_opt;
Juan Castillo11abdcd2014-10-21 11:30:42 +010049 ext_t *ext;
50 X509V3_EXT_METHOD *m;
Juan Castillo1218dd52015-07-03 16:23:16 +010051 int nid, ret;
52 unsigned int i;
Juan Castillo11abdcd2014-10-21 11:30:42 +010053
Juan Castillo1218dd52015-07-03 16:23:16 +010054 for (i = 0; i < num_extensions; i++) {
55 ext = &extensions[i];
56 /* Register command line option */
57 if (ext->opt) {
Juan Castillo212f7382015-12-15 16:37:57 +000058 cmd_opt.long_opt.name = ext->opt;
59 cmd_opt.long_opt.has_arg = required_argument;
60 cmd_opt.long_opt.flag = NULL;
61 cmd_opt.long_opt.val = CMD_OPT_EXT;
62 cmd_opt.help_msg = ext->help_msg;
63 cmd_opt_add(&cmd_opt);
Juan Castillo1218dd52015-07-03 16:23:16 +010064 }
65 /* Register the extension OID in OpenSSL */
66 if (ext->oid == NULL) {
67 continue;
68 }
Juan Castillo11abdcd2014-10-21 11:30:42 +010069 nid = OBJ_create(ext->oid, ext->sn, ext->ln);
70 if (ext->alias) {
71 X509V3_EXT_add_alias(nid, ext->alias);
72 } else {
73 m = &ext->method;
74 memset(m, 0x0, sizeof(X509V3_EXT_METHOD));
Juan Castilloe6d30e92015-06-12 11:27:59 +010075 switch (ext->asn1_type) {
Juan Castillo11abdcd2014-10-21 11:30:42 +010076 case V_ASN1_INTEGER:
77 m->it = ASN1_ITEM_ref(ASN1_INTEGER);
78 m->i2s = (X509V3_EXT_I2S)i2s_ASN1_INTEGER;
79 m->s2i = (X509V3_EXT_S2I)s2i_ASN1_INTEGER;
80 break;
81 case V_ASN1_OCTET_STRING:
82 m->it = ASN1_ITEM_ref(ASN1_OCTET_STRING);
83 m->i2s = (X509V3_EXT_I2S)i2s_ASN1_OCTET_STRING;
84 m->s2i = (X509V3_EXT_S2I)s2i_ASN1_OCTET_STRING;
85 break;
86 default:
87 continue;
88 }
89 m->ext_nid = nid;
90 ret = X509V3_EXT_add(m);
91 if (!ret) {
92 ERR_print_errors_fp(stdout);
93 return 1;
94 }
95 }
96 }
97 return 0;
98}
99
100/*
101 * Create a new extension
102 *
103 * Extension ::= SEQUENCE {
104 * id OBJECT IDENTIFIER,
105 * critical BOOLEAN DEFAULT FALSE,
106 * value OCTET STRING }
107 *
108 * Parameters:
109 * pex: OpenSSL extension pointer (output parameter)
110 * nid: extension identifier
111 * crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
112 * data: extension data. This data will be encapsulated in an Octet String
113 *
114 * Return: Extension address, NULL if error
115 */
116static
117X509_EXTENSION *ext_new(int nid, int crit, unsigned char *data, int len)
118{
119 X509_EXTENSION *ex;
120 ASN1_OCTET_STRING *ext_data;
121
122 /* Octet string containing the extension data */
123 ext_data = ASN1_OCTET_STRING_new();
124 ASN1_OCTET_STRING_set(ext_data, data, len);
125
126 /* Create the extension */
127 ex = X509_EXTENSION_create_by_NID(NULL, nid, crit, ext_data);
128
129 /* The extension makes a copy of the data, so we can free this object */
130 ASN1_OCTET_STRING_free(ext_data);
131
132 return ex;
133}
134
135/*
Juan Castilloac402932015-03-05 14:30:00 +0000136 * Creates a x509v3 extension containing a hash
137 *
138 * DigestInfo ::= SEQUENCE {
139 * digestAlgorithm AlgorithmIdentifier,
140 * digest OCTET STRING
141 * }
142 *
143 * AlgorithmIdentifier ::= SEQUENCE {
144 * algorithm OBJECT IDENTIFIER,
145 * parameters ANY DEFINED BY algorithm OPTIONAL
146 * }
Juan Castillo11abdcd2014-10-21 11:30:42 +0100147 *
148 * Parameters:
Juan Castillo11abdcd2014-10-21 11:30:42 +0100149 * nid: extension identifier
150 * crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
Juan Castilloac402932015-03-05 14:30:00 +0000151 * md: hash algorithm
Juan Castillo11abdcd2014-10-21 11:30:42 +0100152 * buf: pointer to the buffer that contains the hash
153 * len: size of the hash in bytes
154 *
155 * Return: Extension address, NULL if error
156 */
Juan Castilloac402932015-03-05 14:30:00 +0000157X509_EXTENSION *ext_new_hash(int nid, int crit, const EVP_MD *md,
158 unsigned char *buf, size_t len)
Juan Castillo11abdcd2014-10-21 11:30:42 +0100159{
Masahiro Yamada48cb5e52017-02-06 19:47:44 +0900160 X509_EXTENSION *ex;
Masahiro Yamada48cb5e52017-02-06 19:47:44 +0900161 HASH *hash;
162 ASN1_OBJECT *algorithm;
Juan Castillo11abdcd2014-10-21 11:30:42 +0100163 unsigned char *p = NULL;
Masahiro Yamada48cb5e52017-02-06 19:47:44 +0900164 int sz;
Juan Castillo11abdcd2014-10-21 11:30:42 +0100165
Jimmy Brissonbec47e12020-07-27 13:22:42 -0500166 /* HASH structure containing algorithm + hash */
167 hash = HASH_new();
168 if (hash == NULL) {
169 return NULL;
170 }
171
Juan Castilloac402932015-03-05 14:30:00 +0000172 /* OBJECT_IDENTIFIER with hash algorithm */
Michalis Pappas38628942017-10-06 16:11:44 +0800173 algorithm = OBJ_nid2obj(EVP_MD_type(md));
Juan Castilloac402932015-03-05 14:30:00 +0000174 if (algorithm == NULL) {
Jimmy Brissonbec47e12020-07-27 13:22:42 -0500175 HASH_free(hash);
Juan Castilloac402932015-03-05 14:30:00 +0000176 return NULL;
177 }
178
179 /* Create X509_ALGOR */
Jimmy Brissonbec47e12020-07-27 13:22:42 -0500180 hash->hashAlgorithm->algorithm = algorithm;
181 hash->hashAlgorithm->parameter = ASN1_TYPE_new();
182 ASN1_TYPE_set(hash->hashAlgorithm->parameter, V_ASN1_NULL, NULL);
Juan Castilloac402932015-03-05 14:30:00 +0000183
184 /* OCTET_STRING with the actual hash */
Jimmy Brissonbec47e12020-07-27 13:22:42 -0500185 ASN1_OCTET_STRING_set(hash->dataHash, buf, len);
Juan Castilloac402932015-03-05 14:30:00 +0000186
187 /* DER encoded HASH */
188 sz = i2d_HASH(hash, &p);
189 if ((sz <= 0) || (p == NULL)) {
190 HASH_free(hash);
Juan Castilloac402932015-03-05 14:30:00 +0000191 return NULL;
192 }
Juan Castillo11abdcd2014-10-21 11:30:42 +0100193
194 /* Create the extension */
195 ex = ext_new(nid, crit, p, sz);
196
197 /* Clean up */
198 OPENSSL_free(p);
Juan Castilloac402932015-03-05 14:30:00 +0000199 HASH_free(hash);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100200
201 return ex;
202}
203
204/*
205 * Creates a x509v3 extension containing a nvcounter encapsulated in an ASN1
206 * Integer
207 *
208 * Parameters:
209 * pex: OpenSSL extension pointer (output parameter)
210 * nid: extension identifier
211 * crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
212 * value: nvcounter value
213 *
214 * Return: Extension address, NULL if error
215 */
216X509_EXTENSION *ext_new_nvcounter(int nid, int crit, int value)
217{
Masahiro Yamada48cb5e52017-02-06 19:47:44 +0900218 X509_EXTENSION *ex;
219 ASN1_INTEGER *counter;
Juan Castillo11abdcd2014-10-21 11:30:42 +0100220 unsigned char *p = NULL;
Masahiro Yamada48cb5e52017-02-06 19:47:44 +0900221 int sz;
Juan Castillo11abdcd2014-10-21 11:30:42 +0100222
223 /* Encode counter */
224 counter = ASN1_INTEGER_new();
225 ASN1_INTEGER_set(counter, value);
Masahiro Yamadad54cfa92017-02-06 19:00:11 +0900226 sz = i2d_ASN1_INTEGER(counter, &p);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100227
228 /* Create the extension */
229 ex = ext_new(nid, crit, p, sz);
230
231 /* Free objects */
232 OPENSSL_free(p);
233 ASN1_INTEGER_free(counter);
234
235 return ex;
236}
237
238/*
239 * Creates a x509v3 extension containing a public key in DER format:
240 *
241 * SubjectPublicKeyInfo ::= SEQUENCE {
242 * algorithm AlgorithmIdentifier,
243 * subjectPublicKey BIT STRING }
244 *
245 * Parameters:
246 * pex: OpenSSL extension pointer (output parameter)
247 * nid: extension identifier
248 * crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
249 * k: key
250 *
251 * Return: Extension address, NULL if error
252 */
253X509_EXTENSION *ext_new_key(int nid, int crit, EVP_PKEY *k)
254{
Masahiro Yamada48cb5e52017-02-06 19:47:44 +0900255 X509_EXTENSION *ex;
256 unsigned char *p;
257 int sz;
Juan Castillo11abdcd2014-10-21 11:30:42 +0100258
259 /* Encode key */
260 BIO *mem = BIO_new(BIO_s_mem());
261 if (i2d_PUBKEY_bio(mem, k) <= 0) {
262 ERR_print_errors_fp(stderr);
263 return NULL;
264 }
265 p = (unsigned char *)OPENSSL_malloc(4096);
266 sz = BIO_read(mem, p, 4096);
267
268 /* Create the extension */
269 ex = ext_new(nid, crit, p, sz);
270
271 /* Clean up */
Justin Chadwellfa3ec4c2019-08-12 12:19:21 +0100272 BIO_free(mem);
Juan Castillo11abdcd2014-10-21 11:30:42 +0100273 OPENSSL_free(p);
274
275 return ex;
276}
Juan Castillo1218dd52015-07-03 16:23:16 +0100277
278ext_t *ext_get_by_opt(const char *opt)
279{
Masahiro Yamada48cb5e52017-02-06 19:47:44 +0900280 ext_t *ext;
Juan Castillo1218dd52015-07-03 16:23:16 +0100281 unsigned int i;
282
283 /* Sequential search. This is not a performance concern since the number
284 * of extensions is bounded and the code runs on a host machine */
285 for (i = 0; i < num_extensions; i++) {
286 ext = &extensions[i];
287 if (ext->opt && !strcmp(ext->opt, opt)) {
288 return ext;
289 }
290 }
291
292 return NULL;
293}