ID: 3611254 - OEM handle for Intel 82751 in SPT mode

Intel 82751 MAC has several deviations in its RMCP+ implementation while working
in the super pass-through mode.
This patch adds a OEM handle which allows IPMItool succesfully interract with
boards equipped with this NIC.

Commit for Dmitry Bazhenov
This commit is contained in:
Zdenek Styblik 2013-05-28 04:18:22 +00:00
parent 38d71179e9
commit 0cea01e42f
5 changed files with 112 additions and 73 deletions

View File

@ -63,6 +63,10 @@ static struct ipmi_oem_handle ipmi_oem_list[] = {
desc: "IBM OEM support",
setup: ipmi_oem_ibm,
},
{
name: "i82571spt",
desc: "Intel 82571 MAC with integrated RMCP+ support in super pass-through mode",
},
{ 0 }
};

View File

@ -1568,43 +1568,45 @@ ipmi_sol_red_pill(struct ipmi_intf * intf, int instance)
FD_SET(0, &read_fds);
FD_SET(intf->fd, &read_fds);
/* Send periodic keepalive packet */
if(_use_sol_for_keepalive == 0)
if (!ipmi_oem_active(intf,"i82571spt"))
{
keepAliveRet = ipmi_sol_keepalive_using_getdeviceid(intf);
}
else
{
keepAliveRet = ipmi_sol_keepalive_using_sol(intf);
}
if (keepAliveRet != 0)
{
/*
* Retrying the keep Alive before declaring a communication
* lost state with the IPMC. Helpful when the payload is
* reset and brings down the connection temporarily. Otherwise,
* if we send getDevice Id to check the status of IPMC during
* this down time when the connection is restarting, SOL will
* exit even though the IPMC is available and the session is open.
*/
if (retrySol == MAX_SOL_RETRY)
/* Send periodic keepalive packet */
if(_use_sol_for_keepalive == 0)
{
/* no response to Get Device ID keepalive message */
bShouldExit = 1;
continue;
keepAliveRet = ipmi_sol_keepalive_using_getdeviceid(intf);
}
else
{
retrySol++;
keepAliveRet = ipmi_sol_keepalive_using_sol(intf);
}
}
else
{
/* if the keep Alive is successful reset retries to zero */
retrySol = 0;
}
if (keepAliveRet != 0)
{
/*
* Retrying the keep Alive before declaring a communication
* lost state with the IPMC. Helpful when the payload is
* reset and brings down the connection temporarily. Otherwise,
* if we send getDevice Id to check the status of IPMC during
* this down time when the connection is restarting, SOL will
* exit even though the IPMC is available and the session is open.
*/
if (retrySol == MAX_SOL_RETRY)
{
/* no response to Get Device ID keepalive message */
bShouldExit = 1;
continue;
}
else
{
retrySol++;
}
}
else
{
/* if the keep Alive is successful reset retries to zero */
retrySol = 0;
}
} /* !oem="i82571spt" */
/* Wait up to half a second */
tv.tv_sec = 0;
tv.tv_usec = 500000;
@ -1757,6 +1759,20 @@ ipmi_sol_activate(struct ipmi_intf * intf, int looptest, int interval,
if (ipmi_oem_active(intf, "intelplus")) {
data[2] |= IPMI_SOL_BMC_ASSERTS_CTS_MASK_TRUE;
} else if (ipmi_oem_active(intf, "i82571spt")) {
/*
* A quote from Intel: "Engineering believes the problem
* lies within the Auxiliary data being sent with the
* 'Activate Payload' command from IPMITool. IPMITool
* sends a C6h which sets some bits having to do with
* encryption and some behavior dealing with CTS DCD/DSR.
* I recommend that the customer modify this request
* to send 08h instead. This is what our internal utility
* sends and it works without issue. I will work with
* engineering to ensure the settings that IPMITool uses
* (C6h) are supported in the future.
*/
data[2] = 0x08;
} else {
data[2] |= IPMI_SOL_BMC_ASSERTS_CTS_MASK_FALSE;
}

View File

@ -3164,7 +3164,7 @@ ipmi_lanplus_rakp3(struct ipmi_intf * intf)
}
/* Generate our Session Integrity Key, K1, and K2 */
if (lanplus_generate_sik(session))
if (lanplus_generate_sik(session, intf))
{
/* Error */
lprintf(LOG_INFO, "> Error generating session integrity key");
@ -3417,7 +3417,8 @@ ipmi_lanplus_open(struct ipmi_intf * intf)
*
* I'm not sure why we accept a failure for the first call
*/
if (ipmi_get_auth_capabilities_cmd(intf, &auth_cap)) {
if (!ipmi_oem_active(intf, "i82571spt") &&
ipmi_get_auth_capabilities_cmd(intf, &auth_cap)) {
sleep(1);
if (ipmi_get_auth_capabilities_cmd(intf, &auth_cap));
{
@ -3427,7 +3428,7 @@ ipmi_lanplus_open(struct ipmi_intf * intf)
}
}
if (! auth_cap.v20_data_available)
if (!ipmi_oem_active(intf, "i82571spt") && ! auth_cap.v20_data_available)
{
lprintf(LOG_INFO, "This BMC does not support IPMI v2 / RMCP+");
goto fail;
@ -3462,11 +3463,11 @@ ipmi_lanplus_open(struct ipmi_intf * intf)
lprintf(LOG_DEBUG, "IPMIv2 / RMCP+ SESSION OPENED SUCCESSFULLY\n");
rc = ipmi_set_session_privlvl_cmd(intf);
if (rc < 0)
goto fail;
if (!ipmi_oem_active(intf, "i82571spt")) {
rc = ipmi_set_session_privlvl_cmd(intf);
if (rc < 0)
goto fail;
}
intf->manufacturer_id = ipmi_get_oem(intf);
bridgePossible = 1;

View File

@ -68,9 +68,9 @@
* return 0 on success (the authcode matches)
* 1 on failure (the authcode does not match)
*/
int lanplus_rakp2_hmac_matches(const struct ipmi_session * session,
const uint8_t * bmc_mac,
struct ipmi_intf * intf)
int
lanplus_rakp2_hmac_matches(const struct ipmi_session * session,
const uint8_t * bmc_mac, struct ipmi_intf * intf)
{
uint8_t * buffer;
int bufferLength, i;
@ -153,6 +153,15 @@ int lanplus_rakp2_hmac_matches(const struct ipmi_session * session,
/* ROLEm */
buffer[56] = session->v2_data.requested_role;
if (ipmi_oem_active(intf, "i82571spt")) {
/*
* The HMAC calculation code in the Intel 82571 GbE
* skips this bit! Looks like a GbE bug, but we need
* to work around it here anyway...
*/
buffer[56] &= ~0x10;
}
/* ULENGTHm */
buffer[57] = strlen((const char *)session->username);
@ -213,9 +222,9 @@ int lanplus_rakp2_hmac_matches(const struct ipmi_session * session,
* 0 on failure (the authcode does not match)
*
*/
int lanplus_rakp4_hmac_matches(const struct ipmi_session * session,
const uint8_t * bmc_mac,
struct ipmi_intf * intf)
int
lanplus_rakp4_hmac_matches(const struct ipmi_session * session,
const uint8_t * bmc_mac, struct ipmi_intf * intf)
{
uint8_t * buffer;
int bufferLength, i;
@ -341,10 +350,10 @@ int lanplus_rakp4_hmac_matches(const struct ipmi_session * session,
* returns 0 on success
* 1 on failure
*/
int lanplus_generate_rakp3_authcode(uint8_t * output_buffer,
const struct ipmi_session * session,
uint32_t * mac_length,
struct ipmi_intf * intf)
int
lanplus_generate_rakp3_authcode(uint8_t * output_buffer,
const struct ipmi_session * session,
uint32_t * mac_length, struct ipmi_intf * intf)
{
int ret = 0;
int input_buffer_length, i;
@ -396,7 +405,7 @@ int lanplus_generate_rakp3_authcode(uint8_t * output_buffer
memcpy(input_buffer + 16, &SIDm_lsbf, 4);
/* ROLEm */
if (ipmi_oem_active(intf, "intelplus"))
if (ipmi_oem_active(intf, "intelplus") || ipmi_oem_active(intf, "i82571spt"))
input_buffer[20] = session->privlvl;
else
input_buffer[20] = session->v2_data.requested_role;
@ -460,7 +469,8 @@ int lanplus_generate_rakp3_authcode(uint8_t * output_buffer
* returns 0 on success
* 1 on failure
*/
int lanplus_generate_sik(struct ipmi_session * session)
int
lanplus_generate_sik(struct ipmi_session * session, struct ipmi_intf * intf)
{
uint8_t * input_buffer;
int input_buffer_length, i;
@ -516,6 +526,15 @@ int lanplus_generate_sik(struct ipmi_session * session)
/* ROLEm */
input_buffer[32] = session->v2_data.requested_role;
if (ipmi_oem_active(intf, "i82571spt")) {
/*
* The HMAC calculation code in the Intel 82571 GbE
* skips this bit! Looks like a GbE bug, but we need
* to work around it here anyway...
*/
input_buffer[32] &= ~0x10;
}
/* ULENGTHm */
input_buffer[33] = strlen((const char *)session->username);
@ -580,7 +599,8 @@ int lanplus_generate_sik(struct ipmi_session * session)
* returns 0 on success
* 1 on failure
*/
int lanplus_generate_k1(struct ipmi_session * session)
int
lanplus_generate_k1(struct ipmi_session * session)
{
uint32_t mac_length;
@ -623,7 +643,8 @@ int lanplus_generate_k1(struct ipmi_session * session)
* returns 0 on success
* 1 on failure
*/
int lanplus_generate_k2(struct ipmi_session * session)
int
lanplus_generate_k2(struct ipmi_session * session)
{
uint32_t mac_length;
@ -673,12 +694,11 @@ int lanplus_generate_k2(struct ipmi_session * session)
* returns 0 on success
* 1 on failure
*/
int lanplus_encrypt_payload(uint8_t crypt_alg,
const uint8_t * key,
const uint8_t * input,
uint32_t input_length,
uint8_t * output,
uint16_t * bytes_written)
int
lanplus_encrypt_payload(uint8_t crypt_alg,
const uint8_t * key, const uint8_t * input,
uint32_t input_length, uint8_t * output,
uint16_t * bytes_written)
{
uint8_t * padded_input;
uint32_t mod, i, bytes_encrypted;
@ -777,12 +797,12 @@ int lanplus_encrypt_payload(uint8_t crypt_alg,
* returns 1 on success (authcode is valid)
* 0 on failure (autchode integrity check failed)
*/
int lanplus_has_valid_auth_code(struct ipmi_rs * rs,
struct ipmi_session * session)
int
lanplus_has_valid_auth_code(struct ipmi_rs * rs, struct ipmi_session * session)
{
uint8_t * bmc_authcode;
uint8_t generated_authcode[IPMI_MAX_MAC_SIZE];
uint32_t generated_authcode_length;
uint8_t generated_authcode[IPMI_MAX_MAC_SIZE];
uint32_t generated_authcode_length;
if ((rs->session.authtype != IPMI_SESSION_AUTHTYPE_RMCP_PLUS) ||
@ -837,12 +857,10 @@ int lanplus_has_valid_auth_code(struct ipmi_rs * rs,
* returns 0 on success (we were able to successfully decrypt the packet)
* 1 on failure (we were unable to successfully decrypt the packet)
*/
int lanplus_decrypt_payload(uint8_t crypt_alg,
const uint8_t * key,
const uint8_t * input,
uint32_t input_length,
uint8_t * output,
uint16_t * payload_size)
int
lanplus_decrypt_payload(uint8_t crypt_alg, const uint8_t * key,
const uint8_t * input, uint32_t input_length,
uint8_t * output, uint16_t * payload_size)
{
uint8_t * decrypted_payload;
uint32_t bytes_decrypted;
@ -897,7 +915,7 @@ int lanplus_decrypt_payload(uint8_t crypt_alg,
*/
for (i = 0; i < conf_pad_length; ++i)
{
if (decrypted_payload[*payload_size + i] == i)
if (decrypted_payload[*payload_size + i] != (i + 1))
{
lprintf(LOG_ERR, "Malformed payload padding");
assert(0);

View File

@ -51,7 +51,7 @@ int lanplus_generate_rakp3_authcode(uint8_t * buffer,
const struct ipmi_session * session,
uint32_t * auth_length,
struct ipmi_intf * intf);
int lanplus_generate_sik(struct ipmi_session * session);
int lanplus_generate_sik(struct ipmi_session * session, struct ipmi_intf * intf);
int lanplus_generate_k1(struct ipmi_session * session);
int lanplus_generate_k2(struct ipmi_session * session);
int lanplus_encrypt_payload(uint8_t crypt_alg,