<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:base="https://jbeekman.nl/">
  <id>https://jbeekman.nl/</id>
  <title>Technology &amp; Policy</title>
  <updated>2017-03-01T12:00:00Z</updated>
  <link rel="alternate" href="https://jbeekman.nl/"/>
  <link rel="self" href="https://jbeekman.nl/blog/"/>
  <author>
    <name>Jethro Beekman</name>
    <uri>https://jbeekman.nl/blog</uri>
  </author>
  <icon>https://jbeekman.nl/favicon.ico</icon>
  <entry>
    <id>tag:jbeekman.nl,2017-03-01:/blog/2017/03/sgx-side-channel-attacks/</id>
    <title type="html">On the recent side-channel attacks on Intel SGX – Technology &amp; Policy</title>
    <published>2017-03-01T12:00:00Z</published>
    <updated>2017-03-01T12:00:00Z</updated>
    <link rel="alternate" href="https://jbeekman.nl/blog/2017/03/sgx-side-channel-attacks/"/>
    <content type="html">&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Side-channel_attack"&gt;Side-channel attacks&lt;/a&gt; are 
my favorite attack in computer security because they poke giant holes in the 
abstraction and security models that system designers are using. When I hear of 
a new attack avenue in this space, my first reaction often is “wow, that is 
&lt;em&gt;so&lt;/em&gt; cool” and “I didn’t even think about that.”&lt;/p&gt;

&lt;p&gt;In the past week, &lt;a href="https://arxiv.org/abs/1702.07521"&gt;two&lt;/a&gt; 
&lt;a href="https://arxiv.org/abs/1702.08719"&gt;papers&lt;/a&gt; have been published on arXiv 
detailing side-channel attacks on &lt;a href="https://software.intel.com/en-us/sgx"&gt;Intel 
SGX&lt;/a&gt;. While the existence of such attacks 
should be taken seriously by people designing systems using Intel SGX (which 
includes yours truly), these particular attacks are not very interesting.&lt;/p&gt;

&lt;p&gt;First of all, these attacks really shouldn’t come as a surprise to anyone 
following this space. Cache-based side-channel attacks are a well-known attack 
vector. Many papers detailing new techniques have been published over the last 
couple of years. There’s &lt;a href="http://www.cs.tau.ac.il/~tromer/papers/cache.pdf"&gt;Evict+Time and 
Prime+Probe&lt;/a&gt;, 
&lt;a href="https://www.usenix.org/system/files/conference/usenixsecurity14/sec14-paper-yarom.pdf"&gt;Flush+Reload&lt;/a&gt;, 
&lt;a href="https://arxiv.org/abs/1511.04594"&gt;Flush+Flush&lt;/a&gt;, etc. &lt;a href="https://eprint.iacr.org/2016/613"&gt;Ge et. 
al.&lt;/a&gt; present a good overview of the current 
state of the art. Intel explicitly states in their &lt;a href="https://software.intel.com/sites/default/files/managed/ae/48/Software-Guard-Extensions-Enclave-Writers-Guide.pdf"&gt;Enclave Writer’s 
Guide&lt;/a&gt; 
that they don’t protect against attacks at cache line or higher granularity.&lt;/p&gt;

&lt;p&gt;Second of all, both attacks are exploiting well-known flaws in modular 
exponentiation implementations. We &lt;em&gt;know&lt;/em&gt; how to do constant-time RSA. On top 
of that, both papers are at best slightly misleading in describing their attack 
targets.&lt;/p&gt;

&lt;p&gt;From the &lt;a href="https://arxiv.org/abs/1702.07521"&gt;first paper&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;As our victim enclave we chose an RSA implementation from the Intel IIP 
crypto library in the Intel SGX SDK. The attacked decryption variant is a 
fixed-size sliding window exponentiation, the code is available online at 
&lt;a href="https://github.com/01org/linux-sgx/blob/6662022/external/crypto_px/sources/ippcp/src/pcpngrsamontstuff.c#L336"&gt;[32]&lt;/a&gt;. 
The Intel IIP library includes also a variant of RSA that is hardened against 
cache attacks 
&lt;a href="https://github.com/01org/linux-sgx/blob/6662022/external/crypto_px/sources/ippcp/src/pcpngrsamontstuff.c#L438"&gt;[33]&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you look at how these two variants are used, you can see that only 
&lt;a href="https://github.com/01org/linux-sgx/blob/6662022/external/crypto_px/sources/ippcp/src/pcpngrsaencodec.c#L180"&gt;computations with the public 
exponent&lt;/a&gt; 
are done with the “vulnerable” variant, whereas &lt;a href="https://github.com/01org/linux-sgx/blob/6662022/external/crypto_px/sources/ippcp/src/pcpngrsaencodec.c#L265"&gt;computations with the private 
exponent&lt;/a&gt; 
use the “hardened” variant. So, unless you are somehow swapping your public and 
private exponents, using this crypto library as documented will prevent this 
attack for you.&lt;/p&gt;

&lt;p&gt;From the &lt;a href="https://arxiv.org/abs/1702.08719"&gt;second paper’s abstract&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;We perform a Prime+Probe cache side-channel attack on a co-located SGX 
enclave running an up-to-date RSA implementation that uses a constant-time 
multiplication primitive.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Even though the library they use might have a multiplication primitive that is 
constant-time, as the authors explain further on in the paper, the modular 
exponentiation primitive is not. In fact, the modular exponentiation algorithm 
is the textbook example of an algorithm with a secret-dependent branch:&lt;/p&gt;

&lt;div class="language-c++ highlighter-coderay"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span style="color:#0a8;font-weight:bold"&gt;int&lt;/span&gt; modexp(&lt;span style="color:#0a8;font-weight:bold"&gt;int&lt;/span&gt; base, &lt;span style="color:#0a8;font-weight:bold"&gt;int&lt;/span&gt; exponent, &lt;span style="color:#0a8;font-weight:bold"&gt;int&lt;/span&gt; modulus) {
    &lt;span style="color:#0a8;font-weight:bold"&gt;int&lt;/span&gt; result = &lt;span style="color:#00D"&gt;1&lt;/span&gt;;
    &lt;span style="color:#080;font-weight:bold"&gt;for&lt;/span&gt; (&lt;span style="color:#0a8;font-weight:bold"&gt;int&lt;/span&gt; i = &lt;span style="color:#00D"&gt;0&lt;/span&gt;; i &amp;lt; exponent.bits(); i++) {
        result = modsqr(result, modulus);
        &lt;span style="color:#080;font-weight:bold"&gt;if&lt;/span&gt; (exponent &amp;amp; (&lt;span style="color:#00D"&gt;1&lt;/span&gt;&amp;lt;&amp;lt;i)) { &lt;span style="color:#777"&gt;// access bit `i`&lt;/span&gt;
            result = modmul(result, base, modulus);
        }
    }
    &lt;span style="color:#080;font-weight:bold"&gt;return&lt;/span&gt; result;
}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;If for each iteration of the loop you can detect whether the multiplication 
happenned or not, you can reconstruct the individual bits of the exponent. This 
is a fun attack, but as mentioned, this is basically the most well-known timing 
attack, &lt;a href="https://www.eng.tau.ac.il/~yash/infosec-seminar/2005/kocher95.pdf"&gt;first described by Kocher 22 years 
ago&lt;/a&gt;. Oh and 
the library? It implements the blinding mitigation also mentioned in that 
seminal paper.&lt;/p&gt;

&lt;p&gt;To summarize: Yes, programs running with Intel SGX are vulnerable to 
side-channel attacks. The same side-channel attacks that have been used for 
years on modern x86 platforms. This is well-documented. SGX does present a 
slightly different threat model which makes deployment of side-channel attacks 
more likely. Hopefully everyone using SGX is implementing countermeasures. They 
do exist, and are already implemented by most cryptography libraries.&lt;/p&gt;
</content>
    <summary type="html">&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Side-channel_attack"&gt;Side-channel attacks&lt;/a&gt; are 
my favorite attack in computer security because they poke giant holes in the 
abstraction and security models that system designers are using. When I hear of 
a new attack avenue in this space, my first reaction often is &amp;#x201C;wow, that is 
&lt;em&gt;so&lt;/em&gt; cool&amp;#x201D; and &amp;#x201C;I didn&amp;#x2019;t even think about that.&amp;#x201D;&lt;/p&gt;</summary>
  </entry>
  <entry>
    <id>tag:jbeekman.nl,2016-03-09:/blog/2016/03/new-opt-stem-extension/</id>
    <title type="html">New OPT STEM extension rules – Technology &amp; Policy</title>
    <published>2016-03-09T12:00:00Z</published>
    <updated>2016-03-09T12:00:00Z</updated>
    <link rel="alternate" href="https://jbeekman.nl/blog/2016/03/new-opt-stem-extension/"/>
    <content type="html">&lt;p&gt;Today, the &lt;a href="https://www.ice.gov/news/releases/sevp-stem-opt"&gt;U.S. Department of Homeland Security 
announced&lt;/a&gt; that the &lt;a href="https://s3.amazonaws.com/public-inspection.federalregister.gov/2016-04828.pdf"&gt;new rules 
regarding the “Optional Practical Training STEM 
extension”&lt;/a&gt; 
for international students in the U.S. on F-1 visas will be published in the 
Federal Register on Friday. The new rules are a result of a lawsuit against DHS 
that would result in an invalidation of the old rules. The new rules are 
“better” in some respects and “worse” in others. In this blog post I will 
review some of the most important changes and how they will affect 
international students.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update 2016-03-09:&lt;/strong&gt; A previous version of this post suggested that one could 
get two consecutive STEM extensions. Careful reading of the rule counters this, 
as does an explicit comment in the supplementary information: “DHS clarifies 
that the final rule, as with the proposed rule, does not allow students to 
obtain back-to-back STEM OPT extensions.”&lt;/p&gt;

&lt;h3 id="reasons-for-the-stem-extension"&gt;Reasons for the STEM extension&lt;/h3&gt;

