Commit c4a9f055 authored by Chuck Lever's avatar Chuck Lever
Browse files

SUNRPC: Add encryption self-tests



With the KUnit infrastructure recently added, we are free to define
other unit tests particular to our implementation. As an example,
I've added a self-test that encrypts then decrypts a string, and
checks the result.

Tested-by: default avatarScott Mayhew <smayhew@redhat.com>
Reviewed-by: default avatarSimo Sorce <simo@redhat.com>
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent 4d2d15c0
Loading
Loading
Loading
Loading
+16 −4
Original line number Diff line number Diff line
@@ -713,8 +713,19 @@ int krb5_cbc_cts_encrypt(struct crypto_sync_skcipher *cts_tfm,
}
EXPORT_SYMBOL_IF_KUNIT(krb5_cbc_cts_encrypt);

static int
krb5_cbc_cts_decrypt(struct crypto_sync_skcipher *cts_tfm,
/**
 * krb5_cbc_cts_decrypt - decrypt in CBC mode with CTS
 * @cts_tfm: CBC cipher with CTS
 * @cbc_tfm: base CBC cipher
 * @offset: starting byte offset for plaintext
 * @buf: OUT: output buffer
 *
 * Return values:
 *   %0: decryption successful
 *   negative errno: decryption could not be completed
 */
VISIBLE_IF_KUNIT
int krb5_cbc_cts_decrypt(struct crypto_sync_skcipher *cts_tfm,
			 struct crypto_sync_skcipher *cbc_tfm,
			 u32 offset, struct xdr_buf *buf)
{
@@ -752,6 +763,7 @@ krb5_cbc_cts_decrypt(struct crypto_sync_skcipher *cts_tfm,
	/* Remaining plaintext is handled with CBC-CTS. */
	return gss_krb5_cts_crypt(cts_tfm, buf, cbcbytes, desc.iv, NULL, 0);
}
EXPORT_SYMBOL_IF_KUNIT(krb5_cbc_cts_decrypt);

u32
gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset,
+3 −0
Original line number Diff line number Diff line
@@ -221,6 +221,9 @@ int krb5_cbc_cts_encrypt(struct crypto_sync_skcipher *cts_tfm,
			 struct crypto_sync_skcipher *cbc_tfm, u32 offset,
			 struct xdr_buf *buf, struct page **pages,
			 u8 *iv, unsigned int ivsize);
int krb5_cbc_cts_decrypt(struct crypto_sync_skcipher *cts_tfm,
			 struct crypto_sync_skcipher *cbc_tfm,
			 u32 offset, struct xdr_buf *buf);
u32 krb5_etm_checksum(struct crypto_sync_skcipher *cipher,
		      struct crypto_ahash *tfm, const struct xdr_buf *body,
		      int body_offset, struct xdr_netobj *cksumout);
+123 −1
Original line number Diff line number Diff line
@@ -1909,10 +1909,132 @@ static struct kunit_suite rfc8009_suite = {
	.test_cases		= rfc8009_test_cases,
};

/*
 * Encryption self-tests
 */

DEFINE_STR_XDR_NETOBJ(encrypt_selftest_plaintext,
		      "This is the plaintext for the encryption self-test.");

static const struct gss_krb5_test_param encrypt_selftest_params[] = {
	{
		.desc			= "aes128-cts-hmac-sha1-96 encryption self-test",
		.enctype		= ENCTYPE_AES128_CTS_HMAC_SHA1_96,
		.Ke			= &rfc3962_encryption_key,
		.plaintext		= &encrypt_selftest_plaintext,
	},
	{
		.desc			= "aes256-cts-hmac-sha1-96 encryption self-test",
		.enctype		= ENCTYPE_AES256_CTS_HMAC_SHA1_96,
		.Ke			= &rfc3962_encryption_key,
		.plaintext		= &encrypt_selftest_plaintext,
	},
	{
		.desc			= "camellia128-cts-cmac encryption self-test",
		.enctype		= ENCTYPE_CAMELLIA128_CTS_CMAC,
		.Ke			= &camellia128_cts_cmac_Ke,
		.plaintext		= &encrypt_selftest_plaintext,
	},
	{
		.desc			= "camellia256-cts-cmac encryption self-test",
		.enctype		= ENCTYPE_CAMELLIA256_CTS_CMAC,
		.Ke			= &camellia256_cts_cmac_Ke,
		.plaintext		= &encrypt_selftest_plaintext,
	},
	{
		.desc			= "aes128-cts-hmac-sha256-128 encryption self-test",
		.enctype		= ENCTYPE_AES128_CTS_HMAC_SHA256_128,
		.Ke			= &aes128_cts_hmac_sha256_128_Ke,
		.plaintext		= &encrypt_selftest_plaintext,
	},
	{
		.desc			= "aes256-cts-hmac-sha384-192 encryption self-test",
		.enctype		= ENCTYPE_AES256_CTS_HMAC_SHA384_192,
		.Ke			= &aes256_cts_hmac_sha384_192_Ke,
		.plaintext		= &encrypt_selftest_plaintext,
	},
};

/* Creates the function encrypt_selftest_gen_params */
KUNIT_ARRAY_PARAM(encrypt_selftest, encrypt_selftest_params,
		  gss_krb5_get_desc);

/*
 * Encrypt and decrypt plaintext, and ensure the input plaintext
 * matches the output plaintext. A confounder is not added in this
 * case.
 */
static void encrypt_selftest_case(struct kunit *test)
{
	const struct gss_krb5_test_param *param = test->param_value;
	struct crypto_sync_skcipher *cts_tfm, *cbc_tfm;
	const struct gss_krb5_enctype *gk5e;
	struct xdr_buf buf;
	void *text;
	int err;

	/* Arrange */
	gk5e = gss_krb5_lookup_enctype(param->enctype);
	KUNIT_ASSERT_NOT_NULL(test, gk5e);

	cbc_tfm = crypto_alloc_sync_skcipher(gk5e->aux_cipher, 0, 0);
	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cbc_tfm);
	err = crypto_sync_skcipher_setkey(cbc_tfm, param->Ke->data, param->Ke->len);
	KUNIT_ASSERT_EQ(test, err, 0);

	cts_tfm = crypto_alloc_sync_skcipher(gk5e->encrypt_name, 0, 0);
	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cts_tfm);
	err = crypto_sync_skcipher_setkey(cts_tfm, param->Ke->data, param->Ke->len);
	KUNIT_ASSERT_EQ(test, err, 0);

	text = kunit_kzalloc(test, roundup(param->plaintext->len,
					   crypto_sync_skcipher_blocksize(cbc_tfm)),
			     GFP_KERNEL);
	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, text);

	memcpy(text, param->plaintext->data, param->plaintext->len);
	memset(&buf, 0, sizeof(buf));
	buf.head[0].iov_base = text;
	buf.head[0].iov_len = param->plaintext->len;
	buf.len = buf.head[0].iov_len;

	/* Act */
	err = krb5_cbc_cts_encrypt(cts_tfm, cbc_tfm, 0, &buf, NULL, NULL, 0);
	KUNIT_ASSERT_EQ(test, err, 0);
	err = krb5_cbc_cts_decrypt(cts_tfm, cbc_tfm, 0, &buf);
	KUNIT_ASSERT_EQ(test, err, 0);

	/* Assert */
	KUNIT_EXPECT_EQ_MSG(test,
			    param->plaintext->len, buf.len,
			    "length mismatch");
	KUNIT_EXPECT_EQ_MSG(test,
			    memcmp(param->plaintext->data,
				   buf.head[0].iov_base, buf.len), 0,
			    "plaintext mismatch");

	crypto_free_sync_skcipher(cts_tfm);
	crypto_free_sync_skcipher(cbc_tfm);
}

static struct kunit_case encryption_test_cases[] = {
	{
		.name			= "Encryption self-tests",
		.run_case		= encrypt_selftest_case,
		.generate_params	= encrypt_selftest_gen_params,
	},
};

static struct kunit_suite encryption_test_suite = {
	.name			= "Encryption test suite",
	.test_cases		= encryption_test_cases,
};

kunit_test_suites(&rfc3961_suite,
		  &rfc3962_suite,
		  &rfc6803_suite,
		  &rfc8009_suite);
		  &rfc8009_suite,
		  &encryption_test_suite);

MODULE_DESCRIPTION("Test RPCSEC GSS Kerberos 5 functions");
MODULE_LICENSE("GPL");