blob: f031890c5f3235929d75e7fdcd45683da1a2b6c8 [file] [log] [blame]
// Copyright 2015 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "settingsd/crypto.h"
#include <memory>
#include <stdint.h>
#include <base/logging.h>
#include <openssl/crypto.h>
#include <openssl/evp.h>
namespace settingsd {
namespace crypto {
bool ComputeDigest(DigestAlgorithm algorithm,
BlobRef data,
std::vector<uint8_t>* digest) {
const EVP_MD* md = nullptr;
switch (algorithm) {
case kDigestSha256:
md = EVP_sha256();
break;
}
if (!md) {
LOG(ERROR) << "Failed to determine algorithm " << algorithm;
return false;
}
EVP_MD_CTX* md_ctx = EVP_MD_CTX_create();
if (!md_ctx) {
LOG(ERROR) << "Failed to create message digest context.";
return false;
}
const unsigned int digest_size = EVP_MD_size(md);
digest->resize(digest_size);
unsigned int actual_digest_size = digest_size;
if (!EVP_DigestInit_ex(md_ctx, md, nullptr) ||
!EVP_DigestUpdate(md_ctx, data.data(), data.size()) ||
!EVP_DigestFinal_ex(md_ctx, digest->data(), &actual_digest_size)) {
LOG(ERROR) << "Failed to compute digest.";
EVP_MD_CTX_destroy(md_ctx);
return false;
}
EVP_MD_CTX_destroy(md_ctx);
return digest_size == actual_digest_size;
}
bool VerifyDigest(DigestAlgorithm algorithm, BlobRef data, BlobRef digest) {
std::vector<uint8_t> actual_digest;
if (!ComputeDigest(algorithm, data, &actual_digest))
return false;
// Do a constant time memory comparison here. It's not strictly needed, but
// one never knows who'll end up calling this code.
return digest.size() == actual_digest.size() &&
CRYPTO_memcmp(digest.data(), actual_digest.data(), digest.size()) == 0;
}
} // namespace crypto
} // namespace settingsd