&lt;p&gt;The DHS is very clear in the rules and the accompanying comments that the goal 
of OPT is practical training for students, and not to bridge a gap in the U.S. 
labor force. They see practical training as a vital part of a good education, 
and providing OPT is a key mechanism in staying competitive in the 
international education market. Therefore, they basically disregarded any 
comments that talk about a shortage or overage in U.S. STEM workers. There is 
however a provision that employers can’t use a student on the STEM extension to 
replace a U.S. worker, and also that students need to be paid the same as other 
workers in similar positions. These requirements seem to be designed to assuage 
fears of “cheap foreign labor taking our jobs.”&lt;/p&gt;

&lt;p&gt;Because the justification is practical training, you might ask why there is 
this specific extension for STEM workers, and not just a general length 
increase for all OPT. DHS clarifies this as follows:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;[…] because of the specific nature of [STEM students’s] studies and 
fields and the increasing need for enhancement of STEM skill application 
outside of the classroom. DHS also found, as noted previously, that unlike 
post-degree training in many non-STEM fields, training in STEM fields often 
involves multi-year research projects as well as multi-year grants from 
institutions such as the NSF.&lt;/p&gt;

  &lt;p&gt;Many STEM OPT practical training opportunities are research related, as 
indicated by the fact that the employer that retains the most STEM OPT 
students is the University of California system and that two other 
universities are among the top six of such employers (Johns Hopkins 
University and Harvard University).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id="basics"&gt;Basics&lt;/h3&gt;

&lt;p&gt;First up: some straightforward changes. The length of the STEM extension is now 
2 full years instead of the 17 months under the old rule. The “cap-gap 
extension”—where OPT is automatically extended if the student has an approved 
petition for an H-1B visa—is maintained. Students are now allowed to be 
unemployed for a maximum total of 150 days during their initial OPT and their 
STEM extension.&lt;/p&gt;

&lt;h3 id="training-plan-for-stem-opt-students"&gt;Training Plan for STEM OPT Students&lt;/h3&gt;

&lt;p&gt;One of the big changes to the STEM extension is that students and employers now 
need to come up with a training plan in order to get the extension. Students 
must fill out a new Form I-983, “Training Plan for STEM OPT Students,” together 
with their employer and file that with their STEM extension request.&lt;/p&gt;

&lt;p&gt;The new article 8 CFR 214.2(f)(10)(ii)(C)(7) says:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The training plan described in the Form I-983 […] form must identify goals 
for the STEM practical training opportunity, including specific knowledge, 
skills, or techniques that will be imparted to the student, and explain how 
those goals will be achieved through the work-based learning opportunity with 
the employer; describe a performance evaluation process; and describe methods 
of oversight and supervision.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The form is not available at the time of writing, but there is what seems to be 
a &lt;a href="http://www.reginfo.gov/public/do/DownloadDocument?objectID=62195800"&gt;draft of the instructions accompanying the 
form&lt;/a&gt;. The 
relevant parts of the instructions basically echo the rule above.&lt;/p&gt;

&lt;p&gt;At this time it’s not very clear how detailed the plan needs to be. Can 
applicants just write down some business lingo (e.g. “improving core 
competencies”) or do the goals need to be more substantial? Under the current 
rules, it seems that the “Designated School Official” (i.e. someone who works 
at your school’s international office) needs to gauge whether the proposed plan 
meets the regulatory requirements.&lt;/p&gt;

&lt;p&gt;Once the extension is approved, students will need to evaluate themselves 
annually, according to the plan. Their employers will need to sign their 
evaluation as well.&lt;/p&gt;

&lt;p&gt;There are just too many unknowns at this point to really know how this will 
affect the types of jobs international students will be able to get and how 
this will affect the amount of time they have to spend on things besides their 
normal job responsibilities.&lt;/p&gt;

&lt;h3 id="employer-employee-relationship"&gt;Employer-employee relationship&lt;/h3&gt;

&lt;p&gt;While the actual rules text doesn’t seem to touch on this, the comments and 
clarifications accompanying the rules suggest that it might be harder to work 
in an “unusual” work arrangements, such as start-up companies:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;There are several aspects of the STEM OPT extension that do not make it apt 
for certain types of arrangements, including multiple employer arrangements, 
sole proprietorships, employment through “temp” agencies, employment through 
consulting firm arrangements that provide labor for hire, and other 
relationships that do not constitute a bona fide employer-employee 
relationship.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One of these aspects seems to be that someone else at the same company you work 
for needs to sign your Form I-983:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;[…] students cannot qualify for STEM OPT extensions unless they will be 
bona fide employees of the employer signing the Training Plan, and the 
employer that signs the Training Plan must be the same entity that employs 
the student and provides the practical training experience.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;STEM OPT extensions may be employed by new “start-up” businesses so long as 
all regulatory requirements are met, including that the employer adheres to 
the training plan requirements, remains in good standing with E-Verify, will 
provide compensation to the STEM OPT student commensurate to that provided to 
similarly situated U.S. workers, and has the resources to comply with the 
proposed training plan.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;[…] any ownership interest in the employer entity (such as stock options), 
[must be] commensurate with the compensation provided to other similarly 
situated U.S. workers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So while the rules seem to prevent running a sole proprietorship under the STEM 
extension, it seems entirely feasible that another employee at your startup can 
fulfill all the supervisory training requirements. If you’re starting out on 
your own, you could use your first year of regular OPT to get your company off 
the ground, and hopefully by the time you need to file for the STEM extension 
you have a co-founder or such who can provided the necessary “training.”&lt;/p&gt;

&lt;h3 id="summary"&gt;Summary&lt;/h3&gt;

&lt;p&gt;I’m pretty positive in general about the new rules, and am of course glad that 
DHS acted swiftly to make new rules after the court decision in August. I’m 
somewhat concerned about the rules around the training plan, but we’ll see how 
that’s going to work out in practice. Everything else seems to be an 
improvement (big or small) upon the previous rules.&lt;/p&gt;
</content>
    <summary type="html">&lt;p&gt;Today, the &lt;a href="https://www.ice.gov/news/releases/sevp-stem-opt"&gt;U.S. Department of Homeland Security 
announced&lt;/a&gt; that the &lt;a href="https://s3.amazonaws.com/public-inspection.federalregister.gov/2016-04828.pdf"&gt;new rules 
regarding the &amp;#x201C;Optional Practical Training STEM 
extension&amp;#x201D;&lt;/a&gt; 
for international students in the U.S. on F-1 visas will be published in the 
Federal Register on Friday. The new rules are a result of a lawsuit against DHS 
that would result in an invalidation of the old rules. The new rules are 
&amp;#x201C;better&amp;#x201D; in some respects and &amp;#x201C;worse&amp;#x201D; in others. In this blog post I will 
review some of the most important changes and how they will affect 
international students.&lt;/p&gt;</summary>
  </entry>
  <entry>
    <id>tag:jbeekman.nl,2015-10-13:/blog/2015/10/intel-has-full-control-over-sgx/</id>
    <title type="html">Intel has full control over SGX – Technology &amp; Policy</title>
    <published>2015-10-13T12:00:00Z</published>
    <updated>2015-10-13T12:00:00Z</updated>
    <link rel="alternate" href="https://jbeekman.nl/blog/2015/10/intel-has-full-control-over-sgx/"/>
    <content type="html">&lt;p&gt;Intel has full control over what software you can run in SGX. This might seem 
redundant: Intel makes the processor, so of course they have full control. Yet 
the truth is slightly more inconvenient. When Intel processors don’t run the 
instructions in your standard software (whether incorrectly or at all), that is 
a defect at best and a breach of contract at worst. Yet the SGX instruction set 
&lt;em&gt;includes in its specification&lt;/em&gt; that Intel has the authority to make this 
go/no-go decision.&lt;/p&gt;

&lt;p&gt;Let’s take a closer look at how exactly this is specified, since it is pretty 
well-hidden. After creating and measuring a secure enclave using ECREATE, EADD, 
and EEXTEND, the EINIT instruction needs to be executed before execution 
control can be transferred to the enclave. The EINIT instruction has 2 inputs: 
SIGSTRUCT and EINITTOKEN. SIGSTRUCT contains information about the enclave 
including an expected hash of the memory. As the name implies, SIGSTRUCT is 
also cryptographically signed using some key. EINITTOKEN also contains 
information about the enclave including the same expected hash of the memory as 
well as the expected public key for the signature. EINITTOKEN must be 
&lt;a href="https://en.wikipedia.org/wiki/Message_authentication_code"&gt;MAC&lt;/a&gt;ed using the 
so-called &lt;em&gt;launch key&lt;/em&gt;. Both SIGSTRUCT and EINITTOKEN are checked by EINIT and 
must be valid for execution to proceed succesfully.&lt;/p&gt;

&lt;p&gt;Since the launch key is a symmetric cryptography device, surely this key is not 
widely distributed and most likely is CPU-specific. But how can one obtain this 
key? The EGETKEY instruction can be used to obtain SGX keys, including the 
launch key. But this is a user-mode instruction that can only be executed from 
inside an enclave. There seems to be a chicken-and-egg problem here: to launch 
an enclave, we need the launch key. To get the launch key, we need to launch an 
enclave! Here’s the catch: the EINITTOKEN need not be valid if SIGSTRUCT is 
signed by an Intel key that is baked into the processor.&lt;/p&gt;

&lt;p&gt;Thus, Intel can distribute an Intel-signed “launch enclave” that is able to 
hand out correctly-MACed EINITTOKENs that can then be used to start other 
enclaves. But they can include whatever logic they want in the launch enclave
so Intel can at its sole discretion choose not to MAC a particular EINITTOKEN.&lt;/p&gt;

