void JSCryptoKeySerializationJWK::reconcileUsages(CryptoKeyUsage& suggestedUsages) const
{
    CryptoKeyUsage jwkUsages = 0;

    JSArray* keyOps;
    if (getJSArrayFromJSON(m_exec, m_json.get(), "key_ops", keyOps)) {
        for (size_t i = 0; i < keyOps->length(); ++i) {
            JSValue jsValue = keyOps->getIndex(m_exec, i);
            String operation;
            if (!jsValue.getString(m_exec, operation)) {
                if (!m_exec->hadException())
                    throwTypeError(m_exec, "JWK key_ops attribute could not be processed");
                return;
            }
            if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("sign"), CryptoKeyUsageSign))
                return;
            if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("verify"), CryptoKeyUsageVerify))
                return;
            if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("encrypt"), CryptoKeyUsageEncrypt))
                return;
            if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("decrypt"), CryptoKeyUsageDecrypt))
                return;
            if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("wrapKey"), CryptoKeyUsageWrapKey))
                return;
            if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("unwrapKey"), CryptoKeyUsageUnwrapKey))
                return;
            if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("deriveKey"), CryptoKeyUsageDeriveKey))
                return;
            if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("deriveBits"), CryptoKeyUsageDeriveBits))
                return;
        }
    } else {
        if (m_exec->hadException())
            return;

        String jwkUseString;
        if (!getStringFromJSON(m_exec, m_json.get(), "use", jwkUseString)) {
            // We have neither key_ops nor use.
            return;
        }

        if (jwkUseString == "enc")
            jwkUsages |= (CryptoKeyUsageEncrypt | CryptoKeyUsageDecrypt | CryptoKeyUsageWrapKey | CryptoKeyUsageUnwrapKey);
        else if (jwkUseString == "sig")
            jwkUsages |= (CryptoKeyUsageSign | CryptoKeyUsageVerify);
        else {
            throwTypeError(m_exec, "Unsupported JWK key use value \"" + jwkUseString + "\"");
            return;
        }
    }

    suggestedUsages = suggestedUsages & jwkUsages;
}
Ejemplo n.º 2
0
std::unique_ptr<CryptoKeyData> JSCryptoKeySerializationJWK::keyData() const
{
    String jwkKeyType;
    if (!getStringFromJSON(m_exec, m_json.get(), "kty", jwkKeyType)) {
        if (!m_exec->hadException())
            throwTypeError(m_exec, "Required JWK \"kty\" member is missing");
        return nullptr;
    }

    if (jwkKeyType == "oct")
        return keyDataOctetSequence();

    if (jwkKeyType == "RSA")
        return keyDataRSAComponents();

    throwTypeError(m_exec, "Unsupported JWK key type " + jwkKeyType);
    return nullptr;
}
Ejemplo n.º 3
0
static bool getBigIntegerVectorFromJSON(ExecState* exec, JSObject* json, const char* key, Vector<uint8_t>& result)
{
    String base64urlEncodedNumber;
    if (!getStringFromJSON(exec, json, key, base64urlEncodedNumber))
        return false;

    if (!base64URLDecode(base64urlEncodedNumber, result)) {
        throwTypeError(exec, "Cannot decode base64url key data in JWK");
        return false;
    }

    if (result[0] == 0) {
        throwTypeError(exec, "JWK BigInteger must utilize the minimum number of octets to represent the value");
        return false;
    }

    return true;
}
Ejemplo n.º 4
0
void JSCryptoKeySerializationJWK::reconcileUsages(CryptoKeyUsage& suggestedUsage) const
{
    String jwkUseString;
    if (!getStringFromJSON(m_exec, m_json.get(), "use", jwkUseString)) {
        // "use" is optional in JWK.
        return;
    }

    // FIXME: CryptoKeyUsageDeriveKey, CryptoKeyUsageDeriveBits - should these be implicitly allowed by any JWK use value?
    // FIXME: "use" mapping is in flux, see <https://www.w3.org/Bugs/Public/show_bug.cgi?id=23796>.
    if (jwkUseString == "sig")
        suggestedUsage = suggestedUsage & (CryptoKeyUsageSign | CryptoKeyUsageVerify);
    else if (jwkUseString == "enc")
        suggestedUsage = suggestedUsage & (CryptoKeyUsageEncrypt | CryptoKeyUsageDecrypt | CryptoKeyUsageWrapKey | CryptoKeyUsageUnwrapKey);
    else if (jwkUseString == "wrap")
        suggestedUsage = suggestedUsage & (CryptoKeyUsageWrapKey | CryptoKeyUsageUnwrapKey);
    else
        suggestedUsage = 0; // Unknown usage, better be safe.
}
Ejemplo n.º 5
0
std::unique_ptr<CryptoKeyData> JSCryptoKeySerializationJWK::keyDataOctetSequence() const
{
    String keyBase64URL;
    if (!getStringFromJSON(m_exec, m_json.get(), "k", keyBase64URL)) {
        if (!m_exec->hadException())
            throwTypeError(m_exec, "Secret key data is not present is JWK");
        return nullptr;
    }

    Vector<uint8_t> octetSequence;
    if (!base64URLDecode(keyBase64URL, octetSequence)) {
        throwTypeError(m_exec, "Cannot decode base64url key data in JWK");
        return nullptr;
    }

    if (!keySizeIsValid(octetSequence.size() * 8)) {
        throwTypeError(m_exec, "Key size is not valid for " + m_jwkAlgorithmName);
        return nullptr;
    }

    return CryptoKeyDataOctetSequence::create(octetSequence);
}
Ejemplo n.º 6
0
bool JSCryptoKeySerializationJWK::reconcileAlgorithm(std::unique_ptr<CryptoAlgorithm>& suggestedAlgorithm, std::unique_ptr<CryptoAlgorithmParameters>& suggestedParameters) const
{
    if (!getStringFromJSON(m_exec, m_json.get(), "alg", m_jwkAlgorithmName)) {
        // Algorithm is optional in JWK.
        return true;
    }

    std::unique_ptr<CryptoAlgorithm> algorithm;
    std::unique_ptr<CryptoAlgorithmParameters> parameters;
    if (m_jwkAlgorithmName == "HS256") {
        algorithm = CryptoAlgorithmRegistry::shared().create(CryptoAlgorithmIdentifier::HMAC);
        parameters = createHMACParameters(CryptoAlgorithmIdentifier::SHA_256);
    } else if (m_jwkAlgorithmName == "HS384") {
        algorithm = CryptoAlgorithmRegistry::shared().create(CryptoAlgorithmIdentifier::HMAC);
        parameters = createHMACParameters(CryptoAlgorithmIdentifier::SHA_384);
    } else if (m_jwkAlgorithmName == "HS512") {
        algorithm = CryptoAlgorithmRegistry::shared().create(CryptoAlgorithmIdentifier::HMAC);
        parameters = createHMACParameters(CryptoAlgorithmIdentifier::SHA_512);
    } else if (m_jwkAlgorithmName == "RS256") {
        algorithm = CryptoAlgorithmRegistry::shared().create(CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5);
        parameters = createRSASSAKeyParameters(CryptoAlgorithmIdentifier::SHA_256);
    } else if (m_jwkAlgorithmName == "RS384") {
        algorithm = CryptoAlgorithmRegistry::shared().create(CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5);
        parameters = createRSASSAKeyParameters(CryptoAlgorithmIdentifier::SHA_384);
    } else if (m_jwkAlgorithmName == "RS512") {
        algorithm = CryptoAlgorithmRegistry::shared().create(CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5);
        parameters = createRSASSAKeyParameters(CryptoAlgorithmIdentifier::SHA_512);
    } else if (m_jwkAlgorithmName == "A128CBC") {
        algorithm = CryptoAlgorithmRegistry::shared().create(CryptoAlgorithmIdentifier::AES_CBC);
        parameters = std::make_unique<CryptoAlgorithmParameters>();
    } else if (m_jwkAlgorithmName == "A192CBC") {
        algorithm = CryptoAlgorithmRegistry::shared().create(CryptoAlgorithmIdentifier::AES_CBC);
        parameters = std::make_unique<CryptoAlgorithmParameters>();
    } else if (m_jwkAlgorithmName == "A256CBC") {
        algorithm = CryptoAlgorithmRegistry::shared().create(CryptoAlgorithmIdentifier::AES_CBC);
        parameters = std::make_unique<CryptoAlgorithmParameters>();
    } else {
        throwTypeError(m_exec, "Unsupported JWK algorithm " + m_jwkAlgorithmName);
        return false;
    }

    if (!suggestedAlgorithm) {
        suggestedAlgorithm = std::move(algorithm);
        suggestedParameters =  std::move(parameters);
        return true;
    }

    if (!algorithm)
        return true;

    if (algorithm->identifier() != suggestedAlgorithm->identifier())
        return false;

    if (algorithm->identifier() == CryptoAlgorithmIdentifier::HMAC)
        return toCryptoAlgorithmHmacParams(*parameters).hash == toCryptoAlgorithmHmacParams(*suggestedParameters).hash;
    if (algorithm->identifier() == CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5) {
        CryptoAlgorithmRsaSsaKeyParams& rsaSSAParameters = toCryptoAlgorithmRsaSsaKeyParams(*parameters);
        CryptoAlgorithmRsaSsaKeyParams& suggestedRSASSAParameters = toCryptoAlgorithmRsaSsaKeyParams(*suggestedParameters);
        ASSERT(rsaSSAParameters.hasHash);
        if (suggestedRSASSAParameters.hasHash)
            return suggestedRSASSAParameters.hash == rsaSSAParameters.hash;
        suggestedRSASSAParameters.hasHash = true;
        suggestedRSASSAParameters.hash = rsaSSAParameters.hash;
    }

    // Other algorithms don't have parameters.
    return true;
}