]> git.proxmox.com Git - ceph.git/blob - ceph/src/auth/Crypto.h
3691d97feee0f80c8ac37add93e960003da3e65f
[ceph.git] / ceph / src / auth / Crypto.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2004-2009 Sage Weil <sage@newdream.net>
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15 #ifndef CEPH_AUTH_CRYPTO_H
16 #define CEPH_AUTH_CRYPTO_H
17
18 #include "include/common_fwd.h"
19 #include "include/types.h"
20 #include "include/utime.h"
21 #include "include/buffer.h"
22
23 #include <string>
24
25 class CryptoKeyContext;
26 namespace ceph { class Formatter; }
27
28 /*
29 * Random byte stream generator suitable for cryptographic use
30 */
31 class CryptoRandom {
32 public:
33 CryptoRandom(); // throws on failure
34 ~CryptoRandom();
35 /// copy up to 256 random bytes into the given buffer. throws on failure
36 void get_bytes(char *buf, int len);
37 private:
38 static int open_urandom();
39 const int fd;
40 };
41
42 /*
43 * some per-key context that is specific to a particular crypto backend
44 */
45 class CryptoKeyHandler {
46 public:
47 // The maximum size of a single block for all descendants of the class.
48 static constexpr std::size_t MAX_BLOCK_SIZE {16};
49
50 // A descendant pick-ups one from these and passes it to the ctor template.
51 typedef std::integral_constant<std::size_t, 0> BLOCK_SIZE_0B;
52 typedef std::integral_constant<std::size_t, 16> BLOCK_SIZE_16B;
53
54 struct in_slice_t {
55 const std::size_t length;
56 const unsigned char* const buf;
57 };
58
59 struct out_slice_t {
60 const std::size_t max_length;
61 unsigned char* const buf;
62 };
63
64 ceph::bufferptr secret;
65
66 template <class BlockSizeT>
67 CryptoKeyHandler(BlockSizeT) {
68 static_assert(BlockSizeT::value <= MAX_BLOCK_SIZE);
69 }
70
71 virtual ~CryptoKeyHandler() {}
72
73 virtual int encrypt(const ceph::buffer::list& in,
74 ceph::buffer::list& out, std::string *error) const = 0;
75 virtual int decrypt(const ceph::buffer::list& in,
76 ceph::buffer::list& out, std::string *error) const = 0;
77
78 // TODO: provide nullptr in the out::buf to get/estimate size requirements?
79 // Or maybe dedicated methods?
80 virtual std::size_t encrypt(const in_slice_t& in,
81 const out_slice_t& out) const;
82 virtual std::size_t decrypt(const in_slice_t& in,
83 const out_slice_t& out) const;
84
85 sha256_digest_t hmac_sha256(const ceph::bufferlist& in) const;
86 };
87
88 /*
89 * match encoding of struct ceph_secret
90 */
91 class CryptoKey {
92 protected:
93 __u16 type;
94 utime_t created;
95 ceph::buffer::ptr secret; // must set this via set_secret()!
96
97 // cache a pointer to the implementation-specific key handler, so we
98 // don't have to create it for every crypto operation.
99 mutable std::shared_ptr<CryptoKeyHandler> ckh;
100
101 int _set_secret(int type, const ceph::buffer::ptr& s);
102
103 public:
104 CryptoKey() : type(0) { }
105 CryptoKey(int t, utime_t c, ceph::buffer::ptr& s)
106 : created(c) {
107 _set_secret(t, s);
108 }
109 ~CryptoKey() {
110 }
111
112 void encode(ceph::buffer::list& bl) const;
113 void decode(ceph::buffer::list::const_iterator& bl);
114
115 int get_type() const { return type; }
116 utime_t get_created() const { return created; }
117 void print(std::ostream& out) const;
118
119 int set_secret(int type, const ceph::buffer::ptr& s, utime_t created);
120 const ceph::buffer::ptr& get_secret() { return secret; }
121 const ceph::buffer::ptr& get_secret() const { return secret; }
122
123 bool empty() const { return ckh.get() == nullptr; }
124
125 void encode_base64(std::string& s) const {
126 ceph::buffer::list bl;
127 encode(bl);
128 ceph::bufferlist e;
129 bl.encode_base64(e);
130 e.append('\0');
131 s = e.c_str();
132 }
133 std::string encode_base64() const {
134 std::string s;
135 encode_base64(s);
136 return s;
137 }
138 void decode_base64(const std::string& s) {
139 ceph::buffer::list e;
140 e.append(s);
141 ceph::buffer::list bl;
142 bl.decode_base64(e);
143 auto p = std::cbegin(bl);
144 decode(p);
145 }
146
147 void encode_formatted(std::string label, ceph::Formatter *f,
148 ceph::buffer::list &bl);
149 void encode_plaintext(ceph::buffer::list &bl);
150
151 // --
152 int create(CephContext *cct, int type);
153 int encrypt(CephContext *cct, const ceph::buffer::list& in,
154 ceph::buffer::list& out,
155 std::string *error) const {
156 ceph_assert(ckh); // Bad key?
157 return ckh->encrypt(in, out, error);
158 }
159 int decrypt(CephContext *cct, const ceph::buffer::list& in,
160 ceph::buffer::list& out,
161 std::string *error) const {
162 ceph_assert(ckh); // Bad key?
163 return ckh->decrypt(in, out, error);
164 }
165
166 using in_slice_t = CryptoKeyHandler::in_slice_t;
167 using out_slice_t = CryptoKeyHandler::out_slice_t;
168
169 std::size_t encrypt(CephContext*, const in_slice_t& in,
170 const out_slice_t& out) {
171 ceph_assert(ckh);
172 return ckh->encrypt(in, out);
173 }
174 std::size_t decrypt(CephContext*, const in_slice_t& in,
175 const out_slice_t& out) {
176 ceph_assert(ckh);
177 return ckh->encrypt(in, out);
178 }
179
180 sha256_digest_t hmac_sha256(CephContext*, const ceph::buffer::list& in) {
181 ceph_assert(ckh);
182 return ckh->hmac_sha256(in);
183 }
184
185 static constexpr std::size_t get_max_outbuf_size(std::size_t want_size) {
186 return want_size + CryptoKeyHandler::MAX_BLOCK_SIZE;
187 }
188
189 void to_str(std::string& s) const;
190 };
191 WRITE_CLASS_ENCODER(CryptoKey)
192
193 inline std::ostream& operator<<(std::ostream& out, const CryptoKey& k)
194 {
195 k.print(out);
196 return out;
197 }
198
199
200 /*
201 * Driver for a particular algorithm
202 *
203 * To use these functions, you need to call ceph::crypto::init(), see
204 * common/ceph_crypto.h. common_init_finish does this for you.
205 */
206 class CryptoHandler {
207 public:
208 virtual ~CryptoHandler() {}
209 virtual int get_type() const = 0;
210 virtual int create(CryptoRandom *random, ceph::buffer::ptr& secret) = 0;
211 virtual int validate_secret(const ceph::buffer::ptr& secret) = 0;
212 virtual CryptoKeyHandler *get_key_handler(const ceph::buffer::ptr& secret,
213 std::string& error) = 0;
214
215 static CryptoHandler *create(int type);
216 };
217
218
219 #endif