diff --git a/README.md b/README.md index 85d495a1..433785d3 100644 --- a/README.md +++ b/README.md @@ -370,6 +370,16 @@ Please see the [utasker/README.md](utasker/README.md) for further usage and details. +
+ +#### UEFI (wolfCrypt UEFI application Example) + +This directory contains an example UEFI application that runs wolfcrypt test. + +Please see the [uefi/README.md](uefi/README.md) for further usage and +details. + +
## Notes diff --git a/uefi/Makefile b/uefi/Makefile new file mode 100644 index 00000000..83f921be --- /dev/null +++ b/uefi/Makefile @@ -0,0 +1,53 @@ +BUILD_DIR=./build +CRYPTO_SRC=./wolfssl/wolfcrypt/src +WOLFSSL_REPO=https://github.com/wolfSSL/wolfssl +CFLAGS=-fpie -ffreestanding -fno-stack-protector -fno-stack-check -fshort-wchar -mno-red-zone -maccumulate-outgoing-args -static-libgcc -nostdlib +# enable user settings +CFLAGS+= -DWOLFSSL_USER_SETTINGS +CFLAGS+=-I./wolfssl/ -I. -I/usr/include/efi +CFLAGS+=-ggdb +CC=gcc +LD=ld +LDFLAGS_START=-static -pie --no-dynamic-linker -Bsymbolic -L/usr/lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/13.2.1/ -Lgnu-efi-dir/x86_64/gnuefi -T/usr/lib/elf_x86_64_efi.lds /usr/lib/crt0-efi-x86_64.o $(LDFLAGS) +LDFLAGS_END=-lgnuefi -lefi -lgcc + +_OBJS=sha256.o sha3.o misc.o coding.o hmac.o rsa.o random.o wolfmath.o \ + integer.o tfm.o asm.o cpuid.o memory.o logging.o wc_port.o asn.o hash.o \ + main.o test.o error.o string.o aes.o wc_encrypt.o + +OBJS=$(addprefix $(BUILD_DIR)/,$(_OBJS)) + +$(shell mkdir -p $(BUILD_DIR)) + +all: wolfcrypt.efi + +.PHONY: clone_repo + +clone_repo: + @if [ ! -d $(CRYPTO_SRC) ]; then \ + git clone $(WOLFSSL_REPO); \ + fi + +create_build_dir: + @if [ ! -d $(BUILD_DIR) ]; then mkdir $(BUILD_DIR); fi + +$(BUILD_DIR)/wolfcrypt.elf: clone_repo $(OBJS) + $(LD) $(LDFLAGS_START) $(OBJS) -o $(BUILD_DIR)/wolfcrypt.elf $(LDFLAGS_END) + +wolfcrypt.efi: $(BUILD_DIR)/wolfcrypt.elf + objcopy -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel -j .rela -j .rel.* -j .rela.* -j .reloc --target efi-app-x86_64 --subsystem=10 $(BUILD_DIR)/wolfcrypt.elf wolfcrypt.efi + +$(BUILD_DIR)/test.o: $(CRYPTO_SRC)/../test/test.c + $(CC) $(CFLAGS) -c $? -o $@ + +$(BUILD_DIR)/main.o: main.c + $(CC) $(CFLAGS) -c $? -o $@ + +$(BUILD_DIR)/string.o: string.c + $(CC) $(CFLAGS) -c $? -o $@ + +$(BUILD_DIR)/%.o: $(CRYPTO_SRC)/%.c + $(CC) $(CFLAGS) -c $? -o $@ + +clean: + rm -rf $(BUILD_DIR) wolfcrypt.efi diff --git a/uefi/README.md b/uefi/README.md new file mode 100644 index 00000000..4e467b1a --- /dev/null +++ b/uefi/README.md @@ -0,0 +1,96 @@ +wolfcrypt UEFI Example Applications +=================================== + +Requires gnu-efi. Tested with qemu and OVFM UEFI implementation. It uses a +custom implementation for string.h functions (`string.c`) based on wolfBoot +`src/string.c`. You can customize the build by changing `user_settings.h` and +adding the relevant `.o` file into the Makefile `_OBJS` variable. + +# Compile + +## Pre-requisites + +``` +git make gcc gnu-efi +``` + +## build + +``` +make + +``` + +# Test on qemu + +## Pre-requisites +``` +dosfstools qemu qemu-system-x86 ovmf +``` +## Create efi disk + +We need to create a FAT partition to store efi application. + +``` +dd if=/dev/zero of=./efi.disk bs=256M count=1 +sudo mkfs.vfat ./efi.disk +``` + +Move wolfcrypt.efi and startup.nsh into the fat32 partition +``` +mkdir -p /tmp/efi +sudo mount ./efi.disk /tmp/efi -oloop +sudo cp wolfcrypt.efi /tmp/efi +sudo cp startup.nsh /tmp/efi +sudo umount /tmp/efi +``` + +## Run qemu + +``` +qemu-system-x86_64 -bios /path/to/OVMF.fd -display none -serial stdio -net none -m 256M -drive file=./efi.disk,index=0,media=disk,format=raw +``` + +/path/to/OVMF.fd may be /usr/share/edk2-ovmf/x64 or /usr/share/qemu + +## Example output + +``` +UEFI Interactive Shell v2.2 +EDK II +UEFI v2.70 (EDK II, 0x00010000) +Mapping table + FS0: Alias(s):F0a:;BLK0: + PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0) + BLK1: Alias(s): + PciRoot(0x0)/Pci(0x1,0x1)/Ata(0x0) +Press ESC in 1 seconds to skip startup.nsh or any other key to continue. +Shell> fs0: +FS0:\> wolfcrypt.efi +status: 0x0 +Image base: 0xE15E000 +------------------------------------------------------------------------------ + wolfSSL version ⸵⸶6 +------------------------------------------------------------------------------ +error test passed! +MEMORY test passed! +base64 test passed! +asn test passed! +RANDOM test passed! +SHA-256 test passed! +SHA-3 test passed! +SHAKE128 test passed! +SHAKE256 test passed! +Hash test passed! +HMAC-SHA256 test passed! +HMAC-SHA3 test passed! +AES test passed! +AES192 test passed! +AES256 test passed! +RSA test passed! +logging test passed! +mutex test passed! +Test complete +ret: 0 +FS0:\> +``` diff --git a/uefi/main.c b/uefi/main.c new file mode 100644 index 00000000..6eef1b4b --- /dev/null +++ b/uefi/main.c @@ -0,0 +1,107 @@ + +#include +#include +#include +#include +#include + +#define STR_SIZE 512 + +#ifndef WAIT_FOR_GDB +#define WAIT_FOR_GDB 0 +#endif + +#define uefi_printf(_f_, ...) Print(L##_f_, ##__VA_ARGS__) + +void char8_to_char16(const char* str8, wchar_t* str16) +{ + size_t i; + size_t size_str8 = strlen(str8); + for (i = 0; i < size_str8; ++i) { + str16[i] = (wchar_t)str8[i]; + } + str16[i] = '\0'; +} + +void logging_cb(const int logLevel, const char *const logMessage) +{ + wchar_t str16[STR_SIZE]; + char8_to_char16(logMessage, str16); + uefi_printf("%s", str16); +} + +void *XMALLOC(size_t n, void* heap, int type) +{ + return AllocateZeroPool(n); +} + +void *XREALLOC(void *p, size_t n, void* heap, int type) +{ + FreePool(p); + p = NULL; + return AllocateZeroPool(n); +} + +void XFREE(void *p, void* heap, int type) +{ + return FreePool(p); +} + +/* TODO: remove dependencies in random.c to open/read/close */ +int open (const char *__file, int __oflag) +{ + uefi_printf("open\n"); + return -1; +} + +ssize_t read (int __fd, void *__buf, size_t __nbytes) +{ + uefi_printf("read\n"); + return -1; +} + +int close(int __fd) +{ + uefi_printf("close\n"); + return -1; +} + +EFI_STATUS +EFIAPI +efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) +{ + EFI_LOADED_IMAGE *loaded_image = NULL; + volatile int debug = 1; + EFI_STATUS status; + int ret; + + InitializeLib(ImageHandle, SystemTable); + wolfSSL_Debugging_ON(); + wolfSSL_SetLoggingCb(logging_cb); + + status = uefi_call_wrapper(SystemTable->BootServices->HandleProtocol, + 3, + ImageHandle, + &LoadedImageProtocol, + (void **)&loaded_image); + Print(L"status: 0x%lx\n", status); + Print(L"Image base: 0x%lx\n", loaded_image->ImageBase); + +#if WAIT_FOR_GDB + /* to debug from gdb: + * + * 1. run qemu with -s option. Take note of Image base value printed by the + * app. + * 2. run gdb, use command: symbol-file wolfcrypt.elf -o $image_base + * with image based value from the print above. + * 3. set variable debug = 0 to exit the loop and continue the debugging */ + while(debug) {}; +#else + (void)debug; +#endif + + ret = wolfcrypt_test(NULL); + Print(L"ret: %d\n", ret); + + return EFI_SUCCESS; +} diff --git a/uefi/startup.nsh b/uefi/startup.nsh new file mode 100644 index 00000000..26fd77a4 --- /dev/null +++ b/uefi/startup.nsh @@ -0,0 +1,2 @@ +fs0: +wolfcrypt.efi diff --git a/uefi/string.c b/uefi/string.c new file mode 100644 index 00000000..40cc4e53 --- /dev/null +++ b/uefi/string.c @@ -0,0 +1,227 @@ +/* string.c + * + * Implementations of standard library functions to eliminate external dependencies. + * + * + * Copyright (C) 2021 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSLL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#include +#include + +int islower(int c) +{ + return (c >= 'a' && c <= 'z'); +} + +int isupper(int c) +{ + return (c >= 'A' && c <= 'Z'); +} + +int tolower(int c) +{ + return isupper(c) ? c - 'A' + 'a' : c; +} + +int toupper(int c) +{ + return islower(c) ? c - 'a' + 'A' : c; +} + +int isalpha(int c) +{ + return (isupper(c) || islower(c)); +} + +char *strcat(char *dest, const char *src) +{ + size_t i = 0; + size_t j = strlen(dest); + + for (i = 0; i < strlen(src); i++) { + dest[j++] = src[i]; + } + dest[j] = '\0'; + + return dest; +} + +int strcmp(const char *s1, const char *s2) +{ + int diff = 0; + + while (!diff && *s1) { + diff = (int)*s1 - (int)*s2; + s1++; + s2++; + } + + return diff; +} + +int strcasecmp(const char *s1, const char *s2) +{ + int diff = 0; + + while (!diff && *s1) { + diff = (int)*s1 - (int)*s2; + + if ((diff == 'A' - 'a') || (diff == 'a' - 'A')) + diff = 0; + + s1++; + s2++; + } + + return diff; +} + +int strncasecmp(const char *s1, const char *s2, size_t n) +{ + int diff = 0; + size_t i = 0; + + while (!diff && *s1) { + diff = (int)*s1 - (int)*s2; + + if ((diff == 'A' - 'a') || (diff == 'a' - 'A')) + diff = 0; + + s1++; + s2++; + if (++i > n) + break; + } + return diff; +} + +char *strncat(char *dest, const char *src, size_t n) +{ + size_t i = 0; + size_t j = strlen(dest); + + for (i = 0; i < strlen(src); i++) { + if (j >= (n - 1)) { + break; + } + dest[j++] = src[i]; + } + dest[j] = '\0'; + + return dest; +} + +int strncmp(const char *s1, const char *s2, size_t n) +{ + int diff = 0; + + while (n > 0) { + diff = (unsigned char)*s1 - (unsigned char)*s2; + if (diff || !*s1) + break; + s1++; + s2++; + n--; + } + + return diff; +} + +char *strncpy(char *dst, const char *src, size_t n) +{ + size_t i; + + for (i = 0; i < n; i++) { + dst[i] = src[i]; + if (src[i] == '\0') + break; + } + + return dst; +} + +char *strcpy(char *dst, const char *src) +{ + size_t i = 0; + + while(1) { + dst[i] = src[i]; + if (src[i] == '\0') + break; + i++; + } + + return dst; +} + +int memcmp(const void *_s1, const void *_s2, size_t n) +{ + int diff = 0; + const unsigned char *s1 = (const unsigned char *)_s1; + const unsigned char *s2 = (const unsigned char *)_s2; + + while (!diff && n) { + diff = (int)*s1 - (int)*s2; + s1++; + s2++; + n--; + } + + return diff; +} + +void* memchr(void const *s, int c_in, size_t n) +{ + unsigned char c = (unsigned char)c_in; + unsigned char *char_ptr = (unsigned char*)s; + for (; n > 0; --n, ++char_ptr) { + if (*char_ptr == c) { + return (void*)char_ptr; + } + } + return NULL; +} + +size_t strlen(const char *s) +{ + size_t i = 0; + + while (s[i] != 0) + i++; + + return i; +} + +void *memmove(void *dst, const void *src, size_t n) +{ + int i; + if (dst == src) + return dst; + if (src < dst) { + const char *s = (const char *)src; + char *d = (char *)dst; + for (i = n - 1; i >= 0; i--) { + d[i] = s[i]; + } + return dst; + } else { + return memcpy(dst, src, n); + } +} diff --git a/uefi/user_settings.h b/uefi/user_settings.h new file mode 100644 index 00000000..257f8020 --- /dev/null +++ b/uefi/user_settings.h @@ -0,0 +1,24 @@ +#define WOLFCRYPT_ONLY +#define HAVE_ENTROPY_MEMUSE +#define ENTROPY_MEMUSE_FORCE_FAILURE +#define USE_FAST_MATH +#define FP_MAX_BITS 8192 +#define WOLFSSL_SHA3 +#define HAVE_HASHDRBG +#define SINGLE_THREADED +#define XMALLOC_USER +#define NO_MD5 +#define NO_SHA +#define NO_PKCS8 +#define NO_PKCS12 +#define NO_DSA +#define NO_ASN_TIME +#define NO_FILESYSTEM +#define NO_INLINE +#define NO_DH +#define NO_DES3 +#define NO_MD4 +#define NO_SIG_WRAPPER +#define NO_PWDBASED +#define NO_ERROR_STRINGS +#define XPRINTF(_f_, ...) Print(L##_f_, ##__VA_ARGS__)