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

Side by Side Diff: crypto/encryptor_nss.cc

Issue 8511050: Unify the error checking of crypto::Encryptor and add WARN_UNUSED_RESULT to prevent misuse. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix mac and linux Created 9 years 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 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 "crypto/encryptor.h" 5 #include "crypto/encryptor.h"
6 6
7 #include <cryptohi.h> 7 #include <cryptohi.h>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/string_util.h"
11 #include "crypto/nss_util.h" 12 #include "crypto/nss_util.h"
12 #include "crypto/symmetric_key.h" 13 #include "crypto/symmetric_key.h"
13 14
14 namespace crypto { 15 namespace crypto {
15 16
16 namespace { 17 namespace {
17 18
18 inline CK_MECHANISM_TYPE GetMechanism(Encryptor::Mode mode) { 19 inline CK_MECHANISM_TYPE GetMechanism(Encryptor::Mode mode) {
19 switch (mode) { 20 switch (mode) {
20 case Encryptor::CBC: 21 case Encryptor::CBC:
(...skipping 16 matching lines...) Expand all
37 mode_(CBC) { 38 mode_(CBC) {
38 EnsureNSSInit(); 39 EnsureNSSInit();
39 } 40 }
40 41
41 Encryptor::~Encryptor() { 42 Encryptor::~Encryptor() {
42 } 43 }
43 44
44 bool Encryptor::Init(SymmetricKey* key, 45 bool Encryptor::Init(SymmetricKey* key,
45 Mode mode, 46 Mode mode,
46 const base::StringPiece& iv) { 47 const base::StringPiece& iv) {
47 DCHECK(key); 48 DCHECK(CBC == mode || CTR == mode);
48 DCHECK(CBC == mode || CTR == mode) << "Unsupported mode of operation"; 49 if (!key)
50 return false;
49 51
50 key_ = key; 52 key_ = key;
51 mode_ = mode; 53 mode_ = mode;
52 54
53 if (mode == CBC && iv.size() != AES_BLOCK_SIZE) 55 if (mode == CBC && iv.size() != AES_BLOCK_SIZE)
54 return false; 56 return false;
55 57
56 slot_.reset(PK11_GetBestSlot(GetMechanism(mode), NULL)); 58 slot_.reset(PK11_GetBestSlot(GetMechanism(mode), NULL));
57 if (!slot_.get()) 59 if (!slot_.get())
58 return false; 60 return false;
(...skipping 11 matching lines...) Expand all
70 case CTR: 72 case CTR:
71 param_.reset(PK11_ParamFromIV(GetMechanism(mode), NULL)); 73 param_.reset(PK11_ParamFromIV(GetMechanism(mode), NULL));
72 break; 74 break;
73 } 75 }
74 76
75 return param_ != NULL; 77 return param_ != NULL;
76 } 78 }
77 79
78 bool Encryptor::Encrypt(const base::StringPiece& plaintext, 80 bool Encryptor::Encrypt(const base::StringPiece& plaintext,
79 std::string* ciphertext) { 81 std::string* ciphertext) {
80 CHECK(!plaintext.empty() || (mode_ == CBC)); 82 if (plaintext.empty() && mode_ != CBC) {
83 ciphertext->clear();
wtc 2011/12/15 02:03:58 The clear() calls before returning false can all b
84 return false;
85 }
86
81 ScopedPK11Context context(PK11_CreateContextBySymKey(GetMechanism(mode_), 87 ScopedPK11Context context(PK11_CreateContextBySymKey(GetMechanism(mode_),
82 CKA_ENCRYPT, 88 CKA_ENCRYPT,
83 key_->key(), 89 key_->key(),
84 param_.get())); 90 param_.get()));
85 if (!context.get()) 91 if (!context.get()) {
92 ciphertext->clear();
86 return false; 93 return false;
94 }
87 95
88 return (mode_ == CTR) ? 96 return (mode_ == CTR) ?
89 CryptCTR(context.get(), plaintext, ciphertext) : 97 CryptCTR(context.get(), plaintext, ciphertext) :
90 Crypt(context.get(), plaintext, ciphertext); 98 Crypt(context.get(), plaintext, ciphertext);
91 } 99 }
92 100
93 bool Encryptor::Decrypt(const base::StringPiece& ciphertext, 101 bool Encryptor::Decrypt(const base::StringPiece& ciphertext,
94 std::string* plaintext) { 102 std::string* plaintext) {
95 CHECK(!ciphertext.empty()); 103 if (ciphertext.empty()) {
104 plaintext->clear();
105 return false;
106 }
107
96 ScopedPK11Context context(PK11_CreateContextBySymKey( 108 ScopedPK11Context context(PK11_CreateContextBySymKey(
97 GetMechanism(mode_), (mode_ == CTR ? CKA_ENCRYPT : CKA_DECRYPT), 109 GetMechanism(mode_), (mode_ == CTR ? CKA_ENCRYPT : CKA_DECRYPT),
98 key_->key(), param_.get())); 110 key_->key(), param_.get()));
99 if (!context.get()) 111 if (!context.get()) {
112 plaintext->clear();
100 return false; 113 return false;
114 }
101 115
102 return (mode_ == CTR) ? 116 return (mode_ == CTR) ?
103 CryptCTR(context.get(), ciphertext, plaintext) : 117 CryptCTR(context.get(), ciphertext, plaintext) :
104 Crypt(context.get(), ciphertext, plaintext); 118 Crypt(context.get(), ciphertext, plaintext);
105 } 119 }
106 120
107 bool Encryptor::Crypt(PK11Context* context, 121 bool Encryptor::Crypt(PK11Context* context,
108 const base::StringPiece& input, 122 const base::StringPiece& input,
109 std::string* output) { 123 std::string* output) {
124 std::string result;
125 output->swap(result);
126
110 size_t output_len = input.size() + AES_BLOCK_SIZE; 127 size_t output_len = input.size() + AES_BLOCK_SIZE;
111 CHECK_GT(output_len, input.size()); 128 if (output_len == 0 || output_len < input.size() ||
112 129 output_len + 1 < input.size()) {
113 output->resize(output_len); 130 return false; // size_t overflow.
114 uint8* output_data = 131 }
115 reinterpret_cast<uint8*>(const_cast<char*>(output->data()));
116 132
117 int input_len = input.size(); 133 int input_len = input.size();
118 uint8* input_data = 134 uint8* input_data =
119 reinterpret_cast<uint8*>(const_cast<char*>(input.data())); 135 reinterpret_cast<uint8*>(const_cast<char*>(input.data()));
136 uint8* result_data =
137 reinterpret_cast<uint8*>(WriteInto(&result, output_len + 1));
120 138
121 int op_len; 139 int op_len;
122 SECStatus rv = PK11_CipherOp(context, 140 SECStatus rv = PK11_CipherOp(context, result_data, &op_len, output_len,
123 output_data, 141 input_data, input_len);
124 &op_len, 142 if (SECSuccess != rv)
125 output_len,
126 input_data,
127 input_len);
128
129 if (SECSuccess != rv) {
130 output->clear();
131 return false; 143 return false;
132 }
133 144
134 unsigned int digest_len; 145 unsigned int digest_len;
135 rv = PK11_DigestFinal(context, 146 rv = PK11_DigestFinal(context, result_data + op_len, &digest_len,
136 output_data + op_len,
137 &digest_len,
138 output_len - op_len); 147 output_len - op_len);
139 if (SECSuccess != rv) { 148 if (SECSuccess != rv)
140 output->clear();
141 return false; 149 return false;
142 }
143 150
144 output->resize(op_len + digest_len); 151 result.resize(op_len + digest_len);
152 output->swap(result);
145 return true; 153 return true;
146 } 154 }
147 155
148 bool Encryptor::CryptCTR(PK11Context* context, 156 bool Encryptor::CryptCTR(PK11Context* context,
149 const base::StringPiece& input, 157 const base::StringPiece& input,
150 std::string* output) { 158 std::string* output) {
159 // Work on the result in a local variable, and then only transfer it to
160 // |output| on success to ensure no partial data is returned.
161 std::string result;
162 output->swap(result);
163
151 if (!counter_.get()) { 164 if (!counter_.get()) {
152 LOG(ERROR) << "Counter value not set in CTR mode."; 165 LOG(ERROR) << "Counter value not set in CTR mode.";
153 return false; 166 return false;
154 } 167 }
155 168
156 size_t output_len = ((input.size() + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE) * 169 size_t output_len = ((input.size() + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE) *
157 AES_BLOCK_SIZE; 170 AES_BLOCK_SIZE;
158 CHECK_GE(output_len, input.size()); 171 if (output_len == 0 || output_len < input.size() ||
159 output->resize(output_len); 172 output_len + 1 < input.size()) {
160 uint8* output_data = 173 return false; // size_t overflow.
161 reinterpret_cast<uint8*>(const_cast<char*>(output->data())); 174 }
175
176 uint8* result_data =
177 reinterpret_cast<uint8*>(WriteInto(&result, output_len + 1));
162 178
163 size_t mask_len; 179 size_t mask_len;
164 bool ret = GenerateCounterMask(input.size(), output_data, &mask_len); 180 bool ret = GenerateCounterMask(input.size(), result_data, &mask_len);
165 if (!ret) 181 if (!ret)
166 return false; 182 return false;
167 183
168 CHECK_EQ(mask_len, output_len); 184 CHECK_EQ(mask_len, output_len);
169 int op_len; 185 int op_len;
170 SECStatus rv = PK11_CipherOp(context, 186 SECStatus rv = PK11_CipherOp(context, result_data, &op_len, output_len,
171 output_data, 187 result_data, mask_len);
172 &op_len,
173 output_len,
174 output_data,
175 mask_len);
176 if (SECSuccess != rv) 188 if (SECSuccess != rv)
177 return false; 189 return false;
178 CHECK_EQ(static_cast<int>(mask_len), op_len); 190 CHECK_EQ(static_cast<int>(mask_len), op_len);
179 191
180 unsigned int digest_len; 192 unsigned int digest_len;
181 rv = PK11_DigestFinal(context, 193 rv = PK11_DigestFinal(context, NULL, &digest_len, 0);
182 NULL,
183 &digest_len,
184 0);
185 if (SECSuccess != rv) 194 if (SECSuccess != rv)
186 return false; 195 return false;
187 CHECK(!digest_len); 196 CHECK(!digest_len);
188 197
189 // Use |output_data| to mask |input|. 198 // Use |result_data| to mask |input|.
190 MaskMessage( 199 MaskMessage(reinterpret_cast<uint8*>(const_cast<char*>(input.data())),
191 reinterpret_cast<uint8*>(const_cast<char*>(input.data())), 200 input.size(), result_data, result_data);
192 input.length(), output_data, output_data); 201 result.resize(input.size());
193 output->resize(input.length()); 202 output->swap(result);
194 return true; 203 return true;
195 } 204 }
196 205
197 } // namespace crypto 206 } // namespace crypto
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698