early-access version 2698

This commit is contained in:
pineappleEA
2022-04-24 22:29:35 +02:00
parent c96f949832
commit caa0c2911b
486 changed files with 37806 additions and 14362 deletions

View File

@@ -1,3 +1,5 @@
add_definitions(-DLIBRESSL_CRYPTO_INTERNAL)
if(HOST_ASM_ELF_ARMV4)
set(
ASM_ARMV4_ELF_SRC
@@ -231,6 +233,7 @@ set(
malloc-wrapper.c
mem_clr.c
mem_dbg.c
o_fips.c
o_init.c
o_str.c
o_time.c
@@ -242,49 +245,38 @@ set(
aes/aes_ofb.c
aes/aes_wrap.c
asn1/a_bitstr.c
asn1/a_bool.c
asn1/a_d2i_fp.c
asn1/a_digest.c
asn1/a_dup.c
asn1/a_enum.c
asn1/a_i2d_fp.c
asn1/a_int.c
asn1/a_mbstr.c
asn1/a_object.c
asn1/a_octet.c
asn1/a_pkey.c
asn1/a_print.c
asn1/a_sign.c
asn1/a_pubkey.c
asn1/a_strex.c
asn1/a_string.c
asn1/a_strnid.c
asn1/a_time.c
asn1/a_time_tm.c
asn1/a_type.c
asn1/a_utf8.c
asn1/a_verify.c
asn1/ameth_lib.c
asn1/asn1_err.c
asn1/asn1_gen.c
asn1/asn1_item.c
asn1/asn1_lib.c
asn1/asn1_old.c
asn1/asn1_old_lib.c
asn1/asn1_par.c
asn1/asn1_types.c
asn1/asn_mime.c
asn1/asn_moid.c
asn1/asn_pack.c
asn1/bio_asn1.c
asn1/bio_ndef.c
asn1/d2i_pr.c
asn1/d2i_pu.c
asn1/evp_asn1.c
asn1/f_enum.c
asn1/f_int.c
asn1/f_string.c
asn1/i2d_pr.c
asn1/i2d_pu.c
asn1/n_pkey.c
asn1/nsseq.c
asn1/p5_pbe.c
asn1/p5_pbev2.c
asn1/p8_pkey.c
asn1/t_bitst.c
asn1/t_crl.c
asn1/t_pkey.c
asn1/t_req.c
@@ -306,7 +298,6 @@ set(
asn1/x_info.c
asn1/x_long.c
asn1/x_name.c
asn1/x_nx509.c
asn1/x_pkey.c
asn1/x_pubkey.c
asn1/x_req.c
@@ -370,6 +361,9 @@ set(
buffer/buf_err.c
buffer/buf_str.c
buffer/buffer.c
bytestring/bs_ber.c
bytestring/bs_cbb.c
bytestring/bs_cbs.c
camellia/cmll_cfb.c
camellia/cmll_ctr.c
camellia/cmll_ecb.c
@@ -409,6 +403,16 @@ set(
conf/conf_mall.c
conf/conf_mod.c
conf/conf_sap.c
ct/ct_b64.c
ct/ct_err.c
ct/ct_log.c
ct/ct_oct.c
ct/ct_policy.c
ct/ct_prn.c
ct/ct_sct.c
ct/ct_sct_ctx.c
ct/ct_vfy.c
ct/ct_x509v3.c
curve25519/curve25519-generic.c
curve25519/curve25519.c
des/cbc_cksm.c
@@ -550,9 +554,6 @@ set(
evp/evp_lib.c
evp/evp_pbe.c
evp/evp_pkey.c
evp/m_dss.c
evp/m_dss1.c
evp/m_ecdsa.c
evp/m_gost2814789.c
evp/m_gostr341194.c
evp/m_md4.c
@@ -636,7 +637,6 @@ set(
pem/pem_oth.c
pem/pem_pk8.c
pem/pem_pkey.c
pem/pem_seal.c
pem/pem_sign.c
pem/pem_x509.c
pem/pem_xaux.c
@@ -726,9 +726,11 @@ set(
x509/pcy_map.c
x509/pcy_node.c
x509/pcy_tree.c
x509/x509_addr.c
x509/x509_akey.c
x509/x509_akeya.c
x509/x509_alt.c
x509/x509_asid.c
x509/x509_att.c
x509/x509_bcons.c
x509/x509_bitst.c
@@ -875,6 +877,11 @@ if(NOT HAVE_STRSEP)
set(EXTRA_EXPORT ${EXTRA_EXPORT} strsep)
endif()
if(NOT HAVE_STRTONUM)
set(CRYPTO_SRC ${CRYPTO_SRC} compat/strtonum.c)
set(EXTRA_EXPORT ${EXTRA_EXPORT} strtonum)
endif()
if(NOT HAVE_SYSLOG_R)
set(CRYPTO_SRC ${CRYPTO_SRC} compat/syslog_r.c)
endif()
@@ -968,22 +975,33 @@ if(EXTRA_EXPORT)
endforeach()
endif()
add_library(crypto ${CRYPTO_SRC})
target_include_directories(crypto
set(LIBTLS_EXTRA_EXPORT ${EXTRA_EXPORT} PARENT_SCOPE)
add_library(crypto_obj OBJECT ${CRYPTO_SRC})
target_include_directories(crypto_obj
PRIVATE
.
asn1
bio
bn
bytestring
dh
dsa
ec
ecdh
ecdsa
evp
hmac
modes
ocsp
rsa
x509
../include/compat
PUBLIC
../include)
add_library(crypto $<TARGET_OBJECTS:crypto_obj>)
export_symbol(crypto ${CMAKE_CURRENT_BINARY_DIR}/crypto_p.sym)
target_link_libraries(crypto ${PLATFORM_LIBS})
if (WIN32)
@@ -1003,3 +1021,10 @@ if(ENABLE_LIBRESSL_INSTALL)
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
endif(ENABLE_LIBRESSL_INSTALL)
# build static library for regression test
if(BUILD_SHARED_LIBS)
add_library(crypto-static STATIC $<TARGET_OBJECTS:crypto_obj>)
target_link_libraries(crypto-static ${PLATFORM_LIBS})
endif()

View File

@@ -1 +1 @@
46:1:0
49:0:0

View File

@@ -1,7 +1,7 @@
; 1 "crypto/aes/aes-masm-x86_64.S.tmp"
; 1 "<built-in>" 1
; 1 "<built-in>" 3
; 340 "<built-in>" 3
; 343 "<built-in>" 3
; 1 "<command line>" 1
; 1 "<built-in>" 2
; 1 "crypto/aes/aes-masm-x86_64.S.tmp" 2

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: aes_ige.c,v 1.7 2015/02/10 09:46:30 miod Exp $ */
/* $OpenBSD: aes_ige.c,v 1.8 2022/01/22 00:43:41 inoguchi Exp $ */
/* ====================================================================
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
*
@@ -109,8 +109,8 @@ AES_ige_encrypt(const unsigned char *in, unsigned char *out, size_t length,
in += AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE;
}
memcpy(ivec, ivp->data, AES_BLOCK_SIZE);
memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE);
memmove(ivec, ivp->data, AES_BLOCK_SIZE);
memmove(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE);
} else {
aes_block_t tmp, tmp2;
aes_block_t iv;
@@ -161,8 +161,8 @@ AES_ige_encrypt(const unsigned char *in, unsigned char *out, size_t length,
in += AES_BLOCK_SIZE;
out += AES_BLOCK_SIZE;
}
memcpy(ivec, ivp->data, AES_BLOCK_SIZE);
memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE);
memmove(ivec, ivp->data, AES_BLOCK_SIZE);
memmove(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE);
} else {
aes_block_t tmp, tmp2;
aes_block_t iv;

View File

@@ -1,7 +1,7 @@
; 1 "crypto/aes/aesni-masm-x86_64.S.tmp"
; 1 "<built-in>" 1
; 1 "<built-in>" 3
; 340 "<built-in>" 3
; 343 "<built-in>" 3
; 1 "<command line>" 1
; 1 "<built-in>" 2
; 1 "crypto/aes/aesni-masm-x86_64.S.tmp" 2

View File

@@ -1,7 +1,7 @@
; 1 "crypto/aes/aesni-sha1-masm-x86_64.S.tmp"
; 1 "<built-in>" 1
; 1 "<built-in>" 3
; 340 "<built-in>" 3
; 343 "<built-in>" 3
; 1 "<command line>" 1
; 1 "<built-in>" 2
; 1 "crypto/aes/aesni-sha1-masm-x86_64.S.tmp" 2

View File

@@ -1,7 +1,7 @@
; 1 "crypto/aes/bsaes-masm-x86_64.S.tmp"
; 1 "<built-in>" 1
; 1 "<built-in>" 3
; 340 "<built-in>" 3
; 343 "<built-in>" 3
; 1 "<command line>" 1
; 1 "<built-in>" 2
; 1 "crypto/aes/bsaes-masm-x86_64.S.tmp" 2

View File

@@ -1,7 +1,7 @@
; 1 "crypto/aes/vpaes-masm-x86_64.S.tmp"
; 1 "<built-in>" 1
; 1 "<built-in>" 3
; 340 "<built-in>" 3
; 343 "<built-in>" 3
; 1 "<command line>" 1
; 1 "<built-in>" 2
; 1 "crypto/aes/vpaes-masm-x86_64.S.tmp" 2

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: arm_arch.h,v 1.10 2019/07/02 19:31:28 patrick Exp $ */
/* $OpenBSD: arm_arch.h,v 1.1 2022/03/23 15:13:31 tb Exp $ */
#ifndef __ARM_ARCH_H__
#define __ARM_ARCH_H__

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: armcap.c,v 1.8 2019/03/13 10:18:30 patrick Exp $ */
/* $OpenBSD: armcap.c,v 1.1 2022/03/23 15:13:31 tb Exp $ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: a_bitstr.c,v 1.30 2020/09/03 17:19:27 tb Exp $ */
/* $OpenBSD: a_bitstr.c,v 1.33 2021/12/25 08:52:44 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -60,7 +60,28 @@
#include <string.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/conf.h>
#include <openssl/err.h>
#include <openssl/x509v3.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);
}
void
ASN1_BIT_STRING_free(ASN1_BIT_STRING *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_BIT_STRING_it);
}
int
ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len)
@@ -68,6 +89,127 @@ ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len)
return ASN1_STRING_set(x, d, len);
}
int
ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value)
{
int w, v, iv;
unsigned char *c;
w = n/8;
v = 1 << (7 - (n & 0x07));
iv = ~v;
if (!value)
v = 0;
if (a == NULL)
return 0;
a->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear, set on write */
if ((a->length < (w + 1)) || (a->data == NULL)) {
if (!value)
return(1); /* Don't need to set */
if ((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);
}
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);
}
/*
* Checks if the given bit string contains only bits specified by
* the flags vector. Returns 0 if there is at least one bit set in 'a'
* which is not specified in 'flags', 1 otherwise.
* 'len' is the length of 'flags'.
*/
int
ASN1_BIT_STRING_check(const ASN1_BIT_STRING *a, const unsigned char *flags,
int flags_len)
{
int i, ok;
/* Check if there is one bit set at all. */
if (!a || !a->data)
return 1;
/* Check each byte of the internal representation of the bit string. */
ok = 1;
for (i = 0; i < a->length && ok; ++i) {
unsigned char mask = i < flags_len ? ~flags[i] : 0xff;
/* We are done if there is an unneeded bit set. */
ok = (a->data[i] & mask) == 0;
}
return ok;
}
int
ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs,
BIT_STRING_BITNAME *tbl, int indent)
{
BIT_STRING_BITNAME *bnam;
char first = 1;
BIO_printf(out, "%*s", indent, "");
for (bnam = tbl; bnam->lname; bnam++) {
if (ASN1_BIT_STRING_get_bit(bs, bnam->bitnum)) {
if (!first)
BIO_puts(out, ", ");
BIO_puts(out, bnam->lname);
first = 0;
}
}
BIO_puts(out, "\n");
return 1;
}
int
ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, const char *name, int value,
BIT_STRING_BITNAME *tbl)
{
int bitnum;
bitnum = ASN1_BIT_STRING_num_asc(name, tbl);
if (bitnum < 0)
return 0;
if (bs) {
if (!ASN1_BIT_STRING_set_bit(bs, bitnum, value))
return 0;
}
return 1;
}
int
ASN1_BIT_STRING_num_asc(const char *name, BIT_STRING_BITNAME *tbl)
{
BIT_STRING_BITNAME *bnam;
for (bnam = tbl; bnam->lname; bnam++) {
if (!strcmp(bnam->sname, name) ||
!strcmp(bnam->lname, name))
return bnam->bitnum;
}
return -1;
}
int
i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp)
{
@@ -192,73 +334,14 @@ c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, const unsigned char **pp, long len)
}
int
ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value)
i2d_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **out)
{
int w, v, iv;
unsigned char *c;
w = n/8;
v = 1 << (7 - (n & 0x07));
iv = ~v;
if (!value)
v = 0;
if (a == NULL)
return 0;
a->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear, set on write */
if ((a->length < (w + 1)) || (a->data == NULL)) {
if (!value)
return(1); /* Don't need to set */
if ((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);
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_BIT_STRING_it);
}
int
ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n)
ASN1_BIT_STRING *
d2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, const unsigned char **in, long len)
{
int w, v;
w = n / 8;
v = 1 << (7 - (n & 0x07));
if ((a == NULL) || (a->length < (w + 1)) || (a->data == NULL))
return (0);
return ((a->data[w] & v) != 0);
}
/*
* Checks if the given bit string contains only bits specified by
* the flags vector. Returns 0 if there is at least one bit set in 'a'
* which is not specified in 'flags', 1 otherwise.
* 'len' is the length of 'flags'.
*/
int
ASN1_BIT_STRING_check(const ASN1_BIT_STRING *a, const unsigned char *flags,
int flags_len)
{
int i, ok;
/* Check if there is one bit set at all. */
if (!a || !a->data)
return 1;
/* Check each byte of the internal representation of the bit string. */
ok = 1;
for (i = 0; i < a->length && ok; ++i) {
unsigned char mask = i < flags_len ? ~flags[i] : 0xff;
/* We are done if there is an unneeded bit set. */
ok = (a->data[i] & mask) == 0;
}
return ok;
return (ASN1_BIT_STRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&ASN1_BIT_STRING_it);
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: a_enum.c,v 1.20 2019/04/28 05:05:56 tb Exp $ */
/* $OpenBSD: a_enum.c,v 1.23 2021/12/25 13:17:48 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -60,7 +60,9 @@
#include <stdio.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/bn.h>
#include <openssl/buffer.h>
#include <openssl/err.h>
/*
@@ -68,6 +70,24 @@
* 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);
}
void
ASN1_ENUMERATED_free(ASN1_ENUMERATED *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_ENUMERATED_it);
}
int
ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v)
{
@@ -175,7 +195,7 @@ BN_to_ASN1_ENUMERATED(const BIGNUM *bn, ASN1_ENUMERATED *ai)
}
return (ret);
err:
err:
if (ret != ai)
ASN1_ENUMERATED_free(ret);
return (NULL);
@@ -192,3 +212,143 @@ ASN1_ENUMERATED_to_BN(const ASN1_ENUMERATED *ai, BIGNUM *bn)
BN_set_negative(ret, 1);
return (ret);
}
/* 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);
}
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);
}
int
i2d_ASN1_ENUMERATED(ASN1_ENUMERATED *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_ENUMERATED_it);
}
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);
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: a_int.c,v 1.34 2019/04/28 05:03:56 tb Exp $ */
/* $OpenBSD: a_int.c,v 1.38 2021/12/25 13:17:48 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -61,9 +61,29 @@
#include <string.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/bn.h>
#include <openssl/buffer.h>
#include <openssl/err.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);
}
void
ASN1_INTEGER_free(ASN1_INTEGER *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_INTEGER_it);
}
static int
ASN1_INTEGER_valid(const ASN1_INTEGER *a)
{
@@ -101,6 +121,276 @@ ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y)
return ret;
}
int
ASN1_INTEGER_set(ASN1_INTEGER *a, long v)
{
int j, k;
unsigned int i;
unsigned char buf[sizeof(long) + 1];
long d;
a->type = V_ASN1_INTEGER;
/* XXX ssl/ssl_asn1.c:i2d_SSL_SESSION() depends upon this bound vae */
if (a->length < (int)(sizeof(long) + 1)) {
free(a->data);
a->data = calloc(1, sizeof(long) + 1);
}
if (a->data == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
return (0);
}
d = v;
if (d < 0) {
d = -d;
a->type = V_ASN1_NEG_INTEGER;
}
for (i = 0; i < sizeof(long); i++) {
if (d == 0)
break;
buf[i] = (int)d & 0xff;
d >>= 8;
}
j = 0;
for (k = i - 1; k >= 0; k--)
a->data[j++] = buf[k];
a->length = j;
return (1);
}
/*
* XXX this particular API is a gibbering eidrich horror that makes it
* impossible to determine valid return cases from errors.. "a bit
* ugly" is preserved for posterity, unfortunately this is probably
* unfixable without changing public API
*/
long
ASN1_INTEGER_get(const ASN1_INTEGER *a)
{
int neg = 0, i;
unsigned long r = 0;
if (a == NULL)
return (0L);
i = a->type;
if (i == V_ASN1_NEG_INTEGER)
neg = 1;
else if (i != V_ASN1_INTEGER)
return -1;
if (!ASN1_INTEGER_valid(a))
return -1; /* XXX best effort */
if (a->length > (int)sizeof(long)) {
/* hmm... a bit ugly, return all ones */
return -1;
}
if (a->data == NULL)
return 0;
for (i = 0; i < a->length; i++) {
r <<= 8;
r |= (unsigned char)a->data[i];
}
if (r > LONG_MAX)
return -1;
if (neg)
return -(long)r;
return (long)r;
}
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);
}
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);
}
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);
}
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);
}
/*
* This converts an ASN1 INTEGER into its content encoding.
@@ -289,13 +579,25 @@ c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp, long len)
*pp = pend;
return (ret);
err:
err:
ASN1error(i);
if (a == NULL || *a != ret)
ASN1_INTEGER_free(ret);
return (NULL);
}
int
i2d_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_INTEGER_it);
}
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);
}
/* This is a version of d2i_ASN1_INTEGER that ignores the sign bit of
* ASN1 integers: some broken software can encode a positive INTEGER
@@ -364,151 +666,9 @@ d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp, long length)
*pp = p;
return (ret);
err:
err:
ASN1error(i);
if (a == NULL || *a != ret)
ASN1_INTEGER_free(ret);
return (NULL);
}
int
ASN1_INTEGER_set(ASN1_INTEGER *a, long v)
{
int j, k;
unsigned int i;
unsigned char buf[sizeof(long) + 1];
long d;
a->type = V_ASN1_INTEGER;
/* XXX ssl/ssl_asn1.c:i2d_SSL_SESSION() depends upon this bound vae */
if (a->length < (int)(sizeof(long) + 1)) {
free(a->data);
a->data = calloc(1, sizeof(long) + 1);
}
if (a->data == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
return (0);
}
d = v;
if (d < 0) {
d = -d;
a->type = V_ASN1_NEG_INTEGER;
}
for (i = 0; i < sizeof(long); i++) {
if (d == 0)
break;
buf[i] = (int)d & 0xff;
d >>= 8;
}
j = 0;
for (k = i - 1; k >= 0; k--)
a->data[j++] = buf[k];
a->length = j;
return (1);
}
/*
* XXX this particular API is a gibbering eidrich horror that makes it
* impossible to determine valid return cases from errors.. "a bit
* ugly" is preserved for posterity, unfortunately this is probably
* unfixable without changing public API
*/
long
ASN1_INTEGER_get(const ASN1_INTEGER *a)
{
int neg = 0, i;
unsigned long r = 0;
if (a == NULL)
return (0L);
i = a->type;
if (i == V_ASN1_NEG_INTEGER)
neg = 1;
else if (i != V_ASN1_INTEGER)
return -1;
if (!ASN1_INTEGER_valid(a))
return -1; /* XXX best effort */
if (a->length > (int)sizeof(long)) {
/* hmm... a bit ugly, return all ones */
return -1;
}
if (a->data == NULL)
return 0;
for (i = 0; i < a->length; i++) {
r <<= 8;
r |= (unsigned char)a->data[i];
}
if (r > LONG_MAX)
return -1;
if (neg)
return -(long)r;
return (long)r;
}
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);
}
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);
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: a_mbstr.c,v 1.23 2017/01/29 17:49:22 beck Exp $ */
/* $OpenBSD: a_mbstr.c,v 1.24 2021/12/25 13:17:48 jsing Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 1999.
*/
@@ -248,7 +248,7 @@ ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
traverse_string(in, len, inform, cpyfunc, &p);
return str_type;
err:
err:
if (free_out) {
ASN1_STRING_free(dest);
*out = NULL;

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: a_object.c,v 1.31 2018/04/25 11:48:21 tb Exp $ */
/* $OpenBSD: a_object.c,v 1.46 2022/04/10 12:42:33 inoguchi Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -61,308 +61,31 @@
#include <string.h>
#include <openssl/asn1.h>
#include <openssl/bn.h>
#include <openssl/asn1t.h>
#include <openssl/err.h>
#include <openssl/buffer.h>
#include <openssl/objects.h>
int
i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp)
{
unsigned char *p;
int objsize;
#include "asn1_locl.h"
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);
}
int
a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
{
int i, first, len = 0, c, use_bn;
char ftmp[24], *tmp = ftmp;
int tmpsize = sizeof ftmp;
const char *p;
unsigned long l;
BIGNUM *bl = NULL;
if (num == 0)
return (0);
else if (num == -1)
num = strlen(buf);
p = buf;
c = *(p++);
num--;
if ((c >= '0') && (c <= '2')) {
first= c-'0';
} else {
ASN1error(ASN1_R_FIRST_NUM_TOO_LARGE);
goto err;
}
if (num <= 0) {
ASN1error(ASN1_R_MISSING_SECOND_NUMBER);
goto err;
}
c = *(p++);
num--;
for (;;) {
if (num <= 0)
break;
if ((c != '.') && (c != ' ')) {
ASN1error(ASN1_R_INVALID_SEPARATOR);
goto err;
}
l = 0;
use_bn = 0;
for (;;) {
if (num <= 0)
break;
num--;
c = *(p++);
if ((c == ' ') || (c == '.'))
break;
if ((c < '0') || (c > '9')) {
ASN1error(ASN1_R_INVALID_DIGIT);
goto err;
}
if (!use_bn && l >= ((ULONG_MAX - 80) / 10L)) {
use_bn = 1;
if (!bl)
bl = BN_new();
if (!bl || !BN_set_word(bl, l))
goto err;
}
if (use_bn) {
if (!BN_mul_word(bl, 10L) ||
!BN_add_word(bl, c-'0'))
goto err;
} else
l = l * 10L + (long)(c - '0');
}
if (len == 0) {
if ((first < 2) && (l >= 40)) {
ASN1error(ASN1_R_SECOND_NUMBER_TOO_LARGE);
goto err;
}
if (use_bn) {
if (!BN_add_word(bl, first * 40))
goto err;
} else
l += (long)first * 40;
}
i = 0;
if (use_bn) {
int blsize;
blsize = BN_num_bits(bl);
blsize = (blsize + 6) / 7;
if (blsize > tmpsize) {
if (tmp != ftmp)
free(tmp);
tmpsize = blsize + 32;
tmp = malloc(tmpsize);
if (!tmp)
goto err;
}
while (blsize--)
tmp[i++] = (unsigned char)BN_div_word(bl, 0x80L);
} else {
for (;;) {
tmp[i++] = (unsigned char)l & 0x7f;
l >>= 7L;
if (l == 0L)
break;
}
}
if (out != NULL) {
if (len + i > olen) {
ASN1error(ASN1_R_BUFFER_TOO_SMALL);
goto err;
}
while (--i > 0)
out[len++] = tmp[i]|0x80;
out[len++] = tmp[0];
} else
len += i;
}
if (tmp != ftmp)
free(tmp);
BN_free(bl);
return (len);
err:
if (tmp != ftmp)
free(tmp);
BN_free(bl);
return (0);
}
int
i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *a)
{
return OBJ_obj2txt(buf, buf_len, a, 0);
}
int
i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a)
{
char *tmp = NULL;
size_t tlen = 256;
int i = -1;
if ((a == NULL) || (a->data == NULL))
return(BIO_write(bp, "NULL", 4));
if ((tmp = malloc(tlen)) == NULL)
return -1;
i = i2t_ASN1_OBJECT(tmp, tlen, a);
if (i > (int)(tlen - 1)) {
freezero(tmp, tlen);
if ((tmp = malloc(i + 1)) == NULL)
return -1;
tlen = i + 1;
i = i2t_ASN1_OBJECT(tmp, tlen, a);
}
if (i <= 0)
i = BIO_write(bp, "<INVALID>", 9);
else
i = BIO_write(bp, tmp, i);
freezero(tmp, tlen);
return (i);
}
ASN1_OBJECT *
d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, long length)
{
const unsigned char *p;
long len;
int tag, xclass;
int inf, i;
ASN1_OBJECT *ret = NULL;
p = *pp;
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
if (inf & 0x80) {
i = ASN1_R_BAD_OBJECT_HEADER;
goto err;
}
if (tag != V_ASN1_OBJECT) {
i = ASN1_R_EXPECTING_AN_OBJECT;
goto err;
}
ret = c2i_ASN1_OBJECT(a, &p, len);
if (ret)
*pp = p;
return ret;
err:
ASN1error(i);
return (NULL);
}
ASN1_OBJECT *
c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, long len)
{
ASN1_OBJECT *ret;
const unsigned char *p;
unsigned char *data;
int i, length;
/*
* Sanity check OID encoding:
* - need at least one content octet
* - MSB must be clear in the last octet
* - can't have leading 0x80 in subidentifiers, see: X.690 8.19.2
*/
if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
p[len - 1] & 0x80) {
ASN1error(ASN1_R_INVALID_OBJECT_ENCODING);
return (NULL);
}
/* Now 0 < len <= INT_MAX, so the cast is safe. */
length = (int)len;
for (i = 0; i < length; i++, p++) {
if (*p == 0x80 && (!i || !(p[-1] & 0x80))) {
ASN1error(ASN1_R_INVALID_OBJECT_ENCODING);
return (NULL);
}
}
/* only the ASN1_OBJECTs from the 'table' will have values
* for ->sn or ->ln */
if ((a == NULL) || ((*a) == NULL) ||
!((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC)) {
if ((ret = ASN1_OBJECT_new()) == NULL)
return (NULL);
} else
ret = *a;
p = *pp;
/* detach data from object */
data = (unsigned char *)ret->data;
freezero(data, ret->length);
data = malloc(length);
if (data == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
goto err;
}
memcpy(data, p, length);
/* reattach data to object, after which it remains const */
ret->data = data;
ret->length = length;
ret->sn = NULL;
ret->ln = NULL;
ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;
p += length;
if (a != NULL)
*a = ret;
*pp = p;
return (ret);
err:
if (a == NULL || ret != *a)
ASN1_OBJECT_free(ret);
return (NULL);
}
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 *ret;
ASN1_OBJECT *a;
ret = malloc(sizeof(ASN1_OBJECT));
if (ret == NULL) {
if ((a = calloc(1, sizeof(ASN1_OBJECT))) == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
return (NULL);
}
ret->length = 0;
ret->data = NULL;
ret->nid = 0;
ret->sn = NULL;
ret->ln = NULL;
ret->flags = ASN1_OBJECT_FLAG_DYNAMIC;
return (ret);
a->flags = ASN1_OBJECT_FLAG_DYNAMIC;
return a;
}
void
@@ -399,3 +122,539 @@ ASN1_OBJECT_create(int nid, unsigned char *data, int len,
ASN1_OBJECT_FLAG_DYNAMIC_DATA;
return (OBJ_dup(&o));
}
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;
}
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 (!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);
}
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;
}
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 || *out_aobj != NULL)
goto err;
/* 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);
}
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(&content);
if (out_aobj != NULL)
*out_aobj = aobj;
return aobj;
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: a_octet.c,v 1.10 2015/07/29 14:58:34 jsing Exp $ */
/* $OpenBSD: a_octet.c,v 1.11 2021/12/25 08:52:44 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -59,6 +59,26 @@
#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);
}
void
ASN1_OCTET_STRING_free(ASN1_OCTET_STRING *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_OCTET_STRING_it);
}
ASN1_OCTET_STRING *
ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *x)
@@ -77,3 +97,16 @@ ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *x, const unsigned char *d, int len)
{
return ASN1_STRING_set(x, d, len);
}
int
i2d_ASN1_OCTET_STRING(ASN1_OCTET_STRING *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_OCTET_STRING_it);
}
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);
}

186
externals/libressl/crypto/asn1/a_pkey.c vendored Executable file
View File

@@ -0,0 +1,186 @@
/* $OpenBSD: a_pkey.c,v 1.3 2021/12/25 13:17:48 jsing 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_locl.h"
#include "evp_locl.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);
}

160
externals/libressl/crypto/asn1/a_pubkey.c vendored Executable file
View File

@@ -0,0 +1,160 @@
/* $OpenBSD: a_pubkey.c,v 1.3 2021/12/25 13:17:48 jsing 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_locl.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);
}
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: a_strex.c,v 1.28 2018/05/19 10:46:28 tb Exp $ */
/* $OpenBSD: a_strex.c,v 1.31 2021/12/25 12:11:57 jsing Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2000.
*/
@@ -322,22 +322,6 @@ do_dump(unsigned long lflags, char_io *io_ch, void *arg, const ASN1_STRING *str)
return outlen + 1;
}
/* Lookup table to convert tags to character widths,
* 0 = UTF8 encoded, -1 is used for non string types
* otherwise it is the number of bytes per character
*/
static const signed char tag2nbyte[] = {
-1, -1, -1, -1, -1, /* 0-4 */
-1, -1, -1, -1, -1, /* 5-9 */
-1, -1, 0, -1, /* 10-13 */
-1, -1, -1, -1, /* 15-17 */
-1, 1, 1, /* 18-20 */
-1, 1, 1, 1, /* 21-24 */
-1, 1, -1, /* 25-27 */
4, -1, 2 /* 28-30 */
};
/* This is the main function, print out an
* ASN1_STRING taking note of various escape
* and display options. Returns number of
@@ -371,19 +355,16 @@ do_print_ex(char_io *io_ch, void *arg, unsigned long lflags,
/* Decide what to do with type, either dump content or display it */
/* Dump everything */
if (lflags & ASN1_STRFLGS_DUMP_ALL)
if (lflags & ASN1_STRFLGS_DUMP_ALL) {
/* Dump everything. */
type = -1;
/* Ignore the string type */
else if (lflags & ASN1_STRFLGS_IGNORE_TYPE)
} else if (lflags & ASN1_STRFLGS_IGNORE_TYPE) {
/* Ignore the string type. */
type = 1;
else {
/* Else determine width based on type */
if ((type > 0) && (type < 31))
type = tag2nbyte[type];
else
type = -1;
if ((type == -1) && !(lflags & ASN1_STRFLGS_DUMP_UNKNOWN))
} else {
/* Else determine width based on type. */
type = asn1_tag2charwidth(type);
if (type == -1 && !(lflags & ASN1_STRFLGS_DUMP_UNKNOWN))
type = 1;
}
@@ -513,7 +494,7 @@ do_name_ex(char_io *io_ch, void *arg, const X509_NAME *n, int indent,
else
ent = X509_NAME_get_entry(n, i);
if (prev != -1) {
if (prev == ent->set) {
if (prev == X509_NAME_ENTRY_set(ent)) {
if (!io_ch(arg, sep_mv, sep_mv_len))
return -1;
outlen += sep_mv_len;
@@ -526,7 +507,7 @@ do_name_ex(char_io *io_ch, void *arg, const X509_NAME *n, int indent,
outlen += indent;
}
}
prev = ent->set;
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);
@@ -618,32 +599,3 @@ ASN1_STRING_print_ex_fp(FILE *fp, const ASN1_STRING *str, unsigned long flags)
{
return do_print_ex(send_fp_chars, fp, flags, str);
}
/* 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 stmp, *str = &stmp;
int mbflag, type, ret;
if (!in)
return -1;
type = in->type;
if ((type < 0) || (type > 30))
return -1;
mbflag = tag2nbyte[type];
if (mbflag == -1)
return -1;
mbflag |= MBSTRING_FLAG;
stmp.data = NULL;
stmp.length = 0;
ret = ASN1_mbstring_copy(&str, in->data, in->length, mbflag,
B_ASN1_UTF8STRING);
if (ret < 0)
return ret;
*out = stmp.data;
return stmp.length;
}

423
externals/libressl/crypto/asn1/a_string.c vendored Executable file
View File

@@ -0,0 +1,423 @@
/* $OpenBSD: a_string.c,v 1.7 2022/03/17 17:17:58 jsing 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_locl.h"
ASN1_STRING *
ASN1_STRING_new(void)
{
return ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
}
ASN1_STRING *
ASN1_STRING_type_new(int type)
{
ASN1_STRING *astr;
if ((astr = calloc(1, sizeof(ASN1_STRING))) == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
return NULL;
}
astr->type = type;
return astr;
}
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);
}
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 ((cmp = memcmp(a->data, b->data, a->length)) != 0)
return cmp;
return (a->type - b->type);
}
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;
}
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;
}
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;
}
void
ASN1_STRING_set0(ASN1_STRING *astr, void *data, int len)
{
ASN1_STRING_clear(astr);
astr->data = data;
astr->length = len;
}
void
asn1_add_error(const unsigned char *address, int offset)
{
ERR_asprintf_error_data("offset=%d", offset);
}
int
ASN1_STRING_length(const ASN1_STRING *astr)
{
return astr->length;
}
void
ASN1_STRING_length_set(ASN1_STRING *astr, int len)
{
/* This is dangerous and unfixable. */
astr->length = len;
}
int
ASN1_STRING_type(const ASN1_STRING *astr)
{
return astr->type;
}
unsigned char *
ASN1_STRING_data(ASN1_STRING *astr)
{
return astr->data;
}
const unsigned char *
ASN1_STRING_get0_data(const ASN1_STRING *astr)
{
return astr->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;
}
/*
* 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 stmp, *str = &stmp;
int mbflag, ret;
if (in == NULL)
return -1;
if ((mbflag = asn1_tag2charwidth(in->type)) == -1)
return -1;
mbflag |= MBSTRING_FLAG;
stmp.data = NULL;
stmp.length = 0;
ret = ASN1_mbstring_copy(&str, in->data, in->length, mbflag,
B_ASN1_UTF8STRING);
if (ret < 0)
return ret;
*out = stmp.data;
return stmp.length;
}
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;
}
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;
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: a_strnid.c,v 1.21 2017/01/29 17:49:22 beck Exp $ */
/* $OpenBSD: a_strnid.c,v 1.25 2021/12/13 17:55:53 schwarze Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 1999.
*/
@@ -56,8 +56,9 @@
*
*/
#include <ctype.h>
#include <stdio.h>
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/asn1.h>
@@ -65,12 +66,15 @@
#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 use to
/*
* 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.
*/
@@ -89,7 +93,8 @@ ASN1_STRING_get_default_mask(void)
return global_mask;
}
/* This function sets the default to various "flavours" of configuration.
/*
* 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).
@@ -103,20 +108,26 @@ ASN1_STRING_set_default_mask_asc(const char *p)
{
unsigned long mask;
char *end;
int save_errno;
if (!strncmp(p, "MASK:", 5)) {
if (!p[5])
if (strncmp(p, "MASK:", 5) == 0) {
if (p[5] == '\0')
return 0;
save_errno = errno;
errno = 0;
mask = strtoul(p + 5, &end, 0);
if (*end)
if (errno == ERANGE && mask == ULONG_MAX)
return 0;
} else if (!strcmp(p, "nombstr"))
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"))
else if (strcmp(p, "pkix") == 0)
mask = ~((unsigned long)B_ASN1_T61STRING);
else if (!strcmp(p, "utf8only"))
else if (strcmp(p, "utf8only") == 0)
mask = B_ASN1_UTF8STRING;
else if (!strcmp(p, "default"))
else if (strcmp(p, "default") == 0)
mask = 0xFFFFFFFFL;
else
return 0;
@@ -124,7 +135,8 @@ ASN1_STRING_set_default_mask_asc(const char *p)
return 1;
}
/* The following function generates an ASN1_STRING based on limits in a table.
/*
* 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.
*/
@@ -137,12 +149,13 @@ ASN1_STRING_set_by_NID(ASN1_STRING **out, const unsigned char *in, int inlen,
ASN1_STRING *str = NULL;
unsigned long mask;
int ret;
if (!out)
if (out == NULL)
out = &str;
tbl = ASN1_STRING_TABLE_get(nid);
if (tbl) {
if (tbl != NULL) {
mask = tbl->mask;
if (!(tbl->flags & STABLE_NO_MASK))
if ((tbl->flags & STABLE_NO_MASK) == 0)
mask &= global_mask;
ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask,
tbl->minsize, tbl->maxsize);
@@ -154,7 +167,8 @@ ASN1_STRING_set_by_NID(ASN1_STRING **out, const unsigned char *in, int inlen,
return *out;
}
/* Now the tables and helper functions for the string table:
/*
* Now the tables and helper functions for the string table:
*/
/* size limits: this stuff is taken straight from RFC3280 */
@@ -231,20 +245,59 @@ ASN1_STRING_TABLE *
ASN1_STRING_TABLE_get(int nid)
{
int idx;
ASN1_STRING_TABLE *ttmp;
ASN1_STRING_TABLE fnd;
fnd.nid = nid;
ttmp = OBJ_bsearch_table(&fnd, tbl_standard,
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(ASN1_STRING_TABLE));
if (ttmp)
return ttmp;
if (!stable)
}
/*
* 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;
idx = sk_ASN1_STRING_TABLE_find(stable, &fnd);
if (idx < 0)
}
if (!sk_ASN1_STRING_TABLE_push(stable, rv)) {
free(rv);
return NULL;
return sk_ASN1_STRING_TABLE_value(stable, idx);
}
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
@@ -252,37 +305,20 @@ ASN1_STRING_TABLE_add(int nid, long minsize, long maxsize, unsigned long mask,
unsigned long flags)
{
ASN1_STRING_TABLE *tmp;
char new_nid = 0;
flags &= ~STABLE_FLAGS_MALLOC;
if (!stable)
stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
if (!stable) {
if ((tmp = stable_get(nid)) == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
return 0;
}
if (!(tmp = ASN1_STRING_TABLE_get(nid))) {
tmp = malloc(sizeof(ASN1_STRING_TABLE));
if (!tmp) {
ASN1error(ERR_R_MALLOC_FAILURE);
return 0;
}
tmp->flags = flags | STABLE_FLAGS_MALLOC;
tmp->nid = nid;
new_nid = 1;
} else tmp->flags = (tmp->flags & STABLE_FLAGS_MALLOC) | flags;
if (minsize != -1)
if (minsize >= 0)
tmp->minsize = minsize;
if (maxsize != -1)
if (maxsize >= 0)
tmp->maxsize = maxsize;
tmp->mask = mask;
if (new_nid) {
if (sk_ASN1_STRING_TABLE_push(stable, tmp) == 0) {
free(tmp);
ASN1error(ERR_R_MALLOC_FAILURE);
return 0;
}
}
if (mask != 0)
tmp->mask = mask;
if (flags != 0)
tmp->flags = flags | STABLE_FLAGS_MALLOC;
return 1;
}
@@ -292,7 +328,7 @@ ASN1_STRING_TABLE_cleanup(void)
STACK_OF(ASN1_STRING_TABLE) *tmp;
tmp = stable;
if (!tmp)
if (tmp == NULL)
return;
stable = NULL;
sk_ASN1_STRING_TABLE_pop_free(tmp, st_free);

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: a_time.c,v 1.27 2015/10/19 16:32:37 beck Exp $ */
/* $OpenBSD: a_time.c,v 1.33 2021/12/25 07:48:09 jsing Exp $ */
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
*
@@ -80,6 +80,45 @@ const ASN1_ITEM ASN1_TIME_it = {
.sname = "ASN1_TIME",
};
ASN1_TIME *
ASN1_TIME_new(void)
{
return (ASN1_TIME *)ASN1_item_new(&ASN1_TIME_it);
}
void
ASN1_TIME_free(ASN1_TIME *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_TIME_it);
}
/* Public API in OpenSSL. Kept internal for now. */
static 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 gmtime_r(&now, tm) != NULL;
}
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);
}
ASN1_TIME *
d2i_ASN1_TIME(ASN1_TIME **a, const unsigned char **in, long len)
@@ -93,15 +132,3 @@ i2d_ASN1_TIME(ASN1_TIME *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_TIME_it);
}
ASN1_TIME *
ASN1_TIME_new(void)
{
return (ASN1_TIME *)ASN1_item_new(&ASN1_TIME_it);
}
void
ASN1_TIME_free(ASN1_TIME *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_TIME_it);
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: a_time_tm.c,v 1.15 2018/04/25 11:48:21 tb Exp $ */
/* $OpenBSD: a_time_tm.c,v 1.19 2022/03/31 13:04:47 tb Exp $ */
/*
* Copyright (c) 2015 Bob Beck <beck@openbsd.org>
*
@@ -163,10 +163,9 @@ ASN1_time_parse(const char *bytes, size_t len, struct tm *tm, int mode)
return (-1);
lt = tm;
if (lt == NULL) {
memset(&ltm, 0, sizeof(ltm));
if (lt == NULL)
lt = &ltm;
}
memset(lt, 0, sizeof(*lt));
/* Timezone is required and must be GMT (Zulu). */
if (bytes[len - 1] != 'Z')
@@ -260,10 +259,10 @@ ASN1_TIME_adj_internal(ASN1_TIME *s, time_t t, int offset_day, long offset_sec,
int allocated = 0;
struct tm tm;
size_t len;
char * p;
char *p;
if (gmtime_r(&t, &tm) == NULL)
return (NULL);
if (gmtime_r(&t, &tm) == NULL)
return (NULL);
if (offset_day || offset_sec) {
if (!OPENSSL_gmtime_adj(&tm, offset_day, offset_sec))
@@ -289,8 +288,10 @@ ASN1_TIME_adj_internal(ASN1_TIME *s, time_t t, int offset_day, long offset_sec,
}
if (s == NULL) {
if ((s = ASN1_TIME_new()) == NULL)
if ((s = ASN1_TIME_new()) == NULL) {
free(p);
return (NULL);
}
allocated = 1;
}
@@ -299,7 +300,7 @@ ASN1_TIME_adj_internal(ASN1_TIME *s, time_t t, int offset_day, long offset_sec,
case GENTIME_LENGTH:
s->type = V_ASN1_GENERALIZEDTIME;
break;
case UTCTIME_LENGTH:
case UTCTIME_LENGTH:
s->type = V_ASN1_UTCTIME;
break;
default:
@@ -354,7 +355,6 @@ ASN1_TIME_to_generalizedtime(const ASN1_TIME *t, ASN1_GENERALIZEDTIME **out)
if (t->type != V_ASN1_GENERALIZEDTIME && t->type != V_ASN1_UTCTIME)
return (NULL);
memset(&tm, 0, sizeof(tm));
if (t->type != ASN1_time_parse(t->data, t->length, &tm, t->type))
return (NULL);
if ((str = gentime_string_from_tm(&tm)) == NULL)

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: a_type.c,v 1.21 2019/10/24 16:36:10 jsing Exp $ */
/* $OpenBSD: a_type.c,v 1.23 2021/12/25 12:19:16 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -56,11 +56,51 @@
* [including the GNU Public Licence.]
*/
#include <stdio.h>
#include <string.h>
#include <openssl/asn1t.h>
#include <openssl/err.h>
#include <openssl/objects.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);
}
void
ASN1_TYPE_free(ASN1_TYPE *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_ANY_it);
}
int
ASN1_TYPE_get(const ASN1_TYPE *a)
{
@@ -155,6 +195,108 @@ ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b)
return result;
}
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);
}
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);
}
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;
}
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;
}
ASN1_TYPE *
ASN1_TYPE_pack_sequence(const ASN1_ITEM *it, void *s, ASN1_TYPE **t)
{
@@ -185,3 +327,16 @@ ASN1_TYPE_unpack_sequence(const ASN1_ITEM *it, const ASN1_TYPE *t)
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);
}
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);
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: ameth_lib.c,v 1.21 2019/11/02 16:06:25 inoguchi Exp $ */
/* $OpenBSD: ameth_lib.c,v 1.25 2022/01/10 12:10:26 tb Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2006.
*/
@@ -69,6 +69,7 @@
#endif
#include "asn1_locl.h"
#include "evp_locl.h"
extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[];
extern const EVP_PKEY_ASN1_METHOD rsa_pss_asn1_meth;
@@ -340,34 +341,21 @@ EVP_PKEY_asn1_new(int id, int flags, const char *pem_str, const char *info)
void
EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst, const EVP_PKEY_ASN1_METHOD *src)
{
dst->pub_decode = src->pub_decode;
dst->pub_encode = src->pub_encode;
dst->pub_cmp = src->pub_cmp;
dst->pub_print = src->pub_print;
EVP_PKEY_ASN1_METHOD preserve;
dst->priv_decode = src->priv_decode;
dst->priv_encode = src->priv_encode;
dst->priv_print = src->priv_print;
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->old_priv_encode = src->old_priv_encode;
dst->old_priv_decode = src->old_priv_decode;
*dst = *src;
dst->pkey_size = src->pkey_size;
dst->pkey_bits = src->pkey_bits;
dst->param_decode = src->param_decode;
dst->param_encode = src->param_encode;
dst->param_missing = src->param_missing;
dst->param_copy = src->param_copy;
dst->param_cmp = src->param_cmp;
dst->param_print = src->param_print;
dst->sig_print = src->sig_print;
dst->pkey_free = src->pkey_free;
dst->pkey_ctrl = src->pkey_ctrl;
dst->item_sign = src->item_sign;
dst->item_verify = src->item_verify;
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
@@ -441,3 +429,24 @@ EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
{
ameth->pkey_ctrl = pkey_ctrl;
}
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;
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: asn1_err.c,v 1.21 2018/03/29 02:29:24 inoguchi Exp $ */
/* $OpenBSD: asn1_err.c,v 1.22 2020/12/08 15:06:42 tb Exp $ */
/* ====================================================================
* Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved.
*
@@ -85,6 +85,7 @@ static ERR_STRING_DATA ASN1_str_reasons[] = {
{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"},

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: asn1_gen.c,v 1.17 2018/04/25 11:48:21 tb Exp $ */
/* $OpenBSD: asn1_gen.c,v 1.18 2021/12/25 13:17:48 jsing Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2002.
*/
@@ -258,7 +258,7 @@ ASN1_generate_v3(const char *str, X509V3_CTX *cnf)
/* Obtain new ASN1_TYPE structure */
ret = d2i_ASN1_TYPE(NULL, &cp, len);
err:
err:
free(orig_der);
free(new_der);
@@ -478,7 +478,7 @@ asn1_multi(int utype, const char *section, X509V3_CTX *cnf)
der = NULL;
bad:
bad:
free(der);
if (sk)
sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free);
@@ -771,9 +771,9 @@ asn1_str2type(const char *str, int format, int utype)
atmp->type = utype;
return atmp;
bad_str:
bad_str:
ERR_asprintf_error_data("string=%s", str);
bad_form:
bad_form:
ASN1_TYPE_free(atmp);
return NULL;
}

