Reformat the rest of ssl/. Change-Id: I7dc264f7e29b3ba8be4c717583467edf71bf8dd9
diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c index d675fe6..95737a7 100644 --- a/ssl/s3_pkt.c +++ b/ssl/s3_pkt.c
@@ -119,160 +119,139 @@ #include "ssl_locl.h" -static int do_ssl3_write(SSL *s, int type, const unsigned char *buf, - unsigned int len, char fragment, char is_fragment); + +static int do_ssl3_write(SSL *s, int type, const uint8_t *buf, unsigned int len, + char fragment, char is_fragment); static int ssl3_get_record(SSL *s); -int ssl3_read_n(SSL *s, int n, int max, int extend) - { - /* If extend == 0, obtain new n-byte packet; if extend == 1, increase - * packet by another n bytes. - * The packet will be in the sub-array of s->s3->rbuf.buf specified - * by s->packet and s->packet_length. - * (If s->read_ahead is set, 'max' bytes may be stored in rbuf - * [plus s->packet_length bytes if extend == 1].) - */ - int i,len,left; - long align=0; - unsigned char *pkt; - SSL3_BUFFER *rb; +int ssl3_read_n(SSL *s, int n, int max, int extend) { + /* If |extend| is 0, obtain new n-byte packet; + * if |extend| is 1, increase packet by another n bytes. + * + * The packet will be in the sub-array of |s->s3->rbuf.buf| specified by + * |s->packet| and |s->packet_length|. (If |s->read_ahead| is set, |max| + * bytes may be stored in |rbuf| (plus |s->packet_length| bytes if |extend| + * is one.) */ + int i, len, left; + long align = 0; + uint8_t *pkt; + SSL3_BUFFER *rb; - if (n <= 0) return n; + if (n <= 0) { + return n; + } - rb = &(s->s3->rbuf); - if (rb->buf == NULL) - if (!ssl3_setup_read_buffer(s)) - return -1; + rb = &s->s3->rbuf; + if (rb->buf == NULL && !ssl3_setup_read_buffer(s)) { + return -1; + } - left = rb->left; -#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0 - align = (long)rb->buf + SSL3_RT_HEADER_LENGTH; - align = (-align)&(SSL3_ALIGN_PAYLOAD-1); -#endif + left = rb->left; - if (!extend) - { - /* start with empty packet ... */ - if (left == 0) - rb->offset = align; - else if (align != 0 && left >= SSL3_RT_HEADER_LENGTH) - { - /* check if next packet length is large - * enough to justify payload alignment... */ - pkt = rb->buf + rb->offset; - if (pkt[0] == SSL3_RT_APPLICATION_DATA - && (pkt[3]<<8|pkt[4]) >= 128) - { - /* Note that even if packet is corrupted - * and its length field is insane, we can - * only be led to wrong decision about - * whether memmove will occur or not. - * Header values has no effect on memmove - * arguments and therefore no buffer - * overrun can be triggered. */ - memmove (rb->buf+align,pkt,left); - rb->offset = align; - } - } - s->packet = rb->buf + rb->offset; - s->packet_length = 0; - /* ... now we can act as if 'extend' was set */ - } + align = (long)rb->buf + SSL3_RT_HEADER_LENGTH; + align = (-align) & (SSL3_ALIGN_PAYLOAD - 1); - /* For DTLS/UDP reads should not span multiple packets - * because the read operation returns the whole packet - * at once (as long as it fits into the buffer). */ - if (SSL_IS_DTLS(s)) - { - if (left > 0 && n > left) - n = left; - } + if (!extend) { + /* start with empty packet ... */ + if (left == 0) { + rb->offset = align; + } else if (align != 0 && left >= SSL3_RT_HEADER_LENGTH) { + /* check if next packet length is large enough to justify payload + * alignment... */ + pkt = rb->buf + rb->offset; + if (pkt[0] == SSL3_RT_APPLICATION_DATA && (pkt[3] << 8 | pkt[4]) >= 128) { + /* Note that even if packet is corrupted and its length field is + * insane, we can only be led to wrong decision about whether memmove + * will occur or not. Header values has no effect on memmove arguments + * and therefore no buffer overrun can be triggered. */ + memmove(rb->buf + align, pkt, left); + rb->offset = align; + } + } + s->packet = rb->buf + rb->offset; + s->packet_length = 0; + /* ... now we can act as if 'extend' was set */ + } - /* if there is enough in the buffer from a previous read, take some */ - if (left >= n) - { - s->packet_length+=n; - rb->left=left-n; - rb->offset+=n; - return(n); - } + /* For DTLS/UDP reads should not span multiple packets because the read + * operation returns the whole packet at once (as long as it fits into the + * buffer). */ + if (SSL_IS_DTLS(s) && left > 0 && n > left) { + n = left; + } - /* else we need to read more data */ + /* if there is enough in the buffer from a previous read, take some */ + if (left >= n) { + s->packet_length += n; + rb->left = left - n; + rb->offset += n; + return n; + } - len = s->packet_length; - pkt = rb->buf+align; - /* Move any available bytes to front of buffer: - * 'len' bytes already pointed to by 'packet', - * 'left' extra ones at the end */ - if (s->packet != pkt) /* len > 0 */ - { - memmove(pkt, s->packet, len+left); - s->packet = pkt; - rb->offset = len + align; - } + /* else we need to read more data */ - if (n > (int)(rb->len - rb->offset)) /* does not happen */ - { - OPENSSL_PUT_ERROR(SSL, ssl3_read_n, ERR_R_INTERNAL_ERROR); - return -1; - } + len = s->packet_length; + pkt = rb->buf + align; + /* Move any available bytes to front of buffer: |len| bytes already pointed + * to by |packet|, |left| extra ones at the end. */ + if (s->packet != pkt) { + /* len > 0 */ + memmove(pkt, s->packet, len + left); + s->packet = pkt; + rb->offset = len + align; + } - if (!s->read_ahead) - /* ignore max parameter */ - max = n; - else - { - if (max < n) - max = n; - if (max > (int)(rb->len - rb->offset)) - max = rb->len - rb->offset; - } + assert(n <= (int)(rb->len - rb->offset)); - while (left < n) - { - /* Now we have len+left bytes at the front of s->s3->rbuf.buf - * and need to read in more until we have len+n (up to - * len+max if possible) */ + if (!s->read_ahead) { + /* ignore max parameter */ + max = n; + } else { + if (max < n) { + max = n; + } + if (max > (int)(rb->len - rb->offset)) { + max = rb->len - rb->offset; + } + } - ERR_clear_system_error(); - if (s->rbio != NULL) - { - s->rwstate=SSL_READING; - i=BIO_read(s->rbio,pkt+len+left, max-left); - } - else - { - OPENSSL_PUT_ERROR(SSL, ssl3_read_n, SSL_R_READ_BIO_NOT_SET); - i = -1; - } + while (left < n) { + /* Now we have len+left bytes at the front of s->s3->rbuf.buf and need to + * read in more until we have len+n (up to len+max if possible). */ + ERR_clear_system_error(); + if (s->rbio != NULL) { + s->rwstate = SSL_READING; + i = BIO_read(s->rbio, pkt + len + left, max - left); + } else { + OPENSSL_PUT_ERROR(SSL, ssl3_read_n, SSL_R_READ_BIO_NOT_SET); + i = -1; + } - if (i <= 0) - { - rb->left = left; - if (s->mode & SSL_MODE_RELEASE_BUFFERS && - !SSL_IS_DTLS(s)) - if (len+left == 0) - ssl3_release_read_buffer(s); - return(i); - } - left+=i; - /* reads should *never* span multiple packets for DTLS because - * the underlying transport protocol is message oriented as opposed - * to byte oriented as in the TLS case. */ - if (SSL_IS_DTLS(s)) - { - if (n > left) - n = left; /* makes the while condition false */ - } - } + if (i <= 0) { + rb->left = left; + if (s->mode & SSL_MODE_RELEASE_BUFFERS && !SSL_IS_DTLS(s) && + len + left == 0) { + ssl3_release_read_buffer(s); + } + return i; + } + left += i; + /* reads should *never* span multiple packets for DTLS because the + * underlying transport protocol is message oriented as opposed to byte + * oriented as in the TLS case. */ + if (SSL_IS_DTLS(s) && n > left) { + n = left; /* makes the while condition false */ + } + } - /* done reading, now the book-keeping */ - rb->offset += n; - rb->left = left - n; - s->packet_length += n; - s->rwstate=SSL_NOTHING; - return(n); - } + /* done reading, now the book-keeping */ + rb->offset += n; + rb->left = left - n; + s->packet_length += n; + s->rwstate = SSL_NOTHING; + + return n; +} /* MAX_EMPTY_RECORDS defines the number of consecutive, empty records that will * be processed per call to ssl3_get_record. Without this limit an attacker @@ -280,632 +259,548 @@ * ssl3_get_record to loop forever. */ #define MAX_EMPTY_RECORDS 32 -/* Call this to get a new input record. - * It will return <= 0 if more data is needed, normally due to an error - * or non-blocking IO. - * When it finishes, one packet has been decoded and can be found in +/* Call this to get a new input record. It will return <= 0 if more data is + * needed, normally due to an error or non-blocking IO. When it finishes, one + * packet has been decoded and can be found in * ssl->s3->rrec.type - is the type of record - * ssl->s3->rrec.data, - data - * ssl->s3->rrec.length, - number of bytes - */ + * ssl->s3->rrec.data - data + * ssl->s3->rrec.length - number of bytes */ /* used only by ssl3_read_bytes */ -static int ssl3_get_record(SSL *s) - { - int ssl_major,ssl_minor,al; - int enc_err,n,i,ret= -1; - SSL3_RECORD *rr; - SSL_SESSION *sess; - unsigned char *p; - unsigned char md[EVP_MAX_MD_SIZE]; - short version; - unsigned mac_size, orig_len; - size_t extra; - unsigned empty_record_count = 0; +static int ssl3_get_record(SSL *s) { + int ssl_major, ssl_minor, al; + int enc_err, n, i, ret = -1; + SSL3_RECORD *rr; + SSL_SESSION *sess; + uint8_t *p; + uint8_t md[EVP_MAX_MD_SIZE]; + short version; + unsigned mac_size, orig_len; + size_t extra; + unsigned empty_record_count = 0; - rr= &(s->s3->rrec); - sess=s->session; + rr = &s->s3->rrec; + sess = s->session; - if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER) - extra=SSL3_RT_MAX_EXTRA; - else - extra=0; - if (extra && !s->s3->init_extra) - { - /* An application error: SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER - * set after ssl3_setup_buffers() was done */ - OPENSSL_PUT_ERROR(SSL, ssl3_get_record, ERR_R_INTERNAL_ERROR); - return -1; - } + if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER) { + extra = SSL3_RT_MAX_EXTRA; + } else { + extra = 0; + } + + if (extra && !s->s3->init_extra) { + /* An application error: SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER set after + * ssl3_setup_buffers() was done */ + OPENSSL_PUT_ERROR(SSL, ssl3_get_record, ERR_R_INTERNAL_ERROR); + return -1; + } again: - /* check if we have the header */ - if ( (s->rstate != SSL_ST_READ_BODY) || - (s->packet_length < SSL3_RT_HEADER_LENGTH)) - { - n=ssl3_read_n(s, SSL3_RT_HEADER_LENGTH, s->s3->rbuf.len, 0); - if (n <= 0) return(n); /* error or non-blocking */ - s->rstate=SSL_ST_READ_BODY; + /* check if we have the header */ + if (s->rstate != SSL_ST_READ_BODY || + s->packet_length < SSL3_RT_HEADER_LENGTH) { + n = ssl3_read_n(s, SSL3_RT_HEADER_LENGTH, s->s3->rbuf.len, 0); + if (n <= 0) { + return n; /* error or non-blocking */ + } + s->rstate = SSL_ST_READ_BODY; - p=s->packet; - if (s->msg_callback) - s->msg_callback(0, 0, SSL3_RT_HEADER, p, 5, s, s->msg_callback_arg); + p = s->packet; + if (s->msg_callback) { + s->msg_callback(0, 0, SSL3_RT_HEADER, p, 5, s, s->msg_callback_arg); + } - /* Pull apart the header into the SSL3_RECORD */ - rr->type= *(p++); - ssl_major= *(p++); - ssl_minor= *(p++); - version=(ssl_major<<8)|ssl_minor; - n2s(p,rr->length); -#if 0 -fprintf(stderr, "Record type=%d, Length=%d\n", rr->type, rr->length); -#endif + /* Pull apart the header into the SSL3_RECORD */ + rr->type = *(p++); + ssl_major = *(p++); + ssl_minor = *(p++); + version = (ssl_major << 8) | ssl_minor; + n2s(p, rr->length); - /* Lets check version */ - if (s->s3->have_version) - { - if (version != s->version) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_record, SSL_R_WRONG_VERSION_NUMBER); - if ((s->version & 0xFF00) == (version & 0xFF00)) - /* Send back error using their minor version number :-) */ - s->version = (unsigned short)version; - al=SSL_AD_PROTOCOL_VERSION; - goto f_err; - } - } + if (s->s3->have_version && version != s->version) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_record, SSL_R_WRONG_VERSION_NUMBER); + if ((s->version & 0xFF00) == (version & 0xFF00)) { + /* Send back error using their minor version number. */ + s->version = (unsigned short)version; + } + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } - if ((version>>8) != SSL3_VERSION_MAJOR) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_record, SSL_R_WRONG_VERSION_NUMBER); - goto err; - } + if ((version >> 8) != SSL3_VERSION_MAJOR) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_record, SSL_R_WRONG_VERSION_NUMBER); + goto err; + } - if (rr->length > s->s3->rbuf.len - SSL3_RT_HEADER_LENGTH) - { - al=SSL_AD_RECORD_OVERFLOW; - OPENSSL_PUT_ERROR(SSL, ssl3_get_record, SSL_R_PACKET_LENGTH_TOO_LONG); - goto f_err; - } + if (rr->length > s->s3->rbuf.len - SSL3_RT_HEADER_LENGTH) { + al = SSL_AD_RECORD_OVERFLOW; + OPENSSL_PUT_ERROR(SSL, ssl3_get_record, SSL_R_PACKET_LENGTH_TOO_LONG); + goto f_err; + } - /* now s->rstate == SSL_ST_READ_BODY */ - } + /* now s->rstate == SSL_ST_READ_BODY */ + } - /* s->rstate == SSL_ST_READ_BODY, get and decode the data */ + /* s->rstate == SSL_ST_READ_BODY, get and decode the data */ - if (rr->length > s->packet_length-SSL3_RT_HEADER_LENGTH) - { - /* now s->packet_length == SSL3_RT_HEADER_LENGTH */ - i=rr->length; - n=ssl3_read_n(s,i,i,1); - if (n <= 0) return(n); /* error or non-blocking io */ - /* now n == rr->length, - * and s->packet_length == SSL3_RT_HEADER_LENGTH + rr->length */ - } + if (rr->length > s->packet_length - SSL3_RT_HEADER_LENGTH) { + /* now s->packet_length == SSL3_RT_HEADER_LENGTH */ + i = rr->length; + n = ssl3_read_n(s, i, i, 1); + if (n <= 0) { + /* Error or non-blocking IO. Now |n| == |rr->length|, and + * |s->packet_length| == |SSL3_RT_HEADER_LENGTH| + |rr->length|. */ + return n; + } + } - s->rstate=SSL_ST_READ_HEADER; /* set state for later operations */ + s->rstate = SSL_ST_READ_HEADER; /* set state for later operations */ - /* At this point, s->packet_length == SSL3_RT_HEADER_LNGTH + rr->length, - * and we have that many bytes in s->packet - */ - rr->input= &(s->packet[SSL3_RT_HEADER_LENGTH]); + /* At this point, s->packet_length == SSL3_RT_HEADER_LNGTH + rr->length, and + * we have that many bytes in s->packet. */ + rr->input = &s->packet[SSL3_RT_HEADER_LENGTH]; - /* ok, we can now read from 's->packet' data into 'rr' - * rr->input points at rr->length bytes, which - * need to be copied into rr->data by either - * the decryption or by the decompression - * When the data is 'copied' into the rr->data buffer, - * rr->input will be pointed at the new buffer */ + /* ok, we can now read from |s->packet| data into |rr|. |rr->input| points at + * |rr->length| bytes, which need to be copied into |rr->data| by decryption. + * When the data is 'copied' into the |rr->data| buffer, |rr->input| will be + * pointed at the new buffer. */ - /* We now have - encrypted [ MAC [ compressed [ plain ] ] ] - * rr->length bytes of encrypted compressed stuff. */ + /* We now have - encrypted [ MAC [ compressed [ plain ] ] ] + * rr->length bytes of encrypted compressed stuff. */ - /* check is not needed I believe */ - if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH+extra) - { - al=SSL_AD_RECORD_OVERFLOW; - OPENSSL_PUT_ERROR(SSL, ssl3_get_record, SSL_R_ENCRYPTED_LENGTH_TOO_LONG); - goto f_err; - } + /* check is not needed I believe */ + if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH + extra) { + al = SSL_AD_RECORD_OVERFLOW; + OPENSSL_PUT_ERROR(SSL, ssl3_get_record, SSL_R_ENCRYPTED_LENGTH_TOO_LONG); + goto f_err; + } - /* decrypt in place in 'rr->input' */ - rr->data=rr->input; + /* decrypt in place in 'rr->input' */ + rr->data = rr->input; - enc_err = s->enc_method->enc(s,0); - /* enc_err is: - * 0: (in non-constant time) if the record is publically invalid. - * 1: if the padding is valid - * -1: if the padding is invalid */ - if (enc_err == 0) - { - al=SSL_AD_DECRYPTION_FAILED; - OPENSSL_PUT_ERROR(SSL, ssl3_get_record, SSL_R_BLOCK_CIPHER_PAD_IS_WRONG); - goto f_err; - } + enc_err = s->enc_method->enc(s, 0); + /* enc_err is: + * 0: (in non-constant time) if the record is publically invalid. + * 1: if the padding is valid + * -1: if the padding is invalid */ + if (enc_err == 0) { + al = SSL_AD_DECRYPTION_FAILED; + OPENSSL_PUT_ERROR(SSL, ssl3_get_record, SSL_R_BLOCK_CIPHER_PAD_IS_WRONG); + goto f_err; + } -#ifdef TLS_DEBUG -printf("dec %d\n",rr->length); -{ unsigned int z; for (z=0; z<rr->length; z++) printf("%02X%c",rr->data[z],((z+1)%16)?' ':'\n'); } -printf("\n"); -#endif + /* |r->length| is now the compressed data plus MAC. */ + if (sess != NULL && s->enc_read_ctx != NULL && + EVP_MD_CTX_md(s->read_hash) != NULL) { + /* s->read_hash != NULL => mac_size != -1 */ + uint8_t *mac = NULL; + uint8_t mac_tmp[EVP_MAX_MD_SIZE]; + mac_size = EVP_MD_CTX_size(s->read_hash); + assert(mac_size <= EVP_MAX_MD_SIZE); - /* r->length is now the compressed data plus mac */ - if ((sess != NULL) && - (s->enc_read_ctx != NULL) && - (EVP_MD_CTX_md(s->read_hash) != NULL)) - { - /* s->read_hash != NULL => mac_size != -1 */ - unsigned char *mac = NULL; - unsigned char mac_tmp[EVP_MAX_MD_SIZE]; - mac_size=EVP_MD_CTX_size(s->read_hash); - assert(mac_size <= EVP_MAX_MD_SIZE); + /* kludge: *_cbc_remove_padding passes padding length in rr->type */ + orig_len = rr->length + ((unsigned int)rr->type >> 8); - /* kludge: *_cbc_remove_padding passes padding length in rr->type */ - orig_len = rr->length+((unsigned int)rr->type>>8); + /* orig_len is the length of the record before any padding was removed. + * This is public information, as is the MAC in use, therefore we can + * safely process the record in a different amount of time if it's too + * short to possibly contain a MAC. */ + if (orig_len < mac_size || + /* CBC records must have a padding length byte too. */ + (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE && + orig_len < mac_size + 1)) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_record, SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } - /* orig_len is the length of the record before any padding was - * removed. This is public information, as is the MAC in use, - * therefore we can safely process the record in a different - * amount of time if it's too short to possibly contain a MAC. - */ - if (orig_len < mac_size || - /* CBC records must have a padding length byte too. */ - (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE && - orig_len < mac_size+1)) - { - al=SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_record, SSL_R_LENGTH_TOO_SHORT); - goto f_err; - } + if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE) { + /* We update the length so that the TLS header bytes can be constructed + * correctly but we need to extract the MAC in constant time from within + * the record, without leaking the contents of the padding bytes. */ + mac = mac_tmp; + ssl3_cbc_copy_mac(mac_tmp, rr, mac_size, orig_len); + rr->length -= mac_size; + } else { + /* In this case there's no padding, so |orig_len| equals |rec->length| + * and we checked that there's enough bytes for |mac_size| above. */ + rr->length -= mac_size; + mac = &rr->data[rr->length]; + } - if (EVP_CIPHER_CTX_mode(s->enc_read_ctx) == EVP_CIPH_CBC_MODE) - { - /* We update the length so that the TLS header bytes - * can be constructed correctly but we need to extract - * the MAC in constant time from within the record, - * without leaking the contents of the padding bytes. - * */ - mac = mac_tmp; - ssl3_cbc_copy_mac(mac_tmp, rr, mac_size, orig_len); - rr->length -= mac_size; - } - else - { - /* In this case there's no padding, so |orig_len| - * equals |rec->length| and we checked that there's - * enough bytes for |mac_size| above. */ - rr->length -= mac_size; - mac = &rr->data[rr->length]; - } + i = s->enc_method->mac(s, md, 0 /* not send */); + if (i < 0 || mac == NULL || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0) { + enc_err = -1; + } + if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH + extra + mac_size) { + enc_err = -1; + } + } - i=s->enc_method->mac(s,md,0 /* not send */); - if (i < 0 || mac == NULL || CRYPTO_memcmp(md, mac, (size_t)mac_size) != 0) - enc_err = -1; - if (rr->length > SSL3_RT_MAX_COMPRESSED_LENGTH+extra+mac_size) - enc_err = -1; - } + if (enc_err < 0) { + /* A separate 'decryption_failed' alert was introduced with TLS 1.0, SSL + * 3.0 only has 'bad_record_mac'. But unless a decryption failure is + * directly visible from the ciphertext anyway, we should not reveal which + * kind of error occured – this might become visible to an attacker (e.g. + * via a logfile) */ + al = SSL_AD_BAD_RECORD_MAC; + OPENSSL_PUT_ERROR(SSL, ssl3_get_record, + SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC); + goto f_err; + } - if (enc_err < 0) - { - /* A separate 'decryption_failed' alert was introduced with TLS 1.0, - * SSL 3.0 only has 'bad_record_mac'. But unless a decryption - * failure is directly visible from the ciphertext anyway, - * we should not reveal which kind of error occured -- this - * might become visible to an attacker (e.g. via a logfile) */ - al=SSL_AD_BAD_RECORD_MAC; - OPENSSL_PUT_ERROR(SSL, ssl3_get_record, SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC); - goto f_err; - } + if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH + extra) { + al = SSL_AD_RECORD_OVERFLOW; + OPENSSL_PUT_ERROR(SSL, ssl3_get_record, SSL_R_DATA_LENGTH_TOO_LONG); + goto f_err; + } - if (rr->length > SSL3_RT_MAX_PLAIN_LENGTH+extra) - { - al=SSL_AD_RECORD_OVERFLOW; - OPENSSL_PUT_ERROR(SSL, ssl3_get_record, SSL_R_DATA_LENGTH_TOO_LONG); - goto f_err; - } + rr->off = 0; + /* So at this point the following is true: + * ssl->s3->rrec.type is the type of record; + * ssl->s3->rrec.length is the number of bytes in the record; + * ssl->s3->rrec.off is the offset to first valid byte; + * ssl->s3->rrec.data is where to take bytes from (increment after use). */ - rr->off=0; - /* So at this point the following is true - * ssl->s3->rrec.type is the type of record - * ssl->s3->rrec.length == number of bytes in record - * ssl->s3->rrec.off == offset to first valid byte - * ssl->s3->rrec.data == where to take bytes from, increment - * after use :-). - */ + /* we have pulled in a full packet so zero things */ + s->packet_length = 0; - /* we have pulled in a full packet so zero things */ - s->packet_length=0; + /* just read a 0 length packet */ + if (rr->length == 0) { + empty_record_count++; + if (empty_record_count > MAX_EMPTY_RECORDS) { + al = SSL_AD_UNEXPECTED_MESSAGE; + OPENSSL_PUT_ERROR(SSL, ssl3_get_record, SSL_R_TOO_MANY_EMPTY_FRAGMENTS); + goto f_err; + } + goto again; + } - /* just read a 0 length packet */ - if (rr->length == 0) - { - empty_record_count++; - if (empty_record_count > MAX_EMPTY_RECORDS) - { - al=SSL_AD_UNEXPECTED_MESSAGE; - OPENSSL_PUT_ERROR(SSL, ssl3_get_record, SSL_R_TOO_MANY_EMPTY_FRAGMENTS); - goto f_err; - } - goto again; - } - -#if 0 -fprintf(stderr, "Ultimate Record type=%d, Length=%d\n", rr->type, rr->length); -#endif - - return(1); + return 1; f_err: - ssl3_send_alert(s,SSL3_AL_FATAL,al); + ssl3_send_alert(s, SSL3_AL_FATAL, al); err: - return(ret); - } + return ret; +} -/* Call this to write data in records of type 'type' - * It will return <= 0 if not all data has been sent or non-blocking IO. - */ -int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len) - { - const unsigned char *buf=buf_; - unsigned int tot,n,nw; - int i; +/* Call this to write data in records of type |type|. It will return <= 0 if + * not all data has been sent or non-blocking IO. */ +int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len) { + const uint8_t *buf = buf_; + unsigned int tot, n, nw; + int i; - s->rwstate=SSL_NOTHING; - assert(s->s3->wnum <= INT_MAX); - tot=s->s3->wnum; - s->s3->wnum=0; + s->rwstate = SSL_NOTHING; + assert(s->s3->wnum <= INT_MAX); + tot = s->s3->wnum; + s->s3->wnum = 0; - if (SSL_in_init(s) && !s->in_handshake) - { - i=s->handshake_func(s); - if (i < 0) return(i); - if (i == 0) - { - OPENSSL_PUT_ERROR(SSL, ssl3_write_bytes, SSL_R_SSL_HANDSHAKE_FAILURE); - return -1; - } - } + if (SSL_in_init(s) && !s->in_handshake) { + i = s->handshake_func(s); + if (i < 0) { + return i; + } + if (i == 0) { + OPENSSL_PUT_ERROR(SSL, ssl3_write_bytes, SSL_R_SSL_HANDSHAKE_FAILURE); + return -1; + } + } - /* ensure that if we end up with a smaller value of data to write - * out than the the original len from a write which didn't complete - * for non-blocking I/O and also somehow ended up avoiding - * the check for this in ssl3_write_pending/SSL_R_BAD_WRITE_RETRY as - * it must never be possible to end up with (len-tot) as a large - * number that will then promptly send beyond the end of the users - * buffer ... so we trap and report the error in a way the user - * will notice - */ - if (len < 0 || (size_t)len < tot) - { - OPENSSL_PUT_ERROR(SSL, ssl3_write_bytes, SSL_R_BAD_LENGTH); - return(-1); - } + /* Ensure that if we end up with a smaller value of data to write out than + * the the original len from a write which didn't complete for non-blocking + * I/O and also somehow ended up avoiding the check for this in + * ssl3_write_pending/SSL_R_BAD_WRITE_RETRY as it must never be possible to + * end up with (len-tot) as a large number that will then promptly send + * beyond the end of the users buffer ... so we trap and report the error in + * a way the user will notice. */ + if (len < 0 || (size_t)len < tot) { + OPENSSL_PUT_ERROR(SSL, ssl3_write_bytes, SSL_R_BAD_LENGTH); + return -1; + } - n=(len-tot); - for (;;) - { - /* max contains the maximum number of bytes that we can put - * into a record. */ - unsigned max = s->max_send_fragment; - /* fragment is true if do_ssl3_write should send the first byte - * in its own record in order to randomise a CBC IV. */ - int fragment = 0; + n = (len - tot); + for (;;) { + /* max contains the maximum number of bytes that we can put into a + * record. */ + unsigned max = s->max_send_fragment; + /* fragment is true if do_ssl3_write should send the first byte in its own + * record in order to randomise a CBC IV. */ + int fragment = 0; - if (n > 1 && - s->s3->need_record_splitting && - type == SSL3_RT_APPLICATION_DATA && - !s->s3->record_split_done) - { - fragment = 1; - /* record_split_done records that the splitting has - * been done in case we hit an SSL_WANT_WRITE condition. - * In that case, we don't need to do the split again. */ - s->s3->record_split_done = 1; - } + if (n > 1 && s->s3->need_record_splitting && + type == SSL3_RT_APPLICATION_DATA && !s->s3->record_split_done) { + fragment = 1; + /* record_split_done records that the splitting has been done in case we + * hit an SSL_WANT_WRITE condition. In that case, we don't need to do the + * split again. */ + s->s3->record_split_done = 1; + } - if (n > max) - nw=max; - else - nw=n; + if (n > max) { + nw = max; + } else { + nw = n; + } - i=do_ssl3_write(s, type, &(buf[tot]), nw, fragment, 0); - if (i <= 0) - { - s->s3->wnum=tot; - s->s3->record_split_done = 0; - return i; - } + i = do_ssl3_write(s, type, &(buf[tot]), nw, fragment, 0); + if (i <= 0) { + s->s3->wnum = tot; + s->s3->record_split_done = 0; + return i; + } - if ((i == (int)n) || - (type == SSL3_RT_APPLICATION_DATA && - (s->mode & SSL_MODE_ENABLE_PARTIAL_WRITE))) - { - /* next chunk of data should get another prepended, - * one-byte fragment in ciphersuites with known-IV - * weakness. */ - s->s3->record_split_done = 0; - return tot+i; - } + if (i == (int)n || (type == SSL3_RT_APPLICATION_DATA && + (s->mode & SSL_MODE_ENABLE_PARTIAL_WRITE))) { + /* next chunk of data should get another prepended, one-byte fragment in + * ciphersuites with known-IV weakness. */ + s->s3->record_split_done = 0; + return tot + i; + } - n-=i; - tot+=i; - } - } + n -= i; + tot += i; + } +} /* do_ssl3_write writes an SSL record of the given type. If |fragment| is 1 * then it splits the record into a one byte record and a record with the rest * of the data in order to randomise a CBC IV. If |is_fragment| is true then * this call resulted from do_ssl3_write calling itself in order to create that * one byte fragment. */ -static int do_ssl3_write(SSL *s, int type, const unsigned char *buf, - unsigned int len, char fragment, char is_fragment) - { - unsigned char *p,*plen; - int i,mac_size; - int prefix_len=0; - int eivlen; - long align=0; - SSL3_RECORD *wr; - SSL3_BUFFER *wb=&(s->s3->wbuf); - SSL_SESSION *sess; +static int do_ssl3_write(SSL *s, int type, const uint8_t *buf, unsigned int len, + char fragment, char is_fragment) { + uint8_t *p, *plen; + int i, mac_size; + int prefix_len = 0; + int eivlen = 0; + long align = 0; + SSL3_RECORD *wr; + SSL3_BUFFER *wb = &(s->s3->wbuf); + SSL_SESSION *sess; - /* first check if there is a SSL3_BUFFER still being written - * out. This will happen with non blocking IO */ - if (wb->left != 0) - return(ssl3_write_pending(s,type,buf,len)); + /* first check if there is a SSL3_BUFFER still being written out. This will + * happen with non blocking IO */ + if (wb->left != 0) { + return ssl3_write_pending(s, type, buf, len); + } - /* If we have an alert to send, lets send it */ - if (s->s3->alert_dispatch) - { - i=s->method->ssl_dispatch_alert(s); - if (i <= 0) - return(i); - /* if it went, fall through and send more stuff */ - } + /* If we have an alert to send, lets send it */ + if (s->s3->alert_dispatch) { + i = s->method->ssl_dispatch_alert(s); + if (i <= 0) { + return i; + } + /* if it went, fall through and send more stuff */ + } - if (wb->buf == NULL) - if (!ssl3_setup_write_buffer(s)) - return -1; + if (wb->buf == NULL && !ssl3_setup_write_buffer(s)) { + return -1; + } - if (len == 0) - return 0; + if (len == 0) { + return 0; + } - wr= &(s->s3->wrec); - sess=s->session; + wr = &s->s3->wrec; + sess = s->session; - if ( (sess == NULL) || - (s->enc_write_ctx == NULL) || - (EVP_MD_CTX_md(s->write_hash) == NULL)) - { - mac_size=0; - } - else - { - mac_size=EVP_MD_CTX_size(s->write_hash); - if (mac_size < 0) - goto err; - } + if (sess == NULL || s->enc_write_ctx == NULL || + EVP_MD_CTX_md(s->write_hash) == NULL) { + mac_size = 0; + } else { + mac_size = EVP_MD_CTX_size(s->write_hash); + if (mac_size < 0) { + goto err; + } + } - if (fragment) - { - /* countermeasure against known-IV weakness in CBC ciphersuites - * (see http://www.openssl.org/~bodo/tls-cbc.txt) */ - prefix_len = do_ssl3_write(s, type, buf, 1 /* length */, - 0 /* fragment */, - 1 /* is_fragment */); - if (prefix_len <= 0) - goto err; + if (fragment) { + /* countermeasure against known-IV weakness in CBC ciphersuites (see + * http://www.openssl.org/~bodo/tls-cbc.txt) */ + prefix_len = do_ssl3_write(s, type, buf, 1 /* length */, 0 /* fragment */, + 1 /* is_fragment */); + if (prefix_len <= 0) { + goto err; + } - if (prefix_len > (SSL3_RT_HEADER_LENGTH + - SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD)) - { - /* insufficient space */ - OPENSSL_PUT_ERROR(SSL, do_ssl3_write, ERR_R_INTERNAL_ERROR); - goto err; - } - } + if (prefix_len > + (SSL3_RT_HEADER_LENGTH + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD)) { + /* insufficient space */ + OPENSSL_PUT_ERROR(SSL, do_ssl3_write, ERR_R_INTERNAL_ERROR); + goto err; + } + } - if (is_fragment) - { -#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0 - /* The extra fragment would be couple of cipher blocks, and - * that will be a multiple of SSL3_ALIGN_PAYLOAD. So, if we - * want to align the real payload, we can just pretend that we - * have two headers and a byte. */ - align = (long)wb->buf + 2*SSL3_RT_HEADER_LENGTH + 1; - align = (-align)&(SSL3_ALIGN_PAYLOAD-1); -#endif - p = wb->buf + align; - wb->offset = align; - } - else if (prefix_len) - { - p = wb->buf + wb->offset + prefix_len; - } - else - { -#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0 - align = (long)wb->buf + SSL3_RT_HEADER_LENGTH; - align = (-align)&(SSL3_ALIGN_PAYLOAD-1); -#endif - p = wb->buf + align; - wb->offset = align; - } + if (is_fragment) { + /* The extra fragment would be couple of cipher blocks, and that will be a + * multiple of SSL3_ALIGN_PAYLOAD. So, if we want to align the real + * payload, we can just pretend that we have two headers and a byte. */ + align = (long)wb->buf + 2 * SSL3_RT_HEADER_LENGTH + 1; + align = (-align) & (SSL3_ALIGN_PAYLOAD - 1); + p = wb->buf + align; + wb->offset = align; + } else if (prefix_len) { + p = wb->buf + wb->offset + prefix_len; + } else { + align = (long)wb->buf + SSL3_RT_HEADER_LENGTH; + align = (-align) & (SSL3_ALIGN_PAYLOAD - 1); + p = wb->buf + align; + wb->offset = align; + } - /* write the header */ + /* write the header */ - *(p++)=type&0xff; - wr->type=type; + *(p++) = type & 0xff; + wr->type = type; - /* Some servers hang if initial ClientHello is larger than 256 - * bytes and record version number > TLS 1.0. */ - if (!s->s3->have_version && s->version > SSL3_VERSION) - { - *(p++) = TLS1_VERSION >> 8; - *(p++) = TLS1_VERSION & 0xff; - } - else - { - *(p++) = s->version >> 8; - *(p++) = s->version & 0xff; - } + /* Some servers hang if initial ClientHello is larger than 256 bytes and + * record version number > TLS 1.0. */ + if (!s->s3->have_version && s->version > SSL3_VERSION) { + *(p++) = TLS1_VERSION >> 8; + *(p++) = TLS1_VERSION & 0xff; + } else { + *(p++) = s->version >> 8; + *(p++) = s->version & 0xff; + } - /* field where we are to write out packet length */ - plen=p; - p+=2; - /* Explicit IV length, block ciphers appropriate version flag */ - if (s->enc_write_ctx && SSL_USE_EXPLICIT_IV(s)) - { - int mode = EVP_CIPHER_CTX_mode(s->enc_write_ctx); - if (mode == EVP_CIPH_CBC_MODE) - { - eivlen = EVP_CIPHER_CTX_iv_length(s->enc_write_ctx); - if (eivlen <= 1) - eivlen = 0; - } - else - eivlen = 0; - } - else if (s->aead_write_ctx != NULL && - s->aead_write_ctx->variable_nonce_included_in_record) - { - eivlen = s->aead_write_ctx->variable_nonce_len; - } - else - eivlen = 0; + /* field where we are to write out packet length */ + plen = p; + p += 2; - /* lets setup the record stuff. */ - wr->data=p + eivlen; - wr->length=(int)(len - (fragment != 0)); - wr->input=(unsigned char *)buf + (fragment != 0); + /* Explicit IV length, block ciphers appropriate version flag */ + if (s->enc_write_ctx && SSL_USE_EXPLICIT_IV(s) && + EVP_CIPHER_CTX_mode(s->enc_write_ctx) == EVP_CIPH_CBC_MODE) { + eivlen = EVP_CIPHER_CTX_iv_length(s->enc_write_ctx); + if (eivlen <= 1) { + eivlen = 0; + } + } else if (s->aead_write_ctx != NULL && + s->aead_write_ctx->variable_nonce_included_in_record) { + eivlen = s->aead_write_ctx->variable_nonce_len; + } - /* we now 'read' from wr->input, wr->length bytes into - * wr->data */ + /* lets setup the record stuff. */ + wr->data = p + eivlen; + wr->length = (int)(len - (fragment != 0)); + wr->input = (uint8_t *)buf + (fragment != 0); - memcpy(wr->data,wr->input,wr->length); - wr->input=wr->data; + /* we now 'read' from wr->input, wr->length bytes into wr->data */ - /* we should still have the output to wr->data and the input - * from wr->input. Length should be wr->length. - * wr->data still points in the wb->buf */ + memcpy(wr->data, wr->input, wr->length); + wr->input = wr->data; - if (mac_size != 0) - { - if (s->enc_method->mac(s,&(p[wr->length + eivlen]),1) < 0) - goto err; - wr->length+=mac_size; - } + /* we should still have the output to wr->data and the input from wr->input. + * Length should be wr->length. wr->data still points in the wb->buf */ - wr->input=p; - wr->data=p; - wr->length += eivlen; + if (mac_size != 0) { + if (s->enc_method->mac(s, &(p[wr->length + eivlen]), 1) < 0) { + goto err; + } + wr->length += mac_size; + } - if (s->enc_method->enc(s, 1) < 1) - goto err; + wr->input = p; + wr->data = p; + wr->length += eivlen; - /* record length after mac and block padding */ - s2n(wr->length,plen); + if (s->enc_method->enc(s, 1) < 1) { + goto err; + } - if (s->msg_callback) - s->msg_callback(1, 0, SSL3_RT_HEADER, plen - 5, 5, s, s->msg_callback_arg); + /* record length after mac and block padding */ + s2n(wr->length, plen); - /* we should now have - * wr->data pointing to the encrypted data, which is - * wr->length long */ - wr->type=type; /* not needed but helps for debugging */ - wr->length+=SSL3_RT_HEADER_LENGTH; + if (s->msg_callback) { + s->msg_callback(1, 0, SSL3_RT_HEADER, plen - 5, 5, s, s->msg_callback_arg); + } - if (is_fragment) - { - /* we are in a recursive call; just return the length, don't - * write out anything. */ - return wr->length; - } + /* we should now have wr->data pointing to the encrypted data, which is + * wr->length long. */ + wr->type = type; /* not needed but helps for debugging */ + wr->length += SSL3_RT_HEADER_LENGTH; - /* now let's set up wb */ - wb->left = prefix_len + wr->length; + if (is_fragment) { + /* we are in a recursive call; just return the length, don't write out + * anything. */ + return wr->length; + } - /* memorize arguments so that ssl3_write_pending can detect bad write retries later */ - s->s3->wpend_tot=len; - s->s3->wpend_buf=buf; - s->s3->wpend_type=type; - s->s3->wpend_ret=len; + /* now let's set up wb */ + wb->left = prefix_len + wr->length; - /* we now just need to write the buffer */ - return ssl3_write_pending(s,type,buf,len); + /* memorize arguments so that ssl3_write_pending can detect bad write retries + * later */ + s->s3->wpend_tot = len; + s->s3->wpend_buf = buf; + s->s3->wpend_type = type; + s->s3->wpend_ret = len; + + /* we now just need to write the buffer */ + return ssl3_write_pending(s, type, buf, len); + err: - return -1; - } + return -1; +} /* if s->s3->wbuf.left != 0, we need to call this */ -int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, - unsigned int len) - { - int i; - SSL3_BUFFER *wb=&(s->s3->wbuf); +int ssl3_write_pending(SSL *s, int type, const uint8_t *buf, unsigned int len) { + int i; + SSL3_BUFFER *wb = &(s->s3->wbuf); -/* XXXX */ - if ((s->s3->wpend_tot > (int)len) - || ((s->s3->wpend_buf != buf) && - !(s->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)) - || (s->s3->wpend_type != type)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_write_pending, SSL_R_BAD_WRITE_RETRY); - return(-1); - } + if (s->s3->wpend_tot > (int)len || + (s->s3->wpend_buf != buf && + !(s->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)) || + s->s3->wpend_type != type) { + OPENSSL_PUT_ERROR(SSL, ssl3_write_pending, SSL_R_BAD_WRITE_RETRY); + return -1; + } - for (;;) - { - ERR_clear_system_error(); - if (s->wbio != NULL) - { - s->rwstate=SSL_WRITING; - i=BIO_write(s->wbio, - (char *)&(wb->buf[wb->offset]), - (unsigned int)wb->left); - } - else - { - OPENSSL_PUT_ERROR(SSL, ssl3_write_pending, SSL_R_BIO_NOT_SET); - i= -1; - } - if (i == wb->left) - { - wb->left=0; - wb->offset+=i; - if (s->mode & SSL_MODE_RELEASE_BUFFERS && - !SSL_IS_DTLS(s)) - ssl3_release_write_buffer(s); - s->rwstate=SSL_NOTHING; - return(s->s3->wpend_ret); - } - else if (i <= 0) { - if (SSL_IS_DTLS(s)) { - /* For DTLS, just drop it. That's kind of the whole - point in using a datagram service */ - wb->left = 0; - } - return(i); - } - wb->offset+=i; - wb->left-=i; - } - } + for (;;) { + ERR_clear_system_error(); + if (s->wbio != NULL) { + s->rwstate = SSL_WRITING; + i = BIO_write(s->wbio, (char *)&(wb->buf[wb->offset]), + (unsigned int)wb->left); + } else { + OPENSSL_PUT_ERROR(SSL, ssl3_write_pending, SSL_R_BIO_NOT_SET); + i = -1; + } + if (i == wb->left) { + wb->left = 0; + wb->offset += i; + if (s->mode & SSL_MODE_RELEASE_BUFFERS && !SSL_IS_DTLS(s)) { + ssl3_release_write_buffer(s); + } + s->rwstate = SSL_NOTHING; + return s->s3->wpend_ret; + } else if (i <= 0) { + if (SSL_IS_DTLS(s)) { + /* For DTLS, just drop it. That's kind of the whole + point in using a datagram service */ + wb->left = 0; + } + return i; + } + wb->offset += i; + wb->left -= i; + } +} /* ssl3_expect_change_cipher_spec informs the record layer that a * ChangeCipherSpec record is required at this point. If a Handshake record is * received before ChangeCipherSpec, the connection will fail. Moreover, if * there are unprocessed handshake bytes, the handshake will also fail and the * function returns zero. Otherwise, the function returns one. */ -int ssl3_expect_change_cipher_spec(SSL *s) - { - if (s->s3->handshake_fragment_len > 0 || s->s3->tmp.reuse_message) - { - OPENSSL_PUT_ERROR(SSL, ssl3_expect_change_cipher_spec, SSL_R_UNPROCESSED_HANDSHAKE_DATA); - return 0; - } - s->s3->flags |= SSL3_FLAGS_EXPECT_CCS; - return 1; - } +int ssl3_expect_change_cipher_spec(SSL *s) { + if (s->s3->handshake_fragment_len > 0 || s->s3->tmp.reuse_message) { + OPENSSL_PUT_ERROR(SSL, ssl3_expect_change_cipher_spec, + SSL_R_UNPROCESSED_HANDSHAKE_DATA); + return 0; + } + + s->s3->flags |= SSL3_FLAGS_EXPECT_CCS; + return 1; +} /* Return up to 'len' payload bytes received in 'type' records. * 'type' is one of the following: @@ -934,496 +829,479 @@ * Application data protocol * none of our business */ -int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) - { - int al,i,j,ret; - unsigned int n; - SSL3_RECORD *rr; - void (*cb)(const SSL *ssl,int type2,int val)=NULL; - uint8_t alert_buffer[2]; +int ssl3_read_bytes(SSL *s, int type, uint8_t *buf, int len, int peek) { + int al, i, j, ret; + unsigned int n; + SSL3_RECORD *rr; + void (*cb)(const SSL *ssl, int type2, int val) = NULL; + uint8_t alert_buffer[2]; - if (s->s3->rbuf.buf == NULL) /* Not initialized yet */ - if (!ssl3_setup_read_buffer(s)) - return(-1); + if (s->s3->rbuf.buf == NULL && !ssl3_setup_read_buffer(s)) { + return -1; + } - if ((type && (type != SSL3_RT_APPLICATION_DATA) && (type != SSL3_RT_HANDSHAKE)) || - (peek && (type != SSL3_RT_APPLICATION_DATA))) - { - OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, ERR_R_INTERNAL_ERROR); - return -1; - } + if ((type && type != SSL3_RT_APPLICATION_DATA && type != SSL3_RT_HANDSHAKE) || + (peek && type != SSL3_RT_APPLICATION_DATA)) { + OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, ERR_R_INTERNAL_ERROR); + return -1; + } - if ((type == SSL3_RT_HANDSHAKE) && (s->s3->handshake_fragment_len > 0)) - /* (partially) satisfy request from storage */ - { - unsigned char *src = s->s3->handshake_fragment; - unsigned char *dst = buf; - unsigned int k; + if (type == SSL3_RT_HANDSHAKE && s->s3->handshake_fragment_len > 0) { + /* (partially) satisfy request from storage */ + uint8_t *src = s->s3->handshake_fragment; + uint8_t *dst = buf; + unsigned int k; - /* peek == 0 */ - n = 0; - while ((len > 0) && (s->s3->handshake_fragment_len > 0)) - { - *dst++ = *src++; - len--; s->s3->handshake_fragment_len--; - n++; - } - /* move any remaining fragment bytes: */ - for (k = 0; k < s->s3->handshake_fragment_len; k++) - s->s3->handshake_fragment[k] = *src++; - return n; - } + /* peek == 0 */ + n = 0; + while (len > 0 && s->s3->handshake_fragment_len > 0) { + *dst++ = *src++; + len--; + s->s3->handshake_fragment_len--; + n++; + } + /* move any remaining fragment bytes: */ + for (k = 0; k < s->s3->handshake_fragment_len; k++) { + s->s3->handshake_fragment[k] = *src++; + } + return n; + } - /* Now s->s3->handshake_fragment_len == 0 if type == SSL3_RT_HANDSHAKE. */ + /* Now s->s3->handshake_fragment_len == 0 if type == SSL3_RT_HANDSHAKE. */ - if (!s->in_handshake && SSL_in_init(s)) - { - /* type == SSL3_RT_APPLICATION_DATA */ - i=s->handshake_func(s); - if (i < 0) return(i); - if (i == 0) - { - OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_SSL_HANDSHAKE_FAILURE); - return(-1); - } - } + if (!s->in_handshake && SSL_in_init(s)) { + /* type == SSL3_RT_APPLICATION_DATA */ + i = s->handshake_func(s); + if (i < 0) { + return i; + } + if (i == 0) { + OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_SSL_HANDSHAKE_FAILURE); + return -1; + } + } + start: - s->rwstate=SSL_NOTHING; + s->rwstate = SSL_NOTHING; - /* s->s3->rrec.type - is the type of record - * s->s3->rrec.data, - data - * s->s3->rrec.off, - offset into 'data' for next read - * s->s3->rrec.length, - number of bytes. */ - rr = &(s->s3->rrec); + /* s->s3->rrec.type - is the type of record + * s->s3->rrec.data - data + * s->s3->rrec.off - offset into 'data' for next read + * s->s3->rrec.length - number of bytes. */ + rr = &s->s3->rrec; - /* get new packet if necessary */ - if ((rr->length == 0) || (s->rstate == SSL_ST_READ_BODY)) - { - ret=ssl3_get_record(s); - if (ret <= 0) return(ret); - } + /* get new packet if necessary */ + if (rr->length == 0 || s->rstate == SSL_ST_READ_BODY) { + ret = ssl3_get_record(s); + if (ret <= 0) { + return ret; + } + } - /* we now have a packet which can be read and processed */ + /* we now have a packet which can be read and processed */ - if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec, - * reset by ssl3_get_finished */ - && (rr->type != SSL3_RT_HANDSHAKE)) - { - al=SSL_AD_UNEXPECTED_MESSAGE; - OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_DATA_BETWEEN_CCS_AND_FINISHED); - goto f_err; - } + if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec, + * reset by ssl3_get_finished */ + && rr->type != SSL3_RT_HANDSHAKE) { + al = SSL_AD_UNEXPECTED_MESSAGE; + OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, + SSL_R_DATA_BETWEEN_CCS_AND_FINISHED); + goto f_err; + } - /* If we are expecting a ChangeCipherSpec, it is illegal to receive a - * Handshake record. */ - if (rr->type == SSL3_RT_HANDSHAKE && (s->s3->flags & SSL3_FLAGS_EXPECT_CCS)) - { - al = SSL_AD_UNEXPECTED_MESSAGE; - OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_HANDSHAKE_RECORD_BEFORE_CCS); - goto f_err; - } + /* If we are expecting a ChangeCipherSpec, it is illegal to receive a + * Handshake record. */ + if (rr->type == SSL3_RT_HANDSHAKE && (s->s3->flags & SSL3_FLAGS_EXPECT_CCS)) { + al = SSL_AD_UNEXPECTED_MESSAGE; + OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_HANDSHAKE_RECORD_BEFORE_CCS); + goto f_err; + } - /* If the other end has shut down, throw anything we read away - * (even in 'peek' mode) */ - if (s->shutdown & SSL_RECEIVED_SHUTDOWN) - { - rr->length=0; - s->rwstate=SSL_NOTHING; - return(0); - } + /* If the other end has shut down, throw anything we read away (even in + * 'peek' mode) */ + if (s->shutdown & SSL_RECEIVED_SHUTDOWN) { + rr->length = 0; + s->rwstate = SSL_NOTHING; + return 0; + } - if (type == rr->type) /* SSL3_RT_APPLICATION_DATA or SSL3_RT_HANDSHAKE */ - { - /* make sure that we are not getting application data when we - * are doing a handshake for the first time */ - if (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) && - (s->enc_read_ctx == NULL)) - { - al=SSL_AD_UNEXPECTED_MESSAGE; - OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_APP_DATA_IN_HANDSHAKE); - goto f_err; - } + if (type == rr->type) { + /* SSL3_RT_APPLICATION_DATA or SSL3_RT_HANDSHAKE */ + /* make sure that we are not getting application data when we are doing a + * handshake for the first time */ + if (SSL_in_init(s) && type == SSL3_RT_APPLICATION_DATA && + s->enc_read_ctx == NULL) { + al = SSL_AD_UNEXPECTED_MESSAGE; + OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_APP_DATA_IN_HANDSHAKE); + goto f_err; + } - if (len <= 0) return(len); + if (len <= 0) { + return len; + } - if ((unsigned int)len > rr->length) - n = rr->length; - else - n = (unsigned int)len; + if ((unsigned int)len > rr->length) { + n = rr->length; + } else { + n = (unsigned int)len; + } - memcpy(buf,&(rr->data[rr->off]),n); - if (!peek) - { - rr->length-=n; - rr->off+=n; - if (rr->length == 0) - { - s->rstate=SSL_ST_READ_HEADER; - rr->off=0; - if (s->mode & SSL_MODE_RELEASE_BUFFERS && s->s3->rbuf.left == 0) - ssl3_release_read_buffer(s); - } - } - return(n); - } + memcpy(buf, &(rr->data[rr->off]), n); + if (!peek) { + rr->length -= n; + rr->off += n; + if (rr->length == 0) { + s->rstate = SSL_ST_READ_HEADER; + rr->off = 0; + if (s->mode & SSL_MODE_RELEASE_BUFFERS && s->s3->rbuf.left == 0) { + ssl3_release_read_buffer(s); + } + } + } + + return n; + } - /* If we get here, then type != rr->type; if we have a handshake - * message, then it was unexpected (Hello Request or Client Hello). */ + /* If we get here, then type != rr->type; if we have a handshake message, + * then it was unexpected (Hello Request or Client Hello). */ - /* In case of record types for which we have 'fragment' storage, - * fill that so that we can process the data at a fixed place. - */ + /* In case of record types for which we have 'fragment' storage, fill that so + * that we can process the data at a fixed place. */ - if (rr->type == SSL3_RT_HANDSHAKE) - { - const size_t size = sizeof(s->s3->handshake_fragment); - const size_t avail = size - s->s3->handshake_fragment_len; - const size_t todo = (rr->length < avail) ? rr->length : avail; - memcpy(s->s3->handshake_fragment + s->s3->handshake_fragment_len, - &rr->data[rr->off], todo); - rr->off += todo; - rr->length -= todo; - s->s3->handshake_fragment_len += todo; - if (s->s3->handshake_fragment_len < size) - { - goto start; /* fragment was too small */ - } - } - else if (rr->type == SSL3_RT_ALERT) - { - /* Note that this will still allow multiple alerts to - * be processed in the same record */ - if (rr->length < sizeof(alert_buffer)) - { - al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_BAD_ALERT); - goto f_err; - } - memcpy(alert_buffer, &rr->data[rr->off], sizeof(alert_buffer)); - rr->off += sizeof(alert_buffer); - rr->length -= sizeof(alert_buffer); - } + if (rr->type == SSL3_RT_HANDSHAKE) { + const size_t size = sizeof(s->s3->handshake_fragment); + const size_t avail = size - s->s3->handshake_fragment_len; + const size_t todo = (rr->length < avail) ? rr->length : avail; + memcpy(s->s3->handshake_fragment + s->s3->handshake_fragment_len, + &rr->data[rr->off], todo); + rr->off += todo; + rr->length -= todo; + s->s3->handshake_fragment_len += todo; + if (s->s3->handshake_fragment_len < size) { + goto start; /* fragment was too small */ + } + } else if (rr->type == SSL3_RT_ALERT) { + /* Note that this will still allow multiple alerts to be processed in the + * same record */ + if (rr->length < sizeof(alert_buffer)) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_BAD_ALERT); + goto f_err; + } + memcpy(alert_buffer, &rr->data[rr->off], sizeof(alert_buffer)); + rr->off += sizeof(alert_buffer); + rr->length -= sizeof(alert_buffer); + } - /* s->s3->handshake_fragment_len == 4 iff rr->type == SSL3_RT_HANDSHAKE; - * (Possibly rr is 'empty' now, i.e. rr->length may be 0.) */ + /* s->s3->handshake_fragment_len == 4 iff rr->type == SSL3_RT_HANDSHAKE; + * (Possibly rr is 'empty' now, i.e. rr->length may be 0.) */ - /* If we are a client, check for an incoming 'Hello Request': */ - if ((!s->server) && - (s->s3->handshake_fragment_len >= 4) && - (s->s3->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) && - (s->session != NULL) && (s->session->cipher != NULL)) - { - s->s3->handshake_fragment_len = 0; + /* If we are a client, check for an incoming 'Hello Request': */ + if (!s->server && s->s3->handshake_fragment_len >= 4 && + s->s3->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST && + s->session != NULL && s->session->cipher != NULL) { + s->s3->handshake_fragment_len = 0; - if ((s->s3->handshake_fragment[1] != 0) || - (s->s3->handshake_fragment[2] != 0) || - (s->s3->handshake_fragment[3] != 0)) - { - al=SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_BAD_HELLO_REQUEST); - goto f_err; - } + if (s->s3->handshake_fragment[1] != 0 || + s->s3->handshake_fragment[2] != 0 || + s->s3->handshake_fragment[3] != 0) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_BAD_HELLO_REQUEST); + goto f_err; + } - if (s->msg_callback) - s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->s3->handshake_fragment, 4, s, s->msg_callback_arg); + if (s->msg_callback) { + s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, + s->s3->handshake_fragment, 4, s, s->msg_callback_arg); + } - if (SSL_is_init_finished(s) && !s->s3->renegotiate) - { - ssl3_renegotiate(s); - if (ssl3_renegotiate_check(s)) - { - i=s->handshake_func(s); - if (i < 0) return(i); - if (i == 0) - { - OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_SSL_HANDSHAKE_FAILURE); - return(-1); - } - } - } - /* we either finished a handshake or ignored the request, - * now try again to obtain the (application) data we were asked for */ - goto start; - } + if (SSL_is_init_finished(s) && !s->s3->renegotiate) { + ssl3_renegotiate(s); + if (ssl3_renegotiate_check(s)) { + i = s->handshake_func(s); + if (i < 0) { + return i; + } + if (i == 0) { + OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_SSL_HANDSHAKE_FAILURE); + return -1; + } + } + } + /* we either finished a handshake or ignored the request, now try again to + * obtain the (application) data we were asked for */ + goto start; + } - if (rr->type == SSL3_RT_ALERT) - { - uint8_t alert_level = alert_buffer[0]; - uint8_t alert_descr = alert_buffer[1]; + if (rr->type == SSL3_RT_ALERT) { + const uint8_t alert_level = alert_buffer[0]; + const uint8_t alert_descr = alert_buffer[1]; - if (s->msg_callback) - s->msg_callback(0, s->version, SSL3_RT_ALERT, alert_buffer, 2, s, s->msg_callback_arg); + if (s->msg_callback) { + s->msg_callback(0, s->version, SSL3_RT_ALERT, alert_buffer, 2, s, + s->msg_callback_arg); + } - if (s->info_callback != NULL) - cb=s->info_callback; - else if (s->ctx->info_callback != NULL) - cb=s->ctx->info_callback; + if (s->info_callback != NULL) { + cb = s->info_callback; + } else if (s->ctx->info_callback != NULL) { + cb = s->ctx->info_callback; + } - if (cb != NULL) - { - j = (alert_level << 8) | alert_descr; - cb(s, SSL_CB_READ_ALERT, j); - } + if (cb != NULL) { + j = (alert_level << 8) | alert_descr; + cb(s, SSL_CB_READ_ALERT, j); + } - if (alert_level == 1) /* warning */ - { - s->s3->warn_alert = alert_descr; - if (alert_descr == SSL_AD_CLOSE_NOTIFY) - { - s->shutdown |= SSL_RECEIVED_SHUTDOWN; - return(0); - } - /* This is a warning but we receive it if we requested - * renegotiation and the peer denied it. Terminate with - * a fatal alert because if application tried to - * renegotiatie it presumably had a good reason and - * expects it to succeed. - * - * In future we might have a renegotiation where we - * don't care if the peer refused it where we carry on. - */ - else if (alert_descr == SSL_AD_NO_RENEGOTIATION) - { - al = SSL_AD_HANDSHAKE_FAILURE; - OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_NO_RENEGOTIATION); - goto f_err; - } - } - else if (alert_level == 2) /* fatal */ - { - char tmp[16]; + if (alert_level == 1) { + /* warning */ + s->s3->warn_alert = alert_descr; + if (alert_descr == SSL_AD_CLOSE_NOTIFY) { + s->shutdown |= SSL_RECEIVED_SHUTDOWN; + return 0; + } - s->rwstate=SSL_NOTHING; - s->s3->fatal_alert = alert_descr; - OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_AD_REASON_OFFSET + alert_descr); - BIO_snprintf(tmp,sizeof tmp,"%d",alert_descr); - ERR_add_error_data(2,"SSL alert number ",tmp); - s->shutdown|=SSL_RECEIVED_SHUTDOWN; - SSL_CTX_remove_session(s->ctx,s->session); - return(0); - } - else - { - al=SSL_AD_ILLEGAL_PARAMETER; - OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_UNKNOWN_ALERT_TYPE); - goto f_err; - } + /* This is a warning but we receive it if we requested renegotiation and + * the peer denied it. Terminate with a fatal alert because if + * application tried to renegotiatie it presumably had a good reason and + * expects it to succeed. + * + * In future we might have a renegotiation where we don't care if the + * peer refused it where we carry on. */ + else if (alert_descr == SSL_AD_NO_RENEGOTIATION) { + al = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_NO_RENEGOTIATION); + goto f_err; + } + } else if (alert_level == 2) { + /* fatal */ + char tmp[16]; - goto start; - } + s->rwstate = SSL_NOTHING; + s->s3->fatal_alert = alert_descr; + OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, + SSL_AD_REASON_OFFSET + alert_descr); + BIO_snprintf(tmp, sizeof(tmp), "%d", alert_descr); + ERR_add_error_data(2, "SSL alert number ", tmp); + s->shutdown |= SSL_RECEIVED_SHUTDOWN; + SSL_CTX_remove_session(s->ctx, s->session); + return 0; + } else { + al = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_UNKNOWN_ALERT_TYPE); + goto f_err; + } - if (s->shutdown & SSL_SENT_SHUTDOWN) /* but we have not received a shutdown */ - { - s->rwstate=SSL_NOTHING; - rr->length=0; - return(0); - } + goto start; + } - if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC) - { - /* 'Change Cipher Spec' is just a single byte, so we know - * exactly what the record payload has to look like */ - if ( (rr->length != 1) || (rr->off != 0) || - (rr->data[0] != SSL3_MT_CCS)) - { - al=SSL_AD_ILLEGAL_PARAMETER; - OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_BAD_CHANGE_CIPHER_SPEC); - goto f_err; - } + if (s->shutdown & SSL_SENT_SHUTDOWN) { + /* but we have not received a shutdown */ + s->rwstate = SSL_NOTHING; + rr->length = 0; + return 0; + } - /* Check we have a cipher to change to */ - if (s->s3->tmp.new_cipher == NULL) - { - al=SSL_AD_UNEXPECTED_MESSAGE; - OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_CCS_RECEIVED_EARLY); - goto f_err; - } + if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC) { + /* 'Change Cipher Spec' is just a single byte, so we know exactly what the + * record payload has to look like */ + if (rr->length != 1 || rr->off != 0 || rr->data[0] != SSL3_MT_CCS) { + al = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_BAD_CHANGE_CIPHER_SPEC); + goto f_err; + } - if (!(s->s3->flags & SSL3_FLAGS_EXPECT_CCS)) - { - al=SSL_AD_UNEXPECTED_MESSAGE; - OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_CCS_RECEIVED_EARLY); - goto f_err; - } + /* Check we have a cipher to change to */ + if (s->s3->tmp.new_cipher == NULL) { + al = SSL_AD_UNEXPECTED_MESSAGE; + OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_CCS_RECEIVED_EARLY); + goto f_err; + } - s->s3->flags &= ~SSL3_FLAGS_EXPECT_CCS; + if (!(s->s3->flags & SSL3_FLAGS_EXPECT_CCS)) { + al = SSL_AD_UNEXPECTED_MESSAGE; + OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_CCS_RECEIVED_EARLY); + goto f_err; + } - rr->length=0; + s->s3->flags &= ~SSL3_FLAGS_EXPECT_CCS; - if (s->msg_callback) - s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, rr->data, 1, s, s->msg_callback_arg); + rr->length = 0; - s->s3->change_cipher_spec=1; - if (!ssl3_do_change_cipher_spec(s)) - goto err; - else - goto start; - } + if (s->msg_callback) { + s->msg_callback(0, s->version, SSL3_RT_CHANGE_CIPHER_SPEC, rr->data, 1, s, + s->msg_callback_arg); + } - /* Unexpected handshake message (Client Hello, or protocol violation) */ - if ((s->s3->handshake_fragment_len >= 4) && !s->in_handshake) - { - if ((s->state&SSL_ST_MASK) == SSL_ST_OK) - { - s->state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT; - s->renegotiate=1; - s->new_session=1; - } - i=s->handshake_func(s); - if (i < 0) return(i); - if (i == 0) - { - OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_SSL_HANDSHAKE_FAILURE); - return(-1); - } + s->s3->change_cipher_spec = 1; + if (!ssl3_do_change_cipher_spec(s)) { + goto err; + } else { + goto start; + } + } - goto start; - } + /* Unexpected handshake message (Client Hello, or protocol violation) */ + if (s->s3->handshake_fragment_len >= 4 && !s->in_handshake) { + if ((s->state & SSL_ST_MASK) == SSL_ST_OK) { + s->state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT; + s->renegotiate = 1; + s->new_session = 1; + } + i = s->handshake_func(s); + if (i < 0) { + return i; + } + if (i == 0) { + OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_SSL_HANDSHAKE_FAILURE); + return -1; + } - switch (rr->type) - { - default: - /* TLS up to v1.1 just ignores unknown message types: - * TLS v1.2 give an unexpected message alert. - */ - if (s->version >= TLS1_VERSION && s->version <= TLS1_1_VERSION) - { - rr->length = 0; - goto start; - } - al=SSL_AD_UNEXPECTED_MESSAGE; - OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_UNEXPECTED_RECORD); - goto f_err; - case SSL3_RT_CHANGE_CIPHER_SPEC: - case SSL3_RT_ALERT: - case SSL3_RT_HANDSHAKE: - /* we already handled all of these, with the possible exception - * of SSL3_RT_HANDSHAKE when s->in_handshake is set, but that - * should not happen when type != rr->type */ - al=SSL_AD_UNEXPECTED_MESSAGE; - OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, ERR_R_INTERNAL_ERROR); - goto f_err; - case SSL3_RT_APPLICATION_DATA: - /* At this point, we were expecting handshake data, - * but have application data. If the library was - * running inside ssl3_read() (i.e. in_read_app_data - * is set) and it makes sense to read application data - * at this point (session renegotiation not yet started), - * we will indulge it. - */ - if (s->s3->in_read_app_data && - (s->s3->total_renegotiations != 0) && - (( - (s->state & SSL_ST_CONNECT) && - (s->state >= SSL3_ST_CW_CLNT_HELLO_A) && - (s->state <= SSL3_ST_CR_SRVR_HELLO_A) - ) || ( - (s->state & SSL_ST_ACCEPT) && - (s->state <= SSL3_ST_SW_HELLO_REQ_A) && - (s->state >= SSL3_ST_SR_CLNT_HELLO_A) - ) - )) - { - s->s3->in_read_app_data=2; - return(-1); - } - else - { - al=SSL_AD_UNEXPECTED_MESSAGE; - OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_UNEXPECTED_RECORD); - goto f_err; - } - } - /* not reached */ + goto start; + } + + switch (rr->type) { + default: + /* TLS up to v1.1 just ignores unknown message types. TLS v1.2 gives an + * unexpected message alert. */ + if (s->version >= TLS1_VERSION && s->version <= TLS1_1_VERSION) { + rr->length = 0; + goto start; + } + al = SSL_AD_UNEXPECTED_MESSAGE; + OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_UNEXPECTED_RECORD); + goto f_err; + + case SSL3_RT_CHANGE_CIPHER_SPEC: + case SSL3_RT_ALERT: + case SSL3_RT_HANDSHAKE: + /* we already handled all of these, with the possible exception of + * SSL3_RT_HANDSHAKE when s->in_handshake is set, but that should not + * happen when type != rr->type */ + al = SSL_AD_UNEXPECTED_MESSAGE; + OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, ERR_R_INTERNAL_ERROR); + goto f_err; + + case SSL3_RT_APPLICATION_DATA: + /* At this point we were expecting handshake data but have application + * data. If the library was running inside ssl3_read() (i.e. + * |in_read_app_data| is set) and it makes sense to read application data + * at this point (session renegotiation not yet started), we will indulge + * it. */ + if (s->s3->in_read_app_data && s->s3->total_renegotiations != 0 && + (((s->state & SSL_ST_CONNECT) && + s->state >= SSL3_ST_CW_CLNT_HELLO_A && + s->state <= SSL3_ST_CR_SRVR_HELLO_A) || + ((s->state & SSL_ST_ACCEPT) && + s->state <= SSL3_ST_SW_HELLO_REQ_A && + s->state >= SSL3_ST_SR_CLNT_HELLO_A))) { + s->s3->in_read_app_data = 2; + return -1; + } else { + al = SSL_AD_UNEXPECTED_MESSAGE; + OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_UNEXPECTED_RECORD); + goto f_err; + } + } + /* not reached */ 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_do_change_cipher_spec(SSL *s) - { - int i; +int ssl3_do_change_cipher_spec(SSL *s) { + int i; - if (s->state & SSL_ST_ACCEPT) - i=SSL3_CHANGE_CIPHER_SERVER_READ; - else - i=SSL3_CHANGE_CIPHER_CLIENT_READ; + if (s->state & SSL_ST_ACCEPT) { + i = SSL3_CHANGE_CIPHER_SERVER_READ; + } else { + i = SSL3_CHANGE_CIPHER_CLIENT_READ; + } - if (s->s3->tmp.key_block == NULL) - { - if (s->session == NULL || s->session->master_key_length == 0) - { - /* might happen if dtls1_read_bytes() calls this */ - OPENSSL_PUT_ERROR(SSL, ssl3_do_change_cipher_spec, SSL_R_CCS_RECEIVED_EARLY); - return (0); - } + if (s->s3->tmp.key_block == NULL) { + if (s->session == NULL || s->session->master_key_length == 0) { + /* might happen if dtls1_read_bytes() calls this */ + OPENSSL_PUT_ERROR(SSL, ssl3_do_change_cipher_spec, + SSL_R_CCS_RECEIVED_EARLY); + return 0; + } - s->session->cipher=s->s3->tmp.new_cipher; - if (!s->enc_method->setup_key_block(s)) return(0); - } + s->session->cipher = s->s3->tmp.new_cipher; + if (!s->enc_method->setup_key_block(s)) { + return 0; + } + } - if (!s->enc_method->change_cipher_state(s,i)) - return(0); + if (!s->enc_method->change_cipher_state(s, i)) { + return 0; + } - return(1); - } + return 1; +} -int ssl3_send_alert(SSL *s, int level, int desc) - { - /* Map tls/ssl alert value to correct one */ - desc=s->enc_method->alert_value(desc); - if (s->version == SSL3_VERSION && desc == SSL_AD_PROTOCOL_VERSION) - desc = SSL_AD_HANDSHAKE_FAILURE; /* SSL 3.0 does not have protocol_version alerts */ - if (desc < 0) return -1; - /* If a fatal one, remove from cache */ - if ((level == 2) && (s->session != NULL)) - SSL_CTX_remove_session(s->ctx,s->session); +int ssl3_send_alert(SSL *s, int level, int desc) { + /* Map tls/ssl alert value to correct one */ + desc = s->enc_method->alert_value(desc); + if (s->version == SSL3_VERSION && desc == SSL_AD_PROTOCOL_VERSION) { + /* SSL 3.0 does not have protocol_version alerts */ + desc = SSL_AD_HANDSHAKE_FAILURE; + } + if (desc < 0) { + return -1; + } - s->s3->alert_dispatch=1; - s->s3->send_alert[0]=level; - s->s3->send_alert[1]=desc; - if (s->s3->wbuf.left == 0) /* data still being written out? */ - return s->method->ssl_dispatch_alert(s); - /* else data is still being written out, we will get written - * some time in the future */ - return -1; - } + /* If a fatal one, remove from cache */ + if (level == 2 && s->session != NULL) { + SSL_CTX_remove_session(s->ctx, s->session); + } -int ssl3_dispatch_alert(SSL *s) - { - int i,j; - void (*cb)(const SSL *ssl,int type,int val)=NULL; + s->s3->alert_dispatch = 1; + s->s3->send_alert[0] = level; + s->s3->send_alert[1] = desc; + if (s->s3->wbuf.left == 0) { + /* data is still being written out. */ + return s->method->ssl_dispatch_alert(s); + } - s->s3->alert_dispatch=0; - i = do_ssl3_write(s, SSL3_RT_ALERT, &s->s3->send_alert[0], 2, 0, 0); - if (i <= 0) - { - s->s3->alert_dispatch=1; - } - else - { - /* Alert sent to BIO. If it is important, flush it now. - * If the message does not get sent due to non-blocking IO, - * we will not worry too much. */ - if (s->s3->send_alert[0] == SSL3_AL_FATAL) - (void)BIO_flush(s->wbio); + /* else data is still being written out, we will get written some time in the + * future */ + return -1; +} - if (s->msg_callback) - s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3->send_alert, 2, s, s->msg_callback_arg); +int ssl3_dispatch_alert(SSL *s) { + int i, j; + void (*cb)(const SSL *ssl, int type, int val) = NULL; - if (s->info_callback != NULL) - cb=s->info_callback; - else if (s->ctx->info_callback != NULL) - cb=s->ctx->info_callback; + s->s3->alert_dispatch = 0; + i = do_ssl3_write(s, SSL3_RT_ALERT, &s->s3->send_alert[0], 2, 0, 0); + if (i <= 0) { + s->s3->alert_dispatch = 1; + } else { + /* Alert sent to BIO. If it is important, flush it now. If the message + * does not get sent due to non-blocking IO, we will not worry too much. */ + if (s->s3->send_alert[0] == SSL3_AL_FATAL) { + BIO_flush(s->wbio); + } - if (cb != NULL) - { - j=(s->s3->send_alert[0]<<8)|s->s3->send_alert[1]; - cb(s,SSL_CB_WRITE_ALERT,j); - } - } - return(i); - } + if (s->msg_callback) { + s->msg_callback(1, s->version, SSL3_RT_ALERT, s->s3->send_alert, 2, s, + s->msg_callback_arg); + } + + if (s->info_callback != NULL) { + cb = s->info_callback; + } else if (s->ctx->info_callback != NULL) { + cb = s->ctx->info_callback; + } + + if (cb != NULL) { + j = (s->s3->send_alert[0] << 8) | s->s3->send_alert[1]; + cb(s, SSL_CB_WRITE_ALERT, j); + } + } + + return i; +}
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index 170777b..88f462b 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c
@@ -172,2857 +172,2642 @@ #include "../crypto/internal.h" #include "../crypto/dh/internal.h" + /* INITIAL_SNIFF_BUFFER_SIZE is the number of bytes read in the initial sniff * buffer. */ #define INITIAL_SNIFF_BUFFER_SIZE 8 -int ssl3_accept(SSL *s) - { - BUF_MEM *buf = NULL; - unsigned long alg_a; - void (*cb)(const SSL *ssl,int type,int val)=NULL; - int ret= -1; - int new_state,state,skip=0; +int ssl3_accept(SSL *s) { + BUF_MEM *buf = NULL; + unsigned long alg_a; + void (*cb)(const SSL *ssl, int type, int val) = NULL; + int ret = -1; + int new_state, state, skip = 0; - assert(s->handshake_func == ssl3_accept); - assert(s->server); - assert(!SSL_IS_DTLS(s)); + assert(s->handshake_func == ssl3_accept); + assert(s->server); + assert(!SSL_IS_DTLS(s)); - ERR_clear_error(); - ERR_clear_system_error(); + ERR_clear_error(); + ERR_clear_system_error(); - if (s->info_callback != NULL) - cb=s->info_callback; - else if (s->ctx->info_callback != NULL) - cb=s->ctx->info_callback; + if (s->info_callback != NULL) { + cb = s->info_callback; + } else if (s->ctx->info_callback != NULL) { + cb = s->ctx->info_callback; + } - s->in_handshake++; + s->in_handshake++; - if (s->cert == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_accept, SSL_R_NO_CERTIFICATE_SET); - return(-1); - } + if (s->cert == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_accept, SSL_R_NO_CERTIFICATE_SET); + return -1; + } - for (;;) - { - state=s->state; + for (;;) { + state = s->state; - switch (s->state) - { - case SSL_ST_RENEGOTIATE: - /* This state is the renegotiate entry point. It sends a - * HelloRequest and nothing else. */ - s->renegotiate = 1; + switch (s->state) { + case SSL_ST_RENEGOTIATE: + /* This state is the renegotiate entry point. It sends a HelloRequest + * and nothing else. */ + s->renegotiate = 1; - if (cb != NULL) - cb(s, SSL_CB_HANDSHAKE_START, 1); + if (cb != NULL) { + cb(s, SSL_CB_HANDSHAKE_START, 1); + } - if (s->init_buf == NULL) - { - buf = BUF_MEM_new(); - if (!buf || !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) - { - ret = -1; - goto end; - } - s->init_buf = buf; - buf = NULL; - } - s->init_num = 0; + if (s->init_buf == NULL) { + buf = BUF_MEM_new(); + if (!buf || !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) { + ret = -1; + goto end; + } + s->init_buf = buf; + buf = NULL; + } + s->init_num = 0; - if (!ssl3_setup_buffers(s)) - { - ret = -1; - goto end; - } + if (!ssl3_setup_buffers(s)) { + ret = -1; + goto end; + } - if (!s->s3->send_connection_binding && - !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) - { - /* Server attempting to renegotiate with - * client that doesn't support secure - * renegotiation. - */ - OPENSSL_PUT_ERROR(SSL, ssl3_accept, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); - ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE); - ret = -1; - goto end; - } + if (!s->s3->send_connection_binding && + !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) { + /* Server attempting to renegotiate with client that doesn't support + * secure renegotiation. */ + OPENSSL_PUT_ERROR(SSL, ssl3_accept, + SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + ret = -1; + goto end; + } - s->ctx->stats.sess_accept_renegotiate++; - s->state = SSL3_ST_SW_HELLO_REQ_A; - break; + s->ctx->stats.sess_accept_renegotiate++; + s->state = SSL3_ST_SW_HELLO_REQ_A; + break; - case SSL3_ST_SW_HELLO_REQ_A: - case SSL3_ST_SW_HELLO_REQ_B: + case SSL3_ST_SW_HELLO_REQ_A: + case SSL3_ST_SW_HELLO_REQ_B: + s->shutdown = 0; + ret = ssl3_send_hello_request(s); + if (ret <= 0) { + goto end; + } + s->s3->tmp.next_state = SSL3_ST_SW_HELLO_REQ_C; + s->state = SSL3_ST_SW_FLUSH; + s->init_num = 0; - s->shutdown=0; - ret=ssl3_send_hello_request(s); - if (ret <= 0) goto end; - s->s3->tmp.next_state=SSL3_ST_SW_HELLO_REQ_C; - s->state=SSL3_ST_SW_FLUSH; - s->init_num=0; + if (!ssl3_init_finished_mac(s)) { + OPENSSL_PUT_ERROR(SSL, ssl3_accept, ERR_R_INTERNAL_ERROR); + ret = -1; + goto end; + } + break; - if (!ssl3_init_finished_mac(s)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_accept, ERR_R_INTERNAL_ERROR); - ret = -1; - goto end; - } - break; + case SSL3_ST_SW_HELLO_REQ_C: + s->state = SSL_ST_OK; + break; - case SSL3_ST_SW_HELLO_REQ_C: - s->state=SSL_ST_OK; - break; + case SSL_ST_ACCEPT: + case SSL_ST_BEFORE | SSL_ST_ACCEPT: + /* This state is the entry point for the handshake itself (initial and + * renegotiation). */ + if (cb != NULL) { + cb(s, SSL_CB_HANDSHAKE_START, 1); + } - case SSL_ST_ACCEPT: - case SSL_ST_BEFORE|SSL_ST_ACCEPT: - /* This state is the entry point for the handshake - * itself (initial and renegotiation). */ - if (cb != NULL) - cb(s, SSL_CB_HANDSHAKE_START, 1); + if (s->init_buf == NULL) { + buf = BUF_MEM_new(); + if (!buf || !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) { + ret = -1; + goto end; + } + s->init_buf = buf; + buf = NULL; + } + s->init_num = 0; - if (s->init_buf == NULL) - { - buf = BUF_MEM_new(); - if (!buf || !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) - { - ret = -1; - goto end; - } - s->init_buf = buf; - buf = NULL; - } - s->init_num = 0; + if (!ssl3_init_finished_mac(s)) { + OPENSSL_PUT_ERROR(SSL, ssl3_accept, ERR_R_INTERNAL_ERROR); + ret = -1; + goto end; + } - if (!ssl3_init_finished_mac(s)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_accept, ERR_R_INTERNAL_ERROR); - ret = -1; - goto end; - } + if (!s->s3->have_version) { + /* This is the initial handshake. The record layer has not been + * initialized yet. Sniff for a V2ClientHello before reading a + * ClientHello normally. */ + assert(s->s3->rbuf.buf == NULL); + assert(s->s3->wbuf.buf == NULL); + s->state = SSL3_ST_SR_INITIAL_BYTES; + } else { + /* Enable a write buffer. This groups handshake messages within a + * flight into a single write. */ + if (!ssl3_setup_buffers(s) || !ssl_init_wbio_buffer(s, 1)) { + ret = -1; + goto end; + } + s->state = SSL3_ST_SR_CLNT_HELLO_A; + } + s->ctx->stats.sess_accept++; + break; - if (!s->s3->have_version) - { - /* This is the initial handshake. The record - * layer has not been initialized yet. Sniff for - * a V2ClientHello before reading a ClientHello - * normally. */ - assert(s->s3->rbuf.buf == NULL); - assert(s->s3->wbuf.buf == NULL); - s->state = SSL3_ST_SR_INITIAL_BYTES; - } - else - { - /* Enable a write buffer. This groups handshake - * messages within a flight into a single - * write. */ - if (!ssl3_setup_buffers(s) || - !ssl_init_wbio_buffer(s, 1)) - { - ret = -1; - goto end; - } - s->state = SSL3_ST_SR_CLNT_HELLO_A; - } - s->ctx->stats.sess_accept++; - break; + case SSL3_ST_SR_INITIAL_BYTES: + ret = ssl3_get_initial_bytes(s); + if (ret <= 0) { + goto end; + } + /* ssl3_get_initial_bytes sets s->state to one of + * SSL3_ST_SR_V2_CLIENT_HELLO or SSL3_ST_SR_CLNT_HELLO_A on success. */ + break; - case SSL3_ST_SR_INITIAL_BYTES: - ret = ssl3_get_initial_bytes(s); - if (ret <= 0) - goto end; - /* ssl3_get_initial_bytes sets s->state to one of - * SSL3_ST_SR_V2_CLIENT_HELLO or SSL3_ST_SR_CLNT_HELLO_A - * on success. */ - break; + case SSL3_ST_SR_V2_CLIENT_HELLO: + ret = ssl3_get_v2_client_hello(s); + if (ret <= 0) { + goto end; + } + s->state = SSL3_ST_SR_CLNT_HELLO_A; + break; - case SSL3_ST_SR_V2_CLIENT_HELLO: - ret = ssl3_get_v2_client_hello(s); - if (ret <= 0) - goto end; - s->state = SSL3_ST_SR_CLNT_HELLO_A; - break; + case SSL3_ST_SR_CLNT_HELLO_A: + case SSL3_ST_SR_CLNT_HELLO_B: + case SSL3_ST_SR_CLNT_HELLO_C: + case SSL3_ST_SR_CLNT_HELLO_D: + s->shutdown = 0; + ret = ssl3_get_client_hello(s); + if (ret == PENDING_SESSION) { + s->rwstate = SSL_PENDING_SESSION; + goto end; + } + if (ret == CERTIFICATE_SELECTION_PENDING) { + s->rwstate = SSL_CERTIFICATE_SELECTION_PENDING; + goto end; + } + if (ret <= 0) { + goto end; + } + s->renegotiate = 2; + s->state = SSL3_ST_SW_SRVR_HELLO_A; + s->init_num = 0; + break; - case SSL3_ST_SR_CLNT_HELLO_A: - case SSL3_ST_SR_CLNT_HELLO_B: - case SSL3_ST_SR_CLNT_HELLO_C: - case SSL3_ST_SR_CLNT_HELLO_D: - s->shutdown=0; - ret=ssl3_get_client_hello(s); - if (ret == PENDING_SESSION) { - s->rwstate = SSL_PENDING_SESSION; - goto end; - } - if (ret == CERTIFICATE_SELECTION_PENDING) - { - s->rwstate = SSL_CERTIFICATE_SELECTION_PENDING; - goto end; - } - if (ret <= 0) goto end; - s->renegotiate = 2; - s->state=SSL3_ST_SW_SRVR_HELLO_A; - s->init_num=0; - break; + case SSL3_ST_SW_SRVR_HELLO_A: + case SSL3_ST_SW_SRVR_HELLO_B: + ret = ssl3_send_server_hello(s); + if (ret <= 0) { + goto end; + } + if (s->hit) { + if (s->tlsext_ticket_expected) { + s->state = SSL3_ST_SW_SESSION_TICKET_A; + } else { + s->state = SSL3_ST_SW_CHANGE_A; + } + } else { + s->state = SSL3_ST_SW_CERT_A; + } + s->init_num = 0; + break; - case SSL3_ST_SW_SRVR_HELLO_A: - case SSL3_ST_SW_SRVR_HELLO_B: - ret=ssl3_send_server_hello(s); - if (ret <= 0) goto end; - if (s->hit) - { - if (s->tlsext_ticket_expected) - s->state=SSL3_ST_SW_SESSION_TICKET_A; - else - s->state=SSL3_ST_SW_CHANGE_A; - } - else - s->state = SSL3_ST_SW_CERT_A; - s->init_num = 0; - break; + case SSL3_ST_SW_CERT_A: + case SSL3_ST_SW_CERT_B: + if (ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) { + ret = ssl3_send_server_certificate(s); + if (ret <= 0) { + goto end; + } + if (s->s3->tmp.certificate_status_expected) { + s->state = SSL3_ST_SW_CERT_STATUS_A; + } else { + s->state = SSL3_ST_SW_KEY_EXCH_A; + } + } else { + skip = 1; + s->state = SSL3_ST_SW_KEY_EXCH_A; + } + s->init_num = 0; + break; - case SSL3_ST_SW_CERT_A: - case SSL3_ST_SW_CERT_B: - if (ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) - { - ret=ssl3_send_server_certificate(s); - if (ret <= 0) goto end; - if (s->s3->tmp.certificate_status_expected) - s->state=SSL3_ST_SW_CERT_STATUS_A; - else - s->state=SSL3_ST_SW_KEY_EXCH_A; - } - else - { - skip = 1; - s->state=SSL3_ST_SW_KEY_EXCH_A; - } - s->init_num=0; - break; + case SSL3_ST_SW_KEY_EXCH_A: + case SSL3_ST_SW_KEY_EXCH_B: + alg_a = s->s3->tmp.new_cipher->algorithm_auth; - case SSL3_ST_SW_KEY_EXCH_A: - case SSL3_ST_SW_KEY_EXCH_B: - alg_a = s->s3->tmp.new_cipher->algorithm_auth; + /* Send a ServerKeyExchange message if: + * - The key exchange is ephemeral or anonymous + * Diffie-Hellman. + * - There is a PSK identity hint. + * + * TODO(davidben): This logic is currently duplicated in d1_srvr.c. Fix + * this. In the meantime, keep them in sync. */ + if (ssl_cipher_requires_server_key_exchange(s->s3->tmp.new_cipher) || + ((alg_a & SSL_aPSK) && s->psk_identity_hint)) { + ret = ssl3_send_server_key_exchange(s); + if (ret <= 0) + goto end; + } else { + skip = 1; + } - /* Send a ServerKeyExchange message if: - * - The key exchange is ephemeral or anonymous - * Diffie-Hellman. - * - There is a PSK identity hint. - * - * TODO(davidben): This logic is currently duplicated - * in d1_srvr.c. Fix this. In the meantime, keep them - * in sync. - */ - if (ssl_cipher_requires_server_key_exchange(s->s3->tmp.new_cipher) || - ((alg_a & SSL_aPSK) && s->psk_identity_hint)) - { - ret=ssl3_send_server_key_exchange(s); - if (ret <= 0) goto end; - } - else - skip=1; + s->state = SSL3_ST_SW_CERT_REQ_A; + s->init_num = 0; + break; - s->state=SSL3_ST_SW_CERT_REQ_A; - s->init_num=0; - break; - - case SSL3_ST_SW_CERT_REQ_A: - case SSL3_ST_SW_CERT_REQ_B: - if (/* don't request cert unless asked for it: */ - !(s->verify_mode & SSL_VERIFY_PEER) || - /* Don't request a certificate if an obc was presented */ - ((s->verify_mode & SSL_VERIFY_PEER_IF_NO_OBC) && - s->s3->tlsext_channel_id_valid) || - /* if SSL_VERIFY_CLIENT_ONCE is set, - * don't request cert during re-negotiation: */ - ((s->session->peer != NULL) && - (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) || - /* never request cert in anonymous ciphersuites - * (see section "Certificate request" in SSL 3 drafts - * and in RFC 2246): */ - ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && - /* ... except when the application insists on verification - * (against the specs, but s3_clnt.c accepts this for SSL 3) */ - !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) || - /* With normal PSK Certificates and - * Certificate Requests are omitted */ - (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) - { - /* no cert request */ - skip=1; - s->s3->tmp.cert_request=0; - s->state=SSL3_ST_SW_SRVR_DONE_A; - if (s->s3->handshake_buffer) - if (!ssl3_digest_cached_records(s, free_handshake_buffer)) - return -1; - } - else - { - s->s3->tmp.cert_request=1; - ret=ssl3_send_certificate_request(s); - if (ret <= 0) goto end; + case SSL3_ST_SW_CERT_REQ_A: + case SSL3_ST_SW_CERT_REQ_B: + if (/* don't request cert unless asked for it: */ + !(s->verify_mode & SSL_VERIFY_PEER) || + /* Don't request a certificate if an obc was presented */ + ((s->verify_mode & SSL_VERIFY_PEER_IF_NO_OBC) && + s->s3->tlsext_channel_id_valid) || + /* if SSL_VERIFY_CLIENT_ONCE is set, + * don't request cert during re-negotiation: */ + ((s->session->peer != NULL) && + (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) || + /* never request cert in anonymous ciphersuites + * (see section "Certificate request" in SSL 3 drafts + * and in RFC 2246): */ + ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) && + /* ... except when the application insists on verification + * (against the specs, but s3_clnt.c accepts this for SSL 3) */ + !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) || + /* With normal PSK Certificates and + * Certificate Requests are omitted */ + (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { + /* no cert request */ + skip = 1; + s->s3->tmp.cert_request = 0; + s->state = SSL3_ST_SW_SRVR_DONE_A; + if (s->s3->handshake_buffer && + !ssl3_digest_cached_records(s, free_handshake_buffer)) { + return -1; + } + } else { + s->s3->tmp.cert_request = 1; + ret = ssl3_send_certificate_request(s); + if (ret <= 0) { + goto end; + } #ifndef NETSCAPE_HANG_BUG - s->state=SSL3_ST_SW_SRVR_DONE_A; + s->state = SSL3_ST_SW_SRVR_DONE_A; #else - /* ServerHelloDone was already sent in the - * previous record. */ - s->state=SSL3_ST_SW_FLUSH; - s->s3->tmp.next_state=SSL3_ST_SR_CERT_A; + /* ServerHelloDone was already sent in the + * previous record. */ + s->state = SSL3_ST_SW_FLUSH; + s->s3->tmp.next_state = SSL3_ST_SR_CERT_A; #endif - s->init_num=0; - } - break; + s->init_num = 0; + } + break; - case SSL3_ST_SW_SRVR_DONE_A: - case SSL3_ST_SW_SRVR_DONE_B: - ret=ssl3_send_server_done(s); - if (ret <= 0) goto end; - s->s3->tmp.next_state=SSL3_ST_SR_CERT_A; - s->state=SSL3_ST_SW_FLUSH; - s->init_num=0; - break; - - case SSL3_ST_SW_FLUSH: + case SSL3_ST_SW_SRVR_DONE_A: + case SSL3_ST_SW_SRVR_DONE_B: + ret = ssl3_send_server_done(s); + if (ret <= 0) { + goto end; + } + s->s3->tmp.next_state = SSL3_ST_SR_CERT_A; + s->state = SSL3_ST_SW_FLUSH; + s->init_num = 0; + break; - /* This code originally checked to see if - * any data was pending using BIO_CTRL_INFO - * and then flushed. This caused problems - * as documented in PR#1939. The proposed - * fix doesn't completely resolve this issue - * as buggy implementations of BIO_CTRL_PENDING - * still exist. So instead we just flush - * unconditionally. - */ + case SSL3_ST_SW_FLUSH: + /* This code originally checked to see if any data was pending using + * BIO_CTRL_INFO and then flushed. This caused problems as documented + * in PR#1939. The proposed fix doesn't completely resolve this issue + * as buggy implementations of BIO_CTRL_PENDING still exist. So instead + * we just flush unconditionally. */ + s->rwstate = SSL_WRITING; + if (BIO_flush(s->wbio) <= 0) { + ret = -1; + goto end; + } + s->rwstate = SSL_NOTHING; - 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; - s->state=s->s3->tmp.next_state; - break; + case SSL3_ST_SR_CERT_A: + case SSL3_ST_SR_CERT_B: + if (s->s3->tmp.cert_request) { + ret = ssl3_get_client_certificate(s); + if (ret <= 0) { + goto end; + } + } + s->init_num = 0; + s->state = SSL3_ST_SR_KEY_EXCH_A; + break; - case SSL3_ST_SR_CERT_A: - case SSL3_ST_SR_CERT_B: - if (s->s3->tmp.cert_request) - { - ret=ssl3_get_client_certificate(s); - if (ret <= 0) goto end; - } - s->init_num=0; - s->state=SSL3_ST_SR_KEY_EXCH_A; - break; + case SSL3_ST_SR_KEY_EXCH_A: + case SSL3_ST_SR_KEY_EXCH_B: + ret = ssl3_get_client_key_exchange(s); + if (ret <= 0) { + goto end; + } + s->state = SSL3_ST_SR_CERT_VRFY_A; + s->init_num = 0; + break; - case SSL3_ST_SR_KEY_EXCH_A: - case SSL3_ST_SR_KEY_EXCH_B: - ret=ssl3_get_client_key_exchange(s); - if (ret <= 0) - goto end; - s->state=SSL3_ST_SR_CERT_VRFY_A; - s->init_num=0; - break; + case SSL3_ST_SR_CERT_VRFY_A: + case SSL3_ST_SR_CERT_VRFY_B: + ret = ssl3_get_cert_verify(s); + if (ret <= 0) { + goto end; + } - case SSL3_ST_SR_CERT_VRFY_A: - case SSL3_ST_SR_CERT_VRFY_B: - ret=ssl3_get_cert_verify(s); - if (ret <= 0) goto end; + s->state = SSL3_ST_SR_CHANGE; + s->init_num = 0; + break; - s->state = SSL3_ST_SR_CHANGE; - s->init_num=0; - break; + case SSL3_ST_SR_CHANGE: { + char next_proto_neg = 0; + char channel_id = 0; + next_proto_neg = s->s3->next_proto_neg_seen; + channel_id = s->s3->tlsext_channel_id_valid; - case SSL3_ST_SR_CHANGE: { - char next_proto_neg = 0; - char channel_id = 0; - next_proto_neg = s->s3->next_proto_neg_seen; - channel_id = s->s3->tlsext_channel_id_valid; + /* At this point, the next message must be entirely behind a + * ChangeCipherSpec. */ + if (!ssl3_expect_change_cipher_spec(s)) { + ret = -1; + goto end; + } + if (next_proto_neg) { + s->state = SSL3_ST_SR_NEXT_PROTO_A; + } else if (channel_id) { + s->state = SSL3_ST_SR_CHANNEL_ID_A; + } else { + s->state = SSL3_ST_SR_FINISHED_A; + } + break; + } - /* At this point, the next message must be entirely - * behind a ChangeCipherSpec. */ - if (!ssl3_expect_change_cipher_spec(s)) - { - ret = -1; - goto end; - } - if (next_proto_neg) - s->state = SSL3_ST_SR_NEXT_PROTO_A; - else if (channel_id) - s->state = SSL3_ST_SR_CHANNEL_ID_A; - else - s->state = SSL3_ST_SR_FINISHED_A; - break; - } + case SSL3_ST_SR_NEXT_PROTO_A: + case SSL3_ST_SR_NEXT_PROTO_B: + ret = ssl3_get_next_proto(s); + if (ret <= 0) { + goto end; + } + s->init_num = 0; + if (s->s3->tlsext_channel_id_valid) { + s->state = SSL3_ST_SR_CHANNEL_ID_A; + } else { + s->state = SSL3_ST_SR_FINISHED_A; + } + break; - case SSL3_ST_SR_NEXT_PROTO_A: - case SSL3_ST_SR_NEXT_PROTO_B: - ret=ssl3_get_next_proto(s); - if (ret <= 0) goto end; - s->init_num = 0; - if (s->s3->tlsext_channel_id_valid) - s->state=SSL3_ST_SR_CHANNEL_ID_A; - else - s->state=SSL3_ST_SR_FINISHED_A; - break; + case SSL3_ST_SR_CHANNEL_ID_A: + case SSL3_ST_SR_CHANNEL_ID_B: + ret = ssl3_get_channel_id(s); + if (ret <= 0) { + goto end; + } + s->init_num = 0; + s->state = SSL3_ST_SR_FINISHED_A; + break; - case SSL3_ST_SR_CHANNEL_ID_A: - case SSL3_ST_SR_CHANNEL_ID_B: - ret=ssl3_get_channel_id(s); - if (ret <= 0) goto end; - s->init_num = 0; - s->state=SSL3_ST_SR_FINISHED_A; - break; + case SSL3_ST_SR_FINISHED_A: + case SSL3_ST_SR_FINISHED_B: + ret = + ssl3_get_finished(s, SSL3_ST_SR_FINISHED_A, SSL3_ST_SR_FINISHED_B); + if (ret <= 0) { + goto end; + } - case SSL3_ST_SR_FINISHED_A: - case SSL3_ST_SR_FINISHED_B: - ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A, - SSL3_ST_SR_FINISHED_B); - if (ret <= 0) goto end; - if (s->hit) - s->state=SSL_ST_OK; - else if (s->tlsext_ticket_expected) - s->state=SSL3_ST_SW_SESSION_TICKET_A; - else - s->state=SSL3_ST_SW_CHANGE_A; - /* If this is a full handshake with ChannelID then - * record the hashshake hashes in |s->session| in case - * we need them to verify a ChannelID signature on a - * resumption of this session in the future. */ - if (!s->hit && s->s3->tlsext_channel_id_new) - { - ret = tls1_record_handshake_hashes_for_channel_id(s); - if (ret <= 0) goto end; - } - s->init_num=0; - break; + if (s->hit) { + s->state = SSL_ST_OK; + } else if (s->tlsext_ticket_expected) { + s->state = SSL3_ST_SW_SESSION_TICKET_A; + } else { + s->state = SSL3_ST_SW_CHANGE_A; + } + /* If this is a full handshake with ChannelID then record the hashshake + * hashes in |s->session| in case we need them to verify a ChannelID + * signature on a resumption of this session in the future. */ + if (!s->hit && s->s3->tlsext_channel_id_new) { + ret = tls1_record_handshake_hashes_for_channel_id(s); + if (ret <= 0) { + goto end; + } + } + s->init_num = 0; + break; - case SSL3_ST_SW_SESSION_TICKET_A: - case SSL3_ST_SW_SESSION_TICKET_B: - ret=ssl3_send_new_session_ticket(s); - if (ret <= 0) goto end; - s->state=SSL3_ST_SW_CHANGE_A; - s->init_num=0; - break; + case SSL3_ST_SW_SESSION_TICKET_A: + case SSL3_ST_SW_SESSION_TICKET_B: + ret = ssl3_send_new_session_ticket(s); + if (ret <= 0) { + goto end; + } + s->state = SSL3_ST_SW_CHANGE_A; + s->init_num = 0; + break; -#if 0 - // TODO(davidben): Implement OCSP stapling on the server. - case SSL3_ST_SW_CERT_STATUS_A: - case SSL3_ST_SW_CERT_STATUS_B: - ret=ssl3_send_cert_status(s); - if (ret <= 0) goto end; - s->state=SSL3_ST_SW_KEY_EXCH_A; - s->init_num=0; - break; -#endif + case SSL3_ST_SW_CHANGE_A: + case SSL3_ST_SW_CHANGE_B: + s->session->cipher = s->s3->tmp.new_cipher; + if (!s->enc_method->setup_key_block(s)) { + ret = -1; + goto end; + } - case SSL3_ST_SW_CHANGE_A: - case SSL3_ST_SW_CHANGE_B: + ret = ssl3_send_change_cipher_spec(s, SSL3_ST_SW_CHANGE_A, + SSL3_ST_SW_CHANGE_B); + if (ret <= 0) { + goto end; + } + s->state = SSL3_ST_SW_FINISHED_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; } + if (!s->enc_method->change_cipher_state( + s, SSL3_CHANGE_CIPHER_SERVER_WRITE)) { + ret = -1; + goto end; + } + break; - ret=ssl3_send_change_cipher_spec(s, - SSL3_ST_SW_CHANGE_A,SSL3_ST_SW_CHANGE_B); + case SSL3_ST_SW_FINISHED_A: + case SSL3_ST_SW_FINISHED_B: + ret = + ssl3_send_finished(s, SSL3_ST_SW_FINISHED_A, SSL3_ST_SW_FINISHED_B, + s->enc_method->server_finished_label, + s->enc_method->server_finished_label_len); + if (ret <= 0) { + goto end; + } + s->state = SSL3_ST_SW_FLUSH; + if (s->hit) { + s->s3->tmp.next_state = SSL3_ST_SR_CHANGE; + } else { + s->s3->tmp.next_state = SSL_ST_OK; + } + s->init_num = 0; + break; - if (ret <= 0) goto end; - s->state=SSL3_ST_SW_FINISHED_A; - s->init_num=0; + case SSL_ST_OK: + /* clean a few things up */ + ssl3_cleanup_key_block(s); - if (!s->enc_method->change_cipher_state(s, - SSL3_CHANGE_CIPHER_SERVER_WRITE)) - { - ret= -1; - goto end; - } + BUF_MEM_free(s->init_buf); + s->init_buf = NULL; - break; + /* remove buffering on output */ + ssl_free_wbio_buffer(s); - case SSL3_ST_SW_FINISHED_A: - case SSL3_ST_SW_FINISHED_B: - ret=ssl3_send_finished(s, - SSL3_ST_SW_FINISHED_A,SSL3_ST_SW_FINISHED_B, - s->enc_method->server_finished_label, - s->enc_method->server_finished_label_len); - if (ret <= 0) goto end; - s->state = SSL3_ST_SW_FLUSH; - if (s->hit) - s->s3->tmp.next_state = SSL3_ST_SR_CHANGE; - else - s->s3->tmp.next_state = SSL_ST_OK; - s->init_num=0; - break; + s->init_num = 0; - case SSL_ST_OK: - /* clean a few things up */ - ssl3_cleanup_key_block(s); + /* If we aren't retaining peer certificates then we can discard it + * now. */ + if (s->session->peer && s->ctx->retain_only_sha256_of_client_certs) { + X509_free(s->session->peer); + s->session->peer = NULL; + } - BUF_MEM_free(s->init_buf); - s->init_buf=NULL; + if (s->renegotiate == 2) { + /* skipped if we just sent a HelloRequest */ + s->renegotiate = 0; + s->new_session = 0; - /* remove buffering on output */ - ssl_free_wbio_buffer(s); + ssl_update_cache(s, SSL_SESS_CACHE_SERVER); - s->init_num=0; + s->ctx->stats.sess_accept_good++; - /* If we aren't retaining peer certificates then we can - * discard it now. */ - if (s->session->peer && s->ctx->retain_only_sha256_of_client_certs) - { - X509_free(s->session->peer); - s->session->peer = NULL; - } + if (cb != NULL) { + cb(s, SSL_CB_HANDSHAKE_DONE, 1); + } + } - if (s->renegotiate == 2) /* skipped if we just sent a HelloRequest */ - { - s->renegotiate=0; - s->new_session=0; - - ssl_update_cache(s,SSL_SESS_CACHE_SERVER); - - s->ctx->stats.sess_accept_good++; - /* s->server=1; */ + ret = 1; + goto end; - if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1); - } - - ret = 1; - goto end; - /* break; */ + default: + OPENSSL_PUT_ERROR(SSL, ssl3_accept, SSL_R_UNKNOWN_STATE); + ret = -1; + goto end; + } - default: - OPENSSL_PUT_ERROR(SSL, ssl3_accept, SSL_R_UNKNOWN_STATE); - ret= -1; - goto end; - /* break; */ - } - - if (!s->s3->tmp.reuse_message && !skip) - { - if ((cb != NULL) && (s->state != state)) - { - new_state=s->state; - s->state=state; - cb(s,SSL_CB_ACCEPT_LOOP,1); - s->state=new_state; - } - } - skip=0; - } + if (!s->s3->tmp.reuse_message && !skip && cb != NULL && s->state != state) { + new_state = s->state; + s->state = state; + cb(s, SSL_CB_ACCEPT_LOOP, 1); + s->state = new_state; + } + skip = 0; + } + end: - /* BIO_flush(s->wbio); */ + s->in_handshake--; + if (buf != NULL) { + BUF_MEM_free(buf); + } + if (cb != NULL) { + cb(s, SSL_CB_ACCEPT_EXIT, ret); + } + return ret; +} - s->in_handshake--; - if (buf != NULL) - BUF_MEM_free(buf); - if (cb != NULL) - cb(s,SSL_CB_ACCEPT_EXIT,ret); - return(ret); - } +static int ssl3_read_sniff_buffer(SSL *s, size_t n) { + if (s->s3->sniff_buffer == NULL) { + s->s3->sniff_buffer = BUF_MEM_new(); + } + if (s->s3->sniff_buffer == NULL || !BUF_MEM_grow(s->s3->sniff_buffer, n)) { + return -1; + } -static int ssl3_read_sniff_buffer(SSL *s, size_t n) - { - if (s->s3->sniff_buffer == NULL) - { - s->s3->sniff_buffer = BUF_MEM_new(); - } - if (s->s3->sniff_buffer == NULL || - !BUF_MEM_grow(s->s3->sniff_buffer, n)) - { - return -1; - } + while (s->s3->sniff_buffer_len < n) { + int ret; - while (s->s3->sniff_buffer_len < n) - { - int ret; + s->rwstate = SSL_READING; + ret = BIO_read(s->rbio, s->s3->sniff_buffer->data + s->s3->sniff_buffer_len, + n - s->s3->sniff_buffer_len); + if (ret <= 0) { + return ret; + } + s->rwstate = SSL_NOTHING; + s->s3->sniff_buffer_len += ret; + } - s->rwstate = SSL_READING; - ret = BIO_read(s->rbio, - s->s3->sniff_buffer->data + s->s3->sniff_buffer_len, - n - s->s3->sniff_buffer_len); - if (ret <= 0) - return ret; - s->rwstate = SSL_NOTHING; - s->s3->sniff_buffer_len += ret; - } - return 1; - } + return 1; +} -int ssl3_get_initial_bytes(SSL *s) - { - int ret; - const uint8_t *p; +int ssl3_get_initial_bytes(SSL *s) { + int ret; + const uint8_t *p; - /* Read the first 8 bytes. To recognize a ClientHello or V2ClientHello - * only needs the first 6 bytes, but 8 is needed to recognize CONNECT - * below. */ - ret = ssl3_read_sniff_buffer(s, INITIAL_SNIFF_BUFFER_SIZE); - if (ret <= 0) - return ret; - assert(s->s3->sniff_buffer_len >= INITIAL_SNIFF_BUFFER_SIZE); - p = (const uint8_t *)s->s3->sniff_buffer->data; + /* Read the first 8 bytes. To recognize a ClientHello or V2ClientHello only + * needs the first 6 bytes, but 8 is needed to recognize CONNECT below. */ + ret = ssl3_read_sniff_buffer(s, INITIAL_SNIFF_BUFFER_SIZE); + if (ret <= 0) { + return ret; + } + assert(s->s3->sniff_buffer_len >= INITIAL_SNIFF_BUFFER_SIZE); + p = (const uint8_t *)s->s3->sniff_buffer->data; - /* Some dedicated error codes for protocol mixups should the application - * wish to interpret them differently. (These do not overlap with - * ClientHello or V2ClientHello.) */ - if (strncmp("GET ", (const char *)p, 4) == 0 || - strncmp("POST ", (const char *)p, 5) == 0 || - strncmp("HEAD ", (const char *)p, 5) == 0 || - strncmp("PUT ", (const char *)p, 4) == 0) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_initial_bytes, SSL_R_HTTP_REQUEST); - return -1; - } - if (strncmp("CONNECT ", (const char *)p, 8) == 0) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_initial_bytes, SSL_R_HTTPS_PROXY_REQUEST); - return -1; - } + /* Some dedicated error codes for protocol mixups should the application wish + * to interpret them differently. (These do not overlap with ClientHello or + * V2ClientHello.) */ + if (strncmp("GET ", (const char *)p, 4) == 0 || + strncmp("POST ", (const char *)p, 5) == 0 || + strncmp("HEAD ", (const char *)p, 5) == 0 || + strncmp("PUT ", (const char *)p, 4) == 0) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_initial_bytes, SSL_R_HTTP_REQUEST); + return -1; + } + if (strncmp("CONNECT ", (const char *)p, 8) == 0) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_initial_bytes, SSL_R_HTTPS_PROXY_REQUEST); + return -1; + } - /* Determine if this is a ClientHello or V2ClientHello. */ + /* Determine if this is a ClientHello or V2ClientHello. */ + if ((p[0] & 0x80) && p[2] == SSL2_MT_CLIENT_HELLO && + p[3] >= SSL3_VERSION_MAJOR) { + /* This is a V2ClientHello. */ + s->state = SSL3_ST_SR_V2_CLIENT_HELLO; + return 1; + } + if (p[0] == SSL3_RT_HANDSHAKE && p[1] >= SSL3_VERSION_MAJOR && + p[5] == SSL3_MT_CLIENT_HELLO) { + /* This is a ClientHello. Initialize the record layer with the already + * consumed data and continue the handshake. */ + if (!ssl3_setup_buffers(s) || !ssl_init_wbio_buffer(s, 1)) { + return -1; + } + assert(s->rstate == SSL_ST_READ_HEADER); + memcpy(s->s3->rbuf.buf, p, s->s3->sniff_buffer_len); + s->s3->rbuf.offset = 0; + s->s3->rbuf.left = s->s3->sniff_buffer_len; + s->packet_length = 0; - if ((p[0] & 0x80) && p[2] == SSL2_MT_CLIENT_HELLO && - p[3] >= SSL3_VERSION_MAJOR) - { - /* This is a V2ClientHello. */ - s->state = SSL3_ST_SR_V2_CLIENT_HELLO; - return 1; - } - if (p[0] == SSL3_RT_HANDSHAKE && p[1] >= SSL3_VERSION_MAJOR && - p[5] == SSL3_MT_CLIENT_HELLO) - { - /* This is a ClientHello. Initialize the record layer with the - * already consumed data and continue the handshake. */ - if (!ssl3_setup_buffers(s) || !ssl_init_wbio_buffer(s, 1)) - { - return -1; - } - assert(s->rstate == SSL_ST_READ_HEADER); - memcpy(s->s3->rbuf.buf, p, s->s3->sniff_buffer_len); - s->s3->rbuf.offset = 0; - s->s3->rbuf.left = s->s3->sniff_buffer_len; - s->packet_length = 0; + BUF_MEM_free(s->s3->sniff_buffer); + s->s3->sniff_buffer = NULL; + s->s3->sniff_buffer_len = 0; - BUF_MEM_free(s->s3->sniff_buffer); - s->s3->sniff_buffer = NULL; - s->s3->sniff_buffer_len = 0; + s->state = SSL3_ST_SR_CLNT_HELLO_A; + return 1; + } - s->state = SSL3_ST_SR_CLNT_HELLO_A; - return 1; - } + OPENSSL_PUT_ERROR(SSL, ssl3_get_initial_bytes, SSL_R_UNKNOWN_PROTOCOL); + return -1; +} - OPENSSL_PUT_ERROR(SSL, ssl3_get_initial_bytes, SSL_R_UNKNOWN_PROTOCOL); - return -1; - } +int ssl3_get_v2_client_hello(SSL *s) { + const uint8_t *p; + int ret; + CBS v2_client_hello, cipher_specs, session_id, challenge; + size_t msg_length, rand_len, len; + uint8_t msg_type; + uint16_t version, cipher_spec_length, session_id_length, challenge_length; + CBB client_hello, hello_body, cipher_suites; + uint8_t random[SSL3_RANDOM_SIZE]; -int ssl3_get_v2_client_hello(SSL *s) - { - const uint8_t *p; - int ret; - CBS v2_client_hello, cipher_specs, session_id, challenge; - size_t msg_length, rand_len, len; - uint8_t msg_type; - uint16_t version, cipher_spec_length, session_id_length, challenge_length; - CBB client_hello, hello_body, cipher_suites; - uint8_t random[SSL3_RANDOM_SIZE]; + /* Read the remainder of the V2ClientHello. We have previously read 8 bytes + * in ssl3_get_initial_bytes. */ + assert(s->s3->sniff_buffer_len >= INITIAL_SNIFF_BUFFER_SIZE); + p = (const uint8_t *)s->s3->sniff_buffer->data; + msg_length = ((p[0] & 0x7f) << 8) | p[1]; + if (msg_length > (1024 * 4)) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, SSL_R_RECORD_TOO_LARGE); + return -1; + } + if (msg_length < INITIAL_SNIFF_BUFFER_SIZE - 2) { + /* Reject lengths that are too short early. We have already read 8 bytes, + * so we should not attempt to process an (invalid) V2ClientHello which + * would be shorter than that. */ + OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, + SSL_R_RECORD_LENGTH_MISMATCH); + return -1; + } - /* Read the remainder of the V2ClientHello. We have previously read 8 - * bytes in ssl3_get_initial_bytes. */ - assert(s->s3->sniff_buffer_len >= INITIAL_SNIFF_BUFFER_SIZE); - p = (const uint8_t *)s->s3->sniff_buffer->data; - msg_length = ((p[0] & 0x7f) << 8) | p[1]; - if (msg_length > (1024 * 4)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, SSL_R_RECORD_TOO_LARGE); - return -1; - } - if (msg_length < INITIAL_SNIFF_BUFFER_SIZE - 2) - { - /* Reject lengths that are too short early. We have already read - * 8 bytes, so we should not attempt to process an (invalid) - * V2ClientHello which would be shorter than that. */ - OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, SSL_R_RECORD_LENGTH_MISMATCH); - return -1; - } + ret = ssl3_read_sniff_buffer(s, msg_length + 2); + if (ret <= 0) { + return ret; + } + assert(s->s3->sniff_buffer_len == msg_length + 2); + CBS_init(&v2_client_hello, (const uint8_t *)s->s3->sniff_buffer->data + 2, + msg_length); - ret = ssl3_read_sniff_buffer(s, msg_length + 2); - if (ret <= 0) - return ret; - assert(s->s3->sniff_buffer_len == msg_length + 2); - CBS_init(&v2_client_hello, - (const uint8_t *)s->s3->sniff_buffer->data + 2, msg_length); + /* The V2ClientHello without the length is incorporated into the Finished + * hash. */ + ssl3_finish_mac(s, CBS_data(&v2_client_hello), CBS_len(&v2_client_hello)); + if (s->msg_callback) { + s->msg_callback(0, SSL2_VERSION, 0, CBS_data(&v2_client_hello), + CBS_len(&v2_client_hello), s, s->msg_callback_arg); + } - /* The V2ClientHello without the length is incorporated into the - * Finished hash. */ - ssl3_finish_mac(s, CBS_data(&v2_client_hello), CBS_len(&v2_client_hello)); - if (s->msg_callback) - s->msg_callback(0, SSL2_VERSION, 0, CBS_data(&v2_client_hello), - CBS_len(&v2_client_hello), s, s->msg_callback_arg); + if (!CBS_get_u8(&v2_client_hello, &msg_type) || + !CBS_get_u16(&v2_client_hello, &version) || + !CBS_get_u16(&v2_client_hello, &cipher_spec_length) || + !CBS_get_u16(&v2_client_hello, &session_id_length) || + !CBS_get_u16(&v2_client_hello, &challenge_length) || + !CBS_get_bytes(&v2_client_hello, &cipher_specs, cipher_spec_length) || + !CBS_get_bytes(&v2_client_hello, &session_id, session_id_length) || + !CBS_get_bytes(&v2_client_hello, &challenge, challenge_length) || + CBS_len(&v2_client_hello) != 0) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, SSL_R_DECODE_ERROR); + return -1; + } - if (!CBS_get_u8(&v2_client_hello, &msg_type) || - !CBS_get_u16(&v2_client_hello, &version) || - !CBS_get_u16(&v2_client_hello, &cipher_spec_length) || - !CBS_get_u16(&v2_client_hello, &session_id_length) || - !CBS_get_u16(&v2_client_hello, &challenge_length) || - !CBS_get_bytes(&v2_client_hello, &cipher_specs, cipher_spec_length) || - !CBS_get_bytes(&v2_client_hello, &session_id, session_id_length) || - !CBS_get_bytes(&v2_client_hello, &challenge, challenge_length) || - CBS_len(&v2_client_hello) != 0) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, SSL_R_DECODE_ERROR); - return -1; - } + /* msg_type has already been checked. */ + assert(msg_type == SSL2_MT_CLIENT_HELLO); - /* msg_type has already been checked. */ - assert(msg_type == SSL2_MT_CLIENT_HELLO); + /* The client_random is the V2ClientHello challenge. Truncate or + * left-pad with zeros as needed. */ + memset(random, 0, SSL3_RANDOM_SIZE); + rand_len = CBS_len(&challenge); + if (rand_len > SSL3_RANDOM_SIZE) { + rand_len = SSL3_RANDOM_SIZE; + } + memcpy(random + (SSL3_RANDOM_SIZE - rand_len), CBS_data(&challenge), + rand_len); - /* The client_random is the V2ClientHello challenge. Truncate or - * left-pad with zeros as needed. */ - memset(random, 0, SSL3_RANDOM_SIZE); - rand_len = CBS_len(&challenge); - if (rand_len > SSL3_RANDOM_SIZE) - rand_len = SSL3_RANDOM_SIZE; - memcpy(random + (SSL3_RANDOM_SIZE - rand_len), CBS_data(&challenge), rand_len); + /* Write out an equivalent SSLv3 ClientHello. */ + if (!CBB_init_fixed(&client_hello, (uint8_t *)s->init_buf->data, + s->init_buf->max)) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, ERR_R_MALLOC_FAILURE); + return -1; + } + if (!CBB_add_u8(&client_hello, SSL3_MT_CLIENT_HELLO) || + !CBB_add_u24_length_prefixed(&client_hello, &hello_body) || + !CBB_add_u16(&hello_body, version) || + !CBB_add_bytes(&hello_body, random, SSL3_RANDOM_SIZE) || + /* No session id. */ + !CBB_add_u8(&hello_body, 0) || + !CBB_add_u16_length_prefixed(&hello_body, &cipher_suites)) { + CBB_cleanup(&client_hello); + OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, ERR_R_INTERNAL_ERROR); + return -1; + } - /* Write out an equivalent SSLv3 ClientHello. */ - if (!CBB_init_fixed(&client_hello, (uint8_t *)s->init_buf->data, s->init_buf->max)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, ERR_R_MALLOC_FAILURE); - return -1; - } - if (!CBB_add_u8(&client_hello, SSL3_MT_CLIENT_HELLO) || - !CBB_add_u24_length_prefixed(&client_hello, &hello_body) || - !CBB_add_u16(&hello_body, version) || - !CBB_add_bytes(&hello_body, random, SSL3_RANDOM_SIZE) || - /* No session id. */ - !CBB_add_u8(&hello_body, 0) || - !CBB_add_u16_length_prefixed(&hello_body, &cipher_suites)) - { - CBB_cleanup(&client_hello); - OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, ERR_R_INTERNAL_ERROR); - return -1; - } + /* Copy the cipher suites. */ + while (CBS_len(&cipher_specs) > 0) { + uint32_t cipher_spec; + if (!CBS_get_u24(&cipher_specs, &cipher_spec)) { + CBB_cleanup(&client_hello); + OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, SSL_R_DECODE_ERROR); + return -1; + } - /* Copy the cipher suites. */ - while (CBS_len(&cipher_specs) > 0) - { - uint32_t cipher_spec; - if (!CBS_get_u24(&cipher_specs, &cipher_spec)) - { - CBB_cleanup(&client_hello); - OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, SSL_R_DECODE_ERROR); - return -1; - } + /* Skip SSLv2 ciphers. */ + if ((cipher_spec & 0xff0000) != 0) { + continue; + } + if (!CBB_add_u16(&cipher_suites, cipher_spec)) { + CBB_cleanup(&client_hello); + OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, ERR_R_INTERNAL_ERROR); + return -1; + } + } - /* Skip SSLv2 ciphers. */ - if ((cipher_spec & 0xff0000) != 0) - continue; - if (!CBB_add_u16(&cipher_suites, cipher_spec)) - { - CBB_cleanup(&client_hello); - OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, ERR_R_INTERNAL_ERROR); - return -1; - } - } + /* Add the null compression scheme and finish. */ + if (!CBB_add_u8(&hello_body, 1) || !CBB_add_u8(&hello_body, 0) || + !CBB_finish(&client_hello, NULL, &len)) { + CBB_cleanup(&client_hello); + OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, ERR_R_INTERNAL_ERROR); + return -1; + } - /* Add the null compression scheme and finish. */ - if (!CBB_add_u8(&hello_body, 1) || - !CBB_add_u8(&hello_body, 0) || - !CBB_finish(&client_hello, NULL, &len)) - { - CBB_cleanup(&client_hello); - OPENSSL_PUT_ERROR(SSL, ssl3_get_v2_client_hello, ERR_R_INTERNAL_ERROR); - return -1; - } + /* Mark the message for "re"-use by the version-specific method. */ + s->s3->tmp.reuse_message = 1; + s->s3->tmp.message_type = SSL3_MT_CLIENT_HELLO; + /* The handshake message header is 4 bytes. */ + s->s3->tmp.message_size = len - 4; - /* Mark the message for "re"-use by the version-specific - * method. */ - s->s3->tmp.reuse_message = 1; - s->s3->tmp.message_type = SSL3_MT_CLIENT_HELLO; - /* The handshake message header is 4 bytes. */ - s->s3->tmp.message_size = len - 4; + /* Initialize the record layer. */ + if (!ssl3_setup_buffers(s) || !ssl_init_wbio_buffer(s, 1)) { + return -1; + } - /* Initialize the record layer. */ - if (!ssl3_setup_buffers(s) || !ssl_init_wbio_buffer(s, 1)) - { - return -1; - } + /* Drop the sniff buffer. */ + BUF_MEM_free(s->s3->sniff_buffer); + s->s3->sniff_buffer = NULL; + s->s3->sniff_buffer_len = 0; - /* Drop the sniff buffer. */ - BUF_MEM_free(s->s3->sniff_buffer); - s->s3->sniff_buffer = NULL; - s->s3->sniff_buffer_len = 0; + return 1; +} - return 1; - } +int ssl3_send_hello_request(SSL *s) { + if (s->state == SSL3_ST_SW_HELLO_REQ_A) { + ssl_set_handshake_header(s, SSL3_MT_HELLO_REQUEST, 0); + s->state = SSL3_ST_SW_HELLO_REQ_B; + } -int ssl3_send_hello_request(SSL *s) - { + /* SSL3_ST_SW_HELLO_REQ_B */ + return ssl_do_write(s); +} - if (s->state == SSL3_ST_SW_HELLO_REQ_A) - { - ssl_set_handshake_header(s, SSL3_MT_HELLO_REQUEST, 0); - s->state=SSL3_ST_SW_HELLO_REQ_B; - } +int ssl3_get_client_hello(SSL *s) { + int i, ok, al = SSL_AD_INTERNAL_ERROR, ret = -1; + long n; + const SSL_CIPHER *c; + STACK_OF(SSL_CIPHER) *ciphers = NULL; + struct ssl_early_callback_ctx early_ctx; + CBS client_hello; + uint16_t client_version; + CBS client_random, session_id, cipher_suites, compression_methods; - /* SSL3_ST_SW_HELLO_REQ_B */ - return ssl_do_write(s); - } + /* We do this so that we will respond with our native type. If we are TLSv1 + * and we get SSLv3, we will respond with TLSv1, This down switching should + * be handled by a different method. If we are SSLv3, we will respond with + * SSLv3, even if prompted with TLSv1. */ + switch (s->state) { + case SSL3_ST_SR_CLNT_HELLO_A: + case SSL3_ST_SR_CLNT_HELLO_B: + n = s->method->ssl_get_message( + s, SSL3_ST_SR_CLNT_HELLO_A, SSL3_ST_SR_CLNT_HELLO_B, + SSL3_MT_CLIENT_HELLO, SSL3_RT_MAX_PLAIN_LENGTH, + SSL_GET_MESSAGE_HASH_MESSAGE, &ok); -int ssl3_get_client_hello(SSL *s) - { - int i,ok,al=SSL_AD_INTERNAL_ERROR,ret= -1; - long n; - const SSL_CIPHER *c; - STACK_OF(SSL_CIPHER) *ciphers=NULL; - struct ssl_early_callback_ctx early_ctx; - CBS client_hello; - uint16_t client_version; - CBS client_random, session_id, cipher_suites, compression_methods; + if (!ok) { + return n; + } - /* We do this so that we will respond with our native type. - * If we are TLSv1 and we get SSLv3, we will respond with TLSv1, - * This down switching should be handled by a different method. - * If we are SSLv3, we will respond with SSLv3, even if prompted with - * TLSv1. - */ - switch (s->state) { - case SSL3_ST_SR_CLNT_HELLO_A: - case SSL3_ST_SR_CLNT_HELLO_B: - n=s->method->ssl_get_message(s, - SSL3_ST_SR_CLNT_HELLO_A, - SSL3_ST_SR_CLNT_HELLO_B, - SSL3_MT_CLIENT_HELLO, - SSL3_RT_MAX_PLAIN_LENGTH, - SSL_GET_MESSAGE_HASH_MESSAGE, - &ok); + /* If we require cookies and this ClientHello doesn't contain one, just + * return since we do not want to allocate any memory yet. So check + * cookie length... */ + if (SSL_IS_DTLS(s) && (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)) { + uint8_t cookie_length; - if (!ok) return((int)n); + CBS_init(&client_hello, s->init_msg, n); + if (!CBS_skip(&client_hello, 2 + SSL3_RANDOM_SIZE) || + !CBS_get_u8_length_prefixed(&client_hello, &session_id) || + !CBS_get_u8(&client_hello, &cookie_length)) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_DECODE_ERROR); + goto f_err; + } - /* If we require cookies and this ClientHello doesn't - * contain one, just return since we do not want to - * allocate any memory yet. So check cookie length... - */ - if (SSL_IS_DTLS(s) && (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)) - { - uint8_t cookie_length; + if (cookie_length == 0) { + return 1; + } + } + s->state = SSL3_ST_SR_CLNT_HELLO_C; + /* fallthrough */ + case SSL3_ST_SR_CLNT_HELLO_C: + case SSL3_ST_SR_CLNT_HELLO_D: + /* We have previously parsed the ClientHello message, and can't call + * ssl_get_message again without hashing the message into the Finished + * digest again. */ + n = s->init_num; - CBS_init(&client_hello, s->init_msg, n); - if (!CBS_skip(&client_hello, 2 + SSL3_RANDOM_SIZE) || - !CBS_get_u8_length_prefixed(&client_hello, &session_id) || - !CBS_get_u8(&client_hello, &cookie_length)) - { - al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_DECODE_ERROR); - goto f_err; - } + memset(&early_ctx, 0, sizeof(early_ctx)); + early_ctx.ssl = s; + early_ctx.client_hello = s->init_msg; + early_ctx.client_hello_len = n; + if (!ssl_early_callback_init(&early_ctx)) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, + SSL_R_CLIENTHELLO_PARSE_FAILED); + goto f_err; + } - if (cookie_length == 0) - return 1; - } - s->state = SSL3_ST_SR_CLNT_HELLO_C; - /* fallthrough */ - case SSL3_ST_SR_CLNT_HELLO_C: - case SSL3_ST_SR_CLNT_HELLO_D: - /* We have previously parsed the ClientHello message, - * and can't call ssl_get_message again without hashing - * the message into the Finished digest again. */ - n = s->init_num; + if (s->state == SSL3_ST_SR_CLNT_HELLO_C && + s->ctx->select_certificate_cb != NULL) { + s->state = SSL3_ST_SR_CLNT_HELLO_D; + switch (s->ctx->select_certificate_cb(&early_ctx)) { + case 0: + return CERTIFICATE_SELECTION_PENDING; - memset(&early_ctx, 0, sizeof(early_ctx)); - early_ctx.ssl = s; - early_ctx.client_hello = s->init_msg; - early_ctx.client_hello_len = n; - if (!ssl_early_callback_init(&early_ctx)) - { - al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_CLIENTHELLO_PARSE_FAILED); - goto f_err; - } + case -1: + /* Connection rejected. */ + al = SSL_AD_ACCESS_DENIED; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, + SSL_R_CONNECTION_REJECTED); + goto f_err; - if (s->state == SSL3_ST_SR_CLNT_HELLO_C && - s->ctx->select_certificate_cb != NULL) - { - s->state = SSL3_ST_SR_CLNT_HELLO_D; - switch (s->ctx->select_certificate_cb(&early_ctx)) - { - case 0: - return CERTIFICATE_SELECTION_PENDING; - case -1: - /* Connection rejected. */ - al = SSL_AD_ACCESS_DENIED; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_CONNECTION_REJECTED); - goto f_err; - default: - /* fallthrough */; - } - } - s->state = SSL3_ST_SR_CLNT_HELLO_D; - break; - default: - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_UNKNOWN_STATE); - return -1; - } + default: + /* fallthrough */; + } + } + s->state = SSL3_ST_SR_CLNT_HELLO_D; + break; - CBS_init(&client_hello, s->init_msg, n); - if (!CBS_get_u16(&client_hello, &client_version) || - !CBS_get_bytes(&client_hello, &client_random, SSL3_RANDOM_SIZE) || - !CBS_get_u8_length_prefixed(&client_hello, &session_id) || - CBS_len(&session_id) > SSL_MAX_SSL_SESSION_ID_LENGTH) - { - al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_DECODE_ERROR); - goto f_err; - } + default: + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_UNKNOWN_STATE); + return -1; + } - /* use version from inside client hello, not from record header - * (may differ: see RFC 2246, Appendix E, second paragraph) */ - s->client_version = client_version; + CBS_init(&client_hello, s->init_msg, n); + if (!CBS_get_u16(&client_hello, &client_version) || + !CBS_get_bytes(&client_hello, &client_random, SSL3_RANDOM_SIZE) || + !CBS_get_u8_length_prefixed(&client_hello, &session_id) || + CBS_len(&session_id) > SSL_MAX_SSL_SESSION_ID_LENGTH) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_DECODE_ERROR); + goto f_err; + } - /* Load the client random. */ - memcpy(s->s3->client_random, CBS_data(&client_random), SSL3_RANDOM_SIZE); + /* use version from inside client hello, not from record header (may differ: + * see RFC 2246, Appendix E, second paragraph) */ + s->client_version = client_version; - if (SSL_IS_DTLS(s)) - { - CBS cookie; + /* Load the client random. */ + memcpy(s->s3->client_random, CBS_data(&client_random), SSL3_RANDOM_SIZE); - if (!CBS_get_u8_length_prefixed(&client_hello, &cookie) || - CBS_len(&cookie) > DTLS1_COOKIE_LENGTH) - { - al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_DECODE_ERROR); - goto f_err; - } + if (SSL_IS_DTLS(s)) { + CBS cookie; - /* Verify the cookie if appropriate option is set. */ - if ((SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) && - CBS_len(&cookie) > 0) - { - if (s->ctx->app_verify_cookie_cb != NULL) - { - if (s->ctx->app_verify_cookie_cb(s, - CBS_data(&cookie), CBS_len(&cookie)) == 0) - { - al=SSL_AD_HANDSHAKE_FAILURE; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_COOKIE_MISMATCH); - goto f_err; - } - /* else cookie verification succeeded */ - } - else if (!CBS_mem_equal(&cookie, s->d1->cookie, s->d1->cookie_len)) - { - /* default verification */ - al=SSL_AD_HANDSHAKE_FAILURE; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_COOKIE_MISMATCH); - goto f_err; - } - /* Set to -2 so if successful we return 2 and - * don't send HelloVerifyRequest. */ - ret = -2; - } - } + if (!CBS_get_u8_length_prefixed(&client_hello, &cookie) || + CBS_len(&cookie) > DTLS1_COOKIE_LENGTH) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_DECODE_ERROR); + goto f_err; + } - if (!s->s3->have_version) - { - /* Select version to use */ - uint16_t version = ssl3_get_mutual_version(s, client_version); - if (version == 0) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_UNSUPPORTED_PROTOCOL); - s->version = s->client_version; - al = SSL_AD_PROTOCOL_VERSION; - goto f_err; - } - s->version = version; - s->enc_method = ssl3_get_enc_method(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 (SSL_IS_DTLS(s) ? (s->client_version > s->version) - : (s->client_version < s->version)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_WRONG_VERSION_NUMBER); - al = SSL_AD_PROTOCOL_VERSION; - goto f_err; - } + /* Verify the cookie if appropriate option is set. */ + if ((SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) && CBS_len(&cookie) > 0) { + if (s->ctx->app_verify_cookie_cb != NULL) { + if (s->ctx->app_verify_cookie_cb(s, CBS_data(&cookie), + CBS_len(&cookie)) == 0) { + al = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_COOKIE_MISMATCH); + goto f_err; + } + /* else cookie verification succeeded */ + } else if (!CBS_mem_equal(&cookie, s->d1->cookie, s->d1->cookie_len)) { + /* default verification */ + al = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_COOKIE_MISMATCH); + goto f_err; + } + /* Set to -2 so if successful we return 2 and don't send + * HelloVerifyRequest. */ + ret = -2; + } + } - s->hit=0; - /* Versions before 0.9.7 always allow clients to resume sessions in renegotiation. - * 0.9.7 and later allow this by default, but optionally ignore resumption requests - * with flag SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION (it's a new flag rather - * than a change to default behavior so that applications relying on this for security - * won't even compile against older library versions). - * - * 1.0.1 and later also have a function SSL_renegotiate_abbreviated() to request - * renegotiation but not a new session (s->new_session remains unset): for servers, - * this essentially just means that the SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION - * setting will be ignored. - */ - if ((s->new_session && (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION))) - { - if (!ssl_get_new_session(s,1)) - goto err; - } - else - { - i = ssl_get_prev_session(s, &early_ctx); - if (i == PENDING_SESSION) - { - ret = PENDING_SESSION; - goto err; - } - else if (i == -1) - { - goto err; - } + if (!s->s3->have_version) { + /* Select version to use */ + uint16_t version = ssl3_get_mutual_version(s, client_version); + if (version == 0) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_UNSUPPORTED_PROTOCOL); + s->version = s->client_version; + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } + s->version = version; + s->enc_method = ssl3_get_enc_method(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 (SSL_IS_DTLS(s) ? (s->client_version > s->version) + : (s->client_version < s->version)) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_WRONG_VERSION_NUMBER); + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } - /* Only resume if the session's version matches the negotiated - * version: most clients do not accept a mismatch. */ - if (i == 1 && s->version == s->session->ssl_version) - { - s->hit = 1; - } - else - { - /* No session was found or it was unacceptable. */ - if (!ssl_get_new_session(s, 1)) - goto err; - } - } + s->hit = 0; + /* Versions before 0.9.7 always allow clients to resume sessions in + * renegotiation. 0.9.7 and later allow this by default, but optionally + * ignore resumption requests with flag + * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION (it's a new flag rather than + * a change to default behavior so that applications relying on this for + * security won't even compile against older library versions). + * + * 1.0.1 and later also have a function SSL_renegotiate_abbreviated() to + * request renegotiation but not a new session (s->new_session remains + * unset): for servers, this essentially just means that the + * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION setting will be ignored. */ + if (s->new_session && + (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)) { + if (!ssl_get_new_session(s, 1)) { + goto err; + } + } else { + i = ssl_get_prev_session(s, &early_ctx); + if (i == PENDING_SESSION) { + ret = PENDING_SESSION; + goto err; + } else if (i == -1) { + goto err; + } - if (!CBS_get_u16_length_prefixed(&client_hello, &cipher_suites) || - !CBS_get_u8_length_prefixed(&client_hello, &compression_methods) || - CBS_len(&compression_methods) == 0) - { - al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_DECODE_ERROR); - goto f_err; - } + /* Only resume if the session's version matches the negotiated version: + * most clients do not accept a mismatch. */ + if (i == 1 && s->version == s->session->ssl_version) { + s->hit = 1; + } else { + /* No session was found or it was unacceptable. */ + if (!ssl_get_new_session(s, 1)) { + goto err; + } + } + } - /* TODO(davidben): Per spec, cipher_suites can never be empty - * (specified at the ClientHello structure level). This logic - * allows it to be empty if resuming a session. Can we always - * require non-empty? If a client sends empty cipher_suites - * because it's resuming a session, it could always fail to - * resume a session, so it's unlikely to actually work. */ - if (CBS_len(&cipher_suites) == 0 && CBS_len(&session_id) != 0) - { - /* We need a cipher if we are not resuming a session. */ - al = SSL_AD_ILLEGAL_PARAMETER; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_NO_CIPHERS_SPECIFIED); - goto f_err; - } + if (!CBS_get_u16_length_prefixed(&client_hello, &cipher_suites) || + !CBS_get_u8_length_prefixed(&client_hello, &compression_methods) || + CBS_len(&compression_methods) == 0) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_DECODE_ERROR); + goto f_err; + } - ciphers = ssl_bytes_to_cipher_list(s, &cipher_suites); - if (ciphers == NULL) - { - goto err; - } + /* TODO(davidben): Per spec, cipher_suites can never be empty (specified at + * the ClientHello structure level). This logic allows it to be empty if + * resuming a session. Can we always require non-empty? If a client sends + * empty cipher_suites because it's resuming a session, it could always fail + * to resume a session, so it's unlikely to actually work. */ + if (CBS_len(&cipher_suites) == 0 && CBS_len(&session_id) != 0) { + /* We need a cipher if we are not resuming a session. */ + al = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_NO_CIPHERS_SPECIFIED); + goto f_err; + } - /* If it is a hit, check that the cipher is in the list */ - if (s->hit && CBS_len(&cipher_suites) > 0) - { - size_t j; - int found_cipher = 0; - unsigned long id = s->session->cipher->id; + ciphers = ssl_bytes_to_cipher_list(s, &cipher_suites); + if (ciphers == NULL) { + goto err; + } - for (j = 0; j < sk_SSL_CIPHER_num(ciphers); j++) - { - c = sk_SSL_CIPHER_value(ciphers, j); - if (c->id == id) - { - found_cipher = 1; - break; - } - } - if (!found_cipher) - { - /* we need to have the cipher in the cipher - * list if we are asked to reuse it */ - al=SSL_AD_ILLEGAL_PARAMETER; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_REQUIRED_CIPHER_MISSING); - goto f_err; - } - } + /* If it is a hit, check that the cipher is in the list. */ + if (s->hit && CBS_len(&cipher_suites) > 0) { + size_t j; + int found_cipher = 0; + unsigned long id = s->session->cipher->id; - /* Only null compression is supported. */ - if (memchr(CBS_data(&compression_methods), 0, - CBS_len(&compression_methods)) == NULL) - { - al = SSL_AD_ILLEGAL_PARAMETER; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_NO_COMPRESSION_SPECIFIED); - goto f_err; - } + for (j = 0; j < sk_SSL_CIPHER_num(ciphers); j++) { + c = sk_SSL_CIPHER_value(ciphers, j); + if (c->id == id) { + found_cipher = 1; + break; + } + } - /* TLS extensions*/ - if (s->version >= SSL3_VERSION) - { - if (!ssl_parse_clienthello_tlsext(s, &client_hello)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_PARSE_TLSEXT); - goto err; - } - } + if (!found_cipher) { + /* we need to have the cipher in the cipher list if we are asked to reuse + * it */ + al = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, + SSL_R_REQUIRED_CIPHER_MISSING); + goto f_err; + } + } - /* There should be nothing left over in the record. */ - if (CBS_len(&client_hello) != 0) - { - /* wrong packet length */ - al=SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_BAD_PACKET_LENGTH); - goto f_err; - } + /* Only null compression is supported. */ + if (memchr(CBS_data(&compression_methods), 0, + CBS_len(&compression_methods)) == NULL) { + al = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, + SSL_R_NO_COMPRESSION_SPECIFIED); + goto f_err; + } - /* Given ciphers and SSL_get_ciphers, we must pick a cipher */ - if (!s->hit) - { - if (ciphers == NULL) - { - al=SSL_AD_ILLEGAL_PARAMETER; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_NO_CIPHERS_PASSED); - goto f_err; - } - /* Let cert callback update server certificates if required */ - if (s->cert->cert_cb) - { - int rv = s->cert->cert_cb(s, s->cert->cert_cb_arg); - if (rv == 0) - { - al=SSL_AD_INTERNAL_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_CERT_CB_ERROR); - goto f_err; - } - if (rv < 0) - { - s->rwstate=SSL_X509_LOOKUP; - goto err; - } - s->rwstate = SSL_NOTHING; - } - c=ssl3_choose_cipher(s, ciphers, ssl_get_cipher_preferences(s)); + /* TLS extensions. */ + if (s->version >= SSL3_VERSION && + !ssl_parse_clienthello_tlsext(s, &client_hello)) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_PARSE_TLSEXT); + goto err; + } - if (c == NULL) - { - al=SSL_AD_HANDSHAKE_FAILURE; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_NO_SHARED_CIPHER); - goto f_err; - } - s->s3->tmp.new_cipher=c; - } - else - { - /* Session-id reuse */ - s->s3->tmp.new_cipher=s->session->cipher; - } + /* There should be nothing left over in the record. */ + if (CBS_len(&client_hello) != 0) { + /* wrong packet length */ + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_BAD_PACKET_LENGTH); + goto f_err; + } - if (!SSL_USE_SIGALGS(s) || !(s->verify_mode & SSL_VERIFY_PEER)) - { - if (!ssl3_digest_cached_records(s, free_handshake_buffer)) - goto f_err; - } - - /* we now have the following setup. - * client_random - * cipher_list - our prefered list of ciphers - * ciphers - the clients prefered list of ciphers - * compression - basically ignored right now - * ssl version is set - sslv3 - * s->session - The ssl session has been setup. - * s->hit - session reuse flag - * s->tmp.new_cipher - the new cipher to use. - */ + /* Given ciphers and SSL_get_ciphers, we must pick a cipher */ + if (!s->hit) { + if (ciphers == NULL) { + al = SSL_AD_ILLEGAL_PARAMETER; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_NO_CIPHERS_PASSED); + goto f_err; + } - if (ret < 0) ret=-ret; - if (0) - { -f_err: - ssl3_send_alert(s,SSL3_AL_FATAL,al); - } + /* Let cert callback update server certificates if required */ + if (s->cert->cert_cb) { + int rv = s->cert->cert_cb(s, s->cert->cert_cb_arg); + if (rv == 0) { + al = SSL_AD_INTERNAL_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_CERT_CB_ERROR); + goto f_err; + } + if (rv < 0) { + s->rwstate = SSL_X509_LOOKUP; + goto err; + } + s->rwstate = SSL_NOTHING; + } + c = ssl3_choose_cipher(s, ciphers, ssl_get_cipher_preferences(s)); + + if (c == NULL) { + al = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_NO_SHARED_CIPHER); + goto f_err; + } + s->s3->tmp.new_cipher = c; + } else { + /* Session-id reuse */ + s->s3->tmp.new_cipher = s->session->cipher; + } + + if ((!SSL_USE_SIGALGS(s) || !(s->verify_mode & SSL_VERIFY_PEER)) && + !ssl3_digest_cached_records(s, free_handshake_buffer)) { + goto f_err; + } + + /* we now have the following setup; + * client_random + * cipher_list - our prefered list of ciphers + * ciphers - the clients prefered list of ciphers + * compression - basically ignored right now + * ssl version is set - sslv3 + * s->session - The ssl session has been setup. + * s->hit - session reuse flag + * s->tmp.new_cipher - the new cipher to use. */ + + if (ret < 0) { + ret = -ret; + } + + if (0) { + f_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + } + err: - if (ciphers != NULL) sk_SSL_CIPHER_free(ciphers); - return ret; - } + if (ciphers != NULL) { + sk_SSL_CIPHER_free(ciphers); + } + return ret; +} -int ssl3_send_server_hello(SSL *s) - { - unsigned char *buf; - unsigned char *p,*d; - int sl; - unsigned long l; +int ssl3_send_server_hello(SSL *s) { + uint8_t *buf; + uint8_t *p, *d; + int sl; + unsigned long l; - if (s->state == SSL3_ST_SW_SRVR_HELLO_A) - { - /* We only accept ChannelIDs on connections with ECDHE in order - * to avoid a known attack while we fix ChannelID itself. */ - if (s->s3->tlsext_channel_id_valid && - (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kEECDH) == 0) - s->s3->tlsext_channel_id_valid = 0; + if (s->state == SSL3_ST_SW_SRVR_HELLO_A) { + /* We only accept ChannelIDs on connections with ECDHE in order to avoid a + * known attack while we fix ChannelID itself. */ + if (s->s3->tlsext_channel_id_valid && + (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kEECDH) == 0) { + s->s3->tlsext_channel_id_valid = 0; + } - /* If this is a resumption and the original handshake didn't - * support ChannelID then we didn't record the original - * handshake hashes in the session and so cannot resume with - * ChannelIDs. */ - if (s->hit && - s->s3->tlsext_channel_id_new && - s->session->original_handshake_hash_len == 0) - s->s3->tlsext_channel_id_valid = 0; + /* If this is a resumption and the original handshake didn't support + * ChannelID then we didn't record the original handshake hashes in the + * session and so cannot resume with ChannelIDs. */ + if (s->hit && s->s3->tlsext_channel_id_new && + s->session->original_handshake_hash_len == 0) { + s->s3->tlsext_channel_id_valid = 0; + } - buf=(unsigned char *)s->init_buf->data; - /* Do the message type and length last */ - d=p= ssl_handshake_start(s); + buf = (uint8_t *)s->init_buf->data; + /* Do the message type and length last */ + d = p = ssl_handshake_start(s); - *(p++)=s->version>>8; - *(p++)=s->version&0xff; + *(p++) = s->version >> 8; + *(p++) = s->version & 0xff; - /* Random stuff */ - if (!ssl_fill_hello_random(s, 1, s->s3->server_random, SSL3_RANDOM_SIZE)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_hello, ERR_R_INTERNAL_ERROR); - return -1; - } - memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE); - p+=SSL3_RANDOM_SIZE; + /* Random stuff */ + if (!ssl_fill_hello_random(s, 1, s->s3->server_random, SSL3_RANDOM_SIZE)) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_hello, ERR_R_INTERNAL_ERROR); + return -1; + } + memcpy(p, s->s3->server_random, SSL3_RANDOM_SIZE); + p += SSL3_RANDOM_SIZE; - /* There are several cases for the session ID to send - * back in the server hello: - * - For session reuse from the session cache, - * we send back the old session ID. - * - If stateless session reuse (using a session ticket) - * is successful, we send back the client's "session ID" - * (which doesn't actually identify the session). - * - If it is a new session, we send back the new - * session ID. - * - However, if we want the new session to be single-use, - * we send back a 0-length session ID. - * s->hit is non-zero in either case of session reuse, - * so the following won't overwrite an ID that we're supposed - * to send back. - */ - if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER) - && !s->hit) - s->session->session_id_length=0; + /* There are several cases for the session ID to send + * back in the server hello: + * - For session reuse from the session cache, we send back the old session + * ID. + * - If stateless session reuse (using a session ticket) is successful, we + * send back the client's "session ID" (which doesn't actually identify + * the session). + * - If it is a new session, we send back the new session ID. + * - However, if we want the new session to be single-use, we send back a + * 0-length session ID. + * s->hit is non-zero in either case of session reuse, so the following + * won't overwrite an ID that we're supposed to send back. */ + if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER) && !s->hit) { + s->session->session_id_length = 0; + } - sl=s->session->session_id_length; - if (sl > (int)sizeof(s->session->session_id)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_hello, ERR_R_INTERNAL_ERROR); - return -1; - } - *(p++)=sl; - memcpy(p,s->session->session_id,sl); - p+=sl; + sl = s->session->session_id_length; + if (sl > (int)sizeof(s->session->session_id)) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_hello, ERR_R_INTERNAL_ERROR); + return -1; + } + *(p++) = sl; + memcpy(p, s->session->session_id, sl); + p += sl; - /* put the cipher */ - s2n(ssl3_get_cipher_value(s->s3->tmp.new_cipher), p); + /* put the cipher */ + s2n(ssl3_get_cipher_value(s->s3->tmp.new_cipher), p); - /* put the compression method */ - *(p++)=0; - if (ssl_prepare_serverhello_tlsext(s) <= 0) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_hello, SSL_R_SERVERHELLO_TLSEXT); - return -1; - } - if ((p = ssl_add_serverhello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_hello, ERR_R_INTERNAL_ERROR); - return -1; - } - /* do the header */ - l=(p-d); - ssl_set_handshake_header(s, SSL3_MT_SERVER_HELLO, l); - s->state=SSL3_ST_SW_SRVR_HELLO_B; - } + /* put the compression method */ + *(p++) = 0; + if (ssl_prepare_serverhello_tlsext(s) <= 0) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_hello, SSL_R_SERVERHELLO_TLSEXT); + return -1; + } + p = ssl_add_serverhello_tlsext(s, p, buf + SSL3_RT_MAX_PLAIN_LENGTH); + if (p == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_hello, ERR_R_INTERNAL_ERROR); + return -1; + } - /* SSL3_ST_SW_SRVR_HELLO_B */ - return ssl_do_write(s); - } + /* do the header */ + l = (p - d); + ssl_set_handshake_header(s, SSL3_MT_SERVER_HELLO, l); + s->state = SSL3_ST_SW_SRVR_HELLO_B; + } -int ssl3_send_server_done(SSL *s) - { + /* SSL3_ST_SW_SRVR_HELLO_B */ + return ssl_do_write(s); +} - if (s->state == SSL3_ST_SW_SRVR_DONE_A) - { - ssl_set_handshake_header(s, SSL3_MT_SERVER_DONE, 0); - s->state = SSL3_ST_SW_SRVR_DONE_B; - } +int ssl3_send_server_done(SSL *s) { + if (s->state == SSL3_ST_SW_SRVR_DONE_A) { + ssl_set_handshake_header(s, SSL3_MT_SERVER_DONE, 0); + s->state = SSL3_ST_SW_SRVR_DONE_B; + } - /* SSL3_ST_SW_SRVR_DONE_B */ - return ssl_do_write(s); - } + /* SSL3_ST_SW_SRVR_DONE_B */ + return ssl_do_write(s); +} -int ssl3_send_server_key_exchange(SSL *s) - { - DH *dh=NULL,*dhp; - EC_KEY *ecdh=NULL, *ecdhp; - unsigned char *encodedPoint = NULL; - int encodedlen = 0; - int curve_id = 0; - BN_CTX *bn_ctx = NULL; - const char* psk_identity_hint = NULL; - size_t psk_identity_hint_len = 0; - EVP_PKEY *pkey; - unsigned char *p,*d; - int al,i; - unsigned long alg_k; - unsigned long alg_a; - int n; - CERT *cert; - BIGNUM *r[4]; - int nr[4],kn; - BUF_MEM *buf; - EVP_MD_CTX md_ctx; +int ssl3_send_server_key_exchange(SSL *s) { + DH *dh = NULL, *dhp; + EC_KEY *ecdh = NULL, *ecdhp; + uint8_t *encodedPoint = NULL; + int encodedlen = 0; + int curve_id = 0; + BN_CTX *bn_ctx = NULL; + const char *psk_identity_hint = NULL; + size_t psk_identity_hint_len = 0; + EVP_PKEY *pkey; + uint8_t *p, *d; + int al, i; + unsigned long alg_k; + unsigned long alg_a; + int n; + CERT *cert; + BIGNUM *r[4]; + int nr[4], kn; + BUF_MEM *buf; + EVP_MD_CTX md_ctx; - EVP_MD_CTX_init(&md_ctx); - if (s->state == SSL3_ST_SW_KEY_EXCH_A) - { - alg_k=s->s3->tmp.new_cipher->algorithm_mkey; - alg_a=s->s3->tmp.new_cipher->algorithm_auth; - cert=s->cert; + EVP_MD_CTX_init(&md_ctx); + if (s->state == SSL3_ST_SW_KEY_EXCH_A) { + alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + alg_a = s->s3->tmp.new_cipher->algorithm_auth; + cert = s->cert; - buf=s->init_buf; + buf = s->init_buf; - r[0]=r[1]=r[2]=r[3]=NULL; - n=0; - if (alg_a & SSL_aPSK) - { - /* size for PSK identity hint */ - psk_identity_hint = s->psk_identity_hint; - if (psk_identity_hint) - psk_identity_hint_len = strlen(psk_identity_hint); - else - psk_identity_hint_len = 0; - n+=2+psk_identity_hint_len; - } - if (alg_k & SSL_kEDH) - { - dhp=cert->dh_tmp; - if ((dhp == NULL) && (s->cert->dh_tmp_cb != NULL)) - dhp=s->cert->dh_tmp_cb(s, 0, 1024); - if (dhp == NULL) - { - al=SSL_AD_HANDSHAKE_FAILURE; - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, SSL_R_MISSING_TMP_DH_KEY); - goto f_err; - } + r[0] = r[1] = r[2] = r[3] = NULL; + n = 0; + if (alg_a & SSL_aPSK) { + /* size for PSK identity hint */ + psk_identity_hint = s->psk_identity_hint; + if (psk_identity_hint) { + psk_identity_hint_len = strlen(psk_identity_hint); + } else { + psk_identity_hint_len = 0; + } + n += 2 + psk_identity_hint_len; + } - if (s->s3->tmp.dh != NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_INTERNAL_ERROR); - goto err; - } + if (alg_k & SSL_kEDH) { + dhp = cert->dh_tmp; + if (dhp == NULL && s->cert->dh_tmp_cb != NULL) { + dhp = s->cert->dh_tmp_cb(s, 0, 1024); + } + if (dhp == NULL) { + al = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, + SSL_R_MISSING_TMP_DH_KEY); + goto f_err; + } - if ((dh=DHparams_dup(dhp)) == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_DH_LIB); - goto err; - } + if (s->s3->tmp.dh != NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, + ERR_R_INTERNAL_ERROR); + goto err; + } - s->s3->tmp.dh=dh; - if ((dhp->pub_key == NULL || - dhp->priv_key == NULL || - (s->options & SSL_OP_SINGLE_DH_USE))) - { - if(!DH_generate_key(dh)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_DH_LIB); - goto err; - } - } - else - { - dh->pub_key=BN_dup(dhp->pub_key); - dh->priv_key=BN_dup(dhp->priv_key); - if ((dh->pub_key == NULL) || - (dh->priv_key == NULL)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_DH_LIB); - goto err; - } - } - r[0]=dh->p; - r[1]=dh->g; - r[2]=dh->pub_key; - } - else - if (alg_k & SSL_kEECDH) - { - const EC_GROUP *group; + dh = DHparams_dup(dhp); + if (dh == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_DH_LIB); + goto err; + } - ecdhp=cert->ecdh_tmp; - if (s->cert->ecdh_tmp_auto) - { - /* Get NID of appropriate shared curve */ - int nid = tls1_get_shared_curve(s); - if (nid != NID_undef) - ecdhp = EC_KEY_new_by_curve_name(nid); - } - else if ((ecdhp == NULL) && s->cert->ecdh_tmp_cb) - { - ecdhp = s->cert->ecdh_tmp_cb(s, 0, 1024); - } - if (ecdhp == NULL) - { - al=SSL_AD_HANDSHAKE_FAILURE; - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, SSL_R_MISSING_TMP_ECDH_KEY); - goto f_err; - } + s->s3->tmp.dh = dh; + if (dhp->pub_key == NULL || dhp->priv_key == NULL || + (s->options & SSL_OP_SINGLE_DH_USE)) { + if (!DH_generate_key(dh)) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_DH_LIB); + goto err; + } + } else { + dh->pub_key = BN_dup(dhp->pub_key); + dh->priv_key = BN_dup(dhp->priv_key); + if (dh->pub_key == NULL || dh->priv_key == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_DH_LIB); + goto err; + } + } - if (s->s3->tmp.ecdh != NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_INTERNAL_ERROR); - goto err; - } + r[0] = dh->p; + r[1] = dh->g; + r[2] = dh->pub_key; + } else if (alg_k & SSL_kEECDH) { + const EC_GROUP *group; - /* Duplicate the ECDH structure. */ - if (ecdhp == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_ECDH_LIB); - goto err; - } - if (s->cert->ecdh_tmp_auto) - ecdh = ecdhp; - else if ((ecdh = EC_KEY_dup(ecdhp)) == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_ECDH_LIB); - goto err; - } + ecdhp = cert->ecdh_tmp; + if (s->cert->ecdh_tmp_auto) { + /* Get NID of appropriate shared curve */ + int nid = tls1_get_shared_curve(s); + if (nid != NID_undef) { + ecdhp = EC_KEY_new_by_curve_name(nid); + } + } else if (ecdhp == NULL && s->cert->ecdh_tmp_cb) { + ecdhp = s->cert->ecdh_tmp_cb(s, 0, 1024); + } + if (ecdhp == NULL) { + al = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, + SSL_R_MISSING_TMP_ECDH_KEY); + goto f_err; + } - s->s3->tmp.ecdh=ecdh; - if ((EC_KEY_get0_public_key(ecdh) == NULL) || - (EC_KEY_get0_private_key(ecdh) == NULL) || - (s->options & SSL_OP_SINGLE_ECDH_USE)) - { - if(!EC_KEY_generate_key(ecdh)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_ECDH_LIB); - goto err; - } - } + if (s->s3->tmp.ecdh != NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, + ERR_R_INTERNAL_ERROR); + goto err; + } - if (((group = EC_KEY_get0_group(ecdh)) == NULL) || - (EC_KEY_get0_public_key(ecdh) == NULL) || - (EC_KEY_get0_private_key(ecdh) == NULL)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_ECDH_LIB); - goto err; - } + /* Duplicate the ECDH structure. */ + if (ecdhp == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_ECDH_LIB); + goto err; + } - /* XXX: For now, we only support ephemeral ECDH - * keys over named (not generic) curves. For - * supported named curves, curve_id is non-zero. - */ - if ((curve_id = - tls1_ec_nid2curve_id(EC_GROUP_get_curve_name(group))) - == 0) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, SSL_R_UNSUPPORTED_ELLIPTIC_CURVE); - goto err; - } + if (s->cert->ecdh_tmp_auto) { + ecdh = ecdhp; + } else { + ecdh = EC_KEY_dup(ecdhp); + if (ecdh == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_ECDH_LIB); + goto err; + } + } - /* Encode the public key. - * First check the size of encoding and - * allocate memory accordingly. - */ - encodedlen = EC_POINT_point2oct(group, - EC_KEY_get0_public_key(ecdh), - POINT_CONVERSION_UNCOMPRESSED, - NULL, 0, NULL); + s->s3->tmp.ecdh = ecdh; + if (EC_KEY_get0_public_key(ecdh) == NULL || + EC_KEY_get0_private_key(ecdh) == NULL || + (s->options & SSL_OP_SINGLE_ECDH_USE)) { + if (!EC_KEY_generate_key(ecdh)) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_ECDH_LIB); + goto err; + } + } - encodedPoint = (unsigned char *) - OPENSSL_malloc(encodedlen*sizeof(unsigned char)); - bn_ctx = BN_CTX_new(); - if ((encodedPoint == NULL) || (bn_ctx == NULL)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_MALLOC_FAILURE); - goto err; - } + group = EC_KEY_get0_group(ecdh); + if (group == NULL || + EC_KEY_get0_public_key(ecdh) == NULL || + EC_KEY_get0_private_key(ecdh) == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_ECDH_LIB); + goto err; + } + /* We only support ephemeral ECDH keys over named (not generic) curves. + * For supported named curves, curve_id is non-zero. */ + curve_id = tls1_ec_nid2curve_id(EC_GROUP_get_curve_name(group)); + if (curve_id == 0) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, + SSL_R_UNSUPPORTED_ELLIPTIC_CURVE); + goto err; + } - encodedlen = EC_POINT_point2oct(group, - EC_KEY_get0_public_key(ecdh), - POINT_CONVERSION_UNCOMPRESSED, - encodedPoint, encodedlen, bn_ctx); + /* Encode the public key. First check the size of encoding and allocate + * memory accordingly. */ + encodedlen = + EC_POINT_point2oct(group, EC_KEY_get0_public_key(ecdh), + POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); - if (encodedlen == 0) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_ECDH_LIB); - goto err; - } + encodedPoint = (uint8_t *)OPENSSL_malloc(encodedlen * sizeof(uint8_t)); + bn_ctx = BN_CTX_new(); + if (encodedPoint == NULL || bn_ctx == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, + ERR_R_MALLOC_FAILURE); + goto err; + } - BN_CTX_free(bn_ctx); bn_ctx=NULL; + encodedlen = EC_POINT_point2oct(group, EC_KEY_get0_public_key(ecdh), + POINT_CONVERSION_UNCOMPRESSED, + encodedPoint, encodedlen, bn_ctx); - /* XXX: For now, we only support named (not - * generic) curves in ECDH ephemeral key exchanges. - * In this situation, we need four additional bytes - * to encode the entire ServerECDHParams - * structure. - */ - n += 4 + encodedlen; + if (encodedlen == 0) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_ECDH_LIB); + goto err; + } - /* We'll generate the serverKeyExchange message - * explicitly so we can set these to NULLs - */ - r[0]=NULL; - r[1]=NULL; - r[2]=NULL; - r[3]=NULL; - } - else - if (!(alg_k & SSL_kPSK)) - { - al=SSL_AD_HANDSHAKE_FAILURE; - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE); - goto f_err; - } - for (i=0; i < 4 && r[i] != NULL; i++) - { - nr[i]=BN_num_bytes(r[i]); - n+=2+nr[i]; - } + BN_CTX_free(bn_ctx); + bn_ctx = NULL; - if (ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) - { - if ((pkey=ssl_get_sign_pkey(s,s->s3->tmp.new_cipher)) - == NULL) - { - al=SSL_AD_DECODE_ERROR; - goto f_err; - } - kn=EVP_PKEY_size(pkey); - } - else - { - pkey=NULL; - kn=0; - } + /* We only support named (not generic) curves in ECDH ephemeral key + * exchanges. In this situation, we need four additional bytes to encode + * the entire ServerECDHParams structure. */ + n += 4 + encodedlen; - if (!BUF_MEM_grow_clean(buf,n+SSL_HM_HEADER_LENGTH(s)+kn)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_LIB_BUF); - goto err; - } - d = p = ssl_handshake_start(s); + /* We'll generate the serverKeyExchange message explicitly so we can set + * these to NULLs */ + r[0] = NULL; + r[1] = NULL; + r[2] = NULL; + r[3] = NULL; + } else if (!(alg_k & SSL_kPSK)) { + al = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, + SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE); + goto f_err; + } - for (i=0; i < 4 && r[i] != NULL; i++) - { - s2n(nr[i],p); - BN_bn2bin(r[i],p); - p+=nr[i]; - } + for (i = 0; i < 4 && r[i] != NULL; i++) { + nr[i] = BN_num_bytes(r[i]); + n += 2 + nr[i]; + } -/* Note: ECDHE PSK ciphersuites use SSL_kEECDH and SSL_aPSK. - * When one of them is used, the server key exchange record needs to have both - * the psk_identity_hint and the ServerECDHParams. */ - if (alg_a & SSL_aPSK) - { - /* copy PSK identity hint (if provided) */ - s2n(psk_identity_hint_len, p); - if (psk_identity_hint_len > 0) - { - memcpy(p, psk_identity_hint, psk_identity_hint_len); - p+=psk_identity_hint_len; - } - } + if (ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) { + pkey = ssl_get_sign_pkey(s, s->s3->tmp.new_cipher); + if (pkey == NULL) { + al = SSL_AD_DECODE_ERROR; + goto f_err; + } + kn = EVP_PKEY_size(pkey); + } else { + pkey = NULL; + kn = 0; + } - if (alg_k & SSL_kEECDH) - { - /* XXX: For now, we only support named (not generic) curves. - * In this situation, the serverKeyExchange message has: - * [1 byte CurveType], [2 byte CurveName] - * [1 byte length of encoded point], followed by - * the actual encoded point itself - */ - *p = NAMED_CURVE_TYPE; - p += 1; - *p = 0; - p += 1; - *p = curve_id; - p += 1; - *p = encodedlen; - p += 1; - memcpy((unsigned char*)p, - (unsigned char *)encodedPoint, - encodedlen); - OPENSSL_free(encodedPoint); - encodedPoint = NULL; - p += encodedlen; - } + if (!BUF_MEM_grow_clean(buf, n + SSL_HM_HEADER_LENGTH(s) + kn)) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_LIB_BUF); + goto err; + } + d = p = ssl_handshake_start(s); - /* not anonymous */ - if (pkey != NULL) - { - /* n is the length of the params, they start at &(d[4]) - * and p points to the space at the end. */ - const EVP_MD *md; - size_t sig_len = EVP_PKEY_size(pkey); + for (i = 0; i < 4 && r[i] != NULL; i++) { + s2n(nr[i], p); + BN_bn2bin(r[i], p); + p += nr[i]; + } - /* Determine signature algorithm. */ - if (SSL_USE_SIGALGS(s)) - { - md = tls1_choose_signing_digest(s, pkey); - if (!tls12_get_sigandhash(p, pkey, md)) - { - /* Should never happen */ - al=SSL_AD_INTERNAL_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_R_INTERNAL_ERROR); - goto f_err; - } - p+=2; - } - else if (pkey->type == EVP_PKEY_RSA) - { - md = EVP_md5_sha1(); - } - else - { - md = EVP_sha1(); - } + /* Note: ECDHE PSK ciphersuites use SSL_kEECDH and SSL_aPSK. When one of + * them is used, the server key exchange record needs to have both the + * psk_identity_hint and the ServerECDHParams. */ + if (alg_a & SSL_aPSK) { + /* copy PSK identity hint (if provided) */ + s2n(psk_identity_hint_len, p); + if (psk_identity_hint_len > 0) { + memcpy(p, psk_identity_hint, psk_identity_hint_len); + p += psk_identity_hint_len; + } + } - if (!EVP_DigestSignInit(&md_ctx, NULL, md, NULL, pkey) || - !EVP_DigestSignUpdate(&md_ctx, s->s3->client_random, SSL3_RANDOM_SIZE) || - !EVP_DigestSignUpdate(&md_ctx, s->s3->server_random, SSL3_RANDOM_SIZE) || - !EVP_DigestSignUpdate(&md_ctx, d, n) || - !EVP_DigestSignFinal(&md_ctx, &p[2], &sig_len)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_LIB_EVP); - goto err; - } - s2n(sig_len, p); - n += sig_len + 2; - if (SSL_USE_SIGALGS(s)) - n += 2; - } + if (alg_k & SSL_kEECDH) { + /* We only support named (not generic) curves. In this situation, the + * serverKeyExchange message has: + * [1 byte CurveType], [2 byte CurveName] + * [1 byte length of encoded point], followed by + * the actual encoded point itself. */ + *p = NAMED_CURVE_TYPE; + p += 1; + *p = 0; + p += 1; + *p = curve_id; + p += 1; + *p = encodedlen; + p += 1; + memcpy((uint8_t *)p, (uint8_t *)encodedPoint, encodedlen); + OPENSSL_free(encodedPoint); + encodedPoint = NULL; + p += encodedlen; + } - ssl_set_handshake_header(s, SSL3_MT_SERVER_KEY_EXCHANGE, n); - } + /* not anonymous */ + if (pkey != NULL) { + /* n is the length of the params, they start at &(d[4]) and p points to + * the space at the end. */ + const EVP_MD *md; + size_t sig_len = EVP_PKEY_size(pkey); - s->state = SSL3_ST_SW_KEY_EXCH_B; - EVP_MD_CTX_cleanup(&md_ctx); - return ssl_do_write(s); + /* Determine signature algorithm. */ + if (SSL_USE_SIGALGS(s)) { + md = tls1_choose_signing_digest(s, pkey); + if (!tls12_get_sigandhash(p, pkey, md)) { + /* Should never happen */ + al = SSL_AD_INTERNAL_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, + ERR_R_INTERNAL_ERROR); + goto f_err; + } + p += 2; + } else if (pkey->type == EVP_PKEY_RSA) { + md = EVP_md5_sha1(); + } else { + md = EVP_sha1(); + } + + if (!EVP_DigestSignInit(&md_ctx, NULL, md, NULL, pkey) || + !EVP_DigestSignUpdate(&md_ctx, s->s3->client_random, + SSL3_RANDOM_SIZE) || + !EVP_DigestSignUpdate(&md_ctx, s->s3->server_random, + SSL3_RANDOM_SIZE) || + !EVP_DigestSignUpdate(&md_ctx, d, n) || + !EVP_DigestSignFinal(&md_ctx, &p[2], &sig_len)) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_LIB_EVP); + goto err; + } + + s2n(sig_len, p); + n += sig_len + 2; + if (SSL_USE_SIGALGS(s)) { + n += 2; + } + } + + ssl_set_handshake_header(s, SSL3_MT_SERVER_KEY_EXCHANGE, n); + } + + s->state = SSL3_ST_SW_KEY_EXCH_B; + EVP_MD_CTX_cleanup(&md_ctx); + return ssl_do_write(s); + f_err: - ssl3_send_alert(s,SSL3_AL_FATAL,al); + ssl3_send_alert(s, SSL3_AL_FATAL, al); err: - if (encodedPoint != NULL) OPENSSL_free(encodedPoint); - BN_CTX_free(bn_ctx); - EVP_MD_CTX_cleanup(&md_ctx); - return(-1); - } + if (encodedPoint != NULL) { + OPENSSL_free(encodedPoint); + } + BN_CTX_free(bn_ctx); + EVP_MD_CTX_cleanup(&md_ctx); + return -1; +} -int ssl3_send_certificate_request(SSL *s) - { - unsigned char *p,*d; - size_t i; - int j,nl,off,n; - STACK_OF(X509_NAME) *sk=NULL; - X509_NAME *name; - BUF_MEM *buf; +int ssl3_send_certificate_request(SSL *s) { + uint8_t *p, *d; + size_t i; + int j, nl, off, n; + STACK_OF(X509_NAME) *sk = NULL; + X509_NAME *name; + BUF_MEM *buf; - if (s->state == SSL3_ST_SW_CERT_REQ_A) - { - buf=s->init_buf; + if (s->state == SSL3_ST_SW_CERT_REQ_A) { + buf = s->init_buf; - d=p=ssl_handshake_start(s); + d = p = ssl_handshake_start(s); - /* get the list of acceptable cert types */ - p++; - n=ssl3_get_req_cert_type(s,p); - d[0]=n; - p+=n; - n++; + /* get the list of acceptable cert types */ + p++; + n = ssl3_get_req_cert_type(s, p); + d[0] = n; + p += n; + n++; - if (SSL_USE_SIGALGS(s)) - { - const unsigned char *psigs; - nl = tls12_get_psigalgs(s, &psigs); - s2n(nl, p); - memcpy(p, psigs, nl); - p += nl; - n += nl + 2; - } + if (SSL_USE_SIGALGS(s)) { + const uint8_t *psigs; + nl = tls12_get_psigalgs(s, &psigs); + s2n(nl, p); + memcpy(p, psigs, nl); + p += nl; + n += nl + 2; + } - off=n; - p+=2; - n+=2; + off = n; + p += 2; + n += 2; - sk=SSL_get_client_CA_list(s); - nl=0; - if (sk != NULL) - { - for (i=0; i<sk_X509_NAME_num(sk); i++) - { - name=sk_X509_NAME_value(sk,i); - j=i2d_X509_NAME(name,NULL); - if (!BUF_MEM_grow_clean(buf,SSL_HM_HEADER_LENGTH(s)+n+j+2)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_certificate_request, ERR_R_BUF_LIB); - goto err; - } - p = ssl_handshake_start(s) + n; - s2n(j,p); - i2d_X509_NAME(name,&p); - n+=2+j; - nl+=2+j; - } - } - /* else no CA names */ - p = ssl_handshake_start(s) + off; - s2n(nl,p); + sk = SSL_get_client_CA_list(s); + nl = 0; + if (sk != NULL) { + for (i = 0; i < sk_X509_NAME_num(sk); i++) { + name = sk_X509_NAME_value(sk, i); + j = i2d_X509_NAME(name, NULL); + if (!BUF_MEM_grow_clean(buf, SSL_HM_HEADER_LENGTH(s) + n + j + 2)) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_certificate_request, ERR_R_BUF_LIB); + goto err; + } + p = ssl_handshake_start(s) + n; + s2n(j, p); + i2d_X509_NAME(name, &p); + n += 2 + j; + nl += 2 + j; + } + } - ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_REQUEST, n); + /* else no CA names */ + p = ssl_handshake_start(s) + off; + s2n(nl, p); + + ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_REQUEST, n); #ifdef NETSCAPE_HANG_BUG - if (!SSL_IS_DTLS(s)) - { - /* Prepare a ServerHelloDone in the same record. This is - * to workaround a hang in Netscape. */ - if (!BUF_MEM_grow_clean(buf, s->init_num + 4)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_certificate_request, ERR_R_BUF_LIB); - goto err; - } - p=(unsigned char *)s->init_buf->data + s->init_num; - /* do the header */ - *(p++)=SSL3_MT_SERVER_DONE; - *(p++)=0; - *(p++)=0; - *(p++)=0; - s->init_num += 4; - ssl3_finish_mac(s, p - 4, 4); - } + if (!SSL_IS_DTLS(s)) { + /* Prepare a ServerHelloDone in the same record. This is to workaround a + * hang in Netscape. */ + if (!BUF_MEM_grow_clean(buf, s->init_num + 4)) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_certificate_request, ERR_R_BUF_LIB); + goto err; + } + p = (uint8_t *)s->init_buf->data + s->init_num; + /* do the header */ + *(p++) = SSL3_MT_SERVER_DONE; + *(p++) = 0; + *(p++) = 0; + *(p++) = 0; + s->init_num += 4; + ssl3_finish_mac(s, p - 4, 4); + } #endif - s->state = SSL3_ST_SW_CERT_REQ_B; - } + s->state = SSL3_ST_SW_CERT_REQ_B; + } - /* SSL3_ST_SW_CERT_REQ_B */ - return ssl_do_write(s); + /* SSL3_ST_SW_CERT_REQ_B */ + return ssl_do_write(s); + err: - return(-1); - } + return -1; +} -int ssl3_get_client_key_exchange(SSL *s) - { - int al,ok; - long n; - CBS client_key_exchange; - unsigned long alg_k; - unsigned long alg_a; - uint8_t *premaster_secret = NULL; - size_t premaster_secret_len = 0; - RSA *rsa=NULL; - uint8_t *decrypt_buf = NULL; - EVP_PKEY *pkey=NULL; - BIGNUM *pub=NULL; - DH *dh_srvr; +int ssl3_get_client_key_exchange(SSL *s) { + int al, ok; + long n; + CBS client_key_exchange; + unsigned long alg_k; + unsigned long alg_a; + uint8_t *premaster_secret = NULL; + size_t premaster_secret_len = 0; + RSA *rsa = NULL; + uint8_t *decrypt_buf = NULL; + EVP_PKEY *pkey = NULL; + BIGNUM *pub = NULL; + DH *dh_srvr; - EC_KEY *srvr_ecdh = NULL; - EVP_PKEY *clnt_pub_pkey = NULL; - EC_POINT *clnt_ecpoint = NULL; - BN_CTX *bn_ctx = NULL; - unsigned int psk_len = 0; - unsigned char psk[PSK_MAX_PSK_LEN]; + EC_KEY *srvr_ecdh = NULL; + EVP_PKEY *clnt_pub_pkey = NULL; + EC_POINT *clnt_ecpoint = NULL; + BN_CTX *bn_ctx = NULL; + unsigned int psk_len = 0; + uint8_t psk[PSK_MAX_PSK_LEN]; - n=s->method->ssl_get_message(s, - SSL3_ST_SR_KEY_EXCH_A, - SSL3_ST_SR_KEY_EXCH_B, - SSL3_MT_CLIENT_KEY_EXCHANGE, - 2048, /* ??? */ - SSL_GET_MESSAGE_HASH_MESSAGE, - &ok); + n = s->method->ssl_get_message(s, SSL3_ST_SR_KEY_EXCH_A, + SSL3_ST_SR_KEY_EXCH_B, + SSL3_MT_CLIENT_KEY_EXCHANGE, 2048, /* ??? */ + SSL_GET_MESSAGE_HASH_MESSAGE, &ok); - if (!ok) return((int)n); - CBS_init(&client_key_exchange, s->init_msg, n); + if (!ok) { + return n; + } - alg_k=s->s3->tmp.new_cipher->algorithm_mkey; - alg_a=s->s3->tmp.new_cipher->algorithm_auth; + CBS_init(&client_key_exchange, s->init_msg, n); - /* If using a PSK key exchange, prepare the pre-shared key. */ - if (alg_a & SSL_aPSK) - { - CBS psk_identity; + alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + alg_a = s->s3->tmp.new_cipher->algorithm_auth; - /* If using PSK, the ClientKeyExchange contains a - * psk_identity. If PSK, then this is the only field - * in the message. */ - if (!CBS_get_u16_length_prefixed(&client_key_exchange, &psk_identity) || - ((alg_k & SSL_kPSK) && CBS_len(&client_key_exchange) != 0)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_DECODE_ERROR); - al = SSL_AD_DECODE_ERROR; - goto f_err; - } + /* If using a PSK key exchange, prepare the pre-shared key. */ + if (alg_a & SSL_aPSK) { + CBS psk_identity; - if (s->psk_server_callback == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_PSK_NO_SERVER_CB); - al = SSL_AD_INTERNAL_ERROR; - goto f_err; - } + /* If using PSK, the ClientKeyExchange contains a psk_identity. If PSK, + * then this is the only field in the message. */ + if (!CBS_get_u16_length_prefixed(&client_key_exchange, &psk_identity) || + ((alg_k & SSL_kPSK) && CBS_len(&client_key_exchange) != 0)) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_DECODE_ERROR); + al = SSL_AD_DECODE_ERROR; + goto f_err; + } - if (CBS_len(&psk_identity) > PSK_MAX_IDENTITY_LEN || - CBS_contains_zero_byte(&psk_identity)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_DATA_LENGTH_TOO_LONG); - al = SSL_AD_ILLEGAL_PARAMETER; - goto f_err; - } + if (s->psk_server_callback == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + SSL_R_PSK_NO_SERVER_CB); + al = SSL_AD_INTERNAL_ERROR; + goto f_err; + } - if (!CBS_strdup(&psk_identity, &s->session->psk_identity)) - { - al = SSL_AD_INTERNAL_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_MALLOC_FAILURE); - goto f_err; - } + if (CBS_len(&psk_identity) > PSK_MAX_IDENTITY_LEN || + CBS_contains_zero_byte(&psk_identity)) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + SSL_R_DATA_LENGTH_TOO_LONG); + al = SSL_AD_ILLEGAL_PARAMETER; + goto f_err; + } - /* Look up the key for the identity. */ - psk_len = s->psk_server_callback(s, s->session->psk_identity, psk, sizeof(psk)); - if (psk_len > PSK_MAX_PSK_LEN) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_INTERNAL_ERROR); - al = SSL_AD_INTERNAL_ERROR; - goto f_err; - } - else if (psk_len == 0) - { - /* PSK related to the given identity not found */ - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_PSK_IDENTITY_NOT_FOUND); - al = SSL_AD_UNKNOWN_PSK_IDENTITY; - goto f_err; - } - } + if (!CBS_strdup(&psk_identity, &s->session->psk_identity)) { + al = SSL_AD_INTERNAL_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + ERR_R_MALLOC_FAILURE); + goto f_err; + } - /* Depending on the key exchange method, compute |premaster_secret| and - * |premaster_secret_len|. */ - if (alg_k & SSL_kRSA) - { - CBS encrypted_premaster_secret; - uint8_t rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH]; - uint8_t good; - size_t rsa_size, decrypt_len, premaster_index, j; + /* Look up the key for the identity. */ + psk_len = + s->psk_server_callback(s, s->session->psk_identity, psk, sizeof(psk)); + if (psk_len > PSK_MAX_PSK_LEN) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + ERR_R_INTERNAL_ERROR); + al = SSL_AD_INTERNAL_ERROR; + goto f_err; + } else if (psk_len == 0) { + /* PSK related to the given identity not found */ + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + SSL_R_PSK_IDENTITY_NOT_FOUND); + al = SSL_AD_UNKNOWN_PSK_IDENTITY; + goto f_err; + } + } - pkey=s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey; - if ( (pkey == NULL) || - (pkey->type != EVP_PKEY_RSA) || - (pkey->pkey.rsa == NULL)) - { - al=SSL_AD_HANDSHAKE_FAILURE; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_MISSING_RSA_CERTIFICATE); - goto f_err; - } - rsa=pkey->pkey.rsa; + /* Depending on the key exchange method, compute |premaster_secret| and + * |premaster_secret_len|. */ + if (alg_k & SSL_kRSA) { + CBS encrypted_premaster_secret; + uint8_t rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH]; + uint8_t good; + size_t rsa_size, decrypt_len, premaster_index, j; - /* TLS and [incidentally] DTLS{0xFEFF} */ - if (s->version > SSL3_VERSION) - { - CBS copy = client_key_exchange; - if (!CBS_get_u16_length_prefixed(&client_key_exchange, - &encrypted_premaster_secret) || - CBS_len(&client_key_exchange) != 0) - { - if (!(s->options & SSL_OP_TLS_D5_BUG)) - { - al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG); - goto f_err; - } - else - encrypted_premaster_secret = copy; - } - } - else - encrypted_premaster_secret = client_key_exchange; + pkey = s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey; + if (pkey == NULL || pkey->type != EVP_PKEY_RSA || pkey->pkey.rsa == NULL) { + al = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + SSL_R_MISSING_RSA_CERTIFICATE); + goto f_err; + } + rsa = pkey->pkey.rsa; - /* Reject overly short RSA keys because we want to be sure that - * the buffer size makes it safe to iterate over the entire size - * of a premaster secret (SSL_MAX_MASTER_KEY_LENGTH). The actual - * expected size is larger due to RSA padding, but the bound is - * sufficient to be safe. */ - rsa_size = RSA_size(rsa); - if (rsa_size < SSL_MAX_MASTER_KEY_LENGTH) - { - al = SSL_AD_DECRYPT_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_DECRYPTION_FAILED); - goto f_err; - } + /* TLS and [incidentally] DTLS{0xFEFF} */ + if (s->version > SSL3_VERSION) { + CBS copy = client_key_exchange; + if (!CBS_get_u16_length_prefixed(&client_key_exchange, + &encrypted_premaster_secret) || + CBS_len(&client_key_exchange) != 0) { + if (!(s->options & SSL_OP_TLS_D5_BUG)) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG); + goto f_err; + } else { + encrypted_premaster_secret = copy; + } + } + } else { + encrypted_premaster_secret = client_key_exchange; + } - /* We must not leak whether a decryption failure occurs because - * of Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see - * RFC 2246, section 7.4.7.1). The code follows that advice of - * the TLS RFC and generates a random premaster secret for the - * case that the decrypt fails. See - * https://tools.ietf.org/html/rfc5246#section-7.4.7.1 */ - if (!RAND_bytes(rand_premaster_secret, - sizeof(rand_premaster_secret))) - goto err; + /* Reject overly short RSA keys because we want to be sure that the buffer + * size makes it safe to iterate over the entire size of a premaster secret + * (SSL_MAX_MASTER_KEY_LENGTH). The actual expected size is larger due to + * RSA padding, but the bound is sufficient to be safe. */ + rsa_size = RSA_size(rsa); + if (rsa_size < SSL_MAX_MASTER_KEY_LENGTH) { + al = SSL_AD_DECRYPT_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + SSL_R_DECRYPTION_FAILED); + goto f_err; + } - /* Allocate a buffer large enough for an RSA decryption. */ - decrypt_buf = OPENSSL_malloc(rsa_size); - if (decrypt_buf == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_MALLOC_FAILURE); - goto err; - } + /* We must not leak whether a decryption failure occurs because of + * Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see RFC 2246, + * section 7.4.7.1). The code follows that advice of the TLS RFC and + * generates a random premaster secret for the case that the decrypt fails. + * See https://tools.ietf.org/html/rfc5246#section-7.4.7.1 */ + if (!RAND_bytes(rand_premaster_secret, sizeof(rand_premaster_secret))) { + goto err; + } - /* Decrypt with no padding. PKCS#1 padding will be removed as - * part of the timing-sensitive code below. */ - if (!RSA_decrypt(rsa, &decrypt_len, decrypt_buf, rsa_size, - CBS_data(&encrypted_premaster_secret), - CBS_len(&encrypted_premaster_secret), - RSA_NO_PADDING)) - { - goto err; - } - if (decrypt_len != rsa_size) - { - /* This should never happen, but do a check so we do not - * read uninitialized memory. */ - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_INTERNAL_ERROR); - goto err; - } + /* Allocate a buffer large enough for an RSA decryption. */ + decrypt_buf = OPENSSL_malloc(rsa_size); + if (decrypt_buf == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + ERR_R_MALLOC_FAILURE); + goto err; + } - /* Remove the PKCS#1 padding and adjust |decrypt_len| as - * appropriate. |good| will be 0xff if the premaster is - * acceptable and zero otherwise. */ - good = constant_time_eq_int_8( - RSA_message_index_PKCS1_type_2(decrypt_buf, decrypt_len, &premaster_index), 1); - decrypt_len = decrypt_len - premaster_index; + /* Decrypt with no padding. PKCS#1 padding will be removed as part of the + * timing-sensitive code below. */ + if (!RSA_decrypt(rsa, &decrypt_len, decrypt_buf, rsa_size, + CBS_data(&encrypted_premaster_secret), + CBS_len(&encrypted_premaster_secret), RSA_NO_PADDING)) { + goto err; + } + if (decrypt_len != rsa_size) { + /* This should never happen, but do a check so we do not read + * uninitialized memory. */ + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + ERR_R_INTERNAL_ERROR); + goto err; + } - /* decrypt_len should be SSL_MAX_MASTER_KEY_LENGTH. */ - good &= constant_time_eq_8(decrypt_len, SSL_MAX_MASTER_KEY_LENGTH); + /* Remove the PKCS#1 padding and adjust |decrypt_len| as appropriate. + * |good| will be 0xff if the premaster is acceptable and zero otherwise. + * */ + good = + constant_time_eq_int_8(RSA_message_index_PKCS1_type_2( + decrypt_buf, decrypt_len, &premaster_index), + 1); + decrypt_len = decrypt_len - premaster_index; - /* Copy over the unpadded premaster. Whatever the value of - * |decrypt_good_mask|, copy as if the premaster were the right - * length. It is important the memory access pattern be - * constant. */ - premaster_secret = BUF_memdup( - decrypt_buf + (rsa_size - SSL_MAX_MASTER_KEY_LENGTH), - SSL_MAX_MASTER_KEY_LENGTH); - if (premaster_secret == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_MALLOC_FAILURE); - goto err; - } - OPENSSL_free(decrypt_buf); - decrypt_buf = NULL; + /* decrypt_len should be SSL_MAX_MASTER_KEY_LENGTH. */ + good &= constant_time_eq_8(decrypt_len, SSL_MAX_MASTER_KEY_LENGTH); - /* If the version in the decrypted pre-master secret is correct - * then version_good will be 0xff, otherwise it'll be zero. The - * Klima-Pokorny-Rosa extension of Bleichenbacher's attack - * (http://eprint.iacr.org/2003/052/) exploits the version - * number check as a "bad version oracle". Thus version checks - * are done in constant time and are treated like any other - * decryption error. */ - good &= constant_time_eq_8(premaster_secret[0], (unsigned)(s->client_version>>8)); - good &= constant_time_eq_8(premaster_secret[1], (unsigned)(s->client_version&0xff)); + /* Copy over the unpadded premaster. Whatever the value of + * |decrypt_good_mask|, copy as if the premaster were the right length. It + * is important the memory access pattern be constant. */ + premaster_secret = + BUF_memdup(decrypt_buf + (rsa_size - SSL_MAX_MASTER_KEY_LENGTH), + SSL_MAX_MASTER_KEY_LENGTH); + if (premaster_secret == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + ERR_R_MALLOC_FAILURE); + goto err; + } + OPENSSL_free(decrypt_buf); + decrypt_buf = NULL; - /* Now copy rand_premaster_secret over premaster_secret using - * decrypt_good_mask. */ - for (j = 0; j < sizeof(rand_premaster_secret); j++) - { - premaster_secret[j] = constant_time_select_8(good, premaster_secret[j], rand_premaster_secret[j]); - } + /* If the version in the decrypted pre-master secret is correct then + * version_good will be 0xff, otherwise it'll be zero. The + * Klima-Pokorny-Rosa extension of Bleichenbacher's attack + * (http://eprint.iacr.org/2003/052/) exploits the version number check as + * a "bad version oracle". Thus version checks are done in constant time + * and are treated like any other decryption error. */ + good &= constant_time_eq_8(premaster_secret[0], + (unsigned)(s->client_version >> 8)); + good &= constant_time_eq_8(premaster_secret[1], + (unsigned)(s->client_version & 0xff)); - premaster_secret_len = sizeof(rand_premaster_secret); - } - else if (alg_k & SSL_kEDH) - { - CBS dh_Yc; - int dh_len; + /* Now copy rand_premaster_secret over premaster_secret using + * decrypt_good_mask. */ + for (j = 0; j < sizeof(rand_premaster_secret); j++) { + premaster_secret[j] = constant_time_select_8(good, premaster_secret[j], + rand_premaster_secret[j]); + } - if (!CBS_get_u16_length_prefixed(&client_key_exchange, &dh_Yc) || - CBS_len(&dh_Yc) == 0 || - CBS_len(&client_key_exchange) != 0) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG); - al = SSL_R_DECODE_ERROR; - goto f_err; - } + premaster_secret_len = sizeof(rand_premaster_secret); + } else if (alg_k & SSL_kEDH) { + CBS dh_Yc; + int dh_len; - if (s->s3->tmp.dh == NULL) - { - al=SSL_AD_HANDSHAKE_FAILURE; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_MISSING_TMP_DH_KEY); - goto f_err; - } - dh_srvr=s->s3->tmp.dh; + if (!CBS_get_u16_length_prefixed(&client_key_exchange, &dh_Yc) || + CBS_len(&dh_Yc) == 0 || CBS_len(&client_key_exchange) != 0) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG); + al = SSL_R_DECODE_ERROR; + goto f_err; + } - pub = BN_bin2bn(CBS_data(&dh_Yc), CBS_len(&dh_Yc), NULL); - if (pub == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_BN_LIB); - goto err; - } + if (s->s3->tmp.dh == NULL) { + al = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + SSL_R_MISSING_TMP_DH_KEY); + goto f_err; + } + dh_srvr = s->s3->tmp.dh; - /* Allocate a buffer for the premaster secret. */ - premaster_secret = OPENSSL_malloc(DH_size(dh_srvr)); - if (premaster_secret == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_MALLOC_FAILURE); - goto err; - } + pub = BN_bin2bn(CBS_data(&dh_Yc), CBS_len(&dh_Yc), NULL); + if (pub == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_BN_LIB); + goto err; + } - dh_len = DH_compute_key(premaster_secret, pub, dh_srvr); - if (dh_len <= 0) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_DH_LIB); - BN_clear_free(pub); - goto err; - } + /* Allocate a buffer for the premaster secret. */ + premaster_secret = OPENSSL_malloc(DH_size(dh_srvr)); + if (premaster_secret == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + ERR_R_MALLOC_FAILURE); + goto err; + } - DH_free(s->s3->tmp.dh); - s->s3->tmp.dh=NULL; - BN_clear_free(pub); - pub=NULL; + dh_len = DH_compute_key(premaster_secret, pub, dh_srvr); + if (dh_len <= 0) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_DH_LIB); + BN_clear_free(pub); + goto err; + } - premaster_secret_len = dh_len; - } + DH_free(s->s3->tmp.dh); + s->s3->tmp.dh = NULL; + BN_clear_free(pub); + pub = NULL; - else if (alg_k & SSL_kEECDH) - { - int field_size = 0, ecdh_len; - const EC_KEY *tkey; - const EC_GROUP *group; - const BIGNUM *priv_key; - CBS ecdh_Yc; + premaster_secret_len = dh_len; + } else if (alg_k & SSL_kEECDH) { + int field_size = 0, ecdh_len; + const EC_KEY *tkey; + const EC_GROUP *group; + const BIGNUM *priv_key; + CBS ecdh_Yc; - /* initialize structures for server's ECDH key pair */ - if ((srvr_ecdh = EC_KEY_new()) == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_MALLOC_FAILURE); - goto err; - } + /* initialize structures for server's ECDH key pair */ + srvr_ecdh = EC_KEY_new(); + if (srvr_ecdh == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + ERR_R_MALLOC_FAILURE); + goto err; + } - /* Use the ephermeral values we saved when generating the - * ServerKeyExchange msg. */ - tkey = s->s3->tmp.ecdh; + /* Use the ephermeral values we saved when generating the ServerKeyExchange + * msg. */ + tkey = s->s3->tmp.ecdh; - group = EC_KEY_get0_group(tkey); - priv_key = EC_KEY_get0_private_key(tkey); + group = EC_KEY_get0_group(tkey); + priv_key = EC_KEY_get0_private_key(tkey); - if (!EC_KEY_set_group(srvr_ecdh, group) || - !EC_KEY_set_private_key(srvr_ecdh, priv_key)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_EC_LIB); - goto err; - } + if (!EC_KEY_set_group(srvr_ecdh, group) || + !EC_KEY_set_private_key(srvr_ecdh, priv_key)) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_EC_LIB); + goto err; + } - /* Let's get client's public key */ - if ((clnt_ecpoint = EC_POINT_new(group)) == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_MALLOC_FAILURE); - goto err; - } + /* Let's get client's public key */ + clnt_ecpoint = EC_POINT_new(group); + if (clnt_ecpoint == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + ERR_R_MALLOC_FAILURE); + goto err; + } - /* Get client's public key from encoded point - * in the ClientKeyExchange message. - */ - if (!CBS_get_u8_length_prefixed(&client_key_exchange, &ecdh_Yc) || - CBS_len(&client_key_exchange) != 0) - { - al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_DECODE_ERROR); - goto f_err; - } + /* Get client's public key from encoded point in the ClientKeyExchange + * message. */ + if (!CBS_get_u8_length_prefixed(&client_key_exchange, &ecdh_Yc) || + CBS_len(&client_key_exchange) != 0) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_DECODE_ERROR); + goto f_err; + } - if ((bn_ctx = BN_CTX_new()) == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_MALLOC_FAILURE); - goto err; - } + bn_ctx = BN_CTX_new(); + if (bn_ctx == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + ERR_R_MALLOC_FAILURE); + goto err; + } - if (!EC_POINT_oct2point(group, clnt_ecpoint, - CBS_data(&ecdh_Yc), CBS_len(&ecdh_Yc), bn_ctx)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_EC_LIB); - goto err; - } + if (!EC_POINT_oct2point(group, clnt_ecpoint, CBS_data(&ecdh_Yc), + CBS_len(&ecdh_Yc), bn_ctx)) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_EC_LIB); + goto err; + } - /* Allocate a buffer for both the secret and the PSK. */ - field_size = EC_GROUP_get_degree(group); - if (field_size <= 0) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_ECDH_LIB); - goto err; - } + /* Allocate a buffer for both the secret and the PSK. */ + field_size = EC_GROUP_get_degree(group); + if (field_size <= 0) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_ECDH_LIB); + goto err; + } - ecdh_len = (field_size + 7) / 8; - premaster_secret = OPENSSL_malloc(ecdh_len); - if (premaster_secret == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_MALLOC_FAILURE); - goto err; - } + ecdh_len = (field_size + 7) / 8; + premaster_secret = OPENSSL_malloc(ecdh_len); + if (premaster_secret == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + ERR_R_MALLOC_FAILURE); + goto err; + } - /* Compute the shared pre-master secret */ - ecdh_len = ECDH_compute_key(premaster_secret, - ecdh_len, clnt_ecpoint, srvr_ecdh, NULL); - if (ecdh_len <= 0) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_ECDH_LIB); - goto err; - } + /* Compute the shared pre-master secret */ + ecdh_len = ECDH_compute_key(premaster_secret, ecdh_len, clnt_ecpoint, + srvr_ecdh, NULL); + if (ecdh_len <= 0) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_ECDH_LIB); + goto err; + } - EVP_PKEY_free(clnt_pub_pkey); - clnt_pub_pkey = NULL; - EC_POINT_free(clnt_ecpoint); - clnt_ecpoint = NULL; - EC_KEY_free(srvr_ecdh); - srvr_ecdh = NULL; - BN_CTX_free(bn_ctx); - bn_ctx = NULL; - EC_KEY_free(s->s3->tmp.ecdh); - s->s3->tmp.ecdh = NULL; + EVP_PKEY_free(clnt_pub_pkey); + clnt_pub_pkey = NULL; + EC_POINT_free(clnt_ecpoint); + clnt_ecpoint = NULL; + EC_KEY_free(srvr_ecdh); + srvr_ecdh = NULL; + BN_CTX_free(bn_ctx); + bn_ctx = NULL; + EC_KEY_free(s->s3->tmp.ecdh); + s->s3->tmp.ecdh = NULL; - premaster_secret_len = ecdh_len; - } - 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. */ - premaster_secret_len = psk_len; - premaster_secret = OPENSSL_malloc(premaster_secret_len); - if (premaster_secret == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_MALLOC_FAILURE); - goto err; - } - memset(premaster_secret, 0, premaster_secret_len); - } - else - { - al=SSL_AD_HANDSHAKE_FAILURE; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, SSL_R_UNKNOWN_CIPHER_TYPE); - goto f_err; - } + premaster_secret_len = ecdh_len; + } 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. */ + premaster_secret_len = psk_len; + premaster_secret = OPENSSL_malloc(premaster_secret_len); + if (premaster_secret == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + ERR_R_MALLOC_FAILURE); + goto err; + } + memset(premaster_secret, 0, premaster_secret_len); + } else { + al = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + SSL_R_UNKNOWN_CIPHER_TYPE); + goto f_err; + } - /* For a PSK cipher suite, the actual pre-master secret is combined with - * the pre-shared key. */ - if (alg_a & SSL_aPSK) - { - CBB new_premaster, child; - uint8_t *new_data; - size_t new_len; + /* For a PSK cipher suite, the actual pre-master secret is combined with the + * pre-shared key. */ + if (alg_a & SSL_aPSK) { + CBB new_premaster, child; + uint8_t *new_data; + size_t new_len; - if (!CBB_init(&new_premaster, 2 + psk_len + 2 + premaster_secret_len)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_MALLOC_FAILURE); - goto err; - } - if (!CBB_add_u16_length_prefixed(&new_premaster, &child) || - !CBB_add_bytes(&child, premaster_secret, premaster_secret_len) || - !CBB_add_u16_length_prefixed(&new_premaster, &child) || - !CBB_add_bytes(&child, psk, psk_len) || - !CBB_finish(&new_premaster, &new_data, &new_len)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, ERR_R_INTERNAL_ERROR); - CBB_cleanup(&new_premaster); - goto err; - } + if (!CBB_init(&new_premaster, 2 + psk_len + 2 + premaster_secret_len)) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + ERR_R_MALLOC_FAILURE); + goto err; + } + if (!CBB_add_u16_length_prefixed(&new_premaster, &child) || + !CBB_add_bytes(&child, premaster_secret, premaster_secret_len) || + !CBB_add_u16_length_prefixed(&new_premaster, &child) || + !CBB_add_bytes(&child, psk, psk_len) || + !CBB_finish(&new_premaster, &new_data, &new_len)) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_key_exchange, + ERR_R_INTERNAL_ERROR); + CBB_cleanup(&new_premaster); + goto err; + } - OPENSSL_cleanse(premaster_secret, premaster_secret_len); - OPENSSL_free(premaster_secret); - premaster_secret = new_data; - premaster_secret_len = new_len; - } + OPENSSL_cleanse(premaster_secret, premaster_secret_len); + OPENSSL_free(premaster_secret); + premaster_secret = new_data; + premaster_secret_len = new_len; + } - /* Compute the master secret */ - s->session->master_key_length = s->enc_method - ->generate_master_secret(s, - s->session->master_key, premaster_secret, premaster_secret_len); - if (s->session->master_key_length == 0) - goto err; - s->session->extended_master_secret = s->s3->tmp.extended_master_secret; + /* Compute the master secret */ + s->session->master_key_length = s->enc_method->generate_master_secret( + s, s->session->master_key, premaster_secret, premaster_secret_len); + if (s->session->master_key_length == 0) { + goto err; + } + s->session->extended_master_secret = s->s3->tmp.extended_master_secret; - OPENSSL_cleanse(premaster_secret, premaster_secret_len); - OPENSSL_free(premaster_secret); - return 1; + OPENSSL_cleanse(premaster_secret, premaster_secret_len); + OPENSSL_free(premaster_secret); + return 1; + f_err: - ssl3_send_alert(s,SSL3_AL_FATAL,al); + ssl3_send_alert(s, SSL3_AL_FATAL, al); err: - if (premaster_secret) - { - if (premaster_secret_len) - OPENSSL_cleanse(premaster_secret, premaster_secret_len); - OPENSSL_free(premaster_secret); - } - if (decrypt_buf) - OPENSSL_free(decrypt_buf); - EVP_PKEY_free(clnt_pub_pkey); - EC_POINT_free(clnt_ecpoint); - if (srvr_ecdh != NULL) - EC_KEY_free(srvr_ecdh); - BN_CTX_free(bn_ctx); - return(-1); - } + if (premaster_secret) { + if (premaster_secret_len) { + OPENSSL_cleanse(premaster_secret, premaster_secret_len); + } + OPENSSL_free(premaster_secret); + } + if (decrypt_buf) { + OPENSSL_free(decrypt_buf); + } + EVP_PKEY_free(clnt_pub_pkey); + EC_POINT_free(clnt_ecpoint); + if (srvr_ecdh != NULL) { + EC_KEY_free(srvr_ecdh); + } + BN_CTX_free(bn_ctx); -int ssl3_get_cert_verify(SSL *s) - { - int al,ok,ret=0; - long n; - CBS certificate_verify, signature; - X509 *peer = s->session->peer; - EVP_PKEY *pkey = NULL; - const EVP_MD *md = NULL; - uint8_t digest[EVP_MAX_MD_SIZE]; - size_t digest_length; - EVP_PKEY_CTX *pctx = NULL; + return -1; +} - /* Only RSA and ECDSA client certificates are supported, so a - * CertificateVerify is required if and only if there's a - * client certificate. */ - if (peer == NULL) - { - if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s, free_handshake_buffer)) - return -1; - return 1; - } +int ssl3_get_cert_verify(SSL *s) { + int al, ok, ret = 0; + long n; + CBS certificate_verify, signature; + X509 *peer = s->session->peer; + EVP_PKEY *pkey = NULL; + const EVP_MD *md = NULL; + uint8_t digest[EVP_MAX_MD_SIZE]; + size_t digest_length; + EVP_PKEY_CTX *pctx = NULL; - n=s->method->ssl_get_message(s, - SSL3_ST_SR_CERT_VRFY_A, - SSL3_ST_SR_CERT_VRFY_B, - SSL3_MT_CERTIFICATE_VERIFY, - SSL3_RT_MAX_PLAIN_LENGTH, - SSL_GET_MESSAGE_DONT_HASH_MESSAGE, - &ok); + /* Only RSA and ECDSA client certificates are supported, so a + * CertificateVerify is required if and only if there's a client certificate. + * */ + if (peer == NULL) { + if (s->s3->handshake_buffer && + !ssl3_digest_cached_records(s, free_handshake_buffer)) { + return -1; + } + return 1; + } - if (!ok) - return (int)n; + n = s->method->ssl_get_message( + s, SSL3_ST_SR_CERT_VRFY_A, SSL3_ST_SR_CERT_VRFY_B, + SSL3_MT_CERTIFICATE_VERIFY, SSL3_RT_MAX_PLAIN_LENGTH, + SSL_GET_MESSAGE_DONT_HASH_MESSAGE, &ok); - /* Filter out unsupported certificate types. */ - pkey = X509_get_pubkey(peer); - if (!(X509_certificate_type(peer, pkey) & EVP_PKT_SIGN) || - (pkey->type != EVP_PKEY_RSA && pkey->type != EVP_PKEY_EC)) - { - al = SSL_AD_UNSUPPORTED_CERTIFICATE; - OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_verify, SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE); - goto f_err; - } + if (!ok) { + return n; + } - CBS_init(&certificate_verify, s->init_msg, n); + /* Filter out unsupported certificate types. */ + pkey = X509_get_pubkey(peer); + if (!(X509_certificate_type(peer, pkey) & EVP_PKT_SIGN) || + (pkey->type != EVP_PKEY_RSA && pkey->type != EVP_PKEY_EC)) { + al = SSL_AD_UNSUPPORTED_CERTIFICATE; + OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_verify, + SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE); + goto f_err; + } - /* Determine the digest type if needbe. */ - if (SSL_USE_SIGALGS(s)) - { - if (!tls12_check_peer_sigalg(&md, &al, s, &certificate_verify, pkey)) - goto f_err; - } + CBS_init(&certificate_verify, s->init_msg, n); - /* Compute the digest. */ - if (!ssl3_cert_verify_hash(s, digest, &digest_length, &md, pkey)) - goto err; + /* Determine the digest type if needbe. */ + if (SSL_USE_SIGALGS(s) && + !tls12_check_peer_sigalg(&md, &al, s, &certificate_verify, pkey)) { + goto f_err; + } - /* The handshake buffer is no longer necessary, and we may hash the - * current message.*/ - if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s, free_handshake_buffer)) - goto err; - ssl3_hash_current_message(s); + /* Compute the digest. */ + if (!ssl3_cert_verify_hash(s, digest, &digest_length, &md, pkey)) { + goto err; + } - /* Parse and verify the signature. */ - if (!CBS_get_u16_length_prefixed(&certificate_verify, &signature) || - CBS_len(&certificate_verify) != 0) - { - al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_verify, SSL_R_DECODE_ERROR); - goto f_err; - } + /* The handshake buffer is no longer necessary, and we may hash the current + * message.*/ + if (s->s3->handshake_buffer && + !ssl3_digest_cached_records(s, free_handshake_buffer)) { + goto err; + } + ssl3_hash_current_message(s); - pctx = EVP_PKEY_CTX_new(pkey, NULL); - if (pctx == NULL) - goto err; - if (!EVP_PKEY_verify_init(pctx) || - !EVP_PKEY_CTX_set_signature_md(pctx, md) || - !EVP_PKEY_verify(pctx, CBS_data(&signature), CBS_len(&signature), - digest, digest_length)) - { - al = SSL_AD_DECRYPT_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_verify, SSL_R_BAD_SIGNATURE); - goto f_err; - } + /* Parse and verify the signature. */ + if (!CBS_get_u16_length_prefixed(&certificate_verify, &signature) || + CBS_len(&certificate_verify) != 0) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_verify, SSL_R_DECODE_ERROR); + goto f_err; + } - ret = 1; - if (0) - { -f_err: - ssl3_send_alert(s,SSL3_AL_FATAL,al); - } + pctx = EVP_PKEY_CTX_new(pkey, NULL); + if (pctx == NULL) { + goto err; + } + if (!EVP_PKEY_verify_init(pctx) || + !EVP_PKEY_CTX_set_signature_md(pctx, md) || + !EVP_PKEY_verify(pctx, CBS_data(&signature), CBS_len(&signature), digest, + digest_length)) { + al = SSL_AD_DECRYPT_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_cert_verify, SSL_R_BAD_SIGNATURE); + goto f_err; + } + + ret = 1; + + if (0) { + f_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + } + err: - EVP_PKEY_CTX_free(pctx); - EVP_PKEY_free(pkey); - return(ret); - } + EVP_PKEY_CTX_free(pctx); + EVP_PKEY_free(pkey); -int ssl3_get_client_certificate(SSL *s) - { - int i,ok,al,ret= -1; - X509 *x=NULL; - unsigned long n; - STACK_OF(X509) *sk=NULL; - SHA256_CTX sha256; - CBS certificate_msg, certificate_list; - int is_first_certificate = 1; + return ret; +} - n=s->method->ssl_get_message(s, - SSL3_ST_SR_CERT_A, - SSL3_ST_SR_CERT_B, - -1, - s->max_cert_list, - SSL_GET_MESSAGE_HASH_MESSAGE, - &ok); +int ssl3_get_client_certificate(SSL *s) { + int i, ok, al, ret = -1; + X509 *x = NULL; + unsigned long n; + STACK_OF(X509) *sk = NULL; + SHA256_CTX sha256; + CBS certificate_msg, certificate_list; + int is_first_certificate = 1; - if (!ok) return((int)n); + n = s->method->ssl_get_message(s, SSL3_ST_SR_CERT_A, SSL3_ST_SR_CERT_B, -1, + s->max_cert_list, SSL_GET_MESSAGE_HASH_MESSAGE, + &ok); - if (s->s3->tmp.message_type == SSL3_MT_CLIENT_KEY_EXCHANGE) - { - if ( (s->verify_mode & SSL_VERIFY_PEER) && - (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); - al=SSL_AD_HANDSHAKE_FAILURE; - goto f_err; - } - /* If tls asked for a client cert, the client must return a 0 list */ - if ((s->version > SSL3_VERSION) && s->s3->tmp.cert_request) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST); - al=SSL_AD_UNEXPECTED_MESSAGE; - goto f_err; - } - s->s3->tmp.reuse_message=1; - return(1); - } + if (!ok) { + return n; + } - if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE) - { - al=SSL_AD_UNEXPECTED_MESSAGE; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, SSL_R_WRONG_MESSAGE_TYPE); - goto f_err; - } + if (s->s3->tmp.message_type == SSL3_MT_CLIENT_KEY_EXCHANGE) { + if ((s->verify_mode & SSL_VERIFY_PEER) && + (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, + SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); + al = SSL_AD_HANDSHAKE_FAILURE; + goto f_err; + } - CBS_init(&certificate_msg, s->init_msg, n); + /* If tls asked for a client cert, the client must return a 0 list */ + if (s->version > SSL3_VERSION && s->s3->tmp.cert_request) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, + SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST); + al = SSL_AD_UNEXPECTED_MESSAGE; + goto f_err; + } + s->s3->tmp.reuse_message = 1; - if ((sk=sk_X509_new_null()) == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, ERR_R_MALLOC_FAILURE); - goto err; - } + return 1; + } - if (!CBS_get_u24_length_prefixed(&certificate_msg, &certificate_list) || - CBS_len(&certificate_msg) != 0) - { - al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, SSL_R_DECODE_ERROR); - goto f_err; - } + if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE) { + al = SSL_AD_UNEXPECTED_MESSAGE; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, + SSL_R_WRONG_MESSAGE_TYPE); + goto f_err; + } - while (CBS_len(&certificate_list) > 0) - { - CBS certificate; - const uint8_t *data; + CBS_init(&certificate_msg, s->init_msg, n); - if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate)) - { - al = SSL_AD_DECODE_ERROR; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, SSL_R_DECODE_ERROR); - goto f_err; - } - if (is_first_certificate && s->ctx->retain_only_sha256_of_client_certs) - { - /* If this is the first certificate, and we don't want - * to keep peer certificates in memory, then we hash it - * right away. */ - SHA256_Init(&sha256); - SHA256_Update(&sha256, CBS_data(&certificate), CBS_len(&certificate)); - SHA256_Final(s->session->peer_sha256, &sha256); - s->session->peer_sha256_valid = 1; - } - is_first_certificate = 0; - 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_client_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_client_certificate, SSL_R_CERT_LENGTH_MISMATCH); - goto f_err; - } - if (!sk_X509_push(sk, x)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, ERR_R_MALLOC_FAILURE); - goto err; - } - x = NULL; - } + sk = sk_X509_new_null(); + if (sk == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, ERR_R_MALLOC_FAILURE); + goto err; + } - if (sk_X509_num(sk) <= 0) - { - /* TLS does not mind 0 certs returned */ - if (s->version == SSL3_VERSION) - { - al=SSL_AD_HANDSHAKE_FAILURE; - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, SSL_R_NO_CERTIFICATES_RETURNED); - goto f_err; - } - /* Fail for TLS only if we required a certificate */ - else if ((s->verify_mode & SSL_VERIFY_PEER) && - (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); - al=SSL_AD_HANDSHAKE_FAILURE; - goto f_err; - } - /* No client certificate so digest cached records */ - if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s, free_handshake_buffer)) - { - al=SSL_AD_INTERNAL_ERROR; - goto f_err; - } - } - else - { - i=ssl_verify_cert_chain(s,sk); - if (i <= 0) - { - al=ssl_verify_alarm_type(s->verify_result); - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, SSL_R_CERTIFICATE_VERIFY_FAILED); - goto f_err; - } - } + if (!CBS_get_u24_length_prefixed(&certificate_msg, &certificate_list) || + CBS_len(&certificate_msg) != 0) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, SSL_R_DECODE_ERROR); + goto f_err; + } - if (s->session->peer != NULL) /* This should not be needed */ - X509_free(s->session->peer); - s->session->peer=sk_X509_shift(sk); - s->session->verify_result = s->verify_result; + while (CBS_len(&certificate_list) > 0) { + CBS certificate; + const uint8_t *data; - /* With the current implementation, sess_cert will always be NULL - * when we arrive here. */ - if (s->session->sess_cert == NULL) - { - s->session->sess_cert = ssl_sess_cert_new(); - if (s->session->sess_cert == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, ERR_R_MALLOC_FAILURE); - goto err; - } - } - if (s->session->sess_cert->cert_chain != NULL) - sk_X509_pop_free(s->session->sess_cert->cert_chain, X509_free); - s->session->sess_cert->cert_chain=sk; - /* Inconsistency alert: cert_chain does *not* include the - * peer's own certificate, while we do include it in s3_clnt.c */ + if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate)) { + al = SSL_AD_DECODE_ERROR; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, SSL_R_DECODE_ERROR); + goto f_err; + } - sk=NULL; + if (is_first_certificate && s->ctx->retain_only_sha256_of_client_certs) { + /* If this is the first certificate, and we don't want to keep peer + * certificates in memory, then we hash it right away. */ + SHA256_Init(&sha256); + SHA256_Update(&sha256, CBS_data(&certificate), CBS_len(&certificate)); + SHA256_Final(s->session->peer_sha256, &sha256); + s->session->peer_sha256_valid = 1; + } + is_first_certificate = 0; - ret=1; - if (0) - { -f_err: - ssl3_send_alert(s,SSL3_AL_FATAL,al); - } + 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_client_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_client_certificate, + SSL_R_CERT_LENGTH_MISMATCH); + goto f_err; + } + if (!sk_X509_push(sk, x)) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, ERR_R_MALLOC_FAILURE); + goto err; + } + x = NULL; + } + + if (sk_X509_num(sk) <= 0) { + /* TLS does not mind 0 certs returned */ + if (s->version == SSL3_VERSION) { + al = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, + SSL_R_NO_CERTIFICATES_RETURNED); + goto f_err; + } + /* Fail for TLS only if we required a certificate */ + else if ((s->verify_mode & SSL_VERIFY_PEER) && + (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, + SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); + al = SSL_AD_HANDSHAKE_FAILURE; + goto f_err; + } + /* No client certificate so digest cached records */ + if (s->s3->handshake_buffer && + !ssl3_digest_cached_records(s, free_handshake_buffer)) { + al = SSL_AD_INTERNAL_ERROR; + goto f_err; + } + } else { + i = ssl_verify_cert_chain(s, sk); + if (i <= 0) { + al = ssl_verify_alarm_type(s->verify_result); + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, + SSL_R_CERTIFICATE_VERIFY_FAILED); + goto f_err; + } + } + + if (s->session->peer != NULL) { + /* This should not be needed */ + X509_free(s->session->peer); + } + + s->session->peer = sk_X509_shift(sk); + s->session->verify_result = s->verify_result; + + /* With the current implementation, sess_cert will always be NULL when we + * arrive here. */ + if (s->session->sess_cert == NULL) { + s->session->sess_cert = ssl_sess_cert_new(); + if (s->session->sess_cert == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_client_certificate, ERR_R_MALLOC_FAILURE); + goto err; + } + } + if (s->session->sess_cert->cert_chain != NULL) { + sk_X509_pop_free(s->session->sess_cert->cert_chain, X509_free); + } + s->session->sess_cert->cert_chain = sk; + /* Inconsistency alert: cert_chain does *not* include the peer's own + * certificate, while we do include it in s3_clnt.c */ + + sk = NULL; + + ret = 1; + + if (0) { + f_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + } + err: - if (x != NULL) X509_free(x); - if (sk != NULL) sk_X509_pop_free(sk,X509_free); - return(ret); - } + if (x != NULL) { + X509_free(x); + } + if (sk != NULL) { + sk_X509_pop_free(sk, X509_free); + } + return ret; +} -int ssl3_send_server_certificate(SSL *s) - { - CERT_PKEY *cpk; +int ssl3_send_server_certificate(SSL *s) { + CERT_PKEY *cpk; - if (s->state == SSL3_ST_SW_CERT_A) - { - cpk=ssl_get_server_send_pkey(s); - if (cpk == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl3_send_server_certificate, ERR_R_INTERNAL_ERROR); - return(0); - } + if (s->state == SSL3_ST_SW_CERT_A) { + cpk = ssl_get_server_send_pkey(s); + if (cpk == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl3_send_server_certificate, + ERR_R_INTERNAL_ERROR); + return 0; + } - ssl3_output_cert_chain(s,cpk); - s->state=SSL3_ST_SW_CERT_B; - } + ssl3_output_cert_chain(s, cpk); + s->state = SSL3_ST_SW_CERT_B; + } - /* SSL3_ST_SW_CERT_B */ - return ssl_do_write(s); - } + /* SSL3_ST_SW_CERT_B */ + return ssl_do_write(s); +} /* send a new session ticket (not necessarily for a new session) */ -int ssl3_send_new_session_ticket(SSL *s) - { - if (s->state == SSL3_ST_SW_SESSION_TICKET_A) - { - uint8_t *session; - size_t session_len; - uint8_t *p, *macstart; - int len; - unsigned int hlen; - EVP_CIPHER_CTX ctx; - HMAC_CTX hctx; - SSL_CTX *tctx = s->initial_ctx; - unsigned char iv[EVP_MAX_IV_LENGTH]; - unsigned char key_name[16]; - /* The maximum overhead of encrypting the session is 16 (key - * name) + IV + one block of encryption overhead + HMAC. */ - const size_t max_ticket_overhead = 16 + EVP_MAX_IV_LENGTH + - EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE; +int ssl3_send_new_session_ticket(SSL *s) { + if (s->state == SSL3_ST_SW_SESSION_TICKET_A) { + uint8_t *session; + size_t session_len; + uint8_t *p, *macstart; + int len; + unsigned int hlen; + EVP_CIPHER_CTX ctx; + HMAC_CTX hctx; + SSL_CTX *tctx = s->initial_ctx; + uint8_t iv[EVP_MAX_IV_LENGTH]; + uint8_t key_name[16]; + /* The maximum overhead of encrypting the session is 16 (key name) + IV + + * one block of encryption overhead + HMAC. */ + const size_t max_ticket_overhead = + 16 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE; - /* Serialize the SSL_SESSION to be encoded into the ticket. */ - if (!SSL_SESSION_to_bytes_for_ticket(s->session, &session, - &session_len)) - { - return -1; - } + /* Serialize the SSL_SESSION to be encoded into the ticket. */ + if (!SSL_SESSION_to_bytes_for_ticket(s->session, &session, &session_len)) { + return -1; + } - /* If the session is too long, emit a dummy value rather than - * abort the connection. */ - if (session_len > 0xFFFF - max_ticket_overhead) - { - const char kTicketPlaceholder[] = "TICKET TOO LARGE"; - size_t placeholder_len = strlen(kTicketPlaceholder); + /* If the session is too long, emit a dummy value rather than abort the + * connection. */ + if (session_len > 0xFFFF - max_ticket_overhead) { + static const char kTicketPlaceholder[] = "TICKET TOO LARGE"; + const size_t placeholder_len = strlen(kTicketPlaceholder); - OPENSSL_free(session); + OPENSSL_free(session); - p = ssl_handshake_start(s); - /* Emit ticket_lifetime_hint. */ - l2n(0, p); - /* Emit ticket. */ - s2n(placeholder_len, p); - memcpy(p, kTicketPlaceholder, placeholder_len); - p += placeholder_len; + p = ssl_handshake_start(s); + /* Emit ticket_lifetime_hint. */ + l2n(0, p); + /* Emit ticket. */ + s2n(placeholder_len, p); + memcpy(p, kTicketPlaceholder, placeholder_len); + p += placeholder_len; - len = p - ssl_handshake_start(s); - ssl_set_handshake_header(s, SSL3_MT_NEWSESSION_TICKET, len); - s->state = SSL3_ST_SW_SESSION_TICKET_B; - return ssl_do_write(s); - } + len = p - ssl_handshake_start(s); + ssl_set_handshake_header(s, SSL3_MT_NEWSESSION_TICKET, len); + s->state = SSL3_ST_SW_SESSION_TICKET_B; + return ssl_do_write(s); + } - /* Grow buffer if need be: the length calculation is as - * follows: handshake_header_length + - * 4 (ticket lifetime hint) + 2 (ticket length) + - * max_ticket_overhead + * session_length */ - if (!BUF_MEM_grow(s->init_buf, - SSL_HM_HEADER_LENGTH(s) + 6 + - max_ticket_overhead + session_len)) - { - OPENSSL_free(session); - return -1; - } - p = ssl_handshake_start(s); - EVP_CIPHER_CTX_init(&ctx); - HMAC_CTX_init(&hctx); - /* Initialize HMAC and cipher contexts. If callback present - * it does all the work otherwise use generated values - * from parent ctx. - */ - if (tctx->tlsext_ticket_key_cb) - { - if (tctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx, - &hctx, 1) < 0) - { - OPENSSL_free(session); - EVP_CIPHER_CTX_cleanup(&ctx); - HMAC_CTX_cleanup(&hctx); - return -1; - } - } - else - { - if (!RAND_bytes(iv, 16) || - !EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, tctx->tlsext_tick_aes_key, iv) || - !HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16, tlsext_tick_md(), NULL)) - { - OPENSSL_free(session); - EVP_CIPHER_CTX_cleanup(&ctx); - HMAC_CTX_cleanup(&hctx); - return -1; - } - memcpy(key_name, tctx->tlsext_tick_key_name, 16); - } + /* Grow buffer if need be: the length calculation is as follows: + * handshake_header_length + 4 (ticket lifetime hint) + 2 (ticket length) + + * max_ticket_overhead + * session_length */ + if (!BUF_MEM_grow(s->init_buf, SSL_HM_HEADER_LENGTH(s) + 6 + + max_ticket_overhead + session_len)) { + OPENSSL_free(session); + return -1; + } + p = ssl_handshake_start(s); + EVP_CIPHER_CTX_init(&ctx); + HMAC_CTX_init(&hctx); + /* Initialize HMAC and cipher contexts. If callback present it does all the + * work otherwise use generated values from parent ctx. */ + if (tctx->tlsext_ticket_key_cb) { + if (tctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx, &hctx, 1) < 0) { + OPENSSL_free(session); + EVP_CIPHER_CTX_cleanup(&ctx); + HMAC_CTX_cleanup(&hctx); + return -1; + } + } else { + if (!RAND_bytes(iv, 16) || + !EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, + tctx->tlsext_tick_aes_key, iv) || + !HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16, tlsext_tick_md(), + NULL)) { + OPENSSL_free(session); + EVP_CIPHER_CTX_cleanup(&ctx); + HMAC_CTX_cleanup(&hctx); + return -1; + } + memcpy(key_name, tctx->tlsext_tick_key_name, 16); + } - /* Ticket lifetime hint (advisory only): - * We leave this unspecified for resumed session (for simplicity), - * and guess that tickets for new sessions will live as long - * as their sessions. */ - l2n(s->hit ? 0 : s->session->timeout, p); + /* Ticket lifetime hint (advisory only): We leave this unspecified for + * resumed session (for simplicity), and guess that tickets for new + * sessions will live as long as their sessions. */ + l2n(s->hit ? 0 : s->session->timeout, p); - /* Skip ticket length for now */ - p += 2; - /* Output key name */ - macstart = p; - memcpy(p, key_name, 16); - p += 16; - /* output IV */ - memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx)); - p += EVP_CIPHER_CTX_iv_length(&ctx); - /* Encrypt session data */ - EVP_EncryptUpdate(&ctx, p, &len, session, session_len); - p += len; - EVP_EncryptFinal_ex(&ctx, p, &len); - p += len; - EVP_CIPHER_CTX_cleanup(&ctx); + /* Skip ticket length for now */ + p += 2; + /* Output key name */ + macstart = p; + memcpy(p, key_name, 16); + p += 16; + /* output IV */ + memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx)); + p += EVP_CIPHER_CTX_iv_length(&ctx); + /* Encrypt session data */ + EVP_EncryptUpdate(&ctx, p, &len, session, session_len); + p += len; + EVP_EncryptFinal_ex(&ctx, p, &len); + p += len; + EVP_CIPHER_CTX_cleanup(&ctx); - HMAC_Update(&hctx, macstart, p - macstart); - HMAC_Final(&hctx, p, &hlen); - HMAC_CTX_cleanup(&hctx); + HMAC_Update(&hctx, macstart, p - macstart); + HMAC_Final(&hctx, p, &hlen); + HMAC_CTX_cleanup(&hctx); - p += hlen; - /* Now write out lengths: p points to end of data written */ - /* Total length */ - len = p - ssl_handshake_start(s); - /* Skip ticket lifetime hint */ - p = ssl_handshake_start(s) + 4; - s2n(len - 6, p); - ssl_set_handshake_header(s, SSL3_MT_NEWSESSION_TICKET, len); - s->state=SSL3_ST_SW_SESSION_TICKET_B; - OPENSSL_free(session); - } + p += hlen; + /* Now write out lengths: p points to end of data written */ + /* Total length */ + len = p - ssl_handshake_start(s); + /* Skip ticket lifetime hint */ + p = ssl_handshake_start(s) + 4; + s2n(len - 6, p); + ssl_set_handshake_header(s, SSL3_MT_NEWSESSION_TICKET, len); + s->state = SSL3_ST_SW_SESSION_TICKET_B; + OPENSSL_free(session); + } - /* SSL3_ST_SW_SESSION_TICKET_B */ - return ssl_do_write(s); - } - -#if 0 -int ssl3_send_cert_status(SSL *s) - { - if (s->state == SSL3_ST_SW_CERT_STATUS_A) - { - unsigned char *p; - /* Grow buffer if need be: the length calculation is as - * follows 1 (message type) + 3 (message length) + - * 1 (ocsp response type) + 3 (ocsp response length) - * + (ocsp response) - */ - if (!BUF_MEM_grow(s->init_buf, 8 + s->tlsext_ocsp_resplen)) - return -1; - - p=(unsigned char *)s->init_buf->data; - - /* do the header */ - *(p++)=SSL3_MT_CERTIFICATE_STATUS; - /* message length */ - l2n3(s->tlsext_ocsp_resplen + 4, p); - /* status type */ - *(p++)= s->tlsext_status_type; - /* length of OCSP response */ - l2n3(s->tlsext_ocsp_resplen, p); - /* actual response */ - memcpy(p, s->tlsext_ocsp_resp, s->tlsext_ocsp_resplen); - /* number of bytes to write */ - s->init_num = 8 + s->tlsext_ocsp_resplen; - s->state=SSL3_ST_SW_CERT_STATUS_B; - s->init_off = 0; - } - - /* SSL3_ST_SW_CERT_STATUS_B */ - return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); - } -#endif + /* SSL3_ST_SW_SESSION_TICKET_B */ + return ssl_do_write(s); +} /* ssl3_get_next_proto reads a Next Protocol Negotiation handshake message. It * sets the next_proto member in s if found */ -int ssl3_get_next_proto(SSL *s) - { - int ok; - long n; - CBS next_protocol, selected_protocol, padding; +int ssl3_get_next_proto(SSL *s) { + int ok; + long n; + CBS next_protocol, selected_protocol, padding; - /* Clients cannot send a NextProtocol message if we didn't see the - * extension in their ClientHello */ - if (!s->s3->next_proto_neg_seen) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_next_proto, SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION); - return -1; - } + /* Clients cannot send a NextProtocol message if we didn't see the extension + * in their ClientHello */ + if (!s->s3->next_proto_neg_seen) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_next_proto, + SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION); + return -1; + } - n=s->method->ssl_get_message(s, - SSL3_ST_SR_NEXT_PROTO_A, - SSL3_ST_SR_NEXT_PROTO_B, - SSL3_MT_NEXT_PROTO, - 514, /* See the payload format below */ - SSL_GET_MESSAGE_HASH_MESSAGE, - &ok); + n = s->method->ssl_get_message(s, SSL3_ST_SR_NEXT_PROTO_A, + SSL3_ST_SR_NEXT_PROTO_B, SSL3_MT_NEXT_PROTO, + 514, /* See the payload format below */ + SSL_GET_MESSAGE_HASH_MESSAGE, &ok); - if (!ok) - return((int)n); + if (!ok) { + return n; + } - /* s->state doesn't reflect whether ChangeCipherSpec has been received - * in this handshake, but s->s3->change_cipher_spec does (will be reset - * by ssl3_get_finished). - * TODO(davidben): Is this check now redundant with - * SSL3_FLAGS_EXPECT_CCS? */ - if (!s->s3->change_cipher_spec) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_next_proto, SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS); - return -1; - } + /* s->state doesn't reflect whether ChangeCipherSpec has been received in + * this handshake, but s->s3->change_cipher_spec does (will be reset by + * ssl3_get_finished). + * + * TODO(davidben): Is this check now redundant with + * SSL3_FLAGS_EXPECT_CCS? */ + if (!s->s3->change_cipher_spec) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_next_proto, + SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS); + return -1; + } - CBS_init(&next_protocol, s->init_msg, n); + CBS_init(&next_protocol, s->init_msg, n); - /* The payload looks like: - * uint8 proto_len; - * uint8 proto[proto_len]; - * uint8 padding_len; - * uint8 padding[padding_len]; - */ - if (!CBS_get_u8_length_prefixed(&next_protocol, &selected_protocol) || - !CBS_get_u8_length_prefixed(&next_protocol, &padding) || - CBS_len(&next_protocol) != 0) - return 0; + /* The payload looks like: + * uint8 proto_len; + * uint8 proto[proto_len]; + * uint8 padding_len; + * uint8 padding[padding_len]; */ + if (!CBS_get_u8_length_prefixed(&next_protocol, &selected_protocol) || + !CBS_get_u8_length_prefixed(&next_protocol, &padding) || + CBS_len(&next_protocol) != 0 || + !CBS_stow(&selected_protocol, &s->next_proto_negotiated, + &s->next_proto_negotiated_len)) { + return 0; + } - if (!CBS_stow(&selected_protocol, - &s->next_proto_negotiated, - &s->next_proto_negotiated_len)) - return 0; - - return 1; - } + return 1; +} /* ssl3_get_channel_id reads and verifies a ClientID handshake message. */ -int ssl3_get_channel_id(SSL *s) - { - int ret = -1, ok; - long n; - EVP_MD_CTX md_ctx; - uint8_t channel_id_hash[SHA256_DIGEST_LENGTH]; - unsigned int channel_id_hash_len; - const uint8_t *p; - uint16_t extension_type, expected_extension_type; - EC_GROUP* p256 = NULL; - EC_KEY* key = NULL; - EC_POINT* point = NULL; - ECDSA_SIG sig; - BIGNUM x, y; - CBS encrypted_extensions, extension; +int ssl3_get_channel_id(SSL *s) { + int ret = -1, ok; + long n; + EVP_MD_CTX md_ctx; + uint8_t channel_id_hash[SHA256_DIGEST_LENGTH]; + unsigned int channel_id_hash_len; + const uint8_t *p; + uint16_t extension_type, expected_extension_type; + EC_GROUP *p256 = NULL; + EC_KEY *key = NULL; + EC_POINT *point = NULL; + ECDSA_SIG sig; + BIGNUM x, y; + CBS encrypted_extensions, extension; - n = s->method->ssl_get_message(s, - SSL3_ST_SR_CHANNEL_ID_A, - SSL3_ST_SR_CHANNEL_ID_B, - SSL3_MT_ENCRYPTED_EXTENSIONS, - 2 + 2 + TLSEXT_CHANNEL_ID_SIZE, - SSL_GET_MESSAGE_DONT_HASH_MESSAGE, - &ok); + n = s->method->ssl_get_message( + s, SSL3_ST_SR_CHANNEL_ID_A, SSL3_ST_SR_CHANNEL_ID_B, + SSL3_MT_ENCRYPTED_EXTENSIONS, 2 + 2 + TLSEXT_CHANNEL_ID_SIZE, + SSL_GET_MESSAGE_DONT_HASH_MESSAGE, &ok); - if (!ok) - return((int)n); + if (!ok) { + return n; + } - /* Before incorporating the EncryptedExtensions message to the - * handshake hash, compute the hash that should have been signed. */ - channel_id_hash_len = sizeof(channel_id_hash); - EVP_MD_CTX_init(&md_ctx); - if (!EVP_DigestInit_ex(&md_ctx, EVP_sha256(), NULL) || - !tls1_channel_id_hash(&md_ctx, s) || - !EVP_DigestFinal(&md_ctx, channel_id_hash, &channel_id_hash_len)) - { - EVP_MD_CTX_cleanup(&md_ctx); - return -1; - } - EVP_MD_CTX_cleanup(&md_ctx); - assert(channel_id_hash_len == SHA256_DIGEST_LENGTH); + /* Before incorporating the EncryptedExtensions message to the handshake + * hash, compute the hash that should have been signed. */ + channel_id_hash_len = sizeof(channel_id_hash); + EVP_MD_CTX_init(&md_ctx); + if (!EVP_DigestInit_ex(&md_ctx, EVP_sha256(), NULL) || + !tls1_channel_id_hash(&md_ctx, s) || + !EVP_DigestFinal(&md_ctx, channel_id_hash, &channel_id_hash_len)) { + EVP_MD_CTX_cleanup(&md_ctx); + return -1; + } + EVP_MD_CTX_cleanup(&md_ctx); + assert(channel_id_hash_len == SHA256_DIGEST_LENGTH); - ssl3_hash_current_message(s); + ssl3_hash_current_message(s); - /* s->state doesn't reflect whether ChangeCipherSpec has been received - * in this handshake, but s->s3->change_cipher_spec does (will be reset - * by ssl3_get_finished). - * TODO(davidben): Is this check now redundant with - * SSL3_FLAGS_EXPECT_CCS? */ - if (!s->s3->change_cipher_spec) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_channel_id, SSL_R_GOT_CHANNEL_ID_BEFORE_A_CCS); - return -1; - } + /* s->state doesn't reflect whether ChangeCipherSpec has been received in + * this handshake, but s->s3->change_cipher_spec does (will be reset by + * ssl3_get_finished). + * + * TODO(davidben): Is this check now redundant with SSL3_FLAGS_EXPECT_CCS? */ + if (!s->s3->change_cipher_spec) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_channel_id, + SSL_R_GOT_CHANNEL_ID_BEFORE_A_CCS); + return -1; + } - CBS_init(&encrypted_extensions, s->init_msg, n); + CBS_init(&encrypted_extensions, s->init_msg, n); - /* EncryptedExtensions could include multiple extensions, but - * the only extension that could be negotiated is ChannelID, - * so there can only be one entry. - * - * The payload looks like: - * uint16 extension_type - * uint16 extension_len; - * uint8 x[32]; - * uint8 y[32]; - * uint8 r[32]; - * uint8 s[32]; - */ - expected_extension_type = TLSEXT_TYPE_channel_id; - if (s->s3->tlsext_channel_id_new) - expected_extension_type = TLSEXT_TYPE_channel_id_new; + /* EncryptedExtensions could include multiple extensions, but the only + * extension that could be negotiated is ChannelID, so there can only be one + * entry. + * + * The payload looks like: + * uint16 extension_type + * uint16 extension_len; + * uint8 x[32]; + * uint8 y[32]; + * uint8 r[32]; + * uint8 s[32]; */ + expected_extension_type = TLSEXT_TYPE_channel_id; + if (s->s3->tlsext_channel_id_new) { + expected_extension_type = TLSEXT_TYPE_channel_id_new; + } - if (!CBS_get_u16(&encrypted_extensions, &extension_type) || - !CBS_get_u16_length_prefixed(&encrypted_extensions, &extension) || - CBS_len(&encrypted_extensions) != 0 || - extension_type != expected_extension_type || - CBS_len(&extension) != TLSEXT_CHANNEL_ID_SIZE) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_channel_id, SSL_R_INVALID_MESSAGE); - return -1; - } + if (!CBS_get_u16(&encrypted_extensions, &extension_type) || + !CBS_get_u16_length_prefixed(&encrypted_extensions, &extension) || + CBS_len(&encrypted_extensions) != 0 || + extension_type != expected_extension_type || + CBS_len(&extension) != TLSEXT_CHANNEL_ID_SIZE) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_channel_id, SSL_R_INVALID_MESSAGE); + return -1; + } - p256 = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); - if (!p256) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_channel_id, SSL_R_NO_P256_SUPPORT); - return -1; - } + p256 = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); + if (!p256) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_channel_id, SSL_R_NO_P256_SUPPORT); + return -1; + } - BN_init(&x); - BN_init(&y); - sig.r = BN_new(); - sig.s = BN_new(); + BN_init(&x); + BN_init(&y); + sig.r = BN_new(); + sig.s = BN_new(); - p = CBS_data(&extension); - if (BN_bin2bn(p + 0, 32, &x) == NULL || - BN_bin2bn(p + 32, 32, &y) == NULL || - BN_bin2bn(p + 64, 32, sig.r) == NULL || - BN_bin2bn(p + 96, 32, sig.s) == NULL) - goto err; + p = CBS_data(&extension); + if (BN_bin2bn(p + 0, 32, &x) == NULL || + BN_bin2bn(p + 32, 32, &y) == NULL || + BN_bin2bn(p + 64, 32, sig.r) == NULL || + BN_bin2bn(p + 96, 32, sig.s) == NULL) { + goto err; + } - point = EC_POINT_new(p256); - if (!point || - !EC_POINT_set_affine_coordinates_GFp(p256, point, &x, &y, NULL)) - goto err; + point = EC_POINT_new(p256); + if (!point || !EC_POINT_set_affine_coordinates_GFp(p256, point, &x, &y, NULL)) { + goto err; + } - key = EC_KEY_new(); - if (!key || - !EC_KEY_set_group(key, p256) || - !EC_KEY_set_public_key(key, point)) - goto err; + key = EC_KEY_new(); + if (!key || !EC_KEY_set_group(key, p256) || + !EC_KEY_set_public_key(key, point)) { + goto err; + } - /* We stored the handshake hash in |tlsext_channel_id| the first time - * that we were called. */ - if (!ECDSA_do_verify(channel_id_hash, channel_id_hash_len, &sig, key)) - { - OPENSSL_PUT_ERROR(SSL, ssl3_get_channel_id, SSL_R_CHANNEL_ID_SIGNATURE_INVALID); - s->s3->tlsext_channel_id_valid = 0; - goto err; - } + /* We stored the handshake hash in |tlsext_channel_id| the first time that we + * were called. */ + if (!ECDSA_do_verify(channel_id_hash, channel_id_hash_len, &sig, key)) { + OPENSSL_PUT_ERROR(SSL, ssl3_get_channel_id, + SSL_R_CHANNEL_ID_SIGNATURE_INVALID); + s->s3->tlsext_channel_id_valid = 0; + goto err; + } - memcpy(s->s3->tlsext_channel_id, p, 64); - ret = 1; + memcpy(s->s3->tlsext_channel_id, p, 64); + ret = 1; err: - BN_free(&x); - BN_free(&y); - BN_free(sig.r); - BN_free(sig.s); - if (key) - EC_KEY_free(key); - if (point) - EC_POINT_free(point); - if (p256) - EC_GROUP_free(p256); - return ret; - } - + BN_free(&x); + BN_free(&y); + BN_free(sig.r); + BN_free(sig.s); + if (key) { + EC_KEY_free(key); + } + if (point) { + EC_POINT_free(point); + } + if (p256) { + EC_GROUP_free(p256); + } + return ret; +}
diff --git a/ssl/ssl_algs.c b/ssl/ssl_algs.c index a1aa7b2..71fabf0 100644 --- a/ssl/ssl_algs.c +++ b/ssl/ssl_algs.c
@@ -60,15 +60,13 @@ extern const ERR_STRING_DATA SSL_error_string_data[]; -int SSL_library_init(void) - { - CRYPTO_library_init(); - SSL_load_error_strings(); - return(1); - } +int SSL_library_init(void) { + CRYPTO_library_init(); + SSL_load_error_strings(); + return 1; +} -void SSL_load_error_strings(void) - { - ERR_load_crypto_strings(); - ERR_load_strings(SSL_error_string_data); - } +void SSL_load_error_strings(void) { + ERR_load_crypto_strings(); + ERR_load_strings(SSL_error_string_data); +}
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c index f3fc663..ed8b524 100644 --- a/ssl/ssl_cert.c +++ b/ssl/ssl_cert.c
@@ -128,994 +128,954 @@ #include "../crypto/directory.h" #include "ssl_locl.h" -int SSL_get_ex_data_X509_STORE_CTX_idx(void) - { - static volatile int ssl_x509_store_ctx_idx= -1; - int got_write_lock = 0; - CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); +int SSL_get_ex_data_X509_STORE_CTX_idx(void) { + static int ssl_x509_store_ctx_idx = -1; + int got_write_lock = 0; - if (ssl_x509_store_ctx_idx < 0) - { - CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); - CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); - got_write_lock = 1; - - if (ssl_x509_store_ctx_idx < 0) - { - ssl_x509_store_ctx_idx=X509_STORE_CTX_get_ex_new_index( - 0,"SSL for verify callback",NULL,NULL,NULL); - } - } + CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); - if (got_write_lock) - CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); - else - CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); - - return ssl_x509_store_ctx_idx; - } + if (ssl_x509_store_ctx_idx < 0) { + CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + got_write_lock = 1; -CERT *ssl_cert_new(void) - { - CERT *ret; + if (ssl_x509_store_ctx_idx < 0) { + ssl_x509_store_ctx_idx = X509_STORE_CTX_get_ex_new_index( + 0, "SSL for verify callback", NULL, NULL, NULL); + } + } - ret=(CERT *)OPENSSL_malloc(sizeof(CERT)); - if (ret == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl_cert_new, ERR_R_MALLOC_FAILURE); - return(NULL); - } - memset(ret,0,sizeof(CERT)); + if (got_write_lock) { + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); + } else { + CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); + } - ret->key= &(ret->pkeys[SSL_PKEY_RSA_ENC]); - return(ret); - } + return ssl_x509_store_ctx_idx; +} -CERT *ssl_cert_dup(CERT *cert) - { - CERT *ret; - int i; +CERT *ssl_cert_new(void) { + CERT *ret; - ret = (CERT *)OPENSSL_malloc(sizeof(CERT)); - if (ret == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_MALLOC_FAILURE); - return(NULL); - } + ret = (CERT *)OPENSSL_malloc(sizeof(CERT)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl_cert_new, ERR_R_MALLOC_FAILURE); + return NULL; + } + memset(ret, 0, sizeof(CERT)); - memset(ret, 0, sizeof(CERT)); + ret->key = &ret->pkeys[SSL_PKEY_RSA_ENC]; + return ret; +} - ret->key = &ret->pkeys[cert->key - &cert->pkeys[0]]; - /* or ret->key = ret->pkeys + (cert->key - cert->pkeys), - * if you find that more readable */ +CERT *ssl_cert_dup(CERT *cert) { + CERT *ret; + int i; - ret->mask_k = cert->mask_k; - ret->mask_a = cert->mask_a; + ret = (CERT *)OPENSSL_malloc(sizeof(CERT)); + if (ret == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_MALLOC_FAILURE); + return NULL; + } - if (cert->dh_tmp != NULL) - { - ret->dh_tmp = DHparams_dup(cert->dh_tmp); - if (ret->dh_tmp == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_DH_LIB); - goto err; - } - if (cert->dh_tmp->priv_key) - { - BIGNUM *b = BN_dup(cert->dh_tmp->priv_key); - if (!b) - { - OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_BN_LIB); - goto err; - } - ret->dh_tmp->priv_key = b; - } - if (cert->dh_tmp->pub_key) - { - BIGNUM *b = BN_dup(cert->dh_tmp->pub_key); - if (!b) - { - OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_BN_LIB); - goto err; - } - ret->dh_tmp->pub_key = b; - } - } - ret->dh_tmp_cb = cert->dh_tmp_cb; + memset(ret, 0, sizeof(CERT)); - if (cert->ecdh_tmp) - { - ret->ecdh_tmp = EC_KEY_dup(cert->ecdh_tmp); - if (ret->ecdh_tmp == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_EC_LIB); - goto err; - } - } - ret->ecdh_tmp_cb = cert->ecdh_tmp_cb; - ret->ecdh_tmp_auto = cert->ecdh_tmp_auto; + ret->key = &ret->pkeys[cert->key - &cert->pkeys[0]]; + /* or ret->key = ret->pkeys + (cert->key - cert->pkeys), if you find that + * more readable */ - for (i = 0; i < SSL_PKEY_NUM; i++) - { - CERT_PKEY *cpk = cert->pkeys + i; - CERT_PKEY *rpk = ret->pkeys + i; - if (cpk->x509 != NULL) - { - rpk->x509 = X509_up_ref(cpk->x509); - } - - if (cpk->privatekey != NULL) - { - rpk->privatekey = EVP_PKEY_dup(cpk->privatekey); - } + ret->mask_k = cert->mask_k; + ret->mask_a = cert->mask_a; - if (cpk->chain) - { - rpk->chain = X509_chain_up_ref(cpk->chain); - if (!rpk->chain) - { - OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_MALLOC_FAILURE); - goto err; - } - } - } - - /* Peer sigalgs set to NULL as we get these from handshake too */ - ret->peer_sigalgs = NULL; - ret->peer_sigalgslen = 0; - /* Configured sigalgs however we copy across */ + if (cert->dh_tmp != NULL) { + ret->dh_tmp = DHparams_dup(cert->dh_tmp); + if (ret->dh_tmp == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_DH_LIB); + goto err; + } + if (cert->dh_tmp->priv_key) { + BIGNUM *b = BN_dup(cert->dh_tmp->priv_key); + if (!b) { + OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_BN_LIB); + goto err; + } + ret->dh_tmp->priv_key = b; + } + if (cert->dh_tmp->pub_key) { + BIGNUM *b = BN_dup(cert->dh_tmp->pub_key); + if (!b) { + OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_BN_LIB); + goto err; + } + ret->dh_tmp->pub_key = b; + } + } + ret->dh_tmp_cb = cert->dh_tmp_cb; - if (cert->conf_sigalgs) - { - ret->conf_sigalgs = OPENSSL_malloc(cert->conf_sigalgslen); - if (!ret->conf_sigalgs) - goto err; - memcpy(ret->conf_sigalgs, cert->conf_sigalgs, - cert->conf_sigalgslen); - ret->conf_sigalgslen = cert->conf_sigalgslen; - } - else - ret->conf_sigalgs = NULL; + if (cert->ecdh_tmp) { + ret->ecdh_tmp = EC_KEY_dup(cert->ecdh_tmp); + if (ret->ecdh_tmp == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_EC_LIB); + goto err; + } + } + ret->ecdh_tmp_cb = cert->ecdh_tmp_cb; + ret->ecdh_tmp_auto = cert->ecdh_tmp_auto; - if (cert->client_sigalgs) - { - ret->client_sigalgs = OPENSSL_malloc(cert->client_sigalgslen); - if (!ret->client_sigalgs) - goto err; - memcpy(ret->client_sigalgs, cert->client_sigalgs, - cert->client_sigalgslen); - ret->client_sigalgslen = cert->client_sigalgslen; - } - else - ret->client_sigalgs = NULL; - /* Shared sigalgs also NULL */ - ret->shared_sigalgs = NULL; - /* Copy any custom client certificate types */ - if (cert->client_certificate_types) - { - ret->client_certificate_types = BUF_memdup( - cert->client_certificate_types, - cert->num_client_certificate_types); - if (!ret->client_certificate_types) - goto err; - ret->num_client_certificate_types = cert->num_client_certificate_types; - } + for (i = 0; i < SSL_PKEY_NUM; i++) { + CERT_PKEY *cpk = cert->pkeys + i; + CERT_PKEY *rpk = ret->pkeys + i; + if (cpk->x509 != NULL) { + rpk->x509 = X509_up_ref(cpk->x509); + } - ret->cert_flags = cert->cert_flags; + if (cpk->privatekey != NULL) { + rpk->privatekey = EVP_PKEY_dup(cpk->privatekey); + } - ret->cert_cb = cert->cert_cb; - ret->cert_cb_arg = cert->cert_cb_arg; + if (cpk->chain) { + rpk->chain = X509_chain_up_ref(cpk->chain); + if (!rpk->chain) { + OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_MALLOC_FAILURE); + goto err; + } + } + } - if (cert->verify_store) - { - CRYPTO_add(&cert->verify_store->references, 1, CRYPTO_LOCK_X509_STORE); - ret->verify_store = cert->verify_store; - } + /* Peer sigalgs set to NULL as we get these from handshake too */ + ret->peer_sigalgs = NULL; + ret->peer_sigalgslen = 0; + /* Configured sigalgs however we copy across */ - if (cert->chain_store) - { - CRYPTO_add(&cert->chain_store->references, 1, CRYPTO_LOCK_X509_STORE); - ret->chain_store = cert->chain_store; - } + if (cert->conf_sigalgs) { + ret->conf_sigalgs = OPENSSL_malloc(cert->conf_sigalgslen); + if (!ret->conf_sigalgs) { + goto err; + } + memcpy(ret->conf_sigalgs, cert->conf_sigalgs, cert->conf_sigalgslen); + ret->conf_sigalgslen = cert->conf_sigalgslen; + } else { + ret->conf_sigalgs = NULL; + } - ret->ciphers_raw = NULL; + if (cert->client_sigalgs) { + ret->client_sigalgs = OPENSSL_malloc(cert->client_sigalgslen); + if (!ret->client_sigalgs) { + goto err; + } + memcpy(ret->client_sigalgs, cert->client_sigalgs, cert->client_sigalgslen); + ret->client_sigalgslen = cert->client_sigalgslen; + } else { + ret->client_sigalgs = NULL; + } + /* Shared sigalgs also NULL */ + ret->shared_sigalgs = NULL; + /* Copy any custom client certificate types */ + if (cert->client_certificate_types) { + ret->client_certificate_types = BUF_memdup( + cert->client_certificate_types, cert->num_client_certificate_types); + if (!ret->client_certificate_types) { + goto err; + } + ret->num_client_certificate_types = cert->num_client_certificate_types; + } - return(ret); - + ret->cert_flags = cert->cert_flags; + + ret->cert_cb = cert->cert_cb; + ret->cert_cb_arg = cert->cert_cb_arg; + + if (cert->verify_store) { + CRYPTO_add(&cert->verify_store->references, 1, CRYPTO_LOCK_X509_STORE); + ret->verify_store = cert->verify_store; + } + + if (cert->chain_store) { + CRYPTO_add(&cert->chain_store->references, 1, CRYPTO_LOCK_X509_STORE); + ret->chain_store = cert->chain_store; + } + + ret->ciphers_raw = NULL; + + return ret; + err: - ssl_cert_free(ret); - return NULL; - } + ssl_cert_free(ret); + return NULL; +} /* Free up and clear all certificates and chains */ +void ssl_cert_clear_certs(CERT *c) { + int i; + if (c == NULL) { + return; + } -void ssl_cert_clear_certs(CERT *c) - { - int i; - if (c == NULL) - return; - for (i = 0; i<SSL_PKEY_NUM; i++) - { - CERT_PKEY *cpk = c->pkeys + i; - if (cpk->x509) - { - X509_free(cpk->x509); - cpk->x509 = NULL; - } - if (cpk->privatekey) - { - EVP_PKEY_free(cpk->privatekey); - cpk->privatekey = NULL; - } - if (cpk->chain) - { - sk_X509_pop_free(cpk->chain, X509_free); - cpk->chain = NULL; - } - } - } + for (i = 0; i < SSL_PKEY_NUM; i++) { + CERT_PKEY *cpk = c->pkeys + i; + if (cpk->x509) { + X509_free(cpk->x509); + cpk->x509 = NULL; + } + if (cpk->privatekey) { + EVP_PKEY_free(cpk->privatekey); + cpk->privatekey = NULL; + } + if (cpk->chain) { + sk_X509_pop_free(cpk->chain, X509_free); + cpk->chain = NULL; + } + } +} -void ssl_cert_free(CERT *c) - { - if(c == NULL) - return; +void ssl_cert_free(CERT *c) { + if (c == NULL) { + return; + } - if (c->dh_tmp) DH_free(c->dh_tmp); - if (c->ecdh_tmp) EC_KEY_free(c->ecdh_tmp); + if (c->dh_tmp) { + DH_free(c->dh_tmp); + } + if (c->ecdh_tmp) { + EC_KEY_free(c->ecdh_tmp); + } - ssl_cert_clear_certs(c); - if (c->peer_sigalgs) - OPENSSL_free(c->peer_sigalgs); - if (c->conf_sigalgs) - OPENSSL_free(c->conf_sigalgs); - if (c->client_sigalgs) - OPENSSL_free(c->client_sigalgs); - if (c->shared_sigalgs) - OPENSSL_free(c->shared_sigalgs); - if (c->client_certificate_types) - OPENSSL_free(c->client_certificate_types); - if (c->verify_store) - X509_STORE_free(c->verify_store); - if (c->chain_store) - X509_STORE_free(c->chain_store); - if (c->ciphers_raw) - OPENSSL_free(c->ciphers_raw); - OPENSSL_free(c); - } + ssl_cert_clear_certs(c); + if (c->peer_sigalgs) { + OPENSSL_free(c->peer_sigalgs); + } + if (c->conf_sigalgs) { + OPENSSL_free(c->conf_sigalgs); + } + if (c->client_sigalgs) { + OPENSSL_free(c->client_sigalgs); + } + if (c->shared_sigalgs) { + OPENSSL_free(c->shared_sigalgs); + } + if (c->client_certificate_types) { + OPENSSL_free(c->client_certificate_types); + } + if (c->verify_store) { + X509_STORE_free(c->verify_store); + } + if (c->chain_store) { + X509_STORE_free(c->chain_store); + } + if (c->ciphers_raw) { + OPENSSL_free(c->ciphers_raw); + } -int ssl_cert_inst(CERT **o) - { - /* Create a CERT if there isn't already one - * (which cannot really happen, as it is initially created in - * SSL_CTX_new; but the earlier code usually allows for that one - * being non-existant, so we follow that behaviour, as it might - * turn out that there actually is a reason for it -- but I'm - * not sure that *all* of the existing code could cope with - * s->cert being NULL, otherwise we could do without the - * initialization in SSL_CTX_new). - */ - - if (o == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl_cert_inst, ERR_R_PASSED_NULL_PARAMETER); - return(0); - } - if (*o == NULL) - { - if ((*o = ssl_cert_new()) == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl_cert_new, ERR_R_MALLOC_FAILURE); - return(0); - } - } - return(1); - } + OPENSSL_free(c); +} -int ssl_cert_set0_chain(CERT *c, STACK_OF(X509) *chain) - { - CERT_PKEY *cpk = c->key; - if (!cpk) - return 0; - if (cpk->chain) - sk_X509_pop_free(cpk->chain, X509_free); - cpk->chain = chain; - return 1; - } +int ssl_cert_inst(CERT **o) { + /* Create a CERT if there isn't already one (which cannot really happen, as + * it is initially created in SSL_CTX_new; but the earlier code usually + * allows for that one being non-existant, so we follow that behaviour, as it + * might turn out that there actually is a reason for it -- but I'm not sure + * that *all* of the existing code could cope with s->cert being NULL, + * otherwise we could do without the initialization in SSL_CTX_new). */ -int ssl_cert_set1_chain(CERT *c, STACK_OF(X509) *chain) - { - STACK_OF(X509) *dchain; - if (!chain) - return ssl_cert_set0_chain(c, NULL); - dchain = X509_chain_up_ref(chain); - if (!dchain) - return 0; - if (!ssl_cert_set0_chain(c, dchain)) - { - sk_X509_pop_free(dchain, X509_free); - return 0; - } - return 1; - } + if (o == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl_cert_inst, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (*o == NULL) { + *o = ssl_cert_new(); + if (*o == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl_cert_new, ERR_R_MALLOC_FAILURE); + return 0; + } + } -int ssl_cert_add0_chain_cert(CERT *c, X509 *x) - { - CERT_PKEY *cpk = c->key; - if (!cpk) - return 0; - if (!cpk->chain) - cpk->chain = sk_X509_new_null(); - if (!cpk->chain || !sk_X509_push(cpk->chain, x)) - return 0; - return 1; - } + return 1; +} -int ssl_cert_add1_chain_cert(CERT *c, X509 *x) - { - if (!ssl_cert_add0_chain_cert(c, x)) - return 0; - X509_up_ref(x); - return 1; - } +int ssl_cert_set0_chain(CERT *c, STACK_OF(X509) * chain) { + CERT_PKEY *cpk = c->key; + if (!cpk) { + return 0; + } + if (cpk->chain) { + sk_X509_pop_free(cpk->chain, X509_free); + } + cpk->chain = chain; + return 1; +} -int ssl_cert_select_current(CERT *c, X509 *x) - { - int i; - if (x == NULL) - return 0; - for (i = 0; i < SSL_PKEY_NUM; i++) - { - if (c->pkeys[i].x509 == x) - { - c->key = &c->pkeys[i]; - return 1; - } - } +int ssl_cert_set1_chain(CERT *c, STACK_OF(X509) * chain) { + STACK_OF(X509) * dchain; + if (!chain) { + return ssl_cert_set0_chain(c, NULL); + } - for (i = 0; i < SSL_PKEY_NUM; i++) - { - if (c->pkeys[i].x509 && !X509_cmp(c->pkeys[i].x509, x)) - { - c->key = &c->pkeys[i]; - return 1; - } - } - return 0; - } + dchain = X509_chain_up_ref(chain); + if (!dchain) { + return 0; + } -void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg), void *arg) - { - c->cert_cb = cb; - c->cert_cb_arg = arg; - } + if (!ssl_cert_set0_chain(c, dchain)) { + sk_X509_pop_free(dchain, X509_free); + return 0; + } -SESS_CERT *ssl_sess_cert_new(void) - { - SESS_CERT *ret; + return 1; +} - ret = OPENSSL_malloc(sizeof *ret); - if (ret == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl_sess_cert_new, ERR_R_MALLOC_FAILURE); - return NULL; - } +int ssl_cert_add0_chain_cert(CERT *c, X509 *x) { + CERT_PKEY *cpk = c->key; + if (!cpk) { + return 0; + } - memset(ret, 0 ,sizeof *ret); - ret->peer_key = &(ret->peer_pkeys[SSL_PKEY_RSA_ENC]); + if (!cpk->chain) { + cpk->chain = sk_X509_new_null(); + } + if (!cpk->chain || !sk_X509_push(cpk->chain, x)) { + return 0; + } - return ret; - } + return 1; +} -void ssl_sess_cert_free(SESS_CERT *sc) - { - int i; +int ssl_cert_add1_chain_cert(CERT *c, X509 *x) { + if (!ssl_cert_add0_chain_cert(c, x)) { + return 0; + } - if (sc == NULL) - return; + X509_up_ref(x); + return 1; +} - if (sc->cert_chain != NULL) - sk_X509_pop_free(sc->cert_chain, X509_free); - for (i = 0; i < SSL_PKEY_NUM; i++) - { - if (sc->peer_pkeys[i].x509 != NULL) - X509_free(sc->peer_pkeys[i].x509); -#if 0 /* We don't have the peer's private key. These lines are just - * here as a reminder that we're still using a not-quite-appropriate - * data structure. */ - if (sc->peer_pkeys[i].privatekey != NULL) - EVP_PKEY_free(sc->peer_pkeys[i].privatekey); -#endif - } +int ssl_cert_select_current(CERT *c, X509 *x) { + int i; + if (x == NULL) { + return 0; + } - if (sc->peer_dh_tmp != NULL) - DH_free(sc->peer_dh_tmp); - if (sc->peer_ecdh_tmp != NULL) - EC_KEY_free(sc->peer_ecdh_tmp); + for (i = 0; i < SSL_PKEY_NUM; i++) { + if (c->pkeys[i].x509 == x) { + c->key = &c->pkeys[i]; + return 1; + } + } - OPENSSL_free(sc); - } + for (i = 0; i < SSL_PKEY_NUM; i++) { + if (c->pkeys[i].x509 && !X509_cmp(c->pkeys[i].x509, x)) { + c->key = &c->pkeys[i]; + return 1; + } + } -int ssl_set_peer_cert_type(SESS_CERT *sc,int type) - { - sc->peer_cert_type = type; - return(1); - } + return 0; +} -int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk) - { - X509 *x; - int i; - X509_STORE *verify_store; - X509_STORE_CTX ctx; +void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg), void *arg) { + c->cert_cb = cb; + c->cert_cb_arg = arg; +} - if (s->cert->verify_store) - verify_store = s->cert->verify_store; - else - verify_store = s->ctx->cert_store; +SESS_CERT *ssl_sess_cert_new(void) { + SESS_CERT *ret; - if ((sk == NULL) || (sk_X509_num(sk) == 0)) - return(0); + ret = OPENSSL_malloc(sizeof *ret); + if (ret == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl_sess_cert_new, ERR_R_MALLOC_FAILURE); + return NULL; + } - x=sk_X509_value(sk,0); - if(!X509_STORE_CTX_init(&ctx,verify_store,x,sk)) - { - OPENSSL_PUT_ERROR(SSL, ssl_verify_cert_chain, ERR_R_X509_LIB); - return(0); - } -#if 0 - if (SSL_get_verify_depth(s) >= 0) - X509_STORE_CTX_set_depth(&ctx, SSL_get_verify_depth(s)); -#endif - X509_STORE_CTX_set_ex_data(&ctx,SSL_get_ex_data_X509_STORE_CTX_idx(),s); + memset(ret, 0, sizeof *ret); + ret->peer_key = &(ret->peer_pkeys[SSL_PKEY_RSA_ENC]); - /* We need to inherit the verify parameters. These can be determined by - * the context: if its a server it will verify SSL client certificates - * or vice versa. - */ + return ret; +} - X509_STORE_CTX_set_default(&ctx, - s->server ? "ssl_client" : "ssl_server"); - /* Anything non-default in "param" should overwrite anything in the - * ctx. - */ - X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(&ctx), s->param); +void ssl_sess_cert_free(SESS_CERT *sc) { + int i; - if (s->verify_callback) - X509_STORE_CTX_set_verify_cb(&ctx, s->verify_callback); + if (sc == NULL) { + return; + } - if (s->ctx->app_verify_callback != NULL) -#if 1 /* new with OpenSSL 0.9.7 */ - i=s->ctx->app_verify_callback(&ctx, s->ctx->app_verify_arg); -#else - i=s->ctx->app_verify_callback(&ctx); /* should pass app_verify_arg */ -#endif - else - { -#ifndef OPENSSL_NO_X509_VERIFY - i=X509_verify_cert(&ctx); -#else - i=0; - ctx.error=X509_V_ERR_APPLICATION_VERIFICATION; - OPENSSL_PUT_ERROR(SSL, ssl_verify_cert_chain, SSL_R_NO_VERIFY_CALLBACK); -#endif - } + if (sc->cert_chain != NULL) { + sk_X509_pop_free(sc->cert_chain, X509_free); + } - s->verify_result=ctx.error; - X509_STORE_CTX_cleanup(&ctx); + for (i = 0; i < SSL_PKEY_NUM; i++) { + if (sc->peer_pkeys[i].x509 != NULL) { + X509_free(sc->peer_pkeys[i].x509); + } + } - return(i); - } + if (sc->peer_dh_tmp != NULL) { + DH_free(sc->peer_dh_tmp); + } + if (sc->peer_ecdh_tmp != NULL) { + EC_KEY_free(sc->peer_ecdh_tmp); + } -static void set_client_CA_list(STACK_OF(X509_NAME) **ca_list,STACK_OF(X509_NAME) *name_list) - { - if (*ca_list != NULL) - sk_X509_NAME_pop_free(*ca_list,X509_NAME_free); + OPENSSL_free(sc); +} - *ca_list=name_list; - } +int ssl_set_peer_cert_type(SESS_CERT *sc, int type) { + sc->peer_cert_type = type; + return 1; +} -STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *sk) - { - size_t i; - STACK_OF(X509_NAME) *ret; - X509_NAME *name; +int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) * sk) { + X509 *x; + int i; + X509_STORE *verify_store; + X509_STORE_CTX ctx; - ret=sk_X509_NAME_new_null(); - for (i=0; i<sk_X509_NAME_num(sk); i++) - { - name=X509_NAME_dup(sk_X509_NAME_value(sk,i)); - if ((name == NULL) || !sk_X509_NAME_push(ret,name)) - { - sk_X509_NAME_pop_free(ret,X509_NAME_free); - return(NULL); - } - } - return(ret); - } + if (s->cert->verify_store) { + verify_store = s->cert->verify_store; + } else { + verify_store = s->ctx->cert_store; + } -void SSL_set_client_CA_list(SSL *s,STACK_OF(X509_NAME) *name_list) - { - set_client_CA_list(&(s->client_CA),name_list); - } + if (sk == NULL || sk_X509_num(sk) == 0) { + return 0; + } -void SSL_CTX_set_client_CA_list(SSL_CTX *ctx,STACK_OF(X509_NAME) *name_list) - { - set_client_CA_list(&(ctx->client_CA),name_list); - } + x = sk_X509_value(sk, 0); + if (!X509_STORE_CTX_init(&ctx, verify_store, x, sk)) { + OPENSSL_PUT_ERROR(SSL, ssl_verify_cert_chain, ERR_R_X509_LIB); + return 0; + } + X509_STORE_CTX_set_ex_data(&ctx, SSL_get_ex_data_X509_STORE_CTX_idx(), s); -STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *ctx) - { - return(ctx->client_CA); - } + /* We need to inherit the verify parameters. These can be determined by the + * context: if its a server it will verify SSL client certificates or vice + * versa. */ + X509_STORE_CTX_set_default(&ctx, s->server ? "ssl_client" : "ssl_server"); -STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s) - { - if (s->server) - { - if (s->client_CA != NULL) - return(s->client_CA); - else - return(s->ctx->client_CA); - } - else - { - if (((s->version>>8) == SSL3_VERSION_MAJOR) && - (s->s3 != NULL)) - return(s->s3->tmp.ca_names); - else - return(NULL); - } - } + /* Anything non-default in "param" should overwrite anything in the ctx. */ + X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(&ctx), s->param); -static int add_client_CA(STACK_OF(X509_NAME) **sk,X509 *x) - { - X509_NAME *name; + if (s->verify_callback) { + X509_STORE_CTX_set_verify_cb(&ctx, s->verify_callback); + } - if (x == NULL) return(0); - if ((*sk == NULL) && ((*sk=sk_X509_NAME_new_null()) == NULL)) - return(0); - - if ((name=X509_NAME_dup(X509_get_subject_name(x))) == NULL) - return(0); + if (s->ctx->app_verify_callback != NULL) { + i = s->ctx->app_verify_callback(&ctx, s->ctx->app_verify_arg); + } else { + i = X509_verify_cert(&ctx); + } - if (!sk_X509_NAME_push(*sk,name)) - { - X509_NAME_free(name); - return(0); - } - return(1); - } + s->verify_result = ctx.error; + X509_STORE_CTX_cleanup(&ctx); -int SSL_add_client_CA(SSL *ssl,X509 *x) - { - return(add_client_CA(&(ssl->client_CA),x)); - } + return i; +} -int SSL_CTX_add_client_CA(SSL_CTX *ctx,X509 *x) - { - return(add_client_CA(&(ctx->client_CA),x)); - } +static void set_client_CA_list(STACK_OF(X509_NAME) * *ca_list, + STACK_OF(X509_NAME) * name_list) { + if (*ca_list != NULL) { + sk_X509_NAME_pop_free(*ca_list, X509_NAME_free); + } -static int xname_cmp(const X509_NAME **a, const X509_NAME **b) - { - return(X509_NAME_cmp(*a,*b)); - } + *ca_list = name_list; +} -#ifndef OPENSSL_NO_STDIO -/*! - * Load CA certs from a file into a ::STACK. Note that it is somewhat misnamed; +STACK_OF(X509_NAME) * SSL_dup_CA_list(STACK_OF(X509_NAME) * sk) { + size_t i; + STACK_OF(X509_NAME) * ret; + X509_NAME *name; + + ret = sk_X509_NAME_new_null(); + for (i = 0; i < sk_X509_NAME_num(sk); i++) { + name = X509_NAME_dup(sk_X509_NAME_value(sk, i)); + if (name == NULL || !sk_X509_NAME_push(ret, name)) { + sk_X509_NAME_pop_free(ret, X509_NAME_free); + return NULL; + } + } + + return ret; +} + +void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) * name_list) { + set_client_CA_list(&(s->client_CA), name_list); +} + +void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) * name_list) { + set_client_CA_list(&(ctx->client_CA), name_list); +} + +STACK_OF(X509_NAME) * SSL_CTX_get_client_CA_list(const SSL_CTX *ctx) { + return ctx->client_CA; +} + +STACK_OF(X509_NAME) * SSL_get_client_CA_list(const SSL *s) { + if (s->server) { + if (s->client_CA != NULL) { + return s->client_CA; + } else { + return s->ctx->client_CA; + } + } else { + if ((s->version >> 8) == SSL3_VERSION_MAJOR && s->s3 != NULL) { + return s->s3->tmp.ca_names; + } else { + return NULL; + } + } +} + +static int add_client_CA(STACK_OF(X509_NAME) * *sk, X509 *x) { + X509_NAME *name; + + if (x == NULL) { + return 0; + } + if (*sk == NULL) { + *sk = sk_X509_NAME_new_null(); + if (*sk == NULL) { + return 0; + } + } + + name = X509_NAME_dup(X509_get_subject_name(x)); + if (name == NULL) { + return 0; + } + + if (!sk_X509_NAME_push(*sk, name)) { + X509_NAME_free(name); + return 0; + } + + return 1; +} + +int SSL_add_client_CA(SSL *ssl, X509 *x) { + return add_client_CA(&(ssl->client_CA), x); +} + +int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x) { + return add_client_CA(&(ctx->client_CA), x); +} + +static int xname_cmp(const X509_NAME **a, const X509_NAME **b) { + return X509_NAME_cmp(*a, *b); +} + +/* Load CA certs from a file into a STACK. Note that it is somewhat misnamed; * it doesn't really have anything to do with clients (except that a common use * for a stack of CAs is to send it to the client). Actually, it doesn't have * much to do with CAs, either, since it will load any old cert. + * * \param file the file containing one or more certs. - * \return a ::STACK containing the certs. - */ -STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file) - { - BIO *in; - X509 *x=NULL; - X509_NAME *xn=NULL; - STACK_OF(X509_NAME) *ret = NULL,*sk; + * \return a ::STACK containing the certs. */ +STACK_OF(X509_NAME) * SSL_load_client_CA_file(const char *file) { + BIO *in; + X509 *x = NULL; + X509_NAME *xn = NULL; + STACK_OF(X509_NAME) *ret = NULL, *sk; - sk=sk_X509_NAME_new(xname_cmp); + sk = sk_X509_NAME_new(xname_cmp); + in = BIO_new(BIO_s_file()); - in=BIO_new(BIO_s_file()); + if (sk == NULL || in == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_load_client_CA_file, ERR_R_MALLOC_FAILURE); + goto err; + } - if ((sk == NULL) || (in == NULL)) - { - OPENSSL_PUT_ERROR(SSL, SSL_load_client_CA_file, ERR_R_MALLOC_FAILURE); - goto err; - } - - if (!BIO_read_filename(in,file)) - goto err; + if (!BIO_read_filename(in, file)) { + goto err; + } - for (;;) - { - if (PEM_read_bio_X509(in,&x,NULL,NULL) == NULL) - break; - if (ret == NULL) - { - ret = sk_X509_NAME_new_null(); - if (ret == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_load_client_CA_file, ERR_R_MALLOC_FAILURE); - goto err; - } - } - if ((xn=X509_get_subject_name(x)) == NULL) goto err; - /* check for duplicates */ - xn=X509_NAME_dup(xn); - if (xn == NULL) goto err; - if (sk_X509_NAME_find(sk, NULL, xn)) - X509_NAME_free(xn); - else - { - sk_X509_NAME_push(sk,xn); - sk_X509_NAME_push(ret,xn); - } - } + for (;;) { + if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL) { + break; + } + if (ret == NULL) { + ret = sk_X509_NAME_new_null(); + if (ret == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_load_client_CA_file, ERR_R_MALLOC_FAILURE); + goto err; + } + } + xn = X509_get_subject_name(x); + if (xn == NULL) { + goto err; + } - if (0) - { -err: - if (ret != NULL) sk_X509_NAME_pop_free(ret,X509_NAME_free); - ret=NULL; - } - if (sk != NULL) sk_X509_NAME_free(sk); - if (in != NULL) BIO_free(in); - if (x != NULL) X509_free(x); - if (ret != NULL) - ERR_clear_error(); - return(ret); - } -#endif + /* check for duplicates */ + xn = X509_NAME_dup(xn); + if (xn == NULL) { + goto err; + } + if (sk_X509_NAME_find(sk, NULL, xn)) { + X509_NAME_free(xn); + } else { + sk_X509_NAME_push(sk, xn); + sk_X509_NAME_push(ret, xn); + } + } -/*! - * Add a file of certs to a stack. + if (0) { + err: + if (ret != NULL) { + sk_X509_NAME_pop_free(ret, X509_NAME_free); + } + ret = NULL; + } + + if (sk != NULL) { + sk_X509_NAME_free(sk); + } + if (in != NULL) { + BIO_free(in); + } + if (x != NULL) { + X509_free(x); + } + if (ret != NULL) { + ERR_clear_error(); + } + return ret; +} + +/* Add a file of certs to a stack. + * * \param stack the stack to add to. * \param file the file to add from. All certs in this file that are not - * already in the stack will be added. + * already in the stack will be added. * \return 1 for success, 0 for failure. Note that in the case of failure some - * certs may have been added to \c stack. - */ + * certs may have been added to \c stack. */ +int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) * stack, + const char *file) { + BIO *in; + X509 *x = NULL; + X509_NAME *xn = NULL; + int ret = 1; + int (*oldcmp)(const X509_NAME **a, const X509_NAME **b); -int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, - const char *file) - { - BIO *in; - X509 *x=NULL; - X509_NAME *xn=NULL; - int ret=1; - int (*oldcmp)(const X509_NAME **a, const X509_NAME **b); - - oldcmp=sk_X509_NAME_set_cmp_func(stack,xname_cmp); - - in=BIO_new(BIO_s_file()); - - if (in == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_add_file_cert_subjects_to_stack, ERR_R_MALLOC_FAILURE); - goto err; - } - - if (!BIO_read_filename(in,file)) - goto err; - - for (;;) - { - if (PEM_read_bio_X509(in,&x,NULL,NULL) == NULL) - break; - if ((xn=X509_get_subject_name(x)) == NULL) goto err; - xn=X509_NAME_dup(xn); - if (xn == NULL) goto err; - if (sk_X509_NAME_find(stack, NULL, xn)) - X509_NAME_free(xn); - else - sk_X509_NAME_push(stack,xn); - } + oldcmp = sk_X509_NAME_set_cmp_func(stack, xname_cmp); + in = BIO_new(BIO_s_file()); - ERR_clear_error(); + if (in == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_add_file_cert_subjects_to_stack, + ERR_R_MALLOC_FAILURE); + goto err; + } - if (0) - { -err: - ret=0; - } - if(in != NULL) - BIO_free(in); - if(x != NULL) - X509_free(x); - - (void)sk_X509_NAME_set_cmp_func(stack,oldcmp); + if (!BIO_read_filename(in, file)) { + goto err; + } - return ret; - } + for (;;) { + if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL) { + break; + } + xn = X509_get_subject_name(x); + if (xn == NULL) { + goto err; + } + xn = X509_NAME_dup(xn); + if (xn == NULL) { + goto err; + } + if (sk_X509_NAME_find(stack, NULL, xn)) { + X509_NAME_free(xn); + } else { + sk_X509_NAME_push(stack, xn); + } + } -/*! - * Add a directory of certs to a stack. + ERR_clear_error(); + + if (0) { + err: + ret = 0; + } + + if (in != NULL) { + BIO_free(in); + } + if (x != NULL) { + X509_free(x); + } + + sk_X509_NAME_set_cmp_func(stack, oldcmp); + + return ret; +} + +/* Add a directory of certs to a stack. + * * \param stack the stack to append to. * \param dir the directory to append from. All files in this directory will be - * examined as potential certs. Any that are acceptable to - * SSL_add_dir_cert_subjects_to_stack() that are not already in the stack will be - * included. + * examined as potential certs. Any that are acceptable to + * SSL_add_dir_cert_subjects_to_stack() that are not already in the stack will + * be included. * \return 1 for success, 0 for failure. Note that in the case of failure some - * certs may have been added to \c stack. - */ + * certs may have been added to \c stack. */ +int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) * stack, + const char *dir) { + OPENSSL_DIR_CTX *d = NULL; + const char *filename; + int ret = 0; -int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, - const char *dir) - { - OPENSSL_DIR_CTX *d = NULL; - const char *filename; - int ret = 0; + CRYPTO_w_lock(CRYPTO_LOCK_READDIR); - CRYPTO_w_lock(CRYPTO_LOCK_READDIR); + /* Note that a side effect is that the CAs will be sorted by name */ + while ((filename = OPENSSL_DIR_read(&d, dir))) { + char buf[1024]; + int r; - /* Note that a side effect is that the CAs will be sorted by name */ + if (strlen(dir) + strlen(filename) + 2 > sizeof(buf)) { + OPENSSL_PUT_ERROR(SSL, SSL_add_dir_cert_subjects_to_stack, + SSL_R_PATH_TOO_LONG); + goto err; + } - while((filename = OPENSSL_DIR_read(&d, dir))) - { - char buf[1024]; - int r; + r = BIO_snprintf(buf, sizeof buf, "%s/%s", dir, filename); + if (r <= 0 || r >= (int)sizeof(buf) || + !SSL_add_file_cert_subjects_to_stack(stack, buf)) { + goto err; + } + } - if(strlen(dir)+strlen(filename)+2 > sizeof buf) - { - OPENSSL_PUT_ERROR(SSL, SSL_add_dir_cert_subjects_to_stack, SSL_R_PATH_TOO_LONG); - goto err; - } + if (errno) { + OPENSSL_PUT_ERROR(SSL, SSL_add_file_cert_subjects_to_stack, ERR_R_SYS_LIB); + ERR_add_error_data(3, "OPENSSL_DIR_read(&ctx, '", dir, "')"); + goto err; + } -#ifdef OPENSSL_SYS_VMS - r = BIO_snprintf(buf,sizeof buf,"%s%s",dir,filename); -#else - r = BIO_snprintf(buf,sizeof buf,"%s/%s",dir,filename); -#endif - if (r <= 0 || r >= (int)sizeof(buf)) - goto err; - if(!SSL_add_file_cert_subjects_to_stack(stack,buf)) - goto err; - } - - if (errno) - { - OPENSSL_PUT_ERROR(SSL, SSL_add_file_cert_subjects_to_stack, ERR_R_SYS_LIB); - ERR_add_error_data(3, "OPENSSL_DIR_read(&ctx, '", dir, "')"); - goto err; - } - - ret = 1; + ret = 1; err: - if (d) OPENSSL_DIR_end(&d); - CRYPTO_w_unlock(CRYPTO_LOCK_READDIR); - return ret; - } + if (d) { + OPENSSL_DIR_end(&d); + } + CRYPTO_w_unlock(CRYPTO_LOCK_READDIR); + return ret; +} /* Add a certificate to a BUF_MEM structure */ +static int ssl_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x) { + int n; + uint8_t *p; -static int ssl_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x) - { - int n; - unsigned char *p; + n = i2d_X509(x, NULL); + if (!BUF_MEM_grow_clean(buf, (int)(n + (*l) + 3))) { + OPENSSL_PUT_ERROR(SSL, ssl_add_cert_to_buf, ERR_R_BUF_LIB); + return 0; + } + p = (uint8_t *)&(buf->data[*l]); + l2n3(n, p); + i2d_X509(x, &p); + *l += n + 3; - n=i2d_X509(x,NULL); - if (!BUF_MEM_grow_clean(buf,(int)(n+(*l)+3))) - { - OPENSSL_PUT_ERROR(SSL, ssl_add_cert_to_buf, ERR_R_BUF_LIB); - return 0; - } - p=(unsigned char *)&(buf->data[*l]); - l2n3(n,p); - i2d_X509(x,&p); - *l+=n+3; - - return 1; - } + return 1; +} /* Add certificate chain to internal SSL BUF_MEM structure. */ -int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l) - { - BUF_MEM *buf = s->init_buf; - int no_chain; - size_t i; +int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l) { + BUF_MEM *buf = s->init_buf; + int no_chain = 0; + size_t i; - X509 *x; - STACK_OF(X509) *extra_certs; - X509_STORE *chain_store; + X509 *x = NULL; + STACK_OF(X509) * extra_certs; + X509_STORE *chain_store; - if (cpk) - x = cpk->x509; - else - x = NULL; + if (cpk) { + x = cpk->x509; + } - if (s->cert->chain_store) - chain_store = s->cert->chain_store; - else - chain_store = s->ctx->cert_store; + if (s->cert->chain_store) { + chain_store = s->cert->chain_store; + } else { + chain_store = s->ctx->cert_store; + } - /* If we have a certificate specific chain use it, else use - * parent ctx. - */ - if (cpk && cpk->chain) - extra_certs = cpk->chain; - else - extra_certs = s->ctx->extra_certs; + /* If we have a certificate specific chain use it, else use parent ctx. */ + if (cpk && cpk->chain) { + extra_certs = cpk->chain; + } else { + extra_certs = s->ctx->extra_certs; + } - if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || extra_certs) - no_chain = 1; - else - no_chain = 0; + if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || extra_certs) { + no_chain = 1; + } - /* TLSv1 sends a chain with nothing in it, instead of an alert */ - if (!BUF_MEM_grow_clean(buf,10)) - { - OPENSSL_PUT_ERROR(SSL, ssl_add_cert_chain, ERR_R_BUF_LIB); - return 0; - } - if (x != NULL) - { - if (no_chain) - { - if (!ssl_add_cert_to_buf(buf, l, x)) - return 0; - } - else - { - X509_STORE_CTX xs_ctx; + /* TLSv1 sends a chain with nothing in it, instead of an alert. */ + if (!BUF_MEM_grow_clean(buf, 10)) { + OPENSSL_PUT_ERROR(SSL, ssl_add_cert_chain, ERR_R_BUF_LIB); + return 0; + } - if (!X509_STORE_CTX_init(&xs_ctx,chain_store,x,NULL)) - { - OPENSSL_PUT_ERROR(SSL, ssl_add_cert_chain, ERR_R_X509_LIB); - return(0); - } - X509_verify_cert(&xs_ctx); - /* Don't leave errors in the queue */ - ERR_clear_error(); - for (i=0; i < sk_X509_num(xs_ctx.chain); i++) - { - x = sk_X509_value(xs_ctx.chain, i); + if (x != NULL) { + if (no_chain) { + if (!ssl_add_cert_to_buf(buf, l, x)) { + return 0; + } + } else { + X509_STORE_CTX xs_ctx; - if (!ssl_add_cert_to_buf(buf, l, x)) - { - X509_STORE_CTX_cleanup(&xs_ctx); - return 0; - } - } - X509_STORE_CTX_cleanup(&xs_ctx); - } - } - for (i=0; i<sk_X509_num(extra_certs); i++) - { - x=sk_X509_value(extra_certs,i); - if (!ssl_add_cert_to_buf(buf, l, x)) - return 0; - } + if (!X509_STORE_CTX_init(&xs_ctx, chain_store, x, NULL)) { + OPENSSL_PUT_ERROR(SSL, ssl_add_cert_chain, ERR_R_X509_LIB); + return 0; + } + X509_verify_cert(&xs_ctx); + /* Don't leave errors in the queue */ + ERR_clear_error(); + for (i = 0; i < sk_X509_num(xs_ctx.chain); i++) { + x = sk_X509_value(xs_ctx.chain, i); - return 1; - } + if (!ssl_add_cert_to_buf(buf, l, x)) { + X509_STORE_CTX_cleanup(&xs_ctx); + return 0; + } + } + X509_STORE_CTX_cleanup(&xs_ctx); + } + } + + for (i = 0; i < sk_X509_num(extra_certs); i++) { + x = sk_X509_value(extra_certs, i); + if (!ssl_add_cert_to_buf(buf, l, x)) { + return 0; + } + } + + return 1; +} /* Build a certificate chain for current certificate */ -int ssl_build_cert_chain(CERT *c, X509_STORE *chain_store, int flags) - { - CERT_PKEY *cpk = c->key; - X509_STORE_CTX xs_ctx; - STACK_OF(X509) *chain = NULL, *untrusted = NULL; - X509 *x; - int i, rv = 0; - unsigned long error; +int ssl_build_cert_chain(CERT *c, X509_STORE *chain_store, int flags) { + CERT_PKEY *cpk = c->key; + X509_STORE_CTX xs_ctx; + STACK_OF(X509) *chain = NULL, *untrusted = NULL; + X509 *x; + int i, rv = 0; + unsigned long error; - if (!cpk->x509) - { - OPENSSL_PUT_ERROR(SSL, ssl_build_cert_chain, SSL_R_NO_CERTIFICATE_SET); - goto err; - } - /* Rearranging and check the chain: add everything to a store */ - if (flags & SSL_BUILD_CHAIN_FLAG_CHECK) - { - size_t j; - chain_store = X509_STORE_new(); - if (!chain_store) - goto err; - for (j = 0; j < sk_X509_num(cpk->chain); j++) - { - x = sk_X509_value(cpk->chain, j); - if (!X509_STORE_add_cert(chain_store, x)) - { - error = ERR_peek_last_error(); - if (ERR_GET_LIB(error) != ERR_LIB_X509 || - ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) - goto err; - ERR_clear_error(); - } - } - /* Add EE cert too: it might be self signed */ - if (!X509_STORE_add_cert(chain_store, cpk->x509)) - { - error = ERR_peek_last_error(); - if (ERR_GET_LIB(error) != ERR_LIB_X509 || - ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) - goto err; - ERR_clear_error(); - } - } - else - { - if (c->chain_store) - chain_store = c->chain_store; + if (!cpk->x509) { + OPENSSL_PUT_ERROR(SSL, ssl_build_cert_chain, SSL_R_NO_CERTIFICATE_SET); + goto err; + } - if (flags & SSL_BUILD_CHAIN_FLAG_UNTRUSTED) - untrusted = cpk->chain; - } + /* Rearranging and check the chain: add everything to a store */ + if (flags & SSL_BUILD_CHAIN_FLAG_CHECK) { + size_t j; + chain_store = X509_STORE_new(); + if (!chain_store) { + goto err; + } - if (!X509_STORE_CTX_init(&xs_ctx, chain_store, cpk->x509, untrusted)) - { - OPENSSL_PUT_ERROR(SSL, ssl_build_cert_chain, ERR_R_X509_LIB); - goto err; - } + for (j = 0; j < sk_X509_num(cpk->chain); j++) { + x = sk_X509_value(cpk->chain, j); + if (!X509_STORE_add_cert(chain_store, x)) { + error = ERR_peek_last_error(); + if (ERR_GET_LIB(error) != ERR_LIB_X509 || + ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) { + goto err; + } + ERR_clear_error(); + } + } - i = X509_verify_cert(&xs_ctx); - if (i <= 0 && flags & SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR) - { - if (flags & SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR) - ERR_clear_error(); - i = 1; - rv = 2; - } - if (i > 0) - chain = X509_STORE_CTX_get1_chain(&xs_ctx); - if (i <= 0) - { - OPENSSL_PUT_ERROR(SSL, ssl_build_cert_chain, SSL_R_CERTIFICATE_VERIFY_FAILED); - i = X509_STORE_CTX_get_error(&xs_ctx); - ERR_add_error_data(2, "Verify error:", - X509_verify_cert_error_string(i)); + /* Add EE cert too: it might be self signed */ + if (!X509_STORE_add_cert(chain_store, cpk->x509)) { + error = ERR_peek_last_error(); + if (ERR_GET_LIB(error) != ERR_LIB_X509 || + ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) { + goto err; + } + ERR_clear_error(); + } + } else { + if (c->chain_store) { + chain_store = c->chain_store; + } - X509_STORE_CTX_cleanup(&xs_ctx); - goto err; - } - X509_STORE_CTX_cleanup(&xs_ctx); - if (cpk->chain) - sk_X509_pop_free(cpk->chain, X509_free); - /* Remove EE certificate from chain */ - x = sk_X509_shift(chain); - X509_free(x); - if (flags & SSL_BUILD_CHAIN_FLAG_NO_ROOT) - { - if (sk_X509_num(chain) > 0) - { - /* See if last cert is self signed */ - x = sk_X509_value(chain, sk_X509_num(chain) - 1); - X509_check_purpose(x, -1, 0); - if (x->ex_flags & EXFLAG_SS) - { - x = sk_X509_pop(chain); - X509_free(x); - } - } - } - cpk->chain = chain; - if (rv == 0) - rv = 1; - err: - if (flags & SSL_BUILD_CHAIN_FLAG_CHECK) - X509_STORE_free(chain_store); + if (flags & SSL_BUILD_CHAIN_FLAG_UNTRUSTED) { + untrusted = cpk->chain; + } + } - return rv; - } + if (!X509_STORE_CTX_init(&xs_ctx, chain_store, cpk->x509, untrusted)) { + OPENSSL_PUT_ERROR(SSL, ssl_build_cert_chain, ERR_R_X509_LIB); + goto err; + } -int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain, int ref) - { - X509_STORE **pstore; - if (chain) - pstore = &c->chain_store; - else - pstore = &c->verify_store; - if (*pstore) - X509_STORE_free(*pstore); - *pstore = store; - if (ref && store) - CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE); - return 1; - } + i = X509_verify_cert(&xs_ctx); + if (i <= 0 && flags & SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR) { + if (flags & SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR) { + ERR_clear_error(); + } + i = 1; + rv = 2; + } + if (i > 0) { + chain = X509_STORE_CTX_get1_chain(&xs_ctx); + } + if (i <= 0) { + OPENSSL_PUT_ERROR(SSL, ssl_build_cert_chain, + SSL_R_CERTIFICATE_VERIFY_FAILED); + i = X509_STORE_CTX_get_error(&xs_ctx); + ERR_add_error_data(2, "Verify error:", X509_verify_cert_error_string(i)); + + X509_STORE_CTX_cleanup(&xs_ctx); + goto err; + } + + X509_STORE_CTX_cleanup(&xs_ctx); + if (cpk->chain) { + sk_X509_pop_free(cpk->chain, X509_free); + } + + /* Remove EE certificate from chain */ + x = sk_X509_shift(chain); + X509_free(x); + if (flags & SSL_BUILD_CHAIN_FLAG_NO_ROOT) { + if (sk_X509_num(chain) > 0) { + /* See if last cert is self signed */ + x = sk_X509_value(chain, sk_X509_num(chain) - 1); + X509_check_purpose(x, -1, 0); + if (x->ex_flags & EXFLAG_SS) { + x = sk_X509_pop(chain); + X509_free(x); + } + } + } + + cpk->chain = chain; + if (rv == 0) + rv = 1; + +err: + if (flags & SSL_BUILD_CHAIN_FLAG_CHECK) { + X509_STORE_free(chain_store); + } + + return rv; +} + +int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain, int ref) { + X509_STORE **pstore; + if (chain) { + pstore = &c->chain_store; + } else { + pstore = &c->verify_store; + } + + if (*pstore) { + X509_STORE_free(*pstore); + } + *pstore = store; + + if (ref && store) { + CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE); + } + return 1; +}
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c index d5039cc..629eb8f 100644 --- a/ssl/ssl_ciph.c +++ b/ssl/ssl_ciph.c
@@ -147,173 +147,183 @@ #include "ssl_locl.h" -struct handshake_digest - { - long mask; - const EVP_MD *(*md_func)(void); - }; -static const struct handshake_digest ssl_handshake_digests[SSL_MAX_DIGEST] = { - { SSL_HANDSHAKE_MAC_MD5, EVP_md5 }, - { SSL_HANDSHAKE_MAC_SHA, EVP_sha1 }, - { SSL_HANDSHAKE_MAC_SHA256, EVP_sha256 }, - { SSL_HANDSHAKE_MAC_SHA384, EVP_sha384 }, +struct handshake_digest { + long mask; + const EVP_MD *(*md_func)(void); }; -#define CIPHER_ADD 1 -#define CIPHER_KILL 2 -#define CIPHER_DEL 3 -#define CIPHER_ORD 4 -#define CIPHER_SPECIAL 5 +static const struct handshake_digest ssl_handshake_digests[SSL_MAX_DIGEST] = { + {SSL_HANDSHAKE_MAC_MD5, EVP_md5}, + {SSL_HANDSHAKE_MAC_SHA, EVP_sha1}, + {SSL_HANDSHAKE_MAC_SHA256, EVP_sha256}, + {SSL_HANDSHAKE_MAC_SHA384, EVP_sha384}, +}; -typedef struct cipher_order_st - { - const SSL_CIPHER *cipher; - int active; - int dead; - int in_group; - struct cipher_order_st *next,*prev; - } CIPHER_ORDER; +#define CIPHER_ADD 1 +#define CIPHER_KILL 2 +#define CIPHER_DEL 3 +#define CIPHER_ORD 4 +#define CIPHER_SPECIAL 5 -static const SSL_CIPHER cipher_aliases[]={ - {0,SSL_TXT_ALL,0, 0,0,0,0,0,0,0,0,0}, +typedef struct cipher_order_st { + const SSL_CIPHER *cipher; + int active; + int dead; + int in_group; + struct cipher_order_st *next, *prev; +} CIPHER_ORDER; - /* "COMPLEMENTOFDEFAULT" (does *not* include ciphersuites not found in ALL!) */ - {0,SSL_TXT_CMPDEF,0, SSL_kEDH|SSL_kEECDH,SSL_aNULL,0,0,0,0,0,0,0}, +static const SSL_CIPHER cipher_aliases[] = + { + {0, SSL_TXT_ALL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - /* key exchange aliases - * (some of those using only a single bit here combine - * multiple key exchange algs according to the RFCs, - * e.g. kEDH combines DHE_DSS and DHE_RSA) */ - {0,SSL_TXT_kRSA,0, SSL_kRSA, 0,0,0,0,0,0,0,0}, + /* "COMPLEMENTOFDEFAULT" (does *not* include ciphersuites not found in + ALL!) */ + {0, SSL_TXT_CMPDEF, 0, SSL_kEDH | SSL_kEECDH, SSL_aNULL, 0, 0, 0, 0, 0, 0, + 0}, - {0,SSL_TXT_kEDH,0, SSL_kEDH, 0,0,0,0,0,0,0,0}, - {0,SSL_TXT_DH,0, SSL_kEDH,0,0,0,0,0,0,0,0}, + /* key exchange aliases + * (some of those using only a single bit here combine + * multiple key exchange algs according to the RFCs, + * e.g. kEDH combines DHE_DSS and DHE_RSA) */ + {0, SSL_TXT_kRSA, 0, SSL_kRSA, 0, 0, 0, 0, 0, 0, 0, 0}, - {0,SSL_TXT_kEECDH,0, SSL_kEECDH,0,0,0,0,0,0,0,0}, - {0,SSL_TXT_ECDH,0, SSL_kEECDH,0,0,0,0,0,0,0,0}, + {0, SSL_TXT_kEDH, 0, SSL_kEDH, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, SSL_TXT_DH, 0, SSL_kEDH, 0, 0, 0, 0, 0, 0, 0, 0}, - {0,SSL_TXT_kPSK,0, SSL_kPSK, 0,0,0,0,0,0,0,0}, + {0, SSL_TXT_kEECDH, 0, SSL_kEECDH, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, SSL_TXT_ECDH, 0, SSL_kEECDH, 0, 0, 0, 0, 0, 0, 0, 0}, - /* server authentication aliases */ - {0,SSL_TXT_aRSA,0, 0,SSL_aRSA, 0,0,0,0,0,0,0}, - {0,SSL_TXT_aNULL,0, 0,SSL_aNULL, 0,0,0,0,0,0,0}, - {0,SSL_TXT_aECDSA,0, 0,SSL_aECDSA,0,0,0,0,0,0,0}, - {0,SSL_TXT_ECDSA,0, 0,SSL_aECDSA, 0,0,0,0,0,0,0}, - {0,SSL_TXT_aPSK,0, 0,SSL_aPSK, 0,0,0,0,0,0,0}, + {0, SSL_TXT_kPSK, 0, SSL_kPSK, 0, 0, 0, 0, 0, 0, 0, 0}, - /* aliases combining key exchange and server authentication */ - {0,SSL_TXT_EDH,0, SSL_kEDH,~SSL_aNULL,0,0,0,0,0,0,0}, - {0,SSL_TXT_EECDH,0, SSL_kEECDH,~SSL_aNULL,0,0,0,0,0,0,0}, - {0,SSL_TXT_RSA,0, SSL_kRSA,SSL_aRSA,0,0,0,0,0,0,0}, - {0,SSL_TXT_ADH,0, SSL_kEDH,SSL_aNULL,0,0,0,0,0,0,0}, - {0,SSL_TXT_AECDH,0, SSL_kEECDH,SSL_aNULL,0,0,0,0,0,0,0}, - {0,SSL_TXT_PSK,0, SSL_kPSK,SSL_aPSK,0,0,0,0,0,0,0}, + /* server authentication aliases */ + {0, SSL_TXT_aRSA, 0, 0, SSL_aRSA, 0, 0, 0, 0, 0, 0, 0}, + {0, SSL_TXT_aNULL, 0, 0, SSL_aNULL, 0, 0, 0, 0, 0, 0, 0}, + {0, SSL_TXT_aECDSA, 0, 0, SSL_aECDSA, 0, 0, 0, 0, 0, 0, 0}, + {0, SSL_TXT_ECDSA, 0, 0, SSL_aECDSA, 0, 0, 0, 0, 0, 0, 0}, + {0, SSL_TXT_aPSK, 0, 0, SSL_aPSK, 0, 0, 0, 0, 0, 0, 0}, + /* aliases combining key exchange and server authentication */ + {0, SSL_TXT_EDH, 0, SSL_kEDH, ~SSL_aNULL, 0, 0, 0, 0, 0, 0, 0}, + {0, SSL_TXT_EECDH, 0, SSL_kEECDH, ~SSL_aNULL, 0, 0, 0, 0, 0, 0, 0}, + {0, SSL_TXT_RSA, 0, SSL_kRSA, SSL_aRSA, 0, 0, 0, 0, 0, 0, 0}, + {0, SSL_TXT_ADH, 0, SSL_kEDH, SSL_aNULL, 0, 0, 0, 0, 0, 0, 0}, + {0, SSL_TXT_AECDH, 0, SSL_kEECDH, SSL_aNULL, 0, 0, 0, 0, 0, 0, 0}, + {0, SSL_TXT_PSK, 0, SSL_kPSK, SSL_aPSK, 0, 0, 0, 0, 0, 0, 0}, - /* symmetric encryption aliases */ - {0,SSL_TXT_3DES,0, 0,0,SSL_3DES, 0,0,0,0,0,0}, - {0,SSL_TXT_RC4,0, 0,0,SSL_RC4, 0,0,0,0,0,0}, - {0,SSL_TXT_AES128,0, 0,0,SSL_AES128|SSL_AES128GCM,0,0,0,0,0,0}, - {0,SSL_TXT_AES256,0, 0,0,SSL_AES256|SSL_AES256GCM,0,0,0,0,0,0}, - {0,SSL_TXT_AES,0, 0,0,SSL_AES,0,0,0,0,0,0}, - {0,SSL_TXT_AES_GCM,0, 0,0,SSL_AES128GCM|SSL_AES256GCM,0,0,0,0,0,0}, - {0,SSL_TXT_CHACHA20 ,0,0,0,SSL_CHACHA20POLY1305,0,0,0,0,0,0}, + /* symmetric encryption aliases */ + {0, SSL_TXT_3DES, 0, 0, 0, SSL_3DES, 0, 0, 0, 0, 0, 0}, + {0, SSL_TXT_RC4, 0, 0, 0, SSL_RC4, 0, 0, 0, 0, 0, 0}, + {0, SSL_TXT_AES128, 0, 0, 0, SSL_AES128 | SSL_AES128GCM, 0, 0, 0, 0, 0, 0}, + {0, SSL_TXT_AES256, 0, 0, 0, SSL_AES256 | SSL_AES256GCM, 0, 0, 0, 0, 0, 0}, + {0, SSL_TXT_AES, 0, 0, 0, SSL_AES, 0, 0, 0, 0, 0, 0}, + {0, SSL_TXT_AES_GCM, 0, 0, 0, SSL_AES128GCM | SSL_AES256GCM, 0, 0, 0, 0, 0, + 0}, + {0, SSL_TXT_CHACHA20, 0, 0, 0, SSL_CHACHA20POLY1305, 0, 0, 0, 0, 0, 0}, - /* MAC aliases */ - {0,SSL_TXT_MD5,0, 0,0,0,SSL_MD5, 0,0,0,0,0}, - {0,SSL_TXT_SHA1,0, 0,0,0,SSL_SHA1, 0,0,0,0,0}, - {0,SSL_TXT_SHA,0, 0,0,0,SSL_SHA1, 0,0,0,0,0}, - {0,SSL_TXT_SHA256,0, 0,0,0,SSL_SHA256, 0,0,0,0,0}, - {0,SSL_TXT_SHA384,0, 0,0,0,SSL_SHA384, 0,0,0,0,0}, + /* MAC aliases */ + {0, SSL_TXT_MD5, 0, 0, 0, 0, SSL_MD5, 0, 0, 0, 0, 0}, + {0, SSL_TXT_SHA1, 0, 0, 0, 0, SSL_SHA1, 0, 0, 0, 0, 0}, + {0, SSL_TXT_SHA, 0, 0, 0, 0, SSL_SHA1, 0, 0, 0, 0, 0}, + {0, SSL_TXT_SHA256, 0, 0, 0, 0, SSL_SHA256, 0, 0, 0, 0, 0}, + {0, SSL_TXT_SHA384, 0, 0, 0, 0, SSL_SHA384, 0, 0, 0, 0, 0}, - /* protocol version aliases */ - {0,SSL_TXT_SSLV3,0, 0,0,0,0,SSL_SSLV3, 0,0,0,0}, - {0,SSL_TXT_TLSV1,0, 0,0,0,0,SSL_TLSV1, 0,0,0,0}, - {0,SSL_TXT_TLSV1_2,0, 0,0,0,0,SSL_TLSV1_2, 0,0,0,0}, + /* protocol version aliases */ + {0, SSL_TXT_SSLV3, 0, 0, 0, 0, 0, SSL_SSLV3, 0, 0, 0, 0}, + {0, SSL_TXT_TLSV1, 0, 0, 0, 0, 0, SSL_TLSV1, 0, 0, 0, 0}, + {0, SSL_TXT_TLSV1_2, 0, 0, 0, 0, 0, SSL_TLSV1_2, 0, 0, 0, 0}, - /* strength classes */ - {0,SSL_TXT_MEDIUM,0, 0,0,0,0,0,SSL_MEDIUM,0,0,0}, - {0,SSL_TXT_HIGH,0, 0,0,0,0,0,SSL_HIGH, 0,0,0}, - /* FIPS 140-2 approved ciphersuite */ - {0,SSL_TXT_FIPS,0, 0,0,0,0,0,SSL_FIPS, 0,0,0}, - }; + /* strength classes */ + {0, SSL_TXT_MEDIUM, 0, 0, 0, 0, 0, 0, SSL_MEDIUM, 0, 0, 0}, + {0, SSL_TXT_HIGH, 0, 0, 0, 0, 0, 0, SSL_HIGH, 0, 0, 0}, + /* FIPS 140-2 approved ciphersuite */ + {0, SSL_TXT_FIPS, 0, 0, 0, 0, 0, 0, SSL_FIPS, 0, 0, 0}, +}; /* ssl_cipher_get_evp_aead sets |*aead| to point to the correct EVP_AEAD object * for |s->cipher|. It returns 1 on success and 0 on error. */ -int ssl_cipher_get_evp_aead(const SSL_SESSION *s, const EVP_AEAD **aead) - { - const SSL_CIPHER *c = s->cipher; +int ssl_cipher_get_evp_aead(const SSL_SESSION *s, const EVP_AEAD **aead) { + const SSL_CIPHER *c = s->cipher; - *aead = NULL; + *aead = NULL; - if (c == NULL) - return 0; - if ((c->algorithm2 & SSL_CIPHER_ALGORITHM2_AEAD) == 0 && - (c->algorithm2 & SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD) == 0) - return 0; + if (c == NULL) { + return 0; + } - switch (c->algorithm_enc) - { - case SSL_AES128GCM: - *aead = EVP_aead_aes_128_gcm(); - return 1; - case SSL_AES256GCM: - *aead = EVP_aead_aes_256_gcm(); - return 1; - case SSL_CHACHA20POLY1305: - *aead = EVP_aead_chacha20_poly1305(); - return 1; - case SSL_RC4: - if (c->algorithm_mac == SSL_MD5) - *aead = EVP_aead_rc4_md5_tls(); - else - return 0; - return 1; - } + if ((c->algorithm2 & SSL_CIPHER_ALGORITHM2_AEAD) == 0 && + (c->algorithm2 & SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD) == 0) { + return 0; + } - return 0; - } + switch (c->algorithm_enc) { + case SSL_AES128GCM: + *aead = EVP_aead_aes_128_gcm(); + return 1; + + case SSL_AES256GCM: + *aead = EVP_aead_aes_256_gcm(); + return 1; + + case SSL_CHACHA20POLY1305: + *aead = EVP_aead_chacha20_poly1305(); + return 1; + + case SSL_RC4: + if (c->algorithm_mac != SSL_MD5) { + return 0; + } + *aead = EVP_aead_rc4_md5_tls(); + return 1; + } + + return 0; +} int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc, - const EVP_MD **md, int *mac_pkey_type, int *mac_secret_size) - { - const SSL_CIPHER *c; + const EVP_MD **md, int *mac_pkey_type, + int *mac_secret_size) { + const SSL_CIPHER *c; - c=s->cipher; - if (c == NULL) return(0); + c = s->cipher; + if (c == NULL || + /* This function doesn't deal with EVP_AEAD. See + * |ssl_cipher_get_aead_evp|. */ + (c->algorithm2 & SSL_CIPHER_ALGORITHM2_AEAD) || + enc == NULL || + md == NULL) { + return 0; + } - /* This function doesn't deal with EVP_AEAD. See - * |ssl_cipher_get_aead_evp|. */ - if (c->algorithm2 & SSL_CIPHER_ALGORITHM2_AEAD) - return(0); + switch (c->algorithm_enc) { + case SSL_3DES: + *enc = EVP_des_ede3_cbc(); + break; - if ((enc == NULL) || (md == NULL)) return(0); + case SSL_RC4: + *enc = EVP_rc4(); + break; - switch (c->algorithm_enc) - { - case SSL_3DES: - *enc = EVP_des_ede3_cbc(); - break; - case SSL_RC4: - *enc = EVP_rc4(); - break; - case SSL_AES128: - *enc = EVP_aes_128_cbc(); - break; - case SSL_AES256: - *enc = EVP_aes_256_cbc(); - break; - default: - return 0; - } + case SSL_AES128: + *enc = EVP_aes_128_cbc(); + break; - if (!ssl_cipher_get_mac(s, md, mac_pkey_type, mac_secret_size)) - return 0; + case SSL_AES256: + *enc = EVP_aes_256_cbc(); + break; - assert(*enc != NULL && *md != NULL); + default: + return 0; + } - /* TODO(fork): enable the stitched cipher modes. */ + if (!ssl_cipher_get_mac(s, md, mac_pkey_type, mac_secret_size)) { + return 0; + } + + assert(*enc != NULL && *md != NULL); + +/* TODO(fork): enable the stitched cipher modes. */ #if 0 if (s->ssl_version>>8 != TLS1_VERSION_MAJOR || s->ssl_version < TLS1_VERSION) @@ -333,1032 +343,1000 @@ *enc = evp, *md = NULL; #endif - return 1; - } + return 1; +} -int ssl_cipher_get_mac(const SSL_SESSION *s, const EVP_MD **md, int *mac_pkey_type, int *mac_secret_size) - { - const SSL_CIPHER *c; +int ssl_cipher_get_mac(const SSL_SESSION *s, const EVP_MD **md, + int *mac_pkey_type, int *mac_secret_size) { + const SSL_CIPHER *c; - c=s->cipher; - if (c == NULL) return(0); + c = s->cipher; + if (c == NULL) { + return 0; + } - switch (c->algorithm_mac) - { - case SSL_MD5: - *md = EVP_md5(); - break; - case SSL_SHA1: - *md = EVP_sha1(); - break; - case SSL_SHA256: - *md = EVP_sha256(); - break; - case SSL_SHA384: - *md = EVP_sha384(); - break; - default: - return 0; - } + switch (c->algorithm_mac) { + case SSL_MD5: + *md = EVP_md5(); + break; - if (mac_pkey_type != NULL) - { - *mac_pkey_type = EVP_PKEY_HMAC; - } - if (mac_secret_size!=NULL) - { - *mac_secret_size = EVP_MD_size(*md); - } - return 1; - } + case SSL_SHA1: + *md = EVP_sha1(); + break; -int ssl_get_handshake_digest(int idx, long *mask, const EVP_MD **md) -{ - if (idx < 0 || idx >= SSL_MAX_DIGEST) - { - return 0; - } - *mask = ssl_handshake_digests[idx].mask; - *md = ssl_handshake_digests[idx].md_func(); - return 1; + case SSL_SHA256: + *md = EVP_sha256(); + break; + + case SSL_SHA384: + *md = EVP_sha384(); + break; + + default: + return 0; + } + + if (mac_pkey_type != NULL) { + *mac_pkey_type = EVP_PKEY_HMAC; + } + if (mac_secret_size != NULL) { + *mac_secret_size = EVP_MD_size(*md); + } + + return 1; +} + +int ssl_get_handshake_digest(int idx, long *mask, const EVP_MD **md) { + if (idx < 0 || idx >= SSL_MAX_DIGEST) { + return 0; + } + *mask = ssl_handshake_digests[idx].mask; + *md = ssl_handshake_digests[idx].md_func(); + return 1; } #define ITEM_SEP(a) \ - (((a) == ':') || ((a) == ' ') || ((a) == ';') || ((a) == ',')) + (((a) == ':') || ((a) == ' ') || ((a) == ';') || ((a) == ',')) static void ll_append_tail(CIPHER_ORDER **head, CIPHER_ORDER *curr, - CIPHER_ORDER **tail) - { - if (curr == *tail) return; - if (curr == *head) - *head=curr->next; - if (curr->prev != NULL) - curr->prev->next=curr->next; - if (curr->next != NULL) - curr->next->prev=curr->prev; - (*tail)->next=curr; - curr->prev= *tail; - curr->next=NULL; - *tail=curr; - } + CIPHER_ORDER **tail) { + if (curr == *tail) { + return; + } + if (curr == *head) { + *head = curr->next; + } + if (curr->prev != NULL) { + curr->prev->next = curr->next; + } + if (curr->next != NULL) { + curr->next->prev = curr->prev; + } + (*tail)->next = curr; + curr->prev = *tail; + curr->next = NULL; + *tail = curr; +} static void ll_append_head(CIPHER_ORDER **head, CIPHER_ORDER *curr, - CIPHER_ORDER **tail) - { - if (curr == *head) return; - if (curr == *tail) - *tail=curr->prev; - if (curr->next != NULL) - curr->next->prev=curr->prev; - if (curr->prev != NULL) - curr->prev->next=curr->next; - (*head)->prev=curr; - curr->next= *head; - curr->prev=NULL; - *head=curr; - } + CIPHER_ORDER **tail) { + if (curr == *head) { + return; + } + if (curr == *tail) { + *tail = curr->prev; + } + if (curr->next != NULL) { + curr->next->prev = curr->prev; + } + if (curr->prev != NULL) { + curr->prev->next = curr->next; + } + (*head)->prev = curr; + curr->next = *head; + curr->prev = NULL; + *head = curr; +} static void ssl_cipher_collect_ciphers(const SSL_PROTOCOL_METHOD *ssl_method, - int num_of_ciphers, - CIPHER_ORDER *co_list, - CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p) - { - int i, co_list_num; - const SSL_CIPHER *c; + int num_of_ciphers, + CIPHER_ORDER *co_list, + CIPHER_ORDER **head_p, + CIPHER_ORDER **tail_p) { + int i, co_list_num; + const SSL_CIPHER *c; - /* - * We have num_of_ciphers descriptions compiled in, depending on the - * method selected (SSLv2 and/or SSLv3, TLSv1 etc). - * These will later be sorted in a linked list with at most num - * entries. - */ + /* We have num_of_ciphers descriptions compiled in, depending on the method + * selected (SSLv2 and/or SSLv3, TLSv1 etc). These will later be sorted in a + * linked list with at most num entries. */ - /* Get the initial list of ciphers */ - co_list_num = 0; /* actual count of ciphers */ - for (i = 0; i < num_of_ciphers; i++) - { - c = ssl_method->get_cipher(i); - /* drop those that use any of that is not available */ - if ((c != NULL) && c->valid) - { - co_list[co_list_num].cipher = c; - co_list[co_list_num].next = NULL; - co_list[co_list_num].prev = NULL; - co_list[co_list_num].active = 0; - co_list[co_list_num].in_group = 0; - co_list_num++; - } - } + /* Get the initial list of ciphers */ + co_list_num = 0; /* actual count of ciphers */ + for (i = 0; i < num_of_ciphers; i++) { + c = ssl_method->get_cipher(i); + /* drop those that use any of that is not available */ + if (c != NULL && c->valid) { + co_list[co_list_num].cipher = c; + co_list[co_list_num].next = NULL; + co_list[co_list_num].prev = NULL; + co_list[co_list_num].active = 0; + co_list[co_list_num].in_group = 0; + co_list_num++; + } + } - /* - * Prepare linked list from list entries - */ - if (co_list_num > 0) - { - co_list[0].prev = NULL; + /* Prepare linked list from list entries. */ + if (co_list_num > 0) { + co_list[0].prev = NULL; - if (co_list_num > 1) - { - co_list[0].next = &co_list[1]; - - for (i = 1; i < co_list_num - 1; i++) - { - co_list[i].prev = &co_list[i - 1]; - co_list[i].next = &co_list[i + 1]; - } + if (co_list_num > 1) { + co_list[0].next = &co_list[1]; - co_list[co_list_num - 1].prev = &co_list[co_list_num - 2]; - } - - co_list[co_list_num - 1].next = NULL; + for (i = 1; i < co_list_num - 1; i++) { + co_list[i].prev = &co_list[i - 1]; + co_list[i].next = &co_list[i + 1]; + } - *head_p = &co_list[0]; - *tail_p = &co_list[co_list_num - 1]; - } - } + co_list[co_list_num - 1].prev = &co_list[co_list_num - 2]; + } + + co_list[co_list_num - 1].next = NULL; + + *head_p = &co_list[0]; + *tail_p = &co_list[co_list_num - 1]; + } +} static void ssl_cipher_collect_aliases(const SSL_CIPHER **ca_list, - int num_of_group_aliases, - CIPHER_ORDER *head) - { - CIPHER_ORDER *ciph_curr; - const SSL_CIPHER **ca_curr; - int i; + int num_of_group_aliases, + CIPHER_ORDER *head) { + CIPHER_ORDER *ciph_curr; + const SSL_CIPHER **ca_curr; + int i; - /* - * First, add the real ciphers as already collected - */ - ciph_curr = head; - ca_curr = ca_list; - while (ciph_curr != NULL) - { - *ca_curr = ciph_curr->cipher; - ca_curr++; - ciph_curr = ciph_curr->next; - } + /* First, add the real ciphers as already collected. */ + ciph_curr = head; + ca_curr = ca_list; + while (ciph_curr != NULL) { + *ca_curr = ciph_curr->cipher; + ca_curr++; + ciph_curr = ciph_curr->next; + } - /* - * Now we add the available ones from the cipher_aliases[] table. - * They represent either one or more algorithms, some of which - * in any affected category must be supported (set in enabled_mask), - * or represent a cipher strength value (will be added in any case because algorithms=0). - */ - for (i = 0; i < num_of_group_aliases; i++) - { - *ca_curr = cipher_aliases + i; - ca_curr++; - } + /* Now we add the available ones from the cipher_aliases[] table. They + * represent either one or more algorithms, some of which in any affected + * category must be supported (set in enabled_mask), or represent a cipher + * strength value (will be added in any case because algorithms=0). */ + for (i = 0; i < num_of_group_aliases; i++) { + *ca_curr = cipher_aliases + i; + ca_curr++; + } - *ca_curr = NULL; /* end of list */ - } + *ca_curr = NULL; /* end of list */ +} -static void ssl_cipher_apply_rule(unsigned long cipher_id, - unsigned long alg_mkey, unsigned long alg_auth, - unsigned long alg_enc, unsigned long alg_mac, - unsigned long alg_ssl, - unsigned long algo_strength, - int rule, int strength_bits, int in_group, - CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p) - { - CIPHER_ORDER *head, *tail, *curr, *next, *last; - const SSL_CIPHER *cp; - int reverse = 0; +static void ssl_cipher_apply_rule( + unsigned long cipher_id, unsigned long alg_mkey, unsigned long alg_auth, + unsigned long alg_enc, unsigned long alg_mac, unsigned long alg_ssl, + unsigned long algo_strength, int rule, int strength_bits, int in_group, + CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p) { + CIPHER_ORDER *head, *tail, *curr, *next, *last; + const SSL_CIPHER *cp; + int reverse = 0; -#ifdef CIPHER_DEBUG - printf("Applying rule %d with %08lx/%08lx/%08lx/%08lx/%08lx %08lx (%d) in_group:%d\n", - rule, alg_mkey, alg_auth, alg_enc, alg_mac, alg_ssl, algo_strength, strength_bits, in_group); -#endif + if (rule == CIPHER_DEL) { + /* needed to maintain sorting between currently deleted ciphers */ + reverse = 1; + } - if (rule == CIPHER_DEL) - reverse = 1; /* needed to maintain sorting between currently deleted ciphers */ + head = *head_p; + tail = *tail_p; - head = *head_p; - tail = *tail_p; + if (reverse) { + next = tail; + last = head; + } else { + next = head; + last = tail; + } - if (reverse) - { - next = tail; - last = head; - } - else - { - next = head; - last = tail; - } + curr = NULL; + for (;;) { + if (curr == last) { + break; + } - curr = NULL; - for (;;) - { - if (curr == last) break; + curr = next; + if (curr == NULL) { + break; + } - curr = next; + next = reverse ? curr->prev : curr->next; + cp = curr->cipher; - if (curr == NULL) break; + /* Selection criteria is either the value of strength_bits + * or the algorithms used. */ + if (strength_bits >= 0) { + if (strength_bits != cp->strength_bits) { + continue; + } + } else { + if ((alg_mkey && !(alg_mkey & cp->algorithm_mkey)) || + (alg_auth && !(alg_auth & cp->algorithm_auth)) || + (alg_enc && !(alg_enc & cp->algorithm_enc)) || + (alg_mac && !(alg_mac & cp->algorithm_mac)) || + (alg_ssl && !(alg_ssl & cp->algorithm_ssl)) || + (algo_strength && !(algo_strength & cp->algo_strength))) { + continue; + } + } - next = reverse ? curr->prev : curr->next; + /* add the cipher if it has not been added yet. */ + if (rule == CIPHER_ADD) { + /* reverse == 0 */ + if (!curr->active) { + ll_append_tail(&head, curr, &tail); + curr->active = 1; + curr->in_group = in_group; + } + } - cp = curr->cipher; + /* Move the added cipher to this location */ + else if (rule == CIPHER_ORD) { + /* reverse == 0 */ + if (curr->active) { + ll_append_tail(&head, curr, &tail); + curr->in_group = 0; + } + } else if (rule == CIPHER_DEL) { + /* reverse == 1 */ + if (curr->active) { + /* most recently deleted ciphersuites get best positions + * for any future CIPHER_ADD (note that the CIPHER_DEL loop + * works in reverse to maintain the order) */ + ll_append_head(&head, curr, &tail); + curr->active = 0; + curr->in_group = 0; + } + } else if (rule == CIPHER_KILL) { + /* reverse == 0 */ + if (head == curr) { + head = curr->next; + } else { + curr->prev->next = curr->next; + } - /* - * Selection criteria is either the value of strength_bits - * or the algorithms used. - */ - if (strength_bits >= 0) - { - if (strength_bits != cp->strength_bits) - continue; - } - else - { -#ifdef CIPHER_DEBUG - printf("\nName: %s:\nAlgo = %08lx/%08lx/%08lx/%08lx/%08lx Algo_strength = %08lx\n", cp->name, cp->algorithm_mkey, cp->algorithm_auth, cp->algorithm_enc, cp->algorithm_mac, cp->algorithm_ssl, cp->algo_strength); -#endif - if (alg_mkey && !(alg_mkey & cp->algorithm_mkey)) - continue; - if (alg_auth && !(alg_auth & cp->algorithm_auth)) - continue; - if (alg_enc && !(alg_enc & cp->algorithm_enc)) - continue; - if (alg_mac && !(alg_mac & cp->algorithm_mac)) - continue; - if (alg_ssl && !(alg_ssl & cp->algorithm_ssl)) - continue; - if (algo_strength && !(algo_strength & cp->algo_strength)) - continue; - } + if (tail == curr) { + tail = curr->prev; + } + curr->active = 0; + if (curr->next != NULL) { + curr->next->prev = curr->prev; + } + if (curr->prev != NULL) { + curr->prev->next = curr->next; + } + curr->next = NULL; + curr->prev = NULL; + } + } -#ifdef CIPHER_DEBUG - printf("Action = %d\n", rule); -#endif - - /* add the cipher if it has not been added yet. */ - if (rule == CIPHER_ADD) - { - /* reverse == 0 */ - if (!curr->active) - { - ll_append_tail(&head, curr, &tail); - curr->active = 1; - curr->in_group = in_group; - } - } - /* Move the added cipher to this location */ - else if (rule == CIPHER_ORD) - { - /* reverse == 0 */ - if (curr->active) - { - ll_append_tail(&head, curr, &tail); - curr->in_group = 0; - } - } - else if (rule == CIPHER_DEL) - { - /* reverse == 1 */ - if (curr->active) - { - /* most recently deleted ciphersuites get best positions - * for any future CIPHER_ADD (note that the CIPHER_DEL loop - * works in reverse to maintain the order) */ - ll_append_head(&head, curr, &tail); - curr->active = 0; - curr->in_group = 0; - } - } - else if (rule == CIPHER_KILL) - { - /* reverse == 0 */ - if (head == curr) - head = curr->next; - else - curr->prev->next = curr->next; - if (tail == curr) - tail = curr->prev; - curr->active = 0; - if (curr->next != NULL) - curr->next->prev = curr->prev; - if (curr->prev != NULL) - curr->prev->next = curr->next; - curr->next = NULL; - curr->prev = NULL; - } - } - - *head_p = head; - *tail_p = tail; - } + *head_p = head; + *tail_p = tail; +} static int ssl_cipher_strength_sort(CIPHER_ORDER **head_p, - CIPHER_ORDER **tail_p) - { - int max_strength_bits, i, *number_uses; - CIPHER_ORDER *curr; + CIPHER_ORDER **tail_p) { + int max_strength_bits, i, *number_uses; + CIPHER_ORDER *curr; - /* - * This routine sorts the ciphers with descending strength. The sorting - * must keep the pre-sorted sequence, so we apply the normal sorting - * routine as '+' movement to the end of the list. - */ - max_strength_bits = 0; - curr = *head_p; - while (curr != NULL) - { - if (curr->active && - (curr->cipher->strength_bits > max_strength_bits)) - max_strength_bits = curr->cipher->strength_bits; - curr = curr->next; - } + /* This routine sorts the ciphers with descending strength. The sorting must + * keep the pre-sorted sequence, so we apply the normal sorting routine as + * '+' movement to the end of the list. */ + max_strength_bits = 0; + curr = *head_p; + while (curr != NULL) { + if (curr->active && curr->cipher->strength_bits > max_strength_bits) { + max_strength_bits = curr->cipher->strength_bits; + } + curr = curr->next; + } - number_uses = OPENSSL_malloc((max_strength_bits + 1) * sizeof(int)); - if (!number_uses) - { - OPENSSL_PUT_ERROR(SSL, ssl_cipher_strength_sort, ERR_R_MALLOC_FAILURE); - return(0); - } - memset(number_uses, 0, (max_strength_bits + 1) * sizeof(int)); + number_uses = OPENSSL_malloc((max_strength_bits + 1) * sizeof(int)); + if (!number_uses) { + OPENSSL_PUT_ERROR(SSL, ssl_cipher_strength_sort, ERR_R_MALLOC_FAILURE); + return 0; + } + memset(number_uses, 0, (max_strength_bits + 1) * sizeof(int)); - /* - * Now find the strength_bits values actually used - */ - curr = *head_p; - while (curr != NULL) - { - if (curr->active) - number_uses[curr->cipher->strength_bits]++; - curr = curr->next; - } - /* - * Go through the list of used strength_bits values in descending - * order. - */ - for (i = max_strength_bits; i >= 0; i--) - if (number_uses[i] > 0) - ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ORD, i, 0, head_p, tail_p); + /* Now find the strength_bits values actually used. */ + curr = *head_p; + while (curr != NULL) { + if (curr->active) { + number_uses[curr->cipher->strength_bits]++; + } + curr = curr->next; + } - OPENSSL_free(number_uses); - return(1); - } + /* Go through the list of used strength_bits values in descending order. */ + for (i = max_strength_bits; i >= 0; i--) { + if (number_uses[i] > 0) { + ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ORD, i, 0, head_p, + tail_p); + } + } + + OPENSSL_free(number_uses); + return 1; +} static int ssl_cipher_process_rulestr(const char *rule_str, - CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p, - const SSL_CIPHER **ca_list) - { - unsigned long alg_mkey, alg_auth, alg_enc, alg_mac, alg_ssl, algo_strength; - const char *l, *buf; - int j, multi, found, rule, retval, ok, buflen, in_group = 0, - has_group = 0; - unsigned long cipher_id = 0; - char ch; + CIPHER_ORDER **head_p, + CIPHER_ORDER **tail_p, + const SSL_CIPHER **ca_list) { + unsigned long alg_mkey, alg_auth, alg_enc, alg_mac, alg_ssl, algo_strength; + const char *l, *buf; + int j, multi, found, rule, retval, ok, buflen, in_group = 0, has_group = 0; + unsigned long cipher_id = 0; + char ch; - retval = 1; - l = rule_str; - for (;;) - { - ch = *l; + retval = 1; + l = rule_str; + for (;;) { + ch = *l; - if (ch == '\0') - break; /* done */ - if (in_group) - { - if (ch == ']') - { - if (!in_group) - { - OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_UNEXPECTED_GROUP_CLOSE); - retval = found = in_group = 0; - break; - } - if (*tail_p) - (*tail_p)->in_group = 0; - in_group = 0; - l++; - continue; - } - if (ch == '|') - { rule = CIPHER_ADD; l++; continue; } - else if (!(ch >= 'a' && ch <= 'z') && - !(ch >= 'A' && ch <= 'Z') && - !(ch >= '0' && ch <= '9')) - { - OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_UNEXPECTED_OPERATOR_IN_GROUP); - retval = found = in_group = 0; - break; - } - else - rule = CIPHER_ADD; - } - else if (ch == '-') - { rule = CIPHER_DEL; l++; } - else if (ch == '+') - { rule = CIPHER_ORD; l++; } - else if (ch == '!') - { rule = CIPHER_KILL; l++; } - else if (ch == '@') - { rule = CIPHER_SPECIAL; l++; } - else if (ch == '[') - { - if (in_group) - { - OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_NESTED_GROUP); - retval = found = in_group = 0; - break; - } - in_group = 1; - has_group = 1; - l++; - continue; - } - else - { rule = CIPHER_ADD; } + if (ch == '\0') { + break; /* done */ + } - /* If preference groups are enabled, the only legal - * operator is +. Otherwise the in_group bits will get - * mixed up. */ - if (has_group && rule != CIPHER_ADD) - { - OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS); - retval = found = in_group = 0; - break; - } + if (in_group) { + if (ch == ']') { + if (!in_group) { + OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, + SSL_R_UNEXPECTED_GROUP_CLOSE); + retval = found = in_group = 0; + break; + } + if (*tail_p) { + (*tail_p)->in_group = 0; + } + in_group = 0; + l++; + continue; + } - if (ITEM_SEP(ch)) - { - l++; - continue; - } + if (ch == '|') { + rule = CIPHER_ADD; + l++; + continue; + } else if (!(ch >= 'a' && ch <= 'z') && !(ch >= 'A' && ch <= 'Z') && + !(ch >= '0' && ch <= '9')) { + OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, + SSL_R_UNEXPECTED_OPERATOR_IN_GROUP); + retval = found = in_group = 0; + break; + } else { + rule = CIPHER_ADD; + } + } else if (ch == '-') { + rule = CIPHER_DEL; + l++; + } else if (ch == '+') { + rule = CIPHER_ORD; + l++; + } else if (ch == '!') { + rule = CIPHER_KILL; + l++; + } else if (ch == '@') { + rule = CIPHER_SPECIAL; + l++; + } else if (ch == '[') { + if (in_group) { + OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_NESTED_GROUP); + retval = found = in_group = 0; + break; + } + in_group = 1; + has_group = 1; + l++; + continue; + } else { + rule = CIPHER_ADD; + } - alg_mkey = 0; - alg_auth = 0; - alg_enc = 0; - alg_mac = 0; - alg_ssl = 0; - algo_strength = 0; + /* If preference groups are enabled, the only legal operator is +. + * Otherwise the in_group bits will get mixed up. */ + if (has_group && rule != CIPHER_ADD) { + OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, + SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS); + retval = found = in_group = 0; + break; + } - for (;;) - { - ch = *l; - buf = l; - buflen = 0; - while ( ((ch >= 'A') && (ch <= 'Z')) || - ((ch >= '0') && (ch <= '9')) || - ((ch >= 'a') && (ch <= 'z')) || - (ch == '-') || (ch == '.')) - { - ch = *(++l); - buflen++; - } + if (ITEM_SEP(ch)) { + l++; + continue; + } - if (buflen == 0) - { - /* - * We hit something we cannot deal with, - * it is no command or separator nor - * alphanumeric, so we call this an error. - */ - OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_INVALID_COMMAND); - retval = found = in_group = 0; - l++; - break; - } + alg_mkey = 0; + alg_auth = 0; + alg_enc = 0; + alg_mac = 0; + alg_ssl = 0; + algo_strength = 0; - if (rule == CIPHER_SPECIAL) - { - found = 0; /* unused -- avoid compiler warning */ - break; /* special treatment */ - } + for (;;) { + ch = *l; + buf = l; + buflen = 0; + while (((ch >= 'A') && (ch <= 'Z')) || ((ch >= '0') && (ch <= '9')) || + ((ch >= 'a') && (ch <= 'z')) || (ch == '-') || (ch == '.')) { + ch = *(++l); + buflen++; + } - /* check for multi-part specification */ - if (ch == '+') - { - multi=1; - l++; - } - else - multi=0; + if (buflen == 0) { + /* We hit something we cannot deal with, it is no command or separator + * nor alphanumeric, so we call this an error. */ + OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, + SSL_R_INVALID_COMMAND); + retval = found = in_group = 0; + l++; + break; + } - /* - * Now search for the cipher alias in the ca_list. Be careful - * with the strncmp, because the "buflen" limitation - * will make the rule "ADH:SOME" and the cipher - * "ADH-MY-CIPHER" look like a match for buflen=3. - * So additionally check whether the cipher name found - * has the correct length. We can save a strlen() call: - * just checking for the '\0' at the right place is - * sufficient, we have to strncmp() anyway. (We cannot - * use strcmp(), because buf is not '\0' terminated.) - */ - j = found = 0; - cipher_id = 0; - while (ca_list[j]) - { - if (!strncmp(buf, ca_list[j]->name, buflen) && - (ca_list[j]->name[buflen] == '\0')) - { - found = 1; - break; - } - else - j++; - } + if (rule == CIPHER_SPECIAL) { + found = 0; /* unused -- avoid compiler warning */ + break; /* special treatment */ + } - if (!found) - break; /* ignore this entry */ + /* check for multi-part specification */ + if (ch == '+') { + multi = 1; + l++; + } else { + multi = 0; + } - if (ca_list[j]->algorithm_mkey) - { - if (alg_mkey) - { - alg_mkey &= ca_list[j]->algorithm_mkey; - if (!alg_mkey) { found = 0; break; } - } - else - alg_mkey = ca_list[j]->algorithm_mkey; - } + /* Now search for the cipher alias in the ca_list. Be careful with the + * strncmp, because the "buflen" limitation will make the rule "ADH:SOME" + * and the cipher "ADH-MY-CIPHER" look like a match for buflen=3. So + * additionally check whether the cipher name found has the correct + * length. We can save a strlen() call: just checking for the '\0' at the + * right place is sufficient, we have to strncmp() anyway. (We cannot use + * strcmp(), because buf is not '\0' terminated.) */ + j = found = 0; + cipher_id = 0; + while (ca_list[j]) { + if (!strncmp(buf, ca_list[j]->name, buflen) && + (ca_list[j]->name[buflen] == '\0')) { + found = 1; + break; + } else { + j++; + } + } - if (ca_list[j]->algorithm_auth) - { - if (alg_auth) - { - alg_auth &= ca_list[j]->algorithm_auth; - if (!alg_auth) { found = 0; break; } - } - else - alg_auth = ca_list[j]->algorithm_auth; - } - - if (ca_list[j]->algorithm_enc) - { - if (alg_enc) - { - alg_enc &= ca_list[j]->algorithm_enc; - if (!alg_enc) { found = 0; break; } - } - else - alg_enc = ca_list[j]->algorithm_enc; - } - - if (ca_list[j]->algorithm_mac) - { - if (alg_mac) - { - alg_mac &= ca_list[j]->algorithm_mac; - if (!alg_mac) { found = 0; break; } - } - else - alg_mac = ca_list[j]->algorithm_mac; - } - - if (ca_list[j]->algo_strength) - { - if (algo_strength) - { - algo_strength &= ca_list[j]->algo_strength; - if (!algo_strength) { found = 0; break; } - } - else - algo_strength |= ca_list[j]->algo_strength; - } - - if (ca_list[j]->valid) - { - /* explicit ciphersuite found; its protocol version - * does not become part of the search pattern!*/ + if (!found) { + break; /* ignore this entry */ + } - cipher_id = ca_list[j]->id; - } - else - { - /* not an explicit ciphersuite; only in this case, the - * protocol version is considered part of the search pattern */ + if (ca_list[j]->algorithm_mkey) { + if (alg_mkey) { + alg_mkey &= ca_list[j]->algorithm_mkey; + if (!alg_mkey) { + found = 0; + break; + } + } else { + alg_mkey = ca_list[j]->algorithm_mkey; + } + } - if (ca_list[j]->algorithm_ssl) - { - if (alg_ssl) - { - alg_ssl &= ca_list[j]->algorithm_ssl; - if (!alg_ssl) { found = 0; break; } - } - else - alg_ssl = ca_list[j]->algorithm_ssl; - } - } - - if (!multi) break; - } + if (ca_list[j]->algorithm_auth) { + if (alg_auth) { + alg_auth &= ca_list[j]->algorithm_auth; + if (!alg_auth) { + found = 0; + break; + } + } else { + alg_auth = ca_list[j]->algorithm_auth; + } + } - /* - * Ok, we have the rule, now apply it - */ - if (rule == CIPHER_SPECIAL) - { /* special command */ - ok = 0; - if ((buflen == 8) && - !strncmp(buf, "STRENGTH", 8)) - ok = ssl_cipher_strength_sort(head_p, tail_p); - else - OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_INVALID_COMMAND); - if (ok == 0) - retval = 0; - /* - * We do not support any "multi" options - * together with "@", so throw away the - * rest of the command, if any left, until - * end or ':' is found. - */ - while ((*l != '\0') && !ITEM_SEP(*l)) - l++; - } - else if (found) - { - ssl_cipher_apply_rule(cipher_id, - alg_mkey, alg_auth, alg_enc, alg_mac, alg_ssl, algo_strength, - rule, -1, in_group, head_p, tail_p); - } - else - { - while ((*l != '\0') && !ITEM_SEP(*l)) - l++; - } - } + if (ca_list[j]->algorithm_enc) { + if (alg_enc) { + alg_enc &= ca_list[j]->algorithm_enc; + if (!alg_enc) { + found = 0; + break; + } + } else { + alg_enc = ca_list[j]->algorithm_enc; + } + } - if (in_group) - { - OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_INVALID_COMMAND); - retval = 0; - } + if (ca_list[j]->algorithm_mac) { + if (alg_mac) { + alg_mac &= ca_list[j]->algorithm_mac; + if (!alg_mac) { + found = 0; + break; + } + } else { + alg_mac = ca_list[j]->algorithm_mac; + } + } - return(retval); - } + if (ca_list[j]->algo_strength) { + if (algo_strength) { + algo_strength &= ca_list[j]->algo_strength; + if (!algo_strength) { + found = 0; + break; + } + } else { + algo_strength |= ca_list[j]->algo_strength; + } + } + if (ca_list[j]->valid) { + /* explicit ciphersuite found; its protocol version does not become + * part of the search pattern! */ + cipher_id = ca_list[j]->id; + } else { + /* not an explicit ciphersuite; only in this case, the protocol version + * is considered part of the search pattern. */ + if (ca_list[j]->algorithm_ssl) { + if (alg_ssl) { + alg_ssl &= ca_list[j]->algorithm_ssl; + if (!alg_ssl) { + found = 0; + break; + } + } else { + alg_ssl = ca_list[j]->algorithm_ssl; + } + } + } -STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_PROTOCOL_METHOD *ssl_method, - struct ssl_cipher_preference_list_st **cipher_list, - STACK_OF(SSL_CIPHER) **cipher_list_by_id, - const char *rule_str, CERT *c) - { - int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases; - STACK_OF(SSL_CIPHER) *cipherstack = NULL, *tmp_cipher_list = NULL; - const char *rule_p; - CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr; - const SSL_CIPHER **ca_list = NULL; - unsigned char *in_group_flags = NULL; - unsigned int num_in_group_flags = 0; - struct ssl_cipher_preference_list_st *pref_list = NULL; + if (!multi) { + break; + } + } - /* - * Return with error if nothing to do. - */ - if (rule_str == NULL || cipher_list == NULL) - return NULL; + /* Ok, we have the rule, now apply it. */ + if (rule == CIPHER_SPECIAL) { + /* special command */ + ok = 0; + if (buflen == 8 && !strncmp(buf, "STRENGTH", 8)) { + ok = ssl_cipher_strength_sort(head_p, tail_p); + } else { + OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, + SSL_R_INVALID_COMMAND); + } - /* - * Now we have to collect the available ciphers from the compiled - * in ciphers. We cannot get more than the number compiled in, so - * it is used for allocation. - */ - num_of_ciphers = ssl_method->num_ciphers(); - co_list = (CIPHER_ORDER *)OPENSSL_malloc(sizeof(CIPHER_ORDER) * num_of_ciphers); - if (co_list == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl_create_cipher_list, ERR_R_MALLOC_FAILURE); - return(NULL); /* Failure */ - } + if (ok == 0) { + retval = 0; + } - ssl_cipher_collect_ciphers(ssl_method, num_of_ciphers, - co_list, &head, &tail); + /* We do not support any "multi" options together with "@", so throw away + * the rest of the command, if any left, until end or ':' is found. */ + while (*l != '\0' && !ITEM_SEP(*l)) { + l++; + } + } else if (found) { + ssl_cipher_apply_rule(cipher_id, alg_mkey, alg_auth, alg_enc, alg_mac, + alg_ssl, algo_strength, rule, -1, in_group, head_p, + tail_p); + } else { + while (*l != '\0' && !ITEM_SEP(*l)) { + l++; + } + } + } + if (in_group) { + OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_INVALID_COMMAND); + retval = 0; + } - /* Now arrange all ciphers by preference: - * TODO(davidben): Compute this order once and copy it. */ + return retval; +} - /* Everything else being equal, prefer ECDHE_ECDSA then ECDHE_RSA over - * other key exchange mechanisms */ - ssl_cipher_apply_rule(0, SSL_kEECDH, SSL_aECDSA, 0, 0, 0, 0, CIPHER_ADD, -1, 0, &head, &tail); - ssl_cipher_apply_rule(0, SSL_kEECDH, 0, 0, 0, 0, 0, CIPHER_ADD, -1, 0, &head, &tail); - ssl_cipher_apply_rule(0, SSL_kEECDH, 0, 0, 0, 0, 0, CIPHER_DEL, -1, 0, &head, &tail); +STACK_OF(SSL_CIPHER) * +ssl_create_cipher_list(const SSL_PROTOCOL_METHOD *ssl_method, + struct ssl_cipher_preference_list_st **cipher_list, + STACK_OF(SSL_CIPHER) * *cipher_list_by_id, + const char *rule_str, CERT *c) { + int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases; + STACK_OF(SSL_CIPHER) *cipherstack = NULL, *tmp_cipher_list = NULL; + const char *rule_p; + CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr; + const SSL_CIPHER **ca_list = NULL; + uint8_t *in_group_flags = NULL; + unsigned int num_in_group_flags = 0; + struct ssl_cipher_preference_list_st *pref_list = NULL; - /* Order the bulk ciphers. First the preferred AEAD ciphers. We prefer - * CHACHA20 unless there is hardware support for fast and constant-time - * AES_GCM. */ - if (EVP_has_aes_hardware()) - { - ssl_cipher_apply_rule(0, 0, 0, SSL_AES256GCM, 0, 0, 0, CIPHER_ADD, -1, 0, &head, &tail); - ssl_cipher_apply_rule(0, 0, 0, SSL_AES128GCM, 0, 0, 0, CIPHER_ADD, -1, 0, &head, &tail); - ssl_cipher_apply_rule(0, 0, 0, SSL_CHACHA20POLY1305, 0, 0, 0, CIPHER_ADD, -1, 0, &head, &tail); - } - else - { - ssl_cipher_apply_rule(0, 0, 0, SSL_CHACHA20POLY1305, 0, 0, 0, CIPHER_ADD, -1, 0, &head, &tail); - ssl_cipher_apply_rule(0, 0, 0, SSL_AES256GCM, 0, 0, 0, CIPHER_ADD, -1, 0, &head, &tail); - ssl_cipher_apply_rule(0, 0, 0, SSL_AES128GCM, 0, 0, 0, CIPHER_ADD, -1, 0, &head, &tail); - } + /* Return with error if nothing to do. */ + if (rule_str == NULL || cipher_list == NULL) { + return NULL; + } - /* Then the legacy non-AEAD ciphers: AES_256_CBC, AES-128_CBC, - * RC4_128_SHA, RC4_128_MD5, 3DES_EDE_CBC_SHA. */ - ssl_cipher_apply_rule(0, 0, 0, SSL_AES256, 0, 0, 0, CIPHER_ADD, -1, 0, &head, &tail); - ssl_cipher_apply_rule(0, 0, 0, SSL_AES128, 0, 0, 0, CIPHER_ADD, -1, 0, &head, &tail); - ssl_cipher_apply_rule(0, 0, 0, SSL_RC4, ~SSL_MD5, 0, 0, CIPHER_ADD, -1, 0, &head, &tail); - ssl_cipher_apply_rule(0, 0, 0, SSL_RC4, SSL_MD5, 0, 0, CIPHER_ADD, -1, 0, &head, &tail); - ssl_cipher_apply_rule(0, 0, 0, SSL_3DES, 0, 0, 0, CIPHER_ADD, -1, 0, &head, &tail); + /* Now we have to collect the available ciphers from the compiled in ciphers. + * We cannot get more than the number compiled in, so it is used for + * allocation. */ + num_of_ciphers = ssl_method->num_ciphers(); + co_list = + (CIPHER_ORDER *)OPENSSL_malloc(sizeof(CIPHER_ORDER) * num_of_ciphers); + if (co_list == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl_create_cipher_list, ERR_R_MALLOC_FAILURE); + return NULL; + } - /* Temporarily enable everything else for sorting */ - ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ADD, -1, 0, &head, &tail); + ssl_cipher_collect_ciphers(ssl_method, num_of_ciphers, co_list, &head, &tail); - /* Move ciphers without forward secrecy to the end. */ - ssl_cipher_apply_rule(0, ~(SSL_kEDH|SSL_kEECDH), 0, 0, 0, 0, 0, CIPHER_ORD, -1, 0, &head, &tail); + /* Now arrange all ciphers by preference: + * TODO(davidben): Compute this order once and copy it. */ - /* Move anonymous ciphers to the end. Usually, these will remain disabled. - * (For applications that allow them, they aren't too bad, but we prefer - * authenticated ciphers.) - * TODO(davidben): Remove them altogether? */ - ssl_cipher_apply_rule(0, 0, SSL_aNULL, 0, 0, 0, 0, CIPHER_ORD, -1, 0, &head, &tail); + /* Everything else being equal, prefer ECDHE_ECDSA then ECDHE_RSA over other + * key exchange mechanisms */ + ssl_cipher_apply_rule(0, SSL_kEECDH, SSL_aECDSA, 0, 0, 0, 0, CIPHER_ADD, -1, + 0, &head, &tail); + ssl_cipher_apply_rule(0, SSL_kEECDH, 0, 0, 0, 0, 0, CIPHER_ADD, -1, 0, &head, + &tail); + ssl_cipher_apply_rule(0, SSL_kEECDH, 0, 0, 0, 0, 0, CIPHER_DEL, -1, 0, &head, + &tail); - /* Now disable everything (maintaining the ordering!) */ - ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_DEL, -1, 0, &head, &tail); + /* Order the bulk ciphers. First the preferred AEAD ciphers. We prefer + * CHACHA20 unless there is hardware support for fast and constant-time + * AES_GCM. */ + if (EVP_has_aes_hardware()) { + ssl_cipher_apply_rule(0, 0, 0, SSL_AES256GCM, 0, 0, 0, CIPHER_ADD, -1, 0, + &head, &tail); + ssl_cipher_apply_rule(0, 0, 0, SSL_AES128GCM, 0, 0, 0, CIPHER_ADD, -1, 0, + &head, &tail); + ssl_cipher_apply_rule(0, 0, 0, SSL_CHACHA20POLY1305, 0, 0, 0, CIPHER_ADD, + -1, 0, &head, &tail); + } else { + ssl_cipher_apply_rule(0, 0, 0, SSL_CHACHA20POLY1305, 0, 0, 0, CIPHER_ADD, + -1, 0, &head, &tail); + ssl_cipher_apply_rule(0, 0, 0, SSL_AES256GCM, 0, 0, 0, CIPHER_ADD, -1, 0, + &head, &tail); + ssl_cipher_apply_rule(0, 0, 0, SSL_AES128GCM, 0, 0, 0, CIPHER_ADD, -1, 0, + &head, &tail); + } - /* - * We also need cipher aliases for selecting based on the rule_str. - * There might be two types of entries in the rule_str: 1) names - * of ciphers themselves 2) aliases for groups of ciphers. - * For 1) we need the available ciphers and for 2) the cipher - * groups of cipher_aliases added together in one list (otherwise - * we would be happy with just the cipher_aliases table). - */ - num_of_group_aliases = sizeof(cipher_aliases) / sizeof(SSL_CIPHER); - num_of_alias_max = num_of_ciphers + num_of_group_aliases + 1; - ca_list = OPENSSL_malloc(sizeof(SSL_CIPHER *) * num_of_alias_max); - if (ca_list == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl_create_cipher_list, ERR_R_MALLOC_FAILURE); - goto err; - } - ssl_cipher_collect_aliases(ca_list, num_of_group_aliases, head); + /* Then the legacy non-AEAD ciphers: AES_256_CBC, AES-128_CBC, RC4_128_SHA, + * RC4_128_MD5, 3DES_EDE_CBC_SHA. */ + ssl_cipher_apply_rule(0, 0, 0, SSL_AES256, 0, 0, 0, CIPHER_ADD, -1, 0, &head, + &tail); + ssl_cipher_apply_rule(0, 0, 0, SSL_AES128, 0, 0, 0, CIPHER_ADD, -1, 0, &head, + &tail); + ssl_cipher_apply_rule(0, 0, 0, SSL_RC4, ~SSL_MD5, 0, 0, CIPHER_ADD, -1, 0, + &head, &tail); + ssl_cipher_apply_rule(0, 0, 0, SSL_RC4, SSL_MD5, 0, 0, CIPHER_ADD, -1, 0, + &head, &tail); + ssl_cipher_apply_rule(0, 0, 0, SSL_3DES, 0, 0, 0, CIPHER_ADD, -1, 0, &head, + &tail); - /* - * If the rule_string begins with DEFAULT, apply the default rule - * before using the (possibly available) additional rules. - */ - ok = 1; - rule_p = rule_str; - if (strncmp(rule_str,"DEFAULT",7) == 0) - { - ok = ssl_cipher_process_rulestr(SSL_DEFAULT_CIPHER_LIST, - &head, &tail, ca_list); - rule_p += 7; - if (*rule_p == ':') - rule_p++; - } + /* Temporarily enable everything else for sorting */ + ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ADD, -1, 0, &head, &tail); - if (ok && (strlen(rule_p) > 0)) - ok = ssl_cipher_process_rulestr(rule_p, &head, &tail, ca_list); + /* Move ciphers without forward secrecy to the end. */ + ssl_cipher_apply_rule(0, ~(SSL_kEDH | SSL_kEECDH), 0, 0, 0, 0, 0, CIPHER_ORD, + -1, 0, &head, &tail); - OPENSSL_free((void *)ca_list); /* Not needed anymore */ + /* Move anonymous ciphers to the end. Usually, these will remain disabled. + * (For applications that allow them, they aren't too bad, but we prefer + * authenticated ciphers.) + * TODO(davidben): Remove them altogether? */ + ssl_cipher_apply_rule(0, 0, SSL_aNULL, 0, 0, 0, 0, CIPHER_ORD, -1, 0, &head, + &tail); - if (!ok) - goto err; - - /* - * Allocate new "cipherstack" for the result, return with error - * if we cannot get one. - */ - if ((cipherstack = sk_SSL_CIPHER_new_null()) == NULL) - goto err; + /* Now disable everything (maintaining the ordering!) */ + ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_DEL, -1, 0, &head, &tail); - in_group_flags = OPENSSL_malloc(num_of_ciphers); - if (!in_group_flags) - goto err; - /* - * The cipher selection for the list is done. The ciphers are added - * to the resulting precedence to the STACK_OF(SSL_CIPHER). - */ - for (curr = head; curr != NULL; curr = curr->next) - { - if (curr->active) - { - sk_SSL_CIPHER_push(cipherstack, curr->cipher); - in_group_flags[num_in_group_flags++] = curr->in_group; -#ifdef CIPHER_DEBUG - printf("<%s>\n",curr->cipher->name); -#endif - } - } - OPENSSL_free(co_list); /* Not needed any longer */ - co_list = NULL; + /* We also need cipher aliases for selecting based on the rule_str. There + * might be two types of entries in the rule_str: 1) names of ciphers + * themselves 2) aliases for groups of ciphers. For 1) we need the available + * ciphers and for 2) the cipher groups of cipher_aliases added together in + * one list (otherwise we would be happy with just the cipher_aliases + * table). */ + num_of_group_aliases = sizeof(cipher_aliases) / sizeof(SSL_CIPHER); + num_of_alias_max = num_of_ciphers + num_of_group_aliases + 1; + ca_list = OPENSSL_malloc(sizeof(SSL_CIPHER *) * num_of_alias_max); + if (ca_list == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl_create_cipher_list, ERR_R_MALLOC_FAILURE); + goto err; + } + ssl_cipher_collect_aliases(ca_list, num_of_group_aliases, head); - tmp_cipher_list = sk_SSL_CIPHER_dup(cipherstack); - if (tmp_cipher_list == NULL) - goto err; - pref_list = OPENSSL_malloc(sizeof(struct ssl_cipher_preference_list_st)); - if (!pref_list) - goto err; - pref_list->ciphers = cipherstack; - pref_list->in_group_flags = OPENSSL_malloc(num_in_group_flags); - if (!pref_list->in_group_flags) - goto err; - memcpy(pref_list->in_group_flags, in_group_flags, num_in_group_flags); - OPENSSL_free(in_group_flags); - in_group_flags = NULL; - if (*cipher_list != NULL) - ssl_cipher_preference_list_free(*cipher_list); - *cipher_list = pref_list; - pref_list = NULL; + /* If the rule_string begins with DEFAULT, apply the default rule before + * using the (possibly available) additional rules. */ + ok = 1; + rule_p = rule_str; + if (strncmp(rule_str, "DEFAULT", 7) == 0) { + ok = ssl_cipher_process_rulestr(SSL_DEFAULT_CIPHER_LIST, &head, &tail, + ca_list); + rule_p += 7; + if (*rule_p == ':') { + rule_p++; + } + } - if (cipher_list_by_id != NULL) - { - if (*cipher_list_by_id != NULL) - sk_SSL_CIPHER_free(*cipher_list_by_id); - *cipher_list_by_id = tmp_cipher_list; - tmp_cipher_list = NULL; - (void)sk_SSL_CIPHER_set_cmp_func(*cipher_list_by_id,ssl_cipher_ptr_id_cmp); + if (ok && strlen(rule_p) > 0) { + ok = ssl_cipher_process_rulestr(rule_p, &head, &tail, ca_list); + } - sk_SSL_CIPHER_sort(*cipher_list_by_id); - } - else - { - sk_SSL_CIPHER_free(tmp_cipher_list); - tmp_cipher_list = NULL; - } + OPENSSL_free(ca_list); /* Not needed anymore */ - return(cipherstack); + if (!ok) { + goto err; + } + + /* Allocate new "cipherstack" for the result, return with error + * if we cannot get one. */ + cipherstack = sk_SSL_CIPHER_new_null(); + if (cipherstack == NULL) { + goto err; + } + + in_group_flags = OPENSSL_malloc(num_of_ciphers); + if (!in_group_flags) { + goto err; + } + + /* The cipher selection for the list is done. The ciphers are added + * to the resulting precedence to the STACK_OF(SSL_CIPHER). */ + for (curr = head; curr != NULL; curr = curr->next) { + if (curr->active) { + sk_SSL_CIPHER_push(cipherstack, curr->cipher); + in_group_flags[num_in_group_flags++] = curr->in_group; + } + } + OPENSSL_free(co_list); /* Not needed any longer */ + co_list = NULL; + + tmp_cipher_list = sk_SSL_CIPHER_dup(cipherstack); + if (tmp_cipher_list == NULL) { + goto err; + } + pref_list = OPENSSL_malloc(sizeof(struct ssl_cipher_preference_list_st)); + if (!pref_list) { + goto err; + } + pref_list->ciphers = cipherstack; + pref_list->in_group_flags = OPENSSL_malloc(num_in_group_flags); + if (!pref_list->in_group_flags) { + goto err; + } + memcpy(pref_list->in_group_flags, in_group_flags, num_in_group_flags); + OPENSSL_free(in_group_flags); + in_group_flags = NULL; + if (*cipher_list != NULL) { + ssl_cipher_preference_list_free(*cipher_list); + } + *cipher_list = pref_list; + pref_list = NULL; + + if (cipher_list_by_id != NULL) { + if (*cipher_list_by_id != NULL) { + sk_SSL_CIPHER_free(*cipher_list_by_id); + } + *cipher_list_by_id = tmp_cipher_list; + tmp_cipher_list = NULL; + sk_SSL_CIPHER_set_cmp_func(*cipher_list_by_id, ssl_cipher_ptr_id_cmp); + + sk_SSL_CIPHER_sort(*cipher_list_by_id); + } else { + sk_SSL_CIPHER_free(tmp_cipher_list); + tmp_cipher_list = NULL; + } + + return cipherstack; err: - if (co_list) - OPENSSL_free(co_list); - if (in_group_flags) - OPENSSL_free(in_group_flags); - if (cipherstack) - sk_SSL_CIPHER_free(cipherstack); - if (tmp_cipher_list) - sk_SSL_CIPHER_free(tmp_cipher_list); - if (pref_list && pref_list->in_group_flags) - OPENSSL_free(pref_list->in_group_flags); - if (pref_list) - OPENSSL_free(pref_list); - return NULL; - } + if (co_list) { + OPENSSL_free(co_list); + } + if (in_group_flags) { + OPENSSL_free(in_group_flags); + } + if (cipherstack) { + sk_SSL_CIPHER_free(cipherstack); + } + if (tmp_cipher_list) { + sk_SSL_CIPHER_free(tmp_cipher_list); + } + if (pref_list && pref_list->in_group_flags) { + OPENSSL_free(pref_list->in_group_flags); + } + if (pref_list) { + OPENSSL_free(pref_list); + } + return NULL; +} -const char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len) - { - const char *ver; - const char *kx,*au,*enc,*mac; - unsigned long alg_mkey,alg_auth,alg_enc,alg_mac,alg_ssl; - static const char *format="%-23s %s Kx=%-8s Au=%-4s Enc=%-9s Mac=%-4s\n"; +const char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, + int len) { + const char *ver; + const char *kx, *au, *enc, *mac; + unsigned long alg_mkey, alg_auth, alg_enc, alg_mac, alg_ssl; + static const char *format = "%-23s %s Kx=%-8s Au=%-4s Enc=%-9s Mac=%-4s\n"; - alg_mkey = cipher->algorithm_mkey; - alg_auth = cipher->algorithm_auth; - alg_enc = cipher->algorithm_enc; - alg_mac = cipher->algorithm_mac; - alg_ssl = cipher->algorithm_ssl; + alg_mkey = cipher->algorithm_mkey; + alg_auth = cipher->algorithm_auth; + alg_enc = cipher->algorithm_enc; + alg_mac = cipher->algorithm_mac; + alg_ssl = cipher->algorithm_ssl; - if (alg_ssl & SSL_SSLV3) - ver="SSLv3"; - else if (alg_ssl & SSL_TLSV1_2) - ver="TLSv1.2"; - else - ver="unknown"; + if (alg_ssl & SSL_SSLV3) { + ver = "SSLv3"; + } else if (alg_ssl & SSL_TLSV1_2) { + ver = "TLSv1.2"; + } else { + ver = "unknown"; + } - switch (alg_mkey) - { - case SSL_kRSA: - kx="RSA"; - break; - case SSL_kEDH: - kx="DH"; - break; - case SSL_kEECDH: - kx="ECDH"; - break; - case SSL_kPSK: - kx="PSK"; - break; - default: - kx="unknown"; - } + switch (alg_mkey) { + case SSL_kRSA: + kx = "RSA"; + break; - switch (alg_auth) - { - case SSL_aRSA: - au="RSA"; - break; - case SSL_aNULL: - au="None"; - break; - case SSL_aECDSA: - au="ECDSA"; - break; - case SSL_aPSK: - au="PSK"; - break; - default: - au="unknown"; - break; - } + case SSL_kEDH: + kx = "DH"; + break; - switch (alg_enc) - { - case SSL_3DES: - enc="3DES(168)"; - break; - case SSL_RC4: - enc="RC4(128)"; - break; - case SSL_AES128: - enc="AES(128)"; - break; - case SSL_AES256: - enc="AES(256)"; - break; - case SSL_AES128GCM: - enc="AESGCM(128)"; - break; - case SSL_AES256GCM: - enc="AESGCM(256)"; - break; - case SSL_CHACHA20POLY1305: - enc="ChaCha20-Poly1305"; - break; - default: - enc="unknown"; - break; - } + case SSL_kEECDH: + kx = "ECDH"; + break; - switch (alg_mac) - { - case SSL_MD5: - mac="MD5"; - break; - case SSL_SHA1: - mac="SHA1"; - break; - case SSL_SHA256: - mac="SHA256"; - break; - case SSL_SHA384: - mac="SHA384"; - break; - case SSL_AEAD: - mac="AEAD"; - break; - default: - mac="unknown"; - break; - } + case SSL_kPSK: + kx = "PSK"; + break; - if (buf == NULL) - { - len=128; - buf=OPENSSL_malloc(len); - if (buf == NULL) return("OPENSSL_malloc Error"); - } - else if (len < 128) - return("Buffer too small"); + default: + kx = "unknown"; + } - BIO_snprintf(buf,len,format,cipher->name,ver,kx,au,enc,mac); - return(buf); - } + switch (alg_auth) { + case SSL_aRSA: + au = "RSA"; + break; -/* Next three functions require non-null cipher */ -int SSL_CIPHER_is_AES(const SSL_CIPHER *c) - { - return (c->algorithm_enc & SSL_AES) != 0; - } + case SSL_aNULL: + au = "None"; + break; -int SSL_CIPHER_has_MD5_HMAC(const SSL_CIPHER *c) - { - return (c->algorithm_mac & SSL_MD5) != 0; - } + case SSL_aECDSA: + au = "ECDSA"; + break; -int SSL_CIPHER_is_AESGCM(const SSL_CIPHER *c) - { - return (c->algorithm_mac & (SSL_AES128GCM|SSL_AES256GCM)) != 0; - } + case SSL_aPSK: + au = "PSK"; + break; -int SSL_CIPHER_is_CHACHA20POLY1305(const SSL_CIPHER *c) - { - return (c->algorithm_enc & SSL_CHACHA20POLY1305) != 0; - } + default: + au = "unknown"; + break; + } -const char *SSL_CIPHER_get_version(const SSL_CIPHER *c) - { - int i; + switch (alg_enc) { + case SSL_3DES: + enc = "3DES(168)"; + break; - if (c == NULL) return("(NONE)"); - i=(int)(c->id>>24L); - if (i == 3) - return("TLSv1/SSLv3"); - else if (i == 2) - return("SSLv2"); - else - return("unknown"); - } + case SSL_RC4: + enc = "RC4(128)"; + break; + + case SSL_AES128: + enc = "AES(128)"; + break; + + case SSL_AES256: + enc = "AES(256)"; + break; + + case SSL_AES128GCM: + enc = "AESGCM(128)"; + break; + + case SSL_AES256GCM: + enc = "AESGCM(256)"; + break; + + case SSL_CHACHA20POLY1305: + enc = "ChaCha20-Poly1305"; + break; + + default: + enc = "unknown"; + break; + } + + switch (alg_mac) { + case SSL_MD5: + mac = "MD5"; + break; + + case SSL_SHA1: + mac = "SHA1"; + break; + + case SSL_SHA256: + mac = "SHA256"; + break; + + case SSL_SHA384: + mac = "SHA384"; + break; + + case SSL_AEAD: + mac = "AEAD"; + break; + + default: + mac = "unknown"; + break; + } + + if (buf == NULL) { + len = 128; + buf = OPENSSL_malloc(len); + if (buf == NULL) + return "OPENSSL_malloc Error"; + } else if (len < 128) { + return "Buffer too small"; + } + + BIO_snprintf(buf, len, format, cipher->name, ver, kx, au, enc, mac); + return buf; +} + +int SSL_CIPHER_is_AES(const SSL_CIPHER *c) { + return (c->algorithm_enc & SSL_AES) != 0; +} + +int SSL_CIPHER_has_MD5_HMAC(const SSL_CIPHER *c) { + return (c->algorithm_mac & SSL_MD5) != 0; +} + +int SSL_CIPHER_is_AESGCM(const SSL_CIPHER *c) { + return (c->algorithm_mac & (SSL_AES128GCM | SSL_AES256GCM)) != 0; +} + +int SSL_CIPHER_is_CHACHA20POLY1305(const SSL_CIPHER *c) { + return (c->algorithm_enc & SSL_CHACHA20POLY1305) != 0; +} + +const char *SSL_CIPHER_get_version(const SSL_CIPHER *c) { + int i; + + if (c == NULL) { + return "(NONE)"; + } + + i = (int)(c->id >> 24L); + if (i == 3) { + return "TLSv1/SSLv3"; + } else if (i == 2) { + return "SSLv2"; + } else { + return "unknown"; + } +} /* return the actual cipher being used */ -const char *SSL_CIPHER_get_name(const SSL_CIPHER *c) - { - if (c != NULL) - return(c->name); - return("(NONE)"); - } +const char *SSL_CIPHER_get_name(const SSL_CIPHER *c) { + if (c != NULL) { + return c->name; + } + + return "(NONE)"; +} const char *SSL_CIPHER_get_kx_name(const SSL_CIPHER *cipher) { if (cipher == NULL) { @@ -1368,6 +1346,7 @@ switch (cipher->algorithm_mkey) { case SSL_kRSA: return SSL_TXT_RSA; + case SSL_kEDH: switch (cipher->algorithm_auth) { case SSL_aRSA: @@ -1377,6 +1356,7 @@ default: return "UNKNOWN"; } + case SSL_kEECDH: switch (cipher->algorithm_auth) { case SSL_aECDSA: @@ -1388,84 +1368,78 @@ default: return "UNKNOWN"; } + default: return "UNKNOWN"; } } /* number of bits for symmetric cipher */ -int SSL_CIPHER_get_bits(const SSL_CIPHER *c, int *alg_bits) - { - int ret=0; +int SSL_CIPHER_get_bits(const SSL_CIPHER *c, int *alg_bits) { + int ret = 0; - if (c != NULL) - { - if (alg_bits != NULL) *alg_bits = c->alg_bits; - ret = c->strength_bits; - } - return(ret); - } + if (c != NULL) { + if (alg_bits != NULL) { + *alg_bits = c->alg_bits; + } + ret = c->strength_bits; + } -unsigned long SSL_CIPHER_get_id(const SSL_CIPHER *c) - { - return c->id; - } + return ret; +} -void *SSL_COMP_get_compression_methods(void) - { - return NULL; - } -int SSL_COMP_add_compression_method(int id, void *cm) - { - return 1; - } +unsigned long SSL_CIPHER_get_id(const SSL_CIPHER *c) { return c->id; } -const char *SSL_COMP_get_name(const void *comp) - { - return NULL; - } +void *SSL_COMP_get_compression_methods(void) { return NULL; } + +int SSL_COMP_add_compression_method(int id, void *cm) { return 1; } + +const char *SSL_COMP_get_name(const void *comp) { return NULL; } /* For a cipher return the index corresponding to the certificate type */ -int ssl_cipher_get_cert_index(const SSL_CIPHER *c) - { - unsigned long alg_a = c->algorithm_auth; +int ssl_cipher_get_cert_index(const SSL_CIPHER *c) { + unsigned long alg_a = c->algorithm_auth; - if (alg_a & SSL_aECDSA) - return SSL_PKEY_ECC; - else if (alg_a & SSL_aRSA) - return SSL_PKEY_RSA_ENC; - return -1; - } + if (alg_a & SSL_aECDSA) { + return SSL_PKEY_ECC; + } else if (alg_a & SSL_aRSA) { + return SSL_PKEY_RSA_ENC; + } -/* ssl_cipher_has_server_public_key returns 1 if |cipher| involves a - * server public key in the key exchange, sent in a server Certificate - * message. Otherwise it returns 0. */ -int ssl_cipher_has_server_public_key(const SSL_CIPHER *cipher) - { - /* Anonymous ciphers do not include a server certificate. */ - if (cipher->algorithm_auth & SSL_aNULL) - return 0; - /* Neither do PSK ciphers, except for RSA_PSK. */ - if ((cipher->algorithm_auth & SSL_aPSK) && - !(cipher->algorithm_mkey & SSL_kRSA)) - return 0; - /* All other ciphers include it. */ - return 1; - } + return -1; +} -/* ssl_cipher_requires_server_key_exchange returns 1 if |cipher| - * requires a ServerKeyExchange message. Otherwise it returns 0. +/* ssl_cipher_has_server_public_key returns 1 if |cipher| involves a server + * public key in the key exchange, sent in a server Certificate message. + * Otherwise it returns 0. */ +int ssl_cipher_has_server_public_key(const SSL_CIPHER *cipher) { + /* Anonymous ciphers do not include a server certificate. */ + if (cipher->algorithm_auth & SSL_aNULL) { + return 0; + } + + /* Neither do PSK ciphers, except for RSA_PSK. */ + if ((cipher->algorithm_auth & SSL_aPSK) && + !(cipher->algorithm_mkey & SSL_kRSA)) { + return 0; + } + + /* All other ciphers include it. */ + return 1; +} + +/* ssl_cipher_requires_server_key_exchange returns 1 if |cipher| requires a + * ServerKeyExchange message. Otherwise it returns 0. * * Unlike ssl_cipher_has_server_public_key, some ciphers take optional - * ServerKeyExchanges. PSK and RSA_PSK only use the ServerKeyExchange - * to communicate a psk_identity_hint, so it is optional. */ -int ssl_cipher_requires_server_key_exchange(const SSL_CIPHER *cipher) - { - /* Ephemeral Diffie-Hellman key exchanges require a - * ServerKeyExchange. */ - if (cipher->algorithm_mkey & SSL_kEDH || - cipher->algorithm_mkey & SSL_kEECDH) - return 1; - /* It is optional in all others. */ - return 0; - } + * ServerKeyExchanges. PSK and RSA_PSK only use the ServerKeyExchange to + * communicate a psk_identity_hint, so it is optional. */ +int ssl_cipher_requires_server_key_exchange(const SSL_CIPHER *cipher) { + /* Ephemeral Diffie-Hellman key exchanges require a ServerKeyExchange. */ + if (cipher->algorithm_mkey & SSL_kEDH || cipher->algorithm_mkey & SSL_kEECDH) { + return 1; + } + + /* It is optional in all others. */ + return 0; +}
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 877b874..5ed3531 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c
@@ -152,1457 +152,1398 @@ #include "ssl_locl.h" -/* Some error codes are special. Ensure the make_errors.go script - * never regresses this. */ -OPENSSL_COMPILE_ASSERT( - SSL_R_TLSV1_ALERT_NO_RENEGOTIATION == - SSL_AD_NO_RENEGOTIATION + SSL_AD_REASON_OFFSET, - ssl_alert_reason_code_mismatch); +/* Some error codes are special. Ensure the make_errors.go script never + * regresses this. */ +OPENSSL_COMPILE_ASSERT(SSL_R_TLSV1_ALERT_NO_RENEGOTIATION == + SSL_AD_NO_RENEGOTIATION + SSL_AD_REASON_OFFSET, + ssl_alert_reason_code_mismatch); -int SSL_clear(SSL *s) - { +int SSL_clear(SSL *s) { + if (s->method == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_clear, SSL_R_NO_METHOD_SPECIFIED); + return 0; + } - if (s->method == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_clear, SSL_R_NO_METHOD_SPECIFIED); - return(0); - } + if (ssl_clear_bad_session(s)) { + SSL_SESSION_free(s->session); + s->session = NULL; + } - if (ssl_clear_bad_session(s)) - { - SSL_SESSION_free(s->session); - s->session=NULL; - } + s->hit = 0; + s->shutdown = 0; - s->hit=0; - s->shutdown=0; + if (s->renegotiate) { + OPENSSL_PUT_ERROR(SSL, SSL_clear, ERR_R_INTERNAL_ERROR); + return 0; + } -#if 0 /* Disabled since version 1.10 of this file (early return not - * needed because SSL_clear is not called when doing renegotiation) */ - /* This is set if we are doing dynamic renegotiation so keep - * the old cipher. It is sort of a SSL_clear_lite :-) */ - if (s->renegotiate) return(1); -#else - if (s->renegotiate) - { - OPENSSL_PUT_ERROR(SSL, SSL_clear, ERR_R_INTERNAL_ERROR); - return 0; - } -#endif + /* SSL_clear may be called before or after the |s| is initialized in either + * accept or connect state. In the latter case, SSL_clear should preserve the + * half and reset |s->state| accordingly. */ + if (s->handshake_func != NULL) { + if (s->server) { + SSL_set_accept_state(s); + } else { + SSL_set_connect_state(s); + } + } else { + assert(s->state == 0); + } - /* SSL_clear may be called before or after the |s| is initialized in - * either accept or connect state. In the latter case, SSL_clear should - * preserve the half and reset |s->state| accordingly. */ - if (s->handshake_func != NULL) - { - if (s->server) - SSL_set_accept_state(s); - else - SSL_set_connect_state(s); - } - else - { - assert(s->state == 0); - } + s->rwstate = SSL_NOTHING; + s->rstate = SSL_ST_READ_HEADER; - s->rwstate=SSL_NOTHING; - s->rstate=SSL_ST_READ_HEADER; -#if 0 - s->read_ahead=s->ctx->read_ahead; -#endif + if (s->init_buf != NULL) { + BUF_MEM_free(s->init_buf); + s->init_buf = NULL; + } - if (s->init_buf != NULL) - { - BUF_MEM_free(s->init_buf); - s->init_buf=NULL; - } + ssl_clear_cipher_ctx(s); + ssl_clear_hash_ctx(&s->read_hash); + ssl_clear_hash_ctx(&s->write_hash); - ssl_clear_cipher_ctx(s); - ssl_clear_hash_ctx(&s->read_hash); - ssl_clear_hash_ctx(&s->write_hash); + s->method->ssl_clear(s); + s->client_version = s->version; - s->method->ssl_clear(s); - s->client_version=s->version; - return(1); - } + return 1; +} -SSL *SSL_new(SSL_CTX *ctx) - { - SSL *s; +SSL *SSL_new(SSL_CTX *ctx) { + SSL *s; - if (ctx == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_new, SSL_R_NULL_SSL_CTX); - return(NULL); - } - if (ctx->method == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_new, SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION); - return(NULL); - } + if (ctx == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_new, SSL_R_NULL_SSL_CTX); + return NULL; + } + if (ctx->method == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_new, SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION); + return NULL; + } - s=(SSL *)OPENSSL_malloc(sizeof(SSL)); - if (s == NULL) goto err; - memset(s,0,sizeof(SSL)); + s = (SSL *)OPENSSL_malloc(sizeof(SSL)); + if (s == NULL) { + goto err; + } + memset(s, 0, sizeof(SSL)); - s->min_version = ctx->min_version; - s->max_version = ctx->max_version; + s->min_version = ctx->min_version; + s->max_version = ctx->max_version; - s->options=ctx->options; - s->mode=ctx->mode; - s->max_cert_list=ctx->max_cert_list; + s->options = ctx->options; + s->mode = ctx->mode; + s->max_cert_list = ctx->max_cert_list; - if (ctx->cert != NULL) - { - /* Earlier library versions used to copy the pointer to - * the CERT, not its contents; only when setting new - * parameters for the per-SSL copy, ssl_cert_new would be - * called (and the direct reference to the per-SSL_CTX - * settings would be lost, but those still were indirectly - * accessed for various purposes, and for that reason they - * used to be known as s->ctx->default_cert). - * Now we don't look at the SSL_CTX's CERT after having - * duplicated it once. */ + if (ctx->cert != NULL) { + /* Earlier library versions used to copy the pointer to the CERT, not its + * contents; only when setting new parameters for the per-SSL copy, + * ssl_cert_new would be called (and the direct reference to the + * per-SSL_CTX settings would be lost, but those still were indirectly + * accessed for various purposes, and for that reason they used to be known + * as s->ctx->default_cert). Now we don't look at the SSL_CTX's CERT after + * having duplicated it once. */ - s->cert = ssl_cert_dup(ctx->cert); - if (s->cert == NULL) - goto err; - } - else - s->cert=NULL; /* Cannot really happen (see SSL_CTX_new) */ + s->cert = ssl_cert_dup(ctx->cert); + if (s->cert == NULL) { + goto err; + } + } else { + s->cert = NULL; /* Cannot really happen (see SSL_CTX_new) */ + } - s->read_ahead=ctx->read_ahead; - s->msg_callback=ctx->msg_callback; - s->msg_callback_arg=ctx->msg_callback_arg; - s->verify_mode=ctx->verify_mode; -#if 0 - s->verify_depth=ctx->verify_depth; -#endif - s->sid_ctx_length=ctx->sid_ctx_length; - assert(s->sid_ctx_length <= sizeof s->sid_ctx); - memcpy(&s->sid_ctx,&ctx->sid_ctx,sizeof(s->sid_ctx)); - s->verify_callback=ctx->default_verify_callback; - s->generate_session_id=ctx->generate_session_id; + s->read_ahead = ctx->read_ahead; + s->msg_callback = ctx->msg_callback; + s->msg_callback_arg = ctx->msg_callback_arg; + s->verify_mode = ctx->verify_mode; + s->sid_ctx_length = ctx->sid_ctx_length; + assert(s->sid_ctx_length <= sizeof s->sid_ctx); + memcpy(&s->sid_ctx, &ctx->sid_ctx, sizeof(s->sid_ctx)); + s->verify_callback = ctx->default_verify_callback; + s->generate_session_id = ctx->generate_session_id; - s->param = X509_VERIFY_PARAM_new(); - if (!s->param) - goto err; - X509_VERIFY_PARAM_inherit(s->param, ctx->param); -#if 0 - s->purpose = ctx->purpose; - s->trust = ctx->trust; -#endif - s->quiet_shutdown=ctx->quiet_shutdown; - s->max_send_fragment = ctx->max_send_fragment; + s->param = X509_VERIFY_PARAM_new(); + if (!s->param) { + goto err; + } + X509_VERIFY_PARAM_inherit(s->param, ctx->param); + s->quiet_shutdown = ctx->quiet_shutdown; + s->max_send_fragment = ctx->max_send_fragment; - CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX); - s->ctx=ctx; - s->tlsext_debug_cb = 0; - s->tlsext_debug_arg = NULL; - s->tlsext_ticket_expected = 0; - CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX); - s->initial_ctx=ctx; - if (ctx->tlsext_ecpointformatlist) - { - s->tlsext_ecpointformatlist = - BUF_memdup(ctx->tlsext_ecpointformatlist, - ctx->tlsext_ecpointformatlist_length); - if (!s->tlsext_ecpointformatlist) - goto err; - s->tlsext_ecpointformatlist_length = - ctx->tlsext_ecpointformatlist_length; - } - if (ctx->tlsext_ellipticcurvelist) - { - s->tlsext_ellipticcurvelist = - BUF_memdup(ctx->tlsext_ellipticcurvelist, - ctx->tlsext_ellipticcurvelist_length * 2); - if (!s->tlsext_ellipticcurvelist) - goto err; - s->tlsext_ellipticcurvelist_length = - ctx->tlsext_ellipticcurvelist_length; - } - s->next_proto_negotiated = NULL; + CRYPTO_add(&ctx->references, 1, CRYPTO_LOCK_SSL_CTX); + s->ctx = ctx; + s->tlsext_debug_cb = 0; + s->tlsext_debug_arg = NULL; + s->tlsext_ticket_expected = 0; + CRYPTO_add(&ctx->references, 1, CRYPTO_LOCK_SSL_CTX); + s->initial_ctx = ctx; + if (ctx->tlsext_ecpointformatlist) { + s->tlsext_ecpointformatlist = BUF_memdup( + ctx->tlsext_ecpointformatlist, ctx->tlsext_ecpointformatlist_length); + if (!s->tlsext_ecpointformatlist) { + goto err; + } + s->tlsext_ecpointformatlist_length = ctx->tlsext_ecpointformatlist_length; + } - if (s->ctx->alpn_client_proto_list) - { - s->alpn_client_proto_list = BUF_memdup( - s->ctx->alpn_client_proto_list, - s->ctx->alpn_client_proto_list_len); - if (s->alpn_client_proto_list == NULL) - goto err; - s->alpn_client_proto_list_len = s->ctx->alpn_client_proto_list_len; - } + if (ctx->tlsext_ellipticcurvelist) { + s->tlsext_ellipticcurvelist = + BUF_memdup(ctx->tlsext_ellipticcurvelist, + ctx->tlsext_ellipticcurvelist_length * 2); + if (!s->tlsext_ellipticcurvelist) { + goto err; + } + s->tlsext_ellipticcurvelist_length = ctx->tlsext_ellipticcurvelist_length; + } + s->next_proto_negotiated = NULL; - s->verify_result=X509_V_OK; + if (s->ctx->alpn_client_proto_list) { + s->alpn_client_proto_list = BUF_memdup(s->ctx->alpn_client_proto_list, + s->ctx->alpn_client_proto_list_len); + if (s->alpn_client_proto_list == NULL) { + goto err; + } + s->alpn_client_proto_list_len = s->ctx->alpn_client_proto_list_len; + } - s->method=ctx->method; + s->verify_result = X509_V_OK; + s->method = ctx->method; - if (!s->method->ssl_new(s)) - goto err; - s->enc_method = ssl3_get_enc_method(s->version); - assert(s->enc_method != NULL); + if (!s->method->ssl_new(s)) { + goto err; + } + s->enc_method = ssl3_get_enc_method(s->version); + assert(s->enc_method != NULL); - s->references=1; + s->references = 1; - SSL_clear(s); + SSL_clear(s); - CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data); + CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data); - s->psk_identity_hint = NULL; - if (ctx->psk_identity_hint) - { - s->psk_identity_hint = BUF_strdup(ctx->psk_identity_hint); - if (s->psk_identity_hint == NULL) - goto err; - } - s->psk_client_callback=ctx->psk_client_callback; - s->psk_server_callback=ctx->psk_server_callback; + s->psk_identity_hint = NULL; + if (ctx->psk_identity_hint) { + s->psk_identity_hint = BUF_strdup(ctx->psk_identity_hint); + if (s->psk_identity_hint == NULL) { + goto err; + } + } + s->psk_client_callback = ctx->psk_client_callback; + s->psk_server_callback = ctx->psk_server_callback; - s->signed_cert_timestamps_enabled = s->ctx->signed_cert_timestamps_enabled; - s->ocsp_stapling_enabled = s->ctx->ocsp_stapling_enabled; + s->signed_cert_timestamps_enabled = s->ctx->signed_cert_timestamps_enabled; + s->ocsp_stapling_enabled = s->ctx->ocsp_stapling_enabled; - return(s); + return s; + err: - if (s != NULL) - { - if (s->cert != NULL) - ssl_cert_free(s->cert); - if (s->ctx != NULL) - SSL_CTX_free(s->ctx); /* decrement reference count */ - OPENSSL_free(s); - } - OPENSSL_PUT_ERROR(SSL, SSL_new, ERR_R_MALLOC_FAILURE); - return(NULL); - } - -int SSL_CTX_set_session_id_context(SSL_CTX *ctx,const unsigned char *sid_ctx, - unsigned int sid_ctx_len) - { - if(sid_ctx_len > sizeof ctx->sid_ctx) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_set_session_id_context, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG); - return 0; - } - ctx->sid_ctx_length=sid_ctx_len; - memcpy(ctx->sid_ctx,sid_ctx,sid_ctx_len); - - return 1; + if (s != NULL) { + if (s->cert != NULL) { + ssl_cert_free(s->cert); } - -int SSL_set_session_id_context(SSL *ssl,const unsigned char *sid_ctx, - unsigned int sid_ctx_len) - { - if(sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) - { - OPENSSL_PUT_ERROR(SSL, SSL_set_session_id_context, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG); - return 0; - } - ssl->sid_ctx_length=sid_ctx_len; - memcpy(ssl->sid_ctx,sid_ctx,sid_ctx_len); - - return 1; + if (s->ctx != NULL) { + SSL_CTX_free(s->ctx); } + OPENSSL_free(s); + } + OPENSSL_PUT_ERROR(SSL, SSL_new, ERR_R_MALLOC_FAILURE); -int SSL_CTX_set_generate_session_id(SSL_CTX *ctx, GEN_SESSION_CB cb) - { - CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); - ctx->generate_session_id = cb; - CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); - return 1; - } + return NULL; +} -int SSL_set_generate_session_id(SSL *ssl, GEN_SESSION_CB cb) - { - CRYPTO_w_lock(CRYPTO_LOCK_SSL); - ssl->generate_session_id = cb; - CRYPTO_w_unlock(CRYPTO_LOCK_SSL); - return 1; - } +int SSL_CTX_set_session_id_context(SSL_CTX *ctx, const uint8_t *sid_ctx, + unsigned int sid_ctx_len) { + if (sid_ctx_len > sizeof ctx->sid_ctx) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_set_session_id_context, + SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG); + return 0; + } + ctx->sid_ctx_length = sid_ctx_len; + memcpy(ctx->sid_ctx, sid_ctx, sid_ctx_len); -int SSL_has_matching_session_id(const SSL *ssl, const unsigned char *id, - unsigned int id_len) - { - /* A quick examination of SSL_SESSION_hash and SSL_SESSION_cmp shows how - * we can "construct" a session to give us the desired check - ie. to - * find if there's a session in the hash table that would conflict with - * any new session built out of this id/id_len and the ssl_version in - * use by this SSL. */ - SSL_SESSION r, *p; + return 1; +} - if(id_len > sizeof r.session_id) - return 0; +int SSL_set_session_id_context(SSL *ssl, const uint8_t *sid_ctx, + unsigned int sid_ctx_len) { + if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) { + OPENSSL_PUT_ERROR(SSL, SSL_set_session_id_context, + SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG); + return 0; + } + ssl->sid_ctx_length = sid_ctx_len; + memcpy(ssl->sid_ctx, sid_ctx, sid_ctx_len); - r.ssl_version = ssl->version; - r.session_id_length = id_len; - memcpy(r.session_id, id, id_len); + return 1; +} - CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); - p = lh_SSL_SESSION_retrieve(ssl->ctx->sessions, &r); - CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); - return (p != NULL); - } +int SSL_CTX_set_generate_session_id(SSL_CTX *ctx, GEN_SESSION_CB cb) { + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + ctx->generate_session_id = cb; + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); + return 1; +} -int SSL_CTX_set_purpose(SSL_CTX *s, int purpose) - { - return X509_VERIFY_PARAM_set_purpose(s->param, purpose); - } +int SSL_set_generate_session_id(SSL *ssl, GEN_SESSION_CB cb) { + CRYPTO_w_lock(CRYPTO_LOCK_SSL); + ssl->generate_session_id = cb; + CRYPTO_w_unlock(CRYPTO_LOCK_SSL); + return 1; +} -int SSL_set_purpose(SSL *s, int purpose) - { - return X509_VERIFY_PARAM_set_purpose(s->param, purpose); - } +int SSL_has_matching_session_id(const SSL *ssl, const uint8_t *id, + unsigned int id_len) { + /* A quick examination of SSL_SESSION_hash and SSL_SESSION_cmp shows how we + * can "construct" a session to give us the desired check - ie. to find if + * there's a session in the hash table that would conflict with any new + * session built out of this id/id_len and the ssl_version in use by this + * SSL. */ + SSL_SESSION r, *p; -int SSL_CTX_set_trust(SSL_CTX *s, int trust) - { - return X509_VERIFY_PARAM_set_trust(s->param, trust); - } + if (id_len > sizeof r.session_id) { + return 0; + } -int SSL_set_trust(SSL *s, int trust) - { - return X509_VERIFY_PARAM_set_trust(s->param, trust); - } + r.ssl_version = ssl->version; + r.session_id_length = id_len; + memcpy(r.session_id, id, id_len); -int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm) - { - return X509_VERIFY_PARAM_set1(ctx->param, vpm); - } + CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); + p = lh_SSL_SESSION_retrieve(ssl->ctx->sessions, &r); + CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); + return p != NULL; +} -int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm) - { - return X509_VERIFY_PARAM_set1(ssl->param, vpm); - } +int SSL_CTX_set_purpose(SSL_CTX *s, int purpose) { + return X509_VERIFY_PARAM_set_purpose(s->param, purpose); +} + +int SSL_set_purpose(SSL *s, int purpose) { + return X509_VERIFY_PARAM_set_purpose(s->param, purpose); +} + +int SSL_CTX_set_trust(SSL_CTX *s, int trust) { + return X509_VERIFY_PARAM_set_trust(s->param, trust); +} + +int SSL_set_trust(SSL *s, int trust) { + return X509_VERIFY_PARAM_set_trust(s->param, trust); +} + +int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm) { + return X509_VERIFY_PARAM_set1(ctx->param, vpm); +} + +int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm) { + return X509_VERIFY_PARAM_set1(ssl->param, vpm); +} void ssl_cipher_preference_list_free( - struct ssl_cipher_preference_list_st *cipher_list) - { - sk_SSL_CIPHER_free(cipher_list->ciphers); - OPENSSL_free(cipher_list->in_group_flags); - OPENSSL_free(cipher_list); - } + struct ssl_cipher_preference_list_st *cipher_list) { + sk_SSL_CIPHER_free(cipher_list->ciphers); + OPENSSL_free(cipher_list->in_group_flags); + OPENSSL_free(cipher_list); +} -struct ssl_cipher_preference_list_st* -ssl_cipher_preference_list_dup( - struct ssl_cipher_preference_list_st *cipher_list) - { - struct ssl_cipher_preference_list_st* ret = NULL; - size_t n = sk_SSL_CIPHER_num(cipher_list->ciphers); +struct ssl_cipher_preference_list_st *ssl_cipher_preference_list_dup( + struct ssl_cipher_preference_list_st *cipher_list) { + struct ssl_cipher_preference_list_st *ret = NULL; + size_t n = sk_SSL_CIPHER_num(cipher_list->ciphers); - ret = OPENSSL_malloc(sizeof(struct ssl_cipher_preference_list_st)); - if (!ret) - goto err; - ret->ciphers = NULL; - ret->in_group_flags = NULL; - ret->ciphers = sk_SSL_CIPHER_dup(cipher_list->ciphers); - if (!ret->ciphers) - goto err; - ret->in_group_flags = BUF_memdup(cipher_list->in_group_flags, n); - if (!ret->in_group_flags) - goto err; - return ret; + ret = OPENSSL_malloc(sizeof(struct ssl_cipher_preference_list_st)); + if (!ret) { + goto err; + } + + ret->ciphers = NULL; + ret->in_group_flags = NULL; + ret->ciphers = sk_SSL_CIPHER_dup(cipher_list->ciphers); + if (!ret->ciphers) { + goto err; + } + ret->in_group_flags = BUF_memdup(cipher_list->in_group_flags, n); + if (!ret->in_group_flags) { + goto err; + } + + return ret; err: - if (ret && ret->ciphers) - sk_SSL_CIPHER_free(ret->ciphers); - if (ret) - OPENSSL_free(ret); - return NULL; - } + if (ret && ret->ciphers) { + sk_SSL_CIPHER_free(ret->ciphers); + } + if (ret) { + OPENSSL_free(ret); + } + return NULL; +} -struct ssl_cipher_preference_list_st* -ssl_cipher_preference_list_from_ciphers(STACK_OF(SSL_CIPHER) *ciphers) - { - struct ssl_cipher_preference_list_st* ret = NULL; - size_t n = sk_SSL_CIPHER_num(ciphers); +struct ssl_cipher_preference_list_st *ssl_cipher_preference_list_from_ciphers( + STACK_OF(SSL_CIPHER) * ciphers) { + struct ssl_cipher_preference_list_st *ret = NULL; + size_t n = sk_SSL_CIPHER_num(ciphers); - ret = OPENSSL_malloc(sizeof(struct ssl_cipher_preference_list_st)); - if (!ret) - goto err; - ret->ciphers = NULL; - ret->in_group_flags = NULL; - ret->ciphers = sk_SSL_CIPHER_dup(ciphers); - if (!ret->ciphers) - goto err; - ret->in_group_flags = OPENSSL_malloc(n); - if (!ret->in_group_flags) - goto err; - memset(ret->in_group_flags, 0, n); - return ret; + ret = OPENSSL_malloc(sizeof(struct ssl_cipher_preference_list_st)); + if (!ret) { + goto err; + } + ret->ciphers = NULL; + ret->in_group_flags = NULL; + ret->ciphers = sk_SSL_CIPHER_dup(ciphers); + if (!ret->ciphers) { + goto err; + } + ret->in_group_flags = OPENSSL_malloc(n); + if (!ret->in_group_flags) { + goto err; + } + memset(ret->in_group_flags, 0, n); + return ret; err: - if (ret && ret->ciphers) - sk_SSL_CIPHER_free(ret->ciphers); - if (ret) - OPENSSL_free(ret); - return NULL; - } + if (ret && ret->ciphers) { + sk_SSL_CIPHER_free(ret->ciphers); + } + if (ret) { + OPENSSL_free(ret); + } + return NULL; +} -X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx) - { - return ctx->param; - } +X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx) { return ctx->param; } -X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl) - { - return ssl->param; - } +X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl) { return ssl->param; } -void SSL_certs_clear(SSL *s) - { - ssl_cert_clear_certs(s->cert); - } +void SSL_certs_clear(SSL *s) { ssl_cert_clear_certs(s->cert); } -void SSL_free(SSL *s) - { - int i; +void SSL_free(SSL *s) { + int i; - if(s == NULL) - return; + if (s == NULL) { + return; + } - i=CRYPTO_add(&s->references,-1,CRYPTO_LOCK_SSL); -#ifdef REF_PRINT - REF_PRINT("SSL",s); -#endif - if (i > 0) return; -#ifdef REF_CHECK - if (i < 0) - { - fprintf(stderr,"SSL_free, bad reference count\n"); - abort(); /* ok */ - } -#endif + i = CRYPTO_add(&s->references, -1, CRYPTO_LOCK_SSL); + if (i > 0) { + return; + } - if (s->param) - X509_VERIFY_PARAM_free(s->param); + if (s->param) { + X509_VERIFY_PARAM_free(s->param); + } - CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data); + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data); - if (s->bbio != NULL) - { - /* If the buffering BIO is in place, pop it off */ - if (s->bbio == s->wbio) - { - s->wbio=BIO_pop(s->wbio); - } - BIO_free(s->bbio); - s->bbio=NULL; - } - if (s->rbio != NULL) - BIO_free_all(s->rbio); - if ((s->wbio != NULL) && (s->wbio != s->rbio)) - BIO_free_all(s->wbio); + if (s->bbio != NULL) { + /* If the buffering BIO is in place, pop it off */ + if (s->bbio == s->wbio) { + s->wbio = BIO_pop(s->wbio); + } + BIO_free(s->bbio); + s->bbio = NULL; + } - if (s->init_buf != NULL) BUF_MEM_free(s->init_buf); + if (s->rbio != NULL) { + BIO_free_all(s->rbio); + } - /* add extra stuff */ - if (s->cipher_list != NULL) - ssl_cipher_preference_list_free(s->cipher_list); - if (s->cipher_list_by_id != NULL) sk_SSL_CIPHER_free(s->cipher_list_by_id); + if (s->wbio != NULL && s->wbio != s->rbio) { + BIO_free_all(s->wbio); + } - /* Make the next call work :-) */ - if (s->session != NULL) - { - ssl_clear_bad_session(s); - SSL_SESSION_free(s->session); - } + if (s->init_buf != NULL) { + BUF_MEM_free(s->init_buf); + } - ssl_clear_cipher_ctx(s); - ssl_clear_hash_ctx(&s->read_hash); - ssl_clear_hash_ctx(&s->write_hash); + /* add extra stuff */ + if (s->cipher_list != NULL) { + ssl_cipher_preference_list_free(s->cipher_list); + } + if (s->cipher_list_by_id != NULL) { + sk_SSL_CIPHER_free(s->cipher_list_by_id); + } - if (s->cert != NULL) ssl_cert_free(s->cert); - /* Free up if allocated */ + if (s->session != NULL) { + ssl_clear_bad_session(s); + SSL_SESSION_free(s->session); + } - if (s->tlsext_hostname) - OPENSSL_free(s->tlsext_hostname); - if (s->initial_ctx) SSL_CTX_free(s->initial_ctx); - if (s->tlsext_ecpointformatlist) OPENSSL_free(s->tlsext_ecpointformatlist); - if (s->tlsext_ellipticcurvelist) OPENSSL_free(s->tlsext_ellipticcurvelist); - if (s->alpn_client_proto_list) - OPENSSL_free(s->alpn_client_proto_list); - if (s->tlsext_channel_id_private) - EVP_PKEY_free(s->tlsext_channel_id_private); + ssl_clear_cipher_ctx(s); + ssl_clear_hash_ctx(&s->read_hash); + ssl_clear_hash_ctx(&s->write_hash); - if (s->psk_identity_hint) - OPENSSL_free(s->psk_identity_hint); + if (s->cert != NULL) { + ssl_cert_free(s->cert); + } - if (s->client_CA != NULL) - sk_X509_NAME_pop_free(s->client_CA,X509_NAME_free); + if (s->tlsext_hostname) { + OPENSSL_free(s->tlsext_hostname); + } + if (s->initial_ctx) { + SSL_CTX_free(s->initial_ctx); + } + if (s->tlsext_ecpointformatlist) { + OPENSSL_free(s->tlsext_ecpointformatlist); + } + if (s->tlsext_ellipticcurvelist) { + OPENSSL_free(s->tlsext_ellipticcurvelist); + } + if (s->alpn_client_proto_list) { + OPENSSL_free(s->alpn_client_proto_list); + } + if (s->tlsext_channel_id_private) { + EVP_PKEY_free(s->tlsext_channel_id_private); + } + if (s->psk_identity_hint) { + OPENSSL_free(s->psk_identity_hint); + } + if (s->client_CA != NULL) { + sk_X509_NAME_pop_free(s->client_CA, X509_NAME_free); + } + if (s->next_proto_negotiated) { + OPENSSL_free(s->next_proto_negotiated); + } + if (s->srtp_profiles) { + sk_SRTP_PROTECTION_PROFILE_free(s->srtp_profiles); + } - if (s->method != NULL) s->method->ssl_free(s); + if (s->method != NULL) { + s->method->ssl_free(s); + } + if (s->ctx) { + SSL_CTX_free(s->ctx); + } - if (s->ctx) SSL_CTX_free(s->ctx); + OPENSSL_free(s); +} - if (s->next_proto_negotiated) - OPENSSL_free(s->next_proto_negotiated); +void SSL_set_bio(SSL *s, BIO *rbio, BIO *wbio) { + /* If the output buffering BIO is still in place, remove it. */ + if (s->bbio != NULL) { + if (s->wbio == s->bbio) { + s->wbio = s->wbio->next_bio; + s->bbio->next_bio = NULL; + } + } - if (s->srtp_profiles) - sk_SRTP_PROTECTION_PROFILE_free(s->srtp_profiles); + if (s->rbio != NULL && s->rbio != rbio) { + BIO_free_all(s->rbio); + } + if (s->wbio != NULL && s->wbio != wbio && s->rbio != s->wbio) { + BIO_free_all(s->wbio); + } + s->rbio = rbio; + s->wbio = wbio; +} - OPENSSL_free(s); - } +BIO *SSL_get_rbio(const SSL *s) { return s->rbio; } -void SSL_set_bio(SSL *s,BIO *rbio,BIO *wbio) - { - /* If the output buffering BIO is still in place, remove it - */ - if (s->bbio != NULL) - { - if (s->wbio == s->bbio) - { - s->wbio=s->wbio->next_bio; - s->bbio->next_bio=NULL; - } - } - if ((s->rbio != NULL) && (s->rbio != rbio)) - BIO_free_all(s->rbio); - if ((s->wbio != NULL) && (s->wbio != wbio) && (s->rbio != s->wbio)) - BIO_free_all(s->wbio); - s->rbio=rbio; - s->wbio=wbio; - } +BIO *SSL_get_wbio(const SSL *s) { return s->wbio; } -BIO *SSL_get_rbio(const SSL *s) - { return(s->rbio); } +int SSL_get_fd(const SSL *s) { return SSL_get_rfd(s); } -BIO *SSL_get_wbio(const SSL *s) - { return(s->wbio); } +int SSL_get_rfd(const SSL *s) { + int ret = -1; + BIO *b, *r; -int SSL_get_fd(const SSL *s) - { - return(SSL_get_rfd(s)); - } + b = SSL_get_rbio(s); + r = BIO_find_type(b, BIO_TYPE_DESCRIPTOR); + if (r != NULL) { + BIO_get_fd(r, &ret); + } + return ret; +} -int SSL_get_rfd(const SSL *s) - { - int ret= -1; - BIO *b,*r; +int SSL_get_wfd(const SSL *s) { + int ret = -1; + BIO *b, *r; - b=SSL_get_rbio(s); - r=BIO_find_type(b,BIO_TYPE_DESCRIPTOR); - if (r != NULL) - BIO_get_fd(r,&ret); - return(ret); - } + b = SSL_get_wbio(s); + r = BIO_find_type(b, BIO_TYPE_DESCRIPTOR); + if (r != NULL) { + BIO_get_fd(r, &ret); + } -int SSL_get_wfd(const SSL *s) - { - int ret= -1; - BIO *b,*r; + return ret; +} - b=SSL_get_wbio(s); - r=BIO_find_type(b,BIO_TYPE_DESCRIPTOR); - if (r != NULL) - BIO_get_fd(r,&ret); - return(ret); - } +int SSL_set_fd(SSL *s, int fd) { + int ret = 0; + BIO *bio = NULL; -#ifndef OPENSSL_NO_SOCK -int SSL_set_fd(SSL *s,int fd) - { - int ret=0; - BIO *bio=NULL; + bio = BIO_new(BIO_s_fd()); - bio=BIO_new(BIO_s_fd()); + if (bio == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_set_fd, ERR_R_BUF_LIB); + goto err; + } + BIO_set_fd(bio, fd, BIO_NOCLOSE); + SSL_set_bio(s, bio, bio); + ret = 1; - if (bio == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_set_fd, ERR_R_BUF_LIB); - goto err; - } - BIO_set_fd(bio,fd,BIO_NOCLOSE); - SSL_set_bio(s,bio,bio); - ret=1; err: - return(ret); - } + return ret; +} -int SSL_set_wfd(SSL *s,int fd) - { - int ret=0; - BIO *bio=NULL; +int SSL_set_wfd(SSL *s, int fd) { + int ret = 0; + BIO *bio = NULL; - if ((s->rbio == NULL) || (BIO_method_type(s->rbio) != BIO_TYPE_FD) - || ((int)BIO_get_fd(s->rbio,NULL) != fd)) - { - bio=BIO_new(BIO_s_fd()); + if (s->rbio == NULL || BIO_method_type(s->rbio) != BIO_TYPE_FD || + (int)BIO_get_fd(s->rbio, NULL) != fd) { + bio = BIO_new(BIO_s_fd()); - if (bio == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_set_wfd, ERR_R_BUF_LIB); - goto err; - } - BIO_set_fd(bio,fd,BIO_NOCLOSE); - SSL_set_bio(s,SSL_get_rbio(s),bio); - } - else - SSL_set_bio(s,SSL_get_rbio(s),SSL_get_rbio(s)); - ret=1; + if (bio == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_set_wfd, ERR_R_BUF_LIB); + goto err; + } + BIO_set_fd(bio, fd, BIO_NOCLOSE); + SSL_set_bio(s, SSL_get_rbio(s), bio); + } else { + SSL_set_bio(s, SSL_get_rbio(s), SSL_get_rbio(s)); + } + + ret = 1; + err: - return(ret); - } + return ret; +} -int SSL_set_rfd(SSL *s,int fd) - { - int ret=0; - BIO *bio=NULL; +int SSL_set_rfd(SSL *s, int fd) { + int ret = 0; + BIO *bio = NULL; - if ((s->wbio == NULL) || (BIO_method_type(s->wbio) != BIO_TYPE_FD) - || ((int)BIO_get_fd(s->wbio,NULL) != fd)) - { - bio=BIO_new(BIO_s_fd()); + if (s->wbio == NULL || BIO_method_type(s->wbio) != BIO_TYPE_FD || + (int)BIO_get_fd(s->wbio, NULL) != fd) { + bio = BIO_new(BIO_s_fd()); - if (bio == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_set_rfd, ERR_R_BUF_LIB); - goto err; - } - BIO_set_fd(bio,fd,BIO_NOCLOSE); - SSL_set_bio(s,bio,SSL_get_wbio(s)); - } - else - SSL_set_bio(s,SSL_get_wbio(s),SSL_get_wbio(s)); - ret=1; + if (bio == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_set_rfd, ERR_R_BUF_LIB); + goto err; + } + BIO_set_fd(bio, fd, BIO_NOCLOSE); + SSL_set_bio(s, bio, SSL_get_wbio(s)); + } else { + SSL_set_bio(s, SSL_get_wbio(s), SSL_get_wbio(s)); + } + ret = 1; + err: - return(ret); - } -#endif - + return ret; +} /* return length of latest Finished message we sent, copy to 'buf' */ -size_t SSL_get_finished(const SSL *s, void *buf, size_t count) - { - size_t ret = 0; - - if (s->s3 != NULL) - { - ret = s->s3->tmp.finish_md_len; - if (count > ret) - count = ret; - memcpy(buf, s->s3->tmp.finish_md, count); - } - return ret; - } +size_t SSL_get_finished(const SSL *s, void *buf, size_t count) { + size_t ret = 0; + + if (s->s3 != NULL) { + ret = s->s3->tmp.finish_md_len; + if (count > ret) { + count = ret; + } + memcpy(buf, s->s3->tmp.finish_md, count); + } + + return ret; +} /* return length of latest Finished message we expected, copy to 'buf' */ -size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count) - { - size_t ret = 0; - - if (s->s3 != NULL) - { - ret = s->s3->tmp.peer_finish_md_len; - if (count > ret) - count = ret; - memcpy(buf, s->s3->tmp.peer_finish_md, count); - } - return ret; - } +size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count) { + size_t ret = 0; + if (s->s3 != NULL) { + ret = s->s3->tmp.peer_finish_md_len; + if (count > ret) { + count = ret; + } + memcpy(buf, s->s3->tmp.peer_finish_md, count); + } -int SSL_get_verify_mode(const SSL *s) - { - return(s->verify_mode); - } + return ret; +} -int SSL_get_verify_depth(const SSL *s) - { - return X509_VERIFY_PARAM_get_depth(s->param); - } +int SSL_get_verify_mode(const SSL *s) { return s->verify_mode; } -int (*SSL_get_verify_callback(const SSL *s))(int,X509_STORE_CTX *) - { - return(s->verify_callback); - } +int SSL_get_verify_depth(const SSL *s) { + return X509_VERIFY_PARAM_get_depth(s->param); +} -int SSL_CTX_get_verify_mode(const SSL_CTX *ctx) - { - return(ctx->verify_mode); - } +int (*SSL_get_verify_callback(const SSL *s))(int, X509_STORE_CTX *) { + return s->verify_callback; +} -int SSL_CTX_get_verify_depth(const SSL_CTX *ctx) - { - return X509_VERIFY_PARAM_get_depth(ctx->param); - } +int SSL_CTX_get_verify_mode(const SSL_CTX *ctx) { return ctx->verify_mode; } -int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx))(int,X509_STORE_CTX *) - { - return(ctx->default_verify_callback); - } +int SSL_CTX_get_verify_depth(const SSL_CTX *ctx) { + return X509_VERIFY_PARAM_get_depth(ctx->param); +} -void SSL_set_verify(SSL *s,int mode, - int (*callback)(int ok,X509_STORE_CTX *ctx)) - { - s->verify_mode=mode; - if (callback != NULL) - s->verify_callback=callback; - } +int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx))(int, X509_STORE_CTX *) { + return ctx->default_verify_callback; +} -void SSL_set_verify_depth(SSL *s,int depth) - { - X509_VERIFY_PARAM_set_depth(s->param, depth); - } +void SSL_set_verify(SSL *s, int mode, + int (*callback)(int ok, X509_STORE_CTX *ctx)) { + s->verify_mode = mode; + if (callback != NULL) { + s->verify_callback = callback; + } +} -void SSL_set_read_ahead(SSL *s,int yes) - { - s->read_ahead=yes; - } +void SSL_set_verify_depth(SSL *s, int depth) { + X509_VERIFY_PARAM_set_depth(s->param, depth); +} -int SSL_get_read_ahead(const SSL *s) - { - return(s->read_ahead); - } +void SSL_set_read_ahead(SSL *s, int yes) { s->read_ahead = yes; } -int SSL_pending(const SSL *s) - { - /* SSL_pending cannot work properly if read-ahead is enabled - * (SSL_[CTX_]ctrl(..., SSL_CTRL_SET_READ_AHEAD, 1, NULL)), - * and it is impossible to fix since SSL_pending cannot report - * errors that may be observed while scanning the new data. - * (Note that SSL_pending() is often used as a boolean value, - * so we'd better not return -1.) - */ - return(s->method->ssl_pending(s)); - } +int SSL_get_read_ahead(const SSL *s) { return s->read_ahead; } -X509 *SSL_get_peer_certificate(const SSL *s) - { - X509 *r; - - if ((s == NULL) || (s->session == NULL)) - r=NULL; - else - r=s->session->peer; +int SSL_pending(const SSL *s) { + /* SSL_pending cannot work properly if read-ahead is enabled + * (SSL_[CTX_]ctrl(..., SSL_CTRL_SET_READ_AHEAD, 1, NULL)), and it is + * impossible to fix since SSL_pending cannot report errors that may be + * observed while scanning the new data. (Note that SSL_pending() is often + * used as a boolean value, so we'd better not return -1.). */ + return s->method->ssl_pending(s); +} - if (r == NULL) - return NULL; +X509 *SSL_get_peer_certificate(const SSL *s) { + X509 *r; - return X509_up_ref(r); - } + if (s == NULL || s->session == NULL) { + r = NULL; + } else { + r = s->session->peer; + } -STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s) - { - STACK_OF(X509) *r; - - if ((s == NULL) || (s->session == NULL) || (s->session->sess_cert == NULL)) - r=NULL; - else - r=s->session->sess_cert->cert_chain; + if (r == NULL) { + return NULL; + } - /* If we are a client, cert_chain includes the peer's own - * certificate; if we are a server, it does not. */ - - return(r); - } + return X509_up_ref(r); +} + +STACK_OF(X509) * SSL_get_peer_cert_chain(const SSL *s) { + STACK_OF(X509) * r; + + if (s == NULL || s->session == NULL || s->session->sess_cert == NULL) { + r = NULL; + } else { + r = s->session->sess_cert->cert_chain; + } + + /* If we are a client, cert_chain includes the peer's own certificate; if we + * are a server, it does not. */ + return r; +} /* Fix this so it checks all the valid key/cert options */ -int SSL_CTX_check_private_key(const SSL_CTX *ctx) - { - if ( (ctx == NULL) || - (ctx->cert == NULL) || - (ctx->cert->key->x509 == NULL)) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_check_private_key, SSL_R_NO_CERTIFICATE_ASSIGNED); - return(0); - } - if (ctx->cert->key->privatekey == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_check_private_key, SSL_R_NO_PRIVATE_KEY_ASSIGNED); - return(0); - } - return(X509_check_private_key(ctx->cert->key->x509, ctx->cert->key->privatekey)); - } +int SSL_CTX_check_private_key(const SSL_CTX *ctx) { + if (ctx == NULL || ctx->cert == NULL || ctx->cert->key->x509 == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_check_private_key, + SSL_R_NO_CERTIFICATE_ASSIGNED); + return 0; + } + + if (ctx->cert->key->privatekey == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_check_private_key, + SSL_R_NO_PRIVATE_KEY_ASSIGNED); + return 0; + } + + return X509_check_private_key(ctx->cert->key->x509, + ctx->cert->key->privatekey); +} /* Fix this function so that it takes an optional type parameter */ -int SSL_check_private_key(const SSL *ssl) - { - if (ssl == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_check_private_key, ERR_R_PASSED_NULL_PARAMETER); - return(0); - } - if (ssl->cert == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_check_private_key, SSL_R_NO_CERTIFICATE_ASSIGNED); - return 0; - } - if (ssl->cert->key->x509 == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_check_private_key, SSL_R_NO_CERTIFICATE_ASSIGNED); - return(0); - } - if (ssl->cert->key->privatekey == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_check_private_key, SSL_R_NO_PRIVATE_KEY_ASSIGNED); - return(0); - } - return(X509_check_private_key(ssl->cert->key->x509, - ssl->cert->key->privatekey)); - } +int SSL_check_private_key(const SSL *ssl) { + if (ssl == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_check_private_key, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } -int SSL_accept(SSL *s) - { - if (s->handshake_func == 0) - /* Not properly initialized yet */ - SSL_set_accept_state(s); + if (ssl->cert == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_check_private_key, + SSL_R_NO_CERTIFICATE_ASSIGNED); + return 0; + } - if (s->handshake_func != s->method->ssl_accept) - { - OPENSSL_PUT_ERROR(SSL, SSL_connect, ERR_R_INTERNAL_ERROR); - return -1; - } + if (ssl->cert->key->x509 == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_check_private_key, + SSL_R_NO_CERTIFICATE_ASSIGNED); + return 0; + } - return s->handshake_func(s); - } + if (ssl->cert->key->privatekey == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_check_private_key, + SSL_R_NO_PRIVATE_KEY_ASSIGNED); + return 0; + } -int SSL_connect(SSL *s) - { - if (s->handshake_func == 0) - /* Not properly initialized yet */ - SSL_set_connect_state(s); + return X509_check_private_key(ssl->cert->key->x509, + ssl->cert->key->privatekey); +} - if (s->handshake_func != s->method->ssl_connect) - { - OPENSSL_PUT_ERROR(SSL, SSL_connect, ERR_R_INTERNAL_ERROR); - return -1; - } +int SSL_accept(SSL *s) { + if (s->handshake_func == 0) { + /* Not properly initialized yet */ + SSL_set_accept_state(s); + } - return s->handshake_func(s); - } + if (s->handshake_func != s->method->ssl_accept) { + OPENSSL_PUT_ERROR(SSL, SSL_connect, ERR_R_INTERNAL_ERROR); + return -1; + } -long SSL_get_default_timeout(const SSL *s) - { - return SSL_DEFAULT_SESSION_TIMEOUT; - } + return s->handshake_func(s); +} -int SSL_read(SSL *s,void *buf,int num) - { - if (s->handshake_func == 0) - { - OPENSSL_PUT_ERROR(SSL, SSL_read, SSL_R_UNINITIALIZED); - return -1; - } +int SSL_connect(SSL *s) { + if (s->handshake_func == 0) { + /* Not properly initialized yet */ + SSL_set_connect_state(s); + } - if (s->shutdown & SSL_RECEIVED_SHUTDOWN) - { - s->rwstate=SSL_NOTHING; - return(0); - } - return(s->method->ssl_read(s,buf,num)); - } + if (s->handshake_func != s->method->ssl_connect) { + OPENSSL_PUT_ERROR(SSL, SSL_connect, ERR_R_INTERNAL_ERROR); + return -1; + } -int SSL_peek(SSL *s,void *buf,int num) - { - if (s->handshake_func == 0) - { - OPENSSL_PUT_ERROR(SSL, SSL_peek, SSL_R_UNINITIALIZED); - return -1; - } + return s->handshake_func(s); +} - if (s->shutdown & SSL_RECEIVED_SHUTDOWN) - { - return(0); - } - return(s->method->ssl_peek(s,buf,num)); - } +long SSL_get_default_timeout(const SSL *s) { + return SSL_DEFAULT_SESSION_TIMEOUT; +} -int SSL_write(SSL *s,const void *buf,int num) - { - if (s->handshake_func == 0) - { - OPENSSL_PUT_ERROR(SSL, SSL_write, SSL_R_UNINITIALIZED); - return -1; - } +int SSL_read(SSL *s, void *buf, int num) { + if (s->handshake_func == 0) { + OPENSSL_PUT_ERROR(SSL, SSL_read, SSL_R_UNINITIALIZED); + return -1; + } - if (s->shutdown & SSL_SENT_SHUTDOWN) - { - s->rwstate=SSL_NOTHING; - OPENSSL_PUT_ERROR(SSL, SSL_write, SSL_R_PROTOCOL_IS_SHUTDOWN); - return(-1); - } - return(s->method->ssl_write(s,buf,num)); - } + if (s->shutdown & SSL_RECEIVED_SHUTDOWN) { + s->rwstate = SSL_NOTHING; + return 0; + } -int SSL_shutdown(SSL *s) - { - /* Note that this function behaves differently from what one might - * expect. Return values are 0 for no success (yet), - * 1 for success; but calling it once is usually not enough, - * even if blocking I/O is used (see ssl3_shutdown). - */ + return s->method->ssl_read(s, buf, num); +} - if (s->handshake_func == 0) - { - OPENSSL_PUT_ERROR(SSL, SSL_shutdown, SSL_R_UNINITIALIZED); - return -1; - } +int SSL_peek(SSL *s, void *buf, int num) { + if (s->handshake_func == 0) { + OPENSSL_PUT_ERROR(SSL, SSL_peek, SSL_R_UNINITIALIZED); + return -1; + } - if (!SSL_in_init(s)) - return(s->method->ssl_shutdown(s)); - else - return(1); - } + if (s->shutdown & SSL_RECEIVED_SHUTDOWN) { + return 0; + } -int SSL_renegotiate(SSL *s) - { - if (s->renegotiate == 0) - s->renegotiate=1; + return s->method->ssl_peek(s, buf, num); +} - s->new_session=1; +int SSL_write(SSL *s, const void *buf, int num) { + if (s->handshake_func == 0) { + OPENSSL_PUT_ERROR(SSL, SSL_write, SSL_R_UNINITIALIZED); + return -1; + } - return(s->method->ssl_renegotiate(s)); - } + if (s->shutdown & SSL_SENT_SHUTDOWN) { + s->rwstate = SSL_NOTHING; + OPENSSL_PUT_ERROR(SSL, SSL_write, SSL_R_PROTOCOL_IS_SHUTDOWN); + return -1; + } -int SSL_renegotiate_abbreviated(SSL *s) - { - if (s->renegotiate == 0) - s->renegotiate=1; + return s->method->ssl_write(s, buf, num); +} - s->new_session=0; +int SSL_shutdown(SSL *s) { + /* Note that this function behaves differently from what one might expect. + * Return values are 0 for no success (yet), 1 for success; but calling it + * once is usually not enough, even if blocking I/O is used (see + * ssl3_shutdown). */ - return(s->method->ssl_renegotiate(s)); - } + if (s->handshake_func == 0) { + OPENSSL_PUT_ERROR(SSL, SSL_shutdown, SSL_R_UNINITIALIZED); + return -1; + } -int SSL_renegotiate_pending(SSL *s) - { - /* becomes true when negotiation is requested; - * false again once a handshake has finished */ - return (s->renegotiate != 0); - } + if (!SSL_in_init(s)) { + return s->method->ssl_shutdown(s); + } -long SSL_ctrl(SSL *s,int cmd,long larg,void *parg) - { - long l; + return 1; +} - switch (cmd) - { - case SSL_CTRL_GET_READ_AHEAD: - return(s->read_ahead); - case SSL_CTRL_SET_READ_AHEAD: - l=s->read_ahead; - s->read_ahead=larg; - return(l); +int SSL_renegotiate(SSL *s) { + if (s->renegotiate == 0) { + s->renegotiate = 1; + } - case SSL_CTRL_SET_MSG_CALLBACK_ARG: - s->msg_callback_arg = parg; - return 1; + s->new_session = 1; + return s->method->ssl_renegotiate(s); +} - case SSL_CTRL_OPTIONS: - return(s->options|=larg); - case SSL_CTRL_CLEAR_OPTIONS: - return(s->options&=~larg); - case SSL_CTRL_MODE: - return(s->mode|=larg); - case SSL_CTRL_CLEAR_MODE: - return(s->mode &=~larg); - case SSL_CTRL_GET_MAX_CERT_LIST: - return(s->max_cert_list); - case SSL_CTRL_SET_MAX_CERT_LIST: - l=s->max_cert_list; - s->max_cert_list=larg; - return(l); - case SSL_CTRL_SET_MTU: - if (larg < (long)dtls1_min_mtu()) - return 0; - if (SSL_IS_DTLS(s)) - { - s->d1->mtu = larg; - return larg; - } - return 0; - case SSL_CTRL_SET_MAX_SEND_FRAGMENT: - if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH) - return 0; - s->max_send_fragment = larg; - return 1; - case SSL_CTRL_GET_RI_SUPPORT: - if (s->s3) - return s->s3->send_connection_binding; - else return 0; - case SSL_CTRL_CERT_FLAGS: - return(s->cert->cert_flags|=larg); - case SSL_CTRL_CLEAR_CERT_FLAGS: - return(s->cert->cert_flags &=~larg); +int SSL_renegotiate_abbreviated(SSL *s) { + if (s->renegotiate == 0) { + s->renegotiate = 1; + } - case SSL_CTRL_GET_RAW_CIPHERLIST: - if (parg) - { - if (s->cert->ciphers_raw == NULL) - return 0; - *(unsigned char **)parg = s->cert->ciphers_raw; - return (int)s->cert->ciphers_rawlen; - } - else - { - /* Passing a NULL |parg| returns the size of a single - * cipher suite value. */ - return 2; - } - default: - return(s->method->ssl_ctrl(s,cmd,larg,parg)); - } - } + s->new_session = 0; + return s->method->ssl_renegotiate(s); +} -long SSL_callback_ctrl(SSL *s, int cmd, void (*fp)(void)) - { - switch(cmd) - { - case SSL_CTRL_SET_MSG_CALLBACK: - s->msg_callback = (void (*)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg))(fp); - return 1; - - default: - return(s->method->ssl_callback_ctrl(s,cmd,fp)); - } - } +int SSL_renegotiate_pending(SSL *s) { + /* becomes true when negotiation is requested; false again once a handshake + * has finished */ + return s->renegotiate != 0; +} -LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx) - { - return ctx->sessions; - } +long SSL_ctrl(SSL *s, int cmd, long larg, void *parg) { + long l; -long SSL_CTX_ctrl(SSL_CTX *ctx,int cmd,long larg,void *parg) - { - long l; + switch (cmd) { + case SSL_CTRL_GET_READ_AHEAD: + return s->read_ahead; - switch (cmd) - { - case SSL_CTRL_GET_READ_AHEAD: - return(ctx->read_ahead); - case SSL_CTRL_SET_READ_AHEAD: - l=ctx->read_ahead; - ctx->read_ahead=larg; - return(l); - - case SSL_CTRL_SET_MSG_CALLBACK_ARG: - ctx->msg_callback_arg = parg; - return 1; + case SSL_CTRL_SET_READ_AHEAD: + l = s->read_ahead; + s->read_ahead = larg; + return l; - case SSL_CTRL_GET_MAX_CERT_LIST: - return(ctx->max_cert_list); - case SSL_CTRL_SET_MAX_CERT_LIST: - l=ctx->max_cert_list; - ctx->max_cert_list=larg; - return(l); + case SSL_CTRL_SET_MSG_CALLBACK_ARG: + s->msg_callback_arg = parg; + return 1; - case SSL_CTRL_SET_SESS_CACHE_SIZE: - l=ctx->session_cache_size; - ctx->session_cache_size=larg; - return(l); - case SSL_CTRL_GET_SESS_CACHE_SIZE: - return(ctx->session_cache_size); - case SSL_CTRL_SET_SESS_CACHE_MODE: - l=ctx->session_cache_mode; - ctx->session_cache_mode=larg; - return(l); - case SSL_CTRL_GET_SESS_CACHE_MODE: - return(ctx->session_cache_mode); + case SSL_CTRL_OPTIONS: + return s->options |= larg; - case SSL_CTRL_SESS_NUMBER: - return(lh_SSL_SESSION_num_items(ctx->sessions)); - case SSL_CTRL_SESS_CONNECT: - return(ctx->stats.sess_connect); - case SSL_CTRL_SESS_CONNECT_GOOD: - return(ctx->stats.sess_connect_good); - case SSL_CTRL_SESS_CONNECT_RENEGOTIATE: - return(ctx->stats.sess_connect_renegotiate); - case SSL_CTRL_SESS_ACCEPT: - return(ctx->stats.sess_accept); - case SSL_CTRL_SESS_ACCEPT_GOOD: - return(ctx->stats.sess_accept_good); - case SSL_CTRL_SESS_ACCEPT_RENEGOTIATE: - return(ctx->stats.sess_accept_renegotiate); - case SSL_CTRL_SESS_HIT: - return(ctx->stats.sess_hit); - case SSL_CTRL_SESS_CB_HIT: - return(ctx->stats.sess_cb_hit); - case SSL_CTRL_SESS_MISSES: - return(ctx->stats.sess_miss); - case SSL_CTRL_SESS_TIMEOUTS: - return(ctx->stats.sess_timeout); - case SSL_CTRL_SESS_CACHE_FULL: - return(ctx->stats.sess_cache_full); - case SSL_CTRL_OPTIONS: - return(ctx->options|=larg); - case SSL_CTRL_CLEAR_OPTIONS: - return(ctx->options&=~larg); - case SSL_CTRL_MODE: - return(ctx->mode|=larg); - case SSL_CTRL_CLEAR_MODE: - return(ctx->mode&=~larg); - case SSL_CTRL_SET_MAX_SEND_FRAGMENT: - if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH) - return 0; - ctx->max_send_fragment = larg; - return 1; - case SSL_CTRL_CERT_FLAGS: - return(ctx->cert->cert_flags|=larg); - case SSL_CTRL_CLEAR_CERT_FLAGS: - return(ctx->cert->cert_flags &=~larg); - default: - return(ctx->method->ssl_ctx_ctrl(ctx,cmd,larg,parg)); - } - } + case SSL_CTRL_CLEAR_OPTIONS: + return s->options &= ~larg; -long SSL_CTX_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp)(void)) - { - switch(cmd) - { - case SSL_CTRL_SET_MSG_CALLBACK: - ctx->msg_callback = (void (*)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg))(fp); - return 1; + case SSL_CTRL_MODE: + return s->mode |= larg; - default: - return(ctx->method->ssl_ctx_callback_ctrl(ctx,cmd,fp)); - } - } + case SSL_CTRL_CLEAR_MODE: + return s->mode &= ~larg; -int ssl_cipher_id_cmp(const void *in_a, const void *in_b) - { - long l; - const SSL_CIPHER *a = in_a; - const SSL_CIPHER *b = in_b; - const long a_id = a->id; - const long b_id = b->id; + case SSL_CTRL_GET_MAX_CERT_LIST: + return s->max_cert_list; - l = a_id - b_id; - if (l == 0L) - return(0); - else - return((l > 0)?1:-1); - } + case SSL_CTRL_SET_MAX_CERT_LIST: + l = s->max_cert_list; + s->max_cert_list = larg; + return l; -int ssl_cipher_ptr_id_cmp(const SSL_CIPHER **ap, const SSL_CIPHER **bp) - { - long l; - const long a_id = (*ap)->id; - const long b_id = (*bp)->id; + case SSL_CTRL_SET_MTU: + if (larg < (long)dtls1_min_mtu()) { + return 0; + } + if (SSL_IS_DTLS(s)) { + s->d1->mtu = larg; + return larg; + } + return 0; - l = a_id - b_id; - if (l == 0) - return(0); - else - return((l > 0)?1:-1); - } + case SSL_CTRL_SET_MAX_SEND_FRAGMENT: + if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH) { + return 0; + } + s->max_send_fragment = larg; + return 1; -/** return a STACK of the ciphers available for the SSL and in order of + case SSL_CTRL_GET_RI_SUPPORT: + if (s->s3) { + return s->s3->send_connection_binding; + } + return 0; + + case SSL_CTRL_CERT_FLAGS: + return s->cert->cert_flags |= larg; + + case SSL_CTRL_CLEAR_CERT_FLAGS: + return s->cert->cert_flags &= ~larg; + + case SSL_CTRL_GET_RAW_CIPHERLIST: + if (parg) { + if (s->cert->ciphers_raw == NULL) { + return 0; + } + *(uint8_t **)parg = s->cert->ciphers_raw; + return (int)s->cert->ciphers_rawlen; + } + + /* Passing a NULL |parg| returns the size of a single + * cipher suite value. */ + return 2; + + default: + return s->method->ssl_ctrl(s, cmd, larg, parg); + } +} + +long SSL_callback_ctrl(SSL *s, int cmd, void (*fp)(void)) { + switch (cmd) { + case SSL_CTRL_SET_MSG_CALLBACK: + s->msg_callback = + (void (*)(int write_p, int version, int content_type, const void *buf, + size_t len, SSL *ssl, void *arg))(fp); + return 1; + + default: + return s->method->ssl_callback_ctrl(s, cmd, fp); + } +} + +LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx) { return ctx->sessions; } + +long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) { + long l; + + switch (cmd) { + case SSL_CTRL_GET_READ_AHEAD: + return ctx->read_ahead; + + case SSL_CTRL_SET_READ_AHEAD: + l = ctx->read_ahead; + ctx->read_ahead = larg; + return l; + + case SSL_CTRL_SET_MSG_CALLBACK_ARG: + ctx->msg_callback_arg = parg; + return 1; + + case SSL_CTRL_GET_MAX_CERT_LIST: + return ctx->max_cert_list; + + case SSL_CTRL_SET_MAX_CERT_LIST: + l = ctx->max_cert_list; + ctx->max_cert_list = larg; + return l; + + case SSL_CTRL_SET_SESS_CACHE_SIZE: + l = ctx->session_cache_size; + ctx->session_cache_size = larg; + return l; + + case SSL_CTRL_GET_SESS_CACHE_SIZE: + return ctx->session_cache_size; + + case SSL_CTRL_SET_SESS_CACHE_MODE: + l = ctx->session_cache_mode; + ctx->session_cache_mode = larg; + return l; + + case SSL_CTRL_GET_SESS_CACHE_MODE: + return ctx->session_cache_mode; + + case SSL_CTRL_SESS_NUMBER: + return lh_SSL_SESSION_num_items(ctx->sessions); + + case SSL_CTRL_SESS_CONNECT: + return ctx->stats.sess_connect; + + case SSL_CTRL_SESS_CONNECT_GOOD: + return ctx->stats.sess_connect_good; + + case SSL_CTRL_SESS_CONNECT_RENEGOTIATE: + return ctx->stats.sess_connect_renegotiate; + + case SSL_CTRL_SESS_ACCEPT: + return ctx->stats.sess_accept; + + case SSL_CTRL_SESS_ACCEPT_GOOD: + return ctx->stats.sess_accept_good; + + case SSL_CTRL_SESS_ACCEPT_RENEGOTIATE: + return ctx->stats.sess_accept_renegotiate; + + case SSL_CTRL_SESS_HIT: + return ctx->stats.sess_hit; + + case SSL_CTRL_SESS_CB_HIT: + return ctx->stats.sess_cb_hit; + + case SSL_CTRL_SESS_MISSES: + return ctx->stats.sess_miss; + + case SSL_CTRL_SESS_TIMEOUTS: + return ctx->stats.sess_timeout; + + case SSL_CTRL_SESS_CACHE_FULL: + return ctx->stats.sess_cache_full; + + case SSL_CTRL_OPTIONS: + return ctx->options |= larg; + + case SSL_CTRL_CLEAR_OPTIONS: + return ctx->options &= ~larg; + + case SSL_CTRL_MODE: + return ctx->mode |= larg; + + case SSL_CTRL_CLEAR_MODE: + return ctx->mode &= ~larg; + + case SSL_CTRL_SET_MAX_SEND_FRAGMENT: + if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH) { + return 0; + } + ctx->max_send_fragment = larg; + return 1; + + case SSL_CTRL_CERT_FLAGS: + return ctx->cert->cert_flags |= larg; + + case SSL_CTRL_CLEAR_CERT_FLAGS: + return ctx->cert->cert_flags &= ~larg; + + default: + return ctx->method->ssl_ctx_ctrl(ctx, cmd, larg, parg); + } +} + +long SSL_CTX_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp)(void)) { + switch (cmd) { + case SSL_CTRL_SET_MSG_CALLBACK: + ctx->msg_callback = + (void (*)(int write_p, int version, int content_type, const void *buf, + size_t len, SSL *ssl, void *arg))(fp); + return 1; + + default: + return ctx->method->ssl_ctx_callback_ctrl(ctx, cmd, fp); + } +} + +int ssl_cipher_id_cmp(const void *in_a, const void *in_b) { + long l; + const SSL_CIPHER *a = in_a; + const SSL_CIPHER *b = in_b; + const long a_id = a->id; + const long b_id = b->id; + + l = a_id - b_id; + if (l == 0L) { + return 0; + } else { + return (l > 0) ? 1 : -1; + } +} + +int ssl_cipher_ptr_id_cmp(const SSL_CIPHER **ap, const SSL_CIPHER **bp) { + long l; + const long a_id = (*ap)->id; + const long b_id = (*bp)->id; + + l = a_id - b_id; + if (l == 0) { + return 0; + } else { + return (l > 0) ? 1 : -1; + } +} + +/* return a STACK of the ciphers available for the SSL and in order of * preference */ -STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s) - { - if (s == NULL) - return NULL; +STACK_OF(SSL_CIPHER) * SSL_get_ciphers(const SSL *s) { + if (s == NULL) { + return NULL; + } - if (s->cipher_list != NULL) - { - return(s->cipher_list->ciphers); - } + if (s->cipher_list != NULL) { + return s->cipher_list->ciphers; + } - if (s->version >= TLS1_1_VERSION) - { - if (s->ctx != NULL && s->ctx->cipher_list_tls11 != NULL) - return s->ctx->cipher_list_tls11->ciphers; - } + if (s->version >= TLS1_1_VERSION && s->ctx != NULL && + s->ctx->cipher_list_tls11 != NULL) { + return s->ctx->cipher_list_tls11->ciphers; + } - if ((s->ctx != NULL) && - (s->ctx->cipher_list != NULL)) - { - return(s->ctx->cipher_list->ciphers); - } + if (s->ctx != NULL && s->ctx->cipher_list != NULL) { + return s->ctx->cipher_list->ciphers; + } - return(NULL); - } + return NULL; +} -/** return a STACK of the ciphers available for the SSL and in order of +/* return a STACK of the ciphers available for the SSL and in order of * algorithm id */ -STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s) - { - if (s != NULL) - { - if (s->cipher_list_by_id != NULL) - { - return(s->cipher_list_by_id); - } - else if ((s->ctx != NULL) && - (s->ctx->cipher_list_by_id != NULL)) - { - return(s->ctx->cipher_list_by_id); - } - } - return(NULL); - } +STACK_OF(SSL_CIPHER) * ssl_get_ciphers_by_id(SSL *s) { + if (s == NULL) { + return NULL; + } -/** The old interface to get the same thing as SSL_get_ciphers() */ -const char *SSL_get_cipher_list(const SSL *s, int n) - { - const SSL_CIPHER *c; - STACK_OF(SSL_CIPHER) *sk; + if (s->cipher_list_by_id != NULL) { + return s->cipher_list_by_id; + } - if (s == NULL) - return NULL; - sk = SSL_get_ciphers(s); - if (sk == NULL || n < 0 || (size_t)n >= sk_SSL_CIPHER_num(sk)) - return NULL; - c = sk_SSL_CIPHER_value(sk, n); - if (c == NULL) - return NULL; - return c->name; - } + if (s->ctx != NULL && s->ctx->cipher_list_by_id != NULL) { + return s->ctx->cipher_list_by_id; + } -/** specify the ciphers to be used by default by the SSL_CTX */ -int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) - { - STACK_OF(SSL_CIPHER) *sk; - - sk=ssl_create_cipher_list(ctx->method,&ctx->cipher_list, - &ctx->cipher_list_by_id,str, ctx->cert); - /* ssl_create_cipher_list may return an empty stack if it - * was unable to find a cipher matching the given rule string - * (for example if the rule string specifies a cipher which - * has been disabled). This is not an error as far as - * ssl_create_cipher_list is concerned, and hence - * ctx->cipher_list and ctx->cipher_list_by_id has been - * updated. */ - if (sk == NULL) - return 0; - else if (sk_SSL_CIPHER_num(sk) == 0) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_set_cipher_list, SSL_R_NO_CIPHER_MATCH); - return 0; - } - return 1; - } + return NULL; +} -int SSL_CTX_set_cipher_list_tls11(SSL_CTX *ctx, const char *str) - { - STACK_OF(SSL_CIPHER) *sk; - - sk = ssl_create_cipher_list(ctx->method, &ctx->cipher_list_tls11, NULL, str, ctx->cert); - if (sk == NULL) - return 0; - else if (sk_SSL_CIPHER_num(sk) == 0) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_set_cipher_list_tls11, SSL_R_NO_CIPHER_MATCH); - return 0; - } - return 1; - } +/* The old interface to get the same thing as SSL_get_ciphers() */ +const char *SSL_get_cipher_list(const SSL *s, int n) { + const SSL_CIPHER *c; + STACK_OF(SSL_CIPHER) * sk; -/** specify the ciphers to be used by the SSL */ -int SSL_set_cipher_list(SSL *s,const char *str) - { - STACK_OF(SSL_CIPHER) *sk; - - sk=ssl_create_cipher_list(s->ctx->method,&s->cipher_list, - &s->cipher_list_by_id,str, s->cert); - /* see comment in SSL_CTX_set_cipher_list */ - if (sk == NULL) - return 0; - else if (sk_SSL_CIPHER_num(sk) == 0) - { - OPENSSL_PUT_ERROR(SSL, SSL_set_cipher_list, SSL_R_NO_CIPHER_MATCH); - return 0; - } - return 1; - } + if (s == NULL) { + return NULL; + } -int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, uint8_t *p) - { - size_t i; - const SSL_CIPHER *c; - CERT *ct = s->cert; - uint8_t *q; - /* Set disabled masks for this session */ - ssl_set_client_disabled(s); + sk = SSL_get_ciphers(s); + if (sk == NULL || n < 0 || (size_t)n >= sk_SSL_CIPHER_num(sk)) { + return NULL; + } - if (sk == NULL) return(0); - q=p; + c = sk_SSL_CIPHER_value(sk, n); + if (c == NULL) { + return NULL; + } - for (i=0; i<sk_SSL_CIPHER_num(sk); i++) - { - c=sk_SSL_CIPHER_value(sk,i); - /* Skip disabled ciphers */ - if (c->algorithm_ssl & ct->mask_ssl || - c->algorithm_mkey & ct->mask_k || - c->algorithm_auth & ct->mask_a) - continue; - s2n(ssl3_get_cipher_value(c), p); - } - /* If all ciphers were disabled, return the error to the caller. */ - if (p == q) - { - return 0; - } + return c->name; +} - /* Add SCSVs. */ - if (!s->renegotiate) - { - s2n(SSL3_CK_SCSV & 0xffff, p); - } - if (s->fallback_scsv) - { - s2n(SSL3_CK_FALLBACK_SCSV & 0xffff, p); - } +/* specify the ciphers to be used by default by the SSL_CTX */ +int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) { + STACK_OF(SSL_CIPHER) *sk; - return(p-q); - } + sk = ssl_create_cipher_list(ctx->method, &ctx->cipher_list, + &ctx->cipher_list_by_id, str, ctx->cert); + /* ssl_create_cipher_list may return an empty stack if it was unable to find + * a cipher matching the given rule string (for example if the rule string + * specifies a cipher which has been disabled). This is not an error as far + * as ssl_create_cipher_list is concerned, and hence ctx->cipher_list and + * ctx->cipher_list_by_id has been updated. */ + if (sk == NULL) { + return 0; + } else if (sk_SSL_CIPHER_num(sk) == 0) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_set_cipher_list, SSL_R_NO_CIPHER_MATCH); + return 0; + } -STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, const CBS *cbs) - { - CBS cipher_suites = *cbs; - const SSL_CIPHER *c; - STACK_OF(SSL_CIPHER) *sk; + return 1; +} - if (s->s3) - s->s3->send_connection_binding = 0; +int SSL_CTX_set_cipher_list_tls11(SSL_CTX *ctx, const char *str) { + STACK_OF(SSL_CIPHER) *sk; - if (CBS_len(&cipher_suites) % 2 != 0) - { - OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list, SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST); - return NULL; - } + sk = ssl_create_cipher_list(ctx->method, &ctx->cipher_list_tls11, NULL, str, + ctx->cert); + if (sk == NULL) { + return 0; + } else if (sk_SSL_CIPHER_num(sk) == 0) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_set_cipher_list_tls11, + SSL_R_NO_CIPHER_MATCH); + return 0; + } - sk = sk_SSL_CIPHER_new_null(); - if (sk == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list, ERR_R_MALLOC_FAILURE); - goto err; - } + return 1; +} - if (!CBS_stow(&cipher_suites, - &s->cert->ciphers_raw, &s->cert->ciphers_rawlen)) - { - OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list, ERR_R_MALLOC_FAILURE); - goto err; - } +/* specify the ciphers to be used by the SSL */ +int SSL_set_cipher_list(SSL *s, const char *str) { + STACK_OF(SSL_CIPHER) *sk; - while (CBS_len(&cipher_suites) > 0) - { - uint16_t cipher_suite; + sk = ssl_create_cipher_list(s->ctx->method, &s->cipher_list, + &s->cipher_list_by_id, str, s->cert); - if (!CBS_get_u16(&cipher_suites, &cipher_suite)) - { - OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list, ERR_R_INTERNAL_ERROR); - goto err; - } + /* see comment in SSL_CTX_set_cipher_list */ + if (sk == NULL) { + return 0; + } else if (sk_SSL_CIPHER_num(sk) == 0) { + OPENSSL_PUT_ERROR(SSL, SSL_set_cipher_list, SSL_R_NO_CIPHER_MATCH); + return 0; + } - /* Check for SCSV. */ - if (s->s3 && cipher_suite == (SSL3_CK_SCSV & 0xffff)) - { - /* SCSV is fatal if renegotiating. */ - if (s->renegotiate) - { - OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list, SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING); - ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE); - goto err; - } - s->s3->send_connection_binding = 1; - continue; - } + return 1; +} - /* Check for FALLBACK_SCSV. */ - if (s->s3 && cipher_suite == (SSL3_CK_FALLBACK_SCSV & 0xffff)) - { - uint16_t max_version = ssl3_get_max_server_version(s); - if (SSL_IS_DTLS(s) ? (uint16_t)s->version > max_version - : (uint16_t)s->version < max_version) - { - OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list, SSL_R_INAPPROPRIATE_FALLBACK); - ssl3_send_alert(s, SSL3_AL_FATAL, SSL3_AD_INAPPROPRIATE_FALLBACK); - goto err; - } - continue; - } +int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, uint8_t *p) { + size_t i; + const SSL_CIPHER *c; + CERT *ct = s->cert; + uint8_t *q; + /* Set disabled masks for this session */ + ssl_set_client_disabled(s); - c = ssl3_get_cipher_by_value(cipher_suite); - if (c != NULL) - { - if (!sk_SSL_CIPHER_push(sk, c)) - { - OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list, ERR_R_MALLOC_FAILURE); - goto err; - } - } - } + if (sk == NULL) { + return 0; + } + q = p; - return sk; + for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) { + c = sk_SSL_CIPHER_value(sk, i); + /* Skip disabled ciphers */ + if (c->algorithm_ssl & ct->mask_ssl || + c->algorithm_mkey & ct->mask_k || + c->algorithm_auth & ct->mask_a) { + continue; + } + s2n(ssl3_get_cipher_value(c), p); + } + + /* If all ciphers were disabled, return the error to the caller. */ + if (p == q) { + return 0; + } + + /* Add SCSVs. */ + if (!s->renegotiate) { + s2n(SSL3_CK_SCSV & 0xffff, p); + } + + if (s->fallback_scsv) { + s2n(SSL3_CK_FALLBACK_SCSV & 0xffff, p); + } + + return p - q; +} + +STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, const CBS *cbs) { + CBS cipher_suites = *cbs; + const SSL_CIPHER *c; + STACK_OF(SSL_CIPHER) * sk; + + if (s->s3) { + s->s3->send_connection_binding = 0; + } + + if (CBS_len(&cipher_suites) % 2 != 0) { + OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list, + SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST); + return NULL; + } + + sk = sk_SSL_CIPHER_new_null(); + if (sk == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!CBS_stow(&cipher_suites, &s->cert->ciphers_raw, + &s->cert->ciphers_rawlen)) { + OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list, ERR_R_MALLOC_FAILURE); + goto err; + } + + while (CBS_len(&cipher_suites) > 0) { + uint16_t cipher_suite; + + if (!CBS_get_u16(&cipher_suites, &cipher_suite)) { + OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list, ERR_R_INTERNAL_ERROR); + goto err; + } + + /* Check for SCSV. */ + if (s->s3 && cipher_suite == (SSL3_CK_SCSV & 0xffff)) { + /* SCSV is fatal if renegotiating. */ + if (s->renegotiate) { + OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list, + SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + goto err; + } + s->s3->send_connection_binding = 1; + continue; + } + + /* Check for FALLBACK_SCSV. */ + if (s->s3 && cipher_suite == (SSL3_CK_FALLBACK_SCSV & 0xffff)) { + uint16_t max_version = ssl3_get_max_server_version(s); + if (SSL_IS_DTLS(s) ? (uint16_t)s->version > max_version + : (uint16_t)s->version < max_version) { + OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list, + SSL_R_INAPPROPRIATE_FALLBACK); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL3_AD_INAPPROPRIATE_FALLBACK); + goto err; + } + continue; + } + + c = ssl3_get_cipher_by_value(cipher_suite); + if (c != NULL && !sk_SSL_CIPHER_push(sk, c)) { + OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list, ERR_R_MALLOC_FAILURE); + goto err; + } + } + + return sk; err: - if (sk != NULL) - sk_SSL_CIPHER_free(sk); - return NULL; - } + if (sk != NULL) { + sk_SSL_CIPHER_free(sk); + } + return NULL; +} -/** return a servername extension value if provided in Client Hello, or NULL. - * So far, only host_name types are defined (RFC 3546). - */ +/* return a servername extension value if provided in Client Hello, or NULL. So + * far, only host_name types are defined (RFC 3546). */ +const char *SSL_get_servername(const SSL *s, const int type) { + if (type != TLSEXT_NAMETYPE_host_name) { + return NULL; + } -const char *SSL_get_servername(const SSL *s, const int type) - { - if (type != TLSEXT_NAMETYPE_host_name) - return NULL; + return s->session && !s->tlsext_hostname ? s->session->tlsext_hostname + : s->tlsext_hostname; +} - return s->session && !s->tlsext_hostname ? - s->session->tlsext_hostname : - s->tlsext_hostname; - } +int SSL_get_servername_type(const SSL *s) { + if (s->session && + (!s->tlsext_hostname ? s->session->tlsext_hostname : s->tlsext_hostname)) { + return TLSEXT_NAMETYPE_host_name; + } -int SSL_get_servername_type(const SSL *s) - { - if (s->session && (!s->tlsext_hostname ? s->session->tlsext_hostname : s->tlsext_hostname)) - return TLSEXT_NAMETYPE_host_name; - return -1; - } + return -1; +} -void SSL_CTX_enable_signed_cert_timestamps(SSL_CTX *ctx) - { - ctx->signed_cert_timestamps_enabled = 1; - } +void SSL_CTX_enable_signed_cert_timestamps(SSL_CTX *ctx) { + ctx->signed_cert_timestamps_enabled = 1; +} -int SSL_enable_signed_cert_timestamps(SSL *ssl) - { - ssl->signed_cert_timestamps_enabled = 1; - return 1; - } +int SSL_enable_signed_cert_timestamps(SSL *ssl) { + ssl->signed_cert_timestamps_enabled = 1; + return 1; +} -void SSL_CTX_enable_ocsp_stapling(SSL_CTX *ctx) - { - ctx->ocsp_stapling_enabled = 1; - } +void SSL_CTX_enable_ocsp_stapling(SSL_CTX *ctx) { + ctx->ocsp_stapling_enabled = 1; +} -int SSL_enable_ocsp_stapling(SSL *ssl) - { - ssl->ocsp_stapling_enabled = 1; - return 1; - } +int SSL_enable_ocsp_stapling(SSL *ssl) { + ssl->ocsp_stapling_enabled = 1; + return 1; +} -void SSL_get0_signed_cert_timestamp_list(const SSL *ssl, const uint8_t **out, size_t *out_len) - { - SSL_SESSION *session = ssl->session; +void SSL_get0_signed_cert_timestamp_list(const SSL *ssl, const uint8_t **out, + size_t *out_len) { + SSL_SESSION *session = ssl->session; - *out_len = 0; - *out = NULL; - if (ssl->server) - return; - if (!session || !session->tlsext_signed_cert_timestamp_list) - return; - *out = session->tlsext_signed_cert_timestamp_list; - *out_len = session->tlsext_signed_cert_timestamp_list_length; - } + *out_len = 0; + *out = NULL; + if (ssl->server || !session || !session->tlsext_signed_cert_timestamp_list) { + return; + } -void SSL_get0_ocsp_response(const SSL *ssl, const uint8_t **out, size_t *out_len) - { - SSL_SESSION *session = ssl->session; + *out = session->tlsext_signed_cert_timestamp_list; + *out_len = session->tlsext_signed_cert_timestamp_list_length; +} - *out_len = 0; - *out = NULL; - if (ssl->server) - return; - if (!session || !session->ocsp_response) - return; - *out = session->ocsp_response; - *out_len = session->ocsp_response_length; - } +void SSL_get0_ocsp_response(const SSL *ssl, const uint8_t **out, + size_t *out_len) { + SSL_SESSION *session = ssl->session; + + *out_len = 0; + *out = NULL; + if (ssl->server || !session || !session->ocsp_response) { + return; + } + *out = session->ocsp_response; + *out_len = session->ocsp_response_length; +} /* SSL_select_next_proto implements the standard protocol selection. It is * expected that this function is called from the callback set by @@ -1634,41 +1575,39 @@ * OPENSSL_NPN_NEGOTIATED if a common protocol was found, or * OPENSSL_NPN_NO_OVERLAP if the fallback case was reached. */ -int SSL_select_next_proto(unsigned char **out, unsigned char *outlen, const unsigned char *server, unsigned int server_len, const unsigned char *client, unsigned int client_len) - { - unsigned int i, j; - const unsigned char *result; - int status = OPENSSL_NPN_UNSUPPORTED; +int SSL_select_next_proto(uint8_t **out, uint8_t *outlen, const uint8_t *server, + unsigned int server_len, const uint8_t *client, + unsigned int client_len) { + unsigned int i, j; + const uint8_t *result; + int status = OPENSSL_NPN_UNSUPPORTED; - /* For each protocol in server preference order, see if we support it. */ - for (i = 0; i < server_len; ) - { - for (j = 0; j < client_len; ) - { - if (server[i] == client[j] && - memcmp(&server[i+1], &client[j+1], server[i]) == 0) - { - /* We found a match */ - result = &server[i]; - status = OPENSSL_NPN_NEGOTIATED; - goto found; - } - j += client[j]; - j++; - } - i += server[i]; - i++; - } + /* For each protocol in server preference order, see if we support it. */ + for (i = 0; i < server_len;) { + for (j = 0; j < client_len;) { + if (server[i] == client[j] && + memcmp(&server[i + 1], &client[j + 1], server[i]) == 0) { + /* We found a match */ + result = &server[i]; + status = OPENSSL_NPN_NEGOTIATED; + goto found; + } + j += client[j]; + j++; + } + i += server[i]; + i++; + } - /* There's no overlap between our protocols and the server's list. */ - result = client; - status = OPENSSL_NPN_NO_OVERLAP; + /* There's no overlap between our protocols and the server's list. */ + result = client; + status = OPENSSL_NPN_NO_OVERLAP; - found: - *out = (unsigned char *) result + 1; - *outlen = result[0]; - return status; - } +found: + *out = (uint8_t *)result + 1; + *outlen = result[0]; + return status; +} /* SSL_get0_next_proto_negotiated sets *data and *len to point to the client's * requested protocol for this connection and returns 0. If the client didn't @@ -1676,16 +1615,15 @@ * * Note that the client can request any protocol it chooses. The value returned * from this function need not be a member of the list of supported protocols - * provided by the callback. - */ -void SSL_get0_next_proto_negotiated(const SSL *s, const uint8_t **data, unsigned *len) - { - *data = s->next_proto_negotiated; - if (!*data) { - *len = 0; - } else { - *len = s->next_proto_negotiated_len; - } + * provided by the callback. */ +void SSL_get0_next_proto_negotiated(const SSL *s, const uint8_t **data, + unsigned *len) { + *data = s->next_proto_negotiated; + if (!*data) { + *len = 0; + } else { + *len = s->next_proto_negotiated_len; + } } /* SSL_CTX_set_next_protos_advertised_cb sets a callback that is called when a @@ -1695,13 +1633,15 @@ * not be modified, but one should assume that the SSL* keeps a reference to * it. * - * The callback should return SSL_TLSEXT_ERR_OK if it wishes to advertise. Otherwise, no - * such extension will be included in the ServerHello. */ -void SSL_CTX_set_next_protos_advertised_cb(SSL_CTX *ctx, int (*cb) (SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg), void *arg) - { - ctx->next_protos_advertised_cb = cb; - ctx->next_protos_advertised_cb_arg = arg; - } + * The callback should return SSL_TLSEXT_ERR_OK if it wishes to advertise. + * Otherwise, no such extension will be included in the ServerHello. */ +void SSL_CTX_set_next_protos_advertised_cb( + SSL_CTX *ctx, + int (*cb)(SSL *ssl, const uint8_t **out, unsigned int *outlen, void *arg), + void *arg) { + ctx->next_protos_advertised_cb = cb; + ctx->next_protos_advertised_cb_arg = arg; +} /* SSL_CTX_set_next_proto_select_cb sets a callback that is called when a * client needs to select a protocol from the server's provided list. |out| @@ -1713,1582 +1653,1503 @@ * The client must select a protocol. It is fatal to the connection if this * callback returns a value other than SSL_TLSEXT_ERR_OK. */ -void SSL_CTX_set_next_proto_select_cb(SSL_CTX *ctx, int (*cb) (SSL *s, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg), void *arg) - { - ctx->next_proto_select_cb = cb; - ctx->next_proto_select_cb_arg = arg; - } +void SSL_CTX_set_next_proto_select_cb( + SSL_CTX *ctx, int (*cb)(SSL *s, uint8_t **out, uint8_t *outlen, + const uint8_t *in, unsigned int inlen, void *arg), + void *arg) { + ctx->next_proto_select_cb = cb; + ctx->next_proto_select_cb_arg = arg; +} /* SSL_CTX_set_alpn_protos sets the ALPN protocol list on |ctx| to |protos|. * |protos| must be in wire-format (i.e. a series of non-empty, 8-bit * length-prefixed strings). * * Returns 0 on success. */ -int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char* protos, - unsigned protos_len) - { - if (ctx->alpn_client_proto_list) - OPENSSL_free(ctx->alpn_client_proto_list); +int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const uint8_t *protos, + unsigned protos_len) { + if (ctx->alpn_client_proto_list) { + OPENSSL_free(ctx->alpn_client_proto_list); + } - ctx->alpn_client_proto_list = BUF_memdup(protos, protos_len); - if (!ctx->alpn_client_proto_list) - return 1; - ctx->alpn_client_proto_list_len = protos_len; + ctx->alpn_client_proto_list = BUF_memdup(protos, protos_len); + if (!ctx->alpn_client_proto_list) { + return 1; + } + ctx->alpn_client_proto_list_len = protos_len; - return 0; - } + return 0; +} /* SSL_set_alpn_protos sets the ALPN protocol list on |ssl| to |protos|. * |protos| must be in wire-format (i.e. a series of non-empty, 8-bit * length-prefixed strings). * * Returns 0 on success. */ -int SSL_set_alpn_protos(SSL *ssl, const unsigned char* protos, - unsigned protos_len) - { - if (ssl->alpn_client_proto_list) - OPENSSL_free(ssl->alpn_client_proto_list); +int SSL_set_alpn_protos(SSL *ssl, const uint8_t *protos, unsigned protos_len) { + if (ssl->alpn_client_proto_list) { + OPENSSL_free(ssl->alpn_client_proto_list); + } - ssl->alpn_client_proto_list = BUF_memdup(protos, protos_len); - if (!ssl->alpn_client_proto_list) - return 1; - ssl->alpn_client_proto_list_len = protos_len; + ssl->alpn_client_proto_list = BUF_memdup(protos, protos_len); + if (!ssl->alpn_client_proto_list) { + return 1; + } + ssl->alpn_client_proto_list_len = protos_len; - return 0; - } + return 0; +} /* SSL_CTX_set_alpn_select_cb sets a callback function on |ctx| that is called * during ClientHello processing in order to select an ALPN protocol from the * client's list of offered protocols. */ -void SSL_CTX_set_alpn_select_cb(SSL_CTX* ctx, - int (*cb) (SSL *ssl, - const unsigned char **out, - unsigned char *outlen, - const unsigned char *in, - unsigned int inlen, - void *arg), - void *arg) - { - ctx->alpn_select_cb = cb; - ctx->alpn_select_cb_arg = arg; - } +void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx, + int (*cb)(SSL *ssl, const uint8_t **out, + uint8_t *outlen, const uint8_t *in, + unsigned int inlen, void *arg), + void *arg) { + ctx->alpn_select_cb = cb; + ctx->alpn_select_cb_arg = arg; +} /* SSL_get0_alpn_selected gets the selected ALPN protocol (if any) from |ssl|. * On return it sets |*data| to point to |*len| bytes of protocol name (not * including the leading length-prefix byte). If the server didn't respond with * a negotiated protocol then |*len| will be zero. */ -void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data, - unsigned *len) - { - *data = NULL; - if (ssl->s3) - *data = ssl->s3->alpn_selected; - if (*data == NULL) - *len = 0; - else - *len = ssl->s3->alpn_selected_len; - } +void SSL_get0_alpn_selected(const SSL *ssl, const uint8_t **data, + unsigned *len) { + *data = NULL; + if (ssl->s3) { + *data = ssl->s3->alpn_selected; + } + if (*data == NULL) { + *len = 0; + } else { + *len = ssl->s3->alpn_selected_len; + } +} -int SSL_export_keying_material(SSL *s, unsigned char *out, size_t olen, - const char *label, size_t llen, const unsigned char *p, size_t plen, - int use_context) - { - if (s->version < TLS1_VERSION) - return -1; +int SSL_export_keying_material(SSL *s, uint8_t *out, size_t olen, + const char *label, size_t llen, const uint8_t *p, + size_t plen, int use_context) { + if (s->version < TLS1_VERSION) { + return -1; + } - return s->enc_method->export_keying_material(s, out, olen, label, - llen, p, plen, - use_context); - } + return s->enc_method->export_keying_material(s, out, olen, label, llen, p, + plen, use_context); +} -static uint32_t ssl_session_hash(const SSL_SESSION *a) - { - uint32_t hash = ((uint32_t) a->session_id[0]) || - ((uint32_t) a->session_id[1] << 8) || - ((uint32_t) a->session_id[2] << 16) || - ((uint32_t) a->session_id[3] << 24); +static uint32_t ssl_session_hash(const SSL_SESSION *a) { + uint32_t hash = + ((uint32_t)a->session_id[0]) || + ((uint32_t)a->session_id[1] << 8) || + ((uint32_t)a->session_id[2] << 16) || + ((uint32_t)a->session_id[3] << 24); - return hash; - } + return hash; +} /* NB: If this function (or indeed the hash function which uses a sort of * coarser function than this one) is changed, ensure * SSL_CTX_has_matching_session_id() is checked accordingly. It relies on being * able to construct an SSL_SESSION that will collide with any existing session * with a matching session ID. */ -static int ssl_session_cmp(const SSL_SESSION *a, const SSL_SESSION *b) - { - if (a->ssl_version != b->ssl_version) - return(1); - if (a->session_id_length != b->session_id_length) - return(1); - return(memcmp(a->session_id,b->session_id,a->session_id_length)); - } +static int ssl_session_cmp(const SSL_SESSION *a, const SSL_SESSION *b) { + if (a->ssl_version != b->ssl_version) { + return 1; + } -SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) - { - SSL_CTX *ret=NULL; + if (a->session_id_length != b->session_id_length) { + return 1; + } - if (meth == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_new, SSL_R_NULL_SSL_METHOD_PASSED); - return(NULL); - } + return memcmp(a->session_id, b->session_id, a->session_id_length); +} - if (SSL_get_ex_data_X509_STORE_CTX_idx() < 0) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_new, SSL_R_X509_VERIFICATION_SETUP_PROBLEMS); - goto err; - } - ret=(SSL_CTX *)OPENSSL_malloc(sizeof(SSL_CTX)); - if (ret == NULL) - goto err; +SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) { + SSL_CTX *ret = NULL; - memset(ret,0,sizeof(SSL_CTX)); + if (meth == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_new, SSL_R_NULL_SSL_METHOD_PASSED); + return NULL; + } - ret->method = meth->method; + if (SSL_get_ex_data_X509_STORE_CTX_idx() < 0) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_new, SSL_R_X509_VERIFICATION_SETUP_PROBLEMS); + goto err; + } - ret->cert_store=NULL; - ret->session_cache_mode=SSL_SESS_CACHE_SERVER; - ret->session_cache_size=SSL_SESSION_CACHE_MAX_SIZE_DEFAULT; - ret->session_cache_head=NULL; - ret->session_cache_tail=NULL; + ret = (SSL_CTX *)OPENSSL_malloc(sizeof(SSL_CTX)); + if (ret == NULL) { + goto err; + } - /* We take the system default */ - ret->session_timeout = SSL_DEFAULT_SESSION_TIMEOUT; + memset(ret, 0, sizeof(SSL_CTX)); - ret->new_session_cb=0; - ret->remove_session_cb=0; - ret->get_session_cb=0; - ret->generate_session_id=0; + ret->method = meth->method; - memset((char *)&ret->stats,0,sizeof(ret->stats)); + ret->cert_store = NULL; + ret->session_cache_mode = SSL_SESS_CACHE_SERVER; + ret->session_cache_size = SSL_SESSION_CACHE_MAX_SIZE_DEFAULT; + ret->session_cache_head = NULL; + ret->session_cache_tail = NULL; - ret->references=1; - ret->quiet_shutdown=0; + /* We take the system default */ + ret->session_timeout = SSL_DEFAULT_SESSION_TIMEOUT; - ret->info_callback=NULL; + ret->new_session_cb = 0; + ret->remove_session_cb = 0; + ret->get_session_cb = 0; + ret->generate_session_id = 0; - ret->app_verify_callback=0; - ret->app_verify_arg=NULL; + memset((char *)&ret->stats, 0, sizeof(ret->stats)); - ret->max_cert_list=SSL_MAX_CERT_LIST_DEFAULT; - ret->read_ahead=0; - ret->msg_callback=0; - ret->msg_callback_arg=NULL; - ret->verify_mode=SSL_VERIFY_NONE; -#if 0 - ret->verify_depth=-1; /* Don't impose a limit (but x509_lu.c does) */ -#endif - ret->sid_ctx_length=0; - ret->default_verify_callback=NULL; - if ((ret->cert=ssl_cert_new()) == NULL) - goto err; + ret->references = 1; + ret->quiet_shutdown = 0; - ret->default_passwd_callback=0; - ret->default_passwd_callback_userdata=NULL; - ret->client_cert_cb=0; - ret->app_gen_cookie_cb=0; - ret->app_verify_cookie_cb=0; + ret->info_callback = NULL; - ret->sessions=lh_SSL_SESSION_new(ssl_session_hash, ssl_session_cmp); - if (ret->sessions == NULL) goto err; - ret->cert_store=X509_STORE_new(); - if (ret->cert_store == NULL) goto err; + ret->app_verify_callback = 0; + ret->app_verify_arg = NULL; - ssl_create_cipher_list(ret->method, - &ret->cipher_list,&ret->cipher_list_by_id, - SSL_DEFAULT_CIPHER_LIST, ret->cert); - if (ret->cipher_list == NULL - || sk_SSL_CIPHER_num(ret->cipher_list->ciphers) <= 0) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_new, SSL_R_LIBRARY_HAS_NO_CIPHERS); - goto err2; - } + ret->max_cert_list = SSL_MAX_CERT_LIST_DEFAULT; + ret->read_ahead = 0; + ret->msg_callback = 0; + ret->msg_callback_arg = NULL; + ret->verify_mode = SSL_VERIFY_NONE; + ret->sid_ctx_length = 0; + ret->default_verify_callback = NULL; + ret->cert = ssl_cert_new(); + if (ret->cert == NULL) { + goto err; + } - ret->param = X509_VERIFY_PARAM_new(); - if (!ret->param) - goto err; + ret->default_passwd_callback = 0; + ret->default_passwd_callback_userdata = NULL; + ret->client_cert_cb = 0; + ret->app_gen_cookie_cb = 0; + ret->app_verify_cookie_cb = 0; - if ((ret->client_CA=sk_X509_NAME_new_null()) == NULL) - goto err; + ret->sessions = lh_SSL_SESSION_new(ssl_session_hash, ssl_session_cmp); + if (ret->sessions == NULL) { + goto err; + } + ret->cert_store = X509_STORE_new(); + if (ret->cert_store == NULL) { + goto err; + } - CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_CTX, ret, &ret->ex_data); + ssl_create_cipher_list(ret->method, &ret->cipher_list, + &ret->cipher_list_by_id, SSL_DEFAULT_CIPHER_LIST, + ret->cert); + if (ret->cipher_list == NULL || + sk_SSL_CIPHER_num(ret->cipher_list->ciphers) <= 0) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_new, SSL_R_LIBRARY_HAS_NO_CIPHERS); + goto err2; + } - ret->extra_certs=NULL; + ret->param = X509_VERIFY_PARAM_new(); + if (!ret->param) { + goto err; + } - ret->max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH; + ret->client_CA = sk_X509_NAME_new_null(); + if (ret->client_CA == NULL) { + goto err; + } - ret->tlsext_servername_callback = 0; - ret->tlsext_servername_arg = NULL; - /* Setup RFC4507 ticket keys */ - if (!RAND_bytes(ret->tlsext_tick_key_name, 16) || - !RAND_bytes(ret->tlsext_tick_hmac_key, 16) || - !RAND_bytes(ret->tlsext_tick_aes_key, 16)) - ret->options |= SSL_OP_NO_TICKET; + CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_CTX, ret, &ret->ex_data); - ret->tlsext_status_cb = 0; - ret->tlsext_status_arg = NULL; + ret->extra_certs = NULL; - ret->next_protos_advertised_cb = 0; - ret->next_proto_select_cb = 0; - ret->psk_identity_hint=NULL; - ret->psk_client_callback=NULL; - ret->psk_server_callback=NULL; + ret->max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH; - /* Default is to connect to non-RI servers. When RI is more widely - * deployed might change this. - */ - ret->options |= SSL_OP_LEGACY_SERVER_CONNECT; + ret->tlsext_servername_callback = 0; + ret->tlsext_servername_arg = NULL; + /* Setup RFC4507 ticket keys */ + if (!RAND_bytes(ret->tlsext_tick_key_name, 16) || + !RAND_bytes(ret->tlsext_tick_hmac_key, 16) || + !RAND_bytes(ret->tlsext_tick_aes_key, 16)) { + ret->options |= SSL_OP_NO_TICKET; + } - /* Lock the SSL_CTX to the specified version, for compatibility with - * legacy uses of SSL_METHOD. */ - if (meth->version != 0) - { - SSL_CTX_set_max_version(ret, meth->version); - SSL_CTX_set_min_version(ret, meth->version); - } + ret->tlsext_status_cb = 0; + ret->tlsext_status_arg = NULL; - return(ret); + ret->next_protos_advertised_cb = 0; + ret->next_proto_select_cb = 0; + ret->psk_identity_hint = NULL; + ret->psk_client_callback = NULL; + ret->psk_server_callback = NULL; + + /* Default is to connect to non-RI servers. When RI is more widely deployed + * might change this. */ + ret->options |= SSL_OP_LEGACY_SERVER_CONNECT; + + /* Lock the SSL_CTX to the specified version, for compatibility with legacy + * uses of SSL_METHOD. */ + if (meth->version != 0) { + SSL_CTX_set_max_version(ret, meth->version); + SSL_CTX_set_min_version(ret, meth->version); + } + + return ret; + err: - OPENSSL_PUT_ERROR(SSL, SSL_CTX_new, ERR_R_MALLOC_FAILURE); + OPENSSL_PUT_ERROR(SSL, SSL_CTX_new, ERR_R_MALLOC_FAILURE); err2: - if (ret != NULL) SSL_CTX_free(ret); - return(NULL); - } + if (ret != NULL) { + SSL_CTX_free(ret); + } + return NULL; +} +void SSL_CTX_free(SSL_CTX *a) { + int i; -void SSL_CTX_free(SSL_CTX *a) - { - int i; + if (a == NULL) { + return; + } - if (a == NULL) return; + i = CRYPTO_add(&a->references, -1, CRYPTO_LOCK_SSL_CTX); + if (i > 0) { + return; + } - i=CRYPTO_add(&a->references,-1,CRYPTO_LOCK_SSL_CTX); -#ifdef REF_PRINT - REF_PRINT("SSL_CTX",a); -#endif - if (i > 0) return; -#ifdef REF_CHECK - if (i < 0) - { - fprintf(stderr,"SSL_CTX_free, bad reference count\n"); - abort(); /* ok */ - } -#endif + if (a->param) { + X509_VERIFY_PARAM_free(a->param); + } - if (a->param) - X509_VERIFY_PARAM_free(a->param); + /* Free internal session cache. However: the remove_cb() may reference the + * ex_data of SSL_CTX, thus the ex_data store can only be removed after the + * sessions were flushed. As the ex_data handling routines might also touch + * the session cache, the most secure solution seems to be: empty (flush) the + * cache, then free ex_data, then finally free the cache. (See ticket + * [openssl.org #212].) */ + if (a->sessions != NULL) { + SSL_CTX_flush_sessions(a, 0); + } - /* - * Free internal session cache. However: the remove_cb() may reference - * the ex_data of SSL_CTX, thus the ex_data store can only be removed - * after the sessions were flushed. - * As the ex_data handling routines might also touch the session cache, - * the most secure solution seems to be: empty (flush) the cache, then - * free ex_data, then finally free the cache. - * (See ticket [openssl.org #212].) - */ - if (a->sessions != NULL) - SSL_CTX_flush_sessions(a,0); + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_CTX, a, &a->ex_data); - CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_CTX, a, &a->ex_data); + if (a->sessions != NULL) { + lh_SSL_SESSION_free(a->sessions); + } + if (a->cert_store != NULL) { + X509_STORE_free(a->cert_store); + } + if (a->cipher_list != NULL) { + ssl_cipher_preference_list_free(a->cipher_list); + } + if (a->cipher_list_by_id != NULL) { + sk_SSL_CIPHER_free(a->cipher_list_by_id); + } + if (a->cipher_list_tls11 != NULL) { + ssl_cipher_preference_list_free(a->cipher_list_tls11); + } + if (a->cert != NULL) { + ssl_cert_free(a->cert); + } + if (a->client_CA != NULL) { + sk_X509_NAME_pop_free(a->client_CA, X509_NAME_free); + } + if (a->extra_certs != NULL) { + sk_X509_pop_free(a->extra_certs, X509_free); + } + if (a->srtp_profiles) { + sk_SRTP_PROTECTION_PROFILE_free(a->srtp_profiles); + } + if (a->psk_identity_hint) { + OPENSSL_free(a->psk_identity_hint); + } + if (a->tlsext_ecpointformatlist) { + OPENSSL_free(a->tlsext_ecpointformatlist); + } + if (a->tlsext_ellipticcurvelist) { + OPENSSL_free(a->tlsext_ellipticcurvelist); + } + if (a->alpn_client_proto_list != NULL) { + OPENSSL_free(a->alpn_client_proto_list); + } + if (a->tlsext_channel_id_private) { + EVP_PKEY_free(a->tlsext_channel_id_private); + } + if (a->keylog_bio) { + BIO_free(a->keylog_bio); + } - if (a->sessions != NULL) - lh_SSL_SESSION_free(a->sessions); + OPENSSL_free(a); +} - if (a->cert_store != NULL) - X509_STORE_free(a->cert_store); - if (a->cipher_list != NULL) - ssl_cipher_preference_list_free(a->cipher_list); - if (a->cipher_list_by_id != NULL) - sk_SSL_CIPHER_free(a->cipher_list_by_id); - if (a->cipher_list_tls11 != NULL) - ssl_cipher_preference_list_free(a->cipher_list_tls11); - if (a->cert != NULL) - ssl_cert_free(a->cert); - if (a->client_CA != NULL) - sk_X509_NAME_pop_free(a->client_CA,X509_NAME_free); - if (a->extra_certs != NULL) - sk_X509_pop_free(a->extra_certs,X509_free); +void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb) { + ctx->default_passwd_callback = cb; +} - if (a->srtp_profiles) - sk_SRTP_PROTECTION_PROFILE_free(a->srtp_profiles); +void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u) { + ctx->default_passwd_callback_userdata = u; +} - if (a->psk_identity_hint) - OPENSSL_free(a->psk_identity_hint); +void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, + int (*cb)(X509_STORE_CTX *, void *), + void *arg) { + ctx->app_verify_callback = cb; + ctx->app_verify_arg = arg; +} - if (a->tlsext_ecpointformatlist) - OPENSSL_free(a->tlsext_ecpointformatlist); - if (a->tlsext_ellipticcurvelist) - OPENSSL_free(a->tlsext_ellipticcurvelist); - if (a->alpn_client_proto_list != NULL) - OPENSSL_free(a->alpn_client_proto_list); +void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, + int (*cb)(int, X509_STORE_CTX *)) { + ctx->verify_mode = mode; + ctx->default_verify_callback = cb; +} - if (a->tlsext_channel_id_private) - EVP_PKEY_free(a->tlsext_channel_id_private); +void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth) { + X509_VERIFY_PARAM_set_depth(ctx->param, depth); +} - if (a->keylog_bio) - BIO_free(a->keylog_bio); +void SSL_CTX_set_cert_cb(SSL_CTX *c, int (*cb)(SSL *ssl, void *arg), + void *arg) { + ssl_cert_set_cert_cb(c->cert, cb, arg); +} - OPENSSL_free(a); - } +void SSL_set_cert_cb(SSL *s, int (*cb)(SSL *ssl, void *arg), void *arg) { + ssl_cert_set_cert_cb(s->cert, cb, arg); +} -void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb) - { - ctx->default_passwd_callback=cb; - } - -void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx,void *u) - { - ctx->default_passwd_callback_userdata=u; - } - -void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*cb)(X509_STORE_CTX *,void *), void *arg) - { - ctx->app_verify_callback=cb; - ctx->app_verify_arg=arg; - } - -void SSL_CTX_set_verify(SSL_CTX *ctx,int mode,int (*cb)(int, X509_STORE_CTX *)) - { - ctx->verify_mode=mode; - ctx->default_verify_callback=cb; - } - -void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth) - { - X509_VERIFY_PARAM_set_depth(ctx->param, depth); - } - -void SSL_CTX_set_cert_cb(SSL_CTX *c, int (*cb)(SSL *ssl, void *arg), void *arg) - { - ssl_cert_set_cert_cb(c->cert, cb, arg); - } - -void SSL_set_cert_cb(SSL *s, int (*cb)(SSL *ssl, void *arg), void *arg) - { - ssl_cert_set_cert_cb(s->cert, cb, arg); - } - -static int ssl_has_key(SSL *s, size_t idx) - { - CERT_PKEY *cpk = &s->cert->pkeys[idx]; - return cpk->x509 && cpk->privatekey; - } +static int ssl_has_key(SSL *s, size_t idx) { + CERT_PKEY *cpk = &s->cert->pkeys[idx]; + return cpk->x509 && cpk->privatekey; +} void ssl_get_compatible_server_ciphers(SSL *s, unsigned long *out_mask_k, - unsigned long *out_mask_a) - { - CERT *c = s->cert; - int rsa_enc, rsa_sign, dh_tmp; - unsigned long mask_k, mask_a; - int have_ecc_cert, ecdsa_ok; - int have_ecdh_tmp; - X509 *x; + unsigned long *out_mask_a) { + CERT *c = s->cert; + int rsa_enc, rsa_sign, dh_tmp; + unsigned long mask_k, mask_a; + int have_ecc_cert, ecdsa_ok; + int have_ecdh_tmp; + X509 *x; - if (c == NULL) - { - /* TODO(davidben): Is this codepath possible? */ - *out_mask_k = 0; - *out_mask_a = 0; - return; - } + if (c == NULL) { + /* TODO(davidben): Is this codepath possible? */ + *out_mask_k = 0; + *out_mask_a = 0; + return; + } - dh_tmp = (c->dh_tmp != NULL || c->dh_tmp_cb != NULL); + dh_tmp = (c->dh_tmp != NULL || c->dh_tmp_cb != NULL); - have_ecdh_tmp = (c->ecdh_tmp || c->ecdh_tmp_cb || c->ecdh_tmp_auto); - rsa_enc = ssl_has_key(s, SSL_PKEY_RSA_ENC); - rsa_sign = ssl_has_key(s, SSL_PKEY_RSA_SIGN); - have_ecc_cert = ssl_has_key(s, SSL_PKEY_ECC); - mask_k = 0; - mask_a = 0; + have_ecdh_tmp = (c->ecdh_tmp || c->ecdh_tmp_cb || c->ecdh_tmp_auto); + rsa_enc = ssl_has_key(s, SSL_PKEY_RSA_ENC); + rsa_sign = ssl_has_key(s, SSL_PKEY_RSA_SIGN); + have_ecc_cert = ssl_has_key(s, SSL_PKEY_ECC); + mask_k = 0; + mask_a = 0; - if (rsa_enc) - mask_k |= SSL_kRSA; + if (rsa_enc) { + mask_k |= SSL_kRSA; + } + if (dh_tmp) { + mask_k |= SSL_kEDH; + } + if (rsa_enc || rsa_sign) { + mask_a |= SSL_aRSA; + } - if (dh_tmp) - mask_k |= SSL_kEDH; + mask_a |= SSL_aNULL; - if (rsa_enc || rsa_sign) - { - mask_a |= SSL_aRSA; - } + /* An ECC certificate may be usable for ECDSA cipher suites depending on the + * key usage extension and on the client's curve preferences. */ + if (have_ecc_cert) { + x = c->pkeys[SSL_PKEY_ECC].x509; + /* This call populates extension flags (ex_flags). */ + X509_check_purpose(x, -1, 0); + ecdsa_ok = (x->ex_flags & EXFLAG_KUSAGE) + ? (x->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE) + : 1; + if (!tls1_check_ec_cert(s, x)) { + ecdsa_ok = 0; + } + if (ecdsa_ok) { + mask_a |= SSL_aECDSA; + } + } - mask_a |= SSL_aNULL; + /* If we are considering an ECC cipher suite that uses an ephemeral EC + * key, check it. */ + if (have_ecdh_tmp && tls1_check_ec_tmp_key(s)) { + mask_k |= SSL_kEECDH; + } - /* An ECC certificate may be usable for ECDSA cipher suites depending on - * the key usage extension and on the client's curve preferences. */ - if (have_ecc_cert) - { - x = c->pkeys[SSL_PKEY_ECC].x509; - /* This call populates extension flags (ex_flags) */ - X509_check_purpose(x, -1, 0); - ecdsa_ok = (x->ex_flags & EXFLAG_KUSAGE) ? - (x->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE) : 1; - if (!tls1_check_ec_cert(s, x)) - ecdsa_ok = 0; - if (ecdsa_ok) - { - mask_a |= SSL_aECDSA; - } - } + /* PSK requires a server callback. */ + if (s->psk_server_callback != NULL) { + mask_k |= SSL_kPSK; + mask_a |= SSL_aPSK; + } - /* If we are considering an ECC cipher suite that uses an ephemeral EC - * key, check it. */ - if (have_ecdh_tmp && tls1_check_ec_tmp_key(s)) - { - mask_k |= SSL_kEECDH; - } - - /* PSK requires a server callback. */ - if (s->psk_server_callback != NULL) - { - mask_k |= SSL_kPSK; - mask_a |= SSL_aPSK; - } - - *out_mask_k = mask_k; - *out_mask_a = mask_a; - } + *out_mask_k = mask_k; + *out_mask_a = mask_a; +} /* This handy macro borrowed from crypto/x509v3/v3_purp.c */ #define ku_reject(x, usage) \ - (((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage))) + (((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage))) +int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s) { + unsigned long alg_a; + int signature_nid = 0, md_nid = 0, pk_nid = 0; + const SSL_CIPHER *cs = s->s3->tmp.new_cipher; -int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s) - { - unsigned long alg_a; - int signature_nid = 0, md_nid = 0, pk_nid = 0; - const SSL_CIPHER *cs = s->s3->tmp.new_cipher; + alg_a = cs->algorithm_auth; - alg_a = cs->algorithm_auth; + /* This call populates the ex_flags field correctly */ + X509_check_purpose(x, -1, 0); + if (x->sig_alg && x->sig_alg->algorithm) { + signature_nid = OBJ_obj2nid(x->sig_alg->algorithm); + OBJ_find_sigid_algs(signature_nid, &md_nid, &pk_nid); + } + if (alg_a & SSL_aECDSA) { + /* key usage, if present, must allow signing */ + if (ku_reject(x, X509v3_KU_DIGITAL_SIGNATURE)) { + OPENSSL_PUT_ERROR(SSL, ssl_check_srvr_ecc_cert_and_alg, + SSL_R_ECC_CERT_NOT_FOR_SIGNING); + return 0; + } + } - /* This call populates the ex_flags field correctly */ - X509_check_purpose(x, -1, 0); - if ((x->sig_alg) && (x->sig_alg->algorithm)) - { - signature_nid = OBJ_obj2nid(x->sig_alg->algorithm); - OBJ_find_sigid_algs(signature_nid, &md_nid, &pk_nid); - } - if (alg_a & SSL_aECDSA) - { - /* key usage, if present, must allow signing */ - if (ku_reject(x, X509v3_KU_DIGITAL_SIGNATURE)) - { - OPENSSL_PUT_ERROR(SSL, ssl_check_srvr_ecc_cert_and_alg, SSL_R_ECC_CERT_NOT_FOR_SIGNING); - return 0; - } - } + return 1; /* all checks are ok */ +} - return 1; /* all checks are ok */ - } +static int ssl_get_server_cert_index(const SSL *s) { + int idx; + idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher); + if (idx == SSL_PKEY_RSA_ENC && !s->cert->pkeys[SSL_PKEY_RSA_ENC].x509) { + idx = SSL_PKEY_RSA_SIGN; + } + if (idx == -1) { + OPENSSL_PUT_ERROR(SSL, ssl_get_server_cert_index, ERR_R_INTERNAL_ERROR); + } + return idx; +} +CERT_PKEY *ssl_get_server_send_pkey(const SSL *s) { + int i = ssl_get_server_cert_index(s); -static int ssl_get_server_cert_index(const SSL *s) - { - int idx; - idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher); - if (idx == SSL_PKEY_RSA_ENC && !s->cert->pkeys[SSL_PKEY_RSA_ENC].x509) - idx = SSL_PKEY_RSA_SIGN; - if (idx == -1) - OPENSSL_PUT_ERROR(SSL, ssl_get_server_cert_index, ERR_R_INTERNAL_ERROR); - return idx; - } + /* This may or may not be an error. */ + if (i < 0) { + return NULL; + } -CERT_PKEY *ssl_get_server_send_pkey(const SSL *s) - { - int i = ssl_get_server_cert_index(s); + /* May be NULL. */ + return &s->cert->pkeys[i]; +} - /* This may or may not be an error. */ - if (i < 0) - return NULL; +EVP_PKEY *ssl_get_sign_pkey(SSL *s, const SSL_CIPHER *cipher) { + unsigned long alg_a; + CERT *c; + int idx = -1; - /* May be NULL. */ - return &s->cert->pkeys[i]; - } + alg_a = cipher->algorithm_auth; + c = s->cert; -EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *cipher) - { - unsigned long alg_a; - CERT *c; - int idx = -1; + if (alg_a & SSL_aRSA) { + if (c->pkeys[SSL_PKEY_RSA_SIGN].privatekey != NULL) { + idx = SSL_PKEY_RSA_SIGN; + } else if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey != NULL) { + idx = SSL_PKEY_RSA_ENC; + } + } else if ((alg_a & SSL_aECDSA) && + (c->pkeys[SSL_PKEY_ECC].privatekey != NULL)) { + idx = SSL_PKEY_ECC; + } - alg_a = cipher->algorithm_auth; - c=s->cert; + if (idx == -1) { + OPENSSL_PUT_ERROR(SSL, ssl_get_sign_pkey, ERR_R_INTERNAL_ERROR); + return NULL; + } - if (alg_a & SSL_aRSA) - { - if (c->pkeys[SSL_PKEY_RSA_SIGN].privatekey != NULL) - idx = SSL_PKEY_RSA_SIGN; - else if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey != NULL) - idx = SSL_PKEY_RSA_ENC; - } - else if ((alg_a & SSL_aECDSA) && - (c->pkeys[SSL_PKEY_ECC].privatekey != NULL)) - idx = SSL_PKEY_ECC; - if (idx == -1) - { - OPENSSL_PUT_ERROR(SSL, ssl_get_sign_pkey, ERR_R_INTERNAL_ERROR); - return(NULL); - } - return c->pkeys[idx].privatekey; - } + return c->pkeys[idx].privatekey; +} -void ssl_update_cache(SSL *s,int mode) - { - int i; +void ssl_update_cache(SSL *s, int mode) { + int i; - /* If the session_id_length is 0, we are not supposed to cache it, - * and it would be rather hard to do anyway :-) */ - if (s->session->session_id_length == 0) return; + /* If the session_id_length is 0, we are not supposed to cache it, and it + * would be rather hard to do anyway :-) */ + if (s->session->session_id_length == 0) { + return; + } - i=s->initial_ctx->session_cache_mode; - if ((i & mode) && (!s->hit) - && ((i & SSL_SESS_CACHE_NO_INTERNAL_STORE) - || SSL_CTX_add_session(s->initial_ctx,s->session)) - && (s->initial_ctx->new_session_cb != NULL)) - { - CRYPTO_add(&s->session->references,1,CRYPTO_LOCK_SSL_SESSION); - if (!s->initial_ctx->new_session_cb(s,s->session)) - SSL_SESSION_free(s->session); - } + i = s->initial_ctx->session_cache_mode; + if ((i & mode) && !s->hit && + ((i & SSL_SESS_CACHE_NO_INTERNAL_STORE) || + SSL_CTX_add_session(s->initial_ctx, s->session)) && + s->initial_ctx->new_session_cb != NULL) { + CRYPTO_add(&s->session->references, 1, CRYPTO_LOCK_SSL_SESSION); + if (!s->initial_ctx->new_session_cb(s, s->session)) { + SSL_SESSION_free(s->session); + } + } - /* auto flush every 255 connections */ - if ((!(i & SSL_SESS_CACHE_NO_AUTO_CLEAR)) && - ((i & mode) == mode)) - { - if ( (((mode & SSL_SESS_CACHE_CLIENT) - ?s->initial_ctx->stats.sess_connect_good - :s->initial_ctx->stats.sess_accept_good) & 0xff) == 0xff) - { - SSL_CTX_flush_sessions(s->initial_ctx,(unsigned long)time(NULL)); - } - } - } + /* auto flush every 255 connections */ + if ((!(i & SSL_SESS_CACHE_NO_AUTO_CLEAR)) && ((i & mode) == mode)) { + if ((((mode & SSL_SESS_CACHE_CLIENT) + ? s->initial_ctx->stats.sess_connect_good + : s->initial_ctx->stats.sess_accept_good) & + 0xff) == 0xff) { + SSL_CTX_flush_sessions(s->initial_ctx, (unsigned long)time(NULL)); + } + } +} -int SSL_get_error(const SSL *s,int i) - { - int reason; - unsigned long l; - BIO *bio; +int SSL_get_error(const SSL *s, int i) { + int reason; + unsigned long l; + BIO *bio; - if (i > 0) return(SSL_ERROR_NONE); + if (i > 0) { + return SSL_ERROR_NONE; + } - /* Make things return SSL_ERROR_SYSCALL when doing SSL_do_handshake - * etc, where we do encode the error */ - if ((l=ERR_peek_error()) != 0) - { - if (ERR_GET_LIB(l) == ERR_LIB_SYS) - return(SSL_ERROR_SYSCALL); - else - return(SSL_ERROR_SSL); - } + /* Make things return SSL_ERROR_SYSCALL when doing SSL_do_handshake etc, + * where we do encode the error */ + l = ERR_peek_error(); + if (l != 0) { + if (ERR_GET_LIB(l) == ERR_LIB_SYS) { + return SSL_ERROR_SYSCALL; + } + return SSL_ERROR_SSL; + } - if ((i < 0) && SSL_want_session(s)) - return(SSL_ERROR_PENDING_SESSION); + if (i == 0 && (s->shutdown & SSL_RECEIVED_SHUTDOWN) && + (s->s3->warn_alert == SSL_AD_CLOSE_NOTIFY)) { + return SSL_ERROR_ZERO_RETURN; + } - if ((i < 0) && SSL_want_certificate(s)) - return(SSL_ERROR_PENDING_CERTIFICATE); + assert(i < 0); - if ((i < 0) && SSL_want_read(s)) - { - bio=SSL_get_rbio(s); - if (BIO_should_read(bio)) - return(SSL_ERROR_WANT_READ); - else if (BIO_should_write(bio)) - /* This one doesn't make too much sense ... We never try - * to write to the rbio, and an application program where - * rbio and wbio are separate couldn't even know what it - * should wait for. - * However if we ever set s->rwstate incorrectly - * (so that we have SSL_want_read(s) instead of - * SSL_want_write(s)) and rbio and wbio *are* the same, - * this test works around that bug; so it might be safer - * to keep it. */ - return(SSL_ERROR_WANT_WRITE); - else if (BIO_should_io_special(bio)) - { - reason=BIO_get_retry_reason(bio); - if (reason == BIO_RR_CONNECT) - return(SSL_ERROR_WANT_CONNECT); - else if (reason == BIO_RR_ACCEPT) - return(SSL_ERROR_WANT_ACCEPT); - else - return(SSL_ERROR_SYSCALL); /* unknown */ - } - } + if (SSL_want_session(s)) { + return SSL_ERROR_PENDING_SESSION; + } - if ((i < 0) && SSL_want_write(s)) - { - bio=SSL_get_wbio(s); - if (BIO_should_write(bio)) - return(SSL_ERROR_WANT_WRITE); - else if (BIO_should_read(bio)) - /* See above (SSL_want_read(s) with BIO_should_write(bio)) */ - return(SSL_ERROR_WANT_READ); - else if (BIO_should_io_special(bio)) - { - reason=BIO_get_retry_reason(bio); - if (reason == BIO_RR_CONNECT) - return(SSL_ERROR_WANT_CONNECT); - else if (reason == BIO_RR_ACCEPT) - return(SSL_ERROR_WANT_ACCEPT); - else - return(SSL_ERROR_SYSCALL); - } - } - if ((i < 0) && SSL_want_x509_lookup(s)) - { - return(SSL_ERROR_WANT_X509_LOOKUP); - } - if ((i < 0) && SSL_want_channel_id_lookup(s)) - { - return(SSL_ERROR_WANT_CHANNEL_ID_LOOKUP); - } + if (SSL_want_certificate(s)) { + return SSL_ERROR_PENDING_CERTIFICATE; + } - if (i == 0) - { - if ((s->shutdown & SSL_RECEIVED_SHUTDOWN) && - (s->s3->warn_alert == SSL_AD_CLOSE_NOTIFY)) - return(SSL_ERROR_ZERO_RETURN); - } - return(SSL_ERROR_SYSCALL); - } + if (SSL_want_read(s)) { + bio = SSL_get_rbio(s); + if (BIO_should_read(bio)) { + return SSL_ERROR_WANT_READ; + } -int SSL_do_handshake(SSL *s) - { - int ret=1; + if (BIO_should_write(bio)) { + /* This one doesn't make too much sense ... We never try to write to the + * rbio, and an application program where rbio and wbio are separate + * couldn't even know what it should wait for. However if we ever set + * s->rwstate incorrectly (so that we have SSL_want_read(s) instead of + * SSL_want_write(s)) and rbio and wbio *are* the same, this test works + * around that bug; so it might be safer to keep it. */ + return SSL_ERROR_WANT_WRITE; + } - if (s->handshake_func == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_do_handshake, SSL_R_CONNECTION_TYPE_NOT_SET); - return(-1); - } + if (BIO_should_io_special(bio)) { + reason = BIO_get_retry_reason(bio); + if (reason == BIO_RR_CONNECT) { + return SSL_ERROR_WANT_CONNECT; + } - s->method->ssl_renegotiate_check(s); + if (reason == BIO_RR_ACCEPT) { + return SSL_ERROR_WANT_ACCEPT; + } - if (SSL_in_init(s)) - { - ret=s->handshake_func(s); - } - return(ret); - } + return SSL_ERROR_SYSCALL; /* unknown */ + } + } -void SSL_set_accept_state(SSL *s) - { - s->server=1; - s->shutdown=0; - s->state=SSL_ST_ACCEPT|SSL_ST_BEFORE; - s->handshake_func=s->method->ssl_accept; - /* clear the current cipher */ - ssl_clear_cipher_ctx(s); - ssl_clear_hash_ctx(&s->read_hash); - ssl_clear_hash_ctx(&s->write_hash); - } + if (SSL_want_write(s)) { + bio = SSL_get_wbio(s); + if (BIO_should_write(bio)) { + return SSL_ERROR_WANT_WRITE; + } -void SSL_set_connect_state(SSL *s) - { - s->server=0; - s->shutdown=0; - s->state=SSL_ST_CONNECT|SSL_ST_BEFORE; - s->handshake_func=s->method->ssl_connect; - /* clear the current cipher */ - ssl_clear_cipher_ctx(s); - ssl_clear_hash_ctx(&s->read_hash); - ssl_clear_hash_ctx(&s->write_hash); - } + if (BIO_should_read(bio)) { + /* See above (SSL_want_read(s) with BIO_should_write(bio)) */ + return SSL_ERROR_WANT_READ; + } -int ssl_undefined_function(SSL *s) - { - OPENSSL_PUT_ERROR(SSL, ssl_undefined_function, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return(0); - } + if (BIO_should_io_special(bio)) { + reason = BIO_get_retry_reason(bio); + if (reason == BIO_RR_CONNECT) { + return SSL_ERROR_WANT_CONNECT; + } -int ssl_undefined_void_function(void) - { - OPENSSL_PUT_ERROR(SSL, ssl_undefined_void_function, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return(0); - } + if (reason == BIO_RR_ACCEPT) { + return SSL_ERROR_WANT_ACCEPT; + } -int ssl_undefined_const_function(const SSL *s) - { - OPENSSL_PUT_ERROR(SSL, ssl_undefined_const_function, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return(0); - } + return SSL_ERROR_SYSCALL; + } + } -static const char *ssl_get_version(int version) - { - if (version == TLS1_2_VERSION) - return("TLSv1.2"); - else if (version == TLS1_1_VERSION) - return("TLSv1.1"); - else if (version == TLS1_VERSION) - return("TLSv1"); - else if (version == SSL3_VERSION) - return("SSLv3"); - else - return("unknown"); - } + if (SSL_want_x509_lookup(s)) { + return SSL_ERROR_WANT_X509_LOOKUP; + } -const char *SSL_get_version(const SSL *s) - { - return ssl_get_version(s->version); - } + if (SSL_want_channel_id_lookup(s)) { + return SSL_ERROR_WANT_CHANNEL_ID_LOOKUP; + } -const char *SSL_SESSION_get_version(const SSL_SESSION *sess) - { - return ssl_get_version(sess->ssl_version); - } + return SSL_ERROR_SYSCALL; +} -void ssl_clear_cipher_ctx(SSL *s) - { - if (s->enc_read_ctx != NULL) - { - EVP_CIPHER_CTX_cleanup(s->enc_read_ctx); - OPENSSL_free(s->enc_read_ctx); - s->enc_read_ctx=NULL; - } - if (s->enc_write_ctx != NULL) - { - EVP_CIPHER_CTX_cleanup(s->enc_write_ctx); - OPENSSL_free(s->enc_write_ctx); - s->enc_write_ctx=NULL; - } - if (s->aead_read_ctx != NULL) - { - EVP_AEAD_CTX_cleanup(&s->aead_read_ctx->ctx); - OPENSSL_free(s->aead_read_ctx); - s->aead_read_ctx = NULL; - } - if (s->aead_write_ctx != NULL) - { - EVP_AEAD_CTX_cleanup(&s->aead_write_ctx->ctx); - OPENSSL_free(s->aead_write_ctx); - s->aead_write_ctx = NULL; - } - } +int SSL_do_handshake(SSL *s) { + int ret = 1; -X509 *SSL_get_certificate(const SSL *s) - { - if (s->cert != NULL) - return(s->cert->key->x509); - else - return(NULL); - } + if (s->handshake_func == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_do_handshake, SSL_R_CONNECTION_TYPE_NOT_SET); + return -1; + } -EVP_PKEY *SSL_get_privatekey(const SSL *s) - { - if (s->cert != NULL) - return(s->cert->key->privatekey); - else - return(NULL); - } + s->method->ssl_renegotiate_check(s); -X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx) - { - if (ctx->cert != NULL) - return ctx->cert->key->x509; - else - return NULL; - } + if (SSL_in_init(s)) { + ret = s->handshake_func(s); + } + return ret; +} -EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx) - { - if (ctx->cert != NULL) - return ctx->cert->key->privatekey; - else - return NULL ; - } +void SSL_set_accept_state(SSL *s) { + s->server = 1; + s->shutdown = 0; + s->state = SSL_ST_ACCEPT | SSL_ST_BEFORE; + s->handshake_func = s->method->ssl_accept; + /* clear the current cipher */ + ssl_clear_cipher_ctx(s); + ssl_clear_hash_ctx(&s->read_hash); + ssl_clear_hash_ctx(&s->write_hash); +} -const SSL_CIPHER *SSL_get_current_cipher(const SSL *s) - { - if ((s->session != NULL) && (s->session->cipher != NULL)) - return(s->session->cipher); - return(NULL); - } -const void *SSL_get_current_compression(SSL *s) - { - return NULL; - } -const void *SSL_get_current_expansion(SSL *s) - { - return NULL; - } +void SSL_set_connect_state(SSL *s) { + s->server = 0; + s->shutdown = 0; + s->state = SSL_ST_CONNECT | SSL_ST_BEFORE; + s->handshake_func = s->method->ssl_connect; + /* clear the current cipher */ + ssl_clear_cipher_ctx(s); + ssl_clear_hash_ctx(&s->read_hash); + ssl_clear_hash_ctx(&s->write_hash); +} -int ssl_init_wbio_buffer(SSL *s,int push) - { - BIO *bbio; +int ssl_undefined_function(SSL *s) { + OPENSSL_PUT_ERROR(SSL, ssl_undefined_function, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; +} - if (s->bbio == NULL) - { - bbio=BIO_new(BIO_f_buffer()); - if (bbio == NULL) return(0); - s->bbio=bbio; - } - else - { - bbio=s->bbio; - if (s->bbio == s->wbio) - s->wbio=BIO_pop(s->wbio); - } - (void)BIO_reset(bbio); -/* if (!BIO_set_write_buffer_size(bbio,16*1024)) */ - if (!BIO_set_read_buffer_size(bbio,1)) - { - OPENSSL_PUT_ERROR(SSL, ssl_init_wbio_buffer, ERR_R_BUF_LIB); - return(0); - } - if (push) - { - if (s->wbio != bbio) - s->wbio=BIO_push(bbio,s->wbio); - } - else - { - if (s->wbio == bbio) - s->wbio=BIO_pop(bbio); - } - return(1); - } +int ssl_undefined_void_function(void) { + OPENSSL_PUT_ERROR(SSL, ssl_undefined_void_function, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; +} -void ssl_free_wbio_buffer(SSL *s) - { - if (s->bbio == NULL) return; +int ssl_undefined_const_function(const SSL *s) { + OPENSSL_PUT_ERROR(SSL, ssl_undefined_const_function, + ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; +} - if (s->bbio == s->wbio) - { - /* remove buffering */ - s->wbio=BIO_pop(s->wbio); -#ifdef REF_CHECK /* not the usual REF_CHECK, but this avoids adding one more preprocessor symbol */ - assert(s->wbio != NULL); -#endif - } - BIO_free(s->bbio); - s->bbio=NULL; - } - -void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx,int mode) - { - ctx->quiet_shutdown=mode; - } +static const char *ssl_get_version(int version) { + switch (version) { + case TLS1_2_VERSION: + return "TLSv1.2"; -int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx) - { - return(ctx->quiet_shutdown); - } + case TLS1_1_VERSION: + return "TLSv1.1"; -void SSL_set_quiet_shutdown(SSL *s,int mode) - { - s->quiet_shutdown=mode; - } + case TLS1_VERSION: + return "TLSv1"; -int SSL_get_quiet_shutdown(const SSL *s) - { - return(s->quiet_shutdown); - } + case SSL3_VERSION: + return "SSLv3"; -void SSL_set_shutdown(SSL *s,int mode) - { - s->shutdown=mode; - } + default: + return "unknown"; + } +} -int SSL_get_shutdown(const SSL *s) - { - return(s->shutdown); - } +const char *SSL_get_version(const SSL *s) { + return ssl_get_version(s->version); +} -int SSL_version(const SSL *s) - { - return(s->version); - } +const char *SSL_SESSION_get_version(const SSL_SESSION *sess) { + return ssl_get_version(sess->ssl_version); +} -SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl) - { - return(ssl->ctx); - } +void ssl_clear_cipher_ctx(SSL *s) { + if (s->enc_read_ctx != NULL) { + EVP_CIPHER_CTX_cleanup(s->enc_read_ctx); + OPENSSL_free(s->enc_read_ctx); + s->enc_read_ctx = NULL; + } -SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX* ctx) - { - if (ssl->ctx == ctx) - return ssl->ctx; - if (ctx == NULL) - ctx = ssl->initial_ctx; - if (ssl->cert != NULL) - ssl_cert_free(ssl->cert); - ssl->cert = ssl_cert_dup(ctx->cert); - CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX); - if (ssl->ctx != NULL) - SSL_CTX_free(ssl->ctx); /* decrement reference count */ - ssl->ctx = ctx; + if (s->enc_write_ctx != NULL) { + EVP_CIPHER_CTX_cleanup(s->enc_write_ctx); + OPENSSL_free(s->enc_write_ctx); + s->enc_write_ctx = NULL; + } - ssl->sid_ctx_length = ctx->sid_ctx_length; - assert(ssl->sid_ctx_length <= sizeof(ssl->sid_ctx)); - memcpy(ssl->sid_ctx, ctx->sid_ctx, sizeof(ssl->sid_ctx)); + if (s->aead_read_ctx != NULL) { + EVP_AEAD_CTX_cleanup(&s->aead_read_ctx->ctx); + OPENSSL_free(s->aead_read_ctx); + s->aead_read_ctx = NULL; + } - return(ssl->ctx); - } + if (s->aead_write_ctx != NULL) { + EVP_AEAD_CTX_cleanup(&s->aead_write_ctx->ctx); + OPENSSL_free(s->aead_write_ctx); + s->aead_write_ctx = NULL; + } +} -#ifndef OPENSSL_NO_STDIO -int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx) - { - return(X509_STORE_set_default_paths(ctx->cert_store)); - } +X509 *SSL_get_certificate(const SSL *s) { + if (s->cert != NULL) { + return s->cert->key->x509; + } + + return NULL; +} + +EVP_PKEY *SSL_get_privatekey(const SSL *s) { + if (s->cert != NULL) { + return s->cert->key->privatekey; + } + + return NULL; +} + +X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx) { + if (ctx->cert != NULL) { + return ctx->cert->key->x509; + } + + return NULL; +} + +EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx) { + if (ctx->cert != NULL) { + return ctx->cert->key->privatekey; + } + + return NULL; +} + +const SSL_CIPHER *SSL_get_current_cipher(const SSL *s) { + if (s->session != NULL && s->session->cipher != NULL) { + return s->session->cipher; + } + + return NULL; +} + +const void *SSL_get_current_compression(SSL *s) { return NULL; } + +const void *SSL_get_current_expansion(SSL *s) { return NULL; } + +int ssl_init_wbio_buffer(SSL *s, int push) { + BIO *bbio; + + if (s->bbio == NULL) { + bbio = BIO_new(BIO_f_buffer()); + if (bbio == NULL) { + return 0; + } + s->bbio = bbio; + } else { + bbio = s->bbio; + if (s->bbio == s->wbio) { + s->wbio = BIO_pop(s->wbio); + } + } + + BIO_reset(bbio); + if (!BIO_set_read_buffer_size(bbio, 1)) { + OPENSSL_PUT_ERROR(SSL, ssl_init_wbio_buffer, ERR_R_BUF_LIB); + return 0; + } + + if (push) { + if (s->wbio != bbio) { + s->wbio = BIO_push(bbio, s->wbio); + } + } else { + if (s->wbio == bbio) { + s->wbio = BIO_pop(bbio); + } + } + + return 1; +} + +void ssl_free_wbio_buffer(SSL *s) { + if (s->bbio == NULL) { + return; + } + + if (s->bbio == s->wbio) { + /* remove buffering */ + s->wbio = BIO_pop(s->wbio); + } + + BIO_free(s->bbio); + s->bbio = NULL; +} + +void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx, int mode) { + ctx->quiet_shutdown = mode; +} + +int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx) { + return ctx->quiet_shutdown; +} + +void SSL_set_quiet_shutdown(SSL *s, int mode) { s->quiet_shutdown = mode; } + +int SSL_get_quiet_shutdown(const SSL *s) { return s->quiet_shutdown; } + +void SSL_set_shutdown(SSL *s, int mode) { s->shutdown = mode; } + +int SSL_get_shutdown(const SSL *s) { return s->shutdown; } + +int SSL_version(const SSL *s) { return s->version; } + +SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl) { return ssl->ctx; } + +SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx) { + if (ssl->ctx == ctx) { + return ssl->ctx; + } + + if (ctx == NULL) { + ctx = ssl->initial_ctx; + } + + if (ssl->cert != NULL) { + ssl_cert_free(ssl->cert); + } + + ssl->cert = ssl_cert_dup(ctx->cert); + CRYPTO_add(&ctx->references, 1, CRYPTO_LOCK_SSL_CTX); + if (ssl->ctx != NULL) { + SSL_CTX_free(ssl->ctx); /* decrement reference count */ + } + ssl->ctx = ctx; + + ssl->sid_ctx_length = ctx->sid_ctx_length; + assert(ssl->sid_ctx_length <= sizeof(ssl->sid_ctx)); + memcpy(ssl->sid_ctx, ctx->sid_ctx, sizeof(ssl->sid_ctx)); + + return ssl->ctx; +} + +int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx) { + return X509_STORE_set_default_paths(ctx->cert_store); +} int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, - const char *CApath) - { - return(X509_STORE_load_locations(ctx->cert_store,CAfile,CApath)); - } -#endif + const char *CApath) { + return X509_STORE_load_locations(ctx->cert_store, CAfile, CApath); +} void SSL_set_info_callback(SSL *ssl, - void (*cb)(const SSL *ssl,int type,int val)) - { - ssl->info_callback=cb; - } + void (*cb)(const SSL *ssl, int type, int val)) { + ssl->info_callback = cb; +} -/* One compiler (Diab DCC) doesn't like argument names in returned - function pointer. */ -void (*SSL_get_info_callback(const SSL *ssl))(const SSL * /*ssl*/,int /*type*/,int /*val*/) - { - return ssl->info_callback; - } +void (*SSL_get_info_callback(const SSL *ssl))(const SSL * /*ssl*/, int /*type*/, + int /*val*/) { + return ssl->info_callback; +} -int SSL_state(const SSL *ssl) - { - return(ssl->state); - } +int SSL_state(const SSL *ssl) { return ssl->state; } -void SSL_set_state(SSL *ssl, int state) - { - ssl->state = state; - } +void SSL_set_state(SSL *ssl, int state) { ssl->state = state; } -void SSL_set_verify_result(SSL *ssl,long arg) - { - ssl->verify_result=arg; - } +void SSL_set_verify_result(SSL *ssl, long arg) { ssl->verify_result = arg; } -long SSL_get_verify_result(const SSL *ssl) - { - return(ssl->verify_result); - } +long SSL_get_verify_result(const SSL *ssl) { return ssl->verify_result; } -int SSL_get_ex_new_index(long argl,void *argp,CRYPTO_EX_new *new_func, - CRYPTO_EX_dup *dup_func,CRYPTO_EX_free *free_func) - { - return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, argl, argp, - new_func, dup_func, free_func); - } +int SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) { + return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, argl, argp, new_func, + dup_func, free_func); +} -int SSL_set_ex_data(SSL *s,int idx,void *arg) - { - return(CRYPTO_set_ex_data(&s->ex_data,idx,arg)); - } +int SSL_set_ex_data(SSL *s, int idx, void *arg) { + return CRYPTO_set_ex_data(&s->ex_data, idx, arg); +} -void *SSL_get_ex_data(const SSL *s,int idx) - { - return(CRYPTO_get_ex_data(&s->ex_data,idx)); - } +void *SSL_get_ex_data(const SSL *s, int idx) { + return CRYPTO_get_ex_data(&s->ex_data, idx); +} -int SSL_CTX_get_ex_new_index(long argl,void *argp,CRYPTO_EX_new *new_func, - CRYPTO_EX_dup *dup_func,CRYPTO_EX_free *free_func) - { - return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_CTX, argl, argp, - new_func, dup_func, free_func); - } +int SSL_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func) { + return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_CTX, argl, argp, new_func, + dup_func, free_func); +} -int SSL_CTX_set_ex_data(SSL_CTX *s,int idx,void *arg) - { - return(CRYPTO_set_ex_data(&s->ex_data,idx,arg)); - } +int SSL_CTX_set_ex_data(SSL_CTX *s, int idx, void *arg) { + return CRYPTO_set_ex_data(&s->ex_data, idx, arg); +} -void *SSL_CTX_get_ex_data(const SSL_CTX *s,int idx) - { - return(CRYPTO_get_ex_data(&s->ex_data,idx)); - } +void *SSL_CTX_get_ex_data(const SSL_CTX *s, int idx) { + return CRYPTO_get_ex_data(&s->ex_data, idx); +} -int ssl_ok(SSL *s) - { - return(1); - } +int ssl_ok(SSL *s) { return 1; } -X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *ctx) - { - return(ctx->cert_store); - } +X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *ctx) { + return ctx->cert_store; +} -void SSL_CTX_set_cert_store(SSL_CTX *ctx,X509_STORE *store) - { - if (ctx->cert_store != NULL) - X509_STORE_free(ctx->cert_store); - ctx->cert_store=store; - } +void SSL_CTX_set_cert_store(SSL_CTX *ctx, X509_STORE *store) { + if (ctx->cert_store != NULL) { + X509_STORE_free(ctx->cert_store); + } + ctx->cert_store = store; +} -int SSL_want(const SSL *s) - { - return(s->rwstate); - } +int SSL_want(const SSL *s) { return s->rwstate; } -/*! - * \brief Set the callback for generating temporary RSA keys. - * \param ctx the SSL context. - * \param cb the callback - */ +void SSL_CTX_set_tmp_rsa_callback(SSL_CTX *ctx, + RSA *(*cb)(SSL *ssl, int is_export, + int keylength)) { + SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_TMP_RSA_CB, (void (*)(void))cb); +} -void SSL_CTX_set_tmp_rsa_callback(SSL_CTX *ctx,RSA *(*cb)(SSL *ssl, - int is_export, - int keylength)) - { - SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TMP_RSA_CB,(void (*)(void))cb); +void SSL_set_tmp_rsa_callback(SSL *ssl, RSA *(*cb)(SSL *ssl, int is_export, + int keylength)) { + SSL_callback_ctrl(ssl, SSL_CTRL_SET_TMP_RSA_CB, (void (*)(void))cb); +} + +void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx, + DH *(*dh)(SSL *ssl, int is_export, + int keylength)) { + SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_TMP_DH_CB, (void (*)(void))dh); +} + +void SSL_set_tmp_dh_callback(SSL *ssl, DH *(*dh)(SSL *ssl, int is_export, + int keylength)) { + SSL_callback_ctrl(ssl, SSL_CTRL_SET_TMP_DH_CB, (void (*)(void))dh); +} + +void SSL_CTX_set_tmp_ecdh_callback(SSL_CTX *ctx, + EC_KEY *(*ecdh)(SSL *ssl, int is_export, + int keylength)) { + SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_TMP_ECDH_CB, (void (*)(void))ecdh); +} + +void SSL_set_tmp_ecdh_callback(SSL *ssl, + EC_KEY *(*ecdh)(SSL *ssl, int is_export, + int keylength)) { + SSL_callback_ctrl(ssl, SSL_CTRL_SET_TMP_ECDH_CB, (void (*)(void))ecdh); +} + +int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint) { + if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_psk_identity_hint, + SSL_R_DATA_LENGTH_TOO_LONG); + return 0; + } + + if (ctx->psk_identity_hint != NULL) { + OPENSSL_free(ctx->psk_identity_hint); + } + + if (identity_hint != NULL) { + ctx->psk_identity_hint = BUF_strdup(identity_hint); + if (ctx->psk_identity_hint == NULL) { + return 0; } + } else { + ctx->psk_identity_hint = NULL; + } -void SSL_set_tmp_rsa_callback(SSL *ssl,RSA *(*cb)(SSL *ssl, - int is_export, - int keylength)) - { - SSL_callback_ctrl(ssl,SSL_CTRL_SET_TMP_RSA_CB,(void (*)(void))cb); + return 1; +} + +int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint) { + if (s == NULL) { + return 0; + } + + if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) { + OPENSSL_PUT_ERROR(SSL, SSL_use_psk_identity_hint, + SSL_R_DATA_LENGTH_TOO_LONG); + return 0; + } + + /* Clear currently configured hint, if any. */ + if (s->psk_identity_hint != NULL) { + OPENSSL_free(s->psk_identity_hint); + s->psk_identity_hint = NULL; + } + + if (identity_hint != NULL) { + s->psk_identity_hint = BUF_strdup(identity_hint); + if (s->psk_identity_hint == NULL) { + return 0; } + } -#ifdef DOXYGEN -/*! - * \brief The RSA temporary key callback function. - * \param ssl the SSL session. - * \param is_export \c TRUE if the temp RSA key is for an export ciphersuite. - * \param keylength if \c is_export is \c TRUE, then \c keylength is the size - * of the required key in bits. - * \return the temporary RSA key. - * \sa SSL_CTX_set_tmp_rsa_callback, SSL_set_tmp_rsa_callback - */ + return 1; +} -RSA *cb(SSL *ssl,int is_export,int keylength) - {} -#endif +const char *SSL_get_psk_identity_hint(const SSL *s) { + if (s == NULL) { + return NULL; + } + return s->psk_identity_hint; +} -/*! - * \brief Set the callback for generating temporary DH keys. - * \param ctx the SSL context. - * \param dh the callback - */ +const char *SSL_get_psk_identity(const SSL *s) { + if (s == NULL || s->session == NULL) { + return NULL; + } -void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,DH *(*dh)(SSL *ssl,int is_export, - int keylength)) - { - SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TMP_DH_CB,(void (*)(void))dh); - } + return s->session->psk_identity; +} -void SSL_set_tmp_dh_callback(SSL *ssl,DH *(*dh)(SSL *ssl,int is_export, - int keylength)) - { - SSL_callback_ctrl(ssl,SSL_CTRL_SET_TMP_DH_CB,(void (*)(void))dh); - } +void SSL_set_psk_client_callback( + SSL *s, unsigned int (*cb)(SSL *ssl, const char *hint, char *identity, + unsigned int max_identity_len, uint8_t *psk, + unsigned int max_psk_len)) { + s->psk_client_callback = cb; +} -void SSL_CTX_set_tmp_ecdh_callback(SSL_CTX *ctx,EC_KEY *(*ecdh)(SSL *ssl,int is_export, - int keylength)) - { - SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH_CB,(void (*)(void))ecdh); - } +void SSL_CTX_set_psk_client_callback( + SSL_CTX *ctx, unsigned int (*cb)(SSL *ssl, const char *hint, char *identity, + unsigned int max_identity_len, + uint8_t *psk, unsigned int max_psk_len)) { + ctx->psk_client_callback = cb; +} -void SSL_set_tmp_ecdh_callback(SSL *ssl,EC_KEY *(*ecdh)(SSL *ssl,int is_export, - int keylength)) - { - SSL_callback_ctrl(ssl,SSL_CTRL_SET_TMP_ECDH_CB,(void (*)(void))ecdh); - } +void SSL_set_psk_server_callback( + SSL *s, unsigned int (*cb)(SSL *ssl, const char *identity, uint8_t *psk, + unsigned int max_psk_len)) { + s->psk_server_callback = cb; +} -int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint) - { - if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_psk_identity_hint, SSL_R_DATA_LENGTH_TOO_LONG); - return 0; - } - if (ctx->psk_identity_hint != NULL) - OPENSSL_free(ctx->psk_identity_hint); - if (identity_hint != NULL) - { - ctx->psk_identity_hint = BUF_strdup(identity_hint); - if (ctx->psk_identity_hint == NULL) - return 0; - } - else - ctx->psk_identity_hint = NULL; - return 1; - } +void SSL_CTX_set_psk_server_callback( + SSL_CTX *ctx, unsigned int (*cb)(SSL *ssl, const char *identity, + uint8_t *psk, unsigned int max_psk_len)) { + ctx->psk_server_callback = cb; +} -int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint) - { - if (s == NULL) - return 0; +void SSL_CTX_set_min_version(SSL_CTX *ctx, uint16_t version) { + ctx->min_version = version; +} - if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) - { - OPENSSL_PUT_ERROR(SSL, SSL_use_psk_identity_hint, SSL_R_DATA_LENGTH_TOO_LONG); - return 0; - } +void SSL_CTX_set_max_version(SSL_CTX *ctx, uint16_t version) { + ctx->max_version = version; +} - /* Clear currently configured hint, if any. */ - if (s->psk_identity_hint != NULL) - { - OPENSSL_free(s->psk_identity_hint); - s->psk_identity_hint = NULL; - } +void SSL_set_min_version(SSL *ssl, uint16_t version) { + ssl->min_version = version; +} - if (identity_hint != NULL) - { - s->psk_identity_hint = BUF_strdup(identity_hint); - if (s->psk_identity_hint == NULL) - return 0; - } - return 1; - } +void SSL_set_max_version(SSL *ssl, uint16_t version) { + ssl->max_version = version; +} -const char *SSL_get_psk_identity_hint(const SSL *s) - { - if (s == NULL) - return NULL; - return s->psk_identity_hint; - } +void SSL_CTX_set_msg_callback(SSL_CTX *ctx, + void (*cb)(int write_p, int version, + int content_type, const void *buf, + size_t len, SSL *ssl, void *arg)) { + SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb); +} +void SSL_set_msg_callback(SSL *ssl, + void (*cb)(int write_p, int version, int content_type, + const void *buf, size_t len, SSL *ssl, + void *arg)) { + SSL_callback_ctrl(ssl, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb); +} -const char *SSL_get_psk_identity(const SSL *s) - { - if (s == NULL || s->session == NULL) - return NULL; - return(s->session->psk_identity); - } +void SSL_CTX_set_keylog_bio(SSL_CTX *ctx, BIO *keylog_bio) { + if (ctx->keylog_bio != NULL) { + BIO_free(ctx->keylog_bio); + } + ctx->keylog_bio = keylog_bio; +} -void SSL_set_psk_client_callback(SSL *s, - unsigned int (*cb)(SSL *ssl, const char *hint, - char *identity, unsigned int max_identity_len, unsigned char *psk, - unsigned int max_psk_len)) - { - s->psk_client_callback = cb; - } +static int cbb_add_hex(CBB *cbb, const uint8_t *in, size_t in_len) { + static const char hextable[] = "0123456789abcdef"; + uint8_t *out; + size_t i; -void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx, - unsigned int (*cb)(SSL *ssl, const char *hint, - char *identity, unsigned int max_identity_len, unsigned char *psk, - unsigned int max_psk_len)) - { - ctx->psk_client_callback = cb; - } + if (!CBB_add_space(cbb, &out, in_len * 2)) { + return 0; + } -void SSL_set_psk_server_callback(SSL *s, - unsigned int (*cb)(SSL *ssl, const char *identity, - unsigned char *psk, unsigned int max_psk_len)) - { - s->psk_server_callback = cb; - } + for (i = 0; i < in_len; i++) { + *(out++) = (uint8_t)hextable[in[i] >> 4]; + *(out++) = (uint8_t)hextable[in[i] & 0xf]; + } -void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx, - unsigned int (*cb)(SSL *ssl, const char *identity, - unsigned char *psk, unsigned int max_psk_len)) - { - ctx->psk_server_callback = cb; - } - -void SSL_CTX_set_min_version(SSL_CTX *ctx, uint16_t version) - { - ctx->min_version = version; - } - -void SSL_CTX_set_max_version(SSL_CTX *ctx, uint16_t version) - { - ctx->max_version = version; - } - -void SSL_set_min_version(SSL *ssl, uint16_t version) - { - ssl->min_version = version; - } - -void SSL_set_max_version(SSL *ssl, uint16_t version) - { - ssl->max_version = version; - } - -void SSL_CTX_set_msg_callback(SSL_CTX *ctx, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)) - { - SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb); - } -void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)) - { - SSL_callback_ctrl(ssl, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb); - } - -void SSL_CTX_set_keylog_bio(SSL_CTX *ctx, BIO *keylog_bio) - { - if (ctx->keylog_bio != NULL) - BIO_free(ctx->keylog_bio); - ctx->keylog_bio = keylog_bio; - } - -static int cbb_add_hex(CBB *cbb, const uint8_t *in, size_t in_len) - { - static const char hextable[] = "0123456789abcdef"; - uint8_t *out; - size_t i; - - if (!CBB_add_space(cbb, &out, in_len * 2)) - { - return 0; - } - - for (i = 0; i < in_len; i++) - { - *(out++) = (uint8_t)hextable[in[i] >> 4]; - *(out++) = (uint8_t)hextable[in[i] & 0xf]; - } - return 1; - } + return 1; +} int ssl_ctx_log_rsa_client_key_exchange(SSL_CTX *ctx, - const uint8_t *encrypted_premaster, size_t encrypted_premaster_len, - const uint8_t *premaster, size_t premaster_len) - { - BIO *bio = ctx->keylog_bio; - CBB cbb; - uint8_t *out; - size_t out_len; - int ret; + const uint8_t *encrypted_premaster, + size_t encrypted_premaster_len, + const uint8_t *premaster, + size_t premaster_len) { + BIO *bio = ctx->keylog_bio; + CBB cbb; + uint8_t *out; + size_t out_len; + int ret; - if (bio == NULL) - { - return 1; - } + if (bio == NULL) { + return 1; + } - if (encrypted_premaster_len < 8) - { - OPENSSL_PUT_ERROR(SSL, ssl_ctx_log_rsa_client_key_exchange, ERR_R_INTERNAL_ERROR); - return 0; - } + if (encrypted_premaster_len < 8) { + OPENSSL_PUT_ERROR(SSL, ssl_ctx_log_rsa_client_key_exchange, + ERR_R_INTERNAL_ERROR); + return 0; + } - if (!CBB_init(&cbb, 4 + 16 + 1 + premaster_len*2 + 1)) - { - return 0; - } - if (!CBB_add_bytes(&cbb, (const uint8_t*)"RSA ", 4) || - /* Only the first 8 bytes of the encrypted premaster secret are - * logged. */ - !cbb_add_hex(&cbb, encrypted_premaster, 8) || - !CBB_add_bytes(&cbb, (const uint8_t*)" ", 1) || - !cbb_add_hex(&cbb, premaster, premaster_len) || - !CBB_add_bytes(&cbb, (const uint8_t*)"\n", 1) || - !CBB_finish(&cbb, &out, &out_len)) - { - CBB_cleanup(&cbb); - return 0; - } + if (!CBB_init(&cbb, 4 + 16 + 1 + premaster_len * 2 + 1)) { + return 0; + } - CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); - ret = BIO_write(bio, out, out_len) >= 0 && BIO_flush(bio); - CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); + if (!CBB_add_bytes(&cbb, (const uint8_t *)"RSA ", 4) || + /* Only the first 8 bytes of the encrypted premaster secret are + * logged. */ + !cbb_add_hex(&cbb, encrypted_premaster, 8) || + !CBB_add_bytes(&cbb, (const uint8_t *)" ", 1) || + !cbb_add_hex(&cbb, premaster, premaster_len) || + !CBB_add_bytes(&cbb, (const uint8_t *)"\n", 1) || + !CBB_finish(&cbb, &out, &out_len)) { + CBB_cleanup(&cbb); + return 0; + } - OPENSSL_free(out); - return ret; - } + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + ret = BIO_write(bio, out, out_len) >= 0 && BIO_flush(bio); + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); -int ssl_ctx_log_master_secret(SSL_CTX *ctx, - const uint8_t *client_random, size_t client_random_len, - const uint8_t *master, size_t master_len) - { - BIO *bio = ctx->keylog_bio; - CBB cbb; - uint8_t *out; - size_t out_len; - int ret; - - if (bio == NULL) - { - return 1; - } - - if (client_random_len != 32) - { - OPENSSL_PUT_ERROR(SSL, ssl_ctx_log_master_secret, ERR_R_INTERNAL_ERROR); - return 0; - } - - if (!CBB_init(&cbb, 14 + 64 + 1 + master_len*2 + 1)) - { - return 0; - } - if (!CBB_add_bytes(&cbb, (const uint8_t*)"CLIENT_RANDOM ", 14) || - !cbb_add_hex(&cbb, client_random, 32) || - !CBB_add_bytes(&cbb, (const uint8_t*)" ", 1) || - !cbb_add_hex(&cbb, master, master_len) || - !CBB_add_bytes(&cbb, (const uint8_t*)"\n", 1) || - !CBB_finish(&cbb, &out, &out_len)) - { - CBB_cleanup(&cbb); - return 0; - } - - CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); - ret = BIO_write(bio, out, out_len) >= 0 && BIO_flush(bio); - CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); - - OPENSSL_free(out); - return ret; - } - -int SSL_cutthrough_complete(const SSL *s) - { - return (!s->server && /* cutthrough only applies to clients */ - !s->hit && /* full-handshake */ - s->version >= SSL3_VERSION && - s->s3->in_read_app_data == 0 && /* cutthrough only applies to write() */ - (SSL_get_mode((SSL*)s) & SSL_MODE_HANDSHAKE_CUTTHROUGH) && /* cutthrough enabled */ - ssl3_can_cutthrough(s) && /* cutthrough allowed */ - s->s3->previous_server_finished_len == 0 && /* not a renegotiation handshake */ - (s->state == SSL3_ST_CR_SESSION_TICKET_A || /* ready to write app-data*/ - s->state == SSL3_ST_CR_CHANGE || - s->state == SSL3_ST_CR_FINISHED_A)); - } - -void SSL_get_structure_sizes(size_t* ssl_size, size_t* ssl_ctx_size, - size_t* ssl_session_size) -{ - *ssl_size = sizeof(SSL); - *ssl_ctx_size = sizeof(SSL_CTX); - *ssl_session_size = sizeof(SSL_SESSION); + OPENSSL_free(out); + return ret; } -int ssl3_can_cutthrough(const SSL *s) - { - const SSL_CIPHER *c; +int ssl_ctx_log_master_secret(SSL_CTX *ctx, const uint8_t *client_random, + size_t client_random_len, const uint8_t *master, + size_t master_len) { + BIO *bio = ctx->keylog_bio; + CBB cbb; + uint8_t *out; + size_t out_len; + int ret; - /* require a strong enough cipher */ - if (SSL_get_cipher_bits(s, NULL) < 128) - return 0; + if (bio == NULL) { + return 1; + } - /* require ALPN or NPN extension */ - if (!s->s3->alpn_selected && !s->s3->next_proto_neg_seen) - { - return 0; - } + if (client_random_len != 32) { + OPENSSL_PUT_ERROR(SSL, ssl_ctx_log_master_secret, ERR_R_INTERNAL_ERROR); + return 0; + } - /* require a forward-secret cipher */ - c = SSL_get_current_cipher(s); - if (!c || (c->algorithm_mkey != SSL_kEDH && - c->algorithm_mkey != SSL_kEECDH)) - { - return 0; - } + if (!CBB_init(&cbb, 14 + 64 + 1 + master_len * 2 + 1)) { + return 0; + } - return 1; - } + if (!CBB_add_bytes(&cbb, (const uint8_t *)"CLIENT_RANDOM ", 14) || + !cbb_add_hex(&cbb, client_random, 32) || + !CBB_add_bytes(&cbb, (const uint8_t *)" ", 1) || + !cbb_add_hex(&cbb, master, master_len) || + !CBB_add_bytes(&cbb, (const uint8_t *)"\n", 1) || + !CBB_finish(&cbb, &out, &out_len)) { + CBB_cleanup(&cbb); + return 0; + } -const SSL3_ENC_METHOD *ssl3_get_enc_method(uint16_t version) - { - switch (version) - { - case SSL3_VERSION: - return &SSLv3_enc_data; - case TLS1_VERSION: - return &TLSv1_enc_data; - case TLS1_1_VERSION: - return &TLSv1_1_enc_data; - case TLS1_2_VERSION: - return &TLSv1_2_enc_data; - case DTLS1_VERSION: - return &DTLSv1_enc_data; - case DTLS1_2_VERSION: - return &DTLSv1_2_enc_data; - default: - return NULL; - } - } + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + ret = BIO_write(bio, out, out_len) >= 0 && BIO_flush(bio); + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); -uint16_t ssl3_get_max_server_version(const SSL *s) - { - uint16_t max_version; - - if (SSL_IS_DTLS(s)) - { - max_version = (s->max_version != 0) ? s->max_version : DTLS1_2_VERSION; - if (!(s->options & SSL_OP_NO_DTLSv1_2) && DTLS1_2_VERSION >= max_version) - return DTLS1_2_VERSION; - if (!(s->options & SSL_OP_NO_DTLSv1) && DTLS1_VERSION >= max_version) - return DTLS1_VERSION; - return 0; - } - - max_version = (s->max_version != 0) ? s->max_version : TLS1_2_VERSION; - if (!(s->options & SSL_OP_NO_TLSv1_2) && TLS1_2_VERSION <= max_version) - return TLS1_2_VERSION; - if (!(s->options & SSL_OP_NO_TLSv1_1) && TLS1_1_VERSION <= max_version) - return TLS1_1_VERSION; - if (!(s->options & SSL_OP_NO_TLSv1) && TLS1_VERSION <= max_version) - return TLS1_VERSION; - if (!(s->options & SSL_OP_NO_SSLv3) && SSL3_VERSION <= max_version) - return SSL3_VERSION; - return 0; - } - -uint16_t ssl3_get_mutual_version(SSL *s, uint16_t client_version) - { - uint16_t version = 0; - - if (SSL_IS_DTLS(s)) - { - /* Clamp client_version to max_version. */ - if (s->max_version != 0 && client_version < s->max_version) - client_version = s->max_version; - - if (client_version <= DTLS1_2_VERSION && !(s->options & SSL_OP_NO_DTLSv1_2)) - version = DTLS1_2_VERSION; - else if (client_version <= DTLS1_VERSION && !(s->options & SSL_OP_NO_DTLSv1)) - version = DTLS1_VERSION; - - /* Check against min_version. */ - if (version != 0 && s->min_version != 0 && version > s->min_version) - return 0; - return version; - } - else - { - /* Clamp client_version to max_version. */ - if (s->max_version != 0 && client_version > s->max_version) - client_version = s->max_version; - - if (client_version >= TLS1_2_VERSION && !(s->options & SSL_OP_NO_TLSv1_2)) - version = TLS1_2_VERSION; - else if (client_version >= TLS1_1_VERSION && !(s->options & SSL_OP_NO_TLSv1_1)) - version = TLS1_1_VERSION; - else if (client_version >= TLS1_VERSION && !(s->options & SSL_OP_NO_TLSv1)) - version = TLS1_VERSION; - else if (client_version >= SSL3_VERSION && !(s->options & SSL_OP_NO_SSLv3)) - version = SSL3_VERSION; - - /* Check against min_version. */ - if (version != 0 && s->min_version != 0 && version < s->min_version) - return 0; - return version; - } - } - -uint16_t ssl3_get_max_client_version(SSL *s) - { - unsigned long options = s->options; - uint16_t version = 0; - - /* OpenSSL's API for controlling versions entails blacklisting - * individual protocols. This has two problems. First, on the client, - * the protocol can only express a contiguous range of versions. Second, - * a library consumer trying to set a maximum version cannot disable - * protocol versions that get added in a future version of the library. - * - * To account for both of these, OpenSSL interprets the client-side - * bitmask as a min/max range by picking the lowest contiguous non-empty - * range of enabled protocols. Note that this means it is impossible to - * set a maximum version of TLS 1.2 in a future-proof way. - * - * By this scheme, the maximum version is the lowest version V such that - * V is enabled and V+1 is disabled or unimplemented. */ - if (SSL_IS_DTLS(s)) - { - if (!(options & SSL_OP_NO_DTLSv1_2)) - version = DTLS1_2_VERSION; - if (!(options & SSL_OP_NO_DTLSv1) && (options & SSL_OP_NO_DTLSv1_2)) - version = DTLS1_VERSION; - if (s->max_version != 0 && version < s->max_version) - version = s->max_version; - } - else - { - if (!(options & SSL_OP_NO_TLSv1_2)) - version = TLS1_2_VERSION; - if (!(options & SSL_OP_NO_TLSv1_1) && (options & SSL_OP_NO_TLSv1_2)) - version = TLS1_1_VERSION; - if (!(options & SSL_OP_NO_TLSv1) && (options & SSL_OP_NO_TLSv1_1)) - version = TLS1_VERSION; - if (!(options & SSL_OP_NO_SSLv3) && (options & SSL_OP_NO_TLSv1)) - version = SSL3_VERSION; - if (s->max_version != 0 && version > s->max_version) - version = s->max_version; - } - - return version; - } - -int ssl3_is_version_enabled(SSL *s, uint16_t version) - { - if (SSL_IS_DTLS(s)) - { - if (s->max_version != 0 && version < s->max_version) - return 0; - if (s->min_version != 0 && version > s->min_version) - return 0; - switch (version) - { - case DTLS1_VERSION: - return !(s->options & SSL_OP_NO_DTLSv1); - case DTLS1_2_VERSION: - return !(s->options & SSL_OP_NO_DTLSv1_2); - default: - return 0; - } - } - else - { - if (s->max_version != 0 && version > s->max_version) - return 0; - if (s->min_version != 0 && version < s->min_version) - return 0; - switch (version) - { - case SSL3_VERSION: - return !(s->options & SSL_OP_NO_SSLv3); - case TLS1_VERSION: - return !(s->options & SSL_OP_NO_TLSv1); - case TLS1_1_VERSION: - return !(s->options & SSL_OP_NO_TLSv1_1); - case TLS1_2_VERSION: - return !(s->options & SSL_OP_NO_TLSv1_2); - default: - return 0; - } - } - } - -/* Allocates new EVP_MD_CTX and sets pointer to it into given pointer - * vairable, freeing EVP_MD_CTX previously stored in that variable, if - * any. If EVP_MD pointer is passed, initializes ctx with this md - * Returns newly allocated ctx; - */ - -EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash,const EVP_MD *md) -{ - ssl_clear_hash_ctx(hash); - *hash = EVP_MD_CTX_create(); - if (md != NULL && *hash != NULL && - !EVP_DigestInit_ex(*hash, md, NULL)) - { - EVP_MD_CTX_destroy(*hash); - *hash = NULL; - } - return *hash; -} -void ssl_clear_hash_ctx(EVP_MD_CTX **hash) -{ - - if (*hash) EVP_MD_CTX_destroy(*hash); - *hash=NULL; + OPENSSL_free(out); + return ret; } -int SSL_cache_hit(SSL *s) - { - return s->hit; - } +int SSL_cutthrough_complete(const SSL *s) { + return ( + !s->server && /* cutthrough only applies to clients */ + !s->hit && /* full-handshake */ + s->version >= SSL3_VERSION && + s->s3->in_read_app_data == 0 && /* cutthrough only applies to write() */ + (SSL_get_mode((SSL *)s) & + SSL_MODE_HANDSHAKE_CUTTHROUGH) && /* cutthrough enabled */ + ssl3_can_cutthrough(s) && /* cutthrough allowed */ + s->s3->previous_server_finished_len == + 0 && /* not a renegotiation handshake */ + (s->state == SSL3_ST_CR_SESSION_TICKET_A || /* ready to write app-data*/ + s->state == SSL3_ST_CR_CHANGE || s->state == SSL3_ST_CR_FINISHED_A)); +} -int SSL_is_server(SSL *s) - { - return s->server; - } +void SSL_get_structure_sizes(size_t *ssl_size, size_t *ssl_ctx_size, + size_t *ssl_session_size) { + *ssl_size = sizeof(SSL); + *ssl_ctx_size = sizeof(SSL_CTX); + *ssl_session_size = sizeof(SSL_SESSION); +} -void SSL_enable_fastradio_padding(SSL *s, char on_off) - { - s->fastradio_padding = on_off; - } +int ssl3_can_cutthrough(const SSL *s) { + const SSL_CIPHER *c; + + /* require a strong enough cipher */ + if (SSL_get_cipher_bits(s, NULL) < 128) { + return 0; + } + + /* require ALPN or NPN extension */ + if (!s->s3->alpn_selected && !s->s3->next_proto_neg_seen) { + return 0; + } + + /* require a forward-secret cipher */ + c = SSL_get_current_cipher(s); + if (!c || + (c->algorithm_mkey != SSL_kEDH && c->algorithm_mkey != SSL_kEECDH)) { + return 0; + } + + return 1; +} + +const SSL3_ENC_METHOD *ssl3_get_enc_method(uint16_t version) { + switch (version) { + case SSL3_VERSION: + return &SSLv3_enc_data; + + case TLS1_VERSION: + return &TLSv1_enc_data; + + case TLS1_1_VERSION: + return &TLSv1_1_enc_data; + + case TLS1_2_VERSION: + return &TLSv1_2_enc_data; + + case DTLS1_VERSION: + return &DTLSv1_enc_data; + + case DTLS1_2_VERSION: + return &DTLSv1_2_enc_data; + + default: + return NULL; + } +} + +uint16_t ssl3_get_max_server_version(const SSL *s) { + uint16_t max_version; + + if (SSL_IS_DTLS(s)) { + max_version = (s->max_version != 0) ? s->max_version : DTLS1_2_VERSION; + if (!(s->options & SSL_OP_NO_DTLSv1_2) && DTLS1_2_VERSION >= max_version) { + return DTLS1_2_VERSION; + } + if (!(s->options & SSL_OP_NO_DTLSv1) && DTLS1_VERSION >= max_version) { + return DTLS1_VERSION; + } + return 0; + } + + max_version = (s->max_version != 0) ? s->max_version : TLS1_2_VERSION; + if (!(s->options & SSL_OP_NO_TLSv1_2) && TLS1_2_VERSION <= max_version) { + return TLS1_2_VERSION; + } + if (!(s->options & SSL_OP_NO_TLSv1_1) && TLS1_1_VERSION <= max_version) { + return TLS1_1_VERSION; + } + if (!(s->options & SSL_OP_NO_TLSv1) && TLS1_VERSION <= max_version) { + return TLS1_VERSION; + } + if (!(s->options & SSL_OP_NO_SSLv3) && SSL3_VERSION <= max_version) { + return SSL3_VERSION; + } + return 0; +} + +uint16_t ssl3_get_mutual_version(SSL *s, uint16_t client_version) { + uint16_t version = 0; + + if (SSL_IS_DTLS(s)) { + /* Clamp client_version to max_version. */ + if (s->max_version != 0 && client_version < s->max_version) { + client_version = s->max_version; + } + + if (client_version <= DTLS1_2_VERSION && !(s->options & SSL_OP_NO_DTLSv1_2)) { + version = DTLS1_2_VERSION; + } else if (client_version <= DTLS1_VERSION && + !(s->options & SSL_OP_NO_DTLSv1)) { + version = DTLS1_VERSION; + } + + /* Check against min_version. */ + if (version != 0 && s->min_version != 0 && version > s->min_version) { + return 0; + } + return version; + } else { + /* Clamp client_version to max_version. */ + if (s->max_version != 0 && client_version > s->max_version) { + client_version = s->max_version; + } + + if (client_version >= TLS1_2_VERSION && !(s->options & SSL_OP_NO_TLSv1_2)) { + version = TLS1_2_VERSION; + } else if (client_version >= TLS1_1_VERSION && + !(s->options & SSL_OP_NO_TLSv1_1)) { + version = TLS1_1_VERSION; + } else if (client_version >= TLS1_VERSION && !(s->options & SSL_OP_NO_TLSv1)) { + version = TLS1_VERSION; + } else if (client_version >= SSL3_VERSION && !(s->options & SSL_OP_NO_SSLv3)) { + version = SSL3_VERSION; + } + + /* Check against min_version. */ + if (version != 0 && s->min_version != 0 && version < s->min_version) { + return 0; + } + return version; + } +} + +uint16_t ssl3_get_max_client_version(SSL *s) { + unsigned long options = s->options; + uint16_t version = 0; + + /* OpenSSL's API for controlling versions entails blacklisting individual + * protocols. This has two problems. First, on the client, the protocol can + * only express a contiguous range of versions. Second, a library consumer + * trying to set a maximum version cannot disable protocol versions that get + * added in a future version of the library. + * + * To account for both of these, OpenSSL interprets the client-side bitmask + * as a min/max range by picking the lowest contiguous non-empty range of + * enabled protocols. Note that this means it is impossible to set a maximum + * version of TLS 1.2 in a future-proof way. + * + * By this scheme, the maximum version is the lowest version V such that V is + * enabled and V+1 is disabled or unimplemented. */ + if (SSL_IS_DTLS(s)) { + if (!(options & SSL_OP_NO_DTLSv1_2)) { + version = DTLS1_2_VERSION; + } + if (!(options & SSL_OP_NO_DTLSv1) && (options & SSL_OP_NO_DTLSv1_2)) { + version = DTLS1_VERSION; + } + if (s->max_version != 0 && version < s->max_version) { + version = s->max_version; + } + } else { + if (!(options & SSL_OP_NO_TLSv1_2)) { + version = TLS1_2_VERSION; + } + if (!(options & SSL_OP_NO_TLSv1_1) && (options & SSL_OP_NO_TLSv1_2)) { + version = TLS1_1_VERSION; + } + if (!(options & SSL_OP_NO_TLSv1) && (options & SSL_OP_NO_TLSv1_1)) { + version = TLS1_VERSION; + } + if (!(options & SSL_OP_NO_SSLv3) && (options & SSL_OP_NO_TLSv1)) { + version = SSL3_VERSION; + } + if (s->max_version != 0 && version > s->max_version) { + version = s->max_version; + } + } + + return version; +} + +int ssl3_is_version_enabled(SSL *s, uint16_t version) { + if (SSL_IS_DTLS(s)) { + if (s->max_version != 0 && version < s->max_version) { + return 0; + } + if (s->min_version != 0 && version > s->min_version) { + return 0; + } + + switch (version) { + case DTLS1_VERSION: + return !(s->options & SSL_OP_NO_DTLSv1); + + case DTLS1_2_VERSION: + return !(s->options & SSL_OP_NO_DTLSv1_2); + + default: + return 0; + } + } else { + if (s->max_version != 0 && version > s->max_version) { + return 0; + } + if (s->min_version != 0 && version < s->min_version) { + return 0; + } + + switch (version) { + case SSL3_VERSION: + return !(s->options & SSL_OP_NO_SSLv3); + + case TLS1_VERSION: + return !(s->options & SSL_OP_NO_TLSv1); + + case TLS1_1_VERSION: + return !(s->options & SSL_OP_NO_TLSv1_1); + + case TLS1_2_VERSION: + return !(s->options & SSL_OP_NO_TLSv1_2); + + default: + return 0; + } + } +} + +/* Allocates new EVP_MD_CTX and sets pointer to it into given pointer vairable, + * freeing EVP_MD_CTX previously stored in that variable, if any. If EVP_MD + * pointer is passed, initializes ctx with this md Returns newly allocated + * ctx. */ +EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash, const EVP_MD *md) { + ssl_clear_hash_ctx(hash); + *hash = EVP_MD_CTX_create(); + if (md != NULL && *hash != NULL && !EVP_DigestInit_ex(*hash, md, NULL)) { + EVP_MD_CTX_destroy(*hash); + *hash = NULL; + } + return *hash; +} + +void ssl_clear_hash_ctx(EVP_MD_CTX **hash) { + if (*hash) { + EVP_MD_CTX_destroy(*hash); + } + *hash = NULL; +} + +int SSL_cache_hit(SSL *s) { return s->hit; } + +int SSL_is_server(SSL *s) { return s->server; } + +void SSL_enable_fastradio_padding(SSL *s, char on_off) { + s->fastradio_padding = on_off; +}
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index cf89a49..283e89f 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h
@@ -158,160 +158,182 @@ #include <openssl/ssl.h> #include <openssl/stack.h> -#define c2l(c,l) (l = ((unsigned long)(*((c)++))) , \ - l|=(((unsigned long)(*((c)++)))<< 8), \ - l|=(((unsigned long)(*((c)++)))<<16), \ - l|=(((unsigned long)(*((c)++)))<<24)) + +#define c2l(c, l) \ + (l = ((unsigned long)(*((c)++))), l |= (((unsigned long)(*((c)++))) << 8), \ + l |= (((unsigned long)(*((c)++))) << 16), \ + l |= (((unsigned long)(*((c)++))) << 24)) /* NOTE - c is not incremented as per c2l */ -#define c2ln(c,l1,l2,n) { \ - c+=n; \ - l1=l2=0; \ - switch (n) { \ - case 8: l2 =((unsigned long)(*(--(c))))<<24; \ - case 7: l2|=((unsigned long)(*(--(c))))<<16; \ - case 6: l2|=((unsigned long)(*(--(c))))<< 8; \ - case 5: l2|=((unsigned long)(*(--(c)))); \ - case 4: l1 =((unsigned long)(*(--(c))))<<24; \ - case 3: l1|=((unsigned long)(*(--(c))))<<16; \ - case 2: l1|=((unsigned long)(*(--(c))))<< 8; \ - case 1: l1|=((unsigned long)(*(--(c)))); \ - } \ - } +#define c2ln(c, l1, l2, n) \ + { \ + c += n; \ + l1 = l2 = 0; \ + switch (n) { \ + case 8: \ + l2 = ((unsigned long)(*(--(c)))) << 24; \ + case 7: \ + l2 |= ((unsigned long)(*(--(c)))) << 16; \ + case 6: \ + l2 |= ((unsigned long)(*(--(c)))) << 8; \ + case 5: \ + l2 |= ((unsigned long)(*(--(c)))); \ + case 4: \ + l1 = ((unsigned long)(*(--(c)))) << 24; \ + case 3: \ + l1 |= ((unsigned long)(*(--(c)))) << 16; \ + case 2: \ + l1 |= ((unsigned long)(*(--(c)))) << 8; \ + case 1: \ + l1 |= ((unsigned long)(*(--(c)))); \ + } \ + } -#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ - *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ - *((c)++)=(unsigned char)(((l)>>16)&0xff), \ - *((c)++)=(unsigned char)(((l)>>24)&0xff)) +#define l2c(l, c) \ + (*((c)++) = (uint8_t)(((l)) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 8) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 16) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 24) & 0xff)) -#define n2l(c,l) (l =((unsigned long)(*((c)++)))<<24, \ - l|=((unsigned long)(*((c)++)))<<16, \ - l|=((unsigned long)(*((c)++)))<< 8, \ - l|=((unsigned long)(*((c)++)))) +#define n2l(c, l) \ + (l = ((unsigned long)(*((c)++))) << 24, \ + l |= ((unsigned long)(*((c)++))) << 16, \ + l |= ((unsigned long)(*((c)++))) << 8, l |= ((unsigned long)(*((c)++)))) -#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ - *((c)++)=(unsigned char)(((l)>>16)&0xff), \ - *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ - *((c)++)=(unsigned char)(((l) )&0xff)) +#define l2n(l, c) \ + (*((c)++) = (uint8_t)(((l) >> 24) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 16) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 8) & 0xff), \ + *((c)++) = (uint8_t)(((l)) & 0xff)) -#define l2n6(l,c) (*((c)++)=(unsigned char)(((l)>>40)&0xff), \ - *((c)++)=(unsigned char)(((l)>>32)&0xff), \ - *((c)++)=(unsigned char)(((l)>>24)&0xff), \ - *((c)++)=(unsigned char)(((l)>>16)&0xff), \ - *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ - *((c)++)=(unsigned char)(((l) )&0xff)) +#define l2n6(l, c) \ + (*((c)++) = (uint8_t)(((l) >> 40) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 32) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 24) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 16) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 8) & 0xff), \ + *((c)++) = (uint8_t)(((l)) & 0xff)) -#define l2n8(l,c) (*((c)++)=(unsigned char)(((l)>>56)&0xff), \ - *((c)++)=(unsigned char)(((l)>>48)&0xff), \ - *((c)++)=(unsigned char)(((l)>>40)&0xff), \ - *((c)++)=(unsigned char)(((l)>>32)&0xff), \ - *((c)++)=(unsigned char)(((l)>>24)&0xff), \ - *((c)++)=(unsigned char)(((l)>>16)&0xff), \ - *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ - *((c)++)=(unsigned char)(((l) )&0xff)) +#define l2n8(l, c) \ + (*((c)++) = (uint8_t)(((l) >> 56) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 48) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 40) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 32) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 24) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 16) & 0xff), \ + *((c)++) = (uint8_t)(((l) >> 8) & 0xff), \ + *((c)++) = (uint8_t)(((l)) & 0xff)) -#define n2l6(c,l) (l =((BN_ULLONG)(*((c)++)))<<40, \ - l|=((BN_ULLONG)(*((c)++)))<<32, \ - l|=((BN_ULLONG)(*((c)++)))<<24, \ - l|=((BN_ULLONG)(*((c)++)))<<16, \ - l|=((BN_ULLONG)(*((c)++)))<< 8, \ - l|=((BN_ULLONG)(*((c)++)))) +#define n2l6(c, l) \ + (l = ((BN_ULLONG)(*((c)++))) << 40, l |= ((BN_ULLONG)(*((c)++))) << 32, \ + l |= ((BN_ULLONG)(*((c)++))) << 24, l |= ((BN_ULLONG)(*((c)++))) << 16, \ + l |= ((BN_ULLONG)(*((c)++))) << 8, l |= ((BN_ULLONG)(*((c)++)))) /* NOTE - c is not incremented as per l2c */ -#define l2cn(l1,l2,c,n) { \ - c+=n; \ - switch (n) { \ - case 8: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \ - case 7: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \ - case 6: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \ - case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \ - case 4: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \ - case 3: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \ - case 2: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \ - case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \ - } \ - } +#define l2cn(l1, l2, c, n) \ + { \ + c += n; \ + switch (n) { \ + case 8: \ + *(--(c)) = (uint8_t)(((l2) >> 24) & 0xff); \ + case 7: \ + *(--(c)) = (uint8_t)(((l2) >> 16) & 0xff); \ + case 6: \ + *(--(c)) = (uint8_t)(((l2) >> 8) & 0xff); \ + case 5: \ + *(--(c)) = (uint8_t)(((l2)) & 0xff); \ + case 4: \ + *(--(c)) = (uint8_t)(((l1) >> 24) & 0xff); \ + case 3: \ + *(--(c)) = (uint8_t)(((l1) >> 16) & 0xff); \ + case 2: \ + *(--(c)) = (uint8_t)(((l1) >> 8) & 0xff); \ + case 1: \ + *(--(c)) = (uint8_t)(((l1)) & 0xff); \ + } \ + } -#define n2s(c,s) ((s=(((unsigned int)(c[0]))<< 8)| \ - (((unsigned int)(c[1])) )),c+=2) -#define s2n(s,c) ((c[0]=(unsigned char)(((s)>> 8)&0xff), \ - c[1]=(unsigned char)(((s) )&0xff)),c+=2) +#define n2s(c, s) \ + ((s = (((unsigned int)(c[0])) << 8) | (((unsigned int)(c[1])))), c += 2) -#define n2l3(c,l) ((l =(((unsigned long)(c[0]))<<16)| \ - (((unsigned long)(c[1]))<< 8)| \ - (((unsigned long)(c[2])) )),c+=3) +#define s2n(s, c) \ + ((c[0] = (uint8_t)(((s) >> 8) & 0xff), \ + c[1] = (uint8_t)(((s)) & 0xff)), \ + c += 2) -#define l2n3(l,c) ((c[0]=(unsigned char)(((l)>>16)&0xff), \ - c[1]=(unsigned char)(((l)>> 8)&0xff), \ - c[2]=(unsigned char)(((l) )&0xff)),c+=3) +#define n2l3(c, l) \ + ((l = (((unsigned long)(c[0])) << 16) | (((unsigned long)(c[1])) << 8) | \ + (((unsigned long)(c[2])))), \ + c += 3) + +#define l2n3(l, c) \ + ((c[0] = (uint8_t)(((l) >> 16) & 0xff), \ + c[1] = (uint8_t)(((l) >> 8) & 0xff), \ + c[2] = (uint8_t)(((l)) & 0xff)), \ + c += 3) /* LOCAL STUFF */ -#define SSL_DECRYPT 0 -#define SSL_ENCRYPT 1 +#define SSL_DECRYPT 0 +#define SSL_ENCRYPT 1 -#define TWO_BYTE_BIT 0x80 -#define SEC_ESC_BIT 0x40 -#define TWO_BYTE_MASK 0x7fff -#define THREE_BYTE_MASK 0x3fff +#define TWO_BYTE_BIT 0x80 +#define SEC_ESC_BIT 0x40 +#define TWO_BYTE_MASK 0x7fff +#define THREE_BYTE_MASK 0x3fff -#define INC32(a) ((a)=((a)+1)&0xffffffffL) -#define DEC32(a) ((a)=((a)-1)&0xffffffffL) -#define MAX_MAC_SIZE 20 /* up from 16 for SSLv3 */ +#define INC32(a) ((a) = ((a) + 1) & 0xffffffffL) +#define DEC32(a) ((a) = ((a)-1) & 0xffffffffL) +#define MAX_MAC_SIZE 20 /* up from 16 for SSLv3 */ -/* - * Define the Bitmasks for SSL_CIPHER.algorithms. - * This bits are used packed as dense as possible. If new methods/ciphers - * etc will be added, the bits a likely to change, so this information - * is for internal library use only, even though SSL_CIPHER.algorithms - * can be publicly accessed. - * Use the according functions for cipher management instead. +/* Define the Bitmasks for SSL_CIPHER.algorithms. + * + * This bits are used packed as dense as possible. If new methods/ciphers etc + * will be added, the bits a likely to change, so this information is for + * internal library use only, even though SSL_CIPHER.algorithms can be publicly + * accessed. Use the according functions for cipher management instead. * * The bit mask handling in the selection and sorting scheme in - * ssl_create_cipher_list() has only limited capabilities, reflecting - * that the different entities within are mutually exclusive: - * ONLY ONE BIT PER MASK CAN BE SET AT A TIME. - */ + * ssl_create_cipher_list() has only limited capabilities, reflecting that the + * different entities within are mutually exclusive: + * ONLY ONE BIT PER MASK CAN BE SET AT A TIME. */ /* Bits for algorithm_mkey (key exchange algorithm) */ -#define SSL_kRSA 0x00000001L /* RSA key exchange */ -#define SSL_kEDH 0x00000002L /* tmp DH key no DH cert */ -#define SSL_kEECDH 0x00000004L /* ephemeral ECDH */ -#define SSL_kPSK 0x00000008L /* PSK */ +#define SSL_kRSA 0x00000001L /* RSA key exchange */ +#define SSL_kEDH 0x00000002L /* tmp DH key no DH cert */ +#define SSL_kEECDH 0x00000004L /* ephemeral ECDH */ +#define SSL_kPSK 0x00000008L /* PSK */ /* Bits for algorithm_auth (server authentication) */ -#define SSL_aRSA 0x00000001L /* RSA auth */ -#define SSL_aNULL 0x00000002L /* no auth (i.e. use ADH or AECDH) */ -#define SSL_aECDSA 0x00000004L /* ECDSA auth*/ -#define SSL_aPSK 0x00000008L /* PSK auth */ - +#define SSL_aRSA 0x00000001L /* RSA auth */ +#define SSL_aNULL 0x00000002L /* no auth (i.e. use ADH or AECDH) */ +#define SSL_aECDSA 0x00000004L /* ECDSA auth*/ +#define SSL_aPSK 0x00000008L /* PSK auth */ /* Bits for algorithm_enc (symmetric encryption) */ -#define SSL_3DES 0x00000001L -#define SSL_RC4 0x00000002L -#define SSL_AES128 0x00000004L -#define SSL_AES256 0x00000008L -#define SSL_AES128GCM 0x00000010L -#define SSL_AES256GCM 0x00000020L -#define SSL_CHACHA20POLY1305 0x00000040L +#define SSL_3DES 0x00000001L +#define SSL_RC4 0x00000002L +#define SSL_AES128 0x00000004L +#define SSL_AES256 0x00000008L +#define SSL_AES128GCM 0x00000010L +#define SSL_AES256GCM 0x00000020L +#define SSL_CHACHA20POLY1305 0x00000040L -#define SSL_AES (SSL_AES128|SSL_AES256|SSL_AES128GCM|SSL_AES256GCM) - +#define SSL_AES (SSL_AES128 | SSL_AES256 | SSL_AES128GCM | SSL_AES256GCM) /* Bits for algorithm_mac (symmetric authentication) */ -#define SSL_MD5 0x00000001L -#define SSL_SHA1 0x00000002L -#define SSL_SHA256 0x00000004L -#define SSL_SHA384 0x00000008L +#define SSL_MD5 0x00000001L +#define SSL_SHA1 0x00000002L +#define SSL_SHA256 0x00000004L +#define SSL_SHA384 0x00000008L /* Not a real MAC, just an indication it is part of cipher */ -#define SSL_AEAD 0x00000010L +#define SSL_AEAD 0x00000010L /* Bits for algorithm_ssl (protocol version) */ -#define SSL_SSLV3 0x00000002L -#define SSL_TLSV1 SSL_SSLV3 /* for now */ -#define SSL_TLSV1_2 0x00000004L - +#define SSL_SSLV3 0x00000002L +#define SSL_TLSV1 SSL_SSLV3 /* for now */ +#define SSL_TLSV1_2 0x00000004L /* Bits for algorithm2 (handshake digests and other extra flags) */ @@ -319,13 +341,14 @@ #define SSL_HANDSHAKE_MAC_SHA 0x20 #define SSL_HANDSHAKE_MAC_SHA256 0x40 #define SSL_HANDSHAKE_MAC_SHA384 0x80 -#define SSL_HANDSHAKE_MAC_DEFAULT (SSL_HANDSHAKE_MAC_MD5 | SSL_HANDSHAKE_MAC_SHA) +#define SSL_HANDSHAKE_MAC_DEFAULT \ + (SSL_HANDSHAKE_MAC_MD5 | SSL_HANDSHAKE_MAC_SHA) /* When adding new digest in the ssl_ciph.c and increment SSM_MD_NUM_IDX * make sure to update this constant too */ #define SSL_MAX_DIGEST 4 -#define TLS1_PRF_DGST_MASK (0xff << TLS1_PRF_DGST_SHIFT) +#define TLS1_PRF_DGST_MASK (0xff << TLS1_PRF_DGST_SHIFT) #define TLS1_PRF_DGST_SHIFT 10 #define TLS1_PRF_MD5 (SSL_HANDSHAKE_MAC_MD5 << TLS1_PRF_DGST_SHIFT) @@ -338,12 +361,12 @@ /* SSL_CIPHER_ALGORITHM2_AEAD is a flag in SSL_CIPHER.algorithm2 which * indicates that the cipher is implemented via an EVP_AEAD. */ -#define SSL_CIPHER_ALGORITHM2_AEAD (1<<23) +#define SSL_CIPHER_ALGORITHM2_AEAD (1 << 23) /* SSL_CIPHER_AEAD_FIXED_NONCE_LEN returns the number of bytes of fixed nonce * for an SSL_CIPHER* with the SSL_CIPHER_ALGORITHM2_AEAD flag. */ #define SSL_CIPHER_AEAD_FIXED_NONCE_LEN(ssl_cipher) \ - (((ssl_cipher->algorithm2 >> 24) & 0xf)*2) + (((ssl_cipher->algorithm2 >> 24) & 0xf) * 2) /* SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD is a flag in * SSL_CIPHER.algorithm2 which indicates that the variable part of the nonce is @@ -356,319 +379,272 @@ * only true of legacy cipher suites. */ #define SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD (1<<28) -/* - * Cipher strength information. - */ -#define SSL_MEDIUM 0x00000001L -#define SSL_HIGH 0x00000002L -#define SSL_FIPS 0x00000004L +/* Cipher strength information. */ +#define SSL_MEDIUM 0x00000001L +#define SSL_HIGH 0x00000002L +#define SSL_FIPS 0x00000004L /* we have used 000001ff - 23 bits left to go */ /* Check if an SSL structure is using DTLS */ -#define SSL_IS_DTLS(s) (s->enc_method->enc_flags & SSL_ENC_FLAG_DTLS) +#define SSL_IS_DTLS(s) (s->enc_method->enc_flags & SSL_ENC_FLAG_DTLS) /* See if we need explicit IV */ -#define SSL_USE_EXPLICIT_IV(s) \ - (s->enc_method->enc_flags & SSL_ENC_FLAG_EXPLICIT_IV) -/* See if we use signature algorithms extension - * and signature algorithm before signatures. - */ -#define SSL_USE_SIGALGS(s) \ - (s->enc_method->enc_flags & SSL_ENC_FLAG_SIGALGS) -/* Allow TLS 1.2 ciphersuites: applies to DTLS 1.2 as well as TLS 1.2: - * may apply to others in future. - */ -#define SSL_USE_TLS1_2_CIPHERS(s) \ - (s->enc_method->enc_flags & SSL_ENC_FLAG_TLS1_2_CIPHERS) +#define SSL_USE_EXPLICIT_IV(s) \ + (s->enc_method->enc_flags & SSL_ENC_FLAG_EXPLICIT_IV) +/* See if we use signature algorithms extension and signature algorithm before + * signatures. */ +#define SSL_USE_SIGALGS(s) (s->enc_method->enc_flags & SSL_ENC_FLAG_SIGALGS) +/* Allow TLS 1.2 ciphersuites: applies to DTLS 1.2 as well as TLS 1.2: may + * apply to others in future. */ +#define SSL_USE_TLS1_2_CIPHERS(s) \ + (s->enc_method->enc_flags & SSL_ENC_FLAG_TLS1_2_CIPHERS) /* Determine if a client can use TLS 1.2 ciphersuites: can't rely on method - * flags because it may not be set to correct version yet. - */ -#define SSL_CLIENT_USE_TLS1_2_CIPHERS(s) \ - ((SSL_IS_DTLS(s) && s->client_version <= DTLS1_2_VERSION) || \ - (!SSL_IS_DTLS(s) && s->client_version >= TLS1_2_VERSION)) + * flags because it may not be set to correct version yet. */ +#define SSL_CLIENT_USE_TLS1_2_CIPHERS(s) \ + ((SSL_IS_DTLS(s) && s->client_version <= DTLS1_2_VERSION) || \ + (!SSL_IS_DTLS(s) && s->client_version >= TLS1_2_VERSION)) /* Mostly for SSLv3 */ -#define SSL_PKEY_RSA_ENC 0 -#define SSL_PKEY_RSA_SIGN 1 -#define SSL_PKEY_ECC 2 -#define SSL_PKEY_NUM 3 +#define SSL_PKEY_RSA_ENC 0 +#define SSL_PKEY_RSA_SIGN 1 +#define SSL_PKEY_ECC 2 +#define SSL_PKEY_NUM 3 /* SSL_kRSA <- RSA_ENC | (RSA_TMP & RSA_SIGN) | * <- (EXPORT & (RSA_ENC | RSA_TMP) & RSA_SIGN) * SSL_kDH <- DH_ENC & (RSA_ENC | RSA_SIGN | DSA_SIGN) * SSL_kEDH <- RSA_ENC | RSA_SIGN | DSA_SIGN * SSL_aRSA <- RSA_ENC | RSA_SIGN - * SSL_aDSS <- DSA_SIGN - */ - -/* -#define CERT_INVALID 0 -#define CERT_PUBLIC_KEY 1 -#define CERT_PRIVATE_KEY 2 -*/ + * SSL_aDSS <- DSA_SIGN */ #define PENDING_SESSION -10000 #define CERTIFICATE_SELECTION_PENDING -10001 /* From RFC4492, used in encoding the curve type in ECParameters */ -#define EXPLICIT_PRIME_CURVE_TYPE 1 -#define EXPLICIT_CHAR2_CURVE_TYPE 2 -#define NAMED_CURVE_TYPE 3 +#define EXPLICIT_PRIME_CURVE_TYPE 1 +#define EXPLICIT_CHAR2_CURVE_TYPE 2 +#define NAMED_CURVE_TYPE 3 /* Values for the |hash_message| parameter of |s->method->ssl_get_message|. */ #define SSL_GET_MESSAGE_DONT_HASH_MESSAGE 0 #define SSL_GET_MESSAGE_HASH_MESSAGE 1 -typedef struct cert_pkey_st - { - X509 *x509; - EVP_PKEY *privatekey; - /* Chain for this certificate */ - STACK_OF(X509) *chain; - } CERT_PKEY; +typedef struct cert_pkey_st { + X509 *x509; + EVP_PKEY *privatekey; + /* Chain for this certificate */ + STACK_OF(X509) * chain; +} CERT_PKEY; -typedef struct cert_st - { - /* Current active set */ - CERT_PKEY *key; /* ALWAYS points to an element of the pkeys array - * Probably it would make more sense to store - * an index, not a pointer. */ - - /* For clients the following masks are of *disabled* key and auth - * algorithms based on the current session. - * - * TODO(davidben): Remove these. They get checked twice: when sending - * the ClientHello and when processing the ServerHello. However, - * mask_ssl is a different value both times. mask_k and mask_a are not, - * but is a round-about way of checking the server's cipher was one of - * the advertised ones. (Currently it checks the masks and then the list - * of ciphers prior to applying the masks in ClientHello.) */ - unsigned long mask_k; - unsigned long mask_a; - unsigned long mask_ssl; +typedef struct cert_st { + /* Current active set */ + CERT_PKEY *key; /* ALWAYS points to an element of the pkeys array + * Probably it would make more sense to store + * an index, not a pointer. */ - DH *dh_tmp; - DH *(*dh_tmp_cb)(SSL *ssl,int is_export,int keysize); - EC_KEY *ecdh_tmp; - /* Callback for generating ephemeral ECDH keys */ - EC_KEY *(*ecdh_tmp_cb)(SSL *ssl,int is_export,int keysize); - /* Select ECDH parameters automatically */ - int ecdh_tmp_auto; - /* Flags related to certificates */ - unsigned int cert_flags; - CERT_PKEY pkeys[SSL_PKEY_NUM]; + /* For clients the following masks are of *disabled* key and auth algorithms + * based on the current session. + * + * TODO(davidben): Remove these. They get checked twice: when sending the + * ClientHello and when processing the ServerHello. However, mask_ssl is a + * different value both times. mask_k and mask_a are not, but is a + * round-about way of checking the server's cipher was one of the advertised + * ones. (Currently it checks the masks and then the list of ciphers prior to + * applying the masks in ClientHello.) */ + unsigned long mask_k; + unsigned long mask_a; + unsigned long mask_ssl; - /* Server-only: client_certificate_types is list of certificate types to - * include in the CertificateRequest message. - */ - unsigned char *client_certificate_types; - size_t num_client_certificate_types; + DH *dh_tmp; + DH *(*dh_tmp_cb)(SSL *ssl, int is_export, int keysize); + EC_KEY *ecdh_tmp; + /* Callback for generating ephemeral ECDH keys */ + EC_KEY *(*ecdh_tmp_cb)(SSL *ssl, int is_export, int keysize); + /* Select ECDH parameters automatically */ + int ecdh_tmp_auto; + /* Flags related to certificates */ + unsigned int cert_flags; + CERT_PKEY pkeys[SSL_PKEY_NUM]; - /* signature algorithms peer reports: e.g. supported signature - * algorithms extension for server or as part of a certificate - * request for client. - */ - unsigned char *peer_sigalgs; - /* Size of above array */ - size_t peer_sigalgslen; - /* suppported signature algorithms. - * When set on a client this is sent in the client hello as the - * supported signature algorithms extension. For servers - * it represents the signature algorithms we are willing to use. - */ - unsigned char *conf_sigalgs; - /* Size of above array */ - size_t conf_sigalgslen; - /* Client authentication signature algorithms, if not set then - * uses conf_sigalgs. On servers these will be the signature - * algorithms sent to the client in a cerificate request for TLS 1.2. - * On a client this represents the signature algortithms we are - * willing to use for client authentication. - */ - unsigned char *client_sigalgs; - /* Size of above array */ - size_t client_sigalgslen; - /* Signature algorithms shared by client and server: cached - * because these are used most often. - */ - TLS_SIGALGS *shared_sigalgs; - size_t shared_sigalgslen; + /* Server-only: client_certificate_types is list of certificate types to + * include in the CertificateRequest message. + */ + uint8_t *client_certificate_types; + size_t num_client_certificate_types; - /* Certificate setup callback: if set is called whenever a - * certificate may be required (client or server). the callback - * can then examine any appropriate parameters and setup any - * certificates required. This allows advanced applications - * to select certificates on the fly: for example based on - * supported signature algorithms or curves. - */ - int (*cert_cb)(SSL *ssl, void *arg); - void *cert_cb_arg; + /* signature algorithms peer reports: e.g. supported signature + * algorithms extension for server or as part of a certificate + * request for client. */ + uint8_t *peer_sigalgs; + /* Size of above array */ + size_t peer_sigalgslen; + /* suppported signature algorithms. + * When set on a client this is sent in the client hello as the + * supported signature algorithms extension. For servers + * it represents the signature algorithms we are willing to use. */ + uint8_t *conf_sigalgs; + /* Size of above array */ + size_t conf_sigalgslen; + /* Client authentication signature algorithms, if not set then + * uses conf_sigalgs. On servers these will be the signature + * algorithms sent to the client in a cerificate request for TLS 1.2. + * On a client this represents the signature algortithms we are + * willing to use for client authentication. */ + uint8_t *client_sigalgs; + /* Size of above array */ + size_t client_sigalgslen; + /* Signature algorithms shared by client and server: cached + * because these are used most often. */ + TLS_SIGALGS *shared_sigalgs; + size_t shared_sigalgslen; - /* Optional X509_STORE for chain building or certificate validation - * If NULL the parent SSL_CTX store is used instead. - */ - X509_STORE *chain_store; - X509_STORE *verify_store; + /* Certificate setup callback: if set is called whenever a + * certificate may be required (client or server). the callback + * can then examine any appropriate parameters and setup any + * certificates required. This allows advanced applications + * to select certificates on the fly: for example based on + * supported signature algorithms or curves. */ + int (*cert_cb)(SSL *ssl, void *arg); + void *cert_cb_arg; - /* Raw values of the cipher list from a client */ - unsigned char *ciphers_raw; - size_t ciphers_rawlen; - } CERT; + /* Optional X509_STORE for chain building or certificate validation + * If NULL the parent SSL_CTX store is used instead. */ + X509_STORE *chain_store; + X509_STORE *verify_store; + /* Raw values of the cipher list from a client */ + uint8_t *ciphers_raw; + size_t ciphers_rawlen; +} CERT; -typedef struct sess_cert_st - { - STACK_OF(X509) *cert_chain; /* as received from peer (not for SSL2) */ +typedef struct sess_cert_st { + STACK_OF(X509) * cert_chain; /* as received from peer (not for SSL2) */ - /* The 'peer_...' members are used only by clients. */ - int peer_cert_type; + /* The 'peer_...' members are used only by clients. */ + int peer_cert_type; - CERT_PKEY *peer_key; /* points to an element of peer_pkeys (never NULL!) */ - CERT_PKEY peer_pkeys[SSL_PKEY_NUM]; - /* Obviously we don't have the private keys of these, - * so maybe we shouldn't even use the CERT_PKEY type here. */ + CERT_PKEY *peer_key; /* points to an element of peer_pkeys (never NULL!) */ + CERT_PKEY peer_pkeys[SSL_PKEY_NUM]; + /* Obviously we don't have the private keys of these, + * so maybe we shouldn't even use the CERT_PKEY type here. */ - DH *peer_dh_tmp; - EC_KEY *peer_ecdh_tmp; - } SESS_CERT; + DH *peer_dh_tmp; + EC_KEY *peer_ecdh_tmp; +} SESS_CERT; + /* Structure containing decoded values of signature algorithms extension */ -struct tls_sigalgs_st - { - /* NID of hash algorithm */ - int hash_nid; - /* NID of signature algorithm */ - int sign_nid; - /* Combined hash and signature NID */ - int signandhash_nid; - /* Raw values used in extension */ - unsigned char rsign; - unsigned char rhash; - }; +struct tls_sigalgs_st { + /* NID of hash algorithm */ + int hash_nid; + /* NID of signature algorithm */ + int sign_nid; + /* Combined hash and signature NID */ + int signandhash_nid; + /* Raw values used in extension */ + uint8_t rsign; + uint8_t rhash; +}; -/*#define MAC_DEBUG */ - -/*#define ERR_DEBUG */ -/*#define ABORT_DEBUG */ -/*#define PKT_DEBUG 1 */ -/*#define DES_DEBUG */ -/*#define DES_OFB_DEBUG */ -/*#define SSL_DEBUG */ -/*#define RSA_DEBUG */ -/*#define IDEA_DEBUG */ - -#define FP_ICC (int (*)(const void *,const void *)) - -/* SSL_METHOD is a compatibility structure to support the legacy - * version-locked methods. */ -struct ssl_method_st - { - /* version, if non-zero, is the only protocol version acceptable to an - * SSL_CTX initialized from this method. */ - uint16_t version; - /* method is the underlying SSL_PROTOCOL_METHOD that initializes the - * SSL_CTX. */ - const SSL_PROTOCOL_METHOD *method; - }; +/* SSL_METHOD is a compatibility structure to support the legacy version-locked + * methods. */ +struct ssl_method_st { + /* version, if non-zero, is the only protocol version acceptable to an + * SSL_CTX initialized from this method. */ + uint16_t version; + /* method is the underlying SSL_PROTOCOL_METHOD that initializes the + * SSL_CTX. */ + const SSL_PROTOCOL_METHOD *method; +}; /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ -struct ssl_protocol_method_st - { - int (*ssl_new)(SSL *s); - void (*ssl_clear)(SSL *s); - void (*ssl_free)(SSL *s); - int (*ssl_accept)(SSL *s); - int (*ssl_connect)(SSL *s); - int (*ssl_read)(SSL *s,void *buf,int len); - int (*ssl_peek)(SSL *s,void *buf,int len); - int (*ssl_write)(SSL *s,const void *buf,int len); - int (*ssl_shutdown)(SSL *s); - int (*ssl_renegotiate)(SSL *s); - int (*ssl_renegotiate_check)(SSL *s); - long (*ssl_get_message)(SSL *s, int header_state, int body_state, - int msg_type, long max, int hash_message, - int *ok); - int (*ssl_read_bytes)(SSL *s, int type, unsigned char *buf, int len, - int peek); - int (*ssl_write_bytes)(SSL *s, int type, const void *buf_, int len); - int (*ssl_dispatch_alert)(SSL *s); - long (*ssl_ctrl)(SSL *s,int cmd,long larg,void *parg); - long (*ssl_ctx_ctrl)(SSL_CTX *ctx,int cmd,long larg,void *parg); - int (*ssl_pending)(const SSL *s); - int (*num_ciphers)(void); - const SSL_CIPHER *(*get_cipher)(unsigned ncipher); - int (*ssl_version)(void); - long (*ssl_callback_ctrl)(SSL *s, int cb_id, void (*fp)(void)); - long (*ssl_ctx_callback_ctrl)(SSL_CTX *s, int cb_id, void (*fp)(void)); - }; +struct ssl_protocol_method_st { + int (*ssl_new)(SSL *s); + void (*ssl_clear)(SSL *s); + void (*ssl_free)(SSL *s); + int (*ssl_accept)(SSL *s); + int (*ssl_connect)(SSL *s); + int (*ssl_read)(SSL *s, void *buf, int len); + int (*ssl_peek)(SSL *s, void *buf, int len); + int (*ssl_write)(SSL *s, const void *buf, int len); + int (*ssl_shutdown)(SSL *s); + int (*ssl_renegotiate)(SSL *s); + int (*ssl_renegotiate_check)(SSL *s); + long (*ssl_get_message)(SSL *s, int header_state, int body_state, + int msg_type, long max, int hash_message, int *ok); + int (*ssl_read_bytes)(SSL *s, int type, uint8_t *buf, int len, int peek); + int (*ssl_write_bytes)(SSL *s, int type, const void *buf_, int len); + int (*ssl_dispatch_alert)(SSL *s); + long (*ssl_ctrl)(SSL *s, int cmd, long larg, void *parg); + long (*ssl_ctx_ctrl)(SSL_CTX *ctx, int cmd, long larg, void *parg); + int (*ssl_pending)(const SSL *s); + int (*num_ciphers)(void); + const SSL_CIPHER *(*get_cipher)(unsigned ncipher); + int (*ssl_version)(void); + long (*ssl_callback_ctrl)(SSL *s, int cb_id, void (*fp)(void)); + long (*ssl_ctx_callback_ctrl)(SSL_CTX *s, int cb_id, void (*fp)(void)); +}; -/* This is for the SSLv3/TLSv1.0 differences in crypto/hash stuff - * It is a bit of a mess of functions, but hell, think of it as - * an opaque structure :-) */ -struct ssl3_enc_method - { - int (*enc)(SSL *, int); - int (*mac)(SSL *, unsigned char *, int); - int (*setup_key_block)(SSL *); - int (*generate_master_secret)(SSL *, unsigned char *, unsigned char *, int); - int (*change_cipher_state)(SSL *, int); - int (*final_finish_mac)(SSL *, const char *, int, unsigned char *); - int finish_mac_length; - int (*cert_verify_mac)(SSL *, int, unsigned char *); - const char *client_finished_label; - int client_finished_label_len; - const char *server_finished_label; - int server_finished_label_len; - int (*alert_value)(int); - int (*export_keying_material)(SSL *, unsigned char *, size_t, - const char *, size_t, - const unsigned char *, size_t, - int use_context); - /* Various flags indicating protocol version requirements */ - unsigned int enc_flags; - /* Handshake header length */ - unsigned int hhlen; - /* Set the handshake header */ - void (*set_handshake_header)(SSL *s, int type, unsigned long len); - /* Write out handshake message */ - int (*do_write)(SSL *s); - }; +/* This is for the SSLv3/TLSv1.0 differences in crypto/hash stuff It is a bit + * of a mess of functions, but hell, think of it as an opaque structure. */ +struct ssl3_enc_method { + int (*enc)(SSL *, int); + int (*mac)(SSL *, uint8_t *, int); + int (*setup_key_block)(SSL *); + int (*generate_master_secret)(SSL *, uint8_t *, uint8_t *, int); + int (*change_cipher_state)(SSL *, int); + int (*final_finish_mac)(SSL *, const char *, int, uint8_t *); + int finish_mac_length; + int (*cert_verify_mac)(SSL *, int, uint8_t *); + const char *client_finished_label; + int client_finished_label_len; + const char *server_finished_label; + int server_finished_label_len; + int (*alert_value)(int); + int (*export_keying_material)(SSL *, uint8_t *, size_t, const char *, size_t, + const uint8_t *, size_t, int use_context); + /* Various flags indicating protocol version requirements */ + unsigned int enc_flags; + /* Handshake header length */ + unsigned int hhlen; + /* Set the handshake header */ + void (*set_handshake_header)(SSL *s, int type, unsigned long len); + /* Write out handshake message */ + int (*do_write)(SSL *s); +}; -#define SSL_HM_HEADER_LENGTH(s) s->enc_method->hhlen +#define SSL_HM_HEADER_LENGTH(s) s->enc_method->hhlen #define ssl_handshake_start(s) \ - (((unsigned char *)s->init_buf->data) + s->enc_method->hhlen) + (((uint8_t *)s->init_buf->data) + s->enc_method->hhlen) #define ssl_set_handshake_header(s, htype, len) \ - s->enc_method->set_handshake_header(s, htype, len) -#define ssl_do_write(s) s->enc_method->do_write(s) + s->enc_method->set_handshake_header(s, htype, len) +#define ssl_do_write(s) s->enc_method->do_write(s) /* Values for enc_flags */ /* Uses explicit IV for CBC mode */ -#define SSL_ENC_FLAG_EXPLICIT_IV 0x1 +#define SSL_ENC_FLAG_EXPLICIT_IV 0x1 /* Uses signature algorithms extension */ -#define SSL_ENC_FLAG_SIGALGS 0x2 +#define SSL_ENC_FLAG_SIGALGS 0x2 /* Uses SHA256 default PRF */ -#define SSL_ENC_FLAG_SHA256_PRF 0x4 +#define SSL_ENC_FLAG_SHA256_PRF 0x4 /* Is DTLS */ -#define SSL_ENC_FLAG_DTLS 0x8 +#define SSL_ENC_FLAG_DTLS 0x8 /* Allow TLS 1.2 ciphersuites: applies to DTLS 1.2 as well as TLS 1.2: - * may apply to others in future. - */ -#define SSL_ENC_FLAG_TLS1_2_CIPHERS 0x10 + * may apply to others in future. */ +#define SSL_ENC_FLAG_TLS1_2_CIPHERS 0x10 /* ssl_aead_ctx_st contains information about an AEAD that is being used to * encrypt an SSL connection. */ -struct ssl_aead_ctx_st - { - EVP_AEAD_CTX ctx; - /* fixed_nonce contains any bytes of the nonce that are fixed for all - * records. */ - unsigned char fixed_nonce[8]; - unsigned char fixed_nonce_len, variable_nonce_len, tag_len; - /* variable_nonce_included_in_record is non-zero if the variable nonce - * for a record is included as a prefix before the ciphertext. */ - char variable_nonce_included_in_record; - }; - +struct ssl_aead_ctx_st { + EVP_AEAD_CTX ctx; + /* fixed_nonce contains any bytes of the nonce that are fixed for all + * records. */ + uint8_t fixed_nonce[8]; + uint8_t fixed_nonce_len, variable_nonce_len, tag_len; + /* variable_nonce_included_in_record is non-zero if the variable nonce + * for a record is included as a prefix before the ciphertext. */ + char variable_nonce_included_in_record; +}; extern const SSL_CIPHER ssl3_ciphers[]; @@ -692,36 +668,39 @@ int ssl_get_prev_session(SSL *s, const struct ssl_early_callback_ctx *ctx); int ssl_cipher_id_cmp(const void *in_a, const void *in_b); int ssl_cipher_ptr_id_cmp(const SSL_CIPHER **ap, const SSL_CIPHER **bp); -STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, const CBS *cbs); -int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, uint8_t *p); -STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_PROTOCOL_METHOD *meth, - struct ssl_cipher_preference_list_st **pref, - STACK_OF(SSL_CIPHER) **sorted, - const char *rule_str, CERT *c); -struct ssl_cipher_preference_list_st* ssl_cipher_preference_list_dup( - struct ssl_cipher_preference_list_st *cipher_list); +STACK_OF(SSL_CIPHER) * ssl_bytes_to_cipher_list(SSL *s, const CBS *cbs); +int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) * sk, uint8_t *p); +STACK_OF(SSL_CIPHER) * + ssl_create_cipher_list(const SSL_PROTOCOL_METHOD *meth, + struct ssl_cipher_preference_list_st **pref, + STACK_OF(SSL_CIPHER) * *sorted, const char *rule_str, + CERT *c); +struct ssl_cipher_preference_list_st *ssl_cipher_preference_list_dup( + struct ssl_cipher_preference_list_st *cipher_list); void ssl_cipher_preference_list_free( - struct ssl_cipher_preference_list_st *cipher_list); -struct ssl_cipher_preference_list_st* ssl_cipher_preference_list_from_ciphers( - STACK_OF(SSL_CIPHER) *ciphers); -struct ssl_cipher_preference_list_st* ssl_get_cipher_preferences(SSL *s); + struct ssl_cipher_preference_list_st *cipher_list); +struct ssl_cipher_preference_list_st *ssl_cipher_preference_list_from_ciphers( + STACK_OF(SSL_CIPHER) * ciphers); +struct ssl_cipher_preference_list_st *ssl_get_cipher_preferences(SSL *s); int ssl_cipher_get_evp_aead(const SSL_SESSION *s, const EVP_AEAD **aead); -int ssl_cipher_get_evp(const SSL_SESSION *s,const EVP_CIPHER **enc, - const EVP_MD **md,int *mac_pkey_type,int *mac_secret_size); -int ssl_cipher_get_mac(const SSL_SESSION *s, const EVP_MD **md, int *mac_pkey_type, int *mac_secret_size); -int ssl_get_handshake_digest(int i,long *mask,const EVP_MD **md); +int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc, + const EVP_MD **md, int *mac_pkey_type, + int *mac_secret_size); +int ssl_cipher_get_mac(const SSL_SESSION *s, const EVP_MD **md, + int *mac_pkey_type, int *mac_secret_size); +int ssl_get_handshake_digest(int i, long *mask, const EVP_MD **md); int ssl_cipher_get_cert_index(const SSL_CIPHER *c); int ssl_cipher_has_server_public_key(const SSL_CIPHER *cipher); int ssl_cipher_requires_server_key_exchange(const SSL_CIPHER *cipher); -int ssl_cert_set0_chain(CERT *c, STACK_OF(X509) *chain); -int ssl_cert_set1_chain(CERT *c, STACK_OF(X509) *chain); +int ssl_cert_set0_chain(CERT *c, STACK_OF(X509) * chain); +int ssl_cert_set1_chain(CERT *c, STACK_OF(X509) * chain); int ssl_cert_add0_chain_cert(CERT *c, X509 *x); int ssl_cert_add1_chain_cert(CERT *c, X509 *x); int ssl_cert_select_current(CERT *c, X509 *x); void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg), void *arg); -int ssl_verify_cert_chain(SSL *s,STACK_OF(X509) *sk); +int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) * sk); int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l); int ssl_build_cert_chain(CERT *c, X509_STORE *chain_store, int flags); int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain, int ref); @@ -729,7 +708,7 @@ int ssl_undefined_void_function(void); int ssl_undefined_const_function(const SSL *s); CERT_PKEY *ssl_get_server_send_pkey(const SSL *s); -EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *c); +EVP_PKEY *ssl_get_sign_pkey(SSL *s, const SSL_CIPHER *c); int ssl_cert_type(EVP_PKEY *pkey); /* ssl_get_compatible_server_ciphers determines the key exchange and @@ -737,9 +716,9 @@ * and current ClientHello parameters of |s|. It sets |*out_mask_k| to the key * exchange mask and |*out_mask_a| to the authentication mask. */ void ssl_get_compatible_server_ciphers(SSL *s, unsigned long *out_mask_k, - unsigned long *out_mask_a); + unsigned long *out_mask_a); -STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s); +STACK_OF(SSL_CIPHER) * ssl_get_ciphers_by_id(SSL *s); int ssl_verify_alarm_type(long type); int ssl_fill_hello_random(SSL *s, int server, uint8_t *field, size_t len); @@ -749,18 +728,17 @@ int ssl3_send_server_certificate(SSL *s); int ssl3_send_new_session_ticket(SSL *s); int ssl3_send_cert_status(SSL *s); -int ssl3_get_finished(SSL *s,int state_a,int state_b); +int ssl3_get_finished(SSL *s, int state_a, int state_b); int ssl3_setup_key_block(SSL *s); -int ssl3_send_change_cipher_spec(SSL *s,int state_a,int state_b); -int ssl3_change_cipher_state(SSL *s,int which); +int ssl3_send_change_cipher_spec(SSL *s, int state_a, int state_b); +int ssl3_change_cipher_state(SSL *s, int which); void ssl3_cleanup_key_block(SSL *s); int ssl3_do_write(SSL *s, int type); -int ssl3_send_alert(SSL *s,int level, int desc); -int ssl3_generate_master_secret(SSL *s, unsigned char *out, - unsigned char *p, int len); -int ssl3_get_req_cert_type(SSL *s,unsigned char *p); +int ssl3_send_alert(SSL *s, int level, int desc); +int ssl3_generate_master_secret(SSL *s, uint8_t *out, uint8_t *p, int len); +int ssl3_get_req_cert_type(SSL *s, uint8_t *p); long ssl3_get_message(SSL *s, int header_state, int body_state, int msg_type, - long max, int hash_message, int *ok); + long max, int hash_message, int *ok); /* ssl3_hash_current_message incorporates the current handshake message into * the handshake hash. */ @@ -772,66 +750,68 @@ * for the hash function, otherwise the hash function depends on the type of * |pkey| and is written to |*out_md|. It returns one on success and zero on * failure. */ -int ssl3_cert_verify_hash(SSL *s, uint8_t *out, size_t *out_len, const EVP_MD **out_md, EVP_PKEY *pkey); +int ssl3_cert_verify_hash(SSL *s, uint8_t *out, size_t *out_len, + const EVP_MD **out_md, EVP_PKEY *pkey); -int ssl3_send_finished(SSL *s, int a, int b, const char *sender,int slen); +int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen); int ssl3_num_ciphers(void); const SSL_CIPHER *ssl3_get_cipher(unsigned int u); -int ssl3_renegotiate(SSL *ssl); -int ssl3_renegotiate_check(SSL *ssl); +int ssl3_renegotiate(SSL *ssl); +int ssl3_renegotiate_check(SSL *ssl); int ssl3_dispatch_alert(SSL *s); int ssl3_expect_change_cipher_spec(SSL *s); -int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek); +int ssl3_read_bytes(SSL *s, int type, uint8_t *buf, int len, int peek); int ssl3_write_bytes(SSL *s, int type, const void *buf, int len); -int ssl3_final_finish_mac(SSL *s, const char *sender, int slen,unsigned char *p); -int ssl3_cert_verify_mac(SSL *s, int md_nid, unsigned char *p); -void ssl3_finish_mac(SSL *s, const unsigned char *buf, int len); +int ssl3_final_finish_mac(SSL *s, const char *sender, int slen, uint8_t *p); +int ssl3_cert_verify_mac(SSL *s, int md_nid, uint8_t *p); +void ssl3_finish_mac(SSL *s, const uint8_t *buf, int len); int ssl3_enc(SSL *s, int send_data); -int n_ssl3_mac(SSL *ssl, unsigned char *md, int send_data); +int n_ssl3_mac(SSL *ssl, uint8_t *md, int send_data); void ssl3_free_digest_list(SSL *s); unsigned long ssl3_output_cert_chain(SSL *s, CERT_PKEY *cpk); -const SSL_CIPHER *ssl3_choose_cipher(SSL *ssl,STACK_OF(SSL_CIPHER) *clnt, - struct ssl_cipher_preference_list_st *srvr); -int ssl3_setup_buffers(SSL *s); -int ssl3_setup_read_buffer(SSL *s); -int ssl3_setup_write_buffer(SSL *s); -int ssl3_release_read_buffer(SSL *s); -int ssl3_release_write_buffer(SSL *s); +const SSL_CIPHER *ssl3_choose_cipher( + SSL *ssl, STACK_OF(SSL_CIPHER) * clnt, + struct ssl_cipher_preference_list_st *srvr); +int ssl3_setup_buffers(SSL *s); +int ssl3_setup_read_buffer(SSL *s); +int ssl3_setup_write_buffer(SSL *s); +int ssl3_release_read_buffer(SSL *s); +int ssl3_release_write_buffer(SSL *s); enum should_free_handshake_buffer_t { - free_handshake_buffer, - dont_free_handshake_buffer, + free_handshake_buffer, + dont_free_handshake_buffer, }; -int ssl3_digest_cached_records(SSL *s, enum should_free_handshake_buffer_t); +int ssl3_digest_cached_records(SSL *s, enum should_free_handshake_buffer_t); -int ssl3_new(SSL *s); -void ssl3_free(SSL *s); -int ssl3_accept(SSL *s); -int ssl3_connect(SSL *s); -int ssl3_read(SSL *s, void *buf, int len); -int ssl3_peek(SSL *s, void *buf, int len); -int ssl3_write(SSL *s, const void *buf, int len); -int ssl3_shutdown(SSL *s); -void ssl3_clear(SSL *s); -long ssl3_ctrl(SSL *s,int cmd, long larg, void *parg); -long ssl3_ctx_ctrl(SSL_CTX *s,int cmd, long larg, void *parg); -long ssl3_callback_ctrl(SSL *s,int cmd, void (*fp)(void)); -long ssl3_ctx_callback_ctrl(SSL_CTX *s,int cmd, void (*fp)(void)); -int ssl3_pending(const SSL *s); +int ssl3_new(SSL *s); +void ssl3_free(SSL *s); +int ssl3_accept(SSL *s); +int ssl3_connect(SSL *s); +int ssl3_read(SSL *s, void *buf, int len); +int ssl3_peek(SSL *s, void *buf, int len); +int ssl3_write(SSL *s, const void *buf, int len); +int ssl3_shutdown(SSL *s); +void ssl3_clear(SSL *s); +long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg); +long ssl3_ctx_ctrl(SSL_CTX *s, int cmd, long larg, void *parg); +long ssl3_callback_ctrl(SSL *s, int cmd, void (*fp)(void)); +long ssl3_ctx_callback_ctrl(SSL_CTX *s, int cmd, void (*fp)(void)); +int ssl3_pending(const SSL *s); -void ssl3_record_sequence_update(unsigned char *seq); +void ssl3_record_sequence_update(uint8_t *seq); int ssl3_do_change_cipher_spec(SSL *ssl); void ssl3_set_handshake_header(SSL *s, int htype, unsigned long len); int ssl3_handshake_write(SSL *s); -int dtls1_do_write(SSL *s,int type); +int dtls1_do_write(SSL *s, int type); int ssl3_read_n(SSL *s, int n, int max, int extend); -int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek); -int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, - unsigned int len); +int dtls1_read_bytes(SSL *s, int type, uint8_t *buf, int len, int peek); +int ssl3_write_pending(SSL *s, int type, const uint8_t *buf, unsigned int len); void dtls1_set_message_header(SSL *s, uint8_t mt, unsigned long len, - unsigned short seq_num, unsigned long frag_off, unsigned long frag_len); + unsigned short seq_num, unsigned long frag_off, + unsigned long frag_len); int dtls1_write_app_data_bytes(SSL *s, int type, const void *buf, int len); int dtls1_write_bytes(SSL *s, int type, const void *buf, int len); @@ -841,13 +821,13 @@ unsigned long dtls1_output_cert_chain(SSL *s, CERT_PKEY *cpk); int dtls1_read_failed(SSL *s, int code); int dtls1_buffer_message(SSL *s, int ccs); -int dtls1_retransmit_message(SSL *s, unsigned short seq, - unsigned long frag_off, int *found); +int dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off, + int *found); int dtls1_get_queue_priority(unsigned short seq, int is_ccs); int dtls1_retransmit_buffered_messages(SSL *s); void dtls1_clear_record_buffer(SSL *s); -void dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr); -void dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr); +void dtls1_get_message_header(uint8_t *data, struct hm_header_st *msg_hdr); +void dtls1_get_ccs_header(uint8_t *data, struct ccs_header_st *ccs_hdr); void dtls1_reset_seq_numbers(SSL *s, int rw); int dtls1_check_timeout_num(SSL *s); int dtls1_handle_timeout(SSL *s); @@ -894,14 +874,15 @@ int ssl3_get_channel_id(SSL *s); int dtls1_new(SSL *s); -int dtls1_accept(SSL *s); -int dtls1_connect(SSL *s); +int dtls1_accept(SSL *s); +int dtls1_connect(SSL *s); void dtls1_free(SSL *s); void dtls1_clear(SSL *s); -long dtls1_ctrl(SSL *s,int cmd, long larg, void *parg); +long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg); int dtls1_shutdown(SSL *s); -long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int hash_message, int *ok); +long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, + int hash_message, int *ok); int dtls1_get_record(SSL *s); int dtls1_dispatch_alert(SSL *s); @@ -911,16 +892,14 @@ int tls1_change_cipher_state(SSL *s, int which); int tls1_setup_key_block(SSL *s); int tls1_enc(SSL *s, int snd); -int tls1_handshake_digest(SSL *s, unsigned char *out, size_t out_len); -int tls1_final_finish_mac(SSL *s, - const char *str, int slen, unsigned char *p); -int tls1_cert_verify_mac(SSL *s, int md_nid, unsigned char *p); -int tls1_mac(SSL *ssl, unsigned char *md, int snd); -int tls1_generate_master_secret(SSL *s, unsigned char *out, - unsigned char *p, int len); -int tls1_export_keying_material(SSL *s, unsigned char *out, size_t olen, - const char *label, size_t llen, - const unsigned char *p, size_t plen, int use_context); +int tls1_handshake_digest(SSL *s, uint8_t *out, size_t out_len); +int tls1_final_finish_mac(SSL *s, const char *str, int slen, uint8_t *p); +int tls1_cert_verify_mac(SSL *s, int md_nid, uint8_t *p); +int tls1_mac(SSL *ssl, uint8_t *md, int snd); +int tls1_generate_master_secret(SSL *s, uint8_t *out, uint8_t *p, int len); +int tls1_export_keying_material(SSL *s, uint8_t *out, size_t olen, + const char *label, size_t llen, + const uint8_t *p, size_t plen, int use_context); int tls1_alert_code(int code); int ssl3_alert_code(int code); int ssl_ok(SSL *s); @@ -947,7 +926,7 @@ * returns one and writes the array to |*out_curve_ids| and its size to * |*out_curve_ids_len|. Otherwise, it returns zero. */ int tls1_set_curves(uint16_t **out_curve_ids, size_t *out_curve_ids_len, - const int *curves, size_t ncurves); + const int *curves, size_t ncurves); /* tls1_check_ec_cert returns one if |x| is an ECC certificate with curve and * point format compatible with the client's preferences. Otherwise it returns @@ -958,25 +937,23 @@ * client extensions and zero otherwise. */ int tls1_check_ec_tmp_key(SSL *s); -int tls1_shared_list(SSL *s, - const unsigned char *l1, size_t l1len, - const unsigned char *l2, size_t l2len, - int nmatch); -unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned char *limit, size_t header_len); -unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned char *limit); +int tls1_shared_list(SSL *s, const uint8_t *l1, size_t l1len, const uint8_t *l2, + size_t l2len, int nmatch); +uint8_t *ssl_add_clienthello_tlsext(SSL *s, uint8_t *buf, uint8_t *limit, + size_t header_len); +uint8_t *ssl_add_serverhello_tlsext(SSL *s, uint8_t *buf, uint8_t *limit); int ssl_parse_clienthello_tlsext(SSL *s, CBS *cbs); int ssl_parse_serverhello_tlsext(SSL *s, CBS *cbs); int ssl_prepare_clienthello_tlsext(SSL *s); int ssl_prepare_serverhello_tlsext(SSL *s); -#define tlsext_tick_md EVP_sha256 +#define tlsext_tick_md EVP_sha256 int tls1_process_ticket(SSL *s, const struct ssl_early_callback_ctx *ctx, - SSL_SESSION **ret); + SSL_SESSION **ret); -int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk, - const EVP_MD *md); +int tls12_get_sigandhash(uint8_t *p, const EVP_PKEY *pk, const EVP_MD *md); int tls12_get_sigid(const EVP_PKEY *pk); -const EVP_MD *tls12_get_hash(unsigned char hash_alg); +const EVP_MD *tls12_get_hash(uint8_t hash_alg); int tls1_channel_id_hash(EVP_MD_CTX *ctx, SSL *s); int tls1_record_handshake_hashes_for_channel_id(SSL *s); @@ -988,15 +965,17 @@ * enabled. It returns one on success and zero on failure. The entry is * identified by the first 8 bytes of |encrypted_premaster|. */ int ssl_ctx_log_rsa_client_key_exchange(SSL_CTX *ctx, - const uint8_t *encrypted_premaster, size_t encrypted_premaster_len, - const uint8_t *premaster, size_t premaster_len); + const uint8_t *encrypted_premaster, + size_t encrypted_premaster_len, + const uint8_t *premaster, + size_t premaster_len); /* ssl_ctx_log_master_secret logs |master| to |ctx|, if logging is enabled. It * returns one on success and zero on failure. The entry is identified by * |client_random|. */ -int ssl_ctx_log_master_secret(SSL_CTX *ctx, - const uint8_t *client_random, size_t client_random_len, - const uint8_t *master, size_t master_len); +int ssl_ctx_log_master_secret(SSL_CTX *ctx, const uint8_t *client_random, + size_t client_random_len, const uint8_t *master, + size_t master_len); int ssl3_can_cutthrough(const SSL *s); @@ -1023,13 +1002,13 @@ * version for |s| and zero otherwise. */ int ssl3_is_version_enabled(SSL *s, uint16_t version); -EVP_MD_CTX* ssl_replace_hash(EVP_MD_CTX **hash,const EVP_MD *md) ; +EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash, const EVP_MD *md); void ssl_clear_hash_ctx(EVP_MD_CTX **hash); -int ssl_add_serverhello_renegotiate_ext(SSL *s, unsigned char *p, int *len, - int maxlen); +int ssl_add_serverhello_renegotiate_ext(SSL *s, uint8_t *p, int *len, + int maxlen); int ssl_parse_serverhello_renegotiate_ext(SSL *s, CBS *cbs, int *out_alert); -int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len, - int maxlen); +int ssl_add_clienthello_renegotiate_ext(SSL *s, uint8_t *p, int *len, + int maxlen); int ssl_parse_clienthello_renegotiate_ext(SSL *s, CBS *cbs, int *out_alert); long ssl_get_algorithm2(SSL *s); int tls1_process_sigalgs(SSL *s, const CBS *sigalgs); @@ -1038,39 +1017,29 @@ * peer's preferences recorded for |s| and the digests supported by |pkey|. */ const EVP_MD *tls1_choose_signing_digest(SSL *s, EVP_PKEY *pkey); -size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs); +size_t tls12_get_psigalgs(SSL *s, const uint8_t **psigs); int tls12_check_peer_sigalg(const EVP_MD **out_md, int *out_alert, SSL *s, - CBS *cbs, EVP_PKEY *pkey); + CBS *cbs, EVP_PKEY *pkey); void ssl_set_client_disabled(SSL *s); -int ssl_add_clienthello_use_srtp_ext(SSL *s, unsigned char *p, int *len, int maxlen); +int ssl_add_clienthello_use_srtp_ext(SSL *s, uint8_t *p, int *len, int maxlen); int ssl_parse_clienthello_use_srtp_ext(SSL *s, CBS *cbs, int *out_alert); -int ssl_add_serverhello_use_srtp_ext(SSL *s, unsigned char *p, int *len, int maxlen); +int ssl_add_serverhello_use_srtp_ext(SSL *s, uint8_t *p, int *len, int maxlen); int ssl_parse_serverhello_use_srtp_ext(SSL *s, CBS *cbs, int *out_alert); /* s3_cbc.c */ -void ssl3_cbc_copy_mac(unsigned char* out, - const SSL3_RECORD *rec, - unsigned md_size,unsigned orig_len); -int ssl3_cbc_remove_padding(const SSL* s, - SSL3_RECORD *rec, - unsigned block_size, - unsigned mac_size); -int tls1_cbc_remove_padding(const SSL* s, - SSL3_RECORD *rec, - unsigned block_size, - unsigned mac_size); +void ssl3_cbc_copy_mac(uint8_t *out, const SSL3_RECORD *rec, unsigned md_size, + unsigned orig_len); +int ssl3_cbc_remove_padding(const SSL *s, SSL3_RECORD *rec, unsigned block_size, + unsigned mac_size); +int tls1_cbc_remove_padding(const SSL *s, SSL3_RECORD *rec, unsigned block_size, + unsigned mac_size); char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx); -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); +int ssl3_cbc_digest_record(const EVP_MD_CTX *ctx, uint8_t *md_out, + size_t *md_out_size, const uint8_t header[13], + const uint8_t *data, size_t data_plus_mac_size, + size_t data_plus_mac_plus_padding_size, + const uint8_t *mac_secret, + unsigned mac_secret_length, char is_sslv3); #endif
diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c index bb91b7d..3d1bc62 100644 --- a/ssl/ssl_rsa.c +++ b/ssl/ssl_rsa.c
@@ -68,693 +68,640 @@ static int ssl_set_cert(CERT *c, X509 *x509); static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey); -int SSL_use_certificate(SSL *ssl, X509 *x) - { - if (x == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_use_certificate, ERR_R_PASSED_NULL_PARAMETER); - return(0); - } - if (!ssl_cert_inst(&ssl->cert)) - { - OPENSSL_PUT_ERROR(SSL, SSL_use_certificate, ERR_R_MALLOC_FAILURE); - return(0); - } - return(ssl_set_cert(ssl->cert,x)); - } -#ifndef OPENSSL_NO_STDIO -int SSL_use_certificate_file(SSL *ssl, const char *file, int type) - { - int reason_code; - BIO *in; - int ret=0; - X509 *x=NULL; +int SSL_use_certificate(SSL *ssl, X509 *x) { + if (x == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_use_certificate, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (!ssl_cert_inst(&ssl->cert)) { + OPENSSL_PUT_ERROR(SSL, SSL_use_certificate, ERR_R_MALLOC_FAILURE); + return 0; + } + return ssl_set_cert(ssl->cert, x); +} - in=BIO_new(BIO_s_file()); - if (in == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_use_certificate_file, ERR_R_BUF_LIB); - goto end; - } +int SSL_use_certificate_file(SSL *ssl, const char *file, int type) { + int reason_code; + BIO *in; + int ret = 0; + X509 *x = NULL; - if (BIO_read_filename(in,file) <= 0) - { - OPENSSL_PUT_ERROR(SSL, SSL_use_certificate_file, ERR_R_SYS_LIB); - goto end; - } - if (type == SSL_FILETYPE_ASN1) - { - reason_code =ERR_R_ASN1_LIB; - x=d2i_X509_bio(in,NULL); - } - else if (type == SSL_FILETYPE_PEM) - { - reason_code=ERR_R_PEM_LIB; - x=PEM_read_bio_X509(in,NULL,ssl->ctx->default_passwd_callback,ssl->ctx->default_passwd_callback_userdata); - } - else - { - OPENSSL_PUT_ERROR(SSL, SSL_use_certificate_file, SSL_R_BAD_SSL_FILETYPE); - goto end; - } + in = BIO_new(BIO_s_file()); + if (in == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_use_certificate_file, ERR_R_BUF_LIB); + goto end; + } - if (x == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_use_certificate_file,reason_code); - goto end; - } + if (BIO_read_filename(in, file) <= 0) { + OPENSSL_PUT_ERROR(SSL, SSL_use_certificate_file, ERR_R_SYS_LIB); + goto end; + } - ret=SSL_use_certificate(ssl,x); -end: - if (x != NULL) X509_free(x); - if (in != NULL) BIO_free(in); - return(ret); - } -#endif + if (type == SSL_FILETYPE_ASN1) { + reason_code = ERR_R_ASN1_LIB; + x = d2i_X509_bio(in, NULL); + } else if (type == SSL_FILETYPE_PEM) { + reason_code = ERR_R_PEM_LIB; + x = PEM_read_bio_X509(in, NULL, ssl->ctx->default_passwd_callback, + ssl->ctx->default_passwd_callback_userdata); + } else { + OPENSSL_PUT_ERROR(SSL, SSL_use_certificate_file, SSL_R_BAD_SSL_FILETYPE); + goto end; + } -int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len) - { - X509 *x; - int ret; + if (x == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_use_certificate_file, reason_code); + goto end; + } - x=d2i_X509(NULL,&d,(long)len); - if (x == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_use_certificate_ASN1, ERR_R_ASN1_LIB); - return(0); - } - - ret=SSL_use_certificate(ssl,x); - X509_free(x); - return(ret); - } - -int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) - { - EVP_PKEY *pkey; - int ret; - - if (rsa == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey, ERR_R_PASSED_NULL_PARAMETER); - return(0); - } - if (!ssl_cert_inst(&ssl->cert)) - { - OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey, ERR_R_MALLOC_FAILURE); - return(0); - } - if ((pkey=EVP_PKEY_new()) == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey, ERR_R_EVP_LIB); - return(0); - } - - RSA_up_ref(rsa); - EVP_PKEY_assign_RSA(pkey,rsa); - - ret=ssl_set_pkey(ssl->cert,pkey); - EVP_PKEY_free(pkey); - return(ret); - } - -static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey) - { - int i; - - i=ssl_cert_type(pkey); - if (i < 0) - { - OPENSSL_PUT_ERROR(SSL, ssl_set_pkey, SSL_R_UNKNOWN_CERTIFICATE_TYPE); - return(0); - } - - if (c->pkeys[i].x509 != NULL) - { - EVP_PKEY *pktmp; - pktmp = X509_get_pubkey(c->pkeys[i].x509); - EVP_PKEY_copy_parameters(pktmp,pkey); - EVP_PKEY_free(pktmp); - ERR_clear_error(); - - /* Sanity-check that the private key and the certificate match, - * unless the key is opaque (in case of, say, a smartcard). */ - if (!EVP_PKEY_is_opaque(pkey) && - !X509_check_private_key(c->pkeys[i].x509,pkey)) - { - X509_free(c->pkeys[i].x509); - c->pkeys[i].x509 = NULL; - return 0; - } - } - - if (c->pkeys[i].privatekey != NULL) - EVP_PKEY_free(c->pkeys[i].privatekey); - c->pkeys[i].privatekey = EVP_PKEY_dup(pkey); - c->key = &(c->pkeys[i]); - - return(1); - } - -#ifndef OPENSSL_NO_STDIO -int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type) - { - int reason_code,ret=0; - BIO *in; - RSA *rsa=NULL; - - in=BIO_new(BIO_s_file()); - if (in == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey_file, ERR_R_BUF_LIB); - goto end; - } - - if (BIO_read_filename(in,file) <= 0) - { - OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey_file, ERR_R_SYS_LIB); - goto end; - } - if (type == SSL_FILETYPE_ASN1) - { - reason_code=ERR_R_ASN1_LIB; - rsa=d2i_RSAPrivateKey_bio(in,NULL); - } - else if (type == SSL_FILETYPE_PEM) - { - reason_code=ERR_R_PEM_LIB; - rsa=PEM_read_bio_RSAPrivateKey(in,NULL, - ssl->ctx->default_passwd_callback,ssl->ctx->default_passwd_callback_userdata); - } - else - { - OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey_file, SSL_R_BAD_SSL_FILETYPE); - goto end; - } - if (rsa == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey_file,reason_code); - goto end; - } - ret=SSL_use_RSAPrivateKey(ssl,rsa); - RSA_free(rsa); -end: - if (in != NULL) BIO_free(in); - return(ret); - } -#endif - -int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, unsigned char *d, long len) - { - int ret; - const unsigned char *p; - RSA *rsa; - - p=d; - if ((rsa=d2i_RSAPrivateKey(NULL,&p,(long)len)) == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey_ASN1, ERR_R_ASN1_LIB); - return(0); - } - - ret=SSL_use_RSAPrivateKey(ssl,rsa); - RSA_free(rsa); - return(ret); - } - -int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) - { - int ret; - - if (pkey == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey, ERR_R_PASSED_NULL_PARAMETER); - return(0); - } - if (!ssl_cert_inst(&ssl->cert)) - { - OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey, ERR_R_MALLOC_FAILURE); - return(0); - } - ret=ssl_set_pkey(ssl->cert,pkey); - return(ret); - } - -#ifndef OPENSSL_NO_STDIO -int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type) - { - int reason_code,ret=0; - BIO *in; - EVP_PKEY *pkey=NULL; - - in=BIO_new(BIO_s_file()); - if (in == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey_file, ERR_R_BUF_LIB); - goto end; - } - - if (BIO_read_filename(in,file) <= 0) - { - OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey_file, ERR_R_SYS_LIB); - goto end; - } - if (type == SSL_FILETYPE_PEM) - { - reason_code=ERR_R_PEM_LIB; - pkey=PEM_read_bio_PrivateKey(in,NULL, - ssl->ctx->default_passwd_callback,ssl->ctx->default_passwd_callback_userdata); - } - else if (type == SSL_FILETYPE_ASN1) - { - reason_code = ERR_R_ASN1_LIB; - pkey = d2i_PrivateKey_bio(in,NULL); - } - else - { - OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey_file, SSL_R_BAD_SSL_FILETYPE); - goto end; - } - if (pkey == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey_file,reason_code); - goto end; - } - ret=SSL_use_PrivateKey(ssl,pkey); - EVP_PKEY_free(pkey); -end: - if (in != NULL) BIO_free(in); - return(ret); - } -#endif - -int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const unsigned char *d, long len) - { - int ret; - const unsigned char *p; - EVP_PKEY *pkey; - - p=d; - if ((pkey=d2i_PrivateKey(type,NULL,&p,(long)len)) == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey_ASN1, ERR_R_ASN1_LIB); - return(0); - } - - ret=SSL_use_PrivateKey(ssl,pkey); - EVP_PKEY_free(pkey); - return(ret); - } - -int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) - { - if (x == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate, ERR_R_PASSED_NULL_PARAMETER); - return(0); - } - if (!ssl_cert_inst(&ctx->cert)) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate, ERR_R_MALLOC_FAILURE); - return(0); - } - return(ssl_set_cert(ctx->cert, x)); - } - -static int ssl_set_cert(CERT *c, X509 *x) - { - EVP_PKEY *pkey; - int i; - - pkey=X509_get_pubkey(x); - if (pkey == NULL) - { - OPENSSL_PUT_ERROR(SSL, ssl_set_cert, SSL_R_X509_LIB); - return(0); - } - - i=ssl_cert_type(pkey); - if (i < 0) - { - OPENSSL_PUT_ERROR(SSL, ssl_set_cert, SSL_R_UNKNOWN_CERTIFICATE_TYPE); - EVP_PKEY_free(pkey); - return(0); - } - - if (c->pkeys[i].privatekey != NULL) - { - EVP_PKEY_copy_parameters(pkey,c->pkeys[i].privatekey); - ERR_clear_error(); - - /* Sanity-check that the private key and the certificate match, - * unless the key is opaque (in case of, say, a smartcard). */ - if (!EVP_PKEY_is_opaque(c->pkeys[i].privatekey) && - !X509_check_private_key(x,c->pkeys[i].privatekey)) - { - /* don't fail for a cert/key mismatch, just free - * current private key (when switching to a different - * cert & key, first this function should be used, - * then ssl_set_pkey */ - EVP_PKEY_free(c->pkeys[i].privatekey); - c->pkeys[i].privatekey=NULL; - /* clear error queue */ - ERR_clear_error(); - } - } - - EVP_PKEY_free(pkey); - - if (c->pkeys[i].x509 != NULL) - X509_free(c->pkeys[i].x509); - c->pkeys[i].x509 = X509_up_ref(x); - c->key= &(c->pkeys[i]); - - return(1); - } - -#ifndef OPENSSL_NO_STDIO -int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type) - { - int reason_code; - BIO *in; - int ret=0; - X509 *x=NULL; - - in=BIO_new(BIO_s_file()); - if (in == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_file, ERR_R_BUF_LIB); - goto end; - } - - if (BIO_read_filename(in,file) <= 0) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_file, ERR_R_SYS_LIB); - goto end; - } - if (type == SSL_FILETYPE_ASN1) - { - reason_code=ERR_R_ASN1_LIB; - x=d2i_X509_bio(in,NULL); - } - else if (type == SSL_FILETYPE_PEM) - { - reason_code=ERR_R_PEM_LIB; - x=PEM_read_bio_X509(in,NULL,ctx->default_passwd_callback,ctx->default_passwd_callback_userdata); - } - else - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_file, SSL_R_BAD_SSL_FILETYPE); - goto end; - } - - if (x == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_file,reason_code); - goto end; - } - - ret=SSL_CTX_use_certificate(ctx,x); -end: - if (x != NULL) X509_free(x); - if (in != NULL) BIO_free(in); - return(ret); - } -#endif - -int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d) - { - X509 *x; - int ret; - - x=d2i_X509(NULL,&d,(long)len); - if (x == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_ASN1, ERR_R_ASN1_LIB); - return(0); - } - - ret=SSL_CTX_use_certificate(ctx,x); - X509_free(x); - return(ret); - } - -int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa) - { - int ret; - EVP_PKEY *pkey; - - if (rsa == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey, ERR_R_PASSED_NULL_PARAMETER); - return(0); - } - if (!ssl_cert_inst(&ctx->cert)) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey, ERR_R_MALLOC_FAILURE); - return(0); - } - if ((pkey=EVP_PKEY_new()) == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey, ERR_R_EVP_LIB); - return(0); - } - - RSA_up_ref(rsa); - EVP_PKEY_assign_RSA(pkey,rsa); - - ret=ssl_set_pkey(ctx->cert, pkey); - EVP_PKEY_free(pkey); - return(ret); - } - -#ifndef OPENSSL_NO_STDIO -int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type) - { - int reason_code,ret=0; - BIO *in; - RSA *rsa=NULL; - - in=BIO_new(BIO_s_file()); - if (in == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey_file, ERR_R_BUF_LIB); - goto end; - } - - if (BIO_read_filename(in,file) <= 0) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey_file, ERR_R_SYS_LIB); - goto end; - } - if (type == SSL_FILETYPE_ASN1) - { - reason_code=ERR_R_ASN1_LIB; - rsa=d2i_RSAPrivateKey_bio(in,NULL); - } - else if (type == SSL_FILETYPE_PEM) - { - reason_code=ERR_R_PEM_LIB; - rsa=PEM_read_bio_RSAPrivateKey(in,NULL, - ctx->default_passwd_callback,ctx->default_passwd_callback_userdata); - } - else - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey_file, SSL_R_BAD_SSL_FILETYPE); - goto end; - } - if (rsa == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey_file,reason_code); - goto end; - } - ret=SSL_CTX_use_RSAPrivateKey(ctx,rsa); - RSA_free(rsa); -end: - if (in != NULL) BIO_free(in); - return(ret); - } -#endif - -int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, long len) - { - int ret; - const unsigned char *p; - RSA *rsa; - - p=d; - if ((rsa=d2i_RSAPrivateKey(NULL,&p,(long)len)) == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey_ASN1, ERR_R_ASN1_LIB); - return(0); - } - - ret=SSL_CTX_use_RSAPrivateKey(ctx,rsa); - RSA_free(rsa); - return(ret); - } - -int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) - { - if (pkey == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey, ERR_R_PASSED_NULL_PARAMETER); - return(0); - } - if (!ssl_cert_inst(&ctx->cert)) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey, ERR_R_MALLOC_FAILURE); - return(0); - } - return(ssl_set_pkey(ctx->cert,pkey)); - } - -#ifndef OPENSSL_NO_STDIO -int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type) - { - int reason_code,ret=0; - BIO *in; - EVP_PKEY *pkey=NULL; - - in=BIO_new(BIO_s_file()); - if (in == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey_file, ERR_R_BUF_LIB); - goto end; - } - - if (BIO_read_filename(in,file) <= 0) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey_file, ERR_R_SYS_LIB); - goto end; - } - if (type == SSL_FILETYPE_PEM) - { - reason_code=ERR_R_PEM_LIB; - pkey=PEM_read_bio_PrivateKey(in,NULL, - ctx->default_passwd_callback,ctx->default_passwd_callback_userdata); - } - else if (type == SSL_FILETYPE_ASN1) - { - reason_code = ERR_R_ASN1_LIB; - pkey = d2i_PrivateKey_bio(in,NULL); - } - else - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey_file, SSL_R_BAD_SSL_FILETYPE); - goto end; - } - if (pkey == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey_file,reason_code); - goto end; - } - ret=SSL_CTX_use_PrivateKey(ctx,pkey); - EVP_PKEY_free(pkey); -end: - if (in != NULL) BIO_free(in); - return(ret); - } -#endif - -int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const unsigned char *d, - long len) - { - int ret; - const unsigned char *p; - EVP_PKEY *pkey; - - p=d; - if ((pkey=d2i_PrivateKey(type,NULL,&p,(long)len)) == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey_ASN1, ERR_R_ASN1_LIB); - return(0); - } - - ret=SSL_CTX_use_PrivateKey(ctx,pkey); - EVP_PKEY_free(pkey); - return(ret); - } - - -#ifndef OPENSSL_NO_STDIO -/* Read a file that contains our certificate in "PEM" format, - * possibly followed by a sequence of CA certificates that should be - * sent to the peer in the Certificate message. - */ -int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) - { - BIO *in; - int ret=0; - X509 *x=NULL; - - ERR_clear_error(); /* clear error stack for SSL_CTX_use_certificate() */ - - in = BIO_new(BIO_s_file()); - if (in == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_chain_file, ERR_R_BUF_LIB); - goto end; - } - - if (BIO_read_filename(in,file) <= 0) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_chain_file, ERR_R_SYS_LIB); - goto end; - } - - x=PEM_read_bio_X509_AUX(in,NULL,ctx->default_passwd_callback, - ctx->default_passwd_callback_userdata); - if (x == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_chain_file, ERR_R_PEM_LIB); - goto end; - } - - ret = SSL_CTX_use_certificate(ctx, x); - - if (ERR_peek_error() != 0) - ret = 0; /* Key/certificate mismatch doesn't imply ret==0 ... */ - if (ret) - { - /* If we could set up our certificate, now proceed to - * the CA certificates. - */ - X509 *ca; - int r; - unsigned long err; - - SSL_CTX_clear_chain_certs(ctx); - - while ((ca = PEM_read_bio_X509(in, NULL, - ctx->default_passwd_callback, - ctx->default_passwd_callback_userdata)) - != NULL) - { - r = SSL_CTX_add0_chain_cert(ctx, ca); - if (!r) - { - X509_free(ca); - ret = 0; - goto end; - } - /* Note that we must not free r if it was successfully - * added to the chain (while we must free the main - * certificate, since its reference count is increased - * by SSL_CTX_use_certificate). */ - } - /* When the while loop ends, it's usually just EOF. */ - err = ERR_peek_last_error(); - if (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE) - ERR_clear_error(); - else - ret = 0; /* some real error */ - } + ret = SSL_use_certificate(ssl, x); end: - if (x != NULL) X509_free(x); - if (in != NULL) BIO_free(in); - return(ret); - } -#endif /* OPENSSL_NO_STDIO */ + if (x != NULL) { + X509_free(x); + } + if (in != NULL) { + BIO_free(in); + } + + return ret; +} + +int SSL_use_certificate_ASN1(SSL *ssl, const uint8_t *d, int len) { + X509 *x; + int ret; + + x = d2i_X509(NULL, &d, (long)len); + if (x == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_use_certificate_ASN1, ERR_R_ASN1_LIB); + return 0; + } + + ret = SSL_use_certificate(ssl, x); + X509_free(x); + return ret; +} + +int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) { + EVP_PKEY *pkey; + int ret; + + if (rsa == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (!ssl_cert_inst(&ssl->cert)) { + OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey, ERR_R_MALLOC_FAILURE); + return 0; + } + + pkey = EVP_PKEY_new(); + if (pkey == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey, ERR_R_EVP_LIB); + return 0; + } + + RSA_up_ref(rsa); + EVP_PKEY_assign_RSA(pkey, rsa); + + ret = ssl_set_pkey(ssl->cert, pkey); + EVP_PKEY_free(pkey); + + return ret; +} + +static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey) { + int i; + + i = ssl_cert_type(pkey); + if (i < 0) { + OPENSSL_PUT_ERROR(SSL, ssl_set_pkey, SSL_R_UNKNOWN_CERTIFICATE_TYPE); + return 0; + } + + if (c->pkeys[i].x509 != NULL) { + EVP_PKEY *pktmp; + pktmp = X509_get_pubkey(c->pkeys[i].x509); + EVP_PKEY_copy_parameters(pktmp, pkey); + EVP_PKEY_free(pktmp); + ERR_clear_error(); + + /* Sanity-check that the private key and the certificate match, unless the + * key is opaque (in case of, say, a smartcard). */ + if (!EVP_PKEY_is_opaque(pkey) && + !X509_check_private_key(c->pkeys[i].x509, pkey)) { + X509_free(c->pkeys[i].x509); + c->pkeys[i].x509 = NULL; + return 0; + } + } + + if (c->pkeys[i].privatekey != NULL) { + EVP_PKEY_free(c->pkeys[i].privatekey); + } + c->pkeys[i].privatekey = EVP_PKEY_dup(pkey); + c->key = &(c->pkeys[i]); + + return 1; +} + +int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type) { + int reason_code, ret = 0; + BIO *in; + RSA *rsa = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey_file, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey_file, ERR_R_SYS_LIB); + goto end; + } + + if (type == SSL_FILETYPE_ASN1) { + reason_code = ERR_R_ASN1_LIB; + rsa = d2i_RSAPrivateKey_bio(in, NULL); + } else if (type == SSL_FILETYPE_PEM) { + reason_code = ERR_R_PEM_LIB; + rsa = + PEM_read_bio_RSAPrivateKey(in, NULL, ssl->ctx->default_passwd_callback, + ssl->ctx->default_passwd_callback_userdata); + } else { + OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey_file, SSL_R_BAD_SSL_FILETYPE); + goto end; + } + + if (rsa == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey_file, reason_code); + goto end; + } + ret = SSL_use_RSAPrivateKey(ssl, rsa); + RSA_free(rsa); + +end: + if (in != NULL) { + BIO_free(in); + } + return ret; +} + +int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, uint8_t *d, long len) { + int ret; + const uint8_t *p; + RSA *rsa; + + p = d; + rsa = d2i_RSAPrivateKey(NULL, &p, (long)len); + if (rsa == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_use_RSAPrivateKey_ASN1, ERR_R_ASN1_LIB); + return 0; + } + + ret = SSL_use_RSAPrivateKey(ssl, rsa); + RSA_free(rsa); + return ret; +} + +int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) { + int ret; + + if (pkey == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (!ssl_cert_inst(&ssl->cert)) { + OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey, ERR_R_MALLOC_FAILURE); + return 0; + } + + ret = ssl_set_pkey(ssl->cert, pkey); + return ret; +} + +int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type) { + int reason_code, ret = 0; + BIO *in; + EVP_PKEY *pkey = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey_file, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey_file, ERR_R_SYS_LIB); + goto end; + } + + if (type == SSL_FILETYPE_PEM) { + reason_code = ERR_R_PEM_LIB; + pkey = PEM_read_bio_PrivateKey(in, NULL, ssl->ctx->default_passwd_callback, + ssl->ctx->default_passwd_callback_userdata); + } else if (type == SSL_FILETYPE_ASN1) { + reason_code = ERR_R_ASN1_LIB; + pkey = d2i_PrivateKey_bio(in, NULL); + } else { + OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey_file, SSL_R_BAD_SSL_FILETYPE); + goto end; + } + + if (pkey == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey_file, reason_code); + goto end; + } + ret = SSL_use_PrivateKey(ssl, pkey); + EVP_PKEY_free(pkey); + +end: + if (in != NULL) { + BIO_free(in); + } + return ret; +} + +int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const uint8_t *d, long len) { + int ret; + const uint8_t *p; + EVP_PKEY *pkey; + + p = d; + pkey = d2i_PrivateKey(type, NULL, &p, (long)len); + if (pkey == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_use_PrivateKey_ASN1, ERR_R_ASN1_LIB); + return 0; + } + + ret = SSL_use_PrivateKey(ssl, pkey); + EVP_PKEY_free(pkey); + return ret; +} + +int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) { + if (x == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (!ssl_cert_inst(&ctx->cert)) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate, ERR_R_MALLOC_FAILURE); + return 0; + } + + return ssl_set_cert(ctx->cert, x); +} + +static int ssl_set_cert(CERT *c, X509 *x) { + EVP_PKEY *pkey; + int i; + + pkey = X509_get_pubkey(x); + if (pkey == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl_set_cert, SSL_R_X509_LIB); + return 0; + } + + i = ssl_cert_type(pkey); + if (i < 0) { + OPENSSL_PUT_ERROR(SSL, ssl_set_cert, SSL_R_UNKNOWN_CERTIFICATE_TYPE); + EVP_PKEY_free(pkey); + return 0; + } + + if (c->pkeys[i].privatekey != NULL) { + EVP_PKEY_copy_parameters(pkey, c->pkeys[i].privatekey); + ERR_clear_error(); + + /* Sanity-check that the private key and the certificate match, unless the + * key is opaque (in case of, say, a smartcard). */ + if (!EVP_PKEY_is_opaque(c->pkeys[i].privatekey) && + !X509_check_private_key(x, c->pkeys[i].privatekey)) { + /* don't fail for a cert/key mismatch, just free current private key + * (when switching to a different cert & key, first this function should + * be used, then ssl_set_pkey */ + EVP_PKEY_free(c->pkeys[i].privatekey); + c->pkeys[i].privatekey = NULL; + /* clear error queue */ + ERR_clear_error(); + } + } + + EVP_PKEY_free(pkey); + + if (c->pkeys[i].x509 != NULL) { + X509_free(c->pkeys[i].x509); + } + c->pkeys[i].x509 = X509_up_ref(x); + c->key = &(c->pkeys[i]); + + return 1; +} + +int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type) { + int reason_code; + BIO *in; + int ret = 0; + X509 *x = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_file, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_file, ERR_R_SYS_LIB); + goto end; + } + + if (type == SSL_FILETYPE_ASN1) { + reason_code = ERR_R_ASN1_LIB; + x = d2i_X509_bio(in, NULL); + } else if (type == SSL_FILETYPE_PEM) { + reason_code = ERR_R_PEM_LIB; + x = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, + ctx->default_passwd_callback_userdata); + } else { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_file, + SSL_R_BAD_SSL_FILETYPE); + goto end; + } + + if (x == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_file, reason_code); + goto end; + } + + ret = SSL_CTX_use_certificate(ctx, x); + +end: + if (x != NULL) { + X509_free(x); + } + if (in != NULL) { + BIO_free(in); + } + return ret; +} + +int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const uint8_t *d) { + X509 *x; + int ret; + + x = d2i_X509(NULL, &d, (long)len); + if (x == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_ASN1, ERR_R_ASN1_LIB); + return 0; + } + + ret = SSL_CTX_use_certificate(ctx, x); + X509_free(x); + return ret; +} + +int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa) { + int ret; + EVP_PKEY *pkey; + + if (rsa == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (!ssl_cert_inst(&ctx->cert)) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey, ERR_R_MALLOC_FAILURE); + return 0; + } + + pkey = EVP_PKEY_new(); + if (pkey == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey, ERR_R_EVP_LIB); + return 0; + } + + RSA_up_ref(rsa); + EVP_PKEY_assign_RSA(pkey, rsa); + + ret = ssl_set_pkey(ctx->cert, pkey); + EVP_PKEY_free(pkey); + return ret; +} + +int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type) { + int reason_code, ret = 0; + BIO *in; + RSA *rsa = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey_file, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey_file, ERR_R_SYS_LIB); + goto end; + } + + if (type == SSL_FILETYPE_ASN1) { + reason_code = ERR_R_ASN1_LIB; + rsa = d2i_RSAPrivateKey_bio(in, NULL); + } else if (type == SSL_FILETYPE_PEM) { + reason_code = ERR_R_PEM_LIB; + rsa = PEM_read_bio_RSAPrivateKey(in, NULL, ctx->default_passwd_callback, + ctx->default_passwd_callback_userdata); + } else { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey_file, + SSL_R_BAD_SSL_FILETYPE); + goto end; + } + + if (rsa == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey_file, reason_code); + goto end; + } + ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa); + RSA_free(rsa); + +end: + if (in != NULL) { + BIO_free(in); + } + return ret; +} + +int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const uint8_t *d, long len) { + int ret; + const uint8_t *p; + RSA *rsa; + + p = d; + rsa = d2i_RSAPrivateKey(NULL, &p, (long)len); + if (rsa == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_RSAPrivateKey_ASN1, ERR_R_ASN1_LIB); + return 0; + } + + ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa); + RSA_free(rsa); + return ret; +} + +int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) { + if (pkey == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (!ssl_cert_inst(&ctx->cert)) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey, ERR_R_MALLOC_FAILURE); + return 0; + } + + return ssl_set_pkey(ctx->cert, pkey); +} + +int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type) { + int reason_code, ret = 0; + BIO *in; + EVP_PKEY *pkey = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey_file, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey_file, ERR_R_SYS_LIB); + goto end; + } + + if (type == SSL_FILETYPE_PEM) { + reason_code = ERR_R_PEM_LIB; + pkey = PEM_read_bio_PrivateKey(in, NULL, ctx->default_passwd_callback, + ctx->default_passwd_callback_userdata); + } else if (type == SSL_FILETYPE_ASN1) { + reason_code = ERR_R_ASN1_LIB; + pkey = d2i_PrivateKey_bio(in, NULL); + } else { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey_file, SSL_R_BAD_SSL_FILETYPE); + goto end; + } + + if (pkey == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey_file, reason_code); + goto end; + } + ret = SSL_CTX_use_PrivateKey(ctx, pkey); + EVP_PKEY_free(pkey); + +end: + if (in != NULL) { + BIO_free(in); + } + return ret; +} + +int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const uint8_t *d, + long len) { + int ret; + const uint8_t *p; + EVP_PKEY *pkey; + + p = d; + pkey = d2i_PrivateKey(type, NULL, &p, (long)len); + if (pkey == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_PrivateKey_ASN1, ERR_R_ASN1_LIB); + return 0; + } + + ret = SSL_CTX_use_PrivateKey(ctx, pkey); + EVP_PKEY_free(pkey); + return ret; +} + + +/* Read a file that contains our certificate in "PEM" format, possibly followed + * by a sequence of CA certificates that should be sent to the peer in the + * Certificate message. */ +int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) { + BIO *in; + int ret = 0; + X509 *x = NULL; + + ERR_clear_error(); /* clear error stack for SSL_CTX_use_certificate() */ + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_chain_file, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_chain_file, ERR_R_SYS_LIB); + goto end; + } + + x = PEM_read_bio_X509_AUX(in, NULL, ctx->default_passwd_callback, + ctx->default_passwd_callback_userdata); + if (x == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_certificate_chain_file, ERR_R_PEM_LIB); + goto end; + } + + ret = SSL_CTX_use_certificate(ctx, x); + + if (ERR_peek_error() != 0) { + ret = 0; /* Key/certificate mismatch doesn't imply ret==0 ... */ + } + + if (ret) { + /* If we could set up our certificate, now proceed to the CA + * certificates. */ + X509 *ca; + int r; + unsigned long err; + + SSL_CTX_clear_chain_certs(ctx); + + while ((ca = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, + ctx->default_passwd_callback_userdata)) != + NULL) { + r = SSL_CTX_add0_chain_cert(ctx, ca); + if (!r) { + X509_free(ca); + ret = 0; + goto end; + } + /* Note that we must not free r if it was successfully added to the chain + * (while we must free the main certificate, since its reference count is + * increased by SSL_CTX_use_certificate). */ + } + + /* When the while loop ends, it's usually just EOF. */ + err = ERR_peek_last_error(); + if (ERR_GET_LIB(err) == ERR_LIB_PEM && + ERR_GET_REASON(err) == PEM_R_NO_START_LINE) { + ERR_clear_error(); + } else { + ret = 0; /* some real error */ + } + } + +end: + if (x != NULL) { + X509_free(x); + } + if (in != NULL) { + BIO_free(in); + } + return ret; +}
diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c index cbfdb9a..117e53c 100644 --- a/ssl/ssl_sess.c +++ b/ssl/ssl_sess.c
@@ -152,224 +152,218 @@ static void SSL_SESSION_list_add(SSL_CTX *ctx,SSL_SESSION *s); static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck); -SSL_SESSION *SSL_magic_pending_session_ptr(void) - { - return (SSL_SESSION*) &g_pending_session_magic; - } - -SSL_SESSION *SSL_get_session(const SSL *ssl) -/* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */ - { - return(ssl->session); - } - -SSL_SESSION *SSL_get1_session(SSL *ssl) -/* variant of SSL_get_session: caller really gets something */ - { - SSL_SESSION *sess; - /* Need to lock this all up rather than just use CRYPTO_add so that - * somebody doesn't free ssl->session between when we check it's - * non-null and when we up the reference count. */ - CRYPTO_w_lock(CRYPTO_LOCK_SSL_SESSION); - sess = ssl->session; - if(sess) - sess->references++; - CRYPTO_w_unlock(CRYPTO_LOCK_SSL_SESSION); - return(sess); - } - -int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, - CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) - { - return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, argl, argp, - new_func, dup_func, free_func); - } - -int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg) - { - return(CRYPTO_set_ex_data(&s->ex_data,idx,arg)); - } - -void *SSL_SESSION_get_ex_data(const SSL_SESSION *s, int idx) - { - return(CRYPTO_get_ex_data(&s->ex_data,idx)); - } - -SSL_SESSION *SSL_SESSION_new(void) - { - SSL_SESSION *ss; - - ss=(SSL_SESSION *)OPENSSL_malloc(sizeof(SSL_SESSION)); - if (ss == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_SESSION_new, ERR_R_MALLOC_FAILURE); - return(0); - } - memset(ss,0,sizeof(SSL_SESSION)); - - ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */ - ss->references=1; - ss->timeout = SSL_DEFAULT_SESSION_TIMEOUT; - ss->time=(unsigned long)time(NULL); - CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); - return(ss); - } - -const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len) - { - if(len) - *len = s->session_id_length; - return s->session_id; - } - -/* Even with SSLv2, we have 16 bytes (128 bits) of session ID space. SSLv3/TLSv1 - * has 32 bytes (256 bits). As such, filling the ID with random gunk repeatedly - * until we have no conflict is going to complete in one iteration pretty much - * "most" of the time (btw: understatement). So, if it takes us 10 iterations - * and we still can't avoid a conflict - well that's a reasonable point to call - * it quits. Either the RAND code is broken or someone is trying to open roughly - * very close to 2^128 (or 2^256) SSL sessions to our server. How you might - * store that many sessions is perhaps a more interesting question ... */ - -#define MAX_SESS_ID_ATTEMPTS 10 -static int def_generate_session_id(const SSL *ssl, unsigned char *id, - unsigned int *id_len) -{ - unsigned int retry = 0; - do - { - if (!RAND_bytes(id, *id_len)) - return 0; - } - while(SSL_has_matching_session_id(ssl, id, *id_len) && - (++retry < MAX_SESS_ID_ATTEMPTS)); - if(retry < MAX_SESS_ID_ATTEMPTS) - return 1; - /* else - woops a session_id match */ - /* XXX We should also check the external cache -- - * but the probability of a collision is negligible, and - * we could not prevent the concurrent creation of sessions - * with identical IDs since we currently don't have means - * to atomically check whether a session ID already exists - * and make a reservation for it if it does not - * (this problem applies to the internal cache as well). - */ - return 0; +SSL_SESSION *SSL_magic_pending_session_ptr(void) { + return (SSL_SESSION *)&g_pending_session_magic; } -int ssl_get_new_session(SSL *s, int session) - { - /* This gets used by clients and servers. */ +SSL_SESSION *SSL_get_session(const SSL *ssl) +{ + /* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */ + return ssl->session; +} - unsigned int tmp; - SSL_SESSION *ss=NULL; - GEN_SESSION_CB cb = def_generate_session_id; +SSL_SESSION *SSL_get1_session(SSL *ssl) { + /* variant of SSL_get_session: caller really gets something */ + SSL_SESSION *sess; + /* Need to lock this all up rather than just use CRYPTO_add so that + * somebody doesn't free ssl->session between when we check it's + * non-null and when we up the reference count. */ + CRYPTO_w_lock(CRYPTO_LOCK_SSL_SESSION); + sess = ssl->session; + if (sess) { + sess->references++; + } + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_SESSION); - if (s->mode & SSL_MODE_NO_SESSION_CREATION) - { - OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, SSL_R_SESSION_MAY_NOT_BE_CREATED); - return 0; - } + return sess; +} - if ((ss=SSL_SESSION_new()) == NULL) return(0); +int SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func) { + return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, argl, argp, + new_func, dup_func, free_func); +} - /* If the context has a default timeout, use it over the default. */ - if (s->initial_ctx->session_timeout != 0) - ss->timeout=s->initial_ctx->session_timeout; +int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg) { + return CRYPTO_set_ex_data(&s->ex_data, idx, arg); +} - if (s->session != NULL) - { - SSL_SESSION_free(s->session); - s->session=NULL; - } +void *SSL_SESSION_get_ex_data(const SSL_SESSION *s, int idx) { + return CRYPTO_get_ex_data(&s->ex_data, idx); +} - if (session) - { - if (s->version == SSL3_VERSION || - s->version == TLS1_VERSION || - s->version == TLS1_1_VERSION || - s->version == TLS1_2_VERSION || - s->version == DTLS1_VERSION || - s->version == DTLS1_2_VERSION) - { - ss->ssl_version = s->version; - ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH; - } - else - { - OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, SSL_R_UNSUPPORTED_SSL_VERSION); - SSL_SESSION_free(ss); - return(0); - } - /* If RFC4507 ticket use empty session ID */ - if (s->tlsext_ticket_expected) - { - ss->session_id_length = 0; - goto sess_id_done; - } - /* Choose which callback will set the session ID */ - CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); - if(s->generate_session_id) - cb = s->generate_session_id; - else if(s->initial_ctx->generate_session_id) - cb = s->initial_ctx->generate_session_id; - CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); - /* Choose a session ID */ - tmp = ss->session_id_length; - if(!cb(s, ss->session_id, &tmp)) - { - /* The callback failed */ - OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, SSL_R_SSL_SESSION_ID_CALLBACK_FAILED); - SSL_SESSION_free(ss); - return(0); - } - /* Don't allow the callback to set the session length to zero. - * nor set it higher than it was. */ - if(!tmp || (tmp > ss->session_id_length)) - { - /* The callback set an illegal length */ - OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH); - SSL_SESSION_free(ss); - return(0); - } - ss->session_id_length = tmp; - /* Finally, check for a conflict */ - if(SSL_has_matching_session_id(s, ss->session_id, - ss->session_id_length)) - { - OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, SSL_R_SSL_SESSION_ID_CONFLICT); - SSL_SESSION_free(ss); - return(0); - } - sess_id_done: - if (s->tlsext_hostname) { - ss->tlsext_hostname = BUF_strdup(s->tlsext_hostname); - if (ss->tlsext_hostname == NULL) { - OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, ERR_R_INTERNAL_ERROR); - SSL_SESSION_free(ss); - return 0; - } - } - } - else - { - ss->session_id_length=0; - } +SSL_SESSION *SSL_SESSION_new(void) { + SSL_SESSION *ss; - if (s->sid_ctx_length > sizeof ss->sid_ctx) - { - OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, ERR_R_INTERNAL_ERROR); - SSL_SESSION_free(ss); - return 0; - } - memcpy(ss->sid_ctx,s->sid_ctx,s->sid_ctx_length); - ss->sid_ctx_length=s->sid_ctx_length; - s->session=ss; - ss->ssl_version=s->version; - ss->verify_result = X509_V_OK; + ss = (SSL_SESSION *)OPENSSL_malloc(sizeof(SSL_SESSION)); + if (ss == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_SESSION_new, ERR_R_MALLOC_FAILURE); + return 0; + } + memset(ss, 0, sizeof(SSL_SESSION)); - return(1); - } + ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */ + ss->references = 1; + ss->timeout = SSL_DEFAULT_SESSION_TIMEOUT; + ss->time = (unsigned long)time(NULL); + CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); + return ss; +} + +const uint8_t *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len) { + if (len) { + *len = s->session_id_length; + } + return s->session_id; +} + +/* Even with SSLv2, we have 16 bytes (128 bits) of session ID space. + * SSLv3/TLSv1 has 32 bytes (256 bits). As such, filling the ID with random + * gunk repeatedly until we have no conflict is going to complete in one + * iteration pretty much "most" of the time (btw: understatement). So, if it + * takes us 10 iterations and we still can't avoid a conflict - well that's a + * reasonable point to call it quits. Either the RAND code is broken or someone + * is trying to open roughly very close to 2^128 (or 2^256) SSL sessions to our + * server. How you might store that many sessions is perhaps a more interesting + * question ... */ +static int def_generate_session_id(const SSL *ssl, uint8_t *id, + unsigned int *id_len) { + static const unsigned kMaxAttempts = 10; + unsigned int retry = 0; + do { + if (!RAND_bytes(id, *id_len)) { + return 0; + } + } while (SSL_has_matching_session_id(ssl, id, *id_len) && + (++retry < kMaxAttempts)); + + if (retry < kMaxAttempts) { + return 1; + } + + /* else - woops a session_id match */ + /* XXX We should also check the external cache -- but the probability of a + * collision is negligible, and we could not prevent the concurrent creation + * of sessions with identical IDs since we currently don't have means to + * atomically check whether a session ID already exists and make a + * reservation for it if it does not (this problem applies to the internal + * cache as well). */ + return 0; +} + +int ssl_get_new_session(SSL *s, int session) { + /* This gets used by clients and servers. */ + + unsigned int tmp; + SSL_SESSION *ss = NULL; + GEN_SESSION_CB cb = def_generate_session_id; + + if (s->mode & SSL_MODE_NO_SESSION_CREATION) { + OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, + SSL_R_SESSION_MAY_NOT_BE_CREATED); + return 0; + } + + ss = SSL_SESSION_new(); + if (ss == NULL) { + return 0; + } + + /* If the context has a default timeout, use it over the default. */ + if (s->initial_ctx->session_timeout != 0) { + ss->timeout = s->initial_ctx->session_timeout; + } + + if (s->session != NULL) { + SSL_SESSION_free(s->session); + s->session = NULL; + } + + if (session) { + if (s->version == SSL3_VERSION || s->version == TLS1_VERSION || + s->version == TLS1_1_VERSION || s->version == TLS1_2_VERSION || + s->version == DTLS1_VERSION || s->version == DTLS1_2_VERSION) { + ss->ssl_version = s->version; + ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH; + } else { + OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, + SSL_R_UNSUPPORTED_SSL_VERSION); + SSL_SESSION_free(ss); + return 0; + } + + /* If RFC4507 ticket use empty session ID */ + if (s->tlsext_ticket_expected) { + ss->session_id_length = 0; + goto sess_id_done; + } + + /* Choose which callback will set the session ID */ + CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); + if (s->generate_session_id) { + cb = s->generate_session_id; + } else if (s->initial_ctx->generate_session_id) { + cb = s->initial_ctx->generate_session_id; + } + CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); + + /* Choose a session ID */ + tmp = ss->session_id_length; + if (!cb(s, ss->session_id, &tmp)) { + /* The callback failed */ + OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, + SSL_R_SSL_SESSION_ID_CALLBACK_FAILED); + SSL_SESSION_free(ss); + return 0; + } + + /* Don't allow the callback to set the session length to zero. nor set it + * higher than it was. */ + if (!tmp || tmp > ss->session_id_length) { + /* The callback set an illegal length */ + OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, + SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH); + SSL_SESSION_free(ss); + return 0; + } + + ss->session_id_length = tmp; + /* Finally, check for a conflict */ + if (SSL_has_matching_session_id(s, ss->session_id, ss->session_id_length)) { + OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, + SSL_R_SSL_SESSION_ID_CONFLICT); + SSL_SESSION_free(ss); + return 0; + } + + sess_id_done: + if (s->tlsext_hostname) { + ss->tlsext_hostname = BUF_strdup(s->tlsext_hostname); + if (ss->tlsext_hostname == NULL) { + OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, ERR_R_INTERNAL_ERROR); + SSL_SESSION_free(ss); + return 0; + } + } + } else { + ss->session_id_length = 0; + } + + if (s->sid_ctx_length > sizeof(ss->sid_ctx)) { + OPENSSL_PUT_ERROR(SSL, ssl_get_new_session, ERR_R_INTERNAL_ERROR); + SSL_SESSION_free(ss); + return 0; + } + + memcpy(ss->sid_ctx, s->sid_ctx, s->sid_ctx_length); + ss->sid_ctx_length = s->sid_ctx_length; + s->session = ss; + ss->ssl_version = s->version; + ss->verify_result = X509_V_OK; + + return 1; +} /* ssl_get_prev attempts to find an SSL_SESSION to be used to resume this * connection. It is only called by servers. @@ -385,561 +379,542 @@ * - If a session is found then s->session is pointed at it (after freeing an * existing session if need be) and s->verify_result is set from the session. * - Both for new and resumed sessions, s->tlsext_ticket_expected is set to 1 - * if the server should issue a new session ticket (to 0 otherwise). - */ -int ssl_get_prev_session(SSL *s, const struct ssl_early_callback_ctx *ctx) - { - /* This is used only by servers. */ + * if the server should issue a new session ticket (to 0 otherwise). */ +int ssl_get_prev_session(SSL *s, const struct ssl_early_callback_ctx *ctx) { + /* This is used only by servers. */ + SSL_SESSION *ret = NULL; + int fatal = 0; + int try_session_cache = 1; + int r; - SSL_SESSION *ret=NULL; - int fatal = 0; - int try_session_cache = 1; - int r; + if (ctx->session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) { + goto err; + } - if (ctx->session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) - goto err; + if (ctx->session_id_len == 0) { + try_session_cache = 0; + } - if (ctx->session_id_len == 0) - try_session_cache = 0; + r = tls1_process_ticket(s, ctx, &ret); /* sets s->tlsext_ticket_expected */ + switch (r) { + case -1: /* Error during processing */ + fatal = 1; + goto err; - r = tls1_process_ticket(s, ctx, &ret); /* sets s->tlsext_ticket_expected */ - switch (r) - { - case -1: /* Error during processing */ - fatal = 1; - goto err; - case 0: /* No ticket found */ - case 1: /* Zero length ticket found */ - break; /* Ok to carry on processing session id. */ - case 2: /* Ticket found but not decrypted. */ - case 3: /* Ticket decrypted, *ret has been set. */ - try_session_cache = 0; - break; - default: - abort(); - } + case 0: /* No ticket found */ + case 1: /* Zero length ticket found */ + break; /* Ok to carry on processing session id. */ - if (try_session_cache && - ret == NULL && - !(s->initial_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) - { - SSL_SESSION data; - data.ssl_version=s->version; - data.session_id_length=ctx->session_id_len; - if (ctx->session_id_len == 0) - return 0; - memcpy(data.session_id,ctx->session_id,ctx->session_id_len); - CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); - ret=lh_SSL_SESSION_retrieve(s->initial_ctx->sessions,&data); - if (ret != NULL) - { - /* don't allow other threads to steal it: */ - CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION); - } - CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); - if (ret == NULL) - s->initial_ctx->stats.sess_miss++; - } + case 2: /* Ticket found but not decrypted. */ + case 3: /* Ticket decrypted, *ret has been set. */ + try_session_cache = 0; + break; - if (try_session_cache && - ret == NULL && - s->initial_ctx->get_session_cb != NULL) - { - int copy=1; - - if ((ret=s->initial_ctx->get_session_cb(s,(unsigned char *) ctx->session_id,ctx->session_id_len,©))) - { - if (ret == SSL_magic_pending_session_ptr()) - { - /* This is a magic value which indicates that - * the callback needs to unwind the stack and - * figure out the session asynchronously. */ - return PENDING_SESSION; - } - s->initial_ctx->stats.sess_cb_hit++; + default: + abort(); + } - /* Increment reference count now if the session callback - * asks us to do so (note that if the session structures - * returned by the callback are shared between threads, - * it must handle the reference count itself [i.e. copy == 0], - * or things won't be thread-safe). */ - if (copy) - CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION); + if (try_session_cache && ret == NULL && + !(s->initial_ctx->session_cache_mode & + SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) { + SSL_SESSION data; + data.ssl_version = s->version; + data.session_id_length = ctx->session_id_len; + if (ctx->session_id_len == 0) { + return 0; + } + memcpy(data.session_id, ctx->session_id, ctx->session_id_len); + CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); + ret = lh_SSL_SESSION_retrieve(s->initial_ctx->sessions, &data); + if (ret != NULL) { + /* don't allow other threads to steal it: */ + CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_SSL_SESSION); + } + CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); + if (ret == NULL) { + s->initial_ctx->stats.sess_miss++; + } + } - /* Add the externally cached session to the internal - * cache as well if and only if we are supposed to. */ - if(!(s->initial_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_STORE)) - /* The following should not return 1, otherwise, - * things are very strange */ - SSL_CTX_add_session(s->initial_ctx,ret); - } - } + if (try_session_cache && ret == NULL && + s->initial_ctx->get_session_cb != NULL) { + int copy = 1; - if (ret == NULL) - goto err; + ret = s->initial_ctx->get_session_cb(s, (uint8_t *)ctx->session_id, + ctx->session_id_len, ©); + if (ret != NULL) { + if (ret == SSL_magic_pending_session_ptr()) { + /* This is a magic value which indicates that the callback needs to + * unwind the stack and figure out the session asynchronously. */ + return PENDING_SESSION; + } + s->initial_ctx->stats.sess_cb_hit++; - /* Now ret is non-NULL and we own one of its reference counts. */ + /* Increment reference count now if the session callback asks us to do so + * (note that if the session structures returned by the callback are + * shared between threads, it must handle the reference count itself + * [i.e. copy == 0], or things won't be thread-safe). */ + if (copy) { + CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_SSL_SESSION); + } - if (ret->sid_ctx_length != s->sid_ctx_length - || memcmp(ret->sid_ctx,s->sid_ctx,ret->sid_ctx_length)) - { - /* We have the session requested by the client, but we don't - * want to use it in this context. */ - goto err; /* treat like cache miss */ - } - - if((s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0) - { - /* We can't be sure if this session is being used out of - * context, which is especially important for SSL_VERIFY_PEER. - * The application should have used SSL[_CTX]_set_session_id_context. - * - * For this error case, we generate an error instead of treating - * the event like a cache miss (otherwise it would be easy for - * applications to effectively disable the session cache by - * accident without anyone noticing). - */ - - OPENSSL_PUT_ERROR(SSL, ssl_get_prev_session, SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED); - fatal = 1; - goto err; - } + /* Add the externally cached session to the internal cache as well if and + * only if we are supposed to. */ + if (!(s->initial_ctx->session_cache_mode & + SSL_SESS_CACHE_NO_INTERNAL_STORE)) { + /* The following should not return 1, otherwise, things are very + * strange */ + SSL_CTX_add_session(s->initial_ctx, ret); + } + } + } - if (ret->timeout < (long)(time(NULL) - ret->time)) /* timeout */ - { - s->initial_ctx->stats.sess_timeout++; - if (try_session_cache) - { - /* session was from the cache, so remove it */ - SSL_CTX_remove_session(s->initial_ctx,ret); - } - goto err; - } + if (ret == NULL) { + goto err; + } - s->initial_ctx->stats.sess_hit++; + /* Now ret is non-NULL and we own one of its reference counts. */ - if (s->session != NULL) - SSL_SESSION_free(s->session); - s->session=ret; - s->verify_result = s->session->verify_result; - return 1; + if (ret->sid_ctx_length != s->sid_ctx_length || + memcmp(ret->sid_ctx, s->sid_ctx, ret->sid_ctx_length)) { + /* We have the session requested by the client, but we don't want to use it + * in this context. */ + goto err; /* treat like cache miss */ + } - err: - if (ret != NULL) - { - SSL_SESSION_free(ret); - if (!try_session_cache) - { - /* The session was from a ticket, so we should - * issue a ticket for the new session */ - s->tlsext_ticket_expected = 1; - } - } - if (fatal) - return -1; - else - return 0; - } + if ((s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0) { + /* We can't be sure if this session is being used out of context, which is + * especially important for SSL_VERIFY_PEER. The application should have + * used SSL[_CTX]_set_session_id_context. + * + * For this error case, we generate an error instead of treating the event + * like a cache miss (otherwise it would be easy for applications to + * effectively disable the session cache by accident without anyone + * noticing). */ + OPENSSL_PUT_ERROR(SSL, ssl_get_prev_session, + SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED); + fatal = 1; + goto err; + } -int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) - { - int ret=0; - SSL_SESSION *s; + if (ret->timeout < (long)(time(NULL) - ret->time)) { + /* timeout */ + s->initial_ctx->stats.sess_timeout++; + if (try_session_cache) { + /* session was from the cache, so remove it */ + SSL_CTX_remove_session(s->initial_ctx, ret); + } + goto err; + } - /* add just 1 reference count for the SSL_CTX's session cache - * even though it has two ways of access: each session is in a - * doubly linked list and an lhash */ - CRYPTO_add(&c->references,1,CRYPTO_LOCK_SSL_SESSION); - /* if session c is in already in cache, we take back the increment later */ + s->initial_ctx->stats.sess_hit++; - CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); - if (!lh_SSL_SESSION_insert(ctx->sessions,&s,c)) { - return 0; - } - - /* s != NULL iff we already had a session with the given PID. - * In this case, s == c should hold (then we did not really modify - * ctx->sessions), or we're in trouble. */ - if (s != NULL && s != c) - { - /* We *are* in trouble ... */ - SSL_SESSION_list_remove(ctx,s); - SSL_SESSION_free(s); - /* ... so pretend the other session did not exist in cache - * (we cannot handle two SSL_SESSION structures with identical - * session ID in the same cache, which could happen e.g. when - * two threads concurrently obtain the same session from an external - * cache) */ - s = NULL; - } + if (s->session != NULL) { + SSL_SESSION_free(s->session); + } + s->session = ret; + s->verify_result = s->session->verify_result; + return 1; - /* Put at the head of the queue unless it is already in the cache */ - if (s == NULL) - SSL_SESSION_list_add(ctx,c); - - if (s != NULL) - { - /* existing cache entry -- decrement previously incremented reference - * count because it already takes into account the cache */ - - SSL_SESSION_free(s); /* s == c */ - ret=0; - } - else - { - /* new cache entry -- remove old ones if cache has become too large */ - - ret=1; - - if (SSL_CTX_sess_get_cache_size(ctx) > 0) - { - while (SSL_CTX_sess_number(ctx) > - SSL_CTX_sess_get_cache_size(ctx)) - { - if (!remove_session_lock(ctx, - ctx->session_cache_tail, 0)) - break; - else - ctx->stats.sess_cache_full++; - } - } - } - CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); - return(ret); - } - -int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c) -{ - return remove_session_lock(ctx, c, 1); +err: + if (ret != NULL) { + SSL_SESSION_free(ret); + if (!try_session_cache) { + /* The session was from a ticket, so we should + * issue a ticket for the new session */ + s->tlsext_ticket_expected = 1; + } + } + if (fatal) { + return -1; + } + return 0; } -static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck) - { - SSL_SESSION *r; - int ret=0; +int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) { + int ret = 0; + SSL_SESSION *s; - if ((c != NULL) && (c->session_id_length != 0)) - { - if(lck) CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); - if ((r = lh_SSL_SESSION_retrieve(ctx->sessions,c)) == c) - { - ret=1; - r=lh_SSL_SESSION_delete(ctx->sessions,c); - SSL_SESSION_list_remove(ctx,c); - } + /* add just 1 reference count for the SSL_CTX's session cache even though it + * has two ways of access: each session is in a doubly linked list and an + * lhash */ + CRYPTO_add(&c->references, 1, CRYPTO_LOCK_SSL_SESSION); + /* if session c is in already in cache, we take back the increment later */ - if(lck) CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + if (!lh_SSL_SESSION_insert(ctx->sessions, &s, c)) { + return 0; + } - if (ret) - { - r->not_resumable=1; - if (ctx->remove_session_cb != NULL) - ctx->remove_session_cb(ctx,r); - SSL_SESSION_free(r); - } - } - else - ret=0; - return(ret); - } + /* s != NULL iff we already had a session with the given PID. In this case, s + * == c should hold (then we did not really modify ctx->sessions), or we're + * in trouble. */ + if (s != NULL && s != c) { + /* We *are* in trouble ... */ + SSL_SESSION_list_remove(ctx, s); + SSL_SESSION_free(s); + /* ... so pretend the other session did not exist in cache (we cannot + * handle two SSL_SESSION structures with identical session ID in the same + * cache, which could happen e.g. when two threads concurrently obtain the + * same session from an external cache) */ + s = NULL; + } -void SSL_SESSION_free(SSL_SESSION *ss) - { - int i; + /* Put at the head of the queue unless it is already in the cache */ + if (s == NULL) { + SSL_SESSION_list_add(ctx, c); + } - if(ss == NULL) - return; + if (s != NULL) { + /* existing cache entry -- decrement previously incremented reference count + * because it already takes into account the cache */ + SSL_SESSION_free(s); /* s == c */ + ret = 0; + } else { + /* new cache entry -- remove old ones if cache has become too large */ + ret = 1; - i=CRYPTO_add(&ss->references,-1,CRYPTO_LOCK_SSL_SESSION); -#ifdef REF_PRINT - REF_PRINT("SSL_SESSION",ss); -#endif - if (i > 0) return; -#ifdef REF_CHECK - if (i < 0) - { - fprintf(stderr,"SSL_SESSION_free, bad reference count\n"); - abort(); /* ok */ - } -#endif + if (SSL_CTX_sess_get_cache_size(ctx) > 0) { + while (SSL_CTX_sess_number(ctx) > SSL_CTX_sess_get_cache_size(ctx)) { + if (!remove_session_lock(ctx, ctx->session_cache_tail, 0)) { + break; + } + ctx->stats.sess_cache_full++; + } + } + } - CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); + return ret; +} - OPENSSL_cleanse(ss->master_key,sizeof ss->master_key); - OPENSSL_cleanse(ss->session_id,sizeof ss->session_id); - if (ss->sess_cert != NULL) ssl_sess_cert_free(ss->sess_cert); - if (ss->peer != NULL) X509_free(ss->peer); - if (ss->tlsext_hostname != NULL) OPENSSL_free(ss->tlsext_hostname); - if (ss->tlsext_tick != NULL) OPENSSL_free(ss->tlsext_tick); - if (ss->tlsext_signed_cert_timestamp_list != NULL) - OPENSSL_free(ss->tlsext_signed_cert_timestamp_list); - if (ss->ocsp_response != NULL) - OPENSSL_free(ss->ocsp_response); - if (ss->psk_identity != NULL) - OPENSSL_free(ss->psk_identity); - OPENSSL_cleanse(ss,sizeof(*ss)); - OPENSSL_free(ss); - } +int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c) { + return remove_session_lock(ctx, c, 1); +} -int SSL_set_session(SSL *s, SSL_SESSION *session) - { - if (s->session == session) - return 1; +static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lock) { + SSL_SESSION *r; + int ret = 0; - if (s->session != NULL) - SSL_SESSION_free(s->session); - s->session = session; - if (session != NULL) - { - CRYPTO_add(&session->references, 1, CRYPTO_LOCK_SSL_SESSION); - s->verify_result = session->verify_result; - } - return 1; - } + if (c != NULL && c->session_id_length != 0) { + if (lock) { + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + } + r = lh_SSL_SESSION_retrieve(ctx->sessions, c); + if (r == c) { + ret = 1; + r = lh_SSL_SESSION_delete(ctx->sessions, c); + SSL_SESSION_list_remove(ctx, c); + } -long SSL_SESSION_set_timeout(SSL_SESSION *s, long t) - { - if (s == NULL) return(0); - s->timeout=t; - return(1); - } + if (lock) { + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); + } -long SSL_SESSION_get_timeout(const SSL_SESSION *s) - { - if (s == NULL) return(0); - return(s->timeout); - } + if (ret) { + r->not_resumable = 1; + if (ctx->remove_session_cb != NULL) { + ctx->remove_session_cb(ctx, r); + } + SSL_SESSION_free(r); + } + } -long SSL_SESSION_get_time(const SSL_SESSION *s) - { - if (s == NULL) return(0); - return(s->time); - } + return ret; +} -long SSL_SESSION_set_time(SSL_SESSION *s, long t) - { - if (s == NULL) return(0); - s->time=t; - return(t); - } +void SSL_SESSION_free(SSL_SESSION *ss) { + int i; -X509 *SSL_SESSION_get0_peer(SSL_SESSION *s) - { - return s->peer; - } + if (ss == NULL) { + return; + } -int SSL_SESSION_set1_id_context(SSL_SESSION *s,const unsigned char *sid_ctx, - unsigned int sid_ctx_len) - { - if(sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) - { - OPENSSL_PUT_ERROR(SSL, SSL_SESSION_set1_id_context, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG); - return 0; - } - s->sid_ctx_length=sid_ctx_len; - memcpy(s->sid_ctx,sid_ctx,sid_ctx_len); + i = CRYPTO_add(&ss->references, -1, CRYPTO_LOCK_SSL_SESSION); + if (i > 0) { + return; + } - return 1; - } + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); -long SSL_CTX_set_timeout(SSL_CTX *s, long t) - { - long l; - if (s == NULL) return(0); - l=s->session_timeout; - s->session_timeout=t; - return(l); - } + OPENSSL_cleanse(ss->master_key, sizeof ss->master_key); + OPENSSL_cleanse(ss->session_id, sizeof ss->session_id); + if (ss->sess_cert != NULL) { + ssl_sess_cert_free(ss->sess_cert); + } + if (ss->peer != NULL) { + X509_free(ss->peer); + } + if (ss->tlsext_hostname != NULL) { + OPENSSL_free(ss->tlsext_hostname); + } + if (ss->tlsext_tick != NULL) { + OPENSSL_free(ss->tlsext_tick); + } + if (ss->tlsext_signed_cert_timestamp_list != NULL) { + OPENSSL_free(ss->tlsext_signed_cert_timestamp_list); + } + if (ss->ocsp_response != NULL) { + OPENSSL_free(ss->ocsp_response); + } + if (ss->psk_identity != NULL) { + OPENSSL_free(ss->psk_identity); + } + OPENSSL_cleanse(ss, sizeof(*ss)); + OPENSSL_free(ss); +} -long SSL_CTX_get_timeout(const SSL_CTX *s) - { - if (s == NULL) return(0); - return(s->session_timeout); - } +int SSL_set_session(SSL *s, SSL_SESSION *session) { + if (s->session == session) { + return 1; + } -typedef struct timeout_param_st - { - SSL_CTX *ctx; - long time; - LHASH_OF(SSL_SESSION) *cache; - } TIMEOUT_PARAM; + if (s->session != NULL) { + SSL_SESSION_free(s->session); + } + s->session = session; + if (session != NULL) { + CRYPTO_add(&session->references, 1, CRYPTO_LOCK_SSL_SESSION); + s->verify_result = session->verify_result; + } -static void timeout_doall_arg(SSL_SESSION *sess, void *void_param) - { - TIMEOUT_PARAM *param = void_param; + return 1; +} - if ((param->time == 0) || (param->time > (sess->time+sess->timeout))) /* timeout */ - { - /* The reason we don't call SSL_CTX_remove_session() is to - * save on locking overhead */ - (void)lh_SSL_SESSION_delete(param->cache,sess); - SSL_SESSION_list_remove(param->ctx,sess); - sess->not_resumable=1; - if (param->ctx->remove_session_cb != NULL) - param->ctx->remove_session_cb(param->ctx,sess); - SSL_SESSION_free(sess); - } - } +long SSL_SESSION_set_timeout(SSL_SESSION *s, long t) { + if (s == NULL) { + return 0; + } -void SSL_CTX_flush_sessions(SSL_CTX *s, long t) - { - TIMEOUT_PARAM tp; + s->timeout = t; + return 1; +} - tp.ctx=s; - tp.cache=s->sessions; - if (tp.cache == NULL) return; - tp.time=t; - CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); - lh_SSL_SESSION_doall_arg(tp.cache, timeout_doall_arg, &tp); - CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); - } +long SSL_SESSION_get_timeout(const SSL_SESSION *s) { + if (s == NULL) { + return 0; + } -int ssl_clear_bad_session(SSL *s) - { - if (s->session != NULL && - !(s->shutdown & SSL_SENT_SHUTDOWN) && - !SSL_in_init(s)) - { - SSL_CTX_remove_session(s->ctx,s->session); - return(1); - } - else - return(0); - } + return s->timeout; +} + +long SSL_SESSION_get_time(const SSL_SESSION *s) { + if (s == NULL) { + return 0; + } + + return s->time; +} + +long SSL_SESSION_set_time(SSL_SESSION *s, long t) { + if (s == NULL) { + return 0; + } + + s->time = t; + return t; +} + +X509 *SSL_SESSION_get0_peer(SSL_SESSION *s) { return s->peer; } + +int SSL_SESSION_set1_id_context(SSL_SESSION *s, const uint8_t *sid_ctx, + unsigned int sid_ctx_len) { + if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) { + OPENSSL_PUT_ERROR(SSL, SSL_SESSION_set1_id_context, + SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG); + return 0; + } + + s->sid_ctx_length = sid_ctx_len; + memcpy(s->sid_ctx, sid_ctx, sid_ctx_len); + + return 1; +} + +long SSL_CTX_set_timeout(SSL_CTX *s, long t) { + long l; + if (s == NULL) { + return 0; + } + + l = s->session_timeout; + s->session_timeout = t; + return l; +} + +long SSL_CTX_get_timeout(const SSL_CTX *s) { + if (s == NULL) { + return 0; + } + + return s->session_timeout; +} + +typedef struct timeout_param_st { + SSL_CTX *ctx; + long time; + LHASH_OF(SSL_SESSION) * cache; +} TIMEOUT_PARAM; + +static void timeout_doall_arg(SSL_SESSION *sess, void *void_param) { + TIMEOUT_PARAM *param = void_param; + + if (param->time == 0 || + param->time > (sess->time + sess->timeout)) { + /* timeout */ + /* The reason we don't call SSL_CTX_remove_session() is to + * save on locking overhead */ + lh_SSL_SESSION_delete(param->cache, sess); + SSL_SESSION_list_remove(param->ctx, sess); + sess->not_resumable = 1; + if (param->ctx->remove_session_cb != NULL) { + param->ctx->remove_session_cb(param->ctx, sess); + } + SSL_SESSION_free(sess); + } +} + +void SSL_CTX_flush_sessions(SSL_CTX *s, long t) { + TIMEOUT_PARAM tp; + + tp.ctx = s; + tp.cache = s->sessions; + if (tp.cache == NULL) { + return; + } + tp.time = t; + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + lh_SSL_SESSION_doall_arg(tp.cache, timeout_doall_arg, &tp); + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); +} + +int ssl_clear_bad_session(SSL *s) { + if (s->session != NULL && !(s->shutdown & SSL_SENT_SHUTDOWN) && + !SSL_in_init(s)) { + SSL_CTX_remove_session(s->ctx, s->session); + return 1; + } + + return 0; +} /* locked by SSL_CTX in the calling function */ -static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s) - { - if ((s->next == NULL) || (s->prev == NULL)) return; +static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s) { + if (s->next == NULL || s->prev == NULL) { + return; + } - if (s->next == (SSL_SESSION *)&(ctx->session_cache_tail)) - { /* last element in list */ - if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head)) - { /* only one element in list */ - ctx->session_cache_head=NULL; - ctx->session_cache_tail=NULL; - } - else - { - ctx->session_cache_tail=s->prev; - s->prev->next=(SSL_SESSION *)&(ctx->session_cache_tail); - } - } - else - { - if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head)) - { /* first element in list */ - ctx->session_cache_head=s->next; - s->next->prev=(SSL_SESSION *)&(ctx->session_cache_head); - } - else - { /* middle of list */ - s->next->prev=s->prev; - s->prev->next=s->next; - } - } - s->prev=s->next=NULL; - } + if (s->next == (SSL_SESSION *)&ctx->session_cache_tail) { + /* last element in list */ + if (s->prev == (SSL_SESSION *)&ctx->session_cache_head) { + /* only one element in list */ + ctx->session_cache_head = NULL; + ctx->session_cache_tail = NULL; + } else { + ctx->session_cache_tail = s->prev; + s->prev->next = (SSL_SESSION *)&(ctx->session_cache_tail); + } + } else { + if (s->prev == (SSL_SESSION *)&ctx->session_cache_head) { + /* first element in list */ + ctx->session_cache_head = s->next; + s->next->prev = (SSL_SESSION *)&(ctx->session_cache_head); + } else { /* middle of list */ + s->next->prev = s->prev; + s->prev->next = s->next; + } + } + s->prev = s->next = NULL; +} -static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s) - { - if ((s->next != NULL) && (s->prev != NULL)) - SSL_SESSION_list_remove(ctx,s); +static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s) { + if (s->next != NULL && s->prev != NULL) { + SSL_SESSION_list_remove(ctx, s); + } - if (ctx->session_cache_head == NULL) - { - ctx->session_cache_head=s; - ctx->session_cache_tail=s; - s->prev=(SSL_SESSION *)&(ctx->session_cache_head); - s->next=(SSL_SESSION *)&(ctx->session_cache_tail); - } - else - { - s->next=ctx->session_cache_head; - s->next->prev=s; - s->prev=(SSL_SESSION *)&(ctx->session_cache_head); - ctx->session_cache_head=s; - } - } + if (ctx->session_cache_head == NULL) { + ctx->session_cache_head = s; + ctx->session_cache_tail = s; + s->prev = (SSL_SESSION *)&(ctx->session_cache_head); + s->next = (SSL_SESSION *)&(ctx->session_cache_tail); + } else { + s->next = ctx->session_cache_head; + s->next->prev = s; + s->prev = (SSL_SESSION *)&(ctx->session_cache_head); + ctx->session_cache_head = s; + } +} void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx, - int (*cb)(struct ssl_st *ssl,SSL_SESSION *sess)) - { - ctx->new_session_cb=cb; - } + int (*cb)(struct ssl_st *ssl, SSL_SESSION *sess)) { + ctx->new_session_cb = cb; +} -int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(SSL *ssl, SSL_SESSION *sess) - { - return ctx->new_session_cb; - } +int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(SSL *ssl, SSL_SESSION *sess) { + return ctx->new_session_cb; +} void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx, - void (*cb)(SSL_CTX *ctx,SSL_SESSION *sess)) - { - ctx->remove_session_cb=cb; - } + void (*cb)(SSL_CTX *ctx, SSL_SESSION *sess)) { + ctx->remove_session_cb = cb; +} -void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(SSL_CTX * ctx,SSL_SESSION *sess) - { - return ctx->remove_session_cb; - } +void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(SSL_CTX *ctx, + SSL_SESSION *sess) { + return ctx->remove_session_cb; +} void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, - SSL_SESSION *(*cb)(struct ssl_st *ssl, - unsigned char *data,int len,int *copy)) - { - ctx->get_session_cb=cb; - } + SSL_SESSION *(*cb)(struct ssl_st *ssl, + uint8_t *data, int len, + int *copy)) { + ctx->get_session_cb = cb; +} -SSL_SESSION * (*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(SSL *ssl, - unsigned char *data,int len,int *copy) - { - return ctx->get_session_cb; - } +SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(SSL *ssl, uint8_t *data, + int len, int *copy) { + return ctx->get_session_cb; +} -void SSL_CTX_set_info_callback(SSL_CTX *ctx, - void (*cb)(const SSL *ssl,int type,int val)) - { - ctx->info_callback=cb; - } +void SSL_CTX_set_info_callback(SSL_CTX *ctx, + void (*cb)(const SSL *ssl, int type, int val)) { + ctx->info_callback = cb; +} -void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl,int type,int val) - { - return ctx->info_callback; - } +void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl, int type, + int val) { + return ctx->info_callback; +} -void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, - int (*cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey)) - { - ctx->client_cert_cb=cb; - } +void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, int (*cb)(SSL *ssl, X509 **x509, + EVP_PKEY **pkey)) { + ctx->client_cert_cb = cb; +} -int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL * ssl, X509 ** x509 , EVP_PKEY **pkey) - { - return ctx->client_cert_cb; - } +int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL *ssl, X509 **x509, + EVP_PKEY **pkey) { + return ctx->client_cert_cb; +} void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx, - int (*cb)(SSL *ssl, uint8_t *cookie, size_t *cookie_len)) - { - ctx->app_gen_cookie_cb=cb; - } + int (*cb)(SSL *ssl, uint8_t *cookie, + size_t *cookie_len)) { + ctx->app_gen_cookie_cb = cb; +} void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx, - int (*cb)(SSL *ssl, const uint8_t *cookie, size_t cookie_len)) - { - ctx->app_verify_cookie_cb=cb; - } + int (*cb)(SSL *ssl, const uint8_t *cookie, + size_t cookie_len)) { + ctx->app_verify_cookie_cb = cb; +} void SSL_CTX_set_channel_id_cb(SSL_CTX *ctx, - void (*cb)(SSL *ssl, EVP_PKEY **pkey)) - { - ctx->channel_id_cb=cb; - } + void (*cb)(SSL *ssl, EVP_PKEY **pkey)) { + ctx->channel_id_cb = cb; +} -void (*SSL_CTX_get_channel_id_cb(SSL_CTX *ctx))(SSL * ssl, EVP_PKEY **pkey) - { - return ctx->channel_id_cb; - } +void (*SSL_CTX_get_channel_id_cb(SSL_CTX *ctx))(SSL *ssl, EVP_PKEY **pkey) { + return ctx->channel_id_cb; +} IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION)
diff --git a/ssl/ssl_stat.c b/ssl/ssl_stat.c index 465c8ef..450ed7c 100644 --- a/ssl/ssl_stat.c +++ b/ssl/ssl_stat.c
@@ -85,391 +85,934 @@ #include <stdio.h> #include "ssl_locl.h" -const char *SSL_state_string_long(const SSL *s) - { - const char *str; +const char *SSL_state_string_long(const SSL *s) { + const char *str; - switch (s->state) - { -case SSL_ST_ACCEPT: str="before accept initialization"; break; -case SSL_ST_CONNECT: str="before connect initialization"; break; -case SSL_ST_OK: str="SSL negotiation finished successfully"; break; -case SSL_ST_RENEGOTIATE: str="SSL renegotiate ciphers"; break; -case SSL_ST_BEFORE|SSL_ST_CONNECT: str="before/connect initialization"; break; -case SSL_ST_BEFORE|SSL_ST_ACCEPT: str="before/accept initialization"; break; + switch (s->state) { + case SSL_ST_ACCEPT: + str = "before accept initialization"; + break; -/* SSLv3 additions */ -case SSL3_ST_CW_CLNT_HELLO_A: str="SSLv3 write client hello A"; break; -case SSL3_ST_CW_CLNT_HELLO_B: str="SSLv3 write client hello B"; break; -case SSL3_ST_CR_SRVR_HELLO_A: str="SSLv3 read server hello A"; break; -case SSL3_ST_CR_SRVR_HELLO_B: str="SSLv3 read server hello B"; break; -case SSL3_ST_CR_CERT_A: str="SSLv3 read server certificate A"; break; -case SSL3_ST_CR_CERT_B: str="SSLv3 read server certificate B"; break; -case SSL3_ST_CR_KEY_EXCH_A: str="SSLv3 read server key exchange A"; break; -case SSL3_ST_CR_KEY_EXCH_B: str="SSLv3 read server key exchange B"; break; -case SSL3_ST_CR_CERT_REQ_A: str="SSLv3 read server certificate request A"; break; -case SSL3_ST_CR_CERT_REQ_B: str="SSLv3 read server certificate request B"; break; -case SSL3_ST_CR_SESSION_TICKET_A: str="SSLv3 read server session ticket A";break; -case SSL3_ST_CR_SESSION_TICKET_B: str="SSLv3 read server session ticket B";break; -case SSL3_ST_CR_SRVR_DONE_A: str="SSLv3 read server done A"; break; -case SSL3_ST_CR_SRVR_DONE_B: str="SSLv3 read server done B"; break; -case SSL3_ST_CW_CERT_A: str="SSLv3 write client certificate A"; break; -case SSL3_ST_CW_CERT_B: str="SSLv3 write client certificate B"; break; -case SSL3_ST_CW_CERT_C: str="SSLv3 write client certificate C"; break; -case SSL3_ST_CW_CERT_D: str="SSLv3 write client certificate D"; break; -case SSL3_ST_CW_KEY_EXCH_A: str="SSLv3 write client key exchange A"; break; -case SSL3_ST_CW_KEY_EXCH_B: str="SSLv3 write client key exchange B"; break; -case SSL3_ST_CW_CERT_VRFY_A: str="SSLv3 write certificate verify A"; break; -case SSL3_ST_CW_CERT_VRFY_B: str="SSLv3 write certificate verify B"; break; + case SSL_ST_CONNECT: + str = "before connect initialization"; + break; -case SSL3_ST_CW_CHANGE_A: -case SSL3_ST_SW_CHANGE_A: str="SSLv3 write change cipher spec A"; break; -case SSL3_ST_CW_CHANGE_B: -case SSL3_ST_SW_CHANGE_B: str="SSLv3 write change cipher spec B"; break; -case SSL3_ST_CW_FINISHED_A: -case SSL3_ST_SW_FINISHED_A: str="SSLv3 write finished A"; break; -case SSL3_ST_CW_FINISHED_B: -case SSL3_ST_SW_FINISHED_B: str="SSLv3 write finished B"; break; -case SSL3_ST_CR_CHANGE: -case SSL3_ST_SR_CHANGE: str="SSLv3 read change cipher spec"; break; -case SSL3_ST_CR_FINISHED_A: -case SSL3_ST_SR_FINISHED_A: str="SSLv3 read finished A"; break; -case SSL3_ST_CR_FINISHED_B: -case SSL3_ST_SR_FINISHED_B: str="SSLv3 read finished B"; break; + case SSL_ST_OK: + str = "SSL negotiation finished successfully"; + break; -case SSL3_ST_CW_FLUSH: -case SSL3_ST_SW_FLUSH: str="SSLv3 flush data"; break; + case SSL_ST_RENEGOTIATE: + str = "SSL renegotiate ciphers"; + break; -case SSL3_ST_SR_CLNT_HELLO_A: str="SSLv3 read client hello A"; break; -case SSL3_ST_SR_CLNT_HELLO_B: str="SSLv3 read client hello B"; break; -case SSL3_ST_SR_CLNT_HELLO_C: str="SSLv3 read client hello C"; break; -case SSL3_ST_SR_CLNT_HELLO_D: str="SSLv3 read client hello D"; break; -case SSL3_ST_SW_HELLO_REQ_A: str="SSLv3 write hello request A"; break; -case SSL3_ST_SW_HELLO_REQ_B: str="SSLv3 write hello request B"; break; -case SSL3_ST_SW_HELLO_REQ_C: str="SSLv3 write hello request C"; break; -case SSL3_ST_SW_SRVR_HELLO_A: str="SSLv3 write server hello A"; break; -case SSL3_ST_SW_SRVR_HELLO_B: str="SSLv3 write server hello B"; break; -case SSL3_ST_SW_CERT_A: str="SSLv3 write certificate A"; break; -case SSL3_ST_SW_CERT_B: str="SSLv3 write certificate B"; break; -case SSL3_ST_SW_KEY_EXCH_A: str="SSLv3 write key exchange A"; break; -case SSL3_ST_SW_KEY_EXCH_B: str="SSLv3 write key exchange B"; break; -case SSL3_ST_SW_CERT_REQ_A: str="SSLv3 write certificate request A"; break; -case SSL3_ST_SW_CERT_REQ_B: str="SSLv3 write certificate request B"; break; -case SSL3_ST_SW_SESSION_TICKET_A: str="SSLv3 write session ticket A"; break; -case SSL3_ST_SW_SESSION_TICKET_B: str="SSLv3 write session ticket B"; break; -case SSL3_ST_SW_SRVR_DONE_A: str="SSLv3 write server done A"; break; -case SSL3_ST_SW_SRVR_DONE_B: str="SSLv3 write server done B"; break; -case SSL3_ST_SR_CERT_A: str="SSLv3 read client certificate A"; break; -case SSL3_ST_SR_CERT_B: str="SSLv3 read client certificate B"; break; -case SSL3_ST_SR_KEY_EXCH_A: str="SSLv3 read client key exchange A"; break; -case SSL3_ST_SR_KEY_EXCH_B: str="SSLv3 read client key exchange B"; break; -case SSL3_ST_SR_CERT_VRFY_A: str="SSLv3 read certificate verify A"; break; -case SSL3_ST_SR_CERT_VRFY_B: str="SSLv3 read certificate verify B"; break; + case SSL_ST_BEFORE | SSL_ST_CONNECT: + str = "before/connect initialization"; + break; -/* SSLv2/v3 compatibility states */ -/* client */ -case SSL23_ST_CW_CLNT_HELLO_A: str="SSLv2/v3 write client hello A"; break; -case SSL23_ST_CW_CLNT_HELLO_B: str="SSLv2/v3 write client hello B"; break; -case SSL23_ST_CR_SRVR_HELLO_A: str="SSLv2/v3 read server hello A"; break; -case SSL23_ST_CR_SRVR_HELLO_B: str="SSLv2/v3 read server hello B"; break; -/* server */ -case SSL23_ST_SR_CLNT_HELLO: str="SSLv2/v3 read client hello"; break; -case SSL23_ST_SR_V2_CLNT_HELLO: str="SSLv2/v3 read v2 client hello"; break; -case SSL23_ST_SR_SWITCH_VERSION: str="SSLv2/v3 switch version"; break; + case SSL_ST_BEFORE | SSL_ST_ACCEPT: + str = "before/accept initialization"; + break; -/* DTLS */ -case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A: str="DTLS1 read hello verify request A"; break; -case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B: str="DTLS1 read hello verify request B"; break; -case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A: str="DTLS1 write hello verify request A"; break; -case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B: str="DTLS1 write hello verify request B"; break; + /* SSLv3 additions */ + case SSL3_ST_CW_CLNT_HELLO_A: + str = "SSLv3 write client hello A"; + break; -default: str="unknown state"; break; - } - return(str); - } + case SSL3_ST_CW_CLNT_HELLO_B: + str = "SSLv3 write client hello B"; + break; -const char *SSL_rstate_string_long(const SSL *s) - { - const char *str; + case SSL3_ST_CR_SRVR_HELLO_A: + str = "SSLv3 read server hello A"; + break; - switch (s->rstate) - { - case SSL_ST_READ_HEADER: str="read header"; break; - case SSL_ST_READ_BODY: str="read body"; break; - case SSL_ST_READ_DONE: str="read done"; break; - default: str="unknown"; break; - } - return(str); - } + case SSL3_ST_CR_SRVR_HELLO_B: + str = "SSLv3 read server hello B"; + break; -const char *SSL_state_string(const SSL *s) - { - const char *str; + case SSL3_ST_CR_CERT_A: + str = "SSLv3 read server certificate A"; + break; - switch (s->state) - { -case SSL_ST_ACCEPT: str="AINIT "; break; -case SSL_ST_CONNECT: str="CINIT "; break; -case SSL_ST_OK: str="SSLOK "; break; + case SSL3_ST_CR_CERT_B: + str = "SSLv3 read server certificate B"; + break; -/* SSLv3 additions */ -case SSL3_ST_SW_FLUSH: -case SSL3_ST_CW_FLUSH: str="3FLUSH"; break; -case SSL3_ST_CW_CLNT_HELLO_A: str="3WCH_A"; break; -case SSL3_ST_CW_CLNT_HELLO_B: str="3WCH_B"; break; -case SSL3_ST_CR_SRVR_HELLO_A: str="3RSH_A"; break; -case SSL3_ST_CR_SRVR_HELLO_B: str="3RSH_B"; break; -case SSL3_ST_CR_CERT_A: str="3RSC_A"; break; -case SSL3_ST_CR_CERT_B: str="3RSC_B"; break; -case SSL3_ST_CR_KEY_EXCH_A: str="3RSKEA"; break; -case SSL3_ST_CR_KEY_EXCH_B: str="3RSKEB"; break; -case SSL3_ST_CR_CERT_REQ_A: str="3RCR_A"; break; -case SSL3_ST_CR_CERT_REQ_B: str="3RCR_B"; break; -case SSL3_ST_CR_SRVR_DONE_A: str="3RSD_A"; break; -case SSL3_ST_CR_SRVR_DONE_B: str="3RSD_B"; break; -case SSL3_ST_CW_CERT_A: str="3WCC_A"; break; -case SSL3_ST_CW_CERT_B: str="3WCC_B"; break; -case SSL3_ST_CW_CERT_C: str="3WCC_C"; break; -case SSL3_ST_CW_CERT_D: str="3WCC_D"; break; -case SSL3_ST_CW_KEY_EXCH_A: str="3WCKEA"; break; -case SSL3_ST_CW_KEY_EXCH_B: str="3WCKEB"; break; -case SSL3_ST_CW_CERT_VRFY_A: str="3WCV_A"; break; -case SSL3_ST_CW_CERT_VRFY_B: str="3WCV_B"; break; + case SSL3_ST_CR_KEY_EXCH_A: + str = "SSLv3 read server key exchange A"; + break; -case SSL3_ST_SW_CHANGE_A: -case SSL3_ST_CW_CHANGE_A: str="3WCCSA"; break; -case SSL3_ST_SW_CHANGE_B: -case SSL3_ST_CW_CHANGE_B: str="3WCCSB"; break; -case SSL3_ST_SW_FINISHED_A: -case SSL3_ST_CW_FINISHED_A: str="3WFINA"; break; -case SSL3_ST_SW_FINISHED_B: -case SSL3_ST_CW_FINISHED_B: str="3WFINB"; break; -case SSL3_ST_CR_CHANGE: -case SSL3_ST_SR_CHANGE: str="3RCCS_"; break; -case SSL3_ST_SR_FINISHED_A: -case SSL3_ST_CR_FINISHED_A: str="3RFINA"; break; -case SSL3_ST_SR_FINISHED_B: -case SSL3_ST_CR_FINISHED_B: str="3RFINB"; break; + case SSL3_ST_CR_KEY_EXCH_B: + str = "SSLv3 read server key exchange B"; + break; -case SSL3_ST_SW_HELLO_REQ_A: str="3WHR_A"; break; -case SSL3_ST_SW_HELLO_REQ_B: str="3WHR_B"; break; -case SSL3_ST_SW_HELLO_REQ_C: str="3WHR_C"; break; -case SSL3_ST_SR_CLNT_HELLO_A: str="3RCH_A"; break; -case SSL3_ST_SR_CLNT_HELLO_B: str="3RCH_B"; break; -case SSL3_ST_SR_CLNT_HELLO_C: str="3RCH_C"; break; -case SSL3_ST_SR_CLNT_HELLO_D: str="3RCH_D"; break; -case SSL3_ST_SW_SRVR_HELLO_A: str="3WSH_A"; break; -case SSL3_ST_SW_SRVR_HELLO_B: str="3WSH_B"; break; -case SSL3_ST_SW_CERT_A: str="3WSC_A"; break; -case SSL3_ST_SW_CERT_B: str="3WSC_B"; break; -case SSL3_ST_SW_KEY_EXCH_A: str="3WSKEA"; break; -case SSL3_ST_SW_KEY_EXCH_B: str="3WSKEB"; break; -case SSL3_ST_SW_CERT_REQ_A: str="3WCR_A"; break; -case SSL3_ST_SW_CERT_REQ_B: str="3WCR_B"; break; -case SSL3_ST_SW_SRVR_DONE_A: str="3WSD_A"; break; -case SSL3_ST_SW_SRVR_DONE_B: str="3WSD_B"; break; -case SSL3_ST_SR_CERT_A: str="3RCC_A"; break; -case SSL3_ST_SR_CERT_B: str="3RCC_B"; break; -case SSL3_ST_SR_KEY_EXCH_A: str="3RCKEA"; break; -case SSL3_ST_SR_KEY_EXCH_B: str="3RCKEB"; break; -case SSL3_ST_SR_CERT_VRFY_A: str="3RCV_A"; break; -case SSL3_ST_SR_CERT_VRFY_B: str="3RCV_B"; break; + case SSL3_ST_CR_CERT_REQ_A: + str = "SSLv3 read server certificate request A"; + break; -/* SSLv2/v3 compatibility states */ -/* client */ -case SSL23_ST_CW_CLNT_HELLO_A: str="23WCHA"; break; -case SSL23_ST_CW_CLNT_HELLO_B: str="23WCHB"; break; -case SSL23_ST_CR_SRVR_HELLO_A: str="23RSHA"; break; -case SSL23_ST_CR_SRVR_HELLO_B: str="23RSHA"; break; -/* server */ -case SSL23_ST_SR_CLNT_HELLO: str="23RCH_"; break; -case SSL23_ST_SR_V2_CLNT_HELLO: str="23R2CH"; break; -case SSL23_ST_SR_SWITCH_VERSION: str="23RSW_"; break; -/* DTLS */ -case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A: str="DRCHVA"; break; -case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B: str="DRCHVB"; break; -case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A: str="DWCHVA"; break; -case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B: str="DWCHVB"; break; + case SSL3_ST_CR_CERT_REQ_B: + str = "SSLv3 read server certificate request B"; + break; -default: str="UNKWN "; break; - } - return(str); - } + case SSL3_ST_CR_SESSION_TICKET_A: + str = "SSLv3 read server session ticket A"; + break; -const char *SSL_alert_type_string_long(int value) - { - value>>=8; - if (value == SSL3_AL_WARNING) - return("warning"); - else if (value == SSL3_AL_FATAL) - return("fatal"); - else - return("unknown"); - } + case SSL3_ST_CR_SESSION_TICKET_B: + str = "SSLv3 read server session ticket B"; + break; -const char *SSL_alert_type_string(int value) - { - value>>=8; - if (value == SSL3_AL_WARNING) - return("W"); - else if (value == SSL3_AL_FATAL) - return("F"); - else - return("U"); - } + case SSL3_ST_CR_SRVR_DONE_A: + str = "SSLv3 read server done A"; + break; -const char *SSL_alert_desc_string(int value) - { - const char *str; + case SSL3_ST_CR_SRVR_DONE_B: + str = "SSLv3 read server done B"; + break; - switch (value & 0xff) - { - case SSL3_AD_CLOSE_NOTIFY: str="CN"; break; - case SSL3_AD_UNEXPECTED_MESSAGE: str="UM"; break; - case SSL3_AD_BAD_RECORD_MAC: str="BM"; break; - case SSL3_AD_DECOMPRESSION_FAILURE: str="DF"; break; - case SSL3_AD_HANDSHAKE_FAILURE: str="HF"; break; - case SSL3_AD_NO_CERTIFICATE: str="NC"; break; - case SSL3_AD_BAD_CERTIFICATE: str="BC"; break; - case SSL3_AD_UNSUPPORTED_CERTIFICATE: str="UC"; break; - case SSL3_AD_CERTIFICATE_REVOKED: str="CR"; break; - case SSL3_AD_CERTIFICATE_EXPIRED: str="CE"; break; - case SSL3_AD_CERTIFICATE_UNKNOWN: str="CU"; break; - case SSL3_AD_ILLEGAL_PARAMETER: str="IP"; break; - case TLS1_AD_DECRYPTION_FAILED: str="DC"; break; - case TLS1_AD_RECORD_OVERFLOW: str="RO"; break; - case TLS1_AD_UNKNOWN_CA: str="CA"; break; - case TLS1_AD_ACCESS_DENIED: str="AD"; break; - case TLS1_AD_DECODE_ERROR: str="DE"; break; - case TLS1_AD_DECRYPT_ERROR: str="CY"; break; - case TLS1_AD_EXPORT_RESTRICTION: str="ER"; break; - case TLS1_AD_PROTOCOL_VERSION: str="PV"; break; - case TLS1_AD_INSUFFICIENT_SECURITY: str="IS"; break; - case TLS1_AD_INTERNAL_ERROR: str="IE"; break; - case TLS1_AD_USER_CANCELLED: str="US"; break; - case TLS1_AD_NO_RENEGOTIATION: str="NR"; break; - case TLS1_AD_UNSUPPORTED_EXTENSION: str="UE"; break; - case TLS1_AD_CERTIFICATE_UNOBTAINABLE: str="CO"; break; - case TLS1_AD_UNRECOGNIZED_NAME: str="UN"; break; - case TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE: str="BR"; break; - case TLS1_AD_BAD_CERTIFICATE_HASH_VALUE: str="BH"; break; - case TLS1_AD_UNKNOWN_PSK_IDENTITY: str="UP"; break; - default: str="UK"; break; - } - return(str); - } + case SSL3_ST_CW_CERT_A: + str = "SSLv3 write client certificate A"; + break; -const char *SSL_alert_desc_string_long(int value) - { - const char *str; + case SSL3_ST_CW_CERT_B: + str = "SSLv3 write client certificate B"; + break; - switch (value & 0xff) - { - case SSL3_AD_CLOSE_NOTIFY: - str="close notify"; - break; - case SSL3_AD_UNEXPECTED_MESSAGE: - str="unexpected_message"; - break; - case SSL3_AD_BAD_RECORD_MAC: - str="bad record mac"; - break; - case SSL3_AD_DECOMPRESSION_FAILURE: - str="decompression failure"; - break; - case SSL3_AD_HANDSHAKE_FAILURE: - str="handshake failure"; - break; - case SSL3_AD_NO_CERTIFICATE: - str="no certificate"; - break; - case SSL3_AD_BAD_CERTIFICATE: - str="bad certificate"; - break; - case SSL3_AD_UNSUPPORTED_CERTIFICATE: - str="unsupported certificate"; - break; - case SSL3_AD_CERTIFICATE_REVOKED: - str="certificate revoked"; - break; - case SSL3_AD_CERTIFICATE_EXPIRED: - str="certificate expired"; - break; - case SSL3_AD_CERTIFICATE_UNKNOWN: - str="certificate unknown"; - break; - case SSL3_AD_ILLEGAL_PARAMETER: - str="illegal parameter"; - break; - case TLS1_AD_DECRYPTION_FAILED: - str="decryption failed"; - break; - case TLS1_AD_RECORD_OVERFLOW: - str="record overflow"; - break; - case TLS1_AD_UNKNOWN_CA: - str="unknown CA"; - break; - case TLS1_AD_ACCESS_DENIED: - str="access denied"; - break; - case TLS1_AD_DECODE_ERROR: - str="decode error"; - break; - case TLS1_AD_DECRYPT_ERROR: - str="decrypt error"; - break; - case TLS1_AD_EXPORT_RESTRICTION: - str="export restriction"; - break; - case TLS1_AD_PROTOCOL_VERSION: - str="protocol version"; - break; - case TLS1_AD_INSUFFICIENT_SECURITY: - str="insufficient security"; - break; - case TLS1_AD_INTERNAL_ERROR: - str="internal error"; - break; - case TLS1_AD_USER_CANCELLED: - str="user canceled"; - break; - case TLS1_AD_NO_RENEGOTIATION: - str="no renegotiation"; - break; - case TLS1_AD_UNSUPPORTED_EXTENSION: - str="unsupported extension"; - break; - case TLS1_AD_CERTIFICATE_UNOBTAINABLE: - str="certificate unobtainable"; - break; - case TLS1_AD_UNRECOGNIZED_NAME: - str="unrecognized name"; - break; - case TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE: - str="bad certificate status response"; - break; - case TLS1_AD_BAD_CERTIFICATE_HASH_VALUE: - str="bad certificate hash value"; - break; - case TLS1_AD_UNKNOWN_PSK_IDENTITY: - str="unknown PSK identity"; - break; - default: str="unknown"; break; - } - return(str); - } + case SSL3_ST_CW_CERT_C: + str = "SSLv3 write client certificate C"; + break; -const char *SSL_rstate_string(const SSL *s) - { - const char *str; + case SSL3_ST_CW_CERT_D: + str = "SSLv3 write client certificate D"; + break; - switch (s->rstate) - { - case SSL_ST_READ_HEADER:str="RH"; break; - case SSL_ST_READ_BODY: str="RB"; break; - case SSL_ST_READ_DONE: str="RD"; break; - default: str="unknown"; break; - } - return(str); - } + case SSL3_ST_CW_KEY_EXCH_A: + str = "SSLv3 write client key exchange A"; + break; + + case SSL3_ST_CW_KEY_EXCH_B: + str = "SSLv3 write client key exchange B"; + break; + + case SSL3_ST_CW_CERT_VRFY_A: + str = "SSLv3 write certificate verify A"; + break; + + case SSL3_ST_CW_CERT_VRFY_B: + str = "SSLv3 write certificate verify B"; + break; + + case SSL3_ST_CW_CHANGE_A: + case SSL3_ST_SW_CHANGE_A: + str = "SSLv3 write change cipher spec A"; + break; + + case SSL3_ST_CW_CHANGE_B: + case SSL3_ST_SW_CHANGE_B: + str = "SSLv3 write change cipher spec B"; + break; + + case SSL3_ST_CW_FINISHED_A: + case SSL3_ST_SW_FINISHED_A: + str = "SSLv3 write finished A"; + break; + + case SSL3_ST_CW_FINISHED_B: + case SSL3_ST_SW_FINISHED_B: + str = "SSLv3 write finished B"; + break; + + case SSL3_ST_CR_CHANGE: + case SSL3_ST_SR_CHANGE: + str = "SSLv3 read change cipher spec"; + break; + + case SSL3_ST_CR_FINISHED_A: + case SSL3_ST_SR_FINISHED_A: + str = "SSLv3 read finished A"; + break; + + case SSL3_ST_CR_FINISHED_B: + case SSL3_ST_SR_FINISHED_B: + str = "SSLv3 read finished B"; + break; + + case SSL3_ST_CW_FLUSH: + case SSL3_ST_SW_FLUSH: + str = "SSLv3 flush data"; + break; + + case SSL3_ST_SR_CLNT_HELLO_A: + str = "SSLv3 read client hello A"; + break; + + case SSL3_ST_SR_CLNT_HELLO_B: + str = "SSLv3 read client hello B"; + break; + + case SSL3_ST_SR_CLNT_HELLO_C: + str = "SSLv3 read client hello C"; + break; + + case SSL3_ST_SR_CLNT_HELLO_D: + str = "SSLv3 read client hello D"; + break; + + case SSL3_ST_SW_HELLO_REQ_A: + str = "SSLv3 write hello request A"; + break; + + case SSL3_ST_SW_HELLO_REQ_B: + str = "SSLv3 write hello request B"; + break; + + case SSL3_ST_SW_HELLO_REQ_C: + str = "SSLv3 write hello request C"; + break; + + case SSL3_ST_SW_SRVR_HELLO_A: + str = "SSLv3 write server hello A"; + break; + + case SSL3_ST_SW_SRVR_HELLO_B: + str = "SSLv3 write server hello B"; + break; + + case SSL3_ST_SW_CERT_A: + str = "SSLv3 write certificate A"; + break; + + case SSL3_ST_SW_CERT_B: + str = "SSLv3 write certificate B"; + break; + + case SSL3_ST_SW_KEY_EXCH_A: + str = "SSLv3 write key exchange A"; + break; + + case SSL3_ST_SW_KEY_EXCH_B: + str = "SSLv3 write key exchange B"; + break; + + case SSL3_ST_SW_CERT_REQ_A: + str = "SSLv3 write certificate request A"; + break; + + case SSL3_ST_SW_CERT_REQ_B: + str = "SSLv3 write certificate request B"; + break; + + case SSL3_ST_SW_SESSION_TICKET_A: + str = "SSLv3 write session ticket A"; + break; + + case SSL3_ST_SW_SESSION_TICKET_B: + str = "SSLv3 write session ticket B"; + break; + + case SSL3_ST_SW_SRVR_DONE_A: + str = "SSLv3 write server done A"; + break; + + case SSL3_ST_SW_SRVR_DONE_B: + str = "SSLv3 write server done B"; + break; + + case SSL3_ST_SR_CERT_A: + str = "SSLv3 read client certificate A"; + break; + + case SSL3_ST_SR_CERT_B: + str = "SSLv3 read client certificate B"; + break; + + case SSL3_ST_SR_KEY_EXCH_A: + str = "SSLv3 read client key exchange A"; + break; + + case SSL3_ST_SR_KEY_EXCH_B: + str = "SSLv3 read client key exchange B"; + break; + + case SSL3_ST_SR_CERT_VRFY_A: + str = "SSLv3 read certificate verify A"; + break; + + case SSL3_ST_SR_CERT_VRFY_B: + str = "SSLv3 read certificate verify B"; + break; + + /* SSLv2/v3 compatibility states */ + /* client */ + case SSL23_ST_CW_CLNT_HELLO_A: + str = "SSLv2/v3 write client hello A"; + break; + + case SSL23_ST_CW_CLNT_HELLO_B: + str = "SSLv2/v3 write client hello B"; + break; + + case SSL23_ST_CR_SRVR_HELLO_A: + str = "SSLv2/v3 read server hello A"; + break; + + case SSL23_ST_CR_SRVR_HELLO_B: + str = "SSLv2/v3 read server hello B"; + break; + + /* server */ + case SSL23_ST_SR_CLNT_HELLO: + str = "SSLv2/v3 read client hello"; + break; + + case SSL23_ST_SR_V2_CLNT_HELLO: + str = "SSLv2/v3 read v2 client hello"; + break; + + case SSL23_ST_SR_SWITCH_VERSION: + str = "SSLv2/v3 switch version"; + break; + + /* DTLS */ + case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A: + str = "DTLS1 read hello verify request A"; + break; + + case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B: + str = "DTLS1 read hello verify request B"; + break; + + case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A: + str = "DTLS1 write hello verify request A"; + break; + + case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B: + str = "DTLS1 write hello verify request B"; + break; + + default: + str = "unknown state"; + break; + } + + return str; +} + +const char *SSL_rstate_string_long(const SSL *s) { + const char *str; + + switch (s->rstate) { + case SSL_ST_READ_HEADER: + str = "read header"; + break; + + case SSL_ST_READ_BODY: + str = "read body"; + break; + + case SSL_ST_READ_DONE: + str = "read done"; + break; + + default: + str = "unknown"; + break; + } + + return str; +} + +const char *SSL_state_string(const SSL *s) { + const char *str; + + switch (s->state) { + case SSL_ST_ACCEPT: + str = "AINIT "; + break; + + case SSL_ST_CONNECT: + str = "CINIT "; + break; + + case SSL_ST_OK: + str = "SSLOK "; + break; + + /* SSLv3 additions */ + case SSL3_ST_SW_FLUSH: + case SSL3_ST_CW_FLUSH: + str = "3FLUSH"; + break; + + case SSL3_ST_CW_CLNT_HELLO_A: + str = "3WCH_A"; + break; + + case SSL3_ST_CW_CLNT_HELLO_B: + str = "3WCH_B"; + break; + + case SSL3_ST_CR_SRVR_HELLO_A: + str = "3RSH_A"; + break; + + case SSL3_ST_CR_SRVR_HELLO_B: + str = "3RSH_B"; + break; + + case SSL3_ST_CR_CERT_A: + str = "3RSC_A"; + break; + + case SSL3_ST_CR_CERT_B: + str = "3RSC_B"; + break; + + case SSL3_ST_CR_KEY_EXCH_A: + str = "3RSKEA"; + break; + + case SSL3_ST_CR_KEY_EXCH_B: + str = "3RSKEB"; + break; + + case SSL3_ST_CR_CERT_REQ_A: + str = "3RCR_A"; + break; + + case SSL3_ST_CR_CERT_REQ_B: + str = "3RCR_B"; + break; + + case SSL3_ST_CR_SRVR_DONE_A: + str = "3RSD_A"; + break; + + case SSL3_ST_CR_SRVR_DONE_B: + str = "3RSD_B"; + break; + + case SSL3_ST_CW_CERT_A: + str = "3WCC_A"; + break; + + case SSL3_ST_CW_CERT_B: + str = "3WCC_B"; + break; + + case SSL3_ST_CW_CERT_C: + str = "3WCC_C"; + break; + + case SSL3_ST_CW_CERT_D: + str = "3WCC_D"; + break; + + case SSL3_ST_CW_KEY_EXCH_A: + str = "3WCKEA"; + break; + + case SSL3_ST_CW_KEY_EXCH_B: + str = "3WCKEB"; + break; + + case SSL3_ST_CW_CERT_VRFY_A: + str = "3WCV_A"; + break; + + case SSL3_ST_CW_CERT_VRFY_B: + str = "3WCV_B"; + break; + + case SSL3_ST_SW_CHANGE_A: + case SSL3_ST_CW_CHANGE_A: + str = "3WCCSA"; + break; + + case SSL3_ST_SW_CHANGE_B: + case SSL3_ST_CW_CHANGE_B: + str = "3WCCSB"; + break; + + case SSL3_ST_SW_FINISHED_A: + case SSL3_ST_CW_FINISHED_A: + str = "3WFINA"; + break; + + case SSL3_ST_SW_FINISHED_B: + case SSL3_ST_CW_FINISHED_B: + str = "3WFINB"; + break; + + case SSL3_ST_CR_CHANGE: + case SSL3_ST_SR_CHANGE: + str = "3RCCS_"; + break; + + case SSL3_ST_SR_FINISHED_A: + case SSL3_ST_CR_FINISHED_A: + str = "3RFINA"; + break; + + case SSL3_ST_SR_FINISHED_B: + case SSL3_ST_CR_FINISHED_B: + str = "3RFINB"; + break; + + case SSL3_ST_SW_HELLO_REQ_A: + str = "3WHR_A"; + break; + + case SSL3_ST_SW_HELLO_REQ_B: + str = "3WHR_B"; + break; + + case SSL3_ST_SW_HELLO_REQ_C: + str = "3WHR_C"; + break; + + case SSL3_ST_SR_CLNT_HELLO_A: + str = "3RCH_A"; + break; + + case SSL3_ST_SR_CLNT_HELLO_B: + str = "3RCH_B"; + break; + + case SSL3_ST_SR_CLNT_HELLO_C: + str = "3RCH_C"; + break; + + case SSL3_ST_SR_CLNT_HELLO_D: + str = "3RCH_D"; + break; + + case SSL3_ST_SW_SRVR_HELLO_A: + str = "3WSH_A"; + break; + + case SSL3_ST_SW_SRVR_HELLO_B: + str = "3WSH_B"; + break; + + case SSL3_ST_SW_CERT_A: + str = "3WSC_A"; + break; + + case SSL3_ST_SW_CERT_B: + str = "3WSC_B"; + break; + + case SSL3_ST_SW_KEY_EXCH_A: + str = "3WSKEA"; + break; + + case SSL3_ST_SW_KEY_EXCH_B: + str = "3WSKEB"; + break; + + case SSL3_ST_SW_CERT_REQ_A: + str = "3WCR_A"; + break; + + case SSL3_ST_SW_CERT_REQ_B: + str = "3WCR_B"; + break; + + case SSL3_ST_SW_SRVR_DONE_A: + str = "3WSD_A"; + break; + + case SSL3_ST_SW_SRVR_DONE_B: + str = "3WSD_B"; + break; + + case SSL3_ST_SR_CERT_A: + str = "3RCC_A"; + break; + + case SSL3_ST_SR_CERT_B: + str = "3RCC_B"; + break; + + case SSL3_ST_SR_KEY_EXCH_A: + str = "3RCKEA"; + break; + + case SSL3_ST_SR_KEY_EXCH_B: + str = "3RCKEB"; + break; + + case SSL3_ST_SR_CERT_VRFY_A: + str = "3RCV_A"; + break; + + case SSL3_ST_SR_CERT_VRFY_B: + str = "3RCV_B"; + break; + + /* SSLv2/v3 compatibility states */ + /* client */ + case SSL23_ST_CW_CLNT_HELLO_A: + str = "23WCHA"; + break; + + case SSL23_ST_CW_CLNT_HELLO_B: + str = "23WCHB"; + break; + + case SSL23_ST_CR_SRVR_HELLO_A: + str = "23RSHA"; + break; + + case SSL23_ST_CR_SRVR_HELLO_B: + str = "23RSHA"; + break; + + /* server */ + case SSL23_ST_SR_CLNT_HELLO: + str = "23RCH_"; + break; + + case SSL23_ST_SR_V2_CLNT_HELLO: + str = "23R2CH"; + break; + + case SSL23_ST_SR_SWITCH_VERSION: + str = "23RSW_"; + break; + + /* DTLS */ + case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A: + str = "DRCHVA"; + break; + + case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B: + str = "DRCHVB"; + break; + + case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A: + str = "DWCHVA"; + break; + + case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B: + str = "DWCHVB"; + break; + + default: + str = "UNKWN "; + break; + } + + return str; +} + +const char *SSL_alert_type_string_long(int value) { + value >>= 8; + if (value == SSL3_AL_WARNING) { + return "warning"; + } else if (value == SSL3_AL_FATAL) { + return "fatal"; + } + + return "unknown"; +} + +const char *SSL_alert_type_string(int value) { + value >>= 8; + if (value == SSL3_AL_WARNING) { + return "W"; + } else if (value == SSL3_AL_FATAL) { + return "F"; + } + + return "U"; +} + +const char *SSL_alert_desc_string(int value) { + const char *str; + + switch (value & 0xff) { + case SSL3_AD_CLOSE_NOTIFY: + str = "CN"; + break; + + case SSL3_AD_UNEXPECTED_MESSAGE: + str = "UM"; + break; + + case SSL3_AD_BAD_RECORD_MAC: + str = "BM"; + break; + + case SSL3_AD_DECOMPRESSION_FAILURE: + str = "DF"; + break; + + case SSL3_AD_HANDSHAKE_FAILURE: + str = "HF"; + break; + + case SSL3_AD_NO_CERTIFICATE: + str = "NC"; + break; + + case SSL3_AD_BAD_CERTIFICATE: + str = "BC"; + break; + + case SSL3_AD_UNSUPPORTED_CERTIFICATE: + str = "UC"; + break; + + case SSL3_AD_CERTIFICATE_REVOKED: + str = "CR"; + break; + + case SSL3_AD_CERTIFICATE_EXPIRED: + str = "CE"; + break; + + case SSL3_AD_CERTIFICATE_UNKNOWN: + str = "CU"; + break; + + case SSL3_AD_ILLEGAL_PARAMETER: + str = "IP"; + break; + + case TLS1_AD_DECRYPTION_FAILED: + str = "DC"; + break; + + case TLS1_AD_RECORD_OVERFLOW: + str = "RO"; + break; + + case TLS1_AD_UNKNOWN_CA: + str = "CA"; + break; + + case TLS1_AD_ACCESS_DENIED: + str = "AD"; + break; + + case TLS1_AD_DECODE_ERROR: + str = "DE"; + break; + + case TLS1_AD_DECRYPT_ERROR: + str = "CY"; + break; + + case TLS1_AD_EXPORT_RESTRICTION: + str = "ER"; + break; + + case TLS1_AD_PROTOCOL_VERSION: + str = "PV"; + break; + + case TLS1_AD_INSUFFICIENT_SECURITY: + str = "IS"; + break; + + case TLS1_AD_INTERNAL_ERROR: + str = "IE"; + break; + + case TLS1_AD_USER_CANCELLED: + str = "US"; + break; + + case TLS1_AD_NO_RENEGOTIATION: + str = "NR"; + break; + + case TLS1_AD_UNSUPPORTED_EXTENSION: + str = "UE"; + break; + + case TLS1_AD_CERTIFICATE_UNOBTAINABLE: + str = "CO"; + break; + + case TLS1_AD_UNRECOGNIZED_NAME: + str = "UN"; + break; + + case TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE: + str = "BR"; + break; + + case TLS1_AD_BAD_CERTIFICATE_HASH_VALUE: + str = "BH"; + break; + + case TLS1_AD_UNKNOWN_PSK_IDENTITY: + str = "UP"; + break; + + default: + str = "UK"; + break; + } + + return str; +} + +const char *SSL_alert_desc_string_long(int value) { + const char *str; + + switch (value & 0xff) { + case SSL3_AD_CLOSE_NOTIFY: + str = "close notify"; + break; + + case SSL3_AD_UNEXPECTED_MESSAGE: + str = "unexpected_message"; + break; + + case SSL3_AD_BAD_RECORD_MAC: + str = "bad record mac"; + break; + + case SSL3_AD_DECOMPRESSION_FAILURE: + str = "decompression failure"; + break; + + case SSL3_AD_HANDSHAKE_FAILURE: + str = "handshake failure"; + break; + + case SSL3_AD_NO_CERTIFICATE: + str = "no certificate"; + break; + + case SSL3_AD_BAD_CERTIFICATE: + str = "bad certificate"; + break; + + case SSL3_AD_UNSUPPORTED_CERTIFICATE: + str = "unsupported certificate"; + break; + + case SSL3_AD_CERTIFICATE_REVOKED: + str = "certificate revoked"; + break; + + case SSL3_AD_CERTIFICATE_EXPIRED: + str = "certificate expired"; + break; + + case SSL3_AD_CERTIFICATE_UNKNOWN: + str = "certificate unknown"; + break; + + case SSL3_AD_ILLEGAL_PARAMETER: + str = "illegal parameter"; + break; + + case TLS1_AD_DECRYPTION_FAILED: + str = "decryption failed"; + break; + + case TLS1_AD_RECORD_OVERFLOW: + str = "record overflow"; + break; + + case TLS1_AD_UNKNOWN_CA: + str = "unknown CA"; + break; + + case TLS1_AD_ACCESS_DENIED: + str = "access denied"; + break; + + case TLS1_AD_DECODE_ERROR: + str = "decode error"; + break; + + case TLS1_AD_DECRYPT_ERROR: + str = "decrypt error"; + break; + + case TLS1_AD_EXPORT_RESTRICTION: + str = "export restriction"; + break; + + case TLS1_AD_PROTOCOL_VERSION: + str = "protocol version"; + break; + + case TLS1_AD_INSUFFICIENT_SECURITY: + str = "insufficient security"; + break; + + case TLS1_AD_INTERNAL_ERROR: + str = "internal error"; + break; + + case TLS1_AD_USER_CANCELLED: + str = "user canceled"; + break; + + case TLS1_AD_NO_RENEGOTIATION: + str = "no renegotiation"; + break; + + case TLS1_AD_UNSUPPORTED_EXTENSION: + str = "unsupported extension"; + break; + + case TLS1_AD_CERTIFICATE_UNOBTAINABLE: + str = "certificate unobtainable"; + break; + + case TLS1_AD_UNRECOGNIZED_NAME: + str = "unrecognized name"; + break; + + case TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE: + str = "bad certificate status response"; + break; + + case TLS1_AD_BAD_CERTIFICATE_HASH_VALUE: + str = "bad certificate hash value"; + break; + + case TLS1_AD_UNKNOWN_PSK_IDENTITY: + str = "unknown PSK identity"; + break; + + default: + str = "unknown"; + break; + } + + return str; +} + +const char *SSL_rstate_string(const SSL *s) { + const char *str; + + switch (s->rstate) { + case SSL_ST_READ_HEADER: + str = "RH"; + break; + + case SSL_ST_READ_BODY: + str = "RB"; + break; + + case SSL_ST_READ_DONE: + str = "RD"; + break; + + default: + str = "unknown"; + break; + } + + return str; +}
diff --git a/ssl/ssl_txt.c b/ssl/ssl_txt.c index b91324e..50da0a6 100644 --- a/ssl/ssl_txt.c +++ b/ssl/ssl_txt.c
@@ -89,102 +89,130 @@ #include "ssl_locl.h" -int SSL_SESSION_print_fp(FILE *fp, const SSL_SESSION *x) - { - BIO *b; - int ret; - if ((b=BIO_new(BIO_s_file())) == NULL) - { - OPENSSL_PUT_ERROR(SSL, SSL_SESSION_print_fp, ERR_R_BUF_LIB); - return(0); - } - BIO_set_fp(b,fp,BIO_NOCLOSE); - ret=SSL_SESSION_print(b,x); - BIO_free(b); - return(ret); - } +int SSL_SESSION_print_fp(FILE *fp, const SSL_SESSION *x) { + BIO *b; + int ret; -int SSL_SESSION_print(BIO *bp, const SSL_SESSION *x) - { - unsigned int i; - const char *s; + b = BIO_new(BIO_s_file()); + if (b == NULL) { + OPENSSL_PUT_ERROR(SSL, SSL_SESSION_print_fp, ERR_R_BUF_LIB); + return 0; + } - if (x == NULL) goto err; - if (BIO_puts(bp,"SSL-Session:\n") <= 0) goto err; - if (x->ssl_version == SSL3_VERSION) - s="SSLv3"; - else if (x->ssl_version == TLS1_2_VERSION) - s="TLSv1.2"; - else if (x->ssl_version == TLS1_1_VERSION) - s="TLSv1.1"; - else if (x->ssl_version == TLS1_VERSION) - s="TLSv1"; - else if (x->ssl_version == DTLS1_VERSION) - s="DTLSv1"; - else if (x->ssl_version == DTLS1_2_VERSION) - s="DTLSv1.2"; - else - s="unknown"; - if (BIO_printf(bp," Protocol : %s\n",s) <= 0) goto err; + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = SSL_SESSION_print(b, x); + BIO_free(b); + return ret; +} - if (x->cipher == NULL) - { - if (BIO_printf(bp," Cipher : %06lX\n",x->cipher_id&0xffffff) <= 0) - goto err; - } - else - { - if (BIO_printf(bp," Cipher : %s\n",((x->cipher == NULL)?"unknown":x->cipher->name)) <= 0) - goto err; - } - if (BIO_puts(bp," Session-ID: ") <= 0) goto err; - for (i=0; i<x->session_id_length; i++) - { - if (BIO_printf(bp,"%02X",x->session_id[i]) <= 0) goto err; - } - if (BIO_puts(bp,"\n Session-ID-ctx: ") <= 0) goto err; - for (i=0; i<x->sid_ctx_length; i++) - { - if (BIO_printf(bp,"%02X",x->sid_ctx[i]) <= 0) - goto err; - } - if (BIO_puts(bp,"\n Master-Key: ") <= 0) goto err; - for (i=0; i<(unsigned int)x->master_key_length; i++) - { - if (BIO_printf(bp,"%02X",x->master_key[i]) <= 0) goto err; - } - if (BIO_puts(bp,"\n PSK identity: ") <= 0) goto err; - if (BIO_printf(bp, "%s", x->psk_identity ? x->psk_identity : "None") <= 0) goto err; - if (x->tlsext_tick_lifetime_hint) - { - if (BIO_printf(bp, - "\n TLS session ticket lifetime hint: %" PRIu32 " (seconds)", - x->tlsext_tick_lifetime_hint) <=0) - goto err; - } - if (x->tlsext_tick) - { - if (BIO_puts(bp, "\n TLS session ticket:\n") <= 0) goto err; - if (BIO_hexdump(bp, x->tlsext_tick, x->tlsext_ticklen, 4) <= 0) - goto err; - } +int SSL_SESSION_print(BIO *bp, const SSL_SESSION *x) { + unsigned int i; + const char *s; - if (x->time != 0L) - { - if (BIO_printf(bp, "\n Start Time: %ld",x->time) <= 0) goto err; - } - if (x->timeout != 0L) - { - if (BIO_printf(bp, "\n Timeout : %ld (sec)",x->timeout) <= 0) goto err; - } - if (BIO_puts(bp,"\n") <= 0) goto err; + if (x == NULL || + BIO_puts(bp, "SSL-Session:\n") <= 0) { + goto err; + } - if (BIO_puts(bp, " Verify return code: ") <= 0) goto err; - if (BIO_printf(bp, "%ld (%s)\n", x->verify_result, - X509_verify_cert_error_string(x->verify_result)) <= 0) goto err; - - return(1); + if (x->ssl_version == SSL3_VERSION) { + s = "SSLv3"; + } else if (x->ssl_version == TLS1_2_VERSION) { + s = "TLSv1.2"; + } else if (x->ssl_version == TLS1_1_VERSION) { + s = "TLSv1.1"; + } else if (x->ssl_version == TLS1_VERSION) { + s = "TLSv1"; + } else if (x->ssl_version == DTLS1_VERSION) { + s = "DTLSv1"; + } else if (x->ssl_version == DTLS1_2_VERSION) { + s = "DTLSv1.2"; + } else { + s = "unknown"; + } + + if (BIO_printf(bp, " Protocol : %s\n", s) <= 0) { + goto err; + } + + if (x->cipher == NULL) { + if (BIO_printf(bp, " Cipher : %06lX\n", x->cipher_id & 0xffffff) <= + 0) { + goto err; + } + } else { + if (BIO_printf(bp, " Cipher : %s\n", + ((x->cipher == NULL) ? "unknown" : x->cipher->name)) <= 0) { + goto err; + } + } + + if (BIO_puts(bp, " Session-ID: ") <= 0) { + goto err; + } + + for (i = 0; i < x->session_id_length; i++) { + if (BIO_printf(bp, "%02X", x->session_id[i]) <= 0) + goto err; + } + + if (BIO_puts(bp, "\n Session-ID-ctx: ") <= 0) { + goto err; + } + + for (i = 0; i < x->sid_ctx_length; i++) { + if (BIO_printf(bp, "%02X", x->sid_ctx[i]) <= 0) { + goto err; + } + } + + if (BIO_puts(bp, "\n Master-Key: ") <= 0) { + goto err; + } + + for (i = 0; i < (unsigned int)x->master_key_length; i++) { + if (BIO_printf(bp, "%02X", x->master_key[i]) <= 0) { + goto err; + } + } + + if (BIO_puts(bp, "\n PSK identity: ") <= 0 || + BIO_printf(bp, "%s", x->psk_identity ? x->psk_identity : "None") <= 0) { + goto err; + } + + if (x->tlsext_tick_lifetime_hint && + BIO_printf(bp, "\n TLS session ticket lifetime hint: %" PRIu32 + " (seconds)", + x->tlsext_tick_lifetime_hint) <= 0) { + goto err; + } + + if (x->tlsext_tick) { + if (BIO_puts(bp, "\n TLS session ticket:\n") <= 0 || + BIO_hexdump(bp, x->tlsext_tick, x->tlsext_ticklen, 4) <= 0) { + goto err; + } + } + + if (x->time != 0L && BIO_printf(bp, "\n Start Time: %ld", x->time) <= 0) { + goto err; + } + + if (x->timeout != 0L && + BIO_printf(bp, "\n Timeout : %ld (sec)", x->timeout) <= 0) { + goto err; + } + + if (BIO_puts(bp, "\n") <= 0 || + BIO_puts(bp, " Verify return code: ") <= 0 || + BIO_printf(bp, "%ld (%s)\n", x->verify_result, + X509_verify_cert_error_string(x->verify_result)) <= 0) { + goto err; + } + + return 1; + err: - return(0); - } + return 0; +}
diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c index 28405b7..669f736 100644 --- a/ssl/t1_enc.c +++ b/ssl/t1_enc.c
@@ -146,276 +146,259 @@ #include "ssl_locl.h" -/* seed1 through seed5 are virtually concatenated */ -static int tls1_P_hash(const EVP_MD *md, const unsigned char *sec, - int sec_len, - const void *seed1, int seed1_len, - const void *seed2, int seed2_len, - const void *seed3, int seed3_len, - unsigned char *out, int olen) - { - int chunk; - size_t j; - EVP_MD_CTX ctx, ctx_tmp, ctx_init; - EVP_PKEY *mac_key; - unsigned char A1[EVP_MAX_MD_SIZE]; - size_t A1_len; - int ret = 0; - - chunk=EVP_MD_size(md); - EVP_MD_CTX_init(&ctx); - EVP_MD_CTX_init(&ctx_tmp); - EVP_MD_CTX_init(&ctx_init); - mac_key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, sec, sec_len); - if (!mac_key) - goto err; - if (!EVP_DigestSignInit(&ctx_init,NULL,md, NULL, mac_key)) - goto err; - if (!EVP_MD_CTX_copy_ex(&ctx,&ctx_init)) - goto err; - if (seed1 && !EVP_DigestSignUpdate(&ctx,seed1,seed1_len)) - goto err; - if (seed2 && !EVP_DigestSignUpdate(&ctx,seed2,seed2_len)) - goto err; - if (seed3 && !EVP_DigestSignUpdate(&ctx,seed3,seed3_len)) - goto err; - A1_len = EVP_MAX_MD_SIZE; - if (!EVP_DigestSignFinal(&ctx,A1,&A1_len)) - goto err; +/* seed1 through seed3 are virtually concatenated */ +static int tls1_P_hash(const EVP_MD *md, const uint8_t *sec, int sec_len, + const void *seed1, int seed1_len, + const void *seed2, int seed2_len, + const void *seed3, int seed3_len, + uint8_t *out, int olen) { + int chunk; + size_t j; + EVP_MD_CTX ctx, ctx_tmp, ctx_init; + EVP_PKEY *mac_key; + uint8_t A1[EVP_MAX_MD_SIZE]; + size_t A1_len; + int ret = 0; - for (;;) - { - /* Reinit mac contexts */ - if (!EVP_MD_CTX_copy_ex(&ctx,&ctx_init)) - goto err; - if (!EVP_DigestSignUpdate(&ctx,A1,A1_len)) - goto err; - if (olen>chunk && !EVP_MD_CTX_copy_ex(&ctx_tmp,&ctx)) - goto err; - if (seed1 && !EVP_DigestSignUpdate(&ctx,seed1,seed1_len)) - goto err; - if (seed2 && !EVP_DigestSignUpdate(&ctx,seed2,seed2_len)) - goto err; - if (seed3 && !EVP_DigestSignUpdate(&ctx,seed3,seed3_len)) - goto err; + chunk = EVP_MD_size(md); - if (olen > chunk) - { - j = olen; - if (!EVP_DigestSignFinal(&ctx,out,&j)) - goto err; - out+=j; - olen-=j; - /* calc the next A1 value */ - A1_len = EVP_MAX_MD_SIZE; - if (!EVP_DigestSignFinal(&ctx_tmp,A1,&A1_len)) - goto err; - } - else /* last one */ - { - A1_len = EVP_MAX_MD_SIZE; - if (!EVP_DigestSignFinal(&ctx,A1,&A1_len)) - goto err; - memcpy(out,A1,olen); - break; - } - } - ret = 1; + EVP_MD_CTX_init(&ctx); + EVP_MD_CTX_init(&ctx_tmp); + EVP_MD_CTX_init(&ctx_init); + mac_key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, sec, sec_len); + A1_len = EVP_MAX_MD_SIZE; + if (!mac_key || + !EVP_DigestSignInit(&ctx_init, NULL, md, NULL, mac_key) || + !EVP_MD_CTX_copy_ex(&ctx, &ctx_init) || + (seed1 && !EVP_DigestSignUpdate(&ctx, seed1, seed1_len)) || + (seed2 && !EVP_DigestSignUpdate(&ctx, seed2, seed2_len)) || + (seed3 && !EVP_DigestSignUpdate(&ctx, seed3, seed3_len)) || + !EVP_DigestSignFinal(&ctx, A1, &A1_len)) { + goto err; + } + + for (;;) { + /* Reinit mac contexts */ + if (!EVP_MD_CTX_copy_ex(&ctx, &ctx_init) || + !EVP_DigestSignUpdate(&ctx, A1, A1_len) || + (olen > chunk && !EVP_MD_CTX_copy_ex(&ctx_tmp, &ctx)) || + (seed1 && !EVP_DigestSignUpdate(&ctx, seed1, seed1_len)) || + (seed2 && !EVP_DigestSignUpdate(&ctx, seed2, seed2_len)) || + (seed3 && !EVP_DigestSignUpdate(&ctx, seed3, seed3_len))) { + goto err; + } + + if (olen > chunk) { + j = olen; + if (!EVP_DigestSignFinal(&ctx, out, &j)) { + goto err; + } + out += j; + olen -= j; + /* calc the next A1 value */ + A1_len = EVP_MAX_MD_SIZE; + if (!EVP_DigestSignFinal(&ctx_tmp, A1, &A1_len)) { + goto err; + } + } else { + /* last one */ + A1_len = EVP_MAX_MD_SIZE; + if (!EVP_DigestSignFinal(&ctx, A1, &A1_len)) { + goto err; + } + memcpy(out, A1, olen); + break; + } + } + + ret = 1; + err: - EVP_PKEY_free(mac_key); - EVP_MD_CTX_cleanup(&ctx); - EVP_MD_CTX_cleanup(&ctx_tmp); - EVP_MD_CTX_cleanup(&ctx_init); - OPENSSL_cleanse(A1,sizeof(A1)); - return ret; - } - -/* seed1 through seed5 are virtually concatenated */ -static int tls1_PRF(long digest_mask, - const void *seed1, int seed1_len, - const void *seed2, int seed2_len, - const void *seed3, int seed3_len, - const unsigned char *sec, int slen, - unsigned char *out1, - unsigned char *out2, int olen) - { - int len,i,idx,count; - const unsigned char *S1; - long m; - const EVP_MD *md; - int ret = 0; - - /* Count number of digests and partition sec evenly */ - count=0; - for (idx=0;ssl_get_handshake_digest(idx,&m,&md);idx++) { - if ((m<<TLS1_PRF_DGST_SHIFT) & digest_mask) count++; - } - len=slen/count; - if (count == 1) - slen = 0; - S1=sec; - memset(out1,0,olen); - for (idx=0;ssl_get_handshake_digest(idx,&m,&md);idx++) { - if ((m<<TLS1_PRF_DGST_SHIFT) & digest_mask) { - if (!md) { - OPENSSL_PUT_ERROR(SSL, tls1_PRF, SSL_R_UNSUPPORTED_DIGEST_TYPE); - goto err; - } - if (!tls1_P_hash(md ,S1,len+(slen&1), - seed1,seed1_len,seed2,seed2_len,seed3,seed3_len, - out2,olen)) - goto err; - S1+=len; - for (i=0; i<olen; i++) - { - out1[i]^=out2[i]; - } - } - } - ret = 1; -err: - return ret; + EVP_PKEY_free(mac_key); + EVP_MD_CTX_cleanup(&ctx); + EVP_MD_CTX_cleanup(&ctx_tmp); + EVP_MD_CTX_cleanup(&ctx_init); + OPENSSL_cleanse(A1, sizeof(A1)); + return ret; } -static int tls1_generate_key_block(SSL *s, unsigned char *km, - unsigned char *tmp, int num) - { - int ret; - ret = tls1_PRF(ssl_get_algorithm2(s), - TLS_MD_KEY_EXPANSION_CONST,TLS_MD_KEY_EXPANSION_CONST_SIZE, - s->s3->server_random,SSL3_RANDOM_SIZE, - s->s3->client_random,SSL3_RANDOM_SIZE, - s->session->master_key,s->session->master_key_length, - km,tmp,num); - return ret; - } +/* seed1 through seed3 are virtually concatenated */ +static int tls1_PRF(long digest_mask, + const void *seed1, int seed1_len, + const void *seed2, int seed2_len, + const void *seed3, int seed3_len, + const uint8_t *sec, int slen, + uint8_t *out1, uint8_t *out2, int olen) { + int len, i, idx, count; + const uint8_t *S1; + long m; + const EVP_MD *md; + int ret = 0; + + /* Count number of digests and partition sec evenly */ + count = 0; + for (idx = 0; ssl_get_handshake_digest(idx, &m, &md); idx++) { + if ((m << TLS1_PRF_DGST_SHIFT) & digest_mask) { + count++; + } + } + len = slen / count; + if (count == 1) { + slen = 0; + } + S1 = sec; + memset(out1, 0, olen); + for (idx = 0; ssl_get_handshake_digest(idx, &m, &md); idx++) { + if ((m << TLS1_PRF_DGST_SHIFT) & digest_mask) { + if (!md) { + OPENSSL_PUT_ERROR(SSL, tls1_PRF, SSL_R_UNSUPPORTED_DIGEST_TYPE); + goto err; + } + if (!tls1_P_hash(md, S1, len + (slen & 1), seed1, seed1_len, seed2, + seed2_len, seed3, seed3_len, out2, olen)) { + goto err; + } + S1 += len; + for (i = 0; i < olen; i++) { + out1[i] ^= out2[i]; + } + } + } + ret = 1; + +err: + return ret; +} + +static int tls1_generate_key_block(SSL *s, uint8_t *km, uint8_t *tmp, int num) { + return tls1_PRF(ssl_get_algorithm2(s), TLS_MD_KEY_EXPANSION_CONST, + TLS_MD_KEY_EXPANSION_CONST_SIZE, s->s3->server_random, + SSL3_RANDOM_SIZE, s->s3->client_random, SSL3_RANDOM_SIZE, + s->session->master_key, s->session->master_key_length, km, + tmp, num); +} /* tls1_aead_ctx_init allocates |*aead_ctx|, if needed and returns 1. It * returns 0 on malloc error. */ -static int tls1_aead_ctx_init(SSL_AEAD_CTX **aead_ctx) - { - if (*aead_ctx != NULL) - EVP_AEAD_CTX_cleanup(&(*aead_ctx)->ctx); - else - { - *aead_ctx = (SSL_AEAD_CTX*) OPENSSL_malloc(sizeof(SSL_AEAD_CTX)); - if (*aead_ctx == NULL) - { - OPENSSL_PUT_ERROR(SSL, tls1_aead_ctx_init, ERR_R_MALLOC_FAILURE); - return 0; - } - } +static int tls1_aead_ctx_init(SSL_AEAD_CTX **aead_ctx) { + if (*aead_ctx != NULL) { + EVP_AEAD_CTX_cleanup(&(*aead_ctx)->ctx); + } else { + *aead_ctx = (SSL_AEAD_CTX *)OPENSSL_malloc(sizeof(SSL_AEAD_CTX)); + if (*aead_ctx == NULL) { + OPENSSL_PUT_ERROR(SSL, tls1_aead_ctx_init, ERR_R_MALLOC_FAILURE); + return 0; + } + } - return 1; - } + return 1; +} -static void tls1_cleanup_enc_ctx(EVP_CIPHER_CTX **ctx) - { - if (*ctx != NULL) - EVP_CIPHER_CTX_free(*ctx); - *ctx = NULL; - } +static void tls1_cleanup_enc_ctx(EVP_CIPHER_CTX **ctx) { + if (*ctx != NULL) { + EVP_CIPHER_CTX_free(*ctx); + } + *ctx = NULL; +} -static void tls1_cleanup_hash_ctx(EVP_MD_CTX **ctx) - { - if (*ctx != NULL) - EVP_MD_CTX_destroy(*ctx); - *ctx = NULL; - } +static void tls1_cleanup_hash_ctx(EVP_MD_CTX **ctx) { + if (*ctx != NULL) { + EVP_MD_CTX_destroy(*ctx); + } + *ctx = NULL; +} static int tls1_change_cipher_state_aead(SSL *s, char is_read, - const unsigned char *key, unsigned key_len, - const unsigned char *iv, unsigned iv_len, - const unsigned char *mac_secret, unsigned mac_secret_len) - { - const EVP_AEAD *aead = s->s3->tmp.new_aead; - SSL_AEAD_CTX *aead_ctx; - /* mac_key_and_key is used to merge the MAC and cipher keys for an AEAD - * which simulates pre-AEAD cipher suites. It needs to be large enough - * to cope with the largest pair of keys. */ - uint8_t mac_key_and_key[32 /* HMAC(SHA256) */ + 32 /* AES-256 */]; + const uint8_t *key, unsigned key_len, + const uint8_t *iv, unsigned iv_len, + const uint8_t *mac_secret, + unsigned mac_secret_len) { + const EVP_AEAD *aead = s->s3->tmp.new_aead; + SSL_AEAD_CTX *aead_ctx; + /* mac_key_and_key is used to merge the MAC and cipher keys for an AEAD which + * simulates pre-AEAD cipher suites. It needs to be large enough to cope with + * the largest pair of keys. */ + uint8_t mac_key_and_key[32 /* HMAC(SHA256) */ + 32 /* AES-256 */]; - if (is_read) - { - tls1_cleanup_enc_ctx(&s->enc_read_ctx); - tls1_cleanup_hash_ctx(&s->read_hash); - } - else - { - tls1_cleanup_enc_ctx(&s->enc_write_ctx); - tls1_cleanup_hash_ctx(&s->write_hash); - } + if (is_read) { + tls1_cleanup_enc_ctx(&s->enc_read_ctx); + tls1_cleanup_hash_ctx(&s->read_hash); + } else { + tls1_cleanup_enc_ctx(&s->enc_write_ctx); + tls1_cleanup_hash_ctx(&s->write_hash); + } - if (mac_secret_len > 0) - { - /* This is a "stateful" AEAD (for compatibility with pre-AEAD - * cipher suites). */ - if (mac_secret_len + key_len > sizeof(mac_key_and_key)) - { - OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_aead, ERR_R_INTERNAL_ERROR); - return 0; - } - memcpy(mac_key_and_key, mac_secret, mac_secret_len); - memcpy(mac_key_and_key + mac_secret_len, key, key_len); - key = mac_key_and_key; - key_len += mac_secret_len; - } + if (mac_secret_len > 0) { + /* This is a "stateful" AEAD (for compatibility with pre-AEAD cipher + * suites). */ + if (mac_secret_len + key_len > sizeof(mac_key_and_key)) { + OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_aead, + ERR_R_INTERNAL_ERROR); + return 0; + } + memcpy(mac_key_and_key, mac_secret, mac_secret_len); + memcpy(mac_key_and_key + mac_secret_len, key, key_len); + key = mac_key_and_key; + key_len += mac_secret_len; + } - if (is_read) - { - if (!tls1_aead_ctx_init(&s->aead_read_ctx)) - return 0; - aead_ctx = s->aead_read_ctx; - } - else - { - if (!tls1_aead_ctx_init(&s->aead_write_ctx)) - return 0; - aead_ctx = s->aead_write_ctx; - } + if (is_read) { + if (!tls1_aead_ctx_init(&s->aead_read_ctx)) { + return 0; + } + aead_ctx = s->aead_read_ctx; + } else { + if (!tls1_aead_ctx_init(&s->aead_write_ctx)) { + return 0; + } + aead_ctx = s->aead_write_ctx; + } - if (!EVP_AEAD_CTX_init(&aead_ctx->ctx, aead, key, key_len, - EVP_AEAD_DEFAULT_TAG_LENGTH, NULL /* engine */)) - { - OPENSSL_free(aead_ctx); - if (is_read) - s->aead_read_ctx = NULL; - else - s->aead_write_ctx = NULL; - return 0; - } - if (iv_len > sizeof(aead_ctx->fixed_nonce)) - { - OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_aead, ERR_R_INTERNAL_ERROR); - return 0; - } - memcpy(aead_ctx->fixed_nonce, iv, iv_len); - aead_ctx->fixed_nonce_len = iv_len; - aead_ctx->variable_nonce_len = 8; /* correct for all true AEADs so far. */ - if (s->s3->tmp.new_cipher->algorithm2 & SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD) - aead_ctx->variable_nonce_len = 0; - aead_ctx->variable_nonce_included_in_record = - (s->s3->tmp.new_cipher->algorithm2 & SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD) != 0; - if (aead_ctx->variable_nonce_len + aead_ctx->fixed_nonce_len != EVP_AEAD_nonce_length(aead)) - { - OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_aead, ERR_R_INTERNAL_ERROR); - return 0; - } - aead_ctx->tag_len = EVP_AEAD_max_overhead(aead); + if (!EVP_AEAD_CTX_init(&aead_ctx->ctx, aead, key, key_len, + EVP_AEAD_DEFAULT_TAG_LENGTH, NULL /* engine */)) { + OPENSSL_free(aead_ctx); + if (is_read) { + s->aead_read_ctx = NULL; + } else { + s->aead_write_ctx = NULL; + } - return 1; - } + return 0; + } -static void tls1_cleanup_aead_ctx(SSL_AEAD_CTX **ctx) - { - if (*ctx != NULL) - { - EVP_AEAD_CTX_cleanup(&(*ctx)->ctx); - OPENSSL_free(*ctx); - } - *ctx = NULL; - } + if (iv_len > sizeof(aead_ctx->fixed_nonce)) { + OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_aead, ERR_R_INTERNAL_ERROR); + return 0; + } + + memcpy(aead_ctx->fixed_nonce, iv, iv_len); + aead_ctx->fixed_nonce_len = iv_len; + aead_ctx->variable_nonce_len = 8; /* correct for all true AEADs so far. */ + if (s->s3->tmp.new_cipher->algorithm2 & SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD) { + aead_ctx->variable_nonce_len = 0; + } + + aead_ctx->variable_nonce_included_in_record = + (s->s3->tmp.new_cipher->algorithm2 & + SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD) != 0; + if (aead_ctx->variable_nonce_len + aead_ctx->fixed_nonce_len != + EVP_AEAD_nonce_length(aead)) { + OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_aead, ERR_R_INTERNAL_ERROR); + return 0; + } + aead_ctx->tag_len = EVP_AEAD_max_overhead(aead); + + return 1; +} + +static void tls1_cleanup_aead_ctx(SSL_AEAD_CTX **ctx) { + if (*ctx != NULL) { + EVP_AEAD_CTX_cleanup(&(*ctx)->ctx); + OPENSSL_free(*ctx); + } + *ctx = NULL; +} /* tls1_change_cipher_state_cipher performs the work needed to switch cipher * states when using EVP_CIPHER. The argument |is_read| is true iff this @@ -423,941 +406,913 @@ * ChangeCipherSpec message. In order to support export ciphersuites, * use_client_keys indicates whether the key material provided is in the * "client write" direction. */ -static int tls1_change_cipher_state_cipher( - SSL *s, char is_read, char use_client_keys, - const unsigned char *mac_secret, unsigned mac_secret_len, - const unsigned char *key, unsigned key_len, - const unsigned char *iv, unsigned iv_len) - { - const EVP_CIPHER *cipher = s->s3->tmp.new_sym_enc; - EVP_CIPHER_CTX *cipher_ctx; - EVP_MD_CTX *mac_ctx; +static int tls1_change_cipher_state_cipher(SSL *s, char is_read, + char use_client_keys, + const uint8_t *mac_secret, + unsigned mac_secret_len, + const uint8_t *key, unsigned key_len, + const uint8_t *iv, unsigned iv_len) { + const EVP_CIPHER *cipher = s->s3->tmp.new_sym_enc; + EVP_CIPHER_CTX *cipher_ctx; + EVP_MD_CTX *mac_ctx; - if (is_read) - tls1_cleanup_aead_ctx(&s->aead_read_ctx); - else - tls1_cleanup_aead_ctx(&s->aead_write_ctx); + if (is_read) { + tls1_cleanup_aead_ctx(&s->aead_read_ctx); + } else { + tls1_cleanup_aead_ctx(&s->aead_write_ctx); + } - if (is_read) - { - if (s->enc_read_ctx != NULL && !SSL_IS_DTLS(s)) - EVP_CIPHER_CTX_cleanup(s->enc_read_ctx); - else if ((s->enc_read_ctx=EVP_CIPHER_CTX_new()) == NULL) - goto err; + if (is_read) { + if (s->enc_read_ctx != NULL && !SSL_IS_DTLS(s)) { + EVP_CIPHER_CTX_cleanup(s->enc_read_ctx); + } else if ((s->enc_read_ctx = EVP_CIPHER_CTX_new()) == NULL) { + goto err; + } - cipher_ctx = s->enc_read_ctx; - mac_ctx = ssl_replace_hash(&s->read_hash, NULL); - if (mac_ctx == NULL) - goto err; + cipher_ctx = s->enc_read_ctx; + mac_ctx = ssl_replace_hash(&s->read_hash, NULL); + if (mac_ctx == NULL) { + goto err; + } - memcpy(s->s3->read_mac_secret, mac_secret, mac_secret_len); - s->s3->read_mac_secret_size = mac_secret_len; - } - else - { - /* When updating the write contexts for DTLS, we do not wish to - * free the old ones because DTLS stores pointers to them in - * order to implement retransmission. */ + memcpy(s->s3->read_mac_secret, mac_secret, mac_secret_len); + s->s3->read_mac_secret_size = mac_secret_len; + } else { + /* When updating the write contexts for DTLS, we do not wish to free the + * old ones because DTLS stores pointers to them in order to implement + * retransmission. */ - if (s->enc_write_ctx != NULL && !SSL_IS_DTLS(s)) - EVP_CIPHER_CTX_cleanup(s->enc_write_ctx); - else if ((s->enc_write_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL) - goto err; - else - /* make sure it's intialized in case we exit later with an error */ - EVP_CIPHER_CTX_init(s->enc_write_ctx); + if (s->enc_write_ctx != NULL && !SSL_IS_DTLS(s)) { + EVP_CIPHER_CTX_cleanup(s->enc_write_ctx); + } else { + s->enc_write_ctx = OPENSSL_malloc(sizeof(EVP_CIPHER_CTX)); + if (s->enc_write_ctx == NULL) { + goto err; + } + } + EVP_CIPHER_CTX_init(s->enc_write_ctx); - cipher_ctx = s->enc_write_ctx; - if (SSL_IS_DTLS(s)) - { - /* This is the same as ssl_replace_hash, but doesn't - * free the old |s->write_hash|. */ - mac_ctx = EVP_MD_CTX_create(); - if (!mac_ctx) - goto err; - s->write_hash = mac_ctx; - } - else - { - mac_ctx = ssl_replace_hash(&s->write_hash, NULL); - if (mac_ctx == NULL) - goto err; - } + cipher_ctx = s->enc_write_ctx; + if (SSL_IS_DTLS(s)) { + /* This is the same as ssl_replace_hash, but doesn't + * free the old |s->write_hash|. */ + mac_ctx = EVP_MD_CTX_create(); + if (!mac_ctx) { + goto err; + } + s->write_hash = mac_ctx; + } else { + mac_ctx = ssl_replace_hash(&s->write_hash, NULL); + if (mac_ctx == NULL) { + goto err; + } + } - memcpy(s->s3->write_mac_secret, mac_secret, mac_secret_len); - s->s3->write_mac_secret_size = mac_secret_len; - } + memcpy(s->s3->write_mac_secret, mac_secret, mac_secret_len); + s->s3->write_mac_secret_size = mac_secret_len; + } - EVP_PKEY *mac_key = - EVP_PKEY_new_mac_key(s->s3->tmp.new_mac_pkey_type, - NULL, mac_secret, mac_secret_len); - if (!mac_key) - return 0; - if (!EVP_DigestSignInit(mac_ctx, NULL, s->s3->tmp.new_hash, NULL, mac_key)) - { - EVP_PKEY_free(mac_key); - goto err; - } - EVP_PKEY_free(mac_key); + EVP_PKEY *mac_key = EVP_PKEY_new_mac_key(s->s3->tmp.new_mac_pkey_type, NULL, + mac_secret, mac_secret_len); + if (!mac_key) { + return 0; + } - if (!EVP_CipherInit_ex(cipher_ctx, cipher, NULL /* engine */, key, iv, !is_read)) - goto err; + if (!EVP_DigestSignInit(mac_ctx, NULL, s->s3->tmp.new_hash, NULL, mac_key)) { + EVP_PKEY_free(mac_key); + goto err; + } + EVP_PKEY_free(mac_key); - return 1; + if (!EVP_CipherInit_ex(cipher_ctx, cipher, NULL /* engine */, key, iv, + !is_read)) { + goto err; + } + + return 1; err: - OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_cipher, ERR_R_MALLOC_FAILURE); - return 0; - } + OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_cipher, ERR_R_MALLOC_FAILURE); + return 0; +} -int tls1_change_cipher_state(SSL *s, int which) - { - /* is_read is true if we have just read a ChangeCipherSpec message - - * i.e. we need to update the read cipherspec. Otherwise we have just - * written one. */ - const char is_read = (which & SSL3_CC_READ) != 0; - /* use_client_keys is true if we wish to use the keys for the "client - * write" direction. This is the case if we're a client sending a - * ChangeCipherSpec, or a server reading a client's ChangeCipherSpec. */ - const char use_client_keys = which == SSL3_CHANGE_CIPHER_CLIENT_WRITE || - which == SSL3_CHANGE_CIPHER_SERVER_READ; - const unsigned char *client_write_mac_secret, *server_write_mac_secret, *mac_secret; - const unsigned char *client_write_key, *server_write_key, *key; - const unsigned char *client_write_iv, *server_write_iv, *iv; - const EVP_CIPHER *cipher = s->s3->tmp.new_sym_enc; - const EVP_AEAD *aead = s->s3->tmp.new_aead; - unsigned key_len, iv_len, mac_secret_len; - const unsigned char *key_data; +int tls1_change_cipher_state(SSL *s, int which) { + /* is_read is true if we have just read a ChangeCipherSpec message - i.e. we + * need to update the read cipherspec. Otherwise we have just written one. */ + const char is_read = (which & SSL3_CC_READ) != 0; + /* use_client_keys is true if we wish to use the keys for the "client write" + * direction. This is the case if we're a client sending a ChangeCipherSpec, + * or a server reading a client's ChangeCipherSpec. */ + const char use_client_keys = which == SSL3_CHANGE_CIPHER_CLIENT_WRITE || + which == SSL3_CHANGE_CIPHER_SERVER_READ; + const uint8_t *client_write_mac_secret, *server_write_mac_secret, *mac_secret; + const uint8_t *client_write_key, *server_write_key, *key; + const uint8_t *client_write_iv, *server_write_iv, *iv; + const EVP_CIPHER *cipher = s->s3->tmp.new_sym_enc; + const EVP_AEAD *aead = s->s3->tmp.new_aead; + unsigned key_len, iv_len, mac_secret_len; + const uint8_t *key_data; - /* Reset sequence number to zero. */ - if (!SSL_IS_DTLS(s)) - memset(is_read ? s->s3->read_sequence : s->s3->write_sequence, 0, 8); + /* Reset sequence number to zero. */ + if (!SSL_IS_DTLS(s)) { + memset(is_read ? s->s3->read_sequence : s->s3->write_sequence, 0, 8); + } - mac_secret_len = s->s3->tmp.new_mac_secret_size; + mac_secret_len = s->s3->tmp.new_mac_secret_size; - if (aead != NULL) - { - key_len = EVP_AEAD_key_length(aead); - /* For "stateful" AEADs (i.e. compatibility with pre-AEAD - * cipher suites) the key length reported by - * |EVP_AEAD_key_length| will include the MAC key bytes. */ - if (key_len < mac_secret_len) - { - OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state, ERR_R_INTERNAL_ERROR); - return 0; - } - key_len -= mac_secret_len; - iv_len = SSL_CIPHER_AEAD_FIXED_NONCE_LEN(s->s3->tmp.new_cipher); - } - else - { - key_len = EVP_CIPHER_key_length(cipher); - iv_len = EVP_CIPHER_iv_length(cipher); - } + if (aead != NULL) { + key_len = EVP_AEAD_key_length(aead); + /* For "stateful" AEADs (i.e. compatibility with pre-AEAD cipher suites) + * the key length reported by |EVP_AEAD_key_length| will include the MAC + * key bytes. */ + if (key_len < mac_secret_len) { + OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state, ERR_R_INTERNAL_ERROR); + return 0; + } + key_len -= mac_secret_len; + iv_len = SSL_CIPHER_AEAD_FIXED_NONCE_LEN(s->s3->tmp.new_cipher); + } else { + key_len = EVP_CIPHER_key_length(cipher); + iv_len = EVP_CIPHER_iv_length(cipher); + } - key_data = s->s3->tmp.key_block; - client_write_mac_secret = key_data; key_data += mac_secret_len; - server_write_mac_secret = key_data; key_data += mac_secret_len; - client_write_key = key_data; key_data += key_len; - server_write_key = key_data; key_data += key_len; - client_write_iv = key_data; key_data += iv_len; - server_write_iv = key_data; key_data += iv_len; + key_data = s->s3->tmp.key_block; + client_write_mac_secret = key_data; + key_data += mac_secret_len; + server_write_mac_secret = key_data; + key_data += mac_secret_len; + client_write_key = key_data; + key_data += key_len; + server_write_key = key_data; + key_data += key_len; + client_write_iv = key_data; + key_data += iv_len; + server_write_iv = key_data; + key_data += iv_len; - if (use_client_keys) - { - mac_secret = client_write_mac_secret; - key = client_write_key; - iv = client_write_iv; - } - else - { - mac_secret = server_write_mac_secret; - key = server_write_key; - iv = server_write_iv; - } + if (use_client_keys) { + mac_secret = client_write_mac_secret; + key = client_write_key; + iv = client_write_iv; + } else { + mac_secret = server_write_mac_secret; + key = server_write_key; + iv = server_write_iv; + } - if (key_data - s->s3->tmp.key_block != s->s3->tmp.key_block_length) - { - OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state, ERR_R_INTERNAL_ERROR); - return 0; - } + if (key_data - s->s3->tmp.key_block != s->s3->tmp.key_block_length) { + OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state, ERR_R_INTERNAL_ERROR); + return 0; + } - if (aead != NULL) - { - if (!tls1_change_cipher_state_aead(s, is_read, - key, key_len, iv, iv_len, - mac_secret, mac_secret_len)) - return 0; - } - else - { - if (!tls1_change_cipher_state_cipher(s, is_read, use_client_keys, - mac_secret, mac_secret_len, - key, key_len, - iv, iv_len)) - return 0; - } + if (aead != NULL) { + if (!tls1_change_cipher_state_aead(s, is_read, key, key_len, iv, iv_len, + mac_secret, mac_secret_len)) { + return 0; + } + } else { + if (!tls1_change_cipher_state_cipher(s, is_read, use_client_keys, + mac_secret, mac_secret_len, key, + key_len, iv, iv_len)) { + return 0; + } + } - return 1; - } + return 1; +} -int tls1_setup_key_block(SSL *s) - { - unsigned char *p1,*p2=NULL; - const EVP_CIPHER *c = NULL; - const EVP_MD *hash = NULL; - const EVP_AEAD *aead = NULL; - int num; - int mac_type= NID_undef,mac_secret_size=0; - int ret=0; - unsigned key_len, iv_len; +int tls1_setup_key_block(SSL *s) { + uint8_t *p1, *p2 = NULL; + const EVP_CIPHER *c = NULL; + const EVP_MD *hash = NULL; + const EVP_AEAD *aead = NULL; + int num; + int mac_type = NID_undef, mac_secret_size = 0; + int ret = 0; + unsigned key_len, iv_len; - if (s->s3->tmp.key_block_length != 0) - return(1); + if (s->s3->tmp.key_block_length != 0) { + return 1; + } - if (s->session->cipher && - ((s->session->cipher->algorithm2 & SSL_CIPHER_ALGORITHM2_AEAD) || - (s->session->cipher->algorithm2 & SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD))) - { - if (!ssl_cipher_get_evp_aead(s->session, &aead)) - goto cipher_unavailable_err; - key_len = EVP_AEAD_key_length(aead); - iv_len = SSL_CIPHER_AEAD_FIXED_NONCE_LEN(s->session->cipher); - if ((s->session->cipher->algorithm2 & - SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD) && - !ssl_cipher_get_mac(s->session, &hash, &mac_type, &mac_secret_size)) - goto cipher_unavailable_err; - /* For "stateful" AEADs (i.e. compatibility with pre-AEAD - * cipher suites) the key length reported by - * |EVP_AEAD_key_length| will include the MAC key bytes. */ - if (key_len < (size_t)mac_secret_size) - { - OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state, ERR_R_INTERNAL_ERROR); - return 0; - } - key_len -= mac_secret_size; - } - else - { - if (!ssl_cipher_get_evp(s->session,&c,&hash,&mac_type,&mac_secret_size)) - goto cipher_unavailable_err; - key_len = EVP_CIPHER_key_length(c); - iv_len = EVP_CIPHER_iv_length(c); - } + if (s->session->cipher && + ((s->session->cipher->algorithm2 & SSL_CIPHER_ALGORITHM2_AEAD) || + (s->session->cipher->algorithm2 & + SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD))) { + if (!ssl_cipher_get_evp_aead(s->session, &aead)) { + goto cipher_unavailable_err; + } + key_len = EVP_AEAD_key_length(aead); + iv_len = SSL_CIPHER_AEAD_FIXED_NONCE_LEN(s->session->cipher); + if ((s->session->cipher->algorithm2 & + SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD) && + !ssl_cipher_get_mac(s->session, &hash, &mac_type, &mac_secret_size)) { + goto cipher_unavailable_err; + } + /* For "stateful" AEADs (i.e. compatibility with pre-AEAD cipher suites) + * the key length reported by |EVP_AEAD_key_length| will include the MAC + * key bytes. */ + if (key_len < (size_t)mac_secret_size) { + OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state, ERR_R_INTERNAL_ERROR); + return 0; + } + key_len -= mac_secret_size; + } else { + if (!ssl_cipher_get_evp(s->session, &c, &hash, &mac_type, + &mac_secret_size)) { + goto cipher_unavailable_err; + } + key_len = EVP_CIPHER_key_length(c); + iv_len = EVP_CIPHER_iv_length(c); + } - s->s3->tmp.new_aead=aead; - s->s3->tmp.new_sym_enc=c; - s->s3->tmp.new_hash=hash; - s->s3->tmp.new_mac_pkey_type = mac_type; - s->s3->tmp.new_mac_secret_size = mac_secret_size; + s->s3->tmp.new_aead = aead; + s->s3->tmp.new_sym_enc = c; + s->s3->tmp.new_hash = hash; + s->s3->tmp.new_mac_pkey_type = mac_type; + s->s3->tmp.new_mac_secret_size = mac_secret_size; - num=key_len+mac_secret_size+iv_len; - num*=2; + num = key_len + mac_secret_size + iv_len; + num *= 2; - ssl3_cleanup_key_block(s); + ssl3_cleanup_key_block(s); - if ((p1=(unsigned char *)OPENSSL_malloc(num)) == NULL) - { - OPENSSL_PUT_ERROR(SSL, tls1_setup_key_block, ERR_R_MALLOC_FAILURE); - goto err; - } + p1 = (uint8_t *)OPENSSL_malloc(num); + if (p1 == NULL) { + OPENSSL_PUT_ERROR(SSL, tls1_setup_key_block, ERR_R_MALLOC_FAILURE); + goto err; + } - s->s3->tmp.key_block_length=num; - s->s3->tmp.key_block=p1; + s->s3->tmp.key_block_length = num; + s->s3->tmp.key_block = p1; - if ((p2=(unsigned char *)OPENSSL_malloc(num)) == NULL) - { - OPENSSL_PUT_ERROR(SSL, tls1_setup_key_block, ERR_R_MALLOC_FAILURE); - goto err; - } + p2 = (uint8_t *)OPENSSL_malloc(num); + if (p2 == NULL) { + OPENSSL_PUT_ERROR(SSL, tls1_setup_key_block, ERR_R_MALLOC_FAILURE); + goto err; + } -#ifdef TLS_DEBUG -printf("client random\n"); -{ int z; for (z=0; z<SSL3_RANDOM_SIZE; z++) printf("%02X%c",s->s3->client_random[z],((z+1)%16)?' ':'\n'); } -printf("server random\n"); -{ int z; for (z=0; z<SSL3_RANDOM_SIZE; z++) printf("%02X%c",s->s3->server_random[z],((z+1)%16)?' ':'\n'); } -printf("pre-master\n"); -{ int z; for (z=0; z<s->session->master_key_length; z++) printf("%02X%c",s->session->master_key[z],((z+1)%16)?' ':'\n'); } -#endif - if (!tls1_generate_key_block(s,p1,p2,num)) - goto err; -#ifdef TLS_DEBUG -printf("\nkey block\n"); -{ int z; for (z=0; z<num; z++) printf("%02X%c",p1[z],((z+1)%16)?' ':'\n'); } -#endif + if (!tls1_generate_key_block(s, p1, p2, num)) { + goto err; + } - if (!SSL_USE_EXPLICIT_IV(s) && - (s->mode & SSL_MODE_CBC_RECORD_SPLITTING) != 0) - { - /* enable vulnerability countermeasure for CBC ciphers with - * known-IV problem (http://www.openssl.org/~bodo/tls-cbc.txt) - */ - s->s3->need_record_splitting = 1; + if (!SSL_USE_EXPLICIT_IV(s) && + (s->mode & SSL_MODE_CBC_RECORD_SPLITTING) != 0) { + /* enable vulnerability countermeasure for CBC ciphers with known-IV + * problem (http://www.openssl.org/~bodo/tls-cbc.txt). */ + s->s3->need_record_splitting = 1; - if (s->session->cipher != NULL) - { - if (s->session->cipher->algorithm_enc == SSL_RC4) - s->s3->need_record_splitting = 0; - } - } - - ret = 1; + if (s->session->cipher != NULL && + s->session->cipher->algorithm_enc == SSL_RC4) { + s->s3->need_record_splitting = 0; + } + } + + ret = 1; + err: - if (p2) - { - OPENSSL_cleanse(p2,num); - OPENSSL_free(p2); - } - return(ret); + if (p2) { + OPENSSL_cleanse(p2, num); + OPENSSL_free(p2); + } + return ret; cipher_unavailable_err: - OPENSSL_PUT_ERROR(SSL, tls1_setup_key_block, SSL_R_CIPHER_OR_HASH_UNAVAILABLE); - return 0; - } + OPENSSL_PUT_ERROR(SSL, tls1_setup_key_block, + SSL_R_CIPHER_OR_HASH_UNAVAILABLE); + return 0; +} -/* tls1_enc encrypts/decrypts the record in |s->wrec| / |s->rrec|, respectively. +/* tls1_enc encrypts/decrypts the record in |s->wrec| / |s->rrec|, + * respectively. * * Returns: * 0: (in non-constant time) if the record is publically invalid (i.e. too * short etc). * 1: if the record's padding is valid / the encryption was successful. * -1: if the record's padding/AEAD-authenticator is invalid or, if sending, - * an internal error occured. - */ -int tls1_enc(SSL *s, int send) - { - SSL3_RECORD *rec; - EVP_CIPHER_CTX *ds; - unsigned long l; - int bs,i,j,k,pad=0,ret,mac_size=0; - const EVP_CIPHER *enc; - const SSL_AEAD_CTX *aead; + * an internal error occured. */ +int tls1_enc(SSL *s, int send) { + SSL3_RECORD *rec; + EVP_CIPHER_CTX *ds; + unsigned long l; + int bs, i, j, k, pad = 0, ret, mac_size = 0; + const EVP_CIPHER *enc; + const SSL_AEAD_CTX *aead; - if (send) - rec = &s->s3->wrec; - else - rec = &s->s3->rrec; + if (send) { + rec = &s->s3->wrec; + aead = s->aead_write_ctx; + } else { + rec = &s->s3->rrec; + aead = s->aead_read_ctx; + } - if (send) - aead = s->aead_write_ctx; - else - aead = s->aead_read_ctx; + if (aead) { + uint8_t ad[13], *seq, *in, *out, nonce[16]; + unsigned nonce_used; + size_t n; - if (aead) - { - unsigned char ad[13], *seq, *in, *out, nonce[16]; - unsigned nonce_used; - size_t n; + seq = send ? s->s3->write_sequence : s->s3->read_sequence; - seq = send ? s->s3->write_sequence : s->s3->read_sequence; + if (SSL_IS_DTLS(s)) { + uint8_t dtlsseq[9], *p = dtlsseq; - if (SSL_IS_DTLS(s)) - { - unsigned char dtlsseq[9], *p = dtlsseq; + s2n(send ? s->d1->w_epoch : s->d1->r_epoch, p); + memcpy(p, &seq[2], 6); + memcpy(ad, dtlsseq, 8); + } else { + memcpy(ad, seq, 8); + for (i = 7; i >= 0; i--) { + ++seq[i]; + if (seq[i] != 0) { + break; + } + } + } - s2n(send ? s->d1->w_epoch : s->d1->r_epoch, p); - memcpy(p, &seq[2], 6); - memcpy(ad, dtlsseq, 8); - } - else - { - memcpy(ad, seq, 8); - for (i=7; i>=0; i--) /* increment */ - { - ++seq[i]; - if (seq[i] != 0) - break; - } - } + ad[8] = rec->type; + ad[9] = (uint8_t)(s->version >> 8); + ad[10] = (uint8_t)(s->version); - ad[8] = rec->type; - ad[9] = (unsigned char)(s->version>>8); - ad[10] = (unsigned char)(s->version); + if (aead->fixed_nonce_len + aead->variable_nonce_len > sizeof(nonce) || + aead->variable_nonce_len > 8) { + return -1; /* internal error - should never happen. */ + } - if (aead->fixed_nonce_len + aead->variable_nonce_len > sizeof(nonce) || - aead->variable_nonce_len > 8) - return -1; /* internal error - should never happen. */ + memcpy(nonce, aead->fixed_nonce, aead->fixed_nonce_len); + nonce_used = aead->fixed_nonce_len; - memcpy(nonce, aead->fixed_nonce, aead->fixed_nonce_len); - nonce_used = aead->fixed_nonce_len; + if (send) { + size_t len = rec->length; + size_t eivlen = 0; + in = rec->input; + out = rec->data; - if (send) - { - size_t len = rec->length; - size_t eivlen = 0; - in = rec->input; - out = rec->data; + /* When sending we use the sequence number as the variable part of the + * nonce. */ + if (aead->variable_nonce_len > 8) { + return -1; + } + memcpy(nonce + nonce_used, ad, aead->variable_nonce_len); + nonce_used += aead->variable_nonce_len; - /* When sending we use the sequence number as the - * variable part of the nonce. */ - if (aead->variable_nonce_len > 8) - return -1; - memcpy(nonce + nonce_used, ad, aead->variable_nonce_len); - nonce_used += aead->variable_nonce_len; + /* in do_ssl3_write, rec->input is moved forward by variable_nonce_len in + * order to leave space for the variable nonce. Thus we can copy the + * sequence number bytes into place without overwriting any of the + * plaintext. */ + if (aead->variable_nonce_included_in_record) { + memcpy(out, ad, aead->variable_nonce_len); + len -= aead->variable_nonce_len; + eivlen = aead->variable_nonce_len; + } - /* in do_ssl3_write, rec->input is moved forward by - * variable_nonce_len in order to leave space for the - * variable nonce. Thus we can copy the sequence number - * bytes into place without overwriting any of the - * plaintext. */ - if (aead->variable_nonce_included_in_record) - { - memcpy(out, ad, aead->variable_nonce_len); - len -= aead->variable_nonce_len; - eivlen = aead->variable_nonce_len; - } + ad[11] = len >> 8; + ad[12] = len & 0xff; - ad[11] = len >> 8; - ad[12] = len & 0xff; + if (!EVP_AEAD_CTX_seal(&aead->ctx, out + eivlen, &n, len + aead->tag_len, + nonce, nonce_used, in + eivlen, len, ad, + sizeof(ad))) { + return -1; + } - if (!EVP_AEAD_CTX_seal( - &aead->ctx, - out + eivlen, &n, len + aead->tag_len, - nonce, nonce_used, - in + eivlen, len, - ad, sizeof(ad))) - { - return -1; - } - if (aead->variable_nonce_included_in_record) - n += aead->variable_nonce_len; - } - else - { - /* receive */ - size_t len = rec->length; + if (aead->variable_nonce_included_in_record) { + n += aead->variable_nonce_len; + } + } else { + /* receive */ + size_t len = rec->length; - if (rec->data != rec->input) - return -1; /* internal error - should never happen. */ - out = in = rec->input; + if (rec->data != rec->input) { + return -1; /* internal error - should never happen. */ + } + out = in = rec->input; - if (len < aead->variable_nonce_len) - return 0; - memcpy(nonce + nonce_used, - aead->variable_nonce_included_in_record ? in : ad, - aead->variable_nonce_len); - nonce_used += aead->variable_nonce_len; + if (len < aead->variable_nonce_len) { + return 0; + } + memcpy(nonce + nonce_used, + aead->variable_nonce_included_in_record ? in : ad, + aead->variable_nonce_len); + nonce_used += aead->variable_nonce_len; - if (aead->variable_nonce_included_in_record) - { - in += aead->variable_nonce_len; - len -= aead->variable_nonce_len; - out += aead->variable_nonce_len; - } + if (aead->variable_nonce_included_in_record) { + in += aead->variable_nonce_len; + len -= aead->variable_nonce_len; + out += aead->variable_nonce_len; + } - if (len < aead->tag_len) - return 0; - len -= aead->tag_len; + if (len < aead->tag_len) { + return 0; + } + len -= aead->tag_len; - ad[11] = len >> 8; - ad[12] = len & 0xff; + ad[11] = len >> 8; + ad[12] = len & 0xff; - if (!EVP_AEAD_CTX_open( - &aead->ctx, - out, &n, len, - nonce, nonce_used, - in, len + aead->tag_len, - ad, sizeof(ad))) - { - return -1; - } + if (!EVP_AEAD_CTX_open(&aead->ctx, out, &n, len, nonce, nonce_used, in, + len + aead->tag_len, ad, sizeof(ad))) { + return -1; + } - rec->data = rec->input = out; - } + rec->data = rec->input = out; + } - rec->length = n; - return 1; - } + rec->length = n; + return 1; + } - if (send) - { - ds=s->enc_write_ctx; - rec= &(s->s3->wrec); - if (s->enc_write_ctx == NULL) - enc=NULL; - else - { - int ivlen; - enc=EVP_CIPHER_CTX_cipher(s->enc_write_ctx); - /* For TLSv1.1 and later explicit IV */ - if (SSL_USE_EXPLICIT_IV(s) - && EVP_CIPHER_mode(enc) == EVP_CIPH_CBC_MODE) - ivlen = EVP_CIPHER_iv_length(enc); - else - ivlen = 0; - if (ivlen > 1) - { - if ( rec->data != rec->input) - /* we can't write into the input stream: - * Can this ever happen?? (steve) - */ - fprintf(stderr, - "%s:%d: rec->data != rec->input\n", - __FILE__, __LINE__); - else if (!RAND_bytes(rec->input, ivlen)) - return -1; - } - } - } - else - { - ds=s->enc_read_ctx; - rec= &(s->s3->rrec); - if (s->enc_read_ctx == NULL) - enc=NULL; - else - enc=EVP_CIPHER_CTX_cipher(s->enc_read_ctx); - } + if (send) { + ds = s->enc_write_ctx; + rec = &(s->s3->wrec); + if (s->enc_write_ctx == NULL) { + enc = NULL; + } else { + int ivlen; + enc = EVP_CIPHER_CTX_cipher(s->enc_write_ctx); + /* For TLSv1.1 and later explicit IV */ + if (SSL_USE_EXPLICIT_IV(s) && EVP_CIPHER_mode(enc) == EVP_CIPH_CBC_MODE) { + ivlen = EVP_CIPHER_iv_length(enc); + } else { + ivlen = 0; + } - if ((s->session == NULL) || (ds == NULL) || (enc == NULL)) - { - memmove(rec->data,rec->input,rec->length); - rec->input=rec->data; - ret = 1; - } - else - { - l=rec->length; - bs=EVP_CIPHER_block_size(ds->cipher); + if (ivlen > 1) { + if (rec->data != rec->input) { + /* we can't write into the input stream: + * Can this ever happen?? (steve) + */ + fprintf(stderr, "%s:%d: rec->data != rec->input\n", __FILE__, + __LINE__); + } else if (!RAND_bytes(rec->input, ivlen)) { + return -1; + } + } + } + } else { + ds = s->enc_read_ctx; + rec = &(s->s3->rrec); + if (s->enc_read_ctx == NULL) { + enc = NULL; + } else { + enc = EVP_CIPHER_CTX_cipher(s->enc_read_ctx); + } + } - if ((bs != 1) && send) - { - i=bs-((int)l%bs); + if (s->session == NULL || ds == NULL || enc == NULL) { + memmove(rec->data, rec->input, rec->length); + rec->input = rec->data; + ret = 1; + } else { + l = rec->length; + bs = EVP_CIPHER_block_size(ds->cipher); - /* Add weird padding of upto 256 bytes */ + if (bs != 1 && send) { + i = bs - ((int)l % bs); - /* we need to add 'i' padding bytes of value j */ - j=i-1; - for (k=(int)l; k<(int)(l+i); k++) - rec->input[k]=j; - l+=i; - rec->length+=i; - } + /* Add weird padding of upto 256 bytes */ + /* we need to add 'i' padding bytes of value j */ + j = i - 1; + for (k = (int)l; k < (int)(l + i); k++) { + rec->input[k] = j; + } + l += i; + rec->length += i; + } - if (!send) - { - if (l == 0 || l%bs != 0) - return 0; - } - - if (!EVP_Cipher(ds, rec->data, rec->input, l)) - return -1; + if (!send && (l == 0 || l % bs != 0)) { + return 0; + } - ret = 1; - if (EVP_MD_CTX_md(s->read_hash) != NULL) - mac_size = EVP_MD_CTX_size(s->read_hash); - if ((bs != 1) && !send) - ret = tls1_cbc_remove_padding(s, rec, bs, mac_size); - if (pad && !send) - rec->length -= pad; - } - return ret; - } + if (!EVP_Cipher(ds, rec->data, rec->input, l)) { + return -1; + } -int tls1_cert_verify_mac(SSL *s, int md_nid, unsigned char *out) - { - unsigned int ret; - EVP_MD_CTX ctx, *d=NULL; - int i; + ret = 1; + if (EVP_MD_CTX_md(s->read_hash) != NULL) { + mac_size = EVP_MD_CTX_size(s->read_hash); + } - if (s->s3->handshake_buffer) - if (!ssl3_digest_cached_records(s, free_handshake_buffer)) - return 0; + if (bs != 1 && !send) { + ret = tls1_cbc_remove_padding(s, rec, bs, mac_size); + } + if (pad && !send) { + rec->length -= pad; + } + } + return ret; +} - for (i=0;i<SSL_MAX_DIGEST;i++) - { - if (s->s3->handshake_dgst[i]&&EVP_MD_CTX_type(s->s3->handshake_dgst[i])==md_nid) - { - d=s->s3->handshake_dgst[i]; - break; - } - } - if (!d) { - OPENSSL_PUT_ERROR(SSL, tls1_cert_verify_mac, SSL_R_NO_REQUIRED_DIGEST); - return 0; - } +int tls1_cert_verify_mac(SSL *s, int md_nid, uint8_t *out) { + unsigned int ret; + EVP_MD_CTX ctx, *d = NULL; + int i; - EVP_MD_CTX_init(&ctx); - EVP_MD_CTX_copy_ex(&ctx,d); - EVP_DigestFinal_ex(&ctx,out,&ret); - EVP_MD_CTX_cleanup(&ctx); - return((int)ret); - } + if (s->s3->handshake_buffer && + !ssl3_digest_cached_records(s, free_handshake_buffer)) { + return 0; + } + + for (i = 0; i < SSL_MAX_DIGEST; i++) { + if (s->s3->handshake_dgst[i] && + EVP_MD_CTX_type(s->s3->handshake_dgst[i]) == md_nid) { + d = s->s3->handshake_dgst[i]; + break; + } + } + + if (!d) { + OPENSSL_PUT_ERROR(SSL, tls1_cert_verify_mac, SSL_R_NO_REQUIRED_DIGEST); + return 0; + } + + EVP_MD_CTX_init(&ctx); + EVP_MD_CTX_copy_ex(&ctx, d); + EVP_DigestFinal_ex(&ctx, out, &ret); + EVP_MD_CTX_cleanup(&ctx); + + return ret; +} /* tls1_handshake_digest calculates the current handshake hash and writes it to * |out|, which has space for |out_len| bytes. It returns the number of bytes * written or -1 in the event of an error. This function works on a copy of the * underlying digests so can be called multiple times and prior to the final * update etc. */ -int tls1_handshake_digest(SSL *s, unsigned char *out, size_t out_len) - { - const EVP_MD *md; - EVP_MD_CTX ctx; - int i, err = 0, len = 0; - long mask; +int tls1_handshake_digest(SSL *s, uint8_t *out, size_t out_len) { + const EVP_MD *md; + EVP_MD_CTX ctx; + int i, err = 0, len = 0; + long mask; - EVP_MD_CTX_init(&ctx); + EVP_MD_CTX_init(&ctx); - for (i = 0; ssl_get_handshake_digest(i, &mask, &md); i++) - { - int hash_size; - unsigned int digest_len; - EVP_MD_CTX *hdgst = s->s3->handshake_dgst[i]; + for (i = 0; ssl_get_handshake_digest(i, &mask, &md); i++) { + int hash_size; + unsigned int digest_len; + EVP_MD_CTX *hdgst = s->s3->handshake_dgst[i]; - if ((mask & ssl_get_algorithm2(s)) == 0) - continue; + if ((mask & ssl_get_algorithm2(s)) == 0) { + continue; + } - hash_size = EVP_MD_size(md); - if (!hdgst || hash_size < 0 || (size_t)hash_size > out_len) - { - err = 1; - break; - } + hash_size = EVP_MD_size(md); + if (!hdgst || + hash_size < 0 || + (size_t)hash_size > out_len || + !EVP_MD_CTX_copy_ex(&ctx, hdgst) || + !EVP_DigestFinal_ex(&ctx, out, &digest_len) || + digest_len != (unsigned int)hash_size /* internal error */) { + err = 1; + break; + } - if (!EVP_MD_CTX_copy_ex(&ctx, hdgst) || - !EVP_DigestFinal_ex(&ctx, out, &digest_len) || - digest_len != (unsigned int)hash_size) /* internal error */ - { - err = 1; - break; - } - out += digest_len; - out_len -= digest_len; - len += digest_len; - } + out += digest_len; + out_len -= digest_len; + len += digest_len; + } - EVP_MD_CTX_cleanup(&ctx); + EVP_MD_CTX_cleanup(&ctx); - if (err != 0) - return -1; - return len; - } + if (err != 0) { + return -1; + } + return len; +} -int tls1_final_finish_mac(SSL *s, - const char *str, int slen, unsigned char *out) - { - unsigned char buf[2*EVP_MAX_MD_SIZE]; - unsigned char buf2[12]; - int err=0; - int digests_len; +int tls1_final_finish_mac(SSL *s, const char *str, int slen, uint8_t *out) { + uint8_t buf[2 * EVP_MAX_MD_SIZE]; + uint8_t buf2[12]; + int err = 0; + int digests_len; - if (s->s3->handshake_buffer) - if (!ssl3_digest_cached_records(s, free_handshake_buffer)) - return 0; + if (s->s3->handshake_buffer && + !ssl3_digest_cached_records(s, free_handshake_buffer)) { + return 0; + } - digests_len = tls1_handshake_digest(s, buf, sizeof(buf)); - if (digests_len < 0) - { - err = 1; - digests_len = 0; - } - - if (!tls1_PRF(ssl_get_algorithm2(s), - str,slen, buf, digests_len, NULL,0, - s->session->master_key,s->session->master_key_length, - out,buf2,sizeof buf2)) - err = 1; + digests_len = tls1_handshake_digest(s, buf, sizeof(buf)); + if (digests_len < 0) { + err = 1; + digests_len = 0; + } - if (err) - return 0; - else - return sizeof buf2; - } + if (!tls1_PRF(ssl_get_algorithm2(s), str, slen, buf, digests_len, NULL, 0, + s->session->master_key, s->session->master_key_length, out, + buf2, sizeof buf2)) { + err = 1; + } -int tls1_mac(SSL *ssl, unsigned char *md, int send) - { - SSL3_RECORD *rec; - unsigned char *seq; - EVP_MD_CTX *hash; - size_t md_size, orig_len; - int i, ok; - EVP_MD_CTX hmac, *mac_ctx; - unsigned char header[13]; - int t; + if (err) { + return 0; + } else { + return sizeof(buf2); + } +} - if (send) - { - rec= &(ssl->s3->wrec); - seq= &(ssl->s3->write_sequence[0]); - hash=ssl->write_hash; - } - else - { - rec= &(ssl->s3->rrec); - seq= &(ssl->s3->read_sequence[0]); - hash=ssl->read_hash; - } +int tls1_mac(SSL *ssl, uint8_t *md, int send) { + SSL3_RECORD *rec; + uint8_t *seq; + EVP_MD_CTX *hash; + size_t md_size, orig_len; + int i, ok; + EVP_MD_CTX hmac, *mac_ctx; + uint8_t header[13]; + int t; - t=EVP_MD_CTX_size(hash); - assert(t >= 0); - md_size=t; + if (send) { + rec = &ssl->s3->wrec; + seq = &ssl->s3->write_sequence[0]; + hash = ssl->write_hash; + } else { + rec = &ssl->s3->rrec; + seq = &ssl->s3->read_sequence[0]; + hash = ssl->read_hash; + } - mac_ctx = &hmac; - if (!EVP_MD_CTX_copy(mac_ctx, hash)) - return -1; + t = EVP_MD_CTX_size(hash); + assert(t >= 0); + md_size = t; - if (SSL_IS_DTLS(ssl)) - { - unsigned char dtlsseq[8],*p=dtlsseq; + mac_ctx = &hmac; + if (!EVP_MD_CTX_copy(mac_ctx, hash)) { + return -1; + } - s2n(send?ssl->d1->w_epoch:ssl->d1->r_epoch, p); - memcpy (p,&seq[2],6); + if (SSL_IS_DTLS(ssl)) { + uint8_t dtlsseq[8], *p = dtlsseq; - memcpy(header, dtlsseq, 8); - } - else - memcpy(header, seq, 8); + s2n(send ? ssl->d1->w_epoch : ssl->d1->r_epoch, p); + memcpy(p, &seq[2], 6); - /* kludge: tls1_cbc_remove_padding passes padding length in rec->type */ - orig_len = rec->length+md_size+((unsigned int)rec->type>>8); - rec->type &= 0xff; + memcpy(header, dtlsseq, 8); + } else { + memcpy(header, seq, 8); + } - header[8]=rec->type; - header[9]=(unsigned char)(ssl->version>>8); - header[10]=(unsigned char)(ssl->version); - header[11]=(rec->length)>>8; - header[12]=(rec->length)&0xff; + /* kludge: tls1_cbc_remove_padding passes padding length in rec->type */ + orig_len = rec->length + md_size + ((unsigned int)rec->type >> 8); + rec->type &= 0xff; - if (!send && - EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE && - ssl3_cbc_record_digest_supported(mac_ctx)) - { - /* This is a CBC-encrypted record. We must avoid leaking any - * timing-side channel information about how many blocks of - * data we are hashing because that gives an attacker a - * timing-oracle. */ - ok = ssl3_cbc_digest_record( - mac_ctx, - md, &md_size, - header, rec->input, - rec->length + md_size, orig_len, - ssl->s3->read_mac_secret, - ssl->s3->read_mac_secret_size, - 0 /* not SSLv3 */); - } - else - { - EVP_DigestSignUpdate(mac_ctx,header,sizeof(header)); - EVP_DigestSignUpdate(mac_ctx,rec->input,rec->length); - ok = EVP_DigestSignFinal(mac_ctx,md,&md_size); - } + header[8] = rec->type; + header[9] = (uint8_t)(ssl->version >> 8); + header[10] = (uint8_t)(ssl->version); + header[11] = (rec->length) >> 8; + header[12] = (rec->length) & 0xff; - EVP_MD_CTX_cleanup(mac_ctx); + if (!send && EVP_CIPHER_CTX_mode(ssl->enc_read_ctx) == EVP_CIPH_CBC_MODE && + ssl3_cbc_record_digest_supported(mac_ctx)) { + /* This is a CBC-encrypted record. We must avoid leaking any timing-side + * channel information about how many blocks of data we are hashing because + * that gives an attacker a timing-oracle. */ + ok = ssl3_cbc_digest_record( + mac_ctx, md, &md_size, header, rec->input, rec->length + md_size, + orig_len, ssl->s3->read_mac_secret, ssl->s3->read_mac_secret_size, + 0 /* not SSLv3 */); + } else { + EVP_DigestSignUpdate(mac_ctx, header, sizeof(header)); + EVP_DigestSignUpdate(mac_ctx, rec->input, rec->length); + ok = EVP_DigestSignFinal(mac_ctx, md, &md_size); + } - if (!ok) - return -1; + EVP_MD_CTX_cleanup(mac_ctx); - if (!SSL_IS_DTLS(ssl)) - { - for (i=7; i>=0; i--) - { - ++seq[i]; - if (seq[i] != 0) break; - } - } + if (!ok) { + return -1; + } - return md_size; - } + if (!SSL_IS_DTLS(ssl)) { + for (i = 7; i >= 0; i--) { + ++seq[i]; + if (seq[i] != 0) { + break; + } + } + } -int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, - int len) - { - unsigned char buff[SSL_MAX_MASTER_KEY_LENGTH]; + return md_size; +} - if (s->s3->tmp.extended_master_secret) - { - uint8_t digests[2*EVP_MAX_MD_SIZE]; - int digests_len; +int tls1_generate_master_secret(SSL *s, uint8_t *out, uint8_t *p, int len) { + uint8_t buff[SSL_MAX_MASTER_KEY_LENGTH]; - if (s->s3->handshake_buffer) - { - /* The master secret is based on the handshake hash - * just after sending the ClientKeyExchange. However, - * we might have a client certificate to send, in which - * case we might need different hashes for the - * verification and thus still need the handshake - * buffer around. Keeping both a handshake buffer *and* - * running hashes isn't yet supported so, when it comes - * to calculating the Finished hash, we'll have to hash - * the handshake buffer again. */ - if (!ssl3_digest_cached_records(s, dont_free_handshake_buffer)) - return 0; - } + if (s->s3->tmp.extended_master_secret) { + uint8_t digests[2 * EVP_MAX_MD_SIZE]; + int digests_len; - digests_len = tls1_handshake_digest(s, digests, sizeof(digests)); + /* The master secret is based on the handshake hash just after sending the + * ClientKeyExchange. However, we might have a client certificate to send, + * in which case we might need different hashes for the verification and + * thus still need the handshake buffer around. Keeping both a handshake + * buffer *and* running hashes isn't yet supported so, when it comes to + * calculating the Finished hash, we'll have to hash the handshake buffer + * again. */ + if (s->s3->handshake_buffer && + !ssl3_digest_cached_records(s, dont_free_handshake_buffer)) { + return 0; + } - if (digests_len == -1) - { - return 0; - } + digests_len = tls1_handshake_digest(s, digests, sizeof(digests)); - tls1_PRF(ssl_get_algorithm2(s), - TLS_MD_EXTENDED_MASTER_SECRET_CONST, - TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE, - digests, digests_len, - NULL, 0, - p, len, - s->session->master_key, - buff, sizeof(buff)); - } - else - { - tls1_PRF(ssl_get_algorithm2(s), - TLS_MD_MASTER_SECRET_CONST,TLS_MD_MASTER_SECRET_CONST_SIZE, - s->s3->client_random,SSL3_RANDOM_SIZE, - s->s3->server_random,SSL3_RANDOM_SIZE, - p, len, - s->session->master_key,buff,sizeof buff); - } + if (digests_len == -1) { + return 0; + } -#ifdef SSL_DEBUG - fprintf(stderr, "Premaster Secret:\n"); - BIO_dump_fp(stderr, (char *)p, len); - fprintf(stderr, "Client Random:\n"); - BIO_dump_fp(stderr, (char *)s->s3->client_random, SSL3_RANDOM_SIZE); - fprintf(stderr, "Server Random:\n"); - BIO_dump_fp(stderr, (char *)s->s3->server_random, SSL3_RANDOM_SIZE); - fprintf(stderr, "Master Secret:\n"); - BIO_dump_fp(stderr, (char *)s->session->master_key, SSL3_MASTER_SECRET_SIZE); -#endif + tls1_PRF(ssl_get_algorithm2(s), TLS_MD_EXTENDED_MASTER_SECRET_CONST, + TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE, digests, digests_len, + NULL, 0, p, len, s->session->master_key, buff, sizeof(buff)); + } else { + tls1_PRF(ssl_get_algorithm2(s), TLS_MD_MASTER_SECRET_CONST, + TLS_MD_MASTER_SECRET_CONST_SIZE, s->s3->client_random, + SSL3_RANDOM_SIZE, s->s3->server_random, SSL3_RANDOM_SIZE, p, len, + s->session->master_key, buff, sizeof buff); + } -#ifdef OPENSSL_SSL_TRACE_CRYPTO - if (s->msg_callback) - { - s->msg_callback(2, s->version, TLS1_RT_CRYPTO_PREMASTER, - p, len, s, s->msg_callback_arg); - s->msg_callback(2, s->version, TLS1_RT_CRYPTO_CLIENT_RANDOM, - s->s3->client_random, SSL3_RANDOM_SIZE, - s, s->msg_callback_arg); - s->msg_callback(2, s->version, TLS1_RT_CRYPTO_SERVER_RANDOM, - s->s3->server_random, SSL3_RANDOM_SIZE, - s, s->msg_callback_arg); - s->msg_callback(2, s->version, TLS1_RT_CRYPTO_MASTER, - s->session->master_key, - SSL3_MASTER_SECRET_SIZE, - s, s->msg_callback_arg); - } -#endif + return SSL3_MASTER_SECRET_SIZE; +} - return(SSL3_MASTER_SECRET_SIZE); - } +int tls1_export_keying_material(SSL *s, uint8_t *out, size_t olen, + const char *label, size_t llen, + const uint8_t *context, size_t contextlen, + int use_context) { + uint8_t *buff; + uint8_t *val = NULL; + size_t vallen, currentvalpos; + int ret; -int tls1_export_keying_material(SSL *s, unsigned char *out, size_t olen, - const char *label, size_t llen, const unsigned char *context, - size_t contextlen, int use_context) - { - unsigned char *buff; - unsigned char *val = NULL; - size_t vallen, currentvalpos; - int rv; + buff = OPENSSL_malloc(olen); + if (buff == NULL) { + goto err2; + } - buff = OPENSSL_malloc(olen); - if (buff == NULL) goto err2; + /* construct PRF arguments we construct the PRF argument ourself rather than + * passing separate values into the TLS PRF to ensure that the concatenation + * of values does not create a prohibited label. */ + vallen = llen + SSL3_RANDOM_SIZE * 2; + if (use_context) { + vallen += 2 + contextlen; + } - /* construct PRF arguments - * we construct the PRF argument ourself rather than passing separate - * values into the TLS PRF to ensure that the concatenation of values - * does not create a prohibited label. - */ - vallen = llen + SSL3_RANDOM_SIZE * 2; - if (use_context) - { - vallen += 2 + contextlen; - } + val = OPENSSL_malloc(vallen); + if (val == NULL) { + goto err2; + } - val = OPENSSL_malloc(vallen); - if (val == NULL) goto err2; - currentvalpos = 0; - memcpy(val + currentvalpos, (unsigned char *) label, llen); - currentvalpos += llen; - memcpy(val + currentvalpos, s->s3->client_random, SSL3_RANDOM_SIZE); - currentvalpos += SSL3_RANDOM_SIZE; - memcpy(val + currentvalpos, s->s3->server_random, SSL3_RANDOM_SIZE); - currentvalpos += SSL3_RANDOM_SIZE; + currentvalpos = 0; + memcpy(val + currentvalpos, (uint8_t *)label, llen); + currentvalpos += llen; + memcpy(val + currentvalpos, s->s3->client_random, SSL3_RANDOM_SIZE); + currentvalpos += SSL3_RANDOM_SIZE; + memcpy(val + currentvalpos, s->s3->server_random, SSL3_RANDOM_SIZE); + currentvalpos += SSL3_RANDOM_SIZE; - if (use_context) - { - val[currentvalpos] = (contextlen >> 8) & 0xff; - currentvalpos++; - val[currentvalpos] = contextlen & 0xff; - currentvalpos++; - if ((contextlen > 0) || (context != NULL)) - { - memcpy(val + currentvalpos, context, contextlen); - } - } + if (use_context) { + val[currentvalpos] = (contextlen >> 8) & 0xff; + currentvalpos++; + val[currentvalpos] = contextlen & 0xff; + currentvalpos++; + if (contextlen > 0 || context != NULL) { + memcpy(val + currentvalpos, context, contextlen); + } + } - /* disallow prohibited labels - * note that SSL3_RANDOM_SIZE > max(prohibited label len) = - * 15, so size of val > max(prohibited label len) = 15 and the - * comparisons won't have buffer overflow - */ - if (memcmp(val, TLS_MD_CLIENT_FINISH_CONST, - TLS_MD_CLIENT_FINISH_CONST_SIZE) == 0) goto err1; - if (memcmp(val, TLS_MD_SERVER_FINISH_CONST, - TLS_MD_SERVER_FINISH_CONST_SIZE) == 0) goto err1; - if (memcmp(val, TLS_MD_MASTER_SECRET_CONST, - TLS_MD_MASTER_SECRET_CONST_SIZE) == 0) goto err1; - if (memcmp(val, TLS_MD_KEY_EXPANSION_CONST, - TLS_MD_KEY_EXPANSION_CONST_SIZE) == 0) goto err1; + /* disallow prohibited labels note that SSL3_RANDOM_SIZE > max(prohibited + * label len) = 15, so size of val > max(prohibited label len) = 15 and the + * comparisons won't have buffer overflow. */ + if (memcmp(val, TLS_MD_CLIENT_FINISH_CONST, + TLS_MD_CLIENT_FINISH_CONST_SIZE) == 0 || + memcmp(val, TLS_MD_SERVER_FINISH_CONST, + TLS_MD_SERVER_FINISH_CONST_SIZE) == 0 || + memcmp(val, TLS_MD_MASTER_SECRET_CONST, + TLS_MD_MASTER_SECRET_CONST_SIZE) == 0 || + memcmp(val, TLS_MD_KEY_EXPANSION_CONST, + TLS_MD_KEY_EXPANSION_CONST_SIZE) == 0) { + goto err1; + } - rv = tls1_PRF(ssl_get_algorithm2(s), - val, vallen, - NULL, 0, - NULL, 0, - s->session->master_key,s->session->master_key_length, - out,buff,olen); + ret = tls1_PRF(ssl_get_algorithm2(s), val, vallen, NULL, 0, NULL, 0, + s->session->master_key, s->session->master_key_length, out, + buff, olen); - goto ret; + goto out; + err1: - OPENSSL_PUT_ERROR(SSL, tls1_export_keying_material, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL); - rv = 0; - goto ret; -err2: - OPENSSL_PUT_ERROR(SSL, tls1_export_keying_material, ERR_R_MALLOC_FAILURE); - rv = 0; -ret: - if (buff != NULL) OPENSSL_free(buff); - if (val != NULL) OPENSSL_free(val); - return(rv); - } + OPENSSL_PUT_ERROR(SSL, tls1_export_keying_material, + SSL_R_TLS_ILLEGAL_EXPORTER_LABEL); + ret = 0; + goto out; -int tls1_alert_code(int code) - { - switch (code) - { - case SSL_AD_CLOSE_NOTIFY: return(SSL3_AD_CLOSE_NOTIFY); - case SSL_AD_UNEXPECTED_MESSAGE: return(SSL3_AD_UNEXPECTED_MESSAGE); - case SSL_AD_BAD_RECORD_MAC: return(SSL3_AD_BAD_RECORD_MAC); - case SSL_AD_DECRYPTION_FAILED: return(TLS1_AD_DECRYPTION_FAILED); - case SSL_AD_RECORD_OVERFLOW: return(TLS1_AD_RECORD_OVERFLOW); - case SSL_AD_DECOMPRESSION_FAILURE:return(SSL3_AD_DECOMPRESSION_FAILURE); - case SSL_AD_HANDSHAKE_FAILURE: return(SSL3_AD_HANDSHAKE_FAILURE); - case SSL_AD_NO_CERTIFICATE: return(-1); - case SSL_AD_BAD_CERTIFICATE: return(SSL3_AD_BAD_CERTIFICATE); - case SSL_AD_UNSUPPORTED_CERTIFICATE:return(SSL3_AD_UNSUPPORTED_CERTIFICATE); - case SSL_AD_CERTIFICATE_REVOKED:return(SSL3_AD_CERTIFICATE_REVOKED); - case SSL_AD_CERTIFICATE_EXPIRED:return(SSL3_AD_CERTIFICATE_EXPIRED); - case SSL_AD_CERTIFICATE_UNKNOWN:return(SSL3_AD_CERTIFICATE_UNKNOWN); - case SSL_AD_ILLEGAL_PARAMETER: return(SSL3_AD_ILLEGAL_PARAMETER); - case SSL_AD_UNKNOWN_CA: return(TLS1_AD_UNKNOWN_CA); - case SSL_AD_ACCESS_DENIED: return(TLS1_AD_ACCESS_DENIED); - case SSL_AD_DECODE_ERROR: return(TLS1_AD_DECODE_ERROR); - case SSL_AD_DECRYPT_ERROR: return(TLS1_AD_DECRYPT_ERROR); - case SSL_AD_EXPORT_RESTRICTION: return(TLS1_AD_EXPORT_RESTRICTION); - case SSL_AD_PROTOCOL_VERSION: return(TLS1_AD_PROTOCOL_VERSION); - case SSL_AD_INSUFFICIENT_SECURITY:return(TLS1_AD_INSUFFICIENT_SECURITY); - case SSL_AD_INTERNAL_ERROR: return(TLS1_AD_INTERNAL_ERROR); - case SSL_AD_USER_CANCELLED: return(TLS1_AD_USER_CANCELLED); - case SSL_AD_NO_RENEGOTIATION: return(TLS1_AD_NO_RENEGOTIATION); - case SSL_AD_UNSUPPORTED_EXTENSION: return(TLS1_AD_UNSUPPORTED_EXTENSION); - case SSL_AD_CERTIFICATE_UNOBTAINABLE: return(TLS1_AD_CERTIFICATE_UNOBTAINABLE); - case SSL_AD_UNRECOGNIZED_NAME: return(TLS1_AD_UNRECOGNIZED_NAME); - case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE: return(TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE); - case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: return(TLS1_AD_BAD_CERTIFICATE_HASH_VALUE); - case SSL_AD_UNKNOWN_PSK_IDENTITY:return(TLS1_AD_UNKNOWN_PSK_IDENTITY); - case SSL_AD_INAPPROPRIATE_FALLBACK:return(SSL3_AD_INAPPROPRIATE_FALLBACK); - default: return(-1); - } - } +err2: + OPENSSL_PUT_ERROR(SSL, tls1_export_keying_material, ERR_R_MALLOC_FAILURE); + ret = 0; + +out: + if (buff != NULL) { + OPENSSL_free(buff); + } + if (val != NULL) { + OPENSSL_free(val); + } + + return ret; +} + +int tls1_alert_code(int code) { + switch (code) { + case SSL_AD_CLOSE_NOTIFY: + return SSL3_AD_CLOSE_NOTIFY; + + case SSL_AD_UNEXPECTED_MESSAGE: + return SSL3_AD_UNEXPECTED_MESSAGE; + + case SSL_AD_BAD_RECORD_MAC: + return SSL3_AD_BAD_RECORD_MAC; + + case SSL_AD_DECRYPTION_FAILED: + return TLS1_AD_DECRYPTION_FAILED; + + case SSL_AD_RECORD_OVERFLOW: + return TLS1_AD_RECORD_OVERFLOW; + + case SSL_AD_DECOMPRESSION_FAILURE: + return SSL3_AD_DECOMPRESSION_FAILURE; + + case SSL_AD_HANDSHAKE_FAILURE: + return SSL3_AD_HANDSHAKE_FAILURE; + + case SSL_AD_NO_CERTIFICATE: + return -1; + + case SSL_AD_BAD_CERTIFICATE: + return SSL3_AD_BAD_CERTIFICATE; + + case SSL_AD_UNSUPPORTED_CERTIFICATE: + return SSL3_AD_UNSUPPORTED_CERTIFICATE; + + case SSL_AD_CERTIFICATE_REVOKED: + return SSL3_AD_CERTIFICATE_REVOKED; + + case SSL_AD_CERTIFICATE_EXPIRED: + return SSL3_AD_CERTIFICATE_EXPIRED; + + case SSL_AD_CERTIFICATE_UNKNOWN: + return SSL3_AD_CERTIFICATE_UNKNOWN; + + case SSL_AD_ILLEGAL_PARAMETER: + return SSL3_AD_ILLEGAL_PARAMETER; + + case SSL_AD_UNKNOWN_CA: + return TLS1_AD_UNKNOWN_CA; + + case SSL_AD_ACCESS_DENIED: + return TLS1_AD_ACCESS_DENIED; + + case SSL_AD_DECODE_ERROR: + return TLS1_AD_DECODE_ERROR; + + case SSL_AD_DECRYPT_ERROR: + return TLS1_AD_DECRYPT_ERROR; + case SSL_AD_EXPORT_RESTRICTION: + return TLS1_AD_EXPORT_RESTRICTION; + + case SSL_AD_PROTOCOL_VERSION: + return TLS1_AD_PROTOCOL_VERSION; + + case SSL_AD_INSUFFICIENT_SECURITY: + return TLS1_AD_INSUFFICIENT_SECURITY; + + case SSL_AD_INTERNAL_ERROR: + return TLS1_AD_INTERNAL_ERROR; + + case SSL_AD_USER_CANCELLED: + return TLS1_AD_USER_CANCELLED; + + case SSL_AD_NO_RENEGOTIATION: + return TLS1_AD_NO_RENEGOTIATION; + + case SSL_AD_UNSUPPORTED_EXTENSION: + return TLS1_AD_UNSUPPORTED_EXTENSION; + + case SSL_AD_CERTIFICATE_UNOBTAINABLE: + return TLS1_AD_CERTIFICATE_UNOBTAINABLE; + + case SSL_AD_UNRECOGNIZED_NAME: + return TLS1_AD_UNRECOGNIZED_NAME; + + case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE: + return TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE; + + case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: + return TLS1_AD_BAD_CERTIFICATE_HASH_VALUE; + + case SSL_AD_UNKNOWN_PSK_IDENTITY: + return TLS1_AD_UNKNOWN_PSK_IDENTITY; + + case SSL_AD_INAPPROPRIATE_FALLBACK: + return SSL3_AD_INAPPROPRIATE_FALLBACK; + + default: + return -1; + } +}
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index c3cac06..5975f70 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c
@@ -118,392 +118,369 @@ #include <openssl/rand.h> #include "ssl_locl.h" -static int tls_decrypt_ticket(SSL *s, const unsigned char *tick, int ticklen, - const unsigned char *sess_id, int sesslen, - SSL_SESSION **psess); + + +static int tls_decrypt_ticket(SSL *s, const uint8_t *tick, int ticklen, + const uint8_t *sess_id, int sesslen, + SSL_SESSION **psess); static int ssl_check_clienthello_tlsext(SSL *s); static int ssl_check_serverhello_tlsext(SSL *s); const SSL3_ENC_METHOD TLSv1_enc_data = { - tls1_enc, - tls1_mac, - tls1_setup_key_block, - tls1_generate_master_secret, - tls1_change_cipher_state, - tls1_final_finish_mac, - TLS1_FINISH_MAC_LENGTH, - tls1_cert_verify_mac, - TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE, - TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE, - tls1_alert_code, - tls1_export_keying_material, - 0, - SSL3_HM_HEADER_LENGTH, - ssl3_set_handshake_header, - ssl3_handshake_write, - }; + tls1_enc, + tls1_mac, + tls1_setup_key_block, + tls1_generate_master_secret, + tls1_change_cipher_state, + tls1_final_finish_mac, + TLS1_FINISH_MAC_LENGTH, + tls1_cert_verify_mac, + TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE, + TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE, + tls1_alert_code, + tls1_export_keying_material, + 0, + SSL3_HM_HEADER_LENGTH, + ssl3_set_handshake_header, + ssl3_handshake_write, +}; const SSL3_ENC_METHOD TLSv1_1_enc_data = { - tls1_enc, - tls1_mac, - tls1_setup_key_block, - tls1_generate_master_secret, - tls1_change_cipher_state, - tls1_final_finish_mac, - TLS1_FINISH_MAC_LENGTH, - tls1_cert_verify_mac, - TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE, - TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE, - tls1_alert_code, - tls1_export_keying_material, - SSL_ENC_FLAG_EXPLICIT_IV, - SSL3_HM_HEADER_LENGTH, - ssl3_set_handshake_header, - ssl3_handshake_write, - }; + tls1_enc, + tls1_mac, + tls1_setup_key_block, + tls1_generate_master_secret, + tls1_change_cipher_state, + tls1_final_finish_mac, + TLS1_FINISH_MAC_LENGTH, + tls1_cert_verify_mac, + TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE, + TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE, + tls1_alert_code, + tls1_export_keying_material, + SSL_ENC_FLAG_EXPLICIT_IV, + SSL3_HM_HEADER_LENGTH, + ssl3_set_handshake_header, + ssl3_handshake_write, +}; const SSL3_ENC_METHOD TLSv1_2_enc_data = { - tls1_enc, - tls1_mac, - tls1_setup_key_block, - tls1_generate_master_secret, - tls1_change_cipher_state, - tls1_final_finish_mac, - TLS1_FINISH_MAC_LENGTH, - tls1_cert_verify_mac, - TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE, - TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE, - tls1_alert_code, - tls1_export_keying_material, - SSL_ENC_FLAG_EXPLICIT_IV|SSL_ENC_FLAG_SIGALGS|SSL_ENC_FLAG_SHA256_PRF - |SSL_ENC_FLAG_TLS1_2_CIPHERS, - SSL3_HM_HEADER_LENGTH, - ssl3_set_handshake_header, - ssl3_handshake_write, - }; + tls1_enc, + tls1_mac, + tls1_setup_key_block, + tls1_generate_master_secret, + tls1_change_cipher_state, + tls1_final_finish_mac, + TLS1_FINISH_MAC_LENGTH, + tls1_cert_verify_mac, + TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE, + TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE, + tls1_alert_code, + tls1_export_keying_material, + SSL_ENC_FLAG_EXPLICIT_IV|SSL_ENC_FLAG_SIGALGS|SSL_ENC_FLAG_SHA256_PRF + |SSL_ENC_FLAG_TLS1_2_CIPHERS, + SSL3_HM_HEADER_LENGTH, + ssl3_set_handshake_header, + ssl3_handshake_write, +}; -static int compare_uint16_t(const void *p1, const void *p2) - { - uint16_t u1 = *((const uint16_t*)p1); - uint16_t u2 = *((const uint16_t*)p2); - if (u1 < u2) - { - return -1; - } - else if (u1 > u2) - { - return 1; - } - else - { - return 0; - } - } +static int compare_uint16_t(const void *p1, const void *p2) { + uint16_t u1 = *((const uint16_t *)p1); + uint16_t u2 = *((const uint16_t *)p2); + if (u1 < u2) { + return -1; + } else if (u1 > u2) { + return 1; + } else { + return 0; + } +} -/* Per http://tools.ietf.org/html/rfc5246#section-7.4.1.4, there may not be more - * than one extension of the same type in a ClientHello or ServerHello. This - * function does an initial scan over the extensions block to filter those +/* Per http://tools.ietf.org/html/rfc5246#section-7.4.1.4, there may not be + * more than one extension of the same type in a ClientHello or ServerHello. + * This function does an initial scan over the extensions block to filter those * out. */ -static int tls1_check_duplicate_extensions(const CBS *cbs) - { - CBS extensions = *cbs; - size_t num_extensions = 0, i = 0; - uint16_t *extension_types = NULL; - int ret = 0; +static int tls1_check_duplicate_extensions(const CBS *cbs) { + CBS extensions = *cbs; + size_t num_extensions = 0, i = 0; + uint16_t *extension_types = NULL; + int ret = 0; - /* First pass: count the extensions. */ - while (CBS_len(&extensions) > 0) - { - uint16_t type; - CBS extension; + /* First pass: count the extensions. */ + while (CBS_len(&extensions) > 0) { + uint16_t type; + CBS extension; - if (!CBS_get_u16(&extensions, &type) || - !CBS_get_u16_length_prefixed(&extensions, &extension)) - { - goto done; - } + if (!CBS_get_u16(&extensions, &type) || + !CBS_get_u16_length_prefixed(&extensions, &extension)) { + goto done; + } - num_extensions++; - } + num_extensions++; + } - if (num_extensions == 0) - { - return 1; - } + if (num_extensions == 0) { + return 1; + } - extension_types = (uint16_t*)OPENSSL_malloc(sizeof(uint16_t) * num_extensions); - if (extension_types == NULL) - { - OPENSSL_PUT_ERROR(SSL, tls1_check_duplicate_extensions, ERR_R_MALLOC_FAILURE); - goto done; - } + extension_types = + (uint16_t *)OPENSSL_malloc(sizeof(uint16_t) * num_extensions); + if (extension_types == NULL) { + OPENSSL_PUT_ERROR(SSL, tls1_check_duplicate_extensions, + ERR_R_MALLOC_FAILURE); + goto done; + } - /* Second pass: gather the extension types. */ - extensions = *cbs; - for (i = 0; i < num_extensions; i++) - { - CBS extension; + /* Second pass: gather the extension types. */ + extensions = *cbs; + for (i = 0; i < num_extensions; i++) { + CBS extension; - if (!CBS_get_u16(&extensions, &extension_types[i]) || - !CBS_get_u16_length_prefixed(&extensions, &extension)) - { - /* This should not happen. */ - goto done; - } - } - assert(CBS_len(&extensions) == 0); + if (!CBS_get_u16(&extensions, &extension_types[i]) || + !CBS_get_u16_length_prefixed(&extensions, &extension)) { + /* This should not happen. */ + goto done; + } + } + assert(CBS_len(&extensions) == 0); - /* Sort the extensions and make sure there are no duplicates. */ - qsort(extension_types, num_extensions, sizeof(uint16_t), compare_uint16_t); - for (i = 1; i < num_extensions; i++) - { - if (extension_types[i-1] == extension_types[i]) - { - goto done; - } - } + /* Sort the extensions and make sure there are no duplicates. */ + qsort(extension_types, num_extensions, sizeof(uint16_t), compare_uint16_t); + for (i = 1; i < num_extensions; i++) { + if (extension_types[i - 1] == extension_types[i]) { + goto done; + } + } - ret = 1; + ret = 1; + done: - if (extension_types) - OPENSSL_free(extension_types); - return ret; - } + if (extension_types) + OPENSSL_free(extension_types); + return ret; +} -char ssl_early_callback_init(struct ssl_early_callback_ctx *ctx) - { - CBS client_hello, session_id, cipher_suites, compression_methods, extensions; +char ssl_early_callback_init(struct ssl_early_callback_ctx *ctx) { + CBS client_hello, session_id, cipher_suites, compression_methods, extensions; - CBS_init(&client_hello, ctx->client_hello, ctx->client_hello_len); + CBS_init(&client_hello, ctx->client_hello, ctx->client_hello_len); - /* Skip client version. */ - if (!CBS_skip(&client_hello, 2)) - return 0; + if (/* Skip client version. */ + !CBS_skip(&client_hello, 2) || + /* Skip client nonce. */ + !CBS_skip(&client_hello, 32) || + /* Extract session_id. */ + !CBS_get_u8_length_prefixed(&client_hello, &session_id)) { + return 0; + } - /* Skip client nonce. */ - if (!CBS_skip(&client_hello, 32)) - return 0; + ctx->session_id = CBS_data(&session_id); + ctx->session_id_len = CBS_len(&session_id); - /* Extract session_id. */ - if (!CBS_get_u8_length_prefixed(&client_hello, &session_id)) - return 0; - ctx->session_id = CBS_data(&session_id); - ctx->session_id_len = CBS_len(&session_id); + /* Skip past DTLS cookie */ + if (SSL_IS_DTLS(ctx->ssl)) { + CBS cookie; - /* Skip past DTLS cookie */ - if (SSL_IS_DTLS(ctx->ssl)) - { - CBS cookie; + if (!CBS_get_u8_length_prefixed(&client_hello, &cookie)) { + return 0; + } + } - if (!CBS_get_u8_length_prefixed(&client_hello, &cookie)) - return 0; - } + /* Extract cipher_suites. */ + if (!CBS_get_u16_length_prefixed(&client_hello, &cipher_suites) || + CBS_len(&cipher_suites) < 2 || (CBS_len(&cipher_suites) & 1) != 0) { + return 0; + } + ctx->cipher_suites = CBS_data(&cipher_suites); + ctx->cipher_suites_len = CBS_len(&cipher_suites); - /* Extract cipher_suites. */ - if (!CBS_get_u16_length_prefixed(&client_hello, &cipher_suites) || - CBS_len(&cipher_suites) < 2 || - (CBS_len(&cipher_suites) & 1) != 0) - return 0; - ctx->cipher_suites = CBS_data(&cipher_suites); - ctx->cipher_suites_len = CBS_len(&cipher_suites); + /* Extract compression_methods. */ + if (!CBS_get_u8_length_prefixed(&client_hello, &compression_methods) || + CBS_len(&compression_methods) < 1) { + return 0; + } + ctx->compression_methods = CBS_data(&compression_methods); + ctx->compression_methods_len = CBS_len(&compression_methods); - /* Extract compression_methods. */ - if (!CBS_get_u8_length_prefixed(&client_hello, &compression_methods) || - CBS_len(&compression_methods) < 1) - return 0; - ctx->compression_methods = CBS_data(&compression_methods); - ctx->compression_methods_len = CBS_len(&compression_methods); + /* If the ClientHello ends here then it's valid, but doesn't have any + * extensions. (E.g. SSLv3.) */ + if (CBS_len(&client_hello) == 0) { + ctx->extensions = NULL; + ctx->extensions_len = 0; + return 1; + } - /* If the ClientHello ends here then it's valid, but doesn't have any - * extensions. (E.g. SSLv3.) */ - if (CBS_len(&client_hello) == 0) - { - ctx->extensions = NULL; - ctx->extensions_len = 0; - return 1; - } + /* Extract extensions and check it is valid. */ + if (!CBS_get_u16_length_prefixed(&client_hello, &extensions) || + !tls1_check_duplicate_extensions(&extensions) || + CBS_len(&client_hello) != 0) { + return 0; + } + ctx->extensions = CBS_data(&extensions); + ctx->extensions_len = CBS_len(&extensions); - /* Extract extensions and check it is valid. */ - if (!CBS_get_u16_length_prefixed(&client_hello, &extensions) || - !tls1_check_duplicate_extensions(&extensions) || - CBS_len(&client_hello) != 0) - return 0; - ctx->extensions = CBS_data(&extensions); - ctx->extensions_len = CBS_len(&extensions); + return 1; +} - return 1; - } +char SSL_early_callback_ctx_extension_get( + const struct ssl_early_callback_ctx *ctx, uint16_t extension_type, + const uint8_t **out_data, size_t *out_len) { + CBS extensions; -char -SSL_early_callback_ctx_extension_get(const struct ssl_early_callback_ctx *ctx, - uint16_t extension_type, - const unsigned char **out_data, - size_t *out_len) - { - CBS extensions; + CBS_init(&extensions, ctx->extensions, ctx->extensions_len); - CBS_init(&extensions, ctx->extensions, ctx->extensions_len); + while (CBS_len(&extensions) != 0) { + uint16_t type; + CBS extension; - while (CBS_len(&extensions) != 0) - { - uint16_t type; - CBS extension; + /* Decode the next extension. */ + if (!CBS_get_u16(&extensions, &type) || + !CBS_get_u16_length_prefixed(&extensions, &extension)) { + return 0; + } - /* Decode the next extension. */ - if (!CBS_get_u16(&extensions, &type) || - !CBS_get_u16_length_prefixed(&extensions, &extension)) - return 0; + if (type == extension_type) { + *out_data = CBS_data(&extension); + *out_len = CBS_len(&extension); + return 1; + } + } - if (type == extension_type) - { - *out_data = CBS_data(&extension); - *out_len = CBS_len(&extension); - return 1; - } - } - - return 0; - } - + return 0; +} /* ECC curves from RFC4492 */ -static const int nid_list[] = - { - NID_sect163k1, /* sect163k1 (1) */ - NID_sect163r1, /* sect163r1 (2) */ - NID_sect163r2, /* sect163r2 (3) */ - NID_sect193r1, /* sect193r1 (4) */ - NID_sect193r2, /* sect193r2 (5) */ - NID_sect233k1, /* sect233k1 (6) */ - NID_sect233r1, /* sect233r1 (7) */ - NID_sect239k1, /* sect239k1 (8) */ - NID_sect283k1, /* sect283k1 (9) */ - NID_sect283r1, /* sect283r1 (10) */ - NID_sect409k1, /* sect409k1 (11) */ - NID_sect409r1, /* sect409r1 (12) */ - NID_sect571k1, /* sect571k1 (13) */ - NID_sect571r1, /* sect571r1 (14) */ - NID_secp160k1, /* secp160k1 (15) */ - NID_secp160r1, /* secp160r1 (16) */ - NID_secp160r2, /* secp160r2 (17) */ - NID_secp192k1, /* secp192k1 (18) */ - NID_X9_62_prime192v1, /* secp192r1 (19) */ - NID_secp224k1, /* secp224k1 (20) */ - NID_secp224r1, /* secp224r1 (21) */ - NID_secp256k1, /* secp256k1 (22) */ - NID_X9_62_prime256v1, /* secp256r1 (23) */ - NID_secp384r1, /* secp384r1 (24) */ - NID_secp521r1, /* secp521r1 (25) */ - NID_brainpoolP256r1, /* brainpoolP256r1 (26) */ - NID_brainpoolP384r1, /* brainpoolP384r1 (27) */ - NID_brainpoolP512r1 /* brainpool512r1 (28) */ - }; +static const int nid_list[] = { + NID_sect163k1, /* sect163k1 (1) */ + NID_sect163r1, /* sect163r1 (2) */ + NID_sect163r2, /* sect163r2 (3) */ + NID_sect193r1, /* sect193r1 (4) */ + NID_sect193r2, /* sect193r2 (5) */ + NID_sect233k1, /* sect233k1 (6) */ + NID_sect233r1, /* sect233r1 (7) */ + NID_sect239k1, /* sect239k1 (8) */ + NID_sect283k1, /* sect283k1 (9) */ + NID_sect283r1, /* sect283r1 (10) */ + NID_sect409k1, /* sect409k1 (11) */ + NID_sect409r1, /* sect409r1 (12) */ + NID_sect571k1, /* sect571k1 (13) */ + NID_sect571r1, /* sect571r1 (14) */ + NID_secp160k1, /* secp160k1 (15) */ + NID_secp160r1, /* secp160r1 (16) */ + NID_secp160r2, /* secp160r2 (17) */ + NID_secp192k1, /* secp192k1 (18) */ + NID_X9_62_prime192v1, /* secp192r1 (19) */ + NID_secp224k1, /* secp224k1 (20) */ + NID_secp224r1, /* secp224r1 (21) */ + NID_secp256k1, /* secp256k1 (22) */ + NID_X9_62_prime256v1, /* secp256r1 (23) */ + NID_secp384r1, /* secp384r1 (24) */ + NID_secp521r1, /* secp521r1 (25) */ + NID_brainpoolP256r1, /* brainpoolP256r1 (26) */ + NID_brainpoolP384r1, /* brainpoolP384r1 (27) */ + NID_brainpoolP512r1 /* brainpool512r1 (28) */ +}; -static const uint8_t ecformats_default[] = - { - TLSEXT_ECPOINTFORMAT_uncompressed, - }; +static const uint8_t ecformats_default[] = { + TLSEXT_ECPOINTFORMAT_uncompressed, +}; -static const uint16_t eccurves_default[] = - { - 23, /* secp256r1 (23) */ - 24, /* secp384r1 (24) */ - 25, /* secp521r1 (25) */ - }; +static const uint16_t eccurves_default[] = { + 23, /* secp256r1 (23) */ + 24, /* secp384r1 (24) */ + 25, /* secp521r1 (25) */ +}; -int tls1_ec_curve_id2nid(uint16_t curve_id) - { - if (curve_id < 1 || curve_id > sizeof(nid_list)/sizeof(nid_list[0])) - return OBJ_undef; - return nid_list[curve_id-1]; - } +int tls1_ec_curve_id2nid(uint16_t curve_id) { + if (curve_id < 1 || curve_id > sizeof(nid_list) / sizeof(nid_list[0])) { + return OBJ_undef; + } + return nid_list[curve_id - 1]; +} -uint16_t tls1_ec_nid2curve_id(int nid) - { - size_t i; - for (i = 0; i < sizeof(nid_list)/sizeof(nid_list[0]); i++) - { - /* nid_list[i] stores the NID corresponding to curve ID i+1. */ - if (nid == nid_list[i]) - return i + 1; - } - /* Use 0 for non-existent curve ID. Note: this assumes that curve ID 0 - * will never be allocated. */ - return 0; - } +uint16_t tls1_ec_nid2curve_id(int nid) { + size_t i; + for (i = 0; i < sizeof(nid_list) / sizeof(nid_list[0]); i++) { + /* nid_list[i] stores the NID corresponding to curve ID i+1. */ + if (nid == nid_list[i]) { + return i + 1; + } + } -/* tls1_get_curvelist sets |*out_curve_ids| and |*out_curve_ids_len| - * to the list of allowed curve IDs. If |get_peer_curves| is non-zero, - * return the peer's curve list. Otherwise, return the preferred - * list. */ + /* Use 0 for non-existent curve ID. Note: this assumes that curve ID 0 will + * never be allocated. */ + return 0; +} + +/* tls1_get_curvelist sets |*out_curve_ids| and |*out_curve_ids_len| to the + * list of allowed curve IDs. If |get_peer_curves| is non-zero, return the + * peer's curve list. Otherwise, return the preferred list. */ static void tls1_get_curvelist(SSL *s, int get_peer_curves, - const uint16_t **out_curve_ids, size_t *out_curve_ids_len) - { - if (get_peer_curves) - { - *out_curve_ids = s->s3->tmp.peer_ellipticcurvelist; - *out_curve_ids_len = s->s3->tmp.peer_ellipticcurvelist_length; - return; - } + const uint16_t **out_curve_ids, + size_t *out_curve_ids_len) { + if (get_peer_curves) { + *out_curve_ids = s->s3->tmp.peer_ellipticcurvelist; + *out_curve_ids_len = s->s3->tmp.peer_ellipticcurvelist_length; + return; + } - *out_curve_ids = s->tlsext_ellipticcurvelist; - *out_curve_ids_len = s->tlsext_ellipticcurvelist_length; - if (!*out_curve_ids) - { - *out_curve_ids = eccurves_default; - *out_curve_ids_len = sizeof(eccurves_default) / sizeof(eccurves_default[0]); - } - } + *out_curve_ids = s->tlsext_ellipticcurvelist; + *out_curve_ids_len = s->tlsext_ellipticcurvelist_length; + if (!*out_curve_ids) { + *out_curve_ids = eccurves_default; + *out_curve_ids_len = sizeof(eccurves_default) / sizeof(eccurves_default[0]); + } +} -int tls1_check_curve(SSL *s, CBS *cbs, uint16_t *out_curve_id) - { - uint8_t curve_type; - uint16_t curve_id; - const uint16_t *curves; - size_t curves_len, i; +int tls1_check_curve(SSL *s, CBS *cbs, uint16_t *out_curve_id) { + uint8_t curve_type; + uint16_t curve_id; + const uint16_t *curves; + size_t curves_len, i; - /* Only support named curves. */ - if (!CBS_get_u8(cbs, &curve_type) || - curve_type != NAMED_CURVE_TYPE || - !CBS_get_u16(cbs, &curve_id)) - return 0; + /* Only support named curves. */ + if (!CBS_get_u8(cbs, &curve_type) || + curve_type != NAMED_CURVE_TYPE || + !CBS_get_u16(cbs, &curve_id)) { + return 0; + } - tls1_get_curvelist(s, 0, &curves, &curves_len); - for (i = 0; i < curves_len; i++) - { - if (curve_id == curves[i]) - { - *out_curve_id = curve_id; - return 1; - } - } - return 0; - } + tls1_get_curvelist(s, 0, &curves, &curves_len); + for (i = 0; i < curves_len; i++) { + if (curve_id == curves[i]) { + *out_curve_id = curve_id; + return 1; + } + } -int tls1_get_shared_curve(SSL *s) - { - const uint16_t *pref, *supp; - size_t preflen, supplen, i, j; + return 0; +} - /* Can't do anything on client side */ - if (s->server == 0) - return NID_undef; +int tls1_get_shared_curve(SSL *s) { + const uint16_t *pref, *supp; + size_t preflen, supplen, i, j; - /* Return first preference shared curve */ - tls1_get_curvelist(s, !!(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE), - &supp, &supplen); - tls1_get_curvelist(s, !(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE), - &pref, &preflen); - for (i = 0; i < preflen; i++) - { - for (j = 0; j < supplen; j++) - { - if (pref[i] == supp[j]) - return tls1_ec_curve_id2nid(pref[i]); - } - } - return NID_undef; - } + /* Can't do anything on client side */ + if (s->server == 0) { + return NID_undef; + } + + /* Return first preference shared curve */ + tls1_get_curvelist(s, !!(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE), &supp, + &supplen); + tls1_get_curvelist(s, !(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE), &pref, + &preflen); + + for (i = 0; i < preflen; i++) { + for (j = 0; j < supplen; j++) { + if (pref[i] == supp[j]) { + return tls1_ec_curve_id2nid(pref[i]); + } + } + } + + return NID_undef; +} /* NOTE: tls1_ec_curve_id2nid and tls1_set_curves assume that * @@ -513,851 +490,850 @@ * * Those implementations must be revised before adding support for curve IDs * that break these assumptions. */ -OPENSSL_COMPILE_ASSERT( - (sizeof(nid_list) / sizeof(nid_list[0])) < 32, small_curve_ids); +OPENSSL_COMPILE_ASSERT((sizeof(nid_list) / sizeof(nid_list[0])) < 32, + small_curve_ids); int tls1_set_curves(uint16_t **out_curve_ids, size_t *out_curve_ids_len, - const int *curves, size_t ncurves) - { - uint16_t *curve_ids; - size_t i; - /* Bitmap of curves included to detect duplicates: only works - * while curve ids < 32 - */ - uint32_t dup_list = 0; - curve_ids = (uint16_t*)OPENSSL_malloc(ncurves * sizeof(uint16_t)); - if (!curve_ids) - return 0; - for (i = 0; i < ncurves; i++) - { - uint32_t idmask; - uint16_t id; - id = tls1_ec_nid2curve_id(curves[i]); - idmask = ((uint32_t)1) << id; - if (!id || (dup_list & idmask)) - { - OPENSSL_free(curve_ids); - return 0; - } - dup_list |= idmask; - curve_ids[i] = id; - } - if (*out_curve_ids) - OPENSSL_free(*out_curve_ids); - *out_curve_ids = curve_ids; - *out_curve_ids_len = ncurves; - return 1; - } + const int *curves, size_t ncurves) { + uint16_t *curve_ids; + size_t i; + + /* Bitmap of curves included to detect duplicates: only works + * while curve ids < 32. */ + uint32_t dup_list = 0; + curve_ids = (uint16_t *)OPENSSL_malloc(ncurves * sizeof(uint16_t)); + if (curve_ids == NULL) { + return 0; + } + + for (i = 0; i < ncurves; i++) { + uint32_t idmask; + uint16_t id; + id = tls1_ec_nid2curve_id(curves[i]); + idmask = ((uint32_t)1) << id; + if (!id || (dup_list & idmask)) { + OPENSSL_free(curve_ids); + return 0; + } + dup_list |= idmask; + curve_ids[i] = id; + } + + if (*out_curve_ids) { + OPENSSL_free(*out_curve_ids); + } + *out_curve_ids = curve_ids; + *out_curve_ids_len = ncurves; + + return 1; +} /* tls1_curve_params_from_ec_key sets |*out_curve_id| and |*out_comp_id| to the * TLS curve ID and point format, respectively, for |ec|. It returns one on * success and zero on failure. */ -static int tls1_curve_params_from_ec_key(uint16_t *out_curve_id, uint8_t *out_comp_id, EC_KEY *ec) - { - int nid; - uint16_t id; - const EC_GROUP *grp; - if (!ec) - return 0; +static int tls1_curve_params_from_ec_key(uint16_t *out_curve_id, + uint8_t *out_comp_id, EC_KEY *ec) { + int nid; + uint16_t id; + const EC_GROUP *grp; - grp = EC_KEY_get0_group(ec); - if (!grp) - return 0; + if (ec == NULL) { + return 0; + } - /* Determine curve ID */ - nid = EC_GROUP_get_curve_name(grp); - id = tls1_ec_nid2curve_id(nid); - if (!id) - return 0; + grp = EC_KEY_get0_group(ec); + if (grp == NULL) { + return 0; + } - /* Set the named curve ID. Arbitrary explicit curves are not - * supported. */ - *out_curve_id = id; + /* Determine curve ID */ + nid = EC_GROUP_get_curve_name(grp); + id = tls1_ec_nid2curve_id(nid); + if (!id) { + return 0; + } - if (out_comp_id) - { - if (EC_KEY_get0_public_key(ec) == NULL) - return 0; - if (EC_KEY_get_conv_form(ec) == POINT_CONVERSION_COMPRESSED) - *out_comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime; - else - *out_comp_id = TLSEXT_ECPOINTFORMAT_uncompressed; - } - return 1; - } + /* Set the named curve ID. Arbitrary explicit curves are not supported. */ + *out_curve_id = id; + + if (out_comp_id) { + if (EC_KEY_get0_public_key(ec) == NULL) { + return 0; + } + if (EC_KEY_get_conv_form(ec) == POINT_CONVERSION_COMPRESSED) { + *out_comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime; + } else { + *out_comp_id = TLSEXT_ECPOINTFORMAT_uncompressed; + } + } + + return 1; +} /* tls1_check_point_format returns one if |comp_id| is consistent with the * peer's point format preferences. */ -static int tls1_check_point_format(SSL *s, uint8_t comp_id) - { - uint8_t *p = s->s3->tmp.peer_ecpointformatlist; - size_t plen = s->s3->tmp.peer_ecpointformatlist_length; - size_t i; +static int tls1_check_point_format(SSL *s, uint8_t comp_id) { + uint8_t *p = s->s3->tmp.peer_ecpointformatlist; + size_t plen = s->s3->tmp.peer_ecpointformatlist_length; + size_t i; - /* If point formats extension present check it, otherwise everything - * is supported (see RFC4492). */ - if (p == NULL) - return 1; + /* If point formats extension present check it, otherwise everything is + * supported (see RFC4492). */ + if (p == NULL) { + return 1; + } - for (i = 0; i < plen; i++) - { - if (comp_id == p[i]) - return 1; - } - return 0; - } + for (i = 0; i < plen; i++) { + if (comp_id == p[i]) { + return 1; + } + } -/* tls1_check_curve_id returns one if |curve_id| is consistent with both our and - * the peer's curve preferences. Note: if called as the client, only our + return 0; +} + +/* tls1_check_curve_id returns one if |curve_id| is consistent with both our + * and the peer's curve preferences. Note: if called as the client, only our * preferences are checked; the peer (the server) does not send preferences. */ -static int tls1_check_curve_id(SSL *s, uint16_t curve_id) - { - const uint16_t *curves; - size_t curves_len, i, j; +static int tls1_check_curve_id(SSL *s, uint16_t curve_id) { + const uint16_t *curves; + size_t curves_len, i, j; - /* Check against our list, then the peer's list. */ - for (j = 0; j <= 1; j++) - { - tls1_get_curvelist(s, j, &curves, &curves_len); - for (i = 0; i < curves_len; i++) - { - if (curves[i] == curve_id) - break; - } - if (i == curves_len) - return 0; - /* Servers do not present a preference list so, if we are a - * client, only check our list. */ - if (!s->server) - return 1; - } - return 1; - } + /* Check against our list, then the peer's list. */ + for (j = 0; j <= 1; j++) { + tls1_get_curvelist(s, j, &curves, &curves_len); + for (i = 0; i < curves_len; i++) { + if (curves[i] == curve_id) { + break; + } + } -static void tls1_get_formatlist(SSL *s, const unsigned char **pformats, - size_t *pformatslen) - { - /* If we have a custom point format list use it otherwise - * use default */ - if (s->tlsext_ecpointformatlist) - { - *pformats = s->tlsext_ecpointformatlist; - *pformatslen = s->tlsext_ecpointformatlist_length; - } - else - { - *pformats = ecformats_default; - *pformatslen = sizeof(ecformats_default); - } - } + if (i == curves_len) { + return 0; + } -int tls1_check_ec_cert(SSL *s, X509 *x) - { - int ret = 0; - EVP_PKEY *pkey = X509_get_pubkey(x); - uint16_t curve_id; - uint8_t comp_id; + /* Servers do not present a preference list so, if we are a client, only + * check our list. */ + if (!s->server) { + return 1; + } + } - if (!pkey || - pkey->type != EVP_PKEY_EC || - !tls1_curve_params_from_ec_key(&curve_id, &comp_id, pkey->pkey.ec) || - !tls1_check_curve_id(s, curve_id) || - !tls1_check_point_format(s, comp_id)) - { - goto done; - } + return 1; +} - ret = 1; +static void tls1_get_formatlist(SSL *s, const uint8_t **pformats, + size_t *pformatslen) { + /* If we have a custom point format list use it otherwise use default */ + if (s->tlsext_ecpointformatlist) { + *pformats = s->tlsext_ecpointformatlist; + *pformatslen = s->tlsext_ecpointformatlist_length; + } else { + *pformats = ecformats_default; + *pformatslen = sizeof(ecformats_default); + } +} + +int tls1_check_ec_cert(SSL *s, X509 *x) { + int ret = 0; + EVP_PKEY *pkey = X509_get_pubkey(x); + uint16_t curve_id; + uint8_t comp_id; + + if (!pkey || + pkey->type != EVP_PKEY_EC || + !tls1_curve_params_from_ec_key(&curve_id, &comp_id, pkey->pkey.ec) || + !tls1_check_curve_id(s, curve_id) || + !tls1_check_point_format(s, comp_id)) { + goto done; + } + + ret = 1; done: - if (pkey) - EVP_PKEY_free(pkey); - return ret; - } + if (pkey) { + EVP_PKEY_free(pkey); + } + return ret; +} -int tls1_check_ec_tmp_key(SSL *s) - { - uint16_t curve_id; - EC_KEY *ec = s->cert->ecdh_tmp; - if (s->cert->ecdh_tmp_auto) - { - /* Need a shared curve */ - return tls1_get_shared_curve(s) != NID_undef; - } - if (!ec) - { - if (s->cert->ecdh_tmp_cb) - return 1; - else - return 0; - } - return tls1_curve_params_from_ec_key(&curve_id, NULL, ec) && - tls1_check_curve_id(s, curve_id); - } +int tls1_check_ec_tmp_key(SSL *s) { + uint16_t curve_id; + EC_KEY *ec = s->cert->ecdh_tmp; + if (s->cert->ecdh_tmp_auto) { + /* Need a shared curve */ + return tls1_get_shared_curve(s) != NID_undef; + } + if (!ec) { + if (s->cert->ecdh_tmp_cb) { + return 1; + } + return 0; + } + + return tls1_curve_params_from_ec_key(&curve_id, NULL, ec) && + tls1_check_curve_id(s, curve_id); +} /* List of supported signature algorithms and hashes. Should make this - * customisable at some point, for now include everything we support. - */ + * customisable at some point, for now include everything we support. */ #define tlsext_sigalg_rsa(md) md, TLSEXT_signature_rsa, #define tlsext_sigalg_ecdsa(md) md, TLSEXT_signature_ecdsa, -#define tlsext_sigalg(md) \ - tlsext_sigalg_rsa(md) \ - tlsext_sigalg_ecdsa(md) +#define tlsext_sigalg(md) tlsext_sigalg_rsa(md) tlsext_sigalg_ecdsa(md) static const uint8_t tls12_sigalgs[] = { - tlsext_sigalg(TLSEXT_hash_sha512) - tlsext_sigalg(TLSEXT_hash_sha384) - tlsext_sigalg(TLSEXT_hash_sha256) - tlsext_sigalg(TLSEXT_hash_sha224) - tlsext_sigalg(TLSEXT_hash_sha1) + tlsext_sigalg(TLSEXT_hash_sha512) + tlsext_sigalg(TLSEXT_hash_sha384) + tlsext_sigalg(TLSEXT_hash_sha256) + tlsext_sigalg(TLSEXT_hash_sha224) + tlsext_sigalg(TLSEXT_hash_sha1) }; -size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs) - { - /* If server use client authentication sigalgs if not NULL */ - if (s->server && s->cert->client_sigalgs) - { - *psigs = s->cert->client_sigalgs; - return s->cert->client_sigalgslen; - } - else if (s->cert->conf_sigalgs) - { - *psigs = s->cert->conf_sigalgs; - return s->cert->conf_sigalgslen; - } - else - { - *psigs = tls12_sigalgs; - return sizeof(tls12_sigalgs); - } - } -/* tls12_check_peer_sigalg parses a SignatureAndHashAlgorithm out of - * |cbs|. It checks it is consistent with |s|'s sent supported - * signature algorithms and, if so, writes the relevant digest into - * |*out_md| and returns 1. Otherwise it returns 0 and writes an alert - * into |*out_alert|. - */ -int tls12_check_peer_sigalg(const EVP_MD **out_md, int *out_alert, - SSL *s, CBS *cbs, EVP_PKEY *pkey) - { - const unsigned char *sent_sigs; - size_t sent_sigslen, i; - int sigalg = tls12_get_sigid(pkey); - uint8_t hash, signature; - /* Should never happen */ - if (sigalg == -1) - { - OPENSSL_PUT_ERROR(SSL, tls12_check_peer_sigalg, ERR_R_INTERNAL_ERROR); - *out_alert = SSL_AD_INTERNAL_ERROR; - return 0; - } - if (!CBS_get_u8(cbs, &hash) || - !CBS_get_u8(cbs, &signature)) - { - OPENSSL_PUT_ERROR(SSL, tls12_check_peer_sigalg, SSL_R_DECODE_ERROR); - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } - /* Check key type is consistent with signature */ - if (sigalg != signature) - { - OPENSSL_PUT_ERROR(SSL, tls12_check_peer_sigalg, SSL_R_WRONG_SIGNATURE_TYPE); - *out_alert = SSL_AD_ILLEGAL_PARAMETER; - return 0; - } - if (pkey->type == EVP_PKEY_EC) - { - uint16_t curve_id; - uint8_t comp_id; - /* Check compression and curve matches extensions */ - if (!tls1_curve_params_from_ec_key(&curve_id, &comp_id, pkey->pkey.ec)) - { - *out_alert = SSL_AD_INTERNAL_ERROR; - return 0; - } - if (s->server) - { - if (!tls1_check_curve_id(s, curve_id) || - !tls1_check_point_format(s, comp_id)) - { - OPENSSL_PUT_ERROR(SSL, tls12_check_peer_sigalg, SSL_R_WRONG_CURVE); - *out_alert = SSL_AD_ILLEGAL_PARAMETER; - return 0; - } - } - } +size_t tls12_get_psigalgs(SSL *s, const uint8_t **psigs) { + /* If server use client authentication sigalgs if not NULL */ + if (s->server && s->cert->client_sigalgs) { + *psigs = s->cert->client_sigalgs; + return s->cert->client_sigalgslen; + } else if (s->cert->conf_sigalgs) { + *psigs = s->cert->conf_sigalgs; + return s->cert->conf_sigalgslen; + } else { + *psigs = tls12_sigalgs; + return sizeof(tls12_sigalgs); + } +} - /* Check signature matches a type we sent */ - sent_sigslen = tls12_get_psigalgs(s, &sent_sigs); - for (i = 0; i < sent_sigslen; i+=2, sent_sigs+=2) - { - if (hash == sent_sigs[0] && signature == sent_sigs[1]) - break; - } - /* Allow fallback to SHA-1. */ - if (i == sent_sigslen && hash != TLSEXT_hash_sha1) - { - OPENSSL_PUT_ERROR(SSL, tls12_check_peer_sigalg, SSL_R_WRONG_SIGNATURE_TYPE); - *out_alert = SSL_AD_ILLEGAL_PARAMETER; - return 0; - } - *out_md = tls12_get_hash(hash); - if (*out_md == NULL) - { - OPENSSL_PUT_ERROR(SSL, tls12_check_peer_sigalg, SSL_R_UNKNOWN_DIGEST); - *out_alert = SSL_AD_ILLEGAL_PARAMETER; - return 0; - } - return 1; - } -/* Get a mask of disabled algorithms: an algorithm is disabled - * if it isn't supported or doesn't appear in supported signature - * algorithms. Unlike ssl_cipher_get_disabled this applies to a specific - * session and not global settings. - * - */ -void ssl_set_client_disabled(SSL *s) - { - CERT *c = s->cert; - const unsigned char *sigalgs; - size_t i, sigalgslen; - int have_rsa = 0, have_ecdsa = 0; - c->mask_a = 0; - c->mask_k = 0; - /* Don't allow TLS 1.2 only ciphers if we don't suppport them */ - if (!SSL_CLIENT_USE_TLS1_2_CIPHERS(s)) - c->mask_ssl = SSL_TLSV1_2; - else - c->mask_ssl = 0; - /* Now go through all signature algorithms seeing if we support - * any for RSA, DSA, ECDSA. Do this for all versions not just - * TLS 1.2. - */ - sigalgslen = tls12_get_psigalgs(s, &sigalgs); - for (i = 0; i < sigalgslen; i += 2, sigalgs += 2) - { - switch(sigalgs[1]) - { - case TLSEXT_signature_rsa: - have_rsa = 1; - break; - case TLSEXT_signature_ecdsa: - have_ecdsa = 1; - break; - } - } - /* Disable auth if we don't include any appropriate signature - * algorithms. - */ - if (!have_rsa) - { - c->mask_a |= SSL_aRSA; - } - if (!have_ecdsa) - { - c->mask_a |= SSL_aECDSA; - } - /* with PSK there must be client callback set */ - if (!s->psk_client_callback) - { - c->mask_a |= SSL_aPSK; - c->mask_k |= SSL_kPSK; - } - } +/* tls12_check_peer_sigalg parses a SignatureAndHashAlgorithm out of |cbs|. It + * checks it is consistent with |s|'s sent supported signature algorithms and, + * if so, writes the relevant digest into |*out_md| and returns 1. Otherwise it + * returns 0 and writes an alert into |*out_alert|. */ +int tls12_check_peer_sigalg(const EVP_MD **out_md, int *out_alert, SSL *s, + CBS *cbs, EVP_PKEY *pkey) { + const uint8_t *sent_sigs; + size_t sent_sigslen, i; + int sigalg = tls12_get_sigid(pkey); + uint8_t hash, signature; + + /* Should never happen */ + if (sigalg == -1) { + OPENSSL_PUT_ERROR(SSL, tls12_check_peer_sigalg, ERR_R_INTERNAL_ERROR); + *out_alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + + if (!CBS_get_u8(cbs, &hash) || + !CBS_get_u8(cbs, &signature)) { + OPENSSL_PUT_ERROR(SSL, tls12_check_peer_sigalg, SSL_R_DECODE_ERROR); + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } + + /* Check key type is consistent with signature */ + if (sigalg != signature) { + OPENSSL_PUT_ERROR(SSL, tls12_check_peer_sigalg, SSL_R_WRONG_SIGNATURE_TYPE); + *out_alert = SSL_AD_ILLEGAL_PARAMETER; + return 0; + } + + if (pkey->type == EVP_PKEY_EC) { + uint16_t curve_id; + uint8_t comp_id; + /* Check compression and curve matches extensions */ + if (!tls1_curve_params_from_ec_key(&curve_id, &comp_id, pkey->pkey.ec)) { + *out_alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + + if (s->server && (!tls1_check_curve_id(s, curve_id) || + !tls1_check_point_format(s, comp_id))) { + OPENSSL_PUT_ERROR(SSL, tls12_check_peer_sigalg, SSL_R_WRONG_CURVE); + *out_alert = SSL_AD_ILLEGAL_PARAMETER; + return 0; + } + } + + /* Check signature matches a type we sent */ + sent_sigslen = tls12_get_psigalgs(s, &sent_sigs); + for (i = 0; i < sent_sigslen; i += 2, sent_sigs += 2) { + if (hash == sent_sigs[0] && signature == sent_sigs[1]) { + break; + } + } + + /* Allow fallback to SHA-1. */ + if (i == sent_sigslen && hash != TLSEXT_hash_sha1) { + OPENSSL_PUT_ERROR(SSL, tls12_check_peer_sigalg, SSL_R_WRONG_SIGNATURE_TYPE); + *out_alert = SSL_AD_ILLEGAL_PARAMETER; + return 0; + } + + *out_md = tls12_get_hash(hash); + if (*out_md == NULL) { + OPENSSL_PUT_ERROR(SSL, tls12_check_peer_sigalg, SSL_R_UNKNOWN_DIGEST); + *out_alert = SSL_AD_ILLEGAL_PARAMETER; + return 0; + } + + return 1; +} + +/* Get a mask of disabled algorithms: an algorithm is disabled if it isn't + * supported or doesn't appear in supported signature algorithms. Unlike + * ssl_cipher_get_disabled this applies to a specific session and not global + * settings. */ +void ssl_set_client_disabled(SSL *s) { + CERT *c = s->cert; + const uint8_t *sigalgs; + size_t i, sigalgslen; + int have_rsa = 0, have_ecdsa = 0; + c->mask_a = 0; + c->mask_k = 0; + + /* Don't allow TLS 1.2 only ciphers if we don't suppport them */ + if (!SSL_CLIENT_USE_TLS1_2_CIPHERS(s)) { + c->mask_ssl = SSL_TLSV1_2; + } else { + c->mask_ssl = 0; + } + + /* Now go through all signature algorithms seeing if we support any for RSA, + * DSA, ECDSA. Do this for all versions not just TLS 1.2. */ + sigalgslen = tls12_get_psigalgs(s, &sigalgs); + for (i = 0; i < sigalgslen; i += 2, sigalgs += 2) { + switch (sigalgs[1]) { + case TLSEXT_signature_rsa: + have_rsa = 1; + break; + + case TLSEXT_signature_ecdsa: + have_ecdsa = 1; + break; + } + } + + /* Disable auth if we don't include any appropriate signature algorithms. */ + if (!have_rsa) { + c->mask_a |= SSL_aRSA; + } + if (!have_ecdsa) { + c->mask_a |= SSL_aECDSA; + } + + /* with PSK there must be client callback set */ + if (!s->psk_client_callback) { + c->mask_a |= SSL_aPSK; + c->mask_k |= SSL_kPSK; + } +} /* header_len is the length of the ClientHello header written so far, used to * compute padding. It does not include the record header. Pass 0 if no padding * is to be done. */ -unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned char *limit, size_t header_len) - { - int extdatalen=0; - unsigned char *ret = buf; - unsigned char *orig = buf; - /* See if we support any ECC ciphersuites */ - int using_ecc = 0; - if (s->version >= TLS1_VERSION || SSL_IS_DTLS(s)) - { - size_t i; - unsigned long alg_k, alg_a; - STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(s); +uint8_t *ssl_add_clienthello_tlsext(SSL *s, uint8_t *buf, uint8_t *limit, + size_t header_len) { + int extdatalen = 0; + uint8_t *ret = buf; + uint8_t *orig = buf; + /* See if we support any ECC ciphersuites */ + int using_ecc = 0; - for (i = 0; i < sk_SSL_CIPHER_num(cipher_stack); i++) - { - const SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i); + if (s->version >= TLS1_VERSION || SSL_IS_DTLS(s)) { + size_t i; + unsigned long alg_k, alg_a; + STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(s); - alg_k = c->algorithm_mkey; - alg_a = c->algorithm_auth; - if ((alg_k & SSL_kEECDH) || (alg_a & SSL_aECDSA)) - { - using_ecc = 1; - break; - } - } - } + for (i = 0; i < sk_SSL_CIPHER_num(cipher_stack); i++) { + const SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i); - /* don't add extensions for SSLv3 unless doing secure renegotiation */ - if (s->client_version == SSL3_VERSION - && !s->s3->send_connection_binding) - return orig; + alg_k = c->algorithm_mkey; + alg_a = c->algorithm_auth; + if ((alg_k & SSL_kEECDH) || (alg_a & SSL_aECDSA)) { + using_ecc = 1; + break; + } + } + } - ret+=2; + /* don't add extensions for SSLv3 unless doing secure renegotiation */ + if (s->client_version == SSL3_VERSION && !s->s3->send_connection_binding) { + return orig; + } - if (ret>=limit) return NULL; /* this really never occurs, but ... */ + ret += 2; - if (s->tlsext_hostname != NULL) - { - /* Add TLS extension servername to the Client Hello message */ - unsigned long size_str; - long lenmax; + if (ret >= limit) { + return NULL; /* should never occur. */ + } - /* check for enough space. - 4 for the servername type and entension length - 2 for servernamelist length - 1 for the hostname type - 2 for hostname length - + hostname length - */ - - if ((lenmax = limit - ret - 9) < 0 - || (size_str = strlen(s->tlsext_hostname)) > (unsigned long)lenmax) - return NULL; - - /* extension type and length */ - s2n(TLSEXT_TYPE_server_name,ret); - s2n(size_str+5,ret); - - /* length of servername list */ - s2n(size_str+3,ret); - - /* hostname type, length and hostname */ - *(ret++) = (unsigned char) TLSEXT_NAMETYPE_host_name; - s2n(size_str,ret); - memcpy(ret, s->tlsext_hostname, size_str); - ret+=size_str; - } + if (s->tlsext_hostname != NULL) { + /* Add TLS extension servername to the Client Hello message */ + unsigned long size_str; + long lenmax; - /* Add RI if renegotiating */ - if (s->renegotiate) - { - int el; - - if(!ssl_add_clienthello_renegotiate_ext(s, 0, &el, 0)) - { - OPENSSL_PUT_ERROR(SSL, ssl_add_clienthello_tlsext, ERR_R_INTERNAL_ERROR); - return NULL; - } + /* check for enough space. + 4 for the servername type and entension length + 2 for servernamelist length + 1 for the hostname type + 2 for hostname length + + hostname length */ - if((limit - ret - 4 - el) < 0) return NULL; - - s2n(TLSEXT_TYPE_renegotiate,ret); - s2n(el,ret); + lenmax = limit - ret - 9; + size_str = strlen(s->tlsext_hostname); + if (lenmax < 0 || size_str > (unsigned long)lenmax) { + return NULL; + } - if(!ssl_add_clienthello_renegotiate_ext(s, ret, &el, el)) - { - OPENSSL_PUT_ERROR(SSL, ssl_add_clienthello_tlsext, ERR_R_INTERNAL_ERROR); - return NULL; - } + /* extension type and length */ + s2n(TLSEXT_TYPE_server_name, ret); + s2n(size_str + 5, ret); - ret += el; - } + /* length of servername list */ + s2n(size_str + 3, ret); - /* Add extended master secret. */ - if (s->version != SSL3_VERSION) - { - if (limit - ret - 4 < 0) - return NULL; - s2n(TLSEXT_TYPE_extended_master_secret,ret); - s2n(0,ret); - } + /* hostname type, length and hostname */ + *(ret++) = (uint8_t)TLSEXT_NAMETYPE_host_name; + s2n(size_str, ret); + memcpy(ret, s->tlsext_hostname, size_str); + ret += size_str; + } - if (!(SSL_get_options(s) & SSL_OP_NO_TICKET)) - { - int ticklen = 0; - if (!s->new_session && s->session && s->session->tlsext_tick) - ticklen = s->session->tlsext_ticklen; + /* Add RI if renegotiating */ + if (s->renegotiate) { + int el; - /* Check for enough room 2 for extension type, 2 for len - * rest for ticket - */ - if ((long)(limit - ret - 4 - ticklen) < 0) return NULL; - s2n(TLSEXT_TYPE_session_ticket,ret); - s2n(ticklen,ret); - if (ticklen) - { - memcpy(ret, s->session->tlsext_tick, ticklen); - ret += ticklen; - } - } + if (!ssl_add_clienthello_renegotiate_ext(s, 0, &el, 0)) { + OPENSSL_PUT_ERROR(SSL, ssl_add_clienthello_tlsext, ERR_R_INTERNAL_ERROR); + return NULL; + } - if (SSL_USE_SIGALGS(s)) - { - size_t salglen; - const unsigned char *salg; - salglen = tls12_get_psigalgs(s, &salg); - if ((size_t)(limit - ret) < salglen + 6) - return NULL; - s2n(TLSEXT_TYPE_signature_algorithms,ret); - s2n(salglen + 2, ret); - s2n(salglen, ret); - memcpy(ret, salg, salglen); - ret += salglen; - } + if ((limit - ret - 4 - el) < 0) { + return NULL; + } - if (s->ocsp_stapling_enabled) - { - /* The status_request extension is excessively extensible at - * every layer. On the client, only support requesting OCSP - * responses with an empty responder_id_list and no - * extensions. */ - if (limit - ret - 4 - 1 - 2 - 2 < 0) return NULL; + s2n(TLSEXT_TYPE_renegotiate, ret); + s2n(el, ret); - s2n(TLSEXT_TYPE_status_request, ret); - s2n(1 + 2 + 2, ret); - /* status_type */ - *(ret++) = TLSEXT_STATUSTYPE_ocsp; - /* responder_id_list - empty */ - s2n(0, ret); - /* request_extensions - empty */ - s2n(0, ret); - } + if (!ssl_add_clienthello_renegotiate_ext(s, ret, &el, el)) { + OPENSSL_PUT_ERROR(SSL, ssl_add_clienthello_tlsext, ERR_R_INTERNAL_ERROR); + return NULL; + } - if (s->ctx->next_proto_select_cb && !s->s3->tmp.finish_md_len) - { - /* The client advertises an emtpy extension to indicate its - * support for Next Protocol Negotiation */ - if (limit - ret - 4 < 0) - return NULL; - s2n(TLSEXT_TYPE_next_proto_neg,ret); - s2n(0,ret); - } + ret += el; + } - if (s->signed_cert_timestamps_enabled && !s->s3->tmp.finish_md_len) - { - /* The client advertises an empty extension to indicate its support for - * certificate timestamps. */ - if (limit - ret - 4 < 0) - return NULL; - s2n(TLSEXT_TYPE_certificate_timestamp,ret); - s2n(0,ret); - } + /* Add extended master secret. */ + if (s->version != SSL3_VERSION) { + if (limit - ret - 4 < 0) { + return NULL; + } + s2n(TLSEXT_TYPE_extended_master_secret, ret); + s2n(0, ret); + } - if (s->alpn_client_proto_list && !s->s3->tmp.finish_md_len) - { - if ((size_t)(limit - ret) < 6 + s->alpn_client_proto_list_len) - return NULL; - s2n(TLSEXT_TYPE_application_layer_protocol_negotiation,ret); - s2n(2 + s->alpn_client_proto_list_len,ret); - s2n(s->alpn_client_proto_list_len,ret); - memcpy(ret, s->alpn_client_proto_list, - s->alpn_client_proto_list_len); - ret += s->alpn_client_proto_list_len; - } + if (!(SSL_get_options(s) & SSL_OP_NO_TICKET)) { + int ticklen = 0; + if (!s->new_session && s->session && s->session->tlsext_tick) { + ticklen = s->session->tlsext_ticklen; + } - if (s->tlsext_channel_id_enabled) - { - /* The client advertises an emtpy extension to indicate its - * support for Channel ID. */ - if (limit - ret - 4 < 0) - return NULL; - if (s->ctx->tlsext_channel_id_enabled_new) - s2n(TLSEXT_TYPE_channel_id_new,ret); - else - s2n(TLSEXT_TYPE_channel_id,ret); - s2n(0,ret); - } + /* Check for enough room 2 for extension type, 2 for len rest for + * ticket. */ + if ((long)(limit - ret - 4 - ticklen) < 0) { + return NULL; + } + s2n(TLSEXT_TYPE_session_ticket, ret); + s2n(ticklen, ret); + if (ticklen) { + memcpy(ret, s->session->tlsext_tick, ticklen); + ret += ticklen; + } + } - if(SSL_get_srtp_profiles(s)) - { - int el; + if (SSL_USE_SIGALGS(s)) { + size_t salglen; + const uint8_t *salg; + salglen = tls12_get_psigalgs(s, &salg); + if ((size_t)(limit - ret) < salglen + 6) { + return NULL; + } + s2n(TLSEXT_TYPE_signature_algorithms, ret); + s2n(salglen + 2, ret); + s2n(salglen, ret); + memcpy(ret, salg, salglen); + ret += salglen; + } - ssl_add_clienthello_use_srtp_ext(s, 0, &el, 0); - - if((limit - ret - 4 - el) < 0) return NULL; + if (s->ocsp_stapling_enabled) { + /* The status_request extension is excessively extensible at every layer. + * On the client, only support requesting OCSP responses with an empty + * responder_id_list and no extensions. */ + if (limit - ret - 4 - 1 - 2 - 2 < 0) { + return NULL; + } - s2n(TLSEXT_TYPE_use_srtp,ret); - s2n(el,ret); + s2n(TLSEXT_TYPE_status_request, ret); + s2n(1 + 2 + 2, ret); + /* status_type */ + *(ret++) = TLSEXT_STATUSTYPE_ocsp; + /* responder_id_list - empty */ + s2n(0, ret); + /* request_extensions - empty */ + s2n(0, ret); + } - if(!ssl_add_clienthello_use_srtp_ext(s, ret, &el, el)) - { - OPENSSL_PUT_ERROR(SSL, ssl_add_clienthello_tlsext, ERR_R_INTERNAL_ERROR); - return NULL; - } - ret += el; - } + if (s->ctx->next_proto_select_cb && !s->s3->tmp.finish_md_len) { + /* The client advertises an emtpy extension to indicate its support for + * Next Protocol Negotiation */ + if (limit - ret - 4 < 0) { + return NULL; + } + s2n(TLSEXT_TYPE_next_proto_neg, ret); + s2n(0, ret); + } - if (using_ecc) - { - /* Add TLS extension ECPointFormats to the ClientHello message */ - long lenmax; - const uint8_t *formats; - const uint16_t *curves; - size_t formats_len, curves_len, i; + if (s->signed_cert_timestamps_enabled && !s->s3->tmp.finish_md_len) { + /* The client advertises an empty extension to indicate its support for + * certificate timestamps. */ + if (limit - ret - 4 < 0) { + return NULL; + } + s2n(TLSEXT_TYPE_certificate_timestamp, ret); + s2n(0, ret); + } - tls1_get_formatlist(s, &formats, &formats_len); + if (s->alpn_client_proto_list && !s->s3->tmp.finish_md_len) { + if ((size_t)(limit - ret) < 6 + s->alpn_client_proto_list_len) { + return NULL; + } + s2n(TLSEXT_TYPE_application_layer_protocol_negotiation, ret); + s2n(2 + s->alpn_client_proto_list_len, ret); + s2n(s->alpn_client_proto_list_len, ret); + memcpy(ret, s->alpn_client_proto_list, s->alpn_client_proto_list_len); + ret += s->alpn_client_proto_list_len; + } - if ((lenmax = limit - ret - 5) < 0) return NULL; - if (formats_len > (size_t)lenmax) return NULL; - if (formats_len > 255) - { - OPENSSL_PUT_ERROR(SSL, ssl_add_clienthello_tlsext, ERR_R_INTERNAL_ERROR); - return NULL; - } - - s2n(TLSEXT_TYPE_ec_point_formats,ret); - s2n(formats_len + 1,ret); - *(ret++) = (unsigned char)formats_len; - memcpy(ret, formats, formats_len); - ret+=formats_len; + if (s->tlsext_channel_id_enabled) { + /* The client advertises an emtpy extension to indicate its support for + * Channel ID. */ + if (limit - ret - 4 < 0) { + return NULL; + } + if (s->ctx->tlsext_channel_id_enabled_new) { + s2n(TLSEXT_TYPE_channel_id_new, ret); + } else { + s2n(TLSEXT_TYPE_channel_id, ret); + } + s2n(0, ret); + } - /* Add TLS extension EllipticCurves to the ClientHello message */ - tls1_get_curvelist(s, 0, &curves, &curves_len); + if (SSL_get_srtp_profiles(s)) { + int el; - if ((lenmax = limit - ret - 6) < 0) return NULL; - if ((curves_len * 2) > (size_t)lenmax) return NULL; - if ((curves_len * 2) > 65532) - { - OPENSSL_PUT_ERROR(SSL, ssl_add_clienthello_tlsext, ERR_R_INTERNAL_ERROR); - return NULL; - } - - s2n(TLSEXT_TYPE_elliptic_curves,ret); - s2n((curves_len * 2) + 2, ret); + ssl_add_clienthello_use_srtp_ext(s, 0, &el, 0); - s2n(curves_len * 2, ret); - for (i = 0; i < curves_len; i++) - { - s2n(curves[i], ret); - } - } + if ((limit - ret - 4 - el) < 0) { + return NULL; + } - if (header_len > 0) - { - size_t clienthello_minsize = 0; - header_len += ret - orig; - if (header_len > 0xff && header_len < 0x200) - { - /* Add padding to workaround bugs in F5 terminators. - * See https://tools.ietf.org/html/draft-agl-tls-padding-03 - * - * NB: because this code works out the length of all existing - * extensions it MUST always appear last. */ - clienthello_minsize = 0x200; - } - if (s->fastradio_padding) - { - /* Pad the ClientHello record to 1024 bytes to fast forward - * the radio into DCH (high data rate) state in 3G networks. - * Note that when fastradio_padding is enabled, even if the - * header_len is less than 255 bytes, the padding will be - * applied regardless. This is slightly different from the TLS - * padding extension suggested in - * https://tools.ietf.org/html/draft-agl-tls-padding-03 */ - clienthello_minsize = 0x400; - } - if (header_len < clienthello_minsize) - { - size_t padding_len = clienthello_minsize - header_len; - /* Extensions take at least four bytes to encode. Always - * include least one byte of data if including the - * extension. WebSphere Application Server 7.0 is - * intolerant to the last extension being zero-length. */ - if (padding_len >= 4 + 1) - padding_len -= 4; - else - padding_len = 1; - if (limit - ret - 4 - (long)padding_len < 0) - return NULL; + s2n(TLSEXT_TYPE_use_srtp, ret); + s2n(el, ret); - s2n(TLSEXT_TYPE_padding, ret); - s2n(padding_len, ret); - memset(ret, 0, padding_len); - ret += padding_len; - } - } + if (!ssl_add_clienthello_use_srtp_ext(s, ret, &el, el)) { + OPENSSL_PUT_ERROR(SSL, ssl_add_clienthello_tlsext, ERR_R_INTERNAL_ERROR); + return NULL; + } + ret += el; + } - if ((extdatalen = ret-orig-2)== 0) - return orig; + if (using_ecc) { + /* Add TLS extension ECPointFormats to the ClientHello message */ + long lenmax; + const uint8_t *formats; + const uint16_t *curves; + size_t formats_len, curves_len, i; - s2n(extdatalen, orig); - return ret; - } + tls1_get_formatlist(s, &formats, &formats_len); -unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned char *limit) - { - int extdatalen=0; - unsigned char *orig = buf; - unsigned char *ret = buf; - int next_proto_neg_seen; - unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; - unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth; - int using_ecc = (alg_k & SSL_kEECDH) || (alg_a & SSL_aECDSA); - using_ecc = using_ecc && (s->s3->tmp.peer_ecpointformatlist != NULL); - /* don't add extensions for SSLv3, unless doing secure renegotiation */ - if (s->version == SSL3_VERSION && !s->s3->send_connection_binding) - return orig; - - ret+=2; - if (ret>=limit) return NULL; /* this really never occurs, but ... */ + lenmax = limit - ret - 5; + if (lenmax < 0) { + return NULL; + } + if (formats_len > (size_t)lenmax) { + return NULL; + } + if (formats_len > 255) { + OPENSSL_PUT_ERROR(SSL, ssl_add_clienthello_tlsext, ERR_R_INTERNAL_ERROR); + return NULL; + } - if (!s->hit && s->should_ack_sni && s->session->tlsext_hostname != NULL) - { - if ((long)(limit - ret - 4) < 0) return NULL; + s2n(TLSEXT_TYPE_ec_point_formats, ret); + s2n(formats_len + 1, ret); + *(ret++) = (uint8_t)formats_len; + memcpy(ret, formats, formats_len); + ret += formats_len; - s2n(TLSEXT_TYPE_server_name,ret); - s2n(0,ret); - } + /* Add TLS extension EllipticCurves to the ClientHello message */ + tls1_get_curvelist(s, 0, &curves, &curves_len); - if(s->s3->send_connection_binding) - { - int el; - - if(!ssl_add_serverhello_renegotiate_ext(s, 0, &el, 0)) - { - OPENSSL_PUT_ERROR(SSL, ssl_add_serverhello_tlsext, ERR_R_INTERNAL_ERROR); - return NULL; - } + lenmax = limit - ret - 6; + if (lenmax < 0) { + return NULL; + } + if (curves_len * 2 > (size_t)lenmax) { + return NULL; + } + if (curves_len * 2 > 65532) { + OPENSSL_PUT_ERROR(SSL, ssl_add_clienthello_tlsext, ERR_R_INTERNAL_ERROR); + return NULL; + } - if((limit - ret - 4 - el) < 0) return NULL; - - s2n(TLSEXT_TYPE_renegotiate,ret); - s2n(el,ret); + s2n(TLSEXT_TYPE_elliptic_curves, ret); + s2n((curves_len * 2) + 2, ret); - if(!ssl_add_serverhello_renegotiate_ext(s, ret, &el, el)) - { - OPENSSL_PUT_ERROR(SSL, ssl_add_serverhello_tlsext, ERR_R_INTERNAL_ERROR); - return NULL; - } + s2n(curves_len * 2, ret); + for (i = 0; i < curves_len; i++) { + s2n(curves[i], ret); + } + } - ret += el; - } + if (header_len > 0) { + size_t clienthello_minsize = 0; + header_len += ret - orig; + if (header_len > 0xff && header_len < 0x200) { + /* Add padding to workaround bugs in F5 terminators. See + * https://tools.ietf.org/html/draft-agl-tls-padding-03 + * + * NB: because this code works out the length of all existing extensions + * it MUST always appear last. */ + clienthello_minsize = 0x200; + } + if (s->fastradio_padding) { + /* Pad the ClientHello record to 1024 bytes to fast forward the radio + * into DCH (high data rate) state in 3G networks. Note that when + * fastradio_padding is enabled, even if the header_len is less than 255 + * bytes, the padding will be applied regardless. This is slightly + * different from the TLS padding extension suggested in + * https://tools.ietf.org/html/draft-agl-tls-padding-03 */ + clienthello_minsize = 0x400; + } + if (header_len < clienthello_minsize) { + size_t padding_len = clienthello_minsize - header_len; + /* Extensions take at least four bytes to encode. Always include least + * one byte of data if including the extension. WebSphere Application + * Server 7.0 is intolerant to the last extension being zero-length. */ + if (padding_len >= 4 + 1) { + padding_len -= 4; + } else { + padding_len = 1; + } - if (s->s3->tmp.extended_master_secret) - { - if ((long)(limit - ret - 4) < 0) return NULL; + if (limit - ret - 4 - (long)padding_len < 0) { + return NULL; + } - s2n(TLSEXT_TYPE_extended_master_secret,ret); - s2n(0,ret); - } + s2n(TLSEXT_TYPE_padding, ret); + s2n(padding_len, ret); + memset(ret, 0, padding_len); + ret += padding_len; + } + } - if (using_ecc) - { - const unsigned char *plist; - size_t plistlen; - /* Add TLS extension ECPointFormats to the ServerHello message */ - long lenmax; + extdatalen = ret - orig - 2; + if (extdatalen == 0) { + return orig; + } - tls1_get_formatlist(s, &plist, &plistlen); + s2n(extdatalen, orig); + return ret; +} - if ((lenmax = limit - ret - 5) < 0) return NULL; - if (plistlen > (size_t)lenmax) return NULL; - if (plistlen > 255) - { - OPENSSL_PUT_ERROR(SSL, ssl_add_serverhello_tlsext, ERR_R_INTERNAL_ERROR); - return NULL; - } - - s2n(TLSEXT_TYPE_ec_point_formats,ret); - s2n(plistlen + 1,ret); - *(ret++) = (unsigned char) plistlen; - memcpy(ret, plist, plistlen); - ret+=plistlen; +uint8_t *ssl_add_serverhello_tlsext(SSL *s, uint8_t *buf, uint8_t *limit) { + int extdatalen = 0; + uint8_t *orig = buf; + uint8_t *ret = buf; + int next_proto_neg_seen; + unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth; + int using_ecc = (alg_k & SSL_kEECDH) || (alg_a & SSL_aECDSA); + using_ecc = using_ecc && (s->s3->tmp.peer_ecpointformatlist != NULL); - } - /* Currently the server should not respond with a SupportedCurves extension */ + /* don't add extensions for SSLv3, unless doing secure renegotiation */ + if (s->version == SSL3_VERSION && !s->s3->send_connection_binding) { + return orig; + } - if (s->tlsext_ticket_expected - && !(SSL_get_options(s) & SSL_OP_NO_TICKET)) - { - if ((long)(limit - ret - 4) < 0) return NULL; - s2n(TLSEXT_TYPE_session_ticket,ret); - s2n(0,ret); - } + ret += 2; + if (ret >= limit) { + return NULL; /* should never happen. */ + } - if (s->s3->tmp.certificate_status_expected) - { - if ((long)(limit - ret - 4) < 0) return NULL; - s2n(TLSEXT_TYPE_status_request,ret); - s2n(0,ret); - } + if (!s->hit && s->should_ack_sni && s->session->tlsext_hostname != NULL) { + if ((long)(limit - ret - 4) < 0) { + return NULL; + } - if(s->srtp_profile) - { - int el; + s2n(TLSEXT_TYPE_server_name, ret); + s2n(0, ret); + } - ssl_add_serverhello_use_srtp_ext(s, 0, &el, 0); - - if((limit - ret - 4 - el) < 0) return NULL; + if (s->s3->send_connection_binding) { + int el; - s2n(TLSEXT_TYPE_use_srtp,ret); - s2n(el,ret); + if (!ssl_add_serverhello_renegotiate_ext(s, 0, &el, 0)) { + OPENSSL_PUT_ERROR(SSL, ssl_add_serverhello_tlsext, ERR_R_INTERNAL_ERROR); + return NULL; + } - if(!ssl_add_serverhello_use_srtp_ext(s, ret, &el, el)) - { - OPENSSL_PUT_ERROR(SSL, ssl_add_serverhello_tlsext, ERR_R_INTERNAL_ERROR); - return NULL; - } - ret+=el; - } + if ((limit - ret - 4 - el) < 0) { + return NULL; + } - next_proto_neg_seen = s->s3->next_proto_neg_seen; - s->s3->next_proto_neg_seen = 0; - if (next_proto_neg_seen && s->ctx->next_protos_advertised_cb) - { - const unsigned char *npa; - unsigned int npalen; - int r; + s2n(TLSEXT_TYPE_renegotiate, ret); + s2n(el, ret); - r = s->ctx->next_protos_advertised_cb(s, &npa, &npalen, s->ctx->next_protos_advertised_cb_arg); - if (r == SSL_TLSEXT_ERR_OK) - { - if ((long)(limit - ret - 4 - npalen) < 0) return NULL; - s2n(TLSEXT_TYPE_next_proto_neg,ret); - s2n(npalen,ret); - memcpy(ret, npa, npalen); - ret += npalen; - s->s3->next_proto_neg_seen = 1; - } - } + if (!ssl_add_serverhello_renegotiate_ext(s, ret, &el, el)) { + OPENSSL_PUT_ERROR(SSL, ssl_add_serverhello_tlsext, ERR_R_INTERNAL_ERROR); + return NULL; + } - if (s->s3->alpn_selected) - { - const uint8_t *selected = s->s3->alpn_selected; - size_t len = s->s3->alpn_selected_len; + ret += el; + } - if ((long)(limit - ret - 4 - 2 - 1 - len) < 0) - return NULL; - s2n(TLSEXT_TYPE_application_layer_protocol_negotiation,ret); - s2n(3 + len,ret); - s2n(1 + len,ret); - *ret++ = len; - memcpy(ret, selected, len); - ret += len; - } + if (s->s3->tmp.extended_master_secret) { + if ((long)(limit - ret - 4) < 0) { + return NULL; + } - /* If the client advertised support for Channel ID, and we have it - * enabled, then we want to echo it back. */ - if (s->s3->tlsext_channel_id_valid) - { - if (limit - ret - 4 < 0) - return NULL; - if (s->s3->tlsext_channel_id_new) - s2n(TLSEXT_TYPE_channel_id_new,ret); - else - s2n(TLSEXT_TYPE_channel_id,ret); - s2n(0,ret); - } + s2n(TLSEXT_TYPE_extended_master_secret, ret); + s2n(0, ret); + } - if ((extdatalen = ret-orig-2) == 0) - return orig; + if (using_ecc) { + const uint8_t *plist; + size_t plistlen; + /* Add TLS extension ECPointFormats to the ServerHello message */ + long lenmax; - s2n(extdatalen, orig); - return ret; - } + tls1_get_formatlist(s, &plist, &plistlen); + + lenmax = limit - ret - 5; + if (lenmax < 0) { + return NULL; + } + if (plistlen > (size_t)lenmax) { + return NULL; + } + if (plistlen > 255) { + OPENSSL_PUT_ERROR(SSL, ssl_add_serverhello_tlsext, ERR_R_INTERNAL_ERROR); + return NULL; + } + + s2n(TLSEXT_TYPE_ec_point_formats, ret); + s2n(plistlen + 1, ret); + *(ret++) = (uint8_t)plistlen; + memcpy(ret, plist, plistlen); + ret += plistlen; + } + /* Currently the server should not respond with a SupportedCurves extension */ + + if (s->tlsext_ticket_expected && !(SSL_get_options(s) & SSL_OP_NO_TICKET)) { + if ((long)(limit - ret - 4) < 0) { + return NULL; + } + s2n(TLSEXT_TYPE_session_ticket, ret); + s2n(0, ret); + } + + if (s->s3->tmp.certificate_status_expected) { + if ((long)(limit - ret - 4) < 0) { + return NULL; + } + s2n(TLSEXT_TYPE_status_request, ret); + s2n(0, ret); + } + + if (s->srtp_profile) { + int el; + + ssl_add_serverhello_use_srtp_ext(s, 0, &el, 0); + + if ((limit - ret - 4 - el) < 0) { + return NULL; + } + + s2n(TLSEXT_TYPE_use_srtp, ret); + s2n(el, ret); + + if (!ssl_add_serverhello_use_srtp_ext(s, ret, &el, el)) { + OPENSSL_PUT_ERROR(SSL, ssl_add_serverhello_tlsext, ERR_R_INTERNAL_ERROR); + return NULL; + } + ret += el; + } + + next_proto_neg_seen = s->s3->next_proto_neg_seen; + s->s3->next_proto_neg_seen = 0; + if (next_proto_neg_seen && s->ctx->next_protos_advertised_cb) { + const uint8_t *npa; + unsigned int npalen; + int r; + + r = s->ctx->next_protos_advertised_cb( + s, &npa, &npalen, s->ctx->next_protos_advertised_cb_arg); + if (r == SSL_TLSEXT_ERR_OK) { + if ((long)(limit - ret - 4 - npalen) < 0) { + return NULL; + } + s2n(TLSEXT_TYPE_next_proto_neg, ret); + s2n(npalen, ret); + memcpy(ret, npa, npalen); + ret += npalen; + s->s3->next_proto_neg_seen = 1; + } + } + + if (s->s3->alpn_selected) { + const uint8_t *selected = s->s3->alpn_selected; + size_t len = s->s3->alpn_selected_len; + + if ((long)(limit - ret - 4 - 2 - 1 - len) < 0) { + return NULL; + } + s2n(TLSEXT_TYPE_application_layer_protocol_negotiation, ret); + s2n(3 + len, ret); + s2n(1 + len, ret); + *ret++ = len; + memcpy(ret, selected, len); + ret += len; + } + + /* If the client advertised support for Channel ID, and we have it + * enabled, then we want to echo it back. */ + if (s->s3->tlsext_channel_id_valid) { + if (limit - ret - 4 < 0) { + return NULL; + } + if (s->s3->tlsext_channel_id_new) { + s2n(TLSEXT_TYPE_channel_id_new, ret); + } else { + s2n(TLSEXT_TYPE_channel_id, ret); + } + s2n(0, ret); + } + + extdatalen = ret - orig - 2; + if (extdatalen == 0) { + return orig; + } + + s2n(extdatalen, orig); + return ret; +} /* tls1_alpn_handle_client_hello is called to process the ALPN extension in a * ClientHello. @@ -1366,875 +1342,739 @@ * return. * * returns: 1 on success. */ -static int tls1_alpn_handle_client_hello(SSL *s, CBS *cbs, int *out_alert) - { - CBS protocol_name_list, protocol_name_list_copy; - const unsigned char *selected; - unsigned char selected_len; - int r; +static int tls1_alpn_handle_client_hello(SSL *s, CBS *cbs, int *out_alert) { + CBS protocol_name_list, protocol_name_list_copy; + const uint8_t *selected; + uint8_t selected_len; + int r; - if (s->ctx->alpn_select_cb == NULL) - return 1; + if (s->ctx->alpn_select_cb == NULL) { + return 1; + } - if (!CBS_get_u16_length_prefixed(cbs, &protocol_name_list) || - CBS_len(cbs) != 0 || - CBS_len(&protocol_name_list) < 2) - goto parse_error; + if (!CBS_get_u16_length_prefixed(cbs, &protocol_name_list) || + CBS_len(cbs) != 0 || CBS_len(&protocol_name_list) < 2) { + goto parse_error; + } - /* Validate the protocol list. */ - protocol_name_list_copy = protocol_name_list; - while (CBS_len(&protocol_name_list_copy) > 0) - { - CBS protocol_name; + /* Validate the protocol list. */ + protocol_name_list_copy = protocol_name_list; + while (CBS_len(&protocol_name_list_copy) > 0) { + CBS protocol_name; - if (!CBS_get_u8_length_prefixed(&protocol_name_list_copy, &protocol_name)) - goto parse_error; - } + if (!CBS_get_u8_length_prefixed(&protocol_name_list_copy, &protocol_name)) { + goto parse_error; + } + } - r = s->ctx->alpn_select_cb(s, &selected, &selected_len, - CBS_data(&protocol_name_list), CBS_len(&protocol_name_list), - s->ctx->alpn_select_cb_arg); - if (r == SSL_TLSEXT_ERR_OK) { - if (s->s3->alpn_selected) - OPENSSL_free(s->s3->alpn_selected); - s->s3->alpn_selected = BUF_memdup(selected, selected_len); - if (!s->s3->alpn_selected) - { - *out_alert = SSL_AD_INTERNAL_ERROR; - return 0; - } - s->s3->alpn_selected_len = selected_len; - } - return 1; + r = s->ctx->alpn_select_cb( + s, &selected, &selected_len, CBS_data(&protocol_name_list), + CBS_len(&protocol_name_list), s->ctx->alpn_select_cb_arg); + if (r == SSL_TLSEXT_ERR_OK) { + if (s->s3->alpn_selected) { + OPENSSL_free(s->s3->alpn_selected); + } + s->s3->alpn_selected = BUF_memdup(selected, selected_len); + if (!s->s3->alpn_selected) { + *out_alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + s->s3->alpn_selected_len = selected_len; + } + + return 1; parse_error: - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } + *out_alert = SSL_AD_DECODE_ERROR; + return 0; +} -static int ssl_scan_clienthello_tlsext(SSL *s, CBS *cbs, int *out_alert) - { - int renegotiate_seen = 0; - CBS extensions; +static int ssl_scan_clienthello_tlsext(SSL *s, CBS *cbs, int *out_alert) { + int renegotiate_seen = 0; + CBS extensions; - s->should_ack_sni = 0; - s->s3->next_proto_neg_seen = 0; - s->s3->tmp.certificate_status_expected = 0; - s->s3->tmp.extended_master_secret = 0; + s->should_ack_sni = 0; + s->s3->next_proto_neg_seen = 0; + s->s3->tmp.certificate_status_expected = 0; + s->s3->tmp.extended_master_secret = 0; - if (s->s3->alpn_selected) - { - OPENSSL_free(s->s3->alpn_selected); - s->s3->alpn_selected = NULL; - } + if (s->s3->alpn_selected) { + OPENSSL_free(s->s3->alpn_selected); + s->s3->alpn_selected = NULL; + } - /* Clear any signature algorithms extension received */ - if (s->cert->peer_sigalgs) - { - OPENSSL_free(s->cert->peer_sigalgs); - s->cert->peer_sigalgs = NULL; - } - /* Clear any shared signature algorithms */ - if (s->cert->shared_sigalgs) - { - OPENSSL_free(s->cert->shared_sigalgs); - s->cert->shared_sigalgs = NULL; - } - /* Clear ECC extensions */ - if (s->s3->tmp.peer_ecpointformatlist != 0) - { - OPENSSL_free(s->s3->tmp.peer_ecpointformatlist); - s->s3->tmp.peer_ecpointformatlist = NULL; - s->s3->tmp.peer_ecpointformatlist_length = 0; - } - if (s->s3->tmp.peer_ellipticcurvelist != 0) - { - OPENSSL_free(s->s3->tmp.peer_ellipticcurvelist); - s->s3->tmp.peer_ellipticcurvelist = NULL; - s->s3->tmp.peer_ellipticcurvelist_length = 0; - } + /* Clear any signature algorithms extension received */ + if (s->cert->peer_sigalgs) { + OPENSSL_free(s->cert->peer_sigalgs); + s->cert->peer_sigalgs = NULL; + } - /* There may be no extensions. */ - if (CBS_len(cbs) == 0) - { - goto ri_check; - } + /* Clear any shared signature algorithms */ + if (s->cert->shared_sigalgs) { + OPENSSL_free(s->cert->shared_sigalgs); + s->cert->shared_sigalgs = NULL; + } - /* Decode the extensions block and check it is valid. */ - if (!CBS_get_u16_length_prefixed(cbs, &extensions) || - !tls1_check_duplicate_extensions(&extensions)) - { - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } + /* Clear ECC extensions */ + if (s->s3->tmp.peer_ecpointformatlist != 0) { + OPENSSL_free(s->s3->tmp.peer_ecpointformatlist); + s->s3->tmp.peer_ecpointformatlist = NULL; + s->s3->tmp.peer_ecpointformatlist_length = 0; + } - while (CBS_len(&extensions) != 0) - { - uint16_t type; - CBS extension; + if (s->s3->tmp.peer_ellipticcurvelist != 0) { + OPENSSL_free(s->s3->tmp.peer_ellipticcurvelist); + s->s3->tmp.peer_ellipticcurvelist = NULL; + s->s3->tmp.peer_ellipticcurvelist_length = 0; + } - /* Decode the next extension. */ - if (!CBS_get_u16(&extensions, &type) || - !CBS_get_u16_length_prefixed(&extensions, &extension)) - { - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } + /* There may be no extensions. */ + if (CBS_len(cbs) == 0) { + goto ri_check; + } - if (s->tlsext_debug_cb) - { - s->tlsext_debug_cb(s, 0, type, (unsigned char*)CBS_data(&extension), - CBS_len(&extension), s->tlsext_debug_arg); - } + /* Decode the extensions block and check it is valid. */ + if (!CBS_get_u16_length_prefixed(cbs, &extensions) || + !tls1_check_duplicate_extensions(&extensions)) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } -/* The servername extension is treated as follows: + while (CBS_len(&extensions) != 0) { + uint16_t type; + CBS extension; - - Only the hostname type is supported with a maximum length of 255. - - The servername is rejected if too long or if it contains zeros, - in which case an fatal alert is generated. - - The servername field is maintained together with the session cache. - - When a session is resumed, the servername call back invoked in order - to allow the application to position itself to the right context. - - The servername is acknowledged if it is new for a session or when - it is identical to a previously used for the same session. - Applications can control the behaviour. They can at any time - set a 'desirable' servername for a new SSL object. This can be the - case for example with HTTPS when a Host: header field is received and - a renegotiation is requested. In this case, a possible servername - presented in the new client hello is only acknowledged if it matches - the value of the Host: field. - - Applications must use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION - if they provide for changing an explicit servername context for the session, - i.e. when the session has been established with a servername extension. - - On session reconnect, the servername extension may be absent. + /* Decode the next extension. */ + if (!CBS_get_u16(&extensions, &type) || + !CBS_get_u16_length_prefixed(&extensions, &extension)) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } -*/ + if (s->tlsext_debug_cb) { + s->tlsext_debug_cb(s, 0, type, (uint8_t *)CBS_data(&extension), + CBS_len(&extension), s->tlsext_debug_arg); + } - if (type == TLSEXT_TYPE_server_name) - { - CBS server_name_list; - char have_seen_host_name = 0; + /* The servername extension is treated as follows: - if (!CBS_get_u16_length_prefixed(&extension, &server_name_list) || - CBS_len(&server_name_list) < 1 || - CBS_len(&extension) != 0) - { - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } + - Only the hostname type is supported with a maximum length of 255. + - The servername is rejected if too long or if it contains zeros, in + which case an fatal alert is generated. + - The servername field is maintained together with the session cache. + - When a session is resumed, the servername call back invoked in order + to allow the application to position itself to the right context. + - The servername is acknowledged if it is new for a session or when + it is identical to a previously used for the same session. + Applications can control the behaviour. They can at any time + set a 'desirable' servername for a new SSL object. This can be the + case for example with HTTPS when a Host: header field is received and + a renegotiation is requested. In this case, a possible servername + presented in the new client hello is only acknowledged if it matches + the value of the Host: field. + - Applications must use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION + if they provide for changing an explicit servername context for the + session, + i.e. when the session has been established with a servername extension. + - On session reconnect, the servername extension may be absent. */ - /* Decode each ServerName in the extension. */ - while (CBS_len(&server_name_list) > 0) - { - uint8_t name_type; - CBS host_name; + if (type == TLSEXT_TYPE_server_name) { + CBS server_name_list; + char have_seen_host_name = 0; - /* Decode the NameType. */ - if (!CBS_get_u8(&server_name_list, &name_type)) - { - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } + if (!CBS_get_u16_length_prefixed(&extension, &server_name_list) || + CBS_len(&server_name_list) < 1 || CBS_len(&extension) != 0) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } - /* Only host_name is supported. */ - if (name_type != TLSEXT_NAMETYPE_host_name) - continue; + /* Decode each ServerName in the extension. */ + while (CBS_len(&server_name_list) > 0) { + uint8_t name_type; + CBS host_name; - if (have_seen_host_name) - { - /* The ServerNameList MUST NOT contain - * more than one name of the same - * name_type. */ - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } + /* Decode the NameType. */ + if (!CBS_get_u8(&server_name_list, &name_type)) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } - have_seen_host_name = 1; + /* Only host_name is supported. */ + if (name_type != TLSEXT_NAMETYPE_host_name) { + continue; + } - if (!CBS_get_u16_length_prefixed(&server_name_list, &host_name) || - CBS_len(&host_name) < 1) - { - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } + if (have_seen_host_name) { + /* The ServerNameList MUST NOT contain more than one name of the same + * name_type. */ + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } - if (CBS_len(&host_name) > TLSEXT_MAXLEN_host_name || - CBS_contains_zero_byte(&host_name)) - { - *out_alert = SSL_AD_UNRECOGNIZED_NAME; - return 0; - } + have_seen_host_name = 1; - if (!s->hit) - { - assert(s->session->tlsext_hostname == NULL); - if (s->session->tlsext_hostname) - { - /* This should be impossible. */ - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } + if (!CBS_get_u16_length_prefixed(&server_name_list, &host_name) || + CBS_len(&host_name) < 1) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } - /* Copy the hostname as a string. */ - if (!CBS_strdup(&host_name, &s->session->tlsext_hostname)) - { - *out_alert = SSL_AD_INTERNAL_ERROR; - return 0; - } + if (CBS_len(&host_name) > TLSEXT_MAXLEN_host_name || + CBS_contains_zero_byte(&host_name)) { + *out_alert = SSL_AD_UNRECOGNIZED_NAME; + return 0; + } - s->should_ack_sni = 1; - } - } - } + if (!s->hit) { + assert(s->session->tlsext_hostname == NULL); + if (s->session->tlsext_hostname) { + /* This should be impossible. */ + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } - else if (type == TLSEXT_TYPE_ec_point_formats) - { - CBS ec_point_format_list; + /* Copy the hostname as a string. */ + if (!CBS_strdup(&host_name, &s->session->tlsext_hostname)) { + *out_alert = SSL_AD_INTERNAL_ERROR; + return 0; + } - if (!CBS_get_u8_length_prefixed(&extension, &ec_point_format_list) || - CBS_len(&extension) != 0) - { - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } + s->should_ack_sni = 1; + } + } + } else if (type == TLSEXT_TYPE_ec_point_formats) { + CBS ec_point_format_list; - if (!CBS_stow(&ec_point_format_list, - &s->s3->tmp.peer_ecpointformatlist, - &s->s3->tmp.peer_ecpointformatlist_length)) - { - *out_alert = SSL_AD_INTERNAL_ERROR; - return 0; - } - } - else if (type == TLSEXT_TYPE_elliptic_curves) - { - CBS elliptic_curve_list; - size_t i, num_curves; + if (!CBS_get_u8_length_prefixed(&extension, &ec_point_format_list) || + CBS_len(&extension) != 0) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } - if (!CBS_get_u16_length_prefixed(&extension, &elliptic_curve_list) || - CBS_len(&elliptic_curve_list) == 0 || - (CBS_len(&elliptic_curve_list) & 1) != 0 || - CBS_len(&extension) != 0) - { - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } + if (!CBS_stow(&ec_point_format_list, &s->s3->tmp.peer_ecpointformatlist, + &s->s3->tmp.peer_ecpointformatlist_length)) { + *out_alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + } else if (type == TLSEXT_TYPE_elliptic_curves) { + CBS elliptic_curve_list; + size_t i, num_curves; - if (s->s3->tmp.peer_ellipticcurvelist) - { - OPENSSL_free(s->s3->tmp.peer_ellipticcurvelist); - s->s3->tmp.peer_ellipticcurvelist_length = 0; - } - s->s3->tmp.peer_ellipticcurvelist = - (uint16_t*)OPENSSL_malloc(CBS_len(&elliptic_curve_list)); - if (s->s3->tmp.peer_ellipticcurvelist == NULL) - { - *out_alert = SSL_AD_INTERNAL_ERROR; - return 0; - } - num_curves = CBS_len(&elliptic_curve_list) / 2; - for (i = 0; i < num_curves; i++) - { - if (!CBS_get_u16(&elliptic_curve_list, - &s->s3->tmp.peer_ellipticcurvelist[i])) - { - *out_alert = SSL_AD_INTERNAL_ERROR; - return 0; - } - } - if (CBS_len(&elliptic_curve_list) != 0) - { - *out_alert = SSL_AD_INTERNAL_ERROR; - return 0; - } - s->s3->tmp.peer_ellipticcurvelist_length = num_curves; - } - else if (type == TLSEXT_TYPE_renegotiate) - { - if (!ssl_parse_clienthello_renegotiate_ext(s, &extension, out_alert)) - return 0; - renegotiate_seen = 1; - } - else if (type == TLSEXT_TYPE_signature_algorithms) - { - CBS supported_signature_algorithms; + if (!CBS_get_u16_length_prefixed(&extension, &elliptic_curve_list) || + CBS_len(&elliptic_curve_list) == 0 || + (CBS_len(&elliptic_curve_list) & 1) != 0 || + CBS_len(&extension) != 0) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } - if (!CBS_get_u16_length_prefixed(&extension, &supported_signature_algorithms) || - CBS_len(&extension) != 0) - { - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } + if (s->s3->tmp.peer_ellipticcurvelist) { + OPENSSL_free(s->s3->tmp.peer_ellipticcurvelist); + s->s3->tmp.peer_ellipticcurvelist_length = 0; + } - /* Ensure the signature algorithms are non-empty. It - * contains a list of SignatureAndHashAlgorithms - * which are two bytes each. */ - if (CBS_len(&supported_signature_algorithms) == 0 || - (CBS_len(&supported_signature_algorithms) % 2) != 0) - { - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } + s->s3->tmp.peer_ellipticcurvelist = + (uint16_t *)OPENSSL_malloc(CBS_len(&elliptic_curve_list)); - if (!tls1_process_sigalgs(s, &supported_signature_algorithms)) - { - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } - /* If sigalgs received and no shared algorithms fatal - * error. - */ - if (s->cert->peer_sigalgs && !s->cert->shared_sigalgs) - { - OPENSSL_PUT_ERROR(SSL, ssl_add_serverhello_tlsext, SSL_R_NO_SHARED_SIGATURE_ALGORITHMS); - *out_alert = SSL_AD_ILLEGAL_PARAMETER; - return 0; - } - } + if (s->s3->tmp.peer_ellipticcurvelist == NULL) { + *out_alert = SSL_AD_INTERNAL_ERROR; + return 0; + } - else if (type == TLSEXT_TYPE_next_proto_neg && - s->s3->tmp.finish_md_len == 0 && - s->s3->alpn_selected == NULL) - { - /* The extension must be empty. */ - if (CBS_len(&extension) != 0) - { - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } + num_curves = CBS_len(&elliptic_curve_list) / 2; + for (i = 0; i < num_curves; i++) { + if (!CBS_get_u16(&elliptic_curve_list, + &s->s3->tmp.peer_ellipticcurvelist[i])) { + *out_alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + } - /* We shouldn't accept this extension on a - * renegotiation. - * - * s->new_session will be set on renegotiation, but we - * probably shouldn't rely that it couldn't be set on - * the initial renegotation too in certain cases (when - * there's some other reason to disallow resuming an - * earlier session -- the current code won't be doing - * anything like that, but this might change). + if (CBS_len(&elliptic_curve_list) != 0) { + *out_alert = SSL_AD_INTERNAL_ERROR; + return 0; + } - * A valid sign that there's been a previous handshake - * in this connection is if s->s3->tmp.finish_md_len > - * 0. (We are talking about a check that will happen - * in the Hello protocol round, well before a new - * Finished message could have been computed.) */ - s->s3->next_proto_neg_seen = 1; - } + s->s3->tmp.peer_ellipticcurvelist_length = num_curves; + } else if (type == TLSEXT_TYPE_renegotiate) { + if (!ssl_parse_clienthello_renegotiate_ext(s, &extension, out_alert)) { + return 0; + } + renegotiate_seen = 1; + } else if (type == TLSEXT_TYPE_signature_algorithms) { + CBS supported_signature_algorithms; - else if (type == TLSEXT_TYPE_application_layer_protocol_negotiation && - s->ctx->alpn_select_cb && - s->s3->tmp.finish_md_len == 0) - { - if (!tls1_alpn_handle_client_hello(s, &extension, out_alert)) - return 0; - /* ALPN takes precedence over NPN. */ - s->s3->next_proto_neg_seen = 0; - } + if (!CBS_get_u16_length_prefixed(&extension, + &supported_signature_algorithms) || + CBS_len(&extension) != 0) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } - else if (type == TLSEXT_TYPE_channel_id && - s->tlsext_channel_id_enabled) - { - /* The extension must be empty. */ - if (CBS_len(&extension) != 0) - { - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } + /* Ensure the signature algorithms are non-empty. It contains a list of + * SignatureAndHashAlgorithms which are two bytes each. */ + if (CBS_len(&supported_signature_algorithms) == 0 || + (CBS_len(&supported_signature_algorithms) % 2) != 0) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } - s->s3->tlsext_channel_id_valid = 1; - } + if (!tls1_process_sigalgs(s, &supported_signature_algorithms)) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } + /* If sigalgs received and no shared algorithms fatal error. */ + if (s->cert->peer_sigalgs && !s->cert->shared_sigalgs) { + OPENSSL_PUT_ERROR(SSL, ssl_add_serverhello_tlsext, + SSL_R_NO_SHARED_SIGATURE_ALGORITHMS); + *out_alert = SSL_AD_ILLEGAL_PARAMETER; + return 0; + } + } else if (type == TLSEXT_TYPE_next_proto_neg && + s->s3->tmp.finish_md_len == 0 && s->s3->alpn_selected == NULL) { + /* The extension must be empty. */ + if (CBS_len(&extension) != 0) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } - else if (type == TLSEXT_TYPE_channel_id_new && - s->tlsext_channel_id_enabled) - { - /* The extension must be empty. */ - if (CBS_len(&extension) != 0) - { - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } + /* We shouldn't accept this extension on a renegotiation. + * + * s->new_session will be set on renegotiation, but we probably shouldn't + * rely that it couldn't be set on the initial renegotation too in + * certain cases (when there's some other reason to disallow resuming an + * earlier session -- the current code won't be doing anything like that, + * but this might change). - s->s3->tlsext_channel_id_valid = 1; - s->s3->tlsext_channel_id_new = 1; - } + * A valid sign that there's been a previous handshake in this connection + * is if s->s3->tmp.finish_md_len > 0. (We are talking about a check + * that will happen in the Hello protocol round, well before a new + * Finished message could have been computed.) */ + s->s3->next_proto_neg_seen = 1; + } else if (type == TLSEXT_TYPE_application_layer_protocol_negotiation && + s->ctx->alpn_select_cb && s->s3->tmp.finish_md_len == 0) { + if (!tls1_alpn_handle_client_hello(s, &extension, out_alert)) { + return 0; + } + /* ALPN takes precedence over NPN. */ + s->s3->next_proto_neg_seen = 0; + } else if (type == TLSEXT_TYPE_channel_id && s->tlsext_channel_id_enabled) { + /* The extension must be empty. */ + if (CBS_len(&extension) != 0) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } + s->s3->tlsext_channel_id_valid = 1; + } else if (type == TLSEXT_TYPE_channel_id_new && + s->tlsext_channel_id_enabled) { + /* The extension must be empty. */ + if (CBS_len(&extension) != 0) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } - /* session ticket processed earlier */ - else if (type == TLSEXT_TYPE_use_srtp) - { - if (!ssl_parse_clienthello_use_srtp_ext(s, &extension, out_alert)) - return 0; - } + s->s3->tlsext_channel_id_valid = 1; + s->s3->tlsext_channel_id_new = 1; + } else if (type == TLSEXT_TYPE_use_srtp) { + if (!ssl_parse_clienthello_use_srtp_ext(s, &extension, out_alert)) { + return 0; + } + } else if (type == TLSEXT_TYPE_extended_master_secret && + s->version != SSL3_VERSION) { + if (CBS_len(&extension) != 0) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } - else if (type == TLSEXT_TYPE_extended_master_secret && - s->version != SSL3_VERSION) - { - if (CBS_len(&extension) != 0) - { - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } + s->s3->tmp.extended_master_secret = 1; + } + } - s->s3->tmp.extended_master_secret = 1; - } - } +ri_check: + /* Need RI if renegotiating */ - ri_check: + if (!renegotiate_seen && s->renegotiate && + !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) { + *out_alert = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, ssl_scan_clienthello_tlsext, + SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); + return 0; + } - /* Need RI if renegotiating */ + return 1; +} - if (!renegotiate_seen && s->renegotiate && - !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) - { - *out_alert = SSL_AD_HANDSHAKE_FAILURE; - OPENSSL_PUT_ERROR(SSL, ssl_scan_clienthello_tlsext, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); - return 0; - } +int ssl_parse_clienthello_tlsext(SSL *s, CBS *cbs) { + int alert = -1; + if (ssl_scan_clienthello_tlsext(s, cbs, &alert) <= 0) { + ssl3_send_alert(s, SSL3_AL_FATAL, alert); + return 0; + } - return 1; - } + if (ssl_check_clienthello_tlsext(s) <= 0) { + OPENSSL_PUT_ERROR(SSL, ssl_parse_clienthello_tlsext, + SSL_R_CLIENTHELLO_TLSEXT); + return 0; + } -int ssl_parse_clienthello_tlsext(SSL *s, CBS *cbs) - { - int alert = -1; - if (ssl_scan_clienthello_tlsext(s, cbs, &alert) <= 0) - { - ssl3_send_alert(s, SSL3_AL_FATAL, alert); - return 0; - } - - if (ssl_check_clienthello_tlsext(s) <= 0) - { - OPENSSL_PUT_ERROR(SSL, ssl_parse_clienthello_tlsext, SSL_R_CLIENTHELLO_TLSEXT); - return 0; - } - return 1; - } + return 1; +} /* ssl_next_proto_validate validates a Next Protocol Negotiation block. No - * elements of zero length are allowed and the set of elements must exactly fill - * the length of the block. */ -static char ssl_next_proto_validate(const CBS *cbs) - { - CBS copy = *cbs; + * elements of zero length are allowed and the set of elements must exactly + * fill the length of the block. */ +static char ssl_next_proto_validate(const CBS *cbs) { + CBS copy = *cbs; - while (CBS_len(©) != 0) - { - CBS proto; - if (!CBS_get_u8_length_prefixed(©, &proto) || - CBS_len(&proto) == 0) - { - return 0; - } - } - return 1; - } + while (CBS_len(©) != 0) { + CBS proto; + if (!CBS_get_u8_length_prefixed(©, &proto) || CBS_len(&proto) == 0) { + return 0; + } + } -static int ssl_scan_serverhello_tlsext(SSL *s, CBS *cbs, int *out_alert) - { - int tlsext_servername = 0; - int renegotiate_seen = 0; - CBS extensions; + return 1; +} - /* TODO(davidben): Move all of these to some per-handshake state that - * gets systematically reset on a new handshake; perhaps allocate it - * fresh each time so it's not even kept around post-handshake. */ - s->s3->next_proto_neg_seen = 0; +static int ssl_scan_serverhello_tlsext(SSL *s, CBS *cbs, int *out_alert) { + int tlsext_servername = 0; + int renegotiate_seen = 0; + CBS extensions; - s->tlsext_ticket_expected = 0; - s->s3->tmp.certificate_status_expected = 0; - s->s3->tmp.extended_master_secret = 0; + /* TODO(davidben): Move all of these to some per-handshake state that gets + * systematically reset on a new handshake; perhaps allocate it fresh each + * time so it's not even kept around post-handshake. */ + s->s3->next_proto_neg_seen = 0; - if (s->s3->alpn_selected) - { - OPENSSL_free(s->s3->alpn_selected); - s->s3->alpn_selected = NULL; - } + s->tlsext_ticket_expected = 0; + s->s3->tmp.certificate_status_expected = 0; + s->s3->tmp.extended_master_secret = 0; - /* Clear ECC extensions */ - if (s->s3->tmp.peer_ecpointformatlist != 0) - { - OPENSSL_free(s->s3->tmp.peer_ecpointformatlist); - s->s3->tmp.peer_ecpointformatlist = NULL; - s->s3->tmp.peer_ecpointformatlist_length = 0; - } + if (s->s3->alpn_selected) { + OPENSSL_free(s->s3->alpn_selected); + s->s3->alpn_selected = NULL; + } - /* There may be no extensions. */ - if (CBS_len(cbs) == 0) - { - goto ri_check; - } + /* Clear ECC extensions */ + if (s->s3->tmp.peer_ecpointformatlist != 0) { + OPENSSL_free(s->s3->tmp.peer_ecpointformatlist); + s->s3->tmp.peer_ecpointformatlist = NULL; + s->s3->tmp.peer_ecpointformatlist_length = 0; + } - /* Decode the extensions block and check it is valid. */ - if (!CBS_get_u16_length_prefixed(cbs, &extensions) || - !tls1_check_duplicate_extensions(&extensions)) - { - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } + /* There may be no extensions. */ + if (CBS_len(cbs) == 0) { + goto ri_check; + } - while (CBS_len(&extensions) != 0) - { - uint16_t type; - CBS extension; + /* Decode the extensions block and check it is valid. */ + if (!CBS_get_u16_length_prefixed(cbs, &extensions) || + !tls1_check_duplicate_extensions(&extensions)) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } - /* Decode the next extension. */ - if (!CBS_get_u16(&extensions, &type) || - !CBS_get_u16_length_prefixed(&extensions, &extension)) - { - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } + while (CBS_len(&extensions) != 0) { + uint16_t type; + CBS extension; - if (s->tlsext_debug_cb) - { - s->tlsext_debug_cb(s, 1, type, (unsigned char*)CBS_data(&extension), - CBS_len(&extension), s->tlsext_debug_arg); - } + /* Decode the next extension. */ + if (!CBS_get_u16(&extensions, &type) || + !CBS_get_u16_length_prefixed(&extensions, &extension)) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } - if (type == TLSEXT_TYPE_server_name) - { - /* The extension must be empty. */ - if (CBS_len(&extension) != 0) - { - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } - /* We must have sent it in ClientHello. */ - if (s->tlsext_hostname == NULL) - { - *out_alert = SSL_AD_UNSUPPORTED_EXTENSION; - return 0; - } - tlsext_servername = 1; - } - else if (type == TLSEXT_TYPE_ec_point_formats) - { - CBS ec_point_format_list; + if (s->tlsext_debug_cb) { + s->tlsext_debug_cb(s, 1, type, (uint8_t *)CBS_data(&extension), + CBS_len(&extension), s->tlsext_debug_arg); + } - if (!CBS_get_u8_length_prefixed(&extension, &ec_point_format_list) || - CBS_len(&extension) != 0) - { - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } + if (type == TLSEXT_TYPE_server_name) { + /* The extension must be empty. */ + if (CBS_len(&extension) != 0) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } - if (!CBS_stow(&ec_point_format_list, - &s->s3->tmp.peer_ecpointformatlist, - &s->s3->tmp.peer_ecpointformatlist_length)) - { - *out_alert = SSL_AD_INTERNAL_ERROR; - return 0; - } - } - else if (type == TLSEXT_TYPE_session_ticket) - { - if ((SSL_get_options(s) & SSL_OP_NO_TICKET) || CBS_len(&extension) > 0) - { - *out_alert = SSL_AD_UNSUPPORTED_EXTENSION; - return 0; - } + /* We must have sent it in ClientHello. */ + if (s->tlsext_hostname == NULL) { + *out_alert = SSL_AD_UNSUPPORTED_EXTENSION; + return 0; + } - s->tlsext_ticket_expected = 1; - } - else if (type == TLSEXT_TYPE_status_request) - { - /* The extension MUST be empty and may only sent if - * we've requested a status request message. */ - if (CBS_len(&extension) != 0) - { - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } - if (!s->ocsp_stapling_enabled) - { - *out_alert = SSL_AD_UNSUPPORTED_EXTENSION; - return 0; - } - /* Set a flag to expect a CertificateStatus message */ - s->s3->tmp.certificate_status_expected = 1; - } - else if (type == TLSEXT_TYPE_next_proto_neg && s->s3->tmp.finish_md_len == 0) { - unsigned char *selected; - unsigned char selected_len; + tlsext_servername = 1; + } else if (type == TLSEXT_TYPE_ec_point_formats) { + CBS ec_point_format_list; - /* We must have requested it. */ - if (s->ctx->next_proto_select_cb == NULL) - { - *out_alert = SSL_AD_UNSUPPORTED_EXTENSION; - return 0; - } + if (!CBS_get_u8_length_prefixed(&extension, &ec_point_format_list) || + CBS_len(&extension) != 0) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } - /* The data must be valid. */ - if (!ssl_next_proto_validate(&extension)) - { - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } + if (!CBS_stow(&ec_point_format_list, &s->s3->tmp.peer_ecpointformatlist, + &s->s3->tmp.peer_ecpointformatlist_length)) { + *out_alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + } else if (type == TLSEXT_TYPE_session_ticket) { + if ((SSL_get_options(s) & SSL_OP_NO_TICKET) || CBS_len(&extension) > 0) { + *out_alert = SSL_AD_UNSUPPORTED_EXTENSION; + return 0; + } - if (s->ctx->next_proto_select_cb(s, &selected, &selected_len, - CBS_data(&extension), CBS_len(&extension), - s->ctx->next_proto_select_cb_arg) != SSL_TLSEXT_ERR_OK) - { - *out_alert = SSL_AD_INTERNAL_ERROR; - return 0; - } + s->tlsext_ticket_expected = 1; + } else if (type == TLSEXT_TYPE_status_request) { + /* The extension MUST be empty and may only sent if we've requested a + * status request message. */ + if (CBS_len(&extension) != 0) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } - s->next_proto_negotiated = BUF_memdup(selected, selected_len); - if (s->next_proto_negotiated == NULL) - { - *out_alert = SSL_AD_INTERNAL_ERROR; - return 0; - } - s->next_proto_negotiated_len = selected_len; - s->s3->next_proto_neg_seen = 1; - } - else if (type == TLSEXT_TYPE_application_layer_protocol_negotiation) - { - CBS protocol_name_list, protocol_name; + if (!s->ocsp_stapling_enabled) { + *out_alert = SSL_AD_UNSUPPORTED_EXTENSION; + return 0; + } - /* We must have requested it. */ - if (s->alpn_client_proto_list == NULL) - { - *out_alert = SSL_AD_UNSUPPORTED_EXTENSION; - return 0; - } + /* Set a flag to expect a CertificateStatus message */ + s->s3->tmp.certificate_status_expected = 1; + } else if (type == TLSEXT_TYPE_next_proto_neg && + s->s3->tmp.finish_md_len == 0) { + uint8_t *selected; + uint8_t selected_len; - /* The extension data consists of a ProtocolNameList - * which must have exactly one ProtocolName. Each of - * these is length-prefixed. */ - if (!CBS_get_u16_length_prefixed(&extension, &protocol_name_list) || - CBS_len(&extension) != 0 || - !CBS_get_u8_length_prefixed(&protocol_name_list, &protocol_name) || - CBS_len(&protocol_name_list) != 0) - { - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } + /* We must have requested it. */ + if (s->ctx->next_proto_select_cb == NULL) { + *out_alert = SSL_AD_UNSUPPORTED_EXTENSION; + return 0; + } - if (!CBS_stow(&protocol_name, - &s->s3->alpn_selected, - &s->s3->alpn_selected_len)) - { - *out_alert = SSL_AD_INTERNAL_ERROR; - return 0; - } - } + /* The data must be valid. */ + if (!ssl_next_proto_validate(&extension)) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } - else if (type == TLSEXT_TYPE_channel_id) - { - if (CBS_len(&extension) != 0) - { - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } - s->s3->tlsext_channel_id_valid = 1; - } - else if (type == TLSEXT_TYPE_channel_id_new) - { - if (CBS_len(&extension) != 0) - { - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } - s->s3->tlsext_channel_id_valid = 1; - s->s3->tlsext_channel_id_new = 1; - } - else if (type == TLSEXT_TYPE_certificate_timestamp) - { - if (CBS_len(&extension) == 0) - { - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } + if (s->ctx->next_proto_select_cb( + s, &selected, &selected_len, CBS_data(&extension), + CBS_len(&extension), + s->ctx->next_proto_select_cb_arg) != SSL_TLSEXT_ERR_OK) { + *out_alert = SSL_AD_INTERNAL_ERROR; + return 0; + } - /* Session resumption uses the original session information. */ - if (!s->hit) - { - if (!CBS_stow(&extension, - &s->session->tlsext_signed_cert_timestamp_list, - &s->session->tlsext_signed_cert_timestamp_list_length)) - { - *out_alert = SSL_AD_INTERNAL_ERROR; - return 0; - } - } - } - else if (type == TLSEXT_TYPE_renegotiate) - { - if (!ssl_parse_serverhello_renegotiate_ext(s, &extension, out_alert)) - return 0; - renegotiate_seen = 1; - } - else if (type == TLSEXT_TYPE_use_srtp) - { - if (!ssl_parse_serverhello_use_srtp_ext(s, &extension, out_alert)) - return 0; - } + s->next_proto_negotiated = BUF_memdup(selected, selected_len); + if (s->next_proto_negotiated == NULL) { + *out_alert = SSL_AD_INTERNAL_ERROR; + return 0; + } - else if (type == TLSEXT_TYPE_extended_master_secret) - { - if (/* It is invalid for the server to select EMS and - SSLv3. */ - s->version == SSL3_VERSION || - CBS_len(&extension) != 0) - { - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } + s->next_proto_negotiated_len = selected_len; + s->s3->next_proto_neg_seen = 1; + } else if (type == TLSEXT_TYPE_application_layer_protocol_negotiation) { + CBS protocol_name_list, protocol_name; - s->s3->tmp.extended_master_secret = 1; - } - } + /* We must have requested it. */ + if (s->alpn_client_proto_list == NULL) { + *out_alert = SSL_AD_UNSUPPORTED_EXTENSION; + return 0; + } - if (!s->hit && tlsext_servername == 1) - { - if (s->tlsext_hostname) - { - if (s->session->tlsext_hostname == NULL) - { - s->session->tlsext_hostname = BUF_strdup(s->tlsext_hostname); - if (!s->session->tlsext_hostname) - { - *out_alert = SSL_AD_UNRECOGNIZED_NAME; - return 0; - } - } - else - { - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } - } - } + /* The extension data consists of a ProtocolNameList which must have + * exactly one ProtocolName. Each of these is length-prefixed. */ + if (!CBS_get_u16_length_prefixed(&extension, &protocol_name_list) || + CBS_len(&extension) != 0 || + !CBS_get_u8_length_prefixed(&protocol_name_list, &protocol_name) || + CBS_len(&protocol_name_list) != 0) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } - ri_check: + if (!CBS_stow(&protocol_name, &s->s3->alpn_selected, + &s->s3->alpn_selected_len)) { + *out_alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + } else if (type == TLSEXT_TYPE_channel_id) { + if (CBS_len(&extension) != 0) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } - /* Determine if we need to see RI. Strictly speaking if we want to - * avoid an attack we should *always* see RI even on initial server - * hello because the client doesn't see any renegotiation during an - * attack. However this would mean we could not connect to any server - * which doesn't support RI so for the immediate future tolerate RI - * absence on initial connect only. - */ - if (!renegotiate_seen - && !(s->options & SSL_OP_LEGACY_SERVER_CONNECT) - && !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) - { - *out_alert = SSL_AD_HANDSHAKE_FAILURE; - OPENSSL_PUT_ERROR(SSL, ssl_scan_serverhello_tlsext, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); - return 0; - } + s->s3->tlsext_channel_id_valid = 1; + } else if (type == TLSEXT_TYPE_channel_id_new) { + if (CBS_len(&extension) != 0) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } - return 1; - } + s->s3->tlsext_channel_id_valid = 1; + s->s3->tlsext_channel_id_new = 1; + } else if (type == TLSEXT_TYPE_certificate_timestamp) { + if (CBS_len(&extension) == 0) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } + /* Session resumption uses the original session information. */ + if (!s->hit && + !CBS_stow(&extension, &s->session->tlsext_signed_cert_timestamp_list, + &s->session->tlsext_signed_cert_timestamp_list_length)) { + *out_alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + } else if (type == TLSEXT_TYPE_renegotiate) { + if (!ssl_parse_serverhello_renegotiate_ext(s, &extension, out_alert)) { + return 0; + } -int ssl_prepare_clienthello_tlsext(SSL *s) - { - return 1; - } + renegotiate_seen = 1; + } else if (type == TLSEXT_TYPE_use_srtp) { + if (!ssl_parse_serverhello_use_srtp_ext(s, &extension, out_alert)) { + return 0; + } + } else if (type == TLSEXT_TYPE_extended_master_secret) { + if (/* It is invalid for the server to select EMS and + SSLv3. */ + s->version == SSL3_VERSION || CBS_len(&extension) != 0) { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } -int ssl_prepare_serverhello_tlsext(SSL *s) - { - return 1; - } + s->s3->tmp.extended_master_secret = 1; + } + } -static int ssl_check_clienthello_tlsext(SSL *s) - { - int ret=SSL_TLSEXT_ERR_NOACK; - int al = SSL_AD_UNRECOGNIZED_NAME; + if (!s->hit && tlsext_servername == 1 && s->tlsext_hostname) { + if (s->session->tlsext_hostname == NULL) { + s->session->tlsext_hostname = BUF_strdup(s->tlsext_hostname); + if (!s->session->tlsext_hostname) { + *out_alert = SSL_AD_UNRECOGNIZED_NAME; + return 0; + } + } else { + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } + } - /* The handling of the ECPointFormats extension is done elsewhere, namely in - * ssl3_choose_cipher in s3_lib.c. - */ - /* The handling of the EllipticCurves extension is done elsewhere, namely in - * ssl3_choose_cipher in s3_lib.c. - */ +ri_check: + /* Determine if we need to see RI. Strictly speaking if we want to avoid an + * attack we should *always* see RI even on initial server hello because the + * client doesn't see any renegotiation during an attack. However this would + * mean we could not connect to any server which doesn't support RI so for + * the immediate future tolerate RI absence on initial connect only. */ + if (!renegotiate_seen && !(s->options & SSL_OP_LEGACY_SERVER_CONNECT) && + !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) { + *out_alert = SSL_AD_HANDSHAKE_FAILURE; + OPENSSL_PUT_ERROR(SSL, ssl_scan_serverhello_tlsext, + SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); + return 0; + } - if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0) - ret = s->ctx->tlsext_servername_callback(s, &al, s->ctx->tlsext_servername_arg); - else if (s->initial_ctx != NULL && s->initial_ctx->tlsext_servername_callback != 0) - ret = s->initial_ctx->tlsext_servername_callback(s, &al, s->initial_ctx->tlsext_servername_arg); + return 1; +} - switch (ret) - { - case SSL_TLSEXT_ERR_ALERT_FATAL: - ssl3_send_alert(s,SSL3_AL_FATAL,al); - return -1; +int ssl_prepare_clienthello_tlsext(SSL *s) { return 1; } - case SSL_TLSEXT_ERR_ALERT_WARNING: - ssl3_send_alert(s,SSL3_AL_WARNING,al); - return 1; +int ssl_prepare_serverhello_tlsext(SSL *s) { return 1; } - case SSL_TLSEXT_ERR_NOACK: - s->should_ack_sni = 0; - return 1; +static int ssl_check_clienthello_tlsext(SSL *s) { + int ret = SSL_TLSEXT_ERR_NOACK; + int al = SSL_AD_UNRECOGNIZED_NAME; - default: - return 1; - } - } + /* The handling of the ECPointFormats extension is done elsewhere, namely in + * ssl3_choose_cipher in s3_lib.c. */ -static int ssl_check_serverhello_tlsext(SSL *s) - { - int ret=SSL_TLSEXT_ERR_NOACK; - int al = SSL_AD_UNRECOGNIZED_NAME; + if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0) { + ret = s->ctx->tlsext_servername_callback(s, &al, + s->ctx->tlsext_servername_arg); + } else if (s->initial_ctx != NULL && + s->initial_ctx->tlsext_servername_callback != 0) { + ret = s->initial_ctx->tlsext_servername_callback( + s, &al, s->initial_ctx->tlsext_servername_arg); + } - /* If we are client and using an elliptic curve cryptography cipher - * suite, then if server returns an EC point formats lists extension - * it must contain uncompressed. - */ - unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; - unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth; - if (((alg_k & SSL_kEECDH) || (alg_a & SSL_aECDSA)) && - !tls1_check_point_format(s, TLSEXT_ECPOINTFORMAT_uncompressed)) - { - OPENSSL_PUT_ERROR(SSL, ssl_check_serverhello_tlsext, SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST); - return -1; - } - ret = SSL_TLSEXT_ERR_OK; + switch (ret) { + case SSL_TLSEXT_ERR_ALERT_FATAL: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + return -1; - if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0) - ret = s->ctx->tlsext_servername_callback(s, &al, s->ctx->tlsext_servername_arg); - else if (s->initial_ctx != NULL && s->initial_ctx->tlsext_servername_callback != 0) - ret = s->initial_ctx->tlsext_servername_callback(s, &al, s->initial_ctx->tlsext_servername_arg); + case SSL_TLSEXT_ERR_ALERT_WARNING: + ssl3_send_alert(s, SSL3_AL_WARNING, al); + return 1; - switch (ret) - { - case SSL_TLSEXT_ERR_ALERT_FATAL: - ssl3_send_alert(s,SSL3_AL_FATAL,al); - return -1; + case SSL_TLSEXT_ERR_NOACK: + s->should_ack_sni = 0; + return 1; - case SSL_TLSEXT_ERR_ALERT_WARNING: - ssl3_send_alert(s,SSL3_AL_WARNING,al); - return 1; + default: + return 1; + } +} - default: - return 1; - } - } +static int ssl_check_serverhello_tlsext(SSL *s) { + int ret = SSL_TLSEXT_ERR_NOACK; + int al = SSL_AD_UNRECOGNIZED_NAME; -int ssl_parse_serverhello_tlsext(SSL *s, CBS *cbs) - { - int alert = -1; - if (s->version < SSL3_VERSION) - return 1; + /* If we are client and using an elliptic curve cryptography cipher suite, + * then if server returns an EC point formats lists extension it must contain + * uncompressed. */ + unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey; + unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth; + if (((alg_k & SSL_kEECDH) || (alg_a & SSL_aECDSA)) && + !tls1_check_point_format(s, TLSEXT_ECPOINTFORMAT_uncompressed)) { + OPENSSL_PUT_ERROR(SSL, ssl_check_serverhello_tlsext, + SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST); + return -1; + } + ret = SSL_TLSEXT_ERR_OK; - if (ssl_scan_serverhello_tlsext(s, cbs, &alert) <= 0) - { - ssl3_send_alert(s, SSL3_AL_FATAL, alert); - return 0; - } + if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0) { + ret = s->ctx->tlsext_servername_callback(s, &al, + s->ctx->tlsext_servername_arg); + } else if (s->initial_ctx != NULL && + s->initial_ctx->tlsext_servername_callback != 0) { + ret = s->initial_ctx->tlsext_servername_callback( + s, &al, s->initial_ctx->tlsext_servername_arg); + } - if (ssl_check_serverhello_tlsext(s) <= 0) - { - OPENSSL_PUT_ERROR(SSL, ssl_parse_serverhello_tlsext, SSL_R_SERVERHELLO_TLSEXT); - return 0; - } + switch (ret) { + case SSL_TLSEXT_ERR_ALERT_FATAL: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + return -1; - return 1; - } + case SSL_TLSEXT_ERR_ALERT_WARNING: + ssl3_send_alert(s, SSL3_AL_WARNING, al); + return 1; + + default: + return 1; + } +} + +int ssl_parse_serverhello_tlsext(SSL *s, CBS *cbs) { + int alert = -1; + if (s->version < SSL3_VERSION) { + return 1; + } + + if (ssl_scan_serverhello_tlsext(s, cbs, &alert) <= 0) { + ssl3_send_alert(s, SSL3_AL_FATAL, alert); + return 0; + } + + if (ssl_check_serverhello_tlsext(s) <= 0) { + OPENSSL_PUT_ERROR(SSL, ssl_parse_serverhello_tlsext, + SSL_R_SERVERHELLO_TLSEXT); + return 0; + } + + return 1; +} /* Since the server cache lookup is done early on in the processing of the * ClientHello, and other operations depend on the result, we need to handle @@ -2262,49 +2102,46 @@ * the client's ticket. Otherwise, s->tlsext_ticket_expected is set to 0. */ int tls1_process_ticket(SSL *s, const struct ssl_early_callback_ctx *ctx, - SSL_SESSION **ret) - { - *ret = NULL; - s->tlsext_ticket_expected = 0; - const unsigned char *data; - size_t len; - int r; + SSL_SESSION **ret) { + *ret = NULL; + s->tlsext_ticket_expected = 0; + const uint8_t *data; + size_t len; + int r; - /* If tickets disabled behave as if no ticket present - * to permit stateful resumption. - */ - if (SSL_get_options(s) & SSL_OP_NO_TICKET) - return 0; - if ((s->version <= SSL3_VERSION) && !ctx->extensions) - return 0; - if (!SSL_early_callback_ctx_extension_get( - ctx, TLSEXT_TYPE_session_ticket, &data, &len)) - { - return 0; - } - if (len == 0) - { - /* The client will accept a ticket but doesn't - * currently have one. */ - s->tlsext_ticket_expected = 1; - return 1; - } - r = tls_decrypt_ticket(s, data, len, ctx->session_id, - ctx->session_id_len, ret); - switch (r) - { - case 2: /* ticket couldn't be decrypted */ - s->tlsext_ticket_expected = 1; - return 2; - case 3: /* ticket was decrypted */ - return r; - case 4: /* ticket decrypted but need to renew */ - s->tlsext_ticket_expected = 1; - return 3; - default: /* fatal error */ - return -1; - } - } + /* If tickets disabled behave as if no ticket present to permit stateful + * resumption. */ + if ((SSL_get_options(s) & SSL_OP_NO_TICKET) || + (s->version <= SSL3_VERSION && !ctx->extensions) || + !SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_session_ticket, + &data, &len)) { + return 0; + } + + if (len == 0) { + /* The client will accept a ticket but doesn't currently have one. */ + s->tlsext_ticket_expected = 1; + return 1; + } + + r = tls_decrypt_ticket(s, data, len, ctx->session_id, ctx->session_id_len, + ret); + switch (r) { + case 2: /* ticket couldn't be decrypted */ + s->tlsext_ticket_expected = 1; + return 2; + + case 3: /* ticket was decrypted */ + return r; + + case 4: /* ticket decrypted but need to renew */ + s->tlsext_ticket_expected = 1; + return 3; + + default: /* fatal error */ + return -1; + } +} /* tls_decrypt_ticket attempts to decrypt a session ticket. * @@ -2319,539 +2156,552 @@ * -1: fatal error, either from parsing or decrypting the ticket. * 2: the ticket couldn't be decrypted. * 3: a ticket was successfully decrypted and *psess was set. - * 4: same as 3, but the ticket needs to be renewed. - */ -static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen, - const unsigned char *sess_id, int sesslen, - SSL_SESSION **psess) - { - SSL_SESSION *sess; - unsigned char *sdec; - const unsigned char *p; - int slen, mlen, renew_ticket = 0; - unsigned char tick_hmac[EVP_MAX_MD_SIZE]; - HMAC_CTX hctx; - EVP_CIPHER_CTX ctx; - SSL_CTX *tctx = s->initial_ctx; - /* Need at least keyname + iv + some encrypted data */ - if (eticklen < 48) - return 2; - /* Initialize session ticket encryption and HMAC contexts */ - HMAC_CTX_init(&hctx); - EVP_CIPHER_CTX_init(&ctx); - if (tctx->tlsext_ticket_key_cb) - { - unsigned char *nctick = (unsigned char *)etick; - int rv = tctx->tlsext_ticket_key_cb(s, nctick, nctick + 16, - &ctx, &hctx, 0); - if (rv < 0) - return -1; - if (rv == 0) - return 2; - if (rv == 2) - renew_ticket = 1; - } - else - { - /* Check key name matches */ - if (memcmp(etick, tctx->tlsext_tick_key_name, 16)) - return 2; - if (!HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16, - tlsext_tick_md(), NULL) || - !EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, - tctx->tlsext_tick_aes_key, etick + 16)) - { - HMAC_CTX_cleanup(&hctx); - EVP_CIPHER_CTX_cleanup(&ctx); - return -1; - } - } - /* Attempt to process session ticket, first conduct sanity and - * integrity checks on ticket. - */ - mlen = HMAC_size(&hctx); - if (mlen < 0) - { - HMAC_CTX_cleanup(&hctx); - EVP_CIPHER_CTX_cleanup(&ctx); - return -1; - } - eticklen -= mlen; - /* Check HMAC of encrypted ticket */ - HMAC_Update(&hctx, etick, eticklen); - HMAC_Final(&hctx, tick_hmac, NULL); - HMAC_CTX_cleanup(&hctx); - if (CRYPTO_memcmp(tick_hmac, etick + eticklen, mlen)) - { - EVP_CIPHER_CTX_cleanup(&ctx); - return 2; - } - /* Attempt to decrypt session data */ - /* Move p after IV to start of encrypted ticket, update length */ - p = etick + 16 + EVP_CIPHER_CTX_iv_length(&ctx); - eticklen -= 16 + EVP_CIPHER_CTX_iv_length(&ctx); - sdec = OPENSSL_malloc(eticklen); - if (!sdec) - { - EVP_CIPHER_CTX_cleanup(&ctx); - return -1; - } - EVP_DecryptUpdate(&ctx, sdec, &slen, p, eticklen); - if (EVP_DecryptFinal_ex(&ctx, sdec + slen, &mlen) <= 0) - { - EVP_CIPHER_CTX_cleanup(&ctx); - OPENSSL_free(sdec); - return 2; - } - slen += mlen; - EVP_CIPHER_CTX_cleanup(&ctx); - p = sdec; + * 4: same as 3, but the ticket needs to be renewed. */ +static int tls_decrypt_ticket(SSL *s, const uint8_t *etick, int eticklen, + const uint8_t *sess_id, int sesslen, + SSL_SESSION **psess) { + SSL_SESSION *sess; + uint8_t *sdec; + const uint8_t *p; + int slen, mlen, renew_ticket = 0; + uint8_t tick_hmac[EVP_MAX_MD_SIZE]; + HMAC_CTX hctx; + EVP_CIPHER_CTX ctx; + SSL_CTX *tctx = s->initial_ctx; - sess = d2i_SSL_SESSION(NULL, &p, slen); - OPENSSL_free(sdec); - if (sess) - { - /* The session ID, if non-empty, is used by some clients to - * detect that the ticket has been accepted. So we copy it to - * the session structure. If it is empty set length to zero - * as required by standard. - */ - if (sesslen) - memcpy(sess->session_id, sess_id, sesslen); - sess->session_id_length = sesslen; - *psess = sess; - if (renew_ticket) - return 4; - else - return 3; - } - ERR_clear_error(); - /* For session parse failure, indicate that we need to send a new - * ticket. */ - return 2; - } + /* Need at least keyname + iv + some encrypted data */ + if (eticklen < 48) { + return 2; + } + + /* Initialize session ticket encryption and HMAC contexts */ + HMAC_CTX_init(&hctx); + EVP_CIPHER_CTX_init(&ctx); + if (tctx->tlsext_ticket_key_cb) { + uint8_t *nctick = (uint8_t *)etick; + int rv = tctx->tlsext_ticket_key_cb(s, nctick, nctick + 16, &ctx, &hctx, 0); + if (rv < 0) { + return -1; + } + if (rv == 0) { + return 2; + } + if (rv == 2) { + renew_ticket = 1; + } + } else { + /* Check key name matches */ + if (memcmp(etick, tctx->tlsext_tick_key_name, 16)) { + return 2; + } + if (!HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16, tlsext_tick_md(), + NULL) || + !EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, + tctx->tlsext_tick_aes_key, etick + 16)) { + HMAC_CTX_cleanup(&hctx); + EVP_CIPHER_CTX_cleanup(&ctx); + return -1; + } + } + + /* Attempt to process session ticket, first conduct sanity and integrity + * checks on ticket. */ + mlen = HMAC_size(&hctx); + if (mlen < 0) { + HMAC_CTX_cleanup(&hctx); + EVP_CIPHER_CTX_cleanup(&ctx); + return -1; + } + eticklen -= mlen; + /* Check HMAC of encrypted ticket */ + HMAC_Update(&hctx, etick, eticklen); + HMAC_Final(&hctx, tick_hmac, NULL); + HMAC_CTX_cleanup(&hctx); + if (CRYPTO_memcmp(tick_hmac, etick + eticklen, mlen)) { + EVP_CIPHER_CTX_cleanup(&ctx); + return 2; + } + + /* Attempt to decrypt session data */ + /* Move p after IV to start of encrypted ticket, update length */ + p = etick + 16 + EVP_CIPHER_CTX_iv_length(&ctx); + eticklen -= 16 + EVP_CIPHER_CTX_iv_length(&ctx); + sdec = OPENSSL_malloc(eticklen); + if (!sdec) { + EVP_CIPHER_CTX_cleanup(&ctx); + return -1; + } + EVP_DecryptUpdate(&ctx, sdec, &slen, p, eticklen); + if (EVP_DecryptFinal_ex(&ctx, sdec + slen, &mlen) <= 0) { + EVP_CIPHER_CTX_cleanup(&ctx); + OPENSSL_free(sdec); + return 2; + } + slen += mlen; + EVP_CIPHER_CTX_cleanup(&ctx); + p = sdec; + + sess = d2i_SSL_SESSION(NULL, &p, slen); + OPENSSL_free(sdec); + if (sess) { + /* The session ID, if non-empty, is used by some clients to detect that the + * ticket has been accepted. So we copy it to the session structure. If it + * is empty set length to zero as required by standard. */ + if (sesslen) { + memcpy(sess->session_id, sess_id, sesslen); + } + sess->session_id_length = sesslen; + *psess = sess; + if (renew_ticket) { + return 4; + } + return 3; + } + + ERR_clear_error(); + /* For session parse failure, indicate that we need to send a new ticket. */ + return 2; +} /* Tables to translate from NIDs to TLS v1.2 ids */ +typedef struct { + int nid; + int id; +} tls12_lookup; -typedef struct - { - int nid; - int id; - } tls12_lookup; +static const tls12_lookup tls12_md[] = {{NID_md5, TLSEXT_hash_md5}, + {NID_sha1, TLSEXT_hash_sha1}, + {NID_sha224, TLSEXT_hash_sha224}, + {NID_sha256, TLSEXT_hash_sha256}, + {NID_sha384, TLSEXT_hash_sha384}, + {NID_sha512, TLSEXT_hash_sha512}}; -static const tls12_lookup tls12_md[] = { - {NID_md5, TLSEXT_hash_md5}, - {NID_sha1, TLSEXT_hash_sha1}, - {NID_sha224, TLSEXT_hash_sha224}, - {NID_sha256, TLSEXT_hash_sha256}, - {NID_sha384, TLSEXT_hash_sha384}, - {NID_sha512, TLSEXT_hash_sha512} -}; +static const tls12_lookup tls12_sig[] = {{EVP_PKEY_RSA, TLSEXT_signature_rsa}, + {EVP_PKEY_EC, TLSEXT_signature_ecdsa}}; -static const tls12_lookup tls12_sig[] = { - {EVP_PKEY_RSA, TLSEXT_signature_rsa}, - {EVP_PKEY_EC, TLSEXT_signature_ecdsa} -}; +static int tls12_find_id(int nid, const tls12_lookup *table, size_t tlen) { + size_t i; + for (i = 0; i < tlen; i++) { + if (table[i].nid == nid) { + return table[i].id; + } + } -static int tls12_find_id(int nid, const tls12_lookup *table, size_t tlen) - { - size_t i; - for (i = 0; i < tlen; i++) - { - if (table[i].nid == nid) - return table[i].id; - } - return -1; - } + return -1; +} -static int tls12_find_nid(int id, const tls12_lookup *table, size_t tlen) - { - size_t i; - for (i = 0; i < tlen; i++) - { - if ((table[i].id) == id) - return table[i].nid; - } - return NID_undef; - } +static int tls12_find_nid(int id, const tls12_lookup *table, size_t tlen) { + size_t i; + for (i = 0; i < tlen; i++) { + if (table[i].id == id) { + return table[i].nid; + } + } -int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk, const EVP_MD *md) - { - int sig_id, md_id; - if (!md) - return 0; - md_id = tls12_find_id(EVP_MD_type(md), tls12_md, - sizeof(tls12_md)/sizeof(tls12_lookup)); - if (md_id == -1) - return 0; - sig_id = tls12_get_sigid(pk); - if (sig_id == -1) - return 0; - p[0] = (unsigned char)md_id; - p[1] = (unsigned char)sig_id; - return 1; - } + return NID_undef; +} -int tls12_get_sigid(const EVP_PKEY *pk) - { - return tls12_find_id(pk->type, tls12_sig, - sizeof(tls12_sig)/sizeof(tls12_lookup)); - } +int tls12_get_sigandhash(uint8_t *p, const EVP_PKEY *pk, const EVP_MD *md) { + int sig_id, md_id; -const EVP_MD *tls12_get_hash(unsigned char hash_alg) - { - switch(hash_alg) - { - case TLSEXT_hash_md5: - return EVP_md5(); - case TLSEXT_hash_sha1: - return EVP_sha1(); - case TLSEXT_hash_sha224: - return EVP_sha224(); + if (!md) { + return 0; + } - case TLSEXT_hash_sha256: - return EVP_sha256(); - case TLSEXT_hash_sha384: - return EVP_sha384(); + md_id = tls12_find_id(EVP_MD_type(md), tls12_md, + sizeof(tls12_md) / sizeof(tls12_lookup)); + if (md_id == -1) { + return 0; + } - case TLSEXT_hash_sha512: - return EVP_sha512(); - default: - return NULL; + sig_id = tls12_get_sigid(pk); + if (sig_id == -1) { + return 0; + } - } - } + p[0] = (uint8_t)md_id; + p[1] = (uint8_t)sig_id; + return 1; +} + +int tls12_get_sigid(const EVP_PKEY *pk) { + return tls12_find_id(pk->type, tls12_sig, + sizeof(tls12_sig) / sizeof(tls12_lookup)); +} + +const EVP_MD *tls12_get_hash(uint8_t hash_alg) { + switch (hash_alg) { + case TLSEXT_hash_md5: + return EVP_md5(); + + case TLSEXT_hash_sha1: + return EVP_sha1(); + + case TLSEXT_hash_sha224: + return EVP_sha224(); + + case TLSEXT_hash_sha256: + return EVP_sha256(); + + case TLSEXT_hash_sha384: + return EVP_sha384(); + + case TLSEXT_hash_sha512: + return EVP_sha512(); + + default: + return NULL; + } +} /* tls12_get_pkey_type returns the EVP_PKEY type corresponding to TLS signature * algorithm |sig_alg|. It returns -1 if the type is unknown. */ -static int tls12_get_pkey_type(uint8_t sig_alg) - { - switch(sig_alg) - { - case TLSEXT_signature_rsa: - return EVP_PKEY_RSA; - case TLSEXT_signature_ecdsa: - return EVP_PKEY_EC; - } - return -1; - } +static int tls12_get_pkey_type(uint8_t sig_alg) { + switch (sig_alg) { + case TLSEXT_signature_rsa: + return EVP_PKEY_RSA; + + case TLSEXT_signature_ecdsa: + return EVP_PKEY_EC; + + default: + return -1; + } +} /* Convert TLS 1.2 signature algorithm extension values into NIDs */ static void tls1_lookup_sigalg(int *phash_nid, int *psign_nid, - int *psignhash_nid, const unsigned char *data) - { - int sign_nid = 0, hash_nid = 0; - if (!phash_nid && !psign_nid && !psignhash_nid) - return; - if (phash_nid || psignhash_nid) - { - hash_nid = tls12_find_nid(data[0], tls12_md, - sizeof(tls12_md)/sizeof(tls12_lookup)); - if (phash_nid) - *phash_nid = hash_nid; - } - if (psign_nid || psignhash_nid) - { - sign_nid = tls12_find_nid(data[1], tls12_sig, - sizeof(tls12_sig)/sizeof(tls12_lookup)); - if (psign_nid) - *psign_nid = sign_nid; - } - if (psignhash_nid) - { - if (sign_nid && hash_nid) - OBJ_find_sigid_by_algs(psignhash_nid, - hash_nid, sign_nid); - else - *psignhash_nid = NID_undef; - } - } + int *psignhash_nid, const uint8_t *data) { + int sign_nid = 0, hash_nid = 0; + if (!phash_nid && !psign_nid && !psignhash_nid) { + return; + } + + if (phash_nid || psignhash_nid) { + hash_nid = tls12_find_nid(data[0], tls12_md, + sizeof(tls12_md) / sizeof(tls12_lookup)); + if (phash_nid) { + *phash_nid = hash_nid; + } + } + + if (psign_nid || psignhash_nid) { + sign_nid = tls12_find_nid(data[1], tls12_sig, + sizeof(tls12_sig) / sizeof(tls12_lookup)); + if (psign_nid) { + *psign_nid = sign_nid; + } + } + + if (psignhash_nid) { + if (sign_nid && hash_nid) { + OBJ_find_sigid_by_algs(psignhash_nid, hash_nid, sign_nid); + } else { + *psignhash_nid = NID_undef; + } + } +} + /* Given preference and allowed sigalgs set shared sigalgs */ -static int tls12_do_shared_sigalgs(TLS_SIGALGS *shsig, - const unsigned char *pref, size_t preflen, - const unsigned char *allow, size_t allowlen) - { - const unsigned char *ptmp, *atmp; - size_t i, j, nmatch = 0; - for (i = 0, ptmp = pref; i < preflen; i+=2, ptmp+=2) - { - /* Skip disabled hashes or signature algorithms */ - if (tls12_get_hash(ptmp[0]) == NULL) - continue; - if (tls12_get_pkey_type(ptmp[1]) == -1) - continue; - for (j = 0, atmp = allow; j < allowlen; j+=2, atmp+=2) - { - if (ptmp[0] == atmp[0] && ptmp[1] == atmp[1]) - { - nmatch++; - if (shsig) - { - shsig->rhash = ptmp[0]; - shsig->rsign = ptmp[1]; - tls1_lookup_sigalg(&shsig->hash_nid, - &shsig->sign_nid, - &shsig->signandhash_nid, - ptmp); - shsig++; - } - break; - } - } - } - return nmatch; - } +static int tls12_do_shared_sigalgs(TLS_SIGALGS *shsig, const uint8_t *pref, + size_t preflen, const uint8_t *allow, + size_t allowlen) { + const uint8_t *ptmp, *atmp; + size_t i, j, nmatch = 0; + + for (i = 0, ptmp = pref; i < preflen; i += 2, ptmp += 2) { + /* Skip disabled hashes or signature algorithms */ + if (tls12_get_hash(ptmp[0]) == NULL || + tls12_get_pkey_type(ptmp[1]) == -1) { + continue; + } + + for (j = 0, atmp = allow; j < allowlen; j += 2, atmp += 2) { + if (ptmp[0] == atmp[0] && ptmp[1] == atmp[1]) { + nmatch++; + if (shsig) { + shsig->rhash = ptmp[0]; + shsig->rsign = ptmp[1]; + tls1_lookup_sigalg(&shsig->hash_nid, &shsig->sign_nid, + &shsig->signandhash_nid, ptmp); + shsig++; + } + + break; + } + } + } + + return nmatch; +} /* Set shared signature algorithms for SSL structures */ -static int tls1_set_shared_sigalgs(SSL *s) - { - const unsigned char *pref, *allow, *conf; - size_t preflen, allowlen, conflen; - size_t nmatch; - TLS_SIGALGS *salgs = NULL; - CERT *c = s->cert; - if (c->shared_sigalgs) - { - OPENSSL_free(c->shared_sigalgs); - c->shared_sigalgs = NULL; - } - /* If client use client signature algorithms if not NULL */ - if (!s->server && c->client_sigalgs) - { - conf = c->client_sigalgs; - conflen = c->client_sigalgslen; - } - else if (c->conf_sigalgs) - { - conf = c->conf_sigalgs; - conflen = c->conf_sigalgslen; - } - else - conflen = tls12_get_psigalgs(s, &conf); - if(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) - { - pref = conf; - preflen = conflen; - allow = c->peer_sigalgs; - allowlen = c->peer_sigalgslen; - } - else - { - allow = conf; - allowlen = conflen; - pref = c->peer_sigalgs; - preflen = c->peer_sigalgslen; - } - nmatch = tls12_do_shared_sigalgs(NULL, pref, preflen, allow, allowlen); - if (!nmatch) - return 1; - salgs = OPENSSL_malloc(nmatch * sizeof(TLS_SIGALGS)); - if (!salgs) - return 0; - nmatch = tls12_do_shared_sigalgs(salgs, pref, preflen, allow, allowlen); - c->shared_sigalgs = salgs; - c->shared_sigalgslen = nmatch; - return 1; - } - +static int tls1_set_shared_sigalgs(SSL *s) { + const uint8_t *pref, *allow, *conf; + size_t preflen, allowlen, conflen; + size_t nmatch; + TLS_SIGALGS *salgs = NULL; + CERT *c = s->cert; + + if (c->shared_sigalgs) { + OPENSSL_free(c->shared_sigalgs); + c->shared_sigalgs = NULL; + } + + /* If client use client signature algorithms if not NULL */ + if (!s->server && c->client_sigalgs) { + conf = c->client_sigalgs; + conflen = c->client_sigalgslen; + } else if (c->conf_sigalgs) { + conf = c->conf_sigalgs; + conflen = c->conf_sigalgslen; + } else { + conflen = tls12_get_psigalgs(s, &conf); + } + + if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) { + pref = conf; + preflen = conflen; + allow = c->peer_sigalgs; + allowlen = c->peer_sigalgslen; + } else { + allow = conf; + allowlen = conflen; + pref = c->peer_sigalgs; + preflen = c->peer_sigalgslen; + } + + nmatch = tls12_do_shared_sigalgs(NULL, pref, preflen, allow, allowlen); + if (!nmatch) { + return 1; + } + + salgs = OPENSSL_malloc(nmatch * sizeof(TLS_SIGALGS)); + if (!salgs) { + return 0; + } + + nmatch = tls12_do_shared_sigalgs(salgs, pref, preflen, allow, allowlen); + c->shared_sigalgs = salgs; + c->shared_sigalgslen = nmatch; + return 1; +} /* Set preferred digest for each key type */ +int tls1_process_sigalgs(SSL *s, const CBS *sigalgs) { + CERT *c = s->cert; -int tls1_process_sigalgs(SSL *s, const CBS *sigalgs) - { - CERT *c = s->cert; + /* Extension ignored for inappropriate versions */ + if (!SSL_USE_SIGALGS(s)) { + return 1; + } - /* Extension ignored for inappropriate versions */ - if (!SSL_USE_SIGALGS(s)) - return 1; - /* Length must be even */ - if (CBS_len(sigalgs) % 2 != 0) - return 0; - /* Should never happen */ - if (!c) - return 0; + /* Length must be even */ + if (CBS_len(sigalgs) % 2 != 0) { + return 0; + } - if (!CBS_stow(sigalgs, &c->peer_sigalgs, &c->peer_sigalgslen)) - return 0; + /* Should never happen */ + if (!c) { + return 0; + } - tls1_set_shared_sigalgs(s); - return 1; - } + if (!CBS_stow(sigalgs, &c->peer_sigalgs, &c->peer_sigalgslen)) { + return 0; + } -const EVP_MD *tls1_choose_signing_digest(SSL *s, EVP_PKEY *pkey) - { - CERT *c = s->cert; - int type = EVP_PKEY_id(pkey); - size_t i; + tls1_set_shared_sigalgs(s); + return 1; +} - /* Select the first shared digest supported by our key. */ - for (i = 0; i < c->shared_sigalgslen; i++) - { - const EVP_MD *md = tls12_get_hash(c->shared_sigalgs[i].rhash); - if (md == NULL || tls12_get_pkey_type(c->shared_sigalgs[i].rsign) != type) - continue; - if (!EVP_PKEY_supports_digest(pkey, md)) - continue; - return md; - } +const EVP_MD *tls1_choose_signing_digest(SSL *s, EVP_PKEY *pkey) { + CERT *c = s->cert; + int type = EVP_PKEY_id(pkey); + size_t i; - /* If no suitable digest may be found, default to SHA-1. */ - return EVP_sha1(); - } + /* Select the first shared digest supported by our key. */ + for (i = 0; i < c->shared_sigalgslen; i++) { + const EVP_MD *md = tls12_get_hash(c->shared_sigalgs[i].rhash); + if (md == NULL || + tls12_get_pkey_type(c->shared_sigalgs[i].rsign) != type || + !EVP_PKEY_supports_digest(pkey, md)) { + continue; + } + return md; + } -int SSL_get_sigalgs(SSL *s, int idx, - int *psign, int *phash, int *psignhash, - unsigned char *rsig, unsigned char *rhash) - { - const unsigned char *psig = s->cert->peer_sigalgs; - if (psig == NULL) - return 0; - if (idx >= 0) - { - idx <<= 1; - if (idx >= (int)s->cert->peer_sigalgslen) - return 0; - psig += idx; - if (rhash) - *rhash = psig[0]; - if (rsig) - *rsig = psig[1]; - tls1_lookup_sigalg(phash, psign, psignhash, psig); - } - return s->cert->peer_sigalgslen / 2; - } + /* If no suitable digest may be found, default to SHA-1. */ + return EVP_sha1(); +} -int SSL_get_shared_sigalgs(SSL *s, int idx, - int *psign, int *phash, int *psignhash, - unsigned char *rsig, unsigned char *rhash) - { - TLS_SIGALGS *shsigalgs = s->cert->shared_sigalgs; - if (!shsigalgs || idx >= (int)s->cert->shared_sigalgslen) - return 0; - shsigalgs += idx; - if (phash) - *phash = shsigalgs->hash_nid; - if (psign) - *psign = shsigalgs->sign_nid; - if (psignhash) - *psignhash = shsigalgs->signandhash_nid; - if (rsig) - *rsig = shsigalgs->rsign; - if (rhash) - *rhash = shsigalgs->rhash; - return s->cert->shared_sigalgslen; - } - -/* tls1_channel_id_hash calculates the signed data for a Channel ID on the given - * SSL connection and writes it to |md|. */ -int -tls1_channel_id_hash(EVP_MD_CTX *md, SSL *s) - { - EVP_MD_CTX ctx; - unsigned char temp_digest[EVP_MAX_MD_SIZE]; - unsigned temp_digest_len; - int i; - static const char kClientIDMagic[] = "TLS Channel ID signature"; +int SSL_get_sigalgs(SSL *s, int idx, int *psign, int *phash, int *psignhash, + uint8_t *rsig, uint8_t *rhash) { + const uint8_t *psig = s->cert->peer_sigalgs; - if (s->s3->handshake_buffer) - if (!ssl3_digest_cached_records(s, free_handshake_buffer)) - return 0; + if (psig == NULL) { + return 0; + } - EVP_DigestUpdate(md, kClientIDMagic, sizeof(kClientIDMagic)); + if (idx >= 0) { + idx <<= 1; + if (idx >= (int)s->cert->peer_sigalgslen) { + return 0; + } + psig += idx; + if (rhash) { + *rhash = psig[0]; + } + if (rsig) { + *rsig = psig[1]; + } + tls1_lookup_sigalg(phash, psign, psignhash, psig); + } - if (s->hit && s->s3->tlsext_channel_id_new) - { - static const char kResumptionMagic[] = "Resumption"; - EVP_DigestUpdate(md, kResumptionMagic, - sizeof(kResumptionMagic)); - if (s->session->original_handshake_hash_len == 0) - return 0; - EVP_DigestUpdate(md, s->session->original_handshake_hash, - s->session->original_handshake_hash_len); - } + return s->cert->peer_sigalgslen / 2; +} - EVP_MD_CTX_init(&ctx); - for (i = 0; i < SSL_MAX_DIGEST; i++) - { - if (s->s3->handshake_dgst[i] == NULL) - continue; - EVP_MD_CTX_copy_ex(&ctx, s->s3->handshake_dgst[i]); - EVP_DigestFinal_ex(&ctx, temp_digest, &temp_digest_len); - EVP_DigestUpdate(md, temp_digest, temp_digest_len); - } - EVP_MD_CTX_cleanup(&ctx); +int SSL_get_shared_sigalgs(SSL *s, int idx, int *psign, int *phash, + int *psignhash, uint8_t *rsig, uint8_t *rhash) { + TLS_SIGALGS *shsigalgs = s->cert->shared_sigalgs; - return 1; - } + if (!shsigalgs || idx >= (int)s->cert->shared_sigalgslen) { + return 0; + } + + shsigalgs += idx; + if (phash) { + *phash = shsigalgs->hash_nid; + } + if (psign) { + *psign = shsigalgs->sign_nid; + } + if (psignhash) { + *psignhash = shsigalgs->signandhash_nid; + } + if (rsig) { + *rsig = shsigalgs->rsign; + } + if (rhash) { + *rhash = shsigalgs->rhash; + } + + return s->cert->shared_sigalgslen; +} + +/* tls1_channel_id_hash calculates the signed data for a Channel ID on the + * given SSL connection and writes it to |md|. */ +int tls1_channel_id_hash(EVP_MD_CTX *md, SSL *s) { + EVP_MD_CTX ctx; + uint8_t temp_digest[EVP_MAX_MD_SIZE]; + unsigned temp_digest_len; + int i; + static const char kClientIDMagic[] = "TLS Channel ID signature"; + + if (s->s3->handshake_buffer && + !ssl3_digest_cached_records(s, free_handshake_buffer)) { + return 0; + } + + EVP_DigestUpdate(md, kClientIDMagic, sizeof(kClientIDMagic)); + + if (s->hit && s->s3->tlsext_channel_id_new) { + static const char kResumptionMagic[] = "Resumption"; + EVP_DigestUpdate(md, kResumptionMagic, sizeof(kResumptionMagic)); + if (s->session->original_handshake_hash_len == 0) { + return 0; + } + EVP_DigestUpdate(md, s->session->original_handshake_hash, + s->session->original_handshake_hash_len); + } + + EVP_MD_CTX_init(&ctx); + for (i = 0; i < SSL_MAX_DIGEST; i++) { + if (s->s3->handshake_dgst[i] == NULL) { + continue; + } + EVP_MD_CTX_copy_ex(&ctx, s->s3->handshake_dgst[i]); + EVP_DigestFinal_ex(&ctx, temp_digest, &temp_digest_len); + EVP_DigestUpdate(md, temp_digest, temp_digest_len); + } + EVP_MD_CTX_cleanup(&ctx); + + return 1; +} /* tls1_record_handshake_hashes_for_channel_id records the current handshake * hashes in |s->session| so that Channel ID resumptions can sign that data. */ -int tls1_record_handshake_hashes_for_channel_id(SSL *s) - { - int digest_len; - /* This function should never be called for a resumed session because - * the handshake hashes that we wish to record are for the original, - * full handshake. */ - if (s->hit) - return -1; - /* It only makes sense to call this function if Channel IDs have been - * negotiated. */ - if (!s->s3->tlsext_channel_id_new) - return -1; +int tls1_record_handshake_hashes_for_channel_id(SSL *s) { + int digest_len; + /* This function should never be called for a resumed session because the + * handshake hashes that we wish to record are for the original, full + * handshake. */ + if (s->hit) { + return -1; + } - digest_len = tls1_handshake_digest( - s, s->session->original_handshake_hash, - sizeof(s->session->original_handshake_hash)); - if (digest_len < 0) - return -1; + /* It only makes sense to call this function if Channel IDs have been + * negotiated. */ + if (!s->s3->tlsext_channel_id_new) { + return -1; + } - s->session->original_handshake_hash_len = digest_len; + digest_len = + tls1_handshake_digest(s, s->session->original_handshake_hash, + sizeof(s->session->original_handshake_hash)); + if (digest_len < 0) { + return -1; + } - return 1; - } + s->session->original_handshake_hash_len = digest_len; -int tls1_set_sigalgs(CERT *c, const int *psig_nids, size_t salglen, int client) - { - unsigned char *sigalgs, *sptr; - int rhash, rsign; - size_t i; - if (salglen & 1) - return 0; - sigalgs = OPENSSL_malloc(salglen); - if (sigalgs == NULL) - return 0; - for (i = 0, sptr = sigalgs; i < salglen; i+=2) - { - rhash = tls12_find_id(*psig_nids++, tls12_md, - sizeof(tls12_md)/sizeof(tls12_lookup)); - rsign = tls12_find_id(*psig_nids++, tls12_sig, - sizeof(tls12_sig)/sizeof(tls12_lookup)); + return 1; +} - if (rhash == -1 || rsign == -1) - goto err; - *sptr++ = rhash; - *sptr++ = rsign; - } +int tls1_set_sigalgs(CERT *c, const int *psig_nids, size_t salglen, + int client) { + uint8_t *sigalgs, *sptr; + int rhash, rsign; + size_t i; - if (client) - { - if (c->client_sigalgs) - OPENSSL_free(c->client_sigalgs); - c->client_sigalgs = sigalgs; - c->client_sigalgslen = salglen; - } - else - { - if (c->conf_sigalgs) - OPENSSL_free(c->conf_sigalgs); - c->conf_sigalgs = sigalgs; - c->conf_sigalgslen = salglen; - } + if (salglen & 1) { + return 0; + } - return 1; + sigalgs = OPENSSL_malloc(salglen); + if (sigalgs == NULL) { + return 0; + } - err: - OPENSSL_free(sigalgs); - return 0; - } + for (i = 0, sptr = sigalgs; i < salglen; i += 2) { + rhash = tls12_find_id(*psig_nids++, tls12_md, + sizeof(tls12_md) / sizeof(tls12_lookup)); + rsign = tls12_find_id(*psig_nids++, tls12_sig, + sizeof(tls12_sig) / sizeof(tls12_lookup)); + if (rhash == -1 || rsign == -1) { + goto err; + } + *sptr++ = rhash; + *sptr++ = rsign; + } + + if (client) { + if (c->client_sigalgs) { + OPENSSL_free(c->client_sigalgs); + } + c->client_sigalgs = sigalgs; + c->client_sigalgslen = salglen; + } else { + if (c->conf_sigalgs) { + OPENSSL_free(c->conf_sigalgs); + } + c->conf_sigalgs = sigalgs; + c->conf_sigalgslen = salglen; + } + + return 1; + +err: + OPENSSL_free(sigalgs); + return 0; +}
diff --git a/ssl/t1_reneg.c b/ssl/t1_reneg.c index 5d7a240..2d9fbc0 100644 --- a/ssl/t1_reneg.c +++ b/ssl/t1_reneg.c
@@ -115,148 +115,133 @@ #include "ssl_locl.h" + /* Add the client's renegotiation binding */ int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len, - int maxlen) - { - if(p) - { - if((s->s3->previous_client_finished_len+1) > maxlen) - { - OPENSSL_PUT_ERROR(SSL, ssl_add_clienthello_renegotiate_ext, SSL_R_RENEGOTIATE_EXT_TOO_LONG); - return 0; - } - - /* Length byte */ - *p = s->s3->previous_client_finished_len; - p++; - - memcpy(p, s->s3->previous_client_finished, - s->s3->previous_client_finished_len); -#ifdef OPENSSL_RI_DEBUG - fprintf(stderr, "%s RI extension sent by client\n", - s->s3->previous_client_finished_len ? "Non-empty" : "Empty"); -#endif - } - - *len=s->s3->previous_client_finished_len + 1; - - - return 1; + int maxlen) { + if (p) { + if (s->s3->previous_client_finished_len + 1 > maxlen) { + OPENSSL_PUT_ERROR(SSL, ssl_add_clienthello_renegotiate_ext, + SSL_R_RENEGOTIATE_EXT_TOO_LONG); + return 0; } -/* Parse the client's renegotiation binding and abort if it's not - right */ -int ssl_parse_clienthello_renegotiate_ext(SSL *s, CBS *cbs, int *out_alert) - { - CBS renegotiated_connection; + /* Length byte */ + *p = s->s3->previous_client_finished_len; + p++; - if (!CBS_get_u8_length_prefixed(cbs, &renegotiated_connection) || - CBS_len(cbs) != 0) - { - OPENSSL_PUT_ERROR(SSL, ssl_parse_clienthello_renegotiate_ext, SSL_R_RENEGOTIATION_ENCODING_ERR); - *out_alert = SSL_AD_DECODE_ERROR; - return 0; - } + memcpy(p, s->s3->previous_client_finished, + s->s3->previous_client_finished_len); + } - /* Check that the extension matches */ - if (!CBS_mem_equal(&renegotiated_connection, - s->s3->previous_client_finished, - s->s3->previous_client_finished_len)) - { - OPENSSL_PUT_ERROR(SSL, ssl_parse_clienthello_renegotiate_ext, SSL_R_RENEGOTIATION_MISMATCH); - *out_alert = SSL_AD_HANDSHAKE_FAILURE; - return 0; - } + *len = s->s3->previous_client_finished_len + 1; - s->s3->send_connection_binding = 1; + return 1; +} - return 1; - } +/* Parse the client's renegotiation binding and abort if it's not right */ +int ssl_parse_clienthello_renegotiate_ext(SSL *s, CBS *cbs, int *out_alert) { + CBS renegotiated_connection; + + if (!CBS_get_u8_length_prefixed(cbs, &renegotiated_connection) || + CBS_len(cbs) != 0) { + OPENSSL_PUT_ERROR(SSL, ssl_parse_clienthello_renegotiate_ext, + SSL_R_RENEGOTIATION_ENCODING_ERR); + *out_alert = SSL_AD_DECODE_ERROR; + return 0; + } + + /* Check that the extension matches */ + if (!CBS_mem_equal(&renegotiated_connection, s->s3->previous_client_finished, + s->s3->previous_client_finished_len)) { + OPENSSL_PUT_ERROR(SSL, ssl_parse_clienthello_renegotiate_ext, + SSL_R_RENEGOTIATION_MISMATCH); + *out_alert = SSL_AD_HANDSHAKE_FAILURE; + return 0; + } + + s->s3->send_connection_binding = 1; + + return 1; +} /* Add the server's renegotiation binding */ int ssl_add_serverhello_renegotiate_ext(SSL *s, unsigned char *p, int *len, - int maxlen) - { - if(p) - { - if((s->s3->previous_client_finished_len + - s->s3->previous_server_finished_len + 1) > maxlen) - { - OPENSSL_PUT_ERROR(SSL, ssl_add_serverhello_renegotiate_ext, SSL_R_RENEGOTIATE_EXT_TOO_LONG); - return 0; - } - - /* Length byte */ - *p = s->s3->previous_client_finished_len + s->s3->previous_server_finished_len; - p++; - - memcpy(p, s->s3->previous_client_finished, - s->s3->previous_client_finished_len); - p += s->s3->previous_client_finished_len; - - memcpy(p, s->s3->previous_server_finished, - s->s3->previous_server_finished_len); -#ifdef OPENSSL_RI_DEBUG - fprintf(stderr, "%s RI extension sent by server\n", - s->s3->previous_client_finished_len ? "Non-empty" : "Empty"); -#endif - } - - *len=s->s3->previous_client_finished_len - + s->s3->previous_server_finished_len + 1; - - return 1; + int maxlen) { + if (p) { + if (s->s3->previous_client_finished_len + + s->s3->previous_server_finished_len + 1 > + maxlen) { + OPENSSL_PUT_ERROR(SSL, ssl_add_serverhello_renegotiate_ext, + SSL_R_RENEGOTIATE_EXT_TOO_LONG); + return 0; } -/* Parse the server's renegotiation binding and abort if it's not - right */ -int ssl_parse_serverhello_renegotiate_ext(SSL *s, CBS *cbs, int *out_alert) - { - int expected_len=s->s3->previous_client_finished_len - + s->s3->previous_server_finished_len; - CBS renegotiated_connection; - const uint8_t *d; + /* Length byte */ + *p = s->s3->previous_client_finished_len + + s->s3->previous_server_finished_len; + p++; - /* Check for logic errors */ - assert(!expected_len || s->s3->previous_client_finished_len); - assert(!expected_len || s->s3->previous_server_finished_len); + memcpy(p, s->s3->previous_client_finished, + s->s3->previous_client_finished_len); + p += s->s3->previous_client_finished_len; - /* Parse out the extension contents. */ - if (!CBS_get_u8_length_prefixed(cbs, &renegotiated_connection) || - CBS_len(cbs) != 0) - { - OPENSSL_PUT_ERROR(SSL, ssl_parse_serverhello_renegotiate_ext, SSL_R_RENEGOTIATION_ENCODING_ERR); - *out_alert = SSL_AD_ILLEGAL_PARAMETER; - return 0; - } - - /* Check that the extension matches. */ - if(CBS_len(&renegotiated_connection) != expected_len) - { - OPENSSL_PUT_ERROR(SSL, ssl_parse_serverhello_renegotiate_ext, SSL_R_RENEGOTIATION_MISMATCH); - *out_alert = SSL_AD_HANDSHAKE_FAILURE; - return 0; - } + memcpy(p, s->s3->previous_server_finished, + s->s3->previous_server_finished_len); + } - d = CBS_data(&renegotiated_connection); - if(memcmp(d, s->s3->previous_client_finished, - s->s3->previous_client_finished_len)) - { - OPENSSL_PUT_ERROR(SSL, ssl_parse_serverhello_renegotiate_ext, SSL_R_RENEGOTIATION_MISMATCH); - *out_alert = SSL_AD_HANDSHAKE_FAILURE; - return 0; - } - d += s->s3->previous_client_finished_len; + *len = s->s3->previous_client_finished_len + + s->s3->previous_server_finished_len + 1; - if(memcmp(d, s->s3->previous_server_finished, - s->s3->previous_server_finished_len)) - { - OPENSSL_PUT_ERROR(SSL, ssl_parse_serverhello_renegotiate_ext, SSL_R_RENEGOTIATION_MISMATCH); - *out_alert = SSL_AD_ILLEGAL_PARAMETER; - return 0; - } - s->s3->send_connection_binding = 1; + return 1; +} - return 1; - } +/* Parse the server's renegotiation binding and abort if it's not right */ +int ssl_parse_serverhello_renegotiate_ext(SSL *s, CBS *cbs, int *out_alert) { + int expected_len = + s->s3->previous_client_finished_len + s->s3->previous_server_finished_len; + CBS renegotiated_connection; + const uint8_t *d; + + /* Check for logic errors */ + assert(!expected_len || s->s3->previous_client_finished_len); + assert(!expected_len || s->s3->previous_server_finished_len); + + /* Parse out the extension contents. */ + if (!CBS_get_u8_length_prefixed(cbs, &renegotiated_connection) || + CBS_len(cbs) != 0) { + OPENSSL_PUT_ERROR(SSL, ssl_parse_serverhello_renegotiate_ext, + SSL_R_RENEGOTIATION_ENCODING_ERR); + *out_alert = SSL_AD_ILLEGAL_PARAMETER; + return 0; + } + + /* Check that the extension matches. */ + if (CBS_len(&renegotiated_connection) != expected_len) { + OPENSSL_PUT_ERROR(SSL, ssl_parse_serverhello_renegotiate_ext, + SSL_R_RENEGOTIATION_MISMATCH); + *out_alert = SSL_AD_HANDSHAKE_FAILURE; + return 0; + } + + d = CBS_data(&renegotiated_connection); + if (memcmp(d, s->s3->previous_client_finished, + s->s3->previous_client_finished_len)) { + OPENSSL_PUT_ERROR(SSL, ssl_parse_serverhello_renegotiate_ext, + SSL_R_RENEGOTIATION_MISMATCH); + *out_alert = SSL_AD_HANDSHAKE_FAILURE; + return 0; + } + d += s->s3->previous_client_finished_len; + + if (memcmp(d, s->s3->previous_server_finished, + s->s3->previous_server_finished_len)) { + OPENSSL_PUT_ERROR(SSL, ssl_parse_serverhello_renegotiate_ext, + SSL_R_RENEGOTIATION_MISMATCH); + *out_alert = SSL_AD_ILLEGAL_PARAMETER; + return 0; + } + s->s3->send_connection_binding = 1; + + return 1; +}