Example #1
0
static int
parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass)
{
	long tag_num;
	char *eptr;

	if (!vstart)
		return 0;
	tag_num = strtoul(vstart, &eptr, 10);
	/* Check we haven't gone past max length: should be impossible */
	if (eptr && *eptr && (eptr > vstart + vlen))
		return 0;
	if (tag_num < 0) {
		ASN1error(ASN1_R_INVALID_NUMBER);
		return 0;
	}
	*ptag = tag_num;
	/* If we have non numeric characters, parse them */
	if (eptr)
		vlen -= eptr - vstart;
	else
		vlen = 0;
	if (vlen) {
		switch (*eptr) {

		case 'U':
			*pclass = V_ASN1_UNIVERSAL;
			break;

		case 'A':
			*pclass = V_ASN1_APPLICATION;
			break;

		case 'P':
			*pclass = V_ASN1_PRIVATE;
			break;

		case 'C':
			*pclass = V_ASN1_CONTEXT_SPECIFIC;
			break;

		default:
			ASN1error(ASN1_R_INVALID_MODIFIER);
			ERR_asprintf_error_data("Char=%c", *eptr);
			return 0;
			break;

		}
	} else
		*pclass = V_ASN1_CONTEXT_SPECIFIC;

	return 1;

}
Example #2
0
int
PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
    const unsigned char *salt, int saltlen)
{
	PBEPARAM *pbe = NULL;
	ASN1_STRING *pbe_str = NULL;
	unsigned char *sstr;

	pbe = PBEPARAM_new();
	if (!pbe) {
		ASN1error(ERR_R_MALLOC_FAILURE);
		goto err;
	}
	if (iter <= 0)
		iter = PKCS5_DEFAULT_ITER;
	if (!ASN1_INTEGER_set(pbe->iter, iter)) {
		ASN1error(ERR_R_MALLOC_FAILURE);
		goto err;
	}
	if (!saltlen)
		saltlen = PKCS5_SALT_LEN;
	if (!ASN1_STRING_set(pbe->salt, NULL, saltlen)) {
		ASN1error(ERR_R_MALLOC_FAILURE);
		goto err;
	}
	sstr = ASN1_STRING_data(pbe->salt);
	if (salt)
		memcpy(sstr, salt, saltlen);
	else
		arc4random_buf(sstr, saltlen);

	if (!ASN1_item_pack(pbe, &PBEPARAM_it, &pbe_str)) {
		ASN1error(ERR_R_MALLOC_FAILURE);
		goto err;
	}

	PBEPARAM_free(pbe);
	pbe = NULL;

	if (X509_ALGOR_set0(algor, OBJ_nid2obj(alg), V_ASN1_SEQUENCE, pbe_str))
		return 1;

err:
	if (pbe != NULL)
		PBEPARAM_free(pbe);
	ASN1_STRING_free(pbe_str);
	return 0;
}
Example #3
0
static ASN1_TIME *
ASN1_TIME_adj_internal(ASN1_TIME *s, time_t t, int offset_day, long offset_sec,
    int mode)
{
	int allocated = 0;
	struct tm tm;
	size_t len;
	char * p;

 	if (gmtime_r(&t, &tm) == NULL)
 		return (NULL);

	if (offset_day || offset_sec) {
		if (!OPENSSL_gmtime_adj(&tm, offset_day, offset_sec))
			return (NULL);
	}

	switch (mode) {
	case V_ASN1_UTCTIME:
		p = utctime_string_from_tm(&tm);
		break;
	case V_ASN1_GENERALIZEDTIME:
		p = gentime_string_from_tm(&tm);
		break;
	case RFC5280:
		p = rfc5280_string_from_tm(&tm);
		break;
	default:
		return (NULL);
	}
	if (p == NULL) {
		ASN1error(ASN1_R_ILLEGAL_TIME_VALUE);
		return (NULL);
	}

	if (s == NULL) {
		if ((s = ASN1_TIME_new()) == NULL)
			return (NULL);
		allocated = 1;
	}

	len = strlen(p);
	switch (len) {
	case GENTIME_LENGTH:
		s->type = V_ASN1_GENERALIZEDTIME;
		break;
 	case UTCTIME_LENGTH:
		s->type = V_ASN1_UTCTIME;
		break;
	default:
		if (allocated)
			ASN1_TIME_free(s);
		free(p);
		return (NULL);
	}
	free(s->data);
	s->data = p;
	s->length = len;
	return (s);
}
Example #4
0
ASN1_OBJECT *
d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, long length)
{
	const unsigned char *p;
	long len;
	int tag, xclass;
	int inf, i;
	ASN1_OBJECT *ret = NULL;

	p = *pp;
	inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
	if (inf & 0x80) {
		i = ASN1_R_BAD_OBJECT_HEADER;
		goto err;
	}

	if (tag != V_ASN1_OBJECT) {
		i = ASN1_R_EXPECTING_AN_OBJECT;
		goto err;
	}
	ret = c2i_ASN1_OBJECT(a, &p, len);
	if (ret)
		*pp = p;
	return ret;

err:
	ASN1error(i);
	return (NULL);
}
Example #5
0
ASN1_INTEGER *
d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp, long length)
{
	ASN1_INTEGER *ret = NULL;
	const unsigned char *p;
	unsigned char *s;
	long len;
	int inf, tag, xclass;
	int i;

	if ((a == NULL) || ((*a) == NULL)) {
		if ((ret = ASN1_INTEGER_new()) == NULL)
			return (NULL);
	} else
		ret = (*a);

	p = *pp;
	inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
	if (inf & 0x80) {
		i = ASN1_R_BAD_OBJECT_HEADER;
		goto err;
	}

	if (tag != V_ASN1_INTEGER) {
		i = ASN1_R_EXPECTING_AN_INTEGER;
		goto err;
	}

	/* We must malloc stuff, even for 0 bytes otherwise it
	 * signifies a missing NULL parameter. */
	s = malloc(len + 1);
	if (s == NULL) {
		i = ERR_R_MALLOC_FAILURE;
		goto err;
	}
	ret->type = V_ASN1_INTEGER;
	if (len) {
		if ((*p == 0) && (len != 1)) {
			p++;
			len--;
		}
		memcpy(s, p, len);
		p += len;
	}

	free(ret->data);
	ret->data = s;
	ret->length = (int)len;
	if (a != NULL)
		(*a) = ret;
	*pp = p;
	return (ret);

err:
	ASN1error(i);
	if (a == NULL || *a != ret)
		ASN1_INTEGER_free(ret);
	return (NULL);
}
Example #6
0
ASN1_INTEGER *
BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai)
{
	ASN1_INTEGER *ret;
	int len, j;

	if (ai == NULL)
		ret = ASN1_INTEGER_new();
	else
		ret = ai;
	if (ret == NULL) {
		ASN1error(ERR_R_NESTED_ASN1_ERROR);
		goto err;
	}
	if (BN_is_negative(bn))
		ret->type = V_ASN1_NEG_INTEGER;
	else
		ret->type = V_ASN1_INTEGER;
	j = BN_num_bits(bn);
	len = ((j == 0) ? 0 : ((j / 8) + 1));
	if (ret->length < len + 4) {
		unsigned char *new_data = realloc(ret->data, len + 4);
		if (!new_data) {
			ASN1error(ERR_R_MALLOC_FAILURE);
			goto err;
		}
		ret->data = new_data;
	}
	ret->length = BN_bn2bin(bn, ret->data);

	/* Correct zero case */
	if (!ret->length) {
		ret->data[0] = 0;
		ret->length = 1;
	}
	return (ret);

err:
	if (ret != ai)
		ASN1_INTEGER_free(ret);
	return (NULL);
}
Example #7
0
BIGNUM *
ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn)
{
	BIGNUM *ret;

	if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL)
		ASN1error(ASN1_R_BN_LIB);
	else if (ai->type == V_ASN1_NEG_INTEGER)
		BN_set_negative(ret, 1);
	return (ret);
}
Example #8
0
static int
bitstr_cb(const char *elem, int len, void *bitstr)
{
	long bitnum;
	char *eptr;

	if (!elem)
		return 0;
	bitnum = strtoul(elem, &eptr, 10);
	if (eptr && *eptr && (eptr != elem + len))
		return 0;
	if (bitnum < 0) {
		ASN1error(ASN1_R_INVALID_NUMBER);
		return 0;
	}
	if (!ASN1_BIT_STRING_set_bit(bitstr, bitnum, 1)) {
		ASN1error(ERR_R_MALLOC_FAILURE);
		return 0;
	}
	return 1;
}
Example #9
0
STACK_OF(OPENSSL_BLOCK) *
ASN1_seq_unpack(const unsigned char *buf, int len, d2i_of_void *d2i,
    void (*free_func)(OPENSSL_BLOCK))
{
	STACK_OF(OPENSSL_BLOCK) *sk;
	const unsigned char *pbuf;

	pbuf = buf;
	if (!(sk = d2i_ASN1_SET(NULL, &pbuf, len, d2i, free_func,
					V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL)))
		ASN1error(ASN1_R_DECODE_ERROR);
	return sk;
}
Example #10
0
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;

	flags &= ~STABLE_FLAGS_MALLOC;
	if (!stable)
		stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
	if (!stable) {
		ASN1error(ERR_R_MALLOC_FAILURE);
		return 0;
	}
	if (!(tmp = ASN1_STRING_TABLE_get(nid))) {
		tmp = malloc(sizeof(ASN1_STRING_TABLE));
		if (!tmp) {
			ASN1error(ERR_R_MALLOC_FAILURE);
			return 0;
		}
		tmp->flags = flags | STABLE_FLAGS_MALLOC;
		tmp->nid = nid;
		new_nid = 1;
	} else tmp->flags = (tmp->flags & STABLE_FLAGS_MALLOC) | flags;
		if (minsize != -1)
		tmp->minsize = minsize;
	if (maxsize != -1)
		tmp->maxsize = maxsize;
	tmp->mask = mask;
	if (new_nid) {
		if (sk_ASN1_STRING_TABLE_push(stable, tmp) == 0) {
			free(tmp);
			ASN1error(ERR_R_MALLOC_FAILURE);
			return 0;
		}
	}
	return 1;
}
Example #11
0
static int
append_exp(tag_exp_arg *arg, int exp_tag, int exp_class, int exp_constructed,
    int exp_pad, int imp_ok)
{
	tag_exp_type *exp_tmp;

	/* Can only have IMPLICIT if permitted */
	if ((arg->imp_tag != -1) && !imp_ok) {
		ASN1error(ASN1_R_ILLEGAL_IMPLICIT_TAG);
		return 0;
	}

	if (arg->exp_count == ASN1_FLAG_EXP_MAX) {
		ASN1error(ASN1_R_DEPTH_EXCEEDED);
		return 0;
	}

	exp_tmp = &arg->exp_list[arg->exp_count++];

	/* If IMPLICIT set tag to implicit value then
	 * reset implicit tag since it has been used.
	 */
	if (arg->imp_tag != -1) {
		exp_tmp->exp_tag = arg->imp_tag;
		exp_tmp->exp_class = arg->imp_class;
		arg->imp_tag = -1;
		arg->imp_class = -1;
	} else {
		exp_tmp->exp_tag = exp_tag;
		exp_tmp->exp_class = exp_class;
	}
	exp_tmp->exp_constructed = exp_constructed;
	exp_tmp->exp_pad = exp_pad;

	return 1;
}
Example #12
0
X509_ALGOR *
PKCS5_pbe_set(int alg, int iter, const unsigned char *salt, int saltlen)
{
	X509_ALGOR *ret;
	ret = X509_ALGOR_new();
	if (!ret) {
		ASN1error(ERR_R_MALLOC_FAILURE);
		return NULL;
	}

	if (PKCS5_pbe_set0_algor(ret, alg, iter, salt, saltlen))
		return ret;

	X509_ALGOR_free(ret);
	return NULL;
}
Example #13
0
int
i2d_EC_PUBKEY(EC_KEY *a, unsigned char **pp)
{
	EVP_PKEY *pktmp;
	int ret;
	if (!a)
		return (0);
	if ((pktmp = EVP_PKEY_new()) == NULL) {
		ASN1error(ERR_R_MALLOC_FAILURE);
		return (0);
	}
	EVP_PKEY_set1_EC_KEY(pktmp, a);
	ret = i2d_PUBKEY(pktmp, pp);
	EVP_PKEY_free(pktmp);
	return (ret);
}
Example #14
0
int
i2d_DSA_PUBKEY(DSA *a, unsigned char **pp)
{
	EVP_PKEY *pktmp;
	int ret;
	if (!a)
		return 0;
	pktmp = EVP_PKEY_new();
	if (!pktmp) {
		ASN1error(ERR_R_MALLOC_FAILURE);
		return 0;
	}
	EVP_PKEY_set1_DSA(pktmp, a);
	ret = i2d_PUBKEY(pktmp, pp);
	EVP_PKEY_free(pktmp);
	return ret;
}
Example #15
0
ASN1_OBJECT *
ASN1_OBJECT_new(void)
{
	ASN1_OBJECT *ret;

	ret = malloc(sizeof(ASN1_OBJECT));
	if (ret == NULL) {
		ASN1error(ERR_R_MALLOC_FAILURE);
		return (NULL);
	}
	ret->length = 0;
	ret->data = NULL;
	ret->nid = 0;
	ret->sn = NULL;
	ret->ln = NULL;
	ret->flags = ASN1_OBJECT_FLAG_DYNAMIC;
	return (ret);
}
Example #16
0
int
ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
{
	const ASN1_ITEM *it = tt->item;
	int ret;

	if (tt->flags & ASN1_TFLG_OPTIONAL) {
		asn1_template_clear(pval, tt);
		return 1;
	}
	/* If ANY DEFINED BY nothing to do */

	if (tt->flags & ASN1_TFLG_ADB_MASK) {
		*pval = NULL;
		return 1;
	}
#ifdef CRYPTO_MDEBUG
	if (tt->field_name)
		CRYPTO_push_info(tt->field_name);
#endif
	/* If SET OF or SEQUENCE OF, its a STACK */
	if (tt->flags & ASN1_TFLG_SK_MASK) {
		STACK_OF(ASN1_VALUE) *skval;
		skval = sk_ASN1_VALUE_new_null();
		if (!skval) {
			ASN1error(ERR_R_MALLOC_FAILURE);
			ret = 0;
			goto done;
		}
		*pval = (ASN1_VALUE *)skval;
		ret = 1;
		goto done;
	}
	/* Otherwise pass it back to the item routine */
	ret = asn1_item_ex_combine_new(pval, it, tt->flags & ASN1_TFLG_COMBINE);
done:
#ifdef CRYPTO_MDEBUG
	if (it->sname)
		CRYPTO_pop_info();
#endif
	return ret;
}
Example #17
0
int
ASN1_INTEGER_set(ASN1_INTEGER *a, long v)
{
	int j, k;
	unsigned int i;
	unsigned char buf[sizeof(long) + 1];
	long d;

	a->type = V_ASN1_INTEGER;
	/* XXX ssl/ssl_asn1.c:i2d_SSL_SESSION() depends upon this bound vae */
	if (a->length < (int)(sizeof(long) + 1)) {
		free(a->data);
		a->data = calloc(1, sizeof(long) + 1);
	}
	if (a->data == NULL) {
		ASN1error(ERR_R_MALLOC_FAILURE);
		return (0);
	}
	d = v;
	if (d < 0) {
		d = -d;
		a->type = V_ASN1_NEG_INTEGER;
	}

	for (i = 0; i < sizeof(long); i++) {
		if (d == 0)
			break;
		buf[i] = (int)d & 0xff;
		d >>= 8;
	}
	j = 0;
	for (k = i - 1; k >= 0; k--)
		a->data[j++] = buf[k];
	a->length = j;
	return (1);
}
Example #18
0
static ASN1_TYPE *
asn1_str2type(const char *str, int format, int utype)
{
	ASN1_TYPE *atmp = NULL;
	CONF_VALUE vtmp;
	unsigned char *rdata;
	long rdlen;
	int no_unused = 1;

	if (!(atmp = ASN1_TYPE_new())) {
		ASN1error(ERR_R_MALLOC_FAILURE);
		return NULL;
	}

	if (!str)
		str = "";

	switch (utype) {

	case V_ASN1_NULL:
		if (str && *str) {
			ASN1error(ASN1_R_ILLEGAL_NULL_VALUE);
			goto bad_form;
		}
		break;

	case V_ASN1_BOOLEAN:
		if (format != ASN1_GEN_FORMAT_ASCII) {
			ASN1error(ASN1_R_NOT_ASCII_FORMAT);
			goto bad_form;
		}
		vtmp.name = NULL;
		vtmp.section = NULL;
		vtmp.value = (char *)str;
		if (!X509V3_get_value_bool(&vtmp, &atmp->value.boolean)) {
			ASN1error(ASN1_R_ILLEGAL_BOOLEAN);
			goto bad_str;
		}
		break;

	case V_ASN1_INTEGER:
	case V_ASN1_ENUMERATED:
		if (format != ASN1_GEN_FORMAT_ASCII) {
			ASN1error(ASN1_R_INTEGER_NOT_ASCII_FORMAT);
			goto bad_form;
		}
		if (!(atmp->value.integer =
		    s2i_ASN1_INTEGER(NULL, (char *)str))) {
			ASN1error(ASN1_R_ILLEGAL_INTEGER);
			goto bad_str;
		}
		break;

	case V_ASN1_OBJECT:
		if (format != ASN1_GEN_FORMAT_ASCII) {
			ASN1error(ASN1_R_OBJECT_NOT_ASCII_FORMAT);
			goto bad_form;
		}
		if (!(atmp->value.object = OBJ_txt2obj(str, 0))) {
			ASN1error(ASN1_R_ILLEGAL_OBJECT);
			goto bad_str;
		}
		break;

	case V_ASN1_UTCTIME:
	case V_ASN1_GENERALIZEDTIME:
		if (format != ASN1_GEN_FORMAT_ASCII) {
			ASN1error(ASN1_R_TIME_NOT_ASCII_FORMAT);
			goto bad_form;
		}
		if (!(atmp->value.asn1_string = ASN1_STRING_new())) {
			ASN1error(ERR_R_MALLOC_FAILURE);
			goto bad_str;
		}
		if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1)) {
			ASN1error(ERR_R_MALLOC_FAILURE);
			goto bad_str;
		}
		atmp->value.asn1_string->type = utype;
		if (!ASN1_TIME_check(atmp->value.asn1_string)) {
			ASN1error(ASN1_R_ILLEGAL_TIME_VALUE);
			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:
	case V_ASN1_NUMERICSTRING:

		if (format == ASN1_GEN_FORMAT_ASCII)
			format = MBSTRING_ASC;
		else if (format == ASN1_GEN_FORMAT_UTF8)
			format = MBSTRING_UTF8;
		else {
			ASN1error(ASN1_R_ILLEGAL_FORMAT);
			goto bad_form;
		}

		if (ASN1_mbstring_copy(&atmp->value.asn1_string,
		    (unsigned char *)str, -1, format,
		    ASN1_tag2bit(utype)) <= 0) {
			ASN1error(ERR_R_MALLOC_FAILURE);
			goto bad_str;
		}
		break;

	case V_ASN1_BIT_STRING:
	case V_ASN1_OCTET_STRING:
		if (!(atmp->value.asn1_string = ASN1_STRING_new())) {
			ASN1error(ERR_R_MALLOC_FAILURE);
			goto bad_form;
		}

		if (format == ASN1_GEN_FORMAT_HEX) {

			if (!(rdata = string_to_hex((char *)str, &rdlen))) {
				ASN1error(ASN1_R_ILLEGAL_HEX);
				goto bad_str;
			}

			atmp->value.asn1_string->data = rdata;
			atmp->value.asn1_string->length = rdlen;
			atmp->value.asn1_string->type = utype;

		} else if (format == ASN1_GEN_FORMAT_ASCII) {
			if (ASN1_STRING_set(atmp->value.asn1_string, str,
			    -1) == 0) {
				ASN1error(ERR_R_MALLOC_FAILURE);
				goto bad_str;
			}
		} else if ((format == ASN1_GEN_FORMAT_BITLIST) &&
		    (utype == V_ASN1_BIT_STRING)) {
			if (!CONF_parse_list(str, ',', 1, bitstr_cb,
			    atmp->value.bit_string)) {
				ASN1error(ASN1_R_LIST_ERROR);
				goto bad_str;
			}
			no_unused = 0;

		} else {
			ASN1error(ASN1_R_ILLEGAL_BITSTRING_FORMAT);
			goto bad_form;
		}

		if ((utype == V_ASN1_BIT_STRING) && no_unused) {
			atmp->value.asn1_string->flags &=
			    ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
			atmp->value.asn1_string->flags |=
			    ASN1_STRING_FLAG_BITS_LEFT;
		}

		break;

	default:
		ASN1error(ASN1_R_UNSUPPORTED_TYPE);
		goto bad_str;
		break;
	}

	atmp->type = utype;
	return atmp;

