]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * linux/drivers/s390/crypto/z90hardware.c | |
3 | * | |
88fbf183 | 4 | * z90crypt 1.3.3 |
1da177e4 | 5 | * |
88fbf183 | 6 | * Copyright (C) 2001, 2005 IBM Corporation |
1da177e4 LT |
7 | * Author(s): Robert Burroughs (burrough@us.ibm.com) |
8 | * Eric Rossman (edrossma@us.ibm.com) | |
9 | * | |
10 | * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) | |
11 | * | |
12 | * This program is free software; you can redistribute it and/or modify | |
13 | * it under the terms of the GNU General Public License as published by | |
14 | * the Free Software Foundation; either version 2, or (at your option) | |
15 | * any later version. | |
16 | * | |
17 | * This program is distributed in the hope that it will be useful, | |
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | * GNU General Public License for more details. | |
21 | * | |
22 | * You should have received a copy of the GNU General Public License | |
23 | * along with this program; if not, write to the Free Software | |
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
25 | */ | |
26 | ||
27 | #include <asm/uaccess.h> | |
28 | #include <linux/compiler.h> | |
29 | #include <linux/delay.h> | |
30 | #include <linux/init.h> | |
31 | #include <linux/module.h> | |
32 | #include "z90crypt.h" | |
33 | #include "z90common.h" | |
34 | ||
2dee702f | 35 | #define VERSION_Z90HARDWARE_C "$Revision: 1.34 $" |
1da177e4 LT |
36 | |
37 | char z90hardware_version[] __initdata = | |
38 | "z90hardware.o (" VERSION_Z90HARDWARE_C "/" | |
39 | VERSION_Z90COMMON_H "/" VERSION_Z90CRYPT_H ")"; | |
40 | ||
41 | struct cca_token_hdr { | |
42 | unsigned char token_identifier; | |
43 | unsigned char version; | |
44 | unsigned short token_length; | |
45 | unsigned char reserved[4]; | |
46 | }; | |
47 | ||
48 | #define CCA_TKN_HDR_ID_EXT 0x1E | |
49 | ||
50 | struct cca_private_ext_ME_sec { | |
51 | unsigned char section_identifier; | |
52 | unsigned char version; | |
53 | unsigned short section_length; | |
54 | unsigned char private_key_hash[20]; | |
55 | unsigned char reserved1[4]; | |
56 | unsigned char key_format; | |
57 | unsigned char reserved2; | |
58 | unsigned char key_name_hash[20]; | |
59 | unsigned char key_use_flags[4]; | |
60 | unsigned char reserved3[6]; | |
61 | unsigned char reserved4[24]; | |
62 | unsigned char confounder[24]; | |
63 | unsigned char exponent[128]; | |
64 | unsigned char modulus[128]; | |
65 | }; | |
66 | ||
67 | #define CCA_PVT_USAGE_ALL 0x80 | |
68 | ||
69 | struct cca_public_sec { | |
70 | unsigned char section_identifier; | |
71 | unsigned char version; | |
72 | unsigned short section_length; | |
73 | unsigned char reserved[2]; | |
74 | unsigned short exponent_len; | |
75 | unsigned short modulus_bit_len; | |
76 | unsigned short modulus_byte_len; | |
77 | unsigned char exponent[3]; | |
78 | }; | |
79 | ||
80 | struct cca_private_ext_ME { | |
81 | struct cca_token_hdr pvtMEHdr; | |
82 | struct cca_private_ext_ME_sec pvtMESec; | |
83 | struct cca_public_sec pubMESec; | |
84 | }; | |
85 | ||
86 | struct cca_public_key { | |
87 | struct cca_token_hdr pubHdr; | |
88 | struct cca_public_sec pubSec; | |
89 | }; | |
90 | ||
91 | struct cca_pvt_ext_CRT_sec { | |
92 | unsigned char section_identifier; | |
93 | unsigned char version; | |
94 | unsigned short section_length; | |
95 | unsigned char private_key_hash[20]; | |
96 | unsigned char reserved1[4]; | |
97 | unsigned char key_format; | |
98 | unsigned char reserved2; | |
99 | unsigned char key_name_hash[20]; | |
100 | unsigned char key_use_flags[4]; | |
101 | unsigned short p_len; | |
102 | unsigned short q_len; | |
103 | unsigned short dp_len; | |
104 | unsigned short dq_len; | |
105 | unsigned short u_len; | |
106 | unsigned short mod_len; | |
107 | unsigned char reserved3[4]; | |
108 | unsigned short pad_len; | |
109 | unsigned char reserved4[52]; | |
110 | unsigned char confounder[8]; | |
111 | }; | |
112 | ||
113 | #define CCA_PVT_EXT_CRT_SEC_ID_PVT 0x08 | |
114 | #define CCA_PVT_EXT_CRT_SEC_FMT_CL 0x40 | |
115 | ||
116 | struct cca_private_ext_CRT { | |
117 | struct cca_token_hdr pvtCrtHdr; | |
118 | struct cca_pvt_ext_CRT_sec pvtCrtSec; | |
119 | struct cca_public_sec pubCrtSec; | |
120 | }; | |
121 | ||
122 | struct ap_status_word { | |
123 | unsigned char q_stat_flags; | |
124 | unsigned char response_code; | |
125 | unsigned char reserved[2]; | |
126 | }; | |
127 | ||
128 | #define AP_Q_STATUS_EMPTY 0x80 | |
129 | #define AP_Q_STATUS_REPLIES_WAITING 0x40 | |
130 | #define AP_Q_STATUS_ARRAY_FULL 0x20 | |
131 | ||
132 | #define AP_RESPONSE_NORMAL 0x00 | |
133 | #define AP_RESPONSE_Q_NOT_AVAIL 0x01 | |
134 | #define AP_RESPONSE_RESET_IN_PROGRESS 0x02 | |
135 | #define AP_RESPONSE_DECONFIGURED 0x03 | |
136 | #define AP_RESPONSE_CHECKSTOPPED 0x04 | |
137 | #define AP_RESPONSE_BUSY 0x05 | |
138 | #define AP_RESPONSE_Q_FULL 0x10 | |
139 | #define AP_RESPONSE_NO_PENDING_REPLY 0x10 | |
140 | #define AP_RESPONSE_INDEX_TOO_BIG 0x11 | |
141 | #define AP_RESPONSE_NO_FIRST_PART 0x13 | |
142 | #define AP_RESPONSE_MESSAGE_TOO_BIG 0x15 | |
143 | ||
144 | #define AP_MAX_CDX_BITL 4 | |
145 | #define AP_RQID_RESERVED_BITL 4 | |
146 | #define SKIP_BITL (AP_MAX_CDX_BITL + AP_RQID_RESERVED_BITL) | |
147 | ||
148 | struct type4_hdr { | |
149 | unsigned char reserved1; | |
150 | unsigned char msg_type_code; | |
151 | unsigned short msg_len; | |
152 | unsigned char request_code; | |
153 | unsigned char msg_fmt; | |
154 | unsigned short reserved2; | |
155 | }; | |
156 | ||
157 | #define TYPE4_TYPE_CODE 0x04 | |
158 | #define TYPE4_REQU_CODE 0x40 | |
159 | ||
160 | #define TYPE4_SME_LEN 0x0188 | |
161 | #define TYPE4_LME_LEN 0x0308 | |
162 | #define TYPE4_SCR_LEN 0x01E0 | |
163 | #define TYPE4_LCR_LEN 0x03A0 | |
164 | ||
165 | #define TYPE4_SME_FMT 0x00 | |
166 | #define TYPE4_LME_FMT 0x10 | |
167 | #define TYPE4_SCR_FMT 0x40 | |
168 | #define TYPE4_LCR_FMT 0x50 | |
169 | ||
170 | struct type4_sme { | |
171 | struct type4_hdr header; | |
172 | unsigned char message[128]; | |
173 | unsigned char exponent[128]; | |
174 | unsigned char modulus[128]; | |
175 | }; | |
176 | ||
177 | struct type4_lme { | |
178 | struct type4_hdr header; | |
179 | unsigned char message[256]; | |
180 | unsigned char exponent[256]; | |
181 | unsigned char modulus[256]; | |
182 | }; | |
183 | ||
184 | struct type4_scr { | |
185 | struct type4_hdr header; | |
186 | unsigned char message[128]; | |
187 | unsigned char dp[72]; | |
188 | unsigned char dq[64]; | |
189 | unsigned char p[72]; | |
190 | unsigned char q[64]; | |
191 | unsigned char u[72]; | |
192 | }; | |
193 | ||
194 | struct type4_lcr { | |
195 | struct type4_hdr header; | |
196 | unsigned char message[256]; | |
197 | unsigned char dp[136]; | |
198 | unsigned char dq[128]; | |
199 | unsigned char p[136]; | |
200 | unsigned char q[128]; | |
201 | unsigned char u[136]; | |
202 | }; | |
203 | ||
204 | union type4_msg { | |
205 | struct type4_sme sme; | |
206 | struct type4_lme lme; | |
207 | struct type4_scr scr; | |
208 | struct type4_lcr lcr; | |
209 | }; | |
210 | ||
211 | struct type84_hdr { | |
212 | unsigned char reserved1; | |
213 | unsigned char code; | |
214 | unsigned short len; | |
215 | unsigned char reserved2[4]; | |
216 | }; | |
217 | ||
218 | #define TYPE84_RSP_CODE 0x84 | |
219 | ||
220 | struct type6_hdr { | |
221 | unsigned char reserved1; | |
222 | unsigned char type; | |
223 | unsigned char reserved2[2]; | |
224 | unsigned char right[4]; | |
225 | unsigned char reserved3[2]; | |
226 | unsigned char reserved4[2]; | |
227 | unsigned char apfs[4]; | |
228 | unsigned int offset1; | |
229 | unsigned int offset2; | |
230 | unsigned int offset3; | |
231 | unsigned int offset4; | |
232 | unsigned char agent_id[16]; | |
233 | unsigned char rqid[2]; | |
234 | unsigned char reserved5[2]; | |
235 | unsigned char function_code[2]; | |
236 | unsigned char reserved6[2]; | |
237 | unsigned int ToCardLen1; | |
238 | unsigned int ToCardLen2; | |
239 | unsigned int ToCardLen3; | |
240 | unsigned int ToCardLen4; | |
241 | unsigned int FromCardLen1; | |
242 | unsigned int FromCardLen2; | |
243 | unsigned int FromCardLen3; | |
244 | unsigned int FromCardLen4; | |
245 | }; | |
246 | ||
247 | struct CPRB { | |
248 | unsigned char cprb_len[2]; | |
249 | unsigned char cprb_ver_id; | |
250 | unsigned char pad_000; | |
251 | unsigned char srpi_rtcode[4]; | |
252 | unsigned char srpi_verb; | |
253 | unsigned char flags; | |
254 | unsigned char func_id[2]; | |
255 | unsigned char checkpoint_flag; | |
256 | unsigned char resv2; | |
257 | unsigned char req_parml[2]; | |
258 | unsigned char req_parmp[4]; | |
259 | unsigned char req_datal[4]; | |
260 | unsigned char req_datap[4]; | |
261 | unsigned char rpl_parml[2]; | |
262 | unsigned char pad_001[2]; | |
263 | unsigned char rpl_parmp[4]; | |
264 | unsigned char rpl_datal[4]; | |
265 | unsigned char rpl_datap[4]; | |
266 | unsigned char ccp_rscode[2]; | |
267 | unsigned char ccp_rtcode[2]; | |
268 | unsigned char repd_parml[2]; | |
269 | unsigned char mac_data_len[2]; | |
270 | unsigned char repd_datal[4]; | |
271 | unsigned char req_pc[2]; | |
272 | unsigned char res_origin[8]; | |
273 | unsigned char mac_value[8]; | |
274 | unsigned char logon_id[8]; | |
275 | unsigned char usage_domain[2]; | |
276 | unsigned char resv3[18]; | |
277 | unsigned char svr_namel[2]; | |
278 | unsigned char svr_name[8]; | |
279 | }; | |
280 | ||
281 | struct type6_msg { | |
282 | struct type6_hdr header; | |
283 | struct CPRB CPRB; | |
284 | }; | |
285 | ||
1da177e4 LT |
286 | struct type86_hdr { |
287 | unsigned char reserved1; | |
288 | unsigned char type; | |
289 | unsigned char format; | |
290 | unsigned char reserved2; | |
291 | unsigned char reply_code; | |
292 | unsigned char reserved3[3]; | |
293 | }; | |
294 | ||
295 | #define TYPE86_RSP_CODE 0x86 | |
296 | #define TYPE86_FMT2 0x02 | |
297 | ||
298 | struct type86_fmt2_msg { | |
2dee702f | 299 | struct type86_hdr header; |
1da177e4 LT |
300 | unsigned char reserved[4]; |
301 | unsigned char apfs[4]; | |
302 | unsigned int count1; | |
303 | unsigned int offset1; | |
304 | unsigned int count2; | |
305 | unsigned int offset2; | |
306 | unsigned int count3; | |
307 | unsigned int offset3; | |
308 | unsigned int count4; | |
309 | unsigned int offset4; | |
310 | }; | |
311 | ||
312 | static struct type6_hdr static_type6_hdr = { | |
313 | 0x00, | |
314 | 0x06, | |
315 | {0x00,0x00}, | |
316 | {0x00,0x00,0x00,0x00}, | |
317 | {0x00,0x00}, | |
318 | {0x00,0x00}, | |
319 | {0x00,0x00,0x00,0x00}, | |
320 | 0x00000058, | |
321 | 0x00000000, | |
322 | 0x00000000, | |
323 | 0x00000000, | |
324 | {0x01,0x00,0x43,0x43,0x41,0x2D,0x41,0x50, | |
325 | 0x50,0x4C,0x20,0x20,0x20,0x01,0x01,0x01}, | |
326 | {0x00,0x00}, | |
327 | {0x00,0x00}, | |
328 | {0x50,0x44}, | |
329 | {0x00,0x00}, | |
330 | 0x00000000, | |
331 | 0x00000000, | |
332 | 0x00000000, | |
333 | 0x00000000, | |
334 | 0x00000000, | |
335 | 0x00000000, | |
336 | 0x00000000, | |
337 | 0x00000000 | |
338 | }; | |
339 | ||
340 | static struct type6_hdr static_type6_hdrX = { | |
341 | 0x00, | |
342 | 0x06, | |
343 | {0x00,0x00}, | |
344 | {0x00,0x00,0x00,0x00}, | |
345 | {0x00,0x00}, | |
346 | {0x00,0x00}, | |
347 | {0x00,0x00,0x00,0x00}, | |
348 | 0x00000058, | |
349 | 0x00000000, | |
350 | 0x00000000, | |
351 | 0x00000000, | |
352 | {0x43,0x41,0x00,0x00,0x00,0x00,0x00,0x00, | |
353 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, | |
354 | {0x00,0x00}, | |
355 | {0x00,0x00}, | |
356 | {0x50,0x44}, | |
357 | {0x00,0x00}, | |
358 | 0x00000000, | |
359 | 0x00000000, | |
360 | 0x00000000, | |
361 | 0x00000000, | |
362 | 0x00000000, | |
363 | 0x00000000, | |
364 | 0x00000000, | |
365 | 0x00000000 | |
366 | }; | |
367 | ||
368 | static struct CPRB static_cprb = { | |
369 | {0x70,0x00}, | |
370 | 0x41, | |
371 | 0x00, | |
372 | {0x00,0x00,0x00,0x00}, | |
373 | 0x00, | |
374 | 0x00, | |
375 | {0x54,0x32}, | |
376 | 0x01, | |
377 | 0x00, | |
378 | {0x00,0x00}, | |
379 | {0x00,0x00,0x00,0x00}, | |
380 | {0x00,0x00,0x00,0x00}, | |
381 | {0x00,0x00,0x00,0x00}, | |
382 | {0x00,0x00}, | |
383 | {0x00,0x00}, | |
384 | {0x00,0x00,0x00,0x00}, | |
385 | {0x00,0x00,0x00,0x00}, | |
386 | {0x00,0x00,0x00,0x00}, | |
387 | {0x00,0x00}, | |
388 | {0x00,0x00}, | |
389 | {0x00,0x00}, | |
390 | {0x00,0x00}, | |
391 | {0x00,0x00,0x00,0x00}, | |
392 | {0x00,0x00}, | |
393 | {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, | |
394 | {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, | |
395 | {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, | |
396 | {0x00,0x00}, | |
397 | {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
398 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
399 | 0x00,0x00}, | |
400 | {0x08,0x00}, | |
401 | {0x49,0x43,0x53,0x46,0x20,0x20,0x20,0x20} | |
402 | }; | |
403 | ||
404 | struct function_and_rules_block { | |
405 | unsigned char function_code[2]; | |
406 | unsigned char ulen[2]; | |
407 | unsigned char only_rule[8]; | |
408 | }; | |
409 | ||
410 | static struct function_and_rules_block static_pkd_function_and_rules = { | |
411 | {0x50,0x44}, | |
412 | {0x0A,0x00}, | |
413 | {'P','K','C','S','-','1','.','2'} | |
414 | }; | |
415 | ||
416 | static struct function_and_rules_block static_pke_function_and_rules = { | |
417 | {0x50,0x4B}, | |
418 | {0x0A,0x00}, | |
419 | {'P','K','C','S','-','1','.','2'} | |
420 | }; | |
421 | ||
422 | struct T6_keyBlock_hdr { | |
423 | unsigned char blen[2]; | |
424 | unsigned char ulen[2]; | |
425 | unsigned char flags[2]; | |
426 | }; | |
427 | ||
428 | static struct T6_keyBlock_hdr static_T6_keyBlock_hdr = { | |
429 | {0x89,0x01}, | |
430 | {0x87,0x01}, | |
431 | {0x00} | |
432 | }; | |
433 | ||
434 | static struct CPRBX static_cprbx = { | |
435 | 0x00DC, | |
436 | 0x02, | |
437 | {0x00,0x00,0x00}, | |
438 | {0x54,0x32}, | |
439 | {0x00,0x00,0x00,0x00}, | |
440 | 0x00000000, | |
441 | 0x00000000, | |
442 | 0x00000000, | |
443 | 0x00000000, | |
444 | 0x00000000, | |
445 | 0x00000000, | |
446 | 0x00000000, | |
447 | {0x00,0x00,0x00,0x00}, | |
448 | 0x00000000, | |
449 | {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
450 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, | |
451 | {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
452 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, | |
453 | {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
454 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, | |
455 | {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
456 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, | |
457 | {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
458 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, | |
459 | {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
460 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, | |
461 | 0x0000, | |
462 | 0x0000, | |
463 | 0x00000000, | |
464 | {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, | |
465 | {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, | |
466 | 0x00, | |
467 | 0x00, | |
468 | 0x0000, | |
469 | {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, | |
470 | {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
471 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
472 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} | |
473 | }; | |
474 | ||
475 | static struct function_and_rules_block static_pkd_function_and_rulesX_MCL2 = { | |
476 | {0x50,0x44}, | |
477 | {0x00,0x0A}, | |
478 | {'P','K','C','S','-','1','.','2'} | |
479 | }; | |
480 | ||
481 | static struct function_and_rules_block static_pke_function_and_rulesX_MCL2 = { | |
482 | {0x50,0x4B}, | |
483 | {0x00,0x0A}, | |
484 | {'Z','E','R','O','-','P','A','D'} | |
485 | }; | |
486 | ||
487 | static struct function_and_rules_block static_pkd_function_and_rulesX = { | |
488 | {0x50,0x44}, | |
489 | {0x00,0x0A}, | |
490 | {'Z','E','R','O','-','P','A','D'} | |
491 | }; | |
492 | ||
493 | static struct function_and_rules_block static_pke_function_and_rulesX = { | |
494 | {0x50,0x4B}, | |
495 | {0x00,0x0A}, | |
496 | {'M','R','P',' ',' ',' ',' ',' '} | |
497 | }; | |
498 | ||
2dee702f ER |
499 | static unsigned char static_PKE_function_code[2] = {0x50, 0x4B}; |
500 | ||
1da177e4 LT |
501 | struct T6_keyBlock_hdrX { |
502 | unsigned short blen; | |
503 | unsigned short ulen; | |
504 | unsigned char flags[2]; | |
505 | }; | |
506 | ||
507 | static unsigned char static_pad[256] = { | |
508 | 0x1B,0x7B,0x5D,0xB5,0x75,0x01,0x3D,0xFD,0x8D,0xD1,0xC7,0x03,0x2D,0x09,0x23,0x57, | |
509 | 0x89,0x49,0xB9,0x3F,0xBB,0x99,0x41,0x5B,0x75,0x21,0x7B,0x9D,0x3B,0x6B,0x51,0x39, | |
510 | 0xBB,0x0D,0x35,0xB9,0x89,0x0F,0x93,0xA5,0x0B,0x47,0xF1,0xD3,0xBB,0xCB,0xF1,0x9D, | |
511 | 0x23,0x73,0x71,0xFF,0xF3,0xF5,0x45,0xFB,0x61,0x29,0x23,0xFD,0xF1,0x29,0x3F,0x7F, | |
512 | 0x17,0xB7,0x1B,0xA9,0x19,0xBD,0x57,0xA9,0xD7,0x95,0xA3,0xCB,0xED,0x1D,0xDB,0x45, | |
513 | 0x7D,0x11,0xD1,0x51,0x1B,0xED,0x71,0xE9,0xB1,0xD1,0xAB,0xAB,0x21,0x2B,0x1B,0x9F, | |
514 | 0x3B,0x9F,0xF7,0xF7,0xBD,0x63,0xEB,0xAD,0xDF,0xB3,0x6F,0x5B,0xDB,0x8D,0xA9,0x5D, | |
515 | 0xE3,0x7D,0x77,0x49,0x47,0xF5,0xA7,0xFD,0xAB,0x2F,0x27,0x35,0x77,0xD3,0x49,0xC9, | |
516 | 0x09,0xEB,0xB1,0xF9,0xBF,0x4B,0xCB,0x2B,0xEB,0xEB,0x05,0xFF,0x7D,0xC7,0x91,0x8B, | |
517 | 0x09,0x83,0xB9,0xB9,0x69,0x33,0x39,0x6B,0x79,0x75,0x19,0xBF,0xBB,0x07,0x1D,0xBD, | |
518 | 0x29,0xBF,0x39,0x95,0x93,0x1D,0x35,0xC7,0xC9,0x4D,0xE5,0x97,0x0B,0x43,0x9B,0xF1, | |
519 | 0x16,0x93,0x03,0x1F,0xA5,0xFB,0xDB,0xF3,0x27,0x4F,0x27,0x61,0x05,0x1F,0xB9,0x23, | |
520 | 0x2F,0xC3,0x81,0xA9,0x23,0x71,0x55,0x55,0xEB,0xED,0x41,0xE5,0xF3,0x11,0xF1,0x43, | |
521 | 0x69,0x03,0xBD,0x0B,0x37,0x0F,0x51,0x8F,0x0B,0xB5,0x89,0x5B,0x67,0xA9,0xD9,0x4F, | |
522 | 0x01,0xF9,0x21,0x77,0x37,0x73,0x79,0xC5,0x7F,0x51,0xC1,0xCF,0x97,0xA1,0x75,0xAD, | |
523 | 0x35,0x9D,0xD3,0xD3,0xA7,0x9D,0x5D,0x41,0x6F,0x65,0x1B,0xCF,0xA9,0x87,0x91,0x09 | |
524 | }; | |
525 | ||
526 | static struct cca_private_ext_ME static_pvt_me_key = { | |
527 | { | |
528 | 0x1E, | |
529 | 0x00, | |
530 | 0x0183, | |
531 | {0x00,0x00,0x00,0x00} | |
532 | }, | |
533 | ||
534 | { | |
535 | 0x02, | |
536 | 0x00, | |
537 | 0x016C, | |
538 | {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
539 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
540 | 0x00,0x00,0x00,0x00}, | |
541 | {0x00,0x00,0x00,0x00}, | |
542 | 0x00, | |
543 | 0x00, | |
544 | {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
545 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
546 | 0x00,0x00,0x00,0x00}, | |
547 | {0x80,0x00,0x00,0x00}, | |
548 | {0x00,0x00,0x00,0x00,0x00,0x00}, | |
549 | {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
550 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
551 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, | |
552 | {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
553 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
554 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, | |
555 | {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
556 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
557 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
558 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
559 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
560 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
561 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
562 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
563 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
564 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
565 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
566 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
567 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
568 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
569 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
570 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, | |
571 | {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
572 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
573 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
574 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
575 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
576 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
577 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
578 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
579 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
580 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
581 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
582 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
583 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
584 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
585 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | |
586 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} | |
587 | }, | |
588 | ||
589 | { | |
590 | 0x04, | |
591 | 0x00, | |
592 | 0x000F, | |
593 | {0x00,0x00}, | |
594 | 0x0003, | |
595 | 0x0000, | |
596 | 0x0000, | |
597 | {0x01,0x00,0x01} | |
598 | } | |
599 | }; | |
600 | ||
601 | static struct cca_public_key static_public_key = { | |
602 | { | |
603 | 0x1E, | |
604 | 0x00, | |
605 | 0x0000, | |
606 | {0x00,0x00,0x00,0x00} | |
607 | }, | |
608 | ||
609 | { | |
610 | 0x04, | |
611 | 0x00, | |
612 | 0x0000, | |
613 | {0x00,0x00}, | |
614 | 0x0000, | |
615 | 0x0000, | |
616 | 0x0000, | |
617 | {0x01,0x00,0x01} | |
618 | } | |
619 | }; | |
620 | ||
621 | #define FIXED_TYPE6_ME_LEN 0x0000025F | |
622 | ||
623 | #define FIXED_TYPE6_ME_EN_LEN 0x000000F0 | |
624 | ||
625 | #define FIXED_TYPE6_ME_LENX 0x000002CB | |
626 | ||
627 | #define FIXED_TYPE6_ME_EN_LENX 0x0000015C | |
628 | ||
629 | static struct cca_public_sec static_cca_pub_sec = { | |
630 | 0x04, | |
631 | 0x00, | |
632 | 0x000f, | |
633 | {0x00,0x00}, | |
634 | 0x0003, | |
635 | 0x0000, | |
636 | 0x0000, | |
637 | {0x01,0x00,0x01} | |
638 | }; | |
639 | ||
640 | #define FIXED_TYPE6_CR_LEN 0x00000177 | |
641 | ||
642 | #define FIXED_TYPE6_CR_LENX 0x000001E3 | |
643 | ||
644 | #define MAX_RESPONSE_SIZE 0x00000710 | |
645 | ||
646 | #define MAX_RESPONSEX_SIZE 0x0000077C | |
647 | ||
648 | #define RESPONSE_CPRB_SIZE 0x000006B8 | |
649 | #define RESPONSE_CPRBX_SIZE 0x00000724 | |
650 | ||
88fbf183 ER |
651 | struct type50_hdr { |
652 | u8 reserved1; | |
653 | u8 msg_type_code; | |
654 | u16 msg_len; | |
655 | u8 reserved2; | |
656 | u8 ignored; | |
657 | u16 reserved3; | |
658 | }; | |
659 | ||
660 | #define TYPE50_TYPE_CODE 0x50 | |
661 | ||
662 | #define TYPE50_MEB1_LEN (sizeof(struct type50_meb1_msg)) | |
663 | #define TYPE50_MEB2_LEN (sizeof(struct type50_meb2_msg)) | |
664 | #define TYPE50_CRB1_LEN (sizeof(struct type50_crb1_msg)) | |
665 | #define TYPE50_CRB2_LEN (sizeof(struct type50_crb2_msg)) | |
666 | ||
667 | #define TYPE50_MEB1_FMT 0x0001 | |
668 | #define TYPE50_MEB2_FMT 0x0002 | |
669 | #define TYPE50_CRB1_FMT 0x0011 | |
670 | #define TYPE50_CRB2_FMT 0x0012 | |
671 | ||
672 | struct type50_meb1_msg { | |
673 | struct type50_hdr header; | |
674 | u16 keyblock_type; | |
675 | u8 reserved[6]; | |
676 | u8 exponent[128]; | |
677 | u8 modulus[128]; | |
678 | u8 message[128]; | |
679 | }; | |
680 | ||
681 | struct type50_meb2_msg { | |
682 | struct type50_hdr header; | |
683 | u16 keyblock_type; | |
684 | u8 reserved[6]; | |
685 | u8 exponent[256]; | |
686 | u8 modulus[256]; | |
687 | u8 message[256]; | |
688 | }; | |
689 | ||
690 | struct type50_crb1_msg { | |
691 | struct type50_hdr header; | |
692 | u16 keyblock_type; | |
693 | u8 reserved[6]; | |
694 | u8 p[64]; | |
695 | u8 q[64]; | |
696 | u8 dp[64]; | |
697 | u8 dq[64]; | |
698 | u8 u[64]; | |
699 | u8 message[128]; | |
700 | }; | |
701 | ||
702 | struct type50_crb2_msg { | |
703 | struct type50_hdr header; | |
704 | u16 keyblock_type; | |
705 | u8 reserved[6]; | |
706 | u8 p[128]; | |
707 | u8 q[128]; | |
708 | u8 dp[128]; | |
709 | u8 dq[128]; | |
710 | u8 u[128]; | |
711 | u8 message[256]; | |
712 | }; | |
713 | ||
714 | union type50_msg { | |
715 | struct type50_meb1_msg meb1; | |
716 | struct type50_meb2_msg meb2; | |
717 | struct type50_crb1_msg crb1; | |
718 | struct type50_crb2_msg crb2; | |
719 | }; | |
720 | ||
721 | struct type80_hdr { | |
722 | u8 reserved1; | |
723 | u8 type; | |
724 | u16 len; | |
725 | u8 code; | |
726 | u8 reserved2[3]; | |
727 | u8 reserved3[8]; | |
728 | }; | |
729 | ||
730 | #define TYPE80_RSP_CODE 0x80 | |
731 | ||
2dee702f ER |
732 | struct error_hdr { |
733 | unsigned char reserved1; | |
734 | unsigned char type; | |
735 | unsigned char reserved2[2]; | |
736 | unsigned char reply_code; | |
737 | unsigned char reserved3[3]; | |
738 | }; | |
1da177e4 | 739 | |
2dee702f | 740 | #define TYPE82_RSP_CODE 0x82 |
88fbf183 | 741 | #define TYPE88_RSP_CODE 0x88 |
2dee702f ER |
742 | |
743 | #define REP82_ERROR_MACHINE_FAILURE 0x10 | |
744 | #define REP82_ERROR_PREEMPT_FAILURE 0x12 | |
745 | #define REP82_ERROR_CHECKPT_FAILURE 0x14 | |
746 | #define REP82_ERROR_MESSAGE_TYPE 0x20 | |
747 | #define REP82_ERROR_INVALID_COMM_CD 0x21 | |
748 | #define REP82_ERROR_INVALID_MSG_LEN 0x23 | |
749 | #define REP82_ERROR_RESERVD_FIELD 0x24 | |
750 | #define REP82_ERROR_FORMAT_FIELD 0x29 | |
751 | #define REP82_ERROR_INVALID_COMMAND 0x30 | |
752 | #define REP82_ERROR_MALFORMED_MSG 0x40 | |
753 | #define REP82_ERROR_RESERVED_FIELDO 0x50 | |
754 | #define REP82_ERROR_WORD_ALIGNMENT 0x60 | |
755 | #define REP82_ERROR_MESSAGE_LENGTH 0x80 | |
756 | #define REP82_ERROR_OPERAND_INVALID 0x82 | |
757 | #define REP82_ERROR_OPERAND_SIZE 0x84 | |
758 | #define REP82_ERROR_EVEN_MOD_IN_OPND 0x85 | |
759 | #define REP82_ERROR_RESERVED_FIELD 0x88 | |
760 | #define REP82_ERROR_TRANSPORT_FAIL 0x90 | |
761 | #define REP82_ERROR_PACKET_TRUNCATED 0xA0 | |
762 | #define REP82_ERROR_ZERO_BUFFER_LEN 0xB0 | |
763 | ||
88fbf183 ER |
764 | #define REP88_ERROR_MODULE_FAILURE 0x10 |
765 | #define REP88_ERROR_MODULE_TIMEOUT 0x11 | |
766 | #define REP88_ERROR_MODULE_NOTINIT 0x13 | |
767 | #define REP88_ERROR_MODULE_NOTAVAIL 0x14 | |
768 | #define REP88_ERROR_MODULE_DISABLED 0x15 | |
769 | #define REP88_ERROR_MODULE_IN_DIAGN 0x17 | |
770 | #define REP88_ERROR_FASTPATH_DISABLD 0x19 | |
771 | #define REP88_ERROR_MESSAGE_TYPE 0x20 | |
772 | #define REP88_ERROR_MESSAGE_MALFORMD 0x22 | |
773 | #define REP88_ERROR_MESSAGE_LENGTH 0x23 | |
774 | #define REP88_ERROR_RESERVED_FIELD 0x24 | |
775 | #define REP88_ERROR_KEY_TYPE 0x34 | |
776 | #define REP88_ERROR_INVALID_KEY 0x82 | |
777 | #define REP88_ERROR_OPERAND 0x84 | |
778 | #define REP88_ERROR_OPERAND_EVEN_MOD 0x85 | |
779 | ||
2dee702f | 780 | #define CALLER_HEADER 12 |
1da177e4 LT |
781 | |
782 | static inline int | |
783 | testq(int q_nr, int *q_depth, int *dev_type, struct ap_status_word *stat) | |
784 | { | |
785 | int ccode; | |
786 | ||
787 | asm volatile | |
347a8dc3 | 788 | #ifdef CONFIG_64BIT |
1da177e4 LT |
789 | (" llgfr 0,%4 \n" |
790 | " slgr 1,1 \n" | |
791 | " lgr 2,1 \n" | |
792 | "0: .long 0xb2af0000 \n" | |
793 | "1: ipm %0 \n" | |
794 | " srl %0,28 \n" | |
795 | " iihh %0,0 \n" | |
796 | " iihl %0,0 \n" | |
797 | " lgr %1,1 \n" | |
798 | " lgr %3,2 \n" | |
799 | " srl %3,24 \n" | |
800 | " sll 2,24 \n" | |
801 | " srl 2,24 \n" | |
802 | " lgr %2,2 \n" | |
803 | "2: \n" | |
804 | ".section .fixup,\"ax\" \n" | |
805 | "3: \n" | |
806 | " lhi %0,%h5 \n" | |
807 | " jg 2b \n" | |
808 | ".previous \n" | |
809 | ".section __ex_table,\"a\" \n" | |
810 | " .align 8 \n" | |
811 | " .quad 0b,3b \n" | |
812 | " .quad 1b,3b \n" | |
813 | ".previous" | |
814 | :"=d" (ccode),"=d" (*stat),"=d" (*q_depth), "=d" (*dev_type) | |
815 | :"d" (q_nr), "K" (DEV_TSQ_EXCEPTION) | |
816 | :"cc","0","1","2","memory"); | |
817 | #else | |
818 | (" lr 0,%4 \n" | |
819 | " slr 1,1 \n" | |
820 | " lr 2,1 \n" | |
821 | "0: .long 0xb2af0000 \n" | |
822 | "1: ipm %0 \n" | |
823 | " srl %0,28 \n" | |
824 | " lr %1,1 \n" | |
825 | " lr %3,2 \n" | |
826 | " srl %3,24 \n" | |
827 | " sll 2,24 \n" | |
828 | " srl 2,24 \n" | |
829 | " lr %2,2 \n" | |
830 | "2: \n" | |
831 | ".section .fixup,\"ax\" \n" | |
832 | "3: \n" | |
833 | " lhi %0,%h5 \n" | |
834 | " bras 1,4f \n" | |
835 | " .long 2b \n" | |
836 | "4: \n" | |
837 | " l 1,0(1) \n" | |
838 | " br 1 \n" | |
839 | ".previous \n" | |
840 | ".section __ex_table,\"a\" \n" | |
841 | " .align 4 \n" | |
842 | " .long 0b,3b \n" | |
843 | " .long 1b,3b \n" | |
844 | ".previous" | |
845 | :"=d" (ccode),"=d" (*stat),"=d" (*q_depth), "=d" (*dev_type) | |
846 | :"d" (q_nr), "K" (DEV_TSQ_EXCEPTION) | |
847 | :"cc","0","1","2","memory"); | |
848 | #endif | |
849 | return ccode; | |
850 | } | |
851 | ||
852 | static inline int | |
853 | resetq(int q_nr, struct ap_status_word *stat_p) | |
854 | { | |
855 | int ccode; | |
856 | ||
857 | asm volatile | |
347a8dc3 | 858 | #ifdef CONFIG_64BIT |
1da177e4 LT |
859 | (" llgfr 0,%2 \n" |
860 | " lghi 1,1 \n" | |
861 | " sll 1,24 \n" | |
862 | " or 0,1 \n" | |
863 | " slgr 1,1 \n" | |
864 | " lgr 2,1 \n" | |
865 | "0: .long 0xb2af0000 \n" | |
866 | "1: ipm %0 \n" | |
867 | " srl %0,28 \n" | |
868 | " iihh %0,0 \n" | |
869 | " iihl %0,0 \n" | |
870 | " lgr %1,1 \n" | |
871 | "2: \n" | |
872 | ".section .fixup,\"ax\" \n" | |
873 | "3: \n" | |
874 | " lhi %0,%h3 \n" | |
875 | " jg 2b \n" | |
876 | ".previous \n" | |
877 | ".section __ex_table,\"a\" \n" | |
878 | " .align 8 \n" | |
879 | " .quad 0b,3b \n" | |
880 | " .quad 1b,3b \n" | |
881 | ".previous" | |
882 | :"=d" (ccode),"=d" (*stat_p) | |
883 | :"d" (q_nr), "K" (DEV_RSQ_EXCEPTION) | |
884 | :"cc","0","1","2","memory"); | |
885 | #else | |
886 | (" lr 0,%2 \n" | |
887 | " lhi 1,1 \n" | |
888 | " sll 1,24 \n" | |
889 | " or 0,1 \n" | |
890 | " slr 1,1 \n" | |
891 | " lr 2,1 \n" | |
892 | "0: .long 0xb2af0000 \n" | |
893 | "1: ipm %0 \n" | |
894 | " srl %0,28 \n" | |
895 | " lr %1,1 \n" | |
896 | "2: \n" | |
897 | ".section .fixup,\"ax\" \n" | |
898 | "3: \n" | |
899 | " lhi %0,%h3 \n" | |
900 | " bras 1,4f \n" | |
901 | " .long 2b \n" | |
902 | "4: \n" | |
903 | " l 1,0(1) \n" | |
904 | " br 1 \n" | |
905 | ".previous \n" | |
906 | ".section __ex_table,\"a\" \n" | |
907 | " .align 4 \n" | |
908 | " .long 0b,3b \n" | |
909 | " .long 1b,3b \n" | |
910 | ".previous" | |
911 | :"=d" (ccode),"=d" (*stat_p) | |
912 | :"d" (q_nr), "K" (DEV_RSQ_EXCEPTION) | |
913 | :"cc","0","1","2","memory"); | |
914 | #endif | |
915 | return ccode; | |
916 | } | |
917 | ||
918 | static inline int | |
919 | sen(int msg_len, unsigned char *msg_ext, struct ap_status_word *stat) | |
920 | { | |
921 | int ccode; | |
922 | ||
923 | asm volatile | |
347a8dc3 | 924 | #ifdef CONFIG_64BIT |
1da177e4 LT |
925 | (" lgr 6,%3 \n" |
926 | " llgfr 7,%2 \n" | |
927 | " llgt 0,0(6) \n" | |
928 | " lghi 1,64 \n" | |
929 | " sll 1,24 \n" | |
930 | " or 0,1 \n" | |
931 | " la 6,4(6) \n" | |
932 | " llgt 2,0(6) \n" | |
933 | " llgt 3,4(6) \n" | |
934 | " la 6,8(6) \n" | |
935 | " slr 1,1 \n" | |
936 | "0: .long 0xb2ad0026 \n" | |
937 | "1: brc 2,0b \n" | |
938 | " ipm %0 \n" | |
939 | " srl %0,28 \n" | |
940 | " iihh %0,0 \n" | |
941 | " iihl %0,0 \n" | |
942 | " lgr %1,1 \n" | |
943 | "2: \n" | |
944 | ".section .fixup,\"ax\" \n" | |
945 | "3: \n" | |
946 | " lhi %0,%h4 \n" | |
947 | " jg 2b \n" | |
948 | ".previous \n" | |
949 | ".section __ex_table,\"a\" \n" | |
950 | " .align 8 \n" | |
951 | " .quad 0b,3b \n" | |
952 | " .quad 1b,3b \n" | |
953 | ".previous" | |
954 | :"=d" (ccode),"=d" (*stat) | |
955 | :"d" (msg_len),"a" (msg_ext), "K" (DEV_SEN_EXCEPTION) | |
956 | :"cc","0","1","2","3","6","7","memory"); | |
957 | #else | |
958 | (" lr 6,%3 \n" | |
959 | " lr 7,%2 \n" | |
960 | " l 0,0(6) \n" | |
961 | " lhi 1,64 \n" | |
962 | " sll 1,24 \n" | |
963 | " or 0,1 \n" | |
964 | " la 6,4(6) \n" | |
965 | " l 2,0(6) \n" | |
966 | " l 3,4(6) \n" | |
967 | " la 6,8(6) \n" | |
968 | " slr 1,1 \n" | |
969 | "0: .long 0xb2ad0026 \n" | |
970 | "1: brc 2,0b \n" | |
971 | " ipm %0 \n" | |
972 | " srl %0,28 \n" | |
973 | " lr %1,1 \n" | |
974 | "2: \n" | |
975 | ".section .fixup,\"ax\" \n" | |
976 | "3: \n" | |
977 | " lhi %0,%h4 \n" | |
978 | " bras 1,4f \n" | |
979 | " .long 2b \n" | |
980 | "4: \n" | |
981 | " l 1,0(1) \n" | |
982 | " br 1 \n" | |
983 | ".previous \n" | |
984 | ".section __ex_table,\"a\" \n" | |
985 | " .align 4 \n" | |
986 | " .long 0b,3b \n" | |
987 | " .long 1b,3b \n" | |
988 | ".previous" | |
989 | :"=d" (ccode),"=d" (*stat) | |
990 | :"d" (msg_len),"a" (msg_ext), "K" (DEV_SEN_EXCEPTION) | |
991 | :"cc","0","1","2","3","6","7","memory"); | |
992 | #endif | |
993 | return ccode; | |
994 | } | |
995 | ||
996 | static inline int | |
997 | rec(int q_nr, int buff_l, unsigned char *rsp, unsigned char *id, | |
998 | struct ap_status_word *st) | |
999 | { | |
1000 | int ccode; | |
1001 | ||
1002 | asm volatile | |
347a8dc3 | 1003 | #ifdef CONFIG_64BIT |
1da177e4 LT |
1004 | (" llgfr 0,%2 \n" |
1005 | " lgr 3,%4 \n" | |
1006 | " lgr 6,%3 \n" | |
1007 | " llgfr 7,%5 \n" | |
1008 | " lghi 1,128 \n" | |
1009 | " sll 1,24 \n" | |
1010 | " or 0,1 \n" | |
1011 | " slgr 1,1 \n" | |
1012 | " lgr 2,1 \n" | |
1013 | " lgr 4,1 \n" | |
1014 | " lgr 5,1 \n" | |
1015 | "0: .long 0xb2ae0046 \n" | |
1016 | "1: brc 2,0b \n" | |
1017 | " brc 4,0b \n" | |
1018 | " ipm %0 \n" | |
1019 | " srl %0,28 \n" | |
1020 | " iihh %0,0 \n" | |
1021 | " iihl %0,0 \n" | |
1022 | " lgr %1,1 \n" | |
1023 | " st 4,0(3) \n" | |
1024 | " st 5,4(3) \n" | |
1025 | "2: \n" | |
1026 | ".section .fixup,\"ax\" \n" | |
1027 | "3: \n" | |
1028 | " lhi %0,%h6 \n" | |
1029 | " jg 2b \n" | |
1030 | ".previous \n" | |
1031 | ".section __ex_table,\"a\" \n" | |
1032 | " .align 8 \n" | |
1033 | " .quad 0b,3b \n" | |
1034 | " .quad 1b,3b \n" | |
1035 | ".previous" | |
1036 | :"=d"(ccode),"=d"(*st) | |
1037 | :"d" (q_nr), "d" (rsp), "d" (id), "d" (buff_l), "K" (DEV_REC_EXCEPTION) | |
1038 | :"cc","0","1","2","3","4","5","6","7","memory"); | |
1039 | #else | |
1040 | (" lr 0,%2 \n" | |
1041 | " lr 3,%4 \n" | |
1042 | " lr 6,%3 \n" | |
1043 | " lr 7,%5 \n" | |
1044 | " lhi 1,128 \n" | |
1045 | " sll 1,24 \n" | |
1046 | " or 0,1 \n" | |
1047 | " slr 1,1 \n" | |
1048 | " lr 2,1 \n" | |
1049 | " lr 4,1 \n" | |
1050 | " lr 5,1 \n" | |
1051 | "0: .long 0xb2ae0046 \n" | |
1052 | "1: brc 2,0b \n" | |
1053 | " brc 4,0b \n" | |
1054 | " ipm %0 \n" | |
1055 | " srl %0,28 \n" | |
1056 | " lr %1,1 \n" | |
1057 | " st 4,0(3) \n" | |
1058 | " st 5,4(3) \n" | |
1059 | "2: \n" | |
1060 | ".section .fixup,\"ax\" \n" | |
1061 | "3: \n" | |
1062 | " lhi %0,%h6 \n" | |
1063 | " bras 1,4f \n" | |
1064 | " .long 2b \n" | |
1065 | "4: \n" | |
1066 | " l 1,0(1) \n" | |
1067 | " br 1 \n" | |
1068 | ".previous \n" | |
1069 | ".section __ex_table,\"a\" \n" | |
1070 | " .align 4 \n" | |
1071 | " .long 0b,3b \n" | |
1072 | " .long 1b,3b \n" | |
1073 | ".previous" | |
1074 | :"=d"(ccode),"=d"(*st) | |
1075 | :"d" (q_nr), "d" (rsp), "d" (id), "d" (buff_l), "K" (DEV_REC_EXCEPTION) | |
1076 | :"cc","0","1","2","3","4","5","6","7","memory"); | |
1077 | #endif | |
1078 | return ccode; | |
1079 | } | |
1080 | ||
1081 | static inline void | |
1082 | itoLe2(int *i_p, unsigned char *lechars) | |
1083 | { | |
1084 | *lechars = *((unsigned char *) i_p + sizeof(int) - 1); | |
1085 | *(lechars + 1) = *((unsigned char *) i_p + sizeof(int) - 2); | |
1086 | } | |
1087 | ||
1088 | static inline void | |
1089 | le2toI(unsigned char *lechars, int *i_p) | |
1090 | { | |
1091 | unsigned char *ic_p; | |
1092 | *i_p = 0; | |
1093 | ic_p = (unsigned char *) i_p; | |
1094 | *(ic_p + 2) = *(lechars + 1); | |
1095 | *(ic_p + 3) = *(lechars); | |
1096 | } | |
1097 | ||
1098 | static inline int | |
1099 | is_empty(unsigned char *ptr, int len) | |
1100 | { | |
1101 | return !memcmp(ptr, (unsigned char *) &static_pvt_me_key+60, len); | |
1102 | } | |
1103 | ||
1104 | enum hdstat | |
1105 | query_online(int deviceNr, int cdx, int resetNr, int *q_depth, int *dev_type) | |
1106 | { | |
1107 | int q_nr, i, t_depth, t_dev_type; | |
1108 | enum devstat ccode; | |
1109 | struct ap_status_word stat_word; | |
1110 | enum hdstat stat; | |
1111 | int break_out; | |
1112 | ||
1113 | q_nr = (deviceNr << SKIP_BITL) + cdx; | |
1114 | stat = HD_BUSY; | |
1115 | ccode = testq(q_nr, &t_depth, &t_dev_type, &stat_word); | |
1116 | PDEBUG("ccode %d response_code %02X\n", ccode, stat_word.response_code); | |
1117 | break_out = 0; | |
1118 | for (i = 0; i < resetNr; i++) { | |
1119 | if (ccode > 3) { | |
1120 | PRINTKC("Exception testing device %d\n", i); | |
1121 | return HD_TSQ_EXCEPTION; | |
1122 | } | |
1123 | switch (ccode) { | |
1124 | case 0: | |
1125 | PDEBUG("t_dev_type %d\n", t_dev_type); | |
1126 | break_out = 1; | |
1127 | stat = HD_ONLINE; | |
1128 | *q_depth = t_depth + 1; | |
1129 | switch (t_dev_type) { | |
1da177e4 LT |
1130 | case PCICA_HW: |
1131 | *dev_type = PCICA; | |
1132 | break; | |
1133 | case PCICC_HW: | |
1134 | *dev_type = PCICC; | |
1135 | break; | |
1136 | case PCIXCC_HW: | |
1137 | *dev_type = PCIXCC_UNK; | |
1138 | break; | |
1139 | case CEX2C_HW: | |
1140 | *dev_type = CEX2C; | |
1141 | break; | |
88fbf183 ER |
1142 | case CEX2A_HW: |
1143 | *dev_type = CEX2A; | |
1144 | break; | |
1da177e4 LT |
1145 | default: |
1146 | *dev_type = NILDEV; | |
1147 | break; | |
1148 | } | |
1149 | PDEBUG("available device %d: Q depth = %d, dev " | |
1150 | "type = %d, stat = %02X%02X%02X%02X\n", | |
1151 | deviceNr, *q_depth, *dev_type, | |
1152 | stat_word.q_stat_flags, | |
1153 | stat_word.response_code, | |
1154 | stat_word.reserved[0], | |
1155 | stat_word.reserved[1]); | |
1156 | break; | |
1157 | case 3: | |
1158 | switch (stat_word.response_code) { | |
1159 | case AP_RESPONSE_NORMAL: | |
1160 | stat = HD_ONLINE; | |
1161 | break_out = 1; | |
1162 | *q_depth = t_depth + 1; | |
1163 | *dev_type = t_dev_type; | |
1164 | PDEBUG("cc3, available device " | |
1165 | "%d: Q depth = %d, dev " | |
1166 | "type = %d, stat = " | |
1167 | "%02X%02X%02X%02X\n", | |
1168 | deviceNr, *q_depth, | |
1169 | *dev_type, | |
1170 | stat_word.q_stat_flags, | |
1171 | stat_word.response_code, | |
1172 | stat_word.reserved[0], | |
1173 | stat_word.reserved[1]); | |
1174 | break; | |
1175 | case AP_RESPONSE_Q_NOT_AVAIL: | |
1176 | stat = HD_NOT_THERE; | |
1177 | break_out = 1; | |
1178 | break; | |
1179 | case AP_RESPONSE_RESET_IN_PROGRESS: | |
1180 | PDEBUG("device %d in reset\n", | |
1181 | deviceNr); | |
1182 | break; | |
1183 | case AP_RESPONSE_DECONFIGURED: | |
1184 | stat = HD_DECONFIGURED; | |
1185 | break_out = 1; | |
1186 | break; | |
1187 | case AP_RESPONSE_CHECKSTOPPED: | |
1188 | stat = HD_CHECKSTOPPED; | |
1189 | break_out = 1; | |
1190 | break; | |
1191 | case AP_RESPONSE_BUSY: | |
1192 | PDEBUG("device %d busy\n", | |
1193 | deviceNr); | |
1194 | break; | |
1195 | default: | |
1196 | break; | |
1197 | } | |
1198 | break; | |
1199 | default: | |
1200 | stat = HD_NOT_THERE; | |
1201 | break_out = 1; | |
1202 | break; | |
1203 | } | |
1204 | if (break_out) | |
1205 | break; | |
1206 | ||
1207 | udelay(5); | |
1208 | ||
1209 | ccode = testq(q_nr, &t_depth, &t_dev_type, &stat_word); | |
1210 | } | |
1211 | return stat; | |
1212 | } | |
1213 | ||
1214 | enum devstat | |
1215 | reset_device(int deviceNr, int cdx, int resetNr) | |
1216 | { | |
1217 | int q_nr, ccode = 0, dummy_qdepth, dummy_devType, i; | |
1218 | struct ap_status_word stat_word; | |
1219 | enum devstat stat; | |
1220 | int break_out; | |
1221 | ||
1222 | q_nr = (deviceNr << SKIP_BITL) + cdx; | |
1223 | stat = DEV_GONE; | |
1224 | ccode = resetq(q_nr, &stat_word); | |
1225 | if (ccode > 3) | |
1226 | return DEV_RSQ_EXCEPTION; | |
1227 | ||
1228 | break_out = 0; | |
1229 | for (i = 0; i < resetNr; i++) { | |
1230 | switch (ccode) { | |
1231 | case 0: | |
1232 | stat = DEV_ONLINE; | |
1233 | if (stat_word.q_stat_flags & AP_Q_STATUS_EMPTY) | |
1234 | break_out = 1; | |
1235 | break; | |
1236 | case 3: | |
1237 | switch (stat_word.response_code) { | |
1238 | case AP_RESPONSE_NORMAL: | |
1239 | stat = DEV_ONLINE; | |
1240 | if (stat_word.q_stat_flags & AP_Q_STATUS_EMPTY) | |
1241 | break_out = 1; | |
1242 | break; | |
1243 | case AP_RESPONSE_Q_NOT_AVAIL: | |
1244 | case AP_RESPONSE_DECONFIGURED: | |
1245 | case AP_RESPONSE_CHECKSTOPPED: | |
1246 | stat = DEV_GONE; | |
1247 | break_out = 1; | |
1248 | break; | |
1249 | case AP_RESPONSE_RESET_IN_PROGRESS: | |
1250 | case AP_RESPONSE_BUSY: | |
1251 | default: | |
1252 | break; | |
1253 | } | |
1254 | break; | |
1255 | default: | |
1256 | stat = DEV_GONE; | |
1257 | break_out = 1; | |
1258 | break; | |
1259 | } | |
1260 | if (break_out == 1) | |
1261 | break; | |
1262 | udelay(5); | |
1263 | ||
1264 | ccode = testq(q_nr, &dummy_qdepth, &dummy_devType, &stat_word); | |
1265 | if (ccode > 3) { | |
1266 | stat = DEV_TSQ_EXCEPTION; | |
1267 | break; | |
1268 | } | |
1269 | } | |
1270 | PDEBUG("Number of testq's needed for reset: %d\n", i); | |
1271 | ||
1272 | if (i >= resetNr) { | |
1273 | stat = DEV_GONE; | |
1274 | } | |
1275 | ||
1276 | return stat; | |
1277 | } | |
1278 | ||
1279 | #ifdef DEBUG_HYDRA_MSGS | |
1280 | static inline void | |
1281 | print_buffer(unsigned char *buffer, int bufflen) | |
1282 | { | |
1283 | int i; | |
1284 | for (i = 0; i < bufflen; i += 16) { | |
1285 | PRINTK("%04X: %02X%02X%02X%02X %02X%02X%02X%02X " | |
1286 | "%02X%02X%02X%02X %02X%02X%02X%02X\n", i, | |
1287 | buffer[i+0], buffer[i+1], buffer[i+2], buffer[i+3], | |
1288 | buffer[i+4], buffer[i+5], buffer[i+6], buffer[i+7], | |
1289 | buffer[i+8], buffer[i+9], buffer[i+10], buffer[i+11], | |
1290 | buffer[i+12], buffer[i+13], buffer[i+14], buffer[i+15]); | |
1291 | } | |
1292 | } | |
1293 | #endif | |
1294 | ||
1295 | enum devstat | |
1296 | send_to_AP(int dev_nr, int cdx, int msg_len, unsigned char *msg_ext) | |
1297 | { | |
1298 | struct ap_status_word stat_word; | |
1299 | enum devstat stat; | |
1300 | int ccode; | |
2dee702f | 1301 | u32 *q_nr_p = (u32 *)msg_ext; |
1da177e4 | 1302 | |
2dee702f | 1303 | *q_nr_p = (dev_nr << SKIP_BITL) + cdx; |
1da177e4 LT |
1304 | PDEBUG("msg_len passed to sen: %d\n", msg_len); |
1305 | PDEBUG("q number passed to sen: %02x%02x%02x%02x\n", | |
1306 | msg_ext[0], msg_ext[1], msg_ext[2], msg_ext[3]); | |
1307 | stat = DEV_GONE; | |
1308 | ||
1309 | #ifdef DEBUG_HYDRA_MSGS | |
1310 | PRINTK("Request header: %02X%02X%02X%02X %02X%02X%02X%02X " | |
1311 | "%02X%02X%02X%02X\n", | |
1312 | msg_ext[0], msg_ext[1], msg_ext[2], msg_ext[3], | |
1313 | msg_ext[4], msg_ext[5], msg_ext[6], msg_ext[7], | |
1314 | msg_ext[8], msg_ext[9], msg_ext[10], msg_ext[11]); | |
1315 | print_buffer(msg_ext+CALLER_HEADER, msg_len); | |
1316 | #endif | |
1317 | ||
1318 | ccode = sen(msg_len, msg_ext, &stat_word); | |
1319 | if (ccode > 3) | |
1320 | return DEV_SEN_EXCEPTION; | |
1321 | ||
1322 | PDEBUG("nq cc: %u, st: %02x%02x%02x%02x\n", | |
1323 | ccode, stat_word.q_stat_flags, stat_word.response_code, | |
1324 | stat_word.reserved[0], stat_word.reserved[1]); | |
1325 | switch (ccode) { | |
1326 | case 0: | |
1327 | stat = DEV_ONLINE; | |
1328 | break; | |
1329 | case 1: | |
1330 | stat = DEV_GONE; | |
1331 | break; | |
1332 | case 3: | |
1333 | switch (stat_word.response_code) { | |
1334 | case AP_RESPONSE_NORMAL: | |
1335 | stat = DEV_ONLINE; | |
1336 | break; | |
1337 | case AP_RESPONSE_Q_FULL: | |
1338 | stat = DEV_QUEUE_FULL; | |
1339 | break; | |
1340 | default: | |
1341 | stat = DEV_GONE; | |
1342 | break; | |
1343 | } | |
1344 | break; | |
1345 | default: | |
1346 | stat = DEV_GONE; | |
1347 | break; | |
1348 | } | |
1349 | ||
1350 | return stat; | |
1351 | } | |
1352 | ||
1353 | enum devstat | |
1354 | receive_from_AP(int dev_nr, int cdx, int resplen, unsigned char *resp, | |
1355 | unsigned char *psmid) | |
1356 | { | |
1357 | int ccode; | |
1358 | struct ap_status_word stat_word; | |
1359 | enum devstat stat; | |
1360 | ||
1361 | memset(resp, 0x00, 8); | |
1362 | ||
1363 | ccode = rec((dev_nr << SKIP_BITL) + cdx, resplen, resp, psmid, | |
1364 | &stat_word); | |
1365 | if (ccode > 3) | |
1366 | return DEV_REC_EXCEPTION; | |
1367 | ||
1368 | PDEBUG("dq cc: %u, st: %02x%02x%02x%02x\n", | |
1369 | ccode, stat_word.q_stat_flags, stat_word.response_code, | |
1370 | stat_word.reserved[0], stat_word.reserved[1]); | |
1371 | ||
1372 | stat = DEV_GONE; | |
1373 | switch (ccode) { | |
1374 | case 0: | |
1375 | stat = DEV_ONLINE; | |
1376 | #ifdef DEBUG_HYDRA_MSGS | |
1377 | print_buffer(resp, resplen); | |
1378 | #endif | |
1379 | break; | |
1380 | case 3: | |
1381 | switch (stat_word.response_code) { | |
1382 | case AP_RESPONSE_NORMAL: | |
1383 | stat = DEV_ONLINE; | |
1384 | break; | |
1385 | case AP_RESPONSE_NO_PENDING_REPLY: | |
1386 | if (stat_word.q_stat_flags & AP_Q_STATUS_EMPTY) | |
1387 | stat = DEV_EMPTY; | |
1388 | else | |
1389 | stat = DEV_NO_WORK; | |
1390 | break; | |
1391 | case AP_RESPONSE_INDEX_TOO_BIG: | |
1392 | case AP_RESPONSE_NO_FIRST_PART: | |
1393 | case AP_RESPONSE_MESSAGE_TOO_BIG: | |
1394 | stat = DEV_BAD_MESSAGE; | |
1395 | break; | |
1396 | default: | |
1397 | break; | |
1398 | } | |
1399 | break; | |
1400 | default: | |
1401 | break; | |
1402 | } | |
1403 | ||
1404 | return stat; | |
1405 | } | |
1406 | ||
1407 | static inline int | |
1408 | pad_msg(unsigned char *buffer, int totalLength, int msgLength) | |
1409 | { | |
1410 | int pad_len; | |
1411 | ||
1412 | for (pad_len = 0; pad_len < (totalLength - msgLength); pad_len++) | |
1413 | if (buffer[pad_len] != 0x00) | |
1414 | break; | |
1415 | pad_len -= 3; | |
1416 | if (pad_len < 8) | |
1417 | return SEN_PAD_ERROR; | |
1418 | ||
1419 | buffer[0] = 0x00; | |
1420 | buffer[1] = 0x02; | |
1421 | ||
1422 | memcpy(buffer+2, static_pad, pad_len); | |
1423 | ||
1424 | buffer[pad_len + 2] = 0x00; | |
1425 | ||
1426 | return 0; | |
1427 | } | |
1428 | ||
1429 | static inline int | |
1430 | is_common_public_key(unsigned char *key, int len) | |
1431 | { | |
1432 | int i; | |
1433 | ||
1434 | for (i = 0; i < len; i++) | |
1435 | if (key[i]) | |
1436 | break; | |
1437 | key += i; | |
1438 | len -= i; | |
1439 | if (((len == 1) && (key[0] == 3)) || | |
1440 | ((len == 3) && (key[0] == 1) && (key[1] == 0) && (key[2] == 1))) | |
1441 | return 1; | |
1442 | ||
1443 | return 0; | |
1444 | } | |
1445 | ||
1446 | static int | |
1447 | ICAMEX_msg_to_type4MEX_msg(struct ica_rsa_modexpo *icaMex_p, int *z90cMsg_l_p, | |
1448 | union type4_msg *z90cMsg_p) | |
1449 | { | |
1450 | int mod_len, msg_size, mod_tgt_len, exp_tgt_len, inp_tgt_len; | |
1451 | unsigned char *mod_tgt, *exp_tgt, *inp_tgt; | |
1452 | union type4_msg *tmp_type4_msg; | |
1453 | ||
1454 | mod_len = icaMex_p->inputdatalength; | |
1455 | ||
1456 | msg_size = ((mod_len <= 128) ? TYPE4_SME_LEN : TYPE4_LME_LEN) + | |
1457 | CALLER_HEADER; | |
1458 | ||
1459 | memset(z90cMsg_p, 0, msg_size); | |
1460 | ||
1461 | tmp_type4_msg = (union type4_msg *) | |
1462 | ((unsigned char *) z90cMsg_p + CALLER_HEADER); | |
1463 | ||
1464 | tmp_type4_msg->sme.header.msg_type_code = TYPE4_TYPE_CODE; | |
1465 | tmp_type4_msg->sme.header.request_code = TYPE4_REQU_CODE; | |
1466 | ||
1467 | if (mod_len <= 128) { | |
1468 | tmp_type4_msg->sme.header.msg_fmt = TYPE4_SME_FMT; | |
1469 | tmp_type4_msg->sme.header.msg_len = TYPE4_SME_LEN; | |
1470 | mod_tgt = tmp_type4_msg->sme.modulus; | |
1471 | mod_tgt_len = sizeof(tmp_type4_msg->sme.modulus); | |
1472 | exp_tgt = tmp_type4_msg->sme.exponent; | |
1473 | exp_tgt_len = sizeof(tmp_type4_msg->sme.exponent); | |
1474 | inp_tgt = tmp_type4_msg->sme.message; | |
1475 | inp_tgt_len = sizeof(tmp_type4_msg->sme.message); | |
1476 | } else { | |
1477 | tmp_type4_msg->lme.header.msg_fmt = TYPE4_LME_FMT; | |
1478 | tmp_type4_msg->lme.header.msg_len = TYPE4_LME_LEN; | |
1479 | mod_tgt = tmp_type4_msg->lme.modulus; | |
1480 | mod_tgt_len = sizeof(tmp_type4_msg->lme.modulus); | |
1481 | exp_tgt = tmp_type4_msg->lme.exponent; | |
1482 | exp_tgt_len = sizeof(tmp_type4_msg->lme.exponent); | |
1483 | inp_tgt = tmp_type4_msg->lme.message; | |
1484 | inp_tgt_len = sizeof(tmp_type4_msg->lme.message); | |
1485 | } | |
1486 | ||
1487 | mod_tgt += (mod_tgt_len - mod_len); | |
1488 | if (copy_from_user(mod_tgt, icaMex_p->n_modulus, mod_len)) | |
1489 | return SEN_RELEASED; | |
1490 | if (is_empty(mod_tgt, mod_len)) | |
1491 | return SEN_USER_ERROR; | |
1492 | exp_tgt += (exp_tgt_len - mod_len); | |
1493 | if (copy_from_user(exp_tgt, icaMex_p->b_key, mod_len)) | |
1494 | return SEN_RELEASED; | |
1495 | if (is_empty(exp_tgt, mod_len)) | |
1496 | return SEN_USER_ERROR; | |
1497 | inp_tgt += (inp_tgt_len - mod_len); | |
1498 | if (copy_from_user(inp_tgt, icaMex_p->inputdata, mod_len)) | |
1499 | return SEN_RELEASED; | |
1500 | if (is_empty(inp_tgt, mod_len)) | |
1501 | return SEN_USER_ERROR; | |
1502 | ||
1503 | *z90cMsg_l_p = msg_size - CALLER_HEADER; | |
1504 | ||
1505 | return 0; | |
1506 | } | |
1507 | ||
1508 | static int | |
1509 | ICACRT_msg_to_type4CRT_msg(struct ica_rsa_modexpo_crt *icaMsg_p, | |
1510 | int *z90cMsg_l_p, union type4_msg *z90cMsg_p) | |
1511 | { | |
1512 | int mod_len, short_len, long_len, tmp_size, p_tgt_len, q_tgt_len, | |
1513 | dp_tgt_len, dq_tgt_len, u_tgt_len, inp_tgt_len; | |
1514 | unsigned char *p_tgt, *q_tgt, *dp_tgt, *dq_tgt, *u_tgt, *inp_tgt; | |
1515 | union type4_msg *tmp_type4_msg; | |
1516 | ||
1517 | mod_len = icaMsg_p->inputdatalength; | |
1518 | short_len = mod_len / 2; | |
1519 | long_len = mod_len / 2 + 8; | |
1520 | ||
1521 | tmp_size = ((mod_len <= 128) ? TYPE4_SCR_LEN : TYPE4_LCR_LEN) + | |
1522 | CALLER_HEADER; | |
1523 | ||
1524 | memset(z90cMsg_p, 0, tmp_size); | |
1525 | ||
1526 | tmp_type4_msg = (union type4_msg *) | |
1527 | ((unsigned char *) z90cMsg_p + CALLER_HEADER); | |
1528 | ||
1529 | tmp_type4_msg->scr.header.msg_type_code = TYPE4_TYPE_CODE; | |
1530 | tmp_type4_msg->scr.header.request_code = TYPE4_REQU_CODE; | |
1531 | if (mod_len <= 128) { | |
1532 | tmp_type4_msg->scr.header.msg_fmt = TYPE4_SCR_FMT; | |
1533 | tmp_type4_msg->scr.header.msg_len = TYPE4_SCR_LEN; | |
1534 | p_tgt = tmp_type4_msg->scr.p; | |
1535 | p_tgt_len = sizeof(tmp_type4_msg->scr.p); | |
1536 | q_tgt = tmp_type4_msg->scr.q; | |
1537 | q_tgt_len = sizeof(tmp_type4_msg->scr.q); | |
1538 | dp_tgt = tmp_type4_msg->scr.dp; | |
1539 | dp_tgt_len = sizeof(tmp_type4_msg->scr.dp); | |
1540 | dq_tgt = tmp_type4_msg->scr.dq; | |
1541 | dq_tgt_len = sizeof(tmp_type4_msg->scr.dq); | |
1542 | u_tgt = tmp_type4_msg->scr.u; | |
1543 | u_tgt_len = sizeof(tmp_type4_msg->scr.u); | |
1544 | inp_tgt = tmp_type4_msg->scr.message; | |
1545 | inp_tgt_len = sizeof(tmp_type4_msg->scr.message); | |
1546 | } else { | |
1547 | tmp_type4_msg->lcr.header.msg_fmt = TYPE4_LCR_FMT; | |
1548 | tmp_type4_msg->lcr.header.msg_len = TYPE4_LCR_LEN; | |
1549 | p_tgt = tmp_type4_msg->lcr.p; | |
1550 | p_tgt_len = sizeof(tmp_type4_msg->lcr.p); | |
1551 | q_tgt = tmp_type4_msg->lcr.q; | |
1552 | q_tgt_len = sizeof(tmp_type4_msg->lcr.q); | |
1553 | dp_tgt = tmp_type4_msg->lcr.dp; | |
1554 | dp_tgt_len = sizeof(tmp_type4_msg->lcr.dp); | |
1555 | dq_tgt = tmp_type4_msg->lcr.dq; | |
1556 | dq_tgt_len = sizeof(tmp_type4_msg->lcr.dq); | |
1557 | u_tgt = tmp_type4_msg->lcr.u; | |
1558 | u_tgt_len = sizeof(tmp_type4_msg->lcr.u); | |
1559 | inp_tgt = tmp_type4_msg->lcr.message; | |
1560 | inp_tgt_len = sizeof(tmp_type4_msg->lcr.message); | |
1561 | } | |
1562 | ||
1563 | p_tgt += (p_tgt_len - long_len); | |
1564 | if (copy_from_user(p_tgt, icaMsg_p->np_prime, long_len)) | |
1565 | return SEN_RELEASED; | |
1566 | if (is_empty(p_tgt, long_len)) | |
1567 | return SEN_USER_ERROR; | |
1568 | q_tgt += (q_tgt_len - short_len); | |
1569 | if (copy_from_user(q_tgt, icaMsg_p->nq_prime, short_len)) | |
1570 | return SEN_RELEASED; | |
1571 | if (is_empty(q_tgt, short_len)) | |
1572 | return SEN_USER_ERROR; | |
1573 | dp_tgt += (dp_tgt_len - long_len); | |
1574 | if (copy_from_user(dp_tgt, icaMsg_p->bp_key, long_len)) | |
1575 | return SEN_RELEASED; | |
1576 | if (is_empty(dp_tgt, long_len)) | |
1577 | return SEN_USER_ERROR; | |
1578 | dq_tgt += (dq_tgt_len - short_len); | |
1579 | if (copy_from_user(dq_tgt, icaMsg_p->bq_key, short_len)) | |
1580 | return SEN_RELEASED; | |
1581 | if (is_empty(dq_tgt, short_len)) | |
1582 | return SEN_USER_ERROR; | |
1583 | u_tgt += (u_tgt_len - long_len); | |
1584 | if (copy_from_user(u_tgt, icaMsg_p->u_mult_inv, long_len)) | |
1585 | return SEN_RELEASED; | |
1586 | if (is_empty(u_tgt, long_len)) | |
1587 | return SEN_USER_ERROR; | |
1588 | inp_tgt += (inp_tgt_len - mod_len); | |
1589 | if (copy_from_user(inp_tgt, icaMsg_p->inputdata, mod_len)) | |
1590 | return SEN_RELEASED; | |
1591 | if (is_empty(inp_tgt, mod_len)) | |
1592 | return SEN_USER_ERROR; | |
1593 | ||
1594 | *z90cMsg_l_p = tmp_size - CALLER_HEADER; | |
1595 | ||
1596 | return 0; | |
1597 | } | |
1598 | ||
1599 | static int | |
1600 | ICAMEX_msg_to_type6MEX_de_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx, | |
1601 | int *z90cMsg_l_p, struct type6_msg *z90cMsg_p) | |
1602 | { | |
1603 | int mod_len, vud_len, tmp_size, total_CPRB_len, parmBlock_l; | |
1604 | unsigned char *temp; | |
1605 | struct type6_hdr *tp6Hdr_p; | |
1606 | struct CPRB *cprb_p; | |
1607 | struct cca_private_ext_ME *key_p; | |
1608 | static int deprecated_msg_count = 0; | |
1609 | ||
1610 | mod_len = icaMsg_p->inputdatalength; | |
1611 | tmp_size = FIXED_TYPE6_ME_LEN + mod_len; | |
1612 | total_CPRB_len = tmp_size - sizeof(struct type6_hdr); | |
1613 | parmBlock_l = total_CPRB_len - sizeof(struct CPRB); | |
1614 | tmp_size = 4*((tmp_size + 3)/4) + CALLER_HEADER; | |
1615 | ||
1616 | memset(z90cMsg_p, 0, tmp_size); | |
1617 | ||
1618 | temp = (unsigned char *)z90cMsg_p + CALLER_HEADER; | |
1619 | memcpy(temp, &static_type6_hdr, sizeof(struct type6_hdr)); | |
1620 | tp6Hdr_p = (struct type6_hdr *)temp; | |
1621 | tp6Hdr_p->ToCardLen1 = 4*((total_CPRB_len+3)/4); | |
1622 | tp6Hdr_p->FromCardLen1 = RESPONSE_CPRB_SIZE; | |
1623 | ||
1624 | temp += sizeof(struct type6_hdr); | |
1625 | memcpy(temp, &static_cprb, sizeof(struct CPRB)); | |
1626 | cprb_p = (struct CPRB *) temp; | |
1627 | cprb_p->usage_domain[0]= (unsigned char)cdx; | |
1628 | itoLe2(&parmBlock_l, cprb_p->req_parml); | |
1629 | itoLe2((int *)&(tp6Hdr_p->FromCardLen1), cprb_p->rpl_parml); | |
1630 | ||
1631 | temp += sizeof(struct CPRB); | |
1632 | memcpy(temp, &static_pkd_function_and_rules, | |
1633 | sizeof(struct function_and_rules_block)); | |
1634 | ||
1635 | temp += sizeof(struct function_and_rules_block); | |
1636 | vud_len = 2 + icaMsg_p->inputdatalength; | |
1637 | itoLe2(&vud_len, temp); | |
1638 | ||
1639 | temp += 2; | |
1640 | if (copy_from_user(temp, icaMsg_p->inputdata, mod_len)) | |
1641 | return SEN_RELEASED; | |
1642 | if (is_empty(temp, mod_len)) | |
1643 | return SEN_USER_ERROR; | |
1644 | ||
1645 | temp += mod_len; | |
1646 | memcpy(temp, &static_T6_keyBlock_hdr, sizeof(struct T6_keyBlock_hdr)); | |
1647 | ||
1648 | temp += sizeof(struct T6_keyBlock_hdr); | |
1649 | memcpy(temp, &static_pvt_me_key, sizeof(struct cca_private_ext_ME)); | |
1650 | key_p = (struct cca_private_ext_ME *)temp; | |
1651 | temp = key_p->pvtMESec.exponent + sizeof(key_p->pvtMESec.exponent) | |
1652 | - mod_len; | |
1653 | if (copy_from_user(temp, icaMsg_p->b_key, mod_len)) | |
1654 | return SEN_RELEASED; | |
1655 | if (is_empty(temp, mod_len)) | |
1656 | return SEN_USER_ERROR; | |
1657 | ||
1658 | if (is_common_public_key(temp, mod_len)) { | |
1659 | if (deprecated_msg_count < 20) { | |
1660 | PRINTK("Common public key used for modex decrypt\n"); | |
1661 | deprecated_msg_count++; | |
1662 | if (deprecated_msg_count == 20) | |
1663 | PRINTK("No longer issuing messages about common" | |
1664 | " public key for modex decrypt.\n"); | |
1665 | } | |
1666 | return SEN_NOT_AVAIL; | |
1667 | } | |
1668 | ||
1669 | temp = key_p->pvtMESec.modulus + sizeof(key_p->pvtMESec.modulus) | |
1670 | - mod_len; | |
1671 | if (copy_from_user(temp, icaMsg_p->n_modulus, mod_len)) | |
1672 | return SEN_RELEASED; | |
1673 | if (is_empty(temp, mod_len)) | |
1674 | return SEN_USER_ERROR; | |
1675 | ||
1676 | key_p->pubMESec.modulus_bit_len = 8 * mod_len; | |
1677 | ||
1678 | *z90cMsg_l_p = tmp_size - CALLER_HEADER; | |
1679 | ||
1680 | return 0; | |
1681 | } | |
1682 | ||
1683 | static int | |
1684 | ICAMEX_msg_to_type6MEX_en_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx, | |
1685 | int *z90cMsg_l_p, struct type6_msg *z90cMsg_p) | |
1686 | { | |
1687 | int mod_len, vud_len, exp_len, key_len; | |
1688 | int pad_len, tmp_size, total_CPRB_len, parmBlock_l, i; | |
1689 | unsigned char *temp_exp, *exp_p, *temp; | |
1690 | struct type6_hdr *tp6Hdr_p; | |
1691 | struct CPRB *cprb_p; | |
1692 | struct cca_public_key *key_p; | |
1693 | struct T6_keyBlock_hdr *keyb_p; | |
1694 | ||
1695 | temp_exp = kmalloc(256, GFP_KERNEL); | |
1696 | if (!temp_exp) | |
1697 | return EGETBUFF; | |
1698 | mod_len = icaMsg_p->inputdatalength; | |
1699 | if (copy_from_user(temp_exp, icaMsg_p->b_key, mod_len)) { | |
1700 | kfree(temp_exp); | |
1701 | return SEN_RELEASED; | |
1702 | } | |
1703 | if (is_empty(temp_exp, mod_len)) { | |
1704 | kfree(temp_exp); | |
1705 | return SEN_USER_ERROR; | |
1706 | } | |
1707 | ||
1708 | exp_p = temp_exp; | |
1709 | for (i = 0; i < mod_len; i++) | |
1710 | if (exp_p[i]) | |
1711 | break; | |
1712 | if (i >= mod_len) { | |
1713 | kfree(temp_exp); | |
1714 | return SEN_USER_ERROR; | |
1715 | } | |
1716 | ||
1717 | exp_len = mod_len - i; | |
1718 | exp_p += i; | |
1719 | ||
1720 | PDEBUG("exp_len after computation: %08x\n", exp_len); | |
1721 | tmp_size = FIXED_TYPE6_ME_EN_LEN + 2 * mod_len + exp_len; | |
1722 | total_CPRB_len = tmp_size - sizeof(struct type6_hdr); | |
1723 | parmBlock_l = total_CPRB_len - sizeof(struct CPRB); | |
1724 | tmp_size = 4*((tmp_size + 3)/4) + CALLER_HEADER; | |
1725 | ||
1726 | vud_len = 2 + mod_len; | |
1727 | memset(z90cMsg_p, 0, tmp_size); | |
1728 | ||
1729 | temp = (unsigned char *)z90cMsg_p + CALLER_HEADER; | |
1730 | memcpy(temp, &static_type6_hdr, sizeof(struct type6_hdr)); | |
1731 | tp6Hdr_p = (struct type6_hdr *)temp; | |
1732 | tp6Hdr_p->ToCardLen1 = 4*((total_CPRB_len+3)/4); | |
1733 | tp6Hdr_p->FromCardLen1 = RESPONSE_CPRB_SIZE; | |
1734 | memcpy(tp6Hdr_p->function_code, static_PKE_function_code, | |
1735 | sizeof(static_PKE_function_code)); | |
1736 | temp += sizeof(struct type6_hdr); | |
1737 | memcpy(temp, &static_cprb, sizeof(struct CPRB)); | |
1738 | cprb_p = (struct CPRB *) temp; | |
1739 | cprb_p->usage_domain[0]= (unsigned char)cdx; | |
1740 | itoLe2((int *)&(tp6Hdr_p->FromCardLen1), cprb_p->rpl_parml); | |
1741 | temp += sizeof(struct CPRB); | |
1742 | memcpy(temp, &static_pke_function_and_rules, | |
1743 | sizeof(struct function_and_rules_block)); | |
1744 | temp += sizeof(struct function_and_rules_block); | |
1745 | temp += 2; | |
1746 | if (copy_from_user(temp, icaMsg_p->inputdata, mod_len)) { | |
1747 | kfree(temp_exp); | |
1748 | return SEN_RELEASED; | |
1749 | } | |
1750 | if (is_empty(temp, mod_len)) { | |
1751 | kfree(temp_exp); | |
1752 | return SEN_USER_ERROR; | |
1753 | } | |
1754 | if ((temp[0] != 0x00) || (temp[1] != 0x02)) { | |
1755 | kfree(temp_exp); | |
1756 | return SEN_NOT_AVAIL; | |
1757 | } | |
1758 | for (i = 2; i < mod_len; i++) | |
1759 | if (temp[i] == 0x00) | |
1760 | break; | |
1761 | if ((i < 9) || (i > (mod_len - 2))) { | |
1762 | kfree(temp_exp); | |
1763 | return SEN_NOT_AVAIL; | |
1764 | } | |
1765 | pad_len = i + 1; | |
1766 | vud_len = mod_len - pad_len; | |
1767 | memmove(temp, temp+pad_len, vud_len); | |
1768 | temp -= 2; | |
1769 | vud_len += 2; | |
1770 | itoLe2(&vud_len, temp); | |
1771 | temp += (vud_len); | |
1772 | keyb_p = (struct T6_keyBlock_hdr *)temp; | |
1773 | temp += sizeof(struct T6_keyBlock_hdr); | |
1774 | memcpy(temp, &static_public_key, sizeof(static_public_key)); | |
1775 | key_p = (struct cca_public_key *)temp; | |
1776 | temp = key_p->pubSec.exponent; | |
1777 | memcpy(temp, exp_p, exp_len); | |
1778 | kfree(temp_exp); | |
1779 | temp += exp_len; | |
1780 | if (copy_from_user(temp, icaMsg_p->n_modulus, mod_len)) | |
1781 | return SEN_RELEASED; | |
1782 | if (is_empty(temp, mod_len)) | |
1783 | return SEN_USER_ERROR; | |
1784 | key_p->pubSec.modulus_bit_len = 8 * mod_len; | |
1785 | key_p->pubSec.modulus_byte_len = mod_len; | |
1786 | key_p->pubSec.exponent_len = exp_len; | |
1787 | key_p->pubSec.section_length = CALLER_HEADER + mod_len + exp_len; | |
1788 | key_len = key_p->pubSec.section_length + sizeof(struct cca_token_hdr); | |
1789 | key_p->pubHdr.token_length = key_len; | |
1790 | key_len += 4; | |
1791 | itoLe2(&key_len, keyb_p->ulen); | |
1792 | key_len += 2; | |
1793 | itoLe2(&key_len, keyb_p->blen); | |
1794 | parmBlock_l -= pad_len; | |
1795 | itoLe2(&parmBlock_l, cprb_p->req_parml); | |
1796 | *z90cMsg_l_p = tmp_size - CALLER_HEADER; | |
1797 | ||
1798 | return 0; | |
1799 | } | |
1800 | ||
1801 | static int | |
1802 | ICACRT_msg_to_type6CRT_msg(struct ica_rsa_modexpo_crt *icaMsg_p, int cdx, | |
1803 | int *z90cMsg_l_p, struct type6_msg *z90cMsg_p) | |
1804 | { | |
1805 | int mod_len, vud_len, tmp_size, total_CPRB_len, parmBlock_l, short_len; | |
1806 | int long_len, pad_len, keyPartsLen, tmp_l; | |
1807 | unsigned char *tgt_p, *temp; | |
1808 | struct type6_hdr *tp6Hdr_p; | |
1809 | struct CPRB *cprb_p; | |
1810 | struct cca_token_hdr *keyHdr_p; | |
1811 | struct cca_pvt_ext_CRT_sec *pvtSec_p; | |
1812 | struct cca_public_sec *pubSec_p; | |
1813 | ||
1814 | mod_len = icaMsg_p->inputdatalength; | |
1815 | short_len = mod_len / 2; | |
1816 | long_len = 8 + short_len; | |
1817 | keyPartsLen = 3 * long_len + 2 * short_len; | |
1818 | pad_len = (8 - (keyPartsLen % 8)) % 8; | |
1819 | keyPartsLen += pad_len + mod_len; | |
1820 | tmp_size = FIXED_TYPE6_CR_LEN + keyPartsLen + mod_len; | |
1821 | total_CPRB_len = tmp_size - sizeof(struct type6_hdr); | |
1822 | parmBlock_l = total_CPRB_len - sizeof(struct CPRB); | |
1823 | vud_len = 2 + mod_len; | |
1824 | tmp_size = 4*((tmp_size + 3)/4) + CALLER_HEADER; | |
1825 | ||
1826 | memset(z90cMsg_p, 0, tmp_size); | |
1827 | tgt_p = (unsigned char *)z90cMsg_p + CALLER_HEADER; | |
1828 | memcpy(tgt_p, &static_type6_hdr, sizeof(struct type6_hdr)); | |
1829 | tp6Hdr_p = (struct type6_hdr *)tgt_p; | |
1830 | tp6Hdr_p->ToCardLen1 = 4*((total_CPRB_len+3)/4); | |
1831 | tp6Hdr_p->FromCardLen1 = RESPONSE_CPRB_SIZE; | |
1832 | tgt_p += sizeof(struct type6_hdr); | |
1833 | cprb_p = (struct CPRB *) tgt_p; | |
1834 | memcpy(tgt_p, &static_cprb, sizeof(struct CPRB)); | |
1835 | cprb_p->usage_domain[0]= *((unsigned char *)(&(cdx))+3); | |
1836 | itoLe2(&parmBlock_l, cprb_p->req_parml); | |
1837 | memcpy(cprb_p->rpl_parml, cprb_p->req_parml, | |
1838 | sizeof(cprb_p->req_parml)); | |
1839 | tgt_p += sizeof(struct CPRB); | |
1840 | memcpy(tgt_p, &static_pkd_function_and_rules, | |
1841 | sizeof(struct function_and_rules_block)); | |
1842 | tgt_p += sizeof(struct function_and_rules_block); | |
1843 | itoLe2(&vud_len, tgt_p); | |
1844 | tgt_p += 2; | |
1845 | if (copy_from_user(tgt_p, icaMsg_p->inputdata, mod_len)) | |
1846 | return SEN_RELEASED; | |
1847 | if (is_empty(tgt_p, mod_len)) | |
1848 | return SEN_USER_ERROR; | |
1849 | tgt_p += mod_len; | |
1850 | tmp_l = sizeof(struct T6_keyBlock_hdr) + sizeof(struct cca_token_hdr) + | |
1851 | sizeof(struct cca_pvt_ext_CRT_sec) + 0x0F + keyPartsLen; | |
1852 | itoLe2(&tmp_l, tgt_p); | |
1853 | temp = tgt_p + 2; | |
1854 | tmp_l -= 2; | |
1855 | itoLe2(&tmp_l, temp); | |
1856 | tgt_p += sizeof(struct T6_keyBlock_hdr); | |
1857 | keyHdr_p = (struct cca_token_hdr *)tgt_p; | |
1858 | keyHdr_p->token_identifier = CCA_TKN_HDR_ID_EXT; | |
1859 | tmp_l -= 4; | |
1860 | keyHdr_p->token_length = tmp_l; | |
1861 | tgt_p += sizeof(struct cca_token_hdr); | |
1862 | pvtSec_p = (struct cca_pvt_ext_CRT_sec *)tgt_p; | |
1863 | pvtSec_p->section_identifier = CCA_PVT_EXT_CRT_SEC_ID_PVT; | |
1864 | pvtSec_p->section_length = | |
1865 | sizeof(struct cca_pvt_ext_CRT_sec) + keyPartsLen; | |
1866 | pvtSec_p->key_format = CCA_PVT_EXT_CRT_SEC_FMT_CL; | |
1867 | pvtSec_p->key_use_flags[0] = CCA_PVT_USAGE_ALL; | |
1868 | pvtSec_p->p_len = long_len; | |
1869 | pvtSec_p->q_len = short_len; | |
1870 | pvtSec_p->dp_len = long_len; | |
1871 | pvtSec_p->dq_len = short_len; | |
1872 | pvtSec_p->u_len = long_len; | |
1873 | pvtSec_p->mod_len = mod_len; | |
1874 | pvtSec_p->pad_len = pad_len; | |
1875 | tgt_p += sizeof(struct cca_pvt_ext_CRT_sec); | |
1876 | if (copy_from_user(tgt_p, icaMsg_p->np_prime, long_len)) | |
1877 | return SEN_RELEASED; | |
1878 | if (is_empty(tgt_p, long_len)) | |
1879 | return SEN_USER_ERROR; | |
1880 | tgt_p += long_len; | |
1881 | if (copy_from_user(tgt_p, icaMsg_p->nq_prime, short_len)) | |
1882 | return SEN_RELEASED; | |
1883 | if (is_empty(tgt_p, short_len)) | |
1884 | return SEN_USER_ERROR; | |
1885 | tgt_p += short_len; | |
1886 | if (copy_from_user(tgt_p, icaMsg_p->bp_key, long_len)) | |
1887 | return SEN_RELEASED; | |
1888 | if (is_empty(tgt_p, long_len)) | |
1889 | return SEN_USER_ERROR; | |
1890 | tgt_p += long_len; | |
1891 | if (copy_from_user(tgt_p, icaMsg_p->bq_key, short_len)) | |
1892 | return SEN_RELEASED; | |
1893 | if (is_empty(tgt_p, short_len)) | |
1894 | return SEN_USER_ERROR; | |
1895 | tgt_p += short_len; | |
1896 | if (copy_from_user(tgt_p, icaMsg_p->u_mult_inv, long_len)) | |
1897 | return SEN_RELEASED; | |
1898 | if (is_empty(tgt_p, long_len)) | |
1899 | return SEN_USER_ERROR; | |
1900 | tgt_p += long_len; | |
1901 | tgt_p += pad_len; | |
1902 | memset(tgt_p, 0xFF, mod_len); | |
1903 | tgt_p += mod_len; | |
1904 | memcpy(tgt_p, &static_cca_pub_sec, sizeof(struct cca_public_sec)); | |
1905 | pubSec_p = (struct cca_public_sec *) tgt_p; | |
1906 | pubSec_p->modulus_bit_len = 8 * mod_len; | |
1907 | *z90cMsg_l_p = tmp_size - CALLER_HEADER; | |
1908 | ||
1909 | return 0; | |
1910 | } | |
1911 | ||
1912 | static int | |
1913 | ICAMEX_msg_to_type6MEX_msgX(struct ica_rsa_modexpo *icaMsg_p, int cdx, | |
1914 | int *z90cMsg_l_p, struct type6_msg *z90cMsg_p, | |
1915 | int dev_type) | |
1916 | { | |
1917 | int mod_len, exp_len, vud_len, tmp_size, total_CPRB_len, parmBlock_l; | |
1918 | int key_len, i; | |
1919 | unsigned char *temp_exp, *tgt_p, *temp, *exp_p; | |
1920 | struct type6_hdr *tp6Hdr_p; | |
1921 | struct CPRBX *cprbx_p; | |
1922 | struct cca_public_key *key_p; | |
1923 | struct T6_keyBlock_hdrX *keyb_p; | |
1924 | ||
1925 | temp_exp = kmalloc(256, GFP_KERNEL); | |
1926 | if (!temp_exp) | |
1927 | return EGETBUFF; | |
1928 | mod_len = icaMsg_p->inputdatalength; | |
1929 | if (copy_from_user(temp_exp, icaMsg_p->b_key, mod_len)) { | |
1930 | kfree(temp_exp); | |
1931 | return SEN_RELEASED; | |
1932 | } | |
1933 | if (is_empty(temp_exp, mod_len)) { | |
1934 | kfree(temp_exp); | |
1935 | return SEN_USER_ERROR; | |
1936 | } | |
1937 | exp_p = temp_exp; | |
1938 | for (i = 0; i < mod_len; i++) | |
1939 | if (exp_p[i]) | |
1940 | break; | |
1941 | if (i >= mod_len) { | |
1942 | kfree(temp_exp); | |
1943 | return SEN_USER_ERROR; | |
1944 | } | |
1945 | exp_len = mod_len - i; | |
1946 | exp_p += i; | |
1947 | PDEBUG("exp_len after computation: %08x\n", exp_len); | |
1948 | tmp_size = FIXED_TYPE6_ME_EN_LENX + 2 * mod_len + exp_len; | |
1949 | total_CPRB_len = tmp_size - sizeof(struct type6_hdr); | |
1950 | parmBlock_l = total_CPRB_len - sizeof(struct CPRBX); | |
1951 | tmp_size = tmp_size + CALLER_HEADER; | |
1952 | vud_len = 2 + mod_len; | |
1953 | memset(z90cMsg_p, 0, tmp_size); | |
1954 | tgt_p = (unsigned char *)z90cMsg_p + CALLER_HEADER; | |
1955 | memcpy(tgt_p, &static_type6_hdrX, sizeof(struct type6_hdr)); | |
1956 | tp6Hdr_p = (struct type6_hdr *)tgt_p; | |
1957 | tp6Hdr_p->ToCardLen1 = total_CPRB_len; | |
1958 | tp6Hdr_p->FromCardLen1 = RESPONSE_CPRBX_SIZE; | |
1959 | memcpy(tp6Hdr_p->function_code, static_PKE_function_code, | |
1960 | sizeof(static_PKE_function_code)); | |
1961 | tgt_p += sizeof(struct type6_hdr); | |
1962 | memcpy(tgt_p, &static_cprbx, sizeof(struct CPRBX)); | |
1963 | cprbx_p = (struct CPRBX *) tgt_p; | |
1964 | cprbx_p->domain = (unsigned short)cdx; | |
1965 | cprbx_p->rpl_msgbl = RESPONSE_CPRBX_SIZE; | |
1966 | tgt_p += sizeof(struct CPRBX); | |
1967 | if (dev_type == PCIXCC_MCL2) | |
1968 | memcpy(tgt_p, &static_pke_function_and_rulesX_MCL2, | |
1969 | sizeof(struct function_and_rules_block)); | |
1970 | else | |
1971 | memcpy(tgt_p, &static_pke_function_and_rulesX, | |
1972 | sizeof(struct function_and_rules_block)); | |
1973 | tgt_p += sizeof(struct function_and_rules_block); | |
1974 | ||
1975 | tgt_p += 2; | |
1976 | if (copy_from_user(tgt_p, icaMsg_p->inputdata, mod_len)) { | |
1977 | kfree(temp_exp); | |
1978 | return SEN_RELEASED; | |
1979 | } | |
1980 | if (is_empty(tgt_p, mod_len)) { | |
1981 | kfree(temp_exp); | |
1982 | return SEN_USER_ERROR; | |
1983 | } | |
1984 | tgt_p -= 2; | |
1985 | *((short *)tgt_p) = (short) vud_len; | |
1986 | tgt_p += vud_len; | |
1987 | keyb_p = (struct T6_keyBlock_hdrX *)tgt_p; | |
1988 | tgt_p += sizeof(struct T6_keyBlock_hdrX); | |
1989 | memcpy(tgt_p, &static_public_key, sizeof(static_public_key)); | |
1990 | key_p = (struct cca_public_key *)tgt_p; | |
1991 | temp = key_p->pubSec.exponent; | |
1992 | memcpy(temp, exp_p, exp_len); | |
1993 | kfree(temp_exp); | |
1994 | temp += exp_len; | |
1995 | if (copy_from_user(temp, icaMsg_p->n_modulus, mod_len)) | |
1996 | return SEN_RELEASED; | |
1997 | if (is_empty(temp, mod_len)) | |
1998 | return SEN_USER_ERROR; | |
1999 | key_p->pubSec.modulus_bit_len = 8 * mod_len; | |
2000 | key_p->pubSec.modulus_byte_len = mod_len; | |
2001 | key_p->pubSec.exponent_len = exp_len; | |
2002 | key_p->pubSec.section_length = CALLER_HEADER + mod_len + exp_len; | |
2003 | key_len = key_p->pubSec.section_length + sizeof(struct cca_token_hdr); | |
2004 | key_p->pubHdr.token_length = key_len; | |
2005 | key_len += 4; | |
2006 | keyb_p->ulen = (unsigned short)key_len; | |
2007 | key_len += 2; | |
2008 | keyb_p->blen = (unsigned short)key_len; | |
2009 | cprbx_p->req_parml = parmBlock_l; | |
2010 | *z90cMsg_l_p = tmp_size - CALLER_HEADER; | |
2011 | ||
2012 | return 0; | |
2013 | } | |
2014 | ||
2015 | static int | |
2016 | ICACRT_msg_to_type6CRT_msgX(struct ica_rsa_modexpo_crt *icaMsg_p, int cdx, | |
2017 | int *z90cMsg_l_p, struct type6_msg *z90cMsg_p, | |
2018 | int dev_type) | |
2019 | { | |
2020 | int mod_len, vud_len, tmp_size, total_CPRB_len, parmBlock_l, short_len; | |
2021 | int long_len, pad_len, keyPartsLen, tmp_l; | |
2022 | unsigned char *tgt_p, *temp; | |
2023 | struct type6_hdr *tp6Hdr_p; | |
2024 | struct CPRBX *cprbx_p; | |
2025 | struct cca_token_hdr *keyHdr_p; | |
2026 | struct cca_pvt_ext_CRT_sec *pvtSec_p; | |
2027 | struct cca_public_sec *pubSec_p; | |
2028 | ||
2029 | mod_len = icaMsg_p->inputdatalength; | |
2030 | short_len = mod_len / 2; | |
2031 | long_len = 8 + short_len; | |
2032 | keyPartsLen = 3 * long_len + 2 * short_len; | |
2033 | pad_len = (8 - (keyPartsLen % 8)) % 8; | |
2034 | keyPartsLen += pad_len + mod_len; | |
2035 | tmp_size = FIXED_TYPE6_CR_LENX + keyPartsLen + mod_len; | |
2036 | total_CPRB_len = tmp_size - sizeof(struct type6_hdr); | |
2037 | parmBlock_l = total_CPRB_len - sizeof(struct CPRBX); | |
2038 | vud_len = 2 + mod_len; | |
2039 | tmp_size = tmp_size + CALLER_HEADER; | |
2040 | memset(z90cMsg_p, 0, tmp_size); | |
2041 | tgt_p = (unsigned char *)z90cMsg_p + CALLER_HEADER; | |
2042 | memcpy(tgt_p, &static_type6_hdrX, sizeof(struct type6_hdr)); | |
2043 | tp6Hdr_p = (struct type6_hdr *)tgt_p; | |
2044 | tp6Hdr_p->ToCardLen1 = total_CPRB_len; | |
2045 | tp6Hdr_p->FromCardLen1 = RESPONSE_CPRBX_SIZE; | |
2046 | tgt_p += sizeof(struct type6_hdr); | |
2047 | cprbx_p = (struct CPRBX *) tgt_p; | |
2048 | memcpy(tgt_p, &static_cprbx, sizeof(struct CPRBX)); | |
2049 | cprbx_p->domain = (unsigned short)cdx; | |
2050 | cprbx_p->req_parml = parmBlock_l; | |
2051 | cprbx_p->rpl_msgbl = parmBlock_l; | |
2052 | tgt_p += sizeof(struct CPRBX); | |
2053 | if (dev_type == PCIXCC_MCL2) | |
2054 | memcpy(tgt_p, &static_pkd_function_and_rulesX_MCL2, | |
2055 | sizeof(struct function_and_rules_block)); | |
2056 | else | |
2057 | memcpy(tgt_p, &static_pkd_function_and_rulesX, | |
2058 | sizeof(struct function_and_rules_block)); | |
2059 | tgt_p += sizeof(struct function_and_rules_block); | |
2060 | *((short *)tgt_p) = (short) vud_len; | |
2061 | tgt_p += 2; | |
2062 | if (copy_from_user(tgt_p, icaMsg_p->inputdata, mod_len)) | |
2063 | return SEN_RELEASED; | |
2064 | if (is_empty(tgt_p, mod_len)) | |
2065 | return SEN_USER_ERROR; | |
2066 | tgt_p += mod_len; | |
2067 | tmp_l = sizeof(struct T6_keyBlock_hdr) + sizeof(struct cca_token_hdr) + | |
2068 | sizeof(struct cca_pvt_ext_CRT_sec) + 0x0F + keyPartsLen; | |
2069 | *((short *)tgt_p) = (short) tmp_l; | |
2070 | temp = tgt_p + 2; | |
2071 | tmp_l -= 2; | |
2072 | *((short *)temp) = (short) tmp_l; | |
2073 | tgt_p += sizeof(struct T6_keyBlock_hdr); | |
2074 | keyHdr_p = (struct cca_token_hdr *)tgt_p; | |
2075 | keyHdr_p->token_identifier = CCA_TKN_HDR_ID_EXT; | |
2076 | tmp_l -= 4; | |
2077 | keyHdr_p->token_length = tmp_l; | |
2078 | tgt_p += sizeof(struct cca_token_hdr); | |
2079 | pvtSec_p = (struct cca_pvt_ext_CRT_sec *)tgt_p; | |
2080 | pvtSec_p->section_identifier = CCA_PVT_EXT_CRT_SEC_ID_PVT; | |
2081 | pvtSec_p->section_length = | |
2082 | sizeof(struct cca_pvt_ext_CRT_sec) + keyPartsLen; | |
2083 | pvtSec_p->key_format = CCA_PVT_EXT_CRT_SEC_FMT_CL; | |
2084 | pvtSec_p->key_use_flags[0] = CCA_PVT_USAGE_ALL; | |
2085 | pvtSec_p->p_len = long_len; | |
2086 | pvtSec_p->q_len = short_len; | |
2087 | pvtSec_p->dp_len = long_len; | |
2088 | pvtSec_p->dq_len = short_len; | |
2089 | pvtSec_p->u_len = long_len; | |
2090 | pvtSec_p->mod_len = mod_len; | |
2091 | pvtSec_p->pad_len = pad_len; | |
2092 | tgt_p += sizeof(struct cca_pvt_ext_CRT_sec); | |
2093 | if (copy_from_user(tgt_p, icaMsg_p->np_prime, long_len)) | |
2094 | return SEN_RELEASED; | |
2095 | if (is_empty(tgt_p, long_len)) | |
2096 | return SEN_USER_ERROR; | |
2097 | tgt_p += long_len; | |
2098 | if (copy_from_user(tgt_p, icaMsg_p->nq_prime, short_len)) | |
2099 | return SEN_RELEASED; | |
2100 | if (is_empty(tgt_p, short_len)) | |
2101 | return SEN_USER_ERROR; | |
2102 | tgt_p += short_len; | |
2103 | if (copy_from_user(tgt_p, icaMsg_p->bp_key, long_len)) | |
2104 | return SEN_RELEASED; | |
2105 | if (is_empty(tgt_p, long_len)) | |
2106 | return SEN_USER_ERROR; | |
2107 | tgt_p += long_len; | |
2108 | if (copy_from_user(tgt_p, icaMsg_p->bq_key, short_len)) | |
2109 | return SEN_RELEASED; | |
2110 | if (is_empty(tgt_p, short_len)) | |
2111 | return SEN_USER_ERROR; | |
2112 | tgt_p += short_len; | |
2113 | if (copy_from_user(tgt_p, icaMsg_p->u_mult_inv, long_len)) | |
2114 | return SEN_RELEASED; | |
2115 | if (is_empty(tgt_p, long_len)) | |
2116 | return SEN_USER_ERROR; | |
2117 | tgt_p += long_len; | |
2118 | tgt_p += pad_len; | |
2119 | memset(tgt_p, 0xFF, mod_len); | |
2120 | tgt_p += mod_len; | |
2121 | memcpy(tgt_p, &static_cca_pub_sec, sizeof(struct cca_public_sec)); | |
2122 | pubSec_p = (struct cca_public_sec *) tgt_p; | |
2123 | pubSec_p->modulus_bit_len = 8 * mod_len; | |
2124 | *z90cMsg_l_p = tmp_size - CALLER_HEADER; | |
2125 | ||
2126 | return 0; | |
2127 | } | |
2128 | ||
88fbf183 ER |
2129 | static int |
2130 | ICAMEX_msg_to_type50MEX_msg(struct ica_rsa_modexpo *icaMex_p, int *z90cMsg_l_p, | |
2131 | union type50_msg *z90cMsg_p) | |
2132 | { | |
2133 | int mod_len, msg_size, mod_tgt_len, exp_tgt_len, inp_tgt_len; | |
2134 | unsigned char *mod_tgt, *exp_tgt, *inp_tgt; | |
2135 | union type50_msg *tmp_type50_msg; | |
2136 | ||
2137 | mod_len = icaMex_p->inputdatalength; | |
2138 | ||
2139 | msg_size = ((mod_len <= 128) ? TYPE50_MEB1_LEN : TYPE50_MEB2_LEN) + | |
2140 | CALLER_HEADER; | |
2141 | ||
2142 | memset(z90cMsg_p, 0, msg_size); | |
2143 | ||
2144 | tmp_type50_msg = (union type50_msg *) | |
2145 | ((unsigned char *) z90cMsg_p + CALLER_HEADER); | |
2146 | ||
2147 | tmp_type50_msg->meb1.header.msg_type_code = TYPE50_TYPE_CODE; | |
2148 | ||
2149 | if (mod_len <= 128) { | |
2150 | tmp_type50_msg->meb1.header.msg_len = TYPE50_MEB1_LEN; | |
2151 | tmp_type50_msg->meb1.keyblock_type = TYPE50_MEB1_FMT; | |
2152 | mod_tgt = tmp_type50_msg->meb1.modulus; | |
2153 | mod_tgt_len = sizeof(tmp_type50_msg->meb1.modulus); | |
2154 | exp_tgt = tmp_type50_msg->meb1.exponent; | |
2155 | exp_tgt_len = sizeof(tmp_type50_msg->meb1.exponent); | |
2156 | inp_tgt = tmp_type50_msg->meb1.message; | |
2157 | inp_tgt_len = sizeof(tmp_type50_msg->meb1.message); | |
2158 | } else { | |
2159 | tmp_type50_msg->meb2.header.msg_len = TYPE50_MEB2_LEN; | |
2160 | tmp_type50_msg->meb2.keyblock_type = TYPE50_MEB2_FMT; | |
2161 | mod_tgt = tmp_type50_msg->meb2.modulus; | |
2162 | mod_tgt_len = sizeof(tmp_type50_msg->meb2.modulus); | |
2163 | exp_tgt = tmp_type50_msg->meb2.exponent; | |
2164 | exp_tgt_len = sizeof(tmp_type50_msg->meb2.exponent); | |
2165 | inp_tgt = tmp_type50_msg->meb2.message; | |
2166 | inp_tgt_len = sizeof(tmp_type50_msg->meb2.message); | |
2167 | } | |
2168 | ||
2169 | mod_tgt += (mod_tgt_len - mod_len); | |
2170 | if (copy_from_user(mod_tgt, icaMex_p->n_modulus, mod_len)) | |
2171 | return SEN_RELEASED; | |
2172 | if (is_empty(mod_tgt, mod_len)) | |
2173 | return SEN_USER_ERROR; | |
2174 | exp_tgt += (exp_tgt_len - mod_len); | |
2175 | if (copy_from_user(exp_tgt, icaMex_p->b_key, mod_len)) | |
2176 | return SEN_RELEASED; | |
2177 | if (is_empty(exp_tgt, mod_len)) | |
2178 | return SEN_USER_ERROR; | |
2179 | inp_tgt += (inp_tgt_len - mod_len); | |
2180 | if (copy_from_user(inp_tgt, icaMex_p->inputdata, mod_len)) | |
2181 | return SEN_RELEASED; | |
2182 | if (is_empty(inp_tgt, mod_len)) | |
2183 | return SEN_USER_ERROR; | |
2184 | ||
2185 | *z90cMsg_l_p = msg_size - CALLER_HEADER; | |
2186 | ||
2187 | return 0; | |
2188 | } | |
2189 | ||
2190 | static int | |
2191 | ICACRT_msg_to_type50CRT_msg(struct ica_rsa_modexpo_crt *icaMsg_p, | |
2192 | int *z90cMsg_l_p, union type50_msg *z90cMsg_p) | |
2193 | { | |
2194 | int mod_len, short_len, long_len, tmp_size, p_tgt_len, q_tgt_len, | |
2195 | dp_tgt_len, dq_tgt_len, u_tgt_len, inp_tgt_len, long_offset; | |
2196 | unsigned char *p_tgt, *q_tgt, *dp_tgt, *dq_tgt, *u_tgt, *inp_tgt, | |
2197 | temp[8]; | |
2198 | union type50_msg *tmp_type50_msg; | |
2199 | ||
2200 | mod_len = icaMsg_p->inputdatalength; | |
2201 | short_len = mod_len / 2; | |
2202 | long_len = mod_len / 2 + 8; | |
2203 | long_offset = 0; | |
2204 | ||
2205 | if (long_len > 128) { | |
2206 | memset(temp, 0x00, sizeof(temp)); | |
2207 | if (copy_from_user(temp, icaMsg_p->np_prime, long_len-128)) | |
2208 | return SEN_RELEASED; | |
2209 | if (!is_empty(temp, 8)) | |
2210 | return SEN_NOT_AVAIL; | |
2211 | if (copy_from_user(temp, icaMsg_p->bp_key, long_len-128)) | |
2212 | return SEN_RELEASED; | |
2213 | if (!is_empty(temp, 8)) | |
2214 | return SEN_NOT_AVAIL; | |
2215 | if (copy_from_user(temp, icaMsg_p->u_mult_inv, long_len-128)) | |
2216 | return SEN_RELEASED; | |
2217 | if (!is_empty(temp, 8)) | |
2218 | return SEN_NOT_AVAIL; | |
2219 | long_offset = long_len - 128; | |
2220 | long_len = 128; | |
2221 | } | |
2222 | ||
2223 | tmp_size = ((mod_len <= 128) ? TYPE50_CRB1_LEN : TYPE50_CRB2_LEN) + | |
2224 | CALLER_HEADER; | |
2225 | ||
2226 | memset(z90cMsg_p, 0, tmp_size); | |
2227 | ||
2228 | tmp_type50_msg = (union type50_msg *) | |
2229 | ((unsigned char *) z90cMsg_p + CALLER_HEADER); | |
2230 | ||
2231 | tmp_type50_msg->crb1.header.msg_type_code = TYPE50_TYPE_CODE; | |
2232 | if (long_len <= 64) { | |
2233 | tmp_type50_msg->crb1.header.msg_len = TYPE50_CRB1_LEN; | |
2234 | tmp_type50_msg->crb1.keyblock_type = TYPE50_CRB1_FMT; | |
2235 | p_tgt = tmp_type50_msg->crb1.p; | |
2236 | p_tgt_len = sizeof(tmp_type50_msg->crb1.p); | |
2237 | q_tgt = tmp_type50_msg->crb1.q; | |
2238 | q_tgt_len = sizeof(tmp_type50_msg->crb1.q); | |
2239 | dp_tgt = tmp_type50_msg->crb1.dp; | |
2240 | dp_tgt_len = sizeof(tmp_type50_msg->crb1.dp); | |
2241 | dq_tgt = tmp_type50_msg->crb1.dq; | |
2242 | dq_tgt_len = sizeof(tmp_type50_msg->crb1.dq); | |
2243 | u_tgt = tmp_type50_msg->crb1.u; | |
2244 | u_tgt_len = sizeof(tmp_type50_msg->crb1.u); | |
2245 | inp_tgt = tmp_type50_msg->crb1.message; | |
2246 | inp_tgt_len = sizeof(tmp_type50_msg->crb1.message); | |
2247 | } else { | |
2248 | tmp_type50_msg->crb2.header.msg_len = TYPE50_CRB2_LEN; | |
2249 | tmp_type50_msg->crb2.keyblock_type = TYPE50_CRB2_FMT; | |
2250 | p_tgt = tmp_type50_msg->crb2.p; | |
2251 | p_tgt_len = sizeof(tmp_type50_msg->crb2.p); | |
2252 | q_tgt = tmp_type50_msg->crb2.q; | |
2253 | q_tgt_len = sizeof(tmp_type50_msg->crb2.q); | |
2254 | dp_tgt = tmp_type50_msg->crb2.dp; | |
2255 | dp_tgt_len = sizeof(tmp_type50_msg->crb2.dp); | |
2256 | dq_tgt = tmp_type50_msg->crb2.dq; | |
2257 | dq_tgt_len = sizeof(tmp_type50_msg->crb2.dq); | |
2258 | u_tgt = tmp_type50_msg->crb2.u; | |
2259 | u_tgt_len = sizeof(tmp_type50_msg->crb2.u); | |
2260 | inp_tgt = tmp_type50_msg->crb2.message; | |
2261 | inp_tgt_len = sizeof(tmp_type50_msg->crb2.message); | |
2262 | } | |
2263 | ||
2264 | p_tgt += (p_tgt_len - long_len); | |
2265 | if (copy_from_user(p_tgt, icaMsg_p->np_prime + long_offset, long_len)) | |
2266 | return SEN_RELEASED; | |
2267 | if (is_empty(p_tgt, long_len)) | |
2268 | return SEN_USER_ERROR; | |
2269 | q_tgt += (q_tgt_len - short_len); | |
2270 | if (copy_from_user(q_tgt, icaMsg_p->nq_prime, short_len)) | |
2271 | return SEN_RELEASED; | |
2272 | if (is_empty(q_tgt, short_len)) | |
2273 | return SEN_USER_ERROR; | |
2274 | dp_tgt += (dp_tgt_len - long_len); | |
2275 | if (copy_from_user(dp_tgt, icaMsg_p->bp_key + long_offset, long_len)) | |
2276 | return SEN_RELEASED; | |
2277 | if (is_empty(dp_tgt, long_len)) | |
2278 | return SEN_USER_ERROR; | |
2279 | dq_tgt += (dq_tgt_len - short_len); | |
2280 | if (copy_from_user(dq_tgt, icaMsg_p->bq_key, short_len)) | |
2281 | return SEN_RELEASED; | |
2282 | if (is_empty(dq_tgt, short_len)) | |
2283 | return SEN_USER_ERROR; | |
2284 | u_tgt += (u_tgt_len - long_len); | |
2285 | if (copy_from_user(u_tgt, icaMsg_p->u_mult_inv + long_offset, long_len)) | |
2286 | return SEN_RELEASED; | |
2287 | if (is_empty(u_tgt, long_len)) | |
2288 | return SEN_USER_ERROR; | |
2289 | inp_tgt += (inp_tgt_len - mod_len); | |
2290 | if (copy_from_user(inp_tgt, icaMsg_p->inputdata, mod_len)) | |
2291 | return SEN_RELEASED; | |
2292 | if (is_empty(inp_tgt, mod_len)) | |
2293 | return SEN_USER_ERROR; | |
2294 | ||
2295 | *z90cMsg_l_p = tmp_size - CALLER_HEADER; | |
2296 | ||
2297 | return 0; | |
2298 | } | |
2299 | ||
1da177e4 LT |
2300 | int |
2301 | convert_request(unsigned char *buffer, int func, unsigned short function, | |
2302 | int cdx, int dev_type, int *msg_l_p, unsigned char *msg_p) | |
2303 | { | |
2304 | if (dev_type == PCICA) { | |
2305 | if (func == ICARSACRT) | |
2306 | return ICACRT_msg_to_type4CRT_msg( | |
2307 | (struct ica_rsa_modexpo_crt *) buffer, | |
2308 | msg_l_p, (union type4_msg *) msg_p); | |
2309 | else | |
2310 | return ICAMEX_msg_to_type4MEX_msg( | |
2311 | (struct ica_rsa_modexpo *) buffer, | |
2312 | msg_l_p, (union type4_msg *) msg_p); | |
2313 | } | |
2314 | if (dev_type == PCICC) { | |
2315 | if (func == ICARSACRT) | |
2316 | return ICACRT_msg_to_type6CRT_msg( | |
2317 | (struct ica_rsa_modexpo_crt *) buffer, | |
2318 | cdx, msg_l_p, (struct type6_msg *)msg_p); | |
2319 | if (function == PCI_FUNC_KEY_ENCRYPT) | |
2320 | return ICAMEX_msg_to_type6MEX_en_msg( | |
2321 | (struct ica_rsa_modexpo *) buffer, | |
2322 | cdx, msg_l_p, (struct type6_msg *) msg_p); | |
2323 | else | |
2324 | return ICAMEX_msg_to_type6MEX_de_msg( | |
2325 | (struct ica_rsa_modexpo *) buffer, | |
2326 | cdx, msg_l_p, (struct type6_msg *) msg_p); | |
2327 | } | |
2328 | if ((dev_type == PCIXCC_MCL2) || | |
2329 | (dev_type == PCIXCC_MCL3) || | |
2330 | (dev_type == CEX2C)) { | |
2331 | if (func == ICARSACRT) | |
2332 | return ICACRT_msg_to_type6CRT_msgX( | |
2333 | (struct ica_rsa_modexpo_crt *) buffer, | |
2334 | cdx, msg_l_p, (struct type6_msg *) msg_p, | |
2335 | dev_type); | |
2336 | else | |
2337 | return ICAMEX_msg_to_type6MEX_msgX( | |
2338 | (struct ica_rsa_modexpo *) buffer, | |
2339 | cdx, msg_l_p, (struct type6_msg *) msg_p, | |
2340 | dev_type); | |
2341 | } | |
88fbf183 ER |
2342 | if (dev_type == CEX2A) { |
2343 | if (func == ICARSACRT) | |
2344 | return ICACRT_msg_to_type50CRT_msg( | |
2345 | (struct ica_rsa_modexpo_crt *) buffer, | |
2346 | msg_l_p, (union type50_msg *) msg_p); | |
2347 | else | |
2348 | return ICAMEX_msg_to_type50MEX_msg( | |
2349 | (struct ica_rsa_modexpo *) buffer, | |
2350 | msg_l_p, (union type50_msg *) msg_p); | |
2351 | } | |
1da177e4 LT |
2352 | |
2353 | return 0; | |
2354 | } | |
2355 | ||
2356 | int ext_bitlens_msg_count = 0; | |
2357 | static inline void | |
2358 | unset_ext_bitlens(void) | |
2359 | { | |
2360 | if (!ext_bitlens_msg_count) { | |
2361 | PRINTK("Unable to use coprocessors for extended bitlengths. " | |
88fbf183 ER |
2362 | "Using PCICAs/CEX2As (if present) for extended " |
2363 | "bitlengths. This is not an error.\n"); | |
1da177e4 LT |
2364 | ext_bitlens_msg_count++; |
2365 | } | |
2366 | ext_bitlens = 0; | |
2367 | } | |
2368 | ||
2369 | int | |
2370 | convert_response(unsigned char *response, unsigned char *buffer, | |
2371 | int *respbufflen_p, unsigned char *resp_buff) | |
2372 | { | |
2373 | struct ica_rsa_modexpo *icaMsg_p = (struct ica_rsa_modexpo *) buffer; | |
2dee702f | 2374 | struct error_hdr *errh_p = (struct error_hdr *) response; |
88fbf183 | 2375 | struct type80_hdr *t80h_p = (struct type80_hdr *) response; |
1da177e4 LT |
2376 | struct type84_hdr *t84h_p = (struct type84_hdr *) response; |
2377 | struct type86_fmt2_msg *t86m_p = (struct type86_fmt2_msg *) response; | |
2378 | int reply_code, service_rc, service_rs, src_l; | |
2379 | unsigned char *src_p, *tgt_p; | |
2380 | struct CPRB *cprb_p; | |
2381 | struct CPRBX *cprbx_p; | |
2382 | ||
2383 | src_p = 0; | |
2384 | reply_code = 0; | |
2385 | service_rc = 0; | |
2386 | service_rs = 0; | |
2387 | src_l = 0; | |
2dee702f | 2388 | switch (errh_p->type) { |
1da177e4 | 2389 | case TYPE82_RSP_CODE: |
88fbf183 | 2390 | case TYPE88_RSP_CODE: |
2dee702f ER |
2391 | reply_code = errh_p->reply_code; |
2392 | src_p = (unsigned char *)errh_p; | |
2393 | PRINTK("Hardware error: Type %02X Message Header: " | |
1da177e4 | 2394 | "%02x%02x%02x%02x%02x%02x%02x%02x\n", |
2dee702f | 2395 | errh_p->type, |
1da177e4 LT |
2396 | src_p[0], src_p[1], src_p[2], src_p[3], |
2397 | src_p[4], src_p[5], src_p[6], src_p[7]); | |
2398 | break; | |
88fbf183 ER |
2399 | case TYPE80_RSP_CODE: |
2400 | src_l = icaMsg_p->outputdatalength; | |
2401 | src_p = response + (int)t80h_p->len - src_l; | |
2402 | break; | |
1da177e4 LT |
2403 | case TYPE84_RSP_CODE: |
2404 | src_l = icaMsg_p->outputdatalength; | |
2405 | src_p = response + (int)t84h_p->len - src_l; | |
2406 | break; | |
2407 | case TYPE86_RSP_CODE: | |
2dee702f | 2408 | reply_code = t86m_p->header.reply_code; |
1da177e4 LT |
2409 | if (reply_code != 0) |
2410 | break; | |
2411 | cprb_p = (struct CPRB *) | |
2412 | (response + sizeof(struct type86_fmt2_msg)); | |
2413 | cprbx_p = (struct CPRBX *) cprb_p; | |
2414 | if (cprb_p->cprb_ver_id != 0x02) { | |
2415 | le2toI(cprb_p->ccp_rtcode, &service_rc); | |
2416 | if (service_rc != 0) { | |
2417 | le2toI(cprb_p->ccp_rscode, &service_rs); | |
2418 | if ((service_rc == 8) && (service_rs == 66)) | |
2419 | PDEBUG("Bad block format on PCICC\n"); | |
2dee702f ER |
2420 | else if ((service_rc == 8) && (service_rs == 65)) |
2421 | PDEBUG("Probably an even modulus on " | |
2422 | "PCICC\n"); | |
1da177e4 LT |
2423 | else if ((service_rc == 8) && (service_rs == 770)) { |
2424 | PDEBUG("Invalid key length on PCICC\n"); | |
2425 | unset_ext_bitlens(); | |
2426 | return REC_USE_PCICA; | |
2427 | } | |
2428 | else if ((service_rc == 8) && (service_rs == 783)) { | |
2429 | PDEBUG("Extended bitlengths not enabled" | |
2430 | "on PCICC\n"); | |
2431 | unset_ext_bitlens(); | |
2432 | return REC_USE_PCICA; | |
2433 | } | |
2434 | else | |
2dee702f | 2435 | PRINTK("service rc/rs (PCICC): %d/%d\n", |
1da177e4 LT |
2436 | service_rc, service_rs); |
2437 | return REC_OPERAND_INV; | |
2438 | } | |
2439 | src_p = (unsigned char *)cprb_p + sizeof(struct CPRB); | |
2440 | src_p += 4; | |
2441 | le2toI(src_p, &src_l); | |
2442 | src_l -= 2; | |
2443 | src_p += 2; | |
2444 | } else { | |
2445 | service_rc = (int)cprbx_p->ccp_rtcode; | |
2446 | if (service_rc != 0) { | |
2447 | service_rs = (int) cprbx_p->ccp_rscode; | |
2448 | if ((service_rc == 8) && (service_rs == 66)) | |
2dee702f ER |
2449 | PDEBUG("Bad block format on PCIXCC\n"); |
2450 | else if ((service_rc == 8) && (service_rs == 65)) | |
2451 | PDEBUG("Probably an even modulus on " | |
2452 | "PCIXCC\n"); | |
1da177e4 LT |
2453 | else if ((service_rc == 8) && (service_rs == 770)) { |
2454 | PDEBUG("Invalid key length on PCIXCC\n"); | |
2455 | unset_ext_bitlens(); | |
2456 | return REC_USE_PCICA; | |
2457 | } | |
2458 | else if ((service_rc == 8) && (service_rs == 783)) { | |
2459 | PDEBUG("Extended bitlengths not enabled" | |
2460 | "on PCIXCC\n"); | |
2461 | unset_ext_bitlens(); | |
2462 | return REC_USE_PCICA; | |
2463 | } | |
2464 | else | |
2dee702f | 2465 | PRINTK("service rc/rs (PCIXCC): %d/%d\n", |
1da177e4 LT |
2466 | service_rc, service_rs); |
2467 | return REC_OPERAND_INV; | |
2468 | } | |
2469 | src_p = (unsigned char *) | |
2470 | cprbx_p + sizeof(struct CPRBX); | |
2471 | src_p += 4; | |
2472 | src_l = (int)(*((short *) src_p)); | |
2473 | src_l -= 2; | |
2474 | src_p += 2; | |
2475 | } | |
2476 | break; | |
2477 | default: | |
2dee702f ER |
2478 | src_p = (unsigned char *)errh_p; |
2479 | PRINTK("Unrecognized Message Header: " | |
2480 | "%02x%02x%02x%02x%02x%02x%02x%02x\n", | |
2481 | src_p[0], src_p[1], src_p[2], src_p[3], | |
2482 | src_p[4], src_p[5], src_p[6], src_p[7]); | |
1da177e4 LT |
2483 | return REC_BAD_MESSAGE; |
2484 | } | |
2485 | ||
2486 | if (reply_code) | |
2487 | switch (reply_code) { | |
2dee702f | 2488 | case REP82_ERROR_OPERAND_INVALID: |
88fbf183 | 2489 | case REP88_ERROR_MESSAGE_MALFORMD: |
1da177e4 | 2490 | return REC_OPERAND_INV; |
2dee702f | 2491 | case REP82_ERROR_OPERAND_SIZE: |
1da177e4 | 2492 | return REC_OPERAND_SIZE; |
2dee702f | 2493 | case REP82_ERROR_EVEN_MOD_IN_OPND: |
1da177e4 | 2494 | return REC_EVEN_MOD; |
2dee702f | 2495 | case REP82_ERROR_MESSAGE_TYPE: |
1da177e4 | 2496 | return WRONG_DEVICE_TYPE; |
2dee702f | 2497 | case REP82_ERROR_TRANSPORT_FAIL: |
1da177e4 LT |
2498 | PRINTKW("Transport failed (APFS = %02X%02X%02X%02X)\n", |
2499 | t86m_p->apfs[0], t86m_p->apfs[1], | |
2500 | t86m_p->apfs[2], t86m_p->apfs[3]); | |
2501 | return REC_HARDWAR_ERR; | |
2502 | default: | |
2503 | PRINTKW("reply code = %d\n", reply_code); | |
2504 | return REC_HARDWAR_ERR; | |
2505 | } | |
2506 | ||
2507 | if (service_rc != 0) | |
2508 | return REC_OPERAND_INV; | |
2509 | ||
2510 | if ((src_l > icaMsg_p->outputdatalength) || | |
2511 | (src_l > RESPBUFFSIZE) || | |
2512 | (src_l <= 0)) | |
2513 | return REC_OPERAND_SIZE; | |
2514 | ||
2515 | PDEBUG("Length returned = %d\n", src_l); | |
2516 | tgt_p = resp_buff + icaMsg_p->outputdatalength - src_l; | |
2517 | memcpy(tgt_p, src_p, src_l); | |
2dee702f | 2518 | if ((errh_p->type == TYPE86_RSP_CODE) && (resp_buff < tgt_p)) { |
1da177e4 LT |
2519 | memset(resp_buff, 0, icaMsg_p->outputdatalength - src_l); |
2520 | if (pad_msg(resp_buff, icaMsg_p->outputdatalength, src_l)) | |
2521 | return REC_INVALID_PAD; | |
2522 | } | |
2523 | *respbufflen_p = icaMsg_p->outputdatalength; | |
2524 | if (*respbufflen_p == 0) | |
2525 | PRINTK("Zero *respbufflen_p\n"); | |
2526 | ||
2527 | return 0; | |
2528 | } | |
2529 |