1    	// vim: ts=8 sw=2 smarttab
2    	/*
3    	 * Ceph - scalable distributed file system
4    	 *
5    	 * Copyright (C) 2004-2009 Sage Weil <sage@newdream.net>
6    	 *
7    	 * This is free software; you can redistribute it and/or
8    	 * modify it under the terms of the GNU Lesser General Public
9    	 * License version 2.1, as published by the Free Software 
10   	 * Foundation.  See file COPYING.
11   	 * 
12   	 */
13   	
14   	#include <array>
15   	#include <sstream>
16   	#include <limits>
17   	#include <fcntl.h>
18   	
19   	#include <openssl/aes.h>
20   	
21   	#include "Crypto.h"
22   	
23   	#include "include/ceph_assert.h"
24   	#include "common/Clock.h"
25   	#include "common/armor.h"
26   	#include "common/ceph_context.h"
27   	#include "common/ceph_crypto.h"
28   	#include "common/hex.h"
29   	#include "common/safe_io.h"
30   	#include "include/ceph_fs.h"
31   	#include "include/compat.h"
32   	#include "common/Formatter.h"
33   	#include "common/debug.h"
34   	#include <errno.h>
35   	
36   	// use getentropy() if available. it uses the same source of randomness
37   	// as /dev/urandom without the filesystem overhead
38   	#ifdef HAVE_GETENTROPY
39   	
40   	#include <unistd.h>
41   	
42   	static bool getentropy_works()
43   	{
44   	  char buf;
45   	  auto ret = TEMP_FAILURE_RETRY(::getentropy(&buf, sizeof(buf)));
46   	  if (ret == 0) {
47   	    return true;
48   	  } else if (errno == ENOSYS || errno == EPERM) {
49   	    return false;
50   	  } else {
51   	    throw std::system_error(errno, std::system_category());
52   	  }
53   	}
54   	
55   	CryptoRandom::CryptoRandom() : fd(getentropy_works() ? -1 : open_urandom())
56   	{}
57   	
58   	CryptoRandom::~CryptoRandom()
59   	{
60   	  if (fd >= 0) {
61   	    VOID_TEMP_FAILURE_RETRY(::close(fd));
62   	  }
63   	}
64   	
65   	void CryptoRandom::get_bytes(char *buf, int len)
66   	{
67   	  ssize_t ret = 0;
68   	  if (unlikely(fd >= 0)) {
69   	    ret = safe_read_exact(fd, buf, len);
70   	  } else {
71   	    // getentropy() reads up to 256 bytes
72   	    assert(len <= 256);
73   	    ret = TEMP_FAILURE_RETRY(::getentropy(buf, len));
74   	  }
75   	  if (ret < 0) {
76   	    throw std::system_error(errno, std::system_category());
77   	  }
78   	}
79   	
80   	#else // !HAVE_GETENTROPY
81   	
82   	// open /dev/urandom once on construction and reuse the fd for all reads
83   	CryptoRandom::CryptoRandom()
84   	  : fd{open_urandom()}
85   	{
86   	  if (fd < 0) {
87   	    throw std::system_error(errno, std::system_category());
88   	  }
89   	}
90   	
91   	CryptoRandom::~CryptoRandom()
92   	{
93   	  VOID_TEMP_FAILURE_RETRY(::close(fd));
94   	}
95   	
96   	void CryptoRandom::get_bytes(char *buf, int len)
97   	{
98   	  auto ret = safe_read_exact(fd, buf, len);
99   	  if (ret < 0) {
100  	    throw std::system_error(-ret, std::system_category());
101  	  }
102  	}
103  	
104  	#endif
105  	
106  	int CryptoRandom::open_urandom()
107  	{
108  	  int fd = TEMP_FAILURE_RETRY(::open("/dev/urandom", O_CLOEXEC|O_RDONLY));
109  	  if (fd < 0) {
110  	    throw std::system_error(errno, std::system_category());
111  	  }
112  	  return fd;
113  	}
114  	
115  	// ---------------------------------------------------
116  	// fallback implementation of the bufferlist-free
117  	// interface.
118  	
119  	std::size_t CryptoKeyHandler::encrypt(
120  	  const CryptoKeyHandler::in_slice_t& in,
121  	  const CryptoKeyHandler::out_slice_t& out) const
122  	{
123  	  ceph::bufferptr inptr(reinterpret_cast<const char*>(in.buf), in.length);
124  	  ceph::bufferlist plaintext;
125  	  plaintext.append(std::move(inptr));
126  	
127  	  ceph::bufferlist ciphertext;
128  	  std::string error;
129  	  const int ret = encrypt(plaintext, ciphertext, &error);
130  	  if (ret != 0 || !error.empty()) {
131  	    throw std::runtime_error(std::move(error));
132  	  }
133  	
134  	  // we need to specify the template parameter explicitly as ::length()
135  	  // returns unsigned int, not size_t.
136  	  const auto todo_len = \
137  	    std::min<std::size_t>(ciphertext.length(), out.max_length);
138  	  memcpy(out.buf, ciphertext.c_str(), todo_len);
139  	
140  	  return todo_len;
141  	}
142  	
143  	std::size_t CryptoKeyHandler::decrypt(
144  	  const CryptoKeyHandler::in_slice_t& in,
145  	  const CryptoKeyHandler::out_slice_t& out) const
146  	{
147  	  ceph::bufferptr inptr(reinterpret_cast<const char*>(in.buf), in.length);
148  	  ceph::bufferlist ciphertext;
149  	  ciphertext.append(std::move(inptr));
150  	
151  	  ceph::bufferlist plaintext;
152  	  std::string error;
153  	  const int ret = decrypt(ciphertext, plaintext, &error);
154  	  if (ret != 0 || !error.empty()) {
155  	    throw std::runtime_error(std::move(error));
156  	  }
157  	
158  	  // we need to specify the template parameter explicitly as ::length()
159  	  // returns unsigned int, not size_t.
160  	  const auto todo_len = \
161  	    std::min<std::size_t>(plaintext.length(), out.max_length);
162  	  memcpy(out.buf, plaintext.c_str(), todo_len);
163  	
164  	  return todo_len;
165  	}
166  	
167  	sha256_digest_t CryptoKeyHandler::hmac_sha256(
168  	  const ceph::bufferlist& in) const
169  	{
170  	  ceph::crypto::HMACSHA256 hmac((const unsigned char*)secret.c_str(), secret.length());
171  	
172  	  for (const auto& bptr : in.buffers()) {
173  	    hmac.Update((const unsigned char *)bptr.c_str(), bptr.length());
174  	  }
175  	  sha256_digest_t ret;
176  	  hmac.Final(ret.v);
177  	
178  	  return ret;
179  	}
180  	
181  	// ---------------------------------------------------
182  	
183  	class CryptoNoneKeyHandler : public CryptoKeyHandler {
184  	public:
185  	  CryptoNoneKeyHandler()
186  	    : CryptoKeyHandler(CryptoKeyHandler::BLOCK_SIZE_0B()) {
187  	  }
188  	
189  	  using CryptoKeyHandler::encrypt;
190  	  using CryptoKeyHandler::decrypt;
191  	
192  	  int encrypt(const bufferlist& in,
193  		       bufferlist& out, std::string *error) const override {
194  	    out = in;
195  	    return 0;
196  	  }
197  	  int decrypt(const bufferlist& in,
198  		      bufferlist& out, std::string *error) const override {
199  	    out = in;
200  	    return 0;
201  	  }
202  	};
203  	
204  	class CryptoNone : public CryptoHandler {
205  	public:
206  	  CryptoNone() { }
207  	  ~CryptoNone() override {}
208  	  int get_type() const override {
209  	    return CEPH_CRYPTO_NONE;
210  	  }
211  	  int create(CryptoRandom *random, bufferptr& secret) override {
212  	    return 0;
213  	  }
214  	  int validate_secret(const bufferptr& secret) override {
215  	    return 0;
216  	  }
217  	  CryptoKeyHandler *get_key_handler(const bufferptr& secret, string& error) override {
218  	    return new CryptoNoneKeyHandler;
219  	  }
220  	};
221  	
222  	
223  	// ---------------------------------------------------
224  	
225  	
226  	class CryptoAES : public CryptoHandler {
227  	public:
228  	  CryptoAES() { }
229  	  ~CryptoAES() override {}
230  	  int get_type() const override {
231  	    return CEPH_CRYPTO_AES;
232  	  }
233  	  int create(CryptoRandom *random, bufferptr& secret) override;
234  	  int validate_secret(const bufferptr& secret) override;
235  	  CryptoKeyHandler *get_key_handler(const bufferptr& secret, string& error) override;
236  	};
237  	
238  	// when we say AES, we mean AES-128
239  	static constexpr const std::size_t AES_KEY_LEN{16};
240  	static constexpr const std::size_t AES_BLOCK_LEN{16};
241  	
242  	class CryptoAESKeyHandler : public CryptoKeyHandler {
243  	  AES_KEY enc_key;
244  	  AES_KEY dec_key;
245  	
246  	public:
247  	  CryptoAESKeyHandler()
248  	    : CryptoKeyHandler(CryptoKeyHandler::BLOCK_SIZE_16B()) {
(2) Event uninit_member: Non-static class member field "enc_key.rounds" is not initialized in this constructor nor in any functions that it calls.
(4) Event uninit_member: Non-static class member field "dec_key.rounds" is not initialized in this constructor nor in any functions that it calls.
Also see events: [member_decl][member_decl]
249  	  }
250  	
251  	  int init(const bufferptr& s, ostringstream& err) {
252  	    secret = s;
253  	
254  	    const int enc_key_ret = \
255  	      AES_set_encrypt_key((const unsigned char*)secret.c_str(),
256  				  AES_KEY_LEN * CHAR_BIT, &enc_key);
257  	    if (enc_key_ret != 0) {
258  	      err << "cannot set OpenSSL encrypt key for AES: " << enc_key_ret;
259  	      return -1;
260  	    }
261  	
262  	    const int dec_key_ret = \
263  	      AES_set_decrypt_key((const unsigned char*)secret.c_str(),
264  				  AES_KEY_LEN * CHAR_BIT, &dec_key);
265  	    if (dec_key_ret != 0) {
266  	      err << "cannot set OpenSSL decrypt key for AES: " << dec_key_ret;
267  	      return -1;
268  	    }
269  	
270  	    return 0;
271  	  }
272  	
273  	  int encrypt(const ceph::bufferlist& in,
274  		      ceph::bufferlist& out,
275  	              std::string* /* unused */) const override {
276  	    // we need to take into account the PKCS#7 padding. There *always* will
277  	    // be at least one byte of padding. This stays even to input aligned to
278  	    // AES_BLOCK_LEN. Otherwise we would face ambiguities during decryption.
279  	    // To exemplify:
280  	    //   16 + p2align(10, 16) -> 16
281  	    //   16 + p2align(16, 16) -> 32 including 16 bytes for padding.
282  	    ceph::bufferptr out_tmp{static_cast<unsigned>(
283  	      AES_BLOCK_LEN + p2align<std::size_t>(in.length(), AES_BLOCK_LEN))};
284  	
285  	    // let's pad the data
286  	    std::uint8_t pad_len = out_tmp.length() - in.length();
287  	    ceph::bufferptr pad_buf{pad_len};
288  	    memset(pad_buf.c_str(), pad_len, pad_len);
289  	
290  	    // form contiguous buffer for block cipher. The ctor copies shallowly.
291  	    ceph::bufferlist incopy(in);
292  	    incopy.append(std::move(pad_buf));
293  	    const auto in_buf = reinterpret_cast<unsigned char*>(incopy.c_str());
294  	
295  	    // reinitialize IV each time. It might be unnecessary depending on
296  	    // actual implementation but at the interface layer we are obliged
297  	    // to deliver IV as non-const.
298  	    static_assert(strlen_ct(CEPH_AES_IV) == AES_BLOCK_LEN);
299  	    unsigned char iv[AES_BLOCK_LEN];
300  	    memcpy(iv, CEPH_AES_IV, AES_BLOCK_LEN);
301  	
302  	    // we aren't using EVP because of performance concerns. Profiling
303  	    // shows the cost is quite high. Endianness might be an issue.
304  	    // However, as they would affect Cephx, any fallout should pop up
305  	    // rather early, hopefully.
306  	    AES_cbc_encrypt(in_buf, reinterpret_cast<unsigned char*>(out_tmp.c_str()),
307  			    out_tmp.length(), &enc_key, iv, AES_ENCRYPT);
308  	
309  	    out.append(out_tmp);
310  	    return 0;
311  	  }
312  	
313  	  int decrypt(const ceph::bufferlist& in,
314  		      ceph::bufferlist& out,
315  		      std::string* /* unused */) const override {
316  	    // PKCS#7 padding enlarges even empty plain-text to take 16 bytes.
317  	    if (in.length() < AES_BLOCK_LEN || in.length() % AES_BLOCK_LEN) {
318  	      return -1;
319  	    }
320  	
321  	    // needed because of .c_str() on const. It's a shallow copy.
322  	    ceph::bufferlist incopy(in);
323  	    const auto in_buf = reinterpret_cast<unsigned char*>(incopy.c_str());
324  	
325  	    // make a local, modifiable copy of IV.
326  	    static_assert(strlen_ct(CEPH_AES_IV) == AES_BLOCK_LEN);
327  	    unsigned char iv[AES_BLOCK_LEN];
328  	    memcpy(iv, CEPH_AES_IV, AES_BLOCK_LEN);
329  	
330  	    ceph::bufferptr out_tmp{in.length()};
331  	    AES_cbc_encrypt(in_buf, reinterpret_cast<unsigned char*>(out_tmp.c_str()),
332  			    in.length(), &dec_key, iv, AES_DECRYPT);
333  	
334  	    // BE CAREFUL: we cannot expose any single bit of information about
335  	    // the cause of failure. Otherwise we'll face padding oracle attack.
336  	    // See: https://en.wikipedia.org/wiki/Padding_oracle_attack.
337  	    const auto pad_len = \
338  	      std::min<std::uint8_t>(out_tmp[in.length() - 1], AES_BLOCK_LEN);
339  	    out_tmp.set_length(in.length() - pad_len);
340  	    out.append(std::move(out_tmp));
341  	
342  	    return 0;
343  	  }
344  	
345  	  std::size_t encrypt(const in_slice_t& in,
346  			      const out_slice_t& out) const override {
347  	    if (out.buf == nullptr) {
348  	      // 16 + p2align(10, 16) -> 16
349  	      // 16 + p2align(16, 16) -> 32
350  	      return AES_BLOCK_LEN + p2align<std::size_t>(in.length, AES_BLOCK_LEN);
351  	    }
352  	
353  	    // how many bytes of in.buf hang outside the alignment boundary and how
354  	    // much padding we need.
355  	    //   length = 23 -> tail_len = 7, pad_len = 9
356  	    //   length = 32 -> tail_len = 0, pad_len = 16
357  	    const std::uint8_t tail_len = in.length % AES_BLOCK_LEN;
358  	    const std::uint8_t pad_len = AES_BLOCK_LEN - tail_len;
359  	    static_assert(std::numeric_limits<std::uint8_t>::max() > AES_BLOCK_LEN);
360  	
361  	    std::array<unsigned char, AES_BLOCK_LEN> last_block;
362  	    memcpy(last_block.data(), in.buf + in.length - tail_len, tail_len);
363  	    memset(last_block.data() + tail_len, pad_len, pad_len);
364  	
365  	    // need a local copy because AES_cbc_encrypt takes `iv` as non-const.
366  	    // Useful because it allows us to encrypt in two steps: main + tail.
367  	    static_assert(strlen_ct(CEPH_AES_IV) == AES_BLOCK_LEN);
368  	    std::array<unsigned char, AES_BLOCK_LEN> iv;
369  	    memcpy(iv.data(), CEPH_AES_IV, AES_BLOCK_LEN);
370  	
371  	    const std::size_t main_encrypt_size = \
372  	      std::min(in.length - tail_len, out.max_length);
373  	    AES_cbc_encrypt(in.buf, out.buf, main_encrypt_size, &enc_key, iv.data(),
374  			    AES_ENCRYPT);
375  	
376  	    const std::size_t tail_encrypt_size = \
377  	      std::min(AES_BLOCK_LEN, out.max_length - main_encrypt_size);
378  	    AES_cbc_encrypt(last_block.data(), out.buf + main_encrypt_size,
379  			    tail_encrypt_size, &enc_key, iv.data(), AES_ENCRYPT);
380  	
381  	    return main_encrypt_size + tail_encrypt_size;
382  	  }
383  	
384  	  std::size_t decrypt(const in_slice_t& in,
385  			      const out_slice_t& out) const override {
386  	    if (in.length % AES_BLOCK_LEN != 0 || in.length < AES_BLOCK_LEN) {
387  	      throw std::runtime_error("input not aligned to AES_BLOCK_LEN");
388  	    } else if (out.buf == nullptr) {
389  	      // essentially it would be possible to decrypt into a buffer that
390  	      // doesn't include space for any PKCS#7 padding. We don't do that
391  	      // for the sake of performance and simplicity.
392  	      return in.length;
393  	    } else if (out.max_length < in.length) {
394  	      throw std::runtime_error("output buffer too small");
395  	    }
396  	
397  	    static_assert(strlen_ct(CEPH_AES_IV) == AES_BLOCK_LEN);
398  	    std::array<unsigned char, AES_BLOCK_LEN> iv;
399  	    memcpy(iv.data(), CEPH_AES_IV, AES_BLOCK_LEN);
400  	
401  	    AES_cbc_encrypt(in.buf, out.buf, in.length, &dec_key, iv.data(),
402  			    AES_DECRYPT);
403  	
404  	    // NOTE: we aren't handling partial decrypt. PKCS#7 padding must be
405  	    // at the end. If it's malformed, don't say a word to avoid risk of
406  	    // having an oracle. All we need to ensure is valid buffer boundary.
407  	    const auto pad_len = \
408  	      std::min<std::uint8_t>(out.buf[in.length - 1], AES_BLOCK_LEN);
409  	    return in.length - pad_len;
410  	  }
411  	};
412  	
413  	
414  	// ------------------------------------------------------------
415  	
416  	int CryptoAES::create(CryptoRandom *random, bufferptr& secret)
417  	{
418  	  bufferptr buf(AES_KEY_LEN);
419  	  random->get_bytes(buf.c_str(), buf.length());
420  	  secret = std::move(buf);
421  	  return 0;
422  	}
423  	
424  	int CryptoAES::validate_secret(const bufferptr& secret)
425  	{
426  	  if (secret.length() < AES_KEY_LEN) {
427  	    return -EINVAL;
428  	  }
429  	
430  	  return 0;
431  	}
432  	
433  	CryptoKeyHandler *CryptoAES::get_key_handler(const bufferptr& secret,
434  						     string& error)
435  	{
436  	  CryptoAESKeyHandler *ckh = new CryptoAESKeyHandler;
437  	  ostringstream oss;
438  	  if (ckh->init(secret, oss) < 0) {
439  	    error = oss.str();
440  	    delete ckh;
441  	    return NULL;
442  	  }
443  	  return ckh;
444  	}
445  	
446  	
447  	
448  	
449  	// --
450  	
451  	
452  	// ---------------------------------------------------
453  	
454  	
455  	void CryptoKey::encode(bufferlist& bl) const
456  	{
457  	  using ceph::encode;
458  	  encode(type, bl);
459  	  encode(created, bl);
460  	  __u16 len = secret.length();
461  	  encode(len, bl);
462  	  bl.append(secret);
463  	}
464  	
465  	void CryptoKey::decode(bufferlist::const_iterator& bl)
466  	{
467  	  using ceph::decode;
468  	  decode(type, bl);
469  	  decode(created, bl);
470  	  __u16 len;
471  	  decode(len, bl);
472  	  bufferptr tmp;
473  	  bl.copy_deep(len, tmp);
474  	  if (_set_secret(type, tmp) < 0)
475  	    throw buffer::malformed_input("malformed secret");
476  	}
477  	
478  	int CryptoKey::set_secret(int type, const bufferptr& s, utime_t c)
479  	{
480  	  int r = _set_secret(type, s);
481  	  if (r < 0)
482  	    return r;
483  	  this->created = c;
484  	  return 0;
485  	}
486  	
487  	int CryptoKey::_set_secret(int t, const bufferptr& s)
488  	{
489  	  if (s.length() == 0) {
490  	    secret = s;
491  	    ckh.reset();
492  	    return 0;
493  	  }
494  	
495  	  CryptoHandler *ch = CryptoHandler::create(t);
496  	  if (ch) {
497  	    int ret = ch->validate_secret(s);
498  	    if (ret < 0) {
499  	      delete ch;
500  	      return ret;
501  	    }
502  	    string error;
503  	    ckh.reset(ch->get_key_handler(s, error));
504  	    delete ch;
505  	    if (error.length()) {
506  	      return -EIO;
507  	    }
508  	  } else {
509  	      return -EOPNOTSUPP;
510  	  }
511  	  type = t;
512  	  secret = s;
513  	  return 0;
514  	}
515  	
516  	int CryptoKey::create(CephContext *cct, int t)
517  	{
518  	  CryptoHandler *ch = CryptoHandler::create(t);
519  	  if (!ch) {
520  	    if (cct)
521  	      lderr(cct) << "ERROR: cct->get_crypto_handler(type=" << t << ") returned NULL" << dendl;
522  	    return -EOPNOTSUPP;
523  	  }
524  	  bufferptr s;
525  	  int r = ch->create(cct->random(), s);
526  	  delete ch;
527  	  if (r < 0)
528  	    return r;
529  	
530  	  r = _set_secret(t, s);
531  	  if (r < 0)
532  	    return r;
533  	  created = ceph_clock_now();
534  	  return r;
535  	}
536  	
537  	void CryptoKey::print(std::ostream &out) const
538  	{
539  	  out << encode_base64();
540  	}
541  	
542  	void CryptoKey::to_str(std::string& s) const
543  	{
544  	  int len = secret.length() * 4;
545  	  char buf[len];
546  	  hex2str(secret.c_str(), secret.length(), buf, len);
547  	  s = buf;
548  	}
549  	
550  	void CryptoKey::encode_formatted(string label, Formatter *f, bufferlist &bl)
551  	{
552  	  f->open_object_section(label.c_str());
553  	  f->dump_string("key", encode_base64());
554  	  f->close_section();
555  	  f->flush(bl);
556  	}
557  	
558  	void CryptoKey::encode_plaintext(bufferlist &bl)
559  	{
560  	  bl.append(encode_base64());
561  	}
562  	
563  	
564  	// ------------------
565  	
566  	CryptoHandler *CryptoHandler::create(int type)
567  	{
568  	  switch (type) {
569  	  case CEPH_CRYPTO_NONE:
570  	    return new CryptoNone;
571  	  case CEPH_CRYPTO_AES:
572  	    return new CryptoAES;
573  	  default:
574  	    return NULL;
575  	  }
576  	}
577