- add sources.
[platform/framework/web/crosswalk.git] / src / net / quic / quic_crypto_server_stream.cc
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.
4
5 #include "net/quic/quic_crypto_server_stream.h"
6
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"
15
16 namespace net {
17
18 QuicCryptoServerStream::QuicCryptoServerStream(
19     const QuicCryptoServerConfig& crypto_config,
20     QuicSession* session)
21     : QuicCryptoStream(session),
22       crypto_config_(crypto_config) {
23 }
24
25 QuicCryptoServerStream::~QuicCryptoServerStream() {
26 }
27
28 void QuicCryptoServerStream::OnHandshakeMessage(
29     const CryptoHandshakeMessage& message) {
30   QuicCryptoStream::OnHandshakeMessage(message);
31
32   // Do not process handshake messages after the handshake is confirmed.
33   if (handshake_confirmed_) {
34     CloseConnection(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE);
35     return;
36   }
37
38   if (message.tag() != kCHLO) {
39     CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE);
40     return;
41   }
42
43   string error_details;
44   CryptoHandshakeMessage reply;
45
46   QuicErrorCode error = ProcessClientHello(message, &reply, &error_details);
47
48   if (error != QUIC_NO_ERROR) {
49     CloseConnectionWithDetails(error, error_details);
50     return;
51   }
52
53   if (reply.tag() != kSHLO) {
54     SendHandshakeMessage(reply);
55     return;
56   }
57
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);
63     return;
64   }
65   session()->OnConfigNegotiated();
66
67   config->ToHandshakeMessage(&reply);
68
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
71   // write key.
72   //
73   // NOTE: the SHLO will be encrypted with the new server write key.
74   session()->connection()->SetEncrypter(
75       ENCRYPTION_INITIAL,
76       crypto_negotiated_params_.initial_crypters.encrypter.release());
77   session()->connection()->SetDefaultEncryptionLevel(
78       ENCRYPTION_INITIAL);
79   // Set the decrypter immediately so that we no longer accept unencrypted
80   // packets.
81   session()->connection()->SetDecrypter(
82       crypto_negotiated_params_.initial_crypters.decrypter.release());
83   SendHandshakeMessage(reply);
84
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 */);
93
94   encryption_established_ = true;
95   handshake_confirmed_ = true;
96   session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
97 }
98
99 bool QuicCryptoServerStream::GetBase64SHA256ClientChannelID(
100     string* output) const {
101   if (!encryption_established_ ||
102       crypto_negotiated_params_.channel_id.empty()) {
103     return false;
104   }
105
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());
110   uint8 digest[32];
111   hash->Finish(digest, sizeof(digest));
112
113   base::Base64Encode(string(
114       reinterpret_cast<const char*>(digest), sizeof(digest)), output);
115   // Remove padding.
116   size_t len = output->size();
117   if (len >= 2) {
118     if ((*output)[len - 1] == '=') {
119       len--;
120       if ((*output)[len - 1] == '=') {
121         len--;
122       }
123       output->resize(len);
124     }
125   }
126   return true;
127 }
128
129 QuicErrorCode QuicCryptoServerStream::ProcessClientHello(
130     const CryptoHandshakeMessage& message,
131     CryptoHandshakeMessage* reply,
132     string* error_details) {
133   return crypto_config_.ProcessClientHello(
134       message,
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);
140 }
141
142 }  // namespace net