Implement OCSP stapling in TLS 1.3.

Change-Id: Iad572f44448141c5e2be49bf25b42719c625a97a
Reviewed-on: https://boringssl-review.googlesource.com/8812
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>
This commit is contained in:
David Benjamin 2016-07-16 19:03:49 +03:00 committed by CQ bot account: commit-bot@chromium.org
parent 143e8b3fd9
commit 942f4ed64e
2 changed files with 79 additions and 14 deletions

View File

@ -1184,6 +1184,12 @@ static int ext_ocsp_parse_serverhello(SSL *ssl, uint8_t *out_alert,
return 1; return 1;
} }
/* OCSP stapling is forbidden on a non-certificate cipher. */
if (!ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
return 0;
}
if (ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
if (CBS_len(contents) != 0) { if (CBS_len(contents) != 0) {
return 0; return 0;
} }
@ -1192,6 +1198,25 @@ static int ext_ocsp_parse_serverhello(SSL *ssl, uint8_t *out_alert,
return 1; return 1;
} }
uint8_t status_type;
CBS ocsp_response;
if (!CBS_get_u8(contents, &status_type) ||
status_type != TLSEXT_STATUSTYPE_ocsp ||
!CBS_get_u24_length_prefixed(contents, &ocsp_response) ||
CBS_len(&ocsp_response) == 0 ||
CBS_len(contents) != 0) {
return 0;
}
if (!CBS_stow(&ocsp_response, &ssl->session->ocsp_response,
&ssl->session->ocsp_response_length)) {
*out_alert = SSL_AD_INTERNAL_ERROR;
return 0;
}
return 1;
}
static int ext_ocsp_parse_clienthello(SSL *ssl, uint8_t *out_alert, static int ext_ocsp_parse_clienthello(SSL *ssl, uint8_t *out_alert,
CBS *contents) { CBS *contents) {
if (contents == NULL) { if (contents == NULL) {
@ -1211,14 +1236,15 @@ static int ext_ocsp_parse_clienthello(SSL *ssl, uint8_t *out_alert,
} }
static int ext_ocsp_add_serverhello(SSL *ssl, CBB *out) { static int ext_ocsp_add_serverhello(SSL *ssl, CBB *out) {
if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) { if (!ssl->s3->tmp.ocsp_stapling_requested ||
ssl->ctx->ocsp_response_length == 0 ||
!ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
return 1; return 1;
} }
if (ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
/* The extension shouldn't be sent when resuming sessions. */ /* The extension shouldn't be sent when resuming sessions. */
if (ssl->hit || if (ssl->hit) {
!ssl->s3->tmp.ocsp_stapling_requested ||
ssl->ctx->ocsp_response_length == 0) {
return 1; return 1;
} }
@ -1228,6 +1254,16 @@ static int ext_ocsp_add_serverhello(SSL *ssl, CBB *out) {
CBB_add_u16(out, 0 /* length */); CBB_add_u16(out, 0 /* length */);
} }
CBB body, ocsp_response;
return CBB_add_u16(out, TLSEXT_TYPE_status_request) &&
CBB_add_u16_length_prefixed(out, &body) &&
CBB_add_u8(&body, TLSEXT_STATUSTYPE_ocsp) &&
CBB_add_u24_length_prefixed(&body, &ocsp_response) &&
CBB_add_bytes(&ocsp_response, ssl->ctx->ocsp_response,
ssl->ctx->ocsp_response_length) &&
CBB_flush(out);
}
/* Next protocol negotiation. /* Next protocol negotiation.
* *

View File

@ -507,7 +507,7 @@ func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool) er
} }
if test.expectedOCSPResponse != nil && !bytes.Equal(test.expectedOCSPResponse, tlsConn.OCSPResponse()) { if test.expectedOCSPResponse != nil && !bytes.Equal(test.expectedOCSPResponse, tlsConn.OCSPResponse()) {
return fmt.Errorf("OCSP Response mismatch") return fmt.Errorf("OCSP Response mismatch: got %x, wanted %x", tlsConn.OCSPResponse(), test.expectedOCSPResponse)
} }
if test.expectedSCTList != nil && !bytes.Equal(test.expectedSCTList, connState.SCTList) { if test.expectedSCTList != nil && !bytes.Equal(test.expectedSCTList, connState.SCTList) {
@ -3204,8 +3204,6 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) {
}) })
// OCSP stapling tests. // OCSP stapling tests.
//
// TODO(davidben): Test the TLS 1.3 version of OCSP stapling.
tests = append(tests, testCase{ tests = append(tests, testCase{
testType: clientTest, testType: clientTest,
name: "OCSPStapling-Client", name: "OCSPStapling-Client",
@ -3233,6 +3231,37 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) {
}, },
resumeSession: true, resumeSession: true,
}) })
tests = append(tests, testCase{
testType: clientTest,
name: "OCSPStapling-Client-TLS13",
config: Config{
MaxVersion: VersionTLS13,
},
flags: []string{
"-enable-ocsp-stapling",
"-expect-ocsp-response",
base64.StdEncoding.EncodeToString(testOCSPResponse),
"-verify-peer",
},
// TODO(davidben): Enable this when resumption is implemented
// in TLS 1.3.
resumeSession: false,
})
tests = append(tests, testCase{
testType: serverTest,
name: "OCSPStapling-Server-TLS13",
config: Config{
MaxVersion: VersionTLS13,
},
expectedOCSPResponse: testOCSPResponse,
flags: []string{
"-ocsp-response",
base64.StdEncoding.EncodeToString(testOCSPResponse),
},
// TODO(davidben): Enable this when resumption is implemented
// in TLS 1.3.
resumeSession: false,
})
// Certificate verification tests. // Certificate verification tests.
for _, vers := range tlsVersions { for _, vers := range tlsVersions {