On Tue, 2012-09-25 at 16:30 +0100, Alan Cox wrote:
> On Tue, 25 Sep 2012 16:09:54 +0100
> David Howells <[email protected]> wrote:
>
> >
> > The X.509 certificate has a pair of times in it that delineate the valid
> > period of the cert, and I'm checking that the system clock is within the
> > bounds they define before permitting you to use the cert. I've been setting
> > the expiry date to be 100 years in the future - by which time hopefully I
> > won't have to worry about it - but occasionally clock skew means a freshly
> > built kernel won't boot because the machine trying to boot doesn't think that
> > the start time has been reached yet.
> >
> > Do we actually want to do this, however? Or should we just ignore the times?
> > Or just the start time?
>
> Generate a certificate that is valid from a few minutes before the
> wallclock time. It's a certificate policy question not a kernel hackery
> one.
That's not good enough. I frequently encounter laptops with hardware
clocks which are *way* slower than that. I see lots of machines booting
up thinking it's 1970, 1900 iirc for some Macs, and more recently 2001.
This causes the kernel to refuse to load the certificate:
[ 3.116185] Loading module verification certificates
[ 3.117414] X.509: Cert e1a74f2317b1f38848278d07926ed16c2675393e is not yet valid
[ 3.118639] MODSIGN: Problem loading in-kernel X.509 certificate (-129)
...and then spew error messages every time a module is loaded.
For the kernel, it makes *absolutely* no sense to be checking the start
date of the certificate. We do not have a usage model where someone says
"hey, here's this kernel module but I don't want you to be able to use
it until tomorrow so I've post-dated its signature".
If we *ever* try to load a signed kernel module when the certificate is
"not yet valid", it's because the clock is wrong. It's as simple as
that.
And even if we *did* want to support that stupid "load this tomorrow"
use case, it's broken. You couldn't boot today, then load the offending
module tomorrow. You'd have to *reboot* tomorrow, because the kernel
refused to load the damn cert into its store at all.
For the specific case of module signing, we should probably just disable
the date checks completely.
--
dwmw2
The x509_key_preparse() function will refuse to even *parse* a
certificate when the system clock happens to be set to a time before the
ValidFrom or after the ValidTo date.
This is wrong. If date checks are to be done, they need to be done at
the time the cert is *used*. It should be perfectly possible to load a
cert which is post-dated, and can only be used for validation at some
point in the future. The key in question should immediately start
working at its ValidFrom date, and stop again at its ValidTo date. It
should be allowed to *exist* in the kernel both before and after those
times.
On systems where the hardware clock is inaccurate (a common occurrence
and one which doesn't even get noticed when you use NTP or something
else to fix it during the boot sequence), this was preventing the module
signing cert from being loaded during boot. When the clock got fixed
later on in he boot sequence, things *should* have started working. But
they didn't...
Signed-off-by: David Woodhouse <[email protected]>
---
Arguably, for the specific case of module signing we shouldn't bother
checking for a current time before the ValidFrom date *at all*. It's
*always* going to be a screwed up system clock, because we don't have a
usage model of post-dating module signatures. We should simply document
that the date is *not* checked for module signing, and have done with
it. But that's a separate issue.
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
index 06007f0..326dc80 100644
--- a/crypto/asymmetric_keys/x509_public_key.c
+++ b/crypto/asymmetric_keys/x509_public_key.c
@@ -154,8 +154,6 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
(now.tm_sec < cert->valid_from.tm_sec
))))))))))) {
pr_warn("Cert %s is not yet valid\n", cert->fingerprint);
- ret = -EKEYREJECTED;
- goto error_free_cert;
}
if (now.tm_year > cert->valid_to.tm_year ||
(now.tm_year == cert->valid_to.tm_year &&
@@ -170,8 +168,6 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
(now.tm_sec > cert->valid_to.tm_sec
))))))))))) {
pr_warn("Cert %s has expired\n", cert->fingerprint);
- ret = -EKEYEXPIRED;
- goto error_free_cert;
}
cert->pub->algo = x509_public_key_algorithms[cert->pkey_algo];
--
David Woodhouse Open Source Technology Centre
[email protected] Intel Corporation
Am 14.03.2013 13:24, schrieb David Woodhouse:
> The x509_key_preparse() function will refuse to even *parse* a
> certificate when the system clock happens to be set to a time before the
> ValidFrom or after the ValidTo date.
>
> This is wrong. If date checks are to be done, they need to be done at
> the time the cert is *used*. It should be perfectly possible to load a
> cert which is post-dated, and can only be used for validation at some
> point in the future. The key in question should immediately start
> working at its ValidFrom date, and stop again at its ValidTo date. It
> should be allowed to *exist* in the kernel both before and after those
> times.
>
> On systems where the hardware clock is inaccurate (a common occurrence
> and one which doesn't even get noticed when you use NTP or something
> else to fix it during the boot sequence), this was preventing the module
> signing cert from being loaded during boot. When the clock got fixed
> later on in he boot sequence, things *should* have started working. But
> they didn't...
>
> Signed-off-by: David Woodhouse <[email protected]>
> ---
>
> Arguably, for the specific case of module signing we shouldn't bother
> checking for a current time before the ValidFrom date *at all*. It's
> *always* going to be a screwed up system clock, because we don't have a
> usage model of post-dating module signatures. We should simply document
> that the date is *not* checked for module signing, and have done with
> it. But that's a separate issue.
>
> diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
> index 06007f0..326dc80 100644
> --- a/crypto/asymmetric_keys/x509_public_key.c
> +++ b/crypto/asymmetric_keys/x509_public_key.c
> @@ -154,8 +154,6 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
> (now.tm_sec < cert->valid_from.tm_sec
> ))))))))))) {
> pr_warn("Cert %s is not yet valid\n", cert->fingerprint);
> - ret = -EKEYREJECTED;
> - goto error_free_cert;
> }
> if (now.tm_year > cert->valid_to.tm_year ||
> (now.tm_year == cert->valid_to.tm_year &&
> @@ -170,8 +168,6 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
> (now.tm_sec > cert->valid_to.tm_sec
> ))))))))))) {
> pr_warn("Cert %s has expired\n", cert->fingerprint);
> - ret = -EKEYEXPIRED;
> - goto error_free_cert;
> }
>
> cert->pub->algo = x509_public_key_algorithms[cert->pkey_algo];
Why not remove the check and warning there too?
Regards,
Alexander