summaryrefslogtreecommitdiff
path: root/src/plugins/lanplus/lanplus_crypt.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/lanplus/lanplus_crypt.c')
-rw-r--r--src/plugins/lanplus/lanplus_crypt.c232
1 files changed, 187 insertions, 45 deletions
diff --git a/src/plugins/lanplus/lanplus_crypt.c b/src/plugins/lanplus/lanplus_crypt.c
index 1cdd050..b4d677b 100644
--- a/src/plugins/lanplus/lanplus_crypt.c
+++ b/src/plugins/lanplus/lanplus_crypt.c
@@ -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,16 @@ 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);
+#ifdef HAVE_CRYPTO_SHA256 // assert() is a macro, must not put #ifdef inside it
+ assert((session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1)
+ || (session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_MD5)
+ || (session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA256)
+ );
+#else
+ assert((session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1)
+ || (session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_MD5)
+ );
+#endif /* HAVE_CRYPTO_SHA256 */
bufferLength =
@@ -98,7 +107,7 @@ lanplus_rakp2_hmac_matches(const struct ipmi_session * session,
strlen((const char *)intf->ssn_params.username); /* optional */
buffer = malloc(bufferLength);
- if (buffer == NULL) {
+ if (!buffer) {
lprintf(LOG_ERR, "ipmitool: malloc failure");
return 1;
}
@@ -228,8 +237,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 +248,23 @@ 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);
+#ifdef HAVE_CRYPTO_SHA256 // assert() is a macro, must not put #ifdef inside it
+ assert((session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1)
+ || (session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_MD5)
+ || (session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA256)
+ );
+#else
+ assert((session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1)
+ || (session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_MD5)
+ );
+#endif /* HAVE_CRYPTO_SHA256 */
}
bufferLength =
@@ -253,7 +273,7 @@ lanplus_rakp4_hmac_matches(const struct ipmi_session * session,
16; /* GUIDc */
buffer = (uint8_t *)malloc(bufferLength);
- if (buffer == NULL) {
+ if (!buffer) {
lprintf(LOG_ERR, "ipmitool: malloc failure");
return 1;
}
@@ -294,7 +314,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 +326,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 +338,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 +425,16 @@ 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);
+#ifdef HAVE_CRYPTO_SHA256 // assert() is a macro, must not put #ifdef inside it
+ assert((session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1)
+ || (session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_MD5)
+ || (session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA256)
+ );
+#else
+ assert((session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1)
+ || (session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_MD5)
+ );
+#endif /* HAVE_CRYPTO_SHA256 */
input_buffer_length =
16 + /* Rc */
@@ -378,7 +444,7 @@ lanplus_generate_rakp3_authcode(uint8_t * output_buffer,
strlen((const char *)intf->ssn_params.username);
input_buffer = malloc(input_buffer_length);
- if (input_buffer == NULL) {
+ if (!input_buffer) {
lprintf(LOG_ERR, "ipmitool: malloc failure");
return 1;
}
@@ -458,7 +524,7 @@ lanplus_generate_rakp3_authcode(uint8_t * output_buffer,
* <USERNAME> - Usename (absent for null usernames)
*
* The key used to generated the SIK is Kg if Kg is not null (two-key logins are
- * enabled). Otherwise Kuid (the user authcode) is used as the key to genereate
+ * enabled). Otherwise Kuid (the user authcode) is used as the key to generate
* the SIK.
*
* I am aware that the subscripts look backwards, but that is the way they are
@@ -478,13 +544,23 @@ 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);
+#ifdef HAVE_CRYPTO_SHA256 // assert() is a macro, must not put #ifdef inside it
+ assert((session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1)
+ || (session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_MD5)
+ || (session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA256)
+ );
+#else
+ assert((session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_SHA1)
+ || (session->v2_data.auth_alg == IPMI_AUTH_RAKP_HMAC_MD5)
+ );
+#endif /* HAVE_CRYPTO_SHA256 */
input_buffer_length =
16 + /* Rm */
@@ -494,7 +570,7 @@ lanplus_generate_sik(struct ipmi_session * session, struct ipmi_intf * intf)
strlen((const char *)intf->ssn_params.username);
input_buffer = malloc(input_buffer_length);
- if (input_buffer == NULL) {
+ if (!input_buffer) {
lprintf(LOG_ERR, "ipmitool: malloc failure");
return 1;
}
@@ -572,15 +648,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 +708,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 +768,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;
}
@@ -726,7 +852,7 @@ lanplus_encrypt_payload(uint8_t crypt_alg,
pad_length = IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE - mod;
padded_input = (uint8_t*)malloc(input_length + pad_length + 1);
- if (padded_input == NULL) {
+ if (!padded_input) {
lprintf(LOG_ERR, "ipmitool: malloc failure");
return 1;
}
@@ -743,7 +869,7 @@ lanplus_encrypt_payload(uint8_t crypt_alg,
if (lanplus_rand(output, IPMI_CRYPT_AES_CBC_128_BLOCK_SIZE))
{
lprintf(LOG_ERR, "lanplus_encrypt_payload: Error generating IV");
- if (padded_input != NULL) {
+ if (padded_input) {
free(padded_input);
padded_input = NULL;
}
@@ -787,7 +913,7 @@ lanplus_encrypt_payload(uint8_t crypt_alg,
*
* The authcode is computed using the specified integrity algorithm starting
* with the AuthType / Format field, and ending with the field immediately
- * preceeding the authcode itself.
+ * preceding the authcode itself.
*
* The key key used to generate the authcode MAC is K1.
*
@@ -803,6 +929,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 +938,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);
}
@@ -877,7 +1019,7 @@ lanplus_decrypt_payload(uint8_t crypt_alg, const uint8_t * key,
assert(crypt_alg == IPMI_CRYPT_AES_CBC_128);
decrypted_payload = (uint8_t*)malloc(input_length);
- if (decrypted_payload == NULL) {
+ if (!decrypted_payload) {
lprintf(LOG_ERR, "ipmitool: malloc failure");
return 1;
}
@@ -903,7 +1045,7 @@ lanplus_decrypt_payload(uint8_t crypt_alg, const uint8_t * key,
bytes_decrypted);
/*
- * We have to determine the payload size, by substracting the padding, etc.
+ * We have to determine the payload size, by subtracting the padding, etc.
* The last byte of the decrypted payload is the confidentiality pad length.
*/
conf_pad_length = decrypted_payload[bytes_decrypted - 1];