summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPrimiano Tucci <primiano@google.com>2014-09-30 14:46:28 +0100
committerPrimiano Tucci <primiano@google.com>2014-09-30 14:46:28 +0100
commit7c4e52cd7aebb9f2fa64355c58bc75509685da94 (patch)
treebbdd45cda3f7f15eae3f9dfa9ac4d6a604d82479
parent208436baefdf6180355219406c666c259c7fc450 (diff)
parent885164b8d921ef7dba08b9e5ae031bf7350bf4ff (diff)
downloadsrc-lollipop-mr1-wfc-release.tar.gz
This commit was generated by merge_to_master.py. Change-Id: I9b1c013632df72dcd4e450d6a3b7749444191f77
-rw-r--r--crypto/CMakeLists.txt3
-rw-r--r--crypto/asn1/a_strnid.c4
-rw-r--r--crypto/base64/base64.c103
-rw-r--r--crypto/base64/base64_test.c52
-rw-r--r--crypto/bio/bio.c4
-rw-r--r--crypto/bio/bio_mem.c7
-rw-r--r--crypto/bio/bio_test.c8
-rw-r--r--crypto/bio/internal.h2
-rw-r--r--crypto/bio/socket_helper.c2
-rw-r--r--crypto/bn/bn_test.c7
-rw-r--r--crypto/bn/rsaz_exp.h2
-rw-r--r--crypto/bytestring/CMakeLists.txt1
-rw-r--r--crypto/bytestring/ber.c215
-rw-r--r--crypto/bytestring/bytestring_test.c169
-rw-r--r--crypto/bytestring/cbs.c124
-rw-r--r--crypto/bytestring/internal.h46
-rw-r--r--crypto/chacha/chacha_generic.c4
-rw-r--r--crypto/chacha/chacha_vec_arm.S4
-rw-r--r--crypto/cipher/CMakeLists.txt1
-rw-r--r--crypto/cipher/aead_test.c3
-rw-r--r--crypto/cipher/cipher.c15
-rw-r--r--crypto/cipher/cipher_error.c2
-rw-r--r--crypto/cipher/cipher_test.c5
-rw-r--r--crypto/cipher/e_aes.c22
-rw-r--r--crypto/cipher/e_chacha20poly1305.c4
-rw-r--r--crypto/cipher/e_rc2.c421
-rw-r--r--crypto/cipher/e_rc4.c2
-rw-r--r--crypto/conf/conf.c2
-rw-r--r--crypto/cpu-arm.c4
-rw-r--r--crypto/cpu-intel.c15
-rw-r--r--crypto/crypto.c68
-rw-r--r--crypto/dh/dh_test.c3
-rw-r--r--crypto/digest/digest.c4
-rw-r--r--crypto/digest/digests.c19
-rw-r--r--crypto/dsa/dsa.c33
-rw-r--r--crypto/dsa/dsa_test.c3
-rw-r--r--crypto/ec/ec.c10
-rw-r--r--crypto/ec/ec_error.c1
-rw-r--r--crypto/ec/example_mul.c7
-rw-r--r--crypto/ec/internal.h2
-rw-r--r--crypto/ec/wnaf.c2
-rw-r--r--crypto/ecdsa/ecdsa.c5
-rw-r--r--crypto/ecdsa/ecdsa_test.c6
-rw-r--r--crypto/engine/engine.c2
-rw-r--r--crypto/err/err.c10
-rw-r--r--crypto/err/err_test.c15
-rw-r--r--crypto/evp/evp.c6
-rw-r--r--crypto/evp/example_sign.c17
-rw-r--r--crypto/ex_data.c2
-rw-r--r--crypto/ex_data_impl.c2
-rw-r--r--crypto/hmac/hmac_test.c3
-rw-r--r--crypto/internal.h23
-rw-r--r--crypto/lhash/lhash_test.c9
-rw-r--r--crypto/md4/CMakeLists.txt9
-rw-r--r--crypto/md4/md4.c222
-rw-r--r--crypto/md5/md5_test.c5
-rw-r--r--crypto/modes/gcm.c37
-rw-r--r--crypto/modes/gcm_test.c5
-rw-r--r--crypto/modes/internal.h9
-rw-r--r--crypto/obj/obj.c4
-rw-r--r--crypto/obj/obj_dat.h (renamed from include/openssl/obj_dat.h)0
-rw-r--r--crypto/pem/pem_all.c4
-rw-r--r--crypto/pem/pem_info.c2
-rw-r--r--crypto/pem/pem_pkey.c2
-rwxr-xr-xcrypto/perlasm/x86_64-xlate.pl2
-rw-r--r--crypto/pkcs8/CMakeLists.txt8
-rw-r--r--crypto/pkcs8/p8_pkey.c33
-rw-r--r--crypto/pkcs8/pkcs12_test.c763
-rw-r--r--crypto/pkcs8/pkcs8.c575
-rw-r--r--crypto/pkcs8/pkcs8_error.c15
-rw-r--r--crypto/poly1305/poly1305.c8
-rw-r--r--crypto/poly1305/poly1305_arm.c5
-rw-r--r--crypto/poly1305/poly1305_arm_asm.S4
-rw-r--r--crypto/rand/urandom.c2
-rw-r--r--crypto/rsa/rsa_test.c9
-rw-r--r--crypto/sha/sha1_test.c7
-rw-r--r--crypto/sha/sha512.c36
-rw-r--r--crypto/x509/pkcs7.c71
-rw-r--r--crypto/x509/pkcs7_test.c82
-rw-r--r--crypto/x509/x509_cmp.c26
-rw-r--r--crypto/x509/x509_req.c4
-rw-r--r--crypto/x509/x509spki.c14
-rw-r--r--crypto/x509/x_all.c2
-rw-r--r--crypto/x509/x_crl.c2
-rw-r--r--crypto/x509/x_pubkey.c2
-rw-r--r--crypto/x509v3/tabtest.c4
-rw-r--r--crypto/x509v3/v3_purp.c2
-rw-r--r--crypto/x509v3/v3nametest.c5
-rw-r--r--include/openssl/aead.h8
-rw-r--r--include/openssl/base.h11
-rw-r--r--include/openssl/base64.h21
-rw-r--r--include/openssl/bio.h4
-rw-r--r--include/openssl/bn.h4
-rw-r--r--include/openssl/bytestring.h31
-rw-r--r--include/openssl/cipher.h13
-rw-r--r--include/openssl/conf.h2
-rw-r--r--include/openssl/cpu.h4
-rw-r--r--include/openssl/crypto.h28
-rw-r--r--include/openssl/digest.h5
-rw-r--r--include/openssl/dsa.h8
-rw-r--r--include/openssl/ec.h10
-rw-r--r--include/openssl/engine.h2
-rw-r--r--include/openssl/err.h8
-rw-r--r--include/openssl/evp.h6
-rw-r--r--include/openssl/md4.h105
-rw-r--r--include/openssl/md5.h2
-rw-r--r--include/openssl/opensslfeatures.h1
-rw-r--r--include/openssl/pem.h6
-rw-r--r--include/openssl/pkcs8.h81
-rw-r--r--include/openssl/pqueue.h23
-rw-r--r--include/openssl/rand.h2
-rw-r--r--include/openssl/srtp.h14
-rw-r--r--include/openssl/ssl.h181
-rw-r--r--include/openssl/ssl3.h22
-rw-r--r--include/openssl/tls1.h26
-rw-r--r--include/openssl/x509.h12
-rw-r--r--ssl/CMakeLists.txt2
-rw-r--r--ssl/d1_both.c13
-rw-r--r--ssl/d1_clnt.c7
-rw-r--r--ssl/d1_enc.c5
-rw-r--r--ssl/d1_srtp.c36
-rw-r--r--ssl/d1_srvr.c39
-rw-r--r--ssl/pqueue/CMakeLists.txt8
-rw-r--r--ssl/pqueue/pqueue.c18
-rw-r--r--ssl/pqueue/pqueue_test.c91
-rw-r--r--ssl/s23_clnt.c74
-rw-r--r--ssl/s23_meth.c2
-rw-r--r--ssl/s3_both.c114
-rw-r--r--ssl/s3_cbc.c82
-rw-r--r--ssl/s3_clnt.c205
-rw-r--r--ssl/s3_enc.c13
-rw-r--r--ssl/s3_lib.c201
-rw-r--r--ssl/s3_pkt.c30
-rw-r--r--ssl/s3_srvr.c290
-rw-r--r--ssl/ssl_algs.c6
-rw-r--r--ssl/ssl_asn1.c55
-rw-r--r--ssl/ssl_cert.c20
-rw-r--r--ssl/ssl_ciph.c252
-rw-r--r--ssl/ssl_error.c9
-rw-r--r--ssl/ssl_lib.c270
-rw-r--r--ssl/ssl_locl.h72
-rw-r--r--ssl/ssl_sess.c49
-rw-r--r--ssl/ssl_stat.c8
-rw-r--r--ssl/ssl_test.c263
-rw-r--r--ssl/t1_enc.c34
-rw-r--r--ssl/t1_lib.c478
-rw-r--r--ssl/test/bssl_shim.cc114
-rw-r--r--ssl/test/runner/channel_id_key.pem5
-rw-r--r--ssl/test/runner/cipher_suites.go46
-rw-r--r--ssl/test/runner/common.go84
-rw-r--r--ssl/test/runner/conn.go10
-rw-r--r--ssl/test/runner/handshake_client.go116
-rw-r--r--ssl/test/runner/handshake_messages.go195
-rw-r--r--ssl/test/runner/handshake_server.go119
-rw-r--r--ssl/test/runner/key_agreement.go2
-rw-r--r--ssl/test/runner/prf.go66
-rw-r--r--ssl/test/runner/runner.go587
-rw-r--r--ssl/test/runner/ticket.go33
-rw-r--r--ssl/test/test_config.cc54
-rw-r--r--ssl/test/test_config.h10
-rw-r--r--tool/CMakeLists.txt1
-rw-r--r--tool/client.cc11
-rw-r--r--tool/pkcs12.cc125
-rw-r--r--tool/tool.cc7
-rw-r--r--util/all_tests.sh18
-rw-r--r--util/doc.config62
166 files changed, 6144 insertions, 2392 deletions
diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt
index cbfcd73..5d656ec 100644
--- a/crypto/CMakeLists.txt
+++ b/crypto/CMakeLists.txt
@@ -71,6 +71,7 @@ add_subdirectory(bytestring)
# Level 0.2 - depends on nothing but itself
add_subdirectory(sha)
+add_subdirectory(md4)
add_subdirectory(md5)
add_subdirectory(modes)
add_subdirectory(aes)
@@ -112,6 +113,7 @@ add_library(
crypto
STATIC
+ crypto.c
crypto_error.c
mem.c
thread.c
@@ -129,6 +131,7 @@ add_library(
$<TARGET_OBJECTS:base64>
$<TARGET_OBJECTS:bytestring>
$<TARGET_OBJECTS:sha>
+ $<TARGET_OBJECTS:md4>
$<TARGET_OBJECTS:md5>
$<TARGET_OBJECTS:digest>
$<TARGET_OBJECTS:cipher>
diff --git a/crypto/asn1/a_strnid.c b/crypto/asn1/a_strnid.c
index ded339a..e61de70 100644
--- a/crypto/asn1/a_strnid.c
+++ b/crypto/asn1/a_strnid.c
@@ -251,7 +251,8 @@ static void st_free(ASN1_STRING_TABLE *tbl)
#ifdef STRING_TABLE_TEST
-main()
+int
+main(void)
{
ASN1_STRING_TABLE *tmp;
int i, last_nid = -1;
@@ -278,6 +279,7 @@ main()
printf("Index %d, NID %d, Name=%s\n", i, tmp->nid,
OBJ_nid2ln(tmp->nid));
+ return 0;
}
#endif
diff --git a/crypto/base64/base64.c b/crypto/base64/base64.c
index 2336cf5..5fe23a5 100644
--- a/crypto/base64/base64.c
+++ b/crypto/base64/base64.c
@@ -64,8 +64,6 @@ static const unsigned char data_bin2ascii[65] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
#define conv_bin2ascii(a) (data_bin2ascii[(a) & 0x3f])
-/* TODO(davidben): This doesn't error on bytes above 127. */
-#define conv_ascii2bin(a) (data_ascii2bin[(a) & 0x7f])
/* 64 char lines
* pad input with 0
@@ -91,13 +89,13 @@ static const unsigned char data_bin2ascii[65] =
#define B64_ERROR 0xFF
#define B64_NOT_BASE64(a) (((a) | 0x13) == 0xF3)
-static const unsigned char data_ascii2bin[128] = {
+static const uint8_t data_ascii2bin[128] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xF0, 0xFF,
0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xF2, 0xFF, 0x3F,
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0xFF, 0xFF,
- 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12,
0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
@@ -105,6 +103,13 @@ static const unsigned char data_ascii2bin[128] = {
0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
};
+static uint8_t conv_ascii2bin(uint8_t a) {
+ if (a >= 128) {
+ return 0xFF;
+ }
+ return data_ascii2bin[a];
+}
+
void EVP_EncodeInit(EVP_ENCODE_CTX *ctx) {
ctx->length = 48;
ctx->num = 0;
@@ -200,6 +205,62 @@ size_t EVP_EncodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) {
return ret;
}
+int EVP_DecodedLength(size_t *out_len, size_t len) {
+ if (len % 4 != 0) {
+ return 0;
+ }
+ *out_len = (len / 4) * 3;
+ return 1;
+}
+
+int EVP_DecodeBase64(uint8_t *out, size_t *out_len, size_t max_out,
+ const uint8_t *in, size_t in_len) {
+ uint8_t a, b, c, d;
+ size_t pad_len = 0, len = 0, max_len, i;
+ uint32_t l;
+
+ if (!EVP_DecodedLength(&max_len, in_len) || max_out < max_len) {
+ return 0;
+ }
+
+ for (i = 0; i < in_len; i += 4) {
+ a = conv_ascii2bin(*(in++));
+ b = conv_ascii2bin(*(in++));
+ if (i + 4 == in_len && in[1] == '=') {
+ if (in[0] == '=') {
+ pad_len = 2;
+ } else {
+ pad_len = 1;
+ }
+ }
+ if (pad_len < 2) {
+ c = conv_ascii2bin(*(in++));
+ } else {
+ c = 0;
+ }
+ if (pad_len < 1) {
+ d = conv_ascii2bin(*(in++));
+ } else {
+ d = 0;
+ }
+ if ((a & 0x80) || (b & 0x80) || (c & 0x80) || (d & 0x80)) {
+ return 0;
+ }
+ l = ((((uint32_t)a) << 18L) | (((uint32_t)b) << 12L) |
+ (((uint32_t)c) << 6L) | (((uint32_t)d)));
+ *(out++) = (uint8_t)(l >> 16L) & 0xff;
+ if (pad_len < 2) {
+ *(out++) = (uint8_t)(l >> 8L) & 0xff;
+ }
+ if (pad_len < 1) {
+ *(out++) = (uint8_t)(l) & 0xff;
+ }
+ len += 3 - pad_len;
+ }
+ *out_len = len;
+ return 1;
+}
+
void EVP_DecodeInit(EVP_ENCODE_CTX *ctx) {
ctx->length = 30;
ctx->num = 0;
@@ -304,6 +365,7 @@ int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len,
exp_nl = 1;
}
if (n > 0) {
+ /* TODO(davidben): Switch this to EVP_DecodeBase64. */
v = EVP_DecodeBlock(out, d, n);
n = 0;
if (v < 0) {
@@ -347,6 +409,7 @@ int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *outl) {
*outl = 0;
if (ctx->num != 0) {
+ /* TODO(davidben): Switch this to EVP_DecodeBase64. */
i = EVP_DecodeBlock(out, ctx->enc_data, ctx->num);
if (i < 0) {
return -1;
@@ -360,9 +423,7 @@ int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *outl) {
}
int EVP_DecodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) {
- int a, b, c, d;
- uint32_t l;
- size_t i, ret = 0;
+ size_t dst_len;
/* trim white space from the start of the line. */
while (conv_ascii2bin(*src) == B64_WS && src_len > 0) {
@@ -376,31 +437,21 @@ int EVP_DecodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) {
src_len--;
}
- if (src_len % 4 != 0) {
+ if (!EVP_DecodedLength(&dst_len, src_len) || dst_len > INT_MAX) {
return -1;
}
-
- for (i = 0; i < src_len; i += 4) {
- a = conv_ascii2bin(*(src++));
- b = conv_ascii2bin(*(src++));
- c = conv_ascii2bin(*(src++));
- d = conv_ascii2bin(*(src++));
- if ((a & 0x80) || (b & 0x80) || (c & 0x80) || (d & 0x80)) {
- return -1;
- }
- l = ((((uint32_t)a) << 18L) | (((uint32_t)b) << 12L) |
- (((uint32_t)c) << 6L) | (((uint32_t)d)));
- *(dst++) = (uint8_t)(l >> 16L) & 0xff;
- *(dst++) = (uint8_t)(l >> 8L) & 0xff;
- *(dst++) = (uint8_t)(l) & 0xff;
- ret += 3;
+ if (!EVP_DecodeBase64(dst, &dst_len, dst_len, src, src_len)) {
+ return -1;
}
- if (ret > INT_MAX) {
- return -1;
+ /* EVP_DecodeBlock does not take padding into account, so put the
+ * NULs back in... so the caller can strip them back out. */
+ while (dst_len % 3 != 0) {
+ dst[dst_len++] = '\0';
}
+ assert(dst_len <= INT_MAX);
- return ret;
+ return dst_len;
}
int EVP_EncodedLength(size_t *out_len, size_t len) {
diff --git a/crypto/base64/base64_test.c b/crypto/base64/base64_test.c
index 0cd2b6e..e208e81 100644
--- a/crypto/base64/base64_test.c
+++ b/crypto/base64/base64_test.c
@@ -16,6 +16,7 @@
#include <string.h>
#include <openssl/base64.h>
+#include <openssl/crypto.h>
#include <openssl/err.h>
@@ -37,7 +38,7 @@ static const TEST_VECTOR test_vectors[] = {
static const size_t kNumTests = sizeof(test_vectors) / sizeof(test_vectors[0]);
-static int test_encode() {
+static int test_encode(void) {
uint8_t out[9];
size_t i;
ssize_t len;
@@ -55,19 +56,19 @@ static int test_encode() {
return 1;
}
-static int test_decode() {
+static int test_decode(void) {
uint8_t out[6];
- size_t i;
- ssize_t len;
+ size_t i, len;
+ int ret;
for (i = 0; i < kNumTests; i++) {
+ /* Test the normal API. */
const TEST_VECTOR *t = &test_vectors[i];
size_t expected_len = strlen(t->decoded);
- len = EVP_DecodeBlock(out, (const uint8_t*)t->encoded, strlen(t->encoded));
- /* TODO(davidben): EVP_DecodeBlock doesn't take padding into account. Is
- * this behavior we can change? */
- if (expected_len % 3 != 0) {
- len -= 3 - (expected_len % 3);
+ if (!EVP_DecodeBase64(out, &len, sizeof(out),
+ (const uint8_t*)t->encoded, strlen(t->encoded))) {
+ fprintf(stderr, "decode(\"%s\") failed\n", t->encoded);
+ return 0;
}
if (len != strlen(t->decoded) ||
memcmp(out, t->decoded, len) != 0) {
@@ -75,14 +76,40 @@ static int test_decode() {
t->encoded, (int)len, (const char*)out, t->decoded);
return 0;
}
+
+ /* Test that the padding behavior of the deprecated API is
+ * preserved. */
+ ret = EVP_DecodeBlock(out, (const uint8_t*)t->encoded, strlen(t->encoded));
+ if (ret < 0) {
+ fprintf(stderr, "decode(\"%s\") failed\n", t->encoded);
+ return 0;
+ }
+ if (ret % 3 != 0) {
+ fprintf(stderr, "EVP_DecodeBlock did not ignore padding\n");
+ return 0;
+ }
+ if (expected_len % 3 != 0) {
+ ret -= 3 - (expected_len % 3);
+ }
+ if (ret != strlen(t->decoded) ||
+ memcmp(out, t->decoded, ret) != 0) {
+ fprintf(stderr, "decode(\"%s\") = \"%.*s\", want \"%s\"\n",
+ t->encoded, ret, (const char*)out, t->decoded);
+ return 0;
+ }
+ }
+
+ if (EVP_DecodeBase64(out, &len, sizeof(out), (const uint8_t*)"a!bc", 4)) {
+ fprintf(stderr, "Failed to reject invalid characters in the middle.\n");
+ return 0;
}
- if (EVP_DecodeBlock(out, (const uint8_t*)"a!bc", 4) >= 0) {
+ if (EVP_DecodeBase64(out, &len, sizeof(out), (const uint8_t*)"a=bc", 4)) {
fprintf(stderr, "Failed to reject invalid characters in the middle.\n");
return 0;
}
- if (EVP_DecodeBlock(out, (const uint8_t*)"abc", 3) >= 0) {
+ if (EVP_DecodeBase64(out, &len, sizeof(out), (const uint8_t*)"abc", 4)) {
fprintf(stderr, "Failed to reject invalid input length.\n");
return 0;
}
@@ -90,7 +117,8 @@ static int test_decode() {
return 1;
}
-int main() {
+int main(void) {
+ CRYPTO_library_init();
ERR_load_crypto_strings();
if (!test_encode()) {
diff --git a/crypto/bio/bio.c b/crypto/bio/bio.c
index a35ff65..7bd2976 100644
--- a/crypto/bio/bio.c
+++ b/crypto/bio/bio.c
@@ -351,6 +351,10 @@ size_t BIO_pending(const BIO *bio) {
return BIO_ctrl((BIO *) bio, BIO_CTRL_PENDING, 0, NULL);
}
+size_t BIO_ctrl_pending(const BIO *bio) {
+ return BIO_pending(bio);
+}
+
size_t BIO_wpending(const BIO *bio) {
return BIO_ctrl((BIO *) bio, BIO_CTRL_WPENDING, 0, NULL);
}
diff --git a/crypto/bio/bio_mem.c b/crypto/bio/bio_mem.c
index 457c2e0..6e90db5 100644
--- a/crypto/bio/bio_mem.c
+++ b/crypto/bio/bio_mem.c
@@ -132,13 +132,12 @@ static int mem_free(BIO *bio) {
}
static int mem_read(BIO *bio, char *out, int outl) {
- int ret = -1;
- BUF_MEM *b;
+ int ret;
+ BUF_MEM *b = (BUF_MEM*) bio->ptr;
- b = (BUF_MEM *)bio->ptr;
BIO_clear_retry_flags(bio);
ret = outl;
- if (ret > (int)b->length) {
+ if (b->length < INT_MAX && ret > (int)b->length) {
ret = b->length;
}
diff --git a/crypto/bio/bio_test.c b/crypto/bio/bio_test.c
index f3075b8..beb3849 100644
--- a/crypto/bio/bio_test.c
+++ b/crypto/bio/bio_test.c
@@ -22,10 +22,11 @@
#include <unistd.h>
#include <openssl/bio.h>
+#include <openssl/crypto.h>
#include <openssl/err.h>
-static int test_socket_connect() {
+static int test_socket_connect(void) {
int listening_sock = socket(AF_INET, SOCK_STREAM, 0);
int sock;
struct sockaddr_in sin;
@@ -94,7 +95,7 @@ static int test_socket_connect() {
return 1;
}
-static int test_printf() {
+static int test_printf(void) {
/* Test a short output, a very long one, and various sizes around
* 256 (the size of the buffer) to ensure edge cases are correct. */
static const size_t kLengths[] = { 5, 250, 251, 252, 253, 254, 1023 };
@@ -144,7 +145,8 @@ static int test_printf() {
return 1;
}
-int main() {
+int main(void) {
+ CRYPTO_library_init();
ERR_load_crypto_strings();
if (!test_socket_connect()) {
diff --git a/crypto/bio/internal.h b/crypto/bio/internal.h
index dd3d800..ba28839 100644
--- a/crypto/bio/internal.h
+++ b/crypto/bio/internal.h
@@ -92,7 +92,7 @@ int bio_socket_nbio(int sock, int on);
/* BIO_clear_socket_error clears the last system socket error.
*
* TODO(fork): remove all callers of this. */
-void bio_clear_socket_error();
+void bio_clear_socket_error(void);
/* BIO_sock_error returns the last socket error on |sock|. */
int bio_sock_error(int sock);
diff --git a/crypto/bio/socket_helper.c b/crypto/bio/socket_helper.c
index 0d7d21a..ba65a1a 100644
--- a/crypto/bio/socket_helper.c
+++ b/crypto/bio/socket_helper.c
@@ -97,7 +97,7 @@ int bio_socket_nbio(int sock, int on) {
#endif
}
-void bio_clear_socket_error() {}
+void bio_clear_socket_error(void) {}
int bio_sock_error(int sock) {
int error;
diff --git a/crypto/bn/bn_test.c b/crypto/bn/bn_test.c
index 440e1b6..11b3c62 100644
--- a/crypto/bn/bn_test.c
+++ b/crypto/bn/bn_test.c
@@ -71,6 +71,7 @@
#include <openssl/bio.h>
#include <openssl/bn.h>
+#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/mem.h>
@@ -99,7 +100,7 @@ int test_mod_exp(BIO *bp, BN_CTX *ctx);
int test_mod_exp_mont_consttime(BIO *bp, BN_CTX *ctx);
int test_exp(BIO *bp, BN_CTX *ctx);
int test_mod_sqrt(BIO *bp, BN_CTX *ctx);
-static int test_exp_mod_zero();
+static int test_exp_mod_zero(void);
int test_small_prime(BIO *bp,BN_CTX *ctx);
int test_mod_exp_mont5(BIO *bp, BN_CTX *ctx);
int test_sqrt(BIO *bp, BN_CTX *ctx);
@@ -135,6 +136,8 @@ int main(int argc, char *argv[]) {
BIO *out = NULL;
char *outfile = NULL;
+ CRYPTO_library_init();
+
results = 0;
argc--;
@@ -1129,7 +1132,7 @@ int test_exp(BIO *bp, BN_CTX *ctx) {
}
/* test_exp_mod_zero tests that x**0 mod 1 == 0. */
-static int test_exp_mod_zero() {
+static int test_exp_mod_zero(void) {
BIGNUM a, p, m;
BIGNUM r;
BN_CTX *ctx = BN_CTX_new();
diff --git a/crypto/bn/rsaz_exp.h b/crypto/bn/rsaz_exp.h
index 4241a1f..0bb6b0c 100644
--- a/crypto/bn/rsaz_exp.h
+++ b/crypto/bn/rsaz_exp.h
@@ -36,7 +36,7 @@
void RSAZ_1024_mod_exp_avx2(BN_ULONG result[16],
const BN_ULONG base_norm[16], const BN_ULONG exponent[16],
const BN_ULONG m_norm[16], const BN_ULONG RR[16], BN_ULONG k0);
-int rsaz_avx2_eligible();
+int rsaz_avx2_eligible(void);
void RSAZ_512_mod_exp(BN_ULONG result[8],
const BN_ULONG base_norm[8], const BN_ULONG exponent[8],
diff --git a/crypto/bytestring/CMakeLists.txt b/crypto/bytestring/CMakeLists.txt
index 409a0ce..dc48583 100644
--- a/crypto/bytestring/CMakeLists.txt
+++ b/crypto/bytestring/CMakeLists.txt
@@ -5,6 +5,7 @@ add_library(
OBJECT
+ ber.c
cbs.c
cbb.c
)
diff --git a/crypto/bytestring/ber.c b/crypto/bytestring/ber.c
new file mode 100644
index 0000000..c96c200
--- /dev/null
+++ b/crypto/bytestring/ber.c
@@ -0,0 +1,215 @@
+/* Copyright (c) 2014, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/bytestring.h>
+
+#include "internal.h"
+
+
+/* kMaxDepth is a just a sanity limit. The code should be such that the length
+ * of the input being processes always decreases. None the less, a very large
+ * input could otherwise cause the stack to overflow. */
+static const unsigned kMaxDepth = 2048;
+
+/* cbs_find_ber walks an ASN.1 structure in |orig_in| and sets |*ber_found|
+ * depending on whether an indefinite length element was found. The value of
+ * |in| is not changed. It returns one on success (i.e. |*ber_found| was set)
+ * and zero on error. */
+static int cbs_find_ber(CBS *orig_in, char *ber_found, unsigned depth) {
+ CBS in;
+
+ if (depth > kMaxDepth) {
+ return 0;
+ }
+
+ CBS_init(&in, CBS_data(orig_in), CBS_len(orig_in));
+ *ber_found = 0;
+
+ while (CBS_len(&in) > 0) {
+ CBS contents;
+ unsigned tag;
+ size_t header_len;
+
+ if (!CBS_get_any_asn1_element(&in, &contents, &tag, &header_len)) {
+ return 0;
+ }
+ if (CBS_len(&contents) == header_len &&
+ header_len > 0 &&
+ CBS_data(&contents)[header_len-1] == 0x80) {
+ *ber_found = 1;
+ return 1;
+ }
+ if (tag & CBS_ASN1_CONSTRUCTED) {
+ if (!CBS_skip(&contents, header_len) ||
+ !cbs_find_ber(&contents, ber_found, depth + 1)) {
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+
+/* is_primitive_type returns true if |tag| likely a primitive type. Normally
+ * one can just test the "constructed" bit in the tag but, in BER, even
+ * primitive tags can have the constructed bit if they have indefinite
+ * length. */
+static char is_primitive_type(unsigned tag) {
+ return (tag & 0xc0) == 0 &&
+ (tag & 0x1f) != (CBS_ASN1_SEQUENCE & 0x1f) &&
+ (tag & 0x1f) != (CBS_ASN1_SET & 0x1f);
+}
+
+/* is_eoc returns true if |header_len| and |contents|, as returned by
+ * |CBS_get_any_asn1_element|, indicate an "end of contents" (EOC) value. */
+static char is_eoc(size_t header_len, CBS *contents) {
+ return header_len == 2 && CBS_len(contents) == 2 &&
+ memcmp(CBS_data(contents), "\x00\x00", 2) == 0;
+}
+
+/* cbs_convert_ber reads BER data from |in| and writes DER data to |out|. If
+ * |squash_header| is set then the top-level of elements from |in| will not
+ * have their headers written. This is used when concatenating the fragments of
+ * an indefinite length, primitive value. If |looking_for_eoc| is set then any
+ * EOC elements found will cause the function to return after consuming it.
+ * It returns one on success and zero on error. */
+static int cbs_convert_ber(CBS *in, CBB *out, char squash_header,
+ char looking_for_eoc, unsigned depth) {
+ if (depth > kMaxDepth) {
+ return 0;
+ }
+
+ while (CBS_len(in) > 0) {
+ CBS contents;
+ unsigned tag;
+ size_t header_len;
+ CBB *out_contents, out_contents_storage;
+
+ if (!CBS_get_any_asn1_element(in, &contents, &tag, &header_len)) {
+ return 0;
+ }
+ out_contents = out;
+
+ if (CBS_len(&contents) == header_len) {
+ if (is_eoc(header_len, &contents)) {
+ return looking_for_eoc;
+ }
+
+ if (header_len > 0 && CBS_data(&contents)[header_len - 1] == 0x80) {
+ /* This is an indefinite length element. If it's a SEQUENCE or SET then
+ * we just need to write the out the contents as normal, but with a
+ * concrete length prefix.
+ *
+ * If it's a something else then the contents will be a series of BER
+ * elements of the same type which need to be concatenated. */
+ const char context_specific = (tag & 0xc0) == 0x80;
+ char squash_child_headers = is_primitive_type(tag);
+
+ /* This is a hack, but it sufficies to handle NSS's output. If we find
+ * an indefinite length, context-specific tag with a definite, primtive
+ * tag inside it, then we assume that the context-specific tag is
+ * implicit and the tags within are fragments of a primitive type that
+ * need to be concatenated. */
+ if (context_specific && (tag & CBS_ASN1_CONSTRUCTED)) {
+ CBS in_copy, contents;
+ unsigned tag;
+ size_t header_len;
+
+ CBS_init(&in_copy, CBS_data(in), CBS_len(in));
+ if (!CBS_get_any_asn1_element(&in_copy, &contents, &tag, &header_len)) {
+ return 0;
+ }
+ if (CBS_len(&contents) > header_len && is_primitive_type(tag)) {
+ squash_child_headers = 1;
+ }
+ }
+
+ if (!squash_header) {
+ unsigned out_tag = tag;
+ if (squash_child_headers) {
+ out_tag &= ~CBS_ASN1_CONSTRUCTED;
+ }
+ if (!CBB_add_asn1(out, &out_contents_storage, out_tag)) {
+ return 0;
+ }
+ out_contents = &out_contents_storage;
+ }
+
+ if (!cbs_convert_ber(in, out_contents,
+ squash_child_headers,
+ 1 /* looking for eoc */, depth + 1)) {
+ return 0;
+ }
+ if (out_contents != out && !CBB_flush(out)) {
+ return 0;
+ }
+ continue;
+ }
+ }
+
+ if (!squash_header) {
+ if (!CBB_add_asn1(out, &out_contents_storage, tag)) {
+ return 0;
+ }
+ out_contents = &out_contents_storage;
+ }
+
+ if (!CBS_skip(&contents, header_len)) {
+ return 0;
+ }
+
+ if (tag & CBS_ASN1_CONSTRUCTED) {
+ if (!cbs_convert_ber(&contents, out_contents, 0 /* don't squash header */,
+ 0 /* not looking for eoc */, depth + 1)) {
+ return 0;
+ }
+ } else {
+ if (!CBB_add_bytes(out_contents, CBS_data(&contents),
+ CBS_len(&contents))) {
+ return 0;
+ }
+ }
+
+ if (out_contents != out && !CBB_flush(out)) {
+ return 0;
+ }
+ }
+
+ return looking_for_eoc == 0;
+}
+
+int CBS_asn1_ber_to_der(CBS *in, uint8_t **out, size_t *out_len) {
+ CBB cbb;
+
+ /* First, do a quick walk to find any indefinite-length elements. Most of the
+ * time we hope that there aren't any and thus we can quickly return. */
+ char conversion_needed;
+ if (!cbs_find_ber(in, &conversion_needed, 0)) {
+ return 0;
+ }
+
+ if (!conversion_needed) {
+ *out = NULL;
+ *out_len = 0;
+ return 1;
+ }
+
+ CBB_init(&cbb, CBS_len(in));
+ if (!cbs_convert_ber(in, &cbb, 0, 0, 0)) {
+ CBB_cleanup(&cbb);
+ return 0;
+ }
+
+ return CBB_finish(&cbb, out, out_len);
+}
diff --git a/crypto/bytestring/bytestring_test.c b/crypto/bytestring/bytestring_test.c
index 20ce571..e4afccd 100644
--- a/crypto/bytestring/bytestring_test.c
+++ b/crypto/bytestring/bytestring_test.c
@@ -15,10 +15,13 @@
#include <stdio.h>
#include <stdlib.h>
+#include <openssl/crypto.h>
#include <openssl/bytestring.h>
+#include "internal.h"
-static int test_skip() {
+
+static int test_skip(void) {
static const uint8_t kData[] = {1, 2, 3};
CBS data;
@@ -31,7 +34,7 @@ static int test_skip() {
!CBS_skip(&data, 1);
}
-static int test_get_u() {
+static int test_get_u(void) {
static const uint8_t kData[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
uint8_t u8;
uint16_t u16;
@@ -50,7 +53,7 @@ static int test_get_u() {
!CBS_get_u8(&data, &u8);
}
-static int test_get_prefixed() {
+static int test_get_prefixed(void) {
static const uint8_t kData[] = {1, 2, 0, 2, 3, 4, 0, 0, 3, 3, 2, 1};
uint8_t u8;
uint16_t u16;
@@ -72,7 +75,7 @@ static int test_get_prefixed() {
u32 == 0x30201;
}
-static int test_get_prefixed_bad() {
+static int test_get_prefixed_bad(void) {
static const uint8_t kData1[] = {2, 1};
static const uint8_t kData2[] = {0, 2, 1};
static const uint8_t kData3[] = {0, 0, 2, 1};
@@ -96,7 +99,7 @@ static int test_get_prefixed_bad() {
return 1;
}
-static int test_get_asn1() {
+static int test_get_asn1(void) {
static const uint8_t kData1[] = {0x30, 2, 1, 2};
static const uint8_t kData2[] = {0x30, 3, 1, 2};
static const uint8_t kData3[] = {0x30, 0x80};
@@ -145,62 +148,7 @@ static int test_get_asn1() {
return 1;
}
-static int test_get_indef() {
- static const uint8_t kData1[] = {0x30, 0x80, 0x00, 0x00};
- static const uint8_t kDataWithoutEOC[] = {0x30, 0x80, 0x01, 0x00};
- static const uint8_t kDataWithBadInternalLength[] = {0x30, 0x80, 0x01, 0x01};
- static const uint8_t kDataNested[] = {0x30, 0x80, 0x30, 0x80, 0x30, 0x80,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
- static const uint8_t kDataPrimitive[] = {0x02, 0x80, 0x00, 0x00};
-
- CBS data, contents;
- CBS_init(&data, kData1, sizeof(kData1));
- if (CBS_get_asn1(&data, &contents, 0x30)) {
- /* Indefinite lengths should not be supported in DER mode. */
- fprintf(stderr, "Indefinite length parsed by CBS_get_asn1.\n");
- return 0;
- }
-
- if (!CBS_get_asn1_ber(&data, &contents, 0x30) ||
- CBS_len(&contents) != 0 ||
- CBS_len(&data) != 0) {
- fprintf(stderr, "Simple indefinite length failed.\n");
- return 0;
- }
-
- CBS_init(&data, kDataWithoutEOC, sizeof(kDataWithoutEOC));
- if (CBS_get_asn1_ber(&data, &contents, 0x30)) {
- fprintf(stderr, "Parsed without EOC.\n");
- return 0;
- }
-
- CBS_init(&data, kDataWithBadInternalLength,
- sizeof(kDataWithBadInternalLength));
- if (CBS_get_asn1_ber(&data, &contents, 0x30)) {
- fprintf(stderr, "Parsed with internal length.\n");
- return 0;
- }
-
- CBS_init(&data, kDataNested, sizeof(kDataNested));
- if (!CBS_get_asn1_ber(&data, &contents, 0x30) ||
- CBS_len(&contents) != 8 ||
- CBS_len(&data) != 0) {
- fprintf(stderr, "Nested indefinite lengths failed.\n");
- return 0;
- }
-
- CBS_init(&data, kDataPrimitive, sizeof(kDataPrimitive));
- if (CBS_get_asn1_ber(&data, &contents, 0x02)) {
- /* Indefinite lengths should not be supported for non-constructed
- * elements. */
- fprintf(stderr, "Parsed non-constructed element with indefinite length\n");
- return 0;
- }
-
- return 1;
-}
-
-static int test_cbb_basic() {
+static int test_cbb_basic(void) {
static const uint8_t kExpected[] = {1, 2, 3, 4, 5, 6, 7, 8};
uint8_t *buf;
size_t buf_len;
@@ -226,7 +174,7 @@ static int test_cbb_basic() {
return ok;
}
-static int test_cbb_fixed() {
+static int test_cbb_fixed(void) {
CBB cbb;
uint8_t buf[1];
uint8_t *out_buf;
@@ -253,7 +201,7 @@ static int test_cbb_fixed() {
return 1;
}
-static int test_cbb_finish_child() {
+static int test_cbb_finish_child(void) {
CBB cbb, child;
uint8_t *out_buf;
size_t out_size;
@@ -271,7 +219,7 @@ static int test_cbb_finish_child() {
return 1;
}
-static int test_cbb_prefixed() {
+static int test_cbb_prefixed(void) {
static const uint8_t kExpected[] = {0, 1, 1, 0, 2, 2, 3, 0, 0, 3,
4, 5, 6, 5, 4, 1, 0, 1, 2};
uint8_t *buf;
@@ -301,7 +249,7 @@ static int test_cbb_prefixed() {
return ok;
}
-static int test_cbb_misuse() {
+static int test_cbb_misuse(void) {
CBB cbb, child, contents;
uint8_t *buf;
size_t buf_len;
@@ -337,7 +285,7 @@ static int test_cbb_misuse() {
return 1;
}
-static int test_cbb_asn1() {
+static int test_cbb_asn1(void) {
static const uint8_t kExpected[] = {0x30, 3, 1, 2, 3};
uint8_t *buf, *test_data;
size_t buf_len;
@@ -405,19 +353,102 @@ static int test_cbb_asn1() {
return 1;
}
-int main() {
+static int do_ber_convert(const char *name,
+ const uint8_t *der_expected, size_t der_len,
+ const uint8_t *ber, size_t ber_len) {
+ CBS in;
+ uint8_t *out;
+ size_t out_len;
+
+ CBS_init(&in, ber, ber_len);
+ if (!CBS_asn1_ber_to_der(&in, &out, &out_len)) {
+ fprintf(stderr, "%s: CBS_asn1_ber_to_der failed.\n", name);
+ return 0;
+ }
+
+ if (out == NULL) {
+ if (ber_len != der_len ||
+ memcmp(der_expected, ber, ber_len) != 0) {
+ fprintf(stderr, "%s: incorrect unconverted result.\n", name);
+ return 0;
+ }
+
+ return 1;
+ }
+
+ if (out_len != der_len ||
+ memcmp(out, der_expected, der_len) != 0) {
+ fprintf(stderr, "%s: incorrect converted result.\n", name);
+ return 0;
+ }
+
+ free(out);
+ return 1;
+}
+
+static int test_ber_convert(void) {
+ static const uint8_t kSimpleBER[] = {0x01, 0x01, 0x00};
+
+ /* kIndefBER contains a SEQUENCE with an indefinite length. */
+ static const uint8_t kIndefBER[] = {0x30, 0x80, 0x01, 0x01, 0x02, 0x00, 0x00};
+ static const uint8_t kIndefDER[] = {0x30, 0x03, 0x01, 0x01, 0x02};
+
+ /* kOctetStringBER contains an indefinite length OCTETSTRING with two parts.
+ * These parts need to be concatenated in DER form. */
+ static const uint8_t kOctetStringBER[] = {0x24, 0x80, 0x04, 0x02, 0, 1,
+ 0x04, 0x02, 2, 3, 0x00, 0x00};
+ static const uint8_t kOctetStringDER[] = {0x04, 0x04, 0, 1, 2, 3};
+
+ /* kNSSBER is part of a PKCS#12 message generated by NSS that uses indefinite
+ * length elements extensively. */
+ static const uint8_t kNSSBER[] = {
+ 0x30, 0x80, 0x02, 0x01, 0x03, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48,
+ 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x04,
+ 0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39,
+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05,
+ 0x00, 0x04, 0x14, 0x84, 0x98, 0xfc, 0x66, 0x33, 0xee, 0xba, 0xe7, 0x90,
+ 0xc1, 0xb6, 0xe8, 0x8f, 0xfe, 0x1d, 0xc5, 0xa5, 0x97, 0x93, 0x3e, 0x04,
+ 0x10, 0x38, 0x62, 0xc6, 0x44, 0x12, 0xd5, 0x30, 0x00, 0xf8, 0xf2, 0x1b,
+ 0xf0, 0x6e, 0x10, 0x9b, 0xb8, 0x02, 0x02, 0x07, 0xd0, 0x00, 0x00,
+ };
+
+ static const uint8_t kNSSDER[] = {
+ 0x30, 0x53, 0x02, 0x01, 0x03, 0x30, 0x13, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x06, 0x04, 0x04,
+ 0x01, 0x02, 0x03, 0x04, 0x30, 0x39, 0x30, 0x21, 0x30, 0x09, 0x06,
+ 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x84,
+ 0x98, 0xfc, 0x66, 0x33, 0xee, 0xba, 0xe7, 0x90, 0xc1, 0xb6, 0xe8,
+ 0x8f, 0xfe, 0x1d, 0xc5, 0xa5, 0x97, 0x93, 0x3e, 0x04, 0x10, 0x38,
+ 0x62, 0xc6, 0x44, 0x12, 0xd5, 0x30, 0x00, 0xf8, 0xf2, 0x1b, 0xf0,
+ 0x6e, 0x10, 0x9b, 0xb8, 0x02, 0x02, 0x07, 0xd0,
+ };
+
+ return do_ber_convert("kSimpleBER", kSimpleBER, sizeof(kSimpleBER),
+ kSimpleBER, sizeof(kSimpleBER)) &&
+ do_ber_convert("kIndefBER", kIndefDER, sizeof(kIndefDER), kIndefBER,
+ sizeof(kIndefBER)) &&
+ do_ber_convert("kOctetStringBER", kOctetStringDER,
+ sizeof(kOctetStringDER), kOctetStringBER,
+ sizeof(kOctetStringBER)) &&
+ do_ber_convert("kNSSBER", kNSSDER, sizeof(kNSSDER), kNSSBER,
+ sizeof(kNSSBER));
+}
+
+int main(void) {
+ CRYPTO_library_init();
+
if (!test_skip() ||
!test_get_u() ||
!test_get_prefixed() ||
!test_get_prefixed_bad() ||
!test_get_asn1() ||
- !test_get_indef() ||
!test_cbb_basic() ||
!test_cbb_fixed() ||
!test_cbb_finish_child() ||
!test_cbb_misuse() ||
!test_cbb_prefixed() ||
- !test_cbb_asn1()) {
+ !test_cbb_asn1() ||
+ !test_ber_convert()) {
return 1;
}
diff --git a/crypto/bytestring/cbs.c b/crypto/bytestring/cbs.c
index 547b5a4..244daba 100644
--- a/crypto/bytestring/cbs.c
+++ b/crypto/bytestring/cbs.c
@@ -19,6 +19,8 @@
#include <assert.h>
#include <string.h>
+#include "internal.h"
+
void CBS_init(CBS *cbs, const uint8_t *data, size_t len) {
cbs->data = data;
@@ -156,52 +158,16 @@ int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out) {
return cbs_get_length_prefixed(cbs, out, 3);
}
-static int cbs_get_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
- size_t *out_header_len, unsigned depth,
- int *was_indefinite_len);
-
-/* cbs_get_asn1_indefinite_len sets |*out| to be a CBS that covers an
- * indefinite length element in |cbs| and advances |*in|. On entry, |cbs| will
- * not have had the tag and length byte removed. On exit, |*out| does not cover
- * the EOC element, but |*in| is skipped over it.
- *
- * The |depth| argument counts the number of times the code has recursed trying
- * to find an indefinite length. */
-static int cbs_get_asn1_indefinite_len(CBS *in, CBS *out, unsigned depth) {
- static const size_t kEOCLength = 2;
- size_t header_len;
- unsigned tag;
- int was_indefinite_len;
- CBS orig = *in, child;
-
- if (!CBS_skip(in, 2 /* tag plus 0x80 byte for indefinite len */)) {
- return 0;
- }
-
- for (;;) {
- if (!cbs_get_asn1_element(in, &child, &tag, &header_len, depth + 1,
- &was_indefinite_len)) {
- return 0;
- }
+int CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
+ size_t *out_header_len) {
+ uint8_t tag, length_byte;
+ CBS header = *cbs;
+ CBS throwaway;
- if (!was_indefinite_len && CBS_len(&child) == kEOCLength &&
- header_len == kEOCLength && tag == 0) {
- break;
- }
+ if (out == NULL) {
+ out = &throwaway;
}
- return CBS_get_bytes(&orig, out, CBS_len(&orig) - CBS_len(in) - kEOCLength);
-}
-
-/* MAX_DEPTH the maximum number of levels of indefinite lengths that we'll
- * support. */
-#define MAX_DEPTH 64
-
-static int cbs_get_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
- size_t *out_header_len, unsigned depth,
- int *was_indefinite_len) {
- uint8_t tag, length_byte;
- CBS header = *cbs;
if (!CBS_get_u8(&header, &tag) ||
!CBS_get_u8(&header, &length_byte)) {
return 0;
@@ -212,29 +178,26 @@ static int cbs_get_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
return 0;
}
- *out_tag = tag;
- if (was_indefinite_len) {
- *was_indefinite_len = 0;
+ if (out_tag != NULL) {
+ *out_tag = tag;
}
size_t len;
if ((length_byte & 0x80) == 0) {
/* Short form length. */
len = ((size_t) length_byte) + 2;
- *out_header_len = 2;
+ if (out_header_len != NULL) {
+ *out_header_len = 2;
+ }
} else {
/* Long form length. */
const size_t num_bytes = length_byte & 0x7f;
uint32_t len32;
- if ((tag & CBS_ASN1_CONSTRUCTED) != 0 && depth < MAX_DEPTH &&
- num_bytes == 0) {
+ if ((tag & CBS_ASN1_CONSTRUCTED) != 0 && num_bytes == 0) {
/* indefinite length */
*out_header_len = 2;
- if (was_indefinite_len) {
- *was_indefinite_len = 1;
- }
- return cbs_get_asn1_indefinite_len(cbs, out, depth);
+ return CBS_get_bytes(cbs, out, 2);
}
if (num_bytes == 0 || num_bytes > 4) {
@@ -257,13 +220,15 @@ static int cbs_get_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
return 0;
}
len += 2 + num_bytes;
- *out_header_len = 2 + num_bytes;
+ if (out_header_len != NULL) {
+ *out_header_len = 2 + num_bytes;
+ }
}
return CBS_get_bytes(cbs, out, len);
}
-static int cbs_get_asn1(CBS *cbs, CBS *out, unsigned tag_value, int ber,
+static int cbs_get_asn1(CBS *cbs, CBS *out, unsigned tag_value,
int skip_header) {
size_t header_len;
unsigned tag;
@@ -273,9 +238,13 @@ static int cbs_get_asn1(CBS *cbs, CBS *out, unsigned tag_value, int ber,
out = &throwaway;
}
- if (!cbs_get_asn1_element(cbs, out, &tag, &header_len, ber ? 0 : MAX_DEPTH,
- NULL) ||
- tag != tag_value) {
+ if (!CBS_get_any_asn1_element(cbs, out, &tag, &header_len) ||
+ tag != tag_value ||
+ (header_len > 0 &&
+ /* This ensures that the tag is either zero length or
+ * indefinite-length. */
+ CBS_len(out) == header_len &&
+ CBS_data(out)[header_len - 1] == 0x80)) {
return 0;
}
@@ -288,16 +257,39 @@ static int cbs_get_asn1(CBS *cbs, CBS *out, unsigned tag_value, int ber,
}
int CBS_get_asn1(CBS *cbs, CBS *out, unsigned tag_value) {
- return cbs_get_asn1(cbs, out, tag_value, 0 /* DER */,
- 1 /* skip header */);
+ return cbs_get_asn1(cbs, out, tag_value, 1 /* skip header */);
}
-int CBS_get_asn1_ber(CBS *cbs, CBS *out, unsigned tag_value) {
- return cbs_get_asn1(cbs, out, tag_value, 1 /* BER */,
- 1 /* skip header */);
+int CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned tag_value) {
+ return cbs_get_asn1(cbs, out, tag_value, 0 /* include header */);
}
-int CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned tag_value) {
- return cbs_get_asn1(cbs, out, tag_value, 0 /* DER */,
- 0 /* include header */);
+int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) {
+ CBS bytes;
+ const uint8_t *data;
+ size_t i, len;
+
+ if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_INTEGER)) {
+ return 0;
+ }
+
+ *out = 0;
+ data = CBS_data(&bytes);
+ len = CBS_len(&bytes);
+
+ if (len > 0 && (data[0] & 0x80) != 0) {
+ /* negative number */
+ return 0;
+ }
+
+ for (i = 0; i < len; i++) {
+ if ((*out >> 56) != 0) {
+ /* Too large to represent as a uint64_t. */
+ return 0;
+ }
+ *out <<= 8;
+ *out |= data[i];
+ }
+
+ return 1;
}
diff --git a/crypto/bytestring/internal.h b/crypto/bytestring/internal.h
new file mode 100644
index 0000000..b4ea7e5
--- /dev/null
+++ b/crypto/bytestring/internal.h
@@ -0,0 +1,46 @@
+/* Copyright (c) 2014, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#ifndef OPENSSL_HEADER_BYTESTRING_INTERNAL_H
+#define OPENSSL_HEADER_BYTESTRING_INTERNAL_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* CBS_asn1_ber_to_der reads an ASN.1 structure from |in|. If it finds
+ * indefinite-length elements then it attempts to convert the BER data to DER
+ * and sets |*out| and |*out_length| to describe a malloced buffer containing
+ * the DER data. Additionally, |*in| will be advanced over the ASN.1 data.
+ *
+ * If it doesn't find any indefinite-length elements then it sets |*out| to
+ * NULL and |*in| is unmodified.
+ *
+ * A sufficiently complex ASN.1 structure will break this function because it's
+ * not possible to generically convert BER to DER without knowledge of the
+ * structure itself. However, this sufficies to handle the PKCS#7 and #12 output
+ * from NSS.
+ *
+ * It returns one on success and zero otherwise. */
+OPENSSL_EXPORT int CBS_asn1_ber_to_der(CBS *in, uint8_t **out, size_t *out_len);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_BYTESTRING_INTERNAL_H */
diff --git a/crypto/chacha/chacha_generic.c b/crypto/chacha/chacha_generic.c
index 40a6f20..c497980 100644
--- a/crypto/chacha/chacha_generic.c
+++ b/crypto/chacha/chacha_generic.c
@@ -47,7 +47,7 @@ static const char sigma[16] = "expand 32-byte k";
x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]), 8); \
x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]), 7);
-#if defined(OPENSSL_ARM)
+#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
/* Defined in chacha_vec.c */
void CRYPTO_chacha_20_neon(uint8_t *out, const uint8_t *in, size_t in_len,
const uint8_t key[32], const uint8_t nonce[8],
@@ -87,7 +87,7 @@ void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, size_t in_len,
uint8_t buf[64];
size_t todo, i;
-#if defined(OPENSSL_ARM)
+#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
if (CRYPTO_is_NEON_capable() && ((intptr_t)in & 15) == 0 &&
((intptr_t)out & 15) == 0) {
CRYPTO_chacha_20_neon(out, in, in_len, key, nonce, counter);
diff --git a/crypto/chacha/chacha_vec_arm.S b/crypto/chacha/chacha_vec_arm.S
index be87ab3..535e20a 100644
--- a/crypto/chacha/chacha_vec_arm.S
+++ b/crypto/chacha/chacha_vec_arm.S
@@ -21,6 +21,8 @@
#
# /opt/gcc-linaro-arm-linux-gnueabihf-4.7-2012.10-20121022_linux/bin/arm-linux-gnueabihf-gcc -O3 -mcpu=cortex-a8 -mfpu=neon -S chacha_vec.c -I ../../include -fpic -o chacha_vec_arm.S
+#if !defined(OPENSSL_NO_ASM)
+
.syntax unified
.cpu cortex-a8
.eabi_attribute 27, 3
@@ -884,3 +886,5 @@ CRYPTO_chacha_20_neon:
.word 1797285236
.ident "GCC: (crosstool-NG linaro-1.13.1-4.7-2012.10-20121022 - Linaro GCC 2012.10) 4.7.3 20121001 (prerelease)"
.section .note.GNU-stack,"",%progbits
+
+#endif /* !OPENSSL_NO_ASM */
diff --git a/crypto/cipher/CMakeLists.txt b/crypto/cipher/CMakeLists.txt
index cf2a4e2..40e239c 100644
--- a/crypto/cipher/CMakeLists.txt
+++ b/crypto/cipher/CMakeLists.txt
@@ -11,6 +11,7 @@ add_library(
aead.c
e_null.c
+ e_rc2.c
e_rc4.c
e_des.c
e_aes.c
diff --git a/crypto/cipher/aead_test.c b/crypto/cipher/aead_test.c
index f0f3cf4..ff2244c 100644
--- a/crypto/cipher/aead_test.c
+++ b/crypto/cipher/aead_test.c
@@ -18,6 +18,7 @@
#include <string.h>
#include <openssl/aead.h>
+#include <openssl/crypto.h>
/* This program tests an AEAD against a series of test vectors from a file. The
* test vector file consists of key-value lines where the key and value are
@@ -155,6 +156,8 @@ int main(int argc, char **argv) {
unsigned char bufs[NUM_TYPES][BUF_MAX];
unsigned int lengths[NUM_TYPES];
+ CRYPTO_library_init();
+
if (argc != 3) {
fprintf(stderr, "%s <aead> <test file.txt>\n", argv[0]);
return 1;
diff --git a/crypto/cipher/cipher.c b/crypto/cipher/cipher.c
index c6572b8..cdb8f43 100644
--- a/crypto/cipher/cipher.c
+++ b/crypto/cipher/cipher.c
@@ -573,6 +573,21 @@ int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad) {
return 1;
}
+int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, unsigned key_len) {
+ if (c->key_len == key_len) {
+ return 1;
+ }
+
+ if (key_len == 0 || !(c->cipher->flags & EVP_CIPH_VARIABLE_LENGTH)) {
+ OPENSSL_PUT_ERROR(CIPHER, EVP_CIPHER_CTX_set_key_length,
+ CIPHER_R_INVALID_KEY_LENGTH);
+ return 0;
+ }
+
+ c->key_len = key_len;
+ return 1;
+}
+
int EVP_CIPHER_nid(const EVP_CIPHER *cipher) { return cipher->nid; }
const char *EVP_CIPHER_name(const EVP_CIPHER *cipher) {
diff --git a/crypto/cipher/cipher_error.c b/crypto/cipher/cipher_error.c
index ed72436..5e1afe6 100644
--- a/crypto/cipher/cipher_error.c
+++ b/crypto/cipher/cipher_error.c
@@ -22,6 +22,7 @@ const ERR_STRING_DATA CIPHER_error_string_data[] = {
{ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_EVP_AEAD_CTX_seal, 0), "EVP_AEAD_CTX_seal"},
{ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_EVP_CIPHER_CTX_copy, 0), "EVP_CIPHER_CTX_copy"},
{ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_EVP_CIPHER_CTX_ctrl, 0), "EVP_CIPHER_CTX_ctrl"},
+ {ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_EVP_CIPHER_CTX_set_key_length, 0), "EVP_CIPHER_CTX_set_key_length"},
{ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_EVP_CipherInit_ex, 0), "EVP_CipherInit_ex"},
{ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_EVP_DecryptFinal_ex, 0), "EVP_DecryptFinal_ex"},
{ERR_PACK(ERR_LIB_CIPHER, CIPHER_F_EVP_EncryptFinal_ex, 0), "EVP_EncryptFinal_ex"},
@@ -50,6 +51,7 @@ const ERR_STRING_DATA CIPHER_error_string_data[] = {
{ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_INPUT_NOT_INITIALIZED), "INPUT_NOT_INITIALIZED"},
{ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_INVALID_AD), "INVALID_AD"},
{ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_INVALID_AD_SIZE), "INVALID_AD_SIZE"},
+ {ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_INVALID_KEY_LENGTH), "INVALID_KEY_LENGTH"},
{ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_IV_TOO_LARGE), "IV_TOO_LARGE"},
{ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_NO_CIPHER_SET), "NO_CIPHER_SET"},
{ERR_PACK(ERR_LIB_CIPHER, 0, CIPHER_R_OUTPUT_ALIASES_INPUT), "OUTPUT_ALIASES_INPUT"},
diff --git a/crypto/cipher/cipher_test.c b/crypto/cipher/cipher_test.c
index 3dadb8a..b91b505 100644
--- a/crypto/cipher/cipher_test.c
+++ b/crypto/cipher/cipher_test.c
@@ -56,9 +56,10 @@
#include <stdio.h>
+#include <openssl/bio.h>
#include <openssl/cipher.h>
+#include <openssl/crypto.h>
#include <openssl/err.h>
-#include <openssl/bio.h>
static void hexdump(FILE *f, const char *title, const uint8_t *s, int l) {
@@ -331,6 +332,8 @@ int main(int argc, char **argv) {
const char *input_file;
FILE *f;
+ CRYPTO_library_init();
+
if (argc != 2) {
fprintf(stderr, "%s <test file>\n", argv[0]);
return 1;
diff --git a/crypto/cipher/e_aes.c b/crypto/cipher/e_aes.c
index 15a886c..d22274e 100644
--- a/crypto/cipher/e_aes.c
+++ b/crypto/cipher/e_aes.c
@@ -92,13 +92,13 @@ typedef struct {
#define VPAES
extern unsigned int OPENSSL_ia32cap_P[];
-static char vpaes_capable() {
+static char vpaes_capable(void) {
return (OPENSSL_ia32cap_P[1] & (1 << (41 - 32))) != 0;
}
#if defined(OPENSSL_X86_64)
#define BSAES
-static char bsaes_capable() {
+static char bsaes_capable(void) {
return vpaes_capable();
}
#endif
@@ -107,7 +107,7 @@ static char bsaes_capable() {
#include "../arm_arch.h"
#if __ARM_ARCH__ >= 7
#define BSAES
-static char bsaes_capable() {
+static char bsaes_capable(void) {
return CRYPTO_is_NEON_capable();
}
#endif /* __ARM_ARCH__ >= 7 */
@@ -121,7 +121,7 @@ void bsaes_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
void bsaes_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t len,
const AES_KEY *key, const uint8_t ivec[16]);
#else
-static char bsaes_capable() {
+static char bsaes_capable(void) {
return 0;
}
@@ -150,7 +150,7 @@ void vpaes_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
void vpaes_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
const AES_KEY *key, uint8_t *ivec, int enc);
#else
-static char vpaes_capable() {
+static char vpaes_capable(void) {
return 0;
}
@@ -658,7 +658,7 @@ static const EVP_CIPHER aes_256_gcm = {
/* AES-NI section. */
-static char aesni_capable() {
+static char aesni_capable(void) {
return (OPENSSL_ia32cap_P[1] & (1 << (57 - 32))) != 0;
}
@@ -812,7 +812,7 @@ static const EVP_CIPHER aesni_256_gcm = {
#else /* ^^^ OPENSSL_X86_64 || OPENSSL_X86 */
-static char aesni_capable() {
+static char aesni_capable(void) {
return 0;
}
@@ -1004,9 +1004,9 @@ static const EVP_AEAD aead_aes_256_gcm = {
aead_aes_gcm_seal, aead_aes_gcm_open,
};
-const EVP_AEAD *EVP_aead_aes_128_gcm() { return &aead_aes_128_gcm; }
+const EVP_AEAD *EVP_aead_aes_128_gcm(void) { return &aead_aes_128_gcm; }
-const EVP_AEAD *EVP_aead_aes_256_gcm() { return &aead_aes_256_gcm; }
+const EVP_AEAD *EVP_aead_aes_256_gcm(void) { return &aead_aes_256_gcm; }
/* AES Key Wrap is specified in
@@ -1268,9 +1268,9 @@ static const EVP_AEAD aead_aes_256_key_wrap = {
aead_aes_key_wrap_seal, aead_aes_key_wrap_open,
};
-const EVP_AEAD *EVP_aead_aes_128_key_wrap() { return &aead_aes_128_key_wrap; }
+const EVP_AEAD *EVP_aead_aes_128_key_wrap(void) { return &aead_aes_128_key_wrap; }
-const EVP_AEAD *EVP_aead_aes_256_key_wrap() { return &aead_aes_256_key_wrap; }
+const EVP_AEAD *EVP_aead_aes_256_key_wrap(void) { return &aead_aes_256_key_wrap; }
int EVP_has_aes_hardware(void) {
#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
diff --git a/crypto/cipher/e_chacha20poly1305.c b/crypto/cipher/e_chacha20poly1305.c
index 8b6d378..e656cd7 100644
--- a/crypto/cipher/e_chacha20poly1305.c
+++ b/crypto/cipher/e_chacha20poly1305.c
@@ -217,4 +217,6 @@ static const EVP_AEAD aead_chacha20_poly1305 = {
aead_chacha20_poly1305_seal, aead_chacha20_poly1305_open,
};
-const EVP_AEAD *EVP_aead_chacha20_poly1305() { return &aead_chacha20_poly1305; }
+const EVP_AEAD *EVP_aead_chacha20_poly1305(void) {
+ return &aead_chacha20_poly1305;
+}
diff --git a/crypto/cipher/e_rc2.c b/crypto/cipher/e_rc2.c
new file mode 100644
index 0000000..c26c94e
--- /dev/null
+++ b/crypto/cipher/e_rc2.c
@@ -0,0 +1,421 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/cipher.h>
+#include <openssl/obj.h>
+
+#include "internal.h"
+
+
+#define c2l(c, l) \
+ (l = ((uint32_t)(*((c)++))), l |= ((uint32_t)(*((c)++))) << 8L, \
+ l |= ((uint32_t)(*((c)++))) << 16L, \
+ l |= ((uint32_t)(*((c)++))) << 24L)
+
+#define c2ln(c, l1, l2, n) \
+ { \
+ c += n; \
+ l1 = l2 = 0; \
+ switch (n) { \
+ case 8: \
+ l2 = ((uint32_t)(*(--(c)))) << 24L; \
+ case 7: \
+ l2 |= ((uint32_t)(*(--(c)))) << 16L; \
+ case 6: \
+ l2 |= ((uint32_t)(*(--(c)))) << 8L; \
+ case 5: \
+ l2 |= ((uint32_t)(*(--(c)))); \
+ case 4: \
+ l1 = ((uint32_t)(*(--(c)))) << 24L; \
+ case 3: \
+ l1 |= ((uint32_t)(*(--(c)))) << 16L; \
+ case 2: \
+ l1 |= ((uint32_t)(*(--(c)))) << 8L; \
+ case 1: \
+ l1 |= ((uint32_t)(*(--(c)))); \
+ } \
+ }
+
+#define l2c(l, c) \
+ (*((c)++) = (uint8_t)(((l)) & 0xff), \
+ *((c)++) = (uint8_t)(((l) >> 8L) & 0xff), \
+ *((c)++) = (uint8_t)(((l) >> 16L) & 0xff), \
+ *((c)++) = (uint8_t)(((l) >> 24L) & 0xff))
+
+#define l2cn(l1, l2, c, n) \
+ { \
+ c += n; \
+ switch (n) { \
+ case 8: \
+ *(--(c)) = (uint8_t)(((l2) >> 24L) & 0xff); \
+ case 7: \
+ *(--(c)) = (uint8_t)(((l2) >> 16L) & 0xff); \
+ case 6: \
+ *(--(c)) = (uint8_t)(((l2) >> 8L) & 0xff); \
+ case 5: \
+ *(--(c)) = (uint8_t)(((l2)) & 0xff); \
+ case 4: \
+ *(--(c)) = (uint8_t)(((l1) >> 24L) & 0xff); \
+ case 3: \
+ *(--(c)) = (uint8_t)(((l1) >> 16L) & 0xff); \
+ case 2: \
+ *(--(c)) = (uint8_t)(((l1) >> 8L) & 0xff); \
+ case 1: \
+ *(--(c)) = (uint8_t)(((l1)) & 0xff); \
+ } \
+ }
+
+typedef struct rc2_key_st { uint16_t data[64]; } RC2_KEY;
+
+static void RC2_encrypt(uint32_t *d, RC2_KEY *key) {
+ int i, n;
+ uint16_t *p0, *p1;
+ uint16_t x0, x1, x2, x3, t;
+ uint32_t l;
+
+ l = d[0];
+ x0 = (uint16_t)l & 0xffff;
+ x1 = (uint16_t)(l >> 16L);
+ l = d[1];
+ x2 = (uint16_t)l & 0xffff;
+ x3 = (uint16_t)(l >> 16L);
+
+ n = 3;
+ i = 5;
+
+ p0 = p1 = &key->data[0];
+ for (;;) {
+ t = (x0 + (x1 & ~x3) + (x2 & x3) + *(p0++)) & 0xffff;
+ x0 = (t << 1) | (t >> 15);
+ t = (x1 + (x2 & ~x0) + (x3 & x0) + *(p0++)) & 0xffff;
+ x1 = (t << 2) | (t >> 14);
+ t = (x2 + (x3 & ~x1) + (x0 & x1) + *(p0++)) & 0xffff;
+ x2 = (t << 3) | (t >> 13);
+ t = (x3 + (x0 & ~x2) + (x1 & x2) + *(p0++)) & 0xffff;
+ x3 = (t << 5) | (t >> 11);
+
+ if (--i == 0) {
+ if (--n == 0) {
+ break;
+ }
+ i = (n == 2) ? 6 : 5;
+
+ x0 += p1[x3 & 0x3f];
+ x1 += p1[x0 & 0x3f];
+ x2 += p1[x1 & 0x3f];
+ x3 += p1[x2 & 0x3f];
+ }
+ }
+
+ d[0] = (uint32_t)(x0 & 0xffff) | ((uint32_t)(x1 & 0xffff) << 16L);
+ d[1] = (uint32_t)(x2 & 0xffff) | ((uint32_t)(x3 & 0xffff) << 16L);
+}
+
+static void RC2_decrypt(uint32_t *d, RC2_KEY *key) {
+ int i, n;
+ uint16_t *p0, *p1;
+ uint16_t x0, x1, x2, x3, t;
+ uint32_t l;
+
+ l = d[0];
+ x0 = (uint16_t)l & 0xffff;
+ x1 = (uint16_t)(l >> 16L);
+ l = d[1];
+ x2 = (uint16_t)l & 0xffff;
+ x3 = (uint16_t)(l >> 16L);
+
+ n = 3;
+ i = 5;
+
+ p0 = &key->data[63];
+ p1 = &key->data[0];
+ for (;;) {
+ t = ((x3 << 11) | (x3 >> 5)) & 0xffff;
+ x3 = (t - (x0 & ~x2) - (x1 & x2) - *(p0--)) & 0xffff;
+ t = ((x2 << 13) | (x2 >> 3)) & 0xffff;
+ x2 = (t - (x3 & ~x1) - (x0 & x1) - *(p0--)) & 0xffff;
+ t = ((x1 << 14) | (x1 >> 2)) & 0xffff;
+ x1 = (t - (x2 & ~x0) - (x3 & x0) - *(p0--)) & 0xffff;
+ t = ((x0 << 15) | (x0 >> 1)) & 0xffff;
+ x0 = (t - (x1 & ~x3) - (x2 & x3) - *(p0--)) & 0xffff;
+
+ if (--i == 0) {
+ if (--n == 0) {
+ break;
+ }
+ i = (n == 2) ? 6 : 5;
+
+ x3 = (x3 - p1[x2 & 0x3f]) & 0xffff;
+ x2 = (x2 - p1[x1 & 0x3f]) & 0xffff;
+ x1 = (x1 - p1[x0 & 0x3f]) & 0xffff;
+ x0 = (x0 - p1[x3 & 0x3f]) & 0xffff;
+ }
+ }
+
+ d[0] = (uint32_t)(x0 & 0xffff) | ((uint32_t)(x1 & 0xffff) << 16L);
+ d[1] = (uint32_t)(x2 & 0xffff) | ((uint32_t)(x3 & 0xffff) << 16L);
+}
+
+static void RC2_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
+ RC2_KEY *ks, uint8_t *iv, int encrypt) {
+ uint32_t tin0, tin1;
+ uint32_t tout0, tout1, xor0, xor1;
+ long l = length;
+ uint32_t tin[2];
+
+ if (encrypt) {
+ c2l(iv, tout0);
+ c2l(iv, tout1);
+ iv -= 8;
+ for (l -= 8; l >= 0; l -= 8) {
+ c2l(in, tin0);
+ c2l(in, tin1);
+ tin0 ^= tout0;
+ tin1 ^= tout1;
+ tin[0] = tin0;
+ tin[1] = tin1;
+ RC2_encrypt(tin, ks);
+ tout0 = tin[0];
+ l2c(tout0, out);
+ tout1 = tin[1];
+ l2c(tout1, out);
+ }
+ if (l != -8) {
+ c2ln(in, tin0, tin1, l + 8);
+ tin0 ^= tout0;
+ tin1 ^= tout1;
+ tin[0] = tin0;
+ tin[1] = tin1;
+ RC2_encrypt(tin, ks);
+ tout0 = tin[0];
+ l2c(tout0, out);
+ tout1 = tin[1];
+ l2c(tout1, out);
+ }
+ l2c(tout0, iv);
+ l2c(tout1, iv);
+ } else {
+ c2l(iv, xor0);
+ c2l(iv, xor1);
+ iv -= 8;
+ for (l -= 8; l >= 0; l -= 8) {
+ c2l(in, tin0);
+ tin[0] = tin0;
+ c2l(in, tin1);
+ tin[1] = tin1;
+ RC2_decrypt(tin, ks);
+ tout0 = tin[0] ^ xor0;
+ tout1 = tin[1] ^ xor1;
+ l2c(tout0, out);
+ l2c(tout1, out);
+ xor0 = tin0;
+ xor1 = tin1;
+ }
+ if (l != -8) {
+ c2l(in, tin0);
+ tin[0] = tin0;
+ c2l(in, tin1);
+ tin[1] = tin1;
+ RC2_decrypt(tin, ks);
+ tout0 = tin[0] ^ xor0;
+ tout1 = tin[1] ^ xor1;
+ l2cn(tout0, tout1, out, l + 8);
+ xor0 = tin0;
+ xor1 = tin1;
+ }
+ l2c(xor0, iv);
+ l2c(xor1, iv);
+ }
+ tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0;
+ tin[0] = tin[1] = 0;
+}
+
+static const uint8_t key_table[256] = {
+ 0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 0x28, 0xe9, 0xfd, 0x79,
+ 0x4a, 0xa0, 0xd8, 0x9d, 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e,
+ 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2, 0x17, 0x9a, 0x59, 0xf5,
+ 0x87, 0xb3, 0x4f, 0x13, 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32,
+ 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b, 0xf0, 0x95, 0x21, 0x22,
+ 0x5c, 0x6b, 0x4e, 0x82, 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c,
+ 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc, 0x12, 0x75, 0xca, 0x1f,
+ 0x3b, 0xbe, 0xe4, 0xd1, 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26,
+ 0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57, 0x27, 0xf2, 0x1d, 0x9b,
+ 0xbc, 0x94, 0x43, 0x03, 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7,
+ 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7, 0x08, 0xe8, 0xea, 0xde,
+ 0x80, 0x52, 0xee, 0xf7, 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a,
+ 0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 0x4b, 0x9f, 0xd0, 0x5e,
+ 0x04, 0x18, 0xa4, 0xec, 0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc,
+ 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39, 0x99, 0x7c, 0x3a, 0x85,
+ 0x23, 0xb8, 0xb4, 0x7a, 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31,
+ 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 0x05, 0xdf, 0x29, 0x10,
+ 0x67, 0x6c, 0xba, 0xc9, 0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c,
+ 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9, 0x0d, 0x38, 0x34, 0x1b,
+ 0xab, 0x33, 0xff, 0xb0, 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e,
+ 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 0x0a, 0xa6, 0x20, 0x68,
+ 0xfe, 0x7f, 0xc1, 0xad,
+};
+
+static void RC2_set_key(RC2_KEY *key, int len, const uint8_t *data, int bits) {
+ int i, j;
+ uint8_t *k;
+ uint16_t *ki;
+ unsigned int c, d;
+
+ k = (uint8_t *)&key->data[0];
+ *k = 0; /* for if there is a zero length key */
+
+ if (len > 128) {
+ len = 128;
+ }
+ if (bits <= 0) {
+ bits = 1024;
+ }
+ if (bits > 1024) {
+ bits = 1024;
+ }
+
+ for (i = 0; i < len; i++) {
+ k[i] = data[i];
+ }
+
+ /* expand table */
+ d = k[len - 1];
+ j = 0;
+ for (i = len; i < 128; i++, j++) {
+ d = key_table[(k[j] + d) & 0xff];
+ k[i] = d;
+ }
+
+ /* hmm.... key reduction to 'bits' bits */
+
+ j = (bits + 7) >> 3;
+ i = 128 - j;
+ c = (0xff >> (-bits & 0x07));
+
+ d = key_table[k[i] & c];
+ k[i] = d;
+ while (i--) {
+ d = key_table[k[i + j] ^ d];
+ k[i] = d;
+ }
+
+ /* copy from bytes into uint16_t's */
+ ki = &(key->data[63]);
+ for (i = 127; i >= 0; i -= 2) {
+ *(ki--) = ((k[i] << 8) | k[i - 1]) & 0xffff;
+ }
+}
+
+typedef struct {
+ int key_bits; /* effective key bits */
+ RC2_KEY ks; /* key schedule */
+} EVP_RC2_KEY;
+
+static int rc2_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
+ const uint8_t *iv, int enc) {
+ EVP_RC2_KEY *rc2_key = (EVP_RC2_KEY *)ctx->cipher_data;
+ RC2_set_key(&rc2_key->ks, EVP_CIPHER_CTX_key_length(ctx), key,
+ rc2_key->key_bits);
+ return 1;
+}
+
+static int rc2_cbc_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
+ size_t inl) {
+ EVP_RC2_KEY *key = (EVP_RC2_KEY *)ctx->cipher_data;
+ static const size_t kChunkSize = 0x10000;
+
+ while (inl >= kChunkSize) {
+ RC2_cbc_encrypt(in, out, kChunkSize, &key->ks, ctx->iv, ctx->encrypt);
+ inl -= kChunkSize;
+ in += kChunkSize;
+ out += kChunkSize;
+ }
+ if (inl) {
+ RC2_cbc_encrypt(in, out, inl, &key->ks, ctx->iv, ctx->encrypt);
+ }
+ return 1;
+}
+
+static int rc2_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) {
+ EVP_RC2_KEY *key = (EVP_RC2_KEY *)ctx->cipher_data;
+
+ switch (type) {
+ case EVP_CTRL_INIT:
+ key->key_bits = EVP_CIPHER_CTX_key_length(ctx) * 8;
+ return 1;
+
+ default:
+ return -1;
+ }
+}
+
+static const EVP_CIPHER rc2_40_cbc_cipher = {
+ NID_rc2_40_cbc,
+ 8 /* block size */,
+ 5 /* 40 bit */,
+ 8 /* iv len */,
+ sizeof(EVP_RC2_KEY),
+ EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT,
+ NULL /* app_data */,
+ rc2_init_key,
+ rc2_cbc_cipher,
+ NULL,
+ rc2_ctrl,
+};
+
+const EVP_CIPHER *EVP_rc2_40_cbc() {
+ return &rc2_40_cbc_cipher;
+}
diff --git a/crypto/cipher/e_rc4.c b/crypto/cipher/e_rc4.c
index df1bc11..f1d4c50 100644
--- a/crypto/cipher/e_rc4.c
+++ b/crypto/cipher/e_rc4.c
@@ -366,4 +366,4 @@ static const EVP_AEAD aead_rc4_md5_tls = {
aead_rc4_md5_tls_seal, aead_rc4_md5_tls_open,
};
-const EVP_AEAD *EVP_aead_rc4_md5_tls() { return &aead_rc4_md5_tls; }
+const EVP_AEAD *EVP_aead_rc4_md5_tls(void) { return &aead_rc4_md5_tls; }
diff --git a/crypto/conf/conf.c b/crypto/conf/conf.c
index 1630c93..520416a 100644
--- a/crypto/conf/conf.c
+++ b/crypto/conf/conf.c
@@ -90,7 +90,7 @@ static int conf_value_cmp(const CONF_VALUE *a, const CONF_VALUE *b) {
}
}
-CONF *NCONF_new() {
+CONF *NCONF_new(void) {
CONF *conf;
conf = OPENSSL_malloc(sizeof(CONF));
diff --git a/crypto/cpu-arm.c b/crypto/cpu-arm.c
index 814df26..dac7e1e 100644
--- a/crypto/cpu-arm.c
+++ b/crypto/cpu-arm.c
@@ -69,7 +69,7 @@ uint32_t OPENSSL_armcap_P = ARMV7_NEON | ARMV7_NEON_FUNCTIONAL;
uint32_t OPENSSL_armcap_P = ARMV7_NEON_FUNCTIONAL;
#endif
-char CRYPTO_is_NEON_capable() {
+char CRYPTO_is_NEON_capable(void) {
return (OPENSSL_armcap_P & ARMV7_NEON) != 0;
}
@@ -81,7 +81,7 @@ void CRYPTO_set_NEON_capable(char neon_capable) {
}
}
-char CRYPTO_is_NEON_functional() {
+char CRYPTO_is_NEON_functional(void) {
static const uint32_t kWantFlags = ARMV7_NEON | ARMV7_NEON_FUNCTIONAL;
return (OPENSSL_armcap_P & kWantFlags) == kWantFlags;
}
diff --git a/crypto/cpu-intel.c b/crypto/cpu-intel.c
index bc3148f..3dd08a9 100644
--- a/crypto/cpu-intel.c
+++ b/crypto/cpu-intel.c
@@ -61,7 +61,7 @@
#include <openssl/cpu.h>
-#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
+#if !defined(OPENSSL_NO_ASM) && (defined(OPENSSL_X86) || defined(OPENSSL_X86_64))
#include <stdio.h>
#include <inttypes.h>
@@ -78,10 +78,6 @@ uint32_t OPENSSL_ia32cap_P[4] = {0};
/* OPENSSL_ia32_cpuid is defined in cpu-x86_64-asm.pl. */
extern uint64_t OPENSSL_ia32_cpuid(uint32_t*);
-#if !defined(OPENSSL_WINDOWS)
-void OPENSSL_cpuid_setup(void) __attribute__ ((constructor));
-#endif
-
/* handle_cpu_env applies the value from |in| to the CPUID values in |out[0]|
* and |out[1]|. See the comment in |OPENSSL_cpuid_setup| about this. */
static void handle_cpu_env(uint32_t *out, const char *in) {
@@ -101,14 +97,7 @@ static void handle_cpu_env(uint32_t *out, const char *in) {
}
}
-#if defined(OPENSSL_WINDOWS)
-#pragma section(".CRT$XCU", read)
-void __cdecl OPENSSL_cpuid_setup(void);
-__declspec(allocate(".CRT$XCU")) void(*cpuid_constructor)(void) = OPENSSL_cpuid_setup;
-void __cdecl OPENSSL_cpuid_setup(void) {
-#else
void OPENSSL_cpuid_setup(void) {
-#endif
const char *env1, *env2;
#if defined(OPENSSL_X86_64)
@@ -143,4 +132,4 @@ void OPENSSL_cpuid_setup(void) {
}
}
-#endif /* OPENSSL_X86 || OPENSSL_X86_64 */
+#endif /* !OPENSSL_NO_ASM && (OPENSSL_X86 || OPENSSL_X86_64) */
diff --git a/crypto/crypto.c b/crypto/crypto.c
new file mode 100644
index 0000000..ee7c405
--- /dev/null
+++ b/crypto/crypto.c
@@ -0,0 +1,68 @@
+/* Copyright (c) 2014, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/crypto.h>
+
+#include "internal.h"
+
+#if !defined(OPENSSL_NO_ASM) && \
+ (defined(OPENSSL_X86) || defined(OPENSSL_X86_64))
+/* x86 and x86_64 need to record the result of a cpuid call for the asm to work
+ * correctly, unless compiled without asm code. */
+#define NEED_CPUID
+
+#else
+
+/* Otherwise, don't emit a static initialiser. */
+
+#if !defined(BORINGSSL_NO_STATIC_INITIALIZER)
+#define BORINGSSL_NO_STATIC_INITIALIZER
+#endif
+
+#endif /* !OPENSSL_NO_ASM && (OPENSSL_X86 || OPENSSL_X86_64) */
+
+#if defined(OPENSSL_WINDOWS)
+#define OPENSSL_CDECL __cdecl
+#else
+#define OPENSSL_CDECL
+#endif
+
+#if !defined(BORINGSSL_NO_STATIC_INITIALIZER)
+#if !defined(OPENSSL_WINDOWS)
+static void do_library_init(void) __attribute__ ((constructor));
+#else
+#pragma section(".CRT$XCU", read)
+static void __cdecl do_library_init(void);
+__declspec(allocate(".CRT$XCU")) void(*library_init_constructor)(void) =
+ do_library_init;
+#endif
+#endif /* !BORINGSSL_NO_STATIC_INITIALIZER */
+
+/* do_library_init is the actual initialization function. If
+ * BORINGSSL_NO_STATIC_INITIALIZER isn't defined, this is set as a static
+ * initializer. Otherwise, it is called by CRYPTO_library_init. */
+static void OPENSSL_CDECL do_library_init(void) {
+#if defined(NEED_CPUID)
+ OPENSSL_cpuid_setup();
+#endif
+}
+
+void CRYPTO_library_init(void) {
+ /* TODO(davidben): It would be tidier if this build knob could be replaced
+ * with an internal lazy-init mechanism that would handle things correctly
+ * in-library. */
+#if defined(BORINGSSL_NO_STATIC_INITIALIZER)
+ do_library_init();
+#endif
+}
diff --git a/crypto/dh/dh_test.c b/crypto/dh/dh_test.c
index 73dbba9..31b3dd9 100644
--- a/crypto/dh/dh_test.c
+++ b/crypto/dh/dh_test.c
@@ -60,6 +60,7 @@
#include <openssl/bio.h>
#include <openssl/bn.h>
+#include <openssl/crypto.h>
#include <openssl/mem.h>
#include "internal.h"
@@ -93,6 +94,8 @@ int main(int argc, char *argv[]) {
int i, alen, blen, aout, bout, ret = 1;
BIO *out;
+ CRYPTO_library_init();
+
out = BIO_new(BIO_s_file());
if (out == NULL) {
return 1;
diff --git a/crypto/digest/digest.c b/crypto/digest/digest.c
index 2bfb0fa..3897c60 100644
--- a/crypto/digest/digest.c
+++ b/crypto/digest/digest.c
@@ -267,3 +267,7 @@ void EVP_MD_CTX_clear_flags(EVP_MD_CTX *ctx, uint32_t flags) {
uint32_t EVP_MD_CTX_test_flags(const EVP_MD_CTX *ctx, uint32_t flags) {
return ctx->flags & flags;
}
+
+int EVP_add_digest(const EVP_MD *digest) {
+ return 1;
+}
diff --git a/crypto/digest/digests.c b/crypto/digest/digests.c
index b757ea8..e3d3a87 100644
--- a/crypto/digest/digests.c
+++ b/crypto/digest/digests.c
@@ -56,6 +56,7 @@
#include <openssl/digest.h>
+#include <openssl/md4.h>
#include <openssl/md5.h>
#include <openssl/obj.h>
#include <openssl/sha.h>
@@ -63,6 +64,24 @@
#include "internal.h"
+static int md4_init(EVP_MD_CTX *ctx) { return MD4_Init(ctx->md_data); }
+
+static int md4_update(EVP_MD_CTX *ctx, const void *data, size_t count) {
+ return MD4_Update(ctx->md_data, data, count);
+}
+
+static int md4_final(EVP_MD_CTX *ctx, unsigned char *out) {
+ return MD4_Final(out, ctx->md_data);
+}
+
+static const EVP_MD md4_md = {
+ NID_md4, MD4_DIGEST_LENGTH, 0 /* flags */, md4_init,
+ md4_update, md4_final, 64 /* block size */, sizeof(MD4_CTX),
+};
+
+const EVP_MD *EVP_md4(void) { return &md4_md; }
+
+
static int md5_init(EVP_MD_CTX *ctx) { return MD5_Init(ctx->md_data); }
static int md5_update(EVP_MD_CTX *ctx, const void *data, size_t count) {
diff --git a/crypto/dsa/dsa.c b/crypto/dsa/dsa.c
index 8c66ddf..25d15c0 100644
--- a/crypto/dsa/dsa.c
+++ b/crypto/dsa/dsa.c
@@ -60,6 +60,7 @@
#include <openssl/dsa.h>
#include <openssl/asn1.h>
+#include <openssl/dh.h>
#include <openssl/engine.h>
#include <openssl/err.h>
#include <openssl/ex_data.h>
@@ -332,3 +333,35 @@ int DSA_set_ex_data(DSA *d, int idx, void *arg) {
void *DSA_get_ex_data(const DSA *d, int idx) {
return CRYPTO_get_ex_data(&d->ex_data, idx);
}
+
+DH *DSA_dup_DH(const DSA *r) {
+ DH *ret = NULL;
+
+ if (r == NULL) {
+ goto err;
+ }
+ ret = DH_new();
+ if (ret == NULL) {
+ goto err;
+ }
+ if (r->q != NULL) {
+ ret->priv_length = BN_num_bits(r->q);
+ if ((ret->q = BN_dup(r->q)) == NULL) {
+ goto err;
+ }
+ }
+ if ((r->p != NULL && (ret->p = BN_dup(r->p)) == NULL) ||
+ (r->g != NULL && (ret->g = BN_dup(r->g)) == NULL) ||
+ (r->pub_key != NULL && (ret->pub_key = BN_dup(r->pub_key)) == NULL) ||
+ (r->priv_key != NULL && (ret->priv_key = BN_dup(r->priv_key)) == NULL)) {
+ goto err;
+ }
+
+ return ret;
+
+err:
+ if (ret != NULL) {
+ DH_free(ret);
+ }
+ return NULL;
+}
diff --git a/crypto/dsa/dsa_test.c b/crypto/dsa/dsa_test.c
index 8841c12..1edb7e7 100644
--- a/crypto/dsa/dsa_test.c
+++ b/crypto/dsa/dsa_test.c
@@ -61,6 +61,7 @@
#include <openssl/bio.h>
#include <openssl/bn.h>
+#include <openssl/crypto.h>
#include "internal.h"
@@ -107,6 +108,8 @@ int main(int argc, char **argv) {
unsigned char sig[256];
unsigned int siglen;
+ CRYPTO_library_init();
+
bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
bio_out = BIO_new_fp(stdout, BIO_NOCLOSE);
diff --git a/crypto/ec/ec.c b/crypto/ec/ec.c
index dcb9083..34e6d90 100644
--- a/crypto/ec/ec.c
+++ b/crypto/ec/ec.c
@@ -519,6 +519,16 @@ int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
return !BN_is_zero(&group->cofactor);
}
+int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *out_p, BIGNUM *out_a,
+ BIGNUM *out_b, BN_CTX *ctx) {
+ if (group->meth->group_get_curve == 0) {
+ OPENSSL_PUT_ERROR(EC, EC_GROUP_get_curve_GFp,
+ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+ return group->meth->group_get_curve(group, out_p, out_a, out_b, ctx);
+}
+
int EC_GROUP_get_curve_name(const EC_GROUP *group) { return group->curve_name; }
int EC_GROUP_get_degree(const EC_GROUP *group) {
diff --git a/crypto/ec/ec_error.c b/crypto/ec/ec_error.c
index 3b5d158..73807c7 100644
--- a/crypto/ec/ec_error.c
+++ b/crypto/ec/ec_error.c
@@ -18,6 +18,7 @@
const ERR_STRING_DATA EC_error_string_data[] = {
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_copy, 0), "EC_GROUP_copy"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_get_curve_GFp, 0), "EC_GROUP_get_curve_GFp"},
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_get_degree, 0), "EC_GROUP_get_degree"},
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GROUP_new_by_curve_name, 0), "EC_GROUP_new_by_curve_name"},
{ERR_PACK(ERR_LIB_EC, EC_F_EC_KEY_check_key, 0), "EC_KEY_check_key"},
diff --git a/crypto/ec/example_mul.c b/crypto/ec/example_mul.c
index 1e83d61..ebb724f 100644
--- a/crypto/ec/example_mul.c
+++ b/crypto/ec/example_mul.c
@@ -68,11 +68,12 @@
#include <stdio.h>
#include <openssl/bn.h>
+#include <openssl/crypto.h>
#include <openssl/ec.h>
#include <openssl/obj.h>
-int example_EC_POINT_mul() {
+int example_EC_POINT_mul(void) {
/* This example ensures that 10×∞ + G = G, in P-256. */
EC_GROUP *group = NULL;
EC_POINT *p = NULL, *result = NULL;
@@ -119,7 +120,9 @@ err:
return ret;
}
-int main() {
+int main(void) {
+ CRYPTO_library_init();
+
if (!example_EC_POINT_mul()) {
fprintf(stderr, "failed\n");
return 1;
diff --git a/crypto/ec/internal.h b/crypto/ec/internal.h
index 76c3a80..5c3be55 100644
--- a/crypto/ec/internal.h
+++ b/crypto/ec/internal.h
@@ -186,7 +186,7 @@ struct ec_method_st {
int (*field_set_to_one)(const EC_GROUP *, BIGNUM *r, BN_CTX *);
} /* EC_METHOD */;
-const EC_METHOD* EC_GFp_mont_method();
+const EC_METHOD* EC_GFp_mont_method(void);
struct ec_pre_comp_st;
void ec_pre_comp_free(struct ec_pre_comp_st *pre_comp);
diff --git a/crypto/ec/wnaf.c b/crypto/ec/wnaf.c
index b86107d..2fed4a5 100644
--- a/crypto/ec/wnaf.c
+++ b/crypto/ec/wnaf.c
@@ -448,8 +448,6 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
wNAF[num] = tmp_wNAF;
wNAF[num + 1] = NULL;
wNAF_len[num] = tmp_len;
- if (tmp_len > max_len)
- max_len = tmp_len;
/* pre_comp->points starts with the points that we need here: */
val_sub[num] = pre_comp->points;
} else {
diff --git a/crypto/ecdsa/ecdsa.c b/crypto/ecdsa/ecdsa.c
index 067fd6c..ddc3e61 100644
--- a/crypto/ecdsa/ecdsa.c
+++ b/crypto/ecdsa/ecdsa.c
@@ -140,8 +140,9 @@ int ECDSA_do_verify(const uint8_t *digest, size_t digest_len,
}
/* check input values */
- if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL ||
- (pub_key = EC_KEY_get0_public_key(eckey)) == NULL || sig == NULL) {
+ if ((group = EC_KEY_get0_group(eckey)) == NULL ||
+ (pub_key = EC_KEY_get0_public_key(eckey)) == NULL ||
+ sig == NULL) {
OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ECDSA_R_MISSING_PARAMETERS);
return 0;
}
diff --git a/crypto/ecdsa/ecdsa_test.c b/crypto/ecdsa/ecdsa_test.c
index 64480e3..e3b1142 100644
--- a/crypto/ecdsa/ecdsa_test.c
+++ b/crypto/ecdsa/ecdsa_test.c
@@ -54,6 +54,7 @@
#include <openssl/bio.h>
#include <openssl/bn.h>
+#include <openssl/crypto.h>
#include <openssl/ec.h>
#include <openssl/err.h>
#include <openssl/mem.h>
@@ -285,10 +286,11 @@ int main(void) {
int ret = 1;
BIO *out;
- out = BIO_new_fp(stdout, BIO_NOCLOSE);
-
+ CRYPTO_library_init();
ERR_load_crypto_strings();
+ out = BIO_new_fp(stdout, BIO_NOCLOSE);
+
if (!test_builtin(out))
goto err;
diff --git a/crypto/engine/engine.c b/crypto/engine/engine.c
index bb0886e..c9b8823 100644
--- a/crypto/engine/engine.c
+++ b/crypto/engine/engine.c
@@ -29,7 +29,7 @@ struct engine_st {
ECDSA_METHOD *ecdsa_method;
};
-ENGINE *ENGINE_new() {
+ENGINE *ENGINE_new(void) {
ENGINE *engine = OPENSSL_malloc(sizeof(ENGINE));
if (engine == NULL) {
return NULL;
diff --git a/crypto/err/err.c b/crypto/err/err.c
index fd3a76b..7ca2842 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -298,7 +298,7 @@ void ERR_remove_thread_state(const CRYPTO_THREADID *tid) {
OPENSSL_free(state);
}
-int ERR_get_next_error_library() {
+int ERR_get_next_error_library(void) {
err_fns_check();
return ERRFN(get_next_library)();
}
@@ -694,6 +694,7 @@ extern const ERR_STRING_DATA EC_error_string_data[];
extern const ERR_STRING_DATA EVP_error_string_data[];
extern const ERR_STRING_DATA OBJ_error_string_data[];
extern const ERR_STRING_DATA PEM_error_string_data[];
+extern const ERR_STRING_DATA PKCS8_error_string_data[];
extern const ERR_STRING_DATA RSA_error_string_data[];
extern const ERR_STRING_DATA X509V3_error_string_data[];
extern const ERR_STRING_DATA X509_error_string_data[];
@@ -746,6 +747,7 @@ static void err_load_strings(void) {
ERR_load_strings(EVP_error_string_data);
ERR_load_strings(OBJ_error_string_data);
ERR_load_strings(PEM_error_string_data);
+ ERR_load_strings(PKCS8_error_string_data);
ERR_load_strings(RSA_error_string_data);
ERR_load_strings(X509V3_error_string_data);
ERR_load_strings(X509_error_string_data);
@@ -760,11 +762,11 @@ void ERR_load_strings(const ERR_STRING_DATA *str) {
}
}
-void ERR_load_crypto_strings() { err_load_strings(); }
+void ERR_load_crypto_strings(void) { err_load_strings(); }
-void ERR_free_strings() {
+void ERR_free_strings(void) {
err_fns_check();
ERRFN(shutdown)();
}
-void ERR_load_BIO_strings() {}
+void ERR_load_BIO_strings(void) {}
diff --git a/crypto/err/err_test.c b/crypto/err/err_test.c
index 540ea07..230cada 100644
--- a/crypto/err/err_test.c
+++ b/crypto/err/err_test.c
@@ -14,11 +14,12 @@
#include <stdio.h>
+#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-static int test_overflow() {
+static int test_overflow(void) {
unsigned i;
for (i = 0; i < ERR_NUM_ERRORS*2; i++) {
@@ -40,7 +41,7 @@ static int test_overflow() {
return 1;
}
-static int test_put_error() {
+static int test_put_error(void) {
uint32_t packed_error;
int line, flags;
const char *file;
@@ -72,7 +73,7 @@ static int test_put_error() {
return 1;
}
-static int test_clear_error() {
+static int test_clear_error(void) {
if (ERR_get_error() != 0) {
fprintf(stderr, "ERR_get_error returned value before an error was added.\n");
return 0;
@@ -89,7 +90,7 @@ static int test_clear_error() {
return 1;
}
-static int test_print() {
+static int test_print(void) {
size_t i;
char buf[256];
uint32_t packed_error;
@@ -105,13 +106,15 @@ static int test_print() {
return 1;
}
-static int test_release() {
+static int test_release(void) {
ERR_put_error(1, 2, 3, "test", 4);
ERR_remove_thread_state(NULL);
return 1;
}
-int main() {
+int main(void) {
+ CRYPTO_library_init();
+
if (!test_overflow() ||
!test_put_error() ||
!test_clear_error() ||
diff --git a/crypto/evp/evp.c b/crypto/evp/evp.c
index 06fdabf..c7c4ffb 100644
--- a/crypto/evp/evp.c
+++ b/crypto/evp/evp.c
@@ -74,7 +74,7 @@ extern const EVP_PKEY_ASN1_METHOD ec_asn1_meth;
extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth;
extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meth;
-EVP_PKEY *EVP_PKEY_new() {
+EVP_PKEY *EVP_PKEY_new(void) {
EVP_PKEY *ret;
ret = OPENSSL_malloc(sizeof(EVP_PKEY));
@@ -427,6 +427,6 @@ int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **out_md) {
0, (void *)out_md);
}
-void OpenSSL_add_all_algorithms() {}
+void OpenSSL_add_all_algorithms(void) {}
-void EVP_cleanup() {}
+void EVP_cleanup(void) {}
diff --git a/crypto/evp/example_sign.c b/crypto/evp/example_sign.c
index df7156b..c25ef2a 100644
--- a/crypto/evp/example_sign.c
+++ b/crypto/evp/example_sign.c
@@ -17,6 +17,7 @@
#include <stdlib.h>
#include <openssl/bio.h>
+#include <openssl/crypto.h>
#include <openssl/digest.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
@@ -95,7 +96,7 @@ static const uint8_t kSignature[] = {
};
-int example_EVP_DigestSignInit() {
+int example_EVP_DigestSignInit(void) {
int ret = 0;
EVP_PKEY *pkey = NULL;
RSA *rsa = NULL;
@@ -127,9 +128,13 @@ int example_EVP_DigestSignInit() {
fprintf(stderr, "sig_len mismatch\n");
goto out;
}
+
sig = malloc(sig_len);
- if (sig == NULL ||
- EVP_DigestSignFinal(&md_ctx, sig, &sig_len) != 1) {
+ if (sig == NULL) {
+ goto out;
+ }
+ if (EVP_DigestSignFinal(&md_ctx, sig, &sig_len) != 1) {
+ free(sig);
goto out;
}
@@ -154,7 +159,7 @@ out:
return ret;
}
-int example_EVP_DigestVerifyInit() {
+int example_EVP_DigestVerifyInit(void) {
int ret = 0;
EVP_PKEY *pkey = NULL;
RSA *rsa = NULL;
@@ -193,7 +198,9 @@ out:
return ret;
}
-int main() {
+int main(void) {
+ CRYPTO_library_init();
+
if (!example_EVP_DigestSignInit()) {
fprintf(stderr, "EVP_DigestSignInit failed\n");
return 1;
diff --git a/crypto/ex_data.c b/crypto/ex_data.c
index 00b8ff3..820f48d 100644
--- a/crypto/ex_data.c
+++ b/crypto/ex_data.c
@@ -123,7 +123,7 @@ static const CRYPTO_EX_DATA_IMPL *global_impl = NULL;
extern const CRYPTO_EX_DATA_IMPL ex_data_default_impl;
/* get_impl returns the current ex_data implementatation. */
-static const CRYPTO_EX_DATA_IMPL *get_impl() {
+static const CRYPTO_EX_DATA_IMPL *get_impl(void) {
const CRYPTO_EX_DATA_IMPL *impl;
CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA);
diff --git a/crypto/ex_data_impl.c b/crypto/ex_data_impl.c
index 23d1fac..ddc6b8a 100644
--- a/crypto/ex_data_impl.c
+++ b/crypto/ex_data_impl.c
@@ -171,7 +171,7 @@ static void class_free(EX_CLASS_ITEM *item) {
sk_CRYPTO_EX_DATA_FUNCS_pop_free(item->meth, data_funcs_free);
}
-static LHASH_OF(EX_CLASS_ITEM) *get_classes() {
+static LHASH_OF(EX_CLASS_ITEM) *get_classes(void) {
LHASH_OF(EX_CLASS_ITEM) *ret;
CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA);
diff --git a/crypto/hmac/hmac_test.c b/crypto/hmac/hmac_test.c
index e2ae4a6..7b85196 100644
--- a/crypto/hmac/hmac_test.c
+++ b/crypto/hmac/hmac_test.c
@@ -56,6 +56,7 @@
#include <stdio.h>
+#include <openssl/crypto.h>
#include <openssl/digest.h>
#include <openssl/hmac.h>
@@ -124,6 +125,8 @@ int main(int argc, char *argv[]) {
uint8_t out[EVP_MAX_MD_SIZE];
unsigned out_len;
+ CRYPTO_library_init();
+
for (i = 0; i < NUM_TESTS; i++) {
const struct test_st *test = &kTests[i];
diff --git a/crypto/internal.h b/crypto/internal.h
index 8464239..ffac2d5 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -109,7 +109,11 @@
#ifndef OPENSSL_HEADER_CRYPTO_INTERNAL_H
#define OPENSSL_HEADER_CRYPTO_INTERNAL_H
-#include <openssl/base.h>
+#include <openssl/ex_data.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
/* st_CRYPTO_EX_DATA_IMPL contains an ex_data implementation. See the comments
@@ -128,6 +132,23 @@ struct st_CRYPTO_EX_DATA_IMPL {
};
+#if defined(OPENSSL_WINDOWS)
+#define OPENSSL_U64(x) x##UI64
+#else
+
+#if defined(OPENSSL_64_BIT)
+#define OPENSSL_U64(x) x##UL
+#else
+#define OPENSSL_U64(x) x##ULL
+#endif
+
+#endif /* OPENSSL_WINDOWS */
+
+#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
+/* OPENSSL_cpuid_setup initializes OPENSSL_ia32cap_P. */
+void OPENSSL_cpuid_setup(void);
+#endif
+
#if defined(__cplusplus)
} /* extern C */
#endif
diff --git a/crypto/lhash/lhash_test.c b/crypto/lhash/lhash_test.c
index 2aa90c3..eb40cab 100644
--- a/crypto/lhash/lhash_test.c
+++ b/crypto/lhash/lhash_test.c
@@ -14,6 +14,7 @@
#define _BSD_SOURCE
+#include <openssl/crypto.h>
#include <openssl/lhash.h>
#include <stdio.h>
@@ -99,7 +100,7 @@ static char *dummy_lh_delete(struct dummy_lhash *lh, const void *s) {
return NULL;
}
-static char *rand_string() {
+static char *rand_string(void) {
unsigned len = 1 + (rand() % 3);
char *ret = malloc(len + 1);
unsigned i;
@@ -113,10 +114,14 @@ static char *rand_string() {
}
int main(int argc, char **argv) {
- _LHASH *lh = lh_new(NULL, NULL);
+ _LHASH *lh;
struct dummy_lhash dummy_lh = {NULL};
unsigned i;
+ CRYPTO_library_init();
+
+ lh = lh_new(NULL, NULL);
+
for (i = 0; i < 100000; i++) {
unsigned action;
char *s, *s1, *s2;
diff --git a/crypto/md4/CMakeLists.txt b/crypto/md4/CMakeLists.txt
new file mode 100644
index 0000000..7fbce40
--- /dev/null
+++ b/crypto/md4/CMakeLists.txt
@@ -0,0 +1,9 @@
+include_directories(. .. ../../include)
+
+add_library(
+ md4
+
+ OBJECT
+
+ md4.c
+)
diff --git a/crypto/md4/md4.c b/crypto/md4/md4.c
new file mode 100644
index 0000000..8e86945
--- /dev/null
+++ b/crypto/md4/md4.c
@@ -0,0 +1,222 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/md4.h>
+
+
+/* Implemented from RFC1186 The MD4 Message-Digest Algorithm. */
+
+int MD4_Init(MD4_CTX *md4) {
+ memset(md4, 0, sizeof(MD4_CTX));
+ md4->A = 0x67452301UL;
+ md4->B = 0xefcdab89UL;
+ md4->C = 0x98badcfeUL;
+ md4->D = 0x10325476UL;
+ return 1;
+}
+
+void md4_block_data_order (MD4_CTX *md4, const void *p, size_t num);
+
+#define DATA_ORDER_IS_LITTLE_ENDIAN
+
+#define HASH_LONG uint32_t
+#define HASH_CTX MD4_CTX
+#define HASH_CBLOCK 64
+#define HASH_UPDATE MD4_Update
+#define HASH_TRANSFORM MD4_Transform
+#define HASH_FINAL MD4_Final
+#define HASH_MAKE_STRING(c, s) \
+ do { \
+ unsigned long ll; \
+ ll = (c)->A; \
+ (void) HOST_l2c(ll, (s)); \
+ ll = (c)->B; \
+ (void) HOST_l2c(ll, (s)); \
+ ll = (c)->C; \
+ (void) HOST_l2c(ll, (s)); \
+ ll = (c)->D; \
+ (void) HOST_l2c(ll, (s)); \
+ } while (0)
+#define HASH_BLOCK_DATA_ORDER md4_block_data_order
+
+#include "../digest/md32_common.h"
+
+/* As pointed out by Wei Dai <weidai@eskimo.com>, the above can be
+ * simplified to the code below. Wei attributes these optimizations
+ * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel. */
+#define F(b, c, d) ((((c) ^ (d)) & (b)) ^ (d))
+#define G(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d)))
+#define H(b, c, d) ((b) ^ (c) ^ (d))
+
+#define R0(a, b, c, d, k, s, t) \
+ { \
+ a += ((k) + (t)+F((b), (c), (d))); \
+ a = ROTATE(a, s); \
+ };
+
+#define R1(a, b, c, d, k, s, t) \
+ { \
+ a += ((k) + (t)+G((b), (c), (d))); \
+ a = ROTATE(a, s); \
+ };
+
+#define R2(a, b, c, d, k, s, t) \
+ { \
+ a += ((k) + (t)+H((b), (c), (d))); \
+ a = ROTATE(a, s); \
+ };
+
+void md4_block_data_order(MD4_CTX *c, const void *data_, size_t num) {
+ const uint8_t *data = data_;
+ uint32_t A, B, C, D, l;
+ uint32_t X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15;
+
+ A = c->A;
+ B = c->B;
+ C = c->C;
+ D = c->D;
+
+ for (; num--;) {
+ HOST_c2l(data, l);
+ X0 = l;
+ HOST_c2l(data, l);
+ X1 = l;
+ /* Round 0 */
+ R0(A, B, C, D, X0, 3, 0);
+ HOST_c2l(data, l);
+ X2 = l;
+ R0(D, A, B, C, X1, 7, 0);
+ HOST_c2l(data, l);
+ X3 = l;
+ R0(C, D, A, B, X2, 11, 0);
+ HOST_c2l(data, l);
+ X4 = l;
+ R0(B, C, D, A, X3, 19, 0);
+ HOST_c2l(data, l);
+ X5 = l;
+ R0(A, B, C, D, X4, 3, 0);
+ HOST_c2l(data, l);
+ X6 = l;
+ R0(D, A, B, C, X5, 7, 0);
+ HOST_c2l(data, l);
+ X7 = l;
+ R0(C, D, A, B, X6, 11, 0);
+ HOST_c2l(data, l);
+ X8 = l;
+ R0(B, C, D, A, X7, 19, 0);
+ HOST_c2l(data, l);
+ X9 = l;
+ R0(A, B, C, D, X8, 3, 0);
+ HOST_c2l(data, l);
+ X10 = l;
+ R0(D, A, B, C, X9, 7, 0);
+ HOST_c2l(data, l);
+ X11 = l;
+ R0(C, D, A, B, X10, 11, 0);
+ HOST_c2l(data, l);
+ X12 = l;
+ R0(B, C, D, A, X11, 19, 0);
+ HOST_c2l(data, l);
+ X13 = l;
+ R0(A, B, C, D, X12, 3, 0);
+ HOST_c2l(data, l);
+ X14 = l;
+ R0(D, A, B, C, X13, 7, 0);
+ HOST_c2l(data, l);
+ X15 = l;
+ R0(C, D, A, B, X14, 11, 0);
+ R0(B, C, D, A, X15, 19, 0);
+ /* Round 1 */
+ R1(A, B, C, D, X0, 3, 0x5A827999L);
+ R1(D, A, B, C, X4, 5, 0x5A827999L);
+ R1(C, D, A, B, X8, 9, 0x5A827999L);
+ R1(B, C, D, A, X12, 13, 0x5A827999L);
+ R1(A, B, C, D, X1, 3, 0x5A827999L);
+ R1(D, A, B, C, X5, 5, 0x5A827999L);
+ R1(C, D, A, B, X9, 9, 0x5A827999L);
+ R1(B, C, D, A, X13, 13, 0x5A827999L);
+ R1(A, B, C, D, X2, 3, 0x5A827999L);
+ R1(D, A, B, C, X6, 5, 0x5A827999L);
+ R1(C, D, A, B, X10, 9, 0x5A827999L);
+ R1(B, C, D, A, X14, 13, 0x5A827999L);
+ R1(A, B, C, D, X3, 3, 0x5A827999L);
+ R1(D, A, B, C, X7, 5, 0x5A827999L);
+ R1(C, D, A, B, X11, 9, 0x5A827999L);
+ R1(B, C, D, A, X15, 13, 0x5A827999L);
+ /* Round 2 */
+ R2(A, B, C, D, X0, 3, 0x6ED9EBA1L);
+ R2(D, A, B, C, X8, 9, 0x6ED9EBA1L);
+ R2(C, D, A, B, X4, 11, 0x6ED9EBA1L);
+ R2(B, C, D, A, X12, 15, 0x6ED9EBA1L);
+ R2(A, B, C, D, X2, 3, 0x6ED9EBA1L);
+ R2(D, A, B, C, X10, 9, 0x6ED9EBA1L);
+ R2(C, D, A, B, X6, 11, 0x6ED9EBA1L);
+ R2(B, C, D, A, X14, 15, 0x6ED9EBA1L);
+ R2(A, B, C, D, X1, 3, 0x6ED9EBA1L);
+ R2(D, A, B, C, X9, 9, 0x6ED9EBA1L);
+ R2(C, D, A, B, X5, 11, 0x6ED9EBA1L);
+ R2(B, C, D, A, X13, 15, 0x6ED9EBA1L);
+ R2(A, B, C, D, X3, 3, 0x6ED9EBA1L);
+ R2(D, A, B, C, X11, 9, 0x6ED9EBA1L);
+ R2(C, D, A, B, X7, 11, 0x6ED9EBA1L);
+ R2(B, C, D, A, X15, 15, 0x6ED9EBA1L);
+
+ A = c->A += A;
+ B = c->B += B;
+ C = c->C += C;
+ D = c->D += D;
+ }
+}
diff --git a/crypto/md5/md5_test.c b/crypto/md5/md5_test.c
index eb5984c..fd24341 100644
--- a/crypto/md5/md5_test.c
+++ b/crypto/md5/md5_test.c
@@ -55,8 +55,9 @@
#include <stdio.h>
-#include <openssl/md5.h>
+#include <openssl/crypto.h>
#include <openssl/digest.h>
+#include <openssl/md5.h>
static const char *const test[] = {
@@ -78,6 +79,8 @@ int main(int argc, char **argv) {
char md_hex[sizeof(md) * 2 + 1];
int ok = 1;
+ CRYPTO_library_init();
+
for (i = 0; test[i] != NULL; i++) {
EVP_Digest(test[i], strlen(test[i]), md, NULL, EVP_md5(), NULL);
for (j = 0; j < sizeof(md); j++) {
diff --git a/crypto/modes/gcm.c b/crypto/modes/gcm.c
index 065c457..96139a8 100644
--- a/crypto/modes/gcm.c
+++ b/crypto/modes/gcm.c
@@ -54,6 +54,7 @@
#include <openssl/cpu.h>
#include "internal.h"
+#include "../internal.h"
#if !defined(OPENSSL_NO_ASM) && \
@@ -70,17 +71,17 @@
#endif
#define PACK(s) ((size_t)(s) << (sizeof(size_t) * 8 - 16))
-#define REDUCE1BIT(V) \
- do { \
- if (sizeof(size_t) == 8) { \
- uint64_t T = U64(0xe100000000000000) & (0 - (V.lo & 1)); \
- V.lo = (V.hi << 63) | (V.lo >> 1); \
- V.hi = (V.hi >> 1) ^ T; \
- } else { \
- uint32_t T = 0xe1000000U & (0 - (uint32_t)(V.lo & 1)); \
- V.lo = (V.hi << 63) | (V.lo >> 1); \
- V.hi = (V.hi >> 1) ^ ((uint64_t)T << 32); \
- } \
+#define REDUCE1BIT(V) \
+ do { \
+ if (sizeof(size_t) == 8) { \
+ uint64_t T = OPENSSL_U64(0xe100000000000000) & (0 - (V.lo & 1)); \
+ V.lo = (V.hi << 63) | (V.lo >> 1); \
+ V.hi = (V.hi >> 1) ^ T; \
+ } else { \
+ uint32_t T = 0xe1000000U & (0 - (uint32_t)(V.lo & 1)); \
+ V.lo = (V.hi << 63) | (V.lo >> 1); \
+ V.hi = (V.hi >> 1) ^ ((uint64_t)T << 32); \
+ } \
} while (0)
@@ -542,7 +543,7 @@ int CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx, const uint8_t *aad, size_t len) {
}
alen += len;
- if (alen > (U64(1) << 61) || (sizeof(len) == 8 && alen < len)) {
+ if (alen > (OPENSSL_U64(1) << 61) || (sizeof(len) == 8 && alen < len)) {
return 0;
}
ctx->len.u[0] = alen;
@@ -608,7 +609,8 @@ int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, const unsigned char *in,
#endif
mlen += len;
- if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len)) {
+ if (mlen > ((OPENSSL_U64(1) << 36) - 32) ||
+ (sizeof(len) == 8 && mlen < len)) {
return 0;
}
ctx->len.u[1] = mlen;
@@ -767,7 +769,8 @@ int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, const unsigned char *in,
#endif
mlen += len;
- if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len)) {
+ if (mlen > ((OPENSSL_U64(1) << 36) - 32) ||
+ (sizeof(len) == 8 && mlen < len)) {
return 0;
}
ctx->len.u[1] = mlen;
@@ -932,7 +935,8 @@ int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, const uint8_t *in,
#endif
mlen += len;
- if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len)) {
+ if (mlen > ((OPENSSL_U64(1) << 36) - 32) ||
+ (sizeof(len) == 8 && mlen < len)) {
return 0;
}
ctx->len.u[1] = mlen;
@@ -1041,7 +1045,8 @@ int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, const uint8_t *in,
#endif
mlen += len;
- if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len)) {
+ if (mlen > ((OPENSSL_U64(1) << 36) - 32) ||
+ (sizeof(len) == 8 && mlen < len)) {
return 0;
}
ctx->len.u[1] = mlen;
diff --git a/crypto/modes/gcm_test.c b/crypto/modes/gcm_test.c
index 8c52b85..5308976 100644
--- a/crypto/modes/gcm_test.c
+++ b/crypto/modes/gcm_test.c
@@ -49,6 +49,7 @@
#include <stdio.h>
#include <openssl/aes.h>
+#include <openssl/crypto.h>
#include <openssl/mem.h>
#include <openssl/modes.h>
@@ -413,10 +414,12 @@ out:
return ret;
}
-int main() {
+int main(void) {
int ret = 0;
unsigned i;
+ CRYPTO_library_init();
+
for (i = 0; i < sizeof(test_cases) / sizeof(struct test_case); i++) {
if (!run_test_case(i, &test_cases[i])) {
ret = 1;
diff --git a/crypto/modes/internal.h b/crypto/modes/internal.h
index 4659eab..9662e0d 100644
--- a/crypto/modes/internal.h
+++ b/crypto/modes/internal.h
@@ -185,15 +185,6 @@ struct ccm128_context {
void *key;
};
-#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__)
-#define U64(C) C##UI64
-#elif defined(__arch64__)
-#define U64(C) C##UL
-#else
-#define U64(C) C##ULL
-#endif
-
-
#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
/* crypto_gcm_clmul_enabled returns one if the CLMUL implementation of GCM is
* used. */
diff --git a/crypto/obj/obj.c b/crypto/obj/obj.c
index 6bbac92..bfcc08b 100644
--- a/crypto/obj/obj.c
+++ b/crypto/obj/obj.c
@@ -66,7 +66,7 @@
#include <openssl/mem.h>
#include <openssl/thread.h>
-#include <openssl/obj_dat.h>
+#include "obj_dat.h"
/* These globals are protected by CRYPTO_LOCK_OBJ. */
static LHASH_OF(ASN1_OBJECT) *global_added_by_data = NULL;
@@ -76,7 +76,7 @@ static LHASH_OF(ASN1_OBJECT) *global_added_by_long_name = NULL;
static unsigned global_next_nid = NUM_NID;
-static int obj_next_nid() {
+static int obj_next_nid(void) {
int ret;
CRYPTO_w_lock(CRYPTO_LOCK_OBJ);
diff --git a/include/openssl/obj_dat.h b/crypto/obj/obj_dat.h
index 18bcec1..18bcec1 100644
--- a/include/openssl/obj_dat.h
+++ b/crypto/obj/obj_dat.h
diff --git a/crypto/pem/pem_all.c b/crypto/pem/pem_all.c
index c1b8d6e..24ecc62 100644
--- a/crypto/pem/pem_all.c
+++ b/crypto/pem/pem_all.c
@@ -224,7 +224,6 @@ IMPLEMENT_PEM_rw_const(DSAparams, DSA, PEM_STRING_DSAPARAMS, DSAparams)
#endif
-#ifndef OPENSSL_NO_EC
static EC_KEY *pkey_get_eckey(EVP_PKEY *key, EC_KEY **eckey)
{
EC_KEY *dtmp;
@@ -271,15 +270,12 @@ EC_KEY *PEM_read_ECPrivateKey(FILE *fp, EC_KEY **eckey, pem_password_cb *cb,
#endif
-#endif
-#ifndef OPENSSL_NO_DH
IMPLEMENT_PEM_write_const(DHparams, DH, PEM_STRING_DHPARAMS, DHparams)
/* TODO(fork): remove this code? */
/* IMPLEMENT_PEM_write_const(DHxparams, DH, PEM_STRING_DHXPARAMS, DHxparams) */
-#endif
IMPLEMENT_PEM_rw(PUBKEY, EVP_PKEY, PEM_STRING_PUBLIC, PUBKEY)
diff --git a/crypto/pem/pem_info.c b/crypto/pem/pem_info.c
index 6e59a7f..c4974c2 100644
--- a/crypto/pem/pem_info.c
+++ b/crypto/pem/pem_info.c
@@ -207,7 +207,6 @@ start:
}
else
#endif
-#ifndef OPENSSL_NO_EC
if (strcmp(name,PEM_STRING_ECPRIVATEKEY) == 0)
{
d2i=(D2I_OF(void))d2i_ECPrivateKey;
@@ -228,7 +227,6 @@ start:
raw=1;
}
else
-#endif
{
d2i=NULL;
pp=NULL;
diff --git a/crypto/pem/pem_pkey.c b/crypto/pem/pem_pkey.c
index d0f08c8..0ef08d0 100644
--- a/crypto/pem/pem_pkey.c
+++ b/crypto/pem/pem_pkey.c
@@ -262,7 +262,6 @@ int PEM_write_PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
#endif
-#ifndef OPENSSL_NO_DH
/* Transparently read in PKCS#3 or X9.42 DH parameters */
@@ -310,4 +309,3 @@ DH *PEM_read_DHparams(FILE *fp, DH **x, pem_password_cb *cb, void *u)
}
#endif
-#endif
diff --git a/crypto/perlasm/x86_64-xlate.pl b/crypto/perlasm/x86_64-xlate.pl
index 8018fbd..7c80dc2 100755
--- a/crypto/perlasm/x86_64-xlate.pl
+++ b/crypto/perlasm/x86_64-xlate.pl
@@ -936,7 +936,7 @@ while($line=<>) {
print "\n$current_segment\tENDS\n" if ($current_segment && $masm);
print "END\n" if ($masm);
-print "#endif" if ($gas);
+print "#endif\n" if ($gas);
close STDOUT;
diff --git a/crypto/pkcs8/CMakeLists.txt b/crypto/pkcs8/CMakeLists.txt
index b89af85..ad62768 100644
--- a/crypto/pkcs8/CMakeLists.txt
+++ b/crypto/pkcs8/CMakeLists.txt
@@ -11,3 +11,11 @@ add_library(
p5_pbev2.c
pkcs8_error.c
)
+
+add_executable(
+ pkcs12_test
+
+ pkcs12_test.c
+)
+
+target_link_libraries(pkcs12_test crypto)
diff --git a/crypto/pkcs8/p8_pkey.c b/crypto/pkcs8/p8_pkey.c
index 9095ffd..bd9d30c 100644
--- a/crypto/pkcs8/p8_pkey.c
+++ b/crypto/pkcs8/p8_pkey.c
@@ -62,23 +62,24 @@
/* Minor tweak to operation: zero private key data */
static int pkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
- void *exarg)
-{
- /* Since the structure must still be valid use ASN1_OP_FREE_PRE */
- if(operation == ASN1_OP_FREE_PRE) {
- PKCS8_PRIV_KEY_INFO *key = (PKCS8_PRIV_KEY_INFO *)*pval;
- if (key->pkey->value.octet_string)
- OPENSSL_cleanse(key->pkey->value.octet_string->data,
- key->pkey->value.octet_string->length);
- }
- return 1;
+ void *exarg) {
+ /* Since the structure must still be valid use ASN1_OP_FREE_PRE */
+ if (operation == ASN1_OP_FREE_PRE) {
+ PKCS8_PRIV_KEY_INFO *key = (PKCS8_PRIV_KEY_INFO *)*pval;
+ if (key->pkey &&
+ key->pkey->value.octet_string) {
+ OPENSSL_cleanse(key->pkey->value.octet_string->data,
+ key->pkey->value.octet_string->length);
+ }
+ }
+ return 1;
}
ASN1_SEQUENCE_cb(PKCS8_PRIV_KEY_INFO, pkey_cb) = {
- ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, version, ASN1_INTEGER),
- ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkeyalg, X509_ALGOR),
- ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkey, ASN1_ANY),
- ASN1_IMP_SET_OF_OPT(PKCS8_PRIV_KEY_INFO, attributes, X509_ATTRIBUTE, 0)
-} ASN1_SEQUENCE_END_cb(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO)
+ ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, version, ASN1_INTEGER),
+ ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkeyalg, X509_ALGOR),
+ ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkey, ASN1_ANY),
+ ASN1_IMP_SET_OF_OPT(PKCS8_PRIV_KEY_INFO, attributes, X509_ATTRIBUTE, 0)
+} ASN1_SEQUENCE_END_cb(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO);
-IMPLEMENT_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO)
+IMPLEMENT_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO);
diff --git a/crypto/pkcs8/pkcs12_test.c b/crypto/pkcs8/pkcs12_test.c
new file mode 100644
index 0000000..2292b77
--- /dev/null
+++ b/crypto/pkcs8/pkcs12_test.c
@@ -0,0 +1,763 @@
+/* Copyright (c) 2014, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <openssl/bio.h>
+#include <openssl/bytestring.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/pkcs8.h>
+#include <openssl/stack.h>
+#include <openssl/x509.h>
+
+
+/* kPKCS12DER contains sample PKCS#12 data generated by OpenSSL with:
+ * openssl pkcs12 -export -inkey key.pem -in cacert.pem */
+static const uint8_t kOpenSSL[] = {
+ 0x30, 0x82, 0x09, 0xa1, 0x02, 0x01, 0x03, 0x30, 0x82, 0x09, 0x67, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82,
+ 0x09, 0x58, 0x04, 0x82, 0x09, 0x54, 0x30, 0x82, 0x09, 0x50, 0x30, 0x82,
+ 0x04, 0x07, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07,
+ 0x06, 0xa0, 0x82, 0x03, 0xf8, 0x30, 0x82, 0x03, 0xf4, 0x02, 0x01, 0x00,
+ 0x30, 0x82, 0x03, 0xed, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x07, 0x01, 0x30, 0x1c, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x0c, 0x01, 0x06, 0x30, 0x0e, 0x04, 0x08, 0x31, 0x24, 0xca,
+ 0x7d, 0xc3, 0x25, 0x3e, 0xdc, 0x02, 0x02, 0x08, 0x00, 0x80, 0x82, 0x03,
+ 0xc0, 0x55, 0xe7, 0x7f, 0x9c, 0xd6, 0x0c, 0xd2, 0x69, 0x1d, 0x6e, 0x8b,
+ 0xb8, 0x07, 0xec, 0x4a, 0xe7, 0x06, 0x67, 0xd1, 0x24, 0x1b, 0xd5, 0x68,
+ 0x13, 0x3d, 0xd7, 0x56, 0x5e, 0x15, 0x40, 0xdb, 0xda, 0x88, 0x36, 0xc9,
+ 0x02, 0x96, 0xb5, 0xb5, 0xf7, 0x81, 0xef, 0x88, 0x1d, 0x66, 0x62, 0xa8,
+ 0x83, 0xf7, 0x91, 0xb1, 0x26, 0x1f, 0x9b, 0x25, 0x78, 0x0a, 0x04, 0xb1,
+ 0xc0, 0x93, 0x48, 0xa2, 0xf0, 0x51, 0x4f, 0x2b, 0xf8, 0x03, 0x67, 0x61,
+ 0x1b, 0xed, 0x29, 0xfe, 0x3f, 0xdd, 0x83, 0xa3, 0x93, 0x75, 0xa7, 0xd9,
+ 0x37, 0x5b, 0xa7, 0xc9, 0xf4, 0x52, 0x86, 0xd2, 0x3f, 0xca, 0x61, 0x5c,
+ 0x1e, 0xf9, 0x07, 0x7d, 0xbd, 0xda, 0x76, 0x8a, 0x03, 0x8e, 0x12, 0x4e,
+ 0x8f, 0x68, 0x6e, 0x72, 0x6e, 0xf0, 0xbe, 0x22, 0xc7, 0x9d, 0x97, 0x7c,
+ 0x45, 0xc0, 0xaa, 0x31, 0xe1, 0x55, 0x81, 0xb3, 0xec, 0x98, 0x94, 0xac,
+ 0xf7, 0x15, 0x9b, 0x42, 0x49, 0x8c, 0x2a, 0x29, 0x7a, 0x25, 0x92, 0x64,
+ 0x92, 0xbd, 0x4e, 0x5c, 0xec, 0xff, 0x61, 0xbb, 0x8e, 0x5c, 0xc8, 0xdb,
+ 0xba, 0x97, 0x30, 0xf4, 0x55, 0x9e, 0x1b, 0xfa, 0xbe, 0x2a, 0x90, 0xcf,
+ 0xe8, 0xc0, 0x9d, 0xb0, 0x0e, 0x24, 0x61, 0xe7, 0x3a, 0xb7, 0x7f, 0xda,
+ 0x63, 0xaa, 0x2a, 0x4a, 0xa6, 0x91, 0x52, 0xa6, 0x76, 0xc9, 0xbe, 0x9f,
+ 0x1b, 0x1d, 0xa4, 0x09, 0x5b, 0x0f, 0xd1, 0x64, 0x4e, 0xdf, 0x0c, 0x44,
+ 0x59, 0x3a, 0xef, 0x9a, 0xd8, 0x22, 0xa2, 0x5f, 0x80, 0xb5, 0x4f, 0xbe,
+ 0x84, 0x23, 0xe3, 0x74, 0x77, 0x3c, 0x9e, 0x27, 0x64, 0xac, 0x65, 0xf4,
+ 0xbb, 0x34, 0xb7, 0xa4, 0xfe, 0x02, 0x1a, 0x88, 0x05, 0x3b, 0x4b, 0xb8,
+ 0xd8, 0xb9, 0x26, 0x69, 0x22, 0x97, 0x3d, 0x93, 0x9b, 0xe8, 0x72, 0xaa,
+ 0x4d, 0x8f, 0x76, 0x51, 0x12, 0x59, 0x58, 0xf1, 0x1a, 0xa3, 0xdb, 0x5d,
+ 0xbc, 0xea, 0x84, 0x19, 0x55, 0x4f, 0x00, 0xfb, 0xe2, 0x57, 0x47, 0xca,
+ 0xea, 0xbe, 0x8f, 0x85, 0x8b, 0x1c, 0x27, 0x8d, 0x81, 0x70, 0x7f, 0xf1,
+ 0x56, 0x58, 0xe1, 0x26, 0x94, 0xd8, 0x2f, 0xde, 0xac, 0xc8, 0xac, 0xbf,
+ 0xc3, 0xc6, 0x67, 0xa6, 0xf4, 0x6c, 0xec, 0x20, 0x3c, 0xbc, 0x9d, 0xd9,
+ 0xd0, 0xa1, 0x4e, 0x8c, 0x11, 0x19, 0x2b, 0xb3, 0xa1, 0xdf, 0x6a, 0x8f,
+ 0xa2, 0xc3, 0xcc, 0xf6, 0xbd, 0x09, 0x7a, 0x96, 0x61, 0x20, 0xd4, 0x06,
+ 0x99, 0x4c, 0x6f, 0x23, 0x9b, 0x4c, 0xcc, 0x73, 0x8b, 0x42, 0x48, 0x99,
+ 0x45, 0x8f, 0xcb, 0xc8, 0x46, 0x1a, 0xfb, 0x51, 0x03, 0x6a, 0xf2, 0x22,
+ 0x85, 0x88, 0x9d, 0x61, 0x8b, 0x16, 0x33, 0xf4, 0xf7, 0x9b, 0xc8, 0x21,
+ 0x4f, 0xb1, 0xcd, 0x30, 0xfc, 0x29, 0x88, 0x12, 0xdc, 0xd4, 0x30, 0x4c,
+ 0xb9, 0xad, 0x34, 0xde, 0x01, 0xf8, 0xc1, 0x12, 0xa7, 0x4d, 0xc7, 0x31,
+ 0x99, 0x2b, 0x45, 0x88, 0x06, 0x34, 0x69, 0x6e, 0x6d, 0x34, 0xd8, 0xdd,
+ 0x0a, 0x3d, 0x59, 0x74, 0x36, 0x31, 0x6a, 0xed, 0x91, 0x3b, 0x5b, 0x88,
+ 0x43, 0x46, 0x3f, 0x67, 0x66, 0xe4, 0xde, 0x52, 0xb4, 0xbf, 0x7b, 0x3d,
+ 0x54, 0x79, 0xaf, 0x8d, 0xf5, 0x0a, 0x80, 0xfd, 0xeb, 0x31, 0x24, 0xbc,
+ 0x24, 0xd7, 0x21, 0x9f, 0x87, 0xab, 0xbd, 0x75, 0x2c, 0x13, 0x13, 0x96,
+ 0xab, 0x76, 0xfb, 0xb2, 0x44, 0xd0, 0xd2, 0x19, 0xf1, 0x95, 0x9a, 0x91,
+ 0xbf, 0x7a, 0x7b, 0x76, 0x95, 0x72, 0xa9, 0x16, 0xfc, 0x3e, 0xa9, 0x4e,
+ 0x01, 0x15, 0x3d, 0x43, 0x73, 0xa3, 0x8b, 0xef, 0x48, 0xad, 0x11, 0xbd,
+ 0x53, 0xd3, 0x0c, 0x15, 0x15, 0x1a, 0xb4, 0x3a, 0xe0, 0x7f, 0x9a, 0xa1,
+ 0x36, 0x47, 0x72, 0x92, 0xf0, 0xdf, 0xb0, 0xe2, 0xbc, 0x35, 0xd4, 0x32,
+ 0x6b, 0x37, 0x69, 0x4f, 0x47, 0x9a, 0xe2, 0x35, 0x8a, 0x31, 0x60, 0xed,
+ 0x80, 0x57, 0xe2, 0x9d, 0x58, 0x9c, 0x7f, 0x46, 0xd2, 0x54, 0x0e, 0x28,
+ 0x53, 0x8b, 0x1f, 0x46, 0x34, 0x22, 0xac, 0x71, 0xc7, 0xca, 0x0f, 0xb4,
+ 0xb7, 0x7a, 0xfc, 0x34, 0x57, 0xa5, 0x86, 0x8d, 0x66, 0x5c, 0xc7, 0x3a,
+ 0xdb, 0xf8, 0x79, 0x3a, 0x8a, 0xf6, 0xa2, 0x1e, 0x09, 0xc9, 0x10, 0xe9,
+ 0x93, 0x3a, 0xc5, 0xed, 0xb2, 0xca, 0xbb, 0x66, 0xf1, 0x9d, 0xc9, 0x9c,
+ 0x42, 0x75, 0x64, 0x3e, 0xe4, 0x12, 0x2b, 0x67, 0xf8, 0xbf, 0x2b, 0x98,
+ 0x5d, 0xb6, 0xa0, 0xba, 0x79, 0x98, 0xe0, 0x47, 0x5c, 0x77, 0x85, 0x4e,
+ 0x26, 0x71, 0xfe, 0xab, 0x5c, 0xa8, 0x32, 0x93, 0xec, 0xd0, 0x26, 0x90,
+ 0xe4, 0xda, 0x2f, 0x34, 0x8a, 0x50, 0xb8, 0x3b, 0x7b, 0x4c, 0x5f, 0xa9,
+ 0x3e, 0x8a, 0xa8, 0xf3, 0xc0, 0xb7, 0x50, 0x0b, 0x77, 0x4e, 0x8c, 0xa0,
+ 0xaf, 0xdb, 0x59, 0xe7, 0xac, 0xd1, 0x34, 0x4e, 0x62, 0x47, 0x2e, 0x1e,
+ 0x5e, 0xb4, 0xc9, 0x64, 0xf8, 0x0f, 0xf4, 0xf8, 0xb6, 0x9a, 0xe3, 0x7e,
+ 0xcf, 0xb7, 0xee, 0x11, 0x14, 0x52, 0x89, 0x3b, 0x27, 0x98, 0xfc, 0x95,
+ 0xa7, 0xad, 0xbf, 0x61, 0x34, 0xad, 0x1a, 0x24, 0x2a, 0x48, 0x66, 0x65,
+ 0x75, 0x9c, 0x59, 0xc0, 0x4f, 0x5f, 0x3d, 0x5a, 0x8c, 0xee, 0xd0, 0xb1,
+ 0x17, 0x6d, 0x34, 0x46, 0x37, 0xa0, 0xba, 0x71, 0xac, 0x77, 0x73, 0x29,
+ 0xa3, 0x37, 0x4f, 0x02, 0xd3, 0x7f, 0x0e, 0xe8, 0xce, 0xff, 0x80, 0x11,
+ 0x45, 0x42, 0x03, 0x5a, 0x87, 0xaa, 0xff, 0x25, 0x12, 0x1f, 0x43, 0x19,
+ 0x3e, 0xa9, 0x62, 0x96, 0x0c, 0x6f, 0x33, 0x88, 0x5c, 0xaa, 0xf9, 0xe2,
+ 0xb4, 0xb9, 0xf7, 0x55, 0xae, 0xb5, 0x76, 0x57, 0x47, 0x83, 0xe3, 0xfa,
+ 0x05, 0xda, 0x86, 0x02, 0x97, 0xb4, 0x60, 0xae, 0x59, 0xd5, 0x6c, 0xc1,
+ 0x33, 0xe1, 0x36, 0x36, 0x94, 0x79, 0x9e, 0xad, 0xa3, 0x2d, 0xbc, 0xb5,
+ 0xa2, 0xeb, 0xdd, 0xcd, 0xcb, 0x48, 0x42, 0x15, 0xb8, 0xe6, 0x0e, 0x76,
+ 0x5b, 0x57, 0x74, 0x24, 0xe6, 0x89, 0xc4, 0xe8, 0x08, 0xa9, 0xfe, 0xb3,
+ 0x23, 0xa6, 0xca, 0x72, 0xe2, 0xe4, 0xcb, 0xc1, 0x4a, 0xd1, 0x1d, 0xb9,
+ 0x5e, 0x36, 0x97, 0x19, 0x7c, 0x15, 0x48, 0xf1, 0x2d, 0xeb, 0xec, 0xad,
+ 0x52, 0x6f, 0x2f, 0xe1, 0x19, 0xcf, 0xcf, 0x98, 0x13, 0x0d, 0xcc, 0xb2,
+ 0xa6, 0x8a, 0xda, 0x93, 0x24, 0x3d, 0x5d, 0x83, 0xfe, 0x8d, 0x9e, 0x47,
+ 0xd8, 0x6e, 0x8d, 0x06, 0x52, 0x7d, 0x46, 0x84, 0x04, 0x69, 0x34, 0x61,
+ 0x04, 0x50, 0x1f, 0x86, 0x92, 0x94, 0xe9, 0x0b, 0x13, 0x5b, 0xf6, 0x16,
+ 0x81, 0xeb, 0xfa, 0xf1, 0xbb, 0x04, 0x68, 0x17, 0xca, 0x35, 0x6f, 0xba,
+ 0x4e, 0x4c, 0x33, 0xce, 0xf4, 0x26, 0xb7, 0x74, 0xab, 0xa5, 0xd0, 0xaa,
+ 0x0d, 0x85, 0x11, 0x30, 0x58, 0x62, 0xdf, 0x48, 0xc7, 0xdf, 0xc9, 0x38,
+ 0x9e, 0x6f, 0x96, 0x23, 0x2f, 0xc1, 0xd4, 0x8d, 0x65, 0x9b, 0x46, 0x5f,
+ 0x9c, 0xea, 0x26, 0x60, 0xb5, 0x95, 0x85, 0x71, 0x18, 0xc3, 0xf4, 0x54,
+ 0x61, 0xca, 0xfe, 0x55, 0x3b, 0xbe, 0x81, 0xaf, 0xd9, 0x3a, 0x27, 0xe9,
+ 0x1c, 0x30, 0x82, 0x05, 0x41, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x05, 0x32, 0x04, 0x82, 0x05, 0x2e,
+ 0x30, 0x82, 0x05, 0x2a, 0x30, 0x82, 0x05, 0x26, 0x06, 0x0b, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02, 0xa0, 0x82, 0x04,
+ 0xee, 0x30, 0x82, 0x04, 0xea, 0x30, 0x1c, 0x06, 0x0a, 0x2a, 0x86, 0x48,
+ 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, 0x0e, 0x04, 0x08, 0xd9,
+ 0x68, 0xcb, 0x08, 0x16, 0xc8, 0x93, 0x57, 0x02, 0x02, 0x08, 0x00, 0x04,
+ 0x82, 0x04, 0xc8, 0x7c, 0xdb, 0xa6, 0x1e, 0x33, 0xa4, 0xc6, 0x4e, 0x13,
+ 0x22, 0x7a, 0x1f, 0xc6, 0x82, 0xab, 0x93, 0x5f, 0xf0, 0xa4, 0xe4, 0x40,
+ 0xac, 0xdf, 0x16, 0xec, 0x8d, 0x1f, 0xd9, 0xe4, 0x03, 0xd6, 0xc9, 0xc4,
+ 0x1d, 0xfd, 0xa3, 0xe3, 0xba, 0xfc, 0xcb, 0xd0, 0x47, 0x65, 0x0c, 0x6e,
+ 0x5d, 0xfc, 0xd2, 0xd4, 0x63, 0xa7, 0x93, 0xf6, 0x8a, 0x44, 0x8c, 0xfe,
+ 0x84, 0xd8, 0x0d, 0xa6, 0x16, 0x22, 0xe1, 0x65, 0x10, 0x5e, 0x18, 0x44,
+ 0x58, 0x2f, 0xc7, 0x64, 0x74, 0x5f, 0xcf, 0x73, 0x34, 0xe1, 0x4b, 0xe4,
+ 0xb3, 0x5b, 0xdb, 0x81, 0x4b, 0x1c, 0x38, 0x72, 0xa6, 0xc5, 0xeb, 0x56,
+ 0x9b, 0xc7, 0xe3, 0x3d, 0x54, 0x6e, 0x05, 0x2c, 0xd3, 0x57, 0xc9, 0x4f,
+ 0x80, 0x1e, 0xd7, 0xd8, 0x26, 0x6a, 0xcb, 0x79, 0x46, 0x70, 0xfc, 0x45,
+ 0xa7, 0x79, 0xab, 0x01, 0x03, 0xb6, 0xb1, 0x44, 0x41, 0xd9, 0x73, 0x37,
+ 0xaa, 0xd7, 0xf9, 0x44, 0x93, 0xaf, 0xbb, 0xb5, 0x77, 0xeb, 0x2b, 0x20,
+ 0x2e, 0xbd, 0xea, 0x2f, 0xde, 0xa6, 0x2f, 0xd6, 0xac, 0x74, 0xa5, 0x34,
+ 0xfb, 0xdf, 0xf7, 0x02, 0xa2, 0x20, 0x15, 0xc8, 0x61, 0x72, 0xbb, 0x7f,
+ 0x04, 0xf6, 0x0f, 0xf8, 0x7e, 0xc3, 0xe6, 0xab, 0x2a, 0xe6, 0xd8, 0xe1,
+ 0x0d, 0x5a, 0x3c, 0xc0, 0x58, 0xae, 0xf8, 0x1b, 0x15, 0x3c, 0x7b, 0x7f,
+ 0xf5, 0x9f, 0xec, 0xf7, 0x3f, 0x30, 0x4f, 0x3d, 0x6c, 0x44, 0xdd, 0x0e,
+ 0x4c, 0x2c, 0x93, 0x68, 0x43, 0x31, 0xa8, 0x97, 0x4b, 0xf6, 0x66, 0x71,
+ 0x2a, 0x52, 0x3e, 0x3a, 0xe6, 0x72, 0x8a, 0xe6, 0xe3, 0xc8, 0xff, 0x65,
+ 0x68, 0x1a, 0x46, 0x21, 0xb3, 0xf0, 0x46, 0x7c, 0x0c, 0x65, 0xd1, 0x8e,
+ 0xa4, 0x91, 0x11, 0x5c, 0x93, 0xeb, 0xeb, 0xae, 0x46, 0xf4, 0xbb, 0xf8,
+ 0xf3, 0x7e, 0x20, 0x30, 0xf8, 0xcd, 0x19, 0xcd, 0x54, 0x0a, 0x7f, 0x4f,
+ 0xe8, 0xac, 0xa9, 0xac, 0x72, 0x96, 0x80, 0x45, 0x2a, 0x4a, 0x63, 0x90,
+ 0x01, 0x19, 0xd0, 0x7e, 0x26, 0x53, 0x2d, 0xc4, 0x20, 0xa5, 0x1f, 0x89,
+ 0x67, 0x0f, 0xd9, 0x75, 0x51, 0x0a, 0xf1, 0xd4, 0xfd, 0x2e, 0xbe, 0xe6,
+ 0x94, 0x3b, 0x6c, 0x8c, 0xe3, 0x0f, 0x5f, 0xce, 0x58, 0x48, 0xde, 0x8d,
+ 0xeb, 0xd3, 0xe1, 0x0a, 0xcd, 0xdf, 0x34, 0x4d, 0xd1, 0x5b, 0xab, 0x41,
+ 0x41, 0x6b, 0xeb, 0xa1, 0x2f, 0x01, 0x4a, 0x72, 0x2e, 0xf4, 0x5e, 0x44,
+ 0x76, 0xc7, 0xe6, 0x16, 0xb9, 0xfb, 0x10, 0x37, 0x00, 0x2d, 0xc6, 0x3b,
+ 0x17, 0x72, 0x21, 0xdb, 0xac, 0x86, 0x7b, 0xf5, 0x70, 0x3f, 0x73, 0xa3,
+ 0xce, 0x0e, 0x20, 0xbb, 0x59, 0x4c, 0x23, 0xc2, 0xe8, 0x22, 0x22, 0xe0,
+ 0x02, 0x0d, 0xe4, 0xa2, 0x3f, 0x55, 0x9d, 0xc0, 0xeb, 0x9a, 0xc4, 0xf3,
+ 0xaa, 0xb8, 0xf1, 0x73, 0xec, 0x47, 0xe8, 0x2d, 0x6b, 0xa1, 0x40, 0x94,
+ 0xf6, 0x07, 0xb9, 0x6f, 0x03, 0x5a, 0x78, 0xe5, 0x59, 0x41, 0x1a, 0xc7,
+ 0xcd, 0x43, 0x10, 0x20, 0x28, 0x95, 0xe0, 0x2a, 0x6f, 0xf2, 0xf8, 0x12,
+ 0xd6, 0x13, 0x7f, 0x37, 0x3d, 0x38, 0xa7, 0x22, 0x91, 0xc6, 0xe3, 0x52,
+ 0xde, 0xd8, 0xbf, 0x78, 0x9a, 0xa4, 0xf7, 0xc0, 0x8c, 0xbf, 0x81, 0x28,
+ 0x20, 0xb8, 0x01, 0xde, 0xb5, 0x6b, 0x0a, 0x56, 0x12, 0x5c, 0x62, 0x1d,
+ 0xaf, 0xb7, 0xf2, 0x74, 0x66, 0x0a, 0x7a, 0xc4, 0x9f, 0x1e, 0xc2, 0xa8,
+ 0x4c, 0xd6, 0x76, 0x6d, 0x74, 0x35, 0x37, 0x12, 0x5c, 0x95, 0xee, 0x98,
+ 0x1d, 0xe2, 0x91, 0xde, 0x13, 0x08, 0xd0, 0x59, 0x4d, 0x62, 0x92, 0x69,
+ 0x1b, 0xf7, 0x21, 0x45, 0xaf, 0x83, 0xf8, 0x64, 0xf0, 0xfb, 0x92, 0x9d,
+ 0xa1, 0xd9, 0x61, 0x5e, 0x00, 0xc8, 0x1a, 0x6e, 0x6a, 0x2d, 0xad, 0xa8,
+ 0x1b, 0x0e, 0xaf, 0xea, 0xb2, 0xae, 0x1c, 0x89, 0xc7, 0x4d, 0x2c, 0x0f,
+ 0x4d, 0x8d, 0x78, 0x8d, 0x15, 0x9d, 0x4c, 0x90, 0x52, 0xa1, 0xa9, 0xd8,
+ 0xb2, 0x66, 0xb9, 0xb1, 0x46, 0x0a, 0x69, 0x86, 0x2b, 0x0f, 0xb2, 0x41,
+ 0xce, 0xe8, 0x8e, 0x49, 0x97, 0x08, 0x0b, 0x70, 0x97, 0xcb, 0xa4, 0x33,
+ 0x3f, 0x83, 0x6b, 0x6c, 0x17, 0xce, 0xd8, 0xd5, 0x9b, 0xd4, 0x55, 0x9b,
+ 0x99, 0xe1, 0xba, 0x61, 0x31, 0x36, 0x79, 0x31, 0x5f, 0xa1, 0x8c, 0xa9,
+ 0x77, 0x42, 0xaa, 0x8c, 0x45, 0x6e, 0xb6, 0x90, 0x08, 0xe8, 0x2e, 0xc4,
+ 0x72, 0x69, 0x42, 0xca, 0xa2, 0xd4, 0x8a, 0x2c, 0x37, 0xe1, 0xde, 0xb8,
+ 0x98, 0x36, 0xeb, 0xcc, 0x58, 0x0c, 0x24, 0xad, 0xab, 0x62, 0x44, 0x6d,
+ 0x80, 0xd5, 0xce, 0x2e, 0x4a, 0x3e, 0xa5, 0xc5, 0x34, 0xf8, 0x32, 0x26,
+ 0x2a, 0x56, 0xa4, 0xdd, 0xe9, 0x92, 0x06, 0xad, 0xe8, 0x85, 0x77, 0x6b,
+ 0xf1, 0x1b, 0xeb, 0xac, 0x77, 0x19, 0x1c, 0x6a, 0xb7, 0xef, 0x28, 0x70,
+ 0x87, 0x92, 0x33, 0xdd, 0xaa, 0x30, 0xc1, 0xa0, 0x93, 0x64, 0x18, 0xa2,
+ 0x91, 0x7f, 0xf7, 0xc4, 0xa5, 0x16, 0x93, 0xb3, 0x5b, 0xd8, 0x53, 0x28,
+ 0xc5, 0x5e, 0xb1, 0xce, 0x97, 0xbc, 0xb6, 0x65, 0xa8, 0x53, 0xcd, 0xf4,
+ 0x4d, 0x6b, 0xea, 0x6f, 0x6f, 0xa5, 0x1c, 0xf1, 0x0f, 0xcb, 0x04, 0x25,
+ 0x4a, 0xfe, 0x7d, 0xfc, 0xa3, 0xbd, 0x41, 0xd3, 0x96, 0x6a, 0x8b, 0xad,
+ 0xd4, 0xaa, 0x0a, 0x76, 0xea, 0x3b, 0xab, 0x39, 0x55, 0xa3, 0x89, 0x9f,
+ 0xf6, 0xf5, 0x9b, 0x9c, 0x83, 0xf8, 0x28, 0x50, 0xdf, 0x31, 0x74, 0x83,
+ 0xdb, 0xf1, 0x0f, 0x4c, 0x35, 0x6a, 0xe5, 0x64, 0x2e, 0xb9, 0x77, 0x3d,
+ 0xdd, 0xff, 0xa3, 0xa7, 0x90, 0x79, 0xc6, 0x5b, 0x01, 0x16, 0x38, 0xa8,
+ 0x22, 0xa3, 0x14, 0x13, 0xed, 0xd0, 0x89, 0x0d, 0x1f, 0x3a, 0x41, 0x4c,
+ 0x57, 0x79, 0xfc, 0x1d, 0xdf, 0xad, 0x1a, 0x11, 0x15, 0x31, 0x7e, 0xdb,
+ 0x99, 0x3a, 0x6c, 0xde, 0x94, 0x9a, 0x45, 0x4c, 0xfb, 0xa5, 0xa5, 0x31,
+ 0xee, 0xe3, 0x09, 0x13, 0x6d, 0xfd, 0x19, 0x37, 0x3f, 0xf6, 0xed, 0x8f,
+ 0x0c, 0xce, 0x4b, 0xd1, 0xe1, 0x3d, 0xfb, 0x85, 0x00, 0x84, 0x19, 0xeb,
+ 0xa2, 0x63, 0x1d, 0x2b, 0x2d, 0x21, 0xee, 0x08, 0x5a, 0x6d, 0xb0, 0xb1,
+ 0xd6, 0x81, 0x00, 0xb6, 0xd0, 0x09, 0x90, 0xb4, 0x84, 0x17, 0xd9, 0x2a,
+ 0x3c, 0x1d, 0x53, 0xc6, 0xc1, 0x8b, 0xda, 0xae, 0x0c, 0x0a, 0x3e, 0x1c,
+ 0x8a, 0xc4, 0xd6, 0x97, 0x5d, 0x48, 0xe7, 0x79, 0x80, 0x78, 0xaa, 0xde,
+ 0x17, 0x60, 0x5d, 0x28, 0x15, 0x3a, 0x42, 0xb7, 0x85, 0xc8, 0x60, 0x93,
+ 0x28, 0xb0, 0x4e, 0xc9, 0xf7, 0x46, 0xe7, 0xfc, 0x4e, 0x9f, 0x9f, 0x12,
+ 0xdf, 0xcb, 0x6e, 0x0c, 0xaf, 0x71, 0xda, 0xb7, 0xec, 0x3d, 0x46, 0xf3,
+ 0x35, 0x41, 0x42, 0xd8, 0x27, 0x92, 0x99, 0x1c, 0x4d, 0xc9, 0x3c, 0xe9,
+ 0x0e, 0xcb, 0x3f, 0x57, 0x65, 0x77, 0x0d, 0xdd, 0xff, 0xea, 0x70, 0x35,
+ 0xcc, 0xf5, 0x38, 0x1b, 0x57, 0xdf, 0x6d, 0xcb, 0xfd, 0x13, 0x39, 0xd6,
+ 0x04, 0xe2, 0xf1, 0xc2, 0xd9, 0xea, 0x8c, 0x9f, 0xfb, 0xb5, 0xfc, 0xe6,
+ 0xa9, 0xaa, 0x0f, 0x43, 0xc9, 0x9c, 0x91, 0xe4, 0x21, 0xaf, 0x37, 0x14,
+ 0x78, 0x46, 0xe1, 0x29, 0x41, 0x0c, 0x4e, 0xf5, 0x93, 0x1d, 0xf8, 0x33,
+ 0x47, 0x6f, 0x9d, 0x8b, 0xf3, 0x27, 0xd4, 0xbb, 0xf6, 0xae, 0xfa, 0xa5,
+ 0x8b, 0x41, 0x8f, 0xb4, 0xd7, 0x2f, 0xc1, 0x27, 0xea, 0x70, 0x55, 0x1d,
+ 0xe2, 0xd8, 0x0c, 0x4a, 0x5e, 0x7c, 0x87, 0xa4, 0x0e, 0x84, 0x07, 0xd3,
+ 0x38, 0x67, 0x2c, 0x55, 0x11, 0xfd, 0x1e, 0xda, 0x4d, 0x66, 0x01, 0x12,
+ 0x0c, 0x1b, 0x7c, 0x7c, 0x5c, 0x82, 0x21, 0x35, 0x65, 0x5c, 0x7a, 0xd2,
+ 0x66, 0xc2, 0x2b, 0x5e, 0xb8, 0xb1, 0xcb, 0xdf, 0x59, 0xc9, 0x31, 0xb7,
+ 0x17, 0x26, 0x96, 0x5e, 0x6f, 0x1c, 0x62, 0x3d, 0x8d, 0x88, 0xf1, 0xd1,
+ 0x01, 0x3e, 0xf9, 0x6f, 0xb9, 0x77, 0xdc, 0xee, 0xee, 0x78, 0x59, 0xef,
+ 0xcf, 0x3a, 0x87, 0x88, 0xa2, 0xea, 0xfd, 0x0a, 0xa9, 0xa9, 0x3e, 0x0c,
+ 0xf8, 0x7f, 0x97, 0x32, 0x17, 0xc2, 0x97, 0xcb, 0xa4, 0x9b, 0xae, 0x5d,
+ 0xe7, 0x39, 0x2b, 0x2b, 0xa8, 0xe6, 0x7b, 0x51, 0x75, 0x1f, 0x53, 0x54,
+ 0x37, 0xf4, 0x00, 0xa4, 0xb0, 0xa0, 0x93, 0xb4, 0x33, 0xe7, 0xae, 0x28,
+ 0xc0, 0x2d, 0x3a, 0xb3, 0xaa, 0xd7, 0x3c, 0x76, 0x44, 0x4b, 0xbb, 0x6a,
+ 0x67, 0x98, 0xce, 0xf8, 0x15, 0x13, 0x67, 0x79, 0x3c, 0x15, 0x09, 0xb7,
+ 0x22, 0xc0, 0xec, 0x07, 0x8a, 0xfd, 0x44, 0xcb, 0x99, 0xbd, 0xdc, 0xd5,
+ 0x53, 0x4c, 0x97, 0x1b, 0x46, 0xaf, 0xc0, 0x6c, 0x06, 0x01, 0x93, 0x8a,
+ 0x50, 0x51, 0x6a, 0xe4, 0x5c, 0x0a, 0x52, 0x81, 0x3b, 0x75, 0xed, 0xa2,
+ 0x97, 0xa6, 0x5c, 0x55, 0x63, 0xee, 0xfb, 0x33, 0x82, 0x10, 0xa8, 0x21,
+ 0x1a, 0x8d, 0xc8, 0xe1, 0x52, 0x68, 0x38, 0x88, 0x2f, 0xae, 0x2b, 0x22,
+ 0x7a, 0x9b, 0x0c, 0x19, 0x73, 0x6f, 0x91, 0xc7, 0xfa, 0x95, 0x61, 0x28,
+ 0x74, 0x73, 0x70, 0x31, 0x25, 0x30, 0x23, 0x06, 0x09, 0x2a, 0x86, 0x48,
+ 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x15, 0x31, 0x16, 0x04, 0x14, 0x14, 0x74,
+ 0x2d, 0x52, 0x8e, 0x0d, 0x0c, 0x06, 0x6c, 0x32, 0x64, 0xd3, 0x7e, 0x33,
+ 0x31, 0x68, 0x8b, 0x28, 0x1a, 0x75, 0x30, 0x31, 0x30, 0x21, 0x30, 0x09,
+ 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x22,
+ 0x8e, 0xff, 0x5a, 0x78, 0xec, 0x2c, 0x21, 0xa2, 0x48, 0xb7, 0x63, 0x88,
+ 0x10, 0x47, 0x1c, 0xc0, 0xd3, 0xec, 0x5a, 0x04, 0x08, 0xb3, 0x2e, 0x21,
+ 0xfd, 0x82, 0x14, 0xd8, 0x5c, 0x02, 0x02, 0x08, 0x00,
+};
+
+/* kNSS is the result of importing the OpenSSL example PKCS#12 into Chrome and
+ * then exporting it again. */
+static const uint8_t kNSS[] = {
+ 0x30, 0x80, 0x02, 0x01, 0x03, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48,
+ 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x82,
+ 0x09, 0xef, 0x30, 0x80, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, 0x04, 0x82, 0x05,
+ 0x77, 0x30, 0x82, 0x05, 0x73, 0x30, 0x82, 0x05, 0x6f, 0x06, 0x0b, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02, 0xa0, 0x82,
+ 0x04, 0xf6, 0x30, 0x82, 0x04, 0xf2, 0x30, 0x24, 0x06, 0x0a, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, 0x16, 0x04, 0x10,
+ 0xac, 0x71, 0x8a, 0x7c, 0x89, 0xcf, 0xa8, 0xb0, 0xd6, 0xd1, 0x07, 0xf0,
+ 0x83, 0x4f, 0x7a, 0xd0, 0x02, 0x02, 0x07, 0xd0, 0x04, 0x82, 0x04, 0xc8,
+ 0xea, 0x51, 0x2c, 0x61, 0xaa, 0x9d, 0xf3, 0x90, 0xe1, 0x38, 0x45, 0xb0,
+ 0x5f, 0xfd, 0xe2, 0x04, 0x65, 0xe6, 0xff, 0x87, 0xb6, 0x78, 0x69, 0xb0,
+ 0xcb, 0x14, 0xe9, 0x99, 0x39, 0xe3, 0xe5, 0x70, 0x84, 0x57, 0x68, 0xf7,
+ 0x28, 0xb9, 0x75, 0xa6, 0xfb, 0x16, 0x72, 0xe1, 0x34, 0xb8, 0x3b, 0x61,
+ 0x51, 0x89, 0x18, 0x94, 0x40, 0xef, 0x73, 0xda, 0xdb, 0xd7, 0xb7, 0x44,
+ 0x73, 0x8f, 0x16, 0x84, 0xa2, 0x99, 0xa6, 0x05, 0x5e, 0x74, 0xae, 0xe2,
+ 0xcf, 0x3e, 0x99, 0xca, 0xcd, 0x76, 0x36, 0x77, 0x59, 0xec, 0x25, 0x59,
+ 0x3d, 0x4b, 0x45, 0xa5, 0x4e, 0x7b, 0x7a, 0xc9, 0x8b, 0xde, 0x4f, 0x70,
+ 0x6d, 0xb1, 0xa8, 0xf3, 0xb6, 0xb5, 0xe7, 0x67, 0x3f, 0xe9, 0x64, 0xb8,
+ 0x49, 0xf4, 0x11, 0x94, 0x9d, 0x1c, 0xb0, 0xa5, 0xfb, 0xb3, 0x61, 0xd4,
+ 0xf3, 0xa7, 0x68, 0x66, 0xd7, 0xa4, 0xf0, 0xcd, 0xc8, 0x40, 0x4f, 0x3e,
+ 0xa7, 0x26, 0x40, 0x76, 0x64, 0xa1, 0x4e, 0xf1, 0x91, 0xc2, 0xa3, 0xef,
+ 0xbc, 0xcd, 0x42, 0xe5, 0xd2, 0x6f, 0xff, 0xfe, 0x4d, 0x33, 0x01, 0xb4,
+ 0x99, 0x63, 0x1b, 0xd3, 0x01, 0x55, 0x00, 0xa6, 0x23, 0x9b, 0xa9, 0x17,
+ 0x09, 0x38, 0x32, 0x18, 0x36, 0xbc, 0x20, 0x02, 0xfe, 0x7b, 0xec, 0xd3,
+ 0x4c, 0x7d, 0xc9, 0xc9, 0xce, 0x66, 0x3b, 0x34, 0x6e, 0xea, 0xf9, 0xb1,
+ 0x1a, 0x83, 0xa3, 0x3c, 0x8d, 0xc7, 0x79, 0xc9, 0xff, 0x6b, 0x1d, 0x35,
+ 0xf6, 0x2a, 0x3d, 0x3b, 0x83, 0x16, 0x64, 0xcf, 0x9f, 0x7c, 0x31, 0x02,
+ 0xda, 0x37, 0x1a, 0x16, 0x49, 0xdc, 0xd9, 0x70, 0xae, 0x99, 0x2c, 0xc7,
+ 0x01, 0xba, 0x42, 0xab, 0xe9, 0x4d, 0xa4, 0x78, 0x2c, 0xbd, 0xa0, 0xf1,
+ 0xb7, 0xcf, 0xdd, 0xc1, 0xdb, 0x8f, 0x04, 0x87, 0x0b, 0x47, 0x4f, 0xd5,
+ 0xd5, 0xe7, 0xfc, 0x6e, 0x42, 0xd5, 0x91, 0x4d, 0x7b, 0x1b, 0x5c, 0x3c,
+ 0x02, 0x70, 0xdb, 0x05, 0x91, 0xaf, 0x35, 0x43, 0x05, 0xc2, 0x6d, 0xcf,
+ 0x59, 0x23, 0xfc, 0xc4, 0xf6, 0x67, 0xf1, 0x84, 0x61, 0x4a, 0xb6, 0x4c,
+ 0x15, 0x15, 0xa3, 0xea, 0x8f, 0x13, 0x15, 0xe3, 0xd2, 0xb5, 0x50, 0xc8,
+ 0xae, 0xc8, 0x5c, 0x03, 0xb5, 0x63, 0x93, 0xaa, 0x10, 0xd7, 0x56, 0x0d,
+ 0x6e, 0x13, 0x45, 0x8f, 0xec, 0x17, 0x5c, 0x5c, 0x73, 0x91, 0x5f, 0x6c,
+ 0xaf, 0x11, 0x13, 0x32, 0x5e, 0x14, 0xf9, 0xaf, 0xaf, 0x43, 0x04, 0x60,
+ 0x93, 0x42, 0x30, 0xa6, 0x75, 0xc0, 0x83, 0xd2, 0x4c, 0xa5, 0x0a, 0x16,
+ 0x39, 0xef, 0x3f, 0xf7, 0x9d, 0x23, 0x19, 0xb9, 0xcd, 0xd8, 0x7c, 0x6e,
+ 0xee, 0x6d, 0x2e, 0xff, 0x5a, 0xf3, 0xb9, 0xab, 0xe5, 0x64, 0xdc, 0xc2,
+ 0x67, 0x30, 0x73, 0x19, 0x2d, 0xea, 0xd2, 0x19, 0x1f, 0x1f, 0xe0, 0xd9,
+ 0xac, 0xc9, 0xdb, 0x38, 0x74, 0x5e, 0x31, 0x47, 0x2e, 0x9e, 0x2b, 0xcc,
+ 0xb9, 0xe4, 0x29, 0xf8, 0xb2, 0xbf, 0x1b, 0xbc, 0x68, 0x96, 0x79, 0xcf,
+ 0xaf, 0xf2, 0x1f, 0x57, 0x3f, 0x74, 0xc4, 0x71, 0x63, 0xb4, 0xe8, 0xbe,
+ 0x58, 0xdb, 0x28, 0x62, 0xb5, 0x79, 0x8b, 0xe4, 0xd0, 0x96, 0xd0, 0xda,
+ 0x0f, 0xd2, 0x70, 0x93, 0x2f, 0x71, 0xe0, 0x9f, 0x28, 0xb7, 0x52, 0x38,
+ 0x9c, 0xcb, 0x8b, 0x2a, 0x8e, 0xbf, 0x0e, 0x3d, 0x60, 0x05, 0x0a, 0x91,
+ 0x5b, 0xb5, 0x78, 0x10, 0x31, 0x00, 0x80, 0x31, 0x2d, 0xd7, 0xb0, 0x88,
+ 0xc7, 0xd9, 0x58, 0xc6, 0xfc, 0x3b, 0xf4, 0xee, 0xec, 0xba, 0x05, 0xae,
+ 0xae, 0xff, 0xcf, 0xd0, 0x71, 0xc6, 0xe7, 0xf3, 0x8b, 0x64, 0x50, 0x7a,
+ 0x09, 0x93, 0x0f, 0x34, 0x59, 0x2d, 0xde, 0x4b, 0x1d, 0x86, 0x49, 0xff,
+ 0x63, 0x76, 0x28, 0x6b, 0x52, 0x1b, 0x46, 0x06, 0x18, 0x90, 0x1c, 0x2d,
+ 0xc5, 0x03, 0xcc, 0x00, 0x4d, 0xb7, 0xb2, 0x12, 0xc5, 0xf9, 0xb4, 0xa4,
+ 0x6a, 0x36, 0x62, 0x46, 0x34, 0x2a, 0xf0, 0x11, 0xa3, 0xd6, 0x80, 0x21,
+ 0xbf, 0x3b, 0xfd, 0xc5, 0x25, 0xa0, 0x4d, 0xc0, 0x2e, 0xc0, 0xf1, 0x7b,
+ 0x96, 0x11, 0x64, 0x8e, 0xb9, 0xdb, 0x89, 0x4e, 0x33, 0x89, 0xf5, 0xc6,
+ 0xfc, 0x2b, 0x99, 0xf5, 0xc2, 0x04, 0x83, 0x15, 0x47, 0xa8, 0xa5, 0xc1,
+ 0x4a, 0xe4, 0x76, 0xab, 0x3e, 0xf0, 0x9b, 0xb7, 0x8d, 0x46, 0xd3, 0x52,
+ 0x9b, 0xbd, 0xfd, 0x2b, 0xba, 0x73, 0x5d, 0x23, 0x67, 0x68, 0xe1, 0x76,
+ 0x6f, 0x56, 0x2b, 0x17, 0xe4, 0x7e, 0x9a, 0xfd, 0x05, 0x48, 0x39, 0xc9,
+ 0xcf, 0xa5, 0x83, 0xf7, 0x90, 0x9c, 0xa4, 0x28, 0x57, 0x40, 0xe9, 0xd4,
+ 0x4b, 0x1a, 0x4b, 0x6f, 0x65, 0x14, 0xca, 0x43, 0xc1, 0x3f, 0x7c, 0xec,
+ 0x82, 0x47, 0x0e, 0x64, 0x8b, 0x6f, 0x8c, 0xb2, 0xf0, 0x6d, 0xeb, 0x6f,
+ 0x71, 0x8f, 0xcc, 0x2d, 0x60, 0x2b, 0xc3, 0x9f, 0x13, 0x94, 0xc7, 0x23,
+ 0x02, 0xf5, 0xe6, 0xdf, 0x2d, 0xa9, 0xdb, 0xa9, 0xf3, 0xee, 0xe9, 0x3f,
+ 0x2a, 0x69, 0x24, 0x6b, 0x78, 0xff, 0x6a, 0xd7, 0xe4, 0x69, 0x8c, 0x17,
+ 0xd5, 0xc1, 0x36, 0x1a, 0xca, 0x77, 0xb0, 0xb5, 0x6b, 0x96, 0x4a, 0xb5,
+ 0x0e, 0x4d, 0x0b, 0xd6, 0xd9, 0x78, 0xc5, 0xbf, 0xe3, 0x59, 0xfe, 0x63,
+ 0xe3, 0xd3, 0x3c, 0x9a, 0xfa, 0xd7, 0x69, 0x5b, 0xef, 0xd3, 0xa4, 0xa3,
+ 0xb9, 0x1f, 0x5c, 0x40, 0x20, 0x95, 0x38, 0x2d, 0xf5, 0x04, 0x0c, 0x2c,
+ 0x79, 0x77, 0xc1, 0xb6, 0xcc, 0x74, 0x3c, 0x66, 0xf1, 0xc6, 0x65, 0xab,
+ 0x4d, 0x68, 0x41, 0x16, 0x71, 0x51, 0xb9, 0x1b, 0xcb, 0xa7, 0x6d, 0xe0,
+ 0x70, 0xa9, 0xfa, 0x65, 0x6b, 0x7b, 0x1e, 0xc5, 0xdf, 0xe2, 0x4c, 0x96,
+ 0x44, 0x6b, 0x24, 0xa1, 0x15, 0x8e, 0xe7, 0x9b, 0x1f, 0x51, 0xef, 0xd7,
+ 0x65, 0x5f, 0xcd, 0x74, 0x7f, 0x2d, 0x5c, 0xba, 0xba, 0x20, 0x32, 0x8d,
+ 0x1c, 0xf1, 0x5a, 0xed, 0x21, 0xad, 0x78, 0x7b, 0x59, 0x58, 0xe4, 0xf6,
+ 0xa7, 0x10, 0x35, 0xca, 0x5d, 0x86, 0x1a, 0x68, 0xba, 0x1c, 0x3c, 0x1c,
+ 0x23, 0x79, 0x8b, 0x9f, 0xda, 0x5c, 0xd1, 0x5a, 0xa9, 0xc8, 0xf6, 0xc9,
+ 0xdf, 0x21, 0x5a, 0x98, 0xdc, 0xf4, 0xb9, 0x02, 0x97, 0x2c, 0x10, 0x60,
+ 0xc9, 0xb5, 0xea, 0x75, 0x0b, 0xd9, 0x8a, 0xa4, 0x86, 0x92, 0xbe, 0xf5,
+ 0xd8, 0xc7, 0x6b, 0x13, 0x8b, 0xbb, 0xca, 0x5f, 0xe4, 0x8b, 0xce, 0xb5,
+ 0x27, 0xae, 0x53, 0xed, 0xef, 0x37, 0xa6, 0x81, 0x8f, 0x70, 0x25, 0x18,
+ 0x93, 0x06, 0x8c, 0x18, 0xcd, 0x7a, 0x1a, 0x8d, 0xfc, 0xde, 0x6f, 0x30,
+ 0xdb, 0x41, 0xb6, 0x42, 0x14, 0x54, 0xf8, 0xcd, 0xc6, 0xf8, 0x0f, 0x82,
+ 0x17, 0xfa, 0x8d, 0xba, 0x80, 0x81, 0x6a, 0xf7, 0x02, 0x97, 0x00, 0x78,
+ 0xd6, 0x5b, 0xc9, 0xba, 0xd1, 0x99, 0xef, 0x8e, 0x48, 0x6c, 0x35, 0x10,
+ 0x5b, 0xf1, 0x9b, 0x93, 0x4f, 0xbd, 0x7d, 0x27, 0x9e, 0xc7, 0x86, 0xb2,
+ 0x8f, 0x6a, 0x91, 0x59, 0x2d, 0x14, 0xab, 0x1b, 0x34, 0x6e, 0xfa, 0x25,
+ 0x5e, 0x14, 0xc7, 0xef, 0x3d, 0x0f, 0x13, 0xf9, 0x45, 0x4b, 0x90, 0xbc,
+ 0xd8, 0x51, 0x42, 0x95, 0x25, 0x9b, 0x1b, 0x7c, 0xaf, 0x3b, 0x60, 0x21,
+ 0x4c, 0x5f, 0x7c, 0x63, 0x4b, 0x45, 0xa6, 0xdc, 0xfd, 0x32, 0xf3, 0x06,
+ 0x61, 0x11, 0x2d, 0x27, 0xde, 0x19, 0x38, 0x63, 0xf9, 0x70, 0xd1, 0x82,
+ 0x8e, 0xc7, 0x99, 0xe1, 0x96, 0x9b, 0x54, 0x93, 0x64, 0x5f, 0xd1, 0x62,
+ 0x9c, 0x37, 0x10, 0x1a, 0x8a, 0x82, 0x8d, 0x2a, 0x93, 0x95, 0x22, 0xc9,
+ 0x21, 0xf5, 0xce, 0x21, 0xbb, 0x7c, 0x17, 0xee, 0x20, 0xa0, 0x73, 0xaa,
+ 0x69, 0x78, 0x4e, 0x0d, 0x2c, 0x2c, 0x96, 0x23, 0xdc, 0x07, 0x16, 0xbd,
+ 0xe7, 0xd5, 0x49, 0xcc, 0x44, 0xd1, 0x9d, 0xd7, 0xa3, 0x01, 0x60, 0xa0,
+ 0xe0, 0x41, 0x63, 0x28, 0x8a, 0x43, 0xdb, 0x4f, 0x25, 0x5b, 0x27, 0x52,
+ 0x4a, 0xee, 0x42, 0x43, 0x9a, 0xef, 0x33, 0x43, 0x70, 0xda, 0x64, 0x57,
+ 0x49, 0x0c, 0x7f, 0xfd, 0xc7, 0x88, 0x26, 0x94, 0x10, 0xcc, 0x05, 0x1d,
+ 0x54, 0x95, 0xea, 0x4e, 0x65, 0x28, 0x03, 0xbc, 0xa2, 0x62, 0xd2, 0xce,
+ 0x60, 0x34, 0xf9, 0xdb, 0x26, 0xb5, 0xe6, 0x9b, 0x55, 0x2c, 0x8f, 0x30,
+ 0x3a, 0x94, 0x9a, 0x15, 0x79, 0x22, 0x75, 0x4d, 0x1b, 0x91, 0xe0, 0x5b,
+ 0xdb, 0xd1, 0x15, 0x7f, 0xcc, 0xc6, 0x88, 0xb5, 0x00, 0x3f, 0x5d, 0x84,
+ 0x2e, 0x68, 0xde, 0x6f, 0x41, 0x5b, 0x4e, 0xe7, 0xdf, 0xe6, 0x3b, 0x7e,
+ 0xf2, 0xdd, 0xfc, 0x01, 0xf2, 0x1b, 0x52, 0xba, 0xc4, 0x51, 0xae, 0x8f,
+ 0xa0, 0x55, 0x12, 0x81, 0x57, 0xe0, 0x58, 0x5e, 0xea, 0xd7, 0x85, 0xfb,
+ 0x19, 0x8b, 0xb7, 0x24, 0x29, 0x94, 0xa7, 0xfc, 0xed, 0x17, 0xaa, 0x32,
+ 0x50, 0x11, 0xb3, 0x7a, 0x43, 0x3a, 0xc0, 0x2b, 0x82, 0x9c, 0x85, 0xd9,
+ 0xd0, 0xdb, 0x21, 0x71, 0x83, 0xb4, 0x30, 0x14, 0xec, 0xfc, 0x8d, 0x32,
+ 0xd6, 0xa2, 0x36, 0x5e, 0x3b, 0xe9, 0x12, 0x0c, 0x95, 0xd6, 0x0c, 0x0c,
+ 0x31, 0x66, 0x30, 0x3f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x09, 0x14, 0x31, 0x32, 0x1e, 0x30, 0x00, 0x49, 0x00, 0x6e, 0x00,
+ 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x74, 0x00,
+ 0x20, 0x00, 0x57, 0x00, 0x69, 0x00, 0x64, 0x00, 0x67, 0x00, 0x69, 0x00,
+ 0x74, 0x00, 0x73, 0x00, 0x20, 0x00, 0x50, 0x00, 0x74, 0x00, 0x79, 0x00,
+ 0x20, 0x00, 0x4c, 0x00, 0x74, 0x00, 0x64, 0x30, 0x23, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x15, 0x31, 0x16, 0x04, 0x14,
+ 0x14, 0x74, 0x2d, 0x52, 0x8e, 0x0d, 0x0c, 0x06, 0x6c, 0x32, 0x64, 0xd3,
+ 0x7e, 0x33, 0x31, 0x68, 0x8b, 0x28, 0x1a, 0x75, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x07, 0x06, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x00, 0x30, 0x80,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30,
+ 0x24, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01,
+ 0x06, 0x30, 0x16, 0x04, 0x10, 0x9d, 0x1b, 0x68, 0x8e, 0x11, 0xc2, 0xb2,
+ 0xd6, 0xd0, 0xe9, 0x5a, 0x9e, 0x96, 0xc1, 0x8c, 0xa6, 0x02, 0x02, 0x07,
+ 0xd0, 0xa0, 0x80, 0x04, 0x82, 0x03, 0xf8, 0x1d, 0xce, 0x13, 0x70, 0x7a,
+ 0x6b, 0x0a, 0x12, 0x2d, 0x01, 0x84, 0x63, 0x5c, 0x07, 0x82, 0x23, 0xf8,
+ 0x8a, 0x5e, 0x53, 0x8f, 0xc8, 0xb4, 0x87, 0x1a, 0xa2, 0x98, 0xdb, 0xc6,
+ 0x26, 0xca, 0xbb, 0x20, 0x24, 0xad, 0xac, 0xdf, 0xbe, 0x73, 0x6d, 0x97,
+ 0x4b, 0x6e, 0x5b, 0x45, 0xd2, 0x84, 0xd4, 0xa4, 0x82, 0xd0, 0xce, 0x40,
+ 0x13, 0x4c, 0x6d, 0x4d, 0x2e, 0xc1, 0x96, 0x95, 0x01, 0x64, 0xf3, 0xf0,
+ 0x5f, 0x06, 0x06, 0xea, 0xf7, 0x84, 0x8f, 0xb3, 0xb0, 0x6e, 0x7c, 0x9b,
+ 0x71, 0x73, 0xb9, 0xcd, 0xac, 0x72, 0xf6, 0xa0, 0x23, 0xda, 0x9b, 0x9f,
+ 0xec, 0x16, 0xef, 0x33, 0xd4, 0xd0, 0x4d, 0x20, 0xf0, 0x75, 0xa9, 0x73,
+ 0xf4, 0x31, 0xc7, 0x57, 0xb8, 0x0d, 0x9d, 0x85, 0x7c, 0xee, 0x3a, 0x24,
+ 0x7b, 0x74, 0xa0, 0x5c, 0xad, 0xde, 0x5e, 0x05, 0x1e, 0xeb, 0x02, 0x78,
+ 0x12, 0xb4, 0xb9, 0xc6, 0xe5, 0xc5, 0x99, 0xbc, 0x05, 0x62, 0x5b, 0x10,
+ 0x52, 0x08, 0x00, 0x9e, 0x73, 0xac, 0xe4, 0x1d, 0xdb, 0xb8, 0xbf, 0x48,
+ 0x03, 0x28, 0x05, 0x3c, 0x61, 0x1a, 0x8b, 0x4c, 0xd7, 0x5f, 0x8c, 0xb4,
+ 0xcd, 0x91, 0x1c, 0x0b, 0xf4, 0x55, 0xd4, 0x1c, 0x42, 0x4a, 0xd4, 0xf5,
+ 0x15, 0x38, 0xd9, 0x06, 0xfc, 0x49, 0xf6, 0xe5, 0xa7, 0x09, 0x5d, 0x01,
+ 0xbd, 0xc3, 0xd1, 0x09, 0x9f, 0x5d, 0x0c, 0x19, 0x43, 0xd0, 0xfa, 0x25,
+ 0x17, 0xad, 0x2a, 0xbf, 0x89, 0x63, 0x06, 0xa8, 0x02, 0x03, 0xe4, 0xfe,
+ 0x19, 0x08, 0x70, 0xa1, 0x74, 0x74, 0xb6, 0xb6, 0x0f, 0x19, 0x4d, 0x54,
+ 0xa5, 0xb2, 0xd7, 0x37, 0x3b, 0x17, 0xc0, 0x5d, 0xc2, 0x8a, 0xf1, 0xcc,
+ 0xed, 0xef, 0x65, 0xc8, 0xca, 0xbe, 0x02, 0xd4, 0x9b, 0x1e, 0xef, 0xc9,
+ 0xe0, 0x91, 0x82, 0xb0, 0xe0, 0x50, 0xc7, 0xa0, 0xcc, 0x01, 0x6d, 0x55,
+ 0xe5, 0x67, 0x99, 0x65, 0x13, 0xe4, 0xd2, 0x90, 0x91, 0xf3, 0x76, 0x0b,
+ 0x6a, 0x2d, 0x19, 0xaf, 0x61, 0xb3, 0x7f, 0x4c, 0x04, 0xfe, 0x68, 0xf6,
+ 0xb3, 0x56, 0xd8, 0xf3, 0x34, 0xd7, 0x04, 0x0a, 0x31, 0xc8, 0x37, 0xdf,
+ 0xac, 0xd8, 0x91, 0x80, 0x8a, 0x30, 0x12, 0x22, 0x80, 0xd7, 0x24, 0xcf,
+ 0x70, 0xaf, 0x56, 0xaf, 0x81, 0xfe, 0x63, 0xf1, 0xea, 0x57, 0x4c, 0xf2,
+ 0xdb, 0x30, 0x50, 0x92, 0xc1, 0xeb, 0x04, 0x9a, 0xdf, 0xf5, 0x74, 0x57,
+ 0x5b, 0x58, 0xc2, 0x4e, 0x6b, 0x11, 0xf3, 0xe1, 0xb3, 0x0f, 0x56, 0x35,
+ 0x04, 0xf8, 0x50, 0x1d, 0x7e, 0xe6, 0x99, 0xa2, 0x48, 0xdb, 0xea, 0x62,
+ 0x4f, 0x98, 0xc2, 0xef, 0xbf, 0x7f, 0x94, 0xc0, 0x36, 0xc0, 0xf3, 0x27,
+ 0xfe, 0xe2, 0x17, 0x1e, 0x91, 0x7d, 0x96, 0xa9, 0x2b, 0x71, 0x51, 0xc3,
+ 0x59, 0x2d, 0x11, 0x50, 0x1e, 0xcb, 0xce, 0xff, 0x04, 0x4d, 0x16, 0xf5,
+ 0xc2, 0xd4, 0x1f, 0xdd, 0x7f, 0x5a, 0xfd, 0x1d, 0xe9, 0x63, 0x52, 0x44,
+ 0x76, 0x5f, 0x91, 0xfd, 0xe8, 0xdf, 0x0a, 0x69, 0x0d, 0xd3, 0x64, 0x91,
+ 0xea, 0xdd, 0x03, 0x4f, 0x42, 0xa5, 0xe9, 0xa1, 0x70, 0x05, 0xf3, 0x22,
+ 0x8e, 0xad, 0x70, 0x1a, 0x3e, 0x94, 0x42, 0x06, 0xe7, 0x47, 0x37, 0x3d,
+ 0xf5, 0xda, 0x3e, 0x2a, 0x3a, 0xc0, 0x23, 0xd9, 0x4a, 0x26, 0x69, 0x13,
+ 0xa6, 0x93, 0x7c, 0xf2, 0xaf, 0x04, 0x5e, 0x9b, 0x88, 0xc7, 0x77, 0xd0,
+ 0x93, 0xab, 0x1b, 0xbd, 0x3d, 0x69, 0x90, 0xab, 0x41, 0xa9, 0xbc, 0x84,
+ 0x18, 0x4d, 0x29, 0x02, 0xc1, 0xf8, 0xff, 0x63, 0x18, 0x24, 0x74, 0x8f,
+ 0x7e, 0x44, 0x33, 0xaf, 0x88, 0x8b, 0x93, 0x5b, 0x9a, 0xae, 0x6b, 0x08,
+ 0xa2, 0x82, 0x5d, 0xf3, 0xbe, 0x61, 0xc3, 0xf0, 0x2d, 0x31, 0x4c, 0xb5,
+ 0xb5, 0x91, 0x0f, 0xfa, 0x81, 0x61, 0xad, 0xfc, 0xba, 0x91, 0xeb, 0x3b,
+ 0x9d, 0x22, 0x41, 0x45, 0x0e, 0x8e, 0x24, 0xc7, 0x1c, 0x81, 0x95, 0xa8,
+ 0x7b, 0x64, 0xed, 0xa5, 0xec, 0x5a, 0x68, 0x3c, 0x85, 0x8d, 0x92, 0xb7,
+ 0x24, 0x0f, 0xed, 0xf5, 0xc6, 0x31, 0x61, 0xdc, 0xef, 0xa7, 0xcb, 0x8f,
+ 0xda, 0x43, 0x05, 0x42, 0xf6, 0x9e, 0xbc, 0x1b, 0x9a, 0xa1, 0xe8, 0x1d,
+ 0x8d, 0x42, 0xdb, 0x80, 0x83, 0x55, 0x52, 0x2b, 0x95, 0x00, 0x05, 0x82,
+ 0x84, 0xc3, 0x54, 0x23, 0x8e, 0x1d, 0x00, 0xa2, 0x16, 0x3e, 0xce, 0x3d,
+ 0xcc, 0x9e, 0xb8, 0x4c, 0x59, 0xb2, 0x12, 0xa2, 0x23, 0xc1, 0x46, 0x50,
+ 0x86, 0xae, 0x75, 0x7e, 0x49, 0x38, 0x77, 0x94, 0xf0, 0x27, 0xd8, 0x17,
+ 0x38, 0x8c, 0xe0, 0x73, 0x00, 0xfb, 0xaf, 0xbf, 0xe8, 0xed, 0x85, 0x58,
+ 0x3e, 0xb4, 0x88, 0x04, 0xc8, 0x22, 0x1b, 0xb4, 0x75, 0xa2, 0xc4, 0xdd,
+ 0x06, 0xd2, 0x83, 0x42, 0x21, 0x57, 0xfc, 0xd8, 0xae, 0x9c, 0x0e, 0xd8,
+ 0x6a, 0x70, 0xd1, 0xeb, 0x44, 0x9c, 0xb7, 0x37, 0x04, 0x05, 0xf5, 0x17,
+ 0xbe, 0xf3, 0x56, 0x1b, 0x06, 0x36, 0x1c, 0x59, 0x7b, 0x65, 0x8d, 0xbb,
+ 0xbe, 0x22, 0x9a, 0x70, 0xa3, 0xe9, 0x60, 0x1a, 0xc9, 0xdd, 0x81, 0x3c,
+ 0x2d, 0x4e, 0xc0, 0x8a, 0xe5, 0x91, 0xa7, 0xc1, 0x80, 0x07, 0x47, 0x7a,
+ 0x74, 0x4f, 0x3e, 0x4a, 0xdc, 0xb2, 0xcc, 0xff, 0x37, 0x66, 0x05, 0xcb,
+ 0xd6, 0xe9, 0x90, 0xf5, 0xef, 0x2b, 0x7e, 0xa7, 0x66, 0x51, 0xcb, 0x48,
+ 0xb3, 0x8a, 0x6f, 0x06, 0xba, 0x8b, 0x3d, 0x35, 0x36, 0xdf, 0x0e, 0x40,
+ 0xe5, 0xa1, 0xe3, 0xdd, 0x89, 0xab, 0x64, 0x9c, 0x01, 0x15, 0x9e, 0x93,
+ 0xea, 0xf9, 0x4f, 0x9e, 0xf5, 0x8b, 0xf2, 0xc2, 0xbb, 0xe5, 0xc3, 0xa3,
+ 0xe3, 0x13, 0x63, 0x4f, 0x7d, 0x20, 0xe4, 0x66, 0x96, 0x84, 0x8d, 0xd4,
+ 0xca, 0x72, 0x52, 0xdc, 0xb8, 0x93, 0xd4, 0xa5, 0x3e, 0x6e, 0x42, 0x56,
+ 0x80, 0x46, 0x77, 0x86, 0x49, 0xfe, 0xf3, 0xb4, 0x5b, 0x37, 0xfc, 0xb8,
+ 0x0c, 0xd7, 0x63, 0xac, 0x3c, 0x6f, 0xf0, 0xbe, 0xbe, 0xb4, 0x13, 0xe7,
+ 0x34, 0xe5, 0x06, 0xbf, 0x17, 0x48, 0x6e, 0xc0, 0x26, 0x94, 0xdd, 0xed,
+ 0xf4, 0xda, 0x97, 0x25, 0xab, 0xd6, 0x9b, 0xc3, 0x8c, 0xeb, 0x17, 0x09,
+ 0xfc, 0x03, 0x5a, 0x2f, 0x19, 0x85, 0x50, 0xc4, 0xe6, 0x35, 0x71, 0x94,
+ 0xad, 0xc5, 0xcf, 0x08, 0xcf, 0x69, 0x3b, 0xc3, 0x31, 0xec, 0xf1, 0xfa,
+ 0x80, 0x66, 0x8f, 0x14, 0xde, 0x56, 0x21, 0x12, 0x9b, 0x0c, 0xdf, 0x92,
+ 0x48, 0x06, 0xce, 0xdb, 0xeb, 0x28, 0x54, 0x27, 0x8b, 0xa9, 0xef, 0x0c,
+ 0xf4, 0xa0, 0xcc, 0x84, 0x59, 0x60, 0xed, 0x18, 0x65, 0xca, 0x67, 0x0c,
+ 0xd1, 0x1f, 0xcf, 0x59, 0x4b, 0xce, 0x07, 0x27, 0x08, 0x6a, 0xea, 0x53,
+ 0xdc, 0x47, 0xb3, 0x4e, 0xe4, 0x0b, 0xff, 0x9a, 0x7d, 0x6b, 0x0d, 0x2f,
+ 0x2d, 0x60, 0xd7, 0x8b, 0x22, 0xf5, 0x30, 0x43, 0x09, 0xe6, 0xdf, 0x01,
+ 0x03, 0x27, 0x2d, 0xb5, 0x74, 0x52, 0x5d, 0x08, 0xc7, 0x5a, 0x44, 0x25,
+ 0x0f, 0x2c, 0x14, 0x8f, 0x48, 0xea, 0x18, 0x99, 0xd1, 0xcc, 0xc5, 0xdc,
+ 0x65, 0xa5, 0x3d, 0x25, 0x94, 0xa9, 0xc7, 0xad, 0x3e, 0xa4, 0xf6, 0xe6,
+ 0xbd, 0xa7, 0x70, 0xd4, 0xdc, 0x9b, 0x26, 0xcb, 0x31, 0x70, 0xaf, 0x3e,
+ 0xa4, 0xb6, 0x8d, 0x21, 0x31, 0x67, 0x35, 0x35, 0x86, 0x67, 0xd1, 0x02,
+ 0x6c, 0x36, 0x76, 0xc9, 0x20, 0xf6, 0x0f, 0x30, 0x41, 0x83, 0x19, 0xf5,
+ 0xe1, 0x33, 0x90, 0xbc, 0x7b, 0x8c, 0x9b, 0x8a, 0x68, 0x30, 0x9e, 0xed,
+ 0xf4, 0x88, 0xc9, 0x04, 0x08, 0x2b, 0xb0, 0x0f, 0xae, 0xc7, 0xe0, 0x6e,
+ 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39, 0x30, 0x21, 0x30,
+ 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14,
+ 0xe0, 0xf7, 0xa1, 0x1b, 0xf6, 0x3f, 0x05, 0xad, 0x55, 0x6a, 0x20, 0x4c,
+ 0x71, 0xca, 0x62, 0x47, 0x13, 0x28, 0xd5, 0x05, 0x04, 0x10, 0x3e, 0x87,
+ 0x2d, 0x96, 0xea, 0x80, 0x4b, 0xab, 0x3a, 0xb9, 0xee, 0x09, 0x65, 0x28,
+ 0xbc, 0x8d, 0x02, 0x02, 0x07, 0xd0, 0x00, 0x00,
+};
+
+/* kWindows is a dummy key and certificate exported from the certificate
+ * manager on Windows 7. */
+static const uint8_t kWindows[] = {
+ 0x30, 0x82, 0x0a, 0x02, 0x02, 0x01, 0x03, 0x30, 0x82, 0x09, 0xbe, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82,
+ 0x09, 0xaf, 0x04, 0x82, 0x09, 0xab, 0x30, 0x82, 0x09, 0xa7, 0x30, 0x82,
+ 0x06, 0x08, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07,
+ 0x01, 0xa0, 0x82, 0x05, 0xf9, 0x04, 0x82, 0x05, 0xf5, 0x30, 0x82, 0x05,
+ 0xf1, 0x30, 0x82, 0x05, 0xed, 0x06, 0x0b, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02, 0xa0, 0x82, 0x04, 0xfe, 0x30, 0x82,
+ 0x04, 0xfa, 0x30, 0x1c, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x0c, 0x01, 0x03, 0x30, 0x0e, 0x04, 0x08, 0xb7, 0x20, 0x55, 0x5a,
+ 0x4d, 0x3f, 0x0e, 0x89, 0x02, 0x02, 0x07, 0xd0, 0x04, 0x82, 0x04, 0xd8,
+ 0x3a, 0xcc, 0xd6, 0xcb, 0x4d, 0x54, 0xc0, 0x04, 0x56, 0x10, 0xcc, 0x49,
+ 0xe4, 0xe0, 0x10, 0x73, 0xfb, 0x1a, 0xdd, 0x1d, 0x4f, 0x6e, 0x55, 0xe3,
+ 0xa4, 0xab, 0xf9, 0x26, 0xaa, 0x42, 0x54, 0xa0, 0xd1, 0xf0, 0x8d, 0xbf,
+ 0x71, 0x7d, 0x18, 0x00, 0x17, 0xb3, 0xb7, 0x63, 0x50, 0x8d, 0x2c, 0xeb,
+ 0x2f, 0xe3, 0xc3, 0xbf, 0x93, 0xc8, 0x46, 0x48, 0x99, 0x47, 0xe2, 0x3b,
+ 0x8d, 0x71, 0x01, 0x5f, 0x59, 0x5b, 0x61, 0x7e, 0x1f, 0x0c, 0x6e, 0x3e,
+ 0xc4, 0x74, 0x99, 0x98, 0x30, 0xff, 0x37, 0x7b, 0x30, 0x19, 0xb5, 0xfc,
+ 0x69, 0x94, 0x5f, 0x79, 0x69, 0x34, 0xda, 0xb5, 0x21, 0xcf, 0xfe, 0x72,
+ 0x87, 0xe8, 0x7d, 0x29, 0x7e, 0x27, 0x25, 0x90, 0x80, 0x98, 0xdd, 0x8d,
+ 0xbf, 0x42, 0xb0, 0x10, 0xd8, 0x7d, 0x6d, 0xfe, 0x6f, 0x0d, 0x61, 0x09,
+ 0xfd, 0xb2, 0x9b, 0xeb, 0xbf, 0x1c, 0xca, 0x33, 0xbc, 0x4e, 0x19, 0x52,
+ 0x55, 0x53, 0xb4, 0xa5, 0x98, 0x6c, 0xa3, 0x3b, 0xf8, 0xa4, 0x8d, 0x79,
+ 0xcf, 0x40, 0xf2, 0x89, 0x09, 0x3c, 0x38, 0xab, 0xae, 0xf4, 0x09, 0x3b,
+ 0xb6, 0xcb, 0xdd, 0xd7, 0xad, 0xe0, 0x5a, 0x71, 0x64, 0xc9, 0x0f, 0x18,
+ 0xac, 0x3c, 0x12, 0xd4, 0x22, 0x54, 0x24, 0x1a, 0xa5, 0x35, 0x78, 0x99,
+ 0x09, 0x4a, 0x18, 0x95, 0x23, 0xb9, 0xf7, 0x89, 0x3f, 0x13, 0x43, 0x1f,
+ 0x8d, 0x76, 0x6b, 0x04, 0xdb, 0x64, 0xf4, 0x8e, 0xf5, 0x50, 0xa0, 0xae,
+ 0x1c, 0x8c, 0xc8, 0xf3, 0xde, 0xf3, 0x11, 0x2d, 0xfe, 0x76, 0xf0, 0xac,
+ 0x46, 0x54, 0x23, 0x03, 0x49, 0xfa, 0x73, 0xcd, 0xe0, 0xa1, 0x6c, 0x66,
+ 0x4d, 0x1b, 0x99, 0x57, 0x3d, 0x61, 0x61, 0xeb, 0x61, 0x40, 0xc7, 0xd6,
+ 0x41, 0xbe, 0x63, 0x21, 0x1e, 0x7e, 0xb5, 0x0e, 0x94, 0x93, 0x37, 0x41,
+ 0xe8, 0x91, 0x06, 0xd7, 0xa3, 0x33, 0x78, 0x17, 0x17, 0x59, 0x78, 0x8f,
+ 0xaf, 0xed, 0xf9, 0x90, 0xfb, 0xb6, 0xc8, 0xa9, 0x0b, 0x10, 0x1a, 0xf1,
+ 0xab, 0x10, 0x11, 0xbc, 0x7f, 0xa5, 0x2d, 0x34, 0x7d, 0x7b, 0xaf, 0xc8,
+ 0xb2, 0x00, 0x6b, 0xd4, 0xbb, 0x25, 0x9b, 0xc7, 0x14, 0x8b, 0x50, 0x0a,
+ 0xd5, 0x2c, 0x1f, 0xa0, 0x5f, 0x07, 0x1d, 0x5e, 0x1a, 0xa4, 0x4b, 0x85,
+ 0xb2, 0xa6, 0xe2, 0xdd, 0xb7, 0xda, 0x11, 0x25, 0x51, 0xbf, 0x72, 0x50,
+ 0x53, 0xa1, 0x3d, 0xfa, 0x1d, 0x34, 0x75, 0xdd, 0x7a, 0xe0, 0x90, 0x56,
+ 0x14, 0xc3, 0xe8, 0x0b, 0xea, 0x32, 0x5f, 0x92, 0xfc, 0x2e, 0x4d, 0x0e,
+ 0xfe, 0xba, 0x1a, 0x00, 0x6d, 0x8f, 0x75, 0xac, 0x49, 0x4c, 0x79, 0x03,
+ 0x2e, 0xf2, 0xcc, 0x8e, 0x96, 0x27, 0x3c, 0x59, 0x28, 0x7f, 0x52, 0x8d,
+ 0xc3, 0x3b, 0x24, 0x68, 0xff, 0xbb, 0xd0, 0x4e, 0xdf, 0xc4, 0x91, 0x32,
+ 0x14, 0x5e, 0x43, 0x73, 0xd8, 0x56, 0x65, 0xe1, 0x48, 0x89, 0xe4, 0x33,
+ 0xef, 0x4b, 0x51, 0x50, 0xf2, 0x53, 0xe7, 0xae, 0x7d, 0xb6, 0x8c, 0x80,
+ 0xee, 0x8d, 0x9e, 0x24, 0x1a, 0xdd, 0x95, 0x7d, 0x22, 0x58, 0x76, 0xf8,
+ 0xbb, 0x63, 0x36, 0x17, 0xdc, 0xc6, 0x3e, 0xb8, 0xe9, 0x1f, 0xd8, 0xe0,
+ 0x06, 0x18, 0x1b, 0x3c, 0x45, 0xcb, 0xe1, 0x5a, 0x41, 0xe5, 0x32, 0xa3,
+ 0x85, 0x1b, 0xff, 0xe0, 0x5e, 0x28, 0xee, 0xe9, 0x05, 0xc7, 0xc8, 0x47,
+ 0x85, 0xe8, 0x13, 0x7f, 0x1b, 0xda, 0xd7, 0x3e, 0x8e, 0xb8, 0xa3, 0x96,
+ 0x34, 0x19, 0x3b, 0x0c, 0x88, 0x26, 0x38, 0xe7, 0x65, 0xf6, 0x03, 0x4f,
+ 0xc8, 0x37, 0x6e, 0x2f, 0x5e, 0x5d, 0xcd, 0xa3, 0x29, 0x37, 0xe8, 0x86,
+ 0x84, 0x66, 0x37, 0x84, 0xa0, 0x49, 0x4e, 0x8f, 0x3b, 0x1a, 0x42, 0x9f,
+ 0x62, 0x1f, 0x2b, 0x97, 0xc9, 0x18, 0x21, 0xd2, 0xa5, 0xcd, 0x8f, 0xa4,
+ 0x03, 0xf8, 0x82, 0x1e, 0xb8, 0x3e, 0x6b, 0x54, 0x29, 0x75, 0x5f, 0x80,
+ 0xe6, 0x8f, 0x2f, 0x65, 0xb0, 0x6b, 0xbb, 0x18, 0x6e, 0x0d, 0x32, 0x62,
+ 0x8c, 0x97, 0x48, 0xd3, 0xaa, 0xf2, 0x5e, 0xb8, 0x25, 0xbc, 0xb5, 0x22,
+ 0x4a, 0xac, 0xcf, 0xdc, 0x8b, 0x48, 0xfc, 0x95, 0xf2, 0x17, 0x21, 0x1e,
+ 0xda, 0x13, 0xd3, 0x1b, 0xe2, 0x37, 0xd5, 0xbf, 0x92, 0xe4, 0x81, 0xf5,
+ 0x98, 0x57, 0x51, 0x14, 0xda, 0x80, 0x7d, 0x4a, 0x6a, 0xce, 0x17, 0xaf,
+ 0xdb, 0xc3, 0x2e, 0x84, 0x3b, 0x1e, 0x02, 0x51, 0x4a, 0xc1, 0x25, 0x8c,
+ 0x5a, 0x20, 0x56, 0xee, 0xec, 0x59, 0xcf, 0xd7, 0x3e, 0x5f, 0x39, 0x9f,
+ 0xbf, 0x4d, 0x4e, 0x94, 0xb1, 0x1d, 0x83, 0x70, 0xc0, 0xab, 0xff, 0xfa,
+ 0x7c, 0x2e, 0x5b, 0xfb, 0x57, 0x3f, 0x60, 0xb8, 0xf3, 0x36, 0x5f, 0xbf,
+ 0x6a, 0x8c, 0x6f, 0xe0, 0x34, 0xe8, 0x75, 0x26, 0xc2, 0x1e, 0x22, 0x64,
+ 0x0e, 0x43, 0xc1, 0x93, 0xe6, 0x8a, 0x2e, 0xe9, 0xd9, 0xe0, 0x9f, 0x56,
+ 0x50, 0x8a, 0xbd, 0x68, 0xf6, 0x57, 0x63, 0x55, 0xbb, 0xe7, 0xfe, 0x22,
+ 0xca, 0xdc, 0x85, 0x38, 0x39, 0xc8, 0x66, 0x02, 0x28, 0x0f, 0xe0, 0x1c,
+ 0xd6, 0x0f, 0x5d, 0x6a, 0x0b, 0xd8, 0xe5, 0x6a, 0xeb, 0x54, 0xb2, 0xe0,
+ 0x02, 0x6f, 0xe2, 0x42, 0x89, 0x66, 0xc2, 0xd5, 0xc6, 0xe2, 0xb2, 0x04,
+ 0x6d, 0x8a, 0x2b, 0x48, 0xc2, 0x51, 0x07, 0x8e, 0xf3, 0x91, 0x0b, 0xb7,
+ 0x55, 0x6e, 0xbb, 0xbf, 0x11, 0x5a, 0xcb, 0x2c, 0xb3, 0x1e, 0x61, 0xd3,
+ 0xdb, 0x90, 0xad, 0xba, 0x10, 0x96, 0xe2, 0x16, 0xf4, 0x0c, 0x47, 0xbd,
+ 0x64, 0x66, 0x7a, 0x17, 0x63, 0xb9, 0x02, 0xcb, 0x53, 0x7a, 0x35, 0x92,
+ 0x74, 0xc3, 0x2a, 0x7d, 0xc5, 0x11, 0x18, 0x2f, 0xa3, 0x62, 0x2c, 0xc0,
+ 0x87, 0xd3, 0xd3, 0xba, 0xcb, 0xe0, 0x86, 0x9b, 0x4b, 0xc5, 0x59, 0x98,
+ 0x7e, 0x32, 0x96, 0x55, 0xc1, 0x3d, 0x5a, 0xcd, 0x90, 0x2d, 0xf8, 0xb7,
+ 0xa8, 0xba, 0xce, 0x89, 0x64, 0xa6, 0xf3, 0x1b, 0x11, 0x2e, 0x12, 0x99,
+ 0x4d, 0x34, 0x45, 0x13, 0x66, 0xb7, 0x69, 0x7b, 0xc5, 0x79, 0xf5, 0x6b,
+ 0xc2, 0x1d, 0xc8, 0x3f, 0x09, 0x18, 0x0a, 0xfc, 0xf7, 0xaf, 0x98, 0xc2,
+ 0xc7, 0xcc, 0x85, 0x29, 0xc6, 0x22, 0x7a, 0x77, 0xab, 0xb5, 0xac, 0xf7,
+ 0x9e, 0x70, 0x8e, 0x7f, 0x3c, 0xf1, 0xbd, 0xd9, 0x7a, 0x92, 0x84, 0xc5,
+ 0xb8, 0x56, 0xc3, 0xcb, 0xf7, 0x25, 0xad, 0xda, 0x0e, 0x1c, 0xe4, 0x68,
+ 0x66, 0x83, 0x91, 0x78, 0xf1, 0xe7, 0x8c, 0xaa, 0x45, 0xb6, 0x85, 0x74,
+ 0x9b, 0x08, 0xff, 0xac, 0x38, 0x55, 0xa5, 0x6a, 0xea, 0x2e, 0x75, 0x71,
+ 0xd3, 0xa2, 0xdc, 0x1c, 0xc0, 0xc7, 0x0b, 0xa9, 0xd5, 0x7e, 0xf9, 0x63,
+ 0x82, 0x87, 0xb7, 0x81, 0x01, 0xb9, 0x31, 0xdf, 0x41, 0x35, 0x0e, 0xe2,
+ 0x1f, 0x48, 0xbf, 0x60, 0xce, 0xb0, 0xb4, 0x38, 0xa5, 0xb4, 0x76, 0xa3,
+ 0x80, 0x1f, 0x93, 0x57, 0xf2, 0x05, 0x81, 0x42, 0xd1, 0xae, 0x56, 0x6d,
+ 0xc5, 0x4c, 0xab, 0xa6, 0x24, 0x2a, 0x02, 0x3b, 0xb1, 0xc4, 0x75, 0xcf,
+ 0x15, 0x90, 0xb5, 0xf2, 0xe7, 0x10, 0x69, 0xa0, 0xe3, 0xc4, 0xe6, 0x52,
+ 0x63, 0x14, 0xb4, 0x15, 0x91, 0x8e, 0xba, 0x7a, 0xad, 0x2d, 0x9b, 0x24,
+ 0x74, 0x36, 0x31, 0xca, 0xcb, 0x4b, 0x5a, 0xbf, 0xd3, 0x4e, 0xb4, 0xc1,
+ 0x48, 0x44, 0x74, 0x2f, 0x83, 0xe4, 0x39, 0x3d, 0x90, 0x2d, 0x32, 0x12,
+ 0xf7, 0xfa, 0xd3, 0xe3, 0xdb, 0x4f, 0xe6, 0xe7, 0x20, 0x2c, 0x57, 0xc0,
+ 0xf9, 0x80, 0xe1, 0xdc, 0x1c, 0xf2, 0x05, 0x54, 0x35, 0xf6, 0xbd, 0xfb,
+ 0xbd, 0xc5, 0xb2, 0x82, 0x32, 0x63, 0x32, 0xca, 0xf4, 0xf7, 0x14, 0x92,
+ 0x87, 0x8a, 0x45, 0x37, 0x56, 0x93, 0xda, 0x4f, 0x04, 0x59, 0x03, 0x24,
+ 0x93, 0x1a, 0x0b, 0x4e, 0xdb, 0x58, 0xbf, 0xda, 0x2a, 0x0e, 0x7e, 0x98,
+ 0x6c, 0x0c, 0xeb, 0x21, 0xf9, 0xbf, 0x9b, 0x1f, 0xc0, 0xef, 0xd3, 0xea,
+ 0xcb, 0x99, 0x5e, 0x14, 0x3e, 0x10, 0xfa, 0xad, 0x38, 0xf7, 0x68, 0x9f,
+ 0xa3, 0xcc, 0xdf, 0xe5, 0x31, 0x91, 0x98, 0xde, 0x74, 0x5f, 0x7b, 0xce,
+ 0xe4, 0x54, 0xd9, 0x51, 0xec, 0xf5, 0x4b, 0x17, 0x5f, 0x99, 0x4c, 0xf8,
+ 0x00, 0xe0, 0x10, 0x09, 0x07, 0x64, 0xae, 0x61, 0x3b, 0x60, 0xa3, 0x89,
+ 0x38, 0xc4, 0x80, 0xf2, 0x1e, 0x11, 0x26, 0x78, 0x72, 0x05, 0x97, 0x27,
+ 0xba, 0x83, 0x33, 0x1b, 0x14, 0x4b, 0xc0, 0xc8, 0xb0, 0xcc, 0x0a, 0x9b,
+ 0x3e, 0x4c, 0xde, 0x12, 0x07, 0x11, 0xd5, 0xf0, 0xc0, 0xdd, 0x70, 0x3d,
+ 0xd8, 0x7a, 0xf7, 0xa2, 0xf2, 0x70, 0xad, 0x54, 0xce, 0x67, 0x41, 0x12,
+ 0x29, 0x1f, 0xe1, 0x49, 0x5f, 0x4c, 0x77, 0x41, 0x7c, 0x74, 0x25, 0x9c,
+ 0x91, 0xd1, 0x0d, 0xa5, 0x9a, 0xb8, 0x56, 0x4c, 0x01, 0xc0, 0x77, 0x51,
+ 0x14, 0xc8, 0x92, 0x40, 0x9a, 0xbd, 0x7f, 0x3b, 0x9b, 0x17, 0xbb, 0x80,
+ 0x6e, 0x50, 0x64, 0x31, 0xed, 0xe2, 0x22, 0x9f, 0x96, 0x8e, 0xe2, 0x4e,
+ 0x54, 0x6e, 0x36, 0x35, 0xfc, 0xf2, 0xed, 0xfc, 0x56, 0x63, 0xdb, 0x89,
+ 0x19, 0x99, 0xf8, 0x47, 0xff, 0xce, 0x35, 0xd2, 0x86, 0x63, 0xbc, 0xe4,
+ 0x8c, 0x5d, 0x12, 0x94, 0x31, 0x81, 0xdb, 0x30, 0x13, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x15, 0x31, 0x06, 0x04, 0x04,
+ 0x01, 0x00, 0x00, 0x00, 0x30, 0x57, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x09, 0x14, 0x31, 0x4a, 0x1e, 0x48, 0x00, 0x65, 0x00,
+ 0x65, 0x00, 0x36, 0x00, 0x64, 0x00, 0x38, 0x00, 0x38, 0x00, 0x30, 0x00,
+ 0x35, 0x00, 0x2d, 0x00, 0x30, 0x00, 0x36, 0x00, 0x64, 0x00, 0x39, 0x00,
+ 0x2d, 0x00, 0x34, 0x00, 0x32, 0x00, 0x65, 0x00, 0x32, 0x00, 0x2d, 0x00,
+ 0x38, 0x00, 0x62, 0x00, 0x36, 0x00, 0x38, 0x00, 0x2d, 0x00, 0x66, 0x00,
+ 0x65, 0x00, 0x61, 0x00, 0x62, 0x00, 0x35, 0x00, 0x65, 0x00, 0x66, 0x00,
+ 0x32, 0x00, 0x38, 0x00, 0x32, 0x00, 0x37, 0x00, 0x30, 0x30, 0x6b, 0x06,
+ 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x11, 0x01, 0x31, 0x5e,
+ 0x1e, 0x5c, 0x00, 0x4d, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6f,
+ 0x00, 0x73, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x20, 0x00, 0x45,
+ 0x00, 0x6e, 0x00, 0x68, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x65,
+ 0x00, 0x64, 0x00, 0x20, 0x00, 0x43, 0x00, 0x72, 0x00, 0x79, 0x00, 0x70,
+ 0x00, 0x74, 0x00, 0x6f, 0x00, 0x67, 0x00, 0x72, 0x00, 0x61, 0x00, 0x70,
+ 0x00, 0x68, 0x00, 0x69, 0x00, 0x63, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72,
+ 0x00, 0x6f, 0x00, 0x76, 0x00, 0x69, 0x00, 0x64, 0x00, 0x65, 0x00, 0x72,
+ 0x00, 0x20, 0x00, 0x76, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x30, 0x30, 0x82,
+ 0x03, 0x97, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07,
+ 0x06, 0xa0, 0x82, 0x03, 0x88, 0x30, 0x82, 0x03, 0x84, 0x02, 0x01, 0x00,
+ 0x30, 0x82, 0x03, 0x7d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x07, 0x01, 0x30, 0x1c, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x0c, 0x01, 0x06, 0x30, 0x0e, 0x04, 0x08, 0x92, 0x16, 0x6d,
+ 0x6d, 0x68, 0xd3, 0xb0, 0xc1, 0x02, 0x02, 0x07, 0xd0, 0x80, 0x82, 0x03,
+ 0x50, 0xee, 0x76, 0xe8, 0x60, 0xbf, 0xca, 0x3c, 0x2d, 0xe5, 0x29, 0x22,
+ 0xf6, 0x33, 0xc3, 0x50, 0x6a, 0xdb, 0xf3, 0x58, 0x3c, 0xd9, 0x7c, 0xd8,
+ 0xf9, 0x83, 0x89, 0x17, 0xa8, 0x1b, 0x6b, 0x09, 0xc1, 0x99, 0x49, 0xb0,
+ 0x43, 0x06, 0xc6, 0x42, 0x4b, 0x7c, 0x85, 0x4b, 0xe6, 0x69, 0x38, 0x91,
+ 0xce, 0x3d, 0x3c, 0x97, 0xd5, 0x14, 0x4f, 0x15, 0x5a, 0x81, 0x4d, 0x77,
+ 0x40, 0xe0, 0xe1, 0x1c, 0x69, 0x3f, 0x1d, 0x65, 0x68, 0xb3, 0x98, 0x95,
+ 0x30, 0x6c, 0xb0, 0x70, 0x93, 0x0c, 0xce, 0xec, 0xaf, 0x57, 0xc6, 0x9c,
+ 0x34, 0xb4, 0x2b, 0xaf, 0xc3, 0x5e, 0x70, 0x87, 0x17, 0xe8, 0xc9, 0x54,
+ 0x06, 0xb5, 0xb7, 0x83, 0xff, 0x46, 0x2b, 0xb6, 0x6a, 0x66, 0x2f, 0x6d,
+ 0x0f, 0x96, 0x53, 0x66, 0x65, 0xb8, 0x7b, 0x48, 0x55, 0x83, 0xd3, 0xc4,
+ 0x16, 0x93, 0xde, 0x72, 0x59, 0xf1, 0x9a, 0xab, 0xd5, 0xd5, 0xcb, 0x24,
+ 0xa6, 0x4a, 0x4e, 0x57, 0xf3, 0x6e, 0xca, 0xb1, 0xeb, 0x7d, 0xdb, 0x02,
+ 0xd2, 0x79, 0x89, 0xef, 0xa2, 0x8b, 0xee, 0x6f, 0xdc, 0x5e, 0x65, 0xa5,
+ 0x09, 0x33, 0x51, 0xb5, 0x21, 0xc8, 0xc6, 0xab, 0xed, 0xd5, 0x50, 0x93,
+ 0x39, 0x71, 0x97, 0xd3, 0x2c, 0xdd, 0xaf, 0xb1, 0xc6, 0x9b, 0x4b, 0x69,
+ 0x98, 0xae, 0xaf, 0x21, 0xa0, 0x8a, 0x90, 0x25, 0xe0, 0xf4, 0x8c, 0xf2,
+ 0xc3, 0x4f, 0x64, 0xb6, 0xc6, 0x64, 0x90, 0xff, 0x95, 0x0a, 0xcc, 0x8c,
+ 0xf4, 0x86, 0x80, 0x53, 0x8d, 0x51, 0x0b, 0xcd, 0x45, 0x4f, 0xcf, 0x7c,
+ 0xc6, 0xdf, 0x08, 0x5e, 0xa7, 0xdf, 0x4f, 0xcf, 0x84, 0xde, 0xb8, 0x4d,
+ 0x73, 0x40, 0x06, 0xbe, 0x33, 0x82, 0xe8, 0x41, 0x1b, 0x9a, 0xc3, 0x5b,
+ 0xb6, 0xf3, 0xfc, 0x32, 0x98, 0xcc, 0xcc, 0x5e, 0xd5, 0xb7, 0x86, 0x0f,
+ 0xc8, 0x59, 0x72, 0xcb, 0x9a, 0xc5, 0x3c, 0x50, 0xb8, 0x25, 0xb8, 0x87,
+ 0x3e, 0x49, 0xd4, 0x2d, 0x2f, 0x50, 0x35, 0xeb, 0xb8, 0x10, 0xa7, 0xea,
+ 0xb1, 0xe2, 0x0c, 0x6a, 0x84, 0x2c, 0xe2, 0x7a, 0x26, 0xef, 0x7e, 0x6b,
+ 0x1e, 0x47, 0x6e, 0x98, 0xc0, 0x3f, 0x92, 0x24, 0xe7, 0x88, 0xf9, 0x18,
+ 0x78, 0x37, 0x8a, 0x54, 0xa6, 0x2b, 0x5b, 0xf0, 0xc7, 0xe2, 0x98, 0xa4,
+ 0xa6, 0x2e, 0xc3, 0x6a, 0x75, 0x66, 0x51, 0xe8, 0x0d, 0x90, 0xfd, 0xa7,
+ 0xec, 0x22, 0xb3, 0x7d, 0x9d, 0x0c, 0xfe, 0x72, 0x7f, 0x98, 0xf6, 0x86,
+ 0x30, 0xd3, 0x7c, 0xee, 0xa5, 0xc5, 0x20, 0x89, 0x79, 0x04, 0x8e, 0xa8,
+ 0xb6, 0x94, 0x70, 0x4e, 0x75, 0xe5, 0xa0, 0xae, 0x8c, 0x7f, 0x72, 0x4c,
+ 0xd5, 0x9f, 0xd2, 0x56, 0x0d, 0xb2, 0x28, 0x45, 0x99, 0xf8, 0x40, 0xd4,
+ 0x3f, 0x42, 0x4a, 0x0c, 0x92, 0x23, 0xe1, 0x17, 0xaf, 0x68, 0xa6, 0x0f,
+ 0x1d, 0x32, 0x0d, 0xf8, 0x08, 0x8e, 0xdc, 0x79, 0x68, 0xf0, 0xfe, 0x0b,
+ 0xda, 0x94, 0x2d, 0xa6, 0xa7, 0x76, 0x7e, 0xd6, 0xca, 0xec, 0x7c, 0x37,
+ 0x52, 0x4f, 0x77, 0xcf, 0xa3, 0xcf, 0x8a, 0xfe, 0x89, 0xd9, 0x3e, 0xbc,
+ 0xb5, 0x06, 0xa0, 0x21, 0x91, 0x89, 0x77, 0x84, 0x85, 0x43, 0x2a, 0x65,
+ 0xec, 0x75, 0x4d, 0x0d, 0x1c, 0x79, 0x0f, 0x61, 0xca, 0x3e, 0x62, 0xbb,
+ 0x41, 0xf9, 0x4c, 0x5c, 0x3b, 0xde, 0x33, 0x8e, 0xdf, 0x51, 0x72, 0x93,
+ 0xca, 0xa6, 0xc7, 0x16, 0xe5, 0xb3, 0x22, 0xb6, 0x2e, 0xbf, 0xae, 0x1d,
+ 0x91, 0x1d, 0x49, 0x96, 0xa3, 0x25, 0xd4, 0xce, 0x6f, 0xf0, 0xfb, 0xb7,
+ 0xf5, 0x4a, 0x24, 0x03, 0x54, 0x4b, 0x7f, 0x0b, 0xb4, 0x31, 0xb4, 0x33,
+ 0xb7, 0x40, 0xf0, 0xd5, 0x4c, 0xee, 0xe3, 0x4b, 0x12, 0x8c, 0xc9, 0xa7,
+ 0x06, 0xb1, 0x02, 0x5a, 0x14, 0x6f, 0xe2, 0x3b, 0x68, 0x9b, 0x3d, 0xfc,
+ 0x83, 0x4a, 0xcc, 0xb5, 0x77, 0xe7, 0xf0, 0x1b, 0x52, 0xce, 0x60, 0x89,
+ 0xe2, 0x45, 0x76, 0xaa, 0x76, 0x70, 0xc2, 0xfd, 0x21, 0x8f, 0x1d, 0x67,
+ 0x1a, 0x4c, 0xe8, 0x81, 0x2b, 0x2e, 0xa9, 0x56, 0x0a, 0x27, 0x0f, 0x81,
+ 0xba, 0x5c, 0x4f, 0xfa, 0x6e, 0x7e, 0x33, 0x7d, 0x78, 0xed, 0xd2, 0xe3,
+ 0x24, 0xae, 0x24, 0xb2, 0x1b, 0x62, 0x71, 0x0e, 0x73, 0xfe, 0x8a, 0x3b,
+ 0x98, 0x0d, 0x82, 0x8e, 0x8d, 0x0f, 0xb3, 0xe2, 0x65, 0x87, 0xeb, 0x36,
+ 0x91, 0x4d, 0x8a, 0xfb, 0x22, 0x7a, 0x23, 0x2c, 0xe1, 0xb6, 0x94, 0xb6,
+ 0x90, 0x94, 0xcc, 0x0c, 0x7d, 0x02, 0x36, 0x56, 0xda, 0x45, 0x20, 0x90,
+ 0x48, 0xdb, 0xa4, 0xf5, 0x27, 0xac, 0x22, 0x49, 0x25, 0xaa, 0xd8, 0xa7,
+ 0x79, 0x38, 0x80, 0xc0, 0x95, 0xc7, 0xd1, 0x5c, 0x17, 0x7c, 0xa7, 0xec,
+ 0xd2, 0x63, 0xc6, 0xc6, 0x55, 0xfe, 0x78, 0x99, 0x06, 0x2c, 0x6e, 0x4f,
+ 0xfe, 0xd1, 0x5b, 0x8c, 0x2f, 0xa1, 0x42, 0x03, 0x26, 0x5a, 0x5e, 0xda,
+ 0xef, 0x43, 0xd2, 0x0e, 0xf9, 0x5f, 0xdb, 0x1d, 0x9c, 0xd1, 0xcb, 0x65,
+ 0x84, 0x26, 0xed, 0x91, 0x8f, 0x16, 0xb4, 0x1c, 0xc0, 0xb3, 0x8d, 0x79,
+ 0xae, 0x9b, 0xcb, 0x36, 0x6d, 0xcd, 0x67, 0x1f, 0x87, 0x11, 0x2a, 0x7c,
+ 0xb1, 0x8c, 0xfb, 0x06, 0xab, 0xd2, 0xd6, 0x2a, 0xe3, 0x45, 0x6c, 0xa5,
+ 0xc0, 0x19, 0x6b, 0xfc, 0xc3, 0xb7, 0x54, 0x35, 0xda, 0xdf, 0x12, 0x97,
+ 0x5c, 0xac, 0x59, 0xb4, 0x42, 0x25, 0xef, 0x04, 0xf7, 0x4c, 0xdb, 0x74,
+ 0xb9, 0x68, 0x8f, 0xee, 0x37, 0x0a, 0xc6, 0x21, 0x86, 0x0f, 0x6f, 0x8e,
+ 0xab, 0xd5, 0x7b, 0x38, 0x5e, 0x5f, 0x7d, 0xb9, 0x5a, 0xcb, 0xce, 0xa0,
+ 0x56, 0x37, 0x13, 0x71, 0x4b, 0xba, 0x43, 0x7c, 0xc0, 0xb7, 0x7f, 0x32,
+ 0xd7, 0x46, 0x27, 0x58, 0xfc, 0xdb, 0xb5, 0x64, 0x20, 0x3b, 0x20, 0x85,
+ 0x79, 0xa8, 0x9a, 0x22, 0xaf, 0x29, 0x86, 0xc5, 0x9d, 0x23, 0x96, 0x52,
+ 0xca, 0xc7, 0x9d, 0x92, 0x26, 0xe5, 0x3a, 0x60, 0xd6, 0xad, 0x8d, 0x5a,
+ 0xd9, 0x29, 0xbe, 0xd5, 0x5c, 0x3a, 0x77, 0xda, 0x34, 0xe2, 0x76, 0xcb,
+ 0x98, 0xa4, 0xf3, 0x33, 0xf1, 0x68, 0x20, 0x83, 0x95, 0x0b, 0x8d, 0x93,
+ 0x59, 0x02, 0x0c, 0x8f, 0xe4, 0xc4, 0xb0, 0xe7, 0x61, 0x0d, 0xf9, 0x80,
+ 0x20, 0x58, 0x40, 0xea, 0xb7, 0x0b, 0x1b, 0xad, 0xe3, 0x30, 0x3b, 0x30,
+ 0x1f, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x04, 0x14,
+ 0x2d, 0x77, 0x79, 0x79, 0x90, 0x41, 0x75, 0xf4, 0x4a, 0x7f, 0xf7, 0x15,
+ 0x94, 0x28, 0x62, 0xf7, 0x69, 0xd4, 0x44, 0x27, 0x04, 0x14, 0x2b, 0x2f,
+ 0xd9, 0x24, 0xc3, 0x8a, 0x34, 0xbb, 0x52, 0x52, 0x7b, 0xf6, 0x0e, 0x7b,
+ 0xfe, 0x3a, 0x66, 0x47, 0x40, 0x49, 0x02, 0x02, 0x07, 0xd0,
+};
+
+static int test(const char *name, const uint8_t *der, size_t der_len) {
+ CBS pkcs12;
+ EVP_PKEY *key;
+ STACK_OF(X509) *certs;
+
+ certs = sk_X509_new_null();
+
+ CBS_init(&pkcs12, der, der_len);
+ if (!PKCS12_get_key_and_certs(&key, certs, &pkcs12, "foo")) {
+ fprintf(stderr, "PKCS12 failed on %s data.\n", name);
+ BIO_print_errors_fp(stderr);
+ return 0;
+ }
+
+ if (sk_X509_num(certs) != 1 || key == NULL) {
+ fprintf(stderr, "Bad result from %s data.\n", name);
+ return 0;
+ }
+
+ sk_X509_pop_free(certs, X509_free);
+ EVP_PKEY_free(key);
+
+ return 1;
+}
+
+static int test_compat(const uint8_t *der, size_t der_len) {
+ PKCS12 *p12;
+ X509 *cert = NULL;
+ STACK_OF(X509) *ca_certs = NULL;
+ EVP_PKEY *key;
+ BIO *bio;
+
+ bio = BIO_new_mem_buf((void*) der, der_len);
+
+ p12 = d2i_PKCS12_bio(bio, NULL);
+ if (p12 == NULL) {
+ fprintf(stderr, "PKCS12_parse failed.\n");
+ BIO_print_errors_fp(stderr);
+ return 0;
+ }
+ BIO_free(bio);
+
+ if (!PKCS12_parse(p12, "foo", &key, &cert, &ca_certs)) {
+ fprintf(stderr, "PKCS12_parse failed.\n");
+ BIO_print_errors_fp(stderr);
+ return 0;
+ }
+
+ if (key == NULL || cert == NULL) {
+ fprintf(stderr, "Bad result from PKCS12_parse.\n");
+ return 0;
+ }
+
+ EVP_PKEY_free(key);
+ X509_free(cert);
+
+ if (sk_X509_num(ca_certs) != 0) {
+ fprintf(stderr, "Bad result from PKCS12_parse.\n");
+ return 0;
+ }
+ sk_X509_free(ca_certs);
+
+ PKCS12_free(p12);
+
+ return 1;
+}
+
+int main(int argc, char **argv) {
+ CRYPTO_library_init();
+ ERR_load_crypto_strings();
+
+ if (!test("OpenSSL", kOpenSSL, sizeof(kOpenSSL)) ||
+ !test("NSS", kNSS, sizeof(kNSS)) ||
+ !test("Windows", kWindows, sizeof(kWindows)) ||
+ !test_compat(kWindows, sizeof(kWindows))) {
+ return 1;
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/crypto/pkcs8/pkcs8.c b/crypto/pkcs8/pkcs8.c
index b39f10b..58e400d 100644
--- a/crypto/pkcs8/pkcs8.c
+++ b/crypto/pkcs8/pkcs8.c
@@ -55,19 +55,26 @@
#include <openssl/pkcs8.h>
+#include <assert.h>
+#include <limits.h>
+
#include <openssl/asn1.h>
#include <openssl/bn.h>
+#include <openssl/buf.h>
#include <openssl/cipher.h>
#include <openssl/digest.h>
#include <openssl/err.h>
+#include <openssl/hmac.h>
#include <openssl/mem.h>
#include <openssl/x509.h>
+#include "../bytestring/internal.h"
#include "../evp/internal.h"
#define PKCS12_KEY_ID 1
#define PKCS12_IV_ID 2
+#define PKCS12_MAC_ID 3
static int ascii_to_ucs2(const char *ascii, size_t ascii_len,
uint8_t **out, size_t *out_len) {
@@ -96,7 +103,7 @@ static int ascii_to_ucs2(const char *ascii, size_t ascii_len,
}
static int pkcs12_key_gen_raw(const uint8_t *pass_raw, size_t pass_raw_len,
- uint8_t *salt, size_t salt_len,
+ const uint8_t *salt, size_t salt_len,
int id, int iterations,
size_t out_len, uint8_t *out,
const EVP_MD *md_type) {
@@ -256,17 +263,20 @@ typedef int (*keygen_func)(EVP_CIPHER_CTX *ctx, const uint8_t *pass_raw,
struct pbe_suite {
int pbe_nid;
- int cipher_nid;
- int md_nid;
+ const EVP_CIPHER* (*cipher_func)();
+ const EVP_MD* (*md_func)();
keygen_func keygen;
};
static const struct pbe_suite kBuiltinPBE[] = {
{
- NID_pbe_WithSHA1And128BitRC4, NID_rc4, NID_sha1, pkcs12_pbe_keyivgen,
+ NID_pbe_WithSHA1And40BitRC2_CBC, EVP_rc2_40_cbc, EVP_sha1, pkcs12_pbe_keyivgen,
+ },
+ {
+ NID_pbe_WithSHA1And128BitRC4, EVP_rc4, EVP_sha1, pkcs12_pbe_keyivgen,
},
{
- NID_pbe_WithSHA1And3_Key_TripleDES_CBC, NID_des_ede3_cbc, NID_sha1,
+ NID_pbe_WithSHA1And3_Key_TripleDES_CBC, EVP_des_ede3_cbc, EVP_sha1,
pkcs12_pbe_keyivgen,
},
};
@@ -283,8 +293,8 @@ static int pbe_cipher_init(ASN1_OBJECT *pbe_obj,
const int pbe_nid = OBJ_obj2nid(pbe_obj);
for (i = 0; i < sizeof(kBuiltinPBE) / sizeof(struct pbe_suite); i++) {
- suite = &kBuiltinPBE[i];
- if (suite->pbe_nid == pbe_nid) {
+ if (kBuiltinPBE[i].pbe_nid == pbe_nid) {
+ suite = &kBuiltinPBE[i];
break;
}
}
@@ -301,20 +311,20 @@ static int pbe_cipher_init(ASN1_OBJECT *pbe_obj,
return 0;
}
- if (suite->cipher_nid == -1) {
+ if (suite->cipher_func == NULL) {
cipher = NULL;
} else {
- cipher = EVP_get_cipherbynid(suite->cipher_nid);
+ cipher = suite->cipher_func();
if (!cipher) {
OPENSSL_PUT_ERROR(PKCS8, pbe_cipher_init, PKCS8_R_UNKNOWN_CIPHER);
return 0;
}
}
- if (suite->md_nid == -1) {
+ if (suite->md_func == NULL) {
md = NULL;
} else {
- md = EVP_get_digestbynid(suite->md_nid);
+ md = suite->md_func();
if (!md) {
OPENSSL_PUT_ERROR(PKCS8, pbe_cipher_init, PKCS8_R_UNKNOWN_DIGEST);
return 0;
@@ -332,7 +342,8 @@ static int pbe_cipher_init(ASN1_OBJECT *pbe_obj,
static int pbe_crypt(const X509_ALGOR *algor,
const uint8_t *pass_raw, size_t pass_raw_len,
- uint8_t *in, size_t in_len, uint8_t **out, size_t *out_len,
+ const uint8_t *in, size_t in_len,
+ uint8_t **out, size_t *out_len,
int is_encrypt) {
uint8_t *buf;
int n, ret = 0;
@@ -601,3 +612,543 @@ error:
PKCS8_PRIV_KEY_INFO_free(p8);
return NULL;
}
+
+struct pkcs12_context {
+ EVP_PKEY **out_key;
+ STACK_OF(X509) *out_certs;
+ uint8_t *password;
+ size_t password_len;
+};
+
+static int PKCS12_handle_content_info(CBS *content_info, unsigned depth,
+ struct pkcs12_context *ctx);
+
+/* PKCS12_handle_content_infos parses a series of PKCS#7 ContentInfos in a
+ * SEQUENCE. */
+static int PKCS12_handle_content_infos(CBS *content_infos,
+ unsigned depth,
+ struct pkcs12_context *ctx) {
+ uint8_t *der_bytes = NULL;
+ size_t der_len;
+ CBS in;
+ int ret = 0;
+
+ /* Generally we only expect depths 0 (the top level, with a
+ * pkcs7-encryptedData and a pkcs7-data) and depth 1 (the various PKCS#12
+ * bags). */
+ if (depth > 3) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_infos,
+ PKCS8_R_PKCS12_TOO_DEEPLY_NESTED);
+ return 0;
+ }
+
+ /* Although a BER->DER conversion is done at the beginning of |PKCS12_parse|,
+ * the ASN.1 data gets wrapped in OCTETSTRINGs and/or encrypted and the
+ * conversion cannot see through those wrappings. So each time we step
+ * through one we need to convert to DER again. */
+ if (!CBS_asn1_ber_to_der(content_infos, &der_bytes, &der_len)) {
+ return 0;
+ }
+
+ if (der_bytes != NULL) {
+ CBS_init(&in, der_bytes, der_len);
+ } else {
+ CBS_init(&in, CBS_data(content_infos), CBS_len(content_infos));
+ }
+
+ if (!CBS_get_asn1(&in, &in, CBS_ASN1_SEQUENCE)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_infos,
+ PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+
+ while (CBS_len(&in) > 0) {
+ CBS content_info;
+ if (!CBS_get_asn1(&in, &content_info, CBS_ASN1_SEQUENCE)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_infos,
+ PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+
+ if (!PKCS12_handle_content_info(&content_info, depth + 1, ctx)) {
+ goto err;
+ }
+ }
+
+ /* NSS includes additional data after the SEQUENCE, but it's an (unwrapped)
+ * copy of the same encrypted private key (with the same IV and
+ * ciphertext)! */
+
+ ret = 1;
+
+err:
+ if (der_bytes != NULL) {
+ OPENSSL_free(der_bytes);
+ }
+ return ret;
+}
+
+/* PKCS12_handle_content_info parses a single PKCS#7 ContentInfo element in a
+ * PKCS#12 structure. */
+static int PKCS12_handle_content_info(CBS *content_info, unsigned depth,
+ struct pkcs12_context *ctx) {
+ CBS content_type, wrapped_contents, contents, content_infos;
+ int nid, ret = 0;
+
+ if (!CBS_get_asn1(content_info, &content_type, CBS_ASN1_OBJECT) ||
+ !CBS_get_asn1(content_info, &wrapped_contents,
+ CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+
+ nid = OBJ_cbs2nid(&content_type);
+ if (nid == NID_pkcs7_encrypted) {
+ /* See https://tools.ietf.org/html/rfc2315#section-13.
+ *
+ * PKCS#7 encrypted data inside a PKCS#12 structure is generally an
+ * encrypted certificate bag and it's generally encrypted with 40-bit
+ * RC2-CBC. */
+ CBS version_bytes, eci, contents_type, ai, encrypted_contents;
+ X509_ALGOR *algor = NULL;
+ const uint8_t *inp;
+ uint8_t *out;
+ size_t out_len;
+
+ if (!CBS_get_asn1(&wrapped_contents, &contents, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1(&contents, &version_bytes, CBS_ASN1_INTEGER) ||
+ /* EncryptedContentInfo, see
+ * https://tools.ietf.org/html/rfc2315#section-10.1 */
+ !CBS_get_asn1(&contents, &eci, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1(&eci, &contents_type, CBS_ASN1_OBJECT) ||
+ /* AlgorithmIdentifier, see
+ * https://tools.ietf.org/html/rfc5280#section-4.1.1.2 */
+ !CBS_get_asn1_element(&eci, &ai, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1(&eci, &encrypted_contents,
+ CBS_ASN1_CONTEXT_SPECIFIC | 0)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
+ PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+
+ if (OBJ_cbs2nid(&contents_type) != NID_pkcs7_data) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
+ PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+
+ inp = CBS_data(&ai);
+ algor = d2i_X509_ALGOR(NULL, &inp, CBS_len(&ai));
+ if (algor == NULL) {
+ goto err;
+ }
+ if (inp != CBS_data(&ai) + CBS_len(&ai)) {
+ X509_ALGOR_free(algor);
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
+ PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+
+ if (!pbe_crypt(algor, ctx->password, ctx->password_len,
+ CBS_data(&encrypted_contents), CBS_len(&encrypted_contents),
+ &out, &out_len, 0 /* decrypt */)) {
+ X509_ALGOR_free(algor);
+ goto err;
+ }
+ X509_ALGOR_free(algor);
+
+ CBS_init(&content_infos, out, out_len);
+ ret = PKCS12_handle_content_infos(&content_infos, depth + 1, ctx);
+ OPENSSL_free(out);
+ } else if (nid == NID_pkcs7_data) {
+ CBS octet_string_contents;
+
+ if (!CBS_get_asn1(&wrapped_contents, &octet_string_contents,
+ CBS_ASN1_OCTETSTRING)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
+ PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+
+ ret = PKCS12_handle_content_infos(&octet_string_contents, depth + 1, ctx);
+ } else if (nid == NID_pkcs8ShroudedKeyBag) {
+ /* See ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1.pdf, section
+ * 4.2.2. */
+ const uint8_t *inp = CBS_data(&wrapped_contents);
+ PKCS8_PRIV_KEY_INFO *pki = NULL;
+ X509_SIG *encrypted = NULL;
+
+ if (*ctx->out_key) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
+ PKCS8_R_MULTIPLE_PRIVATE_KEYS_IN_PKCS12);
+ goto err;
+ }
+
+ /* encrypted isn't actually an X.509 signature, but it has the same
+ * structure as one and so |X509_SIG| is reused to store it. */
+ encrypted = d2i_X509_SIG(NULL, &inp, CBS_len(&wrapped_contents));
+ if (encrypted == NULL) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
+ PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+ if (inp != CBS_data(&wrapped_contents) + CBS_len(&wrapped_contents)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
+ PKCS8_R_BAD_PKCS12_DATA);
+ X509_SIG_free(encrypted);
+ goto err;
+ }
+
+ pki = PKCS8_decrypt_pbe(encrypted, ctx->password, ctx->password_len);
+ X509_SIG_free(encrypted);
+ if (pki == NULL) {
+ goto err;
+ }
+
+ *ctx->out_key = EVP_PKCS82PKEY(pki);
+ PKCS8_PRIV_KEY_INFO_free(pki);
+
+ if (ctx->out_key == NULL) {
+ goto err;
+ }
+ ret = 1;
+ } else if (nid == NID_certBag) {
+ CBS cert_bag, cert_type, wrapped_cert, cert;
+
+ if (!CBS_get_asn1(&wrapped_contents, &cert_bag, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1(&cert_bag, &cert_type, CBS_ASN1_OBJECT) ||
+ !CBS_get_asn1(&cert_bag, &wrapped_cert,
+ CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
+ !CBS_get_asn1(&wrapped_cert, &cert, CBS_ASN1_OCTETSTRING)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
+ PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+
+ if (OBJ_cbs2nid(&cert_type) == NID_x509Certificate) {
+ const uint8_t *inp = CBS_data(&cert);
+ X509 *x509 = d2i_X509(NULL, &inp, CBS_len(&cert));
+ if (!x509) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
+ PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+ if (inp != CBS_data(&cert) + CBS_len(&cert)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_handle_content_info,
+ PKCS8_R_BAD_PKCS12_DATA);
+ X509_free(x509);
+ goto err;
+ }
+
+ if (0 == sk_X509_push(ctx->out_certs, x509)) {
+ X509_free(x509);
+ goto err;
+ }
+ }
+ ret = 1;
+ } else {
+ /* Unknown element type - ignore it. */
+ ret = 1;
+ }
+
+err:
+ return ret;
+}
+
+int PKCS12_get_key_and_certs(EVP_PKEY **out_key, STACK_OF(X509) *out_certs,
+ CBS *ber_in, const char *password) {
+ uint8_t *der_bytes = NULL;
+ size_t der_len;
+ CBS in, pfx, mac_data, authsafe, content_type, wrapped_authsafes, authsafes;
+ uint64_t version;
+ int ret = 0;
+ struct pkcs12_context ctx;
+ const size_t original_out_certs_len = sk_X509_num(out_certs);
+
+ /* The input may be in BER format. */
+ if (!CBS_asn1_ber_to_der(ber_in, &der_bytes, &der_len)) {
+ return 0;
+ }
+ if (der_bytes != NULL) {
+ CBS_init(&in, der_bytes, der_len);
+ } else {
+ CBS_init(&in, CBS_data(ber_in), CBS_len(ber_in));
+ }
+
+ *out_key = NULL;
+ memset(&ctx, 0, sizeof(ctx));
+
+ /* See ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1.pdf, section
+ * four. */
+ if (!CBS_get_asn1(&in, &pfx, CBS_ASN1_SEQUENCE) ||
+ CBS_len(&in) != 0 ||
+ !CBS_get_asn1_uint64(&pfx, &version)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+
+ if (version < 3) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_VERSION);
+ goto err;
+ }
+
+ if (!CBS_get_asn1(&pfx, &authsafe, CBS_ASN1_SEQUENCE)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+
+ if (CBS_len(&pfx) == 0) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_MISSING_MAC);
+ goto err;
+ }
+
+ if (!CBS_get_asn1(&pfx, &mac_data, CBS_ASN1_SEQUENCE)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+
+ /* authsafe is a PKCS#7 ContentInfo. See
+ * https://tools.ietf.org/html/rfc2315#section-7. */
+ if (!CBS_get_asn1(&authsafe, &content_type, CBS_ASN1_OBJECT) ||
+ !CBS_get_asn1(&authsafe, &wrapped_authsafes,
+ CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+
+ /* The content type can either be |NID_pkcs7_data| or |NID_pkcs7_signed|. The
+ * latter indicates that it's signed by a public key, which isn't
+ * supported. */
+ if (OBJ_cbs2nid(&content_type) != NID_pkcs7_data) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse,
+ PKCS8_R_PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED);
+ goto err;
+ }
+
+ if (!CBS_get_asn1(&wrapped_authsafes, &authsafes, CBS_ASN1_OCTETSTRING)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+
+ ctx.out_key = out_key;
+ ctx.out_certs = out_certs;
+ if (!ascii_to_ucs2(password, strlen(password), &ctx.password,
+ &ctx.password_len)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_DECODE_ERROR);
+ goto err;
+ }
+
+ /* Verify the MAC. */
+ {
+ CBS mac, hash_type_seq, hash_oid, salt, expected_mac;
+ uint64_t iterations;
+ int hash_nid;
+ const EVP_MD *md;
+ uint8_t hmac_key[EVP_MAX_MD_SIZE];
+ uint8_t hmac[EVP_MAX_MD_SIZE];
+ unsigned hmac_len;
+
+ if (!CBS_get_asn1(&mac_data, &mac, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1(&mac, &hash_type_seq, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1(&hash_type_seq, &hash_oid, CBS_ASN1_OBJECT) ||
+ !CBS_get_asn1(&mac, &expected_mac, CBS_ASN1_OCTETSTRING) ||
+ !CBS_get_asn1(&mac_data, &salt, CBS_ASN1_OCTETSTRING)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+
+ /* The iteration count is optional and the default is one. */
+ iterations = 1;
+ if (CBS_len(&mac_data) > 0) {
+ if (!CBS_get_asn1_uint64(&mac_data, &iterations) ||
+ iterations > INT_MAX) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA);
+ goto err;
+ }
+ }
+
+ hash_nid = OBJ_cbs2nid(&hash_oid);
+ if (hash_nid == NID_undef ||
+ (md = EVP_get_digestbynid(hash_nid)) == NULL) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_UNKNOWN_HASH);
+ goto err;
+ }
+
+ if (!pkcs12_key_gen_raw(ctx.password, ctx.password_len, CBS_data(&salt),
+ CBS_len(&salt), PKCS12_MAC_ID, iterations,
+ EVP_MD_size(md), hmac_key, md)) {
+ goto err;
+ }
+
+ if (NULL == HMAC(md, hmac_key, EVP_MD_size(md), CBS_data(&authsafes),
+ CBS_len(&authsafes), hmac, &hmac_len)) {
+ goto err;
+ }
+
+ if (!CBS_mem_equal(&expected_mac, hmac, hmac_len)) {
+ OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_INCORRECT_PASSWORD);
+ goto err;
+ }
+ }
+
+ /* authsafes contains a series of PKCS#7 ContentInfos. */
+ if (!PKCS12_handle_content_infos(&authsafes, 0, &ctx)) {
+ goto err;
+ }
+
+ ret = 1;
+
+err:
+ if (ctx.password) {
+ OPENSSL_free(ctx.password);
+ }
+ if (der_bytes) {
+ OPENSSL_free(der_bytes);
+ }
+ if (!ret) {
+ if (*out_key) {
+ EVP_PKEY_free(*out_key);
+ *out_key = NULL;
+ }
+ while (sk_X509_num(out_certs) > original_out_certs_len) {
+ X509 *x509 = sk_X509_pop(out_certs);
+ X509_free(x509);
+ }
+ }
+
+ return ret;
+}
+
+void PKCS12_PBE_add(){};
+
+struct pkcs12_st {
+ uint8_t *ber_bytes;
+ size_t ber_len;
+};
+
+PKCS12* d2i_PKCS12(PKCS12 **out_p12, const uint8_t **ber_bytes, size_t ber_len) {
+ PKCS12 *p12;
+
+ /* out_p12 must be NULL because we don't export the PKCS12 structure. */
+ assert(out_p12 == NULL);
+
+ p12 = OPENSSL_malloc(sizeof(PKCS12));
+ if (!p12) {
+ return NULL;
+ }
+
+ p12->ber_bytes = OPENSSL_malloc(ber_len);
+ if (!p12->ber_bytes) {
+ OPENSSL_free(p12);
+ return NULL;
+ }
+
+ memcpy(p12->ber_bytes, *ber_bytes, ber_len);
+ p12->ber_len = ber_len;
+ *ber_bytes += ber_len;
+
+ return p12;
+}
+
+PKCS12* d2i_PKCS12_bio(BIO *bio, PKCS12 **out_p12) {
+ size_t used = 0;
+ BUF_MEM *buf;
+ const uint8_t *dummy;
+ static const size_t kMaxSize = 256 * 1024;
+ PKCS12 *ret = NULL;
+
+ buf = BUF_MEM_new();
+ if (buf == NULL) {
+ return NULL;
+ }
+ if (BUF_MEM_grow(buf, 8192) == 0) {
+ goto out;
+ }
+
+ for (;;) {
+ int n = BIO_read(bio, &buf->data[used], buf->length - used);
+ if (n < 0) {
+ goto out;
+ }
+
+ if (n == 0) {
+ break;
+ }
+ used += n;
+
+ if (used < buf->length) {
+ continue;
+ }
+
+ if (buf->length > kMaxSize ||
+ BUF_MEM_grow(buf, buf->length * 2) == 0) {
+ goto out;
+ }
+ }
+
+ dummy = (uint8_t*) buf->data;
+ ret = d2i_PKCS12(out_p12, &dummy, used);
+
+out:
+ BUF_MEM_free(buf);
+ return ret;
+}
+
+PKCS12* d2i_PKCS12_fp(FILE *fp, PKCS12 **out_p12) {
+ BIO *bio;
+ PKCS12 *ret;
+
+ bio = BIO_new_fp(fp, 0 /* don't take ownership */);
+ if (!bio) {
+ return NULL;
+ }
+
+ ret = d2i_PKCS12_bio(bio, out_p12);
+ BIO_free(bio);
+ return ret;
+}
+
+int PKCS12_parse(const PKCS12 *p12, const char *password, EVP_PKEY **out_pkey,
+ X509 **out_cert, STACK_OF(X509) **out_ca_certs) {
+ CBS ber_bytes;
+ STACK_OF(X509) *ca_certs = NULL;
+ char ca_certs_alloced = 0;
+
+ if (out_ca_certs != NULL && *out_ca_certs != NULL) {
+ ca_certs = *out_ca_certs;
+ }
+
+ if (!ca_certs) {
+ ca_certs = sk_X509_new_null();
+ if (ca_certs == NULL) {
+ return 0;
+ }
+ ca_certs_alloced = 1;
+ }
+
+ CBS_init(&ber_bytes, p12->ber_bytes, p12->ber_len);
+ if (!PKCS12_get_key_and_certs(out_pkey, ca_certs, &ber_bytes, password)) {
+ if (ca_certs_alloced) {
+ sk_X509_free(ca_certs);
+ }
+ return 0;
+ }
+
+ *out_cert = NULL;
+ if (sk_X509_num(ca_certs) > 0) {
+ *out_cert = sk_X509_shift(ca_certs);
+ }
+
+ if (out_ca_certs) {
+ *out_ca_certs = ca_certs;
+ } else {
+ sk_X509_pop_free(ca_certs, X509_free);
+ }
+
+ return 1;
+}
+
+void PKCS12_free(PKCS12 *p12) {
+ OPENSSL_free(p12->ber_bytes);
+ OPENSSL_free(p12);
+}
diff --git a/crypto/pkcs8/pkcs8_error.c b/crypto/pkcs8/pkcs8_error.c
index de1661b..3041658 100644
--- a/crypto/pkcs8/pkcs8_error.c
+++ b/crypto/pkcs8/pkcs8_error.c
@@ -19,6 +19,10 @@
const ERR_STRING_DATA PKCS8_error_string_data[] = {
{ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_EVP_PKCS82PKEY, 0), "EVP_PKCS82PKEY"},
{ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_EVP_PKEY2PKCS8, 0), "EVP_PKEY2PKCS8"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS12_get_key_and_certs, 0), "PKCS12_get_key_and_certs"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS12_handle_content_info, 0), "PKCS12_handle_content_info"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS12_handle_content_infos, 0), "PKCS12_handle_content_infos"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS12_parse, 0), "PKCS12_parse"},
{ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS5_pbe2_set_iv, 0), "PKCS5_pbe2_set_iv"},
{ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS5_pbe_set, 0), "PKCS5_pbe_set"},
{ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_PKCS5_pbe_set0_algor, 0), "PKCS5_pbe_set0_algor"},
@@ -30,17 +34,27 @@ const ERR_STRING_DATA PKCS8_error_string_data[] = {
{ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pbe_crypt, 0), "pbe_crypt"},
{ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pkcs12_item_decrypt_d2i, 0), "pkcs12_item_decrypt_d2i"},
{ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pkcs12_item_i2d_encrypt, 0), "pkcs12_item_i2d_encrypt"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pkcs12_key_gen_asc, 0), "pkcs12_key_gen_asc"},
{ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pkcs12_key_gen_raw, 0), "pkcs12_key_gen_raw"},
+ {ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pkcs12_key_gen_uni, 0), "pkcs12_key_gen_uni"},
{ERR_PACK(ERR_LIB_PKCS8, PKCS8_F_pkcs12_pbe_keyivgen, 0), "pkcs12_pbe_keyivgen"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_BAD_MAC), "BAD_MAC"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_BAD_PKCS12_DATA), "BAD_PKCS12_DATA"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_BAD_PKCS12_VERSION), "BAD_PKCS12_VERSION"},
{ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER), "CIPHER_HAS_NO_OBJECT_IDENTIFIER"},
{ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_CRYPT_ERROR), "CRYPT_ERROR"},
{ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_DECODE_ERROR), "DECODE_ERROR"},
{ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_ENCODE_ERROR), "ENCODE_ERROR"},
{ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_ENCRYPT_ERROR), "ENCRYPT_ERROR"},
{ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_ERROR_SETTING_CIPHER_PARAMS), "ERROR_SETTING_CIPHER_PARAMS"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_INCORRECT_PASSWORD), "INCORRECT_PASSWORD"},
{ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_KEYGEN_FAILURE), "KEYGEN_FAILURE"},
{ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_KEY_GEN_ERROR), "KEY_GEN_ERROR"},
{ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_METHOD_NOT_SUPPORTED), "METHOD_NOT_SUPPORTED"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_MISSING_MAC), "MISSING_MAC"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_MULTIPLE_PRIVATE_KEYS_IN_PKCS12), "MULTIPLE_PRIVATE_KEYS_IN_PKCS12"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED), "PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_PKCS12_TOO_DEEPLY_NESTED), "PKCS12_TOO_DEEPLY_NESTED"},
{ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_PRIVATE_KEY_DECODE_ERROR), "PRIVATE_KEY_DECODE_ERROR"},
{ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_PRIVATE_KEY_ENCODE_ERROR), "PRIVATE_KEY_ENCODE_ERROR"},
{ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_TOO_LONG), "TOO_LONG"},
@@ -48,6 +62,7 @@ const ERR_STRING_DATA PKCS8_error_string_data[] = {
{ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_UNKNOWN_CIPHER), "UNKNOWN_CIPHER"},
{ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_UNKNOWN_CIPHER_ALGORITHM), "UNKNOWN_CIPHER_ALGORITHM"},
{ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_UNKNOWN_DIGEST), "UNKNOWN_DIGEST"},
+ {ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_UNKNOWN_HASH), "UNKNOWN_HASH"},
{ERR_PACK(ERR_LIB_PKCS8, 0, PKCS8_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM), "UNSUPPORTED_PRIVATE_KEY_ALGORITHM"},
{0, NULL},
};
diff --git a/crypto/poly1305/poly1305.c b/crypto/poly1305/poly1305.c
index 9b9c734..bf5cd5e 100644
--- a/crypto/poly1305/poly1305.c
+++ b/crypto/poly1305/poly1305.c
@@ -48,7 +48,7 @@ static void U32TO8_LE(uint8_t *m, uint32_t v) {
}
#endif
-#if defined(OPENSSL_ARM)
+#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
void CRYPTO_poly1305_init_neon(poly1305_state *state, const uint8_t key[32]);
void CRYPTO_poly1305_update_neon(poly1305_state *state, const uint8_t *in,
@@ -165,7 +165,7 @@ void CRYPTO_poly1305_init(poly1305_state *statep, const uint8_t key[32]) {
struct poly1305_state_st *state = (struct poly1305_state_st *)statep;
uint32_t t0, t1, t2, t3;
-#if defined(OPENSSL_ARM)
+#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
if (CRYPTO_is_NEON_functional()) {
CRYPTO_poly1305_init_neon(statep, key);
return;
@@ -212,7 +212,7 @@ void CRYPTO_poly1305_update(poly1305_state *statep, const uint8_t *in,
unsigned int i;
struct poly1305_state_st *state = (struct poly1305_state_st *)statep;
-#if defined(OPENSSL_ARM)
+#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
if (CRYPTO_is_NEON_functional()) {
CRYPTO_poly1305_update_neon(statep, in, in_len);
return;
@@ -255,7 +255,7 @@ void CRYPTO_poly1305_finish(poly1305_state *statep, uint8_t mac[16]) {
uint32_t g0, g1, g2, g3, g4;
uint32_t b, nb;
-#if defined(OPENSSL_ARM)
+#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
if (CRYPTO_is_NEON_functional()) {
CRYPTO_poly1305_finish_neon(statep, mac);
return;
diff --git a/crypto/poly1305/poly1305_arm.c b/crypto/poly1305/poly1305_arm.c
index 9d5e276..002a4c4 100644
--- a/crypto/poly1305/poly1305_arm.c
+++ b/crypto/poly1305/poly1305_arm.c
@@ -17,8 +17,7 @@
#include <openssl/poly1305.h>
-
-#if defined(OPENSSL_ARM)
+#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
typedef struct {
uint32_t v[12]; /* for alignment; only using 10 */
@@ -285,4 +284,4 @@ void CRYPTO_poly1305_finish_neon(poly1305_state *state, uint8_t mac[16]) {
fe1305x2_tobytearray(mac, h);
}
-#endif /* OPENSSL_ARM */
+#endif /* OPENSSL_ARM && !OPENSSL_NO_ASM */
diff --git a/crypto/poly1305/poly1305_arm_asm.S b/crypto/poly1305/poly1305_arm_asm.S
index 9cf7656..9d87413 100644
--- a/crypto/poly1305/poly1305_arm_asm.S
+++ b/crypto/poly1305/poly1305_arm_asm.S
@@ -1,4 +1,4 @@
-#if defined(__arm__)
+#if defined(__arm__) && !defined(OPENSSL_NO_ASM)
# This implementation was taken from the public domain, neon2 version in
# SUPERCOP by D. J. Bernstein and Peter Schwabe.
@@ -2012,4 +2012,4 @@ vst1.8 d4,[r0,: 64]
add sp,sp,#0
bx lr
-#endif
+#endif /* __arm__ && !OPENSSL_NO_ASM */
diff --git a/crypto/rand/urandom.c b/crypto/rand/urandom.c
index 6cd9271..2ad4af0 100644
--- a/crypto/rand/urandom.c
+++ b/crypto/rand/urandom.c
@@ -87,7 +87,7 @@ static int urandom_buffering = 0;
/* urandom_get_fd_locked returns a file descriptor to /dev/urandom. The caller
* of this function must hold CRYPTO_LOCK_RAND. */
-static int urandom_get_fd_locked() {
+static int urandom_get_fd_locked(void) {
if (urandom_fd != -2)
return urandom_fd;
diff --git a/crypto/rsa/rsa_test.c b/crypto/rsa/rsa_test.c
index 4a0069c..a5bc366 100644
--- a/crypto/rsa/rsa_test.c
+++ b/crypto/rsa/rsa_test.c
@@ -58,6 +58,7 @@
#include <openssl/bio.h>
#include <openssl/bn.h>
+#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/obj.h>
@@ -237,7 +238,7 @@ static int key3(RSA *key, unsigned char *c) {
SetKey;
}
-static int test_bad_key() {
+static int test_bad_key(void) {
RSA *key = RSA_new();
BIGNUM e;
@@ -267,7 +268,7 @@ static int test_bad_key() {
return 1;
}
-static int test_only_d_given() {
+static int test_only_d_given(void) {
RSA *key = RSA_new();
uint8_t buf[64];
unsigned buf_len = sizeof(buf);
@@ -312,7 +313,7 @@ err:
return ret;
}
-static int test_recover_crt_params() {
+static int test_recover_crt_params(void) {
RSA *key1, *key2;
BIGNUM *e = BN_new();
uint8_t buf[128];
@@ -394,6 +395,8 @@ int main(int argc, char *argv[]) {
int num;
int n;
+ CRYPTO_library_init();
+
plen = sizeof(ptext_ex) - 1;
for (v = 0; v < 3; v++) {
diff --git a/crypto/sha/sha1_test.c b/crypto/sha/sha1_test.c
index 72ef9e1..d723e40 100644
--- a/crypto/sha/sha1_test.c
+++ b/crypto/sha/sha1_test.c
@@ -56,8 +56,9 @@
#include <stdio.h>
-#include <openssl/sha.h>
+#include <openssl/crypto.h>
#include <openssl/digest.h>
+#include <openssl/sha.h>
static const char *const test[] = {
@@ -67,7 +68,7 @@ static const char *const expected[] = {
"a9993e364706816aba3e25717850c26c9cd0d89d",
"84983e441c3bd26ebaae4aa1f95129e5e54670f1", };
-static int test_incremental() {
+static int test_incremental(void) {
EVP_MD_CTX ctx;
char buf[1000];
uint8_t md[SHA_DIGEST_LENGTH];
@@ -102,6 +103,8 @@ int main(int argc, char **argv) {
char md_hex[sizeof(md) * 2 + 1];
int ok = 1;
+ CRYPTO_library_init();
+
for (i = 0; test[i] != NULL; i++) {
EVP_Digest(test[i], strlen(test[i]), md, NULL, EVP_sha1(), NULL);
for (j = 0; j < sizeof(md); j++) {
diff --git a/crypto/sha/sha512.c b/crypto/sha/sha512.c
index dcaac6f..884371a 100644
--- a/crypto/sha/sha512.c
+++ b/crypto/sha/sha512.c
@@ -60,6 +60,8 @@
#include <openssl/mem.h>
+#include "../internal.h"
+
/* IMPLEMENTATION NOTES.
*
@@ -92,14 +94,14 @@
#endif
int SHA384_Init(SHA512_CTX *sha) {
- sha->h[0] = 0xcbbb9d5dc1059ed8;
- sha->h[1] = 0x629a292a367cd507;
- sha->h[2] = 0x9159015a3070dd17;
- sha->h[3] = 0x152fecd8f70e5939;
- sha->h[4] = 0x67332667ffc00b31;
- sha->h[5] = 0x8eb44a8768581511;
- sha->h[6] = 0xdb0c2e0d64f98fa7;
- sha->h[7] = 0x47b5481dbefa4fa4;
+ sha->h[0] = OPENSSL_U64(0xcbbb9d5dc1059ed8);
+ sha->h[1] = OPENSSL_U64(0x629a292a367cd507);
+ sha->h[2] = OPENSSL_U64(0x9159015a3070dd17);
+ sha->h[3] = OPENSSL_U64(0x152fecd8f70e5939);
+ sha->h[4] = OPENSSL_U64(0x67332667ffc00b31);
+ sha->h[5] = OPENSSL_U64(0x8eb44a8768581511);
+ sha->h[6] = OPENSSL_U64(0xdb0c2e0d64f98fa7);
+ sha->h[7] = OPENSSL_U64(0x47b5481dbefa4fa4);
sha->Nl = 0;
sha->Nh = 0;
@@ -110,14 +112,14 @@ int SHA384_Init(SHA512_CTX *sha) {
int SHA512_Init(SHA512_CTX *sha) {
- sha->h[0] = 0x6a09e667f3bcc908;
- sha->h[1] = 0xbb67ae8584caa73b;
- sha->h[2] = 0x3c6ef372fe94f82b;
- sha->h[3] = 0xa54ff53a5f1d36f1;
- sha->h[4] = 0x510e527fade682d1;
- sha->h[5] = 0x9b05688c2b3e6c1f;
- sha->h[6] = 0x1f83d9abfb41bd6b;
- sha->h[7] = 0x5be0cd19137e2179;
+ sha->h[0] = OPENSSL_U64(0x6a09e667f3bcc908);
+ sha->h[1] = OPENSSL_U64(0xbb67ae8584caa73b);
+ sha->h[2] = OPENSSL_U64(0x3c6ef372fe94f82b);
+ sha->h[3] = OPENSSL_U64(0xa54ff53a5f1d36f1);
+ sha->h[4] = OPENSSL_U64(0x510e527fade682d1);
+ sha->h[5] = OPENSSL_U64(0x9b05688c2b3e6c1f);
+ sha->h[6] = OPENSSL_U64(0x1f83d9abfb41bd6b);
+ sha->h[7] = OPENSSL_U64(0x5be0cd19137e2179);
sha->Nl = 0;
sha->Nh = 0;
@@ -189,7 +191,7 @@ int SHA512_Update(SHA512_CTX *c, const void *in_data, size_t len) {
if (len == 0)
return 1;
- l = (c->Nl + (((uint64_t)len) << 3)) & 0xffffffffffffffff;
+ l = (c->Nl + (((uint64_t)len) << 3)) & OPENSSL_U64(0xffffffffffffffff);
if (l < c->Nl) {
c->Nh++;
}
diff --git a/crypto/x509/pkcs7.c b/crypto/x509/pkcs7.c
index 7744fcc..75c101b 100644
--- a/crypto/x509/pkcs7.c
+++ b/crypto/x509/pkcs7.c
@@ -19,48 +19,61 @@
#include <openssl/obj.h>
#include <openssl/stack.h>
+#include "../bytestring/internal.h"
+
int PKCS7_get_certificates(STACK_OF(X509) *out_certs, CBS *cbs) {
- CBS content_info, content_type, wrapped_signed_data, signed_data,
- version_bytes, certificates;
- int nid;
+ uint8_t *der_bytes = NULL;
+ size_t der_len;
+ CBS in, content_info, content_type, wrapped_signed_data, signed_data,
+ certificates;
const size_t initial_certs_len = sk_X509_num(out_certs);
+ uint64_t version;
+ int ret = 0;
+
+ /* The input may be in BER format. */
+ if (!CBS_asn1_ber_to_der(cbs, &der_bytes, &der_len)) {
+ return 0;
+ }
+ if (der_bytes != NULL) {
+ CBS_init(&in, der_bytes, der_len);
+ } else {
+ CBS_init(&in, CBS_data(cbs), CBS_len(cbs));
+ }
/* See https://tools.ietf.org/html/rfc2315#section-7 */
- if (!CBS_get_asn1_ber(cbs, &content_info, CBS_ASN1_SEQUENCE) ||
+ if (!CBS_get_asn1(&in, &content_info, CBS_ASN1_SEQUENCE) ||
!CBS_get_asn1(&content_info, &content_type, CBS_ASN1_OBJECT)) {
- return 0;
+ goto err;
}
- nid = OBJ_cbs2nid(&content_type);
- if (nid != NID_pkcs7_signed) {
+ if (OBJ_cbs2nid(&content_type) != NID_pkcs7_signed) {
OPENSSL_PUT_ERROR(X509, PKCS7_get_certificates,
X509_R_NOT_PKCS7_SIGNED_DATA);
- return 0;
+ goto err;
}
/* See https://tools.ietf.org/html/rfc2315#section-9.1 */
- if (!CBS_get_asn1_ber(&content_info, &wrapped_signed_data,
- CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
- !CBS_get_asn1_ber(&wrapped_signed_data, &signed_data,
- CBS_ASN1_SEQUENCE) ||
- !CBS_get_asn1_ber(&signed_data, &version_bytes, CBS_ASN1_INTEGER) ||
- !CBS_get_asn1_ber(&signed_data, NULL /* digests */, CBS_ASN1_SET) ||
- !CBS_get_asn1_ber(&signed_data, NULL /* content */, CBS_ASN1_SEQUENCE)) {
- return 0;
+ if (!CBS_get_asn1(&content_info, &wrapped_signed_data,
+ CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
+ !CBS_get_asn1(&wrapped_signed_data, &signed_data, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1_uint64(&signed_data, &version) ||
+ !CBS_get_asn1(&signed_data, NULL /* digests */, CBS_ASN1_SET) ||
+ !CBS_get_asn1(&signed_data, NULL /* content */, CBS_ASN1_SEQUENCE)) {
+ goto err;
}
- if (CBS_len(&version_bytes) < 1 || CBS_data(&version_bytes)[0] == 0) {
+ if (version < 1) {
OPENSSL_PUT_ERROR(X509, PKCS7_get_certificates,
X509_R_BAD_PKCS7_VERSION);
- return 0;
+ goto err;
}
- if (!CBS_get_asn1_ber(&signed_data, &certificates,
- CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
+ if (!CBS_get_asn1(&signed_data, &certificates,
+ CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
OPENSSL_PUT_ERROR(X509, PKCS7_get_certificates,
X509_R_NO_CERTIFICATES_INCLUDED);
- return 0;
+ goto err;
}
while (CBS_len(&certificates) > 0) {
@@ -86,15 +99,21 @@ int PKCS7_get_certificates(STACK_OF(X509) *out_certs, CBS *cbs) {
sk_X509_push(out_certs, x509);
}
- return 1;
+ ret = 1;
err:
- while (sk_X509_num(out_certs) != initial_certs_len) {
- X509 *x509 = sk_X509_pop(out_certs);
- X509_free(x509);
+ if (der_bytes) {
+ OPENSSL_free(der_bytes);
+ }
+
+ if (!ret) {
+ while (sk_X509_num(out_certs) != initial_certs_len) {
+ X509 *x509 = sk_X509_pop(out_certs);
+ X509_free(x509);
+ }
}
- return 0;
+ return ret;
}
int PKCS7_bundle_certificates(CBB *out, const STACK_OF(X509) *certs) {
diff --git a/crypto/x509/pkcs7_test.c b/crypto/x509/pkcs7_test.c
index eb2668f..2e20c40 100644
--- a/crypto/x509/pkcs7_test.c
+++ b/crypto/x509/pkcs7_test.c
@@ -16,13 +16,14 @@
#include <stdlib.h>
#include <openssl/bytestring.h>
+#include <openssl/crypto.h>
#include <openssl/stack.h>
#include <openssl/x509.h>
-/* kPKCS7DER contains the certificate chain of mail.google.com, as saved by NSS
+/* kPKCS7NSS contains the certificate chain of mail.google.com, as saved by NSS
* using the Chrome UI. */
-static const uint8_t kPKCS7DER[] = {
+static const uint8_t kPKCS7NSS[] = {
0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07,
0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01, 0x31, 0x00, 0x30, 0x80,
0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x00,
@@ -267,7 +268,69 @@ static const uint8_t kPKCS7DER[] = {
0x00, 0x00, 0x00,
};
-static int test_reparse() {
+/* kPKCS7Windows is the Equifax root certificate, as exported by Windows 7. */
+static const uint8_t kPKCS7Windows[] = {
+ 0x30, 0x82, 0x02, 0xb1, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0xa2, 0x30, 0x82, 0x02, 0x9e, 0x02,
+ 0x01, 0x01, 0x31, 0x00, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x02, 0x86, 0x30, 0x82, 0x02,
+ 0x82, 0x30, 0x82, 0x01, 0xeb, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01,
+ 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x04, 0x05, 0x00, 0x30, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1c, 0x30, 0x1a, 0x06,
+ 0x03, 0x55, 0x04, 0x0a, 0x13, 0x13, 0x45, 0x71, 0x75, 0x69, 0x66, 0x61,
+ 0x78, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x49, 0x6e, 0x63,
+ 0x2e, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1d,
+ 0x45, 0x71, 0x75, 0x69, 0x66, 0x61, 0x78, 0x20, 0x53, 0x65, 0x63, 0x75,
+ 0x72, 0x65, 0x20, 0x65, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73,
+ 0x20, 0x43, 0x41, 0x2d, 0x31, 0x30, 0x1e, 0x17, 0x0d, 0x39, 0x39, 0x30,
+ 0x36, 0x32, 0x31, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d,
+ 0x32, 0x30, 0x30, 0x36, 0x32, 0x31, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30,
+ 0x5a, 0x30, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x55, 0x53, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04,
+ 0x0a, 0x13, 0x13, 0x45, 0x71, 0x75, 0x69, 0x66, 0x61, 0x78, 0x20, 0x53,
+ 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x26,
+ 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1d, 0x45, 0x71, 0x75,
+ 0x69, 0x66, 0x61, 0x78, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20,
+ 0x65, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x20, 0x43, 0x41,
+ 0x2d, 0x31, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
+ 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00,
+ 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xce, 0x2f, 0x19, 0xbc, 0x17,
+ 0xb7, 0x77, 0xde, 0x93, 0xa9, 0x5f, 0x5a, 0x0d, 0x17, 0x4f, 0x34, 0x1a,
+ 0x0c, 0x98, 0xf4, 0x22, 0xd9, 0x59, 0xd4, 0xc4, 0x68, 0x46, 0xf0, 0xb4,
+ 0x35, 0xc5, 0x85, 0x03, 0x20, 0xc6, 0xaf, 0x45, 0xa5, 0x21, 0x51, 0x45,
+ 0x41, 0xeb, 0x16, 0x58, 0x36, 0x32, 0x6f, 0xe2, 0x50, 0x62, 0x64, 0xf9,
+ 0xfd, 0x51, 0x9c, 0xaa, 0x24, 0xd9, 0xf4, 0x9d, 0x83, 0x2a, 0x87, 0x0a,
+ 0x21, 0xd3, 0x12, 0x38, 0x34, 0x6c, 0x8d, 0x00, 0x6e, 0x5a, 0xa0, 0xd9,
+ 0x42, 0xee, 0x1a, 0x21, 0x95, 0xf9, 0x52, 0x4c, 0x55, 0x5a, 0xc5, 0x0f,
+ 0x38, 0x4f, 0x46, 0xfa, 0x6d, 0xf8, 0x2e, 0x35, 0xd6, 0x1d, 0x7c, 0xeb,
+ 0xe2, 0xf0, 0xb0, 0x75, 0x80, 0xc8, 0xa9, 0x13, 0xac, 0xbe, 0x88, 0xef,
+ 0x3a, 0x6e, 0xab, 0x5f, 0x2a, 0x38, 0x62, 0x02, 0xb0, 0x12, 0x7b, 0xfe,
+ 0x8f, 0xa6, 0x03, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x66, 0x30, 0x64,
+ 0x30, 0x11, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01,
+ 0x01, 0x04, 0x04, 0x03, 0x02, 0x00, 0x07, 0x30, 0x0f, 0x06, 0x03, 0x55,
+ 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff,
+ 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80,
+ 0x14, 0x4a, 0x78, 0x32, 0x52, 0x11, 0xdb, 0x59, 0x16, 0x36, 0x5e, 0xdf,
+ 0xc1, 0x14, 0x36, 0x40, 0x6a, 0x47, 0x7c, 0x4c, 0xa1, 0x30, 0x1d, 0x06,
+ 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x4a, 0x78, 0x32, 0x52,
+ 0x11, 0xdb, 0x59, 0x16, 0x36, 0x5e, 0xdf, 0xc1, 0x14, 0x36, 0x40, 0x6a,
+ 0x47, 0x7c, 0x4c, 0xa1, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x04, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x75,
+ 0x5b, 0xa8, 0x9b, 0x03, 0x11, 0xe6, 0xe9, 0x56, 0x4c, 0xcd, 0xf9, 0xa9,
+ 0x4c, 0xc0, 0x0d, 0x9a, 0xf3, 0xcc, 0x65, 0x69, 0xe6, 0x25, 0x76, 0xcc,
+ 0x59, 0xb7, 0xd6, 0x54, 0xc3, 0x1d, 0xcd, 0x99, 0xac, 0x19, 0xdd, 0xb4,
+ 0x85, 0xd5, 0xe0, 0x3d, 0xfc, 0x62, 0x20, 0xa7, 0x84, 0x4b, 0x58, 0x65,
+ 0xf1, 0xe2, 0xf9, 0x95, 0x21, 0x3f, 0xf5, 0xd4, 0x7e, 0x58, 0x1e, 0x47,
+ 0x87, 0x54, 0x3e, 0x58, 0xa1, 0xb5, 0xb5, 0xf8, 0x2a, 0xef, 0x71, 0xe7,
+ 0xbc, 0xc3, 0xf6, 0xb1, 0x49, 0x46, 0xe2, 0xd7, 0xa0, 0x6b, 0xe5, 0x56,
+ 0x7a, 0x9a, 0x27, 0x98, 0x7c, 0x46, 0x62, 0x14, 0xe7, 0xc9, 0xfc, 0x6e,
+ 0x03, 0x12, 0x79, 0x80, 0x38, 0x1d, 0x48, 0x82, 0x8d, 0xfc, 0x17, 0xfe,
+ 0x2a, 0x96, 0x2b, 0xb5, 0x62, 0xa6, 0xa6, 0x3d, 0xbd, 0x7f, 0x92, 0x59,
+ 0xcd, 0x5a, 0x2a, 0x82, 0xb2, 0x37, 0x79, 0x31, 0x00,
+};
+
+static int test_reparse(const uint8_t *der_bytes, size_t der_len) {
CBS pkcs7;
CBB cbb;
STACK_OF(X509) *certs = sk_X509_new_null();
@@ -275,13 +338,13 @@ static int test_reparse() {
uint8_t *result_data, *result2_data;
size_t result_len, result2_len, i;
- CBS_init(&pkcs7, kPKCS7DER, sizeof(kPKCS7DER));
+ CBS_init(&pkcs7, der_bytes, der_len);
if (!PKCS7_get_certificates(certs, &pkcs7)) {
fprintf(stderr, "PKCS7_get_certificates failed.\n");
return 0;
}
- CBB_init(&cbb, sizeof(kPKCS7DER));
+ CBB_init(&cbb, der_len);
if (!PKCS7_bundle_certificates(&cbb, certs) ||
!CBB_finish(&cbb, &result_data, &result_len)) {
fprintf(stderr, "PKCS7_bundle_certificates failed.\n");
@@ -309,7 +372,7 @@ static int test_reparse() {
}
}
- CBB_init(&cbb, sizeof(kPKCS7DER));
+ CBB_init(&cbb, der_len);
if (!PKCS7_bundle_certificates(&cbb, certs2) ||
!CBB_finish(&cbb, &result2_data, &result2_len)) {
fprintf(stderr,
@@ -331,8 +394,11 @@ static int test_reparse() {
return 1;
}
-int main() {
- if (!test_reparse()) {
+int main(void) {
+ CRYPTO_library_init();
+
+ if (!test_reparse(kPKCS7NSS, sizeof(kPKCS7NSS)) ||
+ !test_reparse(kPKCS7Windows, sizeof(kPKCS7Windows))) {
return 1;
}
diff --git a/crypto/x509/x509_cmp.c b/crypto/x509/x509_cmp.c
index 57e6167..0974ef6 100644
--- a/crypto/x509/x509_cmp.c
+++ b/crypto/x509/x509_cmp.c
@@ -78,7 +78,6 @@ int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b)
return(X509_NAME_cmp(ai->issuer,bi->issuer));
}
-#ifndef OPENSSL_NO_MD5
unsigned long X509_issuer_and_serial_hash(X509 *a)
{
unsigned long ret=0;
@@ -105,7 +104,6 @@ unsigned long X509_issuer_and_serial_hash(X509 *a)
EVP_MD_CTX_cleanup(&ctx);
return(ret);
}
-#endif
int X509_issuer_name_cmp(const X509 *a, const X509 *b)
{
@@ -122,12 +120,10 @@ int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b)
return(X509_NAME_cmp(a->crl->issuer,b->crl->issuer));
}
-#ifndef OPENSSL_NO_SHA
int X509_CRL_match(const X509_CRL *a, const X509_CRL *b)
{
return memcmp(a->sha1_hash, b->sha1_hash, 20);
}
-#endif
X509_NAME *X509_get_issuer_name(X509 *a)
{
@@ -139,12 +135,10 @@ unsigned long X509_issuer_name_hash(X509 *x)
return(X509_NAME_hash(x->cert_info->issuer));
}
-#ifndef OPENSSL_NO_MD5
unsigned long X509_issuer_name_hash_old(X509 *x)
{
return(X509_NAME_hash_old(x->cert_info->issuer));
}
-#endif
X509_NAME *X509_get_subject_name(X509 *a)
{
@@ -161,14 +155,11 @@ unsigned long X509_subject_name_hash(X509 *x)
return(X509_NAME_hash(x->cert_info->subject));
}
-#ifndef OPENSSL_NO_MD5
unsigned long X509_subject_name_hash_old(X509 *x)
{
return(X509_NAME_hash_old(x->cert_info->subject));
}
-#endif
-#ifndef OPENSSL_NO_SHA
/* Compare two certificates: they must be identical for
* this to work. NB: Although "cmp" operations are generally
* prototyped to take "const" arguments (eg. for use in
@@ -199,7 +190,6 @@ int X509_cmp(const X509 *a, const X509 *b)
}
return rv;
}
-#endif
int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b)
@@ -249,7 +239,6 @@ unsigned long X509_NAME_hash(X509_NAME *x)
}
-#ifndef OPENSSL_NO_MD5
/* I now DER encode the name and hash it. Since I cache the DER encoding,
* this is reasonably efficient. */
@@ -273,7 +262,6 @@ unsigned long X509_NAME_hash_old(X509_NAME *x)
return(ret);
}
-#endif
/* Search a stack of X509 for a match */
X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, X509_NAME *name,
@@ -364,7 +352,6 @@ int X509_check_private_key(X509 *x, EVP_PKEY *k)
* flags.
*/
-#ifndef OPENSSL_NO_EC
static int check_suite_b(EVP_PKEY *pkey, int sign_nid, unsigned long *pflags)
{
@@ -484,19 +471,6 @@ int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags)
return check_suite_b(pk, sign_nid, &flags);
}
-#else
-int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain,
- unsigned long flags)
- {
- return 0;
- }
-
-int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags)
- {
- return 0;
- }
-
-#endif
/* Not strictly speaking an "up_ref" as a STACK doesn't have a reference
* count but it has the same effect by duping the STACK and upping the ref
* of each X509 structure.
diff --git a/crypto/x509/x509_req.c b/crypto/x509/x509_req.c
index ccaf729..64f2c37 100644
--- a/crypto/x509/x509_req.c
+++ b/crypto/x509/x509_req.c
@@ -132,21 +132,17 @@ int X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k)
OPENSSL_PUT_ERROR(X509, X509_REQ_check_private_key, X509_R_KEY_TYPE_MISMATCH);
break;
case -2:
-#ifndef OPENSSL_NO_EC
if (k->type == EVP_PKEY_EC)
{
OPENSSL_PUT_ERROR(X509, X509_REQ_check_private_key, ERR_R_EC_LIB);
break;
}
-#endif
-#ifndef OPENSSL_NO_DH
if (k->type == EVP_PKEY_DH)
{
/* No idea */
OPENSSL_PUT_ERROR(X509, X509_REQ_check_private_key, X509_R_CANT_CHECK_DH_KEY);
break;
}
-#endif
OPENSSL_PUT_ERROR(X509, X509_REQ_check_private_key, X509_R_UNKNOWN_KEY_TYPE);
}
diff --git a/crypto/x509/x509spki.c b/crypto/x509/x509spki.c
index 0b0b4fa..03823b7 100644
--- a/crypto/x509/x509spki.c
+++ b/crypto/x509/x509spki.c
@@ -77,15 +77,19 @@ NETSCAPE_SPKI * NETSCAPE_SPKI_b64_decode(const char *str, int len)
{
unsigned char *spki_der;
const unsigned char *p;
- int spki_len;
+ size_t spki_len;
NETSCAPE_SPKI *spki;
- if(len <= 0) len = strlen(str);
- if (!(spki_der = OPENSSL_malloc(len + 1))) {
+ if (len <= 0)
+ len = strlen(str);
+ if (!EVP_DecodedLength(&spki_len, len)) {
+ OPENSSL_PUT_ERROR(X509, NETSCAPE_SPKI_b64_decode, X509_R_BASE64_DECODE_ERROR);
+ return NULL;
+ }
+ if (!(spki_der = OPENSSL_malloc(spki_len))) {
OPENSSL_PUT_ERROR(X509, NETSCAPE_SPKI_b64_decode, ERR_R_MALLOC_FAILURE);
return NULL;
}
- spki_len = EVP_DecodeBlock(spki_der, (const unsigned char *)str, len);
- if(spki_len < 0) {
+ if (!EVP_DecodeBase64(spki_der, &spki_len, spki_len, (const uint8_t *)str, len)) {
OPENSSL_PUT_ERROR(X509, NETSCAPE_SPKI_b64_decode, X509_R_BASE64_DECODE_ERROR);
OPENSSL_free(spki_der);
return NULL;
diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c
index 08cc79d..cbc46e2 100644
--- a/crypto/x509/x_all.c
+++ b/crypto/x509/x_all.c
@@ -345,7 +345,6 @@ int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa)
#endif
-#ifndef OPENSSL_NO_EC
#ifndef OPENSSL_NO_FP_API
EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey)
{
@@ -386,7 +385,6 @@ int i2d_ECPrivateKey_bio(BIO *bp, EC_KEY *eckey)
{
return ASN1_i2d_bio_of_const(EC_KEY,i2d_ECPrivateKey,bp,eckey);
}
-#endif
int X509_pubkey_digest(const X509 *data, const EVP_MD *type, unsigned char *md,
diff --git a/crypto/x509/x_crl.c b/crypto/x509/x_crl.c
index 2f77fd7..21785dc 100644
--- a/crypto/x509/x_crl.c
+++ b/crypto/x509/x_crl.c
@@ -234,9 +234,7 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
break;
case ASN1_OP_D2I_POST:
-#ifndef OPENSSL_NO_SHA
X509_CRL_digest(crl, EVP_sha1(), crl->sha1_hash, NULL);
-#endif
crl->idp = X509_CRL_get_ext_d2i(crl,
NID_issuing_distribution_point, NULL, NULL);
if (crl->idp)
diff --git a/crypto/x509/x_pubkey.c b/crypto/x509/x_pubkey.c
index 04275f7..c285aa6 100644
--- a/crypto/x509/x_pubkey.c
+++ b/crypto/x509/x_pubkey.c
@@ -300,7 +300,6 @@ int i2d_DSA_PUBKEY(const DSA *a, unsigned char **pp)
}
#endif
-#ifndef OPENSSL_NO_EC
EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length)
{
EVP_PKEY *pkey;
@@ -336,7 +335,6 @@ int i2d_EC_PUBKEY(const EC_KEY *a, unsigned char **pp)
EVP_PKEY_free(pktmp);
return(ret);
}
-#endif
int X509_PUBKEY_set0_param(X509_PUBKEY *pub, const ASN1_OBJECT *aobj,
int ptype, void *pval,
diff --git a/crypto/x509v3/tabtest.c b/crypto/x509v3/tabtest.c
index aa27c1e..f783938 100644
--- a/crypto/x509v3/tabtest.c
+++ b/crypto/x509v3/tabtest.c
@@ -62,14 +62,16 @@
#include <stdio.h>
+#include <openssl/crypto.h>
#include <openssl/x509v3.h>
#include "ext_dat.h"
-int main()
+int main(void)
{
int i, prev = -1, bad = 0;
const X509V3_EXT_METHOD **tmp;
+ CRYPTO_library_init();
i = sizeof(standard_exts) / sizeof(X509V3_EXT_METHOD *);
if(i != STANDARD_EXTENSION_COUNT)
fprintf(stderr, "Extension number invalid expecting %d\n", i);
diff --git a/crypto/x509v3/v3_purp.c b/crypto/x509v3/v3_purp.c
index feebd9a..e08bdf4 100644
--- a/crypto/x509v3/v3_purp.c
+++ b/crypto/x509v3/v3_purp.c
@@ -361,9 +361,7 @@ static void x509v3_cache_extensions(X509 *x)
size_t i;
int j;
if(x->ex_flags & EXFLAG_SET) return;
-#ifndef OPENSSL_NO_SHA
X509_digest(x, EVP_sha1(), x->sha1_hash, NULL);
-#endif
/* V1 should mean no extensions ... */
if(!X509_get_version(x)) x->ex_flags |= EXFLAG_V1;
/* Handle basic constraints */
diff --git a/crypto/x509v3/v3nametest.c b/crypto/x509v3/v3nametest.c
index d0d97ff..6a2ea85 100644
--- a/crypto/x509v3/v3nametest.c
+++ b/crypto/x509v3/v3nametest.c
@@ -55,6 +55,7 @@
#include <string.h>
#include <strings.h>
+#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
@@ -285,7 +286,7 @@ static const struct set_name_fn name_fns[] =
{NULL, NULL, 0}
};
-static X509 *make_cert()
+static X509 *make_cert(void)
{
X509 *ret = NULL;
X509 *crt = NULL;
@@ -391,6 +392,8 @@ static void run_cert(X509 *crt, const char *nameincert,
int
main(void)
{
+ CRYPTO_library_init();
+
const struct set_name_fn *pfn = name_fns;
while (pfn->name) {
const char *const *pname = names;
diff --git a/include/openssl/aead.h b/include/openssl/aead.h
index 6f66e9c..ad2bbf7 100644
--- a/include/openssl/aead.h
+++ b/include/openssl/aead.h
@@ -99,7 +99,7 @@ OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_gcm(void);
OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_gcm(void);
/* EVP_aead_chacha20_poly1305 is an AEAD built from ChaCha20 and Poly1305. */
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_chacha20_poly1305();
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_chacha20_poly1305(void);
/* EVP_aead_aes_128_key_wrap is AES-128 Key Wrap mode. This should never be
* used except to interoperate with existing systems that use this mode.
@@ -107,13 +107,13 @@ OPENSSL_EXPORT const EVP_AEAD *EVP_aead_chacha20_poly1305();
* If the nonce is emtpy then the default nonce will be used, otherwise it must
* be eight bytes long. The input must be a multiple of eight bytes long. No
* additional data can be given to this mode. */
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_key_wrap();
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_key_wrap(void);
/* EVP_aead_aes_256_key_wrap is AES-256 in Key Wrap mode. This should never be
* used except to interoperate with existing systems that use this mode.
*
* See |EVP_aead_aes_128_key_wrap| for details. */
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_key_wrap();
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_key_wrap(void);
/* EVP_has_aes_hardware returns one if we enable hardware support for fast and
* constant-time AES-GCM. */
@@ -129,7 +129,7 @@ OPENSSL_EXPORT int EVP_has_aes_hardware(void);
/* EVP_aead_rc4_md5_tls uses RC4 and HMAC(MD5) in MAC-then-encrypt mode. Unlike
* a standard AEAD, this is stateful as the RC4 state is carried from operation
* to operation. */
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_rc4_md5_tls();
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_rc4_md5_tls(void);
/* Utility functions. */
diff --git a/include/openssl/base.h b/include/openssl/base.h
index d79d63f..52cb1e9 100644
--- a/include/openssl/base.h
+++ b/include/openssl/base.h
@@ -63,6 +63,11 @@
#include <openssl/opensslfeatures.h>
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
#if defined(__x86_64) || defined(_M_AMD64) || defined(_M_X64)
#define OPENSSL_64_BIT
#define OPENSSL_X86_64
@@ -184,8 +189,10 @@ typedef struct evp_pkey_ctx_st EVP_PKEY_CTX;
typedef struct evp_pkey_method_st EVP_PKEY_METHOD;
typedef struct evp_pkey_st EVP_PKEY;
typedef struct hmac_ctx_st HMAC_CTX;
+typedef struct md4_state_st MD4_CTX;
typedef struct md5_state_st MD5_CTX;
typedef struct pkcs8_priv_key_info_st PKCS8_PRIV_KEY_INFO;
+typedef struct pkcs12_st PKCS12;
typedef struct rand_meth_st RAND_METHOD;
typedef struct rsa_meth_st RSA_METHOD;
typedef struct rsa_st RSA;
@@ -204,4 +211,8 @@ typedef struct x509_store_st X509_STORE;
typedef void *OPENSSL_BLOCK;
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
#endif /* OPENSSL_HEADER_BASE_H */
diff --git a/include/openssl/base64.h b/include/openssl/base64.h
index de94d8e..44f91eb 100644
--- a/include/openssl/base64.h
+++ b/include/openssl/base64.h
@@ -111,6 +111,19 @@ OPENSSL_EXPORT int EVP_EncodedLength(size_t *out_len, size_t len);
/* Decoding */
+/* EVP_DecodedLength sets |*out_len| to the maximum number of bytes
+ * that will be needed to call |EVP_DecodeBase64| on an input of
+ * length |len|. */
+OPENSSL_EXPORT int EVP_DecodedLength(size_t *out_len, size_t len);
+
+/* EVP_DecodeBase64 decodes |in_len| bytes from base64 and writes
+ * |*out_len| bytes to |out|. |max_out| is the size of the output
+ * buffer. If it is not enough for the maximum output size, the
+ * operation fails. */
+OPENSSL_EXPORT int EVP_DecodeBase64(uint8_t *out, size_t *out_len,
+ size_t max_out, const uint8_t *in,
+ size_t in_len);
+
/* EVP_DecodeInit initialises |*ctx|, which is typically stack allocated, for
* a decoding operation.
*
@@ -135,11 +148,13 @@ OPENSSL_EXPORT int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out,
OPENSSL_EXPORT int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out,
int *out_len);
-/* EVP_DecodeBlock encodes |src_len| bytes from |src| and writes the result to
- * |dst|. It returns the number of bytes written or -1 on error.
+/* Deprecated: EVP_DecodeBlock encodes |src_len| bytes from |src| and
+ * writes the result to |dst|. It returns the number of bytes written
+ * or -1 on error.
*
* WARNING: EVP_DecodeBlock's return value does not take padding into
- * account. TODO(davidben): Possible or worth it to fix or add new API? */
+ * account. It also strips leading whitespace and trailing
+ * whitespace. */
OPENSSL_EXPORT int EVP_DecodeBlock(uint8_t *dst, const uint8_t *src,
size_t src_len);
diff --git a/include/openssl/bio.h b/include/openssl/bio.h
index da0a356..547a36a 100644
--- a/include/openssl/bio.h
+++ b/include/openssl/bio.h
@@ -235,6 +235,10 @@ OPENSSL_EXPORT long BIO_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp);
/* BIO_pending returns the number of bytes pending to be read. */
OPENSSL_EXPORT size_t BIO_pending(const BIO *bio);
+/* BIO_ctrl_pending calls |BIO_pending| and exists only for compatibility with
+ * OpenSSL. */
+OPENSSL_EXPORT size_t BIO_ctrl_pending(const BIO *bio);
+
/* BIO_wpending returns the number of bytes pending to be written. */
OPENSSL_EXPORT size_t BIO_wpending(const BIO *bio);
diff --git a/include/openssl/bn.h b/include/openssl/bn.h
index c9fba98..37a4bba 100644
--- a/include/openssl/bn.h
+++ b/include/openssl/bn.h
@@ -351,11 +351,11 @@ OPENSSL_EXPORT int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
/* BN_add_word adds |w| to |a|. It returns one on success and zero otherwise. */
OPENSSL_EXPORT int BN_add_word(BIGNUM *a, BN_ULONG w);
-/* BN_sub sets |r| = |a| + |b|, where |r| must be a distinct pointer from |a|
+/* BN_sub sets |r| = |a| - |b|, where |r| must be a distinct pointer from |a|
* and |b|. It returns one on success and zero on allocation failure. */
OPENSSL_EXPORT int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
-/* BN_usub sets |r| = |a| + |b|, where |a| and |b| are non-negative integers,
+/* BN_usub sets |r| = |a| - |b|, where |a| and |b| are non-negative integers,
* |b| < |a| and |r| must be a distinct pointer from |a| and |b|. It returns
* one on success and zero on allocation failure. */
OPENSSL_EXPORT int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
diff --git a/include/openssl/bytestring.h b/include/openssl/bytestring.h
index 6c0e799..1af20e8 100644
--- a/include/openssl/bytestring.h
+++ b/include/openssl/bytestring.h
@@ -122,14 +122,13 @@ OPENSSL_EXPORT int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out);
#define CBS_ASN1_BITSTRING 0x3
#define CBS_ASN1_OCTETSTRING 0x4
#define CBS_ASN1_OBJECT 0x6
+#define CBS_ASN1_ENUMERATED 0xa
#define CBS_ASN1_SEQUENCE (0x10 | CBS_ASN1_CONSTRUCTED)
#define CBS_ASN1_SET (0x11 | CBS_ASN1_CONSTRUCTED)
#define CBS_ASN1_CONSTRUCTED 0x20
#define CBS_ASN1_CONTEXT_SPECIFIC 0x80
-#define CBS_ASN1_ANY 0x10000
-
/* CBS_get_asn1 sets |*out| to the contents of DER-encoded, ASN.1 element (not
* including tag and length bytes) and advances |cbs| over it. The ASN.1
* element must match |tag_value|. It returns one on success and zero
@@ -138,20 +137,28 @@ OPENSSL_EXPORT int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out);
* Tag numbers greater than 31 are not supported. */
OPENSSL_EXPORT int CBS_get_asn1(CBS *cbs, CBS *out, unsigned tag_value);
-/* CBS_get_asn1_ber sets |*out| to the contents of BER-encoded, ASN.1 element
- * (not including tag and length bytes) and advances |cbs| over it. The ASN.1
- * element must match |tag_value|. It returns one on success and zero on error.
- *
- * The major difference between this function and |CBS_get_asn1| is that
- * indefinite-length elements may be processed by this function.
- *
- * Tag numbers greater than 31 are not supported. */
-OPENSSL_EXPORT int CBS_get_asn1_ber(CBS *cbs, CBS *out, unsigned tag_value);
-
/* CBS_get_asn1_element acts like |CBS_get_asn1| but |out| will include the
* ASN.1 header bytes too. */
OPENSSL_EXPORT int CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned tag_value);
+/* CBS_get_any_asn1_element sets |*out| to contain the next ASN.1 element from
+ * |*cbs| (including header bytes) and advances |*cbs|. It sets |*out_tag| to
+ * the tag number and |*out_header_len| to the length of the ASN.1 header. If
+ * the element has indefinite length then |*out| will only contain the
+ * header. Each of |out|, |out_tag|, and |out_header_len| may be NULL to ignore
+ * the value.
+ *
+ * Tag numbers greater than 31 are not supported. */
+OPENSSL_EXPORT int CBS_get_any_asn1_element(CBS *cbs, CBS *out,
+ unsigned *out_tag,
+ size_t *out_header_len);
+
+/* CBS_get_asn1_uint64 gets an ASN.1 INTEGER from |cbs| using |CBS_get_asn1|
+ * and sets |*out| to its value. It returns one on success and zero on error,
+ * where error includes the integer being negative, or too large to represent
+ * in 64 bits. */
+OPENSSL_EXPORT int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out);
+
/* CRYPTO ByteBuilder.
*
diff --git a/include/openssl/cipher.h b/include/openssl/cipher.h
index 92cec76..4eae33b 100644
--- a/include/openssl/cipher.h
+++ b/include/openssl/cipher.h
@@ -91,6 +91,12 @@ OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_256_gcm(void);
* ciphertext. */
OPENSSL_EXPORT const EVP_CIPHER *EVP_enc_null(void);
+/* EVP_rc2_40_cbc returns a cipher that implements 40-bit RC2 in CBC mode. This
+ * is obviously very, very weak and is included only in order to read PKCS#12
+ * files, which often encrypt the certificate chain using this cipher. It is
+ * deliberately not exported. */
+const EVP_CIPHER *EVP_rc2_40_cbc(void);
+
/* EVP_get_cipherbynid returns the cipher corresponding to the given NID, or
* NULL if no such cipher is known. */
OPENSSL_EXPORT const EVP_CIPHER *EVP_get_cipherbynid(int nid);
@@ -255,6 +261,11 @@ OPENSSL_EXPORT int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int command,
* to disable. */
OPENSSL_EXPORT int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad);
+/* EVP_CIPHER_CTX_set_key_length sets the key length for |ctx|. This is only
+ * valid for ciphers that can take a variable length key. It returns one on
+ * success and zero on error. */
+OPENSSL_EXPORT int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *ctx, unsigned key_len);
+
/* Cipher accessors. */
@@ -461,6 +472,7 @@ typedef struct evp_cipher_info_st {
#define CIPHER_F_aead_aes_key_wrap_seal 119
#define CIPHER_F_aead_aes_key_wrap_init 120
#define CIPHER_F_aead_aes_key_wrap_open 121
+#define CIPHER_F_EVP_CIPHER_CTX_set_key_length 122
#define CIPHER_R_WRAP_MODE_NOT_ALLOWED 100
#define CIPHER_R_AES_KEY_SETUP_FAILED 101
#define CIPHER_R_INPUT_NOT_INITIALIZED 102
@@ -484,5 +496,6 @@ typedef struct evp_cipher_info_st {
#define CIPHER_R_UNSUPPORTED_INPUT_SIZE 120
#define CIPHER_R_UNSUPPORTED_AD_SIZE 121
#define CIPHER_R_UNSUPPORTED_NONCE_SIZE 122
+#define CIPHER_R_INVALID_KEY_LENGTH 123
#endif /* OPENSSL_HEADER_CIPHER_H */
diff --git a/include/openssl/conf.h b/include/openssl/conf.h
index 51c5525..c67e023 100644
--- a/include/openssl/conf.h
+++ b/include/openssl/conf.h
@@ -91,7 +91,7 @@ struct conf_st {
/* NCONF_new returns a fresh, empty |CONF|, or NULL on error. */
-CONF *NCONF_new();
+CONF *NCONF_new(void);
/* NCONF_free frees all the data owned by |conf| and then |conf| itself. */
void NCONF_free(CONF *conf);
diff --git a/include/openssl/cpu.h b/include/openssl/cpu.h
index 3cc1e5e..5f60754 100644
--- a/include/openssl/cpu.h
+++ b/include/openssl/cpu.h
@@ -90,7 +90,7 @@ extern uint32_t OPENSSL_ia32cap_P[4];
/* CRYPTO_is_NEON_capable returns true if the current CPU has a NEON unit. Note
* that |OPENSSL_armcap_P| also exists and contains the same information in a
* form that's easier for assembly to use. */
-OPENSSL_EXPORT char CRYPTO_is_NEON_capable();
+OPENSSL_EXPORT char CRYPTO_is_NEON_capable(void);
/* CRYPTO_set_NEON_capable sets the return value of |CRYPTO_is_NEON_capable|.
* By default, unless the code was compiled with |-mfpu=neon|, NEON is assumed
@@ -101,7 +101,7 @@ OPENSSL_EXPORT void CRYPTO_set_NEON_capable(char neon_capable);
/* CRYPTO_is_NEON_functional returns true if the current CPU has a /working/
* NEON unit. Some phones have a NEON unit, but the Poly1305 NEON code causes
* it to fail. See https://code.google.com/p/chromium/issues/detail?id=341598 */
-OPENSSL_EXPORT char CRYPTO_is_NEON_functional();
+OPENSSL_EXPORT char CRYPTO_is_NEON_functional(void);
/* CRYPTO_set_NEON_functional sets the "NEON functional" flag. For
* |CRYPTO_is_NEON_functional| to return true, both this flag and the NEON flag
diff --git a/include/openssl/crypto.h b/include/openssl/crypto.h
index ddb97be..112431e 100644
--- a/include/openssl/crypto.h
+++ b/include/openssl/crypto.h
@@ -12,12 +12,34 @@
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
-/* This header is provided in order to make compiling against code that expects
- OpenSSL easier. */
+#ifndef OPENSSL_HEADER_CRYPTO_H
+#define OPENSSL_HEADER_CRYPTO_H
+
+#include <openssl/base.h>
+
+#include <openssl/mem.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* crypto.h contains functions for initializing the crypto library. */
+
+
+/* CRYPTO_library_init initializes the crypto library. It must be called if the
+ * library is built with BORINGSSL_NO_STATIC_INITIALIZER. Otherwise, it does
+ * nothing and a static initializer is used instead. */
+OPENSSL_EXPORT void CRYPTO_library_init(void);
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
#define CRYPTO_F_CRYPTO_set_ex_data 100
#define CRYPTO_F_get_class 101
#define CRYPTO_F_get_new_index 102
#define CRYPTO_F_get_func_pointers 103
-#include "mem.h"
+#endif /* OPENSSL_HEADER_CRYPTO_H */
diff --git a/include/openssl/digest.h b/include/openssl/digest.h
index 76d6677..6d8a165 100644
--- a/include/openssl/digest.h
+++ b/include/openssl/digest.h
@@ -76,6 +76,7 @@ extern "C" {
* The following functions return |EVP_MD| objects that implement the named hash
* function. */
+OPENSSL_EXPORT const EVP_MD *EVP_md4(void);
OPENSSL_EXPORT const EVP_MD *EVP_md5(void);
OPENSSL_EXPORT const EVP_MD *EVP_sha1(void);
OPENSSL_EXPORT const EVP_MD *EVP_sha224(void);
@@ -199,6 +200,10 @@ OPENSSL_EXPORT size_t EVP_MD_block_size(const EVP_MD *md);
* |in|. It returns one on success and zero on error. */
OPENSSL_EXPORT int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in);
+/* EVP_add_digest does nothing and returns one. It exists only for
+ * compatibility with OpenSSL. */
+OPENSSL_EXPORT int EVP_add_digest(const EVP_MD *digest);
+
/* Digest operation accessors. */
diff --git a/include/openssl/dsa.h b/include/openssl/dsa.h
index c8156fa..5e71ae2 100644
--- a/include/openssl/dsa.h
+++ b/include/openssl/dsa.h
@@ -291,6 +291,14 @@ OPENSSL_EXPORT int DSA_sign_setup(const DSA *dsa, BN_CTX *ctx,
BIGNUM **out_kinv, BIGNUM **out_r);
+/* Conversion. */
+
+/* DSA_dup_DH returns a |DH| constructed from the parameters of |dsa|. This is
+ * sometimes needed when Diffie-Hellman parameters are stored in the form of
+ * DSA parameters. It returns an allocated |DH| on success or NULL on error. */
+OPENSSL_EXPORT DH *DSA_dup_DH(const DSA *dsa);
+
+
/* ex_data functions.
*
* These functions are wrappers. See |ex_data.h| for details. */
diff --git a/include/openssl/ec.h b/include/openssl/ec.h
index 55f1adf..47ecfca 100644
--- a/include/openssl/ec.h
+++ b/include/openssl/ec.h
@@ -133,6 +133,15 @@ OPENSSL_EXPORT int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order,
OPENSSL_EXPORT int EC_GROUP_get_cofactor(const EC_GROUP *group,
BIGNUM *cofactor, BN_CTX *ctx);
+/* EC_GROUP_get_curve_GFp gets various parameters about a group. It sets
+ * |*out_p| to the order of the coordinate field and |*out_a| and |*out_b| to
+ * the parameters of the curve when expressed as y² = x³ + ax + b. Any of the
+ * output parameters can be NULL. It returns one on success and zero on
+ * error. */
+OPENSSL_EXPORT int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *out_p,
+ BIGNUM *out_a, BIGNUM *out_b,
+ BN_CTX *ctx);
+
/* EC_GROUP_get_curve_name returns a NID that identifies |group|. */
OPENSSL_EXPORT int EC_GROUP_get_curve_name(const EC_GROUP *group);
@@ -351,6 +360,7 @@ OPENSSL_EXPORT int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r,
#define EC_F_EC_KEY_generate_key 155
#define EC_F_ec_GFp_simple_set_compressed_coordinates 156
#define EC_F_EC_POINT_add 157
+#define EC_F_EC_GROUP_get_curve_GFp 158
#define EC_R_PKPARAMETERS2GROUP_FAILURE 100
#define EC_R_NON_NAMED_CURVE 101
#define EC_R_COORDINATES_OUT_OF_RANGE 102
diff --git a/include/openssl/engine.h b/include/openssl/engine.h
index f2916b3..367e98e 100644
--- a/include/openssl/engine.h
+++ b/include/openssl/engine.h
@@ -37,7 +37,7 @@ extern "C" {
/* ENGINE_new returns an empty ENGINE that uses the default method for all
* algorithms. */
-OPENSSL_EXPORT ENGINE *ENGINE_new();
+OPENSSL_EXPORT ENGINE *ENGINE_new(void);
/* ENGINE_free decrements the reference counts for all methods linked from
* |engine| and frees |engine| itself. */
diff --git a/include/openssl/err.h b/include/openssl/err.h
index d8e7cd5..67a2601 100644
--- a/include/openssl/err.h
+++ b/include/openssl/err.h
@@ -146,11 +146,11 @@ extern "C" {
* values. If this is not called then the string forms of errors produced by
* the functions below will contain numeric identifiers rather than
* human-readable strings. */
-OPENSSL_EXPORT void ERR_load_crypto_strings();
+OPENSSL_EXPORT void ERR_load_crypto_strings(void);
/* ERR_free_strings frees any internal error values that have been loaded. This
* should only be called at process shutdown. */
-OPENSSL_EXPORT void ERR_free_strings();
+OPENSSL_EXPORT void ERR_free_strings(void);
/* Reading and formatting errors. */
@@ -266,7 +266,7 @@ OPENSSL_EXPORT void ERR_remove_thread_state(const CRYPTO_THREADID *tid);
/* ERR_get_next_error_library returns a value suitable for passing as the
* |library| argument to |ERR_put_error|. This is intended for code that wishes
* to push its own, non-standard errors to the error queue. */
-OPENSSL_EXPORT int ERR_get_next_error_library();
+OPENSSL_EXPORT int ERR_get_next_error_library(void);
/* Private functions. */
@@ -515,7 +515,7 @@ struct ERR_FNS_st {
/* ERR_load_BIO_strings does nothing.
*
* TODO(fork): remove. libjingle calls this. */
-OPENSSL_EXPORT void ERR_load_BIO_strings();
+OPENSSL_EXPORT void ERR_load_BIO_strings(void);
#if defined(__cplusplus)
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index edeb850..091912f 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -83,7 +83,7 @@ extern "C" {
/* EVP_PKEY_new creates a new, empty public-key object and returns it or NULL
* on allocation failure. */
-OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_new();
+OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_new(void);
/* EVP_PKEY_free frees all data referenced by |pkey| and then frees |pkey|
* itself. */
@@ -708,10 +708,10 @@ OPENSSL_EXPORT int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx,
/* Private functions */
/* OpenSSL_add_all_algorithms does nothing. */
-OPENSSL_EXPORT void OpenSSL_add_all_algorithms();
+OPENSSL_EXPORT void OpenSSL_add_all_algorithms(void);
/* EVP_cleanup does nothing. */
-OPENSSL_EXPORT void EVP_cleanup();
+OPENSSL_EXPORT void EVP_cleanup(void);
/* EVP_PKEY_asn1_find returns the ASN.1 method table for the given |nid|, which
* should be one of the |EVP_PKEY_*| values. It returns NULL if |nid| is
diff --git a/include/openssl/md4.h b/include/openssl/md4.h
new file mode 100644
index 0000000..715adab
--- /dev/null
+++ b/include/openssl/md4.h
@@ -0,0 +1,105 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#ifndef OPENSSL_HEADER_MD4_H
+#define OPENSSL_HEADER_MD4_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* MD4. */
+
+/* MD4_CBLOCK is the block size of MD4. */
+#define MD4_CBLOCK 64
+
+/* MD4_DIGEST_LENGTH is the length of an MD4 digest. */
+#define MD4_DIGEST_LENGTH 16
+
+/* MD41_Init initialises |md4| and returns one. */
+OPENSSL_EXPORT int MD4_Init(MD4_CTX *md4);
+
+/* MD4_Update adds |len| bytes from |data| to |md4| and returns one. */
+OPENSSL_EXPORT int MD4_Update(MD4_CTX *md4, const void *data, size_t len);
+
+/* MD4_Final adds the final padding to |md4| and writes the resulting digest to
+ * |md|, which must have at least |MD4_DIGEST_LENGTH| bytes of space. It
+ * returns one. */
+OPENSSL_EXPORT int MD4_Final(uint8_t *md, MD4_CTX *md4);
+
+/* MD4 writes the digest of |len| bytes from |data| to |out| and returns |out|.
+ * There must be at least |MD4_DIGEST_LENGTH| bytes of space in |out|. */
+OPENSSL_EXPORT uint8_t *MD4(const uint8_t *data, size_t len, uint8_t *out);
+
+/* MD4_Transform is a low-level function that performs a single, MD4 block
+ * transformation using the state from |md4| and 64 bytes from |block|. */
+OPENSSL_EXPORT void MD4_Transform(MD4_CTX *md4, const uint8_t *block);
+
+struct md4_state_st {
+ uint32_t A, B, C, D;
+ uint32_t Nl, Nh;
+ uint32_t data[16];
+ unsigned int num;
+};
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_MD4_H */
diff --git a/include/openssl/md5.h b/include/openssl/md5.h
index dc800c0..efedc98 100644
--- a/include/openssl/md5.h
+++ b/include/openssl/md5.h
@@ -72,7 +72,7 @@ extern "C" {
/* MD5_DIGEST_LENGTH is the length of an MD5 digest. */
#define MD5_DIGEST_LENGTH 16
-/* MD51_Init initialises |md5| and returns 1. */
+/* MD51_Init initialises |md5| and returns one. */
OPENSSL_EXPORT int MD5_Init(MD5_CTX *md5);
/* MD5_Update adds |len| bytes from |data| to |md5| and returns one. */
diff --git a/include/openssl/opensslfeatures.h b/include/openssl/opensslfeatures.h
index 6026a4b..4f5cb31 100644
--- a/include/openssl/opensslfeatures.h
+++ b/include/openssl/opensslfeatures.h
@@ -37,7 +37,6 @@
#define OPENSSL_NO_JPAKE
#define OPENSSL_NO_KRB5
#define OPENSSL_NO_MD2
-#define OPENSSL_NO_MD4
#define OPENSSL_NO_MDC2
#define OPENSSL_NO_OCSP
#define OPENSSL_NO_RC2
diff --git a/include/openssl/pem.h b/include/openssl/pem.h
index 3eaac0a..c18cedd 100644
--- a/include/openssl/pem.h
+++ b/include/openssl/pem.h
@@ -465,18 +465,14 @@ DECLARE_PEM_rw_const(DSAparams, DSA)
#endif
-#ifndef OPENSSL_NO_EC
DECLARE_PEM_rw_const(ECPKParameters, EC_GROUP)
DECLARE_PEM_rw_cb(ECPrivateKey, EC_KEY)
DECLARE_PEM_rw(EC_PUBKEY, EC_KEY)
-#endif
-#ifndef OPENSSL_NO_DH
DECLARE_PEM_rw_const(DHparams, DH)
DECLARE_PEM_write_const(DHxparams, DH)
-#endif
DECLARE_PEM_rw_cb(PrivateKey, EVP_PKEY)
@@ -506,10 +502,8 @@ OPENSSL_EXPORT EVP_PKEY *b2i_PrivateKey_bio(BIO *in);
OPENSSL_EXPORT EVP_PKEY *b2i_PublicKey_bio(BIO *in);
OPENSSL_EXPORT int i2b_PrivateKey_bio(BIO *out, EVP_PKEY *pk);
OPENSSL_EXPORT int i2b_PublicKey_bio(BIO *out, EVP_PKEY *pk);
-#ifndef OPENSSL_NO_RC4
OPENSSL_EXPORT EVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u);
OPENSSL_EXPORT int i2b_PVK_bio(BIO *out, EVP_PKEY *pk, int enclevel, pem_password_cb *cb, void *u);
-#endif
void ERR_load_PEM_strings(void);
diff --git a/include/openssl/pkcs8.h b/include/openssl/pkcs8.h
index d871e57..8735387 100644
--- a/include/openssl/pkcs8.h
+++ b/include/openssl/pkcs8.h
@@ -59,6 +59,8 @@
#include <openssl/base.h>
+#include <stdio.h>
+
#include <openssl/x509.h>
#if defined(__cplusplus)
@@ -67,11 +69,12 @@ extern "C" {
/* PKCS8_encrypt_pbe serializes and encrypts a PKCS8_PRIV_KEY_INFO with PBES1 as
- * defined in PKCS #5. Only pbeWithSHAAnd128BitRC4 and
- * pbeWithSHAAnd3-KeyTripleDES-CBC, defined in PKCS #12, are supported. The
- * |pass_raw_len| bytes pointed to by |pass_raw| are used as the password. Note
- * that any conversions from the password as supplied in a text string (such as
- * those specified in B.1 of PKCS #12) must be performed by the caller.
+ * defined in PKCS #5. Only pbeWithSHAAnd128BitRC4,
+ * pbeWithSHAAnd3-KeyTripleDES-CBC and pbeWithSHA1And40BitRC2, defined in PKCS
+ * #12, are supported. The |pass_raw_len| bytes pointed to by |pass_raw| are
+ * used as the password. Note that any conversions from the password as
+ * supplied in a text string (such as those specified in B.1 of PKCS #12) must
+ * be performed by the caller.
*
* If |salt| is NULL, a random salt of |salt_len| bytes is generated. If
* |salt_len| is zero, a default salt length is used instead.
@@ -89,11 +92,12 @@ OPENSSL_EXPORT X509_SIG *PKCS8_encrypt_pbe(int pbe_nid,
PKCS8_PRIV_KEY_INFO *p8inf);
/* PKCS8_decrypt_pbe decrypts and decodes a PKCS8_PRIV_KEY_INFO with PBES1 as
- * defined in PKCS #5. Only pbeWithSHAAnd128BitRC4 and
- * pbeWithSHAAnd3-KeyTripleDES-CBC, defined in PKCS #12, are supported. The
- * |pass_raw_len| bytes pointed to by |pass_raw| are used as the password. Note
- * that any conversions from the password as supplied in a text string (such as
- * those specified in B.1 of PKCS #12) must be performed by the caller.
+ * defined in PKCS #5. Only pbeWithSHAAnd128BitRC4,
+ * pbeWithSHAAnd3-KeyTripleDES-CBC and pbeWithSHA1And40BitRC2, defined in PKCS
+ * #12, are supported. The |pass_raw_len| bytes pointed to by |pass_raw| are
+ * used as the password. Note that any conversions from the password as
+ * supplied in a text string (such as those specified in B.1 of PKCS #12) must
+ * be performed by the caller.
*
* The resulting structure must be freed by the caller. */
OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *PKCS8_decrypt_pbe(X509_SIG *pkcs8,
@@ -119,6 +123,50 @@ OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(X509_SIG *pkcs8,
const char *pass,
int pass_len);
+/* PKCS12_get_key_and_certs parses a PKCS#12 structure from |in|, authenticates
+ * and decrypts it using |password|, sets |*out_key| to the included private
+ * key and appends the included certificates to |out_certs|. It returns one on
+ * success and zero on error. The caller takes ownership of the outputs. */
+OPENSSL_EXPORT int PKCS12_get_key_and_certs(EVP_PKEY **out_key,
+ STACK_OF(X509) *out_certs,
+ CBS *in, const char *password);
+
+
+/* Deprecated functions. */
+
+/* PKCS12_PBE_add does nothing. It exists for compatibility with OpenSSL. */
+OPENSSL_EXPORT void PKCS12_PBE_add();
+
+/* d2i_PKCS12 is a dummy function that copies |*ber_bytes| into a
+ * |PKCS12| structure. The |out_p12| argument must be NULL. On exit,
+ * |*ber_bytes| will be advanced by |ber_len|. It returns a fresh |PKCS12|
+ * structure or NULL on error.
+ *
+ * Note: unlike other d2i functions, |d2i_PKCS12| will always consume |ber_len|
+ * bytes.*/
+OPENSSL_EXPORT PKCS12 *d2i_PKCS12(PKCS12 **out_p12, const uint8_t **ber_bytes,
+ size_t ber_len);
+
+/* d2i_PKCS12_bio acts like |d2i_PKCS12| but reads from a |BIO|. */
+OPENSSL_EXPORT PKCS12* d2i_PKCS12_bio(BIO *bio, PKCS12 **out_p12);
+
+/* d2i_PKCS12_fp acts like |d2i_PKCS12| but reads from a |FILE|. */
+OPENSSL_EXPORT PKCS12* d2i_PKCS12_fp(FILE *fp, PKCS12 **out_p12);
+
+/* PKCS12_parse calls |PKCS12_get_key_and_certs| on the ASN.1 data stored in
+ * |p12|. The |out_pkey| and |out_cert| arguments must not be NULL and, on
+ * successful exit, the private key and first certificate will be stored in
+ * them. The |out_ca_certs| argument may be NULL but, if not, then any extra
+ * certificates will be appended to |*out_ca_certs|. If |*out_ca_certs| is NULL
+ * then it will be set to a freshly allocated stack containing the extra certs.
+ *
+ * It returns one on success and zero on error. */
+OPENSSL_EXPORT int PKCS12_parse(const PKCS12 *p12, const char *password,
+ EVP_PKEY **out_pkey, X509 **out_cert,
+ STACK_OF(X509) **out_ca_certs);
+
+/* PKCS12_free frees |p12| and its contents. */
+OPENSSL_EXPORT void PKCS12_free(PKCS12 *p12);
#if defined(__cplusplus)
} /* extern C */
@@ -141,6 +189,10 @@ OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(X509_SIG *pkcs8,
#define PKCS8_F_pkcs12_key_gen_raw 114
#define PKCS8_F_PKCS8_decrypt 115
#define PKCS8_F_PKCS8_encrypt_pbe 116
+#define PKCS8_F_PKCS12_parse 117
+#define PKCS8_F_PKCS12_handle_content_info 118
+#define PKCS8_F_PKCS12_handle_content_infos 119
+#define PKCS8_F_PKCS12_get_key_and_certs 120
#define PKCS8_R_ERROR_SETTING_CIPHER_PARAMS 100
#define PKCS8_R_PRIVATE_KEY_ENCODE_ERROR 101
#define PKCS8_R_UNKNOWN_ALGORITHM 102
@@ -158,5 +210,14 @@ OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(X509_SIG *pkcs8,
#define PKCS8_R_METHOD_NOT_SUPPORTED 114
#define PKCS8_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER 115
#define PKCS8_R_KEY_GEN_ERROR 116
+#define PKCS8_R_BAD_PKCS12_DATA 117
+#define PKCS8_R_PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED 118
+#define PKCS8_R_BAD_PKCS12_VERSION 119
+#define PKCS8_R_PKCS12_TOO_DEEPLY_NESTED 120
+#define PKCS8_R_MULTIPLE_PRIVATE_KEYS_IN_PKCS12 121
+#define PKCS8_R_UNKNOWN_HASH 122
+#define PKCS8_R_BAD_MAC 123
+#define PKCS8_R_MISSING_MAC 124
+#define PKCS8_R_INCORRECT_PASSWORD 125
#endif /* OPENSSL_HEADER_PKCS8_H */
diff --git a/include/openssl/pqueue.h b/include/openssl/pqueue.h
index 8ad023a..ceb1fa2 100644
--- a/include/openssl/pqueue.h
+++ b/include/openssl/pqueue.h
@@ -84,11 +84,11 @@ typedef struct _pitem *piterator;
/* pqueue_new allocates a fresh, empty priority queue object and returns it, or
* NULL on error. */
-pqueue pqueue_new();
+OPENSSL_EXPORT pqueue pqueue_new(void);
/* pqueue_free frees |pq| but not any of the items it points to. Thus |pq| must
* be empty or a memory leak will occur. */
-void pqueue_free(pqueue pq);
+OPENSSL_EXPORT void pqueue_free(pqueue pq);
/* Creating and freeing items. */
@@ -97,47 +97,46 @@ void pqueue_free(pqueue pq);
* has a priority given by |prio64be|, which is a 64-bit, unsigned number
* expressed in big-endian form. It returns the fresh item, or NULL on
* error. */
-pitem *pitem_new(uint8_t prio64be[8], void *data);
+OPENSSL_EXPORT pitem *pitem_new(uint8_t prio64be[8], void *data);
/* pitem_free frees |item|, but not any data that it points to. */
-void pitem_free(pitem *item);
+OPENSSL_EXPORT void pitem_free(pitem *item);
/* Queue accessor functions */
/* pqueue_peek returns the item with the smallest priority from |pq|, or NULL
* if empty. */
-pitem *pqueue_peek(pqueue pq);
+OPENSSL_EXPORT pitem *pqueue_peek(pqueue pq);
/* pqueue_find returns the item whose priority matches |prio64be| or NULL if no
* such item exists. */
-pitem *pqueue_find(pqueue pq, unsigned char *prio64be);
+OPENSSL_EXPORT pitem *pqueue_find(pqueue pq, uint8_t *prio64be);
/* Queue mutation functions */
/* pqueue_insert inserts |item| into |pq| and returns item. */
-pitem *pqueue_insert(pqueue pq, pitem *item);
+OPENSSL_EXPORT pitem *pqueue_insert(pqueue pq, pitem *item);
/* pqueue_pop takes the item with the least priority from |pq| and returns it,
* or NULL if |pq| is empty. */
-pitem *pqueue_pop(pqueue pq);
+OPENSSL_EXPORT pitem *pqueue_pop(pqueue pq);
/* pqueue_size returns the number of items in |pq|. */
-size_t pqueue_size(pqueue pq);
+OPENSSL_EXPORT size_t pqueue_size(pqueue pq);
/* Iterating */
/* pqueue_iterator returns an iterator that can be used to iterate over the
* contents of the queue. */
-pitem *pqueue_iterator(pqueue pq);
+OPENSSL_EXPORT piterator pqueue_iterator(pqueue pq);
/* pqueue_next returns the current value of |iter| and advances it to the next
* position. If the iterator has advanced over all the elements, it returns
* NULL. */
-pitem *pqueue_next(piterator *iter);
-
+OPENSSL_EXPORT pitem *pqueue_next(piterator *iter);
#if defined(__cplusplus)
diff --git a/include/openssl/rand.h b/include/openssl/rand.h
index d17c3ea..5a84a89 100644
--- a/include/openssl/rand.h
+++ b/include/openssl/rand.h
@@ -28,7 +28,7 @@ OPENSSL_EXPORT int RAND_bytes(uint8_t *buf, size_t len);
/* RAND_cleanup frees any resources used by the RNG. This is not safe if other
* threads might still be calling |RAND_bytes|. */
-OPENSSL_EXPORT void RAND_cleanup();
+OPENSSL_EXPORT void RAND_cleanup(void);
/* Deprecated functions */
diff --git a/include/openssl/srtp.h b/include/openssl/srtp.h
index 3e29e5d..c11608e 100644
--- a/include/openssl/srtp.h
+++ b/include/openssl/srtp.h
@@ -130,9 +130,23 @@ extern "C" {
#define SRTP_NULL_SHA1_80 0x0005
#define SRTP_NULL_SHA1_32 0x0006
+/* SSL_CTX_set_tlsext_use_srtp enables SRTP for all SSL objects
+ * created from |ctx|. |profile| contains a colon-separated list of
+ * profile names. It returns zero on success and one on failure.
+ *
+ * WARNING: this function is dangerous because it breaks the usual
+ * return value convention. */
OPENSSL_EXPORT int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx,
const char *profiles);
+
+/* SSL_set_tlsext_use_srtp enables SRTP for |ssl| with a profile list.
+ * |profile| contains a colon-separated list of profile names. It
+ * returns zero on success and one on failure.
+ *
+ * WARNING: this function is dangerous because it breaks the usual
+ * return value convention. */
OPENSSL_EXPORT int SSL_set_tlsext_use_srtp(SSL *ctx, const char *profiles);
+
OPENSSL_EXPORT SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile(SSL *s);
OPENSSL_EXPORT STACK_OF(SRTP_PROTECTION_PROFILE) *
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 3c64237..48ad549 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -342,7 +342,7 @@ struct ssl_method_st
int (*ssl_renegotiate)(SSL *s);
int (*ssl_renegotiate_check)(SSL *s);
long (*ssl_get_message)(SSL *s, int st1, int stn, int mt, long
- max, int *ok);
+ max, int hash_message, int *ok);
int (*ssl_read_bytes)(SSL *s, int type, unsigned char *buf, int len,
int peek);
int (*ssl_write_bytes)(SSL *s, int type, const void *buf_, int len);
@@ -380,6 +380,9 @@ struct ssl_method_st
* Compression_meth [11] EXPLICIT OCTET STRING, -- optional compression method
* SRP_username [ 12 ] EXPLICIT OCTET STRING -- optional SRP username
* Peer SHA256 [13] EXPLICIT OCTET STRING, -- optional SHA256 hash of Peer certifiate
+ * original handshake hash [14] EXPLICIT OCTET STRING, -- optional original handshake hash
+ * tlsext_signed_cert_timestamp_list [15] EXPLICIT OCTET STRING, -- optional signed cert timestamp list extension
+ * ocsp_response [16] EXPLICIT OCTET STRING, -- optional saved OCSP response from the server
* }
* Look in ssl/ssl_asn1.c for more details
* I'm using EXPLICIT tags so I can read the damn things using asn1parse :-).
@@ -439,16 +442,22 @@ struct ssl_session_st
* efficient and to implement a maximum cache size. */
struct ssl_session_st *prev,*next;
char *tlsext_hostname;
-#ifndef OPENSSL_NO_EC
size_t tlsext_ecpointformatlist_length;
unsigned char *tlsext_ecpointformatlist; /* peer's list */
size_t tlsext_ellipticcurvelist_length;
uint16_t *tlsext_ellipticcurvelist; /* peer's list */
-#endif /* OPENSSL_NO_EC */
/* RFC4507 info */
uint8_t *tlsext_tick; /* Session ticket */
size_t tlsext_ticklen; /* Session ticket length */
uint32_t tlsext_tick_lifetime_hint; /* Session lifetime hint in seconds */
+
+ size_t tlsext_signed_cert_timestamp_list_length;
+ uint8_t *tlsext_signed_cert_timestamp_list; /* Server's list. */
+
+ /* The OCSP response that came with the session. */
+ size_t ocsp_response_length;
+ uint8_t *ocsp_response;
+
char peer_sha256_valid; /* Non-zero if peer_sha256 is valid */
unsigned char peer_sha256[SHA256_DIGEST_LENGTH]; /* SHA256 of peer certificate */
@@ -462,33 +471,21 @@ struct ssl_session_st
#endif
-#define SSL_OP_MICROSOFT_SESS_ID_BUG 0x00000001L
-#define SSL_OP_NETSCAPE_CHALLENGE_BUG 0x00000002L
-/* Allow initial connection to servers that don't support RI */
+/* SSL_OP_LEGACY_SERVER_CONNECT allows initial connection to servers
+ * that don't support RI */
#define SSL_OP_LEGACY_SERVER_CONNECT 0x00000004L
-#define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0x00000010L
-#define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 0x00000020L
-#define SSL_OP_SAFARI_ECDHE_ECDSA_BUG 0x00000040L
-#define SSL_OP_TLS_D5_BUG 0x00000100L
-#define SSL_OP_TLS_BLOCK_PADDING_BUG 0x00000200L
-/* Hasn't done anything since OpenSSL 0.9.7h, retained for compatibility */
-#define SSL_OP_MSIE_SSLV2_RSA_PADDING 0x0
+/* SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER allows for record sizes
+ * SSL3_RT_MAX_EXTRA bytes above the maximum record size. */
+#define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 0x00000020L
-/* SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS is vestigial. Previously it disabled the
- * insertion of empty records in CBC mode, but the empty records were commonly
- * misinterpreted as EOF by other TLS stacks and so this was disabled by
- * SSL_OP_ALL.
- *
- * This has been replaced by 1/n-1 record splitting, which is enabled by
- * SSL_MODE_CBC_RECORD_SPLITTING in SSL_set_mode. This involves sending a
- * one-byte record rather than an empty record and has much better
- * compatibility. */
-#define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 0x00000800L /* added in 0.9.6e */
+/* SSL_OP_TLS_D5_BUG accepts an RSAClientKeyExchange in TLS encoded as
+ * SSL3, without a length prefix. */
+#define SSL_OP_TLS_D5_BUG 0x00000100L
-/* SSL_OP_ALL: various bug workarounds that should be rather harmless.
- * This used to be 0x000FFFFFL before 0.9.7. */
-#define SSL_OP_ALL 0x80000BFFL
+/* SSL_OP_ALL enables the above bug workarounds that should be rather
+ * harmless. */
+#define SSL_OP_ALL 0x00000BFFL
/* DTLS options */
#define SSL_OP_NO_QUERY_MTU 0x00001000L
@@ -525,13 +522,13 @@ struct ssl_session_st
#define SSL_OP_NO_SSL_MASK (SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|\
SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2)
-/* These next two were never actually used for anything since SSLeay
- * zap so we have some more flags.
- */
-/* The next flag deliberately changes the ciphertest, this is a check
- * for the PKCS#1 attack */
-#define SSL_OP_PKCS1_CHECK_1 0x0
-#define SSL_OP_PKCS1_CHECK_2 0x0
+/* The following flags do nothing and are included only to make it easier to
+ * compile code with BoringSSL. */
+#define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 0
+#define SSL_OP_MICROSOFT_SESS_ID_BUG 0
+#define SSL_OP_NETSCAPE_CHALLENGE_BUG 0
+#define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0
+#define SSL_OP_TLS_BLOCK_PADDING_BUG 0
/* Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success
* when just a single record has been written): */
@@ -680,6 +677,14 @@ OPENSSL_EXPORT void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int v
#define SSL_CTX_set_msg_callback_arg(ctx, arg) SSL_CTX_ctrl((ctx), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
#define SSL_set_msg_callback_arg(ssl, arg) SSL_ctrl((ssl), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
+/* SSL_CTX_set_keylog_bio sets configures all SSL objects attached to |ctx| to
+ * log session material to |keylog_bio|. This is intended for debugging use with
+ * tools like Wireshark. |ctx| takes ownership of |keylog_bio|.
+ *
+ * The format is described in
+ * https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format. */
+OPENSSL_EXPORT void SSL_CTX_set_keylog_bio(SSL_CTX *ctx, BIO *keylog_bio);
+
struct ssl_aead_ctx_st;
typedef struct ssl_aead_ctx_st SSL_AEAD_CTX;
@@ -778,7 +783,7 @@ DECLARE_LHASH_OF(SSL_SESSION);
struct ssl_cipher_preference_list_st
{
STACK_OF(SSL_CIPHER) *ciphers;
- unsigned char *in_group_flags;
+ uint8_t *in_group_flags;
};
struct ssl_ctx_st
@@ -960,7 +965,6 @@ struct ssl_ctx_st
* memory and session space. Only effective on the server side. */
char retain_only_sha256_of_client_certs;
-# ifndef OPENSSL_NO_NEXTPROTONEG
/* Next protocol negotiation information */
/* (for experimental NPN extension). */
@@ -977,7 +981,6 @@ struct ssl_ctx_st
unsigned int inlen,
void *arg);
void *next_proto_select_cb_arg;
-# endif
/* ALPN information
* (we are in the process of transitioning from NPN to ALPN.) */
@@ -1005,13 +1008,11 @@ struct ssl_ctx_st
/* SRTP profiles we are willing to do from RFC 5764 */
STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles;
-# ifndef OPENSSL_NO_EC
/* EC extension values inherited by SSL structure */
size_t tlsext_ecpointformatlist_length;
uint8_t *tlsext_ecpointformatlist;
size_t tlsext_ellipticcurvelist_length;
uint16_t *tlsext_ellipticcurvelist;
-# endif /* OPENSSL_NO_EC */
/* If true, a client will advertise the Channel ID extension and a
* server will echo it. */
@@ -1023,6 +1024,16 @@ struct ssl_ctx_st
/* The client's Channel ID private key. */
EVP_PKEY *tlsext_channel_id_private;
+ /* If true, a client will request certificate timestamps. */
+ char signed_cert_timestamps_enabled;
+
+ /* If true, a client will request a stapled OCSP response. */
+ char ocsp_stapling_enabled;
+
+ /* If not NULL, session key material will be logged to this BIO for
+ * debugging purposes. The format matches NSS's and is readable by
+ * Wireshark. */
+ BIO *keylog_bio;
};
#endif
@@ -1087,7 +1098,44 @@ OPENSSL_EXPORT void SSL_CTX_set_channel_id_cb(SSL_CTX *ctx, void (*channel_id_cb
OPENSSL_EXPORT void (*SSL_CTX_get_channel_id_cb(SSL_CTX *ctx))(SSL *ssl, EVP_PKEY **pkey);
OPENSSL_EXPORT void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx, int (*app_gen_cookie_cb)(SSL *ssl, uint8_t *cookie, size_t *cookie_len));
OPENSSL_EXPORT void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx, int (*app_verify_cookie_cb)(SSL *ssl, const uint8_t *cookie, size_t cookie_len));
-#ifndef OPENSSL_NO_NEXTPROTONEG
+
+
+/* SSL_enable_signed_cert_timestamps causes |ssl| (which must be the client
+ * end of a connection) to request SCTs from the server.
+ * See https://tools.ietf.org/html/rfc6962.
+ * Returns 1 on success. */
+OPENSSL_EXPORT int SSL_enable_signed_cert_timestamps(SSL *ssl);
+
+/* SSL_CTX_enable_signed_cert_timestamps enables SCT requests on all
+ * client SSL objects created from |ctx|. */
+OPENSSL_EXPORT void SSL_CTX_enable_signed_cert_timestamps(SSL_CTX *ctx);
+
+/* SSL_enable_signed_cert_timestamps causes |ssl| (which must be the client end
+ * of a connection) to request a stapled OCSP response from the server. Returns
+ * 1 on success. */
+OPENSSL_EXPORT int SSL_enable_ocsp_stapling(SSL *ssl);
+
+/* SSL_CTX_enable_ocsp_stapling enables OCSP stapling on all client SSL objects
+ * created from |ctx|. */
+OPENSSL_EXPORT void SSL_CTX_enable_ocsp_stapling(SSL_CTX *ctx);
+
+/* SSL_get0_signed_cert_timestamp_list sets |*out| and |*out_len| to point to
+ * |*out_len| bytes of SCT information from the server. This is only valid if
+ * |ssl| is a client. The SCT information is a SignedCertificateTimestampList
+ * (including the two leading length bytes).
+ * See https://tools.ietf.org/html/rfc6962#section-3.3
+ * If no SCT was received then |*out_len| will be zero on return.
+ *
+ * WARNING: the returned data is not guaranteed to be well formed. */
+OPENSSL_EXPORT void SSL_get0_signed_cert_timestamp_list(const SSL *ssl, uint8_t **out, size_t *out_len);
+
+/* SSL_get0_ocsp_response sets |*out| and |*out_len| to point to |*out_len|
+ * bytes of an OCSP response from the server. This is the DER encoding of an
+ * OCSPResponse type as defined in RFC 2560.
+ *
+ * WARNING: the returned data is not guaranteed to be well formed. */
+OPENSSL_EXPORT void SSL_get0_ocsp_response(const SSL *ssl, uint8_t **out, size_t *out_len);
+
OPENSSL_EXPORT void SSL_CTX_set_next_protos_advertised_cb(SSL_CTX *s,
int (*cb) (SSL *ssl,
const unsigned char **out,
@@ -1101,7 +1149,6 @@ OPENSSL_EXPORT void SSL_CTX_set_next_proto_select_cb(SSL_CTX *s,
void *arg);
OPENSSL_EXPORT void SSL_get0_next_proto_negotiated(const SSL *s,
const uint8_t **data, unsigned *len);
-#endif
OPENSSL_EXPORT int SSL_select_next_proto(unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen,
@@ -1329,31 +1376,15 @@ struct ssl_st
void *arg);
void *tlsext_debug_arg;
char *tlsext_hostname;
- int servername_done; /* no further mod of servername
- 0 : call the servername extension callback.
- 1 : prepare 2, allow last ack just after in server callback.
- 2 : don't call servername callback, no ack in server hello
- */
- /* certificate status request info */
- /* Status type or -1 if no status type */
- int tlsext_status_type;
- /* Expect OCSP CertificateStatus message */
- int tlsext_status_expected;
- /* OCSP status request only */
- STACK_OF(OCSP_RESPID) *tlsext_ocsp_ids;
- X509_EXTENSIONS *tlsext_ocsp_exts;
- /* OCSP response received or to be sent */
- uint8_t *tlsext_ocsp_resp;
- int tlsext_ocsp_resplen;
-
+ /* should_ack_sni is true if the SNI extension should be acked. This is
+ * only used by a server. */
+ char should_ack_sni;
/* RFC4507 session ticket expected to be received or sent */
int tlsext_ticket_expected;
-#ifndef OPENSSL_NO_EC
size_t tlsext_ecpointformatlist_length;
uint8_t *tlsext_ecpointformatlist; /* our list */
size_t tlsext_ellipticcurvelist_length;
uint16_t *tlsext_ellipticcurvelist; /* our list */
-#endif /* OPENSSL_NO_EC */
/* TLS Session Ticket extension override */
TLS_SESSION_TICKET_EXT *tlsext_session_ticket;
@@ -1368,7 +1399,6 @@ struct ssl_st
SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */
-#ifndef OPENSSL_NO_NEXTPROTONEG
/* Next protocol negotiation. For the client, this is the protocol that
* we sent in NextProtocol and is set when handling ServerHello
* extensions.
@@ -1378,9 +1408,6 @@ struct ssl_st
* before the Finished message. */
uint8_t *next_proto_negotiated;
size_t next_proto_negotiated_len;
-#endif
-
-#define session_ctx initial_ctx
STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles; /* What we'll do */
SRTP_PROTECTION_PROFILE *srtp_profile; /* What's been chosen */
@@ -1392,6 +1419,14 @@ struct ssl_st
/* The client's Channel ID private key. */
EVP_PKEY *tlsext_channel_id_private;
+ /* Enable signed certificate time stamps. Currently client only. */
+ char signed_cert_timestamps_enabled;
+
+ /* Enable OCSP stapling. Currently client only.
+ * TODO(davidben): Add a server-side implementation when it becomes
+ * necesary. */
+ char ocsp_stapling_enabled;
+
/* For a client, this contains the list of supported protocols in wire
* format. */
unsigned char* alpn_client_proto_list;
@@ -1631,13 +1666,6 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
#define SSL_CTRL_SET_TLSEXT_TICKET_KEYS 59
#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB 63
#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG 64
-#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE 65
-#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS 66
-#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS 67
-#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS 68
-#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS 69
-#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP 70
-#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP 71
#define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB 72
@@ -2197,22 +2225,18 @@ OPENSSL_EXPORT void SSL_CTX_set_tmp_rsa_callback(SSL_CTX *ctx,
OPENSSL_EXPORT void SSL_set_tmp_rsa_callback(SSL *ssl,
RSA *(*cb)(SSL *ssl,int is_export,
int keylength));
-#ifndef OPENSSL_NO_DH
OPENSSL_EXPORT void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,
DH *(*dh)(SSL *ssl,int is_export,
int keylength));
OPENSSL_EXPORT void SSL_set_tmp_dh_callback(SSL *ssl,
DH *(*dh)(SSL *ssl,int is_export,
int keylength));
-#endif
-#ifndef OPENSSL_NO_ECDH
OPENSSL_EXPORT void SSL_CTX_set_tmp_ecdh_callback(SSL_CTX *ctx,
EC_KEY *(*ecdh)(SSL *ssl,int is_export,
int keylength));
OPENSSL_EXPORT void SSL_set_tmp_ecdh_callback(SSL *ssl,
EC_KEY *(*ecdh)(SSL *ssl,int is_export,
int keylength));
-#endif
OPENSSL_EXPORT const void *SSL_get_current_compression(SSL *s);
OPENSSL_EXPORT const void *SSL_get_current_expansion(SSL *s);
@@ -2352,7 +2376,7 @@ OPENSSL_EXPORT void ERR_load_SSL_strings(void);
#define SSL_F_tls1_setup_key_block 183
#define SSL_F_SSL_set_fd 184
#define SSL_F_SSL_check_private_key 185
-#define SSL_F_ssl3_send_client_verify 186
+#define SSL_F_ssl3_send_cert_verify 186
#define SSL_F_ssl3_write_pending 187
#define SSL_F_ssl_cert_inst 188
#define SSL_F_ssl3_change_cipher_state 189
@@ -2379,7 +2403,7 @@ OPENSSL_EXPORT void ERR_load_SSL_strings(void);
#define SSL_F_SSL_SESSION_new 210
#define SSL_F_check_suiteb_cipher_list 211
#define SSL_F_ssl_scan_clienthello_tlsext 212
-#define SSL_F_ssl3_client_hello 213
+#define SSL_F_ssl3_send_client_hello 213
#define SSL_F_SSL_use_RSAPrivateKey_ASN1 214
#define SSL_F_ssl3_ctrl 215
#define SSL_F_ssl3_setup_write_buffer 216
@@ -2450,6 +2474,9 @@ OPENSSL_EXPORT void ERR_load_SSL_strings(void);
#define SSL_F_tls1_check_duplicate_extensions 281
#define SSL_F_ssl3_expect_change_cipher_spec 282
#define SSL_F_ssl23_get_v2_client_hello 283
+#define SSL_F_ssl3_cert_verify_hash 284
+#define SSL_F_ssl_ctx_log_rsa_client_key_exchange 285
+#define SSL_F_ssl_ctx_log_master_secret 286
#define SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS 100
#define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC 101
#define SSL_R_INVALID_NULL_CMD_NAME 102
@@ -2763,6 +2790,7 @@ OPENSSL_EXPORT void ERR_load_SSL_strings(void);
#define SSL_R_UNPROCESSED_HANDSHAKE_DATA 440
#define SSL_R_HANDSHAKE_RECORD_BEFORE_CCS 441
#define SSL_R_SESSION_MAY_NOT_BE_CREATED 442
+#define SSL_R_SSLV3_ALERT_CLOSE_NOTIFY 1000
#define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010
#define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020
#define SSL_R_TLSV1_ALERT_DECRYPTION_FAILED 1021
@@ -2784,6 +2812,7 @@ OPENSSL_EXPORT void ERR_load_SSL_strings(void);
#define SSL_R_TLSV1_ALERT_PROTOCOL_VERSION 1070
#define SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY 1071
#define SSL_R_TLSV1_ALERT_INTERNAL_ERROR 1080
+#define SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK 1086
#define SSL_R_TLSV1_ALERT_USER_CANCELLED 1090
#define SSL_R_TLSV1_ALERT_NO_RENEGOTIATION 1100
#define SSL_R_TLSV1_UNSUPPORTED_EXTENSION 1110
diff --git a/include/openssl/ssl3.h b/include/openssl/ssl3.h
index a470b89..3aea752 100644
--- a/include/openssl/ssl3.h
+++ b/include/openssl/ssl3.h
@@ -340,8 +340,6 @@ typedef struct ssl3_buffer_st
#define SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS 0x0001
#define SSL3_FLAGS_POP_BUFFER 0x0004
-#define TLS1_FLAGS_TLS_PADDING_BUG 0x0008
-#define TLS1_FLAGS_KEEP_HANDSHAKE 0x0020
/* TODO(davidben): This flag can probably be merged into s3->change_cipher_spec
* to something tri-state. (Normal / Expect CCS / Between CCS and Finished). */
#define SSL3_FLAGS_EXPECT_CCS 0x0080
@@ -422,9 +420,6 @@ typedef struct ssl3_state_st
* established connection state in case of renegotiations.
*/
struct {
- /* actually only needs to be 16+20 */
- unsigned char cert_verify_md[EVP_MAX_MD_SIZE*2];
-
/* actually only need to be 16+20 for SSLv3 and 12 for TLS */
unsigned char finish_md[EVP_MAX_MD_SIZE*2];
int finish_md_len;
@@ -436,13 +431,9 @@ typedef struct ssl3_state_st
/* used to hold the new cipher we are going to use */
const SSL_CIPHER *new_cipher;
-#ifndef OPENSSL_NO_DH
DH *dh;
-#endif
-#ifndef OPENSSL_NO_ECDH
EC_KEY *ecdh; /* holds short lived ECDH key */
-#endif
/* used when SSL_ST_FLUSH_DATA is entered */
int next_state;
@@ -477,6 +468,11 @@ typedef struct ssl3_state_st
/* Server-only: cert_request is true if a client certificate was
* requested. */
int cert_request;
+
+ /* certificate_status_expected is true if OCSP stapling was
+ * negotiated and the server is expected to send a
+ * CertificateStatus message. */
+ char certificate_status_expected;
} tmp;
/* Connection binding to prevent renegotiation attacks */
@@ -486,10 +482,8 @@ typedef struct ssl3_state_st
unsigned char previous_server_finished_len;
int send_connection_binding; /* TODOEKR */
-#ifndef OPENSSL_NO_NEXTPROTONEG
/* Set if we saw the Next Protocol Negotiation extension from our peer. */
int next_proto_neg_seen;
-#endif
/* ALPN information
* (we are in the process of transitioning from NPN to ALPN.) */
@@ -552,10 +546,8 @@ typedef struct ssl3_state_st
#define SSL3_ST_CW_CERT_VRFY_B (0x191|SSL_ST_CONNECT)
#define SSL3_ST_CW_CHANGE_A (0x1A0|SSL_ST_CONNECT)
#define SSL3_ST_CW_CHANGE_B (0x1A1|SSL_ST_CONNECT)
-#ifndef OPENSSL_NO_NEXTPROTONEG
#define SSL3_ST_CW_NEXT_PROTO_A (0x200|SSL_ST_CONNECT)
#define SSL3_ST_CW_NEXT_PROTO_B (0x201|SSL_ST_CONNECT)
-#endif
#define SSL3_ST_CW_CHANNEL_ID_A (0x220|SSL_ST_CONNECT)
#define SSL3_ST_CW_CHANNEL_ID_B (0x221|SSL_ST_CONNECT)
#define SSL3_ST_CW_FINISHED_A (0x1B0|SSL_ST_CONNECT)
@@ -602,10 +594,8 @@ typedef struct ssl3_state_st
#define SSL3_ST_SR_CERT_VRFY_A (0x1A0|SSL_ST_ACCEPT)
#define SSL3_ST_SR_CERT_VRFY_B (0x1A1|SSL_ST_ACCEPT)
#define SSL3_ST_SR_CHANGE (0x1B0|SSL_ST_ACCEPT)
-#ifndef OPENSSL_NO_NEXTPROTONEG
#define SSL3_ST_SR_NEXT_PROTO_A (0x210|SSL_ST_ACCEPT)
#define SSL3_ST_SR_NEXT_PROTO_B (0x211|SSL_ST_ACCEPT)
-#endif
#define SSL3_ST_SR_CHANNEL_ID_A (0x230|SSL_ST_ACCEPT)
#define SSL3_ST_SR_CHANNEL_ID_B (0x231|SSL_ST_ACCEPT)
#define SSL3_ST_SR_FINISHED_A (0x1C0|SSL_ST_ACCEPT)
@@ -635,9 +625,7 @@ typedef struct ssl3_state_st
#define SSL3_MT_FINISHED 20
#define SSL3_MT_CERTIFICATE_STATUS 22
#define SSL3_MT_SUPPLEMENTAL_DATA 23
-#ifndef OPENSSL_NO_NEXTPROTONEG
#define SSL3_MT_NEXT_PROTO 67
-#endif
#define SSL3_MT_ENCRYPTED_EXTENSIONS 203
#define DTLS1_MT_HELLO_VERIFY_REQUEST 3
diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h
index b075a20..08ad8e8 100644
--- a/include/openssl/tls1.h
+++ b/include/openssl/tls1.h
@@ -246,10 +246,11 @@ extern "C" {
/* ExtensionType value from RFC5746 */
#define TLSEXT_TYPE_renegotiate 0xff01
-#ifndef OPENSSL_NO_NEXTPROTONEG
+/* ExtensionType value from RFC6962 */
+#define TLSEXT_TYPE_certificate_timestamp 18
+
/* This is not an IANA defined extension number */
#define TLSEXT_TYPE_next_proto_neg 13172
-#endif
/* This is not an IANA defined extension number */
#define TLSEXT_TYPE_channel_id 30031
@@ -332,27 +333,6 @@ SSL_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_DEBUG_CB,(void (*)(void))cb)
#define SSL_set_tlsext_debug_arg(ssl, arg) \
SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_DEBUG_ARG,0, (void *)arg)
-#define SSL_set_tlsext_status_type(ssl, type) \
-SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE,type, NULL)
-
-#define SSL_get_tlsext_status_exts(ssl, arg) \
-SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS,0, (void *)arg)
-
-#define SSL_set_tlsext_status_exts(ssl, arg) \
-SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS,0, (void *)arg)
-
-#define SSL_get_tlsext_status_ids(ssl, arg) \
-SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS,0, (void *)arg)
-
-#define SSL_set_tlsext_status_ids(ssl, arg) \
-SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS,0, (void *)arg)
-
-#define SSL_get_tlsext_status_ocsp_resp(ssl, arg) \
-SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP,0, (void *)arg)
-
-#define SSL_set_tlsext_status_ocsp_resp(ssl, arg, arglen) \
-SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP,arglen, (void *)arg)
-
#define SSL_CTX_set_tlsext_servername_callback(ctx, cb) \
SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_CB,(void (*)(void))cb)
diff --git a/include/openssl/x509.h b/include/openssl/x509.h
index 29fba40..1f277f3 100644
--- a/include/openssl/x509.h
+++ b/include/openssl/x509.h
@@ -259,9 +259,7 @@ struct x509_st
STACK_OF(DIST_POINT) *crldp;
STACK_OF(GENERAL_NAME) *altname;
NAME_CONSTRAINTS *nc;
-#ifndef OPENSSL_NO_SHA
unsigned char sha1_hash[SHA_DIGEST_LENGTH];
-#endif
X509_CERT_AUX *aux;
} /* X509 */;
@@ -433,9 +431,7 @@ struct X509_crl_st
/* CRL and base CRL numbers for delta processing */
ASN1_INTEGER *crl_number;
ASN1_INTEGER *base_crl_number;
-#ifndef OPENSSL_NO_SHA
unsigned char sha1_hash[SHA_DIGEST_LENGTH];
-#endif
STACK_OF(GENERAL_NAMES) *issuers;
const X509_CRL_METHOD *meth;
void *meth_data;
@@ -664,12 +660,10 @@ OPENSSL_EXPORT int i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa);
OPENSSL_EXPORT DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa);
OPENSSL_EXPORT int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa);
#endif
-#ifndef OPENSSL_NO_EC
OPENSSL_EXPORT EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey);
OPENSSL_EXPORT int i2d_EC_PUBKEY_fp(FILE *fp, EC_KEY *eckey);
OPENSSL_EXPORT EC_KEY *d2i_ECPrivateKey_fp(FILE *fp, EC_KEY **eckey);
OPENSSL_EXPORT int i2d_ECPrivateKey_fp(FILE *fp, EC_KEY *eckey);
-#endif
OPENSSL_EXPORT X509_SIG *d2i_PKCS8_fp(FILE *fp,X509_SIG **p8);
OPENSSL_EXPORT int i2d_PKCS8_fp(FILE *fp,X509_SIG *p8);
OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp,
@@ -701,12 +695,10 @@ OPENSSL_EXPORT int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa);
OPENSSL_EXPORT DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa);
OPENSSL_EXPORT int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa);
#endif
-#ifndef OPENSSL_NO_EC
OPENSSL_EXPORT EC_KEY *d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **eckey);
OPENSSL_EXPORT int i2d_EC_PUBKEY_bio(BIO *bp, EC_KEY *eckey);
OPENSSL_EXPORT EC_KEY *d2i_ECPrivateKey_bio(BIO *bp, EC_KEY **eckey);
OPENSSL_EXPORT int i2d_ECPrivateKey_bio(BIO *bp, EC_KEY *eckey);
-#endif
OPENSSL_EXPORT X509_SIG *d2i_PKCS8_bio(BIO *bp,X509_SIG **p8);
OPENSSL_EXPORT int i2d_PKCS8_bio(BIO *bp,X509_SIG *p8);
OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp,
@@ -770,11 +762,9 @@ OPENSSL_EXPORT int i2d_DSA_PUBKEY(const DSA *a,unsigned char **pp);
OPENSSL_EXPORT DSA * d2i_DSA_PUBKEY(DSA **a,const unsigned char **pp,
long length);
#endif
-#ifndef OPENSSL_NO_EC
OPENSSL_EXPORT int i2d_EC_PUBKEY(const EC_KEY *a, unsigned char **pp);
OPENSSL_EXPORT EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp,
long length);
-#endif
DECLARE_ASN1_FUNCTIONS(X509_SIG)
DECLARE_ASN1_FUNCTIONS(X509_REQ_INFO)
@@ -946,10 +936,8 @@ OPENSSL_EXPORT unsigned long X509_issuer_name_hash(X509 *a);
OPENSSL_EXPORT int X509_subject_name_cmp(const X509 *a, const X509 *b);
OPENSSL_EXPORT unsigned long X509_subject_name_hash(X509 *x);
-#ifndef OPENSSL_NO_MD5
OPENSSL_EXPORT unsigned long X509_issuer_name_hash_old(X509 *a);
OPENSSL_EXPORT unsigned long X509_subject_name_hash_old(X509 *x);
-#endif
OPENSSL_EXPORT int X509_cmp(const X509 *a, const X509 *b);
OPENSSL_EXPORT int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b);
diff --git a/ssl/CMakeLists.txt b/ssl/CMakeLists.txt
index 3db8607..49f7c3d 100644
--- a/ssl/CMakeLists.txt
+++ b/ssl/CMakeLists.txt
@@ -53,4 +53,4 @@ add_executable(
ssl_test.c
)
-target_link_libraries(ssl_test crypto)
+target_link_libraries(ssl_test ssl crypto)
diff --git a/ssl/d1_both.c b/ssl/d1_both.c
index bcfcc47..2d944d8 100644
--- a/ssl/d1_both.c
+++ b/ssl/d1_both.c
@@ -420,7 +420,7 @@ int dtls1_do_write(SSL *s, int type)
* Read an entire handshake message. Handshake messages arrive in
* fragments.
*/
-long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
+long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int hash_message, int *ok)
{
int i, al;
struct hm_header_st *msg_hdr;
@@ -431,6 +431,10 @@ long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
* by the absence of an optional handshake message */
if (s->s3->tmp.reuse_message)
{
+ /* A SSL_GET_MESSAGE_DONT_HASH_MESSAGE call cannot be combined
+ * with reuse_message; the SSL_GET_MESSAGE_DONT_HASH_MESSAGE
+ * would have to have been applied to the previous call. */
+ assert(hash_message != SSL_GET_MESSAGE_DONT_HASH_MESSAGE);
s->s3->tmp.reuse_message=0;
if ((mt >= 0) && (s->s3->tmp.message_type != mt))
{
@@ -467,7 +471,10 @@ again:
p -= DTLS1_HM_HEADER_LENGTH;
msg_len += DTLS1_HM_HEADER_LENGTH;
- ssl3_finish_mac(s, p, msg_len);
+ s->init_msg = (uint8_t*)s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
+
+ if (hash_message != SSL_GET_MESSAGE_DONT_HASH_MESSAGE)
+ ssl3_hash_current_message(s);
if (s->msg_callback)
s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
p, msg_len,
@@ -479,7 +486,6 @@ again:
if (!s->d1->listen)
s->d1->handshake_read_seq++;
- s->init_msg = (uint8_t*)s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
return s->init_num;
f_err:
@@ -1159,7 +1165,6 @@ dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off,
saved_state.write_hash = s->write_hash;
saved_state.session = s->session;
saved_state.epoch = s->d1->w_epoch;
- saved_state.epoch = s->d1->w_epoch;
s->d1->retransmitting = 1;
diff --git a/ssl/d1_clnt.c b/ssl/d1_clnt.c
index 99cfefd..b781d88 100644
--- a/ssl/d1_clnt.c
+++ b/ssl/d1_clnt.c
@@ -245,7 +245,7 @@ int dtls1_connect(SSL *s)
ssl3_init_finished_mac(s);
dtls1_start_timer(s);
- ret=ssl3_client_hello(s);
+ ret=ssl3_send_client_hello(s);
if (ret <= 0) goto end;
if ( s->d1->send_cookie)
@@ -309,7 +309,7 @@ int dtls1_connect(SSL *s)
{
ret=ssl3_get_server_certificate(s);
if (ret <= 0) goto end;
- if (s->tlsext_status_expected)
+ if (s->s3->tmp.certificate_status_expected)
s->state=SSL3_ST_CR_CERT_STATUS_A;
else
s->state=SSL3_ST_CR_KEY_EXCH_A;
@@ -393,7 +393,7 @@ int dtls1_connect(SSL *s)
case SSL3_ST_CW_CERT_VRFY_A:
case SSL3_ST_CW_CERT_VRFY_B:
dtls1_start_timer(s);
- ret=ssl3_send_client_verify(s);
+ ret=ssl3_send_cert_verify(s);
if (ret <= 0) goto end;
s->state=SSL3_ST_CW_CHANGE_A;
s->init_num=0;
@@ -596,6 +596,7 @@ static int dtls1_get_hello_verify(SSL *s)
-1,
/* Use the same maximum size as ssl3_get_server_hello. */
20000,
+ SSL_GET_MESSAGE_HASH_MESSAGE,
&ok);
s->first_packet = 0;
diff --git a/ssl/d1_enc.c b/ssl/d1_enc.c
index 70b74b8..dec0ea5 100644
--- a/ssl/d1_enc.c
+++ b/ssl/d1_enc.c
@@ -202,11 +202,6 @@ int dtls1_enc(SSL *s, int send)
/* we need to add 'i' padding bytes of value j */
j=i-1;
- if (s->options & SSL_OP_TLS_BLOCK_PADDING_BUG)
- {
- if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG)
- j++;
- }
for (k=(int)l; k<(int)(l+i); k++)
rec->input[k]=j;
l+=i;
diff --git a/ssl/d1_srtp.c b/ssl/d1_srtp.c
index 2652f84..1f909de 100644
--- a/ssl/d1_srtp.c
+++ b/ssl/d1_srtp.c
@@ -161,13 +161,13 @@ static int find_profile_by_name(char *profile_name,
len))
{
*pptr=p;
- return 0;
+ return 1;
}
p++;
}
- return 1;
+ return 0;
}
static int find_profile_by_num(unsigned profile_num,
@@ -181,12 +181,12 @@ static int find_profile_by_num(unsigned profile_num,
if(p->id == profile_num)
{
*pptr=p;
- return 0;
+ return 1;
}
p++;
}
- return 1;
+ return 0;
}
static int ssl_ctx_make_profiles(const char *profiles_string,STACK_OF(SRTP_PROTECTION_PROFILE) **out)
@@ -201,14 +201,14 @@ static int ssl_ctx_make_profiles(const char *profiles_string,STACK_OF(SRTP_PROTE
if(!(profiles=sk_SRTP_PROTECTION_PROFILE_new_null()))
{
OPENSSL_PUT_ERROR(SSL, ssl_ctx_make_profiles, SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES);
- return 1;
+ return 0;
}
do
{
col=strchr(ptr,':');
- if(!find_profile_by_name(ptr,&p,
+ if(find_profile_by_name(ptr,&p,
col ? col-ptr : (int)strlen(ptr)))
{
sk_SRTP_PROTECTION_PROFILE_push(profiles,p);
@@ -216,7 +216,7 @@ static int ssl_ctx_make_profiles(const char *profiles_string,STACK_OF(SRTP_PROTE
else
{
OPENSSL_PUT_ERROR(SSL, ssl_ctx_make_profiles, SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE);
- return 1;
+ return 0;
}
if(col) ptr=col+1;
@@ -224,17 +224,19 @@ static int ssl_ctx_make_profiles(const char *profiles_string,STACK_OF(SRTP_PROTE
*out=profiles;
- return 0;
+ return 1;
}
int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx,const char *profiles)
{
- return ssl_ctx_make_profiles(profiles,&ctx->srtp_profiles);
+ /* This API inverts its return value. */
+ return !ssl_ctx_make_profiles(profiles,&ctx->srtp_profiles);
}
int SSL_set_tlsext_use_srtp(SSL *s,const char *profiles)
{
- return ssl_ctx_make_profiles(profiles,&s->srtp_profiles);
+ /* This API inverts its return value. */
+ return !ssl_ctx_make_profiles(profiles,&s->srtp_profiles);
}
@@ -278,13 +280,13 @@ int ssl_add_clienthello_use_srtp_ext(SSL *s, unsigned char *p, int *len, int max
if(ct==0)
{
OPENSSL_PUT_ERROR(SSL, ssl_add_clienthello_use_srtp_ext, SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST);
- return 1;
+ return 0;
}
if((2 + ct*2 + 1) > maxlen)
{
OPENSSL_PUT_ERROR(SSL, ssl_add_clienthello_use_srtp_ext, SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG);
- return 1;
+ return 0;
}
/* Add the length */
@@ -301,7 +303,7 @@ int ssl_add_clienthello_use_srtp_ext(SSL *s, unsigned char *p, int *len, int max
*len=2 + ct*2 + 1;
- return 0;
+ return 1;
}
@@ -335,7 +337,7 @@ int ssl_parse_clienthello_use_srtp_ext(SSL *s, CBS *cbs, int *out_alert)
goto done;
}
- if (!find_profile_by_num(profile_id, &cprof))
+ if (find_profile_by_num(profile_id, &cprof))
{
sk_SRTP_PROTECTION_PROFILE_push(clnt, cprof);
}
@@ -381,13 +383,13 @@ int ssl_add_serverhello_use_srtp_ext(SSL *s, unsigned char *p, int *len, int max
if(maxlen < 5)
{
OPENSSL_PUT_ERROR(SSL, ssl_add_serverhello_use_srtp_ext, SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG);
- return 1;
+ return 0;
}
if(s->srtp_profile==0)
{
OPENSSL_PUT_ERROR(SSL, ssl_add_serverhello_use_srtp_ext, SSL_R_USE_SRTP_NOT_NEGOTIATED);
- return 1;
+ return 0;
}
s2n(2, p);
s2n(s->srtp_profile->id,p);
@@ -395,7 +397,7 @@ int ssl_add_serverhello_use_srtp_ext(SSL *s, unsigned char *p, int *len, int max
}
*len=5;
- return 0;
+ return 1;
}
diff --git a/ssl/d1_srvr.c b/ssl/d1_srvr.c
index fe8001d..79da484 100644
--- a/ssl/d1_srvr.c
+++ b/ssl/d1_srvr.c
@@ -359,7 +359,7 @@ int dtls1_accept(SSL *s)
dtls1_start_timer(s);
ret=ssl3_send_server_certificate(s);
if (ret <= 0) goto end;
- if (s->tlsext_status_expected)
+ if (s->s3->tmp.certificate_status_expected)
s->state=SSL3_ST_SW_CERT_STATUS_A;
else
s->state=SSL3_ST_SW_KEY_EXCH_A;
@@ -485,37 +485,6 @@ int dtls1_accept(SSL *s)
goto end;
s->state=SSL3_ST_SR_CERT_VRFY_A;
s->init_num=0;
-
- /* TODO(davidben): These two blocks are different
- * between SSL and DTLS. Resolve the difference and code
- * duplication. */
- if (SSL_USE_SIGALGS(s))
- {
- if (!s->session->peer)
- break;
- /* For sigalgs freeze the handshake buffer
- * at this point and digest cached records.
- */
- if (!s->s3->handshake_buffer)
- {
- OPENSSL_PUT_ERROR(SSL, dtls1_accept, ERR_R_INTERNAL_ERROR);
- return -1;
- }
- s->s3->flags |= TLS1_FLAGS_KEEP_HANDSHAKE;
- if (!ssl3_digest_cached_records(s))
- return -1;
- }
- else
- {
- /* We need to get hashes here so if there is
- * a client cert, it can be verified */
- s->method->ssl3_enc->cert_verify_mac(s,
- NID_md5,
- &(s->s3->tmp.cert_verify_md[0]));
- s->method->ssl3_enc->cert_verify_mac(s,
- NID_sha1,
- &(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]));
- }
break;
case SSL3_ST_SR_CERT_VRFY_A:
@@ -547,12 +516,14 @@ int dtls1_accept(SSL *s)
case SSL3_ST_SW_SESSION_TICKET_A:
case SSL3_ST_SW_SESSION_TICKET_B:
- ret=ssl3_send_newsession_ticket(s);
+ ret=ssl3_send_new_session_ticket(s);
if (ret <= 0) goto end;
s->state=SSL3_ST_SW_CHANGE_A;
s->init_num=0;
break;
+#if 0
+ // TODO(davidben): Implement OCSP stapling on the server.
case SSL3_ST_SW_CERT_STATUS_A:
case SSL3_ST_SW_CERT_STATUS_B:
ret=ssl3_send_cert_status(s);
@@ -560,7 +531,7 @@ int dtls1_accept(SSL *s)
s->state=SSL3_ST_SW_KEY_EXCH_A;
s->init_num=0;
break;
-
+#endif
case SSL3_ST_SW_CHANGE_A:
case SSL3_ST_SW_CHANGE_B:
diff --git a/ssl/pqueue/CMakeLists.txt b/ssl/pqueue/CMakeLists.txt
index 58963ff..b7166b4 100644
--- a/ssl/pqueue/CMakeLists.txt
+++ b/ssl/pqueue/CMakeLists.txt
@@ -7,3 +7,11 @@ add_library(
pqueue.c
)
+
+add_executable(
+ pqueue_test
+
+ pqueue_test.c
+)
+
+target_link_libraries(pqueue_test ssl crypto)
diff --git a/ssl/pqueue/pqueue.c b/ssl/pqueue/pqueue.c
index e8d0ac5..4c94355 100644
--- a/ssl/pqueue/pqueue.c
+++ b/ssl/pqueue/pqueue.c
@@ -87,7 +87,7 @@ void pitem_free(pitem *item) {
OPENSSL_free(item);
}
-pqueue pqueue_new() {
+pqueue pqueue_new(void) {
pqueue_s *pq = (pqueue_s *)OPENSSL_malloc(sizeof(pqueue_s));
if (pq == NULL) {
return NULL;
@@ -111,7 +111,7 @@ pitem *pqueue_find(pqueue_s *pq, uint8_t *prio64be) {
pitem *curr;
for (curr = pq->items; curr; curr = curr->next) {
- if (memcmp(curr->priority, prio64be, 8) == 0) {
+ if (memcmp(curr->priority, prio64be, sizeof(curr->priority)) == 0) {
return curr;
}
}
@@ -130,9 +130,9 @@ size_t pqueue_size(pqueue_s *pq) {
return count;
}
-pitem *pqueue_iterator(pqueue_s *pq) { return pq->items; }
+piterator pqueue_iterator(pqueue_s *pq) { return pq->items; }
-pitem *pqueue_next(pitem **item) {
+pitem *pqueue_next(piterator *item) {
pitem *ret;
if (item == NULL || *item == NULL) {
@@ -156,9 +156,9 @@ pitem *pqueue_insert(pqueue_s *pq, pitem *item) {
for (curr = NULL, next = pq->items; next != NULL;
curr = next, next = next->next) {
/* we can compare 64-bit value in big-endian encoding with memcmp. */
- int cmp = memcmp(next->priority, item->priority, 8);
- if (cmp > 0) /* next > item */
- {
+ int cmp = memcmp(next->priority, item->priority, sizeof(item->priority));
+ if (cmp > 0) {
+ /* next > item */
item->next = next;
if (curr == NULL) {
@@ -168,8 +168,10 @@ pitem *pqueue_insert(pqueue_s *pq, pitem *item) {
}
return item;
- } else if (cmp == 0) /* duplicates not allowed */
+ } else if (cmp == 0) {
+ /* duplicates not allowed */
return NULL;
+ }
}
item->next = NULL;
diff --git a/ssl/pqueue/pqueue_test.c b/ssl/pqueue/pqueue_test.c
new file mode 100644
index 0000000..16a9ad8
--- /dev/null
+++ b/ssl/pqueue/pqueue_test.c
@@ -0,0 +1,91 @@
+/* Copyright (c) 2014, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/pqueue.h>
+#include <openssl/ssl.h>
+
+
+static int trivial() {
+ pqueue q = pqueue_new();
+ if (q == NULL) {
+ return 0;
+ }
+ int32_t data = 0xdeadbeef;
+ uint8_t priority[8] = {0};
+ pitem *item = pitem_new(priority, &data);
+ if (item == NULL ||
+ pqueue_insert(q, item) != item ||
+ pqueue_size(q) != 1 ||
+ pqueue_peek(q) != item ||
+ pqueue_pop(q) != item ||
+ pqueue_size(q) != 0 ||
+ pqueue_pop(q) != NULL) {
+ return 0;
+ }
+ pitem_free(item);
+ pqueue_free(q);
+ return 1;
+}
+
+#define NUM_ITEMS 10
+
+static int fixed_random() {
+ /* Random order of 10 elements, chosen by
+ random.choice(list(itertools.permutations(range(10)))) */
+ int ordering[NUM_ITEMS] = {9, 6, 3, 4, 0, 2, 7, 1, 8, 5};
+ int i;
+ pqueue q = pqueue_new();
+ if (q == NULL) {
+ return 0;
+ }
+ uint8_t priority[8] = {0};
+ /* Insert the elements */
+ for (i = 0; i < NUM_ITEMS; i++) {
+ priority[7] = ordering[i];
+ pitem *item = pitem_new(priority, &ordering[i]);
+ pqueue_insert(q, item);
+ }
+ piterator iter = pqueue_iterator(q);
+ pitem *curr = pqueue_next(&iter);
+ if (curr == NULL) {
+ return 0;
+ }
+ while (1) {
+ pitem *next = pqueue_next(&iter);
+ if (next == NULL) {
+ break;
+ }
+ int *curr_data = (int*)curr->data;
+ int *next_data = (int*)next->data;
+ if (*curr_data >= *next_data) {
+ return 0;
+ }
+ curr = next;
+ }
+ return 1;
+}
+
+int main(void) {
+ SSL_library_init();
+
+ if (!trivial() || !fixed_random()) {
+ return 1;
+ }
+
+ printf("PASS\n");
+ return 0;
+}
diff --git a/ssl/s23_clnt.c b/ssl/s23_clnt.c
index cfa6d00..ccb3e2c 100644
--- a/ssl/s23_clnt.c
+++ b/ssl/s23_clnt.c
@@ -121,16 +121,13 @@ static int ssl23_client_hello(SSL *s);
static int ssl23_get_server_hello(SSL *s);
static const SSL_METHOD *ssl23_get_client_method(int ver)
{
- if (ver == SSL3_VERSION)
- return(SSLv3_client_method());
- else if (ver == TLS1_VERSION)
- return(TLSv1_client_method());
- else if (ver == TLS1_1_VERSION)
- return(TLSv1_1_client_method());
- else if (ver == TLS1_2_VERSION)
- return(TLSv1_2_client_method());
- else
- return(NULL);
+ /* When SSL_set_session is called, do NOT switch to the version-specific
+ * method table. The server may still negotiate a different version when
+ * rejecting the session.
+ *
+ * TODO(davidben): Clean this up. This duplicates logic from the
+ * version-specific tables. https://crbug.com/403378 */
+ return SSLv23_client_method();
}
IMPLEMENT_ssl23_meth_func(SSLv23_client_method,
@@ -167,12 +164,6 @@ int ssl23_connect(SSL *s)
case SSL_ST_BEFORE|SSL_ST_CONNECT:
case SSL_ST_OK|SSL_ST_CONNECT:
- if (s->session != NULL)
- {
- OPENSSL_PUT_ERROR(SSL, ssl23_connect, SSL_R_SSL23_DOING_SESSION_ID_REUSE);
- ret= -1;
- goto end;
- }
s->server=0;
if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
@@ -288,39 +279,32 @@ static int ssl23_client_hello(SSL *s)
* TLS1>=1, it would be insufficient to pass SSL_NO_TLSv1, the
* answer is SSL_OP_NO_TLSv1|SSL_OP_NO_SSLv3|SSL_OP_NO_SSLv2.
*/
- mask = SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1
-#if !defined(OPENSSL_NO_SSL3)
- |SSL_OP_NO_SSLv3
-#endif
- ;
-#if !defined(OPENSSL_NO_TLS1_2_CLIENT)
+ mask = SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1|SSL_OP_NO_SSLv3;
version = TLS1_2_VERSION;
-
if ((options & SSL_OP_NO_TLSv1_2) && (options & mask) != mask)
version = TLS1_1_VERSION;
-#else
- version = TLS1_1_VERSION;
-#endif
mask &= ~SSL_OP_NO_TLSv1_1;
if ((options & SSL_OP_NO_TLSv1_1) && (options & mask) != mask)
version = TLS1_VERSION;
mask &= ~SSL_OP_NO_TLSv1;
-#if !defined(OPENSSL_NO_SSL3)
if ((options & SSL_OP_NO_TLSv1) && (options & mask) != mask)
version = SSL3_VERSION;
mask &= ~SSL_OP_NO_SSLv3;
-#endif
buf=(unsigned char *)s->init_buf->data;
if (s->state == SSL23_ST_CW_CLNT_HELLO_A)
{
-#if 0
- /* don't reuse session-id's */
- if (!ssl_get_new_session(s,0))
+ /* Check if the session is resumable. If not, drop it. */
+ if (s->session != NULL)
{
- return(-1);
+ if (s->session->ssl_version > version ||
+ s->session->session_id_length == 0 ||
+ s->session->not_resumable)
+ {
+ SSL_SESSION_free(s->session);
+ s->session = NULL;
+ }
}
-#endif
p=s->s3->client_random;
if (ssl_fill_hello_random(s, 0, p, SSL3_RANDOM_SIZE) <= 0)
@@ -374,8 +358,22 @@ static int ssl23_client_hello(SSL *s)
memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE);
p += SSL3_RANDOM_SIZE;
- /* Session ID (zero since there is no reuse) */
- *(p++) = 0;
+ /* Session ID */
+ if (s->new_session || s->session == NULL)
+ i=0;
+ else
+ i=s->session->session_id_length;
+ *(p++)=i;
+ if (i != 0)
+ {
+ if (i > (int)sizeof(s->session->session_id))
+ {
+ OPENSSL_PUT_ERROR(SSL, ssl23_client_hello, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+ memcpy(p,s->session->session_id,i);
+ p+=i;
+ }
/* Ciphers supported (using SSL 3.0/TLS 1.0 format) */
i = ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), &p[2]);
@@ -572,9 +570,9 @@ static int ssl23_get_server_hello(SSL *s)
}
s->init_num=0;
- /* Since, if we are sending a ssl23 client hello, we are not
- * reusing a session-id */
- if (!ssl_get_new_session(s,0))
+ /* If there was no session to resume, now that the final version is
+ * determined, insert a fresh one. */
+ if (s->session == NULL && !ssl_get_new_session(s,0))
goto err;
return(SSL_connect(s));
diff --git a/ssl/s23_meth.c b/ssl/s23_meth.c
index 5f0f8b2..f3af959 100644
--- a/ssl/s23_meth.c
+++ b/ssl/s23_meth.c
@@ -65,11 +65,9 @@
static const SSL_METHOD *ssl23_get_method(int ver);
static const SSL_METHOD *ssl23_get_method(int ver)
{
-#ifndef OPENSSL_NO_SSL3
if (ver == SSL3_VERSION)
return(SSLv3_method());
else
-#endif
if (ver == TLS1_VERSION)
return(TLSv1_method());
else if (ver == TLS1_1_VERSION)
diff --git a/ssl/s3_both.c b/ssl/s3_both.c
index 8ce6b3b..6604fc7 100644
--- a/ssl/s3_both.c
+++ b/ssl/s3_both.c
@@ -118,8 +118,10 @@
#include <openssl/buf.h>
#include <openssl/evp.h>
#include <openssl/mem.h>
+#include <openssl/md5.h>
#include <openssl/obj.h>
#include <openssl/rand.h>
+#include <openssl/sha.h>
#include <openssl/x509.h>
#include "ssl_locl.h"
@@ -166,6 +168,14 @@ int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen)
memcpy(p, s->s3->tmp.finish_md, i);
l=i;
+ /* Log the master secret, if logging is enabled. */
+ if (!ssl_ctx_log_master_secret(s->ctx,
+ s->s3->client_random, SSL3_RANDOM_SIZE,
+ s->session->master_key, s->session->master_key_length))
+ {
+ return 0;
+ }
+
/* Copy the finished so we can use it for
renegotiation checks */
if(s->type == SSL_ST_CONNECT)
@@ -191,7 +201,6 @@ int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen)
return ssl_do_write(s);
}
-#ifndef OPENSSL_NO_NEXTPROTONEG
/* ssl3_take_mac calculates the Finished MAC for the handshakes messages seen to far. */
static void ssl3_take_mac(SSL *s)
{
@@ -216,7 +225,6 @@ static void ssl3_take_mac(SSL *s)
s->s3->tmp.peer_finish_md_len = s->method->ssl3_enc->final_finish_mac(s,
sender,slen,s->s3->tmp.peer_finish_md);
}
-#endif
int ssl3_get_finished(SSL *s, int a, int b)
{
@@ -224,21 +232,20 @@ int ssl3_get_finished(SSL *s, int a, int b)
long n;
unsigned char *p;
-#ifdef OPENSSL_NO_NEXTPROTONEG
- /* the mac has already been generated when we received the
- * change cipher spec message and is in s->s3->tmp.peer_finish_md
- */
-#endif
-
n=s->method->ssl_get_message(s,
a,
b,
SSL3_MT_FINISHED,
64, /* should actually be 36+4 :-) */
+ SSL_GET_MESSAGE_DONT_HASH_MESSAGE,
&ok);
if (!ok) return((int)n);
+ /* Snapshot the finished hash before incorporating the new message. */
+ ssl3_take_mac(s);
+ ssl3_hash_current_message(s);
+
/* If this occurs, we have missed a message.
* TODO(davidben): Is this check now redundant with
* SSL3_FLAGS_EXPECT_CCS? */
@@ -337,7 +344,7 @@ unsigned long ssl3_output_cert_chain(SSL *s, CERT_PKEY *cpk)
* The first four bytes (msg_type and length) are read in state 'st1',
* the body is read in state 'stn'.
*/
-long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
+long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int hash_message, int *ok)
{
unsigned char *p;
unsigned long l;
@@ -346,6 +353,10 @@ long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
if (s->s3->tmp.reuse_message)
{
+ /* A SSL_GET_MESSAGE_DONT_HASH_MESSAGE call cannot be combined
+ * with reuse_message; the SSL_GET_MESSAGE_DONT_HASH_MESSAGE
+ * would have to have been applied to the previous call. */
+ assert(hash_message != SSL_GET_MESSAGE_DONT_HASH_MESSAGE);
s->s3->tmp.reuse_message=0;
if ((mt >= 0) && (s->s3->tmp.message_type != mt))
{
@@ -461,16 +472,9 @@ long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
n -= i;
}
-#ifndef OPENSSL_NO_NEXTPROTONEG
- /* If receiving Finished, record MAC of prior handshake messages for
- * Finished verification. */
- if (*s->init_buf->data == SSL3_MT_FINISHED)
- ssl3_take_mac(s);
-#endif
-
/* Feed this message into MAC computation. */
- if (*((unsigned char*) s->init_buf->data) != SSL3_MT_ENCRYPTED_EXTENSIONS)
- ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, s->init_num + 4);
+ if (hash_message != SSL_GET_MESSAGE_DONT_HASH_MESSAGE)
+ ssl3_hash_current_message(s);
if (s->msg_callback)
s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data, (size_t)s->init_num + 4, s, s->msg_callback_arg);
*ok=1;
@@ -482,6 +486,73 @@ err:
return(-1);
}
+void ssl3_hash_current_message(SSL *s)
+ {
+ /* The handshake header (different size between DTLS and TLS) is included in the hash. */
+ size_t header_len = s->init_msg - (uint8_t *)s->init_buf->data;
+ ssl3_finish_mac(s, (uint8_t *)s->init_buf->data, s->init_num + header_len);
+ }
+
+/* ssl3_cert_verify_hash is documented as needing EVP_MAX_MD_SIZE because that
+ * is sufficient pre-TLS1.2 as well. */
+OPENSSL_COMPILE_ASSERT(EVP_MAX_MD_SIZE > MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH,
+ combined_tls_hash_fits_in_max);
+
+int ssl3_cert_verify_hash(SSL *s, uint8_t *out, size_t *out_len, const EVP_MD **out_md, EVP_PKEY *pkey)
+ {
+ /* For TLS v1.2 send signature algorithm and signature using
+ * agreed digest and cached handshake records. Otherwise, use
+ * SHA1 or MD5 + SHA1 depending on key type. */
+ if (SSL_USE_SIGALGS(s))
+ {
+ const uint8_t *hdata;
+ size_t hdatalen;
+ EVP_MD_CTX mctx;
+ unsigned len;
+
+ if (!BIO_mem_contents(s->s3->handshake_buffer, &hdata, &hdatalen))
+ {
+ OPENSSL_PUT_ERROR(SSL, ssl3_cert_verify_hash, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ EVP_MD_CTX_init(&mctx);
+ if (!EVP_DigestInit_ex(&mctx, *out_md, NULL)
+ || !EVP_DigestUpdate(&mctx, hdata, hdatalen)
+ || !EVP_DigestFinal(&mctx, out, &len))
+ {
+ OPENSSL_PUT_ERROR(SSL, ssl3_cert_verify_hash, ERR_R_EVP_LIB);
+ EVP_MD_CTX_cleanup(&mctx);
+ return 0;
+ }
+ *out_len = len;
+ }
+ else if (pkey->type == EVP_PKEY_RSA)
+ {
+ if (s->method->ssl3_enc->cert_verify_mac(s, NID_md5, out) == 0 ||
+ s->method->ssl3_enc->cert_verify_mac(s,
+ NID_sha1, out + MD5_DIGEST_LENGTH) == 0)
+ return 0;
+ *out_len = MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH;
+ /* Using a NULL signature MD makes EVP_PKEY_sign perform
+ * a raw RSA signature, rather than wrapping in a
+ * DigestInfo. */
+ *out_md = NULL;
+ }
+ else if (pkey->type == EVP_PKEY_EC)
+ {
+ if (s->method->ssl3_enc->cert_verify_mac(s, NID_sha1, out) == 0)
+ return 0;
+ *out_len = SHA_DIGEST_LENGTH;
+ *out_md = EVP_sha1();
+ }
+ else
+ {
+ OPENSSL_PUT_ERROR(SSL, ssl3_cert_verify_hash, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ return 1;
+ }
+
int ssl_cert_type(X509 *x, EVP_PKEY *pkey)
{
EVP_PKEY *pk;
@@ -498,12 +569,10 @@ int ssl_cert_type(X509 *x, EVP_PKEY *pkey)
{
ret=SSL_PKEY_RSA_ENC;
}
-#ifndef OPENSSL_NO_EC
else if (i == EVP_PKEY_EC)
{
ret = SSL_PKEY_ECC;
}
-#endif
err:
if(!pkey) EVP_PKEY_free(pk);
@@ -627,8 +696,9 @@ int ssl3_setup_write_buffer(SSL *s)
len = s->max_send_fragment
+ SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD
+ headerlen + align;
- if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS))
- len += headerlen + align
+ /* Account for 1/n-1 record splitting. */
+ if (s->mode & SSL_MODE_CBC_RECORD_SPLITTING)
+ len += headerlen + align + 1
+ SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD;
if ((p=OPENSSL_malloc(len)) == NULL)
diff --git a/ssl/s3_cbc.c b/ssl/s3_cbc.c
index e80734e..6a0de9c 100644
--- a/ssl/s3_cbc.c
+++ b/ssl/s3_cbc.c
@@ -52,7 +52,6 @@
#include <assert.h>
-#include <openssl/md5.h>
#include <openssl/obj.h>
#include <openssl/sha.h>
@@ -166,28 +165,6 @@ int tls1_cbc_remove_padding(const SSL* s,
padding_length = rec->data[rec->length-1];
- if (s->options & SSL_OP_TLS_BLOCK_PADDING_BUG)
- {
- /* First packet is even in size, so check */
- if ((memcmp(s->s3->read_sequence, "\0\0\0\0\0\0\0\0",8) == 0) &&
- !(padding_length & 1))
- {
- s->s3->flags|=TLS1_FLAGS_TLS_PADDING_BUG;
- }
- if ((s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG) &&
- padding_length > 0)
- {
- padding_length--;
- }
- }
-
- if (EVP_CIPHER_flags(s->enc_read_ctx->cipher)&EVP_CIPH_FLAG_AEAD_CIPHER)
- {
- /* padding is already verified */
- rec->length -= padding_length + 1;
- return 1;
- }
-
good = constant_time_ge(rec->length, overhead+padding_length);
/* The padding consists of a length byte at the end of the record and
* then that many bytes of padding, all with the same value as the
@@ -334,15 +311,6 @@ void ssl3_cbc_copy_mac(unsigned char* out,
/* These functions serialize the state of a hash and thus perform the standard
* "final" operation without adding the padding and length that such a function
* typically does. */
-static void tls1_md5_final_raw(void* ctx, unsigned char *md_out)
- {
- MD5_CTX *md5 = ctx;
- u32toLE(md5->A, md_out);
- u32toLE(md5->B, md_out);
- u32toLE(md5->C, md_out);
- u32toLE(md5->D, md_out);
- }
-
static void tls1_sha1_final_raw(void* ctx, unsigned char *md_out)
{
SHA_CTX *sha1 = ctx;
@@ -386,12 +354,9 @@ char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx)
{
switch (EVP_MD_CTX_type(ctx))
{
- case NID_md5:
case NID_sha1:
- case NID_sha224:
case NID_sha256:
case NID_sha384:
- case NID_sha512:
return 1;
default:
return 0;
@@ -448,7 +413,6 @@ void ssl3_cbc_digest_record(
/* mdLengthSize is the number of bytes in the length field that terminates
* the hash. */
unsigned md_length_size = 8;
- char length_is_big_endian = 1;
/* This is a, hopefully redundant, check that allows us to forget about
* many possible overflows later in this function. */
@@ -456,26 +420,12 @@ void ssl3_cbc_digest_record(
switch (EVP_MD_CTX_type(ctx))
{
- case NID_md5:
- MD5_Init((MD5_CTX*)md_state.c);
- md_final_raw = tls1_md5_final_raw;
- md_transform = (void(*)(void *ctx, const unsigned char *block)) MD5_Transform;
- md_size = 16;
- sslv3_pad_length = 48;
- length_is_big_endian = 0;
- break;
case NID_sha1:
SHA1_Init((SHA_CTX*)md_state.c);
md_final_raw = tls1_sha1_final_raw;
md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA1_Transform;
md_size = 20;
break;
- case NID_sha224:
- SHA224_Init((SHA256_CTX*)md_state.c);
- md_final_raw = tls1_sha256_final_raw;
- md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA256_Transform;
- md_size = 224/8;
- break;
case NID_sha256:
SHA256_Init((SHA256_CTX*)md_state.c);
md_final_raw = tls1_sha256_final_raw;
@@ -490,14 +440,6 @@ void ssl3_cbc_digest_record(
md_block_size = 128;
md_length_size = 16;
break;
- case NID_sha512:
- SHA512_Init((SHA512_CTX*)md_state.c);
- md_final_raw = tls1_sha512_final_raw;
- md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA512_Transform;
- md_size = 64;
- md_block_size = 128;
- md_length_size = 16;
- break;
default:
/* ssl3_cbc_record_digest_supported should have been
* called first to check that the hash function is
@@ -599,22 +541,11 @@ void ssl3_cbc_digest_record(
md_transform(md_state.c, hmac_pad);
}
- if (length_is_big_endian)
- {
- memset(length_bytes,0,md_length_size-4);
- length_bytes[md_length_size-4] = (unsigned char)(bits>>24);
- length_bytes[md_length_size-3] = (unsigned char)(bits>>16);
- length_bytes[md_length_size-2] = (unsigned char)(bits>>8);
- length_bytes[md_length_size-1] = (unsigned char)bits;
- }
- else
- {
- memset(length_bytes,0,md_length_size);
- length_bytes[md_length_size-5] = (unsigned char)(bits>>24);
- length_bytes[md_length_size-6] = (unsigned char)(bits>>16);
- length_bytes[md_length_size-7] = (unsigned char)(bits>>8);
- length_bytes[md_length_size-8] = (unsigned char)bits;
- }
+ memset(length_bytes,0,md_length_size-4);
+ length_bytes[md_length_size-4] = (unsigned char)(bits>>24);
+ length_bytes[md_length_size-3] = (unsigned char)(bits>>16);
+ length_bytes[md_length_size-2] = (unsigned char)(bits>>8);
+ length_bytes[md_length_size-1] = (unsigned char)bits;
if (k > 0)
{
@@ -622,8 +553,7 @@ void ssl3_cbc_digest_record(
{
/* The SSLv3 header is larger than a single block.
* overhang is the number of bytes beyond a single
- * block that the header consumes: either 7 bytes
- * (SHA1) or 11 bytes (MD5). */
+ * block that the header consumes: 7 bytes (SHA1). */
unsigned overhang = header_length-md_block_size;
md_transform(md_state.c, header);
memcpy(first_block, header + md_block_size, overhang);
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 9c2129c..cb9f95f 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -261,7 +261,7 @@ int ssl3_connect(SSL *s)
case SSL3_ST_CW_CLNT_HELLO_B:
s->shutdown=0;
- ret=ssl3_client_hello(s);
+ ret=ssl3_send_client_hello(s);
if (ret <= 0) goto end;
s->state=SSL3_ST_CR_SRVR_HELLO_A;
s->init_num=0;
@@ -299,7 +299,7 @@ int ssl3_connect(SSL *s)
{
ret=ssl3_get_server_certificate(s);
if (ret <= 0) goto end;
- if (s->tlsext_status_expected)
+ if (s->s3->tmp.certificate_status_expected)
s->state=SSL3_ST_CR_CERT_STATUS_A;
else
s->state=SSL3_ST_CR_KEY_EXCH_A;
@@ -379,7 +379,7 @@ int ssl3_connect(SSL *s)
case SSL3_ST_CW_CERT_VRFY_A:
case SSL3_ST_CW_CERT_VRFY_B:
- ret=ssl3_send_client_verify(s);
+ ret=ssl3_send_cert_verify(s);
if (ret <= 0) goto end;
s->state=SSL3_ST_CW_CHANGE_A;
s->init_num=0;
@@ -395,10 +395,8 @@ int ssl3_connect(SSL *s)
s->state=SSL3_ST_CW_FINISHED_A;
if (s->s3->tlsext_channel_id_valid)
s->state=SSL3_ST_CW_CHANNEL_ID_A;
-# if !defined(OPENSSL_NO_NEXTPROTONEG)
if (s->s3->next_proto_neg_seen)
s->state=SSL3_ST_CW_NEXT_PROTO_A;
-# endif
s->init_num=0;
s->session->cipher=s->s3->tmp.new_cipher;
@@ -417,7 +415,6 @@ int ssl3_connect(SSL *s)
break;
-#if !defined(OPENSSL_NO_NEXTPROTONEG)
case SSL3_ST_CW_NEXT_PROTO_A:
case SSL3_ST_CW_NEXT_PROTO_B:
ret=ssl3_send_next_proto(s);
@@ -427,7 +424,6 @@ int ssl3_connect(SSL *s)
else
s->state=SSL3_ST_CW_FINISHED_A;
break;
-#endif
case SSL3_ST_CW_CHANNEL_ID_A:
case SSL3_ST_CW_CHANNEL_ID_B:
@@ -616,7 +612,7 @@ end:
}
-int ssl3_client_hello(SSL *s)
+int ssl3_send_client_hello(SSL *s)
{
unsigned char *buf;
unsigned char *p,*d;
@@ -647,7 +643,7 @@ int ssl3_client_hello(SSL *s)
*/
if (options & SSL_OP_NO_DTLSv1)
{
- OPENSSL_PUT_ERROR(SSL, ssl3_client_hello, SSL_R_WRONG_SSL_VERSION);
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, SSL_R_WRONG_SSL_VERSION);
goto err;
}
/* Update method so we don't use any DTLS 1.2
@@ -735,7 +731,7 @@ int ssl3_client_hello(SSL *s)
{
if (i > (int)sizeof(s->session->session_id))
{
- OPENSSL_PUT_ERROR(SSL, ssl3_client_hello, ERR_R_INTERNAL_ERROR);
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, ERR_R_INTERNAL_ERROR);
goto err;
}
memcpy(p,s->session->session_id,i);
@@ -747,7 +743,7 @@ int ssl3_client_hello(SSL *s)
{
if ( s->d1->cookie_len > sizeof(s->d1->cookie))
{
- OPENSSL_PUT_ERROR(SSL, ssl3_client_hello, ERR_R_INTERNAL_ERROR);
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, ERR_R_INTERNAL_ERROR);
goto err;
}
*(p++) = s->d1->cookie_len;
@@ -759,7 +755,7 @@ int ssl3_client_hello(SSL *s)
i = ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), &p[2]);
if (i == 0)
{
- OPENSSL_PUT_ERROR(SSL, ssl3_client_hello, SSL_R_NO_CIPHERS_AVAILABLE);
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, SSL_R_NO_CIPHERS_AVAILABLE);
goto err;
}
s2n(i,p);
@@ -772,12 +768,12 @@ int ssl3_client_hello(SSL *s)
/* TLS extensions*/
if (ssl_prepare_clienthello_tlsext(s) <= 0)
{
- OPENSSL_PUT_ERROR(SSL, ssl3_client_hello, SSL_R_CLIENTHELLO_TLSEXT);
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, SSL_R_CLIENTHELLO_TLSEXT);
goto err;
}
if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH, p-buf)) == NULL)
{
- OPENSSL_PUT_ERROR(SSL, ssl3_client_hello, ERR_R_INTERNAL_ERROR);
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -802,12 +798,14 @@ int ssl3_get_server_hello(SSL *s)
CBS server_hello, server_random, session_id;
uint16_t server_version, cipher_suite;
uint8_t compression_method;
+ unsigned long mask_ssl;
n=s->method->ssl_get_message(s,
SSL3_ST_CR_SRVR_HELLO_A,
SSL3_ST_CR_SRVR_HELLO_B,
SSL3_MT_SERVER_HELLO,
20000, /* ?? */
+ SSL_GET_MESSAGE_HASH_MESSAGE,
&ok);
if (!ok) return((int)n);
@@ -916,10 +914,16 @@ int ssl3_get_server_hello(SSL *s)
OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_UNKNOWN_CIPHER_RETURNED);
goto f_err;
}
+ /* ct->mask_ssl was computed from client capabilities. Now
+ * that the final version is known, compute a new mask_ssl. */
+ if (!SSL_USE_TLS1_2_CIPHERS(s))
+ mask_ssl = SSL_TLSV1_2;
+ else
+ mask_ssl = 0;
/* If it is a disabled cipher we didn't send it in client hello,
* so return an error.
*/
- if (c->algorithm_ssl & ct->mask_ssl ||
+ if (c->algorithm_ssl & mask_ssl ||
c->algorithm_mkey & ct->mask_k ||
c->algorithm_auth & ct->mask_a)
{
@@ -1002,6 +1006,7 @@ int ssl3_get_server_certificate(SSL *s)
SSL3_ST_CR_CERT_B,
SSL3_MT_CERTIFICATE,
s->max_cert_list,
+ SSL_GET_MESSAGE_HASH_MESSAGE,
&ok);
if (!ok) return((int)n);
@@ -1145,14 +1150,10 @@ int ssl3_get_server_key_exchange(SSL *s)
EVP_PKEY *pkey=NULL;
const EVP_MD *md = NULL;
RSA *rsa=NULL;
-#ifndef OPENSSL_NO_DH
DH *dh=NULL;
-#endif
-#ifndef OPENSSL_NO_ECDH
EC_KEY *ecdh = NULL;
BN_CTX *bn_ctx = NULL;
EC_POINT *srvr_ecpoint = NULL;
-#endif
CBS server_key_exchange, server_key_exchange_orig, parameter;
/* use same message size as in ssl3_get_certificate_request()
@@ -1162,6 +1163,7 @@ int ssl3_get_server_key_exchange(SSL *s)
SSL3_ST_CR_KEY_EXCH_B,
-1,
s->max_cert_list,
+ SSL_GET_MESSAGE_HASH_MESSAGE,
&ok);
if (!ok) return((int)n);
@@ -1207,20 +1209,16 @@ int ssl3_get_server_key_exchange(SSL *s)
RSA_free(s->session->sess_cert->peer_rsa_tmp);
s->session->sess_cert->peer_rsa_tmp=NULL;
}
-#ifndef OPENSSL_NO_DH
if (s->session->sess_cert->peer_dh_tmp)
{
DH_free(s->session->sess_cert->peer_dh_tmp);
s->session->sess_cert->peer_dh_tmp=NULL;
}
-#endif
-#ifndef OPENSSL_NO_ECDH
if (s->session->sess_cert->peer_ecdh_tmp)
{
EC_KEY_free(s->session->sess_cert->peer_ecdh_tmp);
s->session->sess_cert->peer_ecdh_tmp=NULL;
}
-#endif
}
else
{
@@ -1269,8 +1267,7 @@ int ssl3_get_server_key_exchange(SSL *s)
}
}
- if (0) {}
- else if (alg_k & SSL_kRSA)
+ if (alg_k & SSL_kRSA)
{
CBS rsa_modulus, rsa_exponent;
@@ -1318,7 +1315,6 @@ int ssl3_get_server_key_exchange(SSL *s)
s->session->sess_cert->peer_rsa_tmp=rsa;
rsa=NULL;
}
-#ifndef OPENSSL_NO_DH
else if (alg_k & SSL_kEDH)
{
CBS dh_p, dh_g, dh_Ys;
@@ -1370,9 +1366,7 @@ int ssl3_get_server_key_exchange(SSL *s)
s->session->sess_cert->peer_dh_tmp=dh;
dh=NULL;
}
-#endif /* !OPENSSL_NO_DH */
-#ifndef OPENSSL_NO_ECDH
else if (alg_k & SSL_kEECDH)
{
uint16_t curve_id;
@@ -1450,10 +1444,8 @@ int ssl3_get_server_key_exchange(SSL *s)
if (0) ;
else if (alg_a & SSL_aRSA)
pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
-#ifndef OPENSSL_NO_ECDSA
else if (alg_a & SSL_aECDSA)
pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_ECC].x509);
-#endif
/* else anonymous ECDH, so no certificate or pkey. */
EC_KEY_set_public_key(ecdh, srvr_ecpoint);
s->session->sess_cert->peer_ecdh_tmp=ecdh;
@@ -1463,7 +1455,6 @@ int ssl3_get_server_key_exchange(SSL *s)
EC_POINT_free(srvr_ecpoint);
srvr_ecpoint = NULL;
}
-#endif /* !OPENSSL_NO_ECDH */
else if (!(alg_k & SSL_kPSK))
{
@@ -1573,16 +1564,12 @@ err:
EVP_PKEY_free(pkey);
if (rsa != NULL)
RSA_free(rsa);
-#ifndef OPENSSL_NO_DH
if (dh != NULL)
DH_free(dh);
-#endif
-#ifndef OPENSSL_NO_ECDH
BN_CTX_free(bn_ctx);
EC_POINT_free(srvr_ecpoint);
if (ecdh != NULL)
EC_KEY_free(ecdh);
-#endif
EVP_MD_CTX_cleanup(&md_ctx);
return(-1);
}
@@ -1609,6 +1596,7 @@ int ssl3_get_certificate_request(SSL *s)
SSL3_ST_CR_CERT_REQ_B,
-1,
s->max_cert_list,
+ SSL_GET_MESSAGE_HASH_MESSAGE,
&ok);
if (!ok) return((int)n);
@@ -1762,6 +1750,7 @@ int ssl3_get_new_session_ticket(SSL *s)
SSL3_ST_CR_SESSION_TICKET_B,
SSL3_MT_NEWSESSION_TICKET,
16384,
+ SSL_GET_MESSAGE_HASH_MESSAGE,
&ok);
if (!ok)
@@ -1816,13 +1805,13 @@ int ssl3_get_cert_status(SSL *s)
long n;
CBS certificate_status, ocsp_response;
uint8_t status_type;
- size_t resplen;
n=s->method->ssl_get_message(s,
SSL3_ST_CR_CERT_STATUS_A,
SSL3_ST_CR_CERT_STATUS_B,
SSL3_MT_CERTIFICATE_STATUS,
16384,
+ SSL_GET_MESSAGE_HASH_MESSAGE,
&ok);
if (!ok) return((int)n);
@@ -1839,34 +1828,13 @@ int ssl3_get_cert_status(SSL *s)
goto f_err;
}
- /* TODO(davidben): Make tlsext_ocsp_resplen a
- * size_t. Currently it uses -1 to signal no response. The
- * spec does not allow ocsp_response to be zero-length, so
- * using 0 should be fine. */
- if (!CBS_stow(&ocsp_response, &s->tlsext_ocsp_resp, &resplen))
+ if (!CBS_stow(&ocsp_response,
+ &s->session->ocsp_response, &s->session->ocsp_response_length))
{
al = SSL_AD_INTERNAL_ERROR;
OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_status, ERR_R_MALLOC_FAILURE);
goto f_err;
}
- s->tlsext_ocsp_resplen = resplen;
- if (s->ctx->tlsext_status_cb)
- {
- int ret;
- ret = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
- if (ret == 0)
- {
- al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_status, SSL_R_INVALID_STATUS_RESPONSE);
- goto f_err;
- }
- if (ret < 0)
- {
- al = SSL_AD_INTERNAL_ERROR;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_status, ERR_R_MALLOC_FAILURE);
- goto f_err;
- }
- }
return 1;
f_err:
ssl3_send_alert(s,SSL3_AL_FATAL,al);
@@ -1883,6 +1851,7 @@ int ssl3_get_server_done(SSL *s)
SSL3_ST_CR_SRVR_DONE_B,
SSL3_MT_SERVER_DONE,
30, /* should be very small, like 0 :-) */
+ SSL_GET_MESSAGE_HASH_MESSAGE,
&ok);
if (!ok) return((int)n);
@@ -1906,7 +1875,6 @@ int ssl3_send_client_key_exchange(SSL *s)
unsigned long alg_a;
unsigned char *q;
EVP_PKEY *pkey=NULL;
-#ifndef OPENSSL_NO_ECDH
EC_KEY *clnt_ecdh = NULL;
const EC_POINT *srvr_ecpoint = NULL;
EVP_PKEY *srvr_pub_pkey = NULL;
@@ -1915,7 +1883,6 @@ int ssl3_send_client_key_exchange(SSL *s)
BN_CTX * bn_ctx = NULL;
unsigned int psk_len = 0;
unsigned char psk[PSK_MAX_PSK_LEN];
-#endif /* OPENSSL_NO_ECDH */
if (s->state == SSL3_ST_CW_KEY_EXCH_A)
{
@@ -2001,9 +1968,7 @@ int ssl3_send_client_key_exchange(SSL *s)
}
}
- /* Fool emacs indentation */
- if (0) {}
- else if (alg_k & SSL_kRSA)
+ if (alg_k & SSL_kRSA)
{
RSA *rsa;
unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
@@ -2050,6 +2015,13 @@ int ssl3_send_client_key_exchange(SSL *s)
goto err;
}
+ /* Log the premaster secret, if logging is enabled. */
+ if (!ssl_ctx_log_rsa_client_key_exchange(s->ctx,
+ p, n, tmp_buf, sizeof(tmp_buf)))
+ {
+ goto err;
+ }
+
/* Fix buf for TLS and beyond */
if (s->version > SSL3_VERSION)
{
@@ -2063,7 +2035,6 @@ int ssl3_send_client_key_exchange(SSL *s)
tmp_buf,sizeof tmp_buf);
OPENSSL_cleanse(tmp_buf,sizeof tmp_buf);
}
-#ifndef OPENSSL_NO_DH
else if (alg_k & SSL_kEDH)
{
DH *dh_srvr,*dh_clnt;
@@ -2124,9 +2095,7 @@ int ssl3_send_client_key_exchange(SSL *s)
/* perhaps clean things up a bit EAY EAY EAY EAY*/
}
-#endif
-#ifndef OPENSSL_NO_ECDH
else if (alg_k & SSL_kEECDH)
{
const EC_GROUP *srvr_group = NULL;
@@ -2274,12 +2243,10 @@ int ssl3_send_client_key_exchange(SSL *s)
/* Free allocated memory */
BN_CTX_free(bn_ctx);
- if (encodedPoint != NULL) OPENSSL_free(encodedPoint);
- if (clnt_ecdh != NULL)
- EC_KEY_free(clnt_ecdh);
+ OPENSSL_free(encodedPoint);
+ EC_KEY_free(clnt_ecdh);
EVP_PKEY_free(srvr_pub_pkey);
}
-#endif /* !OPENSSL_NO_ECDH */
else if (!(alg_k & SSL_kPSK) || ((alg_k & SSL_kPSK) && !(alg_a & SSL_aPSK)))
{
ssl3_send_alert(s, SSL3_AL_FATAL,
@@ -2295,82 +2262,52 @@ int ssl3_send_client_key_exchange(SSL *s)
/* SSL3_ST_CW_KEY_EXCH_B */
return ssl_do_write(s);
err:
-#ifndef OPENSSL_NO_ECDH
BN_CTX_free(bn_ctx);
if (encodedPoint != NULL) OPENSSL_free(encodedPoint);
if (clnt_ecdh != NULL)
EC_KEY_free(clnt_ecdh);
EVP_PKEY_free(srvr_pub_pkey);
-#endif
return(-1);
}
-int ssl3_send_client_verify(SSL *s)
+int ssl3_send_cert_verify(SSL *s)
{
unsigned char *buf, *p;
- const EVP_MD *md;
+ const EVP_MD *md = NULL;
uint8_t digest[EVP_MAX_MD_SIZE];
- unsigned digest_length;
+ size_t digest_length;
EVP_PKEY *pkey;
EVP_PKEY_CTX *pctx = NULL;
- EVP_MD_CTX mctx;
size_t signature_length = 0;
unsigned long n = 0;
- EVP_MD_CTX_init(&mctx);
buf=(unsigned char *)s->init_buf->data;
if (s->state == SSL3_ST_CW_CERT_VRFY_A)
{
p= ssl_handshake_start(s);
pkey = s->cert->key->privatekey;
- /* For TLS v1.2 send signature algorithm and signature using
- * agreed digest and cached handshake records. Otherwise, use
- * SHA1 or MD5 + SHA1 depending on key type.
- */
+
+ /* Write out the digest type if needbe. */
if (SSL_USE_SIGALGS(s))
{
- const uint8_t *hdata;
- size_t hdatalen;
md = s->cert->key->digest;
- if (!BIO_mem_contents(s->s3->handshake_buffer, &hdata, &hdatalen) ||
- !tls12_get_sigandhash(p, pkey, md))
+ if (!tls12_get_sigandhash(p, pkey, md))
{
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_verify, ERR_R_INTERNAL_ERROR);
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_cert_verify, ERR_R_INTERNAL_ERROR);
goto err;
}
p += 2;
n += 2;
- if (!EVP_DigestInit_ex(&mctx, md, NULL)
- || !EVP_DigestUpdate(&mctx, hdata, hdatalen)
- || !EVP_DigestFinal(&mctx, digest, &digest_length))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_verify, ERR_R_EVP_LIB);
- goto err;
- }
}
- else if (pkey->type == EVP_PKEY_RSA)
- {
- s->method->ssl3_enc->cert_verify_mac(s, NID_md5, digest);
- s->method->ssl3_enc->cert_verify_mac(s,
- NID_sha1, &digest[MD5_DIGEST_LENGTH]);
- digest_length = MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH;
- /* Using a NULL signature MD makes EVP_PKEY_sign perform
- * a raw RSA signature, rather than wrapping in a
- * DigestInfo. */
- md = NULL;
- }
- else if (pkey->type == EVP_PKEY_EC)
- {
- s->method->ssl3_enc->cert_verify_mac(s, NID_sha1, digest);
- digest_length = SHA_DIGEST_LENGTH;
- md = EVP_sha1();
- }
- else
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_verify, ERR_R_INTERNAL_ERROR);
+
+ /* Compute the digest. */
+ if (!ssl3_cert_verify_hash(s, digest, &digest_length, &md, pkey))
+ goto err;
+
+ /* The handshake buffer is no longer necessary. */
+ if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s))
goto err;
- }
/* Sign the digest. */
pctx = EVP_PKEY_CTX_new(pkey, NULL);
@@ -2378,47 +2315,37 @@ int ssl3_send_client_verify(SSL *s)
goto err;
/* Initialize the EVP_PKEY_CTX and determine the size of the signature. */
- if (EVP_PKEY_sign_init(pctx) != 1 ||
- EVP_PKEY_CTX_set_signature_md(pctx, md) != 1 ||
- EVP_PKEY_sign(pctx, NULL, &signature_length,
- digest, digest_length) != 1)
+ if (!EVP_PKEY_sign_init(pctx) ||
+ !EVP_PKEY_CTX_set_signature_md(pctx, md) ||
+ !EVP_PKEY_sign(pctx, NULL, &signature_length,
+ digest, digest_length))
{
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_verify, ERR_R_EVP_LIB);
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_cert_verify, ERR_R_EVP_LIB);
goto err;
}
if (p + 2 + signature_length > buf + SSL3_RT_MAX_PLAIN_LENGTH)
{
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_verify, SSL_R_DATA_LENGTH_TOO_LONG);
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_cert_verify, SSL_R_DATA_LENGTH_TOO_LONG);
goto err;
}
- if (EVP_PKEY_sign(pctx, &p[2], &signature_length,
- digest, digest_length) != 1)
+ if (!EVP_PKEY_sign(pctx, &p[2], &signature_length,
+ digest, digest_length))
{
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_verify, ERR_R_EVP_LIB);
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_cert_verify, ERR_R_EVP_LIB);
goto err;
}
s2n(signature_length, p);
n += signature_length + 2;
- /* Now that client auth is completed, we no longer need cached
- * handshake records and can digest them. */
- if (SSL_USE_SIGALGS(s))
- {
- if (!ssl3_digest_cached_records(s))
- goto err;
- }
-
ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_VERIFY, n);
s->state=SSL3_ST_CW_CERT_VRFY_B;
}
- EVP_MD_CTX_cleanup(&mctx);
EVP_PKEY_CTX_free(pctx);
return ssl_do_write(s);
err:
- EVP_MD_CTX_cleanup(&mctx);
EVP_PKEY_CTX_free(pctx);
return(-1);
}
@@ -2538,9 +2465,7 @@ int ssl3_check_cert_and_algorithm(SSL *s)
EVP_PKEY *pkey=NULL;
SESS_CERT *sc;
RSA *rsa;
-#ifndef OPENSSL_NO_DH
DH *dh;
-#endif
/* we don't have a certificate */
if (!ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher))
@@ -2557,14 +2482,11 @@ int ssl3_check_cert_and_algorithm(SSL *s)
}
rsa=s->session->sess_cert->peer_rsa_tmp;
-#ifndef OPENSSL_NO_DH
dh=s->session->sess_cert->peer_dh_tmp;
-#endif
/* This is the passed certificate */
idx=sc->peer_cert_type;
-#ifndef OPENSSL_NO_ECDH
if (idx == SSL_PKEY_ECC)
{
if (ssl_check_srvr_ecc_cert_and_alg(sc->peer_pkeys[idx].x509,
@@ -2583,7 +2505,6 @@ int ssl3_check_cert_and_algorithm(SSL *s)
OPENSSL_PUT_ERROR(SSL, ssl3_check_cert_and_algorithm, SSL_R_MISSING_ECDSA_SIGNING_CERT);
goto f_err;
}
-#endif
pkey=X509_get_pubkey(sc->peer_pkeys[idx].x509);
i=X509_certificate_type(sc->peer_pkeys[idx].x509,pkey);
EVP_PKEY_free(pkey);
@@ -2601,14 +2522,12 @@ int ssl3_check_cert_and_algorithm(SSL *s)
OPENSSL_PUT_ERROR(SSL, ssl3_check_cert_and_algorithm, SSL_R_MISSING_RSA_ENCRYPTING_CERT);
goto f_err;
}
-#ifndef OPENSSL_NO_DH
if ((alg_k & SSL_kEDH) &&
!(has_bits(i,EVP_PK_DH|EVP_PKT_EXCH) || (dh != NULL)))
{
OPENSSL_PUT_ERROR(SSL, ssl3_check_cert_and_algorithm, SSL_R_MISSING_DH_KEY);
goto f_err;
}
-#endif
return(1);
f_err:
@@ -2617,7 +2536,6 @@ err:
return(0);
}
-# if !defined(OPENSSL_NO_NEXTPROTONEG)
int ssl3_send_next_proto(SSL *s)
{
unsigned int len, padding_len;
@@ -2642,7 +2560,6 @@ int ssl3_send_next_proto(SSL *s)
return ssl3_do_write(s, SSL3_RT_HANDSHAKE);
}
-# endif /* !OPENSSL_NO_NEXTPROTONEG */
int ssl3_send_channel_id(SSL *s)
{
diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c
index b9e4026..d574b25 100644
--- a/ssl/s3_enc.c
+++ b/ssl/s3_enc.c
@@ -369,10 +369,8 @@ int ssl3_setup_key_block(SSL *s)
if (s->session->cipher != NULL)
{
-#ifndef OPENSSL_NO_RC4
if (s->session->cipher->algorithm_enc == SSL_RC4)
s->s3->need_record_splitting = 0;
-#endif
}
}
@@ -499,7 +497,7 @@ void ssl3_free_digest_list(SSL *s)
void ssl3_finish_mac(SSL *s, const unsigned char *buf, int len)
{
- if (s->s3->handshake_buffer && !(s->s3->flags & TLS1_FLAGS_KEEP_HANDSHAKE))
+ if (s->s3->handshake_buffer)
{
BIO_write (s->s3->handshake_buffer,(void *)buf,len);
}
@@ -546,12 +544,9 @@ int ssl3_digest_cached_records(SSL *s)
s->s3->handshake_dgst[i]=NULL;
}
}
- if (!(s->s3->flags & TLS1_FLAGS_KEEP_HANDSHAKE))
- {
- /* Free handshake_buffer BIO */
- BIO_free(s->s3->handshake_buffer);
- s->s3->handshake_buffer = NULL;
- }
+ /* Free handshake_buffer BIO */
+ BIO_free(s->s3->handshake_buffer);
+ s->s3->handshake_buffer = NULL;
return 1;
}
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index cef94b1..5a1b48d 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -178,7 +178,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_RC4,
SSL_MD5,
SSL_SSLV3,
- SSL_NOT_EXP|SSL_MEDIUM,
+ SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF|SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD,
128,
128,
@@ -194,7 +194,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_RC4,
SSL_SHA1,
SSL_SSLV3,
- SSL_NOT_EXP|SSL_MEDIUM,
+ SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -210,7 +210,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_3DES,
SSL_SHA1,
SSL_SSLV3,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
112,
168,
@@ -228,7 +228,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_RC4,
SSL_MD5,
SSL_SSLV3,
- SSL_NOT_EXP|SSL_MEDIUM,
+ SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -245,7 +245,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -260,7 +260,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -275,7 +275,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -291,7 +291,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
256,
256,
@@ -307,7 +307,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
256,
256,
@@ -323,7 +323,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
256,
256,
@@ -340,7 +340,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128,
SSL_SHA256,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -356,7 +356,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256,
SSL_SHA256,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
256,
256,
@@ -374,7 +374,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128,
SSL_SHA256,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -390,7 +390,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256,
SSL_SHA256,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
256,
256,
@@ -406,7 +406,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128,
SSL_SHA256,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -422,7 +422,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256,
SSL_SHA256,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
256,
256,
@@ -439,7 +439,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_RC4,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_MEDIUM,
+ SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -455,7 +455,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -471,7 +471,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
256,
256,
@@ -489,7 +489,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128GCM,
SSL_AEAD,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
128,
128,
@@ -505,7 +505,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256GCM,
SSL_AEAD,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|
SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
256,
@@ -522,7 +522,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128GCM,
SSL_AEAD,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
128,
128,
@@ -538,7 +538,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256GCM,
SSL_AEAD,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|
SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
256,
@@ -555,7 +555,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128GCM,
SSL_AEAD,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
128,
128,
@@ -571,14 +571,13 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256GCM,
SSL_AEAD,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|
SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
256,
256,
},
-#ifndef OPENSSL_NO_ECDH
/* Cipher C007 */
{
1,
@@ -589,7 +588,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_RC4,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_MEDIUM,
+ SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -605,7 +604,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -621,7 +620,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
256,
256,
@@ -637,7 +636,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_RC4,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_MEDIUM,
+ SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -653,7 +652,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -669,7 +668,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
256,
256,
@@ -685,7 +684,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_RC4,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_MEDIUM,
+ SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -701,7 +700,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -717,14 +716,12 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
256,
256,
},
-#endif /* OPENSSL_NO_ECDH */
-#ifndef OPENSSL_NO_ECDH
/* HMAC based TLS v1.2 ciphersuites from RFC5289 */
@@ -738,7 +735,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128,
SSL_SHA256,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
128,
128,
@@ -754,7 +751,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256,
SSL_SHA384,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384,
256,
256,
@@ -770,7 +767,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128,
SSL_SHA256,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
128,
128,
@@ -786,7 +783,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256,
SSL_SHA384,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384,
256,
256,
@@ -804,7 +801,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128GCM,
SSL_AEAD,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
128,
128,
@@ -820,7 +817,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256GCM,
SSL_AEAD,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|
SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
256,
@@ -837,7 +834,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128GCM,
SSL_AEAD,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
128,
128,
@@ -853,7 +850,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256GCM,
SSL_AEAD,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|
SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
256,
@@ -871,14 +868,13 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128GCM,
SSL_AEAD,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH,
+ SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|
SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
128,
128,
},
-#endif /* OPENSSL_NO_ECDH */
{
1,
@@ -889,7 +885,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_CHACHA20POLY1305,
SSL_AEAD,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH,
+ SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(0),
256,
0,
@@ -904,7 +900,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_CHACHA20POLY1305,
SSL_AEAD,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH,
+ SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(0),
256,
0,
@@ -919,7 +915,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_CHACHA20POLY1305,
SSL_AEAD,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH,
+ SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(0),
256,
0,
@@ -1014,14 +1010,10 @@ void ssl3_free(SSL *s)
ssl3_release_read_buffer(s);
if (s->s3->wbuf.buf != NULL)
ssl3_release_write_buffer(s);
-#ifndef OPENSSL_NO_DH
if (s->s3->tmp.dh != NULL)
DH_free(s->s3->tmp.dh);
-#endif
-#ifndef OPENSSL_NO_ECDH
if (s->s3->tmp.ecdh != NULL)
EC_KEY_free(s->s3->tmp.ecdh);
-#endif
if (s->s3->tmp.ca_names != NULL)
sk_X509_NAME_pop_free(s->s3->tmp.ca_names,X509_NAME_free);
@@ -1052,20 +1044,16 @@ void ssl3_clear(SSL *s)
OPENSSL_free(s->s3->tmp.certificate_types);
s->s3->tmp.num_certificate_types = 0;
-#ifndef OPENSSL_NO_DH
if (s->s3->tmp.dh != NULL)
{
DH_free(s->s3->tmp.dh);
s->s3->tmp.dh = NULL;
}
-#endif
-#ifndef OPENSSL_NO_ECDH
if (s->s3->tmp.ecdh != NULL)
{
EC_KEY_free(s->s3->tmp.ecdh);
s->s3->tmp.ecdh = NULL;
}
-#endif
rp = s->s3->rbuf.buf;
wp = s->s3->wbuf.buf;
rlen = s->s3->rbuf.len;
@@ -1100,14 +1088,12 @@ void ssl3_clear(SSL *s)
s->s3->in_read_app_data=0;
s->version = s->method->version;
-#if !defined(OPENSSL_NO_NEXTPROTONEG)
if (s->next_proto_negotiated)
{
OPENSSL_free(s->next_proto_negotiated);
s->next_proto_negotiated = NULL;
s->next_proto_negotiated_len = 0;
}
-#endif
s->s3->tlsext_channel_id_valid = 0;
}
@@ -1118,14 +1104,10 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
{
int ret=0;
- if (
- cmd == SSL_CTRL_SET_TMP_RSA ||
+ if (cmd == SSL_CTRL_SET_TMP_RSA ||
cmd == SSL_CTRL_SET_TMP_RSA_CB ||
-#ifndef OPENSSL_NO_DSA
cmd == SSL_CTRL_SET_TMP_DH ||
- cmd == SSL_CTRL_SET_TMP_DH_CB ||
-#endif
- 0)
+ cmd == SSL_CTRL_SET_TMP_DH_CB)
{
if (!ssl_cert_inst(&s->cert))
{
@@ -1168,7 +1150,6 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
return(ret);
}
break;
-#ifndef OPENSSL_NO_DH
case SSL_CTRL_SET_TMP_DH:
{
DH *dh = (DH *)parg;
@@ -1203,8 +1184,6 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
return(ret);
}
break;
-#endif
-#ifndef OPENSSL_NO_ECDH
case SSL_CTRL_SET_TMP_ECDH:
{
EC_KEY *ecdh = NULL;
@@ -1241,7 +1220,6 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
return(ret);
}
break;
-#endif /* !OPENSSL_NO_ECDH */
case SSL_CTRL_SET_TLSEXT_HOSTNAME:
if (larg == TLSEXT_NAMETYPE_host_name)
{
@@ -1274,44 +1252,6 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
ret = 1;
break;
- case SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE:
- s->tlsext_status_type=larg;
- ret = 1;
- break;
-
- case SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS:
- *(STACK_OF(X509_EXTENSION) **)parg = s->tlsext_ocsp_exts;
- ret = 1;
- break;
-
- case SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS:
- s->tlsext_ocsp_exts = parg;
- ret = 1;
- break;
-
- case SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS:
- *(STACK_OF(OCSP_RESPID) **)parg = s->tlsext_ocsp_ids;
- ret = 1;
- break;
-
- case SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS:
- s->tlsext_ocsp_ids = parg;
- ret = 1;
- break;
-
- case SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP:
- *(unsigned char **)parg = s->tlsext_ocsp_resp;
- return s->tlsext_ocsp_resplen;
-
- case SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP:
- if (s->tlsext_ocsp_resp)
- OPENSSL_free(s->tlsext_ocsp_resp);
- s->tlsext_ocsp_resp = parg;
- s->tlsext_ocsp_resplen = larg;
- ret = 1;
- break;
-
-
case SSL_CTRL_CHAIN:
if (larg)
return ssl_cert_set1_chain(s->cert,
@@ -1333,7 +1273,6 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
case SSL_CTRL_SELECT_CURRENT_CERT:
return ssl_cert_select_current(s->cert, (X509 *)parg);
-#ifndef OPENSSL_NO_EC
case SSL_CTRL_GET_CURVES:
{
const uint16_t *clist;
@@ -1367,7 +1306,6 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
case SSL_CTRL_SET_ECDH_AUTO:
s->cert->ecdh_tmp_auto = larg;
return 1;
-#endif
case SSL_CTRL_SET_SIGALGS:
return tls1_set_sigalgs(s->cert, parg, larg, 0);
@@ -1426,25 +1364,17 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
EVP_PKEY *ptmp;
int rv = 0;
sc = s->session->sess_cert;
-#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DH) && !defined(OPENSSL_NO_EC)
- if (!sc->peer_rsa_tmp && !sc->peer_dh_tmp
- && !sc->peer_ecdh_tmp)
+ if (!sc->peer_rsa_tmp && !sc->peer_dh_tmp && !sc->peer_ecdh_tmp)
return 0;
-#endif
ptmp = EVP_PKEY_new();
if (!ptmp)
return 0;
- if (0);
- else if (sc->peer_rsa_tmp)
+ if (sc->peer_rsa_tmp)
rv = EVP_PKEY_set1_RSA(ptmp, sc->peer_rsa_tmp);
-#ifndef OPENSSL_NO_DH
else if (sc->peer_dh_tmp)
rv = EVP_PKEY_set1_DH(ptmp, sc->peer_dh_tmp);
-#endif
-#ifndef OPENSSL_NO_ECDH
else if (sc->peer_ecdh_tmp)
rv = EVP_PKEY_set1_EC_KEY(ptmp, sc->peer_ecdh_tmp);
-#endif
if (rv)
{
*(EVP_PKEY **)parg = ptmp;
@@ -1453,7 +1383,6 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
EVP_PKEY_free(ptmp);
return 0;
}
-#ifndef OPENSSL_NO_EC
case SSL_CTRL_GET_EC_POINT_FORMATS:
{
SSL_SESSION *sess = s->session;
@@ -1463,7 +1392,6 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
*pformat = sess->tlsext_ecpointformatlist;
return (int)sess->tlsext_ecpointformatlist_length;
}
-#endif
case SSL_CTRL_CHANNEL_ID:
s->tlsext_channel_id_enabled = 1;
@@ -1510,12 +1438,7 @@ long ssl3_callback_ctrl(SSL *s, int cmd, void (*fp)(void))
{
int ret=0;
- if (
- cmd == SSL_CTRL_SET_TMP_RSA_CB ||
-#ifndef OPENSSL_NO_DSA
- cmd == SSL_CTRL_SET_TMP_DH_CB ||
-#endif
- 0)
+ if (cmd == SSL_CTRL_SET_TMP_RSA_CB || cmd == SSL_CTRL_SET_TMP_DH_CB)
{
if (!ssl_cert_inst(&s->cert))
{
@@ -1529,20 +1452,16 @@ long ssl3_callback_ctrl(SSL *s, int cmd, void (*fp)(void))
case SSL_CTRL_SET_TMP_RSA_CB:
/* Ignore the callback; temporary RSA keys are never used. */
break;
-#ifndef OPENSSL_NO_DH
case SSL_CTRL_SET_TMP_DH_CB:
{
s->cert->dh_tmp_cb = (DH *(*)(SSL *, int, int))fp;
}
break;
-#endif
-#ifndef OPENSSL_NO_ECDH
case SSL_CTRL_SET_TMP_ECDH_CB:
{
s->cert->ecdh_tmp_cb = (EC_KEY *(*)(SSL *, int, int))fp;
}
break;
-#endif
case SSL_CTRL_SET_TLSEXT_DEBUG_CB:
s->tlsext_debug_cb=(void (*)(SSL *,int ,int,
unsigned char *, int, void *))fp;
@@ -1573,7 +1492,6 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
return(0);
}
break;
-#ifndef OPENSSL_NO_DH
case SSL_CTRL_SET_TMP_DH:
{
DH *new=NULL,*dh;
@@ -1605,8 +1523,6 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
return(0);
}
break;
-#endif
-#ifndef OPENSSL_NO_ECDH
case SSL_CTRL_SET_TMP_ECDH:
{
EC_KEY *ecdh = NULL;
@@ -1646,7 +1562,6 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
return(0);
}
break;
-#endif /* !OPENSSL_NO_ECDH */
case SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG:
ctx->tlsext_servername_arg=parg;
break;
@@ -1681,7 +1596,6 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
return 1;
break;
-#ifndef OPENSSL_NO_EC
case SSL_CTRL_SET_CURVES:
return tls1_set_curves(&ctx->tlsext_ellipticcurvelist,
&ctx->tlsext_ellipticcurvelist_length,
@@ -1690,7 +1604,6 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
case SSL_CTRL_SET_ECDH_AUTO:
ctx->cert->ecdh_tmp_auto = larg;
return 1;
-#endif
case SSL_CTRL_SET_SIGALGS:
return tls1_set_sigalgs(ctx->cert, parg, larg, 0);
@@ -1792,20 +1705,16 @@ long ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp)(void))
case SSL_CTRL_SET_TMP_RSA_CB:
/* Ignore the callback; temporary RSA keys are never used. */
break;
-#ifndef OPENSSL_NO_DH
case SSL_CTRL_SET_TMP_DH_CB:
{
cert->dh_tmp_cb = (DH *(*)(SSL *, int, int))fp;
}
break;
-#endif
-#ifndef OPENSSL_NO_ECDH
case SSL_CTRL_SET_TMP_ECDH_CB:
{
cert->ecdh_tmp_cb = (EC_KEY *(*)(SSL *, int, int))fp;
}
break;
-#endif
case SSL_CTRL_SET_TLSEXT_SERVERNAME_CB:
ctx->tlsext_servername_callback=(int (*)(SSL *,int *,void *))fp;
break;
@@ -1959,12 +1868,10 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
c->name);
#endif
-#ifndef OPENSSL_NO_EC
/* if we are considering an ECC cipher suite that uses
* an ephemeral EC key check it */
if (alg_k & SSL_kEECDH)
ok = ok && tls1_check_ec_tmp_key(s, c->id);
-#endif /* OPENSSL_NO_EC */
if (ok && sk_SSL_CIPHER_find(allow, &cipher_index, c))
{
@@ -2004,9 +1911,7 @@ int ssl3_get_req_cert_type(SSL *s, unsigned char *p)
const unsigned char *sig;
size_t i, siglen;
int have_rsa_sign = 0;
-#ifndef OPENSSL_NO_ECDSA
int have_ecdsa_sign = 0;
-#endif
/* If we have custom certificate types set, use them */
if (s->cert->client_certificate_types)
@@ -2025,18 +1930,15 @@ int ssl3_get_req_cert_type(SSL *s, unsigned char *p)
have_rsa_sign = 1;
break;
-#ifndef OPENSSL_NO_ECDSA
case TLSEXT_signature_ecdsa:
have_ecdsa_sign = 1;
break;
-#endif
}
}
if (have_rsa_sign)
p[ret++]=SSL3_CT_RSA_SIGN;
-#ifndef OPENSSL_NO_ECDSA
/* ECDSA certs can be used with RSA cipher suites as well
* so we don't need to check for SSL_kECDH or SSL_kEECDH
*/
@@ -2045,7 +1947,6 @@ int ssl3_get_req_cert_type(SSL *s, unsigned char *p)
if (have_ecdsa_sign)
p[ret++]=TLS_CT_ECDSA_SIGN;
}
-#endif
return(ret);
}
diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c
index 393d883..f5079a1 100644
--- a/ssl/s3_pkt.c
+++ b/ssl/s3_pkt.c
@@ -311,7 +311,7 @@ static int ssl3_get_record(SSL *s)
extra=0;
if (extra && !s->s3->init_extra)
{
- /* An application error: SLS_OP_MICROSOFT_BIG_SSLV3_BUFFER
+ /* An application error: SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
* set after ssl3_setup_buffers() was done */
OPENSSL_PUT_ERROR(SSL, ssl3_get_record, ERR_R_INTERNAL_ERROR);
return -1;
@@ -760,9 +760,6 @@ static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
if (eivlen <= 1)
eivlen = 0;
}
- /* Need explicit part of IV for GCM mode */
- else if (mode == EVP_CIPH_GCM_MODE)
- eivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN;
else
eivlen = 0;
}
@@ -1426,8 +1423,6 @@ err:
int ssl3_do_change_cipher_spec(SSL *s)
{
int i;
- const char *sender;
- int slen;
if (s->state & SSL_ST_ACCEPT)
i=SSL3_CHANGE_CIPHER_SERVER_READ;
@@ -1450,29 +1445,6 @@ int ssl3_do_change_cipher_spec(SSL *s)
if (!s->method->ssl3_enc->change_cipher_state(s,i))
return(0);
- /* we have to record the message digest at
- * this point so we can get it before we read
- * the finished message */
- if (s->state & SSL_ST_CONNECT)
- {
- sender=s->method->ssl3_enc->server_finished_label;
- slen=s->method->ssl3_enc->server_finished_label_len;
- }
- else
- {
- sender=s->method->ssl3_enc->client_finished_label;
- slen=s->method->ssl3_enc->client_finished_label_len;
- }
-
- i = s->method->ssl3_enc->final_finish_mac(s,
- sender,slen,s->s3->tmp.peer_finish_md);
- if (i == 0)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_do_change_cipher_spec, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- s->s3->tmp.peer_finish_md_len = i;
-
return(1);
}
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index 9ec6885..0e9c7d5 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -148,6 +148,7 @@
#define NETSCAPE_HANG_BUG
+#include <assert.h>
#include <stdio.h>
#include <string.h>
@@ -351,7 +352,7 @@ int ssl3_accept(SSL *s)
{
ret=ssl3_send_server_certificate(s);
if (ret <= 0) goto end;
- if (s->tlsext_status_expected)
+ if (s->s3->tmp.certificate_status_expected)
s->state=SSL3_ST_SW_CERT_STATUS_A;
else
s->state=SSL3_ST_SW_KEY_EXCH_A;
@@ -485,54 +486,6 @@ int ssl3_accept(SSL *s)
goto end;
s->state=SSL3_ST_SR_CERT_VRFY_A;
s->init_num=0;
-
- /* TODO(davidben): These two blocks are different
- * between SSL and DTLS. Resolve the difference and code
- * duplication. */
- if (SSL_USE_SIGALGS(s))
- {
- if (!s->session->peer)
- break;
- /* For sigalgs freeze the handshake buffer
- * at this point and digest cached records.
- */
- if (!s->s3->handshake_buffer)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_accept, ERR_R_INTERNAL_ERROR);
- return -1;
- }
- s->s3->flags |= TLS1_FLAGS_KEEP_HANDSHAKE;
- if (!ssl3_digest_cached_records(s))
- return -1;
- }
- else
- {
- int offset=0;
- int dgst_num;
-
- /* We need to get hashes here so if there is
- * a client cert, it can be verified
- * FIXME - digest processing for CertificateVerify
- * should be generalized. But it is next step
- */
- if (s->s3->handshake_buffer)
- if (!ssl3_digest_cached_records(s))
- return -1;
- for (dgst_num=0; dgst_num<SSL_MAX_DIGEST;dgst_num++)
- if (s->s3->handshake_dgst[dgst_num])
- {
- int dgst_size;
-
- s->method->ssl3_enc->cert_verify_mac(s,EVP_MD_CTX_type(s->s3->handshake_dgst[dgst_num]),&(s->s3->tmp.cert_verify_md[offset]));
- dgst_size=EVP_MD_CTX_size(s->s3->handshake_dgst[dgst_num]);
- if (dgst_size < 0)
- {
- ret = -1;
- goto end;
- }
- offset+=dgst_size;
- }
- }
break;
case SSL3_ST_SR_CERT_VRFY_A:
@@ -547,9 +500,7 @@ int ssl3_accept(SSL *s)
case SSL3_ST_SR_CHANGE: {
char next_proto_neg = 0;
char channel_id = 0;
-# if !defined(OPENSSL_NO_NEXTPROTONEG)
next_proto_neg = s->s3->next_proto_neg_seen;
-# endif
channel_id = s->s3->tlsext_channel_id_valid;
/* At this point, the next message must be entirely
@@ -568,7 +519,6 @@ int ssl3_accept(SSL *s)
break;
}
-#if !defined(OPENSSL_NO_NEXTPROTONEG)
case SSL3_ST_SR_NEXT_PROTO_A:
case SSL3_ST_SR_NEXT_PROTO_B:
ret=ssl3_get_next_proto(s);
@@ -579,7 +529,6 @@ int ssl3_accept(SSL *s)
else
s->state=SSL3_ST_SR_FINISHED_A;
break;
-#endif
case SSL3_ST_SR_CHANNEL_ID_A:
case SSL3_ST_SR_CHANNEL_ID_B:
@@ -614,12 +563,14 @@ int ssl3_accept(SSL *s)
case SSL3_ST_SW_SESSION_TICKET_A:
case SSL3_ST_SW_SESSION_TICKET_B:
- ret=ssl3_send_newsession_ticket(s);
+ ret=ssl3_send_new_session_ticket(s);
if (ret <= 0) goto end;
s->state=SSL3_ST_SW_CHANGE_A;
s->init_num=0;
break;
+#if 0
+ // TODO(davidben): Implement OCSP stapling on the server.
case SSL3_ST_SW_CERT_STATUS_A:
case SSL3_ST_SW_CERT_STATUS_B:
ret=ssl3_send_cert_status(s);
@@ -627,6 +578,7 @@ int ssl3_accept(SSL *s)
s->state=SSL3_ST_SW_KEY_EXCH_A;
s->init_num=0;
break;
+#endif
case SSL3_ST_SW_CHANGE_A:
case SSL3_ST_SW_CHANGE_B:
@@ -778,6 +730,7 @@ int ssl3_get_client_hello(SSL *s)
SSL3_ST_SR_CLNT_HELLO_B,
SSL3_MT_CLIENT_HELLO,
SSL3_RT_MAX_PLAIN_LENGTH,
+ SSL_GET_MESSAGE_HASH_MESSAGE,
&ok);
if (!ok) return((int)n);
@@ -1187,16 +1140,6 @@ int ssl3_get_client_hello(SSL *s)
* s->tmp.new_cipher - the new cipher to use.
*/
- /* Handles TLS extensions that we couldn't check earlier */
- if (s->version >= SSL3_VERSION)
- {
- if (ssl_check_clienthello_tlsext_late(s) <= 0)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_CLIENTHELLO_TLSEXT);
- goto err;
- }
- }
-
if (ret < 0) ret=-ret;
if (0)
{
@@ -1326,16 +1269,12 @@ int ssl3_send_server_key_exchange(SSL *s)
int j,num;
unsigned char md_buf[MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH];
unsigned int u;
-#ifndef OPENSSL_NO_DH
DH *dh=NULL,*dhp;
-#endif
-#ifndef OPENSSL_NO_ECDH
EC_KEY *ecdh=NULL, *ecdhp;
unsigned char *encodedPoint = NULL;
int encodedlen = 0;
int curve_id = 0;
BN_CTX *bn_ctx = NULL;
-#endif
const char* psk_identity_hint = NULL;
size_t psk_identity_hint_len = 0;
EVP_PKEY *pkey;
@@ -1372,7 +1311,6 @@ int ssl3_send_server_key_exchange(SSL *s)
psk_identity_hint_len = 0;
n+=2+psk_identity_hint_len;
}
-#ifndef OPENSSL_NO_DH
if (alg_k & SSL_kEDH)
{
dhp=cert->dh_tmp;
@@ -1424,8 +1362,6 @@ int ssl3_send_server_key_exchange(SSL *s)
r[2]=dh->pub_key;
}
else
-#endif
-#ifndef OPENSSL_NO_ECDH
if (alg_k & SSL_kEECDH)
{
const EC_GROUP *group;
@@ -1550,7 +1486,6 @@ int ssl3_send_server_key_exchange(SSL *s)
r[3]=NULL;
}
else
-#endif /* !OPENSSL_NO_ECDH */
if (!(alg_k & SSL_kPSK))
{
al=SSL_AD_HANDSHAKE_FAILURE;
@@ -1607,7 +1542,6 @@ int ssl3_send_server_key_exchange(SSL *s)
}
}
-#ifndef OPENSSL_NO_ECDH
if (alg_k & SSL_kEECDH)
{
/* XXX: For now, we only support named (not generic) curves.
@@ -1631,7 +1565,6 @@ int ssl3_send_server_key_exchange(SSL *s)
encodedPoint = NULL;
p += encodedlen;
}
-#endif /* OPENSSL_NO_ECDH */
/* not anonymous */
if (pkey != NULL)
@@ -1715,10 +1648,8 @@ int ssl3_send_server_key_exchange(SSL *s)
f_err:
ssl3_send_alert(s,SSL3_AL_FATAL,al);
err:
-#ifndef OPENSSL_NO_ECDH
if (encodedPoint != NULL) OPENSSL_free(encodedPoint);
BN_CTX_free(bn_ctx);
-#endif
EVP_MD_CTX_cleanup(&md_ctx);
return(-1);
}
@@ -1823,25 +1754,22 @@ int ssl3_get_client_key_exchange(SSL *s)
RSA *rsa=NULL;
uint8_t *decrypt_buf = NULL;
EVP_PKEY *pkey=NULL;
-#ifndef OPENSSL_NO_DH
BIGNUM *pub=NULL;
DH *dh_srvr;
-#endif
-#ifndef OPENSSL_NO_ECDH
EC_KEY *srvr_ecdh = NULL;
EVP_PKEY *clnt_pub_pkey = NULL;
EC_POINT *clnt_ecpoint = NULL;
BN_CTX *bn_ctx = NULL;
unsigned int psk_len = 0;
unsigned char psk[PSK_MAX_PSK_LEN];
-#endif
n=s->method->ssl_get_message(s,
SSL3_ST_SR_KEY_EXCH_A,
SSL3_ST_SR_KEY_EXCH_B,
SSL3_MT_CLIENT_KEY_EXCHANGE,
2048, /* ??? */
+ SSL_GET_MESSAGE_HASH_MESSAGE,
&ok);
if (!ok) return((int)n);
@@ -2063,7 +1991,6 @@ int ssl3_get_client_key_exchange(SSL *s)
premaster_secret_len = sizeof(rand_premaster_secret);
}
-#ifndef OPENSSL_NO_DH
else if (alg_k & SSL_kEDH)
{
CBS dh_Yc;
@@ -2116,9 +2043,7 @@ int ssl3_get_client_key_exchange(SSL *s)
premaster_secret_len = dh_len;
}
-#endif
-#ifndef OPENSSL_NO_ECDH
else if (alg_k & SSL_kEECDH)
{
int field_size = 0, ecdh_len;
@@ -2213,7 +2138,6 @@ int ssl3_get_client_key_exchange(SSL *s)
premaster_secret_len = ecdh_len;
}
-#endif
else if (alg_k & SSL_kPSK)
{
/* For plain PSK, other_secret is a block of 0s with the same
@@ -2283,41 +2207,34 @@ err:
}
if (decrypt_buf)
OPENSSL_free(decrypt_buf);
-#ifndef OPENSSL_NO_ECDH
EVP_PKEY_free(clnt_pub_pkey);
EC_POINT_free(clnt_ecpoint);
if (srvr_ecdh != NULL)
EC_KEY_free(srvr_ecdh);
BN_CTX_free(bn_ctx);
-#endif
return(-1);
}
int ssl3_get_cert_verify(SSL *s)
{
- EVP_PKEY *pkey=NULL;
int al,ok,ret=0;
long n;
CBS certificate_verify, signature;
- int type = 0;
X509 *peer = s->session->peer;
+ EVP_PKEY *pkey = NULL;
const EVP_MD *md = NULL;
- EVP_MD_CTX mctx;
-
- EVP_MD_CTX_init(&mctx);
-
- /* Determine if a CertificateVerify message is expected at all. It is
- * important that this be determined before ssl_get_message is called,
- * so as not to process the ChangeCipherSpec message early. */
- if (peer != NULL)
- {
- pkey = X509_get_pubkey(peer);
- type = X509_certificate_type(peer,pkey);
- }
- if (!(type & EVP_PKT_SIGN))
+ uint8_t digest[EVP_MAX_MD_SIZE];
+ size_t digest_length;
+ EVP_PKEY_CTX *pctx = NULL;
+
+ /* Only RSA and ECDSA client certificates are supported, so a
+ * CertificateVerify is required if and only if there's a
+ * client certificate. */
+ if (peer == NULL)
{
- ret = 1;
- goto done_with_buffer;
+ if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s))
+ return -1;
+ return 1;
}
n=s->method->ssl_get_message(s,
@@ -2325,26 +2242,42 @@ int ssl3_get_cert_verify(SSL *s)
SSL3_ST_SR_CERT_VRFY_B,
SSL3_MT_CERTIFICATE_VERIFY,
SSL3_RT_MAX_PLAIN_LENGTH,
+ SSL_GET_MESSAGE_DONT_HASH_MESSAGE,
&ok);
if (!ok)
+ return (int)n;
+
+ /* Filter out unsupported certificate types. */
+ pkey = X509_get_pubkey(peer);
+ if (!(X509_certificate_type(peer, pkey) & EVP_PKT_SIGN) ||
+ (pkey->type != EVP_PKEY_RSA && pkey->type != EVP_PKEY_EC))
{
- ret = (int)n;
- goto done;
+ al = SSL_AD_UNSUPPORTED_CERTIFICATE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_verify, SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE);
+ goto f_err;
}
CBS_init(&certificate_verify, s->init_msg, n);
- /* We now have a signature that we need to verify. */
- /* TODO(davidben): This should share code with
- * ssl3_get_server_key_exchange. */
-
+ /* Determine the digest type if needbe. */
if (SSL_USE_SIGALGS(s))
{
if (!tls12_check_peer_sigalg(&md, &al, s, &certificate_verify, pkey))
goto f_err;
}
+ /* Compute the digest. */
+ if (!ssl3_cert_verify_hash(s, digest, &digest_length, &md, pkey))
+ goto err;
+
+ /* The handshake buffer is no longer necessary, and we may hash the
+ * current message.*/
+ if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s))
+ goto err;
+ ssl3_hash_current_message(s);
+
+ /* Parse and verify the signature. */
if (!CBS_get_u16_length_prefixed(&certificate_verify, &signature) ||
CBS_len(&certificate_verify) != 0)
{
@@ -2353,87 +2286,27 @@ int ssl3_get_cert_verify(SSL *s)
goto f_err;
}
- if (SSL_USE_SIGALGS(s))
- {
- size_t hdatalen;
- const uint8_t *hdata;
- if (!BIO_mem_contents(s->s3->handshake_buffer, &hdata, &hdatalen))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_verify, ERR_R_INTERNAL_ERROR);
- al=SSL_AD_INTERNAL_ERROR;
- goto f_err;
- }
- if (!EVP_VerifyInit_ex(&mctx, md, NULL)
- || !EVP_VerifyUpdate(&mctx, hdata, hdatalen))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_verify, ERR_R_EVP_LIB);
- al=SSL_AD_INTERNAL_ERROR;
- goto f_err;
- }
-
- if (EVP_VerifyFinal(&mctx,
- CBS_data(&signature), CBS_len(&signature),
- pkey) <= 0)
- {
- al=SSL_AD_DECRYPT_ERROR;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_verify, SSL_R_BAD_SIGNATURE);
- goto f_err;
- }
- }
- else
- if (pkey->type == EVP_PKEY_RSA)
- {
- if (!RSA_verify(NID_md5_sha1, s->s3->tmp.cert_verify_md,
- MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH,
- CBS_data(&signature), CBS_len(&signature),
- pkey->pkey.rsa))
- {
- al = SSL_AD_DECRYPT_ERROR;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_verify, SSL_R_BAD_RSA_SIGNATURE);
- goto f_err;
- }
- }
- else
-#ifndef OPENSSL_NO_ECDSA
- if (pkey->type == EVP_PKEY_EC)
- {
- if (!ECDSA_verify(pkey->save_type,
- &(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]),
- SHA_DIGEST_LENGTH,
- CBS_data(&signature), CBS_len(&signature),
- pkey->pkey.ec))
- {
- /* bad signature */
- al = SSL_AD_DECRYPT_ERROR;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_verify, SSL_R_BAD_ECDSA_SIGNATURE);
- goto f_err;
- }
- }
- else
-#endif
+ pctx = EVP_PKEY_CTX_new(pkey, NULL);
+ if (pctx == NULL)
+ goto err;
+ if (!EVP_PKEY_verify_init(pctx) ||
+ !EVP_PKEY_CTX_set_signature_md(pctx, md) ||
+ !EVP_PKEY_verify(pctx, CBS_data(&signature), CBS_len(&signature),
+ digest, digest_length))
{
- OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_verify, ERR_R_INTERNAL_ERROR);
- al=SSL_AD_UNSUPPORTED_CERTIFICATE;
+ al = SSL_AD_DECRYPT_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_verify, SSL_R_BAD_SIGNATURE);
goto f_err;
}
-
- ret=1;
+ ret = 1;
if (0)
{
f_err:
ssl3_send_alert(s,SSL3_AL_FATAL,al);
}
-done_with_buffer:
- /* There is no more need for the handshake buffer. */
- if (s->s3->handshake_buffer)
- {
- BIO_free(s->s3->handshake_buffer);
- s->s3->handshake_buffer = NULL;
- s->s3->flags &= ~TLS1_FLAGS_KEEP_HANDSHAKE;
- }
-done:
- EVP_MD_CTX_cleanup(&mctx);
+err:
+ EVP_PKEY_CTX_free(pctx);
EVP_PKEY_free(pkey);
return(ret);
}
@@ -2453,6 +2326,7 @@ int ssl3_get_client_certificate(SSL *s)
SSL3_ST_SR_CERT_B,
-1,
s->max_cert_list,
+ SSL_GET_MESSAGE_HASH_MESSAGE,
&ok);
if (!ok) return((int)n);
@@ -2643,7 +2517,7 @@ int ssl3_send_server_certificate(SSL *s)
}
/* send a new session ticket (not necessarily for a new session) */
-int ssl3_send_newsession_ticket(SSL *s)
+int ssl3_send_new_session_ticket(SSL *s)
{
if (s->state == SSL3_ST_SW_SESSION_TICKET_A)
{
@@ -2770,6 +2644,7 @@ int ssl3_send_newsession_ticket(SSL *s)
return ssl_do_write(s);
}
+#if 0
int ssl3_send_cert_status(SSL *s)
{
if (s->state == SSL3_ST_SW_CERT_STATUS_A)
@@ -2804,8 +2679,8 @@ int ssl3_send_cert_status(SSL *s)
/* SSL3_ST_SW_CERT_STATUS_B */
return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
}
+#endif
-# ifndef OPENSSL_NO_NEXTPROTONEG
/* ssl3_get_next_proto reads a Next Protocol Negotiation handshake message. It
* sets the next_proto member in s if found */
int ssl3_get_next_proto(SSL *s)
@@ -2827,6 +2702,7 @@ int ssl3_get_next_proto(SSL *s)
SSL3_ST_SR_NEXT_PROTO_B,
SSL3_MT_NEXT_PROTO,
514, /* See the payload format below */
+ SSL_GET_MESSAGE_HASH_MESSAGE,
&ok);
if (!ok)
@@ -2863,13 +2739,15 @@ int ssl3_get_next_proto(SSL *s)
return 1;
}
-# endif
/* ssl3_get_channel_id reads and verifies a ClientID handshake message. */
int ssl3_get_channel_id(SSL *s)
{
int ret = -1, ok;
long n;
+ EVP_MD_CTX md_ctx;
+ uint8_t channel_id_hash[SHA256_DIGEST_LENGTH];
+ unsigned int channel_id_hash_len;
const uint8_t *p;
uint16_t extension_type, expected_extension_type;
EC_GROUP* p256 = NULL;
@@ -2879,33 +2757,32 @@ int ssl3_get_channel_id(SSL *s)
BIGNUM x, y;
CBS encrypted_extensions, extension;
- if (s->state == SSL3_ST_SR_CHANNEL_ID_A && s->init_num == 0)
- {
- /* The first time that we're called we take the current
- * handshake hash and store it. */
- EVP_MD_CTX md_ctx;
- unsigned int len;
-
- EVP_MD_CTX_init(&md_ctx);
- EVP_DigestInit_ex(&md_ctx, EVP_sha256(), NULL);
- if (!tls1_channel_id_hash(&md_ctx, s))
- return -1;
- len = sizeof(s->s3->tlsext_channel_id);
- EVP_DigestFinal(&md_ctx, s->s3->tlsext_channel_id, &len);
- EVP_MD_CTX_cleanup(&md_ctx);
- }
-
n = s->method->ssl_get_message(s,
SSL3_ST_SR_CHANNEL_ID_A,
SSL3_ST_SR_CHANNEL_ID_B,
SSL3_MT_ENCRYPTED_EXTENSIONS,
2 + 2 + TLSEXT_CHANNEL_ID_SIZE,
+ SSL_GET_MESSAGE_DONT_HASH_MESSAGE,
&ok);
if (!ok)
return((int)n);
- ssl3_finish_mac(s, (unsigned char*)s->init_buf->data, s->init_num + 4);
+ /* Before incorporating the EncryptedExtensions message to the
+ * handshake hash, compute the hash that should have been signed. */
+ channel_id_hash_len = sizeof(channel_id_hash);
+ EVP_MD_CTX_init(&md_ctx);
+ if (!EVP_DigestInit_ex(&md_ctx, EVP_sha256(), NULL) ||
+ !tls1_channel_id_hash(&md_ctx, s) ||
+ !EVP_DigestFinal(&md_ctx, channel_id_hash, &channel_id_hash_len))
+ {
+ EVP_MD_CTX_cleanup(&md_ctx);
+ return -1;
+ }
+ EVP_MD_CTX_cleanup(&md_ctx);
+ assert(channel_id_hash_len == SHA256_DIGEST_LENGTH);
+
+ ssl3_hash_current_message(s);
/* s->state doesn't reflect whether ChangeCipherSpec has been received
* in this handshake, but s->s3->change_cipher_spec does (will be reset
@@ -2978,17 +2855,12 @@ int ssl3_get_channel_id(SSL *s)
/* We stored the handshake hash in |tlsext_channel_id| the first time
* that we were called. */
- switch (ECDSA_do_verify(s->s3->tlsext_channel_id, SHA256_DIGEST_LENGTH, &sig, key)) {
- case 1:
- break;
- case 0:
+ if (!ECDSA_do_verify(channel_id_hash, channel_id_hash_len, &sig, key))
+ {
OPENSSL_PUT_ERROR(SSL, ssl3_get_channel_id, SSL_R_CHANNEL_ID_SIGNATURE_INVALID);
s->s3->tlsext_channel_id_valid = 0;
goto err;
- default:
- s->s3->tlsext_channel_id_valid = 0;
- goto err;
- }
+ }
memcpy(s->s3->tlsext_channel_id, p, 64);
ret = 1;
diff --git a/ssl/ssl_algs.c b/ssl/ssl_algs.c
index 8f7ede6..a1aa7b2 100644
--- a/ssl/ssl_algs.c
+++ b/ssl/ssl_algs.c
@@ -56,14 +56,14 @@
#include "ssl_locl.h"
+#include <openssl/crypto.h>
extern const ERR_STRING_DATA SSL_error_string_data[];
int SSL_library_init(void)
{
- ERR_load_crypto_strings();
- ERR_load_strings(SSL_error_string_data);
- ssl_load_ciphers();
+ CRYPTO_library_init();
+ SSL_load_error_strings();
return(1);
}
diff --git a/ssl/ssl_asn1.c b/ssl/ssl_asn1.c
index 9f372f9..8acd0eb 100644
--- a/ssl/ssl_asn1.c
+++ b/ssl/ssl_asn1.c
@@ -119,12 +119,14 @@ typedef struct ssl_session_asn1_st
ASN1_OCTET_STRING psk_identity;
ASN1_OCTET_STRING peer_sha256;
ASN1_OCTET_STRING original_handshake_hash;
+ ASN1_OCTET_STRING tlsext_signed_cert_timestamp_list;
+ ASN1_OCTET_STRING ocsp_response;
} SSL_SESSION_ASN1;
int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
{
#define LSIZE2 (sizeof(long)*2)
- int v1=0,v2=0,v3=0,v4=0,v5=0,v7=0,v8=0,v13=0,v14=0;
+ int v1=0,v2=0,v3=0,v4=0,v5=0,v7=0,v8=0,v13=0,v14=0,v15=0,v16=0;
unsigned char buf[4],ibuf1[LSIZE2],ibuf2[LSIZE2];
unsigned char ibuf3[LSIZE2],ibuf4[LSIZE2],ibuf5[LSIZE2];
int v6=0,v9=0,v10=0;
@@ -259,6 +261,22 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
a.original_handshake_hash.data = in->original_handshake_hash;
}
+ if (in->tlsext_signed_cert_timestamp_list_length > 0)
+ {
+ a.tlsext_signed_cert_timestamp_list.length =
+ in->tlsext_signed_cert_timestamp_list_length;
+ a.tlsext_signed_cert_timestamp_list.type = V_ASN1_OCTET_STRING;
+ a.tlsext_signed_cert_timestamp_list.data =
+ in->tlsext_signed_cert_timestamp_list;
+ }
+
+ if (in->ocsp_response_length > 0)
+ {
+ a.ocsp_response.length = in->ocsp_response_length;
+ a.ocsp_response.type = V_ASN1_OCTET_STRING;
+ a.ocsp_response.data = in->ocsp_response;
+ }
+
M_ASN1_I2D_len(&(a.version), i2d_ASN1_INTEGER);
M_ASN1_I2D_len(&(a.ssl_version), i2d_ASN1_INTEGER);
M_ASN1_I2D_len(&(a.cipher), i2d_ASN1_OCTET_STRING);
@@ -290,6 +308,11 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
M_ASN1_I2D_len_EXP_opt(&(a.peer_sha256),i2d_ASN1_OCTET_STRING,13,v13);
if (in->original_handshake_hash_len > 0)
M_ASN1_I2D_len_EXP_opt(&(a.original_handshake_hash),i2d_ASN1_OCTET_STRING,14,v14);
+ if (in->tlsext_signed_cert_timestamp_list_length > 0)
+ M_ASN1_I2D_len_EXP_opt(&(a.tlsext_signed_cert_timestamp_list),
+ i2d_ASN1_OCTET_STRING, 15, v15);
+ if (in->ocsp_response_length > 0)
+ M_ASN1_I2D_len_EXP_opt(&(a.ocsp_response), i2d_ASN1_OCTET_STRING, 16, v16);
M_ASN1_I2D_seq_total();
@@ -324,6 +347,11 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
M_ASN1_I2D_put_EXP_opt(&(a.peer_sha256),i2d_ASN1_OCTET_STRING,13,v13);
if (in->original_handshake_hash_len > 0)
M_ASN1_I2D_put_EXP_opt(&(a.original_handshake_hash),i2d_ASN1_OCTET_STRING,14,v14);
+ if (in->tlsext_signed_cert_timestamp_list_length > 0)
+ M_ASN1_I2D_put_EXP_opt(&(a.tlsext_signed_cert_timestamp_list),
+ i2d_ASN1_OCTET_STRING, 15, v15);
+ if (in->ocsp_response > 0)
+ M_ASN1_I2D_put_EXP_opt(&(a.ocsp_response), i2d_ASN1_OCTET_STRING, 16, v16);
M_ASN1_I2D_finish();
}
@@ -572,5 +600,30 @@ SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
os.data = NULL;
}
+ os.length = 0;
+ os.data = NULL;
+ M_ASN1_D2I_get_EXP_opt(osp, d2i_ASN1_OCTET_STRING, 15);
+ if (os.data)
+ {
+ if (ret->tlsext_signed_cert_timestamp_list)
+ OPENSSL_free(ret->tlsext_signed_cert_timestamp_list);
+ ret->tlsext_signed_cert_timestamp_list = os.data;
+ ret->tlsext_signed_cert_timestamp_list_length = os.length;
+ os.data = NULL;
+ }
+
+ os.length = 0;
+ os.data = NULL;
+ M_ASN1_D2I_get_EXP_opt(osp, d2i_ASN1_OCTET_STRING, 16);
+ if (os.data)
+ {
+ if (ret->ocsp_response)
+ OPENSSL_free(ret->ocsp_response);
+ ret->ocsp_response = os.data;
+ ret->ocsp_response_length = os.length;
+ os.data = NULL;
+ }
+
+
M_ASN1_D2I_Finish(a,SSL_SESSION_free,SSL_F_D2I_SSL_SESSION);
}
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index bab0eff..5e9d41d 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -161,9 +161,7 @@ void ssl_cert_set_default_md(CERT *cert)
/* Set digest values to defaults */
cert->pkeys[SSL_PKEY_RSA_SIGN].digest = EVP_sha1();
cert->pkeys[SSL_PKEY_RSA_ENC].digest = EVP_sha1();
-#ifndef OPENSSL_NO_ECDSA
cert->pkeys[SSL_PKEY_ECC].digest = EVP_sha1();
-#endif
}
CERT *ssl_cert_new(void)
@@ -205,7 +203,6 @@ CERT *ssl_cert_dup(CERT *cert)
ret->mask_k = cert->mask_k;
ret->mask_a = cert->mask_a;
-#ifndef OPENSSL_NO_DH
if (cert->dh_tmp != NULL)
{
ret->dh_tmp = DHparams_dup(cert->dh_tmp);
@@ -236,9 +233,7 @@ CERT *ssl_cert_dup(CERT *cert)
}
}
ret->dh_tmp_cb = cert->dh_tmp_cb;
-#endif
-#ifndef OPENSSL_NO_ECDH
if (cert->ecdh_tmp)
{
ret->ecdh_tmp = EC_KEY_dup(cert->ecdh_tmp);
@@ -250,7 +245,6 @@ CERT *ssl_cert_dup(CERT *cert)
}
ret->ecdh_tmp_cb = cert->ecdh_tmp_cb;
ret->ecdh_tmp_auto = cert->ecdh_tmp_auto;
-#endif
for (i = 0; i < SSL_PKEY_NUM; i++)
{
@@ -366,17 +360,11 @@ CERT *ssl_cert_dup(CERT *cert)
return(ret);
-#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_ECDH)
err:
-#endif
-#ifndef OPENSSL_NO_DH
if (ret->dh_tmp != NULL)
DH_free(ret->dh_tmp);
-#endif
-#ifndef OPENSSL_NO_ECDH
if (ret->ecdh_tmp != NULL)
EC_KEY_free(ret->ecdh_tmp);
-#endif
ssl_cert_clear_certs(ret);
@@ -418,12 +406,8 @@ void ssl_cert_free(CERT *c)
if(c == NULL)
return;
-#ifndef OPENSSL_NO_DH
if (c->dh_tmp) DH_free(c->dh_tmp);
-#endif
-#ifndef OPENSSL_NO_ECDH
if (c->ecdh_tmp) EC_KEY_free(c->ecdh_tmp);
-#endif
ssl_cert_clear_certs(c);
if (c->peer_sigalgs)
@@ -591,14 +575,10 @@ void ssl_sess_cert_free(SESS_CERT *sc)
if (sc->peer_rsa_tmp != NULL)
RSA_free(sc->peer_rsa_tmp);
-#ifndef OPENSSL_NO_DH
if (sc->peer_dh_tmp != NULL)
DH_free(sc->peer_dh_tmp);
-#endif
-#ifndef OPENSSL_NO_ECDH
if (sc->peer_ecdh_tmp != NULL)
EC_KEY_free(sc->peer_ecdh_tmp);
-#endif
OPENSSL_free(sc);
}
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index 0caed0b..fbed548 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -147,34 +147,18 @@
#include "ssl_locl.h"
-#define SSL_ENC_3DES_IDX 0
-#define SSL_ENC_RC4_IDX 1
-#define SSL_ENC_AES128_IDX 2
-#define SSL_ENC_AES256_IDX 3
-#define SSL_ENC_NUM_IDX 4
-
-
-static const EVP_CIPHER *ssl_cipher_methods[SSL_ENC_NUM_IDX]= { 0 };
-
-#define SSL_MD_MD5_IDX 0
-#define SSL_MD_SHA1_IDX 1
-#define SSL_MD_SHA256_IDX 2
-#define SSL_MD_SHA384_IDX 3
-/*Constant SSL_MAX_DIGEST equal to size of digests array should be
- * defined in the
- * ssl_locl.h */
-#define SSL_MD_NUM_IDX SSL_MAX_DIGEST
-static const EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX] = { 0 };
-static const int ssl_mac_pkey_id[SSL_MD_NUM_IDX]={
- EVP_PKEY_HMAC, EVP_PKEY_HMAC, EVP_PKEY_HMAC, EVP_PKEY_HMAC,
+struct handshake_digest
+ {
+ long mask;
+ const EVP_MD *(*md_func)(void);
};
-static int ssl_mac_secret_size[SSL_MD_NUM_IDX] = { 0 };
-
-static const int ssl_handshake_digest_flag[SSL_MD_NUM_IDX]={
- SSL_HANDSHAKE_MAC_MD5, SSL_HANDSHAKE_MAC_SHA,
- SSL_HANDSHAKE_MAC_SHA256, SSL_HANDSHAKE_MAC_SHA384,
- };
+static const struct handshake_digest ssl_handshake_digests[SSL_MAX_DIGEST] = {
+ { SSL_HANDSHAKE_MAC_MD5, EVP_md5 },
+ { SSL_HANDSHAKE_MAC_SHA, EVP_sha1 },
+ { SSL_HANDSHAKE_MAC_SHA256, EVP_sha256 },
+ { SSL_HANDSHAKE_MAC_SHA384, EVP_sha384 },
+};
#define CIPHER_ADD 1
#define CIPHER_KILL 2
@@ -255,26 +239,6 @@ static const SSL_CIPHER cipher_aliases[]={
{0,SSL_TXT_FIPS,0, 0,0,0,0,0,SSL_FIPS, 0,0,0},
};
-void ssl_load_ciphers(void)
- {
- ssl_cipher_methods[SSL_ENC_3DES_IDX]= EVP_des_ede3_cbc();
- ssl_cipher_methods[SSL_ENC_RC4_IDX]= EVP_rc4();
- ssl_cipher_methods[SSL_ENC_AES128_IDX]= EVP_aes_128_cbc();
- ssl_cipher_methods[SSL_ENC_AES256_IDX]= EVP_aes_256_cbc();
-
- ssl_digest_methods[SSL_MD_MD5_IDX]= EVP_md5();
- ssl_mac_secret_size[SSL_MD_MD5_IDX]= EVP_MD_size(EVP_md5());
- assert(ssl_mac_secret_size[SSL_MD_MD5_IDX] >= 0);
- ssl_digest_methods[SSL_MD_SHA1_IDX]=EVP_sha1();
- ssl_mac_secret_size[SSL_MD_SHA1_IDX]= EVP_MD_size(EVP_sha1());
- assert(ssl_mac_secret_size[SSL_MD_SHA1_IDX] >= 0);
-
- ssl_digest_methods[SSL_MD_SHA256_IDX]= EVP_sha256();
- ssl_mac_secret_size[SSL_MD_SHA256_IDX]= EVP_MD_size(EVP_sha256());
- ssl_digest_methods[SSL_MD_SHA384_IDX]= EVP_sha384();
- ssl_mac_secret_size[SSL_MD_SHA384_IDX]= EVP_MD_size(EVP_sha384());
- }
-
/* ssl_cipher_get_evp_aead sets |*aead| to point to the correct EVP_AEAD object
* for |s->cipher|. It returns 1 on success and 0 on error. */
int ssl_cipher_get_evp_aead(const SSL_SESSION *s, const EVP_AEAD **aead)
@@ -289,7 +253,6 @@ int ssl_cipher_get_evp_aead(const SSL_SESSION *s, const EVP_AEAD **aead)
(c->algorithm2 & SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD) == 0)
return 0;
-#ifndef OPENSSL_NO_AES
switch (c->algorithm_enc)
{
case SSL_AES128GCM:
@@ -308,7 +271,6 @@ int ssl_cipher_get_evp_aead(const SSL_SESSION *s, const EVP_AEAD **aead)
return 0;
return 1;
}
-#endif
return 0;
}
@@ -316,7 +278,6 @@ int ssl_cipher_get_evp_aead(const SSL_SESSION *s, const EVP_AEAD **aead)
int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
const EVP_MD **md, int *mac_pkey_type, int *mac_secret_size)
{
- int i;
const SSL_CIPHER *c;
c=s->cipher;
@@ -332,40 +293,32 @@ int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
switch (c->algorithm_enc)
{
case SSL_3DES:
- i=SSL_ENC_3DES_IDX;
+ *enc = EVP_des_ede3_cbc();
break;
case SSL_RC4:
- i=SSL_ENC_RC4_IDX;
+ *enc = EVP_rc4();
break;
case SSL_AES128:
- i=SSL_ENC_AES128_IDX;
+ *enc = EVP_aes_128_cbc();
break;
case SSL_AES256:
- i=SSL_ENC_AES256_IDX;
+ *enc = EVP_aes_256_cbc();
break;
default:
- i= -1;
- break;
+ return 0;
}
- if ((i < 0) || (i >= SSL_ENC_NUM_IDX))
- *enc=NULL;
- else
- *enc=ssl_cipher_methods[i];
-
if (!ssl_cipher_get_mac(s, md, mac_pkey_type, mac_secret_size))
return 0;
- if ((*enc != NULL) &&
- (*md != NULL || (EVP_CIPHER_flags(*enc)&EVP_CIPH_FLAG_AEAD_CIPHER)) &&
- (!mac_pkey_type||*mac_pkey_type != NID_undef))
- {
+ assert(*enc != NULL && *md != NULL);
+
+ /* TODO(fork): enable the stitched cipher modes. */
+#if 0
if (s->ssl_version>>8 != TLS1_VERSION_MAJOR ||
s->ssl_version < TLS1_VERSION)
return 1;
- /* TODO(fork): enable the stitched cipher modes. */
-#if 0
if (c->algorithm_enc == SSL_RC4 &&
c->algorithm_mac == SSL_MD5 &&
(evp=EVP_get_cipherbyname("RC4-HMAC-MD5")))
@@ -379,15 +332,12 @@ int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
(evp=EVP_get_cipherbyname("AES-256-CBC-HMAC-SHA1")))
*enc = evp, *md = NULL;
#endif
- return(1);
- }
- else
- return(0);
+
+ return 1;
}
int ssl_cipher_get_mac(const SSL_SESSION *s, const EVP_MD **md, int *mac_pkey_type, int *mac_secret_size)
{
- int i;
const SSL_CIPHER *c;
c=s->cipher;
@@ -396,49 +346,40 @@ int ssl_cipher_get_mac(const SSL_SESSION *s, const EVP_MD **md, int *mac_pkey_ty
switch (c->algorithm_mac)
{
case SSL_MD5:
- i=SSL_MD_MD5_IDX;
+ *md = EVP_md5();
break;
case SSL_SHA1:
- i=SSL_MD_SHA1_IDX;
+ *md = EVP_sha1();
break;
case SSL_SHA256:
- i=SSL_MD_SHA256_IDX;
+ *md = EVP_sha256();
break;
case SSL_SHA384:
- i=SSL_MD_SHA384_IDX;
+ *md = EVP_sha384();
break;
default:
- i= -1;
- break;
+ return 0;
}
- if ((i < 0) || (i >= SSL_MD_NUM_IDX))
+ if (mac_pkey_type != NULL)
{
- *md=NULL;
- if (mac_pkey_type!=NULL) *mac_pkey_type = NID_undef;
- if (mac_secret_size!=NULL) *mac_secret_size = 0;
+ *mac_pkey_type = EVP_PKEY_HMAC;
}
- else
+ if (mac_secret_size!=NULL)
{
- *md=ssl_digest_methods[i];
- if (mac_pkey_type!=NULL) *mac_pkey_type = ssl_mac_pkey_id[i];
- if (mac_secret_size!=NULL) *mac_secret_size = ssl_mac_secret_size[i];
+ *mac_secret_size = EVP_MD_size(*md);
}
-
return 1;
}
int ssl_get_handshake_digest(int idx, long *mask, const EVP_MD **md)
{
- if (idx <0||idx>=SSL_MD_NUM_IDX)
+ if (idx < 0 || idx >= SSL_MAX_DIGEST)
{
return 0;
}
- *mask = ssl_handshake_digest_flag[idx];
- if (*mask)
- *md = ssl_digest_methods[idx];
- else
- *md = NULL;
+ *mask = ssl_handshake_digests[idx].mask;
+ *md = ssl_handshake_digests[idx].md_func();
return 1;
}
@@ -477,31 +418,8 @@ static void ll_append_head(CIPHER_ORDER **head, CIPHER_ORDER *curr,
*head=curr;
}
-static void ssl_cipher_get_disabled(unsigned long *mkey, unsigned long *auth, unsigned long *enc, unsigned long *mac, unsigned long *ssl)
- {
- *mkey = 0;
- *auth = 0;
- *enc = 0;
- *mac = 0;
- *ssl = 0;
-
- *enc |= (ssl_cipher_methods[SSL_ENC_3DES_IDX] == NULL) ? SSL_3DES:0;
- *enc |= (ssl_cipher_methods[SSL_ENC_RC4_IDX ] == NULL) ? SSL_RC4 :0;
- *enc |= (ssl_cipher_methods[SSL_ENC_AES128_IDX] == NULL) ? SSL_AES128:0;
- *enc |= (ssl_cipher_methods[SSL_ENC_AES256_IDX] == NULL) ? SSL_AES256:0;
-
- *mac |= (ssl_digest_methods[SSL_MD_MD5_IDX ] == NULL) ? SSL_MD5 :0;
- *mac |= (ssl_digest_methods[SSL_MD_SHA1_IDX] == NULL) ? SSL_SHA1:0;
- *mac |= (ssl_digest_methods[SSL_MD_SHA256_IDX] == NULL) ? SSL_SHA256:0;
- *mac |= (ssl_digest_methods[SSL_MD_SHA384_IDX] == NULL) ? SSL_SHA384:0;
-
- }
-
static void ssl_cipher_collect_ciphers(const SSL_METHOD *ssl_method,
int num_of_ciphers,
- unsigned long disabled_mkey, unsigned long disabled_auth,
- unsigned long disabled_enc, unsigned long disabled_mac,
- unsigned long disabled_ssl,
CIPHER_ORDER *co_list,
CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p)
{
@@ -521,12 +439,7 @@ static void ssl_cipher_collect_ciphers(const SSL_METHOD *ssl_method,
{
c = ssl_method->get_cipher(i);
/* drop those that use any of that is not available */
- if ((c != NULL) && c->valid &&
- !(c->algorithm_mkey & disabled_mkey) &&
- !(c->algorithm_auth & disabled_auth) &&
- !(c->algorithm_enc & disabled_enc) &&
- !(c->algorithm_mac & disabled_mac) &&
- !(c->algorithm_ssl & disabled_ssl))
+ if ((c != NULL) && c->valid)
{
co_list[co_list_num].cipher = c;
co_list[co_list_num].next = NULL;
@@ -572,19 +485,11 @@ static void ssl_cipher_collect_ciphers(const SSL_METHOD *ssl_method,
static void ssl_cipher_collect_aliases(const SSL_CIPHER **ca_list,
int num_of_group_aliases,
- unsigned long disabled_mkey, unsigned long disabled_auth,
- unsigned long disabled_enc, unsigned long disabled_mac,
- unsigned long disabled_ssl,
CIPHER_ORDER *head)
{
CIPHER_ORDER *ciph_curr;
const SSL_CIPHER **ca_curr;
int i;
- unsigned long mask_mkey = ~disabled_mkey;
- unsigned long mask_auth = ~disabled_auth;
- unsigned long mask_enc = ~disabled_enc;
- unsigned long mask_mac = ~disabled_mac;
- unsigned long mask_ssl = ~disabled_ssl;
/*
* First, add the real ciphers as already collected
@@ -606,32 +511,6 @@ static void ssl_cipher_collect_aliases(const SSL_CIPHER **ca_list,
*/
for (i = 0; i < num_of_group_aliases; i++)
{
- unsigned long algorithm_mkey = cipher_aliases[i].algorithm_mkey;
- unsigned long algorithm_auth = cipher_aliases[i].algorithm_auth;
- unsigned long algorithm_enc = cipher_aliases[i].algorithm_enc;
- unsigned long algorithm_mac = cipher_aliases[i].algorithm_mac;
- unsigned long algorithm_ssl = cipher_aliases[i].algorithm_ssl;
-
- if (algorithm_mkey)
- if ((algorithm_mkey & mask_mkey) == 0)
- continue;
-
- if (algorithm_auth)
- if ((algorithm_auth & mask_auth) == 0)
- continue;
-
- if (algorithm_enc)
- if ((algorithm_enc & mask_enc) == 0)
- continue;
-
- if (algorithm_mac)
- if ((algorithm_mac & mask_mac) == 0)
- continue;
-
- if (algorithm_ssl)
- if ((algorithm_ssl & mask_ssl) == 0)
- continue;
-
*ca_curr = cipher_aliases + i;
ca_curr++;
}
@@ -714,9 +593,7 @@ static void ssl_cipher_apply_rule(unsigned long cipher_id,
continue;
if (alg_ssl && !(alg_ssl & cp->algorithm_ssl))
continue;
- if ((algo_strength & SSL_EXP_MASK) && !(algo_strength & SSL_EXP_MASK & cp->algo_strength))
- continue;
- if ((algo_strength & SSL_STRONG_MASK) && !(algo_strength & SSL_STRONG_MASK & cp->algo_strength))
+ if (algo_strength && !(algo_strength & cp->algo_strength))
continue;
}
@@ -884,20 +761,8 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
{ rule = CIPHER_DEL; l++; }
else if (ch == '+')
{ rule = CIPHER_ORD; l++; }
- else if (ch == '!' && has_group)
- {
- OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS);
- retval = found = in_group = 0;
- break;
- }
else if (ch == '!')
{ rule = CIPHER_KILL; l++; }
- else if (ch == '@' && has_group)
- {
- OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS);
- retval = found = in_group = 0;
- break;
- }
else if (ch == '@')
{ rule = CIPHER_SPECIAL; l++; }
else if (ch == '[')
@@ -916,6 +781,16 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
else
{ rule = CIPHER_ADD; }
+ /* If preference groups are enabled, the only legal
+ * operator is +. Otherwise the in_group bits will get
+ * mixed up. */
+ if (has_group && rule != CIPHER_ADD)
+ {
+ OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS);
+ retval = found = in_group = 0;
+ break;
+ }
+
if (ITEM_SEP(ch))
{
l++;
@@ -1043,26 +918,15 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
alg_mac = ca_list[j]->algorithm_mac;
}
- if (ca_list[j]->algo_strength & SSL_EXP_MASK)
+ if (ca_list[j]->algo_strength)
{
- if (algo_strength & SSL_EXP_MASK)
+ if (algo_strength)
{
- algo_strength &= (ca_list[j]->algo_strength & SSL_EXP_MASK) | ~SSL_EXP_MASK;
- if (!(algo_strength & SSL_EXP_MASK)) { found = 0; break; }
+ algo_strength &= ca_list[j]->algo_strength;
+ if (!algo_strength) { found = 0; break; }
}
else
- algo_strength |= ca_list[j]->algo_strength & SSL_EXP_MASK;
- }
-
- if (ca_list[j]->algo_strength & SSL_STRONG_MASK)
- {
- if (algo_strength & SSL_STRONG_MASK)
- {
- algo_strength &= (ca_list[j]->algo_strength & SSL_STRONG_MASK) | ~SSL_STRONG_MASK;
- if (!(algo_strength & SSL_STRONG_MASK)) { found = 0; break; }
- }
- else
- algo_strength |= ca_list[j]->algo_strength & SSL_STRONG_MASK;
+ algo_strength |= ca_list[j]->algo_strength;
}
if (ca_list[j]->valid)
@@ -1125,7 +989,6 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
while ((*l != '\0') && !ITEM_SEP(*l))
l++;
}
- if (*l == '\0') break; /* done */
}
if (in_group)
@@ -1144,7 +1007,6 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
const char *rule_str, CERT *c)
{
int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases;
- unsigned long disabled_mkey, disabled_auth, disabled_enc, disabled_mac, disabled_ssl;
STACK_OF(SSL_CIPHER) *cipherstack = NULL, *tmp_cipher_list = NULL;
const char *rule_p;
CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr;
@@ -1160,12 +1022,6 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
return NULL;
/*
- * To reduce the work to do we only want to process the compiled
- * in algorithms, so we first get the mask of disabled ciphers.
- */
- ssl_cipher_get_disabled(&disabled_mkey, &disabled_auth, &disabled_enc, &disabled_mac, &disabled_ssl);
-
- /*
* Now we have to collect the available ciphers from the compiled
* in ciphers. We cannot get more than the number compiled in, so
* it is used for allocation.
@@ -1182,7 +1038,6 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
}
ssl_cipher_collect_ciphers(ssl_method, num_of_ciphers,
- disabled_mkey, disabled_auth, disabled_enc, disabled_mac, disabled_ssl,
co_list, &head, &tail);
@@ -1245,13 +1100,10 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
ca_list = OPENSSL_malloc(sizeof(SSL_CIPHER *) * num_of_alias_max);
if (ca_list == NULL)
{
- OPENSSL_free(co_list);
OPENSSL_PUT_ERROR(SSL, ssl_create_cipher_list, ERR_R_MALLOC_FAILURE);
- return(NULL); /* Failure */
+ goto err;
}
- ssl_cipher_collect_aliases(ca_list, num_of_group_aliases,
- disabled_mkey, disabled_auth, disabled_enc,
- disabled_mac, disabled_ssl, head);
+ ssl_cipher_collect_aliases(ca_list, num_of_group_aliases, head);
/*
* If the rule_string begins with DEFAULT, apply the default rule
diff --git a/ssl/ssl_error.c b/ssl/ssl_error.c
index 12c1ffd..0ba125b 100644
--- a/ssl/ssl_error.c
+++ b/ssl/ssl_error.c
@@ -100,10 +100,10 @@ const ERR_STRING_DATA SSL_error_string_data[] = {
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl23_write, 0), "ssl23_write"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_accept, 0), "ssl3_accept"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_callback_ctrl, 0), "ssl3_callback_ctrl"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_cert_verify_hash, 0), "ssl3_cert_verify_hash"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_change_cipher_state, 0), "ssl3_change_cipher_state"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_check_cert_and_algorithm, 0), "ssl3_check_cert_and_algorithm"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_check_client_hello, 0), "ssl3_check_client_hello"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_client_hello, 0), "ssl3_client_hello"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_connect, 0), "ssl3_connect"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_ctrl, 0), "ssl3_ctrl"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_ctx_ctrl, 0), "ssl3_ctx_ctrl"},
@@ -130,11 +130,12 @@ const ERR_STRING_DATA SSL_error_string_data[] = {
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_handshake_mac, 0), "ssl3_handshake_mac"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_read_bytes, 0), "ssl3_read_bytes"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_read_n, 0), "ssl3_read_n"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_send_cert_verify, 0), "ssl3_send_cert_verify"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_send_certificate_request, 0), "ssl3_send_certificate_request"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_send_channel_id, 0), "ssl3_send_channel_id"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_send_client_certificate, 0), "ssl3_send_client_certificate"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_send_client_hello, 0), "ssl3_send_client_hello"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_send_client_key_exchange, 0), "ssl3_send_client_key_exchange"},
- {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_send_client_verify, 0), "ssl3_send_client_verify"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_send_server_certificate, 0), "ssl3_send_server_certificate"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_send_server_hello, 0), "ssl3_send_server_hello"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_send_server_key_exchange, 0), "ssl3_send_server_key_exchange"},
@@ -162,6 +163,8 @@ const ERR_STRING_DATA SSL_error_string_data[] = {
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_cipher_process_rulestr, 0), "ssl_cipher_process_rulestr"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_cipher_strength_sort, 0), "ssl_cipher_strength_sort"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_create_cipher_list, 0), "ssl_create_cipher_list"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_ctx_log_master_secret, 0), "ssl_ctx_log_master_secret"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_ctx_log_rsa_client_key_exchange, 0), "ssl_ctx_log_rsa_client_key_exchange"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_ctx_make_profiles, 0), "ssl_ctx_make_profiles"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_get_new_session, 0), "ssl_get_new_session"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl_get_prev_session, 0), "ssl_get_prev_session"},
@@ -450,6 +453,7 @@ const ERR_STRING_DATA SSL_error_string_data[] = {
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED), "SSLV3_ALERT_CERTIFICATE_EXPIRED"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED), "SSLV3_ALERT_CERTIFICATE_REVOKED"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN), "SSLV3_ALERT_CERTIFICATE_UNKNOWN"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_CLOSE_NOTIFY), "SSLV3_ALERT_CLOSE_NOTIFY"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE), "SSLV3_ALERT_DECOMPRESSION_FAILURE"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE), "SSLV3_ALERT_HANDSHAKE_FAILURE"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER), "SSLV3_ALERT_ILLEGAL_PARAMETER"},
@@ -469,6 +473,7 @@ const ERR_STRING_DATA SSL_error_string_data[] = {
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_DECRYPTION_FAILED), "TLSV1_ALERT_DECRYPTION_FAILED"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_DECRYPT_ERROR), "TLSV1_ALERT_DECRYPT_ERROR"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION), "TLSV1_ALERT_EXPORT_RESTRICTION"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK), "TLSV1_ALERT_INAPPROPRIATE_FALLBACK"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY), "TLSV1_ALERT_INSUFFICIENT_SECURITY"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_INTERNAL_ERROR), "TLSV1_ALERT_INTERNAL_ERROR"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_NO_RENEGOTIATION), "TLSV1_ALERT_NO_RENEGOTIATION"},
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 43ce97b..720ab54 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -172,6 +172,13 @@ SSL3_ENC_METHOD ssl3_undef_enc_method={
int use_context)) ssl_undefined_function,
};
+/* Some error codes are special. Ensure the make_errors.go script
+ * never regresses this. */
+OPENSSL_COMPILE_ASSERT(
+ SSL_R_TLSV1_ALERT_NO_RENEGOTIATION ==
+ SSL_AD_NO_RENEGOTIATION + SSL_AD_REASON_OFFSET,
+ ssl_alert_reason_code_mismatch);
+
int SSL_clear(SSL *s)
{
@@ -336,15 +343,8 @@ SSL *SSL_new(SSL_CTX *ctx)
s->tlsext_debug_cb = 0;
s->tlsext_debug_arg = NULL;
s->tlsext_ticket_expected = 0;
- s->tlsext_status_type = -1;
- s->tlsext_status_expected = 0;
- s->tlsext_ocsp_ids = NULL;
- s->tlsext_ocsp_exts = NULL;
- s->tlsext_ocsp_resp = NULL;
- s->tlsext_ocsp_resplen = -1;
CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX);
s->initial_ctx=ctx;
-#ifndef OPENSSL_NO_EC
if (ctx->tlsext_ecpointformatlist)
{
s->tlsext_ecpointformatlist =
@@ -365,10 +365,7 @@ SSL *SSL_new(SSL_CTX *ctx)
s->tlsext_ellipticcurvelist_length =
ctx->tlsext_ellipticcurvelist_length;
}
-#endif
-# ifndef OPENSSL_NO_NEXTPROTONEG
s->next_proto_negotiated = NULL;
-# endif
if (s->ctx->alpn_client_proto_list)
{
@@ -404,6 +401,12 @@ SSL *SSL_new(SSL_CTX *ctx)
s->psk_client_callback=ctx->psk_client_callback;
s->psk_server_callback=ctx->psk_server_callback;
+ if (!s->server)
+ {
+ s->signed_cert_timestamps_enabled = s->ctx->signed_cert_timestamps_enabled;
+ s->ocsp_stapling_enabled = s->ctx->ocsp_stapling_enabled;
+ }
+
return(s);
err:
if (s != NULL)
@@ -669,20 +672,8 @@ void SSL_free(SSL *s)
if (s->tlsext_hostname)
OPENSSL_free(s->tlsext_hostname);
if (s->initial_ctx) SSL_CTX_free(s->initial_ctx);
-#ifndef OPENSSL_NO_EC
if (s->tlsext_ecpointformatlist) OPENSSL_free(s->tlsext_ecpointformatlist);
if (s->tlsext_ellipticcurvelist) OPENSSL_free(s->tlsext_ellipticcurvelist);
-#endif /* OPENSSL_NO_EC */
- if (s->tlsext_ocsp_exts)
- sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts,
- X509_EXTENSION_free);
- /* TODO(fork): OCSP support */
-#if 0
- if (s->tlsext_ocsp_ids)
- sk_OCSP_RESPID_pop_free(s->tlsext_ocsp_ids, OCSP_RESPID_free);
-#endif
- if (s->tlsext_ocsp_resp)
- OPENSSL_free(s->tlsext_ocsp_resp);
if (s->alpn_client_proto_list)
OPENSSL_free(s->alpn_client_proto_list);
if (s->tlsext_channel_id_private)
@@ -698,10 +689,8 @@ void SSL_free(SSL *s)
if (s->ctx) SSL_CTX_free(s->ctx);
-#if !defined(OPENSSL_NO_NEXTPROTONEG)
if (s->next_proto_negotiated)
OPENSSL_free(s->next_proto_negotiated);
-#endif
if (s->srtp_profiles)
sk_SRTP_PROTECTION_PROFILE_free(s->srtp_profiles);
@@ -1097,7 +1086,7 @@ int SSL_shutdown(SSL *s)
return -1;
}
- if ((s != NULL) && !SSL_in_init(s))
+ if (!SSL_in_init(s))
return(s->method->ssl_shutdown(s));
else
return(1);
@@ -1162,11 +1151,8 @@ long SSL_ctrl(SSL *s,int cmd,long larg,void *parg)
s->max_cert_list=larg;
return(l);
case SSL_CTRL_SET_MTU:
-#ifndef OPENSSL_NO_DTLS1
if (larg < (long)dtls1_min_mtu())
return 0;
-#endif
-
if (SSL_IS_DTLS(s))
{
s->d1->mtu = larg;
@@ -1675,6 +1661,63 @@ int SSL_get_servername_type(const SSL *s)
return -1;
}
+void SSL_CTX_enable_signed_cert_timestamps(SSL_CTX *ctx)
+ {
+ ctx->signed_cert_timestamps_enabled = 1;
+ }
+
+int SSL_enable_signed_cert_timestamps(SSL *ssl)
+ {
+ /* Currently not implemented server-side. */
+ if (ssl->server)
+ return 0;
+
+ ssl->signed_cert_timestamps_enabled = 1;
+ return 1;
+ }
+
+void SSL_CTX_enable_ocsp_stapling(SSL_CTX *ctx)
+ {
+ ctx->ocsp_stapling_enabled = 1;
+ }
+
+int SSL_enable_ocsp_stapling(SSL *ssl)
+ {
+ /* Currently not implemented server-side. */
+ if (ssl->server)
+ return 0;
+ ssl->ocsp_stapling_enabled = 1;
+ return 1;
+ }
+
+void SSL_get0_signed_cert_timestamp_list(const SSL *ssl, uint8_t **out, size_t *out_len)
+ {
+ SSL_SESSION *session = ssl->session;
+
+ *out_len = 0;
+ *out = NULL;
+ if (ssl->server)
+ return;
+ if (!session || !session->tlsext_signed_cert_timestamp_list)
+ return;
+ *out = session->tlsext_signed_cert_timestamp_list;
+ *out_len = session->tlsext_signed_cert_timestamp_list_length;
+ }
+
+void SSL_get0_ocsp_response(const SSL *ssl, uint8_t **out, size_t *out_len)
+ {
+ SSL_SESSION *session = ssl->session;
+
+ *out_len = 0;
+ *out = NULL;
+ if (ssl->server)
+ return;
+ if (!session || !session->ocsp_response)
+ return;
+ *out = session->ocsp_response;
+ *out_len = session->ocsp_response_length;
+ }
+
/* SSL_select_next_proto implements the standard protocol selection. It is
* expected that this function is called from the callback set by
* SSL_CTX_set_next_proto_select_cb.
@@ -1741,7 +1784,6 @@ int SSL_select_next_proto(unsigned char **out, unsigned char *outlen, const unsi
return status;
}
-# ifndef OPENSSL_NO_NEXTPROTONEG
/* SSL_get0_next_proto_negotiated sets *data and *len to point to the client's
* requested protocol for this connection and returns 0. If the client didn't
* request any protocol, then *data is set to NULL.
@@ -1790,7 +1832,6 @@ void SSL_CTX_set_next_proto_select_cb(SSL_CTX *ctx, int (*cb) (SSL *s, unsigned
ctx->next_proto_select_cb = cb;
ctx->next_proto_select_cb_arg = arg;
}
-# endif
/* SSL_CTX_set_alpn_protos sets the ALPN protocol list on |ctx| to |protos|.
* |protos| must be in wire-format (i.e. a series of non-empty, 8-bit
@@ -2003,10 +2044,8 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
ret->tlsext_status_cb = 0;
ret->tlsext_status_arg = NULL;
-# ifndef OPENSSL_NO_NEXTPROTONEG
ret->next_protos_advertised_cb = 0;
ret->next_proto_select_cb = 0;
-# endif
ret->psk_identity_hint=NULL;
ret->psk_client_callback=NULL;
ret->psk_server_callback=NULL;
@@ -2085,18 +2124,19 @@ void SSL_CTX_free(SSL_CTX *a)
if (a->psk_identity_hint)
OPENSSL_free(a->psk_identity_hint);
-# ifndef OPENSSL_NO_EC
if (a->tlsext_ecpointformatlist)
OPENSSL_free(a->tlsext_ecpointformatlist);
if (a->tlsext_ellipticcurvelist)
OPENSSL_free(a->tlsext_ellipticcurvelist);
-# endif /* OPENSSL_NO_EC */
if (a->alpn_client_proto_list != NULL)
OPENSSL_free(a->alpn_client_proto_list);
if (a->tlsext_channel_id_private)
EVP_PKEY_free(a->tlsext_channel_id_private);
+ if (a->keylog_bio)
+ BIO_free(a->keylog_bio);
+
OPENSSL_free(a);
}
@@ -2142,34 +2182,20 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher)
CERT_PKEY *cpk;
int rsa_enc,rsa_sign,dh_tmp;
unsigned long mask_k,mask_a;
-#ifndef OPENSSL_NO_ECDSA
int have_ecc_cert, ecdsa_ok;
-#endif
-#ifndef OPENSSL_NO_ECDH
int have_ecdh_tmp;
-#endif
-#ifndef OPENSSL_NO_EC
X509 *x = NULL;
-#endif
if (c == NULL) return;
-#ifndef OPENSSL_NO_DH
dh_tmp=(c->dh_tmp != NULL || c->dh_tmp_cb != NULL);
-#else
- dh_tmp=0;
-#endif
-#ifndef OPENSSL_NO_ECDH
have_ecdh_tmp=(c->ecdh_tmp || c->ecdh_tmp_cb || c->ecdh_tmp_auto);
-#endif
cpk= &(c->pkeys[SSL_PKEY_RSA_ENC]);
rsa_enc= cpk->valid_flags & CERT_PKEY_VALID;
cpk= &(c->pkeys[SSL_PKEY_RSA_SIGN]);
rsa_sign= cpk->valid_flags & CERT_PKEY_SIGN;
cpk= &(c->pkeys[SSL_PKEY_ECC]);
-#ifndef OPENSSL_NO_EC
have_ecc_cert= cpk->valid_flags & CERT_PKEY_VALID;
-#endif
mask_k=0;
mask_a=0;
@@ -2194,7 +2220,6 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher)
/* An ECC certificate may be usable for ECDSA cipher suites depending on
* the key usage extension. */
-#ifndef OPENSSL_NO_EC
if (have_ecc_cert)
{
cpk = &c->pkeys[SSL_PKEY_ECC];
@@ -2205,21 +2230,16 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher)
(x->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE) : 1;
if (!(cpk->valid_flags & CERT_PKEY_SIGN))
ecdsa_ok = 0;
-#ifndef OPENSSL_NO_ECDSA
if (ecdsa_ok)
{
mask_a|=SSL_aECDSA;
}
-#endif
}
-#endif
-#ifndef OPENSSL_NO_ECDH
if (have_ecdh_tmp)
{
mask_k|=SSL_kEECDH;
}
-#endif
mask_k |= SSL_kPSK;
mask_a |= SSL_aPSK;
@@ -2233,7 +2253,6 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher)
#define ku_reject(x, usage) \
(((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage)))
-#ifndef OPENSSL_NO_EC
int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s)
{
@@ -2263,7 +2282,6 @@ int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s)
return 1; /* all checks are ok */
}
-#endif
static int ssl_get_server_cert_index(const SSL *s)
{
@@ -2348,14 +2366,14 @@ void ssl_update_cache(SSL *s,int mode)
* and it would be rather hard to do anyway :-) */
if (s->session->session_id_length == 0) return;
- i=s->session_ctx->session_cache_mode;
+ i=s->initial_ctx->session_cache_mode;
if ((i & mode) && (!s->hit)
&& ((i & SSL_SESS_CACHE_NO_INTERNAL_STORE)
- || SSL_CTX_add_session(s->session_ctx,s->session))
- && (s->session_ctx->new_session_cb != NULL))
+ || SSL_CTX_add_session(s->initial_ctx,s->session))
+ && (s->initial_ctx->new_session_cb != NULL))
{
CRYPTO_add(&s->session->references,1,CRYPTO_LOCK_SSL_SESSION);
- if (!s->session_ctx->new_session_cb(s,s->session))
+ if (!s->initial_ctx->new_session_cb(s,s->session))
SSL_SESSION_free(s->session);
}
@@ -2364,10 +2382,10 @@ void ssl_update_cache(SSL *s,int mode)
((i & mode) == mode))
{
if ( (((mode & SSL_SESS_CACHE_CLIENT)
- ?s->session_ctx->stats.sess_connect_good
- :s->session_ctx->stats.sess_accept_good) & 0xff) == 0xff)
+ ?s->initial_ctx->stats.sess_connect_good
+ :s->initial_ctx->stats.sess_accept_good) & 0xff) == 0xff)
{
- SSL_CTX_flush_sessions(s->session_ctx,(unsigned long)time(NULL));
+ SSL_CTX_flush_sessions(s->initial_ctx,(unsigned long)time(NULL));
}
}
}
@@ -2932,7 +2950,6 @@ RSA *cb(SSL *ssl,int is_export,int keylength)
* \param dh the callback
*/
-#ifndef OPENSSL_NO_DH
void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,DH *(*dh)(SSL *ssl,int is_export,
int keylength))
{
@@ -2944,9 +2961,7 @@ void SSL_set_tmp_dh_callback(SSL *ssl,DH *(*dh)(SSL *ssl,int is_export,
{
SSL_callback_ctrl(ssl,SSL_CTRL_SET_TMP_DH_CB,(void (*)(void))dh);
}
-#endif
-#ifndef OPENSSL_NO_ECDH
void SSL_CTX_set_tmp_ecdh_callback(SSL_CTX *ctx,EC_KEY *(*ecdh)(SSL *ssl,int is_export,
int keylength))
{
@@ -2958,7 +2973,6 @@ void SSL_set_tmp_ecdh_callback(SSL *ssl,EC_KEY *(*ecdh)(SSL *ssl,int is_export,
{
SSL_callback_ctrl(ssl,SSL_CTRL_SET_TMP_ECDH_CB,(void (*)(void))ecdh);
}
-#endif
int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint)
{
@@ -3081,6 +3095,122 @@ void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int con
SSL_callback_ctrl(ssl, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb);
}
+void SSL_CTX_set_keylog_bio(SSL_CTX *ctx, BIO *keylog_bio)
+ {
+ if (ctx->keylog_bio != NULL)
+ BIO_free(ctx->keylog_bio);
+ ctx->keylog_bio = keylog_bio;
+ }
+
+static int cbb_add_hex(CBB *cbb, const uint8_t *in, size_t in_len)
+ {
+ static const char hextable[] = "0123456789abcdef";
+ uint8_t *out;
+ size_t i;
+
+ if (!CBB_add_space(cbb, &out, in_len * 2))
+ {
+ return 0;
+ }
+
+ for (i = 0; i < in_len; i++)
+ {
+ *(out++) = (uint8_t)hextable[in[i] >> 4];
+ *(out++) = (uint8_t)hextable[in[i] & 0xf];
+ }
+ return 1;
+ }
+
+int ssl_ctx_log_rsa_client_key_exchange(SSL_CTX *ctx,
+ const uint8_t *encrypted_premaster, size_t encrypted_premaster_len,
+ const uint8_t *premaster, size_t premaster_len)
+ {
+ BIO *bio = ctx->keylog_bio;
+ CBB cbb;
+ uint8_t *out;
+ size_t out_len;
+ int ret;
+
+ if (bio == NULL)
+ {
+ return 1;
+ }
+
+ if (encrypted_premaster_len < 8)
+ {
+ OPENSSL_PUT_ERROR(SSL, ssl_ctx_log_rsa_client_key_exchange, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (!CBB_init(&cbb, 4 + 16 + 1 + premaster_len*2 + 1))
+ {
+ return 0;
+ }
+ if (!CBB_add_bytes(&cbb, (const uint8_t*)"RSA ", 4) ||
+ /* Only the first 8 bytes of the encrypted premaster secret are
+ * logged. */
+ !cbb_add_hex(&cbb, encrypted_premaster, 8) ||
+ !CBB_add_bytes(&cbb, (const uint8_t*)" ", 1) ||
+ !cbb_add_hex(&cbb, premaster, premaster_len) ||
+ !CBB_add_bytes(&cbb, (const uint8_t*)"\n", 1) ||
+ !CBB_finish(&cbb, &out, &out_len))
+ {
+ CBB_cleanup(&cbb);
+ return 0;
+ }
+
+ CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
+ ret = BIO_write(bio, out, out_len) >= 0 && BIO_flush(bio);
+ CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
+
+ OPENSSL_free(out);
+ return ret;
+ }
+
+int ssl_ctx_log_master_secret(SSL_CTX *ctx,
+ const uint8_t *client_random, size_t client_random_len,
+ const uint8_t *master, size_t master_len)
+ {
+ BIO *bio = ctx->keylog_bio;
+ CBB cbb;
+ uint8_t *out;
+ size_t out_len;
+ int ret;
+
+ if (bio == NULL)
+ {
+ return 1;
+ }
+
+ if (client_random_len != 32)
+ {
+ OPENSSL_PUT_ERROR(SSL, ssl_ctx_log_master_secret, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ if (!CBB_init(&cbb, 14 + 64 + 1 + master_len*2 + 1))
+ {
+ return 0;
+ }
+ if (!CBB_add_bytes(&cbb, (const uint8_t*)"CLIENT_RANDOM ", 14) ||
+ !cbb_add_hex(&cbb, client_random, 32) ||
+ !CBB_add_bytes(&cbb, (const uint8_t*)" ", 1) ||
+ !cbb_add_hex(&cbb, master, master_len) ||
+ !CBB_add_bytes(&cbb, (const uint8_t*)"\n", 1) ||
+ !CBB_finish(&cbb, &out, &out_len))
+ {
+ CBB_cleanup(&cbb);
+ return 0;
+ }
+
+ CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
+ ret = BIO_write(bio, out, out_len) >= 0 && BIO_flush(bio);
+ CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
+
+ OPENSSL_free(out);
+ return ret;
+ }
+
int SSL_cutthrough_complete(const SSL *s)
{
return (!s->server && /* cutthrough only applies to clients */
@@ -3112,11 +3242,7 @@ int ssl3_can_cutthrough(const SSL *s)
return 0;
/* require ALPN or NPN extension */
- if (!s->s3->alpn_selected
-#ifndef OPENSSL_NO_NEXTPROTONEG
- && !s->s3->next_proto_neg_seen
-#endif
- )
+ if (!s->s3->alpn_selected && !s->s3->next_proto_neg_seen)
{
return 0;
}
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 55f1aaf..f9f3bed 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -359,14 +359,9 @@
/*
* Cipher strength information.
*/
-#define SSL_EXP_MASK 0x00000003L
-#define SSL_STRONG_MASK 0x000001fcL
-
-#define SSL_NOT_EXP 0x00000001L
-
-#define SSL_MEDIUM 0x00000040L
-#define SSL_HIGH 0x00000080L
-#define SSL_FIPS 0x00000100L
+#define SSL_MEDIUM 0x00000001L
+#define SSL_HIGH 0x00000002L
+#define SSL_FIPS 0x00000004L
/* we have used 000001ff - 23 bits left to go */
@@ -415,14 +410,16 @@
#define PENDING_SESSION -10000
#define CERTIFICATE_SELECTION_PENDING -10001
-#ifndef OPENSSL_NO_EC
/* From ECC-TLS draft, used in encoding the curve type in
* ECParameters
*/
#define EXPLICIT_PRIME_CURVE_TYPE 1
#define EXPLICIT_CHAR2_CURVE_TYPE 2
#define NAMED_CURVE_TYPE 3
-#endif /* OPENSSL_NO_EC */
+
+/* Values for the |hash_message| parameter of |s->method->ssl_get_message|. */
+#define SSL_GET_MESSAGE_DONT_HASH_MESSAGE 0
+#define SSL_GET_MESSAGE_HASH_MESSAGE 1
typedef struct cert_pkey_st
{
@@ -459,17 +456,13 @@ typedef struct cert_st
unsigned long mask_a;
/* Client only */
unsigned long mask_ssl;
-#ifndef OPENSSL_NO_DH
DH *dh_tmp;
DH *(*dh_tmp_cb)(SSL *ssl,int is_export,int keysize);
-#endif
-#ifndef OPENSSL_NO_ECDH
EC_KEY *ecdh_tmp;
/* Callback for generating ephemeral ECDH keys */
EC_KEY *(*ecdh_tmp_cb)(SSL *ssl,int is_export,int keysize);
/* Select ECDH parameters automatically */
int ecdh_tmp_auto;
-#endif
/* Flags related to certificates */
unsigned int cert_flags;
CERT_PKEY pkeys[SSL_PKEY_NUM];
@@ -545,12 +538,8 @@ typedef struct sess_cert_st
* so maybe we shouldn't even use the CERT_PKEY type here. */
RSA *peer_rsa_tmp; /* not used for SSL 2 */
-#ifndef OPENSSL_NO_DH
DH *peer_dh_tmp; /* not used for SSL 2 */
-#endif
-#ifndef OPENSSL_NO_ECDH
EC_KEY *peer_ecdh_tmp;
-#endif
} SESS_CERT;
/* Structure containing decoded values of signature algorithms extension */
struct tls_sigalgs_st
@@ -856,14 +845,13 @@ int ssl_cert_type(X509 *x,EVP_PKEY *pkey);
void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher);
STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s);
int ssl_verify_alarm_type(long type);
-void ssl_load_ciphers(void);
int ssl_fill_hello_random(SSL *s, int server, unsigned char *field, int len);
const SSL_CIPHER *ssl3_get_cipher_by_value(uint16_t value);
uint16_t ssl3_get_cipher_value(const SSL_CIPHER *c);
void ssl3_init_finished_mac(SSL *s);
int ssl3_send_server_certificate(SSL *s);
-int ssl3_send_newsession_ticket(SSL *s);
+int ssl3_send_new_session_ticket(SSL *s);
int ssl3_send_cert_status(SSL *s);
int ssl3_get_finished(SSL *s,int state_a,int state_b);
int ssl3_setup_key_block(SSL *s);
@@ -875,7 +863,20 @@ int ssl3_send_alert(SSL *s,int level, int desc);
int ssl3_generate_master_secret(SSL *s, unsigned char *out,
unsigned char *p, int len);
int ssl3_get_req_cert_type(SSL *s,unsigned char *p);
-long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok);
+long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int hash_message, int *ok);
+
+/* ssl3_hash_current_message incorporates the current handshake message into
+ * the handshake hash. */
+void ssl3_hash_current_message(SSL *s);
+
+/* ssl3_cert_verify_hash writes the CertificateVerify hash into the bytes
+ * pointed to by |out| and writes the number of bytes to |*out_len|. |out| must
+ * have room for EVP_MAX_MD_SIZE bytes. For TLS 1.2 and up, |*out_md| is used
+ * for the hash function, otherwise the hash function depends on the type of
+ * |pkey| and is written to |*out_md|. It returns one on success and zero on
+ * failure. */
+int ssl3_cert_verify_hash(SSL *s, uint8_t *out, size_t *out_len, const EVP_MD **out_md, EVP_PKEY *pkey);
+
int ssl3_send_finished(SSL *s, int a, int b, const char *sender,int slen);
int ssl3_num_ciphers(void);
const SSL_CIPHER *ssl3_get_cipher(unsigned int u);
@@ -957,27 +958,24 @@ void dtls1_start_timer(SSL *s);
void dtls1_stop_timer(SSL *s);
int dtls1_is_timer_expired(SSL *s);
void dtls1_double_timeout(SSL *s);
-int dtls1_send_newsession_ticket(SSL *s);
unsigned int dtls1_min_mtu(void);
/* some client-only functions */
-int ssl3_client_hello(SSL *s);
+int ssl3_send_client_hello(SSL *s);
int ssl3_get_server_hello(SSL *s);
int ssl3_get_certificate_request(SSL *s);
int ssl3_get_new_session_ticket(SSL *s);
int ssl3_get_cert_status(SSL *s);
int ssl3_get_server_done(SSL *s);
-int ssl3_send_client_verify(SSL *s);
+int ssl3_send_cert_verify(SSL *s);
int ssl3_send_client_certificate(SSL *s);
int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey);
int ssl3_send_client_key_exchange(SSL *s);
int ssl3_get_server_key_exchange(SSL *s);
int ssl3_get_server_certificate(SSL *s);
int ssl3_check_cert_and_algorithm(SSL *s);
-# ifndef OPENSSL_NO_NEXTPROTONEG
int ssl3_send_next_proto(SSL *s);
int ssl3_send_channel_id(SSL *s);
-# endif
int dtls1_client_hello(SSL *s);
@@ -991,10 +989,8 @@ int ssl3_send_server_done(SSL *s);
int ssl3_get_client_certificate(SSL *s);
int ssl3_get_client_key_exchange(SSL *s);
int ssl3_get_cert_verify(SSL *s);
-#ifndef OPENSSL_NO_NEXTPROTONEG
int ssl3_get_next_proto(SSL *s);
int ssl3_get_channel_id(SSL *s);
-#endif
int ssl23_accept(SSL *s);
int ssl23_connect(SSL *s);
@@ -1009,7 +1005,7 @@ void dtls1_clear(SSL *s);
long dtls1_ctrl(SSL *s,int cmd, long larg, void *parg);
int dtls1_shutdown(SSL *s);
-long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok);
+long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int hash_message, int *ok);
int dtls1_get_record(SSL *s);
int dtls1_dispatch_alert(SSL *s);
int dtls1_enc(SSL *s, int snd);
@@ -1034,12 +1030,9 @@ int tls1_alert_code(int code);
int ssl3_alert_code(int code);
int ssl_ok(SSL *s);
-#ifndef OPENSSL_NO_ECDH
int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s);
-#endif
char ssl_early_callback_init(struct ssl_early_callback_ctx *ctx);
-#ifndef OPENSSL_NO_EC
int tls1_ec_curve_id2nid(uint16_t curve_id);
uint16_t tls1_ec_nid2curve_id(int nid);
@@ -1062,7 +1055,6 @@ int tls1_set_curves(uint16_t **out_curve_ids, size_t *out_curve_ids_len,
const int *curves, size_t ncurves);
int tls1_check_ec_tmp_key(SSL *s, unsigned long id);
-#endif /* OPENSSL_NO_EC */
int tls1_shared_list(SSL *s,
const unsigned char *l1, size_t l1len,
@@ -1071,7 +1063,6 @@ int tls1_shared_list(SSL *s,
unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned char *limit, size_t header_len);
unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned char *limit);
int ssl_parse_clienthello_tlsext(SSL *s, CBS *cbs);
-int ssl_check_clienthello_tlsext_late(SSL *s);
int ssl_parse_serverhello_tlsext(SSL *s, CBS *cbs);
int ssl_prepare_clienthello_tlsext(SSL *s);
int ssl_prepare_serverhello_tlsext(SSL *s);
@@ -1094,6 +1085,19 @@ int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
int idx);
void tls1_set_cert_validity(SSL *s);
+/* ssl_ctx_log_rsa_client_key_exchange logs |premaster| to |ctx|, if logging is
+ * enabled. It returns one on success and zero on failure. The entry is
+ * identified by the first 8 bytes of |encrypted_premaster|. */
+int ssl_ctx_log_rsa_client_key_exchange(SSL_CTX *ctx,
+ const uint8_t *encrypted_premaster, size_t encrypted_premaster_len,
+ const uint8_t *premaster, size_t premaster_len);
+
+/* ssl_ctx_log_master_secret logs |master| to |ctx|, if logging is enabled. It
+ * returns one on success and zero on failure. The entry is identified by
+ * |client_random|. */
+int ssl_ctx_log_master_secret(SSL_CTX *ctx,
+ const uint8_t *client_random, size_t client_random_len,
+ const uint8_t *master, size_t master_len);
int ssl3_can_cutthrough(const SSL *s);
int ssl_get_max_version(const SSL *s);
diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c
index a9f7f9e..7fd1724 100644
--- a/ssl/ssl_sess.c
+++ b/ssl/ssl_sess.c
@@ -152,7 +152,7 @@ static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s);
static void SSL_SESSION_list_add(SSL_CTX *ctx,SSL_SESSION *s);
static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck);
-SSL_SESSION *SSL_magic_pending_session_ptr()
+SSL_SESSION *SSL_magic_pending_session_ptr(void)
{
return (SSL_SESSION*) &g_pending_session_magic;
}
@@ -211,18 +211,7 @@ SSL_SESSION *SSL_SESSION_new(void)
ss->references=1;
ss->timeout = SSL_DEFAULT_SESSION_TIMEOUT;
ss->time=(unsigned long)time(NULL);
- ss->prev=NULL;
- ss->next=NULL;
- ss->tlsext_hostname = NULL;
-#ifndef OPENSSL_NO_EC
- ss->tlsext_ecpointformatlist_length = 0;
- ss->tlsext_ecpointformatlist = NULL;
- ss->tlsext_ellipticcurvelist_length = 0;
- ss->tlsext_ellipticcurvelist = NULL;
-#endif
CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
- ss->psk_identity_hint=NULL;
- ss->psk_identity=NULL;
return(ss);
}
@@ -283,8 +272,8 @@ int ssl_get_new_session(SSL *s, int session)
if ((ss=SSL_SESSION_new()) == NULL) return(0);
/* If the context has a default timeout, use it over the default. */
- if (s->session_ctx->session_timeout != 0)
- ss->timeout=s->session_ctx->session_timeout;
+ if (s->initial_ctx->session_timeout != 0)
+ ss->timeout=s->initial_ctx->session_timeout;
if (s->session != NULL)
{
@@ -345,8 +334,8 @@ int ssl_get_new_session(SSL *s, int session)
CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
if(s->generate_session_id)
cb = s->generate_session_id;
- else if(s->session_ctx->generate_session_id)
- cb = s->session_ctx->generate_session_id;
+ else if(s->initial_ctx->generate_session_id)
+ cb = s->initial_ctx->generate_session_id;
CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
/* Choose a session ID */
tmp = ss->session_id_length;
@@ -469,7 +458,7 @@ int ssl_get_prev_session(SSL *s, const struct ssl_early_callback_ctx *ctx)
if (try_session_cache &&
ret == NULL &&
- !(s->session_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
+ !(s->initial_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
{
SSL_SESSION data;
data.ssl_version=s->version;
@@ -478,7 +467,7 @@ int ssl_get_prev_session(SSL *s, const struct ssl_early_callback_ctx *ctx)
return 0;
memcpy(data.session_id,ctx->session_id,ctx->session_id_len);
CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
- ret=lh_SSL_SESSION_retrieve(s->session_ctx->sessions,&data);
+ ret=lh_SSL_SESSION_retrieve(s->initial_ctx->sessions,&data);
if (ret != NULL)
{
/* don't allow other threads to steal it: */
@@ -486,16 +475,16 @@ int ssl_get_prev_session(SSL *s, const struct ssl_early_callback_ctx *ctx)
}
CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
if (ret == NULL)
- s->session_ctx->stats.sess_miss++;
+ s->initial_ctx->stats.sess_miss++;
}
if (try_session_cache &&
ret == NULL &&
- s->session_ctx->get_session_cb != NULL)
+ s->initial_ctx->get_session_cb != NULL)
{
int copy=1;
- if ((ret=s->session_ctx->get_session_cb(s,(unsigned char *) ctx->session_id,ctx->session_id_len,&copy)))
+ if ((ret=s->initial_ctx->get_session_cb(s,(unsigned char *) ctx->session_id,ctx->session_id_len,&copy)))
{
if (ret == SSL_magic_pending_session_ptr())
{
@@ -504,7 +493,7 @@ int ssl_get_prev_session(SSL *s, const struct ssl_early_callback_ctx *ctx)
* figure out the session asynchronously. */
return PENDING_SESSION;
}
- s->session_ctx->stats.sess_cb_hit++;
+ s->initial_ctx->stats.sess_cb_hit++;
/* Increment reference count now if the session callback
* asks us to do so (note that if the session structures
@@ -516,10 +505,10 @@ int ssl_get_prev_session(SSL *s, const struct ssl_early_callback_ctx *ctx)
/* Add the externally cached session to the internal
* cache as well if and only if we are supposed to. */
- if(!(s->session_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_STORE))
+ if(!(s->initial_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_STORE))
/* The following should not return 1, otherwise,
* things are very strange */
- SSL_CTX_add_session(s->session_ctx,ret);
+ SSL_CTX_add_session(s->initial_ctx,ret);
}
}
@@ -555,16 +544,16 @@ int ssl_get_prev_session(SSL *s, const struct ssl_early_callback_ctx *ctx)
if (ret->timeout < (long)(time(NULL) - ret->time)) /* timeout */
{
- s->session_ctx->stats.sess_timeout++;
+ s->initial_ctx->stats.sess_timeout++;
if (try_session_cache)
{
/* session was from the cache, so remove it */
- SSL_CTX_remove_session(s->session_ctx,ret);
+ SSL_CTX_remove_session(s->initial_ctx,ret);
}
goto err;
}
- s->session_ctx->stats.sess_hit++;
+ s->initial_ctx->stats.sess_hit++;
if (s->session != NULL)
SSL_SESSION_free(s->session);
@@ -721,12 +710,14 @@ void SSL_SESSION_free(SSL_SESSION *ss)
if (ss->ciphers != NULL) sk_SSL_CIPHER_free(ss->ciphers);
if (ss->tlsext_hostname != NULL) OPENSSL_free(ss->tlsext_hostname);
if (ss->tlsext_tick != NULL) OPENSSL_free(ss->tlsext_tick);
-#ifndef OPENSSL_NO_EC
ss->tlsext_ecpointformatlist_length = 0;
if (ss->tlsext_ecpointformatlist != NULL) OPENSSL_free(ss->tlsext_ecpointformatlist);
ss->tlsext_ellipticcurvelist_length = 0;
if (ss->tlsext_ellipticcurvelist != NULL) OPENSSL_free(ss->tlsext_ellipticcurvelist);
-#endif /* OPENSSL_NO_EC */
+ if (ss->tlsext_signed_cert_timestamp_list != NULL)
+ OPENSSL_free(ss->tlsext_signed_cert_timestamp_list);
+ if (ss->ocsp_response != NULL)
+ OPENSSL_free(ss->ocsp_response);
if (ss->psk_identity_hint != NULL)
OPENSSL_free(ss->psk_identity_hint);
if (ss->psk_identity != NULL)
diff --git a/ssl/ssl_stat.c b/ssl/ssl_stat.c
index 361a2fa..2f46b8c 100644
--- a/ssl/ssl_stat.c
+++ b/ssl/ssl_stat.c
@@ -101,7 +101,6 @@ case SSL_ST_OK|SSL_ST_CONNECT: str="ok/connect SSL initialization"; break;
case SSL_ST_BEFORE|SSL_ST_ACCEPT: str="before/accept initialization"; break;
case SSL_ST_OK|SSL_ST_ACCEPT: str="ok/accept SSL initialization"; break;
-#ifndef OPENSSL_NO_SSL3
/* SSLv3 additions */
case SSL3_ST_CW_CLNT_HELLO_A: str="SSLv3 write client hello A"; break;
case SSL3_ST_CW_CLNT_HELLO_B: str="SSLv3 write client hello B"; break;
@@ -169,9 +168,7 @@ case SSL3_ST_SR_KEY_EXCH_A: str="SSLv3 read client key exchange A"; break;
case SSL3_ST_SR_KEY_EXCH_B: str="SSLv3 read client key exchange B"; break;
case SSL3_ST_SR_CERT_VRFY_A: str="SSLv3 read certificate verify A"; break;
case SSL3_ST_SR_CERT_VRFY_B: str="SSLv3 read certificate verify B"; break;
-#endif
-#if !defined(OPENSSL_NO_SSL3)
/* SSLv2/v3 compatibility states */
/* client */
case SSL23_ST_CW_CLNT_HELLO_A: str="SSLv2/v3 write client hello A"; break;
@@ -182,7 +179,6 @@ case SSL23_ST_CR_SRVR_HELLO_B: str="SSLv2/v3 read server hello B"; break;
case SSL23_ST_SR_CLNT_HELLO: str="SSLv2/v3 read client hello"; break;
case SSL23_ST_SR_V2_CLNT_HELLO: str="SSLv2/v3 read v2 client hello"; break;
case SSL23_ST_SR_SWITCH_VERSION: str="SSLv2/v3 switch version"; break;
-#endif
/* DTLS */
case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A: str="DTLS1 read hello verify request A"; break;
@@ -220,7 +216,6 @@ case SSL_ST_ACCEPT: str="AINIT "; break;
case SSL_ST_CONNECT: str="CINIT "; break;
case SSL_ST_OK: str="SSLOK "; break;
-#ifndef OPENSSL_NO_SSL3
/* SSLv3 additions */
case SSL3_ST_SW_FLUSH:
case SSL3_ST_CW_FLUSH: str="3FLUSH"; break;
@@ -283,9 +278,7 @@ case SSL3_ST_SR_KEY_EXCH_A: str="3RCKEA"; break;
case SSL3_ST_SR_KEY_EXCH_B: str="3RCKEB"; break;
case SSL3_ST_SR_CERT_VRFY_A: str="3RCV_A"; break;
case SSL3_ST_SR_CERT_VRFY_B: str="3RCV_B"; break;
-#endif
-#if !defined(OPENSSL_NO_SSL3)
/* SSLv2/v3 compatibility states */
/* client */
case SSL23_ST_CW_CLNT_HELLO_A: str="23WCHA"; break;
@@ -296,7 +289,6 @@ case SSL23_ST_CR_SRVR_HELLO_B: str="23RSHA"; break;
case SSL23_ST_SR_CLNT_HELLO: str="23RCH_"; break;
case SSL23_ST_SR_V2_CLNT_HELLO: str="23R2CH"; break;
case SSL23_ST_SR_SWITCH_VERSION: str="23RSW_"; break;
-#endif
/* DTLS */
case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A: str="DRCHVA"; break;
case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B: str="DRCHVB"; break;
diff --git a/ssl/ssl_test.c b/ssl/ssl_test.c
index 4652e85..68889a0 100644
--- a/ssl/ssl_test.c
+++ b/ssl/ssl_test.c
@@ -14,14 +14,261 @@
#include <stdio.h>
-#include "openssl/ssl.h"
-
-int main() {
- /* Some error codes are special, but the make_errors.go script doesn't know
- * this. This test will catch the case where something regenerates the error
- * codes with the script but doesn't fix up the special ones. */
- if (SSL_R_TLSV1_ALERT_NO_RENEGOTIATION != 100 + SSL_AD_REASON_OFFSET) {
- fprintf(stderr, "SSL alert errors don't match up.\n");
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+
+typedef struct {
+ int id;
+ int in_group_flag;
+} EXPECTED_CIPHER;
+
+typedef struct {
+ /* The rule string to apply. */
+ const char *rule;
+ /* The list of expected ciphers, in order, terminated with -1. */
+ const EXPECTED_CIPHER *expected;
+} CIPHER_TEST;
+
+/* Selecting individual ciphers should work. */
+static const char kRule1[] =
+ "ECDHE-ECDSA-CHACHA20-POLY1305:"
+ "ECDHE-RSA-CHACHA20-POLY1305:"
+ "ECDHE-ECDSA-AES128-GCM-SHA256:"
+ "ECDHE-RSA-AES128-GCM-SHA256";
+
+static const EXPECTED_CIPHER kExpected1[] = {
+ { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305, 0 },
+ { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, 0 },
+ { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 },
+ { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
+ { -1, -1 },
+};
+
+/* + reorders selected ciphers to the end, keeping their relative
+ * order. */
+static const char kRule2[] =
+ "ECDHE-ECDSA-CHACHA20-POLY1305:"
+ "ECDHE-RSA-CHACHA20-POLY1305:"
+ "ECDHE-ECDSA-AES128-GCM-SHA256:"
+ "ECDHE-RSA-AES128-GCM-SHA256:"
+ "+aRSA";
+
+static const EXPECTED_CIPHER kExpected2[] = {
+ { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305, 0 },
+ { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 },
+ { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, 0 },
+ { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
+ { -1, -1 },
+};
+
+/* ! banishes ciphers from future selections. */
+static const char kRule3[] =
+ "!aRSA:"
+ "ECDHE-ECDSA-CHACHA20-POLY1305:"
+ "ECDHE-RSA-CHACHA20-POLY1305:"
+ "ECDHE-ECDSA-AES128-GCM-SHA256:"
+ "ECDHE-RSA-AES128-GCM-SHA256";
+
+static const EXPECTED_CIPHER kExpected3[] = {
+ { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305, 0 },
+ { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 },
+ { -1, -1 },
+};
+
+/* Multiple masks can be ANDed in a single rule. */
+static const char kRule4[] = "kRSA+AESGCM+AES128";
+
+static const EXPECTED_CIPHER kExpected4[] = {
+ { TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, 0 },
+ { -1, -1 },
+};
+
+/* - removes selected ciphers, but preserves their order for future
+ * selections. Select AES_128_GCM, but order the key exchanges RSA,
+ * DHE_RSA, ECDHE_RSA. */
+static const char kRule5[] =
+ "ALL:-kEECDH:-kEDH:-kRSA:-ALL:"
+ "AESGCM+AES128+aRSA";
+
+static const EXPECTED_CIPHER kExpected5[] = {
+ { TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, 0 },
+ { TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
+ { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
+ { -1, -1 },
+};
+
+/* Unknown selectors are no-ops. */
+static const char kRule6[] =
+ "ECDHE-ECDSA-CHACHA20-POLY1305:"
+ "ECDHE-RSA-CHACHA20-POLY1305:"
+ "ECDHE-ECDSA-AES128-GCM-SHA256:"
+ "ECDHE-RSA-AES128-GCM-SHA256:"
+ "BOGUS1:-BOGUS2:+BOGUS3:!BOGUS4";
+
+static const EXPECTED_CIPHER kExpected6[] = {
+ { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305, 0 },
+ { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, 0 },
+ { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 },
+ { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
+ { -1, -1 },
+};
+
+/* Square brackets specify equi-preference groups. */
+static const char kRule7[] =
+ "[ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-ECDSA-AES128-GCM-SHA256]:"
+ "[ECDHE-RSA-CHACHA20-POLY1305]:"
+ "ECDHE-RSA-AES128-GCM-SHA256";
+
+static const EXPECTED_CIPHER kExpected7[] = {
+ { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305, 1 },
+ { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 },
+ { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, 0 },
+ { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
+ { -1, -1 },
+};
+
+/* @STRENGTH performs a stable strength-sort of the selected
+ * ciphers and only the selected ciphers. */
+static const char kRule8[] =
+ /* To simplify things, banish all but {ECDHE_RSA,RSA} x
+ * {CHACHA20,AES_256_CBC,AES_128_CBC,RC4} x SHA1. */
+ "!kEDH:!AESGCM:!3DES:!SHA256:!MD5:!SHA384:"
+ /* Order some ciphers backwards by strength. */
+ "ALL:-CHACHA20:-AES256:-AES128:-RC4:-ALL:"
+ /* Select ECDHE ones and sort them by strength. Ties should resolve
+ * based on the order above. */
+ "kEECDH:@STRENGTH:-ALL:"
+ /* Now bring back everything uses RSA. ECDHE_RSA should be first,
+ * sorted by strength. Then RSA, backwards by strength. */
+ "aRSA";
+
+static const EXPECTED_CIPHER kExpected8[] = {
+ { TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA, 0 },
+ { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, 0 },
+ { TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA, 0 },
+ { TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA, 0 },
+ { SSL3_CK_RSA_RC4_128_SHA, 0 },
+ { TLS1_CK_RSA_WITH_AES_128_SHA, 0 },
+ { TLS1_CK_RSA_WITH_AES_256_SHA, 0 },
+ { -1, -1 },
+};
+
+static CIPHER_TEST kCipherTests[] = {
+ { kRule1, kExpected1 },
+ { kRule2, kExpected2 },
+ { kRule3, kExpected3 },
+ { kRule4, kExpected4 },
+ { kRule5, kExpected5 },
+ { kRule6, kExpected6 },
+ { kRule7, kExpected7 },
+ { kRule8, kExpected8 },
+ { NULL, NULL },
+};
+
+static const char *kBadRules[] = {
+ /* Invalid brackets. */
+ "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256",
+ "RSA]",
+ "[[RSA]]",
+ /* Operators inside brackets */
+ "[+RSA]",
+ /* Unknown directive. */
+ "@BOGUS",
+ /* Empty cipher lists error at SSL_CTX_set_cipher_list. */
+ "",
+ "BOGUS",
+ /* Invalid command. */
+ "?BAR",
+ /* Special operators are not allowed if groups are used. */
+ "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:+FOO",
+ "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:!FOO",
+ "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:-FOO",
+ "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:@STRENGTH",
+ NULL,
+};
+
+static void print_cipher_preference_list(
+ struct ssl_cipher_preference_list_st *list) {
+ size_t i;
+ int in_group = 0;
+ for (i = 0; i < sk_SSL_CIPHER_num(list->ciphers); i++) {
+ const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(list->ciphers, i);
+ if (!in_group && list->in_group_flags[i]) {
+ fprintf(stderr, "\t[\n");
+ in_group = 1;
+ }
+ fprintf(stderr, "\t");
+ if (in_group) {
+ fprintf(stderr, " ");
+ }
+ fprintf(stderr, "%s\n", SSL_CIPHER_get_name(cipher));
+ if (in_group && !list->in_group_flags[i]) {
+ fprintf(stderr, "\t]\n");
+ in_group = 0;
+ }
+ }
+}
+
+static int test_cipher_rule(CIPHER_TEST *t) {
+ int ret = 0;
+ SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method());
+ size_t i;
+
+ if (!SSL_CTX_set_cipher_list(ctx, t->rule)) {
+ fprintf(stderr, "Error testing cipher rule '%s'\n", t->rule);
+ BIO_print_errors_fp(stderr);
+ goto done;
+ }
+
+ /* Compare the two lists. */
+ for (i = 0; i < sk_SSL_CIPHER_num(ctx->cipher_list->ciphers); i++) {
+ const SSL_CIPHER *cipher =
+ sk_SSL_CIPHER_value(ctx->cipher_list->ciphers, i);
+ if (t->expected[i].id != SSL_CIPHER_get_id(cipher) ||
+ t->expected[i].in_group_flag != ctx->cipher_list->in_group_flags[i]) {
+ fprintf(stderr, "Error: cipher rule '%s' evaluted to:\n", t->rule);
+ print_cipher_preference_list(ctx->cipher_list);
+ goto done;
+ }
+ }
+
+ if (t->expected[i].id != -1) {
+ fprintf(stderr, "Error: cipher rule '%s' evaluted to:\n", t->rule);
+ print_cipher_preference_list(ctx->cipher_list);
+ goto done;
+ }
+
+ ret = 1;
+done:
+ SSL_CTX_free(ctx);
+ return ret;
+}
+
+static int test_cipher_rules(void) {
+ size_t i;
+ for (i = 0; kCipherTests[i].rule != NULL; i++) {
+ if (!test_cipher_rule(&kCipherTests[i])) {
+ return 0;
+ }
+ }
+
+ for (i = 0; kBadRules[i] != NULL; i++) {
+ SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method());
+ if (SSL_CTX_set_cipher_list(ctx, kBadRules[i])) {
+ fprintf(stderr, "Cipher rule '%s' unexpectedly succeeded\n", kBadRules[i]);
+ return 0;
+ }
+ ERR_clear_error();
+ SSL_CTX_free(ctx);
+ }
+
+ return 1;
+}
+
+int main(void) {
+ SSL_library_init();
+
+ if (!test_cipher_rules()) {
return 1;
}
diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c
index 743c359..ca6bf6c 100644
--- a/ssl/t1_enc.c
+++ b/ssl/t1_enc.c
@@ -495,9 +495,8 @@ int tls1_change_cipher_state(SSL *s, int which)
unsigned key_len, iv_len, mac_secret_len;
const unsigned char *key_data;
- /* Reset sequence number to zero.
- * TODO(davidben): Is this redundant with dtls1_reset_seq_numbers? */
- if (SSL_IS_DTLS(s))
+ /* Reset sequence number to zero. */
+ if (!SSL_IS_DTLS(s))
memset(is_read ? s->s3->read_sequence : s->s3->write_sequence, 0, 8);
/* key_arg is used for SSLv2. We don't need it for TLS. */
@@ -522,11 +521,7 @@ int tls1_change_cipher_state(SSL *s, int which)
else
{
key_len = EVP_CIPHER_key_length(cipher);
-
- if (EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE)
- iv_len = EVP_GCM_TLS_FIXED_IV_LEN;
- else
- iv_len = EVP_CIPHER_iv_length(cipher);
+ iv_len = EVP_CIPHER_iv_length(cipher);
}
key_data = s->s3->tmp.key_block;
@@ -601,7 +596,9 @@ int tls1_setup_key_block(SSL *s)
goto cipher_unavailable_err;
key_len = EVP_AEAD_key_length(aead);
iv_len = SSL_CIPHER_AEAD_FIXED_NONCE_LEN(s->session->cipher);
- if (!ssl_cipher_get_mac(s->session, &hash, &mac_type, &mac_secret_size))
+ if ((s->session->cipher->algorithm2 &
+ SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD) &&
+ !ssl_cipher_get_mac(s->session, &hash, &mac_type, &mac_secret_size))
goto cipher_unavailable_err;
/* For "stateful" AEADs (i.e. compatibility with pre-AEAD
* cipher suites) the key length reported by
@@ -618,11 +615,7 @@ int tls1_setup_key_block(SSL *s)
if (!ssl_cipher_get_evp(s->session,&c,&hash,&mac_type,&mac_secret_size))
goto cipher_unavailable_err;
key_len = EVP_CIPHER_key_length(c);
-
- if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE)
- iv_len = EVP_GCM_TLS_FIXED_IV_LEN;
- else
- iv_len = EVP_CIPHER_iv_length(c);
+ iv_len = EVP_CIPHER_iv_length(c);
}
s->s3->tmp.new_aead=aead;
@@ -676,10 +669,8 @@ printf("\nkey block\n");
if (s->session->cipher != NULL)
{
-#ifndef OPENSSL_NO_RC4
if (s->session->cipher->algorithm_enc == SSL_RC4)
s->s3->need_record_splitting = 0;
-#endif
}
}
@@ -914,11 +905,6 @@ int tls1_enc(SSL *s, int send)
/* we need to add 'i' padding bytes of value j */
j=i-1;
- if (s->options & SSL_OP_TLS_BLOCK_PADDING_BUG)
- {
- if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG)
- j++;
- }
for (k=(int)l; k<(int)(l+i); k++)
rec->input[k]=j;
l+=i;
@@ -954,12 +940,6 @@ int tls1_enc(SSL *s, int send)
?(i<0)
:(i==0))
return -1; /* AEAD can fail to verify MAC */
- if (EVP_CIPHER_mode(enc) == EVP_CIPH_GCM_MODE && !send)
- {
- rec->data += EVP_GCM_TLS_EXPLICIT_IV_LEN;
- rec->input += EVP_GCM_TLS_EXPLICIT_IV_LEN;
- rec->length -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
- }
#ifdef KSSL_DEBUG
{
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 855d1d0..eccf875 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -121,8 +121,8 @@
static int tls_decrypt_ticket(SSL *s, const unsigned char *tick, int ticklen,
const unsigned char *sess_id, int sesslen,
SSL_SESSION **psess);
-static int ssl_check_clienthello_tlsext_early(SSL *s);
-int ssl_check_serverhello_tlsext(SSL *s);
+static int ssl_check_clienthello_tlsext(SSL *s);
+static int ssl_check_serverhello_tlsext(SSL *s);
SSL3_ENC_METHOD TLSv1_enc_data={
tls1_enc,
@@ -365,7 +365,6 @@ SSL_early_callback_ctx_extension_get(const struct ssl_early_callback_ctx *ctx,
return 0;
}
-#ifndef OPENSSL_NO_EC
static const int nid_list[] =
{
@@ -704,14 +703,6 @@ int tls1_check_ec_tmp_key(SSL *s, unsigned long cid)
#endif
}
-#else
-
-static int tls1_check_cert_param(SSL *s, X509 *x, int set_ee_md)
- {
- return 1;
- }
-
-#endif /* OPENSSL_NO_EC */
/* List of supported signature algorithms and hashes. Should make this
@@ -720,11 +711,7 @@ static int tls1_check_cert_param(SSL *s, X509 *x, int set_ee_md)
#define tlsext_sigalg_rsa(md) md, TLSEXT_signature_rsa,
-#ifdef OPENSSL_NO_ECDSA
-#define tlsext_sigalg_ecdsa(md) /* */
-#else
#define tlsext_sigalg_ecdsa(md) md, TLSEXT_signature_ecdsa,
-#endif
#define tlsext_sigalg(md) \
tlsext_sigalg_rsa(md) \
@@ -735,9 +722,7 @@ static const uint8_t tls12_sigalgs[] = {
tlsext_sigalg(TLSEXT_hash_sha384)
tlsext_sigalg(TLSEXT_hash_sha256)
tlsext_sigalg(TLSEXT_hash_sha224)
-#ifndef OPENSSL_NO_SHA
tlsext_sigalg(TLSEXT_hash_sha1)
-#endif
};
size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs)
{
@@ -793,7 +778,6 @@ int tls12_check_peer_sigalg(const EVP_MD **out_md, int *out_alert,
*out_alert = SSL_AD_ILLEGAL_PARAMETER;
return 0;
}
-#ifndef OPENSSL_NO_EC
if (pkey->type == EVP_PKEY_EC)
{
uint16_t curve_id;
@@ -811,7 +795,6 @@ int tls12_check_peer_sigalg(const EVP_MD **out_md, int *out_alert,
return 0;
}
}
-#endif
/* Check signature matches a type we sent */
sent_sigslen = tls12_get_psigalgs(s, &sent_sigs);
@@ -872,11 +855,9 @@ void ssl_set_client_disabled(SSL *s)
case TLSEXT_signature_rsa:
have_rsa = 1;
break;
-#ifndef OPENSSL_NO_ECDSA
case TLSEXT_signature_ecdsa:
have_ecdsa = 1;
break;
-#endif
}
}
/* Disable auth if we don't include any appropriate signature
@@ -907,7 +888,6 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned c
int extdatalen=0;
unsigned char *ret = buf;
unsigned char *orig = buf;
-#ifndef OPENSSL_NO_EC
/* See if we support any ECC ciphersuites */
int using_ecc = 0;
if (s->version >= TLS1_VERSION || SSL_IS_DTLS(s))
@@ -929,7 +909,6 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned c
}
}
}
-#endif
/* don't add extensions for SSLv3 unless doing secure renegotiation */
if (s->client_version == SSL3_VERSION
@@ -1046,58 +1025,24 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned c
ret += salglen;
}
- /* TODO(fork): we probably want OCSP stapling, but it currently pulls in a lot of code. */
-#if 0
- if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp)
+ if (s->ocsp_stapling_enabled)
{
- int i;
- long extlen, idlen, itmp;
- OCSP_RESPID *id;
+ /* The status_request extension is excessively extensible at
+ * every layer. On the client, only support requesting OCSP
+ * responses with an empty responder_id_list and no
+ * extensions. */
+ if (limit - ret - 4 - 1 - 2 - 2 < 0) return NULL;
- idlen = 0;
- for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++)
- {
- id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i);
- itmp = i2d_OCSP_RESPID(id, NULL);
- if (itmp <= 0)
- return NULL;
- idlen += itmp + 2;
- }
-
- if (s->tlsext_ocsp_exts)
- {
- extlen = i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, NULL);
- if (extlen < 0)
- return NULL;
- }
- else
- extlen = 0;
-
- if ((long)(limit - ret - 7 - extlen - idlen) < 0) return NULL;
s2n(TLSEXT_TYPE_status_request, ret);
- if (extlen + idlen > 0xFFF0)
- return NULL;
- s2n(extlen + idlen + 5, ret);
+ s2n(1 + 2 + 2, ret);
+ /* status_type */
*(ret++) = TLSEXT_STATUSTYPE_ocsp;
- s2n(idlen, ret);
- for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++)
- {
- /* save position of id len */
- unsigned char *q = ret;
- id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, i);
- /* skip over id len */
- ret += 2;
- itmp = i2d_OCSP_RESPID(id, &ret);
- /* write id len */
- s2n(itmp, q);
- }
- s2n(extlen, ret);
- if (extlen > 0)
- i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, &ret);
+ /* responder_id_list - empty */
+ s2n(0, ret);
+ /* request_extensions - empty */
+ s2n(0, ret);
}
-#endif
-#ifndef OPENSSL_NO_NEXTPROTONEG
if (s->ctx->next_proto_select_cb && !s->s3->tmp.finish_md_len)
{
/* The client advertises an emtpy extension to indicate its
@@ -1107,7 +1052,16 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned c
s2n(TLSEXT_TYPE_next_proto_neg,ret);
s2n(0,ret);
}
-#endif
+
+ if (s->signed_cert_timestamps_enabled && !s->s3->tmp.finish_md_len)
+ {
+ /* The client advertises an empty extension to indicate its support for
+ * certificate timestamps. */
+ if (limit - ret - 4 < 0)
+ return NULL;
+ s2n(TLSEXT_TYPE_certificate_timestamp,ret);
+ s2n(0,ret);
+ }
if (s->alpn_client_proto_list && !s->s3->tmp.finish_md_len)
{
@@ -1145,7 +1099,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned c
s2n(TLSEXT_TYPE_use_srtp,ret);
s2n(el,ret);
- if(ssl_add_clienthello_use_srtp_ext(s, ret, &el, el))
+ if(!ssl_add_clienthello_use_srtp_ext(s, ret, &el, el))
{
OPENSSL_PUT_ERROR(SSL, ssl_add_clienthello_tlsext, ERR_R_INTERNAL_ERROR);
return NULL;
@@ -1153,7 +1107,6 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned c
ret += el;
}
-#ifndef OPENSSL_NO_EC
if (using_ecc)
{
/* Add TLS extension ECPointFormats to the ClientHello message */
@@ -1203,7 +1156,6 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned c
s2n(curves[i], ret);
}
}
-#endif /* OPENSSL_NO_EC */
#ifdef TLSEXT_TYPE_padding
/* Add padding to workaround bugs in F5 terminators.
@@ -1248,15 +1200,11 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned c
int extdatalen=0;
unsigned char *orig = buf;
unsigned char *ret = buf;
-#ifndef OPENSSL_NO_NEXTPROTONEG
int next_proto_neg_seen;
-#endif
-#ifndef OPENSSL_NO_EC
unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth;
int using_ecc = (alg_k & SSL_kEECDH) || (alg_a & SSL_aECDSA);
using_ecc = using_ecc && (s->session->tlsext_ecpointformatlist != NULL);
-#endif
/* don't add extensions for SSLv3, unless doing secure renegotiation */
if (s->version == SSL3_VERSION && !s->s3->send_connection_binding)
return orig;
@@ -1264,7 +1212,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned c
ret+=2;
if (ret>=limit) return NULL; /* this really never occurs, but ... */
- if (!s->hit && s->servername_done == 1 && s->session->tlsext_hostname != NULL)
+ if (!s->hit && s->should_ack_sni && s->session->tlsext_hostname != NULL)
{
if ((long)(limit - ret - 4) < 0) return NULL;
@@ -1296,7 +1244,6 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned c
ret += el;
}
-#ifndef OPENSSL_NO_EC
if (using_ecc)
{
const unsigned char *plist;
@@ -1322,7 +1269,6 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned c
}
/* Currently the server should not respond with a SupportedCurves extension */
-#endif /* OPENSSL_NO_EC */
if (s->tlsext_ticket_expected
&& !(SSL_get_options(s) & SSL_OP_NO_TICKET))
@@ -1332,7 +1278,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned c
s2n(0,ret);
}
- if (s->tlsext_status_expected)
+ if (s->s3->tmp.certificate_status_expected)
{
if ((long)(limit - ret - 4) < 0) return NULL;
s2n(TLSEXT_TYPE_status_request,ret);
@@ -1350,7 +1296,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned c
s2n(TLSEXT_TYPE_use_srtp,ret);
s2n(el,ret);
- if(ssl_add_serverhello_use_srtp_ext(s, ret, &el, el))
+ if(!ssl_add_serverhello_use_srtp_ext(s, ret, &el, el))
{
OPENSSL_PUT_ERROR(SSL, ssl_add_serverhello_tlsext, ERR_R_INTERNAL_ERROR);
return NULL;
@@ -1358,7 +1304,6 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned c
ret+=el;
}
-#ifndef OPENSSL_NO_NEXTPROTONEG
next_proto_neg_seen = s->s3->next_proto_neg_seen;
s->s3->next_proto_neg_seen = 0;
if (next_proto_neg_seen && s->ctx->next_protos_advertised_cb)
@@ -1378,7 +1323,6 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned c
s->s3->next_proto_neg_seen = 1;
}
}
-#endif
if (s->s3->alpn_selected)
{
@@ -1474,11 +1418,9 @@ static int ssl_scan_clienthello_tlsext(SSL *s, CBS *cbs, int *out_alert)
CBS extensions;
size_t i;
- s->servername_done = 0;
- s->tlsext_status_type = -1;
-#ifndef OPENSSL_NO_NEXTPROTONEG
+ s->should_ack_sni = 0;
s->s3->next_proto_neg_seen = 0;
-#endif
+ s->s3->tmp.certificate_status_expected = 0;
if (s->s3->alpn_selected)
{
@@ -1505,23 +1447,6 @@ static int ssl_scan_clienthello_tlsext(SSL *s, CBS *cbs, int *out_alert)
s->cert->pkeys[i].valid_flags = 0;
}
- /* TODO(fork): we probably want OCSP stapling support, but this pulls in
- * a lot of code. */
-#if 0
- /* Clear OCSP state. */
- s->tlsext_status_type = -1;
- if (s->tlsext_ocsp_ids)
- {
- sk_OCSP_RESPID_pop_free(s->tlsext_ocsp_ids, OCSP_RESPID_free);
- s->tlsext_ocsp_ids = NULL;
- }
- if (s->tlsext_ocsp_exts)
- {
- sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts, X509_EXTENSION_free);
- s->tlsext_ocsp_exts = NULL;
- }
-#endif
-
/* There may be no extensions. */
if (CBS_len(cbs) == 0)
{
@@ -1581,6 +1506,7 @@ static int ssl_scan_clienthello_tlsext(SSL *s, CBS *cbs, int *out_alert)
if (type == TLSEXT_TYPE_server_name)
{
CBS server_name_list;
+ char have_seen_host_name = 0;
if (!CBS_get_u16_length_prefixed(&extension, &server_name_list) ||
CBS_len(&server_name_list) < 1 ||
@@ -1607,50 +1533,53 @@ static int ssl_scan_clienthello_tlsext(SSL *s, CBS *cbs, int *out_alert)
if (name_type != TLSEXT_NAMETYPE_host_name)
continue;
+ if (have_seen_host_name)
+ {
+ /* The ServerNameList MUST NOT contain
+ * more than one name of the same
+ * name_type. */
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ have_seen_host_name = 1;
+
+ if (!CBS_get_u16_length_prefixed(&server_name_list, &host_name) ||
+ CBS_len(&host_name) < 1)
+ {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ if (CBS_len(&host_name) > TLSEXT_MAXLEN_host_name ||
+ CBS_contains_zero_byte(&host_name))
+ {
+ *out_alert = SSL_AD_UNRECOGNIZED_NAME;
+ return 0;
+ }
+
if (!s->hit)
{
+ assert(s->session->tlsext_hostname == NULL);
if (s->session->tlsext_hostname)
{
- /* The ServerNameList MUST NOT
- contain more than one name of
- the same name_type. */
+ /* This should be impossible. */
*out_alert = SSL_AD_DECODE_ERROR;
return 0;
}
- if (!CBS_get_u16_length_prefixed(&server_name_list, &host_name) ||
- CBS_len(&host_name) < 1)
- {
- *out_alert = SSL_AD_DECODE_ERROR;
- return 0;
- }
-
- if (CBS_len(&host_name) > TLSEXT_MAXLEN_host_name ||
- CBS_contains_zero_byte(&host_name))
- {
- *out_alert = SSL_AD_UNRECOGNIZED_NAME;
- return 0;
- }
-
/* Copy the hostname as a string. */
if (!CBS_strdup(&host_name, &s->session->tlsext_hostname))
{
*out_alert = SSL_AD_INTERNAL_ERROR;
return 0;
}
- s->servername_done = 1;
- }
- else
- {
- s->servername_done = s->session->tlsext_hostname
- && strlen(s->session->tlsext_hostname) == CBS_len(&host_name)
- && strncmp(s->session->tlsext_hostname,
- (char *)CBS_data(&host_name), CBS_len(&host_name)) == 0;
+
+ s->should_ack_sni = 1;
}
}
}
-#ifndef OPENSSL_NO_EC
else if (type == TLSEXT_TYPE_ec_point_formats)
{
CBS ec_point_format_list;
@@ -1719,7 +1648,6 @@ static int ssl_scan_clienthello_tlsext(SSL *s, CBS *cbs, int *out_alert)
s->session->tlsext_ellipticcurvelist_length = num_curves;
}
}
-#endif /* OPENSSL_NO_EC */
else if (type == TLSEXT_TYPE_session_ticket)
{
if (s->tls_session_ticket_ext_cb &&
@@ -1772,120 +1700,6 @@ static int ssl_scan_clienthello_tlsext(SSL *s, CBS *cbs, int *out_alert)
}
}
- /* TODO(fork): we probably want OCSP stapling support, but this pulls in a lot of code. */
-#if 0
- else if (type == TLSEXT_TYPE_status_request)
- {
- uint8_t status_type;
- CBS responder_id_list;
- CBS request_extensions;
-
- if (!CBS_get_u8(&extension, &status_type))
- {
- *out_alert = SSL_AD_DECODE_ERROR;
- return 0;
- }
-
- /* Only OCSP is supported. */
- if (status_type != TLSEXT_STATUSTYPE_ocsp)
- continue;
-
- s->tlsext_status_type = status_type;
-
- /* Extension consists of a responder_id_list and
- * request_extensions. */
- if (!CBS_get_u16_length_prefixed(&extension, &responder_id_list) ||
- !CBS_get_u16_length_prefixed(&extension, &request_extensions) ||
- CBS_len(&extension) != 0)
- {
- *out_alert = SSL_AD_DECODE_ERROR;
- return 0;
- }
-
- if (CBS_len(&responder_id_list) > 0)
- {
- s->tlsext_ocsp_ids = sk_OCSP_RESPID_new_null();
- if (s->tlsext_ocsp_ids == NULL)
- {
- *out_alert = SSL_AD_INTERNAL_ERROR;
- return 0;
- }
- }
-
- /* Parse out the responder IDs. */
- while (CBS_len(&responder_id_list) > 0)
- {
- CBS responder_id;
- OCSP_RESPID *id;
- const uint8_t *data;
-
- /* Each ResponderID must have size at least 1. */
- if (!CBS_get_u16_length_prefixed(&responder_id_list, &responder_id) ||
- CBS_len(&responder_id) < 1)
- {
- *out_alert = SSL_AD_DECODE_ERROR;
- return 0;
- }
-
- /* TODO(fork): Add CBS versions of d2i_FOO_BAR. */
- data = CBS_data(&responder_id);
- id = d2i_OCSP_RESPID(NULL, &data, CBS_len(&responder_id));
- if (!id)
- {
- *out_alert = SSL_AD_DECODE_ERROR;
- return 0;
- }
- if (!CBS_skip(&responder_id, data - CBS_data(&responder_id)))
- {
- /* This should never happen. */
- *out_alert = SSL_AD_INTERNAL_ERROR;
- OCSP_RESPID_free(id);
- return 0;
- }
- if (CBS_len(&responder_id) != 0)
- {
- *out_alert = SSL_AD_DECODE_ERROR;
- OCSP_RESPID_free(id);
- return 0;
- }
-
- if (!sk_OCSP_RESPID_push(s->tlsext_ocsp_ids, id))
- {
- *out_alert = SSL_AD_INTERNAL_ERROR;
- OCSP_RESPID_free(id);
- return 0;
- }
- }
-
- /* Parse out request_extensions. */
- if (CBS_len(&request_extensions) > 0)
- {
- const uint8_t *data;
-
- data = CBS_data(&request_extensions);
- s->tlsext_ocsp_exts = d2i_X509_EXTENSIONS(NULL,
- &data, CBS_len(&request_extensions));
- if (s->tlsext_ocsp_exts == NULL)
- {
- *out_alert = SSL_AD_DECODE_ERROR;
- return 0;
- }
- if (!CBS_skip(&request_extensions, data - CBS_data(&request_extensions)))
- {
- /* This should never happen. */
- *out_alert = SSL_AD_INTERNAL_ERROR;
- return 0;
- }
- if (CBS_len(&request_extensions) != 0)
- {
- *out_alert = SSL_AD_DECODE_ERROR;
- return 0;
- }
- }
- }
-#endif
-
-#ifndef OPENSSL_NO_NEXTPROTONEG
else if (type == TLSEXT_TYPE_next_proto_neg &&
s->s3->tmp.finish_md_len == 0 &&
s->s3->alpn_selected == NULL)
@@ -1914,7 +1728,6 @@ static int ssl_scan_clienthello_tlsext(SSL *s, CBS *cbs, int *out_alert)
* Finished message could have been computed.) */
s->s3->next_proto_neg_seen = 1;
}
-#endif
else if (type == TLSEXT_TYPE_application_layer_protocol_negotiation &&
s->ctx->alpn_select_cb &&
@@ -1922,10 +1735,8 @@ static int ssl_scan_clienthello_tlsext(SSL *s, CBS *cbs, int *out_alert)
{
if (!tls1_alpn_handle_client_hello(s, &extension, out_alert))
return 0;
-#ifndef OPENSSL_NO_NEXTPROTONEG
/* ALPN takes precedence over NPN. */
s->s3->next_proto_neg_seen = 0;
-#endif
}
else if (type == TLSEXT_TYPE_channel_id &&
@@ -1972,7 +1783,7 @@ static int ssl_scan_clienthello_tlsext(SSL *s, CBS *cbs, int *out_alert)
!(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
{
*out_alert = SSL_AD_HANDSHAKE_FAILURE;
- OPENSSL_PUT_ERROR(SSL, ssl_add_serverhello_tlsext, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
+ OPENSSL_PUT_ERROR(SSL, ssl_scan_clienthello_tlsext, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
return 0;
}
/* If no signature algorithms extension set default values */
@@ -1991,7 +1802,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, CBS *cbs)
return 0;
}
- if (ssl_check_clienthello_tlsext_early(s) <= 0)
+ if (ssl_check_clienthello_tlsext(s) <= 0)
{
OPENSSL_PUT_ERROR(SSL, ssl_parse_clienthello_tlsext, SSL_R_CLIENTHELLO_TLSEXT);
return 0;
@@ -1999,7 +1810,6 @@ int ssl_parse_clienthello_tlsext(SSL *s, CBS *cbs)
return 1;
}
-#ifndef OPENSSL_NO_NEXTPROTONEG
/* ssl_next_proto_validate validates a Next Protocol Negotiation block. No
* elements of zero length are allowed and the set of elements must exactly fill
* the length of the block. */
@@ -2018,7 +1828,6 @@ static char ssl_next_proto_validate(const CBS *cbs)
}
return 1;
}
-#endif
static int ssl_scan_serverhello_tlsext(SSL *s, CBS *cbs, int *out_alert)
{
@@ -2026,11 +1835,13 @@ static int ssl_scan_serverhello_tlsext(SSL *s, CBS *cbs, int *out_alert)
int renegotiate_seen = 0;
CBS extensions;
-#ifndef OPENSSL_NO_NEXTPROTONEG
+ /* TODO(davidben): Move all of these to some per-handshake state that
+ * gets systematically reset on a new handshake; perhaps allocate it
+ * fresh each time so it's not even kept around post-handshake. */
s->s3->next_proto_neg_seen = 0;
-#endif
- s->tlsext_ticket_expected = 0;
+ s->tlsext_ticket_expected = 0;
+ s->s3->tmp.certificate_status_expected = 0;
if (s->s3->alpn_selected)
{
@@ -2087,7 +1898,6 @@ static int ssl_scan_serverhello_tlsext(SSL *s, CBS *cbs, int *out_alert)
}
tlsext_servername = 1;
}
-#ifndef OPENSSL_NO_EC
else if (type == TLSEXT_TYPE_ec_point_formats)
{
CBS ec_point_format_list;
@@ -2110,7 +1920,6 @@ static int ssl_scan_serverhello_tlsext(SSL *s, CBS *cbs, int *out_alert)
}
}
}
-#endif /* OPENSSL_NO_EC */
else if (type == TLSEXT_TYPE_session_ticket)
{
if (s->tls_session_ticket_ext_cb &&
@@ -2138,15 +1947,14 @@ static int ssl_scan_serverhello_tlsext(SSL *s, CBS *cbs, int *out_alert)
*out_alert = SSL_AD_DECODE_ERROR;
return 0;
}
- if (s->tlsext_status_type == -1)
+ if (!s->ocsp_stapling_enabled)
{
*out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
return 0;
}
/* Set a flag to expect a CertificateStatus message */
- s->tlsext_status_expected = 1;
+ s->s3->tmp.certificate_status_expected = 1;
}
-#ifndef OPENSSL_NO_NEXTPROTONEG
else if (type == TLSEXT_TYPE_next_proto_neg && s->s3->tmp.finish_md_len == 0) {
unsigned char *selected;
unsigned char selected_len;
@@ -2182,7 +1990,6 @@ static int ssl_scan_serverhello_tlsext(SSL *s, CBS *cbs, int *out_alert)
s->next_proto_negotiated_len = selected_len;
s->s3->next_proto_neg_seen = 1;
}
-#endif
else if (type == TLSEXT_TYPE_application_layer_protocol_negotiation)
{
CBS protocol_name_list, protocol_name;
@@ -2234,7 +2041,26 @@ static int ssl_scan_serverhello_tlsext(SSL *s, CBS *cbs, int *out_alert)
s->s3->tlsext_channel_id_valid = 1;
s->s3->tlsext_channel_id_new = 1;
}
+ else if (type == TLSEXT_TYPE_certificate_timestamp)
+ {
+ if (CBS_len(&extension) == 0)
+ {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+ /* Session resumption uses the original session information. */
+ if (!s->hit)
+ {
+ if (!CBS_stow(&extension,
+ &s->session->tlsext_signed_cert_timestamp_list,
+ &s->session->tlsext_signed_cert_timestamp_list_length))
+ {
+ *out_alert = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ }
+ }
else if (type == TLSEXT_TYPE_renegotiate)
{
if (!ssl_parse_serverhello_renegotiate_ext(s, &extension, out_alert))
@@ -2301,19 +2127,17 @@ int ssl_prepare_serverhello_tlsext(SSL *s)
return 1;
}
-static int ssl_check_clienthello_tlsext_early(SSL *s)
+static int ssl_check_clienthello_tlsext(SSL *s)
{
int ret=SSL_TLSEXT_ERR_NOACK;
int al = SSL_AD_UNRECOGNIZED_NAME;
-#ifndef OPENSSL_NO_EC
/* The handling of the ECPointFormats extension is done elsewhere, namely in
* ssl3_choose_cipher in s3_lib.c.
*/
/* The handling of the EllipticCurves extension is done elsewhere, namely in
* ssl3_choose_cipher in s3_lib.c.
*/
-#endif
if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0)
ret = s->ctx->tlsext_servername_callback(s, &al, s->ctx->tlsext_servername_arg);
@@ -2328,86 +2152,22 @@ static int ssl_check_clienthello_tlsext_early(SSL *s)
case SSL_TLSEXT_ERR_ALERT_WARNING:
ssl3_send_alert(s,SSL3_AL_WARNING,al);
- return 1;
-
- case SSL_TLSEXT_ERR_NOACK:
- s->servername_done=0;
- default:
- return 1;
- }
- }
-
-int ssl_check_clienthello_tlsext_late(SSL *s)
- {
- int ret = SSL_TLSEXT_ERR_OK;
- int al;
-
- /* If status request then ask callback what to do.
- * Note: this must be called after servername callbacks in case
- * the certificate has changed, and must be called after the cipher
- * has been chosen because this may influence which certificate is sent
- */
- if ((s->tlsext_status_type != -1) && s->ctx && s->ctx->tlsext_status_cb)
- {
- int r;
- CERT_PKEY *certpkey;
- certpkey = ssl_get_server_send_pkey(s);
- /* If no certificate can't return certificate status */
- if (certpkey == NULL)
- {
- s->tlsext_status_expected = 0;
return 1;
- }
- /* Set current certificate to one we will use so
- * SSL_get_certificate et al can pick it up.
- */
- s->cert->key = certpkey;
- r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
- switch (r)
- {
- /* We don't want to send a status request response */
- case SSL_TLSEXT_ERR_NOACK:
- s->tlsext_status_expected = 0;
- break;
- /* status request response should be sent */
- case SSL_TLSEXT_ERR_OK:
- if (s->tlsext_ocsp_resp)
- s->tlsext_status_expected = 1;
- else
- s->tlsext_status_expected = 0;
- break;
- /* something bad happened */
- case SSL_TLSEXT_ERR_ALERT_FATAL:
- ret = SSL_TLSEXT_ERR_ALERT_FATAL;
- al = SSL_AD_INTERNAL_ERROR;
- goto err;
- }
- }
- else
- s->tlsext_status_expected = 0;
-
- err:
- switch (ret)
- {
- case SSL_TLSEXT_ERR_ALERT_FATAL:
- ssl3_send_alert(s, SSL3_AL_FATAL, al);
- return -1;
- case SSL_TLSEXT_ERR_ALERT_WARNING:
- ssl3_send_alert(s, SSL3_AL_WARNING, al);
- return 1;
+ case SSL_TLSEXT_ERR_NOACK:
+ s->should_ack_sni = 0;
+ return 1;
default:
return 1;
}
}
-int ssl_check_serverhello_tlsext(SSL *s)
+static int ssl_check_serverhello_tlsext(SSL *s)
{
int ret=SSL_TLSEXT_ERR_NOACK;
int al = SSL_AD_UNRECOGNIZED_NAME;
-#ifndef OPENSSL_NO_EC
/* If we are client and using an elliptic curve cryptography cipher
* suite, then if server returns an EC point formats lists extension
* it must contain uncompressed.
@@ -2433,61 +2193,29 @@ int ssl_check_serverhello_tlsext(SSL *s)
}
if (!found_uncompressed)
{
- OPENSSL_PUT_ERROR(SSL, ssl_add_serverhello_tlsext, SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST);
+ OPENSSL_PUT_ERROR(SSL, ssl_check_serverhello_tlsext, SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST);
return -1;
}
}
ret = SSL_TLSEXT_ERR_OK;
-#endif /* OPENSSL_NO_EC */
if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0)
ret = s->ctx->tlsext_servername_callback(s, &al, s->ctx->tlsext_servername_arg);
else if (s->initial_ctx != NULL && s->initial_ctx->tlsext_servername_callback != 0)
ret = s->initial_ctx->tlsext_servername_callback(s, &al, s->initial_ctx->tlsext_servername_arg);
- /* If we've requested certificate status and we wont get one
- * tell the callback
- */
- if ((s->tlsext_status_type != -1) && !(s->tlsext_status_expected)
- && s->ctx && s->ctx->tlsext_status_cb)
- {
- int r;
- /* Set resp to NULL, resplen to -1 so callback knows
- * there is no response.
- */
- if (s->tlsext_ocsp_resp)
- {
- OPENSSL_free(s->tlsext_ocsp_resp);
- s->tlsext_ocsp_resp = NULL;
- }
- s->tlsext_ocsp_resplen = -1;
- r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
- if (r == 0)
- {
- al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
- ret = SSL_TLSEXT_ERR_ALERT_FATAL;
- }
- if (r < 0)
- {
- al = SSL_AD_INTERNAL_ERROR;
- ret = SSL_TLSEXT_ERR_ALERT_FATAL;
- }
- }
-
switch (ret)
{
case SSL_TLSEXT_ERR_ALERT_FATAL:
- ssl3_send_alert(s,SSL3_AL_FATAL,al);
+ ssl3_send_alert(s,SSL3_AL_FATAL,al);
return -1;
case SSL_TLSEXT_ERR_ALERT_WARNING:
ssl3_send_alert(s,SSL3_AL_WARNING,al);
- return 1;
-
- case SSL_TLSEXT_ERR_NOACK:
- s->servername_done=0;
- default:
- return 1;
+ return 1;
+
+ default:
+ return 1;
}
}
@@ -2783,14 +2511,10 @@ const EVP_MD *tls12_get_hash(unsigned char hash_alg)
{
switch(hash_alg)
{
-#ifndef OPENSSL_NO_MD5
case TLSEXT_hash_md5:
return EVP_md5();
-#endif
-#ifndef OPENSSL_NO_SHA
case TLSEXT_hash_sha1:
return EVP_sha1();
-#endif
case TLSEXT_hash_sha224:
return EVP_sha224();
@@ -2813,10 +2537,8 @@ static int tls12_get_pkey_idx(unsigned char sig_alg)
{
case TLSEXT_signature_rsa:
return SSL_PKEY_RSA_SIGN;
-#ifndef OPENSSL_NO_ECDSA
case TLSEXT_signature_ecdsa:
return SSL_PKEY_ECC;
-#endif
}
return -1;
}
@@ -3021,10 +2743,8 @@ int tls1_process_sigalgs(SSL *s, const CBS *sigalgs)
c->pkeys[SSL_PKEY_RSA_SIGN].digest = EVP_sha1();
c->pkeys[SSL_PKEY_RSA_ENC].digest = EVP_sha1();
}
-#ifndef OPENSSL_NO_ECDSA
if (!c->pkeys[SSL_PKEY_ECC].digest)
c->pkeys[SSL_PKEY_ECC].digest = EVP_sha1();
-#endif
}
return 1;
}
diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc
index c976e7c..5ee7c65 100644
--- a/ssl/test/bssl_shim.cc
+++ b/ssl/test/bssl_shim.cc
@@ -48,6 +48,20 @@ static const TestConfig *GetConfigPtr(SSL *ssl) {
return (const TestConfig *)SSL_get_ex_data(ssl, g_ex_data_index);
}
+static EVP_PKEY *LoadPrivateKey(const std::string &file) {
+ BIO *bio = BIO_new(BIO_s_file());
+ if (bio == NULL) {
+ return NULL;
+ }
+ if (!BIO_read_filename(bio, file.c_str())) {
+ BIO_free(bio);
+ return NULL;
+ }
+ EVP_PKEY *pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
+ BIO_free(bio);
+ return pkey;
+}
+
static int early_callback_called = 0;
static int select_certificate_callback(const struct ssl_early_callback_ctx *ctx) {
@@ -125,6 +139,29 @@ static int next_proto_select_callback(SSL* ssl,
return SSL_TLSEXT_ERR_OK;
}
+static int alpn_select_callback(SSL* ssl,
+ const uint8_t** out,
+ uint8_t* outlen,
+ const uint8_t* in,
+ unsigned inlen,
+ void* arg) {
+ const TestConfig *config = GetConfigPtr(ssl);
+ if (config->select_alpn.empty())
+ return SSL_TLSEXT_ERR_NOACK;
+
+ if (!config->expected_advertised_alpn.empty() &&
+ (config->expected_advertised_alpn.size() != inlen ||
+ memcmp(config->expected_advertised_alpn.data(),
+ in, inlen) != 0)) {
+ fprintf(stderr, "bad ALPN select callback inputs\n");
+ exit(1);
+ }
+
+ *out = (const uint8_t*)config->select_alpn.data();
+ *outlen = config->select_alpn.size();
+ return SSL_TLSEXT_ERR_OK;
+}
+
static int cookie_generate_callback(SSL *ssl, uint8_t *cookie, size_t *cookie_len) {
*cookie_len = 32;
memset(cookie, 42, *cookie_len);
@@ -199,12 +236,19 @@ static SSL_CTX *setup_ctx(const TestConfig *config) {
SSL_CTX_set_next_protos_advertised_cb(
ssl_ctx, next_protos_advertised_callback, NULL);
- SSL_CTX_set_next_proto_select_cb(
- ssl_ctx, next_proto_select_callback, NULL);
+ if (!config->select_next_proto.empty()) {
+ SSL_CTX_set_next_proto_select_cb(ssl_ctx, next_proto_select_callback, NULL);
+ }
+
+ if (!config->select_alpn.empty()) {
+ SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_callback, NULL);
+ }
SSL_CTX_set_cookie_generate_cb(ssl_ctx, cookie_generate_callback);
SSL_CTX_set_cookie_verify_cb(ssl_ctx, cookie_verify_callback);
+ ssl_ctx->tlsext_channel_id_enabled_new = 1;
+
DH_free(dh);
return ssl_ctx;
@@ -300,6 +344,33 @@ static int do_exchange(SSL_SESSION **out_session,
if (config->cookie_exchange) {
SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE);
}
+ if (config->tls_d5_bug) {
+ SSL_set_options(ssl, SSL_OP_TLS_D5_BUG);
+ }
+ if (!config->expected_channel_id.empty()) {
+ SSL_enable_tls_channel_id(ssl);
+ }
+ if (!config->send_channel_id.empty()) {
+ EVP_PKEY *pkey = LoadPrivateKey(config->send_channel_id);
+ if (pkey == NULL) {
+ BIO_print_errors_fp(stdout);
+ return 1;
+ }
+ SSL_enable_tls_channel_id(ssl);
+ if (!SSL_set1_tls_channel_id(ssl, pkey)) {
+ EVP_PKEY_free(pkey);
+ BIO_print_errors_fp(stdout);
+ return 1;
+ }
+ EVP_PKEY_free(pkey);
+ }
+ if (!config->host_name.empty()) {
+ SSL_set_tlsext_host_name(ssl, config->host_name.c_str());
+ }
+ if (!config->advertise_alpn.empty()) {
+ SSL_set_alpn_protos(ssl, (const uint8_t *)config->advertise_alpn.data(),
+ config->advertise_alpn.size());
+ }
BIO *bio = BIO_new_fd(fd, 1 /* take ownership */);
if (bio == NULL) {
@@ -340,8 +411,9 @@ static int do_exchange(SSL_SESSION **out_session,
return 2;
}
- if (is_resume && !SSL_session_reused(ssl)) {
- fprintf(stderr, "session was not reused\n");
+ if (is_resume && (SSL_session_reused(ssl) == config->expect_session_miss)) {
+ fprintf(stderr, "session was%s reused\n",
+ SSL_session_reused(ssl) ? "" : " not");
return 2;
}
@@ -363,7 +435,7 @@ static int do_exchange(SSL_SESSION **out_session,
if (!config->expected_certificate_types.empty()) {
uint8_t *certificate_types;
int num_certificate_types =
- SSL_get0_certificate_types(ssl, &certificate_types);
+ SSL_get0_certificate_types(ssl, &certificate_types);
if (num_certificate_types !=
(int)config->expected_certificate_types.size() ||
memcmp(certificate_types,
@@ -386,6 +458,32 @@ static int do_exchange(SSL_SESSION **out_session,
}
}
+ if (!config->expected_alpn.empty()) {
+ const uint8_t *alpn_proto;
+ unsigned alpn_proto_len;
+ SSL_get0_alpn_selected(ssl, &alpn_proto, &alpn_proto_len);
+ if (alpn_proto_len != config->expected_alpn.size() ||
+ memcmp(alpn_proto, config->expected_alpn.data(),
+ alpn_proto_len) != 0) {
+ fprintf(stderr, "negotiated alpn proto mismatch\n");
+ return 2;
+ }
+ }
+
+ if (!config->expected_channel_id.empty()) {
+ uint8_t channel_id[64];
+ if (!SSL_get_tls_channel_id(ssl, channel_id, sizeof(channel_id))) {
+ fprintf(stderr, "no channel id negotiated\n");
+ return 2;
+ }
+ if (config->expected_channel_id.size() != 64 ||
+ memcmp(config->expected_channel_id.data(),
+ channel_id, 64) != 0) {
+ fprintf(stderr, "channel id mismatch\n");
+ return 2;
+ }
+ }
+
if (config->write_different_record_sizes) {
if (config->is_dtls) {
fprintf(stderr, "write_different_record_sizes not supported for DTLS\n");
@@ -423,6 +521,12 @@ static int do_exchange(SSL_SESSION **out_session,
}
}
} else {
+ if (config->shim_writes_first) {
+ int w;
+ do {
+ w = SSL_write(ssl, "hello", 5);
+ } while (config->async && retry_async(ssl, w, bio));
+ }
for (;;) {
uint8_t buf[512];
int n;
diff --git a/ssl/test/runner/channel_id_key.pem b/ssl/test/runner/channel_id_key.pem
new file mode 100644
index 0000000..604752b
--- /dev/null
+++ b/ssl/test/runner/channel_id_key.pem
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIPwxu50c7LEhVNRYJFRWBUnoaz7JSos96T5hBp4rjyptoAoGCCqGSM49
+AwEHoUQDQgAEzFSVTE5guxJRQ0VbZ8dicPs5e/DT7xpW7Yc9hq0VOchv7cbXuI/T
+CwadDjGWX/oaz0ftFqrVmfkwZu+C58ioWg==
+-----END EC PRIVATE KEY-----
diff --git a/ssl/test/runner/cipher_suites.go b/ssl/test/runner/cipher_suites.go
index ed26f09..6cd0de9 100644
--- a/ssl/test/runner/cipher_suites.go
+++ b/ssl/test/runner/cipher_suites.go
@@ -12,6 +12,8 @@ import (
"crypto/md5"
"crypto/rc4"
"crypto/sha1"
+ "crypto/sha256"
+ "crypto/sha512"
"crypto/x509"
"hash"
)
@@ -79,20 +81,29 @@ var cipherSuites = []*cipherSuite{
{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadAESGCM},
{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadAESGCM},
{TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
+ {TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
{TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, suiteECDHE | suiteNoDTLS, cipherRC4, macSHA1, nil},
{TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteNoDTLS, cipherRC4, macSHA1, nil},
+ {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheRSAKA, suiteECDHE | suiteTLS12, cipherAES, macSHA256, nil},
+ {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, cipherAES, macSHA256, nil},
{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
{TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
+ {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, 32, 48, 16, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, cipherAES, macSHA384, nil},
+ {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, 32, 48, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteSHA384, cipherAES, macSHA384, nil},
{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, dheRSAKA, suiteTLS12, nil, nil, aeadAESGCM},
{TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, dheRSAKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
+ {TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, dheRSAKA, suiteTLS12, cipherAES, macSHA256, nil},
+ {TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, 32, 32, 16, dheRSAKA, suiteTLS12, cipherAES, macSHA256, nil},
{TLS_DHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, dheRSAKA, 0, cipherAES, macSHA1, nil},
{TLS_DHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, dheRSAKA, 0, cipherAES, macSHA1, nil},
{TLS_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, rsaKA, suiteTLS12, nil, nil, aeadAESGCM},
{TLS_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, rsaKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
{TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, suiteNoDTLS, cipherRC4, macSHA1, nil},
{TLS_RSA_WITH_RC4_128_MD5, 16, 16, 0, rsaKA, suiteNoDTLS, cipherRC4, macMD5, nil},
+ {TLS_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, rsaKA, suiteTLS12, cipherAES, macSHA256, nil},
+ {TLS_RSA_WITH_AES_256_CBC_SHA256, 32, 32, 16, rsaKA, suiteTLS12, cipherAES, macSHA256, nil},
{TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
{TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
{TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, suiteECDHE, cipher3DES, macSHA1, nil},
@@ -146,6 +157,30 @@ func macMD5(version uint16, key []byte) macFunction {
return tls10MAC{hmac.New(md5.New, key)}
}
+func macSHA256(version uint16, key []byte) macFunction {
+ if version == VersionSSL30 {
+ mac := ssl30MAC{
+ h: sha256.New(),
+ key: make([]byte, len(key)),
+ }
+ copy(mac.key, key)
+ return mac
+ }
+ return tls10MAC{hmac.New(sha256.New, key)}
+}
+
+func macSHA384(version uint16, key []byte) macFunction {
+ if version == VersionSSL30 {
+ mac := ssl30MAC{
+ h: sha512.New384(),
+ key: make([]byte, len(key)),
+ }
+ copy(mac.key, key)
+ return mac
+ }
+ return tls10MAC{hmac.New(sha512.New384, key)}
+}
+
type macFunction interface {
Size() int
MAC(digestBuf, seq, header, length, data []byte) []byte
@@ -304,6 +339,10 @@ const (
TLS_DHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0x0033
TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035
TLS_DHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0039
+ TLS_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003c
+ TLS_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x003d
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x0067
+ TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x006b
TLS_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009c
TLS_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009d
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009e
@@ -315,8 +354,13 @@ const (
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xc012
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xc013
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xc014
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02f
+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 uint16 = 0xc023
+ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 uint16 = 0xc024
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0xc027
+ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 uint16 = 0xc028
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02b
+ TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc02c
+ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02f
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc030
fallbackSCSV uint16 = 0x5600
)
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index f14f4e9..cf244bc 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -7,6 +7,7 @@ package main
import (
"container/list"
"crypto"
+ "crypto/ecdsa"
"crypto/rand"
"crypto/x509"
"fmt"
@@ -47,19 +48,20 @@ const (
// TLS handshake message types.
const (
- typeClientHello uint8 = 1
- typeServerHello uint8 = 2
- typeHelloVerifyRequest uint8 = 3
- typeNewSessionTicket uint8 = 4
- typeCertificate uint8 = 11
- typeServerKeyExchange uint8 = 12
- typeCertificateRequest uint8 = 13
- typeServerHelloDone uint8 = 14
- typeCertificateVerify uint8 = 15
- typeClientKeyExchange uint8 = 16
- typeFinished uint8 = 20
- typeCertificateStatus uint8 = 22
- typeNextProtocol uint8 = 67 // Not IANA assigned
+ typeClientHello uint8 = 1
+ typeServerHello uint8 = 2
+ typeHelloVerifyRequest uint8 = 3
+ typeNewSessionTicket uint8 = 4
+ typeCertificate uint8 = 11
+ typeServerKeyExchange uint8 = 12
+ typeCertificateRequest uint8 = 13
+ typeServerHelloDone uint8 = 14
+ typeCertificateVerify uint8 = 15
+ typeClientKeyExchange uint8 = 16
+ typeFinished uint8 = 20
+ typeCertificateStatus uint8 = 22
+ typeNextProtocol uint8 = 67 // Not IANA assigned
+ typeEncryptedExtensions uint8 = 203 // Not IANA assigned
)
// TLS compression types.
@@ -74,9 +76,11 @@ const (
extensionSupportedCurves uint16 = 10
extensionSupportedPoints uint16 = 11
extensionSignatureAlgorithms uint16 = 13
+ extensionALPN uint16 = 16
extensionSessionTicket uint16 = 35
extensionNextProtoNeg uint16 = 13172 // not IANA assigned
extensionRenegotiationInfo uint16 = 0xff01
+ extensionChannelID uint16 = 30032 // not IANA assigned
)
// TLS signaling cipher suite values
@@ -135,24 +139,24 @@ const (
// signatureAndHash mirrors the TLS 1.2, SignatureAndHashAlgorithm struct. See
// RFC 5246, section A.4.1.
type signatureAndHash struct {
- hash, signature uint8
+ signature, hash uint8
}
// supportedSKXSignatureAlgorithms contains the signature and hash algorithms
// that the code advertises as supported in a TLS 1.2 ClientHello.
var supportedSKXSignatureAlgorithms = []signatureAndHash{
- {hashSHA256, signatureRSA},
- {hashSHA256, signatureECDSA},
- {hashSHA1, signatureRSA},
- {hashSHA1, signatureECDSA},
+ {signatureRSA, hashSHA256},
+ {signatureECDSA, hashSHA256},
+ {signatureRSA, hashSHA1},
+ {signatureECDSA, hashSHA1},
}
// supportedClientCertSignatureAlgorithms contains the signature and hash
// algorithms that the code advertises as supported in a TLS 1.2
// CertificateRequest.
var supportedClientCertSignatureAlgorithms = []signatureAndHash{
- {hashSHA256, signatureRSA},
- {hashSHA256, signatureECDSA},
+ {signatureRSA, hashSHA256},
+ {signatureECDSA, hashSHA256},
}
// ConnectionState records basic TLS details about the connection.
@@ -163,9 +167,11 @@ type ConnectionState struct {
CipherSuite uint16 // cipher suite in use (TLS_RSA_WITH_RC4_128_SHA, ...)
NegotiatedProtocol string // negotiated next protocol (from Config.NextProtos)
NegotiatedProtocolIsMutual bool // negotiated protocol was advertised by server
+ NegotiatedProtocolFromALPN bool // protocol negotiated with ALPN
ServerName string // server name requested by client, if any (server side only)
PeerCertificates []*x509.Certificate // certificate chain presented by remote peer
VerifiedChains [][]*x509.Certificate // verified chains built from PeerCertificates
+ ChannelID *ecdsa.PublicKey // the channel ID for this connection
}
// ClientAuthType declares the policy the server will follow for
@@ -187,6 +193,7 @@ type ClientSessionState struct {
vers uint16 // SSL/TLS version negotiated for the session
cipherSuite uint16 // Ciphersuite negotiated for the session
masterSecret []byte // MasterSecret generated by client on a full handshake
+ handshakeHash []byte // Handshake hash for Channel ID purposes.
serverCertificates []*x509.Certificate // Certificate chain presented by the server
}
@@ -307,6 +314,15 @@ type Config struct {
// be used.
CurvePreferences []CurveID
+ // ChannelID contains the ECDSA key for the client to use as
+ // its TLS Channel ID.
+ ChannelID *ecdsa.PrivateKey
+
+ // RequestChannelID controls whether the server requests a TLS
+ // Channel ID. If negotiated, the client's public key is
+ // returned in the ConnectionState.
+ RequestChannelID bool
+
// Bugs specifies optional misbehaviour to be used for testing other
// implementations.
Bugs ProtocolBugs
@@ -420,6 +436,34 @@ type ProtocolBugs struct {
// SkipHelloVerifyRequest causes a DTLS server to skip the
// HelloVerifyRequest message.
SkipHelloVerifyRequest bool
+
+ // ExpectFalseStart causes the server to, on full handshakes,
+ // expect the peer to False Start; the server Finished message
+ // isn't sent until we receive an application data record
+ // from the peer.
+ ExpectFalseStart bool
+
+ // SSL3RSAKeyExchange causes the client to always send an RSA
+ // ClientKeyExchange message without the two-byte length
+ // prefix, as if it were SSL3.
+ SSL3RSAKeyExchange bool
+
+ // SkipCipherVersionCheck causes the server to negotiate
+ // TLS 1.2 ciphers in earlier versions of TLS.
+ SkipCipherVersionCheck bool
+
+ // ExpectServerName, if not empty, is the hostname the client
+ // must specify in the server_name extension.
+ ExpectServerName string
+
+ // SwapNPNAndALPN switches the relative order between NPN and
+ // ALPN on the server. This is to test that server preference
+ // of ALPN works regardless of their relative order.
+ SwapNPNAndALPN bool
+
+ // AllowSessionVersionMismatch causes the server to resume sessions
+ // regardless of the version associated with the session.
+ AllowSessionVersionMismatch bool
}
func (c *Config) serverInit() {
diff --git a/ssl/test/runner/conn.go b/ssl/test/runner/conn.go
index 5371a64..9f0c328 100644
--- a/ssl/test/runner/conn.go
+++ b/ssl/test/runner/conn.go
@@ -9,6 +9,7 @@ package main
import (
"bytes"
"crypto/cipher"
+ "crypto/ecdsa"
"crypto/subtle"
"crypto/x509"
"errors"
@@ -46,6 +47,9 @@ type Conn struct {
clientProtocol string
clientProtocolFallback bool
+ usedALPN bool
+
+ channelID *ecdsa.PublicKey
// input/output
in, out halfConn // in.Mutex < out.Mutex
@@ -657,7 +661,7 @@ func (c *Conn) readRecord(want recordType) error {
return c.in.setErrorLocked(errors.New("tls: handshake or ChangeCipherSpec requested after handshake complete"))
}
case recordTypeApplicationData:
- if !c.handshakeComplete {
+ if !c.handshakeComplete && !c.config.Bugs.ExpectFalseStart {
c.sendAlert(alertInternalError)
return c.in.setErrorLocked(errors.New("tls: application data record requested before handshake complete"))
}
@@ -937,6 +941,8 @@ func (c *Conn) readHandshake() (interface{}, error) {
m = new(finishedMsg)
case typeHelloVerifyRequest:
m = new(helloVerifyRequestMsg)
+ case typeEncryptedExtensions:
+ m = new(encryptedExtensionsMsg)
default:
return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
}
@@ -1100,10 +1106,12 @@ func (c *Conn) ConnectionState() ConnectionState {
state.NegotiatedProtocol = c.clientProtocol
state.DidResume = c.didResume
state.NegotiatedProtocolIsMutual = !c.clientProtocolFallback
+ state.NegotiatedProtocolFromALPN = c.usedALPN
state.CipherSuite = c.cipherSuite
state.PeerCertificates = c.peerCertificates
state.VerifiedChains = c.verifiedChains
state.ServerName = c.serverName
+ state.ChannelID = c.channelID
}
return state
diff --git a/ssl/test/runner/handshake_client.go b/ssl/test/runner/handshake_client.go
index ecc2bed..d78e767 100644
--- a/ssl/test/runner/handshake_client.go
+++ b/ssl/test/runner/handshake_client.go
@@ -8,6 +8,7 @@ import (
"bytes"
"crypto"
"crypto/ecdsa"
+ "crypto/elliptic"
"crypto/rsa"
"crypto/subtle"
"crypto/x509"
@@ -42,6 +43,18 @@ func (c *Conn) clientHandshake() error {
c.sendHandshakeSeq = 0
c.recvHandshakeSeq = 0
+ nextProtosLength := 0
+ for _, proto := range c.config.NextProtos {
+ if l := len(proto); l == 0 || l > 255 {
+ return errors.New("tls: invalid NextProtos value")
+ } else {
+ nextProtosLength += 1 + l
+ }
+ }
+ if nextProtosLength > 0xffff {
+ return errors.New("tls: NextProtos values too large")
+ }
+
hello := &clientHelloMsg{
isDTLS: c.isDTLS,
vers: c.config.maxVersion(),
@@ -53,7 +66,10 @@ func (c *Conn) clientHandshake() error {
supportedPoints: []uint8{pointFormatUncompressed},
nextProtoNeg: len(c.config.NextProtos) > 0,
secureRenegotiation: true,
+ alpnProtocols: c.config.NextProtos,
duplicateExtension: c.config.Bugs.DuplicateExtension,
+ channelIDSupported: c.config.ChannelID != nil,
+ npnLast: c.config.Bugs.SwapNPNAndALPN,
}
if c.config.Bugs.SendClientVersion != 0 {
@@ -238,7 +254,7 @@ NextCipherSuite:
if err := hs.readFinished(); err != nil {
return err
}
- if err := hs.sendFinished(); err != nil {
+ if err := hs.sendFinished(isResume); err != nil {
return err
}
} else {
@@ -248,7 +264,7 @@ NextCipherSuite:
if err := hs.establishKeys(); err != nil {
return err
}
- if err := hs.sendFinished(); err != nil {
+ if err := hs.sendFinished(isResume); err != nil {
return err
}
if err := hs.readSessionTicket(); err != nil {
@@ -472,6 +488,8 @@ func (hs *clientHandshakeState) doFullHandshake() error {
c.writeRecord(recordTypeHandshake, ckx.marshal())
}
+ hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random)
+
if chainToSend != nil {
var signed []byte
certVerify := &certificateVerifyMsg{
@@ -485,7 +503,7 @@ func (hs *clientHandshakeState) doFullHandshake() error {
break
}
var digest []byte
- digest, _, err = hs.finishedHash.hashForClientCertificate(certVerify.signatureAndHash)
+ digest, _, err = hs.finishedHash.hashForClientCertificate(certVerify.signatureAndHash, hs.masterSecret)
if err != nil {
break
}
@@ -501,7 +519,7 @@ func (hs *clientHandshakeState) doFullHandshake() error {
}
var digest []byte
var hashFunc crypto.Hash
- digest, hashFunc, err = hs.finishedHash.hashForClientCertificate(certVerify.signatureAndHash)
+ digest, hashFunc, err = hs.finishedHash.hashForClientCertificate(certVerify.signatureAndHash, hs.masterSecret)
if err != nil {
break
}
@@ -519,7 +537,8 @@ func (hs *clientHandshakeState) doFullHandshake() error {
c.writeRecord(recordTypeHandshake, certVerify.marshal())
}
- hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random)
+ hs.finishedHash.discardHandshakeBuffer()
+
return nil
}
@@ -560,15 +579,42 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) {
return false, errors.New("tls: server selected unsupported compression format")
}
- if !hs.hello.nextProtoNeg && hs.serverHello.nextProtoNeg {
+ clientDidNPN := hs.hello.nextProtoNeg
+ clientDidALPN := len(hs.hello.alpnProtocols) > 0
+ serverHasNPN := hs.serverHello.nextProtoNeg
+ serverHasALPN := len(hs.serverHello.alpnProtocol) > 0
+
+ if !clientDidNPN && serverHasNPN {
c.sendAlert(alertHandshakeFailure)
return false, errors.New("server advertised unrequested NPN extension")
}
+ if !clientDidALPN && serverHasALPN {
+ c.sendAlert(alertHandshakeFailure)
+ return false, errors.New("server advertised unrequested ALPN extension")
+ }
+
+ if serverHasNPN && serverHasALPN {
+ c.sendAlert(alertHandshakeFailure)
+ return false, errors.New("server advertised both NPN and ALPN extensions")
+ }
+
+ if serverHasALPN {
+ c.clientProtocol = hs.serverHello.alpnProtocol
+ c.clientProtocolFallback = false
+ c.usedALPN = true
+ }
+
+ if !hs.hello.channelIDSupported && hs.serverHello.channelIDRequested {
+ c.sendAlert(alertHandshakeFailure)
+ return false, errors.New("server advertised unrequested Channel ID extension")
+ }
+
if hs.serverResumedSession() {
// Restore masterSecret and peerCerts from previous state
hs.masterSecret = hs.session.masterSecret
c.peerCertificates = hs.session.serverCertificates
+ hs.finishedHash.discardHandshakeBuffer()
return true, nil
}
return false, nil
@@ -619,20 +665,22 @@ func (hs *clientHandshakeState) readSessionTicket() error {
c.sendAlert(alertUnexpectedMessage)
return unexpectedMessageError(sessionTicketMsg, msg)
}
- hs.writeServerHash(sessionTicketMsg.marshal())
hs.session = &ClientSessionState{
sessionTicket: sessionTicketMsg.ticket,
vers: c.vers,
cipherSuite: hs.suite.id,
masterSecret: hs.masterSecret,
+ handshakeHash: hs.finishedHash.server.Sum(nil),
serverCertificates: c.peerCertificates,
}
+ hs.writeServerHash(sessionTicketMsg.marshal())
+
return nil
}
-func (hs *clientHandshakeState) sendFinished() error {
+func (hs *clientHandshakeState) sendFinished(isResume bool) error {
c := hs.c
var postCCSBytes []byte
@@ -650,6 +698,34 @@ func (hs *clientHandshakeState) sendFinished() error {
postCCSBytes = append(postCCSBytes, nextProtoBytes...)
}
+ if hs.serverHello.channelIDRequested {
+ encryptedExtensions := new(encryptedExtensionsMsg)
+ if c.config.ChannelID.Curve != elliptic.P256() {
+ return fmt.Errorf("tls: Channel ID is not on P-256.")
+ }
+ var resumeHash []byte
+ if isResume {
+ resumeHash = hs.session.handshakeHash
+ }
+ r, s, err := ecdsa.Sign(c.config.rand(), c.config.ChannelID, hs.finishedHash.hashForChannelID(resumeHash))
+ if err != nil {
+ return err
+ }
+ channelID := make([]byte, 128)
+ writeIntPadded(channelID[0:32], c.config.ChannelID.X)
+ writeIntPadded(channelID[32:64], c.config.ChannelID.Y)
+ writeIntPadded(channelID[64:96], r)
+ writeIntPadded(channelID[96:128], s)
+ encryptedExtensions.channelID = channelID
+
+ c.channelID = &c.config.ChannelID.PublicKey
+
+ encryptedExtensionsBytes := encryptedExtensions.marshal()
+ hs.writeHash(encryptedExtensionsBytes, seqno)
+ seqno++
+ postCCSBytes = append(postCCSBytes, encryptedExtensionsBytes...)
+ }
+
finished := new(finishedMsg)
if c.config.Bugs.EarlyChangeCipherSpec == 2 {
finished.verifyData = hs.finishedHash.clientSum(nil)
@@ -709,18 +785,28 @@ func clientSessionCacheKey(serverAddr net.Addr, config *Config) string {
return serverAddr.String()
}
-// mutualProtocol finds the mutual Next Protocol Negotiation protocol given the
-// set of client and server supported protocols. The set of client supported
-// protocols must not be empty. It returns the resulting protocol and flag
+// mutualProtocol finds the mutual Next Protocol Negotiation or ALPN protocol
+// given list of possible protocols and a list of the preference order. The
+// first list must not be empty. It returns the resulting protocol and flag
// indicating if the fallback case was reached.
-func mutualProtocol(clientProtos, serverProtos []string) (string, bool) {
- for _, s := range serverProtos {
- for _, c := range clientProtos {
+func mutualProtocol(protos, preferenceProtos []string) (string, bool) {
+ for _, s := range preferenceProtos {
+ for _, c := range protos {
if s == c {
return s, false
}
}
}
- return clientProtos[0], true
+ return protos[0], true
+}
+
+// writeIntPadded writes x into b, padded up with leading zeros as
+// needed.
+func writeIntPadded(b []byte, x *big.Int) {
+ for i := range b {
+ b[i] = 0
+ }
+ xb := x.Bytes()
+ copy(b[len(b)-len(xb):], xb)
}
diff --git a/ssl/test/runner/handshake_messages.go b/ssl/test/runner/handshake_messages.go
index 7fe8bf5..136360d 100644
--- a/ssl/test/runner/handshake_messages.go
+++ b/ssl/test/runner/handshake_messages.go
@@ -24,7 +24,10 @@ type clientHelloMsg struct {
sessionTicket []uint8
signatureAndHashes []signatureAndHash
secureRenegotiation bool
+ alpnProtocols []string
duplicateExtension bool
+ channelIDSupported bool
+ npnLast bool
}
func (m *clientHelloMsg) equal(i interface{}) bool {
@@ -49,7 +52,11 @@ func (m *clientHelloMsg) equal(i interface{}) bool {
m.ticketSupported == m1.ticketSupported &&
bytes.Equal(m.sessionTicket, m1.sessionTicket) &&
eqSignatureAndHashes(m.signatureAndHashes, m1.signatureAndHashes) &&
- m.secureRenegotiation == m1.secureRenegotiation
+ m.secureRenegotiation == m1.secureRenegotiation &&
+ eqStrings(m.alpnProtocols, m1.alpnProtocols) &&
+ m.duplicateExtension == m1.duplicateExtension &&
+ m.channelIDSupported == m1.channelIDSupported &&
+ m.npnLast == m1.npnLast
}
func (m *clientHelloMsg) marshal() []byte {
@@ -97,6 +104,20 @@ func (m *clientHelloMsg) marshal() []byte {
if m.duplicateExtension {
numExtensions += 2
}
+ if m.channelIDSupported {
+ numExtensions++
+ }
+ if len(m.alpnProtocols) > 0 {
+ extensionsLength += 2
+ for _, s := range m.alpnProtocols {
+ if l := len(s); l == 0 || l > 255 {
+ panic("invalid ALPN protocol")
+ }
+ extensionsLength++
+ extensionsLength += len(s)
+ }
+ numExtensions++
+ }
if numExtensions > 0 {
extensionsLength += 4 * numExtensions
length += 2 + extensionsLength
@@ -141,7 +162,7 @@ func (m *clientHelloMsg) marshal() []byte {
z[1] = 0xff
z = z[4:]
}
- if m.nextProtoNeg {
+ if m.nextProtoNeg && !m.npnLast {
z[0] = byte(extensionNextProtoNeg >> 8)
z[1] = byte(extensionNextProtoNeg & 0xff)
// The length is always 0
@@ -260,6 +281,38 @@ func (m *clientHelloMsg) marshal() []byte {
z[3] = 1
z = z[5:]
}
+ if len(m.alpnProtocols) > 0 {
+ z[0] = byte(extensionALPN >> 8)
+ z[1] = byte(extensionALPN & 0xff)
+ lengths := z[2:]
+ z = z[6:]
+
+ stringsLength := 0
+ for _, s := range m.alpnProtocols {
+ l := len(s)
+ z[0] = byte(l)
+ copy(z[1:], s)
+ z = z[1+l:]
+ stringsLength += 1 + l
+ }
+
+ lengths[2] = byte(stringsLength >> 8)
+ lengths[3] = byte(stringsLength)
+ stringsLength += 2
+ lengths[0] = byte(stringsLength >> 8)
+ lengths[1] = byte(stringsLength)
+ }
+ if m.channelIDSupported {
+ z[0] = byte(extensionChannelID >> 8)
+ z[1] = byte(extensionChannelID & 0xff)
+ z = z[4:]
+ }
+ if m.nextProtoNeg && m.npnLast {
+ z[0] = byte(extensionNextProtoNeg >> 8)
+ z[1] = byte(extensionNextProtoNeg & 0xff)
+ // The length is always 0
+ z = z[4:]
+ }
if m.duplicateExtension {
// Add a duplicate bogus extension at the beginning and end.
z[0] = 0xff
@@ -331,6 +384,7 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
m.ticketSupported = false
m.sessionTicket = nil
m.signatureAndHashes = nil
+ m.alpnProtocols = nil
if len(data) == 0 {
// ClientHello is optionally followed by extension data
@@ -440,6 +494,29 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
return false
}
m.secureRenegotiation = true
+ case extensionALPN:
+ if length < 2 {
+ return false
+ }
+ l := int(data[0])<<8 | int(data[1])
+ if l != length-2 {
+ return false
+ }
+ d := data[2:length]
+ for len(d) != 0 {
+ stringLen := int(d[0])
+ d = d[1:]
+ if stringLen == 0 || stringLen > len(d) {
+ return false
+ }
+ m.alpnProtocols = append(m.alpnProtocols, string(d[:stringLen]))
+ d = d[stringLen:]
+ }
+ case extensionChannelID:
+ if length > 0 {
+ return false
+ }
+ m.channelIDSupported = true
}
data = data[length:]
}
@@ -460,7 +537,9 @@ type serverHelloMsg struct {
ocspStapling bool
ticketSupported bool
secureRenegotiation bool
+ alpnProtocol string
duplicateExtension bool
+ channelIDRequested bool
}
func (m *serverHelloMsg) equal(i interface{}) bool {
@@ -480,7 +559,10 @@ func (m *serverHelloMsg) equal(i interface{}) bool {
eqStrings(m.nextProtos, m1.nextProtos) &&
m.ocspStapling == m1.ocspStapling &&
m.ticketSupported == m1.ticketSupported &&
- m.secureRenegotiation == m1.secureRenegotiation
+ m.secureRenegotiation == m1.secureRenegotiation &&
+ m.alpnProtocol == m1.alpnProtocol &&
+ m.duplicateExtension == m1.duplicateExtension &&
+ m.channelIDRequested == m1.channelIDRequested
}
func (m *serverHelloMsg) marshal() []byte {
@@ -514,6 +596,17 @@ func (m *serverHelloMsg) marshal() []byte {
if m.duplicateExtension {
numExtensions += 2
}
+ if m.channelIDRequested {
+ numExtensions++
+ }
+ if alpnLen := len(m.alpnProtocol); alpnLen > 0 {
+ if alpnLen >= 256 {
+ panic("invalid ALPN protocol")
+ }
+ extensionsLength += 2 + 1 + alpnLen
+ numExtensions++
+ }
+
if numExtensions > 0 {
extensionsLength += 4 * numExtensions
length += 2 + extensionsLength
@@ -581,6 +674,25 @@ func (m *serverHelloMsg) marshal() []byte {
z[3] = 1
z = z[5:]
}
+ if alpnLen := len(m.alpnProtocol); alpnLen > 0 {
+ z[0] = byte(extensionALPN >> 8)
+ z[1] = byte(extensionALPN & 0xff)
+ l := 2 + 1 + alpnLen
+ z[2] = byte(l >> 8)
+ z[3] = byte(l)
+ l -= 2
+ z[4] = byte(l >> 8)
+ z[5] = byte(l)
+ l -= 1
+ z[6] = byte(l)
+ copy(z[7:], []byte(m.alpnProtocol))
+ z = z[7+alpnLen:]
+ }
+ if m.channelIDRequested {
+ z[0] = byte(extensionChannelID >> 8)
+ z[1] = byte(extensionChannelID & 0xff)
+ z = z[4:]
+ }
if m.duplicateExtension {
// Add a duplicate bogus extension at the beginning and end.
z[0] = 0xff
@@ -617,6 +729,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
m.nextProtos = nil
m.ocspStapling = false
m.ticketSupported = false
+ m.alpnProtocol = ""
if len(data) == 0 {
// ServerHello is optionally followed by extension data
@@ -671,6 +784,27 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
return false
}
m.secureRenegotiation = true
+ case extensionALPN:
+ d := data[:length]
+ if len(d) < 3 {
+ return false
+ }
+ l := int(d[0])<<8 | int(d[1])
+ if l != len(d)-2 {
+ return false
+ }
+ d = d[2:]
+ l = int(d[0])
+ if l != len(d)-1 {
+ return false
+ }
+ d = d[1:]
+ m.alpnProtocol = string(d)
+ case extensionChannelID:
+ if length > 0 {
+ return false
+ }
+ m.channelIDRequested = true
}
data = data[length:]
}
@@ -1407,7 +1541,8 @@ func (m *helloVerifyRequestMsg) equal(i interface{}) bool {
return false
}
- return m.vers == m1.vers &&
+ return bytes.Equal(m.raw, m1.raw) &&
+ m.vers == m1.vers &&
bytes.Equal(m.cookie, m1.cookie)
}
@@ -1447,6 +1582,58 @@ func (m *helloVerifyRequestMsg) unmarshal(data []byte) bool {
return true
}
+type encryptedExtensionsMsg struct {
+ raw []byte
+ channelID []byte
+}
+
+func (m *encryptedExtensionsMsg) equal(i interface{}) bool {
+ m1, ok := i.(*encryptedExtensionsMsg)
+ if !ok {
+ return false
+ }
+
+ return bytes.Equal(m.raw, m1.raw) &&
+ bytes.Equal(m.channelID, m1.channelID)
+}
+
+func (m *encryptedExtensionsMsg) marshal() []byte {
+ if m.raw != nil {
+ return m.raw
+ }
+
+ length := 2 + 2 + len(m.channelID)
+
+ x := make([]byte, 4+length)
+ x[0] = typeEncryptedExtensions
+ x[1] = uint8(length >> 16)
+ x[2] = uint8(length >> 8)
+ x[3] = uint8(length)
+ x[4] = uint8(extensionChannelID >> 8)
+ x[5] = uint8(extensionChannelID & 0xff)
+ x[6] = uint8(len(m.channelID) >> 8)
+ x[7] = uint8(len(m.channelID) & 0xff)
+ copy(x[8:], m.channelID)
+
+ return x
+}
+
+func (m *encryptedExtensionsMsg) unmarshal(data []byte) bool {
+ if len(data) != 4+2+2+128 {
+ return false
+ }
+ m.raw = data
+ if (uint16(data[4])<<8)|uint16(data[5]) != extensionChannelID {
+ return false
+ }
+ if int(data[6])<<8|int(data[7]) != 128 {
+ return false
+ }
+ m.channelID = data[4+2+2:]
+
+ return true
+}
+
func eqUint16s(x, y []uint16) bool {
if len(x) != len(y) {
return false
diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go
index d5a660a..1eb3f11 100644
--- a/ssl/test/runner/handshake_server.go
+++ b/ssl/test/runner/handshake_server.go
@@ -8,6 +8,7 @@ import (
"bytes"
"crypto"
"crypto/ecdsa"
+ "crypto/elliptic"
"crypto/rsa"
"crypto/subtle"
"crypto/x509"
@@ -15,6 +16,7 @@ import (
"errors"
"fmt"
"io"
+ "math/big"
)
// serverHandshakeState contains details of a server handshake in progress.
@@ -69,7 +71,7 @@ func (c *Conn) serverHandshake() error {
if err := hs.sendFinished(); err != nil {
return err
}
- if err := hs.readFinished(); err != nil {
+ if err := hs.readFinished(isResume); err != nil {
return err
}
c.didResume = true
@@ -82,9 +84,14 @@ func (c *Conn) serverHandshake() error {
if err := hs.establishKeys(); err != nil {
return err
}
- if err := hs.readFinished(); err != nil {
+ if err := hs.readFinished(isResume); err != nil {
return err
}
+ if c.config.Bugs.ExpectFalseStart {
+ if err := c.readRecord(recordTypeApplicationData); err != nil {
+ return err
+ }
+ }
if err := hs.sendSessionTicket(); err != nil {
return err
}
@@ -213,13 +220,22 @@ Curves:
if len(hs.clientHello.serverName) > 0 {
c.serverName = hs.clientHello.serverName
}
- // Although sending an empty NPN extension is reasonable, Firefox has
- // had a bug around this. Best to send nothing at all if
- // config.NextProtos is empty. See
- // https://code.google.com/p/go/issues/detail?id=5445.
- if hs.clientHello.nextProtoNeg && len(config.NextProtos) > 0 {
- hs.hello.nextProtoNeg = true
- hs.hello.nextProtos = config.NextProtos
+
+ if len(hs.clientHello.alpnProtocols) > 0 {
+ if selectedProto, fallback := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); !fallback {
+ hs.hello.alpnProtocol = selectedProto
+ c.clientProtocol = selectedProto
+ c.usedALPN = true
+ }
+ } else {
+ // Although sending an empty NPN extension is reasonable, Firefox has
+ // had a bug around this. Best to send nothing at all if
+ // config.NextProtos is empty. See
+ // https://code.google.com/p/go/issues/detail?id=5445.
+ if hs.clientHello.nextProtoNeg && len(config.NextProtos) > 0 {
+ hs.hello.nextProtoNeg = true
+ hs.hello.nextProtos = config.NextProtos
+ }
}
if len(config.Certificates) == 0 {
@@ -230,6 +246,13 @@ Curves:
if len(hs.clientHello.serverName) > 0 {
hs.cert = config.getCertificateForName(hs.clientHello.serverName)
}
+ if expected := c.config.Bugs.ExpectServerName; expected != "" && expected != hs.clientHello.serverName {
+ return false, errors.New("tls: unexpected server name")
+ }
+
+ if hs.clientHello.channelIDSupported && config.RequestChannelID {
+ hs.hello.channelIDRequested = true
+ }
_, hs.ecdsaOk = hs.cert.PrivateKey.(*ecdsa.PrivateKey)
@@ -279,16 +302,22 @@ Curves:
func (hs *serverHandshakeState) checkForResumption() bool {
c := hs.c
- var ok bool
- if hs.sessionState, ok = c.decryptTicket(hs.clientHello.sessionTicket); !ok {
+ if c.config.SessionTicketsDisabled {
return false
}
- if hs.sessionState.vers > hs.clientHello.vers {
+ var ok bool
+ if hs.sessionState, ok = c.decryptTicket(hs.clientHello.sessionTicket); !ok {
return false
}
- if vers, ok := c.config.mutualVersion(hs.sessionState.vers); !ok || vers != hs.sessionState.vers {
- return false
+
+ if !c.config.Bugs.AllowSessionVersionMismatch {
+ if hs.sessionState.vers > hs.clientHello.vers {
+ return false
+ }
+ if vers, ok := c.config.mutualVersion(hs.sessionState.vers); !ok || vers != hs.sessionState.vers {
+ return false
+ }
}
cipherSuiteOk := false
@@ -331,6 +360,7 @@ func (hs *serverHandshakeState) doResumeHandshake() error {
hs.hello.ticketSupported = c.config.Bugs.RenewTicketOnResume
hs.finishedHash = newFinishedHash(c.vers, hs.suite)
+ hs.finishedHash.discardHandshakeBuffer()
hs.writeClientHash(hs.clientHello.marshal())
hs.writeServerHash(hs.hello.marshal())
@@ -467,6 +497,13 @@ func (hs *serverHandshakeState) doFullHandshake() error {
}
hs.writeClientHash(ckx.marshal())
+ preMasterSecret, err := keyAgreement.processClientKeyExchange(config, hs.cert, ckx, c.vers)
+ if err != nil {
+ c.sendAlert(alertHandshakeFailure)
+ return err
+ }
+ hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.clientHello.random, hs.hello.random)
+
// If we received a client cert in response to our certificate request message,
// the client will send us a certificateVerifyMsg immediately after the
// clientKeyExchangeMsg. This message is a digest of all preceding
@@ -515,7 +552,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
break
}
var digest []byte
- digest, _, err = hs.finishedHash.hashForClientCertificate(signatureAndHash)
+ digest, _, err = hs.finishedHash.hashForClientCertificate(signatureAndHash, hs.masterSecret)
if err != nil {
break
}
@@ -530,7 +567,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
}
var digest []byte
var hashFunc crypto.Hash
- digest, hashFunc, err = hs.finishedHash.hashForClientCertificate(signatureAndHash)
+ digest, hashFunc, err = hs.finishedHash.hashForClientCertificate(signatureAndHash, hs.masterSecret)
if err != nil {
break
}
@@ -544,12 +581,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
hs.writeClientHash(certVerify.marshal())
}
- preMasterSecret, err := keyAgreement.processClientKeyExchange(config, hs.cert, ckx, c.vers)
- if err != nil {
- c.sendAlert(alertHandshakeFailure)
- return err
- }
- hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.clientHello.random, hs.hello.random)
+ hs.finishedHash.discardHandshakeBuffer()
return nil
}
@@ -579,7 +611,7 @@ func (hs *serverHandshakeState) establishKeys() error {
return nil
}
-func (hs *serverHandshakeState) readFinished() error {
+func (hs *serverHandshakeState) readFinished(isResume bool) error {
c := hs.c
c.readRecord(recordTypeChangeCipherSpec)
@@ -601,6 +633,36 @@ func (hs *serverHandshakeState) readFinished() error {
c.clientProtocol = nextProto.proto
}
+ if hs.hello.channelIDRequested {
+ msg, err := c.readHandshake()
+ if err != nil {
+ return err
+ }
+ encryptedExtensions, ok := msg.(*encryptedExtensionsMsg)
+ if !ok {
+ c.sendAlert(alertUnexpectedMessage)
+ return unexpectedMessageError(encryptedExtensions, msg)
+ }
+ x := new(big.Int).SetBytes(encryptedExtensions.channelID[0:32])
+ y := new(big.Int).SetBytes(encryptedExtensions.channelID[32:64])
+ r := new(big.Int).SetBytes(encryptedExtensions.channelID[64:96])
+ s := new(big.Int).SetBytes(encryptedExtensions.channelID[96:128])
+ if !elliptic.P256().IsOnCurve(x, y) {
+ return errors.New("tls: invalid channel ID public key")
+ }
+ channelID := &ecdsa.PublicKey{elliptic.P256(), x, y}
+ var resumeHash []byte
+ if isResume {
+ resumeHash = hs.sessionState.handshakeHash
+ }
+ if !ecdsa.Verify(channelID, hs.finishedHash.hashForChannelID(resumeHash), r, s) {
+ return errors.New("tls: invalid channel ID signature")
+ }
+ c.channelID = channelID
+
+ hs.writeClientHash(encryptedExtensions.marshal())
+ }
+
msg, err := c.readHandshake()
if err != nil {
return err
@@ -632,10 +694,11 @@ func (hs *serverHandshakeState) sendSessionTicket() error {
var err error
state := sessionState{
- vers: c.vers,
- cipherSuite: hs.suite.id,
- masterSecret: hs.masterSecret,
- certificates: hs.certsFromClient,
+ vers: c.vers,
+ cipherSuite: hs.suite.id,
+ masterSecret: hs.masterSecret,
+ certificates: hs.certsFromClient,
+ handshakeHash: hs.finishedHash.server.Sum(nil),
}
m.ticket, err = c.encryptTicket(&state)
if err != nil {
@@ -787,7 +850,7 @@ func (c *Conn) tryCipherSuite(id uint16, supportedCipherSuites []uint16, version
if (candidate.flags&suiteECDSA != 0) != ecdsaOk {
continue
}
- if version < VersionTLS12 && candidate.flags&suiteTLS12 != 0 {
+ if !c.config.Bugs.SkipCipherVersionCheck && version < VersionTLS12 && candidate.flags&suiteTLS12 != 0 {
continue
}
if c.isDTLS && candidate.flags&suiteNoDTLS != 0 {
diff --git a/ssl/test/runner/key_agreement.go b/ssl/test/runner/key_agreement.go
index 2e2eff4..f8ba1f8 100644
--- a/ssl/test/runner/key_agreement.go
+++ b/ssl/test/runner/key_agreement.go
@@ -87,7 +87,7 @@ func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello
return nil, nil, err
}
ckx := new(clientKeyExchangeMsg)
- if clientHello.vers != VersionSSL30 {
+ if clientHello.vers != VersionSSL30 && !config.Bugs.SSL3RSAKeyExchange {
ckx.ciphertext = make([]byte, len(encrypted)+2)
ckx.ciphertext[0] = byte(len(encrypted) >> 8)
ckx.ciphertext[1] = byte(len(encrypted))
diff --git a/ssl/test/runner/prf.go b/ssl/test/runner/prf.go
index 991196f..6d0db97 100644
--- a/ssl/test/runner/prf.go
+++ b/ssl/test/runner/prf.go
@@ -120,6 +120,8 @@ var masterSecretLabel = []byte("master secret")
var keyExpansionLabel = []byte("key expansion")
var clientFinishedLabel = []byte("client finished")
var serverFinishedLabel = []byte("server finished")
+var channelIDLabel = []byte("TLS Channel ID signature\x00")
+var channelIDResumeLabel = []byte("Resumption\x00")
func prfForVersion(version uint16, suite *cipherSuite) func(result, secret, label, seed []byte) {
switch version {
@@ -180,9 +182,9 @@ func newFinishedHash(version uint16, cipherSuite *cipherSuite) finishedHash {
newHash = sha512.New384
}
- return finishedHash{newHash(), newHash(), nil, nil, version, prf12(newHash)}
+ return finishedHash{newHash(), newHash(), nil, nil, []byte{}, version, prf12(newHash)}
}
- return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), version, prf10}
+ return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), []byte{}, version, prf10}
}
// A finishedHash calculates the hash of a set of handshake messages suitable
@@ -195,11 +197,15 @@ type finishedHash struct {
clientMD5 hash.Hash
serverMD5 hash.Hash
+ // In TLS 1.2 (and SSL 3 for implementation convenience), a
+ // full buffer is required.
+ buffer []byte
+
version uint16
prf func(result, secret, label, seed []byte)
}
-func (h finishedHash) Write(msg []byte) (n int, err error) {
+func (h *finishedHash) Write(msg []byte) (n int, err error) {
h.client.Write(msg)
h.server.Write(msg)
@@ -207,14 +213,19 @@ func (h finishedHash) Write(msg []byte) (n int, err error) {
h.clientMD5.Write(msg)
h.serverMD5.Write(msg)
}
+
+ if h.buffer != nil {
+ h.buffer = append(h.buffer, msg...)
+ }
+
return len(msg), nil
}
// finishedSum30 calculates the contents of the verify_data member of a SSLv3
// Finished message given the MD5 and SHA1 hashes of a set of handshake
// messages.
-func finishedSum30(md5, sha1 hash.Hash, masterSecret []byte, magic [4]byte) []byte {
- md5.Write(magic[:])
+func finishedSum30(md5, sha1 hash.Hash, masterSecret []byte, magic []byte) []byte {
+ md5.Write(magic)
md5.Write(masterSecret)
md5.Write(ssl30Pad1[:])
md5Digest := md5.Sum(nil)
@@ -225,7 +236,7 @@ func finishedSum30(md5, sha1 hash.Hash, masterSecret []byte, magic [4]byte) []by
md5.Write(md5Digest)
md5Digest = md5.Sum(nil)
- sha1.Write(magic[:])
+ sha1.Write(magic)
sha1.Write(masterSecret)
sha1.Write(ssl30Pad1[:40])
sha1Digest := sha1.Sum(nil)
@@ -249,7 +260,7 @@ var ssl3ServerFinishedMagic = [4]byte{0x53, 0x52, 0x56, 0x52}
// Finished message.
func (h finishedHash) clientSum(masterSecret []byte) []byte {
if h.version == VersionSSL30 {
- return finishedSum30(h.clientMD5, h.client, masterSecret, ssl3ClientFinishedMagic)
+ return finishedSum30(h.clientMD5, h.client, masterSecret, ssl3ClientFinishedMagic[:])
}
out := make([]byte, finishedVerifyLength)
@@ -269,7 +280,7 @@ func (h finishedHash) clientSum(masterSecret []byte) []byte {
// Finished message.
func (h finishedHash) serverSum(masterSecret []byte) []byte {
if h.version == VersionSSL30 {
- return finishedSum30(h.serverMD5, h.server, masterSecret, ssl3ServerFinishedMagic)
+ return finishedSum30(h.serverMD5, h.server, masterSecret, ssl3ServerFinishedMagic[:])
}
out := make([]byte, finishedVerifyLength)
@@ -290,7 +301,7 @@ func (h finishedHash) serverSum(masterSecret []byte) []byte {
func (h finishedHash) selectClientCertSignatureAlgorithm(serverList []signatureAndHash, sigType uint8) (signatureAndHash, error) {
if h.version < VersionTLS12 {
// Nothing to negotiate before TLS 1.2.
- return signatureAndHash{sigType, 0}, nil
+ return signatureAndHash{signature: sigType}, nil
}
for _, v := range serverList {
@@ -303,13 +314,24 @@ func (h finishedHash) selectClientCertSignatureAlgorithm(serverList []signatureA
// hashForClientCertificate returns a digest, hash function, and TLS 1.2 hash
// id suitable for signing by a TLS client certificate.
-func (h finishedHash) hashForClientCertificate(signatureAndHash signatureAndHash) ([]byte, crypto.Hash, error) {
+func (h finishedHash) hashForClientCertificate(signatureAndHash signatureAndHash, masterSecret []byte) ([]byte, crypto.Hash, error) {
+ if h.version == VersionSSL30 {
+ if signatureAndHash.signature != signatureRSA {
+ return nil, 0, errors.New("tls: unsupported signature type for client certificate")
+ }
+
+ md5Hash := md5.New()
+ md5Hash.Write(h.buffer)
+ sha1Hash := sha1.New()
+ sha1Hash.Write(h.buffer)
+ return finishedSum30(md5Hash, sha1Hash, masterSecret, nil), crypto.MD5SHA1, nil
+ }
if h.version >= VersionTLS12 {
if signatureAndHash.hash != hashSHA256 {
return nil, 0, errors.New("tls: unsupported hash function for client certificate")
}
- digest := h.server.Sum(nil)
- return digest, crypto.SHA256, nil
+ digest := sha256.Sum256(h.buffer)
+ return digest[:], crypto.SHA256, nil
}
if signatureAndHash.signature == signatureECDSA {
digest := h.server.Sum(nil)
@@ -321,3 +343,23 @@ func (h finishedHash) hashForClientCertificate(signatureAndHash signatureAndHash
digest = h.server.Sum(digest)
return digest, crypto.MD5SHA1, nil
}
+
+// hashForChannelID returns the hash to be signed for TLS Channel
+// ID. If a resumption, resumeHash has the previous handshake
+// hash. Otherwise, it is nil.
+func (h finishedHash) hashForChannelID(resumeHash []byte) []byte {
+ hash := sha256.New()
+ hash.Write(channelIDLabel)
+ if resumeHash != nil {
+ hash.Write(channelIDResumeLabel)
+ hash.Write(resumeHash)
+ }
+ hash.Write(h.server.Sum(nil))
+ return hash.Sum(nil)
+}
+
+// discardHandshakeBuffer is called when there is no more need to
+// buffer the entirety of the handshake messages.
+func (h *finishedHash) discardHandshakeBuffer() {
+ h.buffer = nil
+}
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 4a5b762..323f43f 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -2,7 +2,11 @@ package main
import (
"bytes"
+ "crypto/ecdsa"
+ "crypto/elliptic"
"crypto/x509"
+ "encoding/base64"
+ "encoding/pem"
"flag"
"fmt"
"io"
@@ -25,11 +29,14 @@ const (
)
const (
- rsaKeyFile = "key.pem"
- ecdsaKeyFile = "ecdsa_key.pem"
+ rsaKeyFile = "key.pem"
+ ecdsaKeyFile = "ecdsa_key.pem"
+ channelIDKeyFile = "channel_id_key.pem"
)
var rsaCertificate, ecdsaCertificate Certificate
+var channelIDKey *ecdsa.PrivateKey
+var channelIDBytes []byte
func initCertificates() {
var err error
@@ -42,6 +49,26 @@ func initCertificates() {
if err != nil {
panic(err)
}
+
+ channelIDPEMBlock, err := ioutil.ReadFile(channelIDKeyFile)
+ if err != nil {
+ panic(err)
+ }
+ channelIDDERBlock, _ := pem.Decode(channelIDPEMBlock)
+ if channelIDDERBlock.Type != "EC PRIVATE KEY" {
+ panic("bad key type")
+ }
+ channelIDKey, err = x509.ParseECPrivateKey(channelIDDERBlock.Bytes)
+ if err != nil {
+ panic(err)
+ }
+ if channelIDKey.Curve != elliptic.P256() {
+ panic("bad curve")
+ }
+
+ channelIDBytes = make([]byte, 64)
+ writeIntPadded(channelIDBytes[:32], channelIDKey.X)
+ writeIntPadded(channelIDBytes[32:], channelIDKey.Y)
}
var certificateOnce sync.Once
@@ -70,6 +97,11 @@ const (
dtls
)
+const (
+ alpn = 1
+ npn = 2
+)
+
type testCase struct {
testType testType
protocol protocol
@@ -83,6 +115,18 @@ type testCase struct {
// expectedVersion, if non-zero, specifies the TLS version that must be
// negotiated.
expectedVersion uint16
+ // expectedResumeVersion, if non-zero, specifies the TLS version that
+ // must be negotiated on resumption. If zero, expectedVersion is used.
+ expectedResumeVersion uint16
+ // expectChannelID controls whether the connection should have
+ // negotiated a Channel ID with channelIDKey.
+ expectChannelID bool
+ // expectedNextProto controls whether the connection should
+ // negotiate a next protocol via NPN or ALPN.
+ expectedNextProto string
+ // expectedNextProtoType, if non-zero, is the expected next
+ // protocol negotiation mechanism.
+ expectedNextProtoType int
// messageLen is the length, in bytes, of the test message that will be
// sent.
messageLen int
@@ -91,11 +135,19 @@ type testCase struct {
// keyFile is the path to the private key to use for the server.
keyFile string
// resumeSession controls whether a second connection should be tested
- // which resumes the first session.
+ // which attempts to resume the first session.
resumeSession bool
+ // resumeConfig, if not nil, points to a Config to be used on
+ // resumption. SessionTicketKey and ClientSessionCache are copied from
+ // the initial connection's config. If nil, the initial connection's
+ // config is used.
+ resumeConfig *Config
// sendPrefix sends a prefix on the socket before actually performing a
// handshake.
sendPrefix string
+ // shimWritesFirst controls whether the shim sends an initial "hello"
+ // message before doing a roundtrip with the runner.
+ shimWritesFirst bool
// flags, if not empty, contains a list of command-line flags that will
// be passed to the shim program.
flags []string
@@ -160,7 +212,7 @@ var testCases = []testCase{
expectedLocalError: "no fallback SCSV found",
},
{
- name: "FallbackSCSV",
+ name: "SendFallbackSCSV",
config: Config{
Bugs: ProtocolBugs{
FailIfNotFallbackSCSV: true,
@@ -169,36 +221,6 @@ var testCases = []testCase{
flags: []string{"-fallback-scsv"},
},
{
- testType: serverTest,
- name: "ServerNameExtension",
- config: Config{
- ServerName: "example.com",
- },
- flags: []string{"-expect-server-name", "example.com"},
- },
- {
- testType: clientTest,
- name: "DuplicateExtensionClient",
- config: Config{
- Bugs: ProtocolBugs{
- DuplicateExtension: true,
- },
- },
- shouldFail: true,
- expectedLocalError: "remote error: error decoding message",
- },
- {
- testType: serverTest,
- name: "DuplicateExtensionServer",
- config: Config{
- Bugs: ProtocolBugs{
- DuplicateExtension: true,
- },
- },
- shouldFail: true,
- expectedLocalError: "remote error: error decoding message",
- },
- {
name: "ClientCertificateTypes",
config: Config{
ClientAuth: RequestClientCert,
@@ -208,11 +230,14 @@ var testCases = []testCase{
CertTypeECDSASign,
},
},
- flags: []string{"-expect-certificate-types", string([]byte{
- CertTypeDSSSign,
- CertTypeRSASign,
- CertTypeECDSASign,
- })},
+ flags: []string{
+ "-expect-certificate-types",
+ base64.StdEncoding.EncodeToString([]byte{
+ CertTypeDSSSign,
+ CertTypeRSASign,
+ CertTypeECDSASign,
+ }),
+ },
},
{
name: "NoClientCertificate",
@@ -447,9 +472,21 @@ var testCases = []testCase{
shouldFail: true,
expectedError: ":HTTPS_PROXY_REQUEST:",
},
+ {
+ name: "SkipCipherVersionCheck",
+ config: Config{
+ CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
+ MaxVersion: VersionTLS11,
+ Bugs: ProtocolBugs{
+ SkipCipherVersionCheck: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":WRONG_CIPHER_RETURNED:",
+ },
}
-func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int) error {
+func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, isResume bool) error {
if test.protocol == dtls {
conn = newPacketAdaptor(conn)
}
@@ -480,8 +517,50 @@ func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int) e
return err
}
- if vers := tlsConn.ConnectionState().Version; test.expectedVersion != 0 && vers != test.expectedVersion {
- return fmt.Errorf("got version %x, expected %x", vers, test.expectedVersion)
+ // TODO(davidben): move all per-connection expectations into a dedicated
+ // expectations struct that can be specified separately for the two
+ // legs.
+ expectedVersion := test.expectedVersion
+ if isResume && test.expectedResumeVersion != 0 {
+ expectedVersion = test.expectedResumeVersion
+ }
+ if vers := tlsConn.ConnectionState().Version; expectedVersion != 0 && vers != expectedVersion {
+ return fmt.Errorf("got version %x, expected %x", vers, expectedVersion)
+ }
+
+ if test.expectChannelID {
+ channelID := tlsConn.ConnectionState().ChannelID
+ if channelID == nil {
+ return fmt.Errorf("no channel ID negotiated")
+ }
+ if channelID.Curve != channelIDKey.Curve ||
+ channelIDKey.X.Cmp(channelIDKey.X) != 0 ||
+ channelIDKey.Y.Cmp(channelIDKey.Y) != 0 {
+ return fmt.Errorf("incorrect channel ID")
+ }
+ }
+
+ if expected := test.expectedNextProto; expected != "" {
+ if actual := tlsConn.ConnectionState().NegotiatedProtocol; actual != expected {
+ return fmt.Errorf("next proto mismatch: got %s, wanted %s", actual, expected)
+ }
+ }
+
+ if test.expectedNextProtoType != 0 {
+ if (test.expectedNextProtoType == alpn) != tlsConn.ConnectionState().NegotiatedProtocolFromALPN {
+ return fmt.Errorf("next proto type mismatch")
+ }
+ }
+
+ if test.shimWritesFirst {
+ var buf [5]byte
+ _, err := io.ReadFull(tlsConn, buf[:])
+ if err != nil {
+ return err
+ }
+ if string(buf[:]) != "hello" {
+ return fmt.Errorf("bad initial message")
+ }
}
if messageLen < 0 {
@@ -601,6 +680,10 @@ func runTest(test *testCase, buildDir string) error {
flags = append(flags, "-resume")
}
+ if test.shimWritesFirst {
+ flags = append(flags, "-shim-writes-first")
+ }
+
flags = append(flags, test.flags...)
var shim *exec.Cmd
@@ -630,12 +713,25 @@ func runTest(test *testCase, buildDir string) error {
}
}
- err := doExchange(test, &config, conn, test.messageLen)
+ err := doExchange(test, &config, conn, test.messageLen,
+ false /* not a resumption */)
conn.Close()
if err == nil && test.resumeSession {
- err = doExchange(test, &config, connResume, test.messageLen)
- connResume.Close()
+ var resumeConfig Config
+ if test.resumeConfig != nil {
+ resumeConfig = *test.resumeConfig
+ if len(resumeConfig.Certificates) == 0 {
+ resumeConfig.Certificates = []Certificate{getRSACertificate()}
+ }
+ resumeConfig.SessionTicketKey = config.SessionTicketKey
+ resumeConfig.ClientSessionCache = config.ClientSessionCache
+ } else {
+ resumeConfig = config
+ }
+ err = doExchange(test, &resumeConfig, connResume, test.messageLen,
+ true /* resumption */)
}
+ connResume.Close()
childErr := shim.Wait()
@@ -697,25 +793,40 @@ var testCipherSuites = []struct {
{"3DES-SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
{"AES128-GCM", TLS_RSA_WITH_AES_128_GCM_SHA256},
{"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
+ {"AES128-SHA256", TLS_RSA_WITH_AES_128_CBC_SHA256},
{"AES256-GCM", TLS_RSA_WITH_AES_256_GCM_SHA384},
{"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
+ {"AES256-SHA256", TLS_RSA_WITH_AES_256_CBC_SHA256},
{"DHE-RSA-AES128-GCM", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
{"DHE-RSA-AES128-SHA", TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
+ {"DHE-RSA-AES128-SHA256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
{"DHE-RSA-AES256-GCM", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},
{"DHE-RSA-AES256-SHA", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
+ {"DHE-RSA-AES256-SHA256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
{"ECDHE-ECDSA-AES128-GCM", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
{"ECDHE-ECDSA-AES128-SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
+ {"ECDHE-ECDSA-AES128-SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
+ {"ECDHE-ECDSA-AES256-GCM", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
{"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
+ {"ECDHE-ECDSA-AES256-SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
{"ECDHE-ECDSA-RC4-SHA", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
{"ECDHE-RSA-AES128-GCM", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
{"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
+ {"ECDHE-RSA-AES128-SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
{"ECDHE-RSA-AES256-GCM", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
{"ECDHE-RSA-AES256-SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
+ {"ECDHE-RSA-AES256-SHA384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384},
{"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
{"RC4-MD5", TLS_RSA_WITH_RC4_128_MD5},
{"RC4-SHA", TLS_RSA_WITH_RC4_128_SHA},
}
+func isTLS12Only(suiteName string) bool {
+ return strings.HasSuffix(suiteName, "-GCM") ||
+ strings.HasSuffix(suiteName, "-SHA256") ||
+ strings.HasSuffix(suiteName, "-SHA384")
+}
+
func addCipherSuiteTests() {
for _, suite := range testCipherSuites {
var cert Certificate
@@ -732,7 +843,7 @@ func addCipherSuiteTests() {
}
for _, ver := range tlsVersions {
- if ver.version != VersionTLS12 && strings.HasSuffix(suite.name, "-GCM") {
+ if ver.version < VersionTLS12 && isTLS12Only(suite.name) {
continue
}
@@ -902,29 +1013,14 @@ func addClientAuthTests() {
certPool.AddCert(cert)
for _, ver := range tlsVersions {
- if ver.version == VersionSSL30 {
- // TODO(davidben): The Go implementation does not
- // correctly compute CertificateVerify hashes for SSLv3.
- continue
- }
-
- var cipherSuites []uint16
- if ver.version >= VersionTLS12 {
- // Pick a SHA-256 cipher suite. The Go implementation
- // does not correctly handle client auth with a SHA-384
- // cipher suite.
- cipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}
- }
-
testCases = append(testCases, testCase{
testType: clientTest,
name: ver.name + "-Client-ClientAuth-RSA",
config: Config{
- MinVersion: ver.version,
- MaxVersion: ver.version,
- CipherSuites: cipherSuites,
- ClientAuth: RequireAnyClientCert,
- ClientCAs: certPool,
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ ClientAuth: RequireAnyClientCert,
+ ClientCAs: certPool,
},
flags: []string{
"-cert-file", rsaCertificateFile,
@@ -932,36 +1028,41 @@ func addClientAuthTests() {
},
})
testCases = append(testCases, testCase{
- testType: clientTest,
- name: ver.name + "-Client-ClientAuth-ECDSA",
- config: Config{
- MinVersion: ver.version,
- MaxVersion: ver.version,
- CipherSuites: cipherSuites,
- ClientAuth: RequireAnyClientCert,
- ClientCAs: certPool,
- },
- flags: []string{
- "-cert-file", ecdsaCertificateFile,
- "-key-file", ecdsaKeyFile,
- },
- })
- testCases = append(testCases, testCase{
testType: serverTest,
name: ver.name + "-Server-ClientAuth-RSA",
config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
Certificates: []Certificate{rsaCertificate},
},
flags: []string{"-require-any-client-certificate"},
})
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: ver.name + "-Server-ClientAuth-ECDSA",
- config: Config{
- Certificates: []Certificate{ecdsaCertificate},
- },
- flags: []string{"-require-any-client-certificate"},
- })
+ if ver.version != VersionSSL30 {
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: ver.name + "-Server-ClientAuth-ECDSA",
+ config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ Certificates: []Certificate{ecdsaCertificate},
+ },
+ flags: []string{"-require-any-client-certificate"},
+ })
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: ver.name + "-Client-ClientAuth-ECDSA",
+ config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ ClientAuth: RequireAnyClientCert,
+ ClientCAs: certPool,
+ },
+ flags: []string{
+ "-cert-file", ecdsaCertificateFile,
+ "-key-file", ecdsaKeyFile,
+ },
+ })
+ }
}
}
@@ -1029,8 +1130,7 @@ func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol)
testType: clientTest,
name: "ClientAuth-Client" + suffix,
config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
- ClientAuth: RequireAnyClientCert,
+ ClientAuth: RequireAnyClientCert,
Bugs: ProtocolBugs{
MaxHandshakeRecordLength: maxHandshakeRecordLength,
},
@@ -1080,13 +1180,14 @@ func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol)
protocol: protocol,
name: "NPN-Client" + suffix,
config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- NextProtos: []string{"foo"},
+ NextProtos: []string{"foo"},
Bugs: ProtocolBugs{
MaxHandshakeRecordLength: maxHandshakeRecordLength,
},
},
- flags: append(flags, "-select-next-proto", "foo"),
+ flags: append(flags, "-select-next-proto", "foo"),
+ expectedNextProto: "foo",
+ expectedNextProtoType: npn,
})
testCases = append(testCases, testCase{
protocol: protocol,
@@ -1101,6 +1202,8 @@ func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol)
flags: append(flags,
"-advertise-npn", "\x03foo\x03bar\x03baz",
"-expect-next-proto", "bar"),
+ expectedNextProto: "bar",
+ expectedNextProtoType: npn,
})
// Client does False Start and negotiates NPN.
@@ -1111,13 +1214,34 @@ func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol)
CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
NextProtos: []string{"foo"},
Bugs: ProtocolBugs{
+ ExpectFalseStart: true,
MaxHandshakeRecordLength: maxHandshakeRecordLength,
},
},
flags: append(flags,
"-false-start",
"-select-next-proto", "foo"),
- resumeSession: true,
+ shimWritesFirst: true,
+ resumeSession: true,
+ })
+
+ // Client does False Start and negotiates ALPN.
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ name: "FalseStart-ALPN" + suffix,
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ NextProtos: []string{"foo"},
+ Bugs: ProtocolBugs{
+ ExpectFalseStart: true,
+ MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ },
+ },
+ flags: append(flags,
+ "-false-start",
+ "-advertise-alpn", "\x03foo"),
+ shimWritesFirst: true,
+ resumeSession: true,
})
// False Start without session tickets.
@@ -1127,14 +1251,19 @@ func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol)
CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
NextProtos: []string{"foo"},
SessionTicketsDisabled: true,
+ Bugs: ProtocolBugs{
+ ExpectFalseStart: true,
+ MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ },
},
- flags: []string{
+ flags: append(flags,
"-false-start",
"-select-next-proto", "foo",
- },
+ ),
+ shimWritesFirst: true,
})
- // Client sends a V2ClientHello.
+ // Server parses a V2ClientHello.
testCases = append(testCases, testCase{
protocol: protocol,
testType: serverTest,
@@ -1151,6 +1280,42 @@ func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol)
},
flags: flags,
})
+
+ // Client sends a Channel ID.
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ name: "ChannelID-Client" + suffix,
+ config: Config{
+ RequestChannelID: true,
+ Bugs: ProtocolBugs{
+ MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ },
+ },
+ flags: append(flags,
+ "-send-channel-id", channelIDKeyFile,
+ ),
+ resumeSession: true,
+ expectChannelID: true,
+ })
+
+ // Server accepts a Channel ID.
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ testType: serverTest,
+ name: "ChannelID-Server" + suffix,
+ config: Config{
+ ChannelID: channelIDKey,
+ Bugs: ProtocolBugs{
+ MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ },
+ },
+ flags: append(flags,
+ "-expect-channel-id",
+ base64.StdEncoding.EncodeToString(channelIDBytes),
+ ),
+ resumeSession: true,
+ expectChannelID: true,
+ })
} else {
testCases = append(testCases, testCase{
protocol: protocol,
@@ -1216,6 +1381,231 @@ func addVersionNegotiationTests() {
}
}
+func addD5BugTests() {
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "D5Bug-NoQuirk-Reject",
+ config: Config{
+ CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
+ Bugs: ProtocolBugs{
+ SSL3RSAKeyExchange: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG:",
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "D5Bug-Quirk-Normal",
+ config: Config{
+ CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
+ },
+ flags: []string{"-tls-d5-bug"},
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "D5Bug-Quirk-Bug",
+ config: Config{
+ CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
+ Bugs: ProtocolBugs{
+ SSL3RSAKeyExchange: true,
+ },
+ },
+ flags: []string{"-tls-d5-bug"},
+ })
+}
+
+func addExtensionTests() {
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "DuplicateExtensionClient",
+ config: Config{
+ Bugs: ProtocolBugs{
+ DuplicateExtension: true,
+ },
+ },
+ shouldFail: true,
+ expectedLocalError: "remote error: error decoding message",
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "DuplicateExtensionServer",
+ config: Config{
+ Bugs: ProtocolBugs{
+ DuplicateExtension: true,
+ },
+ },
+ shouldFail: true,
+ expectedLocalError: "remote error: error decoding message",
+ })
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "ServerNameExtensionClient",
+ config: Config{
+ Bugs: ProtocolBugs{
+ ExpectServerName: "example.com",
+ },
+ },
+ flags: []string{"-host-name", "example.com"},
+ })
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "ServerNameExtensionClient",
+ config: Config{
+ Bugs: ProtocolBugs{
+ ExpectServerName: "mismatch.com",
+ },
+ },
+ flags: []string{"-host-name", "example.com"},
+ shouldFail: true,
+ expectedLocalError: "tls: unexpected server name",
+ })
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "ServerNameExtensionClient",
+ config: Config{
+ Bugs: ProtocolBugs{
+ ExpectServerName: "missing.com",
+ },
+ },
+ shouldFail: true,
+ expectedLocalError: "tls: unexpected server name",
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "ServerNameExtensionServer",
+ config: Config{
+ ServerName: "example.com",
+ },
+ flags: []string{"-expect-server-name", "example.com"},
+ resumeSession: true,
+ })
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "ALPNClient",
+ config: Config{
+ NextProtos: []string{"foo"},
+ },
+ flags: []string{
+ "-advertise-alpn", "\x03foo\x03bar\x03baz",
+ "-expect-alpn", "foo",
+ },
+ expectedNextProto: "foo",
+ expectedNextProtoType: alpn,
+ resumeSession: true,
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "ALPNServer",
+ config: Config{
+ NextProtos: []string{"foo", "bar", "baz"},
+ },
+ flags: []string{
+ "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
+ "-select-alpn", "foo",
+ },
+ expectedNextProto: "foo",
+ expectedNextProtoType: alpn,
+ resumeSession: true,
+ })
+ // Test that the server prefers ALPN over NPN.
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "ALPNServer-Preferred",
+ config: Config{
+ NextProtos: []string{"foo", "bar", "baz"},
+ },
+ flags: []string{
+ "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
+ "-select-alpn", "foo",
+ "-advertise-npn", "\x03foo\x03bar\x03baz",
+ },
+ expectedNextProto: "foo",
+ expectedNextProtoType: alpn,
+ resumeSession: true,
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "ALPNServer-Preferred-Swapped",
+ config: Config{
+ NextProtos: []string{"foo", "bar", "baz"},
+ Bugs: ProtocolBugs{
+ SwapNPNAndALPN: true,
+ },
+ },
+ flags: []string{
+ "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
+ "-select-alpn", "foo",
+ "-advertise-npn", "\x03foo\x03bar\x03baz",
+ },
+ expectedNextProto: "foo",
+ expectedNextProtoType: alpn,
+ resumeSession: true,
+ })
+}
+
+func addResumptionVersionTests() {
+ // TODO(davidben): Once DTLS 1.2 is working, test that as well.
+ for _, sessionVers := range tlsVersions {
+ // TODO(davidben): SSLv3 is omitted here because runner does not
+ // support resumption with session IDs.
+ if sessionVers.version == VersionSSL30 {
+ continue
+ }
+ for _, resumeVers := range tlsVersions {
+ if resumeVers.version == VersionSSL30 {
+ continue
+ }
+ suffix := "-" + sessionVers.name + "-" + resumeVers.name
+
+ // TODO(davidben): Write equivalent tests for the server
+ // and clean up the server's logic. This requires being
+ // able to give the shim a different set of SSL_OP_NO_*
+ // flags between the initial connection and the
+ // resume. Perhaps resumption should be tested by
+ // serializing the SSL_SESSION and starting a second
+ // shim.
+ testCases = append(testCases, testCase{
+ name: "Resume-Client" + suffix,
+ resumeSession: true,
+ config: Config{
+ MaxVersion: sessionVers.version,
+ CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+ Bugs: ProtocolBugs{
+ AllowSessionVersionMismatch: true,
+ },
+ },
+ expectedVersion: sessionVers.version,
+ resumeConfig: &Config{
+ MaxVersion: resumeVers.version,
+ CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+ Bugs: ProtocolBugs{
+ AllowSessionVersionMismatch: true,
+ },
+ },
+ expectedResumeVersion: resumeVers.version,
+ })
+
+ testCases = append(testCases, testCase{
+ name: "Resume-Client-NoResume" + suffix,
+ flags: []string{"-expect-session-miss"},
+ resumeSession: true,
+ config: Config{
+ MaxVersion: sessionVers.version,
+ CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+ },
+ expectedVersion: sessionVers.version,
+ resumeConfig: &Config{
+ MaxVersion: resumeVers.version,
+ CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+ SessionTicketsDisabled: true,
+ },
+ expectedResumeVersion: resumeVers.version,
+ })
+ }
+ }
+}
+
func worker(statusChan chan statusMsg, c chan *testCase, buildDir string, wg *sync.WaitGroup) {
defer wg.Done()
@@ -1268,6 +1658,9 @@ func main() {
addCBCSplittingTests()
addClientAuthTests()
addVersionNegotiationTests()
+ addD5BugTests()
+ addExtensionTests()
+ addResumptionVersionTests()
for _, async := range []bool{false, true} {
for _, splitHandshake := range []bool{false, true} {
for _, protocol := range []protocol{tls, dtls} {
diff --git a/ssl/test/runner/ticket.go b/ssl/test/runner/ticket.go
index 519543b..74791d6 100644
--- a/ssl/test/runner/ticket.go
+++ b/ssl/test/runner/ticket.go
@@ -18,10 +18,11 @@ import (
// sessionState contains the information that is serialized into a session
// ticket in order to later resume a connection.
type sessionState struct {
- vers uint16
- cipherSuite uint16
- masterSecret []byte
- certificates [][]byte
+ vers uint16
+ cipherSuite uint16
+ masterSecret []byte
+ handshakeHash []byte
+ certificates [][]byte
}
func (s *sessionState) equal(i interface{}) bool {
@@ -32,7 +33,8 @@ func (s *sessionState) equal(i interface{}) bool {
if s.vers != s1.vers ||
s.cipherSuite != s1.cipherSuite ||
- !bytes.Equal(s.masterSecret, s1.masterSecret) {
+ !bytes.Equal(s.masterSecret, s1.masterSecret) ||
+ !bytes.Equal(s.handshakeHash, s1.handshakeHash) {
return false
}
@@ -50,7 +52,7 @@ func (s *sessionState) equal(i interface{}) bool {
}
func (s *sessionState) marshal() []byte {
- length := 2 + 2 + 2 + len(s.masterSecret) + 2
+ length := 2 + 2 + 2 + len(s.masterSecret) + 2 + len(s.handshakeHash) + 2
for _, cert := range s.certificates {
length += 4 + len(cert)
}
@@ -67,6 +69,12 @@ func (s *sessionState) marshal() []byte {
copy(x, s.masterSecret)
x = x[len(s.masterSecret):]
+ x[0] = byte(len(s.handshakeHash) >> 8)
+ x[1] = byte(len(s.handshakeHash))
+ x = x[2:]
+ copy(x, s.handshakeHash)
+ x = x[len(s.handshakeHash):]
+
x[0] = byte(len(s.certificates) >> 8)
x[1] = byte(len(s.certificates))
x = x[2:]
@@ -103,6 +111,19 @@ func (s *sessionState) unmarshal(data []byte) bool {
return false
}
+ handshakeHashLen := int(data[0])<<8 | int(data[1])
+ data = data[2:]
+ if len(data) < handshakeHashLen {
+ return false
+ }
+
+ s.handshakeHash = data[:handshakeHashLen]
+ data = data[handshakeHashLen:]
+
+ if len(data) < 2 {
+ return false
+ }
+
numCerts := int(data[0])<<8 | int(data[1])
data = data[2:]
diff --git a/ssl/test/test_config.cc b/ssl/test/test_config.cc
index 9716227..70543cc 100644
--- a/ssl/test/test_config.cc
+++ b/ssl/test/test_config.cc
@@ -16,6 +16,9 @@
#include <string.h>
+#include <memory>
+
+#include <openssl/base64.h>
namespace {
@@ -50,25 +53,37 @@ const BoolFlag kBoolFlags[] = {
{ "-no-tls1", &TestConfig::no_tls1 },
{ "-no-ssl3", &TestConfig::no_ssl3 },
{ "-cookie-exchange", &TestConfig::cookie_exchange },
+ { "-shim-writes-first", &TestConfig::shim_writes_first },
+ { "-tls-d5-bug", &TestConfig::tls_d5_bug },
+ { "-expect-session-miss", &TestConfig::expect_session_miss },
};
const size_t kNumBoolFlags = sizeof(kBoolFlags) / sizeof(kBoolFlags[0]);
-// TODO(davidben): Some of these should be in a new kBase64Flags to allow NUL
-// bytes.
const StringFlag kStringFlags[] = {
{ "-key-file", &TestConfig::key_file },
{ "-cert-file", &TestConfig::cert_file },
{ "-expect-server-name", &TestConfig::expected_server_name },
- // Conveniently, 00 is not a certificate type.
- { "-expect-certificate-types", &TestConfig::expected_certificate_types },
{ "-advertise-npn", &TestConfig::advertise_npn },
{ "-expect-next-proto", &TestConfig::expected_next_proto },
{ "-select-next-proto", &TestConfig::select_next_proto },
+ { "-send-channel-id", &TestConfig::send_channel_id },
+ { "-host-name", &TestConfig::host_name },
+ { "-advertise-alpn", &TestConfig::advertise_alpn },
+ { "-expect-alpn", &TestConfig::expected_alpn },
+ { "-expect-advertised-alpn", &TestConfig::expected_advertised_alpn },
+ { "-select-alpn", &TestConfig::select_alpn },
};
const size_t kNumStringFlags = sizeof(kStringFlags) / sizeof(kStringFlags[0]);
+const StringFlag kBase64Flags[] = {
+ { "-expect-certificate-types", &TestConfig::expected_certificate_types },
+ { "-expect-channel-id", &TestConfig::expected_channel_id },
+};
+
+const size_t kNumBase64Flags = sizeof(kBase64Flags) / sizeof(kBase64Flags[0]);
+
} // namespace
TestConfig::TestConfig()
@@ -86,7 +101,10 @@ TestConfig::TestConfig()
no_tls11(false),
no_tls1(false),
no_ssl3(false),
- cookie_exchange(false) {
+ cookie_exchange(false),
+ shim_writes_first(false),
+ tls_d5_bug(false),
+ expect_session_miss(false) {
}
bool ParseConfig(int argc, char **argv, TestConfig *out_config) {
@@ -117,6 +135,32 @@ bool ParseConfig(int argc, char **argv, TestConfig *out_config) {
continue;
}
+ for (j = 0; j < kNumBase64Flags; j++) {
+ if (strcmp(argv[i], kBase64Flags[j].flag) == 0) {
+ break;
+ }
+ }
+ if (j < kNumBase64Flags) {
+ i++;
+ if (i >= argc) {
+ fprintf(stderr, "Missing parameter\n");
+ return false;
+ }
+ size_t len;
+ if (!EVP_DecodedLength(&len, strlen(argv[i]))) {
+ fprintf(stderr, "Invalid base64: %s\n", argv[i]);
+ }
+ std::unique_ptr<uint8_t[]> decoded(new uint8_t[len]);
+ if (!EVP_DecodeBase64(decoded.get(), &len, len,
+ reinterpret_cast<const uint8_t *>(argv[i]),
+ strlen(argv[i]))) {
+ fprintf(stderr, "Invalid base64: %s\n", argv[i]);
+ }
+ out_config->*(kBase64Flags[j].member) = std::string(
+ reinterpret_cast<const char *>(decoded.get()), len);
+ continue;
+ }
+
fprintf(stderr, "Unknown argument: %s\n", argv[i]);
return false;
}
diff --git a/ssl/test/test_config.h b/ssl/test/test_config.h
index 34d720e..acce504 100644
--- a/ssl/test/test_config.h
+++ b/ssl/test/test_config.h
@@ -43,6 +43,16 @@ struct TestConfig {
bool no_tls1;
bool no_ssl3;
bool cookie_exchange;
+ std::string expected_channel_id;
+ std::string send_channel_id;
+ bool shim_writes_first;
+ bool tls_d5_bug;
+ std::string host_name;
+ std::string advertise_alpn;
+ std::string expected_alpn;
+ std::string expected_advertised_alpn;
+ std::string select_alpn;
+ bool expect_session_miss;
};
bool ParseConfig(int argc, char **argv, TestConfig *out_config);
diff --git a/tool/CMakeLists.txt b/tool/CMakeLists.txt
index 4b9c03b..e513c8b 100644
--- a/tool/CMakeLists.txt
+++ b/tool/CMakeLists.txt
@@ -6,6 +6,7 @@ add_executable(
args.cc
client.cc
const.cc
+ pkcs12.cc
speed.cc
tool.cc
)
diff --git a/tool/client.cc b/tool/client.cc
index 5acc8b1..8aef559 100644
--- a/tool/client.cc
+++ b/tool/client.cc
@@ -18,6 +18,7 @@
#include <vector>
#include <errno.h>
+#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
@@ -253,6 +254,16 @@ bool Client(const std::vector<std::string> &args) {
SSL_CTX *ctx = SSL_CTX_new(SSLv23_client_method());
+ const char *keylog_file = getenv("SSLKEYLOGFILE");
+ if (keylog_file) {
+ BIO *keylog_bio = BIO_new_file(keylog_file, "a");
+ if (!keylog_bio) {
+ ERR_print_errors_cb(PrintErrorCallback, stderr);
+ return false;
+ }
+ SSL_CTX_set_keylog_bio(ctx, keylog_bio);
+ }
+
int sock = -1;
if (!Connect(&sock, args_map["-connect"])) {
return false;
diff --git a/tool/pkcs12.cc b/tool/pkcs12.cc
new file mode 100644
index 0000000..d35ba0b
--- /dev/null
+++ b/tool/pkcs12.cc
@@ -0,0 +1,125 @@
+/* Copyright (c) 2014, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <openssl/bytestring.h>
+#include <openssl/pem.h>
+#include <openssl/pkcs8.h>
+#include <openssl/stack.h>
+
+#include "internal.h"
+
+
+static const struct argument kArguments[] = {
+ {
+ "-dump", false, "Dump the key and contents of the given file to stdout",
+ },
+ {
+ "", false, "",
+ },
+};
+
+bool DoPKCS12(const std::vector<std::string> &args) {
+ std::map<std::string, std::string> args_map;
+
+ if (!ParseKeyValueArguments(&args_map, args, kArguments) ||
+ args_map["-dump"].empty()) {
+ PrintUsage(kArguments);
+ return false;
+ }
+
+ int fd = open(args_map["-dump"].c_str(), O_RDONLY);
+ if (fd < 0) {
+ perror("open");
+ return false;
+ }
+
+ struct stat st;
+ if (fstat(fd, &st)) {
+ perror("fstat");
+ close(fd);
+ return false;
+ }
+ const size_t size = st.st_size;
+
+ std::unique_ptr<uint8_t[]> contents(new uint8_t[size]);
+ ssize_t n;
+ size_t off = 0;
+ do {
+ n = read(fd, &contents[off], size - off);
+ if (n >= 0) {
+ off += static_cast<size_t>(n);
+ }
+ } while ((n > 0 && off < size) || (n == -1 && errno == EINTR));
+
+ if (off != size) {
+ perror("read");
+ close(fd);
+ return false;
+ }
+
+ close(fd);
+
+ printf("Enter password: ");
+ fflush(stdout);
+
+ char password[256];
+ off = 0;
+ do {
+ n = read(0, &password[off], sizeof(password) - 1 - off);
+ if (n >= 0) {
+ off += static_cast<size_t>(n);
+ }
+ } while ((n > 0 && memchr(password, '\n', off) == NULL &&
+ off < sizeof(password) - 1) ||
+ (n == -1 && errno == EINTR));
+
+ char *newline = reinterpret_cast<char*>(memchr(password, '\n', off));
+ if (newline == NULL) {
+ return false;
+ }
+ *newline = 0;
+
+ CBS pkcs12;
+ CBS_init(&pkcs12, contents.get(), size);
+
+ EVP_PKEY *key;
+ STACK_OF(X509) *certs = sk_X509_new_null();
+
+ if (!PKCS12_get_key_and_certs(&key, certs, &pkcs12, password)) {
+ fprintf(stderr, "Failed to parse PKCS#12 data:\n");
+ BIO_print_errors_fp(stderr);
+ return false;
+ }
+
+ PEM_write_PrivateKey(stdout, key, NULL, NULL, 0, NULL, NULL);
+ EVP_PKEY_free(key);
+
+ for (size_t i = 0; i < sk_X509_num(certs); i++) {
+ PEM_write_X509(stdout, sk_X509_value(certs, i));
+ }
+ sk_X509_pop_free(certs, X509_free);
+
+ return true;
+}
diff --git a/tool/tool.cc b/tool/tool.cc
index b8aa911..a0866d7 100644
--- a/tool/tool.cc
+++ b/tool/tool.cc
@@ -19,11 +19,12 @@
#include <openssl/ssl.h>
-bool Speed(const std::vector<std::string> &args);
bool Client(const std::vector<std::string> &args);
+bool DoPKCS12(const std::vector<std::string> &args);
+bool Speed(const std::vector<std::string> &args);
static void usage(const char *name) {
- printf("Usage: %s [speed|client]\n", name);
+ printf("Usage: %s [speed|client|pkcs12]\n", name);
}
int main(int argc, char **argv) {
@@ -43,6 +44,8 @@ int main(int argc, char **argv) {
return !Speed(args);
} else if (tool == "s_client" || tool == "client") {
return !Client(args);
+ } else if (tool == "pkcs12") {
+ return !DoPKCS12(args);
} else {
usage(argv[0]);
return 1;
diff --git a/util/all_tests.sh b/util/all_tests.sh
index 178c30b..e4f3126 100644
--- a/util/all_tests.sh
+++ b/util/all_tests.sh
@@ -20,32 +20,34 @@ if [ "$#" -ge 1 ]; then
fi
TESTS="
+./crypto/base64/base64_test
+./crypto/bio/bio_test
+./crypto/bn/bn_test
+./crypto/bytestring/bytestring_test
./crypto/cipher/aead_test aes-128-gcm $SRC/crypto/cipher/aes_128_gcm_tests.txt
+./crypto/cipher/aead_test aes-128-key-wrap $SRC/crypto/cipher/aes_128_key_wrap_tests.txt
./crypto/cipher/aead_test aes-256-gcm $SRC/crypto/cipher/aes_256_gcm_tests.txt
+./crypto/cipher/aead_test aes-256-key-wrap $SRC/crypto/cipher/aes_256_key_wrap_tests.txt
./crypto/cipher/aead_test chacha20-poly1305 $SRC/crypto/cipher/chacha20_poly1305_tests.txt
./crypto/cipher/aead_test rc4-md5 $SRC/crypto/cipher/rc4_md5_tests.txt
-./crypto/cipher/aead_test aes-128-key-wrap $SRC/crypto/cipher/aes_128_key_wrap_tests.txt
-./crypto/cipher/aead_test aes-256-key-wrap $SRC/crypto/cipher/aes_256_key_wrap_tests.txt
-./crypto/base64/base64_test
-./crypto/bio/bio_test
-./crypto/bn/bn_test
./crypto/cipher/cipher_test $SRC/crypto/cipher/cipher_test.txt
./crypto/dh/dh_test
./crypto/dsa/dsa_test
-./crypto/err/err_test
./crypto/ec/example_mul
./crypto/ecdsa/ecdsa_test
+./crypto/err/err_test
./crypto/evp/example_sign
./crypto/hmac/hmac_test
./crypto/lhash/lhash_test
./crypto/md5/md5_test
./crypto/modes/gcm_test
+./crypto/pkcs8/pkcs12_test
./crypto/rsa/rsa_test
./crypto/sha/sha1_test
+./crypto/x509/pkcs7_test
./crypto/x509v3/tab_test
./crypto/x509v3/v3name_test
-./crypto/bytestring/bytestring_test
-./crypto/x509/pkcs7_test
+./ssl/pqueue/pqueue_test
./ssl/ssl_test
"
diff --git a/util/doc.config b/util/doc.config
index 7c0835d..4b5f3b1 100644
--- a/util/doc.config
+++ b/util/doc.config
@@ -3,45 +3,45 @@
"Sections": [{
"Name": "Low-level infrastructure",
"Headers": [
- "crypto/base64/base64.h",
- "crypto/bio/bio.h",
- "crypto/buf/buf.h",
- "crypto/err/err.h",
- "crypto/cpu.h",
- "crypto/ex_data.h",
- "crypto/lhash/lhash.h",
- "crypto/mem.h",
- "crypto/obj/obj.h",
- "crypto/stack/stack.h",
- "crypto/thread.h",
- "crypto/time_support.h"
+ "include/openssl/base64.h",
+ "include/openssl/bio.h",
+ "include/openssl/buf.h",
+ "include/openssl/err.h",
+ "include/openssl/cpu.h",
+ "include/openssl/ex_data.h",
+ "include/openssl/lhash.h",
+ "include/openssl/mem.h",
+ "include/openssl/obj.h",
+ "include/openssl/stack.h",
+ "include/openssl/thread.h",
+ "include/openssl/time_support.h"
]
},{
"Name": "Low-level crypto primitives",
"Headers": [
- "crypto/aes/aes.h",
- "crypto/bn/bn.h",
- "crypto/des/des.h",
- "crypto/dh/dh.h",
- "crypto/dsa/dsa.h",
- "crypto/ec/ec.h",
- "crypto/ec/ec_key.h",
- "crypto/ecdh/ecdh.h",
- "crypto/ecdsa/ecdsa.h",
- "crypto/engine/engine.h",
- "crypto/hmac/hmac.h",
- "crypto/md5/md5.h",
- "crypto/modes/modes.h",
- "crypto/rc4/rc4.h",
- "crypto/rsa/rsa.h",
- "crypto/sha/sha.h"
+ "include/openssl/aes.h",
+ "include/openssl/bn.h",
+ "include/openssl/des.h",
+ "include/openssl/dh.h",
+ "include/openssl/dsa.h",
+ "include/openssl/ec.h",
+ "include/openssl/ec_key.h",
+ "include/openssl/ecdh.h",
+ "include/openssl/ecdsa.h",
+ "include/openssl/engine.h",
+ "include/openssl/hmac.h",
+ "include/openssl/md5.h",
+ "include/openssl/modes.h",
+ "include/openssl/rc4.h",
+ "include/openssl/rsa.h",
+ "include/openssl/sha.h"
]
},{
"Name": "Crypto interfaces",
"Headers": [
- "crypto/digest/digest.h",
- "crypto/cipher/cipher.h",
- "crypto/evp/evp.h"
+ "include/openssl/digest.h",
+ "include/openssl/cipher.h",
+ "include/openssl/evp.h"
]
}]
}