&lt;p&gt;As most things SGX, this “feature” is severely underdocumented. The terms 
“launch key” and “launch enclave” are only mentioned a few times in the SGX 
programming reference and never in the whitepapers or tutorials. At the time of 
writing, nowhere else on the Internet is there any mention of these keywords, 
except for one &lt;a href="https://www.quora.com/What-are-some-good-uses-for-Intel-Software-Guard-Extensions-SGX"&gt;insightful Quora 
answer&lt;/a&gt; 
that I wish I had read months ago.&lt;/p&gt;

&lt;p&gt;What reason could Intel have for this architecture? Along with the fact that 
&lt;a href="/blog/sgx-hardware-first-look"&gt;SGX is being disabled by default&lt;/a&gt;, this looks 
like Intel is again just setting this security technology up for failure due to 
the lack of widespread adoption by developers and users alike (cf. TXT, SMX, 
TPM).&lt;/p&gt;
</content>
    <summary type="html">&lt;p&gt;Intel has full control over what software you can run in SGX. This might seem 
redundant: Intel makes the processor, so of course they have full control. Yet 
the truth is slightly more inconvenient. When Intel processors don&amp;#x2019;t run the 
instructions in your standard software (whether incorrectly or at all), that is 
a defect at best and a breach of contract at worst. Yet the SGX instruction set 
&lt;em&gt;includes in its specification&lt;/em&gt; that Intel has the authority to make this 
go/no-go decision.&lt;/p&gt;</summary>
  </entry>
  <entry>
    <id>tag:jbeekman.nl,2015-10-08:/blog/2015/10/sgx-hardware-first-look/</id>
    <title type="html">SGX Hardware: A first look – Technology &amp; Policy</title>
    <published>2015-10-08T12:00:00Z</published>
    <updated>2015-12-09T12:00:00Z</updated>
    <link rel="alternate" href="https://jbeekman.nl/blog/2015/10/sgx-hardware-first-look/"/>
    <content type="html">&lt;p&gt;Without much fanfare, Intel has released &lt;a href="https://software.intel.com/en-us/isa-extensions/intel-sgx"&gt;Software Guard Extensions 
(SGX)&lt;/a&gt; in Skylake. 
When I say “without much fanfare,” I mean practically only the following 
paragraph hidden on page 3 of a &lt;a href="http://download.intel.com/newsroom/kits/core/6thgen/pdfs/6th_Gen_Intel_Core-Intel_Xeon_Factsheet.pdf"&gt;press fact 
sheet&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;BETTER SECURITY.&lt;/strong&gt; The Skylake architecture has been designed to enable better 
security, including Intel® Software Guard Extensions (Intel® SGX) that can 
provide an additional level of hardware-based protection by putting data into 
a secure container on the platform, and Intel® Memory Protection Extensions 
(Intel® MPX) that can help prevent buffer flow attacks. [What’s a buffer flow 
attack? &lt;em&gt;Ed.&lt;/em&gt;] To be fully utilized, Intel SGX and Intel MPX require additional 
software capabilities, which will begin to be delivered by the ecosystem 
later this year.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It has been extremely difficult to find actual hardware that supports SGX. BIOS 
support is required–the BIOS needs to set aside memory for the Enclave Page 
Cache (EPC)–but of course no vendor will mention anything about this on their 
website, nor will they (be able to) answer when you inquire regarding this 
specific issue.&lt;/p&gt;

&lt;p&gt;To my delight, by using Google to search past week results for “intel sgx” for 
the last few months, I was finally able to find a driver download site that 
linked this &lt;a href="http://www.dell.com/support/home/us/en/19/Drivers/DriversDetails?driverId=F84XC"&gt;Dell 
driver&lt;/a&gt;.
According to Dell’s website, this driver is compatible with the following machine models:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Inspiron 11 i3153&lt;/li&gt;
  &lt;li&gt;Inspiron 11 i3158&lt;/li&gt;
  &lt;li&gt;Inspiron 13 i7353&lt;/li&gt;
  &lt;li&gt;Inspiron 13 i7359&lt;/li&gt;
  &lt;li&gt;Inspiron 15 i7568&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At first I couldn’t find these models mentioned anywhere, but a few days later 
the i7359 showed up at 
&lt;a href="http://www.newegg.com/Product/ProductList.aspx?Submit=ENE&amp;amp;Description=dell+i7359"&gt;NewEgg&lt;/a&gt; 
and then at &lt;a href="http://frys.com/search?query_string=dell+i7359"&gt;Frys&lt;/a&gt;. So, I drove 
to Sunnyvale (where Frys had the i7359-2435SLV in stock) and I can now confirm 
that &lt;strong&gt;SGX is real&lt;/strong&gt;:&lt;/p&gt;

&lt;div style="width:100%;text-align:center"&gt;
	&lt;a href="/img/blog/sgx-hardware-first-look/bios1.jpeg"&gt;&lt;img src="/img/blog/sgx-hardware-first-look/bios1-small.jpeg" style="width:45%;margin-right:3.3%" /&gt;&lt;/a&gt;
	&lt;a href="/img/blog/sgx-hardware-first-look/bios2.jpeg"&gt;&lt;img src="/img/blog/sgx-hardware-first-look/bios2-small.jpeg" style="width:45%" /&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;It’s interesting to note that SGX was disabled in the BIOS by default, so most 
consumers will not be able to benefit from this feature at all.&lt;/p&gt;

&lt;p&gt;The maximum size of the EPC on this laptop is 128MB. This means that enclaves 
requiring more memory than that will need regular paging between the EPC and 
main memory. It’s not clear whether such a copy would require re-encryption of 
the page, the EPC itself is already encrypted so it might not be necessary.&lt;/p&gt;

&lt;p&gt;The laptop comes with Windows 10 which runs excruciatingly slow–not surprising 
considering it only has 4GB of RAM. I installed Arch Linux on it because it’s 
one of the few distro’s that has an installer with a very recent kernel 
(4.2.2), required for such new hardware.&lt;/p&gt;

&lt;p&gt;I collected some CPUID and MSR information to see what SGX features are 
supported:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;CPUID&lt;/strong&gt;&lt;/p&gt;

  &lt;pre&gt;&lt;code&gt;                         bit 2 (SGX) is set
                         v
 7h(0h) 00000000h 029c67afh 00000000h 00000000h

     Max. enclave size 2^31 bytes (32-bit mode)
  Max. enclave size 2^36 bytes (64-bit mode) |
    No extended SSA features supported    |  |
SGX version 1 supported  |                |\/|
               v         v                vvvv
12h(0h) 00000001h 00000000h 00000000h 0000241fh

              all enclave attributes supported
              |\       all XSAVE bits supported
              vv                  vv
12h(1h) 00000036h 00000000h 0000001fh 00000000h

   EPC physical address 80200000h
        ////|     |\\\\\\\  EPC size 93.5 MiB
        vvvvv     vvvvvvvv  vvvvv     vvvvvvvv
12h(2h) 80200001h 00000000h 05d80001h 00000000h

&lt;/code&gt;&lt;/pre&gt;

  &lt;p&gt;&lt;strong&gt;MSR&lt;/strong&gt;&lt;/p&gt;

  &lt;pre&gt;&lt;code&gt;                bit 18 (SGX_ENABLE) is set
                |   bit 0 (LOCK) is set
                v   v
3ah 00000000_00040005h (IA32_FEATURE_CONTROL)
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;I’m currently writing a simple Linux kernel driver to be able to actually use 
SGX. I managed to generate a Page Fault using the &lt;code&gt;ENCLS[EBLOCK]&lt;/code&gt; instruction, 
so at least something seems to be working.&lt;/p&gt;

&lt;p&gt;I really wish Intel would be more forthcoming with information about and 
developer support for SGX. The hardly-announced release and default-disabled 
BIOS setting don’t warrant much hope for the future of SGX.&lt;/p&gt;

&lt;p&gt;In the mean time, I intend to write more blog posts in the near future as I try 
to get SGX up and running. Here’s a cliff hanger for you: the Dell driver 
package mentioned earlier contains a file &lt;code&gt;aesm_service.exe&lt;/code&gt; that contains the 
string “SGX EPID provisioning network failure.” I’ll try to tell you more about 
it next time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update 2015-12-09:&lt;/strong&gt; Please see my 
&lt;a href="https://github.com/jethrogb/sgx-utils"&gt;sgx-utils&lt;/a&gt; repository for any 
open-source SGX utilities, including a bare-bones development Linux driver.&lt;/p&gt;
</content>
    <summary type="html">&lt;p&gt;Without much fanfare, Intel has released &lt;a href="https://software.intel.com/en-us/isa-extensions/intel-sgx"&gt;Software Guard Extensions 
(SGX)&lt;/a&gt; in Skylake. 
When I say &amp;#x201C;without much fanfare,&amp;#x201D; I mean practically only the following 
paragraph hidden on page 3 of a &lt;a href="http://download.intel.com/newsroom/kits/core/6thgen/pdfs/6th_Gen_Intel_Core-Intel_Xeon_Factsheet.pdf"&gt;press fact 
sheet&lt;/a&gt;:&lt;/p&gt;</summary>
  </entry>
  <entry>
    <id>tag:jbeekman.nl,2015-05-20:/blog/2015/05/ssh-logjam/</id>
    <title type="html">On OpenSSH and Logjam – Technology &amp; Policy</title>
    <published>2015-05-20T12:00:00Z</published>
    <updated>2015-05-20T12:00:00Z</updated>
    <link rel="alternate" href="https://jbeekman.nl/blog/2015/05/ssh-logjam/"/>
    <content type="html">&lt;p&gt;&lt;a href="https://weakdh.org/"&gt;Recent work&lt;/a&gt; showing the feasibility of calculating 
