1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/quic/quic_crypto_server_stream.h"
7 #include "base/base64.h"
8 #include "crypto/secure_hash.h"
9 #include "net/quic/crypto/crypto_protocol.h"
10 #include "net/quic/crypto/crypto_utils.h"
11 #include "net/quic/crypto/quic_crypto_server_config.h"
12 #include "net/quic/quic_config.h"
13 #include "net/quic/quic_protocol.h"
14 #include "net/quic/quic_session.h"
18 QuicCryptoServerStream::QuicCryptoServerStream(
19 const QuicCryptoServerConfig& crypto_config,
21 : QuicCryptoStream(session),
22 crypto_config_(crypto_config) {
25 QuicCryptoServerStream::~QuicCryptoServerStream() {
28 void QuicCryptoServerStream::OnHandshakeMessage(
29 const CryptoHandshakeMessage& message) {
30 QuicCryptoStream::OnHandshakeMessage(message);
32 // Do not process handshake messages after the handshake is confirmed.
33 if (handshake_confirmed_) {
34 CloseConnection(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE);
38 if (message.tag() != kCHLO) {
39 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE);
44 CryptoHandshakeMessage reply;
46 QuicErrorCode error = ProcessClientHello(message, &reply, &error_details);
48 if (error != QUIC_NO_ERROR) {
49 CloseConnectionWithDetails(error, error_details);
53 if (reply.tag() != kSHLO) {
54 SendHandshakeMessage(reply);
58 // If we are returning a SHLO then we accepted the handshake.
59 QuicConfig* config = session()->config();
60 error = config->ProcessClientHello(message, &error_details);
61 if (error != QUIC_NO_ERROR) {
62 CloseConnectionWithDetails(error, error_details);
65 session()->OnConfigNegotiated();
67 config->ToHandshakeMessage(&reply);
69 // Receiving a full CHLO implies the client is prepared to decrypt with
70 // the new server write key. We can start to encrypt with the new server
73 // NOTE: the SHLO will be encrypted with the new server write key.
74 session()->connection()->SetEncrypter(
76 crypto_negotiated_params_.initial_crypters.encrypter.release());
77 session()->connection()->SetDefaultEncryptionLevel(
79 // Set the decrypter immediately so that we no longer accept unencrypted
81 session()->connection()->SetDecrypter(
82 crypto_negotiated_params_.initial_crypters.decrypter.release());
83 SendHandshakeMessage(reply);
85 session()->connection()->SetEncrypter(
86 ENCRYPTION_FORWARD_SECURE,
87 crypto_negotiated_params_.forward_secure_crypters.encrypter.release());
88 session()->connection()->SetDefaultEncryptionLevel(
89 ENCRYPTION_FORWARD_SECURE);
90 session()->connection()->SetAlternativeDecrypter(
91 crypto_negotiated_params_.forward_secure_crypters.decrypter.release(),
92 false /* don't latch */);
94 encryption_established_ = true;
95 handshake_confirmed_ = true;
96 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
99 bool QuicCryptoServerStream::GetBase64SHA256ClientChannelID(
100 string* output) const {
101 if (!encryption_established_ ||
102 crypto_negotiated_params_.channel_id.empty()) {
106 const string& channel_id(crypto_negotiated_params_.channel_id);
107 scoped_ptr<crypto::SecureHash> hash(
108 crypto::SecureHash::Create(crypto::SecureHash::SHA256));
109 hash->Update(channel_id.data(), channel_id.size());
111 hash->Finish(digest, sizeof(digest));
113 base::Base64Encode(string(
114 reinterpret_cast<const char*>(digest), sizeof(digest)), output);
116 size_t len = output->size();
118 if ((*output)[len - 1] == '=') {
120 if ((*output)[len - 1] == '=') {
129 QuicErrorCode QuicCryptoServerStream::ProcessClientHello(
130 const CryptoHandshakeMessage& message,
131 CryptoHandshakeMessage* reply,
132 string* error_details) {
133 return crypto_config_.ProcessClientHello(
135 session()->connection()->guid(),
136 session()->connection()->peer_address(),
137 session()->connection()->clock(),
138 session()->connection()->random_generator(),
139 &crypto_negotiated_params_, reply, error_details);