Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(968)

Side by Side Diff: crypto/encryptor_openssl.cc

Issue 1909513003: Rename crypto/ *_openssl files (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « crypto/encryptor.cc ('k') | crypto/rsa_private_key.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "crypto/encryptor.h"
6
7 #include <openssl/aes.h>
8 #include <openssl/evp.h>
9 #include <stddef.h>
10 #include <stdint.h>
11
12 #include "base/logging.h"
13 #include "base/strings/string_util.h"
14 #include "crypto/openssl_util.h"
15 #include "crypto/symmetric_key.h"
16
17 namespace crypto {
18
19 namespace {
20
21 const EVP_CIPHER* GetCipherForKey(SymmetricKey* key) {
22 switch (key->key().length()) {
23 case 16: return EVP_aes_128_cbc();
24 case 32: return EVP_aes_256_cbc();
25 default: return NULL;
26 }
27 }
28
29 // On destruction this class will cleanup the ctx, and also clear the OpenSSL
30 // ERR stack as a convenience.
31 class ScopedCipherCTX {
32 public:
33 explicit ScopedCipherCTX() {
34 EVP_CIPHER_CTX_init(&ctx_);
35 }
36 ~ScopedCipherCTX() {
37 EVP_CIPHER_CTX_cleanup(&ctx_);
38 ClearOpenSSLERRStack(FROM_HERE);
39 }
40 EVP_CIPHER_CTX* get() { return &ctx_; }
41
42 private:
43 EVP_CIPHER_CTX ctx_;
44 };
45
46 } // namespace
47
48 Encryptor::Encryptor()
49 : key_(NULL),
50 mode_(CBC) {
51 }
52
53 Encryptor::~Encryptor() {
54 }
55
56 bool Encryptor::Init(SymmetricKey* key,
57 Mode mode,
58 const base::StringPiece& iv) {
59 DCHECK(key);
60 DCHECK(mode == CBC || mode == CTR);
61
62 EnsureOpenSSLInit();
63 if (mode == CBC && iv.size() != AES_BLOCK_SIZE)
64 return false;
65
66 if (GetCipherForKey(key) == NULL)
67 return false;
68
69 key_ = key;
70 mode_ = mode;
71 iv.CopyToString(&iv_);
72 return true;
73 }
74
75 bool Encryptor::Encrypt(const base::StringPiece& plaintext,
76 std::string* ciphertext) {
77 CHECK(!plaintext.empty() || (mode_ == CBC));
78 return (mode_ == CTR) ?
79 CryptCTR(true, plaintext, ciphertext) :
80 Crypt(true, plaintext, ciphertext);
81 }
82
83 bool Encryptor::Decrypt(const base::StringPiece& ciphertext,
84 std::string* plaintext) {
85 CHECK(!ciphertext.empty());
86 return (mode_ == CTR) ?
87 CryptCTR(false, ciphertext, plaintext) :
88 Crypt(false, ciphertext, plaintext);
89 }
90
91 bool Encryptor::Crypt(bool do_encrypt,
92 const base::StringPiece& input,
93 std::string* output) {
94 DCHECK(key_); // Must call Init() before En/De-crypt.
95 // Work on the result in a local variable, and then only transfer it to
96 // |output| on success to ensure no partial data is returned.
97 std::string result;
98 output->clear();
99
100 const EVP_CIPHER* cipher = GetCipherForKey(key_);
101 DCHECK(cipher); // Already handled in Init();
102
103 const std::string& key = key_->key();
104 DCHECK_EQ(EVP_CIPHER_iv_length(cipher), iv_.length());
105 DCHECK_EQ(EVP_CIPHER_key_length(cipher), key.length());
106
107 ScopedCipherCTX ctx;
108 if (!EVP_CipherInit_ex(
109 ctx.get(), cipher, NULL, reinterpret_cast<const uint8_t*>(key.data()),
110 reinterpret_cast<const uint8_t*>(iv_.data()), do_encrypt))
111 return false;
112
113 // When encrypting, add another block size of space to allow for any padding.
114 const size_t output_size = input.size() + (do_encrypt ? iv_.size() : 0);
115 CHECK_GT(output_size, 0u);
116 CHECK_GT(output_size + 1, input.size());
117 uint8_t* out_ptr =
118 reinterpret_cast<uint8_t*>(base::WriteInto(&result, output_size + 1));
119 int out_len;
120 if (!EVP_CipherUpdate(ctx.get(), out_ptr, &out_len,
121 reinterpret_cast<const uint8_t*>(input.data()),
122 input.length()))
123 return false;
124
125 // Write out the final block plus padding (if any) to the end of the data
126 // just written.
127 int tail_len;
128 if (!EVP_CipherFinal_ex(ctx.get(), out_ptr + out_len, &tail_len))
129 return false;
130
131 out_len += tail_len;
132 DCHECK_LE(out_len, static_cast<int>(output_size));
133 result.resize(out_len);
134
135 output->swap(result);
136 return true;
137 }
138
139 bool Encryptor::CryptCTR(bool do_encrypt,
140 const base::StringPiece& input,
141 std::string* output) {
142 if (!counter_.get()) {
143 LOG(ERROR) << "Counter value not set in CTR mode.";
144 return false;
145 }
146
147 AES_KEY aes_key;
148 if (AES_set_encrypt_key(reinterpret_cast<const uint8_t*>(key_->key().data()),
149 key_->key().size() * 8, &aes_key) != 0) {
150 return false;
151 }
152
153 const size_t out_size = input.size();
154 CHECK_GT(out_size, 0u);
155 CHECK_GT(out_size + 1, input.size());
156
157 std::string result;
158 uint8_t* out_ptr =
159 reinterpret_cast<uint8_t*>(base::WriteInto(&result, out_size + 1));
160
161 uint8_t ivec[AES_BLOCK_SIZE] = { 0 };
162 uint8_t ecount_buf[AES_BLOCK_SIZE] = { 0 };
163 unsigned int block_offset = 0;
164
165 counter_->Write(ivec);
166
167 AES_ctr128_encrypt(reinterpret_cast<const uint8_t*>(input.data()), out_ptr,
168 input.size(), &aes_key, ivec, ecount_buf, &block_offset);
169
170 // AES_ctr128_encrypt() updates |ivec|. Update the |counter_| here.
171 SetCounter(base::StringPiece(reinterpret_cast<const char*>(ivec),
172 AES_BLOCK_SIZE));
173
174 output->swap(result);
175 return true;
176 }
177
178 } // namespace crypto
OLDNEW
« no previous file with comments | « crypto/encryptor.cc ('k') | crypto/rsa_private_key.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698