305 lines
8.2 KiB
C
305 lines
8.2 KiB
C
/*
|
|
******************************************************************************
|
|
* INTERPEAK SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_key_fingerprint.c,v $ $Revision: 1.12.10.1 $
|
|
* $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_key_fingerprint.c,v $
|
|
* $Author: jren $
|
|
* $State: Exp $ $Locker: $
|
|
*
|
|
* INTERPEAK_COPYRIGHT_STRING
|
|
* Design and implementation by Roger Boden <roger@interpeak.se>
|
|
******************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 1 DESCRIPTION
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
|
|
#include "ipssh_config.h"
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#ifdef IPSSH_USE_KEY_FINGERPRINT
|
|
|
|
#include "ipssh_h.h"
|
|
#include "ipssh.h"
|
|
#include "ipssh_buffer.h"
|
|
|
|
#include <ipcom_type.h>
|
|
#include <ipcom_cstyle.h>
|
|
#include <ipcom_clib.h>
|
|
#include <ipcom_err.h>
|
|
|
|
#ifdef IPCRYPTO
|
|
#include <ipcrypto.h>
|
|
#endif
|
|
|
|
#include <openssl/evp.h>
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#define IPSSH_MD5 1
|
|
#define IPSSH_SHA1 2
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 STATIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipssh_hash_data
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC Ip_u8*
|
|
ipssh_hash_data(Ip_u8* data, Ip_size_t data_len, int dgst_type, unsigned int* dgst_len)
|
|
{
|
|
const EVP_MD *md = IP_NULL;
|
|
EVP_MD_CTX ctx;
|
|
Ip_u8* retval;
|
|
|
|
switch(dgst_type)
|
|
{
|
|
case IPSSH_MD5:
|
|
md = EVP_md5();
|
|
break;
|
|
case IPSSH_SHA1:
|
|
md = EVP_sha1();
|
|
break;
|
|
default:
|
|
return IP_NULL;
|
|
}
|
|
if (!md)
|
|
return IP_NULL;
|
|
|
|
*dgst_len = 0;
|
|
retval = ipcom_malloc(EVP_MAX_MD_SIZE);
|
|
if(!retval)
|
|
return IP_NULL;
|
|
|
|
if (!EVP_DigestInit(&ctx, md)
|
|
|| !EVP_DigestUpdate(&ctx, (char*)data, data_len)
|
|
|| !EVP_DigestFinal(&ctx, retval, dgst_len))
|
|
{
|
|
ipcom_free(retval);
|
|
EVP_MD_CTX_cleanup(&ctx);
|
|
return IP_NULL;
|
|
}
|
|
|
|
EVP_MD_CTX_cleanup(&ctx);
|
|
return retval;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipssh_key_fingerprint_hex
|
|
*===========================================================================
|
|
*/
|
|
IP_STATIC char*
|
|
ipssh_key_fingerprint_hex(Ip_u8* dgst, unsigned int dgst_len)
|
|
{
|
|
char *retval;
|
|
unsigned int i;
|
|
|
|
retval = ipcom_malloc(dgst_len * 3 + 1);
|
|
if (retval == IP_NULL)
|
|
return IP_NULL;
|
|
retval[0] = '\0';
|
|
for (i = 0; i < dgst_len; i++) {
|
|
char hex[4];
|
|
ipcom_snprintf(hex, sizeof(hex), "%02x:", dgst[i]);
|
|
ipcom_strncat(retval, hex, dgst_len*3 - ipcom_strlen(retval));
|
|
}
|
|
retval[(dgst_len * 3) - 1] = '\0';
|
|
return retval;
|
|
}
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 GLOBAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 11 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipssh_key_fingerprint
|
|
*===========================================================================
|
|
*/
|
|
IP_PUBLIC Ip_err
|
|
ipssh_key_fingerprint2(EVP_PKEY* key, int key_type, char** fp, int fp_type)
|
|
{
|
|
Ipcom_buffer* buf;
|
|
Ip_err rc = IPCOM_SUCCESS;
|
|
Ip_u8* hash = IP_NULL;
|
|
unsigned int hash_len;
|
|
|
|
if (!key || !fp || (key_type == IPSSH_V1_RSA_ID && key->type != EVP_PKEY_RSA))
|
|
return IPCOM_ERR_INVALID_ARG;
|
|
|
|
buf = ipcom_buffer_new(512);
|
|
if(!buf)
|
|
return IPCOM_ERR_NO_MEMORY;
|
|
|
|
switch(key_type)
|
|
{
|
|
case EVP_PKEY_DSA:
|
|
if(ipssh_buffer_put_sshstr(buf, IPSSH_DSA_STR)
|
|
|| 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)
|
|
{
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cleanup;
|
|
}
|
|
break;
|
|
|
|
#ifdef IPSSH_USE_RSA
|
|
case IPSSH_V1_RSA_ID:
|
|
if (!BN_bn2bin(key->pkey.rsa->n, ipcom_buffer_end_ptr(buf))
|
|
|| ipcom_buffer_decr_cap(buf, BN_num_bytes(key->pkey.rsa->n)) != IPCOM_SUCCESS
|
|
|| !BN_bn2bin(key->pkey.rsa->e, ipcom_buffer_end_ptr(buf))
|
|
|| ipcom_buffer_decr_cap(buf, BN_num_bytes(key->pkey.rsa->e)) != IPCOM_SUCCESS)
|
|
{
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cleanup;
|
|
}
|
|
|
|
break;
|
|
|
|
case EVP_PKEY_RSA:
|
|
if(ipssh_buffer_put_sshstr(buf, IPSSH_RSA_STR)
|
|
|| ipssh_buffer_put_bn(buf, key->pkey.rsa->e) < 0
|
|
|| ipssh_buffer_put_bn(buf, key->pkey.rsa->n) < 0)
|
|
{
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cleanup;
|
|
}
|
|
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
rc = IPCOM_ERR_INVALID_ARG;
|
|
goto cleanup;
|
|
}
|
|
|
|
switch(fp_type)
|
|
{
|
|
case IPSSH_BUBBLE_BABBLE:
|
|
hash = ipssh_hash_data(ipcom_buffer_start_ptr(buf), ipcom_buffer_len(buf), IPSSH_SHA1, &hash_len);
|
|
if(!hash)
|
|
{
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cleanup;
|
|
}
|
|
#ifdef IPCRYPTO
|
|
*fp = ipcrypto_key_fingerprint_bubblebabble(hash, hash_len);
|
|
#else
|
|
*fp = ipssh_key_fingerprint_bubblebabble(hash, hash_len);
|
|
#endif
|
|
break;
|
|
|
|
case IPSSH_HEX:
|
|
hash = ipssh_hash_data(ipcom_buffer_start_ptr(buf), ipcom_buffer_len(buf), IPSSH_MD5, &hash_len);
|
|
if(!hash)
|
|
{
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cleanup;
|
|
}
|
|
*fp = ipssh_key_fingerprint_hex(hash, hash_len);
|
|
break;
|
|
|
|
default:
|
|
IP_PANIC();
|
|
rc = IPCOM_ERR_FAILED;
|
|
goto cleanup;
|
|
}
|
|
|
|
cleanup:
|
|
if(buf)
|
|
ipcom_buffer_free(buf);
|
|
if(hash)
|
|
ipcom_free(hash);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipssh_key_fingerprint
|
|
*===========================================================================
|
|
*/
|
|
IP_PUBLIC Ip_err
|
|
ipssh_key_fingerprint(EVP_PKEY* key, char** fp, int fp_type)
|
|
{
|
|
return ipssh_key_fingerprint2(key, key->type, fp, fp_type);
|
|
}
|
|
|
|
#else
|
|
void ipssh_key_fingerprint_empty_file(void);
|
|
void ipssh_key_fingerprint_empty_file(void) { }
|
|
#endif /* IPSSH_USE_KEY_FINGERPRINT */
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|
|
|