| OLD | NEW | 
|---|
| 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  Loading... | 
| 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" // Must precede ScriptPromiseResolver.h | 
| 34 #include "bindings/v8/ExceptionState.h" | 35 #include "bindings/v8/ExceptionState.h" | 
|  | 36 #include "bindings/v8/custom/V8ArrayBufferCustom.h" // Must precede ScriptPromis
     eResolver.h | 
|  | 37 #include "bindings/v8/ScriptPromiseResolver.h" | 
| 35 #include "core/dom/ExceptionCode.h" | 38 #include "core/dom/ExceptionCode.h" | 
| 36 #include "core/platform/NotImplemented.h" |  | 
| 37 #include "modules/crypto/CryptoOperation.h" |  | 
| 38 #include "modules/crypto/Key.h" | 39 #include "modules/crypto/Key.h" | 
| 39 #include "modules/crypto/KeyOperation.h" |  | 
| 40 #include "modules/crypto/NormalizeAlgorithm.h" | 40 #include "modules/crypto/NormalizeAlgorithm.h" | 
| 41 #include "public/platform/Platform.h" | 41 #include "public/platform/Platform.h" | 
|  | 42 #include "public/platform/WebArrayBuffer.h" | 
| 42 #include "public/platform/WebCrypto.h" | 43 #include "public/platform/WebCrypto.h" | 
| 43 #include "public/platform/WebCryptoAlgorithmParams.h" | 44 #include "public/platform/WebCryptoAlgorithmParams.h" | 
| 44 #include "wtf/ArrayBufferView.h" | 45 #include "wtf/ArrayBufferView.h" | 
| 45 | 46 | 
| 46 namespace WebCore { | 47 namespace WebCore { | 
| 47 | 48 | 
| 48 // FIXME: Outstanding KeyOperations and CryptoOperations should be aborted when | 49 // FIXME: asynchronous completion of CryptoResult. Need to re-enter the | 
| 49 // tearing down SubtleCrypto (to avoid problems completing a | 50 //        v8::Context before trying to fulfill the promise, and enable test. | 
| 50 // ScriptPromiseResolver which is no longer valid). |  | 
| 51 | 51 | 
| 52 namespace { | 52 namespace { | 
| 53 | 53 | 
|  | 54 class CryptoResult : public WebKit::WebCryptoResultPrivate, public ThreadSafeRef
     Counted<CryptoResult> { | 
|  | 55 public: | 
|  | 56     static PassRefPtr<CryptoResult> create() | 
|  | 57     { | 
|  | 58         return adoptRef(new CryptoResult); | 
|  | 59     } | 
|  | 60 | 
|  | 61     virtual void ref() OVERRIDE | 
|  | 62     { | 
|  | 63         ThreadSafeRefCounted<CryptoResult>::ref(); | 
|  | 64     } | 
|  | 65 | 
|  | 66     virtual void deref() OVERRIDE | 
|  | 67     { | 
|  | 68         ThreadSafeRefCounted<CryptoResult>::deref(); | 
|  | 69     } | 
|  | 70 | 
|  | 71     virtual void completeWithError() OVERRIDE | 
|  | 72     { | 
|  | 73         m_promiseResolver->reject(ScriptValue::createNull()); | 
|  | 74         finish(); | 
|  | 75     } | 
|  | 76 | 
|  | 77     virtual void completeWithBuffer(const WebKit::WebArrayBuffer& buffer) OVERRI
     DE | 
|  | 78     { | 
|  | 79         m_promiseResolver->fulfill(PassRefPtr<ArrayBuffer>(buffer)); | 
|  | 80         finish(); | 
|  | 81     } | 
|  | 82 | 
|  | 83     virtual void completeWithBoolean(bool b) OVERRIDE | 
|  | 84     { | 
|  | 85         m_promiseResolver->fulfill(ScriptValue::createBoolean(b)); | 
|  | 86         finish(); | 
|  | 87     } | 
|  | 88 | 
|  | 89     virtual void completeWithKey(const WebKit::WebCryptoKey& key) OVERRIDE | 
|  | 90     { | 
|  | 91         m_promiseResolver->fulfill(Key::create(key)); | 
|  | 92         finish(); | 
|  | 93     } | 
|  | 94 | 
|  | 95     WebKit::WebCryptoResult result() | 
|  | 96     { | 
|  | 97         return WebKit::WebCryptoResult(this); | 
|  | 98     } | 
|  | 99 | 
|  | 100     ScriptObject promise() | 
|  | 101     { | 
|  | 102         return m_promiseResolver->promise(); | 
|  | 103     } | 
|  | 104 | 
|  | 105 private: | 
|  | 106     CryptoResult() | 
|  | 107         : m_promiseResolver(ScriptPromiseResolver::create()) | 
|  | 108         , m_finished(false) { } | 
|  | 109 | 
|  | 110     void finish() | 
|  | 111     { | 
|  | 112         ASSERT(!m_finished); | 
|  | 113         m_finished = true; | 
|  | 114     } | 
|  | 115 | 
|  | 116     RefPtr<ScriptPromiseResolver> m_promiseResolver; | 
|  | 117     bool m_finished; | 
|  | 118 }; | 
|  | 119 | 
| 54 WebKit::WebCryptoKeyUsageMask toKeyUsage(AlgorithmOperation operation) | 120 WebKit::WebCryptoKeyUsageMask toKeyUsage(AlgorithmOperation operation) | 
| 55 { | 121 { | 
| 56     switch (operation) { | 122     switch (operation) { | 
| 57     case Encrypt: | 123     case Encrypt: | 
| 58         return WebKit::WebCryptoKeyUsageEncrypt; | 124         return WebKit::WebCryptoKeyUsageEncrypt; | 
| 59     case Decrypt: | 125     case Decrypt: | 
| 60         return WebKit::WebCryptoKeyUsageDecrypt; | 126         return WebKit::WebCryptoKeyUsageDecrypt; | 
| 61     case Sign: | 127     case Sign: | 
| 62         return WebKit::WebCryptoKeyUsageSign; | 128         return WebKit::WebCryptoKeyUsageSign; | 
| 63     case Verify: | 129     case Verify: | 
| (...skipping 30 matching lines...) Expand all  Loading... | 
| 94     // algorithm. | 160     // algorithm. | 
| 95 | 161 | 
| 96     if (key.algorithm().paramsType() == WebKit::WebCryptoAlgorithmParamsTypeHmac
     Params) { | 162     if (key.algorithm().paramsType() == WebKit::WebCryptoAlgorithmParamsTypeHmac
     Params) { | 
| 97         return key.algorithm().hmacParams()->hash().id() == algorithm.hmacParams
     ()->hash().id(); | 163         return key.algorithm().hmacParams()->hash().id() == algorithm.hmacParams
     ()->hash().id(); | 
| 98     } | 164     } | 
| 99 | 165 | 
| 100     ASSERT_NOT_REACHED(); | 166     ASSERT_NOT_REACHED(); | 
| 101     return false; | 167     return false; | 
| 102 } | 168 } | 
| 103 | 169 | 
| 104 PassRefPtr<CryptoOperation> createCryptoOperation(const Dictionary& rawAlgorithm
     , Key* key, AlgorithmOperation operationType, ArrayBufferView* signature, Except
     ionState& es) | 170 ScriptObject startCryptoOperation(const Dictionary& rawAlgorithm, Key* key, Algo
     rithmOperation operationType, ArrayBufferView* signature, ArrayBufferView* dataB
     uffer, ExceptionState& es) | 
| 105 { | 171 { | 
| 106     WebKit::WebCrypto* platformCrypto = WebKit::Platform::current()->crypto(); | 172     WebKit::WebCrypto* platformCrypto = WebKit::Platform::current()->crypto(); | 
| 107     if (!platformCrypto) { | 173     if (!platformCrypto) { | 
| 108         es.throwDOMException(NotSupportedError); | 174         es.throwDOMException(NotSupportedError); | 
| 109         return 0; | 175         return ScriptObject(); | 
| 110     } | 176     } | 
| 111 | 177 | 
| 112     WebKit::WebCryptoAlgorithm algorithm; | 178     WebKit::WebCryptoAlgorithm algorithm; | 
| 113     if (!normalizeAlgorithm(rawAlgorithm, operationType, algorithm, es)) | 179     if (!normalizeAlgorithm(rawAlgorithm, operationType, algorithm, es)) | 
| 114         return 0; | 180         return ScriptObject(); | 
| 115 | 181 | 
| 116     // All operations other than Digest require a valid Key. | 182     // All operations other than Digest require a valid Key. | 
| 117     if (operationType != Digest) { | 183     if (operationType != Digest) { | 
| 118         if (!key) { | 184         if (!key) { | 
| 119             es.throwTypeError(); | 185             es.throwTypeError(); | 
| 120             return 0; | 186             return ScriptObject(); | 
| 121         } | 187         } | 
| 122 | 188 | 
| 123         if (!keyCanBeUsedForAlgorithm(key->key(), algorithm, operationType)) { | 189         if (!keyCanBeUsedForAlgorithm(key->key(), algorithm, operationType)) { | 
| 124             es.throwDOMException(NotSupportedError); | 190             es.throwDOMException(NotSupportedError); | 
| 125             return 0; | 191             return ScriptObject(); | 
| 126         } | 192         } | 
| 127     } | 193     } | 
| 128 | 194 | 
| 129     // Only Verify takes a signature. | 195     // Only Verify takes a signature. | 
| 130     if (operationType == Verify && !signature) { | 196     if (operationType == Verify && !signature) { | 
| 131         es.throwTypeError(); | 197         es.throwTypeError(); | 
| 132         return 0; | 198         return ScriptObject(); | 
| 133     } | 199     } | 
| 134 | 200 | 
| 135     RefPtr<CryptoOperationImpl> opImpl = CryptoOperationImpl::create(); | 201     if (!dataBuffer) { | 
| 136     WebKit::WebCryptoOperationResult result(opImpl.get()); | 202         es.throwTypeError(); | 
|  | 203         return ScriptObject(); | 
|  | 204     } | 
|  | 205 | 
|  | 206     const unsigned char* data = static_cast<const unsigned char*>(dataBuffer->ba
     seAddress()); | 
|  | 207     size_t dataSize = dataBuffer->byteLength(); | 
|  | 208 | 
|  | 209     RefPtr<CryptoResult> result = CryptoResult::create(); | 
| 137 | 210 | 
| 138     switch (operationType) { | 211     switch (operationType) { | 
| 139     case Encrypt: | 212     case Encrypt: | 
| 140         platformCrypto->encrypt(algorithm, key->key(), result); | 213         platformCrypto->encrypt(algorithm, key->key(), data, dataSize, result->r
     esult()); | 
| 141         break; | 214         break; | 
| 142     case Decrypt: | 215     case Decrypt: | 
| 143         platformCrypto->decrypt(algorithm, key->key(), result); | 216         platformCrypto->decrypt(algorithm, key->key(), data, dataSize, result->r
     esult()); | 
| 144         break; | 217         break; | 
| 145     case Sign: | 218     case Sign: | 
| 146         platformCrypto->sign(algorithm, key->key(), result); | 219         platformCrypto->sign(algorithm, key->key(), data, dataSize, result->resu
     lt()); | 
| 147         break; | 220         break; | 
| 148     case Verify: | 221     case Verify: | 
| 149         platformCrypto->verifySignature(algorithm, key->key(), reinterpret_cast<
     const unsigned char*>(signature->baseAddress()), signature->byteLength(), result
     ); | 222         platformCrypto->verifySignature(algorithm, key->key(), reinterpret_cast<
     const unsigned char*>(signature->baseAddress()), signature->byteLength(), data, 
     dataSize, result->result()); | 
| 150         break; | 223         break; | 
| 151     case Digest: | 224     case Digest: | 
| 152         platformCrypto->digest(algorithm, result); | 225         platformCrypto->digest(algorithm, data, dataSize, result->result()); | 
| 153         break; | 226         break; | 
| 154     default: | 227     default: | 
| 155         ASSERT_NOT_REACHED(); | 228         ASSERT_NOT_REACHED(); | 
| 156         return 0; | 229         return ScriptObject(); | 
| 157     } | 230     } | 
| 158 | 231 | 
| 159     if (opImpl->throwInitializationError(es)) | 232     return result->promise(); | 
| 160         return 0; |  | 
| 161     return CryptoOperation::create(algorithm, opImpl.get()); |  | 
| 162 } | 233 } | 
| 163 | 234 | 
| 164 } // namespace | 235 } // namespace | 
| 165 | 236 | 
| 166 SubtleCrypto::SubtleCrypto() | 237 SubtleCrypto::SubtleCrypto() | 
| 167 { | 238 { | 
| 168     ScriptWrappable::init(this); | 239     ScriptWrappable::init(this); | 
| 169 } | 240 } | 
| 170 | 241 | 
| 171 PassRefPtr<CryptoOperation> SubtleCrypto::encrypt(const Dictionary& rawAlgorithm
     , Key* key, ExceptionState& es) | 242 ScriptObject SubtleCrypto::encrypt(const Dictionary& rawAlgorithm, Key* key, Arr
     ayBufferView* data, ExceptionState& es) | 
| 172 { | 243 { | 
| 173     return createCryptoOperation(rawAlgorithm, key, Encrypt, 0, es); | 244     return startCryptoOperation(rawAlgorithm, key, Encrypt, 0, data, es); | 
| 174 } | 245 } | 
| 175 | 246 | 
| 176 PassRefPtr<CryptoOperation> SubtleCrypto::decrypt(const Dictionary& rawAlgorithm
     , Key* key, ExceptionState& es) | 247 ScriptObject SubtleCrypto::decrypt(const Dictionary& rawAlgorithm, Key* key, Arr
     ayBufferView* data, ExceptionState& es) | 
| 177 { | 248 { | 
| 178     return createCryptoOperation(rawAlgorithm, key, Decrypt, 0, es); | 249     return startCryptoOperation(rawAlgorithm, key, Decrypt, 0, data, es); | 
| 179 } | 250 } | 
| 180 | 251 | 
| 181 PassRefPtr<CryptoOperation> SubtleCrypto::sign(const Dictionary& rawAlgorithm, K
     ey* key, ExceptionState& es) | 252 ScriptObject SubtleCrypto::sign(const Dictionary& rawAlgorithm, Key* key, ArrayB
     ufferView* data, ExceptionState& es) | 
| 182 { | 253 { | 
| 183     return createCryptoOperation(rawAlgorithm, key, Sign, 0, es); | 254     return startCryptoOperation(rawAlgorithm, key, Sign, 0, data, es); | 
| 184 } | 255 } | 
| 185 | 256 | 
| 186 PassRefPtr<CryptoOperation> SubtleCrypto::verifySignature(const Dictionary& rawA
     lgorithm, Key* key, ArrayBufferView* signature, ExceptionState& es) | 257 ScriptObject SubtleCrypto::verifySignature(const Dictionary& rawAlgorithm, Key* 
     key, ArrayBufferView* signature, ArrayBufferView* data, ExceptionState& es) | 
| 187 { | 258 { | 
| 188     return createCryptoOperation(rawAlgorithm, key, Verify, signature, es); | 259     return startCryptoOperation(rawAlgorithm, key, Verify, signature, data, es); | 
| 189 } | 260 } | 
| 190 | 261 | 
| 191 PassRefPtr<CryptoOperation> SubtleCrypto::digest(const Dictionary& rawAlgorithm,
      ExceptionState& es) | 262 ScriptObject SubtleCrypto::digest(const Dictionary& rawAlgorithm, ArrayBufferVie
     w* data, ExceptionState& es) | 
| 192 { | 263 { | 
| 193     return createCryptoOperation(rawAlgorithm, 0, Digest, 0, es); | 264     return startCryptoOperation(rawAlgorithm, 0, Digest, 0, data, es); | 
| 194 } | 265 } | 
| 195 | 266 | 
| 196 ScriptObject SubtleCrypto::generateKey(const Dictionary& rawAlgorithm, bool extr
     actable, const Vector<String>& rawKeyUsages, ExceptionState& es) | 267 ScriptObject SubtleCrypto::generateKey(const Dictionary& rawAlgorithm, bool extr
     actable, const Vector<String>& rawKeyUsages, ExceptionState& es) | 
| 197 { | 268 { | 
| 198     WebKit::WebCrypto* platformCrypto = WebKit::Platform::current()->crypto(); | 269     WebKit::WebCrypto* platformCrypto = WebKit::Platform::current()->crypto(); | 
| 199     if (!platformCrypto) { | 270     if (!platformCrypto) { | 
| 200         es.throwDOMException(NotSupportedError); | 271         es.throwDOMException(NotSupportedError); | 
| 201         return ScriptObject(); | 272         return ScriptObject(); | 
| 202     } | 273     } | 
| 203 | 274 | 
| 204     WebKit::WebCryptoKeyUsageMask keyUsages; | 275     WebKit::WebCryptoKeyUsageMask keyUsages; | 
| 205     if (!Key::parseUsageMask(rawKeyUsages, keyUsages)) { | 276     if (!Key::parseUsageMask(rawKeyUsages, keyUsages)) { | 
| 206         es.throwTypeError(); | 277         es.throwTypeError(); | 
| 207         return ScriptObject(); | 278         return ScriptObject(); | 
| 208     } | 279     } | 
| 209 | 280 | 
| 210     WebKit::WebCryptoAlgorithm algorithm; | 281     WebKit::WebCryptoAlgorithm algorithm; | 
| 211     if (!normalizeAlgorithm(rawAlgorithm, GenerateKey, algorithm, es)) | 282     if (!normalizeAlgorithm(rawAlgorithm, GenerateKey, algorithm, es)) | 
| 212         return ScriptObject(); | 283         return ScriptObject(); | 
| 213 | 284 | 
| 214     RefPtr<KeyOperation> keyOp = KeyOperation::create(); | 285     RefPtr<CryptoResult> result = CryptoResult::create(); | 
| 215     WebKit::WebCryptoKeyOperationResult result(keyOp.get()); | 286     platformCrypto->generateKey(algorithm, extractable, keyUsages, result->resul
     t()); | 
| 216     platformCrypto->generateKey(algorithm, extractable, keyUsages, result); | 287     return result->promise(); | 
| 217     return keyOp->returnValue(es); |  | 
| 218 } | 288 } | 
| 219 | 289 | 
| 220 ScriptObject SubtleCrypto::importKey(const String& rawFormat, ArrayBufferView* k
     eyData, const Dictionary& rawAlgorithm, bool extractable, const Vector<String>& 
     rawKeyUsages, ExceptionState& es) | 290 ScriptObject SubtleCrypto::importKey(const String& rawFormat, ArrayBufferView* k
     eyData, const Dictionary& rawAlgorithm, bool extractable, const Vector<String>& 
     rawKeyUsages, ExceptionState& es) | 
| 221 { | 291 { | 
| 222     WebKit::WebCrypto* platformCrypto = WebKit::Platform::current()->crypto(); | 292     WebKit::WebCrypto* platformCrypto = WebKit::Platform::current()->crypto(); | 
| 223     if (!platformCrypto) { | 293     if (!platformCrypto) { | 
| 224         es.throwDOMException(NotSupportedError); | 294         es.throwDOMException(NotSupportedError); | 
| 225         return ScriptObject(); | 295         return ScriptObject(); | 
| 226     } | 296     } | 
| 227 | 297 | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
| 241         es.throwTypeError(); | 311         es.throwTypeError(); | 
| 242         return ScriptObject(); | 312         return ScriptObject(); | 
| 243     } | 313     } | 
| 244 | 314 | 
| 245     WebKit::WebCryptoAlgorithm algorithm; | 315     WebKit::WebCryptoAlgorithm algorithm; | 
| 246     if (!normalizeAlgorithm(rawAlgorithm, ImportKey, algorithm, es)) | 316     if (!normalizeAlgorithm(rawAlgorithm, ImportKey, algorithm, es)) | 
| 247         return ScriptObject(); | 317         return ScriptObject(); | 
| 248 | 318 | 
| 249     const unsigned char* keyDataBytes = static_cast<unsigned char*>(keyData->bas
     eAddress()); | 319     const unsigned char* keyDataBytes = static_cast<unsigned char*>(keyData->bas
     eAddress()); | 
| 250 | 320 | 
| 251     RefPtr<KeyOperation> keyOp = KeyOperation::create(); | 321     RefPtr<CryptoResult> result = CryptoResult::create(); | 
| 252     WebKit::WebCryptoKeyOperationResult result(keyOp.get()); | 322     platformCrypto->importKey(format, keyDataBytes, keyData->byteLength(), algor
     ithm, extractable, keyUsages, result->result()); | 
| 253     platformCrypto->importKey(format, keyDataBytes, keyData->byteLength(), algor
     ithm, extractable, keyUsages, result); | 323     return result->promise(); | 
| 254     return keyOp->returnValue(es); |  | 
| 255 } | 324 } | 
| 256 | 325 | 
| 257 } // namespace WebCore | 326 } // namespace WebCore | 
| OLD | NEW | 
|---|