fs/smb/server/auth.c

Source file repositories/reference/linux-study-clean/fs/smb/server/auth.c

File Facts

System
Linux kernel
Corpus path
fs/smb/server/auth.c
Extension
.c
Size
24654 bytes
Lines
914
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

struct derivation {
	struct kvec label;
	struct kvec context;
	bool binding;
};

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};
	unsigned char prfhash[SMB2_HMACSHA256_SIZE];
	struct hmac_sha256_ctx ctx;

	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))
		hmac_sha256_update(&ctx, L256, 4);
	else
		hmac_sha256_update(&ctx, L128, 4);

	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)
{
	struct channel *chann;
	char *key;

	chann = lookup_chann_list(sess, conn);
	if (!chann)
		return 0;

	if (conn->dialect >= SMB30_PROT_ID && signing->binding)
		key = chann->smb3signingkey;
	else
		key = sess->smb3signingkey;

	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);

	ksmbd_debug(AUTH, "generated SMB3 signing key\n");
	ksmbd_debug(AUTH, "Session Id    %llu\n", sess->id);
	return 0;
}

int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess,
			       struct ksmbd_conn *conn)
{
	struct derivation d;

	d.label.iov_base = "SMB2AESCMAC";
	d.label.iov_len = 12;
	d.context.iov_base = "SmbSign";
	d.context.iov_len = 8;
	d.binding = conn->binding;

	return generate_smb3signingkey(sess, conn, &d);
}

int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess,
				struct ksmbd_conn *conn)
{
	struct derivation d;

	d.label.iov_base = "SMBSigningKey";
	d.label.iov_len = 14;
	if (conn->binding) {
		struct preauth_session *preauth_sess;

		preauth_sess = ksmbd_preauth_session_lookup(conn, sess->id);
		if (!preauth_sess)
			return -ENOENT;
		d.context.iov_base = preauth_sess->Preauth_HashValue;

Annotation

Implementation Notes