Commit f769ce3e authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

More multibyte character support.

Functions to get keys from EVP_PKEY structures.
parent 042a93e4
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@ LIBSRC= a_object.c a_bitstr.c a_utctm.c a_gentm.c a_time.c a_int.c a_octet.c \
	p7_dgst.c p7_s_e.c p7_enc.c p7_lib.c \
	f_int.c f_string.c i2d_dhp.c i2d_dsap.c d2i_dhp.c d2i_dsap.c n_pkey.c \
	f_enum.c a_hdr.c x_pkey.c a_bool.c x_exten.c \
	asn1_par.c asn1_lib.c asn1_err.c a_meth.c a_bytes.c \
	asn1_par.c asn1_lib.c asn1_err.c a_meth.c a_bytes.c a_strnid.c \
	evp_asn1.c asn_pack.c p5_pbe.c p5_pbev2.c p8_pkey.c
LIBOBJ= a_object.o a_bitstr.o a_utctm.o a_gentm.o a_time.o a_int.o a_octet.o \
	a_print.o a_type.o a_set.o a_dup.o a_d2i_fp.o a_i2d_fp.o a_bmp.o \
@@ -50,7 +50,7 @@ LIBOBJ= a_object.o a_bitstr.o a_utctm.o a_gentm.o a_time.o a_int.o a_octet.o \
	p7_dgst.o p7_s_e.o p7_enc.o p7_lib.o \
	f_int.o f_string.o i2d_dhp.o i2d_dsap.o d2i_dhp.o d2i_dsap.o n_pkey.o \
	f_enum.o a_hdr.o x_pkey.o a_bool.o x_exten.o \
	asn1_par.o asn1_lib.o asn1_err.o a_meth.o a_bytes.o \
	asn1_par.o asn1_lib.o asn1_err.o a_meth.o a_bytes.o a_strnid.o \
	evp_asn1.o asn_pack.o p5_pbe.o p5_pbev2.o p8_pkey.o

SRC= $(LIBSRC)
@@ -268,6 +268,13 @@ a_sign.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h
a_sign.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
a_sign.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
a_sign.o: ../cryptlib.h
a_strnid.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h
a_strnid.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h
a_strnid.o: ../../include/openssl/crypto.h ../../include/openssl/e_os.h
a_strnid.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h
a_strnid.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
a_strnid.o: ../../include/openssl/opensslv.h ../../include/openssl/safestack.h
a_strnid.o: ../../include/openssl/stack.h ../cryptlib.h
a_time.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h
a_time.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h
a_time.o: ../../include/openssl/crypto.h ../../include/openssl/e_os.h
+65 −8
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@
 */

#include <stdio.h>
#include <ctype.h>
#include "cryptlib.h"
#include <openssl/asn1.h>

@@ -71,15 +72,42 @@ static int cpy_univ(unsigned long value, void *arg);
static int cpy_utf8(unsigned long value, void *arg);
static int is_printable(unsigned long value);

/* This function takes a string in UTF8, ASCII or multibyte form and
/* This is the default mask for the mbstring functions: it is designed
 * to be a "safe" DirectoryString. Netscape messenger crashes when it
 * receives a certificate containing a BMPString so by default we don't
 * use them unless we have to.
 */

static long dirstring_mask = B_ASN1_PRINTABLESTRING
				| B_ASN1_T61STRING | B_ASN1_BMPSTRING;

void ASN1_STRING_set_default_mask(unsigned long mask)
{
	dirstring_mask = mask;
}

unsigned long ASN1_STRING_get_default_mask(void)
{
	return dirstring_mask;
}

/* These functions take a string in UTF8, ASCII or multibyte form and
 * a mask of permissible ASN1 string types. It then works out the minimal
 * type (using the order Printable < IA5 < T61 < BMP < Universal < UTF8)
 * and creates a string of the correct type with the supplied data.
 * Yes this is horrible: it has to be :-(
 * The 'ncopy' form checks minimum and maximum size limits too.
 */

int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
					int inform, unsigned long mask)
{
	return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0);
}

