Skip to content

Commit d2c69e6

Browse files
hodgesdsKernel Patches Daemon
authored andcommitted
selftests/bpf: Add tests for bpf_crypto_hash kfunc
Add selftests to validate the bpf_crypto_hash works properly. The tests verify both correct functionality and proper error handling. Test Data: All tests use the well-known NIST test vector input "abc" and validate against the standardized expected outputs for each algorithm. This ensures the BPF kfunc wrappers correctly delegate to the kernel crypto library. Signed-off-by: Daniel Hodges <[email protected]>
1 parent c8c51b6 commit d2c69e6

File tree

3 files changed

+291
-0
lines changed

3 files changed

+291
-0
lines changed

tools/testing/selftests/bpf/config

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ CONFIG_BPF_SYSCALL=y
1212
# CONFIG_BPF_UNPRIV_DEFAULT_OFF is not set
1313
CONFIG_CGROUP_BPF=y
1414
CONFIG_CRYPTO_HMAC=y
15+
CONFIG_CRYPTO_HASH2=y
1516
CONFIG_CRYPTO_SHA256=y
17+
CONFIG_CRYPTO_SHA512=y
1618
CONFIG_CRYPTO_USER_API=y
1719
CONFIG_CRYPTO_USER_API_HASH=y
1820
CONFIG_CRYPTO_USER_API_SKCIPHER=y
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (c) 2025 Meta Platforms, Inc. and affiliates. */
3+
4+
#include <test_progs.h>
5+
#include <errno.h>
6+
#include "crypto_hash.skel.h"
7+
8+
/* NIST test vectors for SHA-256("abc") */
9+
static const unsigned char expected_sha256[32] = {
10+
0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
11+
0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
12+
0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
13+
0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad
14+
};
15+
16+
/* NIST test vectors for SHA-384("abc") */
17+
static const unsigned char expected_sha384[48] = {
18+
0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b,
19+
0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07,
20+
0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63,
21+
0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed,
22+
0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23,
23+
0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7
24+
};
25+
26+
/* NIST test vectors for SHA-512("abc") */
27+
static const unsigned char expected_sha512[64] = {
28+
0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
29+
0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
30+
0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
31+
0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
32+
0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,
33+
0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
34+
0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
35+
0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f
36+
};
37+
38+
static struct crypto_hash *setup_skel(void)
39+
{
40+
struct crypto_hash *skel;
41+
42+
skel = crypto_hash__open_and_load();
43+
if (!skel) {
44+
/* Skip if kfuncs not available (CONFIG_CRYPTO_HASH2 not set) */
45+
if (errno == ENOENT || errno == EINVAL) {
46+
test__skip();
47+
return NULL;
48+
}
49+
ASSERT_OK_PTR(skel, "crypto_hash__open_and_load");
50+
return NULL;
51+
}
52+
53+
return skel;
54+
}
55+
56+
static void test_sha256_basic(void)
57+
{
58+
struct crypto_hash *skel;
59+
int err, prog_fd;
60+
61+
LIBBPF_OPTS(bpf_test_run_opts, topts);
62+
63+
skel = setup_skel();
64+
if (!skel)
65+
return;
66+
67+
prog_fd = bpf_program__fd(skel->progs.test_sha256);
68+
err = bpf_prog_test_run_opts(prog_fd, &topts);
69+
ASSERT_OK(err, "test_sha256");
70+
ASSERT_EQ(skel->data->sha256_status, 0, "sha256_status");
71+
ASSERT_EQ(memcmp(skel->bss->sha256_output, expected_sha256, 32), 0,
72+
"sha256_output_match");
73+
74+
crypto_hash__destroy(skel);
75+
}
76+
77+
static void test_sha384_basic(void)
78+
{
79+
struct crypto_hash *skel;
80+
int err, prog_fd;
81+
82+
LIBBPF_OPTS(bpf_test_run_opts, topts);
83+
84+
skel = setup_skel();
85+
if (!skel)
86+
return;
87+
prog_fd = bpf_program__fd(skel->progs.test_sha384);
88+
err = bpf_prog_test_run_opts(prog_fd, &topts);
89+
ASSERT_OK(err, "test_sha384");
90+
ASSERT_EQ(skel->data->sha384_status, 0, "sha384_status");
91+
ASSERT_EQ(memcmp(skel->bss->sha384_output, expected_sha384, 48), 0,
92+
"sha384_output_match");
93+
94+
crypto_hash__destroy(skel);
95+
}
96+
97+
static void test_sha512_basic(void)
98+
{
99+
struct crypto_hash *skel;
100+
int err, prog_fd;
101+
102+
LIBBPF_OPTS(bpf_test_run_opts, topts);
103+
104+
skel = setup_skel();
105+
if (!skel)
106+
return;
107+
108+
prog_fd = bpf_program__fd(skel->progs.test_sha512);
109+
err = bpf_prog_test_run_opts(prog_fd, &topts);
110+
ASSERT_OK(err, "test_sha512");
111+
ASSERT_EQ(skel->data->sha512_status, 0, "sha512_status");
112+
ASSERT_EQ(memcmp(skel->bss->sha512_output, expected_sha512, 64), 0,
113+
"sha512_output_match");
114+
115+
crypto_hash__destroy(skel);
116+
}
117+
118+
static void test_sha256_invalid_params(void)
119+
{
120+
struct crypto_hash *skel;
121+
int err, prog_fd;
122+
123+
LIBBPF_OPTS(bpf_test_run_opts, topts);
124+
125+
skel = setup_skel();
126+
if (!skel)
127+
return;
128+
129+
prog_fd = bpf_program__fd(skel->progs.test_sha256_zero_len);
130+
err = bpf_prog_test_run_opts(prog_fd, &topts);
131+
ASSERT_OK(err, "test_zero_len");
132+
ASSERT_EQ(skel->data->sha256_status, 0, "zero_len_rejected");
133+
134+
crypto_hash__destroy(skel);
135+
}
136+
137+
void test_crypto_hash(void)
138+
{
139+
if (test__start_subtest("sha256_basic"))
140+
test_sha256_basic();
141+
if (test__start_subtest("sha384_basic"))
142+
test_sha384_basic();
143+
if (test__start_subtest("sha512_basic"))
144+
test_sha512_basic();
145+
if (test__start_subtest("sha256_invalid_params"))
146+
test_sha256_invalid_params();
147+
}
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (c) 2025 Meta Platforms, Inc. and affiliates. */
3+
4+
#include "vmlinux.h"
5+
#include <bpf/bpf_helpers.h>
6+
#include "bpf_misc.h"
7+
#include "bpf_kfuncs.h"
8+
9+
unsigned char test_input[3] = "abc";
10+
11+
/* Expected SHA-256 hash of "abc" */
12+
/* ba7816bf 8f01cfea 414140de 5dae2223 b00361a3 96177a9c b410ff61 f20015ad */
13+
unsigned char expected_sha256[32] = {
14+
0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
15+
0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
16+
0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
17+
0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad
18+
};
19+
20+
/* Output buffers for test results */
21+
unsigned char sha256_output[32] = {};
22+
unsigned char sha384_output[48] = {};
23+
unsigned char sha512_output[64] = {};
24+
25+
int sha256_status = -1;
26+
int sha384_status = -1;
27+
int sha512_status = -1;
28+
29+
/* Declare the crypto kfuncs */
30+
extern struct bpf_crypto_ctx *bpf_crypto_ctx_create(const struct bpf_crypto_params *params,
31+
u32 params__sz, int *err) __ksym;
32+
extern void bpf_crypto_ctx_release(struct bpf_crypto_ctx *ctx) __ksym;
33+
extern int bpf_crypto_hash(struct bpf_crypto_ctx *ctx, const struct bpf_dynptr *data,
34+
const struct bpf_dynptr *out) __ksym;
35+
36+
SEC("syscall")
37+
int test_sha256(void *ctx)
38+
{
39+
struct bpf_dynptr input_ptr, output_ptr;
40+
struct bpf_crypto_ctx *hash_ctx;
41+
struct bpf_crypto_params params = {
42+
.type = "hash",
43+
.algo = "sha256",
44+
.key_len = 0,
45+
};
46+
int err = 0;
47+
48+
hash_ctx = bpf_crypto_ctx_create(&params, sizeof(params), &err);
49+
if (!hash_ctx) {
50+
sha256_status = err;
51+
return 0;
52+
}
53+
54+
bpf_dynptr_from_mem(test_input, sizeof(test_input), 0, &input_ptr);
55+
bpf_dynptr_from_mem(sha256_output, sizeof(sha256_output), 0, &output_ptr);
56+
57+
sha256_status = bpf_crypto_hash(hash_ctx, &input_ptr, &output_ptr);
58+
bpf_crypto_ctx_release(hash_ctx);
59+
return 0;
60+
}
61+
62+
SEC("syscall")
63+
int test_sha384(void *ctx)
64+
{
65+
struct bpf_dynptr input_ptr, output_ptr;
66+
struct bpf_crypto_ctx *hash_ctx;
67+
struct bpf_crypto_params params = {
68+
.type = "hash",
69+
.algo = "sha384",
70+
.key_len = 0,
71+
};
72+
int err = 0;
73+
74+
hash_ctx = bpf_crypto_ctx_create(&params, sizeof(params), &err);
75+
if (!hash_ctx) {
76+
sha384_status = err;
77+
return 0;
78+
}
79+
80+
bpf_dynptr_from_mem(test_input, sizeof(test_input), 0, &input_ptr);
81+
bpf_dynptr_from_mem(sha384_output, sizeof(sha384_output), 0, &output_ptr);
82+
83+
sha384_status = bpf_crypto_hash(hash_ctx, &input_ptr, &output_ptr);
84+
bpf_crypto_ctx_release(hash_ctx);
85+
return 0;
86+
}
87+
88+
SEC("syscall")
89+
int test_sha512(void *ctx)
90+
{
91+
struct bpf_dynptr input_ptr, output_ptr;
92+
struct bpf_crypto_ctx *hash_ctx;
93+
struct bpf_crypto_params params = {
94+
.type = "hash",
95+
.algo = "sha512",
96+
.key_len = 0,
97+
};
98+
int err = 0;
99+
100+
hash_ctx = bpf_crypto_ctx_create(&params, sizeof(params), &err);
101+
if (!hash_ctx) {
102+
sha512_status = err;
103+
return 0;
104+
}
105+
106+
bpf_dynptr_from_mem(test_input, sizeof(test_input), 0, &input_ptr);
107+
bpf_dynptr_from_mem(sha512_output, sizeof(sha512_output), 0, &output_ptr);
108+
109+
sha512_status = bpf_crypto_hash(hash_ctx, &input_ptr, &output_ptr);
110+
bpf_crypto_ctx_release(hash_ctx);
111+
return 0;
112+
}
113+
114+
SEC("syscall")
115+
int test_sha256_zero_len(void *ctx)
116+
{
117+
struct bpf_dynptr input_ptr, output_ptr;
118+
struct bpf_crypto_ctx *hash_ctx;
119+
struct bpf_crypto_params params = {
120+
.type = "hash",
121+
.algo = "sha256",
122+
.key_len = 0,
123+
};
124+
int err = 0;
125+
int ret;
126+
127+
hash_ctx = bpf_crypto_ctx_create(&params, sizeof(params), &err);
128+
if (!hash_ctx) {
129+
sha256_status = err;
130+
return 0;
131+
}
132+
133+
bpf_dynptr_from_mem(test_input, 0, 0, &input_ptr);
134+
bpf_dynptr_from_mem(sha256_output, sizeof(sha256_output), 0, &output_ptr);
135+
136+
ret = bpf_crypto_hash(hash_ctx, &input_ptr, &output_ptr);
137+
sha256_status = (ret == -22) ? 0 : ret;
138+
bpf_crypto_ctx_release(hash_ctx);
139+
return 0;
140+
}
141+
142+
char __license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)