CryptoAlgorithmECDSA.cpp [plain text]
#include "config.h"
#include "CryptoAlgorithmECDSA.h"
#if ENABLE(SUBTLE_CRYPTO)
#include "CryptoAlgorithmEcKeyParams.h"
#include "CryptoKeyEC.h"
#include "ExceptionCode.h"
namespace WebCore {
static const char* const ALG256 = "ES256";
static const char* const ALG384 = "ES384";
static const char* const P256 = "P-256";
static const char* const P384 = "P-384";
Ref<CryptoAlgorithm> CryptoAlgorithmECDSA::create()
{
return adoptRef(*new CryptoAlgorithmECDSA);
}
CryptoAlgorithmIdentifier CryptoAlgorithmECDSA::identifier() const
{
return s_identifier;
}
void CryptoAlgorithmECDSA::sign(std::unique_ptr<CryptoAlgorithmParameters>&& parameters, Ref<CryptoKey>&& key, Vector<uint8_t>&& data, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue)
{
if (key->type() != CryptoKeyType::Private) {
exceptionCallback(INVALID_ACCESS_ERR);
return;
}
platformSign(WTFMove(parameters), WTFMove(key), WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), context, workQueue);
}
void CryptoAlgorithmECDSA::verify(std::unique_ptr<CryptoAlgorithmParameters>&& parameters, Ref<CryptoKey>&& key, Vector<uint8_t>&& signature, Vector<uint8_t>&& data, BoolCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue)
{
if (key->type() != CryptoKeyType::Public) {
exceptionCallback(INVALID_ACCESS_ERR);
return;
}
platformVerify(WTFMove(parameters), WTFMove(key), WTFMove(signature), WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), context, workQueue);
}
void CryptoAlgorithmECDSA::generateKey(const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyOrKeyPairCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext&)
{
const auto& ecParameters = downcast<CryptoAlgorithmEcKeyParams>(parameters);
if (usages & (CryptoKeyUsageEncrypt | CryptoKeyUsageDecrypt | CryptoKeyUsageDeriveKey | CryptoKeyUsageDeriveBits | CryptoKeyUsageWrapKey | CryptoKeyUsageUnwrapKey)) {
exceptionCallback(SYNTAX_ERR);
return;
}
auto result = CryptoKeyEC::generatePair(CryptoAlgorithmIdentifier::ECDSA, ecParameters.namedCurve, extractable, usages);
if (result.hasException()) {
exceptionCallback(result.releaseException().code());
return;
}
auto pair = result.releaseReturnValue();
pair.publicKey->setUsagesBitmap(pair.publicKey->usagesBitmap() & CryptoKeyUsageVerify);
pair.privateKey->setUsagesBitmap(pair.privateKey->usagesBitmap() & CryptoKeyUsageSign);
callback(WTFMove(pair));
}
void CryptoAlgorithmECDSA::importKey(SubtleCrypto::KeyFormat format, KeyData&& data, const std::unique_ptr<CryptoAlgorithmParameters>&& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyCallback&& callback, ExceptionCallback&& exceptionCallback)
{
ASSERT(parameters);
const auto& ecParameters = downcast<CryptoAlgorithmEcKeyParams>(*parameters);
RefPtr<CryptoKeyEC> result;
switch (format) {
case SubtleCrypto::KeyFormat::Jwk: {
JsonWebKey key = WTFMove(WTF::get<JsonWebKey>(data));
if (usages && ((!key.d.isNull() && (usages ^ CryptoKeyUsageSign)) || (key.d.isNull() && (usages ^ CryptoKeyUsageVerify)))) {
exceptionCallback(SYNTAX_ERR);
return;
}
if (usages && !key.use.isNull() && key.use != "sig") {
exceptionCallback(DataError);
return;
}
bool isMatched = false;
if (key.crv == P256)
isMatched = key.alg.isNull() || key.alg == ALG256;
if (key.crv == P384)
isMatched = key.alg.isNull() || key.alg == ALG384;
if (!isMatched) {
exceptionCallback(DataError);
return;
}
result = CryptoKeyEC::importJwk(ecParameters.identifier, ecParameters.namedCurve, WTFMove(key), extractable, usages);
break;
}
case SubtleCrypto::KeyFormat::Raw:
if (usages && (usages ^ CryptoKeyUsageVerify)) {
exceptionCallback(SYNTAX_ERR);
return;
}
result = CryptoKeyEC::importRaw(ecParameters.identifier, ecParameters.namedCurve, WTFMove(WTF::get<Vector<uint8_t>>(data)), extractable, usages);
break;
case SubtleCrypto::KeyFormat::Spki:
if (usages && (usages ^ CryptoKeyUsageVerify)) {
exceptionCallback(SYNTAX_ERR);
return;
}
result = CryptoKeyEC::importSpki(ecParameters.identifier, ecParameters.namedCurve, WTFMove(WTF::get<Vector<uint8_t>>(data)), extractable, usages);
break;
case SubtleCrypto::KeyFormat::Pkcs8:
if (usages && (usages ^ CryptoKeyUsageSign)) {
exceptionCallback(SYNTAX_ERR);
return;
}
result = CryptoKeyEC::importPkcs8(ecParameters.identifier, ecParameters.namedCurve, WTFMove(WTF::get<Vector<uint8_t>>(data)), extractable, usages);
break;
}
if (!result) {
exceptionCallback(DataError);
return;
}
callback(*result);
}
void CryptoAlgorithmECDSA::exportKey(SubtleCrypto::KeyFormat format, Ref<CryptoKey>&& key, KeyDataCallback&& callback, ExceptionCallback&& exceptionCallback)
{
const auto& ecKey = downcast<CryptoKeyEC>(key.get());
if (!ecKey.keySizeInBits()) {
exceptionCallback(OperationError);
return;
}
KeyData result;
switch (format) {
case SubtleCrypto::KeyFormat::Jwk:
result = ecKey.exportJwk();
break;
case SubtleCrypto::KeyFormat::Raw: {
auto raw = ecKey.exportRaw();
if (raw.hasException()) {
exceptionCallback(raw.releaseException().code());
return;
}
result = raw.releaseReturnValue();
break;
}
case SubtleCrypto::KeyFormat::Spki: {
auto spki = ecKey.exportSpki();
if (spki.hasException()) {
exceptionCallback(spki.releaseException().code());
return;
}
result = spki.releaseReturnValue();
break;
}
case SubtleCrypto::KeyFormat::Pkcs8: {
auto pkcs8 = ecKey.exportPkcs8();
if (pkcs8.hasException()) {
exceptionCallback(pkcs8.releaseException().code());
return;
}
result = pkcs8.releaseReturnValue();
break;
}
}
callback(format, WTFMove(result));
}
}
#endif // ENABLE(SUBTLE_CRYPTO)