4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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
23 * Copyright (C) 2015, Trustees of Indiana University
25 * Author: Jeremy Filizetti <jfilizet@iu.edu>
31 #ifdef HAVE_OPENSSL_SSK
32 #include <gssapi/gssapi.h>
33 #ifdef HAVE_LIBKEYUTILS
36 #include <linux/lustre/lustre_idl.h>
37 #include <linux/lustre/lustre_disk.h>
38 #include <openssl/dh.h>
39 #include <openssl/evp.h>
40 #include <openssl/hmac.h>
41 #ifdef HAVE_OPENSSL_EVP_PKEY
42 #include <openssl/core_names.h>
44 #include <openssl/err.h>
45 #include <sys/types.h>
47 #include <libcfs/libcfs_crypto.h>
51 # define ARRAY_SIZE(a) ((sizeof(a)) / (sizeof((a)[0])))
52 #endif /* !ARRAY_SIZE */
54 /* LL_CRYPTO_MAX_NAME value must match value of
55 * CRYPTO_MAX_ALG_NAME in include/linux/crypto.h
57 #ifdef HAVE_CRYPTO_MAX_ALG_NAME_128
58 #define LL_CRYPTO_MAX_NAME 128
60 #define LL_CRYPTO_MAX_NAME 64
63 #if OPENSSL_VERSION_NUMBER < 0x10100000L
64 static inline HMAC_CTX *HMAC_CTX_new(void)
66 HMAC_CTX *ctx = OPENSSL_malloc(sizeof(*ctx));
73 static inline void HMAC_CTX_free(HMAC_CTX *ctx)
76 HMAC_CTX_cleanup(ctx);
77 OPENSSL_cleanse(ctx, sizeof(*ctx));
81 static inline void DH_get0_pqg(const DH *dh,
82 const BIGNUM **p, const BIGNUM **q,
93 static inline int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
95 /* If the fields p and g in dh are NULL, the corresponding input
96 * parameters MUST be non-NULL. q may remain NULL.
98 if ((dh->p == NULL && p == NULL)
99 || (dh->g == NULL && g == NULL))
116 dh->length = BN_num_bits(q);
121 static inline void DH_get0_key(const DH *dh, const BIGNUM **pub_key,
122 const BIGNUM **priv_key)
125 *pub_key = dh->pub_key;
126 if (priv_key != NULL)
127 *priv_key = dh->priv_key;
130 static inline const BIGNUM *DH_get0_p(const DH *dh)
136 /* Some limits and defaults */
137 #define SK_CONF_VERSION 1
138 #define SK_MSG_VERSION 1
139 #define SK_GENERATOR 2
140 #define SK_SESSION_MAX_KEYLEN_BYTES 1024
141 #define SK_MAX_KEYLEN_BYTES 128
142 #define SK_MAX_P_BYTES 2048
143 #define SK_NONCE_SIZE 4
144 #define MAX_MGSNIDS 16
146 enum sk_ctx_init_buffers {
147 /* Initiator netstring buffer ordering */
158 /* Responder netstring buffer ordering */
166 /* String consisting of "lustre:fsname:nodemap_hash" */
167 #define SK_DESCRIPTION_SIZE (9 + MTI_NAME_MAXLEN + LUSTRE_NODEMAP_NAME_LENGTH)
170 SK_TYPE_INVALID = 0x0,
171 SK_TYPE_CLIENT = 0x1,
172 SK_TYPE_SERVER = 0x2,
176 /* This is the packed structure format of key files that are distributed.
177 * The on disk format should be store in big-endian. */
178 struct sk_keyfile_config {
179 /* File format version */
180 uint32_t skc_version;
181 /* HMAC algorithm used for message integrity */
182 uint16_t skc_hmac_alg;
183 /* Crypt algorithm used for privacy mode */
184 uint16_t skc_crypt_alg;
185 /* Number of seconds that a context is valid after it is created from
188 /* Length of shared key in skc_shared_key */
189 uint32_t skc_shared_keylen;
190 /* Length of the prime used in the DHKE */
191 uint32_t skc_prime_bits;
194 /* Array of MGS NIDs to load key's for. This is for the client since
195 * the upcall only knows the target name which is MGC<IP>@<NET>
196 * Only needed when mounting with mgssec */
197 lnet_nid_t skc_mgsnids[MAX_MGSNIDS];
198 /* File system name for this key. It can be unused for MGS only keys */
199 char skc_fsname[MTI_NAME_MAXLEN + 1];
200 /* Nodemap name for this key. Used by the server side to verify the
201 * client is in the correct nodemap */
202 char skc_nodemap[LUSTRE_NODEMAP_NAME_LENGTH + 1];
204 unsigned char skc_shared_key[SK_MAX_KEYLEN_BYTES];
205 /* Prime (p) for DHKE */
206 unsigned char skc_p[SK_MAX_P_BYTES];
207 } __attribute__((packed));
209 /* Format passed to the kernel from userspace */
210 struct sk_kernel_ctx {
211 uint32_t skc_version;
212 char skc_hmac_alg[LL_CRYPTO_MAX_NAME];
213 char skc_crypt_alg[LL_CRYPTO_MAX_NAME];
215 uint32_t skc_host_random;
216 uint32_t skc_peer_random;
217 gss_buffer_desc skc_hmac_key;
218 gss_buffer_desc skc_encrypt_key;
219 gss_buffer_desc skc_shared_key;
220 gss_buffer_desc skc_session_key;
224 #ifdef HAVE_OPENSSL_EVP_PKEY
225 #define DECLARE_EVP_MD(name, hash) \
226 OSSL_PARAM name[] = { \
227 OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, \
228 (char *)EVP_MD_get0_name(hash), \
232 #else /* !HAVE_OPENSSL_EVP_PKEY */
234 #define EVP_PKEY_free(dh) DH_free(dh)
235 struct dh_ssk_ctx { uint32_t bits; uint32_t gen; };
236 #define EVP_PKEY_CTX struct dh_ssk_ctx
237 #define EVP_PKEY_CTX_new_from_name(p1, name, p2) malloc(sizeof(EVP_PKEY_CTX))
238 #define EVP_PKEY_paramgen_init(ctx) 1
239 #undef EVP_PKEY_CTX_set_dh_paramgen_prime_len
240 #define EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len) ((ctx)->bits = len)
241 #undef EVP_PKEY_CTX_set_dh_paramgen_generator
242 #define EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, g) ((ctx)->gen = g)
243 #define EVP_PKEY_paramgen(ctx, dhp) \
244 ((*dhp = DH_new()) && \
245 DH_generate_parameters_ex(*(dhp), (ctx)->bits, (ctx)->gen, NULL))
246 #define EVP_PKEY_get_bn_param(dh, param, bnp) (*bnp = (BIGNUM *)DH_get0_p(dh))
247 #define EVP_PKEY_CTX_free(ctx) free(ctx)
248 #define DECLARE_EVP_MD(name, hash) \
249 const EVP_MD *name = hash
250 #define EVP_MAC_CTX HMAC_CTX
251 #define EVP_MAC_CTX_new(mac) HMAC_CTX_new()
252 #define EVP_MAC_CTX_free HMAC_CTX_free
254 #define EVP_MAC_fetch(a, b, c) (void *)1
255 #define EVP_MAC_init(ctx, val, len, alg) HMAC_Init_ex(ctx, val, len, alg, NULL)
256 #define EVP_MAC_update HMAC_Update
257 #define EVP_MAC_final(ctx, val, lenp, hlen) \
258 HMAC_Final(ctx, val, (unsigned int *)(lenp))
259 #define EVP_MAC_free(mac) {}
262 /* Structure used in context initiation to hold all necessary data */
265 gss_buffer_desc sc_p;
266 gss_buffer_desc sc_pub_key;
267 gss_buffer_desc sc_tgt;
268 gss_buffer_desc sc_nodemap_hash;
269 gss_buffer_desc sc_hmac;
270 gss_buffer_desc sc_dh_shared_key;
271 struct sk_kernel_ctx sc_kctx;
275 /* Names match up with openssl enc and dgst commands */
276 /* When adding new alg types, make sure first occurrence's name
277 * matches cht_name in hash_types array.
279 static const struct sk_crypt_type sk_crypt_algs[] = {
282 .sct_type = SK_CRYPT_EMPTY
286 .sct_type = SK_CRYPT_EMPTY
289 .sct_name = "ctr(aes)",
290 .sct_type = SK_CRYPT_AES256_CTR
293 .sct_name = "AES-256-CTR",
294 .sct_type = SK_CRYPT_AES256_CTR
297 static const struct sk_hmac_type sk_hmac_algs[] = {
300 .sht_type = SK_HMAC_EMPTY
304 .sht_type = SK_HMAC_EMPTY
307 .sht_name = "sha256",
308 .sht_type = SK_HMAC_SHA256
311 .sht_name = "SHA256",
312 .sht_type = SK_HMAC_SHA256
315 .sht_name = "sha512",
316 .sht_type = SK_HMAC_SHA512
319 .sht_name = "SHA512",
320 .sht_type = SK_HMAC_SHA512
324 static inline int sk_name2crypt(char *name)
328 for (i = 0; i < ARRAY_SIZE(sk_crypt_algs); i++) {
329 if (strcasecmp(name, sk_crypt_algs[i].sct_name) == 0)
330 return sk_crypt_algs[i].sct_type;
333 return SK_CRYPT_INVALID;
336 static inline int sk_name2hmac(char *name)
340 for (i = 0; i < ARRAY_SIZE(sk_hmac_algs); i++) {
341 if (strcasecmp(name, sk_hmac_algs[i].sht_name) == 0)
342 return sk_hmac_algs[i].sht_type;
345 return SK_HMAC_INVALID;
348 static inline const char *sk_crypt2name(enum sk_crypt_alg type)
352 for (i = 0; i < ARRAY_SIZE(sk_crypt_algs); i++) {
353 if (type == sk_crypt_algs[i].sct_type)
354 return sk_crypt_algs[i].sct_name;
360 static inline const char *sk_hmac2name(enum sk_hmac_alg type)
364 for (i = 0; i < ARRAY_SIZE(sk_hmac_algs); i++) {
365 if (type == sk_hmac_algs[i].sht_type)
366 return sk_hmac_algs[i].sht_name;
372 void sk_init_logging(char *program, int verbose, int fg);
373 struct sk_keyfile_config *sk_read_file(char *filename);
374 int sk_load_keyfile(char *path);
375 void sk_config_disk_to_cpu(struct sk_keyfile_config *config);
376 void sk_config_cpu_to_disk(struct sk_keyfile_config *config);
377 int sk_validate_config(const struct sk_keyfile_config *config);
378 uint32_t sk_verify_hash(const char *string, const EVP_MD *hash_alg,
379 const gss_buffer_desc *current_hash);
380 struct sk_cred *sk_create_cred(const char *fsname, const char *cluster,
381 const uint32_t flags);
382 #ifndef HAVE_OPENSSL_EVP_PKEY
383 int sk_speedtest_dh_valid(unsigned int usec_check_max);
385 uint32_t sk_gen_params(struct sk_cred *skc, int num_rounds);
386 int sk_sign_bufs(gss_buffer_desc *key, gss_buffer_desc *bufs, const int numbufs,
387 const EVP_MD *hash_alg, gss_buffer_desc *hmac);
388 uint32_t sk_verify_hmac(struct sk_cred *skc, gss_buffer_desc *bufs,
389 const int numbufs, const EVP_MD *hash_alg,
390 gss_buffer_desc *hmac);
391 void sk_free_cred(struct sk_cred *skc);
392 int sk_session_kdf(struct sk_cred *skc, lnet_nid_t client_nid,
393 gss_buffer_desc *client_token, gss_buffer_desc *server_token);
394 uint32_t sk_compute_dh_key(struct sk_cred *skc, const gss_buffer_desc *pub_key);
395 int sk_compute_keys(struct sk_cred *skc);
396 int sk_serialize_kctx(struct sk_cred *skc, gss_buffer_desc *ctx_token);
397 int sk_decode_netstring(gss_buffer_desc *bufs, int numbufs,
398 gss_buffer_desc *ns);
399 int sk_encode_netstring(gss_buffer_desc *bufs, int numbufs,
400 gss_buffer_desc *ns);
402 #endif /* HAVE_OPENSSL_SSK */
403 #endif /* SK_UTILS_H */