Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / modules / crypto / SubtleCrypto.cpp
1 /*
2  * Copyright (C) 2013 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
29  */
30
31 #include "config.h"
32 #include "modules/crypto/SubtleCrypto.h"
33
34 #include "bindings/v8/Dictionary.h"
35 #include "modules/crypto/CryptoResultImpl.h"
36 #include "modules/crypto/Key.h"
37 #include "modules/crypto/NormalizeAlgorithm.h"
38 #include "public/platform/Platform.h"
39 #include "public/platform/WebCrypto.h"
40 #include "public/platform/WebCryptoAlgorithm.h"
41 #include "wtf/ArrayBufferView.h"
42
43 namespace WebCore {
44
45 namespace {
46
47 // Seems like the generated bindings should take care of these however it
48 // currently doesn't. See also http://crbug.com/264520
49 bool ensureNotNull(const ArrayPiece& x, const char* paramName, CryptoResult* result)
50 {
51     if (x.isNull()) {
52         String message = String("Invalid ") + paramName + String(" argument");
53         result->completeWithError(blink::WebCryptoErrorTypeType, blink::WebString(message));
54         return false;
55     }
56     return true;
57 }
58
59 bool ensureNotNull(Key* key, const char* paramName, CryptoResult* result)
60 {
61     if (!key) {
62         String message = String("Invalid ") + paramName + String(" argument");
63         result->completeWithError(blink::WebCryptoErrorTypeType, blink::WebString(message));
64         return false;
65     }
66     return true;
67 }
68
69 ScriptPromise startCryptoOperation(const Dictionary& rawAlgorithm, Key* key, AlgorithmOperation operationType, const ArrayPiece& signature, const ArrayPiece& dataBuffer)
70 {
71     RefPtr<CryptoResultImpl> result = CryptoResultImpl::create();
72     ScriptPromise promise = result->promise();
73
74     bool requiresKey = operationType != Digest;
75
76     if (requiresKey && !ensureNotNull(key, "key", result.get()))
77         return promise;
78     if (operationType == Verify && !ensureNotNull(signature, "signature", result.get()))
79         return promise;
80     if (!ensureNotNull(dataBuffer, "dataBuffer", result.get()))
81         return promise;
82
83     blink::WebCryptoAlgorithm algorithm;
84     if (!parseAlgorithm(rawAlgorithm, operationType, algorithm, result.get()))
85         return promise;
86
87     if (requiresKey && !key->canBeUsedForAlgorithm(algorithm, operationType, result.get()))
88         return promise;
89
90     const unsigned char* data = dataBuffer.bytes();
91     unsigned dataSize = dataBuffer.byteLength();
92
93     switch (operationType) {
94     case Encrypt:
95         blink::Platform::current()->crypto()->encrypt(algorithm, key->key(), data, dataSize, result->result());
96         break;
97     case Decrypt:
98         blink::Platform::current()->crypto()->decrypt(algorithm, key->key(), data, dataSize, result->result());
99         break;
100     case Sign:
101         blink::Platform::current()->crypto()->sign(algorithm, key->key(), data, dataSize, result->result());
102         break;
103     case Verify:
104         blink::Platform::current()->crypto()->verifySignature(algorithm, key->key(), signature.bytes(), signature.byteLength(), data, dataSize, result->result());
105         break;
106     case Digest:
107         blink::Platform::current()->crypto()->digest(algorithm, data, dataSize, result->result());
108         break;
109     default:
110         ASSERT_NOT_REACHED();
111         return ScriptPromise();
112     }
113
114     return promise;
115 }
116
117 } // namespace
118
119 SubtleCrypto::SubtleCrypto()
120 {
121     ScriptWrappable::init(this);
122 }
123
124 ScriptPromise SubtleCrypto::encrypt(const Dictionary& rawAlgorithm, Key* key, const ArrayPiece& data)
125 {
126     return startCryptoOperation(rawAlgorithm, key, Encrypt, ArrayPiece(), data);
127 }
128
129 ScriptPromise SubtleCrypto::decrypt(const Dictionary& rawAlgorithm, Key* key, const ArrayPiece& data)
130 {
131     return startCryptoOperation(rawAlgorithm, key, Decrypt, ArrayPiece(), data);
132 }
133
134 ScriptPromise SubtleCrypto::sign(const Dictionary& rawAlgorithm, Key* key, const ArrayPiece& data)
135 {
136     return startCryptoOperation(rawAlgorithm, key, Sign, ArrayPiece(), data);
137 }
138
139 ScriptPromise SubtleCrypto::verifySignature(const Dictionary& rawAlgorithm, Key* key, const ArrayPiece& signature, const ArrayPiece& data)
140 {
141     return startCryptoOperation(rawAlgorithm, key, Verify, signature, data);
142 }
143
144 ScriptPromise SubtleCrypto::digest(const Dictionary& rawAlgorithm, const ArrayPiece& data)
145 {
146     return startCryptoOperation(rawAlgorithm, 0, Digest, ArrayPiece(), data);
147 }
148
149 ScriptPromise SubtleCrypto::generateKey(const Dictionary& rawAlgorithm, bool extractable, const Vector<String>& rawKeyUsages)
150 {
151     RefPtr<CryptoResultImpl> result = CryptoResultImpl::create();
152     ScriptPromise promise = result->promise();
153
154     blink::WebCryptoKeyUsageMask keyUsages;
155     if (!Key::parseUsageMask(rawKeyUsages, keyUsages, result.get()))
156         return promise;
157
158     blink::WebCryptoAlgorithm algorithm;
159     if (!parseAlgorithm(rawAlgorithm, GenerateKey, algorithm, result.get()))
160         return promise;
161
162     blink::Platform::current()->crypto()->generateKey(algorithm, extractable, keyUsages, result->result());
163     return promise;
164 }
165
166 ScriptPromise SubtleCrypto::importKey(const String& rawFormat, const ArrayPiece& keyData, const Dictionary& rawAlgorithm, bool extractable, const Vector<String>& rawKeyUsages)
167 {
168     RefPtr<CryptoResultImpl> result = CryptoResultImpl::create();
169     ScriptPromise promise = result->promise();
170
171     if (!ensureNotNull(keyData, "keyData", result.get()))
172         return promise;
173
174     blink::WebCryptoKeyFormat format;
175     if (!Key::parseFormat(rawFormat, format, result.get()))
176         return promise;
177
178     blink::WebCryptoKeyUsageMask keyUsages;
179     if (!Key::parseUsageMask(rawKeyUsages, keyUsages, result.get()))
180         return promise;
181
182     blink::WebCryptoAlgorithm algorithm;
183     if (!parseAlgorithm(rawAlgorithm, ImportKey, algorithm, result.get()))
184         return promise;
185
186     blink::Platform::current()->crypto()->importKey(format, keyData.bytes(), keyData.byteLength(), algorithm, extractable, keyUsages, result->result());
187     return promise;
188 }
189
190 ScriptPromise SubtleCrypto::exportKey(const String& rawFormat, Key* key)
191 {
192     RefPtr<CryptoResultImpl> result = CryptoResultImpl::create();
193     ScriptPromise promise = result->promise();
194
195     if (!ensureNotNull(key, "key", result.get()))
196         return promise;
197
198     blink::WebCryptoKeyFormat format;
199     if (!Key::parseFormat(rawFormat, format, result.get()))
200         return promise;
201
202     if (!key->extractable()) {
203         result->completeWithError(blink::WebCryptoErrorTypeInvalidAccess, "key is not extractable");
204         return promise;
205     }
206
207     blink::Platform::current()->crypto()->exportKey(format, key->key(), result->result());
208     return promise;
209 }
210
211 ScriptPromise SubtleCrypto::wrapKey(const String& rawFormat, Key* key, Key* wrappingKey, const Dictionary& rawWrapAlgorithm)
212 {
213     RefPtr<CryptoResultImpl> result = CryptoResultImpl::create();
214     ScriptPromise promise = result->promise();
215
216     if (!ensureNotNull(key, "key", result.get()))
217         return promise;
218
219     if (!ensureNotNull(wrappingKey, "wrappingKey", result.get()))
220         return promise;
221
222     blink::WebCryptoKeyFormat format;
223     if (!Key::parseFormat(rawFormat, format, result.get()))
224         return promise;
225
226     blink::WebCryptoAlgorithm wrapAlgorithm;
227     if (!parseAlgorithm(rawWrapAlgorithm, WrapKey, wrapAlgorithm, result.get()))
228         return promise;
229
230     if (!key->extractable()) {
231         result->completeWithError(blink::WebCryptoErrorTypeInvalidAccess, "key is not extractable");
232         return promise;
233     }
234
235     if (!wrappingKey->canBeUsedForAlgorithm(wrapAlgorithm, WrapKey, result.get()))
236         return promise;
237
238     blink::Platform::current()->crypto()->wrapKey(format, key->key(), wrappingKey->key(), wrapAlgorithm, result->result());
239     return promise;
240 }
241
242 ScriptPromise SubtleCrypto::unwrapKey(const String& rawFormat, const ArrayPiece& wrappedKey, Key* unwrappingKey, const Dictionary& rawUnwrapAlgorithm, const Dictionary& rawUnwrappedKeyAlgorithm, bool extractable, const Vector<String>& rawKeyUsages)
243 {
244     RefPtr<CryptoResultImpl> result = CryptoResultImpl::create();
245     ScriptPromise promise = result->promise();
246
247     if (!ensureNotNull(wrappedKey, "wrappedKey", result.get()))
248         return promise;
249     if (!ensureNotNull(unwrappingKey, "unwrappingKey", result.get()))
250         return promise;
251
252     blink::WebCryptoKeyFormat format;
253     if (!Key::parseFormat(rawFormat, format, result.get()))
254         return promise;
255
256     blink::WebCryptoKeyUsageMask keyUsages;
257     if (!Key::parseUsageMask(rawKeyUsages, keyUsages, result.get()))
258         return promise;
259
260     blink::WebCryptoAlgorithm unwrapAlgorithm;
261     if (!parseAlgorithm(rawUnwrapAlgorithm, UnwrapKey, unwrapAlgorithm, result.get()))
262         return promise;
263
264     blink::WebCryptoAlgorithm unwrappedKeyAlgorithm;
265     if (!parseAlgorithm(rawUnwrappedKeyAlgorithm, ImportKey, unwrappedKeyAlgorithm, result.get()))
266         return promise;
267
268     if (!unwrappingKey->canBeUsedForAlgorithm(unwrapAlgorithm, UnwrapKey, result.get()))
269         return promise;
270
271     blink::Platform::current()->crypto()->unwrapKey(format, wrappedKey.bytes(), wrappedKey.byteLength(), unwrappingKey->key(), unwrapAlgorithm, unwrappedKeyAlgorithm, extractable, keyUsages, result->result());
272     return promise;
273 }
274
275 } // namespace WebCore