<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>On the road to Bandol &#187; bytecode</title>
	<atom:link href="https://javacard.vetilles.com/tag/bytecode/feed/" rel="self" type="application/rss+xml" />
	<link>https://javacard.vetilles.com</link>
	<description>A weblog on Java Card, security, and other things personal</description>
	<lastBuildDate>Mon, 18 Aug 2025 06:48:26 +0000</lastBuildDate>
	<language>en-US</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.0.32</generator>
	<item>
		<title>The misuse of bytecode verification</title>
		<link>https://javacard.vetilles.com/2011/10/19/the-misuse-of-bytecode-verification/</link>
		<comments>https://javacard.vetilles.com/2011/10/19/the-misuse-of-bytecode-verification/#comments</comments>
		<pubDate>Wed, 19 Oct 2011 08:42:21 +0000</pubDate>
		<dc:creator><![CDATA[Eric Vétillard]]></dc:creator>
				<category><![CDATA[Discussions]]></category>
		<category><![CDATA[Java Card 2.x]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Virtual machine]]></category>
		<category><![CDATA[bytecode]]></category>
		<category><![CDATA[GlobalPlatform]]></category>
		<category><![CDATA[static analysis]]></category>

		<guid isPermaLink="false">http://javacard.vetilles.com/?p=759</guid>
		<description><![CDATA[Bytecode verification has been an interesting debate since the very beginning of Java Card. Back then, in 1997, Java was very much about Java applets, and the bytecode verifier was the essential piece of software that allowed untrusted code to run in a browser efficiently (i.e., without doing expensive runtime checks, and without having to [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Bytecode verification has been an interesting debate since the very beginning of Java Card. Back then, in 1997, Java was very much about Java applets, and the bytecode verifier was the essential piece of software that allowed untrusted code to run in a browser efficiently (<em>i.e.</em>, without doing expensive runtime checks, and without having to setup a complex process of applet vetting). We inherited this view of bytecode verification in Java Card, and the verifier was integrated in the Java Card virtual machine.</p>
<p>Since then, there have been many debates about bytecode verification, and my own position has evolved over the years. Today, my opinion is a bit contrasted, some may even say contradictory. Nevertheless, here it is:</p>
<ul>
<li>Bytecode verification has limited use for Java Card runtime security.</li>
<li>Extended bytecode verification is a very good tool for application vetting.</li>
</ul>
<p>Let me give a few more details about these two opinions.</p>
<h4>Bytecode verification and runtime security</h4>
<p>The idea of runtime verification is that it is performed after getting the code, and right before to run it. The code that runs is therefore known correct, at least regarding bytecode execution (unrelated attacks remain possible, of course).</p>
<p>The first big issue with bytecode verification is that, in Java Card, with the split virtual machine model, verification is not performed on the card, but outside of the card, before/during/after converting the application into Java Card&#8217;s specific binary format (CAP file). Then, the application is sent to the card over some channel that may be attacked. Here, we rely on GlobalPlatform&#8217;s cryptography-based security to protect the integrity of the code. So, basically, we still need to establish trust, and we must say goodbye to the power of running untrusted code from arbitrary developers.</p>
<p>This is not a big issue in practice, because there is no business model that allows arbitrary code to be loaded on cards. However, this causes an organizational problem, as the verification process needs to be well organized. Researchers from Nijmegen and Limoges have shown that it is possible to fool the verification process with fake export files, and then load on a card verified code that will perform type confusion attacks.</p>
<p>Going beyond that, some people have designed applications that can be verified, but have been designed to be attacked through hardware attacks (fault induction, usually). Such attacks, usually known as hybrid attacks, completely fool the bytecode verification process.</p>
<p>Most security experts will then remind you at this point of the discussion that bytecode verification is only one part of the process, that GlobalPlatform is also important, that the origin of code is usually known, that this makes it very difficult to include attack code in an application, <em>etc</em>. By doing this, they are just about accepting the fact that bytecode verification is useless or at best  marginally useful: the real security of cards is in the trust between issuers and application providers, and some cryptographic process. Basically, this works because the ecosystems are small enough to be controlled (which is true for cards, and fine for me).</p>
<p>Finally, some vendors claim to have developed defensive virtual machines, which do not require a bytecode verifier, and perform enough runtime verifications to accept any bytecode, good or bad, without any risk. In that case, bytecode verification is really useless, and I believe that it makes things much simpler. Of course, such virtual machines are difficult to design and implement efficiently, but this is definitely possible, and I think that it has been done in the past (or at least that some people has come very close to it).</p>
<p>To conclude, I will get back many years ago. In 2000, Trusted Logic was very proud of its on-card bytecode verifier; the technology worked, but it has not been widely adopted. I believe that the first factor was performance, as verification made the loading and linking process much slower. I also believe that a second factor, less obvious, is that on-card bytecode verification makes the card&#8217;s security more brittle, by encouraging VM developers to rely too much on static verification rather than runtime checks (which also prevent other runtime attacks, for instance using fault induction). More than ten years later, most people admit that this was not the way to go, and I just go one step further by stating that bytecode verification is not that useful for runtime security.</p>
<h4>Bytecode verification and application vetting</h4>
<p>Bytecode verification simply consists of a very simple static analysis of the application code. Basically, this is is a program proof, but a very simple one, whose complexity can be controlled. The objective of such simple proofs is not to demonstrate that a program is correct with respect to its specification, but that this program obeys a predefined set of properties.</p>
<p>For Java bytecode verification, these properties are related to the proper ues of the bytecode instructions. However, the same algorithms can be extended in order to prove many more properties, covering many aspects of application security. Among the things that can be proven, we have the following:</p>
<ul>
<li>Method <em>M</em> is not called.</li>
<li>Method <em>M</em> is not called with arguments <em>A1</em>, &#8230;, <em>An</em>.</li>
<li>Method <em>M</em> is always called before/after method <em>N</em>.</li>
<li>Method <em>M</em> never throws a <code>NullPointerException</code> (or any other exception).</li>
<li>Command <em>INS</em> can only return status codes <em>SW1</em>, &#8230;, <em>SWn</em></li>
<li>Toolkit buffers are only used when they are available.</li>
<li>and many more.</li>
</ul>
<p>Of course, there is no magic. When extending static analysis to many properties, it becomes more and more difficult to avoid false positives, <em>i.e.</em> errors that are caused by weaknesses in the algorithms. Put simply, an application is rejected although it is in fact correct.</p>
<p>Apart from working on the algorithms to make them better, there are two ways to deal with this issue:</p>
<ul>
<li>Providing the verification tool to developers, together with explanations about the rules to follow. Usually, it is rather simple for developers to ensure that their application can be verified, provided that they can use the tool throughout the development process.</li>
<li>Use the tool in a vetting process as a guide for evaluators, who then perform additional verifications. In that case, broken rules are considered as warnings, and then verified by the evaluators. Simple applications can usually be verified easily, and more complex verification requires a few checks, simplified by the fact that the most boring tasks are performed automatically.</li>
</ul>
<p>I believe in both approaches, but the second one has been proven efficient by my then colleagues of Trusted Labs. By using such a static analysis tool, they are able to optimize the vetting process of Java Card applications (and MIDlets, but this is another story) significantly, by allowing them to focus on the the most important parts of the applications.</p>
<p>In addition, this approach allows us to include many more security rules. For instance, hybrid applications must include code that can be modified into attack code through a simple attack. It is possible to build a library of patterns of such code sequences, and to check for them statically. Then, evaluators can be warned of the possible presence of an hybrid attack and check for it. This can be promising, because such checks (very boring to do, but very unlikely to lead to anything) are usually poorly performed by humans.</p>
<p>Finally, extended bytecode verification, or static analysis, has been proven to be a very efficient optimization tool. All optimizing compilers include a static analysis phase to perform their most complex optimizations. Java Card can take great advantage of this, because of the isolation between applications, and also because of the closed world hypothesis that is sometimes possible, when cards are closed (no additional applications can be downloaded).</p>
<p>So, bytecode verification has many uses in Java Card, but runtime security just isn&#8217;t the most compelling.</p>
]]></content:encoded>
			<wfw:commentRss>https://javacard.vetilles.com/2011/10/19/the-misuse-of-bytecode-verification/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Live from e-Smart: Nijmegen strikes again</title>
		<link>https://javacard.vetilles.com/2008/09/19/live-from-esmart-nijmegen-strikes-again/</link>
		<comments>https://javacard.vetilles.com/2008/09/19/live-from-esmart-nijmegen-strikes-again/#comments</comments>
		<pubDate>Fri, 19 Sep 2008 10:00:39 +0000</pubDate>
		<dc:creator><![CDATA[Eric Vétillard]]></dc:creator>
				<category><![CDATA[Java Card 2.x]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[bytecode]]></category>
		<category><![CDATA[e-Smart]]></category>
		<category><![CDATA[exploit]]></category>
		<category><![CDATA[Java Card]]></category>
		<category><![CDATA[verifier]]></category>

		<guid isPermaLink="false">http://javacard.vetilles.com/2008/09/19/live-from-esmart-nijmegen-strikes-again/</guid>
		<description><![CDATA[Wojciech Mostowski is a researcher from the Radboud University Nijmegen, and he is a frequent speaker at e-Smart. He even wa a finalist for the Java Card Forum a while ago. He has been spending years looking very closely at the Java Card specifications, trying to find issues in cards. Today, he is getting at [&#8230;]]]></description>
				<content:encoded><![CDATA[<p><a href="http://www.cs.ru.nl/~woj/" class="liexternal">Wojciech Mostowski</a> is a researcher from the Radboud University Nijmegen, and he is a frequent speaker at e-Smart. He even wa a finalist for the Java Card Forum a while ago. He has been spending years looking very closely at the Java Card specifications, trying to find issues in cards. Today, he is <a href="http://www.cs.ru.nl/~woj/papers/download/esmart2008-slides.pdf" class="lipdf">getting at the firewall</a>.</p>
<p>It seems that logical attacks on Java Card are quite trendy these days, as several teams seem to work on them. On the firewall, the idea is here that the Java Card specifications assume type correctness, but that this correctness is not actually guaranteed, because in most cases, bytecode  verification is not performed on the card, which means that incorrect applications can be loaded.</p>
<p>The presentation starts with a few compliance tests, of course based on cornercases. They found a few issues, but nothing really bad. It may be possible in some cases to get the type of an object when you shouldn&#8217;t, or to use a transient array when it should not be accessible, but in the end, there is no way to get anythingreally  interesting done.</p>
<p>The next item is much more interesting. His idea is to create type confusion on files that are apparently correct, simply by using two different definitions of the Shareable interface: one for the client, and one for the server, with different definitions. For instance:</p>
<p>On the client side:</p>
<pre>
public interface Bad extends Shareable {
  public void doDamage(<strong><font color="#660066">AID aid</font></strong>);
}
</pre>
<p>On the server side:</p>
<pre>
public interface Bad extends Shareable {
  public void doDamage(<strong><font color="#660066">byte[] ba</font></strong>);
}
</pre>
<p>If you verify the client with its definition of the interface, and the server with its own version, verification will succeed in both cases. However, the type confusion is obvious. And in this case, the &#8220;bad&#8221; part is that the AID is a JCRE entry-point object, with high privileges. and this allows an attacker to do bad things. I won&#8217;t go further here, but details are available on the <a href="http://www.cs.ru.nl/~woj/papers/download/esmart2008-slides.pdf" class="lipdf">slides</a>. </p>
<p>Overall, it is nice to see that Java Card logical attacks get exposed. The potential impact is in practice minimal, because it is very difficult for hackers to load applications in deployed cards (since a GlobalPlatform authentication is typically required). Nevertheless, with NFC and other &#8220;open&#8221; schemes, the number of downloaded applications is likely to raise quite fast, and the risk of getting malware in the card may slightly increase (developers remain well identified, so the risk is likely to remain low).</p>
<p>This means that bytecode verification needs to be systematically performed, and that this verification needs to be performed by taking into account the actual context in which the application will be exploited. The exploit above is only possible because the server and client have been verified with respect to different contexts.</p>
<p>Recent multi-application projects, such as the Pegasus project in France, have defined strong requirements in this matter, and we are getting closer to exploiting a complete verification environment, which was my first assignment as a Trusted Logic employee, about 8 years ago. Time to get this code out of the closet&#8230;</p>
<p>Oh, I almost forgot. Of course, Java Card 3.0 addresses this issue, at least in its Connected edition, where on-card bytecode verification is mandatory.</p>
]]></content:encoded>
			<wfw:commentRss>https://javacard.vetilles.com/2008/09/19/live-from-esmart-nijmegen-strikes-again/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
