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

Side by Side Diff: crypto/encryptor_nss.cc

Issue 7056026: Implement AES-CTR for NSS. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: revised Created 9 years, 6 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 | 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 "crypto/nss_util.h" 11 #include "crypto/nss_util.h"
12 #include "crypto/symmetric_key.h" 12 #include "crypto/symmetric_key.h"
13 13
14 namespace crypto { 14 namespace crypto {
15 15
16 namespace {
17
18 inline CK_MECHANISM_TYPE GetMechanism(Encryptor::Mode mode) {
19 switch (mode) {
20 case Encryptor::CBC:
21 return CKM_AES_CBC_PAD;
22 case Encryptor::CTR:
23 return CKM_AES_ECB;
24 default:
25 NOTREACHED() << "Unsupported mode of operation";
26 break;
27 }
28 return 0;
29 }
30
31 } // namespace
32
16 Encryptor::Encryptor() 33 Encryptor::Encryptor()
17 : key_(NULL), 34 : key_(NULL),
18 mode_(CBC) { 35 mode_(CBC) {
19 EnsureNSSInit(); 36 EnsureNSSInit();
20 } 37 }
21 38
22 Encryptor::~Encryptor() { 39 Encryptor::~Encryptor() {
23 } 40 }
24 41
25 bool Encryptor::Init(SymmetricKey* key, Mode mode, const std::string& iv) { 42 bool Encryptor::Init(SymmetricKey* key, Mode mode, const std::string& iv) {
26 DCHECK(key); 43 DCHECK(key);
27 DCHECK_EQ(CBC, mode); 44 DCHECK(CBC == mode || CTR == mode) << "Unsupported mode of operation";
28 45
29 key_ = key; 46 key_ = key;
30 mode_ = mode; 47 mode_ = mode;
31 48
32 if (iv.size() != AES_BLOCK_SIZE) 49 if (mode == CBC && iv.size() != AES_BLOCK_SIZE)
33 return false; 50 return false;
34 51
35 slot_.reset(PK11_GetBestSlot(CKM_AES_CBC_PAD, NULL)); 52 slot_.reset(PK11_GetBestSlot(GetMechanism(mode), NULL));
36 if (!slot_.get()) 53 if (!slot_.get())
37 return false; 54 return false;
38 55
39 SECItem iv_item; 56 if (mode == CBC) {
40 iv_item.type = siBuffer; 57 SECItem iv_item;
41 iv_item.data = reinterpret_cast<unsigned char*>( 58 iv_item.type = siBuffer;
42 const_cast<char *>(iv.data())); 59 iv_item.data = reinterpret_cast<unsigned char*>(
43 iv_item.len = iv.size(); 60 const_cast<char *>(iv.data()));
61 iv_item.len = iv.size();
44 62
45 param_.reset(PK11_ParamFromIV(CKM_AES_CBC_PAD, &iv_item)); 63 param_.reset(PK11_ParamFromIV(GetMechanism(mode), &iv_item));
64 } else {
65 param_.reset(PK11_ParamFromIV(GetMechanism(mode), NULL));
66 }
67
46 if (!param_.get()) 68 if (!param_.get())
47 return false; 69 return false;
48
49 return true; 70 return true;
50 } 71 }
51 72
52 bool Encryptor::Encrypt(const std::string& plaintext, std::string* ciphertext) { 73 bool Encryptor::Encrypt(const std::string& plaintext, std::string* ciphertext) {
53 ScopedPK11Context context(PK11_CreateContextBySymKey(CKM_AES_CBC_PAD, 74 ScopedPK11Context context(PK11_CreateContextBySymKey(GetMechanism(mode_),
54 CKA_ENCRYPT, 75 CKA_ENCRYPT,
55 key_->key(), 76 key_->key(),
56 param_.get())); 77 param_.get()));
57 if (!context.get()) 78 if (!context.get())
58 return false; 79 return false;
59 80
81 if (mode_ == CTR && !counter_.get()) {
82 LOG(ERROR) << "Counter value not set in CTR mode.";
83 return false;
84 }
85
60 size_t ciphertext_len = plaintext.size() + AES_BLOCK_SIZE; 86 size_t ciphertext_len = plaintext.size() + AES_BLOCK_SIZE;
61 std::vector<unsigned char> buffer(ciphertext_len); 87 std::vector<uint8> buffer(ciphertext_len);
88
89 uint8* plaintext_data =
90 reinterpret_cast<uint8*>(const_cast<char*>(plaintext.data()));
91 int plaintext_len = plaintext.size();
92
93 scoped_array<uint8> ctr_mask;
94 if (mode_ == CTR) {
95 GenerateCounterMask(plaintext_len, &ctr_mask, &plaintext_len);
96 plaintext_data = ctr_mask.get();
97 }
62 98
63 int op_len; 99 int op_len;
64 SECStatus rv = PK11_CipherOp(context.get(), 100 SECStatus rv = PK11_CipherOp(context.get(),
65 &buffer[0], 101 &buffer[0],
66 &op_len, 102 &op_len,
67 ciphertext_len, 103 ciphertext_len,
68 reinterpret_cast<unsigned char*>( 104 plaintext_data,
69 const_cast<char*>(plaintext.data())), 105 plaintext_len);
70 plaintext.size());
71 if (SECSuccess != rv) 106 if (SECSuccess != rv)
72 return false; 107 return false;
73 108
109 if (mode_ == CTR) {
110 ciphertext->resize(plaintext.length());
111
112 // Use |buffer| to mask |plaintext|.
113 MaskMessage(
114 reinterpret_cast<uint8*>(const_cast<char*>(plaintext.data())),
115 plaintext.length(), &buffer[0],
116 reinterpret_cast<uint8*>(const_cast<char*>(ciphertext->data())));
117 return true;
118 }
119
74 unsigned int digest_len; 120 unsigned int digest_len;
75 rv = PK11_DigestFinal(context.get(), 121 rv = PK11_DigestFinal(context.get(),
76 &buffer[op_len], 122 &buffer[op_len],
77 &digest_len, 123 &digest_len,
78 ciphertext_len - op_len); 124 ciphertext_len - op_len);
79 if (SECSuccess != rv) 125 if (SECSuccess != rv)
80 return false; 126 return false;
81 127
82 ciphertext->assign(reinterpret_cast<char *>(&buffer[0]), 128 ciphertext->assign(reinterpret_cast<char *>(&buffer[0]),
83 op_len + digest_len); 129 op_len + digest_len);
84 return true; 130 return true;
85 } 131 }
86 132
87 bool Encryptor::Decrypt(const std::string& ciphertext, std::string* plaintext) { 133 bool Encryptor::Decrypt(const std::string& ciphertext, std::string* plaintext) {
88 if (ciphertext.empty()) 134 if (ciphertext.empty())
89 return false; 135 return false;
90 136
91 ScopedPK11Context context(PK11_CreateContextBySymKey(CKM_AES_CBC_PAD, 137 if (mode_ == CTR && !counter_.get()) {
92 CKA_DECRYPT, 138 LOG(ERROR) << "Count value not set in CTR mode.";
93 key_->key(), 139 return false;
94 param_.get())); 140 }
Ryan Sleevi 2011/06/08 01:29:23 In CTR mode, why not just call Encrypt() with the
Alpha Left Google 2011/06/13 23:32:45 I make Encrypt and Decrypt to share the same code
141
142 ScopedPK11Context context(PK11_CreateContextBySymKey(
143 GetMechanism(mode_), (mode_ == CTR ? CKA_ENCRYPT : CKA_DECRYPT),
144 key_->key(), param_.get()));
95 if (!context.get()) 145 if (!context.get())
96 return false; 146 return false;
97 147
98 size_t plaintext_len = ciphertext.size(); 148 uint8* plaintext_data =
99 std::vector<unsigned char> buffer(plaintext_len); 149 reinterpret_cast<uint8*>(const_cast<char*>(ciphertext.data()));
150 int plaintext_len = ciphertext.size();
Ryan Sleevi 2011/06/08 01:29:23 nit: ciphertext_data, ciphertext_len (also lines 1
Alpha Left Google 2011/06/13 23:32:45 See the new functions, they are just called input
151
152 scoped_array<uint8> ctr_mask;
153 if (mode_ == CTR) {
154 GenerateCounterMask(plaintext_len, &ctr_mask, &plaintext_len);
155 plaintext_data = ctr_mask.get();
156 }
157
158 std::vector<uint8> buffer(plaintext_len);
100 159
101 int op_len; 160 int op_len;
102 SECStatus rv = PK11_CipherOp(context.get(), 161 SECStatus rv = PK11_CipherOp(context.get(),
103 &buffer[0], 162 &buffer[0],
104 &op_len, 163 &op_len,
105 plaintext_len, 164 plaintext_len,
106 reinterpret_cast<unsigned char*>( 165 plaintext_data,
107 const_cast<char*>(ciphertext.data())), 166 plaintext_len);
108 ciphertext.size());
109 if (SECSuccess != rv) 167 if (SECSuccess != rv)
110 return false; 168 return false;
111 169
170 if (mode_ == CTR) {
171 plaintext->resize(ciphertext.length());
172
173 // Use |buffer| to mask |ciphertext|.
174 MaskMessage(
175 reinterpret_cast<uint8*>(const_cast<char*>(ciphertext.data())),
176 ciphertext.length(), &buffer[0],
177 reinterpret_cast<uint8*>(const_cast<char*>(plaintext->data())));
178 return true;
179 }
180
112 unsigned int digest_len; 181 unsigned int digest_len;
113 rv = PK11_DigestFinal(context.get(), 182 rv = PK11_DigestFinal(context.get(),
114 &buffer[op_len], 183 &buffer[op_len],
115 &digest_len, 184 &digest_len,
116 plaintext_len - op_len); 185 plaintext_len - op_len);
117 if (SECSuccess != rv) 186 if (SECSuccess != rv)
118 return false; 187 return false;
119 188
120 plaintext->assign(reinterpret_cast<char *>(&buffer[0]), 189 plaintext->assign(reinterpret_cast<char *>(&buffer[0]),
121 op_len + digest_len); 190 op_len + digest_len);
122 return true; 191 return true;
123 } 192 }
124 193
125 } // namespace crypto 194 } // namespace crypto
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698