From: David Howells Subject: Re: [PATCH 21/21] MODSIGN: Apply signature checking to modules on module load [ver #3] Date: Mon, 12 Dec 2011 16:11:27 +0000 Message-ID: <21605.1323706287@redhat.com> References: <87ty56taup.fsf@rustcorp.com.au> <87obvfogc6.fsf@rustcorp.com.au> <8739csq5ac.fsf@rustcorp.com.au> <87boriouwa.fsf@rustcorp.com.au> <20111202184229.21874.25782.stgit@warthog.procyon.org.uk> <20111202184651.21874.57769.stgit@warthog.procyon.org.uk> <2657.1323456206@redhat.com> <30007.1323526114@redhat.com> <26644.1323652900@redhat.com> Cc: dhowells@redhat.com, keyrings@linux-nfs.org, linux-crypto@vger.kernel.org, linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, dmitry.kasatkin@intel.com, zohar@linux.vnet.ibm.com, arjan.van.de.ven@intel.com, alan.cox@intel.com, Jon Masters To: Rusty Russell Return-path: Received: from mx1.redhat.com ([209.132.183.28]:19613 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753192Ab1LLQLm (ORCPT ); Mon, 12 Dec 2011 11:11:42 -0500 In-Reply-To: <87ty56taup.fsf@rustcorp.com.au> Sender: linux-crypto-owner@vger.kernel.org List-ID: Rusty Russell wrote: > OK, then you need to generate stripped modules as part of the build, > too. It's a bit of a pain, sure, but hardly a showstopper. They'd have to be maximally stripped so that mkinitrd doesn't do anything to them, but you'd then get the debuginfo from them into the packaging if you're on some distribution or other. And you also provide an option to not strip them if whoever wants them unstripped. > A signature contains a magic marker I don't like this particularly - you can't guarantee that this won't be generated by the assembler quite by accident. You should find the end of the ELF and work from there. It should be a simple matter of parsing the header and the section table only, right? Then you can look at the file offset + length of the last section in the file. At that point, assuming this isn't coincident with the actual end of the file, you can try parsing what's thereafter as a signature. If it is actual PGP, then an RFC4880 parser should recognise it as valid, and a signature packet should be seen. > A signature contains a magic marker: it signs everything up to the > magic marker (ie. just append them): > SUM=`md5sum drivers/block/loop.ko | cut -d\ -f1`; echo "@Module signature:$SUM" >> drivers/block/loop.ko That's not a useful signature, but I suspect you're just showing this as an example. > We can have false positives, but at worst that make us report EINVAL > (bad signature) instead of ENOENT (no signature). EKEYREJECTED please; that way it's the same as RHEL does now. > Took me longer to figure out the damn crypto API You don't actually need to use that. The crypto API for the moment doesn't do crytographic signature verification. Look at: http://git.kernel.org/?p=linux/kernel/git/dhowells/linux-modsign.git;a=shortlog;h=refs/heads/devel >From tag cryptokeys-2011-12-07. That's my crypto signature verification stuff in the kernel. You can build on that. The last patch in the sequence has some of the bits you need for actually generating the signature, though rather than editing the ELF, you'd just append all the signatures you actually need. The following file: http://git.kernel.org/?p=linux/kernel/git/dhowells/linux-modsign.git;a=blob;f=kernel/module-verify-sig.c;h=ced56816b2c47307a36cce0c6f829ea23fc5f2e6;hb=d71374f23e3a8c88c3ae20f62f04fb07a641f805 has an example of how it can be used, but it's basically: struct crypto_key_verify_context *mod_sig; u8 *sig = ; size_t sig_size = ; /* Find the crypto key for the module signature * - !!! if this tries to load the required hash algorithm module, * we will deadlock!!! */ mod_sig = verify_sig_begin(modsign_keyring, sig, sig_size); if (IS_ERR(mod_sig)) ... returns -EBADMSG if none of its parsers recognise the signature, -ENOPKG if the signature is recognised, but we can't handle it (for instance if it's an unsupported hash algorithm), -ENOKEY if we recognise it, but there's no key available or -EKEYREJECTED if we recognised it, found the matching key, but the key couldn't be used to verify the signature for some reason. /* Call repeatedly to shovel data into the crypto hash */ verify_sig_add_data(mod_sig, dataptr, datasize); /* Call to finalise and actually perform the verification */ ret = verify_sig_end(mod_sig, sig, sig_size); or: /* Call to cancel the verification */ verify_sig_cancel(mod_sig); This does all the work for you. David