external/boringssl: Sync to 2d98d49cf712ca7dc6f4b23b9c5f5542385d8dbe.
This includes the following changes:
https://boringssl.googlesource.com/boringssl/+log/5ede28c8a422801ace3ba5e466ba963005351145..2d98d49cf712ca7dc6f4b23b9c5f5542385d8dbe
Test: BoringSSL CTS Presubmits
Change-Id: I21750d81b070d7e4741e205f5c2ccd8d541b36d1
diff --git a/src/BUILDING.md b/src/BUILDING.md
index ab9b71d..01f5480 100644
--- a/src/BUILDING.md
+++ b/src/BUILDING.md
@@ -128,7 +128,11 @@
`/path/to/symbols.txt`.
It is currently the caller's responsibility to create and maintain the list of
-symbols to be prefixed.
+symbols to be prefixed. Alternatively, `util/read_symbols.go` reads the list of
+exported symbols from a `.a` file, and can be used in a build script to generate
+the symbol list on the fly (by building without prefixing, using
+`read_symbols.go` to construct a symbol list, and then building again with
+prefixing).
This mechanism is under development and may change over time. Please contact the
BoringSSL maintainers if making use of it.
diff --git a/src/crypto/CMakeLists.txt b/src/crypto/CMakeLists.txt
index 78b835c..ee9626a 100644
--- a/src/crypto/CMakeLists.txt
+++ b/src/crypto/CMakeLists.txt
@@ -467,6 +467,7 @@
refcount_test.cc
rsa_extra/rsa_test.cc
self_test.cc
+ stack/stack_test.cc
test/file_test_gtest.cc
thread_test.cc
x509/x509_test.cc
diff --git a/src/crypto/asn1/a_d2i_fp.c b/src/crypto/asn1/a_d2i_fp.c
index 3da6df9..fd423e2 100644
--- a/src/crypto/asn1/a_d2i_fp.c
+++ b/src/crypto/asn1/a_d2i_fp.c
@@ -58,240 +58,36 @@
#include <limits.h>
-#include <openssl/buf.h>
+#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb);
-
-#ifndef NO_OLD_ASN1
-# ifndef OPENSSL_NO_FP_API
-
-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) {
- OPENSSL_PUT_ERROR(ASN1, 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);
-}
-# endif
-
-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);
-}
-
-#endif
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);
+ uint8_t *data;
+ size_t len;
+ // Historically, this function did not impose a limit in OpenSSL and is used
+ // to read CRLs, so we leave this without an external bound.
+ if (!BIO_read_asn1(in, &data, &len, INT_MAX)) {
+ return NULL;
+ }
+ const uint8_t *ptr = data;
+ void *ret = ASN1_item_d2i(x, &ptr, len, it);
+ OPENSSL_free(data);
+ return ret;
}
#ifndef OPENSSL_NO_FP_API
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) {
+ BIO *b = BIO_new_fp(in, BIO_NOCLOSE);
+ if (b == NULL) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
- return (NULL);
+ return NULL;
}
- BIO_set_fp(b, in, BIO_NOCLOSE);
- ret = ASN1_item_d2i_bio(it, b, x);
+ void *ret = ASN1_item_d2i_bio(it, b, x);
BIO_free(b);
- return (ret);
+ return ret;
}
#endif
-
-typedef struct asn1_const_ctx_st
- {
- const unsigned char *p;/* work char pointer */
- int eos; /* end of sequence read for indefinite encoding */
- int error; /* error code to use when returning an error */
- int inf; /* constructed if 0x20, indefinite is 0x21 */
- int tag; /* tag from last 'get object' */
- int xclass; /* class from last 'get object' */
- long slen; /* length of last 'get object' */
- const unsigned char *max; /* largest value of p allowed */
- const unsigned char *q;/* temporary variable */
- const unsigned char **pp;/* variable */
- int line; /* used in error processing */
- } ASN1_const_CTX;
-
-#define HEADER_SIZE 8
-#define ASN1_CHUNK_INITIAL_SIZE (16 * 1024)
-static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
-{
- BUF_MEM *b;
- unsigned char *p;
- int i;
- ASN1_const_CTX c;
- size_t want = HEADER_SIZE;
- int eos = 0;
- size_t off = 0;
- size_t len = 0;
-
- b = BUF_MEM_new();
- if (b == NULL) {
- OPENSSL_PUT_ERROR(ASN1, 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)) {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- i = BIO_read(in, &(b->data[len]), want);
- if ((i < 0) && ((len - off) == 0)) {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
- goto err;
- }
- if (i > 0) {
- if (len + i < len) {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
- goto err;
- }
- len += i;
- }
- }
- /* else data already loaded */
-
- p = (unsigned char *)&(b->data[off]);
- c.p = p;
- c.inf = ASN1_get_object(&(c.p), &(c.slen), &(c.tag), &(c.xclass),
- len - off);
- if (c.inf & 0x80) {
- uint32_t e;
-
- e = ERR_GET_REASON(ERR_peek_error());
- if (e != ASN1_R_TOO_LONG)
- goto err;
- else
- ERR_clear_error(); /* clear error */
- }
- i = c.p - p; /* header length */
- off += i; /* end of data */
-
- if (c.inf & 1) {
- /* no data body so go round again */
- eos++;
- if (eos < 0) {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
- goto err;
- }
- want = HEADER_SIZE;
- } else if (eos && (c.slen == 0) && (c.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 c.slen bytes of data */
- want = c.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) {
- OPENSSL_PUT_ERROR(ASN1, 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)) {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- want -= chunk;
- while (chunk > 0) {
- i = BIO_read(in, &(b->data[len]), chunk);
- if (i <= 0) {
- OPENSSL_PUT_ERROR(ASN1, 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 + c.slen < off) {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
- goto err;
- }
- off += c.slen;
- if (eos <= 0) {
- break;
- } else
- want = HEADER_SIZE;
- }
- }
-
- if (off > INT_MAX) {
- OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
- goto err;
- }
-
- *pb = b;
- return off;
- err:
- if (b != NULL)
- BUF_MEM_free(b);
- return -1;
-}
diff --git a/src/crypto/asn1/a_dup.c b/src/crypto/asn1/a_dup.c
index 57394f5..9ede851 100644
--- a/src/crypto/asn1/a_dup.c
+++ b/src/crypto/asn1/a_dup.c
@@ -59,30 +59,6 @@
#include <openssl/err.h>
#include <openssl/mem.h>
-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 = OPENSSL_malloc(i + 10);
- if (b == NULL) {
- OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- return (NULL);
- }
- p = b;
- i = i2d(x, &p);
- p2 = b;
- ret = d2i(NULL, &p2, i);
- OPENSSL_free(b);
- return (ret);
-}
-
/*
* 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
diff --git a/src/crypto/asn1/a_i2d_fp.c b/src/crypto/asn1/a_i2d_fp.c
index 7b76d0c..db0d812 100644
--- a/src/crypto/asn1/a_i2d_fp.c
+++ b/src/crypto/asn1/a_i2d_fp.c
@@ -56,95 +56,33 @@
#include <openssl/asn1.h>
+#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x)
-{
- BIO *b;
- int ret;
-
- if ((b = BIO_new(BIO_s_file())) == NULL) {
- OPENSSL_PUT_ERROR(ASN1, 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, void *x)
-{
- char *b;
- unsigned char *p;
- int i, j = 0, n, ret = 1;
-
- n = i2d(x, NULL);
- if (n <= 0)
- return 0;
-
- b = (char *)OPENSSL_malloc(n);
- if (b == NULL) {
- OPENSSL_PUT_ERROR(ASN1, 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;
- }
- OPENSSL_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) {
+ BIO *b = BIO_new_fp(out, BIO_NOCLOSE);
+ if (b == NULL) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
- return (0);
+ return 0;
}
- BIO_set_fp(b, out, BIO_NOCLOSE);
- ret = ASN1_item_i2d_bio(it, b, x);
+ int ret = ASN1_item_i2d_bio(it, b, x);
BIO_free(b);
- return (ret);
+ 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);
+ int n = ASN1_item_i2d(x, &b, it);
if (b == NULL) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
- return (0);
+ return 0;
}
- for (;;) {
- i = BIO_write(out, &(b[j]), n);
- if (i == n)
- break;
- if (i <= 0) {
- ret = 0;
- break;
- }
- j += i;
- n -= i;
- }
+ int ret = BIO_write_all(out, b, n);
OPENSSL_free(b);
- return (ret);
+ return ret;
}
diff --git a/src/crypto/bio/bio.c b/src/crypto/bio/bio.c
index 3e788b8..881c14e 100644
--- a/src/crypto/bio/bio.c
+++ b/src/crypto/bio/bio.c
@@ -177,6 +177,19 @@
return ret;
}
+int BIO_write_all(BIO *bio, const void *data, size_t len) {
+ const uint8_t *data_u8 = data;
+ while (len > 0) {
+ int ret = BIO_write(bio, data_u8, len > INT_MAX ? INT_MAX : (int)len);
+ if (ret <= 0) {
+ return 0;
+ }
+ data_u8 += ret;
+ len -= ret;
+ }
+ return 1;
+}
+
int BIO_puts(BIO *bio, const char *in) {
return BIO_write(bio, in, strlen(in));
}
diff --git a/src/crypto/bio/file.c b/src/crypto/bio/file.c
index 6a0b9a9..a177763 100644
--- a/src/crypto/bio/file.c
+++ b/src/crypto/bio/file.c
@@ -107,13 +107,12 @@
return NULL;
}
- ret = BIO_new(BIO_s_file());
+ ret = BIO_new_fp(file, BIO_CLOSE);
if (ret == NULL) {
fclose(file);
return NULL;
}
- BIO_set_fp(ret, file, BIO_CLOSE);
return ret;
}
diff --git a/src/crypto/bn_extra/convert.c b/src/crypto/bn_extra/convert.c
index c70ff8b..9a1a69e 100644
--- a/src/crypto/bn_extra/convert.c
+++ b/src/crypto/bn_extra/convert.c
@@ -367,17 +367,13 @@
}
int BN_print_fp(FILE *fp, const BIGNUM *a) {
- BIO *b;
- int ret;
-
- b = BIO_new(BIO_s_file());
+ BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
if (b == NULL) {
return 0;
}
- BIO_set_fp(b, fp, BIO_NOCLOSE);
- ret = BN_print(b, a);
- BIO_free(b);
+ int ret = BN_print(b, a);
+ BIO_free(b);
return ret;
}
diff --git a/src/crypto/conf/conf.c b/src/crypto/conf/conf.c
index b1982f8..4c27ddf 100644
--- a/src/crypto/conf/conf.c
+++ b/src/crypto/conf/conf.c
@@ -62,6 +62,7 @@
#include <openssl/bio.h>
#include <openssl/buf.h>
#include <openssl/err.h>
+#include <openssl/lhash.h>
#include <openssl/mem.h>
#include "conf_def.h"
@@ -69,6 +70,10 @@
#include "../internal.h"
+struct conf_st {
+ LHASH_OF(CONF_VALUE) *data;
+};
+
// The maximum length we can grow a value to after variable expansion. 64k
// should be more than enough for all reasonable uses.
#define MAX_CONF_VALUE_LENGTH 65536
diff --git a/src/crypto/fipsmodule/CMakeLists.txt b/src/crypto/fipsmodule/CMakeLists.txt
index 9868dd8..e6c8cc6 100644
--- a/src/crypto/fipsmodule/CMakeLists.txt
+++ b/src/crypto/fipsmodule/CMakeLists.txt
@@ -162,12 +162,12 @@
set_target_properties(bcm_hashunset PROPERTIES POSITION_INDEPENDENT_CODE ON)
set_target_properties(bcm_hashunset PROPERTIES LINKER_LANGUAGE C)
- go_executable(inject-hash
- boringssl.googlesource.com/boringssl/util/fipstools/inject-hash)
+ go_executable(inject_hash
+ boringssl.googlesource.com/boringssl/util/fipstools/inject_hash)
add_custom_command(
OUTPUT bcm.o
- COMMAND ./inject-hash -o bcm.o -in-archive $<TARGET_FILE:bcm_hashunset>
- DEPENDS bcm_hashunset inject-hash
+ COMMAND ./inject_hash -o bcm.o -in-archive $<TARGET_FILE:bcm_hashunset>
+ DEPENDS bcm_hashunset inject_hash
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
diff --git a/src/crypto/fipsmodule/FIPS.md b/src/crypto/fipsmodule/FIPS.md
index a691d18..426b38e 100644
--- a/src/crypto/fipsmodule/FIPS.md
+++ b/src/crypto/fipsmodule/FIPS.md
@@ -103,7 +103,7 @@
In order to actually implement the integrity test, a constructor function within the module calculates an HMAC from `module_start` to `module_end` using a fixed, all-zero key. It compares the result with the known-good value added (by the script) to the unhashed portion of the text segment. If they don't match, it calls `exit` in an infinite loop.
-Initially the known-good value will be incorrect. Another script (`inject-hash.go`) calculates the correct value from the assembled object and injects it back into the object.
+Initially the known-good value will be incorrect. Another script (`inject_hash.go`) calculates the correct value from the assembled object and injects it back into the object.
![build process](/crypto/fipsmodule/intcheck2.png)
diff --git a/src/crypto/fipsmodule/aes/mode_wrappers.c b/src/crypto/fipsmodule/aes/mode_wrappers.c
index 5c50c85..0140c70 100644
--- a/src/crypto/fipsmodule/aes/mode_wrappers.c
+++ b/src/crypto/fipsmodule/aes/mode_wrappers.c
@@ -57,8 +57,7 @@
void AES_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
const AES_KEY *key, uint8_t ivec[AES_BLOCK_SIZE],
uint8_t ecount_buf[AES_BLOCK_SIZE], unsigned int *num) {
- CRYPTO_ctr128_encrypt(in, out, len, key, ivec, ecount_buf, num,
- (block128_f)AES_encrypt);
+ CRYPTO_ctr128_encrypt(in, out, len, key, ivec, ecount_buf, num, AES_encrypt);
}
void AES_ecb_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key,
@@ -90,9 +89,9 @@
aes_nohw_cbc_encrypt(in, out, len, key, ivec, enc);
#else
if (enc) {
- CRYPTO_cbc128_encrypt(in, out, len, key, ivec, (block128_f)AES_encrypt);
+ CRYPTO_cbc128_encrypt(in, out, len, key, ivec, AES_encrypt);
} else {
- CRYPTO_cbc128_decrypt(in, out, len, key, ivec, (block128_f)AES_decrypt);
+ CRYPTO_cbc128_decrypt(in, out, len, key, ivec, AES_decrypt);
}
#endif
}
@@ -100,8 +99,7 @@
void AES_ofb128_encrypt(const uint8_t *in, uint8_t *out, size_t length,
const AES_KEY *key, uint8_t *ivec, int *num) {
unsigned num_u = (unsigned)(*num);
- CRYPTO_ofb128_encrypt(in, out, length, key, ivec, &num_u,
- (block128_f)AES_encrypt);
+ CRYPTO_ofb128_encrypt(in, out, length, key, ivec, &num_u, AES_encrypt);
*num = (int)num_u;
}
@@ -109,7 +107,6 @@
const AES_KEY *key, uint8_t *ivec, int *num,
int enc) {
unsigned num_u = (unsigned)(*num);
- CRYPTO_cfb128_encrypt(in, out, length, key, ivec, &num_u, enc,
- (block128_f)AES_encrypt);
+ CRYPTO_cfb128_encrypt(in, out, length, key, ivec, &num_u, enc, AES_encrypt);
*num = (int)num_u;
}
diff --git a/src/crypto/fipsmodule/bcm.c b/src/crypto/fipsmodule/bcm.c
index 6b21f06..e15ecb8 100644
--- a/src/crypto/fipsmodule/bcm.c
+++ b/src/crypto/fipsmodule/bcm.c
@@ -124,6 +124,7 @@
if (!HMAC(EVP_sha512(), kHMACKey, sizeof(kHMACKey), start, end - start,
result, &result_len) ||
result_len != sizeof(result)) {
+ fprintf(stderr, "HMAC failed.\n");
goto err;
}
diff --git a/src/crypto/fipsmodule/bn/div.c b/src/crypto/fipsmodule/bn/div.c
index 57485bd..27b591c 100644
--- a/src/crypto/fipsmodule/bn/div.c
+++ b/src/crypto/fipsmodule/bn/div.c
@@ -64,7 +64,7 @@
#include "internal.h"
-#if !defined(BN_ULLONG)
+#if !defined(BN_CAN_DIVIDE_ULLONG) && !defined(BN_CAN_USE_INLINE_ASM)
// bn_div_words divides a double-width |h|,|l| by |d| and returns the result,
// which must fit in a |BN_ULONG|.
static BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) {
@@ -135,7 +135,7 @@
ret |= q;
return ret;
}
-#endif // !defined(BN_ULLONG)
+#endif // !defined(BN_CAN_DIVIDE_ULLONG) && !defined(BN_CAN_USE_INLINE_ASM)
static inline void bn_div_rem_words(BN_ULONG *quotient_out, BN_ULONG *rem_out,
BN_ULONG n0, BN_ULONG n1, BN_ULONG d0) {
@@ -155,20 +155,18 @@
//
// These issues aren't specific to x86 and x86_64, so it might be worthwhile
// to add more assembly language implementations.
-#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86) && \
- (defined(__GNUC__) || defined(__clang__))
+#if defined(BN_CAN_USE_INLINE_ASM) && defined(OPENSSL_X86)
__asm__ volatile("divl %4"
: "=a"(*quotient_out), "=d"(*rem_out)
: "a"(n1), "d"(n0), "rm"(d0)
: "cc");
-#elif !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \
- (defined(__GNUC__) || defined(__clang__))
+#elif defined(BN_CAN_USE_INLINE_ASM) && defined(OPENSSL_X86_64)
__asm__ volatile("divq %4"
: "=a"(*quotient_out), "=d"(*rem_out)
: "a"(n1), "d"(n0), "rm"(d0)
: "cc");
#else
-#if defined(BN_ULLONG)
+#if defined(BN_CAN_DIVIDE_ULLONG)
BN_ULLONG n = (((BN_ULLONG)n0) << BN_BITS2) | n1;
*quotient_out = (BN_ULONG)(n / d0);
#else
diff --git a/src/crypto/fipsmodule/bn/internal.h b/src/crypto/fipsmodule/bn/internal.h
index 9796831..fb8d11f 100644
--- a/src/crypto/fipsmodule/bn/internal.h
+++ b/src/crypto/fipsmodule/bn/internal.h
@@ -185,6 +185,10 @@
#error "Must define either OPENSSL_32_BIT or OPENSSL_64_BIT"
#endif
+#if !defined(OPENSSL_NO_ASM) && (defined(__GNUC__) || defined(__clang__))
+#define BN_CAN_USE_INLINE_ASM
+#endif
+
// |BN_mod_exp_mont_consttime| is based on the assumption that the L1 data
// cache line width of the target processor is at least the following value.
#define MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH 64
diff --git a/src/crypto/fipsmodule/cipher/e_aes.c b/src/crypto/fipsmodule/cipher/e_aes.c
index 734a517..0ced193 100644
--- a/src/crypto/fipsmodule/cipher/e_aes.c
+++ b/src/crypto/fipsmodule/cipher/e_aes.c
@@ -198,49 +198,45 @@
if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) && !enc) {
if (hwaes_capable()) {
ret = aes_hw_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
- dat->block = (block128_f)aes_hw_decrypt;
+ dat->block = aes_hw_decrypt;
dat->stream.cbc = NULL;
if (mode == EVP_CIPH_CBC_MODE) {
- dat->stream.cbc = (cbc128_f)aes_hw_cbc_encrypt;
+ dat->stream.cbc = aes_hw_cbc_encrypt;
}
} else if (bsaes_capable() && mode == EVP_CIPH_CBC_MODE) {
ret = AES_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
- dat->block = (block128_f)AES_decrypt;
- dat->stream.cbc = (cbc128_f)bsaes_cbc_encrypt;
+ dat->block = AES_decrypt;
+ dat->stream.cbc = bsaes_cbc_encrypt;
} else if (vpaes_capable()) {
ret = vpaes_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
- dat->block = (block128_f)vpaes_decrypt;
- dat->stream.cbc =
- mode == EVP_CIPH_CBC_MODE ? (cbc128_f)vpaes_cbc_encrypt : NULL;
+ dat->block = vpaes_decrypt;
+ dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? vpaes_cbc_encrypt : NULL;
} else {
ret = AES_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
- dat->block = (block128_f)AES_decrypt;
- dat->stream.cbc =
- mode == EVP_CIPH_CBC_MODE ? (cbc128_f)AES_cbc_encrypt : NULL;
+ dat->block = AES_decrypt;
+ dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? AES_cbc_encrypt : NULL;
}
} else if (hwaes_capable()) {
ret = aes_hw_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
- dat->block = (block128_f)aes_hw_encrypt;
+ dat->block = aes_hw_encrypt;
dat->stream.cbc = NULL;
if (mode == EVP_CIPH_CBC_MODE) {
- dat->stream.cbc = (cbc128_f)aes_hw_cbc_encrypt;
+ dat->stream.cbc = aes_hw_cbc_encrypt;
} else if (mode == EVP_CIPH_CTR_MODE) {
- dat->stream.ctr = (ctr128_f)aes_hw_ctr32_encrypt_blocks;
+ dat->stream.ctr = aes_hw_ctr32_encrypt_blocks;
}
} else if (bsaes_capable() && mode == EVP_CIPH_CTR_MODE) {
ret = AES_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
- dat->block = (block128_f)AES_encrypt;
- dat->stream.ctr = (ctr128_f)bsaes_ctr32_encrypt_blocks;
+ dat->block = AES_encrypt;
+ dat->stream.ctr = bsaes_ctr32_encrypt_blocks;
} else if (vpaes_capable()) {
ret = vpaes_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
- dat->block = (block128_f)vpaes_encrypt;
- dat->stream.cbc =
- mode == EVP_CIPH_CBC_MODE ? (cbc128_f)vpaes_cbc_encrypt : NULL;
+ dat->block = vpaes_encrypt;
+ dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? vpaes_cbc_encrypt : NULL;
} else {
ret = AES_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
- dat->block = (block128_f)AES_encrypt;
- dat->stream.cbc =
- mode == EVP_CIPH_CBC_MODE ? (cbc128_f)AES_cbc_encrypt : NULL;
+ dat->block = AES_encrypt;
+ dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? AES_cbc_encrypt : NULL;
}
if (ret < 0) {
@@ -256,11 +252,11 @@
EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
if (dat->stream.cbc) {
- (*dat->stream.cbc)(in, out, len, &dat->ks, ctx->iv, ctx->encrypt);
+ (*dat->stream.cbc)(in, out, len, &dat->ks.ks, ctx->iv, ctx->encrypt);
} else if (ctx->encrypt) {
- CRYPTO_cbc128_encrypt(in, out, len, &dat->ks, ctx->iv, dat->block);
+ CRYPTO_cbc128_encrypt(in, out, len, &dat->ks.ks, ctx->iv, dat->block);
} else {
- CRYPTO_cbc128_decrypt(in, out, len, &dat->ks, ctx->iv, dat->block);
+ CRYPTO_cbc128_decrypt(in, out, len, &dat->ks.ks, ctx->iv, dat->block);
}
return 1;
@@ -277,7 +273,7 @@
len -= bl;
for (size_t i = 0; i <= len; i += bl) {
- (*dat->block)(in + i, out + i, &dat->ks);
+ (*dat->block)(in + i, out + i, &dat->ks.ks);
}
return 1;
@@ -288,11 +284,11 @@
EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
if (dat->stream.ctr) {
- CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks, ctx->iv, ctx->buf,
+ CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks.ks, ctx->iv, ctx->buf,
&ctx->num, dat->stream.ctr);
} else {
- CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, ctx->iv, ctx->buf, &ctx->num,
- dat->block);
+ CRYPTO_ctr128_encrypt(in, out, len, &dat->ks.ks, ctx->iv, ctx->buf,
+ &ctx->num, dat->block);
}
return 1;
}
@@ -301,7 +297,8 @@
size_t len) {
EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
- CRYPTO_ofb128_encrypt(in, out, len, &dat->ks, ctx->iv, &ctx->num, dat->block);
+ CRYPTO_ofb128_encrypt(in, out, len, &dat->ks.ks, ctx->iv, &ctx->num,
+ dat->block);
return 1;
}
@@ -311,42 +308,42 @@
if (hwaes_capable()) {
aes_hw_set_encrypt_key(key, key_bytes * 8, aes_key);
if (gcm_key != NULL) {
- CRYPTO_gcm128_init_key(gcm_key, aes_key, (block128_f)aes_hw_encrypt, 1);
+ CRYPTO_gcm128_init_key(gcm_key, aes_key, aes_hw_encrypt, 1);
}
if (out_block) {
- *out_block = (block128_f) aes_hw_encrypt;
+ *out_block = aes_hw_encrypt;
}
- return (ctr128_f)aes_hw_ctr32_encrypt_blocks;
+ return aes_hw_ctr32_encrypt_blocks;
}
if (bsaes_capable()) {
AES_set_encrypt_key(key, key_bytes * 8, aes_key);
if (gcm_key != NULL) {
- CRYPTO_gcm128_init_key(gcm_key, aes_key, (block128_f)AES_encrypt, 0);
+ CRYPTO_gcm128_init_key(gcm_key, aes_key, AES_encrypt, 0);
}
if (out_block) {
- *out_block = (block128_f) AES_encrypt;
+ *out_block = AES_encrypt;
}
- return (ctr128_f)bsaes_ctr32_encrypt_blocks;
+ return bsaes_ctr32_encrypt_blocks;
}
if (vpaes_capable()) {
vpaes_set_encrypt_key(key, key_bytes * 8, aes_key);
if (out_block) {
- *out_block = (block128_f) vpaes_encrypt;
+ *out_block = vpaes_encrypt;
}
if (gcm_key != NULL) {
- CRYPTO_gcm128_init_key(gcm_key, aes_key, (block128_f)vpaes_encrypt, 0);
+ CRYPTO_gcm128_init_key(gcm_key, aes_key, vpaes_encrypt, 0);
}
return NULL;
}
AES_set_encrypt_key(key, key_bytes * 8, aes_key);
if (gcm_key != NULL) {
- CRYPTO_gcm128_init_key(gcm_key, aes_key, (block128_f)AES_encrypt, 0);
+ CRYPTO_gcm128_init_key(gcm_key, aes_key, AES_encrypt, 0);
}
if (out_block) {
- *out_block = (block128_f) AES_encrypt;
+ *out_block = AES_encrypt;
}
return NULL;
}
diff --git a/src/crypto/fipsmodule/modes/cbc.c b/src/crypto/fipsmodule/modes/cbc.c
index db9f024..64ea505 100644
--- a/src/crypto/fipsmodule/modes/cbc.c
+++ b/src/crypto/fipsmodule/modes/cbc.c
@@ -53,7 +53,7 @@
void CRYPTO_cbc128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
- const void *key, uint8_t ivec[16],
+ const AES_KEY *key, uint8_t ivec[16],
block128_f block) {
size_t n;
const uint8_t *iv = ivec;
@@ -108,7 +108,7 @@
}
void CRYPTO_cbc128_decrypt(const uint8_t *in, uint8_t *out, size_t len,
- const void *key, uint8_t ivec[16],
+ const AES_KEY *key, uint8_t ivec[16],
block128_f block) {
size_t n;
union {
diff --git a/src/crypto/fipsmodule/modes/ccm.c b/src/crypto/fipsmodule/modes/ccm.c
index 784e4fa..5a153f4 100644
--- a/src/crypto/fipsmodule/modes/ccm.c
+++ b/src/crypto/fipsmodule/modes/ccm.c
@@ -64,8 +64,8 @@
} nonce, cmac;
};
-int CRYPTO_ccm128_init(CCM128_CONTEXT *ctx, const void *key, block128_f block,
- ctr128_f ctr, unsigned M, unsigned L) {
+int CRYPTO_ccm128_init(CCM128_CONTEXT *ctx, const AES_KEY *key,
+ block128_f block, ctr128_f ctr, unsigned M, unsigned L) {
if (M < 4 || M > 16 || (M & 1) != 0 || L < 2 || L > 8) {
return 0;
}
@@ -82,7 +82,7 @@
}
static int ccm128_init_state(const CCM128_CONTEXT *ctx,
- struct ccm128_state *state, const void *key,
+ struct ccm128_state *state, const AES_KEY *key,
const uint8_t *nonce, size_t nonce_len,
const uint8_t *aad, size_t aad_len,
size_t plaintext_len) {
@@ -170,7 +170,7 @@
}
static int ccm128_encrypt(const CCM128_CONTEXT *ctx, struct ccm128_state *state,
- const void *key, uint8_t *out, const uint8_t *in,
+ const AES_KEY *key, uint8_t *out, const uint8_t *in,
size_t len) {
// The counter for encryption begins at one.
for (unsigned i = 0; i < ctx->L; i++) {
@@ -191,7 +191,7 @@
}
static int ccm128_compute_mac(const CCM128_CONTEXT *ctx,
- struct ccm128_state *state, const void *key,
+ struct ccm128_state *state, const AES_KEY *key,
uint8_t *out_tag, size_t tag_len,
const uint8_t *in, size_t len) {
block128_f block = ctx->block;
@@ -231,7 +231,7 @@
return 1;
}
-int CRYPTO_ccm128_encrypt(const CCM128_CONTEXT *ctx, const void *key,
+int CRYPTO_ccm128_encrypt(const CCM128_CONTEXT *ctx, const AES_KEY *key,
uint8_t *out, uint8_t *out_tag, size_t tag_len,
const uint8_t *nonce, size_t nonce_len,
const uint8_t *in, size_t len, const uint8_t *aad,
@@ -243,7 +243,7 @@
ccm128_encrypt(ctx, &state, key, out, in, len);
}
-int CRYPTO_ccm128_decrypt(const CCM128_CONTEXT *ctx, const void *key,
+int CRYPTO_ccm128_decrypt(const CCM128_CONTEXT *ctx, const AES_KEY *key,
uint8_t *out, uint8_t *out_tag, size_t tag_len,
const uint8_t *nonce, size_t nonce_len,
const uint8_t *in, size_t len, const uint8_t *aad,
diff --git a/src/crypto/fipsmodule/modes/cfb.c b/src/crypto/fipsmodule/modes/cfb.c
index e1b0a80..d3a38d6 100644
--- a/src/crypto/fipsmodule/modes/cfb.c
+++ b/src/crypto/fipsmodule/modes/cfb.c
@@ -57,7 +57,7 @@
OPENSSL_COMPILE_ASSERT((16 % sizeof(size_t)) == 0, bad_size_t_size_cfb);
void CRYPTO_cfb128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
- const void *key, uint8_t ivec[16], unsigned *num,
+ const AES_KEY *key, uint8_t ivec[16], unsigned *num,
int enc, block128_f block) {
size_t l = 0;
@@ -161,7 +161,7 @@
/* This expects a single block of size nbits for both in and out. Note that
it corrupts any extra bits in the last byte of out */
static void cfbr_encrypt_block(const uint8_t *in, uint8_t *out, unsigned nbits,
- const void *key, uint8_t ivec[16], int enc,
+ const AES_KEY *key, uint8_t ivec[16], int enc,
block128_f block) {
int n, rem, num;
uint8_t ovec[16 * 2 + 1]; /* +1 because we dererefence (but don't use) one
@@ -203,8 +203,8 @@
// N.B. This expects the input to be packed, MS bit first
void CRYPTO_cfb128_1_encrypt(const uint8_t *in, uint8_t *out, size_t bits,
- const void *key, uint8_t ivec[16], unsigned *num,
- int enc, block128_f block) {
+ const AES_KEY *key, uint8_t ivec[16],
+ unsigned *num, int enc, block128_f block) {
size_t n;
uint8_t c[1], d[1];
@@ -220,7 +220,7 @@
}
void CRYPTO_cfb128_8_encrypt(const unsigned char *in, unsigned char *out,
- size_t length, const void *key,
+ size_t length, const AES_KEY *key,
unsigned char ivec[16], unsigned *num, int enc,
block128_f block) {
size_t n;
diff --git a/src/crypto/fipsmodule/modes/ctr.c b/src/crypto/fipsmodule/modes/ctr.c
index 63907b4..5093408 100644
--- a/src/crypto/fipsmodule/modes/ctr.c
+++ b/src/crypto/fipsmodule/modes/ctr.c
@@ -82,7 +82,7 @@
// of the IV. This implementation takes NO responsibility for checking that
// the counter doesn't overflow into the rest of the IV when incremented.
void CRYPTO_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
- const void *key, uint8_t ivec[16],
+ const AES_KEY *key, uint8_t ivec[16],
uint8_t ecount_buf[16], unsigned int *num,
block128_f block) {
unsigned int n;
@@ -153,11 +153,10 @@
} while (n);
}
-void CRYPTO_ctr128_encrypt_ctr32(const uint8_t *in, uint8_t *out,
- size_t len, const void *key,
- uint8_t ivec[16],
- uint8_t ecount_buf[16],
- unsigned int *num, ctr128_f func) {
+void CRYPTO_ctr128_encrypt_ctr32(const uint8_t *in, uint8_t *out, size_t len,
+ const AES_KEY *key, uint8_t ivec[16],
+ uint8_t ecount_buf[16], unsigned int *num,
+ ctr128_f func) {
unsigned int n, ctr32;
assert(key && ecount_buf && num);
diff --git a/src/crypto/fipsmodule/modes/gcm.c b/src/crypto/fipsmodule/modes/gcm.c
index 6eff479..5e556df 100644
--- a/src/crypto/fipsmodule/modes/gcm.c
+++ b/src/crypto/fipsmodule/modes/gcm.c
@@ -271,9 +271,9 @@
size_t len);
#define AESNI_GCM
size_t aesni_gcm_encrypt(const uint8_t *in, uint8_t *out, size_t len,
- const void *key, uint8_t ivec[16], uint64_t *Xi);
+ const AES_KEY *key, uint8_t ivec[16], uint64_t *Xi);
size_t aesni_gcm_decrypt(const uint8_t *in, uint8_t *out, size_t len,
- const void *key, uint8_t ivec[16], uint64_t *Xi);
+ const AES_KEY *key, uint8_t ivec[16], uint64_t *Xi);
#endif
#if defined(OPENSSL_X86)
@@ -419,7 +419,7 @@
#endif
}
-void CRYPTO_gcm128_init_key(GCM128_KEY *gcm_key, const void *aes_key,
+void CRYPTO_gcm128_init_key(GCM128_KEY *gcm_key, const AES_KEY *aes_key,
block128_f block, int block_is_hwaes) {
OPENSSL_memset(gcm_key, 0, sizeof(*gcm_key));
gcm_key->block = block;
@@ -435,7 +435,7 @@
gcm_key->use_aesni_gcm_crypt = (is_avx && block_is_hwaes) ? 1 : 0;
}
-void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const void *key,
+void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const AES_KEY *key,
const uint8_t *iv, size_t len) {
unsigned int ctr;
#ifdef GCM_FUNCREF_4BIT
@@ -553,7 +553,7 @@
return 1;
}
-int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, const void *key,
+int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, const AES_KEY *key,
const uint8_t *in, uint8_t *out, size_t len) {
unsigned int n, ctr;
uint64_t mlen = ctx->len.u[1];
@@ -679,7 +679,7 @@
return 1;
}
-int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, const void *key,
+int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, const AES_KEY *key,
const unsigned char *in, unsigned char *out,
size_t len) {
unsigned int n, ctr;
@@ -813,7 +813,7 @@
return 1;
}
-int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, const void *key,
+int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, const AES_KEY *key,
const uint8_t *in, uint8_t *out, size_t len,
ctr128_f stream) {
unsigned int n, ctr;
@@ -915,7 +915,7 @@
return 1;
}
-int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, const void *key,
+int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, const AES_KEY *key,
const uint8_t *in, uint8_t *out, size_t len,
ctr128_f stream) {
unsigned int n, ctr;
diff --git a/src/crypto/fipsmodule/modes/gcm_test.cc b/src/crypto/fipsmodule/modes/gcm_test.cc
index ab8cc34..30308f8 100644
--- a/src/crypto/fipsmodule/modes/gcm_test.cc
+++ b/src/crypto/fipsmodule/modes/gcm_test.cc
@@ -88,7 +88,7 @@
GCM128_CONTEXT ctx;
OPENSSL_memset(&ctx, 0, sizeof(ctx));
- CRYPTO_gcm128_init_key(&ctx.gcm_key, &aes_key, (block128_f)AES_encrypt, 0);
+ CRYPTO_gcm128_init_key(&ctx.gcm_key, &aes_key, AES_encrypt, 0);
CRYPTO_gcm128_setiv(&ctx, &aes_key, nonce.data(), nonce.size());
if (!additional_data.empty()) {
CRYPTO_gcm128_aad(&ctx, additional_data.data(), additional_data.size());
diff --git a/src/crypto/fipsmodule/modes/internal.h b/src/crypto/fipsmodule/modes/internal.h
index 788960b..23aaca2 100644
--- a/src/crypto/fipsmodule/modes/internal.h
+++ b/src/crypto/fipsmodule/modes/internal.h
@@ -50,6 +50,7 @@
#define OPENSSL_HEADER_MODES_INTERNAL_H
#include <openssl/base.h>
+#include <openssl/aes.h>
#include <string.h>
@@ -87,16 +88,24 @@
OPENSSL_memcpy(out, &v, sizeof(v));
}
-// block128_f is the type of a 128-bit, block cipher.
+// block128_f is the type of an AES block cipher implementation.
+//
+// Unlike upstream OpenSSL, it and the other functions in this file hard-code
+// |AES_KEY|. It is undefined in C to call a function pointer with anything
+// other than the original type. Thus we either must match |block128_f| to the
+// type signature of |AES_encrypt| and friends or pass in |void*| wrapper
+// functions.
+//
+// These functions are called exclusively with AES, so we use the former.
typedef void (*block128_f)(const uint8_t in[16], uint8_t out[16],
- const void *key);
+ const AES_KEY *key);
// CTR.
// ctr128_f is the type of a function that performs CTR-mode encryption.
typedef void (*ctr128_f)(const uint8_t *in, uint8_t *out, size_t blocks,
- const void *key, const uint8_t ivec[16]);
+ const AES_KEY *key, const uint8_t ivec[16]);
// CRYPTO_ctr128_encrypt encrypts (or decrypts, it's the same in CTR mode)
// |len| bytes from |in| to |out| using |block| in counter mode. There's no
@@ -105,7 +114,7 @@
// call. The counter is a 128-bit, big-endian value in |ivec| and is
// incremented by this function.
void CRYPTO_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
- const void *key, uint8_t ivec[16],
+ const AES_KEY *key, uint8_t ivec[16],
uint8_t ecount_buf[16], unsigned *num,
block128_f block);
@@ -114,14 +123,14 @@
// bits of the counter. This is useful when |ctr| can be an optimised
// function.
void CRYPTO_ctr128_encrypt_ctr32(const uint8_t *in, uint8_t *out, size_t len,
- const void *key, uint8_t ivec[16],
+ const AES_KEY *key, uint8_t ivec[16],
uint8_t ecount_buf[16], unsigned *num,
ctr128_f ctr);
#if !defined(OPENSSL_NO_ASM) && \
(defined(OPENSSL_X86) || defined(OPENSSL_X86_64))
void aesni_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t blocks,
- const void *key, const uint8_t *ivec);
+ const AES_KEY *key, const uint8_t *ivec);
#endif
@@ -194,13 +203,13 @@
// CRYPTO_gcm128_init_key initialises |gcm_key| to use |block| (typically AES)
// with the given key. |block_is_hwaes| is one if |block| is |aes_hw_encrypt|.
-OPENSSL_EXPORT void CRYPTO_gcm128_init_key(GCM128_KEY *gcm_key, const void *key,
- block128_f block,
+OPENSSL_EXPORT void CRYPTO_gcm128_init_key(GCM128_KEY *gcm_key,
+ const AES_KEY *key, block128_f block,
int block_is_hwaes);
// CRYPTO_gcm128_setiv sets the IV (nonce) for |ctx|. The |key| must be the
// same key that was passed to |CRYPTO_gcm128_init|.
-OPENSSL_EXPORT void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const void *key,
+OPENSSL_EXPORT void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const AES_KEY *key,
const uint8_t *iv, size_t iv_len);
// CRYPTO_gcm128_aad sets the authenticated data for an instance of GCM.
@@ -212,16 +221,16 @@
// CRYPTO_gcm128_encrypt encrypts |len| bytes from |in| to |out|. The |key|
// must be the same key that was passed to |CRYPTO_gcm128_init|. It returns one
// on success and zero otherwise.
-OPENSSL_EXPORT int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, const void *key,
- const uint8_t *in, uint8_t *out,
- size_t len);
+OPENSSL_EXPORT int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx,
+ const AES_KEY *key, const uint8_t *in,
+ uint8_t *out, size_t len);
// CRYPTO_gcm128_decrypt decrypts |len| bytes from |in| to |out|. The |key|
// must be the same key that was passed to |CRYPTO_gcm128_init|. It returns one
// on success and zero otherwise.
-OPENSSL_EXPORT int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, const void *key,
- const uint8_t *in, uint8_t *out,
- size_t len);
+OPENSSL_EXPORT int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx,
+ const AES_KEY *key, const uint8_t *in,
+ uint8_t *out, size_t len);
// CRYPTO_gcm128_encrypt_ctr32 encrypts |len| bytes from |in| to |out| using
// a CTR function that only handles the bottom 32 bits of the nonce, like
@@ -229,7 +238,7 @@
// passed to |CRYPTO_gcm128_init|. It returns one on success and zero
// otherwise.
OPENSSL_EXPORT int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx,
- const void *key,
+ const AES_KEY *key,
const uint8_t *in, uint8_t *out,
size_t len, ctr128_f stream);
@@ -239,7 +248,7 @@
// passed to |CRYPTO_gcm128_init|. It returns one on success and zero
// otherwise.
OPENSSL_EXPORT int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx,
- const void *key,
+ const AES_KEY *key,
const uint8_t *in, uint8_t *out,
size_t len, ctr128_f stream);
@@ -265,8 +274,8 @@
// CRYPTO_ccm128_init initialises |ctx| to use |block| (typically AES) with the
// specified |M| and |L| parameters. It returns one on success and zero if |M|
// or |L| is invalid.
-int CRYPTO_ccm128_init(CCM128_CONTEXT *ctx, const void *key, block128_f block,
- ctr128_f ctr, unsigned M, unsigned L);
+int CRYPTO_ccm128_init(CCM128_CONTEXT *ctx, const AES_KEY *key,
+ block128_f block, ctr128_f ctr, unsigned M, unsigned L);
// CRYPTO_ccm128_max_input returns the maximum input length accepted by |ctx|.
size_t CRYPTO_ccm128_max_input(const CCM128_CONTEXT *ctx);
@@ -274,7 +283,7 @@
// CRYPTO_ccm128_encrypt encrypts |len| bytes from |in| to |out| writing the tag
// to |out_tag|. |key| must be the same key that was passed to
// |CRYPTO_ccm128_init|. It returns one on success and zero otherwise.
-int CRYPTO_ccm128_encrypt(const CCM128_CONTEXT *ctx, const void *key,
+int CRYPTO_ccm128_encrypt(const CCM128_CONTEXT *ctx, const AES_KEY *key,
uint8_t *out, uint8_t *out_tag, size_t tag_len,
const uint8_t *nonce, size_t nonce_len,
const uint8_t *in, size_t len, const uint8_t *aad,
@@ -283,7 +292,7 @@
// CRYPTO_ccm128_decrypt decrypts |len| bytes from |in| to |out|, writing the
// expected tag to |out_tag|. |key| must be the same key that was passed to
// |CRYPTO_ccm128_init|. It returns one on success and zero otherwise.
-int CRYPTO_ccm128_decrypt(const CCM128_CONTEXT *ctx, const void *key,
+int CRYPTO_ccm128_decrypt(const CCM128_CONTEXT *ctx, const AES_KEY *key,
uint8_t *out, uint8_t *out_tag, size_t tag_len,
const uint8_t *nonce, size_t nonce_len,
const uint8_t *in, size_t len, const uint8_t *aad,
@@ -294,21 +303,23 @@
// cbc128_f is the type of a function that performs CBC-mode encryption.
typedef void (*cbc128_f)(const uint8_t *in, uint8_t *out, size_t len,
- const void *key, uint8_t ivec[16], int enc);
+ const AES_KEY *key, uint8_t ivec[16], int enc);
// CRYPTO_cbc128_encrypt encrypts |len| bytes from |in| to |out| using the
// given IV and block cipher in CBC mode. The input need not be a multiple of
// 128 bits long, but the output will round up to the nearest 128 bit multiple,
// zero padding the input if needed. The IV will be updated on return.
void CRYPTO_cbc128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
- const void *key, uint8_t ivec[16], block128_f block);
+ const AES_KEY *key, uint8_t ivec[16],
+ block128_f block);
// CRYPTO_cbc128_decrypt decrypts |len| bytes from |in| to |out| using the
// given IV and block cipher in CBC mode. If |len| is not a multiple of 128
// bits then only that many bytes will be written, but a multiple of 128 bits
// is always read from |in|. The IV will be updated on return.
void CRYPTO_cbc128_decrypt(const uint8_t *in, uint8_t *out, size_t len,
- const void *key, uint8_t ivec[16], block128_f block);
+ const AES_KEY *key, uint8_t ivec[16],
+ block128_f block);
// OFB.
@@ -318,9 +329,9 @@
// requirement that |len| be a multiple of any value and any partial blocks are
// stored in |ivec| and |*num|, the latter must be zero before the initial
// call.
-void CRYPTO_ofb128_encrypt(const uint8_t *in, uint8_t *out,
- size_t len, const void *key, uint8_t ivec[16],
- unsigned *num, block128_f block);
+void CRYPTO_ofb128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
+ const AES_KEY *key, uint8_t ivec[16], unsigned *num,
+ block128_f block);
// CFB.
@@ -330,25 +341,25 @@
// |len| be a multiple of any value and any partial blocks are stored in |ivec|
// and |*num|, the latter must be zero before the initial call.
void CRYPTO_cfb128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
- const void *key, uint8_t ivec[16], unsigned *num,
+ const AES_KEY *key, uint8_t ivec[16], unsigned *num,
int enc, block128_f block);
// CRYPTO_cfb128_8_encrypt encrypts (or decrypts, if |enc| is zero) |len| bytes
// from |in| to |out| using |block| in CFB-8 mode. Prior to the first call
// |num| should be set to zero.
void CRYPTO_cfb128_8_encrypt(const uint8_t *in, uint8_t *out, size_t len,
- const void *key, uint8_t ivec[16], unsigned *num,
- int enc, block128_f block);
+ const AES_KEY *key, uint8_t ivec[16],
+ unsigned *num, int enc, block128_f block);
// CRYPTO_cfb128_1_encrypt encrypts (or decrypts, if |enc| is zero) |len| bytes
// from |in| to |out| using |block| in CFB-1 mode. Prior to the first call
// |num| should be set to zero.
void CRYPTO_cfb128_1_encrypt(const uint8_t *in, uint8_t *out, size_t bits,
- const void *key, uint8_t ivec[16], unsigned *num,
- int enc, block128_f block);
+ const AES_KEY *key, uint8_t ivec[16],
+ unsigned *num, int enc, block128_f block);
size_t CRYPTO_cts128_encrypt_block(const uint8_t *in, uint8_t *out, size_t len,
- const void *key, uint8_t ivec[16],
+ const AES_KEY *key, uint8_t ivec[16],
block128_f block);
diff --git a/src/crypto/fipsmodule/modes/ofb.c b/src/crypto/fipsmodule/modes/ofb.c
index 63bba68..b1b4d87 100644
--- a/src/crypto/fipsmodule/modes/ofb.c
+++ b/src/crypto/fipsmodule/modes/ofb.c
@@ -57,7 +57,7 @@
OPENSSL_COMPILE_ASSERT((16 % sizeof(size_t)) == 0, bad_size_t_size_ofb);
void CRYPTO_ofb128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
- const void *key, uint8_t ivec[16], unsigned *num,
+ const AES_KEY *key, uint8_t ivec[16], unsigned *num,
block128_f block) {
assert(in && out && key && ivec && num);
diff --git a/src/crypto/fipsmodule/self_check/self_check.c b/src/crypto/fipsmodule/self_check/self_check.c
index 2c5b363..1bbefa9 100644
--- a/src/crypto/fipsmodule/self_check/self_check.c
+++ b/src/crypto/fipsmodule/self_check/self_check.c
@@ -394,6 +394,7 @@
// AES-CBC Encryption KAT
memcpy(aes_iv, kAESIV, sizeof(kAESIV));
if (AES_set_encrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) != 0) {
+ fprintf(stderr, "AES_set_encrypt_key failed.\n");
goto err;
}
AES_cbc_encrypt(kPlaintext, output, sizeof(kPlaintext), &aes_key, aes_iv,
@@ -406,6 +407,7 @@
// AES-CBC Decryption KAT
memcpy(aes_iv, kAESIV, sizeof(kAESIV));
if (AES_set_decrypt_key(kAESKey, 8 * sizeof(kAESKey), &aes_key) != 0) {
+ fprintf(stderr, "AES_set_decrypt_key failed.\n");
goto err;
}
AES_cbc_encrypt(kAESCBCCiphertext, output, sizeof(kAESCBCCiphertext),
@@ -420,6 +422,7 @@
OPENSSL_memset(nonce, 0, sizeof(nonce));
if (!EVP_AEAD_CTX_init(&aead_ctx, EVP_aead_aes_128_gcm(), kAESKey,
sizeof(kAESKey), 0, NULL)) {
+ fprintf(stderr, "EVP_AEAD_CTX_init for AES-128-GCM failed.\n");
goto err;
}
@@ -429,6 +432,7 @@
kPlaintext, sizeof(kPlaintext), NULL, 0) ||
!check_test(kAESGCMCiphertext, output, sizeof(kAESGCMCiphertext),
"AES-GCM Encryption KAT")) {
+ fprintf(stderr, "EVP_AEAD_CTX_seal for AES-128-GCM failed.\n");
goto err;
}
@@ -439,6 +443,7 @@
0) ||
!check_test(kPlaintext, output, sizeof(kPlaintext),
"AES-GCM Decryption KAT")) {
+ fprintf(stderr, "EVP_AEAD_CTX_open for AES-128-GCM failed.\n");
goto err;
}
@@ -504,6 +509,7 @@
&sig_len, rsa_key) ||
!check_test(kRSASignature, output, sizeof(kRSASignature),
"RSA Sign KAT")) {
+ fprintf(stderr, "RSA signing test failed.\n");
goto err;
}
@@ -558,6 +564,7 @@
sizeof(kDRBGAD)) ||
!check_test(kDRBGReseedOutput, output, sizeof(kDRBGReseedOutput),
"DRBG Reseed KAT")) {
+ fprintf(stderr, "CTR-DRBG failed.\n");
goto err;
}
CTR_DRBG_clear(&drbg);
diff --git a/src/crypto/fipsmodule/sha/asm/sha1-armv8.pl b/src/crypto/fipsmodule/sha/asm/sha1-armv8.pl
index cec3669..80567d9 100644
--- a/src/crypto/fipsmodule/sha/asm/sha1-armv8.pl
+++ b/src/crypto/fipsmodule/sha/asm/sha1-armv8.pl
@@ -330,6 +330,7 @@
.asciz "SHA1 block transform for ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
.align 2
.comm OPENSSL_armcap_P,4,4
+.hidden OPENSSL_armcap_P
___
}}}
diff --git a/src/crypto/fipsmodule/sha/asm/sha512-armv8.pl b/src/crypto/fipsmodule/sha/asm/sha512-armv8.pl
index e3244f7..22c47d7 100644
--- a/src/crypto/fipsmodule/sha/asm/sha512-armv8.pl
+++ b/src/crypto/fipsmodule/sha/asm/sha512-armv8.pl
@@ -428,6 +428,7 @@
$code.=<<___;
#ifndef __KERNEL__
.comm OPENSSL_armcap_P,4,4
+.hidden OPENSSL_armcap_P
#endif
___
diff --git a/src/crypto/internal.h b/src/crypto/internal.h
index 0e8ae3a..6944d56 100644
--- a/src/crypto/internal.h
+++ b/src/crypto/internal.h
@@ -132,13 +132,13 @@
#endif
#endif
-#if !defined(OPENSSL_NO_THREADS) && \
+#if defined(OPENSSL_THREADS) && \
(!defined(OPENSSL_WINDOWS) || defined(__MINGW32__))
#include <pthread.h>
#define OPENSSL_PTHREADS
#endif
-#if !defined(OPENSSL_NO_THREADS) && !defined(OPENSSL_PTHREADS) && \
+#if defined(OPENSSL_THREADS) && !defined(OPENSSL_PTHREADS) && \
defined(OPENSSL_WINDOWS)
#define OPENSSL_WINDOWS_THREADS
OPENSSL_MSVC_PRAGMA(warning(push, 3))
@@ -367,7 +367,7 @@
// Thread-safe initialisation.
-#if defined(OPENSSL_NO_THREADS)
+#if !defined(OPENSSL_THREADS)
typedef uint32_t CRYPTO_once_t;
#define CRYPTO_ONCE_INIT 0
#elif defined(OPENSSL_WINDOWS_THREADS)
@@ -423,7 +423,7 @@
// thread.h as a structure large enough to fit the real type. The global lock is
// a different type so it may be initialized with platform initializer macros.
-#if defined(OPENSSL_NO_THREADS)
+#if !defined(OPENSSL_THREADS)
struct CRYPTO_STATIC_MUTEX {
char padding; // Empty structs have different sizes in C and C++.
};
diff --git a/src/crypto/pem/pem_info.c b/src/crypto/pem/pem_info.c
index d707e42..3627a45 100644
--- a/src/crypto/pem/pem_info.c
+++ b/src/crypto/pem/pem_info.c
@@ -75,221 +75,203 @@
STACK_OF(X509_INFO) *PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk,
pem_password_cb *cb, void *u)
{
- BIO *b;
- STACK_OF(X509_INFO) *ret;
-
- if ((b = BIO_new(BIO_s_file())) == NULL) {
+ BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
+ if (b == NULL) {
OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
- return (0);
+ return 0;
}
- BIO_set_fp(b, fp, BIO_NOCLOSE);
- ret = PEM_X509_INFO_read_bio(b, sk, cb, u);
+ STACK_OF(X509_INFO) *ret = PEM_X509_INFO_read_bio(b, sk, cb, u);
BIO_free(b);
- return (ret);
+ return ret;
}
#endif
+enum parse_result_t {
+ parse_ok,
+ parse_error,
+ parse_new_entry,
+};
+
+static enum parse_result_t parse_x509(X509_INFO *info, const uint8_t *data,
+ size_t len, int key_type)
+{
+ if (info->x509 != NULL) {
+ return parse_new_entry;
+ }
+ info->x509 = d2i_X509(NULL, &data, len);
+ return info->x509 != NULL ? parse_ok : parse_error;
+}
+
+static enum parse_result_t parse_x509_aux(X509_INFO *info, const uint8_t *data,
+ size_t len, int key_type)
+{
+ if (info->x509 != NULL) {
+ return parse_new_entry;
+ }
+ info->x509 = d2i_X509_AUX(NULL, &data, len);
+ return info->x509 != NULL ? parse_ok : parse_error;
+}
+
+static enum parse_result_t parse_crl(X509_INFO *info, const uint8_t *data,
+ size_t len, int key_type)
+{
+ if (info->crl != NULL) {
+ return parse_new_entry;
+ }
+ info->crl = d2i_X509_CRL(NULL, &data, len);
+ return info->crl != NULL ? parse_ok : parse_error;
+}
+
+static enum parse_result_t parse_key(X509_INFO *info, const uint8_t *data,
+ size_t len, int key_type)
+{
+ if (info->x_pkey != NULL) {
+ return parse_new_entry;
+ }
+ info->x_pkey = X509_PKEY_new();
+ if (info->x_pkey == NULL) {
+ return parse_error;
+ }
+ info->x_pkey->dec_pkey = d2i_PrivateKey(key_type, NULL, &data, len);
+ return info->x_pkey->dec_pkey != NULL ? parse_ok : parse_error;
+}
+
STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk,
pem_password_cb *cb, void *u)
{
- X509_INFO *xi = NULL;
+ X509_INFO *info = NULL;
char *name = NULL, *header = NULL;
- void *pp;
unsigned char *data = NULL;
- const unsigned char *p;
- long len, error = 0;
+ long len;
int ok = 0;
STACK_OF(X509_INFO) *ret = NULL;
- unsigned int i, raw, ptype;
- d2i_of_void *d2i = 0;
if (sk == NULL) {
- if ((ret = sk_X509_INFO_new_null()) == NULL) {
+ ret = sk_X509_INFO_new_null();
+ if (ret == NULL) {
OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
- goto err;
+ return NULL;
}
- } else
+ } else {
ret = sk;
+ }
+ size_t orig_num = sk_X509_INFO_num(ret);
- if ((xi = X509_INFO_new()) == NULL)
+ info = X509_INFO_new();
+ if (info == NULL) {
goto err;
+ }
+
for (;;) {
- raw = 0;
- ptype = 0;
- i = PEM_read_bio(bp, &name, &header, &data, &len);
- if (i == 0) {
- error = ERR_GET_REASON(ERR_peek_last_error());
- if (error == PEM_R_NO_START_LINE) {
+ if (!PEM_read_bio(bp, &name, &header, &data, &len)) {
+ uint32_t error = ERR_peek_last_error();
+ if (ERR_GET_LIB(error) == ERR_LIB_PEM &&
+ ERR_GET_REASON(error) == PEM_R_NO_START_LINE) {
ERR_clear_error();
break;
}
goto err;
}
- start:
- if ((strcmp(name, PEM_STRING_X509) == 0) ||
- (strcmp(name, PEM_STRING_X509_OLD) == 0)) {
- d2i = (D2I_OF(void)) d2i_X509;
- if (xi->x509 != NULL) {
- if (!sk_X509_INFO_push(ret, xi))
- goto err;
- if ((xi = X509_INFO_new()) == NULL)
- goto err;
- goto start;
- }
- pp = &(xi->x509);
- } else if ((strcmp(name, PEM_STRING_X509_TRUSTED) == 0)) {
- d2i = (D2I_OF(void)) d2i_X509_AUX;
- if (xi->x509 != NULL) {
- if (!sk_X509_INFO_push(ret, xi))
- goto err;
- if ((xi = X509_INFO_new()) == NULL)
- goto err;
- goto start;
- }
- pp = &(xi->x509);
+
+ enum parse_result_t (*parse_function)(X509_INFO *, const uint8_t *,
+ size_t, int) = NULL;
+ int key_type = EVP_PKEY_NONE;
+ if (strcmp(name, PEM_STRING_X509) == 0 ||
+ strcmp(name, PEM_STRING_X509_OLD) == 0) {
+ parse_function = parse_x509;
+ } else if (strcmp(name, PEM_STRING_X509_TRUSTED) == 0) {
+ parse_function = parse_x509_aux;
} else if (strcmp(name, PEM_STRING_X509_CRL) == 0) {
- d2i = (D2I_OF(void)) d2i_X509_CRL;
- if (xi->crl != NULL) {
- if (!sk_X509_INFO_push(ret, xi))
- goto err;
- if ((xi = X509_INFO_new()) == NULL)
- goto err;
- goto start;
- }
- pp = &(xi->crl);
+ parse_function = parse_crl;
} else if (strcmp(name, PEM_STRING_RSA) == 0) {
- d2i = (D2I_OF(void)) d2i_RSAPrivateKey;
- if (xi->x_pkey != NULL) {
- if (!sk_X509_INFO_push(ret, xi))
- goto err;
- if ((xi = X509_INFO_new()) == NULL)
- goto err;
- goto start;
- }
-
- xi->enc_data = NULL;
- xi->enc_len = 0;
-
- xi->x_pkey = X509_PKEY_new();
- ptype = EVP_PKEY_RSA;
- pp = &xi->x_pkey->dec_pkey;
- if ((int)strlen(header) > 10) /* assume encrypted */
- raw = 1;
- } else
-#ifndef OPENSSL_NO_DSA
- if (strcmp(name, PEM_STRING_DSA) == 0) {
- d2i = (D2I_OF(void)) d2i_DSAPrivateKey;
- if (xi->x_pkey != NULL) {
- if (!sk_X509_INFO_push(ret, xi))
- goto err;
- if ((xi = X509_INFO_new()) == NULL)
- goto err;
- goto start;
- }
-
- xi->enc_data = NULL;
- xi->enc_len = 0;
-
- xi->x_pkey = X509_PKEY_new();
- ptype = EVP_PKEY_DSA;
- pp = &xi->x_pkey->dec_pkey;
- if ((int)strlen(header) > 10) /* assume encrypted */
- raw = 1;
- } else
-#endif
- if (strcmp(name, PEM_STRING_ECPRIVATEKEY) == 0) {
- d2i = (D2I_OF(void)) d2i_ECPrivateKey;
- if (xi->x_pkey != NULL) {
- if (!sk_X509_INFO_push(ret, xi))
- goto err;
- if ((xi = X509_INFO_new()) == NULL)
- goto err;
- goto start;
- }
-
- xi->enc_data = NULL;
- xi->enc_len = 0;
-
- xi->x_pkey = X509_PKEY_new();
- ptype = EVP_PKEY_EC;
- pp = &xi->x_pkey->dec_pkey;
- if ((int)strlen(header) > 10) /* assume encrypted */
- raw = 1;
- } else {
- d2i = NULL;
- pp = NULL;
+ parse_function = parse_key;
+ key_type = EVP_PKEY_RSA;
+ } else if (strcmp(name, PEM_STRING_DSA) == 0) {
+ parse_function = parse_key;
+ key_type = EVP_PKEY_DSA;
+ } else if (strcmp(name, PEM_STRING_ECPRIVATEKEY) == 0) {
+ parse_function = parse_key;
+ key_type = EVP_PKEY_EC;
}
- if (d2i != NULL) {
- if (!raw) {
- EVP_CIPHER_INFO cipher;
-
- if (!PEM_get_EVP_CIPHER_INFO(header, &cipher))
- goto err;
- if (!PEM_do_header(&cipher, data, &len, cb, u))
- goto err;
- p = data;
- if (ptype) {
- if (!d2i_PrivateKey(ptype, pp, &p, len)) {
- OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
- goto err;
- }
- } else if (d2i(pp, &p, len) == NULL) {
- OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
+ /* If a private key has a header, assume it is encrypted. */
+ if (key_type != EVP_PKEY_NONE && strlen(header) > 10) {
+ if (info->x_pkey != NULL) {
+ if (!sk_X509_INFO_push(ret, info)) {
goto err;
}
- } else { /* encrypted RSA data */
- if (!PEM_get_EVP_CIPHER_INFO(header, &xi->enc_cipher))
+ info = X509_INFO_new();
+ if (info == NULL) {
goto err;
- xi->enc_data = (char *)data;
- xi->enc_len = (int)len;
- data = NULL;
+ }
}
- } else {
- /* unknown */
+ /* Historically, raw entries pushed an empty key. */
+ info->x_pkey = X509_PKEY_new();
+ if (info->x_pkey == NULL ||
+ !PEM_get_EVP_CIPHER_INFO(header, &info->enc_cipher)) {
+ goto err;
+ }
+ info->enc_data = (char *)data;
+ info->enc_len = (int)len;
+ data = NULL;
+ } else if (parse_function != NULL) {
+ EVP_CIPHER_INFO cipher;
+ if (!PEM_get_EVP_CIPHER_INFO(header, &cipher) ||
+ !PEM_do_header(&cipher, data, &len, cb, u)) {
+ goto err;
+ }
+ enum parse_result_t result =
+ parse_function(info, data, len, key_type);
+ if (result == parse_new_entry) {
+ if (!sk_X509_INFO_push(ret, info)) {
+ goto err;
+ }
+ info = X509_INFO_new();
+ if (info == NULL) {
+ goto err;
+ }
+ result = parse_function(info, data, len, key_type);
+ }
+ if (result != parse_ok) {
+ OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
+ goto err;
+ }
}
- if (name != NULL)
- OPENSSL_free(name);
- if (header != NULL)
- OPENSSL_free(header);
- if (data != NULL)
- OPENSSL_free(data);
+ OPENSSL_free(name);
+ OPENSSL_free(header);
+ OPENSSL_free(data);
name = NULL;
header = NULL;
data = NULL;
}
- /*
- * if the last one hasn't been pushed yet and there is anything in it
- * then add it to the stack ...
- */
- if ((xi->x509 != NULL) || (xi->crl != NULL) ||
- (xi->x_pkey != NULL) || (xi->enc_data != NULL)) {
- if (!sk_X509_INFO_push(ret, xi))
+ /* Push the last entry on the stack if not empty. */
+ if (info->x509 != NULL || info->crl != NULL ||
+ info->x_pkey != NULL || info->enc_data != NULL) {
+ if (!sk_X509_INFO_push(ret, info)) {
goto err;
- xi = NULL;
- }
- ok = 1;
- err:
- if (xi != NULL)
- X509_INFO_free(xi);
- if (!ok) {
- for (i = 0; i < sk_X509_INFO_num(ret); i++) {
- xi = sk_X509_INFO_value(ret, i);
- X509_INFO_free(xi);
}
- if (ret != sk)
+ info = NULL;
+ }
+
+ ok = 1;
+
+ err:
+ X509_INFO_free(info);
+ if (!ok) {
+ while (sk_X509_INFO_num(ret) > orig_num) {
+ X509_INFO_free(sk_X509_INFO_pop(ret));
+ }
+ if (ret != sk) {
sk_X509_INFO_free(ret);
+ }
ret = NULL;
}
- if (name != NULL)
- OPENSSL_free(name);
- if (header != NULL)
- OPENSSL_free(header);
- if (data != NULL)
- OPENSSL_free(data);
- return (ret);
+ OPENSSL_free(name);
+ OPENSSL_free(header);
+ OPENSSL_free(data);
+ return ret;
}
/* A TJH addition */
diff --git a/src/crypto/pem/pem_lib.c b/src/crypto/pem/pem_lib.c
index 5180e55..c682429 100644
--- a/src/crypto/pem/pem_lib.c
+++ b/src/crypto/pem/pem_lib.c
@@ -121,17 +121,14 @@
void *PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x,
pem_password_cb *cb, void *u)
{
- BIO *b;
- void *ret;
-
- if ((b = BIO_new(BIO_s_file())) == NULL) {
+ BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
+ if (b == NULL) {
OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
- return (0);
+ return NULL;
}
- BIO_set_fp(b, fp, BIO_NOCLOSE);
- ret = PEM_ASN1_read_bio(d2i, name, b, x, cb, u);
+ void *ret = PEM_ASN1_read_bio(d2i, name, b, x, cb, u);
BIO_free(b);
- return (ret);
+ return ret;
}
#endif
@@ -220,8 +217,11 @@
for (;;) {
if (!PEM_read_bio(bp, &nm, &header, &data, &len)) {
- if (ERR_GET_REASON(ERR_peek_error()) == PEM_R_NO_START_LINE)
+ uint32_t error = ERR_peek_error();
+ if (ERR_GET_LIB(error) == ERR_LIB_PEM &&
+ ERR_GET_REASON(error) == PEM_R_NO_START_LINE) {
ERR_add_error_data(2, "Expecting: ", name);
+ }
return 0;
}
if (check_pem(nm, name))
@@ -257,17 +257,14 @@
void *x, const EVP_CIPHER *enc, unsigned char *kstr,
int klen, pem_password_cb *callback, void *u)
{
- BIO *b;
- int ret;
-
- if ((b = BIO_new(BIO_s_file())) == NULL) {
+ BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
+ if (b == NULL) {
OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
- return (0);
+ return 0;
}
- BIO_set_fp(b, fp, BIO_NOCLOSE);
- ret = PEM_ASN1_write_bio(i2d, name, b, x, enc, kstr, klen, callback, u);
+ int ret = PEM_ASN1_write_bio(i2d, name, b, x, enc, kstr, klen, callback, u);
BIO_free(b);
- return (ret);
+ return ret;
}
#endif
@@ -514,15 +511,12 @@
int PEM_write(FILE *fp, const char *name, const char *header,
const unsigned char *data, long len)
{
- BIO *b;
- int ret;
-
- if ((b = BIO_new(BIO_s_file())) == NULL) {
+ BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
+ if (b == NULL) {
OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
- return (0);
+ return 0;
}
- BIO_set_fp(b, fp, BIO_NOCLOSE);
- ret = PEM_write_bio(b, name, header, data, len);
+ int ret = PEM_write_bio(b, name, header, data, len);
BIO_free(b);
return (ret);
}
@@ -588,15 +582,12 @@
int PEM_read(FILE *fp, char **name, char **header, unsigned char **data,
long *len)
{
- BIO *b;
- int ret;
-
- if ((b = BIO_new(BIO_s_file())) == NULL) {
+ BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
+ if (b == NULL) {
OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
- return (0);
+ return 0;
}
- BIO_set_fp(b, fp, BIO_NOCLOSE);
- ret = PEM_read_bio(b, name, header, data, len);
+ int ret = PEM_read_bio(b, name, header, data, len);
BIO_free(b);
return (ret);
}
diff --git a/src/crypto/pem/pem_pkey.c b/src/crypto/pem/pem_pkey.c
index 9fbaeef..725a84b 100644
--- a/src/crypto/pem/pem_pkey.c
+++ b/src/crypto/pem/pem_pkey.c
@@ -155,31 +155,26 @@
EVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x, pem_password_cb *cb,
void *u)
{
- BIO *b;
- EVP_PKEY *ret;
-
- if ((b = BIO_new(BIO_s_file())) == NULL) {
+ BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
+ if (b == NULL) {
OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
- return (0);
+ return NULL;
}
- BIO_set_fp(b, fp, BIO_NOCLOSE);
- ret = PEM_read_bio_PrivateKey(b, x, cb, u);
+ EVP_PKEY *ret = PEM_read_bio_PrivateKey(b, x, cb, u);
BIO_free(b);
- return (ret);
+ return ret;
}
int PEM_write_PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
unsigned char *kstr, int klen,
pem_password_cb *cb, void *u)
{
- BIO *b;
- int ret;
-
- if ((b = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) {
+ BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
+ if (b == NULL) {
OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
return 0;
}
- ret = PEM_write_bio_PrivateKey(b, x, enc, kstr, klen, cb, u);
+ int ret = PEM_write_bio_PrivateKey(b, x, enc, kstr, klen, cb, u);
BIO_free(b);
return ret;
}
@@ -212,16 +207,13 @@
#ifndef OPENSSL_NO_FP_API
DH *PEM_read_DHparams(FILE *fp, DH **x, pem_password_cb *cb, void *u)
{
- BIO *b;
- DH *ret;
-
- if ((b = BIO_new(BIO_s_file())) == NULL) {
+ BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
+ if (b == NULL) {
OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
- return (0);
+ return NULL;
}
- BIO_set_fp(b, fp, BIO_NOCLOSE);
- ret = PEM_read_bio_DHparams(b, x, cb, u);
+ DH *ret = PEM_read_bio_DHparams(b, x, cb, u);
BIO_free(b);
- return (ret);
+ return ret;
}
#endif
diff --git a/src/crypto/pkcs7/pkcs7_x509.c b/src/crypto/pkcs7/pkcs7_x509.c
index a2a6b46..d6ca44e 100644
--- a/src/crypto/pkcs7/pkcs7_x509.c
+++ b/src/crypto/pkcs7/pkcs7_x509.c
@@ -333,17 +333,7 @@
}
int i2d_PKCS7_bio(BIO *bio, const PKCS7 *p7) {
- size_t written = 0;
- while (written < p7->ber_len) {
- size_t todo = p7->ber_len - written;
- int len = todo > INT_MAX ? INT_MAX : (int)todo;
- int ret = BIO_write(bio, p7->ber_bytes + written, len);
- if (ret <= 0) {
- return 0;
- }
- written += (size_t)ret;
- }
- return 1;
+ return BIO_write_all(bio, p7->ber_bytes, p7->ber_len);
}
void PKCS7_free(PKCS7 *p7) {
diff --git a/src/crypto/pkcs8/pkcs8_x509.c b/src/crypto/pkcs8/pkcs8_x509.c
index dc74d96..2c7841e 100644
--- a/src/crypto/pkcs8/pkcs8_x509.c
+++ b/src/crypto/pkcs8/pkcs8_x509.c
@@ -861,17 +861,7 @@
}
int i2d_PKCS12_bio(BIO *bio, const PKCS12 *p12) {
- size_t written = 0;
- while (written < p12->ber_len) {
- size_t todo = p12->ber_len - written;
- int len = todo > INT_MAX ? INT_MAX : (int)todo;
- int ret = BIO_write(bio, p12->ber_bytes + written, len);
- if (ret <= 0) {
- return 0;
- }
- written += (size_t)ret;
- }
- return 1;
+ return BIO_write_all(bio, p12->ber_bytes, p12->ber_len);
}
int i2d_PKCS12_fp(FILE *fp, const PKCS12 *p12) {
diff --git a/src/crypto/pool/pool_test.cc b/src/crypto/pool/pool_test.cc
index 62fb17d..8f32fb6 100644
--- a/src/crypto/pool/pool_test.cc
+++ b/src/crypto/pool/pool_test.cc
@@ -18,7 +18,7 @@
#include "../test/test_util.h"
-#if !defined(OPENSSL_NO_THREADS)
+#if defined(OPENSSL_THREADS)
#include <chrono>
#include <thread>
#endif
@@ -61,7 +61,7 @@
EXPECT_EQ(buf.get(), buf2.get()) << "CRYPTO_BUFFER_POOL did not dedup data.";
}
-#if !defined(OPENSSL_NO_THREADS)
+#if defined(OPENSSL_THREADS)
TEST(PoolTest, Threads) {
bssl::UniquePtr<CRYPTO_BUFFER_POOL> pool(CRYPTO_BUFFER_POOL_new());
ASSERT_TRUE(pool);
diff --git a/src/crypto/rand_extra/rand_test.cc b/src/crypto/rand_extra/rand_test.cc
index bd2eb18..d0a7e40 100644
--- a/src/crypto/rand_extra/rand_test.cc
+++ b/src/crypto/rand_extra/rand_test.cc
@@ -20,7 +20,7 @@
#include "../test/test_util.h"
-#if !defined(OPENSSL_NO_THREADS)
+#if defined(OPENSSL_THREADS)
#include <array>
#include <thread>
#include <vector>
@@ -50,7 +50,8 @@
EXPECT_NE(Bytes(buf2), Bytes(kZeros));
}
-#if !defined(OPENSSL_WINDOWS) && !defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
+#if !defined(OPENSSL_WINDOWS) && !defined(OPENSSL_IOS) && \
+ !defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
static bool ForkAndRand(bssl::Span<uint8_t> out) {
int pipefds[2];
if (pipe(pipefds) < 0) {
@@ -144,9 +145,10 @@
EXPECT_NE(Bytes(buf2), Bytes(kZeros));
EXPECT_NE(Bytes(buf3), Bytes(kZeros));
}
-#endif // !OPENSSL_WINDOWS && !BORINGSSL_UNSAFE_DETERMINISTIC_MODE
+#endif // !OPENSSL_WINDOWS && !OPENSSL_IOS &&
+ // !BORINGSSL_UNSAFE_DETERMINISTIC_MODE
-#if !defined(OPENSSL_NO_THREADS)
+#if defined(OPENSSL_THREADS)
static void RunConcurrentRands(size_t num_threads) {
static const uint8_t kZeros[256] = {0};
diff --git a/src/crypto/refcount_test.cc b/src/crypto/refcount_test.cc
index 6ce0746..700863f 100644
--- a/src/crypto/refcount_test.cc
+++ b/src/crypto/refcount_test.cc
@@ -16,7 +16,7 @@
#include <gtest/gtest.h>
-#if !defined(OPENSSL_NO_THREADS)
+#if defined(OPENSSL_THREADS)
#include <thread>
#endif
@@ -43,7 +43,7 @@
EXPECT_EQ(1u, count);
}
-#if !defined(OPENSSL_NO_THREADS)
+#if defined(OPENSSL_THREADS)
// This test is primarily intended to run under ThreadSanitizer.
TEST(RefCountTest, Threads) {
CRYPTO_refcount_t count = 0;
diff --git a/src/crypto/rsa_extra/rsa_test.cc b/src/crypto/rsa_extra/rsa_test.cc
index b0a0b7e..9bd47b1 100644
--- a/src/crypto/rsa_extra/rsa_test.cc
+++ b/src/crypto/rsa_extra/rsa_test.cc
@@ -72,7 +72,7 @@
#include "../internal.h"
#include "../test/test_util.h"
-#if !defined(OPENSSL_NO_THREADS)
+#if defined(OPENSSL_THREADS)
#include <thread>
#include <vector>
#endif
@@ -1048,7 +1048,7 @@
}
#endif // !BORINGSSL_SHARED_LIBRARY
-#if !defined(OPENSSL_NO_THREADS)
+#if defined(OPENSSL_THREADS)
TEST(RSATest, Threads) {
bssl::UniquePtr<RSA> rsa_template(
RSA_private_key_from_bytes(kKey1, sizeof(kKey1) - 1));
diff --git a/src/crypto/stack/stack.c b/src/crypto/stack/stack.c
index 7aa3218..93b9d1b 100644
--- a/src/crypto/stack/stack.c
+++ b/src/crypto/stack/stack.c
@@ -133,19 +133,31 @@
OPENSSL_free(sk);
}
-void sk_pop_free(_STACK *sk, void (*func)(void *)) {
+void sk_pop_free_ex(_STACK *sk, void (*call_free_func)(stack_free_func, void *),
+ stack_free_func free_func) {
if (sk == NULL) {
return;
}
for (size_t i = 0; i < sk->num; i++) {
if (sk->data[i] != NULL) {
- func(sk->data[i]);
+ call_free_func(free_func, sk->data[i]);
}
}
sk_free(sk);
}
+// Historically, |sk_pop_free| called the function as |stack_free_func|
+// directly. This is undefined in C. Some callers called |sk_pop_free| directly,
+// so we must maintain a compatibility version for now.
+static void call_free_func_legacy(stack_free_func func, void *ptr) {
+ func(ptr);
+}
+
+void sk_pop_free(_STACK *sk, stack_free_func free_func) {
+ sk_pop_free_ex(sk, call_free_func_legacy, free_func);
+}
+
size_t sk_insert(_STACK *sk, void *p, size_t where) {
if (sk == NULL) {
return 0;
@@ -209,7 +221,7 @@
return ret;
}
-void *sk_delete_ptr(_STACK *sk, void *p) {
+void *sk_delete_ptr(_STACK *sk, const void *p) {
if (sk == NULL) {
return NULL;
}
@@ -223,7 +235,9 @@
return NULL;
}
-int sk_find(const _STACK *sk, size_t *out_index, void *p) {
+int sk_find(const _STACK *sk, size_t *out_index, const void *p,
+ int (*call_cmp_func)(stack_cmp_func, const void **,
+ const void **)) {
if (sk == NULL) {
return 0;
}
@@ -247,7 +261,8 @@
if (!sk_is_sorted(sk)) {
for (size_t i = 0; i < sk->num; i++) {
- if (sk->comp((const void **)&p, (const void **)&sk->data[i]) == 0) {
+ const void *elem = sk->data[i];
+ if (call_cmp_func(sk->comp, &p, &elem) == 0) {
if (out_index) {
*out_index = i;
}
@@ -262,15 +277,25 @@
// elements. However, since we're passing an array of pointers to
// qsort/bsearch, we can just cast the comparison function and everything
// works.
+ //
+ // TODO(davidben): This is undefined behavior, but the call is in libc so,
+ // e.g., CFI does not notice. Unfortunately, |bsearch| is missing a void*
+ // parameter in its callback and |bsearch_s| is a mess of incompatibility.
const void *const *r = bsearch(&p, sk->data, sk->num, sizeof(void *),
(int (*)(const void *, const void *))sk->comp);
if (r == NULL) {
return 0;
}
size_t idx = ((void **)r) - sk->data;
- // This function always returns the first result.
- while (idx > 0 &&
- sk->comp((const void **)&p, (const void **)&sk->data[idx - 1]) == 0) {
+ // This function always returns the first result. Note this logic is, in the
+ // worst case, O(N) rather than O(log(N)). If this ever becomes a problem,
+ // restore https://boringssl-review.googlesource.com/c/boringssl/+/32115/
+ // which integrates the preference into the binary search.
+ while (idx > 0) {
+ const void *elem = sk->data[idx - 1];
+ if (call_cmp_func(sk->comp, &p, &elem) != 0) {
+ break;
+ }
idx--;
}
if (out_index) {
@@ -340,6 +365,11 @@
}
// See the comment in sk_find about this cast.
+ //
+ // TODO(davidben): This is undefined behavior, but the call is in libc so,
+ // e.g., CFI does not notice. Unfortunately, |qsort| is missing a void*
+ // parameter in its callback and |qsort_s| / |qsort_r| are a mess of
+ // incompatibility.
comp_func = (int (*)(const void *, const void *))(sk->comp);
qsort(sk->data, sk->num, sizeof(void *), comp_func);
sk->sorted = 1;
@@ -363,8 +393,11 @@
return old;
}
-_STACK *sk_deep_copy(const _STACK *sk, void *(*copy_func)(void *),
- void (*free_func)(void *)) {
+_STACK *sk_deep_copy(const _STACK *sk,
+ void *(*call_copy_func)(stack_copy_func, void *),
+ stack_copy_func copy_func,
+ void (*call_free_func)(stack_free_func, void *),
+ stack_free_func free_func) {
_STACK *ret = sk_dup(sk);
if (ret == NULL) {
return NULL;
@@ -374,11 +407,11 @@
if (ret->data[i] == NULL) {
continue;
}
- ret->data[i] = copy_func(ret->data[i]);
+ ret->data[i] = call_copy_func(copy_func, ret->data[i]);
if (ret->data[i] == NULL) {
for (size_t j = 0; j < i; j++) {
if (ret->data[j] != NULL) {
- free_func(ret->data[j]);
+ call_free_func(free_func, ret->data[j]);
}
}
sk_free(ret);
diff --git a/src/crypto/stack/stack_test.cc b/src/crypto/stack/stack_test.cc
new file mode 100644
index 0000000..8b26971
--- /dev/null
+++ b/src/crypto/stack/stack_test.cc
@@ -0,0 +1,394 @@
+/* Copyright (c) 2018, 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 <openssl/stack.h>
+
+#include <limits.h>
+
+#include <algorithm>
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include <openssl/mem.h>
+
+
+// Define a custom stack type for testing.
+using TEST_INT = int;
+
+static void TEST_INT_free(TEST_INT *x) { OPENSSL_free(x); }
+
+namespace bssl {
+BORINGSSL_MAKE_DELETER(TEST_INT, TEST_INT_free)
+} // namespace bssl
+
+static bssl::UniquePtr<TEST_INT> TEST_INT_new(int x) {
+ bssl::UniquePtr<TEST_INT> ret(
+ static_cast<TEST_INT *>(OPENSSL_malloc(sizeof(TEST_INT))));
+ if (!ret) {
+ return nullptr;
+ }
+ *ret = x;
+ return ret;
+}
+
+DEFINE_STACK_OF(TEST_INT)
+
+struct ShallowStackDeleter {
+ void operator()(STACK_OF(TEST_INT) *sk) const { sk_TEST_INT_free(sk); }
+};
+
+using ShallowStack = std::unique_ptr<STACK_OF(TEST_INT), ShallowStackDeleter>;
+
+// kNull is treated as a nullptr expectation for purposes of ExpectStackEquals.
+// The tests in this file will never use it as a test value.
+static const int kNull = INT_MIN;
+
+static void ExpectStackEquals(const STACK_OF(TEST_INT) *sk,
+ const std::vector<int> &vec) {
+ EXPECT_EQ(vec.size(), sk_TEST_INT_num(sk));
+ for (size_t i = 0; i < vec.size(); i++) {
+ SCOPED_TRACE(i);
+ const TEST_INT *obj = sk_TEST_INT_value(sk, i);
+ if (vec[i] == kNull) {
+ EXPECT_FALSE(obj);
+ } else {
+ EXPECT_TRUE(obj);
+ if (obj) {
+ EXPECT_EQ(vec[i], *obj);
+ }
+ }
+ }
+
+ // Reading out-of-bounds fails.
+ EXPECT_FALSE(sk_TEST_INT_value(sk, vec.size()));
+ EXPECT_FALSE(sk_TEST_INT_value(sk, vec.size() + 1));
+}
+
+TEST(StackTest, Basic) {
+ bssl::UniquePtr<STACK_OF(TEST_INT)> sk(sk_TEST_INT_new_null());
+ ASSERT_TRUE(sk);
+
+ // The stack starts out empty.
+ ExpectStackEquals(sk.get(), {});
+
+ // Removing elements from an empty stack does nothing.
+ EXPECT_FALSE(sk_TEST_INT_pop(sk.get()));
+ EXPECT_FALSE(sk_TEST_INT_shift(sk.get()));
+ EXPECT_FALSE(sk_TEST_INT_delete(sk.get(), 0));
+
+ // Push some elements.
+ for (int i = 0; i < 6; i++) {
+ auto value = TEST_INT_new(i);
+ ASSERT_TRUE(value);
+ ASSERT_TRUE(bssl::PushToStack(sk.get(), std::move(value)));
+ }
+
+ ExpectStackEquals(sk.get(), {0, 1, 2, 3, 4, 5});
+
+ // Items may be inserted in the middle.
+ auto value = TEST_INT_new(6);
+ ASSERT_TRUE(value);
+ // Hold on to the object for later.
+ TEST_INT *raw = value.get();
+ ASSERT_TRUE(sk_TEST_INT_insert(sk.get(), value.get(), 4));
+ value.release(); // sk_TEST_INT_insert takes ownership on success.
+
+ ExpectStackEquals(sk.get(), {0, 1, 2, 3, 6, 4, 5});
+
+ // Without a comparison function, find searches by pointer.
+ value = TEST_INT_new(6);
+ ASSERT_TRUE(value);
+ size_t index;
+ EXPECT_FALSE(sk_TEST_INT_find(sk.get(), &index, value.get()));
+ ASSERT_TRUE(sk_TEST_INT_find(sk.get(), &index, raw));
+ EXPECT_EQ(4u, index);
+
+ // sk_TEST_INT_insert can also insert values at the end.
+ value = TEST_INT_new(7);
+ ASSERT_TRUE(value);
+ ASSERT_TRUE(sk_TEST_INT_insert(sk.get(), value.get(), 7));
+ value.release(); // sk_TEST_INT_insert takes ownership on success.
+
+ ExpectStackEquals(sk.get(), {0, 1, 2, 3, 6, 4, 5, 7});
+
+ // Out-of-bounds indices are clamped.
+ value = TEST_INT_new(8);
+ ASSERT_TRUE(value);
+ ASSERT_TRUE(sk_TEST_INT_insert(sk.get(), value.get(), 999));
+ value.release(); // sk_TEST_INT_insert takes ownership on success.
+
+ ExpectStackEquals(sk.get(), {0, 1, 2, 3, 6, 4, 5, 7, 8});
+
+ // Test removing elements from various places.
+ bssl::UniquePtr<TEST_INT> removed(sk_TEST_INT_pop(sk.get()));
+ EXPECT_EQ(8, *removed);
+ ExpectStackEquals(sk.get(), {0, 1, 2, 3, 6, 4, 5, 7});
+
+ removed.reset(sk_TEST_INT_shift(sk.get()));
+ EXPECT_EQ(0, *removed);
+ ExpectStackEquals(sk.get(), {1, 2, 3, 6, 4, 5, 7});
+
+ removed.reset(sk_TEST_INT_delete(sk.get(), 2));
+ EXPECT_EQ(3, *removed);
+ ExpectStackEquals(sk.get(), {1, 2, 6, 4, 5, 7});
+
+ // Objects may also be deleted by pointer.
+ removed.reset(sk_TEST_INT_delete_ptr(sk.get(), raw));
+ EXPECT_EQ(raw, removed.get());
+ ExpectStackEquals(sk.get(), {1, 2, 4, 5, 7});
+
+ // Deleting is a no-op is the object is not found.
+ value = TEST_INT_new(100);
+ ASSERT_TRUE(value);
+ EXPECT_FALSE(sk_TEST_INT_delete_ptr(sk.get(), value.get()));
+
+ // Insert nullptr to test deep copy handling of it.
+ ASSERT_TRUE(sk_TEST_INT_insert(sk.get(), nullptr, 0));
+ ExpectStackEquals(sk.get(), {kNull, 1, 2, 4, 5, 7});
+
+ // Test both deep and shallow copies.
+ bssl::UniquePtr<STACK_OF(TEST_INT)> copy(sk_TEST_INT_deep_copy(
+ sk.get(),
+ [](TEST_INT *x) -> TEST_INT * {
+ return x == nullptr ? nullptr : TEST_INT_new(*x).release();
+ },
+ TEST_INT_free));
+ ASSERT_TRUE(copy);
+ ExpectStackEquals(copy.get(), {kNull, 1, 2, 4, 5, 7});
+
+ ShallowStack shallow(sk_TEST_INT_dup(sk.get()));
+ ASSERT_TRUE(shallow);
+ ASSERT_EQ(sk_TEST_INT_num(sk.get()), sk_TEST_INT_num(shallow.get()));
+ for (size_t i = 0; i < sk_TEST_INT_num(sk.get()); i++) {
+ EXPECT_EQ(sk_TEST_INT_value(sk.get(), i),
+ sk_TEST_INT_value(shallow.get(), i));
+ }
+
+ // Deep copies may fail. This should clean up temporaries.
+ EXPECT_FALSE(sk_TEST_INT_deep_copy(sk.get(),
+ [](TEST_INT *x) -> TEST_INT * {
+ return x == nullptr || *x == 4
+ ? nullptr
+ : TEST_INT_new(*x).release();
+ },
+ TEST_INT_free));
+
+ // sk_TEST_INT_zero clears a stack, but does not free the elements.
+ ShallowStack shallow2(sk_TEST_INT_dup(sk.get()));
+ ASSERT_TRUE(shallow2);
+ sk_TEST_INT_zero(shallow2.get());
+ ExpectStackEquals(shallow2.get(), {});
+}
+
+TEST(StackTest, BigStack) {
+ bssl::UniquePtr<STACK_OF(TEST_INT)> sk(sk_TEST_INT_new_null());
+ ASSERT_TRUE(sk);
+
+ std::vector<int> expected;
+ static const int kCount = 100000;
+ for (int i = 0; i < kCount; i++) {
+ auto value = TEST_INT_new(i);
+ ASSERT_TRUE(value);
+ ASSERT_TRUE(bssl::PushToStack(sk.get(), std::move(value)));
+ expected.push_back(i);
+ }
+ ExpectStackEquals(sk.get(), expected);
+}
+
+static uint64_t g_compare_count = 0;
+
+static int compare(const TEST_INT **a, const TEST_INT **b) {
+ g_compare_count++;
+ if (**a < **b) {
+ return -1;
+ }
+ if (**a > **b) {
+ return 1;
+ }
+ return 0;
+}
+
+static int compare_reverse(const TEST_INT **a, const TEST_INT **b) {
+ return -compare(a, b);
+}
+
+TEST(StackTest, Sorted) {
+ std::vector<int> vec_sorted = {0, 1, 2, 3, 4, 5, 6};
+ std::vector<int> vec = vec_sorted;
+ do {
+ bssl::UniquePtr<STACK_OF(TEST_INT)> sk(sk_TEST_INT_new(compare));
+ ASSERT_TRUE(sk);
+ for (int v : vec) {
+ auto value = TEST_INT_new(v);
+ ASSERT_TRUE(value);
+ ASSERT_TRUE(bssl::PushToStack(sk.get(), std::move(value)));
+ }
+
+ // The stack is not (known to be) sorted.
+ EXPECT_FALSE(sk_TEST_INT_is_sorted(sk.get()));
+
+ // With a comparison function, find matches by value.
+ auto ten = TEST_INT_new(10);
+ ASSERT_TRUE(ten);
+ size_t index;
+ EXPECT_FALSE(sk_TEST_INT_find(sk.get(), &index, ten.get()));
+
+ auto three = TEST_INT_new(3);
+ ASSERT_TRUE(three);
+ ASSERT_TRUE(sk_TEST_INT_find(sk.get(), &index, three.get()));
+ EXPECT_EQ(3, *sk_TEST_INT_value(sk.get(), index));
+
+ sk_TEST_INT_sort(sk.get());
+ EXPECT_TRUE(sk_TEST_INT_is_sorted(sk.get()));
+ ExpectStackEquals(sk.get(), vec_sorted);
+
+ // Sorting an already-sorted list is a no-op.
+ uint64_t old_compare_count = g_compare_count;
+ sk_TEST_INT_sort(sk.get());
+ EXPECT_EQ(old_compare_count, g_compare_count);
+ EXPECT_TRUE(sk_TEST_INT_is_sorted(sk.get()));
+ ExpectStackEquals(sk.get(), vec_sorted);
+
+ // When sorted, find uses binary search.
+ ASSERT_TRUE(ten);
+ EXPECT_FALSE(sk_TEST_INT_find(sk.get(), &index, ten.get()));
+
+ ASSERT_TRUE(three);
+ ASSERT_TRUE(sk_TEST_INT_find(sk.get(), &index, three.get()));
+ EXPECT_EQ(3u, index);
+
+ // Copies preserve comparison and sorted information.
+ bssl::UniquePtr<STACK_OF(TEST_INT)> copy(sk_TEST_INT_deep_copy(
+ sk.get(),
+ [](TEST_INT *x) -> TEST_INT * { return TEST_INT_new(*x).release(); },
+ TEST_INT_free));
+ ASSERT_TRUE(copy);
+ EXPECT_TRUE(sk_TEST_INT_is_sorted(copy.get()));
+ ASSERT_TRUE(sk_TEST_INT_find(copy.get(), &index, three.get()));
+ EXPECT_EQ(3u, index);
+
+ ShallowStack copy2(sk_TEST_INT_dup(sk.get()));
+ ASSERT_TRUE(copy2);
+ EXPECT_TRUE(sk_TEST_INT_is_sorted(copy2.get()));
+ ASSERT_TRUE(sk_TEST_INT_find(copy2.get(), &index, three.get()));
+ EXPECT_EQ(3u, index);
+
+ // Removing elements does not affect sortedness.
+ TEST_INT_free(sk_TEST_INT_delete(sk.get(), 0));
+ EXPECT_TRUE(sk_TEST_INT_is_sorted(sk.get()));
+
+ // Changing the comparison function invalidates sortedness.
+ sk_TEST_INT_set_cmp_func(sk.get(), compare_reverse);
+ EXPECT_FALSE(sk_TEST_INT_is_sorted(sk.get()));
+ ASSERT_TRUE(sk_TEST_INT_find(sk.get(), &index, three.get()));
+ EXPECT_EQ(2u, index);
+
+ sk_TEST_INT_sort(sk.get());
+ ExpectStackEquals(sk.get(), {6, 5, 4, 3, 2, 1});
+ ASSERT_TRUE(sk_TEST_INT_find(sk.get(), &index, three.get()));
+ EXPECT_EQ(3u, index);
+
+ // Inserting a new element invalidates sortedness.
+ auto tmp = TEST_INT_new(10);
+ ASSERT_TRUE(tmp);
+ ASSERT_TRUE(bssl::PushToStack(sk.get(), std::move(tmp)));
+ EXPECT_FALSE(sk_TEST_INT_is_sorted(sk.get()));
+ ASSERT_TRUE(sk_TEST_INT_find(sk.get(), &index, ten.get()));
+ EXPECT_EQ(6u, index);
+ } while (std::next_permutation(vec.begin(), vec.end()));
+}
+
+// sk_*_find should return the first matching element in all cases.
+TEST(StackTest, FindFirst) {
+ bssl::UniquePtr<STACK_OF(TEST_INT)> sk(sk_TEST_INT_new(compare));
+ auto value = TEST_INT_new(1);
+ ASSERT_TRUE(value);
+ ASSERT_TRUE(bssl::PushToStack(sk.get(), std::move(value)));
+ for (int i = 0; i < 10; i++) {
+ value = TEST_INT_new(2);
+ ASSERT_TRUE(value);
+ ASSERT_TRUE(bssl::PushToStack(sk.get(), std::move(value)));
+ }
+
+ const TEST_INT *two = sk_TEST_INT_value(sk.get(), 1);
+ // Pointer-based equality.
+ size_t index;
+ ASSERT_TRUE(sk_TEST_INT_find(sk.get(), &index, two));
+ EXPECT_EQ(1u, index);
+
+ // Comparator-based equality, unsorted.
+ sk_TEST_INT_set_cmp_func(sk.get(), compare);
+ EXPECT_FALSE(sk_TEST_INT_is_sorted(sk.get()));
+ ASSERT_TRUE(sk_TEST_INT_find(sk.get(), &index, two));
+ EXPECT_EQ(1u, index);
+
+ // Comparator-based equality, sorted.
+ sk_TEST_INT_sort(sk.get());
+ EXPECT_TRUE(sk_TEST_INT_is_sorted(sk.get()));
+ ASSERT_TRUE(sk_TEST_INT_find(sk.get(), &index, two));
+ EXPECT_EQ(1u, index);
+
+ // Comparator-based equality, sorted and at the front.
+ sk_TEST_INT_set_cmp_func(sk.get(), compare_reverse);
+ sk_TEST_INT_sort(sk.get());
+ EXPECT_TRUE(sk_TEST_INT_is_sorted(sk.get()));
+ ASSERT_TRUE(sk_TEST_INT_find(sk.get(), &index, two));
+ EXPECT_EQ(0u, index);
+}
+
+// Exhaustively test the binary search.
+TEST(StackTest, BinarySearch) {
+ static const size_t kCount = 100;
+ for (size_t i = 0; i < kCount; i++) {
+ SCOPED_TRACE(i);
+ for (size_t j = i; j <= kCount; j++) {
+ SCOPED_TRACE(j);
+ // Make a stack where [0, i) are below, [i, j) match, and [j, kCount) are
+ // above.
+ bssl::UniquePtr<STACK_OF(TEST_INT)> sk(sk_TEST_INT_new(compare));
+ ASSERT_TRUE(sk);
+ for (size_t k = 0; k < i; k++) {
+ auto value = TEST_INT_new(-1);
+ ASSERT_TRUE(value);
+ ASSERT_TRUE(bssl::PushToStack(sk.get(), std::move(value)));
+ }
+ for (size_t k = i; k < j; k++) {
+ auto value = TEST_INT_new(0);
+ ASSERT_TRUE(value);
+ ASSERT_TRUE(bssl::PushToStack(sk.get(), std::move(value)));
+ }
+ for (size_t k = j; k < kCount; k++) {
+ auto value = TEST_INT_new(1);
+ ASSERT_TRUE(value);
+ ASSERT_TRUE(bssl::PushToStack(sk.get(), std::move(value)));
+ }
+ sk_TEST_INT_sort(sk.get());
+
+ auto key = TEST_INT_new(0);
+ ASSERT_TRUE(key);
+
+ size_t idx;
+ int found = sk_TEST_INT_find(sk.get(), &idx, key.get());
+ if (i == j) {
+ EXPECT_FALSE(found);
+ } else {
+ ASSERT_TRUE(found);
+ EXPECT_EQ(i, idx);
+ }
+ }
+ }
+}
diff --git a/src/crypto/thread_none.c b/src/crypto/thread_none.c
index 718d960..4f07b9d 100644
--- a/src/crypto/thread_none.c
+++ b/src/crypto/thread_none.c
@@ -14,7 +14,7 @@
#include "internal.h"
-#if defined(OPENSSL_NO_THREADS)
+#if !defined(OPENSSL_THREADS)
void CRYPTO_MUTEX_init(CRYPTO_MUTEX *lock) {}
@@ -56,4 +56,4 @@
return 1;
}
-#endif // OPENSSL_NO_THREADS
+#endif // !OPENSSL_THREADS
diff --git a/src/crypto/thread_test.cc b/src/crypto/thread_test.cc
index f89b22e..f9fad9b 100644
--- a/src/crypto/thread_test.cc
+++ b/src/crypto/thread_test.cc
@@ -25,7 +25,7 @@
#include "test/test_util.h"
-#if !defined(OPENSSL_NO_THREADS)
+#if defined(OPENSSL_THREADS)
static unsigned g_once_init_called = 0;
@@ -130,4 +130,4 @@
thread.join();
}
-#endif // !OPENSSL_NO_THREADS
+#endif // OPENSSL_THREADS
diff --git a/src/crypto/x509/by_file.c b/src/crypto/x509/by_file.c
index 555cb85..dfff425 100644
--- a/src/crypto/x509/by_file.c
+++ b/src/crypto/x509/by_file.c
@@ -138,14 +138,15 @@
for (;;) {
x = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
if (x == NULL) {
- if ((ERR_GET_REASON(ERR_peek_last_error()) ==
- PEM_R_NO_START_LINE) && (count > 0)) {
+ uint32_t error = ERR_peek_last_error();
+ if (ERR_GET_LIB(error) == ERR_LIB_PEM &&
+ ERR_GET_REASON(error) == PEM_R_NO_START_LINE &&
+ count > 0) {
ERR_clear_error();
break;
- } else {
- OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB);
- goto err;
}
+ OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB);
+ goto err;
}
i = X509_STORE_add_cert(ctx->store_ctx, x);
if (!i)
@@ -197,14 +198,15 @@
for (;;) {
x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
if (x == NULL) {
- if ((ERR_GET_REASON(ERR_peek_last_error()) ==
- PEM_R_NO_START_LINE) && (count > 0)) {
+ uint32_t error = ERR_peek_last_error();
+ if (ERR_GET_LIB(error) == ERR_LIB_PEM &&
+ ERR_GET_REASON(error) == PEM_R_NO_START_LINE &&
+ count > 0) {
ERR_clear_error();
break;
- } else {
- OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB);
- goto err;
}
+ OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB);
+ goto err;
}
i = X509_STORE_add_crl(ctx->store_ctx, x);
if (!i)
diff --git a/src/crypto/x509/t_crl.c b/src/crypto/x509/t_crl.c
index 6c347cb..dc9b87f 100644
--- a/src/crypto/x509/t_crl.c
+++ b/src/crypto/x509/t_crl.c
@@ -64,17 +64,14 @@
#ifndef OPENSSL_NO_FP_API
int X509_CRL_print_fp(FILE *fp, X509_CRL *x)
{
- BIO *b;
- int ret;
-
- if ((b = BIO_new(BIO_s_file())) == NULL) {
+ BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
+ if (b == NULL) {
OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB);
- return (0);
+ return 0;
}
- BIO_set_fp(b, fp, BIO_NOCLOSE);
- ret = X509_CRL_print(b, x);
+ int ret = X509_CRL_print(b, x);
BIO_free(b);
- return (ret);
+ return ret;
}
#endif
diff --git a/src/crypto/x509/t_req.c b/src/crypto/x509/t_req.c
index 39c836c..2fd36f8 100644
--- a/src/crypto/x509/t_req.c
+++ b/src/crypto/x509/t_req.c
@@ -65,13 +65,11 @@
int X509_REQ_print_fp(FILE *fp, X509_REQ *x) {
- BIO *bio = BIO_new(BIO_s_file());
+ BIO *bio = BIO_new_fp(fp, BIO_NOCLOSE);
if (bio == NULL) {
OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB);
return 0;
}
-
- BIO_set_fp(bio, fp, BIO_NOCLOSE);
int ret = X509_REQ_print(bio, x);
BIO_free(bio);
return ret;
diff --git a/src/crypto/x509/t_x509.c b/src/crypto/x509/t_x509.c
index 3339523..e45a765 100644
--- a/src/crypto/x509/t_x509.c
+++ b/src/crypto/x509/t_x509.c
@@ -72,17 +72,14 @@
int X509_print_ex_fp(FILE *fp, X509 *x, unsigned long nmflag,
unsigned long cflag)
{
- BIO *b;
- int ret;
-
- if ((b = BIO_new(BIO_s_file())) == NULL) {
+ BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
+ if (b == NULL) {
OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB);
- return (0);
+ return 0;
}
- BIO_set_fp(b, fp, BIO_NOCLOSE);
- ret = X509_print_ex(b, x, nmflag, cflag);
+ int ret = X509_print_ex(b, x, nmflag, cflag);
BIO_free(b);
- return (ret);
+ return ret;
}
int X509_print_fp(FILE *fp, X509 *x)
diff --git a/src/crypto/x509/x509_test.cc b/src/crypto/x509/x509_test.cc
index 9ed1b52..bf0b29a 100644
--- a/src/crypto/x509/x509_test.cc
+++ b/src/crypto/x509/x509_test.cc
@@ -1549,3 +1549,125 @@
EXPECT_EQ(ERR_LIB_X509, ERR_GET_LIB(err));
EXPECT_EQ(X509_R_SIGNATURE_ALGORITHM_MISMATCH, ERR_GET_REASON(err));
}
+
+TEST(X509Test, PEMX509Info) {
+ std::string cert = kRootCAPEM;
+ auto cert_obj = CertFromPEM(kRootCAPEM);
+ ASSERT_TRUE(cert_obj);
+
+ std::string rsa = kRSAKey;
+ auto rsa_obj = PrivateKeyFromPEM(kRSAKey);
+ ASSERT_TRUE(rsa_obj);
+
+ std::string crl = kBasicCRL;
+ auto crl_obj = CRLFromPEM(kBasicCRL);
+ ASSERT_TRUE(crl_obj);
+
+ std::string unknown =
+ "-----BEGIN UNKNOWN-----\n"
+ "AAAA\n"
+ "-----END UNKNOWN-----\n";
+
+ std::string invalid =
+ "-----BEGIN CERTIFICATE-----\n"
+ "AAAA\n"
+ "-----END CERTIFICATE-----\n";
+
+ // Each X509_INFO contains at most one certificate, CRL, etc. The format
+ // creates a new X509_INFO when a repeated type is seen.
+ std::string pem =
+ // The first few entries have one of everything in different orders.
+ cert + rsa + crl +
+ rsa + crl + cert +
+ // Unknown types are ignored.
+ crl + unknown + cert + rsa +
+ // Seeing a new certificate starts a new entry, so now we have a bunch of
+ // certificate-only entries.
+ cert + cert + cert +
+ // The key folds into the certificate's entry.
+ cert + rsa +
+ // Doubled keys also start new entries.
+ rsa + rsa + rsa + rsa + crl +
+ // As do CRLs.
+ crl + crl;
+
+ const struct ExpectedInfo {
+ const X509 *cert;
+ const EVP_PKEY *key;
+ const X509_CRL *crl;
+ } kExpected[] = {
+ {cert_obj.get(), rsa_obj.get(), crl_obj.get()},
+ {cert_obj.get(), rsa_obj.get(), crl_obj.get()},
+ {cert_obj.get(), rsa_obj.get(), crl_obj.get()},
+ {cert_obj.get(), nullptr, nullptr},
+ {cert_obj.get(), nullptr, nullptr},
+ {cert_obj.get(), nullptr, nullptr},
+ {cert_obj.get(), rsa_obj.get(), nullptr},
+ {nullptr, rsa_obj.get(), nullptr},
+ {nullptr, rsa_obj.get(), nullptr},
+ {nullptr, rsa_obj.get(), nullptr},
+ {nullptr, rsa_obj.get(), crl_obj.get()},
+ {nullptr, nullptr, crl_obj.get()},
+ {nullptr, nullptr, crl_obj.get()},
+ };
+
+ auto check_info = [](const ExpectedInfo *expected, const X509_INFO *info) {
+ if (expected->cert != nullptr) {
+ EXPECT_EQ(0, X509_cmp(expected->cert, info->x509));
+ } else {
+ EXPECT_EQ(nullptr, info->x509);
+ }
+ if (expected->crl != nullptr) {
+ EXPECT_EQ(0, X509_CRL_cmp(expected->crl, info->crl));
+ } else {
+ EXPECT_EQ(nullptr, info->crl);
+ }
+ if (expected->key != nullptr) {
+ ASSERT_NE(nullptr, info->x_pkey);
+ // EVP_PKEY_cmp returns one if the keys are equal.
+ EXPECT_EQ(1, EVP_PKEY_cmp(expected->key, info->x_pkey->dec_pkey));
+ } else {
+ EXPECT_EQ(nullptr, info->x_pkey);
+ }
+ };
+
+ bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(pem.data(), pem.size()));
+ ASSERT_TRUE(bio);
+ bssl::UniquePtr<STACK_OF(X509_INFO)> infos(
+ PEM_X509_INFO_read_bio(bio.get(), nullptr, nullptr, nullptr));
+ ASSERT_TRUE(infos);
+ ASSERT_EQ(OPENSSL_ARRAY_SIZE(kExpected), sk_X509_INFO_num(infos.get()));
+ for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kExpected); i++) {
+ SCOPED_TRACE(i);
+ check_info(&kExpected[i], sk_X509_INFO_value(infos.get(), i));
+ }
+
+ // Passing an existing stack appends to it.
+ bio.reset(BIO_new_mem_buf(pem.data(), pem.size()));
+ ASSERT_TRUE(bio);
+ ASSERT_EQ(infos.get(),
+ PEM_X509_INFO_read_bio(bio.get(), infos.get(), nullptr, nullptr));
+ ASSERT_EQ(2 * OPENSSL_ARRAY_SIZE(kExpected), sk_X509_INFO_num(infos.get()));
+ for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kExpected); i++) {
+ SCOPED_TRACE(i);
+ check_info(&kExpected[i], sk_X509_INFO_value(infos.get(), i));
+ check_info(
+ &kExpected[i],
+ sk_X509_INFO_value(infos.get(), i + OPENSSL_ARRAY_SIZE(kExpected)));
+ }
+
+ // Gracefully handle errors in both the append and fresh cases.
+ std::string bad_pem = cert + cert + invalid;
+
+ bio.reset(BIO_new_mem_buf(bad_pem.data(), bad_pem.size()));
+ ASSERT_TRUE(bio);
+ bssl::UniquePtr<STACK_OF(X509_INFO)> infos2(
+ PEM_X509_INFO_read_bio(bio.get(), nullptr, nullptr, nullptr));
+ EXPECT_FALSE(infos2);
+
+ bio.reset(BIO_new_mem_buf(bad_pem.data(), bad_pem.size()));
+ ASSERT_TRUE(bio);
+ EXPECT_FALSE(
+ PEM_X509_INFO_read_bio(bio.get(), infos.get(), nullptr, nullptr));
+ EXPECT_EQ(2 * OPENSSL_ARRAY_SIZE(kExpected), sk_X509_INFO_num(infos.get()));
+}
diff --git a/src/crypto/x509/x_all.c b/src/crypto/x509/x_all.c
index 064c89c..a37d7bd 100644
--- a/src/crypto/x509/x_all.c
+++ b/src/crypto/x509/x_all.c
@@ -54,14 +54,18 @@
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
+#include <openssl/x509.h>
+
+#include <limits.h>
+
#include <openssl/asn1.h>
#include <openssl/buf.h>
#include <openssl/digest.h>
#include <openssl/dsa.h>
#include <openssl/evp.h>
+#include <openssl/mem.h>
#include <openssl/rsa.h>
#include <openssl/stack.h>
-#include <openssl/x509.h>
int X509_verify(X509 *a, EVP_PKEY *r)
{
@@ -201,154 +205,102 @@
}
#ifndef OPENSSL_NO_FP_API
-RSA *d2i_RSAPrivateKey_fp(FILE *fp, RSA **rsa)
-{
- return ASN1_d2i_fp_of(RSA, RSA_new, d2i_RSAPrivateKey, fp, rsa);
-}
-int i2d_RSAPrivateKey_fp(FILE *fp, RSA *rsa)
-{
- return ASN1_i2d_fp_of_const(RSA, i2d_RSAPrivateKey, fp, rsa);
-}
+#define IMPLEMENT_D2I_FP(type, name, bio_func) \
+ type *name(FILE *fp, type **obj) { \
+ BIO *bio = BIO_new_fp(fp, BIO_NOCLOSE); \
+ if (bio == NULL) { \
+ return NULL; \
+ } \
+ type *ret = bio_func(bio, obj); \
+ BIO_free(bio); \
+ return ret; \
+ }
-RSA *d2i_RSAPublicKey_fp(FILE *fp, RSA **rsa)
-{
- return ASN1_d2i_fp_of(RSA, RSA_new, d2i_RSAPublicKey, fp, rsa);
-}
+#define IMPLEMENT_I2D_FP(type, name, bio_func) \
+ int name(FILE *fp, type *obj) { \
+ BIO *bio = BIO_new_fp(fp, BIO_NOCLOSE); \
+ if (bio == NULL) { \
+ return 0; \
+ } \
+ int ret = bio_func(bio, obj); \
+ BIO_free(bio); \
+ return ret; \
+ }
-RSA *d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa)
-{
- return ASN1_d2i_fp((void *(*)(void))
- RSA_new, (D2I_OF(void)) d2i_RSA_PUBKEY, fp,
- (void **)rsa);
-}
+IMPLEMENT_D2I_FP(RSA, d2i_RSAPrivateKey_fp, d2i_RSAPrivateKey_bio)
+IMPLEMENT_I2D_FP(RSA, i2d_RSAPrivateKey_fp, i2d_RSAPrivateKey_bio)
-int i2d_RSAPublicKey_fp(FILE *fp, RSA *rsa)
-{
- return ASN1_i2d_fp_of_const(RSA, i2d_RSAPublicKey, fp, rsa);
-}
+IMPLEMENT_D2I_FP(RSA, d2i_RSAPublicKey_fp, d2i_RSAPublicKey_bio)
+IMPLEMENT_I2D_FP(RSA, i2d_RSAPublicKey_fp, i2d_RSAPublicKey_bio)
-int i2d_RSA_PUBKEY_fp(FILE *fp, RSA *rsa)
-{
- return ASN1_i2d_fp((I2D_OF_const(void))i2d_RSA_PUBKEY, fp, rsa);
-}
+IMPLEMENT_D2I_FP(RSA, d2i_RSA_PUBKEY_fp, d2i_RSA_PUBKEY_bio)
+IMPLEMENT_I2D_FP(RSA, i2d_RSA_PUBKEY_fp, i2d_RSA_PUBKEY_bio)
#endif
-RSA *d2i_RSAPrivateKey_bio(BIO *bp, RSA **rsa)
-{
- return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSAPrivateKey, bp, rsa);
-}
+#define IMPLEMENT_D2I_BIO(type, name, d2i_func) \
+ type *name(BIO *bio, type **obj) { \
+ uint8_t *data; \
+ size_t len; \
+ if (!BIO_read_asn1(bio, &data, &len, 100 * 1024)) { \
+ return NULL; \
+ } \
+ const uint8_t *ptr = data; \
+ type *ret = d2i_func(obj, &ptr, (long)len); \
+ OPENSSL_free(data); \
+ return ret; \
+ }
-int i2d_RSAPrivateKey_bio(BIO *bp, RSA *rsa)
-{
- return ASN1_i2d_bio_of_const(RSA, i2d_RSAPrivateKey, bp, rsa);
-}
+#define IMPLEMENT_I2D_BIO(type, name, i2d_func) \
+ int name(BIO *bio, type *obj) { \
+ uint8_t *data = NULL; \
+ int len = i2d_func(obj, &data); \
+ if (len < 0) { \
+ return 0; \
+ } \
+ int ret = BIO_write_all(bio, data, len); \
+ OPENSSL_free(data); \
+ return ret; \
+ }
-RSA *d2i_RSAPublicKey_bio(BIO *bp, RSA **rsa)
-{
- return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSAPublicKey, bp, rsa);
-}
+IMPLEMENT_D2I_BIO(RSA, d2i_RSAPrivateKey_bio, d2i_RSAPrivateKey)
+IMPLEMENT_I2D_BIO(RSA, i2d_RSAPrivateKey_bio, i2d_RSAPrivateKey)
-RSA *d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa)
-{
- return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSA_PUBKEY, bp, rsa);
-}
+IMPLEMENT_D2I_BIO(RSA, d2i_RSAPublicKey_bio, d2i_RSAPublicKey)
+IMPLEMENT_I2D_BIO(RSA, i2d_RSAPublicKey_bio, i2d_RSAPublicKey)
-int i2d_RSAPublicKey_bio(BIO *bp, RSA *rsa)
-{
- return ASN1_i2d_bio_of_const(RSA, i2d_RSAPublicKey, bp, rsa);
-}
-
-int i2d_RSA_PUBKEY_bio(BIO *bp, RSA *rsa)
-{
- return ASN1_i2d_bio_of_const(RSA, i2d_RSA_PUBKEY, bp, rsa);
-}
+IMPLEMENT_D2I_BIO(RSA, d2i_RSA_PUBKEY_bio, d2i_RSA_PUBKEY)
+IMPLEMENT_I2D_BIO(RSA, i2d_RSA_PUBKEY_bio, i2d_RSA_PUBKEY)
#ifndef OPENSSL_NO_DSA
# ifndef OPENSSL_NO_FP_API
-DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa)
-{
- return ASN1_d2i_fp_of(DSA, DSA_new, d2i_DSAPrivateKey, fp, dsa);
-}
+IMPLEMENT_D2I_FP(DSA, d2i_DSAPrivateKey_fp, d2i_DSAPrivateKey_bio)
+IMPLEMENT_I2D_FP(DSA, i2d_DSAPrivateKey_fp, i2d_DSAPrivateKey_bio)
-int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa)
-{
- return ASN1_i2d_fp_of_const(DSA, i2d_DSAPrivateKey, fp, dsa);
-}
-
-DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa)
-{
- return ASN1_d2i_fp_of(DSA, DSA_new, d2i_DSA_PUBKEY, fp, dsa);
-}
-
-int i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa)
-{
- return ASN1_i2d_fp_of_const(DSA, i2d_DSA_PUBKEY, fp, dsa);
-}
+IMPLEMENT_D2I_FP(DSA, d2i_DSA_PUBKEY_fp, d2i_DSA_PUBKEY_bio)
+IMPLEMENT_I2D_FP(DSA, i2d_DSA_PUBKEY_fp, i2d_DSA_PUBKEY_bio)
# endif
-DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa)
-{
- return ASN1_d2i_bio_of(DSA, DSA_new, d2i_DSAPrivateKey, bp, dsa);
-}
+IMPLEMENT_D2I_BIO(DSA, d2i_DSAPrivateKey_bio, d2i_DSAPrivateKey)
+IMPLEMENT_I2D_BIO(DSA, i2d_DSAPrivateKey_bio, i2d_DSAPrivateKey)
-int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa)
-{
- return ASN1_i2d_bio_of_const(DSA, i2d_DSAPrivateKey, bp, dsa);
-}
-
-DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa)
-{
- return ASN1_d2i_bio_of(DSA, DSA_new, d2i_DSA_PUBKEY, bp, dsa);
-}
-
-int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa)
-{
- return ASN1_i2d_bio_of_const(DSA, i2d_DSA_PUBKEY, bp, dsa);
-}
-
+IMPLEMENT_D2I_BIO(DSA, d2i_DSA_PUBKEY_bio, d2i_DSA_PUBKEY)
+IMPLEMENT_I2D_BIO(DSA, i2d_DSA_PUBKEY_bio, i2d_DSA_PUBKEY)
#endif
#ifndef OPENSSL_NO_FP_API
-EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey)
-{
- return ASN1_d2i_fp_of(EC_KEY, EC_KEY_new, d2i_EC_PUBKEY, fp, eckey);
-}
+IMPLEMENT_D2I_FP(EC_KEY, d2i_ECPrivateKey_fp, d2i_ECPrivateKey_bio)
+IMPLEMENT_I2D_FP(EC_KEY, i2d_ECPrivateKey_fp, i2d_ECPrivateKey_bio)
-int i2d_EC_PUBKEY_fp(FILE *fp, EC_KEY *eckey)
-{
- return ASN1_i2d_fp_of_const(EC_KEY, i2d_EC_PUBKEY, fp, eckey);
-}
-
-EC_KEY *d2i_ECPrivateKey_fp(FILE *fp, EC_KEY **eckey)
-{
- return ASN1_d2i_fp_of(EC_KEY, EC_KEY_new, d2i_ECPrivateKey, fp, eckey);
-}
-
-int i2d_ECPrivateKey_fp(FILE *fp, EC_KEY *eckey)
-{
- return ASN1_i2d_fp_of_const(EC_KEY, i2d_ECPrivateKey, fp, eckey);
-}
+IMPLEMENT_D2I_FP(EC_KEY, d2i_EC_PUBKEY_fp, d2i_EC_PUBKEY_bio)
+IMPLEMENT_I2D_FP(EC_KEY, i2d_EC_PUBKEY_fp, i2d_EC_PUBKEY_bio)
#endif
-EC_KEY *d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **eckey)
-{
- return ASN1_d2i_bio_of(EC_KEY, EC_KEY_new, d2i_EC_PUBKEY, bp, eckey);
-}
-int i2d_EC_PUBKEY_bio(BIO *bp, EC_KEY *ecdsa)
-{
- return ASN1_i2d_bio_of_const(EC_KEY, i2d_EC_PUBKEY, bp, ecdsa);
-}
+IMPLEMENT_D2I_BIO(EC_KEY, d2i_ECPrivateKey_bio, d2i_ECPrivateKey)
+IMPLEMENT_I2D_BIO(EC_KEY, i2d_ECPrivateKey_bio, i2d_ECPrivateKey)
-EC_KEY *d2i_ECPrivateKey_bio(BIO *bp, EC_KEY **eckey)
-{
- return ASN1_d2i_bio_of(EC_KEY, EC_KEY_new, d2i_ECPrivateKey, bp, eckey);
-}
-
-int i2d_ECPrivateKey_bio(BIO *bp, EC_KEY *eckey)
-{
- return ASN1_i2d_bio_of_const(EC_KEY, i2d_ECPrivateKey, bp, eckey);
-}
+IMPLEMENT_D2I_BIO(EC_KEY, d2i_EC_PUBKEY_bio, d2i_EC_PUBKEY)
+IMPLEMENT_I2D_BIO(EC_KEY, i2d_EC_PUBKEY_bio, i2d_EC_PUBKEY)
int X509_pubkey_digest(const X509 *data, const EVP_MD *type,
unsigned char *md, unsigned int *len)
@@ -389,40 +341,18 @@
}
#ifndef OPENSSL_NO_FP_API
-X509_SIG *d2i_PKCS8_fp(FILE *fp, X509_SIG **p8)
-{
- return ASN1_d2i_fp_of(X509_SIG, X509_SIG_new, d2i_X509_SIG, fp, p8);
-}
-
-int i2d_PKCS8_fp(FILE *fp, X509_SIG *p8)
-{
- return ASN1_i2d_fp_of(X509_SIG, i2d_X509_SIG, fp, p8);
-}
+IMPLEMENT_D2I_FP(X509_SIG, d2i_PKCS8_fp, d2i_PKCS8_bio)
+IMPLEMENT_I2D_FP(X509_SIG, i2d_PKCS8_fp, i2d_PKCS8_bio)
#endif
-X509_SIG *d2i_PKCS8_bio(BIO *bp, X509_SIG **p8)
-{
- return ASN1_d2i_bio_of(X509_SIG, X509_SIG_new, d2i_X509_SIG, bp, p8);
-}
-
-int i2d_PKCS8_bio(BIO *bp, X509_SIG *p8)
-{
- return ASN1_i2d_bio_of(X509_SIG, i2d_X509_SIG, bp, p8);
-}
+IMPLEMENT_D2I_BIO(X509_SIG, d2i_PKCS8_bio, d2i_X509_SIG)
+IMPLEMENT_I2D_BIO(X509_SIG, i2d_PKCS8_bio, i2d_X509_SIG)
#ifndef OPENSSL_NO_FP_API
-PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp,
- PKCS8_PRIV_KEY_INFO **p8inf)
-{
- return ASN1_d2i_fp_of(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_new,
- d2i_PKCS8_PRIV_KEY_INFO, fp, p8inf);
-}
-
-int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, PKCS8_PRIV_KEY_INFO *p8inf)
-{
- return ASN1_i2d_fp_of(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO, fp,
- p8inf);
-}
+IMPLEMENT_D2I_FP(PKCS8_PRIV_KEY_INFO, d2i_PKCS8_PRIV_KEY_INFO_fp,
+ d2i_PKCS8_PRIV_KEY_INFO_bio)
+IMPLEMENT_I2D_FP(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO_fp,
+ i2d_PKCS8_PRIV_KEY_INFO_bio)
int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key)
{
@@ -436,38 +366,16 @@
return ret;
}
-int i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *pkey)
-{
- return ASN1_i2d_fp_of_const(EVP_PKEY, i2d_PrivateKey, fp, pkey);
-}
+IMPLEMENT_D2I_FP(EVP_PKEY, d2i_PrivateKey_fp, d2i_PrivateKey_bio)
+IMPLEMENT_I2D_FP(EVP_PKEY, i2d_PrivateKey_fp, i2d_PrivateKey_bio)
-EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a)
-{
- return ASN1_d2i_fp_of(EVP_PKEY, EVP_PKEY_new, d2i_AutoPrivateKey, fp, a);
-}
+IMPLEMENT_D2I_FP(EVP_PKEY, d2i_PUBKEY_fp, d2i_PUBKEY_bio)
+IMPLEMENT_I2D_FP(EVP_PKEY, i2d_PUBKEY_fp, i2d_PUBKEY_bio)
-int i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey)
-{
- return ASN1_i2d_fp_of_const(EVP_PKEY, i2d_PUBKEY, fp, pkey);
-}
-
-EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a)
-{
- return ASN1_d2i_fp_of(EVP_PKEY, EVP_PKEY_new, d2i_PUBKEY, fp, a);
-}
-
-PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp,
- PKCS8_PRIV_KEY_INFO **p8inf)
-{
- return ASN1_d2i_bio_of(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_new,
- d2i_PKCS8_PRIV_KEY_INFO, bp, p8inf);
-}
-
-int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, PKCS8_PRIV_KEY_INFO *p8inf)
-{
- return ASN1_i2d_bio_of(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO, bp,
- p8inf);
-}
+IMPLEMENT_D2I_BIO(PKCS8_PRIV_KEY_INFO, d2i_PKCS8_PRIV_KEY_INFO_bio,
+ d2i_PKCS8_PRIV_KEY_INFO)
+IMPLEMENT_I2D_BIO(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO_bio,
+ i2d_PKCS8_PRIV_KEY_INFO)
int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key)
{
@@ -482,32 +390,11 @@
}
#endif
-int i2d_PrivateKey_bio(BIO *bp, EVP_PKEY *pkey)
-{
- return ASN1_i2d_bio_of_const(EVP_PKEY, i2d_PrivateKey, bp, pkey);
-}
+IMPLEMENT_D2I_BIO(EVP_PKEY, d2i_PrivateKey_bio, d2i_AutoPrivateKey)
+IMPLEMENT_I2D_BIO(EVP_PKEY, i2d_PrivateKey_bio, i2d_PrivateKey)
-EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a)
-{
- return ASN1_d2i_bio_of(EVP_PKEY, EVP_PKEY_new, d2i_AutoPrivateKey, bp, a);
-}
+IMPLEMENT_D2I_BIO(EVP_PKEY, d2i_PUBKEY_bio, d2i_PUBKEY)
+IMPLEMENT_I2D_BIO(EVP_PKEY, i2d_PUBKEY_bio, i2d_PUBKEY)
-int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey)
-{
- return ASN1_i2d_bio_of_const(EVP_PKEY, i2d_PUBKEY, bp, pkey);
-}
-
-EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a)
-{
- return ASN1_d2i_bio_of(EVP_PKEY, EVP_PKEY_new, d2i_PUBKEY, bp, a);
-}
-
-DH *d2i_DHparams_bio(BIO *bp, DH **dh)
-{
- return ASN1_d2i_bio_of(DH, DH_new, d2i_DHparams, bp, dh);
-}
-
-int i2d_DHparams_bio(BIO *bp, const DH *dh)
-{
- return ASN1_i2d_bio_of_const(DH, i2d_DHparams, bp, dh);
-}
+IMPLEMENT_D2I_BIO(DH, d2i_DHparams_bio, d2i_DHparams)
+IMPLEMENT_I2D_BIO(const DH, i2d_DHparams_bio, i2d_DHparams)
diff --git a/src/crypto/x509v3/v3_genn.c b/src/crypto/x509v3/v3_genn.c
index 8c92687..552a524 100644
--- a/src/crypto/x509v3/v3_genn.c
+++ b/src/crypto/x509v3/v3_genn.c
@@ -100,12 +100,7 @@
IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAMES)
-GENERAL_NAME *GENERAL_NAME_dup(GENERAL_NAME *a)
-{
- return (GENERAL_NAME *)ASN1_dup((i2d_of_void *)i2d_GENERAL_NAME,
- (d2i_of_void *)d2i_GENERAL_NAME,
- (char *)a);
-}
+IMPLEMENT_ASN1_DUP_FUNCTION(GENERAL_NAME)
/* Returns 0 if they are equal, != 0 otherwise. */
int GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b)
diff --git a/src/decrepit/x509/x509_decrepit.c b/src/decrepit/x509/x509_decrepit.c
index 5714b40..28015f3 100644
--- a/src/decrepit/x509/x509_decrepit.c
+++ b/src/decrepit/x509/x509_decrepit.c
@@ -16,27 +16,7 @@
#include <openssl/x509v3.h>
-X509_EXTENSION *X509V3_EXT_conf_nid(LHASH_OF(CONF_VALUE) *conf,
- X509V3_CTX *ctx, int ext_nid, char *value) {
- CONF *nconf = NULL;
- LHASH_OF(CONF_VALUE) *orig_data = NULL;
-
- if (conf != NULL) {
- nconf = NCONF_new(NULL /* no method */);
- if (nconf == NULL) {
- return NULL;
- }
-
- orig_data = nconf->data;
- nconf->data = conf;
- }
-
- X509_EXTENSION *ret = X509V3_EXT_nconf_nid(nconf, ctx, ext_nid, value);
-
- if (nconf != NULL) {
- nconf->data = orig_data;
- NCONF_free(nconf);
- }
-
- return ret;
+X509_EXTENSION *X509V3_EXT_conf_nid(X509_MUST_BE_NULL *conf, X509V3_CTX *ctx,
+ int ext_nid, char *value) {
+ return X509V3_EXT_nconf_nid(NULL, ctx, ext_nid, value);
}
diff --git a/src/decrepit/xts/xts.c b/src/decrepit/xts/xts.c
index e3189e5..bc2a1b2 100644
--- a/src/decrepit/xts/xts.c
+++ b/src/decrepit/xts/xts.c
@@ -57,7 +57,7 @@
typedef struct xts128_context {
- void *key1, *key2;
+ AES_KEY *key1, *key2;
block128_f block1, block2;
} XTS128_CONTEXT;
@@ -186,20 +186,20 @@
// key_len is two AES keys
if (enc) {
AES_set_encrypt_key(key, ctx->key_len * 4, &xctx->ks1.ks);
- xctx->xts.block1 = (block128_f) AES_encrypt;
+ xctx->xts.block1 = AES_encrypt;
} else {
AES_set_decrypt_key(key, ctx->key_len * 4, &xctx->ks1.ks);
- xctx->xts.block1 = (block128_f) AES_decrypt;
+ xctx->xts.block1 = AES_decrypt;
}
AES_set_encrypt_key(key + ctx->key_len / 2,
ctx->key_len * 4, &xctx->ks2.ks);
- xctx->xts.block2 = (block128_f) AES_encrypt;
- xctx->xts.key1 = &xctx->ks1;
+ xctx->xts.block2 = AES_encrypt;
+ xctx->xts.key1 = &xctx->ks1.ks;
}
if (iv) {
- xctx->xts.key2 = &xctx->ks2;
+ xctx->xts.key2 = &xctx->ks2.ks;
OPENSSL_memcpy(ctx->iv, iv, 16);
}
@@ -226,16 +226,16 @@
EVP_CIPHER_CTX *out = ptr;
EVP_AES_XTS_CTX *xctx_out = out->cipher_data;
if (xctx->xts.key1) {
- if (xctx->xts.key1 != &xctx->ks1) {
+ if (xctx->xts.key1 != &xctx->ks1.ks) {
return 0;
}
- xctx_out->xts.key1 = &xctx_out->ks1;
+ xctx_out->xts.key1 = &xctx_out->ks1.ks;
}
if (xctx->xts.key2) {
- if (xctx->xts.key2 != &xctx->ks2) {
+ if (xctx->xts.key2 != &xctx->ks2.ks) {
return 0;
}
- xctx_out->xts.key2 = &xctx_out->ks2;
+ xctx_out->xts.key2 = &xctx_out->ks2.ks;
}
return 1;
} else if (type != EVP_CTRL_INIT) {
diff --git a/src/include/openssl/asn1.h b/src/include/openssl/asn1.h
index 46e5f53..8b61eaa 100644
--- a/src/include/openssl/asn1.h
+++ b/src/include/openssl/asn1.h
@@ -298,19 +298,6 @@
OPENSSL_EXPORT int fname##_print_ctx(BIO *out, stname *x, int indent, \
const ASN1_PCTX *pctx);
-#define D2I_OF(type) type *(*)(type **,const unsigned char **,long)
-#define I2D_OF(type) int (*)(type *,unsigned char **)
-#define I2D_OF_const(type) int (*)(const type *,unsigned char **)
-
-#define CHECKED_D2I_OF(type, d2i) \
- ((d2i_of_void*) (1 ? d2i : ((D2I_OF(type))0)))
-#define CHECKED_I2D_OF(type, i2d) \
- ((i2d_of_void*) (1 ? i2d : ((I2D_OF(type))0)))
-#define CHECKED_NEW_OF(type, xnew) \
- ((void *(*)(void)) (1 ? xnew : ((type *(*)(void))0)))
-#define CHECKED_PPTR_OF(type, p) \
- ((void**) (1 ? p : (type**)0))
-
typedef void *d2i_of_void(void **, const unsigned char **, long);
typedef int i2d_of_void(const void *, unsigned char **);
@@ -762,76 +749,17 @@
OPENSSL_EXPORT int ASN1_put_eoc(unsigned char **pp);
OPENSSL_EXPORT int ASN1_object_size(int constructed, int length, int tag);
-/* Used to implement other functions */
-OPENSSL_EXPORT void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x);
-
-#define ASN1_dup_of(type,i2d,d2i,x) \
- ((type*)ASN1_dup(CHECKED_I2D_OF(type, i2d), \
- CHECKED_D2I_OF(type, d2i), \
- CHECKED_PTR_OF(type, x)))
-
-#define ASN1_dup_of_const(type,i2d,d2i,x) \
- ((type*)ASN1_dup(CHECKED_I2D_OF(const type, i2d), \
- CHECKED_D2I_OF(type, d2i), \
- CHECKED_PTR_OF(const type, x)))
-
OPENSSL_EXPORT void *ASN1_item_dup(const ASN1_ITEM *it, void *x);
-/* ASN1 alloc/free macros for when a type is only used internally */
-
-#define M_ASN1_new_of(type) (type *)ASN1_item_new(ASN1_ITEM_rptr(type))
-#define M_ASN1_free_of(x, type) \
- ASN1_item_free(CHECKED_PTR_OF(type, x), ASN1_ITEM_rptr(type))
-
#ifndef OPENSSL_NO_FP_API
-OPENSSL_EXPORT void *ASN1_d2i_fp(void *(*xnew)(void), d2i_of_void *d2i, FILE *in, void **x);
-
-#define ASN1_d2i_fp_of(type,xnew,d2i,in,x) \
- ((type*)ASN1_d2i_fp(CHECKED_NEW_OF(type, xnew), \
- CHECKED_D2I_OF(type, d2i), \
- in, \
- CHECKED_PPTR_OF(type, x)))
-
OPENSSL_EXPORT void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x);
-OPENSSL_EXPORT int ASN1_i2d_fp(i2d_of_void *i2d,FILE *out,void *x);
-
-#define ASN1_i2d_fp_of(type,i2d,out,x) \
- (ASN1_i2d_fp(CHECKED_I2D_OF(type, i2d), \
- out, \
- CHECKED_PTR_OF(type, x)))
-
-#define ASN1_i2d_fp_of_const(type,i2d,out,x) \
- (ASN1_i2d_fp(CHECKED_I2D_OF(const type, i2d), \
- out, \
- CHECKED_PTR_OF(const type, x)))
-
OPENSSL_EXPORT int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x);
OPENSSL_EXPORT int ASN1_STRING_print_ex_fp(FILE *fp, ASN1_STRING *str, unsigned long flags);
#endif
OPENSSL_EXPORT int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in);
-OPENSSL_EXPORT void *ASN1_d2i_bio(void *(*xnew)(void), d2i_of_void *d2i, BIO *in, void **x);
-
-#define ASN1_d2i_bio_of(type,xnew,d2i,in,x) \
- ((type*)ASN1_d2i_bio( CHECKED_NEW_OF(type, xnew), \
- CHECKED_D2I_OF(type, d2i), \
- in, \
- CHECKED_PPTR_OF(type, x)))
-
OPENSSL_EXPORT void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x);
-OPENSSL_EXPORT int ASN1_i2d_bio(i2d_of_void *i2d,BIO *out, void *x);
-
-#define ASN1_i2d_bio_of(type,i2d,out,x) \
- (ASN1_i2d_bio(CHECKED_I2D_OF(type, i2d), \
- out, \
- CHECKED_PTR_OF(type, x)))
-
-#define ASN1_i2d_bio_of_const(type,i2d,out,x) \
- (ASN1_i2d_bio(CHECKED_I2D_OF(const type, i2d), \
- out, \
- CHECKED_PTR_OF(const type, x)))
-
OPENSSL_EXPORT int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x);
OPENSSL_EXPORT int ASN1_UTCTIME_print(BIO *fp, const ASN1_UTCTIME *a);
OPENSSL_EXPORT int ASN1_GENERALIZEDTIME_print(BIO *fp, const ASN1_GENERALIZEDTIME *a);
diff --git a/src/include/openssl/base.h b/src/include/openssl/base.h
index d134993..5a4bb66 100644
--- a/src/include/openssl/base.h
+++ b/src/include/openssl/base.h
@@ -65,6 +65,10 @@
#include <stdio.h>
#endif
+#if defined(__APPLE__)
+#include <TargetConditionals.h>
+#endif
+
// Include a BoringSSL-only header so consumers including this header without
// setting up include paths do not accidentally pick up the system
// opensslconf.h.
@@ -120,6 +124,9 @@
#if defined(__APPLE__)
#define OPENSSL_APPLE
+#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
+#define OPENSSL_IOS
+#endif
#endif
#if defined(_WIN32)
@@ -136,14 +143,36 @@
#if defined(TRUSTY)
#define OPENSSL_TRUSTY
-#define OPENSSL_NO_THREADS
+#define OPENSSL_NO_THREADS_CORRUPT_MEMORY_AND_LEAK_SECRETS_IF_THREADED
#endif
#if defined(__ANDROID_API__)
#define OPENSSL_ANDROID
#endif
-#if !defined(OPENSSL_NO_THREADS)
+// OPENSSL_NO_THREADS has been deprecated in favor of this much longer and
+// louder name, to better reflect exactly what that option did.
+//
+// TODO(davidben): Remove this block when callers have migrated.
+#if defined(OPENSSL_NO_THREADS) && \
+ !defined(OPENSSL_NO_THREADS_CORRUPT_MEMORY_AND_LEAK_SECRETS_IF_THREADED)
+#define OPENSSL_NO_THREADS_CORRUPT_MEMORY_AND_LEAK_SECRETS_IF_THREADED
+#endif
+
+// BoringSSL requires platform's locking APIs to make internal global state
+// thread-safe, including the PRNG. On some single-threaded embedded platforms,
+// locking APIs may not exist, so this dependency may be disabled with the
+// following build flag.
+//
+// IMPORTANT: Doing so means the consumer promises the library will never be
+// used in any multi-threaded context. It causes BoringSSL to be globally
+// thread-unsafe. Setting it inappropriately will subtly and unpredictably
+// corrupt memory and leak secret keys.
+//
+// Do not set this flag on any platform where threads are possible. BoringSSL
+// maintainers will not provide support for any consumers that do so. Changes
+// which break such unsupported configurations will not be reverted.
+#if !defined(OPENSSL_NO_THREADS_CORRUPT_MEMORY_AND_LEAK_SECRETS_IF_THREADED)
#define OPENSSL_THREADS
#endif
@@ -217,6 +246,35 @@
#define OPENSSL_UNUSED
#endif
+// C and C++ handle inline functions differently. In C++, an inline function is
+// defined in just the header file, potentially emitted in multiple compilation
+// units (in cases the compiler did not inline), but each copy must be identical
+// to satsify ODR. In C, a non-static inline must be manually emitted in exactly
+// one compilation unit with a separate extern inline declaration.
+//
+// In both languages, exported inline functions referencing file-local symbols
+// are problematic. C forbids this altogether (though GCC and Clang seem not to
+// enforce it). It works in C++, but ODR requires the definitions be identical,
+// including all names in the definitions resolving to the "same entity". In
+// practice, this is unlikely to be a problem, but an inline function that
+// returns a pointer to a file-local symbol
+// could compile oddly.
+//
+// Historically, we used static inline in headers. However, to satisfy ODR, use
+// plain inline in C++, to allow inline consumer functions to call our header
+// functions. Plain inline would also work better with C99 inline, but that is
+// not used much in practice, extern inline is tedious, and there are conflicts
+// with the old gnu89 model:
+// https://stackoverflow.com/questions/216510/extern-inline
+#if defined(__cplusplus)
+#define OPENSSL_INLINE inline
+#else
+// Add OPENSSL_UNUSED so that, should an inline function be emitted via macro
+// (e.g. a |STACK_OF(T)| implementation) in a source file without tripping
+// clang's -Wunused-function.
+#define OPENSSL_INLINE static inline OPENSSL_UNUSED
+#endif
+
#if defined(BORINGSSL_UNSAFE_FUZZER_MODE) && \
!defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
#define BORINGSSL_UNSAFE_DETERMINISTIC_MODE
@@ -477,16 +535,16 @@
template <typename T>
using UniquePtr = std::unique_ptr<T, internal::Deleter<T>>;
-#define BORINGSSL_MAKE_UP_REF(type, up_ref_func) \
- static inline UniquePtr<type> UpRef(type *v) { \
- if (v != nullptr) { \
- up_ref_func(v); \
- } \
- return UniquePtr<type>(v); \
- } \
- \
- static inline UniquePtr<type> UpRef(const UniquePtr<type> &ptr) { \
- return UpRef(ptr.get()); \
+#define BORINGSSL_MAKE_UP_REF(type, up_ref_func) \
+ inline UniquePtr<type> UpRef(type *v) { \
+ if (v != nullptr) { \
+ up_ref_func(v); \
+ } \
+ return UniquePtr<type>(v); \
+ } \
+ \
+ inline UniquePtr<type> UpRef(const UniquePtr<type> &ptr) { \
+ return UpRef(ptr.get()); \
}
BSSL_NAMESPACE_END
diff --git a/src/include/openssl/bio.h b/src/include/openssl/bio.h
index 70c2fbf..8e2db65 100644
--- a/src/include/openssl/bio.h
+++ b/src/include/openssl/bio.h
@@ -117,10 +117,14 @@
// return a line for this call, remove the warning above.
OPENSSL_EXPORT int BIO_gets(BIO *bio, char *buf, int size);
-// BIO_write writes |len| bytes from |data| to BIO. It returns the number of
+// BIO_write writes |len| bytes from |data| to |bio|. It returns the number of
// bytes written or a negative number on error.
OPENSSL_EXPORT int BIO_write(BIO *bio, const void *data, int len);
+// BIO_write_all writes |len| bytes from |data| to |bio|, looping as necessary.
+// It returns one if all bytes were successfully written and zero on error.
+OPENSSL_EXPORT int BIO_write_all(BIO *bio, const void *data, size_t len);
+
// BIO_puts writes a NUL terminated string from |buf| to |bio|. It returns the
// number of bytes written or a negative number on error.
OPENSSL_EXPORT int BIO_puts(BIO *bio, const char *buf);
diff --git a/src/include/openssl/conf.h b/src/include/openssl/conf.h
index 07e34ee..7aa76e1 100644
--- a/src/include/openssl/conf.h
+++ b/src/include/openssl/conf.h
@@ -60,7 +60,6 @@
#include <openssl/base.h>
#include <openssl/stack.h>
-#include <openssl/lhash.h>
#if defined(__cplusplus)
extern "C" {
@@ -85,10 +84,6 @@
char *value;
};
-struct conf_st {
- LHASH_OF(CONF_VALUE) *data;
-};
-
DEFINE_STACK_OF(CONF_VALUE)
diff --git a/src/include/openssl/cpu.h b/src/include/openssl/cpu.h
index bb847f9..b2759fe 100644
--- a/src/include/openssl/cpu.h
+++ b/src/include/openssl/cpu.h
@@ -96,7 +96,7 @@
#if defined(BORINGSSL_FIPS)
const uint32_t *OPENSSL_ia32cap_get(void);
#else
-static inline const uint32_t *OPENSSL_ia32cap_get(void) {
+OPENSSL_INLINE const uint32_t *OPENSSL_ia32cap_get(void) {
return OPENSSL_ia32cap_P;
}
#endif
@@ -119,7 +119,7 @@
// CRYPTO_is_NEON_capable returns true if the current CPU has a NEON unit. If
// this is known statically then it returns one immediately.
-static inline int CRYPTO_is_NEON_capable(void) {
+OPENSSL_INLINE int CRYPTO_is_NEON_capable(void) {
// Only statically skip the runtime lookup on aarch64. On arm, one CPU is
// known to have a broken NEON unit which is known to fail with on some
// hand-written NEON assembly. For now, continue to apply the workaround even
@@ -152,7 +152,7 @@
#else
-static inline int CRYPTO_is_NEON_capable(void) {
+OPENSSL_INLINE int CRYPTO_is_NEON_capable(void) {
#if defined(OPENSSL_STATIC_ARMCAP_NEON) || defined(__ARM_NEON__)
return 1;
#else
@@ -160,7 +160,7 @@
#endif
}
-static inline int CRYPTO_is_ARMv8_AES_capable(void) {
+OPENSSL_INLINE int CRYPTO_is_ARMv8_AES_capable(void) {
#if defined(OPENSSL_STATIC_ARMCAP_AES) || defined(__ARM_FEATURE_CRYPTO)
return 1;
#else
@@ -168,7 +168,7 @@
#endif
}
-static inline int CRYPTO_is_ARMv8_PMULL_capable(void) {
+OPENSSL_INLINE int CRYPTO_is_ARMv8_PMULL_capable(void) {
#if defined(OPENSSL_STATIC_ARMCAP_PMULL) || defined(__ARM_FEATURE_CRYPTO)
return 1;
#else
diff --git a/src/include/openssl/pem.h b/src/include/openssl/pem.h
index a43ca0d..9c0ff93 100644
--- a/src/include/openssl/pem.h
+++ b/src/include/openssl/pem.h
@@ -123,73 +123,109 @@
#else
-#define IMPLEMENT_PEM_read_fp(name, type, str, asn1) \
-OPENSSL_EXPORT type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u)\
-{ \
-return (type *)PEM_ASN1_read((d2i_of_void *)d2i_##asn1, str,fp,(void **)x,cb,u); \
-}
+#define IMPLEMENT_PEM_read_fp(name, type, str, asn1) \
+ static void *pem_read_##name##_d2i(void **x, const unsigned char **inp, \
+ long len) { \
+ return d2i_##asn1((type **)x, inp, len); \
+ } \
+ OPENSSL_EXPORT type *PEM_read_##name(FILE *fp, type **x, \
+ pem_password_cb *cb, void *u) { \
+ return (type *)PEM_ASN1_read(pem_read_##name##_d2i, str, fp, (void **)x, \
+ cb, u); \
+ }
-#define IMPLEMENT_PEM_write_fp(name, type, str, asn1) \
-OPENSSL_EXPORT int PEM_write_##name(FILE *fp, type *x) \
-{ \
-return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,x,NULL,NULL,0,NULL,NULL); \
-}
+#define IMPLEMENT_PEM_write_fp(name, type, str, asn1) \
+ static int pem_write_##name##_i2d(const void *x, unsigned char **outp) { \
+ return i2d_##asn1((type *)x, outp); \
+ } \
+ OPENSSL_EXPORT int PEM_write_##name(FILE *fp, type *x) { \
+ return PEM_ASN1_write(pem_write_##name##_i2d, str, fp, x, NULL, NULL, 0, \
+ NULL, NULL); \
+ }
-#define IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) \
-OPENSSL_EXPORT int PEM_write_##name(FILE *fp, const type *x) \
-{ \
-return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,(void *)x,NULL,NULL,0,NULL,NULL); \
-}
+#define IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) \
+ static int pem_write_##name##_i2d(const void *x, unsigned char **outp) { \
+ return i2d_##asn1((const type *)x, outp); \
+ } \
+ OPENSSL_EXPORT int PEM_write_##name(FILE *fp, const type *x) { \
+ return PEM_ASN1_write(pem_write_##name##_i2d, str, fp, (void *)x, NULL, \
+ NULL, 0, NULL, NULL); \
+ }
-#define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) \
-OPENSSL_EXPORT int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \
- unsigned char *kstr, int klen, pem_password_cb *cb, \
- void *u) \
- { \
- return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,x,enc,kstr,klen,cb,u); \
- }
+#define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) \
+ static int pem_write_##name##_i2d(const void *x, unsigned char **outp) { \
+ return i2d_##asn1((type *)x, outp); \
+ } \
+ OPENSSL_EXPORT int PEM_write_##name( \
+ FILE *fp, type *x, const EVP_CIPHER *enc, unsigned char *kstr, int klen, \
+ pem_password_cb *cb, void *u) { \
+ return PEM_ASN1_write(pem_write_##name##_i2d, str, fp, x, enc, kstr, klen, \
+ cb, u); \
+ }
-#define IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) \
-OPENSSL_EXPORT int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \
- unsigned char *kstr, int klen, pem_password_cb *cb, \
- void *u) \
- { \
- return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,x,enc,kstr,klen,cb,u); \
- }
+#define IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) \
+ static int pem_write_##name##_i2d(const void *x, unsigned char **outp) { \
+ return i2d_##asn1((const type *)x, outp); \
+ } \
+ OPENSSL_EXPORT int PEM_write_##name( \
+ FILE *fp, type *x, const EVP_CIPHER *enc, unsigned char *kstr, int klen, \
+ pem_password_cb *cb, void *u) { \
+ return PEM_ASN1_write(pem_write_##name##_i2d, str, fp, x, enc, kstr, klen, \
+ cb, u); \
+ }
#endif
-#define IMPLEMENT_PEM_read_bio(name, type, str, asn1) \
-OPENSSL_EXPORT type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u)\
-{ \
-return (type *)PEM_ASN1_read_bio((d2i_of_void *)d2i_##asn1, str,bp,(void **)x,cb,u); \
-}
+#define IMPLEMENT_PEM_read_bio(name, type, str, asn1) \
+ static void *pem_read_bio_##name##_d2i(void **x, const unsigned char **inp, \
+ long len) { \
+ return d2i_##asn1((type **)x, inp, len); \
+ } \
+ OPENSSL_EXPORT type *PEM_read_bio_##name(BIO *bp, type **x, \
+ pem_password_cb *cb, void *u) { \
+ return (type *)PEM_ASN1_read_bio(pem_read_bio_##name##_d2i, str, bp, \
+ (void **)x, cb, u); \
+ }
-#define IMPLEMENT_PEM_write_bio(name, type, str, asn1) \
-OPENSSL_EXPORT int PEM_write_bio_##name(BIO *bp, type *x) \
-{ \
-return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,x,NULL,NULL,0,NULL,NULL); \
-}
+#define IMPLEMENT_PEM_write_bio(name, type, str, asn1) \
+ static int pem_write_bio_##name##_i2d(const void *x, unsigned char **outp) { \
+ return i2d_##asn1((type *)x, outp); \
+ } \
+ OPENSSL_EXPORT int PEM_write_bio_##name(BIO *bp, type *x) { \
+ return PEM_ASN1_write_bio(pem_write_bio_##name##_i2d, str, bp, x, NULL, \
+ NULL, 0, NULL, NULL); \
+ }
-#define IMPLEMENT_PEM_write_bio_const(name, type, str, asn1) \
-OPENSSL_EXPORT int PEM_write_bio_##name(BIO *bp, const type *x) \
-{ \
-return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,(void *)x,NULL,NULL,0,NULL,NULL); \
-}
+#define IMPLEMENT_PEM_write_bio_const(name, type, str, asn1) \
+ static int pem_write_bio_##name##_i2d(const void *x, unsigned char **outp) { \
+ return i2d_##asn1((const type *)x, outp); \
+ } \
+ OPENSSL_EXPORT int PEM_write_bio_##name(BIO *bp, const type *x) { \
+ return PEM_ASN1_write_bio(pem_write_bio_##name##_i2d, str, bp, (void *)x, \
+ NULL, NULL, 0, NULL, NULL); \
+ }
-#define IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \
-OPENSSL_EXPORT int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \
- unsigned char *kstr, int klen, pem_password_cb *cb, void *u) \
- { \
- return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,x,enc,kstr,klen,cb,u); \
- }
+#define IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \
+ static int pem_write_bio_##name##_i2d(const void *x, unsigned char **outp) { \
+ return i2d_##asn1((type *)x, outp); \
+ } \
+ OPENSSL_EXPORT int PEM_write_bio_##name( \
+ BIO *bp, type *x, const EVP_CIPHER *enc, unsigned char *kstr, int klen, \
+ pem_password_cb *cb, void *u) { \
+ return PEM_ASN1_write_bio(pem_write_bio_##name##_i2d, str, bp, x, enc, \
+ kstr, klen, cb, u); \
+ }
-#define IMPLEMENT_PEM_write_cb_bio_const(name, type, str, asn1) \
-OPENSSL_EXPORT int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \
- unsigned char *kstr, int klen, pem_password_cb *cb, void *u) \
- { \
- return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,(void *)x,enc,kstr,klen,cb,u); \
- }
+#define IMPLEMENT_PEM_write_cb_bio_const(name, type, str, asn1) \
+ static int pem_write_bio_##name##_i2d(const void *x, unsigned char **outp) { \
+ return i2d_##asn1((const type *)x, outp); \
+ } \
+ OPENSSL_EXPORT int PEM_write_bio_##name( \
+ BIO *bp, type *x, const EVP_CIPHER *enc, unsigned char *kstr, int klen, \
+ pem_password_cb *cb, void *u) { \
+ return PEM_ASN1_write_bio(pem_write_bio_##name##_i2d, str, bp, (void *)x, \
+ enc, kstr, klen, cb, u); \
+ }
#define IMPLEMENT_PEM_write(name, type, str, asn1) \
IMPLEMENT_PEM_write_bio(name, type, str, asn1) \
diff --git a/src/include/openssl/ssl.h b/src/include/openssl/ssl.h
index 0d5a444..c0d44ce 100644
--- a/src/include/openssl/ssl.h
+++ b/src/include/openssl/ssl.h
@@ -3004,7 +3004,7 @@
OPENSSL_EXPORT const char *SSL_get_psk_identity(const SSL *ssl);
-// QUIC Transport Parameters.
+// QUIC transport parameters.
//
// draft-ietf-quic-tls defines a new TLS extension quic_transport_parameters
// used by QUIC for each endpoint to unilaterally declare its supported
@@ -3667,6 +3667,10 @@
OPENSSL_EXPORT void SSL_CTX_set_ignore_tls13_downgrade(SSL_CTX *ctx,
int ignore);
+// SSL_set_ignore_tls13_downgrade configures whether |ssl| ignores the downgrade
+// signal in the server's random value.
+OPENSSL_EXPORT void SSL_set_ignore_tls13_downgrade(SSL *ssl, int ignore);
+
// SSL_is_tls13_downgrade returns one if the TLS 1.3 anti-downgrade
// mechanism would have aborted |ssl|'s handshake and zero otherwise.
OPENSSL_EXPORT int SSL_is_tls13_downgrade(const SSL *ssl);
diff --git a/src/include/openssl/stack.h b/src/include/openssl/stack.h
index 15b6adf..c1bf520 100644
--- a/src/include/openssl/stack.h
+++ b/src/include/openssl/stack.h
@@ -86,10 +86,23 @@
// STACK_OF(FOO), the macros would be sk_FOO_new, sk_FOO_pop etc.
+// stack_free_func is a function that frees an element in a stack. Note its
+// actual type is void (*)(T *) for some T. Low-level |sk_*| functions will be
+// passed a type-specific wrapper to call it correctly.
+typedef void (*stack_free_func)(void *ptr);
+
+// stack_copy_func is a function that copies an element in a stack. Note its
+// actual type is T *(*)(T *) for some T. Low-level |sk_*| functions will be
+// passed a type-specific wrapper to call it correctly.
+typedef void *(*stack_copy_func)(void *ptr);
+
// stack_cmp_func is a comparison function that returns a value < 0, 0 or > 0
// if |*a| is less than, equal to or greater than |*b|, respectively. Note the
// extra indirection - the function is given a pointer to a pointer to the
// element. This differs from the usual qsort/bsearch comparison function.
+//
+// Note its actual type is int (*)(const T **, const T **). Low-level |sk_*|
+// functions will be passed a type-specific wrapper to call it correctly.
typedef int (*stack_cmp_func)(const void **a, const void **b);
// stack_st contains an array of pointers. It is not designed to be used
@@ -140,12 +153,17 @@
OPENSSL_EXPORT void *sk_set(_STACK *sk, size_t i, void *p);
// sk_free frees the given stack and array of pointers, but does nothing to
-// free the individual elements. Also see |sk_pop_free|.
+// free the individual elements. Also see |sk_pop_free_ex|.
OPENSSL_EXPORT void sk_free(_STACK *sk);
-// sk_pop_free calls |free_func| on each element in the stack and then frees
-// the stack itself.
-OPENSSL_EXPORT void sk_pop_free(_STACK *sk, void (*free_func)(void *));
+// sk_pop_free_ex calls |free_func| on each element in the stack and then frees
+// the stack itself. Note this corresponds to |sk_FOO_pop_free|. It is named
+// |sk_pop_free_ex| as a workaround for existing code calling an older version
+// of |sk_pop_free|.
+OPENSSL_EXPORT void sk_pop_free_ex(_STACK *sk,
+ void (*call_free_func)(stack_free_func,
+ void *),
+ stack_free_func free_func);
// sk_insert inserts |p| into the stack at index |where|, moving existing
// elements if needed. It returns the length of the new stack, or zero on
@@ -160,7 +178,7 @@
// sk_delete_ptr removes, at most, one instance of |p| from the stack based on
// pointer equality. If an instance of |p| is found then |p| is returned,
// otherwise it returns NULL.
-OPENSSL_EXPORT void *sk_delete_ptr(_STACK *sk, void *p);
+OPENSSL_EXPORT void *sk_delete_ptr(_STACK *sk, const void *p);
// sk_find returns the first value in the stack equal to |p|. If a comparison
// function has been set on the stack, equality is defined by it, otherwise
@@ -173,7 +191,9 @@
// Note this differs from OpenSSL. The type signature is slightly different, and
// OpenSSL's sk_find will implicitly sort |sk| if it has a comparison function
// defined.
-OPENSSL_EXPORT int sk_find(const _STACK *sk, size_t *out_index, void *p);
+OPENSSL_EXPORT int sk_find(const _STACK *sk, size_t *out_index, const void *p,
+ int (*call_cmp_func)(stack_cmp_func, const void **,
+ const void **));
// sk_shift removes and returns the first element in the stack, or returns NULL
// if the stack is empty.
@@ -207,9 +227,20 @@
// sk_deep_copy performs a copy of |sk| and of each of the non-NULL elements in
// |sk| by using |copy_func|. If an error occurs, |free_func| is used to free
// any copies already made and NULL is returned.
-OPENSSL_EXPORT _STACK *sk_deep_copy(const _STACK *sk,
- void *(*copy_func)(void *),
- void (*free_func)(void *));
+OPENSSL_EXPORT _STACK *sk_deep_copy(
+ const _STACK *sk, void *(*call_copy_func)(stack_copy_func, void *),
+ stack_copy_func copy_func, void (*call_free_func)(stack_free_func, void *),
+ stack_free_func free_func);
+
+
+// Deprecated functions.
+
+// sk_pop_free behaves like |sk_pop_free_ex| but performs an invalid function
+// pointer cast. It exists because some existing callers called |sk_pop_free|
+// directly.
+//
+// TODO(davidben): Migrate callers to bssl::UniquePtr and remove this.
+OPENSSL_EXPORT void sk_pop_free(_STACK *sk, stack_free_func free_func);
// Defining stack types.
@@ -245,113 +276,126 @@
#define BORINGSSL_DEFINE_STACK_TRAITS(name, type, is_const)
#endif
-// Stack functions must be tagged unused to support file-local stack types.
-// Clang's -Wunused-function only allows unused static inline functions if they
-// are defined in a header.
-
#define BORINGSSL_DEFINE_STACK_OF_IMPL(name, ptrtype, constptrtype) \
DECLARE_STACK_OF(name) \
\
+ typedef void (*stack_##name##_free_func)(ptrtype); \
+ typedef ptrtype (*stack_##name##_copy_func)(ptrtype); \
typedef int (*stack_##name##_cmp_func)(constptrtype *a, constptrtype *b); \
\
- static inline OPENSSL_UNUSED STACK_OF(name) * \
+ OPENSSL_INLINE void sk_##name##_call_free_func(stack_free_func free_func, \
+ void *ptr) { \
+ ((stack_##name##_free_func)free_func)((ptrtype)ptr); \
+ } \
+ \
+ OPENSSL_INLINE void *sk_##name##_call_copy_func(stack_copy_func copy_func, \
+ void *ptr) { \
+ return (void *)((stack_##name##_copy_func)copy_func)((ptrtype)ptr); \
+ } \
+ \
+ OPENSSL_INLINE int sk_##name##_call_cmp_func( \
+ stack_cmp_func cmp_func, const void **a, const void **b) { \
+ constptrtype a_ptr = (constptrtype)*a; \
+ constptrtype b_ptr = (constptrtype)*b; \
+ return ((stack_##name##_cmp_func)cmp_func)(&a_ptr, &b_ptr); \
+ } \
+ \
+ OPENSSL_INLINE STACK_OF(name) * \
sk_##name##_new(stack_##name##_cmp_func comp) { \
return (STACK_OF(name) *)sk_new((stack_cmp_func)comp); \
} \
\
- static inline OPENSSL_UNUSED STACK_OF(name) *sk_##name##_new_null(void) { \
+ OPENSSL_INLINE STACK_OF(name) *sk_##name##_new_null(void) { \
return (STACK_OF(name) *)sk_new_null(); \
} \
\
- static inline OPENSSL_UNUSED size_t sk_##name##_num( \
- const STACK_OF(name) *sk) { \
+ OPENSSL_INLINE size_t sk_##name##_num(const STACK_OF(name) *sk) { \
return sk_num((const _STACK *)sk); \
} \
\
- static inline OPENSSL_UNUSED void sk_##name##_zero(STACK_OF(name) *sk) { \
+ OPENSSL_INLINE void sk_##name##_zero(STACK_OF(name) *sk) { \
sk_zero((_STACK *)sk); \
} \
\
- static inline OPENSSL_UNUSED ptrtype sk_##name##_value( \
- const STACK_OF(name) *sk, size_t i) { \
+ OPENSSL_INLINE ptrtype sk_##name##_value(const STACK_OF(name) *sk, \
+ size_t i) { \
return (ptrtype)sk_value((const _STACK *)sk, i); \
} \
\
- static inline OPENSSL_UNUSED ptrtype sk_##name##_set(STACK_OF(name) *sk, \
- size_t i, ptrtype p) { \
+ OPENSSL_INLINE ptrtype sk_##name##_set(STACK_OF(name) *sk, size_t i, \
+ ptrtype p) { \
return (ptrtype)sk_set((_STACK *)sk, i, (void *)p); \
} \
\
- static inline OPENSSL_UNUSED void sk_##name##_free(STACK_OF(name) *sk) { \
+ OPENSSL_INLINE void sk_##name##_free(STACK_OF(name) * sk) { \
sk_free((_STACK *)sk); \
} \
\
- static inline OPENSSL_UNUSED void sk_##name##_pop_free( \
- STACK_OF(name) *sk, void (*free_func)(ptrtype p)) { \
- sk_pop_free((_STACK *)sk, (void (*)(void *))free_func); \
+ OPENSSL_INLINE void sk_##name##_pop_free( \
+ STACK_OF(name) * sk, stack_##name##_free_func free_func) { \
+ sk_pop_free_ex((_STACK *)sk, sk_##name##_call_free_func, \
+ (stack_free_func)free_func); \
} \
\
- static inline OPENSSL_UNUSED size_t sk_##name##_insert( \
- STACK_OF(name) *sk, ptrtype p, size_t where) { \
+ OPENSSL_INLINE size_t sk_##name##_insert(STACK_OF(name) *sk, ptrtype p, \
+ size_t where) { \
return sk_insert((_STACK *)sk, (void *)p, where); \
} \
\
- static inline OPENSSL_UNUSED ptrtype sk_##name##_delete(STACK_OF(name) *sk, \
- size_t where) { \
+ OPENSSL_INLINE ptrtype sk_##name##_delete(STACK_OF(name) *sk, \
+ size_t where) { \
return (ptrtype)sk_delete((_STACK *)sk, where); \
} \
\
- static inline OPENSSL_UNUSED ptrtype sk_##name##_delete_ptr( \
- STACK_OF(name) *sk, ptrtype p) { \
- return (ptrtype)sk_delete_ptr((_STACK *)sk, (void *)p); \
+ OPENSSL_INLINE ptrtype sk_##name##_delete_ptr(STACK_OF(name) *sk, \
+ constptrtype p) { \
+ return (ptrtype)sk_delete_ptr((_STACK *)sk, (const void *)p); \
} \
\
- static inline OPENSSL_UNUSED int sk_##name##_find( \
- const STACK_OF(name) *sk, size_t *out_index, ptrtype p) { \
- return sk_find((const _STACK *)sk, out_index, (void *)p); \
+ OPENSSL_INLINE int sk_##name##_find(const STACK_OF(name) *sk, \
+ size_t * out_index, constptrtype p) { \
+ return sk_find((const _STACK *)sk, out_index, (const void *)p, \
+ sk_##name##_call_cmp_func); \
} \
\
- static inline OPENSSL_UNUSED ptrtype sk_##name##_shift(STACK_OF(name) *sk) { \
+ OPENSSL_INLINE ptrtype sk_##name##_shift(STACK_OF(name) *sk) { \
return (ptrtype)sk_shift((_STACK *)sk); \
} \
\
- static inline OPENSSL_UNUSED size_t sk_##name##_push(STACK_OF(name) *sk, \
- ptrtype p) { \
+ OPENSSL_INLINE size_t sk_##name##_push(STACK_OF(name) *sk, ptrtype p) { \
return sk_push((_STACK *)sk, (void *)p); \
} \
\
- static inline OPENSSL_UNUSED ptrtype sk_##name##_pop(STACK_OF(name) *sk) { \
+ OPENSSL_INLINE ptrtype sk_##name##_pop(STACK_OF(name) *sk) { \
return (ptrtype)sk_pop((_STACK *)sk); \
} \
\
- static inline OPENSSL_UNUSED STACK_OF(name) * \
- sk_##name##_dup(const STACK_OF(name) *sk) { \
+ OPENSSL_INLINE STACK_OF(name) * sk_##name##_dup(const STACK_OF(name) *sk) { \
return (STACK_OF(name) *)sk_dup((const _STACK *)sk); \
} \
\
- static inline OPENSSL_UNUSED void sk_##name##_sort(STACK_OF(name) *sk) { \
+ OPENSSL_INLINE void sk_##name##_sort(STACK_OF(name) *sk) { \
sk_sort((_STACK *)sk); \
} \
\
- static inline OPENSSL_UNUSED int sk_##name##_is_sorted( \
- const STACK_OF(name) *sk) { \
+ OPENSSL_INLINE int sk_##name##_is_sorted(const STACK_OF(name) *sk) { \
return sk_is_sorted((const _STACK *)sk); \
} \
\
- static inline OPENSSL_UNUSED stack_##name##_cmp_func \
- sk_##name##_set_cmp_func(STACK_OF(name) *sk, \
- stack_##name##_cmp_func comp) { \
+ OPENSSL_INLINE stack_##name##_cmp_func sk_##name##_set_cmp_func( \
+ STACK_OF(name) *sk, stack_##name##_cmp_func comp) { \
return (stack_##name##_cmp_func)sk_set_cmp_func((_STACK *)sk, \
(stack_cmp_func)comp); \
} \
\
- static inline OPENSSL_UNUSED STACK_OF(name) * \
+ OPENSSL_INLINE STACK_OF(name) * \
sk_##name##_deep_copy(const STACK_OF(name) *sk, \
ptrtype(*copy_func)(ptrtype), \
void (*free_func)(ptrtype)) { \
- return (STACK_OF(name) *)sk_deep_copy((const _STACK *)sk, \
- (void *(*)(void *))copy_func, \
- (void (*)(void *))free_func); \
+ return (STACK_OF(name) *)sk_deep_copy( \
+ (const _STACK *)sk, sk_##name##_call_copy_func, \
+ (stack_copy_func)copy_func, sk_##name##_call_free_func, \
+ (stack_free_func)free_func); \
}
// DEFINE_NAMED_STACK_OF defines |STACK_OF(name)| to be a stack whose elements
@@ -410,10 +454,14 @@
struct DeleterImpl<
Stack, typename std::enable_if<!StackTraits<Stack>::kIsConst>::type> {
static void Free(Stack *sk) {
- sk_pop_free(
- reinterpret_cast<_STACK *>(sk),
- reinterpret_cast<void (*)(void *)>(
- DeleterImpl<typename StackTraits<Stack>::Type>::Free));
+ // sk_FOO_pop_free is defined by macros and bound by name, so we cannot
+ // access it from C++ here.
+ using Type = typename StackTraits<Stack>::Type;
+ sk_pop_free_ex(reinterpret_cast<_STACK *>(sk),
+ [](stack_free_func /* unused */, void *ptr) {
+ DeleterImpl<Type>::Free(reinterpret_cast<Type *>(ptr));
+ },
+ nullptr);
}
};
@@ -462,7 +510,7 @@
// PushToStack pushes |elem| to |sk|. It returns true on success and false on
// allocation failure.
template <typename Stack>
-static inline
+inline
typename std::enable_if<!internal::StackTraits<Stack>::kIsConst, bool>::type
PushToStack(Stack *sk,
UniquePtr<typename internal::StackTraits<Stack>::Type> elem) {
@@ -478,12 +526,12 @@
// Define begin() and end() for stack types so C++ range for loops work.
template <typename Stack>
-static inline bssl::internal::StackIterator<Stack> begin(const Stack *sk) {
+inline bssl::internal::StackIterator<Stack> begin(const Stack *sk) {
return bssl::internal::StackIterator<Stack>(sk, 0);
}
template <typename Stack>
-static inline bssl::internal::StackIterator<Stack> end(const Stack *sk) {
+inline bssl::internal::StackIterator<Stack> end(const Stack *sk) {
return bssl::internal::StackIterator<Stack>(
sk, sk_num(reinterpret_cast<const _STACK *>(sk)));
}
diff --git a/src/include/openssl/thread.h b/src/include/openssl/thread.h
index 98073b0..91706fe 100644
--- a/src/include/openssl/thread.h
+++ b/src/include/openssl/thread.h
@@ -66,7 +66,7 @@
#endif
-#if defined(OPENSSL_NO_THREADS)
+#if !defined(OPENSSL_THREADS)
typedef struct crypto_mutex_st {
char padding; // Empty structs have different sizes in C and C++.
} CRYPTO_MUTEX;
diff --git a/src/include/openssl/type_check.h b/src/include/openssl/type_check.h
index da78d70..e5d7047 100644
--- a/src/include/openssl/type_check.h
+++ b/src/include/openssl/type_check.h
@@ -72,10 +72,6 @@
// CHECKED_CAST casts |p| from type |from| to type |to|.
#define CHECKED_CAST(to, from, p) ((to) (1 ? (p) : (from)0))
-// CHECKED_PTR_OF casts a given pointer to void* and statically checks that it
-// was a pointer to |type|.
-#define CHECKED_PTR_OF(type, p) CHECKED_CAST(void*, type*, (p))
-
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
#define OPENSSL_COMPILE_ASSERT(cond, msg) _Static_assert(cond, #msg)
#else
diff --git a/src/include/openssl/x509v3.h b/src/include/openssl/x509v3.h
index 53e20a0..7d1c306 100644
--- a/src/include/openssl/x509v3.h
+++ b/src/include/openssl/x509v3.h
@@ -57,7 +57,6 @@
#include <openssl/bio.h>
#include <openssl/conf.h>
-#include <openssl/lhash.h>
#include <openssl/x509.h>
#ifdef __cplusplus
@@ -612,7 +611,8 @@
X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc);
OPENSSL_EXPORT void X509V3_conf_free(CONF_VALUE *val);
-OPENSSL_EXPORT X509_EXTENSION *X509V3_EXT_conf_nid(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, int ext_nid, char *value);
+typedef struct x509_must_be_null_st X509_MUST_BE_NULL;
+OPENSSL_EXPORT X509_EXTENSION *X509V3_EXT_conf_nid(X509_MUST_BE_NULL *conf, X509V3_CTX *ctx, int ext_nid, char *value);
OPENSSL_EXPORT X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid, char *value);
OPENSSL_EXPORT X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, char *name, char *value);
OPENSSL_EXPORT int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, char *section, STACK_OF(X509_EXTENSION) **sk);
@@ -620,9 +620,6 @@
OPENSSL_EXPORT int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, X509_REQ *req);
OPENSSL_EXPORT int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, X509_CRL *crl);
-OPENSSL_EXPORT int X509V3_EXT_CRL_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
- char *section, X509_CRL *crl);
-
OPENSSL_EXPORT int X509V3_add_value_bool_nf(char *name, int asn1_bool,
STACK_OF(CONF_VALUE) **extlist);
OPENSSL_EXPORT int X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool);
diff --git a/src/ssl/handshake_client.cc b/src/ssl/handshake_client.cc
index ae96bcf..e46b39f 100644
--- a/src/ssl/handshake_client.cc
+++ b/src/ssl/handshake_client.cc
@@ -600,7 +600,7 @@
.subspan(SSL3_RANDOM_SIZE - sizeof(kTLS13DowngradeRandom));
if (suffix == kTLS12DowngradeRandom || suffix == kTLS13DowngradeRandom) {
ssl->s3->tls13_downgrade = true;
- if (!ssl->ctx->ignore_tls13_downgrade) {
+ if (!hs->config->ignore_tls13_downgrade) {
OPENSSL_PUT_ERROR(SSL, SSL_R_TLS13_DOWNGRADE);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
return ssl_hs_error;
diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index 0535b8d..561b5d9 100644
--- a/src/ssl/internal.h
+++ b/src/ssl/internal.h
@@ -2456,6 +2456,10 @@
// shed_handshake_config indicates that the handshake config (this object!)
// should be freed after the handshake completes.
bool shed_handshake_config : 1;
+
+ // ignore_tls13_downgrade is whether the connection should continue when the
+ // server random signals a downgrade.
+ bool ignore_tls13_downgrade:1;
};
// From RFC 8446, used in determining PSK modes.
diff --git a/src/ssl/ssl_lib.cc b/src/ssl/ssl_lib.cc
index 13b9cac..9c16de4 100644
--- a/src/ssl/ssl_lib.cc
+++ b/src/ssl/ssl_lib.cc
@@ -693,6 +693,7 @@
ctx->signed_cert_timestamps_enabled;
ssl->config->ocsp_stapling_enabled = ctx->ocsp_stapling_enabled;
ssl->config->handoff = ctx->handoff;
+ ssl->config->ignore_tls13_downgrade = ctx->ignore_tls13_downgrade;
if (!ssl->method->ssl_new(ssl.get()) ||
!ssl->ctx->x509_method->ssl_new(ssl->s3->hs.get())) {
@@ -709,7 +710,8 @@
channel_id_enabled(false),
retain_only_sha256_of_client_certs(false),
handoff(false),
- shed_handshake_config(false) {
+ shed_handshake_config(false),
+ ignore_tls13_downgrade(false) {
assert(ssl);
}
@@ -2642,6 +2644,13 @@
ctx->ignore_tls13_downgrade = !!ignore;
}
+void SSL_set_ignore_tls13_downgrade(SSL *ssl, int ignore) {
+ if (!ssl->config) {
+ return;
+ }
+ ssl->config->ignore_tls13_downgrade = !!ignore;
+}
+
void SSL_set_shed_handshake_config(SSL *ssl, int enable) {
if (!ssl->config) {
return;
diff --git a/src/ssl/ssl_test.cc b/src/ssl/ssl_test.cc
index 894bb14..61a47d3 100644
--- a/src/ssl/ssl_test.cc
+++ b/src/ssl/ssl_test.cc
@@ -48,7 +48,7 @@
#include <sys/time.h>
#endif
-#if !defined(OPENSSL_NO_THREADS)
+#if defined(OPENSSL_THREADS)
#include <thread>
#endif
@@ -4298,7 +4298,7 @@
// These tests test multi-threaded behavior. They are intended to run with
// ThreadSanitizer.
-#if !defined(OPENSSL_NO_THREADS)
+#if defined(OPENSSL_THREADS)
TEST_P(SSLVersionTest, SessionCacheThreads) {
SSL_CTX_set_options(server_ctx_.get(), SSL_OP_NO_TICKET);
SSL_CTX_set_session_cache_mode(client_ctx_.get(), SSL_SESS_CACHE_BOTH);
diff --git a/src/ssl/ssl_x509.cc b/src/ssl/ssl_x509.cc
index 9fa800f..ec203b2 100644
--- a/src/ssl/ssl_x509.cc
+++ b/src/ssl/ssl_x509.cc
@@ -999,17 +999,25 @@
return 1;
}
-static SSL_SESSION *ssl_session_new_with_crypto_x509(void) {
- return ssl_session_new(&ssl_crypto_x509_method).release();
-}
-
SSL_SESSION *d2i_SSL_SESSION_bio(BIO *bio, SSL_SESSION **out) {
- return ASN1_d2i_bio_of(SSL_SESSION, ssl_session_new_with_crypto_x509,
- d2i_SSL_SESSION, bio, out);
+ uint8_t *data;
+ size_t len;
+ if (!BIO_read_asn1(bio, &data, &len, 1024 * 1024)) {
+ return 0;
+ }
+ bssl::UniquePtr<uint8_t> free_data(data);
+ const uint8_t *ptr = data;
+ return d2i_SSL_SESSION(out, &ptr, static_cast<long>(len));
}
int i2d_SSL_SESSION_bio(BIO *bio, const SSL_SESSION *session) {
- return ASN1_i2d_bio_of(SSL_SESSION, i2d_SSL_SESSION, bio, session);
+ uint8_t *data;
+ size_t len;
+ if (!SSL_SESSION_to_bytes(session, &data, &len)) {
+ return 0;
+ }
+ bssl::UniquePtr<uint8_t> free_data(data);
+ return BIO_write_all(bio, data, len);
}
IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION)
diff --git a/src/ssl/test/runner/runner.go b/src/ssl/test/runner/runner.go
index 4bcf603..9631e6e 100644
--- a/src/ssl/test/runner/runner.go
+++ b/src/ssl/test/runner/runner.go
@@ -5891,59 +5891,65 @@
})
// Test TLS 1.3's downgrade signal.
- testCases = append(testCases, testCase{
- name: "Downgrade-TLS12-Client",
- config: Config{
- Bugs: ProtocolBugs{
- NegotiateVersion: VersionTLS12,
- },
- },
- tls13Variant: TLS13RFC,
- expectedVersion: VersionTLS12,
- shouldFail: true,
- expectedError: ":TLS13_DOWNGRADE:",
- expectedLocalError: "remote error: illegal parameter",
- })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "Downgrade-TLS12-Server",
- config: Config{
- Bugs: ProtocolBugs{
- SendSupportedVersions: []uint16{VersionTLS12},
- },
- },
- tls13Variant: TLS13RFC,
- expectedVersion: VersionTLS12,
- shouldFail: true,
- expectedLocalError: "tls: downgrade from TLS 1.3 detected",
- })
+ var downgradeTests = []struct {
+ name string
+ version uint16
+ clientShimError string
+ }{
+ {"TLS12", VersionTLS12, "tls: downgrade from TLS 1.3 detected"},
+ {"TLS11", VersionTLS11, "tls: downgrade from TLS 1.2 detected"},
+ // TLS 1.0 does not have a dedicated value.
+ {"TLS10", VersionTLS10, "tls: downgrade from TLS 1.2 detected"},
+ }
- testCases = append(testCases, testCase{
- name: "Downgrade-TLS11-Client",
- config: Config{
- Bugs: ProtocolBugs{
- NegotiateVersion: VersionTLS11,
+ for _, test := range downgradeTests {
+ // The client should enforce the downgrade sentinel.
+ testCases = append(testCases, testCase{
+ name: "Downgrade-" + test.name + "-Client",
+ config: Config{
+ Bugs: ProtocolBugs{
+ NegotiateVersion: test.version,
+ },
},
- },
- tls13Variant: TLS13RFC,
- expectedVersion: VersionTLS11,
- shouldFail: true,
- expectedError: ":TLS13_DOWNGRADE:",
- expectedLocalError: "remote error: illegal parameter",
- })
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: "Downgrade-TLS11-Server",
- config: Config{
- Bugs: ProtocolBugs{
- SendSupportedVersions: []uint16{VersionTLS11},
+ tls13Variant: TLS13RFC,
+ expectedVersion: test.version,
+ shouldFail: true,
+ expectedError: ":TLS13_DOWNGRADE:",
+ expectedLocalError: "remote error: illegal parameter",
+ })
+
+ // The client should ignore the downgrade sentinel if
+ // configured.
+ testCases = append(testCases, testCase{
+ name: "Downgrade-" + test.name + "-Client-Ignore",
+ config: Config{
+ Bugs: ProtocolBugs{
+ NegotiateVersion: test.version,
+ },
},
- },
- tls13Variant: TLS13RFC,
- expectedVersion: VersionTLS11,
- shouldFail: true,
- expectedLocalError: "tls: downgrade from TLS 1.2 detected",
- })
+ tls13Variant: TLS13RFC,
+ expectedVersion: test.version,
+ flags: []string{
+ "-ignore-tls13-downgrade",
+ "-expect-tls13-downgrade",
+ },
+ })
+
+ // The server should emit the downgrade signal.
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "Downgrade-" + test.name + "-Server",
+ config: Config{
+ Bugs: ProtocolBugs{
+ SendSupportedVersions: []uint16{test.version},
+ },
+ },
+ tls13Variant: TLS13RFC,
+ expectedVersion: test.version,
+ shouldFail: true,
+ expectedLocalError: test.clientShimError,
+ })
+ }
// Test that the draft TLS 1.3 variants don't trigger the downgrade logic.
testCases = append(testCases, testCase{
diff --git a/src/util/fipstools/fipscommon/ar.go b/src/util/ar/ar.go
similarity index 79%
rename from src/util/fipstools/fipscommon/ar.go
rename to src/util/ar/ar.go
index 85b378d..f5dee62 100644
--- a/src/util/fipstools/fipscommon/ar.go
+++ b/src/util/ar/ar.go
@@ -14,11 +14,12 @@
// ar.go contains functions for parsing .a archive files.
-package fipscommon
+package ar
import (
"bytes"
"errors"
+ "fmt"
"io"
"strconv"
"strings"
@@ -113,6 +114,33 @@
name = strings.TrimRight(name, "/")
}
+ // Post-processing for BSD:
+ // https://en.wikipedia.org/wiki/Ar_(Unix)#BSD_variant
+ //
+ // If the name is of the form #1/XXX, XXX identifies the length of the
+ // name, and the name itself is stored as a prefix of the data, possibly
+ // null-padded.
+
+ var namelen uint
+ n, err := fmt.Sscanf(name, "#1/%d", &namelen)
+ if err == nil && n == 1 && len(contents) >= int(namelen) {
+ name = string(contents[:namelen])
+ contents = contents[namelen:]
+
+ // Names can be null padded; find the first null (if any). Note that
+ // this also handles the case of a null followed by non-null
+ // characters. It's not clear whether those can ever show up in
+ // practice, but we might as well handle them in case they can show
+ // up.
+ var null int
+ for ; null < len(name); null++ {
+ if name[null] == 0 {
+ break
+ }
+ }
+ name = name[:null]
+ }
+
ret[name] = contents
}
diff --git a/src/util/fipstools/delocate/delocate.go b/src/util/fipstools/delocate/delocate.go
index a8c4fd0..4734285 100644
--- a/src/util/fipstools/delocate/delocate.go
+++ b/src/util/fipstools/delocate/delocate.go
@@ -26,6 +26,7 @@
"strconv"
"strings"
+ "boringssl.googlesource.com/boringssl/util/ar"
"boringssl.googlesource.com/boringssl/util/fipstools/fipscommon"
)
@@ -1425,7 +1426,7 @@
}
defer arFile.Close()
- ar, err := fipscommon.ParseAR(arFile)
+ ar, err := ar.ParseAR(arFile)
if err != nil {
return err
}
diff --git a/src/util/fipstools/inject-hash/inject-hash.go b/src/util/fipstools/inject_hash/inject_hash.go
similarity index 96%
rename from src/util/fipstools/inject-hash/inject-hash.go
rename to src/util/fipstools/inject_hash/inject_hash.go
index 14418a3..29307c0 100644
--- a/src/util/fipstools/inject-hash/inject-hash.go
+++ b/src/util/fipstools/inject_hash/inject_hash.go
@@ -12,7 +12,7 @@
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
-// inject-hash parses an archive containing a file object file. It finds a FIPS
+// inject_hash parses an archive containing a file object file. It finds a FIPS
// module inside that object, calculates its hash and replaces the default hash
// value in the object with the calculated value.
package main
@@ -29,6 +29,7 @@
"io/ioutil"
"os"
+ "boringssl.googlesource.com/boringssl/util/ar"
"boringssl.googlesource.com/boringssl/util/fipstools/fipscommon"
)
@@ -45,7 +46,7 @@
}
defer arFile.Close()
- ar, err := fipscommon.ParseAR(arFile)
+ ar, err := ar.ParseAR(arFile)
if err != nil {
return err
}
diff --git a/src/util/read_symbols.go b/src/util/read_symbols.go
new file mode 100644
index 0000000..5e3a177
--- /dev/null
+++ b/src/util/read_symbols.go
@@ -0,0 +1,170 @@
+// Copyright (c) 2018, 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.
+
+// read_symbols.go scans one or more .a files and, for each object contained in
+// the .a files, reads the list of symbols in that object file.
+package main
+
+import (
+ "bytes"
+ "debug/elf"
+ "debug/macho"
+ "flag"
+ "fmt"
+ "os"
+ "runtime"
+ "sort"
+ "strings"
+
+ "boringssl.googlesource.com/boringssl/util/ar"
+)
+
+const (
+ ObjFileFormatELF = "elf"
+ ObjFileFormatMachO = "macho"
+)
+
+var outFlag = flag.String("out", "-", "File to write output symbols")
+var objFileFormat = flag.String("obj-file-format", defaultObjFileFormat(runtime.GOOS), "Object file format to expect (options are elf, macho)")
+
+func defaultObjFileFormat(goos string) string {
+ switch goos {
+ case "linux":
+ return ObjFileFormatELF
+ case "darwin":
+ return ObjFileFormatMachO
+ default:
+ // By returning a value here rather than panicking, the user can still
+ // cross-compile from an unsupported platform to a supported platform by
+ // overriding this default with a flag. If the user doesn't provide the
+ // flag, we will panic during flag parsing.
+ return "unsupported"
+ }
+}
+
+func main() {
+ flag.Parse()
+ if flag.NArg() < 1 {
+ fmt.Fprintf(os.Stderr, "Usage: %s [-out OUT] [-obj-file-format FORMAT] ARCHIVE_FILE [ARCHIVE_FILE [...]]\n", os.Args[0])
+ os.Exit(1)
+ }
+ archiveFiles := flag.Args()
+
+ out := os.Stdout
+ if *outFlag != "-" {
+ var err error
+ out, err = os.Create(*outFlag)
+ nilOrPanic(err, "failed to open output file")
+ defer out.Close()
+ }
+
+ var symbols []string
+ // Only add first instance of any symbol; keep track of them in this map.
+ added := make(map[string]bool)
+ for _, archive := range archiveFiles {
+ f, err := os.Open(archive)
+ nilOrPanic(err, "failed to open archive file %s", archive)
+ objectFiles, err := ar.ParseAR(f)
+ nilOrPanic(err, "failed to read archive file %s", archive)
+
+ for name, contents := range objectFiles {
+ if !strings.HasSuffix(name, ".o") {
+ continue
+ }
+ for _, s := range listSymbols(name, contents) {
+ if !added[s] {
+ added[s] = true
+ symbols = append(symbols, s)
+ }
+ }
+ }
+ }
+ sort.Strings(symbols)
+ for _, s := range symbols {
+ // Filter out C++ mangled names.
+ prefix := "_Z"
+ if runtime.GOOS == "darwin" {
+ prefix = "__Z"
+ }
+ if !strings.HasPrefix(s, prefix) {
+ fmt.Fprintln(out, s)
+ }
+ }
+}
+
+// listSymbols lists the exported symbols from an object file.
+func listSymbols(name string, contents []byte) []string {
+ switch *objFileFormat {
+ case ObjFileFormatELF:
+ return listSymbolsELF(name, contents)
+ case ObjFileFormatMachO:
+ return listSymbolsMachO(name, contents)
+ default:
+ panic(fmt.Errorf("unsupported object file format %v", *objFileFormat))
+ }
+}
+
+func listSymbolsELF(name string, contents []byte) []string {
+ f, err := elf.NewFile(bytes.NewReader(contents))
+ nilOrPanic(err, "failed to parse ELF file %s", name)
+ syms, err := f.Symbols()
+ nilOrPanic(err, "failed to read symbol names from ELF file %s", name)
+
+ var names []string
+ for _, sym := range syms {
+ // Only include exported, defined symbols
+ if elf.ST_BIND(sym.Info) != elf.STB_LOCAL && sym.Section != elf.SHN_UNDEF {
+ names = append(names, sym.Name)
+ }
+ }
+ return names
+}
+
+func listSymbolsMachO(name string, contents []byte) []string {
+ f, err := macho.NewFile(bytes.NewReader(contents))
+ nilOrPanic(err, "failed to parse Mach-O file %s", name)
+ if f.Symtab == nil {
+ return nil
+ }
+ var names []string
+ for _, sym := range f.Symtab.Syms {
+ // Source: https://opensource.apple.com/source/xnu/xnu-3789.51.2/EXTERNAL_HEADERS/mach-o/nlist.h.auto.html
+ const (
+ N_PEXT uint8 = 0x10 // Private external symbol bit
+ N_EXT uint8 = 0x01 // External symbol bit, set for external symbols
+ N_TYPE uint8 = 0x0e // mask for the type bits
+
+ N_UNDF uint8 = 0x0 // undefined, n_sect == NO_SECT
+ N_ABS uint8 = 0x2 // absolute, n_sect == NO_SECT
+ N_SECT uint8 = 0xe // defined in section number n_sect
+ N_PBUD uint8 = 0xc // prebound undefined (defined in a dylib)
+ N_INDR uint8 = 0xa // indirect
+ )
+
+ // Only include exported, defined symbols.
+ if sym.Type&N_EXT != 0 && sym.Type&N_TYPE != N_UNDF {
+ if len(sym.Name) == 0 || sym.Name[0] != '_' {
+ panic(fmt.Errorf("unexpected symbol without underscore prefix: %v", sym.Name))
+ }
+ names = append(names, sym.Name[1:])
+ }
+ }
+ return names
+}
+
+func nilOrPanic(err error, f string, args ...interface{}) {
+ if err != nil {
+ panic(fmt.Errorf(f+": %v", append(args, err)...))
+ }
+}