static const char *do_ssl_trace_str(int val, ssl_trace_tbl *tbl, size_t ntbl)
{
size_t i;
+
for (i = 0; i < ntbl; i++, tbl++) {
if (tbl->num == val)
return tbl->name;
size_t vlen, ssl_trace_tbl *tbl, size_t ntbl)
{
int val;
+
if (msglen % vlen)
return 0;
while (msglen) {
{SSL3_MT_SERVER_HELLO, "ServerHello"},
{DTLS1_MT_HELLO_VERIFY_REQUEST, "HelloVerifyRequest"},
{SSL3_MT_NEWSESSION_TICKET, "NewSessionTicket"},
+ {SSL3_MT_HELLO_RETRY_REQUEST, "HelloRetryRequest"},
+ {SSL3_MT_ENCRYPTED_EXTENSIONS, "EncryptedExtensions"},
{SSL3_MT_CERTIFICATE, "Certificate"},
{SSL3_MT_SERVER_KEY_EXCHANGE, "ServerKeyExchange"},
{SSL3_MT_CERTIFICATE_REQUEST, "CertificateRequest"},
- {SSL3_MT_CLIENT_KEY_EXCHANGE, "ClientKeyExchange"},
- {SSL3_MT_CERTIFICATE_STATUS, "CertificateStatus"},
{SSL3_MT_SERVER_DONE, "ServerHelloDone"},
{SSL3_MT_CERTIFICATE_VERIFY, "CertificateVerify"},
{SSL3_MT_CLIENT_KEY_EXCHANGE, "ClientKeyExchange"},
+ {SSL3_MT_CERTIFICATE_STATUS, "CertificateStatus"},
+ {SSL3_MT_CLIENT_KEY_EXCHANGE, "ClientKeyExchange"},
{SSL3_MT_FINISHED, "Finished"},
- {SSL3_MT_ENCRYPTED_EXTENSIONS, "EncryptedExtensions"},
- {SSL3_MT_CERTIFICATE_STATUS, "CertificateStatus"}
+ {SSL3_MT_CERTIFICATE_STATUS, "CertificateStatus"},
+ {SSL3_MT_KEY_UPDATE, "KeyUpdate"}
};
/* Cipher suites */
{0xCCAD, "TLS_DHE_PSK_WITH_CHACHA20_POLY1305"},
{0xCCAE, "TLS_RSA_PSK_WITH_CHACHA20_POLY1305"},
{0x1301, "TLS_AES_128_GCM_SHA256"},
+ {0x1302, "TLS_AES_256_GCM_SHA384"},
+ {0x1303, "TLS_CHACHA20_POLY1305_SHA256"},
+ {0x1304, "TLS_AES_128_CCM_SHA256"},
+ {0x1305, "TLS_AES_128_CCM_8_SHA256"},
{0xFEFE, "SSL_RSA_FIPS_WITH_DES_CBC_SHA"},
{0xFEFF, "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA"},
};
{TLSEXT_TYPE_server_authz, "server_authz"},
{TLSEXT_TYPE_cert_type, "cert_type"},
{TLSEXT_TYPE_key_share, "key_share"},
+ {TLSEXT_TYPE_psk, "psk"},
+ {TLSEXT_TYPE_psk_kex_modes, "psk_key_exchange_modes"},
{TLSEXT_TYPE_supported_groups, "supported_groups"},
{TLSEXT_TYPE_ec_point_formats, "ec_point_formats"},
{TLSEXT_TYPE_srp, "srp"},
# ifndef OPENSSL_NO_NEXTPROTONEG
{TLSEXT_TYPE_next_proto_neg, "next_proto_neg"},
# endif
+ {TLSEXT_TYPE_application_layer_protocol_negotiation,
+ "application_layer_protocol_negotiation"},
{TLSEXT_TYPE_signed_certificate_timestamp, "signed_certificate_timestamps"},
{TLSEXT_TYPE_padding, "padding"},
{TLSEXT_TYPE_encrypt_then_mac, "encrypt_then_mac"},
- {TLSEXT_TYPE_extended_master_secret, "extended_master_secret"}
+ {TLSEXT_TYPE_extended_master_secret, "extended_master_secret"},
+ {TLSEXT_TYPE_early_data_info, "ticket_early_data_info"},
+ {TLSEXT_TYPE_early_data, "early_data"}
};
static ssl_trace_tbl ssl_groups_tbl[] = {
{27, "brainpoolP384r1"},
{28, "brainpoolP512r1"},
{29, "ecdh_x25519"},
+ {256, "ffdhe2048"},
+ {257, "ffdhe3072"},
+ {258, "ffdhe4096"},
+ {259, "ffdhe6144"},
+ {260, "ffdhe8192"},
{0xFF01, "arbitrary_explicit_prime_curves"},
{0xFF02, "arbitrary_explicit_char2_curves"}
};
{2, "ansiX962_compressed_char2"}
};
-static ssl_trace_tbl ssl_md_tbl[] = {
- {TLSEXT_hash_none, "none"},
- {TLSEXT_hash_md5, "md5"},
- {TLSEXT_hash_sha1, "sha1"},
- {TLSEXT_hash_sha224, "sha224"},
- {TLSEXT_hash_sha256, "sha256"},
- {TLSEXT_hash_sha384, "sha384"},
- {TLSEXT_hash_sha512, "sha512"},
- {TLSEXT_hash_gostr3411, "md_gost94"},
- {TLSEXT_hash_gostr34112012_256, "md_gost2012_256"},
- {TLSEXT_hash_gostr34112012_512, "md_gost2012_512"}
-};
-
-static ssl_trace_tbl ssl_sig_tbl[] = {
- {TLSEXT_signature_anonymous, "anonymous"},
- {TLSEXT_signature_rsa, "rsa"},
- {TLSEXT_signature_dsa, "dsa"},
- {TLSEXT_signature_ecdsa, "ecdsa"},
- {TLSEXT_signature_gostr34102001, "gost2001"},
- {TLSEXT_signature_gostr34102012_256, "gost2012_256"},
- {TLSEXT_signature_gostr34102012_512, "gost2012_512"}
+static ssl_trace_tbl ssl_sigalg_tbl[] = {
+ {TLSEXT_SIGALG_ecdsa_secp256r1_sha256, "ecdsa_secp256r1_sha256"},
+ {TLSEXT_SIGALG_ecdsa_secp384r1_sha384, "ecdsa_secp384r1_sha384"},
+ {TLSEXT_SIGALG_ecdsa_secp521r1_sha512, "ecdsa_secp521r1_sha512"},
+ {TLSEXT_SIGALG_ecdsa_sha1, "ecdsa_sha1"},
+ {TLSEXT_SIGALG_rsa_pss_sha256, "rsa_pss_sha256"},
+ {TLSEXT_SIGALG_rsa_pss_sha384, "rsa_pss_sha384"},
+ {TLSEXT_SIGALG_rsa_pss_sha512, "rsa_pss_sha512"},
+ {TLSEXT_SIGALG_rsa_pkcs1_sha256, "rsa_pkcs1_sha256"},
+ {TLSEXT_SIGALG_rsa_pkcs1_sha384, "rsa_pkcs1_sha384"},
+ {TLSEXT_SIGALG_rsa_pkcs1_sha512, "rsa_pkcs1_sha512"},
+ {TLSEXT_SIGALG_rsa_pkcs1_sha1, "rsa_pkcs1_sha1"},
+ {TLSEXT_SIGALG_dsa_sha256, "dsa_sha256"},
+ {TLSEXT_SIGALG_dsa_sha384, "dsa_sha384"},
+ {TLSEXT_SIGALG_dsa_sha512, "dsa_sha512"},
+ {TLSEXT_SIGALG_dsa_sha1, "dsa_sha1"},
+ {TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256, "gost2012_256"},
+ {TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512, "gost2012_512"},
+ {TLSEXT_SIGALG_gostr34102001_gostr3411, "gost2001_gost94"},
};
static ssl_trace_tbl ssl_ctype_tbl[] = {
{66, "ecdsa_fixed_ecdh"}
};
+static ssl_trace_tbl ssl_psk_kex_modes_tbl[] = {
+ {TLSEXT_KEX_MODE_KE, "psk_ke"},
+ {TLSEXT_KEX_MODE_KE_DHE, "psk_dhe_ke"}
+};
+
static ssl_trace_tbl ssl_crypto_tbl[] = {
{TLS1_RT_CRYPTO_PREMASTER, "Premaster Secret"},
{TLS1_RT_CRYPTO_CLIENT_RANDOM, "Client Random"},
{TLS1_RT_CRYPTO_FIXED_IV | TLS1_RT_CRYPTO_READ, "Read IV (fixed part)"}
};
+static ssl_trace_tbl ssl_key_update_tbl[] = {
+ {SSL_KEY_UPDATE_NOT_REQUESTED, "update_not_requested"},
+ {SSL_KEY_UPDATE_REQUESTED, "update_requested"}
+};
+
static void ssl_print_hex(BIO *bio, int indent, const char *name,
const unsigned char *msg, size_t msglen)
{
size_t i;
+
BIO_indent(bio, indent, 80);
BIO_printf(bio, "%s (len=%d): ", name, (int)msglen);
for (i = 0; i < msglen; i++)
{
size_t blen;
const unsigned char *p = *pmsg;
+
if (*pmsglen < nlen)
return 0;
blen = p[0];
unsigned int *version)
{
int vers;
+
if (*pmsglen < 2)
return 0;
vers = ((*pmsg)[0] << 8) | (*pmsg)[1];
{
unsigned int tm;
const unsigned char *p = *pmsg;
+
if (*pmsglen < 32)
return 0;
tm = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
return 0;
if (SSL_USE_SIGALGS(s)) {
const unsigned char *p = *pmsg;
+ unsigned int sigalg = (p[0] << 8) | p[1];
+
BIO_indent(bio, indent, 80);
- BIO_printf(bio, "Signature Algorithm %s+%s (%d+%d)\n",
- ssl_trace_str(p[0], ssl_md_tbl),
- ssl_trace_str(p[1], ssl_sig_tbl), p[0], p[1]);
+ BIO_printf(bio, "Signature Algorithm: %s (0x%04x)\n",
+ ssl_trace_str(sigalg, ssl_sigalg_tbl), sigalg);
*pmsg += 2;
*pmsglen -= 2;
}
return ssl_print_hexbuf(bio, indent, "Signature", 2, pmsg, pmsglen);
}
-static int ssl_print_extension(BIO *bio, int indent, int server, int extype,
+static int ssl_print_extension(BIO *bio, int indent, int server,
+ unsigned char mt, int extype,
const unsigned char *ext, size_t extlen)
{
size_t xlen, share_len;
+ unsigned int sigalg;
+ uint32_t max_early_data;
+
BIO_indent(bio, indent, 80);
BIO_printf(bio, "extension_type=%s(%d), length=%d\n",
ssl_trace_str(extype, ssl_exts_tbl), extype, (int)extlen);
if (extlen != xlen + 2)
return 0;
return ssl_trace_list(bio, indent + 2, ext + 2, xlen, 2, ssl_groups_tbl);
+ case TLSEXT_TYPE_application_layer_protocol_negotiation:
+ if (extlen < 2)
+ return 0;
+ xlen = (ext[0] << 8) | ext[1];
+ if (extlen != xlen + 2)
+ return 0;
+ ext += 2;
+ while (xlen > 0) {
+ size_t plen = *ext++;
+
+ if (plen > xlen + 1)
+ return 0;
+ BIO_indent(bio, indent + 2, 80);
+ BIO_write(bio, ext, plen);
+ BIO_puts(bio, "\n");
+ ext += plen;
+ xlen -= plen + 1;
+ }
+ return 1;
case TLSEXT_TYPE_signature_algorithms:
ext += 2;
while (xlen > 0) {
BIO_indent(bio, indent + 2, 80);
- BIO_printf(bio, "%s+%s (%d+%d)\n",
- ssl_trace_str(ext[0], ssl_md_tbl),
- ssl_trace_str(ext[1], ssl_sig_tbl), ext[0], ext[1]);
+ sigalg = (ext[0] << 8) | ext[1];
+ BIO_printf(bio, "%s (0x%04x)\n",
+ ssl_trace_str(sigalg, ssl_sigalg_tbl), sigalg);
xlen -= 2;
ext += 2;
}
break;
case TLSEXT_TYPE_key_share:
+ if (mt == SSL3_MT_HELLO_RETRY_REQUEST) {
+ int group_id;
+
+ if (extlen != 2)
+ return 0;
+ group_id = (ext[0] << 8) | ext[1];
+ BIO_indent(bio, indent + 4, 80);
+ BIO_printf(bio, "NamedGroup: %s (%d)\n",
+ ssl_trace_str(group_id, ssl_groups_tbl), group_id);
+ break;
+ }
if (extlen < 2)
return 0;
if (server) {
if (xlen < share_len)
return 0;
BIO_indent(bio, indent + 4, 80);
- BIO_printf(bio, "NamedGroup: %s\n",
- ssl_trace_str(group_id, ssl_groups_tbl));
+ BIO_printf(bio, "NamedGroup: %s (%d)\n",
+ ssl_trace_str(group_id, ssl_groups_tbl), group_id);
ssl_print_hex(bio, indent + 4, "key_exchange: ", ext, share_len);
}
break;
return ssl_trace_list(bio, indent + 2, ext + 1, xlen, 2,
ssl_version_tbl);
+ case TLSEXT_TYPE_psk_kex_modes:
+ if (extlen < 1)
+ return 0;
+ xlen = ext[0];
+ if (extlen != xlen + 1)
+ return 0;
+ return ssl_trace_list(bio, indent + 2, ext + 1, xlen, 1,
+ ssl_psk_kex_modes_tbl);
+
+ case TLSEXT_TYPE_early_data_info:
+ if (extlen != 4)
+ return 0;
+ max_early_data = (ext[0] << 24) | (ext[1] << 16) | (ext[2] << 8)
+ | ext[3];
+ BIO_indent(bio, indent + 2, 80);
+ BIO_printf(bio, "max_early_data=%u\n", max_early_data);
+ break;
+
default:
BIO_dump_indent(bio, (const char *)ext, extlen, indent + 2);
}
}
static int ssl_print_extensions(BIO *bio, int indent, int server,
- const unsigned char *msg, size_t msglen)
+ unsigned char mt, const unsigned char **msgin,
+ size_t *msginlen)
{
- size_t extslen;
+ size_t extslen, msglen = *msginlen;
+ const unsigned char *msg = *msgin;
+
BIO_indent(bio, indent, 80);
if (msglen == 0) {
BIO_puts(bio, "No Extensions\n");
if (msglen < extlen + 4)
return 0;
msg += 4;
- if (!ssl_print_extension(bio, indent + 2, server, extype, msg, extlen))
+ if (!ssl_print_extension(bio, indent + 2, server, mt, extype, msg,
+ extlen))
return 0;
msg += extlen;
msglen -= extlen + 4;
}
+
+ *msgin = msg;
+ *msginlen = msglen;
return 1;
}
{
size_t len;
unsigned int cs;
+
if (!ssl_print_version(bio, indent, "client_version", &msg, &msglen, NULL))
return 0;
if (!ssl_print_random(bio, indent, &msg, &msglen))
msglen--;
len--;
}
- if (!ssl_print_extensions(bio, indent, 0, msg, msglen))
+ if (!ssl_print_extensions(bio, indent, 0, SSL3_MT_CLIENT_HELLO, &msg,
+ &msglen))
return 0;
return 1;
}
{
unsigned int cs;
unsigned int vers;
+
if (!ssl_print_version(bio, indent, "server_version", &msg, &msglen, &vers))
return 0;
if (!ssl_print_random(bio, indent, &msg, &msglen))
msg++;
msglen--;
}
- if (!ssl_print_extensions(bio, indent, 1, msg, msglen))
+ if (!ssl_print_extensions(bio, indent, 1, SSL3_MT_SERVER_HELLO, &msg,
+ &msglen))
return 0;
return 1;
}
static int ssl_get_keyex(const char **pname, SSL *ssl)
{
unsigned long alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey;
+
if (alg_k & SSL_kRSA) {
*pname = "rsa";
return SSL_kRSA;
const unsigned char *msg, size_t msglen)
{
const char *algname;
- int id;
- id = ssl_get_keyex(&algname, ssl);
+ int id = ssl_get_keyex(&algname, ssl);
+
BIO_indent(bio, indent, 80);
BIO_printf(bio, "KeyExchangeAlgorithm=%s\n", algname);
if (id & SSL_PSK) {
const unsigned char *msg, size_t msglen)
{
const char *algname;
- int id;
- id = ssl_get_keyex(&algname, ssl);
+ int id = ssl_get_keyex(&algname, ssl);
+
BIO_indent(bio, indent, 80);
BIO_printf(bio, "KeyExchangeAlgorithm=%s\n", algname);
if (id & SSL_PSK) {
size_t clen;
X509 *x;
const unsigned char *p = *pmsg, *q;
+
if (msglen < 3)
return 0;
clen = (p[0] << 16) | (p[1] << 8) | p[2];
return 1;
}
-static int ssl_print_certificates(BIO *bio, int indent,
+static int ssl_print_certificates(BIO *bio, SSL *s, int server, int indent,
const unsigned char *msg, size_t msglen)
{
size_t clen;
+
+ if (SSL_IS_TLS13(s)
+ && !ssl_print_hexbuf(bio, indent, "context", 1, &msg, &msglen))
+ return 0;
+
if (msglen < 3)
return 0;
clen = (msg[0] << 16) | (msg[1] << 8) | msg[2];
while (clen > 0) {
if (!ssl_print_certificate(bio, indent + 2, &msg, &clen))
return 0;
+ if (!ssl_print_extensions(bio, indent + 2, server, SSL3_MT_CERTIFICATE,
+ &msg, &clen))
+ return 0;
+
}
return 1;
}
const unsigned char *msg, size_t msglen)
{
size_t xlen;
- if (msglen < 1)
- return 0;
- xlen = msg[0];
- if (msglen < xlen + 1)
- return 0;
- msg++;
- BIO_indent(bio, indent, 80);
- BIO_printf(bio, "certificate_types (len=%d)\n", (int)xlen);
- if (!ssl_trace_list(bio, indent + 2, msg, xlen, 1, ssl_ctype_tbl))
- return 0;
- msg += xlen;
- msglen -= xlen + 1;
- if (!SSL_USE_SIGALGS(s))
- goto skip_sig;
- if (msglen < 2)
- return 0;
- xlen = (msg[0] << 8) | msg[1];
- if (msglen < xlen + 2 || (xlen & 1))
- return 0;
- msg += 2;
- BIO_indent(bio, indent, 80);
- BIO_printf(bio, "signature_algorithms (len=%d)\n", (int)xlen);
- while (xlen > 0) {
- BIO_indent(bio, indent + 2, 80);
- BIO_printf(bio, "%s+%s (%d+%d)\n",
- ssl_trace_str(msg[0], ssl_md_tbl),
- ssl_trace_str(msg[1], ssl_sig_tbl), msg[0], msg[1]);
- xlen -= 2;
+ unsigned int sigalg;
+
+ if (SSL_IS_TLS13(s)) {
+ if (!ssl_print_hexbuf(bio, indent, "request_context", 1, &msg, &msglen))
+ return 0;
+ } else {
+ if (msglen < 1)
+ return 0;
+ xlen = msg[0];
+ if (msglen < xlen + 1)
+ return 0;
+ msg++;
+ BIO_indent(bio, indent, 80);
+ BIO_printf(bio, "certificate_types (len=%d)\n", (int)xlen);
+ if (!ssl_trace_list(bio, indent + 2, msg, xlen, 1, ssl_ctype_tbl))
+ return 0;
+ msg += xlen;
+ msglen -= xlen + 1;
+ }
+ if (SSL_USE_SIGALGS(s)) {
+ if (msglen < 2)
+ return 0;
+ xlen = (msg[0] << 8) | msg[1];
+ if (msglen < xlen + 2 || (xlen & 1))
+ return 0;
msg += 2;
+ msglen -= xlen + 2;
+ BIO_indent(bio, indent, 80);
+ BIO_printf(bio, "signature_algorithms (len=%d)\n", (int)xlen);
+ while (xlen > 0) {
+ BIO_indent(bio, indent + 2, 80);
+ sigalg = (msg[0] << 8) | msg[1];
+ BIO_printf(bio, "%s (0x%04x)\n",
+ ssl_trace_str(sigalg, ssl_sigalg_tbl), sigalg);
+ xlen -= 2;
+ msg += 2;
+ }
+ msg += xlen;
}
- msg += xlen;
- msglen -= xlen + 2;
- skip_sig:
xlen = (msg[0] << 8) | msg[1];
BIO_indent(bio, indent, 80);
if (msglen < xlen + 2)
return 0;
msg += 2;
- msglen -= 2;
+ msglen -= 2 + xlen;
BIO_printf(bio, "certificate_authorities (len=%d)\n", (int)xlen);
while (xlen > 0) {
size_t dlen;
xlen -= dlen + 2;
msg += dlen;
}
- return 1;
+ if (SSL_IS_TLS13(s)) {
+ if (!ssl_print_hexbuf(bio, indent, "request_extensions", 2,
+ &msg, &msglen))
+ return 0;
+ }
+ return msglen == 0;
}
-static int ssl_print_ticket(BIO *bio, int indent,
+static int ssl_print_ticket(BIO *bio, int indent, SSL *s,
const unsigned char *msg, size_t msglen)
{
unsigned int tick_life;
+
if (msglen == 0) {
BIO_indent(bio, indent + 2, 80);
BIO_puts(bio, "No Ticket\n");
msg += 4;
BIO_indent(bio, indent + 2, 80);
BIO_printf(bio, "ticket_lifetime_hint=%u\n", tick_life);
+ if (SSL_IS_TLS13(s)) {
+ unsigned int ticket_age_add;
+
+ if (msglen < 4)
+ return 0;
+ ticket_age_add = (msg[0] << 24) | (msg[1] << 16) | (msg[2] << 8)
+ | msg[3];
+ msglen -= 4;
+ msg += 4;
+ BIO_indent(bio, indent + 2, 80);
+ BIO_printf(bio, "ticket_age_add=%u\n", ticket_age_add);
+ }
if (!ssl_print_hexbuf(bio, indent + 2, "ticket", 2, &msg, &msglen))
return 0;
+ if (SSL_IS_TLS13(s) && !ssl_print_extensions(bio, indent + 2, 0,
+ SSL3_MT_NEWSESSION_TICKET,
+ &msg, &msglen))
+ return 0;
if (msglen)
return 0;
return 1;
}
-static int ssl_print_handshake(BIO *bio, SSL *ssl,
+static int ssl_print_handshake(BIO *bio, SSL *ssl, int server,
const unsigned char *msg, size_t msglen,
int indent)
{
size_t hlen;
unsigned char htype;
+
if (msglen < 4)
return 0;
htype = msg[0];
break;
case SSL3_MT_CERTIFICATE:
- if (!ssl_print_certificates(bio, indent + 2, msg, msglen))
+ if (!ssl_print_certificates(bio, ssl, server, indent + 2, msg, msglen))
return 0;
break;
break;
case SSL3_MT_NEWSESSION_TICKET:
- if (!ssl_print_ticket(bio, indent + 2, msg, msglen))
+ if (!ssl_print_ticket(bio, indent + 2, ssl, msg, msglen))
+ return 0;
+ break;
+
+ case SSL3_MT_HELLO_RETRY_REQUEST:
+ if (!ssl_print_version(bio, indent + 2, "server_version", &msg, &msglen,
+ NULL)
+ || !ssl_print_extensions(bio, indent + 2, 1,
+ SSL3_MT_HELLO_RETRY_REQUEST, &msg,
+ &msglen))
return 0;
break;
case SSL3_MT_ENCRYPTED_EXTENSIONS:
- if (!ssl_print_extensions(bio, indent + 2, 1, msg, msglen))
+ if (!ssl_print_extensions(bio, indent + 2, 1,
+ SSL3_MT_ENCRYPTED_EXTENSIONS, &msg, &msglen))
+ return 0;
+ break;
+
+ case SSL3_MT_KEY_UPDATE:
+ if (msglen != 1) {
+ ssl_print_hex(bio, indent + 2, "unexpected value", msg, msglen);
+ return 0;
+ }
+ if (!ssl_trace_list(bio, indent + 2, msg, msglen, 1,
+ ssl_key_update_tbl))
return 0;
break;
}
break;
case SSL3_RT_HANDSHAKE:
- if (!ssl_print_handshake(bio, ssl, msg, msglen, 4))
+ if (!ssl_print_handshake(bio, ssl, ssl->server ? write_p : !write_p,
+ msg, msglen, 4))
BIO_printf(bio, "Message length parse error!\n");
break;