195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * All rights reserved. 395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This package is an SSL implementation written 595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * by Eric Young (eay@cryptsoft.com). 695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * The implementation was written so as to conform with Netscapes SSL. 795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This library is free for commercial and non-commercial use as long as 995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * the following conditions are aheared to. The following conditions 1095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * apply to all code found in this distribution, be it the RC4, RSA, 1195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * included with this distribution is covered by the same copyright terms 1395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * except that the holder is Tim Hudson (tjh@cryptsoft.com). 1495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 1595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Copyright remains Eric Young's, and as such any Copyright notices in 1695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * the code are not to be removed. 1795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * If this package is used in a product, Eric Young should be given attribution 1895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * as the author of the parts of the library used. 1995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This can be in the form of a textual message at program startup or 2095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * in documentation (online or textual) provided with the package. 2195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 2295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Redistribution and use in source and binary forms, with or without 2395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * modification, are permitted provided that the following conditions 2495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * are met: 2595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 1. Redistributions of source code must retain the copyright 2695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * notice, this list of conditions and the following disclaimer. 2795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 2. Redistributions in binary form must reproduce the above copyright 2895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * notice, this list of conditions and the following disclaimer in the 2995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * documentation and/or other materials provided with the distribution. 3095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 3. All advertising materials mentioning features or use of this software 3195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * must display the following acknowledgement: 3295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * "This product includes cryptographic software written by 3395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Eric Young (eay@cryptsoft.com)" 3495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * The word 'cryptographic' can be left out if the rouines from the library 3595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * being used are not cryptographic related :-). 3695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 4. If you include any Windows specific code (or a derivative thereof) from 3795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * the apps directory (application code) you must include an acknowledgement: 3895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 3995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 4095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 4995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * SUCH DAMAGE. 5195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 5295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * The licence and distribution terms for any publically available version or 5395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * derivative of this code cannot be changed. i.e. this code cannot simply be 5495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * copied and put under another distribution licence 5595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * [including the GNU Public Licence.] */ 5695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 5795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/asn1.h> 5895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 5995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/err.h> 6095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/mem.h> 6195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 6295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 6395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int traverse_string(const unsigned char *p, int len, int inform, 6495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int (*rfunc)(unsigned long value, void *in), void *arg); 6595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int in_utf8(unsigned long value, void *arg); 6695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int out_utf8(unsigned long value, void *arg); 6795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int type_str(unsigned long value, void *arg); 6895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int cpy_asc(unsigned long value, void *arg); 6995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int cpy_bmp(unsigned long value, void *arg); 7095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int cpy_univ(unsigned long value, void *arg); 7195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int cpy_utf8(unsigned long value, void *arg); 7295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int is_printable(unsigned long value); 7395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 7495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* These functions take a string in UTF8, ASCII or multibyte form and 7595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * a mask of permissible ASN1 string types. It then works out the minimal 7695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * type (using the order Printable < IA5 < T61 < BMP < Universal < UTF8) 7795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * and creates a string of the correct type with the supplied data. 7895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Yes this is horrible: it has to be :-( 7995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * The 'ncopy' form checks minimum and maximum size limits too. 8095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */ 8195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 8295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len, 8395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int inform, unsigned long mask) 8495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley{ 8595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0); 8695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 8795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 8895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, 8995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int inform, unsigned long mask, 9095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley long minsize, long maxsize) 9195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley{ 9295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int str_type; 9395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int ret; 9495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley char free_out; 9595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int outform, outlen = 0; 9695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ASN1_STRING *dest; 9795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley unsigned char *p; 9895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int nchar; 9995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley char strbuf[32]; 10095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int (*cpyfunc)(unsigned long,void *) = NULL; 10195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if(len == -1) len = strlen((const char *)in); 10295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if(!mask) mask = DIRSTRING_TYPE; 10395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 10495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley /* First do a string check and work out the number of characters */ 10595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley switch(inform) { 10695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 10795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley case MBSTRING_BMP: 10895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if(len & 1) { 10995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy, ASN1_R_INVALID_BMPSTRING_LENGTH); 11095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return -1; 11195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 11295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley nchar = len >> 1; 11395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley break; 11495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 11595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley case MBSTRING_UNIV: 11695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if(len & 3) { 11795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH); 11895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return -1; 11995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 12095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley nchar = len >> 2; 12195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley break; 12295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 12395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley case MBSTRING_UTF8: 12495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley nchar = 0; 12595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley /* This counts the characters and does utf8 syntax checking */ 12695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar); 12795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if(ret < 0) { 12895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy, ASN1_R_INVALID_UTF8STRING); 12995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return -1; 13095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 13195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley break; 13295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 13395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley case MBSTRING_ASC: 13495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley nchar = len; 13595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley break; 13695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 13795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley default: 13895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy, ASN1_R_UNKNOWN_FORMAT); 13995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return -1; 14095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 14195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 14295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if((minsize > 0) && (nchar < minsize)) { 14395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy, ASN1_R_STRING_TOO_SHORT); 14495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley BIO_snprintf(strbuf, sizeof strbuf, "%ld", minsize); 14595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ERR_add_error_data(2, "minsize=", strbuf); 14695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return -1; 14795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 14895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 14995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if((maxsize > 0) && (nchar > maxsize)) { 15095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy, ASN1_R_STRING_TOO_LONG); 15195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley BIO_snprintf(strbuf, sizeof strbuf, "%ld", maxsize); 15295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ERR_add_error_data(2, "maxsize=", strbuf); 15395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return -1; 15495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 15595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 15695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley /* Now work out minimal type (if any) */ 15795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if(traverse_string(in, len, inform, type_str, &mask) < 0) { 15895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy, ASN1_R_ILLEGAL_CHARACTERS); 15995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return -1; 16095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 16195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 16295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 16395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley /* Now work out output format and string type */ 16495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley outform = MBSTRING_ASC; 16595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if(mask & B_ASN1_PRINTABLESTRING) str_type = V_ASN1_PRINTABLESTRING; 16695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley else if(mask & B_ASN1_IA5STRING) str_type = V_ASN1_IA5STRING; 16795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley else if(mask & B_ASN1_T61STRING) str_type = V_ASN1_T61STRING; 16895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley else if(mask & B_ASN1_BMPSTRING) { 16995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley str_type = V_ASN1_BMPSTRING; 17095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley outform = MBSTRING_BMP; 17195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } else if(mask & B_ASN1_UNIVERSALSTRING) { 17295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley str_type = V_ASN1_UNIVERSALSTRING; 17395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley outform = MBSTRING_UNIV; 17495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } else { 17595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley str_type = V_ASN1_UTF8STRING; 17695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley outform = MBSTRING_UTF8; 17795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 17895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if(!out) return str_type; 17995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if(*out) { 18095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley free_out = 0; 18195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dest = *out; 18295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if(dest->data) { 18395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dest->length = 0; 18495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_free(dest->data); 18595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dest->data = NULL; 18695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 18795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dest->type = str_type; 18895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } else { 18995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley free_out = 1; 19095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dest = ASN1_STRING_type_new(str_type); 19195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if(!dest) { 19295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy, ERR_R_MALLOC_FAILURE); 19395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return -1; 19495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 19595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *out = dest; 19695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 19795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley /* If both the same type just copy across */ 19895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if(inform == outform) { 19995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if(!ASN1_STRING_set(dest, in, len)) { 20095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy, ERR_R_MALLOC_FAILURE); 20195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return -1; 20295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 20395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return str_type; 20495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 20595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 20695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley /* Work out how much space the destination will need */ 20795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley switch(outform) { 20895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley case MBSTRING_ASC: 20995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley outlen = nchar; 21095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley cpyfunc = cpy_asc; 21195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley break; 21295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 21395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley case MBSTRING_BMP: 21495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley outlen = nchar << 1; 21595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley cpyfunc = cpy_bmp; 21695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley break; 21795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 21895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley case MBSTRING_UNIV: 21995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley outlen = nchar << 2; 22095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley cpyfunc = cpy_univ; 22195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley break; 22295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 22395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley case MBSTRING_UTF8: 22495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley outlen = 0; 22595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley traverse_string(in, len, inform, out_utf8, &outlen); 22695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley cpyfunc = cpy_utf8; 22795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley break; 22895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 22995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if(!(p = OPENSSL_malloc(outlen + 1))) { 23095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if(free_out) ASN1_STRING_free(dest); 23195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy, ERR_R_MALLOC_FAILURE); 23295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return -1; 23395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 23495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dest->length = outlen; 23595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dest->data = p; 23695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley p[outlen] = 0; 23795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley traverse_string(in, len, inform, cpyfunc, &p); 23895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return str_type; 23995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 24095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 24195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* This function traverses a string and passes the value of each character 24295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * to an optional function along with a void * argument. 24395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */ 24495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 24595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int traverse_string(const unsigned char *p, int len, int inform, 24695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int (*rfunc)(unsigned long value, void *in), void *arg) 24795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley{ 24895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley unsigned long value; 24995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int ret; 25095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley while(len) { 25195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if(inform == MBSTRING_ASC) { 25295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley value = *p++; 25395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley len--; 25495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } else if(inform == MBSTRING_BMP) { 25595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley value = *p++ << 8; 25695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley value |= *p++; 25795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley len -= 2; 25895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } else if(inform == MBSTRING_UNIV) { 25995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley value = ((unsigned long)*p++) << 24; 26095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley value |= ((unsigned long)*p++) << 16; 26195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley value |= *p++ << 8; 26295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley value |= *p++; 26395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley len -= 4; 26495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } else { 26595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ret = UTF8_getc(p, len, &value); 26695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if(ret < 0) return -1; 26795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley len -= ret; 26895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley p += ret; 26995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 27095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if(rfunc) { 27195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ret = rfunc(value, arg); 27295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if(ret <= 0) return ret; 27395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 27495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 27595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 27695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 27795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 27895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Various utility functions for traverse_string */ 27995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 28095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Just count number of characters */ 28195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 28295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int in_utf8(unsigned long value, void *arg) 28395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley{ 28495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int *nchar; 28595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley nchar = arg; 28695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley (*nchar)++; 28795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 28895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 28995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 29095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Determine size of output as a UTF8 String */ 29195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 29295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int out_utf8(unsigned long value, void *arg) 29395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley{ 29495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int *outlen; 29595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley outlen = arg; 29695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *outlen += UTF8_putc(NULL, -1, value); 29795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 29895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 29995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 30095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Determine the "type" of a string: check each character against a 30195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * supplied "mask". 30295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */ 30395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 30495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int type_str(unsigned long value, void *arg) 30595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley{ 30695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley unsigned long types; 30795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley types = *((unsigned long *)arg); 30895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if((types & B_ASN1_PRINTABLESTRING) && !is_printable(value)) 30995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley types &= ~B_ASN1_PRINTABLESTRING; 31095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if((types & B_ASN1_IA5STRING) && (value > 127)) 31195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley types &= ~B_ASN1_IA5STRING; 31295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if((types & B_ASN1_T61STRING) && (value > 0xff)) 31395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley types &= ~B_ASN1_T61STRING; 31495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if((types & B_ASN1_BMPSTRING) && (value > 0xffff)) 31595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley types &= ~B_ASN1_BMPSTRING; 31695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if(!types) return -1; 31795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *((unsigned long *)arg) = types; 31895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 31995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 32095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 32195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Copy one byte per character ASCII like strings */ 32295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 32395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int cpy_asc(unsigned long value, void *arg) 32495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley{ 32595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley unsigned char **p, *q; 32695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley p = arg; 32795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley q = *p; 32895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *q = (unsigned char) value; 32995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley (*p)++; 33095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 33195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 33295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 33395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Copy two byte per character BMPStrings */ 33495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 33595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int cpy_bmp(unsigned long value, void *arg) 33695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley{ 33795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley unsigned char **p, *q; 33895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley p = arg; 33995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley q = *p; 34095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *q++ = (unsigned char) ((value >> 8) & 0xff); 34195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *q = (unsigned char) (value & 0xff); 34295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *p += 2; 34395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 34495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 34595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 34695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Copy four byte per character UniversalStrings */ 34795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 34895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int cpy_univ(unsigned long value, void *arg) 34995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley{ 35095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley unsigned char **p, *q; 35195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley p = arg; 35295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley q = *p; 35395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *q++ = (unsigned char) ((value >> 24) & 0xff); 35495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *q++ = (unsigned char) ((value >> 16) & 0xff); 35595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *q++ = (unsigned char) ((value >> 8) & 0xff); 35695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *q = (unsigned char) (value & 0xff); 35795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *p += 4; 35895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 35995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 36095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 36195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Copy to a UTF8String */ 36295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 36395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int cpy_utf8(unsigned long value, void *arg) 36495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley{ 36595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley unsigned char **p; 36695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int ret; 36795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley p = arg; 36895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley /* We already know there is enough room so pass 0xff as the length */ 36995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ret = UTF8_putc(*p, 0xff, value); 37095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *p += ret; 37195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 37295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 37395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 37495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Return 1 if the character is permitted in a PrintableString */ 37595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int is_printable(unsigned long value) 37695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley{ 37795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int ch; 37895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if(value > 0x7f) return 0; 37995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ch = (int) value; 38095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley /* Note: we can't use 'isalnum' because certain accented 38195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * characters may count as alphanumeric in some environments. 38295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */ 38395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if((ch >= 'a') && (ch <= 'z')) return 1; 38495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if((ch >= 'A') && (ch <= 'Z')) return 1; 38595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if((ch >= '0') && (ch <= '9')) return 1; 38695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if ((ch == ' ') || strchr("'()+,-./:=?", ch)) return 1; 38795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 38895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 389