]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ksmbd: Use HMAC-SHA256 library for message signing and key generation
authorEric Biggers <ebiggers@kernel.org>
Tue, 14 Oct 2025 23:17:58 +0000 (16:17 -0700)
committerSteve French <stfrench@microsoft.com>
Mon, 1 Dec 2025 03:11:43 +0000 (21:11 -0600)
Convert ksmbd_sign_smb2_pdu() and generate_key() to use the HMAC-SHA256
library instead of a "hmac(sha256)" crypto_shash.  This is simpler and
faster.  With the library there's no need to allocate memory, no need to
handle errors, and the HMAC-SHA256 code is accessed directly without
inefficient indirect calls and other unnecessary API overhead.

Signed-off-by: Eric Biggers <ebiggers@kernel.org>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/server/Kconfig
fs/smb/server/auth.c
fs/smb/server/auth.h
fs/smb/server/crypto_ctx.c
fs/smb/server/crypto_ctx.h
fs/smb/server/server.c
fs/smb/server/smb2pdu.c
fs/smb/server/smb_common.h

index d5f3a417246d40e5f63c997d55fcbc758792b0a3..788104cfb082f855d7e53cdd14130c9fa648a361 100644 (file)
@@ -14,7 +14,6 @@ config SMB_SERVER
        select CRYPTO_LIB_DES
        select CRYPTO_LIB_SHA256
        select CRYPTO_LIB_SHA512
-       select CRYPTO_SHA256
        select CRYPTO_CMAC
        select CRYPTO_AEAD2
        select CRYPTO_CCM
index b7f2feede221f60cdb13d7057bb210b8fe539927..54918f43d2c6b5f73c58287fc61a3f6f12374558 100644 (file)
@@ -590,46 +590,16 @@ int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
  * @sig:       signature value generated for client request packet
  *
  */
