EXT_RETURN tls_construct_stoc_supported_groups(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { const unsigned char *groups; size_t numgroups, i, first = 1; /* s->s3->group_id is non zero if we accepted a key_share */ if (s->s3->group_id == 0) return EXT_RETURN_NOT_SENT; /* Get our list of supported groups */ if (!tls1_get_curvelist(s, 0, &groups, &numgroups) || numgroups == 0) { SSLerr(SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS, ERR_R_INTERNAL_ERROR); return EXT_RETURN_FAIL; } /* Copy group ID if supported */ for (i = 0; i < numgroups; i++, groups += 2) { if (tls_curve_allowed(s, groups, SSL_SECOP_CURVE_SUPPORTED)) { if (first) { /* * Check if the client is already using our preferred group. If * so we don't need to add this extension */ if (s->s3->group_id == GET_GROUP_ID(groups, 0)) return EXT_RETURN_NOT_SENT; /* Add extension header */ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_groups) /* Sub-packet for supported_groups extension */ || !WPACKET_start_sub_packet_u16(pkt) || !WPACKET_start_sub_packet_u16(pkt)) { SSLerr(SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS, ERR_R_INTERNAL_ERROR); return EXT_RETURN_FAIL; } first = 0; } if (!WPACKET_put_bytes_u16(pkt, GET_GROUP_ID(groups, 0))) { SSLerr(SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS, ERR_R_INTERNAL_ERROR); return EXT_RETURN_FAIL; } } } if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) { SSLerr(SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS, ERR_R_INTERNAL_ERROR); return EXT_RETURN_FAIL; } return EXT_RETURN_SENT; }
/* Check that a curve is one of our preferences. */ int tls1_check_curve(SSL *s, const uint16_t curve_id) { const uint16_t *curves; size_t curveslen, i; tls1_get_curvelist(s, 0, &curves, &curveslen); for (i = 0; i < curveslen; i++) { if (curves[i] == curve_id) return (1); } return (0); }
int tls_construct_ctos_supported_groups(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { const unsigned char *pcurves = NULL, *pcurvestmp; size_t num_curves = 0, i; if (!use_ecc(s)) return 1; /* * Add TLS extension supported_groups to the ClientHello message */ /* TODO(TLS1.3): Add support for DHE groups */ pcurves = s->ext.supportedgroups; if (!tls1_get_curvelist(s, 0, &pcurves, &num_curves)) { SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS, ERR_R_INTERNAL_ERROR); return 0; } pcurvestmp = pcurves; if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_groups) /* Sub-packet for supported_groups extension */ || !WPACKET_start_sub_packet_u16(pkt) || !WPACKET_start_sub_packet_u16(pkt)) { SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS, ERR_R_INTERNAL_ERROR); return 0; } /* Copy curve ID if supported */ for (i = 0; i < num_curves; i++, pcurvestmp += 2) { if (tls_curve_allowed(s, pcurvestmp, SSL_SECOP_CURVE_SUPPORTED)) { if (!WPACKET_put_bytes_u8(pkt, pcurvestmp[0]) || !WPACKET_put_bytes_u8(pkt, pcurvestmp[1])) { SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS, ERR_R_INTERNAL_ERROR); return 0; } } } if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) { SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS, ERR_R_INTERNAL_ERROR); return 0; } return 1; }
int tls1_get_shared_curve(SSL *s) { size_t preflen, supplen, i, j; const uint16_t *pref, *supp; unsigned long server_pref; /* Cannot do anything on the client side. */ if (s->server == 0) return (NID_undef); /* Return first preference shared curve. */ server_pref = (s->internal->options & SSL_OP_CIPHER_SERVER_PREFERENCE); tls1_get_curvelist(s, (server_pref == 0), &pref, &preflen); tls1_get_curvelist(s, (server_pref != 0), &supp, &supplen); 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); }
/* Check that an EC key is compatible with extensions. */ static int tls1_check_ec_key(SSL *s, const uint16_t *curve_id, const uint8_t *comp_id) { size_t curveslen, formatslen, i; const uint16_t *curves; const uint8_t *formats; /* * Check point formats extension if present, otherwise everything * is supported (see RFC4492). */ tls1_get_formatlist(s, 1, &formats, &formatslen); if (comp_id != NULL && formats != NULL) { for (i = 0; i < formatslen; i++) { if (formats[i] == *comp_id) break; } if (i == formatslen) return (0); } /* * Check curve list if present, otherwise everything is supported. */ tls1_get_curvelist(s, 1, &curves, &curveslen); if (curve_id != NULL && curves != NULL) { for (i = 0; i < curveslen; i++) { if (curves[i] == *curve_id) break; } if (i == curveslen) return (0); } return (1); }
/* * Process a key_share extension received in the ClientHello. |pkt| contains * the raw PACKET data for the extension. Returns 1 on success or 0 on failure. * If a failure occurs then |*al| is set to an appropriate alert value. */ int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { #ifndef OPENSSL_NO_TLS1_3 unsigned int group_id; PACKET key_share_list, encoded_pt; const unsigned char *clntcurves, *srvrcurves; size_t clnt_num_curves, srvr_num_curves; int group_nid, found = 0; unsigned int curve_flags; if (s->hit && (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE_DHE) == 0) return 1; /* Sanity check */ if (s->s3->peer_tmp != NULL) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } if (!PACKET_as_length_prefixed_2(pkt, &key_share_list)) { *al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_LENGTH_MISMATCH); return 0; } /* Get our list of supported curves */ if (!tls1_get_curvelist(s, 0, &srvrcurves, &srvr_num_curves)) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } /* Get the clients list of supported curves. */ if (!tls1_get_curvelist(s, 1, &clntcurves, &clnt_num_curves)) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } if (clnt_num_curves == 0) { /* * This can only happen if the supported_groups extension was not sent, * because we verify that the length is non-zero when we process that * extension. */ *al = SSL_AD_MISSING_EXTENSION; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION); return 0; } while (PACKET_remaining(&key_share_list) > 0) { if (!PACKET_get_net_2(&key_share_list, &group_id) || !PACKET_get_length_prefixed_2(&key_share_list, &encoded_pt) || PACKET_remaining(&encoded_pt) == 0) { *al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_LENGTH_MISMATCH); return 0; } /* * If we already found a suitable key_share we loop through the * rest to verify the structure, but don't process them. */ if (found) continue; /* Check if this share is in supported_groups sent from client */ if (!check_in_list(s, group_id, clntcurves, clnt_num_curves, 0)) { *al = SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_KEY_SHARE); return 0; } /* Check if this share is for a group we can use */ if (!check_in_list(s, group_id, srvrcurves, srvr_num_curves, 1)) { /* Share not suitable */ continue; } group_nid = tls1_ec_curve_id2nid(group_id, &curve_flags); if (group_nid == 0) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS); return 0; } if ((curve_flags & TLS_CURVE_TYPE) == TLS_CURVE_CUSTOM) { /* Can happen for some curves, e.g. X25519 */ EVP_PKEY *key = EVP_PKEY_new(); if (key == NULL || !EVP_PKEY_set_type(key, group_nid)) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_EVP_LIB); EVP_PKEY_free(key); return 0; } s->s3->peer_tmp = key; } else { /* Set up EVP_PKEY with named curve as parameters */ EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); if (pctx == NULL || EVP_PKEY_paramgen_init(pctx) <= 0 || EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, group_nid) <= 0 || EVP_PKEY_paramgen(pctx, &s->s3->peer_tmp) <= 0) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_EVP_LIB); EVP_PKEY_CTX_free(pctx); return 0; } EVP_PKEY_CTX_free(pctx); pctx = NULL; } s->s3->group_id = group_id; if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp, PACKET_data(&encoded_pt), PACKET_remaining(&encoded_pt))) { *al = SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_ECPOINT); return 0; } found = 1; } #endif return 1; }
int tls_construct_ctos_key_share(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { #ifndef OPENSSL_NO_TLS1_3 size_t i, num_curves = 0; const unsigned char *pcurves = NULL; unsigned int curve_id = 0; /* key_share extension */ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share) /* Extension data sub-packet */ || !WPACKET_start_sub_packet_u16(pkt) /* KeyShare list sub-packet */ || !WPACKET_start_sub_packet_u16(pkt)) { SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } pcurves = s->ext.supportedgroups; if (!tls1_get_curvelist(s, 0, &pcurves, &num_curves)) { SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } if (s->s3->tmp.pkey != NULL) { /* Shouldn't happen! */ SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } /* * TODO(TLS1.3): Make the number of key_shares sent configurable. For * now, just send one */ if (s->s3->group_id != 0) { curve_id = s->s3->group_id; } else { for (i = 0; i < num_curves; i++, pcurves += 2) { if (!tls_curve_allowed(s, pcurves, SSL_SECOP_CURVE_SUPPORTED)) continue; curve_id = bytestogroup(pcurves); break; } } if (curve_id == 0) { SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE, SSL_R_NO_SUITABLE_KEY_SHARE); return 0; } if (!add_key_share(s, pkt, curve_id)) return 0; if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) { SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } #endif return 1; }
int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { #ifndef OPENSSL_NO_TLS1_3 unsigned int group_id; PACKET encoded_pt; EVP_PKEY *ckey = s->s3->tmp.pkey, *skey = NULL; /* Sanity check */ if (ckey == NULL) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } if (!PACKET_get_net_2(pkt, &group_id)) { *al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_LENGTH_MISMATCH); return 0; } if ((context & EXT_TLS1_3_HELLO_RETRY_REQUEST) != 0) { unsigned const char *pcurves = NULL; size_t i, num_curves; if (PACKET_remaining(pkt) != 0) { *al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_LENGTH_MISMATCH); return 0; } /* * It is an error if the HelloRetryRequest wants a key_share that we * already sent in the first ClientHello */ if (group_id == s->s3->group_id) { *al = SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_KEY_SHARE); return 0; } /* Validate the selected group is one we support */ pcurves = s->ext.supportedgroups; if (!tls1_get_curvelist(s, 0, &pcurves, &num_curves)) { SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } for (i = 0; i < num_curves; i++, pcurves += 2) { if (group_id == bytestogroup(pcurves)) break; } if (i >= num_curves || !tls_curve_allowed(s, pcurves, SSL_SECOP_CURVE_SUPPORTED)) { *al = SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_KEY_SHARE); return 0; } s->s3->group_id = group_id; EVP_PKEY_free(s->s3->tmp.pkey); s->s3->tmp.pkey = NULL; return 1; } if (group_id != s->s3->group_id) { /* * This isn't for the group that we sent in the original * key_share! */ *al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_KEY_SHARE); return 0; } if (!PACKET_as_length_prefixed_2(pkt, &encoded_pt) || PACKET_remaining(&encoded_pt) == 0) { *al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_LENGTH_MISMATCH); return 0; } skey = ssl_generate_pkey(ckey); if (skey == NULL) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, ERR_R_MALLOC_FAILURE); return 0; } if (!EVP_PKEY_set1_tls_encodedpoint(skey, PACKET_data(&encoded_pt), PACKET_remaining(&encoded_pt))) { *al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_ECPOINT); EVP_PKEY_free(skey); return 0; } if (ssl_derive(s, ckey, skey, 1) == 0) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR); EVP_PKEY_free(skey); return 0; } EVP_PKEY_free(skey); #endif return 1; }
int tls_construct_ctos_key_share(SSL *s, WPACKET *pkt, int *al) { size_t i, sharessent = 0, num_curves = 0; const unsigned char *pcurves = NULL; /* key_share extension */ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share) /* Extension data sub-packet */ || !WPACKET_start_sub_packet_u16(pkt) /* KeyShare list sub-packet */ || !WPACKET_start_sub_packet_u16(pkt)) { SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } pcurves = s->tlsext_supportedgroupslist; if (!tls1_get_curvelist(s, 0, &pcurves, &num_curves)) { SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } /* * TODO(TLS1.3): Make the number of key_shares sent configurable. For * now, just send one */ for (i = 0; i < num_curves && sharessent < 1; i++, pcurves += 2) { unsigned char *encodedPoint = NULL; unsigned int curve_id = 0; EVP_PKEY *key_share_key = NULL; size_t encodedlen; if (!tls_curve_allowed(s, pcurves, SSL_SECOP_CURVE_SUPPORTED)) continue; if (s->s3->tmp.pkey != NULL) { /* Shouldn't happen! */ SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } /* Generate a key for this key_share */ curve_id = (pcurves[0] << 8) | pcurves[1]; key_share_key = ssl_generate_pkey_curve(curve_id); if (key_share_key == NULL) { SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE, ERR_R_EVP_LIB); return 0; } /* Encode the public key. */ encodedlen = EVP_PKEY_get1_tls_encodedpoint(key_share_key, &encodedPoint); if (encodedlen == 0) { SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE, ERR_R_EC_LIB); EVP_PKEY_free(key_share_key); return 0; } /* Create KeyShareEntry */ if (!WPACKET_put_bytes_u16(pkt, curve_id) || !WPACKET_sub_memcpy_u16(pkt, encodedPoint, encodedlen)) { SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR); EVP_PKEY_free(key_share_key); OPENSSL_free(encodedPoint); return 0; } /* * TODO(TLS1.3): When changing to send more than one key_share we're * going to need to be able to save more than one EVP_PKEY. For now * we reuse the existing tmp.pkey */ s->s3->group_id = curve_id; s->s3->tmp.pkey = key_share_key; sharessent++; OPENSSL_free(encodedPoint); } if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) { SSLerr(SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } return 1; }
/* * Process a key_share extension received in the ClientHello. |pkt| contains * the raw PACKET data for the extension. Returns 1 on success or 0 on failure. * If a failure occurs then |*al| is set to an appropriate alert value. */ int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, int *al) { unsigned int group_id; PACKET key_share_list, encoded_pt; const unsigned char *clntcurves, *srvrcurves; size_t clnt_num_curves, srvr_num_curves; int group_nid, found = 0; unsigned int curve_flags; if (s->hit) return 1; /* Sanity check */ if (s->s3->peer_tmp != NULL) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } if (!PACKET_as_length_prefixed_2(pkt, &key_share_list)) { *al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_LENGTH_MISMATCH); return 0; } /* Get our list of supported curves */ if (!tls1_get_curvelist(s, 0, &srvrcurves, &srvr_num_curves)) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } /* * Get the clients list of supported curves. * TODO(TLS1.3): We should validate that we actually received * supported_groups! */ if (!tls1_get_curvelist(s, 1, &clntcurves, &clnt_num_curves)) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } while (PACKET_remaining(&key_share_list) > 0) { if (!PACKET_get_net_2(&key_share_list, &group_id) || !PACKET_get_length_prefixed_2(&key_share_list, &encoded_pt) || PACKET_remaining(&encoded_pt) == 0) { *al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_LENGTH_MISMATCH); return 0; } /* * If we already found a suitable key_share we loop through the * rest to verify the structure, but don't process them. */ if (found) continue; /* Check if this share is in supported_groups sent from client */ if (!check_in_list(s, group_id, clntcurves, clnt_num_curves, 0)) { *al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_KEY_SHARE); return 0; } /* Check if this share is for a group we can use */ if (!check_in_list(s, group_id, srvrcurves, srvr_num_curves, 1)) { /* Share not suitable */ continue; } group_nid = tls1_ec_curve_id2nid(group_id, &curve_flags); if (group_nid == 0) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS); return 0; } if ((curve_flags & TLS_CURVE_TYPE) == TLS_CURVE_CUSTOM) { /* Can happen for some curves, e.g. X25519 */ EVP_PKEY *key = EVP_PKEY_new(); if (key == NULL || !EVP_PKEY_set_type(key, group_nid)) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_EVP_LIB); EVP_PKEY_free(key); return 0; } s->s3->peer_tmp = key; } else { /* Set up EVP_PKEY with named curve as parameters */ EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); if (pctx == NULL || EVP_PKEY_paramgen_init(pctx) <= 0 || EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, group_nid) <= 0 || EVP_PKEY_paramgen(pctx, &s->s3->peer_tmp) <= 0) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, ERR_R_EVP_LIB); EVP_PKEY_CTX_free(pctx); return 0; } EVP_PKEY_CTX_free(pctx); pctx = NULL; } s->s3->group_id = group_id; if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp, PACKET_data(&encoded_pt), PACKET_remaining(&encoded_pt))) { *al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_ECPOINT); return 0; } found = 1; } return 1; }