X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fs3_srvr.c;h=200f4951fb193825d3bbe5a58d5302d0e7ca49ff;hp=87678c181b0a9926d5cd7ac9503f20b3224cd206;hb=c6913eeb762edffddecaaba5c84909d7a7962927;hpb=ce33b42bc65a32e21c5553a7b7fa774420c0e0e1 diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index 87678c181b..200f4951fb 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -152,7 +152,6 @@ #define NETSCAPE_HANG_BUG #include -#include #include "ssl_locl.h" #include "kssl_lcl.h" #include @@ -181,7 +180,7 @@ static const SSL_METHOD *ssl3_get_server_method(int ver) } #ifndef OPENSSL_NO_SRP -static int ssl_check_srp_ext_ClientHello(SSL *s,int *al) +static int ssl_check_srp_ext_ClientHello(SSL *s, int *al) { int ret = SSL_ERROR_NONE; @@ -403,10 +402,31 @@ int ssl3_accept(SSL *s) s->state=SSL3_ST_SW_CHANGE_A; #endif else - s->state=SSL3_ST_SW_CERT_A; - s->init_num=0; +#ifndef OPENSSL_NO_TLSEXT + s->state = SSL3_ST_SW_SUPPLEMENTAL_DATA_A; +#else + s->state = SSL3_ST_SW_CERT_A; +#endif + s->init_num = 0; break; +#ifndef OPENSSL_NO_TLSEXT + case SSL3_ST_SW_SUPPLEMENTAL_DATA_A: + case SSL3_ST_SW_SUPPLEMENTAL_DATA_B: + /* We promised to send an audit proof in the hello. */ + if (s->s3->tlsext_authz_promised_to_client) + { + ret = tls1_send_server_supplemental_data(s); + if (ret <= 0) goto end; + } + else + skip = 1; + + s->state = SSL3_ST_SW_CERT_A; + s->init_num = 0; + break; +#endif + case SSL3_ST_SW_CERT_A: case SSL3_ST_SW_CERT_B: /* Check if it is anon DH or anon ECDH, */ @@ -620,13 +640,13 @@ int ssl3_accept(SSL *s) #endif s->init_num = 0; } - else if (TLS1_get_version(s) >= TLS1_2_VERSION) + else if (SSL_USE_SIGALGS(s)) { s->state=SSL3_ST_SR_CERT_VRFY_A; s->init_num=0; if (!s->session->peer) break; - /* For TLS v1.2 freeze the handshake buffer + /* For sigalgs freeze the handshake buffer * at this point and digest cached records. */ if (!s->s3->handshake_buffer) @@ -848,24 +868,15 @@ end: int ssl3_send_hello_request(SSL *s) { - unsigned char *p; if (s->state == SSL3_ST_SW_HELLO_REQ_A) { - p=(unsigned char *)s->init_buf->data; - *(p++)=SSL3_MT_HELLO_REQUEST; - *(p++)=0; - *(p++)=0; - *(p++)=0; - + ssl_set_handshake_header(s, SSL3_MT_HELLO_REQUEST, 0); s->state=SSL3_ST_SW_HELLO_REQ_B; - /* number of bytes to write */ - s->init_num=4; - s->init_off=0; } /* SSL3_ST_SW_HELLO_REQ_B */ - return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); } int ssl3_check_client_hello(SSL *s) @@ -916,13 +927,14 @@ int ssl3_check_client_hello(SSL *s) int ssl3_get_client_hello(SSL *s) { - int i,j,ok,al,ret= -1; + int i,j,ok,al=SSL_AD_INTERNAL_ERROR,ret= -1; unsigned int cookie_len; long n; unsigned long id; - unsigned char *p,*d,*q; + unsigned char *p,*d; SSL_CIPHER *c; #ifndef OPENSSL_NO_COMP + unsigned char *q; SSL_COMP *comp=NULL; #endif STACK_OF(SSL_CIPHER) *ciphers=NULL; @@ -955,8 +967,9 @@ int ssl3_get_client_hello(SSL *s) s->client_version=(((int)p[0])<<8)|(int)p[1]; p+=2; - if ((s->version == DTLS1_VERSION && s->client_version > s->version) || - (s->version != DTLS1_VERSION && s->client_version < s->version)) + if ((SSL_IS_DTLS(s) && s->client_version > s->version + && s->method->version != DTLS_ANY_VERSION) || + (!SSL_IS_DTLS(s) && s->client_version < s->version)) { SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_WRONG_VERSION_NUMBER); if ((s->client_version>>8) == SSL3_VERSION_MAJOR) @@ -1025,7 +1038,7 @@ int ssl3_get_client_hello(SSL *s) p+=j; - if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER) + if (SSL_IS_DTLS(s)) { /* cookie stuff */ cookie_len = *(p++); @@ -1074,6 +1087,30 @@ int ssl3_get_client_hello(SSL *s) } p += cookie_len; + if (s->method->version == DTLS_ANY_VERSION) + { + /* Select version to use */ + if (s->client_version <= DTLS1_2_VERSION && + !(s->options & SSL_OP_NO_DTLSv1_2)) + { + s->version = DTLS1_2_VERSION; + s->method = DTLSv1_2_server_method(); + } + else if (s->client_version <= DTLS1_VERSION && + !(s->options & SSL_OP_NO_DTLSv1)) + { + s->version = DTLS1_VERSION; + s->method = DTLSv1_server_method(); + } + else + { + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_WRONG_VERSION_NUMBER); + s->version = s->client_version; + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } + s->session->ssl_version = s->version; + } } n2s(p,i); @@ -1158,7 +1195,9 @@ int ssl3_get_client_hello(SSL *s) SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_LENGTH_MISMATCH); goto f_err; } +#ifndef OPENSSL_NO_COMP q=p; +#endif for (j=0; joptions & SSL_OP_NO_COMPRESSION) { - al=SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_INCONSISTENT_COMPRESSION); goto f_err; } @@ -1267,7 +1304,6 @@ int ssl3_get_client_hello(SSL *s) } if (s->s3->tmp.new_compression == NULL) { - al=SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_INVALID_COMPRESSION_ALGORITHM); goto f_err; } @@ -1316,7 +1352,6 @@ int ssl3_get_client_hello(SSL *s) */ if (s->session->compress_meth != 0) { - al=SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_INCONSISTENT_COMPRESSION); goto f_err; } @@ -1342,6 +1377,14 @@ int ssl3_get_client_hello(SSL *s) goto f_err; } ciphers=NULL; + /* Let cert callback update server certificates if required */ + if (s->cert->cert_cb + && s->cert->cert_cb(s, s->cert->cert_cb_arg) <= 0) + { + al=SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CERT_CB_ERROR); + goto f_err; + } c=ssl3_choose_cipher(s,s->session->ciphers, SSL_get_ciphers(s)); @@ -1391,7 +1434,7 @@ int ssl3_get_client_hello(SSL *s) s->s3->tmp.new_cipher=s->session->cipher; } - if (TLS1_get_version(s) < TLS1_2_VERSION || !(s->verify_mode & SSL_VERIFY_PEER)) + if (!SSL_USE_SIGALGS(s) || !(s->verify_mode & SSL_VERIFY_PEER)) { if (!ssl3_digest_cached_records(s)) goto f_err; @@ -1408,6 +1451,16 @@ int ssl3_get_client_hello(SSL *s) * s->tmp.new_cipher - the new cipher to use. */ + /* Handles TLS extensions that we couldn't check earlier */ + if (s->version >= SSL3_VERSION) + { + if (ssl_check_clienthello_tlsext_late(s) <= 0) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT); + goto err; + } + } + if (ret < 0) ret=1; if (0) { @@ -1441,7 +1494,7 @@ int ssl3_send_server_hello(SSL *s) return -1; #endif /* Do the message type and length last */ - d=p= &(buf[4]); + d=p= ssl_handshake_start(s); *(p++)=s->version>>8; *(p++)=s->version&0xff; @@ -1507,42 +1560,25 @@ int ssl3_send_server_hello(SSL *s) #endif /* do the header */ l=(p-d); - d=buf; - *(d++)=SSL3_MT_SERVER_HELLO; - l2n3(l,d); - + ssl_set_handshake_header(s, SSL3_MT_SERVER_HELLO, l); s->state=SSL3_ST_SW_SRVR_HELLO_B; - /* number of bytes to write */ - s->init_num=p-buf; - s->init_off=0; } /* SSL3_ST_SW_SRVR_HELLO_B */ - return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); } int ssl3_send_server_done(SSL *s) { - unsigned char *p; if (s->state == SSL3_ST_SW_SRVR_DONE_A) { - p=(unsigned char *)s->init_buf->data; - - /* do the header */ - *(p++)=SSL3_MT_SERVER_DONE; - *(p++)=0; - *(p++)=0; - *(p++)=0; - - s->state=SSL3_ST_SW_SRVR_DONE_B; - /* number of bytes to write */ - s->init_num=4; - s->init_off=0; + 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(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); } int ssl3_send_server_key_exchange(SSL *s) @@ -1680,8 +1716,8 @@ int ssl3_send_server_key_exchange(SSL *s) ecdhp=cert->ecdh_tmp; if (s->cert->ecdh_tmp_auto) { - /* Get NID of first shared curve */ - int nid = tls1_shared_curve(s, 0); + /* Get NID of appropriate shared curve */ + int nid = tls1_shared_curve(s, -2); if (nid != NID_undef) ecdhp = EC_KEY_new_by_curve_name(nid); } @@ -1866,13 +1902,12 @@ int ssl3_send_server_key_exchange(SSL *s) kn=0; } - if (!BUF_MEM_grow_clean(buf,n+4+kn)) + if (!BUF_MEM_grow_clean(buf,n+SSL_HM_HEADER_LENGTH(s)+kn)) { SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,ERR_LIB_BUF); goto err; } - d=(unsigned char *)s->init_buf->data; - p= &(d[4]); + d = p = ssl_handshake_start(s); for (i=0; r[i] != NULL && i<4; i++) { @@ -1931,8 +1966,7 @@ int ssl3_send_server_key_exchange(SSL *s) /* n is the length of the params, they start at &(d[4]) * and p points to the space at the end. */ #ifndef OPENSSL_NO_RSA - if (pkey->type == EVP_PKEY_RSA - && TLS1_get_version(s) < TLS1_2_VERSION) + if (pkey->type == EVP_PKEY_RSA && !SSL_USE_SIGALGS(s)) { q=md_buf; j=0; @@ -1944,7 +1978,7 @@ int ssl3_send_server_key_exchange(SSL *s) ?s->ctx->md5:s->ctx->sha1, NULL); EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE); EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE); - EVP_DigestUpdate(&md_ctx,&(d[4]),n); + EVP_DigestUpdate(&md_ctx,d,n); EVP_DigestFinal_ex(&md_ctx,q, (unsigned int *)&i); q+=i; @@ -1963,9 +1997,8 @@ int ssl3_send_server_key_exchange(SSL *s) #endif if (md) { - /* For TLS1.2 and later send signature - * algorithm */ - if (TLS1_get_version(s) >= TLS1_2_VERSION) + /* send signature algorithm */ + if (SSL_USE_SIGALGS(s)) { if (!tls12_get_sigandhash(p, pkey, md)) { @@ -1983,7 +2016,7 @@ int ssl3_send_server_key_exchange(SSL *s) EVP_SignInit_ex(&md_ctx, md, NULL); EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE); EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE); - EVP_SignUpdate(&md_ctx,&(d[4]),n); + EVP_SignUpdate(&md_ctx,d,n); if (!EVP_SignFinal(&md_ctx,&(p[2]), (unsigned int *)&i,pkey)) { @@ -1992,7 +2025,7 @@ int ssl3_send_server_key_exchange(SSL *s) } s2n(i,p); n+=i+2; - if (TLS1_get_version(s) >= TLS1_2_VERSION) + if (SSL_USE_SIGALGS(s)) n+= 2; } else @@ -2004,18 +2037,12 @@ int ssl3_send_server_key_exchange(SSL *s) } } - *(d++)=SSL3_MT_SERVER_KEY_EXCHANGE; - l2n3(n,d); - - /* we should now have things packed up, so lets send - * it off */ - s->init_num=n+4; - s->init_off=0; + 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(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); f_err: ssl3_send_alert(s,SSL3_AL_FATAL,al); err: @@ -2039,7 +2066,7 @@ int ssl3_send_certificate_request(SSL *s) { buf=s->init_buf; - d=p=(unsigned char *)&(buf->data[4]); + d=p=ssl_handshake_start(s); /* get the list of acceptable cert types */ p++; @@ -2048,11 +2075,13 @@ int ssl3_send_certificate_request(SSL *s) p+=n; n++; - if (TLS1_get_version(s) >= TLS1_2_VERSION) + if (SSL_USE_SIGALGS(s)) { - nl = tls12_get_req_sig_algs(s, p + 2); + const unsigned char *psigs; + nl = tls12_get_psigalgs(s, &psigs); s2n(nl, p); - p += nl + 2; + memcpy(p, psigs, nl); + p += nl; n += nl + 2; } @@ -2092,34 +2121,29 @@ int ssl3_send_certificate_request(SSL *s) } } /* else no CA names */ - p=(unsigned char *)&(buf->data[4+off]); + p = ssl_handshake_start(s) + off; s2n(nl,p); - d=(unsigned char *)buf->data; - *(d++)=SSL3_MT_CERTIFICATE_REQUEST; - l2n3(n,d); - - /* we should now have things packed up, so lets send - * it off */ + ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_REQUEST, n); - s->init_num=n+4; - s->init_off=0; #ifdef NETSCAPE_HANG_BUG - 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; + if (!SSL_IS_DTLS(s)) + { + 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; + } #endif s->state = SSL3_ST_SW_CERT_REQ_B; } /* SSL3_ST_SW_CERT_REQ_B */ - return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); err: return(-1); } @@ -3023,28 +3047,17 @@ int ssl3_get_cert_verify(SSL *s) } else { - if (TLS1_get_version(s) >= TLS1_2_VERSION) + if (SSL_USE_SIGALGS(s)) { - int sigalg = tls12_get_sigid(pkey); - /* Should never happen */ - if (sigalg == -1) + int rv = tls12_check_peer_sigalg(&md, s, p, pkey); + if (rv == -1) { - SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,ERR_R_INTERNAL_ERROR); - al=SSL_AD_INTERNAL_ERROR; + al = SSL_AD_INTERNAL_ERROR; goto f_err; } - /* Check key type is consistent with signature */ - if (sigalg != (int)p[1]) + else if (rv == 0) { - SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_WRONG_SIGNATURE_TYPE); - al=SSL_AD_DECODE_ERROR; - goto f_err; - } - md = tls12_get_hash(p[0]); - if (md == NULL) - { - SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_UNKNOWN_DIGEST); - al=SSL_AD_DECODE_ERROR; + al = SSL_AD_DECODE_ERROR; goto f_err; } #ifdef SSL_DEBUG @@ -3070,7 +3083,7 @@ fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md)); goto f_err; } - if (TLS1_get_version(s) >= TLS1_2_VERSION) + if (SSL_USE_SIGALGS(s)) { long hdatalen = 0; void *hdata; @@ -3323,7 +3336,7 @@ int ssl3_get_client_certificate(SSL *s) if (i <= 0) { al=ssl_verify_alarm_type(s->verify_result); - SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_NO_CERTIFICATE_RETURNED); + SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_CERTIFICATE_VERIFY_FAILED); goto f_err; } } @@ -3366,7 +3379,6 @@ err: int ssl3_send_server_certificate(SSL *s) { - unsigned long l; CERT_PKEY *cpk; if (s->state == SSL3_ST_SW_CERT_A) @@ -3383,14 +3395,12 @@ int ssl3_send_server_certificate(SSL *s) } } - l=ssl3_output_cert_chain(s,cpk); + ssl3_output_cert_chain(s,cpk); s->state=SSL3_ST_SW_CERT_B; - s->init_num=(int)l; - s->init_off=0; } /* SSL3_ST_SW_CERT_B */ - return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); } #ifndef OPENSSL_NO_TLSEXT @@ -3444,22 +3454,17 @@ int ssl3_send_newsession_ticket(SSL *s) SSL_SESSION_free(sess); /* Grow buffer if need be: the length calculation is as - * follows 1 (size of message name) + 3 (message length - * bytes) + 4 (ticket lifetime hint) + 2 (ticket length) + + * follows handshake_header_length + + * 4 (ticket lifetime hint) + 2 (ticket length) + * 16 (key name) + max_iv_len (iv length) + * session_length + max_enc_block_size (max encrypted session * length) + max_md_size (HMAC). */ if (!BUF_MEM_grow(s->init_buf, - 26 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH + - EVP_MAX_MD_SIZE + slen)) + SSL_HM_HEADER_LENGTH(s) + 22 + EVP_MAX_IV_LENGTH + + EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE + slen)) return -1; - - p=(unsigned char *)s->init_buf->data; - /* do the header */ - *(p++)=SSL3_MT_NEWSESSION_TICKET; - /* Skip message length for now */ - p += 3; + p = ssl_handshake_start(s); EVP_CIPHER_CTX_init(&ctx); HMAC_CTX_init(&hctx); /* Initialize HMAC and cipher contexts. If callback present @@ -3514,21 +3519,17 @@ int ssl3_send_newsession_ticket(SSL *s) p += hlen; /* Now write out lengths: p points to end of data written */ /* Total length */ - len = p - (unsigned char *)s->init_buf->data; - p=(unsigned char *)s->init_buf->data + 1; - l2n3(len - 4, p); /* Message length */ - p += 4; - s2n(len - 10, p); /* Ticket length */ - - /* number of bytes to write */ - s->init_num= len; + len = p - ssl_handshake_start(s); + ssl_set_handshake_header(s, SSL3_MT_NEWSESSION_TICKET, len); + /* Skip ticket lifetime hint */ + p = ssl_handshake_start(s) + 4; + s2n(len - 6, p); s->state=SSL3_ST_SW_SESSION_TICKET_B; - s->init_off=0; OPENSSL_free(senc); } /* SSL3_ST_SW_SESSION_TICKET_B */ - return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); } int ssl3_send_cert_status(SSL *s) @@ -3566,7 +3567,7 @@ int ssl3_send_cert_status(SSL *s) return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); } -# ifndef OPENSSL_NO_NPN +# ifndef OPENSSL_NO_NEXTPROTONEG /* ssl3_get_next_proto reads a Next Protocol Negotiation handshake message. It * sets the next_proto member in s if found */ int ssl3_get_next_proto(SSL *s) @@ -3633,4 +3634,99 @@ int ssl3_get_next_proto(SSL *s) return 1; } # endif + +int tls1_send_server_supplemental_data(SSL *s) + { + size_t length = 0; + const unsigned char *authz, *orig_authz; + unsigned char *p; + size_t authz_length, i; + + if (s->state != SSL3_ST_SW_SUPPLEMENTAL_DATA_A) + return ssl3_do_write(s, SSL3_RT_HANDSHAKE); + + orig_authz = authz = ssl_get_authz_data(s, &authz_length); + if (authz == NULL) + { + /* This should never occur. */ + return 0; + } + + /* First we walk over the authz data to see how long the handshake + * message will be. */ + for (i = 0; i < authz_length; i++) + { + unsigned short len; + unsigned char type; + + type = *(authz++); + n2s(authz, len); + /* n2s increments authz by 2*/ + i += 2; + + if (memchr(s->s3->tlsext_authz_client_types, + type, + s->s3->tlsext_authz_client_types_len) != NULL) + length += 1 /* authz type */ + 2 /* length */ + len; + + authz += len; + i += len; + } + + length += 1 /* handshake type */ + + 3 /* handshake length */ + + 3 /* supplemental data length */ + + 2 /* supplemental entry type */ + + 2 /* supplemental entry length */; + + if (!BUF_MEM_grow_clean(s->init_buf, length)) + { + SSLerr(SSL_F_TLS1_SEND_SERVER_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB); + return 0; + } + + p = (unsigned char *)s->init_buf->data; + *(p++) = SSL3_MT_SUPPLEMENTAL_DATA; + /* Handshake length */ + l2n3(length - 4, p); + /* Length of supplemental data */ + l2n3(length - 7, p); + /* Supplemental data type */ + s2n(TLSEXT_SUPPLEMENTALDATATYPE_authz_data, p); + /* Its length */ + s2n(length - 11, p); + + authz = orig_authz; + + /* Walk over the authz again and append the selected elements. */ + for (i = 0; i < authz_length; i++) + { + unsigned short len; + unsigned char type; + + type = *(authz++); + n2s(authz, len); + /* n2s increments authz by 2 */ + i += 2; + + if (memchr(s->s3->tlsext_authz_client_types, + type, + s->s3->tlsext_authz_client_types_len) != NULL) + { + *(p++) = type; + s2n(len, p); + memcpy(p, authz, len); + p += len; + } + + authz += len; + i += len; + } + + s->state = SSL3_ST_SW_SUPPLEMENTAL_DATA_B; + s->init_num = length; + s->init_off = 0; + + return ssl3_do_write(s, SSL3_RT_HANDSHAKE); + } #endif