1 /* 2 * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * Redistributions of source code must retain the above copyright notice, this 8 * list of conditions and the following disclaimer. 9 * 10 * Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * Neither the name of ARM nor the names of its contributors may be used 15 * to endorse or promote products derived from this software without specific 16 * prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <stddef.h> 32 #include <stdio.h> 33 #include <string.h> 34 #include <openssl/err.h> 35 #include <openssl/x509v3.h> 36 #include "ext.h" 37 38 DECLARE_ASN1_ITEM(ASN1_INTEGER) 39 DECLARE_ASN1_ITEM(ASN1_OCTET_STRING) 40 41 /* 42 * This function adds the TBB extensions to the internal extension list 43 * maintained by OpenSSL so they can be used later. 44 * 45 * It also initializes the methods to print the contents of the extension. If an 46 * alias is specified in the TBB extension, we reuse the methods of the alias. 47 * Otherwise, only methods for V_ASN1_INTEGER and V_ASN1_OCTET_STRING are 48 * provided. Any other type will be printed as a raw ascii string. 49 * 50 * Return: 0 = success, Otherwise: error 51 */ 52 int ext_init(ext_t *tbb_ext) 53 { 54 ext_t *ext; 55 X509V3_EXT_METHOD *m; 56 int i = 0, nid, ret; 57 58 while ((ext = &tbb_ext[i++]) && ext->oid) { 59 nid = OBJ_create(ext->oid, ext->sn, ext->ln); 60 if (ext->alias) { 61 X509V3_EXT_add_alias(nid, ext->alias); 62 } else { 63 m = &ext->method; 64 memset(m, 0x0, sizeof(X509V3_EXT_METHOD)); 65 switch (ext->type) { 66 case V_ASN1_INTEGER: 67 m->it = ASN1_ITEM_ref(ASN1_INTEGER); 68 m->i2s = (X509V3_EXT_I2S)i2s_ASN1_INTEGER; 69 m->s2i = (X509V3_EXT_S2I)s2i_ASN1_INTEGER; 70 break; 71 case V_ASN1_OCTET_STRING: 72 m->it = ASN1_ITEM_ref(ASN1_OCTET_STRING); 73 m->i2s = (X509V3_EXT_I2S)i2s_ASN1_OCTET_STRING; 74 m->s2i = (X509V3_EXT_S2I)s2i_ASN1_OCTET_STRING; 75 break; 76 default: 77 continue; 78 } 79 m->ext_nid = nid; 80 ret = X509V3_EXT_add(m); 81 if (!ret) { 82 ERR_print_errors_fp(stdout); 83 return 1; 84 } 85 } 86 } 87 return 0; 88 } 89 90 /* 91 * Create a new extension 92 * 93 * Extension ::= SEQUENCE { 94 * id OBJECT IDENTIFIER, 95 * critical BOOLEAN DEFAULT FALSE, 96 * value OCTET STRING } 97 * 98 * Parameters: 99 * pex: OpenSSL extension pointer (output parameter) 100 * nid: extension identifier 101 * crit: extension critical (EXT_NON_CRIT, EXT_CRIT) 102 * data: extension data. This data will be encapsulated in an Octet String 103 * 104 * Return: Extension address, NULL if error 105 */ 106 static 107 X509_EXTENSION *ext_new(int nid, int crit, unsigned char *data, int len) 108 { 109 X509_EXTENSION *ex; 110 ASN1_OCTET_STRING *ext_data; 111 112 /* Octet string containing the extension data */ 113 ext_data = ASN1_OCTET_STRING_new(); 114 ASN1_OCTET_STRING_set(ext_data, data, len); 115 116 /* Create the extension */ 117 ex = X509_EXTENSION_create_by_NID(NULL, nid, crit, ext_data); 118 119 /* The extension makes a copy of the data, so we can free this object */ 120 ASN1_OCTET_STRING_free(ext_data); 121 122 return ex; 123 } 124 125 /* 126 * Creates a x509v3 extension containing a hash encapsulated in an ASN1 Octet 127 * String 128 * 129 * Parameters: 130 * pex: OpenSSL extension pointer (output parameter) 131 * nid: extension identifier 132 * crit: extension critical (EXT_NON_CRIT, EXT_CRIT) 133 * buf: pointer to the buffer that contains the hash 134 * len: size of the hash in bytes 135 * 136 * Return: Extension address, NULL if error 137 */ 138 X509_EXTENSION *ext_new_hash(int nid, int crit, unsigned char *buf, size_t len) 139 { 140 X509_EXTENSION *ex = NULL; 141 ASN1_OCTET_STRING *hash = NULL; 142 unsigned char *p = NULL; 143 int sz = -1; 144 145 /* Encode Hash */ 146 hash = ASN1_OCTET_STRING_new(); 147 ASN1_OCTET_STRING_set(hash, buf, len); 148 sz = i2d_ASN1_OCTET_STRING(hash, NULL); 149 i2d_ASN1_OCTET_STRING(hash, &p); 150 151 /* Create the extension */ 152 ex = ext_new(nid, crit, p, sz); 153 154 /* Clean up */ 155 OPENSSL_free(p); 156 ASN1_OCTET_STRING_free(hash); 157 158 return ex; 159 } 160 161 /* 162 * Creates a x509v3 extension containing a nvcounter encapsulated in an ASN1 163 * Integer 164 * 165 * Parameters: 166 * pex: OpenSSL extension pointer (output parameter) 167 * nid: extension identifier 168 * crit: extension critical (EXT_NON_CRIT, EXT_CRIT) 169 * value: nvcounter value 170 * 171 * Return: Extension address, NULL if error 172 */ 173 X509_EXTENSION *ext_new_nvcounter(int nid, int crit, int value) 174 { 175 X509_EXTENSION *ex = NULL; 176 ASN1_INTEGER *counter = NULL; 177 unsigned char *p = NULL; 178 int sz = -1; 179 180 /* Encode counter */ 181 counter = ASN1_INTEGER_new(); 182 ASN1_INTEGER_set(counter, value); 183 sz = i2d_ASN1_INTEGER(counter, NULL); 184 i2d_ASN1_INTEGER(counter, &p); 185 186 /* Create the extension */ 187 ex = ext_new(nid, crit, p, sz); 188 189 /* Free objects */ 190 OPENSSL_free(p); 191 ASN1_INTEGER_free(counter); 192 193 return ex; 194 } 195 196 /* 197 * Creates a x509v3 extension containing a public key in DER format: 198 * 199 * SubjectPublicKeyInfo ::= SEQUENCE { 200 * algorithm AlgorithmIdentifier, 201 * subjectPublicKey BIT STRING } 202 * 203 * Parameters: 204 * pex: OpenSSL extension pointer (output parameter) 205 * nid: extension identifier 206 * crit: extension critical (EXT_NON_CRIT, EXT_CRIT) 207 * k: key 208 * 209 * Return: Extension address, NULL if error 210 */ 211 X509_EXTENSION *ext_new_key(int nid, int crit, EVP_PKEY *k) 212 { 213 X509_EXTENSION *ex = NULL; 214 unsigned char *p = NULL; 215 int sz = -1; 216 217 /* Encode key */ 218 BIO *mem = BIO_new(BIO_s_mem()); 219 if (i2d_PUBKEY_bio(mem, k) <= 0) { 220 ERR_print_errors_fp(stderr); 221 return NULL; 222 } 223 p = (unsigned char *)OPENSSL_malloc(4096); 224 sz = BIO_read(mem, p, 4096); 225 226 /* Create the extension */ 227 ex = ext_new(nid, crit, p, sz); 228 229 /* Clean up */ 230 OPENSSL_free(p); 231 232 return ex; 233 } 234