159191Skris/* a_strnid.c */ 2280297Sjkim/* 3280297Sjkim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 4280297Sjkim * 1999. 559191Skris */ 659191Skris/* ==================================================================== 759191Skris * Copyright (c) 1999 The OpenSSL Project. All rights reserved. 859191Skris * 959191Skris * Redistribution and use in source and binary forms, with or without 1059191Skris * modification, are permitted provided that the following conditions 1159191Skris * are met: 1259191Skris * 1359191Skris * 1. Redistributions of source code must retain the above copyright 14280297Sjkim * notice, this list of conditions and the following disclaimer. 1559191Skris * 1659191Skris * 2. Redistributions in binary form must reproduce the above copyright 1759191Skris * notice, this list of conditions and the following disclaimer in 1859191Skris * the documentation and/or other materials provided with the 1959191Skris * distribution. 2059191Skris * 2159191Skris * 3. All advertising materials mentioning features or use of this 2259191Skris * software must display the following acknowledgment: 2359191Skris * "This product includes software developed by the OpenSSL Project 2459191Skris * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 2559191Skris * 2659191Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 2759191Skris * endorse or promote products derived from this software without 2859191Skris * prior written permission. For written permission, please contact 2959191Skris * licensing@OpenSSL.org. 3059191Skris * 3159191Skris * 5. Products derived from this software may not be called "OpenSSL" 3259191Skris * nor may "OpenSSL" appear in their names without prior written 3359191Skris * permission of the OpenSSL Project. 3459191Skris * 3559191Skris * 6. Redistributions of any form whatsoever must retain the following 3659191Skris * acknowledgment: 3759191Skris * "This product includes software developed by the OpenSSL Project 3859191Skris * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 3959191Skris * 4059191Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 4159191Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4259191Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 4359191Skris * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 4459191Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 4559191Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 4659191Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 4759191Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4859191Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 4959191Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 5059191Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 5159191Skris * OF THE POSSIBILITY OF SUCH DAMAGE. 5259191Skris * ==================================================================== 5359191Skris * 5459191Skris * This product includes cryptographic software written by Eric Young 5559191Skris * (eay@cryptsoft.com). This product includes software written by Tim 5659191Skris * Hudson (tjh@cryptsoft.com). 5759191Skris * 5859191Skris */ 5959191Skris 6059191Skris#include <stdio.h> 6159191Skris#include <ctype.h> 6259191Skris#include "cryptlib.h" 6359191Skris#include <openssl/asn1.h> 6459191Skris#include <openssl/objects.h> 6559191Skris 6659191Skrisstatic STACK_OF(ASN1_STRING_TABLE) *stable = NULL; 6759191Skrisstatic void st_free(ASN1_STRING_TABLE *tbl); 68280297Sjkimstatic int sk_table_cmp(const ASN1_STRING_TABLE *const *a, 69280297Sjkim const ASN1_STRING_TABLE *const *b); 7059191Skris 71280297Sjkim/* 72280297Sjkim * This is the global mask for the mbstring functions: this is use to mask 73280297Sjkim * out certain types (such as BMPString and UTF8String) because certain 74280297Sjkim * software (e.g. Netscape) has problems with them. 7559191Skris */ 7659191Skris 77267256Sjkimstatic unsigned long global_mask = B_ASN1_UTF8STRING; 7859191Skris 7959191Skrisvoid ASN1_STRING_set_default_mask(unsigned long mask) 8059191Skris{ 81280297Sjkim global_mask = mask; 8259191Skris} 8359191Skris 8459191Skrisunsigned long ASN1_STRING_get_default_mask(void) 8559191Skris{ 86280297Sjkim return global_mask; 8759191Skris} 8859191Skris 89280297Sjkim/*- 90280297Sjkim * This function sets the default to various "flavours" of configuration. 9159191Skris * based on an ASCII string. Currently this is: 9259191Skris * MASK:XXXX : a numerical mask value. 9359191Skris * nobmp : Don't use BMPStrings (just Printable, T61). 9459191Skris * pkix : PKIX recommendation in RFC2459. 9559191Skris * utf8only : only use UTF8Strings (RFC2459 recommendation for 2004). 9659191Skris * default: the default value, Printable, T61, BMP. 9759191Skris */ 9859191Skris 99237657Sjkimint ASN1_STRING_set_default_mask_asc(const char *p) 10059191Skris{ 101280297Sjkim unsigned long mask; 102280297Sjkim char *end; 103280297Sjkim if (!strncmp(p, "MASK:", 5)) { 104280297Sjkim if (!p[5]) 105280297Sjkim return 0; 106280297Sjkim mask = strtoul(p + 5, &end, 0); 107280297Sjkim if (*end) 108280297Sjkim return 0; 109280297Sjkim } else if (!strcmp(p, "nombstr")) 110280297Sjkim mask = ~((unsigned long)(B_ASN1_BMPSTRING | B_ASN1_UTF8STRING)); 111280297Sjkim else if (!strcmp(p, "pkix")) 112280297Sjkim mask = ~((unsigned long)B_ASN1_T61STRING); 113280297Sjkim else if (!strcmp(p, "utf8only")) 114280297Sjkim mask = B_ASN1_UTF8STRING; 115280297Sjkim else if (!strcmp(p, "default")) 116280297Sjkim mask = 0xFFFFFFFFL; 117280297Sjkim else 118280297Sjkim return 0; 119280297Sjkim ASN1_STRING_set_default_mask(mask); 120280297Sjkim return 1; 12159191Skris} 12259191Skris 123280297Sjkim/* 124280297Sjkim * The following function generates an ASN1_STRING based on limits in a 125280297Sjkim * table. Frequently the types and length of an ASN1_STRING are restricted by 126280297Sjkim * a corresponding OID. For example certificates and certificate requests. 12759191Skris */ 12859191Skris 129280297SjkimASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, 130280297Sjkim const unsigned char *in, int inlen, 131280297Sjkim int inform, int nid) 13259191Skris{ 133280297Sjkim ASN1_STRING_TABLE *tbl; 134280297Sjkim ASN1_STRING *str = NULL; 135280297Sjkim unsigned long mask; 136280297Sjkim int ret; 137280297Sjkim if (!out) 138280297Sjkim out = &str; 139280297Sjkim tbl = ASN1_STRING_TABLE_get(nid); 140280297Sjkim if (tbl) { 141280297Sjkim mask = tbl->mask; 142280297Sjkim if (!(tbl->flags & STABLE_NO_MASK)) 143280297Sjkim mask &= global_mask; 144280297Sjkim ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask, 145280297Sjkim tbl->minsize, tbl->maxsize); 146280297Sjkim } else 147280297Sjkim ret = 148280297Sjkim ASN1_mbstring_copy(out, in, inlen, inform, 149280297Sjkim DIRSTRING_TYPE & global_mask); 150280297Sjkim if (ret <= 0) 151280297Sjkim return NULL; 152280297Sjkim return *out; 15359191Skris} 15459191Skris 155280297Sjkim/* 156280297Sjkim * Now the tables and helper functions for the string table: 15759191Skris */ 15859191Skris 159120631Snectar/* size limits: this stuff is taken straight from RFC3280 */ 16059191Skris 161280297Sjkim#define ub_name 32768 162280297Sjkim#define ub_common_name 64 163280297Sjkim#define ub_locality_name 128 164280297Sjkim#define ub_state_name 128 165280297Sjkim#define ub_organization_name 64 166280297Sjkim#define ub_organization_unit_name 64 167280297Sjkim#define ub_title 64 168280297Sjkim#define ub_email_address 128 169280297Sjkim#define ub_serial_number 64 17059191Skris 17159191Skris/* This table must be kept in NID order */ 17259191Skris 173238405Sjkimstatic const ASN1_STRING_TABLE tbl_standard[] = { 174280297Sjkim {NID_commonName, 1, ub_common_name, DIRSTRING_TYPE, 0}, 175280297Sjkim {NID_countryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK}, 176280297Sjkim {NID_localityName, 1, ub_locality_name, DIRSTRING_TYPE, 0}, 177280297Sjkim {NID_stateOrProvinceName, 1, ub_state_name, DIRSTRING_TYPE, 0}, 178280297Sjkim {NID_organizationName, 1, ub_organization_name, DIRSTRING_TYPE, 0}, 179280297Sjkim {NID_organizationalUnitName, 1, ub_organization_unit_name, DIRSTRING_TYPE, 180280297Sjkim 0}, 181280297Sjkim {NID_pkcs9_emailAddress, 1, ub_email_address, B_ASN1_IA5STRING, 182280297Sjkim STABLE_NO_MASK}, 183280297Sjkim {NID_pkcs9_unstructuredName, 1, -1, PKCS9STRING_TYPE, 0}, 184280297Sjkim {NID_pkcs9_challengePassword, 1, -1, PKCS9STRING_TYPE, 0}, 185280297Sjkim {NID_pkcs9_unstructuredAddress, 1, -1, DIRSTRING_TYPE, 0}, 186280297Sjkim {NID_givenName, 1, ub_name, DIRSTRING_TYPE, 0}, 187280297Sjkim {NID_surname, 1, ub_name, DIRSTRING_TYPE, 0}, 188280297Sjkim {NID_initials, 1, ub_name, DIRSTRING_TYPE, 0}, 189280297Sjkim {NID_serialNumber, 1, ub_serial_number, B_ASN1_PRINTABLESTRING, 190280297Sjkim STABLE_NO_MASK}, 191280297Sjkim {NID_friendlyName, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK}, 192280297Sjkim {NID_name, 1, ub_name, DIRSTRING_TYPE, 0}, 193280297Sjkim {NID_dnQualifier, -1, -1, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK}, 194280297Sjkim {NID_domainComponent, 1, -1, B_ASN1_IA5STRING, STABLE_NO_MASK}, 195325335Sjkim {NID_ms_csp_name, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK}, 196325335Sjkim {NID_jurisdictionCountryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK} 19759191Skris}; 19859191Skris 199280297Sjkimstatic int sk_table_cmp(const ASN1_STRING_TABLE *const *a, 200280297Sjkim const ASN1_STRING_TABLE *const *b) 20159191Skris{ 202280297Sjkim return (*a)->nid - (*b)->nid; 20359191Skris} 20459191Skris 205238405SjkimDECLARE_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table); 206238405Sjkim 207238405Sjkimstatic int table_cmp(const ASN1_STRING_TABLE *a, const ASN1_STRING_TABLE *b) 20859191Skris{ 209280297Sjkim return a->nid - b->nid; 21059191Skris} 21159191Skris 212238405SjkimIMPLEMENT_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table); 213238405Sjkim 21459191SkrisASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid) 21559191Skris{ 216280297Sjkim int idx; 217280297Sjkim ASN1_STRING_TABLE *ttmp; 218280297Sjkim ASN1_STRING_TABLE fnd; 219280297Sjkim fnd.nid = nid; 220280297Sjkim ttmp = OBJ_bsearch_table(&fnd, tbl_standard, 221280297Sjkim sizeof(tbl_standard) / 222280297Sjkim sizeof(ASN1_STRING_TABLE)); 223280297Sjkim if (ttmp) 224280297Sjkim return ttmp; 225280297Sjkim if (!stable) 226280297Sjkim return NULL; 227280297Sjkim idx = sk_ASN1_STRING_TABLE_find(stable, &fnd); 228280297Sjkim if (idx < 0) 229280297Sjkim return NULL; 230280297Sjkim return sk_ASN1_STRING_TABLE_value(stable, idx); 23159191Skris} 232280297Sjkim 23359191Skrisint ASN1_STRING_TABLE_add(int nid, 234280297Sjkim long minsize, long maxsize, unsigned long mask, 235280297Sjkim unsigned long flags) 23659191Skris{ 237280297Sjkim ASN1_STRING_TABLE *tmp; 238280297Sjkim char new_nid = 0; 239280297Sjkim flags &= ~STABLE_FLAGS_MALLOC; 240280297Sjkim if (!stable) 241280297Sjkim stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp); 242280297Sjkim if (!stable) { 243280297Sjkim ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD, ERR_R_MALLOC_FAILURE); 244280297Sjkim return 0; 245280297Sjkim } 246280297Sjkim if (!(tmp = ASN1_STRING_TABLE_get(nid))) { 247280297Sjkim tmp = OPENSSL_malloc(sizeof(ASN1_STRING_TABLE)); 248280297Sjkim if (!tmp) { 249280297Sjkim ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD, ERR_R_MALLOC_FAILURE); 250280297Sjkim return 0; 251280297Sjkim } 252280297Sjkim tmp->flags = flags | STABLE_FLAGS_MALLOC; 253280297Sjkim tmp->nid = nid; 254306195Sjkim tmp->minsize = tmp->maxsize = -1; 255280297Sjkim new_nid = 1; 256280297Sjkim } else 257280297Sjkim tmp->flags = (tmp->flags & STABLE_FLAGS_MALLOC) | flags; 258280297Sjkim if (minsize != -1) 259280297Sjkim tmp->minsize = minsize; 260280297Sjkim if (maxsize != -1) 261280297Sjkim tmp->maxsize = maxsize; 262280297Sjkim tmp->mask = mask; 263280297Sjkim if (new_nid) 264280297Sjkim sk_ASN1_STRING_TABLE_push(stable, tmp); 265280297Sjkim return 1; 26659191Skris} 26759191Skris 26859191Skrisvoid ASN1_STRING_TABLE_cleanup(void) 26959191Skris{ 270280297Sjkim STACK_OF(ASN1_STRING_TABLE) *tmp; 271280297Sjkim tmp = stable; 272280297Sjkim if (!tmp) 273280297Sjkim return; 274280297Sjkim stable = NULL; 275280297Sjkim sk_ASN1_STRING_TABLE_pop_free(tmp, st_free); 27659191Skris} 27759191Skris 27859191Skrisstatic void st_free(ASN1_STRING_TABLE *tbl) 27959191Skris{ 280280297Sjkim if (tbl->flags & STABLE_FLAGS_MALLOC) 281280297Sjkim OPENSSL_free(tbl); 28259191Skris} 28359191Skris 284120631Snectar 28559191SkrisIMPLEMENT_STACK_OF(ASN1_STRING_TABLE) 286120631Snectar 287120631Snectar#ifdef STRING_TABLE_TEST 288120631Snectar 289120631Snectarmain() 290120631Snectar{ 291280297Sjkim ASN1_STRING_TABLE *tmp; 292280297Sjkim int i, last_nid = -1; 293120631Snectar 294280297Sjkim for (tmp = tbl_standard, i = 0; 295280297Sjkim i < sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE); i++, tmp++) { 296280297Sjkim if (tmp->nid < last_nid) { 297280297Sjkim last_nid = 0; 298280297Sjkim break; 299280297Sjkim } 300280297Sjkim last_nid = tmp->nid; 301280297Sjkim } 302120631Snectar 303280297Sjkim if (last_nid != 0) { 304280297Sjkim printf("Table order OK\n"); 305280297Sjkim exit(0); 306280297Sjkim } 307120631Snectar 308280297Sjkim for (tmp = tbl_standard, i = 0; 309280297Sjkim i < sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE); i++, tmp++) 310280297Sjkim printf("Index %d, NID %d, Name=%s\n", i, tmp->nid, 311280297Sjkim OBJ_nid2ln(tmp->nid)); 312120631Snectar 313120631Snectar} 314120631Snectar 315120631Snectar#endif 316