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