diff --git a/cryptolib/selftest-heap/.gitignore b/cryptolib/selftest-heap/.gitignore new file mode 100644 index 00000000..e9e7c568 --- /dev/null +++ b/cryptolib/selftest-heap/.gitignore @@ -0,0 +1,3 @@ +bin/ +*.swp +main diff --git a/cryptolib/selftest-heap/Makefile b/cryptolib/selftest-heap/Makefile new file mode 100644 index 00000000..e3384ec4 --- /dev/null +++ b/cryptolib/selftest-heap/Makefile @@ -0,0 +1,76 @@ +#------------------------------------------------------------------------- +# NMAKE-Makefile +#------------------------------------------------------------------------- +PROJ=dynamic memory tracking example programs +UTIL1=dmt-utils +PROG1=dmt-realloc +PROG2=dmt-access + +#------------------------------------------------------------------------- +# Compiler-Flags General +#------------------------------------------------------------------------- +CC := gcc +CFLAGS := -g -O0 -Wall -Werror +LDD := ldd +LIBS := +INCLUDE := -I. +ifeq ($(MAKECMDGOALS),debug) + CFLAGS += -DDEBUG +endif + +#------------------------------------------------------------------------- +# Objects and Output +#------------------------------------------------------------------------- +DIR_OUTPUT := bin +DIR_UTILS := $(DIR_OUTPUT)/utils +DIR_PROGS := $(DIR_OUTPUT)/programs +UTILS := $(DIR_UTILS)/$(UTIL1) +UTILS_OBJ := $(patsubst %, %.o, $(UTILS)) +PROGRAMS := $(DIR_PROGS)/$(PROG1) $(DIR_PROGS)/$(PROG2) + +#------------------------------------------------------------------------- +# Main-Targets +#------------------------------------------------------------------------- +.PHONY: all help + +all: output $(UTILS) $(PROGRAMS) +debug: all + +output: + @if [ -d $(DIR_OUTPUT) ]; then \ + echo "dir $(DIR_OUTPUT) already exists."; \ + else \ + mkdir -p $(DIR_UTILS); \ + mkdir -p $(DIR_PROGS); \ + fi + +clean: + -$(RM) -r $(DIR_OUTPUT) + +help: + @echo + @echo "$(PROJ)" + @echo + @echo "make [all]" + @echo "make [help|clean]" + @echo + @echo "Targets : help - Shows this text." + @echo " all - Compiles the project." + @echo " debug - Enable debug output." + @echo " clean - Cleans up output files." + @echo + +#------------------------------------------------------------------------- +# Sub-Targets +#------------------------------------------------------------------------- + +# build utils +$(DIR_UTILS)/%: %.c + $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@.o + +# build programs +$(DIR_PROGS)/%: %.c + $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@.o + $(CC) $(INCLUDE) -o $@ $@.o $(UTILS_OBJ) $(LIBS) + $(LDD) $@ + diff --git a/cryptolib/selftest-heap/data_run.sh b/cryptolib/selftest-heap/data_run.sh new file mode 100755 index 00000000..9fee801f --- /dev/null +++ b/cryptolib/selftest-heap/data_run.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +set -e + +OPTIONS="--phase1 --phase2 --export --parallel" +export RESULTDIR=results + +pushd ${BASH_SOURCE%/*} +./framework.sh ${OPTIONS} basic 8 +popd diff --git a/cryptolib/selftest-heap/dmt-access.c b/cryptolib/selftest-heap/dmt-access.c new file mode 100644 index 00000000..c4000d0b --- /dev/null +++ b/cryptolib/selftest-heap/dmt-access.c @@ -0,0 +1,149 @@ +/************************************************************************ + * Copyright (C) 2017-2018 IAIK TU Graz and Fraunhofer AISEC + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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, see . + ***********************************************************************/ + +/** + * @file dmt-access.c + * @brief Dynamic memory tracking simple access selftest. + * @license This project is released under the GNU GPLv3+ License. + * @author See AUTHORS file. + * @version 0.3 + */ + +/***********************************************************************/ + +#include +#include +#include +#include +#include "dmt-utils.h" + +/***********************************************************************/ + +#define LARGE_INIT 524288 + +/***********************************************************************/ + +void help(); + +/***********************************************************************/ + +uint16_t ALLOC_TYPE = 0; +uint16_t USE_ALTERNATIVE = 0; + +/***********************************************************************/ + +/*** + * Main function. + * + * @param argc number of command line arguments + * @param argv command line arguments + * @return 0=success, else=error + */ +int main(int argc, char **argv) +{ + /* init */ + int err = 1; + uint8_t key = 0; + FILE *kfile = NULL; + unsigned char str[2]; + void *obj = NULL; + size_t objsize = 0; + char lookup = 0; + + /* check args */ + if (argc != 4) { + help(); + return (1); + } + + /* get cmdline args */ + sscanf(argv[1], "%hu", &ALLOC_TYPE); + sscanf(argv[2], "%hu", &USE_ALTERNATIVE); + + /* read key */ + kfile = fopen(argv[3], "r"); + if (!kfile) { + printf("[Error] Unable to open key file!\n"); + return (1); + } + if (fread(&str, 1, 2, kfile) != 2) { + printf("[Error] Unable to read key file!\n"); + return (1); + } + key = (str[0] % 32 + 9) % 25; + fclose(kfile); + + /* ini rnd */ + srand(getpid() + time(NULL)); + + /* allocate object */ + objsize = LARGE_INIT; + obj = dmt_allocate(objsize, ALLOC_TYPE, USE_ALTERNATIVE); + if (INVALIDPTR(obj)) { + printf("[Error] Unable to allocate object!\n"); + return (1); + } + + /* debug info */ +#ifdef DEBUG + printf("Max rand() value: %u\n", RAND_MAX); + printf("Allocate type: %s\n", (ALLOC_TYPE ? "mmap" : "malloc")); + printf("Use alternative: %s\n", (USE_ALTERNATIVE ? "yes" : "no")); + printf("Key nibble: %x\n", key); + printf("Object size: %zu\n", objsize); + printf("Object address: %0*"PRIxPTR"\n", (int)(sizeof(void*) * 2), (uintptr_t)obj); +#endif + + /* key-dependent data access */ + /* triggers H_pos(b), H_addr */ + /* expected leak stats: */ + /* difference: 1 */ + /* data leak generic: 1 */ + /* data leak specific: 1 (key byte nibble high) */ + lookup = ((uint8_t*)obj)[key]; + fprintf(stdin, "%d\n", lookup); + + /* key-independent data access */ + /* expected leak stats: */ + /* difference = 1 */ + /* data leak generic = 0 */ + /* data leak specific = 0 */ + key = rand() % 16; + lookup = ((uint8_t*)obj)[key]; + fprintf(stdin, "%d\n", lookup); + + /* deallocate */ + err = dmt_deallocate(obj, objsize, ALLOC_TYPE); + + /* done */ + return (err); +} + +/***********************************************************************/ + +/*** + * Print help text. + */ +void help() +{ + printf("Usage:\n"); + printf(" dmt-access \n\n"); + printf(" ....... 0: malloc & co, else: mmap & co\n"); + printf(" ........ 0: standard (malloc,mmap private), else: alternative (calloc,mmap shared)\n"); + printf(" ... file containing secret key byte as hex string\n"); +} + diff --git a/cryptolib/selftest-heap/dmt-realloc.c b/cryptolib/selftest-heap/dmt-realloc.c new file mode 100644 index 00000000..537565d4 --- /dev/null +++ b/cryptolib/selftest-heap/dmt-realloc.c @@ -0,0 +1,598 @@ +/************************************************************************ + * Copyright (C) 2017-2018 IAIK TU Graz and Fraunhofer AISEC + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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, see . + ***********************************************************************/ + +/** + * @file dmt-realloc.c + * @brief Dynamic memory tracking re-allocation selftest. + * @license This project is released under the GNU GPLv3+ License. + * @author See AUTHORS file. + * @version 0.3 + */ + +/***********************************************************************/ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include "dmt-utils.h" + +/***********************************************************************/ + +#define MIN_OBJ_NUMBER 13 +#define SMALL_INIT 512 +#define MEDIUM_INIT 49152 +#define LARGE_INIT 524288 +#define HUGE_INIT 5242880 + +/***********************************************************************/ + +void help(); +void* allocate(size_t size, int id); +void* reallocate(void* obj, size_t oldsize, size_t newsize, int id); +int deallocate(void* obj, size_t size, int id); +int fill(uint16_t number, void** obj); +int change(uint16_t number, void** obj); +int readaddr(void** addr, uint16_t number); +int test(uint16_t number, uint8_t key); +#ifdef DEBUG +void printstats(uint16_t number, void** obj); +void printaddr(uint16_t number, void** addr); +#endif + +/***********************************************************************/ + +uint16_t ALLOC_TYPE = 0; +uint16_t USE_ALTERNATIVE = 0; +uint16_t LEAKAGE_POINTS = 0; +size_t* ALLOC_SIZES = NULL; +uint8_t* ALLOC_CHANGED = NULL; + +/***********************************************************************/ + +uint8_t DUMMY_OBJ = 0; + +/***********************************************************************/ + +/*** + * Main function. + * + * @param argc number of command line arguments + * @param argv command line arguments + * @return 0=success, else=error + */ +int main(int argc, char **argv) +{ + /* init */ + int err; + uint16_t number; + uint8_t key; + unsigned char str[2]; + FILE *kfile = NULL; + + /* check args */ + if (argc != 6) { + help(); + return (1); + } + + /* get cmdline args */ + sscanf(argv[1], "%hu", &ALLOC_TYPE); + sscanf(argv[2], "%hu", &USE_ALTERNATIVE); + sscanf(argv[3], "%hu", &LEAKAGE_POINTS); + sscanf(argv[4], "%hu", &number); + + /* read key */ + kfile = fopen(argv[5], "r"); + if (!kfile) { + printf("[Error] Unable to open key file!\n"); + return (1); + } + if (fread(&str, 1, 2, kfile) != 2) { + printf("[Error] Unable to read key file!\n"); + return (1); + } + key = (str[0] % 32 + 9) % 25; + fclose(kfile); + + /* ini rnd */ + srand(getpid() + time(NULL)); +#ifdef DEBUG + printf("Max rand() value: %u\n", RAND_MAX); + printf("Allocate type: %s\n", (ALLOC_TYPE ? "mmap" : "malloc")); + printf("Use alternative: %s\n", (USE_ALTERNATIVE ? "yes" : "no")); + printf("Leakage points: %s\n", (LEAKAGE_POINTS ? "2" : "1")); + printf("Number of objects: %u\n", number); + printf("Key nibble: %x\n", key); +#endif + + /* sanity check */ + if (number < MIN_OBJ_NUMBER) { + printf("[Error] Number of objects too small. Please use %u or above.\n", MIN_OBJ_NUMBER); + return (1); + } + + /* test */ + err = test(number, key); + + /* done */ + return (err); +} + +/***********************************************************************/ + +/*** + * Allocate a new object with bytes. + * If is non-zero, the + * alternative will be used (e.g. calloc or + * mmap shared). + * + * @param size number of bytes to allocate + * @param id object id + * @return allocated object pointer + */ +void* allocate(size_t size, int id) +{ + /* init */ + void* obj = NULL; + + /* allocate */ + obj = dmt_allocate(size, ALLOC_TYPE, USE_ALTERNATIVE); + if (INVALIDPTR(obj)) { return(obj); } + + /* keep record */ + if (id >= 0) { + ALLOC_SIZES[id] = size; + ALLOC_CHANGED[id] = 0; + } + + /* done */ + return (obj); +} + +/*** + * Re-allocate an object to bytes. + * + * @param obj object to reallocate + * @param oldsize previous object size + * @param newsize new number of bytes to allocate + * @param id object id + * @return allocated object pointer + */ +void* reallocate(void* obj, size_t oldsize, size_t newsize, int id) +{ + /* init */ + void* objnew = NULL; + + /* re-allocate */ + objnew = dmt_reallocate(obj, oldsize, newsize, ALLOC_TYPE); + if (INVALIDPTR(objnew)) { return(objnew); } + + /* keep record */ + if (id >= 0) { + ALLOC_SIZES[id] = newsize; + if (objnew != obj) { + ALLOC_CHANGED[id] = 1; + } + } + + /* done */ + return (objnew); +} + +/*** + * Free resources of an object. + * + * @param obj object to free + * @param size allocation size in bytes + * @param id object id + * @return 0: success, else: error + */ +int deallocate(void* obj, size_t size, int id) +{ + /* init */ + int res = 0; + + /* free */ + res = dmt_deallocate(obj, size, ALLOC_TYPE); + + /* clear record */ + if (id >= 0) { + ALLOC_SIZES[id] = 0; + ALLOC_CHANGED[id] = 0; + } + + /* done */ + return (res); +} + +/***********************************************************************/ + +/*** + * Fill an array with objects of different sizes: + * 50% ... < 1kB + * 20% ... < 100kB + * 22% ... < 1MB + * 8% ... < 10MB + * + * @param number number of objects to create + * @param obj array to store objects in + * @return 0: success, else: error + */ +int fill(uint16_t number, void** obj) +{ + /* init */ + int i; + int huge = number * 0.08; + int large = number * 0.22; + int medium = number * 0.20; + int small = (number - huge - large - medium); + + /* debug */ +#ifdef DEBUG + printf("*******************************\n"); + printf("Allocating:\n"); + printf(" Small: %d\n", small); + printf(" Medium: %d\n", medium); + printf(" Large: %d\n", large); + printf(" Huge: %d\n", huge); +#endif + + /* fill */ + for (i = 0; i < small; i++) { + obj[i] = allocate(SMALL_INIT, i); + if (INVALIDPTR(obj[i])) { + printf("[Error] Could not allocate small object #%d!\n", i); + return (1); + } + } + for (; i < (small+medium); i++) { + obj[i] = allocate(MEDIUM_INIT, i); + if (INVALIDPTR(obj[i])) { + printf("[Error] Could not allocate medium object #%d!\n", i-small); + return (1); + } + } + for (; i < (small+medium+large); i++) { + obj[i] = allocate(LARGE_INIT, i); + if (INVALIDPTR(obj[i])) { + printf("[Error] Could not allocate large object #%d!\n", i-small-medium); + return (1); + } + } + for (; i < (small+medium+large+huge); i++) { + obj[i] = allocate(HUGE_INIT, i); + if (INVALIDPTR(obj[i])) { + printf("[Error] Could not allocate huge object #%d!\n", i-small-medium-large); + return (1); + } + } + + /* done */ + return (0); +} + +/***********************************************************************/ + +/*** + * Change the size of objects within an array: + * 50% ... < 1kB + * 20% ... < 100kB + * 22% ... < 1MB + * 8% ... < 10MB + * + * @param number number of objects to change + * @param obj array containing objects + * @return 0: success, else: error + */ +int change(uint16_t number, void** obj) +{ + /* init */ + int i,c,p; + int huge = number * 0.08; + int large = number * 0.22; + int medium = number * 0.20; + int small = (number - huge - large - medium); + + /* change */ + for (i = 0; i < number;) { + c = rand() % 4; + p = 0; + switch (c) { + case 0: + if (small > 0) { + small--; + obj[i] = reallocate(obj[i], ALLOC_SIZES[i], SMALL, i); + p = 1; + } + break; + case 1: + if (medium > 0) { + medium--; + obj[i] = reallocate(obj[i], ALLOC_SIZES[i], MEDIUM, i); + p = 1; + } + break; + case 2: + if (large > 0) { + large--; + obj[i] = reallocate(obj[i], ALLOC_SIZES[i], LARGE, i); + p = 1; + } + break; + case 3: + if (huge > 0) { + huge--; + obj[i] = reallocate(obj[i], ALLOC_SIZES[i], HUGE, i); + p = 1; + } + break; + } + if (INVALIDPTR(obj[i])) { + printf("[Error] Could not reallocate object #%d!\n", i); + return (1); + } + if (p) {i++;} + } + + /* done */ + return (0); +} + +/***********************************************************************/ + +/*** + * Read from the addresses in the array. + * + * @param addr array containing addresses + * @param number number of addresses + * @return helper variable + */ +int readaddr(void** addr, uint16_t number) +{ + int i,tmp; + tmp = 1; + for (i = 0; i < number; i++) { + tmp ^= ((uint8_t*)addr[i])[0]; + } + return (tmp); +} + +/***********************************************************************/ + +#ifdef DEBUG +/*** + * Print statistics of malloc and the objects + * contained in the given array. + * + * @param number number of objects + * @param obj array containing objects + */ +void printstats(uint16_t number, void** obj) +{ + /* total memory */ + struct mallinfo mi = mallinfo(); + printf("*******************************\n"); + printf("Allocated bytes: %d\n", mi.arena); + + /* objects entries */ + int i; + for (i = 0; i < number; i++) { + printf(" %*d: %*zu -- %s\n", 5, i, 10, ALLOC_SIZES[i], (ALLOC_CHANGED[i] ? "changed" : "_")); + } +} +#endif + +/***********************************************************************/ + +#ifdef DEBUG +/*** + * Print the addresses contained in + * the given array. + * + * @param number number of objects + * @param addr array containing addresses + */ +void printaddr(uint16_t number, void** addr) +{ + printf("*******************************\n"); + printf("Addresses:\n"); + int i; + for (i = 0; i < number; i++) { + printf(" %0*"PRIxPTR"\n", (int)(sizeof(void*) * 2), (uintptr_t)addr[i]); + } +} +#endif + +/***********************************************************************/ + +/*** + * Creates memory objects of sizes between + * few bytes to several megabytes. The objects will + * be resized once. + * + * @param number number of memory objects + * @param key secret key byte + * @return 0: success, else: error + */ +int test(uint16_t number, uint8_t key) +{ + /* init */ + int i,j; + int err = 1; + void** objects = NULL; + void** addr_before = NULL; + void** addr_after = NULL; + void** addr_current = NULL; + + /* create helper structures */ + ALLOC_SIZES = allocate(number * sizeof(size_t), -1); + if (INVALIDPTR(ALLOC_SIZES)) { + printf("[Error] Could not allocate size array!\n"); + goto cleanup; + } + ALLOC_CHANGED = allocate(number * sizeof(uint8_t), -1); + if (INVALIDPTR(ALLOC_CHANGED)) { + printf("[Error] Could not allocate change array!\n"); + goto cleanup; + } + addr_before = allocate(number * sizeof(void*), -1); + if (INVALIDPTR(addr_before)) { + printf("[Error] Could not allocate address array 'before'!\n"); + goto cleanup; + } + addr_after = allocate(number * sizeof(void*), -1); + if (INVALIDPTR(addr_after)) { + printf("[Error] Could not allocate address array 'after'!\n"); + goto cleanup; + } + + /* create objects */ + objects = allocate(number * sizeof(void*), -1); + if (INVALIDPTR(objects)) { + printf("[Error] Could not allocate object array!\n"); + goto cleanup; + } + if (fill(number, objects)) { + printf("[Error] Could not fill object array!\n"); + goto cleanup; + } +#ifdef DEBUG + printstats(number, objects); +#endif + + /* fill address array */ + for (i = 0; i < number; i++) { + if (rand() & 0x1) { + addr_before[i] = (void*)&DUMMY_OBJ; + } else { + addr_before[i] = (void*)((uint8_t*)(objects[i]) + key); + } + } +#ifdef DEBUG + printaddr(number, addr_before); +#endif + + /* two leakage points */ + if (LEAKAGE_POINTS) { + /* access objects */ + fprintf(stdin, "%d\n", readaddr(addr_before, number)); + + /* realloc objects */ + if (change(number, objects)) { + printf("[Error] Could not re-allocate objects!\n"); + goto cleanup; + } +#ifdef DEBUG + printstats(number, objects); +#endif + + /* fill address array */ + for (i = 0; i < number; i++) { + if (addr_before[i] != (void*)&DUMMY_OBJ) { + addr_after[i] = (void*)&DUMMY_OBJ; + } else { + addr_after[i] = (void*)((uint8_t*)(objects[i]) + key); + } + } +#ifdef DEBUG + printaddr(number, addr_after); +#endif + + /* access objects */ + fprintf(stdin, "%d\n", readaddr(addr_after, number)); + } + /* one leakage point */ + else { + addr_current = addr_before; + for (j = 0; j < 2; j++) { + /* access objects */ + fprintf(stdin, "%d\n", readaddr(addr_current, number)); + if (j == 1) { break; } + + /* realloc objects */ + if (change(number, objects)) { + printf("[Error] Could not re-allocate objects!\n"); + goto cleanup; + } +#ifdef DEBUG + printstats(number, objects); +#endif + + /* fill address array */ + for (i = 0; i < number; i++) { + if (addr_before[i] != (void*)&DUMMY_OBJ) { + addr_after[i] = (void*)&DUMMY_OBJ; + } else { + addr_after[i] = (void*)((uint8_t*)(objects[i]) + key); + } + } +#ifdef DEBUG + printaddr(number, addr_after); +#endif + addr_current = addr_after; + } + addr_current = NULL; + } + + /* done */ + err = 0; +cleanup: + if (!INVALIDPTR(objects)) { + for (i = 0; i < number; i++) { + if (!INVALIDPTR(objects[i])) { + deallocate(objects[i], ALLOC_SIZES[i], i); + objects[i] = NULL; + } + } + deallocate(objects, number * sizeof(void*), -1); + } + if (!INVALIDPTR(ALLOC_SIZES)) { + deallocate(ALLOC_SIZES, number * sizeof(size_t), -1); + } + if (!INVALIDPTR(ALLOC_CHANGED)) { + deallocate(ALLOC_CHANGED, number * sizeof(uint8_t), -1); + } + if (!INVALIDPTR(addr_before)) { + deallocate(addr_before, number * sizeof(void*), -1); + } + if (!INVALIDPTR(addr_after)) { + deallocate(addr_after, number * sizeof(void*), -1); + } + return (err); +} + +/***********************************************************************/ + +/*** + * Print help text. + */ +void help() +{ + printf("Usage:\n"); + printf(" dmt-realloc \n\n"); + printf(" ....... 0: malloc & co, else: mmap & co\n"); + printf(" ........ 0: standard (malloc,mmap private), else: alternative (calloc,mmap shared)\n"); + printf(" ..... 0: one leakage point, else: two leakage points\n"); + printf(" ..... # of objects to create, 16-bit uint\n"); + printf(" ... file containing secret key byte as hex string\n"); +} + diff --git a/cryptolib/selftest-heap/dmt-utils.c b/cryptolib/selftest-heap/dmt-utils.c new file mode 100644 index 00000000..a3fa1f24 --- /dev/null +++ b/cryptolib/selftest-heap/dmt-utils.c @@ -0,0 +1,137 @@ +/************************************************************************ + * Copyright (C) 2017-2018 IAIK TU Graz and Fraunhofer AISEC + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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, see . + ***********************************************************************/ + +/** + * @file dmt-utils.c + * @brief Dynamic memory tracking helper functions. + * @license This project is released under the GNU GPLv3+ License. + * @author See AUTHORS file. + * @version 0.3 + */ + +/***********************************************************************/ + +#define _GNU_SOURCE +#include +#include +#include "dmt-utils.h" + +/***********************************************************************/ + +/*** + * Allocate a new object with bytes. + * If is zero, malloc is used. Otherwise, + * mmap is used. If is non-zero, a slight + * variant of the allocation call is used. + * + * @param size number of bytes to allocate + * @param type 0: malloc, else: mmap + * @param alt 0: standard call, else: alternative call + * @return allocated object pointer + */ +void* dmt_allocate(size_t size, int type, int alt) +{ + /* init */ + void* obj = NULL; + + /* mmap */ + if (type) { + if (alt) { + obj = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); + } else { + obj = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + } + if (INVALIDPTR(obj)) { return(obj); } + memset(obj, 0, size); + } + /* malloc */ + else { + if (alt) { + obj = calloc(1, size); + } else { + obj = malloc(size); + if (INVALIDPTR(obj)) { return(obj); } + memset(obj, 0, size); + } + } + + /* done */ + return (obj); +} + +/***********************************************************************/ + +/*** + * Re-allocate an object to bytes. + * If is zero, realloc is used. Otherwise, + * mremap is used. + * + * @param obj object to reallocate + * @param oldsize previous object size + * @param newsize new number of bytes to allocate + * @param type 0: realloc, else: mremap + * @return re-allocated object pointer + */ +void* dmt_reallocate(void* obj, size_t oldsize, size_t newsize, int type) +{ + /* init */ + void* objnew; + + /* mremap */ + if (type) { + objnew = mremap(obj, oldsize, newsize, MREMAP_MAYMOVE); + } + /* realloc */ + else { + objnew = realloc(obj, newsize); + } + if (INVALIDPTR(objnew)) { return(objnew); } + + /* done */ + return (objnew); +} + +/***********************************************************************/ + +/*** + * Free resources of an object. + * If is zero, free is used. Otherwise, + * munmap is used. + * + * @param obj object to free + * @param size allocation size in bytes + * @param type 0: free, else: munmap + * @return 0: success, else: error + */ +int dmt_deallocate(void* obj, size_t size, int type) +{ + /* init */ + int res = 0; + + /* munmap */ + if (type) { + res = munmap(obj, size); + } + /* free */ + else { + free(obj); + } + + /* done */ + return (res); +} + diff --git a/cryptolib/selftest-heap/dmt-utils.h b/cryptolib/selftest-heap/dmt-utils.h new file mode 100644 index 00000000..1878e4ce --- /dev/null +++ b/cryptolib/selftest-heap/dmt-utils.h @@ -0,0 +1,86 @@ +/************************************************************************ + * Copyright (C) 2017-2018 IAIK TU Graz and Fraunhofer AISEC + * + * This program 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 3 of the License, or + * (at your option) any later version. + * + * This program 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, see . + ***********************************************************************/ + +/** + * @file dmt-utils.h + * @brief Dynamic memory tracking helper functions. + * @license This project is released under the GNU GPLv3+ License. + * @author See AUTHORS file. + * @version 0.3 + */ + +/***********************************************************************/ + +#include +#include + +/***********************************************************************/ + +#define RANDRANGE(M,N) (M + (N - M) * (float)rand() / (float)RAND_MAX) +#define INVALIDPTR(p) (p == NULL || p == (void*)-1) + +/***********************************************************************/ + +#define SMALL RANDRANGE(16,1024) +#define MEDIUM RANDRANGE(1024,100*1024) +#define LARGE RANDRANGE(100*1024,1*1024*1024) +#define HUGE RANDRANGE(1*1024*1024,10*1024*1024) + +/***********************************************************************/ + +/*** + * Allocate a new object with bytes. + * If is zero, malloc is used. Otherwise, + * mmap is used. If is non-zero, a slight + * variant of the allocation call is used. + * + * @param size number of bytes to allocate + * @param type 0: malloc, else: mmap + * @param alt 0: standard call, else: alternative call + * @return allocated object pointer + */ +void* dmt_allocate(size_t size, int type, int alt); + +/***********************************************************************/ + +/*** + * Re-allocate an object to bytes. + * If is zero, realloc is used. Otherwise, + * mremap is used. + * + * @param obj object to reallocate + * @param oldsize previous object size + * @param newsize new number of bytes to allocate + * @param type 0: realloc, else: mremap + * @return re-allocated object pointer + */ +void* dmt_reallocate(void* obj, size_t oldsize, size_t newsize, int type); + +/***********************************************************************/ + +/*** + * Free resources of an object. + * If is zero, free is used. Otherwise, + * munmap is used. + * + * @param obj object to free + * @param size allocation size in bytes + * @param type 0: free, else: munmap + * @return 0: success, else: error + */ +int dmt_deallocate(void* obj, size_t size, int type); + diff --git a/cryptolib/selftest-heap/framework.sh b/cryptolib/selftest-heap/framework.sh new file mode 100755 index 00000000..057e301c --- /dev/null +++ b/cryptolib/selftest-heap/framework.sh @@ -0,0 +1,135 @@ +#!/bin/bash + +######################################################################### +# DO NOT CHANGE: Preparing DATA +#------------------------------------------------------------------------ +source "${DATA_COMMON}/DATA_init.sh" || { echo "source data.sh first!" && exit 1; } +######################################################################### + +#------------------------------------------------------------------------ +# Specify your framework settings used by DATA +#------------------------------------------------------------------------ + +# The name of the framework. Do not use spaces or special characters. +export FRAMEWORK=selftest-heap + +# The file containing all supported algorithms +export TARGETFILE=targets.txt + +# The number of measurements for difference detection (phase1) +export PHASE1_TRACES=3 + +# The number of constant keys for generic tests (phase2) +# Make sure that PHASE2_FIXEDKEYS <= PHASE1_TRACES +export PHASE2_FIXEDKEYS=3 + +# The number of measurements per constant key for generic tests (phase2) +export PHASE2_TRACES=100 + +# The number of measurements for specific tests (phase3) +export PHASE3_TRACES=300 + +# (Optional) Additional flags for the pintool. Supported flags are: +# -main
Start recording at function
. Note that the
+# symbol must exist, otherwise this will yield empty traces! +# -heap Trace heap allocations and replace heap addresses with +# relative offset +export PINTOOL_ARGS="-heap" + +#------------------------------------------------------------------------ +# Implement your framework-specific callbacks +#------------------------------------------------------------------------ +# +# Globally available environment variables: +# $FRAMEWORK The framework name +# $BASEDIR The absolute directory path of this script +# $DATA_COMMON The absolute directory for common DATA scripts +# $DATA_LEAKAGE_MODELS The absolute directory for DATA leakage models +# +# Available for cb_genkey, cb_pre_run, cb_run_command, cb_post_run +# $ALGO The currently tested algo +# +# Available for cb_pre_run, cb_run_command, cb_post_run +# $ENVFILE + +export BINARY=${PWD}/bin/programs/dmt-realloc + +# The leakage model of phase 3. +# See ${DATA_LEAKAGE_MODELS} for all options. +export SPECIFIC_LEAKAGE_CALLBACK=${DATA_LEAKAGE_MODELS}/sym_nibble_high.py + +# DATA callback for setting up the framework to analyze. This callback +# is invoked once inside the current directory before analysis starts. +# Implement framework-specific tasks here like framework compilation. +function cb_prepare_framework { + make -s +} + +# DATA callback for generating keys. This callback is invoked every +# time a new key is needed. Implement key generation according to +# your algorithm and store the generated key inside a file named $2. +# +# $1 ... key file name +function cb_genkey { + "${DATA_COMMON}"/genkey.py "${KEYBYTES}" > "$1" + RES=$((RES + $?)) +} + +# DATA callback for custom commands that are executed immediately before +# the algorithm is profiled. It is executed in a temporary directory +# which contains the keyfile $1 and ${ENVFILE}. +# +# If 'cb_run_command' needs any other files, copy them to ${PWD}. +# +# $1 ... key file name +function cb_pre_run { + log_verbose "running with key $1" +} + +# DATA callback for the main invocation of the tested algorithm. +# It shall return the bash command to execute as string. It is +# executed inside a temporary directory with a clean environment. +# If you need special files or environment variables set, specify +# them in cb_pre_run. +# +# $1 ... key file name +function cb_run_command { + echo "${BINARY} 0 0 0 16 $1" +} + +# DATA callback for custom commands that are executed immediately after +# the algorithm is profiled. It is executed in a temporary directory. +# You can cleanup any custom files generated by your algorithm. +# +# $1 ... key file name +function cb_post_run { + : +} + +# DATA callback for preparing an individual algorithm. It shall: +# 1. Parse the next algorithm from the commandline string of all algorithms +# and set up anything necessary for analyzing this algorithm. +# If the algorithm needs additional parameters (like key sizes), +# increase $SHIFT accordingly. +# 2. Configure $WORKDIR, which will create a subdirectory holding all +# intermediate files generated by the algorithm and the results. +# Do not use an absolute path! +# +# $* ... algorithm string from the commandline +function cb_prepare_algo { + ALGO=$1 + # key bits + PARAM=$2 + SHIFT=$((SHIFT+1)) + KEYBYTES=$(( PARAM / 8 )) + + WORKDIR="$FRAMEWORK/$ALGO/$PARAM" +} + +######################################################################### +# DO NOT CHANGE: Running DATA's commandline parser +#------------------------------------------------------------------------ +DATA_parse "$@" +#------------------------------------------------------------------------ +# DO NOT ADD CODE AFTER THIS LINE +######################################################################### diff --git a/cryptolib/selftest-heap/targets.txt b/cryptolib/selftest-heap/targets.txt new file mode 100644 index 00000000..338a62e4 --- /dev/null +++ b/cryptolib/selftest-heap/targets.txt @@ -0,0 +1 @@ +basic 8