Skip to content

Auto selection of 'best' cipher suite available #32

Merged
merged 3 commits into from
Nov 1, 2018

Conversation

vmauery
Copy link
Member

@vmauery vmauery commented Aug 13, 2018

Based on current crypto alogrithms, one could rank cipher suites along
these lines:

17 > 3 >> all the rest

17 and 3 are the only cipher suites that implement any sort of
confidentiality alogorithm that is secure. In addition, any hmac-md5 or
md5 integrity algorithm used in integrity is weak at best and dangerous
for authentication.

This could possibly be enabled in a simpler mechanism by simply checking
for 17 and then choosing it before falling back to 3, but the way this
is implemented, it makes it easy to change the list of acceptable
algorithms from two to three or more items.

Signed-off-by: Vernon Mauery vernon.mauery@intel.com

memset(cipher_suite_data, 0, sizeof(cipher_suite_data));
memset(suites, 0, sizeof(struct cipher_suite_info)*n_max);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spaces around operator *, please.
also, I'd use sizeof(*suites) to make it independent of the actual type.

@@ -131,6 +131,8 @@ struct get_channel_auth_cap_rsp {
int _ipmi_get_channel_access(struct ipmi_intf *intf,
struct channel_access_t *channel_access,
uint8_t get_volatile_settings);
int _ipmi_get_channel_cipher_suites(struct ipmi_intf *intf, const char *payload_type,
uint8_t channel, struct cipher_suite_info *suites, size_t *count);
Copy link
Contributor

@AlexanderAmelkin AlexanderAmelkin Aug 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I honestly hate these underscore-prefixed functions in the header. Underscored functions are something private/static and should not be exported. I know this isn't your invention here, but I'd prefer you avoid adding new ones.

uint8_t crypt_alg;
uint32_t iana;
};

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks a lot like these should be put under #if defined(IPMI_INTF_LAN) || defined(IPMI_INTF_LANPLUS).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We cannot ifdef this out as only part of lan/lanplus enabled because this construct is used for two cases: determining the best cipher suite for a lanplus session; and as part of the "channel getciphers" call, which can be called over KCS.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see.

uint8_t channel)
int
_ipmi_get_channel_cipher_suites(struct ipmi_intf *intf, const char *payload_type,
uint8_t channel, struct cipher_suite_info *suites, size_t *count)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This brings warning: ‘struct cipher_suite_info’ declared inside parameter list. Apparently, you forgot to include ipmi_intf.h.

Besides, CodeClimate complains that this function is too complex. The complexity factor raised from 24 (paths through the function) to 28 with your change. Please try to reduce it. With a separate follow-up commit within this pull request, please.

}

static int
ipmi_get_channel_cipher_suites(struct ipmi_intf *intf, const char *payload_type,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be called ipmi_print_channel_cipher_suites(), and the other one (with underscore) should have this name.

return IPMI_LANPLUS_CIPHER_SUITE_3;
}
for (ipref = 0; ipref < nr_preferred &&
IPMI_LANPLUS_CIPHER_SUITE_RESERVED != best_suite; ipref++) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't run. IPMI_LANPLUS_CIPHER_SUITE_RESERVED != best_suite is false right away. You probably meant == here.

Besides, same comment applies as above regarding alignment and curly.

struct cipher_suite_info suites[256];
size_t nr_suites = sizeof(suites)/sizeof(suites[0]);
/* cipher suite best order is chosen with this criteria:
* hmac-md5 and md5 are BAD; xc4 is bad; aes128 is required
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

xRC4, I suppose, not xc4 ?
Anyway, I don't see anywhere in the following code that you check/compare algorithms.
You only have two items in cipher_order_preferred, only one of them being different from the default.
So basically, your function returns either 17 or 3, regardless of any other suites supported, and the comment does not help to understand why (without reading the IPMI spec section 22.15.2). Please add an explanation that applying these criteria to the aforementioned section, and taking in account that suite id 3 is mandatory, only id 17 is left that is better than 3.

This even boils down to a much simpler code that only checks if id 17 is supported, no need for all those nested loops, if I understood your logic right.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it would be possible to just check for 17. But I wanted to make it so an arbitrary priority list could be substituted if other people had different opinions about which cipher suites were important to them.

IPMI_LANPLUS_CIPHER_SUITE_RESERVED != best_suite; ipref++) {
for (i = 0; i < nr_suites; i++) {
if (cipher_order_preferred[ipref] ==
suites[i].cipher_suite_id) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And here too. Alignment and curly.

* pick the best one available
*/
if (IPMI_LANPLUS_CIPHER_SUITE_RESERVED ==
intf->ssn_params.cipher_suite_id) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alignment and curly

#define IPMI_LANPLUS_CIPHER_SUITE_14 14
#define IPMI_LANPLUS_CIPHER_SUITE_15 15
#define IPMI_LANPLUS_CIPHER_SUITE_16 16
#define IPMI_LANPLUS_CIPHER_SUITE_17 17
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make these an enum type instead, please. enums are symbols that can be seen/resolved during gdb session, unlike macros. change the associated variables/struct fields to that type too, please.

uint8_t crypt_alg;
uint32_t iana;
};

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see.


do {
/* Always ask for cipher suite format */
rqdata[2] = 0x80 + list_index;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is 0x80 ?

rsp = intf->sendrecv(intf, &req);
if (rsp == NULL) {
lprintf(LOG_ERR, "Unable to Get Channel Cipher Suites");
return -1;
}
if (rsp->ccode > 0) {
if (rsp->ccode > 0 || rsp->data_len < 1) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ccode is uint8_t, it's quite safe to do just if (rsp->ccode) (I mean, omit the > 0 part).

* Increment our list for the next call
*/
++list_index;
} while ((rsp->data_len == 17) &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is 17 ? Please don't use magic numbers.

offset += 3;
record->iana[0] |
(record->iana[1] << 8) |
(record->iana[2] << 16);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an ipmi24toh() for this now. Please use it.

@vmauery vmauery force-pushed the improvement/29 branch 2 times, most recently from 202d973 to 35e5ab8 Compare October 31, 2018 19:30
@vmauery
Copy link
Member Author

vmauery commented Oct 31, 2018

I think I have addressed all the concerns you have raised.

vmauery and others added 3 commits November 1, 2018 18:13
Based on current crypto alogrithms, one could rank cipher suites along
these lines:

17 > 3 >> all the rest

17 and 3 are the only cipher suites that implement any sort of
confidentiality alogorithm that is secure. In addition, any hmac-md5 or
md5 integrity algorithm used in integrity is weak at best and dangerous
for authentication.

This could possibly be enabled in a simpler mechanism by simply checking
for 17 and then choosing it before falling back to 3, but the way this
is implemented, it makes it easy to change the list of acceptable
algorithms from two to three or more items.

Resolves ipmitool#29

Signed-off-by: Vernon Mauery <vernon.mauery@intel.com>
Cipher suite ID is a byte as per IPMI spec.
Use the appropriate function and consider target endianness
(so write to a temporary variable).

Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
Some minor formatting corrections.
Also introduced a new helper function to reduce nesting level.

Signed-off-by: Alexander Amelkin <alexander@amelkin.msk.ru>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
improvement Improves an existing feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants