diff --git a/libkmod/libkmod-file.c b/libkmod/libkmod-file.c
index 5eeba6a912a2..cb1da3c9e2ae 100644
--- a/libkmod/libkmod-file.c
+++ b/libkmod/libkmod-file.c
@@ -52,6 +52,7 @@ struct kmod_file {
 	gzFile gzf;
 #endif
 	int fd;
+	int sig_fd;
 	bool direct;
 	off_t size;
 	void *memory;
@@ -60,6 +61,37 @@ struct kmod_file {
 	struct kmod_elf *elf;
 };
 
+static int append_detached_sig(struct kmod_file *file, size_t buf_size)
+{
+	struct stat st;
+	ssize_t read_size;
+
+	if (file->sig_fd < 0)
+		return 0;
+
+	if (fstat(file->sig_fd, &st) < 0)
+		return -errno;
+
+	/* Grow the buffer if necessary */
+	if ((size_t)st.st_size > buf_size - file->size) {
+		void *tmp = realloc(file->memory, file->size + st.st_size);
+		if (tmp == NULL)
+			return -errno;
+		file->memory = tmp;
+	}
+
+	read_size = read(file->sig_fd, (char *)file->memory + file->size,
+			 st.st_size);
+	if (read_size < 0)
+		return -errno;
+	if (read_size != st.st_size)
+		return -EINVAL;
+
+	file->size += read_size;
+
+	return 0;
+}
+
 #ifdef ENABLE_XZ
 static void xz_uncompress_belch(struct kmod_file *file, lzma_ret ret)
 {
@@ -144,6 +176,7 @@ static int load_xz(struct kmod_file *file)
 {
 	lzma_stream strm = LZMA_STREAM_INIT;
 	lzma_ret lzret;
+	size_t buf_size;
 	int ret;
 
 	lzret = lzma_stream_decoder(&strm, UINT64_MAX, LZMA_CONCATENATED);
@@ -155,7 +188,14 @@ static int load_xz(struct kmod_file *file)
 		return -EINVAL;
 	}
 	ret = xz_uncompress(&strm, file);
+	buf_size = file->size + strm.avail_out;
 	lzma_end(&strm);
+
+	if (!ret) {
+		ret = append_detached_sig(file, buf_size);
+		if (ret)
+			free(file->memory);
+	}
 	return ret;
 }
 
@@ -214,6 +254,11 @@ static int load_zlib(struct kmod_file *file)
 
 	file->memory = p;
 	file->size = did;
+
+	err = append_detached_sig(file, total);
+	if (err)
+		goto error;
+
 	p = NULL;
 	return 0;
 
@@ -254,18 +299,50 @@ static int load_reg(struct kmod_file *file)
 	if (fstat(file->fd, &st) < 0)
 		return -errno;
 
-	file->size = st.st_size;
-	file->memory = mmap(NULL, file->size, PROT_READ, MAP_PRIVATE,
-			    file->fd, 0);
-	if (file->memory == MAP_FAILED)
-		return -errno;
-	file->direct = true;
+	if (file->sig_fd < 0) {
+		file->size = st.st_size;
+		file->memory = mmap(NULL, file->size, PROT_READ, MAP_PRIVATE,
+				    file->fd, 0);
+		if (file->memory == MAP_FAILED)
+			return -errno;
+		file->direct = true;
+	} else {
+		size_t plain_size = st.st_size, sig_size;
+		_cleanup_free_ unsigned char *p = NULL;
+		ssize_t ret;
+
+		if (fstat(file->sig_fd, &st) < 0)
+			return -errno;
+		sig_size = st.st_size;
+
+		p = malloc(plain_size + sig_size);
+		if (!p)
+			return -errno;
+
+		ret = read(file->fd, p, plain_size);
+		if (ret < 0)
+			return -errno;
+		if ((size_t)ret != plain_size)
+			return -EINVAL;
+		file->memory = p;
+		file->size = plain_size;
+
+		ret = append_detached_sig(file, plain_size + sig_size);
+		if (ret)
+			return ret;
+
+		p = NULL;
+	}
+
 	return 0;
 }
 
 static void unload_reg(struct kmod_file *file)
 {
-	munmap(file->memory, file->size);
+	if (file->direct)
+		munmap(file->memory, file->size);
+	else
+		free(file->memory);
 }
 
 static const struct file_ops reg_ops = {
@@ -285,6 +362,7 @@ struct kmod_file *kmod_file_open(const struct kmod_ctx *ctx,
 						const char *filename)
 {
 	struct kmod_file *file = calloc(1, sizeof(struct kmod_file));
+	char *sig_filename = NULL;
 	const struct comp_type *itr;
 	size_t magic_size_max = 0;
 	int err;
@@ -292,12 +370,25 @@ struct kmod_file *kmod_file_open(const struct kmod_ctx *ctx,
 	if (file == NULL)
 		return NULL;
 
+	file->sig_fd = -1;
+
 	file->fd = open(filename, O_RDONLY|O_CLOEXEC);
 	if (file->fd < 0) {
 		err = -errno;
 		goto error;
 	}
 
+	/* Try to open a detached signature.  If it's missing, that's OK. */
+	if (asprintf(&sig_filename, "%s.sig", filename) < 0) {
+		err = -errno;
+		goto error;
+	}
+	file->sig_fd = open(sig_filename, O_RDONLY|O_CLOEXEC);
+	if (file->sig_fd < 0 && errno != ENOENT) {
+		err = -errno;
+		goto error;
+	}
+
 	for (itr = comp_types; itr->ops.load != NULL; itr++) {
 		if (magic_size_max < itr->magic_size)
 			magic_size_max = itr->magic_size;
@@ -336,7 +427,10 @@ struct kmod_file *kmod_file_open(const struct kmod_ctx *ctx,
 	err = file->ops->load(file);
 	file->ctx = ctx;
 error:
+	free(sig_filename);
 	if (err < 0) {
+		if (file->sig_fd >= 0)
+			close(file->sig_fd);
 		if (file->fd >= 0)
 			close(file->fd);
 		free(file);
@@ -373,6 +467,8 @@ void kmod_file_unref(struct kmod_file *file)
 		kmod_elf_unref(file->elf);
 
 	file->ops->unload(file);
+	if (file->sig_fd >= 0)
+		close(file->sig_fd);
 	if (file->fd >= 0)
 		close(file->fd);
 	free(file);
