From: James Bottomley <James.Bottomley@HansenPartnership.com>
To: Laszlo Ersek <lersek@redhat.com>, ekhoruzhenko@absolute.com
Cc: devel@edk2.groups.io,
Paulo Henrique Lacerda de Amorim <phlamorim@riseup.net>
Subject: Re: [edk2-devel] Interpretation of specification
Date: Wed, 08 Jan 2020 11:13:37 -0800 [thread overview]
Message-ID: <1578510817.3260.73.camel@HansenPartnership.com> (raw)
In-Reply-To: <a6170b3c-4964-ec9e-b601-f0d351368a0e@redhat.com>
On Wed, 2020-01-08 at 12:24 +0100, Laszlo Ersek wrote:
> (+James)
>
> On 01/07/20 19:13, Eugene Khoruzhenko wrote:
> > I think I may have found the problem. I can write the
> > file_name.signed created by your scripts in NT32 emulated
> > environment and in EDKII on Minnow board that I build myself.
> > However, I cannot write the file_name.signed on a commercial
> > device. I can write the same authenticate variable with the same
> > Name/GUID and same cert/key on a device when I create the payload
> > in a UEFI Shell app. So the only difference is creating the signed
> > payload by sbvarsign in Ubuntu vs doing it in UEFI. I compared both
> > the working and non-working payloads and the main difference I see
> > is in the timestamp. For some reason sbvarsign writes the Year as
> > 0x0078 (120) vs the UEFI app writing 0x07e4 (2020). The
> > month/day/hour/min seems to be OK, but the year is really off in
> > the sbvarsign's payload. I cannot prove it, but I think the
> > commercial firmware may be having a sanity check for the
> > timestamp date/time, e.g. compare with the device manufacture date.
> > Since sbvarsign does not allow setting a timestamp separately, I
> > cannot force it to create a payload with the correct year.
>
> That looks like a bug in sbvarsign. In UEFI-2.8, the EFI_TIME
> structure is defined under 8.3 "Time Services" / GetTime(). The Year
> field is given like this:
>
> UINT16 Year; // 1900 - 9999
>
> The comment indicates the valid range. It does not indicate that the
> value stored should be relative to the year 1900 (which is what
> sbvarsign appears to assume; 2020-1900=120).
>
> The UEFI application likely uses GetTime(), for populating
> "EFI_VARIABLE_AUTHENTICATION_2.TimeStamp" with the current time
> (which is prescribed in 8.2.2 "Using the
> EFI_VARIABLE_AUTHENTICATION_2 descriptor").
>
> After GetTime() returns successfully, the application may still need
> to manually ensure that "Pad1, Nanosecond, TimeZone, Daylight and
> Pad2" are zeroed. This could involve timezone translation (to the
> required UTC), which in some cases could even imply a change to the
> Year field. But that doesn't change the fact that GetTime() initally
> places an absolute year number in the Year field, and not one
> relative to 1900.
>
> Let me see the "sbsigntool" source code:
>
> https://git.kernel.org/pub/scm/linux/kernel/git/jejb/sbsigntools.gi
> t
>
> (Repository URL via
> <https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=920013>.)
>
> Yup, here's the bug (at current master, that is, commit 0dc3d4b5210d,
> "Fix PE/COFF checksum calculation", 2019-07-27):
>
> https://git.kernel.org/pub/scm/linux/kernel/git/jejb/sbsigntools.gi
> t/tree/src/sbvarsign.c?id=0dc3d4b5210dae158651d058f7ac68a9f178ae84#n2
> 15
>
> Quote:
>
> 199 static int set_timestamp(EFI_TIME *timestamp)
> 200 {
> 201 struct tm *tm;
> 202 time_t t;
> 203
> 204 time(&t);
> 205
> 206 tm = gmtime(&t);
> 207 if (!tm) {
> 208 perror("gmtime");
> 209 return -1;
> 210 }
> 211
> 212 /* copy to our EFI-specific time structure. Other
> fields (Nanosecond,
> 213 * TimeZone, Daylight and Pad) are defined to be zero
> */
> 214 memset(timestamp, 0, sizeof(*timestamp));
> 215 timestamp->Year = tm->tm_year;
> 216 timestamp->Month = tm->tm_mon;
> 217 timestamp->Day = tm->tm_mday;
> 218 timestamp->Hour = tm->tm_hour;
> 219 timestamp->Minute = tm->tm_min;
> 220 timestamp->Second = tm->tm_sec;
> 221
> 222 return 0;
> 223 }
>
> Please refer to POSIX for time(), gmtime(), and "struct tm":
>
> https://pubs.opengroup.org/onlinepubs/9699919799/functions/time.htm
> l
> https://pubs.opengroup.org/onlinepubs/9699919799/functions/gmtime.h
> tml
> https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/time.h.ht
> ml
>
> Quoting the last reference:
>
> > The <time.h> header shall declare the tm structure, which shall
> > include at least the following members:
> >
> > int tm_sec Seconds [0,60].
> > int tm_min Minutes [0,59].
> > int tm_hour Hour [0,23].
> > int tm_mday Day of month [1,31].
> > int tm_mon Month of year [0,11].
> > int tm_year Years since 1900.
> > int tm_wday Day of week [0,6] (Sunday =0).
> > int tm_yday Day of year [0,365].
> > int tm_isdst Daylight Savings flag.
>
> That is, field "tm_year" is relative to 1900.
>
> The bug is therefore in set_timestamp(), on line 215. It should be
>
> timestamp->Year = 1900 + tm->tm_year;
>
> The bug goes back to commit 953b00481f39 ("sbvarsign: First cut of a
> variable-signing tool", 2012-08-02).
>
> (Otherwise, gmtime() is a good choice, because it gives us UTC at
> once, which is what EFI_VARIABLE_AUTHENTICATION_2 requires, per UEFI
> spec ("GMT").)
>
> I don't know where sbsigntools development occurs (mailing list, bug
> tracker, ...). For now, I'm CC'ing James. (The git repo lives in his
> space on <git.kernel.org>.)
Heh, that's a sore point: since Jeremy Kerr left ubuntu, no-one except
me has been maintaining it; Jeremy owns the original tree on the Ubuntu
servers but can't update it any more.
I use groups.io for the openssl_tpm2_engine development list, so I
suppose I can set one up for sbsigntools ... OK, done. If you want to
you can package the above up as a patch and send it there and I'll
apply it.
James
> James, the original thread on edk2-devel is here:
>
> * [edk2-devel] Interpretation of specification
> https://edk2.groups.io/g/devel/message/49402
>
> Thanks,
> Laszlo
>
next prev parent reply other threads:[~2020-01-08 19:13 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-10-23 17:12 Interpretation of specification phlamorim
2019-10-24 12:33 ` [edk2-devel] " Laszlo Ersek
2019-11-15 18:51 ` phlamorim
2019-11-15 21:32 ` Laszlo Ersek
2019-11-23 4:59 ` Eugene Khoruzhenko
2019-11-23 13:08 ` Paulo Henrique Lacerda de Amorim
2019-11-26 6:08 ` Eugene Khoruzhenko
2019-11-26 15:22 ` Paulo Henrique Lacerda de Amorim
2020-01-03 19:52 ` Eugene Khoruzhenko
2020-01-04 17:17 ` Paulo Henrique Lacerda de Amorim
2020-01-07 18:13 ` Eugene Khoruzhenko
2020-01-08 11:24 ` Laszlo Ersek
2020-01-08 19:13 ` James Bottomley [this message]
2020-01-09 17:17 ` Laszlo Ersek
2020-01-09 17:20 ` James Bottomley
2020-01-10 10:55 ` Laszlo Ersek
2020-01-10 16:04 ` James Bottomley
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1578510817.3260.73.camel@HansenPartnership.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox