diff options
author | Kristian Monsen <kristianm@google.com> | 2011-06-28 21:49:31 +0100 |
---|---|---|
committer | Kristian Monsen <kristianm@google.com> | 2011-07-08 17:55:00 +0100 |
commit | ddb351dbec246cf1fab5ec20d2d5520909041de1 (patch) | |
tree | 158e3fb57bdcac07c7f1e767fde3c70687c9fbb1 /crypto/encryptor_win.cc | |
parent | 6b92e04f5f151c896e3088e86f70db7081009308 (diff) | |
download | external_chromium-ddb351dbec246cf1fab5ec20d2d5520909041de1.zip external_chromium-ddb351dbec246cf1fab5ec20d2d5520909041de1.tar.gz external_chromium-ddb351dbec246cf1fab5ec20d2d5520909041de1.tar.bz2 |
Merge Chromium at r12.0.742.93: Initial merge by git
Change-Id: Ic5ee2fec31358bbee305f7e915442377bfa6cda6
Diffstat (limited to 'crypto/encryptor_win.cc')
-rw-r--r-- | crypto/encryptor_win.cc | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/crypto/encryptor_win.cc b/crypto/encryptor_win.cc new file mode 100644 index 0000000..8bbd6b8 --- /dev/null +++ b/crypto/encryptor_win.cc @@ -0,0 +1,115 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/encryptor.h" + +#include <vector> + +#include "crypto/symmetric_key.h" + +namespace crypto { + +namespace { + +// On success, returns the block size (in bytes) for the algorithm that |key| +// is for. On failure, returns 0. +DWORD GetCipherBlockSize(HCRYPTKEY key) { + DWORD block_size_in_bits = 0; + DWORD param_size = sizeof(block_size_in_bits); + BOOL ok = CryptGetKeyParam(key, KP_BLOCKLEN, + reinterpret_cast<BYTE*>(&block_size_in_bits), + ¶m_size, 0); + if (!ok) + return 0; + + return block_size_in_bits / 8; +} + +} // namespace + +Encryptor::Encryptor() + : key_(NULL), + mode_(CBC), + block_size_(0) { +} + +Encryptor::~Encryptor() { +} + +bool Encryptor::Init(SymmetricKey* key, Mode mode, const std::string& iv) { + DCHECK(key); + DCHECK_EQ(CBC, mode) << "Unsupported mode of operation"; + + // In CryptoAPI, the IV, padding mode, and feedback register (for a chaining + // mode) are properties of a key, so we have to create a copy of the key for + // the Encryptor. See the Remarks section of the CryptEncrypt MSDN page. + BOOL ok = CryptDuplicateKey(key->key(), NULL, 0, capi_key_.receive()); + if (!ok) + return false; + + // CRYPT_MODE_CBC is the default for Microsoft Base Cryptographic Provider, + // but we set it anyway to be safe. + DWORD cipher_mode = CRYPT_MODE_CBC; + ok = CryptSetKeyParam(capi_key_.get(), KP_MODE, + reinterpret_cast<BYTE*>(&cipher_mode), 0); + if (!ok) + return false; + + block_size_ = GetCipherBlockSize(capi_key_.get()); + if (block_size_ == 0) + return false; + + if (iv.size() != block_size_) + return false; + + ok = CryptSetKeyParam(capi_key_.get(), KP_IV, + reinterpret_cast<const BYTE*>(iv.data()), 0); + if (!ok) + return false; + + DWORD padding_method = PKCS5_PADDING; + ok = CryptSetKeyParam(capi_key_.get(), KP_PADDING, + reinterpret_cast<BYTE*>(&padding_method), 0); + if (!ok) + return false; + + return true; +} + +bool Encryptor::Encrypt(const std::string& plaintext, std::string* ciphertext) { + DWORD data_len = plaintext.size(); + DWORD total_len = data_len + block_size_; + + // CryptoAPI encrypts/decrypts in place. + std::vector<BYTE> tmp(total_len); + memcpy(&tmp[0], plaintext.data(), data_len); + + BOOL ok = CryptEncrypt(capi_key_.get(), NULL, TRUE, 0, &tmp[0], + &data_len, total_len); + if (!ok) + return false; + + ciphertext->assign(reinterpret_cast<char*>(&tmp[0]), data_len); + return true; +} + +bool Encryptor::Decrypt(const std::string& ciphertext, std::string* plaintext) { + DWORD data_len = ciphertext.size(); + if (data_len == 0) + return false; + + std::vector<BYTE> tmp(data_len); + memcpy(&tmp[0], ciphertext.data(), data_len); + + BOOL ok = CryptDecrypt(capi_key_.get(), NULL, TRUE, 0, &tmp[0], &data_len); + if (!ok) + return false; + + DCHECK_GT(tmp.size(), data_len); + + plaintext->assign(reinterpret_cast<char*>(&tmp[0]), data_len); + return true; +} + +} // namespace crypto |