discrete logarithms on large integers has put the Diffie-Hellman key exchange 
parameters we use every day in the spotlight. I have looked at what this means
for SSH key exchange. In short, on your &lt;strong&gt;SSH server&lt;/strong&gt;, do the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;awk '{ if ($5 &amp;lt;= 2000) printf "#"; print }' /etc/ssh/moduli &amp;gt; /tmp/large_moduli
mv /tmp/large_moduli /etc/ssh/moduli
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And put the following in your &lt;code&gt;sshd_config&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp256,
              ecdh-sha2-nistp384,ecdh-sha2-nistp521,
              diffie-hellman-group14-sha1,
              diffie-hellman-group-exchange-sha1,
              diffie-hellman-group-exchange-sha256
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that &lt;code&gt;curve25519-sha256@libssh.org&lt;/code&gt; is only supported in &lt;a href="http://www.openssh.com/txt/release-6.5"&gt;OpenSSH 
6.5&lt;/a&gt; and up, and only works reliably in 
&lt;a href="http://www.openssh.com/txt/release-6.7"&gt;OpenSSH 6.7&lt;/a&gt; and up. On your &lt;strong&gt;SSH 
client&lt;/strong&gt;, put the following in your &lt;code&gt;ssh_config&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp256,
              ecdh-sha2-nistp384,ecdh-sha2-nistp521,
              diffie-hellman-group14-sha1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If with this configuration you are unable to connect to some SSH servers, and 
you need to add &lt;code&gt;diffie-hellman-group-exchange-sha1&lt;/code&gt; or 
&lt;code&gt;diffie-hellman-group-exchange-sha256&lt;/code&gt; to the supported list of algorithms, you 
should recompile your SSH client with a &lt;code&gt;DH_GRP_MIN&lt;/code&gt; of 2048, so that a server 
can’t force your client to use a weak group.&lt;/p&gt;

&lt;h3 id="technical-details"&gt;Technical details&lt;/h3&gt;

&lt;p&gt;Now follows a detailed explanation of these recommendations. The following key 
exchange mechanisms are supported in the current version (6.8) of OpenSSH:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;curve25519-sha256@libssh.org&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;ecdh-sha2-nistp256&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;ecdh-sha2-nistp384&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;ecdh-sha2-nistp521&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;diffie-hellman-group1-sha1&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;diffie-hellman-group14-sha1&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;diffie-hellman-group-exchange-sha1&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;diffie-hellman-group-exchange-sha256&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first four mechanisms, &lt;code&gt;curve25519-sha256@libssh.org&lt;/code&gt;, 
&lt;code&gt;ecdh-sha2-nistp256&lt;/code&gt;, &lt;code&gt;ecdh-sha2-nistp384&lt;/code&gt;, &lt;code&gt;ecdh-sha2-nistp521&lt;/code&gt;, do not use 
prime-field Diffie-Hellman and are not affected. &lt;a href="http://nmav.gnutls.org/2011/12/price-to-pay-for-perfect-forward.html"&gt;Previous 
work&lt;/a&gt; 
shows that these mechanisms are much faster when used at the same security 
level, so you should use them!&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;diffie-hellman-group1-sha1&lt;/code&gt; mechanism uses the fixed 1024-bit &lt;a href="https://www.ietf.org/rfc/rfc2409.txt"&gt;Oakley 
Group 2&lt;/a&gt; (not the 768-bit group 1, as the 
name of the mechanism might suggest). This group is within the range of being a 
viable target for nation-state attackers, and should not be used.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;diffie-hellman-group14-sha1&lt;/code&gt; mechanism uses the fixed 2048-bit &lt;a href="https://www.ietf.org/rfc/rfc3526.txt"&gt;Oakley 
Group 14&lt;/a&gt;, which should be secure enough 
for now.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;diffie-hellman-group-exchange-sha1&lt;/code&gt; and 
&lt;code&gt;diffie-hellman-group-exchange-sha256&lt;/code&gt; mechanisms let the client and server 
negotiate a custom DH group. The client sends a tuple «min, n, max» to the 
server, indicating the client’s minimum, preferred and maximum group size. 
&lt;a href="https://www.ietf.org/rfc/rfc4419.txt"&gt;According to the RFC&lt;/a&gt;,&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Servers and clients SHOULD support groups with a modulus length of k
bits, where 1024 &amp;lt;= k &amp;lt;= 8192.  The recommended values for min and
max are 1024 and 8192, respectively.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The OpenSSH server selects a suitable group from a pre-generated set of groups, 
installed system-wide in &lt;code&gt;/etc/ssh/moduli&lt;/code&gt; (falling back to &lt;code&gt;/etc/ssh/primes&lt;/code&gt;), 
using the &lt;code&gt;choose_dh&lt;/code&gt; function in 
&lt;a href="https://github.com/openssh/openssh-portable/blob/master/dh.c"&gt;&lt;code&gt;dh.c&lt;/code&gt;&lt;/a&gt;. In case 
no suitable group is found, the code defaults to Oakley Group 14, which is 
safe. A pre-generated set is &lt;a href="https://github.com/openssh/openssh-portable/blob/master/moduli"&gt;distributed with the OpenSSH 
source&lt;/a&gt; and 
many binary distributions and is infrequently changed. The group sizes 
distributed with OpenSSH are 1024, 1536, 2048, 3072, 4096, 6144, and 8192 bits, 
with about 30 groups per size. The OpenSSH-distributed 1024-bit groups are 
well-known and within the range of being a viable target for nation-state 
attackers, and as such should not be used.&lt;/p&gt;

&lt;p&gt;It is possible to generate your own set of groups, in which case it would be 
safer to use a 1024-bit group, but you might as well go for larger groups. The 
&lt;code&gt;ssh-keygen&lt;/code&gt; man page mentions that “It is important that … both ends of a 
connection share common moduli.” That statement should not be interpreted as 
“both server and client need to have the same moduli configured”, as the server 
sends the chosen modulus to the client. As a case-in-point, the OpenSSH client 
does not access the system-wide moduli file at all during connection setup.&lt;/p&gt;

&lt;p&gt;Speaking about the client, it usually offers the RFC-specified minimum of 1024 
bits. There is nothing preventing a server from using that value and offering a 
well-known (and thus weak) group. So, a standard client shouldn’t use the 
custom group key exchange mechanisms, unless there is a way to change the 
minimum group size.&lt;/p&gt;
</content>
    <summary type="html">&lt;p&gt;&lt;a href="https://weakdh.org/"&gt;Recent work&lt;/a&gt; showing the feasibility of calculating 
discrete logarithms on large integers has put the Diffie-Hellman key exchange 
parameters we use every day in the spotlight. I have looked at what this means
for SSH key exchange. In short, on your &lt;strong&gt;SSH server&lt;/strong&gt;, do the following:&lt;/p&gt;</summary>
  </entry>
  <entry>
    <id>tag:jbeekman.nl,2015-03-08:/blog/2015/03/lenovo-thinkpad-hdd-password/</id>
    <title type="html">Lenovo ThinkPad HDD Password – Technology &amp; Policy</title>
    <published>2015-03-09T00:00:01Z</published>
    <updated>2015-03-09T00:00:01Z</updated>
    <link rel="alternate" href="https://jbeekman.nl/blog/2015/03/lenovo-thinkpad-hdd-password/"/>
    <content type="html">&lt;p&gt;Modern SSDs (at least the ones made by Intel, Samsung) always encrypt all 
stored data using AES. The encryption key used is stored in nonvolatile memory 
on the SSD. One of the reasons for this is that to securely wipe the drive now 
you just need to overwrite the encryption key with a new random one. This way, 
you don’t need to erase every flash block, which is very bad for durability 
reasons. The encryption key can optionally be encrypted using a 32-byte 
“security password”, the configuration of which is overloaded on the ATA 
security feature set. If you trust the hardware manufacturer to actually 
implement this securely, this would seem to provide a very solid and fast 
option for encrypted persistent storage.&lt;/p&gt;

&lt;p&gt;To be able to boot off of such an encrypted drive, it needs to be unlocked 
before the OS’s bootloader can be read, which requires BIOS support. Luckily, 
my Lenovo ThinkPad T420s does support this: you can configure a drive password 
in BIOS the setup screen and from then on the BIOS will ask for a password upon 
startup. Now here’s the catch: it turns out that when you take this drive and 
put it in a different machine, it is impossible to unlock the drive. This would 
mean that if my laptop dies but the drive were still intact &lt;em&gt;I would be unable 
to access the data on the drive, even though I know the password!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A couple of weeks ago I finally decided to get to the bottom of this by reverse 
engineering the Lenovo UEFI BIOS on my laptop. The goal was simple: to find the 
code path from &lt;em&gt;password input&lt;/em&gt; to &lt;em&gt;ATA security unlock output&lt;/em&gt; and reproduce 
it. I have &lt;a href="/blog/2015/03/reverse-engineering-uefi-firmware/"&gt;detailed the reverse engineering process in another blog 
post&lt;/a&gt;. Here’s the 
algorithm:&lt;/p&gt;

&lt;div class="MathJax_Preview"&gt;\textit{AtaPassword} \gets \textrm{SHA}_{256}\left( \textrm{SHA}_{256}(\textit{Password}) \parallel \textit{AtaIdentity}_\textit{SerialNumber} \parallel \textit{AtaIdentity}_\textit{ModelNumber} \right)&lt;/div&gt;
&lt;script type="math/tex; mode=display"&gt;\textit{AtaPassword} \gets \textrm{SHA}_{256}\left( \textrm{SHA}_{256}(\textit{Password}) \parallel \textit{AtaIdentity}_\textit{SerialNumber} \parallel \textit{AtaIdentity}_\textit{ModelNumber} \right)&lt;/script&gt;

&lt;p&gt;The inputs are &lt;span class="MathJax_Preview"&gt;\textit{Password}&lt;/span&gt;&lt;script type="math/tex"&gt;\textit{Password}&lt;/script&gt; which is the user-supplied password and 
&lt;span class="MathJax_Preview"&gt;\textit{AtaIdentity}&lt;/span&gt;&lt;script type="math/tex"&gt;\textit{AtaIdentity}&lt;/script&gt; which is the &lt;a href="https://msdn.microsoft.com/en-us/library/windows/hardware/ff559006%28v=vs.85%29.aspx"&gt;ATA Identify Device data 
structure&lt;/a&gt;. 
The output &lt;span class="MathJax_Preview"&gt;\textit{AtaPassword}&lt;/span&gt;&lt;script type="math/tex"&gt;\textit{AtaPassword}&lt;/script&gt; gets sent to the drive. Why do they use 
this algorithm? It’s actually somewhat clever: the S/N and M/N act as a salt, 
such that a hash sniffed off of the ATA bus will only be able to unlock that 
one drive, and not any other drives that use the same password.&lt;/p&gt;

