pure sdk for main

This commit is contained in:
divadiow
2025-08-27 09:51:58 +01:00
parent f0d033f1c9
commit 0571416e7c
3283 changed files with 1577720 additions and 1 deletions
@@ -0,0 +1,263 @@
/* crypto/asn1/a_bitstr.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* 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 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 acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS 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 AUTHOR OR 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.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/asn1.h>
int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len)
{
return M_ASN1_BIT_STRING_set(x, d, len);
}
int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp)
{
int ret, j, bits, len;
unsigned char *p, *d;
if (a == NULL)
return (0);
len = a->length;
if (len > 0) {
if (a->flags & ASN1_STRING_FLAG_BITS_LEFT) {
bits = (int)a->flags & 0x07;
} else {
for (; len > 0; len--) {
if (a->data[len - 1])
break;
}
j = a->data[len - 1];
if (j & 0x01)
bits = 0;
else if (j & 0x02)
bits = 1;
else if (j & 0x04)
bits = 2;
else if (j & 0x08)
bits = 3;
else if (j & 0x10)
bits = 4;
else if (j & 0x20)
bits = 5;
else if (j & 0x40)
bits = 6;
else if (j & 0x80)
bits = 7;
else
bits = 0; /* should not happen */
}
} else
bits = 0;
ret = 1 + len;
if (pp == NULL)
return (ret);
p = *pp;
*(p++) = (unsigned char)bits;
d = a->data;
if (len > 0) {
memcpy(p, d, len);
p += len;
p[-1] &= (0xff << bits);
}
*pp = p;
return (ret);
}
ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
const unsigned char **pp, long len)
{
ASN1_BIT_STRING *ret = NULL;
const unsigned char *p;
unsigned char *s;
int i;
if (len < 1) {
i = ASN1_R_STRING_TOO_SHORT;
goto err;
}
if ((a == NULL) || ((*a) == NULL)) {
if ((ret = M_ASN1_BIT_STRING_new()) == NULL)
return (NULL);
} else
ret = (*a);
p = *pp;
i = *(p++);
if (i > 7) {
i = ASN1_R_INVALID_BIT_STRING_BITS_LEFT;
goto err;
}
/*
* We do this to preserve the settings. If we modify the settings, via
* the _set_bit function, we will recalculate on output
*/
ret->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear */
ret->flags |= (ASN1_STRING_FLAG_BITS_LEFT | i); /* set */
if (len-- > 1) { /* using one because of the bits left byte */
s = (unsigned char *)OPENSSL_malloc((int)len);
if (s == NULL) {
i = ERR_R_MALLOC_FAILURE;
goto err;
}
memcpy(s, p, (int)len);
s[len - 1] &= (0xff << i);
p += len;
} else
s = NULL;
ret->length = (int)len;
if (ret->data != NULL)
OPENSSL_free(ret->data);
ret->data = s;
ret->type = V_ASN1_BIT_STRING;
if (a != NULL)
(*a) = ret;
*pp = p;
return (ret);
err:
ASN1err(ASN1_F_C2I_ASN1_BIT_STRING, i);
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
M_ASN1_BIT_STRING_free(ret);
return (NULL);
}
/*
* These next 2 functions from Goetz Babin-Ebell <babinebell@trustcenter.de>
*/
int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value)
{
int w, v, iv;
unsigned char *c;
w = n / 8;
v = 1 << (7 - (n & 0x07));
iv = ~v;
if (!value)
v = 0;
if (a == NULL)
return 0;
a->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear, set on write */
if ((a->length < (w + 1)) || (a->data == NULL)) {
if (!value)
return (1); /* Don't need to set */
if (a->data == NULL)
c = (unsigned char *)OPENSSL_malloc(w + 1);
else
c = (unsigned char *)OPENSSL_realloc_clean(a->data,
a->length, w + 1);
if (c == NULL) {
ASN1err(ASN1_F_ASN1_BIT_STRING_SET_BIT, ERR_R_MALLOC_FAILURE);
return 0;
}
if (w + 1 - a->length > 0)
memset(c + a->length, 0, w + 1 - a->length);
a->data = c;
a->length = w + 1;
}
a->data[w] = ((a->data[w]) & iv) | v;
while ((a->length > 0) && (a->data[a->length - 1] == 0))
a->length--;
return (1);
}
int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n)
{
int w, v;
w = n / 8;
v = 1 << (7 - (n & 0x07));
if ((a == NULL) || (a->length < (w + 1)) || (a->data == NULL))
return (0);
return ((a->data[w] & v) != 0);
}
/*
* Checks if the given bit string contains only bits specified by
* the flags vector. Returns 0 if there is at least one bit set in 'a'
* which is not specified in 'flags', 1 otherwise.
* 'len' is the length of 'flags'.
*/
int ASN1_BIT_STRING_check(ASN1_BIT_STRING *a,
unsigned char *flags, int flags_len)
{
int i, ok;
/* Check if there is one bit set at all. */
if (!a || !a->data)
return 1;
/*
* Check each byte of the internal representation of the bit string.
*/
ok = 1;
for (i = 0; i < a->length && ok; ++i) {
unsigned char mask = i < flags_len ? ~flags[i] : 0xff;
/* We are done if there is an unneeded bit set. */
ok = (a->data[i] & mask) == 0;
}
return ok;
}
+464
View File
@@ -0,0 +1,464 @@
/* crypto/asn1/a_int.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* 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 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 acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS 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 AUTHOR OR 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.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/asn1.h>
#include <openssl/bn.h>
ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x)
{
return M_ASN1_INTEGER_dup(x);
}
int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y)
{
int neg, ret;
/* Compare signs */
neg = x->type & V_ASN1_NEG;
if (neg != (y->type & V_ASN1_NEG)) {
if (neg)
return -1;
else
return 1;
}
ret = ASN1_STRING_cmp(x, y);
if (neg)
return -ret;
else
return ret;
}
/*-
* This converts an ASN1 INTEGER into its content encoding.
* The internal representation is an ASN1_STRING whose data is a big endian
* representation of the value, ignoring the sign. The sign is determined by
* the type: V_ASN1_INTEGER for positive and V_ASN1_NEG_INTEGER for negative.
*
* Positive integers are no problem: they are almost the same as the DER
* encoding, except if the first byte is >= 0x80 we need to add a zero pad.
*
* Negative integers are a bit trickier...
* The DER representation of negative integers is in 2s complement form.
* The internal form is converted by complementing each octet and finally
* adding one to the result. This can be done less messily with a little trick.
* If the internal form has trailing zeroes then they will become FF by the
* complement and 0 by the add one (due to carry) so just copy as many trailing
* zeros to the destination as there are in the source. The carry will add one
* to the last none zero octet: so complement this octet and add one and finally
* complement any left over until you get to the start of the string.
*
* Padding is a little trickier too. If the first bytes is > 0x80 then we pad
* with 0xff. However if the first byte is 0x80 and one of the following bytes
* is non-zero we pad with 0xff. The reason for this distinction is that 0x80
* followed by optional zeros isn't padded.
*/
int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp)
{
int pad = 0, ret, i, neg;
unsigned char *p, *n, pb = 0;
if (a == NULL)
return (0);
neg = a->type & V_ASN1_NEG;
if (a->length == 0)
ret = 1;
else {
ret = a->length;
i = a->data[0];
if (ret == 1 && i == 0)
neg = 0;
if (!neg && (i > 127)) {
pad = 1;
pb = 0;
} else if (neg) {
if (i > 128) {
pad = 1;
pb = 0xFF;
} else if (i == 128) {
/*
* Special case: if any other bytes non zero we pad:
* otherwise we don't.
*/
for (i = 1; i < a->length; i++)
if (a->data[i]) {
pad = 1;
pb = 0xFF;
break;
}
}
}
ret += pad;
}
if (pp == NULL)
return (ret);
p = *pp;
if (pad)
*(p++) = pb;
if (a->length == 0)
*(p++) = 0;
else if (!neg)
memcpy(p, a->data, (unsigned int)a->length);
else {
/* Begin at the end of the encoding */
n = a->data + a->length - 1;
p += a->length - 1;
i = a->length;
/* Copy zeros to destination as long as source is zero */
while (!*n && i > 1) {
*(p--) = 0;
n--;
i--;
}
/* Complement and increment next octet */
*(p--) = ((*(n--)) ^ 0xff) + 1;
i--;
/* Complement any octets left */
for (; i > 0; i--)
*(p--) = *(n--) ^ 0xff;
}
*pp += ret;
return (ret);
}
/* Convert just ASN1 INTEGER content octets to ASN1_INTEGER structure */
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 = M_ASN1_INTEGER_new()) == NULL)
return (NULL);
ret->type = V_ASN1_INTEGER;
} else
ret = (*a);
p = *pp;
pend = p + len;
/*
* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it signifies
* a missing NULL parameter.
*/
s = (unsigned char *)OPENSSL_malloc((int)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, (int)len);
}
if (ret->data != NULL)
OPENSSL_free(ret->data);
ret->data = s;
ret->length = (int)len;
if (a != NULL)
(*a) = ret;
*pp = pend;
return (ret);
err:
ASN1err(ASN1_F_C2I_ASN1_INTEGER, i);
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
M_ASN1_INTEGER_free(ret);
return (NULL);
}
/*
* This is a version of d2i_ASN1_INTEGER that ignores the sign bit of ASN1
* integers: some broken software can encode a positive INTEGER with its MSB
* set as negative (it doesn't add a padding zero).
*/
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 = M_ASN1_INTEGER_new()) == NULL)
return (NULL);
ret->type = V_ASN1_INTEGER;
} 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 OPENSSL_malloc stuff, even for 0 bytes otherwise it signifies
* a missing NULL parameter.
*/
s = (unsigned char *)OPENSSL_malloc((int)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, (int)len);
p += len;
}
if (ret->data != NULL)
OPENSSL_free(ret->data);
ret->data = s;
ret->length = (int)len;
if (a != NULL)
(*a) = ret;
*pp = p;
return (ret);
err:
ASN1err(ASN1_F_D2I_ASN1_UINTEGER, i);
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
M_ASN1_INTEGER_free(ret);
return (NULL);
}
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;
if (a->length < (int)(sizeof(long) + 1)) {
if (a->data != NULL)
OPENSSL_free(a->data);
if ((a->data =
(unsigned char *)OPENSSL_malloc(sizeof(long) + 1)) != NULL)
memset((char *)a->data, 0, sizeof(long) + 1);
}
if (a->data == NULL) {
ASN1err(ASN1_F_ASN1_INTEGER_SET, 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);
}
long ASN1_INTEGER_get(const ASN1_INTEGER *a)
{
int neg = 0, i;
long r = 0;
if (a == NULL)
return (0L);
i = a->type;
if (i == V_ASN1_NEG_INTEGER)
neg = 1;
else if (i != V_ASN1_INTEGER)
return -1;
if (a->length > (int)sizeof(long)) {
/* hmm... a bit ugly, return all ones */
return -1;
}
if (a->data == NULL)
return 0;
for (i = 0; i < a->length; i++) {
r <<= 8;
r |= (unsigned char)a->data[i];
}
if (neg)
r = -r;
return (r);
}
ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai)
{
ASN1_INTEGER *ret;
int len, j;
if (ai == NULL)
ret = M_ASN1_INTEGER_new();
else
ret = ai;
if (ret == NULL) {
ASN1err(ASN1_F_BN_TO_ASN1_INTEGER, ERR_R_NESTED_ASN1_ERROR);
goto err;
}
if (BN_is_negative(bn) && !BN_is_zero(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 = OPENSSL_realloc(ret->data, len + 4);
if (!new_data) {
ASN1err(ASN1_F_BN_TO_ASN1_INTEGER, 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)
M_ASN1_INTEGER_free(ret);
return (NULL);
}
BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn)
{
BIGNUM *ret;
if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL)
ASN1err(ASN1_F_ASN1_INTEGER_TO_BN, ASN1_R_BN_LIB);
else if (ai->type == V_ASN1_NEG_INTEGER)
BN_set_negative(ret, 1);
return (ret);
}
IMPLEMENT_STACK_OF(ASN1_INTEGER)
IMPLEMENT_ASN1_SET_OF(ASN1_INTEGER)
@@ -0,0 +1,406 @@
/* crypto/asn1/a_object.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* 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 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 acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS 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 AUTHOR OR 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.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include <limits.h>
#include "cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/asn1.h>
#include <openssl/objects.h>
#include <openssl/bn.h>
int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp)
{
unsigned char *p;
int objsize;
if ((a == NULL) || (a->data == NULL))
return (0);
objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT);
if (pp == NULL || objsize == -1)
return objsize;
p = *pp;
ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
memcpy(p, a->data, a->length);
p += a->length;
*pp = p;
return (objsize);
}
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 {
ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_FIRST_NUM_TOO_LARGE);
goto err;
}
if (num <= 0) {
ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_MISSING_SECOND_NUMBER);
goto err;
}
c = *(p++);
num--;
for (;;) {
if (num <= 0)
break;
if ((c != '.') && (c != ' ')) {
ASN1err(ASN1_F_A2D_ASN1_OBJECT, 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')) {
ASN1err(ASN1_F_A2D_ASN1_OBJECT, 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)) {
ASN1err(ASN1_F_A2D_ASN1_OBJECT,
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)
OPENSSL_free(tmp);
tmpsize = blsize + 32;
tmp = OPENSSL_malloc(tmpsize);
if (!tmp)
goto err;
}
while (blsize--) {
BN_ULONG t = BN_div_word(bl, 0x80L);
if (t == (BN_ULONG)-1)
goto err;
tmp[i++] = (unsigned char)t;
}
} else {
for (;;) {
tmp[i++] = (unsigned char)l & 0x7f;
l >>= 7L;
if (l == 0L)
break;
}
}
if (out != NULL) {
if (len + i > olen) {
ASN1err(ASN1_F_A2D_ASN1_OBJECT, 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)
OPENSSL_free(tmp);
if (bl)
BN_free(bl);
return (len);
err:
if (tmp != ftmp)
OPENSSL_free(tmp);
if (bl)
BN_free(bl);
return (0);
}
int i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *a)
{
return OBJ_obj2txt(buf, buf_len, a, 0);
}
int i2a_ASN1_OBJECT(BIO *bp, ASN1_OBJECT *a)
{
char buf[80], *p = buf;
int i;
if ((a == NULL) || (a->data == NULL))
return (BIO_write(bp, "NULL", 4));
i = i2t_ASN1_OBJECT(buf, sizeof buf, a);
if (i > (int)(sizeof(buf) - 1)) {
p = OPENSSL_malloc(i + 1);
if (!p)
return -1;
i2t_ASN1_OBJECT(p, i + 1, a);
}
if (i <= 0)
return BIO_write(bp, "<INVALID>", 9);
BIO_write(bp, p, i);
if (p != buf)
OPENSSL_free(p);
return (i);
}
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:
ASN1err(ASN1_F_D2I_ASN1_OBJECT, i);
return (NULL);
}
ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
long len)
{
ASN1_OBJECT *ret = NULL;
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) {
ASN1err(ASN1_F_C2I_ASN1_OBJECT, 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))) {
ASN1err(ASN1_F_C2I_ASN1_OBJECT, 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;
ret->data = NULL;
/* once detached we can change it */
if ((data == NULL) || (ret->length < length)) {
ret->length = 0;
if (data != NULL)
OPENSSL_free(data);
data = (unsigned char *)OPENSSL_malloc(length);
if (data == NULL) {
i = ERR_R_MALLOC_FAILURE;
goto err;
}
ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;
}
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; we know it is dynamic */
p += length;
if (a != NULL)
(*a) = ret;
*pp = p;
return (ret);
err:
ASN1err(ASN1_F_C2I_ASN1_OBJECT, i);
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
ASN1_OBJECT_free(ret);
return (NULL);
}
ASN1_OBJECT *ASN1_OBJECT_new(void)
{
ASN1_OBJECT *ret;
ret = (ASN1_OBJECT *)OPENSSL_malloc(sizeof(ASN1_OBJECT));
if (ret == NULL) {
ASN1err(ASN1_F_ASN1_OBJECT_NEW, 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);
}
void ASN1_OBJECT_free(ASN1_OBJECT *a)
{
if (a == NULL)
return;
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) {
#ifndef CONST_STRICT /* disable purely for compile-time strict
* const checking. Doing this on a "real"
* compile will cause memory leaks */
if (a->sn != NULL)
OPENSSL_free((void *)a->sn);
if (a->ln != NULL)
OPENSSL_free((void *)a->ln);
#endif
a->sn = a->ln = NULL;
}
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) {
if (a->data != NULL)
OPENSSL_free((void *)a->data);
a->data = NULL;
a->length = 0;
}
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC)
OPENSSL_free(a);
}
ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, int len,
const char *sn, const char *ln)
{
ASN1_OBJECT o;
o.sn = sn;
o.ln = ln;
o.data = data;
o.nid = nid;
o.length = len;
o.flags = ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
ASN1_OBJECT_FLAG_DYNAMIC_DATA;
return (OBJ_dup(&o));
}
IMPLEMENT_STACK_OF(ASN1_OBJECT)
IMPLEMENT_ASN1_SET_OF(ASN1_OBJECT)
@@ -0,0 +1,78 @@
/* crypto/asn1/a_octet.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* 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 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 acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS 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 AUTHOR OR 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.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/asn1.h>
ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *x)
{
return M_ASN1_OCTET_STRING_dup(x);
}
int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a,
const ASN1_OCTET_STRING *b)
{
return M_ASN1_OCTET_STRING_cmp(a, b);
}
int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *x, const unsigned char *d,
int len)
{
return M_ASN1_OCTET_STRING_set(x, d, len);
}
+155
View File
@@ -0,0 +1,155 @@
/* crypto/asn1/a_type.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* 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 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 acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS 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 AUTHOR OR 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.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/objects.h>
int ASN1_TYPE_get(ASN1_TYPE *a)
{
if ((a->value.ptr != NULL) || (a->type == V_ASN1_NULL))
return (a->type);
else
return (0);
}
void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value)
{
if (a->value.ptr != NULL) {
ASN1_TYPE **tmp_a = &a;
ASN1_primitive_free((ASN1_VALUE **)tmp_a, NULL);
}
a->type = type;
if (type == V_ASN1_BOOLEAN)
a->value.boolean = value ? 0xff : 0;
else
a->value.ptr = value;
}
int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value)
{
if (!value || (type == V_ASN1_BOOLEAN)) {
void *p = (void *)value;
ASN1_TYPE_set(a, type, p);
} else if (type == V_ASN1_OBJECT) {
ASN1_OBJECT *odup;
odup = OBJ_dup(value);
if (!odup)
return 0;
ASN1_TYPE_set(a, type, odup);
} else {
ASN1_STRING *sdup;
sdup = ASN1_STRING_dup(value);
if (!sdup)
return 0;
ASN1_TYPE_set(a, type, sdup);
}
return 1;
}
IMPLEMENT_STACK_OF(ASN1_TYPE)
IMPLEMENT_ASN1_SET_OF(ASN1_TYPE)
/* Returns 0 if they are equal, != 0 otherwise. */
int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b)
{
int result = -1;
if (!a || !b || a->type != b->type)
return -1;
switch (a->type) {
case V_ASN1_OBJECT:
result = OBJ_cmp(a->value.object, b->value.object);
break;
case V_ASN1_BOOLEAN:
result = a->value.boolean - b->value.boolean;
break;
case V_ASN1_NULL:
result = 0; /* They do not have content. */
break;
case V_ASN1_INTEGER:
case V_ASN1_ENUMERATED:
case V_ASN1_BIT_STRING:
case V_ASN1_OCTET_STRING:
case V_ASN1_SEQUENCE:
case V_ASN1_SET:
case V_ASN1_NUMERICSTRING:
case V_ASN1_PRINTABLESTRING:
case V_ASN1_T61STRING:
case V_ASN1_VIDEOTEXSTRING:
case V_ASN1_IA5STRING:
case V_ASN1_UTCTIME:
case V_ASN1_GENERALIZEDTIME:
case V_ASN1_GRAPHICSTRING:
case V_ASN1_VISIBLESTRING:
case V_ASN1_GENERALSTRING:
case V_ASN1_UNIVERSALSTRING:
case V_ASN1_BMPSTRING:
case V_ASN1_UTF8STRING:
case V_ASN1_OTHER:
default:
result = ASN1_STRING_cmp((ASN1_STRING *)a->value.ptr,
(ASN1_STRING *)b->value.ptr);
break;
}
return result;
}
@@ -0,0 +1,488 @@
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 2006.
*/
/* ====================================================================
* Copyright (c) 2006 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 "cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#ifndef OPENSSL_NO_ENGINE
# include <openssl/engine.h>
#endif
#include "asn1_locl.h"
int strncasecmp(const char *s1, const char *s2, int n);
extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[];
extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[];
extern const EVP_PKEY_ASN1_METHOD dh_asn1_meth;
extern const EVP_PKEY_ASN1_METHOD dhx_asn1_meth;
extern const EVP_PKEY_ASN1_METHOD eckey_asn1_meth;
extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth;
extern const EVP_PKEY_ASN1_METHOD cmac_asn1_meth;
/* Keep this sorted in type order !! */
static const EVP_PKEY_ASN1_METHOD *standard_methods[] = {
#ifndef OPENSSL_NO_RSA
&rsa_asn1_meths[0],
&rsa_asn1_meths[1],
#endif
#ifndef OPENSSL_NO_DH
&dh_asn1_meth,
#endif
#ifndef OPENSSL_NO_DSA
&dsa_asn1_meths[0],
&dsa_asn1_meths[1],
&dsa_asn1_meths[2],
&dsa_asn1_meths[3],
&dsa_asn1_meths[4],
#endif
#ifndef OPENSSL_NO_EC
&eckey_asn1_meth,
#endif
&hmac_asn1_meth,
#ifndef OPENSSL_NO_CMAC
&cmac_asn1_meth,
#endif
#ifndef OPENSSL_NO_DH
&dhx_asn1_meth
#endif
};
typedef int sk_cmp_fn_type(const char *const *a, const char *const *b);
DECLARE_STACK_OF(EVP_PKEY_ASN1_METHOD)
static STACK_OF(EVP_PKEY_ASN1_METHOD) *app_methods = NULL;
#ifdef TEST
void main()
{
int i;
for (i = 0;
i < sizeof(standard_methods) / sizeof(EVP_PKEY_ASN1_METHOD *); i++)
fprintf(stderr, "Number %d id=%d (%s)\n", i,
standard_methods[i]->pkey_id,
OBJ_nid2sn(standard_methods[i]->pkey_id));
}
#endif
DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_ASN1_METHOD *,
const EVP_PKEY_ASN1_METHOD *, ameth);
static int ameth_cmp(const EVP_PKEY_ASN1_METHOD *const *a,
const EVP_PKEY_ASN1_METHOD *const *b)
{
return ((*a)->pkey_id - (*b)->pkey_id);
}
IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_ASN1_METHOD *,
const EVP_PKEY_ASN1_METHOD *, ameth);
int EVP_PKEY_asn1_get_count(void)
{
int num = sizeof(standard_methods) / sizeof(EVP_PKEY_ASN1_METHOD *);
if (app_methods)
num += sk_EVP_PKEY_ASN1_METHOD_num(app_methods);
return num;
}
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx)
{
int num = sizeof(standard_methods) / sizeof(EVP_PKEY_ASN1_METHOD *);
if (idx < 0)
return NULL;
if (idx < num)
return standard_methods[idx];
idx -= num;
return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx);
}
static const EVP_PKEY_ASN1_METHOD *pkey_asn1_find(int type)
{
EVP_PKEY_ASN1_METHOD tmp;
const EVP_PKEY_ASN1_METHOD *t = &tmp, **ret;
tmp.pkey_id = type;
if (app_methods) {
int idx;
idx = sk_EVP_PKEY_ASN1_METHOD_find(app_methods, &tmp);
if (idx >= 0)
return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx);
}
ret = OBJ_bsearch_ameth(&t, standard_methods, sizeof(standard_methods)
/ sizeof(EVP_PKEY_ASN1_METHOD *));
if (!ret || !*ret)
return NULL;
return *ret;
}
/*
* Find an implementation of an ASN1 algorithm. If 'pe' is not NULL also
* search through engines and set *pe to a functional reference to the engine
* implementing 'type' or NULL if no engine implements it.
*/
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pe, int type)
{
const EVP_PKEY_ASN1_METHOD *t;
for (;;) {
t = pkey_asn1_find(type);
if (!t || !(t->pkey_flags & ASN1_PKEY_ALIAS))
break;
type = t->pkey_base_id;
}
if (pe) {
#ifndef OPENSSL_NO_ENGINE
ENGINE *e;
/* type will contain the final unaliased type */
e = ENGINE_get_pkey_asn1_meth_engine(type);
if (e) {
*pe = e;
return ENGINE_get_pkey_asn1_meth(e, type);
}
#endif
*pe = NULL;
}
return t;
}
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe,
const char *str, int len)
{
int i;
const EVP_PKEY_ASN1_METHOD *ameth;
if (len == -1)
len = strlen(str);
if (pe) {
#ifndef OPENSSL_NO_ENGINE
ENGINE *e;
ameth = ENGINE_pkey_asn1_find_str(&e, str, len);
if (ameth) {
/*
* Convert structural into functional reference
*/
if (!ENGINE_init(e))
ameth = NULL;
ENGINE_free(e);
*pe = e;
return ameth;
}
#endif
*pe = NULL;
}
for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) {
ameth = EVP_PKEY_asn1_get0(i);
if (ameth->pkey_flags & ASN1_PKEY_ALIAS)
continue;
if (((int)strlen(ameth->pem_str) == len) &&
!strncasecmp(ameth->pem_str, str, len))
return ameth;
}
return NULL;
}
int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth)
{
if (app_methods == NULL) {
app_methods = sk_EVP_PKEY_ASN1_METHOD_new(ameth_cmp);
if (!app_methods)
return 0;
}
if (!sk_EVP_PKEY_ASN1_METHOD_push(app_methods, ameth))
return 0;
sk_EVP_PKEY_ASN1_METHOD_sort(app_methods);
return 1;
}
int EVP_PKEY_asn1_add_alias(int to, int from)
{
EVP_PKEY_ASN1_METHOD *ameth;
ameth = EVP_PKEY_asn1_new(from, ASN1_PKEY_ALIAS, NULL, NULL);
if (!ameth)
return 0;
ameth->pkey_base_id = to;
if (!EVP_PKEY_asn1_add0(ameth)) {
EVP_PKEY_asn1_free(ameth);
return 0;
}
return 1;
}
int EVP_PKEY_asn1_get0_info(int *ppkey_id, int *ppkey_base_id,
int *ppkey_flags, const char **pinfo,
const char **ppem_str,
const EVP_PKEY_ASN1_METHOD *ameth)
{
if (!ameth)
return 0;
if (ppkey_id)
*ppkey_id = ameth->pkey_id;
if (ppkey_base_id)
*ppkey_base_id = ameth->pkey_base_id;
if (ppkey_flags)
*ppkey_flags = ameth->pkey_flags;
if (pinfo)
*pinfo = ameth->info;
if (ppem_str)
*ppem_str = ameth->pem_str;
return 1;
}
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_get0_asn1(EVP_PKEY *pkey)
{
return pkey->ameth;
}
EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_new(int id, int flags,
const char *pem_str, const char *info)
{
EVP_PKEY_ASN1_METHOD *ameth;
ameth = OPENSSL_malloc(sizeof(EVP_PKEY_ASN1_METHOD));
if (!ameth)
return NULL;
memset(ameth, 0, sizeof(EVP_PKEY_ASN1_METHOD));
ameth->pkey_id = id;
ameth->pkey_base_id = id;
ameth->pkey_flags = flags | ASN1_PKEY_DYNAMIC;
if (info) {
ameth->info = BUF_strdup(info);
if (!ameth->info)
goto err;
} else
ameth->info = NULL;
if (pem_str) {
ameth->pem_str = BUF_strdup(pem_str);
if (!ameth->pem_str)
goto err;
} else
ameth->pem_str = NULL;
ameth->pub_decode = 0;
ameth->pub_encode = 0;
ameth->pub_cmp = 0;
ameth->pub_print = 0;
ameth->priv_decode = 0;
ameth->priv_encode = 0;
ameth->priv_print = 0;
ameth->old_priv_encode = 0;
ameth->old_priv_decode = 0;
ameth->item_verify = 0;
ameth->item_sign = 0;
ameth->pkey_size = 0;
ameth->pkey_bits = 0;
ameth->param_decode = 0;
ameth->param_encode = 0;
ameth->param_missing = 0;
ameth->param_copy = 0;
ameth->param_cmp = 0;
ameth->param_print = 0;
ameth->pkey_free = 0;
ameth->pkey_ctrl = 0;
return ameth;
err:
EVP_PKEY_asn1_free(ameth);
return NULL;
}
void EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst,
const EVP_PKEY_ASN1_METHOD *src)
{
dst->pub_decode = src->pub_decode;
dst->pub_encode = src->pub_encode;
dst->pub_cmp = src->pub_cmp;
dst->pub_print = src->pub_print;
dst->priv_decode = src->priv_decode;
dst->priv_encode = src->priv_encode;
dst->priv_print = src->priv_print;
dst->old_priv_encode = src->old_priv_encode;
dst->old_priv_decode = src->old_priv_decode;
dst->pkey_size = src->pkey_size;
dst->pkey_bits = src->pkey_bits;
dst->param_decode = src->param_decode;
dst->param_encode = src->param_encode;
dst->param_missing = src->param_missing;
dst->param_copy = src->param_copy;
dst->param_cmp = src->param_cmp;
dst->param_print = src->param_print;
dst->pkey_free = src->pkey_free;
dst->pkey_ctrl = src->pkey_ctrl;
dst->item_sign = src->item_sign;
dst->item_verify = src->item_verify;
}
void EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth)
{
if (ameth && (ameth->pkey_flags & ASN1_PKEY_DYNAMIC)) {
if (ameth->pem_str)
OPENSSL_free(ameth->pem_str);
if (ameth->info)
OPENSSL_free(ameth->info);
OPENSSL_free(ameth);
}
}
void EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth,
int (*pub_decode) (EVP_PKEY *pk,
X509_PUBKEY *pub),
int (*pub_encode) (X509_PUBKEY *pub,
const EVP_PKEY *pk),
int (*pub_cmp) (const EVP_PKEY *a,
const EVP_PKEY *b),
int (*pub_print) (BIO *out,
const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx),
int (*pkey_size) (const EVP_PKEY *pk),
int (*pkey_bits) (const EVP_PKEY *pk))
{
ameth->pub_decode = pub_decode;
ameth->pub_encode = pub_encode;
ameth->pub_cmp = pub_cmp;
ameth->pub_print = pub_print;
ameth->pkey_size = pkey_size;
ameth->pkey_bits = pkey_bits;
}
void EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth,
int (*priv_decode) (EVP_PKEY *pk,
PKCS8_PRIV_KEY_INFO
*p8inf),
int (*priv_encode) (PKCS8_PRIV_KEY_INFO *p8,
const EVP_PKEY *pk),
int (*priv_print) (BIO *out,
const EVP_PKEY *pkey,
int indent,
ASN1_PCTX *pctx))
{
ameth->priv_decode = priv_decode;
ameth->priv_encode = priv_encode;
ameth->priv_print = priv_print;
}
void EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth,
int (*param_decode) (EVP_PKEY *pkey,
const unsigned char **pder,
int derlen),
int (*param_encode) (const EVP_PKEY *pkey,
unsigned char **pder),
int (*param_missing) (const EVP_PKEY *pk),
int (*param_copy) (EVP_PKEY *to,
const EVP_PKEY *from),
int (*param_cmp) (const EVP_PKEY *a,
const EVP_PKEY *b),
int (*param_print) (BIO *out,
const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx))
{
ameth->param_decode = param_decode;
ameth->param_encode = param_encode;
ameth->param_missing = param_missing;
ameth->param_copy = param_copy;
ameth->param_cmp = param_cmp;
ameth->param_print = param_print;
}
void EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth,
void (*pkey_free) (EVP_PKEY *pkey))
{
ameth->pkey_free = pkey_free;
}
void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
int (*pkey_ctrl) (EVP_PKEY *pkey, int op,
long arg1, void *arg2))
{
ameth->pkey_ctrl = pkey_ctrl;
}
void EVP_PKEY_asn1_set_item(EVP_PKEY_ASN1_METHOD *ameth,
int (*item_verify) (EVP_MD_CTX *ctx,
const ASN1_ITEM *it,
void *asn,
X509_ALGOR *a,
ASN1_BIT_STRING *sig,
EVP_PKEY *pkey),
int (*item_sign) (EVP_MD_CTX *ctx,
const ASN1_ITEM *it,
void *asn,
X509_ALGOR *alg1,
X509_ALGOR *alg2,
ASN1_BIT_STRING *sig))
{
ameth->item_sign = item_sign;
ameth->item_verify = item_verify;
}
@@ -0,0 +1,483 @@
/* crypto/asn1/asn1_lib.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* 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 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 acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS 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 AUTHOR OR 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.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include <limits.h>
#include "cryptlib.h"
#include <openssl/asn1.h>
#include <openssl/asn1_mac.h>
static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
long max);
static void asn1_put_length(unsigned char **pp, int length);
const char ASN1_version[] = "ASN.1" OPENSSL_VERSION_PTEXT;
static int _asn1_check_infinite_end(const unsigned char **p, long len)
{
/*
* If there is 0 or 1 byte left, the length check should pick things up
*/
if (len <= 0)
return (1);
else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0)) {
(*p) += 2;
return (1);
}
return (0);
}
int ASN1_check_infinite_end(unsigned char **p, long len)
{
return _asn1_check_infinite_end((const unsigned char **)p, len);
}
int ASN1_const_check_infinite_end(const unsigned char **p, long len)
{
return _asn1_check_infinite_end(p, len);
}
int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
int *pclass, long omax)
{
int i, ret;
long l;
const unsigned char *p = *pp;
int tag, xclass, inf;
long max = omax;
if (!max)
goto err;
ret = (*p & V_ASN1_CONSTRUCTED);
xclass = (*p & V_ASN1_PRIVATE);
i = *p & V_ASN1_PRIMITIVE_TAG;
if (i == V_ASN1_PRIMITIVE_TAG) { /* high-tag */
p++;
if (--max == 0)
goto err;
l = 0;
while (*p & 0x80) {
l <<= 7L;
l |= *(p++) & 0x7f;
if (--max == 0)
goto err;
if (l > (INT_MAX >> 7L))
goto err;
}
l <<= 7L;
l |= *(p++) & 0x7f;
tag = (int)l;
if (--max == 0)
goto err;
} else {
tag = i;
p++;
if (--max == 0)
goto err;
}
*ptag = tag;
*pclass = xclass;
if (!asn1_get_length(&p, &inf, plength, max))
goto err;
if (inf && !(ret & V_ASN1_CONSTRUCTED))
goto err;
#if 0
fprintf(stderr, "p=%d + *plength=%ld > omax=%ld + *pp=%d (%d > %d)\n",
(int)p, *plength, omax, (int)*pp, (int)(p + *plength),
(int)(omax + *pp));
#endif
if (*plength > (omax - (p - *pp))) {
ASN1err(ASN1_F_ASN1_GET_OBJECT, ASN1_R_TOO_LONG);
/*
* Set this so that even if things are not long enough the values are
* set correctly
*/
ret |= 0x80;
}
*pp = p;
return (ret | inf);
err:
ASN1err(ASN1_F_ASN1_GET_OBJECT, ASN1_R_HEADER_TOO_LONG);
return (0x80);
}
static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
long max)
{
const unsigned char *p = *pp;
unsigned long ret = 0;
unsigned long i;
if (max-- < 1)
return 0;
if (*p == 0x80) {
*inf = 1;
ret = 0;
p++;
} else {
*inf = 0;
i = *p & 0x7f;
if (*(p++) & 0x80) {
if (i > sizeof(ret) || max < (long)i)
return 0;
while (i-- > 0) {
ret <<= 8L;
ret |= *(p++);
}
} else
ret = i;
}
if (ret > LONG_MAX)
return 0;
*pp = p;
*rl = (long)ret;
return 1;
}
/*
* class 0 is constructed constructed == 2 for indefinite length constructed
*/
void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
int xclass)
{
unsigned char *p = *pp;
int i, ttag;
i = (constructed) ? V_ASN1_CONSTRUCTED : 0;
i |= (xclass & V_ASN1_PRIVATE);
if (tag < 31)
*(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG);
else {
*(p++) = i | V_ASN1_PRIMITIVE_TAG;
for (i = 0, ttag = tag; ttag > 0; i++)
ttag >>= 7;
ttag = i;
while (i-- > 0) {
p[i] = tag & 0x7f;
if (i != (ttag - 1))
p[i] |= 0x80;
tag >>= 7;
}
p += ttag;
}
if (constructed == 2)
*(p++) = 0x80;
else
asn1_put_length(&p, length);
*pp = p;
}
int ASN1_put_eoc(unsigned char **pp)
{
unsigned char *p = *pp;
*p++ = 0;
*p++ = 0;
*pp = p;
return 2;
}
static void asn1_put_length(unsigned char **pp, int length)
{
unsigned char *p = *pp;
int i, l;
if (length <= 127)
*(p++) = (unsigned char)length;
else {
l = length;
for (i = 0; l > 0; i++)
l >>= 8;
*(p++) = i | 0x80;
l = i;
while (i-- > 0) {
p[i] = length & 0xff;
length >>= 8;
}
p += l;
}
*pp = p;
}
int ASN1_object_size(int constructed, int length, int tag)
{
int ret = 1;
if (length < 0)
return -1;
if (tag >= 31) {
while (tag > 0) {
tag >>= 7;
ret++;
}
}
if (constructed == 2) {
ret += 3;
} else {
ret++;
if (length > 127) {
int tmplen = length;
while (tmplen > 0) {
tmplen >>= 8;
ret++;
}
}
}
if (ret >= INT_MAX - length)
return -1;
return ret + length;
}
static int _asn1_Finish(ASN1_const_CTX *c)
{
if ((c->inf == (1 | V_ASN1_CONSTRUCTED)) && (!c->eos)) {
if (!ASN1_const_check_infinite_end(&c->p, c->slen)) {
c->error = ERR_R_MISSING_ASN1_EOS;
return (0);
}
}
if (((c->slen != 0) && !(c->inf & 1)) || ((c->slen < 0) && (c->inf & 1))) {
c->error = ERR_R_ASN1_LENGTH_MISMATCH;
return (0);
}
return (1);
}
int asn1_Finish(ASN1_CTX *c)
{
return _asn1_Finish((ASN1_const_CTX *)c);
}
int asn1_const_Finish(ASN1_const_CTX *c)
{
return _asn1_Finish(c);
}
int asn1_GetSequence(ASN1_const_CTX *c, long *length)
{
const unsigned char *q;
q = c->p;
c->inf = ASN1_get_object(&(c->p), &(c->slen), &(c->tag), &(c->xclass),
*length);
if (c->inf & 0x80) {
c->error = ERR_R_BAD_GET_ASN1_OBJECT_CALL;
return (0);
}
if (c->tag != V_ASN1_SEQUENCE) {
c->error = ERR_R_EXPECTING_AN_ASN1_SEQUENCE;
return (0);
}
(*length) -= (c->p - q);
if (c->max && (*length < 0)) {
c->error = ERR_R_ASN1_LENGTH_MISMATCH;
return (0);
}
if (c->inf == (1 | V_ASN1_CONSTRUCTED))
c->slen = *length;
c->eos = 0;
return (1);
}
int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str)
{
if (str == NULL)
return 0;
dst->type = str->type;
if (!ASN1_STRING_set(dst, str->data, str->length))
return 0;
dst->flags = str->flags;
return 1;
}
ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str)
{
ASN1_STRING *ret;
if (!str)
return NULL;
ret = ASN1_STRING_new();
if (!ret)
return NULL;
if (!ASN1_STRING_copy(ret, str)) {
ASN1_STRING_free(ret);
return NULL;
}
return ret;
}
int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len)
{
unsigned char *c;
const char *data = _data;
if (len < 0) {
if (data == NULL)
return (0);
else
len = strlen(data);
}
if ((str->length <= len) || (str->data == NULL)) {
c = str->data;
if (c == NULL)
str->data = OPENSSL_malloc(len + 1);
else
str->data = OPENSSL_realloc(c, len + 1);
if (str->data == NULL) {
ASN1err(ASN1_F_ASN1_STRING_SET, ERR_R_MALLOC_FAILURE);
str->data = c;
return (0);
}
}
str->length = len;
if (data != NULL) {
memcpy(str->data, data, len);
/* an allowance for strings :-) */
str->data[len] = '\0';
}
return (1);
}
void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len)
{
if (str->data)
OPENSSL_free(str->data);
str->data = data;
str->length = len;
}
ASN1_STRING *ASN1_STRING_new(void)
{
return (ASN1_STRING_type_new(V_ASN1_OCTET_STRING));
}
ASN1_STRING *ASN1_STRING_type_new(int type)
{
ASN1_STRING *ret;
ret = (ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING));
if (ret == NULL) {
ASN1err(ASN1_F_ASN1_STRING_TYPE_NEW, ERR_R_MALLOC_FAILURE);
return (NULL);
}
ret->length = 0;
ret->type = type;
ret->data = NULL;
ret->flags = 0;
return (ret);
}
void ASN1_STRING_free(ASN1_STRING *a)
{
if (a == NULL)
return;
if (a->data && !(a->flags & ASN1_STRING_FLAG_NDEF))
OPENSSL_free(a->data);
OPENSSL_free(a);
}
void ASN1_STRING_clear_free(ASN1_STRING *a)
{
if (a && a->data && !(a->flags & ASN1_STRING_FLAG_NDEF))
OPENSSL_cleanse(a->data, a->length);
ASN1_STRING_free(a);
}
int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
{
int i;
i = (a->length - b->length);
if (i == 0) {
i = memcmp(a->data, b->data, a->length);
if (i == 0)
return (a->type - b->type);
else
return (i);
} else
return (i);
}
void asn1_add_error(const unsigned char *address, int offset)
{
char buf1[DECIMAL_SIZE(address) + 1], buf2[DECIMAL_SIZE(offset) + 1];
BIO_snprintf(buf1, sizeof buf1, "%lu", (unsigned long)address);
BIO_snprintf(buf2, sizeof buf2, "%d", offset);
ERR_add_error_data(4, "address=", buf1, " offset=", buf2);
}
int ASN1_STRING_length(const ASN1_STRING *x)
{
return M_ASN1_STRING_length(x);
}
void ASN1_STRING_length_set(ASN1_STRING *x, int len)
{
M_ASN1_STRING_length_set(x, len);
return;
}
int ASN1_STRING_type(ASN1_STRING *x)
{
return M_ASN1_STRING_type(x);
}
unsigned char *ASN1_STRING_data(ASN1_STRING *x)
{
return M_ASN1_STRING_data(x);
}
@@ -0,0 +1,135 @@
/* asn1t.h */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 2006.
*/
/* ====================================================================
* Copyright (c) 2006 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).
*
*/
/* Internal ASN1 structures and functions: not for application use */
int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d);
int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d);
/* ASN1 print context structure */
struct asn1_pctx_st {
unsigned long flags;
unsigned long nm_flags;
unsigned long cert_flags;
unsigned long oid_flags;
unsigned long str_flags;
} /* ASN1_PCTX */ ;
/* ASN1 public key method structure */
struct evp_pkey_asn1_method_st {
int pkey_id;
int pkey_base_id;
unsigned long pkey_flags;
char *pem_str;
char *info;
int (*pub_decode) (EVP_PKEY *pk, X509_PUBKEY *pub);
int (*pub_encode) (X509_PUBKEY *pub, const EVP_PKEY *pk);
int (*pub_cmp) (const EVP_PKEY *a, const EVP_PKEY *b);
int (*pub_print) (BIO *out, const EVP_PKEY *pkey, int indent,
ASN1_PCTX *pctx);
int (*priv_decode) (EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf);
int (*priv_encode) (PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk);
int (*priv_print) (BIO *out, const EVP_PKEY *pkey, int indent,
ASN1_PCTX *pctx);
int (*pkey_size) (const EVP_PKEY *pk);
int (*pkey_bits) (const EVP_PKEY *pk);
int (*param_decode) (EVP_PKEY *pkey,
const unsigned char **pder, int derlen);
int (*param_encode) (const EVP_PKEY *pkey, unsigned char **pder);
int (*param_missing) (const EVP_PKEY *pk);
int (*param_copy) (EVP_PKEY *to, const EVP_PKEY *from);
int (*param_cmp) (const EVP_PKEY *a, const EVP_PKEY *b);
int (*param_print) (BIO *out, const EVP_PKEY *pkey, int indent,
ASN1_PCTX *pctx);
int (*sig_print) (BIO *out,
const X509_ALGOR *sigalg, const ASN1_STRING *sig,
int indent, ASN1_PCTX *pctx);
void (*pkey_free) (EVP_PKEY *pkey);
int (*pkey_ctrl) (EVP_PKEY *pkey, int op, long arg1, void *arg2);
/* Legacy functions for old PEM */
int (*old_priv_decode) (EVP_PKEY *pkey,
const unsigned char **pder, int derlen);
int (*old_priv_encode) (const EVP_PKEY *pkey, unsigned char **pder);
/* Custom ASN1 signature verification */
int (*item_verify) (EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
X509_ALGOR *a, ASN1_BIT_STRING *sig, EVP_PKEY *pkey);
int (*item_sign) (EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
X509_ALGOR *alg1, X509_ALGOR *alg2,
ASN1_BIT_STRING *sig);
} /* EVP_PKEY_ASN1_METHOD */ ;
/*
* Method to handle CRL access. In general a CRL could be very large (several
* Mb) and can consume large amounts of resources if stored in memory by
* multiple processes. This method allows general CRL operations to be
* redirected to more efficient callbacks: for example a CRL entry database.
*/
#define X509_CRL_METHOD_DYNAMIC 1
struct x509_crl_method_st {
int flags;
int (*crl_init) (X509_CRL *crl);
int (*crl_free) (X509_CRL *crl);
int (*crl_lookup) (X509_CRL *crl, X509_REVOKED **ret,
ASN1_INTEGER *ser, X509_NAME *issuer);
int (*crl_verify) (X509_CRL *crl, EVP_PKEY *pk);
};
@@ -0,0 +1,145 @@
/* p8_pkey.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 1999.
*/
/* ====================================================================
* Copyright (c) 1999-2005 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 "cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/x509.h>
/* Minor tweak to operation: zero private key data */
static int pkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg)
{
/* Since the structure must still be valid use ASN1_OP_FREE_PRE */
if (operation == ASN1_OP_FREE_PRE) {
PKCS8_PRIV_KEY_INFO *key = (PKCS8_PRIV_KEY_INFO *)*pval;
if (key->pkey && key->pkey->type == V_ASN1_OCTET_STRING
&& key->pkey->value.octet_string != NULL)
OPENSSL_cleanse(key->pkey->value.octet_string->data,
key->pkey->value.octet_string->length);
}
return 1;
}
ASN1_SEQUENCE_cb(PKCS8_PRIV_KEY_INFO, pkey_cb) = {
ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, version, ASN1_INTEGER),
ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkeyalg, X509_ALGOR),
ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkey, ASN1_ANY),
ASN1_IMP_SET_OF_OPT(PKCS8_PRIV_KEY_INFO, attributes, X509_ATTRIBUTE, 0)
} ASN1_SEQUENCE_END_cb(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO)
IMPLEMENT_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO)
int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj,
int version,
int ptype, void *pval, unsigned char *penc, int penclen)
{
unsigned char **ppenc = NULL;
if (version >= 0) {
if (!ASN1_INTEGER_set(priv->version, version))
return 0;
}
if (penc) {
int pmtype;
ASN1_OCTET_STRING *oct;
oct = ASN1_OCTET_STRING_new();
if (!oct)
return 0;
oct->data = penc;
ppenc = &oct->data;
oct->length = penclen;
if (priv->broken == PKCS8_NO_OCTET)
pmtype = V_ASN1_SEQUENCE;
else
pmtype = V_ASN1_OCTET_STRING;
ASN1_TYPE_set(priv->pkey, pmtype, oct);
}
if (!X509_ALGOR_set0(priv->pkeyalg, aobj, ptype, pval)) {
/* If call fails do not swallow 'enc' */
if (ppenc)
*ppenc = NULL;
return 0;
}
return 1;
}
int PKCS8_pkey_get0(ASN1_OBJECT **ppkalg,
const unsigned char **pk, int *ppklen,
X509_ALGOR **pa, PKCS8_PRIV_KEY_INFO *p8)
{
if (ppkalg)
*ppkalg = p8->pkeyalg->algorithm;
if (p8->pkey->type == V_ASN1_OCTET_STRING) {
p8->broken = PKCS8_OK;
if (pk) {
*pk = p8->pkey->value.octet_string->data;
*ppklen = p8->pkey->value.octet_string->length;
}
} else if (p8->pkey->type == V_ASN1_SEQUENCE) {
p8->broken = PKCS8_NO_OCTET;
if (pk) {
*pk = p8->pkey->value.sequence->data;
*ppklen = p8->pkey->value.sequence->length;
}
} else
return 0;
if (pa)
*pa = p8->pkeyalg;
return 1;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,667 @@
/* tasn_enc.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 2000.
*/
/* ====================================================================
* Copyright (c) 2000-2004 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 <stddef.h>
#include <string.h>
#include <limits.h>
#include "cryptlib.h"
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/objects.h>
static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
const ASN1_ITEM *it, int tag, int aclass);
static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
int skcontlen, const ASN1_ITEM *item,
int do_sort, int iclass);
static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
const ASN1_TEMPLATE *tt, int tag, int aclass);
static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
const ASN1_ITEM *it, int flags);
/*
* Top level i2d equivalents: the 'ndef' variant instructs the encoder to use
* indefinite length constructed encoding, where appropriate
*/
int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out,
const ASN1_ITEM *it)
{
return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF);
}
int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
{
return asn1_item_flags_i2d(val, out, it, 0);
}
/*
* Encode an ASN1 item, this is use by the standard 'i2d' function. 'out'
* points to a buffer to output the data to. The new i2d has one additional
* feature. If the output buffer is NULL (i.e. *out == NULL) then a buffer is
* allocated and populated with the encoding.
*/
static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
const ASN1_ITEM *it, int flags)
{
if (out && !*out) {
unsigned char *p, *buf;
int len;
len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags);
if (len <= 0)
return len;
buf = OPENSSL_malloc(len);
if (!buf)
return -1;
p = buf;
ASN1_item_ex_i2d(&val, &p, it, -1, flags);
*out = buf;
return len;
}
return ASN1_item_ex_i2d(&val, out, it, -1, flags);
}
/*
* Encode an item, taking care of IMPLICIT tagging (if any). This function
* performs the normal item handling: it can be used in external types.
*/
int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
const ASN1_ITEM *it, int tag, int aclass)
{
const ASN1_TEMPLATE *tt = NULL;
unsigned char *p = NULL;
int i, seqcontlen, seqlen, ndef = 1;
const ASN1_COMPAT_FUNCS *cf;
const ASN1_EXTERN_FUNCS *ef;
const ASN1_AUX *aux = it->funcs;
ASN1_aux_cb *asn1_cb = 0;
if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
return 0;
if (aux && aux->asn1_cb)
asn1_cb = aux->asn1_cb;
switch (it->itype) {
case ASN1_ITYPE_PRIMITIVE:
if (it->templates)
return asn1_template_ex_i2d(pval, out, it->templates,
tag, aclass);
return asn1_i2d_ex_primitive(pval, out, it, tag, aclass);
break;
case ASN1_ITYPE_MSTRING:
return asn1_i2d_ex_primitive(pval, out, it, -1, aclass);
case ASN1_ITYPE_CHOICE:
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
return 0;
i = asn1_get_choice_selector(pval, it);
if ((i >= 0) && (i < it->tcount)) {
ASN1_VALUE **pchval;
const ASN1_TEMPLATE *chtt;
chtt = it->templates + i;
pchval = asn1_get_field_ptr(pval, chtt);
return asn1_template_ex_i2d(pchval, out, chtt, -1, aclass);
}
/* Fixme: error condition if selector out of range */
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
return 0;
break;
case ASN1_ITYPE_EXTERN:
/* If new style i2d it does all the work */
ef = it->funcs;
return ef->asn1_ex_i2d(pval, out, it, tag, aclass);
case ASN1_ITYPE_COMPAT:
/* old style hackery... */
cf = it->funcs;
if (out)
p = *out;
i = cf->asn1_i2d(*pval, out);
/*
* Fixup for IMPLICIT tag: note this messes up for tags > 30, but so
* did the old code. Tags > 30 are very rare anyway.
*/
if (out && (tag != -1))
*p = aclass | tag | (*p & V_ASN1_CONSTRUCTED);
return i;
case ASN1_ITYPE_NDEF_SEQUENCE:
/* Use indefinite length constructed if requested */
if (aclass & ASN1_TFLG_NDEF)
ndef = 2;
/* fall through */
case ASN1_ITYPE_SEQUENCE:
i = asn1_enc_restore(&seqcontlen, out, pval, it);
/* An error occurred */
if (i < 0)
return 0;
/* We have a valid cached encoding... */
if (i > 0)
return seqcontlen;
/* Otherwise carry on */
seqcontlen = 0;
/* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
if (tag == -1) {
tag = V_ASN1_SEQUENCE;
/* Retain any other flags in aclass */
aclass = (aclass & ~ASN1_TFLG_TAG_CLASS)
| V_ASN1_UNIVERSAL;
}
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
return 0;
/* First work out sequence content length */
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
const ASN1_TEMPLATE *seqtt;
ASN1_VALUE **pseqval;
int tmplen;
seqtt = asn1_do_adb(pval, tt, 1);
if (!seqtt)
return 0;
pseqval = asn1_get_field_ptr(pval, seqtt);
tmplen = asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, aclass);
if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen))
return -1;
seqcontlen += tmplen;
}
seqlen = ASN1_object_size(ndef, seqcontlen, tag);
if (!out || seqlen == -1)
return seqlen;
/* Output SEQUENCE header */
ASN1_put_object(out, ndef, seqcontlen, tag, aclass);
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
const ASN1_TEMPLATE *seqtt;
ASN1_VALUE **pseqval;
seqtt = asn1_do_adb(pval, tt, 1);
if (!seqtt)
return 0;
pseqval = asn1_get_field_ptr(pval, seqtt);
/* FIXME: check for errors in enhanced version */
asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass);
}
if (ndef == 2)
ASN1_put_eoc(out);
if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
return 0;
return seqlen;
default:
return 0;
}
return 0;
}
int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out,
const ASN1_TEMPLATE *tt)
{
return asn1_template_ex_i2d(pval, out, tt, -1, 0);
}
static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
const ASN1_TEMPLATE *tt, int tag, int iclass)
{
int i, ret, flags, ttag, tclass, ndef;
flags = tt->flags;
/*
* Work out tag and class to use: tagging may come either from the
* template or the arguments, not both because this would create
* ambiguity. Additionally the iclass argument may contain some
* additional flags which should be noted and passed down to other
* levels.
*/
if (flags & ASN1_TFLG_TAG_MASK) {
/* Error if argument and template tagging */
if (tag != -1)
/* FIXME: error code here */
return -1;
/* Get tagging from template */
ttag = tt->tag;
tclass = flags & ASN1_TFLG_TAG_CLASS;
} else if (tag != -1) {
/* No template tagging, get from arguments */
ttag = tag;
tclass = iclass & ASN1_TFLG_TAG_CLASS;
} else {
ttag = -1;
tclass = 0;
}
/*
* Remove any class mask from iflag.
*/
iclass &= ~ASN1_TFLG_TAG_CLASS;
/*
* At this point 'ttag' contains the outer tag to use, 'tclass' is the
* class and iclass is any flags passed to this function.
*/
/* if template and arguments require ndef, use it */
if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF))
ndef = 2;
else
ndef = 1;
if (flags & ASN1_TFLG_SK_MASK) {
/* SET OF, SEQUENCE OF */
STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
int isset, sktag, skaclass;
int skcontlen, sklen;
ASN1_VALUE *skitem;
if (!*pval)
return 0;
if (flags & ASN1_TFLG_SET_OF) {
isset = 1;
/* 2 means we reorder */
if (flags & ASN1_TFLG_SEQUENCE_OF)
isset = 2;
} else
isset = 0;
/*
* Work out inner tag value: if EXPLICIT or no tagging use underlying
* type.
*/
if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) {
sktag = ttag;
skaclass = tclass;
} else {
skaclass = V_ASN1_UNIVERSAL;
if (isset)
sktag = V_ASN1_SET;
else
sktag = V_ASN1_SEQUENCE;
}
/* Determine total length of items */
skcontlen = 0;
for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
int tmplen;
skitem = sk_ASN1_VALUE_value(sk, i);
tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item),
-1, iclass);
if (tmplen == -1 || (skcontlen > INT_MAX - tmplen))
return -1;
skcontlen += tmplen;
}
sklen = ASN1_object_size(ndef, skcontlen, sktag);
if (sklen == -1)
return -1;
/* If EXPLICIT need length of surrounding tag */
if (flags & ASN1_TFLG_EXPTAG)
ret = ASN1_object_size(ndef, sklen, ttag);
else
ret = sklen;
if (!out || ret == -1)
return ret;
/* Now encode this lot... */
/* EXPLICIT tag */
if (flags & ASN1_TFLG_EXPTAG)
ASN1_put_object(out, ndef, sklen, ttag, tclass);
/* SET or SEQUENCE and IMPLICIT tag */
ASN1_put_object(out, ndef, skcontlen, sktag, skaclass);
/* And the stuff itself */
asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item),
isset, iclass);
if (ndef == 2) {
ASN1_put_eoc(out);
if (flags & ASN1_TFLG_EXPTAG)
ASN1_put_eoc(out);
}
return ret;
}
if (flags & ASN1_TFLG_EXPTAG) {
/* EXPLICIT tagging */
/* Find length of tagged item */
i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, iclass);
if (!i)
return 0;
/* Find length of EXPLICIT tag */
ret = ASN1_object_size(ndef, i, ttag);
if (out && ret != -1) {
/* Output tag and item */
ASN1_put_object(out, ndef, i, ttag, tclass);
ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, iclass);
if (ndef == 2)
ASN1_put_eoc(out);
}
return ret;
}
/* Either normal or IMPLICIT tagging: combine class and flags */
return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
ttag, tclass | iclass);
}
/* Temporary structure used to hold DER encoding of items for SET OF */
typedef struct {
unsigned char *data;
int length;
ASN1_VALUE *field;
} DER_ENC;
static int der_cmp(const void *a, const void *b)
{
const DER_ENC *d1 = a, *d2 = b;
int cmplen, i;
cmplen = (d1->length < d2->length) ? d1->length : d2->length;
i = memcmp(d1->data, d2->data, cmplen);
if (i)
return i;
return d1->length - d2->length;
}
/* Output the content octets of SET OF or SEQUENCE OF */
static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
int skcontlen, const ASN1_ITEM *item,
int do_sort, int iclass)
{
int i;
ASN1_VALUE *skitem;
unsigned char *tmpdat = NULL, *p = NULL;
DER_ENC *derlst = NULL, *tder;
if (do_sort) {
/* Don't need to sort less than 2 items */
if (sk_ASN1_VALUE_num(sk) < 2)
do_sort = 0;
else {
derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk)
* sizeof(*derlst));
if (!derlst)
return 0;
tmpdat = OPENSSL_malloc(skcontlen);
if (!tmpdat) {
OPENSSL_free(derlst);
return 0;
}
}
}
/* If not sorting just output each item */
if (!do_sort) {
for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
skitem = sk_ASN1_VALUE_value(sk, i);
ASN1_item_ex_i2d(&skitem, out, item, -1, iclass);
}
return 1;
}
p = tmpdat;
/* Doing sort: build up a list of each member's DER encoding */
for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
skitem = sk_ASN1_VALUE_value(sk, i);
tder->data = p;
tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass);
tder->field = skitem;
}
/* Now sort them */
qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
/* Output sorted DER encoding */
p = *out;
for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
memcpy(p, tder->data, tder->length);
p += tder->length;
}
*out = p;
/* If do_sort is 2 then reorder the STACK */
if (do_sort == 2) {
for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
(void)sk_ASN1_VALUE_set(sk, i, tder->field);
}
OPENSSL_free(derlst);
OPENSSL_free(tmpdat);
return 1;
}
static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
const ASN1_ITEM *it, int tag, int aclass)
{
int len;
int utype;
int usetag;
int ndef = 0;
utype = it->utype;
/*
* Get length of content octets and maybe find out the underlying type.
*/
len = asn1_ex_i2c(pval, NULL, &utype, it);
/*
* If SEQUENCE, SET or OTHER then header is included in pseudo content
* octets so don't include tag+length. We need to check here because the
* call to asn1_ex_i2c() could change utype.
*/
if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) ||
(utype == V_ASN1_OTHER))
usetag = 0;
else
usetag = 1;
/* -1 means omit type */
if (len == -1)
return 0;
/* -2 return is special meaning use ndef */
if (len == -2) {
ndef = 2;
len = 0;
}
/* If not implicitly tagged get tag from underlying type */
if (tag == -1)
tag = utype;
/* Output tag+length followed by content octets */
if (out) {
if (usetag)
ASN1_put_object(out, ndef, len, tag, aclass);
asn1_ex_i2c(pval, *out, &utype, it);
if (ndef)
ASN1_put_eoc(out);
else
*out += len;
}
if (usetag)
return ASN1_object_size(ndef, len, tag);
return len;
}
/* Produce content octets from a structure */
int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
const ASN1_ITEM *it)
{
ASN1_BOOLEAN *tbool = NULL;
ASN1_STRING *strtmp;
ASN1_OBJECT *otmp;
int utype;
const unsigned char *cont;
unsigned char c;
int len;
const ASN1_PRIMITIVE_FUNCS *pf;
pf = it->funcs;
if (pf && pf->prim_i2c)
return pf->prim_i2c(pval, cout, putype, it);
/* Should type be omitted? */
if ((it->itype != ASN1_ITYPE_PRIMITIVE)
|| (it->utype != V_ASN1_BOOLEAN)) {
if (!*pval)
return -1;
}
if (it->itype == ASN1_ITYPE_MSTRING) {
/* If MSTRING type set the underlying type */
strtmp = (ASN1_STRING *)*pval;
utype = strtmp->type;
*putype = utype;
} else if (it->utype == V_ASN1_ANY) {
/* If ANY set type and pointer to value */
ASN1_TYPE *typ;
typ = (ASN1_TYPE *)*pval;
utype = typ->type;
*putype = utype;
pval = &typ->value.asn1_value;
} else
utype = *putype;
switch (utype) {
case V_ASN1_OBJECT:
otmp = (ASN1_OBJECT *)*pval;
cont = otmp->data;
len = otmp->length;
break;
case V_ASN1_NULL:
cont = NULL;
len = 0;
break;
case V_ASN1_BOOLEAN:
tbool = (ASN1_BOOLEAN *)pval;
if (*tbool == -1)
return -1;
if (it->utype != V_ASN1_ANY) {
/*
* Default handling if value == size field then omit
*/
if (*tbool && (it->size > 0))
return -1;
if (!*tbool && !it->size)
return -1;
}
c = (unsigned char)*tbool;
cont = &c;
len = 1;
break;
case V_ASN1_BIT_STRING:
return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval,
cout ? &cout : NULL);
break;
case V_ASN1_INTEGER:
case V_ASN1_ENUMERATED:
/*
* These are all have the same content format as ASN1_INTEGER
*/
return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL);
break;
case V_ASN1_OCTET_STRING:
case V_ASN1_NUMERICSTRING:
case V_ASN1_PRINTABLESTRING:
case V_ASN1_T61STRING:
case V_ASN1_VIDEOTEXSTRING:
case V_ASN1_IA5STRING:
case V_ASN1_UTCTIME:
case V_ASN1_GENERALIZEDTIME:
case V_ASN1_GRAPHICSTRING:
case V_ASN1_VISIBLESTRING:
case V_ASN1_GENERALSTRING:
case V_ASN1_UNIVERSALSTRING:
case V_ASN1_BMPSTRING:
case V_ASN1_UTF8STRING:
case V_ASN1_SEQUENCE:
case V_ASN1_SET:
default:
/* All based on ASN1_STRING and handled the same */
strtmp = (ASN1_STRING *)*pval;
/* Special handling for NDEF */
if ((it->size == ASN1_TFLG_NDEF)
&& (strtmp->flags & ASN1_STRING_FLAG_NDEF)) {
if (cout) {
strtmp->data = cout;
strtmp->length = 0;
}
/* Special return code */
return -2;
}
cont = strtmp->data;
len = strtmp->length;
break;
}
if (cout && len)
memcpy(cout, cont, len);
return len;
}
@@ -0,0 +1,250 @@
/* tasn_fre.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 2000.
*/
/* ====================================================================
* Copyright (c) 2000 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 <stddef.h>
#include "openssl/bio.h"
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/objects.h>
static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it,
int combine);
/* Free up an ASN1 structure */
void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it)
{
asn1_item_combine_free(&val, it, 0);
}
void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
asn1_item_combine_free(pval, it, 0);
}
static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it,
int combine)
{
const ASN1_TEMPLATE *tt = NULL, *seqtt;
const ASN1_EXTERN_FUNCS *ef;
const ASN1_COMPAT_FUNCS *cf;
const ASN1_AUX *aux = it->funcs;
ASN1_aux_cb *asn1_cb;
int i;
if (!pval)
return;
if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
return;
if (aux && aux->asn1_cb)
asn1_cb = aux->asn1_cb;
else
asn1_cb = 0;
switch (it->itype) {
case ASN1_ITYPE_PRIMITIVE:
if (it->templates)
ASN1_template_free(pval, it->templates);
else
ASN1_primitive_free(pval, it);
break;
case ASN1_ITYPE_MSTRING:
ASN1_primitive_free(pval, it);
break;
case ASN1_ITYPE_CHOICE:
if (asn1_cb) {
i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
if (i == 2)
return;
}
i = asn1_get_choice_selector(pval, it);
if ((i >= 0) && (i < it->tcount)) {
ASN1_VALUE **pchval;
tt = it->templates + i;
pchval = asn1_get_field_ptr(pval, tt);
ASN1_template_free(pchval, tt);
}
if (asn1_cb)
asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
if (!combine) {
OPENSSL_free(*pval);
*pval = NULL;
}
break;
case ASN1_ITYPE_COMPAT:
cf = it->funcs;
if (cf && cf->asn1_free)
cf->asn1_free(*pval);
break;
case ASN1_ITYPE_EXTERN:
ef = it->funcs;
if (ef && ef->asn1_ex_free)
ef->asn1_ex_free(pval, it);
break;
case ASN1_ITYPE_NDEF_SEQUENCE:
case ASN1_ITYPE_SEQUENCE:
if (asn1_do_lock(pval, -1, it) > 0)
return;
if (asn1_cb) {
i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
if (i == 2)
return;
}
asn1_enc_free(pval, it);
/*
* If we free up as normal we will invalidate any ANY DEFINED BY
* field and we wont be able to determine the type of the field it
* defines. So free up in reverse order.
*/
tt = it->templates + it->tcount - 1;
for (i = 0; i < it->tcount; tt--, i++) {
ASN1_VALUE **pseqval;
seqtt = asn1_do_adb(pval, tt, 0);
if (!seqtt)
continue;
pseqval = asn1_get_field_ptr(pval, seqtt);
ASN1_template_free(pseqval, seqtt);
}
if (asn1_cb)
asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
if (!combine) {
OPENSSL_free(*pval);
*pval = NULL;
}
break;
}
}
void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
{
int i;
if (tt->flags & ASN1_TFLG_SK_MASK) {
STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
ASN1_VALUE *vtmp;
vtmp = sk_ASN1_VALUE_value(sk, i);
asn1_item_combine_free(&vtmp, ASN1_ITEM_ptr(tt->item), 0);
}
sk_ASN1_VALUE_free(sk);
*pval = NULL;
} else
asn1_item_combine_free(pval, ASN1_ITEM_ptr(tt->item),
tt->flags & ASN1_TFLG_COMBINE);
}
void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
int utype;
if (it) {
const ASN1_PRIMITIVE_FUNCS *pf;
pf = it->funcs;
if (pf && pf->prim_free) {
pf->prim_free(pval, it);
return;
}
}
/* Special case: if 'it' is NULL free contents of ASN1_TYPE */
if (!it) {
ASN1_TYPE *typ = (ASN1_TYPE *)*pval;
utype = typ->type;
pval = &typ->value.asn1_value;
if (!*pval)
return;
} else if (it->itype == ASN1_ITYPE_MSTRING) {
utype = -1;
if (!*pval)
return;
} else {
utype = it->utype;
if ((utype != V_ASN1_BOOLEAN) && !*pval)
return;
}
switch (utype) {
case V_ASN1_OBJECT:
ASN1_OBJECT_free((ASN1_OBJECT *)*pval);
break;
case V_ASN1_BOOLEAN:
if (it)
*(ASN1_BOOLEAN *)pval = it->size;
else
*(ASN1_BOOLEAN *)pval = -1;
return;
case V_ASN1_NULL:
break;
case V_ASN1_ANY:
ASN1_primitive_free(pval, NULL);
OPENSSL_free(*pval);
break;
default:
ASN1_STRING_free((ASN1_STRING *)*pval);
*pval = NULL;
break;
}
*pval = NULL;
}
@@ -0,0 +1,385 @@
/* tasn_new.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 2000.
*/
/* ====================================================================
* Copyright (c) 2000-2004 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 <stddef.h>
#include "openssl/bio.h"
#include <openssl/asn1.h>
#include <openssl/objects.h>
#include <openssl/err.h>
#include <openssl/asn1t.h>
#include <string.h>
static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
int combine);
static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it)
{
ASN1_VALUE *ret = NULL;
if (ASN1_item_ex_new(&ret, it) > 0)
return ret;
return NULL;
}
/* Allocate an ASN1 structure */
int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
return asn1_item_ex_combine_new(pval, it, 0);
}
static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
int combine)
{
const ASN1_TEMPLATE *tt = NULL;
const ASN1_COMPAT_FUNCS *cf;
const ASN1_EXTERN_FUNCS *ef;
const ASN1_AUX *aux = it->funcs;
ASN1_aux_cb *asn1_cb;
ASN1_VALUE **pseqval;
int i;
if (aux && aux->asn1_cb)
asn1_cb = aux->asn1_cb;
else
asn1_cb = 0;
#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_COMPAT:
cf = it->funcs;
if (cf && cf->asn1_new) {
*pval = cf->asn1_new();
if (!*pval)
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 = OPENSSL_malloc(it->size);
if (!*pval)
goto memerr;
memset(*pval, 0, it->size);
}
asn1_set_choice_selector(pval, -1, it);
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
goto auxerr2;
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 = OPENSSL_malloc(it->size);
if (!*pval)
goto memerr;
memset(*pval, 0, it->size);
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 memerr2;
}
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
goto auxerr2;
break;
}
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_pop_info();
#endif
return 1;
memerr2:
ASN1_item_ex_free(pval, it);
memerr:
ASN1err(ASN1_F_ASN1_ITEM_EX_COMBINE_NEW, ERR_R_MALLOC_FAILURE);
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_pop_info();
#endif
return 0;
auxerr2:
ASN1_item_ex_free(pval, it);
auxerr:
ASN1err(ASN1_F_ASN1_ITEM_EX_COMBINE_NEW, ASN1_R_AUX_ERROR);
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_pop_info();
#endif
return 0;
}
static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
const ASN1_EXTERN_FUNCS *ef;
switch (it->itype) {
case ASN1_ITYPE_EXTERN:
ef = it->funcs;
if (ef && ef->asn1_ex_clear)
ef->asn1_ex_clear(pval, it);
else
*pval = NULL;
break;
case ASN1_ITYPE_PRIMITIVE:
if (it->templates)
asn1_template_clear(pval, it->templates);
else
asn1_primitive_clear(pval, it);
break;
case ASN1_ITYPE_MSTRING:
asn1_primitive_clear(pval, it);
break;
case ASN1_ITYPE_COMPAT:
case ASN1_ITYPE_CHOICE:
case ASN1_ITYPE_SEQUENCE:
case ASN1_ITYPE_NDEF_SEQUENCE:
*pval = NULL;
break;
}
}
int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
{
const ASN1_ITEM *it = ASN1_ITEM_ptr(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) {
ASN1err(ASN1_F_ASN1_TEMPLATE_NEW, 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;
}
static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
{
/* If ADB or STACK just NULL the field */
if (tt->flags & (ASN1_TFLG_ADB_MASK | ASN1_TFLG_SK_MASK))
*pval = NULL;
else
asn1_item_clear(pval, ASN1_ITEM_ptr(tt->item));
}
/*
* NB: could probably combine most of the real XXX_new() behaviour and junk
* all the old functions.
*/
int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
ASN1_TYPE *typ;
ASN1_STRING *str;
int utype;
if (!it)
return 0;
if (it->funcs) {
const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
if (pf->prim_new)
return pf->prim_new(pval, it);
}
if (it->itype == ASN1_ITYPE_MSTRING)
utype = -1;
else
utype = it->utype;
switch (utype) {
case V_ASN1_OBJECT:
*pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef);
return 1;
case V_ASN1_BOOLEAN:
*(ASN1_BOOLEAN *)pval = it->size;
return 1;
case V_ASN1_NULL:
*pval = (ASN1_VALUE *)1;
return 1;
case V_ASN1_ANY:
typ = OPENSSL_malloc(sizeof(ASN1_TYPE));
if (!typ)
return 0;
typ->value.ptr = NULL;
typ->type = -1;
*pval = (ASN1_VALUE *)typ;
break;
default:
str = ASN1_STRING_type_new(utype);
if (it->itype == ASN1_ITYPE_MSTRING && str)
str->flags |= ASN1_STRING_FLAG_MSTRING;
*pval = (ASN1_VALUE *)str;
break;
}
if (*pval)
return 1;
return 0;
}
static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
int utype;
if (it && it->funcs) {
const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
if (pf->prim_clear)
pf->prim_clear(pval, it);
else
*pval = NULL;
return;
}
if (!it || (it->itype == ASN1_ITYPE_MSTRING))
utype = -1;
else
utype = it->utype;
if (utype == V_ASN1_BOOLEAN)
*(ASN1_BOOLEAN *)pval = it->size;
else
*pval = NULL;
}
@@ -0,0 +1,150 @@
/* tasn_typ.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 2000.
*/
/* ====================================================================
* Copyright (c) 2000 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 "openssl/bio.h"
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
/* Declarations for string types */
IMPLEMENT_ASN1_TYPE(ASN1_INTEGER)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_INTEGER)
IMPLEMENT_ASN1_TYPE(ASN1_ENUMERATED)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_ENUMERATED)
IMPLEMENT_ASN1_TYPE(ASN1_BIT_STRING)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_BIT_STRING)
IMPLEMENT_ASN1_TYPE(ASN1_OCTET_STRING)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_OCTET_STRING)
IMPLEMENT_ASN1_TYPE(ASN1_NULL)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_NULL)
IMPLEMENT_ASN1_TYPE(ASN1_OBJECT)
IMPLEMENT_ASN1_TYPE(ASN1_UTF8STRING)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_UTF8STRING)
IMPLEMENT_ASN1_TYPE(ASN1_PRINTABLESTRING)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_PRINTABLESTRING)
IMPLEMENT_ASN1_TYPE(ASN1_T61STRING)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_T61STRING)
IMPLEMENT_ASN1_TYPE(ASN1_IA5STRING)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_IA5STRING)
IMPLEMENT_ASN1_TYPE(ASN1_GENERALSTRING)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_GENERALSTRING)
IMPLEMENT_ASN1_TYPE(ASN1_UTCTIME)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_UTCTIME)
IMPLEMENT_ASN1_TYPE(ASN1_GENERALIZEDTIME)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_GENERALIZEDTIME)
IMPLEMENT_ASN1_TYPE(ASN1_VISIBLESTRING)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_VISIBLESTRING)
IMPLEMENT_ASN1_TYPE(ASN1_UNIVERSALSTRING)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_UNIVERSALSTRING)
IMPLEMENT_ASN1_TYPE(ASN1_BMPSTRING)
IMPLEMENT_ASN1_FUNCTIONS(ASN1_BMPSTRING)
IMPLEMENT_ASN1_TYPE(ASN1_ANY)
/* Just swallow an ASN1_SEQUENCE in an ASN1_STRING */
IMPLEMENT_ASN1_TYPE(ASN1_SEQUENCE)
IMPLEMENT_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE)
/* Multistring types */
IMPLEMENT_ASN1_MSTRING(ASN1_PRINTABLE, B_ASN1_PRINTABLE)
IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE)
IMPLEMENT_ASN1_MSTRING(DISPLAYTEXT, B_ASN1_DISPLAYTEXT)
IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DISPLAYTEXT)
IMPLEMENT_ASN1_MSTRING(DIRECTORYSTRING, B_ASN1_DIRECTORYSTRING)
IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING)
/* Three separate BOOLEAN type: normal, DEFAULT TRUE and DEFAULT FALSE */
IMPLEMENT_ASN1_TYPE_ex(ASN1_BOOLEAN, ASN1_BOOLEAN, -1)
IMPLEMENT_ASN1_TYPE_ex(ASN1_TBOOLEAN, ASN1_BOOLEAN, 1)
IMPLEMENT_ASN1_TYPE_ex(ASN1_FBOOLEAN, ASN1_BOOLEAN, 0)
/* Special, OCTET STRING with indefinite length constructed support */
IMPLEMENT_ASN1_TYPE_ex(ASN1_OCTET_STRING_NDEF, ASN1_OCTET_STRING, ASN1_TFLG_NDEF)
ASN1_ITEM_TEMPLATE(ASN1_SEQUENCE_ANY) =
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, ASN1_SEQUENCE_ANY, ASN1_ANY)
ASN1_ITEM_TEMPLATE_END(ASN1_SEQUENCE_ANY)
ASN1_ITEM_TEMPLATE(ASN1_SET_ANY) =
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, ASN1_SET_ANY, ASN1_ANY)
ASN1_ITEM_TEMPLATE_END(ASN1_SET_ANY)
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY)
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SET_ANY, ASN1_SET_ANY)
@@ -0,0 +1,276 @@
/* tasn_utl.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 2000.
*/
/* ====================================================================
* Copyright (c) 2000-2004 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 <stddef.h>
#include <string.h>
#include "openssl/bio.h"
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/objects.h>
#include <openssl/err.h>
/* Utility functions for manipulating fields and offsets */
/* Add 'offset' to 'addr' */
#define offset2ptr(addr, offset) (void *)(((char *) addr) + offset)
/*
* Given an ASN1_ITEM CHOICE type return the selector value
*/
int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
int *sel = offset2ptr(*pval, it->utype);
return *sel;
}
/*
* Given an ASN1_ITEM CHOICE type set the selector value, return old value.
*/
int asn1_set_choice_selector(ASN1_VALUE **pval, int value,
const ASN1_ITEM *it)
{
int *sel, ret;
sel = offset2ptr(*pval, it->utype);
ret = *sel;
*sel = value;
return ret;
}
/*
* Do reference counting. The value 'op' decides what to do. if it is +1
* then the count is incremented. If op is 0 count is set to 1. If op is -1
* count is decremented and the return value is the current refrence count or
* 0 if no reference count exists.
*/
int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it)
{
const ASN1_AUX *aux;
int *lck, ret;
if ((it->itype != ASN1_ITYPE_SEQUENCE)
&& (it->itype != ASN1_ITYPE_NDEF_SEQUENCE))
return 0;
aux = it->funcs;
if (!aux || !(aux->flags & ASN1_AFLG_REFCOUNT))
return 0;
lck = offset2ptr(*pval, aux->ref_offset);
if (op == 0) {
*lck = 1;
return 1;
}
ret = CRYPTO_add(lck, op, aux->ref_lock);
#ifdef REF_PRINT
fprintf(stderr, "%s: Reference Count: %d\n", it->sname, *lck);
#endif
#ifdef REF_CHECK
if (ret < 0)
fprintf(stderr, "%s, bad reference count\n", it->sname);
#endif
return ret;
}
static ASN1_ENCODING *asn1_get_enc_ptr(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
const ASN1_AUX *aux;
if (!pval || !*pval)
return NULL;
aux = it->funcs;
if (!aux || !(aux->flags & ASN1_AFLG_ENCODING))
return NULL;
return offset2ptr(*pval, aux->enc_offset);
}
void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
ASN1_ENCODING *enc;
enc = asn1_get_enc_ptr(pval, it);
if (enc) {
enc->enc = NULL;
enc->len = 0;
enc->modified = 1;
}
}
void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
ASN1_ENCODING *enc;
enc = asn1_get_enc_ptr(pval, it);
if (enc) {
if (enc->enc)
OPENSSL_free(enc->enc);
enc->enc = NULL;
enc->len = 0;
enc->modified = 1;
}
}
int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen,
const ASN1_ITEM *it)
{
ASN1_ENCODING *enc;
enc = asn1_get_enc_ptr(pval, it);
if (!enc)
return 1;
if (enc->enc)
OPENSSL_free(enc->enc);
enc->enc = OPENSSL_malloc(inlen);
if (!enc->enc)
return 0;
memcpy(enc->enc, in, inlen);
enc->len = inlen;
enc->modified = 0;
return 1;
}
int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval,
const ASN1_ITEM *it)
{
ASN1_ENCODING *enc;
enc = asn1_get_enc_ptr(pval, it);
if (!enc || enc->modified)
return 0;
if (out) {
memcpy(*out, enc->enc, enc->len);
*out += enc->len;
}
if (len)
*len = enc->len;
return 1;
}
/* Given an ASN1_TEMPLATE get a pointer to a field */
ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
{
ASN1_VALUE **pvaltmp;
if (tt->flags & ASN1_TFLG_COMBINE)
return pval;
pvaltmp = offset2ptr(*pval, tt->offset);
/*
* NOTE for BOOLEAN types the field is just a plain int so we can't
* return int **, so settle for (int *).
*/
return pvaltmp;
}
/*
* Handle ANY DEFINED BY template, find the selector, look up the relevant
* ASN1_TEMPLATE in the table and return it.
*/
const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
int nullerr)
{
const ASN1_ADB *adb;
const ASN1_ADB_TABLE *atbl;
long selector;
ASN1_VALUE **sfld;
int i;
if (!(tt->flags & ASN1_TFLG_ADB_MASK))
return tt;
/* Else ANY DEFINED BY ... get the table */
adb = ASN1_ADB_ptr(tt->item);
/* Get the selector field */
sfld = offset2ptr(*pval, adb->offset);
/* Check if NULL */
if (*sfld == NULL) {
if (!adb->null_tt)
goto err;
return adb->null_tt;
}
/*
* Convert type to a long: NB: don't check for NID_undef here because it
* might be a legitimate value in the table
*/
if (tt->flags & ASN1_TFLG_ADB_OID)
selector = OBJ_obj2nid((ASN1_OBJECT *)*sfld);
else
selector = ASN1_INTEGER_get((ASN1_INTEGER *)*sfld);
/*
* Try to find matching entry in table Maybe should check application
* types first to allow application override? Might also be useful to
* have a flag which indicates table is sorted and we can do a binary
* search. For now stick to a linear search.
*/
for (atbl = adb->tbl, i = 0; i < adb->tblcount; i++, atbl++)
if (atbl->value == selector)
return &atbl->tt;
/* FIXME: need to search application table too */
/* No match, return default type */
if (!adb->default_tt)
goto err;
return adb->default_tt;
err:
/* FIXME: should log the value or OID of unsupported type */
if (nullerr)
ASN1err(ASN1_F_ASN1_DO_ADB, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE);
return NULL;
}
@@ -0,0 +1,148 @@
/* x_algor.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 2000.
*/
/* ====================================================================
* Copyright (c) 2000 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 <stddef.h>
#include <openssl/x509.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
ASN1_SEQUENCE(X509_ALGOR) = {
ASN1_SIMPLE(X509_ALGOR, algorithm, ASN1_OBJECT),
ASN1_OPT(X509_ALGOR, parameter, ASN1_ANY)
} ASN1_SEQUENCE_END(X509_ALGOR)
ASN1_ITEM_TEMPLATE(X509_ALGORS) =
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, algorithms, X509_ALGOR)
ASN1_ITEM_TEMPLATE_END(X509_ALGORS)
IMPLEMENT_ASN1_FUNCTIONS(X509_ALGOR)
IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(X509_ALGORS, X509_ALGORS, X509_ALGORS)
IMPLEMENT_ASN1_DUP_FUNCTION(X509_ALGOR)
IMPLEMENT_STACK_OF(X509_ALGOR)
IMPLEMENT_ASN1_SET_OF(X509_ALGOR)
int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype, void *pval)
{
if (!alg)
return 0;
if (ptype != V_ASN1_UNDEF) {
if (alg->parameter == NULL)
alg->parameter = ASN1_TYPE_new();
if (alg->parameter == NULL)
return 0;
}
if (alg) {
if (alg->algorithm)
ASN1_OBJECT_free(alg->algorithm);
alg->algorithm = aobj;
}
if (ptype == 0)
return 1;
if (ptype == V_ASN1_UNDEF) {
if (alg->parameter) {
ASN1_TYPE_free(alg->parameter);
alg->parameter = NULL;
}
} else
ASN1_TYPE_set(alg->parameter, ptype, pval);
return 1;
}
void X509_ALGOR_get0(ASN1_OBJECT **paobj, int *pptype, void **ppval,
X509_ALGOR *algor)
{
if (paobj)
*paobj = algor->algorithm;
if (pptype) {
if (algor->parameter == NULL) {
*pptype = V_ASN1_UNDEF;
return;
} else
*pptype = algor->parameter->type;
if (ppval)
*ppval = algor->parameter->value.ptr;
}
}
/* Set up an X509_ALGOR DigestAlgorithmIdentifier from an EVP_MD */
void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md)
{
int param_type;
if (md->flags & EVP_MD_FLAG_DIGALGID_ABSENT)
param_type = V_ASN1_UNDEF;
else
param_type = V_ASN1_NULL;
X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL);
}
int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b)
{
int rv;
rv = OBJ_cmp(a->algorithm, b->algorithm);
if (rv)
return rv;
if (!a->parameter && !b->parameter)
return 0;
return ASN1_TYPE_cmp(a->parameter, b->parameter);
}
@@ -0,0 +1,124 @@
/* crypto/asn1/x_attrib.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* 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 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 acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS 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 AUTHOR OR 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.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/objects.h>
#include <openssl/asn1t.h>
#include <openssl/x509.h>
/*-
* X509_ATTRIBUTE: this has the following form:
*
* typedef struct x509_attributes_st
* {
* ASN1_OBJECT *object;
* int single;
* union {
* char *ptr;
* STACK_OF(ASN1_TYPE) *set;
* ASN1_TYPE *single;
* } value;
* } X509_ATTRIBUTE;
*
* this needs some extra thought because the CHOICE type is
* merged with the main structure and because the value can
* be anything at all we *must* try the SET OF first because
* the ASN1_ANY type will swallow anything including the whole
* SET OF structure.
*/
ASN1_CHOICE(X509_ATTRIBUTE_SET) = {
ASN1_SET_OF(X509_ATTRIBUTE, value.set, ASN1_ANY),
ASN1_SIMPLE(X509_ATTRIBUTE, value.single, ASN1_ANY)
} ASN1_CHOICE_END_selector(X509_ATTRIBUTE, X509_ATTRIBUTE_SET, single)
ASN1_SEQUENCE(X509_ATTRIBUTE) = {
ASN1_SIMPLE(X509_ATTRIBUTE, object, ASN1_OBJECT),
/* CHOICE type merged with parent */
ASN1_EX_COMBINE(0, 0, X509_ATTRIBUTE_SET)
} ASN1_SEQUENCE_END(X509_ATTRIBUTE)
IMPLEMENT_ASN1_FUNCTIONS(X509_ATTRIBUTE)
IMPLEMENT_ASN1_DUP_FUNCTION(X509_ATTRIBUTE)
X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value)
{
X509_ATTRIBUTE *ret = NULL;
ASN1_TYPE *val = NULL;
if ((ret = X509_ATTRIBUTE_new()) == NULL)
return (NULL);
ret->object = OBJ_nid2obj(nid);
ret->single = 0;
if ((ret->value.set = sk_ASN1_TYPE_new_null()) == NULL)
goto err;
if ((val = ASN1_TYPE_new()) == NULL)
goto err;
if (!sk_ASN1_TYPE_push(ret->value.set, val))
goto err;
ASN1_TYPE_set(val, atrtype, value);
return (ret);
err:
if (ret != NULL)
X509_ATTRIBUTE_free(ret);
if (val != NULL)
ASN1_TYPE_free(val);
return (NULL);
}
@@ -0,0 +1,166 @@
/* x_bignum.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 2000.
*/
/* ====================================================================
* Copyright (c) 2000 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 "cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/bn.h>
/*
* Custom primitive type for BIGNUM handling. This reads in an ASN1_INTEGER
* as a BIGNUM directly. Currently it ignores the sign which isn't a problem
* since all BIGNUMs used are non negative and anything that looks negative
* is normally due to an encoding error.
*/
#define BN_SENSITIVE 1
static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
const ASN1_ITEM *it);
static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
int utype, char *free_cont, const ASN1_ITEM *it);
static int bn_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
int indent, const ASN1_PCTX *pctx);
static ASN1_PRIMITIVE_FUNCS bignum_pf = {
NULL, 0,
bn_new,
bn_free,
0,
bn_c2i,
bn_i2c,
//bn_print
};
ASN1_ITEM_start(BIGNUM)
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, 0, "BIGNUM"
ASN1_ITEM_end(BIGNUM)
ASN1_ITEM_start(CBIGNUM)
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, BN_SENSITIVE, "BIGNUM"
ASN1_ITEM_end(CBIGNUM)
static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
*pval = (ASN1_VALUE *)BN_new();
if (*pval)
return 1;
else
return 0;
}
static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
if (!*pval)
return;
if (it->size & BN_SENSITIVE)
BN_clear_free((BIGNUM *)*pval);
else
BN_free((BIGNUM *)*pval);
*pval = NULL;
}
static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
const ASN1_ITEM *it)
{
BIGNUM *bn;
int pad;
if (!*pval)
return -1;
bn = (BIGNUM *)*pval;
/* If MSB set in an octet we need a padding byte */
if (BN_num_bits(bn) & 0x7)
pad = 0;
else
pad = 1;
if (cont) {
if (pad)
*cont++ = 0;
BN_bn2bin(bn, cont);
}
return pad + BN_num_bytes(bn);
}
static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
int utype, char *free_cont, const ASN1_ITEM *it)
{
BIGNUM *bn;
if (*pval == NULL && !bn_new(pval, it))
return 0;
bn = (BIGNUM *)*pval;
if (!BN_bin2bn(cont, len, bn)) {
bn_free(pval, it);
return 0;
}
return 1;
}
static int bn_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
int indent, const ASN1_PCTX *pctx)
{
if (!BN_print(out, *(BIGNUM **)pval))
return 0;
if (BIO_puts(out, "\n") <= 0)
return 0;
return 1;
}
+218
View File
@@ -0,0 +1,218 @@
/* x_long.c */
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 2000.
*/
/* ====================================================================
* Copyright (c) 2000 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 "cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/bn.h>
/*
* Custom primitive type for long handling. This converts between an
* ASN1_INTEGER and a long directly.
*/
static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
const ASN1_ITEM *it);
static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
int utype, char *free_cont, const ASN1_ITEM *it);
static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
int indent, const ASN1_PCTX *pctx);
static ASN1_PRIMITIVE_FUNCS long_pf = {
NULL, 0,
long_new,
long_free,
long_free, /* Clear should set to initial value */
long_c2i,
long_i2c,
//long_print
};
ASN1_ITEM_start(LONG)
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, ASN1_LONG_UNDEF, "LONG"
ASN1_ITEM_end(LONG)
ASN1_ITEM_start(ZLONG)
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, 0, "ZLONG"
ASN1_ITEM_end(ZLONG)
static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
*(long *)pval = it->size;
return 1;
}
static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
*(long *)pval = it->size;
}
static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
const ASN1_ITEM *it)
{
long ltmp;
unsigned long utmp;
int clen, pad, i;
/* this exists to bypass broken gcc optimization */
char *cp = (char *)pval;
/* use memcpy, because we may not be long aligned */
memcpy(&ltmp, cp, sizeof(long));
if (ltmp == it->size)
return -1;
/*
* Convert the long to positive: we subtract one if negative so we can
* cleanly handle the padding if only the MSB of the leading octet is
* set.
*/
if (ltmp < 0)
utmp = 0 - (unsigned long)ltmp - 1;
else
utmp = ltmp;
clen = BN_num_bits_word(utmp);
/* If MSB of leading octet set we need to pad */
if (!(clen & 0x7))
pad = 1;
else
pad = 0;
/* Convert number of bits to number of octets */
clen = (clen + 7) >> 3;
if (cont) {
if (pad)
*cont++ = (ltmp < 0) ? 0xff : 0;
for (i = clen - 1; i >= 0; i--) {
cont[i] = (unsigned char)(utmp & 0xff);
if (ltmp < 0)
cont[i] ^= 0xff;
utmp >>= 8;
}
}
return clen + pad;
}
static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
int utype, char *free_cont, const ASN1_ITEM *it)
{
int neg = -1, i;
long ltmp;
unsigned long utmp = 0;
char *cp = (char *)pval;
if (len) {
/*
* Check possible pad byte. Worst case, we're skipping past actual
* content, but since that's only with 0x00 and 0xff and we set neg
* accordingly, the result will be correct in the end anyway.
*/
switch (cont[0]) {
case 0xff:
cont++;
len--;
neg = 1;
break;
case 0:
cont++;
len--;
neg = 0;
break;
}
}
if (len > (int)sizeof(long)) {
ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
return 0;
}
if (neg == -1) {
/* Is it negative? */
if (len && (cont[0] & 0x80))
neg = 1;
else
neg = 0;
}
utmp = 0;
for (i = 0; i < len; i++) {
utmp <<= 8;
if (neg)
utmp |= cont[i] ^ 0xff;
else
utmp |= cont[i];
}
ltmp = (long)utmp;
if (neg) {
ltmp = -ltmp;
ltmp--;
}
if (ltmp == it->size) {
ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
return 0;
}
memcpy(cp, &ltmp, sizeof(long));
return 1;
}
static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
int indent, const ASN1_PCTX *pctx)
{
return BIO_printf(out, "%ld\n", *(long *)pval);
}
@@ -0,0 +1,374 @@
/* crypto/asn1/x_pubkey.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* 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 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 acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS 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 AUTHOR OR 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.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include "asn1_locl.h"
#ifndef OPENSSL_NO_RSA
# include <openssl/rsa.h>
#endif
#ifndef OPENSSL_NO_DSA
# include <openssl/dsa.h>
#endif
/* Minor tweak to operation: free up EVP_PKEY */
static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg)
{
if (operation == ASN1_OP_FREE_POST) {
X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval;
EVP_PKEY_free(pubkey->pkey);
}
return 1;
}
ASN1_SEQUENCE_cb(X509_PUBKEY, pubkey_cb) = {
ASN1_SIMPLE(X509_PUBKEY, algor, X509_ALGOR),
ASN1_SIMPLE(X509_PUBKEY, public_key, ASN1_BIT_STRING)
} ASN1_SEQUENCE_END_cb(X509_PUBKEY, X509_PUBKEY)
IMPLEMENT_ASN1_FUNCTIONS(X509_PUBKEY)
int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey)
{
X509_PUBKEY *pk = NULL;
if (x == NULL)
return (0);
if ((pk = X509_PUBKEY_new()) == NULL)
goto error;
if (pkey->ameth) {
if (pkey->ameth->pub_encode) {
if (!pkey->ameth->pub_encode(pk, pkey)) {
X509err(X509_F_X509_PUBKEY_SET,
X509_R_PUBLIC_KEY_ENCODE_ERROR);
goto error;
}
} else {
X509err(X509_F_X509_PUBKEY_SET, X509_R_METHOD_NOT_SUPPORTED);
goto error;
}
} else {
X509err(X509_F_X509_PUBKEY_SET, X509_R_UNSUPPORTED_ALGORITHM);
goto error;
}
if (*x != NULL)
X509_PUBKEY_free(*x);
*x = pk;
return 1;
error:
if (pk != NULL)
X509_PUBKEY_free(pk);
return 0;
}
EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key)
{
EVP_PKEY *ret = NULL;
if (key == NULL)
goto error;
if (key->pkey != NULL) {
CRYPTO_add(&key->pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
return key->pkey;
}
if (key->public_key == NULL)
goto error;
if ((ret = EVP_PKEY_new()) == NULL) {
X509err(X509_F_X509_PUBKEY_GET, ERR_R_MALLOC_FAILURE);
goto error;
}
if (!EVP_PKEY_set_type(ret, OBJ_obj2nid(key->algor->algorithm))) {
X509err(X509_F_X509_PUBKEY_GET, X509_R_UNSUPPORTED_ALGORITHM);
goto error;
}
if (ret->ameth->pub_decode) {
if (!ret->ameth->pub_decode(ret, key)) {
X509err(X509_F_X509_PUBKEY_GET, X509_R_PUBLIC_KEY_DECODE_ERROR);
goto error;
}
} else {
X509err(X509_F_X509_PUBKEY_GET, X509_R_METHOD_NOT_SUPPORTED);
goto error;
}
/* Check to see if another thread set key->pkey first */
CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
if (key->pkey) {
CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
EVP_PKEY_free(ret);
ret = key->pkey;
} else {
key->pkey = ret;
CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
}
CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_EVP_PKEY);
return ret;
error:
if (ret != NULL)
EVP_PKEY_free(ret);
return (NULL);
}
/*
* Now two pseudo ASN1 routines that take an EVP_PKEY structure and encode or
* decode as X509_PUBKEY
*/
EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length)
{
X509_PUBKEY *xpk;
EVP_PKEY *pktmp;
const unsigned char *q;
q = *pp;
xpk = d2i_X509_PUBKEY(NULL, &q, length);
if (!xpk)
return NULL;
pktmp = X509_PUBKEY_get(xpk);
X509_PUBKEY_free(xpk);
if (!pktmp)
return NULL;
*pp = q;
if (a) {
EVP_PKEY_free(*a);
*a = pktmp;
}
return pktmp;
}
int i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp)
{
X509_PUBKEY *xpk = NULL;
int ret;
if (!a)
return 0;
if (!X509_PUBKEY_set(&xpk, a))
return 0;
ret = i2d_X509_PUBKEY(xpk, pp);
X509_PUBKEY_free(xpk);
return ret;
}
/*
* The following are equivalents but which return RSA and DSA keys
*/
#ifndef OPENSSL_NO_RSA
RSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp, long length)
{
EVP_PKEY *pkey;
RSA *key;
const unsigned char *q;
q = *pp;
pkey = d2i_PUBKEY(NULL, &q, length);
if (!pkey)
return NULL;
key = EVP_PKEY_get1_RSA(pkey);
EVP_PKEY_free(pkey);
if (!key)
return NULL;
*pp = q;
if (a) {
RSA_free(*a);
*a = key;
}
return key;
}
int i2d_RSA_PUBKEY(RSA *a, unsigned char **pp)
{
EVP_PKEY *pktmp;
int ret;
if (!a)
return 0;
pktmp = EVP_PKEY_new();
if (!pktmp) {
ASN1err(ASN1_F_I2D_RSA_PUBKEY, ERR_R_MALLOC_FAILURE);
return 0;
}
EVP_PKEY_set1_RSA(pktmp, a);
ret = i2d_PUBKEY(pktmp, pp);
EVP_PKEY_free(pktmp);
return ret;
}
#endif
#ifndef OPENSSL_NO_DSA
DSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, long length)
{
EVP_PKEY *pkey;
DSA *key;
const unsigned char *q;
q = *pp;
pkey = d2i_PUBKEY(NULL, &q, length);
if (!pkey)
return NULL;
key = EVP_PKEY_get1_DSA(pkey);
EVP_PKEY_free(pkey);
if (!key)
return NULL;
*pp = q;
if (a) {
DSA_free(*a);
*a = key;
}
return key;
}
int i2d_DSA_PUBKEY(DSA *a, unsigned char **pp)
{
EVP_PKEY *pktmp;
int ret;
if (!a)
return 0;
pktmp = EVP_PKEY_new();
if (!pktmp) {
ASN1err(ASN1_F_I2D_DSA_PUBKEY, ERR_R_MALLOC_FAILURE);
return 0;
}
EVP_PKEY_set1_DSA(pktmp, a);
ret = i2d_PUBKEY(pktmp, pp);
EVP_PKEY_free(pktmp);
return ret;
}
#endif
#ifndef OPENSSL_NO_EC
EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length)
{
EVP_PKEY *pkey;
EC_KEY *key;
const unsigned char *q;
q = *pp;
pkey = d2i_PUBKEY(NULL, &q, length);
if (!pkey)
return (NULL);
key = EVP_PKEY_get1_EC_KEY(pkey);
EVP_PKEY_free(pkey);
if (!key)
return (NULL);
*pp = q;
if (a) {
EC_KEY_free(*a);
*a = key;
}
return (key);
}
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) {
ASN1err(ASN1_F_I2D_EC_PUBKEY, ERR_R_MALLOC_FAILURE);
return (0);
}
EVP_PKEY_set1_EC_KEY(pktmp, a);
ret = i2d_PUBKEY(pktmp, pp);
EVP_PKEY_free(pktmp);
return (ret);
}
#endif
int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *aobj,
int ptype, void *pval,
unsigned char *penc, int penclen)
{
if (!X509_ALGOR_set0(pub->algor, aobj, ptype, pval))
return 0;
if (penc) {
if (pub->public_key->data)
OPENSSL_free(pub->public_key->data);
pub->public_key->data = penc;
pub->public_key->length = penclen;
/* Set number of unused bits to zero */
pub->public_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
pub->public_key->flags |= ASN1_STRING_FLAG_BITS_LEFT;
}
return 1;
}
int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg,
const unsigned char **pk, int *ppklen,
X509_ALGOR **pa, X509_PUBKEY *pub)
{
if (ppkalg)
*ppkalg = pub->algor->algorithm;
if (pk) {
*pk = pub->public_key->data;
*ppklen = pub->public_key->length;
}
if (pa)
*pa = pub->algor;
return 1;
}
@@ -0,0 +1,69 @@
/* crypto/asn1/x_sig.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* 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 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 acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS 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 AUTHOR OR 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.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/x509.h>
ASN1_SEQUENCE(X509_SIG) = {
ASN1_SIMPLE(X509_SIG, algor, X509_ALGOR),
ASN1_SIMPLE(X509_SIG, digest, ASN1_OCTET_STRING)
} ASN1_SEQUENCE_END(X509_SIG)
IMPLEMENT_ASN1_FUNCTIONS(X509_SIG)