/*
* rakp.c
*
* MontaVista RMCP+ code for handling RAKP algorithms
*
* Author: MontaVista Software, Inc.
* Corey Minyard <minyard@mvista.com>
* source@mvista.com
*
* Copyright 2004 MontaVista Software Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <config.h>
#include <string.h>
#include <OpenIPMI/ipmi_conn.h>
#include <OpenIPMI/ipmi_msgbits.h>
#include <OpenIPMI/ipmi_auth.h>
#include <OpenIPMI/ipmi_err.h>
#include <OpenIPMI/ipmi_lan.h>
#include <OpenIPMI/internal/ipmi_int.h>
typedef struct rakp_info_s rakp_info_t;
typedef int (*init_cb)(rakp_info_t *info);
typedef void (*cleanup_cb)(rakp_info_t *info);
typedef int (*check_cb)(rakp_info_t *info,
unsigned char *data,
unsigned int data_len);
typedef int (*set_cb)(rakp_info_t *info,
unsigned char *data,
unsigned int *data_len,
unsigned int total_len);
struct rakp_info_s
{
ipmi_rmcpp_auth_t *ainfo;
ipmi_rmcpp_set_info_cb set;
ipmi_rmcpp_finish_auth_cb done;
void *cb_data;
unsigned int hacks;
unsigned char msg_tag;
void *key_data;
/* Check an set the auth keys for the various rakp messages. The
data passed in is the whole message. For set3, the data_len
points to the current message size and total_len is the
total_len available. It should update data_len to the actual
length. These functions may be NULL and will not be used. */
cleanup_cb cleanup;
check_cb check2;
set_cb set3;
check_cb check4;
};
static void
rakp_done(rakp_info_t *info,
ipmi_con_t *ipmi,
int addr_num,
int err)
{
info->done(ipmi, err, addr_num, info->cb_data);
if (info->cleanup)
info->cleanup(info);
ipmi_mem_free(info);
}
static int
check_rakp_rsp(ipmi_con_t *ipmi,
rakp_info_t *info,
ipmi_msg_t *msg,
char *caller,
unsigned int min_length,
int addr_num)
{
if (!ipmi)
return ECANCELED;
if (msg->data_len == 1) {
/* This is kind of a cheap hack, this can happen when there is
a timeout. */
ipmi_log(IPMI_LOG_ERR_INFO,
"rakp.c(%s): IPMI error: %d",
caller, msg->data[0]);
return IPMI_IPMI_ERR_VAL(msg->data[0]);
}
if (msg->data_len < 2) {
ipmi_log(IPMI_LOG_ERR_INFO,
"rakp.c(%s): Message data too short: %d",
caller, msg->data_len);
return EINVAL;
}
if (msg->data[1])
/* Got an RMCP+ error. */
return IPMI_RMCPP_ERR_VAL(msg->data[1]);
if (msg->data_len < min_length) {
ipmi_log(IPMI_LOG_ERR_INFO,
"rakp.c(%s): Message data too short: %d",
caller, msg->data_len);
return EINVAL;
}
return 0;
}
static int
handle_rakp4(ipmi_con_t *ipmi, ipmi_msgi_t *rspi)
{
ipmi_msg_t *msg = &rspi->msg;
rakp_info_t *info = rspi->data1;
int addr_num = (long) rspi->data4;
int rv;
uint32_t session_id;
/* In this function, there's not way to report the error to the
managed system, just report it locally. */
rv = check_rakp_rsp(ipmi, info, msg, "handle_rakp4", 8, addr_num);
if (rv)
goto out;
if (info->check4) {
rv = info->check4(info, msg->data, msg->data_len);
if (rv)
goto out;
}
session_id = ipmi_get_uint32(msg->data+4);
if (session_id != ipmi_rmcpp_auth_get_my_session_id(info->ainfo)) {
ipmi_log(IPMI_LOG_ERR_INFO,
"rakp.c(handle_rakp4): "
" Got wrong session id: 0x%x",
session_id);
rv = EINVAL;
goto out;
}
rakp_done(info, ipmi, addr_num, 0);
return IPMI_MSG_ITEM_NOT_USED;
out:
rakp_done(info, ipmi, addr_num, rv);
return IPMI_MSG_ITEM_NOT_USED;
}
static int
send_rakp3(ipmi_con_t *ipmi, rakp_info_t *info,
ipmi_msgi_t *rspi, int addr_num, int err)
{
int rv;
unsigned char data[64];
ipmi_msg_t msg;
ipmi_rmcpp_addr_t addr;
memset(data, 0, sizeof(data));
data[0] = info->msg_tag;
data[1] = err;
ipmi_set_uint32(data+4, ipmi_rmcpp_auth_get_mgsys_session_id(info->ainfo));
msg.netfn = IPMI_RMCPP_DUMMY_NETFN;
msg.cmd = 0;
msg.data = data;
msg.data_len = 8;
addr.addr_type = IPMI_RMCPP_ADDR_START + IPMI_RMCPP_PAYLOAD_TYPE_RAKP_3;
rspi->data1 = info;
if (info->set3) {
unsigned int len;
len = msg.data_len;
rv = info->set3(info, data, &len, sizeof(data));
if (rv)
return rv;
msg.data_len = len;
}
if (err)
/* Don't handle the responst (if one comes back) on an error. */
rv = ipmi_lan_send_command_forceip(ipmi, addr_num,
(ipmi_addr_t *) &addr, sizeof(addr),
&msg, NULL, rspi);
else
rv = ipmi_lan_send_command_forceip(ipmi, addr_num,
(ipmi_addr_t *) &addr, sizeof(addr),
&msg, handle_rakp4, rspi);
return rv;
}
static int
handle_rakp2(ipmi_con_t *ipmi, ipmi_msgi_t *rspi)
{
ipmi_msg_t *msg = &rspi->msg;
rakp_info_t *info = rspi->data1;
int addr_num = (long) rspi->data4;
int rv;
uint32_t session_id;
int err = 0;
unsigned char *p;
unsigned int plen;
int rv2;
rv = check_rakp_rsp(ipmi, info, msg, "handle_rakp2", 40, addr_num);
if (rv) {
err = IPMI_RMCPP_ILLEGAL_PARAMETER;
goto out;
}
p = ipmi_rmcpp_auth_get_mgsys_rand(info->ainfo, &plen);
if (plen < 16)
return EINVAL;
memcpy(p, msg->data+8, 16);
ipmi_rmcpp_auth_set_mgsys_rand_len(info->ainfo, 16);
p = ipmi_rmcpp_auth_get_mgsys_guid(info->ainfo, &plen);
if (plen < 16)
return EINVAL;
memcpy(p, msg->data+24, 16);
ipmi_rmcpp_auth_set_mgsys_guid_len(info->ainfo, 16);
session_id = ipmi_get_uint32(msg->data+4);
if (session_id != ipmi_rmcpp_auth_get_my_session_id(info->ainfo)) {
ipmi_log(IPMI_LOG_ERR_INFO,
"rakp.c(handle_rakp2): "
" Got wrong session id: 0x%x",
session_id);
err = IPMI_RMCPP_INVALID_SESSION_ID;
goto out;
}
if (info->check2) {
rv = info->check2(info, msg->data, msg->data_len);
if (rv) {
if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
ipmi_log(IPMI_LOG_DEBUG, "Integrity check fail for rakp 2");
err = IPMI_RMCPP_INVALID_INTEGRITY_CHECK_VALUE;
goto out;
}
}
rv = info->set(ipmi, addr_num, info->ainfo, info->cb_data);
if (rv) {
if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
ipmi_log(IPMI_LOG_DEBUG, "Error setting values from rakp 2");
err = IPMI_RMCPP_INSUFFICIENT_RESOURCES_FOR_SESSION;
goto out;
}
rv = send_rakp3(ipmi, info, rspi, addr_num, 0);
if (rv) {
if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
ipmi_log(IPMI_LOG_DEBUG, "Error sending rakp 3");
err = IPMI_RMCPP_INSUFFICIENT_RESOURCES_FOR_SESSION;
goto out;
}
return IPMI_MSG_ITEM_USED;
out:
rv2 = EINVAL;
if (ipmi)
rv2 = send_rakp3(ipmi, info, rspi, addr_num, err);
rakp_done(info, ipmi, addr_num, rv);
if (rv2)
return IPMI_MSG_ITEM_NOT_USED;
else
/* Yes, we use it to send the error response. */
return IPMI_MSG_ITEM_USED;
}
static int
send_rakp1(ipmi_con_t *ipmi, rakp_info_t *info,
ipmi_msgi_t *rspi, int addr_num)
{
int rv;
unsigned char data[44];
ipmi_msg_t msg;
ipmi_rmcpp_addr_t addr;
const unsigned char *p;
unsigned int plen;
memset(data, 0, sizeof(data));
data[0] = info->msg_tag;
ipmi_set_uint32(data+4, ipmi_rmcpp_auth_get_mgsys_session_id(info->ainfo));
p = ipmi_rmcpp_auth_get_my_rand(info->ainfo, &plen);
if (plen < 16)
return EINVAL;
memcpy(data+8, p, 16);
data[24] = ipmi_rmcpp_auth_get_role(info->ainfo);
data[27] = ipmi_rmcpp_auth_get_username_len(info->ainfo);
p = ipmi_rmcpp_auth_get_username(info->ainfo, &plen);
if (plen < 16)
return EINVAL;
memcpy(data+28, p, data[27]);
msg.netfn = IPMI_RMCPP_DUMMY_NETFN;
msg.cmd = 0;
msg.data = data;
msg.data_len = 28 + data[27];
addr.addr_type = IPMI_RMCPP_ADDR_START + IPMI_RMCPP_PAYLOAD_TYPE_RAKP_1;
rspi->data1 = info;
rv = ipmi_lan_send_command_forceip(ipmi, addr_num,
(ipmi_addr_t *) &addr, sizeof(addr),
&msg, handle_rakp2, rspi);
return rv;
}
static int
start_rakp(ipmi_con_t *ipmi,
int addr_num,
unsigned char msg_tag,
ipmi_rmcpp_auth_t *ainfo,
init_cb init,
cleanup_cb cleanup,
check_cb check2,
set_cb set3,
check_cb check4,
ipmi_rmcpp_set_info_cb set,
ipmi_rmcpp_finish_auth_cb done,
void *cb_data)
{
rakp_info_t *info;
ipmi_msgi_t *rspi;
int rv;
unsigned char *p;
unsigned int plen;
info = ipmi_mem_alloc(sizeof(*info));
if (!info)
return ENOMEM;
memset(info, 0, sizeof(*info));
rspi = ipmi_alloc_msg_item();
if (!rspi) {
ipmi_mem_free(info);
return ENOMEM;
}
info->msg_tag = msg_tag;
info->ainfo = ainfo;
info->cleanup = cleanup;
info->set = set;
info->done = done;
info->cb_data = cb_data;
info->check2 = check2;
info->set3 = set3;
info->check4 = check4;
info->hacks = ipmi->hacks;
p = ipmi_rmcpp_auth_get_my_rand(info->ainfo, &plen);
if (plen < 16)
return EINVAL;
ipmi_rmcpp_auth_set_my_rand_len(info->ainfo, 16);
rv = ipmi->os_hnd->get_random(ipmi->os_hnd, p, 16);
if (rv) {
ipmi_free_msg_item(rspi);
ipmi_mem_free(info);
return rv;
}
if (init) {
rv = init(info);
if (rv) {
ipmi_free_msg_item(rspi);
ipmi_mem_free(info);
return rv;
}
}
rv = send_rakp1(ipmi, info, rspi, addr_num);
if (rv) {
if (cleanup)
cleanup(info);
ipmi_free_msg_item(rspi);
ipmi_mem_free(info);
return rv;
}
return 0;
}
static int
start_rakp_none(ipmi_con_t *ipmi,
int addr_num,
unsigned char msg_tag,
ipmi_rmcpp_auth_t *ainfo,
ipmi_rmcpp_set_info_cb set,
ipmi_rmcpp_finish_auth_cb done,
void *cb_data)
{
return start_rakp(ipmi, addr_num, msg_tag, ainfo,
NULL, NULL, NULL, NULL, NULL,
set, done, cb_data);
}
static ipmi_rmcpp_authentication_t rakp_none_auth =
{
start_rakp_none
};
/***********************************************************************
*
* cipher handling
*
***********************************************************************/
#ifdef HAVE_OPENSSL
#include <openssl/hmac.h>
typedef struct rakp_hmac_key_s
{
unsigned int key_len;
unsigned int integ_len;
const EVP_MD *evp_md;
} rakp_hmac_key_t;
static int
rakp_hmac_c2(rakp_info_t *info,
unsigned char *data,
unsigned int data_len)
{
unsigned char idata[74];
unsigned int ilen;
unsigned char integ_data[20];
rakp_hmac_key_t *rinfo = info->key_data;
const unsigned char *p;
unsigned char *s;
unsigned char *k;
unsigned int plen;
if (data_len < 40+rinfo->key_len)
return E2BIG;
ipmi_set_uint32(idata+0, ipmi_rmcpp_auth_get_my_session_id(info->ainfo));
ipmi_set_uint32(idata+4, ipmi_rmcpp_auth_get_mgsys_session_id(info->ainfo));
p = ipmi_rmcpp_auth_get_my_rand(info->ainfo, &plen);
memcpy(idata+8, p, 16);
p = ipmi_rmcpp_auth_get_mgsys_rand(info->ainfo, &plen);
memcpy(idata+24, p, 16);
p = ipmi_rmcpp_auth_get_mgsys_guid(info->ainfo, &plen);
memcpy(idata+40, p, 16);
idata[56] = ipmi_rmcpp_auth_get_role(info->ainfo);
idata[57] = ipmi_rmcpp_auth_get_username_len(info->ainfo);
if (idata[57] > 16)
return EINVAL;
p = ipmi_rmcpp_auth_get_username(info->ainfo, &plen);
memcpy(idata+58, p, idata[57]);
p = ipmi_rmcpp_auth_get_password(info->ainfo, &plen);
if (plen < rinfo->key_len)
return EINVAL;
HMAC(rinfo->evp_md, p, rinfo->key_len, idata, 58+idata[57], integ_data, &ilen);
if (memcmp(data+40, integ_data, rinfo->key_len) != 0)
return EINVAL;
/* Now generate the SIK */
p = ipmi_rmcpp_auth_get_my_rand(info->ainfo, &plen);
memcpy(idata+0, p, 16);
p = ipmi_rmcpp_auth_get_mgsys_rand(info->ainfo, &plen);
memcpy(idata+16, p, 16);
idata[32] = ipmi_rmcpp_auth_get_role(info->ainfo);
idata[33] = ipmi_rmcpp_auth_get_username_len(info->ainfo);
p = ipmi_rmcpp_auth_get_username(info->ainfo, &plen);
memcpy(idata+34, p, idata[33]);
p = ipmi_rmcpp_auth_get_bmc_key(info->ainfo, &plen);
if (plen < rinfo->key_len)
return EINVAL;
s = ipmi_rmcpp_auth_get_sik(info->ainfo, &plen);
if (plen < rinfo->key_len)
return EINVAL;
HMAC(rinfo->evp_md, p, rinfo->key_len, idata, 34+idata[33], s, &ilen);
ipmi_rmcpp_auth_set_sik_len(info->ainfo, rinfo->key_len);
/* Now generate k1 and k2. */
k = ipmi_rmcpp_auth_get_k1(info->ainfo, &plen);
if (plen < rinfo->key_len)
return EINVAL;
memset(idata, 1, rinfo->key_len);
HMAC(rinfo->evp_md, s, rinfo->key_len, idata, rinfo->key_len, k, &ilen);
ipmi_rmcpp_auth_set_k2_len(info->ainfo, rinfo->key_len);
k = ipmi_rmcpp_auth_get_k2(info->ainfo, &plen);
if (plen < rinfo->key_len)
return EINVAL;
memset(idata, 2, rinfo->key_len);
HMAC(rinfo->evp_md, s, rinfo->key_len, idata, rinfo->key_len, k, &ilen);
ipmi_rmcpp_auth_set_k2_len(info->ainfo, rinfo->key_len);
return 0;
}
static int
rakp_hmac_s3(rakp_info_t *info,
unsigned char *data,
unsigned int *data_len,
unsigned int total_len)
{
unsigned char idata[38];
unsigned int ilen;
rakp_hmac_key_t *rinfo = info->key_data;
const unsigned char *p;
unsigned int plen;
if (((*data_len)+rinfo->key_len) > total_len)
return E2BIG;
p = ipmi_rmcpp_auth_get_mgsys_rand(info->ainfo, &plen);
memcpy(idata+0, p, 16);
ipmi_set_uint32(idata+16, ipmi_rmcpp_auth_get_my_session_id(info->ainfo));
idata[20] = ipmi_rmcpp_auth_get_role(info->ainfo);
if (info->hacks & IPMI_CONN_HACK_RAKP3_WRONG_ROLEM)
/* For the RAKP3 message, the Intel BMC only uses the bottom 4
nibbles. */
idata[20] &= 0xf;
idata[21] = ipmi_rmcpp_auth_get_username_len(info->ainfo);
if (idata[21] > 16)
return EINVAL;
p = ipmi_rmcpp_auth_get_username(info->ainfo, &plen);
memcpy(idata+22, p, idata[21]);
p = ipmi_rmcpp_auth_get_password(info->ainfo, &plen);
if (plen < rinfo->key_len)
return EINVAL;
HMAC(rinfo->evp_md, p, rinfo->key_len, idata, 22+idata[21],
data+*data_len, &ilen);
*data_len += rinfo->key_len;
return 0;
}
static int
rakp_hmac_c4(rakp_info_t *info,
unsigned char *data,
unsigned int data_len)
{
unsigned char idata[36];
unsigned int ilen;
unsigned char integ_data[20];
rakp_hmac_key_t *rinfo = info->key_data;
const unsigned char *p;
unsigned int plen;
if (data_len < 8+rinfo->integ_len)
return E2BIG;
p = ipmi_rmcpp_auth_get_my_rand(info->ainfo, &plen);
memcpy(idata+0, p, 16);
ipmi_set_uint32(idata+16, ipmi_rmcpp_auth_get_mgsys_session_id(info->ainfo));
p = ipmi_rmcpp_auth_get_mgsys_guid(info->ainfo, &plen);
if (plen < 16)
return EINVAL;
memcpy(idata+20, p, 16);
p = ipmi_rmcpp_auth_get_sik(info->ainfo, &plen);
HMAC(rinfo->evp_md, p, rinfo->key_len, idata, 36, integ_data, &ilen);
if (memcmp(data+8, integ_data, rinfo->integ_len) != 0)
return EINVAL;
return 0;
}
static void
rakp_hmac_cleanup(rakp_info_t *info)
{
rakp_hmac_key_t *key_data = info->key_data;
ipmi_mem_free(key_data);
}
static int
rakp_sha1_init(rakp_info_t *info)
{
rakp_hmac_key_t *key_data;
key_data = ipmi_mem_alloc(sizeof(*key_data));
if (!key_data)
return ENOMEM;
key_data->evp_md = EVP_sha1();
key_data->key_len = 20;
key_data->integ_len = 12;
info->key_data = key_data;
return 0;
}
static int
start_rakp_hmac_sha1(ipmi_con_t *ipmi,
int addr_num,
unsigned char msg_tag,
ipmi_rmcpp_auth_t *ainfo,
ipmi_rmcpp_set_info_cb set,
ipmi_rmcpp_finish_auth_cb done,
void *cb_data)
{
return start_rakp(ipmi, addr_num, msg_tag, ainfo,
rakp_sha1_init, rakp_hmac_cleanup,
rakp_hmac_c2, rakp_hmac_s3, rakp_hmac_c4,
set, done, cb_data);
}
static ipmi_rmcpp_authentication_t rakp_hmac_sha1_auth =
{
start_rakp_hmac_sha1
};
static int
rakp_md5_init(rakp_info_t *info)
{
rakp_hmac_key_t *key_data;
key_data = ipmi_mem_alloc(sizeof(*key_data));
if (!key_data)
return ENOMEM;
key_data->evp_md = EVP_md5();
key_data->key_len = 16;
key_data->integ_len = 16;
info->key_data = key_data;
return 0;
}
static int
start_rakp_hmac_md5(ipmi_con_t *ipmi,
int addr_num,
unsigned char msg_tag,
ipmi_rmcpp_auth_t *ainfo,
ipmi_rmcpp_set_info_cb set,
ipmi_rmcpp_finish_auth_cb done,
void *cb_data)
{
return start_rakp(ipmi, addr_num, msg_tag, ainfo,
rakp_md5_init, rakp_hmac_cleanup,
rakp_hmac_c2, rakp_hmac_s3, rakp_hmac_c4,
set, done, cb_data);
}
static ipmi_rmcpp_authentication_t rakp_hmac_md5_auth =
{
start_rakp_hmac_md5
};
#endif
/**********************************************************************
*
* RAKP message formatting
*
*********************************************************************/
static int
rakp_format_msg(ipmi_con_t *ipmi,
const ipmi_addr_t *addr,
unsigned int addr_len,
const ipmi_msg_t *msg,
unsigned char *out_data,
unsigned int *out_data_len,
int *out_of_session,
unsigned char seq)
{
if (msg->data_len > *out_data_len)
return E2BIG;
memcpy(out_data, msg->data, msg->data_len);
out_data[0] = seq;
*out_of_session = 1;
*out_data_len = msg->data_len;
return 0;
}
static int
rakp_get_recv_seq(ipmi_con_t *ipmi,
unsigned char *data,
unsigned int data_len,
unsigned char *seq)
{
if (data_len < 1)
return EINVAL;
*seq = data[0];
return 0;
}
static int
rakp_handle_recv(ipmi_con_t *ipmi,
ipmi_msgi_t *rspi,
ipmi_addr_t *orig_addr,
unsigned int orig_addr_len,
ipmi_msg_t *orig_msg,
unsigned char *data,
unsigned int data_len)
{
ipmi_msg_t *msg = &(rspi->msg);
if (data_len > sizeof(rspi->data))
return E2BIG;
memcpy(rspi->data, data, data_len);
msg->data = rspi->data;
msg->data_len = data_len;
return 0;
}
static void
rakp_handle_recv_async(ipmi_con_t *ipmi,
unsigned char *tmsg,
unsigned int data_len)
{
}
static int
rakp_get_msg_tag(unsigned char *tmsg,
unsigned int data_len,
unsigned char *tag)
{
if (data_len < 8)
return EINVAL;
*tag = ipmi_get_uint32(tmsg+4) - 1; /* session id */
return 0;
}
static ipmi_payload_t rakp_payload =
{ rakp_format_msg, rakp_get_recv_seq, rakp_handle_recv,
rakp_handle_recv_async, rakp_get_msg_tag };
void
i_ipmi_rakp_shutdown(void)
{
ipmi_rmcpp_register_payload(IPMI_RMCPP_PAYLOAD_TYPE_RAKP_4, NULL);
ipmi_rmcpp_register_payload(IPMI_RMCPP_PAYLOAD_TYPE_RAKP_3, NULL);
ipmi_rmcpp_register_payload(IPMI_RMCPP_PAYLOAD_TYPE_RAKP_2, NULL);
ipmi_rmcpp_register_payload(IPMI_RMCPP_PAYLOAD_TYPE_RAKP_1, NULL);
#ifdef HAVE_OPENSSL
ipmi_rmcpp_register_authentication
(IPMI_LANP_AUTHENTICATION_ALGORITHM_RAKP_HMAC_MD5, NULL);
ipmi_rmcpp_register_authentication
(IPMI_LANP_AUTHENTICATION_ALGORITHM_RAKP_HMAC_SHA1, NULL);
#endif
ipmi_rmcpp_register_authentication
(IPMI_LANP_AUTHENTICATION_ALGORITHM_RAKP_NONE, NULL);
}
int
i_ipmi_rakp_init(void)
{
int rv;
rv = ipmi_rmcpp_register_authentication
(IPMI_LANP_AUTHENTICATION_ALGORITHM_RAKP_NONE,
&rakp_none_auth);
if (rv)
return rv;
#ifdef HAVE_OPENSSL
rv = ipmi_rmcpp_register_authentication
(IPMI_LANP_AUTHENTICATION_ALGORITHM_RAKP_HMAC_SHA1,
&rakp_hmac_sha1_auth);
if (rv) {
i_ipmi_rakp_shutdown();
return rv;
}
rv = ipmi_rmcpp_register_authentication
(IPMI_LANP_AUTHENTICATION_ALGORITHM_RAKP_HMAC_MD5,
&rakp_hmac_md5_auth);
if (rv) {
i_ipmi_rakp_shutdown();
return rv;
}
#endif
rv = ipmi_rmcpp_register_payload(IPMI_RMCPP_PAYLOAD_TYPE_RAKP_1,
&rakp_payload);
if (rv) {
i_ipmi_rakp_shutdown();
return rv;
}
rv = ipmi_rmcpp_register_payload(IPMI_RMCPP_PAYLOAD_TYPE_RAKP_2,
&rakp_payload);
if (rv) {
i_ipmi_rakp_shutdown();
return rv;
}
rv = ipmi_rmcpp_register_payload(IPMI_RMCPP_PAYLOAD_TYPE_RAKP_3,
&rakp_payload);
if (rv) {
i_ipmi_rakp_shutdown();
return rv;
}
rv = ipmi_rmcpp_register_payload(IPMI_RMCPP_PAYLOAD_TYPE_RAKP_4,
&rakp_payload);
if (rv) {
i_ipmi_rakp_shutdown();
return rv;
}
return 0;
}