瀏覽代碼

Adding HelloRetryRequest.

[Tests added by davidben.]

Change-Id: I0d54a4f8b8fe91b348ff22658d95340cdb48b089
Reviewed-on: https://boringssl-review.googlesource.com/8850
Reviewed-by: Steven Valdez <svaldez@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
kris/onging/CECPQ3_patch15
Steven Valdez 8 年之前
committed by CQ bot account: commit-bot@chromium.org
父節點
當前提交
5440fe0cd1
共有 12 個文件被更改,包括 629 次插入101 次删除
  1. +43
    -30
      ssl/handshake_client.c
  2. +21
    -1
      ssl/internal.h
  3. +39
    -18
      ssl/t1_lib.c
  4. +35
    -2
      ssl/test/runner/common.go
  5. +4
    -0
      ssl/test/runner/conn.go
  6. +13
    -2
      ssl/test/runner/handshake_client.go
  7. +48
    -4
      ssl/test/runner/handshake_server.go
  8. +4
    -1
      ssl/test/runner/key_agreement.go
  9. +171
    -6
      ssl/test/runner/runner.go
  10. +15
    -6
      ssl/tls13_both.c
  11. +105
    -1
      ssl/tls13_client.c
  12. +131
    -30
      ssl/tls13_server.c

+ 43
- 30
ssl/handshake_client.c 查看文件

@@ -548,9 +548,8 @@ end:
return ret;
}

