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/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)