android_kernel_samsung_msm8226/scripts/fips_crypto_utils.c

262 lines
5.7 KiB
C

/*
* Utility functions called from fips_crypto_hmac.sh.
*
* executed during Kernel build
*
*
* Author : Rohit Kothari (r.kothari@samsung.com)
* Date : 11 Feb 2014
*
* Copyright (c) 2014 Samsung Electronics
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int collect_crypto_bytes(const char *in_file, const char *section_name,
unsigned long offset, unsigned long size, const char *out_file);
int update_crypto_hmac(const char *vmlinux_path, const char *hmac_path,
unsigned long offset);
int main (int argc, char **argv)
{
if (argc < 2)
{
printf ("\nUsage : \n");
printf ("fips_crypto_utils -u vmlinux_file hmac_file offset");
printf ("fips_crypto_utils -g vmlinux_file section_name offset size out_file");
printf ("\n");
return -1;
}
if (!strcmp ("-u", argv[1]))
{
unsigned long offset = 0;
unsigned char * vmlinux_file = NULL;
unsigned char * hmac_file = NULL;
if (argc != 5)
{
printf ("\nUsage : \n");
printf ("fips_crypto_utils -u vmlinux_file hmac_file offset");
printf ("\n");
return -1;
}
vmlinux_file = argv[2];
hmac_file = argv[3];
offset = atol(argv[4]);
if (!vmlinux_file || !hmac_file || !offset)
{
printf ("./fips_crypto_utils -u vmlinux_file hmac_file offset");
return -1;
}
return update_crypto_hmac (vmlinux_file, hmac_file, offset);
}
else if (!strcmp ("-g", argv[1]))
{
const char * in_file = NULL;
const char * section_name = NULL;
unsigned long offset = 0;
unsigned long size = 0;
const char * out_file = NULL;
if (argc != 7)
{
printf ("\nUsage : \n");
printf ("./fips_crypto_utils -g vmlinux_file section_name offset size out_file");
printf ("\n");
return -1;
}
in_file = argv[2];
section_name = argv[3];
offset = atol(argv[4]);
size = atol(argv[5]);
out_file = argv[6];
if (!in_file || !section_name || !offset || !size || !out_file)
{
printf ("./fips_crypto_utils -g vmlinux_file section_name offset size out_file");
return -1;
}
return collect_crypto_bytes (in_file, section_name, offset, size, out_file);
}
else
{
printf ("\nUsage : \n");
printf ("fips_crypto_utils -u vmlinux_file hmac_file offset");
printf ("fips_crypto_utils -g vmlinux_file section_name offset size out_file");
printf ("\n");
}
return -1;
}
/*
* Given a vmlinux file, dumps "size" bytes from given "offset" to output file
* in_file : absolute path to vmlinux file
* section_name : Used only for printing / debugging
* offset : offset in file from where to dump bytes
* size : how many bytes to dump
* out_file : Output file, where to dump bytes.
* Open in append mode, to keep previous bytes, if present
* Caller need to clean up before 1st call
*
* Returns 0, if success
* -1, if error
*/
int
collect_crypto_bytes (const char * in_file, const char * section_name, unsigned long offset,
unsigned long size, const char * out_file)
{
FILE * in_fp = NULL;
FILE * out_fp = NULL;
unsigned int i = 0;
unsigned char data = 0;
if (!in_file || !section_name || !offset || !size || !out_file)
{
printf ("collect_crypto_bytes : Invalid arguments");
return -1;
}
printf ("Section : %s\n", section_name);
in_fp = fopen (in_file, "r");
if (!in_fp)
{
printf ("Unable to open file : %s", in_file);
return -1;
}
if (fseek (in_fp, offset, SEEK_SET) != 0 )
{
printf ("Unable to seek file : %s", in_file);
fclose (in_fp);
return -1;
}
out_fp = fopen (out_file, "ab");
if (!out_fp)
{
printf ("Unable to open file : %s", out_file);
fclose(in_fp);
return -1;
}
for (i = 1; i <= size; i++)
{
if ( 1 != fread (&data, sizeof(unsigned char), 1, in_fp))
{
printf ("Unable to read 1 byte from file : %s", in_file);
fclose (in_fp);
fclose (out_fp);
return -1;
}
printf ("%02x ", data);
if (1 != fwrite (&data, 1, 1, out_fp))
{
printf ("Unable to write 1 byte to file : %s", out_file);
fclose (in_fp);
fclose (out_fp);
return -1;
}
if ( !(i % 16))
printf ("\n");
}
fclose (in_fp);
fclose (out_fp);
return 0;
}
#define SHA256_DIGEST_SIZE 32
/*
* Given a vmlinux file, overwrites bytes at given offset with hmac bytes, available in
* hmac file.
* Return 0, if Success
* -1, if Error
*/
int
update_crypto_hmac (const char * vmlinux_path, const char * hmac_path, unsigned long offset)
{
FILE * vmlinux_fp = NULL;
FILE * hmac_fp = NULL;
int i = 0, j = 0;
unsigned char hmac[SHA256_DIGEST_SIZE];
if (!vmlinux_path || !hmac_path || !offset)
{
printf ("FIPS update_crypto_hmac : Invalid Params");
return -1;
}
vmlinux_fp = fopen (vmlinux_path, "r+b");
if (!vmlinux_fp)
{
printf ("Unable to open vmlinux file ");
return -1;
}
hmac_fp = fopen (hmac_path, "rb");
if (!hmac_fp)
{
printf ("Unable to open hmac file ");
fclose (vmlinux_fp);
return -1;
}
if (SHA256_DIGEST_SIZE != fread (&hmac, sizeof(unsigned char), SHA256_DIGEST_SIZE, hmac_fp))
{
printf ("Unable to read %d bytes from hmac file", SHA256_DIGEST_SIZE);
fclose (hmac_fp);
fclose (vmlinux_fp);
return -1;
}
#if 0
printf ("Hash : ");
for (i = 0; i < sizeof(hmac); i++)
printf ("%02x ", hmac[i]);
printf ("\n");
printf ("Offset : %ld", offset);
#endif
if (fseek (vmlinux_fp, offset, SEEK_SET) != 0 )
{
printf ("Unable to seek into vmlinux file.");
fclose (hmac_fp);
fclose (vmlinux_fp);
return -1;
}
if (SHA256_DIGEST_SIZE != fwrite (hmac, sizeof(unsigned char), SHA256_DIGEST_SIZE, vmlinux_fp))
{
printf ("Unable to write %d byte into vmlinux", SHA256_DIGEST_SIZE);
fclose (hmac_fp);
fclose (vmlinux_fp);
return -1;
}
fclose (vmlinux_fp);
fclose (hmac_fp);
return 0;
}