crypto/krb5/rfc3961_simplified.c

Source file repositories/reference/linux-study-clean/crypto/krb5/rfc3961_simplified.c

File Facts

System
Linux kernel
Corpus path
crypto/krb5/rfc3961_simplified.c
Extension
.c
Size
21188 bytes
Lines
794
Domain
Kernel Services
Bucket
crypto
Inferred role
Kernel Services: implementation source
Status
source implementation candidate

Why This File Exists

Shared kernel service surface used by multiple subsystems, including helpers, cryptography, virtualization support, and async I/O infrastructure.

Dependency Surface

Detected Declarations

Annotated Snippet

if (keybytes - n <= outblock.len) {
			memcpy(rawkey.data + n, outblock.data, keybytes - n);
			break;
		}

		memcpy(rawkey.data + n, outblock.data, outblock.len);
		memcpy(inblock.data, outblock.data, outblock.len);
		n += outblock.len;
	}

	/* postprocess the key */
	if (!krb5->random_to_key) {
		/* Identity random-to-key function. */
		memcpy(result->data, rawkey.data, rawkey.len);
		ret = 0;
	} else {
		ret = krb5->random_to_key(krb5, &rawkey, result);
	}

	kfree_sensitive(inblock.data);
err_free_cipher:
	crypto_free_sync_skcipher(cipher);
err_return:
	return ret;
}

/*
 * Calculate single encryption, E()
 *
 *	E(Key, octets)
 */
static int rfc3961_calc_E(const struct krb5_enctype *krb5,
			  const struct krb5_buffer *key,
			  const struct krb5_buffer *in_data,
			  struct krb5_buffer *result,
			  gfp_t gfp)
{
	struct crypto_sync_skcipher *cipher;
	int ret;

	cipher = crypto_alloc_sync_skcipher(krb5->derivation_enc, 0, 0);
	if (IS_ERR(cipher)) {
		ret = (PTR_ERR(cipher) == -ENOENT) ? -ENOPKG : PTR_ERR(cipher);
		goto err;
	}

	ret = crypto_sync_skcipher_setkey(cipher, key->data, key->len);
	if (ret < 0)
		goto err_free;

	ret = rfc3961_do_encrypt(cipher, NULL, in_data, result);

err_free:
	crypto_free_sync_skcipher(cipher);
err:
	return ret;
}

/*
 * Calculate the pseudo-random function, PRF().
 *
 *      tmp1 = H(octet-string)
 *      tmp2 = truncate tmp1 to multiple of m
 *      PRF = E(DK(protocol-key, prfconstant), tmp2, initial-cipher-state)
 *
 *      The "prfconstant" used in the PRF operation is the three-octet string
 *      "prf".
 *      [rfc3961 sec 5.3]
 */
static int rfc3961_calc_PRF(const struct krb5_enctype *krb5,
			    const struct krb5_buffer *protocol_key,
			    const struct krb5_buffer *octet_string,
			    struct krb5_buffer *result,
			    gfp_t gfp)
{
	static const struct krb5_buffer prfconstant = { 3, "prf" };
	struct krb5_buffer derived_key;
	struct krb5_buffer tmp1, tmp2;
	unsigned int m = krb5->block_len;
	void *buffer;
	int ret;

	if (result->len != krb5->prf_len)
		return -EINVAL;

	tmp1.len = krb5->hash_len;
	derived_key.len = krb5->key_bytes;
	buffer = kzalloc(round16(tmp1.len) + round16(derived_key.len), gfp);
	if (!buffer)
		return -ENOMEM;

Annotation

Implementation Notes