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

Side by Side Diff: content/renderer/webcrypto/webcrypto_impl_nss.cc

Issue 24656002: [webcrypto] Add decrypt() for AES-CBC. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: reword "non-block-aligned" to "not a multiple of block size" Created 7 years, 2 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "content/renderer/webcrypto/webcrypto_impl.h" 5 #include "content/renderer/webcrypto/webcrypto_impl.h"
6 6
7 #include <cryptohi.h> 7 #include <cryptohi.h>
8 #include <pk11pub.h> 8 #include <pk11pub.h>
9 #include <sechash.h> 9 #include <sechash.h>
10 10
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 if (new_size == buffer->byteLength()) 77 if (new_size == buffer->byteLength())
78 return; 78 return;
79 79
80 WebKit::WebArrayBuffer new_buffer = 80 WebKit::WebArrayBuffer new_buffer =
81 WebKit::WebArrayBuffer::create(new_size, 1); 81 WebKit::WebArrayBuffer::create(new_size, 1);
82 DCHECK(!new_buffer.isNull()); 82 DCHECK(!new_buffer.isNull());
83 memcpy(new_buffer.data(), buffer->data(), new_size); 83 memcpy(new_buffer.data(), buffer->data(), new_size);
84 *buffer = new_buffer; 84 *buffer = new_buffer;
85 } 85 }
86 86
87 } // namespace 87 bool AesCbcEncryptDecrypt(
88 88 CK_ATTRIBUTE_TYPE operation,
89 void WebCryptoImpl::Init() {
90 crypto::EnsureNSSInit();
91 }
92
93 bool WebCryptoImpl::EncryptInternal(
94 const WebKit::WebCryptoAlgorithm& algorithm, 89 const WebKit::WebCryptoAlgorithm& algorithm,
95 const WebKit::WebCryptoKey& key, 90 const WebKit::WebCryptoKey& key,
96 const unsigned char* data, 91 const unsigned char* data,
97 unsigned data_size, 92 unsigned data_size,
98 WebKit::WebArrayBuffer* buffer) { 93 WebKit::WebArrayBuffer* buffer) {
99 if (algorithm.id() != WebKit::WebCryptoAlgorithmIdAesCbc) 94 DCHECK_EQ(WebKit::WebCryptoAlgorithmIdAesCbc, algorithm.id());
100 return false;
101
102 DCHECK_EQ(algorithm.id(), key.algorithm().id()); 95 DCHECK_EQ(algorithm.id(), key.algorithm().id());
103 DCHECK_EQ(WebKit::WebCryptoKeyTypeSecret, key.type()); 96 DCHECK_EQ(WebKit::WebCryptoKeyTypeSecret, key.type());
97 DCHECK(operation == CKA_ENCRYPT || operation == CKA_DECRYPT);
104 98
105 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); 99 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle());
106 100
107 const WebKit::WebCryptoAesCbcParams* params = algorithm.aesCbcParams(); 101 const WebKit::WebCryptoAesCbcParams* params = algorithm.aesCbcParams();
108 if (params->iv().size() != AES_BLOCK_SIZE) 102 if (params->iv().size() != AES_BLOCK_SIZE)
109 return false; 103 return false;
110 104
111 SECItem iv_item; 105 SECItem iv_item;
112 iv_item.type = siBuffer; 106 iv_item.type = siBuffer;
113 iv_item.data = const_cast<unsigned char*>(params->iv().data()); 107 iv_item.data = const_cast<unsigned char*>(params->iv().data());
114 iv_item.len = params->iv().size(); 108 iv_item.len = params->iv().size();
115 109
116 crypto::ScopedSECItem param(PK11_ParamFromIV(CKM_AES_CBC_PAD, &iv_item)); 110 crypto::ScopedSECItem param(PK11_ParamFromIV(CKM_AES_CBC_PAD, &iv_item));
117 if (!param) 111 if (!param)
118 return false; 112 return false;
119 113
120 crypto::ScopedPK11Context context(PK11_CreateContextBySymKey( 114 crypto::ScopedPK11Context context(PK11_CreateContextBySymKey(
121 CKM_AES_CBC_PAD, CKA_ENCRYPT, sym_key->key(), param.get())); 115 CKM_AES_CBC_PAD, operation, sym_key->key(), param.get()));
122 116
123 if (!context.get()) 117 if (!context.get())
124 return false; 118 return false;
125 119
126 // Oddly PK11_CipherOp takes input and output lenths as "int" rather than 120 // Oddly PK11_CipherOp takes input and output lenths as "int" rather than
127 // "unsigned". Do some checks now to avoid integer overflowing. 121 // "unsigned". Do some checks now to avoid integer overflowing.
128 if (data_size >= INT_MAX - AES_BLOCK_SIZE) { 122 if (data_size >= INT_MAX - AES_BLOCK_SIZE) {
129 // TODO(eroman): Handle this by chunking the input fed into NSS. Right now 123 // TODO(eroman): Handle this by chunking the input fed into NSS. Right now
130 // it doesn't make much difference since the one-shot API would end up 124 // it doesn't make much difference since the one-shot API would end up
131 // blowing out the memory and crashing anyway. However a newer version of 125 // blowing out the memory and crashing anyway. However a newer version of
132 // the spec allows for a sequence<CryptoData> so this will be relevant. 126 // the spec allows for a sequence<CryptoData> so this will be relevant.
133 return false; 127 return false;
134 } 128 }
135 129
130 // PK11_CipherOp does an invalid memory access when given empty decryption
131 // input, or input which is not a multiple of the block size. See also
132 // https://bugzilla.mozilla.com/show_bug.cgi?id=921687.
133 if (operation == CKA_DECRYPT &&
134 (data_size == 0 || (data_size % AES_BLOCK_SIZE != 0))) {
135 return false;
136 }
137
138 // TODO(eroman): Refine the output buffer size. It can be computed exactly for
139 // encryption, and can be smaller for decryption.
136 unsigned output_max_len = data_size + AES_BLOCK_SIZE; 140 unsigned output_max_len = data_size + AES_BLOCK_SIZE;
137 CHECK_GT(output_max_len, data_size); 141 CHECK_GT(output_max_len, data_size);
138 142
139 *buffer = WebKit::WebArrayBuffer::create(output_max_len, 1); 143 *buffer = WebKit::WebArrayBuffer::create(output_max_len, 1);
140 144
141 unsigned char* buffer_data = reinterpret_cast<unsigned char*>(buffer->data()); 145 unsigned char* buffer_data = reinterpret_cast<unsigned char*>(buffer->data());
142 146
143 int output_len; 147 int output_len;
144 if (SECSuccess != PK11_CipherOp(context.get(), 148 if (SECSuccess != PK11_CipherOp(context.get(),
145 buffer_data, 149 buffer_data,
146 &output_len, 150 &output_len,
147 buffer->byteLength(), 151 buffer->byteLength(),
148 data, 152 data,
149 data_size)) { 153 data_size)) {
150 return false; 154 return false;
151 } 155 }
152 156
153 unsigned int final_output_chunk_len; 157 unsigned int final_output_chunk_len;
154 if (SECSuccess != PK11_DigestFinal(context.get(), 158 if (SECSuccess != PK11_DigestFinal(context.get(),
155 buffer_data + output_len, 159 buffer_data + output_len,
156 &final_output_chunk_len, 160 &final_output_chunk_len,
157 output_max_len - output_len)) { 161 output_max_len - output_len)) {
158 return false; 162 return false;
159 } 163 }
160 164
161 ShrinkBuffer(buffer, final_output_chunk_len + output_len); 165 ShrinkBuffer(buffer, final_output_chunk_len + output_len);
162 return true; 166 return true;
163 } 167 }
164 168
169 } // namespace
170
171 void WebCryptoImpl::Init() {
172 crypto::EnsureNSSInit();
173 }
174
175 bool WebCryptoImpl::EncryptInternal(
176 const WebKit::WebCryptoAlgorithm& algorithm,
177 const WebKit::WebCryptoKey& key,
178 const unsigned char* data,
179 unsigned data_size,
180 WebKit::WebArrayBuffer* buffer) {
181 if (algorithm.id() == WebKit::WebCryptoAlgorithmIdAesCbc) {
182 return AesCbcEncryptDecrypt(
183 CKA_ENCRYPT, algorithm, key, data, data_size, buffer);
184 }
185
186 return false;
187 }
188
189 bool WebCryptoImpl::DecryptInternal(
190 const WebKit::WebCryptoAlgorithm& algorithm,
191 const WebKit::WebCryptoKey& key,
192 const unsigned char* data,
193 unsigned data_size,
194 WebKit::WebArrayBuffer* buffer) {
195 if (algorithm.id() == WebKit::WebCryptoAlgorithmIdAesCbc) {
196 return AesCbcEncryptDecrypt(
197 CKA_DECRYPT, algorithm, key, data, data_size, buffer);
198 }
199
200 return false;
201 }
202
165 bool WebCryptoImpl::DigestInternal( 203 bool WebCryptoImpl::DigestInternal(
166 const WebKit::WebCryptoAlgorithm& algorithm, 204 const WebKit::WebCryptoAlgorithm& algorithm,
167 const unsigned char* data, 205 const unsigned char* data,
168 unsigned data_size, 206 unsigned data_size,
169 WebKit::WebArrayBuffer* buffer) { 207 WebKit::WebArrayBuffer* buffer) {
170 HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm); 208 HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm);
171 if (hash_type == HASH_AlgNULL) { 209 if (hash_type == HASH_AlgNULL) {
172 return false; 210 return false;
173 } 211 }
174 212
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 break; 409 break;
372 } 410 }
373 default: 411 default:
374 return false; 412 return false;
375 } 413 }
376 414
377 return true; 415 return true;
378 } 416 }
379 417
380 } // namespace content 418 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/webcrypto/webcrypto_impl.cc ('k') | content/renderer/webcrypto/webcrypto_impl_openssl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698