1*54fd6939SJiyong Park /*
2*54fd6939SJiyong Park * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
3*54fd6939SJiyong Park *
4*54fd6939SJiyong Park * SPDX-License-Identifier: BSD-3-Clause
5*54fd6939SJiyong Park */
6*54fd6939SJiyong Park
7*54fd6939SJiyong Park #include <stddef.h>
8*54fd6939SJiyong Park #include <stdio.h>
9*54fd6939SJiyong Park #include <string.h>
10*54fd6939SJiyong Park #include <openssl/asn1.h>
11*54fd6939SJiyong Park #include <openssl/asn1t.h>
12*54fd6939SJiyong Park #include <openssl/err.h>
13*54fd6939SJiyong Park #include <openssl/x509v3.h>
14*54fd6939SJiyong Park
15*54fd6939SJiyong Park #include "cmd_opt.h"
16*54fd6939SJiyong Park #include "debug.h"
17*54fd6939SJiyong Park #include "ext.h"
18*54fd6939SJiyong Park
19*54fd6939SJiyong Park ext_t *extensions;
20*54fd6939SJiyong Park unsigned int num_extensions;
21*54fd6939SJiyong Park
22*54fd6939SJiyong Park DECLARE_ASN1_ITEM(ASN1_INTEGER)
23*54fd6939SJiyong Park DECLARE_ASN1_ITEM(X509_ALGOR)
24*54fd6939SJiyong Park DECLARE_ASN1_ITEM(ASN1_OCTET_STRING)
25*54fd6939SJiyong Park
26*54fd6939SJiyong Park typedef struct {
27*54fd6939SJiyong Park X509_ALGOR *hashAlgorithm;
28*54fd6939SJiyong Park ASN1_OCTET_STRING *dataHash;
29*54fd6939SJiyong Park } HASH;
30*54fd6939SJiyong Park
31*54fd6939SJiyong Park ASN1_SEQUENCE(HASH) = {
32*54fd6939SJiyong Park ASN1_SIMPLE(HASH, hashAlgorithm, X509_ALGOR),
33*54fd6939SJiyong Park ASN1_SIMPLE(HASH, dataHash, ASN1_OCTET_STRING),
34*54fd6939SJiyong Park } ASN1_SEQUENCE_END(HASH)
35*54fd6939SJiyong Park
36*54fd6939SJiyong Park DECLARE_ASN1_FUNCTIONS(HASH)
37*54fd6939SJiyong Park IMPLEMENT_ASN1_FUNCTIONS(HASH)
38*54fd6939SJiyong Park
39*54fd6939SJiyong Park /*
40*54fd6939SJiyong Park * This function adds the CoT extensions to the internal extension list
41*54fd6939SJiyong Park * maintained by OpenSSL so they can be used later.
42*54fd6939SJiyong Park *
43*54fd6939SJiyong Park * It also initializes the methods to print the contents of the extension. If an
44*54fd6939SJiyong Park * alias is specified in the CoT extension, we reuse the methods of the alias.
45*54fd6939SJiyong Park * Otherwise, only methods for V_ASN1_INTEGER and V_ASN1_OCTET_STRING are
46*54fd6939SJiyong Park * provided. Any other type will be printed as a raw ascii string.
47*54fd6939SJiyong Park *
48*54fd6939SJiyong Park * Return: 0 = success, Otherwise: error
49*54fd6939SJiyong Park */
50*54fd6939SJiyong Park int ext_init(void)
51*54fd6939SJiyong Park {
52*54fd6939SJiyong Park cmd_opt_t cmd_opt;
53*54fd6939SJiyong Park ext_t *ext;
54*54fd6939SJiyong Park X509V3_EXT_METHOD *m;
55*54fd6939SJiyong Park int nid, ret;
56*54fd6939SJiyong Park unsigned int i;
57*54fd6939SJiyong Park
58*54fd6939SJiyong Park extensions = malloc((num_def_extensions * sizeof(def_extensions[0]))
59*54fd6939SJiyong Park #ifdef PDEF_EXTS
60*54fd6939SJiyong Park + (num_pdef_extensions * sizeof(pdef_extensions[0]))
61*54fd6939SJiyong Park #endif
62*54fd6939SJiyong Park );
63*54fd6939SJiyong Park if (extensions == NULL) {
64*54fd6939SJiyong Park ERROR("%s:%d Failed to allocate memory.\n", __func__, __LINE__);
65*54fd6939SJiyong Park return 1;
66*54fd6939SJiyong Park }
67*54fd6939SJiyong Park
68*54fd6939SJiyong Park memcpy(&extensions[0], &def_extensions[0],
69*54fd6939SJiyong Park (num_def_extensions * sizeof(def_extensions[0])));
70*54fd6939SJiyong Park #ifdef PDEF_EXTS
71*54fd6939SJiyong Park memcpy(&extensions[num_def_extensions], &pdef_extensions[0],
72*54fd6939SJiyong Park (num_pdef_extensions * sizeof(pdef_extensions[0])));
73*54fd6939SJiyong Park num_extensions = num_def_extensions + num_pdef_extensions;
74*54fd6939SJiyong Park #else
75*54fd6939SJiyong Park num_extensions = num_def_extensions;
76*54fd6939SJiyong Park #endif
77*54fd6939SJiyong Park
78*54fd6939SJiyong Park for (i = 0; i < num_extensions; i++) {
79*54fd6939SJiyong Park ext = &extensions[i];
80*54fd6939SJiyong Park /* Register command line option */
81*54fd6939SJiyong Park if (ext->opt) {
82*54fd6939SJiyong Park cmd_opt.long_opt.name = ext->opt;
83*54fd6939SJiyong Park cmd_opt.long_opt.has_arg = required_argument;
84*54fd6939SJiyong Park cmd_opt.long_opt.flag = NULL;
85*54fd6939SJiyong Park cmd_opt.long_opt.val = CMD_OPT_EXT;
86*54fd6939SJiyong Park cmd_opt.help_msg = ext->help_msg;
87*54fd6939SJiyong Park cmd_opt_add(&cmd_opt);
88*54fd6939SJiyong Park }
89*54fd6939SJiyong Park /* Register the extension OID in OpenSSL */
90*54fd6939SJiyong Park if (ext->oid == NULL) {
91*54fd6939SJiyong Park continue;
92*54fd6939SJiyong Park }
93*54fd6939SJiyong Park nid = OBJ_create(ext->oid, ext->sn, ext->ln);
94*54fd6939SJiyong Park if (ext->alias) {
95*54fd6939SJiyong Park X509V3_EXT_add_alias(nid, ext->alias);
96*54fd6939SJiyong Park } else {
97*54fd6939SJiyong Park m = &ext->method;
98*54fd6939SJiyong Park memset(m, 0x0, sizeof(X509V3_EXT_METHOD));
99*54fd6939SJiyong Park switch (ext->asn1_type) {
100*54fd6939SJiyong Park case V_ASN1_INTEGER:
101*54fd6939SJiyong Park m->it = ASN1_ITEM_ref(ASN1_INTEGER);
102*54fd6939SJiyong Park m->i2s = (X509V3_EXT_I2S)i2s_ASN1_INTEGER;
103*54fd6939SJiyong Park m->s2i = (X509V3_EXT_S2I)s2i_ASN1_INTEGER;
104*54fd6939SJiyong Park break;
105*54fd6939SJiyong Park case V_ASN1_OCTET_STRING:
106*54fd6939SJiyong Park m->it = ASN1_ITEM_ref(ASN1_OCTET_STRING);
107*54fd6939SJiyong Park m->i2s = (X509V3_EXT_I2S)i2s_ASN1_OCTET_STRING;
108*54fd6939SJiyong Park m->s2i = (X509V3_EXT_S2I)s2i_ASN1_OCTET_STRING;
109*54fd6939SJiyong Park break;
110*54fd6939SJiyong Park default:
111*54fd6939SJiyong Park continue;
112*54fd6939SJiyong Park }
113*54fd6939SJiyong Park m->ext_nid = nid;
114*54fd6939SJiyong Park ret = X509V3_EXT_add(m);
115*54fd6939SJiyong Park if (!ret) {
116*54fd6939SJiyong Park ERR_print_errors_fp(stdout);
117*54fd6939SJiyong Park return 1;
118*54fd6939SJiyong Park }
119*54fd6939SJiyong Park }
120*54fd6939SJiyong Park }
121*54fd6939SJiyong Park return 0;
122*54fd6939SJiyong Park }
123*54fd6939SJiyong Park
124*54fd6939SJiyong Park /*
125*54fd6939SJiyong Park * Create a new extension
126*54fd6939SJiyong Park *
127*54fd6939SJiyong Park * Extension ::= SEQUENCE {
128*54fd6939SJiyong Park * id OBJECT IDENTIFIER,
129*54fd6939SJiyong Park * critical BOOLEAN DEFAULT FALSE,
130*54fd6939SJiyong Park * value OCTET STRING }
131*54fd6939SJiyong Park *
132*54fd6939SJiyong Park * Parameters:
133*54fd6939SJiyong Park * pex: OpenSSL extension pointer (output parameter)
134*54fd6939SJiyong Park * nid: extension identifier
135*54fd6939SJiyong Park * crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
136*54fd6939SJiyong Park * data: extension data. This data will be encapsulated in an Octet String
137*54fd6939SJiyong Park *
138*54fd6939SJiyong Park * Return: Extension address, NULL if error
139*54fd6939SJiyong Park */
140*54fd6939SJiyong Park static
ext_new(int nid,int crit,unsigned char * data,int len)141*54fd6939SJiyong Park X509_EXTENSION *ext_new(int nid, int crit, unsigned char *data, int len)
142*54fd6939SJiyong Park {
143*54fd6939SJiyong Park X509_EXTENSION *ex;
144*54fd6939SJiyong Park ASN1_OCTET_STRING *ext_data;
145*54fd6939SJiyong Park
146*54fd6939SJiyong Park /* Octet string containing the extension data */
147*54fd6939SJiyong Park ext_data = ASN1_OCTET_STRING_new();
148*54fd6939SJiyong Park ASN1_OCTET_STRING_set(ext_data, data, len);
149*54fd6939SJiyong Park
150*54fd6939SJiyong Park /* Create the extension */
151*54fd6939SJiyong Park ex = X509_EXTENSION_create_by_NID(NULL, nid, crit, ext_data);
152*54fd6939SJiyong Park
153*54fd6939SJiyong Park /* The extension makes a copy of the data, so we can free this object */
154*54fd6939SJiyong Park ASN1_OCTET_STRING_free(ext_data);
155*54fd6939SJiyong Park
156*54fd6939SJiyong Park return ex;
157*54fd6939SJiyong Park }
158*54fd6939SJiyong Park
159*54fd6939SJiyong Park /*
160*54fd6939SJiyong Park * Creates a x509v3 extension containing a hash
161*54fd6939SJiyong Park *
162*54fd6939SJiyong Park * DigestInfo ::= SEQUENCE {
163*54fd6939SJiyong Park * digestAlgorithm AlgorithmIdentifier,
164*54fd6939SJiyong Park * digest OCTET STRING
165*54fd6939SJiyong Park * }
166*54fd6939SJiyong Park *
167*54fd6939SJiyong Park * AlgorithmIdentifier ::= SEQUENCE {
168*54fd6939SJiyong Park * algorithm OBJECT IDENTIFIER,
169*54fd6939SJiyong Park * parameters ANY DEFINED BY algorithm OPTIONAL
170*54fd6939SJiyong Park * }
171*54fd6939SJiyong Park *
172*54fd6939SJiyong Park * Parameters:
173*54fd6939SJiyong Park * nid: extension identifier
174*54fd6939SJiyong Park * crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
175*54fd6939SJiyong Park * md: hash algorithm
176*54fd6939SJiyong Park * buf: pointer to the buffer that contains the hash
177*54fd6939SJiyong Park * len: size of the hash in bytes
178*54fd6939SJiyong Park *
179*54fd6939SJiyong Park * Return: Extension address, NULL if error
180*54fd6939SJiyong Park */
ext_new_hash(int nid,int crit,const EVP_MD * md,unsigned char * buf,size_t len)181*54fd6939SJiyong Park X509_EXTENSION *ext_new_hash(int nid, int crit, const EVP_MD *md,
182*54fd6939SJiyong Park unsigned char *buf, size_t len)
183*54fd6939SJiyong Park {
184*54fd6939SJiyong Park X509_EXTENSION *ex;
185*54fd6939SJiyong Park HASH *hash;
186*54fd6939SJiyong Park ASN1_OBJECT *algorithm;
187*54fd6939SJiyong Park unsigned char *p = NULL;
188*54fd6939SJiyong Park int sz;
189*54fd6939SJiyong Park
190*54fd6939SJiyong Park /* HASH structure containing algorithm + hash */
191*54fd6939SJiyong Park hash = HASH_new();
192*54fd6939SJiyong Park if (hash == NULL) {
193*54fd6939SJiyong Park return NULL;
194*54fd6939SJiyong Park }
195*54fd6939SJiyong Park
196*54fd6939SJiyong Park /* OBJECT_IDENTIFIER with hash algorithm */
197*54fd6939SJiyong Park algorithm = OBJ_nid2obj(EVP_MD_type(md));
198*54fd6939SJiyong Park if (algorithm == NULL) {
199*54fd6939SJiyong Park HASH_free(hash);
200*54fd6939SJiyong Park return NULL;
201*54fd6939SJiyong Park }
202*54fd6939SJiyong Park
203*54fd6939SJiyong Park /* Create X509_ALGOR */
204*54fd6939SJiyong Park hash->hashAlgorithm->algorithm = algorithm;
205*54fd6939SJiyong Park hash->hashAlgorithm->parameter = ASN1_TYPE_new();
206*54fd6939SJiyong Park ASN1_TYPE_set(hash->hashAlgorithm->parameter, V_ASN1_NULL, NULL);
207*54fd6939SJiyong Park
208*54fd6939SJiyong Park /* OCTET_STRING with the actual hash */
209*54fd6939SJiyong Park ASN1_OCTET_STRING_set(hash->dataHash, buf, len);
210*54fd6939SJiyong Park
211*54fd6939SJiyong Park /* DER encoded HASH */
212*54fd6939SJiyong Park sz = i2d_HASH(hash, &p);
213*54fd6939SJiyong Park if ((sz <= 0) || (p == NULL)) {
214*54fd6939SJiyong Park HASH_free(hash);
215*54fd6939SJiyong Park return NULL;
216*54fd6939SJiyong Park }
217*54fd6939SJiyong Park
218*54fd6939SJiyong Park /* Create the extension */
219*54fd6939SJiyong Park ex = ext_new(nid, crit, p, sz);
220*54fd6939SJiyong Park
221*54fd6939SJiyong Park /* Clean up */
222*54fd6939SJiyong Park OPENSSL_free(p);
223*54fd6939SJiyong Park HASH_free(hash);
224*54fd6939SJiyong Park
225*54fd6939SJiyong Park return ex;
226*54fd6939SJiyong Park }
227*54fd6939SJiyong Park
228*54fd6939SJiyong Park /*
229*54fd6939SJiyong Park * Creates a x509v3 extension containing a nvcounter encapsulated in an ASN1
230*54fd6939SJiyong Park * Integer
231*54fd6939SJiyong Park *
232*54fd6939SJiyong Park * Parameters:
233*54fd6939SJiyong Park * pex: OpenSSL extension pointer (output parameter)
234*54fd6939SJiyong Park * nid: extension identifier
235*54fd6939SJiyong Park * crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
236*54fd6939SJiyong Park * value: nvcounter value
237*54fd6939SJiyong Park *
238*54fd6939SJiyong Park * Return: Extension address, NULL if error
239*54fd6939SJiyong Park */
ext_new_nvcounter(int nid,int crit,int value)240*54fd6939SJiyong Park X509_EXTENSION *ext_new_nvcounter(int nid, int crit, int value)
241*54fd6939SJiyong Park {
242*54fd6939SJiyong Park X509_EXTENSION *ex;
243*54fd6939SJiyong Park ASN1_INTEGER *counter;
244*54fd6939SJiyong Park unsigned char *p = NULL;
245*54fd6939SJiyong Park int sz;
246*54fd6939SJiyong Park
247*54fd6939SJiyong Park /* Encode counter */
248*54fd6939SJiyong Park counter = ASN1_INTEGER_new();
249*54fd6939SJiyong Park ASN1_INTEGER_set(counter, value);
250*54fd6939SJiyong Park sz = i2d_ASN1_INTEGER(counter, &p);
251*54fd6939SJiyong Park
252*54fd6939SJiyong Park /* Create the extension */
253*54fd6939SJiyong Park ex = ext_new(nid, crit, p, sz);
254*54fd6939SJiyong Park
255*54fd6939SJiyong Park /* Free objects */
256*54fd6939SJiyong Park OPENSSL_free(p);
257*54fd6939SJiyong Park ASN1_INTEGER_free(counter);
258*54fd6939SJiyong Park
259*54fd6939SJiyong Park return ex;
260*54fd6939SJiyong Park }
261*54fd6939SJiyong Park
262*54fd6939SJiyong Park /*
263*54fd6939SJiyong Park * Creates a x509v3 extension containing a public key in DER format:
264*54fd6939SJiyong Park *
265*54fd6939SJiyong Park * SubjectPublicKeyInfo ::= SEQUENCE {
266*54fd6939SJiyong Park * algorithm AlgorithmIdentifier,
267*54fd6939SJiyong Park * subjectPublicKey BIT STRING }
268*54fd6939SJiyong Park *
269*54fd6939SJiyong Park * Parameters:
270*54fd6939SJiyong Park * pex: OpenSSL extension pointer (output parameter)
271*54fd6939SJiyong Park * nid: extension identifier
272*54fd6939SJiyong Park * crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
273*54fd6939SJiyong Park * k: key
274*54fd6939SJiyong Park *
275*54fd6939SJiyong Park * Return: Extension address, NULL if error
276*54fd6939SJiyong Park */
ext_new_key(int nid,int crit,EVP_PKEY * k)277*54fd6939SJiyong Park X509_EXTENSION *ext_new_key(int nid, int crit, EVP_PKEY *k)
278*54fd6939SJiyong Park {
279*54fd6939SJiyong Park X509_EXTENSION *ex;
280*54fd6939SJiyong Park unsigned char *p;
281*54fd6939SJiyong Park int sz;
282*54fd6939SJiyong Park
283*54fd6939SJiyong Park /* Encode key */
284*54fd6939SJiyong Park BIO *mem = BIO_new(BIO_s_mem());
285*54fd6939SJiyong Park if (i2d_PUBKEY_bio(mem, k) <= 0) {
286*54fd6939SJiyong Park ERR_print_errors_fp(stderr);
287*54fd6939SJiyong Park return NULL;
288*54fd6939SJiyong Park }
289*54fd6939SJiyong Park p = (unsigned char *)OPENSSL_malloc(4096);
290*54fd6939SJiyong Park sz = BIO_read(mem, p, 4096);
291*54fd6939SJiyong Park
292*54fd6939SJiyong Park /* Create the extension */
293*54fd6939SJiyong Park ex = ext_new(nid, crit, p, sz);
294*54fd6939SJiyong Park
295*54fd6939SJiyong Park /* Clean up */
296*54fd6939SJiyong Park BIO_free(mem);
297*54fd6939SJiyong Park OPENSSL_free(p);
298*54fd6939SJiyong Park
299*54fd6939SJiyong Park return ex;
300*54fd6939SJiyong Park }
301*54fd6939SJiyong Park
ext_get_by_opt(const char * opt)302*54fd6939SJiyong Park ext_t *ext_get_by_opt(const char *opt)
303*54fd6939SJiyong Park {
304*54fd6939SJiyong Park ext_t *ext;
305*54fd6939SJiyong Park unsigned int i;
306*54fd6939SJiyong Park
307*54fd6939SJiyong Park /* Sequential search. This is not a performance concern since the number
308*54fd6939SJiyong Park * of extensions is bounded and the code runs on a host machine */
309*54fd6939SJiyong Park for (i = 0; i < num_extensions; i++) {
310*54fd6939SJiyong Park ext = &extensions[i];
311*54fd6939SJiyong Park if (ext->opt && !strcmp(ext->opt, opt)) {
312*54fd6939SJiyong Park return ext;
313*54fd6939SJiyong Park }
314*54fd6939SJiyong Park }
315*54fd6939SJiyong Park
316*54fd6939SJiyong Park return NULL;
317*54fd6939SJiyong Park }
318