/*
* Copyright (C) 2015, Trustees of Indiana University
*
+ * Copyright (c) 2016, 2017, Intel Corporation.
+ *
* Author: Jeremy Filizetti <jfilizet@iu.edu>
*/
#include <openssl/hmac.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <lnet/nidstr.h>
#include "sk_utils.h"
#include "write_bytes.h"
-static struct sk_crypt_type sk_crypt_types[] = {
- [SK_CRYPT_AES256_CTR] = {
- .sct_name = "ctr(aes)",
- .sct_bytes = 32,
- },
-};
-
-static struct sk_hmac_type sk_hmac_types[] = {
- [SK_HMAC_SHA256] = {
- .sht_name = "hmac(sha256)",
- .sht_bytes = 32,
- },
- [SK_HMAC_SHA512] = {
- .sht_name = "hmac(sha512)",
- .sht_bytes = 64,
- },
-};
+#define SK_PBKDF2_ITERATIONS 10000
#ifdef _NEW_BUILD_
# include "lgss_utils.h"
/* 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;
remain -= rc;
}
- close(fd);
+ if (fd != STDIN_FILENO)
+ close(fd);
sk_config_disk_to_cpu(config);
return config;
* \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];
/* 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);
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 "
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,
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_session_keylen = htobe32(config->skc_session_keylen);
+ config->skc_prime_bits = htobe32(config->skc_prime_bits);
for (i = 0; i < MAX_MGSNIDS; i++)
config->skc_mgsnids[i] = htobe64(config->skc_mgsnids[i]);
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_session_keylen = be32toh(config->skc_session_keylen);
+ config->skc_prime_bits = be32toh(config->skc_prime_bits);
for (i = 0; i < MAX_MGSNIDS; i++)
config->skc_mgsnids[i] = be64toh(config->skc_mgsnids[i]);
printerr(0, "Null configuration passed\n");
return -1;
}
+
if (config->skc_version != SK_CONF_VERSION) {
printerr(0, "Invalid version\n");
return -1;
}
- if (config->skc_hmac_alg >= SK_HMAC_MAX) {
+
+ if (config->skc_hmac_alg == SK_HMAC_INVALID) {
printerr(0, "Invalid HMAC algorithm\n");
return -1;
}
- if (config->skc_crypt_alg >= SK_CRYPT_MAX) {
+
+ if (config->skc_crypt_alg == SK_CRYPT_INVALID) {
printerr(0, "Invalid crypt algorithm\n");
return -1;
}
+
if (config->skc_expire < 60 || config->skc_expire > INT_MAX) {
/* Try to limit key expiration to some reasonable minimum and
* also prevent values over INT_MAX because there appears
"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 ||
return -1;
}
+ if (config->skc_type == SK_TYPE_INVALID) {
+ printerr(0, "Invalid key type\n");
+ return -1;
+ }
+
return 0;
}
kctx = &skc->sc_kctx;
kctx->skc_version = config->skc_version;
- kctx->skc_hmac_alg = config->skc_hmac_alg;
- kctx->skc_crypt_alg = config->skc_crypt_alg;
+ strcpy(kctx->skc_hmac_alg, sk_hmac2name(config->skc_hmac_alg));
+ strcpy(kctx->skc_crypt_alg, sk_crypt2name(config->skc_crypt_alg));
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) {
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");
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;
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
*
*
* \retval EVP_MD
*/
-static inline const EVP_MD *sk_hash_to_evp_md(enum sk_hmac_alg alg)
+static inline const EVP_MD *sk_hash_to_evp_md(enum cfs_crypto_hash_alg alg)
{
switch (alg) {
- case SK_HMAC_SHA256:
+ case CFS_HASH_ALG_SHA256:
return EVP_sha256();
- case SK_HMAC_SHA512:
+ case CFS_HASH_ALG_SHA512:
return EVP_sha512();
default:
return EVP_md_null();
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;
printerr(0, "Failed to finalize HMAC\n");
goto out;
}
-#endif
if (hmac->length != hashlen) {
printerr(0, "HMAC size does not match expected\n");
*/
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)
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);
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,
+ enum cfs_crypto_hash_alg 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 (cfs_crypto_hash_digestsize(hmac_alg) != 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)
* \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];
+ enum cfs_crypto_crypt_alg crypt_alg;
int rc = -1;
- /* No keys computed unless privacy mode is in use */
- if ((skc->sc_flags & LGSS_SVC_PRIV) == 0)
- return 0;
-
- session_key->length = sk_crypt_types[kctx->skc_crypt_alg].sct_bytes;
+ crypt_alg = cfs_crypto_crypt_alg(kctx->skc_crypt_alg);
+ session_key->length = cfs_crypto_crypt_keysize(crypt_alg);
session_key->value = malloc(session_key->length);
if (!session_key->value) {
printerr(0, "Failed to allocate memory for session key\n");
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 = be32toh(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, cfs_crypto_hash_alg(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;
+ enum cfs_crypto_hash_alg hmac_alg;
+ enum cfs_crypto_crypt_alg crypt_alg;
+ 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_alg = cfs_crypto_hash_alg(kctx->skc_hmac_alg);
+ hmac_key->length = cfs_crypto_hash_digestsize(hmac_alg);
+ 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(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;
+
+ crypt_alg = cfs_crypto_crypt_alg(kctx->skc_crypt_alg);
+ encrypt_key->length = cfs_crypto_crypt_keysize(crypt_alg);
+ 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(hmac_alg),
+ encrypt_key->length, encrypt_key->value);
+ if (rc == 0)
+ return -EINVAL;
return 0;
}
* \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");
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)
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);