Changeset 159637 in webkit


Ignore:
Timestamp:
Nov 21, 2013 11:05:43 AM (10 years ago)
Author:
ap@apple.com
Message:

Implement WebCrypto unwrapKey
https://bugs.webkit.org/show_bug.cgi?id=124725

Reviewed by Anders Carlsson.

Source/WebCore:

Tests: crypto/subtle/aes-cbc-unwrap-failure.html

crypto/subtle/aes-cbc-unwrap-rsa.html

  • bindings/js/JSCryptoAlgorithmDictionary.cpp:
  • bindings/js/JSCryptoAlgorithmDictionary.h:

Removed calls for wrap/unwrap parameter parsing, these are just the same as encrypt/decrypt.

  • bindings/js/JSCryptoOperationData.cpp:

(WebCore::cryptoOperationDataFromJSValue):

  • bindings/js/JSCryptoOperationData.h:
  • crypto/CryptoKeySerialization.h:

More Vector<char> elimination.

  • bindings/js/JSDOMPromise.cpp:
  • bindings/js/JSDOMPromise.h:

Removed unneccessary copy constructor and assignment operator, they are no diffdrent
than compiler generated ones.

  • bindings/js/JSSubtleCryptoCustom.cpp:

(WebCore::cryptoKeyUsagesFromJSValue): Minor style fixes.
(WebCore::JSSubtleCrypto::encrypt): Ditto.
(WebCore::JSSubtleCrypto::decrypt): Ditto.
(WebCore::JSSubtleCrypto::sign): Ditto.
(WebCore::JSSubtleCrypto::verify): Ditto.
(WebCore::JSSubtleCrypto::generateKey): Ditto.
(WebCore::importKey): Separated actual import operation and the parts that read
arguments from ExecState, and call the promise. Logically, this should be outside
of bindings code even, but JWK makes that quite challenging.
(WebCore::JSSubtleCrypto::importKey): This only does the more mundane arguments
and return parts now.
(WebCore::JSSubtleCrypto::exportKey): Minor style fixes.
(WebCore::JSSubtleCrypto::unwrapKey): Chain decrypt and import.

  • crypto/CryptoAlgorithm.cpp:

(WebCore::CryptoAlgorithm::encryptForWrapKey):
(WebCore::CryptoAlgorithm::decryptForUnwrapKey):

  • crypto/CryptoAlgorithm.h:

There are algorithms that expose wrap/unwrap, but not encrypt/decrypt. These will
override these new functions, and leave encrypt/decrypt to raise NOT_SUPPORTED_ERR.

  • crypto/SubtleCrypto.idl: Added unwrapKey.

LayoutTests:

  • crypto/subtle/aes-cbc-unwrap-failure-expected.txt: Added.
  • crypto/subtle/aes-cbc-unwrap-failure.html: Added.
  • crypto/subtle/aes-cbc-unwrap-rsa-expected.txt: Added.
  • crypto/subtle/aes-cbc-unwrap-rsa.html: Added.
