Example #1
0
ScriptPromise SubtleCrypto::unwrapKey(ScriptState* scriptState, const String& rawFormat, const DOMArrayPiece& wrappedKey, CryptoKey* unwrappingKey, const AlgorithmIdentifier& rawUnwrapAlgorithm, const AlgorithmIdentifier& rawUnwrappedKeyAlgorithm, bool extractable, const Vector<String>& rawKeyUsages)
{
    RefPtrWillBeRawPtr<CryptoResultImpl> result = CryptoResultImpl::create(scriptState);
    ScriptPromise promise = result->promise();

    if (!canAccessWebCrypto(scriptState, result.get()))
        return promise;

    WebCryptoKeyFormat format;
    if (!CryptoKey::parseFormat(rawFormat, format, result.get()))
        return promise;

    WebCryptoKeyUsageMask keyUsages;
    if (!CryptoKey::parseUsageMask(rawKeyUsages, keyUsages, result.get()))
        return promise;

    WebCryptoAlgorithm unwrapAlgorithm;
    if (!parseAlgorithm(rawUnwrapAlgorithm, WebCryptoOperationUnwrapKey, unwrapAlgorithm, result.get()))
        return promise;

    WebCryptoAlgorithm unwrappedKeyAlgorithm;
    if (!parseAlgorithm(rawUnwrappedKeyAlgorithm, WebCryptoOperationImportKey, unwrappedKeyAlgorithm, result.get()))
        return promise;

    if (!unwrappingKey->canBeUsedForAlgorithm(unwrapAlgorithm, WebCryptoKeyUsageUnwrapKey, result.get()))
        return promise;

    histogramAlgorithmAndKey(scriptState->executionContext(), unwrapAlgorithm, unwrappingKey->key());
    histogramAlgorithm(scriptState->executionContext(), unwrappedKeyAlgorithm);
    Platform::current()->crypto()->unwrapKey(format, wrappedKey.bytes(), wrappedKey.byteLength(), unwrappingKey->key(), unwrapAlgorithm, unwrappedKeyAlgorithm, extractable, keyUsages, result->result());
    return promise;
}
ScriptPromise MediaKeys::setServerCertificate(ScriptState* scriptState, const DOMArrayPiece& serverCertificate)
{
    // From https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#dom-setservercertificate:
    // The setServerCertificate(serverCertificate) method provides a server
    // certificate to be used to encrypt messages to the license server.
    // It must run the following steps:
    // 1. If serverCertificate is an empty array, return a promise rejected
    //    with a new DOMException whose name is "InvalidAccessError".
    if (!serverCertificate.byteLength()) {
        return ScriptPromise::rejectWithDOMException(
            scriptState, DOMException::create(InvalidAccessError, "The serverCertificate parameter is empty."));
    }

    // 2. If the keySystem does not support server certificates, return a
    //    promise rejected with a new DOMException whose name is
    //    "NotSupportedError".
    //    (Let the CDM decide whether to support this or not.)

    // 3. Let certificate be a copy of the contents of the serverCertificate
    //    parameter.
    RefPtr<DOMArrayBuffer> serverCertificateBuffer = DOMArrayBuffer::create(serverCertificate.data(), serverCertificate.byteLength());

    // 4. Let promise be a new promise.
    SimpleContentDecryptionModuleResultPromise* result = new SimpleContentDecryptionModuleResultPromise(scriptState);
    ScriptPromise promise = result->promise();

    // 5. Run the following steps asynchronously (documented in timerFired()).
    m_pendingActions.append(PendingAction::CreatePendingSetServerCertificate(result, serverCertificateBuffer.release()));
    if (!m_timer.isActive())
        m_timer.startOneShot(0, FROM_HERE);

    // 6. Return promise.
    return promise;
}
Example #3
0
ScriptPromise SubtleCrypto::digest(ScriptState* scriptState, const AlgorithmIdentifier& rawAlgorithm, const DOMArrayPiece& data)
{
    RefPtrWillBeRawPtr<CryptoResultImpl> result = CryptoResultImpl::create(scriptState);
    ScriptPromise promise = result->promise();

    if (!canAccessWebCrypto(scriptState, result.get()))
        return promise;

    WebCryptoAlgorithm algorithm;
    if (!parseAlgorithm(rawAlgorithm, WebCryptoOperationDigest, algorithm, result.get()))
        return promise;

    histogramAlgorithm(scriptState->executionContext(), algorithm);
    Platform::current()->crypto()->digest(algorithm, data.bytes(), data.byteLength(), result->result());
    return promise;
}
Example #4
0
ScriptPromise SubtleCrypto::sign(ScriptState* scriptState, const AlgorithmIdentifier& rawAlgorithm, CryptoKey* key, const DOMArrayPiece& data)
{
    RefPtrWillBeRawPtr<CryptoResultImpl> result = CryptoResultImpl::create(scriptState);
    ScriptPromise promise = result->promise();

    if (!canAccessWebCrypto(scriptState, result.get()))
        return promise;

    WebCryptoAlgorithm algorithm;
    if (!parseAlgorithm(rawAlgorithm, WebCryptoOperationSign, algorithm, result.get()))
        return promise;

    if (!key->canBeUsedForAlgorithm(algorithm, WebCryptoKeyUsageSign, result.get()))
        return promise;

    histogramAlgorithmAndKey(scriptState->executionContext(), algorithm, key->key());
    Platform::current()->crypto()->sign(algorithm, key->key(), data.bytes(), data.byteLength(), result->result());
    return promise;
}
Example #5
0
ScriptPromise MediaKeys::setServerCertificate(
    ScriptState* scriptState,
    const DOMArrayPiece& serverCertificate) {
  // From https://w3c.github.io/encrypted-media/#setServerCertificate
  // The setServerCertificate(serverCertificate) method provides a server
  // certificate to be used to encrypt messages to the license server.
  // It must run the following steps:
  // 1. If the Key System implementation represented by this object's cdm
  //    implementation value does not support server certificates, return
  //    a promise resolved with false.
  // TODO(jrummell): Provide a way to determine if the CDM supports this.
  // http://crbug.com/647816.
  //
  // 2. If serverCertificate is an empty array, return a promise rejected
  //    with a new a newly created TypeError.
  if (!serverCertificate.byteLength()) {
    return ScriptPromise::reject(
        scriptState, V8ThrowException::createTypeError(
                         scriptState->isolate(),
                         "The serverCertificate parameter is empty."));
  }

  // 3. Let certificate be a copy of the contents of the serverCertificate
  //    parameter.
  DOMArrayBuffer* serverCertificateBuffer = DOMArrayBuffer::create(
      serverCertificate.data(), serverCertificate.byteLength());

  // 4. Let promise be a new promise.
  SetCertificateResultPromise* result =
      new SetCertificateResultPromise(scriptState, this);
  ScriptPromise promise = result->promise();

  // 5. Run the following steps asynchronously (documented in timerFired()).
  m_pendingActions.append(PendingAction::CreatePendingSetServerCertificate(
      result, serverCertificateBuffer));
  if (!m_timer.isActive())
    m_timer.startOneShot(0, BLINK_FROM_HERE);

  // 6. Return promise.
  return promise;
}
ScriptPromise BluetoothGATTCharacteristic::writeValue(ScriptState* scriptState, const DOMArrayPiece& value)
{
    WebBluetooth* webbluetooth = BluetoothSupplement::fromScriptState(scriptState);
    // Partial implementation of writeValue algorithm:
    // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothgattcharacteristic-writevalue

    // If bytes is more than 512 bytes long (the maximum length of an attribute
    // value, per Long Attribute Values) return a promise rejected with an
    // InvalidModificationError and abort.
    if (value.byteLength() > 512)
        return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(InvalidModificationError, "Value can't exceed 512 bytes."));

    // Let valueVector be a copy of the bytes held by value.
    WebVector<uint8_t> valueVector(value.bytes(), value.byteLength());

    ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);

    ScriptPromise promise = resolver->promise();
    webbluetooth->writeValue(m_webCharacteristic->characteristicInstanceID, valueVector, new CallbackPromiseAdapter<void, BluetoothError>(resolver));

    return promise;
}
ScriptPromise MediaKeySession::update(ScriptState* scriptState, const DOMArrayPiece& response)
{
    WTF_LOG(Media, "MediaKeySession(%p)::update", this);
    ASSERT(!m_isClosed);

    // From https://w3c.github.io/encrypted-media/#update:
    // Provides messages, including licenses, to the CDM. When this method is
    // invoked, the user agent must run the following steps:

    // 1. If this object's callable value is false, return a promise rejected
    //    with a new DOMException whose name is InvalidStateError.
    if (!m_isCallable)
        return CreateRejectedPromiseNotCallable(scriptState);

    // 2. If response is an empty array, return a promise rejected with a
    //    new DOMException whose name is InvalidAccessError.
    if (!response.byteLength()) {
        return ScriptPromise::rejectWithDOMException(
            scriptState, DOMException::create(InvalidAccessError, "The response parameter is empty."));
    }

    // 3. Let response copy be a copy of the contents of the response parameter.
    RefPtr<DOMArrayBuffer> responseCopy = DOMArrayBuffer::create(response.data(), response.byteLength());

    // 4. Let promise be a new promise.
    SimpleContentDecryptionModuleResultPromise* result = new SimpleContentDecryptionModuleResultPromise(scriptState);
    ScriptPromise promise = result->promise();

    // 5. Run the following steps asynchronously (documented in
    //    actionTimerFired())
    m_pendingActions.append(PendingAction::CreatePendingUpdate(result, responseCopy.release()));
    if (!m_actionTimer.isActive())
        m_actionTimer.startOneShot(0, BLINK_FROM_HERE);

    // 6. Return promise.
    return promise;
}
ScriptPromise SubtleCrypto::verifySignature(ScriptState* scriptState, const AlgorithmIdentifier& rawAlgorithm, CryptoKey* key, const DOMArrayPiece& signature, const DOMArrayPiece& data)
{
    CryptoResultImpl* result = CryptoResultImpl::create(scriptState);
    ScriptPromise promise = result->promise();

    if (!canAccessWebCrypto(scriptState, result))
        return promise;

    WebCryptoAlgorithm algorithm;
    if (!parseAlgorithm(rawAlgorithm, WebCryptoOperationVerify, algorithm, result))
        return promise;

    if (!key->canBeUsedForAlgorithm(algorithm, WebCryptoKeyUsageVerify, result))
        return promise;

    histogramAlgorithmAndKey(scriptState->executionContext(), algorithm, key->key());
    Platform::current()->crypto()->verifySignature(algorithm, key->key(), signature.bytes(), signature.byteLength(), data.bytes(), data.byteLength(), result->result());
    return promise;
}
ScriptPromise MediaKeySession::generateRequest(ScriptState* scriptState, const String& initDataTypeString, const DOMArrayPiece& initData)
{
    WTF_LOG(Media, "MediaKeySession(%p)::generateRequest %s", this, initDataTypeString.ascii().data());

    // From https://w3c.github.io/encrypted-media/#generateRequest:
    // Generates a request based on the initData. When this method is invoked,
    // the user agent must run the following steps:

    // 1. If this object's uninitialized value is false, return a promise
    //    rejected with a new DOMException whose name is "InvalidStateError".
    if (!m_isUninitialized)
        return CreateRejectedPromiseAlreadyInitialized(scriptState);

    // 2. Let this object's uninitialized be false.
    m_isUninitialized = false;

    // 3. If initDataType is an empty string, return a promise rejected with a
    //    new DOMException whose name is "InvalidAccessError".
    if (initDataTypeString.isEmpty()) {
        return ScriptPromise::rejectWithDOMException(
            scriptState, DOMException::create(InvalidAccessError, "The initDataType parameter is empty."));
    }

    // 4. If initData is an empty array, return a promise rejected with a new
    //    DOMException whose name is"InvalidAccessError".
    if (!initData.byteLength()) {
        return ScriptPromise::rejectWithDOMException(
            scriptState, DOMException::create(InvalidAccessError, "The initData parameter is empty."));
    }

    // 5. If the Key System implementation represented by this object's cdm
    //    implementation value does not support initDataType as an
    //    Initialization Data Type, return a promise rejected with a new
    //    DOMException whose name is NotSupportedError. String comparison
    //    is case-sensitive.
    //    (blink side doesn't know what the CDM supports, so the proper check
    //     will be done on the Chromium side. However, we can verify that
    //     |initDataType| is one of the registered values.)
    WebEncryptedMediaInitDataType initDataType = EncryptedMediaUtils::convertToInitDataType(initDataTypeString);
    if (initDataType == WebEncryptedMediaInitDataType::Unknown) {
        return ScriptPromise::rejectWithDOMException(
            scriptState, DOMException::create(NotSupportedError, "The initialization data type '" + initDataTypeString + "' is not supported."));
    }

    // 6. Let init data be a copy of the contents of the initData parameter.
    RefPtr<DOMArrayBuffer> initDataBuffer = DOMArrayBuffer::create(initData.data(), initData.byteLength());

    // 7. Let session type be this object's session type.
    //    (Done in constructor.)

    // 8. Let promise be a new promise.
    NewSessionResultPromise* result = new NewSessionResultPromise(scriptState, this);
    ScriptPromise promise = result->promise();

    // 9. Run the following steps asynchronously (documented in
    //    actionTimerFired())
    m_pendingActions.append(PendingAction::CreatePendingGenerateRequest(result, initDataType, initDataBuffer.release()));
    ASSERT(!m_actionTimer.isActive());
    m_actionTimer.startOneShot(0, BLINK_FROM_HERE);

    // 10. Return promise.
    return promise;
}