Whamcloud - gitweb
LU-8602 gss: Properly port gss to newer crypto api.
[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 #include <gssapi/gssapi.h>
32 #include <keyutils.h>
33 #include <linux/lustre/lustre_idl.h>
34 #include <openssl/dh.h>
35 #include <openssl/evp.h>
36 #include <sys/types.h>
37
38 #include <libcfs/libcfs_crypto.h>
39 #include "lsupport.h"
40
41 #ifndef ARRAY_SIZE
42 # define ARRAY_SIZE(a) ((sizeof(a)) / (sizeof((a)[0])))
43 #endif /* !ARRAY_SIZE */
44
45 /* LL_CRYPTO_MAX_NAME value must match value of
46  * CRYPTO_MAX_ALG_NAME in include/linux/crypto.h
47  */
48 #ifdef HAVE_CRYPTO_MAX_ALG_NAME_128
49 #define LL_CRYPTO_MAX_NAME 128
50 #else
51 #define LL_CRYPTO_MAX_NAME 64
52 #endif
53
54 /* Some limits and defaults */
55 #define SK_CONF_VERSION 1
56 #define SK_MSG_VERSION 1
57 #define SK_GENERATOR 2
58 #define SK_SESSION_MAX_KEYLEN_BYTES 1024
59 #define SK_MAX_KEYLEN_BYTES 128
60 #define SK_MAX_P_BYTES 2048
61 #define SK_NONCE_SIZE 4
62 #define MAX_MGSNIDS 16
63
64 enum sk_ctx_init_buffers {
65         /* Initiator netstring buffer ordering */
66         SK_INIT_VERSION = 0,
67         SK_INIT_RANDOM  = 1,
68         SK_INIT_P       = 2,
69         SK_INIT_PUB_KEY = 3,
70         SK_INIT_TARGET  = 4,
71         SK_INIT_NODEMAP = 5,
72         SK_INIT_FLAGS   = 6,
73         SK_INIT_HMAC    = 7,
74         SK_INIT_BUFFERS = 8,
75
76         /* Responder netstring buffer ordering */
77         SK_RESP_VERSION = 0,
78         SK_RESP_RANDOM  = 1,
79         SK_RESP_PUB_KEY = 2,
80         SK_RESP_HMAC    = 3,
81         SK_RESP_BUFFERS = 4,
82 };
83
84 /* String consisting of "lustre:fsname:nodemap_hash" */
85 #define SK_DESCRIPTION_SIZE (9 + MTI_NAME_MAXLEN + LUSTRE_NODEMAP_NAME_LENGTH)
86
87 enum sk_key_type {
88         SK_TYPE_INVALID = 0x0,
89         SK_TYPE_CLIENT  = 0x1,
90         SK_TYPE_SERVER  = 0x2,
91         SK_TYPE_MGS     = 0x4,
92 };
93
94 /* This is the packed structure format of key files that are distributed.
95  * The on disk format should be store in big-endian. */
96 struct sk_keyfile_config {
97         /* File format version */
98         uint32_t        skc_version;
99         /* HMAC algorithm used for message integrity */
100         uint16_t        skc_hmac_alg;
101         /* Crypt algorithm used for privacy mode */
102         uint16_t        skc_crypt_alg;
103         /* Number of seconds that a context is valid after it is created from
104          * this keyfile */
105         uint32_t        skc_expire;
106         /* Length of shared key in skc_shared_key */
107         uint32_t        skc_shared_keylen;
108         /* Length of the prime used in the DHKE */
109         uint32_t        skc_prime_bits;
110         /* Key type */
111         uint8_t         skc_type;
112         /* Array of MGS NIDs to load key's for.  This is for the client since
113          * the upcall only knows the target name which is MGC<IP>@<NET>
114          * Only needed when mounting with mgssec */
115         lnet_nid_t      skc_mgsnids[MAX_MGSNIDS];
116         /* File system name for this key.  It can be unused for MGS only keys */
117         char            skc_fsname[MTI_NAME_MAXLEN + 1];
118         /* Nodemap name for this key.  Used by the server side to verify the
119          * client is in the correct nodemap */
120         char            skc_nodemap[LUSTRE_NODEMAP_NAME_LENGTH + 1];
121         /* Shared key */
122         unsigned char   skc_shared_key[SK_MAX_KEYLEN_BYTES];
123         /* Prime (p) for DHKE */
124         unsigned char   skc_p[SK_MAX_P_BYTES];
125 } __attribute__((packed));
126
127 /* Format passed to the kernel from userspace */
128 struct sk_kernel_ctx {
129         uint32_t        skc_version;
130         char            skc_hmac_alg[LL_CRYPTO_MAX_NAME];
131         char            skc_crypt_alg[LL_CRYPTO_MAX_NAME];
132         uint32_t        skc_expire;
133         uint32_t        skc_host_random;
134         uint32_t        skc_peer_random;
135         gss_buffer_desc skc_hmac_key;
136         gss_buffer_desc skc_encrypt_key;
137         gss_buffer_desc skc_shared_key;
138         gss_buffer_desc skc_session_key;
139 };
140
141 /* Structure used in context initiation to hold all necessary data */
142 struct sk_cred {
143         uint32_t                 sc_flags;
144         gss_buffer_desc          sc_p;
145         gss_buffer_desc          sc_pub_key;
146         gss_buffer_desc          sc_tgt;
147         gss_buffer_desc          sc_nodemap_hash;
148         gss_buffer_desc          sc_hmac;
149         gss_buffer_desc          sc_dh_shared_key;
150         struct sk_kernel_ctx     sc_kctx;
151         DH                      *sc_params;
152 };
153
154 /* Names match up with openssl enc and dgst commands */
155 /* When adding new alg types, make sure first occurrence's name
156  * matches cht_name in hash_types array.
157  */
158 static const struct sk_crypt_type sk_crypt_algs[] = {
159         {
160                 .sct_name = "null",
161                 .sct_type = SK_CRYPT_EMPTY
162         },
163         {
164                 .sct_name = "NONE",
165                 .sct_type = SK_CRYPT_EMPTY
166         },
167         {
168                 .sct_name = "ctr(aes)",
169                 .sct_type = SK_CRYPT_AES256_CTR
170         },
171         {
172                 .sct_name = "AES-256-CTR",
173                 .sct_type = SK_CRYPT_AES256_CTR
174         }
175 };
176 static const struct sk_hmac_type sk_hmac_algs[] = {
177         {
178                 .sht_name = "null",
179                 .sht_type = SK_HMAC_EMPTY
180         },
181         {
182                 .sht_name = "NONE",
183                 .sht_type = SK_HMAC_EMPTY
184         },
185         {
186                 .sht_name = "sha256",
187                 .sht_type = SK_HMAC_SHA256
188         },
189         {
190                 .sht_name = "SHA256",
191                 .sht_type = SK_HMAC_SHA256
192         },
193         {
194                 .sht_name = "sha512",
195                 .sht_type = SK_HMAC_SHA512
196         },
197         {
198                 .sht_name = "SHA512",
199                 .sht_type = SK_HMAC_SHA512
200         }
201 };
202
203 static inline int sk_name2crypt(char *name)
204 {
205         int i;
206
207         for (i = 0; i < ARRAY_SIZE(sk_crypt_algs); i++) {
208                 if (strcasecmp(name, sk_crypt_algs[i].sct_name) == 0)
209                         return sk_crypt_algs[i].sct_type;
210         }
211
212         return SK_CRYPT_INVALID;
213 }
214
215 static inline int sk_name2hmac(char *name)
216 {
217         int i;
218
219         for (i = 0; i < ARRAY_SIZE(sk_hmac_algs); i++) {
220                 if (strcasecmp(name, sk_hmac_algs[i].sht_name) == 0)
221                         return sk_hmac_algs[i].sht_type;
222         }
223
224         return SK_HMAC_INVALID;
225 }
226
227 static inline const char *sk_crypt2name(enum sk_crypt_alg type)
228 {
229         int i;
230
231         for (i = 0; i < ARRAY_SIZE(sk_crypt_algs); i++) {
232                 if (type == sk_crypt_algs[i].sct_type)
233                         return sk_crypt_algs[i].sct_name;
234         }
235
236         return NULL;
237 }
238
239 static inline const char *sk_hmac2name(enum sk_hmac_alg type)
240 {
241         int i;
242
243         for (i = 0; i < ARRAY_SIZE(sk_hmac_algs); i++) {
244                 if (type == sk_hmac_algs[i].sht_type)
245                         return sk_hmac_algs[i].sht_name;
246         }
247
248         return NULL;
249 }
250
251 void sk_init_logging(char *program, int verbose, int fg);
252 struct sk_keyfile_config *sk_read_file(char *filename);
253 int sk_load_keyfile(char *path);
254 void sk_config_disk_to_cpu(struct sk_keyfile_config *config);
255 void sk_config_cpu_to_disk(struct sk_keyfile_config *config);
256 int sk_validate_config(const struct sk_keyfile_config *config);
257 uint32_t sk_verify_hash(const char *string, const EVP_MD *hash_alg,
258                         const gss_buffer_desc *current_hash);
259 struct sk_cred *sk_create_cred(const char *fsname, const char *cluster,
260                                const uint32_t flags);
261 uint32_t sk_gen_params(struct sk_cred *skc);
262 int sk_sign_bufs(gss_buffer_desc *key, gss_buffer_desc *bufs, const int numbufs,
263                  const EVP_MD *hash_alg, gss_buffer_desc *hmac);
264 uint32_t sk_verify_hmac(struct sk_cred *skc, gss_buffer_desc *bufs,
265                         const int numbufs, const EVP_MD *hash_alg,
266                         gss_buffer_desc *hmac);
267 void sk_free_cred(struct sk_cred *skc);
268 int sk_session_kdf(struct sk_cred *skc, lnet_nid_t client_nid,
269                    gss_buffer_desc *client_token, gss_buffer_desc *server_token);
270 uint32_t sk_compute_dh_key(struct sk_cred *skc, const gss_buffer_desc *pub_key);
271 int sk_compute_keys(struct sk_cred *skc);
272 int sk_serialize_kctx(struct sk_cred *skc, gss_buffer_desc *ctx_token);
273 int sk_decode_netstring(gss_buffer_desc *bufs, int numbufs,
274                         gss_buffer_desc *ns);
275 int sk_encode_netstring(gss_buffer_desc *bufs, int numbufs,
276                         gss_buffer_desc *ns);
277
278 #endif /* SK_UTILS_H */