Reformatting of s3_{cbc|clnt}.c
Change-Id: Ie873bdf0dd5a66e76e6ebf909b1f1fe29b6fa611
diff --git a/ssl/s3_cbc.c b/ssl/s3_cbc.c
index 510d480..418a04f 100644
--- a/ssl/s3_cbc.c
+++ b/ssl/s3_cbc.c
@@ -76,27 +76,25 @@
* 0: (in non-constant time) if the record is publicly invalid.
* 1: if the padding was valid
* -1: otherwise. */
-int ssl3_cbc_remove_padding(const SSL* s,
- SSL3_RECORD *rec,
- unsigned block_size,
- unsigned mac_size)
- {
- unsigned padding_length, good;
- const unsigned overhead = 1 /* padding length byte */ + mac_size;
+int ssl3_cbc_remove_padding(const SSL *s, SSL3_RECORD *rec, unsigned block_size,
+ unsigned mac_size) {
+ unsigned padding_length, good;
+ const unsigned overhead = 1 /* padding length byte */ + mac_size;
- /* These lengths are all public so we can test them in non-constant
- * time. */
- if (overhead > rec->length)
- return 0;
+ /* These lengths are all public so we can test them in non-constant
+ * time. */
+ if (overhead > rec->length) {
+ return 0;
+ }
- padding_length = rec->data[rec->length-1];
- good = constant_time_ge(rec->length, padding_length+overhead);
- /* SSLv3 requires that the padding is minimal. */
- good &= constant_time_ge(block_size, padding_length+1);
- padding_length = good & (padding_length+1);
- rec->length -= padding_length;
- rec->type |= padding_length<<8; /* kludge: pass padding length */
- return constant_time_select_int(good, 1, -1);
+ padding_length = rec->data[rec->length - 1];
+ good = constant_time_ge(rec->length, padding_length + overhead);
+ /* SSLv3 requires that the padding is minimal. */
+ good &= constant_time_ge(block_size, padding_length + 1);
+ padding_length = good & (padding_length + 1);
+ rec->length -= padding_length;
+ rec->type |= padding_length << 8; /* kludge: pass padding length */
+ return constant_time_select_int(good, 1, -1);
}
/* tls1_cbc_remove_padding removes the CBC padding from the decrypted, TLS, CBC
@@ -110,64 +108,61 @@
* 0: (in non-constant time) if the record is publicly invalid.
* 1: if the padding was valid
* -1: otherwise. */
-int tls1_cbc_remove_padding(const SSL* s,
- SSL3_RECORD *rec,
- unsigned block_size,
- unsigned mac_size)
- {
- unsigned padding_length, good, to_check, i;
- const unsigned overhead = 1 /* padding length byte */ + mac_size;
- /* Check if version requires explicit IV */
- if (SSL_USE_EXPLICIT_IV(s))
- {
- /* These lengths are all public so we can test them in
- * non-constant time.
- */
- if (overhead + block_size > rec->length)
- return 0;
- /* We can now safely skip explicit IV */
- rec->data += block_size;
- rec->input += block_size;
- rec->length -= block_size;
- }
- else if (overhead > rec->length)
- return 0;
+int tls1_cbc_remove_padding(const SSL *s, SSL3_RECORD *rec, unsigned block_size,
+ unsigned mac_size) {
+ unsigned padding_length, good, to_check, i;
+ const unsigned overhead = 1 /* padding length byte */ + mac_size;
- padding_length = rec->data[rec->length-1];
+ /* Check if version requires explicit IV */
+ if (SSL_USE_EXPLICIT_IV(s)) {
+ /* These lengths are all public so we can test them in
+ * non-constant time. */
+ if (overhead + block_size > rec->length) {
+ return 0;
+ }
+ /* We can now safely skip explicit IV */
+ rec->data += block_size;
+ rec->input += block_size;
+ rec->length -= block_size;
+ } else if (overhead > rec->length) {
+ return 0;
+ }
- 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
- * length byte. Thus, with the length byte included, there are i+1
- * bytes of padding.
- *
- * We can't check just |padding_length+1| bytes because that leaks
- * decrypted information. Therefore we always have to check the maximum
- * amount of padding possible. (Again, the length of the record is
- * public information so we can use it.) */
- to_check = 256; /* maximum amount of padding, inc length byte. */
- if (to_check > rec->length)
- to_check = rec->length;
+ padding_length = rec->data[rec->length - 1];
- for (i = 0; i < to_check; i++)
- {
- unsigned char mask = constant_time_ge_8(padding_length, i);
- unsigned char b = rec->data[rec->length-1-i];
- /* The final |padding_length+1| bytes should all have the value
- * |padding_length|. Therefore the XOR should be zero. */
- good &= ~(mask&(padding_length ^ b));
- }
+ 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
+ * length byte. Thus, with the length byte included, there are i+1
+ * bytes of padding.
+ *
+ * We can't check just |padding_length+1| bytes because that leaks
+ * decrypted information. Therefore we always have to check the maximum
+ * amount of padding possible. (Again, the length of the record is
+ * public information so we can use it.) */
+ to_check = 256; /* maximum amount of padding, inc length byte. */
+ if (to_check > rec->length) {
+ to_check = rec->length;
+ }
- /* If any of the final |padding_length+1| bytes had the wrong value,
- * one or more of the lower eight bits of |good| will be cleared. */
- good = constant_time_eq(0xff, good & 0xff);
+ for (i = 0; i < to_check; i++) {
+ unsigned char mask = constant_time_ge_8(padding_length, i);
+ unsigned char b = rec->data[rec->length - 1 - i];
+ /* The final |padding_length+1| bytes should all have the value
+ * |padding_length|. Therefore the XOR should be zero. */
+ good &= ~(mask & (padding_length ^ b));
+ }
- padding_length = good & (padding_length+1);
- rec->length -= padding_length;
- rec->type |= padding_length<<8; /* kludge: pass padding length */
+ /* If any of the final |padding_length+1| bytes had the wrong value,
+ * one or more of the lower eight bits of |good| will be cleared. */
+ good = constant_time_eq(0xff, good & 0xff);
- return constant_time_select_int(good, 1, -1);
- }
+ padding_length = good & (padding_length + 1);
+ rec->length -= padding_length;
+ rec->type |= padding_length << 8; /* kludge: pass padding length */
+
+ return constant_time_select_int(good, 1, -1);
+}
/* ssl3_cbc_copy_mac copies |md_size| bytes from the end of |rec| to |out| in
* constant time (independent of the concrete value of rec->length, which may
@@ -188,144 +183,135 @@
*/
#define CBC_MAC_ROTATE_IN_PLACE
-void ssl3_cbc_copy_mac(unsigned char* out,
- const SSL3_RECORD *rec,
- unsigned md_size,unsigned orig_len)
- {
+void ssl3_cbc_copy_mac(unsigned char *out, const SSL3_RECORD *rec,
+ unsigned md_size, unsigned orig_len) {
#if defined(CBC_MAC_ROTATE_IN_PLACE)
- unsigned char rotated_mac_buf[64+EVP_MAX_MD_SIZE];
- unsigned char *rotated_mac;
+ unsigned char rotated_mac_buf[64 + EVP_MAX_MD_SIZE];
+ unsigned char *rotated_mac;
#else
- unsigned char rotated_mac[EVP_MAX_MD_SIZE];
+ unsigned char rotated_mac[EVP_MAX_MD_SIZE];
#endif
- /* mac_end is the index of |rec->data| just after the end of the MAC. */
- unsigned mac_end = rec->length;
- unsigned mac_start = mac_end - md_size;
- /* scan_start contains the number of bytes that we can ignore because
- * the MAC's position can only vary by 255 bytes. */
- unsigned scan_start = 0;
- unsigned i, j;
- unsigned div_spoiler;
- unsigned rotate_offset;
+ /* mac_end is the index of |rec->data| just after the end of the MAC. */
+ unsigned mac_end = rec->length;
+ unsigned mac_start = mac_end - md_size;
+ /* scan_start contains the number of bytes that we can ignore because
+ * the MAC's position can only vary by 255 bytes. */
+ unsigned scan_start = 0;
+ unsigned i, j;
+ unsigned div_spoiler;
+ unsigned rotate_offset;
- assert(orig_len >= md_size);
- assert(md_size <= EVP_MAX_MD_SIZE);
+ assert(orig_len >= md_size);
+ assert(md_size <= EVP_MAX_MD_SIZE);
#if defined(CBC_MAC_ROTATE_IN_PLACE)
- rotated_mac = rotated_mac_buf + ((0-(size_t)rotated_mac_buf)&63);
+ rotated_mac = rotated_mac_buf + ((0 - (size_t)rotated_mac_buf) & 63);
#endif
- /* This information is public so it's safe to branch based on it. */
- if (orig_len > md_size + 255 + 1)
- scan_start = orig_len - (md_size + 255 + 1);
- /* div_spoiler contains a multiple of md_size that is used to cause the
- * modulo operation to be constant time. Without this, the time varies
- * based on the amount of padding when running on Intel chips at least.
- *
- * The aim of right-shifting md_size is so that the compiler doesn't
- * figure out that it can remove div_spoiler as that would require it
- * to prove that md_size is always even, which I hope is beyond it. */
- div_spoiler = md_size >> 1;
- div_spoiler <<= (sizeof(div_spoiler)-1)*8;
- rotate_offset = (div_spoiler + mac_start - scan_start) % md_size;
+ /* This information is public so it's safe to branch based on it. */
+ if (orig_len > md_size + 255 + 1) {
+ scan_start = orig_len - (md_size + 255 + 1);
+ }
+ /* div_spoiler contains a multiple of md_size that is used to cause the
+ * modulo operation to be constant time. Without this, the time varies
+ * based on the amount of padding when running on Intel chips at least.
+ *
+ * The aim of right-shifting md_size is so that the compiler doesn't
+ * figure out that it can remove div_spoiler as that would require it
+ * to prove that md_size is always even, which I hope is beyond it. */
+ div_spoiler = md_size >> 1;
+ div_spoiler <<= (sizeof(div_spoiler) - 1) * 8;
+ rotate_offset = (div_spoiler + mac_start - scan_start) % md_size;
- memset(rotated_mac, 0, md_size);
- for (i = scan_start, j = 0; i < orig_len; i++)
- {
- unsigned char mac_started = constant_time_ge_8(i, mac_start);
- unsigned char mac_ended = constant_time_ge_8(i, mac_end);
- unsigned char b = rec->data[i];
- rotated_mac[j++] |= b & mac_started & ~mac_ended;
- j &= constant_time_lt(j,md_size);
- }
+ memset(rotated_mac, 0, md_size);
+ for (i = scan_start, j = 0; i < orig_len; i++) {
+ unsigned char mac_started = constant_time_ge_8(i, mac_start);
+ unsigned char mac_ended = constant_time_ge_8(i, mac_end);
+ unsigned char b = rec->data[i];
+ rotated_mac[j++] |= b & mac_started & ~mac_ended;
+ j &= constant_time_lt(j, md_size);
+ }
- /* Now rotate the MAC */
+/* Now rotate the MAC */
#if defined(CBC_MAC_ROTATE_IN_PLACE)
- j = 0;
- for (i = 0; i < md_size; i++)
- {
- /* in case cache-line is 32 bytes, touch second line */
- ((volatile unsigned char *)rotated_mac)[rotate_offset^32];
- out[j++] = rotated_mac[rotate_offset++];
- rotate_offset &= constant_time_lt(rotate_offset,md_size);
- }
+ j = 0;
+ for (i = 0; i < md_size; i++) {
+ /* in case cache-line is 32 bytes, touch second line */
+ ((volatile unsigned char *)rotated_mac)[rotate_offset ^ 32];
+ out[j++] = rotated_mac[rotate_offset++];
+ rotate_offset &= constant_time_lt(rotate_offset, md_size);
+ }
#else
- memset(out, 0, md_size);
- rotate_offset = md_size - rotate_offset;
- rotate_offset &= constant_time_lt(rotate_offset,md_size);
- for (i = 0; i < md_size; i++)
- {
- for (j = 0; j < md_size; j++)
- out[j] |= rotated_mac[i] & constant_time_eq_8(j, rotate_offset);
- rotate_offset++;
- rotate_offset &= constant_time_lt(rotate_offset,md_size);
- }
+ memset(out, 0, md_size);
+ rotate_offset = md_size - rotate_offset;
+ rotate_offset &= constant_time_lt(rotate_offset, md_size);
+ for (i = 0; i < md_size; i++) {
+ for (j = 0; j < md_size; j++) {
+ out[j] |= rotated_mac[i] & constant_time_eq_8(j, rotate_offset);
+ }
+ rotate_offset++;
+ rotate_offset &= constant_time_lt(rotate_offset, md_size);
+ }
#endif
- }
+}
/* u32toLE serialises an unsigned, 32-bit number (n) as four bytes at (p) in
* little-endian order. The value of p is advanced by four. */
#define u32toLE(n, p) \
- (*((p)++)=(unsigned char)(n), \
- *((p)++)=(unsigned char)(n>>8), \
- *((p)++)=(unsigned char)(n>>16), \
- *((p)++)=(unsigned char)(n>>24))
+ (*((p)++)=(unsigned char)(n), \
+ *((p)++)=(unsigned char)(n>>8), \
+ *((p)++)=(unsigned char)(n>>16), \
+ *((p)++)=(unsigned char)(n>>24))
/* 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_sha1_final_raw(void* ctx, unsigned char *md_out)
- {
- SHA_CTX *sha1 = ctx;
- l2n(sha1->h0, md_out);
- l2n(sha1->h1, md_out);
- l2n(sha1->h2, md_out);
- l2n(sha1->h3, md_out);
- l2n(sha1->h4, md_out);
- }
+static void tls1_sha1_final_raw(void *ctx, unsigned char *md_out) {
+ SHA_CTX *sha1 = ctx;
+ l2n(sha1->h0, md_out);
+ l2n(sha1->h1, md_out);
+ l2n(sha1->h2, md_out);
+ l2n(sha1->h3, md_out);
+ l2n(sha1->h4, md_out);
+}
#define LARGEST_DIGEST_CTX SHA_CTX
-static void tls1_sha256_final_raw(void* ctx, unsigned char *md_out)
- {
- SHA256_CTX *sha256 = ctx;
- unsigned i;
+static void tls1_sha256_final_raw(void *ctx, unsigned char *md_out) {
+ SHA256_CTX *sha256 = ctx;
+ unsigned i;
- for (i = 0; i < 8; i++)
- {
- l2n(sha256->h[i], md_out);
- }
- }
+ for (i = 0; i < 8; i++) {
+ l2n(sha256->h[i], md_out);
+ }
+}
#undef LARGEST_DIGEST_CTX
#define LARGEST_DIGEST_CTX SHA256_CTX
-static void tls1_sha512_final_raw(void* ctx, unsigned char *md_out)
- {
- SHA512_CTX *sha512 = ctx;
- unsigned i;
+static void tls1_sha512_final_raw(void *ctx, unsigned char *md_out) {
+ SHA512_CTX *sha512 = ctx;
+ unsigned i;
- for (i = 0; i < 8; i++)
- {
- l2n8(sha512->h[i], md_out);
- }
- }
+ for (i = 0; i < 8; i++) {
+ l2n8(sha512->h[i], md_out);
+ }
+}
#undef LARGEST_DIGEST_CTX
#define LARGEST_DIGEST_CTX SHA512_CTX
/* ssl3_cbc_record_digest_supported returns 1 iff |ctx| uses a hash function
* which ssl3_cbc_digest_record supports. */
-char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx)
- {
- switch (EVP_MD_CTX_type(ctx))
- {
- case NID_sha1:
- case NID_sha256:
- case NID_sha384:
- return 1;
- default:
- return 0;
- }
- }
+char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx) {
+ switch (EVP_MD_CTX_type(ctx)) {
+ case NID_sha1:
+ case NID_sha256:
+ case NID_sha384:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
/* ssl3_cbc_digest_record computes the MAC of a decrypted, padded SSLv3/TLS
* record.
@@ -346,277 +332,270 @@
* functions, above, we know that data_plus_mac_size is large enough to contain
* a padding byte and MAC. (If the padding was invalid, it might contain the
* padding too. ) */
-int ssl3_cbc_digest_record(
- const EVP_MD_CTX *ctx,
- unsigned char* md_out,
- size_t* md_out_size,
- const unsigned char header[13],
- const unsigned char *data,
- size_t data_plus_mac_size,
- size_t data_plus_mac_plus_padding_size,
- const unsigned char *mac_secret,
- unsigned mac_secret_length,
- char is_sslv3)
- {
- union { double align;
- unsigned char c[sizeof(LARGEST_DIGEST_CTX)]; } md_state;
- void (*md_final_raw)(void *ctx, unsigned char *md_out);
- void (*md_transform)(void *ctx, const unsigned char *block);
- unsigned md_size, md_block_size = 64;
- unsigned sslv3_pad_length = 40, header_length, variance_blocks,
- len, max_mac_bytes, num_blocks,
- num_starting_blocks, k, mac_end_offset, c, index_a, index_b;
- unsigned int bits; /* at most 18 bits */
- unsigned char length_bytes[MAX_HASH_BIT_COUNT_BYTES];
- /* hmac_pad is the masked HMAC key. */
- unsigned char hmac_pad[MAX_HASH_BLOCK_SIZE];
- unsigned char first_block[MAX_HASH_BLOCK_SIZE];
- unsigned char mac_out[EVP_MAX_MD_SIZE];
- unsigned i, j, md_out_size_u;
- EVP_MD_CTX md_ctx;
- /* mdLengthSize is the number of bytes in the length field that terminates
- * the hash. */
- unsigned md_length_size = 8;
+int ssl3_cbc_digest_record(const EVP_MD_CTX *ctx, unsigned char *md_out,
+ size_t *md_out_size, const unsigned char header[13],
+ const unsigned char *data, size_t data_plus_mac_size,
+ size_t data_plus_mac_plus_padding_size,
+ const unsigned char *mac_secret,
+ unsigned mac_secret_length, char is_sslv3) {
+ union {
+ double align;
+ unsigned char c[sizeof(LARGEST_DIGEST_CTX)];
+ } md_state;
+ void (*md_final_raw)(void *ctx, unsigned char *md_out);
+ void (*md_transform)(void *ctx, const unsigned char *block);
+ unsigned md_size, md_block_size = 64;
+ unsigned sslv3_pad_length = 40, header_length, variance_blocks, len,
+ max_mac_bytes, num_blocks, num_starting_blocks, k, mac_end_offset, c,
+ index_a, index_b;
+ unsigned int bits; /* at most 18 bits */
+ unsigned char length_bytes[MAX_HASH_BIT_COUNT_BYTES];
+ /* hmac_pad is the masked HMAC key. */
+ unsigned char hmac_pad[MAX_HASH_BLOCK_SIZE];
+ unsigned char first_block[MAX_HASH_BLOCK_SIZE];
+ unsigned char mac_out[EVP_MAX_MD_SIZE];
+ unsigned i, j, md_out_size_u;
+ EVP_MD_CTX md_ctx;
+ /* mdLengthSize is the number of bytes in the length field that terminates
+ * the hash. */
+ unsigned md_length_size = 8;
- /* This is a, hopefully redundant, check that allows us to forget about
- * many possible overflows later in this function. */
- assert(data_plus_mac_plus_padding_size < 1024*1024);
+ /* This is a, hopefully redundant, check that allows us to forget about
+ * many possible overflows later in this function. */
+ assert(data_plus_mac_plus_padding_size < 1024 * 1024);
- switch (EVP_MD_CTX_type(ctx))
- {
- 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_sha256:
- SHA256_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 = 32;
- break;
- case NID_sha384:
- SHA384_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 = 384/8;
- 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
- * supported. */
- assert(0);
- *md_out_size = 0;
- return 0;
- }
+ switch (EVP_MD_CTX_type(ctx)) {
+ 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;
- assert(md_length_size <= MAX_HASH_BIT_COUNT_BYTES);
- assert(md_block_size <= MAX_HASH_BLOCK_SIZE);
- assert(md_size <= EVP_MAX_MD_SIZE);
+ case NID_sha256:
+ SHA256_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 = 32;
+ break;
- header_length = 13;
- if (is_sslv3)
- {
- header_length =
- mac_secret_length +
- sslv3_pad_length +
- 8 /* sequence number */ +
- 1 /* record type */ +
- 2 /* record length */;
- }
+ case NID_sha384:
+ SHA384_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 = 384 / 8;
+ md_block_size = 128;
+ md_length_size = 16;
+ break;
- /* variance_blocks is the number of blocks of the hash that we have to
- * calculate in constant time because they could be altered by the
- * padding value.
- *
- * In SSLv3, the padding must be minimal so the end of the plaintext
- * varies by, at most, 15+20 = 35 bytes. (We conservatively assume that
- * the MAC size varies from 0..20 bytes.) In case the 9 bytes of hash
- * termination (0x80 + 64-bit length) don't fit in the final block, we
- * say that the final two blocks can vary based on the padding.
- *
- * TLSv1 has MACs up to 48 bytes long (SHA-384) and the padding is not
- * required to be minimal. Therefore we say that the final six blocks
- * can vary based on the padding.
- *
- * Later in the function, if the message is short and there obviously
- * cannot be this many blocks then variance_blocks can be reduced. */
- variance_blocks = is_sslv3 ? 2 : 6;
- /* From now on we're dealing with the MAC, which conceptually has 13
- * bytes of `header' before the start of the data (TLS) or 71/75 bytes
- * (SSLv3) */
- len = data_plus_mac_plus_padding_size + header_length;
- /* max_mac_bytes contains the maximum bytes of bytes in the MAC, including
- * |header|, assuming that there's no padding. */
- max_mac_bytes = len - md_size - 1;
- /* num_blocks is the maximum number of hash blocks. */
- num_blocks = (max_mac_bytes + 1 + md_length_size + md_block_size - 1) / md_block_size;
- /* In order to calculate the MAC in constant time we have to handle
- * the final blocks specially because the padding value could cause the
- * end to appear somewhere in the final |variance_blocks| blocks and we
- * can't leak where. However, |num_starting_blocks| worth of data can
- * be hashed right away because no padding value can affect whether
- * they are plaintext. */
- num_starting_blocks = 0;
- /* k is the starting byte offset into the conceptual header||data where
- * we start processing. */
- k = 0;
- /* mac_end_offset is the index just past the end of the data to be
- * MACed. */
- mac_end_offset = data_plus_mac_size + header_length - md_size;
- /* c is the index of the 0x80 byte in the final hash block that
- * contains application data. */
- c = mac_end_offset % md_block_size;
- /* index_a is the hash block number that contains the 0x80 terminating
- * value. */
- index_a = mac_end_offset / md_block_size;
- /* index_b is the hash block number that contains the 64-bit hash
- * length, in bits. */
- index_b = (mac_end_offset + md_length_size) / md_block_size;
- /* bits is the hash-length in bits. It includes the additional hash
- * block for the masked HMAC key, or whole of |header| in the case of
- * SSLv3. */
+ default:
+ /* ssl3_cbc_record_digest_supported should have been
+ * called first to check that the hash function is
+ * supported. */
+ assert(0);
+ *md_out_size = 0;
+ return 0;
+ }
- /* For SSLv3, if we're going to have any starting blocks then we need
- * at least two because the header is larger than a single block. */
- if (num_blocks > variance_blocks + (is_sslv3 ? 1 : 0))
- {
- num_starting_blocks = num_blocks - variance_blocks;
- k = md_block_size*num_starting_blocks;
- }
+ assert(md_length_size <= MAX_HASH_BIT_COUNT_BYTES);
+ assert(md_block_size <= MAX_HASH_BLOCK_SIZE);
+ assert(md_size <= EVP_MAX_MD_SIZE);
- bits = 8*mac_end_offset;
- if (!is_sslv3)
- {
- /* Compute the initial HMAC block. For SSLv3, the padding and
- * secret bytes are included in |header| because they take more
- * than a single block. */
- bits += 8*md_block_size;
- memset(hmac_pad, 0, md_block_size);
- assert(mac_secret_length <= sizeof(hmac_pad));
- memcpy(hmac_pad, mac_secret, mac_secret_length);
- for (i = 0; i < md_block_size; i++)
- hmac_pad[i] ^= 0x36;
+ header_length = 13;
+ if (is_sslv3) {
+ header_length = mac_secret_length + sslv3_pad_length +
+ 8 /* sequence number */ + 1 /* record type */ +
+ 2 /* record length */;
+ }
- md_transform(md_state.c, hmac_pad);
- }
+ /* variance_blocks is the number of blocks of the hash that we have to
+ * calculate in constant time because they could be altered by the
+ * padding value.
+ *
+ * In SSLv3, the padding must be minimal so the end of the plaintext
+ * varies by, at most, 15+20 = 35 bytes. (We conservatively assume that
+ * the MAC size varies from 0..20 bytes.) In case the 9 bytes of hash
+ * termination (0x80 + 64-bit length) don't fit in the final block, we
+ * say that the final two blocks can vary based on the padding.
+ *
+ * TLSv1 has MACs up to 48 bytes long (SHA-384) and the padding is not
+ * required to be minimal. Therefore we say that the final six blocks
+ * can vary based on the padding.
+ *
+ * Later in the function, if the message is short and there obviously
+ * cannot be this many blocks then variance_blocks can be reduced. */
+ variance_blocks = is_sslv3 ? 2 : 6;
+ /* From now on we're dealing with the MAC, which conceptually has 13
+ * bytes of `header' before the start of the data (TLS) or 71/75 bytes
+ * (SSLv3) */
+ len = data_plus_mac_plus_padding_size + header_length;
+ /* max_mac_bytes contains the maximum bytes of bytes in the MAC, including
+ * |header|, assuming that there's no padding. */
+ max_mac_bytes = len - md_size - 1;
+ /* num_blocks is the maximum number of hash blocks. */
+ num_blocks =
+ (max_mac_bytes + 1 + md_length_size + md_block_size - 1) / md_block_size;
+ /* In order to calculate the MAC in constant time we have to handle
+ * the final blocks specially because the padding value could cause the
+ * end to appear somewhere in the final |variance_blocks| blocks and we
+ * can't leak where. However, |num_starting_blocks| worth of data can
+ * be hashed right away because no padding value can affect whether
+ * they are plaintext. */
+ num_starting_blocks = 0;
+ /* k is the starting byte offset into the conceptual header||data where
+ * we start processing. */
+ k = 0;
+ /* mac_end_offset is the index just past the end of the data to be
+ * MACed. */
+ mac_end_offset = data_plus_mac_size + header_length - md_size;
+ /* c is the index of the 0x80 byte in the final hash block that
+ * contains application data. */
+ c = mac_end_offset % md_block_size;
+ /* index_a is the hash block number that contains the 0x80 terminating
+ * value. */
+ index_a = mac_end_offset / md_block_size;
+ /* index_b is the hash block number that contains the 64-bit hash
+ * length, in bits. */
+ index_b = (mac_end_offset + md_length_size) / md_block_size;
+ /* bits is the hash-length in bits. It includes the additional hash
+ * block for the masked HMAC key, or whole of |header| in the case of
+ * SSLv3. */
- 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;
+ /* For SSLv3, if we're going to have any starting blocks then we need
+ * at least two because the header is larger than a single block. */
+ if (num_blocks > variance_blocks + (is_sslv3 ? 1 : 0)) {
+ num_starting_blocks = num_blocks - variance_blocks;
+ k = md_block_size * num_starting_blocks;
+ }
- if (k > 0)
- {
- if (is_sslv3)
- {
- /* The SSLv3 header is larger than a single block.
- * overhang is the number of bytes beyond a single
- * 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);
- memcpy(first_block + overhang, data, md_block_size-overhang);
- md_transform(md_state.c, first_block);
- for (i = 1; i < k/md_block_size - 1; i++)
- md_transform(md_state.c, data + md_block_size*i - overhang);
- }
- else
- {
- /* k is a multiple of md_block_size. */
- memcpy(first_block, header, 13);
- memcpy(first_block+13, data, md_block_size-13);
- md_transform(md_state.c, first_block);
- for (i = 1; i < k/md_block_size; i++)
- md_transform(md_state.c, data + md_block_size*i - 13);
- }
- }
+ bits = 8 * mac_end_offset;
+ if (!is_sslv3) {
+ /* Compute the initial HMAC block. For SSLv3, the padding and
+ * secret bytes are included in |header| because they take more
+ * than a single block. */
+ bits += 8 * md_block_size;
+ memset(hmac_pad, 0, md_block_size);
+ assert(mac_secret_length <= sizeof(hmac_pad));
+ memcpy(hmac_pad, mac_secret, mac_secret_length);
+ for (i = 0; i < md_block_size; i++) {
+ hmac_pad[i] ^= 0x36;
+ }
- memset(mac_out, 0, sizeof(mac_out));
+ md_transform(md_state.c, hmac_pad);
+ }
- /* We now process the final hash blocks. For each block, we construct
- * it in constant time. If the |i==index_a| then we'll include the 0x80
- * bytes and zero pad etc. For each block we selectively copy it, in
- * constant time, to |mac_out|. */
- for (i = num_starting_blocks; i <= num_starting_blocks+variance_blocks; i++)
- {
- unsigned char block[MAX_HASH_BLOCK_SIZE];
- unsigned char is_block_a = constant_time_eq_8(i, index_a);
- unsigned char is_block_b = constant_time_eq_8(i, index_b);
- for (j = 0; j < md_block_size; j++)
- {
- unsigned char b = 0, is_past_c, is_past_cp1;
- if (k < header_length)
- b = header[k];
- else if (k < data_plus_mac_plus_padding_size + header_length)
- b = data[k-header_length];
- k++;
+ 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;
- is_past_c = is_block_a & constant_time_ge_8(j, c);
- is_past_cp1 = is_block_a & constant_time_ge_8(j, c+1);
- /* If this is the block containing the end of the
- * application data, and we are at the offset for the
- * 0x80 value, then overwrite b with 0x80. */
- b = constant_time_select_8(is_past_c, 0x80, b);
- /* If this the the block containing the end of the
- * application data and we're past the 0x80 value then
- * just write zero. */
- b = b&~is_past_cp1;
- /* If this is index_b (the final block), but not
- * index_a (the end of the data), then the 64-bit
- * length didn't fit into index_a and we're having to
- * add an extra block of zeros. */
- b &= ~is_block_b | is_block_a;
+ if (k > 0) {
+ if (is_sslv3) {
+ /* The SSLv3 header is larger than a single block.
+ * overhang is the number of bytes beyond a single
+ * 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);
+ memcpy(first_block + overhang, data, md_block_size - overhang);
+ md_transform(md_state.c, first_block);
+ for (i = 1; i < k / md_block_size - 1; i++) {
+ md_transform(md_state.c, data + md_block_size * i - overhang);
+ }
+ } else {
+ /* k is a multiple of md_block_size. */
+ memcpy(first_block, header, 13);
+ memcpy(first_block + 13, data, md_block_size - 13);
+ md_transform(md_state.c, first_block);
+ for (i = 1; i < k / md_block_size; i++) {
+ md_transform(md_state.c, data + md_block_size * i - 13);
+ }
+ }
+ }
- /* The final bytes of one of the blocks contains the
- * length. */
- if (j >= md_block_size - md_length_size)
- {
- /* If this is index_b, write a length byte. */
- b = constant_time_select_8(is_block_b, length_bytes[j-(md_block_size-md_length_size)], b);
- }
- block[j] = b;
- }
+ memset(mac_out, 0, sizeof(mac_out));
- md_transform(md_state.c, block);
- md_final_raw(md_state.c, block);
- /* If this is index_b, copy the hash value to |mac_out|. */
- for (j = 0; j < md_size; j++)
- mac_out[j] |= block[j]&is_block_b;
- }
+ /* We now process the final hash blocks. For each block, we construct
+ * it in constant time. If the |i==index_a| then we'll include the 0x80
+ * bytes and zero pad etc. For each block we selectively copy it, in
+ * constant time, to |mac_out|. */
+ for (i = num_starting_blocks; i <= num_starting_blocks + variance_blocks;
+ i++) {
+ unsigned char block[MAX_HASH_BLOCK_SIZE];
+ unsigned char is_block_a = constant_time_eq_8(i, index_a);
+ unsigned char is_block_b = constant_time_eq_8(i, index_b);
+ for (j = 0; j < md_block_size; j++) {
+ unsigned char b = 0, is_past_c, is_past_cp1;
+ if (k < header_length) {
+ b = header[k];
+ } else if (k < data_plus_mac_plus_padding_size + header_length) {
+ b = data[k - header_length];
+ }
+ k++;
- EVP_MD_CTX_init(&md_ctx);
- if (!EVP_DigestInit_ex(&md_ctx, ctx->digest, NULL /* engine */))
- {
- EVP_MD_CTX_cleanup(&md_ctx);
- return 0;
- }
+ is_past_c = is_block_a & constant_time_ge_8(j, c);
+ is_past_cp1 = is_block_a & constant_time_ge_8(j, c + 1);
+ /* If this is the block containing the end of the
+ * application data, and we are at the offset for the
+ * 0x80 value, then overwrite b with 0x80. */
+ b = constant_time_select_8(is_past_c, 0x80, b);
+ /* If this the the block containing the end of the
+ * application data and we're past the 0x80 value then
+ * just write zero. */
+ b = b & ~is_past_cp1;
+ /* If this is index_b (the final block), but not
+ * index_a (the end of the data), then the 64-bit
+ * length didn't fit into index_a and we're having to
+ * add an extra block of zeros. */
+ b &= ~is_block_b | is_block_a;
- if (is_sslv3)
- {
- /* We repurpose |hmac_pad| to contain the SSLv3 pad2 block. */
- memset(hmac_pad, 0x5c, sslv3_pad_length);
+ /* The final bytes of one of the blocks contains the
+ * length. */
+ if (j >= md_block_size - md_length_size) {
+ /* If this is index_b, write a length byte. */
+ b = constant_time_select_8(
+ is_block_b, length_bytes[j - (md_block_size - md_length_size)], b);
+ }
+ block[j] = b;
+ }
- EVP_DigestUpdate(&md_ctx, mac_secret, mac_secret_length);
- EVP_DigestUpdate(&md_ctx, hmac_pad, sslv3_pad_length);
- EVP_DigestUpdate(&md_ctx, mac_out, md_size);
- }
- else
- {
- /* Complete the HMAC in the standard manner. */
- for (i = 0; i < md_block_size; i++)
- hmac_pad[i] ^= 0x6a;
+ md_transform(md_state.c, block);
+ md_final_raw(md_state.c, block);
+ /* If this is index_b, copy the hash value to |mac_out|. */
+ for (j = 0; j < md_size; j++) {
+ mac_out[j] |= block[j] & is_block_b;
+ }
+ }
- EVP_DigestUpdate(&md_ctx, hmac_pad, md_block_size);
- EVP_DigestUpdate(&md_ctx, mac_out, md_size);
- }
- EVP_DigestFinal(&md_ctx, md_out, &md_out_size_u);
- *md_out_size = md_out_size_u;
- EVP_MD_CTX_cleanup(&md_ctx);
+ EVP_MD_CTX_init(&md_ctx);
+ if (!EVP_DigestInit_ex(&md_ctx, ctx->digest, NULL /* engine */)) {
+ EVP_MD_CTX_cleanup(&md_ctx);
+ return 0;
+ }
- return 1;
- }
+ if (is_sslv3) {
+ /* We repurpose |hmac_pad| to contain the SSLv3 pad2 block. */
+ memset(hmac_pad, 0x5c, sslv3_pad_length);
+
+ EVP_DigestUpdate(&md_ctx, mac_secret, mac_secret_length);
+ EVP_DigestUpdate(&md_ctx, hmac_pad, sslv3_pad_length);
+ EVP_DigestUpdate(&md_ctx, mac_out, md_size);
+ } else {
+ /* Complete the HMAC in the standard manner. */
+ for (i = 0; i < md_block_size; i++) {
+ hmac_pad[i] ^= 0x6a;
+ }
+
+ EVP_DigestUpdate(&md_ctx, hmac_pad, md_block_size);
+ EVP_DigestUpdate(&md_ctx, mac_out, md_size);
+ }
+ EVP_DigestFinal(&md_ctx, md_out, &md_out_size_u);
+ *md_out_size = md_out_size_u;
+ EVP_MD_CTX_cleanup(&md_ctx);
+
+ return 1;
+}
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index c2f2291..1a45805 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -166,2368 +166,2246 @@
#include "ssl_locl.h"
#include "../crypto/dh/internal.h"
-int ssl3_connect(SSL *s)
- {
- BUF_MEM *buf=NULL;
- void (*cb)(const SSL *ssl,int type,int val)=NULL;
- int ret= -1;
- int new_state,state,skip=0;
- assert(s->handshake_func == ssl3_connect);
- assert(!s->server);
- assert(!SSL_IS_DTLS(s));
+int ssl3_connect(SSL *s) {
+ BUF_MEM *buf = NULL;
+ void (*cb)(const SSL *ssl, int type, int val) = NULL;
+ int ret = -1;
+ int new_state, state, skip = 0;
- ERR_clear_error();
- ERR_clear_system_error();
+ assert(s->handshake_func == ssl3_connect);
+ assert(!s->server);
+ assert(!SSL_IS_DTLS(s));
- if (s->info_callback != NULL)
- cb=s->info_callback;
- else if (s->ctx->info_callback != NULL)
- cb=s->ctx->info_callback;
-
- s->in_handshake++;
+ ERR_clear_error();
+ ERR_clear_system_error();
- for (;;)
- {
- state=s->state;
+ if (s->info_callback != NULL) {
+ cb = s->info_callback;
+ } else if (s->ctx->info_callback != NULL) {
+ cb = s->ctx->info_callback;
+ }
- switch(s->state)
- {
- case SSL_ST_RENEGOTIATE:
- s->renegotiate=1;
- s->state=SSL_ST_CONNECT;
- s->ctx->stats.sess_connect_renegotiate++;
- /* break */
- case SSL_ST_CONNECT:
- case SSL_ST_BEFORE|SSL_ST_CONNECT:
+ s->in_handshake++;
- if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
+ for (;;) {
+ state = s->state;
- if (s->init_buf == NULL)
- {
- if ((buf=BUF_MEM_new()) == NULL)
- {
- ret= -1;
- goto end;
- }
- if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH))
- {
- ret= -1;
- goto end;
- }
- s->init_buf=buf;
- buf=NULL;
- }
+ switch (s->state) {
+ case SSL_ST_RENEGOTIATE:
+ s->renegotiate = 1;
+ s->state = SSL_ST_CONNECT;
+ s->ctx->stats.sess_connect_renegotiate++;
+ /* fallthrough */
+ case SSL_ST_CONNECT:
+ case SSL_ST_BEFORE | SSL_ST_CONNECT:
+ if (cb != NULL)
+ cb(s, SSL_CB_HANDSHAKE_START, 1);
- if (!ssl3_setup_buffers(s)) { ret= -1; goto end; }
+ if (s->init_buf == NULL) {
+ buf = BUF_MEM_new();
+ if (buf == NULL ||
+ !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
+ ret = -1;
+ goto end;
+ }
- /* setup buffing BIO */
- if (!ssl_init_wbio_buffer(s,0)) { ret= -1; goto end; }
+ s->init_buf = buf;
+ buf = NULL;
+ }
- /* don't push the buffering BIO quite yet */
+ if (!ssl3_setup_buffers(s) ||
+ !ssl_init_wbio_buffer(s, 0)) {
+ ret = -1;
+ goto end;
+ }
- if (!ssl3_init_finished_mac(s))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_connect, ERR_R_INTERNAL_ERROR);
- ret = -1;
- goto end;
- }
+ /* don't push the buffering BIO quite yet */
- s->state=SSL3_ST_CW_CLNT_HELLO_A;
- s->ctx->stats.sess_connect++;
- s->init_num=0;
- break;
+ if (!ssl3_init_finished_mac(s)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_connect, ERR_R_INTERNAL_ERROR);
+ ret = -1;
+ goto end;
+ }
- case SSL3_ST_CW_CLNT_HELLO_A:
- case SSL3_ST_CW_CLNT_HELLO_B:
+ s->state = SSL3_ST_CW_CLNT_HELLO_A;
+ s->ctx->stats.sess_connect++;
+ s->init_num = 0;
+ break;
- s->shutdown=0;
- ret=ssl3_send_client_hello(s);
- if (ret <= 0) goto end;
- s->state=SSL3_ST_CR_SRVR_HELLO_A;
- s->init_num=0;
+ case SSL3_ST_CW_CLNT_HELLO_A:
+ case SSL3_ST_CW_CLNT_HELLO_B:
+ s->shutdown = 0;
+ ret = ssl3_send_client_hello(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->state = SSL3_ST_CR_SRVR_HELLO_A;
+ s->init_num = 0;
- /* turn on buffering for the next lot of output */
- if (s->bbio != s->wbio)
- s->wbio=BIO_push(s->bbio,s->wbio);
+ /* turn on buffering for the next lot of output */
+ if (s->bbio != s->wbio) {
+ s->wbio = BIO_push(s->bbio, s->wbio);
+ }
- break;
+ break;
- case SSL3_ST_CR_SRVR_HELLO_A:
- case SSL3_ST_CR_SRVR_HELLO_B:
- ret=ssl3_get_server_hello(s);
- if (ret <= 0) goto end;
+ case SSL3_ST_CR_SRVR_HELLO_A:
+ case SSL3_ST_CR_SRVR_HELLO_B:
+ ret = ssl3_get_server_hello(s);
+ if (ret <= 0) {
+ goto end;
+ }
- if (s->hit)
- {
- s->state=SSL3_ST_CR_CHANGE;
- if (s->tlsext_ticket_expected)
- {
- /* receive renewed session ticket */
- s->state=SSL3_ST_CR_SESSION_TICKET_A;
- }
- }
- else
- {
- s->state=SSL3_ST_CR_CERT_A;
- }
- s->init_num=0;
- break;
+ if (s->hit) {
+ s->state = SSL3_ST_CR_CHANGE;
+ if (s->tlsext_ticket_expected) {
+ /* receive renewed session ticket */
+ s->state = SSL3_ST_CR_SESSION_TICKET_A;
+ }
+ } else {
+ s->state = SSL3_ST_CR_CERT_A;
+ }
+ s->init_num = 0;
+ break;
- case SSL3_ST_CR_CERT_A:
- case SSL3_ST_CR_CERT_B:
- if (ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher))
- {
- ret=ssl3_get_server_certificate(s);
- if (ret <= 0) goto end;
- if (s->s3->tmp.certificate_status_expected)
- s->state=SSL3_ST_CR_CERT_STATUS_A;
- else
- s->state=SSL3_ST_CR_KEY_EXCH_A;
- }
- else
- {
- skip = 1;
- s->state=SSL3_ST_CR_KEY_EXCH_A;
- }
- s->init_num=0;
- break;
+ case SSL3_ST_CR_CERT_A:
+ case SSL3_ST_CR_CERT_B:
+ if (ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) {
+ ret = ssl3_get_server_certificate(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ if (s->s3->tmp.certificate_status_expected) {
+ s->state = SSL3_ST_CR_CERT_STATUS_A;
+ } else {
+ s->state = SSL3_ST_CR_KEY_EXCH_A;
+ }
+ } else {
+ skip = 1;
+ s->state = SSL3_ST_CR_KEY_EXCH_A;
+ }
+ s->init_num = 0;
+ break;
- case SSL3_ST_CR_KEY_EXCH_A:
- case SSL3_ST_CR_KEY_EXCH_B:
- ret=ssl3_get_server_key_exchange(s);
- if (ret <= 0) goto end;
- s->state=SSL3_ST_CR_CERT_REQ_A;
- s->init_num=0;
+ case SSL3_ST_CR_KEY_EXCH_A:
+ case SSL3_ST_CR_KEY_EXCH_B:
+ ret = ssl3_get_server_key_exchange(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->state = SSL3_ST_CR_CERT_REQ_A;
+ s->init_num = 0;
- /* at this point we check that we have the
- * required stuff from the server */
- if (!ssl3_check_cert_and_algorithm(s))
- {
- ret= -1;
- goto end;
- }
- break;
+ /* at this point we check that we have the
+ * required stuff from the server */
+ if (!ssl3_check_cert_and_algorithm(s)) {
+ ret = -1;
+ goto end;
+ }
+ break;
- case SSL3_ST_CR_CERT_REQ_A:
- case SSL3_ST_CR_CERT_REQ_B:
- ret=ssl3_get_certificate_request(s);
- if (ret <= 0) goto end;
- s->state=SSL3_ST_CR_SRVR_DONE_A;
- s->init_num=0;
- break;
+ case SSL3_ST_CR_CERT_REQ_A:
+ case SSL3_ST_CR_CERT_REQ_B:
+ ret = ssl3_get_certificate_request(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->state = SSL3_ST_CR_SRVR_DONE_A;
+ s->init_num = 0;
+ break;
- case SSL3_ST_CR_SRVR_DONE_A:
- case SSL3_ST_CR_SRVR_DONE_B:
- ret=ssl3_get_server_done(s);
- if (ret <= 0) goto end;
- if (s->s3->tmp.cert_req)
- s->state=SSL3_ST_CW_CERT_A;
- else
- s->state=SSL3_ST_CW_KEY_EXCH_A;
- s->init_num=0;
+ case SSL3_ST_CR_SRVR_DONE_A:
+ case SSL3_ST_CR_SRVR_DONE_B:
+ ret = ssl3_get_server_done(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ if (s->s3->tmp.cert_req) {
+ s->state = SSL3_ST_CW_CERT_A;
+ } else {
+ s->state = SSL3_ST_CW_KEY_EXCH_A;
+ }
+ s->init_num = 0;
- break;
+ break;
- case SSL3_ST_CW_CERT_A:
- case SSL3_ST_CW_CERT_B:
- case SSL3_ST_CW_CERT_C:
- case SSL3_ST_CW_CERT_D:
- ret=ssl3_send_client_certificate(s);
- if (ret <= 0) goto end;
- s->state=SSL3_ST_CW_KEY_EXCH_A;
- s->init_num=0;
- break;
+ case SSL3_ST_CW_CERT_A:
+ case SSL3_ST_CW_CERT_B:
+ case SSL3_ST_CW_CERT_C:
+ case SSL3_ST_CW_CERT_D:
+ ret = ssl3_send_client_certificate(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->state = SSL3_ST_CW_KEY_EXCH_A;
+ s->init_num = 0;
+ break;
- case SSL3_ST_CW_KEY_EXCH_A:
- case SSL3_ST_CW_KEY_EXCH_B:
- ret=ssl3_send_client_key_exchange(s);
- if (ret <= 0) goto end;
- /* For TLS, cert_req is set to 2, so a cert chain
- * of nothing is sent, but no verify packet is sent */
- if (s->s3->tmp.cert_req == 1)
- {
- s->state=SSL3_ST_CW_CERT_VRFY_A;
- }
- else
- {
- s->state=SSL3_ST_CW_CHANGE_A;
- s->s3->change_cipher_spec=0;
- }
+ case SSL3_ST_CW_KEY_EXCH_A:
+ case SSL3_ST_CW_KEY_EXCH_B:
+ ret = ssl3_send_client_key_exchange(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ /* For TLS, cert_req is set to 2, so a cert chain
+ * of nothing is sent, but no verify packet is sent */
+ if (s->s3->tmp.cert_req == 1) {
+ s->state = SSL3_ST_CW_CERT_VRFY_A;
+ } else {
+ s->state = SSL3_ST_CW_CHANGE_A;
+ s->s3->change_cipher_spec = 0;
+ }
- s->init_num=0;
- break;
+ s->init_num = 0;
+ break;
- case SSL3_ST_CW_CERT_VRFY_A:
- case SSL3_ST_CW_CERT_VRFY_B:
- ret=ssl3_send_cert_verify(s);
- if (ret <= 0) goto end;
- s->state=SSL3_ST_CW_CHANGE_A;
- s->init_num=0;
- s->s3->change_cipher_spec=0;
- break;
+ case SSL3_ST_CW_CERT_VRFY_A:
+ case SSL3_ST_CW_CERT_VRFY_B:
+ ret = ssl3_send_cert_verify(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->state = SSL3_ST_CW_CHANGE_A;
+ s->init_num = 0;
+ s->s3->change_cipher_spec = 0;
+ break;
- case SSL3_ST_CW_CHANGE_A:
- case SSL3_ST_CW_CHANGE_B:
- ret=ssl3_send_change_cipher_spec(s,
- SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B);
- if (ret <= 0) goto end;
+ case SSL3_ST_CW_CHANGE_A:
+ case SSL3_ST_CW_CHANGE_B:
+ ret = ssl3_send_change_cipher_spec(s, SSL3_ST_CW_CHANGE_A,
+ SSL3_ST_CW_CHANGE_B);
+ if (ret <= 0) {
+ goto end;
+ }
- s->state=SSL3_ST_CW_FINISHED_A;
- if (s->s3->tlsext_channel_id_valid)
- s->state=SSL3_ST_CW_CHANNEL_ID_A;
- if (s->s3->next_proto_neg_seen)
- s->state=SSL3_ST_CW_NEXT_PROTO_A;
- s->init_num=0;
+ s->state = SSL3_ST_CW_FINISHED_A;
+ if (s->s3->tlsext_channel_id_valid) {
+ s->state = SSL3_ST_CW_CHANNEL_ID_A;
+ }
+ if (s->s3->next_proto_neg_seen) {
+ s->state = SSL3_ST_CW_NEXT_PROTO_A;
+ }
+ s->init_num = 0;
- s->session->cipher=s->s3->tmp.new_cipher;
- if (!s->enc_method->setup_key_block(s))
- {
- ret= -1;
- goto end;
- }
+ s->session->cipher = s->s3->tmp.new_cipher;
+ if (!s->enc_method->setup_key_block(s)) {
+ ret = -1;
+ goto end;
+ }
- if (!s->enc_method->change_cipher_state(s,
- SSL3_CHANGE_CIPHER_CLIENT_WRITE))
- {
- ret= -1;
- goto end;
- }
+ if (!s->enc_method->change_cipher_state(
+ s, SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
+ ret = -1;
+ goto end;
+ }
- break;
+ break;
- case SSL3_ST_CW_NEXT_PROTO_A:
- case SSL3_ST_CW_NEXT_PROTO_B:
- ret=ssl3_send_next_proto(s);
- if (ret <= 0) goto end;
- if (s->s3->tlsext_channel_id_valid)
- s->state=SSL3_ST_CW_CHANNEL_ID_A;
- else
- s->state=SSL3_ST_CW_FINISHED_A;
- break;
+ case SSL3_ST_CW_NEXT_PROTO_A:
+ case SSL3_ST_CW_NEXT_PROTO_B:
+ ret = ssl3_send_next_proto(s);
+ if (ret <= 0) {
+ goto end;
+ }
- case SSL3_ST_CW_CHANNEL_ID_A:
- case SSL3_ST_CW_CHANNEL_ID_B:
- ret=ssl3_send_channel_id(s);
- if (ret <= 0) goto end;
- s->state=SSL3_ST_CW_FINISHED_A;
- break;
+ if (s->s3->tlsext_channel_id_valid) {
+ s->state = SSL3_ST_CW_CHANNEL_ID_A;
+ } else {
+ s->state = SSL3_ST_CW_FINISHED_A;
+ }
+ break;
- case SSL3_ST_CW_FINISHED_A:
- case SSL3_ST_CW_FINISHED_B:
- ret=ssl3_send_finished(s,
- SSL3_ST_CW_FINISHED_A,SSL3_ST_CW_FINISHED_B,
- s->enc_method->client_finished_label,
- s->enc_method->client_finished_label_len);
- if (ret <= 0) goto end;
- s->state=SSL3_ST_CW_FLUSH;
+ case SSL3_ST_CW_CHANNEL_ID_A:
+ case SSL3_ST_CW_CHANNEL_ID_B:
+ ret = ssl3_send_channel_id(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->state = SSL3_ST_CW_FINISHED_A;
+ break;
- if (s->hit)
- {
- s->s3->tmp.next_state=SSL_ST_OK;
- }
- else
- {
- /* This is a non-resumption handshake. If it
- * involves ChannelID, then record the
- * handshake hashes at this point in the
- * session so that any resumption of this
- * session with ChannelID can sign those
- * hashes. */
- if (s->s3->tlsext_channel_id_new)
- {
- ret = tls1_record_handshake_hashes_for_channel_id(s);
- if (ret <= 0)
- goto end;
- }
- if ((SSL_get_mode(s) & SSL_MODE_HANDSHAKE_CUTTHROUGH)
- && ssl3_can_cutthrough(s)
- && s->s3->previous_server_finished_len == 0 /* no cutthrough on renegotiation (would complicate the state machine) */
- )
- {
- s->s3->tmp.next_state=SSL3_ST_CUTTHROUGH_COMPLETE;
- }
- else
- {
- /* Allow NewSessionTicket if ticket expected */
- if (s->tlsext_ticket_expected)
- s->s3->tmp.next_state=SSL3_ST_CR_SESSION_TICKET_A;
- else
- s->s3->tmp.next_state=SSL3_ST_CR_CHANGE;
- }
- }
- s->init_num=0;
- break;
+ case SSL3_ST_CW_FINISHED_A:
+ case SSL3_ST_CW_FINISHED_B:
+ ret =
+ ssl3_send_finished(s, SSL3_ST_CW_FINISHED_A, SSL3_ST_CW_FINISHED_B,
+ s->enc_method->client_finished_label,
+ s->enc_method->client_finished_label_len);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->state = SSL3_ST_CW_FLUSH;
- case SSL3_ST_CR_SESSION_TICKET_A:
- case SSL3_ST_CR_SESSION_TICKET_B:
- ret=ssl3_get_new_session_ticket(s);
- if (ret <= 0) goto end;
- s->state=SSL3_ST_CR_CHANGE;
- s->init_num=0;
- break;
+ if (s->hit) {
+ s->s3->tmp.next_state = SSL_ST_OK;
+ } else {
+ /* This is a non-resumption handshake. If it involves ChannelID, then
+ * record the handshake hashes at this point in the session so that
+ * any resumption of this session with ChannelID can sign those
+ * hashes. */
+ if (s->s3->tlsext_channel_id_new) {
+ ret = tls1_record_handshake_hashes_for_channel_id(s);
+ if (ret <= 0)
+ goto end;
+ }
+ if ((SSL_get_mode(s) & SSL_MODE_HANDSHAKE_CUTTHROUGH) &&
+ ssl3_can_cutthrough(s) &&
+ /* no cutthrough on renegotiation (would complicate the state
+ * machine) */
+ s->s3->previous_server_finished_len == 0) {
+ s->s3->tmp.next_state = SSL3_ST_CUTTHROUGH_COMPLETE;
+ } else {
+ /* Allow NewSessionTicket if ticket expected */
+ if (s->tlsext_ticket_expected) {
+ s->s3->tmp.next_state = SSL3_ST_CR_SESSION_TICKET_A;
+ } else {
+ s->s3->tmp.next_state = SSL3_ST_CR_CHANGE;
+ }
+ }
+ }
+ s->init_num = 0;
+ break;
- case SSL3_ST_CR_CERT_STATUS_A:
- case SSL3_ST_CR_CERT_STATUS_B:
- ret=ssl3_get_cert_status(s);
- if (ret <= 0) goto end;
- s->state=SSL3_ST_CR_KEY_EXCH_A;
- s->init_num=0;
- break;
+ case SSL3_ST_CR_SESSION_TICKET_A:
+ case SSL3_ST_CR_SESSION_TICKET_B:
+ ret = ssl3_get_new_session_ticket(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->state = SSL3_ST_CR_CHANGE;
+ s->init_num = 0;
+ break;
- case SSL3_ST_CR_CHANGE:
- /* At this point, the next message must be entirely
- * behind a ChangeCipherSpec. */
- if (!ssl3_expect_change_cipher_spec(s))
- {
- ret = -1;
- goto end;
- }
- s->state = SSL3_ST_CR_FINISHED_A;
- break;
+ case SSL3_ST_CR_CERT_STATUS_A:
+ case SSL3_ST_CR_CERT_STATUS_B:
+ ret = ssl3_get_cert_status(s);
+ if (ret <= 0) {
+ goto end;
+ }
+ s->state = SSL3_ST_CR_KEY_EXCH_A;
+ s->init_num = 0;
+ break;
- case SSL3_ST_CR_FINISHED_A:
- case SSL3_ST_CR_FINISHED_B:
- ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A,
- SSL3_ST_CR_FINISHED_B);
- if (ret <= 0) goto end;
+ case SSL3_ST_CR_CHANGE:
+ /* At this point, the next message must be entirely behind a
+ * ChangeCipherSpec. */
+ if (!ssl3_expect_change_cipher_spec(s)) {
+ ret = -1;
+ goto end;
+ }
+ s->state = SSL3_ST_CR_FINISHED_A;
+ break;
- if (s->hit)
- s->state=SSL3_ST_CW_CHANGE_A;
- else
- s->state=SSL_ST_OK;
- s->init_num=0;
- break;
+ case SSL3_ST_CR_FINISHED_A:
+ case SSL3_ST_CR_FINISHED_B:
+ ret =
+ ssl3_get_finished(s, SSL3_ST_CR_FINISHED_A, SSL3_ST_CR_FINISHED_B);
+ if (ret <= 0) {
+ goto end;
+ }
- case SSL3_ST_CW_FLUSH:
- s->rwstate=SSL_WRITING;
- if (BIO_flush(s->wbio) <= 0)
- {
- ret= -1;
- goto end;
- }
- s->rwstate=SSL_NOTHING;
- s->state=s->s3->tmp.next_state;
- break;
+ if (s->hit) {
+ s->state = SSL3_ST_CW_CHANGE_A;
+ } else {
+ s->state = SSL_ST_OK;
+ }
+ s->init_num = 0;
+ break;
- case SSL3_ST_CUTTHROUGH_COMPLETE:
- /* Allow NewSessionTicket if ticket expected */
- if (s->tlsext_ticket_expected)
- s->state=SSL3_ST_CR_SESSION_TICKET_A;
- else
- s->state=SSL3_ST_CR_CHANGE;
+ case SSL3_ST_CW_FLUSH:
+ s->rwstate = SSL_WRITING;
+ if (BIO_flush(s->wbio) <= 0) {
+ ret = -1;
+ goto end;
+ }
+ s->rwstate = SSL_NOTHING;
+ s->state = s->s3->tmp.next_state;
+ break;
- ssl_free_wbio_buffer(s);
- ret = 1;
- goto end;
- /* break; */
+ case SSL3_ST_CUTTHROUGH_COMPLETE:
+ /* Allow NewSessionTicket if ticket expected */
+ if (s->tlsext_ticket_expected) {
+ s->state = SSL3_ST_CR_SESSION_TICKET_A;
+ } else {
+ s->state = SSL3_ST_CR_CHANGE;
+ }
- case SSL_ST_OK:
- /* clean a few things up */
- ssl3_cleanup_key_block(s);
+ ssl_free_wbio_buffer(s);
+ ret = 1;
+ goto end;
- if (s->init_buf != NULL)
- {
- BUF_MEM_free(s->init_buf);
- s->init_buf=NULL;
- }
+ case SSL_ST_OK:
+ /* clean a few things up */
+ ssl3_cleanup_key_block(s);
- /* Remove write buffering now. */
- ssl_free_wbio_buffer(s);
+ if (s->init_buf != NULL) {
+ BUF_MEM_free(s->init_buf);
+ s->init_buf = NULL;
+ }
- s->init_num=0;
- s->renegotiate=0;
- s->new_session=0;
+ /* Remove write buffering now. */
+ ssl_free_wbio_buffer(s);
- ssl_update_cache(s,SSL_SESS_CACHE_CLIENT);
- if (s->hit) s->ctx->stats.sess_hit++;
+ s->init_num = 0;
+ s->renegotiate = 0;
+ s->new_session = 0;
- ret=1;
- /* s->server=0; */
- s->ctx->stats.sess_connect_good++;
+ ssl_update_cache(s, SSL_SESS_CACHE_CLIENT);
+ if (s->hit) {
+ s->ctx->stats.sess_hit++;
+ }
- if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);
+ ret = 1;
+ /* s->server=0; */
+ s->ctx->stats.sess_connect_good++;
- goto end;
- /* break; */
-
- default:
- OPENSSL_PUT_ERROR(SSL, ssl3_connect, SSL_R_UNKNOWN_STATE);
- ret= -1;
- goto end;
- /* break; */
- }
+ if (cb != NULL) {
+ cb(s, SSL_CB_HANDSHAKE_DONE, 1);
+ }
- /* did we do anything */
- if (!s->s3->tmp.reuse_message && !skip)
- {
- if ((cb != NULL) && (s->state != state))
- {
- new_state=s->state;
- s->state=state;
- cb(s,SSL_CB_CONNECT_LOOP,1);
- s->state=new_state;
- }
- }
- skip=0;
- }
+ goto end;
+
+ default:
+ OPENSSL_PUT_ERROR(SSL, ssl3_connect, SSL_R_UNKNOWN_STATE);
+ ret = -1;
+ goto end;
+ }
+
+ if (!s->s3->tmp.reuse_message && !skip) {
+ if (cb != NULL && s->state != state) {
+ new_state = s->state;
+ s->state = state;
+ cb(s, SSL_CB_CONNECT_LOOP, 1);
+ s->state = new_state;
+ }
+ }
+ skip = 0;
+ }
+
end:
- s->in_handshake--;
- if (buf != NULL)
- BUF_MEM_free(buf);
- if (cb != NULL)
- cb(s,SSL_CB_CONNECT_EXIT,ret);
- return(ret);
- }
+ s->in_handshake--;
+ if (buf != NULL) {
+ BUF_MEM_free(buf);
+ }
+ if (cb != NULL) {
+ cb(s, SSL_CB_CONNECT_EXIT, ret);
+ }
+ return ret;
+}
-int ssl3_send_client_hello(SSL *s)
- {
- unsigned char *buf;
- unsigned char *p,*d;
- int i;
- unsigned long l;
+int ssl3_send_client_hello(SSL *s) {
+ uint8_t *buf, *p, *d;
+ int i;
+ unsigned long l;
- buf=(unsigned char *)s->init_buf->data;
- if (s->state == SSL3_ST_CW_CLNT_HELLO_A)
- {
- if (!s->s3->have_version)
- {
- uint16_t max_version = ssl3_get_max_client_version(s);
- /* Disabling all versions is silly: return an error. */
- if (max_version == 0)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, SSL_R_WRONG_SSL_VERSION);
- goto err;
- }
- s->version = max_version;
- s->client_version = max_version;
- }
+ buf = (uint8_t *)s->init_buf->data;
+ if (s->state == SSL3_ST_CW_CLNT_HELLO_A) {
+ if (!s->s3->have_version) {
+ uint16_t max_version = ssl3_get_max_client_version(s);
+ /* Disabling all versions is silly: return an error. */
+ if (max_version == 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, SSL_R_WRONG_SSL_VERSION);
+ goto err;
+ }
+ s->version = max_version;
+ s->client_version = max_version;
+ }
- /* If the configured session was created at a version
- * higher than our maximum version, drop it. */
- if (s->session &&
- (s->session->session_id_length == 0 ||
- s->session->not_resumable ||
- (!SSL_IS_DTLS(s) && s->session->ssl_version > s->version) ||
- (SSL_IS_DTLS(s) && s->session->ssl_version < s->version)))
- {
- SSL_set_session(s, NULL);
- }
+ /* If the configured session was created at a version higher than our
+ * maximum version, drop it. */
+ if (s->session &&
+ (s->session->session_id_length == 0 || s->session->not_resumable ||
+ (!SSL_IS_DTLS(s) && s->session->ssl_version > s->version) ||
+ (SSL_IS_DTLS(s) && s->session->ssl_version < s->version))) {
+ SSL_set_session(s, NULL);
+ }
- /* else use the pre-loaded session */
+ /* else use the pre-loaded session */
+ p = s->s3->client_random;
- p=s->s3->client_random;
+ /* If resending the ClientHello in DTLS after a HelloVerifyRequest, don't
+ * renegerate the client_random. The random must be reused. */
+ if (!SSL_IS_DTLS(s) || !s->d1->send_cookie) {
+ ssl_fill_hello_random(s, 0, p, sizeof(s->s3->client_random));
+ }
- /* If resending the ClientHello in DTLS after a
- * HelloVerifyRequest, don't renegerate the client_random. The
- * random must be reused. */
- if (!SSL_IS_DTLS(s) || !s->d1->send_cookie)
- {
- ssl_fill_hello_random(s, 0, p,
- sizeof(s->s3->client_random));
- }
+ /* Do the message type and length last. Note: the final argument to
+ * ssl_add_clienthello_tlsext below depends on the size of this prefix. */
+ d = p = ssl_handshake_start(s);
- /* Do the message type and length last.
- * Note: the final argument to ssl_add_clienthello_tlsext below
- * depends on the size of this prefix. */
- d=p= ssl_handshake_start(s);
+ /* version indicates the negotiated version: for example from an SSLv2/v3
+ * compatible client hello). The client_version field is the maximum
+ * version we permit and it is also used in RSA encrypted premaster
+ * secrets. Some servers can choke if we initially report a higher version
+ * then renegotiate to a lower one in the premaster secret. This didn't
+ * happen with TLS 1.0 as most servers supported it but it can with TLS 1.1
+ * or later if the server only supports 1.0.
+ *
+ * Possible scenario with previous logic:
+ * 1. Client hello indicates TLS 1.2
+ * 2. Server hello says TLS 1.0
+ * 3. RSA encrypted premaster secret uses 1.2.
+ * 4. Handhaked proceeds using TLS 1.0.
+ * 5. Server sends hello request to renegotiate.
+ * 6. Client hello indicates TLS v1.0 as we now
+ * know that is maximum server supports.
+ * 7. Server chokes on RSA encrypted premaster secret
+ * containing version 1.0.
+ *
+ * For interoperability it should be OK to always use the maximum version
+ * we support in client hello and then rely on the checking of version to
+ * ensure the servers isn't being inconsistent: for example initially
+ * negotiating with TLS 1.0 and renegotiating with TLS 1.2. We do this by
+ * using client_version in client hello and not resetting it to the
+ * negotiated version. */
+ *(p++) = s->client_version >> 8;
+ *(p++) = s->client_version & 0xff;
- /* version indicates the negotiated version: for example from
- * an SSLv2/v3 compatible client hello). The client_version
- * field is the maximum version we permit and it is also
- * used in RSA encrypted premaster secrets. Some servers can
- * choke if we initially report a higher version then
- * renegotiate to a lower one in the premaster secret. This
- * didn't happen with TLS 1.0 as most servers supported it
- * but it can with TLS 1.1 or later if the server only supports
- * 1.0.
- *
- * Possible scenario with previous logic:
- * 1. Client hello indicates TLS 1.2
- * 2. Server hello says TLS 1.0
- * 3. RSA encrypted premaster secret uses 1.2.
- * 4. Handhaked proceeds using TLS 1.0.
- * 5. Server sends hello request to renegotiate.
- * 6. Client hello indicates TLS v1.0 as we now
- * know that is maximum server supports.
- * 7. Server chokes on RSA encrypted premaster secret
- * containing version 1.0.
- *
- * For interoperability it should be OK to always use the
- * maximum version we support in client hello and then rely
- * on the checking of version to ensure the servers isn't
- * being inconsistent: for example initially negotiating with
- * TLS 1.0 and renegotiating with TLS 1.2. We do this by using
- * client_version in client hello and not resetting it to
- * the negotiated version.
- */
- *(p++)=s->client_version>>8;
- *(p++)=s->client_version&0xff;
+ /* Random stuff */
+ memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE);
+ p += SSL3_RANDOM_SIZE;
- /* Random stuff */
- memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE);
- p+=SSL3_RANDOM_SIZE;
+ /* 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, ssl3_send_client_hello, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ memcpy(p, s->session->session_id, i);
+ p += i;
+ }
- /* 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, ssl3_send_client_hello, ERR_R_INTERNAL_ERROR);
- goto err;
- }
- memcpy(p,s->session->session_id,i);
- p+=i;
- }
-
- /* cookie stuff for DTLS */
- if (SSL_IS_DTLS(s))
- {
- if ( s->d1->cookie_len > sizeof(s->d1->cookie))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, ERR_R_INTERNAL_ERROR);
- goto err;
- }
- *(p++) = s->d1->cookie_len;
- memcpy(p, s->d1->cookie, s->d1->cookie_len);
- p += s->d1->cookie_len;
- }
-
- /* Ciphers supported */
- i = ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), &p[2]);
- if (i == 0)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, SSL_R_NO_CIPHERS_AVAILABLE);
- goto err;
- }
- s2n(i,p);
- p+=i;
+ /* cookie stuff for DTLS */
+ if (SSL_IS_DTLS(s)) {
+ if (s->d1->cookie_len > sizeof(s->d1->cookie)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ *(p++) = s->d1->cookie_len;
+ memcpy(p, s->d1->cookie, s->d1->cookie_len);
+ p += s->d1->cookie_len;
+ }
- /* COMPRESSION */
- *(p++)=1;
- *(p++)=0; /* Add the NULL method */
+ /* Ciphers supported */
+ i = ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), &p[2]);
+ if (i == 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello,
+ SSL_R_NO_CIPHERS_AVAILABLE);
+ goto err;
+ }
+ s2n(i, p);
+ p += i;
- /* TLS extensions*/
- if (ssl_prepare_clienthello_tlsext(s) <= 0)
- {
- 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_send_client_hello, ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- l= p-d;
- ssl_set_handshake_header(s, SSL3_MT_CLIENT_HELLO, l);
- s->state=SSL3_ST_CW_CLNT_HELLO_B;
- }
+ /* COMPRESSION */
+ *(p++) = 1;
+ *(p++) = 0; /* Add the NULL method */
- /* SSL3_ST_CW_CLNT_HELLO_B */
- return ssl_do_write(s);
+ /* TLS extensions*/
+ if (ssl_prepare_clienthello_tlsext(s) <= 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, SSL_R_CLIENTHELLO_TLSEXT);
+ goto err;
+ }
+
+ p = ssl_add_clienthello_tlsext(s, p, buf + SSL3_RT_MAX_PLAIN_LENGTH,
+ p - buf);
+ if (p == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_hello, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ l = p - d;
+ ssl_set_handshake_header(s, SSL3_MT_CLIENT_HELLO, l);
+ s->state = SSL3_ST_CW_CLNT_HELLO_B;
+ }
+
+ /* SSL3_ST_CW_CLNT_HELLO_B */
+ return ssl_do_write(s);
+
err:
- return(-1);
- }
+ return -1;
+}
-int ssl3_get_server_hello(SSL *s)
- {
- STACK_OF(SSL_CIPHER) *sk;
- const SSL_CIPHER *c;
- CERT *ct = s->cert;
- int al=SSL_AD_INTERNAL_ERROR,ok;
- long n;
- CBS server_hello, server_random, session_id;
- uint16_t server_version, cipher_suite;
- uint8_t compression_method;
- unsigned long mask_ssl;
+int ssl3_get_server_hello(SSL *s) {
+ STACK_OF(SSL_CIPHER) * sk;
+ const SSL_CIPHER *c;
+ CERT *ct = s->cert;
+ int al = SSL_AD_INTERNAL_ERROR, ok;
+ long n;
+ 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);
+ 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);
+ if (!ok) {
+ return n;
+ }
- CBS_init(&server_hello, s->init_msg, n);
+ CBS_init(&server_hello, s->init_msg, n);
- if (!CBS_get_u16(&server_hello, &server_version) ||
- !CBS_get_bytes(&server_hello, &server_random, SSL3_RANDOM_SIZE) ||
- !CBS_get_u8_length_prefixed(&server_hello, &session_id) ||
- CBS_len(&session_id) > SSL3_SESSION_ID_SIZE ||
- !CBS_get_u16(&server_hello, &cipher_suite) ||
- !CBS_get_u8(&server_hello, &compression_method))
- {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_DECODE_ERROR);
- goto f_err;
- }
+ if (!CBS_get_u16(&server_hello, &server_version) ||
+ !CBS_get_bytes(&server_hello, &server_random, SSL3_RANDOM_SIZE) ||
+ !CBS_get_u8_length_prefixed(&server_hello, &session_id) ||
+ CBS_len(&session_id) > SSL3_SESSION_ID_SIZE ||
+ !CBS_get_u16(&server_hello, &cipher_suite) ||
+ !CBS_get_u8(&server_hello, &compression_method)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
- if (!s->s3->have_version)
- {
- if (!ssl3_is_version_enabled(s, server_version))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_UNSUPPORTED_PROTOCOL);
- s->version = server_version;
- /* Mark the version as fixed so the record-layer version
- * is not clamped to TLS 1.0. */
- s->s3->have_version = 1;
- al = SSL_AD_PROTOCOL_VERSION;
- goto f_err;
- }
- s->version = server_version;
- s->enc_method = ssl3_get_enc_method(server_version);
- assert(s->enc_method != NULL);
- /* At this point, the connection's version is known and
- * s->version is fixed. Begin enforcing the record-layer
- * version. */
- s->s3->have_version = 1;
- }
- else if (server_version != s->version)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_WRONG_SSL_VERSION);
- al = SSL_AD_PROTOCOL_VERSION;
- goto f_err;
- }
+ if (!s->s3->have_version) {
+ if (!ssl3_is_version_enabled(s, server_version)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_UNSUPPORTED_PROTOCOL);
+ s->version = server_version;
+ /* Mark the version as fixed so the record-layer version is not clamped
+ * to TLS 1.0. */
+ s->s3->have_version = 1;
+ al = SSL_AD_PROTOCOL_VERSION;
+ goto f_err;
+ }
+ s->version = server_version;
+ s->enc_method = ssl3_get_enc_method(server_version);
+ assert(s->enc_method != NULL);
+ /* At this point, the connection's version is known and s->version is
+ * fixed. Begin enforcing the record-layer version. */
+ s->s3->have_version = 1;
+ } else if (server_version != s->version) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_WRONG_SSL_VERSION);
+ al = SSL_AD_PROTOCOL_VERSION;
+ goto f_err;
+ }
- /* Copy over the server random. */
- memcpy(s->s3->server_random, CBS_data(&server_random), SSL3_RANDOM_SIZE);
+ /* Copy over the server random. */
+ memcpy(s->s3->server_random, CBS_data(&server_random), SSL3_RANDOM_SIZE);
- assert(s->session == NULL || s->session->session_id_length > 0);
- if (s->session != NULL &&
- CBS_mem_equal(&session_id,
- s->session->session_id, s->session->session_id_length))
- {
- if(s->sid_ctx_length != s->session->sid_ctx_length
- || memcmp(s->session->sid_ctx, s->sid_ctx, s->sid_ctx_length))
- {
- /* actually a client application bug */
- al = SSL_AD_ILLEGAL_PARAMETER;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
- goto f_err;
- }
- s->hit = 1;
- }
- else
- {
- /* The session wasn't resumed. Create a fresh SSL_SESSION to
- * fill out. */
- s->hit = 0;
- if (!ssl_get_new_session(s, 0))
- {
- goto f_err;
- }
- /* Note: session_id could be empty. */
- s->session->session_id_length = CBS_len(&session_id);
- memcpy(s->session->session_id, CBS_data(&session_id), CBS_len(&session_id));
- }
+ assert(s->session == NULL || s->session->session_id_length > 0);
+ if (s->session != NULL && CBS_mem_equal(&session_id, s->session->session_id,
+ s->session->session_id_length)) {
+ if (s->sid_ctx_length != s->session->sid_ctx_length ||
+ memcmp(s->session->sid_ctx, s->sid_ctx, s->sid_ctx_length)) {
+ /* actually a client application bug */
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello,
+ SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
+ goto f_err;
+ }
+ s->hit = 1;
+ } else {
+ /* The session wasn't resumed. Create a fresh SSL_SESSION to
+ * fill out. */
+ s->hit = 0;
+ if (!ssl_get_new_session(s, 0)) {
+ goto f_err;
+ }
+ /* Note: session_id could be empty. */
+ s->session->session_id_length = CBS_len(&session_id);
+ memcpy(s->session->session_id, CBS_data(&session_id), CBS_len(&session_id));
+ }
- c = ssl3_get_cipher_by_value(cipher_suite);
- if (c == NULL)
- {
- /* unknown cipher */
- al = SSL_AD_ILLEGAL_PARAMETER;
- 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 & mask_ssl ||
- c->algorithm_mkey & ct->mask_k ||
- c->algorithm_auth & ct->mask_a)
- {
- al=SSL_AD_ILLEGAL_PARAMETER;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_WRONG_CIPHER_RETURNED);
- goto f_err;
- }
+ c = ssl3_get_cipher_by_value(cipher_suite);
+ if (c == NULL) {
+ /* unknown cipher */
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ 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 the cipher is disabled then we didn't sent it in the ClientHello, so if
+ * the server selected it, it's an error. */
+ if ((c->algorithm_ssl & mask_ssl) ||
+ (c->algorithm_mkey & ct->mask_k) ||
+ (c->algorithm_auth & ct->mask_a)) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_WRONG_CIPHER_RETURNED);
+ goto f_err;
+ }
- sk=ssl_get_ciphers_by_id(s);
- if (!sk_SSL_CIPHER_find(sk, NULL, c))
- {
- /* we did not say we would use this cipher */
- al=SSL_AD_ILLEGAL_PARAMETER;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_WRONG_CIPHER_RETURNED);
- goto f_err;
- }
+ sk = ssl_get_ciphers_by_id(s);
+ if (!sk_SSL_CIPHER_find(sk, NULL, c)) {
+ /* we did not say we would use this cipher */
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_WRONG_CIPHER_RETURNED);
+ goto f_err;
+ }
- /* Depending on the session caching (internal/external), the cipher
- and/or cipher_id values may not be set. Make sure that
- cipher_id is set and use it for comparison. */
- if (s->session->cipher)
- s->session->cipher_id = s->session->cipher->id;
- if (s->hit && (s->session->cipher_id != c->id))
- {
- al = SSL_AD_ILLEGAL_PARAMETER;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
- goto f_err;
- }
- s->s3->tmp.new_cipher=c;
+ /* Depending on the session caching (internal/external), the cipher
+ and/or cipher_id values may not be set. Make sure that cipher_id is set
+ and use it for comparison. */
+ if (s->session->cipher) {
+ s->session->cipher_id = s->session->cipher->id;
+ }
+ if (s->hit && s->session->cipher_id != c->id) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello,
+ SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
+ goto f_err;
+ }
+ s->s3->tmp.new_cipher = c;
- /* Most clients also require that the negotiated version match the
- * session's version if resuming. However OpenSSL has historically not
- * had the corresponding logic on the server, so this may not be
- * compatible, depending on other factors. (Whether the ClientHello
- * version is clamped to the session's version and whether the session
- * cache is keyed on IP address.)
- *
- * TODO(davidben): See if we can still enforce this? Perhaps for the
- * future TLS 1.3 and forward if this is fixed upstream. */
+ /* Most clients also require that the negotiated version match the session's
+ * version if resuming. However OpenSSL has historically not had the
+ * corresponding logic on the server, so this may not be compatible,
+ * depending on other factors. (Whether the ClientHello version is clamped to
+ * the session's version and whether the session cache is keyed on IP
+ * address.)
+ *
+ * TODO(davidben): See if we can still enforce this? Perhaps for the future
+ * TLS 1.3 and forward if this is fixed upstream. */
- /* Don't digest cached records if no sigalgs: we may need them for
- * client authentication.
- */
- if (!SSL_USE_SIGALGS(s) && !ssl3_digest_cached_records(s, free_handshake_buffer))
- goto f_err;
+ /* Don't digest cached records if no sigalgs: we may need them for client
+ * authentication. */
+ if (!SSL_USE_SIGALGS(s) &&
+ !ssl3_digest_cached_records(s, free_handshake_buffer)) {
+ goto f_err;
+ }
- /* Only the NULL compression algorithm is supported. */
- if (compression_method != 0)
- {
- al = SSL_AD_ILLEGAL_PARAMETER;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
- goto f_err;
- }
+ /* Only the NULL compression algorithm is supported. */
+ if (compression_method != 0) {
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello,
+ SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
+ goto f_err;
+ }
- /* TLS extensions */
- if (!ssl_parse_serverhello_tlsext(s, &server_hello))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_PARSE_TLSEXT);
- goto err;
- }
+ /* TLS extensions */
+ if (!ssl_parse_serverhello_tlsext(s, &server_hello)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_PARSE_TLSEXT);
+ goto err;
+ }
- /* There should be nothing left over in the record. */
- if (CBS_len(&server_hello) != 0)
- {
- /* wrong packet length */
- al=SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_BAD_PACKET_LENGTH);
- goto f_err;
- }
+ /* There should be nothing left over in the record. */
+ if (CBS_len(&server_hello) != 0) {
+ /* wrong packet length */
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_hello, SSL_R_BAD_PACKET_LENGTH);
+ goto f_err;
+ }
- return(1);
+ return 1;
+
f_err:
- ssl3_send_alert(s,SSL3_AL_FATAL,al);
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
err:
- return(-1);
- }
+ return -1;
+}
-int ssl3_get_server_certificate(SSL *s)
- {
- int al,i,ok,ret= -1;
- unsigned long n;
- X509 *x=NULL;
- STACK_OF(X509) *sk=NULL;
- SESS_CERT *sc;
- EVP_PKEY *pkey=NULL;
- CBS cbs, certificate_list;
- const uint8_t* data;
+int ssl3_get_server_certificate(SSL *s) {
+ int al, i, ok, ret = -1;
+ unsigned long n;
+ X509 *x = NULL;
+ STACK_OF(X509) *sk = NULL;
+ SESS_CERT *sc;
+ EVP_PKEY *pkey = NULL;
+ CBS cbs, certificate_list;
+ const uint8_t *data;
- n=s->method->ssl_get_message(s,
- SSL3_ST_CR_CERT_A,
- SSL3_ST_CR_CERT_B,
- SSL3_MT_CERTIFICATE,
- s->max_cert_list,
- SSL_GET_MESSAGE_HASH_MESSAGE,
- &ok);
+ n = s->method->ssl_get_message(s, SSL3_ST_CR_CERT_A, SSL3_ST_CR_CERT_B,
+ SSL3_MT_CERTIFICATE, s->max_cert_list,
+ SSL_GET_MESSAGE_HASH_MESSAGE, &ok);
- if (!ok) return((int)n);
+ if (!ok) {
+ return n;
+ }
- CBS_init(&cbs, s->init_msg, n);
+ CBS_init(&cbs, s->init_msg, n);
- if ((sk=sk_X509_new_null()) == NULL)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, ERR_R_MALLOC_FAILURE);
- goto err;
- }
+ sk = sk_X509_new_null();
+ if (sk == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
- if (!CBS_get_u24_length_prefixed(&cbs, &certificate_list) ||
- CBS_len(&cbs) != 0)
- {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, SSL_R_LENGTH_MISMATCH);
- goto f_err;
- }
+ if (!CBS_get_u24_length_prefixed(&cbs, &certificate_list) ||
+ CBS_len(&cbs) != 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, SSL_R_LENGTH_MISMATCH);
+ goto f_err;
+ }
- while (CBS_len(&certificate_list) > 0)
- {
- CBS certificate;
- if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate))
- {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, SSL_R_CERT_LENGTH_MISMATCH);
- goto f_err;
- }
- data = CBS_data(&certificate);
- x = d2i_X509(NULL, &data, CBS_len(&certificate));
- if (x == NULL)
- {
- al = SSL_AD_BAD_CERTIFICATE;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, ERR_R_ASN1_LIB);
- goto f_err;
- }
- if (data != CBS_data(&certificate) + CBS_len(&certificate))
- {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, SSL_R_CERT_LENGTH_MISMATCH);
- goto f_err;
- }
- if (!sk_X509_push(sk, x))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- x=NULL;
- }
+ while (CBS_len(&certificate_list) > 0) {
+ CBS certificate;
+ if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate,
+ SSL_R_CERT_LENGTH_MISMATCH);
+ goto f_err;
+ }
+ data = CBS_data(&certificate);
+ x = d2i_X509(NULL, &data, CBS_len(&certificate));
+ if (x == NULL) {
+ al = SSL_AD_BAD_CERTIFICATE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, ERR_R_ASN1_LIB);
+ goto f_err;
+ }
+ if (data != CBS_data(&certificate) + CBS_len(&certificate)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate,
+ SSL_R_CERT_LENGTH_MISMATCH);
+ goto f_err;
+ }
+ if (!sk_X509_push(sk, x)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ x = NULL;
+ }
- i=ssl_verify_cert_chain(s,sk);
- if ((s->verify_mode != SSL_VERIFY_NONE) && (i <= 0)
- )
- {
- al=ssl_verify_alarm_type(s->verify_result);
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, SSL_R_CERTIFICATE_VERIFY_FAILED);
- goto f_err;
- }
- ERR_clear_error(); /* but we keep s->verify_result */
+ i = ssl_verify_cert_chain(s, sk);
+ if (s->verify_mode != SSL_VERIFY_NONE && i <= 0) {
+ al = ssl_verify_alarm_type(s->verify_result);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate,
+ SSL_R_CERTIFICATE_VERIFY_FAILED);
+ goto f_err;
+ }
+ ERR_clear_error(); /* but we keep s->verify_result */
- sc=ssl_sess_cert_new();
- if (sc == NULL) goto err;
+ sc = ssl_sess_cert_new();
+ if (sc == NULL) {
+ goto err;
+ }
- if (s->session->sess_cert) ssl_sess_cert_free(s->session->sess_cert);
- s->session->sess_cert=sc;
+ if (s->session->sess_cert) {
+ ssl_sess_cert_free(s->session->sess_cert);
+ }
+ s->session->sess_cert = sc;
- sc->cert_chain=sk;
- /* Inconsistency alert: cert_chain does include the peer's
- * certificate, which we don't include in s3_srvr.c */
- x=sk_X509_value(sk,0);
- sk=NULL;
- /* VRS 19990621: possible memory leak; sk=null ==> !sk_pop_free() @end*/
+ sc->cert_chain = sk;
+ /* Inconsistency alert: cert_chain does include the peer's certificate, which
+ * we don't include in s3_srvr.c */
+ x = sk_X509_value(sk, 0);
+ sk = NULL;
+ /* VRS 19990621: possible memory leak; sk=null ==> !sk_pop_free() @end*/
- pkey=X509_get_pubkey(x);
+ pkey = X509_get_pubkey(x);
- if ((pkey == NULL) || EVP_PKEY_missing_parameters(pkey))
- {
- x=NULL;
- al=SSL3_AL_FATAL;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS);
- goto f_err;
- }
+ if (pkey == NULL || EVP_PKEY_missing_parameters(pkey)) {
+ x = NULL;
+ al = SSL3_AL_FATAL;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate,
+ SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS);
+ goto f_err;
+ }
- i = ssl_cert_type(pkey);
- if (i < 0)
- {
- x=NULL;
- al=SSL3_AL_FATAL;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
- goto f_err;
- }
+ i = ssl_cert_type(pkey);
+ if (i < 0) {
+ x = NULL;
+ al = SSL3_AL_FATAL;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate,
+ SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+ goto f_err;
+ }
- int exp_idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher);
- if (exp_idx >= 0 && i != exp_idx)
- {
- x=NULL;
- al=SSL_AD_ILLEGAL_PARAMETER;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, SSL_R_WRONG_CERTIFICATE_TYPE);
- goto f_err;
- }
- sc->peer_cert_type=i;
- /* Why would the following ever happen?
- * We just created sc a couple of lines ago. */
- if (sc->peer_pkeys[i].x509 != NULL)
- X509_free(sc->peer_pkeys[i].x509);
- sc->peer_pkeys[i].x509 = X509_up_ref(x);
- sc->peer_key = &(sc->peer_pkeys[i]);
+ int exp_idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher);
+ if (exp_idx >= 0 && i != exp_idx) {
+ x = NULL;
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate,
+ SSL_R_WRONG_CERTIFICATE_TYPE);
+ goto f_err;
+ }
+ sc->peer_cert_type = i;
+ /* Why would the following ever happen? We just created sc a couple of lines
+ * ago. */
+ if (sc->peer_pkeys[i].x509 != NULL) {
+ X509_free(sc->peer_pkeys[i].x509);
+ }
+ sc->peer_pkeys[i].x509 = X509_up_ref(x);
+ sc->peer_key = &(sc->peer_pkeys[i]);
- if (s->session->peer != NULL)
- X509_free(s->session->peer);
- s->session->peer = X509_up_ref(x);
+ if (s->session->peer != NULL) {
+ X509_free(s->session->peer);
+ }
+ s->session->peer = X509_up_ref(x);
- s->session->verify_result = s->verify_result;
+ s->session->verify_result = s->verify_result;
- x=NULL;
- ret=1;
- if (0)
- {
+ x = NULL;
+ ret = 1;
+
+ if (0) {
+ f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ }
+
+err:
+ EVP_PKEY_free(pkey);
+ X509_free(x);
+ sk_X509_pop_free(sk, X509_free);
+ return ret;
+}
+
+int ssl3_get_server_key_exchange(SSL *s) {
+ EVP_MD_CTX md_ctx;
+ int al, ok;
+ long n, alg_k, alg_a;
+ EVP_PKEY *pkey = NULL;
+ const EVP_MD *md = NULL;
+ RSA *rsa = NULL;
+ DH *dh = NULL;
+ EC_KEY *ecdh = NULL;
+ BN_CTX *bn_ctx = NULL;
+ EC_POINT *srvr_ecpoint = NULL;
+ CBS server_key_exchange, server_key_exchange_orig, parameter;
+
+ /* use same message size as in ssl3_get_certificate_request() as
+ * ServerKeyExchange message may be skipped */
+ n = s->method->ssl_get_message(s, SSL3_ST_CR_KEY_EXCH_A,
+ SSL3_ST_CR_KEY_EXCH_B, -1, s->max_cert_list,
+ SSL_GET_MESSAGE_HASH_MESSAGE, &ok);
+ if (!ok) {
+ return n;
+ }
+
+ if (s->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE) {
+ if (ssl_cipher_requires_server_key_exchange(s->s3->tmp.new_cipher)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange,
+ SSL_R_UNEXPECTED_MESSAGE);
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+ return -1;
+ }
+
+ /* In plain PSK ciphersuite, ServerKeyExchange can be
+ omitted if no identity hint is sent. Set session->sess_cert anyway to
+ avoid problems later.*/
+ if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aPSK) {
+ /* PSK ciphersuites that also send a Certificate would have already
+ * initialized |sess_cert|. */
+ if (s->session->sess_cert == NULL) {
+ s->session->sess_cert = ssl_sess_cert_new();
+ }
+
+ /* TODO(davidben): This should be reset in one place with the rest of the
+ * handshake state. */
+ if (s->s3->tmp.peer_psk_identity_hint) {
+ OPENSSL_free(s->s3->tmp.peer_psk_identity_hint);
+ s->s3->tmp.peer_psk_identity_hint = NULL;
+ }
+ }
+ s->s3->tmp.reuse_message = 1;
+ return 1;
+ }
+
+ /* Retain a copy of the original CBS to compute the signature over. */
+ CBS_init(&server_key_exchange, s->init_msg, n);
+ server_key_exchange_orig = server_key_exchange;
+
+ if (s->session->sess_cert != NULL) {
+ 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;
+ }
+ 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;
+ }
+ } else {
+ s->session->sess_cert = ssl_sess_cert_new();
+ }
+
+ alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+ alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+ EVP_MD_CTX_init(&md_ctx);
+
+ if (alg_a & SSL_aPSK) {
+ CBS psk_identity_hint;
+
+ /* Each of the PSK key exchanges begins with a psk_identity_hint. */
+ if (!CBS_get_u16_length_prefixed(&server_key_exchange,
+ &psk_identity_hint)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ /* Store PSK identity hint for later use, hint is used in
+ * ssl3_send_client_key_exchange. Assume that the maximum length of a PSK
+ * identity hint can be as long as the maximum length of a PSK identity.
+ * Also do not allow NULL characters; identities are saved as C strings.
+ *
+ * TODO(davidben): Should invalid hints be ignored? It's a hint rather than
+ * a specific identity. */
+ if (CBS_len(&psk_identity_hint) > PSK_MAX_IDENTITY_LEN ||
+ CBS_contains_zero_byte(&psk_identity_hint)) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange,
+ SSL_R_DATA_LENGTH_TOO_LONG);
+ goto f_err;
+ }
+
+ /* Save the identity hint as a C string. */
+ if (!CBS_strdup(&psk_identity_hint, &s->s3->tmp.peer_psk_identity_hint)) {
+ al = SSL_AD_INTERNAL_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto f_err;
+ }
+ }
+
+ if (alg_k & SSL_kEDH) {
+ CBS dh_p, dh_g, dh_Ys;
+
+ if (!CBS_get_u16_length_prefixed(&server_key_exchange, &dh_p) ||
+ CBS_len(&dh_p) == 0 ||
+ !CBS_get_u16_length_prefixed(&server_key_exchange, &dh_g) ||
+ CBS_len(&dh_g) == 0 ||
+ !CBS_get_u16_length_prefixed(&server_key_exchange, &dh_Ys) ||
+ CBS_len(&dh_Ys) == 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ dh = DH_new();
+ if (dh == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, ERR_R_DH_LIB);
+ goto err;
+ }
+
+ if ((dh->p = BN_bin2bn(CBS_data(&dh_p), CBS_len(&dh_p), NULL)) == NULL ||
+ (dh->g = BN_bin2bn(CBS_data(&dh_g), CBS_len(&dh_g), NULL)) == NULL ||
+ (dh->pub_key = BN_bin2bn(CBS_data(&dh_Ys), CBS_len(&dh_Ys), NULL)) ==
+ NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, ERR_R_BN_LIB);
+ goto err;
+ }
+
+ if (DH_size(dh) < 512 / 8) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange,
+ SSL_R_BAD_DH_P_LENGTH);
+ goto err;
+ }
+
+ if (alg_a & SSL_aRSA) {
+ pkey = X509_get_pubkey(
+ s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
+ }
+ /* else anonymous DH, so no certificate or pkey. */
+
+ s->session->sess_cert->peer_dh_tmp = dh;
+ dh = NULL;
+ } else if (alg_k & SSL_kEECDH) {
+ uint16_t curve_id;
+ int curve_nid = 0;
+ EC_GROUP *ngroup;
+ const EC_GROUP *group;
+ CBS point;
+
+ /* Extract elliptic curve parameters and the server's ephemeral ECDH public
+ * key. Check curve is one of our preferences, if not server has sent an
+ * invalid curve. */
+ if (!tls1_check_curve(s, &server_key_exchange, &curve_id)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_WRONG_CURVE);
+ goto f_err;
+ }
+
+ curve_nid = tls1_ec_curve_id2nid(curve_id);
+ if (curve_nid == 0) {
+ al = SSL_AD_INTERNAL_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange,
+ SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
+ goto f_err;
+ }
+
+ ecdh = EC_KEY_new();
+ if (ecdh == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ ngroup = EC_GROUP_new_by_curve_name(curve_nid);
+ if (ngroup == NULL ||
+ EC_KEY_set_group(ecdh, ngroup) == 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, ERR_R_EC_LIB);
+ goto err;
+ }
+ EC_GROUP_free(ngroup);
+
+ group = EC_KEY_get0_group(ecdh);
+
+ /* Next, get the encoded ECPoint */
+ if (!CBS_get_u8_length_prefixed(&server_key_exchange, &point)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ if (((srvr_ecpoint = EC_POINT_new(group)) == NULL) ||
+ ((bn_ctx = BN_CTX_new()) == NULL)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!EC_POINT_oct2point(group, srvr_ecpoint, CBS_data(&point),
+ CBS_len(&point), bn_ctx)) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_BAD_ECPOINT);
+ goto f_err;
+ }
+
+ /* The ECC/TLS specification does not mention the use of DSA to sign
+ * ECParameters in the server key exchange message. We do support RSA and
+ * ECDSA. */
+ if (alg_a & SSL_aRSA) {
+ pkey = X509_get_pubkey(
+ s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
+ } else if (alg_a & SSL_aECDSA) {
+ pkey =
+ X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_ECC].x509);
+ }
+ /* else anonymous ECDH, so no certificate or pkey. */
+ EC_KEY_set_public_key(ecdh, srvr_ecpoint);
+ s->session->sess_cert->peer_ecdh_tmp = ecdh;
+ ecdh = NULL;
+ BN_CTX_free(bn_ctx);
+ bn_ctx = NULL;
+ EC_POINT_free(srvr_ecpoint);
+ srvr_ecpoint = NULL;
+ } else if (!(alg_k & SSL_kPSK)) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange,
+ SSL_R_UNEXPECTED_MESSAGE);
+ goto f_err;
+ }
+
+ /* At this point, |server_key_exchange| contains the signature, if any, while
+ * |server_key_exchange_orig| contains the entire message. From that, derive
+ * a CBS containing just the parameter. */
+ CBS_init(¶meter, CBS_data(&server_key_exchange_orig),
+ CBS_len(&server_key_exchange_orig) - CBS_len(&server_key_exchange));
+
+ /* if it was signed, check the signature */
+ if (pkey != NULL) {
+ CBS signature;
+
+ if (SSL_USE_SIGALGS(s)) {
+ if (!tls12_check_peer_sigalg(&md, &al, s, &server_key_exchange, pkey)) {
+ goto f_err;
+ }
+ } else if (pkey->type == EVP_PKEY_RSA) {
+ md = EVP_md5_sha1();
+ } else {
+ md = EVP_sha1();
+ }
+
+ /* The last field in |server_key_exchange| is the signature. */
+ if (!CBS_get_u16_length_prefixed(&server_key_exchange, &signature) ||
+ CBS_len(&server_key_exchange) != 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
+
+ if (!EVP_DigestVerifyInit(&md_ctx, NULL, md, NULL, pkey) ||
+ !EVP_DigestVerifyUpdate(&md_ctx, s->s3->client_random,
+ SSL3_RANDOM_SIZE) ||
+ !EVP_DigestVerifyUpdate(&md_ctx, s->s3->server_random,
+ SSL3_RANDOM_SIZE) ||
+ !EVP_DigestVerifyUpdate(&md_ctx, CBS_data(¶meter),
+ CBS_len(¶meter)) ||
+ !EVP_DigestVerifyFinal(&md_ctx, CBS_data(&signature),
+ CBS_len(&signature))) {
+ /* bad signature */
+ al = SSL_AD_DECRYPT_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_BAD_SIGNATURE);
+ goto f_err;
+ }
+ } else {
+ if (ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) {
+ /* Might be wrong key type, check it */
+ if (ssl3_check_cert_and_algorithm(s)) {
+ /* Otherwise this shouldn't happen */
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange,
+ ERR_R_INTERNAL_ERROR);
+ }
+ goto err;
+ }
+ /* still data left over */
+ if (CBS_len(&server_key_exchange) > 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange,
+ SSL_R_EXTRA_DATA_IN_MESSAGE);
+ goto f_err;
+ }
+ }
+ EVP_PKEY_free(pkey);
+ EVP_MD_CTX_cleanup(&md_ctx);
+ return 1;
+
f_err:
- ssl3_send_alert(s,SSL3_AL_FATAL,al);
- }
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
err:
- EVP_PKEY_free(pkey);
- X509_free(x);
- sk_X509_pop_free(sk,X509_free);
- return(ret);
- }
+ EVP_PKEY_free(pkey);
+ if (rsa != NULL) {
+ RSA_free(rsa);
+ }
+ if (dh != NULL) {
+ DH_free(dh);
+ }
+ BN_CTX_free(bn_ctx);
+ EC_POINT_free(srvr_ecpoint);
+ if (ecdh != NULL) {
+ EC_KEY_free(ecdh);
+ }
+ EVP_MD_CTX_cleanup(&md_ctx);
+ return -1;
+}
-int ssl3_get_server_key_exchange(SSL *s)
- {
- EVP_MD_CTX md_ctx;
- int al,ok;
- long n,alg_k,alg_a;
- EVP_PKEY *pkey=NULL;
- const EVP_MD *md = NULL;
- RSA *rsa=NULL;
- DH *dh=NULL;
- EC_KEY *ecdh = NULL;
- BN_CTX *bn_ctx = NULL;
- EC_POINT *srvr_ecpoint = NULL;
- CBS server_key_exchange, server_key_exchange_orig, parameter;
+static int ca_dn_cmp(const X509_NAME **a, const X509_NAME **b) {
+ return X509_NAME_cmp(*a, *b);
+}
- /* use same message size as in ssl3_get_certificate_request()
- * as ServerKeyExchange message may be skipped */
- n=s->method->ssl_get_message(s,
- SSL3_ST_CR_KEY_EXCH_A,
- SSL3_ST_CR_KEY_EXCH_B,
- -1,
- s->max_cert_list,
- SSL_GET_MESSAGE_HASH_MESSAGE,
- &ok);
- if (!ok) return((int)n);
+int ssl3_get_certificate_request(SSL *s) {
+ int ok, ret = 0;
+ unsigned long n;
+ X509_NAME *xn = NULL;
+ STACK_OF(X509_NAME) *ca_sk = NULL;
+ CBS cbs;
+ CBS certificate_types;
+ CBS certificate_authorities;
+ const uint8_t *data;
- if (s->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE)
- {
- if (ssl_cipher_requires_server_key_exchange(s->s3->tmp.new_cipher))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_UNEXPECTED_MESSAGE);
- ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
- return -1;
- }
+ n = s->method->ssl_get_message(s, SSL3_ST_CR_CERT_REQ_A,
+ SSL3_ST_CR_CERT_REQ_B, -1, s->max_cert_list,
+ SSL_GET_MESSAGE_HASH_MESSAGE, &ok);
- /* In plain PSK ciphersuite, ServerKeyExchange can be
- omitted if no identity hint is sent. Set
- session->sess_cert anyway to avoid problems
- later.*/
- if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aPSK)
- {
- /* PSK ciphersuites that also send a
- * Certificate would have already initialized
- * |sess_cert|. */
- if (s->session->sess_cert == NULL)
- s->session->sess_cert = ssl_sess_cert_new();
+ if (!ok) {
+ return n;
+ }
- /* TODO(davidben): This should be reset in one place
- * with the rest of the handshake state. */
- if (s->s3->tmp.peer_psk_identity_hint)
- {
- OPENSSL_free(s->s3->tmp.peer_psk_identity_hint);
- s->s3->tmp.peer_psk_identity_hint = NULL;
- }
- }
- s->s3->tmp.reuse_message=1;
- return(1);
- }
+ s->s3->tmp.cert_req = 0;
- /* Retain a copy of the original CBS to compute the signature
- * over. */
- CBS_init(&server_key_exchange, s->init_msg, n);
- server_key_exchange_orig = server_key_exchange;
+ if (s->s3->tmp.message_type == SSL3_MT_SERVER_DONE) {
+ s->s3->tmp.reuse_message = 1;
+ /* If we get here we don't need any cached handshake records as we wont be
+ * doing client auth. */
+ if (s->s3->handshake_buffer &&
+ !ssl3_digest_cached_records(s, free_handshake_buffer)) {
+ goto err;
+ }
+ return 1;
+ }
- if (s->session->sess_cert != NULL)
- {
- 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;
- }
- 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;
- }
- }
- else
- {
- s->session->sess_cert=ssl_sess_cert_new();
- }
+ if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE_REQUEST) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request,
+ SSL_R_WRONG_MESSAGE_TYPE);
+ goto err;
+ }
- alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
- alg_a=s->s3->tmp.new_cipher->algorithm_auth;
- EVP_MD_CTX_init(&md_ctx);
+ /* TLS does not like anon-DH with client cert */
+ if (s->version > SSL3_VERSION &&
+ (s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request,
+ SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER);
+ goto err;
+ }
- if (alg_a & SSL_aPSK)
- {
- CBS psk_identity_hint;
+ CBS_init(&cbs, s->init_msg, n);
- /* Each of the PSK key exchanges begins with a
- * psk_identity_hint. */
- if (!CBS_get_u16_length_prefixed(&server_key_exchange, &psk_identity_hint))
- {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_DECODE_ERROR);
- goto f_err;
- }
+ ca_sk = sk_X509_NAME_new(ca_dn_cmp);
+ if (ca_sk == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
- /* Store PSK identity hint for later use, hint is used in
- * ssl3_send_client_key_exchange. Assume that the maximum
- * length of a PSK identity hint can be as long as the maximum
- * length of a PSK identity. Also do not allow NULL
- * characters; identities are saved as C strings.
- *
- * TODO(davidben): Should invalid hints be ignored? It's a hint
- * rather than a specific identity. */
- if (CBS_len(&psk_identity_hint) > PSK_MAX_IDENTITY_LEN ||
- CBS_contains_zero_byte(&psk_identity_hint))
- {
- al = SSL_AD_HANDSHAKE_FAILURE;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_DATA_LENGTH_TOO_LONG);
- goto f_err;
- }
+ /* get the certificate types */
+ if (!CBS_get_u8_length_prefixed(&cbs, &certificate_types)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, SSL_R_DECODE_ERROR);
+ goto err;
+ }
- /* Save the identity hint as a C string. */
- if (!CBS_strdup(&psk_identity_hint, &s->s3->tmp.peer_psk_identity_hint))
- {
- al = SSL_AD_INTERNAL_ERROR;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, ERR_R_MALLOC_FAILURE);
- goto f_err;
- }
- }
+ if (!CBS_stow(&certificate_types, &s->s3->tmp.certificate_types,
+ &s->s3->tmp.num_certificate_types)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ goto err;
+ }
- if (alg_k & SSL_kEDH)
- {
- CBS dh_p, dh_g, dh_Ys;
+ if (SSL_USE_SIGALGS(s)) {
+ CBS supported_signature_algorithms;
+ if (!CBS_get_u16_length_prefixed(&cbs, &supported_signature_algorithms)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, SSL_R_DECODE_ERROR);
+ goto err;
+ }
- if (!CBS_get_u16_length_prefixed(&server_key_exchange, &dh_p) ||
- CBS_len(&dh_p) == 0 ||
- !CBS_get_u16_length_prefixed(&server_key_exchange, &dh_g) ||
- CBS_len(&dh_g) == 0 ||
- !CBS_get_u16_length_prefixed(&server_key_exchange, &dh_Ys) ||
- CBS_len(&dh_Ys) == 0)
- {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_DECODE_ERROR);
- goto f_err;
- }
+ if (!tls1_process_sigalgs(s, &supported_signature_algorithms)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request,
+ SSL_R_SIGNATURE_ALGORITHMS_ERROR);
+ goto err;
+ }
+ }
- if ((dh=DH_new()) == NULL)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, ERR_R_DH_LIB);
- goto err;
- }
+ /* get the CA RDNs */
+ if (!CBS_get_u16_length_prefixed(&cbs, &certificate_authorities)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
- if (!(dh->p = BN_bin2bn(CBS_data(&dh_p), CBS_len(&dh_p), NULL)))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, ERR_R_BN_LIB);
- goto err;
- }
- if (!(dh->g=BN_bin2bn(CBS_data(&dh_g), CBS_len(&dh_g), NULL)))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, ERR_R_BN_LIB);
- goto err;
- }
- if (!(dh->pub_key = BN_bin2bn(CBS_data(&dh_Ys), CBS_len(&dh_Ys), NULL)))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, ERR_R_BN_LIB);
- goto err;
- }
+ while (CBS_len(&certificate_authorities) > 0) {
+ CBS distinguished_name;
+ if (!CBS_get_u16_length_prefixed(&certificate_authorities,
+ &distinguished_name)) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request,
+ SSL_R_CA_DN_TOO_LONG);
+ goto err;
+ }
- if (DH_size(dh) < 512/8)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_BAD_DH_P_LENGTH);
- goto err;
- }
+ data = CBS_data(&distinguished_name);
- if (alg_a & SSL_aRSA)
- pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
- /* else anonymous DH, so no certificate or pkey. */
+ xn = d2i_X509_NAME(NULL, &data, CBS_len(&distinguished_name));
+ if (xn == NULL) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, ERR_R_ASN1_LIB);
+ goto err;
+ }
- s->session->sess_cert->peer_dh_tmp=dh;
- dh=NULL;
- }
+ if (!CBS_skip(&distinguished_name, data - CBS_data(&distinguished_name))) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
- else if (alg_k & SSL_kEECDH)
- {
- uint16_t curve_id;
- int curve_nid = 0;
- EC_GROUP *ngroup;
- const EC_GROUP *group;
- CBS point;
+ if (CBS_len(&distinguished_name) != 0) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request,
+ SSL_R_CA_DN_LENGTH_MISMATCH);
+ goto err;
+ }
- /* Extract elliptic curve parameters and the server's
- * ephemeral ECDH public key. Check curve is one of
- * our preferences, if not server has sent an invalid
- * curve.
- */
- if (!tls1_check_curve(s, &server_key_exchange, &curve_id))
- {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_WRONG_CURVE);
- goto f_err;
- }
+ if (!sk_X509_NAME_push(ca_sk, xn)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
- if ((curve_nid = tls1_ec_curve_id2nid(curve_id)) == 0)
- {
- al=SSL_AD_INTERNAL_ERROR;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
- goto f_err;
- }
+ /* we should setup a certificate to return.... */
+ s->s3->tmp.cert_req = 1;
+ if (s->s3->tmp.ca_names != NULL) {
+ sk_X509_NAME_pop_free(s->s3->tmp.ca_names, X509_NAME_free);
+ }
+ s->s3->tmp.ca_names = ca_sk;
+ ca_sk = NULL;
- if ((ecdh=EC_KEY_new()) == NULL)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- ngroup = EC_GROUP_new_by_curve_name(curve_nid);
- if (ngroup == NULL)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, ERR_R_EC_LIB);
- goto err;
- }
- if (EC_KEY_set_group(ecdh, ngroup) == 0)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, ERR_R_EC_LIB);
- goto err;
- }
- EC_GROUP_free(ngroup);
+ ret = 1;
- group = EC_KEY_get0_group(ecdh);
+err:
+ if (ca_sk != NULL) {
+ sk_X509_NAME_pop_free(ca_sk, X509_NAME_free);
+ }
+ return ret;
+}
- /* Next, get the encoded ECPoint */
- if (!CBS_get_u8_length_prefixed(&server_key_exchange, &point))
- {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_DECODE_ERROR);
- goto f_err;
- }
+int ssl3_get_new_session_ticket(SSL *s) {
+ int ok, al, ret = 0;
+ long n;
+ CBS new_session_ticket, ticket;
- if (((srvr_ecpoint = EC_POINT_new(group)) == NULL) ||
- ((bn_ctx = BN_CTX_new()) == NULL))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, ERR_R_MALLOC_FAILURE);
- goto err;
- }
+ n = s->method->ssl_get_message(
+ s, SSL3_ST_CR_SESSION_TICKET_A, SSL3_ST_CR_SESSION_TICKET_B,
+ SSL3_MT_NEWSESSION_TICKET, 16384, SSL_GET_MESSAGE_HASH_MESSAGE, &ok);
- if (!EC_POINT_oct2point(group, srvr_ecpoint,
- CBS_data(&point), CBS_len(&point), bn_ctx))
- {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_BAD_ECPOINT);
- goto f_err;
- }
+ if (!ok) {
+ return n;
+ }
- /* The ECC/TLS specification does not mention
- * the use of DSA to sign ECParameters in the server
- * key exchange message. We do support RSA and ECDSA.
- */
- if (0) ;
- else if (alg_a & SSL_aRSA)
- pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
- else if (alg_a & SSL_aECDSA)
- pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_ECC].x509);
- /* else anonymous ECDH, so no certificate or pkey. */
- EC_KEY_set_public_key(ecdh, srvr_ecpoint);
- s->session->sess_cert->peer_ecdh_tmp=ecdh;
- ecdh=NULL;
- BN_CTX_free(bn_ctx);
- bn_ctx = NULL;
- EC_POINT_free(srvr_ecpoint);
- srvr_ecpoint = NULL;
- }
+ CBS_init(&new_session_ticket, s->init_msg, n);
- else if (!(alg_k & SSL_kPSK))
- {
- al=SSL_AD_UNEXPECTED_MESSAGE;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_UNEXPECTED_MESSAGE);
- goto f_err;
- }
+ if (!CBS_get_u32(&new_session_ticket,
+ &s->session->tlsext_tick_lifetime_hint) ||
+ !CBS_get_u16_length_prefixed(&new_session_ticket, &ticket) ||
+ CBS_len(&new_session_ticket) != 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_new_session_ticket, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
- /* At this point, |server_key_exchange| contains the
- * signature, if any, while |server_key_exchange_orig|
- * contains the entire message. From that, derive a CBS
- * containing just the parameter. */
- CBS_init(¶meter, CBS_data(&server_key_exchange_orig),
- CBS_len(&server_key_exchange_orig) -
- CBS_len(&server_key_exchange));
+ if (!CBS_stow(&ticket, &s->session->tlsext_tick,
+ &s->session->tlsext_ticklen)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_new_session_ticket, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
- /* if it was signed, check the signature */
- if (pkey != NULL)
- {
- CBS signature;
+ /* There are two ways to detect a resumed ticket sesion. One is to set an
+ * appropriate session ID and then the server must return a match in
+ * ServerHello. This allows the normal client session ID matching to work and
+ * we know much earlier that the ticket has been accepted.
+ *
+ * The other way is to set zero length session ID when the ticket is
+ * presented and rely on the handshake to determine session resumption.
+ *
+ * We choose the former approach because this fits in with assumptions
+ * elsewhere in OpenSSL. The session ID is set to the SHA256 (or SHA1 is
+ * SHA256 is disabled) hash of the ticket. */
+ EVP_Digest(CBS_data(&ticket), CBS_len(&ticket), s->session->session_id,
+ &s->session->session_id_length, EVP_sha256(), NULL);
+ ret = 1;
+ return ret;
- if (SSL_USE_SIGALGS(s))
- {
- if (!tls12_check_peer_sigalg(&md, &al, s, &server_key_exchange, pkey))
- goto f_err;
- }
- else if (pkey->type == EVP_PKEY_RSA)
- {
- md = EVP_md5_sha1();
- }
- else
- {
- md = EVP_sha1();
- }
-
- /* The last field in |server_key_exchange| is the
- * signature. */
- if (!CBS_get_u16_length_prefixed(&server_key_exchange, &signature) ||
- CBS_len(&server_key_exchange) != 0)
- {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_DECODE_ERROR);
- goto f_err;
- }
-
- if (!EVP_DigestVerifyInit(&md_ctx, NULL, md, NULL, pkey) ||
- !EVP_DigestVerifyUpdate(&md_ctx, s->s3->client_random, SSL3_RANDOM_SIZE) ||
- !EVP_DigestVerifyUpdate(&md_ctx, s->s3->server_random, SSL3_RANDOM_SIZE) ||
- !EVP_DigestVerifyUpdate(&md_ctx, CBS_data(¶meter), CBS_len(¶meter)) ||
- !EVP_DigestVerifyFinal(&md_ctx, CBS_data(&signature), CBS_len(&signature)))
- {
- /* bad signature */
- al=SSL_AD_DECRYPT_ERROR;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_BAD_SIGNATURE);
- goto f_err;
- }
- }
- else
- {
- if (ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher))
- {
- /* Might be wrong key type, check it */
- if (ssl3_check_cert_and_algorithm(s))
- /* Otherwise this shouldn't happen */
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, ERR_R_INTERNAL_ERROR);
- goto err;
- }
- /* still data left over */
- if (CBS_len(&server_key_exchange) > 0)
- {
- al=SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_key_exchange, SSL_R_EXTRA_DATA_IN_MESSAGE);
- goto f_err;
- }
- }
- EVP_PKEY_free(pkey);
- EVP_MD_CTX_cleanup(&md_ctx);
- return(1);
f_err:
- ssl3_send_alert(s,SSL3_AL_FATAL,al);
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
err:
- EVP_PKEY_free(pkey);
- if (rsa != NULL)
- RSA_free(rsa);
- if (dh != NULL)
- DH_free(dh);
- BN_CTX_free(bn_ctx);
- EC_POINT_free(srvr_ecpoint);
- if (ecdh != NULL)
- EC_KEY_free(ecdh);
- EVP_MD_CTX_cleanup(&md_ctx);
- return(-1);
- }
+ return -1;
+}
-static int ca_dn_cmp(const X509_NAME **a, const X509_NAME **b)
- {
- return(X509_NAME_cmp(*a,*b));
- }
+int ssl3_get_cert_status(SSL *s) {
+ int ok, al;
+ long n;
+ CBS certificate_status, ocsp_response;
+ uint8_t status_type;
-int ssl3_get_certificate_request(SSL *s)
- {
- int ok,ret=0;
- unsigned long n;
- X509_NAME *xn=NULL;
- STACK_OF(X509_NAME) *ca_sk=NULL;
- CBS cbs;
- CBS certificate_types;
- CBS certificate_authorities;
- const uint8_t *data;
+ 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);
- n=s->method->ssl_get_message(s,
- SSL3_ST_CR_CERT_REQ_A,
- SSL3_ST_CR_CERT_REQ_B,
- -1,
- s->max_cert_list,
- SSL_GET_MESSAGE_HASH_MESSAGE,
- &ok);
+ if (!ok) {
+ return n;
+ }
- if (!ok) return((int)n);
+ CBS_init(&certificate_status, s->init_msg, n);
+ if (!CBS_get_u8(&certificate_status, &status_type) ||
+ status_type != TLSEXT_STATUSTYPE_ocsp ||
+ !CBS_get_u24_length_prefixed(&certificate_status, &ocsp_response) ||
+ CBS_len(&ocsp_response) == 0 ||
+ CBS_len(&certificate_status) != 0) {
+ al = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_status, SSL_R_DECODE_ERROR);
+ goto f_err;
+ }
- s->s3->tmp.cert_req=0;
+ 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;
+ }
+ return 1;
- if (s->s3->tmp.message_type == SSL3_MT_SERVER_DONE)
- {
- s->s3->tmp.reuse_message=1;
- /* If we get here we don't need any cached handshake records
- * as we wont be doing client auth.
- */
- if (s->s3->handshake_buffer)
- {
- if (!ssl3_digest_cached_records(s, free_handshake_buffer))
- goto err;
- }
- return(1);
- }
-
- if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE_REQUEST)
- {
- ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
- OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, SSL_R_WRONG_MESSAGE_TYPE);
- goto err;
- }
-
- /* TLS does not like anon-DH with client cert */
- if (s->version > SSL3_VERSION)
- {
- if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
- {
- ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
- OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER);
- goto err;
- }
- }
-
- CBS_init(&cbs, s->init_msg, n);
-
- ca_sk = sk_X509_NAME_new(ca_dn_cmp);
- if (ca_sk == NULL)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- /* get the certificate types */
- if (!CBS_get_u8_length_prefixed(&cbs, &certificate_types))
- {
- ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, SSL_R_DECODE_ERROR);
- goto err;
- }
- if (!CBS_stow(&certificate_types,
- &s->s3->tmp.certificate_types,
- &s->s3->tmp.num_certificate_types))
- {
- ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
- goto err;
- }
- if (SSL_USE_SIGALGS(s))
- {
- CBS supported_signature_algorithms;
- if (!CBS_get_u16_length_prefixed(&cbs, &supported_signature_algorithms))
- {
- ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
- OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, SSL_R_DECODE_ERROR);
- goto err;
- }
- if (!tls1_process_sigalgs(s, &supported_signature_algorithms))
- {
- ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
- OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, SSL_R_SIGNATURE_ALGORITHMS_ERROR);
- goto err;
- }
- }
-
- /* get the CA RDNs */
- if (!CBS_get_u16_length_prefixed(&cbs, &certificate_authorities))
- {
- ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
- OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, SSL_R_LENGTH_MISMATCH);
- goto err;
- }
-
- while (CBS_len(&certificate_authorities) > 0)
- {
- CBS distinguished_name;
- if (!CBS_get_u16_length_prefixed(&certificate_authorities, &distinguished_name))
- {
- ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
- OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, SSL_R_CA_DN_TOO_LONG);
- goto err;
- }
-
- data = CBS_data(&distinguished_name);
- if ((xn=d2i_X509_NAME(NULL, &data, CBS_len(&distinguished_name))) == NULL)
- {
- ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
- OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, ERR_R_ASN1_LIB);
- goto err;
- }
-
- if (!CBS_skip(&distinguished_name, data - CBS_data(&distinguished_name)))
- {
- ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_certificate, ERR_R_INTERNAL_ERROR);
- goto err;
- }
- if (CBS_len(&distinguished_name) != 0)
- {
- ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
- OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, SSL_R_CA_DN_LENGTH_MISMATCH);
- goto err;
- }
- if (!sk_X509_NAME_push(ca_sk,xn))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_get_certificate_request, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- }
-
- /* we should setup a certificate to return.... */
- s->s3->tmp.cert_req=1;
- if (s->s3->tmp.ca_names != NULL)
- sk_X509_NAME_pop_free(s->s3->tmp.ca_names,X509_NAME_free);
- s->s3->tmp.ca_names=ca_sk;
- ca_sk=NULL;
-
- ret=1;
-err:
- if (ca_sk != NULL) sk_X509_NAME_pop_free(ca_sk,X509_NAME_free);
- return(ret);
- }
-
-int ssl3_get_new_session_ticket(SSL *s)
- {
- int ok,al,ret=0;
- long n;
- CBS new_session_ticket, ticket;
-
- n=s->method->ssl_get_message(s,
- SSL3_ST_CR_SESSION_TICKET_A,
- SSL3_ST_CR_SESSION_TICKET_B,
- SSL3_MT_NEWSESSION_TICKET,
- 16384,
- SSL_GET_MESSAGE_HASH_MESSAGE,
- &ok);
-
- if (!ok)
- return((int)n);
-
- CBS_init(&new_session_ticket, s->init_msg, n);
-
- if (!CBS_get_u32(&new_session_ticket, &s->session->tlsext_tick_lifetime_hint) ||
- !CBS_get_u16_length_prefixed(&new_session_ticket, &ticket) ||
- CBS_len(&new_session_ticket) != 0)
- {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_new_session_ticket, SSL_R_DECODE_ERROR);
- goto f_err;
- }
-
- if (!CBS_stow(&ticket, &s->session->tlsext_tick, &s->session->tlsext_ticklen))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_get_new_session_ticket, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- /* There are two ways to detect a resumed ticket sesion.
- * One is to set an appropriate session ID and then the server
- * must return a match in ServerHello. This allows the normal
- * client session ID matching to work and we know much
- * earlier that the ticket has been accepted.
- *
- * The other way is to set zero length session ID when the
- * ticket is presented and rely on the handshake to determine
- * session resumption.
- *
- * We choose the former approach because this fits in with
- * assumptions elsewhere in OpenSSL. The session ID is set
- * to the SHA256 (or SHA1 is SHA256 is disabled) hash of the
- * ticket.
- */
- EVP_Digest(CBS_data(&ticket), CBS_len(&ticket),
- s->session->session_id, &s->session->session_id_length,
- EVP_sha256(), NULL);
- ret=1;
- return(ret);
f_err:
- ssl3_send_alert(s,SSL3_AL_FATAL,al);
-err:
- return(-1);
- }
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ return -1;
+}
-int ssl3_get_cert_status(SSL *s)
- {
- int ok, al;
- long n;
- CBS certificate_status, ocsp_response;
- uint8_t status_type;
+int ssl3_get_server_done(SSL *s) {
+ int ok;
+ long n;
- 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);
+ n = s->method->ssl_get_message(s, SSL3_ST_CR_SRVR_DONE_A,
+ 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);
+ if (!ok) {
+ return n;
+ }
- CBS_init(&certificate_status, s->init_msg, n);
- if (!CBS_get_u8(&certificate_status, &status_type) ||
- status_type != TLSEXT_STATUSTYPE_ocsp ||
- !CBS_get_u24_length_prefixed(&certificate_status, &ocsp_response) ||
- CBS_len(&ocsp_response) == 0 ||
- CBS_len(&certificate_status) != 0)
- {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_status, SSL_R_DECODE_ERROR);
- goto f_err;
- }
+ if (n > 0) {
+ /* should contain no data */
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(SSL, ssl3_get_server_done, SSL_R_LENGTH_MISMATCH);
+ return -1;
+ }
- 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;
- }
- return 1;
-f_err:
- ssl3_send_alert(s,SSL3_AL_FATAL,al);
- return(-1);
- }
-
-int ssl3_get_server_done(SSL *s)
- {
- int ok,ret=0;
- long n;
-
- n=s->method->ssl_get_message(s,
- SSL3_ST_CR_SRVR_DONE_A,
- 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);
- if (n > 0)
- {
- /* should contain no data */
- ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
- OPENSSL_PUT_ERROR(SSL, ssl3_get_server_done, SSL_R_LENGTH_MISMATCH);
- return -1;
- }
- ret=1;
- return(ret);
- }
-
-
-int ssl3_send_client_key_exchange(SSL *s)
- {
- unsigned char *p;
- int n = 0;
- unsigned long alg_k;
- unsigned long alg_a;
- unsigned char *q;
- EVP_PKEY *pkey=NULL;
- EC_KEY *clnt_ecdh = NULL;
- const EC_POINT *srvr_ecpoint = NULL;
- EVP_PKEY *srvr_pub_pkey = NULL;
- unsigned char *encodedPoint = NULL;
- int encoded_pt_len = 0;
- BN_CTX * bn_ctx = NULL;
- unsigned int psk_len = 0;
- unsigned char psk[PSK_MAX_PSK_LEN];
- uint8_t *pms = NULL;
- size_t pms_len = 0;
-
- if (s->state == SSL3_ST_CW_KEY_EXCH_A)
- {
- p = ssl_handshake_start(s);
-
- alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
- alg_a=s->s3->tmp.new_cipher->algorithm_auth;
-
- /* If using a PSK key exchange, prepare the pre-shared key. */
- if (alg_a & SSL_aPSK)
- {
- char identity[PSK_MAX_IDENTITY_LEN + 1];
- size_t identity_len;
-
- if (s->psk_client_callback == NULL)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, SSL_R_PSK_NO_CLIENT_CB);
- goto err;
- }
-
- memset(identity, 0, sizeof(identity));
- psk_len = s->psk_client_callback(s, s->s3->tmp.peer_psk_identity_hint,
- identity, sizeof(identity), psk, sizeof(psk));
- if (psk_len > PSK_MAX_PSK_LEN)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_INTERNAL_ERROR);
- goto err;
- }
- else if (psk_len == 0)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, SSL_R_PSK_IDENTITY_NOT_FOUND);
- ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
- goto err;
- }
- identity_len = OPENSSL_strnlen(identity, sizeof(identity));
- if (identity_len > PSK_MAX_IDENTITY_LEN)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- if (s->session->psk_identity != NULL)
- OPENSSL_free(s->session->psk_identity);
- s->session->psk_identity = BUF_strdup(identity);
- if (s->session->psk_identity == NULL)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- /* Write out psk_identity. */
- s2n(identity_len, p);
- memcpy(p, identity, identity_len);
- p += identity_len;
- n = 2 + identity_len;
- }
-
- /* Depending on the key exchange method, compute |pms|
- * and |pms_len|. */
- if (alg_k & SSL_kRSA)
- {
- RSA *rsa;
- size_t enc_pms_len;
-
- pms_len = SSL_MAX_MASTER_KEY_LENGTH;
- pms = OPENSSL_malloc(pms_len);
- if (pms == NULL)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (s->session->sess_cert == NULL)
- {
- /* We should always have a server certificate with SSL_kRSA. */
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
- if ((pkey == NULL) ||
- (pkey->type != EVP_PKEY_RSA) ||
- (pkey->pkey.rsa == NULL))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_INTERNAL_ERROR);
- if (pkey != NULL)
- EVP_PKEY_free(pkey);
- goto err;
- }
- rsa=pkey->pkey.rsa;
- EVP_PKEY_free(pkey);
-
- pms[0]=s->client_version>>8;
- pms[1]=s->client_version&0xff;
- if (!RAND_bytes(&pms[2], SSL_MAX_MASTER_KEY_LENGTH - 2))
- goto err;
-
- s->session->master_key_length=SSL_MAX_MASTER_KEY_LENGTH;
-
- q=p;
- /* In TLS and beyond, reserve space for the length prefix. */
- if (s->version > SSL3_VERSION)
- {
- p += 2;
- n += 2;
- }
- if (!RSA_encrypt(rsa, &enc_pms_len, p, RSA_size(rsa),
- pms, pms_len, RSA_PKCS1_PADDING))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, SSL_R_BAD_RSA_ENCRYPT);
- goto err;
- }
- n += enc_pms_len;
-
- /* Log the premaster secret, if logging is enabled. */
- if (!ssl_ctx_log_rsa_client_key_exchange(s->ctx,
- p, enc_pms_len, pms, pms_len))
- {
- goto err;
- }
-
- /* Fill in the length prefix. */
- if (s->version > SSL3_VERSION)
- {
- s2n(enc_pms_len, q);
- }
- }
- else if (alg_k & SSL_kEDH)
- {
- DH *dh_srvr, *dh_clnt;
- SESS_CERT *scert = s->session->sess_cert;
- int dh_len;
- size_t pub_len;
-
- if (scert == NULL)
- {
- ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, SSL_R_UNEXPECTED_MESSAGE);
- goto err;
- }
-
- if (scert->peer_dh_tmp == NULL)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_INTERNAL_ERROR);
- goto err;
- }
- dh_srvr=scert->peer_dh_tmp;
-
- /* generate a new random key */
- if ((dh_clnt=DHparams_dup(dh_srvr)) == NULL)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_DH_LIB);
- goto err;
- }
- if (!DH_generate_key(dh_clnt))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_DH_LIB);
- DH_free(dh_clnt);
- goto err;
- }
-
- pms_len = DH_size(dh_clnt);
- pms = OPENSSL_malloc(pms_len);
- if (pms == NULL)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_MALLOC_FAILURE);
- DH_free(dh_clnt);
- goto err;
- }
-
- dh_len = DH_compute_key(pms, dh_srvr->pub_key, dh_clnt);
- if (dh_len <= 0)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_DH_LIB);
- DH_free(dh_clnt);
- goto err;
- }
- pms_len = dh_len;
-
- /* send off the data */
- pub_len = BN_num_bytes(dh_clnt->pub_key);
- s2n(pub_len, p);
- BN_bn2bin(dh_clnt->pub_key, p);
- n += 2 + pub_len;
-
- DH_free(dh_clnt);
- }
-
- else if (alg_k & SSL_kEECDH)
- {
- const EC_GROUP *srvr_group = NULL;
- EC_KEY *tkey;
- int field_size = 0, ecdh_len;
-
- if (s->session->sess_cert == NULL)
- {
- ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE);
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, SSL_R_UNEXPECTED_MESSAGE);
- goto err;
- }
-
- if (s->session->sess_cert->peer_ecdh_tmp == NULL)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_INTERNAL_ERROR);
- goto err;
- }
- tkey = s->session->sess_cert->peer_ecdh_tmp;
-
- srvr_group = EC_KEY_get0_group(tkey);
- srvr_ecpoint = EC_KEY_get0_public_key(tkey);
-
- if ((srvr_group == NULL) || (srvr_ecpoint == NULL))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- if ((clnt_ecdh=EC_KEY_new()) == NULL)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- if (!EC_KEY_set_group(clnt_ecdh, srvr_group))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_EC_LIB);
- goto err;
- }
- /* Generate a new ECDH key pair */
- if (!(EC_KEY_generate_key(clnt_ecdh)))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_ECDH_LIB);
- goto err;
- }
-
- field_size = EC_GROUP_get_degree(srvr_group);
- if (field_size <= 0)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_ECDH_LIB);
- goto err;
- }
-
- pms_len = (field_size + 7) / 8;
- pms = OPENSSL_malloc(pms_len);
- if (pms == NULL)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- ecdh_len = ECDH_compute_key(pms, pms_len, srvr_ecpoint, clnt_ecdh, NULL);
- if (ecdh_len <= 0)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_ECDH_LIB);
- goto err;
- }
- pms_len = ecdh_len;
-
- /* First check the size of encoding and
- * allocate memory accordingly.
- */
- encoded_pt_len =
- EC_POINT_point2oct(srvr_group,
- EC_KEY_get0_public_key(clnt_ecdh),
- POINT_CONVERSION_UNCOMPRESSED,
- NULL, 0, NULL);
-
- encodedPoint = (unsigned char *)
- OPENSSL_malloc(encoded_pt_len *
- sizeof(unsigned char));
- bn_ctx = BN_CTX_new();
- if ((encodedPoint == NULL) ||
- (bn_ctx == NULL))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- /* Encode the public key */
- encoded_pt_len = EC_POINT_point2oct(srvr_group,
- EC_KEY_get0_public_key(clnt_ecdh),
- POINT_CONVERSION_UNCOMPRESSED,
- encodedPoint, encoded_pt_len, bn_ctx);
-
- *p = encoded_pt_len; /* length of encoded point */
- /* Encoded point will be copied here */
- p += 1;
- n += 1;
- /* copy the point */
- memcpy(p, encodedPoint, encoded_pt_len);
- /* increment n to account for length field */
- n += encoded_pt_len;
-
- /* Free allocated memory */
- BN_CTX_free(bn_ctx);
- bn_ctx = NULL;
- OPENSSL_free(encodedPoint);
- encodedPoint = NULL;
- EC_KEY_free(clnt_ecdh);
- clnt_ecdh = NULL;
- EVP_PKEY_free(srvr_pub_pkey);
- srvr_pub_pkey = NULL;
- }
- else if (alg_k & SSL_kPSK)
- {
- /* For plain PSK, other_secret is a block of 0s with the same
- * length as the pre-shared key. */
- pms_len = psk_len;
- pms = OPENSSL_malloc(pms_len);
- if (pms == NULL)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- memset(pms, 0, pms_len);
- }
- else
- {
- ssl3_send_alert(s, SSL3_AL_FATAL,
- SSL_AD_HANDSHAKE_FAILURE);
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- /* For a PSK cipher suite, other_secret is combined
- * with the pre-shared key. */
- if (alg_a & SSL_aPSK)
- {
- CBB cbb, child;
- uint8_t *new_pms;
- size_t new_pms_len;
-
- if (!CBB_init(&cbb, 2 + psk_len + 2 + pms_len))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
- !CBB_add_bytes(&child, pms, pms_len) ||
- !CBB_add_u16_length_prefixed(&cbb, &child) ||
- !CBB_add_bytes(&child, psk, psk_len) ||
- !CBB_finish(&cbb, &new_pms, &new_pms_len))
- {
- CBB_cleanup(&cbb);
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_INTERNAL_ERROR);
- goto err;
- }
- OPENSSL_cleanse(pms, pms_len);
- OPENSSL_free(pms);
- pms = new_pms;
- pms_len = new_pms_len;
- }
-
- /* The message must be added to the finished hash before
- * calculating the master secret. */
- ssl_set_handshake_header(s, SSL3_MT_CLIENT_KEY_EXCHANGE, n);
- s->state=SSL3_ST_CW_KEY_EXCH_B;
-
- s->session->master_key_length =
- s->enc_method->generate_master_secret(s,
- s->session->master_key,
- pms, pms_len);
- if (s->session->master_key_length == 0)
- {
- goto err;
- }
- s->session->extended_master_secret = s->s3->tmp.extended_master_secret;
- OPENSSL_cleanse(pms, pms_len);
- OPENSSL_free(pms);
- }
-
- /* SSL3_ST_CW_KEY_EXCH_B */
- return s->enc_method->do_write(s);
-
-err:
- 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);
- if (pms)
- {
- OPENSSL_cleanse(pms, pms_len);
- OPENSSL_free(pms);
- }
- return -1;
- }
-
-int ssl3_send_cert_verify(SSL *s)
- {
- unsigned char *buf, *p;
- const EVP_MD *md = NULL;
- uint8_t digest[EVP_MAX_MD_SIZE];
- size_t digest_length;
- EVP_PKEY *pkey;
- EVP_PKEY_CTX *pctx = NULL;
- size_t signature_length = 0;
- unsigned long n = 0;
-
- 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;
-
- /* Write out the digest type if needbe. */
- if (SSL_USE_SIGALGS(s))
- {
- md = tls1_choose_signing_digest(s, pkey);
- if (!tls12_get_sigandhash(p, pkey, md))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_cert_verify, ERR_R_INTERNAL_ERROR);
- goto err;
- }
- p += 2;
- n += 2;
- }
-
- /* 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, free_handshake_buffer))
- goto err;
-
- /* Sign the digest. */
- pctx = EVP_PKEY_CTX_new(pkey, NULL);
- if (pctx == NULL)
- goto err;
-
- /* Initialize the EVP_PKEY_CTX and determine the size of the signature. */
- 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_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_cert_verify, SSL_R_DATA_LENGTH_TOO_LONG);
- goto err;
- }
-
- if (!EVP_PKEY_sign(pctx, &p[2], &signature_length,
- digest, digest_length))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_cert_verify, ERR_R_EVP_LIB);
- goto err;
- }
-
- s2n(signature_length, p);
- n += signature_length + 2;
-
- ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_VERIFY, n);
- s->state=SSL3_ST_CW_CERT_VRFY_B;
- }
- EVP_PKEY_CTX_free(pctx);
- return ssl_do_write(s);
-err:
- EVP_PKEY_CTX_free(pctx);
- return(-1);
- }
-
-/* ssl3_has_client_certificate returns true if a client certificate is
- * configured. */
-static int ssl3_has_client_certificate(SSL *s)
- {
- return s->cert && s->cert->key->x509 && s->cert->key->privatekey;
- }
-
-int ssl3_send_client_certificate(SSL *s)
- {
- X509 *x509=NULL;
- EVP_PKEY *pkey=NULL;
- int i;
-
- if (s->state == SSL3_ST_CW_CERT_A)
- {
- /* Let cert callback update client certificates if required */
- if (s->cert->cert_cb)
- {
- i = s->cert->cert_cb(s, s->cert->cert_cb_arg);
- if (i < 0)
- {
- s->rwstate=SSL_X509_LOOKUP;
- return -1;
- }
- if (i == 0)
- {
- ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_INTERNAL_ERROR);
- return 0;
- }
- s->rwstate=SSL_NOTHING;
- }
- if (ssl3_has_client_certificate(s))
- s->state=SSL3_ST_CW_CERT_C;
- else
- s->state=SSL3_ST_CW_CERT_B;
- }
-
- /* We need to get a client cert */
- if (s->state == SSL3_ST_CW_CERT_B)
- {
- /* If we get an error, we need to
- * ssl->rwstate=SSL_X509_LOOKUP; return(-1);
- * We then get retried later */
- i = ssl_do_client_cert_cb(s, &x509, &pkey);
- if (i < 0)
- {
- s->rwstate=SSL_X509_LOOKUP;
- return(-1);
- }
- s->rwstate=SSL_NOTHING;
- if ((i == 1) && (pkey != NULL) && (x509 != NULL))
- {
- s->state=SSL3_ST_CW_CERT_B;
- if ( !SSL_use_certificate(s,x509) ||
- !SSL_use_PrivateKey(s,pkey))
- i=0;
- }
- else if (i == 1)
- {
- i=0;
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_certificate, SSL_R_BAD_DATA_RETURNED_BY_CALLBACK);
- }
-
- if (x509 != NULL) X509_free(x509);
- if (pkey != NULL) EVP_PKEY_free(pkey);
- if (i && !ssl3_has_client_certificate(s))
- i = 0;
- if (i == 0)
- {
- if (s->version == SSL3_VERSION)
- {
- s->s3->tmp.cert_req=0;
- ssl3_send_alert(s,SSL3_AL_WARNING,SSL_AD_NO_CERTIFICATE);
- return(1);
- }
- else
- {
- s->s3->tmp.cert_req=2;
- }
- }
-
- /* Ok, we have a cert */
- s->state=SSL3_ST_CW_CERT_C;
- }
-
- if (s->state == SSL3_ST_CW_CERT_C)
- {
- s->state=SSL3_ST_CW_CERT_D;
- ssl3_output_cert_chain(s,
- (s->s3->tmp.cert_req == 2)?NULL:s->cert->key);
- }
- /* SSL3_ST_CW_CERT_D */
- return ssl_do_write(s);
- }
-
-#define has_bits(i,m) (((i)&(m)) == (m))
-
-int ssl3_check_cert_and_algorithm(SSL *s)
- {
- int i,idx;
- long alg_k,alg_a;
- EVP_PKEY *pkey=NULL;
- SESS_CERT *sc;
- DH *dh;
-
- /* we don't have a certificate */
- if (!ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher))
- return 1;
-
- alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
- alg_a=s->s3->tmp.new_cipher->algorithm_auth;
-
- sc=s->session->sess_cert;
- if (sc == NULL)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_check_cert_and_algorithm, ERR_R_INTERNAL_ERROR);
- goto err;
- }
-
- dh=s->session->sess_cert->peer_dh_tmp;
-
- /* This is the passed certificate */
-
- idx=sc->peer_cert_type;
- if (idx == SSL_PKEY_ECC)
- {
- if (ssl_check_srvr_ecc_cert_and_alg(sc->peer_pkeys[idx].x509,
- s) == 0)
- { /* check failed */
- OPENSSL_PUT_ERROR(SSL, ssl3_check_cert_and_algorithm, SSL_R_BAD_ECC_CERT);
- goto f_err;
- }
- else
- {
- return 1;
- }
- }
- else if (alg_a & SSL_aECDSA)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_check_cert_and_algorithm, SSL_R_MISSING_ECDSA_SIGNING_CERT);
- goto f_err;
- }
- pkey=X509_get_pubkey(sc->peer_pkeys[idx].x509);
- i=X509_certificate_type(sc->peer_pkeys[idx].x509,pkey);
- EVP_PKEY_free(pkey);
-
-
- /* Check that we have a certificate if we require one */
- if ((alg_a & SSL_aRSA) && !has_bits(i,EVP_PK_RSA|EVP_PKT_SIGN))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_check_cert_and_algorithm, SSL_R_MISSING_RSA_SIGNING_CERT);
- goto f_err;
- }
- if ((alg_k & SSL_kRSA) && !has_bits(i,EVP_PK_RSA|EVP_PKT_ENC))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_check_cert_and_algorithm, SSL_R_MISSING_RSA_ENCRYPTING_CERT);
- goto f_err;
- }
- 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;
- }
-
- return(1);
-f_err:
- ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
-err:
- return(0);
- }
-
-int ssl3_send_next_proto(SSL *s)
- {
- unsigned int len, padding_len;
- uint8_t *d, *p;
-
- if (s->state == SSL3_ST_CW_NEXT_PROTO_A)
- {
- len = s->next_proto_negotiated_len;
- padding_len = 32 - ((len + 2) % 32);
-
- d = p = ssl_handshake_start(s);
- *(p++) = len;
- memcpy(p, s->next_proto_negotiated, len);
- p += len;
- *(p++) = padding_len;
- memset(p, 0, padding_len);
- p += padding_len;
-
- ssl_set_handshake_header(s, SSL3_MT_NEXT_PROTO, p - d);
- s->state = SSL3_ST_CW_NEXT_PROTO_B;
- }
-
- return ssl_do_write(s);
+ return 1;
}
-int ssl3_send_channel_id(SSL *s)
- {
- uint8_t *d;
- int ret = -1, public_key_len;
- EVP_MD_CTX md_ctx;
- size_t sig_len;
- ECDSA_SIG *sig = NULL;
- uint8_t *public_key = NULL, *derp, *der_sig = NULL;
+int ssl3_send_client_key_exchange(SSL *s) {
+ uint8_t *p;
+ int n = 0;
+ unsigned long alg_k;
+ unsigned long alg_a;
+ uint8_t *q;
+ EVP_PKEY *pkey = NULL;
+ EC_KEY *clnt_ecdh = NULL;
+ const EC_POINT *srvr_ecpoint = NULL;
+ EVP_PKEY *srvr_pub_pkey = NULL;
+ uint8_t *encodedPoint = NULL;
+ int encoded_pt_len = 0;
+ BN_CTX *bn_ctx = NULL;
+ unsigned int psk_len = 0;
+ uint8_t psk[PSK_MAX_PSK_LEN];
+ uint8_t *pms = NULL;
+ size_t pms_len = 0;
- if (s->state != SSL3_ST_CW_CHANNEL_ID_A)
- return ssl_do_write(s);
+ if (s->state == SSL3_ST_CW_KEY_EXCH_A) {
+ p = ssl_handshake_start(s);
- if (!s->tlsext_channel_id_private && s->ctx->channel_id_cb)
- {
- EVP_PKEY *key = NULL;
- s->ctx->channel_id_cb(s, &key);
- if (key != NULL)
- {
- s->tlsext_channel_id_private = key;
- }
- }
- if (!s->tlsext_channel_id_private)
- {
- s->rwstate=SSL_CHANNEL_ID_LOOKUP;
- return (-1);
- }
- s->rwstate=SSL_NOTHING;
+ alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+ alg_a = s->s3->tmp.new_cipher->algorithm_auth;
- d = ssl_handshake_start(s);
- if (s->s3->tlsext_channel_id_new)
- s2n(TLSEXT_TYPE_channel_id_new, d);
- else
- s2n(TLSEXT_TYPE_channel_id, d);
- s2n(TLSEXT_CHANNEL_ID_SIZE, d);
+ /* If using a PSK key exchange, prepare the pre-shared key. */
+ if (alg_a & SSL_aPSK) {
+ char identity[PSK_MAX_IDENTITY_LEN + 1];
+ size_t identity_len;
- EVP_MD_CTX_init(&md_ctx);
+ if (s->psk_client_callback == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ SSL_R_PSK_NO_CLIENT_CB);
+ goto err;
+ }
- public_key_len = i2d_PublicKey(s->tlsext_channel_id_private, NULL);
- if (public_key_len <= 0)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, SSL_R_CANNOT_SERIALIZE_PUBLIC_KEY);
- goto err;
- }
- /* i2d_PublicKey will produce an ANSI X9.62 public key which, for a
- * P-256 key, is 0x04 (meaning uncompressed) followed by the x and y
- * field elements as 32-byte, big-endian numbers. */
- if (public_key_len != 65)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, SSL_R_CHANNEL_ID_NOT_P256);
- goto err;
- }
- public_key = OPENSSL_malloc(public_key_len);
- if (!public_key)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, ERR_R_MALLOC_FAILURE);
- goto err;
- }
+ memset(identity, 0, sizeof(identity));
+ psk_len =
+ s->psk_client_callback(s, s->s3->tmp.peer_psk_identity_hint, identity,
+ sizeof(identity), psk, sizeof(psk));
+ if (psk_len > PSK_MAX_PSK_LEN) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ } else if (psk_len == 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ SSL_R_PSK_IDENTITY_NOT_FOUND);
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ goto err;
+ }
- derp = public_key;
- i2d_PublicKey(s->tlsext_channel_id_private, &derp);
+ identity_len = OPENSSL_strnlen(identity, sizeof(identity));
+ if (identity_len > PSK_MAX_IDENTITY_LEN) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
- if (EVP_DigestSignInit(&md_ctx, NULL, EVP_sha256(), NULL,
- s->tlsext_channel_id_private) != 1)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, SSL_R_EVP_DIGESTSIGNINIT_FAILED);
- goto err;
- }
+ if (s->session->psk_identity != NULL) {
+ OPENSSL_free(s->session->psk_identity);
+ }
- if (!tls1_channel_id_hash(&md_ctx, s))
- goto err;
+ s->session->psk_identity = BUF_strdup(identity);
+ if (s->session->psk_identity == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
- if (!EVP_DigestSignFinal(&md_ctx, NULL, &sig_len))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, SSL_R_EVP_DIGESTSIGNFINAL_FAILED);
- goto err;
- }
+ /* Write out psk_identity. */
+ s2n(identity_len, p);
+ memcpy(p, identity, identity_len);
+ p += identity_len;
+ n = 2 + identity_len;
+ }
- der_sig = OPENSSL_malloc(sig_len);
- if (!der_sig)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, ERR_R_MALLOC_FAILURE);
- goto err;
- }
+ /* Depending on the key exchange method, compute |pms| and |pms_len|. */
+ if (alg_k & SSL_kRSA) {
+ RSA *rsa;
+ size_t enc_pms_len;
- if (!EVP_DigestSignFinal(&md_ctx, der_sig, &sig_len))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, SSL_R_EVP_DIGESTSIGNFINAL_FAILED);
- goto err;
- }
+ pms_len = SSL_MAX_MASTER_KEY_LENGTH;
+ pms = OPENSSL_malloc(pms_len);
+ if (pms == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
- derp = der_sig;
- sig = d2i_ECDSA_SIG(NULL, (const unsigned char**) &derp, sig_len);
- if (sig == NULL)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, SSL_R_D2I_ECDSA_SIG);
- goto err;
- }
+ if (s->session->sess_cert == NULL) {
+ /* We should always have a server certificate with SSL_kRSA. */
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
- /* The first byte of public_key will be 0x4, denoting an uncompressed key. */
- memcpy(d, public_key + 1, 64);
- d += 64;
- if (!BN_bn2bin_padded(d, 32, sig->r) ||
- !BN_bn2bin_padded(d + 32, 32, sig->s))
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, ERR_R_INTERNAL_ERROR);
- goto err;
- }
+ pkey = X509_get_pubkey(
+ s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
+ if (pkey == NULL ||
+ pkey->type != EVP_PKEY_RSA ||
+ pkey->pkey.rsa == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_INTERNAL_ERROR);
+ if (pkey != NULL) {
+ EVP_PKEY_free(pkey);
+ }
+ goto err;
+ }
- ssl_set_handshake_header(s, SSL3_MT_ENCRYPTED_EXTENSIONS,
- 2 + 2 + TLSEXT_CHANNEL_ID_SIZE);
- s->state = SSL3_ST_CW_CHANNEL_ID_B;
+ rsa = pkey->pkey.rsa;
+ EVP_PKEY_free(pkey);
- ret = ssl_do_write(s);
+ pms[0] = s->client_version >> 8;
+ pms[1] = s->client_version & 0xff;
+ if (!RAND_bytes(&pms[2], SSL_MAX_MASTER_KEY_LENGTH - 2)) {
+ goto err;
+ }
+
+ s->session->master_key_length = SSL_MAX_MASTER_KEY_LENGTH;
+
+ q = p;
+ /* In TLS and beyond, reserve space for the length prefix. */
+ if (s->version > SSL3_VERSION) {
+ p += 2;
+ n += 2;
+ }
+ if (!RSA_encrypt(rsa, &enc_pms_len, p, RSA_size(rsa), pms, pms_len,
+ RSA_PKCS1_PADDING)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ SSL_R_BAD_RSA_ENCRYPT);
+ goto err;
+ }
+ n += enc_pms_len;
+
+ /* Log the premaster secret, if logging is enabled. */
+ if (!ssl_ctx_log_rsa_client_key_exchange(s->ctx, p, enc_pms_len, pms,
+ pms_len)) {
+ goto err;
+ }
+
+ /* Fill in the length prefix. */
+ if (s->version > SSL3_VERSION) {
+ s2n(enc_pms_len, q);
+ }
+ } else if (alg_k & SSL_kEDH) {
+ DH *dh_srvr, *dh_clnt;
+ SESS_CERT *scert = s->session->sess_cert;
+ int dh_len;
+ size_t pub_len;
+
+ if (scert == NULL) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ SSL_R_UNEXPECTED_MESSAGE);
+ goto err;
+ }
+
+ if (scert->peer_dh_tmp == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ dh_srvr = scert->peer_dh_tmp;
+
+ /* generate a new random key */
+ dh_clnt = DHparams_dup(dh_srvr);
+ if (dh_clnt == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_DH_LIB);
+ goto err;
+ }
+ if (!DH_generate_key(dh_clnt)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_DH_LIB);
+ DH_free(dh_clnt);
+ goto err;
+ }
+
+ pms_len = DH_size(dh_clnt);
+ pms = OPENSSL_malloc(pms_len);
+ if (pms == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ DH_free(dh_clnt);
+ goto err;
+ }
+
+ dh_len = DH_compute_key(pms, dh_srvr->pub_key, dh_clnt);
+ if (dh_len <= 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_DH_LIB);
+ DH_free(dh_clnt);
+ goto err;
+ }
+ pms_len = dh_len;
+
+ /* send off the data */
+ pub_len = BN_num_bytes(dh_clnt->pub_key);
+ s2n(pub_len, p);
+ BN_bn2bin(dh_clnt->pub_key, p);
+ n += 2 + pub_len;
+
+ DH_free(dh_clnt);
+ } else if (alg_k & SSL_kEECDH) {
+ const EC_GROUP *srvr_group = NULL;
+ EC_KEY *tkey;
+ int field_size = 0, ecdh_len;
+
+ if (s->session->sess_cert == NULL) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ SSL_R_UNEXPECTED_MESSAGE);
+ goto err;
+ }
+
+ if (s->session->sess_cert->peer_ecdh_tmp == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ tkey = s->session->sess_cert->peer_ecdh_tmp;
+
+ srvr_group = EC_KEY_get0_group(tkey);
+ srvr_ecpoint = EC_KEY_get0_public_key(tkey);
+ if (srvr_group == NULL || srvr_ecpoint == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ clnt_ecdh = EC_KEY_new();
+ if (clnt_ecdh == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!EC_KEY_set_group(clnt_ecdh, srvr_group)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_EC_LIB);
+ goto err;
+ }
+
+ /* Generate a new ECDH key pair */
+ if (!EC_KEY_generate_key(clnt_ecdh)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_ECDH_LIB);
+ goto err;
+ }
+
+ field_size = EC_GROUP_get_degree(srvr_group);
+ if (field_size <= 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_ECDH_LIB);
+ goto err;
+ }
+
+ pms_len = (field_size + 7) / 8;
+ pms = OPENSSL_malloc(pms_len);
+ if (pms == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ ecdh_len = ECDH_compute_key(pms, pms_len, srvr_ecpoint, clnt_ecdh, NULL);
+ if (ecdh_len <= 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_ECDH_LIB);
+ goto err;
+ }
+ pms_len = ecdh_len;
+
+ /* First check the size of encoding and allocate memory accordingly. */
+ encoded_pt_len =
+ EC_POINT_point2oct(srvr_group, EC_KEY_get0_public_key(clnt_ecdh),
+ POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
+
+ encodedPoint =
+ (uint8_t *)OPENSSL_malloc(encoded_pt_len * sizeof(uint8_t));
+ bn_ctx = BN_CTX_new();
+ if (encodedPoint == NULL || bn_ctx == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* Encode the public key */
+ encoded_pt_len = EC_POINT_point2oct(
+ srvr_group, EC_KEY_get0_public_key(clnt_ecdh),
+ POINT_CONVERSION_UNCOMPRESSED, encodedPoint, encoded_pt_len, bn_ctx);
+
+ *p = encoded_pt_len; /* length of encoded point */
+ /* Encoded point will be copied here */
+ p += 1;
+ n += 1;
+ /* copy the point */
+ memcpy(p, encodedPoint, encoded_pt_len);
+ /* increment n to account for length field */
+ n += encoded_pt_len;
+
+ /* Free allocated memory */
+ BN_CTX_free(bn_ctx);
+ bn_ctx = NULL;
+ OPENSSL_free(encodedPoint);
+ encodedPoint = NULL;
+ EC_KEY_free(clnt_ecdh);
+ clnt_ecdh = NULL;
+ EVP_PKEY_free(srvr_pub_pkey);
+ srvr_pub_pkey = NULL;
+ } else if (alg_k & SSL_kPSK) {
+ /* For plain PSK, other_secret is a block of 0s with the same length as
+ * the pre-shared key. */
+ pms_len = psk_len;
+ pms = OPENSSL_malloc(pms_len);
+ if (pms == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ memset(pms, 0, pms_len);
+ } else {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* For a PSK cipher suite, other_secret is combined with the pre-shared
+ * key. */
+ if (alg_a & SSL_aPSK) {
+ CBB cbb, child;
+ uint8_t *new_pms;
+ size_t new_pms_len;
+
+ if (!CBB_init(&cbb, 2 + psk_len + 2 + pms_len)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
+ !CBB_add_bytes(&child, pms, pms_len) ||
+ !CBB_add_u16_length_prefixed(&cbb, &child) ||
+ !CBB_add_bytes(&child, psk, psk_len) ||
+ !CBB_finish(&cbb, &new_pms, &new_pms_len)) {
+ CBB_cleanup(&cbb);
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange,
+ ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ OPENSSL_cleanse(pms, pms_len);
+ OPENSSL_free(pms);
+ pms = new_pms;
+ pms_len = new_pms_len;
+ }
+
+ /* The message must be added to the finished hash before calculating the
+ * master secret. */
+ ssl_set_handshake_header(s, SSL3_MT_CLIENT_KEY_EXCHANGE, n);
+ s->state = SSL3_ST_CW_KEY_EXCH_B;
+
+ s->session->master_key_length = s->enc_method->generate_master_secret(
+ s, s->session->master_key, pms, pms_len);
+ if (s->session->master_key_length == 0) {
+ goto err;
+ }
+ s->session->extended_master_secret = s->s3->tmp.extended_master_secret;
+ OPENSSL_cleanse(pms, pms_len);
+ OPENSSL_free(pms);
+ }
+
+ /* SSL3_ST_CW_KEY_EXCH_B */
+ return s->enc_method->do_write(s);
err:
- EVP_MD_CTX_cleanup(&md_ctx);
- if (public_key)
- OPENSSL_free(public_key);
- if (der_sig)
- OPENSSL_free(der_sig);
- if (sig)
- ECDSA_SIG_free(sig);
+ 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);
+ if (pms) {
+ OPENSSL_cleanse(pms, pms_len);
+ OPENSSL_free(pms);
+ }
+ return -1;
+}
- return ret;
- }
+int ssl3_send_cert_verify(SSL *s) {
+ uint8_t *buf, *p;
+ const EVP_MD *md = NULL;
+ uint8_t digest[EVP_MAX_MD_SIZE];
+ size_t digest_length;
+ EVP_PKEY *pkey;
+ EVP_PKEY_CTX *pctx = NULL;
+ size_t signature_length = 0;
+ unsigned long n = 0;
-int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey)
- {
- int i = 0;
- if (s->ctx->client_cert_cb)
- i = s->ctx->client_cert_cb(s,px509,ppkey);
- return i;
- }
+ buf = (uint8_t *)s->init_buf->data;
+
+ if (s->state == SSL3_ST_CW_CERT_VRFY_A) {
+ p = ssl_handshake_start(s);
+ pkey = s->cert->key->privatekey;
+
+ /* Write out the digest type if needbe. */
+ if (SSL_USE_SIGALGS(s)) {
+ md = tls1_choose_signing_digest(s, pkey);
+ if (!tls12_get_sigandhash(p, pkey, md)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_cert_verify, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ p += 2;
+ n += 2;
+ }
+
+ /* 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, free_handshake_buffer)) {
+ goto err;
+ }
+
+ /* Sign the digest. */
+ pctx = EVP_PKEY_CTX_new(pkey, NULL);
+ if (pctx == NULL) {
+ goto err;
+ }
+
+ /* Initialize the EVP_PKEY_CTX and determine the size of the signature. */
+ 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_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_cert_verify, SSL_R_DATA_LENGTH_TOO_LONG);
+ goto err;
+ }
+
+ if (!EVP_PKEY_sign(pctx, &p[2], &signature_length, digest, digest_length)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_cert_verify, ERR_R_EVP_LIB);
+ goto err;
+ }
+
+ s2n(signature_length, p);
+ n += signature_length + 2;
+
+ ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_VERIFY, n);
+ s->state = SSL3_ST_CW_CERT_VRFY_B;
+ }
+
+ EVP_PKEY_CTX_free(pctx);
+ return ssl_do_write(s);
+
+err:
+ EVP_PKEY_CTX_free(pctx);
+ return -1;
+}
+
+/* ssl3_has_client_certificate returns true if a client certificate is
+ * configured. */
+static int ssl3_has_client_certificate(SSL *s) {
+ return s->cert && s->cert->key->x509 && s->cert->key->privatekey;
+}
+
+int ssl3_send_client_certificate(SSL *s) {
+ X509 *x509 = NULL;
+ EVP_PKEY *pkey = NULL;
+ int i;
+
+ if (s->state == SSL3_ST_CW_CERT_A) {
+ /* Let cert callback update client certificates if required */
+ if (s->cert->cert_cb) {
+ i = s->cert->cert_cb(s, s->cert->cert_cb_arg);
+ if (i < 0) {
+ s->rwstate = SSL_X509_LOOKUP;
+ return -1;
+ }
+ if (i == 0) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ return 0;
+ }
+ s->rwstate = SSL_NOTHING;
+ }
+
+ if (ssl3_has_client_certificate(s)) {
+ s->state = SSL3_ST_CW_CERT_C;
+ } else {
+ s->state = SSL3_ST_CW_CERT_B;
+ }
+ }
+
+ /* We need to get a client cert */
+ if (s->state == SSL3_ST_CW_CERT_B) {
+ /* If we get an error, we need to:
+ * ssl->rwstate=SSL_X509_LOOKUP; return(-1);
+ * We then get retried later */
+ i = ssl_do_client_cert_cb(s, &x509, &pkey);
+ if (i < 0) {
+ s->rwstate = SSL_X509_LOOKUP;
+ return -1;
+ }
+ s->rwstate = SSL_NOTHING;
+ if (i == 1 && pkey != NULL && x509 != NULL) {
+ s->state = SSL3_ST_CW_CERT_B;
+ if (!SSL_use_certificate(s, x509) || !SSL_use_PrivateKey(s, pkey)) {
+ i = 0;
+ }
+ } else if (i == 1) {
+ i = 0;
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_certificate,
+ SSL_R_BAD_DATA_RETURNED_BY_CALLBACK);
+ }
+
+ if (x509 != NULL) {
+ X509_free(x509);
+ }
+ if (pkey != NULL) {
+ EVP_PKEY_free(pkey);
+ }
+ if (i && !ssl3_has_client_certificate(s)) {
+ i = 0;
+ }
+ if (i == 0) {
+ if (s->version == SSL3_VERSION) {
+ s->s3->tmp.cert_req = 0;
+ ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_CERTIFICATE);
+ return 1;
+ } else {
+ s->s3->tmp.cert_req = 2;
+ }
+ }
+
+ /* Ok, we have a cert */
+ s->state = SSL3_ST_CW_CERT_C;
+ }
+
+ if (s->state == SSL3_ST_CW_CERT_C) {
+ s->state = SSL3_ST_CW_CERT_D;
+ ssl3_output_cert_chain(s, (s->s3->tmp.cert_req == 2) ? NULL : s->cert->key);
+ }
+
+ /* SSL3_ST_CW_CERT_D */
+ return ssl_do_write(s);
+}
+
+#define has_bits(i, m) (((i) & (m)) == (m))
+
+int ssl3_check_cert_and_algorithm(SSL *s) {
+ int i, idx;
+ long alg_k, alg_a;
+ EVP_PKEY *pkey = NULL;
+ SESS_CERT *sc;
+ DH *dh;
+
+ /* we don't have a certificate */
+ if (!ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) {
+ return 1;
+ }
+
+ alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
+ alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+
+ sc = s->session->sess_cert;
+ if (sc == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_check_cert_and_algorithm, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ dh = s->session->sess_cert->peer_dh_tmp;
+
+ /* This is the passed certificate */
+
+ idx = sc->peer_cert_type;
+ if (idx == SSL_PKEY_ECC) {
+ if (ssl_check_srvr_ecc_cert_and_alg(sc->peer_pkeys[idx].x509, s) == 0) {
+ /* check failed */
+ OPENSSL_PUT_ERROR(SSL, ssl3_check_cert_and_algorithm, SSL_R_BAD_ECC_CERT);
+ goto f_err;
+ } else {
+ return 1;
+ }
+ } else if (alg_a & SSL_aECDSA) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_check_cert_and_algorithm,
+ SSL_R_MISSING_ECDSA_SIGNING_CERT);
+ goto f_err;
+ }
+ pkey = X509_get_pubkey(sc->peer_pkeys[idx].x509);
+ i = X509_certificate_type(sc->peer_pkeys[idx].x509, pkey);
+ EVP_PKEY_free(pkey);
+
+ /* Check that we have a certificate if we require one */
+ if ((alg_a & SSL_aRSA) && !has_bits(i, EVP_PK_RSA | EVP_PKT_SIGN)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_check_cert_and_algorithm,
+ SSL_R_MISSING_RSA_SIGNING_CERT);
+ goto f_err;
+ }
+
+ if ((alg_k & SSL_kRSA) && !has_bits(i, EVP_PK_RSA | EVP_PKT_ENC)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_check_cert_and_algorithm,
+ SSL_R_MISSING_RSA_ENCRYPTING_CERT);
+ goto f_err;
+ }
+
+ 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;
+ }
+
+ return 1;
+
+f_err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+err:
+ return 0;
+}
+
+int ssl3_send_next_proto(SSL *s) {
+ unsigned int len, padding_len;
+ uint8_t *d, *p;
+
+ if (s->state == SSL3_ST_CW_NEXT_PROTO_A) {
+ len = s->next_proto_negotiated_len;
+ padding_len = 32 - ((len + 2) % 32);
+
+ d = p = ssl_handshake_start(s);
+ *(p++) = len;
+ memcpy(p, s->next_proto_negotiated, len);
+ p += len;
+ *(p++) = padding_len;
+ memset(p, 0, padding_len);
+ p += padding_len;
+
+ ssl_set_handshake_header(s, SSL3_MT_NEXT_PROTO, p - d);
+ s->state = SSL3_ST_CW_NEXT_PROTO_B;
+ }
+
+ return ssl_do_write(s);
+}
+
+int ssl3_send_channel_id(SSL *s) {
+ uint8_t *d;
+ int ret = -1, public_key_len;
+ EVP_MD_CTX md_ctx;
+ size_t sig_len;
+ ECDSA_SIG *sig = NULL;
+ uint8_t *public_key = NULL, *derp, *der_sig = NULL;
+
+ if (s->state != SSL3_ST_CW_CHANNEL_ID_A) {
+ return ssl_do_write(s);
+ }
+
+ if (!s->tlsext_channel_id_private && s->ctx->channel_id_cb) {
+ EVP_PKEY *key = NULL;
+ s->ctx->channel_id_cb(s, &key);
+ if (key != NULL) {
+ s->tlsext_channel_id_private = key;
+ }
+ }
+
+ if (!s->tlsext_channel_id_private) {
+ s->rwstate = SSL_CHANNEL_ID_LOOKUP;
+ return -1;
+ }
+ s->rwstate = SSL_NOTHING;
+
+ d = ssl_handshake_start(s);
+ if (s->s3->tlsext_channel_id_new) {
+ s2n(TLSEXT_TYPE_channel_id_new, d);
+ } else {
+ s2n(TLSEXT_TYPE_channel_id, d);
+ }
+ s2n(TLSEXT_CHANNEL_ID_SIZE, d);
+
+ EVP_MD_CTX_init(&md_ctx);
+
+ public_key_len = i2d_PublicKey(s->tlsext_channel_id_private, NULL);
+ if (public_key_len <= 0) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id,
+ SSL_R_CANNOT_SERIALIZE_PUBLIC_KEY);
+ goto err;
+ }
+
+ /* i2d_PublicKey will produce an ANSI X9.62 public key which, for a
+ * P-256 key, is 0x04 (meaning uncompressed) followed by the x and y
+ * field elements as 32-byte, big-endian numbers. */
+ if (public_key_len != 65) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, SSL_R_CHANNEL_ID_NOT_P256);
+ goto err;
+ }
+ public_key = OPENSSL_malloc(public_key_len);
+ if (!public_key) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ derp = public_key;
+ i2d_PublicKey(s->tlsext_channel_id_private, &derp);
+
+ if (EVP_DigestSignInit(&md_ctx, NULL, EVP_sha256(), NULL,
+ s->tlsext_channel_id_private) != 1) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id,
+ SSL_R_EVP_DIGESTSIGNINIT_FAILED);
+ goto err;
+ }
+
+ if (!tls1_channel_id_hash(&md_ctx, s)) {
+ goto err;
+ }
+
+ if (!EVP_DigestSignFinal(&md_ctx, NULL, &sig_len)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id,
+ SSL_R_EVP_DIGESTSIGNFINAL_FAILED);
+ goto err;
+ }
+
+ der_sig = OPENSSL_malloc(sig_len);
+ if (!der_sig) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!EVP_DigestSignFinal(&md_ctx, der_sig, &sig_len)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id,
+ SSL_R_EVP_DIGESTSIGNFINAL_FAILED);
+ goto err;
+ }
+
+ derp = der_sig;
+ sig = d2i_ECDSA_SIG(NULL, (const uint8_t **)&derp, sig_len);
+ if (sig == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, SSL_R_D2I_ECDSA_SIG);
+ goto err;
+ }
+
+ /* The first byte of public_key will be 0x4, denoting an uncompressed key. */
+ memcpy(d, public_key + 1, 64);
+ d += 64;
+ if (!BN_bn2bin_padded(d, 32, sig->r) ||
+ !BN_bn2bin_padded(d + 32, 32, sig->s)) {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_channel_id, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ ssl_set_handshake_header(s, SSL3_MT_ENCRYPTED_EXTENSIONS,
+ 2 + 2 + TLSEXT_CHANNEL_ID_SIZE);
+ s->state = SSL3_ST_CW_CHANNEL_ID_B;
+
+ ret = ssl_do_write(s);
+
+err:
+ EVP_MD_CTX_cleanup(&md_ctx);
+ if (public_key) {
+ OPENSSL_free(public_key);
+ }
+ if (der_sig) {
+ OPENSSL_free(der_sig);
+ }
+ if (sig) {
+ ECDSA_SIG_free(sig);
+ }
+
+ return ret;
+}
+
+int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey) {
+ int i = 0;
+ if (s->ctx->client_cert_cb) {
+ i = s->ctx->client_cert_cb(s, px509, ppkey);
+ }
+ return i;
+}