diff options
Diffstat (limited to 'src/lib/crypto/hash_common.cpp')
-rw-r--r-- | src/lib/crypto/hash_common.cpp | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/src/lib/crypto/hash_common.cpp b/src/lib/crypto/hash_common.cpp new file mode 100644 index 0000000..69b400b --- /dev/null +++ b/src/lib/crypto/hash_common.cpp @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2021-2022 Ribose Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "hash.hpp" +#include "types.h" +#include "utils.h" +#include "str-utils.h" +#include "hash_sha1cd.hpp" +#if defined(CRYPTO_BACKEND_BOTAN) +#include "hash_botan.hpp" +#endif +#if defined(CRYPTO_BACKEND_OPENSSL) +#include "hash_ossl.hpp" +#include "hash_crc24.hpp" +#endif + +static const struct hash_alg_map_t { + pgp_hash_alg_t type; + const char * name; + size_t len; +} hash_alg_map[] = {{PGP_HASH_MD5, "MD5", 16}, + {PGP_HASH_SHA1, "SHA1", 20}, + {PGP_HASH_RIPEMD, "RIPEMD160", 20}, + {PGP_HASH_SHA256, "SHA256", 32}, + {PGP_HASH_SHA384, "SHA384", 48}, + {PGP_HASH_SHA512, "SHA512", 64}, + {PGP_HASH_SHA224, "SHA224", 28}, + {PGP_HASH_SM3, "SM3", 32}, + {PGP_HASH_SHA3_256, "SHA3-256", 32}, + {PGP_HASH_SHA3_512, "SHA3-512", 64}}; + +namespace rnp { + +pgp_hash_alg_t +Hash::alg() const +{ + return alg_; +} + +size_t +Hash::size() const +{ + return Hash::size(alg_); +} + +std::unique_ptr<Hash> +Hash::create(pgp_hash_alg_t alg) +{ + if (alg == PGP_HASH_SHA1) { + return Hash_SHA1CD::create(); + } +#if !defined(ENABLE_SM2) + if (alg == PGP_HASH_SM3) { + RNP_LOG("SM3 hash is not available."); + throw rnp_exception(RNP_ERROR_BAD_PARAMETERS); + } +#endif +#if defined(CRYPTO_BACKEND_OPENSSL) + return Hash_OpenSSL::create(alg); +#elif defined(CRYPTO_BACKEND_BOTAN) + return Hash_Botan::create(alg); +#else +#error "Crypto backend not specified" +#endif +} + +std::unique_ptr<CRC24> +CRC24::create() +{ +#if defined(CRYPTO_BACKEND_OPENSSL) + return CRC24_RNP::create(); +#elif defined(CRYPTO_BACKEND_BOTAN) + return CRC24_Botan::create(); +#else +#error "Crypto backend not specified" +#endif +} + +void +Hash::add(uint32_t val) +{ + uint8_t ibuf[4]; + STORE32BE(ibuf, val); + add(ibuf, sizeof(ibuf)); +} + +void +Hash::add(const pgp_mpi_t &val) +{ + size_t len = mpi_bytes(&val); + size_t idx = 0; + while ((idx < len) && (!val.mpi[idx])) { + idx++; + } + + if (idx >= len) { + add(0); + return; + } + + add(len - idx); + if (val.mpi[idx] & 0x80) { + uint8_t padbyte = 0; + add(&padbyte, 1); + } + add(val.mpi + idx, len - idx); +} + +Hash::~Hash() +{ +} + +pgp_hash_alg_t +Hash::alg(const char *name) +{ + if (!name) { + return PGP_HASH_UNKNOWN; + } + for (size_t i = 0; i < ARRAY_SIZE(hash_alg_map); i++) { + if (rnp::str_case_eq(name, hash_alg_map[i].name)) { + return hash_alg_map[i].type; + } + } + return PGP_HASH_UNKNOWN; +} + +const char * +Hash::name(pgp_hash_alg_t alg) +{ + const char *ret = NULL; + ARRAY_LOOKUP_BY_ID(hash_alg_map, type, name, alg, ret); + return ret; +} + +size_t +Hash::size(pgp_hash_alg_t alg) +{ + size_t val = 0; + ARRAY_LOOKUP_BY_ID(hash_alg_map, type, len, alg, val); + return val; +} + +void +HashList::add_alg(pgp_hash_alg_t alg) +{ + if (!get(alg)) { + hashes.emplace_back(rnp::Hash::create(alg)); + } +} + +const Hash * +HashList::get(pgp_hash_alg_t alg) const +{ + for (auto &hash : hashes) { + if (hash->alg() == alg) { + return hash.get(); + } + } + return NULL; +} + +void +HashList::add(const void *buf, size_t len) +{ + for (auto &hash : hashes) { + hash->add(buf, len); + } +} + +} // namespace rnp |