int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
					int inform, unsigned long mask, 
					long minsize, long maxsize)
{
	int str_type;
	int ret;
@@ -87,8 +115,10 @@ int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
	ASN1_STRING *dest;
	unsigned char *p;
	int nchar;
	int (*cpyfunc)(unsigned long value, void *in_) = NULL;
	unsigned char strbuf[32];
	int (*cpyfunc)(unsigned long,void *) = NULL;
	if(len == -1) len = strlen((const char *)in);
	if(!mask) mask = dirstring_mask;

	/* First do a string check and work out the number of characters */
	switch(inform) {
@@ -113,6 +143,7 @@ int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,

		case MBSTRING_UTF8:
		nchar = 0;
		/* This counts the characters and does utf8 syntax checking */
		ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar);
		if(ret < 0) {
			ASN1err(ASN1_F_ASN1_MBSTRING_COPY,
@@ -130,12 +161,27 @@ int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
		return -1;
	}

	if(minsize && (nchar < minsize)) {
		ASN1err(ASN1_F_ASN1_MBSTRING_COPY, ASN1_R_STRING_TOO_SHORT);
		sprintf(strbuf, "%ld", minsize);
		ERR_add_error_data(2, "minsize=", strbuf);
		return -1;
	}

	if(maxsize && (nchar > maxsize)) {
		ASN1err(ASN1_F_ASN1_MBSTRING_COPY, ASN1_R_STRING_TOO_LONG);
		sprintf(strbuf, "%ld", maxsize);
		ERR_add_error_data(2, "maxsize=", strbuf);
		return -1;
	}

	/* Now work out minimal type (if any) */
	if(traverse_string(in, len, inform, type_str, &mask) < 0) {
		ASN1err(ASN1_F_ASN1_MBSTRING_COPY, ASN1_R_ILLEGAL_CHARACTERS);
		return -1;
	}


	/* Now work out output format and string type */
	outform = MBSTRING_ASC;
	if(mask & B_ASN1_PRINTABLESTRING) str_type = V_ASN1_PRINTABLESTRING;
@@ -152,15 +198,26 @@ int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
		outform = MBSTRING_UTF8;
	}
	if(!out) return str_type;
	if(!(dest = ASN1_STRING_type_new(str_type))) {
		ASN1err(ASN1_F_ASN1_MBSTRING_COPY, ERR_R_MALLOC_FAILURE);
	if(*out) {
		dest = *out;
		if(dest->data) {
			dest->length = 0;
			Free(dest->data);
			dest->data = NULL;
		}
		dest->type = str_type;
	} else {
		dest = ASN1_STRING_type_new(str_type);
		if(!dest) {
			ASN1err(ASN1_F_ASN1_MBSTRING_COPY,
							ERR_R_MALLOC_FAILURE);
			return -1;
		}
		*out = dest;
	}
	/* If both the same type just copy across */
	if(inform == outform) {
		if(!ASN1_STRING_set(dest, in, len)) {
			ASN1_STRING_free(dest);
			ASN1err(ASN1_F_ASN1_MBSTRING_COPY,ERR_R_MALLOC_FAILURE);
			return -1;
		}

crypto/asn1/a_strnid.c

0 → 100644
+200 −0
Original line number Diff line number Diff line
/* a_strnid.c */
/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
 * project 1999.
 */
/* ====================================================================
 * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. All advertising materials mentioning features or use of this
 *    software must display the following acknowledgment:
 *    "This product includes software developed by the OpenSSL Project
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
 *
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
 *    endorse or promote products derived from this software without
 *    prior written permission. For written permission, please contact
 *    licensing@OpenSSL.org.
 *
 * 5. Products derived from this software may not be called "OpenSSL"
 *    nor may "OpenSSL" appear in their names without prior written
 *    permission of the OpenSSL Project.
 *
 * 6. Redistributions of any form whatsoever must retain the following
 *    acknowledgment:
 *    "This product includes software developed by the OpenSSL Project
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
 *
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 * ====================================================================
 *
 * This product includes cryptographic software written by Eric Young
 * (eay@cryptsoft.com).  This product includes software written by Tim
 * Hudson (tjh@cryptsoft.com).
 *
 */

#include <stdio.h>
#include <ctype.h>
#include "cryptlib.h"
#include <openssl/asn1.h>
#include <openssl/objects.h>


static STACK_OF(ASN1_STRING_TABLE) *stable = NULL;
static void st_free(ASN1_STRING_TABLE *tbl);
static int sk_table_cmp(ASN1_STRING_TABLE **a, ASN1_STRING_TABLE **b);

/* The following function generates an ASN1_STRING based on limits in a table.
 * Frequently the types and length of an ASN1_STRING are restricted by a 
 * corresponding OID. For example certificates and certificate requests.
 */

ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, const unsigned char *in,
					int inlen, int inform, int nid)
{
	ASN1_STRING_TABLE *tbl;
	ASN1_STRING *str = NULL;
	int ret;
	if(!out) out = &str;
	if(!stable) ASN1_STRING_TABLE_add_standard();
	tbl = ASN1_STRING_TABLE_get(nid);
	if(tbl) ret = ASN1_mbstring_ncopy(out, in, inlen, inform, tbl->mask,
					tbl->minsize, tbl->maxsize);
	else ret = ASN1_mbstring_copy(out, in, inlen, inform, 0);
	if(ret <= 0) return NULL;
	return str;
}

/* Now the tables and helper functions for the string table:
 */

/* size limits: this stuff is taken straight from RFC2459 */

#define ub_name				32768
#define ub_common_name			64
#define ub_locality_name		128
#define ub_state_name			128
#define ub_organization_name		64
#define ub_organization_unit_name	64
#define ub_title			64
#define ub_email_address		128

static ASN1_STRING_TABLE tbl_standard[] = {
{NID_name,			1, ub_name, 0, 0},
{NID_surname,			1, ub_name, 0, 0},
{NID_givenName,			1, ub_name, 0, 0},
{NID_initials,			1, ub_name, 0, 0},
{NID_commonName,		1, ub_common_name, 0, 0},
{NID_localityName,		1, ub_locality_name, 0, 0},
{NID_stateOrProvinceName,	1, ub_state_name, 0, 0},
{NID_organizationName,		1, ub_organization_name, 0, 0},
{NID_organizationalUnitName,	1, ub_organization_unit_name, 0, 0},
{NID_dnQualifier,		-1, -1, B_ASN1_PRINTABLESTRING, 0},
{NID_countryName,		2, 2, B_ASN1_PRINTABLESTRING, 0},
{NID_pkcs9_emailAddress,	1, ub_email_address, B_ASN1_IA5STRING, 0},
{NID_undef, 0, 0, 0, 0}
};

int ASN1_STRING_TABLE_add_standard(void)
{
	static int done = 0;
	ASN1_STRING_TABLE *tmp;
	if(done) return 1;
	if(!stable) stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
	if(!stable) {
		ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD_STANDARD,
						ERR_R_MALLOC_FAILURE);
		return 0;
	}
	for(tmp = tbl_standard; tmp->nid != NID_undef; tmp++) {
		if(!sk_ASN1_STRING_TABLE_push(stable, tmp)) {
			ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD_STANDARD,
							ERR_R_MALLOC_FAILURE);
			return 0;
		}
	}
	return 1;
}

