OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/quic/crypto/aead_base_encrypter.h" | 5 #include "net/quic/crypto/aead_base_encrypter.h" |
6 | 6 |
7 #include <openssl/err.h> | 7 #include <openssl/err.h> |
8 #include <openssl/evp.h> | 8 #include <openssl/evp.h> |
9 #include <string.h> | 9 #include <string.h> |
10 | 10 |
11 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
12 | 12 |
13 using base::StringPiece; | 13 using base::StringPiece; |
14 | 14 |
15 namespace net { | 15 namespace net { |
16 | 16 |
17 namespace { | 17 namespace { |
18 | 18 |
19 // In debug builds only, log OpenSSL error stack. Then clear OpenSSL error | 19 // In debug builds only, log OpenSSL error stack. Then clear OpenSSL error |
20 // stack. | 20 // stack. |
21 void DLogOpenSslErrors() { | 21 void DLogOpenSslErrors() { |
22 #ifdef NDEBUG | 22 #ifdef NDEBUG |
23 while (ERR_get_error()) {} | 23 while (ERR_get_error()) { |
| 24 } |
24 #else | 25 #else |
25 while (unsigned long error = ERR_get_error()) { | 26 while (unsigned long error = ERR_get_error()) { |
26 char buf[120]; | 27 char buf[120]; |
27 ERR_error_string_n(error, buf, arraysize(buf)); | 28 ERR_error_string_n(error, buf, arraysize(buf)); |
28 DLOG(ERROR) << "OpenSSL error: " << buf; | 29 DLOG(ERROR) << "OpenSSL error: " << buf; |
29 } | 30 } |
30 #endif | 31 #endif |
31 } | 32 } |
32 | 33 |
33 } // namespace | 34 } // namespace |
34 | 35 |
35 AeadBaseEncrypter::AeadBaseEncrypter(const EVP_AEAD* aead_alg, | 36 AeadBaseEncrypter::AeadBaseEncrypter(const EVP_AEAD* aead_alg, |
36 size_t key_size, | 37 size_t key_size, |
37 size_t auth_tag_size, | 38 size_t auth_tag_size, |
38 size_t nonce_prefix_size) | 39 size_t nonce_prefix_size) |
39 : aead_alg_(aead_alg), | 40 : aead_alg_(aead_alg), |
40 key_size_(key_size), | 41 key_size_(key_size), |
41 auth_tag_size_(auth_tag_size), | 42 auth_tag_size_(auth_tag_size), |
42 nonce_prefix_size_(nonce_prefix_size) { | 43 nonce_prefix_size_(nonce_prefix_size) { |
43 DCHECK_LE(key_size_, sizeof(key_)); | 44 DCHECK_LE(key_size_, sizeof(key_)); |
44 DCHECK_LE(nonce_prefix_size_, sizeof(nonce_prefix_)); | 45 DCHECK_LE(nonce_prefix_size_, sizeof(nonce_prefix_)); |
45 } | 46 } |
46 | 47 |
47 AeadBaseEncrypter::~AeadBaseEncrypter() {} | 48 AeadBaseEncrypter::~AeadBaseEncrypter() { |
| 49 } |
48 | 50 |
49 bool AeadBaseEncrypter::SetKey(StringPiece key) { | 51 bool AeadBaseEncrypter::SetKey(StringPiece key) { |
50 DCHECK_EQ(key.size(), key_size_); | 52 DCHECK_EQ(key.size(), key_size_); |
51 if (key.size() != key_size_) { | 53 if (key.size() != key_size_) { |
52 return false; | 54 return false; |
53 } | 55 } |
54 memcpy(key_, key.data(), key.size()); | 56 memcpy(key_, key.data(), key.size()); |
55 | 57 |
56 EVP_AEAD_CTX_cleanup(ctx_.get()); | 58 EVP_AEAD_CTX_cleanup(ctx_.get()); |
57 | 59 |
58 if (!EVP_AEAD_CTX_init(ctx_.get(), aead_alg_, key_, key_size_, | 60 if (!EVP_AEAD_CTX_init( |
59 auth_tag_size_, NULL)) { | 61 ctx_.get(), aead_alg_, key_, key_size_, auth_tag_size_, NULL)) { |
60 DLogOpenSslErrors(); | 62 DLogOpenSslErrors(); |
61 return false; | 63 return false; |
62 } | 64 } |
63 | 65 |
64 return true; | 66 return true; |
65 } | 67 } |
66 | 68 |
67 bool AeadBaseEncrypter::SetNoncePrefix(StringPiece nonce_prefix) { | 69 bool AeadBaseEncrypter::SetNoncePrefix(StringPiece nonce_prefix) { |
68 DCHECK_EQ(nonce_prefix.size(), nonce_prefix_size_); | 70 DCHECK_EQ(nonce_prefix.size(), nonce_prefix_size_); |
69 if (nonce_prefix.size() != nonce_prefix_size_) { | 71 if (nonce_prefix.size() != nonce_prefix_size_) { |
70 return false; | 72 return false; |
71 } | 73 } |
72 memcpy(nonce_prefix_, nonce_prefix.data(), nonce_prefix.size()); | 74 memcpy(nonce_prefix_, nonce_prefix.data(), nonce_prefix.size()); |
73 return true; | 75 return true; |
74 } | 76 } |
75 | 77 |
76 bool AeadBaseEncrypter::Encrypt(StringPiece nonce, | 78 bool AeadBaseEncrypter::Encrypt(StringPiece nonce, |
77 StringPiece associated_data, | 79 StringPiece associated_data, |
78 StringPiece plaintext, | 80 StringPiece plaintext, |
79 unsigned char* output) { | 81 unsigned char* output) { |
80 if (nonce.size() != nonce_prefix_size_ + sizeof(QuicPacketSequenceNumber)) { | 82 if (nonce.size() != nonce_prefix_size_ + sizeof(QuicPacketSequenceNumber)) { |
81 return false; | 83 return false; |
82 } | 84 } |
83 | 85 |
84 ssize_t len = EVP_AEAD_CTX_seal( | 86 ssize_t len = EVP_AEAD_CTX_seal( |
85 ctx_.get(), output, plaintext.size() + auth_tag_size_, | 87 ctx_.get(), |
86 reinterpret_cast<const uint8_t*>(nonce.data()), nonce.size(), | 88 output, |
87 reinterpret_cast<const uint8_t*>(plaintext.data()), plaintext.size(), | 89 plaintext.size() + auth_tag_size_, |
| 90 reinterpret_cast<const uint8_t*>(nonce.data()), |
| 91 nonce.size(), |
| 92 reinterpret_cast<const uint8_t*>(plaintext.data()), |
| 93 plaintext.size(), |
88 reinterpret_cast<const uint8_t*>(associated_data.data()), | 94 reinterpret_cast<const uint8_t*>(associated_data.data()), |
89 associated_data.size()); | 95 associated_data.size()); |
90 | 96 |
91 if (len < 0) { | 97 if (len < 0) { |
92 DLogOpenSslErrors(); | 98 DLogOpenSslErrors(); |
93 return false; | 99 return false; |
94 } | 100 } |
95 | 101 |
96 return true; | 102 return true; |
97 } | 103 } |
98 | 104 |
99 QuicData* AeadBaseEncrypter::EncryptPacket( | 105 QuicData* AeadBaseEncrypter::EncryptPacket( |
100 QuicPacketSequenceNumber sequence_number, | 106 QuicPacketSequenceNumber sequence_number, |
101 StringPiece associated_data, | 107 StringPiece associated_data, |
102 StringPiece plaintext) { | 108 StringPiece plaintext) { |
103 size_t ciphertext_size = GetCiphertextSize(plaintext.length()); | 109 size_t ciphertext_size = GetCiphertextSize(plaintext.length()); |
104 scoped_ptr<char[]> ciphertext(new char[ciphertext_size]); | 110 scoped_ptr<char[]> ciphertext(new char[ciphertext_size]); |
105 | 111 |
106 // TODO(ianswett): Introduce a check to ensure that we don't encrypt with the | 112 // TODO(ianswett): Introduce a check to ensure that we don't encrypt with the |
107 // same sequence number twice. | 113 // same sequence number twice. |
108 uint8 nonce[sizeof(nonce_prefix_) + sizeof(sequence_number)]; | 114 uint8 nonce[sizeof(nonce_prefix_) + sizeof(sequence_number)]; |
109 const size_t nonce_size = nonce_prefix_size_ + sizeof(sequence_number); | 115 const size_t nonce_size = nonce_prefix_size_ + sizeof(sequence_number); |
110 DCHECK_LE(nonce_size, sizeof(nonce)); | 116 DCHECK_LE(nonce_size, sizeof(nonce)); |
111 memcpy(nonce, nonce_prefix_, nonce_prefix_size_); | 117 memcpy(nonce, nonce_prefix_, nonce_prefix_size_); |
112 memcpy(nonce + nonce_prefix_size_, &sequence_number, sizeof(sequence_number)); | 118 memcpy(nonce + nonce_prefix_size_, &sequence_number, sizeof(sequence_number)); |
113 if (!Encrypt(StringPiece(reinterpret_cast<char*>(nonce), nonce_size), | 119 if (!Encrypt(StringPiece(reinterpret_cast<char*>(nonce), nonce_size), |
114 associated_data, plaintext, | 120 associated_data, |
| 121 plaintext, |
115 reinterpret_cast<unsigned char*>(ciphertext.get()))) { | 122 reinterpret_cast<unsigned char*>(ciphertext.get()))) { |
116 return NULL; | 123 return NULL; |
117 } | 124 } |
118 | 125 |
119 return new QuicData(ciphertext.release(), ciphertext_size, true); | 126 return new QuicData(ciphertext.release(), ciphertext_size, true); |
120 } | 127 } |
121 | 128 |
122 size_t AeadBaseEncrypter::GetKeySize() const { return key_size_; } | 129 size_t AeadBaseEncrypter::GetKeySize() const { |
| 130 return key_size_; |
| 131 } |
123 | 132 |
124 size_t AeadBaseEncrypter::GetNoncePrefixSize() const { | 133 size_t AeadBaseEncrypter::GetNoncePrefixSize() const { |
125 return nonce_prefix_size_; | 134 return nonce_prefix_size_; |
126 } | 135 } |
127 | 136 |
128 size_t AeadBaseEncrypter::GetMaxPlaintextSize(size_t ciphertext_size) const { | 137 size_t AeadBaseEncrypter::GetMaxPlaintextSize(size_t ciphertext_size) const { |
129 return ciphertext_size - auth_tag_size_; | 138 return ciphertext_size - auth_tag_size_; |
130 } | 139 } |
131 | 140 |
132 size_t AeadBaseEncrypter::GetCiphertextSize(size_t plaintext_size) const { | 141 size_t AeadBaseEncrypter::GetCiphertextSize(size_t plaintext_size) const { |
133 return plaintext_size + auth_tag_size_; | 142 return plaintext_size + auth_tag_size_; |
134 } | 143 } |
135 | 144 |
136 StringPiece AeadBaseEncrypter::GetKey() const { | 145 StringPiece AeadBaseEncrypter::GetKey() const { |
137 return StringPiece(reinterpret_cast<const char*>(key_), key_size_); | 146 return StringPiece(reinterpret_cast<const char*>(key_), key_size_); |
138 } | 147 } |
139 | 148 |
140 StringPiece AeadBaseEncrypter::GetNoncePrefix() const { | 149 StringPiece AeadBaseEncrypter::GetNoncePrefix() const { |
141 if (nonce_prefix_size_ == 0) { | 150 if (nonce_prefix_size_ == 0) { |
142 return StringPiece(); | 151 return StringPiece(); |
143 } | 152 } |
144 return StringPiece(reinterpret_cast<const char*>(nonce_prefix_), | 153 return StringPiece(reinterpret_cast<const char*>(nonce_prefix_), |
145 nonce_prefix_size_); | 154 nonce_prefix_size_); |
146 } | 155 } |
147 | 156 |
148 } // namespace net | 157 } // namespace net |
OLD | NEW |