2 * Routines for Fibre Channel Security Protocol (FC-SP)
3 * This decoder is for FC-SP version 1.1
4 * Copyright 2003, Dinesh G Dutt <ddutt@cisco.com>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include <epan/packet.h>
16 #include <epan/to_str.h>
17 #include <epan/expert.h>
19 void proto_register_fcsp(void);
22 #define FC_AUTH_MSG_AUTH_REJECT 0x0A
23 #define FC_AUTH_MSG_AUTH_NEGOTIATE 0x0B
24 #define FC_AUTH_MSG_AUTH_DONE 0x0C
25 #define FC_AUTH_DHCHAP_CHALLENGE 0x10
26 #define FC_AUTH_DHCHAP_REPLY 0x11
27 #define FC_AUTH_DHCHAP_SUCCESS 0x12
28 #define FC_AUTH_FCAP_REQUEST 0x13
29 #define FC_AUTH_FCAP_ACKNOWLEDGE 0x14
30 #define FC_AUTH_FCAP_CONFIRM 0x15
31 #define FC_AUTH_FCPAP_INIT 0x16
32 #define FC_AUTH_FCPAP_ACCEPT 0x17
33 #define FC_AUTH_FCPAP_COMPLETE 0x18
35 #define FC_AUTH_NAME_TYPE_WWN 0x1
37 #define FC_AUTH_PROTO_TYPE_DHCHAP 0x1
38 #define FC_AUTH_PROTO_TYPE_FCAP 0x2
40 #define FC_AUTH_DHCHAP_HASH_MD5 0x5
41 #define FC_AUTH_DHCHAP_HASH_SHA1 0x6
43 #define FC_AUTH_DHCHAP_PARAM_HASHLIST 0x1
44 #define FC_AUTH_DHCHAP_PARAM_DHgIDLIST 0x2
46 /* Initialize the protocol and registered fields */
47 static int proto_fcsp
;
48 static int hf_auth_proto_ver
;
49 static int hf_auth_msg_code
;
50 static int hf_auth_flags
;
51 static int hf_auth_len
;
52 static int hf_auth_tid
;
53 static int hf_auth_initiator_wwn
;
54 static int hf_auth_initiator_name
;
55 static int hf_auth_usable_proto
;
56 static int hf_auth_rjt_code
;
57 static int hf_auth_rjt_codedet
;
58 static int hf_auth_responder_wwn
;
59 static int hf_auth_responder_name
;
60 /* static int hf_auth_dhchap_groupid; */
61 /* static int hf_auth_dhchap_hashid; */
62 static int hf_auth_dhchap_chal_len
;
63 static int hf_auth_dhchap_val_len
;
64 static int hf_auth_dhchap_rsp_len
;
65 static int hf_auth_initiator_name_type
;
66 static int hf_auth_initiator_name_len
;
67 static int hf_auth_responder_name_len
;
68 static int hf_auth_responder_name_type
;
69 static int hf_auth_proto_type
;
70 static int hf_auth_proto_param_len
;
71 static int hf_auth_dhchap_param_tag
;
72 static int hf_auth_dhchap_param_len
;
73 static int hf_auth_dhchap_hash_type
;
74 static int hf_auth_dhchap_group_type
;
75 static int hf_auth_dhchap_dhvalue
;
76 static int hf_auth_dhchap_chal_value
;
77 static int hf_auth_dhchap_rsp_value
;
79 /* Initialize the subtree pointers */
82 static expert_field ei_auth_fcap_undecoded
;
84 static const value_string fcauth_msgcode_vals
[] = {
85 {FC_AUTH_MSG_AUTH_REJECT
, "AUTH_Reject"},
86 {FC_AUTH_MSG_AUTH_NEGOTIATE
, "AUTH_Negotiate"},
87 {FC_AUTH_MSG_AUTH_DONE
, "AUTH_Done"},
88 {FC_AUTH_DHCHAP_CHALLENGE
, "DHCHAP_Challenge"},
89 {FC_AUTH_DHCHAP_REPLY
, "DHCHAP_Reply"},
90 {FC_AUTH_DHCHAP_SUCCESS
, "DHCHAP_Success"},
91 {FC_AUTH_FCAP_REQUEST
, "FCAP_Request"},
92 {FC_AUTH_FCAP_ACKNOWLEDGE
, "FCAP_Acknowledge"},
93 {FC_AUTH_FCAP_CONFIRM
, "FCAP_Confirm"},
94 {FC_AUTH_FCPAP_INIT
, "FCPAP_Init"},
95 {FC_AUTH_FCPAP_ACCEPT
, "FCPAP_Accept"},
96 {FC_AUTH_FCPAP_COMPLETE
, "FCPAP_Complete"},
100 static const value_string fcauth_rjtcode_vals
[] = {
101 {0x01, "Authentication Failure"},
102 {0x02, "Logical Error"},
106 static const value_string fcauth_rjtcode_detail_vals
[] = {
107 {0x01, "Authentication Mechanism Not Usable"},
108 {0x02, "DH Group Not Usable"},
109 {0x03, "Hash Algorithm Not Usable"},
110 {0x04, "Authentication Protocol Instance Already Started"},
111 {0x05, "Authentication Failed "},
112 {0x06, "Incorrect Payload "},
113 {0x07, "Incorrect Authentication Protocol Message"},
114 {0x08, "Protocol Reset"},
118 static const value_string fcauth_dhchap_param_vals
[] = {
119 {FC_AUTH_DHCHAP_PARAM_HASHLIST
, "HashList"},
120 {FC_AUTH_DHCHAP_PARAM_DHgIDLIST
, "DHgIDList"},
124 static const value_string fcauth_dhchap_hash_algo_vals
[] = {
125 {FC_AUTH_DHCHAP_HASH_MD5
, "MD5"},
126 {FC_AUTH_DHCHAP_HASH_SHA1
, "SHA-1"},
130 static const value_string fcauth_name_type_vals
[] = {
131 {FC_AUTH_NAME_TYPE_WWN
, "WWN"},
135 static const value_string fcauth_proto_type_vals
[] = {
136 {FC_AUTH_PROTO_TYPE_DHCHAP
, "DHCHAP"},
137 {FC_AUTH_PROTO_TYPE_FCAP
, "FCAP"},
141 static const value_string fcauth_dhchap_dhgid_vals
[] = {
143 {1, "DH Group 1024"},
144 {2, "DH Group 1280"},
145 {3, "DH Group 1536"},
146 {4, "DH Group 2048"},
150 /* this format is required because a script is used to build the C function
151 that calls all the protocol registration.
154 static void dissect_fcsp_dhchap_auth_param(tvbuff_t
*tvb
, proto_tree
*tree
,
155 int offset
, int32_t total_len
)
157 uint16_t auth_param_tag
;
158 uint16_t param_len
, i
;
163 while (total_len
> 0) {
164 proto_tree_add_item(tree
, hf_auth_dhchap_param_tag
, tvb
, offset
,
166 proto_tree_add_item(tree
, hf_auth_dhchap_param_len
, tvb
, offset
+2,
169 auth_param_tag
= tvb_get_ntohs(tvb
, offset
);
170 param_len
= tvb_get_ntohs(tvb
, offset
+2)*4;
172 switch (auth_param_tag
) {
173 case FC_AUTH_DHCHAP_PARAM_HASHLIST
:
176 for (i
= 0; i
< param_len
; i
+= 4) {
177 proto_tree_add_item(tree
, hf_auth_dhchap_hash_type
, tvb
,
178 offset
, 4, ENC_BIG_ENDIAN
);
182 case FC_AUTH_DHCHAP_PARAM_DHgIDLIST
:
185 for (i
= 0; i
< param_len
; i
+= 4) {
186 proto_tree_add_item(tree
, hf_auth_dhchap_group_type
, tvb
,
187 offset
, 4, ENC_BIG_ENDIAN
);
192 /* If we don't recognize the auth_param_tag and the param_len
193 * is 0 then just return to prevent an infinite loop. See
194 * https://gitlab.com/wireshark/wireshark/-/issues/8359
196 if (param_len
== 0) {
202 total_len
-= param_len
;
207 static void dissect_fcsp_dhchap_challenge(tvbuff_t
*tvb
, proto_tree
*tree
)
211 uint16_t param_len
, name_len
;
214 proto_tree_add_item(tree
, hf_auth_responder_name_type
, tvb
, offset
,
216 name_type
= tvb_get_ntohs(tvb
, offset
);
218 proto_tree_add_item(tree
, hf_auth_responder_name_len
, tvb
, offset
+2,
221 name_len
= tvb_get_ntohs(tvb
, offset
+2);
223 if (name_type
== FC_AUTH_NAME_TYPE_WWN
) {
224 proto_tree_add_item(tree
, hf_auth_responder_wwn
, tvb
, offset
+4,
228 proto_tree_add_item(tree
, hf_auth_responder_name
, tvb
, offset
+4,
231 offset
+= (4+name_len
);
233 proto_tree_add_item(tree
, hf_auth_dhchap_hash_type
, tvb
, offset
,
235 proto_tree_add_item(tree
, hf_auth_dhchap_group_type
, tvb
, offset
+4,
237 proto_tree_add_item(tree
, hf_auth_dhchap_chal_len
, tvb
, offset
+8,
239 param_len
= tvb_get_ntohl(tvb
, offset
+8);
241 proto_tree_add_item(tree
, hf_auth_dhchap_chal_value
, tvb
, offset
+12,
243 offset
+= (param_len
+ 12);
245 proto_tree_add_item(tree
, hf_auth_dhchap_val_len
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
246 param_len
= tvb_get_ntohl(tvb
, offset
);
248 proto_tree_add_item(tree
, hf_auth_dhchap_dhvalue
, tvb
, offset
+4,
254 static void dissect_fcsp_dhchap_reply(tvbuff_t
*tvb
, proto_tree
*tree
)
260 proto_tree_add_item(tree
, hf_auth_dhchap_rsp_len
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
261 param_len
= tvb_get_ntohl(tvb
, offset
);
263 proto_tree_add_item(tree
, hf_auth_dhchap_rsp_value
, tvb
, offset
+4,
265 offset
+= (param_len
+ 4);
267 proto_tree_add_item(tree
, hf_auth_dhchap_val_len
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
268 param_len
= tvb_get_ntohl(tvb
, offset
);
270 proto_tree_add_item(tree
, hf_auth_dhchap_dhvalue
, tvb
, offset
+4,
272 offset
+= (param_len
+ 4);
274 proto_tree_add_item(tree
, hf_auth_dhchap_chal_len
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
275 param_len
= tvb_get_ntohl(tvb
, offset
);
277 proto_tree_add_item(tree
, hf_auth_dhchap_chal_value
, tvb
, offset
+4,
282 static void dissect_fcsp_dhchap_success(tvbuff_t
*tvb
, proto_tree
*tree
)
288 proto_tree_add_item(tree
, hf_auth_dhchap_rsp_len
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
289 param_len
= tvb_get_ntohl(tvb
, offset
);
291 proto_tree_add_item(tree
, hf_auth_dhchap_rsp_value
, tvb
, offset
+4,
297 static void dissect_fcsp_auth_negotiate(tvbuff_t
*tvb
, proto_tree
*tree
)
300 uint16_t name_type
, name_len
, proto_type
, param_len
;
301 uint32_t num_protos
, i
;
304 proto_tree_add_item(tree
, hf_auth_initiator_name_type
, tvb
, offset
,
306 name_type
= tvb_get_ntohs(tvb
, offset
);
308 proto_tree_add_item(tree
, hf_auth_initiator_name_len
, tvb
, offset
+2,
310 name_len
= tvb_get_ntohs(tvb
, offset
+2);
312 if (name_type
== FC_AUTH_NAME_TYPE_WWN
) {
313 proto_tree_add_item(tree
, hf_auth_initiator_wwn
, tvb
, offset
+4, 8, ENC_NA
);
316 proto_tree_add_item(tree
, hf_auth_initiator_name
, tvb
, offset
+4,
320 offset
+= (4+name_len
);
322 proto_tree_add_item(tree
, hf_auth_usable_proto
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
323 num_protos
= tvb_get_ntohl(tvb
, offset
);
326 for (i
= 0; i
< num_protos
; i
++) {
327 proto_tree_add_item(tree
, hf_auth_proto_param_len
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
328 param_len
= tvb_get_ntohl(tvb
, offset
);
331 if (tvb_bytes_exist(tvb
, offset
, param_len
)) {
332 proto_type
= tvb_get_ntohl(tvb
, offset
);
334 proto_tree_add_item(tree
, hf_auth_proto_type
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
335 switch (proto_type
) {
336 case FC_AUTH_PROTO_TYPE_DHCHAP
:
337 dissect_fcsp_dhchap_auth_param(tvb
, tree
, offset
+4, param_len
);
339 case FC_AUTH_PROTO_TYPE_FCAP
:
350 static void dissect_fcsp_auth_done(tvbuff_t
*tvb _U_
, proto_tree
*tree _U_
)
354 static void dissect_fcsp_auth_rjt(tvbuff_t
*tvb
, proto_tree
*tree
)
359 proto_tree_add_item(tree
, hf_auth_rjt_code
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
360 proto_tree_add_item(tree
, hf_auth_rjt_codedet
, tvb
, offset
+1, 1, ENC_BIG_ENDIAN
);
364 static int dissect_fcsp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
366 proto_item
*ti
= NULL
;
369 proto_tree
*fcsp_tree
= NULL
;
371 /* Make entry in the Info column on summary display */
372 opcode
= tvb_get_uint8(tvb
, 2);
374 col_add_str(pinfo
->cinfo
, COL_INFO
,
375 val_to_str(opcode
, fcauth_msgcode_vals
, "0x%x"));
378 ti
= proto_tree_add_protocol_format(tree
, proto_fcsp
, tvb
, 0,
379 tvb_captured_length(tvb
), "FC-SP");
380 fcsp_tree
= proto_item_add_subtree(ti
, ett_fcsp
);
382 proto_tree_add_item(fcsp_tree
, hf_auth_flags
, tvb
, offset
+1, 1, ENC_BIG_ENDIAN
);
383 proto_tree_add_item(fcsp_tree
, hf_auth_msg_code
, tvb
, offset
+2, 1, ENC_BIG_ENDIAN
);
384 proto_tree_add_item(fcsp_tree
, hf_auth_proto_ver
, tvb
, offset
+3, 1,
386 proto_tree_add_item(fcsp_tree
, hf_auth_len
, tvb
, offset
+4, 4, ENC_BIG_ENDIAN
);
387 proto_tree_add_item(fcsp_tree
, hf_auth_tid
, tvb
, offset
+8, 4, ENC_BIG_ENDIAN
);
390 case FC_AUTH_MSG_AUTH_REJECT
:
391 dissect_fcsp_auth_rjt(tvb
, tree
);
393 case FC_AUTH_MSG_AUTH_NEGOTIATE
:
394 dissect_fcsp_auth_negotiate(tvb
, tree
);
396 case FC_AUTH_MSG_AUTH_DONE
:
397 dissect_fcsp_auth_done(tvb
, tree
);
399 case FC_AUTH_DHCHAP_CHALLENGE
:
400 dissect_fcsp_dhchap_challenge(tvb
, tree
);
402 case FC_AUTH_DHCHAP_REPLY
:
403 dissect_fcsp_dhchap_reply(tvb
, tree
);
405 case FC_AUTH_DHCHAP_SUCCESS
:
406 dissect_fcsp_dhchap_success(tvb
, tree
);
408 case FC_AUTH_FCAP_REQUEST
:
409 case FC_AUTH_FCAP_ACKNOWLEDGE
:
410 case FC_AUTH_FCAP_CONFIRM
:
411 case FC_AUTH_FCPAP_INIT
:
412 case FC_AUTH_FCPAP_ACCEPT
:
413 case FC_AUTH_FCPAP_COMPLETE
:
414 proto_tree_add_expert(fcsp_tree
, pinfo
, &ei_auth_fcap_undecoded
, tvb
, offset
+12, -1);
420 return tvb_captured_length(tvb
);
424 proto_register_fcsp(void)
426 /* Setup list of header fields See Section 1.6.1 for details*/
427 static hf_register_info hf
[] = {
428 { &hf_auth_proto_ver
,
429 { "Protocol Version", "fcsp.version",
430 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
434 { "Message Code", "fcsp.opcode",
435 FT_UINT8
, BASE_HEX
, VALS(fcauth_msgcode_vals
), 0x0,
439 { "Flags", "fcsp.flags",
440 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
444 { "Packet Length", "fcsp.len",
445 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
449 { "Transaction Identifier", "fcsp.tid",
450 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
453 { &hf_auth_initiator_wwn
,
454 { "Initiator Name (WWN)", "fcsp.initwwn",
455 FT_FCWWN
, BASE_NONE
, NULL
, 0x0,
458 { &hf_auth_initiator_name
,
459 { "Initiator Name (Unknown Type)", "fcsp.initname",
460 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
463 { &hf_auth_initiator_name_type
,
464 { "Initiator Name Type", "fcsp.initnametype",
465 FT_UINT16
, BASE_HEX
, VALS(fcauth_name_type_vals
), 0x0,
468 { &hf_auth_initiator_name_len
,
469 { "Initiator Name Length", "fcsp.initnamelen",
470 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
473 { &hf_auth_usable_proto
,
474 { "Number of Usable Protocols", "fcsp.usableproto",
475 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
479 { "Reason Code", "fcsp.rjtcode",
480 FT_UINT8
, BASE_DEC
, VALS(fcauth_rjtcode_vals
), 0x0,
483 { &hf_auth_rjt_codedet
,
484 { "Reason Code Explanation", "fcsp.rjtcodet",
485 FT_UINT8
, BASE_DEC
, VALS(fcauth_rjtcode_detail_vals
), 0x0,
488 { &hf_auth_responder_wwn
,
489 { "Responder Name (WWN)", "fcsp.rspwwn",
490 FT_FCWWN
, BASE_NONE
, NULL
, 0x0,
493 { &hf_auth_responder_name
,
494 { "Responder Name (Unknown Type)", "fcsp.rspname",
495 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
498 { &hf_auth_responder_name_type
,
499 { "Responder Name Type", "fcsp.rspnametype",
500 FT_UINT16
, BASE_HEX
, VALS(fcauth_name_type_vals
), 0x0,
503 { &hf_auth_responder_name_len
,
504 { "Responder Name Type", "fcsp.rspnamelen",
505 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
509 { &hf_auth_dhchap_hashid
,
510 { "Hash Identifier", "fcsp.dhchap.hashid",
511 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
516 { &hf_auth_dhchap_groupid
,
517 { "DH Group Identifier", "fcsp.dhchap.groupid",
518 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
522 { &hf_auth_dhchap_chal_len
,
523 { "Challenge Value Length", "fcsp.dhchap.challen",
524 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
527 { &hf_auth_dhchap_val_len
,
528 { "DH Value Length", "fcsp.dhchap.vallen",
529 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
532 { &hf_auth_dhchap_rsp_len
,
533 { "Response Value Length", "fcsp.dhchap.rsplen",
534 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
537 { &hf_auth_proto_type
,
538 { "Authentication Protocol Type", "fcsp.proto",
539 FT_UINT32
, BASE_DEC
, VALS(fcauth_proto_type_vals
), 0x0,
542 { &hf_auth_proto_param_len
,
543 { "Protocol Parameters Length", "fcsp.protoparamlen",
544 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
547 { &hf_auth_dhchap_param_tag
,
548 { "Parameter Tag", "fcsp.dhchap.paramtype",
549 FT_UINT16
, BASE_HEX
, VALS(fcauth_dhchap_param_vals
), 0x0,
552 { &hf_auth_dhchap_param_len
,
553 { "Parameter Length", "fcsp.dhchap.paramlen",
554 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
557 { &hf_auth_dhchap_hash_type
,
558 { "Hash Algorithm", "fcsp.dhchap.hashtype",
559 FT_UINT32
, BASE_DEC
, VALS(fcauth_dhchap_hash_algo_vals
), 0x0,
562 { &hf_auth_dhchap_group_type
,
563 { "DH Group", "fcsp.dhchap.dhgid",
564 FT_UINT32
, BASE_DEC
, VALS(fcauth_dhchap_dhgid_vals
), 0x0,
567 { &hf_auth_dhchap_chal_value
,
568 { "Challenge Value", "fcsp.dhchap.chalval",
569 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
572 { &hf_auth_dhchap_dhvalue
,
573 { "DH Value", "fcsp.dhchap.dhvalue",
574 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
577 { &hf_auth_dhchap_rsp_value
,
578 { "Response Value", "fcsp.dhchap.rspval",
579 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
584 /* Setup protocol subtree array */
585 static int *ett
[] = {
589 static ei_register_info ei
[] = {
590 { &ei_auth_fcap_undecoded
, { "fcsp.fcap_undecoded", PI_UNDECODED
, PI_WARN
, "FCAP Decoding Not Supported", EXPFILL
}},
593 expert_module_t
* expert_fcsp
;
595 /* Register the protocol name and description */
596 proto_fcsp
= proto_register_protocol("Fibre Channel Security Protocol", "FC-SP", "fcsp");
598 register_dissector("fcsp", dissect_fcsp
, proto_fcsp
);
600 proto_register_field_array(proto_fcsp
, hf
, array_length(hf
));
601 proto_register_subtree_array(ett
, array_length(ett
));
602 expert_fcsp
= expert_register_protocol(proto_fcsp
);
603 expert_register_field_array(expert_fcsp
, ei
, array_length(ei
));
607 * Editor modelines - https://www.wireshark.org/tools/modelines.html
612 * indent-tabs-mode: nil
615 * vi: set shiftwidth=4 tabstop=8 expandtab:
616 * :indentSize=4:tabSize=8:noTabs=true: