]>
git.ipfire.org Git - thirdparty/kmod.git/blob - libkmod/libkmod-signature.c
2 * libkmod - module signature display
4 * Copyright (C) 2013 Michal Marek, SUSE
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
26 #include <shared/missing.h>
27 #include <shared/util.h>
29 #include "libkmod-internal.h"
31 /* These types and tables were copied from the 3.7 kernel sources.
32 * As this is just description of the signature format, it should not be
33 * considered derived work (so libkmod can use the LGPL license).
41 static const char *const pkey_algo
[PKEY_ALGO__LAST
] = {
42 [PKEY_ALGO_DSA
] = "DSA",
43 [PKEY_ALGO_RSA
] = "RSA",
50 PKEY_HASH_RIPE_MD_160
,
58 const char *const pkey_hash_algo
[PKEY_HASH__LAST
] = {
59 [PKEY_HASH_MD4
] = "md4",
60 [PKEY_HASH_MD5
] = "md5",
61 [PKEY_HASH_SHA1
] = "sha1",
62 [PKEY_HASH_RIPE_MD_160
] = "rmd160",
63 [PKEY_HASH_SHA256
] = "sha256",
64 [PKEY_HASH_SHA384
] = "sha384",
65 [PKEY_HASH_SHA512
] = "sha512",
66 [PKEY_HASH_SHA224
] = "sha224",
70 PKEY_ID_PGP
, /* OpenPGP generated key ID */
71 PKEY_ID_X509
, /* X.509 arbitrary subjectKeyIdentifier */
72 PKEY_ID_PKCS7
, /* Signature in PKCS#7 message */
76 const char *const pkey_id_type
[PKEY_ID_TYPE__LAST
] = {
77 [PKEY_ID_PGP
] = "PGP",
78 [PKEY_ID_X509
] = "X509",
79 [PKEY_ID_PKCS7
] = "PKCS#7",
83 * Module signature information block.
85 struct module_signature
{
86 uint8_t algo
; /* Public-key crypto algorithm [enum pkey_algo] */
87 uint8_t hash
; /* Digest algorithm [enum pkey_hash_algo] */
88 uint8_t id_type
; /* Key identifier type [enum pkey_id_type] */
89 uint8_t signer_len
; /* Length of signer's name */
90 uint8_t key_id_len
; /* Length of key identifier */
92 uint32_t sig_len
; /* Length of signature data (big endian) */
95 static bool fill_default(const char *mem
, off_t size
,
96 const struct module_signature
*modsig
, size_t sig_len
,
97 struct kmod_signature_info
*sig_info
)
100 sig_info
->sig
= mem
+ size
;
101 sig_info
->sig_len
= sig_len
;
103 size
-= modsig
->key_id_len
;
104 sig_info
->key_id
= mem
+ size
;
105 sig_info
->key_id_len
= modsig
->key_id_len
;
107 size
-= modsig
->signer_len
;
108 sig_info
->signer
= mem
+ size
;
109 sig_info
->signer_len
= modsig
->signer_len
;
111 sig_info
->algo
= pkey_algo
[modsig
->algo
];
112 sig_info
->hash_algo
= pkey_hash_algo
[modsig
->hash
];
113 sig_info
->id_type
= pkey_id_type
[modsig
->id_type
];
118 static bool fill_unknown(const char *mem
, off_t size
,
119 const struct module_signature
*modsig
, size_t sig_len
,
120 struct kmod_signature_info
*sig_info
)
122 sig_info
->hash_algo
= "unknown";
123 sig_info
->id_type
= pkey_id_type
[modsig
->id_type
];
127 #define SIG_MAGIC "~Module signature appended~\n"
130 * A signed module has the following layout:
136 * [ struct module_signature ]
140 bool kmod_module_signature_info(const struct kmod_file
*file
, struct kmod_signature_info
*sig_info
)
144 const struct module_signature
*modsig
;
147 size
= kmod_file_get_size(file
);
148 mem
= kmod_file_get_contents(file
);
149 if (size
< (off_t
)strlen(SIG_MAGIC
))
151 size
-= strlen(SIG_MAGIC
);
152 if (memcmp(SIG_MAGIC
, mem
+ size
, strlen(SIG_MAGIC
)) != 0)
155 if (size
< (off_t
)sizeof(struct module_signature
))
157 size
-= sizeof(struct module_signature
);
158 modsig
= (struct module_signature
*)(mem
+ size
);
159 if (modsig
->algo
>= PKEY_ALGO__LAST
||
160 modsig
->hash
>= PKEY_HASH__LAST
||
161 modsig
->id_type
>= PKEY_ID_TYPE__LAST
)
163 sig_len
= be32toh(get_unaligned(&modsig
->sig_len
));
165 size
< (int64_t)(modsig
->signer_len
+ modsig
->key_id_len
+ sig_len
))
168 switch (modsig
->id_type
) {
170 return fill_unknown(mem
, size
, modsig
, sig_len
, sig_info
);
172 return fill_default(mem
, size
, modsig
, sig_len
, sig_info
);