diff options
author | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-14 17:37:14 +0000 |
---|---|---|
committer | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-14 17:37:14 +0000 |
commit | 4b559b4ddffc0b7f688019bcb80658f05e063af7 (patch) | |
tree | 0be21d8914de707f5125d2cb66733cbcf088606c /crypto/encryptor_win.cc | |
parent | 056dd45d610de34312344445d7b078a31f4a1e20 (diff) | |
download | chromium_src-4b559b4ddffc0b7f688019bcb80658f05e063af7.zip chromium_src-4b559b4ddffc0b7f688019bcb80658f05e063af7.tar.gz chromium_src-4b559b4ddffc0b7f688019bcb80658f05e063af7.tar.bz2 |
Move crypto files out of base, to a top level directory.
src/crypto is now an independent project that contains our
cryptographic primitives (except md5 and sha1).
This removes the base dependency from nss, openssl and sqlite.
BUG=76996
TEST=none
Review URL: http://codereview.chromium.org/6805019
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@81611 0039d316-1c4b-4281-b951-d872f2087c98
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 |