static int ssl3_write_client_cipher_list(SSL *ssl, CBB *out,
uint16_t min_version,
uint16_t max_version) {
int ssl_write_client_cipher_list(SSL *ssl, CBB *out, uint16_t min_version,
uint16_t max_version) {
/* Prepare disabled cipher masks. */
ssl_set_client_disabled(ssl);

@@ -605,6 +604,45 @@ static int ssl3_write_client_cipher_list(SSL *ssl, CBB *out,
return CBB_flush(out);
}

int ssl_add_client_hello_body(SSL *ssl, CBB *body) {
uint16_t min_version, max_version;
if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
return 0;
}

/* Renegotiations do not participate in session resumption. */
int has_session = ssl->session != NULL &&
!ssl->s3->initial_handshake_complete;

CBB child;
if (!CBB_add_u16(body, ssl->client_version) ||
!CBB_add_bytes(body, ssl->s3->client_random, SSL3_RANDOM_SIZE) ||
!CBB_add_u8_length_prefixed(body, &child) ||
(has_session &&
!CBB_add_bytes(&child, ssl->session->session_id,
ssl->session->session_id_length))) {
return 0;
}

if (SSL_IS_DTLS(ssl)) {
if (!CBB_add_u8_length_prefixed(body, &child) ||
!CBB_add_bytes(&child, ssl->d1->cookie, ssl->d1->cookie_len)) {
return 0;
}
}

size_t header_len =
SSL_IS_DTLS(ssl) ? DTLS1_HM_HEADER_LENGTH : SSL3_HM_HEADER_LENGTH;
if (!ssl_write_client_cipher_list(ssl, body, min_version, max_version) ||
!CBB_add_u8(body, 1 /* one compression method */) ||
!CBB_add_u8(body, 0 /* null compression */) ||
!ssl_add_clienthello_tlsext(ssl, body, header_len + CBB_len(body))) {
return 0;
}

return 1;
}

static int ssl3_send_client_hello(SSL *ssl) {
if (ssl->state == SSL3_ST_CW_CLNT_HELLO_B) {
return ssl->method->write_message(ssl);
@@ -654,34 +692,9 @@ static int ssl3_send_client_hello(SSL *ssl) {
goto err;
}

/* Renegotiations do not participate in session resumption. */
int has_session = ssl->session != NULL &&
!ssl->s3->initial_handshake_complete;

CBB body, child;
CBB body;
if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CLIENT_HELLO) ||
!CBB_add_u16(&body, ssl->client_version) ||
!CBB_add_bytes(&body, ssl->s3->client_random, SSL3_RANDOM_SIZE) ||
!CBB_add_u8_length_prefixed(&body, &child) ||
(has_session &&
!CBB_add_bytes(&child, ssl->session->session_id,
ssl->session->session_id_length))) {
goto err;
}

if (SSL_IS_DTLS(ssl)) {
if (!CBB_add_u8_length_prefixed(&body, &child) ||
!CBB_add_bytes(&child, ssl->d1->cookie, ssl->d1->cookie_len)) {
goto err;
}
}

size_t header_len =
SSL_IS_DTLS(ssl) ? DTLS1_HM_HEADER_LENGTH : SSL3_HM_HEADER_LENGTH;
if (!ssl3_write_client_cipher_list(ssl, &body, min_version, max_version) ||
!CBB_add_u8(&body, 1 /* one compression method */) ||
!CBB_add_u8(&body, 0 /* null compression */) ||
!ssl_add_clienthello_tlsext(ssl, &body, header_len + CBB_len(&body)) ||
!ssl_add_client_hello_body(ssl, &body) ||
!ssl->method->finish_message(ssl, &cbb)) {
goto err;
}


+ 21
- 1
ssl/internal.h 查看文件

@@ -873,6 +873,11 @@ struct ssl_handshake_st {

SSL_ECDH_CTX *groups;
size_t groups_len;
/* retry_group is the group ID selected by the server in HelloRetryRequest. */
uint16_t retry_group;
/* key_share_bytes is the value of the previously sent KeyShare extension. */
uint8_t *key_share_bytes;
size_t key_share_bytes_len;
uint8_t *public_key;
size_t public_key_len;

@@ -882,6 +887,8 @@ struct ssl_handshake_st {

SSL_HANDSHAKE *ssl_handshake_new(enum ssl_hs_wait_t (*do_handshake)(SSL *ssl));

void ssl_handshake_clear_groups(SSL_HANDSHAKE *hs);

/* ssl_handshake_free releases all memory associated with |hs|. */
void ssl_handshake_free(SSL_HANDSHAKE *hs);

@@ -910,11 +917,14 @@ int tls13_prepare_finished(SSL *ssl);
int ext_key_share_parse_serverhello(SSL *ssl, uint8_t **out_secret,
size_t *out_secret_len, uint8_t *out_alert,
CBS *contents);
int ext_key_share_parse_clienthello(SSL *ssl, uint8_t **out_secret,
int ext_key_share_parse_clienthello(SSL *ssl,
int *out_found, uint8_t **out_secret,
size_t *out_secret_len, uint8_t *out_alert,
CBS *contents);
int ext_key_share_add_serverhello(SSL *ssl, CBB *out);

int ssl_add_client_hello_body(SSL *ssl, CBB *body);


/* SSLKEYLOGFILE functions. */

@@ -1228,6 +1238,9 @@ void ssl_get_compatible_server_ciphers(SSL *ssl, uint32_t *out_mask_k,
STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *ssl);
int ssl_verify_alarm_type(long type);

int ssl_write_client_cipher_list(SSL *ssl, CBB *out, uint16_t min_version,
uint16_t max_version);

int ssl3_get_finished(SSL *ssl);
int ssl3_send_change_cipher_spec(SSL *ssl);
void ssl3_cleanup_key_block(SSL *ssl);
@@ -1331,6 +1344,13 @@ int tls1_generate_master_secret(SSL *ssl, uint8_t *out, const uint8_t *premaster

char ssl_early_callback_init(struct ssl_early_callback_ctx *ctx);

/* tls1_get_grouplist sets |*out_group_ids| and |*out_group_ids_len| to the
* list of allowed group IDs. If |get_peer_groups| is non-zero, return the
* peer's group list. Otherwise, return the preferred list. */
void tls1_get_grouplist(SSL *ssl, int get_peer_groups,
const uint16_t **out_group_ids,
size_t *out_group_ids_len);

/* tls1_check_group_id returns one if |group_id| is consistent with both our
* and the peer's group preferences. Note: if called as the client, only our
* preferences are checked; the peer (the server) does not send preferences. */


+ 39
- 18
ssl/t1_lib.c 查看文件

@@ -300,12 +300,9 @@ static const uint16_t kDefaultGroups[] = {
#endif
};

/* tls1_get_grouplist sets |*out_group_ids| and |*out_group_ids_len| to the
* list of allowed group IDs. If |get_peer_groups| is non-zero, return the
* peer's group list. Otherwise, return the preferred list. */
static void tls1_get_grouplist(SSL *ssl, int get_peer_groups,
const uint16_t **out_group_ids,
size_t *out_group_ids_len) {
void tls1_get_grouplist(SSL *ssl, int get_peer_groups,
const uint16_t **out_group_ids,
size_t *out_group_ids_len) {
if (get_peer_groups) {
/* Only clients send a supported group list, so this function is only
* called on the server. */
@@ -1973,7 +1970,24 @@ static int ext_key_share_add_clienthello(SSL *ssl, CBB *out) {

const uint16_t *groups;
size_t groups_len;
tls1_get_grouplist(ssl, 0 /* local groups */, &groups, &groups_len);
if (ssl->s3->hs->retry_group) {
/* Append the new key share to the old list. */
if (!CBB_add_bytes(&kse_bytes, ssl->s3->hs->key_share_bytes,
ssl->s3->hs->key_share_bytes_len)) {
return 0;
}
OPENSSL_free(ssl->s3->hs->key_share_bytes);
ssl->s3->hs->key_share_bytes = NULL;

groups = &ssl->s3->hs->retry_group;
groups_len = 1;
} else {
tls1_get_grouplist(ssl, 0 /* local groups */, &groups, &groups_len);
/* Only send the top two preferred key shares. */
if (groups_len > 2) {
groups_len = 2;
}
}

ssl->s3->hs->groups = OPENSSL_malloc(groups_len * sizeof(SSL_ECDH_CTX));
if (ssl->s3->hs->groups == NULL) {
@@ -1996,6 +2010,17 @@ static int ext_key_share_add_clienthello(SSL *ssl, CBB *out) {
}
}

if (!ssl->s3->hs->retry_group) {
/* Save the contents of the extension to repeat it in the second
* ClientHello. */
ssl->s3->hs->key_share_bytes_len = CBB_len(&kse_bytes);
ssl->s3->hs->key_share_bytes = BUF_memdup(CBB_data(&kse_bytes),
CBB_len(&kse_bytes));
if (ssl->s3->hs->key_share_bytes == NULL) {
return 0;
}
}

return CBB_flush(out);
}

@@ -2030,16 +2055,12 @@ int ext_key_share_parse_serverhello(SSL *ssl, uint8_t **out_secret,
return 0;
}

for (size_t i = 0; i < ssl->s3->hs->groups_len; i++) {
SSL_ECDH_CTX_cleanup(&ssl->s3->hs->groups[i]);
}
OPENSSL_free(ssl->s3->hs->groups);
ssl->s3->hs->groups = NULL;

ssl_handshake_clear_groups(ssl->s3->hs);
return 1;
}

int ext_key_share_parse_clienthello(SSL *ssl, uint8_t **out_secret,
int ext_key_share_parse_clienthello(SSL *ssl, int *out_found,
uint8_t **out_secret,
size_t *out_secret_len, uint8_t *out_alert,
CBS *contents) {
uint16_t group_id;
@@ -2049,7 +2070,7 @@ int ext_key_share_parse_clienthello(SSL *ssl, uint8_t **out_secret,
return 0;
}

int found = 0;
*out_found = 0;
while (CBS_len(&key_shares) > 0) {
uint16_t id;
CBS peer_key;
@@ -2058,7 +2079,7 @@ int ext_key_share_parse_clienthello(SSL *ssl, uint8_t **out_secret,
return 0;
}

if (id != group_id || found) {
if (id != group_id || *out_found) {
continue;
}

@@ -2078,10 +2099,10 @@ int ext_key_share_parse_clienthello(SSL *ssl, uint8_t **out_secret,
}
SSL_ECDH_CTX_cleanup(&group);

found = 1;
*out_found = 1;
}

return found;
return 1;
}

int ext_key_share_add_serverhello(SSL *ssl, CBB *out) {


+ 35
- 2
ssl/test/runner/common.go 查看文件

@@ -206,6 +206,7 @@ type ConnectionState struct {
TLSUnique []byte // the tls-unique channel binding
SCTList []byte // signed certificate timestamp list
PeerSignatureAlgorithm signatureAlgorithm // algorithm used by the peer in the handshake
CurveID CurveID // the curve used in ECDHE
}

// ClientAuthType declares the policy the server will follow for
@@ -438,10 +439,16 @@ type ProtocolBugs struct {
// or CertificateVerify message should be invalid.
InvalidSignature bool

// SendCurve, if non-zero, causes the ServerKeyExchange message to use
// the specified curve ID rather than the negotiated one.
// SendCurve, if non-zero, causes the server to send the specified curve
// ID in ServerKeyExchange (TLS 1.2) or ServerHello (TLS 1.3) rather
// than the negotiated one.
SendCurve CurveID

// SendHelloRetryRequestCurve, if non-zero, causes the server to send
// the specified curve in HelloRetryRequest rather than the negotiated
// one.
SendHelloRetryRequestCurve CurveID

// InvalidECDHPoint, if true, causes the ECC points in
// ServerKeyExchange or ClientKeyExchange messages to be invalid.
InvalidECDHPoint bool
@@ -953,6 +960,16 @@ type ProtocolBugs struct {
// instead.
MissingKeyShare bool

// SecondClientHelloMissingKeyShare, if true, causes the second TLS 1.3
// ClientHello to skip sending a key_share extension and use the zero
// ECDHE secret instead.
SecondClientHelloMissingKeyShare bool

// MisinterpretHelloRetryRequestCurve, if non-zero, causes the TLS 1.3
// client to pretend the server requested a HelloRetryRequest with the
// given curve rather than the actual one.
MisinterpretHelloRetryRequestCurve CurveID

// DuplicateKeyShares, if true, causes the TLS 1.3 client to send two
// copies of each KeyShareEntry.
DuplicateKeyShares bool
@@ -964,6 +981,22 @@ type ProtocolBugs struct {
// EncryptedExtensionsWithKeyShare, if true, causes the TLS 1.3 server to
// include the KeyShare extension in the EncryptedExtensions block.
EncryptedExtensionsWithKeyShare bool

// UnnecessaryHelloRetryRequest, if true, causes the TLS 1.3 server to
// send a HelloRetryRequest regardless of whether it needs to.
UnnecessaryHelloRetryRequest bool

// SecondHelloRetryRequest, if true, causes the TLS 1.3 server to send
// two HelloRetryRequests instead of one.
SecondHelloRetryRequest bool

// SendServerHelloVersion, if non-zero, causes the server to send the
// specified version in ServerHello rather than the true version.
SendServerHelloVersion uint16

// SkipHelloRetryRequest, if true, causes the TLS 1.3 server to not send
// HelloRetryRequest.
SkipHelloRetryRequest bool
}

func (c *Config) serverInit() {


+ 4
- 0
ssl/test/runner/conn.go 查看文件

@@ -53,6 +53,9 @@ type Conn struct {
// peerSignatureAlgorithm contains the signature algorithm that was used
// by the peer in the handshake, or zero if not applicable.
peerSignatureAlgorithm signatureAlgorithm
// curveID contains the curve that was used in the handshake, or zero if
// not applicable.
curveID CurveID

clientRandom, serverRandom [32]byte
exporterSecret []byte
@@ -1500,6 +1503,7 @@ func (c *Conn) ConnectionState() ConnectionState {
state.TLSUnique = c.firstFinished[:]
state.SCTList = c.sctList
state.PeerSignatureAlgorithm = c.peerSignatureAlgorithm
state.CurveID = c.curveID
}

return state


+ 13
- 2
ssl/test/runner/handshake_client.go 查看文件

@@ -140,7 +140,7 @@ func (c *Conn) clientHandshake() error {
}

if c.config.Bugs.MissingKeyShare {
hello.keyShares = nil
hello.hasKeyShares = false
}
}

@@ -337,6 +337,9 @@ NextCipherSuite:
var secondHelloBytes []byte
if haveHelloRetryRequest {
var hrrCurveFound bool
if c.config.Bugs.MisinterpretHelloRetryRequestCurve != 0 {
helloRetryRequest.selectedGroup = c.config.Bugs.MisinterpretHelloRetryRequestCurve
}
group := helloRetryRequest.selectedGroup
for _, curveID := range hello.supportedCurves {
if group == curveID {
@@ -362,6 +365,10 @@ NextCipherSuite:
keyExchange: publicKey,
})

if c.config.Bugs.SecondClientHelloMissingKeyShare {
hello.hasKeyShares = false
}

hello.hasEarlyData = false
hello.earlyDataContext = nil
hello.raw = nil
@@ -553,7 +560,7 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {

// Resolve ECDHE and compute the handshake secret.
var ecdheSecret []byte
if hs.suite.flags&suiteECDHE != 0 && !c.config.Bugs.MissingKeyShare {
if hs.suite.flags&suiteECDHE != 0 && !c.config.Bugs.MissingKeyShare && !c.config.Bugs.SecondClientHelloMissingKeyShare {
if !hs.serverHello.hasKeyShare {
c.sendAlert(alertMissingExtension)
return errors.New("tls: server omitted the key share extension")
@@ -564,6 +571,7 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {
c.sendAlert(alertHandshakeFailure)
return errors.New("tls: server selected an unsupported group")
}
c.curveID = hs.serverHello.keyShare.group

var err error
ecdheSecret, err = curve.finish(hs.serverHello.keyShare.keyExchange)
@@ -821,6 +829,9 @@ func (hs *clientHandshakeState) doFullHandshake() error {
c.sendAlert(alertUnexpectedMessage)
return err
}
if ecdhe, ok := keyAgreement.(*ecdheKeyAgreement); ok {
c.curveID = ecdhe.curveID
}

c.peerSignatureAlgorithm = keyAgreement.peerSignatureAlgorithm()



+ 48
- 4
ssl/test/runner/handshake_server.go 查看文件

@@ -266,6 +266,10 @@ func (hs *serverHandshakeState) doTLS13Handshake() error {
vers: c.vers,
}

if config.Bugs.SendServerHelloVersion != 0 {
hs.hello.vers = config.Bugs.SendServerHelloVersion
}

hs.hello.random = make([]byte, 32)
if _, err := io.ReadFull(config.rand(), hs.hello.random); err != nil {
c.sendAlert(alertInternalError)
@@ -352,13 +356,25 @@ Curves:
}
}

if selectedKeyShare == nil {
sendHelloRetryRequest := selectedKeyShare == nil
if config.Bugs.UnnecessaryHelloRetryRequest {
sendHelloRetryRequest = true
}
if config.Bugs.SkipHelloRetryRequest {
sendHelloRetryRequest = false
}
if sendHelloRetryRequest {
firstTime := true
ResendHelloRetryRequest:
// Send HelloRetryRequest.
helloRetryRequestMsg := helloRetryRequestMsg{
vers: c.vers,
cipherSuite: hs.hello.cipherSuite,
selectedGroup: selectedCurve,
}
if config.Bugs.SendHelloRetryRequestCurve != 0 {
helloRetryRequestMsg.selectedGroup = config.Bugs.SendHelloRetryRequestCurve
}
hs.writeServerHash(helloRetryRequestMsg.marshal())
c.writeRecord(recordTypeHandshake, helloRetryRequestMsg.marshal())

@@ -392,26 +408,47 @@ Curves:
return errors.New("tls: new ClientHello does not match")
}

if firstTime && config.Bugs.SecondHelloRetryRequest {
firstTime = false
goto ResendHelloRetryRequest
}

selectedKeyShare = &newKeyShares[len(newKeyShares)-1]
}

// Once a curve has been selected and a key share identified,
// the server needs to generate a public value and send it in
// the ServerHello.
curve, ok := curveForCurveID(selectedKeyShare.group)
curve, ok := curveForCurveID(selectedCurve)
if !ok {
panic("tls: server failed to look up curve ID")
}
c.curveID = selectedCurve

var peerKey []byte
if config.Bugs.SkipHelloRetryRequest {
// If skipping HelloRetryRequest, use a random key to
// avoid crashing.
curve2, _ := curveForCurveID(selectedCurve)
var err error
peerKey, err = curve2.offer(config.rand())
if err != nil {
return err
}
} else {
peerKey = selectedKeyShare.keyExchange
}

var publicKey []byte
var err error
publicKey, ecdheSecret, err = curve.accept(config.rand(), selectedKeyShare.keyExchange)
publicKey, ecdheSecret, err = curve.accept(config.rand(), peerKey)
if err != nil {
c.sendAlert(alertHandshakeFailure)
return err
}
hs.hello.hasKeyShare = true

curveID := selectedKeyShare.group
curveID := selectedCurve
if c.config.Bugs.SendCurve != 0 {
curveID = config.Bugs.SendCurve
}
@@ -648,6 +685,10 @@ func (hs *serverHandshakeState) processClientHello() (isResume bool, err error)
compressionMethod: compressionNone,
}

if config.Bugs.SendServerHelloVersion != 0 {
hs.hello.vers = config.Bugs.SendServerHelloVersion
}

hs.hello.random = make([]byte, 32)
_, err = io.ReadFull(config.rand(), hs.hello.random)
if err != nil {
@@ -1009,6 +1050,9 @@ func (hs *serverHandshakeState) doFullHandshake() error {
c.sendAlert(alertHandshakeFailure)
return err
}
if ecdhe, ok := keyAgreement.(*ecdheKeyAgreement); ok {
c.curveID = ecdhe.curveID
}
if skx != nil && !config.Bugs.SkipServerKeyExchange {
hs.writeServerHash(skx.marshal())
c.writeRecord(recordTypeHandshake, skx.marshal())


+ 4
- 1
ssl/test/runner/key_agreement.go 查看文件

@@ -484,13 +484,14 @@ func (ka *signedKeyAgreement) verifyParameters(config *Config, clientHello *clie
return verifyMessage(ka.version, cert.PublicKey, config, sigAlg, msg, sig)
}

// ecdheRSAKeyAgreement implements a TLS key agreement where the server
// ecdheKeyAgreement implements a TLS key agreement where the server
// generates a ephemeral EC public/private key pair and signs it. The
// pre-master secret is then calculated using ECDH. The signature may
// either be ECDSA or RSA.
type ecdheKeyAgreement struct {
auth keyAgreementAuthentication
curve ecdhCurve
curveID CurveID
peerKey []byte
}

@@ -516,6 +517,7 @@ NextCandidate:
if ka.curve, ok = curveForCurveID(curveid); !ok {
return nil, errors.New("tls: preferredCurves includes unsupported curve")
}
ka.curveID = curveid

publicKey, err := ka.curve.offer(config.rand())
if err != nil {
@@ -554,6 +556,7 @@ func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHell
return errors.New("tls: server selected unsupported curve")
}
curveid := CurveID(skx.key[1])<<8 | CurveID(skx.key[2])
ka.curveID = curveid

var ok bool
if ka.curve, ok = curveForCurveID(curveid); !ok {


+ 171
- 6
ssl/test/runner/runner.go 查看文件

@@ -254,6 +254,9 @@ type testCase struct {
// expectedPeerSignatureAlgorithm, if not zero, is the signature
// algorithm that the peer should have used in the handshake.
expectedPeerSignatureAlgorithm signatureAlgorithm
// expectedCurveID, if not zero, is the curve that the handshake should
// have used.
expectedCurveID CurveID
// messageLen is the length, in bytes, of the test message that will be
// sent.
messageLen int
@@ -518,6 +521,10 @@ func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool) er
return fmt.Errorf("expected peer to use signature algorithm %04x, but got %04x", expected, connState.PeerSignatureAlgorithm)
}

if expected := test.expectedCurveID; expected != 0 && expected != connState.CurveID {
return fmt.Errorf("expected peer to use curve %04x, but got %04x", expected, connState.CurveID)
}

if test.exportKeyingMaterial > 0 {
actual := make([]byte, test.exportKeyingMaterial)
if _, err := io.ReadFull(tlsConn, actual); err != nil {
@@ -6304,6 +6311,8 @@ var testCurves = []struct {
{"X25519", CurveX25519},
}

const bogusCurve = 0x1234

func addCurveTests() {
for _, curve := range testCurves {
testCases = append(testCases, testCase{
@@ -6313,7 +6322,8 @@ func addCurveTests() {
CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
CurvePreferences: []CurveID{curve.id},
},
flags: []string{"-enable-all-curves"},
flags: []string{"-enable-all-curves"},
expectedCurveID: curve.id,
})
testCases = append(testCases, testCase{
name: "CurveTest-Client-" + curve.name + "-TLS13",
@@ -6322,7 +6332,8 @@ func addCurveTests() {
CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
CurvePreferences: []CurveID{curve.id},
},
flags: []string{"-enable-all-curves"},
flags: []string{"-enable-all-curves"},
expectedCurveID: curve.id,
})
testCases = append(testCases, testCase{
testType: serverTest,
@@ -6332,7 +6343,8 @@ func addCurveTests() {
CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
CurvePreferences: []CurveID{curve.id},
},
flags: []string{"-enable-all-curves"},
flags: []string{"-enable-all-curves"},
expectedCurveID: curve.id,
})
testCases = append(testCases, testCase{
testType: serverTest,
@@ -6342,12 +6354,12 @@ func addCurveTests() {
CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
CurvePreferences: []CurveID{curve.id},
},
flags: []string{"-enable-all-curves"},
flags: []string{"-enable-all-curves"},
expectedCurveID: curve.id,
})
}

// The server must be tolerant to bogus curves.
const bogusCurve = 0x1234
testCases = append(testCases, testCase{
testType: serverTest,
name: "UnknownCurve",
@@ -7359,7 +7371,8 @@ func addTLS13HandshakeTests() {
})

testCases = append(testCases, testCase{
name: "MissingKeyShare-Server",
testType: serverTest,
name: "MissingKeyShare-Server",
config: Config{
MaxVersion: VersionTLS13,
Bugs: ProtocolBugs{
@@ -7432,6 +7445,158 @@ func addTLS13HandshakeTests() {
shouldFail: true,
expectedLocalError: "remote error: unsupported extension",
})

testCases = append(testCases, testCase{
testType: serverTest,
name: "SendHelloRetryRequest",
config: Config{
MaxVersion: VersionTLS13,
// Require a HelloRetryRequest for every curve.
DefaultCurves: []CurveID{},
},
expectedCurveID: CurveX25519,
})

testCases = append(testCases, testCase{
testType: serverTest,
name: "SendHelloRetryRequest-2",
config: Config{
MaxVersion: VersionTLS13,
DefaultCurves: []CurveID{CurveP384},
},
// Although the ClientHello did not predict our preferred curve,
// we always select it whether it is predicted or not.
expectedCurveID: CurveX25519,
})

testCases = append(testCases, testCase{
name: "UnknownCurve-HelloRetryRequest",
config: Config{
MaxVersion: VersionTLS13,
// P-384 requires HelloRetryRequest in BoringSSL.
CurvePreferences: []CurveID{CurveP384},
Bugs: ProtocolBugs{
SendHelloRetryRequestCurve: bogusCurve,
},
},
shouldFail: true,
expectedError: ":WRONG_CURVE:",
})

testCases = append(testCases, testCase{
name: "DisabledCurve-HelloRetryRequest",
config: Config{
MaxVersion: VersionTLS13,
CurvePreferences: []CurveID{CurveP256},
Bugs: ProtocolBugs{
IgnorePeerCurvePreferences: true,
},
},
flags: []string{"-p384-only"},
shouldFail: true,
expectedError: ":WRONG_CURVE:",
})

testCases = append(testCases, testCase{
name: "UnnecessaryHelloRetryRequest",
config: Config{
MaxVersion: VersionTLS13,
Bugs: ProtocolBugs{
UnnecessaryHelloRetryRequest: true,
},
},
shouldFail: true,
expectedError: ":WRONG_CURVE:",
})

testCases = append(testCases, testCase{
name: "SecondHelloRetryRequest",
config: Config{
MaxVersion: VersionTLS13,
// P-384 requires HelloRetryRequest in BoringSSL.
CurvePreferences: []CurveID{CurveP384},
Bugs: ProtocolBugs{
SecondHelloRetryRequest: true,
},
},
shouldFail: true,
expectedError: ":UNEXPECTED_MESSAGE:",
})

testCases = append(testCases, testCase{
testType: serverTest,
name: "SecondClientHelloMissingKeyShare",
config: Config{
MaxVersion: VersionTLS13,
DefaultCurves: []CurveID{},
Bugs: ProtocolBugs{
SecondClientHelloMissingKeyShare: true,
},
},
shouldFail: true,
expectedError: ":MISSING_KEY_SHARE:",
})

testCases = append(testCases, testCase{
testType: serverTest,
name: "SecondClientHelloWrongCurve",
config: Config{
MaxVersion: VersionTLS13,
DefaultCurves: []CurveID{},
Bugs: ProtocolBugs{
MisinterpretHelloRetryRequestCurve: CurveP521,
},
},
shouldFail: true,
expectedError: ":WRONG_CURVE:",
})

testCases = append(testCases, testCase{
name: "HelloRetryRequestVersionMismatch",
config: Config{
MaxVersion: VersionTLS13,
// P-384 requires HelloRetryRequest in BoringSSL.
CurvePreferences: []CurveID{CurveP384},
Bugs: ProtocolBugs{
SendServerHelloVersion: 0x0305,
},
},
shouldFail: true,
expectedError: ":WRONG_VERSION_NUMBER:",
})

testCases = append(testCases, testCase{
name: "HelloRetryRequestCurveMismatch",
config: Config{
MaxVersion: VersionTLS13,
// P-384 requires HelloRetryRequest in BoringSSL.
CurvePreferences: []CurveID{CurveP384},
Bugs: ProtocolBugs{
// Send P-384 (correct) in the HelloRetryRequest.
SendHelloRetryRequestCurve: CurveP384,
// But send P-256 in the ServerHello.
SendCurve: CurveP256,
},
},
shouldFail: true,
expectedError: ":WRONG_CURVE:",
})

// Test the server selecting a curve that requires a HelloRetryRequest
// without sending it.
testCases = append(testCases, testCase{
name: "SkipHelloRetryRequest",
config: Config{
MaxVersion: VersionTLS13,
// P-384 requires HelloRetryRequest in BoringSSL.
CurvePreferences: []CurveID{CurveP384},
Bugs: ProtocolBugs{
SkipHelloRetryRequest: true,
},
},
shouldFail: true,
expectedError: ":WRONG_CURVE:",
})
}

func worker(statusChan chan statusMsg, c chan *testCase, shimPath string, wg *sync.WaitGroup) {


+ 15
- 6
ssl/tls13_both.c 查看文件

@@ -40,6 +40,19 @@ SSL_HANDSHAKE *ssl_handshake_new(enum ssl_hs_wait_t (*do_handshake)(SSL *ssl)) {
return hs;
}

void ssl_handshake_clear_groups(SSL_HANDSHAKE *hs) {
if (hs->groups == NULL) {
return;
}

for (size_t i = 0; i < hs->groups_len; i++) {
SSL_ECDH_CTX_cleanup(&hs->groups[i]);
}
OPENSSL_free(hs->groups);
hs->groups = NULL;
hs->groups_len = 0;
}

void ssl_handshake_free(SSL_HANDSHAKE *hs) {
if (hs == NULL) {
return;
@@ -47,12 +60,8 @@ void ssl_handshake_free(SSL_HANDSHAKE *hs) {

OPENSSL_cleanse(hs->secret, sizeof(hs->secret));
OPENSSL_cleanse(hs->traffic_secret_0, sizeof(hs->traffic_secret_0));
if (hs->groups != NULL) {
for (size_t i = 0; i < hs->groups_len; i++) {
SSL_ECDH_CTX_cleanup(&hs->groups[i]);
}
OPENSSL_free(hs->groups);
}
ssl_handshake_clear_groups(hs);
OPENSSL_free(hs->key_share_bytes);
OPENSSL_free(hs->public_key);
OPENSSL_free(hs->cert_context);
OPENSSL_free(hs);


+ 105
- 1
ssl/tls13_client.c 查看文件

@@ -28,7 +28,10 @@


enum client_hs_state_t {
state_process_server_hello = 0,
state_process_hello_retry_request = 0,
state_send_second_client_hello,
state_flush_second_client_hello,
state_process_server_hello,
state_process_encrypted_extensions,
state_process_certificate_request,
state_process_server_certificate,
@@ -43,6 +46,85 @@ enum client_hs_state_t {
state_done,
};

static enum ssl_hs_wait_t do_process_hello_retry_request(SSL *ssl,
SSL_HANDSHAKE *hs) {
if (ssl->s3->tmp.message_type != SSL3_MT_HELLO_RETRY_REQUEST) {
hs->state = state_process_server_hello;
return ssl_hs_ok;
}

CBS cbs, extensions;
uint16_t server_wire_version, cipher_suite, group_id;
CBS_init(&cbs, ssl->init_msg, ssl->init_num);
if (!CBS_get_u16(&cbs, &server_wire_version) ||
!CBS_get_u16(&cbs, &cipher_suite) ||
!CBS_get_u16(&cbs, &group_id) ||
/* We do not currently parse any HelloRetryRequest extensions. */
!CBS_get_u16_length_prefixed(&cbs, &extensions) ||
CBS_len(&cbs) != 0) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return ssl_hs_error;
}

/* TODO(svaldez): Don't do early_data on HelloRetryRequest. */

const uint16_t *groups;
size_t groups_len;
tls1_get_grouplist(ssl, 0 /* local groups */, &groups, &groups_len);
int found = 0;
for (size_t i = 0; i < groups_len; i++) {
if (groups[i] == group_id) {
found = 1;
break;
}
}

if (!found) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
return ssl_hs_error;
}

for (size_t i = 0; i < ssl->s3->hs->groups_len; i++) {
/* Check that the HelloRetryRequest does not request a key share that was
* provided in the initial ClientHello.
*
* TODO(svaldez): Don't enforce this check when the HelloRetryRequest is due
* to a cookie. */
if (SSL_ECDH_CTX_get_id(&ssl->s3->hs->groups[i]) == group_id) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
return ssl_hs_error;
}
}

ssl_handshake_clear_groups(ssl->s3->hs);
ssl->s3->hs->retry_group = group_id;

hs->state = state_send_second_client_hello;
return ssl_hs_ok;
}

static enum ssl_hs_wait_t do_send_second_client_hello(SSL *ssl,
SSL_HANDSHAKE *hs) {
CBB cbb, body;
if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CLIENT_HELLO) ||
!ssl_add_client_hello_body(ssl, &body) ||
!ssl->method->finish_message(ssl, &cbb)) {
CBB_cleanup(&cbb);
return ssl_hs_error;
}

hs->state = state_flush_second_client_hello;
return ssl_hs_write_message;
}

static enum ssl_hs_wait_t do_flush_second_client_hello(SSL *ssl,
SSL_HANDSHAKE *hs) {
hs->state = state_process_server_hello;
return ssl_hs_flush_and_read_message;
}

static enum ssl_hs_wait_t do_process_server_hello(SSL *ssl, SSL_HANDSHAKE *hs) {
if (!tls13_check_message_type(ssl, SSL3_MT_SERVER_HELLO)) {
return ssl_hs_error;
@@ -58,6 +140,13 @@ static enum ssl_hs_wait_t do_process_server_hello(SSL *ssl, SSL_HANDSHAKE *hs) {
!CBS_get_u16_length_prefixed(&cbs, &extensions) ||
CBS_len(&cbs) != 0) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
return ssl_hs_error;
}

if (server_wire_version != ssl->version) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_VERSION_NUMBER);
return ssl_hs_error;
}

@@ -169,6 +258,12 @@ static enum ssl_hs_wait_t do_process_server_hello(SSL *ssl, SSL_HANDSHAKE *hs) {
if (!tls13_advance_key_schedule(ssl, kZeroes, hash_len)) {
return ssl_hs_error;
}
}

/* If there was no HelloRetryRequest, the version negotiation logic has
* already hashed the message. */
if (ssl->s3->hs->retry_group != 0 &&
!ssl->method->hash_current_message(ssl)) {
return ssl_hs_error;
}

@@ -403,6 +498,15 @@ enum ssl_hs_wait_t tls13_client_handshake(SSL *ssl) {
enum ssl_hs_wait_t ret = ssl_hs_error;
enum client_hs_state_t state = hs->state;
switch (state) {
case state_process_hello_retry_request:
ret = do_process_hello_retry_request(ssl, hs);
break;
case state_send_second_client_hello:
ret = do_send_second_client_hello(ssl, hs);
break;
case state_flush_second_client_hello:
ret = do_flush_second_client_hello(ssl, hs);
break;
case state_process_server_hello:
ret = do_process_server_hello(ssl, hs);
break;


+ 131
- 30
ssl/tls13_server.c 查看文件

@@ -29,6 +29,9 @@

enum server_hs_state_t {
state_process_client_hello = 0,
state_send_hello_retry_request,
state_flush_hello_retry_request,
state_process_second_client_hello,
state_send_server_hello,
state_send_encrypted_extensions,
state_send_certificate_request,
@@ -43,6 +46,60 @@ enum server_hs_state_t {
state_done,
};

static const uint8_t kZeroes[EVP_MAX_MD_SIZE] = {0};

static int resolve_psk_secret(SSL *ssl) {
SSL_HANDSHAKE *hs = ssl->s3->hs;

if (ssl->s3->tmp.new_cipher->algorithm_auth != SSL_aPSK) {
return tls13_advance_key_schedule(ssl, kZeroes, hs->hash_len);
}

/* TODO(davidben): Support PSK. */
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return 0;
}

static int resolve_ecdhe_secret(SSL *ssl, int *out_need_retry,
struct ssl_early_callback_ctx *early_ctx) {
*out_need_retry = 0;
SSL_HANDSHAKE *hs = ssl->s3->hs;

if (ssl->s3->tmp.new_cipher->algorithm_mkey != SSL_kECDHE) {
return tls13_advance_key_schedule(ssl, kZeroes, hs->hash_len);
}

const uint8_t *key_share_buf = NULL;
size_t key_share_len = 0;
CBS key_share;
if (!SSL_early_callback_ctx_extension_get(early_ctx, TLSEXT_TYPE_key_share,
&key_share_buf, &key_share_len)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_KEY_SHARE);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_MISSING_EXTENSION);
return ssl_hs_error;
}

CBS_init(&key_share, key_share_buf, key_share_len);
int found_key_share;
uint8_t *dhe_secret;
size_t dhe_secret_len;
uint8_t alert;
if (!ext_key_share_parse_clienthello(ssl, &found_key_share, &dhe_secret,
&dhe_secret_len, &alert, &key_share)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
return 0;
}

if (!found_key_share) {
*out_need_retry = 1;
return 0;
}

int ok = tls13_advance_key_schedule(ssl, dhe_secret, dhe_secret_len);
OPENSSL_free(dhe_secret);
return ok;
}

static enum ssl_hs_wait_t do_process_client_hello(SSL *ssl, SSL_HANDSHAKE *hs) {
if (!tls13_check_message_type(ssl, SSL3_MT_CLIENT_HELLO)) {
return ssl_hs_error;
@@ -165,7 +222,6 @@ static enum ssl_hs_wait_t do_process_client_hello(SSL *ssl, SSL_HANDSHAKE *hs) {

/* The PRF hash is now known. Set up the key schedule and hash the
* ClientHello. */
static const uint8_t kZeroes[EVP_MAX_MD_SIZE] = {0};
size_t hash_len =
EVP_MD_size(ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl)));
if (!tls13_init_key_schedule(ssl, kZeroes, hash_len)) {
@@ -173,42 +229,79 @@ static enum ssl_hs_wait_t do_process_client_hello(SSL *ssl, SSL_HANDSHAKE *hs) {
}

/* Resolve PSK and incorporate it into the secret. */
if (cipher->algorithm_auth == SSL_aPSK) {
/* TODO(davidben): Support PSK. */
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return ssl_hs_error;
} else if (!tls13_advance_key_schedule(ssl, kZeroes, hash_len)) {
if (!resolve_psk_secret(ssl)) {
return ssl_hs_error;
}

/* Resolve ECDHE and incorporate it into the secret. */
if (cipher->algorithm_mkey == SSL_kECDHE) {
const uint8_t *key_share_buf = NULL;
size_t key_share_len = 0;
CBS key_share;
if (!SSL_early_callback_ctx_extension_get(&early_ctx, TLSEXT_TYPE_key_share,
&key_share_buf, &key_share_len)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_KEY_SHARE);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_MISSING_EXTENSION);
return ssl_hs_error;
int need_retry;
if (!resolve_ecdhe_secret(ssl, &need_retry, &early_ctx)) {
if (need_retry) {
hs->state = state_send_hello_retry_request;
return ssl_hs_ok;
}
return ssl_hs_error;
}

CBS_init(&key_share, key_share_buf, key_share_len);
uint8_t *dhe_secret;
size_t dhe_secret_len;
uint8_t alert;
if (!ext_key_share_parse_clienthello(ssl, &dhe_secret, &dhe_secret_len,
&alert, &key_share)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
return ssl_hs_error;
}
hs->state = state_send_server_hello;
return ssl_hs_ok;
}

int ok = tls13_advance_key_schedule(ssl, dhe_secret, dhe_secret_len);
OPENSSL_free(dhe_secret);
if (!ok) {
return ssl_hs_error;
static enum ssl_hs_wait_t do_send_hello_retry_request(SSL *ssl,
SSL_HANDSHAKE *hs) {
CBB cbb, body, extensions;
uint16_t group_id;
if (!ssl->method->init_message(ssl, &cbb, &body,
SSL3_MT_HELLO_RETRY_REQUEST) ||
!CBB_add_u16(&body, ssl->version) ||
!CBB_add_u16(&body, ssl_cipher_get_value(ssl->s3->tmp.new_cipher)) ||
!tls1_get_shared_group(ssl, &group_id) ||
!CBB_add_u16(&body, group_id) ||
!CBB_add_u16_length_prefixed(&body, &extensions) ||
!ssl->method->finish_message(ssl, &cbb)) {
CBB_cleanup(&cbb);
return ssl_hs_error;
}

hs->state = state_flush_hello_retry_request;
return ssl_hs_write_message;
}

static enum ssl_hs_wait_t do_flush_hello_retry_request(SSL *ssl,
SSL_HANDSHAKE *hs) {
hs->state = state_process_second_client_hello;
return ssl_hs_flush_and_read_message;
}

static enum ssl_hs_wait_t do_process_second_client_hello(SSL *ssl,
SSL_HANDSHAKE *hs) {
if (!tls13_check_message_type(ssl, SSL3_MT_CLIENT_HELLO)) {
return ssl_hs_error;
}

struct ssl_early_callback_ctx early_ctx;

memset(&early_ctx, 0, sizeof(early_ctx));
early_ctx.ssl = ssl;
early_ctx.client_hello = ssl->init_msg;
early_ctx.client_hello_len = ssl->init_num;
if (!ssl_early_callback_init(&early_ctx)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return ssl_hs_error;
}

int need_retry;
if (!resolve_ecdhe_secret(ssl, &need_retry, &early_ctx)) {
if (need_retry) {
/* Only send one HelloRetryRequest. */
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
}
} else if (!tls13_advance_key_schedule(ssl, kZeroes, hash_len)) {
return ssl_hs_error;
}

if (!ssl->method->hash_current_message(ssl)) {
return ssl_hs_error;
}

@@ -352,7 +445,6 @@ static enum ssl_hs_wait_t do_send_server_finished(SSL *ssl, SSL_HANDSHAKE *hs) {

static enum ssl_hs_wait_t do_flush(SSL *ssl, SSL_HANDSHAKE *hs) {
/* Update the secret to the master secret and derive traffic keys. */
static const uint8_t kZeroes[EVP_MAX_MD_SIZE] = {0};
if (!tls13_advance_key_schedule(ssl, kZeroes, hs->hash_len) ||
!tls13_derive_traffic_secret_0(ssl) ||
!tls13_set_traffic_key(ssl, type_data, evp_aead_seal,
@@ -426,6 +518,15 @@ enum ssl_hs_wait_t tls13_server_handshake(SSL *ssl) {
case state_process_client_hello:
ret = do_process_client_hello(ssl, hs);
break;
case state_send_hello_retry_request:
ret = do_send_hello_retry_request(ssl, hs);
break;
case state_flush_hello_retry_request:
ret = do_flush_hello_retry_request(ssl, hs);
break;
case state_process_second_client_hello:
ret = do_process_second_client_hello(ssl, hs);
break;
case state_send_server_hello:
ret = do_send_server_hello(ssl, hs);
break;


Loading…
取消
儲存