Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/security/keys/trusted-keys/trusted_pkwm.c
121833 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* Copyright (C) 2025 IBM Corporation, Srish Srinivasan <[email protected]>
4
*/
5
6
#include <keys/trusted_pkwm.h>
7
#include <keys/trusted-type.h>
8
#include <linux/build_bug.h>
9
#include <linux/key-type.h>
10
#include <linux/parser.h>
11
#include <asm/plpks.h>
12
13
enum {
14
Opt_err,
15
Opt_wrap_flags,
16
};
17
18
static const match_table_t key_tokens = {
19
{Opt_wrap_flags, "wrap_flags=%s"},
20
{Opt_err, NULL}
21
};
22
23
static int getoptions(char *datablob, struct trusted_key_options *opt)
24
{
25
substring_t args[MAX_OPT_ARGS];
26
char *p = datablob;
27
int token;
28
int res;
29
u16 wrap_flags;
30
unsigned long token_mask = 0;
31
struct trusted_pkwm_options *pkwm;
32
33
if (!datablob)
34
return 0;
35
36
pkwm = opt->private;
37
38
while ((p = strsep(&datablob, " \t"))) {
39
if (*p == '\0' || *p == ' ' || *p == '\t')
40
continue;
41
42
token = match_token(p, key_tokens, args);
43
if (test_and_set_bit(token, &token_mask))
44
return -EINVAL;
45
46
switch (token) {
47
case Opt_wrap_flags:
48
res = kstrtou16(args[0].from, 16, &wrap_flags);
49
if (res < 0 || wrap_flags > 2)
50
return -EINVAL;
51
pkwm->wrap_flags = wrap_flags;
52
break;
53
default:
54
return -EINVAL;
55
}
56
}
57
return 0;
58
}
59
60
static struct trusted_key_options *trusted_options_alloc(void)
61
{
62
struct trusted_key_options *options;
63
struct trusted_pkwm_options *pkwm;
64
65
options = kzalloc_obj(*options);
66
67
if (options) {
68
pkwm = kzalloc_obj(*pkwm);
69
70
if (!pkwm) {
71
kfree_sensitive(options);
72
options = NULL;
73
} else {
74
options->private = pkwm;
75
}
76
}
77
78
return options;
79
}
80
81
static int trusted_pkwm_seal(struct trusted_key_payload *p, char *datablob)
82
{
83
struct trusted_key_options *options = NULL;
84
struct trusted_pkwm_options *pkwm = NULL;
85
u8 *input_buf, *output_buf;
86
u32 output_len, input_len;
87
int rc;
88
89
options = trusted_options_alloc();
90
91
if (!options)
92
return -ENOMEM;
93
94
rc = getoptions(datablob, options);
95
if (rc < 0)
96
goto out;
97
dump_options(options);
98
99
input_len = p->key_len;
100
input_buf = kmalloc(ALIGN(input_len, 4096), GFP_KERNEL);
101
if (!input_buf) {
102
pr_err("Input buffer allocation failed. Returning -ENOMEM.");
103
rc = -ENOMEM;
104
goto out;
105
}
106
107
memcpy(input_buf, p->key, p->key_len);
108
109
pkwm = options->private;
110
111
rc = plpks_wrap_object(&input_buf, input_len, pkwm->wrap_flags,
112
&output_buf, &output_len);
113
if (!rc) {
114
memcpy(p->blob, output_buf, output_len);
115
p->blob_len = output_len;
116
dump_payload(p);
117
} else {
118
pr_err("Wrapping of payload key failed: %d\n", rc);
119
}
120
121
kfree(input_buf);
122
kfree(output_buf);
123
124
out:
125
kfree_sensitive(options->private);
126
kfree_sensitive(options);
127
return rc;
128
}
129
130
static int trusted_pkwm_unseal(struct trusted_key_payload *p, char *datablob)
131
{
132
u8 *input_buf, *output_buf;
133
u32 input_len, output_len;
134
int rc;
135
136
input_len = p->blob_len;
137
input_buf = kmalloc(ALIGN(input_len, 4096), GFP_KERNEL);
138
if (!input_buf) {
139
pr_err("Input buffer allocation failed. Returning -ENOMEM.");
140
return -ENOMEM;
141
}
142
143
memcpy(input_buf, p->blob, p->blob_len);
144
145
rc = plpks_unwrap_object(&input_buf, input_len, &output_buf,
146
&output_len);
147
if (!rc) {
148
memcpy(p->key, output_buf, output_len);
149
p->key_len = output_len;
150
dump_payload(p);
151
} else {
152
pr_err("Unwrapping of payload failed: %d\n", rc);
153
}
154
155
kfree(input_buf);
156
kfree(output_buf);
157
158
return rc;
159
}
160
161
static int trusted_pkwm_init(void)
162
{
163
int ret;
164
165
if (!plpks_wrapping_is_supported()) {
166
pr_err("H_PKS_WRAP_OBJECT interface not supported\n");
167
return -ENODEV;
168
}
169
170
ret = plpks_gen_wrapping_key();
171
if (ret) {
172
pr_err("Failed to generate default wrapping key\n");
173
return -EINVAL;
174
}
175
176
return register_key_type(&key_type_trusted);
177
}
178
179
static void trusted_pkwm_exit(void)
180
{
181
unregister_key_type(&key_type_trusted);
182
}
183
184
struct trusted_key_ops pkwm_trusted_key_ops = {
185
.migratable = 0, /* non-migratable */
186
.init = trusted_pkwm_init,
187
.seal = trusted_pkwm_seal,
188
.unseal = trusted_pkwm_unseal,
189
.exit = trusted_pkwm_exit,
190
};
191
192