check in v3.8.1 source

This commit is contained in:
2023-09-03 18:24:16 -07:00
parent fbb21ed921
commit b31c897352
1205 changed files with 561101 additions and 0 deletions

329
crypto/asn1/a_bitstr.c Normal file
View File

@@ -0,0 +1,329 @@
/* $OpenBSD: a_bitstr.c,v 1.41 2023/07/28 10:33:13 tb Exp $ */
/* 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 <limits.h>
#include <stdio.h>
#include <string.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/conf.h>
#include <openssl/err.h>
#include <openssl/x509v3.h>
#include "bytestring.h"
const ASN1_ITEM ASN1_BIT_STRING_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_BIT_STRING,
.sname = "ASN1_BIT_STRING",
};
ASN1_BIT_STRING *
ASN1_BIT_STRING_new(void)
{
return (ASN1_BIT_STRING *)ASN1_item_new(&ASN1_BIT_STRING_it);
}
LCRYPTO_ALIAS(ASN1_BIT_STRING_new);
void
ASN1_BIT_STRING_free(ASN1_BIT_STRING *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_BIT_STRING_it);
}
LCRYPTO_ALIAS(ASN1_BIT_STRING_free);
static void
asn1_abs_clear_unused_bits(ASN1_BIT_STRING *abs)
{
abs->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
}
int
asn1_abs_set_unused_bits(ASN1_BIT_STRING *abs, uint8_t unused_bits)
{
if (unused_bits > 7)
return 0;
asn1_abs_clear_unused_bits(abs);
abs->flags |= ASN1_STRING_FLAG_BITS_LEFT | unused_bits;
return 1;
}
int
ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len)
{
return ASN1_STRING_set(x, d, len);
}
LCRYPTO_ALIAS(ASN1_BIT_STRING_set);
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;
asn1_abs_clear_unused_bits(a);
if ((a->length < (w + 1)) || (a->data == NULL)) {
if (!value)
return(1); /* Don't need to set */
if ((c = recallocarray(a->data, a->length, w + 1, 1)) == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
return 0;
}
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);
}
LCRYPTO_ALIAS(ASN1_BIT_STRING_set_bit);
int
ASN1_BIT_STRING_get_bit(const 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);
}
LCRYPTO_ALIAS(ASN1_BIT_STRING_get_bit);
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);
if (a->length == INT_MAX)
return (0);
ret = a->length + 1;
if (pp == NULL)
return (ret);
len = a->length;
if (len > 0) {
if (a->flags & ASN1_STRING_FLAG_BITS_LEFT) {
bits = (int)a->flags & 0x07;
} else {
j = 0;
for (; len > 0; len--) {
if (a->data[len - 1])
break;
}
if (len > 0)
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;
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);
}
int
c2i_ASN1_BIT_STRING_cbs(ASN1_BIT_STRING **out_abs, CBS *cbs)
{
ASN1_BIT_STRING *abs = NULL;
uint8_t *data = NULL;
size_t data_len = 0;
uint8_t unused_bits;
int ret = 0;
if (out_abs == NULL)
goto err;
if (*out_abs != NULL) {
ASN1_BIT_STRING_free(*out_abs);
*out_abs = NULL;
}
if (!CBS_get_u8(cbs, &unused_bits)) {
ASN1error(ASN1_R_STRING_TOO_SHORT);
goto err;
}
if (!CBS_stow(cbs, &data, &data_len))
goto err;
if (data_len > INT_MAX)
goto err;
if ((abs = ASN1_BIT_STRING_new()) == NULL)
goto err;
abs->data = data;
abs->length = (int)data_len;
data = NULL;
/*
* We do this to preserve the settings. If we modify the settings,
* via the _set_bit function, we will recalculate on output.
*/
if (!asn1_abs_set_unused_bits(abs, unused_bits)) {
ASN1error(ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
goto err;
}
if (abs->length > 0)
abs->data[abs->length - 1] &= 0xff << unused_bits;
*out_abs = abs;
abs = NULL;
ret = 1;
err:
ASN1_BIT_STRING_free(abs);
freezero(data, data_len);
return ret;
}
ASN1_BIT_STRING *
c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **out_abs, const unsigned char **pp, long len)
{
ASN1_BIT_STRING *abs = NULL;
CBS content;
if (out_abs != NULL) {
ASN1_BIT_STRING_free(*out_abs);
*out_abs = NULL;
}
if (len < 0) {
ASN1error(ASN1_R_LENGTH_ERROR);
return NULL;
}
CBS_init(&content, *pp, len);
if (!c2i_ASN1_BIT_STRING_cbs(&abs, &content))
return NULL;
*pp = CBS_data(&content);
if (out_abs != NULL)
*out_abs = abs;
return abs;
}
int
i2d_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_BIT_STRING_it);
}
LCRYPTO_ALIAS(i2d_ASN1_BIT_STRING);
ASN1_BIT_STRING *
d2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, const unsigned char **in, long len)
{
return (ASN1_BIT_STRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&ASN1_BIT_STRING_it);
}
LCRYPTO_ALIAS(d2i_ASN1_BIT_STRING);

393
crypto/asn1/a_enum.c Normal file
View File

@@ -0,0 +1,393 @@
/* $OpenBSD: a_enum.c,v 1.29 2023/07/05 21:23:36 beck Exp $ */
/* 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 <limits.h>
#include <string.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/bn.h>
#include <openssl/buffer.h>
#include <openssl/err.h>
#include "asn1_local.h"
#include "bytestring.h"
/*
* Code for ENUMERATED type: identical to INTEGER apart from a different tag.
* for comments on encoding see a_int.c
*/
const ASN1_ITEM ASN1_ENUMERATED_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_ENUMERATED,
.sname = "ASN1_ENUMERATED",
};
ASN1_ENUMERATED *
ASN1_ENUMERATED_new(void)
{
return (ASN1_ENUMERATED *)ASN1_item_new(&ASN1_ENUMERATED_it);
}
LCRYPTO_ALIAS(ASN1_ENUMERATED_new);
static void
asn1_aenum_clear(ASN1_ENUMERATED *aenum)
{
freezero(aenum->data, aenum->length);
memset(aenum, 0, sizeof(*aenum));
aenum->type = V_ASN1_ENUMERATED;
}
void
ASN1_ENUMERATED_free(ASN1_ENUMERATED *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_ENUMERATED_it);
}
LCRYPTO_ALIAS(ASN1_ENUMERATED_free);
int
ASN1_ENUMERATED_get_int64(int64_t *out_val, const ASN1_ENUMERATED *aenum)
{
CBS cbs;
*out_val = 0;
if (aenum == NULL || aenum->length < 0)
return 0;
if (aenum->type != V_ASN1_ENUMERATED &&
aenum->type != V_ASN1_NEG_ENUMERATED) {
ASN1error(ASN1_R_WRONG_INTEGER_TYPE);
return 0;
}
CBS_init(&cbs, aenum->data, aenum->length);
return asn1_aint_get_int64(&cbs, (aenum->type == V_ASN1_NEG_ENUMERATED),
out_val);
}
LCRYPTO_ALIAS(ASN1_ENUMERATED_get_int64);
int
ASN1_ENUMERATED_set_int64(ASN1_ENUMERATED *aenum, int64_t val)
{
uint64_t uval;
asn1_aenum_clear(aenum);
uval = (uint64_t)val;
if (val < 0) {
aenum->type = V_ASN1_NEG_ENUMERATED;
uval = -uval;
}
return asn1_aint_set_uint64(uval, &aenum->data, &aenum->length);
}
LCRYPTO_ALIAS(ASN1_ENUMERATED_set_int64);
long
ASN1_ENUMERATED_get(const ASN1_ENUMERATED *aenum)
{
int64_t val;
if (aenum == NULL)
return 0;
if (!ASN1_ENUMERATED_get_int64(&val, aenum))
return -1;
if (val < LONG_MIN || val > LONG_MAX) {
/* hmm... a bit ugly, return all ones */
return -1;
}
return (long)val;
}
LCRYPTO_ALIAS(ASN1_ENUMERATED_get);
int
ASN1_ENUMERATED_set(ASN1_ENUMERATED *aenum, long val)
{
return ASN1_ENUMERATED_set_int64(aenum, val);
}
LCRYPTO_ALIAS(ASN1_ENUMERATED_set);
ASN1_ENUMERATED *
BN_to_ASN1_ENUMERATED(const BIGNUM *bn, ASN1_ENUMERATED *ai)
{
ASN1_ENUMERATED *ret;
int len, j;
if (ai == NULL)
ret = ASN1_ENUMERATED_new();
else
ret = ai;
if (ret == NULL) {
ASN1error(ERR_R_NESTED_ASN1_ERROR);
goto err;
}
if (BN_is_negative(bn))
ret->type = V_ASN1_NEG_ENUMERATED;
else
ret->type = V_ASN1_ENUMERATED;
j = BN_num_bits(bn);
len = ((j == 0) ? 0 : ((j / 8) + 1));
if (ret->length < len + 4) {
unsigned char *new_data = realloc(ret->data, len + 4);
if (!new_data) {
ASN1error(ERR_R_MALLOC_FAILURE);
goto err;
}
ret->data = new_data;
}
ret->length = BN_bn2bin(bn, ret->data);
/* Correct zero case */
if (!ret->length) {
ret->data[0] = 0;
ret->length = 1;
}
return (ret);
err:
if (ret != ai)
ASN1_ENUMERATED_free(ret);
return (NULL);
}
LCRYPTO_ALIAS(BN_to_ASN1_ENUMERATED);
BIGNUM *
ASN1_ENUMERATED_to_BN(const ASN1_ENUMERATED *ai, BIGNUM *bn)
{
BIGNUM *ret;
if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL)
ASN1error(ASN1_R_BN_LIB);
else if (ai->type == V_ASN1_NEG_ENUMERATED)
BN_set_negative(ret, 1);
return (ret);
}
LCRYPTO_ALIAS(ASN1_ENUMERATED_to_BN);
/* Based on a_int.c: equivalent ENUMERATED functions */
int
i2a_ASN1_ENUMERATED(BIO *bp, const ASN1_ENUMERATED *a)
{
int i, n = 0;
static const char h[] = "0123456789ABCDEF";
char buf[2];
if (a == NULL)
return (0);
if (a->length == 0) {
if (BIO_write(bp, "00", 2) != 2)
goto err;
n = 2;
} else {
for (i = 0; i < a->length; i++) {
if ((i != 0) && (i % 35 == 0)) {
if (BIO_write(bp, "\\\n", 2) != 2)
goto err;
n += 2;
}
buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
if (BIO_write(bp, buf, 2) != 2)
goto err;
n += 2;
}
}
return (n);
err:
return (-1);
}
LCRYPTO_ALIAS(i2a_ASN1_ENUMERATED);
int
a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size)
{
int ret = 0;
int i, j,k, m,n, again, bufsize;
unsigned char *s = NULL, *sp;
unsigned char *bufp;
int first = 1;
size_t num = 0, slen = 0;
bs->type = V_ASN1_ENUMERATED;
bufsize = BIO_gets(bp, buf, size);
for (;;) {
if (bufsize < 1)
goto err_sl;
i = bufsize;
if (buf[i-1] == '\n')
buf[--i] = '\0';
if (i == 0)
goto err_sl;
if (buf[i-1] == '\r')
buf[--i] = '\0';
if (i == 0)
goto err_sl;
if (buf[i - 1] == '\\') {
i--;
again = 1;
} else
again = 0;
buf[i] = '\0';
if (i < 2)
goto err_sl;
bufp = (unsigned char *)buf;
if (first) {
first = 0;
if ((bufp[0] == '0') && (buf[1] == '0')) {
bufp += 2;
i -= 2;
}
}
k = 0;
if (i % 2 != 0) {
ASN1error(ASN1_R_ODD_NUMBER_OF_CHARS);
goto err;
}
i /= 2;
if (num + i > slen) {
sp = realloc(s, num + i);
if (sp == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
goto err;
}
s = sp;
slen = num + i;
}
for (j = 0; j < i; j++, k += 2) {
for (n = 0; n < 2; n++) {
m = bufp[k + n];
if ((m >= '0') && (m <= '9'))
m -= '0';
else if ((m >= 'a') && (m <= 'f'))
m = m - 'a' + 10;
else if ((m >= 'A') && (m <= 'F'))
m = m - 'A' + 10;
else {
ASN1error(ASN1_R_NON_HEX_CHARACTERS);
goto err;
}
s[num + j] <<= 4;
s[num + j] |= m;
}
}
num += i;
if (again)
bufsize = BIO_gets(bp, buf, size);
else
break;
}
bs->length = num;
bs->data = s;
return (1);
err_sl:
ASN1error(ASN1_R_SHORT_LINE);
err:
free(s);
return (ret);
}
LCRYPTO_ALIAS(a2i_ASN1_ENUMERATED);
int
c2i_ASN1_ENUMERATED_cbs(ASN1_ENUMERATED **out_aenum, CBS *cbs)
{
ASN1_ENUMERATED *aenum = NULL;
if (out_aenum == NULL)
return 0;
if (*out_aenum != NULL) {
ASN1_INTEGER_free(*out_aenum);
*out_aenum = NULL;
}
if (!c2i_ASN1_INTEGER_cbs((ASN1_INTEGER **)&aenum, cbs))
return 0;
aenum->type = V_ASN1_ENUMERATED | (aenum->type & V_ASN1_NEG);
*out_aenum = aenum;
return 1;
}
int
i2d_ASN1_ENUMERATED(ASN1_ENUMERATED *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_ENUMERATED_it);
}
LCRYPTO_ALIAS(i2d_ASN1_ENUMERATED);
ASN1_ENUMERATED *
d2i_ASN1_ENUMERATED(ASN1_ENUMERATED **a, const unsigned char **in, long len)
{
return (ASN1_ENUMERATED *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&ASN1_ENUMERATED_it);
}
LCRYPTO_ALIAS(d2i_ASN1_ENUMERATED);

857
crypto/asn1/a_int.c Normal file
View File

@@ -0,0 +1,857 @@
/* $OpenBSD: a_int.c,v 1.47 2023/07/05 21:23:36 beck Exp $ */
/* 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 <limits.h>
#include <stdio.h>
#include <string.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/bn.h>
#include <openssl/buffer.h>
#include <openssl/err.h>
#include "bytestring.h"
const ASN1_ITEM ASN1_INTEGER_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_INTEGER,
.sname = "ASN1_INTEGER",
};
ASN1_INTEGER *
ASN1_INTEGER_new(void)
{
return (ASN1_INTEGER *)ASN1_item_new(&ASN1_INTEGER_it);
}
LCRYPTO_ALIAS(ASN1_INTEGER_new);
static void
asn1_aint_clear(ASN1_INTEGER *aint)
{
freezero(aint->data, aint->length);
memset(aint, 0, sizeof(*aint));
aint->type = V_ASN1_INTEGER;
}
void
ASN1_INTEGER_free(ASN1_INTEGER *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_INTEGER_it);
}
LCRYPTO_ALIAS(ASN1_INTEGER_free);
static int
ASN1_INTEGER_valid(const ASN1_INTEGER *a)
{
return (a != NULL && a->length >= 0);
}
ASN1_INTEGER *
ASN1_INTEGER_dup(const ASN1_INTEGER *x)
{
if (!ASN1_INTEGER_valid(x))
return NULL;
return ASN1_STRING_dup(x);
}
LCRYPTO_ALIAS(ASN1_INTEGER_dup);
int
ASN1_INTEGER_cmp(const ASN1_INTEGER *a, const ASN1_INTEGER *b)
{
int ret = 1;
/* Compare sign, then content. */
if ((a->type & V_ASN1_NEG) == (b->type & V_ASN1_NEG))
ret = ASN1_STRING_cmp(a, b);
if ((a->type & V_ASN1_NEG) != 0)
return -ret;
return ret;
}
LCRYPTO_ALIAS(ASN1_INTEGER_cmp);
int
asn1_aint_get_uint64(CBS *cbs, uint64_t *out_val)
{
uint64_t val = 0;
uint8_t u8;
*out_val = 0;
while (CBS_len(cbs) > 0) {
if (!CBS_get_u8(cbs, &u8))
return 0;
if (val > (UINT64_MAX >> 8)) {
ASN1error(ASN1_R_TOO_LARGE);
return 0;
}
val = val << 8 | u8;
}
*out_val = val;
return 1;
}
int
asn1_aint_set_uint64(uint64_t val, uint8_t **out_data, int *out_len)
{
uint8_t *data = NULL;
size_t data_len = 0;
int started = 0;
uint8_t u8;
CBB cbb;
int i;
int ret = 0;
if (!CBB_init(&cbb, sizeof(long)))
goto err;
if (out_data == NULL || out_len == NULL)
goto err;
if (*out_data != NULL || *out_len != 0)
goto err;
for (i = sizeof(uint64_t) - 1; i >= 0; i--) {
u8 = (val >> (i * 8)) & 0xff;
if (!started && i != 0 && u8 == 0)
continue;
if (!CBB_add_u8(&cbb, u8))
goto err;
started = 1;
}
if (!CBB_finish(&cbb, &data, &data_len))
goto err;
if (data_len > INT_MAX)
goto err;
*out_data = data;
*out_len = (int)data_len;
data = NULL;
ret = 1;
err:
CBB_cleanup(&cbb);
freezero(data, data_len);
return ret;
}
int
asn1_aint_get_int64(CBS *cbs, int negative, int64_t *out_val)
{
uint64_t val;
if (!asn1_aint_get_uint64(cbs, &val))
return 0;
if (negative) {
if (val > (uint64_t)INT64_MIN) {
ASN1error(ASN1_R_TOO_SMALL);
return 0;
}
*out_val = (int64_t)-val;
} else {
if (val > (uint64_t)INT64_MAX) {
ASN1error(ASN1_R_TOO_LARGE);
return 0;
}
*out_val = (int64_t)val;
}
return 1;
}
int
ASN1_INTEGER_get_uint64(uint64_t *out_val, const ASN1_INTEGER *aint)
{
uint64_t val;
CBS cbs;
*out_val = 0;
if (aint == NULL || aint->length < 0)
return 0;
if (aint->type == V_ASN1_NEG_INTEGER) {
ASN1error(ASN1_R_ILLEGAL_NEGATIVE_VALUE);
return 0;
}
if (aint->type != V_ASN1_INTEGER) {
ASN1error(ASN1_R_WRONG_INTEGER_TYPE);
return 0;
}
CBS_init(&cbs, aint->data, aint->length);
if (!asn1_aint_get_uint64(&cbs, &val))
return 0;
*out_val = val;
return 1;
}
LCRYPTO_ALIAS(ASN1_INTEGER_get_uint64);
int
ASN1_INTEGER_set_uint64(ASN1_INTEGER *aint, uint64_t val)
{
asn1_aint_clear(aint);
return asn1_aint_set_uint64(val, &aint->data, &aint->length);
}
LCRYPTO_ALIAS(ASN1_INTEGER_set_uint64);
int
ASN1_INTEGER_get_int64(int64_t *out_val, const ASN1_INTEGER *aint)
{
CBS cbs;
*out_val = 0;
if (aint == NULL || aint->length < 0)
return 0;
if (aint->type != V_ASN1_INTEGER &&
aint->type != V_ASN1_NEG_INTEGER) {
ASN1error(ASN1_R_WRONG_INTEGER_TYPE);
return 0;
}
CBS_init(&cbs, aint->data, aint->length);
return asn1_aint_get_int64(&cbs, (aint->type == V_ASN1_NEG_INTEGER),
out_val);
}
LCRYPTO_ALIAS(ASN1_INTEGER_get_int64);
int
ASN1_INTEGER_set_int64(ASN1_INTEGER *aint, int64_t val)
{
uint64_t uval;
asn1_aint_clear(aint);
uval = (uint64_t)val;
if (val < 0) {
aint->type = V_ASN1_NEG_INTEGER;
uval = -uval;
}
return asn1_aint_set_uint64(uval, &aint->data, &aint->length);
}
LCRYPTO_ALIAS(ASN1_INTEGER_set_int64);
long
ASN1_INTEGER_get(const ASN1_INTEGER *aint)
{
int64_t val;
if (aint == NULL)
return 0;
if (!ASN1_INTEGER_get_int64(&val, aint))
return -1;
if (val < LONG_MIN || val > LONG_MAX) {
/* hmm... a bit ugly, return all ones */
return -1;
}
return (long)val;
}
LCRYPTO_ALIAS(ASN1_INTEGER_get);
int
ASN1_INTEGER_set(ASN1_INTEGER *aint, long val)
{
return ASN1_INTEGER_set_int64(aint, val);
}
LCRYPTO_ALIAS(ASN1_INTEGER_set);
ASN1_INTEGER *
BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai)
{
ASN1_INTEGER *ret;
int len, j;
if (ai == NULL)
ret = ASN1_INTEGER_new();
else
ret = ai;
if (ret == NULL) {
ASN1error(ERR_R_NESTED_ASN1_ERROR);
goto err;
}
if (!ASN1_INTEGER_valid(ret))
goto err;
if (BN_is_negative(bn))
ret->type = V_ASN1_NEG_INTEGER;
else
ret->type = V_ASN1_INTEGER;
j = BN_num_bits(bn);
len = ((j == 0) ? 0 : ((j / 8) + 1));
if (ret->length < len + 4) {
unsigned char *new_data = realloc(ret->data, len + 4);
if (!new_data) {
ASN1error(ERR_R_MALLOC_FAILURE);
goto err;
}
ret->data = new_data;
}
ret->length = BN_bn2bin(bn, ret->data);
/* Correct zero case */
if (!ret->length) {
ret->data[0] = 0;
ret->length = 1;
}
return (ret);
err:
if (ret != ai)
ASN1_INTEGER_free(ret);
return (NULL);
}
LCRYPTO_ALIAS(BN_to_ASN1_INTEGER);
BIGNUM *
ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn)
{
BIGNUM *ret;
if (!ASN1_INTEGER_valid(ai))
return (NULL);
if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL)
ASN1error(ASN1_R_BN_LIB);
else if (ai->type == V_ASN1_NEG_INTEGER)
BN_set_negative(ret, 1);
return (ret);
}
LCRYPTO_ALIAS(ASN1_INTEGER_to_BN);
int
i2a_ASN1_INTEGER(BIO *bp, const ASN1_INTEGER *a)
{
int i, n = 0;
static const char h[] = "0123456789ABCDEF";
char buf[2];
if (a == NULL)
return (0);
if (a->type & V_ASN1_NEG) {
if (BIO_write(bp, "-", 1) != 1)
goto err;
n = 1;
}
if (a->length == 0) {
if (BIO_write(bp, "00", 2) != 2)
goto err;
n += 2;
} else {
for (i = 0; i < a->length; i++) {
if ((i != 0) && (i % 35 == 0)) {
if (BIO_write(bp, "\\\n", 2) != 2)
goto err;
n += 2;
}
buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
if (BIO_write(bp, buf, 2) != 2)
goto err;
n += 2;
}
}
return (n);
err:
return (-1);
}
LCRYPTO_ALIAS(i2a_ASN1_INTEGER);
int
a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size)
{
int ret = 0;
int i, j,k, m,n, again, bufsize;
unsigned char *s = NULL, *sp;
unsigned char *bufp;
int num = 0, slen = 0, first = 1;
bs->type = V_ASN1_INTEGER;
bufsize = BIO_gets(bp, buf, size);
for (;;) {
if (bufsize < 1)
goto err_sl;
i = bufsize;
if (buf[i - 1] == '\n')
buf[--i] = '\0';
if (i == 0)
goto err_sl;
if (buf[i - 1] == '\r')
buf[--i] = '\0';
if (i == 0)
goto err_sl;
if (buf[i - 1] == '\\') {
i--;
again = 1;
} else
again = 0;
buf[i] = '\0';
if (i < 2)
goto err_sl;
bufp = (unsigned char *)buf;
if (first) {
first = 0;
if ((bufp[0] == '0') && (buf[1] == '0')) {
bufp += 2;
i -= 2;
}
}
k = 0;
if (i % 2 != 0) {
ASN1error(ASN1_R_ODD_NUMBER_OF_CHARS);
goto err;
}
i /= 2;
if (num + i > slen) {
if ((sp = recallocarray(s, slen, num + i, 1)) == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
goto err;
}
s = sp;
slen = num + i;
}
for (j = 0; j < i; j++, k += 2) {
for (n = 0; n < 2; n++) {
m = bufp[k + n];
if ((m >= '0') && (m <= '9'))
m -= '0';
else if ((m >= 'a') && (m <= 'f'))
m = m - 'a' + 10;
else if ((m >= 'A') && (m <= 'F'))
m = m - 'A' + 10;
else {
ASN1error(ASN1_R_NON_HEX_CHARACTERS);
goto err;
}
s[num + j] <<= 4;
s[num + j] |= m;
}
}
num += i;
if (again)
bufsize = BIO_gets(bp, buf, size);
else
break;
}
bs->length = num;
bs->data = s;
return (1);
err_sl:
ASN1error(ASN1_R_SHORT_LINE);
err:
free(s);
return (ret);
}
LCRYPTO_ALIAS(a2i_ASN1_INTEGER);
static void
asn1_aint_twos_complement(uint8_t *data, size_t data_len)
{
uint8_t carry = 1;
ssize_t i;
for (i = data_len - 1; i >= 0; i--) {
data[i] = (data[i] ^ 0xff) + carry;
if (data[i] != 0)
carry = 0;
}
}
static int
asn1_aint_keep_twos_padding(const uint8_t *data, size_t data_len)
{
size_t i;
/*
* If a two's complement value has a padding byte (0xff) and the rest
* of the value is all zeros, the padding byte cannot be removed as when
* converted from two's complement this becomes 0x01 (in the place of
* the padding byte) followed by the same number of zero bytes.
*/
if (data_len <= 1 || data[0] != 0xff)
return 0;
for (i = 1; i < data_len; i++) {
if (data[i] != 0)
return 0;
}
return 1;
}
static int
i2c_ASN1_INTEGER_cbb(ASN1_INTEGER *aint, CBB *cbb)
{
uint8_t *data = NULL;
size_t data_len = 0;
uint8_t padding, val;
uint8_t msb;
CBS cbs;
int ret = 0;
if (aint->length < 0)
goto err;
if (aint->data == NULL && aint->length != 0)
goto err;
if ((aint->type & ~V_ASN1_NEG) != V_ASN1_ENUMERATED &&
(aint->type & ~V_ASN1_NEG) != V_ASN1_INTEGER)
goto err;
CBS_init(&cbs, aint->data, aint->length);
/* Find the first non-zero byte. */
while (CBS_len(&cbs) > 0) {
if (!CBS_peek_u8(&cbs, &val))
goto err;
if (val != 0)
break;
if (!CBS_skip(&cbs, 1))
goto err;
}
/* A zero value is encoded as a single octet. */
if (CBS_len(&cbs) == 0) {
if (!CBB_add_u8(cbb, 0))
goto err;
goto done;
}
if (!CBS_stow(&cbs, &data, &data_len))
goto err;
if ((aint->type & V_ASN1_NEG) != 0)
asn1_aint_twos_complement(data, data_len);
/* Topmost bit indicates sign, padding is all zeros or all ones. */
msb = (data[0] >> 7);
padding = (msb - 1) & 0xff;
/* See if we need a padding octet to avoid incorrect sign. */
if (((aint->type & V_ASN1_NEG) == 0 && msb == 1) ||
((aint->type & V_ASN1_NEG) != 0 && msb == 0)) {
if (!CBB_add_u8(cbb, padding))
goto err;
}
if (!CBB_add_bytes(cbb, data, data_len))
goto err;
done:
ret = 1;
err:
freezero(data, data_len);
return ret;
}
int
i2c_ASN1_INTEGER(ASN1_INTEGER *aint, unsigned char **pp)
{
uint8_t *data = NULL;
size_t data_len = 0;
CBB cbb;
int ret = -3;
if (!CBB_init(&cbb, 0))
goto err;
if (!i2c_ASN1_INTEGER_cbb(aint, &cbb))
goto err;
if (!CBB_finish(&cbb, &data, &data_len))
goto err;
if (data_len > INT_MAX)
goto err;
if (pp != NULL) {
if ((uintptr_t)*pp > UINTPTR_MAX - data_len)
goto err;
memcpy(*pp, data, data_len);
*pp += data_len;
}
ret = data_len;
err:
freezero(data, data_len);
CBB_cleanup(&cbb);
return ret;
}
int
c2i_ASN1_INTEGER_cbs(ASN1_INTEGER **out_aint, CBS *cbs)
{
ASN1_INTEGER *aint = NULL;
uint8_t *data = NULL;
size_t data_len = 0;
uint8_t padding, val;
uint8_t negative;
int ret = 0;
if (out_aint == NULL)
goto err;
if (*out_aint != NULL) {
ASN1_INTEGER_free(*out_aint);
*out_aint = NULL;
}
if (CBS_len(cbs) == 0) {
/* XXX INVALID ENCODING? */
ASN1error(ERR_R_ASN1_LENGTH_MISMATCH);
goto err;
}
if (!CBS_peek_u8(cbs, &val))
goto err;
/* Topmost bit indicates sign, padding is all zeros or all ones. */
negative = (val >> 7);
padding = ~(negative - 1) & 0xff;
/*
* Ensure that the first 9 bits are not all zero or all one, as per
* X.690 section 8.3.2. Remove the padding octet if possible.
*/
if (CBS_len(cbs) > 1 && val == padding) {
if (!asn1_aint_keep_twos_padding(CBS_data(cbs), CBS_len(cbs))) {
if (!CBS_get_u8(cbs, &padding))
goto err;
if (!CBS_peek_u8(cbs, &val))
goto err;
if ((val >> 7) == (padding >> 7)) {
/* XXX INVALID ENCODING? */
ASN1error(ERR_R_ASN1_LENGTH_MISMATCH);
goto err;
}
}
}
if (!CBS_stow(cbs, &data, &data_len))
goto err;
if (data_len > INT_MAX)
goto err;
if ((aint = ASN1_INTEGER_new()) == NULL)
goto err;
/*
* Negative integers are handled as a separate type - convert from
* two's complement for internal representation.
*/
if (negative) {
aint->type = V_ASN1_NEG_INTEGER;
asn1_aint_twos_complement(data, data_len);
}
aint->data = data;
aint->length = (int)data_len;
data = NULL;
*out_aint = aint;
aint = NULL;
ret = 1;
err:
ASN1_INTEGER_free(aint);
freezero(data, data_len);
return ret;
}
ASN1_INTEGER *
c2i_ASN1_INTEGER(ASN1_INTEGER **out_aint, const unsigned char **pp, long len)
{
ASN1_INTEGER *aint = NULL;
CBS content;
if (out_aint != NULL) {
ASN1_INTEGER_free(*out_aint);
*out_aint = NULL;
}
if (len < 0) {
ASN1error(ASN1_R_LENGTH_ERROR);
return NULL;
}
CBS_init(&content, *pp, len);
if (!c2i_ASN1_INTEGER_cbs(&aint, &content))
return NULL;
*pp = CBS_data(&content);
if (out_aint != NULL)
*out_aint = aint;
return aint;
}
int
i2d_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_INTEGER_it);
}
LCRYPTO_ALIAS(i2d_ASN1_INTEGER);
ASN1_INTEGER *
d2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **in, long len)
{
return (ASN1_INTEGER *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&ASN1_INTEGER_it);
}
LCRYPTO_ALIAS(d2i_ASN1_INTEGER);
/* 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 = ASN1_INTEGER_new()) == NULL)
return (NULL);
} else
ret = (*a);
if (!ASN1_INTEGER_valid(ret)) {
i = ERR_R_ASN1_LENGTH_MISMATCH;
goto err;
}
p = *pp;
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
if (inf & 0x80) {
i = ASN1_R_BAD_OBJECT_HEADER;
goto err;
}
if (tag != V_ASN1_INTEGER) {
i = ASN1_R_EXPECTING_AN_INTEGER;
goto err;
}
/* We must malloc stuff, even for 0 bytes otherwise it
* signifies a missing NULL parameter. */
if (len < 0 || len > INT_MAX) {
i = ERR_R_ASN1_LENGTH_MISMATCH;
goto err;
}
s = malloc(len + 1);
if (s == NULL) {
i = ERR_R_MALLOC_FAILURE;
goto err;
}
ret->type = V_ASN1_INTEGER;
if (len) {
if ((*p == 0) && (len != 1)) {
p++;
len--;
}
memcpy(s, p, len);
p += len;
}
free(ret->data);
ret->data = s;
ret->length = (int)len;
if (a != NULL)
(*a) = ret;
*pp = p;
return (ret);
err:
ASN1error(i);
if (a == NULL || *a != ret)
ASN1_INTEGER_free(ret);
return (NULL);
}
LCRYPTO_ALIAS(d2i_ASN1_UINTEGER);

449
crypto/asn1/a_mbstr.c Normal file
View File

@@ -0,0 +1,449 @@
/* $OpenBSD: a_mbstr.c,v 1.27 2023/07/05 21:23:36 beck Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 1999.
*/
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <openssl/asn1.h>
#include <openssl/err.h>
#include "asn1_local.h"
static int traverse_string(const unsigned char *p, int len, int inform,
int (*rfunc)(unsigned long value, void *in), void *arg);
static int in_utf8(unsigned long value, void *arg);
static int out_utf8(unsigned long value, void *arg);
static int type_str(unsigned long value, void *arg);
static int cpy_asc(unsigned long value, void *arg);
static int cpy_bmp(unsigned long value, void *arg);
static int cpy_univ(unsigned long value, void *arg);
static int cpy_utf8(unsigned long value, void *arg);
static int is_printable(unsigned long value);
/* These functions take a string in UTF8, ASCII or multibyte form and
* a mask of permissible ASN1 string types. It then works out the minimal
* type (using the order Printable < IA5 < T61 < BMP < Universal < UTF8)
* and creates a string of the correct type with the supplied data.
* Yes this is horrible: it has to be :-(
* The 'ncopy' form checks minimum and maximum size limits too.
*/
int
ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
int inform, unsigned long mask)
{
return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0);
}
LCRYPTO_ALIAS(ASN1_mbstring_copy);
int
ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
int inform, unsigned long mask, long minsize, long maxsize)
{
int str_type;
int ret;
char free_out;
int outform, outlen = 0;
ASN1_STRING *dest;
unsigned char *p;
int nchar;
int (*cpyfunc)(unsigned long, void *) = NULL;
if (len < 0)
len = strlen((const char *)in);
if (!mask)
mask = DIRSTRING_TYPE;
/* First do a string check and work out the number of characters */
switch (inform) {
case MBSTRING_BMP:
if (len & 1) {
ASN1error(ASN1_R_INVALID_BMPSTRING_LENGTH);
return -1;
}
nchar = len >> 1;
break;
case MBSTRING_UNIV:
if (len & 3) {
ASN1error(ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
return -1;
}
nchar = len >> 2;
break;
case MBSTRING_UTF8:
nchar = 0;
/* This counts the characters and does utf8 syntax checking */
ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar);
if (ret < 0) {
ASN1error(ASN1_R_INVALID_UTF8STRING);
return -1;
}
break;
case MBSTRING_ASC:
nchar = len;
break;
default:
ASN1error(ASN1_R_UNKNOWN_FORMAT);
return -1;
}
if ((minsize > 0) && (nchar < minsize)) {
ASN1error(ASN1_R_STRING_TOO_SHORT);
ERR_asprintf_error_data("minsize=%ld", minsize);
return -1;
}
if ((maxsize > 0) && (nchar > maxsize)) {
ASN1error(ASN1_R_STRING_TOO_LONG);
ERR_asprintf_error_data("maxsize=%ld", maxsize);
return -1;
}
/* Now work out minimal type (if any) */
if (traverse_string(in, len, inform, type_str, &mask) < 0) {
ASN1error(ASN1_R_ILLEGAL_CHARACTERS);
return -1;
}
/* Now work out output format and string type */
outform = MBSTRING_ASC;
if (mask & B_ASN1_PRINTABLESTRING)
str_type = V_ASN1_PRINTABLESTRING;
else if (mask & B_ASN1_IA5STRING)
str_type = V_ASN1_IA5STRING;
else if (mask & B_ASN1_T61STRING)
str_type = V_ASN1_T61STRING;
else if (mask & B_ASN1_BMPSTRING) {
str_type = V_ASN1_BMPSTRING;
outform = MBSTRING_BMP;
} else if (mask & B_ASN1_UNIVERSALSTRING) {
str_type = V_ASN1_UNIVERSALSTRING;
outform = MBSTRING_UNIV;
} else {
str_type = V_ASN1_UTF8STRING;
outform = MBSTRING_UTF8;
}
if (!out)
return str_type;
if (*out) {
free_out = 0;
dest = *out;
if (dest->data) {
dest->length = 0;
free(dest->data);
dest->data = NULL;
}
dest->type = str_type;
} else {
free_out = 1;
dest = ASN1_STRING_type_new(str_type);
if (!dest) {
ASN1error(ERR_R_MALLOC_FAILURE);
return -1;
}
*out = dest;
}
/* If both the same type just copy across */
if (inform == outform) {
if (!ASN1_STRING_set(dest, in, len)) {
ASN1error(ERR_R_MALLOC_FAILURE);
goto err;
}
return str_type;
}
/* Work out how much space the destination will need */
switch (outform) {
case MBSTRING_ASC:
outlen = nchar;
cpyfunc = cpy_asc;
break;
case MBSTRING_BMP:
outlen = nchar << 1;
cpyfunc = cpy_bmp;
break;
case MBSTRING_UNIV:
outlen = nchar << 2;
cpyfunc = cpy_univ;
break;
case MBSTRING_UTF8:
outlen = 0;
if (traverse_string(in, len, inform, out_utf8, &outlen) < 0) {
ASN1error(ASN1_R_ILLEGAL_CHARACTERS);
goto err;
}
cpyfunc = cpy_utf8;
break;
}
if (!(p = malloc(outlen + 1))) {
ASN1error(ERR_R_MALLOC_FAILURE);
goto err;
}
dest->length = outlen;
dest->data = p;
p[outlen] = 0;
traverse_string(in, len, inform, cpyfunc, &p);
return str_type;
err:
if (free_out) {
ASN1_STRING_free(dest);
*out = NULL;
}
return -1;
}
LCRYPTO_ALIAS(ASN1_mbstring_ncopy);
/* This function traverses a string and passes the value of each character
* to an optional function along with a void * argument.
*/
static int
traverse_string(const unsigned char *p, int len, int inform,
int (*rfunc)(unsigned long value, void *in), void *arg)
{
unsigned long value;
int ret;
while (len) {
switch (inform) {
case MBSTRING_ASC:
value = *p++;
len--;
break;
case MBSTRING_BMP:
value = *p++ << 8;
value |= *p++;
/* BMP is explicitly defined to not support surrogates */
if (UNICODE_IS_SURROGATE(value))
return -1;
len -= 2;
break;
case MBSTRING_UNIV:
value = (unsigned long)*p++ << 24;
value |= *p++ << 16;
value |= *p++ << 8;
value |= *p++;
if (value > UNICODE_MAX || UNICODE_IS_SURROGATE(value))
return -1;
len -= 4;
break;
default:
ret = UTF8_getc(p, len, &value);
if (ret < 0)
return -1;
len -= ret;
p += ret;
break;
}
if (rfunc) {
ret = rfunc(value, arg);
if (ret <= 0)
return ret;
}
}
return 1;
}
/* Various utility functions for traverse_string */
/* Just count number of characters */
static int
in_utf8(unsigned long value, void *arg)
{
int *nchar;
nchar = arg;
(*nchar)++;
return 1;
}
/* Determine size of output as a UTF8 String */
static int
out_utf8(unsigned long value, void *arg)
{
int *outlen;
int ret;
outlen = arg;
ret = UTF8_putc(NULL, -1, value);
if (ret < 0)
return ret;
*outlen += ret;
return 1;
}
/* Determine the "type" of a string: check each character against a
* supplied "mask".
*/
static int
type_str(unsigned long value, void *arg)
{
unsigned long types;
types = *((unsigned long *)arg);
if ((types & B_ASN1_PRINTABLESTRING) && !is_printable(value))
types &= ~B_ASN1_PRINTABLESTRING;
if ((types & B_ASN1_IA5STRING) && (value > 127))
types &= ~B_ASN1_IA5STRING;
if ((types & B_ASN1_T61STRING) && (value > 0xff))
types &= ~B_ASN1_T61STRING;
if ((types & B_ASN1_BMPSTRING) && (value > 0xffff))
types &= ~B_ASN1_BMPSTRING;
if (!types)
return -1;
*((unsigned long *)arg) = types;
return 1;
}
/* Copy one byte per character ASCII like strings */
static int
cpy_asc(unsigned long value, void *arg)
{
unsigned char **p, *q;
p = arg;
q = *p;
*q = value;
(*p)++;
return 1;
}
/* Copy two byte per character BMPStrings */
static int
cpy_bmp(unsigned long value, void *arg)
{
unsigned char **p, *q;
p = arg;
q = *p;
*q++ = (value >> 8) & 0xff;
*q = value & 0xff;
*p += 2;
return 1;
}
/* Copy four byte per character UniversalStrings */
static int
cpy_univ(unsigned long value, void *arg)
{
unsigned char **p, *q;
p = arg;
q = *p;
*q++ = (value >> 24) & 0xff;
*q++ = (value >> 16) & 0xff;
*q++ = (value >> 8) & 0xff;
*q = value & 0xff;
*p += 4;
return 1;
}
/* Copy to a UTF8String */
static int
cpy_utf8(unsigned long value, void *arg)
{
unsigned char **p;
int ret;
p = arg;
/* We already know there is enough room so pass 0xff as the length */
ret = UTF8_putc(*p, 0xff, value);
*p += ret;
return 1;
}
/* Return 1 if the character is permitted in a PrintableString */
static int
is_printable(unsigned long value)
{
int ch;
if (value > 0x7f)
return 0;
ch = (int)value;
/* Note: we can't use 'isalnum' because certain accented
* characters may count as alphanumeric in some environments.
*/
if ((ch >= 'a') && (ch <= 'z'))
return 1;
if ((ch >= 'A') && (ch <= 'Z'))
return 1;
if ((ch >= '0') && (ch <= '9'))
return 1;
if ((ch == ' ') || strchr("'()+,-./:=?", ch))
return 1;
return 0;
}

676
crypto/asn1/a_object.c Normal file
View File

@@ -0,0 +1,676 @@
/* $OpenBSD: a_object.c,v 1.51 2023/07/05 21:23:36 beck Exp $ */
/* 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 <limits.h>
#include <stdio.h>
#include <string.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/err.h>
#include <openssl/buffer.h>
#include <openssl/objects.h>
#include "asn1_local.h"
const ASN1_ITEM ASN1_OBJECT_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_OBJECT,
.sname = "ASN1_OBJECT",
};
ASN1_OBJECT *
ASN1_OBJECT_new(void)
{
ASN1_OBJECT *a;
if ((a = calloc(1, sizeof(ASN1_OBJECT))) == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
return (NULL);
}
a->flags = ASN1_OBJECT_FLAG_DYNAMIC;
return a;
}
LCRYPTO_ALIAS(ASN1_OBJECT_new);
void
ASN1_OBJECT_free(ASN1_OBJECT *a)
{
if (a == NULL)
return;
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) {
free((void *)a->sn);
free((void *)a->ln);
a->sn = a->ln = NULL;
}
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) {
freezero((void *)a->data, a->length);
a->data = NULL;
a->length = 0;
}
if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC)
free(a);
}
LCRYPTO_ALIAS(ASN1_OBJECT_free);
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));
}
LCRYPTO_ALIAS(ASN1_OBJECT_create);
static int
oid_add_arc(CBB *cbb, uint64_t arc)
{
int started = 0;
uint8_t val;
int i;
for (i = (sizeof(arc) * 8) / 7; i >= 0; i--) {
val = (arc >> (i * 7)) & 0x7f;
if (!started && i != 0 && val == 0)
continue;
if (i > 0)
val |= 0x80;
if (!CBB_add_u8(cbb, val))
return 0;
started = 1;
}
return 1;
}
static int
oid_parse_arc(CBS *cbs, uint64_t *out_arc)
{
uint64_t arc = 0;
uint8_t val;
do {
if (!CBS_get_u8(cbs, &val))
return 0;
if (arc == 0 && val == 0x80)
return 0;
if (out_arc != NULL && arc > (UINT64_MAX >> 7))
return 0;
arc = (arc << 7) | (val & 0x7f);
} while (val & 0x80);
if (out_arc != NULL)
*out_arc = arc;
return 1;
}
static int
oid_add_arc_txt(CBB *cbb, uint64_t arc, int first)
{
const char *fmt = ".%llu";
char s[22]; /* Digits in decimal representation of 2^64-1, plus '.' and NUL. */
int n;
if (first)
fmt = "%llu";
n = snprintf(s, sizeof(s), fmt, (unsigned long long)arc);
if (n < 0 || (size_t)n >= sizeof(s))
return 0;
if (!CBB_add_bytes(cbb, s, n))
return 0;
return 1;
}
static int
oid_parse_arc_txt(CBS *cbs, uint64_t *out_arc, char *separator, int first)
{
uint64_t arc = 0;
int digits = 0;
uint8_t val;
if (!first) {
if (!CBS_get_u8(cbs, &val))
return 0;
if ((*separator == 0 && val != '.' && val != ' ') ||
(*separator != 0 && val != *separator)) {
ASN1error(ASN1_R_INVALID_SEPARATOR);
return 0;
}
*separator = val;
}
while (CBS_len(cbs) > 0) {
if (!CBS_peek_u8(cbs, &val))
return 0;
if (val == '.' || val == ' ')
break;
if (!CBS_get_u8(cbs, &val))
return 0;
if (val < '0' || val > '9') {
/* For the first arc we treat this as the separator. */
if (first) {
ASN1error(ASN1_R_INVALID_SEPARATOR);
return 0;
}
ASN1error(ASN1_R_INVALID_DIGIT);
return 0;
}
val -= '0';
if (digits > 0 && arc == 0 && val == 0) {
ASN1error(ASN1_R_INVALID_NUMBER);
return 0;
}
digits++;
if (arc > UINT64_MAX / 10) {
ASN1error(ASN1_R_TOO_LONG);
return 0;
}
arc = arc * 10 + val;
}
if (digits < 1) {
ASN1error(ASN1_R_INVALID_NUMBER);
return 0;
}
*out_arc = arc;
return 1;
}
static int
a2c_ASN1_OBJECT_internal(CBB *cbb, CBS *cbs)
{
uint64_t arc, si1, si2;
char separator = 0;
if (!oid_parse_arc_txt(cbs, &si1, &separator, 1))
return 0;
if (CBS_len(cbs) == 0) {
ASN1error(ASN1_R_MISSING_SECOND_NUMBER);
return 0;
}
if (!oid_parse_arc_txt(cbs, &si2, &separator, 0))
return 0;
/*
* X.690 section 8.19 - the first two subidentifiers are encoded as
* (x * 40) + y, with x being limited to [0,1,2]. The second
* subidentifier cannot exceed 39 for x < 2.
*/
if (si1 > 2) {
ASN1error(ASN1_R_FIRST_NUM_TOO_LARGE);
return 0;
}
if ((si1 < 2 && si2 >= 40) || si2 > UINT64_MAX - si1 * 40) {
ASN1error(ASN1_R_SECOND_NUMBER_TOO_LARGE);
return 0;
}
arc = si1 * 40 + si2;
if (!oid_add_arc(cbb, arc))
return 0;
while (CBS_len(cbs) > 0) {
if (!oid_parse_arc_txt(cbs, &arc, &separator, 0))
return 0;
if (!oid_add_arc(cbb, arc))
return 0;
}
return 1;
}
static int
c2a_ASN1_OBJECT(CBS *cbs, CBB *cbb)
{
uint64_t arc, si1, si2;
/*
* X.690 section 8.19 - the first two subidentifiers are encoded as
* (x * 40) + y, with x being limited to [0,1,2].
*/
if (!oid_parse_arc(cbs, &arc))
return 0;
if ((si1 = arc / 40) > 2)
si1 = 2;
si2 = arc - si1 * 40;
if (!oid_add_arc_txt(cbb, si1, 1))
return 0;
if (!oid_add_arc_txt(cbb, si2, 0))
return 0;
while (CBS_len(cbs) > 0) {
if (!oid_parse_arc(cbs, &arc))
return 0;
if (!oid_add_arc_txt(cbb, arc, 0))
return 0;
}
/* NUL terminate. */
if (!CBB_add_u8(cbb, 0))
return 0;
return 1;
}
int
a2d_ASN1_OBJECT(unsigned char *out, int out_len, const char *in, int in_len)
{
uint8_t *data = NULL;
size_t data_len;
CBS cbs;
CBB cbb;
int ret = 0;
memset(&cbb, 0, sizeof(cbb));
if (in_len == -1)
in_len = strlen(in);
if (in_len <= 0)
goto err;
CBS_init(&cbs, in, in_len);
if (!CBB_init(&cbb, 0))
goto err;
if (!a2c_ASN1_OBJECT_internal(&cbb, &cbs))
goto err;
if (!CBB_finish(&cbb, &data, &data_len))
goto err;
if (data_len > INT_MAX)
goto err;
if (out != NULL) {
if (out_len <= 0 || (size_t)out_len < data_len) {
ASN1error(ASN1_R_BUFFER_TOO_SMALL);
goto err;
}
memcpy(out, data, data_len);
}
ret = (int)data_len;
err:
CBB_cleanup(&cbb);
free(data);
return ret;
}
LCRYPTO_ALIAS(a2d_ASN1_OBJECT);
static int
i2t_ASN1_OBJECT_oid(const ASN1_OBJECT *aobj, CBB *cbb)
{
CBS cbs;
CBS_init(&cbs, aobj->data, aobj->length);
return c2a_ASN1_OBJECT(&cbs, cbb);
}
static int
i2t_ASN1_OBJECT_name(const ASN1_OBJECT *aobj, CBB *cbb, const char **out_name)
{
const char *name;
int nid;
*out_name = NULL;
if ((nid = OBJ_obj2nid(aobj)) == NID_undef)
return 0;
if ((name = OBJ_nid2ln(nid)) == NULL)
name = OBJ_nid2sn(nid);
if (name == NULL)
return 0;
*out_name = name;
if (!CBB_add_bytes(cbb, name, strlen(name)))
return 0;
/* NUL terminate. */
if (!CBB_add_u8(cbb, 0))
return 0;
return 1;
}
static int
i2t_ASN1_OBJECT_cbb(const ASN1_OBJECT *aobj, CBB *cbb, int no_name)
{
const char *name;
if (!no_name) {
if (i2t_ASN1_OBJECT_name(aobj, cbb, &name))
return 1;
if (name != NULL)
return 0;
}
return i2t_ASN1_OBJECT_oid(aobj, cbb);
}
int
i2t_ASN1_OBJECT_internal(const ASN1_OBJECT *aobj, char *buf, int buf_len, int no_name)
{
uint8_t *data = NULL;
size_t data_len;
CBB cbb;
int ret = 0;
if (buf_len < 0)
return 0;
if (buf_len > 0)
buf[0] = '\0';
if (aobj == NULL || aobj->data == NULL)
return 0;
if (!CBB_init(&cbb, 0))
goto err;
if (!i2t_ASN1_OBJECT_cbb(aobj, &cbb, no_name))
goto err;
if (!CBB_finish(&cbb, &data, &data_len))
goto err;
ret = strlcpy(buf, data, buf_len);
err:
CBB_cleanup(&cbb);
free(data);
return ret;
}
int
i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *aobj)
{
return i2t_ASN1_OBJECT_internal(aobj, buf, buf_len, 0);
}
LCRYPTO_ALIAS(i2t_ASN1_OBJECT);
ASN1_OBJECT *
t2i_ASN1_OBJECT_internal(const char *oid)
{
ASN1_OBJECT *aobj = NULL;
uint8_t *data = NULL;
size_t data_len;
CBB cbb;
CBS cbs;
memset(&cbb, 0, sizeof(cbb));
CBS_init(&cbs, oid, strlen(oid));
if (!CBB_init(&cbb, 0))
goto err;
if (!a2c_ASN1_OBJECT_internal(&cbb, &cbs))
goto err;
if (!CBB_finish(&cbb, &data, &data_len))
goto err;
if (data_len > INT_MAX)
goto err;
if ((aobj = ASN1_OBJECT_new()) == NULL)
goto err;
aobj->data = data;
aobj->length = (int)data_len;
aobj->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;
data = NULL;
err:
CBB_cleanup(&cbb);
free(data);
return aobj;
}
int
i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *aobj)
{
uint8_t *data = NULL;
size_t data_len;
CBB cbb;
int ret = -1;
if (aobj == NULL || aobj->data == NULL)
return BIO_write(bp, "NULL", 4);
if (!CBB_init(&cbb, 0))
goto err;
if (!i2t_ASN1_OBJECT_cbb(aobj, &cbb, 0)) {
ret = BIO_write(bp, "<INVALID>", 9);
goto err;
}
if (!CBB_finish(&cbb, &data, &data_len))
goto err;
ret = BIO_write(bp, data, strlen(data));
err:
CBB_cleanup(&cbb);
free(data);
return ret;
}
LCRYPTO_ALIAS(i2a_ASN1_OBJECT);
int
c2i_ASN1_OBJECT_cbs(ASN1_OBJECT **out_aobj, CBS *content)
{
ASN1_OBJECT *aobj = NULL;
uint8_t *data = NULL;
size_t data_len;
CBS cbs;
if (out_aobj == NULL)
goto err;
if (*out_aobj != NULL) {
ASN1_OBJECT_free(*out_aobj);
*out_aobj = NULL;
}
/* Parse and validate OID encoding per X.690 8.19.2. */
CBS_dup(content, &cbs);
if (CBS_len(&cbs) == 0) {
ASN1error(ASN1_R_INVALID_OBJECT_ENCODING);
goto err;
}
while (CBS_len(&cbs) > 0) {
if (!oid_parse_arc(&cbs, NULL)) {
ASN1error(ASN1_R_INVALID_OBJECT_ENCODING);
goto err;
}
}
if (!CBS_stow(content, &data, &data_len))
goto err;
if (data_len > INT_MAX)
goto err;
if ((aobj = ASN1_OBJECT_new()) == NULL)
goto err;
aobj->data = data;
aobj->length = (int)data_len; /* XXX - change length to size_t. */
aobj->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;
*out_aobj = aobj;
return 1;
err:
ASN1_OBJECT_free(aobj);
free(data);
return 0;
}
ASN1_OBJECT *
c2i_ASN1_OBJECT(ASN1_OBJECT **out_aobj, const unsigned char **pp, long len)
{
ASN1_OBJECT *aobj = NULL;
CBS content;
if (out_aobj != NULL) {
ASN1_OBJECT_free(*out_aobj);
*out_aobj = NULL;
}
if (len < 0) {
ASN1error(ASN1_R_LENGTH_ERROR);
return NULL;
}
CBS_init(&content, *pp, len);
if (!c2i_ASN1_OBJECT_cbs(&aobj, &content))
return NULL;
*pp = CBS_data(&content);
if (out_aobj != NULL)
*out_aobj = aobj;
return aobj;
}
int
i2d_ASN1_OBJECT(const 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)
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);
}
LCRYPTO_ALIAS(i2d_ASN1_OBJECT);
ASN1_OBJECT *
d2i_ASN1_OBJECT(ASN1_OBJECT **out_aobj, const unsigned char **pp, long length)
{
ASN1_OBJECT *aobj = NULL;
uint32_t tag_number;
CBS cbs, content;
if (out_aobj != NULL) {
ASN1_OBJECT_free(*out_aobj);
*out_aobj = NULL;
}
if (length < 0) {
ASN1error(ASN1_R_LENGTH_ERROR);
return NULL;
}
CBS_init(&cbs, *pp, length);
if (!asn1_get_primitive(&cbs, 0, &tag_number, &content)) {
ASN1error(ASN1_R_BAD_OBJECT_HEADER);
return NULL;
}
if (tag_number != V_ASN1_OBJECT) {
ASN1error(ASN1_R_EXPECTING_AN_OBJECT);
return NULL;
}
if (!c2i_ASN1_OBJECT_cbs(&aobj, &content))
return NULL;
*pp = CBS_data(&cbs);
if (out_aobj != NULL)
*out_aobj = aobj;
return aobj;
}
LCRYPTO_ALIAS(d2i_ASN1_OBJECT);

119
crypto/asn1/a_octet.c Normal file
View File

@@ -0,0 +1,119 @@
/* $OpenBSD: a_octet.c,v 1.12 2023/07/05 21:23:36 beck Exp $ */
/* 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 <openssl/asn1.h>
#include <openssl/asn1t.h>
const ASN1_ITEM ASN1_OCTET_STRING_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_OCTET_STRING,
.sname = "ASN1_OCTET_STRING",
};
ASN1_OCTET_STRING *
ASN1_OCTET_STRING_new(void)
{
return (ASN1_OCTET_STRING *)ASN1_item_new(&ASN1_OCTET_STRING_it);
}
LCRYPTO_ALIAS(ASN1_OCTET_STRING_new);
void
ASN1_OCTET_STRING_free(ASN1_OCTET_STRING *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_OCTET_STRING_it);
}
LCRYPTO_ALIAS(ASN1_OCTET_STRING_free);
ASN1_OCTET_STRING *
ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *x)
{
return ASN1_STRING_dup(x);
}
LCRYPTO_ALIAS(ASN1_OCTET_STRING_dup);
int
ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a, const ASN1_OCTET_STRING *b)
{
return ASN1_STRING_cmp(a, b);
}
LCRYPTO_ALIAS(ASN1_OCTET_STRING_cmp);
int
ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *x, const unsigned char *d, int len)
{
return ASN1_STRING_set(x, d, len);
}
LCRYPTO_ALIAS(ASN1_OCTET_STRING_set);
int
i2d_ASN1_OCTET_STRING(ASN1_OCTET_STRING *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_OCTET_STRING_it);
}
LCRYPTO_ALIAS(i2d_ASN1_OCTET_STRING);
ASN1_OCTET_STRING *
d2i_ASN1_OCTET_STRING(ASN1_OCTET_STRING **a, const unsigned char **in, long len)
{
return (ASN1_OCTET_STRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&ASN1_OCTET_STRING_it);
}
LCRYPTO_ALIAS(d2i_ASN1_OCTET_STRING);

186
crypto/asn1/a_pkey.c Normal file
View File

@@ -0,0 +1,186 @@
/* $OpenBSD: a_pkey.c,v 1.6 2023/07/07 19:37:52 beck Exp $ */
/* 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 <openssl/opensslconf.h>
#include <openssl/asn1.h>
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#ifndef OPENSSL_NO_ENGINE
#include <openssl/engine.h>
#endif
#include "asn1_local.h"
#include "evp_local.h"
EVP_PKEY *
d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp, long length)
{
const unsigned char *p = *pp;
EVP_PKEY *ret;
if ((a == NULL) || (*a == NULL)) {
if ((ret = EVP_PKEY_new()) == NULL) {
ASN1error(ERR_R_EVP_LIB);
return (NULL);
}
} else {
ret = *a;
#ifndef OPENSSL_NO_ENGINE
ENGINE_finish(ret->engine);
ret->engine = NULL;
#endif
}
if (!EVP_PKEY_set_type(ret, type)) {
ASN1error(ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE);
goto err;
}
if (!ret->ameth->old_priv_decode ||
!ret->ameth->old_priv_decode(ret, pp, length)) {
if (ret->ameth->priv_decode) {
PKCS8_PRIV_KEY_INFO *p8 = NULL;
*pp = p; /* XXX */
p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, pp, length);
if (!p8)
goto err;
EVP_PKEY_free(ret);
ret = EVP_PKCS82PKEY(p8);
PKCS8_PRIV_KEY_INFO_free(p8);
} else {
ASN1error(ERR_R_ASN1_LIB);
goto err;
}
}
if (a != NULL)
(*a) = ret;
return (ret);
err:
if (a == NULL || *a != ret)
EVP_PKEY_free(ret);
return (NULL);
}
int
i2d_PrivateKey(EVP_PKEY *a, unsigned char **pp)
{
if (a->ameth && a->ameth->old_priv_encode) {
return a->ameth->old_priv_encode(a, pp);
}
if (a->ameth && a->ameth->priv_encode) {
PKCS8_PRIV_KEY_INFO *p8 = EVP_PKEY2PKCS8(a);
int ret = i2d_PKCS8_PRIV_KEY_INFO(p8, pp);
PKCS8_PRIV_KEY_INFO_free(p8);
return ret;
}
ASN1error(ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
return (-1);
}
/* This works like d2i_PrivateKey() except it automatically works out the type */
EVP_PKEY *
d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp, long length)
{
STACK_OF(ASN1_TYPE) *inkey;
const unsigned char *p;
int keytype;
p = *pp;
/* Dirty trick: read in the ASN1 data into a STACK_OF(ASN1_TYPE):
* by analyzing it we can determine the passed structure: this
* assumes the input is surrounded by an ASN1 SEQUENCE.
*/
inkey = d2i_ASN1_SEQUENCE_ANY(NULL, &p, length);
/* Since we only need to discern "traditional format" RSA and DSA
* keys we can just count the elements.
*/
if (sk_ASN1_TYPE_num(inkey) == 6)
keytype = EVP_PKEY_DSA;
else if (sk_ASN1_TYPE_num(inkey) == 4)
keytype = EVP_PKEY_EC;
else if (sk_ASN1_TYPE_num(inkey) == 3) {
/* This seems to be PKCS8, not traditional format */
PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(
NULL, pp, length);
EVP_PKEY *ret;
sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
if (!p8) {
ASN1error(ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
return NULL;
}
ret = EVP_PKCS82PKEY(p8);
PKCS8_PRIV_KEY_INFO_free(p8);
if (a) {
*a = ret;
}
return ret;
} else
keytype = EVP_PKEY_RSA;
sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
return d2i_PrivateKey(keytype, a, pp, length);
}

127
crypto/asn1/a_print.c Normal file
View File

@@ -0,0 +1,127 @@
/* $OpenBSD: a_print.c,v 1.13 2023/07/05 21:23:36 beck Exp $ */
/* 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 <openssl/asn1.h>
int
ASN1_PRINTABLE_type(const unsigned char *s, int len)
{
int c;
int ia5 = 0;
int t61 = 0;
if (len <= 0)
len = -1;
if (s == NULL)
return (V_ASN1_PRINTABLESTRING);
while (len-- > 0 && *s != '\0') {
c= *(s++);
if (!(((c >= 'a') && (c <= 'z')) ||
((c >= 'A') && (c <= 'Z')) ||
(c == ' ') ||
((c >= '0') && (c <= '9')) ||
(c == ' ') || (c == '\'') ||
(c == '(') || (c == ')') ||
(c == '+') || (c == ',') ||
(c == '-') || (c == '.') ||
(c == '/') || (c == ':') ||
(c == '=') || (c == '?')))
ia5 = 1;
if (c & 0x80)
t61 = 1;
}
if (t61)
return (V_ASN1_T61STRING);
if (ia5)
return (V_ASN1_IA5STRING);
return (V_ASN1_PRINTABLESTRING);
}
LCRYPTO_ALIAS(ASN1_PRINTABLE_type);
int
ASN1_UNIVERSALSTRING_to_string(ASN1_UNIVERSALSTRING *s)
{
int i;
unsigned char *p;
if (s->type != V_ASN1_UNIVERSALSTRING)
return (0);
if ((s->length % 4) != 0)
return (0);
p = s->data;
for (i = 0; i < s->length; i += 4) {
if ((p[0] != '\0') || (p[1] != '\0') || (p[2] != '\0'))
break;
else
p += 4;
}
if (i < s->length)
return (0);
p = s->data;
for (i = 3; i < s->length; i += 4) {
*(p++) = s->data[i];
}
*(p) = '\0';
s->length /= 4;
s->type = ASN1_PRINTABLE_type(s->data, s->length);
return (1);
}
LCRYPTO_ALIAS(ASN1_UNIVERSALSTRING_to_string);

160
crypto/asn1/a_pubkey.c Normal file
View File

@@ -0,0 +1,160 @@
/* $OpenBSD: a_pubkey.c,v 1.6 2023/07/07 19:37:52 beck Exp $ */
/* 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 <openssl/opensslconf.h>
#include <openssl/asn1.h>
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#ifndef OPENSSL_NO_DSA
#include <openssl/dsa.h>
#endif
#ifndef OPENSSL_NO_EC
#include <openssl/ec.h>
#endif
#ifndef OPENSSL_NO_RSA
#include <openssl/rsa.h>
#endif
#include "evp_local.h"
EVP_PKEY *
d2i_PublicKey(int type, EVP_PKEY **a, const unsigned char **pp, long length)
{
EVP_PKEY *ret;
if ((a == NULL) || (*a == NULL)) {
if ((ret = EVP_PKEY_new()) == NULL) {
ASN1error(ERR_R_EVP_LIB);
return (NULL);
}
} else
ret = *a;
if (!EVP_PKEY_set_type(ret, type)) {
ASN1error(ERR_R_EVP_LIB);
goto err;
}
switch (EVP_PKEY_id(ret)) {
#ifndef OPENSSL_NO_RSA
case EVP_PKEY_RSA:
if ((ret->pkey.rsa = d2i_RSAPublicKey(NULL, pp, length)) ==
NULL) {
ASN1error(ERR_R_ASN1_LIB);
goto err;
}
break;
#endif
#ifndef OPENSSL_NO_DSA
case EVP_PKEY_DSA:
if (!d2i_DSAPublicKey(&(ret->pkey.dsa), pp, length)) {
ASN1error(ERR_R_ASN1_LIB);
goto err;
}
break;
#endif
#ifndef OPENSSL_NO_EC
case EVP_PKEY_EC:
if (!o2i_ECPublicKey(&(ret->pkey.ec), pp, length)) {
ASN1error(ERR_R_ASN1_LIB);
goto err;
}
break;
#endif
default:
ASN1error(ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE);
goto err;
/* break; */
}
if (a != NULL)
(*a) = ret;
return (ret);
err:
if (a == NULL || *a != ret)
EVP_PKEY_free(ret);
return (NULL);
}
int
i2d_PublicKey(EVP_PKEY *a, unsigned char **pp)
{
switch (a->type) {
#ifndef OPENSSL_NO_RSA
case EVP_PKEY_RSA:
return (i2d_RSAPublicKey(a->pkey.rsa, pp));
#endif
#ifndef OPENSSL_NO_DSA
case EVP_PKEY_DSA:
return (i2d_DSAPublicKey(a->pkey.dsa, pp));
#endif
#ifndef OPENSSL_NO_EC
case EVP_PKEY_EC:
return (i2o_ECPublicKey(a->pkey.ec, pp));
#endif
default:
ASN1error(ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
return (-1);
}
}

603
crypto/asn1/a_strex.c Normal file
View File

@@ -0,0 +1,603 @@
/* $OpenBSD: a_strex.c,v 1.34 2023/07/07 19:37:52 beck Exp $ */
/* 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 <string.h>
#include <openssl/asn1.h>
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include "asn1_local.h"
#include "charmap.h"
/* ASN1_STRING_print_ex() and X509_NAME_print_ex().
* Enhanced string and name printing routines handling
* multibyte characters, RFC2253 and a host of other
* options.
*/
#define CHARTYPE_BS_ESC (ASN1_STRFLGS_ESC_2253 | CHARTYPE_FIRST_ESC_2253 | CHARTYPE_LAST_ESC_2253)
#define ESC_FLAGS (ASN1_STRFLGS_ESC_2253 | \
ASN1_STRFLGS_ESC_QUOTE | \
ASN1_STRFLGS_ESC_CTRL | \
ASN1_STRFLGS_ESC_MSB)
/* Three IO functions for sending data to memory, a BIO and
* and a FILE pointer.
*/
static int
send_bio_chars(void *arg, const void *buf, int len)
{
if (!arg)
return 1;
if (BIO_write(arg, buf, len) != len)
return 0;
return 1;
}
static int
send_fp_chars(void *arg, const void *buf, int len)
{
if (!arg)
return 1;
if (fwrite(buf, 1, (size_t)len, arg) != (size_t)len)
return 0;
return 1;
}
typedef int char_io(void *arg, const void *buf, int len);
/* This function handles display of
* strings, one character at a time.
* It is passed an unsigned long for each
* character because it could come from 2 or even
* 4 byte forms.
*/
static int
do_esc_char(unsigned long c, unsigned char flags, char *do_quotes,
char_io *io_ch, void *arg)
{
unsigned char chflgs, chtmp;
char tmphex[sizeof(long) * 2 + 3];
if (c > 0xffffffffL)
return -1;
if (c > 0xffff) {
snprintf(tmphex, sizeof tmphex, "\\W%08lX", c);
if (!io_ch(arg, tmphex, 10))
return -1;
return 10;
}
if (c > 0xff) {
snprintf(tmphex, sizeof tmphex, "\\U%04lX", c);
if (!io_ch(arg, tmphex, 6))
return -1;
return 6;
}
chtmp = (unsigned char)c;
if (chtmp > 0x7f)
chflgs = flags & ASN1_STRFLGS_ESC_MSB;
else
chflgs = char_type[chtmp] & flags;
if (chflgs & CHARTYPE_BS_ESC) {
/* If we don't escape with quotes, signal we need quotes */
if (chflgs & ASN1_STRFLGS_ESC_QUOTE) {
if (do_quotes)
*do_quotes = 1;
if (!io_ch(arg, &chtmp, 1))
return -1;
return 1;
}
if (!io_ch(arg, "\\", 1))
return -1;
if (!io_ch(arg, &chtmp, 1))
return -1;
return 2;
}
if (chflgs & (ASN1_STRFLGS_ESC_CTRL|ASN1_STRFLGS_ESC_MSB)) {
snprintf(tmphex, sizeof tmphex, "\\%02X", chtmp);
if (!io_ch(arg, tmphex, 3))
return -1;
return 3;
}
/* If we get this far and do any escaping at all must escape
* the escape character itself: backslash.
*/
if (chtmp == '\\' && flags & ESC_FLAGS) {
if (!io_ch(arg, "\\\\", 2))
return -1;
return 2;
}
if (!io_ch(arg, &chtmp, 1))
return -1;
return 1;
}
#define BUF_TYPE_WIDTH_MASK 0x7
#define BUF_TYPE_CONVUTF8 0x8
/* This function sends each character in a buffer to
* do_esc_char(). It interprets the content formats
* and converts to or from UTF8 as appropriate.
*/
static int
do_buf(unsigned char *buf, int buflen, int type, unsigned char flags,
char *quotes, char_io *io_ch, void *arg)
{
int i, outlen, len;
unsigned char orflags, *p, *q;
unsigned long c;
p = buf;
q = buf + buflen;
outlen = 0;
while (p != q) {
if (p == buf && flags & ASN1_STRFLGS_ESC_2253)
orflags = CHARTYPE_FIRST_ESC_2253;
else
orflags = 0;
switch (type & BUF_TYPE_WIDTH_MASK) {
case 4:
c = ((unsigned long)*p++) << 24;
c |= ((unsigned long)*p++) << 16;
c |= ((unsigned long)*p++) << 8;
c |= *p++;
if (c > UNICODE_MAX || UNICODE_IS_SURROGATE(c))
return -1;
break;
case 2:
c = ((unsigned long)*p++) << 8;
c |= *p++;
if (UNICODE_IS_SURROGATE(c))
return -1;
break;
case 1:
c = *p++;
break;
case 0:
i = UTF8_getc(p, q - p, &c);
if (i < 0)
return -1; /* Invalid UTF8String */
p += i;
break;
default:
return -1; /* invalid width */
}
if (p == q && flags & ASN1_STRFLGS_ESC_2253)
orflags = CHARTYPE_LAST_ESC_2253;
if (type & BUF_TYPE_CONVUTF8) {
unsigned char utfbuf[6];
int utflen;
utflen = UTF8_putc(utfbuf, sizeof utfbuf, c);
if (utflen < 0)
return -1;
for (i = 0; i < utflen; i++) {
/* We don't need to worry about setting orflags correctly
* because if utflen==1 its value will be correct anyway
* otherwise each character will be > 0x7f and so the
* character will never be escaped on first and last.
*/
len = do_esc_char(utfbuf[i],
(unsigned char)(flags | orflags), quotes,
io_ch, arg);
if (len < 0)
return -1;
outlen += len;
}
} else {
len = do_esc_char(c, (unsigned char)(flags | orflags),
quotes, io_ch, arg);
if (len < 0)
return -1;
outlen += len;
}
}
return outlen;
}
/* This function hex dumps a buffer of characters */
static int
do_hex_dump(char_io *io_ch, void *arg, unsigned char *buf, int buflen)
{
static const char hexdig[] = "0123456789ABCDEF";
unsigned char *p, *q;
char hextmp[2];
if (arg) {
p = buf;
q = buf + buflen;
while (p != q) {
hextmp[0] = hexdig[*p >> 4];
hextmp[1] = hexdig[*p & 0xf];
if (!io_ch(arg, hextmp, 2))
return -1;
p++;
}
}
return buflen << 1;
}
/* "dump" a string. This is done when the type is unknown,
* or the flags request it. We can either dump the content
* octets or the entire DER encoding. This uses the RFC2253
* #01234 format.
*/
static int
do_dump(unsigned long lflags, char_io *io_ch, void *arg, const ASN1_STRING *str)
{
/* Placing the ASN1_STRING in a temp ASN1_TYPE allows
* the DER encoding to readily obtained
*/
ASN1_TYPE t;
unsigned char *der_buf, *p;
int outlen, der_len;
if (!io_ch(arg, "#", 1))
return -1;
/* If we don't dump DER encoding just dump content octets */
if (!(lflags & ASN1_STRFLGS_DUMP_DER)) {
outlen = do_hex_dump(io_ch, arg, str->data, str->length);
if (outlen < 0)
return -1;
return outlen + 1;
}
t.type = str->type;
t.value.ptr = (char *)str;
der_len = i2d_ASN1_TYPE(&t, NULL);
der_buf = malloc(der_len);
if (!der_buf)
return -1;
p = der_buf;
i2d_ASN1_TYPE(&t, &p);
outlen = do_hex_dump(io_ch, arg, der_buf, der_len);
free(der_buf);
if (outlen < 0)
return -1;
return outlen + 1;
}
/* This is the main function, print out an
* ASN1_STRING taking note of various escape
* and display options. Returns number of
* characters written or -1 if an error
* occurred.
*/
static int
do_print_ex(char_io *io_ch, void *arg, unsigned long lflags,
const ASN1_STRING *str)
{
int outlen, len;
int type;
char quotes;
unsigned char flags;
quotes = 0;
/* Keep a copy of escape flags */
flags = (unsigned char)(lflags & ESC_FLAGS);
type = str->type;
outlen = 0;
if (lflags & ASN1_STRFLGS_SHOW_TYPE) {
const char *tagname;
tagname = ASN1_tag2str(type);
outlen += strlen(tagname);
if (!io_ch(arg, tagname, outlen) || !io_ch(arg, ":", 1))
return -1;
outlen++;
}
/* Decide what to do with type, either dump content or display it */
if (lflags & ASN1_STRFLGS_DUMP_ALL) {
/* Dump everything. */
type = -1;
} else if (lflags & ASN1_STRFLGS_IGNORE_TYPE) {
/* Ignore the string type. */
type = 1;
} else {
/* Else determine width based on type. */
type = asn1_tag2charwidth(type);
if (type == -1 && !(lflags & ASN1_STRFLGS_DUMP_UNKNOWN))
type = 1;
}
if (type == -1) {
len = do_dump(lflags, io_ch, arg, str);
if (len < 0)
return -1;
outlen += len;
return outlen;
}
if (lflags & ASN1_STRFLGS_UTF8_CONVERT) {
/* Note: if string is UTF8 and we want
* to convert to UTF8 then we just interpret
* it as 1 byte per character to avoid converting
* twice.
*/
if (!type)
type = 1;
else
type |= BUF_TYPE_CONVUTF8;
}
len = do_buf(str->data, str->length, type, flags, &quotes, io_ch, NULL);
if (len < 0)
return -1;
outlen += len;
if (quotes)
outlen += 2;
if (!arg)
return outlen;
if (quotes && !io_ch(arg, "\"", 1))
return -1;
if (do_buf(str->data, str->length, type, flags, NULL, io_ch, arg) < 0)
return -1;
if (quotes && !io_ch(arg, "\"", 1))
return -1;
return outlen;
}
/* Used for line indenting: print 'indent' spaces */
static int
do_indent(char_io *io_ch, void *arg, int indent)
{
int i;
for (i = 0; i < indent; i++)
if (!io_ch(arg, " ", 1))
return 0;
return 1;
}
#define FN_WIDTH_LN 25
#define FN_WIDTH_SN 10
static int
do_name_ex(char_io *io_ch, void *arg, const X509_NAME *n, int indent,
unsigned long flags)
{
int i, prev = -1, orflags, cnt;
int fn_opt, fn_nid;
ASN1_OBJECT *fn;
ASN1_STRING *val;
X509_NAME_ENTRY *ent;
char objtmp[80];
const char *objbuf;
int outlen, len;
char *sep_dn, *sep_mv, *sep_eq;
int sep_dn_len, sep_mv_len, sep_eq_len;
if (indent < 0)
indent = 0;
outlen = indent;
if (!do_indent(io_ch, arg, indent))
return -1;
switch (flags & XN_FLAG_SEP_MASK) {
case XN_FLAG_SEP_MULTILINE:
sep_dn = "\n";
sep_dn_len = 1;
sep_mv = " + ";
sep_mv_len = 3;
break;
case XN_FLAG_SEP_COMMA_PLUS:
sep_dn = ",";
sep_dn_len = 1;
sep_mv = "+";
sep_mv_len = 1;
indent = 0;
break;
case XN_FLAG_SEP_CPLUS_SPC:
sep_dn = ", ";
sep_dn_len = 2;
sep_mv = " + ";
sep_mv_len = 3;
indent = 0;
break;
case XN_FLAG_SEP_SPLUS_SPC:
sep_dn = "; ";
sep_dn_len = 2;
sep_mv = " + ";
sep_mv_len = 3;
indent = 0;
break;
default:
return -1;
}
if (flags & XN_FLAG_SPC_EQ) {
sep_eq = " = ";
sep_eq_len = 3;
} else {
sep_eq = "=";
sep_eq_len = 1;
}
fn_opt = flags & XN_FLAG_FN_MASK;
cnt = X509_NAME_entry_count(n);
for (i = 0; i < cnt; i++) {
if (flags & XN_FLAG_DN_REV)
ent = X509_NAME_get_entry(n, cnt - i - 1);
else
ent = X509_NAME_get_entry(n, i);
if (prev != -1) {
if (prev == X509_NAME_ENTRY_set(ent)) {
if (!io_ch(arg, sep_mv, sep_mv_len))
return -1;
outlen += sep_mv_len;
} else {
if (!io_ch(arg, sep_dn, sep_dn_len))
return -1;
outlen += sep_dn_len;
if (!do_indent(io_ch, arg, indent))
return -1;
outlen += indent;
}
}
prev = X509_NAME_ENTRY_set(ent);
fn = X509_NAME_ENTRY_get_object(ent);
val = X509_NAME_ENTRY_get_data(ent);
fn_nid = OBJ_obj2nid(fn);
if (fn_opt != XN_FLAG_FN_NONE) {
int objlen, fld_len;
if ((fn_opt == XN_FLAG_FN_OID) ||
(fn_nid == NID_undef)) {
OBJ_obj2txt(objtmp, sizeof objtmp, fn, 1);
fld_len = 0; /* XXX: what should this be? */
objbuf = objtmp;
} else {
if (fn_opt == XN_FLAG_FN_SN) {
fld_len = FN_WIDTH_SN;
objbuf = OBJ_nid2sn(fn_nid);
} else if (fn_opt == XN_FLAG_FN_LN) {
fld_len = FN_WIDTH_LN;
objbuf = OBJ_nid2ln(fn_nid);
} else {
fld_len = 0; /* XXX: what should this be? */
objbuf = "";
}
}
objlen = strlen(objbuf);
if (!io_ch(arg, objbuf, objlen))
return -1;
if ((objlen < fld_len) && (flags & XN_FLAG_FN_ALIGN)) {
if (!do_indent(io_ch, arg, fld_len - objlen))
return -1;
outlen += fld_len - objlen;
}
if (!io_ch(arg, sep_eq, sep_eq_len))
return -1;
outlen += objlen + sep_eq_len;
}
/* If the field name is unknown then fix up the DER dump
* flag. We might want to limit this further so it will
* DER dump on anything other than a few 'standard' fields.
*/
if ((fn_nid == NID_undef) &&
(flags & XN_FLAG_DUMP_UNKNOWN_FIELDS))
orflags = ASN1_STRFLGS_DUMP_ALL;
else
orflags = 0;
len = do_print_ex(io_ch, arg, flags | orflags, val);
if (len < 0)
return -1;
outlen += len;
}
return outlen;
}
/* Wrappers round the main functions */
int
X509_NAME_print_ex(BIO *out, const X509_NAME *nm, int indent,
unsigned long flags)
{
if (flags == XN_FLAG_COMPAT)
return X509_NAME_print(out, nm, indent);
return do_name_ex(send_bio_chars, out, nm, indent, flags);
}
int
X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm, int indent,
unsigned long flags)
{
if (flags == XN_FLAG_COMPAT) {
BIO *btmp;
int ret;
btmp = BIO_new_fp(fp, BIO_NOCLOSE);
if (!btmp)
return -1;
ret = X509_NAME_print(btmp, nm, indent);
BIO_free(btmp);
return ret;
}
return do_name_ex(send_fp_chars, fp, nm, indent, flags);
}
int
ASN1_STRING_print_ex(BIO *out, const ASN1_STRING *str, unsigned long flags)
{
return do_print_ex(send_bio_chars, out, flags, str);
}
LCRYPTO_ALIAS(ASN1_STRING_print_ex);
int
ASN1_STRING_print_ex_fp(FILE *fp, const ASN1_STRING *str, unsigned long flags)
{
return do_print_ex(send_fp_chars, fp, flags, str);
}
LCRYPTO_ALIAS(ASN1_STRING_print_ex_fp);

450
crypto/asn1/a_string.c Normal file
View File

@@ -0,0 +1,450 @@
/* $OpenBSD: a_string.c,v 1.17 2023/08/15 18:05:15 tb Exp $ */
/* 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 <limits.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/asn1.h>
#include <openssl/err.h>
#include "asn1_local.h"
ASN1_STRING *
ASN1_STRING_new(void)
{
return ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
}
LCRYPTO_ALIAS(ASN1_STRING_new);
ASN1_STRING *
ASN1_STRING_type_new(int type)
{
ASN1_STRING *astr;
if ((astr = calloc(1, sizeof(ASN1_STRING))) == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
return NULL;
}
astr->type = type;
return astr;
}
LCRYPTO_ALIAS(ASN1_STRING_type_new);
static void
ASN1_STRING_clear(ASN1_STRING *astr)
{
if (!(astr->flags & ASN1_STRING_FLAG_NDEF))
freezero(astr->data, astr->length);
astr->flags &= ~ASN1_STRING_FLAG_NDEF;
astr->data = NULL;
astr->length = 0;
}
void
ASN1_STRING_free(ASN1_STRING *astr)
{
if (astr == NULL)
return;
ASN1_STRING_clear(astr);
free(astr);
}
LCRYPTO_ALIAS(ASN1_STRING_free);
int
ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
{
int cmp;
if (a == NULL || b == NULL)
return -1;
if ((cmp = (a->length - b->length)) != 0)
return cmp;
if (a->length != 0) {
if ((cmp = memcmp(a->data, b->data, a->length)) != 0)
return cmp;
}
return a->type - b->type;
}
LCRYPTO_ALIAS(ASN1_STRING_cmp);
int
ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *src)
{
if (src == NULL)
return 0;
if (!ASN1_STRING_set(dst, src->data, src->length))
return 0;
dst->type = src->type;
dst->flags = src->flags & ~ASN1_STRING_FLAG_NDEF;
return 1;
}
LCRYPTO_ALIAS(ASN1_STRING_copy);
ASN1_STRING *
ASN1_STRING_dup(const ASN1_STRING *src)
{
ASN1_STRING *astr;
if (src == NULL)
return NULL;
if ((astr = ASN1_STRING_new()) == NULL)
return NULL;
if (!ASN1_STRING_copy(astr, src)) {
ASN1_STRING_free(astr);
return NULL;
}
return astr;
}
LCRYPTO_ALIAS(ASN1_STRING_dup);
int
ASN1_STRING_set(ASN1_STRING *astr, const void *_data, int len)
{
const char *data = _data;
if (len == -1) {
size_t slen;
if (data == NULL)
return 0;
if ((slen = strlen(data)) > INT_MAX)
return 0;
len = (int)slen;
}
ASN1_STRING_clear(astr);
if (len < 0 || len >= INT_MAX)
return 0;
if ((astr->data = calloc(1, len + 1)) == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
return 0;
}
astr->length = len;
if (data != NULL) {
memcpy(astr->data, data, len);
astr->data[len] = '\0';
}
return 1;
}
LCRYPTO_ALIAS(ASN1_STRING_set);
void
ASN1_STRING_set0(ASN1_STRING *astr, void *data, int len)
{
ASN1_STRING_clear(astr);
astr->data = data;
astr->length = len;
}
LCRYPTO_ALIAS(ASN1_STRING_set0);
int
ASN1_STRING_length(const ASN1_STRING *astr)
{
return astr->length;
}
LCRYPTO_ALIAS(ASN1_STRING_length);
void
ASN1_STRING_length_set(ASN1_STRING *astr, int len)
{
/* This is dangerous and unfixable. */
astr->length = len;
}
LCRYPTO_ALIAS(ASN1_STRING_length_set);
int
ASN1_STRING_type(const ASN1_STRING *astr)
{
return astr->type;
}
LCRYPTO_ALIAS(ASN1_STRING_type);
unsigned char *
ASN1_STRING_data(ASN1_STRING *astr)
{
return astr->data;
}
LCRYPTO_ALIAS(ASN1_STRING_data);
const unsigned char *
ASN1_STRING_get0_data(const ASN1_STRING *astr)
{
return astr->data;
}
LCRYPTO_ALIAS(ASN1_STRING_get0_data);
int
ASN1_STRING_print(BIO *bp, const ASN1_STRING *astr)
{
int i, n;
char buf[80];
const char *p;
if (astr == NULL)
return 0;
n = 0;
p = (const char *)astr->data;
for (i = 0; i < astr->length; i++) {
if ((p[i] > '~') || ((p[i] < ' ') &&
(p[i] != '\n') && (p[i] != '\r')))
buf[n] = '.';
else
buf[n] = p[i];
n++;
if (n >= 80) {
if (BIO_write(bp, buf, n) <= 0)
return 0;
n = 0;
}
}
if (n > 0) {
if (BIO_write(bp, buf, n) <= 0)
return 0;
}
return 1;
}
LCRYPTO_ALIAS(ASN1_STRING_print);
/*
* Utility function: convert any string type to UTF8, returns number of bytes
* in output string or a negative error code
*/
int
ASN1_STRING_to_UTF8(unsigned char **out, const ASN1_STRING *in)
{
ASN1_STRING *astr = NULL;
int mbflag;
int ret = -1;
/*
* XXX We can't fail on *out != NULL here since things like haproxy and
* grpc pass in a pointer to an uninitialized pointer on the stack.
*/
if (out == NULL)
goto err;
if (in == NULL)
goto err;
if ((mbflag = asn1_tag2charwidth(in->type)) == -1)
goto err;
mbflag |= MBSTRING_FLAG;
if ((ret = ASN1_mbstring_copy(&astr, in->data, in->length, mbflag,
B_ASN1_UTF8STRING)) < 0)
goto err;
*out = astr->data;
ret = astr->length;
astr->data = NULL;
astr->length = 0;
err:
ASN1_STRING_free(astr);
return ret;
}
LCRYPTO_ALIAS(ASN1_STRING_to_UTF8);
int
i2a_ASN1_STRING(BIO *bp, const ASN1_STRING *astr, int type)
{
int i, n = 0;
static const char h[] = "0123456789ABCDEF";
char buf[2];
if (astr == NULL)
return 0;
if (astr->length == 0) {
if (BIO_write(bp, "0", 1) != 1)
goto err;
n = 1;
} else {
for (i = 0; i < astr->length; i++) {
if ((i != 0) && (i % 35 == 0)) {
if (BIO_write(bp, "\\\n", 2) != 2)
goto err;
n += 2;
}
buf[0] = h[((unsigned char)astr->data[i] >> 4) & 0x0f];
buf[1] = h[((unsigned char)astr->data[i]) & 0x0f];
if (BIO_write(bp, buf, 2) != 2)
goto err;
n += 2;
}
}
return n;
err:
return -1;
}
LCRYPTO_ALIAS(i2a_ASN1_STRING);
int
a2i_ASN1_STRING(BIO *bp, ASN1_STRING *astr, char *buf, int size)
{
int ret = 0;
int i, j, k, m, n, again, bufsize;
unsigned char *s = NULL, *sp;
unsigned char *bufp;
int first = 1;
size_t num = 0, slen = 0;
bufsize = BIO_gets(bp, buf, size);
for (;;) {
if (bufsize < 1) {
if (first)
break;
else
goto err_sl;
}
first = 0;
i = bufsize;
if (buf[i-1] == '\n')
buf[--i] = '\0';
if (i == 0)
goto err_sl;
if (buf[i-1] == '\r')
buf[--i] = '\0';
if (i == 0)
goto err_sl;
if (buf[i - 1] == '\\') {
i--;
again = 1;
} else
again = 0;
buf[i] = '\0';
if (i < 2)
goto err_sl;
bufp = (unsigned char *)buf;
k = 0;
if (i % 2 != 0) {
ASN1error(ASN1_R_ODD_NUMBER_OF_CHARS);
goto err;
}
i /= 2;
if (num + i > slen) {
sp = realloc(s, num + i);
if (sp == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
goto err;
}
s = sp;
slen = num + i;
}
for (j = 0; j < i; j++, k += 2) {
for (n = 0; n < 2; n++) {
m = bufp[k + n];
if ((m >= '0') && (m <= '9'))
m -= '0';
else if ((m >= 'a') && (m <= 'f'))
m = m - 'a' + 10;
else if ((m >= 'A') && (m <= 'F'))
m = m - 'A' + 10;
else {
ASN1error(ASN1_R_NON_HEX_CHARACTERS);
goto err;
}
s[num + j] <<= 4;
s[num + j] |= m;
}
}
num += i;
if (again)
bufsize = BIO_gets(bp, buf, size);
else
break;
}
astr->length = num;
astr->data = s;
return 1;
err_sl:
ASN1error(ASN1_R_SHORT_LINE);
err:
free(s);
return ret;
}
LCRYPTO_ALIAS(a2i_ASN1_STRING);

463
crypto/asn1/a_strnid.c Normal file
View File

@@ -0,0 +1,463 @@
/* $OpenBSD: a_strnid.c,v 1.27 2023/07/05 21:23:36 beck Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 1999.
*/
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/objects.h>
static STACK_OF(ASN1_STRING_TABLE) *stable = NULL;
static ASN1_STRING_TABLE *stable_get(int nid);
static void st_free(ASN1_STRING_TABLE *tbl);
static int sk_table_cmp(const ASN1_STRING_TABLE * const *a,
const ASN1_STRING_TABLE * const *b);
/*
* This is the global mask for the mbstring functions: this is used to
* mask out certain types (such as BMPString and UTF8String) because
* certain software (e.g. Netscape) has problems with them.
*/
static unsigned long global_mask = B_ASN1_UTF8STRING;
void
ASN1_STRING_set_default_mask(unsigned long mask)
{
global_mask = mask;
}
LCRYPTO_ALIAS(ASN1_STRING_set_default_mask);
unsigned long
ASN1_STRING_get_default_mask(void)
{
return global_mask;
}
LCRYPTO_ALIAS(ASN1_STRING_get_default_mask);
/*
* This function sets the default to various "flavours" of configuration
* based on an ASCII string. Currently this is:
* MASK:XXXX : a numerical mask value.
* nobmp : Don't use BMPStrings (just Printable, T61).
* pkix : PKIX recommendation in RFC2459.
* utf8only : only use UTF8Strings (RFC2459 recommendation for 2004).
* default: the default value, Printable, T61, BMP.
*/
int
ASN1_STRING_set_default_mask_asc(const char *p)
{
unsigned long mask;
char *end;
int save_errno;
if (strncmp(p, "MASK:", 5) == 0) {
if (p[5] == '\0')
return 0;
save_errno = errno;
errno = 0;
mask = strtoul(p + 5, &end, 0);
if (errno == ERANGE && mask == ULONG_MAX)
return 0;
errno = save_errno;
if (*end != '\0')
return 0;
} else if (strcmp(p, "nombstr") == 0)
mask = ~((unsigned long)(B_ASN1_BMPSTRING|B_ASN1_UTF8STRING));
else if (strcmp(p, "pkix") == 0)
mask = ~((unsigned long)B_ASN1_T61STRING);
else if (strcmp(p, "utf8only") == 0)
mask = B_ASN1_UTF8STRING;
else if (strcmp(p, "default") == 0)
mask = 0xFFFFFFFFL;
else
return 0;
ASN1_STRING_set_default_mask(mask);
return 1;
}
LCRYPTO_ALIAS(ASN1_STRING_set_default_mask_asc);
/*
* The following function generates an ASN1_STRING based on limits in a table.
* Frequently the types and length of an ASN1_STRING are restricted by a
* corresponding OID. For example certificates and certificate requests.
*/
ASN1_STRING *
ASN1_STRING_set_by_NID(ASN1_STRING **out, const unsigned char *in, int inlen,
int inform, int nid)
{
ASN1_STRING_TABLE *tbl;
ASN1_STRING *str = NULL;
unsigned long mask;
int ret;
if (out == NULL)
out = &str;
tbl = ASN1_STRING_TABLE_get(nid);
if (tbl != NULL) {
mask = tbl->mask;
if ((tbl->flags & STABLE_NO_MASK) == 0)
mask &= global_mask;
ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask,
tbl->minsize, tbl->maxsize);
} else
ret = ASN1_mbstring_copy(out, in, inlen, inform,
DIRSTRING_TYPE & global_mask);
if (ret <= 0)
return NULL;
return *out;
}
LCRYPTO_ALIAS(ASN1_STRING_set_by_NID);
/*
* Now the tables and helper functions for the string table:
*/
/* size limits: this stuff is taken straight from RFC3280 */
#define ub_name 32768
#define ub_common_name 64
#define ub_locality_name 128
#define ub_state_name 128
#define ub_organization_name 64
#define ub_organization_unit_name 64
#define ub_title 64
#define ub_email_address 128
#define ub_serial_number 64
/* This table must be kept in NID order */
static const ASN1_STRING_TABLE tbl_standard[] = {
{
.nid = NID_commonName,
.minsize = 1,
.maxsize = ub_common_name,
.mask = DIRSTRING_TYPE,
.flags = 0,
},
{
.nid = NID_countryName,
.minsize = 2,
.maxsize = 2,
.mask = B_ASN1_PRINTABLESTRING,
.flags = STABLE_NO_MASK,
},
{
.nid = NID_localityName,
.minsize = 1,
.maxsize = ub_locality_name,
.mask = DIRSTRING_TYPE,
.flags = 0,
},
{
.nid = NID_stateOrProvinceName,
.minsize = 1,
.maxsize = ub_state_name,
.mask = DIRSTRING_TYPE,
.flags = 0,
},
{
.nid = NID_organizationName,
.minsize = 1,
.maxsize = ub_organization_name,
.mask = DIRSTRING_TYPE,
.flags = 0,
},
{
.nid = NID_organizationalUnitName,
.minsize = 1,
.maxsize = ub_organization_unit_name,
.mask = DIRSTRING_TYPE,
.flags = 0,
},
{
.nid = NID_pkcs9_emailAddress,
.minsize = 1,
.maxsize = ub_email_address,
.mask = B_ASN1_IA5STRING,
.flags = STABLE_NO_MASK,
},
{
.nid = NID_pkcs9_unstructuredName,
.minsize = 1,
.maxsize = -1,
.mask = PKCS9STRING_TYPE,
.flags = 0,
},
{
.nid = NID_pkcs9_challengePassword,
.minsize = 1,
.maxsize = -1,
.mask = PKCS9STRING_TYPE,
.flags = 0,
},
{
.nid = NID_pkcs9_unstructuredAddress,
.minsize = 1,
.maxsize = -1,
.mask = DIRSTRING_TYPE,
.flags = 0,
},
{
.nid = NID_givenName,
.minsize = 1,
.maxsize = ub_name,
.mask = DIRSTRING_TYPE,
.flags = 0,
},
{
.nid = NID_surname,
.minsize = 1,
.maxsize = ub_name,
.mask = DIRSTRING_TYPE,
.flags = 0,
},
{
.nid = NID_initials,
.minsize = 1,
.maxsize = ub_name,
.mask = DIRSTRING_TYPE,
.flags = 0,
},
{
.nid = NID_serialNumber,
.minsize = 1,
.maxsize = ub_serial_number,
.mask = B_ASN1_PRINTABLESTRING,
.flags = STABLE_NO_MASK,
},
{
.nid = NID_friendlyName,
.minsize = -1,
.maxsize = -1,
.mask = B_ASN1_BMPSTRING,
.flags = STABLE_NO_MASK,
},
{
.nid = NID_name,
.minsize = 1,
.maxsize = ub_name,
.mask = DIRSTRING_TYPE,
.flags = 0,
},
{
.nid = NID_dnQualifier,
.minsize = -1,
.maxsize = -1,
.mask = B_ASN1_PRINTABLESTRING,
.flags = STABLE_NO_MASK,
},
{
.nid = NID_domainComponent,
.minsize = 1,
.maxsize = -1,
.mask = B_ASN1_IA5STRING,
.flags = STABLE_NO_MASK,
},
{
.nid = NID_ms_csp_name,
.minsize = -1,
.maxsize = -1,
.mask = B_ASN1_BMPSTRING,
.flags = STABLE_NO_MASK,
},
};
static int
sk_table_cmp(const ASN1_STRING_TABLE * const *a,
const ASN1_STRING_TABLE * const *b)
{
return (*a)->nid - (*b)->nid;
}
static int table_cmp_BSEARCH_CMP_FN(const void *, const void *);
static int table_cmp(ASN1_STRING_TABLE const *, ASN1_STRING_TABLE const *);
static ASN1_STRING_TABLE *OBJ_bsearch_table(ASN1_STRING_TABLE *key, ASN1_STRING_TABLE const *base, int num);
static int
table_cmp(const ASN1_STRING_TABLE *a, const ASN1_STRING_TABLE *b)
{
return a->nid - b->nid;
}
static int
table_cmp_BSEARCH_CMP_FN(const void *a_, const void *b_)
{
ASN1_STRING_TABLE const *a = a_;
ASN1_STRING_TABLE const *b = b_;
return table_cmp(a, b);
}
static ASN1_STRING_TABLE *
OBJ_bsearch_table(ASN1_STRING_TABLE *key, ASN1_STRING_TABLE const *base, int num)
{
return (ASN1_STRING_TABLE *)OBJ_bsearch_(key, base, num, sizeof(ASN1_STRING_TABLE),
table_cmp_BSEARCH_CMP_FN);
}
ASN1_STRING_TABLE *
ASN1_STRING_TABLE_get(int nid)
{
int idx;
ASN1_STRING_TABLE fnd;
fnd.nid = nid;
if (stable != NULL) {
idx = sk_ASN1_STRING_TABLE_find(stable, &fnd);
if (idx >= 0)
return sk_ASN1_STRING_TABLE_value(stable, idx);
}
return OBJ_bsearch_table(&fnd, tbl_standard,
sizeof(tbl_standard) / sizeof(tbl_standard[0]));
}
LCRYPTO_ALIAS(ASN1_STRING_TABLE_get);
/*
* Return a string table pointer which can be modified: either directly
* from table or a copy of an internal value added to the table.
*/
static ASN1_STRING_TABLE *
stable_get(int nid)
{
ASN1_STRING_TABLE *tmp, *rv;
/* Always need a string table so allocate one if NULL */
if (stable == NULL) {
stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
if (stable == NULL)
return NULL;
}
tmp = ASN1_STRING_TABLE_get(nid);
if (tmp != NULL && (tmp->flags & STABLE_FLAGS_MALLOC) != 0)
return tmp;
if ((rv = calloc(1, sizeof(*rv))) == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
return NULL;
}
if (!sk_ASN1_STRING_TABLE_push(stable, rv)) {
free(rv);
return NULL;
}
if (tmp != NULL) {
rv->nid = tmp->nid;
rv->minsize = tmp->minsize;
rv->maxsize = tmp->maxsize;
rv->mask = tmp->mask;
rv->flags = tmp->flags | STABLE_FLAGS_MALLOC;
} else {
rv->nid = nid;
rv->minsize = -1;
rv->maxsize = -1;
rv->flags = STABLE_FLAGS_MALLOC;
}
return rv;
}
int
ASN1_STRING_TABLE_add(int nid, long minsize, long maxsize, unsigned long mask,
unsigned long flags)
{
ASN1_STRING_TABLE *tmp;
if ((tmp = stable_get(nid)) == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
return 0;
}
if (minsize >= 0)
tmp->minsize = minsize;
if (maxsize >= 0)
tmp->maxsize = maxsize;
if (mask != 0)
tmp->mask = mask;
if (flags != 0)
tmp->flags = flags | STABLE_FLAGS_MALLOC;
return 1;
}
LCRYPTO_ALIAS(ASN1_STRING_TABLE_add);
void
ASN1_STRING_TABLE_cleanup(void)
{
STACK_OF(ASN1_STRING_TABLE) *tmp;
tmp = stable;
if (tmp == NULL)
return;
stable = NULL;
sk_ASN1_STRING_TABLE_pop_free(tmp, st_free);
}
LCRYPTO_ALIAS(ASN1_STRING_TABLE_cleanup);
static void
st_free(ASN1_STRING_TABLE *tbl)
{
if (tbl->flags & STABLE_FLAGS_MALLOC)
free(tbl);
}

138
crypto/asn1/a_time.c Normal file
View File

@@ -0,0 +1,138 @@
/* $OpenBSD: a_time.c,v 1.37 2023/07/05 21:23:36 beck Exp $ */
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
/* This is an implementation of the ASN1 Time structure which is:
* Time ::= CHOICE {
* utcTime UTCTime,
* generalTime GeneralizedTime }
* written by Steve Henson.
*/
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <openssl/asn1t.h>
#include <openssl/err.h>
#include "asn1_local.h"
const ASN1_ITEM ASN1_TIME_it = {
.itype = ASN1_ITYPE_MSTRING,
.utype = B_ASN1_TIME,
.templates = NULL,
.tcount = 0,
.funcs = NULL,
.size = sizeof(ASN1_STRING),
.sname = "ASN1_TIME",
};
ASN1_TIME *
ASN1_TIME_new(void)
{
return (ASN1_TIME *)ASN1_item_new(&ASN1_TIME_it);
}
LCRYPTO_ALIAS(ASN1_TIME_new);
void
ASN1_TIME_free(ASN1_TIME *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_TIME_it);
}
LCRYPTO_ALIAS(ASN1_TIME_free);
int
ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm)
{
time_t now;
if (s != NULL)
return ASN1_time_parse(s->data, s->length, tm, 0) != -1;
time(&now);
memset(tm, 0, sizeof(*tm));
return asn1_time_time_t_to_tm(&now, tm);
}
LCRYPTO_ALIAS(ASN1_TIME_to_tm);
int
ASN1_TIME_diff(int *pday, int *psec, const ASN1_TIME *from, const ASN1_TIME *to)
{
struct tm tm_from, tm_to;
if (!ASN1_TIME_to_tm(from, &tm_from))
return 0;
if (!ASN1_TIME_to_tm(to, &tm_to))
return 0;
return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to);
}
LCRYPTO_ALIAS(ASN1_TIME_diff);
ASN1_TIME *
d2i_ASN1_TIME(ASN1_TIME **a, const unsigned char **in, long len)
{
return (ASN1_TIME *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&ASN1_TIME_it);
}
LCRYPTO_ALIAS(d2i_ASN1_TIME);
int
i2d_ASN1_TIME(ASN1_TIME *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_TIME_it);
}
LCRYPTO_ALIAS(i2d_ASN1_TIME);

274
crypto/asn1/a_time_posix.c Normal file
View File

@@ -0,0 +1,274 @@
/* $OpenBSD: a_time_posix.c,v 1.3 2023/01/01 16:58:23 miod Exp $ */
/*
* Copyright (c) 2022, Google Inc.
* Copyright (c) 2022, Bob Beck <beck@obtuse.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Time conversion to/from POSIX time_t and struct tm, with no support
* for time zones other than UTC
*/
#include <inttypes.h>
#include <limits.h>
#include <string.h>
#include <time.h>
#define SECS_PER_HOUR (int64_t)(60 * 60)
#define SECS_PER_DAY (int64_t)(24 * SECS_PER_HOUR)
/*
* Is a year/month/day combination valid, in the range from year 0000
* to 9999?
*/
static int
is_valid_date(int year, int month, int day)
{
int days_in_month;
if (day < 1 || month < 1 || year < 0 || year > 9999)
return 0;
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
days_in_month = 31;
break;
case 4:
case 6:
case 9:
case 11:
days_in_month = 30;
break;
case 2:
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
days_in_month = 29;
else
days_in_month = 28;
break;
default:
return 0;
}
return day <= days_in_month;
}
/*
* Is a time valid? Leap seconds of 60 are not considered valid, as
* the POSIX time in seconds does not include them.
*/
static int
is_valid_time(int hours, int minutes, int seconds)
{
return hours >= 0 && minutes >= 0 && seconds >= 0 && hours <= 23 &&
minutes <= 59 && seconds <= 59;
}
/* Is a int64 time representing a time within our expected range? */
static int
is_valid_epoch_time(int64_t time)
{
/* 0000-01-01 00:00:00 UTC to 9999-12-31 23:59:59 UTC */
return (int64_t)-62167219200LL <= time &&
time <= (int64_t)253402300799LL;
}
/*
* Inspired by algorithms presented in
* https://howardhinnant.github.io/date_algorithms.html
* (Public Domain)
*/
static int
posix_time_from_utc(int year, int month, int day, int hours, int minutes,
int seconds, int64_t *out_time)
{
int64_t era, year_of_era, day_of_year, day_of_era, posix_days;
if (!is_valid_date(year, month, day) ||
!is_valid_time(hours, minutes, seconds))
return 0;
if (month <= 2)
year--; /* Start years on Mar 1, so leap days end a year. */
/* At this point year will be in the range -1 and 9999.*/
era = (year >= 0 ? year : year - 399) / 400;
year_of_era = year - era * 400;
day_of_year = (153 * (month > 2 ? month - 3 : month + 9) + 2) /
5 + day - 1;
day_of_era = year_of_era * 365 + year_of_era / 4 - year_of_era /
100 + day_of_year;
posix_days = era * 146097 + day_of_era - 719468;
*out_time = posix_days * SECS_PER_DAY + hours * SECS_PER_HOUR +
minutes * 60 + seconds;
return 1;
}
/*
* Inspired by algorithms presented in
* https://howardhinnant.github.io/date_algorithms.html
* (Public Domain)
*/
static int
utc_from_posix_time(int64_t time, int *out_year, int *out_month, int *out_day,
int *out_hours, int *out_minutes, int *out_seconds)
{
int64_t days, leftover_seconds, era, day_of_era, year_of_era,
day_of_year, month_of_year;
if (!is_valid_epoch_time(time))
return 0;
days = time / SECS_PER_DAY;
leftover_seconds = time % SECS_PER_DAY;
if (leftover_seconds < 0) {
days--;
leftover_seconds += SECS_PER_DAY;
}
days += 719468; /* Shift to starting epoch of Mar 1 0000. */
/* At this point, days will be in the range -61 and 3652364. */
era = (days > 0 ? days : days - 146096) / 146097;
day_of_era = days - era * 146097;
year_of_era = (day_of_era - day_of_era / 1460 + day_of_era / 36524 -
day_of_era / 146096) /
365;
*out_year = year_of_era + era * 400; /* Year starts on Mar 1 */
day_of_year = day_of_era - (365 * year_of_era + year_of_era / 4 -
year_of_era / 100);
month_of_year = (5 * day_of_year + 2) / 153;
*out_month = (month_of_year < 10 ? month_of_year + 3 :
month_of_year - 9);
if (*out_month <= 2)
(*out_year)++; /* Adjust year back to Jan 1 start of year. */
*out_day = day_of_year - (153 * month_of_year + 2) / 5 + 1;
*out_hours = leftover_seconds / SECS_PER_HOUR;
leftover_seconds %= SECS_PER_HOUR;
*out_minutes = leftover_seconds / 60;
*out_seconds = leftover_seconds % 60;
return 1;
}
static int
asn1_time_tm_to_posix(const struct tm *tm, int64_t *out)
{
/* Ensure additions below do not overflow */
if (tm->tm_year > 9999)
return 0;
if (tm->tm_mon > 12)
return 0;
return posix_time_from_utc(tm->tm_year + 1900, tm->tm_mon + 1,
tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, out);
}
static int
asn1_time_posix_to_tm(int64_t time, struct tm *out_tm)
{
memset(out_tm, 0, sizeof(struct tm));
if (!utc_from_posix_time(time, &out_tm->tm_year, &out_tm->tm_mon,
&out_tm->tm_mday, &out_tm->tm_hour, &out_tm->tm_min,
&out_tm->tm_sec))
return 0;
out_tm->tm_year -= 1900;
out_tm->tm_mon -= 1;
return 1;
}
int
asn1_time_tm_to_time_t(const struct tm *tm, time_t *out)
{
int64_t posix_time;
if (!asn1_time_tm_to_posix(tm, &posix_time))
return 0;
#ifdef SMALL_TIME_T
/* For portable. */
if (sizeof(time_t) == sizeof(int32_t) &&
(posix_time > INT32_MAX || posix_time < INT32_MIN))
return 0;
#endif
*out = posix_time;
return 1;
}
int
asn1_time_time_t_to_tm(const time_t *time, struct tm *out_tm)
{
int64_t posix_time = *time;
return asn1_time_posix_to_tm(posix_time, out_tm);
}
int
OPENSSL_gmtime_adj(struct tm *tm, int off_day, long offset_sec)
{
int64_t posix_time;
/* Ensure additions below do not overflow */
if (tm->tm_year > 9999)
return 0;
if (tm->tm_mon > 12)
return 0;
if (!posix_time_from_utc(tm->tm_year + 1900, tm->tm_mon + 1,
tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, &posix_time))
return 0;
if (!utc_from_posix_time(posix_time + off_day * SECS_PER_DAY +
offset_sec, &tm->tm_year, &tm->tm_mon, &tm->tm_mday, &tm->tm_hour,
&tm->tm_min, &tm->tm_sec))
return 0;
tm->tm_year -= 1900;
tm->tm_mon -= 1;
return 1;
}
int
OPENSSL_gmtime_diff(int *out_days, int *out_secs, const struct tm *from,
const struct tm *to)
{
int64_t time_to, time_from, timediff, daydiff;
if (!posix_time_from_utc(to->tm_year + 1900, to->tm_mon + 1,
to->tm_mday, to->tm_hour, to->tm_min, to->tm_sec, &time_to))
return 0;
if (!posix_time_from_utc(from->tm_year + 1900, from->tm_mon + 1,
from->tm_mday, from->tm_hour, from->tm_min,
from->tm_sec, &time_from))
return 0;
timediff = time_to - time_from;
daydiff = timediff / SECS_PER_DAY;
timediff %= SECS_PER_DAY;
if (daydiff > INT_MAX || daydiff < INT_MIN)
return 0;
*out_secs = timediff;
*out_days = daydiff;
return 1;
}

626
crypto/asn1/a_time_tm.c Normal file
View File

@@ -0,0 +1,626 @@
/* $OpenBSD: a_time_tm.c,v 1.30 2023/08/30 10:13:12 job Exp $ */
/*
* Copyright (c) 2015 Bob Beck <beck@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <ctype.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <openssl/asn1t.h>
#include <openssl/err.h>
#include "bytestring.h"
#include "asn1_local.h"
#define RFC5280 0
#define GENTIME_LENGTH 15
#define UTCTIME_LENGTH 13
int
ASN1_time_tm_cmp(struct tm *tm1, struct tm *tm2)
{
if (tm1->tm_year < tm2->tm_year)
return (-1);
if (tm1->tm_year > tm2->tm_year)
return (1);
if (tm1->tm_mon < tm2->tm_mon)
return (-1);
if (tm1->tm_mon > tm2->tm_mon)
return (1);
if (tm1->tm_mday < tm2->tm_mday)
return (-1);
if (tm1->tm_mday > tm2->tm_mday)
return (1);
if (tm1->tm_hour < tm2->tm_hour)
return (-1);
if (tm1->tm_hour > tm2->tm_hour)
return (1);
if (tm1->tm_min < tm2->tm_min)
return (-1);
if (tm1->tm_min > tm2->tm_min)
return (1);
if (tm1->tm_sec < tm2->tm_sec)
return (-1);
if (tm1->tm_sec > tm2->tm_sec)
return (1);
return 0;
}
LCRYPTO_ALIAS(ASN1_time_tm_cmp);
int
ASN1_time_tm_clamp_notafter(struct tm *tm)
{
#ifdef SMALL_TIME_T
struct tm broken_os_epoch_tm;
time_t broken_os_epoch_time = INT_MAX;
if (!asn1_time_time_t_to_tm(&broken_os_epoch_time, &broken_os_epoch_tm))
return 0;
if (ASN1_time_tm_cmp(tm, &broken_os_epoch_tm) == 1)
memcpy(tm, &broken_os_epoch_tm, sizeof(*tm));
#endif
return 1;
}
/* Convert time to GeneralizedTime, X.690, 11.7. */
ASN1_TIME *
tm_to_gentime(struct tm *tm, ASN1_TIME *atime)
{
char *time_str = NULL;
int year;
year = tm->tm_year + 1900;
if (year < 0 || year > 9999) {
ASN1error(ASN1_R_ILLEGAL_TIME_VALUE);
goto err;
}
if (asprintf(&time_str, "%04u%02u%02u%02u%02u%02uZ", year,
tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min,
tm->tm_sec) == -1) {
time_str = NULL;
ASN1error(ERR_R_MALLOC_FAILURE);
goto err;
}
if (atime == NULL)
atime = ASN1_TIME_new();
if (atime == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
goto err;
}
free(atime->data);
atime->data = time_str;
atime->length = GENTIME_LENGTH;
atime->type = V_ASN1_GENERALIZEDTIME;
return (atime);
err:
free(time_str);
return (NULL);
}
/* Convert time to UTCTime, X.690, 11.8. */
ASN1_TIME *
tm_to_utctime(struct tm *tm, ASN1_TIME *atime)
{
char *time_str = NULL;
if (tm->tm_year >= 150 || tm->tm_year < 50) {
ASN1error(ASN1_R_ILLEGAL_TIME_VALUE);
goto err;
}
if (asprintf(&time_str, "%02u%02u%02u%02u%02u%02uZ",
tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec) == -1) {
time_str = NULL;
ASN1error(ERR_R_MALLOC_FAILURE);
goto err;
}
if (atime == NULL)
atime = ASN1_TIME_new();
if (atime == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
goto err;
}
free(atime->data);
atime->data = time_str;
atime->length = UTCTIME_LENGTH;
atime->type = V_ASN1_UTCTIME;
return (atime);
err:
free(time_str);
return (NULL);
}
ASN1_TIME *
tm_to_rfc5280_time(struct tm *tm, ASN1_TIME *atime)
{
int year;
year = tm->tm_year + 1900;
if (year < 1950 || year > 9999) {
ASN1error(ASN1_R_ILLEGAL_TIME_VALUE);
return (NULL);
}
if (year < 2050)
return (tm_to_utctime(tm, atime));
return (tm_to_gentime(tm, atime));
}
static int
cbs_get_two_digit_value(CBS *cbs, int *out)
{
uint8_t first_digit, second_digit;
if (!CBS_get_u8(cbs, &first_digit))
return 0;
if (!isdigit(first_digit))
return 0;
if (!CBS_get_u8(cbs, &second_digit))
return 0;
if (!isdigit(second_digit))
return 0;
*out = (first_digit - '0') * 10 + (second_digit - '0');
return 1;
}
static int
is_valid_day(int year, int month, int day)
{
if (day < 1)
return 0;
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
return day <= 31;
case 4:
case 6:
case 9:
case 11:
return day <= 30;
case 2:
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
return day <= 29;
else
return day <= 28;
default:
return 0;
}
}
/*
* asn1_time_parse_cbs returns one if |cbs| is a valid DER-encoded, ASN.1 Time
* body within the limitations imposed by RFC 5280, or zero otherwise. The time
* is expected to parse as a Generalized Time if is_gentime is true, and as a
* UTC Time otherwise. If |out_tm| is non-NULL, |*out_tm| will be zeroed, and
* then set to the corresponding time in UTC. This function does not compute
* |out_tm->tm_wday| or |out_tm->tm_yday|. |cbs| is not consumed.
*/
int
asn1_time_parse_cbs(const CBS *cbs, int is_gentime, struct tm *out_tm)
{
int year, month, day, hour, min, sec, val;
CBS copy;
uint8_t tz;
CBS_dup(cbs, &copy);
if (is_gentime) {
if (!cbs_get_two_digit_value(&copy, &val))
return 0;
year = val * 100;
if (!cbs_get_two_digit_value(&copy, &val))
return 0;
year += val;
} else {
year = 1900;
if (!cbs_get_two_digit_value(&copy, &val))
return 0;
year += val;
if (year < 1950)
year += 100;
if (year >= 2050)
return 0; /* A Generalized time must be used. */
}
if (!cbs_get_two_digit_value(&copy, &month))
return 0;
if (month < 1 || month > 12)
return 0; /* Reject invalid months. */
if (!cbs_get_two_digit_value(&copy, &day))
return 0;
if (!is_valid_day(year, month, day))
return 0; /* Reject invalid days. */
if (!cbs_get_two_digit_value(&copy, &hour))
return 0;
if (hour > 23)
return 0; /* Reject invalid hours. */
if (!cbs_get_two_digit_value(&copy, &min))
return 0;
if (min > 59)
return 0; /* Reject invalid minutes. */
if (!cbs_get_two_digit_value(&copy, &sec))
return 0;
if (sec > 59)
return 0; /* Reject invalid seconds. Leap seconds are invalid. */
if (!CBS_get_u8(&copy, &tz))
return 0;
if (tz != 'Z')
return 0; /* Reject anything but Z on the end. */
if (CBS_len(&copy) != 0)
return 0; /* Reject invalid lengths. */
if (out_tm != NULL) {
memset(out_tm, 0, sizeof(*out_tm));
/* Fill in the tm fields corresponding to what we validated. */
out_tm->tm_year = year - 1900;
out_tm->tm_mon = month - 1;
out_tm->tm_mday = day;
out_tm->tm_hour = hour;
out_tm->tm_min = min;
out_tm->tm_sec = sec;
}
return 1;
}
/*
* Parse an RFC 5280 format ASN.1 time string.
*
* mode must be:
* 0 if we expect to parse a time as specified in RFC 5280 for an X509 object.
* V_ASN1_UTCTIME if we wish to parse an RFC5280 format UTC time.
* V_ASN1_GENERALIZEDTIME if we wish to parse an RFC5280 format Generalized time.
*
* Returns:
* -1 if the string was invalid.
* V_ASN1_UTCTIME if the string validated as a UTC time string.
* V_ASN1_GENERALIZEDTIME if the string validated as a Generalized time string.
*
* Fills in *tm with the corresponding time if tm is non NULL.
*/
int
ASN1_time_parse(const char *bytes, size_t len, struct tm *tm, int mode)
{
struct tm tml, *tmp = tm ? tm : &tml;
int type = 0;
CBS cbs;
if (bytes == NULL)
return (-1);
CBS_init(&cbs, bytes, len);
if (CBS_len(&cbs) == UTCTIME_LENGTH)
type = V_ASN1_UTCTIME;
if (CBS_len(&cbs) == GENTIME_LENGTH)
type = V_ASN1_GENERALIZEDTIME;
if (asn1_time_parse_cbs(&cbs, type == V_ASN1_GENERALIZEDTIME, tmp)) {
if (mode != 0 && mode != type)
return -1;
return type;
}
return -1;
}
LCRYPTO_ALIAS(ASN1_time_parse);
/*
* ASN1_TIME generic functions.
*/
static int
ASN1_TIME_set_string_internal(ASN1_TIME *s, const char *str, int mode)
{
int type;
char *tmp;
if ((type = ASN1_time_parse(str, strlen(str), NULL, mode)) == -1)
return (0);
if (mode != 0 && mode != type)
return (0);
if (s == NULL)
return (1);
if ((tmp = strdup(str)) == NULL)
return (0);
free(s->data);
s->data = tmp;
s->length = strlen(tmp);
s->type = type;
return (1);
}
static ASN1_TIME *
ASN1_TIME_adj_internal(ASN1_TIME *s, time_t t, int offset_day, long offset_sec,
int mode)
{
struct tm tm;
if (!asn1_time_time_t_to_tm(&t, &tm))
return (NULL);
if (offset_day != 0 || offset_sec != 0) {
if (!OPENSSL_gmtime_adj(&tm, offset_day, offset_sec))
return (NULL);
}
switch (mode) {
case V_ASN1_UTCTIME:
return (tm_to_utctime(&tm, s));
case V_ASN1_GENERALIZEDTIME:
return (tm_to_gentime(&tm, s));
case RFC5280:
return (tm_to_rfc5280_time(&tm, s));
default:
return (NULL);
}
}
ASN1_TIME *
ASN1_TIME_set(ASN1_TIME *s, time_t t)
{
return (ASN1_TIME_adj(s, t, 0, 0));
}
LCRYPTO_ALIAS(ASN1_TIME_set);
ASN1_TIME *
ASN1_TIME_set_tm(ASN1_TIME *s, struct tm *tm)
{
time_t t;
if (!asn1_time_tm_to_time_t(tm, &t))
return NULL;
return (ASN1_TIME_adj(s, t, 0, 0));
}
LCRYPTO_ALIAS(ASN1_TIME_set_tm);
ASN1_TIME *
ASN1_TIME_adj(ASN1_TIME *s, time_t t, int offset_day, long offset_sec)
{
return (ASN1_TIME_adj_internal(s, t, offset_day, offset_sec, RFC5280));
}
LCRYPTO_ALIAS(ASN1_TIME_adj);
int
ASN1_TIME_check(const ASN1_TIME *t)
{
if (t->type != V_ASN1_GENERALIZEDTIME && t->type != V_ASN1_UTCTIME)
return (0);
return (t->type == ASN1_time_parse(t->data, t->length, NULL, t->type));
}
LCRYPTO_ALIAS(ASN1_TIME_check);
ASN1_GENERALIZEDTIME *
ASN1_TIME_to_generalizedtime(const ASN1_TIME *t, ASN1_GENERALIZEDTIME **out)
{
ASN1_GENERALIZEDTIME *agt = NULL;
struct tm tm;
if (t->type != V_ASN1_GENERALIZEDTIME && t->type != V_ASN1_UTCTIME)
return (NULL);
if (t->type != ASN1_time_parse(t->data, t->length, &tm, t->type))
return (NULL);
if (out != NULL)
agt = *out;
if ((agt = tm_to_gentime(&tm, agt)) == NULL)
return (NULL);
if (out != NULL)
*out = agt;
return (agt);
}
LCRYPTO_ALIAS(ASN1_TIME_to_generalizedtime);
int
ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
{
return (ASN1_TIME_set_string_internal(s, str, 0));
}
LCRYPTO_ALIAS(ASN1_TIME_set_string);
static int
ASN1_TIME_cmp_time_t_internal(const ASN1_TIME *s, time_t t2, int mode)
{
struct tm tm1, tm2;
/*
* This function has never handled failure conditions properly
* The OpenSSL version used to simply follow NULL pointers on failure.
* BoringSSL and OpenSSL now make it return -2 on failure.
*
* The danger is that users of this function will not differentiate the
* -2 failure case from s < t2. Callers must be careful. Sadly this is
* one of those pervasive things from OpenSSL we must continue with.
*/
if (ASN1_time_parse(s->data, s->length, &tm1, mode) == -1)
return -2;
if (!asn1_time_time_t_to_tm(&t2, &tm2))
return -2;
return ASN1_time_tm_cmp(&tm1, &tm2);
}
int
ASN1_TIME_compare(const ASN1_TIME *t1, const ASN1_TIME *t2)
{
struct tm tm1, tm2;
if (t1->type != V_ASN1_UTCTIME && t1->type != V_ASN1_GENERALIZEDTIME)
return -2;
if (t2->type != V_ASN1_UTCTIME && t2->type != V_ASN1_GENERALIZEDTIME)
return -2;
if (ASN1_time_parse(t1->data, t1->length, &tm1, t1->type) == -1)
return -2;
if (ASN1_time_parse(t1->data, t2->length, &tm2, t2->type) == -1)
return -2;
return ASN1_time_tm_cmp(&tm1, &tm2);
}
LCRYPTO_ALIAS(ASN1_TIME_compare);
int
ASN1_TIME_cmp_time_t(const ASN1_TIME *s, time_t t)
{
if (s->type == V_ASN1_UTCTIME)
return ASN1_TIME_cmp_time_t_internal(s, t, V_ASN1_UTCTIME);
if (s->type == V_ASN1_GENERALIZEDTIME)
return ASN1_TIME_cmp_time_t_internal(s, t,
V_ASN1_GENERALIZEDTIME);
return -2;
}
LCRYPTO_ALIAS(ASN1_TIME_cmp_time_t);
/*
* ASN1_UTCTIME wrappers
*/
int
ASN1_UTCTIME_check(const ASN1_UTCTIME *d)
{
if (d->type != V_ASN1_UTCTIME)
return (0);
return (d->type == ASN1_time_parse(d->data, d->length, NULL, d->type));
}
LCRYPTO_ALIAS(ASN1_UTCTIME_check);
int
ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str)
{
if (s != NULL && s->type != V_ASN1_UTCTIME)
return (0);
return (ASN1_TIME_set_string_internal(s, str, V_ASN1_UTCTIME));
}
LCRYPTO_ALIAS(ASN1_UTCTIME_set_string);
ASN1_UTCTIME *
ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t)
{
return (ASN1_UTCTIME_adj(s, t, 0, 0));
}
LCRYPTO_ALIAS(ASN1_UTCTIME_set);
ASN1_UTCTIME *
ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, int offset_day, long offset_sec)
{
return (ASN1_TIME_adj_internal(s, t, offset_day, offset_sec,
V_ASN1_UTCTIME));
}
LCRYPTO_ALIAS(ASN1_UTCTIME_adj);
int
ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t)
{
if (s->type == V_ASN1_UTCTIME)
return ASN1_TIME_cmp_time_t_internal(s, t, V_ASN1_UTCTIME);
return -2;
}
/*
* ASN1_GENERALIZEDTIME wrappers
*/
int
ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *d)
{
if (d->type != V_ASN1_GENERALIZEDTIME)
return (0);
return (d->type == ASN1_time_parse(d->data, d->length, NULL, d->type));
}
LCRYPTO_ALIAS(ASN1_GENERALIZEDTIME_check);
int
ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str)
{
if (s != NULL && s->type != V_ASN1_GENERALIZEDTIME)
return (0);
return (ASN1_TIME_set_string_internal(s, str, V_ASN1_GENERALIZEDTIME));
}
LCRYPTO_ALIAS(ASN1_GENERALIZEDTIME_set_string);
ASN1_GENERALIZEDTIME *
ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s, time_t t)
{
return (ASN1_GENERALIZEDTIME_adj(s, t, 0, 0));
}
LCRYPTO_ALIAS(ASN1_GENERALIZEDTIME_set);
ASN1_GENERALIZEDTIME *
ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, time_t t, int offset_day,
long offset_sec)
{
return (ASN1_TIME_adj_internal(s, t, offset_day, offset_sec,
V_ASN1_GENERALIZEDTIME));
}
LCRYPTO_ALIAS(ASN1_GENERALIZEDTIME_adj);
int
ASN1_TIME_normalize(ASN1_TIME *t)
{
struct tm tm;
if (t == NULL)
return 0;
if (!ASN1_TIME_to_tm(t, &tm))
return 0;
return tm_to_rfc5280_time(&tm, t) != NULL;
}
LCRYPTO_ALIAS(ASN1_TIME_normalize);
int
ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str)
{
return ASN1_TIME_set_string_internal(s, str, RFC5280);
}
LCRYPTO_ALIAS(ASN1_TIME_set_string_X509);

360
crypto/asn1/a_type.c Normal file
View File

@@ -0,0 +1,360 @@
/* $OpenBSD: a_type.c,v 1.27 2023/07/28 10:00:10 tb Exp $ */
/* 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 <string.h>
#include <openssl/asn1t.h>
#include <openssl/err.h>
#include <openssl/objects.h>
#include "asn1_local.h"
typedef struct {
ASN1_INTEGER *num;
ASN1_OCTET_STRING *value;
} ASN1_int_octetstring;
static const ASN1_TEMPLATE ASN1_INT_OCTETSTRING_seq_tt[] = {
{
.offset = offsetof(ASN1_int_octetstring, num),
.field_name = "num",
.item = &ASN1_INTEGER_it,
},
{
.offset = offsetof(ASN1_int_octetstring, value),
.field_name = "value",
.item = &ASN1_OCTET_STRING_it,
},
};
const ASN1_ITEM ASN1_INT_OCTETSTRING_it = {
.itype = ASN1_ITYPE_SEQUENCE,
.utype = V_ASN1_SEQUENCE,
.templates = ASN1_INT_OCTETSTRING_seq_tt,
.tcount = sizeof(ASN1_INT_OCTETSTRING_seq_tt) / sizeof(ASN1_TEMPLATE),
.size = sizeof(ASN1_int_octetstring),
.sname = "ASN1_INT_OCTETSTRING",
};
ASN1_TYPE *
ASN1_TYPE_new(void)
{
return (ASN1_TYPE *)ASN1_item_new(&ASN1_ANY_it);
}
LCRYPTO_ALIAS(ASN1_TYPE_new);
void
ASN1_TYPE_free(ASN1_TYPE *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_ANY_it);
}
LCRYPTO_ALIAS(ASN1_TYPE_free);
int
ASN1_TYPE_get(const ASN1_TYPE *a)
{
/* Special non-pointer types. */
if (a->type == V_ASN1_BOOLEAN || a->type == V_ASN1_NULL)
return a->type;
if (a->value.ptr != NULL)
return a->type;
return 0;
}
LCRYPTO_ALIAS(ASN1_TYPE_get);
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;
}
LCRYPTO_ALIAS(ASN1_TYPE_set);
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;
}
LCRYPTO_ALIAS(ASN1_TYPE_set1);
/* 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;
}
LCRYPTO_ALIAS(ASN1_TYPE_cmp);
int
ASN1_TYPE_set_octetstring(ASN1_TYPE *a, const unsigned char *data, int len)
{
ASN1_STRING *os;
if ((os = ASN1_OCTET_STRING_new()) == NULL)
return (0);
if (!ASN1_STRING_set(os, data, len)) {
ASN1_OCTET_STRING_free(os);
return (0);
}
ASN1_TYPE_set(a, V_ASN1_OCTET_STRING, os);
return (1);
}
LCRYPTO_ALIAS(ASN1_TYPE_set_octetstring);
int
ASN1_TYPE_get_octetstring(const ASN1_TYPE *a, unsigned char *data, int max_len)
{
int ret, num;
unsigned char *p;
if ((a->type != V_ASN1_OCTET_STRING) ||
(a->value.octet_string == NULL)) {
ASN1error(ASN1_R_DATA_IS_WRONG);
return (-1);
}
p = ASN1_STRING_data(a->value.octet_string);
ret = ASN1_STRING_length(a->value.octet_string);
if (ret < max_len)
num = ret;
else
num = max_len;
memcpy(data, p, num);
return (ret);
}
LCRYPTO_ALIAS(ASN1_TYPE_get_octetstring);
int
ASN1_TYPE_set_int_octetstring(ASN1_TYPE *at, long num, const unsigned char *data,
int len)
{
ASN1_int_octetstring *ios;
ASN1_STRING *sp = NULL;
int ret = 0;
if ((ios = (ASN1_int_octetstring *)ASN1_item_new(
&ASN1_INT_OCTETSTRING_it)) == NULL)
goto err;
if (!ASN1_INTEGER_set(ios->num, num))
goto err;
if (!ASN1_OCTET_STRING_set(ios->value, data, len))
goto err;
if ((sp = ASN1_item_pack(ios, &ASN1_INT_OCTETSTRING_it, NULL)) == NULL)
goto err;
ASN1_TYPE_set(at, V_ASN1_SEQUENCE, sp);
sp = NULL;
ret = 1;
err:
ASN1_item_free((ASN1_VALUE *)ios, &ASN1_INT_OCTETSTRING_it);
ASN1_STRING_free(sp);
return ret;
}
LCRYPTO_ALIAS(ASN1_TYPE_set_int_octetstring);
int
ASN1_TYPE_get_int_octetstring(const ASN1_TYPE *at, long *num, unsigned char *data,
int max_len)
{
ASN1_STRING *sp = at->value.sequence;
ASN1_int_octetstring *ios = NULL;
int ret = -1;
int len;
if (at->type != V_ASN1_SEQUENCE || sp == NULL)
goto err;
if ((ios = ASN1_item_unpack(sp, &ASN1_INT_OCTETSTRING_it)) == NULL)
goto err;
if (num != NULL)
*num = ASN1_INTEGER_get(ios->num);
if (data != NULL) {
len = ASN1_STRING_length(ios->value);
if (len > max_len)
len = max_len;
memcpy(data, ASN1_STRING_data(ios->value), len);
}
ret = ASN1_STRING_length(ios->value);
err:
ASN1_item_free((ASN1_VALUE *)ios, &ASN1_INT_OCTETSTRING_it);
if (ret == -1)
ASN1error(ASN1_R_DATA_IS_WRONG);
return ret;
}
LCRYPTO_ALIAS(ASN1_TYPE_get_int_octetstring);
ASN1_TYPE *
ASN1_TYPE_pack_sequence(const ASN1_ITEM *it, void *s, ASN1_TYPE **t)
{
ASN1_OCTET_STRING *oct;
ASN1_TYPE *rt;
if ((oct = ASN1_item_pack(s, it, NULL)) == NULL)
return NULL;
if (t != NULL && *t != NULL) {
rt = *t;
} else {
if ((rt = ASN1_TYPE_new()) == NULL) {
ASN1_OCTET_STRING_free(oct);
return NULL;
}
if (t != NULL)
*t = rt;
}
ASN1_TYPE_set(rt, V_ASN1_SEQUENCE, oct);
return rt;
}
void *
ASN1_TYPE_unpack_sequence(const ASN1_ITEM *it, const ASN1_TYPE *t)
{
if (t == NULL || t->type != V_ASN1_SEQUENCE || t->value.sequence == NULL)
return NULL;
return ASN1_item_unpack(t->value.sequence, it);
}
int
i2d_ASN1_TYPE(ASN1_TYPE *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_ANY_it);
}
LCRYPTO_ALIAS(i2d_ASN1_TYPE);
ASN1_TYPE *
d2i_ASN1_TYPE(ASN1_TYPE **a, const unsigned char **in, long len)
{
return (ASN1_TYPE *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&ASN1_ANY_it);
}
LCRYPTO_ALIAS(d2i_ASN1_TYPE);

199
crypto/asn1/a_utf8.c Normal file
View File

@@ -0,0 +1,199 @@
/* $OpenBSD: a_utf8.c,v 1.9 2022/11/26 16:08:50 tb Exp $ */
/* 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 <openssl/asn1.h>
#include "asn1_local.h"
/* UTF8 utilities */
/*
* This parses a UTF8 string one character at a time. It is passed a pointer
* to the string and the length of the string. It sets 'value' to the value of
* the current character. It returns the number of characters read or a
* negative error code:
* -1 = string too short
* -2 = illegal character
* -3 = subsequent characters not of the form 10xxxxxx
* -4 = character encoded incorrectly (not minimal length).
*/
int
UTF8_getc(const unsigned char *str, int len, unsigned long *val)
{
const unsigned char *p;
unsigned long value;
int ret;
if (len <= 0)
return 0;
p = str;
/* Check syntax and work out the encoded value (if correct) */
if ((*p & 0x80) == 0) {
value = *p++ & 0x7f;
ret = 1;
} else if ((*p & 0xe0) == 0xc0) {
if (*p < 0xc2)
return -2;
if (len < 2)
return -1;
if ((p[1] & 0xc0) != 0x80)
return -3;
value = (*p++ & 0x1f) << 6;
value |= *p++ & 0x3f;
if (value < 0x80)
return -4;
ret = 2;
} else if ((*p & 0xf0) == 0xe0) {
if (len < 3)
return -1;
if (((p[1] & 0xc0) != 0x80) ||
((p[2] & 0xc0) != 0x80))
return -3;
value = (*p++ & 0xf) << 12;
value |= (*p++ & 0x3f) << 6;
value |= *p++ & 0x3f;
if (value < 0x800)
return -4;
/* surrogate pair code points are not valid */
if (value >= 0xd800 && value < 0xe000)
return -2;
ret = 3;
} else if ((*p & 0xf8) == 0xf0 && (*p < 0xf5)) {
if (len < 4)
return -1;
if (((p[1] & 0xc0) != 0x80) ||
((p[2] & 0xc0) != 0x80) ||
((p[3] & 0xc0) != 0x80))
return -3;
value = ((unsigned long)(*p++ & 0x7)) << 18;
value |= (*p++ & 0x3f) << 12;
value |= (*p++ & 0x3f) << 6;
value |= *p++ & 0x3f;
if (value < 0x10000)
return -4;
if (value > UNICODE_MAX)
return -2;
ret = 4;
} else
return -2;
*val = value;
return ret;
}
/* This takes a Unicode code point 'value' and writes its UTF-8 encoded form
* in 'str' where 'str' is a buffer of at least length 'len'. If 'str'
* is NULL, then nothing is written and just the return code is determined.
* Returns less than zero on error:
* -1 if 'str' is not NULL and 'len' is too small
* -2 if 'value' is an invalid character (surrogate or out-of-range)
*
* Otherwise, returns the number of bytes in 'value's encoded form
* (i.e., the number of bytes written to 'str' when it's not NULL).
*
* It will need at most 4 characters.
*/
int
UTF8_putc(unsigned char *str, int len, unsigned long value)
{
if (value < 0x80) {
if (str != NULL) {
if (len < 1)
return -1;
str[0] = (unsigned char)value;
}
return 1;
}
if (value < 0x800) {
if (str != NULL) {
if (len < 2)
return -1;
str[0] = (unsigned char)(((value >> 6) & 0x1f) | 0xc0);
str[1] = (unsigned char)((value & 0x3f) | 0x80);
}
return 2;
}
if (value < 0x10000) {
if (UNICODE_IS_SURROGATE(value))
return -2;
if (str != NULL) {
if (len < 3)
return -1;
str[0] = (unsigned char)(((value >> 12) & 0xf) | 0xe0);
str[1] = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
str[2] = (unsigned char)((value & 0x3f) | 0x80);
}
return 3;
}
if (value <= UNICODE_MAX) {
if (str != NULL) {
if (len < 4)
return -1;
str[0] = (unsigned char)(((value >> 18) & 0x7) | 0xf0);
str[1] = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
str[2] = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
str[3] = (unsigned char)((value & 0x3f) | 0x80);
}
return 4;
}
return -2;
}

428
crypto/asn1/ameth_lib.c Normal file
View File

@@ -0,0 +1,428 @@
/* $OpenBSD: ameth_lib.c,v 1.32 2023/07/07 19:37:52 beck Exp $ */
/* 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 <string.h>
#include <openssl/opensslconf.h>
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#ifndef OPENSSL_NO_ENGINE
#include <openssl/engine.h>
#endif
#include "asn1_local.h"
#include "evp_local.h"
extern const EVP_PKEY_ASN1_METHOD cmac_asn1_meth;
extern const EVP_PKEY_ASN1_METHOD dh_asn1_meth;
extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[];
extern const EVP_PKEY_ASN1_METHOD eckey_asn1_meth;
extern const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth;
extern const EVP_PKEY_ASN1_METHOD gostimit_asn1_meth;
extern const EVP_PKEY_ASN1_METHOD gostr01_asn1_meths[];
extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth;
extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[];
extern const EVP_PKEY_ASN1_METHOD rsa_pss_asn1_meth;
extern const EVP_PKEY_ASN1_METHOD x25519_asn1_meth;
static const EVP_PKEY_ASN1_METHOD *asn1_methods[] = {
&cmac_asn1_meth,
&dh_asn1_meth,
&dsa_asn1_meths[0],
&dsa_asn1_meths[1],
&dsa_asn1_meths[2],
&dsa_asn1_meths[3],
&dsa_asn1_meths[4],
&eckey_asn1_meth,
&ed25519_asn1_meth,
&gostimit_asn1_meth,
&gostr01_asn1_meths[0],
&gostr01_asn1_meths[1],
&gostr01_asn1_meths[2],
&hmac_asn1_meth,
&rsa_asn1_meths[0],
&rsa_asn1_meths[1],
&rsa_pss_asn1_meth,
&x25519_asn1_meth,
};
static const size_t asn1_methods_count =
sizeof(asn1_methods) / sizeof(asn1_methods[0]);
DECLARE_STACK_OF(EVP_PKEY_ASN1_METHOD)
static STACK_OF(EVP_PKEY_ASN1_METHOD) *asn1_app_methods = NULL;
int
EVP_PKEY_asn1_get_count(void)
{
int num = asn1_methods_count;
if (asn1_app_methods != NULL)
num += sk_EVP_PKEY_ASN1_METHOD_num(asn1_app_methods);
return num;
}
const EVP_PKEY_ASN1_METHOD *
EVP_PKEY_asn1_get0(int idx)
{
int num = asn1_methods_count;
if (idx < 0)
return NULL;
if (idx < num)
return asn1_methods[idx];
idx -= num;
return sk_EVP_PKEY_ASN1_METHOD_value(asn1_app_methods, idx);
}
static const EVP_PKEY_ASN1_METHOD *
pkey_asn1_find(int pkey_id)
{
const EVP_PKEY_ASN1_METHOD *ameth;
int i;
for (i = EVP_PKEY_asn1_get_count() - 1; i >= 0; i--) {
ameth = EVP_PKEY_asn1_get0(i);
if (ameth->pkey_id == pkey_id)
return ameth;
}
return NULL;
}
/*
* 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 *mp;
for (;;) {
if ((mp = pkey_asn1_find(type)) == NULL)
break;
if ((mp->pkey_flags & ASN1_PKEY_ALIAS) == 0)
break;
type = mp->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 mp;
}
const EVP_PKEY_ASN1_METHOD *
EVP_PKEY_asn1_find_str(ENGINE **pe, const char *str, int len)
{
const EVP_PKEY_ASN1_METHOD *ameth;
int i;
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 = EVP_PKEY_asn1_get_count() - 1; i >= 0; 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 (asn1_app_methods == NULL) {
asn1_app_methods = sk_EVP_PKEY_ASN1_METHOD_new(NULL);
if (asn1_app_methods == NULL)
return 0;
}
if (!sk_EVP_PKEY_ASN1_METHOD_push(asn1_app_methods, ameth))
return 0;
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 == NULL)
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(const 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;
if ((ameth = calloc(1, sizeof(EVP_PKEY_ASN1_METHOD))) == NULL)
return NULL;
ameth->pkey_id = id;
ameth->pkey_base_id = id;
ameth->pkey_flags = flags | ASN1_PKEY_DYNAMIC;
if (info != NULL) {
if ((ameth->info = strdup(info)) == NULL)
goto err;
}
if (pem_str != NULL) {
if ((ameth->pem_str = strdup(pem_str)) == NULL)
goto err;
}
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)
{
EVP_PKEY_ASN1_METHOD preserve;
preserve.pkey_id = dst->pkey_id;
preserve.pkey_base_id = dst->pkey_base_id;
preserve.pkey_flags = dst->pkey_flags;
preserve.pem_str = dst->pem_str;
preserve.info = dst->info;
*dst = *src;
dst->pkey_id = preserve.pkey_id;
dst->pkey_base_id = preserve.pkey_base_id;
dst->pkey_flags = preserve.pkey_flags;
dst->pem_str = preserve.pem_str;
dst->info = preserve.info;
}
void
EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth)
{
if (ameth && (ameth->pkey_flags & ASN1_PKEY_DYNAMIC)) {
free(ameth->pem_str);
free(ameth->info);
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, const 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_security_bits(EVP_PKEY_ASN1_METHOD *ameth,
int (*pkey_security_bits)(const EVP_PKEY *pkey))
{
ameth->pkey_security_bits = pkey_security_bits;
}
void
EVP_PKEY_asn1_set_check(EVP_PKEY_ASN1_METHOD *ameth,
int (*pkey_check)(const EVP_PKEY *pk))
{
ameth->pkey_check = pkey_check;
}
void
EVP_PKEY_asn1_set_public_check(EVP_PKEY_ASN1_METHOD *ameth,
int (*pkey_public_check)(const EVP_PKEY *pk))
{
ameth->pkey_public_check = pkey_public_check;
}
void
EVP_PKEY_asn1_set_param_check(EVP_PKEY_ASN1_METHOD *ameth,
int (*pkey_param_check)(const EVP_PKEY *pk))
{
ameth->pkey_param_check = pkey_param_check;
}

214
crypto/asn1/asn1_err.c Normal file
View File

@@ -0,0 +1,214 @@
/* $OpenBSD: asn1_err.c,v 1.26 2023/07/05 21:23:36 beck Exp $ */
/* ====================================================================
* Copyright (c) 1999-2011 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
* openssl-core@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/opensslconf.h>
#include <openssl/err.h>
#include <openssl/asn1.h>
#ifndef OPENSSL_NO_ERR
#define ERR_FUNC(func) ERR_PACK(ERR_LIB_ASN1,func,0)
#define ERR_REASON(reason) ERR_PACK(ERR_LIB_ASN1,0,reason)
static ERR_STRING_DATA ASN1_str_functs[] = {
{ERR_FUNC(0xfff), "CRYPTO_internal"},
{0, NULL}
};
static ERR_STRING_DATA ASN1_str_reasons[] = {
{ERR_REASON(ASN1_R_ADDING_OBJECT) , "adding object"},
{ERR_REASON(ASN1_R_ASN1_PARSE_ERROR) , "asn1 parse error"},
{ERR_REASON(ASN1_R_ASN1_SIG_PARSE_ERROR) , "asn1 sig parse error"},
{ERR_REASON(ASN1_R_AUX_ERROR) , "aux error"},
{ERR_REASON(ASN1_R_BAD_CLASS) , "bad class"},
{ERR_REASON(ASN1_R_BAD_OBJECT_HEADER) , "bad object header"},
{ERR_REASON(ASN1_R_BAD_PASSWORD_READ) , "bad password read"},
{ERR_REASON(ASN1_R_BAD_TAG) , "bad tag"},
{ERR_REASON(ASN1_R_BAD_TEMPLATE) , "bad template"},
{ERR_REASON(ASN1_R_BMPSTRING_IS_WRONG_LENGTH), "bmpstring is wrong length"},
{ERR_REASON(ASN1_R_BN_LIB) , "bn lib"},
{ERR_REASON(ASN1_R_BOOLEAN_IS_WRONG_LENGTH), "boolean is wrong length"},
{ERR_REASON(ASN1_R_BUFFER_TOO_SMALL) , "buffer too small"},
{ERR_REASON(ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER), "cipher has no object identifier"},
{ERR_REASON(ASN1_R_CONTEXT_NOT_INITIALISED), "context not initialised"},
{ERR_REASON(ASN1_R_DATA_IS_WRONG) , "data is wrong"},
{ERR_REASON(ASN1_R_DECODE_ERROR) , "decode error"},
{ERR_REASON(ASN1_R_DECODING_ERROR) , "decoding error"},
{ERR_REASON(ASN1_R_DEPTH_EXCEEDED) , "depth exceeded"},
{ERR_REASON(ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED), "digest and key type not supported"},
{ERR_REASON(ASN1_R_ENCODE_ERROR) , "encode error"},
{ERR_REASON(ASN1_R_ERROR_GETTING_TIME) , "error getting time"},
{ERR_REASON(ASN1_R_ERROR_LOADING_SECTION), "error loading section"},
{ERR_REASON(ASN1_R_ERROR_PARSING_SET_ELEMENT), "error parsing set element"},
{ERR_REASON(ASN1_R_ERROR_SETTING_CIPHER_PARAMS), "error setting cipher params"},
{ERR_REASON(ASN1_R_EXPECTING_AN_INTEGER) , "expecting an integer"},
{ERR_REASON(ASN1_R_EXPECTING_AN_OBJECT) , "expecting an object"},
{ERR_REASON(ASN1_R_EXPECTING_A_BOOLEAN) , "expecting a boolean"},
{ERR_REASON(ASN1_R_EXPECTING_A_TIME) , "expecting a time"},
{ERR_REASON(ASN1_R_EXPLICIT_LENGTH_MISMATCH), "explicit length mismatch"},
{ERR_REASON(ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED), "explicit tag not constructed"},
{ERR_REASON(ASN1_R_FIELD_MISSING) , "field missing"},
{ERR_REASON(ASN1_R_FIRST_NUM_TOO_LARGE) , "first num too large"},
{ERR_REASON(ASN1_R_HEADER_TOO_LONG) , "header too long"},
{ERR_REASON(ASN1_R_ILLEGAL_BITSTRING_FORMAT), "illegal bitstring format"},
{ERR_REASON(ASN1_R_ILLEGAL_BOOLEAN) , "illegal boolean"},
{ERR_REASON(ASN1_R_ILLEGAL_CHARACTERS) , "illegal characters"},
{ERR_REASON(ASN1_R_ILLEGAL_FORMAT) , "illegal format"},
{ERR_REASON(ASN1_R_ILLEGAL_HEX) , "illegal hex"},
{ERR_REASON(ASN1_R_ILLEGAL_IMPLICIT_TAG) , "illegal implicit tag"},
{ERR_REASON(ASN1_R_ILLEGAL_INTEGER) , "illegal integer"},
{ERR_REASON(ASN1_R_ILLEGAL_NEGATIVE_VALUE), "illegal negative value"},
{ERR_REASON(ASN1_R_ILLEGAL_NESTED_TAGGING), "illegal nested tagging"},
{ERR_REASON(ASN1_R_ILLEGAL_NULL) , "illegal null"},
{ERR_REASON(ASN1_R_ILLEGAL_NULL_VALUE) , "illegal null value"},
{ERR_REASON(ASN1_R_ILLEGAL_OBJECT) , "illegal object"},
{ERR_REASON(ASN1_R_ILLEGAL_OPTIONAL_ANY) , "illegal optional any"},
{ERR_REASON(ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE), "illegal options on item template"},
{ERR_REASON(ASN1_R_ILLEGAL_TAGGED_ANY) , "illegal tagged any"},
{ERR_REASON(ASN1_R_ILLEGAL_TIME_VALUE) , "illegal time value"},
{ERR_REASON(ASN1_R_INTEGER_NOT_ASCII_FORMAT), "integer not ascii format"},
{ERR_REASON(ASN1_R_INTEGER_TOO_LARGE_FOR_LONG), "integer too large for long"},
{ERR_REASON(ASN1_R_INVALID_BIT_STRING_BITS_LEFT), "invalid bit string bits left"},
{ERR_REASON(ASN1_R_INVALID_BMPSTRING_LENGTH), "invalid bmpstring length"},
{ERR_REASON(ASN1_R_INVALID_DIGIT) , "invalid digit"},
{ERR_REASON(ASN1_R_INVALID_MIME_TYPE) , "invalid mime type"},
{ERR_REASON(ASN1_R_INVALID_MODIFIER) , "invalid modifier"},
{ERR_REASON(ASN1_R_INVALID_NUMBER) , "invalid number"},
{ERR_REASON(ASN1_R_INVALID_OBJECT_ENCODING), "invalid object encoding"},
{ERR_REASON(ASN1_R_INVALID_SEPARATOR) , "invalid separator"},
{ERR_REASON(ASN1_R_INVALID_TIME_FORMAT) , "invalid time format"},
{ERR_REASON(ASN1_R_INVALID_UNIVERSALSTRING_LENGTH), "invalid universalstring length"},
{ERR_REASON(ASN1_R_INVALID_UTF8STRING) , "invalid utf8string"},
{ERR_REASON(ASN1_R_IV_TOO_LARGE) , "iv too large"},
{ERR_REASON(ASN1_R_LENGTH_ERROR) , "length error"},
{ERR_REASON(ASN1_R_LIST_ERROR) , "list error"},
{ERR_REASON(ASN1_R_MIME_NO_CONTENT_TYPE) , "mime no content type"},
{ERR_REASON(ASN1_R_MIME_PARSE_ERROR) , "mime parse error"},
{ERR_REASON(ASN1_R_MIME_SIG_PARSE_ERROR) , "mime sig parse error"},
{ERR_REASON(ASN1_R_MISSING_EOC) , "missing eoc"},
{ERR_REASON(ASN1_R_MISSING_SECOND_NUMBER), "missing second number"},
{ERR_REASON(ASN1_R_MISSING_VALUE) , "missing value"},
{ERR_REASON(ASN1_R_MSTRING_NOT_UNIVERSAL), "mstring not universal"},
{ERR_REASON(ASN1_R_MSTRING_WRONG_TAG) , "mstring wrong tag"},
{ERR_REASON(ASN1_R_NESTED_ASN1_STRING) , "nested asn1 string"},
{ERR_REASON(ASN1_R_NESTED_TOO_DEEP) , "nested too deep"},
{ERR_REASON(ASN1_R_NON_HEX_CHARACTERS) , "non hex characters"},
{ERR_REASON(ASN1_R_NOT_ASCII_FORMAT) , "not ascii format"},
{ERR_REASON(ASN1_R_NOT_ENOUGH_DATA) , "not enough data"},
{ERR_REASON(ASN1_R_NO_CONTENT_TYPE) , "no content type"},
{ERR_REASON(ASN1_R_NO_DEFAULT_DIGEST) , "no default digest"},
{ERR_REASON(ASN1_R_NO_MATCHING_CHOICE_TYPE), "no matching choice type"},
{ERR_REASON(ASN1_R_NO_MULTIPART_BODY_FAILURE), "no multipart body failure"},
{ERR_REASON(ASN1_R_NO_MULTIPART_BOUNDARY), "no multipart boundary"},
{ERR_REASON(ASN1_R_NO_SIG_CONTENT_TYPE) , "no sig content type"},
{ERR_REASON(ASN1_R_NULL_IS_WRONG_LENGTH) , "null is wrong length"},
{ERR_REASON(ASN1_R_OBJECT_NOT_ASCII_FORMAT), "object not ascii format"},
{ERR_REASON(ASN1_R_ODD_NUMBER_OF_CHARS) , "odd number of chars"},
{ERR_REASON(ASN1_R_PRIVATE_KEY_HEADER_MISSING), "private key header missing"},
{ERR_REASON(ASN1_R_SECOND_NUMBER_TOO_LARGE), "second number too large"},
{ERR_REASON(ASN1_R_SEQUENCE_LENGTH_MISMATCH), "sequence length mismatch"},
{ERR_REASON(ASN1_R_SEQUENCE_NOT_CONSTRUCTED), "sequence not constructed"},
{ERR_REASON(ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG), "sequence or set needs config"},
{ERR_REASON(ASN1_R_SHORT_LINE) , "short line"},
{ERR_REASON(ASN1_R_SIG_INVALID_MIME_TYPE), "sig invalid mime type"},
{ERR_REASON(ASN1_R_STREAMING_NOT_SUPPORTED), "streaming not supported"},
{ERR_REASON(ASN1_R_STRING_TOO_LONG) , "string too long"},
{ERR_REASON(ASN1_R_STRING_TOO_SHORT) , "string too short"},
{ERR_REASON(ASN1_R_TAG_VALUE_TOO_HIGH) , "tag value too high"},
{ERR_REASON(ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD), "the asn1 object identifier is not known for this md"},
{ERR_REASON(ASN1_R_TIME_NOT_ASCII_FORMAT), "time not ascii format"},
{ERR_REASON(ASN1_R_TOO_LARGE) , "too large"},
{ERR_REASON(ASN1_R_TOO_LONG) , "too long"},
{ERR_REASON(ASN1_R_TOO_SMALL) , "too small"},
{ERR_REASON(ASN1_R_TYPE_NOT_CONSTRUCTED) , "type not constructed"},
{ERR_REASON(ASN1_R_TYPE_NOT_PRIMITIVE) , "type not primitive"},
{ERR_REASON(ASN1_R_UNABLE_TO_DECODE_RSA_KEY), "unable to decode rsa key"},
{ERR_REASON(ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY), "unable to decode rsa private key"},
{ERR_REASON(ASN1_R_UNEXPECTED_EOC) , "unexpected eoc"},
{ERR_REASON(ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH), "universalstring is wrong length"},
{ERR_REASON(ASN1_R_UNKNOWN_FORMAT) , "unknown format"},
{ERR_REASON(ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM), "unknown message digest algorithm"},
{ERR_REASON(ASN1_R_UNKNOWN_OBJECT_TYPE) , "unknown object type"},
{ERR_REASON(ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE), "unknown public key type"},
{ERR_REASON(ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM), "unknown signature algorithm"},
{ERR_REASON(ASN1_R_UNKNOWN_TAG) , "unknown tag"},
{ERR_REASON(ASN1_R_UNKOWN_FORMAT) , "unknown format"},
{ERR_REASON(ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE), "unsupported any defined by type"},
{ERR_REASON(ASN1_R_UNSUPPORTED_CIPHER) , "unsupported cipher"},
{ERR_REASON(ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM), "unsupported encryption algorithm"},
{ERR_REASON(ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE), "unsupported public key type"},
{ERR_REASON(ASN1_R_UNSUPPORTED_TYPE) , "unsupported type"},
{ERR_REASON(ASN1_R_WRONG_INTEGER_TYPE) , "wrong integer type"},
{ERR_REASON(ASN1_R_WRONG_PUBLIC_KEY_TYPE), "wrong public key type"},
{ERR_REASON(ASN1_R_WRONG_TAG) , "wrong tag"},
{ERR_REASON(ASN1_R_WRONG_TYPE) , "wrong type"},
{0, NULL}
};
#endif
void
ERR_load_ASN1_strings(void)
{
#ifndef OPENSSL_NO_ERR
if (ERR_func_error_string(ASN1_str_functs[0].error) == NULL) {
ERR_load_strings(0, ASN1_str_functs);
ERR_load_strings(0, ASN1_str_reasons);
}
#endif
}
LCRYPTO_ALIAS(ERR_load_ASN1_strings);

804
crypto/asn1/asn1_gen.c Normal file
View File

@@ -0,0 +1,804 @@
/* $OpenBSD: asn1_gen.c,v 1.21 2023/07/05 21:23:36 beck Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2002.
*/
/* ====================================================================
* Copyright (c) 2002 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* 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 <string.h>
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/x509v3.h>
#include "asn1_local.h"
#define ASN1_GEN_FLAG 0x10000
#define ASN1_GEN_FLAG_IMP (ASN1_GEN_FLAG|1)
#define ASN1_GEN_FLAG_EXP (ASN1_GEN_FLAG|2)
#define ASN1_GEN_FLAG_TAG (ASN1_GEN_FLAG|3)
#define ASN1_GEN_FLAG_BITWRAP (ASN1_GEN_FLAG|4)
#define ASN1_GEN_FLAG_OCTWRAP (ASN1_GEN_FLAG|5)
#define ASN1_GEN_FLAG_SEQWRAP (ASN1_GEN_FLAG|6)
#define ASN1_GEN_FLAG_SETWRAP (ASN1_GEN_FLAG|7)
#define ASN1_GEN_FLAG_FORMAT (ASN1_GEN_FLAG|8)
#define ASN1_GEN_STR(str,val){str, sizeof(str) - 1, val}
#define ASN1_FLAG_EXP_MAX 20
/* Input formats */
/* ASCII: default */
#define ASN1_GEN_FORMAT_ASCII 1
/* UTF8 */
#define ASN1_GEN_FORMAT_UTF8 2
/* Hex */
#define ASN1_GEN_FORMAT_HEX 3
/* List of bits */
#define ASN1_GEN_FORMAT_BITLIST 4
struct tag_name_st {
const char *strnam;
int len;
int tag;
};
typedef struct {
int exp_tag;
int exp_class;
int exp_constructed;
int exp_pad;
long exp_len;
} tag_exp_type;
typedef struct {
int imp_tag;
int imp_class;
int utype;
int format;
const char *str;
tag_exp_type exp_list[ASN1_FLAG_EXP_MAX];
int exp_count;
} tag_exp_arg;
static int bitstr_cb(const char *elem, int len, void *bitstr);
static int asn1_cb(const char *elem, int len, void *bitstr);
static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class,
int exp_constructed, int exp_pad, int imp_ok);
static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass);
static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf);
static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype);
static int asn1_str2tag(const char *tagstr, int len);
ASN1_TYPE *
ASN1_generate_nconf(const char *str, CONF *nconf)
{
X509V3_CTX cnf;
if (!nconf)
return ASN1_generate_v3(str, NULL);
X509V3_set_nconf(&cnf, nconf);
return ASN1_generate_v3(str, &cnf);
}
LCRYPTO_ALIAS(ASN1_generate_nconf);
ASN1_TYPE *
ASN1_generate_v3(const char *str, X509V3_CTX *cnf)
{
ASN1_TYPE *ret;
tag_exp_arg asn1_tags;
tag_exp_type *etmp;
int i, len;
unsigned char *orig_der = NULL, *new_der = NULL;
const unsigned char *cpy_start;
unsigned char *p;
const unsigned char *cp;
int cpy_len;
long hdr_len = 0;
int hdr_constructed = 0, hdr_tag, hdr_class;
int r;
asn1_tags.imp_tag = -1;
asn1_tags.imp_class = -1;
asn1_tags.format = ASN1_GEN_FORMAT_ASCII;
asn1_tags.exp_count = 0;
if (CONF_parse_list(str, ',', 1, asn1_cb, &asn1_tags) != 0)
return NULL;
if ((asn1_tags.utype == V_ASN1_SEQUENCE) ||
(asn1_tags.utype == V_ASN1_SET)) {
if (!cnf) {
ASN1error(ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG);
return NULL;
}
ret = asn1_multi(asn1_tags.utype, asn1_tags.str, cnf);
} else
ret = asn1_str2type(asn1_tags.str, asn1_tags.format,
asn1_tags.utype);
if (!ret)
return NULL;
/* If no tagging return base type */
if ((asn1_tags.imp_tag == -1) && (asn1_tags.exp_count == 0))
return ret;
/* Generate the encoding */
cpy_len = i2d_ASN1_TYPE(ret, &orig_der);
ASN1_TYPE_free(ret);
ret = NULL;
/* Set point to start copying for modified encoding */
cpy_start = orig_der;
/* Do we need IMPLICIT tagging? */
if (asn1_tags.imp_tag != -1) {
/* If IMPLICIT we will replace the underlying tag */
/* Skip existing tag+len */
r = ASN1_get_object(&cpy_start, &hdr_len, &hdr_tag,
&hdr_class, cpy_len);
if (r & 0x80)
goto err;
/* Update copy length */
cpy_len -= cpy_start - orig_der;
/* For IMPLICIT tagging the length should match the
* original length and constructed flag should be
* consistent.
*/
if (r & 0x1) {
/* Indefinite length constructed */
hdr_constructed = 2;
hdr_len = 0;
} else
/* Just retain constructed flag */
hdr_constructed = r & V_ASN1_CONSTRUCTED;
/* Work out new length with IMPLICIT tag: ignore constructed
* because it will mess up if indefinite length
*/
len = ASN1_object_size(0, hdr_len, asn1_tags.imp_tag);
} else
len = cpy_len;
/* Work out length in any EXPLICIT, starting from end */
for (i = 0, etmp = asn1_tags.exp_list + asn1_tags.exp_count - 1;
i < asn1_tags.exp_count; i++, etmp--) {
/* Content length: number of content octets + any padding */
len += etmp->exp_pad;
etmp->exp_len = len;
/* Total object length: length including new header */
len = ASN1_object_size(0, len, etmp->exp_tag);
}
/* Allocate buffer for new encoding */
new_der = malloc(len);
if (!new_der)
goto err;
/* Generate tagged encoding */
p = new_der;
/* Output explicit tags first */
for (i = 0, etmp = asn1_tags.exp_list; i < asn1_tags.exp_count;
i++, etmp++) {
ASN1_put_object(&p, etmp->exp_constructed, etmp->exp_len,
etmp->exp_tag, etmp->exp_class);
if (etmp->exp_pad)
*p++ = 0;
}
/* If IMPLICIT, output tag */
if (asn1_tags.imp_tag != -1) {
if (asn1_tags.imp_class == V_ASN1_UNIVERSAL &&
(asn1_tags.imp_tag == V_ASN1_SEQUENCE ||
asn1_tags.imp_tag == V_ASN1_SET))
hdr_constructed = V_ASN1_CONSTRUCTED;
ASN1_put_object(&p, hdr_constructed, hdr_len,
asn1_tags.imp_tag, asn1_tags.imp_class);
}
/* Copy across original encoding */
memcpy(p, cpy_start, cpy_len);
cp = new_der;
/* Obtain new ASN1_TYPE structure */
ret = d2i_ASN1_TYPE(NULL, &cp, len);
err:
free(orig_der);
free(new_der);
return ret;
}
LCRYPTO_ALIAS(ASN1_generate_v3);
static int
asn1_cb(const char *elem, int len, void *bitstr)
{
tag_exp_arg *arg = bitstr;
int i;
int utype;
int vlen = 0;
const char *p, *vstart = NULL;
int tmp_tag, tmp_class;
for (i = 0, p = elem; i < len; p++, i++) {
/* Look for the ':' in name value pairs */
if (*p == ':') {
vstart = p + 1;
vlen = len - (vstart - elem);
len = p - elem;
break;
}
}
utype = asn1_str2tag(elem, len);
if (utype == -1) {
ASN1error(ASN1_R_UNKNOWN_TAG);
ERR_asprintf_error_data("tag=%s", elem);
return -1;
}
/* If this is not a modifier mark end of string and exit */
if (!(utype & ASN1_GEN_FLAG)) {
arg->utype = utype;
arg->str = vstart;
/* If no value and not end of string, error */
if (!vstart && elem[len]) {
ASN1error(ASN1_R_MISSING_VALUE);
return -1;
}
return 0;
}
switch (utype) {
case ASN1_GEN_FLAG_IMP:
/* Check for illegal multiple IMPLICIT tagging */
if (arg->imp_tag != -1) {
ASN1error(ASN1_R_ILLEGAL_NESTED_TAGGING);
return -1;
}
if (!parse_tagging(vstart, vlen, &arg->imp_tag,
&arg->imp_class))
return -1;
break;
case ASN1_GEN_FLAG_EXP:
if (!parse_tagging(vstart, vlen, &tmp_tag, &tmp_class))
return -1;
if (!append_exp(arg, tmp_tag, tmp_class, 1, 0, 0))
return -1;
break;
case ASN1_GEN_FLAG_SEQWRAP:
if (!append_exp(arg, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL, 1, 0, 1))
return -1;
break;
case ASN1_GEN_FLAG_SETWRAP:
if (!append_exp(arg, V_ASN1_SET, V_ASN1_UNIVERSAL, 1, 0, 1))
return -1;
break;
case ASN1_GEN_FLAG_BITWRAP:
if (!append_exp(arg, V_ASN1_BIT_STRING, V_ASN1_UNIVERSAL, 0, 1, 1))
return -1;
break;
case ASN1_GEN_FLAG_OCTWRAP:
if (!append_exp(arg, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL, 0, 0, 1))
return -1;
break;
case ASN1_GEN_FLAG_FORMAT:
if (vstart == NULL) {
ASN1error(ASN1_R_ILLEGAL_FORMAT);
return -1;
}
if (!strncmp(vstart, "ASCII", 5))
arg->format = ASN1_GEN_FORMAT_ASCII;
else if (!strncmp(vstart, "UTF8", 4))
arg->format = ASN1_GEN_FORMAT_UTF8;
else if (!strncmp(vstart, "HEX", 3))
arg->format = ASN1_GEN_FORMAT_HEX;
else if (!strncmp(vstart, "BITLIST", 7))
arg->format = ASN1_GEN_FORMAT_BITLIST;
else {
ASN1error(ASN1_R_UNKOWN_FORMAT);
return -1;
}
break;
}
return 1;
}
static int
parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass)
{
long tag_num;
char *eptr;
if (!vstart)
return 0;
tag_num = strtoul(vstart, &eptr, 10);
/* Check we haven't gone past max length: should be impossible */
if (eptr && *eptr && (eptr > vstart + vlen))
return 0;
if (tag_num < 0) {
ASN1error(ASN1_R_INVALID_NUMBER);
return 0;
}
*ptag = tag_num;
/* If we have non numeric characters, parse them */
if (eptr)
vlen -= eptr - vstart;
else
vlen = 0;
if (vlen) {
switch (*eptr) {
case 'U':
*pclass = V_ASN1_UNIVERSAL;
break;
case 'A':
*pclass = V_ASN1_APPLICATION;
break;
case 'P':
*pclass = V_ASN1_PRIVATE;
break;
case 'C':
*pclass = V_ASN1_CONTEXT_SPECIFIC;
break;
default:
ASN1error(ASN1_R_INVALID_MODIFIER);
ERR_asprintf_error_data("Char=%c", *eptr);
return 0;
break;
}
} else
*pclass = V_ASN1_CONTEXT_SPECIFIC;
return 1;
}
/* Handle multiple types: SET and SEQUENCE */
static ASN1_TYPE *
asn1_multi(int utype, const char *section, X509V3_CTX *cnf)
{
ASN1_TYPE *ret = NULL;
STACK_OF(ASN1_TYPE) *sk = NULL;
STACK_OF(CONF_VALUE) *sect = NULL;
unsigned char *der = NULL;
int derlen;
int i;
sk = sk_ASN1_TYPE_new_null();
if (!sk)
goto bad;
if (section) {
if (!cnf)
goto bad;
sect = X509V3_get_section(cnf, (char *)section);
if (!sect)
goto bad;
for (i = 0; i < sk_CONF_VALUE_num(sect); i++) {
ASN1_TYPE *typ = ASN1_generate_v3(
sk_CONF_VALUE_value(sect, i)->value, cnf);
if (!typ)
goto bad;
if (!sk_ASN1_TYPE_push(sk, typ))
goto bad;
}
}
/* Now we has a STACK of the components, convert to the correct form */
if (utype == V_ASN1_SET)
derlen = i2d_ASN1_SET_ANY(sk, &der);
else
derlen = i2d_ASN1_SEQUENCE_ANY(sk, &der);
if (derlen < 0)
goto bad;
if (!(ret = ASN1_TYPE_new()))
goto bad;
if (!(ret->value.asn1_string = ASN1_STRING_type_new(utype)))
goto bad;
ret->type = utype;
ret->value.asn1_string->data = der;
ret->value.asn1_string->length = derlen;
der = NULL;
bad:
free(der);
if (sk)
sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free);
if (sect)
X509V3_section_free(cnf, sect);
return ret;
}
static int
append_exp(tag_exp_arg *arg, int exp_tag, int exp_class, int exp_constructed,
int exp_pad, int imp_ok)
{
tag_exp_type *exp_tmp;
/* Can only have IMPLICIT if permitted */
if ((arg->imp_tag != -1) && !imp_ok) {
ASN1error(ASN1_R_ILLEGAL_IMPLICIT_TAG);
return 0;
}
if (arg->exp_count == ASN1_FLAG_EXP_MAX) {
ASN1error(ASN1_R_DEPTH_EXCEEDED);
return 0;
}
exp_tmp = &arg->exp_list[arg->exp_count++];
/* If IMPLICIT set tag to implicit value then
* reset implicit tag since it has been used.
*/
if (arg->imp_tag != -1) {
exp_tmp->exp_tag = arg->imp_tag;
exp_tmp->exp_class = arg->imp_class;
arg->imp_tag = -1;
arg->imp_class = -1;
} else {
exp_tmp->exp_tag = exp_tag;
exp_tmp->exp_class = exp_class;
}
exp_tmp->exp_constructed = exp_constructed;
exp_tmp->exp_pad = exp_pad;
return 1;
}
static int
asn1_str2tag(const char *tagstr, int len)
{
unsigned int i;
static const struct tag_name_st *tntmp, tnst [] = {
ASN1_GEN_STR("BOOL", V_ASN1_BOOLEAN),
ASN1_GEN_STR("BOOLEAN", V_ASN1_BOOLEAN),
ASN1_GEN_STR("NULL", V_ASN1_NULL),
ASN1_GEN_STR("INT", V_ASN1_INTEGER),
ASN1_GEN_STR("INTEGER", V_ASN1_INTEGER),
ASN1_GEN_STR("ENUM", V_ASN1_ENUMERATED),
ASN1_GEN_STR("ENUMERATED", V_ASN1_ENUMERATED),
ASN1_GEN_STR("OID", V_ASN1_OBJECT),
ASN1_GEN_STR("OBJECT", V_ASN1_OBJECT),
ASN1_GEN_STR("UTCTIME", V_ASN1_UTCTIME),
ASN1_GEN_STR("UTC", V_ASN1_UTCTIME),
ASN1_GEN_STR("GENERALIZEDTIME", V_ASN1_GENERALIZEDTIME),
ASN1_GEN_STR("GENTIME", V_ASN1_GENERALIZEDTIME),
ASN1_GEN_STR("OCT", V_ASN1_OCTET_STRING),
ASN1_GEN_STR("OCTETSTRING", V_ASN1_OCTET_STRING),
ASN1_GEN_STR("BITSTR", V_ASN1_BIT_STRING),
ASN1_GEN_STR("BITSTRING", V_ASN1_BIT_STRING),
ASN1_GEN_STR("UNIVERSALSTRING", V_ASN1_UNIVERSALSTRING),
ASN1_GEN_STR("UNIV", V_ASN1_UNIVERSALSTRING),
ASN1_GEN_STR("IA5", V_ASN1_IA5STRING),
ASN1_GEN_STR("IA5STRING", V_ASN1_IA5STRING),
ASN1_GEN_STR("UTF8", V_ASN1_UTF8STRING),
ASN1_GEN_STR("UTF8String", V_ASN1_UTF8STRING),
ASN1_GEN_STR("BMP", V_ASN1_BMPSTRING),
ASN1_GEN_STR("BMPSTRING", V_ASN1_BMPSTRING),
ASN1_GEN_STR("VISIBLESTRING", V_ASN1_VISIBLESTRING),
ASN1_GEN_STR("VISIBLE", V_ASN1_VISIBLESTRING),
ASN1_GEN_STR("PRINTABLESTRING", V_ASN1_PRINTABLESTRING),
ASN1_GEN_STR("PRINTABLE", V_ASN1_PRINTABLESTRING),
ASN1_GEN_STR("T61", V_ASN1_T61STRING),
ASN1_GEN_STR("T61STRING", V_ASN1_T61STRING),
ASN1_GEN_STR("TELETEXSTRING", V_ASN1_T61STRING),
ASN1_GEN_STR("GeneralString", V_ASN1_GENERALSTRING),
ASN1_GEN_STR("GENSTR", V_ASN1_GENERALSTRING),
ASN1_GEN_STR("NUMERIC", V_ASN1_NUMERICSTRING),
ASN1_GEN_STR("NUMERICSTRING", V_ASN1_NUMERICSTRING),
/* Special cases */
ASN1_GEN_STR("SEQUENCE", V_ASN1_SEQUENCE),
ASN1_GEN_STR("SEQ", V_ASN1_SEQUENCE),
ASN1_GEN_STR("SET", V_ASN1_SET),
/* type modifiers */
/* Explicit tag */
ASN1_GEN_STR("EXP", ASN1_GEN_FLAG_EXP),
ASN1_GEN_STR("EXPLICIT", ASN1_GEN_FLAG_EXP),
/* Implicit tag */
ASN1_GEN_STR("IMP", ASN1_GEN_FLAG_IMP),
ASN1_GEN_STR("IMPLICIT", ASN1_GEN_FLAG_IMP),
/* OCTET STRING wrapper */
ASN1_GEN_STR("OCTWRAP", ASN1_GEN_FLAG_OCTWRAP),
/* SEQUENCE wrapper */
ASN1_GEN_STR("SEQWRAP", ASN1_GEN_FLAG_SEQWRAP),
/* SET wrapper */
ASN1_GEN_STR("SETWRAP", ASN1_GEN_FLAG_SETWRAP),
/* BIT STRING wrapper */
ASN1_GEN_STR("BITWRAP", ASN1_GEN_FLAG_BITWRAP),
ASN1_GEN_STR("FORM", ASN1_GEN_FLAG_FORMAT),
ASN1_GEN_STR("FORMAT", ASN1_GEN_FLAG_FORMAT),
};
if (len == -1)
len = strlen(tagstr);
tntmp = tnst;
for (i = 0; i < sizeof(tnst) / sizeof(struct tag_name_st);
i++, tntmp++) {
if ((len == tntmp->len) && !strncmp(tntmp->strnam, tagstr, len))
return tntmp->tag;
}
return -1;
}
static ASN1_TYPE *
asn1_str2type(const char *str, int format, int utype)
{
ASN1_TYPE *atmp = NULL;
CONF_VALUE vtmp;
unsigned char *rdata;
long rdlen;
int no_unused = 1;
if (!(atmp = ASN1_TYPE_new())) {
ASN1error(ERR_R_MALLOC_FAILURE);
return NULL;
}
if (!str)
str = "";
switch (utype) {
case V_ASN1_NULL:
if (str && *str) {
ASN1error(ASN1_R_ILLEGAL_NULL_VALUE);
goto bad_form;
}
break;
case V_ASN1_BOOLEAN:
if (format != ASN1_GEN_FORMAT_ASCII) {
ASN1error(ASN1_R_NOT_ASCII_FORMAT);
goto bad_form;
}
vtmp.name = NULL;
vtmp.section = NULL;
vtmp.value = (char *)str;
if (!X509V3_get_value_bool(&vtmp, &atmp->value.boolean)) {
ASN1error(ASN1_R_ILLEGAL_BOOLEAN);
goto bad_str;
}
break;
case V_ASN1_INTEGER:
case V_ASN1_ENUMERATED:
if (format != ASN1_GEN_FORMAT_ASCII) {
ASN1error(ASN1_R_INTEGER_NOT_ASCII_FORMAT);
goto bad_form;
}
if (!(atmp->value.integer =
s2i_ASN1_INTEGER(NULL, (char *)str))) {
ASN1error(ASN1_R_ILLEGAL_INTEGER);
goto bad_str;
}
break;
case V_ASN1_OBJECT:
if (format != ASN1_GEN_FORMAT_ASCII) {
ASN1error(ASN1_R_OBJECT_NOT_ASCII_FORMAT);
goto bad_form;
}
if (!(atmp->value.object = OBJ_txt2obj(str, 0))) {
ASN1error(ASN1_R_ILLEGAL_OBJECT);
goto bad_str;
}
break;
case V_ASN1_UTCTIME:
case V_ASN1_GENERALIZEDTIME:
if (format != ASN1_GEN_FORMAT_ASCII) {
ASN1error(ASN1_R_TIME_NOT_ASCII_FORMAT);
goto bad_form;
}
if (!(atmp->value.asn1_string = ASN1_STRING_new())) {
ASN1error(ERR_R_MALLOC_FAILURE);
goto bad_str;
}
if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1)) {
ASN1error(ERR_R_MALLOC_FAILURE);
goto bad_str;
}
atmp->value.asn1_string->type = utype;
if (!ASN1_TIME_check(atmp->value.asn1_string)) {
ASN1error(ASN1_R_ILLEGAL_TIME_VALUE);
goto bad_str;
}
break;
case V_ASN1_BMPSTRING:
case V_ASN1_PRINTABLESTRING:
case V_ASN1_IA5STRING:
case V_ASN1_T61STRING:
case V_ASN1_UTF8STRING:
case V_ASN1_VISIBLESTRING:
case V_ASN1_UNIVERSALSTRING:
case V_ASN1_GENERALSTRING:
case V_ASN1_NUMERICSTRING:
if (format == ASN1_GEN_FORMAT_ASCII)
format = MBSTRING_ASC;
else if (format == ASN1_GEN_FORMAT_UTF8)
format = MBSTRING_UTF8;
else {
ASN1error(ASN1_R_ILLEGAL_FORMAT);
goto bad_form;
}
if (ASN1_mbstring_copy(&atmp->value.asn1_string,
(unsigned char *)str, -1, format,
ASN1_tag2bit(utype)) <= 0) {
ASN1error(ERR_R_MALLOC_FAILURE);
goto bad_str;
}
break;
case V_ASN1_BIT_STRING:
case V_ASN1_OCTET_STRING:
if (!(atmp->value.asn1_string = ASN1_STRING_new())) {
ASN1error(ERR_R_MALLOC_FAILURE);
goto bad_form;
}
if (format == ASN1_GEN_FORMAT_HEX) {
if (!(rdata = string_to_hex((char *)str, &rdlen))) {
ASN1error(ASN1_R_ILLEGAL_HEX);
goto bad_str;
}
atmp->value.asn1_string->data = rdata;
atmp->value.asn1_string->length = rdlen;
atmp->value.asn1_string->type = utype;
} else if (format == ASN1_GEN_FORMAT_ASCII) {
if (ASN1_STRING_set(atmp->value.asn1_string, str,
-1) == 0) {
ASN1error(ERR_R_MALLOC_FAILURE);
goto bad_str;
}
} else if ((format == ASN1_GEN_FORMAT_BITLIST) &&
(utype == V_ASN1_BIT_STRING)) {
if (!CONF_parse_list(str, ',', 1, bitstr_cb,
atmp->value.bit_string)) {
ASN1error(ASN1_R_LIST_ERROR);
goto bad_str;
}
no_unused = 0;
} else {
ASN1error(ASN1_R_ILLEGAL_BITSTRING_FORMAT);
goto bad_form;
}
if ((utype == V_ASN1_BIT_STRING) && no_unused) {
if (!asn1_abs_set_unused_bits(atmp->value.asn1_string,
0))
goto bad_str;
}
break;
default:
ASN1error(ASN1_R_UNSUPPORTED_TYPE);
goto bad_str;
break;
}
atmp->type = utype;
return atmp;
bad_str:
ERR_asprintf_error_data("string=%s", str);
bad_form:
ASN1_TYPE_free(atmp);
return NULL;
}
static int
bitstr_cb(const char *elem, int len, void *bitstr)
{
long bitnum;
char *eptr;
if (!elem)
return 0;
bitnum = strtoul(elem, &eptr, 10);
if (eptr && *eptr && (eptr != elem + len))
return 0;
if (bitnum < 0) {
ASN1error(ASN1_R_INVALID_NUMBER);
return 0;
}
if (!ASN1_BIT_STRING_set_bit(bitstr, bitnum, 1)) {
ASN1error(ERR_R_MALLOC_FAILURE);
return 0;
}
return 1;
}

689
crypto/asn1/asn1_item.c Normal file
View File

@@ -0,0 +1,689 @@
/* $OpenBSD: asn1_item.c,v 1.17 2023/07/13 20:59:10 tb Exp $ */
/* 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.]
*/
/* ====================================================================
* Copyright (c) 1998-2003 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
* openssl-core@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 <limits.h>
#include <openssl/buffer.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include "asn1_local.h"
#include "evp_local.h"
int
ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *asn,
unsigned char *md, unsigned int *len)
{
int i;
unsigned char *str = NULL;
i = ASN1_item_i2d(asn, &str, it);
if (!str)
return (0);
if (!EVP_Digest(str, i, md, len, type, NULL)) {
free(str);
return (0);
}
free(str);
return (1);
}
/*
* ASN1_ITEM version of ASN1_dup(): follows the same model except there's no
* need to allocate the buffer. At some point this could be rewritten to dup
* the underlying structure directly instead of doing an encode and decode.
*/
void *
ASN1_item_dup(const ASN1_ITEM *it, void *x)
{
unsigned char *b = NULL;
const unsigned char *p;
long i;
void *ret;
if (x == NULL)
return (NULL);
i = ASN1_item_i2d(x, &b, it);
if (b == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
return (NULL);
}
p = b;
ret = ASN1_item_d2i(NULL, &p, i, it);
free(b);
return (ret);
}
LCRYPTO_ALIAS(ASN1_item_dup);
/* Pack an ASN1 object into an ASN1_STRING. */
ASN1_STRING *
ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct)
{
ASN1_STRING *octmp;
if (!oct || !*oct) {
if (!(octmp = ASN1_STRING_new ())) {
ASN1error(ERR_R_MALLOC_FAILURE);
return NULL;
}
} else
octmp = *oct;
free(octmp->data);
octmp->data = NULL;
if (!(octmp->length = ASN1_item_i2d(obj, &octmp->data, it))) {
ASN1error(ASN1_R_ENCODE_ERROR);
goto err;
}
if (!octmp->data) {
ASN1error(ERR_R_MALLOC_FAILURE);
goto err;
}
if (oct)
*oct = octmp;
return octmp;
err:
if (!oct || octmp != *oct)
ASN1_STRING_free(octmp);
return NULL;
}
LCRYPTO_ALIAS(ASN1_item_pack);
/* Extract an ASN1 object from an ASN1_STRING. */
void *
ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it)
{
const unsigned char *p;
void *ret;
p = oct->data;
if (!(ret = ASN1_item_d2i(NULL, &p, oct->length, it)))
ASN1error(ASN1_R_DECODE_ERROR);
return ret;
}
LCRYPTO_ALIAS(ASN1_item_unpack);
int
ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey, const EVP_MD *type)
{
EVP_MD_CTX ctx;
EVP_MD_CTX_init(&ctx);
if (!EVP_DigestSignInit(&ctx, NULL, type, NULL, pkey)) {
EVP_MD_CTX_cleanup(&ctx);
return 0;
}
return ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, &ctx);
}
static int
asn1_item_set_algorithm_identifiers(EVP_MD_CTX *ctx, X509_ALGOR *algor1,
X509_ALGOR *algor2)
{
EVP_PKEY *pkey;
ASN1_OBJECT *aobj;
const EVP_MD *md;
int sign_id, sign_param;
if ((pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx)) == NULL) {
ASN1error(ASN1_R_CONTEXT_NOT_INITIALISED);
return 0;
}
if ((md = EVP_MD_CTX_md(ctx)) == NULL) {
ASN1error(ASN1_R_CONTEXT_NOT_INITIALISED);
return 0;
}
if (!OBJ_find_sigid_by_algs(&sign_id, EVP_MD_nid(md),
pkey->ameth->pkey_id)) {
ASN1error(ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
return 0;
}
if ((aobj = OBJ_nid2obj(sign_id)) == NULL) {
ASN1error(ASN1_R_UNKNOWN_OBJECT_TYPE);
return 0;
}
sign_param = V_ASN1_UNDEF;
if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL)
sign_param = V_ASN1_NULL;
if (algor1 != NULL) {
if (!X509_ALGOR_set0(algor1, aobj, sign_param, NULL))
return 0;
}
if (algor2 != NULL) {
if (!X509_ALGOR_set0(algor2, aobj, sign_param, NULL))
return 0;
}
return 1;
}
static int
asn1_item_sign(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
ASN1_BIT_STRING *signature)
{
unsigned char *in = NULL, *out = NULL;
size_t out_len = 0;
int in_len = 0;
int ret = 0;
if ((in_len = ASN1_item_i2d(asn, &in, it)) <= 0) {
in_len = 0;
goto err;
}
if (!EVP_DigestSign(ctx, NULL, &out_len, in, in_len)) {
ASN1error(ERR_R_EVP_LIB);
goto err;
}
if ((out = calloc(1, out_len)) == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
goto err;
}
if (!EVP_DigestSign(ctx, out, &out_len, in, in_len)) {
ASN1error(ERR_R_EVP_LIB);
goto err;
}
if (out_len > INT_MAX) {
ASN1error(ASN1_R_TOO_LONG);
goto err;
}
ASN1_STRING_set0(signature, out, out_len);
out = NULL;
if (!asn1_abs_set_unused_bits(signature, 0)) {
ASN1_STRING_set0(signature, NULL, 0);
ASN1error(ERR_R_ASN1_LIB);
goto err;
}
ret = 1;
err:
freezero(in, in_len);
freezero(out, out_len);
return ret;
}
int
ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx)
{
EVP_PKEY *pkey;
int rv;
int ret = 0;
if ((pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx)) == NULL) {
ASN1error(ASN1_R_CONTEXT_NOT_INITIALISED);
goto err;
}
if (pkey->ameth == NULL) {
ASN1error(ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
goto err;
}
/*
* API insanity ahead. If the item_sign() method is absent or if it
* returns 2, this means: do all the work here. If it returns 3, only
* sign. If it returns 1, then there's nothing to do but to return
* the signature's length. Everything else is an error.
*/
rv = 2;
if (pkey->ameth->item_sign != NULL)
rv = pkey->ameth->item_sign(ctx, it, asn, algor1, algor2,
signature);
if (rv <= 0 || rv > 3)
goto err;
if (rv == 1)
goto done;
if (rv == 2) {
if (!asn1_item_set_algorithm_identifiers(ctx, algor1, algor2))
goto err;
}
if (!asn1_item_sign(ctx, it, asn, signature))
goto err;
done:
ret = signature->length;
err:
EVP_MD_CTX_cleanup(ctx);
return ret;
}
int
ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey)
{
EVP_MD_CTX ctx;
unsigned char *in = NULL;
int mdnid, pknid;
int in_len = 0;
int ret = -1;
if (pkey == NULL) {
ASN1error(ERR_R_PASSED_NULL_PARAMETER);
return -1;
}
if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) {
ASN1error(ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
return -1;
}
EVP_MD_CTX_init(&ctx);
/* Convert signature OID into digest and public key OIDs */
if (!OBJ_find_sigid_algs(OBJ_obj2nid(a->algorithm), &mdnid, &pknid)) {
ASN1error(ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
goto err;
}
if (mdnid == NID_undef) {
if (!pkey->ameth || !pkey->ameth->item_verify) {
ASN1error(ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
goto err;
}
ret = pkey->ameth->item_verify(&ctx, it, asn, a,
signature, pkey);
/* Return value of 2 means carry on, anything else means we
* exit straight away: either a fatal error of the underlying
* verification routine handles all verification.
*/
if (ret != 2)
goto err;
ret = -1;
} else {
const EVP_MD *type;
type = EVP_get_digestbynid(mdnid);
if (type == NULL) {
ASN1error(ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
goto err;
}
/* Check public key OID matches public key type */
if (EVP_PKEY_type(pknid) != pkey->ameth->pkey_id) {
ASN1error(ASN1_R_WRONG_PUBLIC_KEY_TYPE);
goto err;
}
if (!EVP_DigestVerifyInit(&ctx, NULL, type, NULL, pkey)) {
ASN1error(ERR_R_EVP_LIB);
ret = 0;
goto err;
}
}
if ((in_len = ASN1_item_i2d(asn, &in, it)) <= 0) {
ASN1error(ERR_R_MALLOC_FAILURE);
in_len = 0;
goto err;
}
if (EVP_DigestVerify(&ctx, signature->data, signature->length,
in, in_len) <= 0) {
ASN1error(ERR_R_EVP_LIB);
ret = 0;
goto err;
}
ret = 1;
err:
EVP_MD_CTX_cleanup(&ctx);
freezero(in, in_len);
return ret;
}
#define HEADER_SIZE 8
#define ASN1_CHUNK_INITIAL_SIZE (16 * 1024)
int
asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
{
BUF_MEM *b;
unsigned char *p;
const unsigned char *q;
long slen;
int i, inf, tag, xclass;
size_t want = HEADER_SIZE;
int eos = 0;
size_t off = 0;
size_t len = 0;
b = BUF_MEM_new();
if (b == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
return -1;
}
ERR_clear_error();
for (;;) {
if (want >= (len - off)) {
want -= (len - off);
if (len + want < len ||
!BUF_MEM_grow_clean(b, len + want)) {
ASN1error(ERR_R_MALLOC_FAILURE);
goto err;
}
i = BIO_read(in, &(b->data[len]), want);
if ((i < 0) && ((len - off) == 0)) {
ASN1error(ASN1_R_NOT_ENOUGH_DATA);
goto err;
}
if (i > 0) {
if (len + i < len) {
ASN1error(ASN1_R_TOO_LONG);
goto err;
}
len += i;
}
}
/* else data already loaded */
p = (unsigned char *) & (b->data[off]);
q = p;
inf = ASN1_get_object(&q, &slen, &tag, &xclass, len - off);
if (inf & 0x80) {
unsigned long e;
e = ERR_GET_REASON(ERR_peek_error());
if (e != ASN1_R_TOO_LONG)
goto err;
else
ERR_clear_error(); /* clear error */
}
i = q - p; /* header length */
off += i; /* end of data */
if (inf & 1) {
/* no data body so go round again */
eos++;
if (eos < 0) {
ASN1error(ASN1_R_HEADER_TOO_LONG);
goto err;
}
want = HEADER_SIZE;
} else if (eos && slen == 0 && tag == V_ASN1_EOC) {
/* eos value, so go back and read another header */
eos--;
if (eos <= 0)
break;
else
want = HEADER_SIZE;
} else {
/* suck in slen bytes of data */
want = slen;
if (want > (len - off)) {
size_t chunk_max = ASN1_CHUNK_INITIAL_SIZE;
want -= (len - off);
if (want > INT_MAX /* BIO_read takes an int length */ ||
len+want < len) {
ASN1error(ASN1_R_TOO_LONG);
goto err;
}
while (want > 0) {
/*
* Read content in chunks of increasing size
* so we can return an error for EOF without
* having to allocate the entire content length
* in one go.
*/
size_t chunk = want > chunk_max ? chunk_max : want;
if (!BUF_MEM_grow_clean(b, len + chunk)) {
ASN1error(ERR_R_MALLOC_FAILURE);
goto err;
}
want -= chunk;
while (chunk > 0) {
i = BIO_read(in, &(b->data[len]), chunk);
if (i <= 0) {
ASN1error(ASN1_R_NOT_ENOUGH_DATA);
goto err;
}
/*
* This can't overflow because |len+want|
* didn't overflow.
*/
len += i;
chunk -= i;
}
if (chunk_max < INT_MAX/2)
chunk_max *= 2;
}
}
if (off + slen < off) {
ASN1error(ASN1_R_TOO_LONG);
goto err;
}
off += slen;
if (eos <= 0) {
break;
} else
want = HEADER_SIZE;
}
}
if (off > INT_MAX) {
ASN1error(ASN1_R_TOO_LONG);
goto err;
}
*pb = b;
return off;
err:
if (b != NULL)
BUF_MEM_free(b);
return -1;
}
void *
ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x)
{
BUF_MEM *b = NULL;
const unsigned char *p;
void *ret = NULL;
int len;
len = asn1_d2i_read_bio(in, &b);
if (len < 0)
goto err;
p = (const unsigned char *)b->data;
ret = ASN1_item_d2i(x, &p, len, it);
err:
if (b != NULL)
BUF_MEM_free(b);
return (ret);
}
LCRYPTO_ALIAS(ASN1_item_d2i_bio);
void *
ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x)
{
BIO *b;
char *ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
ASN1error(ERR_R_BUF_LIB);
return (NULL);
}
BIO_set_fp(b, in, BIO_NOCLOSE);
ret = ASN1_item_d2i_bio(it, b, x);
BIO_free(b);
return (ret);
}
LCRYPTO_ALIAS(ASN1_item_d2i_fp);
int
ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x)
{
unsigned char *b = NULL;
int i, j = 0, n, ret = 1;
n = ASN1_item_i2d(x, &b, it);
if (b == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
return (0);
}
for (;;) {
i = BIO_write(out, &(b[j]), n);
if (i == n)
break;
if (i <= 0) {
ret = 0;
break;
}
j += i;
n -= i;
}
free(b);
return (ret);
}
LCRYPTO_ALIAS(ASN1_item_i2d_bio);
int
ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x)
{
BIO *b;
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
ASN1error(ERR_R_BUF_LIB);
return (0);
}
BIO_set_fp(b, out, BIO_NOCLOSE);
ret = ASN1_item_i2d_bio(it, b, x);
BIO_free(b);
return (ret);
}
LCRYPTO_ALIAS(ASN1_item_i2d_fp);

204
crypto/asn1/asn1_lib.c Normal file
View File

@@ -0,0 +1,204 @@
/* $OpenBSD: asn1_lib.c,v 1.54 2022/05/05 19:18:56 jsing Exp $ */
/*
* Copyright (c) 2021 Joel Sing <jsing@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <limits.h>
#include <stdlib.h>
#include "bytestring.h"
int
asn1_get_identifier_cbs(CBS *cbs, int der_mode, uint8_t *out_class,
int *out_constructed, uint32_t *out_tag_number)
{
uint8_t tag_class, tag_val;
int tag_constructed;
uint32_t tag_number;
/*
* Decode ASN.1 identifier octets - see ITU-T X.690 section 8.1.2.
*/
*out_class = 0;
*out_constructed = 0;
*out_tag_number = 0;
if (!CBS_get_u8(cbs, &tag_val))
return 0;
/*
* ASN.1 tag class, encoding (primitive or constructed) and tag number
* are encoded in one or more identifier octets - the first octet
* contains the 2 bit tag class, the 1 bit encoding type and 5 bits
* of tag number.
*
* For tag numbers larger than 30 (0x1e) the 5 bit tag number in the
* first octet is set to all ones (0x1f) - the tag number is then
* encoded in subsequent octets - each of which have a one bit
* continuation flag and 7 bits of tag number in big-endian form.
* The encoding should not contain leading zeros but can for BER.
*/
tag_class = (tag_val >> 6) & 0x3;
tag_constructed = (tag_val >> 5) & 0x1;
tag_number = tag_val & 0x1f;
/* Long form. */
if (tag_number == 0x1f) {
tag_number = 0;
do {
if (!CBS_get_u8(cbs, &tag_val))
return 0;
if (der_mode && tag_number == 0 && tag_val == 0x80)
return 0;
if (tag_number > (UINT32_MAX >> 7))
return 0;
tag_number = tag_number << 7 | (tag_val & 0x7f);
} while ((tag_val & 0x80) != 0);
}
*out_class = tag_class;
*out_constructed = tag_constructed;
*out_tag_number = tag_number;
return 1;
}
int
asn1_get_length_cbs(CBS *cbs, int der_mode, int *out_indefinite,
size_t *out_length)
{
uint8_t len_bytes;
size_t length;
uint8_t val;
/*
* Decode ASN.1 length octets - see ITU-T X.690 section 8.1.3.
*/
*out_length = 0;
*out_indefinite = 0;
if (!CBS_get_u8(cbs, &val))
return 0;
/*
* Short form - length is encoded in the lower 7 bits of a single byte.
*/
if (val < 0x80) {
*out_length = val;
return 1;
}
/*
* Indefinite length - content continues until an End of Content (EOC)
* marker is reached. Must be used with constructed encoding.
*/
if (val == 0x80) {
*out_indefinite = 1;
return 1;
}
/*
* Long form - the lower 7 bits of the first byte specifies the number
* of bytes used to encode the length, the following bytes specify the
* length in big-endian form. The encoding should not contain leading
* zeros but can for BER. A length value of 0x7f is invalid.
*/
if ((len_bytes = val & 0x7f) == 0x7f)
return 0;
length = 0;
while (len_bytes-- > 0) {
if (!CBS_get_u8(cbs, &val))
return 0;
if (der_mode && length == 0 && val == 0)
return 0;
if (length > (SIZE_MAX >> 8))
return 0;
length = (length << 8) | val;
}
*out_length = length;
return 1;
}
int
asn1_get_object_cbs(CBS *cbs, int der_mode, uint8_t *out_tag_class,
int *out_constructed, uint32_t *out_tag_number, int *out_indefinite,
size_t *out_length)
{
int constructed, indefinite;
uint32_t tag_number;
uint8_t tag_class;
size_t length;
*out_tag_class = 0;
*out_constructed = 0;
*out_tag_number = 0;
*out_indefinite = 0;
*out_length = 0;
if (!asn1_get_identifier_cbs(cbs, der_mode, &tag_class, &constructed,
&tag_number))
return 0;
if (!asn1_get_length_cbs(cbs, der_mode, &indefinite, &length))
return 0;
/* Indefinite length can only be used with constructed encoding. */
if (indefinite && !constructed)
return 0;
*out_tag_class = tag_class;
*out_constructed = constructed;
*out_tag_number = tag_number;
*out_indefinite = indefinite;
*out_length = length;
return 1;
}
int
asn1_get_primitive(CBS *cbs, int der_mode, uint32_t *out_tag_number,
CBS *out_content)
{
int constructed, indefinite;
uint32_t tag_number;
uint8_t tag_class;
size_t length;
*out_tag_number = 0;
CBS_init(out_content, NULL, 0);
if (!asn1_get_identifier_cbs(cbs, der_mode, &tag_class, &constructed,
&tag_number))
return 0;
if (!asn1_get_length_cbs(cbs, der_mode, &indefinite, &length))
return 0;
/* A primitive is not constructed and has a definite length. */
if (constructed || indefinite)
return 0;
if (!CBS_get_bytes(cbs, out_content, length))
return 0;
*out_tag_number = tag_number;
return 1;
}

272
crypto/asn1/asn1_local.h Normal file
View File

@@ -0,0 +1,272 @@
/* $OpenBSD: asn1_local.h,v 1.4 2023/07/28 10:00:10 tb Exp $ */
/* 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 "bytestring.h"
__BEGIN_HIDDEN_DECLS
/* Internal ASN1 structures and functions: not for application use */
ASN1_TYPE *ASN1_TYPE_pack_sequence(const ASN1_ITEM *it, void *s, ASN1_TYPE **t);
void *ASN1_TYPE_unpack_sequence(const ASN1_ITEM *it, const ASN1_TYPE *t);
/* These are used internally in the ASN1_OBJECT to keep track of
* whether the names and data need to be free()ed */
#define ASN1_OBJECT_FLAG_DYNAMIC 0x01 /* internal use */
#define ASN1_OBJECT_FLAG_CRITICAL 0x02 /* critical x509v3 object id */
#define ASN1_OBJECT_FLAG_DYNAMIC_STRINGS 0x04 /* internal use */
#define ASN1_OBJECT_FLAG_DYNAMIC_DATA 0x08 /* internal use */
struct asn1_object_st {
const char *sn, *ln;
int nid;
int length;
const unsigned char *data; /* data remains const after init */
int flags; /* Should we free this one */
} /* ASN1_OBJECT */;
/* 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, const 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 (*pkey_security_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);
int (*pkey_check)(const EVP_PKEY *pk);
int (*pkey_public_check)(const EVP_PKEY *pk);
int (*pkey_param_check)(const EVP_PKEY *pk);
int (*set_priv_key)(EVP_PKEY *pk, const unsigned char *private_key,
size_t len);
int (*set_pub_key)(EVP_PKEY *pk, const unsigned char *public_key,
size_t len);
int (*get_priv_key)(const EVP_PKEY *pk, unsigned char *out_private_key,
size_t *out_len);
int (*get_pub_key)(const EVP_PKEY *pk, unsigned char *out_public_key,
size_t *out_len);
} /* 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);
};
int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it);
int asn1_set_choice_selector(ASN1_VALUE **pval, int value, const ASN1_ITEM *it);
ASN1_VALUE ** asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, int nullerr);
int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it);
void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it);
void asn1_enc_cleanup(ASN1_VALUE **pval, const ASN1_ITEM *it);
int asn1_enc_save(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it);
int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval, const ASN1_ITEM *it);
int i2d_ASN1_BOOLEAN(int a, unsigned char **pp);
int d2i_ASN1_BOOLEAN(int *a, const unsigned char **pp, long length);
/*
* Unicode codepoint constants
*/
#define UNICODE_MAX 0x10FFFF
#define UNICODE_SURROGATE_MIN 0x00D800
#define UNICODE_SURROGATE_MAX 0x00DFFF
#define UNICODE_IS_SURROGATE(x) \
((x) >= UNICODE_SURROGATE_MIN && (x) <= UNICODE_SURROGATE_MAX)
int UTF8_getc(const unsigned char *str, int len, unsigned long *val);
int UTF8_putc(unsigned char *str, int len, unsigned long value);
int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb);
int asn1_get_identifier_cbs(CBS *cbs, int der_mode, uint8_t *out_class,
int *out_constructed, uint32_t *out_tag_number);
int asn1_get_length_cbs(CBS *cbs, int der_mode, int *out_indefinite,
size_t *out_length);
int asn1_get_object_cbs(CBS *cbs, int der_mode, uint8_t *out_class,
int *out_constructed, uint32_t *out_tag_number, int *out_indefinite,
size_t *out_length);
int asn1_get_primitive(CBS *cbs, int der_mode, uint32_t *out_tag_number,
CBS *out_content);
int asn1_must_be_constructed(int tag);
int asn1_must_be_primitive(int tag);
int asn1_tag2charwidth(int tag);
int asn1_abs_set_unused_bits(ASN1_BIT_STRING *abs, uint8_t unused_bits);
int c2i_ASN1_BIT_STRING_cbs(ASN1_BIT_STRING **out_abs, CBS *cbs);
int c2i_ASN1_ENUMERATED_cbs(ASN1_ENUMERATED **out_aenum, CBS *cbs);
int asn1_aint_get_uint64(CBS *cbs, uint64_t *out_val);
int asn1_aint_set_uint64(uint64_t val, uint8_t **out_data, int *out_len);
int asn1_aint_get_int64(CBS *cbs, int negative, int64_t *out_val);
int c2i_ASN1_INTEGER_cbs(ASN1_INTEGER **out_aint, CBS *cbs);
int c2i_ASN1_OBJECT_cbs(ASN1_OBJECT **out_aobj, CBS *content);
int i2t_ASN1_OBJECT_internal(const ASN1_OBJECT *aobj, char *buf, int buf_len,
int no_name);
ASN1_OBJECT *t2i_ASN1_OBJECT_internal(const char *oid);
int asn1_time_parse_cbs(const CBS *cbs, int is_gentime, struct tm *out_tm);
ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
long length);
int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp);
ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
const unsigned char **pp, long length);
int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp);
ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
long length);
int OPENSSL_gmtime_adj(struct tm *tm, int offset_day, long offset_sec);
int OPENSSL_gmtime_diff(int *pday, int *psec, const struct tm *from,
const struct tm *to);
int asn1_time_time_t_to_tm(const time_t *time, struct tm *out_tm);
int asn1_time_tm_to_time_t(const struct tm *tm, time_t *out);
int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it);
const BIO_METHOD *BIO_f_asn1(void);
BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it);
int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
const ASN1_ITEM *it);
int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
const char *hdr, const ASN1_ITEM *it);
int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
int ctype_nid, int econt_nid, STACK_OF(X509_ALGOR) *mdalgs,
const ASN1_ITEM *it);
ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it);
int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
__END_HIDDEN_DECLS

184
crypto/asn1/asn1_old.c Normal file
View File

@@ -0,0 +1,184 @@
/* $OpenBSD: asn1_old.c,v 1.5 2023/07/07 19:37:52 beck Exp $ */
/* 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 <limits.h>
#include <stdio.h>
#include <openssl/asn1.h>
#include <openssl/buffer.h>
#include <openssl/err.h>
#include "asn1_local.h"
#ifndef NO_OLD_ASN1
void *
ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x)
{
unsigned char *b, *p;
const unsigned char *p2;
int i;
char *ret;
if (x == NULL)
return (NULL);
i = i2d(x, NULL);
b = malloc(i + 10);
if (b == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
return (NULL);
}
p = b;
i = i2d(x, &p);
p2 = b;
ret = d2i(NULL, &p2, i);
free(b);
return (ret);
}
void *
ASN1_d2i_fp(void *(*xnew)(void), d2i_of_void *d2i, FILE *in, void **x)
{
BIO *b;
void *ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
ASN1error(ERR_R_BUF_LIB);
return (NULL);
}
BIO_set_fp(b, in, BIO_NOCLOSE);
ret = ASN1_d2i_bio(xnew, d2i, b, x);
BIO_free(b);
return (ret);
}
LCRYPTO_ALIAS(ASN1_d2i_fp);
void *
ASN1_d2i_bio(void *(*xnew)(void), d2i_of_void *d2i, BIO *in, void **x)
{
BUF_MEM *b = NULL;
const unsigned char *p;
void *ret = NULL;
int len;
len = asn1_d2i_read_bio(in, &b);
if (len < 0)
goto err;
p = (unsigned char *)b->data;
ret = d2i(x, &p, len);
err:
if (b != NULL)
BUF_MEM_free(b);
return (ret);
}
LCRYPTO_ALIAS(ASN1_d2i_bio);
int
ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x)
{
BIO *b;
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
ASN1error(ERR_R_BUF_LIB);
return (0);
}
BIO_set_fp(b, out, BIO_NOCLOSE);
ret = ASN1_i2d_bio(i2d, b, x);
BIO_free(b);
return (ret);
}
LCRYPTO_ALIAS(ASN1_i2d_fp);
int
ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, unsigned char *x)
{
char *b;
unsigned char *p;
int i, j = 0, n, ret = 1;
n = i2d(x, NULL);
b = malloc(n);
if (b == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
return (0);
}
p = (unsigned char *)b;
i2d(x, &p);
for (;;) {
i = BIO_write(out, &(b[j]), n);
if (i == n)
break;
if (i <= 0) {
ret = 0;
break;
}
j += i;
n -= i;
}
free(b);
return (ret);
}
LCRYPTO_ALIAS(ASN1_i2d_bio);
#endif

216
crypto/asn1/asn1_old_lib.c Normal file
View File

@@ -0,0 +1,216 @@
/* $OpenBSD: asn1_old_lib.c,v 1.6 2023/07/05 21:23:36 beck Exp $ */
/* 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 <limits.h>
#include <stdio.h>
#include <string.h>
#include <openssl/asn1.h>
#include <openssl/err.h>
#include "asn1_local.h"
static void asn1_put_length(unsigned char **pp, int length);
int
ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
int *pclass, long omax)
{
int constructed, indefinite;
uint32_t tag_number;
uint8_t tag_class;
size_t length;
CBS cbs;
int ret = 0;
*pclass = 0;
*ptag = 0;
*plength = 0;
CBS_init(&cbs, *pp, omax);
if (!asn1_get_object_cbs(&cbs, 0, &tag_class, &constructed, &tag_number,
&indefinite, &length)) {
ASN1error(ASN1_R_HEADER_TOO_LONG);
return 0x80;
}
if (tag_number > INT_MAX) {
ASN1error(ASN1_R_HEADER_TOO_LONG);
return 0x80;
}
/*
* API insanity ahead... in this case we add an error to the stack and
* signal an error by setting the 8th bit in the return value... but we
* still provide all of the decoded data.
*/
if (length > CBS_len(&cbs) || length > LONG_MAX) {
ASN1error(ASN1_R_TOO_LONG);
ret = 0x80;
}
*pclass = tag_class << 6;
*ptag = tag_number;
*plength = length;
*pp = CBS_data(&cbs);
if (constructed)
ret |= 1 << 5;
if (indefinite)
ret |= 1;
return ret;
}
LCRYPTO_ALIAS(ASN1_get_object);
/* 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;
}
LCRYPTO_ALIAS(ASN1_put_object);
int
ASN1_put_eoc(unsigned char **pp)
{
unsigned char *p = *pp;
*p++ = 0;
*p++ = 0;
*pp = p;
return 2;
}
LCRYPTO_ALIAS(ASN1_put_eoc);
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;
ret = length;
ret++;
if (tag >= 31) {
while (tag > 0) {
tag >>= 7;
ret++;
}
}
if (constructed == 2)
return ret + 3;
ret++;
if (length > 127) {
while (length > 0) {
length >>= 8;
ret++;
}
}
return (ret);
}
LCRYPTO_ALIAS(ASN1_object_size);

386
crypto/asn1/asn1_par.c Normal file
View File

@@ -0,0 +1,386 @@
/* $OpenBSD: asn1_par.c,v 1.35 2023/07/05 21:23:36 beck Exp $ */
/* 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 <openssl/asn1.h>
#include <openssl/buffer.h>
#include <openssl/objects.h>
static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
int indent);
static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
int offset, int depth, int indent, int dump);
static int
asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
int indent)
{
char str[128];
const char *p;
if (constructed & V_ASN1_CONSTRUCTED)
p="cons: ";
else
p="prim: ";
if (BIO_write(bp, p, 6) < 6)
goto err;
if (!BIO_indent(bp, indent, 128))
goto err;
p = str;
if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
snprintf(str, sizeof str, "priv [ %d ] ", tag);
else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
snprintf(str, sizeof str, "cont [ %d ]", tag);
else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
snprintf(str, sizeof str, "appl [ %d ]", tag);
else if (tag > 30)
snprintf(str, sizeof str, "<ASN1 %d>", tag);
else
p = ASN1_tag2str(tag);
if (BIO_printf(bp, "%-18s", p) <= 0)
goto err;
return (1);
err:
return (0);
}
int
ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent)
{
return (asn1_parse2(bp, &pp, len, 0, 0, indent, 0));
}
LCRYPTO_ALIAS(ASN1_parse);
int
ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent, int dump)
{
return (asn1_parse2(bp, &pp, len, 0, 0, indent, dump));
}
LCRYPTO_ALIAS(ASN1_parse_dump);
static int
asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offset,
int depth, int indent, int dump)
{
const unsigned char *p, *ep, *tot, *op, *opp;
long len;
int tag, xclass, ret = 0;
int nl, hl, j, r;
ASN1_OBJECT *o = NULL;
ASN1_OCTET_STRING *os = NULL;
ASN1_INTEGER *ai = NULL;
ASN1_ENUMERATED *ae = NULL;
/* ASN1_BMPSTRING *bmp=NULL;*/
int dump_indent;
dump_indent = 6; /* Because we know BIO_dump_indent() */
p = *pp;
tot = p + length;
op = p - 1;
if (depth > 128) {
BIO_printf(bp, "Max depth exceeded\n");
goto end;
}
while ((p < tot) && (op < p)) {
op = p;
j = ASN1_get_object(&p, &len, &tag, &xclass, length);
if (j & 0x80) {
if (BIO_write(bp, "Error in encoding\n", 18) <= 0)
goto end;
ret = 0;
goto end;
}
hl = (p - op);
length -= hl;
/* if j == 0x21 it is a constructed indefinite length object */
if (BIO_printf(bp, "%5ld:", (long)offset +
(long)(op - *pp)) <= 0)
goto end;
if (j != (V_ASN1_CONSTRUCTED | 1)) {
if (BIO_printf(bp, "d=%-2d hl=%ld l=%4ld ",
depth, (long)hl, len) <= 0)
goto end;
} else {
if (BIO_printf(bp, "d=%-2d hl=%ld l=inf ",
depth, (long)hl) <= 0)
goto end;
}
if (!asn1_print_info(bp, tag, xclass, j, (indent) ? depth : 0))
goto end;
if (j & V_ASN1_CONSTRUCTED) {
ep = p + len;
if (BIO_write(bp, "\n", 1) <= 0)
goto end;
if (len > length) {
BIO_printf(bp, "length is greater than %ld\n",
length);
ret = 0;
goto end;
}
if ((j == 0x21) && (len == 0)) {
for (;;) {
r = asn1_parse2(bp, &p, (long)(tot - p),
offset + (p - *pp), depth + 1,
indent, dump);
if (r == 0) {
ret = 0;
goto end;
}
if ((r == 2) || (p >= tot)) {
len = (long)(p - ep);
break;
}
}
} else {
while (p < ep) {
r = asn1_parse2(bp, &p, (long)(ep - p),
offset + (p - *pp), depth + 1,
indent, dump);
if (r == 0) {
ret = 0;
goto end;
}
}
}
} else if (xclass != 0) {
p += len;
if (BIO_write(bp, "\n", 1) <= 0)
goto end;
} else {
nl = 0;
if ((tag == V_ASN1_PRINTABLESTRING) ||
(tag == V_ASN1_T61STRING) ||
(tag == V_ASN1_IA5STRING) ||
(tag == V_ASN1_VISIBLESTRING) ||
(tag == V_ASN1_NUMERICSTRING) ||
(tag == V_ASN1_UTF8STRING) ||
(tag == V_ASN1_UTCTIME) ||
(tag == V_ASN1_GENERALIZEDTIME)) {
if (BIO_write(bp, ":", 1) <= 0)
goto end;
if ((len > 0) &&
BIO_write(bp, (const char *)p, (int)len) !=
(int)len)
goto end;
} else if (tag == V_ASN1_OBJECT) {
opp = op;
if (d2i_ASN1_OBJECT(&o, &opp, len + hl) !=
NULL) {
if (BIO_write(bp, ":", 1) <= 0)
goto end;
i2a_ASN1_OBJECT(bp, o);
} else {
if (BIO_write(bp, ":BAD OBJECT",
11) <= 0)
goto end;
}
} else if (tag == V_ASN1_BOOLEAN) {
if (len == 1 && p < tot) {
BIO_printf(bp, ":%u", p[0]);
} else {
if (BIO_write(bp, "Bad boolean\n",
12) <= 0)
goto end;
}
} else if (tag == V_ASN1_BMPSTRING) {
/* do the BMP thang */
} else if (tag == V_ASN1_OCTET_STRING) {
int i, printable = 1;
opp = op;
os = d2i_ASN1_OCTET_STRING(NULL, &opp, len + hl);
if (os != NULL && os->length > 0) {
opp = os->data;
/* testing whether the octet string is
* printable */
for (i = 0; i < os->length; i++) {
if (((opp[i] < ' ') &&
(opp[i] != '\n') &&
(opp[i] != '\r') &&
(opp[i] != '\t')) ||
(opp[i] > '~')) {
printable = 0;
break;
}
}
if (printable) {
/* printable string */
if (BIO_write(bp, ":", 1) <= 0)
goto end;
if (BIO_write(bp, (const char *)opp,
os->length) <= 0)
goto end;
} else if (!dump) {
/* not printable => print octet string
* as hex dump */
if (BIO_write(bp, "[HEX DUMP]:", 11) <= 0)
goto end;
for (i = 0; i < os->length; i++) {
if (BIO_printf(bp,
"%02X", opp[i]) <= 0)
goto end;
}
} else {
/* print the normal dump */
if (!nl) {
if (BIO_write(bp, "\n", 1) <= 0)
goto end;
}
if (BIO_dump_indent(bp,
(const char *)opp,
((dump == -1 || dump >
os->length) ? os->length : dump),
dump_indent) <= 0)
goto end;
nl = 1;
}
}
ASN1_OCTET_STRING_free(os);
os = NULL;
} else if (tag == V_ASN1_INTEGER) {
int i;
opp = op;
ai = d2i_ASN1_INTEGER(NULL, &opp, len + hl);
if (ai != NULL) {
if (BIO_write(bp, ":", 1) <= 0)
goto end;
if (ai->type == V_ASN1_NEG_INTEGER)
if (BIO_write(bp, "-", 1) <= 0)
goto end;
for (i = 0; i < ai->length; i++) {
if (BIO_printf(bp, "%02X",
ai->data[i]) <= 0)
goto end;
}
if (ai->length == 0) {
if (BIO_write(bp, "00", 2) <= 0)
goto end;
}
} else {
if (BIO_write(bp, "BAD INTEGER", 11) <= 0)
goto end;
}
ASN1_INTEGER_free(ai);
ai = NULL;
} else if (tag == V_ASN1_ENUMERATED) {
int i;
opp = op;
ae = d2i_ASN1_ENUMERATED(NULL, &opp, len + hl);
if (ae != NULL) {
if (BIO_write(bp, ":", 1) <= 0)
goto end;
if (ae->type == V_ASN1_NEG_ENUMERATED)
if (BIO_write(bp, "-", 1) <= 0)
goto end;
for (i = 0; i < ae->length; i++) {
if (BIO_printf(bp, "%02X",
ae->data[i]) <= 0)
goto end;
}
if (ae->length == 0) {
if (BIO_write(bp, "00", 2) <= 0)
goto end;
}
} else {
if (BIO_write(bp, "BAD ENUMERATED", 14) <= 0)
goto end;
}
ASN1_ENUMERATED_free(ae);
ae = NULL;
} else if (len > 0 && dump) {
if (!nl) {
if (BIO_write(bp, "\n", 1) <= 0)
goto end;
}
if (BIO_dump_indent(bp, (const char *)p,
((dump == -1 || dump > len) ? len : dump),
dump_indent) <= 0)
goto end;
nl = 1;
}
if (!nl) {
if (BIO_write(bp, "\n", 1) <= 0)
goto end;
}
p += len;
if ((tag == V_ASN1_EOC) && (xclass == 0)) {
ret = 2; /* End of sequence */
goto end;
}
}
length -= len;
}
ret = 1;
end:
if (o != NULL)
ASN1_OBJECT_free(o);
ASN1_OCTET_STRING_free(os);
ASN1_INTEGER_free(ai);
ASN1_ENUMERATED_free(ae);
*pp = p;
return (ret);
}

305
crypto/asn1/asn1_types.c Normal file
View File

@@ -0,0 +1,305 @@
/* $OpenBSD: asn1_types.c,v 1.3 2023/07/05 21:23:36 beck Exp $ */
/*
* Copyright (c) 2021 Joel Sing <jsing@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stddef.h>
#include <openssl/asn1.h>
#define ASN1_ENCODING_CONSTRUCTED_ONLY 1
#define ASN1_ENCODING_PRIMITIVE_ONLY 2
struct asn1_type {
const char *name;
uint32_t bit_value;
int char_width;
int encoding;
};
/*
* Universal class tag types - ITU X.680.
*/
static const struct asn1_type asn1_types[31] = {
[0] = {
/* Tag 0 (0x00) - Reserved for use by encoding rules */
.name = "EOC",
.bit_value = 0,
.char_width = -1,
},
[1] = {
/* Tag 1 (0x01) - Boolean */
.name = "BOOLEAN",
.bit_value = 0,
.char_width = -1,
.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
},
[2] = {
/* Tag 2 (0x02) - Integer */
.name = "INTEGER",
.bit_value = 0,
.char_width = -1,
.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
},
[3] = {
/* Tag 3 (0x03) - BitString */
.name = "BIT STRING",
.bit_value = B_ASN1_BIT_STRING,
.char_width = -1,
},
[4] = {
/* Tag 4 (0x04) - OctetString */
.name = "OCTET STRING",
.bit_value = B_ASN1_OCTET_STRING,
.char_width = -1,
},
[5] = {
/* Tag 5 (0x05) - Null */
.name = "NULL",
.bit_value = 0,
.char_width = -1,
.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
},
[6] = {
/* Tag 6 (0x06) - Object Identifier */
.name = "OBJECT",
.bit_value = 0,
.char_width = -1,
.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
},
[7] = {
/* Tag 7 (0x07) - Object Descriptor */
.name = "OBJECT DESCRIPTOR",
.bit_value = B_ASN1_UNKNOWN,
.char_width = -1,
},
[8] = {
/* Tag 8 (0x08) - External */
.name = "EXTERNAL",
.bit_value = B_ASN1_UNKNOWN,
.char_width = -1,
},
[9] = {
/* Tag 9 (0x09) - Real */
.name = "REAL",
.bit_value = B_ASN1_UNKNOWN,
.char_width = -1,
.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
},
[10] = {
/* Tag 10 (0x0a) - Enumerated */
.name = "ENUMERATED",
.bit_value = B_ASN1_UNKNOWN,
.char_width = -1,
.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
},
[11] = {
/* Tag 11 (0x0b) - Embedded PDV */
.name = "<ASN1 11 EMBEDDED PDV>",
.bit_value = B_ASN1_UNKNOWN,
.char_width = -1,
},
[12] = {
/* Tag 12 (0x0c) - UTF8String */
.name = "UTF8STRING",
.bit_value = B_ASN1_UTF8STRING,
.char_width = 0,
},
[13] = {
/* Tag 13 (0x0d) - Relative Object Identifier */
.name = "<ASN1 13 RELATIVE OID>",
.bit_value = B_ASN1_UNKNOWN,
.char_width = -1,
.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
},
[14] = {
/* Tag 14 (0x0e) - Time */
.name = "<ASN1 14 TIME>",
.bit_value = B_ASN1_UNKNOWN,
.char_width = -1,
.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
},
[15] = {
/* Tag 15 (0x0f) - Reserved */
.name = "<ASN1 15 RESERVED>",
.bit_value = B_ASN1_UNKNOWN,
.char_width = -1,
},
[16] = {
/* Tag 16 (0x10)- Sequence */
.name = "SEQUENCE",
.bit_value = B_ASN1_SEQUENCE,
.char_width = -1,
.encoding = ASN1_ENCODING_CONSTRUCTED_ONLY,
},
[17] = {
/* Tag 17 (0x11) - Set */
.name = "SET",
.bit_value = 0,
.char_width = -1,
.encoding = ASN1_ENCODING_CONSTRUCTED_ONLY,
},
[18] = {
/* Tag 18 (0x12) - NumericString */
.name = "NUMERICSTRING",
.bit_value = B_ASN1_NUMERICSTRING,
.char_width = -1,
},
[19] = {
/* Tag 19 (0x13) - PrintableString */
.name = "PRINTABLESTRING",
.bit_value = B_ASN1_PRINTABLESTRING,
.char_width = 1,
},
[20] = {
/* Tag 20 (0x14) - TeletexString (T61String) */
.name = "T61STRING",
.bit_value = B_ASN1_T61STRING,
.char_width = 1,
},
[21] = {
/* Tag 21 (0x15) - VideotexString */
.name = "VIDEOTEXSTRING",
.bit_value = B_ASN1_VIDEOTEXSTRING,
.char_width = -1,
},
[22] = {
/* Tag 22 (0x16) - IA5String */
.name = "IA5STRING",
.bit_value = B_ASN1_IA5STRING,
.char_width = 1,
},
[23] = {
/* Tag 23 (0x17) - UTCTime */
.name = "UTCTIME",
.bit_value = B_ASN1_UTCTIME,
.char_width = 1,
},
[24] = {
/* Tag 24 (0x18) - GeneralizedTime */
.name = "GENERALIZEDTIME",
.bit_value = B_ASN1_GENERALIZEDTIME,
.char_width = 1,
},
[25] = {
/* Tag 25 (0x19) - GraphicString */
.name = "GRAPHICSTRING",
.bit_value = B_ASN1_GRAPHICSTRING,
.char_width = -1,
},
[26] = {
/* Tag 26 (0x1a) - VisibleString (ISO646String) */
.name = "VISIBLESTRING",
.bit_value = B_ASN1_ISO64STRING,
.char_width = 1,
},
[27] = {
/* Tag 27 (0x1b) - GeneralString */
.name = "GENERALSTRING",
.bit_value = B_ASN1_GENERALSTRING,
.char_width = -1,
},
[28] = {
/* Tag 28 (0x1c) - UniversalString */
.name = "UNIVERSALSTRING",
.bit_value = B_ASN1_UNIVERSALSTRING,
.char_width = 4,
},
[29] = {
/* Tag 29 (0x1d) - Unallocated */
.name = "<ASN1 29>",
.bit_value = B_ASN1_UNKNOWN,
.char_width = -1,
},
[30] = {
/* Tag 30 (0x1e) - BMPString */
.name = "BMPSTRING",
.bit_value = B_ASN1_BMPSTRING,
.char_width = 2,
},
};
static const struct asn1_type *
asn1_type_by_tag(int tag)
{
if (tag < 0 || tag > 30)
return NULL;
return &asn1_types[tag];
}
int
asn1_must_be_constructed(int tag)
{
const struct asn1_type *at;
if (tag == V_ASN1_NEG_INTEGER || tag == V_ASN1_NEG_ENUMERATED)
tag &= ~V_ASN1_NEG;
if ((at = asn1_type_by_tag(tag)) != NULL)
return at->encoding == ASN1_ENCODING_CONSTRUCTED_ONLY;
return 0;
}
int
asn1_must_be_primitive(int tag)
{
const struct asn1_type *at;
if (tag == V_ASN1_NEG_INTEGER || tag == V_ASN1_NEG_ENUMERATED)
tag &= ~V_ASN1_NEG;
if ((at = asn1_type_by_tag(tag)) != NULL)
return at->encoding == ASN1_ENCODING_PRIMITIVE_ONLY;
return 0;
}
int
asn1_tag2charwidth(int tag)
{
const struct asn1_type *at;
if ((at = asn1_type_by_tag(tag)) != NULL)
return at->char_width;
return -1;
}
unsigned long
ASN1_tag2bit(int tag)
{
const struct asn1_type *at;
if ((at = asn1_type_by_tag(tag)) != NULL)
return (unsigned long)at->bit_value;
return 0;
}
LCRYPTO_ALIAS(ASN1_tag2bit);
const char *
ASN1_tag2str(int tag)
{
const struct asn1_type *at;
if (tag == V_ASN1_NEG_INTEGER || tag == V_ASN1_NEG_ENUMERATED)
tag &= ~V_ASN1_NEG;
if ((at = asn1_type_by_tag(tag)) != NULL)
return at->name;
return "(unknown)";
}
LCRYPTO_ALIAS(ASN1_tag2str);

1013
crypto/asn1/asn_mime.c Normal file

File diff suppressed because it is too large Load Diff

161
crypto/asn1/asn_moid.c Normal file
View File

@@ -0,0 +1,161 @@
/* $OpenBSD: asn_moid.c,v 1.16 2023/07/05 21:23:36 beck Exp $ */
/* Written by Stephen Henson (steve@openssl.org) for the OpenSSL
* project 2001.
*/
/* ====================================================================
* Copyright (c) 2001-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 <ctype.h>
#include <stdio.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/conf.h>
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include "asn1_local.h"
/* Simple ASN1 OID module: add all objects in a given section */
static int do_create(char *value, char *name);
static int
oid_module_init(CONF_IMODULE *md, const CONF *cnf)
{
int i;
const char *oid_section;
STACK_OF(CONF_VALUE) *sktmp;
CONF_VALUE *oval;
oid_section = CONF_imodule_get_value(md);
if (!(sktmp = NCONF_get_section(cnf, oid_section))) {
ASN1error(ASN1_R_ERROR_LOADING_SECTION);
return 0;
}
for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
oval = sk_CONF_VALUE_value(sktmp, i);
if (!do_create(oval->value, oval->name)) {
ASN1error(ASN1_R_ADDING_OBJECT);
return 0;
}
}
return 1;
}
static void
oid_module_finish(CONF_IMODULE *md)
{
OBJ_cleanup();
}
void
ASN1_add_oid_module(void)
{
CONF_module_add("oid_section", oid_module_init, oid_module_finish);
}
LCRYPTO_ALIAS(ASN1_add_oid_module);
/* Create an OID based on a name value pair. Accept two formats.
* shortname = 1.2.3.4
* shortname = some long name, 1.2.3.4
*/
static int
do_create(char *value, char *name)
{
int nid;
ASN1_OBJECT *oid;
char *ln, *ostr, *p, *lntmp;
p = strrchr(value, ',');
if (!p) {
ln = name;
ostr = value;
} else {
ln = NULL;
ostr = p + 1;
if (!*ostr)
return 0;
while (isspace((unsigned char)*ostr))
ostr++;
}
nid = OBJ_create(ostr, name, ln);
if (nid == NID_undef)
return 0;
if (p) {
ln = value;
while (isspace((unsigned char)*ln))
ln++;
p--;
while (isspace((unsigned char)*p)) {
if (p == ln)
return 0;
p--;
}
p++;
lntmp = malloc((p - ln) + 1);
if (lntmp == NULL)
return 0;
memcpy(lntmp, ln, p - ln);
lntmp[p - ln] = 0;
oid = OBJ_nid2obj(nid);
oid->ln = lntmp;
}
return 1;
}

453
crypto/asn1/bio_asn1.c Normal file
View File

@@ -0,0 +1,453 @@
/* $OpenBSD: bio_asn1.c,v 1.23 2023/07/28 09:58:30 tb Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project.
*/
/* ====================================================================
* 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).
*
*/
/* Experimental ASN1 BIO. When written through the data is converted
* to an ASN1 string type: default is OCTET STRING. Additional functions
* can be provided to add prefix and suffix data.
*/
#include <stdlib.h>
#include <string.h>
#include <openssl/bio.h>
#include <openssl/asn1.h>
#include "bio_local.h"
#define BIO_C_SET_PREFIX 149
#define BIO_C_SET_SUFFIX 151
/* Must be large enough for biggest tag+length */
#define DEFAULT_ASN1_BUF_SIZE 20
typedef enum {
ASN1_STATE_START,
ASN1_STATE_PRE_COPY,
ASN1_STATE_HEADER,
ASN1_STATE_HEADER_COPY,
ASN1_STATE_DATA_COPY,
ASN1_STATE_POST_COPY,
ASN1_STATE_DONE
} asn1_bio_state_t;
typedef struct BIO_ASN1_EX_FUNCS_st {
asn1_ps_func *ex_func;
asn1_ps_func *ex_free_func;
} BIO_ASN1_EX_FUNCS;
typedef struct BIO_ASN1_BUF_CTX_t {
/* Internal state */
asn1_bio_state_t state;
/* Internal buffer */
unsigned char *buf;
/* Size of buffer */
int bufsize;
/* Current position in buffer */
int bufpos;
/* Current buffer length */
int buflen;
/* Amount of data to copy */
int copylen;
/* Class and tag to use */
int asn1_class, asn1_tag;
asn1_ps_func *prefix, *prefix_free, *suffix, *suffix_free;
/* Extra buffer for prefix and suffix data */
unsigned char *ex_buf;
int ex_len;
int ex_pos;
void *ex_arg;
} BIO_ASN1_BUF_CTX;
static int asn1_bio_write(BIO *h, const char *buf, int num);
static int asn1_bio_read(BIO *h, char *buf, int size);
static int asn1_bio_puts(BIO *h, const char *str);
static int asn1_bio_gets(BIO *h, char *str, int size);
static long asn1_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
static int asn1_bio_new(BIO *h);
static int asn1_bio_free(BIO *data);
static long asn1_bio_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
asn1_ps_func *cleanup, asn1_bio_state_t next);
static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
asn1_ps_func *setup, asn1_bio_state_t ex_state,
asn1_bio_state_t other_state);
static const BIO_METHOD methods_asn1 = {
.type = BIO_TYPE_ASN1,
.name = "asn1",
.bwrite = asn1_bio_write,
.bread = asn1_bio_read,
.bputs = asn1_bio_puts,
.bgets = asn1_bio_gets,
.ctrl = asn1_bio_ctrl,
.create = asn1_bio_new,
.destroy = asn1_bio_free,
.callback_ctrl = asn1_bio_callback_ctrl
};
const BIO_METHOD *
BIO_f_asn1(void)
{
return (&methods_asn1);
}
static int
asn1_bio_new(BIO *b)
{
BIO_ASN1_BUF_CTX *ctx;
if ((ctx = calloc(1, sizeof(*ctx))) == NULL)
return 0;
if ((ctx->buf = malloc(DEFAULT_ASN1_BUF_SIZE)) == NULL) {
free(ctx);
return 0;
}
ctx->bufsize = DEFAULT_ASN1_BUF_SIZE;
ctx->asn1_class = V_ASN1_UNIVERSAL;
ctx->asn1_tag = V_ASN1_OCTET_STRING;
ctx->state = ASN1_STATE_START;
b->init = 1;
b->ptr = ctx;
b->flags = 0;
return 1;
}
static int
asn1_bio_free(BIO *b)
{
BIO_ASN1_BUF_CTX *ctx = b->ptr;
if (ctx == NULL)
return 0;
if (ctx->prefix_free != NULL)
ctx->prefix_free(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg);
if (ctx->suffix_free != NULL)
ctx->suffix_free(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg);
free(ctx->buf);
free(ctx);
b->init = 0;
b->ptr = NULL;
b->flags = 0;
return 1;
}
static int
asn1_bio_write(BIO *b, const char *in , int inl)
{
BIO_ASN1_BUF_CTX *ctx;
int wrmax, wrlen, ret, buflen;
unsigned char *p;
if (!in || (inl < 0) || (b->next_bio == NULL))
return 0;
if ((ctx = b->ptr) == NULL)
return 0;
wrlen = 0;
ret = -1;
for (;;) {
switch (ctx->state) {
/* Setup prefix data, call it */
case ASN1_STATE_START:
if (!asn1_bio_setup_ex(b, ctx, ctx->prefix,
ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER))
return 0;
break;
/* Copy any pre data first */
case ASN1_STATE_PRE_COPY:
ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free,
ASN1_STATE_HEADER);
if (ret <= 0)
goto done;
break;
case ASN1_STATE_HEADER:
buflen = ASN1_object_size(0, inl, ctx->asn1_tag) - inl;
if (buflen <= 0 || buflen > ctx->bufsize)
return -1;
ctx->buflen = buflen;
p = ctx->buf;
ASN1_put_object(&p, 0, inl,
ctx->asn1_tag, ctx->asn1_class);
ctx->copylen = inl;
ctx->state = ASN1_STATE_HEADER_COPY;
break;
case ASN1_STATE_HEADER_COPY:
ret = BIO_write(b->next_bio,
ctx->buf + ctx->bufpos, ctx->buflen);
if (ret <= 0)
goto done;
ctx->buflen -= ret;
if (ctx->buflen)
ctx->bufpos += ret;
else {
ctx->bufpos = 0;
ctx->state = ASN1_STATE_DATA_COPY;
}
break;
case ASN1_STATE_DATA_COPY:
if (inl > ctx->copylen)
wrmax = ctx->copylen;
else
wrmax = inl;
ret = BIO_write(b->next_bio, in, wrmax);
if (ret <= 0)
goto done;
wrlen += ret;
ctx->copylen -= ret;
in += ret;
inl -= ret;
if (ctx->copylen == 0)
ctx->state = ASN1_STATE_HEADER;
if (inl == 0)
goto done;
break;
default:
BIO_clear_retry_flags(b);
return 0;
}
}
done:
BIO_clear_retry_flags(b);
BIO_copy_next_retry(b);
return (wrlen > 0) ? wrlen : ret;
}
static int
asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx, asn1_ps_func *cleanup,
asn1_bio_state_t next)
{
int ret;
if (ctx->ex_len <= 0)
return 1;
for (;;) {
ret = BIO_write(b->next_bio, ctx->ex_buf + ctx->ex_pos,
ctx->ex_len);
if (ret <= 0)
break;
ctx->ex_len -= ret;
if (ctx->ex_len > 0)
ctx->ex_pos += ret;
else {
if (cleanup)
cleanup(b, &ctx->ex_buf, &ctx->ex_len,
&ctx->ex_arg);
ctx->state = next;
ctx->ex_pos = 0;
break;
}
}
return ret;
}
static int
asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx, asn1_ps_func *setup,
asn1_bio_state_t ex_state, asn1_bio_state_t other_state)
{
if (setup && !setup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg)) {
BIO_clear_retry_flags(b);
return 0;
}
if (ctx->ex_len > 0)
ctx->state = ex_state;
else
ctx->state = other_state;
return 1;
}
static int
asn1_bio_read(BIO *b, char *in , int inl)
{
if (!b->next_bio)
return 0;
return BIO_read(b->next_bio, in , inl);
}
static int
asn1_bio_puts(BIO *b, const char *str)
{
return asn1_bio_write(b, str, strlen(str));
}
static int
asn1_bio_gets(BIO *b, char *str, int size)
{
if (!b->next_bio)
return 0;
return BIO_gets(b->next_bio, str , size);
}
static long
asn1_bio_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
{
if (b->next_bio == NULL)
return (0);
return BIO_callback_ctrl(b->next_bio, cmd, fp);
}
static long
asn1_bio_ctrl(BIO *b, int cmd, long arg1, void *arg2)
{
BIO_ASN1_BUF_CTX *ctx;
BIO_ASN1_EX_FUNCS *ex_func;
long ret = 1;
if ((ctx = b->ptr) == NULL)
return 0;
switch (cmd) {
case BIO_C_SET_PREFIX:
ex_func = arg2;
ctx->prefix = ex_func->ex_func;
ctx->prefix_free = ex_func->ex_free_func;
break;
case BIO_C_SET_SUFFIX:
ex_func = arg2;
ctx->suffix = ex_func->ex_func;
ctx->suffix_free = ex_func->ex_free_func;
break;
case BIO_C_SET_EX_ARG:
ctx->ex_arg = arg2;
break;
case BIO_C_GET_EX_ARG:
*(void **)arg2 = ctx->ex_arg;
break;
case BIO_CTRL_FLUSH:
if (!b->next_bio)
return 0;
/* Call post function if possible */
if (ctx->state == ASN1_STATE_HEADER) {
if (!asn1_bio_setup_ex(b, ctx, ctx->suffix,
ASN1_STATE_POST_COPY, ASN1_STATE_DONE))
return 0;
}
if (ctx->state == ASN1_STATE_POST_COPY) {
ret = asn1_bio_flush_ex(b, ctx, ctx->suffix_free,
ASN1_STATE_DONE);
if (ret <= 0)
return ret;
}
if (ctx->state == ASN1_STATE_DONE)
return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
else {
BIO_clear_retry_flags(b);
return 0;
}
break;
default:
if (!b->next_bio)
return 0;
return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
}
return ret;
}
static int
asn1_bio_set_ex(BIO *b, int cmd, asn1_ps_func *ex_func, asn1_ps_func
*ex_free_func)
{
BIO_ASN1_EX_FUNCS extmp;
extmp.ex_func = ex_func;
extmp.ex_free_func = ex_free_func;
return BIO_ctrl(b, cmd, 0, &extmp);
}
int
BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix, asn1_ps_func *prefix_free)
{
return asn1_bio_set_ex(b, BIO_C_SET_PREFIX, prefix, prefix_free);
}
int
BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix, asn1_ps_func *suffix_free)
{
return asn1_bio_set_ex(b, BIO_C_SET_SUFFIX, suffix, suffix_free);
}

270
crypto/asn1/bio_ndef.c Normal file
View File

@@ -0,0 +1,270 @@
/* $OpenBSD: bio_ndef.c,v 1.24 2023/07/28 09:58:30 tb Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project.
*/
/* ====================================================================
* Copyright (c) 2008 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.
* ====================================================================
*
*/
#include <stdio.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include "asn1_local.h"
int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix, asn1_ps_func *prefix_free);
int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix, asn1_ps_func *suffix_free);
/* Experimental NDEF ASN1 BIO support routines */
/* The usage is quite simple, initialize an ASN1 structure,
* get a BIO from it then any data written through the BIO
* will end up translated to approptiate format on the fly.
* The data is streamed out and does *not* need to be
* all held in memory at once.
*
* When the BIO is flushed the output is finalized and any
* signatures etc written out.
*
* The BIO is a 'proper' BIO and can handle non blocking I/O
* correctly.
*
* The usage is simple. The implementation is *not*...
*/
/* BIO support data stored in the ASN1 BIO ex_arg */
typedef struct ndef_aux_st {
/* ASN1 structure this BIO refers to */
ASN1_VALUE *val;
const ASN1_ITEM *it;
/* Top of the BIO chain */
BIO *ndef_bio;
/* Output BIO */
BIO *out;
/* Boundary where content is inserted */
unsigned char **boundary;
/* DER buffer start */
unsigned char *derbuf;
} NDEF_SUPPORT;
static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg);
static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg);
BIO *
BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it)
{
NDEF_SUPPORT *ndef_aux = NULL;
BIO *asn_bio = NULL, *pop_bio = NULL;
const ASN1_AUX *aux = it->funcs;
ASN1_STREAM_ARG sarg;
if (aux == NULL || aux->asn1_cb == NULL) {
ASN1error(ASN1_R_STREAMING_NOT_SUPPORTED);
goto err;
}
if ((asn_bio = BIO_new(BIO_f_asn1())) == NULL)
goto err;
if (BIO_push(asn_bio, out) == NULL)
goto err;
pop_bio = asn_bio;
/*
* Set up prefix and suffix handlers first. This ensures that ndef_aux
* is freed as part of asn_bio once it is the asn_bio's ex_arg.
*/
if (BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free) <= 0)
goto err;
if (BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free) <= 0)
goto err;
/*
* Allocate early to avoid the tricky cleanup after the asn1_cb().
* Ownership of ndef_aux is transferred to asn_bio in BIO_ctrl().
* Keep a reference to populate it after callback success.
*/
if ((ndef_aux = calloc(1, sizeof(*ndef_aux))) == NULL)
goto err;
if (BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux) <= 0) {
free(ndef_aux);
goto err;
}
/*
* The callback prepends BIOs to the chain starting at asn_bio for
* digest, cipher, etc. The resulting chain starts at sarg.ndef_bio.
*/
sarg.out = asn_bio;
sarg.ndef_bio = NULL;
sarg.boundary = NULL;
if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0)
goto err;
ndef_aux->val = val;
ndef_aux->it = it;
ndef_aux->ndef_bio = sarg.ndef_bio;
ndef_aux->boundary = sarg.boundary;
ndef_aux->out = asn_bio;
return sarg.ndef_bio;
err:
BIO_pop(pop_bio);
BIO_free(asn_bio);
return NULL;
}
static int
ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
{
NDEF_SUPPORT *ndef_aux;
unsigned char *p = NULL;
int derlen;
if (!parg)
return 0;
ndef_aux = *(NDEF_SUPPORT **)parg;
if ((derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it)) <= 0)
return 0;
ndef_aux->derbuf = p;
*pbuf = p;
if (*ndef_aux->boundary == NULL)
return 0;
*plen = *ndef_aux->boundary - *pbuf;
return 1;
}
static int
ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg)
{
NDEF_SUPPORT **pndef_aux = parg;
if (pndef_aux == NULL || *pndef_aux == NULL)
return 0;
free((*pndef_aux)->derbuf);
(*pndef_aux)->derbuf = NULL;
*pbuf = NULL;
*plen = 0;
return 1;
}
static int
ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg)
{
NDEF_SUPPORT **pndef_aux = parg;
/* Ensure ndef_prefix_free() won't fail, so we won't leak *pndef_aux. */
if (pndef_aux == NULL || *pndef_aux == NULL)
return 0;
if (!ndef_prefix_free(b, pbuf, plen, parg))
return 0;
free(*pndef_aux);
*pndef_aux = NULL;
return 1;
}
static int
ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
{
NDEF_SUPPORT *ndef_aux;
unsigned char *p = NULL;
int derlen;
const ASN1_AUX *aux;
ASN1_STREAM_ARG sarg;
if (!parg)
return 0;
ndef_aux = *(NDEF_SUPPORT **)parg;
aux = ndef_aux->it->funcs;
/* Finalize structures */
sarg.ndef_bio = ndef_aux->ndef_bio;
sarg.out = ndef_aux->out;
sarg.boundary = ndef_aux->boundary;
if (aux->asn1_cb(ASN1_OP_STREAM_POST,
&ndef_aux->val, ndef_aux->it, &sarg) <= 0)
return 0;
if ((derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it)) <= 0)
return 0;
ndef_aux->derbuf = p;
*pbuf = p;
if (*ndef_aux->boundary == NULL)
return 0;
*pbuf = *ndef_aux->boundary;
*plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf);
return 1;
}

19
crypto/asn1/charmap.h Normal file
View File

@@ -0,0 +1,19 @@
/* $OpenBSD: charmap.h,v 1.5 2016/12/21 15:49:29 jsing Exp $ */
/* Auto generated with chartype.pl script.
* Mask of various character properties
*/
__BEGIN_HIDDEN_DECLS
static const unsigned char char_type[] = {
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
120, 0, 1, 40, 0, 0, 0, 16, 16, 16, 0, 25, 25, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 9, 9, 16, 9, 16,
0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 1, 0, 0, 0,
0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 2
};
__END_HIDDEN_DECLS

186
crypto/asn1/p5_pbe.c Normal file
View File

@@ -0,0 +1,186 @@
/* $OpenBSD: p5_pbe.c,v 1.25 2023/07/07 19:37:52 beck Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 1999.
*/
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/asn1t.h>
#include <openssl/err.h>
#include <openssl/x509.h>
/* PKCS#5 password based encryption structure */
static const ASN1_TEMPLATE PBEPARAM_seq_tt[] = {
{
.offset = offsetof(PBEPARAM, salt),
.field_name = "salt",
.item = &ASN1_OCTET_STRING_it,
},
{
.offset = offsetof(PBEPARAM, iter),
.field_name = "iter",
.item = &ASN1_INTEGER_it,
},
};
const ASN1_ITEM PBEPARAM_it = {
.itype = ASN1_ITYPE_SEQUENCE,
.utype = V_ASN1_SEQUENCE,
.templates = PBEPARAM_seq_tt,
.tcount = sizeof(PBEPARAM_seq_tt) / sizeof(ASN1_TEMPLATE),
.size = sizeof(PBEPARAM),
.sname = "PBEPARAM",
};
PBEPARAM *
d2i_PBEPARAM(PBEPARAM **a, const unsigned char **in, long len)
{
return (PBEPARAM *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&PBEPARAM_it);
}
int
i2d_PBEPARAM(PBEPARAM *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &PBEPARAM_it);
}
PBEPARAM *
PBEPARAM_new(void)
{
return (PBEPARAM *)ASN1_item_new(&PBEPARAM_it);
}
void
PBEPARAM_free(PBEPARAM *a)
{
ASN1_item_free((ASN1_VALUE *)a, &PBEPARAM_it);
}
/* Set an algorithm identifier for a PKCS#5 PBE algorithm */
int
PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
const unsigned char *salt, int saltlen)
{
PBEPARAM *pbe = NULL;
ASN1_STRING *pbe_str = NULL;
unsigned char *sstr;
pbe = PBEPARAM_new();
if (!pbe) {
ASN1error(ERR_R_MALLOC_FAILURE);
goto err;
}
if (iter <= 0)
iter = PKCS5_DEFAULT_ITER;
if (!ASN1_INTEGER_set(pbe->iter, iter)) {
ASN1error(ERR_R_MALLOC_FAILURE);
goto err;
}
if (!saltlen)
saltlen = PKCS5_SALT_LEN;
if (!ASN1_STRING_set(pbe->salt, NULL, saltlen)) {
ASN1error(ERR_R_MALLOC_FAILURE);
goto err;
}
sstr = ASN1_STRING_data(pbe->salt);
if (salt)
memcpy(sstr, salt, saltlen);
else
arc4random_buf(sstr, saltlen);
if (!ASN1_item_pack(pbe, &PBEPARAM_it, &pbe_str)) {
ASN1error(ERR_R_MALLOC_FAILURE);
goto err;
}
PBEPARAM_free(pbe);
pbe = NULL;
if (X509_ALGOR_set0(algor, OBJ_nid2obj(alg), V_ASN1_SEQUENCE, pbe_str))
return 1;
err:
if (pbe != NULL)
PBEPARAM_free(pbe);
ASN1_STRING_free(pbe_str);
return 0;
}
/* Return an algorithm identifier for a PKCS#5 PBE algorithm */
X509_ALGOR *
PKCS5_pbe_set(int alg, int iter, const unsigned char *salt, int saltlen)
{
X509_ALGOR *ret;
ret = X509_ALGOR_new();
if (!ret) {
ASN1error(ERR_R_MALLOC_FAILURE);
return NULL;
}
if (PKCS5_pbe_set0_algor(ret, alg, iter, salt, saltlen))
return ret;
X509_ALGOR_free(ret);
return NULL;
}

374
crypto/asn1/p5_pbev2.c Normal file
View File

@@ -0,0 +1,374 @@
/* $OpenBSD: p5_pbev2.c,v 1.30 2023/07/07 19:37:52 beck Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 1999-2004.
*/
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/asn1t.h>
#include <openssl/err.h>
#include <openssl/x509.h>
#include "evp_local.h"
/* PKCS#5 v2.0 password based encryption structures */
static const ASN1_TEMPLATE PBE2PARAM_seq_tt[] = {
{
.offset = offsetof(PBE2PARAM, keyfunc),
.field_name = "keyfunc",
.item = &X509_ALGOR_it,
},
{
.offset = offsetof(PBE2PARAM, encryption),
.field_name = "encryption",
.item = &X509_ALGOR_it,
},
};
const ASN1_ITEM PBE2PARAM_it = {
.itype = ASN1_ITYPE_SEQUENCE,
.utype = V_ASN1_SEQUENCE,
.templates = PBE2PARAM_seq_tt,
.tcount = sizeof(PBE2PARAM_seq_tt) / sizeof(ASN1_TEMPLATE),
.size = sizeof(PBE2PARAM),
.sname = "PBE2PARAM",
};
PBE2PARAM *
d2i_PBE2PARAM(PBE2PARAM **a, const unsigned char **in, long len)
{
return (PBE2PARAM *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&PBE2PARAM_it);
}
int
i2d_PBE2PARAM(PBE2PARAM *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &PBE2PARAM_it);
}
PBE2PARAM *
PBE2PARAM_new(void)
{
return (PBE2PARAM *)ASN1_item_new(&PBE2PARAM_it);
}
void
PBE2PARAM_free(PBE2PARAM *a)
{
ASN1_item_free((ASN1_VALUE *)a, &PBE2PARAM_it);
}
static const ASN1_TEMPLATE PBKDF2PARAM_seq_tt[] = {
{
.offset = offsetof(PBKDF2PARAM, salt),
.field_name = "salt",
.item = &ASN1_ANY_it,
},
{
.offset = offsetof(PBKDF2PARAM, iter),
.field_name = "iter",
.item = &ASN1_INTEGER_it,
},
{
.flags = ASN1_TFLG_OPTIONAL,
.offset = offsetof(PBKDF2PARAM, keylength),
.field_name = "keylength",
.item = &ASN1_INTEGER_it,
},
{
.flags = ASN1_TFLG_OPTIONAL,
.offset = offsetof(PBKDF2PARAM, prf),
.field_name = "prf",
.item = &X509_ALGOR_it,
},
};
const ASN1_ITEM PBKDF2PARAM_it = {
.itype = ASN1_ITYPE_SEQUENCE,
.utype = V_ASN1_SEQUENCE,
.templates = PBKDF2PARAM_seq_tt,
.tcount = sizeof(PBKDF2PARAM_seq_tt) / sizeof(ASN1_TEMPLATE),
.size = sizeof(PBKDF2PARAM),
.sname = "PBKDF2PARAM",
};
PBKDF2PARAM *
d2i_PBKDF2PARAM(PBKDF2PARAM **a, const unsigned char **in, long len)
{
return (PBKDF2PARAM *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&PBKDF2PARAM_it);
}
int
i2d_PBKDF2PARAM(PBKDF2PARAM *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &PBKDF2PARAM_it);
}
PBKDF2PARAM *
PBKDF2PARAM_new(void)
{
return (PBKDF2PARAM *)ASN1_item_new(&PBKDF2PARAM_it);
}
void
PBKDF2PARAM_free(PBKDF2PARAM *a)
{
ASN1_item_free((ASN1_VALUE *)a, &PBKDF2PARAM_it);
}
/* Return an algorithm identifier for a PKCS#5 v2.0 PBE algorithm:
* yes I know this is horrible!
*
* Extended version to allow application supplied PRF NID and IV.
*/
X509_ALGOR *
PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter, unsigned char *salt,
int saltlen, unsigned char *aiv, int prf_nid)
{
X509_ALGOR *scheme = NULL, *kalg = NULL, *ret = NULL;
int alg_nid, keylen;
EVP_CIPHER_CTX ctx;
unsigned char iv[EVP_MAX_IV_LENGTH];
PBE2PARAM *pbe2 = NULL;
ASN1_OBJECT *obj;
alg_nid = EVP_CIPHER_type(cipher);
if (alg_nid == NID_undef) {
ASN1error(ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER);
goto err;
}
obj = OBJ_nid2obj(alg_nid);
if (!(pbe2 = PBE2PARAM_new()))
goto merr;
/* Setup the AlgorithmIdentifier for the encryption scheme */
scheme = pbe2->encryption;
scheme->algorithm = obj;
if (!(scheme->parameter = ASN1_TYPE_new()))
goto merr;
/* Create random IV */
if (EVP_CIPHER_iv_length(cipher)) {
if (aiv)
memcpy(iv, aiv, EVP_CIPHER_iv_length(cipher));
else
arc4random_buf(iv, EVP_CIPHER_iv_length(cipher));
}
EVP_CIPHER_CTX_init(&ctx);
/* Dummy cipherinit to just setup the IV, and PRF */
if (!EVP_CipherInit_ex(&ctx, cipher, NULL, NULL, iv, 0))
goto err;
if (EVP_CIPHER_param_to_asn1(&ctx, scheme->parameter) < 0) {
ASN1error(ASN1_R_ERROR_SETTING_CIPHER_PARAMS);
EVP_CIPHER_CTX_cleanup(&ctx);
goto err;
}
/* If prf NID unspecified see if cipher has a preference.
* An error is OK here: just means use default PRF.
*/
if ((prf_nid == -1) &&
EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_PBE_PRF_NID, 0, &prf_nid) <= 0) {
ERR_clear_error();
prf_nid = NID_hmacWithSHA1;
}
EVP_CIPHER_CTX_cleanup(&ctx);
/* If its RC2 then we'd better setup the key length */
if (alg_nid == NID_rc2_cbc)
keylen = EVP_CIPHER_key_length(cipher);
else
keylen = -1;
/* Setup keyfunc */
X509_ALGOR_free(pbe2->keyfunc);
pbe2->keyfunc = PKCS5_pbkdf2_set(iter, salt, saltlen, prf_nid, keylen);
if (!pbe2->keyfunc)
goto merr;
/* Now set up top level AlgorithmIdentifier */
if (!(ret = X509_ALGOR_new()))
goto merr;
if (!(ret->parameter = ASN1_TYPE_new()))
goto merr;
ret->algorithm = OBJ_nid2obj(NID_pbes2);
/* Encode PBE2PARAM into parameter */
if (!ASN1_item_pack(pbe2, &PBE2PARAM_it,
&ret->parameter->value.sequence)) goto merr;
ret->parameter->type = V_ASN1_SEQUENCE;
PBE2PARAM_free(pbe2);
pbe2 = NULL;
return ret;
merr:
ASN1error(ERR_R_MALLOC_FAILURE);
err:
PBE2PARAM_free(pbe2);
/* Note 'scheme' is freed as part of pbe2 */
X509_ALGOR_free(kalg);
X509_ALGOR_free(ret);
return NULL;
}
X509_ALGOR *
PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter, unsigned char *salt,
int saltlen)
{
return PKCS5_pbe2_set_iv(cipher, iter, salt, saltlen, NULL, -1);
}
X509_ALGOR *
PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen, int prf_nid,
int keylen)
{
X509_ALGOR *keyfunc = NULL;
PBKDF2PARAM *kdf = NULL;
ASN1_OCTET_STRING *osalt = NULL;
if (!(kdf = PBKDF2PARAM_new()))
goto merr;
if (!(osalt = ASN1_OCTET_STRING_new()))
goto merr;
kdf->salt->value.octet_string = osalt;
kdf->salt->type = V_ASN1_OCTET_STRING;
if (!saltlen)
saltlen = PKCS5_SALT_LEN;
if (!(osalt->data = malloc (saltlen)))
goto merr;
osalt->length = saltlen;
if (salt)
memcpy (osalt->data, salt, saltlen);
else
arc4random_buf(osalt->data, saltlen);
if (iter <= 0)
iter = PKCS5_DEFAULT_ITER;
if (!ASN1_INTEGER_set(kdf->iter, iter))
goto merr;
/* If have a key len set it up */
if (keylen > 0) {
if (!(kdf->keylength = ASN1_INTEGER_new()))
goto merr;
if (!ASN1_INTEGER_set(kdf->keylength, keylen))
goto merr;
}
/* prf can stay NULL if we are using hmacWithSHA1 */
if (prf_nid > 0 && prf_nid != NID_hmacWithSHA1) {
kdf->prf = X509_ALGOR_new();
if (!kdf->prf)
goto merr;
X509_ALGOR_set0(kdf->prf, OBJ_nid2obj(prf_nid),
V_ASN1_NULL, NULL);
}
/* Finally setup the keyfunc structure */
keyfunc = X509_ALGOR_new();
if (!keyfunc)
goto merr;
keyfunc->algorithm = OBJ_nid2obj(NID_id_pbkdf2);
/* Encode PBKDF2PARAM into parameter of pbe2 */
if (!(keyfunc->parameter = ASN1_TYPE_new()))
goto merr;
if (!ASN1_item_pack(kdf, &PBKDF2PARAM_it,
&keyfunc->parameter->value.sequence))
goto merr;
keyfunc->parameter->type = V_ASN1_SEQUENCE;
PBKDF2PARAM_free(kdf);
return keyfunc;
merr:
ASN1error(ERR_R_MALLOC_FAILURE);
PBKDF2PARAM_free(kdf);
X509_ALGOR_free(keyfunc);
return NULL;
}

187
crypto/asn1/p8_pkey.c Normal file
View File

@@ -0,0 +1,187 @@
/* $OpenBSD: p8_pkey.c,v 1.23 2023/07/07 19:37:52 beck Exp $ */
/* 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 <string.h>
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include "x509_local.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 != NULL)
explicit_bzero(key->pkey->data, key->pkey->length);
}
return 1;
}
static const ASN1_AUX PKCS8_PRIV_KEY_INFO_aux = {
.asn1_cb = pkey_cb,
};
static const ASN1_TEMPLATE PKCS8_PRIV_KEY_INFO_seq_tt[] = {
{
.offset = offsetof(PKCS8_PRIV_KEY_INFO, version),
.field_name = "version",
.item = &ASN1_INTEGER_it,
},
{
.offset = offsetof(PKCS8_PRIV_KEY_INFO, pkeyalg),
.field_name = "pkeyalg",
.item = &X509_ALGOR_it,
},
{
.offset = offsetof(PKCS8_PRIV_KEY_INFO, pkey),
.field_name = "pkey",
.item = &ASN1_OCTET_STRING_it,
},
{
.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SET_OF | ASN1_TFLG_OPTIONAL,
.offset = offsetof(PKCS8_PRIV_KEY_INFO, attributes),
.field_name = "attributes",
.item = &X509_ATTRIBUTE_it,
},
};
const ASN1_ITEM PKCS8_PRIV_KEY_INFO_it = {
.itype = ASN1_ITYPE_SEQUENCE,
.utype = V_ASN1_SEQUENCE,
.templates = PKCS8_PRIV_KEY_INFO_seq_tt,
.tcount = sizeof(PKCS8_PRIV_KEY_INFO_seq_tt) / sizeof(ASN1_TEMPLATE),
.funcs = &PKCS8_PRIV_KEY_INFO_aux,
.size = sizeof(PKCS8_PRIV_KEY_INFO),
.sname = "PKCS8_PRIV_KEY_INFO",
};
PKCS8_PRIV_KEY_INFO *
d2i_PKCS8_PRIV_KEY_INFO(PKCS8_PRIV_KEY_INFO **a, const unsigned char **in, long len)
{
return (PKCS8_PRIV_KEY_INFO *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&PKCS8_PRIV_KEY_INFO_it);
}
int
i2d_PKCS8_PRIV_KEY_INFO(PKCS8_PRIV_KEY_INFO *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &PKCS8_PRIV_KEY_INFO_it);
}
PKCS8_PRIV_KEY_INFO *
PKCS8_PRIV_KEY_INFO_new(void)
{
return (PKCS8_PRIV_KEY_INFO *)ASN1_item_new(&PKCS8_PRIV_KEY_INFO_it);
}
void
PKCS8_PRIV_KEY_INFO_free(PKCS8_PRIV_KEY_INFO *a)
{
ASN1_item_free((ASN1_VALUE *)a, &PKCS8_PRIV_KEY_INFO_it);
}
int
PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj, int version,
int ptype, void *pval, unsigned char *penc, int penclen)
{
if (version >= 0) {
if (!ASN1_INTEGER_set(priv->version, version))
return 0;
}
if (!X509_ALGOR_set0(priv->pkeyalg, aobj, ptype, pval))
return 0;
if (penc != NULL)
ASN1_STRING_set0(priv->pkey, penc, penclen);
return 1;
}
int
PKCS8_pkey_get0(const ASN1_OBJECT **ppkalg, const unsigned char **pk,
int *ppklen, const X509_ALGOR **pa, const PKCS8_PRIV_KEY_INFO *p8)
{
if (ppkalg != NULL)
*ppkalg = p8->pkeyalg->algorithm;
if (pk != NULL) {
*pk = ASN1_STRING_data(p8->pkey);
*ppklen = ASN1_STRING_length(p8->pkey);
}
if (pa != NULL)
*pa = p8->pkeyalg;
return 1;
}
const STACK_OF(X509_ATTRIBUTE) *
PKCS8_pkey_get0_attrs(const PKCS8_PRIV_KEY_INFO *p8)
{
return p8->attributes;
}
int
PKCS8_pkey_add1_attr_by_NID(PKCS8_PRIV_KEY_INFO *p8, int nid, int type,
const unsigned char *bytes, int len)
{
if (X509at_add1_attr_by_NID(&p8->attributes, nid, type, bytes,
len) != NULL)
return 1;
return 0;
}

145
crypto/asn1/t_crl.c Normal file
View File

@@ -0,0 +1,145 @@
/* $OpenBSD: t_crl.c,v 1.23 2023/07/07 19:37:52 beck Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 1999.
*/
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
#include <stdio.h>
#include <limits.h>
#include <openssl/bn.h>
#include <openssl/buffer.h>
#include <openssl/err.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include "x509_local.h"
int
X509_CRL_print_fp(FILE *fp, X509_CRL *x)
{
BIO *b;
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
X509error(ERR_R_BUF_LIB);
return (0);
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
ret = X509_CRL_print(b, x);
BIO_free(b);
return (ret);
}
int
X509_CRL_print(BIO *out, X509_CRL *x)
{
STACK_OF(X509_REVOKED) *rev;
X509_REVOKED *r;
long l;
int i;
char *p;
BIO_printf(out, "Certificate Revocation List (CRL):\n");
l = X509_CRL_get_version(x);
if (l < 0 || l == LONG_MAX)
goto err;
BIO_printf(out, "%8sVersion %lu (0x%lx)\n", "", l + 1, l);
i = OBJ_obj2nid(x->sig_alg->algorithm);
if (X509_signature_print(out, x->sig_alg, NULL) == 0)
goto err;
p = X509_NAME_oneline(X509_CRL_get_issuer(x), NULL, 0);
if (p == NULL)
goto err;
BIO_printf(out, "%8sIssuer: %s\n", "", p);
free(p);
BIO_printf(out, "%8sLast Update: ", "");
ASN1_TIME_print(out, X509_CRL_get_lastUpdate(x));
BIO_printf(out, "\n%8sNext Update: ", "");
if (X509_CRL_get_nextUpdate(x))
ASN1_TIME_print(out, X509_CRL_get_nextUpdate(x));
else
BIO_printf(out, "NONE");
BIO_printf(out, "\n");
X509V3_extensions_print(out, "CRL extensions",
x->crl->extensions, 0, 8);
rev = X509_CRL_get_REVOKED(x);
if (sk_X509_REVOKED_num(rev) > 0)
BIO_printf(out, "Revoked Certificates:\n");
else
BIO_printf(out, "No Revoked Certificates.\n");
for (i = 0; i < sk_X509_REVOKED_num(rev); i++) {
r = sk_X509_REVOKED_value(rev, i);
BIO_printf(out, " Serial Number: ");
i2a_ASN1_INTEGER(out, r->serialNumber);
BIO_printf(out, "\n Revocation Date: ");
ASN1_TIME_print(out, r->revocationDate);
BIO_printf(out, "\n");
X509V3_extensions_print(out, "CRL entry extensions",
r->extensions, 0, 8);
}
if (X509_signature_print(out, x->sig_alg, x->signature) == 0)
goto err;
return 1;
err:
return 0;
}

262
crypto/asn1/t_req.c Normal file
View File

@@ -0,0 +1,262 @@
/* $OpenBSD: t_req.c,v 1.26 2023/07/07 19:37:52 beck Exp $ */
/* 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 <openssl/opensslconf.h>
#include <openssl/bn.h>
#include <openssl/buffer.h>
#include <openssl/err.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#ifndef OPENSSL_NO_DSA
#include <openssl/dsa.h>
#endif
#ifndef OPENSSL_NO_RSA
#include <openssl/rsa.h>
#endif
#include "x509_local.h"
int
X509_REQ_print_fp(FILE *fp, X509_REQ *x)
{
BIO *b;
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
X509error(ERR_R_BUF_LIB);
return (0);
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
ret = X509_REQ_print(b, x);
BIO_free(b);
return (ret);
}
int
X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflags,
unsigned long cflag)
{
unsigned long l;
int i;
const char *neg;
X509_REQ_INFO *ri;
EVP_PKEY *pkey;
STACK_OF(X509_ATTRIBUTE) *sk;
STACK_OF(X509_EXTENSION) *exts = NULL;
char mlch = ' ';
int nmindent = 0;
if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
mlch = '\n';
nmindent = 12;
}
if (nmflags == X509_FLAG_COMPAT)
nmindent = 16;
ri = x->req_info;
if (!(cflag & X509_FLAG_NO_HEADER)) {
if (BIO_write(bp, "Certificate Request:\n", 21) <= 0)
goto err;
if (BIO_write(bp, " Data:\n", 10) <= 0)
goto err;
}
if (!(cflag & X509_FLAG_NO_VERSION)) {
neg = (ri->version->type == V_ASN1_NEG_INTEGER) ? "-" : "";
l = 0;
for (i = 0; i < ri->version->length; i++) {
l <<= 8;
l += ri->version->data[i];
}
if (BIO_printf(bp, "%8sVersion: %s%lu (%s0x%lx)\n", "", neg,
l, neg, l) <= 0)
goto err;
}
if (!(cflag & X509_FLAG_NO_SUBJECT)) {
if (BIO_printf(bp, " Subject:%c", mlch) <= 0)
goto err;
if (X509_NAME_print_ex(bp, ri->subject, nmindent, nmflags) < 0)
goto err;
if (BIO_write(bp, "\n", 1) <= 0)
goto err;
}
if (!(cflag & X509_FLAG_NO_PUBKEY)) {
if (BIO_write(bp, " Subject Public Key Info:\n",
33) <= 0)
goto err;
if (BIO_printf(bp, "%12sPublic Key Algorithm: ", "") <= 0)
goto err;
if (i2a_ASN1_OBJECT(bp, ri->pubkey->algor->algorithm) <= 0)
goto err;
if (BIO_puts(bp, "\n") <= 0)
goto err;
pkey = X509_REQ_get_pubkey(x);
if (pkey == NULL) {
BIO_printf(bp, "%12sUnable to load Public Key\n", "");
ERR_print_errors(bp);
} else {
EVP_PKEY_print_public(bp, pkey, 16, NULL);
EVP_PKEY_free(pkey);
}
}
if (!(cflag & X509_FLAG_NO_ATTRIBUTES)) {
/* may not be */
if (BIO_printf(bp, "%8sAttributes:\n", "") <= 0)
goto err;
sk = x->req_info->attributes;
if (sk_X509_ATTRIBUTE_num(sk) == 0) {
if (BIO_printf(bp, "%12sa0:00\n", "") <= 0)
goto err;
} else {
for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) {
ASN1_TYPE *at;
X509_ATTRIBUTE *a;
ASN1_BIT_STRING *bs = NULL;
int j, type = 0, count = 1, ii = 0;
a = sk_X509_ATTRIBUTE_value(sk, i);
if (X509_REQ_extension_nid(
OBJ_obj2nid(a->object)))
continue;
if (BIO_printf(bp, "%12s", "") <= 0)
goto err;
if ((j = i2a_ASN1_OBJECT(bp, a->object)) > 0) {
ii = 0;
count = sk_ASN1_TYPE_num(a->set);
get_next:
at = sk_ASN1_TYPE_value(a->set, ii);
type = at->type;
bs = at->value.asn1_string;
}
for (j = 25 - j; j > 0; j--)
if (BIO_write(bp, " ", 1) != 1)
goto err;
if (BIO_puts(bp, ":") <= 0)
goto err;
if ((type == V_ASN1_PRINTABLESTRING) ||
(type == V_ASN1_T61STRING) ||
(type == V_ASN1_IA5STRING)) {
if (BIO_write(bp, (char *)bs->data,
bs->length) != bs->length)
goto err;
BIO_puts(bp, "\n");
} else {
BIO_puts(bp,
"unable to print attribute\n");
}
if (++ii < count)
goto get_next;
}
}
}
if (!(cflag & X509_FLAG_NO_EXTENSIONS)) {
exts = X509_REQ_get_extensions(x);
if (exts) {
BIO_printf(bp, "%8sRequested Extensions:\n", "");
for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
ASN1_OBJECT *obj;
X509_EXTENSION *ex;
int j;
ex = sk_X509_EXTENSION_value(exts, i);
if (BIO_printf(bp, "%12s", "") <= 0)
goto err;
obj = X509_EXTENSION_get_object(ex);
i2a_ASN1_OBJECT(bp, obj);
j = X509_EXTENSION_get_critical(ex);
if (BIO_printf(bp, ": %s\n",
j ? "critical" : "") <= 0)
goto err;
if (!X509V3_EXT_print(bp, ex, cflag, 16)) {
BIO_printf(bp, "%16s", "");
ASN1_STRING_print(bp, ex->value);
}
if (BIO_write(bp, "\n", 1) <= 0)
goto err;
}
sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
exts = NULL;
}
}
if (!(cflag & X509_FLAG_NO_SIGDUMP)) {
if (!X509_signature_print(bp, x->sig_alg, x->signature))
goto err;
}
return (1);
err:
sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
X509error(ERR_R_BUF_LIB);
return (0);
}
int
X509_REQ_print(BIO *bp, X509_REQ *x)
{
return X509_REQ_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
}

115
crypto/asn1/t_spki.c Normal file
View File

@@ -0,0 +1,115 @@
/* $OpenBSD: t_spki.c,v 1.16 2023/07/07 19:37:52 beck Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 1999.
*/
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
#include <stdio.h>
#include <openssl/opensslconf.h>
#include <openssl/asn1.h>
#include <openssl/bn.h>
#include <openssl/x509.h>
#ifndef OPENSSL_NO_DSA
#include <openssl/dsa.h>
#endif
#ifndef OPENSSL_NO_RSA
#include <openssl/rsa.h>
#endif
#include "x509_local.h"
/* Print out an SPKI */
int
NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki)
{
EVP_PKEY *pkey;
ASN1_IA5STRING *chal;
int i, n;
char *s;
BIO_printf(out, "Netscape SPKI:\n");
i = OBJ_obj2nid(spki->spkac->pubkey->algor->algorithm);
BIO_printf(out, " Public Key Algorithm: %s\n",
(i == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(i));
pkey = X509_PUBKEY_get(spki->spkac->pubkey);
if (!pkey)
BIO_printf(out, " Unable to load public key\n");
else {
EVP_PKEY_print_public(out, pkey, 4, NULL);
EVP_PKEY_free(pkey);
}
chal = spki->spkac->challenge;
if (chal->length)
BIO_printf(out, " Challenge String: %.*s\n", chal->length,
chal->data);
i = OBJ_obj2nid(spki->sig_algor->algorithm);
BIO_printf(out, " Signature Algorithm: %s",
(i == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(i));
n = spki->signature->length;
s = (char *)spki->signature->data;
for (i = 0; i < n; i++) {
if ((i % 18) == 0)
BIO_write(out, "\n ", 7);
BIO_printf(out, "%02x%s", (unsigned char)s[i],
((i + 1) == n) ? "" : ":");
}
BIO_write(out, "\n", 1);
return 1;
}

515
crypto/asn1/t_x509.c Normal file
View File

@@ -0,0 +1,515 @@
/* $OpenBSD: t_x509.c,v 1.43 2023/07/07 19:37:52 beck Exp $ */
/* 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 <openssl/opensslconf.h>
#include <openssl/bn.h>
#include <openssl/buffer.h>
#include <openssl/err.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#ifndef OPENSSL_NO_DSA
#include <openssl/dsa.h>
#endif
#ifndef OPENSSL_NO_EC
#include <openssl/ec.h>
#endif
#ifndef OPENSSL_NO_RSA
#include <openssl/rsa.h>
#endif
#include "asn1_local.h"
#include "x509_local.h"
int
X509_print_fp(FILE *fp, X509 *x)
{
return X509_print_ex_fp(fp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
}
int
X509_print_ex_fp(FILE *fp, X509 *x, unsigned long nmflag, unsigned long cflag)
{
BIO *b;
int ret;
if ((b = BIO_new(BIO_s_file())) == NULL) {
X509error(ERR_R_BUF_LIB);
return (0);
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
ret = X509_print_ex(b, x, nmflag, cflag);
BIO_free(b);
return (ret);
}
int
X509_print(BIO *bp, X509 *x)
{
return X509_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
}
int
X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, unsigned long cflag)
{
long l;
int ret = 0, i;
char *m = NULL, mlch = ' ';
int nmindent = 0;
X509_CINF *ci;
ASN1_INTEGER *bs;
EVP_PKEY *pkey = NULL;
if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
mlch = '\n';
nmindent = 12;
}
if (nmflags == X509_FLAG_COMPAT)
nmindent = 16;
ci = x->cert_info;
if (!(cflag & X509_FLAG_NO_HEADER)) {
if (BIO_write(bp, "Certificate:\n", 13) <= 0)
goto err;
if (BIO_write(bp, " Data:\n", 10) <= 0)
goto err;
}
if (!(cflag & X509_FLAG_NO_VERSION)) {
l = X509_get_version(x);
if (l >= 0 && l <= 2) {
if (BIO_printf(bp, "%8sVersion: %ld (0x%lx)\n",
"", l + 1, l) <= 0)
goto err;
} else {
if (BIO_printf(bp, "%8sVersion: unknown (%ld)\n",
"", l) <= 0)
goto err;
}
}
if (!(cflag & X509_FLAG_NO_SERIAL)) {
if (BIO_write(bp, " Serial Number:", 22) <= 0)
goto err;
bs = X509_get_serialNumber(x);
l = -1;
if (bs->length <= (int)sizeof(long))
l = ASN1_INTEGER_get(bs);
if (l >= 0) {
if (BIO_printf(bp, " %ld (0x%lx)\n", l, l) <= 0)
goto err;
} else {
const char *neg = "";
if (bs->type == V_ASN1_NEG_INTEGER)
neg = " (Negative)";
if (BIO_printf(bp, "\n%12s%s", "", neg) <= 0)
goto err;
for (i = 0; i < bs->length; i++) {
if (BIO_printf(bp, "%02x%c", bs->data[i],
((i + 1 == bs->length) ? '\n' : ':')) <= 0)
goto err;
}
}
}
if (!(cflag & X509_FLAG_NO_SIGNAME)) {
if (X509_signature_print(bp, x->sig_alg, NULL) <= 0)
goto err;
}
if (!(cflag & X509_FLAG_NO_ISSUER)) {
if (BIO_printf(bp, " Issuer:%c", mlch) <= 0)
goto err;
if (X509_NAME_print_ex(bp, X509_get_issuer_name(x),
nmindent, nmflags) < (nmflags == X509_FLAG_COMPAT ? 1 : 0))
goto err;
if (BIO_write(bp, "\n", 1) <= 0)
goto err;
}
if (!(cflag & X509_FLAG_NO_VALIDITY)) {
if (BIO_write(bp, " Validity\n", 17) <= 0)
goto err;
if (BIO_write(bp, " Not Before: ", 24) <= 0)
goto err;
if (!ASN1_TIME_print(bp, X509_get_notBefore(x)))
goto err;
if (BIO_write(bp, "\n Not After : ", 25) <= 0)
goto err;
if (!ASN1_TIME_print(bp, X509_get_notAfter(x)))
goto err;
if (BIO_write(bp, "\n", 1) <= 0)
goto err;
}
if (!(cflag & X509_FLAG_NO_SUBJECT)) {
if (BIO_printf(bp, " Subject:%c", mlch) <= 0)
goto err;
if (X509_NAME_print_ex(bp, X509_get_subject_name(x),
nmindent, nmflags) < (nmflags == X509_FLAG_COMPAT ? 1 : 0))
goto err;
if (BIO_write(bp, "\n", 1) <= 0)
goto err;
}
if (!(cflag & X509_FLAG_NO_PUBKEY)) {
if (BIO_write(bp, " Subject Public Key Info:\n",
33) <= 0)
goto err;
if (BIO_printf(bp, "%12sPublic Key Algorithm: ", "") <= 0)
goto err;
if (i2a_ASN1_OBJECT(bp, ci->key->algor->algorithm) <= 0)
goto err;
if (BIO_puts(bp, "\n") <= 0)
goto err;
pkey = X509_get_pubkey(x);
if (pkey == NULL) {
BIO_printf(bp, "%12sUnable to load Public Key\n", "");
ERR_print_errors(bp);
} else {
EVP_PKEY_print_public(bp, pkey, 16, NULL);
EVP_PKEY_free(pkey);
}
}
if (!(cflag & X509_FLAG_NO_EXTENSIONS))
X509V3_extensions_print(bp, "X509v3 extensions",
ci->extensions, cflag, 8);
if (!(cflag & X509_FLAG_NO_SIGDUMP)) {
if (X509_signature_print(bp, x->sig_alg, x->signature) <= 0)
goto err;
}
if (!(cflag & X509_FLAG_NO_AUX)) {
if (!X509_CERT_AUX_print(bp, x->aux, 0))
goto err;
}
ret = 1;
err:
free(m);
return (ret);
}
int
X509_ocspid_print(BIO *bp, X509 *x)
{
unsigned char *der = NULL;
unsigned char *dertmp;
int derlen;
int i;
unsigned char SHA1md[SHA_DIGEST_LENGTH];
/* display the hash of the subject as it would appear
in OCSP requests */
if (BIO_printf(bp, " Subject OCSP hash: ") <= 0)
goto err;
if ((derlen = i2d_X509_NAME(x->cert_info->subject, NULL)) <= 0)
goto err;
if ((der = dertmp = malloc(derlen)) == NULL)
goto err;
if (i2d_X509_NAME(x->cert_info->subject, &dertmp) <= 0)
goto err;
if (!EVP_Digest(der, derlen, SHA1md, NULL, EVP_sha1(), NULL))
goto err;
for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0)
goto err;
}
free (der);
der = NULL;
/* display the hash of the public key as it would appear
in OCSP requests */
if (BIO_printf(bp, "\n Public key OCSP hash: ") <= 0)
goto err;
if (!EVP_Digest(x->cert_info->key->public_key->data,
x->cert_info->key->public_key->length,
SHA1md, NULL, EVP_sha1(), NULL))
goto err;
for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0)
goto err;
}
BIO_printf(bp, "\n");
return (1);
err:
free(der);
return (0);
}
int
X509_signature_dump(BIO *bp, const ASN1_STRING *sig, int indent)
{
const unsigned char *s;
int i, n;
n = sig->length;
s = sig->data;
for (i = 0; i < n; i++) {
if ((i % 18) == 0) {
if (BIO_write(bp, "\n", 1) <= 0)
return 0;
if (BIO_indent(bp, indent, indent) <= 0)
return 0;
}
if (BIO_printf(bp, "%02x%s", s[i],
((i + 1) == n) ? "" : ":") <= 0)
return 0;
}
if (BIO_write(bp, "\n", 1) != 1)
return 0;
return 1;
}
int
X509_signature_print(BIO *bp, const X509_ALGOR *sigalg, const ASN1_STRING *sig)
{
int sig_nid;
if (BIO_puts(bp, " Signature Algorithm: ") <= 0)
return 0;
if (i2a_ASN1_OBJECT(bp, sigalg->algorithm) <= 0)
return 0;
sig_nid = OBJ_obj2nid(sigalg->algorithm);
if (sig_nid != NID_undef) {
int pkey_nid, dig_nid;
const EVP_PKEY_ASN1_METHOD *ameth;
if (OBJ_find_sigid_algs(sig_nid, &dig_nid, &pkey_nid)) {
ameth = EVP_PKEY_asn1_find(NULL, pkey_nid);
if (ameth && ameth->sig_print)
return ameth->sig_print(bp, sigalg, sig, 9, 0);
}
}
if (sig)
return X509_signature_dump(bp, sig, 9);
else if (BIO_puts(bp, "\n") <= 0)
return 0;
return 1;
}
int
ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm)
{
if (tm->type == V_ASN1_UTCTIME)
return ASN1_UTCTIME_print(bp, tm);
if (tm->type == V_ASN1_GENERALIZEDTIME)
return ASN1_GENERALIZEDTIME_print(bp, tm);
BIO_write(bp, "Bad time value", 14);
return (0);
}
LCRYPTO_ALIAS(ASN1_TIME_print);
static const char *mon[12] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
int
ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm)
{
char *v;
int gmt = 0;
int i;
int y = 0, M = 0, d = 0, h = 0, m = 0, s = 0;
char *f = "";
int f_len = 0;
i = tm->length;
v = (char *)tm->data;
if (i < 12)
goto err;
if (v[i-1] == 'Z')
gmt = 1;
for (i = 0; i < 12; i++)
if ((v[i] > '9') || (v[i] < '0'))
goto err;
y = (v[0] - '0') * 1000 + (v[1] - '0') * 100 +
(v[2] - '0') * 10 + (v[3] - '0');
M = (v[4] - '0') * 10 + (v[5] - '0');
if ((M > 12) || (M < 1))
goto err;
d = (v[6] - '0') * 10 + (v[7] - '0');
h = (v[8] - '0') * 10 + (v[9] - '0');
m = (v[10] - '0') * 10 + (v[11] - '0');
if (tm->length >= 14 &&
(v[12] >= '0') && (v[12] <= '9') &&
(v[13] >= '0') && (v[13] <= '9')) {
s = (v[12] - '0') * 10 + (v[13] - '0');
/* Check for fractions of seconds. */
if (tm->length >= 15 && v[14] == '.') {
int l = tm->length;
f = &v[14]; /* The decimal point. */
f_len = 1;
while (14 + f_len < l && f[f_len] >= '0' &&
f[f_len] <= '9')
++f_len;
}
}
if (BIO_printf(bp, "%s %2d %02d:%02d:%02d%.*s %d%s",
mon[M - 1], d, h, m, s, f_len, f, y, (gmt) ? " GMT" : "") <= 0)
return (0);
else
return (1);
err:
BIO_write(bp, "Bad time value", 14);
return (0);
}
LCRYPTO_ALIAS(ASN1_GENERALIZEDTIME_print);
int
ASN1_UTCTIME_print(BIO *bp, const ASN1_UTCTIME *tm)
{
const char *v;
int gmt = 0;
int i;
int y = 0, M = 0, d = 0, h = 0, m = 0, s = 0;
i = tm->length;
v = (const char *)tm->data;
if (i < 10)
goto err;
if (v[i-1] == 'Z')
gmt = 1;
for (i = 0; i < 10; i++)
if ((v[i] > '9') || (v[i] < '0'))
goto err;
y = (v[0] - '0') * 10 + (v[1] - '0');
if (y < 50)
y += 100;
M = (v[2] - '0') * 10 + (v[3] - '0');
if ((M > 12) || (M < 1))
goto err;
d = (v[4] - '0') * 10 + (v[5] - '0');
h = (v[6] - '0') * 10 + (v[7] - '0');
m = (v[8] - '0') * 10 + (v[9] - '0');
if (tm->length >=12 &&
(v[10] >= '0') && (v[10] <= '9') &&
(v[11] >= '0') && (v[11] <= '9'))
s = (v[10] - '0') * 10 + (v[11] - '0');
if (BIO_printf(bp, "%s %2d %02d:%02d:%02d %d%s",
mon[M - 1], d, h, m, s, y + 1900, (gmt) ? " GMT" : "") <= 0)
return (0);
else
return (1);
err:
BIO_write(bp, "Bad time value", 14);
return (0);
}
LCRYPTO_ALIAS(ASN1_UTCTIME_print);
int
X509_NAME_print(BIO *bp, const X509_NAME *name, int obase)
{
char *s, *c, *b;
int i;
int ret = 0;
b = X509_NAME_oneline(name, NULL, 0);
if (b == NULL)
return 0;
if (*b == '\0') {
free(b);
return 1;
}
s = b + 1; /* skip the first slash */
c = s;
for (;;) {
if (((*s == '/') &&
((s[1] >= 'A') && (s[1] <= 'Z') &&
((s[2] == '=') || ((s[2] >= 'A') && (s[2] <= 'Z') &&
(s[3] == '='))))) || (*s == '\0')) {
i = s - c;
if (BIO_write(bp, c, i) != i)
goto err;
c = s + 1; /* skip following slash */
if (*s != '\0') {
if (BIO_write(bp, ", ", 2) != 2)
goto err;
}
}
if (*s == '\0')
break;
s++;
}
ret = 1;
if (0) {
err:
X509error(ERR_R_BUF_LIB);
}
free(b);
return (ret);
}

119
crypto/asn1/t_x509a.c Normal file
View File

@@ -0,0 +1,119 @@
/* $OpenBSD: t_x509a.c,v 1.13 2023/07/07 19:37:52 beck Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 1999.
*/
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
#include <stdio.h>
#include <openssl/asn1.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include "x509_local.h"
/* X509_CERT_AUX and string set routines */
int
X509_CERT_AUX_print(BIO *out, X509_CERT_AUX *aux, int indent)
{
char oidstr[80], first;
int i;
if (!aux)
return 1;
if (aux->trust) {
first = 1;
BIO_printf(out, "%*sTrusted Uses:\n%*s",
indent, "", indent + 2, "");
for (i = 0; i < sk_ASN1_OBJECT_num(aux->trust); i++) {
if (!first)
BIO_puts(out, ", ");
else
first = 0;
OBJ_obj2txt(oidstr, sizeof oidstr,
sk_ASN1_OBJECT_value(aux->trust, i), 0);
BIO_puts(out, oidstr);
}
BIO_puts(out, "\n");
} else
BIO_printf(out, "%*sNo Trusted Uses.\n", indent, "");
if (aux->reject) {
first = 1;
BIO_printf(out, "%*sRejected Uses:\n%*s",
indent, "", indent + 2, "");
for (i = 0; i < sk_ASN1_OBJECT_num(aux->reject); i++) {
if (!first)
BIO_puts(out, ", ");
else
first = 0;
OBJ_obj2txt(oidstr, sizeof oidstr,
sk_ASN1_OBJECT_value(aux->reject, i), 0);
BIO_puts(out, oidstr);
}
BIO_puts(out, "\n");
} else
BIO_printf(out, "%*sNo Rejected Uses.\n", indent, "");
if (aux->alias)
BIO_printf(out, "%*sAlias: %.*s\n", indent, "",
aux->alias->length, aux->alias->data);
if (aux->keyid) {
BIO_printf(out, "%*sKey Id: ", indent, "");
for (i = 0; i < aux->keyid->length; i++)
BIO_printf(out, "%s%02X", i ? ":" : "",
aux->keyid->data[i]);
BIO_write(out, "\n", 1);
}
return 1;
}

1260
crypto/asn1/tasn_dec.c Normal file

File diff suppressed because it is too large Load Diff

682
crypto/asn1/tasn_enc.c Normal file
View File

@@ -0,0 +1,682 @@
/* $OpenBSD: tasn_enc.c,v 1.33 2023/07/28 10:00:10 tb Exp $ */
/* 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/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/err.h>
#include <openssl/objects.h>
#include "asn1_local.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);
static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
const ASN1_ITEM *it);
/* 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);
}
LCRYPTO_ALIAS(ASN1_item_i2d);
/* 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)
{
unsigned char *p, *buf;
int len;
if (out == NULL || *out != NULL)
return ASN1_item_ex_i2d(&val, out, it, -1, flags);
if ((len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags)) <= 0)
return len;
if ((buf = calloc(1, len)) == NULL)
return -1;
p = buf;
if (ASN1_item_ex_i2d(&val, &p, it, -1, flags) != len) {
freezero(buf, len);
ASN1error(ASN1_R_LENGTH_ERROR);
return -1;
}
*out = buf;
return len;
}
/* 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;
int i, seqcontlen, seqlen, ndef = 1;
const ASN1_EXTERN_FUNCS *ef;
const ASN1_AUX *aux = it->funcs;
ASN1_aux_cb *asn1_cb = NULL;
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:
/*
* It never makes sense for multi-strings to have implicit
* tagging, so if tag != -1, then this looks like an error in
* the template.
*/
if (tag != -1) {
ASN1error(ASN1_R_BAD_TEMPLATE);
return 0;
}
return asn1_i2d_ex_primitive(pval, out, it, -1, aclass);
case ASN1_ITYPE_CHOICE:
/*
* It never makes sense for CHOICE types to have implicit
* tagging, so if tag != -1, then this looks like an error in
* the template.
*/
if (tag != -1) {
ASN1error(ASN1_R_BAD_TEMPLATE);
return 0;
}
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_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;
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 */
seqcontlen += asn1_template_ex_i2d(pseqval, NULL, seqtt,
-1, aclass);
}
seqlen = ASN1_object_size(ndef, seqcontlen, tag);
if (!out)
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;
}
LCRYPTO_ALIAS(ASN1_item_ex_i2d);
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++) {
skitem = sk_ASN1_VALUE_value(sk, i);
skcontlen += ASN1_item_ex_i2d(&skitem, NULL,
tt->item, -1, iclass);
}
sklen = ASN1_object_size(ndef, skcontlen, sktag);
/* If EXPLICIT need length of surrounding tag */
if (flags & ASN1_TFLG_EXPTAG)
ret = ASN1_object_size(ndef, sklen, ttag);
else
ret = sklen;
if (!out)
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, 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, tt->item,
-1, iclass);
if (!i)
return 0;
/* Find length of EXPLICIT tag */
ret = ASN1_object_size(ndef, i, ttag);
if (out) {
/* Output tag and item */
ASN1_put_object(out, ndef, i, ttag, tclass);
ASN1_item_ex_i2d(pval, out, 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, 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 = reallocarray(NULL, sk_ASN1_VALUE_num(sk),
sizeof(*derlst));
tmpdat = malloc(skcontlen);
if (!derlst || !tmpdat) {
free(derlst);
free(tmpdat);
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);
}
free(derlst);
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 olen, len;
int utype;
int usetag;
int ndef = 0;
utype = it->utype;
/* Get length of content octets and maybe find
* out the underlying type.
*/
olen = 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;
}
/* Treat any other negative value as an error. */
if (len < 0)
return -1;
/* 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);
if (asn1_ex_i2c(pval, *out, &utype, it) != olen)
return -1;
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 */
static 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;
if (it->funcs != NULL) {
const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
if (pf->prim_i2c == NULL)
return -1;
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;
}

243
crypto/asn1/tasn_fre.c Normal file
View File

@@ -0,0 +1,243 @@
/* $OpenBSD: tasn_fre.c,v 1.23 2023/07/28 10:00:10 tb Exp $ */
/* 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/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/objects.h>
#include "asn1_local.h"
static void asn1_item_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
/* Free up an ASN1 structure */
void
ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it)
{
asn1_item_free(&val, it);
}
LCRYPTO_ALIAS(ASN1_item_free);
void
ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
asn1_item_free(pval, it);
}
LCRYPTO_ALIAS(ASN1_item_ex_free);
static void
asn1_item_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
const ASN1_TEMPLATE *tt = NULL, *seqtt;
const ASN1_EXTERN_FUNCS *ef;
const ASN1_AUX *aux = it->funcs;
ASN1_aux_cb *asn1_cb = NULL;
int i;
if (pval == NULL)
return;
/* For primitive types *pval may be something other than C pointer. */
if (it->itype != ASN1_ITYPE_PRIMITIVE && *pval == NULL)
return;
if (aux != NULL && aux->asn1_cb != NULL)
asn1_cb = aux->asn1_cb;
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);
free(*pval);
*pval = NULL;
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_cleanup(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);
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_free(&vtmp, tt->item);
}
sk_ASN1_VALUE_free(sk);
*pval = NULL;
} else
asn1_item_free(pval, tt->item);
}
void
ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
int utype;
if (it != NULL && it->funcs != NULL) {
const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
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);
free(*pval);
break;
default:
ASN1_STRING_free((ASN1_STRING *)*pval);
break;
}
*pval = NULL;
}

344
crypto/asn1/tasn_new.c Normal file
View File

@@ -0,0 +1,344 @@
/* $OpenBSD: tasn_new.c,v 1.25 2023/07/28 10:00:10 tb Exp $ */
/* 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/asn1.h>
#include <openssl/objects.h>
#include <openssl/err.h>
#include <openssl/asn1t.h>
#include <string.h>
#include "asn1_local.h"
static int asn1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
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;
}
LCRYPTO_ALIAS(ASN1_item_new);
/* Allocate an ASN1 structure */
int
ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
return asn1_item_ex_new(pval, it);
}
LCRYPTO_ALIAS(ASN1_item_ex_new);
static int
asn1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
const ASN1_TEMPLATE *tt = NULL;
const ASN1_EXTERN_FUNCS *ef;
const ASN1_AUX *aux = it->funcs;
ASN1_aux_cb *asn1_cb = NULL;
ASN1_VALUE **pseqval;
int i;
if (aux != NULL && aux->asn1_cb != NULL)
asn1_cb = aux->asn1_cb;
*pval = NULL;
switch (it->itype) {
case ASN1_ITYPE_EXTERN:
ef = it->funcs;
if (ef && ef->asn1_ex_new) {
if (!ef->asn1_ex_new(pval, it))
goto memerr;
}
break;
case ASN1_ITYPE_PRIMITIVE:
if (it->templates) {
if (!ASN1_template_new(pval, it->templates))
goto memerr;
} else if (!ASN1_primitive_new(pval, it))
goto memerr;
break;
case ASN1_ITYPE_MSTRING:
if (!ASN1_primitive_new(pval, it))
goto memerr;
break;
case ASN1_ITYPE_CHOICE:
if (asn1_cb) {
i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
if (!i)
goto auxerr;
if (i == 2) {
return 1;
}
}
*pval = calloc(1, it->size);
if (!*pval)
goto memerr;
asn1_set_choice_selector(pval, -1, it);
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
goto auxerr;
break;
case ASN1_ITYPE_NDEF_SEQUENCE:
case ASN1_ITYPE_SEQUENCE:
if (asn1_cb) {
i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
if (!i)
goto auxerr;
if (i == 2) {
return 1;
}
}
*pval = calloc(1, it->size);
if (!*pval)
goto memerr;
asn1_do_lock(pval, 0, it);
asn1_enc_init(pval, it);
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
pseqval = asn1_get_field_ptr(pval, tt);
if (!ASN1_template_new(pseqval, tt))
goto memerr;
}
if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
goto auxerr;
break;
}
return 1;
memerr:
ASN1error(ERR_R_MALLOC_FAILURE);
return 0;
auxerr:
ASN1error(ASN1_R_AUX_ERROR);
ASN1_item_ex_free(pval, it);
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_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 = 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;
}
/* If SET OF or SEQUENCE OF, its a STACK */
if (tt->flags & ASN1_TFLG_SK_MASK) {
STACK_OF(ASN1_VALUE) *skval;
skval = sk_ASN1_VALUE_new_null();
if (!skval) {
ASN1error(ERR_R_MALLOC_FAILURE);
ret = 0;
goto done;
}
*pval = (ASN1_VALUE *)skval;
ret = 1;
goto done;
}
/* Otherwise pass it back to the item routine */
ret = asn1_item_ex_new(pval, it);
done:
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, 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 != NULL && it->funcs != NULL) {
const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
if (pf->prim_new == NULL)
return 0;
return pf->prim_new(pval, it);
}
if (!it || (it->itype == ASN1_ITYPE_MSTRING))
utype = V_ASN1_UNDEF;
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 = malloc(sizeof(ASN1_TYPE));
if (typ != NULL) {
typ->value.ptr = NULL;
typ->type = V_ASN1_UNDEF;
}
*pval = (ASN1_VALUE *)typ;
break;
default:
str = ASN1_STRING_type_new(utype);
if (it != NULL && it->itype == ASN1_ITYPE_MSTRING &&
str != NULL)
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 != NULL && it->funcs != NULL) {
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 = V_ASN1_UNDEF;
else
utype = it->utype;
if (utype == V_ASN1_BOOLEAN)
*(ASN1_BOOLEAN *)pval = it->size;
else
*pval = NULL;
}

612
crypto/asn1/tasn_prn.c Normal file
View File

@@ -0,0 +1,612 @@
/* $OpenBSD: tasn_prn.c,v 1.25 2023/07/05 21:23:36 beck Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2000.
*/
/* ====================================================================
* Copyright (c) 2000,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 <stddef.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/buffer.h>
#include <openssl/err.h>
#include <openssl/objects.h>
#include <openssl/x509v3.h>
#include "asn1_local.h"
/* Print routines.
*/
/* ASN1_PCTX routines */
static const ASN1_PCTX default_pctx = {
.flags = ASN1_PCTX_FLAGS_SHOW_ABSENT,
};
ASN1_PCTX *
ASN1_PCTX_new(void)
{
ASN1_PCTX *p;
if ((p = calloc(1, sizeof(ASN1_PCTX))) == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
return NULL;
}
return p;
}
LCRYPTO_ALIAS(ASN1_PCTX_new);
void
ASN1_PCTX_free(ASN1_PCTX *p)
{
free(p);
}
LCRYPTO_ALIAS(ASN1_PCTX_free);
unsigned long
ASN1_PCTX_get_flags(const ASN1_PCTX *p)
{
return p->flags;
}
LCRYPTO_ALIAS(ASN1_PCTX_get_flags);
void
ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags)
{
p->flags = flags;
}
LCRYPTO_ALIAS(ASN1_PCTX_set_flags);
unsigned long
ASN1_PCTX_get_nm_flags(const ASN1_PCTX *p)
{
return p->nm_flags;
}
LCRYPTO_ALIAS(ASN1_PCTX_get_nm_flags);
void
ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags)
{
p->nm_flags = flags;
}
LCRYPTO_ALIAS(ASN1_PCTX_set_nm_flags);
unsigned long
ASN1_PCTX_get_cert_flags(const ASN1_PCTX *p)
{
return p->cert_flags;
}
LCRYPTO_ALIAS(ASN1_PCTX_get_cert_flags);
void
ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags)
{
p->cert_flags = flags;
}
LCRYPTO_ALIAS(ASN1_PCTX_set_cert_flags);
unsigned long
ASN1_PCTX_get_oid_flags(const ASN1_PCTX *p)
{
return p->oid_flags;
}
LCRYPTO_ALIAS(ASN1_PCTX_get_oid_flags);
void
ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags)
{
p->oid_flags = flags;
}
LCRYPTO_ALIAS(ASN1_PCTX_set_oid_flags);
unsigned long
ASN1_PCTX_get_str_flags(const ASN1_PCTX *p)
{
return p->str_flags;
}
LCRYPTO_ALIAS(ASN1_PCTX_get_str_flags);
void
ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags)
{
p->str_flags = flags;
}
LCRYPTO_ALIAS(ASN1_PCTX_set_str_flags);
/* Main print routines */
static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
const ASN1_ITEM *it, const char *fname, const char *sname, int nohdr,
const ASN1_PCTX *pctx);
int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx);
static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld,
const ASN1_ITEM *it, int indent, const char *fname, const char *sname,
const ASN1_PCTX *pctx);
static int asn1_print_fsname(BIO *out, int indent, const char *fname,
const char *sname, const ASN1_PCTX *pctx);
int
ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent, const ASN1_ITEM *it,
const ASN1_PCTX *pctx)
{
const char *sname;
if (pctx == NULL)
pctx = &default_pctx;
if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME)
sname = NULL;
else
sname = it->sname;
return asn1_item_print_ctx(out, &ifld, indent, it, NULL, sname,
0, pctx);
}
LCRYPTO_ALIAS(ASN1_item_print);
static int
asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent, const ASN1_ITEM *it,
const char *fname, const char *sname, int nohdr, const ASN1_PCTX *pctx)
{
const ASN1_TEMPLATE *tt;
const ASN1_EXTERN_FUNCS *ef;
ASN1_VALUE **tmpfld;
const ASN1_AUX *aux = it->funcs;
ASN1_aux_cb *asn1_cb;
ASN1_PRINT_ARG parg;
int i;
if (aux && aux->asn1_cb) {
parg.out = out;
parg.indent = indent;
parg.pctx = pctx;
asn1_cb = aux->asn1_cb;
} else
asn1_cb = NULL;
if ((it->itype != ASN1_ITYPE_PRIMITIVE ||
it->utype != V_ASN1_BOOLEAN) && *fld == NULL) {
if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_ABSENT) {
if (!nohdr &&
!asn1_print_fsname(out, indent, fname, sname, pctx))
return 0;
if (BIO_puts(out, "<ABSENT>\n") <= 0)
return 0;
}
return 1;
}
switch (it->itype) {
case ASN1_ITYPE_PRIMITIVE:
if (it->templates) {
if (!asn1_template_print_ctx(out, fld, indent,
it->templates, pctx))
return 0;
}
/* fall thru */
case ASN1_ITYPE_MSTRING:
if (!asn1_primitive_print(out, fld, it,
indent, fname, sname, pctx))
return 0;
break;
case ASN1_ITYPE_EXTERN:
if (!nohdr &&
!asn1_print_fsname(out, indent, fname, sname, pctx))
return 0;
/* Use new style print routine if possible */
ef = it->funcs;
if (ef && ef->asn1_ex_print) {
i = ef->asn1_ex_print(out, fld, indent, "", pctx);
if (!i)
return 0;
if ((i == 2) && (BIO_puts(out, "\n") <= 0))
return 0;
return 1;
} else if (sname &&
BIO_printf(out, ":EXTERNAL TYPE %s\n", sname) <= 0)
return 0;
break;
case ASN1_ITYPE_CHOICE:
/* CHOICE type, get selector */
i = asn1_get_choice_selector(fld, it);
/* This should never happen... */
if ((i < 0) || (i >= it->tcount)) {
if (BIO_printf(out,
"ERROR: selector [%d] invalid\n", i) <= 0)
return 0;
return 1;
}
tt = it->templates + i;
tmpfld = asn1_get_field_ptr(fld, tt);
if (!asn1_template_print_ctx(out, tmpfld, indent, tt, pctx))
return 0;
break;
case ASN1_ITYPE_SEQUENCE:
case ASN1_ITYPE_NDEF_SEQUENCE:
if (!nohdr &&
!asn1_print_fsname(out, indent, fname, sname, pctx))
return 0;
if (fname || sname) {
if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
if (BIO_puts(out, " {\n") <= 0)
return 0;
} else {
if (BIO_puts(out, "\n") <= 0)
return 0;
}
}
if (asn1_cb) {
i = asn1_cb(ASN1_OP_PRINT_PRE, fld, it, &parg);
if (i == 0)
return 0;
if (i == 2)
return 1;
}
/* Print each field entry */
for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
const ASN1_TEMPLATE *seqtt;
seqtt = asn1_do_adb(fld, tt, 1);
if (seqtt == NULL)
return 0;
tmpfld = asn1_get_field_ptr(fld, seqtt);
if (!asn1_template_print_ctx(out, tmpfld, indent + 2,
seqtt, pctx))
return 0;
}
if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
if (BIO_printf(out, "%*s}\n", indent, "") < 0)
return 0;
}
if (asn1_cb) {
i = asn1_cb(ASN1_OP_PRINT_POST, fld, it, &parg);
if (i == 0)
return 0;
}
break;
default:
BIO_printf(out, "Unprocessed type %d\n", it->itype);
return 0;
}
return 1;
}
int
asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx)
{
int i, flags;
const char *sname, *fname;
flags = tt->flags;
if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME)
sname = tt->item->sname;
else
sname = NULL;
if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
fname = NULL;
else
fname = tt->field_name;
if (flags & ASN1_TFLG_SK_MASK) {
char *tname;
ASN1_VALUE *skitem;
STACK_OF(ASN1_VALUE) *stack;
/* SET OF, SEQUENCE OF */
if (fname) {
if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SSOF) {
if (flags & ASN1_TFLG_SET_OF)
tname = "SET";
else
tname = "SEQUENCE";
if (BIO_printf(out, "%*s%s OF %s {\n",
indent, "", tname, tt->field_name) <= 0)
return 0;
} else if (BIO_printf(out, "%*s%s:\n", indent, "",
fname) <= 0)
return 0;
}
stack = (STACK_OF(ASN1_VALUE) *)*fld;
for (i = 0; i < sk_ASN1_VALUE_num(stack); i++) {
if ((i > 0) && (BIO_puts(out, "\n") <= 0))
return 0;
skitem = sk_ASN1_VALUE_value(stack, i);
if (!asn1_item_print_ctx(out, &skitem, indent + 2,
tt->item, NULL, NULL, 1, pctx))
return 0;
}
if (!i && BIO_printf(out, "%*s<EMPTY>\n", indent + 2, "") <= 0)
return 0;
if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
if (BIO_printf(out, "%*s}\n", indent, "") <= 0)
return 0;
}
return 1;
}
return asn1_item_print_ctx(out, fld, indent, tt->item,
fname, sname, 0, pctx);
}
static int
asn1_print_fsname(BIO *out, int indent, const char *fname, const char *sname,
const ASN1_PCTX *pctx)
{
static char spaces[] = " ";
const int nspaces = sizeof(spaces) - 1;
while (indent > nspaces) {
if (BIO_write(out, spaces, nspaces) != nspaces)
return 0;
indent -= nspaces;
}
if (BIO_write(out, spaces, indent) != indent)
return 0;
if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME)
sname = NULL;
if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
fname = NULL;
if (!sname && !fname)
return 1;
if (fname) {
if (BIO_puts(out, fname) <= 0)
return 0;
}
if (sname) {
if (fname) {
if (BIO_printf(out, " (%s)", sname) <= 0)
return 0;
} else {
if (BIO_puts(out, sname) <= 0)
return 0;
}
}
if (BIO_write(out, ": ", 2) != 2)
return 0;
return 1;
}
static int
asn1_print_boolean_ctx(BIO *out, int boolval, const ASN1_PCTX *pctx)
{
const char *str;
switch (boolval) {
case -1:
str = "BOOL ABSENT";
break;
case 0:
str = "FALSE";
break;
default:
str = "TRUE";
break;
}
if (BIO_puts(out, str) <= 0)
return 0;
return 1;
}
static int
asn1_print_integer_ctx(BIO *out, ASN1_INTEGER *str, const ASN1_PCTX *pctx)
{
char *s;
int ret = 1;
if ((s = i2s_ASN1_INTEGER(NULL, str)) == NULL)
return 0;
if (BIO_puts(out, s) <= 0)
ret = 0;
free(s);
return ret;
}
static int
asn1_print_oid_ctx(BIO *out, const ASN1_OBJECT *oid, const ASN1_PCTX *pctx)
{
char objbuf[80];
const char *ln;
ln = OBJ_nid2ln(OBJ_obj2nid(oid));
if (!ln)
ln = "";
OBJ_obj2txt(objbuf, sizeof objbuf, oid, 1);
if (BIO_printf(out, "%s (%s)", ln, objbuf) <= 0)
return 0;
return 1;
}
static int
asn1_print_obstring_ctx(BIO *out, ASN1_STRING *str, int indent,
const ASN1_PCTX *pctx)
{
if (str->type == V_ASN1_BIT_STRING) {
if (BIO_printf(out, " (%ld unused bits)\n",
str->flags & 0x7) <= 0)
return 0;
} else if (BIO_puts(out, "\n") <= 0)
return 0;
if ((str->length > 0) &&
BIO_dump_indent(out, (char *)str->data, str->length,
indent + 2) <= 0)
return 0;
return 1;
}
static int
asn1_primitive_print(BIO *out, ASN1_VALUE **fld, const ASN1_ITEM *it,
int indent, const char *fname, const char *sname, const ASN1_PCTX *pctx)
{
long utype;
ASN1_STRING *str;
int ret = 1, needlf = 1;
const char *pname;
if (!asn1_print_fsname(out, indent, fname, sname, pctx))
return 0;
if (it != NULL && it->funcs != NULL) {
const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
if (pf->prim_print == NULL)
return 0;
return pf->prim_print(out, fld, it, indent, pctx);
}
if (it->itype == ASN1_ITYPE_MSTRING) {
str = (ASN1_STRING *)*fld;
utype = str->type & ~V_ASN1_NEG;
} else {
utype = it->utype;
if (utype == V_ASN1_BOOLEAN)
str = NULL;
else
str = (ASN1_STRING *)*fld;
}
if (utype == V_ASN1_ANY) {
ASN1_TYPE *atype = (ASN1_TYPE *)*fld;
utype = atype->type;
fld = &atype->value.asn1_value;
str = (ASN1_STRING *)*fld;
if (pctx->flags & ASN1_PCTX_FLAGS_NO_ANY_TYPE)
pname = NULL;
else
pname = ASN1_tag2str(utype);
} else {
if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_TYPE)
pname = ASN1_tag2str(utype);
else
pname = NULL;
}
if (utype == V_ASN1_NULL) {
if (BIO_puts(out, "NULL\n") <= 0)
return 0;
return 1;
}
if (pname) {
if (BIO_puts(out, pname) <= 0)
return 0;
if (BIO_puts(out, ":") <= 0)
return 0;
}
switch (utype) {
case V_ASN1_BOOLEAN:
{
int boolval = *(int *)fld;
if (boolval == -1)
boolval = it->size;
ret = asn1_print_boolean_ctx(out, boolval, pctx);
}
break;
case V_ASN1_INTEGER:
case V_ASN1_ENUMERATED:
ret = asn1_print_integer_ctx(out, str, pctx);
break;
case V_ASN1_UTCTIME:
ret = ASN1_UTCTIME_print(out, str);
break;
case V_ASN1_GENERALIZEDTIME:
ret = ASN1_GENERALIZEDTIME_print(out, str);
break;
case V_ASN1_OBJECT:
ret = asn1_print_oid_ctx(out, (const ASN1_OBJECT *)*fld, pctx);
break;
case V_ASN1_OCTET_STRING:
case V_ASN1_BIT_STRING:
ret = asn1_print_obstring_ctx(out, str, indent, pctx);
needlf = 0;
break;
case V_ASN1_SEQUENCE:
case V_ASN1_SET:
case V_ASN1_OTHER:
if (BIO_puts(out, "\n") <= 0)
return 0;
if (ASN1_parse_dump(out, str->data, str->length,
indent, 0) <= 0)
ret = 0;
needlf = 0;
break;
default:
ret = ASN1_STRING_print_ex(out, str, pctx->str_flags);
}
if (!ret)
return 0;
if (needlf && BIO_puts(out, "\n") <= 0)
return 0;
return 1;
}

721
crypto/asn1/tasn_typ.c Normal file
View File

@@ -0,0 +1,721 @@
/* $OpenBSD: tasn_typ.c,v 1.18 2023/07/05 21:23:37 beck Exp $ */
/* 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/asn1.h>
#include <openssl/asn1t.h>
/* Declarations for string types */
const ASN1_ITEM ASN1_NULL_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_NULL,
.sname = "ASN1_NULL",
};
ASN1_NULL *
d2i_ASN1_NULL(ASN1_NULL **a, const unsigned char **in, long len)
{
return (ASN1_NULL *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&ASN1_NULL_it);
}
LCRYPTO_ALIAS(d2i_ASN1_NULL);
int
i2d_ASN1_NULL(ASN1_NULL *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_NULL_it);
}
LCRYPTO_ALIAS(i2d_ASN1_NULL);
ASN1_NULL *
ASN1_NULL_new(void)
{
return (ASN1_NULL *)ASN1_item_new(&ASN1_NULL_it);
}
LCRYPTO_ALIAS(ASN1_NULL_new);
void
ASN1_NULL_free(ASN1_NULL *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_NULL_it);
}
LCRYPTO_ALIAS(ASN1_NULL_free);
const ASN1_ITEM ASN1_UTF8STRING_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_UTF8STRING,
.sname = "ASN1_UTF8STRING",
};
ASN1_UTF8STRING *
d2i_ASN1_UTF8STRING(ASN1_UTF8STRING **a, const unsigned char **in, long len)
{
return (ASN1_UTF8STRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&ASN1_UTF8STRING_it);
}
LCRYPTO_ALIAS(d2i_ASN1_UTF8STRING);
int
i2d_ASN1_UTF8STRING(ASN1_UTF8STRING *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_UTF8STRING_it);
}
LCRYPTO_ALIAS(i2d_ASN1_UTF8STRING);
ASN1_UTF8STRING *
ASN1_UTF8STRING_new(void)
{
return (ASN1_UTF8STRING *)ASN1_item_new(&ASN1_UTF8STRING_it);
}
LCRYPTO_ALIAS(ASN1_UTF8STRING_new);
void
ASN1_UTF8STRING_free(ASN1_UTF8STRING *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_UTF8STRING_it);
}
LCRYPTO_ALIAS(ASN1_UTF8STRING_free);
const ASN1_ITEM ASN1_PRINTABLESTRING_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_PRINTABLESTRING,
.sname = "ASN1_PRINTABLESTRING",
};
ASN1_PRINTABLESTRING *
d2i_ASN1_PRINTABLESTRING(ASN1_PRINTABLESTRING **a, const unsigned char **in,
long len)
{
return (ASN1_PRINTABLESTRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&ASN1_PRINTABLESTRING_it);
}
LCRYPTO_ALIAS(d2i_ASN1_PRINTABLESTRING);
int
i2d_ASN1_PRINTABLESTRING(ASN1_PRINTABLESTRING *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_PRINTABLESTRING_it);
}
LCRYPTO_ALIAS(i2d_ASN1_PRINTABLESTRING);
ASN1_PRINTABLESTRING *
ASN1_PRINTABLESTRING_new(void)
{
return (ASN1_PRINTABLESTRING *)ASN1_item_new(&ASN1_PRINTABLESTRING_it);
}
LCRYPTO_ALIAS(ASN1_PRINTABLESTRING_new);
void
ASN1_PRINTABLESTRING_free(ASN1_PRINTABLESTRING *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_PRINTABLESTRING_it);
}
LCRYPTO_ALIAS(ASN1_PRINTABLESTRING_free);
const ASN1_ITEM ASN1_T61STRING_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_T61STRING,
.sname = "ASN1_T61STRING",
};
ASN1_T61STRING *
d2i_ASN1_T61STRING(ASN1_T61STRING **a, const unsigned char **in, long len)
{
return (ASN1_T61STRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&ASN1_T61STRING_it);
}
LCRYPTO_ALIAS(d2i_ASN1_T61STRING);
int
i2d_ASN1_T61STRING(ASN1_T61STRING *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_T61STRING_it);
}
LCRYPTO_ALIAS(i2d_ASN1_T61STRING);
ASN1_T61STRING *
ASN1_T61STRING_new(void)
{
return (ASN1_T61STRING *)ASN1_item_new(&ASN1_T61STRING_it);
}
LCRYPTO_ALIAS(ASN1_T61STRING_new);
void
ASN1_T61STRING_free(ASN1_T61STRING *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_T61STRING_it);
}
LCRYPTO_ALIAS(ASN1_T61STRING_free);
const ASN1_ITEM ASN1_IA5STRING_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_IA5STRING,
.sname = "ASN1_IA5STRING",
};
ASN1_IA5STRING *
d2i_ASN1_IA5STRING(ASN1_IA5STRING **a, const unsigned char **in, long len)
{
return (ASN1_IA5STRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&ASN1_IA5STRING_it);
}
LCRYPTO_ALIAS(d2i_ASN1_IA5STRING);
int
i2d_ASN1_IA5STRING(ASN1_IA5STRING *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_IA5STRING_it);
}
LCRYPTO_ALIAS(i2d_ASN1_IA5STRING);
ASN1_IA5STRING *
ASN1_IA5STRING_new(void)
{
return (ASN1_IA5STRING *)ASN1_item_new(&ASN1_IA5STRING_it);
}
LCRYPTO_ALIAS(ASN1_IA5STRING_new);
void
ASN1_IA5STRING_free(ASN1_IA5STRING *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_IA5STRING_it);
}
LCRYPTO_ALIAS(ASN1_IA5STRING_free);
const ASN1_ITEM ASN1_GENERALSTRING_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_GENERALSTRING,
.sname = "ASN1_GENERALSTRING",
};
ASN1_GENERALSTRING *
d2i_ASN1_GENERALSTRING(ASN1_GENERALSTRING **a, const unsigned char **in,
long len)
{
return (ASN1_GENERALSTRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&ASN1_GENERALSTRING_it);
}
LCRYPTO_ALIAS(d2i_ASN1_GENERALSTRING);
int
i2d_ASN1_GENERALSTRING(ASN1_GENERALSTRING *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_GENERALSTRING_it);
}
LCRYPTO_ALIAS(i2d_ASN1_GENERALSTRING);
ASN1_GENERALSTRING *
ASN1_GENERALSTRING_new(void)
{
return (ASN1_GENERALSTRING *)ASN1_item_new(&ASN1_GENERALSTRING_it);
}
LCRYPTO_ALIAS(ASN1_GENERALSTRING_new);
void
ASN1_GENERALSTRING_free(ASN1_GENERALSTRING *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_GENERALSTRING_it);
}
LCRYPTO_ALIAS(ASN1_GENERALSTRING_free);
const ASN1_ITEM ASN1_UTCTIME_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_UTCTIME,
.sname = "ASN1_UTCTIME",
};
ASN1_UTCTIME *
d2i_ASN1_UTCTIME(ASN1_UTCTIME **a, const unsigned char **in, long len)
{
return (ASN1_UTCTIME *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&ASN1_UTCTIME_it);
}
LCRYPTO_ALIAS(d2i_ASN1_UTCTIME);
int
i2d_ASN1_UTCTIME(ASN1_UTCTIME *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_UTCTIME_it);
}
LCRYPTO_ALIAS(i2d_ASN1_UTCTIME);
ASN1_UTCTIME *
ASN1_UTCTIME_new(void)
{
return (ASN1_UTCTIME *)ASN1_item_new(&ASN1_UTCTIME_it);
}
LCRYPTO_ALIAS(ASN1_UTCTIME_new);
void
ASN1_UTCTIME_free(ASN1_UTCTIME *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_UTCTIME_it);
}
LCRYPTO_ALIAS(ASN1_UTCTIME_free);
const ASN1_ITEM ASN1_GENERALIZEDTIME_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_GENERALIZEDTIME,
.sname = "ASN1_GENERALIZEDTIME",
};
ASN1_GENERALIZEDTIME *
d2i_ASN1_GENERALIZEDTIME(ASN1_GENERALIZEDTIME **a, const unsigned char **in,
long len)
{
return (ASN1_GENERALIZEDTIME *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&ASN1_GENERALIZEDTIME_it);
}
LCRYPTO_ALIAS(d2i_ASN1_GENERALIZEDTIME);
int
i2d_ASN1_GENERALIZEDTIME(ASN1_GENERALIZEDTIME *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_GENERALIZEDTIME_it);
}
LCRYPTO_ALIAS(i2d_ASN1_GENERALIZEDTIME);
ASN1_GENERALIZEDTIME *
ASN1_GENERALIZEDTIME_new(void)
{
return (ASN1_GENERALIZEDTIME *)ASN1_item_new(&ASN1_GENERALIZEDTIME_it);
}
LCRYPTO_ALIAS(ASN1_GENERALIZEDTIME_new);
void
ASN1_GENERALIZEDTIME_free(ASN1_GENERALIZEDTIME *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_GENERALIZEDTIME_it);
}
LCRYPTO_ALIAS(ASN1_GENERALIZEDTIME_free);
const ASN1_ITEM ASN1_VISIBLESTRING_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_VISIBLESTRING,
.sname = "ASN1_VISIBLESTRING",
};
ASN1_VISIBLESTRING *
d2i_ASN1_VISIBLESTRING(ASN1_VISIBLESTRING **a, const unsigned char **in,
long len)
{
return (ASN1_VISIBLESTRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&ASN1_VISIBLESTRING_it);
}
LCRYPTO_ALIAS(d2i_ASN1_VISIBLESTRING);
int
i2d_ASN1_VISIBLESTRING(ASN1_VISIBLESTRING *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_VISIBLESTRING_it);
}
LCRYPTO_ALIAS(i2d_ASN1_VISIBLESTRING);
ASN1_VISIBLESTRING *
ASN1_VISIBLESTRING_new(void)
{
return (ASN1_VISIBLESTRING *)ASN1_item_new(&ASN1_VISIBLESTRING_it);
}
LCRYPTO_ALIAS(ASN1_VISIBLESTRING_new);
void
ASN1_VISIBLESTRING_free(ASN1_VISIBLESTRING *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_VISIBLESTRING_it);
}
LCRYPTO_ALIAS(ASN1_VISIBLESTRING_free);
const ASN1_ITEM ASN1_UNIVERSALSTRING_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_UNIVERSALSTRING,
.sname = "ASN1_UNIVERSALSTRING",
};
ASN1_UNIVERSALSTRING *
d2i_ASN1_UNIVERSALSTRING(ASN1_UNIVERSALSTRING **a, const unsigned char **in,
long len)
{
return (ASN1_UNIVERSALSTRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&ASN1_UNIVERSALSTRING_it);
}
LCRYPTO_ALIAS(d2i_ASN1_UNIVERSALSTRING);
int
i2d_ASN1_UNIVERSALSTRING(ASN1_UNIVERSALSTRING *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_UNIVERSALSTRING_it);
}
LCRYPTO_ALIAS(i2d_ASN1_UNIVERSALSTRING);
ASN1_UNIVERSALSTRING *
ASN1_UNIVERSALSTRING_new(void)
{
return (ASN1_UNIVERSALSTRING *)ASN1_item_new(&ASN1_UNIVERSALSTRING_it);
}
LCRYPTO_ALIAS(ASN1_UNIVERSALSTRING_new);
void
ASN1_UNIVERSALSTRING_free(ASN1_UNIVERSALSTRING *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_UNIVERSALSTRING_it);
}
LCRYPTO_ALIAS(ASN1_UNIVERSALSTRING_free);
const ASN1_ITEM ASN1_BMPSTRING_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_BMPSTRING,
.sname = "ASN1_BMPSTRING",
};
ASN1_BMPSTRING *
d2i_ASN1_BMPSTRING(ASN1_BMPSTRING **a, const unsigned char **in, long len)
{
return (ASN1_BMPSTRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&ASN1_BMPSTRING_it);
}
LCRYPTO_ALIAS(d2i_ASN1_BMPSTRING);
int
i2d_ASN1_BMPSTRING(ASN1_BMPSTRING *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_BMPSTRING_it);
}
LCRYPTO_ALIAS(i2d_ASN1_BMPSTRING);
ASN1_BMPSTRING *
ASN1_BMPSTRING_new(void)
{
return (ASN1_BMPSTRING *)ASN1_item_new(&ASN1_BMPSTRING_it);
}
LCRYPTO_ALIAS(ASN1_BMPSTRING_new);
void
ASN1_BMPSTRING_free(ASN1_BMPSTRING *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_BMPSTRING_it);
}
LCRYPTO_ALIAS(ASN1_BMPSTRING_free);
const ASN1_ITEM ASN1_ANY_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_ANY,
.sname = "ASN1_ANY",
};
/* Just swallow an ASN1_SEQUENCE in an ASN1_STRING */
const ASN1_ITEM ASN1_SEQUENCE_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_SEQUENCE,
.sname = "ASN1_SEQUENCE",
};
/* Multistring types */
const ASN1_ITEM ASN1_PRINTABLE_it = {
.itype = ASN1_ITYPE_MSTRING,
.utype = B_ASN1_PRINTABLE,
.templates = NULL,
.tcount = 0,
.funcs = NULL,
.size = sizeof(ASN1_STRING),
.sname = "ASN1_PRINTABLE",
};
ASN1_STRING *
d2i_ASN1_PRINTABLE(ASN1_STRING **a, const unsigned char **in, long len)
{
return (ASN1_STRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&ASN1_PRINTABLE_it);
}
LCRYPTO_ALIAS(d2i_ASN1_PRINTABLE);
int
i2d_ASN1_PRINTABLE(ASN1_STRING *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_PRINTABLE_it);
}
LCRYPTO_ALIAS(i2d_ASN1_PRINTABLE);
ASN1_STRING *
ASN1_PRINTABLE_new(void)
{
return (ASN1_STRING *)ASN1_item_new(&ASN1_PRINTABLE_it);
}
LCRYPTO_ALIAS(ASN1_PRINTABLE_new);
void
ASN1_PRINTABLE_free(ASN1_STRING *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_PRINTABLE_it);
}
LCRYPTO_ALIAS(ASN1_PRINTABLE_free);
const ASN1_ITEM DISPLAYTEXT_it = {
.itype = ASN1_ITYPE_MSTRING,
.utype = B_ASN1_DISPLAYTEXT,
.templates = NULL,
.tcount = 0,
.funcs = NULL,
.size = sizeof(ASN1_STRING),
.sname = "DISPLAYTEXT",
};
ASN1_STRING *
d2i_DISPLAYTEXT(ASN1_STRING **a, const unsigned char **in, long len)
{
return (ASN1_STRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&DISPLAYTEXT_it);
}
LCRYPTO_ALIAS(d2i_DISPLAYTEXT);
int
i2d_DISPLAYTEXT(ASN1_STRING *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &DISPLAYTEXT_it);
}
LCRYPTO_ALIAS(i2d_DISPLAYTEXT);
ASN1_STRING *
DISPLAYTEXT_new(void)
{
return (ASN1_STRING *)ASN1_item_new(&DISPLAYTEXT_it);
}
LCRYPTO_ALIAS(DISPLAYTEXT_new);
void
DISPLAYTEXT_free(ASN1_STRING *a)
{
ASN1_item_free((ASN1_VALUE *)a, &DISPLAYTEXT_it);
}
LCRYPTO_ALIAS(DISPLAYTEXT_free);
const ASN1_ITEM DIRECTORYSTRING_it = {
.itype = ASN1_ITYPE_MSTRING,
.utype = B_ASN1_DIRECTORYSTRING,
.templates = NULL,
.tcount = 0,
.funcs = NULL,
.size = sizeof(ASN1_STRING),
.sname = "DIRECTORYSTRING",
};
ASN1_STRING *
d2i_DIRECTORYSTRING(ASN1_STRING **a, const unsigned char **in, long len)
{
return (ASN1_STRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&DIRECTORYSTRING_it);
}
LCRYPTO_ALIAS(d2i_DIRECTORYSTRING);
int
i2d_DIRECTORYSTRING(ASN1_STRING *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &DIRECTORYSTRING_it);
}
LCRYPTO_ALIAS(i2d_DIRECTORYSTRING);
ASN1_STRING *
DIRECTORYSTRING_new(void)
{
return (ASN1_STRING *)ASN1_item_new(&DIRECTORYSTRING_it);
}
LCRYPTO_ALIAS(DIRECTORYSTRING_new);
void
DIRECTORYSTRING_free(ASN1_STRING *a)
{
ASN1_item_free((ASN1_VALUE *)a, &DIRECTORYSTRING_it);
}
LCRYPTO_ALIAS(DIRECTORYSTRING_free);
/* Three separate BOOLEAN type: normal, DEFAULT TRUE and DEFAULT FALSE */
const ASN1_ITEM ASN1_BOOLEAN_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_BOOLEAN,
.size = -1,
.sname = "ASN1_BOOLEAN",
};
int
i2d_ASN1_BOOLEAN(int a, unsigned char **out)
{
return ASN1_item_ex_i2d((ASN1_VALUE **)&a, out,
&ASN1_BOOLEAN_it, -1, 0);
}
int
d2i_ASN1_BOOLEAN(int *a, const unsigned char **in, long len)
{
ASN1_BOOLEAN abool;
if (ASN1_item_ex_d2i((ASN1_VALUE **)&abool, in, len, &ASN1_BOOLEAN_it,
-1, 0, 0, NULL) <= 0)
return -1;
if (a != NULL)
*a = abool;
return abool;
}
const ASN1_ITEM ASN1_TBOOLEAN_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_BOOLEAN,
.size = 1,
.sname = "ASN1_TBOOLEAN",
};
const ASN1_ITEM ASN1_FBOOLEAN_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_BOOLEAN,
.size = 0,
.sname = "ASN1_FBOOLEAN",
};
/* Special, OCTET STRING with indefinite length constructed support */
const ASN1_ITEM ASN1_OCTET_STRING_NDEF_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_OCTET_STRING,
.size = ASN1_TFLG_NDEF,
.sname = "ASN1_OCTET_STRING_NDEF",
};
static const ASN1_TEMPLATE ASN1_SEQUENCE_ANY_item_tt = {
.flags = ASN1_TFLG_SEQUENCE_OF,
.tag = 0,
.offset = 0,
.field_name = "ASN1_SEQUENCE_ANY",
.item = &ASN1_ANY_it,
};
const ASN1_ITEM ASN1_SEQUENCE_ANY_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = -1,
.templates = &ASN1_SEQUENCE_ANY_item_tt,
.tcount = 0,
.funcs = NULL,
.size = 0,
.sname = "ASN1_SEQUENCE_ANY",
};
static const ASN1_TEMPLATE ASN1_SET_ANY_item_tt = {
.flags = ASN1_TFLG_SET_OF,
.tag = 0,
.offset = 0,
.field_name = "ASN1_SET_ANY",
.item = &ASN1_ANY_it,
};
const ASN1_ITEM ASN1_SET_ANY_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = -1,
.templates = &ASN1_SET_ANY_item_tt,
.tcount = 0,
.funcs = NULL,
.size = 0,
.sname = "ASN1_SET_ANY",
};
ASN1_SEQUENCE_ANY *
d2i_ASN1_SEQUENCE_ANY(ASN1_SEQUENCE_ANY **a, const unsigned char **in, long len)
{
return (ASN1_SEQUENCE_ANY *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&ASN1_SEQUENCE_ANY_it);
}
LCRYPTO_ALIAS(d2i_ASN1_SEQUENCE_ANY);
int
i2d_ASN1_SEQUENCE_ANY(const ASN1_SEQUENCE_ANY *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_SEQUENCE_ANY_it);
}
LCRYPTO_ALIAS(i2d_ASN1_SEQUENCE_ANY);
ASN1_SEQUENCE_ANY *
d2i_ASN1_SET_ANY(ASN1_SEQUENCE_ANY **a, const unsigned char **in, long len)
{
return (ASN1_SEQUENCE_ANY *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&ASN1_SET_ANY_it);
}
LCRYPTO_ALIAS(d2i_ASN1_SET_ANY);
int
i2d_ASN1_SET_ANY(const ASN1_SEQUENCE_ANY *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_SET_ANY_it);
}
LCRYPTO_ALIAS(i2d_ASN1_SET_ANY);

299
crypto/asn1/tasn_utl.c Normal file
View File

@@ -0,0 +1,299 @@
/* $OpenBSD: tasn_utl.c,v 1.18 2022/12/26 07:18:51 jmc Exp $ */
/* 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 <limits.h>
#include <stddef.h>
#include <string.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/objects.h>
#include <openssl/err.h>
#include "bytestring.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 reference 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);
return ret;
}
static ASN1_ENCODING *
asn1_get_enc_ptr(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
const ASN1_AUX *aux = it->funcs;
if (pval == NULL || *pval == NULL)
return NULL;
if (aux == NULL || (aux->flags & ASN1_AFLG_ENCODING) == 0)
return NULL;
return offset2ptr(*pval, aux->enc_offset);
}
void
asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
ASN1_ENCODING *aenc;
if ((aenc = asn1_get_enc_ptr(pval, it)) == NULL)
return;
aenc->enc = NULL;
aenc->len = 0;
aenc->modified = 1;
}
static void
asn1_enc_clear(ASN1_ENCODING *aenc)
{
freezero(aenc->enc, aenc->len);
aenc->enc = NULL;
aenc->len = 0;
aenc->modified = 1;
}
void
asn1_enc_cleanup(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
ASN1_ENCODING *aenc;
if ((aenc = asn1_get_enc_ptr(pval, it)) == NULL)
return;
asn1_enc_clear(aenc);
}
int
asn1_enc_save(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it)
{
ASN1_ENCODING *aenc;
uint8_t *data = NULL;
size_t data_len = 0;
if ((aenc = asn1_get_enc_ptr(pval, it)) == NULL)
return 1;
asn1_enc_clear(aenc);
if (!CBS_stow(cbs, &data, &data_len))
return 0;
if (data_len > LONG_MAX) {
freezero(data, data_len);
return 0;
}
aenc->enc = data;
aenc->len = (long)data_len;
aenc->modified = 0;
return 1;
}
int
asn1_enc_restore(int *out_len, unsigned char **out, ASN1_VALUE **pval,
const ASN1_ITEM *it)
{
ASN1_ENCODING *aenc;
if ((aenc = asn1_get_enc_ptr(pval, it)) == NULL)
return 0;
if (aenc->modified)
return 0;
if (out != NULL) {
memcpy(*out, aenc->enc, aenc->len);
*out += aenc->len;
}
if (out_len != NULL)
*out_len = aenc->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;
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 = (const ASN1_ADB *)tt->item;
/* Get the selector field */
sfld = offset2ptr(*pval, adb->offset);
/* Check if NULL */
if (!sfld) {
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)
ASN1error(ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE);
return NULL;
}

220
crypto/asn1/x_algor.c Normal file
View File

@@ -0,0 +1,220 @@
/* $OpenBSD: x_algor.c,v 1.25 2023/07/07 19:37:52 beck Exp $ */
/* 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>
static const ASN1_TEMPLATE X509_ALGOR_seq_tt[] = {
{
.offset = offsetof(X509_ALGOR, algorithm),
.field_name = "algorithm",
.item = &ASN1_OBJECT_it,
},
{
.flags = ASN1_TFLG_OPTIONAL,
.offset = offsetof(X509_ALGOR, parameter),
.field_name = "parameter",
.item = &ASN1_ANY_it,
},
};
const ASN1_ITEM X509_ALGOR_it = {
.itype = ASN1_ITYPE_SEQUENCE,
.utype = V_ASN1_SEQUENCE,
.templates = X509_ALGOR_seq_tt,
.tcount = sizeof(X509_ALGOR_seq_tt) / sizeof(ASN1_TEMPLATE),
.size = sizeof(X509_ALGOR),
.sname = "X509_ALGOR",
};
static const ASN1_TEMPLATE X509_ALGORS_item_tt = {
.flags = ASN1_TFLG_SEQUENCE_OF,
.tag = 0,
.offset = 0,
.field_name = "algorithms",
.item = &X509_ALGOR_it,
};
const ASN1_ITEM X509_ALGORS_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = -1,
.templates = &X509_ALGORS_item_tt,
.tcount = 0,
.funcs = NULL,
.size = 0,
.sname = "X509_ALGORS",
};
X509_ALGOR *
d2i_X509_ALGOR(X509_ALGOR **a, const unsigned char **in, long len)
{
return (X509_ALGOR *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&X509_ALGOR_it);
}
int
i2d_X509_ALGOR(X509_ALGOR *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_ALGOR_it);
}
X509_ALGOR *
X509_ALGOR_new(void)
{
return (X509_ALGOR *)ASN1_item_new(&X509_ALGOR_it);
}
void
X509_ALGOR_free(X509_ALGOR *a)
{
ASN1_item_free((ASN1_VALUE *)a, &X509_ALGOR_it);
}
X509_ALGORS *
d2i_X509_ALGORS(X509_ALGORS **a, const unsigned char **in, long len)
{
return (X509_ALGORS *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&X509_ALGORS_it);
}
int
i2d_X509_ALGORS(X509_ALGORS *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_ALGORS_it);
}
X509_ALGOR *
X509_ALGOR_dup(X509_ALGOR *x)
{
return ASN1_item_dup(&X509_ALGOR_it, x);
}
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(const ASN1_OBJECT **paobj, int *pptype, const void **ppval,
const 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 = V_ASN1_NULL;
if ((EVP_MD_flags(md) & EVP_MD_FLAG_DIGALGID_ABSENT) != 0)
param_type = V_ASN1_UNDEF;
X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL);
}
/* Returns 0 if they are equal, != 0 otherwise. */
int
X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b)
{
int rv = OBJ_cmp(a->algorithm, b->algorithm);
if (!rv) {
if (!a->parameter && !b->parameter)
rv = 0;
else
rv = ASN1_TYPE_cmp(a->parameter, b->parameter);
}
return(rv);
}

152
crypto/asn1/x_attrib.c Normal file
View File

@@ -0,0 +1,152 @@
/* $OpenBSD: x_attrib.c,v 1.21 2023/07/28 13:30:07 jsg Exp $ */
/* 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 <openssl/asn1t.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#include "x509_local.h"
static const ASN1_TEMPLATE X509_ATTRIBUTE_seq_tt[] = {
{
.flags = 0,
.tag = 0,
.offset = offsetof(X509_ATTRIBUTE, object),
.field_name = "object",
.item = &ASN1_OBJECT_it,
},
{
.flags = ASN1_TFLG_SET_OF,
.tag = 0,
.offset = offsetof(X509_ATTRIBUTE, set),
.field_name = "set",
.item = &ASN1_ANY_it,
},
};
const ASN1_ITEM X509_ATTRIBUTE_it = {
.itype = ASN1_ITYPE_SEQUENCE,
.utype = V_ASN1_SEQUENCE,
.templates = X509_ATTRIBUTE_seq_tt,
.tcount = sizeof(X509_ATTRIBUTE_seq_tt) / sizeof(ASN1_TEMPLATE),
.funcs = NULL,
.size = sizeof(X509_ATTRIBUTE),
.sname = "X509_ATTRIBUTE",
};
X509_ATTRIBUTE *
d2i_X509_ATTRIBUTE(X509_ATTRIBUTE **a, const unsigned char **in, long len)
{
return (X509_ATTRIBUTE *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&X509_ATTRIBUTE_it);
}
int
i2d_X509_ATTRIBUTE(X509_ATTRIBUTE *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_ATTRIBUTE_it);
}
X509_ATTRIBUTE *
X509_ATTRIBUTE_new(void)
{
return (X509_ATTRIBUTE *)ASN1_item_new(&X509_ATTRIBUTE_it);
}
void
X509_ATTRIBUTE_free(X509_ATTRIBUTE *a)
{
ASN1_item_free((ASN1_VALUE *)a, &X509_ATTRIBUTE_it);
}
X509_ATTRIBUTE *
X509_ATTRIBUTE_dup(X509_ATTRIBUTE *x)
{
return ASN1_item_dup(&X509_ATTRIBUTE_it, x);
}
X509_ATTRIBUTE *
X509_ATTRIBUTE_create(int nid, int atrtype, void *value)
{
X509_ATTRIBUTE *ret = NULL;
ASN1_TYPE *val = NULL;
ASN1_OBJECT *oid;
if ((oid = OBJ_nid2obj(nid)) == NULL)
return (NULL);
if ((ret = X509_ATTRIBUTE_new()) == NULL)
return (NULL);
ret->object = oid;
if ((val = ASN1_TYPE_new()) == NULL)
goto err;
if (!sk_ASN1_TYPE_push(ret->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);
}

205
crypto/asn1/x_bignum.c Normal file
View File

@@ -0,0 +1,205 @@
/* $OpenBSD: x_bignum.c,v 1.13 2022/11/26 16:08:50 tb Exp $ */
/* 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/asn1t.h>
#include <openssl/bn.h>
#include "asn1_local.h"
#include "bytestring.h"
/*
* Custom primitive type for that reads an ASN.1 INTEGER into a BIGNUM.
*/
static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
static void bn_clear(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 = {
.app_data = NULL,
.flags = 0,
.prim_new = bn_new,
.prim_free = bn_free,
.prim_clear = bn_clear,
.prim_c2i = bn_c2i,
.prim_i2c = bn_i2c,
.prim_print = bn_print,
};
const ASN1_ITEM BIGNUM_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_INTEGER,
.templates = NULL,
.tcount = 0,
.funcs = &bignum_pf,
.size = 0,
.sname = "BIGNUM",
};
const ASN1_ITEM CBIGNUM_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_INTEGER,
.templates = NULL,
.tcount = 0,
.funcs = &bignum_pf,
.size = 0,
.sname = "BIGNUM",
};
static int
bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
if ((*pval = (ASN1_VALUE *)BN_new()) == NULL)
return 0;
return 1;
}
static void
bn_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
BN_free((BIGNUM *)*pval);
*pval = NULL;
}
static void
bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
if (*pval == NULL)
return;
bn_clear(pval, it);
}
static int
bn_i2c(ASN1_VALUE **pval, unsigned char *content, int *putype, const ASN1_ITEM *it)
{
ASN1_INTEGER *aint = NULL;
unsigned char **pp = NULL;
const BIGNUM *bn;
int ret;
if (*pval == NULL)
return -1;
bn = (const BIGNUM *)*pval;
if ((aint = BN_to_ASN1_INTEGER(bn, NULL)) == NULL)
return -1;
if (content != NULL)
pp = &content;
ret = i2c_ASN1_INTEGER(aint, pp);
ASN1_INTEGER_free(aint);
return ret;
}
static int
bn_c2i(ASN1_VALUE **pval, const unsigned char *content, int len, int utype,
char *free_content, const ASN1_ITEM *it)
{
ASN1_INTEGER *aint = NULL;
BIGNUM *bn;
CBS cbs;
int ret = 0;
bn_clear(pval, it);
if (len < 0)
goto err;
CBS_init(&cbs, content, len);
if (!c2i_ASN1_INTEGER_cbs(&aint, &cbs))
goto err;
if ((bn = ASN1_INTEGER_to_BN(aint, NULL)) == NULL)
goto err;
*pval = (ASN1_VALUE *)bn;
ret = 1;
err:
ASN1_INTEGER_free(aint);
return ret;
}
static int
bn_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, int indent,
const ASN1_PCTX *pctx)
{
const BIGNUM *bn = (BIGNUM *)*pval;
if (!BN_print(out, bn))
return 0;
if (BIO_printf(out, "\n") <= 0)
return 0;
return 1;
}

763
crypto/asn1/x_crl.c Normal file
View File

@@ -0,0 +1,763 @@
/* $OpenBSD: x_crl.c,v 1.41 2023/07/07 19:37:52 beck Exp $ */
/* 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 <openssl/opensslconf.h>
#include <openssl/asn1t.h>
#include <openssl/err.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include "asn1_local.h"
#include "x509_local.h"
static int X509_REVOKED_cmp(const X509_REVOKED * const *a,
const X509_REVOKED * const *b);
static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp);
static const ASN1_TEMPLATE X509_REVOKED_seq_tt[] = {
{
.offset = offsetof(X509_REVOKED, serialNumber),
.field_name = "serialNumber",
.item = &ASN1_INTEGER_it,
},
{
.offset = offsetof(X509_REVOKED, revocationDate),
.field_name = "revocationDate",
.item = &ASN1_TIME_it,
},
{
.flags = ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL,
.offset = offsetof(X509_REVOKED, extensions),
.field_name = "extensions",
.item = &X509_EXTENSION_it,
},
};
const ASN1_ITEM X509_REVOKED_it = {
.itype = ASN1_ITYPE_SEQUENCE,
.utype = V_ASN1_SEQUENCE,
.templates = X509_REVOKED_seq_tt,
.tcount = sizeof(X509_REVOKED_seq_tt) / sizeof(ASN1_TEMPLATE),
.size = sizeof(X509_REVOKED),
.sname = "X509_REVOKED",
};
static int def_crl_verify(X509_CRL *crl, EVP_PKEY *r);
static int def_crl_lookup(X509_CRL *crl, X509_REVOKED **ret,
ASN1_INTEGER *serial, X509_NAME *issuer);
static X509_CRL_METHOD int_crl_meth = {
.crl_lookup = def_crl_lookup,
.crl_verify = def_crl_verify
};
static const X509_CRL_METHOD *default_crl_method = &int_crl_meth;
/* The X509_CRL_INFO structure needs a bit of customisation.
* Since we cache the original encoding the signature wont be affected by
* reordering of the revoked field.
*/
static int
crl_inf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
{
X509_CRL_INFO *a = (X509_CRL_INFO *)*pval;
if (!a || !a->revoked)
return 1;
switch (operation) {
/* Just set cmp function here. We don't sort because that
* would affect the output of X509_CRL_print().
*/
case ASN1_OP_D2I_POST:
(void)sk_X509_REVOKED_set_cmp_func(a->revoked, X509_REVOKED_cmp);
break;
}
return 1;
}
static const ASN1_AUX X509_CRL_INFO_aux = {
.flags = ASN1_AFLG_ENCODING,
.asn1_cb = crl_inf_cb,
.enc_offset = offsetof(X509_CRL_INFO, enc),
};
static const ASN1_TEMPLATE X509_CRL_INFO_seq_tt[] = {
{
.flags = ASN1_TFLG_OPTIONAL,
.offset = offsetof(X509_CRL_INFO, version),
.field_name = "version",
.item = &ASN1_INTEGER_it,
},
{
.offset = offsetof(X509_CRL_INFO, sig_alg),
.field_name = "sig_alg",
.item = &X509_ALGOR_it,
},
{
.offset = offsetof(X509_CRL_INFO, issuer),
.field_name = "issuer",
.item = &X509_NAME_it,
},
{
.offset = offsetof(X509_CRL_INFO, lastUpdate),
.field_name = "lastUpdate",
.item = &ASN1_TIME_it,
},
{
.flags = ASN1_TFLG_OPTIONAL,
.offset = offsetof(X509_CRL_INFO, nextUpdate),
.field_name = "nextUpdate",
.item = &ASN1_TIME_it,
},
{
.flags = ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL,
.offset = offsetof(X509_CRL_INFO, revoked),
.field_name = "revoked",
.item = &X509_REVOKED_it,
},
{
.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL,
.offset = offsetof(X509_CRL_INFO, extensions),
.field_name = "extensions",
.item = &X509_EXTENSION_it,
},
};
const ASN1_ITEM X509_CRL_INFO_it = {
.itype = ASN1_ITYPE_SEQUENCE,
.utype = V_ASN1_SEQUENCE,
.templates = X509_CRL_INFO_seq_tt,
.tcount = sizeof(X509_CRL_INFO_seq_tt) / sizeof(ASN1_TEMPLATE),
.funcs = &X509_CRL_INFO_aux,
.size = sizeof(X509_CRL_INFO),
.sname = "X509_CRL_INFO",
};
/* Set CRL entry issuer according to CRL certificate issuer extension.
* Check for unhandled critical CRL entry extensions.
*/
static int
crl_set_issuers(X509_CRL *crl)
{
int i, j;
GENERAL_NAMES *gens, *gtmp;
STACK_OF(X509_REVOKED) *revoked;
revoked = X509_CRL_get_REVOKED(crl);
gens = NULL;
for (i = 0; i < sk_X509_REVOKED_num(revoked); i++) {
X509_REVOKED *rev = sk_X509_REVOKED_value(revoked, i);
STACK_OF(X509_EXTENSION) *exts;
ASN1_ENUMERATED *reason;
X509_EXTENSION *ext;
gtmp = X509_REVOKED_get_ext_d2i(rev, NID_certificate_issuer,
&j, NULL);
if (!gtmp && (j != -1)) {
crl->flags |= EXFLAG_INVALID;
return 1;
}
if (gtmp) {
gens = gtmp;
if (!crl->issuers) {
crl->issuers = sk_GENERAL_NAMES_new_null();
if (!crl->issuers)
return 0;
}
if (!sk_GENERAL_NAMES_push(crl->issuers, gtmp))
return 0;
}
rev->issuer = gens;
reason = X509_REVOKED_get_ext_d2i(rev, NID_crl_reason,
&j, NULL);
if (!reason && (j != -1)) {
crl->flags |= EXFLAG_INVALID;
return 1;
}
if (reason) {
rev->reason = ASN1_ENUMERATED_get(reason);
ASN1_ENUMERATED_free(reason);
} else
rev->reason = CRL_REASON_NONE;
/* Check for critical CRL entry extensions */
exts = rev->extensions;
for (j = 0; j < sk_X509_EXTENSION_num(exts); j++) {
ext = sk_X509_EXTENSION_value(exts, j);
if (ext->critical > 0) {
if (OBJ_obj2nid(ext->object) ==
NID_certificate_issuer)
continue;
crl->flags |= EXFLAG_CRITICAL;
break;
}
}
}
return 1;
}
/* The X509_CRL structure needs a bit of customisation. Cache some extensions
* and hash of the whole CRL.
*/
static int
crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
{
X509_CRL *crl = (X509_CRL *)*pval;
STACK_OF(X509_EXTENSION) *exts;
X509_EXTENSION *ext;
int idx;
int rc = 1;
switch (operation) {
case ASN1_OP_NEW_POST:
crl->idp = NULL;
crl->akid = NULL;
crl->flags = 0;
crl->idp_flags = 0;
crl->idp_reasons = CRLDP_ALL_REASONS;
crl->meth = default_crl_method;
crl->meth_data = NULL;
crl->issuers = NULL;
crl->crl_number = NULL;
crl->base_crl_number = NULL;
break;
case ASN1_OP_D2I_POST:
X509_CRL_digest(crl, X509_CRL_HASH_EVP, crl->hash, NULL);
crl->idp = X509_CRL_get_ext_d2i(crl,
NID_issuing_distribution_point, NULL, NULL);
if (crl->idp)
setup_idp(crl, crl->idp);
crl->akid = X509_CRL_get_ext_d2i(crl,
NID_authority_key_identifier, NULL, NULL);
crl->crl_number = X509_CRL_get_ext_d2i(crl,
NID_crl_number, NULL, NULL);
crl->base_crl_number = X509_CRL_get_ext_d2i(crl,
NID_delta_crl, NULL, NULL);
/* Delta CRLs must have CRL number */
if (crl->base_crl_number && !crl->crl_number)
crl->flags |= EXFLAG_INVALID;
/* See if we have any unhandled critical CRL extensions and
* indicate this in a flag. We only currently handle IDP,
* AKID and deltas, so anything else critical sets the flag.
*
* This code accesses the X509_CRL structure directly:
* applications shouldn't do this.
*/
exts = crl->crl->extensions;
for (idx = 0; idx < sk_X509_EXTENSION_num(exts); idx++) {
int nid;
ext = sk_X509_EXTENSION_value(exts, idx);
nid = OBJ_obj2nid(ext->object);
if (nid == NID_freshest_crl)
crl->flags |= EXFLAG_FRESHEST;
if (ext->critical > 0) {
/* We handle IDP, AKID and deltas */
if (nid == NID_issuing_distribution_point ||
nid == NID_authority_key_identifier ||
nid == NID_delta_crl)
break;
crl->flags |= EXFLAG_CRITICAL;
break;
}
}
if (!crl_set_issuers(crl))
return 0;
if (crl->meth->crl_init) {
if (crl->meth->crl_init(crl) == 0)
return 0;
}
break;
case ASN1_OP_FREE_POST:
if (crl->meth->crl_free) {
if (!crl->meth->crl_free(crl))
rc = 0;
}
if (crl->akid)
AUTHORITY_KEYID_free(crl->akid);
if (crl->idp)
ISSUING_DIST_POINT_free(crl->idp);
ASN1_INTEGER_free(crl->crl_number);
ASN1_INTEGER_free(crl->base_crl_number);
sk_GENERAL_NAMES_pop_free(crl->issuers, GENERAL_NAMES_free);
break;
}
return rc;
}
/* Convert IDP into a more convenient form */
static void
setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp)
{
int idp_only = 0;
/* Set various flags according to IDP */
crl->idp_flags |= IDP_PRESENT;
if (idp->onlyuser > 0) {
idp_only++;
crl->idp_flags |= IDP_ONLYUSER;
}
if (idp->onlyCA > 0) {
idp_only++;
crl->idp_flags |= IDP_ONLYCA;
}
if (idp->onlyattr > 0) {
idp_only++;
crl->idp_flags |= IDP_ONLYATTR;
}
if (idp_only > 1)
crl->idp_flags |= IDP_INVALID;
if (idp->indirectCRL > 0)
crl->idp_flags |= IDP_INDIRECT;
if (idp->onlysomereasons) {
crl->idp_flags |= IDP_REASONS;
if (idp->onlysomereasons->length > 0)
crl->idp_reasons = idp->onlysomereasons->data[0];
if (idp->onlysomereasons->length > 1)
crl->idp_reasons |=
(idp->onlysomereasons->data[1] << 8);
crl->idp_reasons &= CRLDP_ALL_REASONS;
}
DIST_POINT_set_dpname(idp->distpoint, X509_CRL_get_issuer(crl));
}
static const ASN1_AUX X509_CRL_aux = {
.app_data = NULL,
.flags = ASN1_AFLG_REFCOUNT,
.ref_offset = offsetof(X509_CRL, references),
.ref_lock = CRYPTO_LOCK_X509_CRL,
.asn1_cb = crl_cb,
};
static const ASN1_TEMPLATE X509_CRL_seq_tt[] = {
{
.offset = offsetof(X509_CRL, crl),
.field_name = "crl",
.item = &X509_CRL_INFO_it,
},
{
.offset = offsetof(X509_CRL, sig_alg),
.field_name = "sig_alg",
.item = &X509_ALGOR_it,
},
{
.offset = offsetof(X509_CRL, signature),
.field_name = "signature",
.item = &ASN1_BIT_STRING_it,
},
};
const ASN1_ITEM X509_CRL_it = {
.itype = ASN1_ITYPE_SEQUENCE,
.utype = V_ASN1_SEQUENCE,
.templates = X509_CRL_seq_tt,
.tcount = sizeof(X509_CRL_seq_tt) / sizeof(ASN1_TEMPLATE),
.funcs = &X509_CRL_aux,
.size = sizeof(X509_CRL),
.sname = "X509_CRL",
};
X509_REVOKED *
d2i_X509_REVOKED(X509_REVOKED **a, const unsigned char **in, long len)
{
return (X509_REVOKED *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&X509_REVOKED_it);
}
int
i2d_X509_REVOKED(X509_REVOKED *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_REVOKED_it);
}
X509_REVOKED *
X509_REVOKED_new(void)
{
return (X509_REVOKED *)ASN1_item_new(&X509_REVOKED_it);
}
void
X509_REVOKED_free(X509_REVOKED *a)
{
ASN1_item_free((ASN1_VALUE *)a, &X509_REVOKED_it);
}
X509_REVOKED *
X509_REVOKED_dup(X509_REVOKED *a)
{
return ASN1_item_dup(&X509_REVOKED_it, a);
}
X509_CRL_INFO *
d2i_X509_CRL_INFO(X509_CRL_INFO **a, const unsigned char **in, long len)
{
return (X509_CRL_INFO *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&X509_CRL_INFO_it);
}
int
i2d_X509_CRL_INFO(X509_CRL_INFO *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_CRL_INFO_it);
}
X509_CRL_INFO *
X509_CRL_INFO_new(void)
{
return (X509_CRL_INFO *)ASN1_item_new(&X509_CRL_INFO_it);
}
void
X509_CRL_INFO_free(X509_CRL_INFO *a)
{
ASN1_item_free((ASN1_VALUE *)a, &X509_CRL_INFO_it);
}
X509_CRL *
d2i_X509_CRL(X509_CRL **a, const unsigned char **in, long len)
{
return (X509_CRL *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&X509_CRL_it);
}
int
i2d_X509_CRL(X509_CRL *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_CRL_it);
}
X509_CRL *
X509_CRL_new(void)
{
return (X509_CRL *)ASN1_item_new(&X509_CRL_it);
}
void
X509_CRL_free(X509_CRL *a)
{
ASN1_item_free((ASN1_VALUE *)a, &X509_CRL_it);
}
X509_CRL *
X509_CRL_dup(X509_CRL *x)
{
return ASN1_item_dup(&X509_CRL_it, x);
}
static int
X509_REVOKED_cmp(const X509_REVOKED * const *a, const X509_REVOKED * const *b)
{
return(ASN1_INTEGER_cmp((*a)->serialNumber, (*b)->serialNumber));
}
int
X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev)
{
X509_CRL_INFO *inf;
inf = crl->crl;
if (!inf->revoked)
inf->revoked = sk_X509_REVOKED_new(X509_REVOKED_cmp);
if (!inf->revoked || !sk_X509_REVOKED_push(inf->revoked, rev)) {
ASN1error(ERR_R_MALLOC_FAILURE);
return 0;
}
inf->enc.modified = 1;
return 1;
}
int
X509_CRL_verify(X509_CRL *crl, EVP_PKEY *r)
{
if (crl->meth->crl_verify)
return crl->meth->crl_verify(crl, r);
return 0;
}
int
X509_CRL_get0_by_serial(X509_CRL *crl, X509_REVOKED **ret,
ASN1_INTEGER *serial)
{
if (crl->meth->crl_lookup)
return crl->meth->crl_lookup(crl, ret, serial, NULL);
return 0;
}
int
X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x)
{
if (crl->meth->crl_lookup)
return crl->meth->crl_lookup(crl, ret,
X509_get_serialNumber(x), X509_get_issuer_name(x));
return 0;
}
static int
def_crl_verify(X509_CRL *crl, EVP_PKEY *r)
{
return(ASN1_item_verify(&X509_CRL_INFO_it,
crl->sig_alg, crl->signature, crl->crl, r));
}
static int
crl_revoked_issuer_match(X509_CRL *crl, X509_NAME *nm, X509_REVOKED *rev)
{
int i;
if (!rev->issuer) {
if (!nm)
return 1;
if (!X509_NAME_cmp(nm, X509_CRL_get_issuer(crl)))
return 1;
return 0;
}
if (!nm)
nm = X509_CRL_get_issuer(crl);
for (i = 0; i < sk_GENERAL_NAME_num(rev->issuer); i++) {
GENERAL_NAME *gen = sk_GENERAL_NAME_value(rev->issuer, i);
if (gen->type != GEN_DIRNAME)
continue;
if (!X509_NAME_cmp(nm, gen->d.directoryName))
return 1;
}
return 0;
}
static int
def_crl_lookup(X509_CRL *crl, X509_REVOKED **ret, ASN1_INTEGER *serial,
X509_NAME *issuer)
{
X509_REVOKED rtmp, *rev;
int idx;
rtmp.serialNumber = serial;
/* Sort revoked into serial number order if not already sorted.
* Do this under a lock to avoid race condition.
*/
if (!sk_X509_REVOKED_is_sorted(crl->crl->revoked)) {
CRYPTO_w_lock(CRYPTO_LOCK_X509_CRL);
sk_X509_REVOKED_sort(crl->crl->revoked);
CRYPTO_w_unlock(CRYPTO_LOCK_X509_CRL);
}
idx = sk_X509_REVOKED_find(crl->crl->revoked, &rtmp);
if (idx < 0)
return 0;
/* Need to look for matching name */
for (; idx < sk_X509_REVOKED_num(crl->crl->revoked); idx++) {
rev = sk_X509_REVOKED_value(crl->crl->revoked, idx);
if (ASN1_INTEGER_cmp(rev->serialNumber, serial))
return 0;
if (crl_revoked_issuer_match(crl, issuer, rev)) {
if (ret)
*ret = rev;
if (rev->reason == CRL_REASON_REMOVE_FROM_CRL)
return 2;
return 1;
}
}
return 0;
}
void
X509_CRL_set_default_method(const X509_CRL_METHOD *meth)
{
if (meth == NULL)
default_crl_method = &int_crl_meth;
else
default_crl_method = meth;
}
X509_CRL_METHOD *
X509_CRL_METHOD_new(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))
{
X509_CRL_METHOD *m;
if ((m = calloc(1, sizeof(X509_CRL_METHOD))) == NULL)
return NULL;
m->crl_init = crl_init;
m->crl_free = crl_free;
m->crl_lookup = crl_lookup;
m->crl_verify = crl_verify;
m->flags = X509_CRL_METHOD_DYNAMIC;
return m;
}
void
X509_CRL_METHOD_free(X509_CRL_METHOD *m)
{
if (m == NULL)
return;
if (!(m->flags & X509_CRL_METHOD_DYNAMIC))
return;
free(m);
}
void
X509_CRL_set_meth_data(X509_CRL *crl, void *dat)
{
crl->meth_data = dat;
}
void *
X509_CRL_get_meth_data(X509_CRL *crl)
{
return crl->meth_data;
}
int
X509_CRL_get_signature_nid(const X509_CRL *crl)
{
return OBJ_obj2nid(crl->sig_alg->algorithm);
}
const STACK_OF(X509_EXTENSION) *
X509_CRL_get0_extensions(const X509_CRL *crl)
{
return crl->crl->extensions;
}
long
X509_CRL_get_version(const X509_CRL *crl)
{
return ASN1_INTEGER_get(crl->crl->version);
}
const ASN1_TIME *
X509_CRL_get0_lastUpdate(const X509_CRL *crl)
{
return crl->crl->lastUpdate;
}
ASN1_TIME *
X509_CRL_get_lastUpdate(X509_CRL *crl)
{
return crl->crl->lastUpdate;
}
const ASN1_TIME *
X509_CRL_get0_nextUpdate(const X509_CRL *crl)
{
return crl->crl->nextUpdate;
}
ASN1_TIME *
X509_CRL_get_nextUpdate(X509_CRL *crl)
{
return crl->crl->nextUpdate;
}
X509_NAME *
X509_CRL_get_issuer(const X509_CRL *crl)
{
return crl->crl->issuer;
}
STACK_OF(X509_REVOKED) *
X509_CRL_get_REVOKED(X509_CRL *crl)
{
return crl->crl->revoked;
}
void
X509_CRL_get0_signature(const X509_CRL *crl, const ASN1_BIT_STRING **psig,
const X509_ALGOR **palg)
{
if (psig != NULL)
*psig = crl->signature;
if (palg != NULL)
*palg = crl->sig_alg;
}
const X509_ALGOR *
X509_CRL_get0_tbs_sigalg(const X509_CRL *crl)
{
return crl->crl->sig_alg;
}

155
crypto/asn1/x_exten.c Normal file
View File

@@ -0,0 +1,155 @@
/* $OpenBSD: x_exten.c,v 1.20 2023/07/07 19:37:52 beck Exp $ */
/* 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>
#include "x509_local.h"
static const ASN1_TEMPLATE X509_EXTENSION_seq_tt[] = {
{
.offset = offsetof(X509_EXTENSION, object),
.field_name = "object",
.item = &ASN1_OBJECT_it,
},
{
.flags = ASN1_TFLG_OPTIONAL,
.offset = offsetof(X509_EXTENSION, critical),
.field_name = "critical",
.item = &ASN1_BOOLEAN_it,
},
{
.offset = offsetof(X509_EXTENSION, value),
.field_name = "value",
.item = &ASN1_OCTET_STRING_it,
},
};
const ASN1_ITEM X509_EXTENSION_it = {
.itype = ASN1_ITYPE_SEQUENCE,
.utype = V_ASN1_SEQUENCE,
.templates = X509_EXTENSION_seq_tt,
.tcount = sizeof(X509_EXTENSION_seq_tt) / sizeof(ASN1_TEMPLATE),
.size = sizeof(X509_EXTENSION),
.sname = "X509_EXTENSION",
};
static const ASN1_TEMPLATE X509_EXTENSIONS_item_tt = {
.flags = ASN1_TFLG_SEQUENCE_OF,
.tag = 0,
.offset = 0,
.field_name = "Extension",
.item = &X509_EXTENSION_it,
};
const ASN1_ITEM X509_EXTENSIONS_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = -1,
.templates = &X509_EXTENSIONS_item_tt,
.tcount = 0,
.funcs = NULL,
.size = 0,
.sname = "X509_EXTENSIONS",
};
X509_EXTENSION *
d2i_X509_EXTENSION(X509_EXTENSION **a, const unsigned char **in, long len)
{
return (X509_EXTENSION *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&X509_EXTENSION_it);
}
int
i2d_X509_EXTENSION(X509_EXTENSION *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_EXTENSION_it);
}
X509_EXTENSION *
X509_EXTENSION_new(void)
{
return (X509_EXTENSION *)ASN1_item_new(&X509_EXTENSION_it);
}
void
X509_EXTENSION_free(X509_EXTENSION *a)
{
ASN1_item_free((ASN1_VALUE *)a, &X509_EXTENSION_it);
}
X509_EXTENSIONS *
d2i_X509_EXTENSIONS(X509_EXTENSIONS **a, const unsigned char **in, long len)
{
return (X509_EXTENSIONS *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&X509_EXTENSIONS_it);
}
int
i2d_X509_EXTENSIONS(X509_EXTENSIONS *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_EXTENSIONS_it);
}
X509_EXTENSION *
X509_EXTENSION_dup(X509_EXTENSION *x)
{
return ASN1_item_dup(&X509_EXTENSION_it, x);
}

94
crypto/asn1/x_info.c Normal file
View File

@@ -0,0 +1,94 @@
/* $OpenBSD: x_info.c,v 1.20 2023/07/07 19:37:52 beck Exp $ */
/* 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 <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/x509.h>
X509_INFO *
X509_INFO_new(void)
{
X509_INFO *ret;
if ((ret = calloc(1, sizeof(X509_INFO))) == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
return (NULL);
}
ret->references = 1;
return ret;
}
void
X509_INFO_free(X509_INFO *x)
{
if (x == NULL)
return;
if (CRYPTO_add(&x->references, -1, CRYPTO_LOCK_X509_INFO) > 0)
return;
X509_free(x->x509);
X509_CRL_free(x->crl);
X509_PKEY_free(x->x_pkey);
free(x->enc_data);
free(x);
}

239
crypto/asn1/x_long.c Normal file
View File

@@ -0,0 +1,239 @@
/* $OpenBSD: x_long.c,v 1.19 2022/11/26 16:08:50 tb Exp $ */
/* 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 <limits.h>
#include <string.h>
#include <openssl/asn1t.h>
#include <openssl/bn.h>
#include <openssl/err.h>
#include "asn1_local.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 void long_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
static int long_i2c(ASN1_VALUE **pval, unsigned char *content, int *putype,
const ASN1_ITEM *it);
static int long_c2i(ASN1_VALUE **pval, const unsigned char *content, int len,
int utype, char *free_content, 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 = {
.app_data = NULL,
.flags = 0,
.prim_new = long_new,
.prim_free = long_free,
.prim_clear = long_clear,
.prim_c2i = long_c2i,
.prim_i2c = long_i2c,
.prim_print = long_print,
};
const ASN1_ITEM LONG_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_INTEGER,
.templates = NULL,
.tcount = 0,
.funcs = &long_pf,
.size = ASN1_LONG_UNDEF,
.sname = "LONG",
};
const ASN1_ITEM ZLONG_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_INTEGER,
.templates = NULL,
.tcount = 0,
.funcs = &long_pf,
.size = 0,
.sname = "ZLONG",
};
static void
long_get(ASN1_VALUE **pval, long *out_val)
{
memcpy(out_val, pval, sizeof(long));
}
static void
long_set(ASN1_VALUE **pval, long val)
{
memcpy(pval, &val, sizeof(long));
}
static int
long_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
long_clear(pval, it);
return 1;
}
static void
long_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
long_clear(pval, it);
}
static void
long_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
/* Zero value. */
long_set(pval, it->size);
}
static int
long_i2c(ASN1_VALUE **pval, unsigned char *content, int *putype,
const ASN1_ITEM *it)
{
ASN1_INTEGER *aint;
uint8_t **pp = NULL;
long val;
int ret = 0;
long_get(pval, &val);
/*
* The zero value for this type (stored in the overloaded it->size
* field) is considered to be invalid.
*/
if (val == it->size)
return -1;
if ((aint = ASN1_INTEGER_new()) == NULL)
goto err;
if (!ASN1_INTEGER_set_int64(aint, (int64_t)val))
goto err;
if (content != NULL)
pp = &content;
ret = i2c_ASN1_INTEGER(aint, pp);
err:
ASN1_INTEGER_free(aint);
return ret;
}
static int
long_c2i(ASN1_VALUE **pval, const unsigned char *content, int len, int utype,
char *free_content, const ASN1_ITEM *it)
{
ASN1_INTEGER *aint = NULL;
const uint8_t **pp = NULL;
int64_t val = 0;
int ret = 0;
/*
* The original long_i2c() mishandled 0 values and encoded them as
* content with zero length, rather than a single zero byte. Permit
* zero length content here for backwards compatibility.
*/
if (len != 0) {
if (content != NULL)
pp = &content;
if (!c2i_ASN1_INTEGER(&aint, pp, len))
goto err;
if (!ASN1_INTEGER_get_int64(&val, aint))
goto err;
}
if (val < LONG_MIN || val > LONG_MAX) {
ASN1error(ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
goto err;
}
/*
* The zero value for this type (stored in the overloaded it->size
* field) is considered to be invalid.
*/
if (val == (int64_t)it->size) {
ASN1error(ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
goto err;
}
long_set(pval, (long)val);
ret = 1;
err:
ASN1_INTEGER_free(aint);
return ret;
}
static int
long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, int indent,
const ASN1_PCTX *pctx)
{
long val;
long_get(pval, &val);
if (BIO_printf(out, "%ld\n", val) <= 0)
return 0;
return 1;
}

650
crypto/asn1/x_name.c Normal file
View File

@@ -0,0 +1,650 @@
/* $OpenBSD: x_name.c,v 1.41 2023/07/24 06:56:54 tb Exp $ */
/* 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 <ctype.h>
#include <stdio.h>
#include <string.h>
#include <openssl/asn1t.h>
#include <openssl/err.h>
#include <openssl/x509.h>
#include "asn1_local.h"
#include "x509_local.h"
typedef STACK_OF(X509_NAME_ENTRY) STACK_OF_X509_NAME_ENTRY;
DECLARE_STACK_OF(STACK_OF_X509_NAME_ENTRY)
static int x509_name_ex_d2i(ASN1_VALUE **val, const unsigned char **in,
long len, const ASN1_ITEM *it, int tag, int aclass, char opt,
ASN1_TLC *ctx);
static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out,
const ASN1_ITEM *it, int tag, int aclass);
static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it);
static void x509_name_ex_free(ASN1_VALUE **val, const ASN1_ITEM *it);
static int x509_name_encode(X509_NAME *a);
static int x509_name_canon(X509_NAME *a);
static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in);
static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname,
unsigned char **in);
static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval, int indent,
const char *fname, const ASN1_PCTX *pctx);
static const ASN1_TEMPLATE X509_NAME_ENTRY_seq_tt[] = {
{
.offset = offsetof(X509_NAME_ENTRY, object),
.field_name = "object",
.item = &ASN1_OBJECT_it,
},
{
.offset = offsetof(X509_NAME_ENTRY, value),
.field_name = "value",
.item = &ASN1_PRINTABLE_it,
},
};
const ASN1_ITEM X509_NAME_ENTRY_it = {
.itype = ASN1_ITYPE_SEQUENCE,
.utype = V_ASN1_SEQUENCE,
.templates = X509_NAME_ENTRY_seq_tt,
.tcount = sizeof(X509_NAME_ENTRY_seq_tt) / sizeof(ASN1_TEMPLATE),
.size = sizeof(X509_NAME_ENTRY),
.sname = "X509_NAME_ENTRY",
};
X509_NAME_ENTRY *
d2i_X509_NAME_ENTRY(X509_NAME_ENTRY **a, const unsigned char **in, long len)
{
return (X509_NAME_ENTRY *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&X509_NAME_ENTRY_it);
}
int
i2d_X509_NAME_ENTRY(X509_NAME_ENTRY *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_NAME_ENTRY_it);
}
X509_NAME_ENTRY *
X509_NAME_ENTRY_new(void)
{
return (X509_NAME_ENTRY *)ASN1_item_new(&X509_NAME_ENTRY_it);
}
void
X509_NAME_ENTRY_free(X509_NAME_ENTRY *a)
{
ASN1_item_free((ASN1_VALUE *)a, &X509_NAME_ENTRY_it);
}
X509_NAME_ENTRY *
X509_NAME_ENTRY_dup(X509_NAME_ENTRY *x)
{
return ASN1_item_dup(&X509_NAME_ENTRY_it, x);
}
/* For the "Name" type we need a SEQUENCE OF { SET OF X509_NAME_ENTRY }
* so declare two template wrappers for this
*/
static const ASN1_TEMPLATE X509_NAME_ENTRIES_item_tt = {
.flags = ASN1_TFLG_SET_OF,
.tag = 0,
.offset = 0,
.field_name = "RDNS",
.item = &X509_NAME_ENTRY_it,
};
const ASN1_ITEM X509_NAME_ENTRIES_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = -1,
.templates = &X509_NAME_ENTRIES_item_tt,
.tcount = 0,
.funcs = NULL,
.size = 0,
.sname = "X509_NAME_ENTRIES",
};
static const ASN1_TEMPLATE X509_NAME_INTERNAL_item_tt = {
.flags = ASN1_TFLG_SEQUENCE_OF,
.tag = 0,
.offset = 0,
.field_name = "Name",
.item = &X509_NAME_ENTRIES_it,
};
const ASN1_ITEM X509_NAME_INTERNAL_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = -1,
.templates = &X509_NAME_INTERNAL_item_tt,
.tcount = 0,
.funcs = NULL,
.size = 0,
.sname = "X509_NAME_INTERNAL",
};
/* Normally that's where it would end: we'd have two nested STACK structures
* representing the ASN1. Unfortunately X509_NAME uses a completely different
* form and caches encodings so we have to process the internal form and convert
* to the external form.
*/
const ASN1_EXTERN_FUNCS x509_name_ff = {
.app_data = NULL,
.asn1_ex_new = x509_name_ex_new,
.asn1_ex_free = x509_name_ex_free,
.asn1_ex_clear = NULL,
.asn1_ex_d2i = x509_name_ex_d2i,
.asn1_ex_i2d = x509_name_ex_i2d,
.asn1_ex_print = x509_name_ex_print,
};
const ASN1_ITEM X509_NAME_it = {
.itype = ASN1_ITYPE_EXTERN,
.utype = V_ASN1_SEQUENCE,
.templates = NULL,
.tcount = 0,
.funcs = &x509_name_ff,
.size = 0,
.sname = "X509_NAME",
};
X509_NAME *
d2i_X509_NAME(X509_NAME **a, const unsigned char **in, long len)
{
return (X509_NAME *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&X509_NAME_it);
}
int
i2d_X509_NAME(X509_NAME *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_NAME_it);
}
X509_NAME *
X509_NAME_new(void)
{
return (X509_NAME *)ASN1_item_new(&X509_NAME_it);
}
void
X509_NAME_free(X509_NAME *a)
{
ASN1_item_free((ASN1_VALUE *)a, &X509_NAME_it);
}
X509_NAME *
X509_NAME_dup(X509_NAME *x)
{
return ASN1_item_dup(&X509_NAME_it, x);
}
static int
x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it)
{
X509_NAME *ret = NULL;
ret = malloc(sizeof(X509_NAME));
if (!ret)
goto memerr;
if ((ret->entries = sk_X509_NAME_ENTRY_new_null()) == NULL)
goto memerr;
if ((ret->bytes = BUF_MEM_new()) == NULL)
goto memerr;
ret->canon_enc = NULL;
ret->canon_enclen = 0;
ret->modified = 1;
*val = (ASN1_VALUE *)ret;
return 1;
memerr:
ASN1error(ERR_R_MALLOC_FAILURE);
if (ret) {
if (ret->entries)
sk_X509_NAME_ENTRY_free(ret->entries);
free(ret);
}
return 0;
}
static void
x509_name_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
X509_NAME *a;
if (!pval || !*pval)
return;
a = (X509_NAME *)*pval;
BUF_MEM_free(a->bytes);
sk_X509_NAME_ENTRY_pop_free(a->entries, X509_NAME_ENTRY_free);
free(a->canon_enc);
free(a);
*pval = NULL;
}
static int
x509_name_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long len,
const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx)
{
const unsigned char *p = *in, *q;
union {
STACK_OF(STACK_OF_X509_NAME_ENTRY) *s;
ASN1_VALUE *a;
} intname = {NULL};
union {
X509_NAME *x;
ASN1_VALUE *a;
} nm = {NULL};
int i, j, ret;
STACK_OF(X509_NAME_ENTRY) *entries;
X509_NAME_ENTRY *entry;
q = p;
/* Get internal representation of Name */
ret = ASN1_item_ex_d2i(&intname.a, &p, len,
&X509_NAME_INTERNAL_it, tag, aclass, opt, ctx);
if (ret <= 0)
return ret;
if (*val)
x509_name_ex_free(val, NULL);
if (!x509_name_ex_new(&nm.a, NULL))
goto err;
/* We've decoded it: now cache encoding */
if (!BUF_MEM_grow(nm.x->bytes, p - q))
goto err;
memcpy(nm.x->bytes->data, q, p - q);
/* Convert internal representation to X509_NAME structure */
for (i = 0; i < sk_STACK_OF_X509_NAME_ENTRY_num(intname.s); i++) {
entries = sk_STACK_OF_X509_NAME_ENTRY_value(intname.s, i);
for (j = 0; j < sk_X509_NAME_ENTRY_num(entries); j++) {
entry = sk_X509_NAME_ENTRY_value(entries, j);
entry->set = i;
if (!sk_X509_NAME_ENTRY_push(nm.x->entries, entry))
goto err;
}
sk_X509_NAME_ENTRY_free(entries);
}
sk_STACK_OF_X509_NAME_ENTRY_free(intname.s);
ret = x509_name_canon(nm.x);
if (!ret)
goto err;
nm.x->modified = 0;
*val = nm.a;
*in = p;
return ret;
err:
if (nm.x != NULL)
X509_NAME_free(nm.x);
ASN1error(ERR_R_NESTED_ASN1_ERROR);
return 0;
}
static int
x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, const ASN1_ITEM *it,
int tag, int aclass)
{
int ret;
X509_NAME *a = (X509_NAME *)*val;
if (a->modified) {
ret = x509_name_encode(a);
if (ret < 0)
return ret;
ret = x509_name_canon(a);
if (ret < 0)
return ret;
}
ret = a->bytes->length;
if (out != NULL) {
memcpy(*out, a->bytes->data, ret);
*out += ret;
}
return ret;
}
static void
local_sk_X509_NAME_ENTRY_free(STACK_OF(X509_NAME_ENTRY) *ne)
{
sk_X509_NAME_ENTRY_free(ne);
}
static void
local_sk_X509_NAME_ENTRY_pop_free(STACK_OF(X509_NAME_ENTRY) *ne)
{
sk_X509_NAME_ENTRY_pop_free(ne, X509_NAME_ENTRY_free);
}
static int
x509_name_encode(X509_NAME *a)
{
union {
STACK_OF(STACK_OF_X509_NAME_ENTRY) *s;
ASN1_VALUE *a;
} intname = {NULL};
int len;
unsigned char *p;
STACK_OF(X509_NAME_ENTRY) *entries = NULL;
X509_NAME_ENTRY *entry;
int i, set = -1;
intname.s = sk_STACK_OF_X509_NAME_ENTRY_new_null();
if (!intname.s)
goto memerr;
for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
entry = sk_X509_NAME_ENTRY_value(a->entries, i);
if (entry->set != set) {
entries = sk_X509_NAME_ENTRY_new_null();
if (!entries)
goto memerr;
if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname.s,
entries))
goto memerr;
set = entry->set;
}
if (entries == NULL /* if entry->set is bogusly -1 */ ||
!sk_X509_NAME_ENTRY_push(entries, entry))
goto memerr;
}
len = ASN1_item_ex_i2d(&intname.a, NULL,
&X509_NAME_INTERNAL_it, -1, -1);
if (!BUF_MEM_grow(a->bytes, len))
goto memerr;
p = (unsigned char *)a->bytes->data;
ASN1_item_ex_i2d(&intname.a, &p, &X509_NAME_INTERNAL_it,
-1, -1);
sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
local_sk_X509_NAME_ENTRY_free);
a->modified = 0;
return len;
memerr:
sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
local_sk_X509_NAME_ENTRY_free);
ASN1error(ERR_R_MALLOC_FAILURE);
return -1;
}
static int
x509_name_ex_print(BIO *out, ASN1_VALUE **pval, int indent, const char *fname,
const ASN1_PCTX *pctx)
{
if (X509_NAME_print_ex(out, (X509_NAME *)*pval, indent,
pctx->nm_flags) <= 0)
return 0;
return 2;
}
/* This function generates the canonical encoding of the Name structure.
* In it all strings are converted to UTF8, leading, trailing and
* multiple spaces collapsed, converted to lower case and the leading
* SEQUENCE header removed.
*
* In future we could also normalize the UTF8 too.
*
* By doing this comparison of Name structures can be rapidly
* performed by just using memcmp() of the canonical encoding.
* By omitting the leading SEQUENCE name constraints of type
* dirName can also be checked with a simple memcmp().
*/
static int
x509_name_canon(X509_NAME *a)
{
unsigned char *p;
STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname = NULL;
STACK_OF(X509_NAME_ENTRY) *entries = NULL;
X509_NAME_ENTRY *entry, *tmpentry = NULL;
int i, len, set = -1, ret = 0;
if (a->canon_enc) {
free(a->canon_enc);
a->canon_enc = NULL;
}
/* Special case: empty X509_NAME => null encoding */
if (sk_X509_NAME_ENTRY_num(a->entries) == 0) {
a->canon_enclen = 0;
return 1;
}
intname = sk_STACK_OF_X509_NAME_ENTRY_new_null();
if (!intname)
goto err;
for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
entry = sk_X509_NAME_ENTRY_value(a->entries, i);
if (entry->set != set) {
entries = sk_X509_NAME_ENTRY_new_null();
if (!entries)
goto err;
if (sk_STACK_OF_X509_NAME_ENTRY_push(intname,
entries) == 0) {
sk_X509_NAME_ENTRY_free(entries);
goto err;
}
set = entry->set;
}
tmpentry = X509_NAME_ENTRY_new();
if (tmpentry == NULL)
goto err;
tmpentry->object = OBJ_dup(entry->object);
if (tmpentry->object == NULL)
goto err;
if (!asn1_string_canon(tmpentry->value, entry->value))
goto err;
if (entries == NULL /* if entry->set is bogusly -1 */ ||
!sk_X509_NAME_ENTRY_push(entries, tmpentry))
goto err;
tmpentry = NULL;
}
/* Finally generate encoding */
len = i2d_name_canon(intname, NULL);
if (len < 0)
goto err;
p = malloc(len);
if (p == NULL)
goto err;
a->canon_enc = p;
a->canon_enclen = len;
i2d_name_canon(intname, &p);
ret = 1;
err:
if (tmpentry)
X509_NAME_ENTRY_free(tmpentry);
if (intname)
sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname,
local_sk_X509_NAME_ENTRY_pop_free);
return ret;
}
/* Bitmap of all the types of string that will be canonicalized. */
#define ASN1_MASK_CANON \
(B_ASN1_UTF8STRING | B_ASN1_BMPSTRING | B_ASN1_UNIVERSALSTRING \
| B_ASN1_PRINTABLESTRING | B_ASN1_T61STRING | B_ASN1_IA5STRING \
| B_ASN1_VISIBLESTRING)
static int
asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in)
{
unsigned char *to, *from;
int len, i;
/* If type not in bitmask just copy string across */
if (!(ASN1_tag2bit(in->type) & ASN1_MASK_CANON)) {
if (!ASN1_STRING_copy(out, in))
return 0;
return 1;
}
out->type = V_ASN1_UTF8STRING;
out->length = ASN1_STRING_to_UTF8(&out->data, in);
if (out->length == -1)
return 0;
to = out->data;
from = to;
len = out->length;
/* Convert string in place to canonical form.
* Ultimately we may need to handle a wider range of characters
* but for now ignore anything with MSB set and rely on the
* isspace() and tolower() functions.
*/
/* Ignore leading spaces */
while ((len > 0) && !(*from & 0x80) && isspace(*from)) {
from++;
len--;
}
to = from + len - 1;
/* Ignore trailing spaces */
while ((len > 0) && !(*to & 0x80) && isspace(*to)) {
to--;
len--;
}
to = out->data;
i = 0;
while (i < len) {
/* If MSB set just copy across */
if (*from & 0x80) {
*to++ = *from++;
i++;
}
/* Collapse multiple spaces */
else if (isspace(*from)) {
/* Copy one space across */
*to++ = ' ';
/* Ignore subsequent spaces. Note: don't need to
* check len here because we know the last
* character is a non-space so we can't overflow.
*/
do {
from++;
i++;
} while (!(*from & 0x80) && isspace(*from));
} else {
*to++ = tolower(*from);
from++;
i++;
}
}
out->length = to - out->data;
return 1;
}
static int
i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) *_intname, unsigned char **in)
{
int i, len, ltmp;
ASN1_VALUE *v;
STACK_OF(ASN1_VALUE) *intname = (STACK_OF(ASN1_VALUE) *)_intname;
len = 0;
for (i = 0; i < sk_ASN1_VALUE_num(intname); i++) {
v = sk_ASN1_VALUE_value(intname, i);
ltmp = ASN1_item_ex_i2d(&v, in,
&X509_NAME_ENTRIES_it, -1, -1);
if (ltmp < 0)
return ltmp;
len += ltmp;
}
return len;
}
int
X509_NAME_set(X509_NAME **xn, X509_NAME *name)
{
if (*xn == name)
return *xn != NULL;
if ((name = X509_NAME_dup(name)) == NULL)
return 0;
X509_NAME_free(*xn);
*xn = name;
return 1;
}
int
X509_NAME_get0_der(X509_NAME *nm, const unsigned char **pder, size_t *pderlen)
{
/* Make sure encoding is valid. */
if (i2d_X509_NAME(nm, NULL) <= 0)
return 0;
if (pder != NULL)
*pder = (unsigned char *)nm->bytes->data;
if (pderlen != NULL)
*pderlen = nm->bytes->length;
return 1;
}

121
crypto/asn1/x_pkey.c Normal file
View File

@@ -0,0 +1,121 @@
/* $OpenBSD: x_pkey.c,v 1.23 2023/07/07 19:37:53 beck Exp $ */
/* 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 <string.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
X509_PKEY *
X509_PKEY_new(void)
{
X509_PKEY *ret = NULL;
if ((ret = malloc(sizeof(X509_PKEY))) == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
goto err;
}
ret->version = 0;
if ((ret->enc_algor = X509_ALGOR_new()) == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
goto err;
}
if ((ret->enc_pkey = ASN1_OCTET_STRING_new()) == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
goto err;
}
ret->dec_pkey = NULL;
ret->key_length = 0;
ret->key_data = NULL;
ret->key_free = 0;
ret->cipher.cipher = NULL;
memset(ret->cipher.iv, 0, EVP_MAX_IV_LENGTH);
ret->references = 1;
return (ret);
err:
if (ret) {
X509_ALGOR_free(ret->enc_algor);
free(ret);
}
return NULL;
}
void
X509_PKEY_free(X509_PKEY *x)
{
int i;
if (x == NULL)
return;
i = CRYPTO_add(&x->references, -1, CRYPTO_LOCK_X509_PKEY);
if (i > 0)
return;
if (x->enc_algor != NULL)
X509_ALGOR_free(x->enc_algor);
ASN1_OCTET_STRING_free(x->enc_pkey);
EVP_PKEY_free(x->dec_pkey);
if ((x->key_data != NULL) && (x->key_free))
free(x->key_data);
free(x);
}

741
crypto/asn1/x_pubkey.c Normal file
View File

@@ -0,0 +1,741 @@
/* $OpenBSD: x_pubkey.c,v 1.35 2023/07/07 19:37:53 beck Exp $ */
/* 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 <openssl/opensslconf.h>
#include <openssl/asn1t.h>
#include <openssl/err.h>
#include <openssl/x509.h>
#ifndef OPENSSL_NO_DSA
#include <openssl/dsa.h>
#endif
#ifndef OPENSSL_NO_RSA
#include <openssl/rsa.h>
#endif
#include "asn1_local.h"
#include "evp_local.h"
#include "x509_local.h"
/* 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;
}
static const ASN1_AUX X509_PUBKEY_aux = {
.asn1_cb = pubkey_cb,
};
static const ASN1_TEMPLATE X509_PUBKEY_seq_tt[] = {
{
.offset = offsetof(X509_PUBKEY, algor),
.field_name = "algor",
.item = &X509_ALGOR_it,
},
{
.offset = offsetof(X509_PUBKEY, public_key),
.field_name = "public_key",
.item = &ASN1_BIT_STRING_it,
},
};
const ASN1_ITEM X509_PUBKEY_it = {
.itype = ASN1_ITYPE_SEQUENCE,
.utype = V_ASN1_SEQUENCE,
.templates = X509_PUBKEY_seq_tt,
.tcount = sizeof(X509_PUBKEY_seq_tt) / sizeof(ASN1_TEMPLATE),
.funcs = &X509_PUBKEY_aux,
.size = sizeof(X509_PUBKEY),
.sname = "X509_PUBKEY",
};
X509_PUBKEY *
d2i_X509_PUBKEY(X509_PUBKEY **a, const unsigned char **in, long len)
{
return (X509_PUBKEY *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&X509_PUBKEY_it);
}
int
i2d_X509_PUBKEY(X509_PUBKEY *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_PUBKEY_it);
}
X509_PUBKEY *
X509_PUBKEY_new(void)
{
return (X509_PUBKEY *)ASN1_item_new(&X509_PUBKEY_it);
}
void
X509_PUBKEY_free(X509_PUBKEY *a)
{
ASN1_item_free((ASN1_VALUE *)a, &X509_PUBKEY_it);
}
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)) {
X509error(X509_R_PUBLIC_KEY_ENCODE_ERROR);
goto error;
}
} else {
X509error(X509_R_METHOD_NOT_SUPPORTED);
goto error;
}
} else {
X509error(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_get0(X509_PUBKEY *key)
{
EVP_PKEY *ret = NULL;
if (key == NULL)
goto error;
if (key->pkey != NULL)
return key->pkey;
if (key->public_key == NULL)
goto error;
if ((ret = EVP_PKEY_new()) == NULL) {
X509error(ERR_R_MALLOC_FAILURE);
goto error;
}
if (!EVP_PKEY_set_type(ret, OBJ_obj2nid(key->algor->algorithm))) {
X509error(X509_R_UNSUPPORTED_ALGORITHM);
goto error;
}
if (ret->ameth->pub_decode) {
if (!ret->ameth->pub_decode(ret, key)) {
X509error(X509_R_PUBLIC_KEY_DECODE_ERROR);
goto error;
}
} else {
X509error(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);
}
return ret;
error:
EVP_PKEY_free(ret);
return (NULL);
}
EVP_PKEY *
X509_PUBKEY_get(X509_PUBKEY *key)
{
EVP_PKEY *pkey;
if ((pkey = X509_PUBKEY_get0(key)) == NULL)
return (NULL);
CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
return pkey;
}
/*
* Decode an X509_PUBKEY into the specified key type.
*/
static int
pubkey_ex_d2i(int pkey_type, ASN1_VALUE **pval, const unsigned char **in,
long len, const ASN1_ITEM *it)
{
const ASN1_EXTERN_FUNCS *ef = it->funcs;
const unsigned char *p = *in;
X509_PUBKEY *xpk = NULL;
ASN1_VALUE *key = NULL;
EVP_PKEY *pkey = NULL;
int ret = 0;
if ((xpk = d2i_X509_PUBKEY(NULL, &p, len)) == NULL)
goto err;
if ((pkey = X509_PUBKEY_get(xpk)) == NULL)
goto err;
switch (pkey_type) {
case EVP_PKEY_NONE:
key = (ASN1_VALUE *)pkey;
pkey = NULL;
break;
case EVP_PKEY_DSA:
key = (ASN1_VALUE *)EVP_PKEY_get1_DSA(pkey);
break;
case EVP_PKEY_RSA:
key = (ASN1_VALUE *)EVP_PKEY_get1_RSA(pkey);
break;
case EVP_PKEY_EC:
key = (ASN1_VALUE *)EVP_PKEY_get1_EC_KEY(pkey);
break;
default:
goto err;
}
if (key == NULL)
goto err;
ef->asn1_ex_free(pval, it);
*pval = key;
*in = p;
ret = 1;
err:
EVP_PKEY_free(pkey);
X509_PUBKEY_free(xpk);
return ret;
}
/*
* Encode the specified key type into an X509_PUBKEY.
*/
static int
pubkey_ex_i2d(int pkey_type, ASN1_VALUE **pval, unsigned char **out,
const ASN1_ITEM *it)
{
X509_PUBKEY *xpk = NULL;
EVP_PKEY *pkey, *pktmp;
int ret = -1;
if ((pkey = pktmp = EVP_PKEY_new()) == NULL)
goto err;
switch (pkey_type) {
case EVP_PKEY_NONE:
pkey = (EVP_PKEY *)*pval;
break;
case EVP_PKEY_DSA:
if (!EVP_PKEY_set1_DSA(pkey, (DSA *)*pval))
goto err;
break;
case EVP_PKEY_RSA:
if (!EVP_PKEY_set1_RSA(pkey, (RSA *)*pval))
goto err;
break;
case EVP_PKEY_EC:
if (!EVP_PKEY_set1_EC_KEY(pkey, (EC_KEY*)*pval))
goto err;
break;
default:
goto err;
}
if (!X509_PUBKEY_set(&xpk, pkey))
goto err;
ret = i2d_X509_PUBKEY(xpk, out);
err:
EVP_PKEY_free(pktmp);
X509_PUBKEY_free(xpk);
return ret;
}
static int
pkey_pubkey_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
if ((*pval = (ASN1_VALUE *)EVP_PKEY_new()) == NULL)
return 0;
return 1;
}
static void
pkey_pubkey_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
EVP_PKEY_free((EVP_PKEY *)*pval);
*pval = NULL;
}
static int
pkey_pubkey_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx)
{
return pubkey_ex_d2i(EVP_PKEY_NONE, pval, in, len, it);
}
static int
pkey_pubkey_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it,
int tag, int aclass)
{
return pubkey_ex_i2d(EVP_PKEY_NONE, pval, out, it);
}
const ASN1_EXTERN_FUNCS pkey_pubkey_asn1_ff = {
.app_data = NULL,
.asn1_ex_new = pkey_pubkey_ex_new,
.asn1_ex_free = pkey_pubkey_ex_free,
.asn1_ex_clear = NULL,
.asn1_ex_d2i = pkey_pubkey_ex_d2i,
.asn1_ex_i2d = pkey_pubkey_ex_i2d,
.asn1_ex_print = NULL,
};
const ASN1_ITEM EVP_PKEY_PUBKEY_it = {
.itype = ASN1_ITYPE_EXTERN,
.utype = 0,
.templates = NULL,
.tcount = 0,
.funcs = &pkey_pubkey_asn1_ff,
.size = 0,
.sname = NULL,
};
EVP_PKEY *
d2i_PUBKEY(EVP_PKEY **pkey, const unsigned char **in, long len)
{
return (EVP_PKEY *)ASN1_item_d2i((ASN1_VALUE **)pkey, in, len,
&EVP_PKEY_PUBKEY_it);
}
int
i2d_PUBKEY(EVP_PKEY *pkey, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)pkey, out, &EVP_PKEY_PUBKEY_it);
}
EVP_PKEY *
d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **pkey)
{
return (EVP_PKEY *)ASN1_item_d2i_bio(&EVP_PKEY_PUBKEY_it, bp,
(ASN1_VALUE **)pkey);
}
int
i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey)
{
return ASN1_item_i2d_bio(&EVP_PKEY_PUBKEY_it, bp, (ASN1_VALUE *)pkey);
}
EVP_PKEY *
d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **pkey)
{
return (EVP_PKEY *)ASN1_item_d2i_fp(&EVP_PKEY_PUBKEY_it, fp,
(ASN1_VALUE **)pkey);
}
int
i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey)
{
return ASN1_item_i2d_fp(&EVP_PKEY_PUBKEY_it, fp, (ASN1_VALUE *)pkey);
}
/*
* The following are equivalents but which return RSA and DSA keys.
*/
#ifndef OPENSSL_NO_RSA
static int
rsa_pubkey_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
if ((*pval = (ASN1_VALUE *)RSA_new()) == NULL)
return 0;
return 1;
}
static void
rsa_pubkey_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
RSA_free((RSA *)*pval);
*pval = NULL;
}
static int
rsa_pubkey_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx)
{
return pubkey_ex_d2i(EVP_PKEY_RSA, pval, in, len, it);
}
static int
rsa_pubkey_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it,
int tag, int aclass)
{
return pubkey_ex_i2d(EVP_PKEY_RSA, pval, out, it);
}
const ASN1_EXTERN_FUNCS rsa_pubkey_asn1_ff = {
.app_data = NULL,
.asn1_ex_new = rsa_pubkey_ex_new,
.asn1_ex_free = rsa_pubkey_ex_free,
.asn1_ex_clear = NULL,
.asn1_ex_d2i = rsa_pubkey_ex_d2i,
.asn1_ex_i2d = rsa_pubkey_ex_i2d,
.asn1_ex_print = NULL,
};
const ASN1_ITEM RSA_PUBKEY_it = {
.itype = ASN1_ITYPE_EXTERN,
.utype = 0,
.templates = NULL,
.tcount = 0,
.funcs = &rsa_pubkey_asn1_ff,
.size = 0,
.sname = NULL,
};
RSA *
d2i_RSA_PUBKEY(RSA **rsa, const unsigned char **in, long len)
{
return (RSA *)ASN1_item_d2i((ASN1_VALUE **)rsa, in, len,
&RSA_PUBKEY_it);
}
int
i2d_RSA_PUBKEY(RSA *rsa, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)rsa, out, &RSA_PUBKEY_it);
}
RSA *
d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa)
{
return (RSA *)ASN1_item_d2i_bio(&RSA_PUBKEY_it, bp, (ASN1_VALUE **)rsa);
}
int
i2d_RSA_PUBKEY_bio(BIO *bp, RSA *rsa)
{
return ASN1_item_i2d_bio(&RSA_PUBKEY_it, bp, (ASN1_VALUE *)rsa);
}
RSA *
d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa)
{
return (RSA *)ASN1_item_d2i_fp(&RSA_PUBKEY_it, fp, (ASN1_VALUE **)rsa);
}
int
i2d_RSA_PUBKEY_fp(FILE *fp, RSA *rsa)
{
return ASN1_item_i2d_fp(&RSA_PUBKEY_it, fp, (ASN1_VALUE *)rsa);
}
#endif
#ifndef OPENSSL_NO_DSA
static int
dsa_pubkey_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
if ((*pval = (ASN1_VALUE *)DSA_new()) == NULL)
return 0;
return 1;
}
static void
dsa_pubkey_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
DSA_free((DSA *)*pval);
*pval = NULL;
}
static int
dsa_pubkey_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx)
{
return pubkey_ex_d2i(EVP_PKEY_DSA, pval, in, len, it);
}
static int
dsa_pubkey_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it,
int tag, int aclass)
{
return pubkey_ex_i2d(EVP_PKEY_DSA, pval, out, it);
}
const ASN1_EXTERN_FUNCS dsa_pubkey_asn1_ff = {
.app_data = NULL,
.asn1_ex_new = dsa_pubkey_ex_new,
.asn1_ex_free = dsa_pubkey_ex_free,
.asn1_ex_clear = NULL,
.asn1_ex_d2i = dsa_pubkey_ex_d2i,
.asn1_ex_i2d = dsa_pubkey_ex_i2d,
.asn1_ex_print = NULL,
};
const ASN1_ITEM DSA_PUBKEY_it = {
.itype = ASN1_ITYPE_EXTERN,
.utype = 0,
.templates = NULL,
.tcount = 0,
.funcs = &dsa_pubkey_asn1_ff,
.size = 0,
.sname = NULL,
};
DSA *
d2i_DSA_PUBKEY(DSA **dsa, const unsigned char **in, long len)
{
return (DSA *)ASN1_item_d2i((ASN1_VALUE **)dsa, in, len,
&DSA_PUBKEY_it);
}
int
i2d_DSA_PUBKEY(DSA *dsa, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)dsa, out, &DSA_PUBKEY_it);
}
DSA *
d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa)
{
return (DSA *)ASN1_item_d2i_bio(&DSA_PUBKEY_it, bp, (ASN1_VALUE **)dsa);
}
int
i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa)
{
return ASN1_item_i2d_bio(&DSA_PUBKEY_it, bp, (ASN1_VALUE *)dsa);
}
DSA *
d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa)
{
return (DSA *)ASN1_item_d2i_fp(&DSA_PUBKEY_it, fp, (ASN1_VALUE **)dsa);
}
int
i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa)
{
return ASN1_item_i2d_fp(&DSA_PUBKEY_it, fp, (ASN1_VALUE *)dsa);
}
#endif
#ifndef OPENSSL_NO_EC
static int
ec_pubkey_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
if ((*pval = (ASN1_VALUE *)EC_KEY_new()) == NULL)
return 0;
return 1;
}
static void
ec_pubkey_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
EC_KEY_free((EC_KEY *)*pval);
*pval = NULL;
}
static int
ec_pubkey_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx)
{
return pubkey_ex_d2i(EVP_PKEY_EC, pval, in, len, it);
}
static int
ec_pubkey_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it,
int tag, int aclass)
{
return pubkey_ex_i2d(EVP_PKEY_EC, pval, out, it);
}
const ASN1_EXTERN_FUNCS ec_pubkey_asn1_ff = {
.app_data = NULL,
.asn1_ex_new = ec_pubkey_ex_new,
.asn1_ex_free = ec_pubkey_ex_free,
.asn1_ex_clear = NULL,
.asn1_ex_d2i = ec_pubkey_ex_d2i,
.asn1_ex_i2d = ec_pubkey_ex_i2d,
.asn1_ex_print = NULL,
};
const ASN1_ITEM EC_PUBKEY_it = {
.itype = ASN1_ITYPE_EXTERN,
.utype = 0,
.templates = NULL,
.tcount = 0,
.funcs = &ec_pubkey_asn1_ff,
.size = 0,
.sname = NULL,
};
EC_KEY *
d2i_EC_PUBKEY(EC_KEY **ec, const unsigned char **in, long len)
{
return (EC_KEY *)ASN1_item_d2i((ASN1_VALUE **)ec, in, len,
&EC_PUBKEY_it);
}
int
i2d_EC_PUBKEY(EC_KEY *ec, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)ec, out, &EC_PUBKEY_it);
}
EC_KEY *
d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **ec)
{
return (EC_KEY *)ASN1_item_d2i_bio(&EC_PUBKEY_it, bp, (ASN1_VALUE **)ec);
}
int
i2d_EC_PUBKEY_bio(BIO *bp, EC_KEY *ec)
{
return ASN1_item_i2d_bio(&EC_PUBKEY_it, bp, (ASN1_VALUE *)ec);
}
EC_KEY *
d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **ec)
{
return (EC_KEY *)ASN1_item_d2i_fp(&EC_PUBKEY_it, fp, (ASN1_VALUE **)ec);
}
int
i2d_EC_PUBKEY_fp(FILE *fp, EC_KEY *ec)
{
return ASN1_item_i2d_fp(&EC_PUBKEY_it, fp, (ASN1_VALUE *)ec);
}
#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 == NULL)
return 1;
ASN1_STRING_set0(pub->public_key, penc, penclen);
return asn1_abs_set_unused_bits(pub->public_key, 0);
}
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;
}

245
crypto/asn1/x_req.c Normal file
View File

@@ -0,0 +1,245 @@
/* $OpenBSD: x_req.c,v 1.21 2023/07/07 19:37:53 beck Exp $ */
/* 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 <openssl/asn1t.h>
#include <openssl/x509.h>
#include "x509_local.h"
/* X509_REQ_INFO is handled in an unusual way to get round
* invalid encodings. Some broken certificate requests don't
* encode the attributes field if it is empty. This is in
* violation of PKCS#10 but we need to tolerate it. We do
* this by making the attributes field OPTIONAL then using
* the callback to initialise it to an empty STACK.
*
* This means that the field will be correctly encoded unless
* we NULL out the field.
*
* As a result we no longer need the req_kludge field because
* the information is now contained in the attributes field:
* 1. If it is NULL then it's the invalid omission.
* 2. If it is empty it is the correct encoding.
* 3. If it is not empty then some attributes are present.
*
*/
static int
rinf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
{
X509_REQ_INFO *rinf = (X509_REQ_INFO *)*pval;
if (operation == ASN1_OP_NEW_POST) {
rinf->attributes = sk_X509_ATTRIBUTE_new_null();
if (!rinf->attributes)
return 0;
}
return 1;
}
static const ASN1_AUX X509_REQ_INFO_aux = {
.flags = ASN1_AFLG_ENCODING,
.asn1_cb = rinf_cb,
.enc_offset = offsetof(X509_REQ_INFO, enc),
};
static const ASN1_TEMPLATE X509_REQ_INFO_seq_tt[] = {
{
.offset = offsetof(X509_REQ_INFO, version),
.field_name = "version",
.item = &ASN1_INTEGER_it,
},
{
.offset = offsetof(X509_REQ_INFO, subject),
.field_name = "subject",
.item = &X509_NAME_it,
},
{
.offset = offsetof(X509_REQ_INFO, pubkey),
.field_name = "pubkey",
.item = &X509_PUBKEY_it,
},
/* This isn't really OPTIONAL but it gets round invalid
* encodings
*/
{
.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SET_OF | ASN1_TFLG_OPTIONAL,
.offset = offsetof(X509_REQ_INFO, attributes),
.field_name = "attributes",
.item = &X509_ATTRIBUTE_it,
},
};
const ASN1_ITEM X509_REQ_INFO_it = {
.itype = ASN1_ITYPE_SEQUENCE,
.utype = V_ASN1_SEQUENCE,
.templates = X509_REQ_INFO_seq_tt,
.tcount = sizeof(X509_REQ_INFO_seq_tt) / sizeof(ASN1_TEMPLATE),
.funcs = &X509_REQ_INFO_aux,
.size = sizeof(X509_REQ_INFO),
.sname = "X509_REQ_INFO",
};
X509_REQ_INFO *
d2i_X509_REQ_INFO(X509_REQ_INFO **a, const unsigned char **in, long len)
{
return (X509_REQ_INFO *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&X509_REQ_INFO_it);
}
int
i2d_X509_REQ_INFO(X509_REQ_INFO *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_REQ_INFO_it);
}
X509_REQ_INFO *
X509_REQ_INFO_new(void)
{
return (X509_REQ_INFO *)ASN1_item_new(&X509_REQ_INFO_it);
}
void
X509_REQ_INFO_free(X509_REQ_INFO *a)
{
ASN1_item_free((ASN1_VALUE *)a, &X509_REQ_INFO_it);
}
static const ASN1_AUX X509_REQ_aux = {
.app_data = NULL,
.flags = ASN1_AFLG_REFCOUNT,
.ref_offset = offsetof(X509_REQ, references),
.ref_lock = CRYPTO_LOCK_X509_REQ,
};
static const ASN1_TEMPLATE X509_REQ_seq_tt[] = {
{
.offset = offsetof(X509_REQ, req_info),
.field_name = "req_info",
.item = &X509_REQ_INFO_it,
},
{
.offset = offsetof(X509_REQ, sig_alg),
.field_name = "sig_alg",
.item = &X509_ALGOR_it,
},
{
.offset = offsetof(X509_REQ, signature),
.field_name = "signature",
.item = &ASN1_BIT_STRING_it,
},
};
const ASN1_ITEM X509_REQ_it = {
.itype = ASN1_ITYPE_SEQUENCE,
.utype = V_ASN1_SEQUENCE,
.templates = X509_REQ_seq_tt,
.tcount = sizeof(X509_REQ_seq_tt) / sizeof(ASN1_TEMPLATE),
.funcs = &X509_REQ_aux,
.size = sizeof(X509_REQ),
.sname = "X509_REQ",
};
X509_REQ *
d2i_X509_REQ(X509_REQ **a, const unsigned char **in, long len)
{
return (X509_REQ *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&X509_REQ_it);
}
int
i2d_X509_REQ(X509_REQ *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_REQ_it);
}
X509_REQ *
X509_REQ_new(void)
{
return (X509_REQ *)ASN1_item_new(&X509_REQ_it);
}
void
X509_REQ_free(X509_REQ *a)
{
ASN1_item_free((ASN1_VALUE *)a, &X509_REQ_it);
}
X509_REQ *
X509_REQ_dup(X509_REQ *x)
{
return ASN1_item_dup(&X509_REQ_it, x);
}
int
X509_REQ_get_signature_nid(const X509_REQ *req)
{
return OBJ_obj2nid(req->sig_alg->algorithm);
}
void
X509_REQ_get0_signature(const X509_REQ *req, const ASN1_BIT_STRING **psig,
const X509_ALGOR **palg)
{
if (psig != NULL)
*psig = req->signature;
if (palg != NULL)
*palg = req->sig_alg;
}

131
crypto/asn1/x_sig.c Normal file
View File

@@ -0,0 +1,131 @@
/* $OpenBSD: x_sig.c,v 1.16 2023/07/07 19:37:53 beck Exp $ */
/* 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 <openssl/asn1t.h>
#include <openssl/x509.h>
#include "x509_local.h"
static const ASN1_TEMPLATE X509_SIG_seq_tt[] = {
{
.offset = offsetof(X509_SIG, algor),
.field_name = "algor",
.item = &X509_ALGOR_it,
},
{
.offset = offsetof(X509_SIG, digest),
.field_name = "digest",
.item = &ASN1_OCTET_STRING_it,
},
};
const ASN1_ITEM X509_SIG_it = {
.itype = ASN1_ITYPE_SEQUENCE,
.utype = V_ASN1_SEQUENCE,
.templates = X509_SIG_seq_tt,
.tcount = sizeof(X509_SIG_seq_tt) / sizeof(ASN1_TEMPLATE),
.size = sizeof(X509_SIG),
.sname = "X509_SIG",
};
X509_SIG *
d2i_X509_SIG(X509_SIG **a, const unsigned char **in, long len)
{
return (X509_SIG *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&X509_SIG_it);
}
int
i2d_X509_SIG(X509_SIG *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_SIG_it);
}
X509_SIG *
X509_SIG_new(void)
{
return (X509_SIG *)ASN1_item_new(&X509_SIG_it);
}
void
X509_SIG_free(X509_SIG *a)
{
ASN1_item_free((ASN1_VALUE *)a, &X509_SIG_it);
}
void
X509_SIG_get0(const X509_SIG *sig, const X509_ALGOR **palg,
const ASN1_OCTET_STRING **pdigest)
{
if (palg != NULL)
*palg = sig->algor;
if (pdigest != NULL)
*pdigest = sig->digest;
}
void
X509_SIG_getm(X509_SIG *sig, X509_ALGOR **palg, ASN1_OCTET_STRING **pdigest)
{
if (palg != NULL)
*palg = sig->algor;
if (pdigest != NULL)
*pdigest = sig->digest;
}

174
crypto/asn1/x_spki.c Normal file
View File

@@ -0,0 +1,174 @@
/* $OpenBSD: x_spki.c,v 1.13 2023/07/07 19:37:53 beck Exp $ */
/* 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.]
*/
/* This module was send to me my Pat Richards <patr@x509.com> who
* wrote it. It is under my Copyright with his permission
*/
#include <stdio.h>
#include <openssl/x509.h>
#include <openssl/asn1t.h>
static const ASN1_TEMPLATE NETSCAPE_SPKAC_seq_tt[] = {
{
.offset = offsetof(NETSCAPE_SPKAC, pubkey),
.field_name = "pubkey",
.item = &X509_PUBKEY_it,
},
{
.offset = offsetof(NETSCAPE_SPKAC, challenge),
.field_name = "challenge",
.item = &ASN1_IA5STRING_it,
},
};
const ASN1_ITEM NETSCAPE_SPKAC_it = {
.itype = ASN1_ITYPE_SEQUENCE,
.utype = V_ASN1_SEQUENCE,
.templates = NETSCAPE_SPKAC_seq_tt,
.tcount = sizeof(NETSCAPE_SPKAC_seq_tt) / sizeof(ASN1_TEMPLATE),
.size = sizeof(NETSCAPE_SPKAC),
.sname = "NETSCAPE_SPKAC",
};
NETSCAPE_SPKAC *
d2i_NETSCAPE_SPKAC(NETSCAPE_SPKAC **a, const unsigned char **in, long len)
{
return (NETSCAPE_SPKAC *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&NETSCAPE_SPKAC_it);
}
int
i2d_NETSCAPE_SPKAC(NETSCAPE_SPKAC *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &NETSCAPE_SPKAC_it);
}
NETSCAPE_SPKAC *
NETSCAPE_SPKAC_new(void)
{
return (NETSCAPE_SPKAC *)ASN1_item_new(&NETSCAPE_SPKAC_it);
}
void
NETSCAPE_SPKAC_free(NETSCAPE_SPKAC *a)
{
ASN1_item_free((ASN1_VALUE *)a, &NETSCAPE_SPKAC_it);
}
static const ASN1_TEMPLATE NETSCAPE_SPKI_seq_tt[] = {
{
.flags = 0,
.tag = 0,
.offset = offsetof(NETSCAPE_SPKI, spkac),
.field_name = "spkac",
.item = &NETSCAPE_SPKAC_it,
},
{
.flags = 0,
.tag = 0,
.offset = offsetof(NETSCAPE_SPKI, sig_algor),
.field_name = "sig_algor",
.item = &X509_ALGOR_it,
},
{
.flags = 0,
.tag = 0,
.offset = offsetof(NETSCAPE_SPKI, signature),
.field_name = "signature",
.item = &ASN1_BIT_STRING_it,
},
};
const ASN1_ITEM NETSCAPE_SPKI_it = {
.itype = ASN1_ITYPE_SEQUENCE,
.utype = V_ASN1_SEQUENCE,
.templates = NETSCAPE_SPKI_seq_tt,
.tcount = sizeof(NETSCAPE_SPKI_seq_tt) / sizeof(ASN1_TEMPLATE),
.funcs = NULL,
.size = sizeof(NETSCAPE_SPKI),
.sname = "NETSCAPE_SPKI",
};
NETSCAPE_SPKI *
d2i_NETSCAPE_SPKI(NETSCAPE_SPKI **a, const unsigned char **in, long len)
{
return (NETSCAPE_SPKI *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&NETSCAPE_SPKI_it);
}
int
i2d_NETSCAPE_SPKI(NETSCAPE_SPKI *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &NETSCAPE_SPKI_it);
}
NETSCAPE_SPKI *
NETSCAPE_SPKI_new(void)
{
return (NETSCAPE_SPKI *)ASN1_item_new(&NETSCAPE_SPKI_it);
}
void
NETSCAPE_SPKI_free(NETSCAPE_SPKI *a)
{
ASN1_item_free((ASN1_VALUE *)a, &NETSCAPE_SPKI_it);
}

110
crypto/asn1/x_val.c Normal file
View File

@@ -0,0 +1,110 @@
/* $OpenBSD: x_val.c,v 1.13 2023/07/07 19:37:53 beck Exp $ */
/* 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 <openssl/asn1t.h>
#include <openssl/x509.h>
static const ASN1_TEMPLATE X509_VAL_seq_tt[] = {
{
.offset = offsetof(X509_VAL, notBefore),
.field_name = "notBefore",
.item = &ASN1_TIME_it,
},
{
.offset = offsetof(X509_VAL, notAfter),
.field_name = "notAfter",
.item = &ASN1_TIME_it,
},
};
const ASN1_ITEM X509_VAL_it = {
.itype = ASN1_ITYPE_SEQUENCE,
.utype = V_ASN1_SEQUENCE,
.templates = X509_VAL_seq_tt,
.tcount = sizeof(X509_VAL_seq_tt) / sizeof(ASN1_TEMPLATE),
.size = sizeof(X509_VAL),
.sname = "X509_VAL",
};
X509_VAL *
d2i_X509_VAL(X509_VAL **a, const unsigned char **in, long len)
{
return (X509_VAL *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&X509_VAL_it);
}
int
i2d_X509_VAL(X509_VAL *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_VAL_it);
}
X509_VAL *
X509_VAL_new(void)
{
return (X509_VAL *)ASN1_item_new(&X509_VAL_it);
}
void
X509_VAL_free(X509_VAL *a)
{
ASN1_item_free((ASN1_VALUE *)a, &X509_VAL_it);
}

376
crypto/asn1/x_x509.c Normal file
View File

@@ -0,0 +1,376 @@
/* $OpenBSD: x_x509.c,v 1.37 2023/07/07 19:37:53 beck Exp $ */
/* 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 <openssl/opensslconf.h>
#include <openssl/asn1t.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include "x509_local.h"
static const ASN1_AUX X509_CINF_aux = {
.flags = ASN1_AFLG_ENCODING,
.enc_offset = offsetof(X509_CINF, enc),
};
static const ASN1_TEMPLATE X509_CINF_seq_tt[] = {
{
.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
.offset = offsetof(X509_CINF, version),
.field_name = "version",
.item = &ASN1_INTEGER_it,
},
{
.offset = offsetof(X509_CINF, serialNumber),
.field_name = "serialNumber",
.item = &ASN1_INTEGER_it,
},
{
.offset = offsetof(X509_CINF, signature),
.field_name = "signature",
.item = &X509_ALGOR_it,
},
{
.offset = offsetof(X509_CINF, issuer),
.field_name = "issuer",
.item = &X509_NAME_it,
},
{
.offset = offsetof(X509_CINF, validity),
.field_name = "validity",
.item = &X509_VAL_it,
},
{
.offset = offsetof(X509_CINF, subject),
.field_name = "subject",
.item = &X509_NAME_it,
},
{
.offset = offsetof(X509_CINF, key),
.field_name = "key",
.item = &X509_PUBKEY_it,
},
{
.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL,
.tag = 1,
.offset = offsetof(X509_CINF, issuerUID),
.field_name = "issuerUID",
.item = &ASN1_BIT_STRING_it,
},
{
.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL,
.tag = 2,
.offset = offsetof(X509_CINF, subjectUID),
.field_name = "subjectUID",
.item = &ASN1_BIT_STRING_it,
},
{
.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_SEQUENCE_OF |
ASN1_TFLG_OPTIONAL,
.tag = 3,
.offset = offsetof(X509_CINF, extensions),
.field_name = "extensions",
.item = &X509_EXTENSION_it,
},
};
const ASN1_ITEM X509_CINF_it = {
.itype = ASN1_ITYPE_SEQUENCE,
.utype = V_ASN1_SEQUENCE,
.templates = X509_CINF_seq_tt,
.tcount = sizeof(X509_CINF_seq_tt) / sizeof(ASN1_TEMPLATE),
.funcs = &X509_CINF_aux,
.size = sizeof(X509_CINF),
.sname = "X509_CINF",
};
X509_CINF *
d2i_X509_CINF(X509_CINF **a, const unsigned char **in, long len)
{
return (X509_CINF *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&X509_CINF_it);
}
int
i2d_X509_CINF(X509_CINF *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_CINF_it);
}
X509_CINF *
X509_CINF_new(void)
{
return (X509_CINF *)ASN1_item_new(&X509_CINF_it);
}
void
X509_CINF_free(X509_CINF *a)
{
ASN1_item_free((ASN1_VALUE *)a, &X509_CINF_it);
}
/* X509 top level structure needs a bit of customisation */
static int
x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
{
X509 *ret = (X509 *)*pval;
switch (operation) {
case ASN1_OP_NEW_POST:
ret->valid = 0;
ret->name = NULL;
ret->ex_flags = 0;
ret->ex_pathlen = -1;
ret->skid = NULL;
ret->akid = NULL;
ret->aux = NULL;
ret->crldp = NULL;
#ifndef OPENSSL_NO_RFC3779
ret->rfc3779_addr = NULL;
ret->rfc3779_asid = NULL;
#endif
CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data);
break;
case ASN1_OP_D2I_POST:
free(ret->name);
ret->name = X509_NAME_oneline(ret->cert_info->subject, NULL, 0);
break;
case ASN1_OP_FREE_POST:
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data);
X509_CERT_AUX_free(ret->aux);
ASN1_OCTET_STRING_free(ret->skid);
AUTHORITY_KEYID_free(ret->akid);
CRL_DIST_POINTS_free(ret->crldp);
GENERAL_NAMES_free(ret->altname);
NAME_CONSTRAINTS_free(ret->nc);
#ifndef OPENSSL_NO_RFC3779
sk_IPAddressFamily_pop_free(ret->rfc3779_addr, IPAddressFamily_free);
ASIdentifiers_free(ret->rfc3779_asid);
#endif
free(ret->name);
ret->name = NULL;
break;
}
return 1;
}
static const ASN1_AUX X509_aux = {
.app_data = NULL,
.flags = ASN1_AFLG_REFCOUNT,
.ref_offset = offsetof(X509, references),
.ref_lock = CRYPTO_LOCK_X509,
.asn1_cb = x509_cb,
};
static const ASN1_TEMPLATE X509_seq_tt[] = {
{
.offset = offsetof(X509, cert_info),
.field_name = "cert_info",
.item = &X509_CINF_it,
},
{
.offset = offsetof(X509, sig_alg),
.field_name = "sig_alg",
.item = &X509_ALGOR_it,
},
{
.offset = offsetof(X509, signature),
.field_name = "signature",
.item = &ASN1_BIT_STRING_it,
},
};
const ASN1_ITEM X509_it = {
.itype = ASN1_ITYPE_SEQUENCE,
.utype = V_ASN1_SEQUENCE,
.templates = X509_seq_tt,
.tcount = sizeof(X509_seq_tt) / sizeof(ASN1_TEMPLATE),
.funcs = &X509_aux,
.size = sizeof(X509),
.sname = "X509",
};
X509 *
d2i_X509(X509 **a, const unsigned char **in, long len)
{
return (X509 *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&X509_it);
}
int
i2d_X509(X509 *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_it);
}
X509 *
X509_new(void)
{
return (X509 *)ASN1_item_new(&X509_it);
}
void
X509_free(X509 *a)
{
ASN1_item_free((ASN1_VALUE *)a, &X509_it);
}
X509 *
X509_dup(X509 *x)
{
return ASN1_item_dup(&X509_it, x);
}
int
X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
{
return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509, argl, argp,
new_func, dup_func, free_func);
}
int
X509_set_ex_data(X509 *r, int idx, void *arg)
{
return (CRYPTO_set_ex_data(&r->ex_data, idx, arg));
}
void *
X509_get_ex_data(X509 *r, int idx)
{
return (CRYPTO_get_ex_data(&r->ex_data, idx));
}
/* X509_AUX ASN1 routines. X509_AUX is the name given to
* a certificate with extra info tagged on the end. Since these
* functions set how a certificate is trusted they should only
* be used when the certificate comes from a reliable source
* such as local storage.
*
*/
X509 *
d2i_X509_AUX(X509 **a, const unsigned char **pp, long length)
{
const unsigned char *q;
X509 *ret;
/* Save start position */
q = *pp;
ret = d2i_X509(NULL, pp, length);
/* If certificate unreadable then forget it */
if (!ret)
return NULL;
/* update length */
length -= *pp - q;
if (length > 0) {
if (!d2i_X509_CERT_AUX(&ret->aux, pp, length))
goto err;
}
if (a != NULL) {
X509_free(*a);
*a = ret;
}
return ret;
err:
X509_free(ret);
return NULL;
}
int
i2d_X509_AUX(X509 *a, unsigned char **pp)
{
int length;
length = i2d_X509(a, pp);
if (a)
length += i2d_X509_CERT_AUX(a->aux, pp);
return length;
}
int
i2d_re_X509_tbs(X509 *x, unsigned char **pp)
{
x->cert_info->enc.modified = 1;
return i2d_X509_CINF(x->cert_info, pp);
}
void
X509_get0_signature(const ASN1_BIT_STRING **psig, const X509_ALGOR **palg,
const X509 *x)
{
if (psig != NULL)
*psig = x->signature;
if (palg != NULL)
*palg = x->sig_alg;
}
int
X509_get_signature_nid(const X509 *x)
{
return OBJ_obj2nid(x->sig_alg->algorithm);
}

274
crypto/asn1/x_x509a.c Normal file
View File

@@ -0,0 +1,274 @@
/* $OpenBSD: x_x509a.c,v 1.21 2023/07/07 19:37:53 beck Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 1999.
*/
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
#include <stdio.h>
#include <openssl/asn1t.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include "x509_local.h"
/* X509_CERT_AUX routines. These are used to encode additional
* user modifiable data about a certificate. This data is
* appended to the X509 encoding when the *_X509_AUX routines
* are used. This means that the "traditional" X509 routines
* will simply ignore the extra data.
*/
static X509_CERT_AUX *aux_get(X509 *x);
static const ASN1_TEMPLATE X509_CERT_AUX_seq_tt[] = {
{
.flags = ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL,
.offset = offsetof(X509_CERT_AUX, trust),
.field_name = "trust",
.item = &ASN1_OBJECT_it,
},
{
.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SEQUENCE_OF |
ASN1_TFLG_OPTIONAL,
.tag = 0,
.offset = offsetof(X509_CERT_AUX, reject),
.field_name = "reject",
.item = &ASN1_OBJECT_it,
},
{
.flags = ASN1_TFLG_OPTIONAL,
.offset = offsetof(X509_CERT_AUX, alias),
.field_name = "alias",
.item = &ASN1_UTF8STRING_it,
},
{
.flags = ASN1_TFLG_OPTIONAL,
.offset = offsetof(X509_CERT_AUX, keyid),
.field_name = "keyid",
.item = &ASN1_OCTET_STRING_it,
},
{
.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SEQUENCE_OF |
ASN1_TFLG_OPTIONAL,
.tag = 1,
.offset = offsetof(X509_CERT_AUX, other),
.field_name = "other",
.item = &X509_ALGOR_it,
},
};
const ASN1_ITEM X509_CERT_AUX_it = {
.itype = ASN1_ITYPE_SEQUENCE,
.utype = V_ASN1_SEQUENCE,
.templates = X509_CERT_AUX_seq_tt,
.tcount = sizeof(X509_CERT_AUX_seq_tt) / sizeof(ASN1_TEMPLATE),
.size = sizeof(X509_CERT_AUX),
.sname = "X509_CERT_AUX",
};
X509_CERT_AUX *
d2i_X509_CERT_AUX(X509_CERT_AUX **a, const unsigned char **in, long len)
{
return (X509_CERT_AUX *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&X509_CERT_AUX_it);
}
int
i2d_X509_CERT_AUX(X509_CERT_AUX *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_CERT_AUX_it);
}
X509_CERT_AUX *
X509_CERT_AUX_new(void)
{
return (X509_CERT_AUX *)ASN1_item_new(&X509_CERT_AUX_it);
}
void
X509_CERT_AUX_free(X509_CERT_AUX *a)
{
ASN1_item_free((ASN1_VALUE *)a, &X509_CERT_AUX_it);
}
static X509_CERT_AUX *
aux_get(X509 *x)
{
if (!x)
return NULL;
if (!x->aux && !(x->aux = X509_CERT_AUX_new()))
return NULL;
return x->aux;
}
int
X509_alias_set1(X509 *x, const unsigned char *name, int len)
{
X509_CERT_AUX *aux;
if (!name) {
if (!x || !x->aux || !x->aux->alias)
return 1;
ASN1_UTF8STRING_free(x->aux->alias);
x->aux->alias = NULL;
return 1;
}
if (!(aux = aux_get(x)))
return 0;
if (!aux->alias && !(aux->alias = ASN1_UTF8STRING_new()))
return 0;
return ASN1_STRING_set(aux->alias, name, len);
}
int
X509_keyid_set1(X509 *x, const unsigned char *id, int len)
{
X509_CERT_AUX *aux;
if (!id) {
if (!x || !x->aux || !x->aux->keyid)
return 1;
ASN1_OCTET_STRING_free(x->aux->keyid);
x->aux->keyid = NULL;
return 1;
}
if (!(aux = aux_get(x)))
return 0;
if (!aux->keyid && !(aux->keyid = ASN1_OCTET_STRING_new()))
return 0;
return ASN1_STRING_set(aux->keyid, id, len);
}
unsigned char *
X509_alias_get0(X509 *x, int *len)
{
if (!x->aux || !x->aux->alias)
return NULL;
if (len)
*len = x->aux->alias->length;
return x->aux->alias->data;
}
unsigned char *
X509_keyid_get0(X509 *x, int *len)
{
if (!x->aux || !x->aux->keyid)
return NULL;
if (len)
*len = x->aux->keyid->length;
return x->aux->keyid->data;
}
int
X509_add1_trust_object(X509 *x, const ASN1_OBJECT *obj)
{
X509_CERT_AUX *aux;
ASN1_OBJECT *objtmp;
int rc;
if (!(objtmp = OBJ_dup(obj)))
return 0;
if (!(aux = aux_get(x)))
goto err;
if (!aux->trust && !(aux->trust = sk_ASN1_OBJECT_new_null()))
goto err;
rc = sk_ASN1_OBJECT_push(aux->trust, objtmp);
if (rc != 0)
return rc;
err:
ASN1_OBJECT_free(objtmp);
return 0;
}
int
X509_add1_reject_object(X509 *x, const ASN1_OBJECT *obj)
{
X509_CERT_AUX *aux;
ASN1_OBJECT *objtmp;
int rc;
if (!(objtmp = OBJ_dup(obj)))
return 0;
if (!(aux = aux_get(x)))
goto err;
if (!aux->reject && !(aux->reject = sk_ASN1_OBJECT_new_null()))
goto err;
rc = sk_ASN1_OBJECT_push(aux->reject, objtmp);
if (rc != 0)
return rc;
err:
ASN1_OBJECT_free(objtmp);
return 0;
}
void
X509_trust_clear(X509 *x)
{
if (x->aux && x->aux->trust) {
sk_ASN1_OBJECT_pop_free(x->aux->trust, ASN1_OBJECT_free);
x->aux->trust = NULL;
}
}
void
X509_reject_clear(X509 *x)
{
if (x->aux && x->aux->reject) {
sk_ASN1_OBJECT_pop_free(x->aux->reject, ASN1_OBJECT_free);
x->aux->reject = NULL;
}
}