236 lines
5.5 KiB
C
236 lines
5.5 KiB
C
|
/*
|
||
|
* 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;
|
||
|
}
|
||
|
|