bad_str:
	ERR_asprintf_error_data("string=%s", str);
bad_form:
	ASN1_TYPE_free(atmp);
	return NULL;
}
Example #19
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;
	char free_out;
	int outform, outlen = 0;
	ASN1_STRING *dest;
	unsigned char *p;
	int nchar;
	int (*cpyfunc)(unsigned long, void *) = NULL;

	if (len < 0)
		len = strlen((const char *)in);
	if (!mask)
		mask = DIRSTRING_TYPE;

	/* First do a string check and work out the number of characters */
	switch (inform) {
	case MBSTRING_BMP:
		if (len & 1) {
			ASN1error(ASN1_R_INVALID_BMPSTRING_LENGTH);
			return -1;
		}
		nchar = len >> 1;
		break;

	case MBSTRING_UNIV:
		if (len & 3) {
			ASN1error(ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
			return -1;
		}
		nchar = len >> 2;
		break;

	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) {
			ASN1error(ASN1_R_INVALID_UTF8STRING);
			return -1;
		}
		break;

	case MBSTRING_ASC:
		nchar = len;
		break;

	default:
		ASN1error(ASN1_R_UNKNOWN_FORMAT);
		return -1;
	}

	if ((minsize > 0) && (nchar < minsize)) {
		ASN1error(ASN1_R_STRING_TOO_SHORT);
		ERR_asprintf_error_data("minsize=%ld", minsize);
		return -1;
	}

	if ((maxsize > 0) && (nchar > maxsize)) {
		ASN1error(ASN1_R_STRING_TOO_LONG);
		ERR_asprintf_error_data("maxsize=%ld", maxsize);
		return -1;
	}

	/* Now work out minimal type (if any) */
	if (traverse_string(in, len, inform, type_str, &mask) < 0) {
		ASN1error(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;
	else if (mask & B_ASN1_IA5STRING)
		str_type = V_ASN1_IA5STRING;
	else if (mask & B_ASN1_T61STRING)
		str_type = V_ASN1_T61STRING;
	else if (mask & B_ASN1_BMPSTRING) {
		str_type = V_ASN1_BMPSTRING;
		outform = MBSTRING_BMP;
	} else if (mask & B_ASN1_UNIVERSALSTRING) {
		str_type = V_ASN1_UNIVERSALSTRING;
		outform = MBSTRING_UNIV;
	} else {
		str_type = V_ASN1_UTF8STRING;
		outform = MBSTRING_UTF8;
	}
	if (!out)
		return str_type;
	if (*out) {
		free_out = 0;
		dest = *out;
		if (dest->data) {
			dest->length = 0;
			free(dest->data);
			dest->data = NULL;
		}
		dest->type = str_type;
	} else {
		free_out = 1;
		dest = ASN1_STRING_type_new(str_type);
		if (!dest) {
			ASN1error(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)) {
			ASN1error(ERR_R_MALLOC_FAILURE);
			goto err;
		}
		return str_type;
	}

	/* Work out how much space the destination will need */
	switch (outform) {
	case MBSTRING_ASC:
		outlen = nchar;
		cpyfunc = cpy_asc;
		break;

	case MBSTRING_BMP:
		outlen = nchar << 1;
		cpyfunc = cpy_bmp;
		break;

	case MBSTRING_UNIV:
		outlen = nchar << 2;
		cpyfunc = cpy_univ;
		break;

	case MBSTRING_UTF8:
		outlen = 0;
		if (traverse_string(in, len, inform, out_utf8, &outlen) < 0) {
			ASN1error(ASN1_R_ILLEGAL_CHARACTERS);
			goto err;
		}
		cpyfunc = cpy_utf8;
		break;
	}
	if (!(p = malloc(outlen + 1))) {
		ASN1error(ERR_R_MALLOC_FAILURE);
		goto err;
	}
	dest->length = outlen;
	dest->data = p;
	p[outlen] = 0;
	traverse_string(in, len, inform, cpyfunc, &p);
	return str_type;

err:
	if (free_out) {
		ASN1_STRING_free(dest);
		*out = NULL;
	}
	return -1;
}
Example #20
0
int
a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
{
	int i, first, len = 0, c, use_bn;
	char ftmp[24], *tmp = ftmp;
	int tmpsize = sizeof ftmp;
	const char *p;
	unsigned long l;
	BIGNUM *bl = NULL;

	if (num == 0)
		return (0);
	else if (num == -1)
		num = strlen(buf);

	p = buf;
	c = *(p++);
	num--;
	if ((c >= '0') && (c <= '2')) {
		first= c-'0';
	} else {
		ASN1error(ASN1_R_FIRST_NUM_TOO_LARGE);
		goto err;
	}

	if (num <= 0) {
		ASN1error(ASN1_R_MISSING_SECOND_NUMBER);
		goto err;
	}
	c = *(p++);
	num--;
	for (;;) {
		if (num <= 0)
			break;
		if ((c != '.') && (c != ' ')) {
			ASN1error(ASN1_R_INVALID_SEPARATOR);
			goto err;
		}
		l = 0;
		use_bn = 0;
		for (;;) {
			if (num <= 0)
				break;
			num--;
			c = *(p++);
			if ((c == ' ') || (c == '.'))
				break;
			if ((c < '0') || (c > '9')) {
				ASN1error(ASN1_R_INVALID_DIGIT);
				goto err;
			}
			if (!use_bn && l >= ((ULONG_MAX - 80) / 10L)) {
				use_bn = 1;
				if (!bl)
					bl = BN_new();
				if (!bl || !BN_set_word(bl, l))
					goto err;
			}
			if (use_bn) {
				if (!BN_mul_word(bl, 10L) ||
				    !BN_add_word(bl, c-'0'))
					goto err;
			} else
				l = l * 10L + (long)(c - '0');
		}
		if (len == 0) {
			if ((first < 2) && (l >= 40)) {
				ASN1error(ASN1_R_SECOND_NUMBER_TOO_LARGE);
				goto err;
			}
			if (use_bn) {
				if (!BN_add_word(bl, first * 40))
					goto err;
			} else
				l += (long)first * 40;
		}
		i = 0;
		if (use_bn) {
			int blsize;
			blsize = BN_num_bits(bl);
			blsize = (blsize + 6) / 7;
			if (blsize > tmpsize) {
				if (tmp != ftmp)
					free(tmp);
				tmpsize = blsize + 32;
				tmp = malloc(tmpsize);
				if (!tmp)
					goto err;
			}
			while (blsize--)
				tmp[i++] = (unsigned char)BN_div_word(bl, 0x80L);
		} else {

			for (;;) {
				tmp[i++] = (unsigned char)l & 0x7f;
				l >>= 7L;
				if (l == 0L)
					break;
			}

		}
		if (out != NULL) {
			if (len + i > olen) {
				ASN1error(ASN1_R_BUFFER_TOO_SMALL);
				goto err;
			}
			while (--i > 0)
				out[len++] = tmp[i]|0x80;
			out[len++] = tmp[0];
		} else
			len += i;
	}
	if (tmp != ftmp)
		free(tmp);
	BN_free(bl);
	return (len);

err:
	if (tmp != ftmp)
		free(tmp);
	BN_free(bl);
	return (0);
}
Example #21
0
ASN1_TYPE *
ASN1_generate_v3(char *str, X509V3_CTX *cnf)
{
	ASN1_TYPE *ret;
	tag_exp_arg asn1_tags;
	tag_exp_type *etmp;

	int i, len;

	unsigned char *orig_der = NULL, *new_der = NULL;
	const unsigned char *cpy_start;
	unsigned char *p;
	const unsigned char *cp;
	int cpy_len;
	long hdr_len = 0;
	int hdr_constructed = 0, hdr_tag, hdr_class;
	int r;

	asn1_tags.imp_tag = -1;
	asn1_tags.imp_class = -1;
	asn1_tags.format = ASN1_GEN_FORMAT_ASCII;
	asn1_tags.exp_count = 0;
	if (CONF_parse_list(str, ',', 1, asn1_cb, &asn1_tags) != 0)
		return NULL;

	if ((asn1_tags.utype == V_ASN1_SEQUENCE) ||
	    (asn1_tags.utype == V_ASN1_SET)) {
		if (!cnf) {
			ASN1error(ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG);
			return NULL;
		}
		ret = asn1_multi(asn1_tags.utype, asn1_tags.str, cnf);
	} else
		ret = asn1_str2type(asn1_tags.str, asn1_tags.format,
		    asn1_tags.utype);

	if (!ret)
		return NULL;

	/* If no tagging return base type */
	if ((asn1_tags.imp_tag == -1) && (asn1_tags.exp_count == 0))
		return ret;

	/* Generate the encoding */
	cpy_len = i2d_ASN1_TYPE(ret, &orig_der);
	ASN1_TYPE_free(ret);
	ret = NULL;
	/* Set point to start copying for modified encoding */
	cpy_start = orig_der;

	/* Do we need IMPLICIT tagging? */
	if (asn1_tags.imp_tag != -1) {
		/* If IMPLICIT we will replace the underlying tag */
		/* Skip existing tag+len */
		r = ASN1_get_object(&cpy_start, &hdr_len, &hdr_tag,
		    &hdr_class, cpy_len);
		if (r & 0x80)
			goto err;
		/* Update copy length */
		cpy_len -= cpy_start - orig_der;
		/* 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 */
			hdr_constructed = r & V_ASN1_CONSTRUCTED;
		/* Work out new length with IMPLICIT tag: ignore constructed
		 * because it will mess up if indefinite length
		 */
		len = ASN1_object_size(0, hdr_len, asn1_tags.imp_tag);
	} else
		len = cpy_len;

	/* 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 */
		len += etmp->exp_pad;
		etmp->exp_len = len;
		/* Total object length: length including new header */
		len = ASN1_object_size(0, len, etmp->exp_tag);
	}

	/* Allocate buffer for new encoding */

	new_der = malloc(len);
	if (!new_der)
		goto err;

	/* Generate tagged encoding */
	p = new_der;

	/* Output explicit tags first */
	for (i = 0, etmp = asn1_tags.exp_list; i < asn1_tags.exp_count;
	    i++, etmp++) {
		ASN1_put_object(&p, etmp->exp_constructed, etmp->exp_len,
		    etmp->exp_tag, etmp->exp_class);
		if (etmp->exp_pad)
			*p++ = 0;
	}

	/* If IMPLICIT, output tag */

	if (asn1_tags.imp_tag != -1) {
		if (asn1_tags.imp_class == V_ASN1_UNIVERSAL &&
		    (asn1_tags.imp_tag == V_ASN1_SEQUENCE ||
		    asn1_tags.imp_tag == V_ASN1_SET))
			hdr_constructed = V_ASN1_CONSTRUCTED;
		ASN1_put_object(&p, hdr_constructed, hdr_len,
		    asn1_tags.imp_tag, asn1_tags.imp_class);
	}

	/* Copy across original encoding */
	memcpy(p, cpy_start, cpy_len);

	cp = new_der;

	/* Obtain new ASN1_TYPE structure */
	ret = d2i_ASN1_TYPE(NULL, &cp, len);

err:
	free(orig_der);
	free(new_der);

	return ret;
}
Example #22
0
ASN1_INTEGER *
c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp, long len)
{
	ASN1_INTEGER *ret = NULL;
	const unsigned char *p, *pend;
	unsigned char *to, *s;
	int i;

	if ((a == NULL) || ((*a) == NULL)) {
		if ((ret = ASN1_INTEGER_new()) == NULL)
			return (NULL);
	} else
		ret = (*a);

	p = *pp;
	pend = p + len;

	/* We must malloc stuff, even for 0 bytes otherwise it
	 * signifies a missing NULL parameter. */
	s = malloc(len + 1);
	if (s == NULL) {
		i = ERR_R_MALLOC_FAILURE;
		goto err;
	}
	to = s;
	if (!len) {
		/* Strictly speaking this is an illegal INTEGER but we
		 * tolerate it.
		 */
		ret->type = V_ASN1_INTEGER;
	} else if (*p & 0x80) /* a negative number */ {
		ret->type = V_ASN1_NEG_INTEGER;
		if ((*p == 0xff) && (len != 1)) {
			p++;
			len--;
		}
		i = len;
		p += i - 1;
		to += i - 1;
		while((!*p) && i) {
			*(to--) = 0;
			i--;
			p--;
		}
		/* Special case: if all zeros then the number will be of
		 * the form FF followed by n zero bytes: this corresponds to
		 * 1 followed by n zero bytes. We've already written n zeros
		 * so we just append an extra one and set the first byte to
		 * a 1. This is treated separately because it is the only case
		 * where the number of bytes is larger than len.
		 */
		if (!i) {
			*s = 1;
			s[len] = 0;
			len++;
		} else {
			*(to--) = (*(p--) ^ 0xff) + 1;
			i--;
			for (; i > 0; i--)
				*(to--) = *(p--) ^ 0xff;
		}
	} else {
		ret->type = V_ASN1_INTEGER;
		if ((*p == 0) && (len != 1)) {
			p++;
			len--;
		}
		memcpy(s, p, len);
	}

	free(ret->data);
	ret->data = s;
	ret->length = (int)len;
	if (a != NULL)
		(*a) = ret;
	*pp = pend;
	return (ret);

err:
	ASN1error(i);
	if (a == NULL || *a != ret)
		ASN1_INTEGER_free(ret);
	return (NULL);
}
Example #23
0
int
ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
    ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx)
{
	const EVP_MD *type;
	EVP_PKEY *pkey;
	unsigned char *buf_in = NULL, *buf_out = NULL;
	size_t inl = 0, outl = 0, outll = 0;
	int signid, paramtype;
	int rv;

	type = EVP_MD_CTX_md(ctx);
	pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);

	if (!type || !pkey) {
		ASN1error(ASN1_R_CONTEXT_NOT_INITIALISED);
		return 0;
	}

	if (pkey->ameth->item_sign) {
		rv = pkey->ameth->item_sign(ctx, it, asn, algor1, algor2,
		    signature);
		if (rv == 1)
			outl = signature->length;
		/* Return value meanings:
		 * <=0: error.
		 *   1: method does everything.
		 *   2: carry on as normal.
		 *   3: ASN1 method sets algorithm identifiers: just sign.
		 */
		if (rv <= 0)
			ASN1error(ERR_R_EVP_LIB);
		if (rv <= 1)
			goto err;
	} else
		rv = 2;

	if (rv == 2) {
		if (type->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE) {
			if (!pkey->ameth ||
			    !OBJ_find_sigid_by_algs(&signid,
				EVP_MD_nid(type), pkey->ameth->pkey_id)) {
				ASN1error(ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
				return 0;
			}
		} else
			signid = type->pkey_type;

		if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL)
			paramtype = V_ASN1_NULL;
		else
			paramtype = V_ASN1_UNDEF;

		if (algor1)
			X509_ALGOR_set0(algor1,
			    OBJ_nid2obj(signid), paramtype, NULL);
		if (algor2)
			X509_ALGOR_set0(algor2,
			    OBJ_nid2obj(signid), paramtype, NULL);

	}

	inl = ASN1_item_i2d(asn, &buf_in, it);
	outll = outl = EVP_PKEY_size(pkey);
	buf_out = malloc(outl);
	if ((buf_in == NULL) || (buf_out == NULL)) {
		outl = 0;
		ASN1error(ERR_R_MALLOC_FAILURE);
		goto err;
	}

	if (!EVP_DigestSignUpdate(ctx, buf_in, inl) ||
	    !EVP_DigestSignFinal(ctx, buf_out, &outl)) {
		outl = 0;
		ASN1error(ERR_R_EVP_LIB);
		goto err;
	}
	free(signature->data);
	signature->data = buf_out;
	buf_out = NULL;
	signature->length = outl;
	/* In the interests of compatibility, I'll make sure that
	 * the bit string has a 'not-used bits' value of 0
	 */
	signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
	signature->flags |= ASN1_STRING_FLAG_BITS_LEFT;