639
externals/libressl/crypto/asn1/asn1_item.c vendored Executable file
View File

@@ -0,0 +1,639 @@
/* $OpenBSD: asn1_item.c,v 1.4 2022/01/14 08:38:05 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_locl.h"
#include "evp_locl.h"
/*
* ASN1_ITEM version of dup: this follows the model above except we don't need
* to allocate the buffer. At some point this could be rewritten to directly dup
* the underlying structure instead of doing and encode and decode.
*/
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);
}
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);
}
/* 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;
}
/* 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;
}
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);
}
int
ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx)
{
const EVP_MD *type;
EVP_PKEY *pkey;
unsigned char *buf_in = NULL, *buf_out = NULL;
size_t inl = 0, outl = 0, outll = 0;
int signid, paramtype;
int rv;
type = EVP_MD_CTX_md(ctx);
pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
if (!type || !pkey) {
ASN1error(ASN1_R_CONTEXT_NOT_INITIALISED);
return 0;
}
if (pkey->ameth->item_sign) {
rv = pkey->ameth->item_sign(ctx, it, asn, algor1, algor2,
signature);
if (rv == 1)
outl = signature->length;
/* Return value meanings:
* <=0: error.
* 1: method does everything.
* 2: carry on as normal.
* 3: ASN1 method sets algorithm identifiers: just sign.
*/
if (rv <= 0)
ASN1error(ERR_R_EVP_LIB);
if (rv <= 1)
goto err;
} else
rv = 2;
if (rv == 2) {
if (!pkey->ameth ||
!OBJ_find_sigid_by_algs(&signid, EVP_MD_nid(type),
pkey->ameth->pkey_id)) {
ASN1error(ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
return 0;
}
if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL)
paramtype = V_ASN1_NULL;
else
paramtype = V_ASN1_UNDEF;
if (algor1)
X509_ALGOR_set0(algor1,
OBJ_nid2obj(signid), paramtype, NULL);
if (algor2)
X509_ALGOR_set0(algor2,
OBJ_nid2obj(signid), paramtype, NULL);
}
inl = ASN1_item_i2d(asn, &buf_in, it);
outll = outl = EVP_PKEY_size(pkey);
buf_out = malloc(outl);
if ((buf_in == NULL) || (buf_out == NULL)) {
outl = 0;
ASN1error(ERR_R_MALLOC_FAILURE);
goto err;
}
if (!EVP_DigestSignUpdate(ctx, buf_in, inl) ||
!EVP_DigestSignFinal(ctx, buf_out, &outl)) {
outl = 0;
ASN1error(ERR_R_EVP_LIB);
goto err;
}
free(signature->data);
signature->data = buf_out;
buf_out = NULL;
signature->length = outl;
/* In the interests of compatibility, I'll make sure that
* the bit string has a 'not-used bits' value of 0
*/
signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
signature->flags |= ASN1_STRING_FLAG_BITS_LEFT;
err:
EVP_MD_CTX_cleanup(ctx);
freezero((char *)buf_in, inl);
freezero((char *)buf_out, outll);
return (outl);
}
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 *buf_in = NULL;
int ret = -1, inl;
int mdnid, pknid;
if (!pkey) {
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;
}
}
inl = ASN1_item_i2d(asn, &buf_in, it);
if (buf_in == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
goto err;
}
if (!EVP_DigestVerifyUpdate(&ctx, buf_in, inl)) {
ASN1error(ERR_R_EVP_LIB);
ret = 0;
goto err;
}
freezero(buf_in, (unsigned int)inl);
if (EVP_DigestVerifyFinal(&ctx, signature->data,
(size_t)signature->length) <= 0) {
ASN1error(ERR_R_EVP_LIB);
ret = 0;
goto err;
}
/* we don't need to zero the 'ctx' because we just checked
* public information */
/* memset(&ctx,0,sizeof(ctx)); */
ret = 1;
err:
EVP_MD_CTX_cleanup(&ctx);
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);
}
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);
}
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);
}
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);
}