&lt;p&gt;That’s the good part. The bad part is that the algorithm above is not quite 
complete. Here is the &lt;em&gt;actual&lt;/em&gt; algorithm:&lt;/p&gt;

&lt;div class="MathJax_Preview"&gt;\textit{PasswordHash} \gets \textrm{SHA}_{256}\left( \left( \textrm{ToScanCodes}(\textrm{LowerCase}(\textit{Password})) \parallel ␀^{64} \right)_{1:64} \right)_{1:12}&lt;/div&gt;
&lt;script type="math/tex; mode=display"&gt;\textit{PasswordHash} \gets \textrm{SHA}_{256}\left( \left( \textrm{ToScanCodes}(\textrm{LowerCase}(\textit{Password})) \parallel ␀^{64} \right)_{1:64} \right)_{1:12}&lt;/script&gt;

&lt;div class="MathJax_Preview"&gt;\textit{SN} \gets \textit{AtaIdentity}_\textit{SerialNumber} \qquad \textit{MN} \gets \textit{AtaIdentity}_\textit{ModelNumber}&lt;/div&gt;
&lt;script type="math/tex; mode=display"&gt;\textit{SN} \gets \textit{AtaIdentity}_\textit{SerialNumber} \qquad \textit{MN} \gets \textit{AtaIdentity}_\textit{ModelNumber}&lt;/script&gt;

&lt;div class="MathJax_Preview"&gt;\textit{AtaPassword} \gets \textrm{SHA}_{256}\left( \textit{PasswordHash} \parallel \textrm{SwapBytes}(\textit{SN}) \parallel \textrm{SwapBytes}(\textit{MN}) \right)&lt;/div&gt;
&lt;script type="math/tex; mode=display"&gt;\textit{AtaPassword} \gets \textrm{SHA}_{256}\left( \textit{PasswordHash} \parallel \textrm{SwapBytes}(\textit{SN}) \parallel \textrm{SwapBytes}(\textit{MN}) \right)&lt;/script&gt;

&lt;p&gt;The function &lt;span class="MathJax_Preview"&gt;\textrm{ToScanCodes}&lt;/span&gt;&lt;script type="math/tex"&gt;\textrm{ToScanCodes}&lt;/script&gt; translates the characters 
&lt;code&gt;1234567890qwertyuiopasdfghjkl;zxcvbnm␣&lt;/code&gt; to integers in the ranges 2–11, 16–25, 
30–39, 44–50, 57–57, respectively, while dropping other characters. 
&lt;span class="MathJax_Preview"&gt;\textrm{SHA}_{256}&lt;/span&gt;&lt;script type="math/tex"&gt;\textrm{SHA}_{256}&lt;/script&gt; is the well-known hash function. &lt;span class="MathJax_Preview"&gt;\textrm{SwapBytes}&lt;/span&gt;&lt;script type="math/tex"&gt;\textrm{SwapBytes}&lt;/script&gt; 
is the POSIX &lt;code&gt;swab&lt;/code&gt; function, it swaps odd and even bytes.&lt;/p&gt;

&lt;p&gt;There are a couple of peculiarities in the algorithm that reduce the security. 
First of all, I’m not sure why the characters get converted into scancodes. The 
UEFI BIOS is well-equiped to deal with keyboard layouts, so that just seems 
unnecessary. It also reduces the entropy to only 5.3 bits per character, making 
short passwords very insecure. What’s worse though, is that only 12 bytes of 
the password hash are used, putting an upper bound of 96 bits on the entropy. 
If your password is sampled uniformly at random from the available scancodes, 
don’t bother making it longer than 18 characters.&lt;/p&gt;

&lt;p&gt;The other weird thing is the &lt;span class="MathJax_Preview"&gt;\textrm{SwapBytes}&lt;/span&gt;&lt;script type="math/tex"&gt;\textrm{SwapBytes}&lt;/script&gt; function. This means that 
if your model number is 
&lt;code style="word-break:break-all"&gt;Samsung␣SSD␣840␣EVO␣500GB␣…&lt;/code&gt;, that part of the 
input to the hash function will be 
&lt;code style="word-break:break-all"&gt;aSsmnu␣gSS␣D48␣0VE␣O05G0␣B…&lt;/code&gt;. Why is that? 
Between the ATA Identify Device data structure being defined in terms of 16-bit 
words and the UEFI specification using 16-bit wide characters, while the model 
and serial number are encoded as 8-bit ASCII, I can only assume that someone 
messed up some endianness conversion somewhere.&lt;/p&gt;

&lt;p&gt;Today, am I &lt;a href="https://github.com/jethrogb/lenovo-password"&gt;releasing a tool to unlock your 
drive&lt;/a&gt;. If despite all the 
above—96 bits is more entropy than most passwords have—you still decide to use 
the Lenovo BIOS to do your password management, you can use this to unlock your 
drive in the event of hardware failure. You will need &lt;code&gt;hdparm&lt;/code&gt; to talk to your 
drive. If the password hash contains a ␀ character, you’ll need to patch 
&lt;code&gt;hdparm&lt;/code&gt; to be able to use that. I tested this on my own setup, but you may 
want to verify it actually works before you start depending on it.&lt;/p&gt;
</content>
    <summary type="html">&lt;p&gt;Modern SSDs (at least the ones made by Intel, Samsung) always encrypt all 
stored data using AES. The encryption key used is stored in nonvolatile memory 
on the SSD. One of the reasons for this is that to securely wipe the drive now 
you just need to overwrite the encryption key with a new random one. This way, 
you don&amp;#x2019;t need to erase every flash block, which is very bad for durability 
reasons. The encryption key can optionally be encrypted using a 32-byte 
&amp;#x201C;security password&amp;#x201D;, the configuration of which is overloaded on the ATA 
security feature set. If you trust the hardware manufacturer to actually 
implement this securely, this would seem to provide a very solid and fast 
option for encrypted persistent storage.&lt;/p&gt;</summary>
  </entry>
  <entry>
    <id>tag:jbeekman.nl,2015-03-08:/blog/2015/03/reverse-engineering-uefi-firmware/</id>
    <title type="html">Reverse Engineering UEFI Firmware – Technology &amp; Policy</title>
    <published>2015-03-09T00:00:00Z</published>
    <updated>2015-03-09T00:00:00Z</updated>
    <link rel="alternate" href="https://jbeekman.nl/blog/2015/03/reverse-engineering-uefi-firmware/"/>
    <content type="html">&lt;p&gt;In order to &lt;a href="/blog/2015/03/lenovo-thinkpad-hdd-password/"&gt;figure out how my BIOS drive password 
worked,&lt;/a&gt; I had to 
reverse-engineer the firmware that comes with my laptop. You can find the 
binary blobs on the update CD that Lenovo provides, and it turns out these 
blobs are actually UEFI images. UEFI firmware is made up of many different 
loadable modules (drivers, shared libraries, etc.), which are stored in the 
Portable Executable (PE) image format. These modules can be extracted from the 
image using Nikolaj Schlej’s excellent UEFIExtract (from 
&lt;a href="https://github.com/LongSoft/UEFITool"&gt;UEFITool&lt;/a&gt;). Once you have all the PE 
modules, the real reversing can begin.&lt;/p&gt;

&lt;p&gt;It helps to understand how UEFI works. The Internet contains a wealth of 
information, and here are two articles to get you started: &lt;a href="http://mjg59.dreamwidth.org/18773.html"&gt;Getting started 
with UEFI development&lt;/a&gt; and &lt;a href="http://x86asm.net/articles/uefi-programming-first-steps/"&gt;UEFI 
Programming - First 
Steps&lt;/a&gt;. The main 
problem that makes reverse engineering hard is that while the firmware consists 
of over 300 loadable modules, there is no dynamic linker. Instead, the entry 
point of a module gets passed an pointer to a “protocol” registry. A protocol 
is basically an interface, or in other words a struct of function pointers. The 
registry is keyed by Globally unique identifiers (GUIDs). To call into another 
module, you need to lookup a GUID in the registry and then call some function 
returned in the interface.&lt;/p&gt;

&lt;p&gt;My first strategy to get some insight into the firmware was to collect GUIDs 
from images and build a dependency graph. This turned out to be useless. The 
UEFI image contains &lt;em&gt;PEI dependency sections&lt;/em&gt; for each image, but the GUIDs 
that are listed seem to have no relation to actually required protocols. 
Furthermore, identifying GUIDs (also known as 16 random bytes) in binaries is 
hard, and even when I manged to identify a section that seemed to store GUIDs, 
there would be many GUIDs in such a section that were never referenced from 
code in that image.&lt;/p&gt;

&lt;p&gt;To figure out the dependencies, I decided to actually run the modules and see 
which protocols they lookup and which ones they register. &lt;em&gt;Wait what, run UEFI 
PE modules?&lt;/em&gt; Yes, &lt;a href="https://github.com/jethrogb/uefireverse/tree/master/efiperun"&gt;I wrote a tool called 
&lt;code&gt;efiperun&lt;/code&gt;&lt;/a&gt; that 
can load PE modules into memory and simulate enough of what an UEFI environment 
is supposed to look like to actually run them. Most modules will upon entry 
lookup some standard protocols, do some initialization, and register one or 
more protocols that other modules can use.&lt;/p&gt;

