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