View File

@@ -1,436 +1,202 @@
/* $OpenBSD: asn1_lib.c,v 1.44 2018/11/17 09:34:11 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
/* $OpenBSD: asn1_lib.c,v 1.52 2022/03/26 14:47:58 jsing Exp $ */
/*
* Copyright (c) 2021 Joel Sing <jsing@openbsd.org>
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
* 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.
*
* 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.]
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/asn1.h>
#include <openssl/err.h>
static int asn1_get_length(const unsigned char **pp, int *inf, long *rl, int max);
static void asn1_put_length(unsigned char **pp, int length);
#include "bytestring.h"
static int
_asn1_check_infinite_end(const unsigned char **p, long len)
asn1_get_identifier_cbs(CBS *cbs, int der_mode, uint8_t *out_class,
int *out_constructed, uint32_t *out_tag_number)
{
/* If there is 0 or 1 byte left, the length check should pick
* things up */
if (len <= 0)
return (1);
else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0)) {
(*p) += 2;
return (1);
}
return (0);
}
uint8_t tag_class, tag_val;
int tag_constructed;
uint32_t tag_number;
int
ASN1_check_infinite_end(unsigned char **p, long len)
{
return _asn1_check_infinite_end((const unsigned char **)p, len);
}
/*
* Decode ASN.1 identifier octets - see ITU-T X.690 section 8.1.2.
*/
int
ASN1_const_check_infinite_end(const unsigned char **p, long len)
{
return _asn1_check_infinite_end(p, len);
}
*out_class = 0;
*out_constructed = 0;
*out_tag_number = 0;
int
ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
int *pclass, long omax)
{
int i, ret;
long l;
const unsigned char *p = *pp;
int tag, xclass, inf;
long max = omax;
if (!CBS_get_u8(cbs, &tag_val))
return 0;
if (!max)
goto err;
ret = (*p & V_ASN1_CONSTRUCTED);
xclass = (*p & V_ASN1_PRIVATE);
i = *p & V_ASN1_PRIMITIVE_TAG;
if (i == V_ASN1_PRIMITIVE_TAG) { /* high-tag */
p++;
if (--max == 0)
goto err;
l = 0;
while (*p & 0x80) {
l <<= 7L;
l |= *(p++) & 0x7f;
if (--max == 0)
goto err;
if (l > (INT_MAX >> 7L))
goto err;
}
l <<= 7L;
l |= *(p++) & 0x7f;
tag = (int)l;
if (--max == 0)
goto err;
} else {
tag = i;
p++;
if (--max == 0)
goto err;
}
*ptag = tag;
*pclass = xclass;
if (!asn1_get_length(&p, &inf, plength, (int)max))
goto err;
/*
* 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;
if (inf && !(ret & V_ASN1_CONSTRUCTED))
goto err;
if (*plength > (omax - (p - *pp))) {
ASN1error(ASN1_R_TOO_LONG);
/* Set this so that even if things are not long enough
* the values are set correctly */
ret |= 0x80;
}
*pp = p;
return (ret | inf);
err:
ASN1error(ASN1_R_HEADER_TOO_LONG);
return (0x80);
}
static int
asn1_get_length(const unsigned char **pp, int *inf, long *rl, int max)
{
const unsigned char *p = *pp;
unsigned long ret = 0;
unsigned int i;
if (max-- < 1)
return (0);
if (*p == 0x80) {
*inf = 1;
ret = 0;
p++;
} else {
*inf = 0;
i = *p & 0x7f;
if (*(p++) & 0x80) {
if (max < (int)i)
return (0);
/* skip leading zeroes */
while (i && *p == 0) {
p++;
i--;
}
if (i > sizeof(long))
/* Long form. */
if (tag_number == 0x1f) {
tag_number = 0;
do {
if (!CBS_get_u8(cbs, &tag_val))
return 0;
while (i-- > 0) {
ret <<= 8L;
ret |= *(p++);
}
} else
ret = i;
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);
}
if (ret > LONG_MAX)
return 0;
*pp = p;
*rl = (long)ret;
return (1);
}
/* class 0 is constructed
* constructed == 2 for indefinite length constructed */
void
ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
int xclass)
{
unsigned char *p = *pp;
int i, ttag;
*out_class = tag_class;
*out_constructed = tag_constructed;
*out_tag_number = tag_number;
i = (constructed) ? V_ASN1_CONSTRUCTED : 0;
i |= (xclass & V_ASN1_PRIVATE);
if (tag < 31)
*(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG);
else {
*(p++) = i | V_ASN1_PRIMITIVE_TAG;
for(i = 0, ttag = tag; ttag > 0; i++)
ttag >>= 7;
ttag = i;
while (i-- > 0) {
p[i] = tag & 0x7f;
if (i != (ttag - 1))
p[i] |= 0x80;
tag >>= 7;
}
p += ttag;
}
if (constructed == 2)
*(p++) = 0x80;
else
asn1_put_length(&p, length);
*pp = p;
}
int
ASN1_put_eoc(unsigned char **pp)
{
unsigned char *p = *pp;
*p++ = 0;
*p++ = 0;
*pp = p;
return 2;
}
static void
asn1_put_length(unsigned char **pp, int length)
{
unsigned char *p = *pp;
int i, l;
if (length <= 127)
*(p++) = (unsigned char)length;
else {
l = length;
for (i = 0; l > 0; i++)
l >>= 8;
*(p++) = i | 0x80;
l = i;
while (i-- > 0) {
p[i] = length & 0xff;
length >>= 8;
}
p += l;
}
*pp = p;
}
int
ASN1_object_size(int constructed, int length, int tag)
{
int ret;
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);
}
int
ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str)
{
if (str == NULL)
return 0;
dst->type = str->type;
if (!ASN1_STRING_set(dst, str->data, str->length))
return 0;
dst->flags = str->flags;
return 1;
}
ASN1_STRING *
ASN1_STRING_dup(const ASN1_STRING *str)
static int
asn1_get_length_cbs(CBS *cbs, int der_mode, int *out_indefinite,
uint32_t *out_length)
{
ASN1_STRING *ret;
uint8_t len_bytes;
uint32_t length;
uint8_t val;
if (!str)
return NULL;
ret = ASN1_STRING_new();
if (!ret)
return NULL;
if (!ASN1_STRING_copy(ret, str)) {
ASN1_STRING_free(ret);
return NULL;
/*
* 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;
}
return ret;
/*
* 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 > (UINT32_MAX >> 8))
return 0;
length = (length << 8) | val;
}
*out_length = length;
return 1;
}
int
ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len)
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,
uint32_t *out_length)
{
const char *data = _data;
int constructed, indefinite;
uint32_t tag_number, length;
uint8_t tag_class;
if (len < 0) {
if (data == NULL)
return (0);
else
len = strlen(data);
}
if ((str->length < len) || (str->data == NULL)) {
unsigned char *tmp;
tmp = realloc(str->data, len + 1);
if (tmp == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
return (0);
}
str->data = tmp;
}
str->length = len;
if (data != NULL) {
memmove(str->data, data, len);
}
str->data[str->length] = '\0';
return (1);
}
*out_tag_class = 0;
*out_constructed = 0;
*out_tag_number = 0;
*out_indefinite = 0;
*out_length = 0;
void
ASN1_STRING_set0(ASN1_STRING *str, void *data, int len)
{
freezero(str->data, str->length);
str->data = data;
str->length = len;
}
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;
ASN1_STRING *
ASN1_STRING_new(void)
{
return (ASN1_STRING_type_new(V_ASN1_OCTET_STRING));
}
/* Indefinite length can only be used with constructed encoding. */
if (indefinite && !constructed)
return 0;
ASN1_STRING *
ASN1_STRING_type_new(int type)
{
ASN1_STRING *ret;
*out_tag_class = tag_class;
*out_constructed = constructed;
*out_tag_number = tag_number;
*out_indefinite = indefinite;
*out_length = length;
ret = malloc(sizeof(ASN1_STRING));
if (ret == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
return (NULL);
}
ret->length = 0;
ret->type = type;
ret->data = NULL;
ret->flags = 0;
return (ret);
}
void
ASN1_STRING_free(ASN1_STRING *a)
{
if (a == NULL)
return;
if (a->data != NULL && !(a->flags & ASN1_STRING_FLAG_NDEF))
freezero(a->data, a->length);
free(a);
return 1;
}
int
ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
asn1_get_primitive(CBS *cbs, int der_mode, uint32_t *out_tag_number,
CBS *out_content)
{
int i;
int constructed, indefinite;
uint32_t tag_number, length;
uint8_t tag_class;
i = (a->length - b->length);
if (i == 0) {
i = memcmp(a->data, b->data, a->length);
if (i == 0)
return (a->type - b->type);
else
return (i);
} else
return (i);
}
*out_tag_number = 0;
void
asn1_add_error(const unsigned char *address, int offset)
{
ERR_asprintf_error_data("offset=%d", offset);
}
CBS_init(out_content, NULL, 0);
int
ASN1_STRING_length(const ASN1_STRING *x)
{
return (x->length);
}
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;
void
ASN1_STRING_length_set(ASN1_STRING *x, int len)
{
x->length = len;
}
/* A primitive is not constructed and has a definite length. */
if (constructed || indefinite)
return 0;
int
ASN1_STRING_type(const ASN1_STRING *x)
{
return (x->type);
}
if (!CBS_get_bytes(cbs, out_content, length))
return 0;
unsigned char *
ASN1_STRING_data(ASN1_STRING *x)
{
return (x->data);
}
*out_tag_number = tag_number;
const unsigned char *
ASN1_STRING_get0_data(const ASN1_STRING *x)
{
return (x->data);
return 1;
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: asn1_locl.h,v 1.12 2019/10/24 16:36:10 jsing Exp $ */
/* $OpenBSD: asn1_locl.h,v 1.24 2022/03/26 14:47:58 jsing Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2006.
*/
@@ -56,6 +56,8 @@
*
*/
#include "bytestring.h"
__BEGIN_HIDDEN_DECLS
/* Internal ASN1 structures and functions: not for application use */
@@ -63,6 +65,20 @@ __BEGIN_HIDDEN_DECLS
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 {
@@ -122,6 +138,9 @@ struct evp_pkey_asn1_method_st {
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);
} /* EVP_PKEY_ASN1_METHOD */;
/* Method to handle CRL access.
@@ -142,6 +161,23 @@ struct x509_crl_method_st {
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_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval, const ASN1_ITEM *it);
int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen, 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
*/
@@ -155,4 +191,18 @@ struct x509_crl_method_st {
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_object_cbs(CBS *cbs, int der_mode, uint8_t *out_class,
int *out_constructed, uint32_t *out_tag_number, int *out_indefinite,
uint32_t *out_length);
int asn1_get_primitive(CBS *cbs, int der_mode, uint32_t *out_tag_number,
CBS *out_content);
int asn1_tag2charwidth(int tag);
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);
__END_HIDDEN_DECLS

180
externals/libressl/crypto/asn1/asn1_old.c vendored Executable file
View File

@@ -0,0 +1,180 @@
/* $OpenBSD: asn1_old.c,v 1.2 2021/12/25 13:17:48 jsing 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_locl.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);
}
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);
}
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);
}
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);
}
#endif

211
externals/libressl/crypto/asn1/asn1_old_lib.c vendored Executable file
View File

@@ -0,0 +1,211 @@
/* $OpenBSD: asn1_old_lib.c,v 1.3 2022/01/14 07:57:17 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/err.h>
#include "asn1_locl.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, length;
uint8_t tag_class;
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)) {
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;
}
/* class 0 is constructed
* constructed == 2 for indefinite length constructed */
void
ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
int xclass)
{
unsigned char *p = *pp;
int i, ttag;
i = (constructed) ? V_ASN1_CONSTRUCTED : 0;
i |= (xclass & V_ASN1_PRIVATE);
if (tag < 31)
*(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG);
else {
*(p++) = i | V_ASN1_PRIMITIVE_TAG;
for(i = 0, ttag = tag; ttag > 0; i++)
ttag >>= 7;
ttag = i;
while (i-- > 0) {
p[i] = tag & 0x7f;
if (i != (ttag - 1))
p[i] |= 0x80;
tag >>= 7;
}
p += ttag;
}
if (constructed == 2)
*(p++) = 0x80;
else
asn1_put_length(&p, length);
*pp = p;
}
int
ASN1_put_eoc(unsigned char **pp)
{
unsigned char *p = *pp;
*p++ = 0;
*p++ = 0;
*pp = p;
return 2;
}
static void
asn1_put_length(unsigned char **pp, int length)
{
unsigned char *p = *pp;
int i, l;
if (length <= 127)
*(p++) = (unsigned char)length;
else {
l = length;
for (i = 0; l > 0; i++)
l >>= 8;
*(p++) = i | 0x80;
l = i;
while (i-- > 0) {
p[i] = length & 0xff;
length >>= 8;
}
p += l;
}
*pp = p;
}
int
ASN1_object_size(int constructed, int length, int tag)
{
int ret;
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);
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: asn1_par.c,v 1.28 2020/01/09 11:27:21 inoguchi Exp $ */
/* $OpenBSD: asn1_par.c,v 1.34 2022/02/12 03:07:24 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -80,7 +80,8 @@ asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
p="prim: ";
if (BIO_write(bp, p, 6) < 6)
goto err;
BIO_indent(bp, indent, 128);
if (!BIO_indent(bp, indent, 128))
goto err;
p = str;
if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
@@ -97,7 +98,7 @@ asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
if (BIO_printf(bp, "%-18s", p) <= 0)
goto err;
return (1);
err:
err:
return (0);
}
@@ -232,16 +233,13 @@ asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offset,
goto end;
}
} else if (tag == V_ASN1_BOOLEAN) {
int ii;
opp = op;
ii = d2i_ASN1_BOOLEAN(NULL, &opp, len + hl);
if (ii < 0) {
if (len == 1 && p < tot) {
BIO_printf(bp, ":%u", p[0]);
} else {
if (BIO_write(bp, "Bad boolean\n",
12) <= 0)
goto end;
}
BIO_printf(bp, ":%d", ii);
} else if (tag == V_ASN1_BMPSTRING) {
/* do the BMP thang */
} else if (tag == V_ASN1_OCTET_STRING) {
@@ -375,7 +373,7 @@ asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offset,
}
ret = 1;
end:
end:
if (o != NULL)
ASN1_OBJECT_free(o);
ASN1_OCTET_STRING_free(os);
@@ -384,25 +382,3 @@ end:
*pp = p;
return (ret);
}
const char *
ASN1_tag2str(int tag)
{
static const char * const tag2str[] = {
"EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", /* 0-4 */
"NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", /* 5-9 */
"ENUMERATED", "<ASN1 11>", "UTF8STRING", "<ASN1 13>", /* 10-13 */
"<ASN1 14>", "<ASN1 15>", "SEQUENCE", "SET", /* 15-17 */
"NUMERICSTRING", "PRINTABLESTRING", "T61STRING", /* 18-20 */
"VIDEOTEXSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME", /* 21-24 */
"GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", /* 25-27 */
"UNIVERSALSTRING", "<ASN1 29>", "BMPSTRING" /* 28-30 */
};
if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
tag &= ~0x100;
if (tag < 0 || tag > 30)
return "(unknown)";
return tag2str[tag];
}

263
externals/libressl/crypto/asn1/asn1_types.c vendored Executable file
View File

