Whamcloud - gitweb
e54d6c4b5c3638715e73b1c7a0c00cb57ba53ddf
[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 #include <linux/lustre/lustre_disk.h>
38 #include <openssl/dh.h>
39 #include <openssl/dsa.h>
40 #include <openssl/evp.h>
41 #include <openssl/hmac.h>
42 #ifdef HAVE_OPENSSL_FIPS
43 #include <openssl/fips.h>
44 #endif
45 #ifdef HAVE_OPENSSL_EVP_PKEY
46 #include <openssl/core_names.h>
47 #endif
48 #include <openssl/err.h>
49 #include <sys/types.h>
50
51 #include <libcfs/libcfs_crypto.h>
52 #include "lsupport.h"
53
54 #ifndef ARRAY_SIZE
55 # define ARRAY_SIZE(a) ((sizeof(a)) / (sizeof((a)[0])))
56 #endif /* !ARRAY_SIZE */
57
58 /* LL_CRYPTO_MAX_NAME value must match value of
59  * CRYPTO_MAX_ALG_NAME in include/linux/crypto.h
60  */
61 #ifdef HAVE_CRYPTO_MAX_ALG_NAME_128
62 #define LL_CRYPTO_MAX_NAME 128
63 #else
64 #define LL_CRYPTO_MAX_NAME 64
65 #endif
66
67 #if OPENSSL_VERSION_NUMBER < 0x10100000L
68 static inline HMAC_CTX *HMAC_CTX_new(void)
69 {
70         HMAC_CTX *ctx = OPENSSL_malloc(sizeof(*ctx));
71
72         if (ctx != NULL)
73                 HMAC_CTX_init(ctx);
74         return ctx;
75 }
76
77 static inline void HMAC_CTX_free(HMAC_CTX *ctx)
78 {
79         if (ctx != NULL) {
80                 HMAC_CTX_cleanup(ctx);
81                 OPENSSL_cleanse(ctx, sizeof(*ctx));
82                 OPENSSL_free(ctx);
83         }
84 }
85 static inline void DH_get0_pqg(const DH *dh,
86                                const BIGNUM **p, const BIGNUM **q,
87                                const BIGNUM **g)
88 {
89         if (p != NULL)
90                 *p = dh->p;
91         if (q != NULL)
92                 *q = dh->q;
93         if (g != NULL)
94                 *g = dh->g;
95 }
96
97 static inline int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
98 {
99         /* If the fields p and g in dh are NULL, the corresponding input
100          * parameters MUST be non-NULL.  q may remain NULL.
101          */
102         if ((dh->p == NULL && p == NULL)
103             || (dh->g == NULL && g == NULL))
104                 return 0;
105
106         if (p != NULL) {
107                 BN_free(dh->p);
108                 dh->p = p;
109         }
110         if (q != NULL) {
111                 BN_free(dh->q);
112                 dh->q = q;
113         }
114         if (g != NULL) {
115                 BN_free(dh->g);
116                 dh->g = g;
117         }
118
119         if (q != NULL)
120                 dh->length = BN_num_bits(q);
121
122         return 1;
123 }
124
125 static inline void DH_get0_key(const DH *dh, const BIGNUM **pub_key,
126                                const BIGNUM **priv_key)
127 {
128         if (pub_key != NULL)
129                 *pub_key = dh->pub_key;
130         if (priv_key != NULL)
131                 *priv_key = dh->priv_key;
132 }
133
134 static inline const BIGNUM *DH_get0_p(const DH *dh)
135 {
136         return dh->p;
137 }
138 #endif
139
140 #ifndef HAVE_OPENSSL_FIPS
141 #define FIPS_mode()     0
142 #endif
143
144 /* Some limits and defaults */
145 #define SK_CONF_VERSION 1
146 #define SK_MSG_VERSION 1
147 #define SK_GENERATOR 2
148 #define SK_SESSION_MAX_KEYLEN_BYTES 1024
149 #define SK_MAX_KEYLEN_BYTES 128
150 #define SK_MAX_P_BYTES 2048
151 #define SK_NONCE_SIZE 4
152 #define MAX_MGSNIDS 16
153
154 enum sk_ctx_init_buffers {
155         /* Initiator netstring buffer ordering */
156         SK_INIT_VERSION = 0,
157         SK_INIT_RANDOM  = 1,
158         SK_INIT_P       = 2,
159         SK_INIT_PUB_KEY = 3,
160         SK_INIT_TARGET  = 4,
161         SK_INIT_NODEMAP = 5,
162         SK_INIT_FLAGS   = 6,
163         SK_INIT_HMAC    = 7,
164         SK_INIT_BUFFERS = 8,
165
166         /* Responder netstring buffer ordering */
167         SK_RESP_VERSION = 0,
168         SK_RESP_RANDOM  = 1,
169         SK_RESP_PUB_KEY = 2,
170         SK_RESP_HMAC    = 3,
171         SK_RESP_BUFFERS = 4,
172 };
173
174 /* String consisting of "lustre:fsname:nodemap_hash" */
175 #define SK_DESCRIPTION_SIZE (9 + MTI_NAME_MAXLEN + LUSTRE_NODEMAP_NAME_LENGTH)
176
177 enum sk_key_type {
178         SK_TYPE_INVALID = 0x0,
179         SK_TYPE_CLIENT  = 0x1,
180         SK_TYPE_SERVER  = 0x2,
181         SK_TYPE_MGS     = 0x4,
182 };
183
184 /* This is the packed structure format of key files that are distributed.
185  * The on disk format should be store in big-endian. */
186 struct sk_keyfile_config {
187         /* File format version */
188         uint32_t        skc_version;
189         /* HMAC algorithm used for message integrity */
190         uint16_t        skc_hmac_alg;
191         /* Crypt algorithm used for privacy mode */
192         uint16_t        skc_crypt_alg;
193         /* Number of seconds that a context is valid after it is created from
194          * this keyfile */
195         uint32_t        skc_expire;
196         /* Length of shared key in skc_shared_key */
197         uint32_t        skc_shared_keylen;
198         /* Length of the prime used in the DHKE */
199         uint32_t        skc_prime_bits;
200         /* Key type */
201         uint8_t         skc_type;
202         /* Array of MGS NIDs to load key's for.  This is for the client since
203          * the upcall only knows the target name which is MGC<IP>@<NET>
204          * Only needed when mounting with mgssec */
205         lnet_nid_t      skc_mgsnids[MAX_MGSNIDS];
206         /* File system name for this key.  It can be unused for MGS only keys */
207         char            skc_fsname[MTI_NAME_MAXLEN + 1];
208         /* Nodemap name for this key.  Used by the server side to verify the
209          * client is in the correct nodemap */
210         char            skc_nodemap[LUSTRE_NODEMAP_NAME_LENGTH + 1];
211         /* Shared key */
212         unsigned char   skc_shared_key[SK_MAX_KEYLEN_BYTES];
213         /* Prime (p) for DHKE */
214         unsigned char   skc_p[SK_MAX_P_BYTES];
215 } __attribute__((packed));
216
217 /* Format passed to the kernel from userspace */
218 struct sk_kernel_ctx {
219         uint32_t        skc_version;
220         char            skc_hmac_alg[LL_CRYPTO_MAX_NAME];
221         char            skc_crypt_alg[LL_CRYPTO_MAX_NAME];
222         uint32_t        skc_expire;
223         uint32_t        skc_host_random;
224         uint32_t        skc_peer_random;
225         gss_buffer_desc skc_hmac_key;
226         gss_buffer_desc skc_encrypt_key;
227         gss_buffer_desc skc_shared_key;
228         gss_buffer_desc skc_session_key;
229 };
230
231
232 #ifdef HAVE_OPENSSL_EVP_PKEY
233 #define DECLARE_EVP_MD(name, hash)                                      \
234         OSSL_PARAM name[] = {                                           \
235                 OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, \
236                                                (char *)EVP_MD_get0_name(hash), \
237                                                0),                      \
238                 OSSL_PARAM_END                                          \
239         }
240 #else /* !HAVE_OPENSSL_EVP_PKEY */
241 #define EVP_PKEY DH
242 #define EVP_PKEY_free(dh) DH_free(dh)
243 struct dh_ssk_ctx { uint32_t bits; uint32_t gen; };
244 #define EVP_PKEY_CTX struct dh_ssk_ctx
245 #define EVP_PKEY_CTX_new_from_name(p1, name, p2) malloc(sizeof(EVP_PKEY_CTX))
246 #define EVP_PKEY_paramgen_init(ctx) 1
247 #undef EVP_PKEY_CTX_set_dh_paramgen_prime_len
248 #define EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len) ((ctx)->bits = len)
249 #undef EVP_PKEY_CTX_set_dh_paramgen_generator
250 #define EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, g) ((ctx)->gen = g)
251 #define EVP_PKEY_paramgen(ctx, dhp)                                     \
252         ((*dhp = DH_new()) &&                                           \
253          DH_generate_parameters_ex(*(dhp), (ctx)->bits, (ctx)->gen, NULL))
254 #define EVP_PKEY_get_bn_param(dh, param, bnp) (*bnp = (BIGNUM *)DH_get0_p(dh))
255 #define EVP_PKEY_CTX_free(ctx) free(ctx)
256 #define DECLARE_EVP_MD(name, hash)      \
257         const EVP_MD *name = hash
258 #define EVP_MAC_CTX HMAC_CTX
259 #define EVP_MAC_CTX_new(mac) HMAC_CTX_new()
260 #define EVP_MAC_CTX_free HMAC_CTX_free
261 #define EVP_MAC void
262 #define EVP_MAC_fetch(a, b, c) (void *)1
263 #define EVP_MAC_init(ctx, val, len, alg) HMAC_Init_ex(ctx, val, len, alg, NULL)
264 #define EVP_MAC_update HMAC_Update
265 #define EVP_MAC_final(ctx, val, lenp, hlen)             \
266         HMAC_Final(ctx, val, (unsigned int *)(lenp))
267 #define EVP_MAC_free(mac) {}
268 #endif
269
270 /* Structure used in context initiation to hold all necessary data */
271 struct sk_cred {
272         uint32_t                 sc_flags;
273         gss_buffer_desc          sc_p;
274         gss_buffer_desc          sc_pub_key;
275         gss_buffer_desc          sc_tgt;
276         gss_buffer_desc          sc_nodemap_hash;
277         gss_buffer_desc          sc_hmac;
278         gss_buffer_desc          sc_dh_shared_key;
279         struct sk_kernel_ctx     sc_kctx;
280         EVP_PKEY *sc_params;
281 };
282
283 /* Names match up with openssl enc and dgst commands */
284 /* When adding new alg types, make sure first occurrence's name
285  * matches cht_name in hash_types array.
286  */
287 static const struct sk_crypt_type sk_crypt_algs[] = {
288         {
289                 .sct_name = "null",
290                 .sct_type = SK_CRYPT_EMPTY
291         },
292         {
293                 .sct_name = "NONE",
294                 .sct_type = SK_CRYPT_EMPTY
295         },
296         {
297                 .sct_name = "ctr(aes)",
298                 .sct_type = SK_CRYPT_AES256_CTR
299         },
300         {
301                 .sct_name = "AES-256-CTR",
302                 .sct_type = SK_CRYPT_AES256_CTR
303         }
304 };
305 static const struct sk_hmac_type sk_hmac_algs[] = {
306         {
307                 .sht_name = "null",
308                 .sht_type = SK_HMAC_EMPTY
309         },
310         {
311                 .sht_name = "NONE",
312                 .sht_type = SK_HMAC_EMPTY
313         },
314         {
315                 .sht_name = "sha256",
316                 .sht_type = SK_HMAC_SHA256
317         },
318         {
319                 .sht_name = "SHA256",
320                 .sht_type = SK_HMAC_SHA256
321         },
322         {
323                 .sht_name = "sha512",
324                 .sht_type = SK_HMAC_SHA512
325         },
326         {
327                 .sht_name = "SHA512",
328                 .sht_type = SK_HMAC_SHA512
329         }
330 };
331
332 static inline int sk_name2crypt(char *name)
333 {
334         int i;
335
336         for (i = 0; i < ARRAY_SIZE(sk_crypt_algs); i++) {
337                 if (strcasecmp(name, sk_crypt_algs[i].sct_name) == 0)
338                         return sk_crypt_algs[i].sct_type;
339         }
340
341         return SK_CRYPT_INVALID;
342 }
343
344 static inline int sk_name2hmac(char *name)
345 {
346         int i;
347
348         for (i = 0; i < ARRAY_SIZE(sk_hmac_algs); i++) {
349                 if (strcasecmp(name, sk_hmac_algs[i].sht_name) == 0)
350                         return sk_hmac_algs[i].sht_type;
351         }
352
353         return SK_HMAC_INVALID;
354 }
355
356 static inline const char *sk_crypt2name(enum sk_crypt_alg type)
357 {
358         int i;
359
360         for (i = 0; i < ARRAY_SIZE(sk_crypt_algs); i++) {
361                 if (type == sk_crypt_algs[i].sct_type)
362                         return sk_crypt_algs[i].sct_name;
363         }
364
365         return NULL;
366 }
367
368 static inline const char *sk_hmac2name(enum sk_hmac_alg type)
369 {
370         int i;
371
372         for (i = 0; i < ARRAY_SIZE(sk_hmac_algs); i++) {
373                 if (type == sk_hmac_algs[i].sht_type)
374                         return sk_hmac_algs[i].sht_name;
375         }
376
377         return NULL;
378 }
379
380 #ifndef NID_ffdhe2048
381 #define NID_ffdhe2048           1126
382 #define NID_ffdhe3072           1127
383 #define NID_ffdhe4096           1128
384 #define NID_ffdhe6144           1129
385 #define NID_ffdhe8192           1130
386 #endif
387
388 static const struct sk_prime_type sk_prime_nids[] = {
389         {
390                 .spt_name = "null",
391                 .spt_type = 0,
392                 .spt_primebits = 0
393         },
394         {
395                 .spt_name = "ffdhe2048",
396                 .spt_type = NID_ffdhe2048,
397                 .spt_primebits = 2048
398         },
399         {
400                 .spt_name = "ffdhe3072",
401                 .spt_type = NID_ffdhe3072,
402                 .spt_primebits = 3072
403         },
404         {
405                 .spt_name = "ffdhe4096",
406                 .spt_type = NID_ffdhe4096,
407                 .spt_primebits = 4096
408         },
409         {
410                 .spt_name = "ffdhe6144",
411                 .spt_type = NID_ffdhe6144,
412                 .spt_primebits = 6144
413         },
414         {
415                 .spt_name = "ffdhe8192",
416                 .spt_type = NID_ffdhe8192,
417                 .spt_primebits = 8192
418         },
419 };
420
421 static inline int sk_primebits2primenid(int primebits)
422 {
423         int i;
424
425         for (i = 0; i < ARRAY_SIZE(sk_prime_nids); i++) {
426                 if (primebits == sk_prime_nids[i].spt_primebits)
427                         return sk_prime_nids[i].spt_type;
428         }
429
430         return -1;
431 }
432
433 static inline const char *sk_primebits2name(int primebits)
434 {
435         int i;
436
437         for (i = 0; i < ARRAY_SIZE(sk_prime_nids); i++) {
438                 if (primebits == sk_prime_nids[i].spt_primebits)
439                         return sk_prime_nids[i].spt_name;
440         }
441
442         return NULL;
443 }
444
445 void sk_init_logging(char *program, int verbose, int fg);
446 struct sk_keyfile_config *sk_read_file(char *filename);
447 int sk_load_keyfile(char *path);
448 void sk_config_disk_to_cpu(struct sk_keyfile_config *config);
449 void sk_config_cpu_to_disk(struct sk_keyfile_config *config);
450 int sk_validate_config(const struct sk_keyfile_config *config);
451 uint32_t sk_verify_hash(const char *string, const EVP_MD *hash_alg,
452                         const gss_buffer_desc *current_hash);
453 struct sk_cred *sk_create_cred(const char *fsname, const char *cluster,
454                                const uint32_t flags);
455 #ifndef HAVE_OPENSSL_EVP_PKEY
456 int sk_speedtest_dh_valid(unsigned int usec_check_max, pid_t *child);
457 #endif
458 uint32_t sk_gen_params(struct sk_cred *skc, int num_rounds);
459 int sk_sign_bufs(gss_buffer_desc *key, gss_buffer_desc *bufs, const int numbufs,
460                  const EVP_MD *hash_alg, gss_buffer_desc *hmac);
461 uint32_t sk_verify_hmac(struct sk_cred *skc, gss_buffer_desc *bufs,
462                         const int numbufs, const EVP_MD *hash_alg,
463                         gss_buffer_desc *hmac);
464 void sk_free_cred(struct sk_cred *skc);
465 int sk_session_kdf(struct sk_cred *skc, lnet_nid_t client_nid,
466                    gss_buffer_desc *client_token, gss_buffer_desc *server_token);
467 uint32_t sk_compute_dh_key(struct sk_cred *skc, const gss_buffer_desc *pub_key);
468 int sk_compute_keys(struct sk_cred *skc);
469 int sk_serialize_kctx(struct sk_cred *skc, gss_buffer_desc *ctx_token);
470 int sk_decode_netstring(gss_buffer_desc *bufs, int numbufs,
471                         gss_buffer_desc *ns);
472 int sk_encode_netstring(gss_buffer_desc *bufs, int numbufs,
473                         gss_buffer_desc *ns);
474
475 #endif /* HAVE_OPENSSL_SSK */
476 #endif /* SK_UTILS_H */