123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- #include <elf.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/mman.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <openssl/hmac.h>
- static Elf64_Ehdr *ehdr;
- static Elf64_Shdr *shdr;
- static int num_shdr;
- static const char *strtab, *shstrtab;
- static Elf64_Sym *syms;
- static int num_syms;
- static Elf64_Shdr *find_symtab_section(void)
- {
- int i;
- for (i = 0; i < num_shdr; i++)
- if (shdr[i].sh_type == SHT_SYMTAB)
- return &shdr[i];
- return NULL;
- }
- static int get_section_idx(const char *name)
- {
- int i;
- for (i = 0; i < num_shdr; i++)
- if (!strcmp(shstrtab + shdr[i].sh_name, name))
- return i;
- return -1;
- }
- static int get_sym_idx(const char *sym_name)
- {
- int i;
- for (i = 0; i < num_syms; i++)
- if (!strcmp(strtab + syms[i].st_name, sym_name))
- return i;
- return -1;
- }
- static void *get_sym_addr(const char *sym_name)
- {
- int i = get_sym_idx(sym_name);
- if (i >= 0)
- return (void *)ehdr + shdr[syms[i].st_shndx].sh_offset +
- syms[i].st_value;
- return NULL;
- }
- static int update_rela_ref(const char *name)
- {
-
- unsigned int *size_var;
- int sec_idx, sym_idx;
- char str[32];
- sprintf(str, "fips140_rela_%s", name);
- size_var = get_sym_addr(str);
- if (!size_var) {
- printf("variable '%s' not found, disregarding .%s section\n",
- str, name);
- return 1;
- }
- sprintf(str, "__sec_rela_%s", name);
- sym_idx = get_sym_idx(str);
- sprintf(str, ".init.rela.%s", name);
- sec_idx = get_section_idx(str);
- if (sec_idx < 0 || sym_idx < 0) {
- fprintf(stderr, "failed to locate metadata for .%s section in binary\n",
- name);
- return 0;
- }
- syms[sym_idx].st_shndx = sec_idx;
- syms[sym_idx].st_info = (STB_GLOBAL << 4) | STT_SECTION;
- size_var[1] = shdr[sec_idx].sh_size / sizeof(Elf64_Rela);
- return 1;
- }
- static void hmac_section(HMAC_CTX *hmac, const char *start, const char *end)
- {
- void *start_addr = get_sym_addr(start);
- void *end_addr = get_sym_addr(end);
- HMAC_Update(hmac, start_addr, end_addr - start_addr);
- }
- int main(int argc, char **argv)
- {
- Elf64_Shdr *symtab_shdr;
- const char *hmac_key;
- unsigned char *dg;
- unsigned int dglen;
- struct stat stat;
- HMAC_CTX *hmac;
- int fd, ret;
- if (argc < 2) {
- fprintf(stderr, "file argument missing\n");
- exit(EXIT_FAILURE);
- }
- fd = open(argv[1], O_RDWR);
- if (fd < 0) {
- fprintf(stderr, "failed to open %s\n", argv[1]);
- exit(EXIT_FAILURE);
- }
- ret = fstat(fd, &stat);
- if (ret < 0) {
- fprintf(stderr, "failed to stat() %s\n", argv[1]);
- exit(EXIT_FAILURE);
- }
- ehdr = mmap(0, stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- if (ehdr == MAP_FAILED) {
- fprintf(stderr, "failed to mmap() %s\n", argv[1]);
- exit(EXIT_FAILURE);
- }
- shdr = (void *)ehdr + ehdr->e_shoff;
- num_shdr = ehdr->e_shnum;
- symtab_shdr = find_symtab_section();
- syms = (void *)ehdr + symtab_shdr->sh_offset;
- num_syms = symtab_shdr->sh_size / sizeof(Elf64_Sym);
- strtab = (void *)ehdr + shdr[symtab_shdr->sh_link].sh_offset;
- shstrtab = (void *)ehdr + shdr[ehdr->e_shstrndx].sh_offset;
- if (!update_rela_ref("text") || !update_rela_ref("rodata"))
- exit(EXIT_FAILURE);
- hmac_key = get_sym_addr("fips140_integ_hmac_key");
- if (!hmac_key) {
- fprintf(stderr, "failed to locate HMAC key in binary\n");
- exit(EXIT_FAILURE);
- }
- dg = get_sym_addr("fips140_integ_hmac_digest");
- if (!dg) {
- fprintf(stderr, "failed to locate HMAC digest in binary\n");
- exit(EXIT_FAILURE);
- }
- hmac = HMAC_CTX_new();
- HMAC_Init_ex(hmac, hmac_key, strlen(hmac_key), EVP_sha256(), NULL);
- hmac_section(hmac, "__fips140_text_start", "__fips140_text_end");
- hmac_section(hmac, "__fips140_rodata_start", "__fips140_rodata_end");
- HMAC_Final(hmac, dg, &dglen);
- close(fd);
- return 0;
- }
|