Coverage Report

Created: 2025-04-11 06:34

/src/botan/src/lib/pubkey/hybrid_kem/hybrid_kem.cpp
Line
Count
Source (jump to first uncovered line)
1
/**
2
* Abstraction for a combined KEM public and private key.
3
*
4
* (C) 2024 Jack Lloyd
5
*     2024 Fabian Albert, René Meusel - Rohde & Schwarz Cybersecurity
6
*
7
* Botan is released under the Simplified BSD License (see license.txt)
8
*/
9
#include <botan/internal/hybrid_kem.h>
10
11
#include <botan/pk_algs.h>
12
#include <botan/internal/fmt.h>
13
#include <botan/internal/kex_to_kem_adapter.h>
14
#include <botan/internal/pk_ops_impl.h>
15
#include <botan/internal/stl_util.h>
16
17
namespace Botan {
18
19
Hybrid_PublicKey::Hybrid_PublicKey(std::vector<std::unique_ptr<Public_Key>> pks) :
20
0
      m_pks(std::move(pks)), m_key_length(0), m_estimated_strength(0) {
21
0
   BOTAN_ARG_CHECK(m_pks.size() >= 2, "List of public keys must include at least two keys");
22
0
   for(const auto& pk : m_pks) {
23
0
      BOTAN_ARG_CHECK(pk != nullptr, "List of public keys contains a nullptr");
24
0
      BOTAN_ARG_CHECK(pk->supports_operation(PublicKeyOperation::KeyEncapsulation),
25
0
                      fmt("Public key type '{}' does not support key encapsulation", pk->algo_name()).c_str());
26
0
      m_key_length = std::max(m_key_length, pk->key_length());
27
0
      m_estimated_strength = std::max(m_estimated_strength, pk->estimated_strength());
28
0
   }
29
0
}
30
31
0
bool Hybrid_PublicKey::check_key(RandomNumberGenerator& rng, bool strong) const {
32
0
   return reduce(public_keys(), true, [&](bool ckr, const auto& key) { return ckr && key->check_key(rng, strong); });
33
0
}
34
35
0
std::vector<uint8_t> Hybrid_PublicKey::raw_public_key_bits() const {
36
0
   return reduce(public_keys(), std::vector<uint8_t>(), [](auto pkb, const auto& key) {
37
0
      return concat(pkb, key->raw_public_key_bits());
38
0
   });
39
0
}
40
41
0
bool Hybrid_PublicKey::supports_operation(PublicKeyOperation op) const {
42
0
   return PublicKeyOperation::KeyEncapsulation == op;
43
0
}
44
45
std::vector<std::unique_ptr<Private_Key>> Hybrid_PublicKey::generate_other_sks_from_pks(
46
0
   RandomNumberGenerator& rng) const {
47
0
   std::vector<std::unique_ptr<Private_Key>> new_private_keys;
48
0
   new_private_keys.reserve(public_keys().size());
49
0
   for(const auto& pk : public_keys()) {
50
0
      new_private_keys.push_back(pk->generate_another(rng));
51
0
   }
52
0
   return new_private_keys;
53
0
}
54
55
Hybrid_PrivateKey::Hybrid_PrivateKey(std::vector<std::unique_ptr<Private_Key>> private_keys) :
56
0
      m_sks(std::move(private_keys)) {
57
0
   BOTAN_ARG_CHECK(m_sks.size() >= 2, "List of secret keys must include at least two keys");
58
0
   for(const auto& sk : m_sks) {
59
0
      BOTAN_ARG_CHECK(sk != nullptr, "List of secret keys contains a nullptr");
60
0
      BOTAN_ARG_CHECK(sk->supports_operation(PublicKeyOperation::KeyEncapsulation),
61
0
                      "Some provided secret key is not compatible with this hybrid wrapper");
62
0
   }
63
0
}
64
65
0
secure_vector<uint8_t> Hybrid_PrivateKey::private_key_bits() const {
66
0
   throw Not_Implemented("Hybrid private keys cannot be serialized");
67
0
}
68
69
0
bool Hybrid_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const {
70
0
   return reduce(private_keys(), true, [&](bool ckr, const auto& key) { return ckr && key->check_key(rng, strong); });
71
0
}
72
73
std::vector<std::unique_ptr<Public_Key>> Hybrid_PrivateKey::extract_public_keys(
74
0
   const std::vector<std::unique_ptr<Private_Key>>& private_keys) {
75
0
   std::vector<std::unique_ptr<Public_Key>> public_keys;
76
0
   public_keys.reserve(private_keys.size());
77
0
   for(const auto& sk : private_keys) {
78
0
      BOTAN_ARG_CHECK(sk != nullptr, "List of private keys contains a nullptr");
79
0
      public_keys.push_back(sk->public_key());
80
0
   }
81
0
   return public_keys;
82
0
}
83
84
}  // namespace Botan