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

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: Created 9 years, 1 month 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"
(...skipping 26 matching lines...) Expand all
37 mode_(CBC) { 37 mode_(CBC) {
38 EnsureNSSInit(); 38 EnsureNSSInit();
39 } 39 }
40 40
41 Encryptor::~Encryptor() { 41 Encryptor::~Encryptor() {
42 } 42 }
43 43
44 bool Encryptor::Init(SymmetricKey* key, 44 bool Encryptor::Init(SymmetricKey* key,
45 Mode mode, 45 Mode mode,
46 const base::StringPiece& iv) { 46 const base::StringPiece& iv) {
47 DCHECK(key); 47 if (!key || !(mode == CBC || mode == CTR))
48 DCHECK(CBC == mode || CTR == mode) << "Unsupported mode of operation"; 48 return false;
49 49
50 key_ = key; 50 key_ = key;
51 mode_ = mode; 51 mode_ = mode;
52 52
53 if (mode == CBC && iv.size() != AES_BLOCK_SIZE) 53 if (mode == CBC && iv.size() != AES_BLOCK_SIZE)
54 return false; 54 return false;
55 55
56 slot_.reset(PK11_GetBestSlot(GetMechanism(mode), NULL)); 56 slot_.reset(PK11_GetBestSlot(GetMechanism(mode), NULL));
57 if (!slot_.get()) 57 if (!slot_.get())
58 return false; 58 return false;
59 59
60 switch (mode) { 60 switch (mode) {
61 case CBC: 61 case CBC:
62 SECItem iv_item; 62 SECItem iv_item;
63 iv_item.type = siBuffer; 63 iv_item.type = siBuffer;
64 iv_item.data = reinterpret_cast<unsigned char*>( 64 iv_item.data = reinterpret_cast<unsigned char*>(
65 const_cast<char *>(iv.data())); 65 const_cast<char *>(iv.data()));
66 iv_item.len = iv.size(); 66 iv_item.len = iv.size();
67 67
68 param_.reset(PK11_ParamFromIV(GetMechanism(mode), &iv_item)); 68 param_.reset(PK11_ParamFromIV(GetMechanism(mode), &iv_item));
69 break; 69 break;
70 case CTR: 70 case CTR:
71 param_.reset(PK11_ParamFromIV(GetMechanism(mode), NULL)); 71 param_.reset(PK11_ParamFromIV(GetMechanism(mode), NULL));
72 break; 72 break;
73 } 73 }
74 74
75 if (!param_.get()) 75 return param_ != NULL;
76 return false;
77 return true;
78 } 76 }
79 77
80 bool Encryptor::Encrypt(const base::StringPiece& plaintext, 78 bool Encryptor::Encrypt(const base::StringPiece& plaintext,
81 std::string* ciphertext) { 79 std::string* ciphertext) {
82 ScopedPK11Context context(PK11_CreateContextBySymKey(GetMechanism(mode_), 80 ciphertext->clear();
83 CKA_ENCRYPT, 81 if (plaintext.empty() && mode_ != CBC)
84 key_->key(), 82 return false;
85 param_.get())); 83
84 ScopedPK11Context context(
85 PK11_CreateContextBySymKey(GetMechanism(mode_), CKA_ENCRYPT,
86 key_->key(), param_.get()));
86 if (!context.get()) 87 if (!context.get())
87 return false; 88 return false;
88 89
89 if (mode_ == CTR) 90 return (mode_ == CTR) ?
90 return CryptCTR(context.get(), plaintext, ciphertext); 91 CryptCTR(context.get(), plaintext, ciphertext) :
91 else 92 Crypt(context.get(), plaintext, ciphertext);
92 return Crypt(context.get(), plaintext, ciphertext);
93 } 93 }
94 94
95 bool Encryptor::Decrypt(const base::StringPiece& ciphertext, 95 bool Encryptor::Decrypt(const base::StringPiece& ciphertext,
96 std::string* plaintext) { 96 std::string* plaintext) {
97 plaintext->clear();
97 if (ciphertext.empty()) 98 if (ciphertext.empty())
98 return false; 99 return false;
99 100
100 ScopedPK11Context context(PK11_CreateContextBySymKey( 101 ScopedPK11Context context(PK11_CreateContextBySymKey(
101 GetMechanism(mode_), (mode_ == CTR ? CKA_ENCRYPT : CKA_DECRYPT), 102 GetMechanism(mode_), (mode_ == CTR ? CKA_ENCRYPT : CKA_DECRYPT),
102 key_->key(), param_.get())); 103 key_->key(), param_.get()));
103 if (!context.get()) 104 if (!context.get())
104 return false; 105 return false;
105 106
106 if (mode_ == CTR) 107 return (mode_ == CTR) ?
107 return CryptCTR(context.get(), ciphertext, plaintext); 108 CryptCTR(context.get(), ciphertext, plaintext) :
108 else 109 Crypt(context.get(), ciphertext, plaintext);
109 return Crypt(context.get(), ciphertext, plaintext);
110 } 110 }
111 111
112 bool Encryptor::Crypt(PK11Context* context, 112 bool Encryptor::Crypt(PK11Context* context,
113 const base::StringPiece& input, 113 const base::StringPiece& input,
114 std::string* output) { 114 std::string* output) {
115 size_t output_len = input.size() + AES_BLOCK_SIZE; 115 size_t output_len = input.size() + AES_BLOCK_SIZE;
116 CHECK(output_len > input.size()) << "Output size overflow"; 116 if (output_len < input.size())
117 return false; // Size overflow.
wtc 2011/11/15 02:33:58 Nit: Size => size_t
117 118
118 output->resize(output_len); 119 std::string result;
119 uint8* output_data = 120 result.resize(output_len);
wtc 2011/11/15 02:33:58 Is there a constructor that takes the size input?
120 reinterpret_cast<uint8*>(const_cast<char*>(output->data())); 121 uint8* result_data =
122 reinterpret_cast<uint8*>(const_cast<char*>(result.data()));
121 123
122 int input_len = input.size(); 124 int input_len = input.size();
123 uint8* input_data = 125 uint8* input_data =
124 reinterpret_cast<uint8*>(const_cast<char*>(input.data())); 126 reinterpret_cast<uint8*>(const_cast<char*>(input.data()));
125 127
126 int op_len; 128 int op_len;
127 SECStatus rv = PK11_CipherOp(context, 129 SECStatus rv = PK11_CipherOp(context, result_data, &op_len, output_len,
128 output_data, 130 input_data, input_len);
129 &op_len, 131 if (SECSuccess != rv)
130 output_len,
131 input_data,
132 input_len);
133
134 if (SECSuccess != rv) {
135 output->clear();
136 return false; 132 return false;
137 }
138 133
139 unsigned int digest_len; 134 unsigned int digest_len;
140 rv = PK11_DigestFinal(context, 135 rv = PK11_DigestFinal(context, result_data + op_len, &digest_len,
141 output_data + op_len,
142 &digest_len,
143 output_len - op_len); 136 output_len - op_len);
144 if (SECSuccess != rv) { 137 if (SECSuccess != rv)
145 output->clear();
146 return false; 138 return false;
147 }
148 139
149 output->resize(op_len + digest_len); 140 result.resize(op_len + digest_len);
141 output->swap(result);
150 return true; 142 return true;
151 } 143 }
152 144
153 bool Encryptor::CryptCTR(PK11Context* context, 145 bool Encryptor::CryptCTR(PK11Context* context,
154 const base::StringPiece& input, 146 const base::StringPiece& input,
155 std::string* output) { 147 std::string* output) {
156 if (!counter_.get()) { 148 if (!counter_.get()) {
157 LOG(ERROR) << "Counter value not set in CTR mode."; 149 LOG(ERROR) << "Counter value not set in CTR mode.";
158 return false; 150 return false;
159 } 151 }
160 152
161 size_t output_len = ((input.size() + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE) * 153 size_t output_len = ((input.size() + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE) *
162 AES_BLOCK_SIZE; 154 AES_BLOCK_SIZE;
163 CHECK(output_len >= input.size()) << "Output size overflow"; 155 if (output_len < input.size())
164 output->resize(output_len); 156 return false; // Size overflow.
165 uint8* output_data = 157
166 reinterpret_cast<uint8*>(const_cast<char*>(output->data())); 158 // Work on the result in a local variable, and then only transfer it to
159 // |output| on success to ensure no partial data is returned.
160 std::string result;
161 result.resize(output_len);
162 uint8* result_data =
163 reinterpret_cast<uint8*>(const_cast<char*>(result.data()));
167 164
168 size_t mask_len; 165 size_t mask_len;
169 bool ret = GenerateCounterMask(input.size(), output_data, &mask_len); 166 bool ret = GenerateCounterMask(input.size(), result_data, &mask_len);
170 if (!ret) 167 if (!ret)
171 return false; 168 return false;
172 169
173 CHECK_EQ(mask_len, output_len); 170 CHECK_EQ(mask_len, output_len);
174 int op_len; 171 int op_len;
175 SECStatus rv = PK11_CipherOp(context, 172 SECStatus rv = PK11_CipherOp(context, result_data, &op_len, output_len,
176 output_data, 173 result_data, mask_len);
177 &op_len, 174 if (SECSuccess != rv || op_len != static_cast<int>(mask_len))
178 output_len,
179 output_data,
180 mask_len);
181 if (SECSuccess != rv)
182 return false; 175 return false;
183 CHECK(op_len == static_cast<int>(mask_len));
184 176
185 unsigned int digest_len; 177 unsigned int digest_len;
186 rv = PK11_DigestFinal(context, 178 rv = PK11_DigestFinal(context, NULL, &digest_len, 0);
187 NULL, 179 if (SECSuccess != rv || digest_len)
188 &digest_len,
189 0);
190 if (SECSuccess != rv)
191 return false; 180 return false;
192 CHECK(!digest_len);
wtc 2011/11/15 02:33:58 IMPORTANT: Some of these CHECKs should not be conv
193 181
194 // Use |output_data| to mask |input|. 182 // Use |result_data| to mask |input|.
195 MaskMessage( 183 MaskMessage(reinterpret_cast<uint8*>(const_cast<char*>(input.data())),
196 reinterpret_cast<uint8*>(const_cast<char*>(input.data())), 184 input.size(), result_data, result_data);
197 input.length(), output_data, output_data); 185 result.resize(input.size());
198 output->resize(input.length()); 186 output->swap(result);
199 return true; 187 return true;
200 } 188 }
201 189
202 } // namespace crypto 190 } // namespace crypto
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698