err:
	EVP_MD_CTX_cleanup(ctx);
	freezero((char *)buf_in, inl);
	freezero((char *)buf_out, outll);
	return (outl);
}
Example #24
0
static int
asn1_cb(const char *elem, int len, void *bitstr)
{
	tag_exp_arg *arg = bitstr;
	int i;
	int utype;
	int vlen = 0;
	const char *p, *vstart = NULL;

	int tmp_tag, tmp_class;

	for (i = 0, p = elem; i < len; p++, i++) {
		/* Look for the ':' in name value pairs */
		if (*p == ':') {
			vstart = p + 1;
			vlen = len - (vstart - elem);
			len = p - elem;
			break;
		}
	}

	utype = asn1_str2tag(elem, len);

	if (utype == -1) {
		ASN1error(ASN1_R_UNKNOWN_TAG);
		ERR_asprintf_error_data("tag=%s", elem);
		return -1;
	}

	/* If this is not a modifier mark end of string and exit */
	if (!(utype & ASN1_GEN_FLAG)) {
		arg->utype = utype;
		arg->str = vstart;
		/* If no value and not end of string, error */
		if (!vstart && elem[len]) {
			ASN1error(ASN1_R_MISSING_VALUE);
			return -1;
		}
		return 0;
	}

	switch (utype) {

	case ASN1_GEN_FLAG_IMP:
		/* Check for illegal multiple IMPLICIT tagging */
		if (arg->imp_tag != -1) {
			ASN1error(ASN1_R_ILLEGAL_NESTED_TAGGING);
			return -1;
		}
		if (!parse_tagging(vstart, vlen, &arg->imp_tag,
		    &arg->imp_class))
			return -1;
		break;

	case ASN1_GEN_FLAG_EXP:
		if (!parse_tagging(vstart, vlen, &tmp_tag, &tmp_class))
			return -1;
		if (!append_exp(arg, tmp_tag, tmp_class, 1, 0, 0))
			return -1;
		break;

	case ASN1_GEN_FLAG_SEQWRAP:
		if (!append_exp(arg, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL, 1, 0, 1))
			return -1;
		break;

	case ASN1_GEN_FLAG_SETWRAP:
		if (!append_exp(arg, V_ASN1_SET, V_ASN1_UNIVERSAL, 1, 0, 1))
			return -1;
		break;

	case ASN1_GEN_FLAG_BITWRAP:
		if (!append_exp(arg, V_ASN1_BIT_STRING, V_ASN1_UNIVERSAL, 0, 1, 1))
			return -1;
		break;

	case ASN1_GEN_FLAG_OCTWRAP:
		if (!append_exp(arg, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL, 0, 0, 1))
			return -1;
		break;

	case ASN1_GEN_FLAG_FORMAT:
		if (vstart == NULL) {
			ASN1error(ASN1_R_ILLEGAL_FORMAT);
			return -1;
		}
		if (!strncmp(vstart, "ASCII", 5))
			arg->format = ASN1_GEN_FORMAT_ASCII;
		else if (!strncmp(vstart, "UTF8", 4))
			arg->format = ASN1_GEN_FORMAT_UTF8;
		else if (!strncmp(vstart, "HEX", 3))
			arg->format = ASN1_GEN_FORMAT_HEX;
		else if (!strncmp(vstart, "BITLIST", 7))
			arg->format = ASN1_GEN_FORMAT_BITLIST;
		else {
			ASN1error(ASN1_R_UNKOWN_FORMAT);
			return -1;
		}
		break;

	}

	return 1;
}
Example #25
0
static int
asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine)
{
	const ASN1_TEMPLATE *tt = NULL;
	const ASN1_EXTERN_FUNCS *ef;
	const ASN1_AUX *aux = it->funcs;
	ASN1_aux_cb *asn1_cb = NULL;
	ASN1_VALUE **pseqval;
	int i;

	if (aux != NULL && aux->asn1_cb != NULL)
		asn1_cb = aux->asn1_cb;

	if (!combine)
		*pval = NULL;

#ifdef CRYPTO_MDEBUG
	if (it->sname)
		CRYPTO_push_info(it->sname);
#endif

	switch (it->itype) {
	case ASN1_ITYPE_EXTERN:
		ef = it->funcs;
		if (ef && ef->asn1_ex_new) {
			if (!ef->asn1_ex_new(pval, it))
				goto memerr;
		}
		break;

	case ASN1_ITYPE_PRIMITIVE:
		if (it->templates) {
			if (!ASN1_template_new(pval, it->templates))
				goto memerr;
		} else if (!ASN1_primitive_new(pval, it))
			goto memerr;
		break;

	case ASN1_ITYPE_MSTRING:
		if (!ASN1_primitive_new(pval, it))
			goto memerr;
		break;

	case ASN1_ITYPE_CHOICE:
		if (asn1_cb) {
			i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
			if (!i)
				goto auxerr;
			if (i == 2) {
#ifdef CRYPTO_MDEBUG
				if (it->sname)
					CRYPTO_pop_info();
#endif
				return 1;
			}
		}
		if (!combine) {
			*pval = calloc(1, it->size);
			if (!*pval)
				goto memerr;
		}
		asn1_set_choice_selector(pval, -1, it);
		if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
			goto auxerr;
		break;

	case ASN1_ITYPE_NDEF_SEQUENCE:
	case ASN1_ITYPE_SEQUENCE:
		if (asn1_cb) {
			i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
			if (!i)
				goto auxerr;
			if (i == 2) {
#ifdef CRYPTO_MDEBUG
				if (it->sname)
					CRYPTO_pop_info();
#endif
				return 1;
			}
		}
		if (!combine) {
			*pval = calloc(1, it->size);
			if (!*pval)
				goto memerr;
			asn1_do_lock(pval, 0, it);
			asn1_enc_init(pval, it);
		}
		for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
			pseqval = asn1_get_field_ptr(pval, tt);
			if (!ASN1_template_new(pseqval, tt))
				goto memerr;
		}
		if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
			goto auxerr;
		break;
	}
