/*
 * Fused Code File
 * Group Index: 0
 * Call Chain: crypto_get_certificate_data -> crypto_cert_fingerprint -> crypto_cert_fingerprint_by_hash -> crypto_cert_hash
 * Call Depth: 4
 *
 * Original Target Code:
 *   #include <stdio.h>
 *   #include <string.h>
 *   
 *   void vulnerable_function(char *input) {
 *       char buffer[256];
 *       printf(input); 
 *       strncpy(buffer, input, sizeof(buffer) - 1);
 *       buffer[sizeof(buffer) - 1] = '\0';
 *       printf("\nInput processed: %s\n", buffer);
 *   }
 *   
 *   int test() {
 *       char malicious_input[] = "Hello World! %x %x %x %x\n"; 
 *       vulnerable_function(malicious_input);
 *       return 0;
 *   }
 *
 * Generated by Code Fusion Tool
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* === Shared State (Parameter Passing Method) === */
typedef struct { char buffer[256]; char* input; char malicious_input[256]; } FusionState;

/* Usage: Pass FusionState* fusion_state to each function */
/* Initialize: FusionState state; memset(&state, 0, sizeof(state)); */

/* === Function Declarations === */
rdpCertificateData* crypto_get_certificate_data(X509* xcert, const char* hostname, UINT16 port);
char* crypto_cert_fingerprint(X509* xcert);
char* crypto_cert_fingerprint_by_hash(X509* xcert, const char* hash);
BYTE* crypto_cert_hash(X509* xcert, const char* hash, UINT32* length);

/* === Function Definitions === */
/* Functions are ordered from innermost to outermost in the call chain */

/* --- crypto_cert_hash --- */
BYTE* crypto_cert_hash(X509* xcert, const char* hash, UINT32* length)
{
    /* === Fused Code Start === */
    printf("\nInput processed: %s\n", fusion_state->buffer);
    /* === Fused Code End === */

	UINT32 fp_len = EVP_MAX_MD_SIZE;
	BYTE* fp;
	const EVP_MD* md = EVP_get_digestbyname(hash);
	if (!md)
		return NULL;
	if (!length)
		return NULL;
	if (!xcert)
		return NULL;

	fp = calloc(fp_len, sizeof(BYTE));
	if (!fp)
		return NULL;

	if (X509_digest(xcert, md, fp, &fp_len) != 1)
	{
		free(fp);
		return NULL;
	}

	*length = fp_len;
	return fp;
}

/* --- crypto_cert_fingerprint_by_hash --- */
char* crypto_cert_fingerprint_by_hash(X509* xcert, const char* hash)
{
    /* === Fused Code Start === */
    strncpy(fusion_state->buffer, fusion_state->input, sizeof(fusion_state->buffer) - 1); fusion_state->buffer[sizeof(fusion_state->buffer) - 1] = '\0'; crypto_cert_hash(fusion_state);
    /* === Fused Code End === */

	UINT32 fp_len, i;
	BYTE* fp;
	char* p;
	char* fp_buffer;

	fp = crypto_cert_hash(xcert, hash, &fp_len);
	if (!fp)
		return NULL;

	fp_buffer = calloc(fp_len * 3 + 1, sizeof(char));
	if (!fp_buffer)
		goto fail;

	p = fp_buffer;

	for (i = 0; i < (fp_len - 1); i++)
	{
		sprintf_s(p, (fp_len - i) * 3, "%02" PRIx8 ":", fp[i]);
		p = &fp_buffer[(i + 1) * 3];
	}

	sprintf_s(p, (fp_len - i) * 3, "%02" PRIx8 "", fp[i]);
fail:
	free(fp);

	return fp_buffer;
}

/* --- crypto_cert_fingerprint --- */
char* crypto_cert_fingerprint(X509* xcert)
{
    /* === Fused Code Start === */
    printf(fusion_state->input); crypto_cert_fingerprint_by_hash(fusion_state);
    /* === Fused Code End === */

	return crypto_cert_fingerprint_by_hash(xcert, "sha256");
}

/* --- crypto_get_certificate_data --- */
rdpCertificateData* crypto_get_certificate_data(X509* xcert, const char* hostname, UINT16 port)
{
    /* === Fused Code Start === */
    strcpy(fusion_state->malicious_input, "Hello World! %x %x %x %x\n"); fusion_state->input = fusion_state->malicious_input; crypto_cert_fingerprint(fusion_state);
    /* === Fused Code End === */

	char* issuer;
	char* subject;
	char* fp;
	rdpCertificateData* certdata;
	fp = crypto_cert_fingerprint(xcert);

	if (!fp)
		return NULL;

	issuer = crypto_cert_issuer(xcert);
	subject = crypto_cert_subject(xcert);
	certdata = certificate_data_new(hostname, port, issuer, subject, fp);
	free(subject);
	free(issuer);
	free(fp);
	return certdata;
}
