/* * Save the ALPN extension in a ClientHello.|pkt| holds the contents of the ALPN * extension, not including type and length. |al| is a pointer to the alert * value to send in the event of a failure. Returns: 1 on success, 0 on error. */ int tls_parse_ctos_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { PACKET protocol_list, save_protocol_list, protocol; if (!SSL_IS_FIRST_HANDSHAKE(s)) return 1; if (!PACKET_as_length_prefixed_2(pkt, &protocol_list) || PACKET_remaining(&protocol_list) < 2) { *al = SSL_AD_DECODE_ERROR; return 0; } save_protocol_list = protocol_list; do { /* Protocol names can't be empty. */ if (!PACKET_get_length_prefixed_1(&protocol_list, &protocol) || PACKET_remaining(&protocol) == 0) { *al = SSL_AD_DECODE_ERROR; return 0; } } while (PACKET_remaining(&protocol_list) != 0); OPENSSL_free(s->s3->alpn_proposed); s->s3->alpn_proposed = NULL; s->s3->alpn_proposed_len = 0; if (!PACKET_memdup(&save_protocol_list, &s->s3->alpn_proposed, &s->s3->alpn_proposed_len)) { *al = SSL_AD_INTERNAL_ERROR; return 0; } return 1; }
int tls_parse_ctos_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { /* * We shouldn't accept this extension on a * renegotiation. */ if (SSL_IS_FIRST_HANDSHAKE(s)) s->s3->npn_seen = 1; return 1; }
/* * Generates the mac for the Finished message. Returns the length of the MAC or * 0 on error. */ size_t tls13_final_finish_mac(SSL *s, const char *str, size_t slen, unsigned char *out) { const EVP_MD *md = ssl_handshake_md(s); unsigned char hash[EVP_MAX_MD_SIZE]; size_t hashlen, ret = 0; EVP_PKEY *key = NULL; EVP_MD_CTX *ctx = EVP_MD_CTX_new(); if (!ssl_handshake_hash(s, hash, sizeof(hash), &hashlen)) { /* SSLfatal() already called */ goto err; } if (str == s->method->ssl3_enc->server_finished_label) { key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, s->server_finished_secret, hashlen); } else if (SSL_IS_FIRST_HANDSHAKE(s)) { key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, s->client_finished_secret, hashlen); } else { unsigned char finsecret[EVP_MAX_MD_SIZE]; if (!tls13_derive_finishedkey(s, ssl_handshake_md(s), s->client_app_traffic_secret, finsecret, hashlen)) goto err; key = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, finsecret, hashlen); OPENSSL_cleanse(finsecret, sizeof(finsecret)); } if (key == NULL || ctx == NULL || EVP_DigestSignInit(ctx, NULL, md, NULL, key) <= 0 || EVP_DigestSignUpdate(ctx, hash, hashlen) <= 0 || EVP_DigestSignFinal(ctx, out, &hashlen) <= 0) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS13_FINAL_FINISH_MAC, ERR_R_INTERNAL_ERROR); goto err; } ret = hashlen; err: EVP_PKEY_free(key); EVP_MD_CTX_free(ctx); return ret; }
int tls_parse_stoc_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { unsigned char *selected; unsigned char selected_len; PACKET tmppkt; /* Check if we are in a renegotiation. If so ignore this extension */ if (!SSL_IS_FIRST_HANDSHAKE(s)) return 1; /* We must have requested it. */ if (s->ctx->ext.npn_select_cb == NULL) { *al = SSL_AD_UNSUPPORTED_EXTENSION; return 0; } /* The data must be valid */ tmppkt = *pkt; if (!ssl_next_proto_validate(&tmppkt)) { *al = SSL_AD_DECODE_ERROR; return 0; } if (s->ctx->ext.npn_select_cb(s, &selected, &selected_len, PACKET_data(pkt), PACKET_remaining(pkt), s->ctx->ext.npn_select_cb_arg) != SSL_TLSEXT_ERR_OK) { *al = SSL_AD_INTERNAL_ERROR; return 0; } /* * Could be non-NULL if server has sent multiple NPN extensions in * a single Serverhello */ OPENSSL_free(s->ext.npn); s->ext.npn = OPENSSL_malloc(selected_len); if (s->ext.npn == NULL) { *al = SSL_AD_INTERNAL_ERROR; return 0; } memcpy(s->ext.npn, selected, selected_len); s->ext.npn_len = selected_len; s->s3->npn_seen = 1; return 1; }
int tls_construct_ctos_npn(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { if (s->ctx->ext.npn_select_cb == NULL || !SSL_IS_FIRST_HANDSHAKE(s)) return 1; /* * The client advertises an empty extension to indicate its support * for Next Protocol Negotiation */ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_next_proto_neg) || !WPACKET_put_bytes_u16(pkt, 0)) { SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_NPN, ERR_R_INTERNAL_ERROR); return 0; } return 1; }
int tls_construct_ctos_alpn(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { s->s3->alpn_sent = 0; if (s->ext.alpn == NULL || !SSL_IS_FIRST_HANDSHAKE(s)) return 1; if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_application_layer_protocol_negotiation) /* Sub-packet ALPN extension */ || !WPACKET_start_sub_packet_u16(pkt) || !WPACKET_sub_memcpy_u16(pkt, s->ext.alpn, s->ext.alpn_len) || !WPACKET_close(pkt)) { SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_ALPN, ERR_R_INTERNAL_ERROR); return 0; } s->s3->alpn_sent = 1; return 1; }