]>
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/>.
23 #include <openssl/pkcs7.h>
24 #include <openssl/ssl.h>
30 #include <shared/missing.h>
31 #include <shared/util.h>
33 #include "libkmod-internal.h"
35 /* These types and tables were copied from the 3.7 kernel sources.
36 * As this is just description of the signature format, it should not be
37 * considered derived work (so libkmod can use the LGPL license).
45 static const char *const pkey_algo
[PKEY_ALGO__LAST
] = {
46 [PKEY_ALGO_DSA
] = "DSA",
47 [PKEY_ALGO_RSA
] = "RSA",
54 PKEY_HASH_RIPE_MD_160
,
63 const char *const pkey_hash_algo
[PKEY_HASH__LAST
] = {
64 [PKEY_HASH_MD4
] = "md4",
65 [PKEY_HASH_MD5
] = "md5",
66 [PKEY_HASH_SHA1
] = "sha1",
67 [PKEY_HASH_RIPE_MD_160
] = "rmd160",
68 [PKEY_HASH_SHA256
] = "sha256",
69 [PKEY_HASH_SHA384
] = "sha384",
70 [PKEY_HASH_SHA512
] = "sha512",
71 [PKEY_HASH_SHA224
] = "sha224",
72 [PKEY_HASH_SM3
] = "sm3",
76 PKEY_ID_PGP
, /* OpenPGP generated key ID */
77 PKEY_ID_X509
, /* X.509 arbitrary subjectKeyIdentifier */
78 PKEY_ID_PKCS7
, /* Signature in PKCS#7 message */
82 const char *const pkey_id_type
[PKEY_ID_TYPE__LAST
] = {
83 [PKEY_ID_PGP
] = "PGP",
84 [PKEY_ID_X509
] = "X509",
85 [PKEY_ID_PKCS7
] = "PKCS#7",
89 * Module signature information block.
91 struct module_signature
{
92 uint8_t algo
; /* Public-key crypto algorithm [enum pkey_algo] */
93 uint8_t hash
; /* Digest algorithm [enum pkey_hash_algo] */
94 uint8_t id_type
; /* Key identifier type [enum pkey_id_type] */
95 uint8_t signer_len
; /* Length of signer's name */
96 uint8_t key_id_len
; /* Length of key identifier */
98 uint32_t sig_len
; /* Length of signature data (big endian) */
101 static bool fill_default(const char *mem
, off_t size
,
102 const struct module_signature
*modsig
, size_t sig_len
,
103 struct kmod_signature_info
*sig_info
)
106 sig_info
->sig
= mem
+ size
;
107 sig_info
->sig_len
= sig_len
;
109 size
-= modsig
->key_id_len
;
110 sig_info
->key_id
= mem
+ size
;
111 sig_info
->key_id_len
= modsig
->key_id_len
;
113 size
-= modsig
->signer_len
;
114 sig_info
->signer
= mem
+ size
;
115 sig_info
->signer_len
= modsig
->signer_len
;
117 sig_info
->algo
= pkey_algo
[modsig
->algo
];
118 sig_info
->hash_algo
= pkey_hash_algo
[modsig
->hash
];
119 sig_info
->id_type
= pkey_id_type
[modsig
->id_type
];
124 #ifdef ENABLE_OPENSSL
126 struct pkcs7_private
{
128 unsigned char *key_id
;
133 static void pkcs7_free(void *s
)
135 struct kmod_signature_info
*si
= s
;
136 struct pkcs7_private
*pvt
= si
->private;
138 PKCS7_free(pvt
->pkcs7
);
141 free(pvt
->hash_algo
);
146 static const char *x509_name_to_str(X509_NAME
*name
)
155 for (i
= 0; i
< X509_NAME_entry_count(name
); i
++) {
156 e
= X509_NAME_get_entry(name
, i
);
157 o
= X509_NAME_ENTRY_get_object(e
);
158 nid
= OBJ_obj2nid(o
);
159 if (nid
== NID_commonName
)
165 d
= X509_NAME_ENTRY_get_data(e
);
166 str
= (const char *)ASN1_STRING_get0_data(d
);
171 static bool fill_pkcs7(const char *mem
, off_t size
,
172 const struct module_signature
*modsig
, size_t sig_len
,
173 struct kmod_signature_info
*sig_info
)
175 const char *pkcs7_raw
;
177 STACK_OF(PKCS7_SIGNER_INFO
) *sis
;
178 PKCS7_SIGNER_INFO
*si
;
179 PKCS7_ISSUER_AND_SERIAL
*is
;
182 ASN1_OCTET_STRING
*sig
;
186 const ASN1_OBJECT
*o
;
189 unsigned char *key_id_str
;
190 struct pkcs7_private
*pvt
;
191 const char *issuer_str
;
196 pkcs7_raw
= mem
+ size
;
198 in
= BIO_new_mem_buf(pkcs7_raw
, sig_len
);
200 pkcs7
= d2i_PKCS7_bio(in
, NULL
);
208 sis
= PKCS7_get_signer_info(pkcs7
);
212 si
= sk_PKCS7_SIGNER_INFO_value(sis
, 0);
216 is
= si
->issuer_and_serial
;
222 sig
= si
->enc_digest
;
226 PKCS7_SIGNER_INFO_get0_algs(si
, NULL
, &dig_alg
, &sig_alg
);
228 sig_info
->sig
= (const char *)ASN1_STRING_get0_data(sig
);
229 sig_info
->sig_len
= ASN1_STRING_length(sig
);
231 sno_bn
= ASN1_INTEGER_to_BN(sno
, NULL
);
235 len
= BN_num_bytes(sno_bn
);
236 key_id_str
= malloc(len
);
237 if (key_id_str
== NULL
)
239 BN_bn2bin(sno_bn
, key_id_str
);
241 sig_info
->key_id
= (const char *)key_id_str
;
242 sig_info
->key_id_len
= len
;
244 issuer_str
= x509_name_to_str(issuer
);
245 if (issuer_str
!= NULL
) {
246 sig_info
->signer
= issuer_str
;
247 sig_info
->signer_len
= strlen(issuer_str
);
250 X509_ALGOR_get0(&o
, NULL
, NULL
, dig_alg
);
252 // Use OBJ_obj2txt to calculate string length
253 hash_algo_len
= OBJ_obj2txt(NULL
, 0, o
, 0);
254 if (hash_algo_len
< 0)
256 hash_algo
= malloc(hash_algo_len
+ 1);
257 if (hash_algo
== NULL
)
259 hash_algo_len
= OBJ_obj2txt(hash_algo
, hash_algo_len
+ 1, o
, 0);
260 if (hash_algo_len
< 0)
263 // Assign libcrypto hash algo string or number
264 sig_info
->hash_algo
= hash_algo
;
266 sig_info
->id_type
= pkey_id_type
[modsig
->id_type
];
268 pvt
= malloc(sizeof(*pvt
));
273 pvt
->key_id
= key_id_str
;
275 pvt
->hash_algo
= hash_algo
;
276 sig_info
->private = pvt
;
278 sig_info
->free
= pkcs7_free
;
292 #else /* ENABLE OPENSSL */
294 static bool fill_pkcs7(const char *mem
, off_t size
,
295 const struct module_signature
*modsig
, size_t sig_len
,
296 struct kmod_signature_info
*sig_info
)
298 sig_info
->hash_algo
= "unknown";
299 sig_info
->id_type
= pkey_id_type
[modsig
->id_type
];
303 #endif /* ENABLE OPENSSL */
305 #define SIG_MAGIC "~Module signature appended~\n"
308 * A signed module has the following layout:
314 * [ struct module_signature ]
318 bool kmod_module_signature_info(const struct kmod_file
*file
, struct kmod_signature_info
*sig_info
)
322 const struct module_signature
*modsig
;
325 size
= kmod_file_get_size(file
);
326 mem
= kmod_file_get_contents(file
);
327 if (size
< (off_t
)strlen(SIG_MAGIC
))
329 size
-= strlen(SIG_MAGIC
);
330 if (memcmp(SIG_MAGIC
, mem
+ size
, strlen(SIG_MAGIC
)) != 0)
333 if (size
< (off_t
)sizeof(struct module_signature
))
335 size
-= sizeof(struct module_signature
);
336 modsig
= (struct module_signature
*)(mem
+ size
);
337 if (modsig
->algo
>= PKEY_ALGO__LAST
||
338 modsig
->hash
>= PKEY_HASH__LAST
||
339 modsig
->id_type
>= PKEY_ID_TYPE__LAST
)
341 sig_len
= be32toh(get_unaligned(&modsig
->sig_len
));
343 size
< (int64_t)(modsig
->signer_len
+ modsig
->key_id_len
+ sig_len
))
346 switch (modsig
->id_type
) {
348 return fill_pkcs7(mem
, size
, modsig
, sig_len
, sig_info
);
350 return fill_default(mem
, size
, modsig
, sig_len
, sig_info
);
354 void kmod_module_signature_info_free(struct kmod_signature_info
*sig_info
)
357 sig_info
->free(sig_info
);