159191Skris/* a_strnid.c */ 2194206Ssimon/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 359191Skris * project 1999. 459191Skris */ 559191Skris/* ==================================================================== 659191Skris * Copyright (c) 1999 The OpenSSL Project. All rights reserved. 759191Skris * 859191Skris * Redistribution and use in source and binary forms, with or without 959191Skris * modification, are permitted provided that the following conditions 1059191Skris * are met: 1159191Skris * 1259191Skris * 1. Redistributions of source code must retain the above copyright 1359191Skris * notice, this list of conditions and the following disclaimer. 1459191Skris * 1559191Skris * 2. Redistributions in binary form must reproduce the above copyright 1659191Skris * notice, this list of conditions and the following disclaimer in 1759191Skris * the documentation and/or other materials provided with the 1859191Skris * distribution. 1959191Skris * 2059191Skris * 3. All advertising materials mentioning features or use of this 2159191Skris * software must display the following acknowledgment: 2259191Skris * "This product includes software developed by the OpenSSL Project 2359191Skris * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 2459191Skris * 2559191Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 2659191Skris * endorse or promote products derived from this software without 2759191Skris * prior written permission. For written permission, please contact 2859191Skris * licensing@OpenSSL.org. 2959191Skris * 3059191Skris * 5. Products derived from this software may not be called "OpenSSL" 3159191Skris * nor may "OpenSSL" appear in their names without prior written 3259191Skris * permission of the OpenSSL Project. 3359191Skris * 3459191Skris * 6. Redistributions of any form whatsoever must retain the following 3559191Skris * acknowledgment: 3659191Skris * "This product includes software developed by the OpenSSL Project 3759191Skris * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 3859191Skris * 3959191Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 4059191Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4159191Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 4259191Skris * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 4359191Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 4459191Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 4559191Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 4659191Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4759191Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 4859191Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 4959191Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 5059191Skris * OF THE POSSIBILITY OF SUCH DAMAGE. 5159191Skris * ==================================================================== 5259191Skris * 5359191Skris * This product includes cryptographic software written by Eric Young 5459191Skris * (eay@cryptsoft.com). This product includes software written by Tim 5559191Skris * Hudson (tjh@cryptsoft.com). 5659191Skris * 5759191Skris */ 5859191Skris 5959191Skris#include <stdio.h> 6059191Skris#include <ctype.h> 6159191Skris#include "cryptlib.h" 6259191Skris#include <openssl/asn1.h> 6359191Skris#include <openssl/objects.h> 6459191Skris 6559191Skris 6659191Skrisstatic STACK_OF(ASN1_STRING_TABLE) *stable = NULL; 6759191Skrisstatic void st_free(ASN1_STRING_TABLE *tbl); 6868651Skrisstatic int sk_table_cmp(const ASN1_STRING_TABLE * const *a, 6968651Skris const ASN1_STRING_TABLE * const *b); 7059191Skris 7159191Skris 7259191Skris/* This is the global mask for the mbstring functions: this is use to 7359191Skris * mask out certain types (such as BMPString and UTF8String) because 7459191Skris * certain software (e.g. Netscape) has problems with them. 7559191Skris */ 7659191Skris 77279264Sdelphijstatic unsigned long global_mask = B_ASN1_UTF8STRING; 7859191Skris 7959191Skrisvoid ASN1_STRING_set_default_mask(unsigned long mask) 8059191Skris{ 8159191Skris global_mask = mask; 8259191Skris} 8359191Skris 8459191Skrisunsigned long ASN1_STRING_get_default_mask(void) 8559191Skris{ 8659191Skris return global_mask; 8759191Skris} 8859191Skris 8959191Skris/* This function sets the default to various "flavours" of configuration. 9059191Skris * based on an ASCII string. Currently this is: 9159191Skris * MASK:XXXX : a numerical mask value. 9259191Skris * nobmp : Don't use BMPStrings (just Printable, T61). 9359191Skris * pkix : PKIX recommendation in RFC2459. 9459191Skris * utf8only : only use UTF8Strings (RFC2459 recommendation for 2004). 9559191Skris * default: the default value, Printable, T61, BMP. 9659191Skris */ 9759191Skris 98237657Sjkimint ASN1_STRING_set_default_mask_asc(const char *p) 9959191Skris{ 10059191Skris unsigned long mask; 10159191Skris char *end; 10259191Skris if(!strncmp(p, "MASK:", 5)) { 10359191Skris if(!p[5]) return 0; 10459191Skris mask = strtoul(p + 5, &end, 0); 10559191Skris if(*end) return 0; 10659191Skris } else if(!strcmp(p, "nombstr")) 107109998Smarkm mask = ~((unsigned long)(B_ASN1_BMPSTRING|B_ASN1_UTF8STRING)); 10859191Skris else if(!strcmp(p, "pkix")) 10989837Skris mask = ~((unsigned long)B_ASN1_T61STRING); 11059191Skris else if(!strcmp(p, "utf8only")) mask = B_ASN1_UTF8STRING; 11159191Skris else if(!strcmp(p, "default")) 11259191Skris mask = 0xFFFFFFFFL; 11359191Skris else return 0; 11459191Skris ASN1_STRING_set_default_mask(mask); 11559191Skris return 1; 11659191Skris} 11759191Skris 11859191Skris/* The following function generates an ASN1_STRING based on limits in a table. 11959191Skris * Frequently the types and length of an ASN1_STRING are restricted by a 12059191Skris * corresponding OID. For example certificates and certificate requests. 12159191Skris */ 12259191Skris 12359191SkrisASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, const unsigned char *in, 12459191Skris int inlen, int inform, int nid) 12559191Skris{ 12659191Skris ASN1_STRING_TABLE *tbl; 12759191Skris ASN1_STRING *str = NULL; 12859191Skris unsigned long mask; 12959191Skris int ret; 13059191Skris if(!out) out = &str; 13159191Skris tbl = ASN1_STRING_TABLE_get(nid); 13259191Skris if(tbl) { 13359191Skris mask = tbl->mask; 13459191Skris if(!(tbl->flags & STABLE_NO_MASK)) mask &= global_mask; 13572613Skris ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask, 13659191Skris tbl->minsize, tbl->maxsize); 13759191Skris } else ret = ASN1_mbstring_copy(out, in, inlen, inform, DIRSTRING_TYPE & global_mask); 13859191Skris if(ret <= 0) return NULL; 13959191Skris return *out; 14059191Skris} 14159191Skris 14259191Skris/* Now the tables and helper functions for the string table: 14359191Skris */ 14459191Skris 145120631Snectar/* size limits: this stuff is taken straight from RFC3280 */ 14659191Skris 14759191Skris#define ub_name 32768 14859191Skris#define ub_common_name 64 14959191Skris#define ub_locality_name 128 15059191Skris#define ub_state_name 128 15159191Skris#define ub_organization_name 64 15259191Skris#define ub_organization_unit_name 64 15359191Skris#define ub_title 64 15459191Skris#define ub_email_address 128 155120631Snectar#define ub_serial_number 64 15659191Skris 157120631Snectar 15859191Skris/* This table must be kept in NID order */ 15959191Skris 160238405Sjkimstatic const ASN1_STRING_TABLE tbl_standard[] = { 16159191Skris{NID_commonName, 1, ub_common_name, DIRSTRING_TYPE, 0}, 16259191Skris{NID_countryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK}, 16359191Skris{NID_localityName, 1, ub_locality_name, DIRSTRING_TYPE, 0}, 16459191Skris{NID_stateOrProvinceName, 1, ub_state_name, DIRSTRING_TYPE, 0}, 16559191Skris{NID_organizationName, 1, ub_organization_name, DIRSTRING_TYPE, 0}, 16659191Skris{NID_organizationalUnitName, 1, ub_organization_unit_name, DIRSTRING_TYPE, 0}, 16759191Skris{NID_pkcs9_emailAddress, 1, ub_email_address, B_ASN1_IA5STRING, STABLE_NO_MASK}, 16859191Skris{NID_pkcs9_unstructuredName, 1, -1, PKCS9STRING_TYPE, 0}, 16959191Skris{NID_pkcs9_challengePassword, 1, -1, PKCS9STRING_TYPE, 0}, 17059191Skris{NID_pkcs9_unstructuredAddress, 1, -1, DIRSTRING_TYPE, 0}, 17159191Skris{NID_givenName, 1, ub_name, DIRSTRING_TYPE, 0}, 17259191Skris{NID_surname, 1, ub_name, DIRSTRING_TYPE, 0}, 17359191Skris{NID_initials, 1, ub_name, DIRSTRING_TYPE, 0}, 174120631Snectar{NID_serialNumber, 1, ub_serial_number, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK}, 175109998Smarkm{NID_friendlyName, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK}, 17659191Skris{NID_name, 1, ub_name, DIRSTRING_TYPE, 0}, 177109998Smarkm{NID_dnQualifier, -1, -1, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK}, 178120631Snectar{NID_domainComponent, 1, -1, B_ASN1_IA5STRING, STABLE_NO_MASK}, 179109998Smarkm{NID_ms_csp_name, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK} 18059191Skris}; 18159191Skris 18268651Skrisstatic int sk_table_cmp(const ASN1_STRING_TABLE * const *a, 18368651Skris const ASN1_STRING_TABLE * const *b) 18459191Skris{ 18559191Skris return (*a)->nid - (*b)->nid; 18659191Skris} 18759191Skris 188238405SjkimDECLARE_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table); 189238405Sjkim 190238405Sjkimstatic int table_cmp(const ASN1_STRING_TABLE *a, const ASN1_STRING_TABLE *b) 19159191Skris{ 192238405Sjkim return a->nid - b->nid; 19359191Skris} 19459191Skris 195238405SjkimIMPLEMENT_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table); 196238405Sjkim 19759191SkrisASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid) 19859191Skris{ 19959191Skris int idx; 20059191Skris ASN1_STRING_TABLE *ttmp; 20159191Skris ASN1_STRING_TABLE fnd; 20259191Skris fnd.nid = nid; 203238405Sjkim ttmp = OBJ_bsearch_table(&fnd, tbl_standard, 204238405Sjkim sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE)); 20559191Skris if(ttmp) return ttmp; 20659191Skris if(!stable) return NULL; 20759191Skris idx = sk_ASN1_STRING_TABLE_find(stable, &fnd); 20859191Skris if(idx < 0) return NULL; 20959191Skris return sk_ASN1_STRING_TABLE_value(stable, idx); 21059191Skris} 21159191Skris 21259191Skrisint ASN1_STRING_TABLE_add(int nid, 21359191Skris long minsize, long maxsize, unsigned long mask, 21459191Skris unsigned long flags) 21559191Skris{ 21659191Skris ASN1_STRING_TABLE *tmp; 21759191Skris char new_nid = 0; 21859191Skris flags &= ~STABLE_FLAGS_MALLOC; 21959191Skris if(!stable) stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp); 22059191Skris if(!stable) { 22159191Skris ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD, ERR_R_MALLOC_FAILURE); 22259191Skris return 0; 22359191Skris } 22459191Skris if(!(tmp = ASN1_STRING_TABLE_get(nid))) { 22568651Skris tmp = OPENSSL_malloc(sizeof(ASN1_STRING_TABLE)); 22659191Skris if(!tmp) { 22759191Skris ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD, 22859191Skris ERR_R_MALLOC_FAILURE); 22959191Skris return 0; 23059191Skris } 23159191Skris tmp->flags = flags | STABLE_FLAGS_MALLOC; 23259191Skris tmp->nid = nid; 23359191Skris new_nid = 1; 23459191Skris } else tmp->flags = (tmp->flags & STABLE_FLAGS_MALLOC) | flags; 23559191Skris if(minsize != -1) tmp->minsize = minsize; 23659191Skris if(maxsize != -1) tmp->maxsize = maxsize; 23759191Skris tmp->mask = mask; 23859191Skris if(new_nid) sk_ASN1_STRING_TABLE_push(stable, tmp); 23959191Skris return 1; 24059191Skris} 24159191Skris 24259191Skrisvoid ASN1_STRING_TABLE_cleanup(void) 24359191Skris{ 24459191Skris STACK_OF(ASN1_STRING_TABLE) *tmp; 24559191Skris tmp = stable; 24659191Skris if(!tmp) return; 24759191Skris stable = NULL; 24859191Skris sk_ASN1_STRING_TABLE_pop_free(tmp, st_free); 24959191Skris} 25059191Skris 25159191Skrisstatic void st_free(ASN1_STRING_TABLE *tbl) 25259191Skris{ 25368651Skris if(tbl->flags & STABLE_FLAGS_MALLOC) OPENSSL_free(tbl); 25459191Skris} 25559191Skris 256120631Snectar 25759191SkrisIMPLEMENT_STACK_OF(ASN1_STRING_TABLE) 258120631Snectar 259120631Snectar#ifdef STRING_TABLE_TEST 260120631Snectar 261120631Snectarmain() 262120631Snectar{ 263120631Snectar ASN1_STRING_TABLE *tmp; 264120631Snectar int i, last_nid = -1; 265120631Snectar 266120631Snectar for (tmp = tbl_standard, i = 0; 267120631Snectar i < sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE); i++, tmp++) 268120631Snectar { 269120631Snectar if (tmp->nid < last_nid) 270120631Snectar { 271120631Snectar last_nid = 0; 272120631Snectar break; 273120631Snectar } 274120631Snectar last_nid = tmp->nid; 275120631Snectar } 276120631Snectar 277120631Snectar if (last_nid != 0) 278120631Snectar { 279120631Snectar printf("Table order OK\n"); 280120631Snectar exit(0); 281120631Snectar } 282120631Snectar 283120631Snectar for (tmp = tbl_standard, i = 0; 284120631Snectar i < sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE); i++, tmp++) 285120631Snectar printf("Index %d, NID %d, Name=%s\n", i, tmp->nid, 286120631Snectar OBJ_nid2ln(tmp->nid)); 287120631Snectar 288120631Snectar} 289120631Snectar 290120631Snectar#endif 291