&lt;p&gt;With this information in hand, you can do more targeted reversing, trying to 
identify interfaces and function signatures. For example, 
&lt;code&gt;LenovoTranslateService.efi&lt;/code&gt; installs a protocol 
&lt;code&gt;e3abb023-b8b1-4696-98e1-8eedc3d3c63d&lt;/code&gt;. This protocol turns out to have the 
following interface:&lt;/p&gt;

&lt;div class="language-c highlighter-coderay"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span style="color:#080;font-weight:bold"&gt;struct&lt;/span&gt; interface_e3abb023_b8b1_4696_98e1_8eedc3d3c63d
{
    &lt;span style="color:#088;font-weight:bold"&gt;void&lt;/span&gt;(EFIAPI *translate)(&lt;span style="color:#088;font-weight:bold"&gt;void&lt;/span&gt;* _this, &lt;span style="color:#088;font-weight:bold"&gt;const&lt;/span&gt; &lt;span style="color:#0a8;font-weight:bold"&gt;char&lt;/span&gt;* input, &lt;span style="color:#0a8;font-weight:bold"&gt;char&lt;/span&gt;* output, size_t length);
}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;With &lt;code&gt;efiperun&lt;/code&gt; you can actually write code that calls into loaded EFI modules, 
which makes it easy to test installed interfaces. Utilizing this functionality, 
I was able to determine that the &lt;code&gt;translate&lt;/code&gt; function above actually translates 
an ASCII string to keyboard scan codes.&lt;/p&gt;

&lt;p&gt;When doing reverse engineering, you always end up exploring branches that turn 
out to be less fruitful. But the knowledge obtained exploring such a branch can 
be useful in exploring other ideas. Now that I’ve setup the stage with the 
tools I’m going to use, I will describe the path that lead to the discovery of 
the algorithm. Keep in mind that this is a reconstruction and the order in 
which I actually figured parts out is different.&lt;/p&gt;

&lt;h4 id="graphical-entry-point"&gt;Graphical entry point&lt;/h4&gt;

&lt;p&gt;&lt;img src="/img/blog/reverse-engineering-uefi-firmware/hdp-prompt.png" alt="Lenovo HDP Prompt" align="right" /&gt;&lt;/p&gt;

&lt;p&gt;The Lenovo firmware does not make heavy use of graphical elements, but the Hard 
Drive Password prompt actually does display a small pictogram, pictured on the
right. Now, judging by the filenames, there are only a few modules that deal with graphics:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;SystemGraphicsConsoleDxe.efi&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;SystemHiiImageDisplayDxe.efi&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;SystemImageDecoderDxe.efi&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;SystemImageDisplayDxe.efi&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All these modules install a single protocol that don’t use a &lt;a href="https://github.com/jethrogb/uefireverse/blob/master/guiddb/efi_guid.c"&gt;well-known 
GUID&lt;/a&gt;, 
so let’s see what modules call them. As it turns out, only 
&lt;code&gt;SystemSplashDxe.efi&lt;/code&gt; calls &lt;code&gt;SystemHiiImageDisplayDxe.efi&lt;/code&gt; 
(96ce4c12-55e4-4a1c-bbf3-73a5055fb364) and only &lt;code&gt;LenovoPromptService.efi&lt;/code&gt; calls 
&lt;code&gt;SystemImageDisplayDxe.efi&lt;/code&gt; (71583a77-2789-4213-a83b-eef42afe85e0). 
&lt;code&gt;SystemSplashDxe.efi&lt;/code&gt; pretty much seems to be as advertised and even contains a 
GIF file with the ThinkPad splash image. Upon further inspection, 
&lt;code&gt;LenovoPromptService.efi&lt;/code&gt; contains 21 BMP files, all related to displaying 
password prompts. Bingo!&lt;/p&gt;

&lt;h4 id="password-control-program"&gt;Password control program&lt;/h4&gt;

&lt;p&gt;The Prompt service installs a single protocol 
56350810-2cb2-4aa0-96d2-66d1b8e1aac2 which is only called by 
&lt;code&gt;LenovoPasswordCp.efi&lt;/code&gt;. This module contains key code connecting various 
password-related modules, and I’ll assume Cp means “control progam”. Besides 
the prompt service (for text input), it also calls into 
&lt;code&gt;LenovoSoundService.efi&lt;/code&gt; (e01fc710-ba41-493b-a919-53583368f6d9, for beeping 
noises when you press an invalid key), &lt;code&gt;LenovoTranslateService.efi&lt;/code&gt; (described 
above) and &lt;code&gt;LenovoCryptService.efi&lt;/code&gt; (73e47354-b0c5-4e00-a714-9d0d5a4fdbfd, 
supposedly a crypto module—see next section).&lt;/p&gt;

&lt;p&gt;The password control program has an interesting function at offset &lt;code&gt;0x8cc&lt;/code&gt; that 
calls only &lt;code&gt;SetMem&lt;/code&gt;, &lt;code&gt;CopyMem&lt;/code&gt; and the Crypto and Translate services. Here’s 
roughly the code for this function:&lt;/p&gt;

&lt;div class="language-c highlighter-coderay"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span style="color:#088;font-weight:bold"&gt;void&lt;/span&gt; _0x8cc(&lt;span style="color:#088;font-weight:bold"&gt;const&lt;/span&gt; CHAR16 in[&lt;span style="color:#00D"&gt;64&lt;/span&gt;], UINT8 out[&lt;span style="color:#00D"&gt;16&lt;/span&gt;])
{
    UINT8 ascii[&lt;span style="color:#00D"&gt;64&lt;/span&gt;], scancode[&lt;span style="color:#00D"&gt;64&lt;/span&gt;], hash[&lt;span style="color:#00D"&gt;32&lt;/span&gt;];
    BootServices-&amp;gt;SetMem(out,&lt;span style="color:#00D"&gt;16&lt;/span&gt;,&lt;span style="color:#00D"&gt;0&lt;/span&gt;);
    BootServices-&amp;gt;SetMem(ascii,&lt;span style="color:#00D"&gt;64&lt;/span&gt;,&lt;span style="color:#00D"&gt;0&lt;/span&gt;);
    BootServices-&amp;gt;SetMem(scancode,&lt;span style="color:#00D"&gt;64&lt;/span&gt;,&lt;span style="color:#00D"&gt;0&lt;/span&gt;);
    BootServices-&amp;gt;SetMem(hash,&lt;span style="color:#00D"&gt;32&lt;/span&gt;,&lt;span style="color:#00D"&gt;0&lt;/span&gt;);
    &lt;span style="color:#080;font-weight:bold"&gt;for&lt;/span&gt; (&lt;span style="color:#0a8;font-weight:bold"&gt;int&lt;/span&gt; i=&lt;span style="color:#00D"&gt;0&lt;/span&gt;;i&amp;lt;&lt;span style="color:#00D"&gt;64&lt;/span&gt;;i++)
    {
        ascii[i]=in[i];
    }
    &lt;span style="color:#080;font-weight:bold"&gt;if&lt;/span&gt; (TranslateService)
    {
        TranslateService-&amp;gt;Translate(TranslateService,ascii,scancode,&lt;span style="color:#00D"&gt;64&lt;/span&gt;);
        &lt;span style="color:#080;font-weight:bold"&gt;if&lt;/span&gt; (CryptService)
        {
            CryptService-&amp;gt;SHA256(CryptService,scancode,&lt;span style="color:#00D"&gt;64&lt;/span&gt;,hash);
            BootServices-&amp;gt;CopyMem(out,hash,&lt;span style="color:#00D"&gt;16&lt;/span&gt;);
        }
        BootServices-&amp;gt;SetMem(ascii,&lt;span style="color:#00D"&gt;64&lt;/span&gt;,&lt;span style="color:#00D"&gt;0&lt;/span&gt;);
        BootServices-&amp;gt;SetMem(scancode,&lt;span style="color:#00D"&gt;64&lt;/span&gt;,&lt;span style="color:#00D"&gt;0&lt;/span&gt;);
        BootServices-&amp;gt;SetMem(hash,&lt;span style="color:#00D"&gt;32&lt;/span&gt;,&lt;span style="color:#00D"&gt;0&lt;/span&gt;);
    }
    &lt;span style="color:#080;font-weight:bold"&gt;else&lt;/span&gt;
    {
        BootServices-&amp;gt;SetMem(ascii,&lt;span style="color:#00D"&gt;64&lt;/span&gt;,&lt;span style="color:#00D"&gt;0&lt;/span&gt;);
    }
}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;I’ll assume that this function is used to hash a password input by the user. 
There’s another interesting function at offset &lt;code&gt;0xa30&lt;/code&gt;, which checks whether the 
input &lt;code&gt;CHAR16&lt;/code&gt; is in the character class &lt;code&gt;[0-9A-Za-z ;]&lt;/code&gt;, which is used to limit 
the possible characters in the password input.&lt;/p&gt;

&lt;p&gt;I’ve made good progress identifying part of the path from password input to 
security unlock command, but here I’ve hit a dead end. It’s not really clear 
from where the password control program gets called and what happens to the 
hash it outputs. I’ll try a different approach next, but first let’s talk about 
the crypto service.&lt;/p&gt;

&lt;h4 id="crypto-service"&gt;Crypto service&lt;/h4&gt;

&lt;p&gt;The password control program calls a function in the Crypto service at offset 
&lt;code&gt;0x26e0&lt;/code&gt;, which references three GUIDs that I hadn’t seen before:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;69188a5f-6bbd-46c7-9c16-55f194befcdf&lt;/li&gt;
  &lt;li&gt;d0b3d668-16cf-4feb-95f5-1ca3693cfe56&lt;/li&gt;
  &lt;li&gt;6c48f74a-b4df-461f-80c4-5cae8a85b7ee&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These GUIDs do not appear in any &lt;code&gt;efiperun&lt;/code&gt; output. Instead, I just searched 
