CryptoAlgorithmHMACOpenSSL.cpp [plain text]
#include "config.h"
#include "CryptoAlgorithmHMAC.h"
#if ENABLE(WEB_CRYPTO)
#include "CryptoKeyHMAC.h"
#include "OpenSSLCryptoUniquePtr.h"
#include <openssl/evp.h>
#include <wtf/CryptographicUtilities.h>
namespace WebCore {
static const EVP_MD* HMACAlgorithm(CryptoAlgorithmIdentifier hashFunction)
{
switch (hashFunction) {
case CryptoAlgorithmIdentifier::SHA_1:
return EVP_sha1();
case CryptoAlgorithmIdentifier::SHA_224:
return EVP_sha224();
case CryptoAlgorithmIdentifier::SHA_256:
return EVP_sha256();
case CryptoAlgorithmIdentifier::SHA_384:
return EVP_sha384();
case CryptoAlgorithmIdentifier::SHA_512:
return EVP_sha512();
default:
return nullptr;
}
}
static Optional<Vector<uint8_t>> calculateSignature(const EVP_MD* algorithm, const Vector<uint8_t>& key, const uint8_t* data, size_t dataLength)
{
EvpDigestCtxPtr ctx;
if (!(ctx = EvpDigestCtxPtr(EVP_MD_CTX_create())))
return WTF::nullopt;
EvpPKeyPtr hkey;
if (!(hkey = EvpPKeyPtr(EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, nullptr, key.data(), key.size()))))
return WTF::nullopt;
if (1 != EVP_DigestSignInit(ctx.get(), nullptr, algorithm, nullptr, hkey.get()))
return WTF::nullopt;
if (1 != EVP_DigestSignUpdate(ctx.get(), data, dataLength))
return WTF::nullopt;
size_t len = 0;
if (1 != EVP_DigestSignFinal(ctx.get(), nullptr, &len))
return WTF::nullopt;
Vector<uint8_t> cipherText(len);
if (1 != EVP_DigestSignFinal(ctx.get(), cipherText.data(), &len))
return WTF::nullopt;
return cipherText;
}
ExceptionOr<Vector<uint8_t>> CryptoAlgorithmHMAC::platformSign(const CryptoKeyHMAC& key, const Vector<uint8_t>& data)
{
auto algorithm = HMACAlgorithm(key.hashAlgorithmIdentifier());
if (!algorithm)
return Exception { OperationError };
auto result = calculateSignature(algorithm, key.key(), data.data(), data.size());
if (!result)
return Exception { OperationError };
return WTFMove(*result);
}
ExceptionOr<bool> CryptoAlgorithmHMAC::platformVerify(const CryptoKeyHMAC& key, const Vector<uint8_t>& signature, const Vector<uint8_t>& data)
{
auto algorithm = HMACAlgorithm(key.hashAlgorithmIdentifier());
if (!algorithm)
return Exception { OperationError };
auto expectedSignature = calculateSignature(algorithm, key.key(), data.data(), data.size());
if (!expectedSignature)
return Exception { OperationError };
return signature.size() == expectedSignature->size() && !constantTimeMemcmp(expectedSignature->data(), signature.data(), expectedSignature->size());
}
}
#endif // ENABLE(WEB_CRYPTO)