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#include <stdio.h> 11e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 12e1051a39Sopenharmony_ci#include <openssl/asn1.h> 13e1051a39Sopenharmony_ci#include <openssl/objects.h> 14e1051a39Sopenharmony_ci 15e1051a39Sopenharmony_cistatic STACK_OF(ASN1_STRING_TABLE) *stable = NULL; 16e1051a39Sopenharmony_cistatic void st_free(ASN1_STRING_TABLE *tbl); 17e1051a39Sopenharmony_cistatic int sk_table_cmp(const ASN1_STRING_TABLE *const *a, 18e1051a39Sopenharmony_ci const ASN1_STRING_TABLE *const *b); 19e1051a39Sopenharmony_ci 20e1051a39Sopenharmony_ci/* 21e1051a39Sopenharmony_ci * This is the global mask for the mbstring functions: this is use to mask 22e1051a39Sopenharmony_ci * out certain types (such as BMPString and UTF8String) because certain 23e1051a39Sopenharmony_ci * software (e.g. Netscape) has problems with them. 24e1051a39Sopenharmony_ci */ 25e1051a39Sopenharmony_ci 26e1051a39Sopenharmony_cistatic unsigned long global_mask = B_ASN1_UTF8STRING; 27e1051a39Sopenharmony_ci 28e1051a39Sopenharmony_civoid ASN1_STRING_set_default_mask(unsigned long mask) 29e1051a39Sopenharmony_ci{ 30e1051a39Sopenharmony_ci global_mask = mask; 31e1051a39Sopenharmony_ci} 32e1051a39Sopenharmony_ci 33e1051a39Sopenharmony_ciunsigned long ASN1_STRING_get_default_mask(void) 34e1051a39Sopenharmony_ci{ 35e1051a39Sopenharmony_ci return global_mask; 36e1051a39Sopenharmony_ci} 37e1051a39Sopenharmony_ci 38e1051a39Sopenharmony_ci/*- 39e1051a39Sopenharmony_ci * This function sets the default to various "flavours" of configuration. 40e1051a39Sopenharmony_ci * based on an ASCII string. Currently this is: 41e1051a39Sopenharmony_ci * MASK:XXXX : a numerical mask value. 42e1051a39Sopenharmony_ci * nobmp : Don't use BMPStrings (just Printable, T61). 43e1051a39Sopenharmony_ci * pkix : PKIX recommendation in RFC2459. 44e1051a39Sopenharmony_ci * utf8only : only use UTF8Strings (RFC2459 recommendation for 2004). 45e1051a39Sopenharmony_ci * default: the default value, Printable, T61, BMP. 46e1051a39Sopenharmony_ci */ 47e1051a39Sopenharmony_ci 48e1051a39Sopenharmony_ciint ASN1_STRING_set_default_mask_asc(const char *p) 49e1051a39Sopenharmony_ci{ 50e1051a39Sopenharmony_ci unsigned long mask; 51e1051a39Sopenharmony_ci char *end; 52e1051a39Sopenharmony_ci 53e1051a39Sopenharmony_ci if (strncmp(p, "MASK:", 5) == 0) { 54e1051a39Sopenharmony_ci if (p[5] == '\0') 55e1051a39Sopenharmony_ci return 0; 56e1051a39Sopenharmony_ci mask = strtoul(p + 5, &end, 0); 57e1051a39Sopenharmony_ci if (*end) 58e1051a39Sopenharmony_ci return 0; 59e1051a39Sopenharmony_ci } else if (strcmp(p, "nombstr") == 0) 60e1051a39Sopenharmony_ci mask = ~((unsigned long)(B_ASN1_BMPSTRING | B_ASN1_UTF8STRING)); 61e1051a39Sopenharmony_ci else if (strcmp(p, "pkix") == 0) 62e1051a39Sopenharmony_ci mask = ~((unsigned long)B_ASN1_T61STRING); 63e1051a39Sopenharmony_ci else if (strcmp(p, "utf8only") == 0) 64e1051a39Sopenharmony_ci mask = B_ASN1_UTF8STRING; 65e1051a39Sopenharmony_ci else if (strcmp(p, "default") == 0) 66e1051a39Sopenharmony_ci mask = 0xFFFFFFFFL; 67e1051a39Sopenharmony_ci else 68e1051a39Sopenharmony_ci return 0; 69e1051a39Sopenharmony_ci ASN1_STRING_set_default_mask(mask); 70e1051a39Sopenharmony_ci return 1; 71e1051a39Sopenharmony_ci} 72e1051a39Sopenharmony_ci 73e1051a39Sopenharmony_ci/* 74e1051a39Sopenharmony_ci * The following function generates an ASN1_STRING based on limits in a 75e1051a39Sopenharmony_ci * table. Frequently the types and length of an ASN1_STRING are restricted by 76e1051a39Sopenharmony_ci * a corresponding OID. For example certificates and certificate requests. 77e1051a39Sopenharmony_ci */ 78e1051a39Sopenharmony_ci 79e1051a39Sopenharmony_ciASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, 80e1051a39Sopenharmony_ci const unsigned char *in, int inlen, 81e1051a39Sopenharmony_ci int inform, int nid) 82e1051a39Sopenharmony_ci{ 83e1051a39Sopenharmony_ci ASN1_STRING_TABLE *tbl; 84e1051a39Sopenharmony_ci ASN1_STRING *str = NULL; 85e1051a39Sopenharmony_ci unsigned long mask; 86e1051a39Sopenharmony_ci int ret; 87e1051a39Sopenharmony_ci 88e1051a39Sopenharmony_ci if (out == NULL) 89e1051a39Sopenharmony_ci out = &str; 90e1051a39Sopenharmony_ci tbl = ASN1_STRING_TABLE_get(nid); 91e1051a39Sopenharmony_ci if (tbl != NULL) { 92e1051a39Sopenharmony_ci mask = tbl->mask; 93e1051a39Sopenharmony_ci if (!(tbl->flags & STABLE_NO_MASK)) 94e1051a39Sopenharmony_ci mask &= global_mask; 95e1051a39Sopenharmony_ci ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask, 96e1051a39Sopenharmony_ci tbl->minsize, tbl->maxsize); 97e1051a39Sopenharmony_ci } else { 98e1051a39Sopenharmony_ci ret = ASN1_mbstring_copy(out, in, inlen, inform, 99e1051a39Sopenharmony_ci DIRSTRING_TYPE & global_mask); 100e1051a39Sopenharmony_ci } 101e1051a39Sopenharmony_ci if (ret <= 0) 102e1051a39Sopenharmony_ci return NULL; 103e1051a39Sopenharmony_ci return *out; 104e1051a39Sopenharmony_ci} 105e1051a39Sopenharmony_ci 106e1051a39Sopenharmony_ci/* 107e1051a39Sopenharmony_ci * Now the tables and helper functions for the string table: 108e1051a39Sopenharmony_ci */ 109e1051a39Sopenharmony_ci 110e1051a39Sopenharmony_ci#include "tbl_standard.h" 111e1051a39Sopenharmony_ci 112e1051a39Sopenharmony_cistatic int sk_table_cmp(const ASN1_STRING_TABLE *const *a, 113e1051a39Sopenharmony_ci const ASN1_STRING_TABLE *const *b) 114e1051a39Sopenharmony_ci{ 115e1051a39Sopenharmony_ci return (*a)->nid - (*b)->nid; 116e1051a39Sopenharmony_ci} 117e1051a39Sopenharmony_ci 118e1051a39Sopenharmony_ciDECLARE_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table); 119e1051a39Sopenharmony_ci 120e1051a39Sopenharmony_cistatic int table_cmp(const ASN1_STRING_TABLE *a, const ASN1_STRING_TABLE *b) 121e1051a39Sopenharmony_ci{ 122e1051a39Sopenharmony_ci return a->nid - b->nid; 123e1051a39Sopenharmony_ci} 124e1051a39Sopenharmony_ci 125e1051a39Sopenharmony_ciIMPLEMENT_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table); 126e1051a39Sopenharmony_ci 127e1051a39Sopenharmony_ciASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid) 128e1051a39Sopenharmony_ci{ 129e1051a39Sopenharmony_ci int idx; 130e1051a39Sopenharmony_ci ASN1_STRING_TABLE fnd; 131e1051a39Sopenharmony_ci 132e1051a39Sopenharmony_ci /* "stable" can be impacted by config, so load the config file first */ 133e1051a39Sopenharmony_ci OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL); 134e1051a39Sopenharmony_ci 135e1051a39Sopenharmony_ci fnd.nid = nid; 136e1051a39Sopenharmony_ci if (stable) { 137e1051a39Sopenharmony_ci idx = sk_ASN1_STRING_TABLE_find(stable, &fnd); 138e1051a39Sopenharmony_ci if (idx >= 0) 139e1051a39Sopenharmony_ci return sk_ASN1_STRING_TABLE_value(stable, idx); 140e1051a39Sopenharmony_ci } 141e1051a39Sopenharmony_ci return OBJ_bsearch_table(&fnd, tbl_standard, OSSL_NELEM(tbl_standard)); 142e1051a39Sopenharmony_ci} 143e1051a39Sopenharmony_ci 144e1051a39Sopenharmony_ci/* 145e1051a39Sopenharmony_ci * Return a string table pointer which can be modified: either directly from 146e1051a39Sopenharmony_ci * table or a copy of an internal value added to the table. 147e1051a39Sopenharmony_ci */ 148e1051a39Sopenharmony_ci 149e1051a39Sopenharmony_cistatic ASN1_STRING_TABLE *stable_get(int nid) 150e1051a39Sopenharmony_ci{ 151e1051a39Sopenharmony_ci ASN1_STRING_TABLE *tmp, *rv; 152e1051a39Sopenharmony_ci 153e1051a39Sopenharmony_ci /* Always need a string table so allocate one if NULL */ 154e1051a39Sopenharmony_ci if (stable == NULL) { 155e1051a39Sopenharmony_ci stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp); 156e1051a39Sopenharmony_ci if (stable == NULL) 157e1051a39Sopenharmony_ci return NULL; 158e1051a39Sopenharmony_ci } 159e1051a39Sopenharmony_ci tmp = ASN1_STRING_TABLE_get(nid); 160e1051a39Sopenharmony_ci if (tmp != NULL && tmp->flags & STABLE_FLAGS_MALLOC) 161e1051a39Sopenharmony_ci return tmp; 162e1051a39Sopenharmony_ci if ((rv = OPENSSL_zalloc(sizeof(*rv))) == NULL) { 163e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); 164e1051a39Sopenharmony_ci return NULL; 165e1051a39Sopenharmony_ci } 166e1051a39Sopenharmony_ci if (!sk_ASN1_STRING_TABLE_push(stable, rv)) { 167e1051a39Sopenharmony_ci OPENSSL_free(rv); 168e1051a39Sopenharmony_ci return NULL; 169e1051a39Sopenharmony_ci } 170e1051a39Sopenharmony_ci if (tmp != NULL) { 171e1051a39Sopenharmony_ci rv->nid = tmp->nid; 172e1051a39Sopenharmony_ci rv->minsize = tmp->minsize; 173e1051a39Sopenharmony_ci rv->maxsize = tmp->maxsize; 174e1051a39Sopenharmony_ci rv->mask = tmp->mask; 175e1051a39Sopenharmony_ci rv->flags = tmp->flags | STABLE_FLAGS_MALLOC; 176e1051a39Sopenharmony_ci } else { 177e1051a39Sopenharmony_ci rv->nid = nid; 178e1051a39Sopenharmony_ci rv->minsize = -1; 179e1051a39Sopenharmony_ci rv->maxsize = -1; 180e1051a39Sopenharmony_ci rv->flags = STABLE_FLAGS_MALLOC; 181e1051a39Sopenharmony_ci } 182e1051a39Sopenharmony_ci return rv; 183e1051a39Sopenharmony_ci} 184e1051a39Sopenharmony_ci 185e1051a39Sopenharmony_ciint ASN1_STRING_TABLE_add(int nid, 186e1051a39Sopenharmony_ci long minsize, long maxsize, unsigned long mask, 187e1051a39Sopenharmony_ci unsigned long flags) 188e1051a39Sopenharmony_ci{ 189e1051a39Sopenharmony_ci ASN1_STRING_TABLE *tmp; 190e1051a39Sopenharmony_ci 191e1051a39Sopenharmony_ci tmp = stable_get(nid); 192e1051a39Sopenharmony_ci if (tmp == NULL) { 193e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); 194e1051a39Sopenharmony_ci return 0; 195e1051a39Sopenharmony_ci } 196e1051a39Sopenharmony_ci if (minsize >= 0) 197e1051a39Sopenharmony_ci tmp->minsize = minsize; 198e1051a39Sopenharmony_ci if (maxsize >= 0) 199e1051a39Sopenharmony_ci tmp->maxsize = maxsize; 200e1051a39Sopenharmony_ci if (mask) 201e1051a39Sopenharmony_ci tmp->mask = mask; 202e1051a39Sopenharmony_ci if (flags) 203e1051a39Sopenharmony_ci tmp->flags = STABLE_FLAGS_MALLOC | flags; 204e1051a39Sopenharmony_ci return 1; 205e1051a39Sopenharmony_ci} 206e1051a39Sopenharmony_ci 207e1051a39Sopenharmony_civoid ASN1_STRING_TABLE_cleanup(void) 208e1051a39Sopenharmony_ci{ 209e1051a39Sopenharmony_ci STACK_OF(ASN1_STRING_TABLE) *tmp; 210e1051a39Sopenharmony_ci 211e1051a39Sopenharmony_ci tmp = stable; 212e1051a39Sopenharmony_ci if (tmp == NULL) 213e1051a39Sopenharmony_ci return; 214e1051a39Sopenharmony_ci stable = NULL; 215e1051a39Sopenharmony_ci sk_ASN1_STRING_TABLE_pop_free(tmp, st_free); 216e1051a39Sopenharmony_ci} 217e1051a39Sopenharmony_ci 218e1051a39Sopenharmony_cistatic void st_free(ASN1_STRING_TABLE *tbl) 219e1051a39Sopenharmony_ci{ 220e1051a39Sopenharmony_ci if (tbl->flags & STABLE_FLAGS_MALLOC) 221e1051a39Sopenharmony_ci OPENSSL_free(tbl); 222e1051a39Sopenharmony_ci} 223