| /* |
| * 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; |
| } |
| |