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