summaryrefslogtreecommitdiffstats
path: root/src/lib/crypto/hash_common.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/crypto/hash_common.cpp')
-rw-r--r--src/lib/crypto/hash_common.cpp194
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