security/keys/dh.c

Source file repositories/reference/linux-study-clean/security/keys/dh.c

File Facts

System
Linux kernel
Corpus path
security/keys/dh.c
Extension
.c
Size
6492 bytes
Lines
314
Domain
Core OS
Bucket
Security And Isolation
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

if (status == 0) {
			const struct user_key_payload *payload;
			uint8_t *duplicate;

			payload = user_key_payload_locked(key);

			duplicate = kmemdup(payload->data, payload->datalen,
					    GFP_KERNEL);
			if (duplicate) {
				*data = duplicate;
				ret = payload->datalen;
			} else {
				ret = -ENOMEM;
			}
		}
		up_read(&key->sem);
	}

	key_put(key);
error:
	return ret;
}

static void dh_free_data(struct dh *dh)
{
	kfree_sensitive(dh->key);
	kfree_sensitive(dh->p);
	kfree_sensitive(dh->g);
}

static int kdf_alloc(struct crypto_shash **hash, char *hashname)
{
	struct crypto_shash *tfm;

	/* allocate synchronous hash */
	tfm = crypto_alloc_shash(hashname, 0, 0);
	if (IS_ERR(tfm)) {
		pr_info("could not allocate digest TFM handle %s\n", hashname);
		return PTR_ERR(tfm);
	}

	if (crypto_shash_digestsize(tfm) == 0) {
		crypto_free_shash(tfm);
		return -EINVAL;
	}

	*hash = tfm;

	return 0;
}

static void kdf_dealloc(struct crypto_shash *hash)
{
	if (hash)
		crypto_free_shash(hash);
}

static int keyctl_dh_compute_kdf(struct crypto_shash *hash,
				 char __user *buffer, size_t buflen,
				 uint8_t *kbuf, size_t kbuflen)
{
	struct kvec kbuf_iov = { .iov_base = kbuf, .iov_len = kbuflen };
	uint8_t *outbuf = NULL;
	int ret;
	size_t outbuf_len = roundup(buflen, crypto_shash_digestsize(hash));

	outbuf = kmalloc(outbuf_len, GFP_KERNEL);
	if (!outbuf) {
		ret = -ENOMEM;
		goto err;
	}

	ret = crypto_kdf108_ctr_generate(hash, &kbuf_iov, 1, outbuf, outbuf_len);
	if (ret)
		goto err;

	ret = buflen;
	if (copy_to_user(buffer, outbuf, buflen) != 0)
		ret = -EFAULT;

err:
	kfree_sensitive(outbuf);
	return ret;
}

long __keyctl_dh_compute(struct keyctl_dh_params __user *params,
			 char __user *buffer, size_t buflen,
			 struct keyctl_kdf_params *kdfcopy)
{
	long ret;

Annotation

Implementation Notes