Whamcloud - gitweb
0601a46491cf540651b2378dc5caa40157bb2f1f
[fs/lustre-release.git] / lustre / utils / gss / sk_utils.h
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (C) 2015, Trustees of Indiana University
24  *
25  * Author: Jeremy Filizetti <jfilizet@iu.edu>
26  */
27
28 #ifndef SK_UTILS_H
29 #define SK_UTILS_H
30
31 #ifdef HAVE_OPENSSL_SSK
32 #include <gssapi/gssapi.h>
33 #ifdef HAVE_LIBKEYUTILS
34 #include <keyutils.h>
35 #endif
36 #include <linux/lustre/lustre_idl.h>
37 /* We need to use some deprecated APIs */
38 #define OPENSSL_SUPPRESS_DEPRECATED
39 #include <openssl/dh.h>
40 #include <openssl/evp.h>
41 #include <openssl/hmac.h>
42 #include <sys/types.h>
43
44 #include <libcfs/libcfs_crypto.h>
45 #include "lsupport.h"
46
47 #ifndef ARRAY_SIZE
48 # define ARRAY_SIZE(a) ((sizeof(a)) / (sizeof((a)[0])))
49 #endif /* !ARRAY_SIZE */
50
51 /* LL_CRYPTO_MAX_NAME value must match value of
52  * CRYPTO_MAX_ALG_NAME in include/linux/crypto.h
53  */
54 #ifdef HAVE_CRYPTO_MAX_ALG_NAME_128
55 #define LL_CRYPTO_MAX_NAME 128
56 #else
57 #define LL_CRYPTO_MAX_NAME 64
58 #endif
59
60 #if OPENSSL_VERSION_NUMBER < 0x10100000L
61 static inline HMAC_CTX *HMAC_CTX_new(void)
62 {
63         HMAC_CTX *ctx = OPENSSL_malloc(sizeof(*ctx));
64
65         if (ctx != NULL)
66                 HMAC_CTX_init(ctx);
67         return ctx;
68 }
69
70 static inline void HMAC_CTX_free(HMAC_CTX *ctx)
71 {
72         if (ctx != NULL) {
73                 HMAC_CTX_cleanup(ctx);
74                 OPENSSL_cleanse(ctx, sizeof(*ctx));
75                 OPENSSL_free(ctx);
76         }
77 }
78 static inline void DH_get0_pqg(const DH *dh,
79                                const BIGNUM **p, const BIGNUM **q,
80                                const BIGNUM **g)
81 {
82         if (p != NULL)
83                 *p = dh->p;
84         if (q != NULL)
85                 *q = dh->q;
86         if (g != NULL)
87                 *g = dh->g;
88 }
89
90 static inline int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
91 {
92         /* If the fields p and g in dh are NULL, the corresponding input
93          * parameters MUST be non-NULL.  q may remain NULL.
94          */
95         if ((dh->p == NULL && p == NULL)
96             || (dh->g == NULL && g == NULL))
97                 return 0;
98
99         if (p != NULL) {
100                 BN_free(dh->p);
101                 dh->p = p;
102         }
103         if (q != NULL) {
104                 BN_free(dh->q);
105                 dh->q = q;
106         }
107         if (g != NULL) {
108                 BN_free(dh->g);
109                 dh->g = g;
110         }
111
112         if (q != NULL)
113                 dh->length = BN_num_bits(q);
114
115         return 1;
116 }
117
118 static inline void DH_get0_key(const DH *dh, const BIGNUM **pub_key,
119                                const BIGNUM **priv_key)
120 {
121         if (pub_key != NULL)
122                 *pub_key = dh->pub_key;
123         if (priv_key != NULL)
124                 *priv_key = dh->priv_key;
125 }
126 #endif
127
128 /* Some limits and defaults */
129 #define SK_CONF_VERSION 1
130 #define SK_MSG_VERSION 1
131 #define SK_GENERATOR 2
132 #define SK_SESSION_MAX_KEYLEN_BYTES 1024
133 #define SK_MAX_KEYLEN_BYTES 128
134 #define SK_MAX_P_BYTES 2048
135 #define SK_NONCE_SIZE 4
136 #define MAX_MGSNIDS 16
137
138 enum sk_ctx_init_buffers {
139         /* Initiator netstring buffer ordering */
140         SK_INIT_VERSION = 0,
141         SK_INIT_RANDOM  = 1,
142         SK_INIT_P       = 2,
143         SK_INIT_PUB_KEY = 3,
144         SK_INIT_TARGET  = 4,
145         SK_INIT_NODEMAP = 5,
146         SK_INIT_FLAGS   = 6,
147         SK_INIT_HMAC    = 7,
148         SK_INIT_BUFFERS = 8,
149
150         /* Responder netstring buffer ordering */
151         SK_RESP_VERSION = 0,
152         SK_RESP_RANDOM  = 1,
153         SK_RESP_PUB_KEY = 2,
154         SK_RESP_HMAC    = 3,
155         SK_RESP_BUFFERS = 4,
156 };
157
158 /* String consisting of "lustre:fsname:nodemap_hash" */
159 #define SK_DESCRIPTION_SIZE (9 + MTI_NAME_MAXLEN + LUSTRE_NODEMAP_NAME_LENGTH)
160
161 enum sk_key_type {
162         SK_TYPE_INVALID = 0x0,
163         SK_TYPE_CLIENT  = 0x1,
164         SK_TYPE_SERVER  = 0x2,
165         SK_TYPE_MGS     = 0x4,
166 };
167
168 /* This is the packed structure format of key files that are distributed.
169  * The on disk format should be store in big-endian. */
170 struct sk_keyfile_config {
171         /* File format version */
172         uint32_t        skc_version;
173         /* HMAC algorithm used for message integrity */
174         uint16_t        skc_hmac_alg;
175         /* Crypt algorithm used for privacy mode */
176         uint16_t        skc_crypt_alg;
177         /* Number of seconds that a context is valid after it is created from
178          * this keyfile */
179         uint32_t        skc_expire;
180         /* Length of shared key in skc_shared_key */
181         uint32_t        skc_shared_keylen;
182         /* Length of the prime used in the DHKE */
183         uint32_t        skc_prime_bits;
184         /* Key type */
185         uint8_t         skc_type;
186         /* Array of MGS NIDs to load key's for.  This is for the client since
187          * the upcall only knows the target name which is MGC<IP>@<NET>
188          * Only needed when mounting with mgssec */
189         lnet_nid_t      skc_mgsnids[MAX_MGSNIDS];
190         /* File system name for this key.  It can be unused for MGS only keys */
191         char            skc_fsname[MTI_NAME_MAXLEN + 1];
192         /* Nodemap name for this key.  Used by the server side to verify the
193          * client is in the correct nodemap */
194         char            skc_nodemap[LUSTRE_NODEMAP_NAME_LENGTH + 1];
195         /* Shared key */
196         unsigned char   skc_shared_key[SK_MAX_KEYLEN_BYTES];
197         /* Prime (p) for DHKE */
198         unsigned char   skc_p[SK_MAX_P_BYTES];
199 } __attribute__((packed));
200
201 /* Format passed to the kernel from userspace */
202 struct sk_kernel_ctx {
203         uint32_t        skc_version;
204         char            skc_hmac_alg[LL_CRYPTO_MAX_NAME];
205         char            skc_crypt_alg[LL_CRYPTO_MAX_NAME];
206         uint32_t        skc_expire;
207         uint32_t        skc_host_random;
208         uint32_t        skc_peer_random;
209         gss_buffer_desc skc_hmac_key;
210         gss_buffer_desc skc_encrypt_key;
211         gss_buffer_desc skc_shared_key;
212         gss_buffer_desc skc_session_key;
213 };
214
215 /* Structure used in context initiation to hold all necessary data */
216 struct sk_cred {
217         uint32_t                 sc_flags;
218         gss_buffer_desc          sc_p;
219         gss_buffer_desc          sc_pub_key;
220         gss_buffer_desc          sc_tgt;
221         gss_buffer_desc          sc_nodemap_hash;
222         gss_buffer_desc          sc_hmac;
223         gss_buffer_desc          sc_dh_shared_key;
224         struct sk_kernel_ctx     sc_kctx;
225         DH                      *sc_params;
226 };
227
228 /* Names match up with openssl enc and dgst commands */
229 /* When adding new alg types, make sure first occurrence's name
230  * matches cht_name in hash_types array.
231  */
232 static const struct sk_crypt_type sk_crypt_algs[] = {
233         {
234                 .sct_name = "null",
235                 .sct_type = SK_CRYPT_EMPTY
236         },
237         {
238                 .sct_name = "NONE",
239                 .sct_type = SK_CRYPT_EMPTY
240         },
241         {
242                 .sct_name = "ctr(aes)",
243                 .sct_type = SK_CRYPT_AES256_CTR
244         },
245         {
246                 .sct_name = "AES-256-CTR",
247                 .sct_type = SK_CRYPT_AES256_CTR
248         }
249 };
250 static const struct sk_hmac_type sk_hmac_algs[] = {
251         {
252                 .sht_name = "null",
253                 .sht_type = SK_HMAC_EMPTY
254         },
255         {
256                 .sht_name = "NONE",
257                 .sht_type = SK_HMAC_EMPTY
258         },
259         {
260                 .sht_name = "sha256",
261                 .sht_type = SK_HMAC_SHA256
262         },
263         {
264                 .sht_name = "SHA256",
265                 .sht_type = SK_HMAC_SHA256
266         },
267         {
268                 .sht_name = "sha512",
269                 .sht_type = SK_HMAC_SHA512
270         },
271         {
272                 .sht_name = "SHA512",
273                 .sht_type = SK_HMAC_SHA512
274         }
275 };
276
277 static inline int sk_name2crypt(char *name)
278 {
279         int i;
280
281         for (i = 0; i < ARRAY_SIZE(sk_crypt_algs); i++) {
282                 if (strcasecmp(name, sk_crypt_algs[i].sct_name) == 0)
283                         return sk_crypt_algs[i].sct_type;
284         }
285
286         return SK_CRYPT_INVALID;
287 }
288
289 static inline int sk_name2hmac(char *name)
290 {
291         int i;
292
293         for (i = 0; i < ARRAY_SIZE(sk_hmac_algs); i++) {
294                 if (strcasecmp(name, sk_hmac_algs[i].sht_name) == 0)
295                         return sk_hmac_algs[i].sht_type;
296         }
297
298         return SK_HMAC_INVALID;
299 }
300
301 static inline const char *sk_crypt2name(enum sk_crypt_alg type)
302 {
303         int i;
304
305         for (i = 0; i < ARRAY_SIZE(sk_crypt_algs); i++) {
306                 if (type == sk_crypt_algs[i].sct_type)
307                         return sk_crypt_algs[i].sct_name;
308         }
309
310         return NULL;
311 }
312
313 static inline const char *sk_hmac2name(enum sk_hmac_alg type)
314 {
315         int i;
316
317         for (i = 0; i < ARRAY_SIZE(sk_hmac_algs); i++) {
318                 if (type == sk_hmac_algs[i].sht_type)
319                         return sk_hmac_algs[i].sht_name;
320         }
321
322         return NULL;
323 }
324
325 void sk_init_logging(char *program, int verbose, int fg);
326 struct sk_keyfile_config *sk_read_file(char *filename);
327 int sk_load_keyfile(char *path);
328 void sk_config_disk_to_cpu(struct sk_keyfile_config *config);
329 void sk_config_cpu_to_disk(struct sk_keyfile_config *config);
330 int sk_validate_config(const struct sk_keyfile_config *config);
331 uint32_t sk_verify_hash(const char *string, const EVP_MD *hash_alg,
332                         const gss_buffer_desc *current_hash);
333 struct sk_cred *sk_create_cred(const char *fsname, const char *cluster,
334                                const uint32_t flags);
335 int sk_speedtest_dh_valid(unsigned int usec_check_max);
336 uint32_t sk_gen_params(struct sk_cred *skc, int num_rounds);
337 int sk_sign_bufs(gss_buffer_desc *key, gss_buffer_desc *bufs, const int numbufs,
338                  const EVP_MD *hash_alg, gss_buffer_desc *hmac);
339 uint32_t sk_verify_hmac(struct sk_cred *skc, gss_buffer_desc *bufs,
340                         const int numbufs, const EVP_MD *hash_alg,
341                         gss_buffer_desc *hmac);
342 void sk_free_cred(struct sk_cred *skc);
343 int sk_session_kdf(struct sk_cred *skc, lnet_nid_t client_nid,
344                    gss_buffer_desc *client_token, gss_buffer_desc *server_token);
345 uint32_t sk_compute_dh_key(struct sk_cred *skc, const gss_buffer_desc *pub_key);
346 int sk_compute_keys(struct sk_cred *skc);
347 int sk_serialize_kctx(struct sk_cred *skc, gss_buffer_desc *ctx_token);
348 int sk_decode_netstring(gss_buffer_desc *bufs, int numbufs,
349                         gss_buffer_desc *ns);
350 int sk_encode_netstring(gss_buffer_desc *bufs, int numbufs,
351                         gss_buffer_desc *ns);
352
353 #endif /* HAVE_OPENSSL_SSK */
354 #endif /* SK_UTILS_H */