OLD | NEW |
| (Empty) |
1 // Copyright (c) 2013 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/crypto/crypto_secret_boxer.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "base/memory/scoped_ptr.h" | |
9 #include "net/quic/crypto/crypto_protocol.h" | |
10 #include "net/quic/crypto/quic_decrypter.h" | |
11 #include "net/quic/crypto/quic_encrypter.h" | |
12 #include "net/quic/crypto/quic_random.h" | |
13 | |
14 using base::StringPiece; | |
15 using std::string; | |
16 | |
17 namespace net { | |
18 | |
19 // Defined kKeySize for GetKeySize() and SetKey(). | |
20 static const size_t kKeySize = 16; | |
21 | |
22 // kBoxNonceSize contains the number of bytes of nonce that we use in each box. | |
23 // TODO(rtenneti): Add support for kBoxNonceSize to be 16 bytes. | |
24 // | |
25 // From agl@: | |
26 // 96-bit nonces are on the edge. An attacker who can collect 2^41 | |
27 // source-address tokens has a 1% chance of finding a duplicate. | |
28 // | |
29 // The "average" DDoS is now 32.4M PPS. That's 2^25 source-address tokens | |
30 // per second. So one day of that DDoS botnot would reach the 1% mark. | |
31 // | |
32 // It's not terrible, but it's not a "forget about it" margin. | |
33 static const size_t kBoxNonceSize = 12; | |
34 | |
35 // static | |
36 size_t CryptoSecretBoxer::GetKeySize() { return kKeySize; } | |
37 | |
38 void CryptoSecretBoxer::SetKey(StringPiece key) { | |
39 DCHECK_EQ(kKeySize, key.size()); | |
40 key_ = key.as_string(); | |
41 } | |
42 | |
43 string CryptoSecretBoxer::Box(QuicRandom* rand, StringPiece plaintext) const { | |
44 scoped_ptr<QuicEncrypter> encrypter(QuicEncrypter::Create(kAESG)); | |
45 if (!encrypter->SetKey(key_)) { | |
46 DLOG(DFATAL) << "CryptoSecretBoxer's encrypter->SetKey failed."; | |
47 return string(); | |
48 } | |
49 size_t ciphertext_size = encrypter->GetCiphertextSize(plaintext.length()); | |
50 | |
51 string ret; | |
52 const size_t len = kBoxNonceSize + ciphertext_size; | |
53 ret.resize(len); | |
54 char* data = &ret[0]; | |
55 | |
56 // Generate nonce. | |
57 rand->RandBytes(data, kBoxNonceSize); | |
58 memcpy(data + kBoxNonceSize, plaintext.data(), plaintext.size()); | |
59 | |
60 if (!encrypter->Encrypt(StringPiece(data, kBoxNonceSize), StringPiece(), | |
61 plaintext, reinterpret_cast<unsigned char*>( | |
62 data + kBoxNonceSize))) { | |
63 DLOG(DFATAL) << "CryptoSecretBoxer's Encrypt failed."; | |
64 return string(); | |
65 } | |
66 | |
67 return ret; | |
68 } | |
69 | |
70 bool CryptoSecretBoxer::Unbox(StringPiece ciphertext, | |
71 string* out_storage, | |
72 StringPiece* out) const { | |
73 if (ciphertext.size() < kBoxNonceSize) { | |
74 return false; | |
75 } | |
76 | |
77 StringPiece nonce(ciphertext.data(), kBoxNonceSize); | |
78 ciphertext.remove_prefix(kBoxNonceSize); | |
79 QuicPacketSequenceNumber sequence_number; | |
80 StringPiece nonce_prefix(nonce.data(), | |
81 nonce.size() - sizeof(sequence_number)); | |
82 memcpy(&sequence_number, nonce.data() + nonce_prefix.size(), | |
83 sizeof(sequence_number)); | |
84 | |
85 scoped_ptr<QuicDecrypter> decrypter(QuicDecrypter::Create(kAESG)); | |
86 if (!decrypter->SetKey(key_)) { | |
87 DLOG(DFATAL) << "CryptoSecretBoxer's decrypter->SetKey failed."; | |
88 return false; | |
89 } | |
90 decrypter->SetNoncePrefix(nonce_prefix); | |
91 char plaintext[kMaxPacketSize]; | |
92 size_t plaintext_length = 0; | |
93 const bool success = decrypter->DecryptPacket( | |
94 sequence_number, StringPiece() /* associated data */, ciphertext, | |
95 plaintext, &plaintext_length, kMaxPacketSize); | |
96 if (!success) { | |
97 return false; | |
98 } | |
99 | |
100 out_storage->resize(plaintext_length); | |
101 out_storage->assign(plaintext, plaintext_length); | |
102 out->set(out_storage->data(), plaintext_length); | |
103 return true; | |
104 } | |
105 | |
106 } // namespace net | |
OLD | NEW |