static int sk_table_cmp(ASN1_STRING_TABLE **a, ASN1_STRING_TABLE **b)
{
	return (*a)->nid - (*b)->nid;
}

ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid)
{
	int idx;
	ASN1_STRING_TABLE fnd;
	fnd.nid = nid;
	idx = sk_ASN1_STRING_TABLE_find(stable, &fnd);
	if(idx < 0) return NULL;
	return sk_ASN1_STRING_TABLE_value(stable, idx);
}
	
int ASN1_STRING_TABLE_add(int nid,
		 long minsize, long maxsize, unsigned long mask,
				unsigned long flags)
{
	ASN1_STRING_TABLE *tmp;
	char new_nid = 0;
	if(!stable) stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
	if(!stable) {
		ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD, ERR_R_MALLOC_FAILURE);
		return 0;
	}
	if(!(tmp = ASN1_STRING_TABLE_get(nid))) {
		tmp = Malloc(sizeof(ASN1_STRING_TABLE));
		if(!tmp) {
			ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD,
							ERR_R_MALLOC_FAILURE);
			return 0;
		}
		tmp->flags = STABLE_FLAGS_MALLOC;
		tmp->nid = nid;
		new_nid = 1;
	}
	if(minsize != -1) tmp->minsize = minsize;
	if(maxsize != -1) tmp->maxsize = maxsize;
	tmp->mask = mask;
	tmp->flags = flags & ~STABLE_FLAGS_MALLOC;
	if(new_nid) sk_ASN1_STRING_TABLE_push(stable, tmp);
	return 1;
}

void ASN1_STRING_TABLE_cleanup(void)
{
	STACK_OF(ASN1_STRING_TABLE) *tmp;
	tmp = stable;
	stable = NULL;
	sk_ASN1_STRING_TABLE_pop_free(tmp, st_free);
}

static void st_free(ASN1_STRING_TABLE *tbl)
{
	if(tbl->flags & STABLE_FLAGS_MALLOC) Free(tbl);
}

IMPLEMENT_STACK_OF(ASN1_STRING_TABLE)
+43 −4
Original line number Diff line number Diff line
@@ -130,10 +130,11 @@ extern "C" {
#define B_ASN1_UTF8STRING	0x2000

/* For use with ASN1_mbstring_copy() */
#define MBSTRING_ASC		1
#define MBSTRING_BMP		2
#define MBSTRING_UNIV		3
#define MBSTRING_UTF8		4
#define MBSTRING_FLAG		0x1000
#define MBSTRING_ASC		(MBSTRING_FLAG|1)
#define MBSTRING_BMP		(MBSTRING_FLAG|2)
#define MBSTRING_UNIV		(MBSTRING_FLAG|3)
#define MBSTRING_UTF8		(MBSTRING_FLAG|4)

#define DECLARE_ASN1_SET_OF(type) \
int i2d_ASN1_SET_OF_##type(STACK_OF(type) *a,unsigned char **pp, \
@@ -206,6 +207,29 @@ typedef struct asn1_string_st
	long flags;
	} ASN1_STRING;

