Chromium Code Reviews| Index: crypto/encryptor_openssl.cc |
| diff --git a/crypto/encryptor_openssl.cc b/crypto/encryptor_openssl.cc |
| index 65131818243edbf48733b84015e5c36d36cc2a35..5755a6386cef0018ee33b53fae6a6593871f5074 100644 |
| --- a/crypto/encryptor_openssl.cc |
| +++ b/crypto/encryptor_openssl.cc |
| @@ -55,8 +55,8 @@ Encryptor::~Encryptor() { |
| bool Encryptor::Init(SymmetricKey* key, |
| Mode mode, |
| const base::StringPiece& iv) { |
| - DCHECK(key); |
| - DCHECK_EQ(CBC, mode); |
| + if (!key || mode != CBC) |
| + return false; |
| EnsureOpenSSLInit(); |
| if (iv.size() != AES_BLOCK_SIZE) |
| @@ -73,39 +73,49 @@ bool Encryptor::Init(SymmetricKey* key, |
| bool Encryptor::Encrypt(const base::StringPiece& plaintext, |
| std::string* ciphertext) { |
| + ciphertext->clear(); |
| + if (plaintext.empty() && mode_ != CBC) |
| + return false; |
| return Crypt(true, plaintext, ciphertext); |
| } |
| bool Encryptor::Decrypt(const base::StringPiece& ciphertext, |
| std::string* plaintext) { |
| + plaintext->clear(); |
| + if (ciphertext.empty()) |
| + return false; |
| return Crypt(false, ciphertext, plaintext); |
| } |
| bool Encryptor::Crypt(bool do_encrypt, |
| const base::StringPiece& input, |
| std::string* output) { |
| - DCHECK(key_); // Must call Init() before En/De-crypt. |
| - // Work on the result in a local variable, and then only transfer it to |
| - // |output| on success to ensure no partial data is returned. |
| - std::string result; |
| - output->swap(result); |
| + if (!key_) |
| + return false; // Must call Init() first. |
| const EVP_CIPHER* cipher = GetCipherForKey(key_); |
| DCHECK(cipher); // Already handled in Init(); |
| const std::string& key = key_->key(); |
| - DCHECK_EQ(EVP_CIPHER_iv_length(cipher), static_cast<int>(iv_.length())); |
| - DCHECK_EQ(EVP_CIPHER_key_length(cipher), static_cast<int>(key.length())); |
| + if (EVP_CIPHER_iv_length(cipher) != static_cast<int>(iv_.length()) || |
| + EVP_CIPHER_key_length(cipher) != static_cast<int>(key.length())) { |
| + return false; |
| + } |
| ScopedCipherCTX ctx; |
| if (!EVP_CipherInit_ex(ctx.get(), cipher, NULL, |
| reinterpret_cast<const uint8*>(key.data()), |
| reinterpret_cast<const uint8*>(iv_.data()), |
| - do_encrypt)) |
| + do_encrypt)) { |
| return false; |
| + } |
| + std::string result; |
| // When encrypting, add another block size of space to allow for any padding. |
| const size_t output_size = input.size() + (do_encrypt ? iv_.size() : 0); |
| + if (output_size == 0 || output_size + 1 < input.size()) |
| + return false; |
| + |
| uint8* out_ptr = reinterpret_cast<uint8*>(WriteInto(&result, |
| output_size + 1)); |
| int out_len; |
| @@ -121,9 +131,10 @@ bool Encryptor::Crypt(bool do_encrypt, |
| return false; |
| out_len += tail_len; |
| - DCHECK_LE(out_len, static_cast<int>(output_size)); |
| - result.resize(out_len); |
| + if (static_cast<int>(output_size) < out_len) |
| + return false; |
|
wtc
2011/11/15 02:33:58
If we get here, we have overrun the buffer in 'res
|
| + result.resize(out_len); |
| output->swap(result); |
| return true; |
| } |