mirror of
https://github.com/ipmitool/ipmitool.git
synced 2025-05-10 10:37:22 +00:00
ID:441 - Add support for HMAC_MD5 and HMAC_SHA256
Commit adds support for cipher suites 6/7/8 (HMAC-MD5) and cipher suites 15/16/17 (HMAC_SHA256). This also fixes: * ID:442 - IPMI_AUTH_RAKP_HMAC_MD5 support in lanplus * ID:141 - RMCP+ Cipher-suite 17 not supported Original author Liebig Holger(Fujitsu). Code cleanup done by Florian Breu and Zdenek Styblik.
This commit is contained in:
parent
b74c20c5d5
commit
8ca47f21ca
10
configure.ac
10
configure.ac
@ -164,6 +164,16 @@ AC_CHECK_LIB([crypto], [EVP_aes_128_cbc],
|
||||
fi],
|
||||
[have_crypto=no], [-lcrypto])
|
||||
|
||||
AC_CHECK_LIB([crypto], [EVP_sha256],
|
||||
[if test "x$xenable_internal_sha256" != "xyes"; then
|
||||
if test "x$have_crypto" != "xyes"; then
|
||||
LIBS="$LIBS -lcrypto"
|
||||
have_sha256=yes
|
||||
fi
|
||||
AC_DEFINE(HAVE_CRYPTO_SHA256, [1], [Define to 1 if libcrypto supports SHA256.])
|
||||
fi],
|
||||
[], [-lcrypto])
|
||||
|
||||
AC_CHECK_LIB([crypto], [MD5_Init],
|
||||
[if test "x$xenable_internal_md5" != "xyes"; then
|
||||
if test "x$have_crypto" != "xyes"; then
|
||||
|
@ -46,6 +46,7 @@
|
||||
#endif
|
||||
|
||||
#define IPMI_BUF_SIZE 1024
|
||||
#define IPMI_MAX_MD_SIZE 0x20
|
||||
|
||||
#if HAVE_PRAGMA_PACK
|
||||
#define ATTRIBUTE_PACKING
|
||||
@ -211,13 +212,13 @@ struct ipmi_rs {
|
||||
uint32_t console_id;
|
||||
uint8_t bmc_rand[16]; /* Random number generated by the BMC */
|
||||
uint8_t bmc_guid[16];
|
||||
uint8_t key_exchange_auth_code[20];
|
||||
uint8_t key_exchange_auth_code[IPMI_MAX_MD_SIZE];
|
||||
} rakp2_message;
|
||||
struct {
|
||||
uint8_t message_tag;
|
||||
uint8_t rakp_return_code;
|
||||
uint32_t console_id;
|
||||
uint8_t integrity_check_value[20];
|
||||
uint8_t integrity_check_value[IPMI_MAX_MD_SIZE];
|
||||
} rakp4_message;
|
||||
struct {
|
||||
uint8_t packet_sequence_number;
|
||||
|
@ -118,12 +118,14 @@
|
||||
#define IPMI_AUTH_RAKP_NONE 0x00
|
||||
#define IPMI_AUTH_RAKP_HMAC_SHA1 0x01
|
||||
#define IPMI_AUTH_RAKP_HMAC_MD5 0x02
|
||||
#define IPMI_AUTH_RAKP_HMAC_SHA256 0x03
|
||||
|
||||
/* From table 13-18 of the IPMI v2 specification */
|
||||
#define IPMI_INTEGRITY_NONE 0x00
|
||||
#define IPMI_INTEGRITY_HMAC_SHA1_96 0x01
|
||||
#define IPMI_INTEGRITY_HMAC_MD5_128 0x02
|
||||
#define IPMI_INTEGRITY_MD5_128 0x03
|
||||
#define IPMI_INTEGRITY_HMAC_SHA256_128 0x04
|
||||
|
||||
/* From table 13-19 of the IPMI v2 specfication */
|
||||
#define IPMI_CRYPT_NONE 0x00
|
||||
|
@ -59,7 +59,7 @@ enum LANPLUS_SESSION_STATE {
|
||||
|
||||
|
||||
#define IPMI_AUTHCODE_BUFFER_SIZE 20
|
||||
#define IPMI_SIK_BUFFER_SIZE 20
|
||||
#define IPMI_SIK_BUFFER_SIZE IPMI_MAX_MD_SIZE
|
||||
#define IPMI_KG_BUFFER_SIZE 21 /* key plus null byte */
|
||||
|
||||
struct ipmi_session_params {
|
||||
@ -131,10 +131,13 @@ struct ipmi_session {
|
||||
uint8_t requested_role; /* As sent in the RAKP 1 message */
|
||||
uint8_t rakp2_return_code;
|
||||
|
||||
uint8_t sik[IPMI_SIK_BUFFER_SIZE]; /* Session integrity key */
|
||||
uint8_t kg[IPMI_KG_BUFFER_SIZE]; /* BMC key */
|
||||
uint8_t k1[20]; /* Used for Integrity checking? */
|
||||
uint8_t k2[20]; /* First 16 bytes used for AES */
|
||||
uint8_t sik[IPMI_SIK_BUFFER_SIZE]; /* Session integrity key */
|
||||
uint8_t sik_len; /* Session Integrity key length */
|
||||
uint8_t kg[IPMI_KG_BUFFER_SIZE]; /* BMC key */
|
||||
uint8_t k1[IPMI_MAX_MD_SIZE]; /* Used for Integrity checking? */
|
||||
uint8_t k1_len; /* K1 key length */
|
||||
uint8_t k2[IPMI_MAX_MD_SIZE]; /* First 16 bytes used for AES */
|
||||
uint8_t k2_len; /* K2 key length */
|
||||
} v2_data;
|
||||
|
||||
|
||||
|
@ -621,6 +621,9 @@ const struct valstr ipmi_auth_algorithms[] = {
|
||||
{ IPMI_AUTH_RAKP_NONE, "none" },
|
||||
{ IPMI_AUTH_RAKP_HMAC_SHA1, "hmac_sha1" },
|
||||
{ IPMI_AUTH_RAKP_HMAC_MD5, "hmac_md5" },
|
||||
#ifdef HAVE_CRYPTO_SHA256
|
||||
{ IPMI_AUTH_RAKP_HMAC_SHA256, "hmac_sha256" },
|
||||
#endif /* HAVE_CRYPTO_SHA256 */
|
||||
{ 0x00, NULL }
|
||||
};
|
||||
|
||||
@ -629,6 +632,9 @@ const struct valstr ipmi_integrity_algorithms[] = {
|
||||
{ IPMI_INTEGRITY_HMAC_SHA1_96, "hmac_sha1_96" },
|
||||
{ IPMI_INTEGRITY_HMAC_MD5_128, "hmac_md5_128" },
|
||||
{ IPMI_INTEGRITY_MD5_128 , "md5_128" },
|
||||
#ifdef HAVE_CRYPTO_SHA256
|
||||
{ IPMI_INTEGRITY_HMAC_SHA256_128, "sha256_128" },
|
||||
#endif /* HAVE_CRYPTO_SHA256 */
|
||||
{ 0x00, NULL }
|
||||
};
|
||||
|
||||
|
@ -169,9 +169,14 @@ int lanplus_get_requested_ciphers(int cipher_suite_id,
|
||||
uint8_t * integrity_alg,
|
||||
uint8_t * crypt_alg)
|
||||
{
|
||||
#ifdef HAVE_CRYPTO_SHA256
|
||||
if ((cipher_suite_id < 0) || (cipher_suite_id > 17)) {
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
if ((cipher_suite_id < 0) || (cipher_suite_id > 14))
|
||||
return 1;
|
||||
|
||||
#endif /* HAVE_CRYPTO_SHA256 */
|
||||
/* See table 22-19 for the source of the statement */
|
||||
switch (cipher_suite_id)
|
||||
{
|
||||
@ -250,6 +255,23 @@ int lanplus_get_requested_ciphers(int cipher_suite_id,
|
||||
*integrity_alg = IPMI_INTEGRITY_MD5_128;
|
||||
*crypt_alg = IPMI_CRYPT_XRC4_40;
|
||||
break;
|
||||
#ifdef HAVE_CRYPTO_SHA256
|
||||
case 15:
|
||||
*auth_alg = IPMI_AUTH_RAKP_HMAC_SHA256;
|
||||
*integrity_alg = IPMI_INTEGRITY_NONE;
|
||||
*crypt_alg = IPMI_CRYPT_NONE;
|
||||
break;
|
||||
case 16:
|
||||
*auth_alg = IPMI_AUTH_RAKP_HMAC_SHA256;
|
||||
*integrity_alg = IPMI_INTEGRITY_HMAC_SHA256_128;
|
||||
*crypt_alg = IPMI_CRYPT_NONE;
|
||||
break;
|
||||
case 17:
|
||||
*auth_alg = IPMI_AUTH_RAKP_HMAC_SHA256;
|
||||
*integrity_alg = IPMI_INTEGRITY_HMAC_SHA256_128;
|
||||
*crypt_alg = IPMI_CRYPT_AES_CBC_128;
|
||||
break;
|
||||
#endif /* HAVE_CRYPTO_SHA256 */
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1022,15 +1044,34 @@ read_rakp2_message(
|
||||
break;
|
||||
|
||||
case IPMI_AUTH_RAKP_HMAC_SHA1:
|
||||
/* We need to copy 20 bytes */
|
||||
for (i = 0; i < 20; ++i)
|
||||
rsp->payload.rakp2_message.key_exchange_auth_code[i] =
|
||||
rsp->data[offset + 40 + i];
|
||||
break;
|
||||
/* We need to copy 20 bytes */
|
||||
for (i = 0; i < IPMI_SHA_DIGEST_LENGTH; ++i) {
|
||||
rsp->payload.rakp2_message.key_exchange_auth_code[i] =
|
||||
rsp->data[offset + 40 + i];
|
||||
}
|
||||
break;
|
||||
|
||||
case IPMI_AUTH_RAKP_HMAC_MD5:
|
||||
lprintf(LOG_ERR, "read_rakp2_message: no support for "
|
||||
"IPMI_AUTH_RAKP_HMAC_MD5");
|
||||
/* We need to copy 16 bytes */
|
||||
for (i = 0; i < IPMI_MD5_DIGEST_LENGTH; ++i) {
|
||||
rsp->payload.rakp2_message.key_exchange_auth_code[i] =
|
||||
rsp->data[offset + 40 + i];
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef HAVE_CRYPTO_SHA256
|
||||
case IPMI_AUTH_RAKP_HMAC_SHA256:
|
||||
/* We need to copy 32 bytes */
|
||||
for (i = 0; i < IPMI_SHA256_DIGEST_LENGTH; ++i) {
|
||||
rsp->payload.rakp2_message.key_exchange_auth_code[i] =
|
||||
rsp->data[offset + 40 + i];
|
||||
}
|
||||
break;
|
||||
#endif /* HAVE_CRYPTO_SHA256 */
|
||||
|
||||
default:
|
||||
lprintf(LOG_ERR, "read_rakp2_message: no support "
|
||||
"for authentication algorithm 0x%x", auth_alg);
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
@ -1088,13 +1129,32 @@ read_rakp4_message(
|
||||
break;
|
||||
|
||||
case IPMI_AUTH_RAKP_HMAC_SHA1:
|
||||
/* We need to copy 12 bytes */
|
||||
for (i = 0; i < 12; ++i)
|
||||
rsp->payload.rakp4_message.integrity_check_value[i] =
|
||||
rsp->data[offset + 8 + i];
|
||||
break;
|
||||
/* We need to copy 12 bytes */
|
||||
for (i = 0; i < IPMI_SHA1_AUTHCODE_SIZE; ++i) {
|
||||
rsp->payload.rakp4_message.integrity_check_value[i] =
|
||||
rsp->data[offset + 8 + i];
|
||||
}
|
||||
break;
|
||||
|
||||
case IPMI_AUTH_RAKP_HMAC_MD5:
|
||||
/* We need to copy 16 bytes */
|
||||
for (i = 0; i < IPMI_HMAC_MD5_AUTHCODE_SIZE; ++i) {
|
||||
rsp->payload.rakp4_message.integrity_check_value[i] =
|
||||
rsp->data[offset + 8 + i];
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef HAVE_CRYPTO_SHA256
|
||||
case IPMI_AUTH_RAKP_HMAC_SHA256:
|
||||
/* We need to copy 16 bytes */
|
||||
for (i = 0; i < IPMI_HMAC_SHA256_AUTHCODE_SIZE; ++i) {
|
||||
rsp->payload.rakp4_message.integrity_check_value[i] =
|
||||
rsp->data[offset + 8 + i];
|
||||
}
|
||||
break;
|
||||
#endif /* HAVE_CRYPTO_SHA256 */
|
||||
|
||||
default:
|
||||
lprintf(LOG_ERR, "read_rakp4_message: no support "
|
||||
"for authentication algorithm 0x%x", auth_alg);
|
||||
assert(0);
|
||||
@ -1760,7 +1820,11 @@ ipmi_lanplus_build_v2x_msg(
|
||||
if ((session->v2_data.session_state == LANPLUS_STATE_ACTIVE) &&
|
||||
(session->v2_data.integrity_alg != IPMI_INTEGRITY_NONE))
|
||||
{
|
||||
uint32_t i, hmac_length, integrity_pad_size = 0, hmac_input_size;
|
||||
uint32_t i;
|
||||
uint32_t hmac_length;
|
||||
uint32_t auth_length = 0;
|
||||
uint32_t integrity_pad_size = 0;
|
||||
uint32_t hmac_input_size;
|
||||
uint8_t * hmac_output;
|
||||
uint32_t start_of_session_trailer =
|
||||
IPMI_LANPLUS_OFFSET_PAYLOAD +
|
||||
@ -1818,22 +1882,43 @@ ipmi_lanplus_build_v2x_msg(
|
||||
/* Auth Code */
|
||||
lanplus_HMAC(session->v2_data.integrity_alg,
|
||||
session->v2_data.k1, /* key */
|
||||
20, /* key length */
|
||||
session->v2_data.k1_len, /* key length */
|
||||
msg + IPMI_LANPLUS_OFFSET_AUTHTYPE, /* hmac input */
|
||||
hmac_input_size,
|
||||
hmac_output,
|
||||
&hmac_length);
|
||||
|
||||
assert(hmac_length == 20);
|
||||
switch(session->v2_data.integrity_alg) {
|
||||
case IPMI_INTEGRITY_HMAC_SHA1_96:
|
||||
assert(hmac_length == IPMI_SHA_DIGEST_LENGTH);
|
||||
auth_length = IPMI_SHA1_AUTHCODE_SIZE;
|
||||
break;
|
||||
case IPMI_INTEGRITY_HMAC_MD5_128 :
|
||||
assert(hmac_length == IPMI_MD5_DIGEST_LENGTH);
|
||||
auth_length = IPMI_HMAC_MD5_AUTHCODE_SIZE;
|
||||
break;
|
||||
#ifdef HAVE_CRYPTO_SHA256
|
||||
case IPMI_INTEGRITY_HMAC_SHA256_128:
|
||||
assert(hmac_length == IPMI_SHA256_DIGEST_LENGTH);
|
||||
auth_length = IPMI_HMAC_SHA256_AUTHCODE_SIZE;
|
||||
break;
|
||||
#endif /* HAVE_CRYPTO_SHA256 */
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
if (verbose > 2)
|
||||
printbuf(hmac_output, 12, "authcode output");
|
||||
printbuf(hmac_output, auth_length, "authcode output");
|
||||
|
||||
/* Set session_trailer_length appropriately */
|
||||
session_trailer_length =
|
||||
integrity_pad_size +
|
||||
2 + /* pad length + next header */
|
||||
12; /* Size of the authcode (we only use the first 12 bytes) */
|
||||
auth_length; /* Size of the authcode. We only
|
||||
* use the first 12(SHA1) or
|
||||
* 16(MD5/SHA256) bytes.
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
@ -96,12 +96,20 @@
|
||||
#define IPMI_MAX_CONF_HEADER_SIZE 0x20
|
||||
#define IPMI_MAX_PAYLOAD_SIZE 0xFFFF /* Includes confidentiality header/trailer */
|
||||
#define IPMI_MAX_CONF_TRAILER_SIZE 0x20
|
||||
#define IPMI_MAX_INTEGRITY_PAD_SIZE 0x20
|
||||
#define IPMI_MAX_AUTH_CODE_SIZE 0x20
|
||||
#define IPMI_MAX_INTEGRITY_PAD_SIZE IPMI_MAX_MD_SIZE
|
||||
#define IPMI_MAX_AUTH_CODE_SIZE IPMI_MAX_MD_SIZE
|
||||
|
||||
#define IPMI_REQUEST_MESSAGE_SIZE 0x07
|
||||
#define IPMI_MAX_MAC_SIZE 0x14 /* The largest mac we ever expect to generate */
|
||||
#define IPMI_SHA1_AUTHCODE_SIZE 0x0C
|
||||
#define IPMI_MAX_MAC_SIZE IPMI_MAX_MD_SIZE /* The largest mac we ever expect to generate */
|
||||
|
||||
#define IPMI_SHA1_AUTHCODE_SIZE 12
|
||||
#define IPMI_HMAC_MD5_AUTHCODE_SIZE 16
|
||||
#define IPMI_MD5_AUTHCODE_SIZE 16
|
||||
#define IPMI_HMAC_SHA256_AUTHCODE_SIZE 16
|
||||
|
||||
#define IPMI_SHA_DIGEST_LENGTH 20
|
||||
#define IPMI_MD5_DIGEST_LENGTH 16
|
||||
#define IPMI_SHA256_DIGEST_LENGTH 32
|
||||
|
||||
/*
|
||||
*This is accurate, as long as we're only passing 1 auth algorithm,
|
||||
@ -109,7 +117,7 @@
|
||||
*/
|
||||
#define IPMI_OPEN_SESSION_REQUEST_SIZE 32
|
||||
#define IPMI_RAKP1_MESSAGE_SIZE 44
|
||||
#define IPMI_RAKP3_MESSAGE_MAX_SIZE 28
|
||||
#define IPMI_RAKP3_MESSAGE_MAX_SIZE (8 + IPMI_MAX_MD_SIZE)
|
||||
|
||||
#define IPMI_MAX_USER_NAME_LENGTH 16
|
||||
|
||||
|
@ -74,7 +74,7 @@ lanplus_rakp2_hmac_matches(const struct ipmi_session * session,
|
||||
{
|
||||
uint8_t * buffer;
|
||||
int bufferLength, i;
|
||||
uint8_t mac[20];
|
||||
uint8_t mac[IPMI_MAX_MD_SIZE];
|
||||
uint32_t macLength;
|
||||
|
||||
uint32_t SIDm_lsbf, SIDc_lsbf;
|
||||
@ -84,7 +84,12 @@ lanplus_rakp2_hmac_matches(const struct ipmi_session * session,
|
||||
return 1;
|
||||
|
||||
/* We don't yet support other algorithms */
|
||||
assert(session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1);
|
||||
assert((session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1)
|
||||
|| (session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_MD5)
|
||||
#ifdef HAVE_CRYPTO_SHA256
|
||||
|| (session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA256)
|
||||
#endif /* HAVE_CRYPTO_SHA256 */
|
||||
);
|
||||
|
||||
|
||||
bufferLength =
|
||||
@ -228,8 +233,9 @@ lanplus_rakp4_hmac_matches(const struct ipmi_session * session,
|
||||
{
|
||||
uint8_t * buffer;
|
||||
int bufferLength, i;
|
||||
uint8_t mac[20];
|
||||
uint8_t mac[IPMI_MAX_MD_SIZE];
|
||||
uint32_t macLength;
|
||||
uint32_t cmpLength;
|
||||
uint32_t SIDc_lsbf;
|
||||
|
||||
if (ipmi_oem_active(intf, "intelplus")){
|
||||
@ -238,13 +244,19 @@ lanplus_rakp4_hmac_matches(const struct ipmi_session * session,
|
||||
return 1;
|
||||
|
||||
/* We don't yet support other algorithms */
|
||||
assert(session->v2_data.integrity_alg == IPMI_INTEGRITY_HMAC_SHA1_96);
|
||||
assert((session->v2_data.integrity_alg == IPMI_INTEGRITY_HMAC_SHA1_96)
|
||||
|| (session->v2_data.integrity_alg == IPMI_INTEGRITY_HMAC_MD5_128));
|
||||
} else {
|
||||
if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
|
||||
return 1;
|
||||
|
||||
/* We don't yet support other algorithms */
|
||||
assert(session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1);
|
||||
assert((session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1)
|
||||
|| (session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_MD5)
|
||||
#ifdef HAVE_CRYPTO_SHA256
|
||||
|| (session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA256)
|
||||
#endif /* HAVE_CRYPTO_SHA256 */
|
||||
);
|
||||
}
|
||||
|
||||
bufferLength =
|
||||
@ -294,7 +306,8 @@ lanplus_rakp4_hmac_matches(const struct ipmi_session * session,
|
||||
if (verbose > 2)
|
||||
{
|
||||
printbuf((const uint8_t *)buffer, bufferLength, ">> rakp4 mac input buffer");
|
||||
printbuf(session->v2_data.sik, 20l, ">> rakp4 mac key (sik)");
|
||||
printbuf(session->v2_data.sik, session->v2_data.sik_len,
|
||||
">> rakp4 mac key (sik)");
|
||||
}
|
||||
|
||||
|
||||
@ -305,7 +318,7 @@ lanplus_rakp4_hmac_matches(const struct ipmi_session * session,
|
||||
? session->v2_data.integrity_alg
|
||||
: session->v2_data.auth_alg ,
|
||||
session->v2_data.sik,
|
||||
IPMI_SIK_BUFFER_SIZE,
|
||||
session->v2_data.sik_len,
|
||||
buffer,
|
||||
bufferLength,
|
||||
mac,
|
||||
@ -317,12 +330,48 @@ lanplus_rakp4_hmac_matches(const struct ipmi_session * session,
|
||||
printbuf(mac, macLength, ">> rakp4 mac as computed by the remote console");
|
||||
}
|
||||
|
||||
|
||||
if (ipmi_oem_active(intf, "intelplus")) {
|
||||
/* Intel BMC responds with the integrity Algorithm in RAKP4 */
|
||||
switch(session->v2_data.integrity_alg) {
|
||||
case IPMI_INTEGRITY_HMAC_SHA1_96:
|
||||
assert(macLength == IPMI_SHA_DIGEST_LENGTH);
|
||||
cmpLength = IPMI_SHA1_AUTHCODE_SIZE;
|
||||
break;
|
||||
case IPMI_INTEGRITY_HMAC_MD5_128:
|
||||
assert(macLength == IPMI_MD5_DIGEST_LENGTH);
|
||||
cmpLength = IPMI_HMAC_MD5_AUTHCODE_SIZE;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* We don't yet support other algorithms */
|
||||
switch(session->v2_data.auth_alg) {
|
||||
case IPMI_AUTH_RAKP_HMAC_SHA1:
|
||||
assert(macLength == IPMI_SHA_DIGEST_LENGTH);
|
||||
cmpLength = IPMI_SHA1_AUTHCODE_SIZE;
|
||||
break;
|
||||
case IPMI_AUTH_RAKP_HMAC_MD5:
|
||||
assert(macLength == IPMI_MD5_DIGEST_LENGTH);
|
||||
cmpLength = IPMI_HMAC_MD5_AUTHCODE_SIZE;
|
||||
break;
|
||||
#ifdef HAVE_CRYPTO_SHA256
|
||||
case IPMI_AUTH_RAKP_HMAC_SHA256:
|
||||
assert(macLength == IPMI_SHA256_DIGEST_LENGTH);
|
||||
cmpLength = IPMI_HMAC_SHA256_AUTHCODE_SIZE;
|
||||
break;
|
||||
#endif /* HAVE_CRYPTO_SHA256 */
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
buffer = NULL;
|
||||
assert(macLength == 20);
|
||||
return (memcmp(bmc_mac, mac, 12) == 0);
|
||||
assert(macLength >= cmpLength);
|
||||
return (memcmp(bmc_mac, mac, cmpLength) == 0);
|
||||
}
|
||||
|
||||
|
||||
@ -368,7 +417,12 @@ lanplus_generate_rakp3_authcode(uint8_t * output_buffer,
|
||||
}
|
||||
|
||||
/* We don't yet support other algorithms */
|
||||
assert(session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1);
|
||||
assert((session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1)
|
||||
|| (session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_MD5)
|
||||
#ifdef HAVE_CRYPTO_SHA256
|
||||
|| (session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA256)
|
||||
#endif /* HAVE_CRYPTO_SHA256 */
|
||||
);
|
||||
|
||||
input_buffer_length =
|
||||
16 + /* Rc */
|
||||
@ -478,13 +532,19 @@ lanplus_generate_sik(struct ipmi_session * session, struct ipmi_intf * intf)
|
||||
uint32_t mac_length;
|
||||
|
||||
|
||||
memset(session->v2_data.sik, 0, IPMI_SIK_BUFFER_SIZE);
|
||||
memset(session->v2_data.sik, 0, sizeof(session->v2_data.sik));
|
||||
session->v2_data.sik_len = 0;
|
||||
|
||||
if (session->v2_data.auth_alg == IPMI_AUTH_RAKP_NONE)
|
||||
return 0;
|
||||
|
||||
/* We don't yet support other algorithms */
|
||||
assert(session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1);
|
||||
assert((session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1)
|
||||
|| (session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_MD5)
|
||||
#ifdef HAVE_CRYPTO_SHA256
|
||||
|| (session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA256)
|
||||
#endif /* HAVE_CRYPTO_SHA256 */
|
||||
);
|
||||
|
||||
input_buffer_length =
|
||||
16 + /* Rm */
|
||||
@ -572,15 +632,33 @@ lanplus_generate_sik(struct ipmi_session * session, struct ipmi_intf * intf)
|
||||
|
||||
free(input_buffer);
|
||||
input_buffer = NULL;
|
||||
assert(mac_length == 20);
|
||||
switch (session->v2_data.auth_alg) {
|
||||
case IPMI_AUTH_RAKP_HMAC_SHA1:
|
||||
assert(mac_length == IPMI_SHA_DIGEST_LENGTH);
|
||||
break;
|
||||
case IPMI_AUTH_RAKP_HMAC_MD5:
|
||||
assert(mac_length == IPMI_MD5_DIGEST_LENGTH);
|
||||
break;
|
||||
#ifdef HAVE_CRYPTO_SHA256
|
||||
case IPMI_AUTH_RAKP_HMAC_SHA256:
|
||||
assert(mac_length == IPMI_SHA256_DIGEST_LENGTH);
|
||||
break;
|
||||
#endif /* HAVE_CRYPTO_SHA256 */
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
session->v2_data.sik_len = mac_length;
|
||||
|
||||
/*
|
||||
* The key MAC generated is 20 bytes, but we will only be using the first
|
||||
* 12 for SHA1 96
|
||||
*/
|
||||
if (verbose >= 2)
|
||||
printbuf(session->v2_data.sik, 20, "Generated session integrity key");
|
||||
|
||||
if (verbose >= 2) {
|
||||
printbuf(session->v2_data.sik, session->v2_data.sik_len,
|
||||
"Generated session integrity key");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -614,16 +692,32 @@ lanplus_generate_k1(struct ipmi_session * session)
|
||||
{
|
||||
lanplus_HMAC(session->v2_data.auth_alg,
|
||||
session->v2_data.sik,
|
||||
IPMI_SIK_BUFFER_SIZE, /* SIK length */
|
||||
session->v2_data.sik_len, /* SIK length */
|
||||
CONST_1,
|
||||
20,
|
||||
session->v2_data.k1,
|
||||
&mac_length);
|
||||
assert(mac_length == 20);
|
||||
switch (session->v2_data.auth_alg) {
|
||||
case IPMI_AUTH_RAKP_HMAC_SHA1:
|
||||
assert(mac_length == IPMI_SHA_DIGEST_LENGTH);
|
||||
break;
|
||||
case IPMI_AUTH_RAKP_HMAC_MD5:
|
||||
assert(mac_length == IPMI_MD5_DIGEST_LENGTH);
|
||||
break;
|
||||
#ifdef HAVE_CRYPTO_SHA256
|
||||
case IPMI_AUTH_RAKP_HMAC_SHA256:
|
||||
assert(mac_length == IPMI_SHA256_DIGEST_LENGTH);
|
||||
break;
|
||||
#endif /* HAVE_CRYPTO_SHA256 */
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
session->v2_data.k1_len = mac_length;
|
||||
}
|
||||
|
||||
if (verbose >= 2)
|
||||
printbuf(session->v2_data.k1, 20, "Generated K1");
|
||||
printbuf(session->v2_data.k1, session->v2_data.k1_len, "Generated K1");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -658,16 +752,32 @@ lanplus_generate_k2(struct ipmi_session * session)
|
||||
{
|
||||
lanplus_HMAC(session->v2_data.auth_alg,
|
||||
session->v2_data.sik,
|
||||
IPMI_SIK_BUFFER_SIZE, /* SIK length */
|
||||
session->v2_data.sik_len, /* SIK length */
|
||||
CONST_2,
|
||||
20,
|
||||
session->v2_data.k2,
|
||||
&mac_length);
|
||||
assert(mac_length == 20);
|
||||
switch (session->v2_data.auth_alg) {
|
||||
case IPMI_AUTH_RAKP_HMAC_SHA1:
|
||||
assert(mac_length == IPMI_SHA_DIGEST_LENGTH);
|
||||
break;
|
||||
case IPMI_AUTH_RAKP_HMAC_MD5:
|
||||
assert(mac_length == IPMI_MD5_DIGEST_LENGTH);
|
||||
break;
|
||||
#ifdef HAVE_CRYPTO_SHA256
|
||||
case IPMI_AUTH_RAKP_HMAC_SHA256:
|
||||
assert(mac_length == IPMI_SHA256_DIGEST_LENGTH);
|
||||
break;
|
||||
#endif /* HAVE_CRYPTO_SHA256 */
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
session->v2_data.k2_len = mac_length;
|
||||
}
|
||||
|
||||
if (verbose >= 2)
|
||||
printbuf(session->v2_data.k2, 20, "Generated K2");
|
||||
printbuf(session->v2_data.k2, session->v2_data.k2_len, "Generated K2");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -803,6 +913,7 @@ 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;
|
||||
uint32_t authcode_length;
|
||||
|
||||
|
||||
if ((rs->session.authtype != IPMI_SESSION_AUTHTYPE_RMCP_PLUS) ||
|
||||
@ -811,36 +922,51 @@ lanplus_has_valid_auth_code(struct ipmi_rs * rs, struct ipmi_session * session)
|
||||
(session->v2_data.integrity_alg == IPMI_INTEGRITY_NONE))
|
||||
return 1;
|
||||
|
||||
/* We only support SHA1-96 now */
|
||||
assert(session->v2_data.integrity_alg == IPMI_INTEGRITY_HMAC_SHA1_96);
|
||||
switch (session->v2_data.integrity_alg) {
|
||||
case IPMI_INTEGRITY_HMAC_SHA1_96:
|
||||
authcode_length = IPMI_SHA1_AUTHCODE_SIZE;
|
||||
break;
|
||||
case IPMI_INTEGRITY_HMAC_MD5_128:
|
||||
authcode_length = IPMI_HMAC_MD5_AUTHCODE_SIZE;
|
||||
break;
|
||||
#ifdef HAVE_CRYPTO_SHA256
|
||||
case IPMI_INTEGRITY_HMAC_SHA256_128:
|
||||
authcode_length = IPMI_HMAC_SHA256_AUTHCODE_SIZE;
|
||||
break;
|
||||
#endif /* HAVE_CRYPTO_SHA256 */
|
||||
/* Unsupported */
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* For SHA1-96, the authcode will be the last 12 bytes in the packet
|
||||
* For SHA256-128 or MD5-128, the authcode will be the last 16 bytes in the packet
|
||||
*/
|
||||
bmc_authcode = rs->data + (rs->data_len - IPMI_SHA1_AUTHCODE_SIZE);
|
||||
bmc_authcode = rs->data + (rs->data_len - authcode_length);
|
||||
|
||||
lanplus_HMAC(session->v2_data.integrity_alg,
|
||||
session->v2_data.k1,
|
||||
IPMI_AUTHCODE_BUFFER_SIZE,
|
||||
session->v2_data.k1_len,
|
||||
rs->data + IPMI_LANPLUS_OFFSET_AUTHTYPE,
|
||||
rs->data_len - IPMI_LANPLUS_OFFSET_AUTHTYPE - IPMI_SHA1_AUTHCODE_SIZE,
|
||||
rs->data_len - IPMI_LANPLUS_OFFSET_AUTHTYPE - authcode_length,
|
||||
generated_authcode,
|
||||
&generated_authcode_length);
|
||||
|
||||
if (verbose > 3)
|
||||
{
|
||||
lprintf(LOG_DEBUG+2, "Validating authcode");
|
||||
printbuf(session->v2_data.k1, 20, "K1");
|
||||
printbuf(session->v2_data.k1, session->v2_data.k1_len, "K1");
|
||||
printbuf(rs->data + IPMI_LANPLUS_OFFSET_AUTHTYPE,
|
||||
rs->data_len - IPMI_LANPLUS_OFFSET_AUTHTYPE - IPMI_SHA1_AUTHCODE_SIZE,
|
||||
rs->data_len - IPMI_LANPLUS_OFFSET_AUTHTYPE - authcode_length,
|
||||
"Authcode Input Data");
|
||||
printbuf(generated_authcode, 12, "Generated authcode");
|
||||
printbuf(bmc_authcode, 12, "Expected authcode");
|
||||
printbuf(generated_authcode, generated_authcode_length, "Generated authcode");
|
||||
printbuf(bmc_authcode, authcode_length, "Expected authcode");
|
||||
}
|
||||
|
||||
|
||||
assert(generated_authcode_length == 20);
|
||||
return (memcmp(bmc_authcode, generated_authcode, 12) == 0);
|
||||
assert(generated_authcode_length >= authcode_length);
|
||||
return (memcmp(bmc_authcode, generated_authcode, authcode_length) == 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -99,7 +99,8 @@ lanplus_rand(uint8_t * buffer, uint32_t num_bytes)
|
||||
/*
|
||||
* lanplus_HMAC
|
||||
*
|
||||
* param mac specifies the algorithm to be used, currently only SHA1 is supported
|
||||
* param mac specifies the algorithm to be used, currently SHA1, SHA256 and MD5
|
||||
* are supported
|
||||
* param key is the key used for HMAC generation
|
||||
* param key_len is the lenght of key
|
||||
* param d is the data to be MAC'd
|
||||
@ -123,6 +124,14 @@ lanplus_HMAC(uint8_t mac,
|
||||
if ((mac == IPMI_AUTH_RAKP_HMAC_SHA1) ||
|
||||
(mac == IPMI_INTEGRITY_HMAC_SHA1_96))
|
||||
evp_md = EVP_sha1();
|
||||
else if ((mac == IPMI_AUTH_RAKP_HMAC_MD5) ||
|
||||
(mac == IPMI_INTEGRITY_HMAC_MD5_128))
|
||||
evp_md = EVP_md5();
|
||||
#ifdef HAVE_CRYPTO_SHA256
|
||||
else if ((mac == IPMI_AUTH_RAKP_HMAC_SHA256) ||
|
||||
(mac == IPMI_INTEGRITY_HMAC_SHA256_128))
|
||||
evp_md = EVP_sha256();
|
||||
#endif /* HAVE_CRYPTO_SHA256 */
|
||||
else
|
||||
{
|
||||
lprintf(LOG_DEBUG, "Invalid mac type 0x%x in lanplus_HMAC\n", mac);
|
||||
|
@ -31,6 +31,7 @@
|
||||
*/
|
||||
|
||||
#include "lanplus.h"
|
||||
#include "lanplus_crypt.h"
|
||||
#include "lanplus_dump.h"
|
||||
|
||||
extern const struct valstr ipmi_rakp_return_codes[];
|
||||
@ -127,16 +128,27 @@ void lanplus_dump_rakp2_message(const struct ipmi_rs * rsp, uint8_t auth_alg)
|
||||
break;
|
||||
case IPMI_AUTH_RAKP_HMAC_SHA1:
|
||||
printf("%s Key exchange auth code [sha1] : 0x", DUMP_PREFIX_INCOMING);
|
||||
for (i = 0; i < 20; ++i)
|
||||
for (i = 0; i < IPMI_SHA_DIGEST_LENGTH; ++i) {
|
||||
printf("%02x", rsp->payload.rakp2_message.key_exchange_auth_code[i]);
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
break;
|
||||
case IPMI_AUTH_RAKP_HMAC_MD5:
|
||||
printf("%s Key exchange auth code [md5] : 0x", DUMP_PREFIX_INCOMING);
|
||||
for (i = 0; i < 16; ++i)
|
||||
for (i = 0; i < IPMI_MD5_DIGEST_LENGTH; ++i) {
|
||||
printf("%02x", rsp->payload.rakp2_message.key_exchange_auth_code[i]);
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
break;
|
||||
#ifdef HAVE_CRYPTO_SHA256
|
||||
case IPMI_AUTH_RAKP_HMAC_SHA256:
|
||||
printf("%s Key exchange auth code [sha256]: 0x", DUMP_PREFIX_INCOMING);
|
||||
for (i = 0; i < IPMI_SHA256_DIGEST_LENGTH; ++i) {
|
||||
printf("%02x", rsp->payload.rakp2_message.key_exchange_auth_code[i]);
|
||||
}
|
||||
printf("\n");
|
||||
break;
|
||||
#endif /* HAVE_CRYPTO_SHA256 */
|
||||
default:
|
||||
printf("%s Key exchange auth code : invalid", DUMP_PREFIX_INCOMING);
|
||||
}
|
||||
@ -174,16 +186,27 @@ void lanplus_dump_rakp4_message(const struct ipmi_rs * rsp, uint8_t auth_alg)
|
||||
break;
|
||||
case IPMI_AUTH_RAKP_HMAC_SHA1:
|
||||
printf("%s Key exchange auth code [sha1] : 0x", DUMP_PREFIX_INCOMING);
|
||||
for (i = 0; i < 12; ++i)
|
||||
for (i = 0; i < IPMI_SHA1_AUTHCODE_SIZE; ++i) {
|
||||
printf("%02x", rsp->payload.rakp4_message.integrity_check_value[i]);
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
break;
|
||||
case IPMI_AUTH_RAKP_HMAC_MD5:
|
||||
printf("%s Key exchange auth code [md5] : 0x", DUMP_PREFIX_INCOMING);
|
||||
for (i = 0; i < 12; ++i)
|
||||
for (i = 0; i < IPMI_HMAC_MD5_AUTHCODE_SIZE; ++i) {
|
||||
printf("%02x", rsp->payload.rakp4_message.integrity_check_value[i]);
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
break;
|
||||
#ifdef HAVE_CRYPTO_SHA256
|
||||
case IPMI_AUTH_RAKP_HMAC_SHA256:
|
||||
printf("%s Key exchange auth code [sha256]: 0x", DUMP_PREFIX_INCOMING);
|
||||
for (i = 0; i < IPMI_HMAC_SHA256_AUTHCODE_SIZE; ++i) {
|
||||
printf("%02x", rsp->payload.rakp4_message.integrity_check_value[i]);
|
||||
}
|
||||
printf("\n");
|
||||
break;
|
||||
#endif /* HAVE_CRYPTO_SHA256 */
|
||||
default:
|
||||
printf("%s Key exchange auth code : invalid", DUMP_PREFIX_INCOMING);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user