1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci/* X509 v3 extension utilities */ 11e1051a39Sopenharmony_ci 12e1051a39Sopenharmony_ci#include <stdio.h> 13e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 14e1051a39Sopenharmony_ci#include <openssl/conf.h> 15e1051a39Sopenharmony_ci#include <openssl/x509v3.h> 16e1051a39Sopenharmony_ci 17e1051a39Sopenharmony_ci/* Extension printing routines */ 18e1051a39Sopenharmony_ci 19e1051a39Sopenharmony_cistatic int unknown_ext_print(BIO *out, const unsigned char *ext, int extlen, 20e1051a39Sopenharmony_ci unsigned long flag, int indent, int supported); 21e1051a39Sopenharmony_ci 22e1051a39Sopenharmony_ci/* Print out a name+value stack */ 23e1051a39Sopenharmony_ci 24e1051a39Sopenharmony_civoid X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent, 25e1051a39Sopenharmony_ci int ml) 26e1051a39Sopenharmony_ci{ 27e1051a39Sopenharmony_ci int i; 28e1051a39Sopenharmony_ci CONF_VALUE *nval; 29e1051a39Sopenharmony_ci if (!val) 30e1051a39Sopenharmony_ci return; 31e1051a39Sopenharmony_ci if (!ml || !sk_CONF_VALUE_num(val)) { 32e1051a39Sopenharmony_ci BIO_printf(out, "%*s", indent, ""); 33e1051a39Sopenharmony_ci if (!sk_CONF_VALUE_num(val)) 34e1051a39Sopenharmony_ci BIO_puts(out, "<EMPTY>\n"); 35e1051a39Sopenharmony_ci } 36e1051a39Sopenharmony_ci for (i = 0; i < sk_CONF_VALUE_num(val); i++) { 37e1051a39Sopenharmony_ci if (ml) { 38e1051a39Sopenharmony_ci if (i > 0) 39e1051a39Sopenharmony_ci BIO_printf(out, "\n"); 40e1051a39Sopenharmony_ci BIO_printf(out, "%*s", indent, ""); 41e1051a39Sopenharmony_ci } 42e1051a39Sopenharmony_ci else if (i > 0) 43e1051a39Sopenharmony_ci BIO_printf(out, ", "); 44e1051a39Sopenharmony_ci nval = sk_CONF_VALUE_value(val, i); 45e1051a39Sopenharmony_ci if (!nval->name) 46e1051a39Sopenharmony_ci BIO_puts(out, nval->value); 47e1051a39Sopenharmony_ci else if (!nval->value) 48e1051a39Sopenharmony_ci BIO_puts(out, nval->name); 49e1051a39Sopenharmony_ci#ifndef CHARSET_EBCDIC 50e1051a39Sopenharmony_ci else 51e1051a39Sopenharmony_ci BIO_printf(out, "%s:%s", nval->name, nval->value); 52e1051a39Sopenharmony_ci#else 53e1051a39Sopenharmony_ci else { 54e1051a39Sopenharmony_ci int len; 55e1051a39Sopenharmony_ci char *tmp; 56e1051a39Sopenharmony_ci len = strlen(nval->value) + 1; 57e1051a39Sopenharmony_ci tmp = OPENSSL_malloc(len); 58e1051a39Sopenharmony_ci if (tmp != NULL) { 59e1051a39Sopenharmony_ci ascii2ebcdic(tmp, nval->value, len); 60e1051a39Sopenharmony_ci BIO_printf(out, "%s:%s", nval->name, tmp); 61e1051a39Sopenharmony_ci OPENSSL_free(tmp); 62e1051a39Sopenharmony_ci } 63e1051a39Sopenharmony_ci } 64e1051a39Sopenharmony_ci#endif 65e1051a39Sopenharmony_ci } 66e1051a39Sopenharmony_ci} 67e1051a39Sopenharmony_ci 68e1051a39Sopenharmony_ci/* Main routine: print out a general extension */ 69e1051a39Sopenharmony_ci 70e1051a39Sopenharmony_ciint X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, 71e1051a39Sopenharmony_ci int indent) 72e1051a39Sopenharmony_ci{ 73e1051a39Sopenharmony_ci void *ext_str = NULL; 74e1051a39Sopenharmony_ci char *value = NULL; 75e1051a39Sopenharmony_ci ASN1_OCTET_STRING *extoct; 76e1051a39Sopenharmony_ci const unsigned char *p; 77e1051a39Sopenharmony_ci int extlen; 78e1051a39Sopenharmony_ci const X509V3_EXT_METHOD *method; 79e1051a39Sopenharmony_ci STACK_OF(CONF_VALUE) *nval = NULL; 80e1051a39Sopenharmony_ci int ok = 1; 81e1051a39Sopenharmony_ci 82e1051a39Sopenharmony_ci extoct = X509_EXTENSION_get_data(ext); 83e1051a39Sopenharmony_ci p = ASN1_STRING_get0_data(extoct); 84e1051a39Sopenharmony_ci extlen = ASN1_STRING_length(extoct); 85e1051a39Sopenharmony_ci 86e1051a39Sopenharmony_ci if ((method = X509V3_EXT_get(ext)) == NULL) 87e1051a39Sopenharmony_ci return unknown_ext_print(out, p, extlen, flag, indent, 0); 88e1051a39Sopenharmony_ci if (method->it) 89e1051a39Sopenharmony_ci ext_str = ASN1_item_d2i(NULL, &p, extlen, ASN1_ITEM_ptr(method->it)); 90e1051a39Sopenharmony_ci else 91e1051a39Sopenharmony_ci ext_str = method->d2i(NULL, &p, extlen); 92e1051a39Sopenharmony_ci 93e1051a39Sopenharmony_ci if (!ext_str) 94e1051a39Sopenharmony_ci return unknown_ext_print(out, p, extlen, flag, indent, 1); 95e1051a39Sopenharmony_ci 96e1051a39Sopenharmony_ci if (method->i2s) { 97e1051a39Sopenharmony_ci if ((value = method->i2s(method, ext_str)) == NULL) { 98e1051a39Sopenharmony_ci ok = 0; 99e1051a39Sopenharmony_ci goto err; 100e1051a39Sopenharmony_ci } 101e1051a39Sopenharmony_ci#ifndef CHARSET_EBCDIC 102e1051a39Sopenharmony_ci BIO_printf(out, "%*s%s", indent, "", value); 103e1051a39Sopenharmony_ci#else 104e1051a39Sopenharmony_ci { 105e1051a39Sopenharmony_ci int len; 106e1051a39Sopenharmony_ci char *tmp; 107e1051a39Sopenharmony_ci len = strlen(value) + 1; 108e1051a39Sopenharmony_ci tmp = OPENSSL_malloc(len); 109e1051a39Sopenharmony_ci if (tmp != NULL) { 110e1051a39Sopenharmony_ci ascii2ebcdic(tmp, value, len); 111e1051a39Sopenharmony_ci BIO_printf(out, "%*s%s", indent, "", tmp); 112e1051a39Sopenharmony_ci OPENSSL_free(tmp); 113e1051a39Sopenharmony_ci } 114e1051a39Sopenharmony_ci } 115e1051a39Sopenharmony_ci#endif 116e1051a39Sopenharmony_ci } else if (method->i2v) { 117e1051a39Sopenharmony_ci if ((nval = method->i2v(method, ext_str, NULL)) == NULL) { 118e1051a39Sopenharmony_ci ok = 0; 119e1051a39Sopenharmony_ci goto err; 120e1051a39Sopenharmony_ci } 121e1051a39Sopenharmony_ci X509V3_EXT_val_prn(out, nval, indent, 122e1051a39Sopenharmony_ci method->ext_flags & X509V3_EXT_MULTILINE); 123e1051a39Sopenharmony_ci } else if (method->i2r) { 124e1051a39Sopenharmony_ci if (!method->i2r(method, ext_str, out, indent)) 125e1051a39Sopenharmony_ci ok = 0; 126e1051a39Sopenharmony_ci } else 127e1051a39Sopenharmony_ci ok = 0; 128e1051a39Sopenharmony_ci 129e1051a39Sopenharmony_ci err: 130e1051a39Sopenharmony_ci sk_CONF_VALUE_pop_free(nval, X509V3_conf_free); 131e1051a39Sopenharmony_ci OPENSSL_free(value); 132e1051a39Sopenharmony_ci if (method->it) 133e1051a39Sopenharmony_ci ASN1_item_free(ext_str, ASN1_ITEM_ptr(method->it)); 134e1051a39Sopenharmony_ci else 135e1051a39Sopenharmony_ci method->ext_free(ext_str); 136e1051a39Sopenharmony_ci return ok; 137e1051a39Sopenharmony_ci} 138e1051a39Sopenharmony_ci 139e1051a39Sopenharmony_ciint X509V3_extensions_print(BIO *bp, const char *title, 140e1051a39Sopenharmony_ci const STACK_OF(X509_EXTENSION) *exts, 141e1051a39Sopenharmony_ci unsigned long flag, int indent) 142e1051a39Sopenharmony_ci{ 143e1051a39Sopenharmony_ci int i, j; 144e1051a39Sopenharmony_ci 145e1051a39Sopenharmony_ci if (sk_X509_EXTENSION_num(exts) <= 0) 146e1051a39Sopenharmony_ci return 1; 147e1051a39Sopenharmony_ci 148e1051a39Sopenharmony_ci if (title) { 149e1051a39Sopenharmony_ci BIO_printf(bp, "%*s%s:\n", indent, "", title); 150e1051a39Sopenharmony_ci indent += 4; 151e1051a39Sopenharmony_ci } 152e1051a39Sopenharmony_ci 153e1051a39Sopenharmony_ci for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { 154e1051a39Sopenharmony_ci ASN1_OBJECT *obj; 155e1051a39Sopenharmony_ci X509_EXTENSION *ex; 156e1051a39Sopenharmony_ci 157e1051a39Sopenharmony_ci ex = sk_X509_EXTENSION_value(exts, i); 158e1051a39Sopenharmony_ci obj = X509_EXTENSION_get_object(ex); 159e1051a39Sopenharmony_ci if ((flag & X509_FLAG_EXTENSIONS_ONLY_KID) != 0 160e1051a39Sopenharmony_ci && OBJ_obj2nid(obj) != NID_subject_key_identifier 161e1051a39Sopenharmony_ci && OBJ_obj2nid(obj) != NID_authority_key_identifier) 162e1051a39Sopenharmony_ci continue; 163e1051a39Sopenharmony_ci if (indent && BIO_printf(bp, "%*s", indent, "") <= 0) 164e1051a39Sopenharmony_ci return 0; 165e1051a39Sopenharmony_ci i2a_ASN1_OBJECT(bp, obj); 166e1051a39Sopenharmony_ci j = X509_EXTENSION_get_critical(ex); 167e1051a39Sopenharmony_ci if (BIO_printf(bp, ": %s\n", j ? "critical" : "") <= 0) 168e1051a39Sopenharmony_ci return 0; 169e1051a39Sopenharmony_ci if (!X509V3_EXT_print(bp, ex, flag, indent + 4)) { 170e1051a39Sopenharmony_ci BIO_printf(bp, "%*s", indent + 4, ""); 171e1051a39Sopenharmony_ci ASN1_STRING_print(bp, X509_EXTENSION_get_data(ex)); 172e1051a39Sopenharmony_ci } 173e1051a39Sopenharmony_ci if (BIO_write(bp, "\n", 1) <= 0) 174e1051a39Sopenharmony_ci return 0; 175e1051a39Sopenharmony_ci } 176e1051a39Sopenharmony_ci return 1; 177e1051a39Sopenharmony_ci} 178e1051a39Sopenharmony_ci 179e1051a39Sopenharmony_cistatic int unknown_ext_print(BIO *out, const unsigned char *ext, int extlen, 180e1051a39Sopenharmony_ci unsigned long flag, int indent, int supported) 181e1051a39Sopenharmony_ci{ 182e1051a39Sopenharmony_ci switch (flag & X509V3_EXT_UNKNOWN_MASK) { 183e1051a39Sopenharmony_ci 184e1051a39Sopenharmony_ci case X509V3_EXT_DEFAULT: 185e1051a39Sopenharmony_ci return 0; 186e1051a39Sopenharmony_ci 187e1051a39Sopenharmony_ci case X509V3_EXT_ERROR_UNKNOWN: 188e1051a39Sopenharmony_ci if (supported) 189e1051a39Sopenharmony_ci BIO_printf(out, "%*s<Parse Error>", indent, ""); 190e1051a39Sopenharmony_ci else 191e1051a39Sopenharmony_ci BIO_printf(out, "%*s<Not Supported>", indent, ""); 192e1051a39Sopenharmony_ci return 1; 193e1051a39Sopenharmony_ci 194e1051a39Sopenharmony_ci case X509V3_EXT_PARSE_UNKNOWN: 195e1051a39Sopenharmony_ci return ASN1_parse_dump(out, ext, extlen, indent, -1); 196e1051a39Sopenharmony_ci case X509V3_EXT_DUMP_UNKNOWN: 197e1051a39Sopenharmony_ci return BIO_dump_indent(out, (const char *)ext, extlen, indent); 198e1051a39Sopenharmony_ci 199e1051a39Sopenharmony_ci default: 200e1051a39Sopenharmony_ci return 1; 201e1051a39Sopenharmony_ci } 202e1051a39Sopenharmony_ci} 203e1051a39Sopenharmony_ci 204e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_STDIO 205e1051a39Sopenharmony_ciint X509V3_EXT_print_fp(FILE *fp, X509_EXTENSION *ext, int flag, int indent) 206e1051a39Sopenharmony_ci{ 207e1051a39Sopenharmony_ci BIO *bio_tmp; 208e1051a39Sopenharmony_ci int ret; 209e1051a39Sopenharmony_ci 210e1051a39Sopenharmony_ci if ((bio_tmp = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) 211e1051a39Sopenharmony_ci return 0; 212e1051a39Sopenharmony_ci ret = X509V3_EXT_print(bio_tmp, ext, flag, indent); 213e1051a39Sopenharmony_ci BIO_free(bio_tmp); 214e1051a39Sopenharmony_ci return ret; 215e1051a39Sopenharmony_ci} 216e1051a39Sopenharmony_ci#endif 217