Skip to content

Commit 5c12a9c

Browse files
Hannes Reineckekeithbusch
authored andcommitted
nvme: add nvme_auth_generate_psk()
Add a function to generate a NVMe PSK from the shared credentials negotiated by DH-HMAC-CHAP. Signed-off-by: Hannes Reinecke <[email protected]> Reviewed-by: Sagi Grimberg <[email protected]> Signed-off-by: Keith Busch <[email protected]>
1 parent 3241cd0 commit 5c12a9c

File tree

2 files changed

+90
-0
lines changed

2 files changed

+90
-0
lines changed

drivers/nvme/common/auth.c

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <linux/unaligned.h>
1212
#include <crypto/hash.h>
1313
#include <crypto/dh.h>
14+
#include <crypto/hkdf.h>
1415
#include <linux/nvme.h>
1516
#include <linux/nvme-auth.h>
1617

@@ -471,5 +472,91 @@ int nvme_auth_generate_key(u8 *secret, struct nvme_dhchap_key **ret_key)
471472
}
472473
EXPORT_SYMBOL_GPL(nvme_auth_generate_key);
473474

475+
/**
476+
* nvme_auth_generate_psk - Generate a PSK for TLS
477+
* @hmac_id: Hash function identifier
478+
* @skey: Session key
479+
* @skey_len: Length of @skey
480+
* @c1: Value of challenge C1
481+
* @c2: Value of challenge C2
482+
* @hash_len: Hash length of the hash algorithm
483+
* @ret_psk: Pointer too the resulting generated PSK
484+
* @ret_len: length of @ret_psk
485+
*
486+
* Generate a PSK for TLS as specified in NVMe base specification, section
487+
* 8.13.5.9: Generated PSK for TLS
488+
*
489+
* The generated PSK for TLS shall be computed applying the HMAC function
490+
* using the hash function H( ) selected by the HashID parameter in the
491+
* DH-HMAC-CHAP_Challenge message with the session key KS as key to the
492+
* concatenation of the two challenges C1 and C2 (i.e., generated
493+
* PSK = HMAC(KS, C1 || C2)).
494+
*
495+
* Returns 0 on success with a valid generated PSK pointer in @ret_psk and
496+
* the length of @ret_psk in @ret_len, or a negative error number otherwise.
497+
*/
498+
int nvme_auth_generate_psk(u8 hmac_id, u8 *skey, size_t skey_len,
499+
u8 *c1, u8 *c2, size_t hash_len, u8 **ret_psk, size_t *ret_len)
500+
{
501+
struct crypto_shash *tfm;
502+
SHASH_DESC_ON_STACK(shash, tfm);
503+
u8 *psk;
504+
const char *hmac_name;
505+
int ret, psk_len;
506+
507+
if (!c1 || !c2)
508+
return -EINVAL;
509+
510+
hmac_name = nvme_auth_hmac_name(hmac_id);
511+
if (!hmac_name) {
512+
pr_warn("%s: invalid hash algorithm %d\n",
513+
__func__, hmac_id);
514+
return -EINVAL;
515+
}
516+
517+
tfm = crypto_alloc_shash(hmac_name, 0, 0);
518+
if (IS_ERR(tfm))
519+
return PTR_ERR(tfm);
520+
521+
psk_len = crypto_shash_digestsize(tfm);
522+
psk = kzalloc(psk_len, GFP_KERNEL);
523+
if (!psk) {
524+
ret = -ENOMEM;
525+
goto out_free_tfm;
526+
}
527+
528+
shash->tfm = tfm;
529+
ret = crypto_shash_setkey(tfm, skey, skey_len);
530+
if (ret)
531+
goto out_free_psk;
532+
533+
ret = crypto_shash_init(shash);
534+
if (ret)
535+
goto out_free_psk;
536+
537+
ret = crypto_shash_update(shash, c1, hash_len);
538+
if (ret)
539+
goto out_free_psk;
540+
541+
ret = crypto_shash_update(shash, c2, hash_len);
542+
if (ret)
543+
goto out_free_psk;
544+
545+
ret = crypto_shash_final(shash, psk);
546+
if (!ret) {
547+
*ret_psk = psk;
548+
*ret_len = psk_len;
549+
}
550+
551+
out_free_psk:
552+
if (ret)
553+
kfree_sensitive(psk);
554+
out_free_tfm:
555+
crypto_free_shash(tfm);
556+
557+
return ret;
558+
}
559+
EXPORT_SYMBOL_GPL(nvme_auth_generate_psk);
560+
474561
MODULE_DESCRIPTION("NVMe Authentication framework");
475562
MODULE_LICENSE("GPL v2");

include/linux/nvme-auth.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,8 @@ int nvme_auth_gen_pubkey(struct crypto_kpp *dh_tfm,
4040
int nvme_auth_gen_shared_secret(struct crypto_kpp *dh_tfm,
4141
u8 *ctrl_key, size_t ctrl_key_len,
4242
u8 *sess_key, size_t sess_key_len);
43+
int nvme_auth_generate_psk(u8 hmac_id, u8 *skey, size_t skey_len,
44+
u8 *c1, u8 *c2, size_t hash_len,
45+
u8 **ret_psk, size_t *ret_len);
4346

4447
#endif /* _NVME_AUTH_H */

0 commit comments

Comments
 (0)