#define STABLE_FLAGS_MALLOC	0x01

typedef struct asn1_string_table_st {
	int nid;
	long minsize;
	long maxsize;
	unsigned long mask;
	unsigned long flags;
} ASN1_STRING_TABLE;

DECLARE_STACK_OF(ASN1_STRING_TABLE)

/* size limits: this stuff is taken straight from RFC2459 */

#define ub_name				32768
#define ub_common_name			64
#define ub_locality_name		128
#define ub_state_name			128
#define ub_organization_name		64
#define ub_organization_unit_name	64
#define ub_title			64
#define ub_email_address		128

#ifndef DEBUG
#define ASN1_INTEGER		ASN1_STRING
#define ASN1_ENUMERATED		ASN1_STRING
@@ -718,8 +742,20 @@ unsigned char *ASN1_seq_pack(STACK *safes, int (*i2d)(), unsigned char **buf,
								 int *len );
void *ASN1_unpack_string(ASN1_STRING *oct, char *(*d2i)());
ASN1_STRING *ASN1_pack_string(void *obj, int (*i2d)(), ASN1_OCTET_STRING **oct);

void ASN1_STRING_set_default_mask(unsigned long mask);
unsigned long ASN1_STRING_get_default_mask(void);
int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
					int inform, unsigned long mask);
int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
					int inform, unsigned long mask, 
					long minsize, long maxsize);

ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, 
		const unsigned char *in, int inlen, int inform, int nid);
int ASN1_STRING_TABLE_add_standard(void);
ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid);
void ASN1_STRING_TABLE_cleanup(void);

/* BEGIN ERROR CODES */
/* The following lines are auto generated by the script mkerr.pl. Any changes
@@ -754,6 +790,8 @@ int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
#define ASN1_F_ASN1_SEQ_UNPACK				 247
#define ASN1_F_ASN1_SIGN				 114
#define ASN1_F_ASN1_STRING_NEW				 115
#define ASN1_F_ASN1_STRING_TABLE_ADD			 283
#define ASN1_F_ASN1_STRING_TABLE_ADD_STANDARD		 284
#define ASN1_F_ASN1_STRING_TYPE_NEW			 116
#define ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING		 117
#define ASN1_F_ASN1_TYPE_GET_OCTETSTRING		 118
@@ -959,6 +997,7 @@ int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
#define ASN1_R_PRIVATE_KEY_HEADER_MISSING		 131
#define ASN1_R_SECOND_NUMBER_TOO_LARGE			 132
#define ASN1_R_SHORT_LINE				 133
#define ASN1_R_STRING_TOO_LONG				 163
#define ASN1_R_STRING_TOO_SHORT				 134
#define ASN1_R_TAG_VALUE_TOO_HIGH			 135
#define ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 136
+3 −0
Original line number Diff line number Diff line
@@ -90,6 +90,8 @@ static ERR_STRING_DATA ASN1_str_functs[]=
{ERR_PACK(0,ASN1_F_ASN1_SEQ_UNPACK,0),	"ASN1_seq_unpack"},
{ERR_PACK(0,ASN1_F_ASN1_SIGN,0),	"ASN1_sign"},
{ERR_PACK(0,ASN1_F_ASN1_STRING_NEW,0),	"ASN1_STRING_new"},
{ERR_PACK(0,ASN1_F_ASN1_STRING_TABLE_ADD,0),	"ASN1_STRING_TABLE_ADD"},
{ERR_PACK(0,ASN1_F_ASN1_STRING_TABLE_ADD_STANDARD,0),	"ASN1_STRING_TABLE_add_standard"},
{ERR_PACK(0,ASN1_F_ASN1_STRING_TYPE_NEW,0),	"ASN1_STRING_type_new"},
{ERR_PACK(0,ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING,0),	"ASN1_TYPE_get_int_octetstring"},
{ERR_PACK(0,ASN1_F_ASN1_TYPE_GET_OCTETSTRING,0),	"ASN1_TYPE_get_octetstring"},
@@ -298,6 +300,7 @@ static ERR_STRING_DATA ASN1_str_reasons[]=
{ASN1_R_PRIVATE_KEY_HEADER_MISSING       ,"private key header missing"},
{ASN1_R_SECOND_NUMBER_TOO_LARGE          ,"second number too large"},
{ASN1_R_SHORT_LINE                       ,"short line"},
{ASN1_R_STRING_TOO_LONG                  ,"string too long"},
{ASN1_R_STRING_TOO_SHORT                 ,"string too short"},
{ASN1_R_TAG_VALUE_TOO_HIGH               ,"tag value too high"},
{ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD,"the asn1 object identifier is not known for this md"},
Loading