xref: /aosp_15_r20/external/arm-trusted-firmware/tools/cert_create/src/ext.c (revision 54fd6939e177f8ff529b10183254802c76df6d08)
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