GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/crypto/encrypt.h
Date: 2024-04-28 02:33:07
Exec Total Coverage
Lines: 13 18 72.2%
Branches: 0 4 0.0%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System
3 *
4 * Symmetric encryption/decryption of small pieces of text. Plain text and
5 * cipher text are stored in std::string. Uses cbc mode, there is no inherent
6 * integrity check. The cipher text should only be used in a data structure
7 * that is itself protected by a digital signature, HMAC, or similar.
8 *
9 * The initialization vector is transferred together with the cipher text. It
10 * is constructed from the HMAC of the key and nonce.
11 */
12
13 #ifndef CVMFS_CRYPTO_ENCRYPT_H_
14 #define CVMFS_CRYPTO_ENCRYPT_H_
15
16 #include <pthread.h>
17
18 #include <map>
19 #include <string>
20
21 #include "crypto/hash.h"
22 #include "gtest/gtest_prod.h"
23 #include "util/export.h"
24 #include "util/single_copy.h"
25
26 namespace cipher {
27
28 enum Algorithms {
29 kAes256Cbc = 0,
30 kNone, // needs to be last
31 };
32
33
34 /**
35 * Encapsulates a small non-copyable piece of pinned memory. Is actively set to
36 * zero on destruction.
37 */
38 class CVMFS_EXPORT Key : SingleCopy {
39 public:
40 static const unsigned kMaxSize = 64;
41
42 static Key *CreateRandomly(const unsigned size);
43 static Key *CreateFromFile(const std::string &path);
44 static Key *CreateFromString(const std::string &key);
45 bool SaveToFile(const std::string &path);
46 ~Key();
47
48 300124 unsigned size() const { return size_; }
49 300062 const unsigned char *data() const { return data_; }
50 std::string ToBase64() const;
51
52 private:
53 300039 Key() : data_(NULL), size_(0) { }
54 unsigned char *data_;
55 unsigned size_;
56 };
57
58
59 /**
60 * Allows to access keys by identifiers. This might at some point move into a
61 * separate compilation unit.
62 */
63 class CVMFS_EXPORT AbstractKeyDatabase {
64 public:
65 6 virtual ~AbstractKeyDatabase() { }
66 virtual bool StoreNew(const Key *key, std::string *id) = 0;
67 virtual const Key *Find(const std::string &id) = 0;
68 };
69
70
71 class CVMFS_EXPORT MemoryKeyDatabase : SingleCopy, public AbstractKeyDatabase {
72 public:
73 MemoryKeyDatabase();
74 virtual ~MemoryKeyDatabase();
75 virtual bool StoreNew(const Key *key, std::string *id);
76 virtual const Key *Find(const std::string &id);
77
78 private:
79 pthread_mutex_t *lock_;
80 std::map<std::string, const Key *> database_;
81 };
82
83
84 /**
85 * The interface for an encryption algorithm. Uses a simple envelope with a one
86 * byte prefix: the first 4 bits are the envelope version (currently 0), the
87 * second 4 bits are the encryption algorithm and refers to Algorithms.
88 */
89 class CVMFS_EXPORT Cipher {
90 public:
91 static Cipher *Create(const Algorithms a);
92 88 virtual ~Cipher() { }
93
94 bool Encrypt(const std::string &plaintext, const Key &key,
95 std::string *ciphertext);
96 static bool Decrypt(const std::string &ciphertext, const Key &key,
97 std::string *plaintext);
98
99 virtual std::string name() const = 0;
100 virtual Algorithms algorithm() const = 0;
101 virtual unsigned key_size() const = 0;
102 virtual unsigned iv_size() const = 0;
103 virtual unsigned block_size() const = 0;
104
105 protected:
106 44 Cipher() { }
107 virtual std::string DoEncrypt(const std::string &plaintext,
108 const Key &key) = 0;
109 virtual std::string DoDecrypt(const std::string &ciphertext,
110 const Key &key) = 0;
111 };
112
113
114 /**
115 * Uses OpenSSL EVP_... format. The IV is created from the system time.
116 */
117 class CVMFS_EXPORT CipherAes256Cbc : public Cipher {
118 FRIEND_TEST(T_Encrypt, Aes_256_Cbc_Iv);
119
120 public:
121 static const unsigned kKeySize = 256/8;
122 static const unsigned kIvSize = 128/8;
123 static const unsigned kBlockSize = 128/8;
124
125 112 virtual ~CipherAes256Cbc() { }
126
127 virtual std::string name() const { return "AES-256-CBC"; }
128 18 virtual Algorithms algorithm() const { return kAes256Cbc; }
129 41 virtual unsigned key_size() const { return kKeySize; }
130 virtual unsigned iv_size() const { return kIvSize; }
131 1 virtual unsigned block_size() const { return kBlockSize; }
132
133 protected:
134 virtual std::string DoEncrypt(const std::string &plaintext, const Key &key);
135 virtual std::string DoDecrypt(const std::string &ciphertext, const Key &key);
136
137 private:
138 shash::Md5 GenerateIv(const Key &key);
139 };
140
141
142 /**
143 * No encryption, plaintext and ciphertext are identical. For testing.
144 */
145 class CVMFS_EXPORT CipherNone : public Cipher {
146 public:
147 54 virtual ~CipherNone() { }
148
149 virtual std::string name() const { return "FOR TESTING ONLY"; }
150 7 virtual Algorithms algorithm() const { return kNone; }
151 21 virtual unsigned key_size() const { return 256/8; }
152 virtual unsigned iv_size() const { return 128/8; }
153 virtual unsigned block_size() const { return 128/8; }
154
155 protected:
156 virtual std::string DoEncrypt(const std::string &plaintext, const Key &key);
157 virtual std::string DoDecrypt(const std::string &ciphertext, const Key &key);
158 };
159
160 } // namespace cipher
161
162 #endif // CVMFS_CRYPTO_ENCRYPT_H_
163