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

Side by Side Diff: Source/modules/crypto/SubtleCrypto.cpp

Issue 23164012: WebCrypto: Remove support for multi-part operations. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years, 4 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 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 13 matching lines...) Expand all
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31 #include "config.h" 31 #include "config.h"
32 #include "modules/crypto/SubtleCrypto.h" 32 #include "modules/crypto/SubtleCrypto.h"
33 33
34 #include "V8Key.h" // NOTE: This must appear before ScriptPromiseResolver to def ine toV8()
34 #include "bindings/v8/ExceptionState.h" 35 #include "bindings/v8/ExceptionState.h"
36 #include "bindings/v8/custom/V8ArrayBufferCustom.h" // MUST precede ScriptPromis eResolver for compilation to work.
abarth-chromium 2013/08/16 04:53:07 We should fix these include order dependencies.
eroman 2013/08/16 22:59:41 The issue is that the header file inlines this tem
37 #include "bindings/v8/ScriptPromiseResolver.h"
35 #include "core/dom/ExceptionCode.h" 38 #include "core/dom/ExceptionCode.h"
36 #include "core/platform/NotImplemented.h" 39 #include "core/platform/NotImplemented.h"
37 #include "modules/crypto/CryptoOperation.h"
38 #include "modules/crypto/Key.h" 40 #include "modules/crypto/Key.h"
39 #include "modules/crypto/KeyOperation.h"
40 #include "modules/crypto/NormalizeAlgorithm.h" 41 #include "modules/crypto/NormalizeAlgorithm.h"
41 #include "public/platform/Platform.h" 42 #include "public/platform/Platform.h"
43 #include "public/platform/WebArrayBuffer.h"
42 #include "public/platform/WebCrypto.h" 44 #include "public/platform/WebCrypto.h"
43 #include "public/platform/WebCryptoAlgorithmParams.h" 45 #include "public/platform/WebCryptoAlgorithmParams.h"
44 #include "wtf/ArrayBufferView.h" 46 #include "wtf/ArrayBufferView.h"
45 47
46 namespace WebCore { 48 namespace WebCore {
47 49
48 // FIXME: Outstanding KeyOperations and CryptoOperations should be aborted when 50 // FIXME: Orphan outstanding CryptoOperationResults once SubtleCrypto gets delet ed
49 // tearing down SubtleCrypto (to avoid problems completing a 51 // (to avoid problems completing a ScriptPromiseResolver which is no longer vali d).
50 // ScriptPromiseResolver which is no longer valid). 52
53 // FIXME: Asynchronous completion needs to re-enter the v8::Context before tryin g
54 // to fulfill the Promise or it will hit
55 // ASSERT(v8::Context::InContext());
51 56
52 namespace { 57 namespace {
53 58
59 // Wrapper around the Promise which the embedder calls into.
60 class CryptoOperationResult : public WebKit::WebCryptoOperationResult {
61 public:
62 CryptoOperationResult()
63 : m_completed(false)
64 , m_async(false)
65 , m_promiseResolver(ScriptPromiseResolver::create()) { }
66
67 virtual void completeWithError() OVERRIDE
68 {
69 m_promiseResolver->reject(WebCore::ScriptValue::createNull());
70 finish();
71 }
72
73 virtual void completeWithBuffer(const WebKit::WebArrayBuffer& buffer) OVERRI DE
74 {
75 m_promiseResolver->fulfill(PassRefPtr<ArrayBuffer>(buffer));
76 finish();
77 }
78
79 virtual void completeWithBoolean(bool b) OVERRIDE
80 {
81 m_promiseResolver->fulfill(WebCore::ScriptValue::createBoolean(b));
82 finish();
83 }
84
85 virtual void completeWithKey(const WebKit::WebCryptoKey& key) OVERRIDE
86 {
87 m_promiseResolver->fulfill(WebCore::Key::create(key));
abarth-chromium 2013/08/16 04:53:07 WebCore::Key -> Key We're in the WebCore namespac
88 finish();
89 }
90
91 virtual void willFinishLater() OVERRIDE
92 {
93 ASSERT(!m_completed);
94 ASSERT(!m_async);
95 m_async = true;
96 }
97
98 ScriptObject releasePromise()
99 {
100 if (!m_completed && !m_async) {
101 // The embedder forgot to set the result.
102 ASSERT_NOT_REACHED();
abarth-chromium 2013/08/16 04:53:07 Rather than handling this unreachable condition, w
103 completeWithError();
104 }
105
106 ScriptObject promise = m_promiseResolver->promise();
107
108 if (m_completed)
109 delete this;
abarth-chromium 2013/08/16 04:53:07 :( I don't understand why we keep needing this |d
eroman 2013/08/16 06:45:58 This is the same model as callbacks, in which the
110
111 return promise;
112 }
113
114 private:
115 void finish()
116 {
117 ASSERT(!m_completed);
118 m_completed = true;
119
120 if (m_async)
121 delete this;
122 }
123
124 bool m_completed;
125 bool m_async;
126
127 RefPtr<ScriptPromiseResolver> m_promiseResolver;
128 };
129
54 WebKit::WebCryptoKeyUsageMask toKeyUsage(AlgorithmOperation operation) 130 WebKit::WebCryptoKeyUsageMask toKeyUsage(AlgorithmOperation operation)
55 { 131 {
56 switch (operation) { 132 switch (operation) {
57 case Encrypt: 133 case Encrypt:
58 return WebKit::WebCryptoKeyUsageEncrypt; 134 return WebKit::WebCryptoKeyUsageEncrypt;
59 case Decrypt: 135 case Decrypt:
60 return WebKit::WebCryptoKeyUsageDecrypt; 136 return WebKit::WebCryptoKeyUsageDecrypt;
61 case Sign: 137 case Sign:
62 return WebKit::WebCryptoKeyUsageSign; 138 return WebKit::WebCryptoKeyUsageSign;
63 case Verify: 139 case Verify:
(...skipping 30 matching lines...) Expand all
94 // algorithm. 170 // algorithm.
95 171
96 if (key.algorithm().paramsType() == WebKit::WebCryptoAlgorithmParamsTypeHmac Params) { 172 if (key.algorithm().paramsType() == WebKit::WebCryptoAlgorithmParamsTypeHmac Params) {
97 return key.algorithm().hmacParams()->hash().id() == algorithm.hmacParams ()->hash().id(); 173 return key.algorithm().hmacParams()->hash().id() == algorithm.hmacParams ()->hash().id();
98 } 174 }
99 175
100 ASSERT_NOT_REACHED(); 176 ASSERT_NOT_REACHED();
101 return false; 177 return false;
102 } 178 }
103 179
104 PassRefPtr<CryptoOperation> createCryptoOperation(const Dictionary& rawAlgorithm , Key* key, AlgorithmOperation operationType, ArrayBufferView* signature, Except ionState& es) 180 ScriptObject startCryptoOperation(const Dictionary& rawAlgorithm, Key* key, Algo rithmOperation operationType, ArrayBufferView* signature, ArrayBufferView* dataB uffer, ExceptionState& es)
105 { 181 {
106 WebKit::WebCrypto* platformCrypto = WebKit::Platform::current()->crypto(); 182 WebKit::WebCrypto* platformCrypto = WebKit::Platform::current()->crypto();
107 if (!platformCrypto) { 183 if (!platformCrypto) {
108 es.throwDOMException(NotSupportedError); 184 es.throwDOMException(NotSupportedError);
109 return 0; 185 return ScriptObject();
110 } 186 }
111 187
112 WebKit::WebCryptoAlgorithm algorithm; 188 WebKit::WebCryptoAlgorithm algorithm;
113 if (!normalizeAlgorithm(rawAlgorithm, operationType, algorithm, es)) 189 if (!normalizeAlgorithm(rawAlgorithm, operationType, algorithm, es))
114 return 0; 190 return ScriptObject();
115 191
116 // All operations other than Digest require a valid Key. 192 // All operations other than Digest require a valid Key.
117 if (operationType != Digest) { 193 if (operationType != Digest) {
118 if (!key) { 194 if (!key) {
119 es.throwTypeError(); 195 es.throwTypeError();
120 return 0; 196 return ScriptObject();
121 } 197 }
122 198
123 if (!keyCanBeUsedForAlgorithm(key->key(), algorithm, operationType)) { 199 if (!keyCanBeUsedForAlgorithm(key->key(), algorithm, operationType)) {
124 es.throwDOMException(NotSupportedError); 200 es.throwDOMException(NotSupportedError);
125 return 0; 201 return ScriptObject();
126 } 202 }
127 } 203 }
128 204
129 // Only Verify takes a signature. 205 // Only Verify takes a signature.
130 if (operationType == Verify && !signature) { 206 if (operationType == Verify && !signature) {
131 es.throwTypeError(); 207 es.throwTypeError();
132 return 0; 208 return ScriptObject();
133 } 209 }
134 210
135 RefPtr<CryptoOperationImpl> opImpl = CryptoOperationImpl::create(); 211 if (!dataBuffer) {
136 WebKit::WebCryptoOperationResult result(opImpl.get()); 212 es.throwTypeError();
213 return ScriptObject();
214 }
215
216 const unsigned char* data = static_cast<const unsigned char*>(dataBuffer->ba seAddress());
217 size_t dataSize = dataBuffer->byteLength();
218
219 // This is deleted either by releasePromise() below, or on asynchronous
220 // completion of the request.
221 CryptoOperationResult* result = new CryptoOperationResult();
abarth-chromium 2013/08/16 04:53:07 This is a naked call to |new|. We shouldn't have
eroman 2013/08/16 06:45:58 This was to enable the implementations of encrypt(
137 222
138 switch (operationType) { 223 switch (operationType) {
139 case Encrypt: 224 case Encrypt:
140 platformCrypto->encrypt(algorithm, key->key(), result); 225 platformCrypto->encrypt(algorithm, key->key(), data, dataSize, result);
141 break; 226 break;
142 case Decrypt: 227 case Decrypt:
143 platformCrypto->decrypt(algorithm, key->key(), result); 228 platformCrypto->decrypt(algorithm, key->key(), data, dataSize, result);
144 break; 229 break;
145 case Sign: 230 case Sign:
146 platformCrypto->sign(algorithm, key->key(), result); 231 platformCrypto->sign(algorithm, key->key(), data, dataSize, result);
147 break; 232 break;
148 case Verify: 233 case Verify:
149 platformCrypto->verifySignature(algorithm, key->key(), reinterpret_cast< const unsigned char*>(signature->baseAddress()), signature->byteLength(), result ); 234 platformCrypto->verifySignature(algorithm, key->key(), reinterpret_cast< const unsigned char*>(signature->baseAddress()), signature->byteLength(), data, dataSize, result);
150 break; 235 break;
151 case Digest: 236 case Digest:
152 platformCrypto->digest(algorithm, result); 237 platformCrypto->digest(algorithm, data, dataSize, result);
153 break; 238 break;
154 default: 239 default:
155 ASSERT_NOT_REACHED(); 240 ASSERT_NOT_REACHED();
156 return 0; 241 return ScriptObject();
157 } 242 }
158 243
159 if (opImpl->throwInitializationError(es)) 244 return result->releasePromise();
160 return 0;
161 return CryptoOperation::create(algorithm, opImpl.get());
162 } 245 }
163 246
164 } // namespace 247 } // namespace
165 248
166 SubtleCrypto::SubtleCrypto() 249 SubtleCrypto::SubtleCrypto()
167 { 250 {
168 ScriptWrappable::init(this); 251 ScriptWrappable::init(this);
169 } 252 }
170 253
171 PassRefPtr<CryptoOperation> SubtleCrypto::encrypt(const Dictionary& rawAlgorithm , Key* key, ExceptionState& es) 254 ScriptObject SubtleCrypto::encrypt(const Dictionary& rawAlgorithm, Key* key, Arr ayBufferView* data, ExceptionState& es)
172 { 255 {
173 return createCryptoOperation(rawAlgorithm, key, Encrypt, 0, es); 256 return startCryptoOperation(rawAlgorithm, key, Encrypt, 0, data, es);
174 } 257 }
175 258
176 PassRefPtr<CryptoOperation> SubtleCrypto::decrypt(const Dictionary& rawAlgorithm , Key* key, ExceptionState& es) 259 ScriptObject SubtleCrypto::decrypt(const Dictionary& rawAlgorithm, Key* key, Arr ayBufferView* data, ExceptionState& es)
177 { 260 {
178 return createCryptoOperation(rawAlgorithm, key, Decrypt, 0, es); 261 return startCryptoOperation(rawAlgorithm, key, Decrypt, 0, data, es);
179 } 262 }
180 263
181 PassRefPtr<CryptoOperation> SubtleCrypto::sign(const Dictionary& rawAlgorithm, K ey* key, ExceptionState& es) 264 ScriptObject SubtleCrypto::sign(const Dictionary& rawAlgorithm, Key* key, ArrayB ufferView* data, ExceptionState& es)
182 { 265 {
183 return createCryptoOperation(rawAlgorithm, key, Sign, 0, es); 266 return startCryptoOperation(rawAlgorithm, key, Sign, 0, data, es);
184 } 267 }
185 268
186 PassRefPtr<CryptoOperation> SubtleCrypto::verifySignature(const Dictionary& rawA lgorithm, Key* key, ArrayBufferView* signature, ExceptionState& es) 269 ScriptObject SubtleCrypto::verifySignature(const Dictionary& rawAlgorithm, Key* key, ArrayBufferView* signature, ArrayBufferView* data, ExceptionState& es)
187 { 270 {
188 return createCryptoOperation(rawAlgorithm, key, Verify, signature, es); 271 return startCryptoOperation(rawAlgorithm, key, Verify, signature, data, es);
189 } 272 }
190 273
191 PassRefPtr<CryptoOperation> SubtleCrypto::digest(const Dictionary& rawAlgorithm, ExceptionState& es) 274 ScriptObject SubtleCrypto::digest(const Dictionary& rawAlgorithm, ArrayBufferVie w* data, ExceptionState& es)
192 { 275 {
193 return createCryptoOperation(rawAlgorithm, 0, Digest, 0, es); 276 return startCryptoOperation(rawAlgorithm, 0, Digest, 0, data, es);
194 } 277 }
195 278
196 ScriptObject SubtleCrypto::generateKey(const Dictionary& rawAlgorithm, bool extr actable, const Vector<String>& rawKeyUsages, ExceptionState& es) 279 ScriptObject SubtleCrypto::generateKey(const Dictionary& rawAlgorithm, bool extr actable, const Vector<String>& rawKeyUsages, ExceptionState& es)
197 { 280 {
198 WebKit::WebCrypto* platformCrypto = WebKit::Platform::current()->crypto(); 281 WebKit::WebCrypto* platformCrypto = WebKit::Platform::current()->crypto();
199 if (!platformCrypto) { 282 if (!platformCrypto) {
200 es.throwDOMException(NotSupportedError); 283 es.throwDOMException(NotSupportedError);
201 return ScriptObject(); 284 return ScriptObject();
202 } 285 }
203 286
204 WebKit::WebCryptoKeyUsageMask keyUsages; 287 WebKit::WebCryptoKeyUsageMask keyUsages;
205 if (!Key::parseUsageMask(rawKeyUsages, keyUsages)) { 288 if (!Key::parseUsageMask(rawKeyUsages, keyUsages)) {
206 es.throwTypeError(); 289 es.throwTypeError();
207 return ScriptObject(); 290 return ScriptObject();
208 } 291 }
209 292
210 WebKit::WebCryptoAlgorithm algorithm; 293 WebKit::WebCryptoAlgorithm algorithm;
211 if (!normalizeAlgorithm(rawAlgorithm, GenerateKey, algorithm, es)) 294 if (!normalizeAlgorithm(rawAlgorithm, GenerateKey, algorithm, es))
212 return ScriptObject(); 295 return ScriptObject();
213 296
214 RefPtr<KeyOperation> keyOp = KeyOperation::create(); 297 // This is deleted either by releasePromise() below, or on asynchronous
215 WebKit::WebCryptoKeyOperationResult result(keyOp.get()); 298 // completion of the request.
299 CryptoOperationResult* result = new CryptoOperationResult();
abarth-chromium 2013/08/16 04:53:07 Another naked |new|. None of these should be nece
300
216 platformCrypto->generateKey(algorithm, extractable, keyUsages, result); 301 platformCrypto->generateKey(algorithm, extractable, keyUsages, result);
217 return keyOp->returnValue(es); 302
303 return result->releasePromise();
218 } 304 }
219 305
220 ScriptObject SubtleCrypto::importKey(const String& rawFormat, ArrayBufferView* k eyData, const Dictionary& rawAlgorithm, bool extractable, const Vector<String>& rawKeyUsages, ExceptionState& es) 306 ScriptObject SubtleCrypto::importKey(const String& rawFormat, ArrayBufferView* k eyData, const Dictionary& rawAlgorithm, bool extractable, const Vector<String>& rawKeyUsages, ExceptionState& es)
221 { 307 {
222 WebKit::WebCrypto* platformCrypto = WebKit::Platform::current()->crypto(); 308 WebKit::WebCrypto* platformCrypto = WebKit::Platform::current()->crypto();
223 if (!platformCrypto) { 309 if (!platformCrypto) {
224 es.throwDOMException(NotSupportedError); 310 es.throwDOMException(NotSupportedError);
225 return ScriptObject(); 311 return ScriptObject();
226 } 312 }
227 313
(...skipping 13 matching lines...) Expand all
241 es.throwTypeError(); 327 es.throwTypeError();
242 return ScriptObject(); 328 return ScriptObject();
243 } 329 }
244 330
245 WebKit::WebCryptoAlgorithm algorithm; 331 WebKit::WebCryptoAlgorithm algorithm;
246 if (!normalizeAlgorithm(rawAlgorithm, ImportKey, algorithm, es)) 332 if (!normalizeAlgorithm(rawAlgorithm, ImportKey, algorithm, es))
247 return ScriptObject(); 333 return ScriptObject();
248 334
249 const unsigned char* keyDataBytes = static_cast<unsigned char*>(keyData->bas eAddress()); 335 const unsigned char* keyDataBytes = static_cast<unsigned char*>(keyData->bas eAddress());
250 336
251 RefPtr<KeyOperation> keyOp = KeyOperation::create(); 337 // This is deleted either by releasePromise() below, or on asynchronous
252 WebKit::WebCryptoKeyOperationResult result(keyOp.get()); 338 // completion of the request.
339 CryptoOperationResult* result = new CryptoOperationResult();
340
253 platformCrypto->importKey(format, keyDataBytes, keyData->byteLength(), algor ithm, extractable, keyUsages, result); 341 platformCrypto->importKey(format, keyDataBytes, keyData->byteLength(), algor ithm, extractable, keyUsages, result);
254 return keyOp->returnValue(es); 342
343 return result->releasePromise();
255 } 344 }
256 345
257 } // namespace WebCore 346 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698