Skip to content

Commit e1a9a38

Browse files
committed
SUNRPC: Add Kunit tests for RFC 3962-defined encryption/decryption
Add Kunit tests for ENCTYPE_AES128_CTS_HMAC_SHA1_96. The test vectors come from RFC 3962 Appendix B. Tested-by: Scott Mayhew <smayhew@redhat.com> Reviewed-by: Simo Sorce <simo@redhat.com> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
1 parent 6eb6b8a commit e1a9a38

4 files changed

Lines changed: 296 additions & 9 deletions

File tree

net/sunrpc/.kunitconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ CONFIG_CRYPTO_HMAC=y
1414
CONFIG_CRYPTO_MD5=y
1515
CONFIG_CRYPTO_SHA1=y
1616
CONFIG_CRYPTO_DES=y
17+
CONFIG_CRYPTO_AES=y
1718
CONFIG_NFS_FS=y
1819
CONFIG_SUNRPC=y
1920
CONFIG_SUNRPC_GSS=y
2021
CONFIG_RPCSEC_GSS_KRB5=y
2122
CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_DES=y
23+
CONFIG_RPCSEC_GSS_KRB5_ENCTYPES_AES_SHA1=y
2224
CONFIG_RPCSEC_GSS_KRB5_KUNIT_TEST=y

net/sunrpc/auth_gss/gss_krb5_crypto.c

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#include <linux/random.h>
4747
#include <linux/sunrpc/gss_krb5.h>
4848
#include <linux/sunrpc/xdr.h>
49+
#include <kunit/visibility.h>
4950

5051
#include "gss_krb5_internal.h"
5152

@@ -640,14 +641,28 @@ gss_krb5_cts_crypt(struct crypto_sync_skcipher *cipher, struct xdr_buf *buf,
640641
return ret;
641642
}
642643

