diff --git a/dist/tools/riotboot_gen_hdr/Makefile b/dist/tools/riotboot_gen_hdr/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..dd57e45f27107856e5c16abc913baacd2e98fe62
--- /dev/null
+++ b/dist/tools/riotboot_gen_hdr/Makefile
@@ -0,0 +1,39 @@
+RIOTBASE       := ../../..
+RIOT_INCLUDE   := $(RIOTBASE)/sys/include
+RIOT_CORE_INC  := $(RIOTBASE)/core/include
+NATIVE_INCLUDE := $(RIOTBASE)/cpu/native/include
+COMMON_SRC     := common.c
+COMMON_HDR     := common.h
+
+RIOT_HDR_SRC := \
+	$(RIOTBASE)/sys/checksum/fletcher32.c \
+	$(RIOTBASE)/sys/riotboot/hdr.c
+
+RIOT_HDR_HDR := $(RIOT_INCLUDE)/riotboot/hdr.h \
+	$(RIOT_INCLUDE)/checksum/fletcher32.h \
+	$(RIOTBASE)/core/include/byteorder.h
+
+GENHDR_SRC := $(COMMON_SRC) $(RIOT_HDR_SRC) \
+	main.c genhdr.c
+
+GENHDR_HDR := $(COMMON_HDR) $(RIOT_HDR_HDR)
+
+CFLAGS += -g -I. -O3 -Wall -Wextra -pedantic -std=c99
+
+ifeq ($(QUIET),1)
+  Q=@
+else
+  Q=
+endif
+
+all: bin/genhdr
+
+bin/:
+	$(Q)mkdir -p bin
+
+bin/genhdr: $(GENHDR_HDR) $(GENHDR_SRC) Makefile | bin/
+	$(Q)$(CC) $(CFLAGS) -I$(RIOT_INCLUDE) -I$(RIOT_CORE_INC) \
+		-I$(NATIVE_INCLUDE) $(GENHDR_SRC) -o $@
+
+clean:
+	$(Q)rm -rf bin/
diff --git a/dist/tools/riotboot_gen_hdr/common.c b/dist/tools/riotboot_gen_hdr/common.c
new file mode 100644
index 0000000000000000000000000000000000000000..c3cb771b6a15c183369e5d91a5c5bc14c06b11f4
--- /dev/null
+++ b/dist/tools/riotboot_gen_hdr/common.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 Kaspar Schleiser <kaspar@schleiser.de>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License v2. See the file LICENSE for more details.
+ */
+
+/**
+ * @file
+ * @brief       Common tools for RIOT images header generation
+ *
+ * @author      Kaspar Schleiser <kaspar@schleiser.de>
+ */
+
+#include <fcntl.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+int to_file(const char *filename, void *buf, size_t len)
+{
+    int fd;
+
+    if (strcmp("-", filename)) {
+        fd = open(filename, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
+    }
+    else {
+        fd = STDOUT_FILENO;
+    }
+
+    if (fd > 0) {
+        ssize_t res = write(fd, buf, len);
+        close(fd);
+        return res == (ssize_t)len;
+    }
+    else {
+        return fd;
+    }
+}
diff --git a/dist/tools/riotboot_gen_hdr/common.h b/dist/tools/riotboot_gen_hdr/common.h
new file mode 100644
index 0000000000000000000000000000000000000000..f3380d8ffb4b3d777cb9048e8f58f9636d573a0a
--- /dev/null
+++ b/dist/tools/riotboot_gen_hdr/common.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 Kaspar Schleiser <kaspar@schleiser.de>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License v2. See the file LICENSE for more details.
+ */
+
+#ifndef COMMON_H
+#define COMMON_H
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/**
+ * @brief  Write len bytes of a given buffer into a file
+ *
+ * @param[out] filename    name of the file to be written
+ * @param[in]  buf         a pointer to the buffer which needs to be written
+ * @param[in]  len         the number of bytes from buf to be written
+ *
+ */
+int to_file(const char *filename, void *buf, size_t len);
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif
+
+#endif /* COMMON_H */
diff --git a/dist/tools/riotboot_gen_hdr/genhdr.c b/dist/tools/riotboot_gen_hdr/genhdr.c
new file mode 100644
index 0000000000000000000000000000000000000000..f8559d589fddc002ff07c0a1ad94af9b6666ae46
--- /dev/null
+++ b/dist/tools/riotboot_gen_hdr/genhdr.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2016 Inria
+ *               2017 Kaspar Schleiser <kaspar@schleiser.de>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License v2. See the file LICENSE for more details.
+ *
+ */
+
+/**
+ * @author      Francisco Acosta <francisco.acosta@inria.fr>
+ * @author      Kaspar Schleiser <kaspar@schleiser.de>
+ */
+
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "riotboot/hdr.h"
+#include "common.h"
+
+/**
+ *  @brief Alignment required to set VTOR in Cortex-M0+/3/4/7
+ */
+#define HDR_ALIGN              (256)
+
+static void populate_hdr(riotboot_hdr_t *hdr, uint32_t ver, uint32_t addr)
+{
+    /* ensure the buffer and header have 0's */
+    memset(hdr, '\0', sizeof(riotboot_hdr_t));
+
+    /* Generate image header */
+    hdr->magic_number = RIOTBOOT_MAGIC;
+    hdr->version = ver;
+    hdr->start_addr = addr;
+
+    /* calculate header checksum */
+    hdr->chksum = riotboot_hdr_checksum(hdr);
+}
+
+int genhdr(int argc, char *argv[])
+{
+    const char generate_usage[] = "<IMG_BIN> <APP_VER> <START_ADDR> <HDR_LEN> <outfile|->";
+
+    /* riotboot_hdr buffer */
+    uint8_t *hdr_buf;
+
+    /* arguments storage variables */
+    long app_ver_arg = 0;
+    long start_addr_arg = 0;
+    long hdr_len_arg = 0;
+
+    /* header variables */
+    size_t hdr_len = 0;
+    uint32_t app_ver = 0;
+    uint32_t start_addr = 0;
+
+    /* helpers */
+    errno = 0;
+    char *p;
+
+    if (argc < 6) {
+        fprintf(stderr, "usage: genhdr generate %s\n", generate_usage);
+        return -1;
+    }
+
+    app_ver_arg = strtol(argv[2], &p, 0);
+    if (errno != 0 || *p != '\0' || app_ver_arg > UINT32_MAX) {
+        fprintf(stderr, "Error: APP_VER not valid!\n");
+    }
+    else {
+        app_ver = app_ver_arg;
+    }
+
+    start_addr_arg = strtol(argv[3], &p, 0);
+    if (errno != 0 || *p != '\0' || start_addr_arg > UINT32_MAX) {
+        fprintf(stderr, "Error: START_ADDR not valid!\n");
+    }
+    else {
+        start_addr = start_addr_arg;
+    }
+
+    hdr_len_arg = strtol(argv[4], &p, 0);
+    if (errno != 0 || *p != '\0' || hdr_len_arg % HDR_ALIGN || hdr_len_arg > UINT32_MAX) {
+        fprintf(stderr, "Error: HDR_LEN not valid!\n");
+        return -1;
+    }
+    else {
+        hdr_len = hdr_len_arg;
+    }
+
+    /* prepare a 0 initialised buffer for riotboot_hdr_t */
+    hdr_buf = calloc(1, hdr_len);
+    if (hdr_buf == NULL) {
+        fprintf(stderr, "Error: not enough memory!\n");
+        return -1;
+    }
+
+    populate_hdr((riotboot_hdr_t*)hdr_buf, app_ver, start_addr);
+
+    /* Write the header */
+    if (!to_file(argv[5], hdr_buf, hdr_len)) {
+        fprintf(stderr, "Error: cannot write output\n");
+        free(hdr_buf);
+        return 1;
+    }
+
+    free(hdr_buf);
+
+    return 0;
+}
diff --git a/dist/tools/riotboot_gen_hdr/main.c b/dist/tools/riotboot_gen_hdr/main.c
new file mode 100644
index 0000000000000000000000000000000000000000..6288fa29edda6b155c743e25f77e57aa8cceb8d1
--- /dev/null
+++ b/dist/tools/riotboot_gen_hdr/main.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2017 Kaspar Schleiser <kaspar@schleiser.de>
+ *               2018 Inria
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License v2. See the file LICENSE for more details.
+ */
+
+/**
+ * @file
+ * @brief       Header generation tool for RIOT firmware images
+ *
+ * @author      Francisco Acosta <francisco.acosta@inria.fr>
+ * @author      Kaspar Schleiser <kaspar@schleiser.de>
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+int genhdr(int argc, char *argv[]);
+
+int main(int argc, char *argv[])
+{
+    char *usage = "genhdr generate [args]";
+
+    if (argc < 2) {
+        goto usage;
+    }
+    else if (!strcmp(argv[1], "generate")) {
+        return genhdr(argc - 1, &argv[1]);
+    }
+
+usage:
+    fprintf(stderr, "usage: %s\n", usage);
+    return 1;
+}