xref: /rk3399_ARM-atf/tools/cert_create/src/ext.c (revision c3da66b1bb3b0769bfb8a8fcdefed1b49cf373a4)
16f971622SJuan Castillo /*
26f971622SJuan Castillo  * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
36f971622SJuan Castillo  *
46f971622SJuan Castillo  * Redistribution and use in source and binary forms, with or without
56f971622SJuan Castillo  * modification, are permitted provided that the following conditions are met:
66f971622SJuan Castillo  *
76f971622SJuan Castillo  * Redistributions of source code must retain the above copyright notice, this
86f971622SJuan Castillo  * list of conditions and the following disclaimer.
96f971622SJuan Castillo  *
106f971622SJuan Castillo  * Redistributions in binary form must reproduce the above copyright notice,
116f971622SJuan Castillo  * this list of conditions and the following disclaimer in the documentation
126f971622SJuan Castillo  * and/or other materials provided with the distribution.
136f971622SJuan Castillo  *
146f971622SJuan Castillo  * Neither the name of ARM nor the names of its contributors may be used
156f971622SJuan Castillo  * to endorse or promote products derived from this software without specific
166f971622SJuan Castillo  * prior written permission.
176f971622SJuan Castillo  *
186f971622SJuan Castillo  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
196f971622SJuan Castillo  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
206f971622SJuan Castillo  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
216f971622SJuan Castillo  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
226f971622SJuan Castillo  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
236f971622SJuan Castillo  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
246f971622SJuan Castillo  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
256f971622SJuan Castillo  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
266f971622SJuan Castillo  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
276f971622SJuan Castillo  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
286f971622SJuan Castillo  * POSSIBILITY OF SUCH DAMAGE.
296f971622SJuan Castillo  */
306f971622SJuan Castillo 
316f971622SJuan Castillo #include <stddef.h>
326f971622SJuan Castillo #include <stdio.h>
336f971622SJuan Castillo #include <string.h>
34*c3da66b1SJuan Castillo #include <openssl/asn1.h>
35*c3da66b1SJuan Castillo #include <openssl/asn1t.h>
366f971622SJuan Castillo #include <openssl/err.h>
376f971622SJuan Castillo #include <openssl/x509v3.h>
386f971622SJuan Castillo #include "ext.h"
396f971622SJuan Castillo 
406f971622SJuan Castillo DECLARE_ASN1_ITEM(ASN1_INTEGER)
41*c3da66b1SJuan Castillo DECLARE_ASN1_ITEM(X509_ALGOR)
426f971622SJuan Castillo DECLARE_ASN1_ITEM(ASN1_OCTET_STRING)
436f971622SJuan Castillo 
44*c3da66b1SJuan Castillo typedef struct {
45*c3da66b1SJuan Castillo 	X509_ALGOR *hashAlgorithm;
46*c3da66b1SJuan Castillo 	ASN1_OCTET_STRING *dataHash;
47*c3da66b1SJuan Castillo } HASH;
48*c3da66b1SJuan Castillo 
49*c3da66b1SJuan Castillo ASN1_SEQUENCE(HASH) = {
50*c3da66b1SJuan Castillo 	ASN1_SIMPLE(HASH, hashAlgorithm, X509_ALGOR),
51*c3da66b1SJuan Castillo 	ASN1_SIMPLE(HASH, dataHash, ASN1_OCTET_STRING),
52*c3da66b1SJuan Castillo } ASN1_SEQUENCE_END(HASH)
53*c3da66b1SJuan Castillo 
54*c3da66b1SJuan Castillo DECLARE_ASN1_FUNCTIONS(HASH)
55*c3da66b1SJuan Castillo IMPLEMENT_ASN1_FUNCTIONS(HASH)
56*c3da66b1SJuan Castillo 
576f971622SJuan Castillo /*
586f971622SJuan Castillo  * This function adds the TBB extensions to the internal extension list
596f971622SJuan Castillo  * maintained by OpenSSL so they can be used later.
606f971622SJuan Castillo  *
616f971622SJuan Castillo  * It also initializes the methods to print the contents of the extension. If an
626f971622SJuan Castillo  * alias is specified in the TBB extension, we reuse the methods of the alias.
636f971622SJuan Castillo  * Otherwise, only methods for V_ASN1_INTEGER and V_ASN1_OCTET_STRING are
646f971622SJuan Castillo  * provided. Any other type will be printed as a raw ascii string.
656f971622SJuan Castillo  *
666f971622SJuan Castillo  * Return: 0 = success, Otherwise: error
676f971622SJuan Castillo  */
686f971622SJuan Castillo int ext_init(ext_t *tbb_ext)
696f971622SJuan Castillo {
706f971622SJuan Castillo 	ext_t *ext;
716f971622SJuan Castillo 	X509V3_EXT_METHOD *m;
726f971622SJuan Castillo 	int i = 0, nid, ret;
736f971622SJuan Castillo 
746f971622SJuan Castillo 	while ((ext = &tbb_ext[i++]) && ext->oid) {
756f971622SJuan Castillo 		nid = OBJ_create(ext->oid, ext->sn, ext->ln);
766f971622SJuan Castillo 		if (ext->alias) {
776f971622SJuan Castillo 			X509V3_EXT_add_alias(nid, ext->alias);
786f971622SJuan Castillo 		} else {
796f971622SJuan Castillo 			m = &ext->method;
806f971622SJuan Castillo 			memset(m, 0x0, sizeof(X509V3_EXT_METHOD));
816f971622SJuan Castillo 			switch (ext->type) {
826f971622SJuan Castillo 			case V_ASN1_INTEGER:
836f971622SJuan Castillo 				m->it = ASN1_ITEM_ref(ASN1_INTEGER);
846f971622SJuan Castillo 				m->i2s = (X509V3_EXT_I2S)i2s_ASN1_INTEGER;
856f971622SJuan Castillo 				m->s2i = (X509V3_EXT_S2I)s2i_ASN1_INTEGER;
866f971622SJuan Castillo 				break;
876f971622SJuan Castillo 			case V_ASN1_OCTET_STRING:
886f971622SJuan Castillo 				m->it = ASN1_ITEM_ref(ASN1_OCTET_STRING);
896f971622SJuan Castillo 				m->i2s = (X509V3_EXT_I2S)i2s_ASN1_OCTET_STRING;
906f971622SJuan Castillo 				m->s2i = (X509V3_EXT_S2I)s2i_ASN1_OCTET_STRING;
916f971622SJuan Castillo 				break;
926f971622SJuan Castillo 			default:
936f971622SJuan Castillo 				continue;
946f971622SJuan Castillo 			}
956f971622SJuan Castillo 			m->ext_nid = nid;
966f971622SJuan Castillo 			ret = X509V3_EXT_add(m);
976f971622SJuan Castillo 			if (!ret) {
986f971622SJuan Castillo 				ERR_print_errors_fp(stdout);
996f971622SJuan Castillo 				return 1;
1006f971622SJuan Castillo 			}
1016f971622SJuan Castillo 		}
1026f971622SJuan Castillo 	}
1036f971622SJuan Castillo 	return 0;
1046f971622SJuan Castillo }
1056f971622SJuan Castillo 
1066f971622SJuan Castillo /*
1076f971622SJuan Castillo  * Create a new extension
1086f971622SJuan Castillo  *
1096f971622SJuan Castillo  * Extension  ::=  SEQUENCE  {
1106f971622SJuan Castillo  *      id          OBJECT IDENTIFIER,
1116f971622SJuan Castillo  *      critical    BOOLEAN DEFAULT FALSE,
1126f971622SJuan Castillo  *      value       OCTET STRING  }
1136f971622SJuan Castillo  *
1146f971622SJuan Castillo  * Parameters:
1156f971622SJuan Castillo  *   pex: OpenSSL extension pointer (output parameter)
1166f971622SJuan Castillo  *   nid: extension identifier
1176f971622SJuan Castillo  *   crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
1186f971622SJuan Castillo  *   data: extension data. This data will be encapsulated in an Octet String
1196f971622SJuan Castillo  *
1206f971622SJuan Castillo  * Return: Extension address, NULL if error
1216f971622SJuan Castillo  */
1226f971622SJuan Castillo static
1236f971622SJuan Castillo X509_EXTENSION *ext_new(int nid, int crit, unsigned char *data, int len)
1246f971622SJuan Castillo {
1256f971622SJuan Castillo 	X509_EXTENSION *ex;
1266f971622SJuan Castillo 	ASN1_OCTET_STRING *ext_data;
1276f971622SJuan Castillo 
1286f971622SJuan Castillo 	/* Octet string containing the extension data */
1296f971622SJuan Castillo 	ext_data = ASN1_OCTET_STRING_new();
1306f971622SJuan Castillo 	ASN1_OCTET_STRING_set(ext_data, data, len);
1316f971622SJuan Castillo 
1326f971622SJuan Castillo 	/* Create the extension */
1336f971622SJuan Castillo 	ex = X509_EXTENSION_create_by_NID(NULL, nid, crit, ext_data);
1346f971622SJuan Castillo 
1356f971622SJuan Castillo 	/* The extension makes a copy of the data, so we can free this object */
1366f971622SJuan Castillo 	ASN1_OCTET_STRING_free(ext_data);
1376f971622SJuan Castillo 
1386f971622SJuan Castillo 	return ex;
1396f971622SJuan Castillo }
1406f971622SJuan Castillo 
1416f971622SJuan Castillo /*
142*c3da66b1SJuan Castillo  * Creates a x509v3 extension containing a hash
143*c3da66b1SJuan Castillo  *
144*c3da66b1SJuan Castillo  * DigestInfo ::= SEQUENCE {
145*c3da66b1SJuan Castillo  *     digestAlgorithm  AlgorithmIdentifier,
146*c3da66b1SJuan Castillo  *     digest           OCTET STRING
147*c3da66b1SJuan Castillo  * }
148*c3da66b1SJuan Castillo  *
149*c3da66b1SJuan Castillo  * AlgorithmIdentifier ::=  SEQUENCE  {
150*c3da66b1SJuan Castillo  *     algorithm        OBJECT IDENTIFIER,
151*c3da66b1SJuan Castillo  *     parameters       ANY DEFINED BY algorithm OPTIONAL
152*c3da66b1SJuan Castillo  * }
1536f971622SJuan Castillo  *
1546f971622SJuan Castillo  * Parameters:
1556f971622SJuan Castillo  *   nid: extension identifier
1566f971622SJuan Castillo  *   crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
157*c3da66b1SJuan Castillo  *   md: hash algorithm
1586f971622SJuan Castillo  *   buf: pointer to the buffer that contains the hash
1596f971622SJuan Castillo  *   len: size of the hash in bytes
1606f971622SJuan Castillo  *
1616f971622SJuan Castillo  * Return: Extension address, NULL if error
1626f971622SJuan Castillo  */
163*c3da66b1SJuan Castillo X509_EXTENSION *ext_new_hash(int nid, int crit, const EVP_MD *md,
164*c3da66b1SJuan Castillo 		unsigned char *buf, size_t len)
1656f971622SJuan Castillo {
1666f971622SJuan Castillo 	X509_EXTENSION *ex = NULL;
167*c3da66b1SJuan Castillo 	ASN1_OCTET_STRING *octet = NULL;
168*c3da66b1SJuan Castillo 	HASH *hash = NULL;
169*c3da66b1SJuan Castillo 	ASN1_OBJECT *algorithm = NULL;
170*c3da66b1SJuan Castillo 	X509_ALGOR *x509_algor = NULL;
1716f971622SJuan Castillo 	unsigned char *p = NULL;
1726f971622SJuan Castillo 	int sz = -1;
1736f971622SJuan Castillo 
174*c3da66b1SJuan Castillo 	/* OBJECT_IDENTIFIER with hash algorithm */
175*c3da66b1SJuan Castillo 	algorithm = OBJ_nid2obj(md->type);
176*c3da66b1SJuan Castillo 	if (algorithm == NULL) {
177*c3da66b1SJuan Castillo 		return NULL;
178*c3da66b1SJuan Castillo 	}
179*c3da66b1SJuan Castillo 
180*c3da66b1SJuan Castillo 	/* Create X509_ALGOR */
181*c3da66b1SJuan Castillo 	x509_algor = X509_ALGOR_new();
182*c3da66b1SJuan Castillo 	if (x509_algor == NULL) {
183*c3da66b1SJuan Castillo 		return NULL;
184*c3da66b1SJuan Castillo 	}
185*c3da66b1SJuan Castillo 	x509_algor->algorithm = algorithm;
186*c3da66b1SJuan Castillo 	x509_algor->parameter = ASN1_TYPE_new();
187*c3da66b1SJuan Castillo 	ASN1_TYPE_set(x509_algor->parameter, V_ASN1_NULL, NULL);
188*c3da66b1SJuan Castillo 
189*c3da66b1SJuan Castillo 	/* OCTET_STRING with the actual hash */
190*c3da66b1SJuan Castillo 	octet = ASN1_OCTET_STRING_new();
191*c3da66b1SJuan Castillo 	if (octet == NULL) {
192*c3da66b1SJuan Castillo 		X509_ALGOR_free(x509_algor);
193*c3da66b1SJuan Castillo 		return NULL;
194*c3da66b1SJuan Castillo 	}
195*c3da66b1SJuan Castillo 	ASN1_OCTET_STRING_set(octet, buf, len);
196*c3da66b1SJuan Castillo 
197*c3da66b1SJuan Castillo 	/* HASH structure containing algorithm + hash */
198*c3da66b1SJuan Castillo 	hash = HASH_new();
199*c3da66b1SJuan Castillo 	if (hash == NULL) {
200*c3da66b1SJuan Castillo 		ASN1_OCTET_STRING_free(octet);
201*c3da66b1SJuan Castillo 		X509_ALGOR_free(x509_algor);
202*c3da66b1SJuan Castillo 		return NULL;
203*c3da66b1SJuan Castillo 	}
204*c3da66b1SJuan Castillo 	hash->hashAlgorithm = x509_algor;
205*c3da66b1SJuan Castillo 	hash->dataHash = octet;
206*c3da66b1SJuan Castillo 
207*c3da66b1SJuan Castillo 	/* DER encoded HASH */
208*c3da66b1SJuan Castillo 	sz = i2d_HASH(hash, &p);
209*c3da66b1SJuan Castillo 	if ((sz <= 0) || (p == NULL)) {
210*c3da66b1SJuan Castillo 		HASH_free(hash);
211*c3da66b1SJuan Castillo 		X509_ALGOR_free(x509_algor);
212*c3da66b1SJuan Castillo 		return NULL;
213*c3da66b1SJuan Castillo 	}
2146f971622SJuan Castillo 
2156f971622SJuan Castillo 	/* Create the extension */
2166f971622SJuan Castillo 	ex = ext_new(nid, crit, p, sz);
2176f971622SJuan Castillo 
2186f971622SJuan Castillo 	/* Clean up */
2196f971622SJuan Castillo 	OPENSSL_free(p);
220*c3da66b1SJuan Castillo 	HASH_free(hash);
2216f971622SJuan Castillo 
2226f971622SJuan Castillo 	return ex;
2236f971622SJuan Castillo }
2246f971622SJuan Castillo 
2256f971622SJuan Castillo /*
2266f971622SJuan Castillo  * Creates a x509v3 extension containing a nvcounter encapsulated in an ASN1
2276f971622SJuan Castillo  * Integer
2286f971622SJuan Castillo  *
2296f971622SJuan Castillo  * Parameters:
2306f971622SJuan Castillo  *   pex: OpenSSL extension pointer (output parameter)
2316f971622SJuan Castillo  *   nid: extension identifier
2326f971622SJuan Castillo  *   crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
2336f971622SJuan Castillo  *   value: nvcounter value
2346f971622SJuan Castillo  *
2356f971622SJuan Castillo  * Return: Extension address, NULL if error
2366f971622SJuan Castillo  */
2376f971622SJuan Castillo X509_EXTENSION *ext_new_nvcounter(int nid, int crit, int value)
2386f971622SJuan Castillo {
2396f971622SJuan Castillo 	X509_EXTENSION *ex = NULL;
2406f971622SJuan Castillo 	ASN1_INTEGER *counter = NULL;
2416f971622SJuan Castillo 	unsigned char *p = NULL;
2426f971622SJuan Castillo 	int sz = -1;
2436f971622SJuan Castillo 
2446f971622SJuan Castillo 	/* Encode counter */
2456f971622SJuan Castillo 	counter = ASN1_INTEGER_new();
2466f971622SJuan Castillo 	ASN1_INTEGER_set(counter, value);
2476f971622SJuan Castillo 	sz = i2d_ASN1_INTEGER(counter, NULL);
2486f971622SJuan Castillo 	i2d_ASN1_INTEGER(counter, &p);
2496f971622SJuan Castillo 
2506f971622SJuan Castillo 	/* Create the extension */
2516f971622SJuan Castillo 	ex = ext_new(nid, crit, p, sz);
2526f971622SJuan Castillo 
2536f971622SJuan Castillo 	/* Free objects */
2546f971622SJuan Castillo 	OPENSSL_free(p);
2556f971622SJuan Castillo 	ASN1_INTEGER_free(counter);
2566f971622SJuan Castillo 
2576f971622SJuan Castillo 	return ex;
2586f971622SJuan Castillo }
2596f971622SJuan Castillo 
2606f971622SJuan Castillo /*
2616f971622SJuan Castillo  * Creates a x509v3 extension containing a public key in DER format:
2626f971622SJuan Castillo  *
2636f971622SJuan Castillo  *  SubjectPublicKeyInfo  ::=  SEQUENCE  {
2646f971622SJuan Castillo  *       algorithm            AlgorithmIdentifier,
2656f971622SJuan Castillo  *       subjectPublicKey     BIT STRING }
2666f971622SJuan Castillo  *
2676f971622SJuan Castillo  * Parameters:
2686f971622SJuan Castillo  *   pex: OpenSSL extension pointer (output parameter)
2696f971622SJuan Castillo  *   nid: extension identifier
2706f971622SJuan Castillo  *   crit: extension critical (EXT_NON_CRIT, EXT_CRIT)
2716f971622SJuan Castillo  *   k: key
2726f971622SJuan Castillo  *
2736f971622SJuan Castillo  * Return: Extension address, NULL if error
2746f971622SJuan Castillo  */
2756f971622SJuan Castillo X509_EXTENSION *ext_new_key(int nid, int crit, EVP_PKEY *k)
2766f971622SJuan Castillo {
2776f971622SJuan Castillo 	X509_EXTENSION *ex = NULL;
2786f971622SJuan Castillo 	unsigned char *p = NULL;
2796f971622SJuan Castillo 	int sz = -1;
2806f971622SJuan Castillo 
2816f971622SJuan Castillo 	/* Encode key */
2826f971622SJuan Castillo 	BIO *mem = BIO_new(BIO_s_mem());
2836f971622SJuan Castillo 	if (i2d_PUBKEY_bio(mem, k) <= 0) {
2846f971622SJuan Castillo 		ERR_print_errors_fp(stderr);
2856f971622SJuan Castillo 		return NULL;
2866f971622SJuan Castillo 	}
2876f971622SJuan Castillo 	p = (unsigned char *)OPENSSL_malloc(4096);
2886f971622SJuan Castillo 	sz = BIO_read(mem, p, 4096);
2896f971622SJuan Castillo 
2906f971622SJuan Castillo 	/* Create the extension */
2916f971622SJuan Castillo 	ex = ext_new(nid, crit, p, sz);
2926f971622SJuan Castillo 
2936f971622SJuan Castillo 	/* Clean up */
2946f971622SJuan Castillo 	OPENSSL_free(p);
2956f971622SJuan Castillo 
2966f971622SJuan Castillo 	return ex;
2976f971622SJuan Castillo }
298