original files of m241
This commit is contained in:
@@ -0,0 +1,910 @@
|
||||
/*
|
||||
******************************************************************************
|
||||
* SOURCE FILE
|
||||
*
|
||||
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_buffer.c,v $ $Revision: 1.53.10.5 $
|
||||
* $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_buffer.c,v $
|
||||
* $Author: jren $ $Date: 2016-10-31 08:49:42 $
|
||||
* $State: Exp $ $Locker: $
|
||||
*
|
||||
* INTERPEAK_COPYRIGHT_STRING
|
||||
* Design and implementation by Roger Boden <roger@interpeak.se>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 1 DESCRIPTION
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 2 CONFIGURATION
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 3 INCLUDE FILES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
#include "ipssh_h.h"
|
||||
#include "ipssh_buffer.h"
|
||||
|
||||
#include <ipcom_clib.h>
|
||||
#include <ipcom_sock.h>
|
||||
#include <ipcom_err.h>
|
||||
#include <ipcom_buffer.h>
|
||||
#include <ipcom_syslog.h>
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 4 EXTERN PROTOTYPES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 5 DEFINES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 6 TYPES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 7 LOCAL PROTOTYPES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 8 DATA
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 9 LOCAL FUNCTIONS
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 10 PUBLIC FUNCTIONS
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipssh_buffer_get_sshstr
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_PUBLIC char*
|
||||
#if defined(IPCOM_USE_DMALLOC) && !defined(IPCOM_DMALLOC_C)
|
||||
ipssh_buffer_get_sshstr_d(Ipcom_buffer* buf, const char *file, const char *function, Ip_u32 line)
|
||||
#else
|
||||
ipssh_buffer_get_sshstr(Ipcom_buffer* buf)
|
||||
#endif
|
||||
{
|
||||
Ip_u32 len;
|
||||
char* str;
|
||||
|
||||
if(ipssh_buffer_get_uint(buf, &len) != IPCOM_SUCCESS)
|
||||
return IP_NULL;
|
||||
if(len > ipcom_buffer_len(buf))
|
||||
return IP_NULL;
|
||||
|
||||
#if defined(IPCOM_USE_DMALLOC) && !defined(IPCOM_DMALLOC_C)
|
||||
str = ipcom_dmalloc(len+1, file, function, line);
|
||||
#else
|
||||
str = ipcom_malloc(len+1);
|
||||
#endif
|
||||
if(!str)
|
||||
return IP_NULL;
|
||||
|
||||
if(ipcom_buffer_get(buf, (Ip_u8*)str, len) != IPCOM_SUCCESS)
|
||||
{
|
||||
ipcom_free(str);
|
||||
return IP_NULL;
|
||||
}
|
||||
|
||||
str[len] = 0;
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipssh_buffer_get_sshbuf
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_PUBLIC Ip_u8*
|
||||
ipssh_buffer_get_sshbuf(Ipcom_buffer* buf, Ip_u32* len)
|
||||
{
|
||||
char* data;
|
||||
|
||||
if(ipssh_buffer_get_uint(buf, len) != IPCOM_SUCCESS)
|
||||
return IP_NULL;
|
||||
if(*len == 0)
|
||||
return IP_NULL;
|
||||
if(*len>ipcom_buffer_len(buf))
|
||||
return IP_NULL;
|
||||
|
||||
data = ipcom_malloc(*len);
|
||||
if(!data)
|
||||
return IP_NULL;
|
||||
|
||||
if(ipcom_buffer_get(buf, (Ip_u8*)data, *len) != IPCOM_SUCCESS)
|
||||
{
|
||||
ipcom_free(data);
|
||||
return IP_NULL;
|
||||
}
|
||||
|
||||
return (Ip_u8*)data;
|
||||
}
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipssh_buffer_put_sshstr
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_PUBLIC Ip_err
|
||||
ipssh_buffer_put_sshstr(Ipcom_buffer* buf, const char* str)
|
||||
{
|
||||
Ip_size_t len;
|
||||
|
||||
if(!str)
|
||||
return ipcom_buffer_put_int(buf, 0);
|
||||
|
||||
len = ipcom_strlen(str);
|
||||
|
||||
if(ipcom_buffer_put_int(buf, ip_htonl(len)))
|
||||
return IPCOM_ERR_FAILED;
|
||||
return ipcom_buffer_put(buf, (Ip_u8*)str, len);
|
||||
}
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipssh_buffer_put_sshbuf
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_PUBLIC Ip_err
|
||||
ipssh_buffer_put_sshbuf(Ipcom_buffer* buf, const Ip_u8* str, Ip_size_t len)
|
||||
{
|
||||
if ( ipcom_buffer_put_int(buf, ip_htonl(len)))
|
||||
return IPCOM_ERR_FAILED;
|
||||
return ipcom_buffer_put(buf, (Ip_u8*)str, len);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipssh_buffer_put_bn
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_PUBLIC Ip_err
|
||||
ipssh_buffer_put_bn(Ipcom_buffer* buf, BIGNUM* bn)
|
||||
{
|
||||
int len;
|
||||
Ip_u8* tmp_bn;
|
||||
Ip_s32 rc;
|
||||
|
||||
len = BN_num_bytes(bn);
|
||||
if (len == 0)
|
||||
return IPCOM_ERR_FAILED;
|
||||
if(!(tmp_bn = ipcom_malloc(len+1)))
|
||||
return IPCOM_ERR_FAILED;
|
||||
tmp_bn[0] = 0;
|
||||
if(BN_bn2bin(bn, tmp_bn+1) != len)
|
||||
{
|
||||
ipcom_free(tmp_bn);
|
||||
return IPCOM_ERR_FAILED;
|
||||
}
|
||||
|
||||
if(tmp_bn[1] & 0x80) /* if most significant bit is set, a zero byte must be added */
|
||||
{
|
||||
len++;
|
||||
rc = ipssh_buffer_put_ssh_mpint(buf, tmp_bn, len);
|
||||
}
|
||||
else
|
||||
rc = ipssh_buffer_put_ssh_mpint(buf, &(tmp_bn[1]), len);
|
||||
|
||||
ipcom_free(tmp_bn);
|
||||
if(rc != IPCOM_SUCCESS)
|
||||
return IPCOM_ERR_FAILED;
|
||||
else
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipssh_buffer_get_ssh_mpint2
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_PUBLIC Ip_err
|
||||
ipssh_buffer_get_ssh_mpint2(Ipcom_buffer* buf, BIGNUM** bnp)
|
||||
{
|
||||
Ip_u32 len;
|
||||
BIGNUM* bn = *bnp;
|
||||
|
||||
if(ipssh_buffer_get_uint(buf, &len) != IPCOM_SUCCESS)
|
||||
return IPCOM_ERR_FAILED;
|
||||
|
||||
if(len>ipcom_buffer_len(buf))
|
||||
return IPCOM_ERR_FAILED;
|
||||
|
||||
bn = BN_bin2bn(ipcom_buffer_start_ptr(buf), len, bn);
|
||||
if(IP_NULL == bn)
|
||||
return IPCOM_ERR_FAILED;
|
||||
|
||||
(void)ipcom_buffer_consume(buf, len);
|
||||
*bnp = bn;
|
||||
|
||||
return IPCOM_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipssh_buffer_put_ssh_mpint
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_PUBLIC Ip_err
|
||||
ipssh_buffer_put_ssh_mpint(Ipcom_buffer* buf, Ip_u8* mpint, Ip_size_t len)
|
||||
{
|
||||
/* If most significant bit is set, a zero byte must be added */
|
||||
if(mpint[0] & 0x80)
|
||||
{
|
||||
if ( ipcom_buffer_put_int(buf, ip_htonl(len+1)) ||
|
||||
ipcom_buffer_put_char(buf, 0))
|
||||
{
|
||||
return IPCOM_ERR_FAILED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ipcom_buffer_put_int(buf, ip_htonl(len)))
|
||||
{
|
||||
return IPCOM_ERR_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
return ipcom_buffer_put(buf, mpint, len);
|
||||
}
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipssh_buffer_get_int
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_PUBLIC Ip_err
|
||||
ipssh_buffer_get_int(Ipcom_buffer* buf, Ip_s32* val)
|
||||
{
|
||||
if(ipcom_buffer_get_int(buf, val))
|
||||
return IPCOM_ERR_FAILED;
|
||||
|
||||
*val = ip_ntohl(*val);
|
||||
return IPCOM_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipssh_buffer_get_u64
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_PUBLIC Ip_err
|
||||
ipssh_buffer_get_u64(Ipcom_buffer* buf, Ip_u64* val)
|
||||
{
|
||||
Ip_u32 hi, lo;
|
||||
if(ipcom_buffer_get_int(buf, (Ip_s32*)&hi) ||
|
||||
ipcom_buffer_get_int(buf, (Ip_s32*)&lo))
|
||||
{
|
||||
return IPCOM_ERR_FAILED;
|
||||
}
|
||||
|
||||
IP_U64_SET(*val, ip_ntohl(hi), ip_ntohl(lo));
|
||||
|
||||
return IPCOM_SUCCESS;
|
||||
}
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipssh_buffer_get_u64
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipssh_buffer_put_u64
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_PUBLIC Ip_err
|
||||
ipssh_buffer_put_u64(Ipcom_buffer* buf, Ip_u64 val)
|
||||
{
|
||||
Ip_u32 hi, lo;
|
||||
|
||||
hi = IP_U64_GETHI(val);
|
||||
lo = IP_U64_GETLO(val);
|
||||
|
||||
if(ipssh_buffer_put_uint(buf, hi) ||
|
||||
ipssh_buffer_put_uint(buf, lo))
|
||||
{
|
||||
return IPCOM_ERR_FAILED;
|
||||
}
|
||||
|
||||
return IPCOM_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipssh_append_list
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_GLOBAL Ip_err
|
||||
ipssh_append_list(Ipcom_buffer* buf, Ip_u8* alg_ids)
|
||||
{
|
||||
Ip_size_t len;
|
||||
Ip_size_t org_len;
|
||||
Ip_size_t len_pos;
|
||||
char* len_ptr;
|
||||
|
||||
len_pos = ipcom_buffer_len(buf);
|
||||
org_len = ipcom_buffer_len(buf);
|
||||
if(ipcom_buffer_decr_cap(buf, 4) != IPCOM_SUCCESS) /* Proceed past length field */
|
||||
return IPCOM_ERR_FAILED;
|
||||
|
||||
for(;*alg_ids != IPSSH_ID_END; alg_ids++)
|
||||
{
|
||||
const char* str;
|
||||
|
||||
str = ipssh_alg_id2str(*alg_ids);
|
||||
if(!str || ipcom_buffer_put(buf, (Ip_u8*)str, (Ip_u32)ipcom_strlen(str)))
|
||||
{
|
||||
return IPCOM_ERR_FAILED;
|
||||
}
|
||||
if(alg_ids[1] != IPSSH_ID_END) /* Add a comma if there is an additional item in the list */
|
||||
{
|
||||
if(ipcom_buffer_put(buf, (Ip_u8*)",", 1))
|
||||
{
|
||||
return IPCOM_ERR_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Update length */
|
||||
len = ipcom_buffer_len(buf) - org_len - 4;
|
||||
len_ptr = ipcom_buffer_ptr2pos(buf, len_pos);
|
||||
IP_SET_32ON8(len_ptr, ip_htonl(len));
|
||||
|
||||
return IPCOM_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipssh_buffer_put_dsa_key
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*/
|
||||
IP_GLOBAL Ip_err
|
||||
ipssh_buffer_put_dsa_key(Ipcom_buffer* buf, DSA* dsa)
|
||||
{
|
||||
Ip_size_t len;
|
||||
Ip_size_t len_pos;
|
||||
char* len_ptr;
|
||||
|
||||
len_pos = ipcom_buffer_len(buf);
|
||||
len = ipcom_buffer_len(buf);
|
||||
|
||||
if(ipcom_buffer_put_int(buf, 0)
|
||||
|| ipssh_buffer_put_sshstr(buf, IPSSH_DSA_STR)
|
||||
|| ipssh_buffer_put_bn(buf, dsa->p) < 0
|
||||
|| ipssh_buffer_put_bn(buf, dsa->q) < 0
|
||||
|| ipssh_buffer_put_bn(buf, dsa->g) < 0
|
||||
|| ipssh_buffer_put_bn(buf, dsa->pub_key) < 0)
|
||||
{
|
||||
IPCOM_LOG0(ERR, "ipssh_buffer_put_dsa_key :: ipssh_buffer_put_bn() failed");
|
||||
return IPCOM_ERR_FAILED;
|
||||
}
|
||||
|
||||
len_ptr = ipcom_buffer_ptr2pos(buf, len_pos);
|
||||
len = ipcom_buffer_len(buf)-len-4;
|
||||
IP_SET_32ON8(len_ptr, (ip_htonl(len)));
|
||||
|
||||
return IPCOM_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef IPSSH_USE_RSA
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipssh_buffer_put_rsa_key
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*/
|
||||
IP_GLOBAL Ip_err
|
||||
ipssh_buffer_put_rsa_key(Ipcom_buffer* buf, RSA* rsa)
|
||||
{
|
||||
Ip_u32 len;
|
||||
Ip_size_t len_pos;
|
||||
char* len_ptr;
|
||||
|
||||
len_pos = ipcom_buffer_len(buf);
|
||||
len = (Ip_u32)ipcom_buffer_len(buf);
|
||||
|
||||
if(ipcom_buffer_put_int(buf, 0)
|
||||
|| ipssh_buffer_put_sshstr(buf, IPSSH_RSA_STR)
|
||||
|| ipssh_buffer_put_bn(buf, rsa->e) < 0
|
||||
|| ipssh_buffer_put_bn(buf, rsa->n) < 0)
|
||||
{
|
||||
IPCOM_LOG0(ERR, "ipssh_buffer_put_rsa_key :: failed");
|
||||
return IPCOM_ERR_FAILED;
|
||||
}
|
||||
|
||||
len_ptr = ipcom_buffer_ptr2pos(buf, len_pos);
|
||||
len = (Ip_u32)(ipcom_buffer_len(buf)-len-4);
|
||||
IP_SET_32ON8(len_ptr, (ip_htonl(len)));
|
||||
|
||||
return IPCOM_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipssh_buffer_get_pub_key
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_GLOBAL EVP_PKEY*
|
||||
ipssh_buffer_get_pub_key(Ipcom_buffer* buf)
|
||||
{
|
||||
char* key_type;
|
||||
EVP_PKEY* key = IP_NULL;
|
||||
DSA* dsa_key = IP_NULL;
|
||||
RSA* rsa_key = IP_NULL;
|
||||
Ip_s32 blob_len;
|
||||
|
||||
/* Read length of key blob */
|
||||
if(ipssh_buffer_get_int(buf, &blob_len) != IPCOM_SUCCESS)
|
||||
return IP_NULL;
|
||||
|
||||
key_type = ipssh_buffer_get_sshstr(buf);
|
||||
if(!key_type)
|
||||
return IP_NULL;
|
||||
if(ipcom_strcmp(key_type, IPSSH_DSA_STR) == 0)
|
||||
{
|
||||
dsa_key = DSA_new();
|
||||
if(!dsa_key)
|
||||
goto cleanup;
|
||||
if(ipssh_buffer_get_ssh_mpint2(buf, &dsa_key->p) != IPCOM_SUCCESS
|
||||
|| ipssh_buffer_get_ssh_mpint2(buf, &dsa_key->q) != IPCOM_SUCCESS
|
||||
|| ipssh_buffer_get_ssh_mpint2(buf, &dsa_key->g) != IPCOM_SUCCESS
|
||||
|| ipssh_buffer_get_ssh_mpint2(buf, &dsa_key->pub_key) != IPCOM_SUCCESS)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
key = EVP_PKEY_new();
|
||||
if(!key)
|
||||
goto cleanup;
|
||||
|
||||
if(!EVP_PKEY_assign_DSA(key, dsa_key))
|
||||
{
|
||||
EVP_PKEY_free(key);
|
||||
key = IP_NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
(void)DSA_up_ref(dsa_key);
|
||||
}
|
||||
#ifdef IPSSH_USE_RSA
|
||||
else if(ipcom_strcmp(key_type, IPSSH_RSA_STR) == 0)
|
||||
{
|
||||
rsa_key = RSA_new();
|
||||
if(!rsa_key)
|
||||
goto cleanup;
|
||||
if(ipssh_buffer_get_ssh_mpint2(buf, &rsa_key->e) != IPCOM_SUCCESS
|
||||
|| ipssh_buffer_get_ssh_mpint2(buf, &rsa_key->n) != IPCOM_SUCCESS)
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
key = EVP_PKEY_new();
|
||||
if(!key)
|
||||
goto cleanup;
|
||||
|
||||
if(!EVP_PKEY_assign_RSA(key, rsa_key))
|
||||
{
|
||||
EVP_PKEY_free(key);
|
||||
key = IP_NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
(void)RSA_up_ref(rsa_key);
|
||||
}
|
||||
#endif /* IPSSH_USE_RSA */
|
||||
else
|
||||
goto cleanup;
|
||||
|
||||
cleanup:
|
||||
ipcom_free(key_type);
|
||||
if(rsa_key)
|
||||
RSA_free(rsa_key);
|
||||
if(dsa_key)
|
||||
DSA_free(dsa_key);
|
||||
|
||||
return key;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipssh_buffer_put_pub_key
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_GLOBAL Ip_err
|
||||
ipssh_buffer_put_pub_key(Ipcom_buffer* buf, EVP_PKEY* key)
|
||||
{
|
||||
Ip_size_t len_pos;
|
||||
Ip_u32 blob_len;
|
||||
|
||||
switch(key->type)
|
||||
{
|
||||
case NID_dsa:
|
||||
len_pos = ipcom_buffer_len(buf);
|
||||
if(ipssh_buffer_put_int(buf, 0) /* Dummy key blob length */
|
||||
||ipssh_buffer_put_sshstr(buf, IPSSH_DSA_STR))
|
||||
{
|
||||
return IPCOM_ERR_FAILED;
|
||||
}
|
||||
|
||||
if(ipssh_buffer_put_bn(buf, key->pkey.dsa->p)<0
|
||||
||ipssh_buffer_put_bn(buf, key->pkey.dsa->q)<0
|
||||
||ipssh_buffer_put_bn(buf, key->pkey.dsa->g)<0
|
||||
||ipssh_buffer_put_bn(buf, key->pkey.dsa->pub_key)<0)
|
||||
{
|
||||
return IPCOM_ERR_FAILED;
|
||||
}
|
||||
blob_len = (Ip_u32)(ipcom_buffer_len(buf) - len_pos - 4);
|
||||
IP_SET_32ON8(ipcom_buffer_ptr2pos(buf, len_pos), ip_htonl(blob_len));
|
||||
|
||||
break;
|
||||
|
||||
#ifdef IPSSH_USE_RSA
|
||||
case NID_rsaEncryption:
|
||||
len_pos = ipcom_buffer_len(buf);
|
||||
if(ipssh_buffer_put_int(buf, 0) /* Dummy key blob length */
|
||||
|| ipssh_buffer_put_sshstr(buf, IPSSH_RSA_STR))
|
||||
{
|
||||
return IPCOM_ERR_FAILED;
|
||||
}
|
||||
|
||||
if (ipssh_buffer_put_bn(buf, key->pkey.rsa->e) <0
|
||||
|| ipssh_buffer_put_bn(buf, key->pkey.rsa->n) <0)
|
||||
return IPCOM_ERR_FAILED;
|
||||
blob_len = (Ip_u32)(ipcom_buffer_len(buf) - len_pos - 4);
|
||||
IP_SET_32ON8(ipcom_buffer_ptr2pos(buf, len_pos), ip_htonl(blob_len));
|
||||
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
IP_PANIC();
|
||||
}
|
||||
|
||||
return IPCOM_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
IP_GLOBAL Ip_err
|
||||
ipssh_buffer_put_dsa_sig(Ipcom_buffer* buf, DSA_SIG* dsa_sig)
|
||||
{
|
||||
Ip_s32 r_len;
|
||||
Ip_s32 s_len;
|
||||
int i;
|
||||
int pad;
|
||||
|
||||
if (ipcom_buffer_capacity(buf) < (4+ipcom_strlen(IPSSH_DSA_STR)+4+2*IPSSH_SIG_LEN))
|
||||
return IPCOM_ERR_INVALID_ARG;
|
||||
|
||||
r_len = BN_num_bytes(dsa_sig->r);
|
||||
s_len = BN_num_bytes(dsa_sig->s);
|
||||
if (r_len > IPSSH_MAX_INT_LEN || s_len > IPSSH_MAX_INT_LEN) {
|
||||
IPCOM_LOG2(ERR, "ipssh_buffer_put_dsa_sig :: bad sig size %d %d", r_len, s_len);
|
||||
return IPCOM_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
for(i=0,pad=IPSSH_SIG_LEN-r_len; i<pad; i++)
|
||||
(void)ipcom_buffer_put_char(buf, 0);
|
||||
(void)BN_bn2bin(dsa_sig->r, ipcom_buffer_end_ptr(buf));
|
||||
(void)ipcom_buffer_decr_cap(buf, r_len);
|
||||
|
||||
for(i=0,pad=IPSSH_SIG_LEN-s_len; i<pad; i++)
|
||||
(void)ipcom_buffer_put_char(buf, 0);
|
||||
(void)BN_bn2bin(dsa_sig->s, ipcom_buffer_end_ptr(buf));
|
||||
(void)ipcom_buffer_decr_cap(buf, s_len);
|
||||
|
||||
return IPCOM_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipssh_buffer_put_bn_v1
|
||||
*===========================================================================
|
||||
* Description: Store a multiprecision integer in SSH v1 format
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*/
|
||||
IP_GLOBAL Ip_err
|
||||
ipssh_buffer_put_bn_v1(Ipcom_buffer* buf, BIGNUM* bn)
|
||||
{
|
||||
Ip_u16 bits;
|
||||
int len;
|
||||
Ip_u8* ptr;
|
||||
|
||||
bits = (Ip_u16) BN_num_bits(bn);
|
||||
len = BN_num_bytes(bn);
|
||||
if((int)ipcom_buffer_capacity(buf) < (len+2))
|
||||
{
|
||||
IPCOM_LOG2(ERR, "ipssh_buffer_put_bn_v1 :: buffer too small, buf size=%d, needed=%d",
|
||||
ipcom_buffer_capacity(buf), len+2);
|
||||
return IPCOM_ERR_FAILED;
|
||||
}
|
||||
ptr = ipcom_buffer_end_ptr(buf);
|
||||
IPSSH_SET_16_PTR(ptr, bits);
|
||||
(void)ipcom_buffer_decr_cap(buf, 2);
|
||||
|
||||
if(BN_bn2bin(bn, ipcom_buffer_end_ptr(buf)) < 0)
|
||||
{
|
||||
IPCOM_LOG0(ERR, "ipssh_buffer_put_bn_v1 :: BN_bn2bin() failed");
|
||||
return IPCOM_ERR_FAILED;
|
||||
}
|
||||
|
||||
return ipcom_buffer_decr_cap(buf, len);
|
||||
}
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipssh_buffer_put_bn2_v1
|
||||
*===========================================================================
|
||||
* Description: Store a multiprecision integer in SSH v1 format
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*/
|
||||
IP_GLOBAL Ip_err
|
||||
ipssh_buffer_put_bn2_v1(Ipcom_buffer* buf, Ip_u8* value, Ip_u16 bits)
|
||||
{
|
||||
int len;
|
||||
Ip_u8* ptr;
|
||||
|
||||
len = (bits+7)/8;
|
||||
|
||||
if(ipcom_buffer_capacity(buf) < ((Ip_u32)(len+2)))
|
||||
{
|
||||
IPCOM_LOG2(ERR, "ipssh_buffer_put_bn_v1 :: buffer too small, buf size=%d, needed=%d",
|
||||
ipcom_buffer_capacity(buf), len+2);
|
||||
return IPCOM_ERR_FAILED;
|
||||
}
|
||||
ptr = ipcom_buffer_end_ptr(buf);
|
||||
IPSSH_SET_16_PTR(ptr, bits);
|
||||
(void)ipcom_buffer_decr_cap(buf, 2);
|
||||
|
||||
if(ipcom_buffer_put(buf, value, len) != IPCOM_SUCCESS)
|
||||
{
|
||||
IPCOM_LOG0(ERR, "ipssh_buffer_put_bn2_v1 :: ipcom_buffer_put() failed");
|
||||
return IPCOM_ERR_FAILED;
|
||||
}
|
||||
|
||||
return IPCOM_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipssh_buffer_new_v1_pkt
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_GLOBAL Ipcom_buffer*
|
||||
ipssh_buffer_new_v1_pkt(Ip_size_t size, Ip_u8 pkt_type)
|
||||
{
|
||||
Ipcom_buffer* pkt;
|
||||
|
||||
pkt = ipcom_buffer_new(size);
|
||||
if(!pkt)
|
||||
return IP_NULL;
|
||||
|
||||
(void)ipcom_buffer_decr_cap(pkt, 12); /* make room for length and padding fields */
|
||||
(void)ipcom_buffer_put_char(pkt, pkt_type);
|
||||
|
||||
return pkt;
|
||||
}
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipssh_buffer_new_v2_pkt
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_GLOBAL Ipcom_buffer*
|
||||
ipssh_buffer_new_v2_pkt(Ip_size_t size, Ip_u8 pkt_type)
|
||||
{
|
||||
Ipcom_buffer* pkt;
|
||||
|
||||
pkt = ipcom_buffer_new(size + 5 + IPSSH_MAX_PAD);
|
||||
if(!pkt)
|
||||
return IP_NULL;
|
||||
|
||||
(void)ipcom_buffer_decr_cap(pkt, 5); /* make room for packet length and pad length fields */
|
||||
(void)ipcom_buffer_put_char(pkt, pkt_type);
|
||||
|
||||
return pkt;
|
||||
}
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipssh_buffer_get_v1_bn
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_GLOBAL BIGNUM*
|
||||
ipssh_buffer_get_v1_bn(Ipcom_buffer* buf)
|
||||
{
|
||||
BIGNUM* bn;
|
||||
Ip_u16 bits;
|
||||
Ip_u32 bytes;
|
||||
|
||||
if(ipcom_buffer_get(buf, (Ip_u8*)&bits, 2))
|
||||
return IP_NULL;
|
||||
bits = ip_ntohs(bits);
|
||||
bytes = (bits+7) / 8;
|
||||
if(bytes>ipcom_buffer_len(buf))
|
||||
return IP_NULL;
|
||||
|
||||
bn = BN_bin2bn(ipcom_buffer_start_ptr(buf), bytes, IP_NULL);
|
||||
if(IP_NULL == bn)
|
||||
return IP_NULL;
|
||||
|
||||
(void)ipcom_buffer_consume(buf, bytes);
|
||||
|
||||
return bn;
|
||||
}
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipssh_buffer_new_sftp_pkt
|
||||
*===========================================================================
|
||||
* Description: An sftp packet looks as follows:
|
||||
* L1 P T ID L2 L3 M P
|
||||
* | | | | | | | |
|
||||
* transport +----+-+-+
|
||||
* channel +----+----+
|
||||
* sftp +----+-+----
|
||||
*
|
||||
* L1 - Length of packet (4 bytes)
|
||||
* P - Pad length (1 byte)
|
||||
* T - Packet type (Always CHANNEL_DATA) (1 byte)
|
||||
* ID - Channel ID (4 bytes)
|
||||
* L2 - Length of CHANNEL_DATA message (4 bytes)
|
||||
* L3 - Length of sftp message (4bytes)
|
||||
* M - sftp message type (1 byte)
|
||||
* P - Payload of sftp message
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_PUBLIC Ipcom_buffer*
|
||||
ipssh_buffer_new_sftp_pkt(Ip_size_t sftp_msg_size, Ip_u8 sftp_msg_type)
|
||||
{
|
||||
Ipcom_buffer* pkt;
|
||||
|
||||
pkt = ipcom_buffer_new(sftp_msg_size+6+8+5+IPSSH_MAX_PAD); /* transport overhead, channel overhead, sftp overhead, max padding */
|
||||
if(!pkt)
|
||||
return IP_NULL;
|
||||
(void)ipcom_buffer_decr_cap(pkt, 18);
|
||||
(void)ipcom_buffer_put_char(pkt, sftp_msg_type);
|
||||
|
||||
return pkt;
|
||||
}
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipssh_buffer_new_channel_data_pkt
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_PUBLIC Ipcom_buffer*
|
||||
ipssh_buffer_new_channel_data_pkt(Ip_size_t pkt_size, Ipssh_channel* channel)
|
||||
{
|
||||
Ipcom_buffer* pkt;
|
||||
|
||||
(void) channel;
|
||||
|
||||
pkt = ipcom_buffer_new(pkt_size+6+8+IPSSH_MAX_PAD); /* transport overhead, channel overhead, max padding */
|
||||
if(!pkt)
|
||||
return IP_NULL;
|
||||
|
||||
(void)ipcom_buffer_decr_cap(pkt, 14);
|
||||
|
||||
return pkt;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* END OF FILE
|
||||
****************************************************************************
|
||||
*/
|
||||
Reference in New Issue
Block a user