a_strnid.c revision 279264
1168404Spjd/* a_strnid.c */ 2168404Spjd/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3168404Spjd * project 1999. 4168404Spjd */ 5168404Spjd/* ==================================================================== 6168404Spjd * Copyright (c) 1999 The OpenSSL Project. All rights reserved. 7168404Spjd * 8168404Spjd * Redistribution and use in source and binary forms, with or without 9168404Spjd * modification, are permitted provided that the following conditions 10168404Spjd * are met: 11168404Spjd * 12168404Spjd * 1. Redistributions of source code must retain the above copyright 13168404Spjd * notice, this list of conditions and the following disclaimer. 14168404Spjd * 15168404Spjd * 2. Redistributions in binary form must reproduce the above copyright 16168404Spjd * notice, this list of conditions and the following disclaimer in 17168404Spjd * the documentation and/or other materials provided with the 18168404Spjd * distribution. 19168404Spjd * 20168404Spjd * 3. All advertising materials mentioning features or use of this 21168404Spjd * software must display the following acknowledgment: 22211931Smm * "This product includes software developed by the OpenSSL Project 23339105Smav * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24246675Smm * 25296519Smav * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26168404Spjd * endorse or promote products derived from this software without 27168404Spjd * prior written permission. For written permission, please contact 28168404Spjd * licensing@OpenSSL.org. 29168404Spjd * 30168404Spjd * 5. Products derived from this software may not be called "OpenSSL" 31168404Spjd * nor may "OpenSSL" appear in their names without prior written 32168404Spjd * permission of the OpenSSL Project. 33168404Spjd * 34168404Spjd * 6. Redistributions of any form whatsoever must retain the following 35258717Savg * acknowledgment: 36269118Sdelphij * "This product includes software developed by the OpenSSL Project 37332525Smav * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38332547Smav * 39168404Spjd * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40255226Spjd * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41255226Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42255226Spjd * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43307277Smav * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44307277Smav * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45224177Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46168404Spjd * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47332553Smav * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48332553Smav * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49332553Smav * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50255226Spjd * OF THE POSSIBILITY OF SUCH DAMAGE. 51168404Spjd * ==================================================================== 52168404Spjd * 53332547Smav * This product includes cryptographic software written by Eric Young 54332547Smav * (eay@cryptsoft.com). This product includes software written by Tim 55332547Smav * Hudson (tjh@cryptsoft.com). 56332547Smav * 57332547Smav */ 58332547Smav 59332547Smav#include <stdio.h> 60332547Smav#include <ctype.h> 61332547Smav#include "cryptlib.h" 62332547Smav#include <openssl/asn1.h> 63332547Smav#include <openssl/objects.h> 64247398Smm 65247398Smm 66321529Smavstatic STACK_OF(ASN1_STRING_TABLE) *stable = NULL; 67247398Smmstatic void st_free(ASN1_STRING_TABLE *tbl); 68247398Smmstatic int sk_table_cmp(const ASN1_STRING_TABLE * const *a, 69247398Smm const ASN1_STRING_TABLE * const *b); 70258717Savg 71258717Savg 72258717Savg/* This is the global mask for the mbstring functions: this is use to 73258717Savg * mask out certain types (such as BMPString and UTF8String) because 74247398Smm * certain software (e.g. Netscape) has problems with them. 75247398Smm */ 76268855Sdelphij 77268855Sdelphijstatic unsigned long global_mask = B_ASN1_UTF8STRING; 78272504Sdelphij 79268855Sdelphijvoid ASN1_STRING_set_default_mask(unsigned long mask) 80268855Sdelphij{ 81268855Sdelphij global_mask = mask; 82268855Sdelphij} 83268855Sdelphij 84268855Sdelphijunsigned long ASN1_STRING_get_default_mask(void) 85268855Sdelphij{ 86268855Sdelphij return global_mask; 87268855Sdelphij} 88268855Sdelphij 89268855Sdelphij/* This function sets the default to various "flavours" of configuration. 90268855Sdelphij * based on an ASCII string. Currently this is: 91258633Savg * MASK:XXXX : a numerical mask value. 92258633Savg * nobmp : Don't use BMPStrings (just Printable, T61). 93269118Sdelphij * pkix : PKIX recommendation in RFC2459. 94258633Savg * utf8only : only use UTF8Strings (RFC2459 recommendation for 2004). 95258633Savg * default: the default value, Printable, T61, BMP. 96258633Savg */ 97258633Savg 98258633Savgint ASN1_STRING_set_default_mask_asc(const char *p) 99258633Savg{ 100258633Savg unsigned long mask; 101258633Savg char *end; 102258633Savg if(!strncmp(p, "MASK:", 5)) { 103258633Savg if(!p[5]) return 0; 104258717Savg mask = strtoul(p + 5, &end, 0); 105258717Savg if(*end) return 0; 106258717Savg } else if(!strcmp(p, "nombstr")) 107258717Savg mask = ~((unsigned long)(B_ASN1_BMPSTRING|B_ASN1_UTF8STRING)); 108258633Savg else if(!strcmp(p, "pkix")) 109258633Savg mask = ~((unsigned long)B_ASN1_T61STRING); 110269118Sdelphij else if(!strcmp(p, "utf8only")) mask = B_ASN1_UTF8STRING; 111269118Sdelphij else if(!strcmp(p, "default")) 112269118Sdelphij mask = 0xFFFFFFFFL; 113269118Sdelphij else return 0; 114269118Sdelphij ASN1_STRING_set_default_mask(mask); 115269118Sdelphij return 1; 116269118Sdelphij} 117269138Sdelphij 118269138Sdelphij/* The following function generates an ASN1_STRING based on limits in a table. 119269138Sdelphij * Frequently the types and length of an ASN1_STRING are restricted by a 120269138Sdelphij * corresponding OID. For example certificates and certificate requests. 121269138Sdelphij */ 122269118Sdelphij 123269118SdelphijASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, const unsigned char *in, 124269118Sdelphij int inlen, int inform, int nid) 125269118Sdelphij{ 126269118Sdelphij ASN1_STRING_TABLE *tbl; 127269118Sdelphij ASN1_STRING *str = NULL; 128269118Sdelphij unsigned long mask; 129269118Sdelphij int ret; 130269138Sdelphij if(!out) out = &str; 131269138Sdelphij tbl = ASN1_STRING_TABLE_get(nid); 132269138Sdelphij if(tbl) { 133269118Sdelphij mask = tbl->mask; 134269118Sdelphij if(!(tbl->flags & STABLE_NO_MASK)) mask &= global_mask; 135258717Savg ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask, 136219089Spjd tbl->minsize, tbl->maxsize); 137258717Savg } else ret = ASN1_mbstring_copy(out, in, inlen, inform, DIRSTRING_TYPE & global_mask); 138258717Savg if(ret <= 0) return NULL; 139258717Savg return *out; 140258717Savg} 141219089Spjd 142219089Spjd/* Now the tables and helper functions for the string table: 143258717Savg */ 144258717Savg 145258717Savg/* size limits: this stuff is taken straight from RFC3280 */ 146258717Savg 147258717Savg#define ub_name 32768 148258717Savg#define ub_common_name 64 149258717Savg#define ub_locality_name 128 150258717Savg#define ub_state_name 128 151209962Smm#define ub_organization_name 64 152211931Smm#define ub_organization_unit_name 64 153209962Smm#define ub_title 64 154209962Smm#define ub_email_address 128 155209962Smm#define ub_serial_number 64 156274337Sdelphij 157255226Spjd 158255226Spjd/* This table must be kept in NID order */ 159255226Spjd 160209962Smmstatic const ASN1_STRING_TABLE tbl_standard[] = { 161209962Smm{NID_commonName, 1, ub_common_name, DIRSTRING_TYPE, 0}, 162209962Smm{NID_countryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK}, 163209962Smm{NID_localityName, 1, ub_locality_name, DIRSTRING_TYPE, 0}, 164321529Smav{NID_stateOrProvinceName, 1, ub_state_name, DIRSTRING_TYPE, 0}, 165209962Smm{NID_organizationName, 1, ub_organization_name, DIRSTRING_TYPE, 0}, 166209962Smm{NID_organizationalUnitName, 1, ub_organization_unit_name, DIRSTRING_TYPE, 0}, 167211931Smm{NID_pkcs9_emailAddress, 1, ub_email_address, B_ASN1_IA5STRING, STABLE_NO_MASK}, 168255226Spjd{NID_pkcs9_unstructuredName, 1, -1, PKCS9STRING_TYPE, 0}, 169255226Spjd{NID_pkcs9_challengePassword, 1, -1, PKCS9STRING_TYPE, 0}, 170267992Shselasky{NID_pkcs9_unstructuredAddress, 1, -1, DIRSTRING_TYPE, 0}, 171267992Shselasky{NID_givenName, 1, ub_name, DIRSTRING_TYPE, 0}, 172209962Smm{NID_surname, 1, ub_name, DIRSTRING_TYPE, 0}, 173209962Smm{NID_initials, 1, ub_name, DIRSTRING_TYPE, 0}, 174211931Smm{NID_serialNumber, 1, ub_serial_number, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK}, 175211931Smm{NID_friendlyName, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK}, 176211931Smm{NID_name, 1, ub_name, DIRSTRING_TYPE, 0}, 177211931Smm{NID_dnQualifier, -1, -1, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK}, 178255226Spjd{NID_domainComponent, 1, -1, B_ASN1_IA5STRING, STABLE_NO_MASK}, 179255226Spjd{NID_ms_csp_name, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK} 180267992Shselasky}; 181267992Shselasky 182211931Smmstatic int sk_table_cmp(const ASN1_STRING_TABLE * const *a, 183211931Smm const ASN1_STRING_TABLE * const *b) 184258717Savg{ 185211931Smm return (*a)->nid - (*b)->nid; 186258717Savg} 187258717Savg 188258717SavgDECLARE_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table); 189258717Savg 190211931Smmstatic int table_cmp(const ASN1_STRING_TABLE *a, const ASN1_STRING_TABLE *b) 191211931Smm{ 192258717Savg return a->nid - b->nid; 193258717Savg} 194258717Savg 195211931SmmIMPLEMENT_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table); 196258717Savg 197258717SavgASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid) 198258717Savg{ 199258717Savg int idx; 200211931Smm ASN1_STRING_TABLE *ttmp; 201211931Smm ASN1_STRING_TABLE fnd; 202258717Savg fnd.nid = nid; 203258717Savg ttmp = OBJ_bsearch_table(&fnd, tbl_standard, 204258717Savg sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE)); 205258717Savg if(ttmp) return ttmp; 206258717Savg if(!stable) return NULL; 207258717Savg idx = sk_ASN1_STRING_TABLE_find(stable, &fnd); 208258717Savg if(idx < 0) return NULL; 209258717Savg return sk_ASN1_STRING_TABLE_value(stable, idx); 210258717Savg} 211258717Savg 212258717Savgint ASN1_STRING_TABLE_add(int nid, 213258717Savg long minsize, long maxsize, unsigned long mask, 214258717Savg unsigned long flags) 215258717Savg{ 216258717Savg ASN1_STRING_TABLE *tmp; 217258717Savg char new_nid = 0; 218269118Sdelphij flags &= ~STABLE_FLAGS_MALLOC; 219258717Savg if(!stable) stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp); 220269118Sdelphij if(!stable) { 221269118Sdelphij ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD, ERR_R_MALLOC_FAILURE); 222269118Sdelphij return 0; 223269118Sdelphij } 224258717Savg if(!(tmp = ASN1_STRING_TABLE_get(nid))) { 225269118Sdelphij tmp = OPENSSL_malloc(sizeof(ASN1_STRING_TABLE)); 226269118Sdelphij if(!tmp) { 227269118Sdelphij ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD, 228269118Sdelphij ERR_R_MALLOC_FAILURE); 229269118Sdelphij return 0; 230269118Sdelphij } 231269118Sdelphij tmp->flags = flags | STABLE_FLAGS_MALLOC; 232258717Savg tmp->nid = nid; 233258717Savg new_nid = 1; 234269118Sdelphij } else tmp->flags = (tmp->flags & STABLE_FLAGS_MALLOC) | flags; 235269118Sdelphij if(minsize != -1) tmp->minsize = minsize; 236269118Sdelphij if(maxsize != -1) tmp->maxsize = maxsize; 237269118Sdelphij tmp->mask = mask; 238269118Sdelphij if(new_nid) sk_ASN1_STRING_TABLE_push(stable, tmp); 239269118Sdelphij return 1; 240269118Sdelphij} 241321529Smav 242332525Smavvoid ASN1_STRING_TABLE_cleanup(void) 243332525Smav{ 244332525Smav STACK_OF(ASN1_STRING_TABLE) *tmp; 245332525Smav tmp = stable; 246332525Smav if(!tmp) return; 247321529Smav stable = NULL; 248321529Smav sk_ASN1_STRING_TABLE_pop_free(tmp, st_free); 249321529Smav} 250269118Sdelphij 251269118Sdelphijstatic void st_free(ASN1_STRING_TABLE *tbl) 252321529Smav{ 253321529Smav if(tbl->flags & STABLE_FLAGS_MALLOC) OPENSSL_free(tbl); 254321529Smav} 255321529Smav 256321529Smav 257321529SmavIMPLEMENT_STACK_OF(ASN1_STRING_TABLE) 258321529Smav 259321529Smav#ifdef STRING_TABLE_TEST 260321529Smav 261321529Smavmain() 262321529Smav{ 263321529Smav ASN1_STRING_TABLE *tmp; 264321529Smav int i, last_nid = -1; 265321529Smav 266321529Smav for (tmp = tbl_standard, i = 0; 267321529Smav i < sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE); i++, tmp++) 268321529Smav { 269321529Smav if (tmp->nid < last_nid) 270321529Smav { 271321529Smav last_nid = 0; 272321529Smav break; 273321529Smav } 274321529Smav last_nid = tmp->nid; 275321529Smav } 276332547Smav 277332525Smav if (last_nid != 0) 278339105Smav { 279339105Smav printf("Table order OK\n"); 280321529Smav exit(0); 281321529Smav } 282321529Smav 283321529Smav for (tmp = tbl_standard, i = 0; 284168404Spjd i < sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE); i++, tmp++) 285168404Spjd printf("Index %d, NID %d, Name=%s\n", i, tmp->nid, 286168404Spjd OBJ_nid2ln(tmp->nid)); 287168404Spjd 288168404Spjd} 289258717Savg 290168404Spjd#endif 291168404Spjd