-int ksmbd_sign_smb2_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
-                       int n_vec, char *sig)
+void ksmbd_sign_smb2_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
+                        int n_vec, char *sig)
 {
-       struct ksmbd_crypto_ctx *ctx;
-       int rc, i;
-
-       ctx = ksmbd_crypto_ctx_find_hmacsha256();
-       if (!ctx) {
-               ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n");
-               return -ENOMEM;
-       }
+       struct hmac_sha256_ctx ctx;
+       int i;
 
-       rc = crypto_shash_setkey(CRYPTO_HMACSHA256_TFM(ctx),
-                                key,
-                                SMB2_NTLMV2_SESSKEY_SIZE);
-       if (rc)
-               goto out;
-
-       rc = crypto_shash_init(CRYPTO_HMACSHA256(ctx));
-       if (rc) {
-               ksmbd_debug(AUTH, "hmacsha256 init error %d\n", rc);
-               goto out;
-       }
-
-       for (i = 0; i < n_vec; i++) {
-               rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx),
-                                        iov[i].iov_base,
-                                        iov[i].iov_len);
-               if (rc) {
-                       ksmbd_debug(AUTH, "hmacsha256 update error %d\n", rc);
-                       goto out;
-               }
-       }
-
-       rc = crypto_shash_final(CRYPTO_HMACSHA256(ctx), sig);
-       if (rc)
-               ksmbd_debug(AUTH, "hmacsha256 generation error %d\n", rc);
-out:
-       ksmbd_release_crypto_ctx(ctx);
-       return rc;
+       hmac_sha256_init_usingrawkey(&ctx, key, SMB2_NTLMV2_SESSKEY_SIZE);
+       for (i = 0; i < n_vec; i++)
+               hmac_sha256_update(&ctx, iov[i].iov_base, iov[i].iov_len);
+       hmac_sha256_final(&ctx, sig);
 }
 
 /**
@@ -689,98 +659,39 @@ struct derivation {
        bool binding;
 };
 
-static int generate_key(struct ksmbd_conn *conn, struct ksmbd_session *sess,
-                       struct kvec label, struct kvec context, __u8 *key,
-                       unsigned int key_size)
+static void generate_key(struct ksmbd_conn *conn, struct ksmbd_session *sess,
+                        struct kvec label, struct kvec context, __u8 *key,
+                        unsigned int key_size)
 {
        unsigned char zero = 0x0;
        __u8 i[4] = {0, 0, 0, 1};
        __u8 L128[4] = {0, 0, 0, 128};
        __u8 L256[4] = {0, 0, 1, 0};
-       int rc;
        unsigned char prfhash[SMB2_HMACSHA256_SIZE];
-       unsigned char *hashptr = prfhash;
-       struct ksmbd_crypto_ctx *ctx;
-
-       memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE);
-       memset(key, 0x0, key_size);
-
-       ctx = ksmbd_crypto_ctx_find_hmacsha256();
-       if (!ctx) {
-               ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n");
-               return -ENOMEM;
-       }
+       struct hmac_sha256_ctx ctx;
 
-       rc = crypto_shash_setkey(CRYPTO_HMACSHA256_TFM(ctx),
-                                sess->sess_key,
-                                SMB2_NTLMV2_SESSKEY_SIZE);
-       if (rc)
-               goto smb3signkey_ret;
-
-       rc = crypto_shash_init(CRYPTO_HMACSHA256(ctx));
-       if (rc) {
-               ksmbd_debug(AUTH, "hmacsha256 init error %d\n", rc);
-               goto smb3signkey_ret;
-       }
-
-       rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), i, 4);
-       if (rc) {
-               ksmbd_debug(AUTH, "could not update with n\n");
-               goto smb3signkey_ret;
-       }
-
-       rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx),
-                                label.iov_base,
-                                label.iov_len);
-       if (rc) {
-               ksmbd_debug(AUTH, "could not update with label\n");
-               goto smb3signkey_ret;
-       }
-
-       rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), &zero, 1);
-       if (rc) {
-               ksmbd_debug(AUTH, "could not update with zero\n");
-               goto smb3signkey_ret;
-       }
-
-       rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx),
-                                context.iov_base,
-                                context.iov_len);
-       if (rc) {
-               ksmbd_debug(AUTH, "could not update with context\n");
-               goto smb3signkey_ret;
-       }
+       hmac_sha256_init_usingrawkey(&ctx, sess->sess_key,
+                                    SMB2_NTLMV2_SESSKEY_SIZE);
+       hmac_sha256_update(&ctx, i, 4);
+       hmac_sha256_update(&ctx, label.iov_base, label.iov_len);
+       hmac_sha256_update(&ctx, &zero, 1);
+       hmac_sha256_update(&ctx, context.iov_base, context.iov_len);
 
        if (key_size == SMB3_ENC_DEC_KEY_SIZE &&
            (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
             conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
-               rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L256, 4);
+               hmac_sha256_update(&ctx, L256, 4);
        else
-               rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L128, 4);
-       if (rc) {
-               ksmbd_debug(AUTH, "could not update with L\n");
-               goto smb3signkey_ret;
-       }
+               hmac_sha256_update(&ctx, L128, 4);
 
-       rc = crypto_shash_final(CRYPTO_HMACSHA256(ctx), hashptr);
-       if (rc) {
-               ksmbd_debug(AUTH, "Could not generate hmacmd5 hash error %d\n",
-                           rc);
-               goto smb3signkey_ret;
-       }
-
-       memcpy(key, hashptr, key_size);
-
-smb3signkey_ret:
-       ksmbd_release_crypto_ctx(ctx);
-       return rc;
+       hmac_sha256_final(&ctx, prfhash);
+       memcpy(key, prfhash, key_size);
 }
 
 static int generate_smb3signingkey(struct ksmbd_session *sess,
                                   struct ksmbd_conn *conn,
                                   const struct derivation *signing)
 {
-       int rc;
        struct channel *chann;
        char *key;
 
@@ -793,10 +704,8 @@ static int generate_smb3signingkey(struct ksmbd_session *sess,
        else
                key = sess->smb3signingkey;
 
-       rc = generate_key(conn, sess, signing->label, signing->context, key,
-                         SMB3_SIGN_KEY_SIZE);
-       if (rc)
-               return rc;
+       generate_key(conn, sess, signing->label, signing->context, key,
+                    SMB3_SIGN_KEY_SIZE);
 
        if (!(conn->dialect >= SMB30_PROT_ID && signing->binding))
                memcpy(chann->smb3signingkey, key, SMB3_SIGN_KEY_SIZE);
@@ -852,23 +761,17 @@ struct derivation_twin {
        struct derivation decryption;
 };
 
-static int generate_smb3encryptionkey(struct ksmbd_conn *conn,
-                                     struct ksmbd_session *sess,
-                                     const struct derivation_twin *ptwin)
+static void generate_smb3encryptionkey(struct ksmbd_conn *conn,
+                                      struct ksmbd_session *sess,
+                                      const struct derivation_twin *ptwin)
 {
-       int rc;
+       generate_key(conn, sess, ptwin->encryption.label,
+                    ptwin->encryption.context, sess->smb3encryptionkey,
+                    SMB3_ENC_DEC_KEY_SIZE);
 
-       rc = generate_key(conn, sess, ptwin->encryption.label,
-                         ptwin->encryption.context, sess->smb3encryptionkey,
-                         SMB3_ENC_DEC_KEY_SIZE);
-       if (rc)
-               return rc;
-
-       rc = generate_key(conn, sess, ptwin->decryption.label,
-                         ptwin->decryption.context,
-                         sess->smb3decryptionkey, SMB3_ENC_DEC_KEY_SIZE);
-       if (rc)
-               return rc;
+       generate_key(conn, sess, ptwin->decryption.label,
+                    ptwin->decryption.context,
+                    sess->smb3decryptionkey, SMB3_ENC_DEC_KEY_SIZE);
 
        ksmbd_debug(AUTH, "dumping generated AES encryption keys\n");
        ksmbd_debug(AUTH, "Cipher type   %d\n", conn->cipher_type);
@@ -887,11 +790,10 @@ static int generate_smb3encryptionkey(struct ksmbd_conn *conn,
                ksmbd_debug(AUTH, "ServerOut Key %*ph\n",
                            SMB3_GCM128_CRYPTKEY_SIZE, sess->smb3decryptionkey);
        }
-       return 0;
 }
 
-int ksmbd_gen_smb30_encryptionkey(struct ksmbd_conn *conn,
-                                 struct ksmbd_session *sess)
+void ksmbd_gen_smb30_encryptionkey(struct ksmbd_conn *conn,
+                                  struct ksmbd_session *sess)
 {
        struct derivation_twin twin;
        struct derivation *d;
@@ -908,11 +810,11 @@ int ksmbd_gen_smb30_encryptionkey(struct ksmbd_conn *conn,
        d->context.iov_base = "ServerIn ";
        d->context.iov_len = 10;
 
-       return generate_smb3encryptionkey(conn, sess, &twin);
+       generate_smb3encryptionkey(conn, sess, &twin);
 }
 
-int ksmbd_gen_smb311_encryptionkey(struct ksmbd_conn *conn,
-                                  struct ksmbd_session *sess)
+void ksmbd_gen_smb311_encryptionkey(struct ksmbd_conn *conn,
+                                   struct ksmbd_session *sess)
 {
        struct derivation_twin twin;
        struct derivation *d;
@@ -929,7 +831,7 @@ int ksmbd_gen_smb311_encryptionkey(struct ksmbd_conn *conn,
        d->context.iov_base = sess->Preauth_HashValue;
        d->context.iov_len = 64;
 
-       return generate_smb3encryptionkey(conn, sess, &twin);
+       generate_smb3encryptionkey(conn, sess, &twin);
 }
 
 int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf,
index 6879a1bd1b91f5175ad474db03211ae6dc1de77a..6d351d61b0e575e2902784b2b0a2d5f106df7418 100644 (file)
@@ -52,18 +52,18 @@ ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob,
                                   struct ksmbd_conn *conn);
 int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
                            int in_len, char *out_blob, int *out_len);
-int ksmbd_sign_smb2_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
-                       int n_vec, char *sig);
+void ksmbd_sign_smb2_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
+                        int n_vec, char *sig);
 int ksmbd_sign_smb3_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
                        int n_vec, char *sig);
 int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess,
                               struct ksmbd_conn *conn);
 int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess,
                                struct ksmbd_conn *conn);
-int ksmbd_gen_smb30_encryptionkey(struct ksmbd_conn *conn,
-                                 struct ksmbd_session *sess);
-int ksmbd_gen_smb311_encryptionkey(struct ksmbd_conn *conn,
+void ksmbd_gen_smb30_encryptionkey(struct ksmbd_conn *conn,
                                   struct ksmbd_session *sess);
+void ksmbd_gen_smb311_encryptionkey(struct ksmbd_conn *conn,
+                                   struct ksmbd_session *sess);
 int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf,
                                     __u8 *pi_hash);
 #endif
index 1de41b10528bc4756860afa9da76377eb0ae9ed4..a5ec22ba8ae37630e68e0198859de2e917a5604d 100644 (file)
@@ -69,9 +69,6 @@ static struct shash_desc *alloc_shash_desc(int id)
        case CRYPTO_SHASH_HMACMD5:
                tfm = crypto_alloc_shash("hmac(md5)", 0, 0);
                break;
-       case CRYPTO_SHASH_HMACSHA256:
-               tfm = crypto_alloc_shash("hmac(sha256)", 0, 0);
-               break;
        case CRYPTO_SHASH_CMACAES:
                tfm = crypto_alloc_shash("cmac(aes)", 0, 0);
                break;
@@ -182,11 +179,6 @@ struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacmd5(void)
        return ____crypto_shash_ctx_find(CRYPTO_SHASH_HMACMD5);
 }
 
-struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacsha256(void)
-{
-       return ____crypto_shash_ctx_find(CRYPTO_SHASH_HMACSHA256);
-}
-
 struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_cmacaes(void)
 {
        return ____crypto_shash_ctx_find(CRYPTO_SHASH_CMACAES);
index 4e8954acd8b8b986c8dbbf14e0257be658a9e26c..c571d65a16f3eb83aec3e54fb7902df1910bc8b1 100644 (file)
@@ -11,7 +11,6 @@
 
 enum {
        CRYPTO_SHASH_HMACMD5    = 0,
-       CRYPTO_SHASH_HMACSHA256,
        CRYPTO_SHASH_CMACAES,
        CRYPTO_SHASH_MAX,
 };
@@ -35,12 +34,9 @@ struct ksmbd_crypto_ctx {
 };
 
 #define CRYPTO_HMACMD5(c)      ((c)->desc[CRYPTO_SHASH_HMACMD5])
-#define CRYPTO_HMACSHA256(c)   ((c)->desc[CRYPTO_SHASH_HMACSHA256])
 #define CRYPTO_CMACAES(c)      ((c)->desc[CRYPTO_SHASH_CMACAES])
 
 #define CRYPTO_HMACMD5_TFM(c)  ((c)->desc[CRYPTO_SHASH_HMACMD5]->tfm)
-#define CRYPTO_HMACSHA256_TFM(c)\
-                               ((c)->desc[CRYPTO_SHASH_HMACSHA256]->tfm)
 #define CRYPTO_CMACAES_TFM(c)  ((c)->desc[CRYPTO_SHASH_CMACAES]->tfm)
 
 #define CRYPTO_GCM(c)          ((c)->ccmaes[CRYPTO_AEAD_AES_GCM])
@@ -48,7 +44,6 @@ struct ksmbd_crypto_ctx {
 
 void ksmbd_release_crypto_ctx(struct ksmbd_crypto_ctx *ctx);
 struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacmd5(void);
-struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacsha256(void);
 struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_cmacaes(void);
 struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_gcm(void);
 struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_ccm(void);
index 51e2aee2a6985197bcb11944ced366d9e04e0138..8bce97633e01a4526657da13f13e6a8e35357f78 100644 (file)
@@ -627,7 +627,6 @@ MODULE_SOFTDEP("pre: md5");
 MODULE_SOFTDEP("pre: nls");
 MODULE_SOFTDEP("pre: aes");
 MODULE_SOFTDEP("pre: cmac");
-MODULE_SOFTDEP("pre: sha256");
 MODULE_SOFTDEP("pre: aead2");
 MODULE_SOFTDEP("pre: ccm");
 MODULE_SOFTDEP("pre: gcm");
index f901ae18e68adf66b4b93700f36aa8a44e5c12b2..17ce41fb99957568ae3f92feba4912ebd3afd9f7 100644 (file)
@@ -1538,12 +1538,7 @@ static int ntlm_authenticate(struct ksmbd_work *work,
 
        if (smb3_encryption_negotiated(conn) &&
                        !(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
-               rc = conn->ops->generate_encryptionkey(conn, sess);
-               if (rc) {
-                       ksmbd_debug(SMB,
-                                       "SMB3 encryption key generation failed\n");
-                       return -EINVAL;
-               }
+               conn->ops->generate_encryptionkey(conn, sess);
                sess->enc = true;
                if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION)
                        rsp->SessionFlags = SMB2_SESSION_FLAG_ENCRYPT_DATA_LE;
@@ -1640,12 +1635,7 @@ static int krb5_authenticate(struct ksmbd_work *work,
 
        if (smb3_encryption_negotiated(conn) &&
            !(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
-               retval = conn->ops->generate_encryptionkey(conn, sess);
-               if (retval) {
-                       ksmbd_debug(SMB,
-                                   "SMB3 encryption key generation failed\n");
-                       return -EINVAL;
-               }
+               conn->ops->generate_encryptionkey(conn, sess);
                sess->enc = true;
                if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION)
                        rsp->SessionFlags = SMB2_SESSION_FLAG_ENCRYPT_DATA_LE;
@@ -8861,9 +8851,8 @@ int smb2_check_sign_req(struct ksmbd_work *work)
        iov[0].iov_base = (char *)&hdr->ProtocolId;
        iov[0].iov_len = len;
 
-       if (ksmbd_sign_smb2_pdu(work->conn, work->sess->sess_key, iov, 1,
-                               signature))
-               return 0;
+       ksmbd_sign_smb2_pdu(work->conn, work->sess->sess_key, iov, 1,
+                           signature);
 
        if (memcmp(signature, signature_req, SMB2_SIGNATURE_SIZE)) {
                pr_err("bad smb2 signature\n");
@@ -8896,9 +8885,9 @@ void smb2_set_sign_rsp(struct ksmbd_work *work)
                iov = &work->iov[work->iov_idx];
        }
 
-       if (!ksmbd_sign_smb2_pdu(work->conn, work->sess->sess_key, iov, n_vec,
-                                signature))
-               memcpy(hdr->Signature, signature, SMB2_SIGNATURE_SIZE);
+       ksmbd_sign_smb2_pdu(work->conn, work->sess->sess_key, iov, n_vec,
+                           signature);
+       memcpy(hdr->Signature, signature, SMB2_SIGNATURE_SIZE);
 }
 
 /**
index 863716207a0defcdc02fd96ad7cc4f97b2435752..9fa1da647d90e851edd913822808e28fe3ec023c 100644 (file)
@@ -402,7 +402,7 @@ struct smb_version_ops {
        int (*check_sign_req)(struct ksmbd_work *work);
        void (*set_sign_rsp)(struct ksmbd_work *work);
        int (*generate_signingkey)(struct ksmbd_session *sess, struct ksmbd_conn *conn);
-       int (*generate_encryptionkey)(struct ksmbd_conn *conn, struct ksmbd_session *sess);
+       void (*generate_encryptionkey)(struct ksmbd_conn *conn, struct ksmbd_session *sess);
        bool (*is_transform_hdr)(void *buf);
        int (*decrypt_req)(struct ksmbd_work *work);
        int (*encrypt_resp)(struct ksmbd_work *work);