/*
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* ====================================================================
* Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
* ECC cipher suite support in OpenSSL originally developed by
* SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
*/
#include <limits.h>
#include <string.h>
#include <stdio.h>
#include "../ssl_locl.h"
#include "statem_locl.h"
#include <openssl/buffer.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
/*
* send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or
* SSL3_RT_CHANGE_CIPHER_SPEC)
*/
int ssl3_do_write(SSL *s, int type)
{
int ret;
ret = ssl3_write_bytes(s, type, &s->init_buf->data[s->init_off],
s->init_num);
if (ret < 0)
return (-1);
if (type == SSL3_RT_HANDSHAKE)
/*
* should not be done for 'Hello Request's, but in that case we'll
* ignore the result anyway
*/
if (!ssl3_finish_mac(s,
(unsigned char *)&s->init_buf->data[s->init_off],
ret))
return -1;
if (ret == s->init_num) {
if (s->msg_callback)
s->msg_callback(1, s->version, type, s->init_buf->data,
(size_t)(s->init_off + s->init_num), s,
s->msg_callback_arg);
return (1);
}
s->init_off += ret;
s->init_num -= ret;
return (0);
}
int tls_construct_finished(SSL *s, const char *sender, int slen)
{
unsigned char *p;
int i;
unsigned long l;
p = ssl_handshake_start(s);
i = s->method->ssl3_enc->final_finish_mac(s,
sender, slen,
s->s3->tmp.finish_md);
if (i <= 0)
return 0;
s->s3->tmp.finish_md_len = i;
memcpy(p, s->s3->tmp.finish_md, i);
l = i;
/*
* Copy the finished so we can use it for renegotiation checks
*/
if (!s->server) {
OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
memcpy(s->s3->previous_client_finished, s->s3->tmp.finish_md, i);
s->s3->previous_client_finished_len = i;
} else {
OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
memcpy(s->s3->previous_server_finished, s->s3->tmp.finish_md, i);
s->s3->previous_server_finished_len = i;
}
if (!ssl_set_handshake_header(s, SSL3_MT_FINISHED, l)) {
SSLerr(SSL_F_TLS_CONSTRUCT_FINISHED, ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
#ifndef OPENSSL_NO_NEXTPROTONEG
/*
* ssl3_take_mac calculates the Finished MAC for the handshakes messages seen
* to far.
*/
static void ssl3_take_mac(SSL *s)
{
const char *sender;
int slen;
/*
* If no new cipher setup return immediately: other functions will set
* the appropriate error.
*/
if (s->s3->tmp.new_cipher == NULL)
return;
if (!s->server) {
sender = s->method->