diff options
Diffstat (limited to 'src/plugins/lanplus/lanplus_crypt.c')
-rw-r--r-- | src/plugins/lanplus/lanplus_crypt.c | 232 |
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]; |