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

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

Issue 24656002: [webcrypto] Add decrypt() for AES-CBC. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: 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_impl.h" 5 #include "content/renderer/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 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 if (new_size == buffer->byteLength()) 74 if (new_size == buffer->byteLength())
75 return; 75 return;
76 76
77 WebKit::WebArrayBuffer new_buffer = 77 WebKit::WebArrayBuffer new_buffer =
78 WebKit::WebArrayBuffer::create(new_size, 1); 78 WebKit::WebArrayBuffer::create(new_size, 1);
79 CHECK(!new_buffer.isNull()); 79 CHECK(!new_buffer.isNull());
80 memcpy(new_buffer.data(), buffer->data(), new_size); 80 memcpy(new_buffer.data(), buffer->data(), new_size);
81 *buffer = new_buffer; 81 *buffer = new_buffer;
82 } 82 }
83 83
84 } // namespace 84 bool AesCbcEncryptDecrypt(
85 85 CK_ATTRIBUTE_TYPE operation,
86 void WebCryptoImpl::Init() {
87 crypto::EnsureNSSInit();
88 }
89
90 bool WebCryptoImpl::EncryptInternal(
91 const WebKit::WebCryptoAlgorithm& algorithm, 86 const WebKit::WebCryptoAlgorithm& algorithm,
92 const WebKit::WebCryptoKey& key, 87 const WebKit::WebCryptoKey& key,
93 const unsigned char* data, 88 const unsigned char* data,
94 unsigned data_size, 89 unsigned data_size,
95 WebKit::WebArrayBuffer* buffer) { 90 WebKit::WebArrayBuffer* buffer) {
96 if (algorithm.id() != WebKit::WebCryptoAlgorithmIdAesCbc) 91 DCHECK_EQ(WebKit::WebCryptoAlgorithmIdAesCbc, algorithm.id());
97 return false;
98
99 CHECK_EQ(algorithm.id(), key.algorithm().id()); 92 CHECK_EQ(algorithm.id(), key.algorithm().id());
100 CHECK_EQ(WebKit::WebCryptoKeyTypeSecret, key.type()); 93 CHECK_EQ(WebKit::WebCryptoKeyTypeSecret, key.type());
94 CHECK(operation == CKA_ENCRYPT || operation == CKA_DECRYPT);
jamesr 2013/09/25 21:29:05 why are these hard CHECKs?
eroman 2013/09/25 22:11:59 Changed to DCHECK()
101 95
102 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); 96 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle());
103 97
104 const WebKit::WebCryptoAesCbcParams* params = algorithm.aesCbcParams(); 98 const WebKit::WebCryptoAesCbcParams* params = algorithm.aesCbcParams();
105 if (params->iv().size() != AES_BLOCK_SIZE) 99 if (params->iv().size() != AES_BLOCK_SIZE)
106 return false; 100 return false;
107 101
108 SECItem iv_item; 102 SECItem iv_item;
109 iv_item.type = siBuffer; 103 iv_item.type = siBuffer;
110 iv_item.data = const_cast<unsigned char*>(params->iv().data()); 104 iv_item.data = const_cast<unsigned char*>(params->iv().data());
111 iv_item.len = params->iv().size(); 105 iv_item.len = params->iv().size();
112 106
113 crypto::ScopedSECItem param(PK11_ParamFromIV(CKM_AES_CBC_PAD, &iv_item)); 107 crypto::ScopedSECItem param(PK11_ParamFromIV(CKM_AES_CBC_PAD, &iv_item));
114 if (!param) 108 if (!param)
115 return false; 109 return false;
116 110
117 crypto::ScopedPK11Context context(PK11_CreateContextBySymKey( 111 crypto::ScopedPK11Context context(PK11_CreateContextBySymKey(
118 CKM_AES_CBC_PAD, CKA_ENCRYPT, sym_key->key(), param.get())); 112 CKM_AES_CBC_PAD, operation, sym_key->key(), param.get()));
119 113
120 if (!context.get()) 114 if (!context.get())
121 return false; 115 return false;
122 116
123 // Oddly PK11_CipherOp takes input and output lenths as "int" rather than 117 // Oddly PK11_CipherOp takes input and output lenths as "int" rather than
124 // "unsigned". Do some checks now to avoid integer overflowing. 118 // "unsigned". Do some checks now to avoid integer overflowing.
125 if (data_size >= INT_MAX - AES_BLOCK_SIZE) { 119 if (data_size >= INT_MAX - AES_BLOCK_SIZE) {
126 // TODO(eroman): Handle this by chunking the input fed into NSS. Right now 120 // TODO(eroman): Handle this by chunking the input fed into NSS. Right now
127 // it doesn't make much difference since the one-shot API would end up 121 // it doesn't make much difference since the one-shot API would end up
128 // blowing out the memory and crashing anyway. However a newer version of 122 // blowing out the memory and crashing anyway. However a newer version of
129 // the spec allows for a sequence<CryptoData> so this will be relevant. 123 // the spec allows for a sequence<CryptoData> so this will be relevant.
130 return false; 124 return false;
131 } 125 }
132 126
127 // TODO(eroman): Refine the output buffer size. It can be computed exactly for
128 // encryption, and can be smaller for decryption.
133 unsigned output_max_len = data_size + AES_BLOCK_SIZE; 129 unsigned output_max_len = data_size + AES_BLOCK_SIZE;
134 CHECK_GT(output_max_len, data_size); 130 CHECK_GT(output_max_len, data_size);
135 131
136 *buffer = WebKit::WebArrayBuffer::create(output_max_len, 1); 132 *buffer = WebKit::WebArrayBuffer::create(output_max_len, 1);
137 133
138 unsigned char* buffer_data = reinterpret_cast<unsigned char*>(buffer->data()); 134 unsigned char* buffer_data = reinterpret_cast<unsigned char*>(buffer->data());
139 135
140 int output_len; 136 int output_len;
141 if (SECSuccess != PK11_CipherOp(context.get(), 137 if (SECSuccess != PK11_CipherOp(context.get(),
142 buffer_data, 138 buffer_data,
143 &output_len, 139 &output_len,
144 buffer->byteLength(), 140 buffer->byteLength(),
145 data, 141 data,
146 data_size)) { 142 data_size)) {
147 return false; 143 return false;
148 } 144 }
149 145
150 unsigned int final_output_chunk_len; 146 unsigned int final_output_chunk_len;
151 if (SECSuccess != PK11_DigestFinal(context.get(), 147 if (SECSuccess != PK11_DigestFinal(context.get(),
152 buffer_data + output_len, 148 buffer_data + output_len,
153 &final_output_chunk_len, 149 &final_output_chunk_len,
154 output_max_len - output_len)) { 150 output_max_len - output_len)) {
155 return false; 151 return false;
156 } 152 }
157 153
158 ShrinkBuffer(buffer, final_output_chunk_len + output_len); 154 ShrinkBuffer(buffer, final_output_chunk_len + output_len);
159 return true; 155 return true;
160 } 156 }
161 157
158 } // namespace
159
160 void WebCryptoImpl::Init() {
161 crypto::EnsureNSSInit();
162 }
163
164 bool WebCryptoImpl::EncryptInternal(
165 const WebKit::WebCryptoAlgorithm& algorithm,
166 const WebKit::WebCryptoKey& key,
167 const unsigned char* data,
168 unsigned data_size,
169 WebKit::WebArrayBuffer* buffer) {
170 if (algorithm.id() == WebKit::WebCryptoAlgorithmIdAesCbc) {
171 return AesCbcEncryptDecrypt(
172 CKA_ENCRYPT, algorithm, key, data, data_size, buffer);
173 }
174
175 return false;
176 }
177
178 bool WebCryptoImpl::DecryptInternal(
179 const WebKit::WebCryptoAlgorithm& algorithm,
180 const WebKit::WebCryptoKey& key,
181 const unsigned char* data,
182 unsigned data_size,
183 WebKit::WebArrayBuffer* buffer) {
184 if (algorithm.id() == WebKit::WebCryptoAlgorithmIdAesCbc) {
185 return AesCbcEncryptDecrypt(
186 CKA_DECRYPT, algorithm, key, data, data_size, buffer);
187 }
188
189 return false;
190 }
191
162 bool WebCryptoImpl::DigestInternal( 192 bool WebCryptoImpl::DigestInternal(
163 const WebKit::WebCryptoAlgorithm& algorithm, 193 const WebKit::WebCryptoAlgorithm& algorithm,
164 const unsigned char* data, 194 const unsigned char* data,
165 unsigned data_size, 195 unsigned data_size,
166 WebKit::WebArrayBuffer* buffer) { 196 WebKit::WebArrayBuffer* buffer) {
167 HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm); 197 HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm);
168 if (hash_type == HASH_AlgNULL) { 198 if (hash_type == HASH_AlgNULL) {
169 return false; 199 return false;
170 } 200 }
171 201
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 } 367 }
338 default: 368 default:
339 return false; 369 return false;
340 } 370 }
341 371
342 *buffer = result; 372 *buffer = result;
343 return true; 373 return true;
344 } 374 }
345 375
346 } // namespace content 376 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698