@@ -0,0 +1,263 @@
/* $OpenBSD: asn1_types.c,v 1.1 2021/12/14 17:35:21 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 <stddef.h>
#include <openssl/asn1.h>
struct asn1_type {
const char *name;
uint32_t bit_value;
int char_width;
};
/*
* 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,
},
[2] = {
/* Tag 2 (0x02) - Integer */
.name = "INTEGER",
.bit_value = 0,
.char_width = -1,
},
[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,
},
[6] = {
/* Tag 6 (0x06) - Object Identifier */
.name = "OBJECT",
.bit_value = 0,
.char_width = -1,
},
[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,
},
[10] = {
/* Tag 10 (0x0a) - Enumerated */
.name = "ENUMERATED",
.bit_value = B_ASN1_UNKNOWN,
.char_width = -1,
},
[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,
},
[14] = {
/* Tag 14 (0x0e) - Time */
.name = "<ASN1 14 TIME>",
.bit_value = B_ASN1_UNKNOWN,
.char_width = -1,
},
[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,
},
[17] = {
/* Tag 17 (0x11) - Set */
.name = "SET",
.bit_value = 0,
.char_width = -1,
},
[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_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;
}
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)";
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: asn_mime.c,v 1.27 2017/01/29 17:49:22 beck Exp $ */
/* $OpenBSD: asn_mime.c,v 1.29 2021/12/25 13:17:48 jsing Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project.
*/
@@ -63,6 +63,7 @@
#include <openssl/x509.h>
#include "asn1_locl.h"
#include "evp_locl.h"
/* Generalised MIME like utilities for streaming ASN1. Although many
* have a PKCS7/CMS like flavour others are more general purpose.
@@ -267,7 +268,7 @@ asn1_write_micalg(BIO *out, STACK_OF(X509_ALGOR) *mdalgs)
ret = 1;
err:
err:
return ret;
}
@@ -778,7 +779,7 @@ STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio)
return headers;
merr:
merr:
if (mhdr != NULL)
mime_hdr_free(mhdr);
sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
@@ -866,7 +867,7 @@ mime_hdr_new(char *name, char *value)
goto err;
}
return mhdr;
err:
err:
free(tmpname);
free(tmpval);
return NULL;
@@ -901,7 +902,7 @@ mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value)
goto err;
}
return 1;
err:
err:
free(tmpname);
free(tmpval);
return 0;

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: asn_moid.c,v 1.13 2017/01/29 17:49:22 beck Exp $ */
/* $OpenBSD: asn_moid.c,v 1.14 2022/01/07 11:13:54 tb Exp $ */
/* Written by Stephen Henson (steve@openssl.org) for the OpenSSL
* project 2001.
*/
@@ -65,6 +65,8 @@
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include "asn1_locl.h"
/* Simple ASN1 OID module: add all objects in a given section */
static int do_create(char *value, char *name);

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bio_asn1.c,v 1.13 2018/05/01 13:29:09 tb Exp $ */
/* $OpenBSD: bio_asn1.c,v 1.17 2022/01/14 08:40:57 tb Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project.
*/
@@ -67,6 +67,8 @@
#include <openssl/bio.h>
#include <openssl/asn1.h>
#include "bio_local.h"
/* Must be large enough for biggest tag+length */
#define DEFAULT_ASN1_BUF_SIZE 20
@@ -116,9 +118,8 @@ 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 long asn1_bio_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size);
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,
@@ -148,35 +149,23 @@ static int
asn1_bio_new(BIO *b)
{
BIO_ASN1_BUF_CTX *ctx;
ctx = malloc(sizeof(BIO_ASN1_BUF_CTX));
if (!ctx)
if ((ctx = calloc(1, sizeof(*ctx))) == NULL)
return 0;
if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE)) {
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 = (char *)ctx;
b->flags = 0;
return 1;
}
static int
asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size)
{
ctx->buf = malloc(size);
if (!ctx->buf)
return 0;
ctx->bufsize = size;
ctx->bufpos = 0;
ctx->buflen = 0;
ctx->copylen = 0;
ctx->asn1_class = V_ASN1_UNIVERSAL;
ctx->asn1_tag = V_ASN1_OCTET_STRING;
ctx->ex_buf = NULL;
ctx->ex_pos = 0;
ctx->ex_len = 0;
ctx->state = ASN1_STATE_START;
return 1;
}
@@ -284,7 +273,7 @@ asn1_bio_write(BIO *b, const char *in , int inl)
}
done:
done:
BIO_clear_retry_flags(b);
BIO_copy_next_retry(b);
@@ -357,7 +346,7 @@ asn1_bio_gets(BIO *b, char *str, int size)
}
static long
asn1_bio_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
asn1_bio_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
{
if (b->next_bio == NULL)
return (0);

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bio_ndef.c,v 1.10 2017/01/29 17:49:22 beck Exp $ */
/* $OpenBSD: bio_ndef.c,v 1.11 2021/12/25 13:17:48 jsing Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project.
*/
@@ -143,7 +143,7 @@ BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it)
return sarg.ndef_bio;
err:
err:
BIO_free(asn_bio);
free(ndef_aux);
return NULL;

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: p5_pbe.c,v 1.22 2017/01/29 17:49:22 beck Exp $ */
/* $OpenBSD: p5_pbe.c,v 1.23 2021/12/25 13:17:48 jsing Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 1999.
*/
@@ -159,7 +159,7 @@ PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
if (X509_ALGOR_set0(algor, OBJ_nid2obj(alg), V_ASN1_SEQUENCE, pbe_str))
return 1;
err:
err:
if (pbe != NULL)
PBEPARAM_free(pbe);
ASN1_STRING_free(pbe_str);

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: p5_pbev2.c,v 1.25 2017/01/29 17:49:22 beck Exp $ */
/* $OpenBSD: p5_pbev2.c,v 1.27 2021/12/25 13:17:48 jsing Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 1999-2004.
*/
@@ -64,6 +64,8 @@
#include <openssl/err.h>
#include <openssl/x509.h>
#include "evp_locl.h"
/* PKCS#5 v2.0 password based encryption structures */
static const ASN1_TEMPLATE PBE2PARAM_seq_tt[] = {
@@ -272,10 +274,10 @@ PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter, unsigned char *salt,
return ret;
merr:
merr:
ASN1error(ERR_R_MALLOC_FAILURE);
err:
err:
PBE2PARAM_free(pbe2);
/* Note 'scheme' is freed as part of pbe2 */
X509_ALGOR_free(kalg);
@@ -364,7 +366,7 @@ PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen, int prf_nid,
PBKDF2PARAM_free(kdf);
return keyfunc;
merr:
merr:
ASN1error(ERR_R_MALLOC_FAILURE);
PBKDF2PARAM_free(kdf);
X509_ALGOR_free(keyfunc);

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: p8_pkey.c,v 1.19 2018/08/24 20:17:33 tb Exp $ */
/* $OpenBSD: p8_pkey.c,v 1.20 2021/11/01 20:53:08 tb Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 1999.
*/
@@ -62,6 +62,8 @@
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include "x509_lcl.h"
/* Minor tweak to operation: zero private key data */
static int
pkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: t_crl.c,v 1.18 2019/05/12 15:56:31 tb Exp $ */
/* $OpenBSD: t_crl.c,v 1.20 2021/12/25 13:17:48 jsing Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 1999.
*/
@@ -66,6 +66,8 @@
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include "x509_lcl.h"
int
X509_CRL_print_fp(FILE *fp, X509_CRL *x)
{
@@ -138,6 +140,6 @@ X509_CRL_print(BIO *out, X509_CRL *x)
return 1;
err:
err:
return 0;
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: t_pkey.c,v 1.16 2014/07/11 08:44:47 jsing Exp $ */
/* $OpenBSD: t_pkey.c,v 1.17 2021/12/04 16:08:32 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -62,6 +62,8 @@
#include <openssl/buffer.h>
#include <openssl/objects.h>
#include "bn_lcl.h"
int
ASN1_bn_print(BIO *bp, const char *number, const BIGNUM *num,
unsigned char *buf, int off)

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: t_req.c,v 1.19 2017/01/29 17:49:22 beck Exp $ */
/* $OpenBSD: t_req.c,v 1.21 2021/12/25 13:17:48 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -74,6 +74,8 @@
#include <openssl/rsa.h>
#endif
#include "x509_lcl.h"
int
X509_REQ_print_fp(FILE *fp, X509_REQ *x)
{
@@ -192,7 +194,7 @@ X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflags,
ii = 0;
count = sk_ASN1_TYPE_num(
a->value.set);
get_next:
get_next:
at = sk_ASN1_TYPE_value(
a->value.set, ii);
type = at->type;
@@ -255,7 +257,7 @@ get_next:
return (1);
err:
err:
X509error(ERR_R_BUF_LIB);
return (0);
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: t_spki.c,v 1.11 2014/07/11 08:44:47 jsing Exp $ */
/* $OpenBSD: t_spki.c,v 1.13 2021/11/01 20:53:08 tb Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 1999.
*/
@@ -71,6 +71,8 @@
#include <openssl/rsa.h>
#endif
#include "x509_lcl.h"
/* Print out an SPKI */
int
@@ -94,7 +96,8 @@ NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki)
}
chal = spki->spkac->challenge;
if (chal->length)
BIO_printf(out, " Challenge String: %s\n", chal->data);
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));

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: t_x509.c,v 1.32 2020/04/10 07:05:24 tb Exp $ */
/* $OpenBSD: t_x509.c,v 1.37 2021/12/25 13:17:48 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -78,6 +78,7 @@
#endif
#include "asn1_locl.h"
#include "x509_lcl.h"
int
X509_print_fp(FILE *fp, X509 *x)
@@ -180,7 +181,7 @@ X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, unsigned long cflag)
if (BIO_printf(bp, " Issuer:%c", mlch) <= 0)
goto err;
if (X509_NAME_print_ex(bp, X509_get_issuer_name(x),
nmindent, nmflags) < 0)
nmindent, nmflags) < (nmflags == X509_FLAG_COMPAT ? 1 : 0))
goto err;
if (BIO_write(bp, "\n", 1) <= 0)
goto err;
@@ -203,7 +204,7 @@ X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, unsigned long cflag)
if (BIO_printf(bp, " Subject:%c", mlch) <= 0)
goto err;
if (X509_NAME_print_ex(bp, X509_get_subject_name(x),
nmindent, nmflags) < 0)
nmindent, nmflags) < (nmflags == X509_FLAG_COMPAT ? 1 : 0))
goto err;
if (BIO_write(bp, "\n", 1) <= 0)
goto err;
@@ -243,7 +244,7 @@ X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, unsigned long cflag)
}
ret = 1;
err:
err:
free(m);
return (ret);
}
@@ -261,10 +262,12 @@ X509_ocspid_print(BIO *bp, X509 *x)
in OCSP requests */
if (BIO_printf(bp, " Subject OCSP hash: ") <= 0)
goto err;
derlen = i2d_X509_NAME(x->cert_info->subject, NULL);
if ((derlen = i2d_X509_NAME(x->cert_info->subject, NULL)) <= 0)
goto err;
if ((der = dertmp = malloc(derlen)) == NULL)
goto err;
i2d_X509_NAME(x->cert_info->subject, &dertmp);
if (i2d_X509_NAME(x->cert_info->subject, &dertmp) <= 0)
goto err;
if (!EVP_Digest(der, derlen, SHA1md, NULL, EVP_sha1(), NULL))
goto err;
@@ -292,7 +295,7 @@ X509_ocspid_print(BIO *bp, X509 *x)
return (1);
err:
err:
free(der);
return (0);
}
@@ -348,36 +351,6 @@ X509_signature_print(BIO *bp, const X509_ALGOR *sigalg, const ASN1_STRING *sig)
return 1;
}
int
ASN1_STRING_print(BIO *bp, const ASN1_STRING *v)
{
int i, n;
char buf[80];
const char *p;
if (v == NULL)
return (0);
n = 0;
p = (const char *)v->data;
for (i = 0; i < v->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);
}
int
ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm)
{
@@ -443,7 +416,7 @@ ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm)
else
return (1);
err:
err:
BIO_write(bp, "Bad time value", 14);
return (0);
}
@@ -486,7 +459,7 @@ ASN1_UTCTIME_print(BIO *bp, const ASN1_UTCTIME *tm)
else
return (1);
err:
err:
BIO_write(bp, "Bad time value", 14);
return (0);
}
@@ -532,7 +505,7 @@ X509_NAME_print(BIO *bp, const X509_NAME *name, int obase)
ret = 1;
if (0) {
err:
err:
X509error(ERR_R_BUF_LIB);
}
free(b);

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: t_x509a.c,v 1.8 2014/07/11 08:44:47 jsing Exp $ */
/* $OpenBSD: t_x509a.c,v 1.10 2021/11/01 20:53:08 tb Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 1999.
*/
@@ -62,8 +62,9 @@
#include <openssl/evp.h>
#include <openssl/x509.h>
/* X509_CERT_AUX and string set routines
*/
#include "x509_lcl.h"
/* X509_CERT_AUX and string set routines */
int
X509_CERT_AUX_print(BIO *out, X509_CERT_AUX *aux, int indent)
@@ -105,8 +106,8 @@ X509_CERT_AUX_print(BIO *out, X509_CERT_AUX *aux, int indent)
} else
BIO_printf(out, "%*sNo Rejected Uses.\n", indent, "");
if (aux->alias)
BIO_printf(out, "%*sAlias: %s\n", indent, "",
aux->alias->data);
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++)

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: tasn_dec.c,v 1.37 2019/04/01 15:48:04 jsing Exp $ */
/* $OpenBSD: tasn_dec.c,v 1.49 2022/03/13 14:58:14 jsing Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2000.
*/
@@ -56,14 +56,18 @@
*
*/
#include <limits.h>
#include <stddef.h>
#include <string.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/objects.h>
#include <openssl/buffer.h>
#include <openssl/err.h>
#include <openssl/objects.h>
#include "asn1_locl.h"
#include "bytestring.h"
/* Constructed types with a recursive definition (such as can be found in PKCS7)
* could eventually exceed the stack given malicious input with excessive
@@ -74,15 +78,16 @@
static int asn1_check_eoc(const unsigned char **in, long len);
static int asn1_find_end(const unsigned char **in, long len, char inf);
static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len,
static int asn1_collect(CBB *cbb, const unsigned char **in, long len,
char inf, int tag, int aclass, int depth);
static int collect_data(BUF_MEM *buf, const unsigned char **p, long plen);
static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
char *inf, char *cst, const unsigned char **in, long len, int exptag,
int expclass, char opt, ASN1_TLC *ctx);
static int asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in,
long len, const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx,
int depth);
static int asn1_template_ex_d2i(ASN1_VALUE **pval, const unsigned char **in,
long len, const ASN1_TEMPLATE *tt, char opt, ASN1_TLC *ctx, int depth);
static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in,
@@ -90,68 +95,44 @@ static int asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in,
static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in,
long len, const ASN1_ITEM *it, int tag, int aclass, char opt,
ASN1_TLC *ctx);
static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *content, int len,
int utype, const ASN1_ITEM *it);
/* Table to convert tags to bit values, used for MSTRING type */
static const unsigned long tag2bit[32] = {
0, 0, 0, B_ASN1_BIT_STRING, /* tags 0 - 3 */
B_ASN1_OCTET_STRING, 0, 0, B_ASN1_UNKNOWN,/* tags 4- 7 */
B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN,/* tags 8-11 */
B_ASN1_UTF8STRING,B_ASN1_UNKNOWN,B_ASN1_UNKNOWN,B_ASN1_UNKNOWN,/* tags 12-15 */
B_ASN1_SEQUENCE,0,B_ASN1_NUMERICSTRING,B_ASN1_PRINTABLESTRING, /* tags 16-19 */
B_ASN1_T61STRING,B_ASN1_VIDEOTEXSTRING,B_ASN1_IA5STRING, /* tags 20-22 */
B_ASN1_UTCTIME, B_ASN1_GENERALIZEDTIME, /* tags 23-24 */
B_ASN1_GRAPHICSTRING,B_ASN1_ISO64STRING,B_ASN1_GENERALSTRING, /* tags 25-27 */
B_ASN1_UNIVERSALSTRING,B_ASN1_UNKNOWN,B_ASN1_BMPSTRING,B_ASN1_UNKNOWN, /* tags 28-31 */
};
unsigned long
ASN1_tag2bit(int tag)
static void
asn1_tlc_invalidate(ASN1_TLC *ctx)
{
if ((tag < 0) || (tag > 30))
return 0;
return tag2bit[tag];
if (ctx != NULL)
ctx->valid = 0;
}
/* Macro to initialize and invalidate the cache */
#define asn1_tlc_clear(c) if (c) (c)->valid = 0
/* Version to avoid compiler warning about 'c' always non-NULL */
#define asn1_tlc_clear_nc(c) (c)->valid = 0
/* Decode an ASN1 item, this currently behaves just
* like a standard 'd2i' function. 'in' points to
* a buffer to read the data from, in future we will
* have more advanced versions that can input data
* a piece at a time and this will simply be a special
* case.
*/
ASN1_VALUE *
ASN1_item_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
const ASN1_ITEM *it)
{
ASN1_TLC c;
ASN1_VALUE *ptmpval = NULL;
ASN1_TLC ctx;
if (!pval)
asn1_tlc_invalidate(&ctx);
if (pval == NULL)
pval = &ptmpval;
asn1_tlc_clear_nc(&c);
if (ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0)
return *pval;
return NULL;
if (asn1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &ctx, 0) <= 0)
return NULL;
return *pval;
}
int
ASN1_template_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
const ASN1_TEMPLATE *tt)
{
ASN1_TLC c;
ASN1_TLC ctx;
asn1_tlc_clear_nc(&c);
return asn1_template_ex_d2i(pval, in, len, tt, 0, &c, 0);
asn1_tlc_invalidate(&ctx);
return asn1_template_ex_d2i(pval, in, len, tt, 0, &ctx, 0);
}
/* Decode an item, taking care of IMPLICIT tagging, if any.
* If 'opt' set and tag mismatch return -1 to handle OPTIONAL
*/
@@ -210,6 +191,16 @@ asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
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);
goto err;
}
p = *in;
/* Just read in tag and class */
ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL,
@@ -245,6 +236,16 @@ asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
it, tag, aclass, opt, ctx);
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);
goto err;
}
if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL))
goto auxerr;
@@ -446,9 +447,9 @@ asn1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
return 0;
}
auxerr:
auxerr:
ASN1error(ASN1_R_AUX_ERROR);
err:
err:
if (combine == 0)
ASN1_item_ex_free(pval, it);
if (errtt)
@@ -535,7 +536,7 @@ asn1_template_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long inlen,
*in = p;
return 1;
err:
err:
ASN1_template_free(val, tt);
return 0;
}
@@ -652,7 +653,7 @@ asn1_template_noexp_d2i(ASN1_VALUE **val, const unsigned char **in, long len,
*in = p;
return 1;
err:
err:
ASN1_template_free(val, tt);
return 0;
}
@@ -663,15 +664,15 @@ asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen,
{
int ret = 0, utype;
long plen;
char cst, inf, free_cont = 0;
char cst, inf;
const unsigned char *p;
BUF_MEM buf;
const unsigned char *cont = NULL;
const unsigned char *content = NULL;
uint8_t *data = NULL;
size_t data_len = 0;
CBB cbb;
long len;
buf.length = 0;
buf.max = 0;
buf.data = NULL;
memset(&cbb, 0, sizeof(cbb));
if (!pval) {
ASN1error(ASN1_R_ILLEGAL_NULL);
@@ -726,69 +727,68 @@ asn1_d2i_ex_primitive(ASN1_VALUE **pval, const unsigned char **in, long inlen,
* when we have a exact match wont work
*/
if (utype == V_ASN1_OTHER) {
asn1_tlc_clear(ctx);
}
/* SEQUENCE and SET must be constructed */
else if (!cst) {
asn1_tlc_invalidate(ctx);
} else if (!cst) {
/* SEQUENCE and SET must be constructed */
ASN1error(ASN1_R_TYPE_NOT_CONSTRUCTED);
return 0;
}
cont = *in;
content = *in;
/* If indefinite length constructed find the real end */
if (inf) {
if (!asn1_find_end(&p, plen, inf))
goto err;
len = p - cont;
len = p - content;
} else {
len = p - cont + plen;
len = p - content + plen;
p += plen;
buf.data = NULL;
}
} else if (cst) {
/* Should really check the internal tags are correct but
/*
* Should really check the internal tags are correct but
* some things may get this wrong. The relevant specs
* say that constructed string types should be OCTET STRINGs
* internally irrespective of the type. So instead just check
* for UNIVERSAL class and ignore the tag.
*/
if (!asn1_collect(&buf, &p, plen, inf, -1, V_ASN1_UNIVERSAL, 0)) {
free_cont = 1;
if (!CBB_init(&cbb, 0))
goto err;
}
len = buf.length;
/* Append a final null to string */
if (!BUF_MEM_grow_clean(&buf, len + 1)) {
ASN1error(ERR_R_MALLOC_FAILURE);
return 0;
}
buf.data[len] = 0;
cont = (const unsigned char *)buf.data;
free_cont = 1;
if (!asn1_collect(&cbb, &p, plen, inf, -1, V_ASN1_UNIVERSAL, 0))
goto err;
if (!CBB_finish(&cbb, &data, &data_len))
goto err;
if (data_len > LONG_MAX)
goto err;
content = data;
len = data_len;
} else {
cont = p;
content = p;
len = plen;
p += plen;
}
/* We now have content length and type: translate into a structure */
if (!asn1_ex_c2i(pval, cont, len, utype, &free_cont, it))
if (!asn1_ex_c2i(pval, content, len, utype, it))
goto err;
*in = p;
ret = 1;
err:
if (free_cont && buf.data)
free(buf.data);
err:
CBB_cleanup(&cbb);
freezero(data, data_len);
return ret;
}
/* Translate ASN1 content octets into a structure */
int
asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype,
char *free_cont, const ASN1_ITEM *it)
static int
asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *content, int len, int utype,
const ASN1_ITEM *it)
{
ASN1_VALUE **opval = NULL;
ASN1_STRING *stmp;
@@ -798,10 +798,11 @@ asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype,
if (it->funcs != NULL) {
const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
char free_content = 0;
if (pf->prim_c2i == NULL)
return 0;
return pf->prim_c2i(pval, cont, len, utype, free_cont, it);
return pf->prim_c2i(pval, content, len, utype, &free_content, it);
}
/* If ANY type clear type and set pointer to internal value */
@@ -821,7 +822,7 @@ asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype,
}
switch (utype) {
case V_ASN1_OBJECT:
if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len))
if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &content, len))
goto err;
break;
@@ -840,19 +841,19 @@ asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype,
} else {
ASN1_BOOLEAN *tbool;
tbool = (ASN1_BOOLEAN *)pval;
*tbool = *cont;
*tbool = *content;
}
break;
case V_ASN1_BIT_STRING:
if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len))
if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &content, len))
goto err;
break;
case V_ASN1_INTEGER:
case V_ASN1_ENUMERATED:
tint = (ASN1_INTEGER **)pval;
if (!c2i_ASN1_INTEGER(tint, &cont, len))
if (!c2i_ASN1_INTEGER(tint, &content, len))
goto err;
/* Fixup type to match the expected form */
(*tint)->type = utype | ((*tint)->type & V_ASN1_NEG);
@@ -884,10 +885,9 @@ asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype,
ASN1error(ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH);
goto err;
}
/* All based on ASN1_STRING and handled the same */
if (!*pval) {
stmp = ASN1_STRING_type_new(utype);
if (!stmp) {
/* All based on ASN1_STRING and handled the same way. */
if (*pval == NULL) {
if ((stmp = ASN1_STRING_type_new(utype)) == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -896,19 +896,10 @@ asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype,
stmp = (ASN1_STRING *)*pval;
stmp->type = utype;
}
/* If we've already allocated a buffer use it */
if (*free_cont) {
free(stmp->data);
stmp->data = (unsigned char *)cont; /* UGLY CAST! RL */
stmp->length = len;
*free_cont = 0;
} else {
if (!ASN1_STRING_set(stmp, cont, len)) {
ASN1error(ERR_R_MALLOC_FAILURE);
ASN1_STRING_free(stmp);
*pval = NULL;
goto err;
}
if (!ASN1_STRING_set(stmp, content, len)) {
ASN1_STRING_free(stmp);
*pval = NULL;
goto err;
}
break;
}
@@ -918,7 +909,7 @@ asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype,
ret = 1;
err:
err:
if (!ret) {
ASN1_TYPE_free(typ);
if (opval)
@@ -927,7 +918,6 @@ err:
return ret;
}
/* This function finds the end of an ASN1 structure when passed its maximum
* length, whether it is indefinite length and a pointer to the content.
* This is more efficient than calling asn1_collect because it does not
@@ -996,21 +986,21 @@ asn1_find_end(const unsigned char **in, long len, char inf)
#endif
static int
asn1_collect(BUF_MEM *buf, const unsigned char **in, long len, char inf,
asn1_collect(CBB *cbb, const unsigned char **in, long len, char inf,
int tag, int aclass, int depth)
{
const unsigned char *p, *q;
long plen;
char cst, ininf;
if (depth > ASN1_MAX_STRING_NEST) {
ASN1error(ASN1_R_NESTED_ASN1_STRING);
return 0;
}
p = *in;
inf &= 1;
/* If no buffer and not indefinite length constructed just pass over
* the encoded data */
if (!buf && !inf) {
*in += len;
return 1;
}
while (len > 0) {
q = p;
/* Check for EOC */
@@ -1033,15 +1023,14 @@ asn1_collect(BUF_MEM *buf, const unsigned char **in, long len, char inf,
/* If indefinite length constructed update max length */
if (cst) {
if (depth >= ASN1_MAX_STRING_NEST) {
ASN1error(ASN1_R_NESTED_ASN1_STRING);
return 0;
}
if (!asn1_collect(buf, &p, plen, ininf, tag, aclass,
if (!asn1_collect(cbb, &p, plen, ininf, tag, aclass,
depth + 1))
return 0;
} else if (plen && !collect_data(buf, &p, plen))
return 0;
} else if (plen > 0) {
if (!CBB_add_bytes(cbb, p, plen))
return 0;
p += plen;
}
len -= p - q;
}
if (inf) {
@@ -1052,22 +1041,6 @@ asn1_collect(BUF_MEM *buf, const unsigned char **in, long len, char inf,
return 1;
}
static int
collect_data(BUF_MEM *buf, const unsigned char **p, long plen)
{
int len;
if (buf) {
len = buf->length;
if (!BUF_MEM_grow_clean(buf, len + plen)) {
ASN1error(ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(buf->data + len, *p, plen);
}
*p += plen;
return 1;
}
/* Check for ASN1 EOC and swallow it if found */
static int
@@ -1125,7 +1098,7 @@ asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, char *inf,
*/
if (!(i & 0x81) && ((plen + ctx->hdrlen) > len)) {
ASN1error(ASN1_R_TOO_LONG);
asn1_tlc_clear(ctx);
asn1_tlc_invalidate(ctx);
return 0;
}
}
@@ -1133,7 +1106,7 @@ asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, char *inf,
if (i & 0x80) {
ASN1error(ASN1_R_BAD_OBJECT_HEADER);
asn1_tlc_clear(ctx);
asn1_tlc_invalidate(ctx);
return 0;
}
if (exptag >= 0) {
@@ -1143,13 +1116,13 @@ asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, char *inf,
*/
if (opt)
return -1;
asn1_tlc_clear(ctx);
asn1_tlc_invalidate(ctx);
ASN1error(ASN1_R_WRONG_TAG);
return 0;
}
/* We have a tag and class match:
* assume we are going to do something with it */
asn1_tlc_clear(ctx);
asn1_tlc_invalidate(ctx);
}
if (i & 1)

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: tasn_enc.c,v 1.22 2019/04/01 15:48:04 jsing Exp $ */
/* $OpenBSD: tasn_enc.c,v 1.24 2022/01/07 11:13:54 tb Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2000.
*/
@@ -61,8 +61,11 @@
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/err.h>
#include <openssl/objects.h>
#include "asn1_locl.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,
@@ -152,9 +155,27 @@ ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it,
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);

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: tasn_fre.c,v 1.17 2019/04/01 15:48:04 jsing Exp $ */
/* $OpenBSD: tasn_fre.c,v 1.18 2022/01/07 12:24:17 tb Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2000.
*/
@@ -62,6 +62,8 @@
#include <openssl/asn1t.h>
#include <openssl/objects.h>
#include "asn1_locl.h"
static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it,
int combine);

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: tasn_new.c,v 1.18 2019/04/01 15:48:04 jsing Exp $ */
/* $OpenBSD: tasn_new.c,v 1.21 2022/01/07 12:24:17 tb Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2000.
*/
@@ -64,6 +64,8 @@
#include <openssl/asn1t.h>
#include <string.h>
#include "asn1_locl.h"
static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
int combine);
static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
@@ -103,10 +105,6 @@ asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine)
if (!combine)
*pval = NULL;
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_push_info(it->sname);
#endif
switch (it->itype) {
case ASN1_ITYPE_EXTERN:
@@ -136,10 +134,6 @@ asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine)
if (!i)
goto auxerr;
if (i == 2) {
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_pop_info();
#endif
return 1;
}
}
@@ -160,10 +154,6 @@ asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine)
if (!i)
goto auxerr;
if (i == 2) {
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_pop_info();
#endif
return 1;
}
}
@@ -183,27 +173,15 @@ asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine)
goto auxerr;
break;
}
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_pop_info();
#endif
return 1;
memerr:
memerr:
ASN1error(ERR_R_MALLOC_FAILURE);
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_pop_info();
#endif
return 0;
auxerr:
auxerr:
ASN1error(ASN1_R_AUX_ERROR);
ASN1_item_ex_free(pval, it);
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_pop_info();
#endif
return 0;
}
@@ -257,10 +235,6 @@ ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
*pval = NULL;
return 1;
}
#ifdef CRYPTO_MDEBUG
if (tt->field_name)
CRYPTO_push_info(tt->field_name);
#endif
/* If SET OF or SEQUENCE OF, its a STACK */
if (tt->flags & ASN1_TFLG_SK_MASK) {
STACK_OF(ASN1_VALUE) *skval;
@@ -276,11 +250,7 @@ ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
}
/* Otherwise pass it back to the item routine */
ret = asn1_item_ex_combine_new(pval, it, tt->flags & ASN1_TFLG_COMBINE);
done:
#ifdef CRYPTO_MDEBUG
if (it->sname)
CRYPTO_pop_info();
#endif
done:
return ret;
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: tasn_prn.c,v 1.21 2020/03/24 10:46:38 inoguchi Exp $ */
/* $OpenBSD: tasn_prn.c,v 1.22 2021/12/03 17:10:49 jsing Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2000.
*/
@@ -84,18 +84,14 @@ ASN1_PCTX default_pctx = {
ASN1_PCTX *
ASN1_PCTX_new(void)
{
ASN1_PCTX *ret;
ret = malloc(sizeof(ASN1_PCTX));
if (ret == NULL) {
ASN1_PCTX *p;
if ((p = calloc(1, sizeof(ASN1_PCTX))) == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->flags = 0;
ret->nm_flags = 0;
ret->cert_flags = 0;
ret->oid_flags = 0;
ret->str_flags = 0;
return ret;
return p;
}
void

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: tasn_typ.c,v 1.13 2015/07/24 15:09:52 jsing Exp $ */
/* $OpenBSD: tasn_typ.c,v 1.17 2021/12/26 15:20:21 tb Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2000.
*/
@@ -61,134 +61,6 @@
/* Declarations for string types */
const ASN1_ITEM ASN1_INTEGER_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_INTEGER,
.sname = "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);
}
int
i2d_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_INTEGER_it);
}
ASN1_INTEGER *
ASN1_INTEGER_new(void)
{
return (ASN1_INTEGER *)ASN1_item_new(&ASN1_INTEGER_it);
}
void
ASN1_INTEGER_free(ASN1_INTEGER *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_INTEGER_it);
}
const ASN1_ITEM ASN1_ENUMERATED_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_ENUMERATED,
.sname = "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);
}
int
i2d_ASN1_ENUMERATED(ASN1_ENUMERATED *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_ENUMERATED_it);
}
ASN1_ENUMERATED *
ASN1_ENUMERATED_new(void)
{
return (ASN1_ENUMERATED *)ASN1_item_new(&ASN1_ENUMERATED_it);
}
void
ASN1_ENUMERATED_free(ASN1_ENUMERATED *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_ENUMERATED_it);
}
const ASN1_ITEM ASN1_BIT_STRING_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_BIT_STRING,
.sname = "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);
}
int
i2d_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_BIT_STRING_it);
}
ASN1_BIT_STRING *
ASN1_BIT_STRING_new(void)
{
return (ASN1_BIT_STRING *)ASN1_item_new(&ASN1_BIT_STRING_it);
}
void
ASN1_BIT_STRING_free(ASN1_BIT_STRING *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_BIT_STRING_it);
}
const ASN1_ITEM ASN1_OCTET_STRING_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_OCTET_STRING,
.sname = "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);
}
int
i2d_ASN1_OCTET_STRING(ASN1_OCTET_STRING *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_OCTET_STRING_it);
}
ASN1_OCTET_STRING *
ASN1_OCTET_STRING_new(void)
{
return (ASN1_OCTET_STRING *)ASN1_item_new(&ASN1_OCTET_STRING_it);
}
void
ASN1_OCTET_STRING_free(ASN1_OCTET_STRING *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_OCTET_STRING_it);
}
const ASN1_ITEM ASN1_NULL_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_NULL,
@@ -221,13 +93,6 @@ ASN1_NULL_free(ASN1_NULL *a)
}
const ASN1_ITEM ASN1_OBJECT_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_OBJECT,
.sname = "ASN1_OBJECT",
};
const ASN1_ITEM ASN1_UTF8STRING_it = {
.itype = ASN1_ITYPE_PRIMITIVE,
.utype = V_ASN1_UTF8STRING,
@@ -552,13 +417,13 @@ ASN1_BMPSTRING_free(ASN1_BMPSTRING *a)
ASN1_item_free((ASN1_VALUE *)a, &ASN1_BMPSTRING_it);
}
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 = {
@@ -568,31 +433,6 @@ const ASN1_ITEM ASN1_SEQUENCE_it = {
};
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);
}
int
i2d_ASN1_TYPE(ASN1_TYPE *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_ANY_it);
}
ASN1_TYPE *
ASN1_TYPE_new(void)
{
return (ASN1_TYPE *)ASN1_item_new(&ASN1_ANY_it);
}
void
ASN1_TYPE_free(ASN1_TYPE *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_ANY_it);
}
/* Multistring types */
@@ -712,6 +552,28 @@ const ASN1_ITEM ASN1_BOOLEAN_it = {
.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,

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: tasn_utl.c,v 1.12 2017/01/29 17:49:22 beck Exp $ */
/* $OpenBSD: tasn_utl.c,v 1.13 2021/12/25 13:17:48 jsing Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2000.
*/
@@ -272,7 +272,7 @@ asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, int nullerr)
goto err;
return adb->default_tt;
err:
err:
/* FIXME: should log the value or OID of unsupported type */
if (nullerr)
ASN1error(ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE);

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: x_algor.c,v 1.22 2018/05/01 19:01:27 tb Exp $ */
/* $OpenBSD: x_algor.c,v 1.23 2021/12/12 14:27:20 tb Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2000.
*/
@@ -197,12 +197,10 @@ X509_ALGOR_get0(const ASN1_OBJECT **paobj, int *pptype, const void **ppval,
void
X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md)
{
int param_type;
int param_type = V_ASN1_NULL;
if (md->flags & EVP_MD_FLAG_DIGALGID_ABSENT)
if ((EVP_MD_flags(md) & EVP_MD_FLAG_DIGALGID_ABSENT) != 0)
param_type = V_ASN1_UNDEF;
else
param_type = V_ASN1_NULL;
X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL);
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: x_attrib.c,v 1.14 2020/06/04 21:21:03 schwarze Exp $ */
/* $OpenBSD: x_attrib.c,v 1.16 2021/12/25 13:17:48 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -62,6 +62,8 @@
#include <openssl/objects.h>
#include <openssl/x509.h>
#include "x509_lcl.h"
/* X509_ATTRIBUTE: this has the following form:
*
* typedef struct x509_attributes_st
@@ -192,7 +194,7 @@ X509_ATTRIBUTE_create(int nid, int atrtype, void *value)
ASN1_TYPE_set(val, atrtype, value);
return (ret);
err:
err:
if (ret != NULL)
X509_ATTRIBUTE_free(ret);
if (val != NULL)

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: x_crl.c,v 1.34 2019/03/13 20:34:00 tb Exp $ */
/* $OpenBSD: x_crl.c,v 1.37 2022/02/24 22:05:06 beck Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -66,6 +66,7 @@
#include <openssl/x509v3.h>
#include "asn1_locl.h"
#include "x509_lcl.h"
static int X509_REVOKED_cmp(const X509_REVOKED * const *a,
const X509_REVOKED * const *b);
@@ -287,9 +288,7 @@ crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
break;
case ASN1_OP_D2I_POST:
#ifndef OPENSSL_NO_SHA
X509_CRL_digest(crl, EVP_sha1(), crl->sha1_hash, NULL);
#endif
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)
@@ -659,14 +658,15 @@ X509_CRL_METHOD_new(int (*crl_init)(X509_CRL *crl),
{
X509_CRL_METHOD *m;
m = malloc(sizeof(X509_CRL_METHOD));
if (!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;
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: x_exten.c,v 1.16 2015/07/24 15:09:52 jsing Exp $ */
/* $OpenBSD: x_exten.c,v 1.17 2021/11/01 20:53:08 tb Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2000.
*/
@@ -61,6 +61,8 @@
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include "x509_lcl.h"
static const ASN1_TEMPLATE X509_EXTENSION_seq_tt[] = {
{
.offset = offsetof(X509_EXTENSION, object),

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: x_name.c,v 1.34 2018/02/20 17:09:20 jsing Exp $ */
/* $OpenBSD: x_name.c,v 1.37 2021/12/25 13:17:48 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -65,6 +65,7 @@
#include <openssl/x509.h>
#include "asn1_locl.h"
#include "x509_lcl.h"
typedef STACK_OF(X509_NAME_ENTRY) STACK_OF_X509_NAME_ENTRY;
DECLARE_STACK_OF(STACK_OF_X509_NAME_ENTRY)
@@ -256,7 +257,7 @@ x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it)
*val = (ASN1_VALUE *)ret;
return 1;
memerr:
memerr:
ASN1error(ERR_R_MALLOC_FAILURE);
if (ret) {
if (ret->entries)
@@ -336,7 +337,7 @@ x509_name_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long len,
*in = p;
return ret;
err:
err:
if (nm.x != NULL)
X509_NAME_free(nm.x);
ASN1error(ERR_R_NESTED_ASN1_ERROR);
@@ -421,7 +422,7 @@ x509_name_encode(X509_NAME *a)
a->modified = 0;
return len;
memerr:
memerr:
sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
local_sk_X509_NAME_ENTRY_free);
ASN1error(ERR_R_MALLOC_FAILURE);
@@ -511,7 +512,7 @@ x509_name_canon(X509_NAME *a)
i2d_name_canon(intname, &p);
ret = 1;
err:
err:
if (tmpentry)
X509_NAME_ENTRY_free(tmpentry);
if (intname)
@@ -626,19 +627,13 @@ i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) *_intname, unsigned char **in)
int
X509_NAME_set(X509_NAME **xn, X509_NAME *name)
{
X509_NAME *in;
if (!xn || !name)
return (0);
if (*xn != name) {
in = X509_NAME_dup(name);
if (in != NULL) {
X509_NAME_free(*xn);
*xn = in;
}
}
return (*xn != NULL);
if (*xn == name)
return *xn != NULL;
if ((name = X509_NAME_dup(name)) == NULL)
return 0;
X509_NAME_free(*xn);
*xn = name;
return 1;
}
int

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: x_pkey.c,v 1.20 2017/01/29 17:49:22 beck Exp $ */
/* $OpenBSD: x_pkey.c,v 1.21 2021/12/25 13:17:48 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -91,7 +91,7 @@ X509_PKEY_new(void)
ret->references = 1;
return (ret);
err:
err:
if (ret) {
X509_ALGOR_free(ret->enc_algor);
free(ret);

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: x_pubkey.c,v 1.27 2018/03/17 14:55:39 jsing Exp $ */
/* $OpenBSD: x_pubkey.c,v 1.31 2021/12/25 13:17:48 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -72,6 +72,8 @@
#endif
#include "asn1_locl.h"
#include "evp_locl.h"
#include "x509_lcl.h"
/* Minor tweak to operation: free up EVP_PKEY */
static int
@@ -110,7 +112,6 @@ const ASN1_ITEM X509_PUBKEY_it = {
.sname = "X509_PUBKEY",
};
X509_PUBKEY *
d2i_X509_PUBKEY(X509_PUBKEY **a, const unsigned char **in, long len)
{
@@ -168,7 +169,7 @@ X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey)
return 1;
error:
error:
if (pk != NULL)
X509_PUBKEY_free(pk);
return 0;
@@ -221,7 +222,7 @@ X509_PUBKEY_get0(X509_PUBKEY *key)
return ret;
error:
error:
EVP_PKEY_free(ret);
return (NULL);
}
@@ -239,168 +240,473 @@ X509_PUBKEY_get(X509_PUBKEY *key)
return pkey;
}
/* Now two pseudo ASN1 routines that take an EVP_PKEY structure
* and encode or decode as X509_PUBKEY
/*
* Decode an X509_PUBKEY into the specified key type.
*/
EVP_PKEY *
d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length)
static int
pubkey_ex_d2i(int pkey_type, ASN1_VALUE **pval, const unsigned char **in,
long len, const ASN1_ITEM *it)
{
X509_PUBKEY *xpk;
EVP_PKEY *pktmp;
xpk = d2i_X509_PUBKEY(NULL, pp, length);
if (!xpk)
return NULL;
pktmp = X509_PUBKEY_get(xpk);
X509_PUBKEY_free(xpk);
if (!pktmp)
return NULL;
if (a) {
EVP_PKEY_free(*a);
*a = pktmp;
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;
}
return pktmp;
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;
}
int
i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp)
/*
* 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;
int ret;
if (!a)
return 0;
if (!X509_PUBKEY_set(&xpk, a))
return 0;
ret = i2d_X509_PUBKEY(xpk, pp);
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;
}
/* The following are equivalents but which return RSA and DSA
* keys
*/
#ifndef OPENSSL_NO_RSA
RSA *
d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp, long length)
static int
pkey_pubkey_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
EVP_PKEY *pkey;
RSA *key;
const unsigned char *q;
q = *pp;
pkey = d2i_PUBKEY(NULL, &q, length);
if (!pkey)
return NULL;
key = EVP_PKEY_get1_RSA(pkey);
EVP_PKEY_free(pkey);
if (!key)
return NULL;
*pp = q;
if (a) {
RSA_free(*a);
*a = key;
}
return key;
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_RSA_PUBKEY(RSA *a, unsigned char **pp)
i2d_PUBKEY(EVP_PKEY *pkey, unsigned char **out)
{
EVP_PKEY *pktmp;
int ret;
if (!a)
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;
pktmp = EVP_PKEY_new();
if (!pktmp) {
ASN1error(ERR_R_MALLOC_FAILURE);
return 0;
}
EVP_PKEY_set1_RSA(pktmp, a);
ret = i2d_PUBKEY(pktmp, pp);
EVP_PKEY_free(pktmp);
return ret;
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
DSA *
d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, long length)
static int
dsa_pubkey_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
EVP_PKEY *pkey;
DSA *key;
const unsigned char *q;
q = *pp;
pkey = d2i_PUBKEY(NULL, &q, length);
if (!pkey)
return NULL;
key = EVP_PKEY_get1_DSA(pkey);
EVP_PKEY_free(pkey);
if (!key)
return NULL;
*pp = q;
if (a) {
DSA_free(*a);
*a = key;
}
return key;
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 *a, unsigned char **pp)
i2d_DSA_PUBKEY(DSA *dsa, unsigned char **out)
{
EVP_PKEY *pktmp;
int ret;
if (!a)
return 0;
pktmp = EVP_PKEY_new();
if (!pktmp) {
ASN1error(ERR_R_MALLOC_FAILURE);
return 0;
}
EVP_PKEY_set1_DSA(pktmp, a);
ret = i2d_PUBKEY(pktmp, pp);
EVP_PKEY_free(pktmp);
return ret;
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
EC_KEY *
d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length)
static int
ec_pubkey_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
{
EVP_PKEY *pkey;
EC_KEY *key;
const unsigned char *q;
q = *pp;
pkey = d2i_PUBKEY(NULL, &q, length);
if (!pkey)
return (NULL);
key = EVP_PKEY_get1_EC_KEY(pkey);
EVP_PKEY_free(pkey);
if (!key)
return (NULL);
*pp = q;
if (a) {
EC_KEY_free(*a);
*a = key;
}
return (key);
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 *a, unsigned char **pp)
i2d_EC_PUBKEY(EC_KEY *ec, unsigned char **out)
{
EVP_PKEY *pktmp;
int ret;
if (!a)
return (0);
if ((pktmp = EVP_PKEY_new()) == NULL) {
ASN1error(ERR_R_MALLOC_FAILURE);
return (0);
}
EVP_PKEY_set1_EC_KEY(pktmp, a);
ret = i2d_PUBKEY(pktmp, pp);
EVP_PKEY_free(pktmp);
return (ret);
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

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: x_req.c,v 1.17 2018/02/22 16:50:30 jsing Exp $ */
/* $OpenBSD: x_req.c,v 1.18 2021/11/01 20:53:08 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -61,6 +61,8 @@
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include "x509_lcl.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

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: x_sig.c,v 1.11 2015/02/11 04:00:39 jsing Exp $ */
/* $OpenBSD: x_sig.c,v 1.13 2021/11/01 20:53:08 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -61,6 +61,8 @@
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include "x509_lcl.h"
static const ASN1_TEMPLATE X509_SIG_seq_tt[] = {
{
.offset = offsetof(X509_SIG, algor),
@@ -108,3 +110,22 @@ 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;
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: x_x509.c,v 1.26 2018/02/17 15:50:42 jsing Exp $ */
/* $OpenBSD: x_x509.c,v 1.30 2021/12/25 13:17:48 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -65,6 +65,8 @@
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include "x509_lcl.h"
static const ASN1_AUX X509_CINF_aux = {
.flags = ASN1_AFLG_ENCODING,
.enc_offset = offsetof(X509_CINF, enc),
@@ -185,6 +187,10 @@ x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
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;
@@ -202,6 +208,10 @@ x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
policy_cache_free(ret->policy_cache);
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;
@@ -329,7 +339,7 @@ d2i_X509_AUX(X509 **a, const unsigned char **pp, long length)
}
return ret;
err:
err:
X509_free(ret);
return NULL;
}
@@ -345,6 +355,13 @@ i2d_X509_AUX(X509 *a, unsigned char **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)

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: x_x509a.c,v 1.15 2018/05/01 19:01:27 tb Exp $ */
/* $OpenBSD: x_x509a.c,v 1.18 2021/12/25 13:17:48 jsing Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 1999.
*/
@@ -62,6 +62,8 @@
#include <openssl/evp.h>
#include <openssl/x509.h>
#include "x509_lcl.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
@@ -226,7 +228,7 @@ X509_add1_trust_object(X509 *x, const ASN1_OBJECT *obj)
if (rc != 0)
return rc;
err:
err:
ASN1_OBJECT_free(objtmp);
return 0;
}
@@ -248,7 +250,7 @@ X509_add1_reject_object(X509 *x, const ASN1_OBJECT *obj)
if (rc != 0)
return rc;
err:
err:
ASN1_OBJECT_free(objtmp);
return 0;
}
@@ -270,56 +272,3 @@ X509_reject_clear(X509 *x)
x->aux->reject = NULL;
}
}
static const ASN1_TEMPLATE X509_CERT_PAIR_seq_tt[] = {
{
.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
.tag = 0,
.offset = offsetof(X509_CERT_PAIR, forward),
.field_name = "forward",
.item = &X509_it,
},
{
.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
.tag = 1,
.offset = offsetof(X509_CERT_PAIR, reverse),
.field_name = "reverse",
.item = &X509_it,
},
};
const ASN1_ITEM X509_CERT_PAIR_it = {
.itype = ASN1_ITYPE_SEQUENCE,
.utype = V_ASN1_SEQUENCE,
.templates = X509_CERT_PAIR_seq_tt,
.tcount = sizeof(X509_CERT_PAIR_seq_tt) / sizeof(ASN1_TEMPLATE),
.funcs = NULL,
.size = sizeof(X509_CERT_PAIR),
.sname = "X509_CERT_PAIR",
};
X509_CERT_PAIR *
d2i_X509_CERT_PAIR(X509_CERT_PAIR **a, const unsigned char **in, long len)
{
return (X509_CERT_PAIR *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
&X509_CERT_PAIR_it);
}
int
i2d_X509_CERT_PAIR(X509_CERT_PAIR *a, unsigned char **out)
{
return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_CERT_PAIR_it);
}
X509_CERT_PAIR *
X509_CERT_PAIR_new(void)
{
return (X509_CERT_PAIR *)ASN1_item_new(&X509_CERT_PAIR_it);
}
void
X509_CERT_PAIR_free(X509_CERT_PAIR *a)
{
ASN1_item_free((ASN1_VALUE *)a, &X509_CERT_PAIR_it);
}

