1 /*
2 * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <stddef.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <openssl/asn1.h>
11 #include <openssl/asn1t.h>
12 #include <openssl/err.h>
13 #include <openssl/x509v3.h>
14
15 #include "cmd_opt.h"
16 #include "ext.h"
17
18 DECLARE_ASN1_ITEM(ASN1_INTEGER)
19 DECLARE_ASN1_ITEM(X509_ALGOR)
20 DECLARE_ASN1_ITEM(ASN1_OCTET_STRING)
21
22 typedef struct {
23 X509_ALGOR *hashAlgorithm;
24 ASN1_OCTET_STRING *dataHash;
25 } HASH;
26
27 ASN1_SEQUENCE(HASH) = {
28 ASN1_SIMPLE(HASH, hashAlgorithm, X509_ALGOR),
29 ASN1_SIMPLE(HASH, dataHash, ASN1_OCTET_STRING),
30 } ASN1_SEQUENCE_END(HASH)
31
32 DECLARE_ASN1_FUNCTIONS(HASH)
33 IMPLEMENT_ASN1_FUNCTIONS(HASH)
34
35 /*
36 * This function adds the TBB extensions to the internal extension list
37 * 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
40 * alias is specified in the TBB extension, we reuse the methods of the alias.
41 * 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 */
46 int ext_init(void)
47 {
48 cmd_opt_t cmd_opt;
49 ext_t *ext;
50 X509V3_EXT_METHOD *m;
51 int nid, ret;
52 unsigned int i;
53
54 for (i = 0; i < num_extensions; i++) {
55 ext = &extensions[i];
56 /* Register command line option */
57 if (ext->opt) {
58 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);
64 }
65 /* Register the extension OID in OpenSSL */
66 if (ext->oid == NULL) {
67 continue;
68 }
69 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));
75 switch (ext->asn1_type) {
76 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 */
116 static
ext_new(int nid,int crit,unsigned char * data,int len)117 X509_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 /*
136 * 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 * }
147 *
148 * Parameters:
149 * nid: extension identifier
150 * crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
151 * md: hash algorithm
152 * 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 */
ext_new_hash(int nid,int crit,const EVP_MD * md,unsigned char * buf,size_t len)157 X509_EXTENSION *ext_new_hash(int nid, int crit, const EVP_MD *md,
158 unsigned char *buf, size_t len)
159 {
160 X509_EXTENSION *ex;
161 ASN1_OCTET_STRING *octet;
162 HASH *hash;
163 ASN1_OBJECT *algorithm;
164 X509_ALGOR *x509_algor;
165 unsigned char *p = NULL;
166 int sz;
167
168 /* OBJECT_IDENTIFIER with hash algorithm */
169 algorithm = OBJ_nid2obj(EVP_MD_type(md));
170 if (algorithm == NULL) {
171 return NULL;
172 }
173
174 /* Create X509_ALGOR */
175 x509_algor = X509_ALGOR_new();
176 if (x509_algor == NULL) {
177 return NULL;
178 }
179 x509_algor->algorithm = algorithm;
180 x509_algor->parameter = ASN1_TYPE_new();
181 ASN1_TYPE_set(x509_algor->parameter, V_ASN1_NULL, NULL);
182
183 /* OCTET_STRING with the actual hash */
184 octet = ASN1_OCTET_STRING_new();
185 if (octet == NULL) {
186 X509_ALGOR_free(x509_algor);
187 return NULL;
188 }
189 ASN1_OCTET_STRING_set(octet, buf, len);
190
191 /* HASH structure containing algorithm + hash */
192 hash = HASH_new();
193 if (hash == NULL) {
194 ASN1_OCTET_STRING_free(octet);
195 X509_ALGOR_free(x509_algor);
196 return NULL;
197 }
198 hash->hashAlgorithm = x509_algor;
199 hash->dataHash = octet;
200
201 /* DER encoded HASH */
202 sz = i2d_HASH(hash, &p);
203 if ((sz <= 0) || (p == NULL)) {
204 HASH_free(hash);
205 X509_ALGOR_free(x509_algor);
206 return NULL;
207 }
208
209 /* Create the extension */
210 ex = ext_new(nid, crit, p, sz);
211
212 /* Clean up */
213 OPENSSL_free(p);
214 HASH_free(hash);
215
216 return ex;
217 }
218
219 /*
220 * Creates a x509v3 extension containing a nvcounter encapsulated in an ASN1
221 * Integer
222 *
223 * Parameters:
224 * pex: OpenSSL extension pointer (output parameter)
225 * nid: extension identifier
226 * crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
227 * value: nvcounter value
228 *
229 * Return: Extension address, NULL if error
230 */
ext_new_nvcounter(int nid,int crit,int value)231 X509_EXTENSION *ext_new_nvcounter(int nid, int crit, int value)
232 {
233 X509_EXTENSION *ex;
234 ASN1_INTEGER *counter;
235 unsigned char *p = NULL;
236 int sz;
237
238 /* Encode counter */
239 counter = ASN1_INTEGER_new();
240 ASN1_INTEGER_set(counter, value);
241 sz = i2d_ASN1_INTEGER(counter, &p);
242
243 /* Create the extension */
244 ex = ext_new(nid, crit, p, sz);
245
246 /* Free objects */
247 OPENSSL_free(p);
248 ASN1_INTEGER_free(counter);
249
250 return ex;
251 }
252
253 /*
254 * Creates a x509v3 extension containing a public key in DER format:
255 *
256 * SubjectPublicKeyInfo ::= SEQUENCE {
257 * algorithm AlgorithmIdentifier,
258 * subjectPublicKey BIT STRING }
259 *
260 * Parameters:
261 * pex: OpenSSL extension pointer (output parameter)
262 * nid: extension identifier
263 * crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
264 * k: key
265 *
266 * Return: Extension address, NULL if error
267 */
ext_new_key(int nid,int crit,EVP_PKEY * k)268 X509_EXTENSION *ext_new_key(int nid, int crit, EVP_PKEY *k)
269 {
270 X509_EXTENSION *ex;
271 unsigned char *p;
272 int sz;
273
274 /* Encode key */
275 BIO *mem = BIO_new(BIO_s_mem());
276 if (i2d_PUBKEY_bio(mem, k) <= 0) {
277 ERR_print_errors_fp(stderr);
278 return NULL;
279 }
280 p = (unsigned char *)OPENSSL_malloc(4096);
281 sz = BIO_read(mem, p, 4096);
282
283 /* Create the extension */
284 ex = ext_new(nid, crit, p, sz);
285
286 /* Clean up */
287 OPENSSL_free(p);
288
289 return ex;
290 }
291
ext_get_by_opt(const char * opt)292 ext_t *ext_get_by_opt(const char *opt)
293 {
294 ext_t *ext;
295 unsigned int i;
296
297 /* Sequential search. This is not a performance concern since the number
298 * of extensions is bounded and the code runs on a host machine */
299 for (i = 0; i < num_extensions; i++) {
300 ext = &extensions[i];
301 if (ext->opt && !strcmp(ext->opt, opt)) {
302 return ext;
303 }
304 }
305
306 return NULL;
307 }
308