all images for appearances of these GUIDs, and they appear in 10 other images. 
A noteworthy appearance is in &lt;code&gt;SystemCryptSvcRt.efi&lt;/code&gt; at offset &lt;code&gt;0x1c70&lt;/code&gt;. Offset 
&lt;code&gt;0x1c70&lt;/code&gt; is referenced at offset &lt;code&gt;0x330&lt;/code&gt;, where it is immediately followed by 
the unicode string “SHA256”. This is followed by a jump table at offset 
&lt;code&gt;0x370&lt;/code&gt;, which points to 3 jumps at offset &lt;code&gt;0x33c0&lt;/code&gt; that jump to 3 functions at 
offsets &lt;code&gt;0x753c&lt;/code&gt;, &lt;code&gt;0x7570&lt;/code&gt; and &lt;code&gt;0x760c&lt;/code&gt;. The function at offset &lt;code&gt;0x753c&lt;/code&gt; 
references offset &lt;code&gt;0x2258&lt;/code&gt;, &lt;em&gt;which stores the &lt;a href="https://en.wikipedia.org/wiki/SHA-2#Pseudocode"&gt;hash initialization constants 
for SHA256&lt;/a&gt;&lt;/em&gt;! The rest of the 
&lt;code&gt;SystemCryptSvcRt.efi&lt;/code&gt; module also contains SHA256 round constants, and similar 
strings and constants for other algorithms.&lt;/p&gt;

&lt;p&gt;All in all this suggests that the Crypto service is a front for the 
cryptographic routines in &lt;code&gt;SystemCryptSvcRt.efi&lt;/code&gt; and that the password control 
program calls SHA256. I wrote a small test program for the &lt;a href="http://tianocore.sourceforge.net/wiki/Efi-shell"&gt;EFI shell&lt;/a&gt; that 
tests this:&lt;/p&gt;

&lt;div class="language-c highlighter-coderay"&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;&lt;span style="color:#088;font-weight:bold"&gt;void&lt;/span&gt; buf2hexstr(VOID*buf,CHAR16*str,UINTN len)
{
    UINTN i;
    &lt;span style="color:#088;font-weight:bold"&gt;static&lt;/span&gt; CHAR16 hchars[&lt;span style="color:#00D"&gt;16&lt;/span&gt;]={&lt;span style="color:#D20"&gt;'0'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'1'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'2'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'3'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'4'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'5'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'6'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'7'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'8'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'9'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'a'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'b'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'c'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'d'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'e'&lt;/span&gt;,&lt;span style="color:#D20"&gt;'f'&lt;/span&gt;};
    UINT8* buf_=(UINT8*)buf;
    &lt;span style="color:#080;font-weight:bold"&gt;for&lt;/span&gt; (i=&lt;span style="color:#00D"&gt;0&lt;/span&gt;;i&amp;lt;len;i++)
    {
        *(str++)=hchars[*(buf_)  &amp;gt;&amp;gt;&lt;span style="color:#00D"&gt;4&lt;/span&gt;];
        *(str++)=hchars[*(buf_++)&amp;amp;&lt;span style="color:#02b"&gt;0xf&lt;/span&gt;];
    }
}

