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 #ifndef IPMI_RMCPPLUS_INTERFACE_H
20 #define IPMI_RMCPPLUS_INTERFACE_H
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 
26 #include <stdint.h>
27 #include <freeipmi/fiid/fiid.h>
28 
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 
32 /**************************
33 * IPMI 2.0 Payload Types *
34 **************************/
35 
36 #define IPMI_PAYLOAD_TYPE_IPMI                            0x00
37 #define IPMI_PAYLOAD_TYPE_SOL                             0x01
38 #define IPMI_PAYLOAD_TYPE_OEM_EXPLICIT                    0x02
39 #define IPMI_PAYLOAD_TYPE_RMCPPLUS_OPEN_SESSION_REQUEST   0x10
40 #define IPMI_PAYLOAD_TYPE_RMCPPLUS_OPEN_SESSION_RESPONSE  0x11
41 #define IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_1                  0x12
42 #define IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_2                  0x13
43 #define IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_3                  0x14
44 #define IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_4                  0x15
45 /* 20h - 27h - OEM */
46 /* all other reserved */
47 
48 #define IPMI_PAYLOAD_TYPE_VALID(__payload_type)                             \
49   (((__payload_type) == IPMI_PAYLOAD_TYPE_IPMI                              \
50     || (__payload_type) == IPMI_PAYLOAD_TYPE_SOL                            \
51     || (__payload_type) == IPMI_PAYLOAD_TYPE_OEM_EXPLICIT                   \
52     || (__payload_type) == IPMI_PAYLOAD_TYPE_RMCPPLUS_OPEN_SESSION_REQUEST  \
53     || (__payload_type) == IPMI_PAYLOAD_TYPE_RMCPPLUS_OPEN_SESSION_RESPONSE \
54     || (__payload_type) == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_1                 \
55     || (__payload_type) == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_2                 \
56     || (__payload_type) == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_3                 \
57     || (__payload_type) == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_4) ? 1 : 0)
58 
59 #define IPMI_PAYLOAD_TYPE_SESSION_SETUP(__payload_type)                     \
60   (((__payload_type) == IPMI_PAYLOAD_TYPE_RMCPPLUS_OPEN_SESSION_REQUEST     \
61     || (__payload_type) == IPMI_PAYLOAD_TYPE_RMCPPLUS_OPEN_SESSION_RESPONSE \
62     || (__payload_type) == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_1                 \
63     || (__payload_type) == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_2                 \
64     || (__payload_type) == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_3                 \
65     || (__payload_type) == IPMI_PAYLOAD_TYPE_RAKP_MESSAGE_4) ? 1 : 0)
66 
67 /**************************
68 * IPMI 2.0 Payload Flags *
69 **************************/
70 #define IPMI_PAYLOAD_FLAG_UNENCRYPTED                      0x0
71 #define IPMI_PAYLOAD_FLAG_ENCRYPTED                        0x1
72 #define IPMI_PAYLOAD_FLAG_UNAUTHENTICATED                  0x0
73 #define IPMI_PAYLOAD_FLAG_AUTHENTICATED                    0x1
74 
75 #define IPMI_PAYLOAD_ENCRYPTED_FLAG_VALID(__payload_flag) \
76   (((__payload_flag) == IPMI_PAYLOAD_FLAG_UNENCRYPTED     \
77     || (__payload_flag) == IPMI_PAYLOAD_FLAG_ENCRYPTED) ? 1 : 0)
78 
79 #define IPMI_PAYLOAD_AUTHENTICATED_FLAG_VALID(__payload_flag) \
80   (((__payload_flag) == IPMI_PAYLOAD_FLAG_UNENCRYPTED         \
81     || (__payload_flag) == IPMI_PAYLOAD_FLAG_ENCRYPTED) ? 1 : 0)
82 
83 /*********************************************
84 * IPMI 2.0 Authentication Algorithm Numbers *
85 *********************************************/
86 
87 #define IPMI_AUTHENTICATION_ALGORITHM_RAKP_NONE           0x00
88 #define IPMI_AUTHENTICATION_ALGORITHM_RAKP_HMAC_SHA1      0x01
89 #define IPMI_AUTHENTICATION_ALGORITHM_RAKP_HMAC_MD5       0x02
90 #define IPMI_AUTHENTICATION_ALGORITHM_RAKP_HMAC_SHA256    0x03
91 /* C0h - FFh - OEM */
92 /* all other reserved */
93 
94 #define IPMI_AUTHENTICATION_ALGORITHM_VALID(__algorithm)             \
95   (((__algorithm) == IPMI_AUTHENTICATION_ALGORITHM_RAKP_NONE         \
96     || (__algorithm) == IPMI_AUTHENTICATION_ALGORITHM_RAKP_HMAC_SHA1 \
97     || (__algorithm) == IPMI_AUTHENTICATION_ALGORITHM_RAKP_HMAC_MD5  \
98     || (__algorithm) == IPMI_AUTHENTICATION_ALGORITHM_RAKP_HMAC_SHA256) ? 1 : 0)
99 
100 #define IPMI_AUTHENTICATION_ALGORITHM_SUPPORTED(__algorithm)         \
101   (((__algorithm) == IPMI_AUTHENTICATION_ALGORITHM_RAKP_NONE         \
102     || (__algorithm) == IPMI_AUTHENTICATION_ALGORITHM_RAKP_HMAC_SHA1 \
103     || (__algorithm) == IPMI_AUTHENTICATION_ALGORITHM_RAKP_HMAC_MD5  \
104     || (__algorithm) == IPMI_AUTHENTICATION_ALGORITHM_RAKP_HMAC_SHA256) ? 1 : 0)
105 
106 /****************************************
107 * IPMI 2.0 Integrity Algorithm Numbers *
108 ****************************************/
109 
110 #define IPMI_INTEGRITY_ALGORITHM_NONE                     0x00
111 #define IPMI_INTEGRITY_ALGORITHM_HMAC_SHA1_96             0x01
112 #define IPMI_INTEGRITY_ALGORITHM_HMAC_MD5_128             0x02
113 #define IPMI_INTEGRITY_ALGORITHM_MD5_128                  0x03
114 #define IPMI_INTEGRITY_ALGORITHM_HMAC_SHA256_128          0x04
115 /* C0h - FFh - OEM */
116 /* all other reserved */
117 
118 #define IPMI_INTEGRITY_ALGORITHM_VALID(__algorithm)           \
119   (((__algorithm) == IPMI_INTEGRITY_ALGORITHM_NONE            \
120     || (__algorithm) == IPMI_INTEGRITY_ALGORITHM_HMAC_SHA1_96 \
121     || (__algorithm) == IPMI_INTEGRITY_ALGORITHM_HMAC_MD5_128 \
122     || (__algorithm) == IPMI_INTEGRITY_ALGORITHM_MD5_128      \
123     || (__algorithm) == IPMI_INTEGRITY_ALGORITHM_HMAC_SHA256_128) ? 1 : 0)
124 
125 #define IPMI_INTEGRITY_ALGORITHM_SUPPORTED(__algorithm)       \
126   (((__algorithm) == IPMI_INTEGRITY_ALGORITHM_NONE            \
127     || (__algorithm) == IPMI_INTEGRITY_ALGORITHM_HMAC_SHA1_96 \
128     || (__algorithm) == IPMI_INTEGRITY_ALGORITHM_HMAC_MD5_128 \
129     || (__algorithm) == IPMI_INTEGRITY_ALGORITHM_MD5_128      \
130     || (__algorithm) == IPMI_INTEGRITY_ALGORITHM_HMAC_SHA256_128) ? 1 : 0)
131 
132 /**********************************************
133 * IPMI 2.0 Confidentiality Algorithm Numbers *
134 **********************************************/
135 
136 #define IPMI_CONFIDENTIALITY_ALGORITHM_NONE               0x00
137 #define IPMI_CONFIDENTIALITY_ALGORITHM_AES_CBC_128        0x01
138 #define IPMI_CONFIDENTIALITY_ALGORITHM_XRC4_128           0x02
139 #define IPMI_CONFIDENTIALITY_ALGORITHM_XRC4_40            0x03
140 /* 30h - 3Fh - OEM */
141 /* all other reserved */
142 
143 #define IPMI_CONFIDENTIALITY_ALGORITHM_VALID(__algorithm)           \
144   (((__algorithm) ==  IPMI_CONFIDENTIALITY_ALGORITHM_NONE           \
145     || (__algorithm) ==  IPMI_CONFIDENTIALITY_ALGORITHM_AES_CBC_128 \
146     || (__algorithm) ==  IPMI_CONFIDENTIALITY_ALGORITHM_XRC4_128    \
147     || (__algorithm) == IPMI_CONFIDENTIALITY_ALGORITHM_XRC4_40) ? 1 : 0)
148 
149 #define IPMI_CONFIDENTIALITY_ALGORITHM_SUPPORTED(__algorithm)       \
150   (((__algorithm) ==  IPMI_CONFIDENTIALITY_ALGORITHM_NONE           \
151     || (__algorithm) ==  IPMI_CONFIDENTIALITY_ALGORITHM_AES_CBC_128) ? 1 : 0)
152 
153 /***************************************
154 * IPMI 2.0 Misc Flags and Definitions *
155 ***************************************/
156 
157 #define IPMI_AUTHENTICATION_PAYLOAD_TYPE                  0x00
158 #define IPMI_AUTHENTICATION_PAYLOAD_LENGTH                0x08
159 #define IPMI_INTEGRITY_PAYLOAD_TYPE                       0x01
160 #define IPMI_INTEGRITY_PAYLOAD_LENGTH                     0x08
161 #define IPMI_CONFIDENTIALITY_PAYLOAD_TYPE                 0x02
162 #define IPMI_CONFIDENTIALITY_PAYLOAD_LENGTH               0x08
163 
164 #define IPMI_USER_NAME_PRIVILEGE_LOOKUP                   0x0
165 #define IPMI_NAME_ONLY_LOOKUP                             0x1
166 
167 #define IPMI_USER_NAME_LOOKUP_VALID(__username_lookup_flag)     \
168   (((__username_lookup_flag) == IPMI_USER_NAME_PRIVILEGE_LOOKUP \
169     || (__username_lookup_flag) == IPMI_NAME_ONLY_LOOKUP) ? 1 : 0)
170 
171 #define IPMI_REMOTE_CONSOLE_RANDOM_NUMBER_LENGTH          16
172 #define IPMI_MANAGED_SYSTEM_RANDOM_NUMBER_LENGTH          16
173 #define IPMI_MANAGED_SYSTEM_GUID_LENGTH                   16
174 
175 #define IPMI_NEXT_HEADER                                  0x07
176 
177 #define IPMI_INTEGRITY_PAD_MULTIPLE                       4
178 #define IPMI_INTEGRITY_PAD_DATA                           0xFF
179 
180 #define IPMI_MAX_PAYLOAD_LENGTH                           65536
181 /* achu: b/c ipmi_msg_len is 2 bytes */
182 
183 #define IPMI_HMAC_SHA1_DIGEST_LENGTH                      20
184 #define IPMI_HMAC_MD5_DIGEST_LENGTH                       16
185 #define IPMI_MD5_DIGEST_LENGTH                            16
186 #define IPMI_HMAC_SHA1_96_DIGEST_LENGTH                   12
187 #define IPMI_HMAC_SHA256_DIGEST_LENGTH                    32
188 
189 #define IPMI_HMAC_SHA1_96_AUTHENTICATION_CODE_LENGTH      12
190 #define IPMI_HMAC_MD5_128_AUTHENTICATION_CODE_LENGTH      16
191 #define IPMI_MD5_128_AUTHENTICATION_CODE_LENGTH           16
192 #define IPMI_HMAC_SHA256_128_AUTHENTICATION_CODE_LENGTH   16
193 
194 /* Refer to table 22-19 */
195 /* XXX - Errata 4 defines SHA256 but not cipher suite IDs */
196 /* achu: Intel support says Cipher Suite 15-19 maps to 1-5 using
197  * SHA256 instead of SHA1 and SHA256-128 instead of SHA1-96.
198  */
199 /* Cipher Suite 17 confirmed via DCMI 1.1 specification */
200 #define IPMI_CIPHER_SUITE_ID_MIN                          0
201 #define IPMI_CIPHER_SUITE_ID_MAX                          19
202 
203 /*
204  * fill* functions return 0 on success, -1 on error.
205  *
206  * object must be for the fill function's respective fiid
207  * template.
208  *
209  * assemble/unassemble functions must be passed fiid objects of the
210  * respective expected header/trailer templates.
211  *
212  * see freeipmi/templates/ for template definitions
213  */
214 
215 extern fiid_template_t tmpl_rmcpplus_session_hdr;
216 extern fiid_template_t tmpl_rmcpplus_session_trlr;
217 
218 extern fiid_template_t tmpl_rmcpplus_payload;
219 
220 extern fiid_template_t tmpl_rmcpplus_open_session_request;
221 extern fiid_template_t tmpl_rmcpplus_open_session_response;
222 extern fiid_template_t tmpl_rmcpplus_rakp_message_1;
223 extern fiid_template_t tmpl_rmcpplus_rakp_message_2;
224 extern fiid_template_t tmpl_rmcpplus_rakp_message_3;
225 extern fiid_template_t tmpl_rmcpplus_rakp_message_4;
226 
227 /* ipmi_rmcpplus_init
228  *
229  * Must be called first to initialize crypt libs.  In threaded
230  * programs, must be called before threads are created.
231  *
232  * If errno returned == EPERM, underlying crypt library incompatible.
233  *
234  * Returns 0 on success, -1 on error.
235  */
236 int ipmi_rmcpplus_init (void);
237 
238 int fill_rmcpplus_session_hdr (uint8_t payload_type,
239                                uint8_t payload_authenticated,
240                                uint8_t payload_encrypted,
241                                uint32_t oem_iana,
242                                uint16_t oem_payload_id,
243                                uint32_t session_id,
244                                uint32_t session_sequence_number,
245                                fiid_obj_t obj_rmcpplus_session_hdr);
246 
247 int fill_rmcpplus_session_trlr (fiid_obj_t obj_rmcpplus_session_trlr);
248 
249 int fill_rmcpplus_payload (const void *confidentiality_header,
250                            unsigned int confidentiality_header_len,
251                            const void *payload_data,
252                            unsigned int payload_data_len,
253                            const void *confidentiality_trailer,
254                            unsigned int confidentiality_trailer_len,
255                            fiid_obj_t obj_cmd_rq);
256 
257 int fill_rmcpplus_open_session (uint8_t message_tag,
258                                 uint8_t requested_maximum_privilege_level,
259                                 uint32_t remote_console_session_id,
260                                 uint8_t authentication_algorithm,
261                                 uint8_t integrity_algorithm,
262                                 uint8_t confidentiality_algorithm,
263                                 fiid_obj_t obj_cmd_rq);
264 
265 int fill_rmcpplus_rakp_message_1 (uint8_t message_tag,
266                                   uint32_t managed_system_session_id,
267                                   const void *remote_console_random_number,
268                                   unsigned int remote_console_random_number_len,
269                                   uint8_t requested_maximum_privilege_level,
270                                   uint8_t name_only_lookup_flag,
271                                   const char *username,
272                                   unsigned int username_len,
273                                   fiid_obj_t obj_cmd_rq);
274 
275 int fill_rmcpplus_rakp_message_3 (uint8_t message_tag,
276                                   uint8_t rmcpplus_status_code,
277                                   uint32_t managed_system_session_id,
278                                   const void *key_exchange_authentication_code,
279                                   unsigned int key_exchange_authentication_code_len,
280                                   fiid_obj_t obj_cmd_rq);
281 
282 /* returns length written to pkt on success, -1 on error */
283 int assemble_ipmi_rmcpplus_pkt (uint8_t authentication_algorithm,
284                                 uint8_t integrity_algorithm,
285                                 uint8_t confidentiality_algorithm,
286                                 const void *integrity_key,
287                                 unsigned int integrity_key_len,
288                                 const void *confidentiality_key,
289                                 unsigned int confidentiality_key_len,
290                                 const void *authentication_code_data,
291                                 unsigned int authentication_code_data_len,
292                                 fiid_obj_t obj_rmcp_hdr,
293                                 fiid_obj_t obj_rmcpplus_session_hdr,
294                                 fiid_obj_t obj_lan_msg_hdr,
295                                 fiid_obj_t obj_cmd,
296                                 fiid_obj_t obj_rmcpplus_session_trlr,
297                                 void *pkt,
298                                 unsigned int pkt_len,
299                                 unsigned int flags);
300 
301 /* returns 1 if fully unparsed, 0 if not, -1 on error */
302 int unassemble_ipmi_rmcpplus_pkt (uint8_t authentication_algorithm,
303                                   uint8_t integrity_algorithm,
304                                   uint8_t confidentiality_algorithm,
305                                   const void *integrity_key,
306                                   unsigned int integrity_key_len,
307                                   const void *confidentiality_key,
308                                   unsigned int confidentiality_key_len,
309                                   const void *pkt,
310                                   unsigned int pkt_len,
311                                   fiid_obj_t obj_rmcp_hdr,
312                                   fiid_obj_t obj_rmcpplus_session_hdr,
313                                   fiid_obj_t obj_rmcpplus_payload,
314                                   fiid_obj_t obj_lan_msg_hdr,
315                                   fiid_obj_t obj_cmd,
316                                   fiid_obj_t obj_lan_msg_trlr,
317                                   fiid_obj_t obj_rmcpplus_session_trlr,
318                                   unsigned int flags);
319 
320 /* returns length sent on success, -1 on error */
321 /* A few extra error checks, but nearly identical to system sendto() */
322 ssize_t ipmi_rmcpplus_sendto (int s,
323                               const void *buf,
324                               size_t len,
325                               int flags,
326                               const struct sockaddr *to,
327                               socklen_t tolen);
328 
329 /* returns length received on success, 0 on orderly shutdown, -1 on error */
330 /* A few extra error checks, but nearly identical to system recvfrom() */
331 ssize_t ipmi_rmcpplus_recvfrom (int s,
332                                 void *buf,
333                                 size_t len,
334                                 int flags,
335                                 struct sockaddr *from,
336                                 socklen_t *fromlen);
337 
338 #ifdef __cplusplus
339 }
340 #endif
341 
342 #endif /* IPMI_RMCPPLUS_INTERFACE_H */
343