*
* Get a list of entries in ELF section ".modinfo", these contain
* alias, license, depends, vermagic and other keys with respective
- * values.
+ * values. If the module is signed (CONFIG_MODULE_SIG), information
+ * about the module signature is included as well: signer,
+ * sig_key and sig_hashalgo.
*
* After use, free the @list by calling kmod_module_info_free_list().
*
struct kmod_elf *elf;
char **strings;
int i, count, ret = -ENOMEM;
+ struct kmod_signature_info sig_info;
if (mod == NULL || list == NULL)
return -ENOENT;
if (n == NULL)
goto list_error;
}
+
+ if (kmod_module_signature_info(mod->file, &sig_info)) {
+ struct kmod_list *n;
+ char *key_hex;
+
+ n = kmod_module_info_append(list, "signer", strlen("signer"),
+ sig_info.signer, sig_info.signer_len);
+ if (n == NULL)
+ goto list_error;
+ count++;
+
+ /* Display the key id as 01:12:DE:AD:BE:EF:... */
+ key_hex = malloc(sig_info.key_id_len * 3);
+ if (key_hex == NULL)
+ goto list_error;
+ for (i = 0; i < (int)sig_info.key_id_len; i++) {
+ sprintf(key_hex + i * 3, "%02X",
+ (unsigned char)sig_info.key_id[i]);
+ if (i < (int)sig_info.key_id_len - 1)
+ key_hex[i * 3 + 2] = ':';
+ }
+ n = kmod_module_info_append(list, "sig_key", strlen("sig_key"),
+ key_hex, sig_info.key_id_len * 3 - 1);
+ free(key_hex);
+ if (n == NULL)
+ goto list_error;
+ count++;
+
+ n = kmod_module_info_append(list,
+ "sig_hashalgo", strlen("sig_hashalgo"),
+ sig_info.hash_algo, strlen(sig_info.hash_algo));
+ if (n == NULL)
+ goto list_error;
+ count++;
+
+ /*
+ * Omit sig_info.id_type and sig_info.algo for now, as these
+ * are currently constant.
+ */
+ }
ret = count;
list_error:
--- /dev/null
+/*
+ * libkmod - module signature display
+ *
+ * Copyright (C) 2013 Michal Marek, SUSE
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <endian.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "libkmod-private.h"
+
+/* These types and tables were copied from the 3.7 kernel sources.
+ * As this is just description of the signature format, it should not be
+ * considered derived work (so libkmod can use the LGPL license).
+ */
+enum pkey_algo {
+ PKEY_ALGO_DSA,
+ PKEY_ALGO_RSA,
+ PKEY_ALGO__LAST
+};
+
+static const char *const pkey_algo[PKEY_ALGO__LAST] = {
+ [PKEY_ALGO_DSA] = "DSA",
+ [PKEY_ALGO_RSA] = "RSA",
+};
+
+enum pkey_hash_algo {
+ PKEY_HASH_MD4,
+ PKEY_HASH_MD5,
+ PKEY_HASH_SHA1,
+ PKEY_HASH_RIPE_MD_160,
+ PKEY_HASH_SHA256,
+ PKEY_HASH_SHA384,
+ PKEY_HASH_SHA512,
+ PKEY_HASH_SHA224,
+ PKEY_HASH__LAST
+};
+
+const char *const pkey_hash_algo[PKEY_HASH__LAST] = {
+ [PKEY_HASH_MD4] = "md4",
+ [PKEY_HASH_MD5] = "md5",
+ [PKEY_HASH_SHA1] = "sha1",
+ [PKEY_HASH_RIPE_MD_160] = "rmd160",
+ [PKEY_HASH_SHA256] = "sha256",
+ [PKEY_HASH_SHA384] = "sha384",
+ [PKEY_HASH_SHA512] = "sha512",
+ [PKEY_HASH_SHA224] = "sha224",
+};
+
+enum pkey_id_type {
+ PKEY_ID_PGP, /* OpenPGP generated key ID */
+ PKEY_ID_X509, /* X.509 arbitrary subjectKeyIdentifier */
+ PKEY_ID_TYPE__LAST
+};
+
+const char *const pkey_id_type[PKEY_ID_TYPE__LAST] = {
+ [PKEY_ID_PGP] = "PGP",
+ [PKEY_ID_X509] = "X509",
+};
+
+/*
+ * Module signature information block.
+ *
+ * The constituents of the signature section are, in order:
+ *
+ * - Signer's name
+ * - Key identifier
+ * - Signature data
+ * - Information block
+ */
+struct module_signature {
+ uint8_t algo; /* Public-key crypto algorithm [enum pkey_algo] */
+ uint8_t hash; /* Digest algorithm [enum pkey_hash_algo] */
+ uint8_t id_type; /* Key identifier type [enum pkey_id_type] */
+ uint8_t signer_len; /* Length of signer's name */
+ uint8_t key_id_len; /* Length of key identifier */
+ uint8_t __pad[3];
+ uint32_t sig_len; /* Length of signature data (big endian) */
+};
+
+#define SIG_MAGIC "~Module signature appended~\n"
+
+bool kmod_module_signature_info(const struct kmod_file *file, struct kmod_signature_info *sig_info)
+{
+ const char *mem;
+ off_t size;
+ const struct module_signature *modsig;
+ size_t sig_len;
+
+
+ size = kmod_file_get_size(file);
+ mem = kmod_file_get_contents(file);
+ if (size < (off_t)strlen(SIG_MAGIC))
+ return false;
+ size -= strlen(SIG_MAGIC);
+ if (memcmp(SIG_MAGIC, mem + size, strlen(SIG_MAGIC)) != 0)
+ return false;
+
+ if (size < (off_t)sizeof(struct module_signature))
+ return false;
+ size -= sizeof(struct module_signature);
+ modsig = (struct module_signature *)(mem + size);
+ if (modsig->algo >= PKEY_ALGO__LAST ||
+ modsig->hash >= PKEY_HASH__LAST ||
+ modsig->id_type >= PKEY_ID_TYPE__LAST)
+ return false;
+ sig_len = be32toh(modsig->sig_len);
+ if (size < (off_t)(modsig->signer_len + modsig->key_id_len + sig_len))
+ return false;
+
+ size -= modsig->key_id_len + sig_len;
+ sig_info->key_id = mem + size;
+ sig_info->key_id_len = modsig->key_id_len;
+
+ size -= modsig->signer_len;
+ sig_info->signer = mem + size;
+ sig_info->signer_len = modsig->signer_len;
+
+ sig_info->algo = pkey_algo[modsig->algo];
+ sig_info->hash_algo = pkey_hash_algo[modsig->hash];
+ sig_info->id_type = pkey_id_type[modsig->id_type];
+
+ return true;
+}