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 * Copyright (c) 2016, 2017, Intel Corporation.
27 * Author: Jeremy Filizetti <jfilizet@iu.edu>
36 #include <openssl/dh.h>
37 #include <openssl/engine.h>
38 #include <openssl/err.h>
39 #include <openssl/hmac.h>
40 #include <sys/types.h>
44 #include "write_bytes.h"
46 #define SK_PBKDF2_ITERATIONS 10000
49 # include "lgss_utils.h"
51 # include "gss_util.h"
52 # include "gss_oids.h"
53 # include "err_util.h"
59 * \param[in] program Program name to output
60 * \param[in] verbose Verbose flag
61 * \param[in] fg Whether or not to run in foreground
64 void sk_init_logging(char *program, int verbose, int fg)
66 initerr(program, verbose, fg);
71 * Loads the key from \a filename and returns the struct sk_keyfile_config.
72 * It should be freed by the caller.
74 * \param[in] filename Disk or key payload data
76 * \return sk_keyfile_config sucess
77 * \return NULL failure
79 struct sk_keyfile_config *sk_read_file(char *filename)
81 struct sk_keyfile_config *config;
87 config = malloc(sizeof(*config));
89 printerr(0, "Failed to allocate memory for config\n");
93 /* allow standard input override */
94 if (strcmp(filename, "-") == 0)
97 fd = open(filename, O_RDONLY);
100 printerr(0, "Error opening key file '%s': %s\n", filename,
103 } else if (fd != STDIN_FILENO) {
107 if (rc == 0 && (st.st_mode & ~(S_IFREG | 0600)))
108 fprintf(stderr, "warning: "
109 "secret key '%s' has insecure file mode %#o\n",
110 filename, st.st_mode);
113 ptr = (char *)config;
114 remain = sizeof(*config);
116 rc = read(fd, ptr, remain);
120 printerr(0, "read() failed on %s: %s\n", filename,
123 } else if (rc == 0) {
124 printerr(0, "File %s does not have a complete key\n",
132 if (fd != STDIN_FILENO)
134 sk_config_disk_to_cpu(config);
145 * Checks if a key matching \a description is found in the keyring for
146 * logging purposes and then attempts to load \a payload of \a psize into a key
147 * with \a description.
149 * \param[in] payload Key payload
150 * \param[in] psize Payload size
151 * \param[in] description Description used for key in keyring
156 static key_serial_t sk_load_key(const struct sk_keyfile_config *skc,
157 const char *description)
159 struct sk_keyfile_config payload;
162 memcpy(&payload, skc, sizeof(*skc));
164 /* In the keyring use the disk layout so keyctl pipe can be used */
165 sk_config_cpu_to_disk(&payload);
167 /* Check to see if a key is already loaded matching description */
168 key = keyctl_search(KEY_SPEC_USER_KEYRING, "user", description, 0);
170 printerr(2, "Key %d found in session keyring, replacing\n",
173 key = add_key("user", description, &payload, sizeof(payload),
174 KEY_SPEC_USER_KEYRING);
176 printerr(2, "Added key %d with description %s\n", key,
179 printerr(0, "Failed to add key with %s\n", description);
185 * Reads the key from \a path, verifies it and loads into the session keyring
186 * using a description determined by the the \a type. Existing keys with the
187 * same description are replaced.
189 * \param[in] path Path to key file
190 * \param[in] type Type of key to load which determines the description
195 int sk_load_keyfile(char *path)
197 struct sk_keyfile_config *config;
198 char description[SK_DESCRIPTION_SIZE + 1];
204 rc = stat(path, &buf);
206 printerr(0, "stat() failed for file %s: %s\n", path,
211 config = sk_read_file(path);
215 /* Similar to ssh, require adequate care of key files */
216 if (buf.st_mode & (S_IRGRP | S_IWGRP | S_IWOTH | S_IXOTH)) {
217 printerr(0, "Shared key files must be read/writeable only by "
222 if (sk_validate_config(config))
225 /* The server side can have multiple key files per file system so
226 * the nodemap name is appended to the key description to uniquely
228 if (config->skc_type & SK_TYPE_MGS) {
229 /* Any key can be an MGS key as long as we are told to use it */
230 rc = snprintf(description, SK_DESCRIPTION_SIZE, "lustre:MGS:%s",
231 config->skc_nodemap);
232 if (rc >= SK_DESCRIPTION_SIZE)
234 if (sk_load_key(config, description) == -1)
237 if (config->skc_type & SK_TYPE_SERVER) {
238 /* Server keys need to have the file system name in the key */
239 if (!config->skc_fsname) {
240 printerr(0, "Key configuration has no file system "
241 "attribute. Can't load as server type\n");
244 rc = snprintf(description, SK_DESCRIPTION_SIZE, "lustre:%s:%s",
245 config->skc_fsname, config->skc_nodemap);
246 if (rc >= SK_DESCRIPTION_SIZE)
248 if (sk_load_key(config, description) == -1)
251 if (config->skc_type & SK_TYPE_CLIENT) {
252 /* Load client file system key */
253 if (config->skc_fsname) {
254 rc = snprintf(description, SK_DESCRIPTION_SIZE,
255 "lustre:%s", config->skc_fsname);
256 if (rc >= SK_DESCRIPTION_SIZE)
258 if (sk_load_key(config, description) == -1)
262 /* Load client MGC keys */
263 for (i = 0; i < MAX_MGSNIDS; i++) {
264 if (config->skc_mgsnids[i] == LNET_NID_ANY)
266 rc = snprintf(description, SK_DESCRIPTION_SIZE,
268 libcfs_nid2str(config->skc_mgsnids[i]));
269 if (rc >= SK_DESCRIPTION_SIZE)
271 if (sk_load_key(config, description) == -1)
284 * Byte swaps config from cpu format to disk
286 * \param[in,out] config sk_keyfile_config to swap
288 void sk_config_cpu_to_disk(struct sk_keyfile_config *config)
295 config->skc_version = htobe32(config->skc_version);
296 config->skc_hmac_alg = htobe16(config->skc_hmac_alg);
297 config->skc_crypt_alg = htobe16(config->skc_crypt_alg);
298 config->skc_expire = htobe32(config->skc_expire);
299 config->skc_shared_keylen = htobe32(config->skc_shared_keylen);
300 config->skc_prime_bits = htobe32(config->skc_prime_bits);
302 for (i = 0; i < MAX_MGSNIDS; i++)
303 config->skc_mgsnids[i] = htobe64(config->skc_mgsnids[i]);
309 * Byte swaps config from disk format to cpu
311 * \param[in,out] config sk_keyfile_config to swap
313 void sk_config_disk_to_cpu(struct sk_keyfile_config *config)
320 config->skc_version = be32toh(config->skc_version);
321 config->skc_hmac_alg = be16toh(config->skc_hmac_alg);
322 config->skc_crypt_alg = be16toh(config->skc_crypt_alg);
323 config->skc_expire = be32toh(config->skc_expire);
324 config->skc_shared_keylen = be32toh(config->skc_shared_keylen);
325 config->skc_prime_bits = be32toh(config->skc_prime_bits);
327 for (i = 0; i < MAX_MGSNIDS; i++)
328 config->skc_mgsnids[i] = be64toh(config->skc_mgsnids[i]);
334 * Verifies the on key payload format is valid
336 * \param[in] config sk_keyfile_config
341 int sk_validate_config(const struct sk_keyfile_config *config)
346 printerr(0, "Null configuration passed\n");
350 if (config->skc_version != SK_CONF_VERSION) {
351 printerr(0, "Invalid version\n");
355 if (config->skc_hmac_alg == SK_HMAC_INVALID) {
356 printerr(0, "Invalid HMAC algorithm\n");
360 if (config->skc_crypt_alg == SK_CRYPT_INVALID) {
361 printerr(0, "Invalid crypt algorithm\n");
365 if (config->skc_expire < 60 || config->skc_expire > INT_MAX) {
366 /* Try to limit key expiration to some reasonable minimum and
367 * also prevent values over INT_MAX because there appears
368 * to be a type conversion issue */
369 printerr(0, "Invalid expiration time should be between %d "
370 "and %d\n", 60, INT_MAX);
373 if (config->skc_prime_bits % 8 != 0 ||
374 config->skc_prime_bits > SK_MAX_P_BYTES * 8) {
375 printerr(0, "Invalid session key length must be a multiple of 8"
376 " and less then %d bits\n",
380 if (config->skc_shared_keylen % 8 != 0 ||
381 config->skc_shared_keylen > SK_MAX_KEYLEN_BYTES * 8){
382 printerr(0, "Invalid shared key max length must be a multiple "
383 "of 8 and less then %d bits\n",
384 SK_MAX_KEYLEN_BYTES * 8);
388 /* Check for terminating nulls on strings */
389 for (i = 0; i < sizeof(config->skc_fsname) &&
390 config->skc_fsname[i] != '\0'; i++)
392 if (i == sizeof(config->skc_fsname)) {
393 printerr(0, "File system name not null terminated\n");
397 for (i = 0; i < sizeof(config->skc_nodemap) &&
398 config->skc_nodemap[i] != '\0'; i++)
400 if (i == sizeof(config->skc_nodemap)) {
401 printerr(0, "Nodemap name not null terminated\n");
405 if (config->skc_type == SK_TYPE_INVALID) {
406 printerr(0, "Invalid key type\n");
414 * Hashes \a string and places the hash in \a hash
417 * \param[in] string Null terminated string to hash
418 * \param[in] hash_alg OpenSSL EVP_MD to use for hash
419 * \param[in,out] hash gss_buffer_desc to hold the result
424 static int sk_hash_string(const char *string, const EVP_MD *hash_alg,
425 gss_buffer_desc *hash)
427 EVP_MD_CTX *ctx = EVP_MD_CTX_create();
428 size_t len = strlen(string);
429 unsigned int hashlen;
431 if (!hash->value || hash->length < EVP_MD_size(hash_alg))
433 if (!EVP_DigestInit_ex(ctx, hash_alg, NULL))
435 if (!EVP_DigestUpdate(ctx, string, len))
437 if (!EVP_DigestFinal_ex(ctx, hash->value, &hashlen))
440 EVP_MD_CTX_destroy(ctx);
441 hash->length = hashlen;
445 EVP_MD_CTX_destroy(ctx);
450 * Hashes \a string and verifies the resulting hash matches the value
453 * \param[in] string Null terminated string to hash
454 * \param[in] hash_alg OpenSSL EVP_MD to use for hash
455 * \param[in,out] current_hash gss_buffer_desc to compare to
457 * \return gss error failure
458 * \return GSS_S_COMPLETE success
460 uint32_t sk_verify_hash(const char *string, const EVP_MD *hash_alg,
461 const gss_buffer_desc *current_hash)
463 gss_buffer_desc hash;
464 unsigned char hashbuf[EVP_MAX_MD_SIZE];
466 hash.value = hashbuf;
467 hash.length = sizeof(hashbuf);
469 if (sk_hash_string(string, hash_alg, &hash))
470 return GSS_S_FAILURE;
471 if (current_hash->length != hash.length)
472 return GSS_S_DEFECTIVE_TOKEN;
473 if (memcmp(current_hash->value, hash.value, hash.length))
474 return GSS_S_BAD_SIG;
476 return GSS_S_COMPLETE;
479 static inline int sk_config_has_mgsnid(struct sk_keyfile_config *config,
485 nid = libcfs_str2nid(mgsnid);
486 if (nid == LNET_NID_ANY)
489 for (i = 0; i < MAX_MGSNIDS; i++)
490 if (config->skc_mgsnids[i] == nid)
496 * Create an sk_cred structure populated with initial configuration info and the
497 * key. \a tgt and \a nodemap are used in determining the expected key
498 * description so the key can be found by searching the keyring.
499 * This is done because there is no easy way to pass keys from the mount command
500 * all the way to the request_key call. In addition any keys can be dynamically
501 * added to the keyrings and still found. The keyring that needs to be used
502 * must be the session keyring.
504 * \param[in] tgt Target file system
505 * \param[in] nodemap Cluster name for the key. This correlates to
506 * the nodemap name and is used by the server side.
507 * For the client this will be NULL.
508 * \param[in] flags Flags for the credentials
510 * \return sk_cred Allocated struct sk_cred on success
511 * \return NULL failure
513 struct sk_cred *sk_create_cred(const char *tgt, const char *nodemap,
514 const uint32_t flags)
516 struct sk_keyfile_config *config;
517 struct sk_kernel_ctx *kctx;
518 struct sk_cred *skc = NULL;
519 char description[SK_DESCRIPTION_SIZE + 1];
520 char fsname[MTI_NAME_MAXLEN + 1];
521 const char *mgsnid = NULL;
528 printerr(2, "Creating credentials for target: %s with nodemap: %s\n",
531 memset(description, 0, sizeof(description));
532 memset(fsname, 0, sizeof(fsname));
534 /* extract the file system name from target */
535 ptr = index(tgt, '-');
539 /* This must be an MGC target */
540 if (strncmp(tgt, "MGC", 3) || len <= 3) {
541 printerr(0, "Invalid target name\n");
549 if (len > MTI_NAME_MAXLEN) {
550 printerr(0, "Invalid target name\n");
553 memcpy(fsname, tgt, len);
557 rc = snprintf(description, SK_DESCRIPTION_SIZE,
558 "lustre:MGS:%s", nodemap);
560 rc = snprintf(description, SK_DESCRIPTION_SIZE,
561 "lustre:%s:%s", fsname, nodemap);
563 rc = snprintf(description, SK_DESCRIPTION_SIZE, "lustre:%s",
567 if (rc >= SK_DESCRIPTION_SIZE) {
568 printerr(0, "Invalid key description\n");
572 /* It may be a good idea to move Lustre keys to the gss_keyring
573 * (lgssc) type so that they expire when Lustre modules are removed.
574 * Unfortunately it can't be done at mount time because the mount
575 * syscall could trigger the Lustre modules to load and until that
576 * point we don't have a lgssc key type.
578 * TODO: Query the community for a consensus here */
579 printerr(2, "Searching for key with description: %s\n", description);
580 sk_key = keyctl_search(KEY_SPEC_USER_KEYRING, "user",
583 printerr(1, "No key found for %s\n", description);
587 keylen = keyctl_read_alloc(sk_key, (void **)&config);
589 printerr(0, "keyctl_read() failed for key %ld: %s\n", sk_key,
592 } else if (keylen != sizeof(*config)) {
593 printerr(0, "Unexpected key size: %d returned for key %ld, "
594 "expected %zu bytes\n",
595 keylen, sk_key, sizeof(*config));
599 sk_config_disk_to_cpu(config);
601 if (sk_validate_config(config)) {
602 printerr(0, "Invalid key configuration for key: %ld\n", sk_key);
606 if (mgsnid && !sk_config_has_mgsnid(config, mgsnid)) {
607 printerr(0, "Target name does not match key's MGS NIDs\n");
611 if (!mgsnid && strcmp(fsname, config->skc_fsname)) {
612 printerr(0, "Target name does not match key's file system\n");
616 skc = malloc(sizeof(*skc));
618 printerr(0, "Failed to allocate memory for sk_cred\n");
622 /* this initializes all gss_buffer_desc to empty as well */
623 memset(skc, 0, sizeof(*skc));
625 skc->sc_flags = flags;
626 skc->sc_tgt.length = strlen(tgt) + 1;
627 skc->sc_tgt.value = malloc(skc->sc_tgt.length);
628 if (!skc->sc_tgt.value) {
629 printerr(0, "Failed to allocate memory for target\n");
632 memcpy(skc->sc_tgt.value, tgt, skc->sc_tgt.length);
634 skc->sc_nodemap_hash.length = EVP_MD_size(EVP_sha256());
635 skc->sc_nodemap_hash.value = malloc(skc->sc_nodemap_hash.length);
636 if (!skc->sc_nodemap_hash.value) {
637 printerr(0, "Failed to allocate memory for nodemap hash\n");
641 if (sk_hash_string(config->skc_nodemap, EVP_sha256(),
642 &skc->sc_nodemap_hash)) {
643 printerr(0, "Failed to generate hash for nodemap name\n");
647 kctx = &skc->sc_kctx;
648 kctx->skc_version = config->skc_version;
649 strcpy(kctx->skc_hmac_alg, sk_hmac2name(config->skc_hmac_alg));
650 strcpy(kctx->skc_crypt_alg, sk_crypt2name(config->skc_crypt_alg));
651 kctx->skc_expire = config->skc_expire;
653 /* key payload format is in bits, convert to bytes */
654 kctx->skc_shared_key.length = config->skc_shared_keylen / 8;
655 kctx->skc_shared_key.value = malloc(kctx->skc_shared_key.length);
656 if (!kctx->skc_shared_key.value) {
657 printerr(0, "Failed to allocate memory for shared key\n");
660 memcpy(kctx->skc_shared_key.value, config->skc_shared_key,
661 kctx->skc_shared_key.length);
663 skc->sc_p.length = config->skc_prime_bits / 8;
664 skc->sc_p.value = malloc(skc->sc_p.length);
665 if (!skc->sc_p.value) {
666 printerr(0, "Failed to allocate p\n");
669 memcpy(skc->sc_p.value, config->skc_p, skc->sc_p.length);
683 * Populates the DH parameters for the DHKE
685 * \param[in,out] skc Shared key credentials structure to
686 * populate with DH parameters
688 * \retval GSS_S_COMPLETE success
689 * \retval GSS_S_FAILURE failure
691 uint32_t sk_gen_params(struct sk_cred *skc)
695 const BIGNUM *pub_key;
698 /* Random value used by both the request and response as part of the
699 * key binding material. This also should ensure we have unqiue
700 * tokens that are sent to the remote server which is important because
701 * the token is hashed for the sunrpc cache lookups and a failure there
702 * would cause connection attempts to fail indefinitely due to the large
703 * timeout value on the server side */
704 if (RAND_bytes((unsigned char *)&random, sizeof(random)) != 1) {
705 printerr(0, "Failed to get data for random parameter: %s\n",
706 ERR_error_string(ERR_get_error(), NULL));
707 return GSS_S_FAILURE;
710 /* The random value will always be used in byte range operations
711 * so we keep it as big endian from this point on */
712 skc->sc_kctx.skc_host_random = random;
714 /* Populate DH parameters */
715 skc->sc_params = DH_new();
716 if (!skc->sc_params) {
717 printerr(0, "Failed to allocate DH\n");
718 return GSS_S_FAILURE;
721 p = BN_bin2bn(skc->sc_p.value, skc->sc_p.length, NULL);
723 printerr(0, "Failed to convert binary to BIGNUM\n");
724 return GSS_S_FAILURE;
727 /* We use a static generator for shared key */
730 printerr(0, "Failed to allocate new BIGNUM\n");
731 return GSS_S_FAILURE;
733 if (BN_set_word(g, SK_GENERATOR) != 1) {
734 printerr(0, "Failed to set g value for DH params\n");
735 return GSS_S_FAILURE;
738 if (!DH_set0_pqg(skc->sc_params, p, NULL, g)) {
739 printerr(0, "Failed to set pqg\n");
740 return GSS_S_FAILURE;
743 /* Verify that we have a safe prime and valid generator */
744 if (DH_check(skc->sc_params, &rc) != 1) {
745 printerr(0, "DH_check() failed: %d\n", rc);
746 return GSS_S_FAILURE;
748 printerr(0, "DH_check() returned error codes: 0x%x\n", rc);
749 return GSS_S_FAILURE;
752 if (DH_generate_key(skc->sc_params) != 1) {
753 printerr(0, "Failed to generate public DH key: %s\n",
754 ERR_error_string(ERR_get_error(), NULL));
755 return GSS_S_FAILURE;
758 DH_get0_key(skc->sc_params, &pub_key, NULL);
759 skc->sc_pub_key.length = BN_num_bytes(pub_key);
760 skc->sc_pub_key.value = malloc(skc->sc_pub_key.length);
761 if (!skc->sc_pub_key.value) {
762 printerr(0, "Failed to allocate memory for public key\n");
763 return GSS_S_FAILURE;
766 BN_bn2bin(pub_key, skc->sc_pub_key.value);
768 return GSS_S_COMPLETE;
772 * Convert SK hash algorithm into openssl message digest
774 * \param[in,out] alg SK hash algorithm
778 static inline const EVP_MD *sk_hash_to_evp_md(enum cfs_crypto_hash_alg alg)
781 case CFS_HASH_ALG_SHA256:
783 case CFS_HASH_ALG_SHA512:
786 return EVP_md_null();
791 * Signs (via HMAC) the parameters used only in the key initialization protocol.
793 * \param[in] key Key to use for HMAC
794 * \param[in] bufs Array of gss_buffer_desc to generate
796 * \param[in] numbufs Number of buffers in array
797 * \param[in] hash_alg OpenSSL EVP_MD to use for hash
798 * \param[in,out] hmac HMAC of buffers is allocated and placed
799 * in this gss_buffer_desc. Caller must
805 int sk_sign_bufs(gss_buffer_desc *key, gss_buffer_desc *bufs, const int numbufs,
806 const EVP_MD *hash_alg, gss_buffer_desc *hmac)
809 unsigned int hashlen = EVP_MD_size(hash_alg);
813 if (hash_alg == EVP_md_null()) {
814 printerr(0, "Invalid hash algorithm\n");
818 hctx = HMAC_CTX_new();
820 hmac->length = hashlen;
821 hmac->value = malloc(hashlen);
823 printerr(0, "Failed to allocate memory for HMAC\n");
827 if (HMAC_Init_ex(hctx, key->value, key->length, hash_alg, NULL) != 1) {
828 printerr(0, "Failed to init HMAC\n");
832 for (i = 0; i < numbufs; i++) {
833 if (HMAC_Update(hctx, bufs[i].value, bufs[i].length) != 1) {
834 printerr(0, "Failed to update HMAC\n");
839 /* The result gets populated in hmac */
840 if (HMAC_Final(hctx, hmac->value, &hashlen) != 1) {
841 printerr(0, "Failed to finalize HMAC\n");
845 if (hmac->length != hashlen) {
846 printerr(0, "HMAC size does not match expected\n");
857 * Generates an HMAC for gss_buffer_desc array in \a bufs of \a numbufs
858 * and verifies against \a hmac.
860 * \param[in] skc Shared key credentials
861 * \param[in] bufs Array of gss_buffer_desc to generate HMAC for
862 * \param[in] numbufs Number of buffers in array
863 * \param[in] hash_alg OpenSSL EVP_MD to use for hash
864 * \param[in] hmac HMAC to verify against
866 * \retval GSS_S_COMPLETE success (match)
867 * \retval gss error failure
869 uint32_t sk_verify_hmac(struct sk_cred *skc, gss_buffer_desc *bufs,
870 const int numbufs, const EVP_MD *hash_alg,
871 gss_buffer_desc *hmac)
873 gss_buffer_desc bufs_hmac;
876 if (sk_sign_bufs(&skc->sc_kctx.skc_shared_key, bufs, numbufs, hash_alg,
878 printerr(0, "Failed to sign buffers to verify HMAC\n");
880 free(bufs_hmac.value);
881 return GSS_S_FAILURE;
884 if (hmac->length != bufs_hmac.length) {
885 printerr(0, "Invalid HMAC size\n");
886 free(bufs_hmac.value);
887 return GSS_S_BAD_SIG;
890 rc = memcmp(hmac->value, bufs_hmac.value, bufs_hmac.length);
891 free(bufs_hmac.value);
894 return GSS_S_BAD_SIG;
896 return GSS_S_COMPLETE;
900 * Cleanup an sk_cred freeing any resources
902 * \param[in,out] skc Shared key credentials to free
904 void sk_free_cred(struct sk_cred *skc)
910 free(skc->sc_p.value);
911 if (skc->sc_pub_key.value)
912 free(skc->sc_pub_key.value);
913 if (skc->sc_tgt.value)
914 free(skc->sc_tgt.value);
915 if (skc->sc_nodemap_hash.value)
916 free(skc->sc_nodemap_hash.value);
917 if (skc->sc_hmac.value)
918 free(skc->sc_hmac.value);
920 /* Overwrite keys and IV before freeing */
921 if (skc->sc_dh_shared_key.value) {
922 memset(skc->sc_dh_shared_key.value, 0,
923 skc->sc_dh_shared_key.length);
924 free(skc->sc_dh_shared_key.value);
926 if (skc->sc_kctx.skc_hmac_key.value) {
927 memset(skc->sc_kctx.skc_hmac_key.value, 0,
928 skc->sc_kctx.skc_hmac_key.length);
929 free(skc->sc_kctx.skc_hmac_key.value);
931 if (skc->sc_kctx.skc_encrypt_key.value) {
932 memset(skc->sc_kctx.skc_encrypt_key.value, 0,
933 skc->sc_kctx.skc_encrypt_key.length);
934 free(skc->sc_kctx.skc_encrypt_key.value);
936 if (skc->sc_kctx.skc_shared_key.value) {
937 memset(skc->sc_kctx.skc_shared_key.value, 0,
938 skc->sc_kctx.skc_shared_key.length);
939 free(skc->sc_kctx.skc_shared_key.value);
941 if (skc->sc_kctx.skc_session_key.value) {
942 memset(skc->sc_kctx.skc_session_key.value, 0,
943 skc->sc_kctx.skc_session_key.length);
944 free(skc->sc_kctx.skc_session_key.value);
948 DH_free(skc->sc_params);
954 /* This function handles key derivation using the hash algorithm specified in
955 * \a hash_alg, buffers in \a key_binding_bufs, and original key in
956 * \a origin_key to produce a \a derived_key. The first element of the
957 * key_binding_bufs array is reserved for the counter used in the KDF. The
958 * derived key in \a derived_key could differ in size from \a origin_key and
959 * must be populated with the expected size and a valid buffer to hold the
962 * If the derived key size is greater than the HMAC algorithm size it will be
963 * a done using several iterations of a counter and the key binding bufs.
965 * If the size is smaller it will take copy the first N bytes necessary to
966 * fill the derived key. */
967 int sk_kdf(gss_buffer_desc *derived_key , gss_buffer_desc *origin_key,
968 gss_buffer_desc *key_binding_bufs, int numbufs,
969 enum cfs_crypto_hash_alg hmac_alg)
975 gss_buffer_desc tmp_hash;
982 /* Use a counter as the first buffer followed by the key binding
983 * buffers in the event we need more than one a single cycle to
984 * produced a symmetric key large enough in size */
985 key_binding_bufs[0].value = &counter;
986 key_binding_bufs[0].length = sizeof(counter);
988 remain = derived_key->length;
989 keydata = derived_key->value;
992 counter = htobe32(i++);
993 rc = sk_sign_bufs(origin_key, key_binding_bufs, numbufs,
994 sk_hash_to_evp_md(hmac_alg), &tmp_hash);
997 free(tmp_hash.value);
1001 if (cfs_crypto_hash_digestsize(hmac_alg) != tmp_hash.length) {
1002 free(tmp_hash.value);
1006 bytes = (remain < tmp_hash.length) ? remain : tmp_hash.length;
1007 memcpy(keydata, tmp_hash.value, bytes);
1008 free(tmp_hash.value);
1016 /* Populates the sk_cred's session_key using the a Key Derviation Function (KDF)
1017 * based on the recommendations in NIST Special Publication SP 800-56B Rev 1
1018 * (Sep 2014) Section 5.5.1
1020 * \param[in,out] skc Shared key credentials structure with
1022 * \return -1 failure
1025 int sk_session_kdf(struct sk_cred *skc, lnet_nid_t client_nid,
1026 gss_buffer_desc *client_token, gss_buffer_desc *server_token)
1028 struct sk_kernel_ctx *kctx = &skc->sc_kctx;
1029 gss_buffer_desc *session_key = &kctx->skc_session_key;
1030 gss_buffer_desc bufs[5];
1031 enum cfs_crypto_crypt_alg crypt_alg;
1034 crypt_alg = cfs_crypto_crypt_alg(kctx->skc_crypt_alg);
1035 session_key->length = cfs_crypto_crypt_keysize(crypt_alg);
1036 session_key->value = malloc(session_key->length);
1037 if (!session_key->value) {
1038 printerr(0, "Failed to allocate memory for session key\n");
1042 /* Key binding info ordering
1043 * 1. Reserved for counter
1047 * 4. Server's token */
1048 bufs[0].value = NULL;
1050 bufs[1] = skc->sc_dh_shared_key;
1051 bufs[2].value = &client_nid;
1052 bufs[2].length = sizeof(client_nid);
1053 bufs[3] = *client_token;
1054 bufs[4] = *server_token;
1056 return sk_kdf(&kctx->skc_session_key, &kctx->skc_shared_key, bufs,
1057 5, cfs_crypto_hash_alg(kctx->skc_hmac_alg));
1060 /* Uses the session key to create an HMAC key and encryption key. In
1061 * integrity mode the session key used to generate the HMAC key uses
1062 * session information which is available on the wire but by creating
1063 * a session based HMAC key we can prevent potential replay as both the
1064 * client and server have random numbers used as part of the key creation.
1066 * The keys used for integrity and privacy are formulated as below using
1067 * the session key that is the output of the key derivation function. The
1068 * HMAC algorithm is determined by the shared key algorithm selected in the
1072 * Session HMAC Key = PBKDF2("Integrity", KDF derived Session Key)
1075 * Session HMAC Key = PBKDF2("Integrity", KDF derived Session Key)
1076 * Session Encryption Key = PBKDF2("Encrypt", KDF derived Session Key)
1078 * \param[in,out] skc Shared key credentials structure with
1080 * \return -1 failure
1083 int sk_compute_keys(struct sk_cred *skc)
1085 struct sk_kernel_ctx *kctx = &skc->sc_kctx;
1086 gss_buffer_desc *session_key = &kctx->skc_session_key;
1087 gss_buffer_desc *hmac_key = &kctx->skc_hmac_key;
1088 gss_buffer_desc *encrypt_key = &kctx->skc_encrypt_key;
1089 enum cfs_crypto_hash_alg hmac_alg;
1090 enum cfs_crypto_crypt_alg crypt_alg;
1091 char *encrypt = "Encrypt";
1092 char *integrity = "Integrity";
1095 hmac_alg = cfs_crypto_hash_alg(kctx->skc_hmac_alg);
1096 hmac_key->length = cfs_crypto_hash_digestsize(hmac_alg);
1097 hmac_key->value = malloc(hmac_key->length);
1098 if (!hmac_key->value)
1101 rc = PKCS5_PBKDF2_HMAC(integrity, -1, session_key->value,
1102 session_key->length, SK_PBKDF2_ITERATIONS,
1103 sk_hash_to_evp_md(hmac_alg),
1104 hmac_key->length, hmac_key->value);
1108 /* Encryption key is only populated in privacy mode */
1109 if ((skc->sc_flags & LGSS_SVC_PRIV) == 0)
1112 crypt_alg = cfs_crypto_crypt_alg(kctx->skc_crypt_alg);
1113 encrypt_key->length = cfs_crypto_crypt_keysize(crypt_alg);
1114 encrypt_key->value = malloc(encrypt_key->length);
1115 if (!encrypt_key->value)
1118 rc = PKCS5_PBKDF2_HMAC(encrypt, -1, session_key->value,
1119 session_key->length, SK_PBKDF2_ITERATIONS,
1120 sk_hash_to_evp_md(hmac_alg),
1121 encrypt_key->length, encrypt_key->value);
1129 * Computes a session key based on the DH parameters from the host and its peer
1131 * \param[in,out] skc Shared key credentials structure with
1132 * the session key populated with the
1134 * \param[in] pub_key Public key returned from peer in
1136 * \return gss error failure
1137 * \return GSS_S_COMPLETE success
1139 uint32_t sk_compute_dh_key(struct sk_cred *skc, const gss_buffer_desc *pub_key)
1141 gss_buffer_desc *dh_shared = &skc->sc_dh_shared_key;
1142 BIGNUM *remote_pub_key;
1144 uint32_t rc = GSS_S_FAILURE;
1146 remote_pub_key = BN_bin2bn(pub_key->value, pub_key->length, NULL);
1147 if (!remote_pub_key) {
1148 printerr(0, "Failed to convert binary to BIGNUM\n");
1152 dh_shared->length = DH_size(skc->sc_params);
1153 dh_shared->value = malloc(dh_shared->length);
1154 if (!dh_shared->value) {
1155 printerr(0, "Failed to allocate memory for computed shared "
1160 /* This compute the shared key from the DHKE */
1161 status = DH_compute_key(dh_shared->value, remote_pub_key,
1164 printerr(0, "DH_compute_key() failed: %s\n",
1165 ERR_error_string(ERR_get_error(), NULL));
1167 } else if (status < dh_shared->length) {
1168 printerr(0, "DH_compute_key() returned a short key of %d "
1169 "bytes, expected: %zu\n", status, dh_shared->length);
1170 rc = GSS_S_DEFECTIVE_TOKEN;
1174 rc = GSS_S_COMPLETE;
1177 BN_free(remote_pub_key);
1182 * Creates a serialized buffer for the kernel in the order of struct
1185 * \param[in,out] skc Shared key credentials structure
1186 * \param[in,out] ctx_token Serialized buffer for kernel.
1187 * Caller must free this buffer.
1190 * \return -1 failure
1192 int sk_serialize_kctx(struct sk_cred *skc, gss_buffer_desc *ctx_token)
1194 struct sk_kernel_ctx *kctx = &skc->sc_kctx;
1198 bufsize = sizeof(*kctx) + kctx->skc_hmac_key.length +
1199 kctx->skc_encrypt_key.length;
1201 ctx_token->value = malloc(bufsize);
1202 if (!ctx_token->value)
1204 ctx_token->length = bufsize;
1206 p = ctx_token->value;
1207 end = p + ctx_token->length;
1209 if (WRITE_BYTES(&p, end, kctx->skc_version))
1211 if (WRITE_BYTES(&p, end, kctx->skc_hmac_alg))
1213 if (WRITE_BYTES(&p, end, kctx->skc_crypt_alg))
1215 if (WRITE_BYTES(&p, end, kctx->skc_expire))
1217 if (WRITE_BYTES(&p, end, kctx->skc_host_random))
1219 if (WRITE_BYTES(&p, end, kctx->skc_peer_random))
1221 if (write_buffer(&p, end, &kctx->skc_hmac_key))
1223 if (write_buffer(&p, end, &kctx->skc_encrypt_key))
1226 printerr(2, "Serialized buffer of %zu bytes for kernel\n", bufsize);
1232 * Decodes a netstring \a ns into array of gss_buffer_descs at \a bufs
1233 * up to \a numbufs. Memory is allocated for each value and length
1234 * will be populated with the length
1236 * \param[in,out] bufs Array of gss_buffer_descs
1237 * \param[in,out] numbufs number of gss_buffer_desc in array
1238 * \param[in] ns netstring to decode
1240 * \return buffers populated success
1241 * \return -1 failure
1243 int sk_decode_netstring(gss_buffer_desc *bufs, int numbufs, gss_buffer_desc *ns)
1245 char *ptr = ns->value;
1246 size_t remain = ns->length;
1253 for (i = 0; i < numbufs; i++) {
1254 /* read the size of first buffer */
1255 rc = sscanf(ptr, "%9u", &size);
1258 digits = (size) ? ceil(log10(size + 1)) : 1;
1260 /* sep of current string */
1261 sep = size + digits + 2;
1263 /* check to make sure it's valid */
1264 if (remain < sep || ptr[digits] != ':' ||
1265 ptr[sep - 1] != ',')
1268 bufs[i].length = size;
1270 bufs[i].value = NULL;
1272 bufs[i].value = malloc(size);
1275 memcpy(bufs[i].value, &ptr[digits + 1], size);
1282 printerr(2, "Decoded netstring of %zu bytes\n", ns->length);
1288 free(bufs[i].value);
1295 * Creates a netstring in a gss_buffer_desc that consists of all
1296 * the gss_buffer_desc found in \a bufs. The netstring should be treated
1297 * as binary as it can contain null characters.
1299 * \param[in] bufs Array of gss_buffer_desc to use as input
1300 * \param[in] numbufs Number of buffers in array
1301 * \param[in,out] ns Destination gss_buffer_desc to hold
1304 * \return -1 failure
1307 int sk_encode_netstring(gss_buffer_desc *bufs, int numbufs,
1308 gss_buffer_desc *ns)
1315 /* size of string in decimal, string size, colon, and comma */
1316 for (i = 0; i < numbufs; i++) {
1318 if (bufs[i].length == 0)
1321 size += ceil(log10(bufs[i].length + 1)) +
1326 ns->value = malloc(ns->length);
1333 for (i = 0; i < numbufs; i++) {
1335 rc = snprintf((char *) ptr, size, "%zu:", bufs[i].length);
1339 memcpy(ptr, bufs[i].value, bufs[i].length);
1340 ptr += bufs[i].length;
1345 size -= bufs[i].length + rc + 1;
1347 /* should not happen */
1352 printerr(2, "Encoded netstring of %zu bytes\n", ns->length);