diff options
author | Primiano Tucci <primiano@google.com> | 2014-09-30 14:46:28 +0100 |
---|---|---|
committer | Primiano Tucci <primiano@google.com> | 2014-09-30 14:46:28 +0100 |
commit | 7c4e52cd7aebb9f2fa64355c58bc75509685da94 (patch) | |
tree | bbdd45cda3f7f15eae3f9dfa9ac4d6a604d82479 | |
parent | 208436baefdf6180355219406c666c259c7fc450 (diff) | |
parent | 885164b8d921ef7dba08b9e5ae031bf7350bf4ff (diff) | |
download | src-lollipop-mr1-wfc-release.tar.gz |
Merge from Chromium at DEPS revision 267aeeb8d85candroid-cts-5.1_r9android-cts-5.1_r8android-cts-5.1_r7android-cts-5.1_r6android-cts-5.1_r5android-cts-5.1_r4android-cts-5.1_r3android-cts-5.1_r28android-cts-5.1_r27android-cts-5.1_r26android-cts-5.1_r25android-cts-5.1_r24android-cts-5.1_r23android-cts-5.1_r22android-cts-5.1_r21android-cts-5.1_r20android-cts-5.1_r2android-cts-5.1_r19android-cts-5.1_r18android-cts-5.1_r17android-cts-5.1_r16android-cts-5.1_r15android-cts-5.1_r14android-cts-5.1_r13android-cts-5.1_r10android-cts-5.1_r1android-5.1.1_r9android-5.1.1_r8android-5.1.1_r7android-5.1.1_r6android-5.1.1_r5android-5.1.1_r4android-5.1.1_r38android-5.1.1_r37android-5.1.1_r36android-5.1.1_r35android-5.1.1_r34android-5.1.1_r33android-5.1.1_r30android-5.1.1_r3android-5.1.1_r29android-5.1.1_r28android-5.1.1_r26android-5.1.1_r25android-5.1.1_r24android-5.1.1_r23android-5.1.1_r22android-5.1.1_r20android-5.1.1_r2android-5.1.1_r19android-5.1.1_r18android-5.1.1_r17android-5.1.1_r16android-5.1.1_r15android-5.1.1_r14android-5.1.1_r13android-5.1.1_r12android-5.1.1_r10android-5.1.1_r1android-5.1.0_r5android-5.1.0_r4android-5.1.0_r3android-5.1.0_r1lollipop-mr1-wfc-releaselollipop-mr1-releaselollipop-mr1-fi-releaselollipop-mr1-devlollipop-mr1-cts-release
This commit was generated by merge_to_master.py.
Change-Id: I9b1c013632df72dcd4e450d6a3b7749444191f77
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,©))) + if ((ret=s->initial_ctx->get_session_cb(s,(unsigned char *) ctx->session_id,ctx->session_id_len,©))) { 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" ] }] } |