EFI_STATUS Initialize(...)
{
    ...
    EFI_GUID guid={&lt;span style="color:#02b"&gt;0x73e47354&lt;/span&gt;,&lt;span style="color:#02b"&gt;0xb0c5&lt;/span&gt;,&lt;span style="color:#02b"&gt;0x4e00&lt;/span&gt;,{&lt;span style="color:#02b"&gt;0xa7&lt;/span&gt;,&lt;span style="color:#02b"&gt;0x14&lt;/span&gt;,&lt;span style="color:#02b"&gt;0x9d&lt;/span&gt;,&lt;span style="color:#02b"&gt;0x0d&lt;/span&gt;,&lt;span style="color:#02b"&gt;0x5a&lt;/span&gt;,&lt;span style="color:#02b"&gt;0x4f&lt;/span&gt;,&lt;span style="color:#02b"&gt;0xdb&lt;/span&gt;,&lt;span style="color:#02b"&gt;0xfd&lt;/span&gt;}};
    &lt;span style="color:#088;font-weight:bold"&gt;void&lt;/span&gt;* intf;

    &lt;span style="color:#080;font-weight:bold"&gt;if&lt;/span&gt; (SystemTable-&amp;gt;BootServices-&amp;gt;LocateProtocol(&amp;amp;guid,&lt;span style="color:#069"&gt;NULL&lt;/span&gt;,&amp;amp;intf)==EFI_SUCCESS)
    {
        &lt;span style="color:#088;font-weight:bold"&gt;const&lt;/span&gt; &lt;span style="color:#0a8;font-weight:bold"&gt;char&lt;/span&gt;* in=&lt;span style="background-color:hsla(0,100%,50%,0.05)"&gt;&lt;span style="color:#710"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#D20"&gt;TEST&lt;/span&gt;&lt;span style="color:#710"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;
        &lt;span style="color:#0a8;font-weight:bold"&gt;char&lt;/span&gt; out[&lt;span style="color:#00D"&gt;32&lt;/span&gt;]={};
        CHAR16 str[&lt;span style="color:#00D"&gt;13&lt;/span&gt;+(&lt;span style="color:#00D"&gt;32&lt;/span&gt;*&lt;span style="color:#00D"&gt;2&lt;/span&gt;)+&lt;span style="color:#00D"&gt;2&lt;/span&gt;]=L&lt;span style="background-color:hsla(0,100%,50%,0.05)"&gt;&lt;span style="color:#710"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#D20"&gt;SHA256 test: &lt;/span&gt;&lt;span style="color:#710"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;;
        ((&lt;span style="color:#088;font-weight:bold"&gt;void&lt;/span&gt;(*)(&lt;span style="color:#088;font-weight:bold"&gt;void&lt;/span&gt;*,&lt;span style="color:#088;font-weight:bold"&gt;const&lt;/span&gt; &lt;span style="color:#0a8;font-weight:bold"&gt;char&lt;/span&gt;*,UINTN,&lt;span style="color:#0a8;font-weight:bold"&gt;char&lt;/span&gt;*))(*(&lt;span style="color:#088;font-weight:bold"&gt;void&lt;/span&gt;**)intf))(intf,in,&lt;span style="color:#00D"&gt;4&lt;/span&gt;,out);
        buf2hexstr(out,str+&lt;span style="color:#00D"&gt;13&lt;/span&gt;,&lt;span style="color:#00D"&gt;32&lt;/span&gt;);
        str[&lt;span style="color:#00D"&gt;13&lt;/span&gt;+(&lt;span style="color:#00D"&gt;32&lt;/span&gt;*&lt;span style="color:#00D"&gt;2&lt;/span&gt;)]=&lt;span style="color:#D20"&gt;'\n'&lt;/span&gt;;
        SystemTable-&amp;gt;ConOut-&amp;gt;OutputString(SystemTable-&amp;gt;ConOut, str);
        SystemTable-&amp;gt;ConOut-&amp;gt;OutputString(SystemTable-&amp;gt;ConOut,
            L&lt;span style="background-color:hsla(0,100%,50%,0.05)"&gt;&lt;span style="color:#710"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#D20"&gt;Expected:    94ee059335e587e501cc4bf90613e0814f00a7b08bc7c648fd865a2af6a22cc2&lt;/span&gt;&lt;span style="color:#b0b"&gt;\n&lt;/span&gt;&lt;span style="color:#710"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
    }
    &lt;span style="color:#080;font-weight:bold"&gt;else&lt;/span&gt;
    {
        SystemTable-&amp;gt;ConOut-&amp;gt;OutputString(SystemTable-&amp;gt;ConOut,
            L&lt;span style="background-color:hsla(0,100%,50%,0.05)"&gt;&lt;span style="color:#710"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#D20"&gt;Unable to load CryptService protocol&lt;/span&gt;&lt;span style="color:#b0b"&gt;\n&lt;/span&gt;&lt;span style="color:#710"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;);
    }
    ...
}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Outputs:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;SHA256 test: 94ee059335e587e501cc4bf90613e0814f00a7b08bc7c648fd865a2af6a22cc2
Expected:    94ee059335e587e501cc4bf90613e0814f00a7b08bc7c648fd865a2af6a22cc2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Success!&lt;/p&gt;

&lt;h4 id="hard-drive-communication"&gt;Hard-drive communication&lt;/h4&gt;

&lt;p&gt;As mentioned, I discovered how the input password got hashed, but it still 
needs to be sent to the drive. The UEFI standard defines the &lt;em&gt;ATA Pass Thru 
Protocol&lt;/em&gt;, which can be used to send raw ATA commands to a drive. This protocol 
is very likely to be used for sending ATA security commands. This protocol is 
not loaded upon initialization by any modules, but the GUID does appear in the 
following modules:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;FdiskOem.efi&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;LenovoHdpManagerDxe.efi&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;LenovoMfgBenchEventDxe.efi&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;SystemAhciAtaAtapiPassThruDxe.efi&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;SystemAhciBusDxe.efi&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;SystemAhciBusSmm.efi&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;SystemIdeAtaPassThruDxe.efi&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;SystemIdeBusDxe.efi&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wait a minute, is that second module called &lt;em&gt;Lenovo Hard Drive Password 
Manager&lt;/em&gt;? Why yes, it is. There’s a bunch of code in this module, but I found
an interesting function call chain for you:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;offset &lt;code&gt;0xce0&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;offset &lt;code&gt;0x8a0&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;CryptService.SHA256&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;offset &lt;code&gt;0x144c&lt;/code&gt;
        &lt;ul&gt;
          &lt;li&gt;offset &lt;code&gt;0x232c&lt;/code&gt;
            &lt;ul&gt;
              &lt;li&gt;EFI_ATA_PASS_THRU_PROTOCOL.PassThru&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The input to the SHA256 function is a parameter to the function at offset 
&lt;code&gt;0xce0&lt;/code&gt;, and data from an EFI runtime variable “LenovoHddSecInfoVar”. The 
PassThru function is called with a ATA_OP_SECURITY_UNLOCK command block 
including the hash generated just before. I assume the input to the function at 
offset &lt;code&gt;0xce0&lt;/code&gt; is the password hash from the password control program, but what 
is the data in “LenovoHddSecInfoVar”? The &lt;code&gt;dmpstore&lt;/code&gt; utility in the &lt;a href="http://tianocore.sourceforge.net/wiki/Efi-shell"&gt;EFI shell&lt;/a&gt; 
that will dump runtime variables. Here’s mine:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Variable BS '2D8FBE63-3A04-4EF8-A8A4-77321DB5A9AB:LenovoHddSecInfoVar' DataSize = 8
  00000000: 98 7D BC B7 00 00 00 00-                         *........*
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;From the code I know that the value is being used as a memory address, so let’s 
use the &lt;code&gt;mem&lt;/code&gt; utility to dump that:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  B7BC7D98: .. .. .. .. .. .. .. ..-18 E0 0F B8 00 00 00 00           ........*
  B7BC7DA8: 98 DF 0F B8 00 00 00 00-.. .. .. .. .. .. .. ..  *........
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Those are two more memory addresses, let’s see what’s there:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  B80FDF98: 61 53 73 6D 6E 75 20 67-53 53 20 44 34 38 20 30  *aSsmnu gSS D48 0*
  B80FDFA8: 56 45 20 4F 30 35 47 30-20 42 20 20 20 20 20 20  *VE O05G0 B      *
  B80FDFB8: 20 20 20 20 20 20 20 20-.. .. .. .. .. .. .. ..  *        

  B80FE018: 31 53 48 44 53 4E 46 41-30 42 38 35 39 34 20 45  *1SHDSNFA0B8594 E*
  B80FE028: 20 20 20 20 .. .. .. ..-.. .. .. .. .. .. .. ..  *    
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you squint your eyes just right, those kind of read &lt;code&gt;Samsung SSD 840 EVO 
500GB&lt;/code&gt; and &lt;code&gt;S1DHNSAFB05849E&lt;/code&gt;, the Model Number and Serial Number for my SSD, 
respectively. Piecing all this together, you get the algorithm described in &lt;a href="/blog/2015/03/lenovo-thinkpad-hdd-password/"&gt;my 
other blog post&lt;/a&gt;.&lt;/p&gt;

&lt;h4 id="conclusion"&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;As I mentioned, this story is the abridged version of how I found the password 
hashing algorithm. In reality, I looked at many other modules, including many 
hours spent looking at useless things. In the end though, I prevailed and found 
what I was looking for, developing &lt;a href="https://github.com/jethrogb/uefireverse"&gt;a bunch of 
tools&lt;/a&gt; in the process:&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;efiperun:&lt;/dt&gt;
  &lt;dd&gt;Load and run EFI PE image files in a regular OS environment.&lt;/dd&gt;
  &lt;dt&gt;guiddb:&lt;/dt&gt;
  &lt;dd&gt;Scan files for GUIDs and output them in C-source file format.&lt;/dd&gt;
  &lt;dt&gt;memdmp:&lt;/dt&gt;
  &lt;dd&gt;Dump UEFI memory using &lt;a href="http://tianocore.sourceforge.net/wiki/Efi-shell"&gt;EFI shell&lt;/a&gt;.&lt;/dd&gt;
  &lt;dt&gt;tree:&lt;/dt&gt;
  &lt;dd&gt;A Ruby abstraction for a firmware tree on your filesystem previously 
extracted by &lt;a href="https://github.com/LongSoft/UEFITool"&gt;UEFIExtract&lt;/a&gt;.&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;I hope these tools are of use to anyone. Patches welcome. ☺️&lt;/p&gt;

</content>
    <summary type="html">&lt;p&gt;In order to &lt;a href="/blog/2015/03/lenovo-thinkpad-hdd-password/"&gt;figure out how my BIOS drive password 
worked,&lt;/a&gt; I had to 
reverse-engineer the firmware that comes with my laptop. You can find the 
binary blobs on the update CD that Lenovo provides, and it turns out these 
blobs are actually UEFI images. UEFI firmware is made up of many different 
loadable modules (drivers, shared libraries, etc.), which are stored in the 
Portable Executable (PE) image format. These modules can be extracted from the 
image using Nikolaj Schlej&amp;#x2019;s excellent UEFIExtract (from 
&lt;a href="https://github.com/LongSoft/UEFITool"&gt;UEFITool&lt;/a&gt;). Once you have all the PE 
modules, the real reversing can begin.&lt;/p&gt;</summary>
  </entry>
  <entry>
    <id>tag:jbeekman.nl,2015-01-28:/blog/2015/01/nibble-sort/</id>
    <title type="html">Parallel Nibble Sort – Technology &amp; Policy</title>
    <published>2015-01-28T12:00:00Z</published>
    <updated>2015-07-20T12:00:00Z</updated>
    <link rel="alternate" href="https://jbeekman.nl/blog/2015/01/nibble-sort/"/>
    <content type="html">&lt;p&gt;&lt;em&gt;Update July 20, 2015: The winning solution by Alexander Monakov also uses a 
sorting network but transposes the items to be sorted to sort 32 nibbles in 
parallel with a length 60 network, instead of my 4 nibbles with a depth 9 
network. &lt;a href="http://www.hanshq.net/nibble_sort.html#winning-simd"&gt;Hans Wennborg&lt;/a&gt; 
has a nice write-up of that solution.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Professor John Regehr at University of Utah held a small &lt;a href="http://blog.regehr.org/archives/1213"&gt;programming contest 
for “nibble sort”&lt;/a&gt;. The goal is to sort 
nibbles in a 64-bit value, 1024 times, as fast as possible. For example, the 
nibble sort of &lt;code&gt;0xbadbeef&lt;/code&gt; is &lt;code&gt;0xfeedbba000000000&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id="algorithm"&gt;Algorithm&lt;/h3&gt;
&lt;p&gt;I chose to implement the sort using a &lt;a href="https://en.wikipedia.org/wiki/Sorting_network"&gt;sorting 
network&lt;/a&gt;. I used the following 
minimum-depth network to sort 16 items, which was designed by David C. Van 
Voorhis.&lt;/p&gt;

&lt;div style="text-align:center"&gt;
&lt;img src="/img/nibble-sort.png" /&gt;
&lt;p&gt;Figure 1. From &lt;i&gt;“The Art of Computer Programming, Volume 3”.&lt;/i&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;The inputs are distributed in rows on the left, and each vertical line segment 
compares the two numbers on the parallel lines, swapping them if the upper 
element is less than the lower element.&lt;/p&gt;

&lt;h3 id="parallelization"&gt;Parallelization&lt;/h3&gt;
&lt;p&gt;For each of the 9 stages, the elements to be sorted are split into two buckets, 
and the same indices in each bucket are compared and potentially swapped at the 
same time using SIMD instructions. The split for each stage is a different 
permutation depending on which elements are to be compared. This process was 
inspired by the paper &lt;em&gt;“Efficient implementation of sorting on multi-core SIMD 
CPU architecture”&lt;/em&gt;. After each stage, the buckets are then again combined into 
a single list using the inverse permutation. The permutations of combining the 
buckets from the last stage and splitting them again for the next stage can be 
reduced to a single permutation.&lt;/p&gt;

&lt;div style="text-align:center"&gt;
&lt;pre style="text-align:left;display:inline-block"&gt;
&lt;b&gt;function&lt;/b&gt; sort(input):
    b1:b2 &amp;lt;- input
    &lt;b&gt;for&lt;/b&gt; i := 1 &lt;b&gt;to&lt;/b&gt; 9:
        b1:b2 &amp;lt;- each_min(b1,b2):each_max(b1,b2)
        b1:b2 &amp;lt;- permute(step=i,b1:b2)
    &lt;b&gt;return&lt;/b&gt; b1:b2
&lt;/pre&gt;
&lt;p&gt;Algorithm 1. Parallel network sort.&lt;/p&gt;
&lt;/div&gt;

&lt;h3 id="implementation"&gt;Implementation&lt;/h3&gt;
&lt;p&gt;On IA-32, the smallest unit that can be processed is a byte. Every 2 of the 16 
nibbles in the input word are unpacked into the lower nibble of 2 bytes for a 
total of 16 bytes to be sorted, and each bucket is 8 bytes. AVX2 can process 32 
bytes or 4 buckets in parallel. &lt;a href="https://github.com/regehr/nibble-sort/blob/master/beekman2.c"&gt;This 
implementation&lt;/a&gt; 
runs more than 72× faster than the &lt;a href="https://github.com/regehr/nibble-sort/blob/master/ref.c"&gt;reference 
implementation&lt;/a&gt; on my 
test machine.&lt;/p&gt;

&lt;h3 id="discussion"&gt;Discussion&lt;/h3&gt;
&lt;p&gt;Currently, the min/max operation takes ½ operation per word, while the permute 
operation takes 1½ operations per word. The reason the permutation requires so 
many instructions is that both buckets need to be in the same register for the 
permute operation but they need to be in seperate registers for the min/max 
operation. By carefully considering the shuffling constants, it’s possible to 
do permutations #3 and #8 in 1 operation per word and ½ operation per word, 
respectively.&lt;/p&gt;

&lt;p&gt;The application can be further sped up by using multiple threads to do the 
sorting, each of the 1024 elements can be sorted individually. When working 
with much larger datasets, subsets of it can still be sorted individually, so 
this algorithm scales very well.&lt;/p&gt;
</content>
    <summary type="html">&lt;p&gt;
  &lt;em&gt;Update July 20, 2015: The winning solution by Alexander Monakov also uses a 
sorting network but transposes the items to be sorted to sort 32 nibbles in 
parallel with a length 60 network, instead of my 4 nibbles with a depth 9 
network. &lt;a href="http://www.hanshq.net/nibble_sort.html#winning-simd"&gt;Hans Wennborg&lt;/a&gt; 
has a nice write-up of that solution.&lt;/em&gt;
&lt;/p&gt;</summary>
  </entry>
</feed>