#ifdef CRYPTO_MDEBUG
	if (it->sname)
		CRYPTO_pop_info();
#endif
	return 1;

memerr:
	ASN1error(ERR_R_MALLOC_FAILURE);
#ifdef CRYPTO_MDEBUG
	if (it->sname)
		CRYPTO_pop_info();
#endif
	return 0;

auxerr:
	ASN1error(ASN1_R_AUX_ERROR);
	ASN1_item_ex_free(pval, it);
#ifdef CRYPTO_MDEBUG
	if (it->sname)
		CRYPTO_pop_info();
#endif
	return 0;

}
Example #26
0
ASN1_OBJECT *
c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, long len)
{
	ASN1_OBJECT *ret;
	const unsigned char *p;
	unsigned char *data;
	int i, length;

	/*
	 * Sanity check OID encoding:
	 * - need at least one content octet
	 * - MSB must be clear in the last octet
	 * - can't have leading 0x80 in subidentifiers, see: X.690 8.19.2
	 */
	if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
	    p[len - 1] & 0x80) {
		ASN1error(ASN1_R_INVALID_OBJECT_ENCODING);
		return (NULL);
	}

	/* Now 0 < len <= INT_MAX, so the cast is safe. */
	length = (int)len;
	for (i = 0; i < length; i++, p++) {
		if (*p == 0x80 && (!i || !(p[-1] & 0x80))) {
			ASN1error(ASN1_R_INVALID_OBJECT_ENCODING);
			return (NULL);
		}
	}

	/* only the ASN1_OBJECTs from the 'table' will have values
	 * for ->sn or ->ln */
	if ((a == NULL) || ((*a) == NULL) ||
	    !((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC)) {
		if ((ret = ASN1_OBJECT_new()) == NULL)
			return (NULL);
	} else
		ret = *a;

	p = *pp;

	/* detach data from object */
	data = (unsigned char *)ret->data;
	if (data != NULL)
		explicit_bzero(data, ret->length);
	free(data);

	data = malloc(length);
	if (data == NULL) {
		ASN1error(ERR_R_MALLOC_FAILURE);
		goto err;
	}

	memcpy(data, p, length);

	/* reattach data to object, after which it remains const */
	ret->data = data;
	ret->length = length;
	ret->sn = NULL;
	ret->ln = NULL;
	ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;
	p += length;

	if (a != NULL)
		*a = ret;
	*pp = p;
	return (ret);

err:
	if (a == NULL || ret != *a)
		ASN1_OBJECT_free(ret);
	return (NULL);
}