Aktualizr
C++ SOTA Client
All Classes Namespaces Files Functions Variables Enumerations Enumerator Pages
crypto.h
1 #ifndef CRYPTO_H_
2 #define CRYPTO_H_
3 
4 #include <openssl/engine.h>
5 #include <openssl/err.h>
6 #include <openssl/evp.h>
7 #include <openssl/pem.h>
8 #include <openssl/pkcs12.h>
9 #include <openssl/rsa.h>
10 #include <sodium.h>
11 #include <boost/algorithm/hex.hpp>
12 #include <boost/algorithm/string.hpp>
13 #include <boost/algorithm/string/case_conv.hpp>
14 
15 #include <string>
16 #include <utility>
17 
18 #include "utilities/types.h"
19 #include "utilities/utils.h"
20 
21 // some older versions of openssl have BIO_new_mem_buf defined with fisrt parameter of type (void*)
22 // which is not true and breaks our build
23 #undef BIO_new_mem_buf
24 BIO *BIO_new_mem_buf(const void *, int);
25 
26 class PublicKey {
27  public:
28  PublicKey() = default;
29  explicit PublicKey(const boost::filesystem::path &path);
30 
31  explicit PublicKey(Json::Value uptane_json);
32 
33  PublicKey(const std::string &value, KeyType type);
34 
35  std::string Value() const { return value_; }
36 
37  KeyType Type() const { return type_; }
38  /**
39  * Verify a signature using this public key
40  */
41  bool VerifySignature(const std::string &signature, const std::string &message) const;
42  /**
43  * Uptane Json representation of this public key. Used in root.json
44  * and during provisioning.
45  */
46  Json::Value ToUptane() const;
47 
48  std::string KeyId() const;
49  bool operator==(const PublicKey &rhs) const;
50 
51  bool operator!=(const PublicKey &rhs) const { return !(*this == rhs); }
52 
53  private:
54  // std::string can be implicitly converted to a Json::Value. Make sure that
55  // the Json::Value constructor is not called accidentally.
56  PublicKey(std::string);
57  std::string value_;
58  KeyType type_{KeyType::kUnknown};
59 };
60 
61 /**
62  * The hash of a file or Uptane metadata. File hashes/checksums in Uptane include the length of the object, in order to
63  * defeat infinite download attacks.
64  */
65 class Hash {
66  public:
67  // order corresponds algorithm priority
68  enum class Type { kSha256, kSha512, kUnknownAlgorithm };
69 
70  static Hash generate(Type type, const std::string &data);
71  Hash(const std::string &type, const std::string &hash);
72  Hash(Type type, const std::string &hash);
73 
74  bool HaveAlgorithm() const { return type_ != Type::kUnknownAlgorithm; }
75  bool operator==(const Hash &other) const;
76  bool operator!=(const Hash &other) const { return !operator==(other); }
77  static std::string TypeString(Type type);
78  std::string TypeString() const;
79  Type type() const;
80  std::string HashString() const { return hash_; }
81  friend std::ostream &operator<<(std::ostream &os, const Hash &h);
82 
83  static std::string encodeVector(const std::vector<Hash> &hashes);
84  static std::vector<Hash> decodeVector(std::string hashes_str);
85 
86  private:
87  Type type_;
88  std::string hash_;
89 };
90 
91 std::ostream &operator<<(std::ostream &os, const Hash &h);
92 
94  public:
95  using Ptr = std::shared_ptr<MultiPartHasher>;
96  static Ptr create(Hash::Type hash_type);
97 
98  public:
99  virtual void update(const unsigned char *part, uint64_t size) = 0;
100  virtual std::string getHexDigest() = 0;
101  virtual Hash getHash() = 0;
102  virtual ~MultiPartHasher() = default;
103 };
104 
106  public:
107  MultiPartSHA512Hasher() { crypto_hash_sha512_init(&state_); }
108  ~MultiPartSHA512Hasher() override = default;
109  void update(const unsigned char *part, uint64_t size) override { crypto_hash_sha512_update(&state_, part, size); }
110  std::string getHexDigest() override {
111  std::array<unsigned char, crypto_hash_sha512_BYTES> sha512_hash{};
112  crypto_hash_sha512_final(&state_, sha512_hash.data());
113  return boost::algorithm::hex(std::string(reinterpret_cast<char *>(sha512_hash.data()), crypto_hash_sha512_BYTES));
114  }
115 
116  Hash getHash() override { return Hash(Hash::Type::kSha512, getHexDigest()); }
117 
118  private:
119  crypto_hash_sha512_state state_{};
120 };
121 
123  public:
124  MultiPartSHA256Hasher() { crypto_hash_sha256_init(&state_); }
125  ~MultiPartSHA256Hasher() override = default;
126  void update(const unsigned char *part, uint64_t size) override { crypto_hash_sha256_update(&state_, part, size); }
127  std::string getHexDigest() override {
128  std::array<unsigned char, crypto_hash_sha256_BYTES> sha256_hash{};
129  crypto_hash_sha256_final(&state_, sha256_hash.data());
130  return boost::algorithm::hex(std::string(reinterpret_cast<char *>(sha256_hash.data()), crypto_hash_sha256_BYTES));
131  }
132 
133  Hash getHash() override { return Hash(Hash::Type::kSha256, getHexDigest()); }
134 
135  private:
136  crypto_hash_sha256_state state_{};
137 };
138 
139 class Crypto {
140  public:
141  static std::string sha256digest(const std::string &text);
142  static std::string sha512digest(const std::string &text);
143  static std::string RSAPSSSign(ENGINE *engine, const std::string &private_key, const std::string &message);
144  static std::string Sign(KeyType key_type, ENGINE *engine, const std::string &private_key, const std::string &message);
145  static std::string ED25519Sign(const std::string &private_key, const std::string &message);
146  static bool parseP12(BIO *p12_bio, const std::string &p12_password, std::string *out_pkey, std::string *out_cert,
147  std::string *out_ca);
148  static bool extractSubjectCN(const std::string &cert, std::string *cn);
149  static StructGuard<EVP_PKEY> generateRSAKeyPairEVP(KeyType key_type);
150  static bool generateRSAKeyPair(KeyType key_type, std::string *public_key, std::string *private_key);
151  static bool generateEDKeyPair(std::string *public_key, std::string *private_key);
152  static bool generateKeyPair(KeyType key_type, std::string *public_key, std::string *private_key);
153 
154  static bool RSAPSSVerify(const std::string &public_key, const std::string &signature, const std::string &message);
155  static bool ED25519Verify(const std::string &public_key, const std::string &signature, const std::string &message);
156 
157  static bool IsRsaKeyType(KeyType type);
158  static KeyType IdentifyRSAKeyType(const std::string &public_key_pem);
159 };
160 
161 #endif // CRYPTO_H_
General data structures.
Definition: types.cc:55
Json::Value ToUptane() const
Uptane Json representation of this public key.
Definition: crypto.cc:75
Definition: crypto.h:139
bool VerifySignature(const std::string &signature, const std::string &message) const
Verify a signature using this public key.
Definition: crypto.cc:61
The hash of a file or Uptane metadata.
Definition: crypto.h:65