SHA-256 example


/* This program is released under the Common Public License V1.0
 *
 * You should have received a copy of Common Public License V1.0 along with
 * with this program.
 *
 * Copyright IBM Corp. 2016
 *
 */

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

#include <ica_api.h>

/* The name of the file to calcualte the SHA256 hash from */
#define FILE_NAME     "example_sha256.c"

/* Size of the chunks in which the file is read.
 * Must be a multiple of 64 bytes.
 */
#define CHUNK_SIZE    1024

/* Prints hex values to standard out. */
static void dump_data(unsigned char *data, unsigned long length);
/* Prints a description of the return value to standard out. */
static int handle_ica_error(int rc);

int main(int argc, char **argv)
{
	int rc;

	/* This is the buffer where the SHA256 hash is generated into.
	 * For SHA256, it needs to be 32 bytes in size (SHA256_HASH_LENGTH).
	 */
	unsigned char sha_result[SHA256_HASH_LENGTH];

	/* The file will be read in several chunks into this buffer.
	 * The chunks will be the input to the ica_sha256 function which
	 * we call for each chunk.
	 */
	unsigned char sha_input[CHUNK_SIZE];

	/* This is the SHA 256 context. It stores intermediate values
	 * needed when chaining multiple chunks (as we do).
	 */
	sha256_context_t context;

	/* Open the file in binary mode and read its content in chunks */
	FILE *f;

	f = fopen(FILE_NAME,"r");
	if (f==NULL)
		return handle_ica_error(errno);

	int len;
	unsigned long total_size = 0;

	while(!feof(f)) {
		/* read a chunk of data */
		len = fread(sha_input, 1, CHUNK_SIZE, f);

		if (total_size == 0) {
			/* this is the first chunk */
			rc = ica_sha256(SHA_MSG_PART_FIRST,
						len, sha_input,
						&context,
						sha_result);
		}
		else if (!feof(f)) {
			/* add this chunk to the hash */
			rc = ica_sha256(SHA_MSG_PART_MIDDLE,
						len, sha_input,
						&context,
						sha_result);
		}
		else  {
			/* this is the last chunk */
			rc = ica_sha256(SHA_MSG_PART_FINAL,
						len, sha_input,
						&context,
						sha_result);
		}

		total_size += len;

		if (rc)
			break;
	}

	/* close the file */
	fclose(f);

	/* Error handling (if necessary). */
	if (rc)
		return handle_ica_error(rc);

	/* Dump the generated hash to standard output, just for
	 * a visual control.
	 *
	 * Note: You can verify the displayed hash using command
	 *       'sha256sum example_sha256.c'
	 */
	printf("SHA256 hash of file '%s' (%u bytes):\n", FILE_NAME, total_size);
	dump_data(sha_result, sizeof(sha_result));
}

static void dump_data(unsigned char *data, unsigned long length)
{
	unsigned char *ptr;
	int i;

	for (ptr = data, i = 1; ptr < (data+length); ptr++, i++) {
		printf("0x%02x ", *ptr);
		if ((i % 16) == 0)
			printf("\n");
	}
	if (i % 16)
		printf("\n");
}

static int handle_ica_error(int rc)
{
	switch (rc) {
	case 0:
		printf("OK\n");
		break;
	case EINVAL:
		printf("Incorrect parameter.\n");
		break;
	case EPERM:
		printf("Operation not permitted by Hardware (CPACF).\n");
		break;
	case EIO:
		printf("I/O error.\n");
		break;
	default:
		printf("unknown error.\n");
	}

	return rc;
}