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

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

Issue 19885002: WebCrypto: Add interfaces for importKey(). (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Move test stuff into MockWebCrypto Created 7 years, 5 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()
35 #include "bindings/v8/ScriptPromiseResolver.h"
34 #include "core/dom/ExceptionCode.h" 36 #include "core/dom/ExceptionCode.h"
35 #include "modules/crypto/CryptoOperation.h" 37 #include "modules/crypto/CryptoOperation.h"
38 #include "modules/crypto/Key.h"
36 #include "modules/crypto/NormalizeAlgorithm.h" 39 #include "modules/crypto/NormalizeAlgorithm.h"
37 #include "public/platform/Platform.h" 40 #include "public/platform/Platform.h"
38 #include "public/platform/WebArrayBuffer.h" // FIXME: temporary
39 #include "public/platform/WebCrypto.h" 41 #include "public/platform/WebCrypto.h"
40 #include "wtf/ArrayBuffer.h"
41 #include "wtf/ArrayBufferView.h" 42 #include "wtf/ArrayBufferView.h"
42 #include "wtf/SHA1.h" // FIXME: temporary
43
44 43
45 namespace WebCore { 44 namespace WebCore {
46 45
47 namespace { 46 namespace {
48 47
49 // FIXME: The following are temporary implementations of what *should* go on the 48 // FIXME: Temporary
50 // embedder's side. Since SHA1 is easily implemented, this serves as 49 PassRefPtr<CryptoOperation> doDummyOperation(const Dictionary& rawAlgorithm, Alg orithmOperation operationType, ExceptionCode& ec)
abarth-chromium 2013/07/23 06:22:07 Like "get", "do" is a weak verb. Perhaps "dummyOp
51 // a useful proof of concept to get layout tests up and running and 50 {
52 // returning correct results, until the embedder's side is implemented. 51 WebKit::WebCrypto* platformCrypto = WebKit::Platform::current()->crypto();
53 //------------------------------------------------------------------------------ 52 if (!platformCrypto) {
54 class DummyOperation : public WebKit::WebCryptoOperation { 53 ec = NotSupportedError;
55 public: 54 return 0;
56 explicit DummyOperation(WebKit::WebCryptoOperationResult* result) : m_result (result) { }
57
58 virtual void process(const unsigned char* bytes, size_t size) OVERRIDE
59 {
60 m_result->completeWithError();
61 delete this;
62 } 55 }
63 56
64 virtual void abort() OVERRIDE
65 {
66 delete this;
67 }
68
69 virtual void finish() OVERRIDE
70 {
71 m_result->completeWithError();
72 delete this;
73 }
74
75 protected:
76 WebKit::WebCryptoOperationResult* m_result;
77 };
78
79 class MockSha1Operation : public DummyOperation {
80 public:
81 explicit MockSha1Operation(WebKit::WebCryptoOperationResult* result) : Dummy Operation(result) { }
82
83 virtual void process(const unsigned char* bytes, size_t size) OVERRIDE
84 {
85 m_sha1.addBytes(bytes, size);
86 }
87
88 virtual void finish() OVERRIDE
89 {
90 Vector<uint8_t, 20> hash;
91 m_sha1.computeHash(hash);
92
93 WebKit::WebArrayBuffer buffer = WebKit::WebArrayBuffer::create(hash.size (), 1);
94 memcpy(buffer.data(), hash.data(), hash.size());
95
96 m_result->completeWithArrayBuffer(buffer);
97 delete this;
98 }
99
100 private:
101 SHA1 m_sha1;
102 };
103
104 class MockPlatformCrypto : public WebKit::WebCrypto {
105 public:
106 virtual void digest(const WebKit::WebCryptoAlgorithm& algorithm, WebKit::Web CryptoOperationResult* result) OVERRIDE
107 {
108 if (algorithm.id() == WebKit::WebCryptoAlgorithmIdSha1) {
109 result->initializationSucceded(new MockSha1Operation(result));
110 } else {
111 // Don't fail synchronously, since existing layout tests rely on
112 // digest for testing algorithm normalization.
113 result->initializationSucceded(new DummyOperation(result));
114 }
115 }
116 };
117
118 WebKit::WebCrypto* mockPlatformCrypto()
119 {
120 DEFINE_STATIC_LOCAL(MockPlatformCrypto, crypto, ());
121 return &crypto;
122 }
123
124 PassRefPtr<CryptoOperation> doDummyOperation(const Dictionary& rawAlgorithm, Alg orithmOperation operationType, ExceptionCode& ec)
125 {
126 WebKit::WebCryptoAlgorithm algorithm; 57 WebKit::WebCryptoAlgorithm algorithm;
127 if (!normalizeAlgorithm(rawAlgorithm, operationType, algorithm, ec)) 58 if (!normalizeAlgorithm(rawAlgorithm, operationType, algorithm, ec))
128 return 0; 59 return 0;
129 60
130 RefPtr<CryptoOperation> op = CryptoOperation::create(algorithm, &ec); 61 RefPtr<CryptoOperation> op = CryptoOperation::create(algorithm, &ec);
131 op->initializationSucceded(new DummyOperation(op.get())); 62 platformCrypto->digest(algorithm, op.get());
132 return op.release(); 63 return op.release();
133 } 64 }
134 //------------------------------------------------------------------------------ 65
66 class KeyOperation : public WebKit::WebCryptoKeyOperationResult {
67 public:
68 KeyOperation(ScriptPromiseResolver* resolver, ExceptionCode* ec)
69 : m_state(Initializing)
70 , m_impl(0)
71 , m_promiseResolver(resolver)
72 , m_exceptionCode(ec)
73 {
74 }
75
76 ~KeyOperation();
77
78 // Implementation of WebKit::WebCryptoKeyOperationResult.
79 virtual void initializationFailed() OVERRIDE;
80 virtual void initializationSucceeded(WebKit::WebCryptoKeyOperation*) OVERRID E;
81 virtual void completeWithError() OVERRIDE;
82 virtual void completeWithKey(const WebKit::WebCryptoKey&) OVERRIDE;
83
84 private:
85 enum State {
86 Initializing,
87 InProgress,
88 Done,
89 };
90
91 State m_state;
92 WebKit::WebCryptoKeyOperation* m_impl;
93 ExceptionCode* m_exceptionCode;
abarth-chromium 2013/07/23 06:22:07 I don't understand how KeyOperation can hold a poi
eroman 2013/07/23 06:53:41 It is a little bit tricky, but the m_exceptionCode
abarth-chromium 2013/07/23 07:06:14 That's too tricky. Is there a simpler design?
94 RefPtr<ScriptPromiseResolver> m_promiseResolver;
95 };
96
97 KeyOperation::~KeyOperation()
98 {
99 // Abort any inprogress operation.
100 switch (m_state) {
101 case Initializing:
102 ASSERT_NOT_REACHED();
103 break;
104 case InProgress:
105 // This will cause m_impl to be deleted.
106 m_state = Done;
107 m_impl->abort();
108 m_impl = 0;
109 case Done:
110 ASSERT(!m_impl);
111 break;
112 }
113 }
114
115 void KeyOperation::initializationFailed()
116 {
117 ASSERT(m_state == Initializing);
118
119 *m_exceptionCode = NotSupportedError;
120
121 m_exceptionCode = 0;
122 m_state = Done;
123 delete this;
abarth-chromium 2013/07/23 06:22:07 This line is suspicious and indicates a bad memory
124 }
125
126 void KeyOperation::initializationSucceeded(WebKit::WebCryptoKeyOperation* operat ionImpl)
127 {
128 ASSERT(m_state == Initializing);
129 ASSERT(operationImpl);
130 ASSERT(!m_impl);
131
132 m_exceptionCode = 0;
133 m_impl = operationImpl;
134 m_state = InProgress;
135 }
136
137 void KeyOperation::completeWithError()
138 {
139 ASSERT(m_state == Initializing || m_state == InProgress);
140
141 m_exceptionCode = 0;
142 m_impl = 0;
143 m_state = Done;
144
145 m_promiseResolver->reject(ScriptValue::createNull());
146 delete this;
147 }
148
149 void KeyOperation::completeWithKey(const WebKit::WebCryptoKey& key)
150 {
151 ASSERT(m_state == Initializing || m_state == InProgress);
152
153 m_exceptionCode = 0;
154 m_impl = 0;
155 m_state = Done;
156
157 m_promiseResolver->fulfill(Key::create(key));
158 delete this;
159 }
135 160
136 } // namespace 161 } // namespace
137 162
138 SubtleCrypto::SubtleCrypto() 163 SubtleCrypto::SubtleCrypto()
139 { 164 {
140 ScriptWrappable::init(this); 165 ScriptWrappable::init(this);
141 } 166 }
142 167
143 PassRefPtr<CryptoOperation> SubtleCrypto::encrypt(const Dictionary& rawAlgorithm , ExceptionCode& ec) 168 PassRefPtr<CryptoOperation> SubtleCrypto::encrypt(const Dictionary& rawAlgorithm , ExceptionCode& ec)
144 { 169 {
(...skipping 10 matching lines...) Expand all
155 return doDummyOperation(rawAlgorithm, Sign, ec); 180 return doDummyOperation(rawAlgorithm, Sign, ec);
156 } 181 }
157 182
158 PassRefPtr<CryptoOperation> SubtleCrypto::verifySignature(const Dictionary& rawA lgorithm, ExceptionCode& ec) 183 PassRefPtr<CryptoOperation> SubtleCrypto::verifySignature(const Dictionary& rawA lgorithm, ExceptionCode& ec)
159 { 184 {
160 return doDummyOperation(rawAlgorithm, Verify, ec); 185 return doDummyOperation(rawAlgorithm, Verify, ec);
161 } 186 }
162 187
163 PassRefPtr<CryptoOperation> SubtleCrypto::digest(const Dictionary& rawAlgorithm, ExceptionCode& ec) 188 PassRefPtr<CryptoOperation> SubtleCrypto::digest(const Dictionary& rawAlgorithm, ExceptionCode& ec)
164 { 189 {
165 WebKit::WebCrypto* platformCrypto = mockPlatformCrypto(); 190 WebKit::WebCrypto* platformCrypto = WebKit::Platform::current()->crypto();
166 if (!platformCrypto) { 191 if (!platformCrypto) {
167 ec = NotSupportedError; 192 ec = NotSupportedError;
168 return 0; 193 return 0;
169 } 194 }
170 195
171 WebKit::WebCryptoAlgorithm algorithm; 196 WebKit::WebCryptoAlgorithm algorithm;
172 if (!normalizeAlgorithm(rawAlgorithm, Digest, algorithm, ec)) 197 if (!normalizeAlgorithm(rawAlgorithm, Digest, algorithm, ec))
173 return 0; 198 return 0;
174 199
175 RefPtr<CryptoOperation> op = CryptoOperation::create(algorithm, &ec); 200 RefPtr<CryptoOperation> op = CryptoOperation::create(algorithm, &ec);
176 platformCrypto->digest(algorithm, op.get()); 201 platformCrypto->digest(algorithm, op.get());
177 return op.release(); 202 return op.release();
178 } 203 }
179 204
205 ScriptObject SubtleCrypto::importKey(const String& rawFormat, ArrayBufferView* k eyData, const Dictionary& rawAlgorithm, bool extractable, const Vector<String>& rawKeyUsages, ExceptionCode& ec)
206 {
207 WebKit::WebCrypto* platformCrypto = WebKit::Platform::current()->crypto();
208 if (!platformCrypto) {
209 ec = NotSupportedError;
210 return ScriptObject();
211 }
212
213 WebKit::WebCryptoKeyUsageMask keyUsages;
214 if (!Key::parseUsageMask(rawKeyUsages, keyUsages)) {
215 ec = TypeError;
216 return ScriptObject();
217 }
218
219 WebKit::WebCryptoKeyFormat format;
220 if (!Key::parseFormat(rawFormat, format)) {
221 ec = TypeError;
222 return ScriptObject();
223 }
224
225 WebKit::WebCryptoAlgorithm algorithm;
226 if (!normalizeAlgorithmForImportKey(rawAlgorithm, algorithm, ec))
227 return ScriptObject();
228
229 const unsigned char* keyDataBytes = static_cast<unsigned char*>(keyData->bas eAddress());
230
231 RefPtr<ScriptPromiseResolver> promiseResolver = ScriptPromiseResolver::creat e();
232
233 // The |op| object is deleted upon completion of the underlying operation
234 // (i.e. when platformCrypto->importKey() notifies completion).
235 //
236 // FIXME: KeyOperation is never aborted. It should probably be aborted when
237 // the SubtleCrypto object that started it gets deleted. The concern being
238 // if the operation eventually does complete, the ScriptPromiseResolver
239 // might no longer be valid because the context it belonged to got torn
240 // down.
241 KeyOperation* op = new KeyOperation(promiseResolver.get(), &ec);
abarth-chromium 2013/07/23 06:22:07 This is a "naked new", which is where the bad memo
eroman 2013/07/23 06:53:41 I'll think about this some more and see what else
abarth-chromium 2013/07/23 07:06:14 We might want to change CryptoOperation to follow
242 platformCrypto->importKey(format, keyDataBytes, keyData->byteLength(), algor ithm, extractable, keyUsages, op);
243 return promiseResolver->promise();
244 }
245
180 } // namespace WebCore 246 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698