/* ****************************************************************************** * 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 ****************************************************************************** */ /* **************************************************************************** * 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 #include #include #include #ifdef IPCRYPTO #include #endif #include /* **************************************************************************** * 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 **************************************************************************** */