Skip to content
Snippets Groups Projects
2011-06-02-Skein-tutorial-part-7-not-dead-but-resting.html 15.6 KiB
Newer Older
---
layout: post
author: Pascal Cuoq
date: 2011-06-02 17:52 +0200
categories: skein value
format: xhtml
title: "Skein tutorial, part 7: not dead, but resting"
summary: 
---
{% raw %}
<p>Do you remember the Skein tutorial? It went off to a good start (it started this blog) and then was never really completed. I blame <strong>laziness</strong>. Looking back at that first post, I notice that indeed, before Boron, we were shipping software without documentation (just think! Ahem). At the time, I also thought that the extended tutorial would be over in a couple of posts, a mistake I have learnt not to make any more. September 2010, those were the days…</p> 
<h2>The story so far</h2> 
<p>The solution provided in <a href="/index.php?post/2010/11/21/Value-analysis-tutorial%2C-part-4">this post</a> was one of two promised solutions. It was in fact my own solution. While conceiving it  I was determined not to look at Skein's source code. I could claim that this was to make the verification method completely independent of the code  which is obviously good. It allows  for instance  to swap in another implementation — say  another entry in the NIST SHA3 contest — and hopefully to verify it just by relaunching the same script. The true reason I didn't want to look at the code is more likely written in bold at the top of this post.</p> 
<p>Because I didn't want to look at Skein's source code  my solution involved the meta-argument that you can cover all possible executions of the loop</p> 
<pre>  while (Frama_C_interval(0 1)) 
  { 
      arbitrarize_msg(); 
      Skein_256_Update(&amp;skein_context  msg  80); 
  } 
</pre> 
<p>by analyzing instead the two pieces of code below  which between them do all the same things:</p> 
<pre>  while (Frama_C_interval(0 1)) 
  { 
      arbitrarize_msg(); 
      Skein_256_Update(&amp;skein_context  msg  80); 
      arbitrarize_msg(); 
      Skein_256_Update(&amp;skein_context  msg  80); 
  } 
</pre> 
<pre>  arbitrarize_msg(); 
  Skein_256_Update(&amp;skein_context  msg  80); 
  while (Frama_C_interval(0 1)) 
  { 
      arbitrarize_msg(); 
      Skein_256_Update(&amp;skein_context  msg  80); 
      arbitrarize_msg(); 
      Skein_256_Update(&amp;skein_context  msg  80); 
  } 
</pre> 
<h2>The alternate solution</h2> 
<p>In July 2010  I was teaching at <a href="http://flolac.iis.sinica.edu.tw/flolac10/en/start.html">the FLOLAC summer school</a> and I was lucky to have <a href="http://joshkos.blogspot.com/">Josh Ko</a> as my Teaching Assistant. He did not have my prejudices against looking at the code being verified. The alternate  and better  solution that follows is his.</p> 
<p>We determined when we elaborated the solution based on pairing the calls to <code>Skein_256_Update()</code>  that the issue was the field <code>skein_context.h.bCnt</code>  
that contained <code>0</code> before the first iteration  and alternately <code>16</code> or <code>32</code> after that. 
Pairing the calls to <code>Skein_256_Update()</code> was one way to force similar calls to be analyzed together and prevent a loss of precision caused by not knowing whether <code>skein_context.h.bCnt</code> was <code>16</code> or <code>32</code>. Josh Ko's solution instead prevents the loss of precision by nudging the value analysis into studying these cases separately by way of an annotation inside <code>Skein_256_Update()</code>:</p> 
<pre>--- skein.c.orig	2011-06-02 21:06:29.000000000 +0200 
+++ skein.c	2011-06-02 21:06:50.000000000 +0200 
@@ -159 6 +159 8 @@ 
     Skein_Assert(ctx-&gt;h.bCnt &lt;= SKEIN_256_BLOCK_BYTES SKEIN_FAIL);     /* catch uninitialized context */ 
