X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Futils%2Fgss%2Fsk_utils.c;h=c25a8ebdc3c7ce8970fb8f4004f0c98e73a2c553;hp=617a12ecb962cbe8a6ca5580ef8a7c165025f53f;hb=2c27b194121665061cc0527e8bef35886ec7fea8;hpb=3565394baa9589e0db190184e00f43689d6a4150 diff --git a/lustre/utils/gss/sk_utils.c b/lustre/utils/gss/sk_utils.c index 617a12e..c25a8eb 100644 --- a/lustre/utils/gss/sk_utils.c +++ b/lustre/utils/gss/sk_utils.c @@ -22,6 +22,8 @@ /* * Copyright (C) 2015, Trustees of Indiana University * + * Copyright (c) 2016, Intel Corporation. + * * Author: Jeremy Filizetti */ @@ -42,6 +44,8 @@ #include "sk_utils.h" #include "write_bytes.h" +#define SK_PBKDF2_ITERATIONS 10000 + static struct sk_crypt_type sk_crypt_types[] = { [SK_CRYPT_AES256_CTR] = { .sct_name = "ctr(aes)", @@ -107,14 +111,22 @@ struct sk_keyfile_config *sk_read_file(char *filename) /* allow standard input override */ if (strcmp(filename, "-") == 0) - fd = dup(STDIN_FILENO); + fd = STDIN_FILENO; else fd = open(filename, O_RDONLY); if (fd == -1) { - printerr(0, "Error opening file %s: %s\n", filename, + printerr(0, "Error opening key file '%s': %s\n", filename, strerror(errno)); goto out_free; + } else if (fd != STDIN_FILENO) { + struct stat st; + + rc = fstat(fd, &st); + if (rc == 0 && (st.st_mode & ~(S_IFREG | 0600))) + fprintf(stderr, "warning: " + "secret key '%s' has insecure file mode %#o\n", + filename, st.st_mode); } ptr = (char *)config; @@ -136,7 +148,8 @@ struct sk_keyfile_config *sk_read_file(char *filename) remain -= rc; } - close(fd); + if (fd != STDIN_FILENO) + close(fd); sk_config_disk_to_cpu(config); return config; @@ -198,7 +211,7 @@ static key_serial_t sk_load_key(const struct sk_keyfile_config *skc, * \return 0 sucess * \return -1 failure */ -int sk_load_keyfile(char *path, int type) +int sk_load_keyfile(char *path) { struct sk_keyfile_config *config; char description[SK_DESCRIPTION_SIZE + 1]; @@ -231,7 +244,7 @@ int sk_load_keyfile(char *path, int type) /* The server side can have multiple key files per file system so * the nodemap name is appended to the key description to uniquely * identify it */ - if (type & SK_TYPE_MGS) { + if (config->skc_type & SK_TYPE_MGS) { /* Any key can be an MGS key as long as we are told to use it */ rc = snprintf(description, SK_DESCRIPTION_SIZE, "lustre:MGS:%s", config->skc_nodemap); @@ -240,7 +253,7 @@ int sk_load_keyfile(char *path, int type) if (sk_load_key(config, description) == -1) goto out; } - if (type & SK_TYPE_SERVER) { + if (config->skc_type & SK_TYPE_SERVER) { /* Server keys need to have the file system name in the key */ if (!config->skc_fsname) { printerr(0, "Key configuration has no file system " @@ -254,7 +267,7 @@ int sk_load_keyfile(char *path, int type) if (sk_load_key(config, description) == -1) goto out; } - if (type & SK_TYPE_CLIENT) { + if (config->skc_type & SK_TYPE_CLIENT) { /* Load client file system key */ if (config->skc_fsname) { rc = snprintf(description, SK_DESCRIPTION_SIZE, @@ -298,15 +311,15 @@ void sk_config_cpu_to_disk(struct sk_keyfile_config *config) if (!config) return; - config->skc_version = be32_to_cpu(config->skc_version); - config->skc_hmac_alg = be16_to_cpu(config->skc_hmac_alg); - config->skc_crypt_alg = be16_to_cpu(config->skc_crypt_alg); - config->skc_expire = be32_to_cpu(config->skc_expire); - config->skc_shared_keylen = be32_to_cpu(config->skc_shared_keylen); - config->skc_session_keylen = be32_to_cpu(config->skc_session_keylen); + config->skc_version = htobe32(config->skc_version); + config->skc_hmac_alg = htobe16(config->skc_hmac_alg); + config->skc_crypt_alg = htobe16(config->skc_crypt_alg); + config->skc_expire = htobe32(config->skc_expire); + config->skc_shared_keylen = htobe32(config->skc_shared_keylen); + config->skc_prime_bits = htobe32(config->skc_prime_bits); for (i = 0; i < MAX_MGSNIDS; i++) - config->skc_mgsnids[i] = be64_to_cpu(config->skc_mgsnids[i]); + config->skc_mgsnids[i] = htobe64(config->skc_mgsnids[i]); return; } @@ -323,15 +336,15 @@ void sk_config_disk_to_cpu(struct sk_keyfile_config *config) if (!config) return; - config->skc_version = cpu_to_be32(config->skc_version); - config->skc_hmac_alg = cpu_to_be16(config->skc_hmac_alg); - config->skc_crypt_alg = cpu_to_be16(config->skc_crypt_alg); - config->skc_expire = cpu_to_be32(config->skc_expire); - config->skc_shared_keylen = cpu_to_be32(config->skc_shared_keylen); - config->skc_session_keylen = cpu_to_be32(config->skc_session_keylen); + config->skc_version = be32toh(config->skc_version); + config->skc_hmac_alg = be16toh(config->skc_hmac_alg); + config->skc_crypt_alg = be16toh(config->skc_crypt_alg); + config->skc_expire = be32toh(config->skc_expire); + config->skc_shared_keylen = be32toh(config->skc_shared_keylen); + config->skc_prime_bits = be32toh(config->skc_prime_bits); for (i = 0; i < MAX_MGSNIDS; i++) - config->skc_mgsnids[i] = cpu_to_be64(config->skc_mgsnids[i]); + config->skc_mgsnids[i] = be64toh(config->skc_mgsnids[i]); return; } @@ -372,11 +385,11 @@ int sk_validate_config(const struct sk_keyfile_config *config) "and %d\n", 60, INT_MAX); return -1; } - if (config->skc_session_keylen % 8 != 0 || - config->skc_session_keylen > SK_SESSION_MAX_KEYLEN_BYTES * 8) { + if (config->skc_prime_bits % 8 != 0 || + config->skc_prime_bits > SK_MAX_P_BYTES * 8) { printerr(0, "Invalid session key length must be a multiple of 8" " and less then %d bits\n", - SK_SESSION_MAX_KEYLEN_BYTES * 8); + SK_MAX_P_BYTES * 8); return -1; } if (config->skc_shared_keylen % 8 != 0 || @@ -404,6 +417,11 @@ int sk_validate_config(const struct sk_keyfile_config *config) return -1; } + if (config->skc_type == SK_TYPE_INVALID) { + printerr(0, "Invalid key type\n"); + return -1; + } + return 0; } @@ -648,7 +666,6 @@ struct sk_cred *sk_create_cred(const char *tgt, const char *nodemap, kctx->skc_expire = config->skc_expire; /* key payload format is in bits, convert to bytes */ - skc->sc_session_keylen = config->skc_session_keylen / 8; kctx->skc_shared_key.length = config->skc_shared_keylen / 8; kctx->skc_shared_key.value = malloc(kctx->skc_shared_key.length); if (!kctx->skc_shared_key.value) { @@ -658,50 +675,69 @@ struct sk_cred *sk_create_cred(const char *tgt, const char *nodemap, memcpy(kctx->skc_shared_key.value, config->skc_shared_key, kctx->skc_shared_key.length); + skc->sc_p.length = config->skc_prime_bits / 8; + skc->sc_p.value = malloc(skc->sc_p.length); + if (!skc->sc_p.value) { + printerr(0, "Failed to allocate p\n"); + goto out_err; + } + memcpy(skc->sc_p.value, config->skc_p, skc->sc_p.length); + free(config); return skc; out_err: - if (skc) - sk_free_cred(skc); + sk_free_cred(skc); free(config); return NULL; } /** - * Generates a public key and computes the private key for the DH key exchange. - * The parameters must be populated with the p and g from the peer. + * Populates the DH parameters for the DHKE * - * \param[in,out] skc Shared key credentials structure to populate - * with DH parameters + * \param[in,out] skc Shared key credentials structure to + * populate with DH parameters * * \retval GSS_S_COMPLETE success * \retval GSS_S_FAILURE failure */ -static uint32_t sk_gen_responder_params(struct sk_cred *skc) +uint32_t sk_gen_params(struct sk_cred *skc) { + uint32_t random; int rc; - /* No keys to generate without privacy mode */ - if ((skc->sc_flags & LGSS_SVC_PRIV) == 0) - return GSS_S_COMPLETE; + /* Random value used by both the request and response as part of the + * key binding material. This also should ensure we have unqiue + * tokens that are sent to the remote server which is important because + * the token is hashed for the sunrpc cache lookups and a failure there + * would cause connection attempts to fail indefinitely due to the large + * timeout value on the server side */ + if (RAND_bytes((unsigned char *)&random, sizeof(random)) != 1) { + printerr(0, "Failed to get data for random parameter: %s\n", + ERR_error_string(ERR_get_error(), NULL)); + return GSS_S_FAILURE; + } + + /* The random value will always be used in byte range operations + * so we keep it as big endian from this point on */ + skc->sc_kctx.skc_host_random = random; + /* Populate DH parameters */ skc->sc_params = DH_new(); if (!skc->sc_params) { printerr(0, "Failed to allocate DH\n"); return GSS_S_FAILURE; } - /* responder should already have sc_p populated */ skc->sc_params->p = BN_bin2bn(skc->sc_p.value, skc->sc_p.length, NULL); if (!skc->sc_params->p) { printerr(0, "Failed to convert binary to BIGNUM\n"); return GSS_S_FAILURE; } - /* and we use a static generator for shared key */ + /* We use a static generator for shared key */ skc->sc_params->g = BN_new(); if (!skc->sc_params->g) { printerr(0, "Failed to allocate new BIGNUM\n"); @@ -712,7 +748,7 @@ static uint32_t sk_gen_responder_params(struct sk_cred *skc) return GSS_S_FAILURE; } - /* verify that we have a safe prime and valid generator */ + /* Verify that we have a safe prime and valid generator */ if (DH_check(skc->sc_params, &rc) != 1) { printerr(0, "DH_check() failed: %d\n", rc); return GSS_S_FAILURE; @@ -739,120 +775,6 @@ static uint32_t sk_gen_responder_params(struct sk_cred *skc) return GSS_S_COMPLETE; } -static void sk_free_parameters(struct sk_cred *skc) -{ - if (skc->sc_params) - DH_free(skc->sc_params); - if (skc->sc_p.value) - free(skc->sc_p.value); - if (skc->sc_pub_key.value) - free(skc->sc_pub_key.value); - - skc->sc_p.value = NULL; - skc->sc_p.length = 0; - skc->sc_pub_key.value = NULL; - skc->sc_pub_key.length = 0; -} - -/** - * Generates shared key Diffie Hellman parameters used for the DH key exchange - * between host and peer if privacy mode is enabled - * - * \param[in,out] skc Shared key credentials structure to populate - * with DH parameters - * - * \retval GSS_S_COMPLETE success - * \retval GSS_S_FAILURE failure - */ -static uint32_t sk_gen_initiator_params(struct sk_cred *skc) -{ - gss_buffer_desc *iv = &skc->sc_kctx.skc_iv; - int rc; - - /* The credential could be used so free existing parameters */ - sk_free_parameters(skc); - - /* Pseudo random should be sufficient here because the IV will be used - * with a key that is used only once. This also should ensure we have - * unqiue tokens that are sent to the remote server which is important - * because the token is hashed for the sunrpc cache lookups and a - * failure there would cause connection attempts to fail indefinitely - * due to the large timeout value on the server side sunrpc cache - * (INT_MAX) */ - iv->length = SK_IV_SIZE; - iv->value = malloc(iv->length); - if (!iv->value) { - printerr(0, "Failed to allocate memory for IV\n"); - return GSS_S_FAILURE; - } - memset(iv->value, 0, iv->length); - if (RAND_bytes(iv->value, iv->length) != 1) { - printerr(0, "Failed to get data for IV\n"); - return GSS_S_FAILURE; - } - - /* Only privacy mode needs the rest of the parameter generation - * but we use IV in other modes as well so tokens should be - * unique */ - if ((skc->sc_flags & LGSS_SVC_PRIV) == 0) - return GSS_S_COMPLETE; - - skc->sc_params = DH_generate_parameters(skc->sc_session_keylen * 8, - SK_GENERATOR, NULL, NULL); - if (skc->sc_params == NULL) { - printerr(0, "Failed to generate diffie-hellman parameters: %s", - ERR_error_string(ERR_get_error(), NULL)); - return GSS_S_FAILURE; - } - - if (DH_check(skc->sc_params, &rc) != 1) { - printerr(0, "DH_check() failed: %d\n", rc); - return GSS_S_FAILURE; - } else if (rc) { - printerr(0, "DH_check() returned error codes: 0x%x\n", rc); - return GSS_S_FAILURE; - } - - if (DH_generate_key(skc->sc_params) != 1) { - printerr(0, "Failed to generate public DH key: %s\n", - ERR_error_string(ERR_get_error(), NULL)); - return GSS_S_FAILURE; - } - - skc->sc_p.length = BN_num_bytes(skc->sc_params->p); - skc->sc_pub_key.length = BN_num_bytes(skc->sc_params->pub_key); - skc->sc_p.value = malloc(skc->sc_p.length); - skc->sc_pub_key.value = malloc(skc->sc_pub_key.length); - if (!skc->sc_p.value || !skc->sc_pub_key.value) { - printerr(0, "Failed to allocate memory for params\n"); - return GSS_S_FAILURE; - } - - BN_bn2bin(skc->sc_params->pub_key, skc->sc_pub_key.value); - BN_bn2bin(skc->sc_params->p, skc->sc_p.value); - - return GSS_S_COMPLETE; -} - -/** - * Generates or populates the DH parameters depending on whether the system is - * the initiator or responder for the connection - * - * \param[in,out] skc Shared key credentials structure to - * populate with DH parameters - * \param[in] initiator Boolean whether to initiate parameters - * - * \retval GSS_S_COMPLETE success - * \retval GSS_S_FAILURE failure - */ -uint32_t sk_gen_params(struct sk_cred *skc, const bool initiator) -{ - if (initiator) - return sk_gen_initiator_params(skc); - - return sk_gen_responder_params(skc); -} - /** * Convert SK hash algorithm into openssl message digest * @@ -909,12 +831,6 @@ int sk_sign_bufs(gss_buffer_desc *key, gss_buffer_desc *bufs, const int numbufs, goto out; } -#ifdef HAVE_VOID_OPENSSL_HMAC_FUNCS - HMAC_Init_ex(&hctx, key->value, key->length, hash_alg, NULL); - for (i = 0; i < numbufs; i++) - HMAC_Update(&hctx, bufs[i].value, bufs[i].length); - HMAC_Final(&hctx, hmac->value, &hashlen); -#else if (HMAC_Init_ex(&hctx, key->value, key->length, hash_alg, NULL) != 1) { printerr(0, "Failed to init HMAC\n"); goto out; @@ -932,7 +848,6 @@ int sk_sign_bufs(gss_buffer_desc *key, gss_buffer_desc *bufs, const int numbufs, printerr(0, "Failed to finalize HMAC\n"); goto out; } -#endif if (hmac->length != hashlen) { printerr(0, "HMAC size does not match expected\n"); @@ -995,6 +910,9 @@ uint32_t sk_verify_hmac(struct sk_cred *skc, gss_buffer_desc *bufs, */ void sk_free_cred(struct sk_cred *skc) { + if (!skc) + return; + if (skc->sc_p.value) free(skc->sc_p.value); if (skc->sc_pub_key.value) @@ -1012,16 +930,21 @@ void sk_free_cred(struct sk_cred *skc) skc->sc_dh_shared_key.length); free(skc->sc_dh_shared_key.value); } + if (skc->sc_kctx.skc_hmac_key.value) { + memset(skc->sc_kctx.skc_hmac_key.value, 0, + skc->sc_kctx.skc_hmac_key.length); + free(skc->sc_kctx.skc_hmac_key.value); + } + if (skc->sc_kctx.skc_encrypt_key.value) { + memset(skc->sc_kctx.skc_encrypt_key.value, 0, + skc->sc_kctx.skc_encrypt_key.length); + free(skc->sc_kctx.skc_encrypt_key.value); + } if (skc->sc_kctx.skc_shared_key.value) { memset(skc->sc_kctx.skc_shared_key.value, 0, skc->sc_kctx.skc_shared_key.length); free(skc->sc_kctx.skc_shared_key.value); } - if (skc->sc_kctx.skc_iv.value) { - memset(skc->sc_kctx.skc_iv.value, 0, - skc->sc_kctx.skc_iv.length); - free(skc->sc_kctx.skc_iv.value); - } if (skc->sc_kctx.skc_session_key.value) { memset(skc->sc_kctx.skc_session_key.value, 0, skc->sc_kctx.skc_session_key.length); @@ -1032,6 +955,68 @@ void sk_free_cred(struct sk_cred *skc) DH_free(skc->sc_params); free(skc); + skc = NULL; +} + +/* This function handles key derivation using the hash algorithm specified in + * \a hash_alg, buffers in \a key_binding_bufs, and original key in + * \a origin_key to produce a \a derived_key. The first element of the + * key_binding_bufs array is reserved for the counter used in the KDF. The + * derived key in \a derived_key could differ in size from \a origin_key and + * must be populated with the expected size and a valid buffer to hold the + * contents. + * + * If the derived key size is greater than the HMAC algorithm size it will be + * a done using several iterations of a counter and the key binding bufs. + * + * If the size is smaller it will take copy the first N bytes necessary to + * fill the derived key. */ +int sk_kdf(gss_buffer_desc *derived_key , gss_buffer_desc *origin_key, + gss_buffer_desc *key_binding_bufs, int numbufs, int hmac_alg) +{ + size_t remain; + size_t bytes; + uint32_t counter; + char *keydata; + gss_buffer_desc tmp_hash; + int i; + int rc; + + if (numbufs < 1) + return -EINVAL; + + /* Use a counter as the first buffer followed by the key binding + * buffers in the event we need more than one a single cycle to + * produced a symmetric key large enough in size */ + key_binding_bufs[0].value = &counter; + key_binding_bufs[0].length = sizeof(counter); + + remain = derived_key->length; + keydata = derived_key->value; + i = 0; + while (remain > 0) { + counter = htobe32(i++); + rc = sk_sign_bufs(origin_key, key_binding_bufs, numbufs, + sk_hash_to_evp_md(hmac_alg), &tmp_hash); + if (rc) { + if (tmp_hash.value) + free(tmp_hash.value); + return rc; + } + + if (sk_hmac_types[hmac_alg].sht_bytes != tmp_hash.length) { + free(tmp_hash.value); + return -EINVAL; + } + + bytes = (remain < tmp_hash.length) ? remain : tmp_hash.length; + memcpy(keydata, tmp_hash.value, bytes); + free(tmp_hash.value); + remain -= bytes; + keydata += bytes; + } + + return 0; } /* Populates the sk_cred's session_key using the a Key Derviation Function (KDF) @@ -1043,18 +1028,12 @@ void sk_free_cred(struct sk_cred *skc) * \return -1 failure * \return 0 success */ -int sk_kdf(struct sk_cred *skc, lnet_nid_t client_nid, - gss_buffer_desc *key_binding_input) +int sk_session_kdf(struct sk_cred *skc, lnet_nid_t client_nid, + gss_buffer_desc *client_token, gss_buffer_desc *server_token) { struct sk_kernel_ctx *kctx = &skc->sc_kctx; gss_buffer_desc *session_key = &kctx->skc_session_key; - gss_buffer_desc bufs[4]; - gss_buffer_desc tmp_hash; - char *skp; - size_t remain; - size_t bytes; - uint32_t counter; - int i; + gss_buffer_desc bufs[5]; int rc = -1; session_key->length = sk_crypt_types[kctx->skc_crypt_alg].sct_bytes; @@ -1064,42 +1043,84 @@ int sk_kdf(struct sk_cred *skc, lnet_nid_t client_nid, return rc; } - /* Use the HMAC algorithm provided by in the shared key file to derive - * a session key. eg: HMAC(key, msg) - * key: the shared key provided in the shared key file - * msg is the bytes in the following order: - * 1. big_endian(counter) - * 2. DH shared key - * 3. Clients NIDs - * 4. key_binding_input */ - bufs[0].value = &counter; - bufs[0].length = sizeof(counter); + /* Key binding info ordering + * 1. Reserved for counter + * 1. DH shared key + * 2. Client's NIDs + * 3. Client's token + * 4. Server's token */ + bufs[0].value = NULL; + bufs[0].length = 0; bufs[1] = skc->sc_dh_shared_key; bufs[2].value = &client_nid; bufs[2].length = sizeof(client_nid); - bufs[3] = *key_binding_input; + bufs[3] = *client_token; + bufs[4] = *server_token; - remain = session_key->length; - skp = session_key->value; - i = 0; - while (remain > 0) { - counter = cpu_to_be32(i++); - rc = sk_sign_bufs(&kctx->skc_shared_key, bufs, 4, - sk_hash_to_evp_md(kctx->skc_hmac_alg), &tmp_hash); - if (rc) { - free(tmp_hash.value); - return rc; - } + return sk_kdf(&kctx->skc_session_key, &kctx->skc_shared_key, bufs, + 5, kctx->skc_hmac_alg); +} - LASSERT(sk_hmac_types[kctx->skc_hmac_alg].sht_bytes == - tmp_hash.length); +/* Uses the session key to create an HMAC key and encryption key. In + * integrity mode the session key used to generate the HMAC key uses + * session information which is available on the wire but by creating + * a session based HMAC key we can prevent potential replay as both the + * client and server have random numbers used as part of the key creation. + * + * The keys used for integrity and privacy are formulated as below using + * the session key that is the output of the key derivation function. The + * HMAC algorithm is determined by the shared key algorithm selected in the + * key file. + * + * For ski mode: + * Session HMAC Key = PBKDF2("Integrity", KDF derived Session Key) + * + * For skpi mode: + * Session HMAC Key = PBKDF2("Integrity", KDF derived Session Key) + * Session Encryption Key = PBKDF2("Encrypt", KDF derived Session Key) + * + * \param[in,out] skc Shared key credentials structure with + * + * \return -1 failure + * \return 0 success + */ +int sk_compute_keys(struct sk_cred *skc) +{ + struct sk_kernel_ctx *kctx = &skc->sc_kctx; + gss_buffer_desc *session_key = &kctx->skc_session_key; + gss_buffer_desc *hmac_key = &kctx->skc_hmac_key; + gss_buffer_desc *encrypt_key = &kctx->skc_encrypt_key; + char *encrypt = "Encrypt"; + char *integrity = "Integrity"; + int rc; - bytes = (remain < tmp_hash.length) ? remain : tmp_hash.length; - memcpy(skp, tmp_hash.value, bytes); - free(tmp_hash.value); - remain -= bytes; - skp += bytes; - } + hmac_key->length = sk_hmac_types[kctx->skc_hmac_alg].sht_bytes; + hmac_key->value = malloc(hmac_key->length); + if (!hmac_key->value) + return -ENOMEM; + + rc = PKCS5_PBKDF2_HMAC(integrity, -1, session_key->value, + session_key->length, SK_PBKDF2_ITERATIONS, + sk_hash_to_evp_md(kctx->skc_hmac_alg), + hmac_key->length, hmac_key->value); + if (rc == 0) + return -EINVAL; + + /* Encryption key is only populated in privacy mode */ + if ((skc->sc_flags & LGSS_SVC_PRIV) == 0) + return 0; + + encrypt_key->length = sk_crypt_types[kctx->skc_crypt_alg].sct_bytes; + encrypt_key->value = malloc(encrypt_key->length); + if (!encrypt_key->value) + return -ENOMEM; + + rc = PKCS5_PBKDF2_HMAC(encrypt, -1, session_key->value, + session_key->length, SK_PBKDF2_ITERATIONS, + sk_hash_to_evp_md(kctx->skc_hmac_alg), + encrypt_key->length, encrypt_key->value); + if (rc == 0) + return -EINVAL; return 0; } @@ -1115,17 +1136,13 @@ int sk_kdf(struct sk_cred *skc, lnet_nid_t client_nid, * \return gss error failure * \return GSS_S_COMPLETE success */ -uint32_t sk_compute_key(struct sk_cred *skc, const gss_buffer_desc *pub_key) +uint32_t sk_compute_dh_key(struct sk_cred *skc, const gss_buffer_desc *pub_key) { gss_buffer_desc *dh_shared = &skc->sc_dh_shared_key; BIGNUM *remote_pub_key; int status; uint32_t rc = GSS_S_FAILURE; - /* No keys computed unless privacy mode is in use */ - if ((skc->sc_flags & LGSS_SVC_PRIV) == 0) - return GSS_S_COMPLETE; - remote_pub_key = BN_bin2bn(pub_key->value, pub_key->length, NULL); if (!remote_pub_key) { printerr(0, "Failed to convert binary to BIGNUM\n"); @@ -1178,8 +1195,8 @@ int sk_serialize_kctx(struct sk_cred *skc, gss_buffer_desc *ctx_token) char *p, *end; size_t bufsize; - bufsize = sizeof(*kctx) + kctx->skc_session_key.length + - kctx->skc_iv.length + kctx->skc_shared_key.length; + bufsize = sizeof(*kctx) + kctx->skc_hmac_key.length + + kctx->skc_encrypt_key.length; ctx_token->value = malloc(bufsize); if (!ctx_token->value) @@ -1197,11 +1214,13 @@ int sk_serialize_kctx(struct sk_cred *skc, gss_buffer_desc *ctx_token) return -1; if (WRITE_BYTES(&p, end, kctx->skc_expire)) return -1; - if (write_buffer(&p, end, &kctx->skc_shared_key)) + if (WRITE_BYTES(&p, end, kctx->skc_host_random)) + return -1; + if (WRITE_BYTES(&p, end, kctx->skc_peer_random)) return -1; - if (write_buffer(&p, end, &kctx->skc_iv)) + if (write_buffer(&p, end, &kctx->skc_hmac_key)) return -1; - if (write_buffer(&p, end, &kctx->skc_session_key)) + if (write_buffer(&p, end, &kctx->skc_encrypt_key)) return -1; printerr(2, "Serialized buffer of %zu bytes for kernel\n", bufsize);