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/asn1.h> 35 #include <openssl/asn1t.h> 36 #include <openssl/err.h> 37 #include <openssl/x509v3.h> 38 #include "ext.h" 39 40 DECLARE_ASN1_ITEM(ASN1_INTEGER) 41 DECLARE_ASN1_ITEM(X509_ALGOR) 42 DECLARE_ASN1_ITEM(ASN1_OCTET_STRING) 43 44 typedef struct { 45 X509_ALGOR *hashAlgorithm; 46 ASN1_OCTET_STRING *dataHash; 47 } HASH; 48 49 ASN1_SEQUENCE(HASH) = { 50 ASN1_SIMPLE(HASH, hashAlgorithm, X509_ALGOR), 51 ASN1_SIMPLE(HASH, dataHash, ASN1_OCTET_STRING), 52 } ASN1_SEQUENCE_END(HASH) 53 54 DECLARE_ASN1_FUNCTIONS(HASH) 55 IMPLEMENT_ASN1_FUNCTIONS(HASH) 56 57 /* 58 * This function adds the TBB extensions to the internal extension list 59 * maintained by OpenSSL so they can be used later. 60 * 61 * It also initializes the methods to print the contents of the extension. If an 62 * alias is specified in the TBB extension, we reuse the methods of the alias. 63 * Otherwise, only methods for V_ASN1_INTEGER and V_ASN1_OCTET_STRING are 64 * provided. Any other type will be printed as a raw ascii string. 65 * 66 * Return: 0 = success, Otherwise: error 67 */ 68 int ext_register(ext_t *exts) 69 { 70 ext_t *ext; 71 X509V3_EXT_METHOD *m; 72 int i = 0, nid, ret; 73 74 while ((ext = &exts[i++]) && ext->oid) { 75 nid = OBJ_create(ext->oid, ext->sn, ext->ln); 76 if (ext->alias) { 77 X509V3_EXT_add_alias(nid, ext->alias); 78 } else { 79 m = &ext->method; 80 memset(m, 0x0, sizeof(X509V3_EXT_METHOD)); 81 switch (ext->asn1_type) { 82 case V_ASN1_INTEGER: 83 m->it = ASN1_ITEM_ref(ASN1_INTEGER); 84 m->i2s = (X509V3_EXT_I2S)i2s_ASN1_INTEGER; 85 m->s2i = (X509V3_EXT_S2I)s2i_ASN1_INTEGER; 86 break; 87 case V_ASN1_OCTET_STRING: 88 m->it = ASN1_ITEM_ref(ASN1_OCTET_STRING); 89 m->i2s = (X509V3_EXT_I2S)i2s_ASN1_OCTET_STRING; 90 m->s2i = (X509V3_EXT_S2I)s2i_ASN1_OCTET_STRING; 91 break; 92 default: 93 continue; 94 } 95 m->ext_nid = nid; 96 ret = X509V3_EXT_add(m); 97 if (!ret) { 98 ERR_print_errors_fp(stdout); 99 return 1; 100 } 101 } 102 } 103 return 0; 104 } 105 106 /* 107 * Create a new extension 108 * 109 * Extension ::= SEQUENCE { 110 * id OBJECT IDENTIFIER, 111 * critical BOOLEAN DEFAULT FALSE, 112 * value OCTET STRING } 113 * 114 * Parameters: 115 * pex: OpenSSL extension pointer (output parameter) 116 * nid: extension identifier 117 * crit: extension critical (EXT_NON_CRIT, EXT_CRIT) 118 * data: extension data. This data will be encapsulated in an Octet String 119 * 120 * Return: Extension address, NULL if error 121 */ 122 static 123 X509_EXTENSION *ext_new(int nid, int crit, unsigned char *data, int len) 124 { 125 X509_EXTENSION *ex; 126 ASN1_OCTET_STRING *ext_data; 127 128 /* Octet string containing the extension data */ 129 ext_data = ASN1_OCTET_STRING_new(); 130 ASN1_OCTET_STRING_set(ext_data, data, len); 131 132 /* Create the extension */ 133 ex = X509_EXTENSION_create_by_NID(NULL, nid, crit, ext_data); 134 135 /* The extension makes a copy of the data, so we can free this object */ 136 ASN1_OCTET_STRING_free(ext_data); 137 138 return ex; 139 } 140 141 /* 142 * Creates a x509v3 extension containing a hash 143 * 144 * DigestInfo ::= SEQUENCE { 145 * digestAlgorithm AlgorithmIdentifier, 146 * digest OCTET STRING 147 * } 148 * 149 * AlgorithmIdentifier ::= SEQUENCE { 150 * algorithm OBJECT IDENTIFIER, 151 * parameters ANY DEFINED BY algorithm OPTIONAL 152 * } 153 * 154 * Parameters: 155 * nid: extension identifier 156 * crit: extension critical (EXT_NON_CRIT, EXT_CRIT) 157 * md: hash algorithm 158 * buf: pointer to the buffer that contains the hash 159 * len: size of the hash in bytes 160 * 161 * Return: Extension address, NULL if error 162 */ 163 X509_EXTENSION *ext_new_hash(int nid, int crit, const EVP_MD *md, 164 unsigned char *buf, size_t len) 165 { 166 X509_EXTENSION *ex = NULL; 167 ASN1_OCTET_STRING *octet = NULL; 168 HASH *hash = NULL; 169 ASN1_OBJECT *algorithm = NULL; 170 X509_ALGOR *x509_algor = NULL; 171 unsigned char *p = NULL; 172 int sz = -1; 173 174 /* OBJECT_IDENTIFIER with hash algorithm */ 175 algorithm = OBJ_nid2obj(md->type); 176 if (algorithm == NULL) { 177 return NULL; 178 } 179 180 /* Create X509_ALGOR */ 181 x509_algor = X509_ALGOR_new(); 182 if (x509_algor == NULL) { 183 return NULL; 184 } 185 x509_algor->algorithm = algorithm; 186 x509_algor->parameter = ASN1_TYPE_new(); 187 ASN1_TYPE_set(x509_algor->parameter, V_ASN1_NULL, NULL); 188 189 /* OCTET_STRING with the actual hash */ 190 octet = ASN1_OCTET_STRING_new(); 191 if (octet == NULL) { 192 X509_ALGOR_free(x509_algor); 193 return NULL; 194 } 195 ASN1_OCTET_STRING_set(octet, buf, len); 196 197 /* HASH structure containing algorithm + hash */ 198 hash = HASH_new(); 199 if (hash == NULL) { 200 ASN1_OCTET_STRING_free(octet); 201 X509_ALGOR_free(x509_algor); 202 return NULL; 203 } 204 hash->hashAlgorithm = x509_algor; 205 hash->dataHash = octet; 206 207 /* DER encoded HASH */ 208 sz = i2d_HASH(hash, &p); 209 if ((sz <= 0) || (p == NULL)) { 210 HASH_free(hash); 211 X509_ALGOR_free(x509_algor); 212 return NULL; 213 } 214 215 /* Create the extension */ 216 ex = ext_new(nid, crit, p, sz); 217 218 /* Clean up */ 219 OPENSSL_free(p); 220 HASH_free(hash); 221 222 return ex; 223 } 224 225 /* 226 * Creates a x509v3 extension containing a nvcounter encapsulated in an ASN1 227 * Integer 228 * 229 * Parameters: 230 * pex: OpenSSL extension pointer (output parameter) 231 * nid: extension identifier 232 * crit: extension critical (EXT_NON_CRIT, EXT_CRIT) 233 * value: nvcounter value 234 * 235 * Return: Extension address, NULL if error 236 */ 237 X509_EXTENSION *ext_new_nvcounter(int nid, int crit, int value) 238 { 239 X509_EXTENSION *ex = NULL; 240 ASN1_INTEGER *counter = NULL; 241 unsigned char *p = NULL; 242 int sz = -1; 243 244 /* Encode counter */ 245 counter = ASN1_INTEGER_new(); 246 ASN1_INTEGER_set(counter, value); 247 sz = i2d_ASN1_INTEGER(counter, NULL); 248 i2d_ASN1_INTEGER(counter, &p); 249 250 /* Create the extension */ 251 ex = ext_new(nid, crit, p, sz); 252 253 /* Free objects */ 254 OPENSSL_free(p); 255 ASN1_INTEGER_free(counter); 256 257 return ex; 258 } 259 260 /* 261 * Creates a x509v3 extension containing a public key in DER format: 262 * 263 * SubjectPublicKeyInfo ::= SEQUENCE { 264 * algorithm AlgorithmIdentifier, 265 * subjectPublicKey BIT STRING } 266 * 267 * Parameters: 268 * pex: OpenSSL extension pointer (output parameter) 269 * nid: extension identifier 270 * crit: extension critical (EXT_NON_CRIT, EXT_CRIT) 271 * k: key 272 * 273 * Return: Extension address, NULL if error 274 */ 275 X509_EXTENSION *ext_new_key(int nid, int crit, EVP_PKEY *k) 276 { 277 X509_EXTENSION *ex = NULL; 278 unsigned char *p = NULL; 279 int sz = -1; 280 281 /* Encode key */ 282 BIO *mem = BIO_new(BIO_s_mem()); 283 if (i2d_PUBKEY_bio(mem, k) <= 0) { 284 ERR_print_errors_fp(stderr); 285 return NULL; 286 } 287 p = (unsigned char *)OPENSSL_malloc(4096); 288 sz = BIO_read(mem, p, 4096); 289 290 /* Create the extension */ 291 ex = ext_new(nid, crit, p, sz); 292 293 /* Clean up */ 294 OPENSSL_free(p); 295 296 return ex; 297 } 298