Location:
trunk
Files:
4 added
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r159628 r159637  
     12013-11-21  Alexey Proskuryakov  <ap@apple.com>
     2
     3        Implement WebCrypto unwrapKey
     4        https://bugs.webkit.org/show_bug.cgi?id=124725
     5
     6        Reviewed by Anders Carlsson.
     7
     8        * crypto/subtle/aes-cbc-unwrap-failure-expected.txt: Added.
     9        * crypto/subtle/aes-cbc-unwrap-failure.html: Added.
     10        * crypto/subtle/aes-cbc-unwrap-rsa-expected.txt: Added.
     11        * crypto/subtle/aes-cbc-unwrap-rsa.html: Added.
     12
    1132013-11-21  Radu Stavila  <stavila@adobe.com>
    214
  • trunk/Source/WebCore/ChangeLog

    r159632 r159637  
     12013-11-21  Alexey Proskuryakov  <ap@apple.com>
     2
     3        Implement WebCrypto unwrapKey
     4        https://bugs.webkit.org/show_bug.cgi?id=124725
     5
     6        Reviewed by Anders Carlsson.
     7
     8        Tests: crypto/subtle/aes-cbc-unwrap-failure.html
     9               crypto/subtle/aes-cbc-unwrap-rsa.html
     10
     11        * bindings/js/JSCryptoAlgorithmDictionary.cpp:
     12        * bindings/js/JSCryptoAlgorithmDictionary.h:
     13        Removed calls for wrap/unwrap parameter parsing, these are just the same as encrypt/decrypt.
     14
     15        * bindings/js/JSCryptoOperationData.cpp:
     16        (WebCore::cryptoOperationDataFromJSValue):
     17        * bindings/js/JSCryptoOperationData.h:
     18        * crypto/CryptoKeySerialization.h:
     19        More Vector<char> elimination.
     20
     21        * bindings/js/JSDOMPromise.cpp:
     22        * bindings/js/JSDOMPromise.h:
     23        Removed unneccessary copy constructor and assignment operator, they are no diffdrent
     24        than compiler generated ones.
     25
     26        * bindings/js/JSSubtleCryptoCustom.cpp:
     27        (WebCore::cryptoKeyUsagesFromJSValue): Minor style fixes.
     28        (WebCore::JSSubtleCrypto::encrypt): Ditto.
     29        (WebCore::JSSubtleCrypto::decrypt): Ditto.
     30        (WebCore::JSSubtleCrypto::sign): Ditto.
     31        (WebCore::JSSubtleCrypto::verify): Ditto.
     32        (WebCore::JSSubtleCrypto::generateKey): Ditto.
     33        (WebCore::importKey): Separated actual import operation and the parts that read
     34        arguments from ExecState, and call the promise. Logically, this should be outside
     35        of bindings code even, but JWK makes that quite challenging.
     36        (WebCore::JSSubtleCrypto::importKey): This only does the more mundane arguments
     37        and return parts now.
     38        (WebCore::JSSubtleCrypto::exportKey): Minor style fixes.
     39        (WebCore::JSSubtleCrypto::unwrapKey): Chain decrypt and import.
     40
     41        * crypto/CryptoAlgorithm.cpp:
     42        (WebCore::CryptoAlgorithm::encryptForWrapKey):
     43        (WebCore::CryptoAlgorithm::decryptForUnwrapKey):
     44        * crypto/CryptoAlgorithm.h:
     45        There are algorithms that expose wrap/unwrap, but not encrypt/decrypt. These will
     46        override these new functions, and leave encrypt/decrypt to raise NOT_SUPPORTED_ERR.
     47
     48        * crypto/SubtleCrypto.idl: Added unwrapKey.
     49
    1502013-11-21  Robert Sipka  <sipka@inf.u-szeged.hu>
    251
  • trunk/Source/WebCore/bindings/js/JSCryptoAlgorithmDictionary.cpp

    r159213 r159637  
    585585}
    586586
    587 std::unique_ptr<CryptoAlgorithmParameters> JSCryptoAlgorithmDictionary::createParametersForWrapKey(ExecState* exec, CryptoAlgorithmIdentifier algorithm, JSValue)
    588 {
    589     switch (algorithm) {
    590     case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
    591     case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
    592     case CryptoAlgorithmIdentifier::RSA_PSS:
    593     case CryptoAlgorithmIdentifier::RSA_OAEP:
    594     case CryptoAlgorithmIdentifier::ECDSA:
    595     case CryptoAlgorithmIdentifier::ECDH:
    596     case CryptoAlgorithmIdentifier::AES_CTR:
    597     case CryptoAlgorithmIdentifier::AES_CBC:
    598     case CryptoAlgorithmIdentifier::AES_CMAC:
    599     case CryptoAlgorithmIdentifier::AES_GCM:
    600     case CryptoAlgorithmIdentifier::AES_CFB:
    601     case CryptoAlgorithmIdentifier::HMAC:
    602     case CryptoAlgorithmIdentifier::DH:
    603     case CryptoAlgorithmIdentifier::SHA_1:
    604     case CryptoAlgorithmIdentifier::SHA_224:
    605     case CryptoAlgorithmIdentifier::SHA_256:
    606     case CryptoAlgorithmIdentifier::SHA_384:
    607     case CryptoAlgorithmIdentifier::SHA_512:
    608     case CryptoAlgorithmIdentifier::CONCAT:
    609     case CryptoAlgorithmIdentifier::HKDF_CTR:
    610     case CryptoAlgorithmIdentifier::PBKDF2:
    611         setDOMException(exec, NOT_SUPPORTED_ERR);
    612         return nullptr;
    613     }
    614 }
    615 
    616 std::unique_ptr<CryptoAlgorithmParameters> JSCryptoAlgorithmDictionary::createParametersForUnwrapKey(ExecState* exec, CryptoAlgorithmIdentifier algorithm, JSValue)
    617 {
    618     switch (algorithm) {
    619     case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
    620     case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
    621     case CryptoAlgorithmIdentifier::RSA_PSS:
    622     case CryptoAlgorithmIdentifier::RSA_OAEP:
    623     case CryptoAlgorithmIdentifier::ECDSA:
    624     case CryptoAlgorithmIdentifier::ECDH:
    625     case CryptoAlgorithmIdentifier::AES_CTR:
    626     case CryptoAlgorithmIdentifier::AES_CBC:
    627     case CryptoAlgorithmIdentifier::AES_CMAC:
    628     case CryptoAlgorithmIdentifier::AES_GCM:
    629     case CryptoAlgorithmIdentifier::AES_CFB:
    630     case CryptoAlgorithmIdentifier::HMAC:
    631     case CryptoAlgorithmIdentifier::DH:
    632     case CryptoAlgorithmIdentifier::SHA_1:
    633     case CryptoAlgorithmIdentifier::SHA_224:
    634     case CryptoAlgorithmIdentifier::SHA_256:
    635     case CryptoAlgorithmIdentifier::SHA_384:
    636     case CryptoAlgorithmIdentifier::SHA_512:
    637     case CryptoAlgorithmIdentifier::CONCAT:
    638     case CryptoAlgorithmIdentifier::HKDF_CTR:
    639     case CryptoAlgorithmIdentifier::PBKDF2:
    640         setDOMException(exec, NOT_SUPPORTED_ERR);
    641         return nullptr;
    642     }
    643 }
    644 
    645587}
    646588
  • trunk/Source/WebCore/bindings/js/JSCryptoAlgorithmDictionary.h

    r158366 r159637  
    5454    static std::unique_ptr<CryptoAlgorithmParameters> createParametersForImportKey(JSC::ExecState*, CryptoAlgorithmIdentifier, JSC::JSValue);
    5555    static std::unique_ptr<CryptoAlgorithmParameters> createParametersForExportKey(JSC::ExecState*, CryptoAlgorithmIdentifier, JSC::JSValue);
    56     static std::unique_ptr<CryptoAlgorithmParameters> createParametersForWrapKey(JSC::ExecState*, CryptoAlgorithmIdentifier, JSC::JSValue);
    57     static std::unique_ptr<CryptoAlgorithmParameters> createParametersForUnwrapKey(JSC::ExecState*, CryptoAlgorithmIdentifier, JSC::JSValue);
    5856};
    5957
  • trunk/Source/WebCore/bindings/js/JSCryptoOperationData.cpp

    r159379 r159637  
    3838{
    3939    if (ArrayBuffer* buffer = toArrayBuffer(value))
    40         result = std::make_pair(static_cast<char*>(buffer->data()), buffer->byteLength());
     40        result = std::make_pair(static_cast<uint8_t*>(buffer->data()), buffer->byteLength());
    4141    else if (RefPtr<ArrayBufferView> bufferView = toArrayBufferView(value))
    42         result = std::make_pair(static_cast<char*>(bufferView->baseAddress()), bufferView->byteLength());
     42        result = std::make_pair(static_cast<uint8_t*>(bufferView->baseAddress()), bufferView->byteLength());
    4343    else {
    4444        throwTypeError(exec, "Only ArrayBuffer and ArrayBufferView objects can be passed as CryptoOperationData");
  • trunk/Source/WebCore/bindings/js/JSCryptoOperationData.h

    r159379 r159637  
    3636namespace WebCore {
    3737
    38 typedef std::pair<const char*, size_t> CryptoOperationData;
     38typedef std::pair<const uint8_t*, size_t> CryptoOperationData;
    3939
    4040bool cryptoOperationDataFromJSValue(JSC::ExecState*, JSC::JSValue, CryptoOperationData&);
  • trunk/Source/WebCore/bindings/js/JSDOMPromise.cpp

    r159578 r159637  
    3535}
    3636
    37 PromiseWrapper::PromiseWrapper(const PromiseWrapper& other)
    38     : m_globalObject(other.m_globalObject)
    39     , m_promise(other.m_promise)
    40 {
    4137}
    42 
    43 PromiseWrapper& PromiseWrapper::operator=(const PromiseWrapper& other)
    44 {
    45     m_globalObject = other.m_globalObject;
    46     m_promise = other.m_promise;
    47     return *this;
    48 }
    49 
    50 }
  • trunk/Source/WebCore/bindings/js/JSDOMPromise.h

    r159578 r159637  
    4040public:
    4141    PromiseWrapper(JSDOMGlobalObject*, JSC::JSPromise*);
    42 
    43     PromiseWrapper(const PromiseWrapper&);
    44     PromiseWrapper& operator=(const PromiseWrapper&);
    4542
    4643    template<class FulfillResultType>
  • trunk/Source/WebCore/bindings/js/JSSubtleCryptoCustom.cpp

    r159578 r159637  
    103103    result = 0;
    104104
    105     JSC::JSArray* array = asArray(value);
     105    JSArray* array = asArray(value);
    106106    for (size_t i = 0; i < array->length(); ++i) {
    107         JSC::JSValue element = array->getIndex(exec, i);
     107        JSValue element = array->getIndex(exec, i);
    108108        String usageString = element.toString(exec)->value(exec);
    109109        if (exec->hadException())
     
    151151
    152152    if (!key->allows(CryptoKeyUsageEncrypt)) {
    153         m_impl->document()->addConsoleMessage(JSMessageSource, ErrorMessageLevel, "Key usages does not include 'encrypt'");
     153        m_impl->document()->addConsoleMessage(JSMessageSource, ErrorMessageLevel, "Key usages do not include 'encrypt'");
    154154        setDOMException(exec, NOT_SUPPORTED_ERR);
    155155        return jsUndefined();
     
    203203
    204204    if (!key->allows(CryptoKeyUsageDecrypt)) {
    205         m_impl->document()->addConsoleMessage(JSMessageSource, ErrorMessageLevel, "Key usages does not include 'decrypt'");
     205        m_impl->document()->addConsoleMessage(JSMessageSource, ErrorMessageLevel, "Key usages do not include 'decrypt'");
    206206        setDOMException(exec, NOT_SUPPORTED_ERR);
    207207        return jsUndefined();
     
    255255
    256256    if (!key->allows(CryptoKeyUsageSign)) {
    257         m_impl->document()->addConsoleMessage(JSMessageSource, ErrorMessageLevel, "Key usages does not include 'sign'");
     257        m_impl->document()->addConsoleMessage(JSMessageSource, ErrorMessageLevel, "Key usages do not include 'sign'");
    258258        setDOMException(exec, NOT_SUPPORTED_ERR);
    259259        return jsUndefined();
     
    307307
    308308    if (!key->allows(CryptoKeyUsageVerify)) {
    309         m_impl->document()->addConsoleMessage(JSMessageSource, ErrorMessageLevel, "Key usages does not include 'verify'");
     309        m_impl->document()->addConsoleMessage(JSMessageSource, ErrorMessageLevel, "Key usages do not include 'verify'");
    310310        setDOMException(exec, NOT_SUPPORTED_ERR);
    311311        return jsUndefined();
     
    385385}
    386386
    387 JSValue JSSubtleCrypto::generateKey(JSC::ExecState* exec)
     387JSValue JSSubtleCrypto::generateKey(ExecState* exec)
    388388{
    389389    if (exec->argumentCount() < 1)
     
    441441}
    442442
    443 JSValue JSSubtleCrypto::importKey(JSC::ExecState* exec)
    444 {
    445     if (exec->argumentCount() < 3)
    446         return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
    447 
    448     CryptoKeyFormat keyFormat;
    449     if (!cryptoKeyFormatFromJSValue(exec, exec->argument(0), keyFormat)) {
    450         ASSERT(exec->hadException());
    451         return jsUndefined();
    452     }
    453 
    454     CryptoOperationData data;
    455     if (!cryptoOperationDataFromJSValue(exec, exec->uncheckedArgument(1), data)) {
    456         ASSERT(exec->hadException());
    457         return jsUndefined();
    458     }
    459 
    460     std::unique_ptr<CryptoAlgorithm> algorithm;
    461     std::unique_ptr<CryptoAlgorithmParameters> parameters;
    462     if (!exec->uncheckedArgument(2).isNull()) {
    463         algorithm = createAlgorithmFromJSValue(exec, exec->uncheckedArgument(2));
    464         if (!algorithm) {
    465             ASSERT(exec->hadException());
    466             return jsUndefined();
    467         }
    468         parameters = JSCryptoAlgorithmDictionary::createParametersForImportKey(exec, algorithm->identifier(), exec->uncheckedArgument(2));
    469         if (!parameters) {
    470             ASSERT(exec->hadException());
    471             return jsUndefined();
    472         }
    473     }
     443static void importKey(ExecState* exec, CryptoKeyFormat keyFormat, CryptoOperationData data, CryptoAlgorithm* algorithmPtr, CryptoAlgorithmParameters* parametersPtr, bool extractable, CryptoKeyUsage keyUsages, CryptoAlgorithm::KeyCallback callback, CryptoAlgorithm::VoidCallback failureCallback)
     444{
     445    std::unique_ptr<CryptoAlgorithm> algorithm(algorithmPtr);
     446    std::unique_ptr<CryptoAlgorithmParameters> parameters(parametersPtr);
    474447
    475448    std::unique_ptr<CryptoKeySerialization> keySerialization;
     
    482455        if (jwkString.isNull()) {
    483456            throwTypeError(exec, "JWK JSON serialization is not valid UTF-8");
    484             return jsUndefined();
     457            return;
    485458        }
    486459        keySerialization = JSCryptoKeySerializationJWK::create(exec, jwkString);
    487460        if (exec->hadException())
    488             return jsUndefined();
     461            return;
    489462        break;
    490463    }
    491464    default:
    492465        throwTypeError(exec, "Unsupported key format for import");
    493         return jsUndefined();
     466        return;
    494467    }
    495468
     
    499472        if (!exec->hadException())
    500473            throwTypeError(exec, "Algorithm specified in key is not compatible with one passed to importKey as argument");
    501         return jsUndefined();
     474        return;
    502475    }
    503476    if (exec->hadException())
    504         return jsUndefined();
     477        return;
    505478
    506479    if (!algorithm) {
    507480        throwTypeError(exec, "Neither key nor function argument has crypto algorithm specified");
    508         return jsUndefined();
     481        return;
    509482    }
    510483    ASSERT(parameters);
     484
     485    keySerialization->reconcileExtractable(extractable);
     486    if (exec->hadException())
     487        return;
     488
     489    keySerialization->reconcileUsages(keyUsages);
     490    if (exec->hadException())
     491        return;
     492
     493    auto keyData = keySerialization->keyData();
     494    if (exec->hadException())
     495        return;
     496
     497    ExceptionCode ec = 0;
     498    algorithm->importKey(*parameters, *keyData, extractable, keyUsages, std::move(callback), std::move(failureCallback), ec);
     499    if (ec)
     500        setDOMException(exec, ec);
     501}
     502
     503JSValue JSSubtleCrypto::importKey(ExecState* exec)
     504{
     505    if (exec->argumentCount() < 3)
     506        return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
     507
     508    CryptoKeyFormat keyFormat;
     509    if (!cryptoKeyFormatFromJSValue(exec, exec->argument(0), keyFormat)) {
     510        ASSERT(exec->hadException());
     511        return jsUndefined();
     512    }
     513
     514    CryptoOperationData data;
     515    if (!cryptoOperationDataFromJSValue(exec, exec->uncheckedArgument(1), data)) {
     516        ASSERT(exec->hadException());
     517        return jsUndefined();
     518    }
     519
     520    std::unique_ptr<CryptoAlgorithm> algorithm;
     521    std::unique_ptr<CryptoAlgorithmParameters> parameters;
     522    if (!exec->uncheckedArgument(2).isNull()) {
     523        algorithm = createAlgorithmFromJSValue(exec, exec->uncheckedArgument(2));
     524        if (!algorithm) {
     525            ASSERT(exec->hadException());
     526            return jsUndefined();
     527        }
     528        parameters = JSCryptoAlgorithmDictionary::createParametersForImportKey(exec, algorithm->identifier(), exec->uncheckedArgument(2));
     529        if (!parameters) {
     530            ASSERT(exec->hadException());
     531            return jsUndefined();
     532        }
     533    }
    511534
    512535    bool extractable = false;
     
    516539            return jsUndefined();
    517540    }
    518     keySerialization->reconcileExtractable(extractable);
    519     if (exec->hadException())
    520         return jsUndefined();
    521541
    522542    CryptoKeyUsage keyUsages = 0;
     
    527547        }
    528548    }
    529     keySerialization->reconcileUsages(keyUsages);
    530     if (exec->hadException())
    531         return jsUndefined();
    532 
    533     auto keyData = keySerialization->keyData();
    534     if (exec->hadException())
    535         return jsUndefined();
    536549
    537550    JSPromise* promise = JSPromise::createWithResolver(exec->vm(), globalObject());
     
    544557    };
    545558
    546     ExceptionCode ec = 0;
    547     algorithm->importKey(*parameters, *keyData, extractable, keyUsages, std::move(successCallback), std::move(failureCallback), ec);
    548     if (ec) {
    549         setDOMException(exec, ec);
    550         return jsUndefined();
    551     }
    552 
    553     return promise;
    554 }
    555 
    556 JSValue JSSubtleCrypto::exportKey(JSC::ExecState* exec)
     559    WebCore::importKey(exec, keyFormat, data, algorithm.release(), parameters.release(), extractable, keyUsages, successCallback, failureCallback);
     560    if (exec->hadException())
     561        return jsUndefined();
     562
     563    return promise;
     564}
     565
     566JSValue JSSubtleCrypto::exportKey(ExecState* exec)
    557567{
    558568    if (exec->argumentCount() < 2)
     
    580590    switch (keyFormat) {
    581591    case CryptoKeyFormat::Raw: {
    582         Vector<unsigned char> result;
     592        Vector<uint8_t> result;
    583593        if (CryptoKeySerializationRaw::serialize(*key, result))
    584594            promiseWrapper.fulfill(result);
     
    594604            return jsUndefined();
    595605        CString utf8String = result.utf8(StrictConversion);
    596         Vector<unsigned char> resultBuffer;
     606        Vector<uint8_t> resultBuffer;
    597607        resultBuffer.append(utf8String.data(), utf8String.length());
    598608        promiseWrapper.fulfill(resultBuffer);
     
    607617}
    608618
     619JSValue JSSubtleCrypto::unwrapKey(ExecState* exec)
     620{
     621    if (exec->argumentCount() < 5)
     622        return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
     623
     624    CryptoKeyFormat keyFormat;
     625    if (!cryptoKeyFormatFromJSValue(exec, exec->argument(0), keyFormat)) {
     626        ASSERT(exec->hadException());
     627        return jsUndefined();
     628    }
     629
     630    CryptoOperationData wrappedKeyData;
     631    if (!cryptoOperationDataFromJSValue(exec, exec->uncheckedArgument(1), wrappedKeyData)) {
     632        ASSERT(exec->hadException());
     633        return jsUndefined();
     634    }
     635
     636    RefPtr<CryptoKey> unwrappingKey = toCryptoKey(exec->uncheckedArgument(2));
     637    if (!unwrappingKey)
     638        return throwTypeError(exec);
     639
     640    if (!unwrappingKey->allows(CryptoKeyUsageUnwrapKey)) {
     641        m_impl->document()->addConsoleMessage(JSMessageSource, ErrorMessageLevel, "Key usages do not include 'unwrapKey'");
     642        setDOMException(exec, NOT_SUPPORTED_ERR);
     643        return jsUndefined();
     644    }
     645
     646    std::unique_ptr<CryptoAlgorithm> unwrapAlgorithm;
     647    std::unique_ptr<CryptoAlgorithmParameters> unwrapAlgorithmParameters;
     648    unwrapAlgorithm = createAlgorithmFromJSValue(exec, exec->uncheckedArgument(3));
     649    if (!unwrapAlgorithm) {
     650        ASSERT(exec->hadException());
     651        return jsUndefined();
     652    }
     653    unwrapAlgorithmParameters = JSCryptoAlgorithmDictionary::createParametersForDecrypt(exec, unwrapAlgorithm->identifier(), exec->uncheckedArgument(3));
     654    if (!unwrapAlgorithmParameters) {
     655        ASSERT(exec->hadException());
     656        return jsUndefined();
     657    }
     658
     659    std::unique_ptr<CryptoAlgorithm> unwrappedKeyAlgorithm;
     660    std::unique_ptr<CryptoAlgorithmParameters> unwrappedKeyAlgorithmParameters;
     661    if (!exec->uncheckedArgument(4).isNull()) {
     662        unwrappedKeyAlgorithm = createAlgorithmFromJSValue(exec, exec->uncheckedArgument(4));
     663        if (!unwrappedKeyAlgorithm) {
     664            ASSERT(exec->hadException());
     665            return jsUndefined();
     666        }
     667        unwrappedKeyAlgorithmParameters = JSCryptoAlgorithmDictionary::createParametersForImportKey(exec, unwrappedKeyAlgorithm->identifier(), exec->uncheckedArgument(4));
     668        if (!unwrappedKeyAlgorithmParameters) {
     669            ASSERT(exec->hadException());
     670            return jsUndefined();
     671        }
     672    }
     673
     674    bool extractable = false;
     675    if (exec->argumentCount() >= 6) {
     676        extractable = exec->uncheckedArgument(5).toBoolean(exec);
     677        if (exec->hadException())
     678            return jsUndefined();
     679    }
     680
     681    CryptoKeyUsage keyUsages = 0;
     682    if (exec->argumentCount() >= 7) {
     683        if (!cryptoKeyUsagesFromJSValue(exec, exec->argument(6), keyUsages)) {
     684            ASSERT(exec->hadException());
     685            return jsUndefined();
     686        }
     687    }
     688
     689    JSPromise* promise = JSPromise::createWithResolver(exec->vm(), globalObject());
     690    PromiseWrapper promiseWrapper(globalObject(), promise);
     691    Strong<JSDOMGlobalObject> domGlobalObject(exec->vm(), globalObject());
     692
     693    CryptoAlgorithm* unwrappedKeyAlgorithmPtr = unwrappedKeyAlgorithm.release();
     694    CryptoAlgorithmParameters* unwrappedKeyAlgorithmParametersPtr = unwrappedKeyAlgorithmParameters.release();
     695
     696    auto failureCallback = [promiseWrapper]() mutable {
     697        promiseWrapper.reject(nullptr);
     698    };
     699
     700    auto successCallback = [domGlobalObject, keyFormat, unwrappedKeyAlgorithmPtr, unwrappedKeyAlgorithmParametersPtr, extractable, keyUsages, promiseWrapper, failureCallback](const Vector<uint8_t>& result) mutable {
     701        auto importSuccessCallback = [promiseWrapper](CryptoKey& key) mutable {
     702            promiseWrapper.fulfill(&key);
     703        };
     704        ExecState* exec = domGlobalObject->globalExec();
     705        WebCore::importKey(exec, keyFormat, std::make_pair(result.data(), result.size()), unwrappedKeyAlgorithmPtr, unwrappedKeyAlgorithmParametersPtr, extractable, keyUsages, importSuccessCallback, failureCallback);
     706        if (exec->hadException()) {
     707            // FIXME: Report exception details to console, and possibly to calling script once there is a standardized way to pass errors to WebCrypto promise reject functions.
     708            exec->clearException();
     709            failureCallback();
     710        }
     711    };
     712
     713    ExceptionCode ec = 0;
     714    unwrapAlgorithm->decryptForUnwrapKey(*unwrapAlgorithmParameters, *unwrappingKey, wrappedKeyData, std::move(successCallback), std::move(failureCallback), ec);
     715    if (ec) {
     716        setDOMException(exec, ec);
     717        return jsUndefined();
     718    }
     719
     720    return promise;
     721}
     722
    609723} // namespace WebCore
    610724
  • trunk/Source/WebCore/crypto/CryptoAlgorithm.cpp

    r159578 r159637  
    8686}
    8787
     88void CryptoAlgorithm::encryptForWrapKey(const CryptoAlgorithmParameters& parameters, const CryptoKey& key, const CryptoOperationData& data, VectorCallback callback, VoidCallback failureCallback, ExceptionCode& ec)
     89{
     90    encrypt(parameters, key, data, callback, failureCallback, ec);
     91}
     92
     93void CryptoAlgorithm::decryptForUnwrapKey(const CryptoAlgorithmParameters& parameters, const CryptoKey& key, const CryptoOperationData& data, VectorCallback callback, VoidCallback failureCallback, ExceptionCode& ec)
     94{
     95    decrypt(parameters, key, data, callback, failureCallback, ec);
     96}
     97
    8898}
    8999
  • trunk/Source/WebCore/crypto/CryptoAlgorithm.h

    r159578 r159637  
    4545
    4646// Data is mutable, so async operations should copy it first.
    47 typedef std::pair<const char*, size_t> CryptoOperationData;
     47typedef std::pair<const uint8_t*, size_t> CryptoOperationData;
    4848
    4949class CryptoAlgorithm {
     
    7070    virtual void importKey(const CryptoAlgorithmParameters&, const CryptoKeyData&, bool extractable, CryptoKeyUsage, KeyCallback, VoidCallback failureCallback, ExceptionCode&);
    7171
     72    // These are only different from encrypt/decrypt because some algorithms may not expose encrypt/decrypt.
     73    virtual void encryptForWrapKey(const CryptoAlgorithmParameters&, const CryptoKey&, const CryptoOperationData&, VectorCallback, VoidCallback failureCallback, ExceptionCode&);
     74    virtual void decryptForUnwrapKey(const CryptoAlgorithmParameters&, const CryptoKey&, const CryptoOperationData&, VectorCallback, VoidCallback failureCallback, ExceptionCode&);
     75
    7276protected:
    7377    CryptoAlgorithm();
  • trunk/Source/WebCore/crypto/CryptoKeySerialization.h

    r159213 r159637  
    3838class CryptoKeyData;
    3939
    40 typedef std::pair<const char*, size_t> CryptoOperationData;
     40typedef std::pair<const uint8_t*, size_t> CryptoOperationData;
    4141
    4242class CryptoKeySerialization {
  • trunk/Source/WebCore/crypto/SubtleCrypto.idl

    r159310 r159637  
    3838    [Custom] Promise importKey(KeyFormat format, CryptoOperationData keyData, AlgorithmIdentifier? algorithm, optional boolean extractable, optional KeyUsage[] keyUsages);
    3939    [Custom] Promise exportKey(KeyFormat format, Key key);
     40    [Custom] Promise unwrapKey(KeyFormat format, CryptoOperationData wrappedKey, Key unwrappingKey, AlgorithmIdentifier unwrapAlgorithm, AlgorithmIdentifier? unwrappedKeyAlgorithm, optional boolean extractable, optional KeyUsage[] keyUsages);
    4041};
Note: See TracChangeset for help on using the changeset viewer.