1 | /* SPDX-License-Identifier: GPL-2.0+ */ |
2 | /* |
3 | * Copyright IBM Corp. 2001, 2006 |
4 | * Author(s): Robert Burroughs |
5 | * Eric Rossman (edrossma@us.ibm.com) |
6 | * |
7 | * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) |
8 | * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com> |
9 | */ |
10 | |
11 | #ifndef _ZCRYPT_CCA_KEY_H_ |
12 | #define _ZCRYPT_CCA_KEY_H_ |
13 | |
14 | struct t6_keyblock_hdr { |
15 | unsigned short blen; |
16 | unsigned short ulen; |
17 | unsigned short flags; |
18 | }; |
19 | |
20 | /** |
21 | * mapping for the cca private ME key token. |
22 | * Three parts of interest here: the header, the private section and |
23 | * the public section. |
24 | * |
25 | * mapping for the cca key token header |
26 | */ |
27 | struct cca_token_hdr { |
28 | unsigned char token_identifier; |
29 | unsigned char version; |
30 | unsigned short token_length; |
31 | unsigned char reserved[4]; |
32 | } __packed; |
33 | |
34 | #define CCA_TKN_HDR_ID_EXT 0x1E |
35 | |
36 | #define CCA_PVT_USAGE_ALL 0x80 |
37 | |
38 | /** |
39 | * mapping for the cca public section |
40 | * In a private key, the modulus doesn't appear in the public |
41 | * section. So, an arbitrary public exponent of 0x010001 will be |
42 | * used, for a section length of 0x0F always. |
43 | */ |
44 | struct cca_public_sec { |
45 | unsigned char section_identifier; |
46 | unsigned char version; |
47 | unsigned short section_length; |
48 | unsigned char reserved[2]; |
49 | unsigned short exponent_len; |
50 | unsigned short modulus_bit_len; |
51 | unsigned short modulus_byte_len; /* In a private key, this is 0 */ |
52 | } __packed; |
53 | |
54 | /** |
55 | * mapping for the cca private CRT key 'token' |
56 | * The first three parts (the only parts considered in this release) |
57 | * are: the header, the private section and the public section. |
58 | * The header and public section are the same as for the |
59 | * struct cca_private_ext_ME |
60 | * |
61 | * Following the structure are the quantities p, q, dp, dq, u, pad, |
62 | * and modulus, in that order, where pad_len is the modulo 8 |
63 | * complement of the residue modulo 8 of the sum of |
64 | * (p_len + q_len + dp_len + dq_len + u_len). |
65 | */ |
66 | struct cca_pvt_ext_crt_sec { |
67 | unsigned char section_identifier; |
68 | unsigned char version; |
69 | unsigned short section_length; |
70 | unsigned char private_key_hash[20]; |
71 | unsigned char reserved1[4]; |
72 | unsigned char key_format; |
73 | unsigned char reserved2; |
74 | unsigned char key_name_hash[20]; |
75 | unsigned char key_use_flags[4]; |
76 | unsigned short p_len; |
77 | unsigned short q_len; |
78 | unsigned short dp_len; |
79 | unsigned short dq_len; |
80 | unsigned short u_len; |
81 | unsigned short mod_len; |
82 | unsigned char reserved3[4]; |
83 | unsigned short pad_len; |
84 | unsigned char reserved4[52]; |
85 | unsigned char confounder[8]; |
86 | } __packed; |
87 | |
88 | #define CCA_PVT_EXT_CRT_SEC_ID_PVT 0x08 |
89 | #define CCA_PVT_EXT_CRT_SEC_FMT_CL 0x40 |
90 | |
91 | /** |
92 | * Set up private key fields of a type6 MEX message. |
93 | * |
94 | * @mex: pointer to user input data |
95 | * @p: pointer to memory area for the key |
96 | * |
97 | * Returns the size of the key area or negative errno value. |
98 | */ |
99 | static inline int zcrypt_type6_mex_key_en(struct ica_rsa_modexpo *mex, void *p) |
100 | { |
101 | static struct cca_token_hdr static_pub_hdr = { |
102 | .token_identifier = 0x1E, |
103 | }; |
104 | static struct cca_public_sec static_pub_sec = { |
105 | .section_identifier = 0x04, |
106 | }; |
107 | struct { |
108 | struct t6_keyblock_hdr t6_hdr; |
109 | struct cca_token_hdr pubhdr; |
110 | struct cca_public_sec pubsec; |
111 | char exponent[]; |
112 | } __packed *key = p; |
113 | unsigned char *ptr; |
114 | |
115 | /* |
116 | * The inputdatalength was a selection criteria in the dispatching |
117 | * function zcrypt_rsa_modexpo(). However, do a plausibility check |
118 | * here to make sure the following copy_from_user() can't be utilized |
119 | * to compromise the system. |
120 | */ |
121 | if (WARN_ON_ONCE(mex->inputdatalength > 512)) |
122 | return -EINVAL; |
123 | |
124 | memset(key, 0, sizeof(*key)); |
125 | |
126 | key->pubhdr = static_pub_hdr; |
127 | key->pubsec = static_pub_sec; |
128 | |
129 | /* key parameter block */ |
130 | ptr = key->exponent; |
131 | if (copy_from_user(to: ptr, from: mex->b_key, n: mex->inputdatalength)) |
132 | return -EFAULT; |
133 | ptr += mex->inputdatalength; |
134 | /* modulus */ |
135 | if (copy_from_user(to: ptr, from: mex->n_modulus, n: mex->inputdatalength)) |
136 | return -EFAULT; |
137 | |
138 | key->pubsec.modulus_bit_len = 8 * mex->inputdatalength; |
139 | key->pubsec.modulus_byte_len = mex->inputdatalength; |
140 | key->pubsec.exponent_len = mex->inputdatalength; |
141 | key->pubsec.section_length = sizeof(key->pubsec) + |
142 | 2 * mex->inputdatalength; |
143 | key->pubhdr.token_length = |
144 | key->pubsec.section_length + sizeof(key->pubhdr); |
145 | key->t6_hdr.ulen = key->pubhdr.token_length + 4; |
146 | key->t6_hdr.blen = key->pubhdr.token_length + 6; |
147 | |
148 | return sizeof(*key) + 2 * mex->inputdatalength; |
149 | } |
150 | |
151 | /** |
152 | * Set up private key fields of a type6 CRT message. |
153 | * |
154 | * @mex: pointer to user input data |
155 | * @p: pointer to memory area for the key |
156 | * |
157 | * Returns the size of the key area or -EFAULT |
158 | */ |
159 | static inline int zcrypt_type6_crt_key(struct ica_rsa_modexpo_crt *crt, void *p) |
160 | { |
161 | static struct cca_public_sec static_cca_pub_sec = { |
162 | .section_identifier = 4, |
163 | .section_length = 0x000f, |
164 | .exponent_len = 0x0003, |
165 | }; |
166 | static char pk_exponent[3] = { 0x01, 0x00, 0x01 }; |
167 | struct { |
168 | struct t6_keyblock_hdr t6_hdr; |
169 | struct cca_token_hdr token; |
170 | struct cca_pvt_ext_crt_sec pvt; |
171 | char key_parts[]; |
172 | } __packed *key = p; |
173 | struct cca_public_sec *pub; |
174 | int short_len, long_len, pad_len, key_len, size; |
175 | |
176 | /* |
177 | * The inputdatalength was a selection criteria in the dispatching |
178 | * function zcrypt_rsa_crt(). However, do a plausibility check |
179 | * here to make sure the following copy_from_user() can't be utilized |
180 | * to compromise the system. |
181 | */ |
182 | if (WARN_ON_ONCE(crt->inputdatalength > 512)) |
183 | return -EINVAL; |
184 | |
185 | memset(key, 0, sizeof(*key)); |
186 | |
187 | short_len = (crt->inputdatalength + 1) / 2; |
188 | long_len = short_len + 8; |
189 | pad_len = -(3 * long_len + 2 * short_len) & 7; |
190 | key_len = 3 * long_len + 2 * short_len + pad_len + crt->inputdatalength; |
191 | size = sizeof(*key) + key_len + sizeof(*pub) + 3; |
192 | |
193 | /* parameter block.key block */ |
194 | key->t6_hdr.blen = size; |
195 | key->t6_hdr.ulen = size - 2; |
196 | |
197 | /* key token header */ |
198 | key->token.token_identifier = CCA_TKN_HDR_ID_EXT; |
199 | key->token.token_length = size - 6; |
200 | |
201 | /* private section */ |
202 | key->pvt.section_identifier = CCA_PVT_EXT_CRT_SEC_ID_PVT; |
203 | key->pvt.section_length = sizeof(key->pvt) + key_len; |
204 | key->pvt.key_format = CCA_PVT_EXT_CRT_SEC_FMT_CL; |
205 | key->pvt.key_use_flags[0] = CCA_PVT_USAGE_ALL; |
206 | key->pvt.p_len = key->pvt.dp_len = key->pvt.u_len = long_len; |
207 | key->pvt.q_len = key->pvt.dq_len = short_len; |
208 | key->pvt.mod_len = crt->inputdatalength; |
209 | key->pvt.pad_len = pad_len; |
210 | |
211 | /* key parts */ |
212 | if (copy_from_user(to: key->key_parts, from: crt->np_prime, n: long_len) || |
213 | copy_from_user(to: key->key_parts + long_len, |
214 | from: crt->nq_prime, n: short_len) || |
215 | copy_from_user(to: key->key_parts + long_len + short_len, |
216 | from: crt->bp_key, n: long_len) || |
217 | copy_from_user(to: key->key_parts + 2 * long_len + short_len, |
218 | from: crt->bq_key, n: short_len) || |
219 | copy_from_user(to: key->key_parts + 2 * long_len + 2 * short_len, |
220 | from: crt->u_mult_inv, n: long_len)) |
221 | return -EFAULT; |
222 | memset(key->key_parts + 3 * long_len + 2 * short_len + pad_len, |
223 | 0xff, crt->inputdatalength); |
224 | pub = (struct cca_public_sec *)(key->key_parts + key_len); |
225 | *pub = static_cca_pub_sec; |
226 | pub->modulus_bit_len = 8 * crt->inputdatalength; |
227 | /* |
228 | * In a private key, the modulus doesn't appear in the public |
229 | * section. So, an arbitrary public exponent of 0x010001 will be |
230 | * used. |
231 | */ |
232 | memcpy((char *)(pub + 1), pk_exponent, 3); |
233 | |
234 | return size; |
235 | } |
236 | |
237 | #endif /* _ZCRYPT_CCA_KEY_H_ */ |
238 | |