+    /*@ assert ctx-&gt;h.bCnt == 0 || ctx-&gt;h.bCnt == 16 || ctx-&gt;h.bCnt == 32 ; */ 
+ 
     /* process full blocks  if any */ 
     if (msgByteCnt + ctx-&gt;h.bCnt &gt; SKEIN_256_BLOCK_BYTES) 
         { 
</pre> 
<p>We have seen how to provide useful annotations in <a href="/index.php?post/2011/03/26/Helping-the-value-analysis-2">this post</a>. The above annotation is another example. With it  we can use this <code>main()</code>:</p> 
<pre>void main(void) 
{ 
  int i; 
  u08b_t hash[HASHLEN]; 
  Skein_256_Ctxt_t skein_context;  
  Skein_256_Init(&amp;skein_context  HASHLEN * 8); 
      arbitrarize_msg(); 
      Skein_256_Update(&amp;skein_context  msg  80); 
      arbitrarize_msg(); 
      Skein_256_Update(&amp;skein_context  msg  80); 
  while (Frama_C_interval(0 1)) 
    { 
      arbitrarize_msg(); 
      Skein_256_Update(&amp;skein_context  msg  80); 
    } 
  Skein_256_Final( &amp;skein_context  hash); 
} 
</pre> 
<pre>$ time frama-c -val -slevel 1000 -slevel-function main:0 *.c -cpp-command "gcc -m32 -C -E -I. " &gt; log2 
real	1m48.218s 
user	1m45.133s 
sys	0m1.325s 
</pre> 
<p>This single <code>main()</code> cover all the programs with n&gt;=2 calls to <code>Skein_256_Update(…  80)</code>:</p> 
<pre>$ grep ssert log2 
skein.c:162:[value] Assertion got status valid. 
</pre> 
<p>And that's that: no alarm is emitted  and the annotation that we provided for the value analysis is verified before being used (so it is not an assumption).</p> 
<p>For the sake of completeness  the cases of 0 and 1 calls to <code>Skein_256_Update(…  80)</code> should also be checked separately. We have done that before  so there is no need to repeat it here.</p> 
<h2>Generalizing</h2> 
<p>The advantage of the method presented in this post over the previous one is that it can more easily be generalized to different buffer lengths passed to <code>Skein_256_Update()</code>. The more complete verification that I <a href="/index.php?post/2010/11/22/Value-analysis-tutorial%2C-part-5%3A-jumping-to-conclusions">last alluded to</a> uses  among other annotations  the assertion below.</p> 
<pre>    /*@ assert                                                                                                                  
      ctx-&gt;h.bCnt ==  0 || ctx-&gt;h.bCnt ==  1 ||                                                                                  
      ctx-&gt;h.bCnt ==  2 || ctx-&gt;h.bCnt ==  3 ||                                                                                  
      ctx-&gt;h.bCnt ==  4 || ctx-&gt;h.bCnt ==  5 ||                                                                                  
      ctx-&gt;h.bCnt ==  6 || ctx-&gt;h.bCnt ==  7 ||                                                                                  
      ctx-&gt;h.bCnt ==  8 || ctx-&gt;h.bCnt ==  9 ||                                                                                  
      ctx-&gt;h.bCnt == 10 || ctx-&gt;h.bCnt == 11 ||                                                                                  
      ctx-&gt;h.bCnt == 12 || ctx-&gt;h.bCnt == 13 ||                                                                                  
      ctx-&gt;h.bCnt == 14 || ctx-&gt;h.bCnt == 15 ||                                                                                  
      ctx-&gt;h.bCnt == 16 || ctx-&gt;h.bCnt == 17 ||                                                                                  
      ctx-&gt;h.bCnt == 18 || ctx-&gt;h.bCnt == 19 ||                                                                                  
      ctx-&gt;h.bCnt == 20 || ctx-&gt;h.bCnt == 21 ||                                                                                  
      ctx-&gt;h.bCnt == 22 || ctx-&gt;h.bCnt == 23 ||                                                                                  
      ctx-&gt;h.bCnt == 24 || ctx-&gt;h.bCnt == 25 ||                                                                                  
      ctx-&gt;h.bCnt == 26 || ctx-&gt;h.bCnt == 27 ||                                                                                  
      ctx-&gt;h.bCnt == 28 || ctx-&gt;h.bCnt == 29 ||                                                                                  
      ctx-&gt;h.bCnt == 30 || ctx-&gt;h.bCnt == 31 ||                                                                                  
      ctx-&gt;h.bCnt == 32 ; */ 
</pre>" <p>Do you remember the Skein tutorial? It went off to a good start (it started this blog) and then was never really completed. I blame <strong>laziness</strong>. Looking back at that first post, I notice that indeed, before Boron, we were shipping software without documentation (just think! Ahem). At the time, I also thought that the extended tutorial would be over in a couple of posts, a mistake I have learnt not to make any more. September 2010, those were the days…</p> 
<h2>The story so far</h2> 
<p>The solution provided in <a href="/index.php?post/2010/11/21/Value-analysis-tutorial%2C-part-4">this post</a> was one of two promised solutions. It was in fact my own solution. While conceiving it  I was determined not to look at Skein's source code. I could claim that this was to make the verification method completely independent of the code  which is obviously good. It allows  for instance  to swap in another implementation — say  another entry in the NIST SHA3 contest — and hopefully to verify it just by relaunching the same script. The true reason I didn't want to look at the code is more likely written in bold at the top of this post.</p> 
<p>Because I didn't want to look at Skein's source code  my solution involved the meta-argument that you can cover all possible executions of the loop</p> 
<pre>  while (Frama_C_interval(0 1)) 
  { 
      arbitrarize_msg(); 
      Skein_256_Update(&amp;skein_context  msg  80); 
  } 
</pre> 
<p>by analyzing instead the two pieces of code below  which between them do all the same things:</p> 
<pre>  while (Frama_C_interval(0 1)) 
  { 
      arbitrarize_msg(); 
      Skein_256_Update(&amp;skein_context  msg  80); 
      arbitrarize_msg(); 
      Skein_256_Update(&amp;skein_context  msg  80); 
  } 
</pre> 
<pre>  arbitrarize_msg(); 
  Skein_256_Update(&amp;skein_context  msg  80); 
  while (Frama_C_interval(0 1)) 
  { 
      arbitrarize_msg(); 
      Skein_256_Update(&amp;skein_context  msg  80); 
      arbitrarize_msg(); 
      Skein_256_Update(&amp;skein_context  msg  80); 
  } 
</pre> 
<h2>The alternate solution</h2> 
<p>In July 2010  I was teaching at <a href="http://flolac.iis.sinica.edu.tw/flolac10/en/start.html">the FLOLAC summer school</a> and I was lucky to have <a href="http://joshkos.blogspot.com/">Josh Ko</a> as my Teaching Assistant. He did not have my prejudices against looking at the code being verified. The alternate  and better  solution that follows is his.</p> 
<p>We determined when we elaborated the solution based on pairing the calls to <code>Skein_256_Update()</code>  that the issue was the field <code>skein_context.h.bCnt</code>  
that contained <code>0</code> before the first iteration  and alternately <code>16</code> or <code>32</code> after that. 
Pairing the calls to <code>Skein_256_Update()</code> was one way to force similar calls to be analyzed together and prevent a loss of precision caused by not knowing whether <code>skein_context.h.bCnt</code> was <code>16</code> or <code>32</code>. Josh Ko's solution instead prevents the loss of precision by nudging the value analysis into studying these cases separately by way of an annotation inside <code>Skein_256_Update()</code>:</p> 
<pre>--- skein.c.orig	2011-06-02 21:06:29.000000000 +0200 
+++ skein.c	2011-06-02 21:06:50.000000000 +0200 
@@ -159 6 +159 8 @@ 
     Skein_Assert(ctx-&gt;h.bCnt &lt;= SKEIN_256_BLOCK_BYTES SKEIN_FAIL);     /* catch uninitialized context */ 
+    /*@ assert ctx-&gt;h.bCnt == 0 || ctx-&gt;h.bCnt == 16 || ctx-&gt;h.bCnt == 32 ; */ 
+ 
     /* process full blocks  if any */ 
     if (msgByteCnt + ctx-&gt;h.bCnt &gt; SKEIN_256_BLOCK_BYTES) 
         { 
</pre> 
<p>We have seen how to provide useful annotations in <a href="/index.php?post/2011/03/26/Helping-the-value-analysis-2">this post</a>. The above annotation is another example. With it  we can use this <code>main()</code>:</p> 
<pre>void main(void) 
{ 
  int i; 
  u08b_t hash[HASHLEN]; 
  Skein_256_Ctxt_t skein_context;  
  Skein_256_Init(&amp;skein_context  HASHLEN * 8); 
      arbitrarize_msg(); 
      Skein_256_Update(&amp;skein_context  msg  80); 
      arbitrarize_msg(); 
      Skein_256_Update(&amp;skein_context  msg  80); 
  while (Frama_C_interval(0 1)) 
    { 
      arbitrarize_msg(); 
      Skein_256_Update(&amp;skein_context  msg  80); 
    } 
  Skein_256_Final( &amp;skein_context  hash); 
} 
</pre> 
<pre>$ time frama-c -val -slevel 1000 -slevel-function main:0 *.c -cpp-command "gcc -m32 -C -E -I. " &gt; log2 
real	1m48.218s 
user	1m45.133s 
sys	0m1.325s 
</pre> 
<p>This single <code>main()</code> cover all the programs with n&gt;=2 calls to <code>Skein_256_Update(…  80)</code>:</p> 
<pre>$ grep ssert log2 
skein.c:162:[value] Assertion got status valid. 
</pre> 
<p>And that's that: no alarm is emitted  and the annotation that we provided for the value analysis is verified before being used (so it is not an assumption).</p> 
<p>For the sake of completeness  the cases of 0 and 1 calls to <code>Skein_256_Update(…  80)</code> should also be checked separately. We have done that before  so there is no need to repeat it here.</p> 
<h2>Generalizing</h2> 
<p>The advantage of the method presented in this post over the previous one is that it can more easily be generalized to different buffer lengths passed to <code>Skein_256_Update()</code>. The more complete verification that I <a href="/index.php?post/2010/11/22/Value-analysis-tutorial%2C-part-5%3A-jumping-to-conclusions">last alluded to</a> uses  among other annotations  the assertion below.</p> 
<pre>    /*@ assert                                                                                                                  
      ctx-&gt;h.bCnt ==  0 || ctx-&gt;h.bCnt ==  1 ||                                                                                  
      ctx-&gt;h.bCnt ==  2 || ctx-&gt;h.bCnt ==  3 ||                                                                                  
      ctx-&gt;h.bCnt ==  4 || ctx-&gt;h.bCnt ==  5 ||                                                                                  
      ctx-&gt;h.bCnt ==  6 || ctx-&gt;h.bCnt ==  7 ||                                                                                  
      ctx-&gt;h.bCnt ==  8 || ctx-&gt;h.bCnt ==  9 ||                                                                                  
      ctx-&gt;h.bCnt == 10 || ctx-&gt;h.bCnt == 11 ||                                                                                  
      ctx-&gt;h.bCnt == 12 || ctx-&gt;h.bCnt == 13 ||                                                                                  
      ctx-&gt;h.bCnt == 14 || ctx-&gt;h.bCnt == 15 ||                                                                                  
      ctx-&gt;h.bCnt == 16 || ctx-&gt;h.bCnt == 17 ||                                                                                  
      ctx-&gt;h.bCnt == 18 || ctx-&gt;h.bCnt == 19 ||                                                                                  
      ctx-&gt;h.bCnt == 20 || ctx-&gt;h.bCnt == 21 ||                                                                                  
      ctx-&gt;h.bCnt == 22 || ctx-&gt;h.bCnt == 23 ||                                                                                  
      ctx-&gt;h.bCnt == 24 || ctx-&gt;h.bCnt == 25 ||                                                                                  
      ctx-&gt;h.bCnt == 26 || ctx-&gt;h.bCnt == 27 ||                                                                                  
      ctx-&gt;h.bCnt == 28 || ctx-&gt;h.bCnt == 29 ||                                                                                  
      ctx-&gt;h.bCnt == 30 || ctx-&gt;h.bCnt == 31 ||                                                                                  
      ctx-&gt;h.bCnt == 32 ; */ 
</pre>" 
{% endraw %}