From 20accb4a0e7141e08887fdf389135cf7b0d8cdf7 Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Tue, 2 Oct 2012 09:56:09 -0400 Subject: [PATCH] Patch from David Howells to fix overflow on 32-bit X.509 certs (rhbz 861322) --- kernel.spec | 5 +- modsign-post-KS-jwb.patch | 174 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+), 1 deletion(-) diff --git a/kernel.spec b/kernel.spec index f9056f115..cc30867e5 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 1 +%global baserelease 2 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -2320,6 +2320,9 @@ fi # ||----w | # || || %changelog +* Tue Oct 02 2012 Josh Boyer +- Patch from David Howells to fix overflow on 32-bit X.509 certs (rhbz 861322) + * Tue Oct 2 2012 Peter Robinson - Update ARM configs for 3.6 final - Add highbank SATA driver for stability diff --git a/modsign-post-KS-jwb.patch b/modsign-post-KS-jwb.patch index 6dd81ffa0..ec61f3472 100644 --- a/modsign-post-KS-jwb.patch +++ b/modsign-post-KS-jwb.patch @@ -9151,3 +9151,177 @@ index 83eb505..2beea56 100644 -- 1.7.11.4 +The current choice of lifetime for the autogenerated X.509 of 100 years, +putting the validTo date in 2112, causes problems on 32-bit systems where a +32-bit time_t wraps in 2106. 64-bit x86_64 systems seem to be unaffected. + +This can result in something like: + + Loading module verification certificates + X.509: Cert 6e03943da0f3b015ba6ed7f5e0cac4fe48680994 has expired + MODSIGN: Problem loading in-kernel X.509 certificate (-127) + +Or: + + X.509: Cert 6e03943da0f3b015ba6ed7f5e0cac4fe48680994 is not yet valid + MODSIGN: Problem loading in-kernel X.509 certificate (-129) + +Instead of turning the dates into time_t values and comparing, turn the system +clock and the ASN.1 dates into tm structs and compare those piecemeal instead. + +Reported-by: Rusty Russell +Signed-off-by: David Howells +--- + + crypto/asymmetric_keys/x509_cert_parser.c | 25 ++++++++--------- + crypto/asymmetric_keys/x509_parser.h | 4 +-- + crypto/asymmetric_keys/x509_public_key.c | 42 ++++++++++++++++++++++++++--- + 3 files changed, 51 insertions(+), 20 deletions(-) + + +diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c +index 8fcac94..db07e8c 100644 +--- a/crypto/asymmetric_keys/x509_cert_parser.c ++++ b/crypto/asymmetric_keys/x509_cert_parser.c +@@ -434,11 +434,10 @@ int x509_process_extension(void *context, size_t hdrlen, + /* + * Record a certificate time. + */ +-static int x509_note_time(time_t *_time, size_t hdrlen, ++static int x509_note_time(struct tm *tm, size_t hdrlen, + unsigned char tag, + const unsigned char *value, size_t vlen) + { +- unsigned YY, MM, DD, hh, mm, ss; + const unsigned char *p = value; + + #define dec2bin(X) ((X) - '0') +@@ -448,30 +447,30 @@ static int x509_note_time(time_t *_time, size_t hdrlen, + /* UTCTime: YYMMDDHHMMSSZ */ + if (vlen != 13) + goto unsupported_time; +- YY = DD2bin(p); +- if (YY > 50) +- YY += 1900; ++ tm->tm_year = DD2bin(p); ++ if (tm->tm_year >= 50) ++ tm->tm_year += 1900; + else +- YY += 2000; ++ tm->tm_year += 2000; + } else if (tag == ASN1_GENTIM) { + /* GenTime: YYYYMMDDHHMMSSZ */ + if (vlen != 15) + goto unsupported_time; +- YY = DD2bin(p) * 100 + DD2bin(p); ++ tm->tm_year = DD2bin(p) * 100 + DD2bin(p); + } else { + goto unsupported_time; + } + +- MM = DD2bin(p); +- DD = DD2bin(p); +- hh = DD2bin(p); +- mm = DD2bin(p); +- ss = DD2bin(p); ++ tm->tm_year -= 1900; ++ tm->tm_mon = DD2bin(p) - 1; ++ tm->tm_mday = DD2bin(p); ++ tm->tm_hour = DD2bin(p); ++ tm->tm_min = DD2bin(p); ++ tm->tm_sec = DD2bin(p); + + if (*p != 'Z') + goto unsupported_time; + +- *_time = mktime(YY, MM, DD, hh, mm, ss); + return 0; + + unsupported_time: +diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h +index 635053f..f86dc5f 100644 +--- a/crypto/asymmetric_keys/x509_parser.h ++++ b/crypto/asymmetric_keys/x509_parser.h +@@ -18,8 +18,8 @@ struct x509_certificate { + char *subject; /* Name of certificate subject */ + char *fingerprint; /* Key fingerprint as hex */ + char *authority; /* Authority key fingerprint as hex */ +- time_t valid_from; +- time_t valid_to; ++ struct tm valid_from; ++ struct tm valid_to; + enum pkey_algo pkey_algo : 8; /* Public key algorithm */ + enum pkey_algo sig_pkey_algo : 8; /* Signature public key algorithm */ + enum pkey_hash_algo sig_hash_algo : 8; /* Signature hash algorithm */ +diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c +index 716917c..5ab736d 100644 +--- a/crypto/asymmetric_keys/x509_public_key.c ++++ b/crypto/asymmetric_keys/x509_public_key.c +@@ -106,7 +106,7 @@ error_no_sig: + static int x509_key_preparse(struct key_preparsed_payload *prep) + { + struct x509_certificate *cert; +- time_t now; ++ struct tm now; + size_t srlen, sulen; + char *desc = NULL; + int ret; +@@ -118,7 +118,14 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) + pr_devel("Cert Issuer: %s\n", cert->issuer); + pr_devel("Cert Subject: %s\n", cert->subject); + pr_devel("Cert Key Algo: %s\n", pkey_algo[cert->pkey_algo]); +- pr_devel("Cert Valid: %lu - %lu\n", cert->valid_from, cert->valid_to); ++ printk("Cert Valid From: %04ld-%02d-%02d %02d:%02d:%02d\n", ++ cert->valid_from.tm_year + 1900, cert->valid_from.tm_mon + 1, ++ cert->valid_from.tm_mday, cert->valid_from.tm_hour, ++ cert->valid_from.tm_min, cert->valid_from.tm_sec); ++ printk("Cert Valid To: %04ld-%02d-%02d %02d:%02d:%02d\n", ++ cert->valid_to.tm_year + 1900, cert->valid_to.tm_mon + 1, ++ cert->valid_to.tm_mday, cert->valid_to.tm_hour, ++ cert->valid_to.tm_min, cert->valid_to.tm_sec); + pr_devel("Cert Signature: %s + %s\n", + pkey_algo[cert->sig_pkey_algo], + pkey_hash_algo[cert->sig_hash_algo]); +@@ -130,13 +137,38 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) + goto error_free_cert; + } + +- now = CURRENT_TIME.tv_sec; +- if (now < cert->valid_from) { ++ time_to_tm(CURRENT_TIME.tv_sec, 0, &now); ++ printk("Now: %04ld-%02d-%02d %02d:%02d:%02d\n", ++ now.tm_year + 1900, now.tm_mon + 1, now.tm_mday, ++ now.tm_hour, now.tm_min, now.tm_sec); ++ if (now.tm_year < cert->valid_from.tm_year || ++ (now.tm_year == cert->valid_from.tm_year && ++ (now.tm_mon < cert->valid_from.tm_mon || ++ (now.tm_mon == cert->valid_from.tm_mon && ++ (now.tm_mday < cert->valid_from.tm_mday || ++ (now.tm_mday == cert->valid_from.tm_mday && ++ (now.tm_hour < cert->valid_from.tm_hour || ++ (now.tm_hour == cert->valid_from.tm_hour && ++ (now.tm_min < cert->valid_from.tm_min || ++ (now.tm_min == cert->valid_from.tm_min && ++ (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 >= cert->valid_to) { ++ if (now.tm_year > cert->valid_to.tm_year || ++ (now.tm_year == cert->valid_to.tm_year && ++ (now.tm_mon > cert->valid_to.tm_mon || ++ (now.tm_mon == cert->valid_to.tm_mon && ++ (now.tm_mday > cert->valid_to.tm_mday || ++ (now.tm_mday == cert->valid_to.tm_mday && ++ (now.tm_hour > cert->valid_to.tm_hour || ++ (now.tm_hour == cert->valid_to.tm_hour && ++ (now.tm_min > cert->valid_to.tm_min || ++ (now.tm_min == cert->valid_to.tm_min && ++ (now.tm_sec > cert->valid_to.tm_sec ++ ))))))))))) { + pr_warn("Cert %s has expired\n", cert->fingerprint); + ret = -EKEYEXPIRED; + goto error_free_cert; +