Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright (C) 2021 - Google LLC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Author: Ard Biesheuvel <ardb@google.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * This is a host tool that is intended to be used to take the HMAC digest of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * the .text and .rodata sections of the fips140.ko module, and store it inside
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * the module. The module will perform an integrity selfcheck at module_init()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * time, by recalculating the digest and comparing it with the value calculated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * Note that the peculiar way an HMAC is being used as a digest with a public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  * key rather than as a symmetric key signature is mandated by FIPS 140-2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <elf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <sys/mman.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <sys/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <sys/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #include <openssl/hmac.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) static Elf64_Ehdr *ehdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) static Elf64_Shdr *shdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) static int num_shdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) static const char *strtab, *shstrtab;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) static Elf64_Sym *syms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) static int num_syms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) static Elf64_Shdr *find_symtab_section(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	for (i = 0; i < num_shdr; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 		if (shdr[i].sh_type == SHT_SYMTAB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 			return &shdr[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) static int get_section_idx(const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	for (i = 0; i < num_shdr; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 		if (!strcmp(shstrtab + shdr[i].sh_name, name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 			return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) static int get_sym_idx(const char *sym_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	for (i = 0; i < num_syms; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		if (!strcmp(strtab + syms[i].st_name, sym_name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 			return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) static void *get_sym_addr(const char *sym_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	int i = get_sym_idx(sym_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	if (i >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		return (void *)ehdr + shdr[syms[i].st_shndx].sh_offset +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 		       syms[i].st_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) static int update_rela_ref(const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	 * We need to do a couple of things to ensure that the copied RELA data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	 * is accessible to the module itself at module init time:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	 * - the associated entry in the symbol table needs to refer to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	 *   correct section index, and have SECTION type and GLOBAL linkage.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	 * - the 'count' global variable in the module need to be set to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	 *   right value based on the size of the RELA section.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	unsigned int *size_var;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	int sec_idx, sym_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	char str[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	sprintf(str, "fips140_rela_%s", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	size_var = get_sym_addr(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	if (!size_var) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		printf("variable '%s' not found, disregarding .%s section\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 		       str, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	sprintf(str, "__sec_rela_%s", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	sym_idx = get_sym_idx(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	sprintf(str, ".init.rela.%s", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	sec_idx = get_section_idx(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	if (sec_idx < 0 || sym_idx < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 		fprintf(stderr, "failed to locate metadata for .%s section in binary\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 			name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	syms[sym_idx].st_shndx = sec_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	syms[sym_idx].st_info = (STB_GLOBAL << 4) | STT_SECTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	size_var[1] = shdr[sec_idx].sh_size / sizeof(Elf64_Rela);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static void hmac_section(HMAC_CTX *hmac, const char *start, const char *end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	void *start_addr = get_sym_addr(start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	void *end_addr = get_sym_addr(end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	HMAC_Update(hmac, start_addr, end_addr - start_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) int main(int argc, char **argv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	Elf64_Shdr *symtab_shdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	const char *hmac_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	unsigned char *dg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	unsigned int dglen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	struct stat stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	HMAC_CTX *hmac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	int fd, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	if (argc < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		fprintf(stderr, "file argument missing\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	fd = open(argv[1], O_RDWR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	if (fd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		fprintf(stderr, "failed to open %s\n", argv[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	ret = fstat(fd, &stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		fprintf(stderr, "failed to stat() %s\n", argv[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	ehdr = mmap(0, stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	if (ehdr == MAP_FAILED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		fprintf(stderr, "failed to mmap() %s\n", argv[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	shdr = (void *)ehdr + ehdr->e_shoff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	num_shdr = ehdr->e_shnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	symtab_shdr = find_symtab_section();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	syms = (void *)ehdr + symtab_shdr->sh_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	num_syms = symtab_shdr->sh_size / sizeof(Elf64_Sym);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	strtab = (void *)ehdr + shdr[symtab_shdr->sh_link].sh_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	shstrtab = (void *)ehdr + shdr[ehdr->e_shstrndx].sh_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	if (!update_rela_ref("text") || !update_rela_ref("rodata"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	hmac_key = get_sym_addr("fips140_integ_hmac_key");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	if (!hmac_key) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 		fprintf(stderr, "failed to locate HMAC key in binary\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 		exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	dg = get_sym_addr("fips140_integ_hmac_digest");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	if (!dg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 		fprintf(stderr, "failed to locate HMAC digest in binary\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 		exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	hmac = HMAC_CTX_new();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	HMAC_Init_ex(hmac, hmac_key, strlen(hmac_key), EVP_sha256(), NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	hmac_section(hmac, "__fips140_text_start", "__fips140_text_end");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	hmac_section(hmac, "__fips140_rodata_start", "__fips140_rodata_end");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	HMAC_Final(hmac, dg, &dglen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }