asn1_gen.c revision 9dc0df1bac950d6e491f9a7c7e4888f2b301cb15
/* asn1_gen.c */
/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
* project 2002.
*/
/* ====================================================================
* Copyright (c) 2002 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
* 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 "cryptlib.h"
#define ASN1_GEN_FLAG 0x10000
#define ASN1_FLAG_EXP_MAX 20
/* Input formats */
/* ASCII: default */
#define ASN1_GEN_FORMAT_ASCII 1
/* UTF8 */
#define ASN1_GEN_FORMAT_UTF8 2
/* Hex */
#define ASN1_GEN_FORMAT_HEX 3
/* List of bits */
#define ASN1_GEN_FORMAT_BITLIST 4
struct tag_name_st
{
const char *strnam;
int len;
int tag;
};
typedef struct
{
int exp_tag;
int exp_class;
int exp_constructed;
int exp_pad;
long exp_len;
} tag_exp_type;
typedef struct
{
int imp_tag;
int imp_class;
int utype;
int format;
const char *str;
int exp_count;
} tag_exp_arg;
static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class, int exp_constructed, int exp_pad, int imp_ok);
{
if (!nconf)
}
{
int i, len;
const unsigned char *cpy_start;
unsigned char *p;
const unsigned char *cp;
int cpy_len;
long hdr_len;
int r;
return NULL;
{
if (!cnf)
{
return NULL;
}
}
else
if (!ret)
return NULL;
/* If no tagging return base type */
return ret;
/* Generate the encoding */
/* Set point to start copying for modified encoding */
/* Do we need IMPLICIT tagging? */
{
/* If IMPLICIT we will replace the underlying tag */
/* Skip existing tag+len */
if (r & 0x80)
goto err;
/* Update copy length */
/* For IMPLICIT tagging the length should match the
* original length and constructed flag should be
* consistent.
*/
if (r & 0x1)
{
/* Indefinite length constructed */
hdr_constructed = 2;
hdr_len = 0;
}
else
/* Just retain constructed flag */
/* Work out new length with IMPLICIT tag: ignore constructed
* because it will mess up if indefinite length
*/
}
else
/* Work out length in any EXPLICIT, starting from end */
for(i = 0, etmp = asn1_tags.exp_list + asn1_tags.exp_count - 1; i < asn1_tags.exp_count; i++, etmp--)
{
/* Content length: number of content octets + any padding */
/* Total object length: length including new header */
}
/* Allocate buffer for new encoding */
/* Generate tagged encoding */
p = new_der;
/* Output explicit tags first */
{
*p++ = 0;
}
/* If IMPLICIT, output tag */
/* Copy across original encoding */
/* Obtain new ASN1_TYPE structure */
err:
if (orig_der)
if (new_der)
return ret;
}
{
int i;
int utype;
int vlen = 0;
{
/* Look for the ':' in name value pairs */
if (*p == ':')
{
vstart = p + 1;
break;
}
}
if (utype == -1)
{
return -1;
}
/* If this is not a modifier mark end of string and exit */
if (!(utype & ASN1_GEN_FLAG))
{
/* If no value and not end of string, error */
{
return -1;
}
return 0;
}
switch(utype)
{
case ASN1_GEN_FLAG_IMP:
/* Check for illegal multiple IMPLICIT tagging */
{
return -1;
}
return -1;
break;
case ASN1_GEN_FLAG_EXP:
return -1;
return -1;
break;
case ASN1_GEN_FLAG_SEQWRAP:
return -1;
break;
case ASN1_GEN_FLAG_SETWRAP:
return -1;
break;
case ASN1_GEN_FLAG_BITWRAP:
return -1;
break;
case ASN1_GEN_FLAG_OCTWRAP:
return -1;
break;
case ASN1_GEN_FLAG_FORMAT:
else
{
return -1;
}
break;
}
return 1;
}
{
char erch[2];
long tag_num;
char *eptr;
if (!vstart)
return 0;
/* Check we haven't gone past max length: should be impossible */
return 0;
if (tag_num < 0)
{
return 0;
}
/* If we have non numeric characters, parse them */
if (eptr)
else
vlen = 0;
if (vlen)
{
switch (*eptr)
{
case 'U':
break;
case 'A':
break;
case 'P':
*pclass = V_ASN1_PRIVATE;
break;
case 'C':
break;
default:
erch[1] = 0;
return 0;
break;
}
}
else
return 1;
}
/* Handle multiple types: SET and SEQUENCE */
{
int derlen;
int i, is_set;
sk = sk_ASN1_TYPE_new_null();
if (section)
{
if (!cnf)
goto bad;
if (!sect)
goto bad;
for (i = 0; i < sk_CONF_VALUE_num(sect); i++)
{
if (!typ)
goto bad;
}
}
/* Now we has a STACK of the components, convert to the correct form */
if (utype == V_ASN1_SET)
is_set = 1;
else
is_set = 0;
p = der;
if (!(ret = ASN1_TYPE_new()))
goto bad;
goto bad;
bad:
if (der)
if (sk)
if (typ)
if (sect)
return ret;
}
static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class, int exp_constructed, int exp_pad, int imp_ok)
{
/* Can only have IMPLICIT if permitted */
{
return 0;
}
{
return 0;
}
/* If IMPLICIT set tag to implicit value then
* reset implicit tag since it has been used.
*/
{
}
else
{
}
return 1;
}
{
unsigned int i;
/* Special cases */
/* type modifiers */
/* Explicit tag */
/* Implicit tag */
/* OCTET STRING wrapper */
/* SEQUENCE wrapper */
/* SET wrapper */
/* BIT STRING wrapper */
};
if (len == -1)
{
}
return -1;
}
{
unsigned char *rdata;
long rdlen;
int no_unused = 1;
if (!(atmp = ASN1_TYPE_new()))
{
return NULL;
}
if (!str)
str = "";
switch(utype)
{
case V_ASN1_NULL:
{
goto bad_form;
}
break;
case V_ASN1_BOOLEAN:
if (format != ASN1_GEN_FORMAT_ASCII)
{
goto bad_form;
}
{
goto bad_str;
}
break;
case V_ASN1_INTEGER:
case V_ASN1_ENUMERATED:
if (format != ASN1_GEN_FORMAT_ASCII)
{
goto bad_form;
}
{
goto bad_str;
}
break;
case V_ASN1_OBJECT:
if (format != ASN1_GEN_FORMAT_ASCII)
{
goto bad_form;
}
{
goto bad_str;
}
break;
case V_ASN1_UTCTIME:
case V_ASN1_GENERALIZEDTIME:
if (format != ASN1_GEN_FORMAT_ASCII)
{
goto bad_form;
}
{
goto bad_str;
}
{
goto bad_str;
}
{
goto bad_str;
}
break;
case V_ASN1_BMPSTRING:
case V_ASN1_PRINTABLESTRING:
case V_ASN1_IA5STRING:
case V_ASN1_T61STRING:
case V_ASN1_UTF8STRING:
case V_ASN1_VISIBLESTRING:
case V_ASN1_UNIVERSALSTRING:
case V_ASN1_GENERALSTRING:
if (format == ASN1_GEN_FORMAT_ASCII)
else if (format == ASN1_GEN_FORMAT_UTF8)
else
{
goto bad_form;
}
{
goto bad_str;
}
break;
case V_ASN1_BIT_STRING:
case V_ASN1_OCTET_STRING:
{
goto bad_form;
}
if (format == ASN1_GEN_FORMAT_HEX)
{
{
goto bad_str;
}
}
else if (format == ASN1_GEN_FORMAT_ASCII)
{
{
goto bad_str;
}
no_unused = 0;
}
else
{
goto bad_form;
}
{
&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
}
break;
default:
goto bad_str;
break;
}
return atmp;
return NULL;
}
{
long bitnum;
char *eptr;
if (!elem)
return 0;
return 0;
if (bitnum < 0)
{
return 0;
}
{
return 0;
}
return 1;
}