From: Rusty Russell Subject: Re: [PATCH 21/21] MODSIGN: Apply signature checking to modules on module load [ver #3] Date: Tue, 13 Dec 2011 12:45:40 +1030 Message-ID: <87obvdtdwz.fsf@rustcorp.com.au> 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> <21605.1323706287@redhat.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii 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: David Howells Return-path: In-Reply-To: <21605.1323706287@redhat.com> Sender: linux-kernel-owner@vger.kernel.org List-Id: linux-crypto.vger.kernel.org On Mon, 12 Dec 2011 16:11:27 +0000, David Howells wrote: > 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. I was thinking we generate multiple modules; people will definitely want unstripped versions as well. > > 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. We don't care, in practice. It can't generate a valid key by accident. The only difference is that you might get "bad key" instead of "no key" if no sigature matches. But a validly parsable signature won't happen in practice. > 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. Tried that first. It's more lines (which need to be carefully scrutinized)... > 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. ...and you can still have padding. At which point, I realised that we might as well just scan the whole thing and be done. It's a bit cheeky, but I *know* it works, and can be verified by any reader without knowing anything about ELF or trusting the format at all. > > 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. Yeah, it was supposed to be a dumb 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. OK, sure (who knew that was there?). > > 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. Sure, I was working on mainline, which is why I chose md5 (plus using md5sum is easy). > 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. That looks really nice, actually! Thanks, Rusty.