1 /*
2  * Copyright (C) 2003-2015 FreeIPMI Core Team
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  *
17  */
18 
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif /* HAVE_CONFIG_H */
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #ifdef STDC_HEADERS
26 #include <string.h>
27 #endif /* STDC_HEADERS */
28 #include <assert.h>
29 #include <errno.h>
30 
31 #include "freeipmi/debug/ipmi-debug.h"
32 #include "freeipmi/cmds/ipmi-messaging-support-cmds.h"
33 #include "freeipmi/cmds/ipmi-sol-cmds.h"
34 #include "freeipmi/fiid/fiid.h"
35 #include "freeipmi/interface/ipmi-ipmb-interface.h"
36 #include "freeipmi/interface/ipmi-lan-interface.h"
37 #include "freeipmi/interface/ipmi-rmcpplus-interface.h"
38 #include "freeipmi/interface/rmcp-interface.h"
39 #include "freeipmi/payload/ipmi-sol-payload.h"
40 #include "freeipmi/util/ipmi-rmcpplus-util.h"
41 
42 #include "ipmi-debug-common.h"
43 
44 #include "libcommon/ipmi-crypt.h"
45 #include "libcommon/ipmi-fiid-util.h"
46 #include "libcommon/ipmi-fill-util.h"
47 #include "libcommon/ipmi-trace.h"
48 
49 #include "freeipmi-portability.h"
50 
51 /* return data parsed on success, 0 if can't parse anymore, -1 on error */
52 static int
53 _dump_rmcpplus_session_hdr (int fd,
54                             const char *prefix,
55                             const char *session_hdr,
56                             const void *pkt,
57                             unsigned int pkt_len,
58                             uint8_t *payload_type,
59                             uint8_t *payload_authenticated,
60                             uint8_t *payload_encrypted,
61                             uint32_t *session_id,
62                             uint16_t *ipmi_payload_len)
63 {
64   fiid_obj_t obj_rmcpplus_session_hdr = NULL;
65   unsigned int indx = 0;
66   int obj_len, rv = -1;
67   uint64_t val;
68 
69   assert (pkt
70           && pkt_len
71           && payload_type
72           && payload_authenticated
73           && payload_encrypted
74           && session_id
75           && ipmi_payload_len);
76 
77   /*
78    * Extract auth_type and payload information
79    */
80   if (!(obj_rmcpplus_session_hdr = fiid_obj_create (tmpl_rmcpplus_session_hdr)))
81     {
82       ERRNO_TRACE (errno);
83       goto cleanup;
84     }
85 
86   if ((obj_len = fiid_obj_set_block (obj_rmcpplus_session_hdr,
87                                      "authentication_type",
88                                      "payload_type.encrypted",
89                                      pkt + indx,
90                                      pkt_len - indx)) < 0)
91     {
92       FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcpplus_session_hdr);
93       goto cleanup;
94     }
95   indx += obj_len;
96 
97   if (pkt_len <= indx)
98     goto output;
99 
100   if (FIID_OBJ_GET (obj_rmcpplus_session_hdr,
101                     "payload_type",
102                     &val) < 0)
103     {
104       FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcpplus_session_hdr);
105       goto cleanup;
106     }
107   (*payload_type) = val;
108 
109   /*
110    * Extract OEM IANA and OEM Payload ID
111    */
112   if (*payload_type == IPMI_PAYLOAD_TYPE_OEM_EXPLICIT)
113     {
114       if ((obj_len = fiid_obj_set_block (obj_rmcpplus_session_hdr,
115                                          "oem_iana",
116                                          "oem_payload_id",
117                                          pkt + indx,
118                                          pkt_len - indx)) < 0)
119         {
120           FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcpplus_session_hdr);
121           goto cleanup;
122         }
123       indx += obj_len;
124 
125       if (pkt_len <= indx)
126         goto output;
127     }
128 
129   /*
130    * Extract Session ID, Session Sequence Number, and Payload Length
131    */
132   if ((obj_len = fiid_obj_set_block (obj_rmcpplus_session_hdr,
133                                      "session_id",
134                                      "ipmi_payload_len",
135                                      pkt + indx,
136                                      pkt_len - indx)) < 0)
137     {
138       FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcpplus_session_hdr);
139       goto cleanup;
140     }
141   indx += obj_len;
142 
143   if (pkt_len <= indx)
144     goto output;
145 
146   if (FIID_OBJ_GET (obj_rmcpplus_session_hdr,
147                     "payload_type.authenticated",
148                     &val) < 0)
149     {
150       FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcpplus_session_hdr);
151       goto cleanup;
152     }
153   (*payload_authenticated) = val;
154 
155   if (FIID_OBJ_GET (obj_rmcpplus_session_hdr,
156                     "payload_type.encrypted",
157                     &val) < 0)
158     {
159       FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcpplus_session_hdr);
160       goto cleanup;
161     }
162   (*payload_encrypted) = val;
163 
164   if (FIID_OBJ_GET (obj_rmcpplus_session_hdr,
165                     "session_id",
166                     &val) < 0)
167     {
168       FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcpplus_session_hdr);
169       goto cleanup;
170     }
171   (*session_id) = val;
172 
173   if (FIID_OBJ_GET (obj_rmcpplus_session_hdr,
174                     "ipmi_payload_len",
175                     &val) < 0)
176     {
177       FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcpplus_session_hdr);
178       goto cleanup;
179     }
180   (*ipmi_payload_len) = val;
181 
182  output:
183   if (ipmi_obj_dump (fd,
184                      prefix,
185                      session_hdr,
186                      NULL,
187                      obj_rmcpplus_session_hdr) < 0)
188     {
189       ERRNO_TRACE (errno);
190       goto cleanup;
191     }
192 
193   rv = indx;
194  cleanup:
195   fiid_obj_destroy (obj_rmcpplus_session_hdr);
196   return (rv);
197 }
198 
199 /* return 1 on parse success, 0 if can't parse anymore, -1 on error */
200 static int
201 _dump_rmcpplus_payload_data (int fd,
202                              const char *prefix,
203                              const char *msg_hdr,
204                              const char *cmd_hdr,
205                              const char *ipmb_msg_hdr,
206                              const char *ipmb_cmd_hdr,
207                              const char *ipmb_msg_trlr_hdr,
208                              const char *trailer_hdr,
209                              uint8_t payload_type,
210                              fiid_template_t tmpl_lan_msg_hdr,
211                              fiid_template_t tmpl_cmd,
212                              fiid_template_t tmpl_ipmb_msg_hdr,
213                              fiid_template_t tmpl_ipmb_cmd,
214                              const void *pkt,
215                              uint16_t ipmi_payload_len)
216 {
217   char *payload_unexpected_hdr =
218     "Payload Unexpected Data:\n"
219     "------------------------";
220   fiid_obj_t obj_lan_msg_hdr = NULL;
221   fiid_obj_t obj_cmd = NULL;
222   fiid_obj_t obj_lan_msg_trlr = NULL;
223   fiid_obj_t obj_payload_unexpected_data = NULL;
224   int obj_lan_msg_trlr_len, len, rv = -1;
225   unsigned int obj_cmd_len;
226   unsigned int indx = 0;
227 
228   assert ((payload_type == IPMI_PAYLOAD_TYPE_IPMI
229            || payload_type == IPMI_PAYLOAD_TYPE_SOL)
230           && !(payload_type == IPMI_PAYLOAD_TYPE_IPMI
231                && !(tmpl_lan_msg_hdr
232                     && (fiid_template_compare (tmpl_lan_msg_hdr,
233                                                tmpl_lan_msg_hdr_rq) == 1
234                         || fiid_template_compare (tmpl_lan_msg_hdr,
235                                                   tmpl_lan_msg_hdr_rs) == 1)))
236           && tmpl_cmd
237           && !(payload_type == IPMI_PAYLOAD_TYPE_SOL
238                && !(fiid_template_compare (tmpl_cmd,
239                                            tmpl_sol_payload_data) == 1
240                     || fiid_template_compare (tmpl_cmd,
241                                               tmpl_sol_payload_data_remote_console_to_bmc) == 1
242                     || fiid_template_compare (tmpl_cmd,
243                                               tmpl_sol_payload_data_bmc_to_remote_console) == 1))
244           && pkt
245           && ipmi_payload_len);
246 
247   /* Dump message header */
248 
249   if (payload_type == IPMI_PAYLOAD_TYPE_IPMI)
250     {
251       uint8_t ipmb_buf[IPMI_DEBUG_MAX_PKT_LEN];
252       int ipmb_buf_len = 0;
253 
254       if (!(obj_lan_msg_hdr = fiid_obj_create (tmpl_lan_msg_hdr)))
255         {
256           ERRNO_TRACE (errno);
257           goto cleanup;
258         }
259 
260       if ((len = fiid_obj_set_all (obj_lan_msg_hdr,
261                                    pkt + indx,
262                                    ipmi_payload_len - indx)) < 0)
263         {
264           FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_hdr);
265           goto cleanup;
266         }
267       indx += len;
268 
269       if (ipmi_obj_dump (fd,
270                          prefix,
271                          msg_hdr,
272                          NULL,
273                          obj_lan_msg_hdr) < 0)
274         {
275           ERRNO_TRACE (errno);
276           goto cleanup;
277         }
278 
279       if (ipmi_payload_len <= indx)
280         {
281           rv = 0;
282           goto cleanup;
283         }
284 
285       if ((obj_lan_msg_trlr_len = fiid_template_len_bytes (tmpl_lan_msg_trlr)) < 0)
286         {
287           ERRNO_TRACE (errno);
288           goto cleanup;
289         }
290 
291       if ((ipmi_payload_len - indx) <= obj_lan_msg_trlr_len)
292         goto dump_payload_extra;
293 
294       obj_cmd_len = (ipmi_payload_len - indx) - obj_lan_msg_trlr_len;
295 
296       if (!(obj_cmd = fiid_obj_create (tmpl_cmd)))
297         {
298           ERRNO_TRACE (errno);
299           goto cleanup;
300         }
301 
302       if ((len = fiid_obj_set_all (obj_cmd,
303                                    pkt + indx,
304                                    obj_cmd_len)) < 0)
305         {
306           FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
307           goto cleanup;
308         }
309       indx += len;
310 
311       if (tmpl_ipmb_msg_hdr && tmpl_ipmb_cmd)
312         {
313           if ((ipmb_buf_len = fiid_obj_get_data (obj_cmd,
314                                                  "message_data",
315                                                  ipmb_buf,
316                                                  IPMI_DEBUG_MAX_PKT_LEN)) < 0)
317             {
318               FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
319               goto cleanup;
320             }
321 
322           if (fiid_obj_clear_field (obj_cmd, "message_data") < 0)
323             {
324               FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
325               goto cleanup;
326             }
327         }
328 
329       if (ipmi_obj_dump (fd,
330                          prefix,
331                          cmd_hdr,
332                          NULL,
333                          obj_cmd) < 0)
334         {
335           ERRNO_TRACE (errno);
336           goto cleanup;
337         }
338 
339       if (tmpl_ipmb_msg_hdr && tmpl_ipmb_cmd && ipmb_buf_len)
340         {
341           if (debug_dump_ipmb (fd,
342                                prefix,
343                                ipmb_buf,
344                                ipmb_buf_len,
345                                tmpl_ipmb_msg_hdr,
346                                tmpl_ipmb_cmd) < 0)
347             goto cleanup;
348         }
349 
350       if (ipmi_payload_len <= indx)
351         {
352           rv = 0;
353           goto cleanup;
354         }
355 
356       /* Dump trailer */
357 
358       if (!(obj_lan_msg_trlr = fiid_obj_create (tmpl_lan_msg_trlr)))
359         {
360           ERRNO_TRACE (errno);
361           goto cleanup;
362         }
363 
364       if ((len = fiid_obj_set_all (obj_lan_msg_trlr,
365                                    pkt + indx,
366                                    ipmi_payload_len - indx)) < 0)
367         {
368           FIID_OBJECT_ERROR_TO_ERRNO (obj_lan_msg_trlr);
369           goto cleanup;
370         }
371       indx += len;
372 
373       if (ipmi_obj_dump (fd,
374                          prefix,
375                          trailer_hdr,
376                          NULL,
377                          obj_lan_msg_trlr) < 0)
378         {
379           ERRNO_TRACE (errno);
380           goto cleanup;
381         }
382     }
383   else /* payload_type == IPMI_PAYLOAD_TYPE_SOL */
384     {
385       obj_cmd_len = ipmi_payload_len;
386 
387       if (!(obj_cmd = fiid_obj_create (tmpl_cmd)))
388         {
389           ERRNO_TRACE (errno);
390           goto cleanup;
391         }
392 
393       if ((len = fiid_obj_set_all (obj_cmd,
394                                    pkt + indx,
395                                    obj_cmd_len)) < 0)
396         {
397           FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
398           goto cleanup;
399         }
400       indx += len;
401 
402       if (ipmi_obj_dump (fd,
403                          prefix,
404                          cmd_hdr,
405                          NULL,
406                          obj_cmd) < 0)
407         {
408           ERRNO_TRACE (errno);
409           goto cleanup;
410         }
411     }
412 
413   /* Dump payload unexpected stuff */
414 
415  dump_payload_extra:
416 
417   if ((ipmi_payload_len - indx) > 0)
418     {
419       if (!(obj_payload_unexpected_data = fiid_obj_create (tmpl_unexpected_data)))
420         {
421           ERRNO_TRACE (errno);
422           goto cleanup;
423         }
424 
425       if ((len = fiid_obj_set_all (obj_payload_unexpected_data,
426                                    pkt + indx,
427                                    ipmi_payload_len - indx)) < 0)
428         {
429           FIID_OBJECT_ERROR_TO_ERRNO (obj_payload_unexpected_data);
430           goto cleanup;
431         }
432       indx += len;
433 
434       if (ipmi_obj_dump (fd,
435                          prefix,
436                          payload_unexpected_hdr,
437                          NULL,
438                          obj_payload_unexpected_data) < 0)
439         {
440           ERRNO_TRACE (errno);
441           goto cleanup;
442         }
443     }
444 
445   rv = 1;
446  cleanup:
447   fiid_obj_destroy (obj_lan_msg_hdr);
448   fiid_obj_destroy (obj_cmd);
449   fiid_obj_destroy (obj_lan_msg_trlr);
450   fiid_obj_destroy (obj_payload_unexpected_data);
451   return (rv);
452 }
453 
454 /* return 1 on parse success, 0 if can't parse anymore, -1 on error */
455 static int
456 _dump_rmcpplus_payload_confidentiality_none (int fd,
457                                              const char *prefix,
458                                              const char *payload_hdr,
459                                              const char *msg_hdr,
460                                              const char *cmd_hdr,
461                                              const char *ipmb_msg_hdr,
462                                              const char *ipmb_cmd_hdr,
463                                              const char *ipmb_msg_trlr_hdr,
464                                              const char *trailer_hdr,
465                                              uint8_t payload_type,
466                                              fiid_template_t tmpl_lan_msg_hdr,
467                                              fiid_template_t tmpl_cmd,
468                                              fiid_template_t tmpl_ipmb_msg_hdr,
469                                              fiid_template_t tmpl_ipmb_cmd,
470                                              const void *pkt,
471                                              uint16_t ipmi_payload_len)
472 {
473   fiid_obj_t obj_rmcpplus_payload = NULL;
474   int ret, rv = -1;
475 
476   assert ((payload_type == IPMI_PAYLOAD_TYPE_IPMI
477            || payload_type == IPMI_PAYLOAD_TYPE_SOL)
478           && !(payload_type == IPMI_PAYLOAD_TYPE_IPMI
479                && !(tmpl_lan_msg_hdr
480                     && (fiid_template_compare (tmpl_lan_msg_hdr,
481                                                tmpl_lan_msg_hdr_rq) == 1
482                         || fiid_template_compare (tmpl_lan_msg_hdr,
483                                                   tmpl_lan_msg_hdr_rs) == 1)))
484           && tmpl_cmd
485           && !(payload_type == IPMI_PAYLOAD_TYPE_SOL
486                && !(fiid_template_compare (tmpl_cmd,
487                                            tmpl_sol_payload_data) == 1
488                     || fiid_template_compare (tmpl_cmd,
489                                               tmpl_sol_payload_data_remote_console_to_bmc) == 1
490                     || fiid_template_compare (tmpl_cmd,
491                                               tmpl_sol_payload_data_bmc_to_remote_console) == 1))
492 
493           && pkt
494           && ipmi_payload_len);
495 
496   if (!(obj_rmcpplus_payload = fiid_obj_create (tmpl_rmcpplus_payload)))
497     {
498       ERRNO_TRACE (errno);
499       goto cleanup;
500     }
501 
502   if (fiid_obj_set_data (obj_rmcpplus_payload,
503                          "payload_data",
504                          pkt,
505                          ipmi_payload_len) < 0)
506     {
507       FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcpplus_payload);
508       goto cleanup;
509     }
510 
511   if (ipmi_obj_dump (fd,
512                      prefix,
513                      payload_hdr,
514                      NULL,
515                      obj_rmcpplus_payload) < 0)
516     {
517       ERRNO_TRACE (errno);
518       goto cleanup;
519     }
520 
521   if ((ret = _dump_rmcpplus_payload_data (fd,
522                                           prefix,
523                                           msg_hdr,
524                                           cmd_hdr,
525                                           ipmb_msg_hdr,
526                                           ipmb_cmd_hdr,
527                                           ipmb_msg_trlr_hdr,
528                                           trailer_hdr,
529                                           payload_type,
530                                           tmpl_lan_msg_hdr,
531                                           tmpl_cmd,
532                                           tmpl_ipmb_msg_hdr,
533                                           tmpl_ipmb_cmd,
534                                           pkt,
535                                           ipmi_payload_len)) < 0)
536     {
537       ERRNO_TRACE (errno);
538       goto cleanup;
539     }
540 
541   rv = ret;
542  cleanup:
543   fiid_obj_destroy (obj_rmcpplus_payload);
544   return (rv);
545 }
546 
547 /* return 1 on parse success, 0 if can't parse anymore, -1 on error */
548 static int
549 _dump_rmcpplus_payload_confidentiality_aes_cbc_128 (int fd,
550                                                     const char *prefix,
551                                                     const char *payload_hdr,
552                                                     const char *msg_hdr,
553                                                     const char *cmd_hdr,
554                                                     const char *ipmb_msg_hdr,
555                                                     const char *ipmb_cmd_hdr,
556                                                     const char *ipmb_msg_trlr_hdr,
557                                                     const char *trailer_hdr,
558                                                     uint8_t payload_type,
559                                                     fiid_template_t tmpl_lan_msg_hdr,
560                                                     fiid_template_t tmpl_cmd,
561                                                     fiid_template_t tmpl_ipmb_msg_hdr,
562                                                     fiid_template_t tmpl_ipmb_cmd,
563                                                     const void *confidentiality_key,
564                                                     unsigned int confidentiality_key_len,
565                                                     const void *pkt,
566                                                     uint16_t ipmi_payload_len)
567 {
568   uint8_t iv[IPMI_CRYPT_AES_CBC_128_IV_LENGTH];
569   uint8_t payload_buf[IPMI_MAX_PAYLOAD_LENGTH];
570   uint8_t pad_len;
571   int cipher_keylen, cipher_blocklen, decrypt_len, ret, rv = -1;
572   unsigned int payload_data_len, cmd_data_len;
573   fiid_obj_t obj_rmcpplus_payload = NULL;
574   unsigned int indx = 0;
575 
576   /* Note: Confidentiality Key for AES_CBS_128 is K2 */
577 
578   assert ((payload_type == IPMI_PAYLOAD_TYPE_IPMI
579            || payload_type == IPMI_PAYLOAD_TYPE_SOL)
580           && !(payload_type == IPMI_PAYLOAD_TYPE_IPMI
581                && !(tmpl_lan_msg_hdr
582                     && (fiid_template_compare (tmpl_lan_msg_hdr,
583                                                tmpl_lan_msg_hdr_rq) == 1
584                         || fiid_template_compare (tmpl_lan_msg_hdr,
585                                                   tmpl_lan_msg_hdr_rs) == 1)))
586           && tmpl_cmd
587           && !(payload_type == IPMI_PAYLOAD_TYPE_SOL
588                && !(fiid_template_compare (tmpl_cmd,
589                                            tmpl_sol_payload_data) == 1
590                     || fiid_template_compare (tmpl_cmd,
591                                               tmpl_sol_payload_data_remote_console_to_bmc) == 1
592                     || fiid_template_compare (tmpl_cmd,
593                                               tmpl_sol_payload_data_bmc_to_remote_console) == 1))
594           && confidentiality_key
595           && confidentiality_key_len
596           && pkt
597           && ipmi_payload_len);
598 
599   if ((cipher_keylen = crypt_cipher_key_len (IPMI_CRYPT_CIPHER_AES)) < 0)
600     {
601       ERRNO_TRACE (errno);
602       goto cleanup;
603     }
604   assert (!(cipher_keylen < IPMI_CRYPT_AES_CBC_128_KEY_LENGTH));
605 
606   if (confidentiality_key_len < IPMI_CRYPT_AES_CBC_128_KEY_LENGTH)
607     {
608       SET_ERRNO (EINVAL);
609       goto cleanup;
610     }
611   confidentiality_key_len = IPMI_CRYPT_AES_CBC_128_KEY_LENGTH;
612 
613   if ((cipher_blocklen = crypt_cipher_block_len (IPMI_CRYPT_CIPHER_AES)) < 0)
614     {
615       ERRNO_TRACE (errno);
616       goto cleanup;
617     }
618   assert (cipher_blocklen == IPMI_CRYPT_AES_CBC_128_BLOCK_LENGTH);
619 
620   if (ipmi_payload_len < IPMI_CRYPT_AES_CBC_128_BLOCK_LENGTH)
621     {
622       rv = 0;
623       goto cleanup;
624     }
625 
626   payload_data_len = ipmi_payload_len - IPMI_CRYPT_AES_CBC_128_BLOCK_LENGTH;
627 
628   if (!payload_data_len)
629     {
630       rv = 0;
631       goto cleanup;
632     }
633 
634   memcpy (iv, pkt, IPMI_CRYPT_AES_CBC_128_BLOCK_LENGTH);
635   indx += IPMI_CRYPT_AES_CBC_128_BLOCK_LENGTH;
636   memcpy (payload_buf, pkt + indx, payload_data_len);
637 
638   if (!(obj_rmcpplus_payload = fiid_obj_create (tmpl_rmcpplus_payload)))
639     {
640       ERRNO_TRACE (errno);
641       goto cleanup;
642     }
643 
644   if (fiid_obj_set_data (obj_rmcpplus_payload,
645                          "confidentiality_header",
646                          iv,
647                          IPMI_CRYPT_AES_CBC_128_BLOCK_LENGTH) < 0)
648     {
649       FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcpplus_payload);
650       goto cleanup;
651     }
652 
653   if ((decrypt_len = crypt_cipher_decrypt (IPMI_CRYPT_CIPHER_AES,
654                                            IPMI_CRYPT_CIPHER_MODE_CBC,
655                                            confidentiality_key,
656                                            confidentiality_key_len,
657                                            iv,
658                                            IPMI_CRYPT_AES_CBC_128_BLOCK_LENGTH,
659                                            payload_buf,
660                                            payload_data_len)) < 0)
661     {
662       ERRNO_TRACE (errno);
663       goto cleanup;
664     }
665 
666   if (decrypt_len != payload_data_len)
667     {
668       SET_ERRNO (EINVAL);
669       goto cleanup;
670     }
671 
672   pad_len = payload_buf[payload_data_len - 1];
673   if (pad_len > IPMI_CRYPT_AES_CBC_128_BLOCK_LENGTH)
674     {
675       rv = 0;
676       goto cleanup;
677     }
678 
679   if ((pad_len + 1) > payload_data_len)
680     {
681       rv = 0;
682       goto cleanup;
683     }
684 
685   cmd_data_len = payload_data_len - pad_len - 1;
686 
687   if (cmd_data_len <= 0)
688     {
689       rv = 0;
690       goto cleanup;
691     }
692 
693   if (fiid_obj_set_data (obj_rmcpplus_payload,
694                          "payload_data",
695                          payload_buf,
696                          cmd_data_len) < 0)
697     {
698       FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcpplus_payload);
699       goto cleanup;
700     }
701 
702   if (fiid_obj_set_data (obj_rmcpplus_payload,
703                          "confidentiality_trailer",
704                          payload_buf + cmd_data_len,
705                          pad_len + 1) < 0)
706     {
707       FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcpplus_payload);
708       goto cleanup;
709     }
710 
711   if (ipmi_obj_dump (fd,
712                      prefix,
713                      payload_hdr,
714                      NULL,
715                      obj_rmcpplus_payload) < 0)
716     {
717       ERRNO_TRACE (errno);
718       goto cleanup;
719     }
720 
721   if ((ret = _dump_rmcpplus_payload_data (fd,
722                                           prefix,
723                                           msg_hdr,
724                                           cmd_hdr,
725                                           ipmb_msg_hdr,
726                                           ipmb_cmd_hdr,
727                                           ipmb_msg_trlr_hdr,
728                                           trailer_hdr,
729                                           payload_type,
730                                           tmpl_lan_msg_hdr,
731                                           tmpl_cmd,
732                                           tmpl_ipmb_msg_hdr,
733                                           tmpl_ipmb_cmd,
734                                           payload_buf,
735                                           cmd_data_len)) < 0)
736     {
737       ERRNO_TRACE (errno);
738       goto cleanup;
739     }
740 
741   rv = ret;
742  cleanup:
743   fiid_obj_destroy (obj_rmcpplus_payload);
744   return (rv);
745 }
746 
747 /* return 1 on parse success, 0 if can't parse anymore, -1 on error */
748 static int
749 _dump_rmcpplus_payload_rakp (int fd,
750                              const char *prefix,
751                              const char *payload_hdr,
752                              const char *cmd_hdr,
753                              uint8_t payload_type,
754                              fiid_template_t tmpl_cmd,
755                              const void *pkt,
756                              uint16_t ipmi_payload_len)
757 {
758   fiid_obj_t obj_rmcpplus_payload = NULL;
759   fiid_obj_t obj_cmd = NULL;
760   int rv = -1;
761 
762   assert ((payload_type == IPMI_PAYLOAD_TYPE_RMCPPLUS_OPEN_SESSION_REQUEST
763            || payload_type == IPMI_PAYLOAD_TYPE_RMCPPLUS_OPEN_SESSION_RESPONSE
764            || payload_type == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_1
765            || payload_type == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_2
766            || payload_type == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_3
767            || payload_type == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_4)
768           && tmpl_cmd
769           && !(payload_type == IPMI_PAYLOAD_TYPE_RMCPPLUS_OPEN_SESSION_REQUEST
770                && (fiid_template_compare (tmpl_cmd,
771                                           tmpl_rmcpplus_open_session_request) != 1))
772           && !(payload_type == IPMI_PAYLOAD_TYPE_RMCPPLUS_OPEN_SESSION_RESPONSE
773                && (fiid_template_compare (tmpl_cmd,
774                                           tmpl_rmcpplus_open_session_response) != 1))
775           && !(payload_type == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_1
776                && (fiid_template_compare (tmpl_cmd,
777                                           tmpl_rmcpplus_rakp_message_1) != 1))
778           && !(payload_type == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_2
779                && (fiid_template_compare (tmpl_cmd,
780                                           tmpl_rmcpplus_rakp_message_2) != 1))
781           && !(payload_type == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_3
782                && (fiid_template_compare (tmpl_cmd,
783                                           tmpl_rmcpplus_rakp_message_3) != 1))
784           && !(payload_type == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_4
785                && (fiid_template_compare (tmpl_cmd,
786                                           tmpl_rmcpplus_rakp_message_4) != 1))
787           && pkt
788           && ipmi_payload_len);
789 
790   if (!(obj_rmcpplus_payload = fiid_obj_create (tmpl_rmcpplus_payload)))
791     {
792       ERRNO_TRACE (errno);
793       goto cleanup;
794     }
795 
796   if (fiid_obj_set_data (obj_rmcpplus_payload,
797                          "payload_data",
798                          pkt,
799                          ipmi_payload_len) < 0)
800     {
801       FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcpplus_payload);
802       goto cleanup;
803     }
804 
805   if (ipmi_obj_dump (fd,
806                      prefix,
807                      payload_hdr,
808                      NULL,
809                      obj_rmcpplus_payload) < 0)
810     {
811       ERRNO_TRACE (errno);
812       goto cleanup;
813     }
814 
815   if (payload_type == IPMI_PAYLOAD_TYPE_RMCPPLUS_OPEN_SESSION_REQUEST)
816     {
817       if (!(obj_cmd = fiid_obj_create (tmpl_rmcpplus_open_session_request)))
818         {
819           ERRNO_TRACE (errno);
820           goto cleanup;
821         }
822     }
823   else if (payload_type == IPMI_PAYLOAD_TYPE_RMCPPLUS_OPEN_SESSION_RESPONSE)
824     {
825       if (!(obj_cmd = fiid_obj_create (tmpl_rmcpplus_open_session_response)))
826         {
827           ERRNO_TRACE (errno);
828           goto cleanup;
829         }
830     }
831   else if (payload_type == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_1)
832     {
833       if (!(obj_cmd = fiid_obj_create (tmpl_rmcpplus_rakp_message_1)))
834         {
835           ERRNO_TRACE (errno);
836           goto cleanup;
837         }
838     }
839   else if (payload_type == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_2)
840     {
841       if (!(obj_cmd = fiid_obj_create (tmpl_rmcpplus_rakp_message_2)))
842         {
843           ERRNO_TRACE (errno);
844           goto cleanup;
845         }
846     }
847   else if (payload_type == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_3)
848     {
849       if (!(obj_cmd = fiid_obj_create (tmpl_rmcpplus_rakp_message_3)))
850         {
851           ERRNO_TRACE (errno);
852           goto cleanup;
853         }
854     }
855   else /* IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_4 */
856     {
857       if (!(obj_cmd = fiid_obj_create (tmpl_rmcpplus_rakp_message_4)))
858         {
859           ERRNO_TRACE (errno);
860           goto cleanup;
861         }
862     }
863 
864   if (fiid_obj_set_all (obj_cmd,
865                         pkt,
866                         ipmi_payload_len) < 0)
867     {
868       FIID_OBJECT_ERROR_TO_ERRNO (obj_cmd);
869       goto cleanup;
870     }
871 
872   if (ipmi_obj_dump (fd,
873                      prefix,
874                      cmd_hdr,
875                      NULL,
876                      obj_cmd) < 0)
877     {
878       ERRNO_TRACE (errno);
879       goto cleanup;
880     }
881 
882   rv = 1;
883  cleanup:
884   fiid_obj_destroy (obj_rmcpplus_payload);
885   fiid_obj_destroy (obj_cmd);
886   return (rv);
887 }
888 
889 /* return 1 on parse success, 0 if can't parse anymore, -1 on error */
890 static int
891 _dump_rmcpplus_payload (int fd,
892                         const char *prefix,
893                         const char *payload_hdr,
894                         const char *msg_hdr,
895                         const char *cmd_hdr,
896                         const char *ipmb_msg_hdr,
897                         const char *ipmb_cmd_hdr,
898                         const char *ipmb_msg_trlr_hdr,
899                         const char *trailer_hdr,
900                         uint8_t payload_type,
901                         uint8_t authentication_algorithm,
902                         uint8_t confidentiality_algorithm,
903                         fiid_template_t tmpl_lan_msg_hdr,
904                         fiid_template_t tmpl_cmd,
905                         fiid_template_t tmpl_ipmb_msg_hdr,
906                         fiid_template_t tmpl_ipmb_cmd,
907                         const void *confidentiality_key,
908                         unsigned int confidentiality_key_len,
909                         const void *pkt,
910                         uint16_t ipmi_payload_len)
911 {
912   assert ((payload_type == IPMI_PAYLOAD_TYPE_IPMI
913            || payload_type == IPMI_PAYLOAD_TYPE_SOL
914            || payload_type == IPMI_PAYLOAD_TYPE_RMCPPLUS_OPEN_SESSION_REQUEST
915            || payload_type == IPMI_PAYLOAD_TYPE_RMCPPLUS_OPEN_SESSION_RESPONSE
916            || payload_type == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_1
917            || payload_type == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_2
918            || payload_type == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_3
919            || payload_type == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_4)
920           && IPMI_AUTHENTICATION_ALGORITHM_SUPPORTED (authentication_algorithm)
921           && IPMI_CONFIDENTIALITY_ALGORITHM_SUPPORTED (confidentiality_algorithm)
922           && !(confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_AES_CBC_128
923                && !(confidentiality_key
924                     && confidentiality_key_len))
925           && ipmi_payload_len
926           && !(payload_type == IPMI_PAYLOAD_TYPE_IPMI
927                && !(tmpl_lan_msg_hdr
928                     && (fiid_template_compare (tmpl_lan_msg_hdr,
929                                                tmpl_lan_msg_hdr_rq) == 1
930                         || fiid_template_compare (tmpl_lan_msg_hdr,
931                                                   tmpl_lan_msg_hdr_rs) == 1)))
932           && tmpl_cmd
933           && !(payload_type == IPMI_PAYLOAD_TYPE_SOL
934                && !(fiid_template_compare (tmpl_cmd,
935                                            tmpl_sol_payload_data) == 1
936                     || fiid_template_compare (tmpl_cmd,
937                                               tmpl_sol_payload_data_remote_console_to_bmc) == 1
938                     || fiid_template_compare (tmpl_cmd,
939                                               tmpl_sol_payload_data_bmc_to_remote_console) == 1))
940           && pkt
941           && ipmi_payload_len);
942 
943   if (payload_type == IPMI_PAYLOAD_TYPE_IPMI
944       || payload_type == IPMI_PAYLOAD_TYPE_SOL)
945     {
946       if (confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_NONE)
947         return (_dump_rmcpplus_payload_confidentiality_none (fd,
948                                                              prefix,
949                                                              payload_hdr,
950                                                              msg_hdr,
951                                                              cmd_hdr,
952                                                              ipmb_msg_hdr,
953                                                              ipmb_cmd_hdr,
954                                                              ipmb_msg_trlr_hdr,
955                                                              trailer_hdr,
956                                                              payload_type,
957                                                              tmpl_lan_msg_hdr,
958                                                              tmpl_cmd,
959                                                              tmpl_ipmb_msg_hdr,
960                                                              tmpl_ipmb_cmd,
961                                                              pkt,
962                                                              ipmi_payload_len));
963       else /* IPMI_CONFIDENTIALITY_ALGORITHM_AES_CBC_128 */
964         return (_dump_rmcpplus_payload_confidentiality_aes_cbc_128 (fd,
965                                                                     prefix,
966                                                                     payload_hdr,
967                                                                     msg_hdr,
968                                                                     cmd_hdr,
969                                                                     ipmb_msg_hdr,
970                                                                     ipmb_cmd_hdr,
971                                                                     ipmb_msg_trlr_hdr,
972                                                                     trailer_hdr,
973                                                                     payload_type,
974                                                                     tmpl_lan_msg_hdr,
975                                                                     tmpl_cmd,
976                                                                     tmpl_ipmb_msg_hdr,
977                                                                     tmpl_ipmb_cmd,
978                                                                     confidentiality_key,
979                                                                     confidentiality_key_len,
980                                                                     pkt,
981                                                                     ipmi_payload_len));
982     }
983   else
984     return (_dump_rmcpplus_payload_rakp (fd,
985                                          prefix,
986                                          payload_hdr,
987                                          cmd_hdr,
988                                          payload_type,
989                                          tmpl_cmd,
990                                          pkt,
991                                          ipmi_payload_len));
992 }
993 
994 /* return data parsed on success, 0 if can't parse anymore, -1 on error */
995 static int
996 _dump_rmcpplus_session_trlr (int fd,
997                              const char *prefix,
998                              const char *session_trailer_hdr,
999                              uint32_t session_id,
1000                              uint8_t payload_authenticated,
1001                              uint8_t integrity_algorithm,
1002                              const void *pkt,
1003                              unsigned int pkt_len)
1004 {
1005   int pad_length_field_len, next_header_field_len, rv = -1;
1006   unsigned int pad_length, authentication_code_len = 0;
1007   fiid_obj_t obj_rmcpplus_session_trlr = NULL;
1008   unsigned int indx = 0;
1009 
1010   assert (IPMI_INTEGRITY_ALGORITHM_SUPPORTED (integrity_algorithm));
1011 
1012   if (!session_id || payload_authenticated == IPMI_PAYLOAD_FLAG_UNAUTHENTICATED)
1013     return (1);
1014 
1015   /* payload should be authenticated */
1016   if (integrity_algorithm == IPMI_INTEGRITY_ALGORITHM_NONE)
1017     authentication_code_len = 0;
1018   else if (integrity_algorithm == IPMI_INTEGRITY_ALGORITHM_HMAC_SHA1_96)
1019     authentication_code_len = IPMI_HMAC_SHA1_96_AUTHENTICATION_CODE_LENGTH;
1020   else if (integrity_algorithm == IPMI_INTEGRITY_ALGORITHM_HMAC_MD5_128)
1021     authentication_code_len = IPMI_HMAC_MD5_128_AUTHENTICATION_CODE_LENGTH;
1022   else if (integrity_algorithm == IPMI_INTEGRITY_ALGORITHM_MD5_128)
1023     authentication_code_len = IPMI_MD5_128_AUTHENTICATION_CODE_LENGTH;
1024   else if (integrity_algorithm == IPMI_INTEGRITY_ALGORITHM_HMAC_SHA256_128)
1025     authentication_code_len = IPMI_HMAC_SHA256_128_AUTHENTICATION_CODE_LENGTH;
1026   else
1027     authentication_code_len = 0; /* just in case IPMI implementation is bogus */
1028 
1029   if (!(obj_rmcpplus_session_trlr = fiid_obj_create (tmpl_rmcpplus_session_trlr)))
1030     {
1031       ERRNO_TRACE (errno);
1032       goto cleanup;
1033     }
1034 
1035   if ((pad_length_field_len = fiid_template_field_len_bytes (tmpl_rmcpplus_session_trlr,
1036                                                              "pad_length")) < 0)
1037     {
1038       ERRNO_TRACE (errno);
1039       goto cleanup;
1040     }
1041 
1042   if ((next_header_field_len = fiid_template_field_len_bytes (tmpl_rmcpplus_session_trlr,
1043                                                               "next_header")) < 0)
1044     {
1045       ERRNO_TRACE (errno);
1046       goto cleanup;
1047     }
1048 
1049   if (pkt_len < (pad_length_field_len))
1050     {
1051       next_header_field_len = 0;
1052       authentication_code_len = 0;
1053     }
1054   else if (pkt_len < (pad_length_field_len + next_header_field_len))
1055     authentication_code_len = 0;
1056   else if (authentication_code_len
1057            && pkt_len < (authentication_code_len + pad_length_field_len + next_header_field_len))
1058     authentication_code_len = pkt_len - pad_length_field_len - next_header_field_len;
1059 
1060   pad_length = pkt_len - pad_length_field_len - next_header_field_len - authentication_code_len;
1061 
1062   if (pad_length)
1063     {
1064       if (fiid_obj_set_data (obj_rmcpplus_session_trlr,
1065                              "integrity_pad",
1066                              pkt + indx,
1067                              pad_length) < 0)
1068         {
1069           FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcpplus_session_trlr);
1070           goto cleanup;
1071         }
1072       indx += pad_length;
1073     }
1074 
1075   if (pad_length_field_len)
1076     {
1077       if (fiid_obj_set_data (obj_rmcpplus_session_trlr,
1078                              "pad_length",
1079                              pkt + indx,
1080                              pad_length_field_len) < 0)
1081         {
1082           FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcpplus_session_trlr);
1083           goto cleanup;
1084         }
1085       indx += pad_length_field_len;
1086     }
1087 
1088   if (next_header_field_len)
1089     {
1090       if (fiid_obj_set_data (obj_rmcpplus_session_trlr,
1091                              "next_header",
1092                              pkt + indx,
1093                              next_header_field_len) < 0)
1094         {
1095           FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcpplus_session_trlr);
1096           goto cleanup;
1097         }
1098       indx += next_header_field_len;
1099     }
1100 
1101   if (authentication_code_len)
1102     {
1103       if (fiid_obj_set_data (obj_rmcpplus_session_trlr,
1104                              "authentication_code",
1105                              pkt + indx,
1106                              authentication_code_len) < 0)
1107         {
1108           FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcpplus_session_trlr);
1109           goto cleanup;
1110         }
1111       indx += authentication_code_len;
1112     }
1113 
1114 
1115   if (ipmi_obj_dump (fd,
1116                      prefix,
1117                      session_trailer_hdr,
1118                      NULL,
1119                      obj_rmcpplus_session_trlr) < 0)
1120     {
1121       ERRNO_TRACE (errno);
1122       goto cleanup;
1123     }
1124 
1125   rv = indx;
1126  cleanup:
1127   fiid_obj_destroy (obj_rmcpplus_session_trlr);
1128   return (rv);
1129 }
1130 
1131 static int
1132 _ipmi_dump_rmcpplus_packet (int fd,
1133                             const char *prefix,
1134                             const char *hdr,
1135                             const char *trlr,
1136                             uint8_t authentication_algorithm,
1137                             uint8_t integrity_algorithm,
1138                             uint8_t confidentiality_algorithm,
1139                             const void *integrity_key,
1140                             unsigned int integrity_key_len,
1141                             const void *confidentiality_key,
1142                             unsigned int confidentiality_key_len,
1143                             const void *pkt,
1144                             unsigned int pkt_len,
1145                             fiid_template_t tmpl_lan_msg_hdr,
1146                             fiid_template_t tmpl_cmd,
1147                             fiid_template_t tmpl_ipmb_msg_hdr,
1148                             fiid_template_t tmpl_ipmb_cmd)
1149 {
1150   int obj_rmcp_hdr_len, obj_len, ret, rv = -1;
1151   uint8_t payload_type = 0, payload_authenticated = 0, payload_encrypted = 0;
1152   uint32_t session_id = 0;
1153   uint16_t ipmi_payload_len = 0;
1154   char prefix_buf[IPMI_DEBUG_MAX_PREFIX_LEN];
1155   fiid_obj_t obj_rmcp_hdr = NULL;
1156   fiid_obj_t obj_unexpected_data = NULL;
1157   char *rmcp_hdr =
1158     "RMCP Header:\n"
1159     "------------";
1160   char *session_hdr =
1161     "IPMI RMCPPLUS Session Header:\n"
1162     "-----------------------------";
1163   char *payload_hdr =
1164     "IPMI RMCPPLUS Payload:\n"
1165     "----------------------";
1166   char *msg_hdr =
1167     "IPMI Message Header:\n"
1168     "--------------------";
1169   char *cmd_hdr =
1170     "IPMI Command Data:\n"
1171     "------------------";
1172   char *ipmb_msg_hdr =
1173     "IPMB Message Header:\n"
1174     "--------------------";
1175   char *ipmb_cmd_hdr =
1176     "IPMB Message Data:\n"
1177     "------------------";
1178   char *ipmb_msg_trlr_hdr =
1179     "IPMB Message Trailer:\n"
1180     "---------------------";
1181   char *trailer_hdr =
1182     "IPMI Trailer:\n"
1183     "-------------";
1184   char *session_trailer_hdr =
1185     "IPMI RMCPPLUS Session Trailer:\n"
1186     "------------------------------";
1187   char *extra_hdr =
1188     "Unexpected Data:\n"
1189     "----------------";
1190   unsigned int indx = 0;
1191 
1192   assert (pkt);
1193   assert (IPMI_AUTHENTICATION_ALGORITHM_SUPPORTED (authentication_algorithm));
1194   assert (IPMI_INTEGRITY_ALGORITHM_SUPPORTED (integrity_algorithm));
1195   assert (IPMI_CONFIDENTIALITY_ALGORITHM_SUPPORTED (confidentiality_algorithm));
1196   assert (!(confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_AES_CBC_128
1197             && !(confidentiality_key
1198                  && confidentiality_key_len)));
1199   assert (tmpl_cmd);
1200 
1201   if (debug_set_prefix (prefix_buf, IPMI_DEBUG_MAX_PREFIX_LEN, prefix) < 0)
1202     {
1203       ERRNO_TRACE (errno);
1204       goto cleanup;
1205     }
1206 
1207   if (debug_output_str (fd, prefix_buf, hdr) < 0)
1208     {
1209       ERRNO_TRACE (errno);
1210       goto cleanup;
1211     }
1212 
1213   /* Dump rmcp header */
1214 
1215   if (!(obj_rmcp_hdr = fiid_obj_create (tmpl_rmcp_hdr)))
1216     {
1217       ERRNO_TRACE (errno);
1218       goto cleanup;
1219     }
1220 
1221   if ((obj_rmcp_hdr_len = fiid_obj_set_all (obj_rmcp_hdr,
1222                                             pkt + indx,
1223                                             pkt_len - indx)) < 0)
1224     {
1225       FIID_OBJECT_ERROR_TO_ERRNO (obj_rmcp_hdr);
1226       goto cleanup;
1227     }
1228   indx += obj_rmcp_hdr_len;
1229 
1230   if (ipmi_obj_dump (fd,
1231                      prefix,
1232                      rmcp_hdr,
1233                      NULL,
1234                      obj_rmcp_hdr) < 0)
1235     {
1236       ERRNO_TRACE (errno);
1237       goto cleanup;
1238     }
1239 
1240   if (pkt_len <= indx)
1241     goto out;
1242 
1243   /* Dump rmcpplus session header */
1244 
1245   if ((obj_len = _dump_rmcpplus_session_hdr (fd,
1246                                              prefix,
1247                                              session_hdr,
1248                                              pkt + indx,
1249                                              pkt_len - indx,
1250                                              &payload_type,
1251                                              &payload_authenticated,
1252                                              &payload_encrypted,
1253                                              &session_id,
1254                                              &ipmi_payload_len)) < 0)
1255     {
1256       ERRNO_TRACE (errno);
1257       goto cleanup;
1258     }
1259 
1260   /* don't know how to parse, dump as just big blob of hex */
1261   if (!obj_len)
1262     goto dump_extra;
1263 
1264   indx += obj_len;
1265 
1266   if (pkt_len <= indx)
1267     goto out;
1268 
1269   /* achu: If the packet is really messed up, dump the packet in raw form */
1270   if ((payload_type != IPMI_PAYLOAD_TYPE_IPMI
1271        && payload_type != IPMI_PAYLOAD_TYPE_SOL
1272        && payload_type != IPMI_PAYLOAD_TYPE_RMCPPLUS_OPEN_SESSION_REQUEST
1273        && payload_type != IPMI_PAYLOAD_TYPE_RMCPPLUS_OPEN_SESSION_RESPONSE
1274        && payload_type != IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_1
1275        && payload_type != IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_2
1276        && payload_type != IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_3
1277        && payload_type != IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_4)
1278       || !IPMI_AUTHENTICATION_ALGORITHM_SUPPORTED (authentication_algorithm)
1279       || !IPMI_INTEGRITY_ALGORITHM_SUPPORTED (integrity_algorithm)
1280       || !IPMI_CONFIDENTIALITY_ALGORITHM_SUPPORTED (confidentiality_algorithm)
1281       || !ipmi_payload_len)
1282     goto dump_extra;
1283 
1284   if (payload_type == IPMI_PAYLOAD_TYPE_IPMI)
1285     {
1286       if (!tmpl_lan_msg_hdr
1287           || (fiid_template_compare (tmpl_lan_msg_hdr,
1288                                      tmpl_lan_msg_hdr_rq) != 1
1289               && fiid_template_compare (tmpl_lan_msg_hdr,
1290                                         tmpl_lan_msg_hdr_rs) != 1))
1291         {
1292           SET_ERRNO (EINVAL);
1293           goto cleanup;
1294         }
1295     }
1296   else if (payload_type == IPMI_PAYLOAD_TYPE_SOL)
1297     {
1298       if (fiid_template_compare (tmpl_cmd,
1299                                  tmpl_sol_payload_data) != 1
1300           && fiid_template_compare (tmpl_cmd,
1301                                     tmpl_sol_payload_data_remote_console_to_bmc) != 1
1302           && fiid_template_compare (tmpl_cmd,
1303                                     tmpl_sol_payload_data_bmc_to_remote_console) != 1)
1304         {
1305           SET_ERRNO (EINVAL);
1306           goto cleanup;
1307         }
1308     }
1309   else if (payload_type == IPMI_PAYLOAD_TYPE_RMCPPLUS_OPEN_SESSION_REQUEST)
1310     {
1311       if (fiid_template_compare (tmpl_cmd, tmpl_rmcpplus_open_session_request) != 1)
1312         {
1313           SET_ERRNO (EINVAL);
1314           goto cleanup;
1315         }
1316     }
1317   else if (payload_type == IPMI_PAYLOAD_TYPE_RMCPPLUS_OPEN_SESSION_RESPONSE)
1318     {
1319       if (fiid_template_compare (tmpl_cmd, tmpl_rmcpplus_open_session_response) != 1)
1320         {
1321           SET_ERRNO (EINVAL);
1322           goto cleanup;
1323         }
1324     }
1325   else if (payload_type == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_1)
1326     {
1327       if (fiid_template_compare (tmpl_cmd, tmpl_rmcpplus_rakp_message_1) != 1)
1328         {
1329           SET_ERRNO (EINVAL);
1330           goto cleanup;
1331         }
1332     }
1333   else if (payload_type == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_2)
1334     {
1335       if (fiid_template_compare (tmpl_cmd, tmpl_rmcpplus_rakp_message_2) != 1)
1336         {
1337           SET_ERRNO (EINVAL);
1338           goto cleanup;
1339         }
1340     }
1341   else if (payload_type == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_3)
1342     {
1343       if (fiid_template_compare (tmpl_cmd, tmpl_rmcpplus_rakp_message_3) != 1)
1344         {
1345           SET_ERRNO (EINVAL);
1346           goto cleanup;
1347         }
1348     }
1349   else if (payload_type == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_4)
1350     {
1351       if (fiid_template_compare (tmpl_cmd, tmpl_rmcpplus_rakp_message_4) != 1)
1352         {
1353           SET_ERRNO (EINVAL);
1354           goto cleanup;
1355         }
1356     }
1357 
1358   /* Dump Payload */
1359 
1360   if ((ret = _dump_rmcpplus_payload (fd,
1361                                      prefix,
1362                                      payload_hdr,
1363                                      msg_hdr,
1364                                      cmd_hdr,
1365                                      ipmb_msg_hdr,
1366                                      ipmb_cmd_hdr,
1367                                      ipmb_msg_trlr_hdr,
1368                                      trailer_hdr,
1369                                      payload_type,
1370                                      authentication_algorithm,
1371                                      confidentiality_algorithm,
1372                                      tmpl_lan_msg_hdr,
1373                                      tmpl_cmd,
1374                                      tmpl_ipmb_msg_hdr,
1375                                      tmpl_ipmb_cmd,
1376                                      confidentiality_key,
1377                                      confidentiality_key_len,
1378                                      pkt + indx,
1379                                      ipmi_payload_len)) < 0)
1380     {
1381       ERRNO_TRACE (errno);
1382       goto cleanup;
1383     }
1384 
1385   /* don't know how to parse, dump as just big blob of hex */
1386   if (!ret)
1387     goto dump_extra;
1388 
1389   indx += ipmi_payload_len;
1390 
1391   if (pkt_len <= indx)
1392     goto out;
1393 
1394   /* Dump trailer */
1395 
1396   if ((obj_len = _dump_rmcpplus_session_trlr (fd,
1397                                               prefix,
1398                                               session_trailer_hdr,
1399                                               session_id,
1400                                               payload_authenticated,
1401                                               integrity_algorithm,
1402                                               pkt + indx,
1403                                               pkt_len - indx)) < 0)
1404     {
1405       ERRNO_TRACE (errno);
1406       goto cleanup;
1407     }
1408 
1409   /* don't know how to parse, dump as just big blob of hex */
1410   if (!obj_len)
1411     goto dump_extra;
1412 
1413   indx += obj_len;
1414 
1415   /* Dump extra stuff if packet is longer than expected */
1416  dump_extra:
1417   if ((pkt_len - indx) > 0)
1418     {
1419       if (!(obj_unexpected_data = fiid_obj_create (tmpl_unexpected_data)))
1420         {
1421           ERRNO_TRACE (errno);
1422           goto cleanup;
1423         }
1424 
1425       if ((obj_len = fiid_obj_set_all (obj_unexpected_data,
1426                                        pkt + indx,
1427                                        pkt_len - indx)) < 0)
1428         {
1429           FIID_OBJECT_ERROR_TO_ERRNO (obj_unexpected_data);
1430           goto cleanup;
1431         }
1432       indx += obj_len;
1433 
1434       if (ipmi_obj_dump (fd,
1435                          prefix,
1436                          extra_hdr,
1437                          NULL,
1438                          obj_unexpected_data) < 0)
1439         {
1440           ERRNO_TRACE (errno);
1441           goto cleanup;
1442         }
1443     }
1444 
1445   if (debug_output_str (fd, prefix_buf, trlr) < 0)
1446     {
1447       ERRNO_TRACE (errno);
1448       goto cleanup;
1449     }
1450 
1451  out:
1452 #if WITH_RAWDUMPS
1453   /* For those vendors that get confused when they see the nice output
1454    * and want the hex output
1455    */
1456   if (ipmi_dump_hex (fd,
1457                      prefix,
1458                      hdr,
1459                      trlr,
1460                      pkt,
1461                      pkt_len) < 0)
1462     {
1463       ERRNO_TRACE (errno);
1464       goto cleanup;
1465     }
1466 #endif
1467 
1468   rv = 0;
1469  cleanup:
1470   fiid_obj_destroy (obj_rmcp_hdr);
1471   fiid_obj_destroy (obj_unexpected_data);
1472   return (rv);
1473 }
1474 
1475 int
1476 ipmi_dump_rmcpplus_packet (int fd,
1477                            const char *prefix,
1478                            const char *hdr,
1479                            const char *trlr,
1480                            uint8_t authentication_algorithm,
1481                            uint8_t integrity_algorithm,
1482                            uint8_t confidentiality_algorithm,
1483                            const void *integrity_key,
1484                            unsigned int integrity_key_len,
1485                            const void *confidentiality_key,
1486                            unsigned int confidentiality_key_len,
1487                            const void *pkt,
1488                            unsigned int pkt_len,
1489                            fiid_template_t tmpl_lan_msg_hdr,
1490                            fiid_template_t tmpl_cmd)
1491 {
1492   if (!pkt
1493       || !IPMI_AUTHENTICATION_ALGORITHM_SUPPORTED (authentication_algorithm)
1494       || !IPMI_INTEGRITY_ALGORITHM_SUPPORTED (integrity_algorithm)
1495       || !IPMI_CONFIDENTIALITY_ALGORITHM_SUPPORTED (confidentiality_algorithm)
1496       || (confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_AES_CBC_128
1497           && (!confidentiality_key
1498               || !confidentiality_key_len))
1499       || !tmpl_cmd)
1500     {
1501       SET_ERRNO (EINVAL);
1502       return (-1);
1503     }
1504 
1505   return (_ipmi_dump_rmcpplus_packet (fd,
1506                                       prefix,
1507                                       hdr,
1508                                       trlr,
1509                                       authentication_algorithm,
1510                                       integrity_algorithm,
1511                                       confidentiality_algorithm,
1512                                       integrity_key,
1513                                       integrity_key_len,
1514                                       confidentiality_key,
1515                                       confidentiality_key_len,
1516                                       pkt,
1517                                       pkt_len,
1518                                       tmpl_lan_msg_hdr,
1519                                       tmpl_cmd,
1520                                       NULL,
1521                                       NULL));
1522 }
1523 
1524 int
1525 ipmi_dump_rmcpplus_packet_ipmb (int fd,
1526                                 const char *prefix,
1527                                 const char *hdr,
1528                                 const char *trlr,
1529                                 uint8_t authentication_algorithm,
1530                                 uint8_t integrity_algorithm,
1531                                 uint8_t confidentiality_algorithm,
1532                                 const void *integrity_key,
1533                                 unsigned int integrity_key_len,
1534                                 const void *confidentiality_key,
1535                                 unsigned int confidentiality_key_len,
1536                                 const void *pkt,
1537                                 unsigned int pkt_len,
1538                                 fiid_template_t tmpl_lan_msg_hdr,
1539                                 fiid_template_t tmpl_cmd,
1540                                 fiid_template_t tmpl_ipmb_msg_hdr,
1541                                 fiid_template_t tmpl_ipmb_cmd)
1542 {
1543   int ret1, ret2;
1544 
1545   if (!pkt
1546       || !IPMI_AUTHENTICATION_ALGORITHM_SUPPORTED (authentication_algorithm)
1547       || !IPMI_INTEGRITY_ALGORITHM_SUPPORTED (integrity_algorithm)
1548       || !IPMI_CONFIDENTIALITY_ALGORITHM_SUPPORTED (confidentiality_algorithm)
1549       || (confidentiality_algorithm == IPMI_CONFIDENTIALITY_ALGORITHM_AES_CBC_128
1550           && (!confidentiality_key
1551               || !confidentiality_key_len))
1552       || !tmpl_cmd
1553       || !tmpl_ipmb_msg_hdr
1554       || !tmpl_ipmb_cmd)
1555     {
1556       SET_ERRNO (EINVAL);
1557       return (-1);
1558     }
1559 
1560   if ((ret1 = fiid_template_compare (tmpl_cmd, tmpl_cmd_send_message_rq)) < 0)
1561     return (-1);
1562 
1563   if ((ret2 = fiid_template_compare (tmpl_cmd, tmpl_cmd_get_message_rs)) < 0)
1564     return (-1);
1565 
1566   if (!ret1 && !ret2)
1567     {
1568       SET_ERRNO (EINVAL);
1569       return (-1);
1570     }
1571 
1572   return (_ipmi_dump_rmcpplus_packet (fd,
1573                                       prefix,
1574                                       hdr,
1575                                       trlr,
1576                                       authentication_algorithm,
1577                                       integrity_algorithm,
1578                                       confidentiality_algorithm,
1579                                       integrity_key,
1580                                       integrity_key_len,
1581                                       confidentiality_key,
1582                                       confidentiality_key_len,
1583                                       pkt,
1584                                       pkt_len,
1585                                       tmpl_lan_msg_hdr,
1586                                       tmpl_cmd,
1587                                       tmpl_ipmb_msg_hdr,
1588                                       tmpl_ipmb_cmd));
1589 }
1590