View File

@@ -1,10 +1,10 @@
/* $OpenBSD: b_dump.c,v 1.21 2015/04/23 06:11:19 deraadt Exp $ */
/* $OpenBSD: b_dump.c,v 1.22 2021/07/11 20:18:07 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.
* 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
@@ -82,7 +82,7 @@ BIO_dump_indent_cb(int (*cb)(const void *data, size_t len, void *u),
{
int ret = 0;
char buf[288 + 1], tmp[20], str[128 + 1];
int i, j, rows, trc;
int i, j, rows, trc, written;
unsigned char ch;
int dump_width;
@@ -133,13 +133,18 @@ BIO_dump_indent_cb(int (*cb)(const void *data, size_t len, void *u),
/* if this is the last call then update the ddt_dump thing so
* that we will move the selection point in the debug window
*/
ret += cb((void *)buf, strlen(buf), u);
if ((written = cb((void *)buf, strlen(buf), u)) < 0)
return -1;
ret += written;
}
#ifdef TRUNCATE
if (trc > 0) {
snprintf(buf, sizeof buf, "%s%04x - <SPACES/NULS>\n",
str, len + trc);
ret += cb((void *)buf, strlen(buf), u);
if ((written = cb((void *)buf, strlen(buf), u)) < 0)
return -1;
ret += written;
}
#endif
return (ret);

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bf_buff.c,v 1.25 2018/05/01 13:29:09 tb Exp $ */
/* $OpenBSD: bf_buff.c,v 1.27 2022/01/14 08:40:57 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -63,6 +63,8 @@
#include <openssl/bio.h>
#include <openssl/err.h>
#include "bio_local.h"
static int buffer_write(BIO *h, const char *buf, int num);
static int buffer_read(BIO *h, char *buf, int size);
static int buffer_puts(BIO *h, const char *str);
@@ -70,7 +72,7 @@ static int buffer_gets(BIO *h, char *str, int size);
static long buffer_ctrl(BIO *h, int cmd, long arg1, void *arg2);
static int buffer_new(BIO *h);
static int buffer_free(BIO *data);
static long buffer_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp);
static long buffer_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
#define DEFAULT_BUFFER_SIZE 4096
static const BIO_METHOD methods_buffer = {
@@ -450,7 +452,7 @@ malloc_error:
}
static long
buffer_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
buffer_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
{
long ret = 1;

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bf_nbio.c,v 1.20 2018/05/01 13:29:09 tb Exp $ */
/* $OpenBSD: bf_nbio.c,v 1.22 2022/01/14 08:40:57 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -62,6 +62,8 @@
#include <openssl/bio.h>
#include "bio_local.h"
/* BIO_put and BIO_get both add to the digest,
* BIO_gets returns the digest */
@@ -72,7 +74,7 @@ static int nbiof_gets(BIO *h, char *str, int size);
static long nbiof_ctrl(BIO *h, int cmd, long arg1, void *arg2);
static int nbiof_new(BIO *h);
static int nbiof_free(BIO *data);
static long nbiof_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp);
static long nbiof_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
typedef struct nbio_test_st {
/* only set if we sent a 'should retry' error */
@@ -221,7 +223,7 @@ nbiof_ctrl(BIO *b, int cmd, long num, void *ptr)
}
static long
nbiof_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
nbiof_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
{
long ret = 1;

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bf_null.c,v 1.12 2018/05/01 13:29:09 tb Exp $ */
/* $OpenBSD: bf_null.c,v 1.14 2022/01/14 08:40:57 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -61,6 +61,8 @@
#include <openssl/bio.h>
#include "bio_local.h"
/* BIO_put and BIO_get both add to the digest,
* BIO_gets returns the digest */
@@ -71,7 +73,7 @@ static int nullf_gets(BIO *h, char *str, int size);
static long nullf_ctrl(BIO *h, int cmd, long arg1, void *arg2);
static int nullf_new(BIO *h);
static int nullf_free(BIO *data);
static long nullf_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp);
static long nullf_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
static const BIO_METHOD methods_nullf = {
.type = BIO_TYPE_NULL_FILTER,
@@ -165,7 +167,7 @@ nullf_ctrl(BIO *b, int cmd, long num, void *ptr)
}
static long
nullf_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
nullf_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
{
long ret = 1;

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bio_cb.c,v 1.16 2014/12/08 03:54:19 bcook Exp $ */
/* $OpenBSD: bio_cb.c,v 1.18 2022/01/07 09:02:17 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -63,6 +63,8 @@
#include <openssl/err.h>
#include <openssl/bio.h>
#include "bio_local.h"
long
BIO_debug_callback(BIO *bio, int cmd, const char *argp, int argi, long argl,
long ret)
@@ -70,15 +72,22 @@ BIO_debug_callback(BIO *bio, int cmd, const char *argp, int argi, long argl,
BIO *b;
char buf[256];
char *p;
int nbuf;
long r = 1;
size_t p_maxlen;
if (BIO_CB_RETURN & cmd)
r = ret;
snprintf(buf, sizeof buf, "BIO[%p]:", bio);
p = &(buf[14]);
p_maxlen = sizeof buf - 14;
nbuf = snprintf(buf, sizeof(buf), "BIO[%p]: ", bio);
if (nbuf < 0)
nbuf = 0; /* Ignore error; continue printing. */
if (nbuf >= sizeof(buf))
goto out;
p = buf + nbuf;
p_maxlen = sizeof(buf) - nbuf;
switch (cmd) {
case BIO_CB_FREE:
snprintf(p, p_maxlen, "Free - %s\n", bio->method->name);
@@ -136,6 +145,7 @@ BIO_debug_callback(BIO *bio, int cmd, const char *argp, int argi, long argl,
break;
}
out:
b = (BIO *)bio->cb_arg;
if (b != NULL)
BIO_write(b, buf, strlen(buf));

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bio_err.c,v 1.17 2017/01/29 17:49:22 beck Exp $ */
/* $OpenBSD: bio_err.c,v 1.18 2022/01/14 08:40:57 tb Exp $ */
/* ====================================================================
* Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved.
*
@@ -92,6 +92,7 @@ static ERR_STRING_DATA BIO_str_reasons[] = {
{ERR_REASON(BIO_R_INVALID_PORT_NUMBER) , "invalid port number"},
{ERR_REASON(BIO_R_IN_USE) , "in use"},
{ERR_REASON(BIO_R_KEEPALIVE) , "keepalive"},
{ERR_REASON(BIO_R_LENGTH_TOO_LONG) , "too long"},
{ERR_REASON(BIO_R_NBIO_CONNECT_ERROR) , "nbio connect error"},
{ERR_REASON(BIO_R_NO_ACCEPT_PORT_SPECIFIED), "no accept port specified"},
{ERR_REASON(BIO_R_NO_HOSTNAME_SPECIFIED) , "no hostname specified"},

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bio_lib.c,v 1.29 2019/04/14 17:39:03 jsing Exp $ */
/* $OpenBSD: bio_lib.c,v 1.35 2022/01/14 08:40:57 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -57,6 +57,7 @@
*/
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <openssl/bio.h>
@@ -64,6 +65,57 @@
#include <openssl/err.h>
#include <openssl/stack.h>
#include "bio_local.h"
/*
* Helper function to work out whether to call the new style callback or the old
* one, and translate between the two.
*
* This has a long return type for consistency with the old callback. Similarly
* for the "long" used for "inret"
*/
static long
bio_call_callback(BIO *b, int oper, const char *argp, size_t len, int argi,
long argl, long inret, size_t *processed)
{
long ret;
int bareoper;
if (b->callback_ex != NULL)
return b->callback_ex(b, oper, argp, len, argi, argl, inret,
processed);
/*
* We have an old style callback, so we will have to do nasty casts and
* check for overflows.
*/
bareoper = oper & ~BIO_CB_RETURN;
if (bareoper == BIO_CB_READ || bareoper == BIO_CB_WRITE ||
bareoper == BIO_CB_GETS) {
/* In this case len is set and should be used instead of argi. */
if (len > INT_MAX)
return -1;
argi = (int)len;
}
if (inret > 0 && (oper & BIO_CB_RETURN) && bareoper != BIO_CB_CTRL) {
if (*processed > INT_MAX)
return -1;
inret = *processed;
}
ret = b->callback(b, oper, argp, argi, argl, inret);
if (ret > 0 && (oper & BIO_CB_RETURN) && bareoper != BIO_CB_CTRL) {
*processed = (size_t)ret;
ret = 1;
}
return ret;
}
int
BIO_get_new_index(void)
{
@@ -83,6 +135,7 @@ BIO_new(const BIO_METHOD *method)
{
BIO *ret = NULL;
/* XXX calloc */
ret = malloc(sizeof(BIO));
if (ret == NULL) {
BIOerror(ERR_R_MALLOC_FAILURE);
@@ -100,6 +153,7 @@ BIO_set(BIO *bio, const BIO_METHOD *method)
{
bio->method = method;
bio->callback = NULL;
bio->callback_ex = NULL;
bio->cb_arg = NULL;
bio->init = 0;
bio->shutdown = 1;
@@ -113,29 +167,32 @@ BIO_set(BIO *bio, const BIO_METHOD *method)
bio->num_read = 0L;
bio->num_write = 0L;
CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
if (method->create != NULL)
if (method->create != NULL) {
if (!method->create(bio)) {
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio,
&bio->ex_data);
return (0);
}
}
return (1);
}
int
BIO_free(BIO *a)
{
int i;
int ret;
if (a == NULL)
return (0);
i = CRYPTO_add(&a->references, -1, CRYPTO_LOCK_BIO);
if (i > 0)
if (CRYPTO_add(&a->references, -1, CRYPTO_LOCK_BIO) > 0)
return (1);
if ((a->callback != NULL) &&
((i = (int)a->callback(a, BIO_CB_FREE, NULL, 0, 0L, 1L)) <= 0))
return (i);
if (a->callback != NULL || a->callback_ex != NULL) {
if ((ret = (int)bio_call_callback(a, BIO_CB_FREE, NULL, 0, 0,
0L, 1L, NULL)) <= 0)
return (ret);
}
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data);
@@ -170,6 +227,12 @@ BIO_set_data(BIO *a, void *ptr)
a->ptr = ptr;
}
int
BIO_get_init(BIO *a)
{
return a->init;
}
void
BIO_set_init(BIO *a, int init)
{
@@ -206,20 +269,30 @@ BIO_set_flags(BIO *b, int flags)
b->flags |= flags;
}
long
(*BIO_get_callback(const BIO *b))(struct bio_st *, int, const char *, int,
long, long)
BIO_callback_fn
BIO_get_callback(const BIO *b)
{
return b->callback;
}
void
BIO_set_callback(BIO *b, long (*cb)(struct bio_st *, int, const char *, int,
long, long))
BIO_set_callback(BIO *b, BIO_callback_fn cb)
{
b->callback = cb;
}
BIO_callback_fn_ex
BIO_get_callback_ex(const BIO *b)
{
return b->callback_ex;
}
void
BIO_set_callback_ex(BIO *b, BIO_callback_fn_ex cb)
{
b->callback_ex = cb;
}
void
BIO_set_callback_arg(BIO *b, char *arg)
{
@@ -247,8 +320,8 @@ BIO_method_type(const BIO *b)
int
BIO_read(BIO *b, void *out, int outl)
{
int i;
long (*cb)(BIO *, int, const char *, int, long, long);
size_t readbytes = 0;
int ret;
if (b == NULL)
return (0);
@@ -261,33 +334,44 @@ BIO_read(BIO *b, void *out, int outl)
return (-2);
}
cb = b->callback;
if ((cb != NULL) &&
((i = (int)cb(b, BIO_CB_READ, out, outl, 0L, 1L)) <= 0))
return (i);
if (b->callback != NULL || b->callback_ex != NULL) {
if ((ret = (int)bio_call_callback(b, BIO_CB_READ, out, outl, 0,
0L, 1L, NULL)) <= 0)
return (ret);
}
if (!b->init) {
BIOerror(BIO_R_UNINITIALIZED);
return (-2);
}
i = b->method->bread(b, out, outl);
if ((ret = b->method->bread(b, out, outl)) > 0)
readbytes = (size_t)ret;
if (i > 0)
b->num_read += (unsigned long)i;
b->num_read += readbytes;
if (cb != NULL)
i = (int)cb(b, BIO_CB_READ|BIO_CB_RETURN, out, outl,
0L, (long)i);
if (b->callback != NULL || b->callback_ex != NULL) {
ret = (int)bio_call_callback(b, BIO_CB_READ | BIO_CB_RETURN,
out, outl, 0, 0L, (ret > 0) ? 1 : ret, &readbytes);
}
return (i);
if (ret > 0) {
if (readbytes > INT_MAX) {
BIOerror(BIO_R_LENGTH_TOO_LONG);
ret = -1;
} else {
ret = (int)readbytes;
}
}
return (ret);
}
int
BIO_write(BIO *b, const void *in, int inl)
{
int i;
long (*cb)(BIO *, int, const char *, int, long, long);
size_t writebytes = 0;
int ret;
if (b == NULL)
return (0);
@@ -300,95 +384,132 @@ BIO_write(BIO *b, const void *in, int inl)
return (-2);
}
cb = b->callback;
if ((cb != NULL) &&
((i = (int)cb(b, BIO_CB_WRITE, in, inl, 0L, 1L)) <= 0))
return (i);
if (b->callback != NULL || b->callback_ex != NULL) {
if ((ret = (int)bio_call_callback(b, BIO_CB_WRITE, in, inl, 0,
0L, 1L, NULL)) <= 0)
return (ret);
}
if (!b->init) {
BIOerror(BIO_R_UNINITIALIZED);
return (-2);
}
i = b->method->bwrite(b, in, inl);
if ((ret = b->method->bwrite(b, in, inl)) > 0)
writebytes = ret;
if (i > 0)
b->num_write += (unsigned long)i;
b->num_write += writebytes;
if (cb != NULL)
i = (int)cb(b, BIO_CB_WRITE|BIO_CB_RETURN, in, inl,
0L, (long)i);
return (i);
if (b->callback != NULL || b->callback_ex != NULL) {
ret = (int)bio_call_callback(b, BIO_CB_WRITE | BIO_CB_RETURN,
in, inl, 0, 0L, (ret > 0) ? 1 : ret, &writebytes);
}
if (ret > 0) {
if (writebytes > INT_MAX) {
BIOerror(BIO_R_LENGTH_TOO_LONG);
ret = -1;
} else {
ret = (int)writebytes;
}
}
return (ret);
}
int
BIO_puts(BIO *b, const char *in)
{
int i;
long (*cb)(BIO *, int, const char *, int, long, long);
size_t writebytes = 0;
int ret;
if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL)) {
if (b == NULL || b->method == NULL || b->method->bputs == NULL) {
BIOerror(BIO_R_UNSUPPORTED_METHOD);
return (-2);
}
cb = b->callback;
if ((cb != NULL) &&
((i = (int)cb(b, BIO_CB_PUTS, in, 0, 0L, 1L)) <= 0))
return (i);
if (b->callback != NULL || b->callback_ex != NULL) {
if ((ret = (int)bio_call_callback(b, BIO_CB_PUTS, in, 0, 0, 0L,
1L, NULL)) <= 0)
return (ret);
}
if (!b->init) {
BIOerror(BIO_R_UNINITIALIZED);
return (-2);
}
i = b->method->bputs(b, in);
if ((ret = b->method->bputs(b, in)) > 0)
writebytes = ret;
if (i > 0)
b->num_write += (unsigned long)i;
b->num_write += writebytes;
if (cb != NULL)
i = (int)cb(b, BIO_CB_PUTS|BIO_CB_RETURN, in, 0, 0L, (long)i);
return (i);
if (b->callback != NULL || b->callback_ex != NULL) {
ret = (int)bio_call_callback(b, BIO_CB_PUTS | BIO_CB_RETURN,
in, 0, 0, 0L, (ret > 0) ? 1 : ret, &writebytes);
}
if (ret > 0) {
if (writebytes > INT_MAX) {
BIOerror(BIO_R_LENGTH_TOO_LONG);
ret = -1;
} else {
ret = (int)writebytes;
}
}
return (ret);
}
int
BIO_gets(BIO *b, char *in, int inl)
{
int i;
long (*cb)(BIO *, int, const char *, int, long, long);
size_t readbytes;
int ret;
if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL)) {
if (b == NULL || b->method == NULL || b->method->bgets == NULL) {
BIOerror(BIO_R_UNSUPPORTED_METHOD);
return (-2);
}
cb = b->callback;
if ((cb != NULL) &&
((i = (int)cb(b, BIO_CB_GETS, in, inl, 0L, 1L)) <= 0))
return (i);
if (b->callback != NULL || b->callback_ex != NULL) {
if ((ret = (int)bio_call_callback(b, BIO_CB_GETS, in, inl, 0, 0L,
1, NULL)) <= 0)
return (ret);
}
if (!b->init) {
BIOerror(BIO_R_UNINITIALIZED);
return (-2);
}
i = b->method->bgets(b, in, inl);
if ((ret = b->method->bgets(b, in, inl)) > 0)
readbytes = ret;
if (cb != NULL)
i = (int)cb(b, BIO_CB_GETS|BIO_CB_RETURN, in, inl, 0L, (long)i);
return (i);
if (b->callback != NULL || b->callback_ex != NULL) {
ret = (int)bio_call_callback(b, BIO_CB_GETS | BIO_CB_RETURN, in,
inl, 0, 0L, (ret > 0) ? 1 : ret, &readbytes);
}
if (ret > 0) {
if (readbytes > INT_MAX) {
BIOerror(BIO_R_LENGTH_TOO_LONG);
ret = -1;
} else {
ret = (int)readbytes;
}
}
return (ret);
}
int
BIO_indent(BIO *b, int indent, int max)
{
if (indent < 0)
indent = 0;
if (indent > max)
indent = max;
if (indent < 0)
indent = 0;
while (indent--)
if (BIO_puts(b, " ") != 1)
return 0;
@@ -419,54 +540,58 @@ long
BIO_ctrl(BIO *b, int cmd, long larg, void *parg)
{
long ret;
long (*cb)(BIO *, int, const char *, int, long, long);
if (b == NULL)
return (0);
if ((b->method == NULL) || (b->method->ctrl == NULL)) {
if (b->method == NULL || b->method->ctrl == NULL) {
BIOerror(BIO_R_UNSUPPORTED_METHOD);
return (-2);
}
cb = b->callback;
if ((cb != NULL) &&
((ret = cb(b, BIO_CB_CTRL, parg, cmd, larg, 1L)) <= 0))
return (ret);
if (b->callback != NULL || b->callback_ex != NULL) {
if ((ret = bio_call_callback(b, BIO_CB_CTRL, parg, 0, cmd, larg,
1L, NULL)) <= 0)
return (ret);
}
ret = b->method->ctrl(b, cmd, larg, parg);
if (cb != NULL)
ret = cb(b, BIO_CB_CTRL|BIO_CB_RETURN, parg, cmd, larg, ret);
if (b->callback != NULL || b->callback_ex != NULL) {
ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, parg, 0,
cmd, larg, ret, NULL);
}
return (ret);
}
long
BIO_callback_ctrl(BIO *b, int cmd,
void (*fp)(struct bio_st *, int, const char *, int, long, long))
BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
{
long ret;
long (*cb)(BIO *, int, const char *, int, long, long);
if (b == NULL)
return (0);
if ((b->method == NULL) || (b->method->callback_ctrl == NULL)) {
if (b->method == NULL || b->method->callback_ctrl == NULL ||
cmd != BIO_CTRL_SET_CALLBACK) {
BIOerror(BIO_R_UNSUPPORTED_METHOD);
return (-2);
}
cb = b->callback;
if ((cb != NULL) &&
((ret = cb(b, BIO_CB_CTRL, (void *)&fp, cmd, 0, 1L)) <= 0))
return (ret);
if (b->callback != NULL || b->callback_ex != NULL) {
if ((ret = bio_call_callback(b, BIO_CB_CTRL, (void *)&fp, 0,
cmd, 0, 1L, NULL)) <= 0)
return (ret);
}
ret = b->method->callback_ctrl(b, cmd, fp);
if (cb != NULL)
ret = cb(b, BIO_CB_CTRL|BIO_CB_RETURN, (void *)&fp, cmd, 0, ret);
if (b->callback != NULL || b->callback_ex != NULL) {
ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN,
(void *)&fp, 0, cmd, 0, ret, NULL);
}
return (ret);
}
@@ -552,6 +677,12 @@ BIO_get_retry_reason(BIO *bio)
return (bio->retry_reason);
}
void
BIO_set_retry_reason(BIO *bio, int reason)
{
bio->retry_reason = reason;
}
BIO *
BIO_find_type(BIO *bio, int type)
{
@@ -582,6 +713,12 @@ BIO_next(BIO *b)
return b->next_bio;
}
void
BIO_set_next(BIO *b, BIO *next)
{
b->next_bio = next;
}
void
BIO_free_all(BIO *bio)
{
@@ -608,6 +745,7 @@ BIO_dup_chain(BIO *in)
if ((new_bio = BIO_new(bio->method)) == NULL)
goto err;
new_bio->callback = bio->callback;
new_bio->callback_ex = bio->callback_ex;
new_bio->cb_arg = bio->cb_arg;
new_bio->init = bio->init;
new_bio->shutdown = bio->shutdown;

123
externals/libressl/crypto/bio/bio_local.h vendored Executable file
View File

@@ -0,0 +1,123 @@
/* $OpenBSD: bio_local.h,v 1.3 2022/01/14 08:40:57 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.]
*/
#ifndef HEADER_BIO_LOCAL_H
#define HEADER_BIO_LOCAL_H
__BEGIN_HIDDEN_DECLS
struct bio_method_st {
int type;
const char *name;
int (*bwrite)(BIO *, const char *, int);
int (*bread)(BIO *, char *, int);
int (*bputs)(BIO *, const char *);
int (*bgets)(BIO *, char *, int);
long (*ctrl)(BIO *, int, long, void *);
int (*create)(BIO *);
int (*destroy)(BIO *);
long (*callback_ctrl)(BIO *, int, BIO_info_cb *);
} /* BIO_METHOD */;
struct bio_st {
const BIO_METHOD *method;
BIO_callback_fn callback;
BIO_callback_fn_ex callback_ex;
char *cb_arg; /* first argument for the callback */
int init;
int shutdown;
int flags; /* extra storage */
int retry_reason;
int num;
void *ptr;
struct bio_st *next_bio; /* used by filter BIOs */
struct bio_st *prev_bio; /* used by filter BIOs */
int references;
unsigned long num_read;
unsigned long num_write;
CRYPTO_EX_DATA ex_data;
} /* BIO */;
typedef struct bio_f_buffer_ctx_struct {
/* Buffers are setup like this:
*
* <---------------------- size ----------------------->
* +---------------------------------------------------+
* | consumed | remaining | free space |
* +---------------------------------------------------+
* <-- off --><------- len ------->
*/
/* BIO *bio; */ /* this is now in the BIO struct */
int ibuf_size; /* how big is the input buffer */
int obuf_size; /* how big is the output buffer */
char *ibuf; /* the char array */
int ibuf_len; /* how many bytes are in it */
int ibuf_off; /* write/read offset */
char *obuf; /* the char array */
int obuf_len; /* how many bytes are in it */
int obuf_off; /* write/read offset */
} BIO_F_BUFFER_CTX;
__END_HIDDEN_DECLS
#endif /* !HEADER_BIO_LOCAL_H */

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bio_meth.c,v 1.6 2018/06/02 04:41:12 tb Exp $ */
/* $OpenBSD: bio_meth.c,v 1.8 2022/01/14 08:40:57 tb Exp $ */
/*
* Copyright (c) 2018 Theo Buehler <tb@openbsd.org>
*
@@ -19,6 +19,8 @@
#include <openssl/bio.h>
#include "bio_local.h"
BIO_METHOD *
BIO_meth_new(int type, const char *name)
{
@@ -133,15 +135,13 @@ BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy)(BIO *))
long
(*BIO_meth_get_callback_ctrl(const BIO_METHOD *biom))(BIO *, int, BIO_info_cb *)
{
return
(long (*)(BIO *, int, BIO_info_cb *))biom->callback_ctrl; /* XXX */
return biom->callback_ctrl;
}
int
BIO_meth_set_callback_ctrl(BIO_METHOD *biom,
long (*callback_ctrl)(BIO *, int, BIO_info_cb *))
{
biom->callback_ctrl =
(long (*)(BIO *, int, bio_info_cb *))callback_ctrl; /* XXX */
biom->callback_ctrl = callback_ctrl;
return 1;
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bss_acpt.c,v 1.29 2018/05/12 18:51:59 tb Exp $ */
/* $OpenBSD: bss_acpt.c,v 1.30 2022/01/07 09:02:17 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -67,6 +67,8 @@
#include <openssl/buffer.h>
#include <openssl/err.h>
#include "bio_local.h"
#define SOCKET_PROTOCOL IPPROTO_TCP
typedef struct bio_accept_st {

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bss_bio.c,v 1.24 2018/05/01 13:29:09 tb Exp $ */
/* $OpenBSD: bss_bio.c,v 1.25 2022/01/07 09:02:17 tb Exp $ */
/* ====================================================================
* Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
*
@@ -84,6 +84,8 @@
#include <openssl/err.h>
#include <openssl/crypto.h>
#include "bio_local.h"
static int bio_new(BIO *bio);
static int bio_free(BIO *bio);
static int bio_read(BIO *bio, char *buf, int size);

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bss_conn.c,v 1.35 2018/05/12 18:51:59 tb Exp $ */
/* $OpenBSD: bss_conn.c,v 1.37 2022/01/14 08:40:57 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -70,6 +70,8 @@
#include <openssl/buffer.h>
#include <openssl/err.h>
#include "bio_local.h"
#define SOCKET_PROTOCOL IPPROTO_TCP
typedef struct bio_connect_st {
@@ -90,7 +92,7 @@ typedef struct bio_connect_st {
/* called when the connection is initially made
* callback(BIO,state,ret); The callback should return
* 'ret'. state is for compatibility with the ssl info_callback */
int (*info_callback)(const BIO *bio, int state, int ret);
BIO_info_cb *info_callback;
} BIO_CONNECT;
static int conn_write(BIO *h, const char *buf, int num);
@@ -99,7 +101,7 @@ static int conn_puts(BIO *h, const char *str);
static long conn_ctrl(BIO *h, int cmd, long arg1, void *arg2);
static int conn_new(BIO *h);
static int conn_free(BIO *data);
static long conn_callback_ctrl(BIO *h, int cmd, bio_info_cb *);
static long conn_callback_ctrl(BIO *h, int cmd, BIO_info_cb *);
static int conn_state(BIO *b, BIO_CONNECT *c);
static void conn_close_socket(BIO *data);
@@ -124,7 +126,7 @@ conn_state(BIO *b, BIO_CONNECT *c)
int ret = -1, i;
unsigned long l;
char *p, *q;
int (*cb)(const BIO *, int, int) = NULL;
BIO_info_cb *cb = NULL;
if (c->info_callback != NULL)
cb = c->info_callback;
@@ -521,9 +523,7 @@ conn_ctrl(BIO *b, int cmd, long num, void *ptr)
BIO_set_conn_hostname(dbio,
data->param_hostname);
BIO_set_nbio(dbio, data->nbio);
/* FIXME: the cast of the function seems unlikely to be a good idea */
(void)BIO_set_info_callback(dbio,
(bio_info_cb *)data->info_callback);
(void)BIO_set_info_callback(dbio, data->info_callback);
}
break;
case BIO_CTRL_SET_CALLBACK:
@@ -538,9 +538,8 @@ conn_ctrl(BIO *b, int cmd, long num, void *ptr)
break;
case BIO_CTRL_GET_CALLBACK:
{
int (**fptr)(const BIO *bio, int state, int xret);
BIO_info_cb **fptr = ptr;
fptr = (int (**)(const BIO *bio, int state, int xret))ptr;
*fptr = data->info_callback;
}
break;
@@ -552,7 +551,7 @@ conn_ctrl(BIO *b, int cmd, long num, void *ptr)
}
static long
conn_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
conn_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
{
long ret = 1;
BIO_CONNECT *data;
@@ -561,9 +560,7 @@ conn_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
switch (cmd) {
case BIO_CTRL_SET_CALLBACK:
{
data->info_callback = (int (*)(const struct bio_st *, int, int))fp;
}
data->info_callback = (BIO_info_cb *)fp;
break;
default:
ret = 0;

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bss_dgram.c,v 1.42 2018/05/12 17:47:53 tb Exp $ */
/* $OpenBSD: bss_dgram.c,v 1.43 2022/01/07 09:02:17 tb Exp $ */
/*
* DTLS implementation written by Nagendra Modadugu
* (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
@@ -72,6 +72,8 @@
#include <openssl/bio.h>
#include "bio_local.h"
#ifndef OPENSSL_NO_DGRAM

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bss_fd.c,v 1.19 2018/05/01 13:29:09 tb Exp $ */
/* $OpenBSD: bss_fd.c,v 1.20 2022/01/07 09:02:17 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -65,6 +65,8 @@
#include <openssl/bio.h>
#include "bio_local.h"
static int fd_write(BIO *h, const char *buf, int num);
static int fd_read(BIO *h, char *buf, int size);
static int fd_puts(BIO *h, const char *str);

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bss_file.c,v 1.33 2018/05/30 00:23:04 tb Exp $ */
/* $OpenBSD: bss_file.c,v 1.34 2022/01/07 09:02:17 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -90,6 +90,8 @@
#include <openssl/bio.h>
#include <openssl/err.h>
#include "bio_local.h"
static int file_write(BIO *h, const char *buf, int num);
static int file_read(BIO *h, char *buf, int size);
static int file_puts(BIO *h, const char *str);

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bss_log.c,v 1.22 2018/05/01 13:29:10 tb Exp $ */
/* $OpenBSD: bss_log.c,v 1.23 2022/01/07 09:02:17 tb Exp $ */
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
*
@@ -70,6 +70,8 @@
#include <openssl/buffer.h>
#include <openssl/err.h>
#include "bio_local.h"
#ifndef NO_SYSLOG
static int slg_write(BIO *h, const char *buf, int num);

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bss_mem.c,v 1.17 2018/05/12 18:51:59 tb Exp $ */
/* $OpenBSD: bss_mem.c,v 1.21 2022/02/19 15:59:12 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -57,6 +57,7 @@
*/
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
@@ -64,13 +65,35 @@
#include <openssl/err.h>
#include <openssl/buffer.h>
static int mem_write(BIO *h, const char *buf, int num);
static int mem_read(BIO *h, char *buf, int size);
static int mem_puts(BIO *h, const char *str);
static int mem_gets(BIO *h, char *str, int size);
static long mem_ctrl(BIO *h, int cmd, long arg1, void *arg2);
static int mem_new(BIO *h);
static int mem_free(BIO *data);
#include "bio_local.h"
struct bio_mem {
BUF_MEM *buf;
size_t read_offset;
};
static size_t
bio_mem_pending(struct bio_mem *bm)
{
if (bm->read_offset > bm->buf->length)
return 0;
return bm->buf->length - bm->read_offset;
}
static uint8_t *
bio_mem_read_ptr(struct bio_mem *bm)
{
return &bm->buf->data[bm->read_offset];
}
static int mem_new(BIO *bio);
static int mem_free(BIO *bio);
static int mem_write(BIO *bio, const char *in, int in_len);
static int mem_read(BIO *bio, char *out, int out_len);
static int mem_puts(BIO *bio, const char *in);
static int mem_gets(BIO *bio, char *out, int out_len);
static long mem_ctrl(BIO *bio, int cmd, long arg1, void *arg2);
static const BIO_METHOD mem_method = {
.type = BIO_TYPE_MEM,
@@ -84,181 +107,207 @@ static const BIO_METHOD mem_method = {
.destroy = mem_free
};
/* bio->num is used to hold the value to return on 'empty', if it is
* 0, should_retry is not set */
/*
* bio->num is used to hold the value to return on 'empty', if it is
* 0, should_retry is not set.
*/
const BIO_METHOD *
BIO_s_mem(void)
{
return (&mem_method);
return &mem_method;
}
BIO *
BIO_new_mem_buf(const void *buf, int len)
BIO_new_mem_buf(const void *buf, int buf_len)
{
BIO *ret;
BUF_MEM *b;
size_t sz;
struct bio_mem *bm;
BIO *bio;
if (!buf) {
if (buf == NULL) {
BIOerror(BIO_R_NULL_PARAMETER);
return NULL;
}
sz = (len < 0) ? strlen(buf) : (size_t)len;
if (!(ret = BIO_new(BIO_s_mem())))
if (buf_len == -1)
buf_len = strlen(buf);
if (buf_len < 0) {
BIOerror(BIO_R_INVALID_ARGUMENT);
return NULL;
b = (BUF_MEM *)ret->ptr;
b->data = (void *)buf; /* Trust in the BIO_FLAGS_MEM_RDONLY flag. */
b->length = sz;
b->max = sz;
ret->flags |= BIO_FLAGS_MEM_RDONLY;
/* Since this is static data retrying wont help */
ret->num = 0;
return ret;
}
static int
mem_new(BIO *bi)
{
BUF_MEM *b;
if ((b = BUF_MEM_new()) == NULL)
return (0);
bi->shutdown = 1;
bi->init = 1;
bi->num = -1;
bi->ptr = (char *)b;
return (1);
}
static int
mem_free(BIO *a)
{
if (a == NULL)
return (0);
if (a->shutdown) {
if ((a->init) && (a->ptr != NULL)) {
BUF_MEM *b;
b = (BUF_MEM *)a->ptr;
if (a->flags & BIO_FLAGS_MEM_RDONLY)
b->data = NULL;
BUF_MEM_free(b);
a->ptr = NULL;
}
}
return (1);
}
static int
mem_read(BIO *b, char *out, int outl)
{
int ret = -1;
BUF_MEM *bm;
bm = (BUF_MEM *)b->ptr;
BIO_clear_retry_flags(b);
ret = (outl >=0 && (size_t)outl > bm->length) ? (int)bm->length : outl;
if ((out != NULL) && (ret > 0)) {
memcpy(out, bm->data, ret);
bm->length -= ret;
if (b->flags & BIO_FLAGS_MEM_RDONLY)
bm->data += ret;
else {
memmove(&(bm->data[0]), &(bm->data[ret]), bm->length);
}
} else if (bm->length == 0) {
ret = b->num;
if (ret != 0)
BIO_set_retry_read(b);
}
return (ret);
}
static int
mem_write(BIO *b, const char *in, int inl)
{
int ret = -1;
int blen;
BUF_MEM *bm;
bm = (BUF_MEM *)b->ptr;
if (in == NULL) {
BIOerror(BIO_R_NULL_PARAMETER);
goto end;
}
if (b->flags & BIO_FLAGS_MEM_RDONLY) {
if ((bio = BIO_new(BIO_s_mem())) == NULL)
return NULL;
bm = bio->ptr;
bm->buf->data = (void *)buf; /* Trust in the BIO_FLAGS_MEM_RDONLY flag. */
bm->buf->length = buf_len;
bm->buf->max = buf_len;
bio->flags |= BIO_FLAGS_MEM_RDONLY;
/* Since this is static data retrying will not help. */
bio->num = 0;
return bio;
}
static int
mem_new(BIO *bio)
{
struct bio_mem *bm;
if ((bm = calloc(1, sizeof(*bm))) == NULL)
return 0;
if ((bm->buf = BUF_MEM_new()) == NULL) {
free(bm);
return 0;
}
bio->shutdown = 1;
bio->init = 1;
bio->num = -1;
bio->ptr = bm;
return 1;
}
static int
mem_free(BIO *bio)
{
struct bio_mem *bm;
if (bio == NULL)
return 0;
if (!bio->init || bio->ptr == NULL)
return 1;
bm = bio->ptr;
if (bio->shutdown) {
if (bio->flags & BIO_FLAGS_MEM_RDONLY)
bm->buf->data = NULL;
BUF_MEM_free(bm->buf);
}
free(bm);
bio->ptr = NULL;
return 1;
}
static int
mem_read(BIO *bio, char *out, int out_len)
{
struct bio_mem *bm = bio->ptr;
BIO_clear_retry_flags(bio);
if (out == NULL || out_len <= 0)
return 0;
if ((size_t)out_len > bio_mem_pending(bm))
out_len = bio_mem_pending(bm);
if (out_len == 0) {
if (bio->num != 0)
BIO_set_retry_read(bio);
return bio->num;
}
memcpy(out, bio_mem_read_ptr(bm), out_len);
bm->read_offset += out_len;
return out_len;
}
static int
mem_write(BIO *bio, const char *in, int in_len)
{
struct bio_mem *bm = bio->ptr;
size_t buf_len;
BIO_clear_retry_flags(bio);
if (in == NULL || in_len <= 0)
return 0;
if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
BIOerror(BIO_R_WRITE_TO_READ_ONLY_BIO);
goto end;
return -1;
}
BIO_clear_retry_flags(b);
blen = bm->length;
if (BUF_MEM_grow_clean(bm, blen + inl) != (blen + inl))
goto end;
memcpy(&(bm->data[blen]), in, inl);
ret = inl;
end:
return (ret);
if (bm->read_offset > 4096) {
memmove(bm->buf->data, bio_mem_read_ptr(bm),
bio_mem_pending(bm));
bm->buf->length = bio_mem_pending(bm);
bm->read_offset = 0;
}
/*
* Check for overflow and ensure we do not exceed an int, otherwise we
* cannot tell if BUF_MEM_grow_clean() succeeded.
*/
buf_len = bm->buf->length + in_len;
if (buf_len < bm->buf->length || buf_len > INT_MAX)
return -1;
if (BUF_MEM_grow_clean(bm->buf, buf_len) != buf_len)
return -1;
memcpy(&bm->buf->data[buf_len - in_len], in, in_len);
return in_len;
}
static long
mem_ctrl(BIO *b, int cmd, long num, void *ptr)
mem_ctrl(BIO *bio, int cmd, long num, void *ptr)
{
struct bio_mem *bm = bio->ptr;
void **pptr;
long ret = 1;
char **pptr;
BUF_MEM *bm = (BUF_MEM *)b->ptr;
switch (cmd) {
case BIO_CTRL_RESET:
if (bm->data != NULL) {
/* For read only case reset to the start again */
if (b->flags & BIO_FLAGS_MEM_RDONLY) {
bm->data -= bm->max - bm->length;
bm->length = bm->max;
} else {
memset(bm->data, 0, bm->max);
bm->length = 0;
if (bm->buf->data != NULL) {
if (!(bio->flags & BIO_FLAGS_MEM_RDONLY)) {
memset(bm->buf->data, 0, bm->buf->max);
bm->buf->length = 0;
}
bm->read_offset = 0;
}
break;
case BIO_CTRL_EOF:
ret = (long)(bm->length == 0);
ret = (long)(bio_mem_pending(bm) == 0);
break;
case BIO_C_SET_BUF_MEM_EOF_RETURN:
b->num = (int)num;
bio->num = (int)num;
break;
case BIO_CTRL_INFO:
ret = (long)bm->length;
if (ptr != NULL) {
pptr = (char **)ptr;
*pptr = (char *)&(bm->data[0]);
pptr = (void **)ptr;
*pptr = bio_mem_read_ptr(bm);
}
ret = (long)bio_mem_pending(bm);
break;
case BIO_C_SET_BUF_MEM:
mem_free(b);
b->shutdown = (int)num;
b->ptr = ptr;
BUF_MEM_free(bm->buf);
bio->shutdown = (int)num;
bm->buf = ptr;
bm->read_offset = 0;
break;
case BIO_C_GET_BUF_MEM_PTR:
if (ptr != NULL) {
pptr = (char **)ptr;
*pptr = (char *)bm;
pptr = (void **)ptr;
*pptr = bm->buf;
}
break;
case BIO_CTRL_GET_CLOSE:
ret = (long)b->shutdown;
ret = (long)bio->shutdown;
break;
case BIO_CTRL_SET_CLOSE:
b->shutdown = (int)num;
bio->shutdown = (int)num;
break;
case BIO_CTRL_WPENDING:
ret = 0L;
break;
case BIO_CTRL_PENDING:
ret = (long)bm->length;
ret = (long)bio_mem_pending(bm);
break;
case BIO_CTRL_DUP:
case BIO_CTRL_FLUSH:
@@ -270,27 +319,29 @@ mem_ctrl(BIO *b, int cmd, long num, void *ptr)
ret = 0;
break;
}
return (ret);
return ret;
}
static int
mem_gets(BIO *bp, char *buf, int size)
mem_gets(BIO *bio, char *out, int out_len)
{
int i, j;
int ret = -1;
struct bio_mem *bm = bio->ptr;
int i, out_max;
char *p;
BUF_MEM *bm = (BUF_MEM *)bp->ptr;
int ret = -1;
BIO_clear_retry_flags(bp);
j = bm->length;
if ((size - 1) < j)
j = size - 1;
if (j <= 0) {
*buf = '\0';
BIO_clear_retry_flags(bio);
out_max = bio_mem_pending(bm);
if (out_len - 1 < out_max)
out_max = out_len - 1;
if (out_max <= 0) {
*out = '\0';
return 0;
}
p = bm->data;
for (i = 0; i < j; i++) {
p = bio_mem_read_ptr(bm);
for (i = 0; i < out_max; i++) {
if (p[i] == '\n') {
i++;
break;
@@ -298,24 +349,17 @@ mem_gets(BIO *bp, char *buf, int size)
}
/*
* i is now the max num of bytes to copy, either j or up to
* and including the first newline
* i is now the max num of bytes to copy, either out_max or up to and
* including the first newline
*/
if ((ret = mem_read(bio, out, i)) > 0)
out[ret] = '\0';
i = mem_read(bp, buf, i);
if (i > 0)
buf[i] = '\0';
ret = i;
return (ret);
return ret;
}
static int
mem_puts(BIO *bp, const char *str)
mem_puts(BIO *bio, const char *in)
{
int n, ret;
n = strlen(str);
ret = mem_write(bp, str, n);
/* memory semantics is that it will always work */
return (ret);
return mem_write(bio, in, strlen(in));
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bss_null.c,v 1.11 2018/05/01 13:29:10 tb Exp $ */
/* $OpenBSD: bss_null.c,v 1.12 2022/01/07 09:02:17 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -62,6 +62,8 @@
#include <openssl/bio.h>
#include "bio_local.h"
static int null_write(BIO *h, const char *buf, int num);
static int null_read(BIO *h, char *buf, int size);
static int null_puts(BIO *h, const char *str);

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bss_sock.c,v 1.24 2018/05/01 13:29:10 tb Exp $ */
/* $OpenBSD: bss_sock.c,v 1.25 2022/01/07 09:02:17 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -65,6 +65,8 @@
#include <openssl/bio.h>
#include "bio_local.h"
static int sock_write(BIO *h, const char *buf, int num);
static int sock_read(BIO *h, char *buf, int size);
static int sock_puts(BIO *h, const char *str);

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bn_exp2.c,v 1.12 2017/01/29 17:49:22 beck Exp $ */
/* $OpenBSD: bn_exp2.c,v 1.13 2022/02/07 19:49:56 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -136,7 +136,7 @@ BN_mod_exp2_mont(BIGNUM *rr, const BIGNUM *a1, const BIGNUM *p1,
bn_check_top(p2);
bn_check_top(m);
if (!(m->d[0] & 1)) {
if (!BN_is_odd(m)) {
BNerror(BN_R_CALLED_WITH_EVEN_MODULUS);
return (0);
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bn_gcd.c,v 1.15 2017/01/29 17:49:22 beck Exp $ */
/* $OpenBSD: bn_gcd.c,v 1.16 2021/12/26 15:16:50 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -576,6 +576,9 @@ BN_mod_inverse_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n,
bn_check_top(a);
bn_check_top(n);
BN_init(&local_A);
BN_init(&local_B);
BN_CTX_start(ctx);
if ((A = BN_CTX_get(ctx)) == NULL)
goto err;
@@ -608,10 +611,12 @@ BN_mod_inverse_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n,
A->neg = 0;
if (B->neg || (BN_ucmp(B, A) >= 0)) {
/* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
* BN_div_no_branch will be called eventually.
*/
/*
* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
* BN_div_no_branch will be called eventually.
*/
pB = &local_B;
/* BN_init() done at the top of the function. */
BN_with_flags(pB, B, BN_FLG_CONSTTIME);
if (!BN_nnmod(B, pB, A, ctx))
goto err;
@@ -633,10 +638,12 @@ BN_mod_inverse_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n,
* sign*Y*a == A (mod |n|)
*/
/* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
* BN_div_no_branch will be called eventually.
*/
/*
* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
* BN_div_no_branch will be called eventually.
*/
pA = &local_A;
/* BN_init() done at the top of the function. */
BN_with_flags(pA, A, BN_FLG_CONSTTIME);
/* (D, M) := (A/B, A%B) ... */
@@ -740,6 +747,9 @@ BN_gcd_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n,
goto err;
R = in;
BN_init(&local_A);
BN_init(&local_B);
bn_check_top(a);
bn_check_top(n);
@@ -768,10 +778,12 @@ BN_gcd_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n,
A->neg = 0;
if (B->neg || (BN_ucmp(B, A) >= 0)) {
/* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
* BN_div_no_branch will be called eventually.
*/
/*
* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
* BN_div_no_branch will be called eventually.
*/
pB = &local_B;
/* BN_init() done at the top of the function. */
BN_with_flags(pB, B, BN_FLG_CONSTTIME);
if (!BN_nnmod(B, pB, A, ctx))
goto err;
@@ -793,10 +805,12 @@ BN_gcd_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n,
* sign*Y*a == A (mod |n|)
*/
/* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
* BN_div_no_branch will be called eventually.
*/
/*
* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
* BN_div_no_branch will be called eventually.
*/
pA = &local_A;
/* BN_init() done at the top of the function. */
BN_with_flags(pA, A, BN_FLG_CONSTTIME);
/* (D, M) := (A/B, A%B) ... */

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bn_lcl.h,v 1.30 2018/11/05 23:52:47 tb Exp $ */
/* $OpenBSD: bn_lcl.h,v 1.31 2022/01/14 08:01:47 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -118,6 +118,50 @@
__BEGIN_HIDDEN_DECLS
struct bignum_st {
BN_ULONG *d; /* Pointer to an array of 'BN_BITS2' bit chunks. */
int top; /* Index of last used d +1. */
/* The next are internal book keeping for bn_expand. */
int dmax; /* Size of the d array. */
int neg; /* one if the number is negative */
int flags;
};
/* Used for montgomery multiplication */
struct bn_mont_ctx_st {
int ri; /* number of bits in R */
BIGNUM RR; /* used to convert to montgomery form */
BIGNUM N; /* The modulus */
BIGNUM Ni; /* R*(1/R mod N) - N*Ni = 1
* (Ni is only stored for bignum algorithm) */
BN_ULONG n0[2];/* least significant word(s) of Ni;
(type changed with 0.9.9, was "BN_ULONG n0;" before) */
int flags;
};
/* Used for reciprocal division/mod functions
* It cannot be shared between threads
*/
struct bn_recp_ctx_st {
BIGNUM N; /* the divisor */
BIGNUM Nr; /* the reciprocal */
int num_bits;
int shift;
int flags;
};
/* Used for slow "generation" functions. */
struct bn_gencb_st {
unsigned int ver; /* To handle binary (in)compatibility */
void *arg; /* callback-specific data */
union {
/* if(ver==1) - handles old style callbacks */
void (*cb_1)(int, int, void *);
/* if(ver==2) - new callback style */
int (*cb_2)(int, int, BN_GENCB *);
} cb;
};
/*
* BN_window_bits_for_exponent_size -- macro for sliding window mod_exp functions
*

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bn_lib.c,v 1.47 2019/06/17 17:11:48 tb Exp $ */
/* $OpenBSD: bn_lib.c,v 1.53 2021/12/27 15:12:22 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -92,6 +92,63 @@ static int bn_limit_num_high = 8; /* (1<<bn_limit_bits_high) */
static int bn_limit_bits_mont = 0;
static int bn_limit_num_mont = 8; /* (1<<bn_limit_bits_mont) */
BIGNUM *
BN_new(void)
{
BIGNUM *ret;
if ((ret = malloc(sizeof(BIGNUM))) == NULL) {
BNerror(ERR_R_MALLOC_FAILURE);
return (NULL);
}
ret->flags = BN_FLG_MALLOCED;
ret->top = 0;
ret->neg = 0;
ret->dmax = 0;
ret->d = NULL;
bn_check_top(ret);
return (ret);
}
void
BN_init(BIGNUM *a)
{
memset(a, 0, sizeof(BIGNUM));
bn_check_top(a);
}
void
BN_clear(BIGNUM *a)
{
bn_check_top(a);
if (a->d != NULL)
explicit_bzero(a->d, a->dmax * sizeof(a->d[0]));
a->top = 0;
a->neg = 0;
}
void
BN_clear_free(BIGNUM *a)
{
int i;
if (a == NULL)
return;
bn_check_top(a);
if (a->d != NULL && !(BN_get_flags(a, BN_FLG_STATIC_DATA)))
freezero(a->d, a->dmax * sizeof(a->d[0]));
i = BN_get_flags(a, BN_FLG_MALLOCED);
explicit_bzero(a, sizeof(BIGNUM));
if (i)
free(a);
}
void
BN_free(BIGNUM *a)
{
BN_clear_free(a);
}
void
BN_set_params(int mult, int high, int low, int mont)
{
@@ -137,6 +194,30 @@ BN_get_params(int which)
}
#endif
void
BN_set_flags(BIGNUM *b, int n)
{
b->flags |= n;
}
int
BN_get_flags(const BIGNUM *b, int n)
{
return b->flags & n;
}
void
BN_with_flags(BIGNUM *dest, const BIGNUM *b, int flags)
{
int dest_flags;
dest_flags = (dest->flags & BN_FLG_MALLOCED) |
(b->flags & ~BN_FLG_MALLOCED) | BN_FLG_STATIC_DATA | flags;
*dest = *b;
dest->flags = dest_flags;
}
const BIGNUM *
BN_value_one(void)
{
@@ -182,53 +263,6 @@ BN_num_bits(const BIGNUM *a)
return ((i * BN_BITS2) + BN_num_bits_word(a->d[i]));
}
void
BN_clear_free(BIGNUM *a)
{
int i;
if (a == NULL)
return;
bn_check_top(a);
if (a->d != NULL && !(BN_get_flags(a, BN_FLG_STATIC_DATA)))
freezero(a->d, a->dmax * sizeof(a->d[0]));
i = BN_get_flags(a, BN_FLG_MALLOCED);
explicit_bzero(a, sizeof(BIGNUM));
if (i)
free(a);
}
void
BN_free(BIGNUM *a)
{
BN_clear_free(a);
}
void
BN_init(BIGNUM *a)
{
memset(a, 0, sizeof(BIGNUM));
bn_check_top(a);
}
BIGNUM *
BN_new(void)
{
BIGNUM *ret;
if ((ret = malloc(sizeof(BIGNUM))) == NULL) {
BNerror(ERR_R_MALLOC_FAILURE);
return (NULL);
}
ret->flags = BN_FLG_MALLOCED;
ret->top = 0;
ret->neg = 0;
ret->dmax = 0;
ret->d = NULL;
bn_check_top(ret);
return (ret);
}
/* This is used both by bn_expand2() and bn_dup_expand() */
/* The caller MUST check that words > b->dmax before calling this */
static BN_ULONG *
@@ -494,16 +528,6 @@ BN_swap(BIGNUM *a, BIGNUM *b)
bn_check_top(b);
}
void
BN_clear(BIGNUM *a)
{
bn_check_top(a);
if (a->d != NULL)
explicit_bzero(a->d, a->dmax * sizeof(a->d[0]));
a->top = 0;
a->neg = 0;
}
BN_ULONG
BN_get_word(const BIGNUM *a)
{
@@ -583,20 +607,143 @@ BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret)
return (ret);
}
typedef enum {
big,
little,
} endianness_t;
/* ignore negative */
static int
bn2binpad(const BIGNUM *a, unsigned char *to, int tolen, endianness_t endianness)
{
int n;
size_t i, lasti, j, atop, mask;
BN_ULONG l;
/*
* In case |a| is fixed-top, BN_num_bytes can return bogus length,
* but it's assumed that fixed-top inputs ought to be "nominated"
* even for padded output, so it works out...
*/
n = BN_num_bytes(a);
if (tolen == -1)
tolen = n;
else if (tolen < n) { /* uncommon/unlike case */
BIGNUM temp = *a;
bn_correct_top(&temp);
n = BN_num_bytes(&temp);
if (tolen < n)
return -1;
}
/* Swipe through whole available data and don't give away padded zero. */
atop = a->dmax * BN_BYTES;
if (atop == 0) {
explicit_bzero(to, tolen);
return tolen;
}
lasti = atop - 1;
atop = a->top * BN_BYTES;
if (endianness == big)
to += tolen; /* start from the end of the buffer */
for (i = 0, j = 0; j < (size_t)tolen; j++) {
unsigned char val;
l = a->d[i / BN_BYTES];
mask = 0 - ((j - atop) >> (8 * sizeof(i) - 1));
val = (unsigned char)(l >> (8 * (i % BN_BYTES)) & mask);
if (endianness == big)
*--to = val;
else
*to++ = val;
i += (i - lasti) >> (8 * sizeof(i) - 1); /* stay on last limb */
}
return tolen;
}
int
BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen)
{
if (tolen < 0)
return -1;
return bn2binpad(a, to, tolen, big);
}
int
BN_bn2bin(const BIGNUM *a, unsigned char *to)
{
int n, i;
BN_ULONG l;
return bn2binpad(a, to, -1, big);
}
bn_check_top(a);
n = i=BN_num_bytes(a);
while (i--) {
l = a->d[i / BN_BYTES];
*(to++) = (unsigned char)(l >> (8 * (i % BN_BYTES))) & 0xff;
BIGNUM *
BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret)
{
unsigned int i, m, n;
BN_ULONG l;
BIGNUM *bn = NULL;
if (ret == NULL)
ret = bn = BN_new();
if (ret == NULL)
return NULL;
bn_check_top(ret);
s += len;
/* Skip trailing zeroes. */
for (; len > 0 && s[-1] == 0; s--, len--)
continue;
n = len;
if (n == 0) {
ret->top = 0;
return ret;
}
return (n);
i = ((n - 1) / BN_BYTES) + 1;
m = (n - 1) % BN_BYTES;
if (bn_wexpand(ret, (int)i) == NULL) {
BN_free(bn);
return NULL;
}
ret->top = i;
ret->neg = 0;
l = 0;
while (n-- > 0) {
s--;
l = (l << 8L) | *s;
if (m-- == 0) {
ret->d[--i] = l;
l = 0;
m = BN_BYTES - 1;
}
}
/*
* need to call this due to clear byte at top if avoiding having the
* top bit set (-ve number)
*/
bn_correct_top(ret);
return ret;
}
int
BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen)
{
if (tolen < 0)
return -1;
return bn2binpad(a, to, tolen, little);
}
int
@@ -914,6 +1061,50 @@ BN_swap_ct(BN_ULONG condition, BIGNUM *a, BIGNUM *b, size_t nwords)
return 1;
}
void
BN_zero_ex(BIGNUM *a)
{
a->neg = 0;
a->top = 0;
/* XXX: a->flags &= ~BN_FIXED_TOP */
}
int
BN_abs_is_word(const BIGNUM *a, const BN_ULONG w)
{
return (a->top == 1 && a->d[0] == w) || (w == 0 && a->top == 0);
}
int
BN_is_zero(const BIGNUM *a)
{
return a->top == 0;
}
int
BN_is_one(const BIGNUM *a)
{
return BN_abs_is_word(a, 1) && !a->neg;
}
int
BN_is_word(const BIGNUM *a, const BN_ULONG w)
{
return BN_abs_is_word(a, w) && (w == 0 || !a->neg);
}
int
BN_is_odd(const BIGNUM *a)
{
return a->top > 0 && (a->d[0] & 1);
}
int
BN_is_negative(const BIGNUM *a)
{
return a->neg != 0;
}
BN_GENCB *
BN_GENCB_new(void)
{
@@ -933,6 +1124,24 @@ BN_GENCB_free(BN_GENCB *cb)
free(cb);
}
/* Populate a BN_GENCB structure with an "old"-style callback */
void
BN_GENCB_set_old(BN_GENCB *gencb, void (*cb)(int, int, void *), void *cb_arg)
{
gencb->ver = 1;
gencb->cb.cb_1 = cb;
gencb->arg = cb_arg;
}
/* Populate a BN_GENCB structure with a "new"-style callback */
void
BN_GENCB_set(BN_GENCB *gencb, int (*cb)(int, int, BN_GENCB *), void *cb_arg)
{
gencb->ver = 2;
gencb->cb.cb_2 = cb;
gencb->arg = cb_arg;
}
void *
BN_GENCB_get_arg(BN_GENCB *cb)
{

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bn_mont.c,v 1.26 2017/01/21 11:00:46 beck Exp $ */
/* $OpenBSD: bn_mont.c,v 1.28 2022/02/07 19:44:23 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -175,6 +175,12 @@ err:
return (ret);
}
int
BN_to_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont, BN_CTX *ctx)
{
return BN_mod_mul_montgomery(r, a, &mont->RR, mont, ctx);
}
#ifdef MONT_WORD
static int
BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
@@ -363,6 +369,9 @@ BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
int ret = 0;
BIGNUM *Ri, *R;
if (BN_is_zero(mod))
return 0;
BN_CTX_start(ctx);
if ((Ri = BN_CTX_get(ctx)) == NULL)
goto err;

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bn_nist.c,v 1.18 2016/07/18 01:04:52 bcook Exp $ */
/* $OpenBSD: bn_nist.c,v 1.19 2021/11/09 18:40:20 bcook Exp $ */
/*
* Written by Nils Larsch for the OpenSSL project
*/
@@ -56,8 +56,7 @@
*
*/
#include <machine/endian.h>
#include <endian.h>
#include <stdint.h>
#include <string.h>

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bn_print.c,v 1.31 2017/01/29 17:49:22 beck Exp $ */
/* $OpenBSD: bn_print.c,v 1.33 2022/01/20 10:53:33 inoguchi Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -216,7 +216,7 @@ BN_hex2bn(BIGNUM **bn, const char *a)
if ((ret = BN_new()) == NULL)
return (0);
} else {
ret= *bn;
ret = *bn;
BN_zero(ret);
}
@@ -228,7 +228,7 @@ BN_hex2bn(BIGNUM **bn, const char *a)
m = 0;
h = 0;
while (j > 0) {
m = ((BN_BYTES*2) <= j) ? (BN_BYTES * 2) : j;
m = ((BN_BYTES * 2) <= j) ? (BN_BYTES * 2) : j;
l = 0;
for (;;) {
c = a[j - m];
@@ -310,8 +310,10 @@ BN_dec2bn(BIGNUM **bn, const char *a)
l += *a - '0';
a++;
if (++j == BN_DEC_NUM) {
BN_mul_word(ret, BN_DEC_CONV);
BN_add_word(ret, l);
if (!BN_mul_word(ret, BN_DEC_CONV))
goto err;
if (!BN_add_word(ret, l))
goto err;
l = 0;
j = 0;
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bn_rand.c,v 1.24 2020/09/12 17:16:36 tb Exp $ */
/* $OpenBSD: bn_rand.c,v 1.25 2021/08/31 11:19:19 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -194,20 +194,20 @@ err:
return (ret);
}
int
int
BN_rand(BIGNUM *rnd, int bits, int top, int bottom)
{
return bnrand(0, rnd, bits, top, bottom);
}
int
int
BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom)
{
return bnrand(1, rnd, bits, top, bottom);
}
#if 1
int
int
BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom)
{
return bnrand(2, rnd, bits, top, bottom);

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bn_sqrt.c,v 1.9 2017/01/29 17:49:22 beck Exp $ */
/* $OpenBSD: bn_sqrt.c,v 1.10 2022/03/15 15:52:39 tb Exp $ */
/* Written by Lenka Fibikova <fibikova@exp-math.uni-essen.de>
* and Bodo Moeller for the OpenSSL project. */
/* ====================================================================
@@ -351,21 +351,22 @@ BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
goto vrfy;
}
/* find smallest i such that b^(2^i) = 1 */
i = 1;
if (!BN_mod_sqr(t, b, p, ctx))
goto end;
while (!BN_is_one(t)) {
i++;
if (i == e) {
BNerror(BN_R_NOT_A_SQUARE);
goto end;
/* Find the smallest i with 0 < i < e such that b^(2^i) = 1. */
for (i = 1; i < e; i++) {
if (i == 1) {
if (!BN_mod_sqr(t, b, p, ctx))
goto end;
} else {
if (!BN_mod_sqr(t, t, p, ctx))
goto end;
}
if (!BN_mod_mul(t, t, t, p, ctx))
goto end;
if (BN_is_one(t))
break;
}
if (i >= e) {
BNerror(BN_R_NOT_A_SQUARE);
goto end;
}
/* t := y^2^(e - i - 1) */
if (!BN_copy(t, y))

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: bn_x931p.c,v 1.11 2019/01/20 01:56:59 tb Exp $ */
/* $OpenBSD: bn_x931p.c,v 1.13 2022/01/20 10:56:22 inoguchi Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2005.
*/
@@ -139,13 +139,13 @@ BN_X931_derive_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2, const BIGNUM *Xp,
/* First set p to value of Rp */
if (!BN_mod_inverse_ct(p, p2, p1, ctx))
if (BN_mod_inverse_ct(p, p2, p1, ctx) == NULL)
goto err;
if (!BN_mul(p, p, p2, ctx))
goto err;
if (!BN_mod_inverse_ct(t, p1, p2, ctx))
if (BN_mod_inverse_ct(t, p1, p2, ctx) == NULL)
goto err;
if (!BN_mul(t, t, p1, ctx))
@@ -154,7 +154,7 @@ BN_X931_derive_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2, const BIGNUM *Xp,
if (!BN_sub(p, p, t))
goto err;
if (p->neg && !BN_add(p, p, p1p2))
if (BN_is_negative(p) && !BN_add(p, p, p1p2))
goto err;
/* p now equals Rp */
@@ -237,7 +237,8 @@ BN_X931_generate_Xpq(BIGNUM *Xp, BIGNUM *Xq, int nbits, BN_CTX *ctx)
if (!BN_rand(Xq, nbits, 1, 0))
goto err;
/* Check that |Xp - Xq| > 2^(nbits - 100) */
BN_sub(t, Xp, Xq);
if (!BN_sub(t, Xp, Xq))
goto err;
if (BN_num_bits(t) > (nbits - 100))
break;
}

View File

@@ -1,7 +1,7 @@
; 1 "crypto/bn/gf2m-masm-x86_64.S.tmp"
; 1 "<built-in>" 1
; 1 "<built-in>" 3
; 340 "<built-in>" 3
; 343 "<built-in>" 3
; 1 "<command line>" 1
; 1 "<built-in>" 2
; 1 "crypto/bn/gf2m-masm-x86_64.S.tmp" 2

View File

@@ -1,7 +1,7 @@
; 1 "crypto/bn/modexp512-masm-x86_64.S.tmp"
; 1 "<built-in>" 1
; 1 "<built-in>" 3
; 340 "<built-in>" 3
; 343 "<built-in>" 3
; 1 "<command line>" 1
; 1 "<built-in>" 2
; 1 "crypto/bn/modexp512-masm-x86_64.S.tmp" 2

View File

@@ -1,7 +1,7 @@
; 1 "crypto/bn/mont-masm-x86_64.S.tmp"
; 1 "<built-in>" 1
; 1 "<built-in>" 3
; 340 "<built-in>" 3
; 343 "<built-in>" 3
; 1 "<command line>" 1
; 1 "<built-in>" 2
; 1 "crypto/bn/mont-masm-x86_64.S.tmp" 2

View File

@@ -1,7 +1,7 @@
; 1 "crypto/bn/mont5-masm-x86_64.S.tmp"
; 1 "<built-in>" 1
; 1 "<built-in>" 3
; 340 "<built-in>" 3
; 343 "<built-in>" 3
; 1 "<command line>" 1
; 1 "<built-in>" 2
; 1 "crypto/bn/mont5-masm-x86_64.S.tmp" 2

269
externals/libressl/crypto/bytestring/bs_ber.c vendored Executable file
View File

@@ -0,0 +1,269 @@
/* $OpenBSD: bs_ber.c,v 1.2 2021/12/15 18:02:39 jsing Exp $ */
/*
* Copyright (c) 2014, Google Inc.
*
* 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.
*/
#include <string.h>
#include "bytestring.h"
/*
* kMaxDepth is a just a sanity limit. The code should be such that the length
* of the input being processes always decreases. None the less, a very large
* input could otherwise cause the stack to overflow.
*/
static const unsigned int kMaxDepth = 2048;
/* Non-strict version that allows a relaxed DER with indefinite form. */
static int
cbs_nonstrict_get_any_asn1_element(CBS *cbs, CBS *out, unsigned int *out_tag,
size_t *out_header_len)
{
return cbs_get_any_asn1_element_internal(cbs, out,
out_tag, out_header_len, 0);
}
/*
* cbs_find_indefinite walks an ASN.1 structure in |orig_in| and sets
* |*indefinite_found| depending on whether an indefinite length element was
* found. The value of |orig_in| is not modified.
*
* Returns one on success (i.e. |*indefinite_found| was set) and zero on error.
*/
static int
cbs_find_indefinite(const CBS *orig_in, char *indefinite_found,
unsigned int depth)
{
CBS in;
if (depth > kMaxDepth)
return 0;
CBS_init(&in, CBS_data(orig_in), CBS_len(orig_in));
while (CBS_len(&in) > 0) {
CBS contents;
unsigned int tag;
size_t header_len;
if (!cbs_nonstrict_get_any_asn1_element(&in, &contents, &tag,
&header_len))
return 0;
/* Indefinite form not allowed by DER. */
if (CBS_len(&contents) == header_len && header_len > 0 &&
CBS_data(&contents)[header_len - 1] == 0x80) {
*indefinite_found = 1;
return 1;
}
if (tag & CBS_ASN1_CONSTRUCTED) {
if (!CBS_skip(&contents, header_len) ||
!cbs_find_indefinite(&contents, indefinite_found,
depth + 1))
return 0;
}
}
*indefinite_found = 0;
return 1;
}
/*
* is_primitive_type returns true if |tag| likely a primitive type. Normally
* one can just test the "constructed" bit in the tag but, in BER, even
* primitive tags can have the constructed bit if they have indefinite
* length.
*/
static char
is_primitive_type(unsigned int tag)
{
return (tag & 0xc0) == 0 &&
(tag & 0x1f) != (CBS_ASN1_SEQUENCE & 0x1f) &&
(tag & 0x1f) != (CBS_ASN1_SET & 0x1f);
}
/*
* is_eoc returns true if |header_len| and |contents|, as returned by
* |cbs_nonstrict_get_any_asn1_element|, indicate an "end of contents" (EOC)
* value.
*/
static char
is_eoc(size_t header_len, CBS *contents)
{
const unsigned char eoc[] = {0x0, 0x0};
return header_len == 2 && CBS_mem_equal(contents, eoc, 2);
}
/*
* cbs_convert_indefinite reads data with DER encoding (but relaxed to allow
* indefinite form) from |in| and writes definite form DER data to |out|. If
* |squash_header| is set then the top-level of elements from |in| will not
* have their headers written. This is used when concatenating the fragments of
* an indefinite length, primitive value. If |looking_for_eoc| is set then any
* EOC elements found will cause the function to return after consuming it.
* It returns one on success and zero on error.
*/
static int
cbs_convert_indefinite(CBS *in, CBB *out, char squash_header,
char looking_for_eoc, unsigned int depth)
{
if (depth > kMaxDepth)
return 0;
while (CBS_len(in) > 0) {
CBS contents;
unsigned int tag;
size_t header_len;
CBB *out_contents, out_contents_storage;
if (!cbs_nonstrict_get_any_asn1_element(in, &contents, &tag,
&header_len))
return 0;
out_contents = out;
if (CBS_len(&contents) == header_len) {
if (is_eoc(header_len, &contents))
return looking_for_eoc;
if (header_len > 0 &&
CBS_data(&contents)[header_len - 1] == 0x80) {
/*
* This is an indefinite length element. If
* it's a SEQUENCE or SET then we just need to
* write the out the contents as normal, but
* with a concrete length prefix.
*
* If it's a something else then the contents
* will be a series of DER elements of the same
* type which need to be concatenated.
*/
const char context_specific = (tag & 0xc0)
== 0x80;
char squash_child_headers =
is_primitive_type(tag);
/*
* This is a hack, but it sufficies to handle
* NSS's output. If we find an indefinite
* length, context-specific tag with a definite,
* primtive tag inside it, then we assume that
* the context-specific tag is implicit and the
* tags within are fragments of a primitive type
* that need to be concatenated.
*/
if (context_specific &&
(tag & CBS_ASN1_CONSTRUCTED)) {
CBS in_copy, inner_contents;
unsigned int inner_tag;
size_t inner_header_len;
CBS_init(&in_copy, CBS_data(in),
CBS_len(in));
if (!cbs_nonstrict_get_any_asn1_element(
&in_copy, &inner_contents,
&inner_tag, &inner_header_len))
return 0;
if (CBS_len(&inner_contents) >
inner_header_len &&
is_primitive_type(inner_tag))
squash_child_headers = 1;
}
if (!squash_header) {
unsigned int out_tag = tag;
if (squash_child_headers)
out_tag &=
~CBS_ASN1_CONSTRUCTED;
if (!CBB_add_asn1(out,
&out_contents_storage, out_tag))
return 0;
out_contents = &out_contents_storage;
}
if (!cbs_convert_indefinite(in, out_contents,
squash_child_headers,
1 /* looking for eoc */, depth + 1))
return 0;
if (out_contents != out && !CBB_flush(out))
return 0;
continue;
}
}
if (!squash_header) {
if (!CBB_add_asn1(out, &out_contents_storage, tag))
return 0;
out_contents = &out_contents_storage;
}
if (!CBS_skip(&contents, header_len))
return 0;
if (tag & CBS_ASN1_CONSTRUCTED) {
if (!cbs_convert_indefinite(&contents, out_contents,
0 /* don't squash header */,
0 /* not looking for eoc */, depth + 1))
return 0;
} else {
if (!CBB_add_bytes(out_contents, CBS_data(&contents),
CBS_len(&contents)))
return 0;
}
if (out_contents != out && !CBB_flush(out))
return 0;
}
return looking_for_eoc == 0;
}
int
CBS_asn1_indefinite_to_definite(CBS *in, uint8_t **out, size_t *out_len)
{
CBB cbb;
/*
* First, do a quick walk to find any indefinite-length elements. Most
* of the time we hope that there aren't any and thus we can quickly
* return.
*/
char conversion_needed;
if (!cbs_find_indefinite(in, &conversion_needed, 0))
return 0;
if (!conversion_needed) {
*out = NULL;
*out_len = 0;
return 1;
}
if (!CBB_init(&cbb, CBS_len(in)))
return 0;
if (!cbs_convert_indefinite(in, &cbb, 0, 0, 0)) {
CBB_cleanup(&cbb);
return 0;
}
return CBB_finish(&cbb, out, out_len);
}

480
externals/libressl/crypto/bytestring/bs_cbb.c vendored Executable file
View File

@@ -0,0 +1,480 @@
/* $OpenBSD: bs_cbb.c,v 1.3 2022/01/06 14:32:55 jsing Exp $ */
/*
* Copyright (c) 2014, Google Inc.
*
* 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.
*/
#include <stdlib.h>
#include <string.h>
#include "bytestring.h"
#define CBB_INITIAL_SIZE 64
static int
cbb_init(CBB *cbb, uint8_t *buf, size_t cap)
{
struct cbb_buffer_st *base;
if ((base = calloc(1, sizeof(struct cbb_buffer_st))) == NULL)
return 0;
base->buf = buf;
base->len = 0;
base->cap = cap;
base->can_resize = 1;
cbb->base = base;
cbb->is_top_level = 1;
return 1;
}
int
CBB_init(CBB *cbb, size_t initial_capacity)
{
uint8_t *buf = NULL;
memset(cbb, 0, sizeof(*cbb));
if (initial_capacity == 0)
initial_capacity = CBB_INITIAL_SIZE;
if ((buf = calloc(1, initial_capacity)) == NULL)
return 0;
if (!cbb_init(cbb, buf, initial_capacity)) {
free(buf);
return 0;
}
return 1;
}
int
CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len)
{
memset(cbb, 0, sizeof(*cbb));
if (!cbb_init(cbb, buf, len))
return 0;
cbb->base->can_resize = 0;
return 1;
}
void
CBB_cleanup(CBB *cbb)
{
if (cbb->base) {
if (cbb->base->can_resize)
freezero(cbb->base->buf, cbb->base->cap);
free(cbb->base);
}
cbb->base = NULL;
cbb->child = NULL;
}
static int
cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out, size_t len)
{
size_t newlen;
if (base == NULL)
return 0;
newlen = base->len + len;
if (newlen < base->len)
/* Overflow */
return 0;
if (newlen > base->cap) {
size_t newcap = base->cap * 2;
uint8_t *newbuf;
if (!base->can_resize)
return 0;
if (newcap < base->cap || newcap < newlen)
newcap = newlen;
newbuf = recallocarray(base->buf, base->cap, newcap, 1);
if (newbuf == NULL)
return 0;
base->buf = newbuf;
base->cap = newcap;
}
if (out)
*out = base->buf + base->len;
base->len = newlen;
return 1;
}
static int
cbb_add_u(CBB *cbb, uint32_t v, size_t len_len)
{
uint8_t *buf;
size_t i;
if (len_len == 0)
return 1;
if (len_len > 4)
return 0;
if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, &buf, len_len))
return 0;
for (i = len_len - 1; i < len_len; i--) {
buf[i] = v;
v >>= 8;
}
return 1;
}
int
CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len)
{
if (!cbb->is_top_level)
return 0;
if (!CBB_flush(cbb))
return 0;
if (cbb->base->can_resize && (out_data == NULL || out_len == NULL))
/*
* |out_data| and |out_len| can only be NULL if the CBB is
* fixed.
*/
return 0;
if (out_data != NULL)
*out_data = cbb->base->buf;
if (out_len != NULL)
*out_len = cbb->base->len;
cbb->base->buf = NULL;
CBB_cleanup(cbb);
return 1;
}
/*
* CBB_flush recurses and then writes out any pending length prefix. The current
* length of the underlying base is taken to be the length of the
* length-prefixed data.
*/
int
CBB_flush(CBB *cbb)
{
size_t child_start, i, len;
if (cbb->base == NULL)
return 0;
if (cbb->child == NULL || cbb->pending_len_len == 0)
return 1;
child_start = cbb->offset + cbb->pending_len_len;
if (!CBB_flush(cbb->child) || child_start < cbb->offset ||
cbb->base->len < child_start)
return 0;
len = cbb->base->len - child_start;
if (cbb->pending_is_asn1) {
/*
* For ASN.1, we assumed that we were using short form which
* only requires a single byte for the length octet.
*
* If it turns out that we need long form, we have to move
* the contents along in order to make space for more length
* octets.
*/
size_t len_len = 1; /* total number of length octets */
uint8_t initial_length_byte;
/* We already wrote 1 byte for the length. */
if (cbb->pending_len_len != 1)
return 0;
/* Check for long form */
if (len > 0xfffffffe)
return 0; /* 0xffffffff is reserved */
else if (len > 0xffffff)
len_len = 5;
else if (len > 0xffff)
len_len = 4;
else if (len > 0xff)
len_len = 3;
else if (len > 0x7f)
len_len = 2;
if (len_len == 1) {
/* For short form, the initial byte is the length. */
initial_length_byte = len;
len = 0;
} else {
/*
* For long form, the initial byte is the number of
* subsequent length octets (plus bit 8 set).
*/
initial_length_byte = 0x80 | (len_len - 1);
/*
* We need to move the contents along in order to make
* space for the long form length octets.
*/
size_t extra_bytes = len_len - 1;
if (!cbb_buffer_add(cbb->base, NULL, extra_bytes))
return 0;
memmove(cbb->base->buf + child_start + extra_bytes,
cbb->base->buf + child_start, len);
}
cbb->base->buf[cbb->offset++] = initial_length_byte;
cbb->pending_len_len = len_len - 1;
}
for (i = cbb->pending_len_len - 1; i < cbb->pending_len_len; i--) {
cbb->base->buf[cbb->offset + i] = len;
len >>= 8;
}
if (len != 0)
return 0;
cbb->child->base = NULL;
cbb->child = NULL;
cbb->pending_len_len = 0;
cbb->pending_is_asn1 = 0;
cbb->offset = 0;
return 1;
}
void
CBB_discard_child(CBB *cbb)
{
if (cbb->child == NULL)
return;
cbb->base->len = cbb->offset;
cbb->child->base = NULL;
cbb->child = NULL;
cbb->pending_len_len = 0;
cbb->pending_is_asn1 = 0;
cbb->offset = 0;
}
static int
cbb_add_length_prefixed(CBB *cbb, CBB *out_contents, size_t len_len)
{
uint8_t *prefix_bytes;
if (!CBB_flush(cbb))
return 0;
cbb->offset = cbb->base->len;
if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len))
return 0;
memset(prefix_bytes, 0, len_len);
memset(out_contents, 0, sizeof(CBB));
out_contents->base = cbb->base;
cbb->child = out_contents;
cbb->pending_len_len = len_len;
cbb->pending_is_asn1 = 0;
return 1;
}
int
CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents)
{
return cbb_add_length_prefixed(cbb, out_contents, 1);
}
int
CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents)
{
return cbb_add_length_prefixed(cbb, out_contents, 2);
}
int
CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents)
{
return cbb_add_length_prefixed(cbb, out_contents, 3);
}
int
CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned int tag)
{
if (tag > UINT8_MAX)
return 0;
/* Long form identifier octets are not supported. */
if ((tag & 0x1f) == 0x1f)
return 0;
/* Short-form identifier octet only needs a single byte */
if (!CBB_flush(cbb) || !CBB_add_u8(cbb, tag))
return 0;
/*
* Add 1 byte to cover the short-form length octet case. If it turns
* out we need long-form, it will be extended later.
*/
cbb->offset = cbb->base->len;
if (!CBB_add_u8(cbb, 0))
return 0;
memset(out_contents, 0, sizeof(CBB));
out_contents->base = cbb->base;
cbb->child = out_contents;
cbb->pending_len_len = 1;
cbb->pending_is_asn1 = 1;
return 1;
}
int
CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len)
{
uint8_t *dest;
if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, &dest, len))
return 0;
memcpy(dest, data, len);
return 1;
}
int
CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len)
{
if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, out_data, len))
return 0;
memset(*out_data, 0, len);
return 1;
}
int
CBB_add_u8(CBB *cbb, size_t value)
{
if (value > UINT8_MAX)
return 0;
return cbb_add_u(cbb, (uint32_t)value, 1);
}
int
CBB_add_u16(CBB *cbb, size_t value)
{
if (value > UINT16_MAX)
return 0;
return cbb_add_u(cbb, (uint32_t)value, 2);
}
int
CBB_add_u24(CBB *cbb, size_t value)
{
if (value > 0xffffffUL)
return 0;
return cbb_add_u(cbb, (uint32_t)value, 3);
}
int
CBB_add_u32(CBB *cbb, size_t value)
{
if (value > 0xffffffffUL)
return 0;
return cbb_add_u(cbb, (uint32_t)value, 4);
}
int
CBB_add_u64(CBB *cbb, uint64_t value)
{
uint32_t a, b;
a = value >> 32;
b = value & 0xffffffff;
if (!CBB_add_u32(cbb, a))
return 0;
return CBB_add_u32(cbb, b);
}
int
CBB_add_asn1_uint64(CBB *cbb, uint64_t value)
{
CBB child;
size_t i;
int started = 0;
if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER))
return 0;
for (i = 0; i < 8; i++) {
uint8_t byte = (value >> 8 * (7 - i)) & 0xff;
/*
* ASN.1 restriction: first 9 bits cannot be all zeroes or
* all ones. Since this function only encodes unsigned
* integers, the only concerns are not encoding leading
* zeros and adding a padding byte if necessary.
*
* In practice, this means:
* 1) Skip leading octets of all zero bits in the value
* 2) After skipping the leading zero octets, if the next 9
* bits are all ones, add an all zero prefix octet (and
* set the high bit of the prefix octet if negative).
*
* Additionally, for an unsigned value, add an all zero
* prefix if the high bit of the first octet would be one.
*/
if (!started) {
if (byte == 0)
/* Don't encode leading zeros. */
continue;
/*
* If the high bit is set, add a padding byte to make it
* unsigned.
*/
if ((byte & 0x80) && !CBB_add_u8(&child, 0))
return 0;
started = 1;
}
if (!CBB_add_u8(&child, byte))
return 0;
}
/* 0 is encoded as a single 0, not the empty string. */
if (!started && !CBB_add_u8(&child, 0))
return 0;
return CBB_flush(cbb);
}

Some files were not shown because too many files have changed in this diff Show More