blob: e444954448e1fe25908f4fab0335151118618f89 [file] [log] [blame]
/*
* Utility functions called from fips_fmp_hmac.sh.
*
* executed during Kernel build
*
* Copyright (c) 2014 Samsung Electronics
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 0x100000
int update_fmp_hmac(const char *vmlinux_path, const char *hmac_path, unsigned long offset);
int collect_fmp_bytes(const char *in_file, const char *section_name, unsigned long offset,
unsigned long size, const char *out_file);
int main(int argc, char **argv)
{
if (argc < 2) {
printf("\nUsage : \n");
printf("fips_fmp_utils -u vmlinux_file hmac_file offset");
printf("fips_fmp_utils -g vmlinux_file section_name offset size out_file");
printf("\n");
return -1;
}
if (!strncmp("-u", argv[1], sizeof("-u"))) {
unsigned long offset = 0;
unsigned char *vmlinux_file = NULL;
unsigned char *hmac_file = NULL;
if (argc != 5) {
printf("\nUsage : \n");
printf("fips_fmp_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_fmp_utils -u vmlinux_file hmac_file offset");
return -1;
}
return update_fmp_hmac(vmlinux_file, hmac_file, offset);
} else if (!strncmp("-g", argv[1], sizeof("-g"))) {
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_fmp_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_fmp_utils -g vmlinux_file section_name offset size out_file");
return -1;
}
if (size > MAX_SIZE) {
printf("Fail fips_fmp_utils due to invalid size: %ld\n", size);
return -1;
}
return collect_fmp_bytes(in_file, section_name, offset, size, out_file);
} else {
printf("\nUsage : \n");
printf("fips_fmp_utils -u vmlinux_file hmac_file offset");
printf("fips_fmp_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_fmp_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_fmp_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;
}
if (size > MAX_SIZE) {
printf("Fail fips_fmp_utils due to invalid size: %ld\n", size);
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_fmp_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_fmp_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 (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;
}