| 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 |