Rocket.Chat.ReactNative/ios/Pods/Flipper-Folly/folly/ssl/OpenSSLHash.h

186 lines
5.1 KiB
C++

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <folly/Range.h>
#include <folly/io/IOBuf.h>
#include <folly/portability/OpenSSL.h>
#include <folly/ssl/OpenSSLPtrTypes.h>
namespace folly {
namespace ssl {
/// Warning:
/// These functions are not thread-safe unless you initialize OpenSSL.
class OpenSSLHash {
public:
class Digest {
public:
Digest() : ctx_(EVP_MD_CTX_new()) {}
Digest(const Digest& other) {
ctx_ = EvpMdCtxUniquePtr(EVP_MD_CTX_new());
if (other.md_ != nullptr) {
hash_init(other.md_);
check_libssl_result(
1, EVP_MD_CTX_copy_ex(ctx_.get(), other.ctx_.get()));
}
}
Digest& operator=(const Digest& other) {
this->~Digest();
return *new (this) Digest(other);
}
void hash_init(const EVP_MD* md) {
md_ = md;
check_libssl_result(1, EVP_DigestInit_ex(ctx_.get(), md, nullptr));
}
void hash_update(ByteRange data) {
check_libssl_result(
1, EVP_DigestUpdate(ctx_.get(), data.data(), data.size()));
}
void hash_update(const IOBuf& data) {
for (auto r : data) {
hash_update(r);
}
}
void hash_final(MutableByteRange out) {
const auto size = EVP_MD_size(md_);
check_out_size(size_t(size), out);
unsigned int len = 0;
check_libssl_result(1, EVP_DigestFinal_ex(ctx_.get(), out.data(), &len));
check_libssl_result(size, int(len));
md_ = nullptr;
}
private:
const EVP_MD* md_ = nullptr;
EvpMdCtxUniquePtr ctx_{nullptr};
};
static void hash(MutableByteRange out, const EVP_MD* md, ByteRange data) {
Digest hash;
hash.hash_init(md);
hash.hash_update(data);
hash.hash_final(out);
}
static void hash(MutableByteRange out, const EVP_MD* md, const IOBuf& data) {
Digest hash;
hash.hash_init(md);
hash.hash_update(data);
hash.hash_final(out);
}
static void sha1(MutableByteRange out, ByteRange data) {
hash(out, EVP_sha1(), data);
}
static void sha1(MutableByteRange out, const IOBuf& data) {
hash(out, EVP_sha1(), data);
}
static void sha256(MutableByteRange out, ByteRange data) {
hash(out, EVP_sha256(), data);
}
static void sha256(MutableByteRange out, const IOBuf& data) {
hash(out, EVP_sha256(), data);
}
class Hmac {
public:
Hmac() : ctx_(HMAC_CTX_new()) {}
void hash_init(const EVP_MD* md, ByteRange key) {
md_ = md;
check_libssl_result(
1,
HMAC_Init_ex(ctx_.get(), key.data(), int(key.size()), md_, nullptr));
}
void hash_update(ByteRange data) {
check_libssl_result(1, HMAC_Update(ctx_.get(), data.data(), data.size()));
}
void hash_update(const IOBuf& data) {
for (auto r : data) {
hash_update(r);
}
}
void hash_final(MutableByteRange out) {
const auto size = EVP_MD_size(md_);
check_out_size(size_t(size), out);
unsigned int len = 0;
check_libssl_result(1, HMAC_Final(ctx_.get(), out.data(), &len));
check_libssl_result(size, int(len));
md_ = nullptr;
}
private:
const EVP_MD* md_ = nullptr;
HmacCtxUniquePtr ctx_{nullptr};
};
static void
hmac(MutableByteRange out, const EVP_MD* md, ByteRange key, ByteRange data) {
Hmac hmac;
hmac.hash_init(md, key);
hmac.hash_update(data);
hmac.hash_final(out);
}
static void hmac(
MutableByteRange out,
const EVP_MD* md,
ByteRange key,
const IOBuf& data) {
Hmac hmac;
hmac.hash_init(md, key);
hmac.hash_update(data);
hmac.hash_final(out);
}
static void hmac_sha1(MutableByteRange out, ByteRange key, ByteRange data) {
hmac(out, EVP_sha1(), key, data);
}
static void
hmac_sha1(MutableByteRange out, ByteRange key, const IOBuf& data) {
hmac(out, EVP_sha1(), key, data);
}
static void hmac_sha256(MutableByteRange out, ByteRange key, ByteRange data) {
hmac(out, EVP_sha256(), key, data);
}
static void
hmac_sha256(MutableByteRange out, ByteRange key, const IOBuf& data) {
hmac(out, EVP_sha256(), key, data);
}
private:
static inline void check_out_size(size_t size, MutableByteRange out) {
if (LIKELY(size == out.size())) {
return;
}
check_out_size_throw(size, out);
}
[[noreturn]] static void check_out_size_throw(
size_t size,
MutableByteRange out);
static inline void check_libssl_result(int expected, int result) {
if (LIKELY(result == expected)) {
return;
}
throw_exception<std::runtime_error>("openssl crypto function failed");
}
};
} // namespace ssl
} // namespace folly