643-
/*
644+
/**
645+
* krb5_cbc_cts_encrypt - encrypt in CBC mode with CTS
646+
* @cts_tfm: CBC cipher with CTS
647+
* @cbc_tfm: base CBC cipher
648+
* @offset: starting byte offset for plaintext
649+
* @buf: OUT: output buffer
650+
* @pages: plaintext
651+
* @iv: output CBC initialization vector, or NULL
652+
* @ivsize: size of @iv, in octets
653+
*
644654
* To provide confidentiality, encrypt using cipher block chaining
645655
* with ciphertext stealing. Message integrity is handled separately.
656+
*
657+
* Return values:
658+
* %0: encryption successful
659+
* negative errno: encryption could not be completed
646660
*/
647-
static int
648-
krb5_cbc_cts_encrypt(struct crypto_sync_skcipher *cts_tfm,
649-
struct crypto_sync_skcipher *cbc_tfm,
650-
u32 offset, struct xdr_buf *buf, struct page **pages)
661+
VISIBLE_IF_KUNIT
662+
int krb5_cbc_cts_encrypt(struct crypto_sync_skcipher *cts_tfm,
663+
struct crypto_sync_skcipher *cbc_tfm,
664+
u32 offset, struct xdr_buf *buf, struct page **pages,
665+
u8 *iv, unsigned int ivsize)
651666
{
652667
u32 blocksize, nbytes, nblocks, cbcbytes;
653668
struct encryptor_desc desc;
@@ -691,8 +706,11 @@ krb5_cbc_cts_encrypt(struct crypto_sync_skcipher *cts_tfm,
691706
if (err)
692707
return err;
693708

709+
if (unlikely(iv))
710+
memcpy(iv, desc.iv, ivsize);
694711
return 0;
695712
}
713+
EXPORT_SYMBOL_IF_KUNIT(krb5_cbc_cts_encrypt);
696714

697715
static int
698716
krb5_cbc_cts_decrypt(struct crypto_sync_skcipher *cts_tfm,
@@ -800,7 +818,7 @@ gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset,
800818

801819
err = krb5_cbc_cts_encrypt(cipher, aux_cipher,
802820
offset + GSS_KRB5_TOK_HDR_LEN,
803-
buf, pages);
821+
buf, pages, NULL, 0);
804822
if (err)
805823
return GSS_S_FAILURE;
806824

@@ -992,7 +1010,7 @@ krb5_etm_encrypt(struct krb5_ctx *kctx, u32 offset,
9921010

9931011
err = krb5_cbc_cts_encrypt(cipher, aux_cipher,
9941012
offset + GSS_KRB5_TOK_HDR_LEN,
995-
buf, pages);
1013+
buf, pages, NULL, 0);
9961014
if (err)
9971015
return GSS_S_FAILURE;
9981016

net/sunrpc/auth_gss/gss_krb5_internal.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,10 @@ u32 krb5_etm_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len,
217217
#if IS_ENABLED(CONFIG_KUNIT)
218218
void krb5_nfold(u32 inbits, const u8 *in, u32 outbits, u8 *out);
219219
const struct gss_krb5_enctype *gss_krb5_lookup_enctype(u32 etype);
220+
int krb5_cbc_cts_encrypt(struct crypto_sync_skcipher *cts_tfm,
221+
struct crypto_sync_skcipher *cbc_tfm, u32 offset,
222+
struct xdr_buf *buf, struct page **pages,
223+
u8 *iv, unsigned int ivsize);
220224
#endif
221225

222226
#endif /* _NET_SUNRPC_AUTH_GSS_KRB5_INTERNAL_H */

net/sunrpc/auth_gss/gss_krb5_test.c

Lines changed: 265 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@ struct gss_krb5_test_param {
2323
u32 enctype;
2424
u32 nfold;
2525
const struct xdr_netobj *base_key;
26+
const struct xdr_netobj *Ke;
2627
const struct xdr_netobj *usage;
27-
const struct xdr_netobj *plaintext;
28+
const struct xdr_netobj *plaintext;
2829
const struct xdr_netobj *expected_result;
30+
const struct xdr_netobj *next_iv;
2931
};
3032

3133
static inline void gss_krb5_get_desc(const struct gss_krb5_test_param *param,
@@ -465,7 +467,268 @@ static struct kunit_suite rfc3961_suite = {
465467
.test_cases = rfc3961_test_cases,
466468
};
467469

468-
kunit_test_suites(&rfc3961_suite);
470+
/*
471+
* From RFC 3962 Appendix B: Sample Test Vectors
472+
*
473+
* Some test vectors for CBC with ciphertext stealing, using an
474+
* initial vector of all-zero.
475+
*
476+
* This test material is copyright (C) The Internet Society (2005).
477+
*/
478+
479+
DEFINE_HEX_XDR_NETOBJ(rfc3962_encryption_key,
480+
0x63, 0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x20,
481+
0x74, 0x65, 0x72, 0x69, 0x79, 0x61, 0x6b, 0x69
482+
);
483+
484+
DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test1_plaintext,
485+
0x49, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20,
486+
0x6c, 0x69, 0x6b, 0x65, 0x20, 0x74, 0x68, 0x65,
487+
0x20
488+
);
489+
DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test1_expected_result,
490+
0xc6, 0x35, 0x35, 0x68, 0xf2, 0xbf, 0x8c, 0xb4,
491+
0xd8, 0xa5, 0x80, 0x36, 0x2d, 0xa7, 0xff, 0x7f,
492+
0x97
493+
);
494+
DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test1_next_iv,
495+
0xc6, 0x35, 0x35, 0x68, 0xf2, 0xbf, 0x8c, 0xb4,
496+
0xd8, 0xa5, 0x80, 0x36, 0x2d, 0xa7, 0xff, 0x7f
497+
);
498+
499+
DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test2_plaintext,
500+
0x49, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20,
501+
0x6c, 0x69, 0x6b, 0x65, 0x20, 0x74, 0x68, 0x65,
502+
0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
503+
0x20, 0x47, 0x61, 0x75, 0x27, 0x73, 0x20
504+
);
505+
DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test2_expected_result,
506+
0xfc, 0x00, 0x78, 0x3e, 0x0e, 0xfd, 0xb2, 0xc1,
507+
0xd4, 0x45, 0xd4, 0xc8, 0xef, 0xf7, 0xed, 0x22,
508+
0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0,
509+
0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5
510+
);
511+
DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test2_next_iv,
512+
0xfc, 0x00, 0x78, 0x3e, 0x0e, 0xfd, 0xb2, 0xc1,
513+
0xd4, 0x45, 0xd4, 0xc8, 0xef, 0xf7, 0xed, 0x22
514+
);
515+
516+
DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test3_plaintext,
517+
0x49, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20,
518+
0x6c, 0x69, 0x6b, 0x65, 0x20, 0x74, 0x68, 0x65,
519+
0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
520+
0x20, 0x47, 0x61, 0x75, 0x27, 0x73, 0x20, 0x43
521+
);
522+
DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test3_expected_result,
523+
0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5,
524+
0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5, 0xa8,
525+
0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0,
526+
0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84
527+
);
528+
DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test3_next_iv,
529+
0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5,
530+
0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5, 0xa8
531+
);
532+
533+
DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test4_plaintext,
534+
0x49, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20,
535+
0x6c, 0x69, 0x6b, 0x65, 0x20, 0x74, 0x68, 0x65,
536+
0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
537+
0x20, 0x47, 0x61, 0x75, 0x27, 0x73, 0x20, 0x43,
538+
0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x2c, 0x20,
539+
0x70, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2c
540+
);
541+
DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test4_expected_result,
542+
0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0,
543+
0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84,
544+
0xb3, 0xff, 0xfd, 0x94, 0x0c, 0x16, 0xa1, 0x8c,
545+
0x1b, 0x55, 0x49, 0xd2, 0xf8, 0x38, 0x02, 0x9e,
546+
0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5,
547+
0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5
548+
);
549+
DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test4_next_iv,
550+
0xb3, 0xff, 0xfd, 0x94, 0x0c, 0x16, 0xa1, 0x8c,
551+
0x1b, 0x55, 0x49, 0xd2, 0xf8, 0x38, 0x02, 0x9e
552+
);
553+
554+
DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test5_plaintext,
555+
0x49, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20,
556+
0x6c, 0x69, 0x6b, 0x65, 0x20, 0x74, 0x68, 0x65,
557+
0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
558+
0x20, 0x47, 0x61, 0x75, 0x27, 0x73, 0x20, 0x43,
559+
0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x2c, 0x20,
560+
0x70, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2c, 0x20
561+
);
562+
DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test5_expected_result,
563+
0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0,
564+
0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84,
565+
0x9d, 0xad, 0x8b, 0xbb, 0x96, 0xc4, 0xcd, 0xc0,
566+
0x3b, 0xc1, 0x03, 0xe1, 0xa1, 0x94, 0xbb, 0xd8,
567+
0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5,
568+
0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5, 0xa8
569+
);
570+
DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test5_next_iv,
571+
0x9d, 0xad, 0x8b, 0xbb, 0x96, 0xc4, 0xcd, 0xc0,
572+
0x3b, 0xc1, 0x03, 0xe1, 0xa1, 0x94, 0xbb, 0xd8
573+
);
574+
575+
DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test6_plaintext,
576+
0x49, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20,
577+
0x6c, 0x69, 0x6b, 0x65, 0x20, 0x74, 0x68, 0x65,
578+
0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
579+
0x20, 0x47, 0x61, 0x75, 0x27, 0x73, 0x20, 0x43,
580+
0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x2c, 0x20,
581+
0x70, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x2c, 0x20,
582+
0x61, 0x6e, 0x64, 0x20, 0x77, 0x6f, 0x6e, 0x74,
583+
0x6f, 0x6e, 0x20, 0x73, 0x6f, 0x75, 0x70, 0x2e
584+
);
585+
DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test6_expected_result,
586+
0x97, 0x68, 0x72, 0x68, 0xd6, 0xec, 0xcc, 0xc0,
587+
0xc0, 0x7b, 0x25, 0xe2, 0x5e, 0xcf, 0xe5, 0x84,
588+
0x39, 0x31, 0x25, 0x23, 0xa7, 0x86, 0x62, 0xd5,
589+
0xbe, 0x7f, 0xcb, 0xcc, 0x98, 0xeb, 0xf5, 0xa8,
590+
0x48, 0x07, 0xef, 0xe8, 0x36, 0xee, 0x89, 0xa5,
591+
0x26, 0x73, 0x0d, 0xbc, 0x2f, 0x7b, 0xc8, 0x40,
592+
0x9d, 0xad, 0x8b, 0xbb, 0x96, 0xc4, 0xcd, 0xc0,
593+
0x3b, 0xc1, 0x03, 0xe1, 0xa1, 0x94, 0xbb, 0xd8
594+
);
595+
DEFINE_HEX_XDR_NETOBJ(rfc3962_enc_test6_next_iv,
596+
0x48, 0x07, 0xef, 0xe8, 0x36, 0xee, 0x89, 0xa5,
597+
0x26, 0x73, 0x0d, 0xbc, 0x2f, 0x7b, 0xc8, 0x40
598+
);
599+
600+
static const struct gss_krb5_test_param rfc3962_encrypt_test_params[] = {
601+
{
602+
.desc = "Encrypt with aes128-cts-hmac-sha1-96 case 1",
603+
.enctype = ENCTYPE_AES128_CTS_HMAC_SHA1_96,
604+
.Ke = &rfc3962_encryption_key,
605+
.plaintext = &rfc3962_enc_test1_plaintext,
606+
.expected_result = &rfc3962_enc_test1_expected_result,
607+
.next_iv = &rfc3962_enc_test1_next_iv,
608+
},
609+
{
610+
.desc = "Encrypt with aes128-cts-hmac-sha1-96 case 2",
611+
.enctype = ENCTYPE_AES128_CTS_HMAC_SHA1_96,
612+
.Ke = &rfc3962_encryption_key,
613+
.plaintext = &rfc3962_enc_test2_plaintext,
614+
.expected_result = &rfc3962_enc_test2_expected_result,
615+
.next_iv = &rfc3962_enc_test2_next_iv,
616+
},
617+
{
618+
.desc = "Encrypt with aes128-cts-hmac-sha1-96 case 3",
619+
.enctype = ENCTYPE_AES128_CTS_HMAC_SHA1_96,
620+
.Ke = &rfc3962_encryption_key,
621+
.plaintext = &rfc3962_enc_test3_plaintext,
622+
.expected_result = &rfc3962_enc_test3_expected_result,
623+
.next_iv = &rfc3962_enc_test3_next_iv,
624+
},
625+
{
626+
.desc = "Encrypt with aes128-cts-hmac-sha1-96 case 4",
627+
.enctype = ENCTYPE_AES128_CTS_HMAC_SHA1_96,
628+
.Ke = &rfc3962_encryption_key,
629+
.plaintext = &rfc3962_enc_test4_plaintext,
630+
.expected_result = &rfc3962_enc_test4_expected_result,
631+
.next_iv = &rfc3962_enc_test4_next_iv,
632+
},
633+
{
634+
.desc = "Encrypt with aes128-cts-hmac-sha1-96 case 5",
635+
.enctype = ENCTYPE_AES128_CTS_HMAC_SHA1_96,
636+
.Ke = &rfc3962_encryption_key,
637+
.plaintext = &rfc3962_enc_test5_plaintext,
638+
.expected_result = &rfc3962_enc_test5_expected_result,
639+
.next_iv = &rfc3962_enc_test5_next_iv,
640+
},
641+
{
642+
.desc = "Encrypt with aes128-cts-hmac-sha1-96 case 6",
643+
.enctype = ENCTYPE_AES128_CTS_HMAC_SHA1_96,
644+
.Ke = &rfc3962_encryption_key,
645+
.plaintext = &rfc3962_enc_test6_plaintext,
646+
.expected_result = &rfc3962_enc_test6_expected_result,
647+
.next_iv = &rfc3962_enc_test6_next_iv,
648+
},
649+
};
650+
651+
/* Creates the function rfc3962_encrypt_gen_params */
652+
KUNIT_ARRAY_PARAM(rfc3962_encrypt, rfc3962_encrypt_test_params,
653+
gss_krb5_get_desc);
654+
655+
/*
656+
* This tests the implementation of the encryption part of the mechanism.
657+
* It does not apply a confounder or test the result of HMAC over the
658+
* plaintext.
659+
*/
660+
static void rfc3962_encrypt_case(struct kunit *test)
661+
{
662+
const struct gss_krb5_test_param *param = test->param_value;
663+
struct crypto_sync_skcipher *cts_tfm, *cbc_tfm;
664+
const struct gss_krb5_enctype *gk5e;
665+
struct xdr_buf buf;
666+
void *iv, *text;
667+
u32 err;
668+
669+
/* Arrange */
670+
gk5e = gss_krb5_lookup_enctype(param->enctype);
671+
KUNIT_ASSERT_NOT_NULL(test, gk5e);
672+
673+
cbc_tfm = crypto_alloc_sync_skcipher(gk5e->aux_cipher, 0, 0);
674+
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cbc_tfm);
675+
err = crypto_sync_skcipher_setkey(cbc_tfm, param->Ke->data, param->Ke->len);
676+
KUNIT_ASSERT_EQ(test, err, 0);
677+
678+
cts_tfm = crypto_alloc_sync_skcipher(gk5e->encrypt_name, 0, 0);
679+
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cts_tfm);
680+
err = crypto_sync_skcipher_setkey(cts_tfm, param->Ke->data, param->Ke->len);
681+
KUNIT_ASSERT_EQ(test, err, 0);
682+
683+
iv = kunit_kzalloc(test, crypto_sync_skcipher_ivsize(cts_tfm), GFP_KERNEL);
684+
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, iv);
685+
686+
text = kunit_kzalloc(test, param->plaintext->len, GFP_KERNEL);
687+
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, text);
688+
689+
memcpy(text, param->plaintext->data, param->plaintext->len);
690+
memset(&buf, 0, sizeof(buf));
691+
buf.head[0].iov_base = text;
692+
buf.head[0].iov_len = param->plaintext->len;
693+
buf.len = buf.head[0].iov_len;
694+
695+
/* Act */
696+
err = krb5_cbc_cts_encrypt(cts_tfm, cbc_tfm, 0, &buf, NULL,
697+
iv, crypto_sync_skcipher_ivsize(cts_tfm));
698+
KUNIT_ASSERT_EQ(test, err, 0);
699+
700+
/* Assert */
701+
KUNIT_EXPECT_EQ_MSG(test,
702+
param->expected_result->len, buf.len,
703+
"ciphertext length mismatch");
704+
KUNIT_EXPECT_EQ_MSG(test,
705+
memcmp(param->expected_result->data,
706+
text, param->expected_result->len), 0,
707+
"ciphertext mismatch");
708+
KUNIT_EXPECT_EQ_MSG(test,
709+
memcmp(param->next_iv->data, iv,
710+
param->next_iv->len), 0,
711+
"IV mismatch");
712+
713+
crypto_free_sync_skcipher(cts_tfm);
714+
crypto_free_sync_skcipher(cbc_tfm);
715+
}
716+
717+
static struct kunit_case rfc3962_test_cases[] = {
718+
{
719+
.name = "RFC 3962 encryption",
720+
.run_case = rfc3962_encrypt_case,
721+
.generate_params = rfc3962_encrypt_gen_params,
722+
},
723+
};
724+
725+
static struct kunit_suite rfc3962_suite = {
726+
.name = "RFC 3962 suite",
727+
.test_cases = rfc3962_test_cases,
728+
};
729+
730+
kunit_test_suites(&rfc3961_suite,
731+
&rfc3962_suite);
469732

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

0 commit comments

Comments
 (0)