<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html lang="en">
<head>
<meta content="text/html; charset=US-ASCII" http-equiv="Content-Type">
<title>
GitLab
</title>


<style>img {
max-width: 100%; height: auto;
}
</style>
</head>
<body>
<div class="content">

<p class="details" style="font-style: italic; color: #666;">
<a href="https://gitlab.com/dwmw2">David Woodhouse</a> created an issue: <a href="https://gitlab.com/gnutls/gnutls/-/issues/1257">#1257</a>
</p>
<div></div>
<p dir="auto">In order to support TLSv1.3 with TPM-based keys (cf. <a href="https://gitlab.com/gnutls/gnutls/-/issues/1235" data-original="#1235" data-link="false" data-link-reference="false" data-project="179611" data-issue="86896374" data-reference-type="issue" data-container="body" data-placement="top" title="Cannot support TLSv1.3 RSA-PSS with external keys" class="gfm gfm-issue has-tooltip">#1235</a>) I implemented RSA-PSS padding in my <em>application</em>: <a href="https://gitlab.com/openconnect/openconnect/-/commit/ff367965fcc13f6c1ba7fbda7a49d1467f1b39de" data-original="https://gitlab.com/openconnect/openconnect/-/commit/ff367965fcc13f6c1ba7fbda7a49d1467f1b39de" data-link="false" data-link-reference="true" data-project="2335175" data-commit="ff367965fcc13f6c1ba7fbda7a49d1467f1b39de" data-reference-type="commit" data-container="body" data-placement="top" title="Implement RSA-PSS padding for TPMv2" class="gfm gfm-commit has-tooltip">openconnect/openconnect@ff367965</a></p>
<p dir="auto">After generating the initial hash <code>M'</code> from <code>( 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | mHash | Salt )</code> we then repeatedly generate hashes of <code>( M' | C )</code> where C is an incrementing 32-bit big-endian counter.</p>
<p dir="auto">Instead of <em>repeatedly</em> feeding <code>M'</code> into the hash function, I chose to use <code>gnutls_hash_copy()</code> from a context where <code>M'</code> had already been hashed. Then each time round the loop it's just <code>gnutls_hash_copy()</code>, <code>gnutls_hash()</code> to add the four bytes of <code>C</code>, and <code>gnutls_hash_deinit()</code> of the copy.</p>
<p dir="auto">This appears to work for SHA256 and SHA512, but fails for SHA384. It seems to have something to do with the fact that the hash context has already been used (to create <code>M'</code>). I thought that <code>gnutls_hash_output()</code> was supposed to reset it and leave it ready for re-use, but apparently not; calling <code>gnutls_hash_deinit()</code> and <code>gnutls_hash_init()</code> again does seem to reset it <em>harder</em> and make it work.</p>
<p dir="auto">Tested with gnutls-3.6.16-1.fc33.x86_64</p>
<p dir="auto">Test case:</p>
<pre class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">#</span>
<span id="LC2" class="line" lang="plaintext">#include <gnutls/gnutls.h></span>
<span id="LC3" class="line" lang="plaintext">#include <gnutls/crypto.h></span>
<span id="LC4" class="line" lang="plaintext">#include <stdio.h></span>
<span id="LC5" class="line" lang="plaintext">#include <stdlib.h></span>
<span id="LC6" class="line" lang="plaintext">#include <string.h></span>
<span id="LC7" class="line" lang="plaintext"></span>
<span id="LC8" class="line" lang="plaintext">#include <arpa/inet.h></span>
<span id="LC9" class="line" lang="plaintext"></span>
<span id="LC10" class="line" lang="plaintext">#define SHA512_SIZE 64</span>
<span id="LC11" class="line" lang="plaintext"></span>
<span id="LC12" class="line" lang="plaintext">static unsigned char mHash[SHA512_SIZE] = {</span>
<span id="LC13" class="line" lang="plaintext">      0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,</span>
<span id="LC14" class="line" lang="plaintext">      0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,</span>
<span id="LC15" class="line" lang="plaintext">      0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,</span>
<span id="LC16" class="line" lang="plaintext">      0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,</span>
<span id="LC17" class="line" lang="plaintext">      0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,</span>
<span id="LC18" class="line" lang="plaintext">      0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,</span>
<span id="LC19" class="line" lang="plaintext">      0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,</span>
<span id="LC20" class="line" lang="plaintext">      0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f</span>
<span id="LC21" class="line" lang="plaintext">};</span>
<span id="LC22" class="line" lang="plaintext"></span>
<span id="LC23" class="line" lang="plaintext">static unsigned char mPrime[SHA512_SIZE];</span>
<span id="LC24" class="line" lang="plaintext"></span>
<span id="LC25" class="line" lang="plaintext">static unsigned char h1[SHA512_SIZE];</span>
<span id="LC26" class="line" lang="plaintext">static unsigned char h2[SHA512_SIZE];</span>
<span id="LC27" class="line" lang="plaintext"></span>
<span id="LC28" class="line" lang="plaintext">static unsigned char h1p[SHA512_SIZE];</span>
<span id="LC29" class="line" lang="plaintext">static unsigned char h2p[SHA512_SIZE];</span>
<span id="LC30" class="line" lang="plaintext"></span>
<span id="LC31" class="line" lang="plaintext"></span>
<span id="LC32" class="line" lang="plaintext">static int mgf1(gnutls_hash_hd_t hctx, int count, unsigned char *buf, int diglen)</span>
<span id="LC33" class="line" lang="plaintext">{</span>
<span id="LC34" class="line" lang="plaintext">      gnutls_hash_hd_t ctx2 = gnutls_hash_copy(hctx);</span>
<span id="LC35" class="line" lang="plaintext"></span>
<span id="LC36" class="line" lang="plaintext">      if (!ctx2)</span>
<span id="LC37" class="line" lang="plaintext">              return GNUTLS_E_PK_SIGN_FAILED;</span>
<span id="LC38" class="line" lang="plaintext"></span>
<span id="LC39" class="line" lang="plaintext">      uint32_t be_count = htonl(count);</span>
<span id="LC40" class="line" lang="plaintext">      int err = gnutls_hash(ctx2, &be_count, sizeof(be_count));</span>
<span id="LC41" class="line" lang="plaintext">      if (err) {</span>
<span id="LC42" class="line" lang="plaintext">              gnutls_hash_deinit(ctx2, NULL);</span>
<span id="LC43" class="line" lang="plaintext">              return err;</span>
<span id="LC44" class="line" lang="plaintext">      }</span>
<span id="LC45" class="line" lang="plaintext">      gnutls_hash_deinit(ctx2, buf);</span>
<span id="LC46" class="line" lang="plaintext"></span>
<span id="LC47" class="line" lang="plaintext">      int i;</span>
<span id="LC48" class="line" lang="plaintext">      for (i = 0; i < diglen; i++) {</span>
<span id="LC49" class="line" lang="plaintext">              if (!(i & 15)) printf("\n(%d) %04x:", count, i);</span>
<span id="LC50" class="line" lang="plaintext">              printf(" %02x", buf[i]);</span>
<span id="LC51" class="line" lang="plaintext">      }</span>
<span id="LC52" class="line" lang="plaintext">      printf("\n");</span>
<span id="LC53" class="line" lang="plaintext">      return 0;</span>
<span id="LC54" class="line" lang="plaintext">}</span>
<span id="LC55" class="line" lang="plaintext"></span>
<span id="LC56" class="line" lang="plaintext">int psstest(int dig)</span>
<span id="LC57" class="line" lang="plaintext">{</span>
<span id="LC58" class="line" lang="plaintext">      gnutls_hash_hd_t hashctx = NULL;</span>
<span id="LC59" class="line" lang="plaintext">      int diglen = gnutls_hash_get_len(dig);</span>
<span id="LC60" class="line" lang="plaintext">      int err = 0;</span>
<span id="LC61" class="line" lang="plaintext"></span>
<span id="LC62" class="line" lang="plaintext">      if ((err = gnutls_hash_init(&hashctx, dig)) ||</span>
<span id="LC63" class="line" lang="plaintext">          (err = gnutls_hash(hashctx, "\0\0\0\0\0\0\0\0", 8)) ||</span>
<span id="LC64" class="line" lang="plaintext">          (err = gnutls_hash(hashctx, mHash, diglen)))</span>
<span id="LC65" class="line" lang="plaintext">              goto out;</span>
<span id="LC66" class="line" lang="plaintext"></span>
<span id="LC67" class="line" lang="plaintext">      gnutls_hash_output(hashctx, mPrime);</span>
<span id="LC68" class="line" lang="plaintext"></span>
<span id="LC69" class="line" lang="plaintext">      /* gnutls_hash_output() is supposed to reset the state. For SHA256 at least</span>
<span id="LC70" class="line" lang="plaintext">       * it *does* seem to work, in</span>
<span id="LC71" class="line" lang="plaintext">       * http://git.infradead.org/users/dwmw2/openconnect.git/commitdiff/ff367965f</span>
<span id="LC72" class="line" lang="plaintext">       */</span>
<span id="LC73" class="line" lang="plaintext">      if (err = gnutls_hash(hashctx, mPrime, diglen))</span>
<span id="LC74" class="line" lang="plaintext">              goto out;</span>
<span id="LC75" class="line" lang="plaintext"></span>
<span id="LC76" class="line" lang="plaintext">      if (err = mgf1(hashctx, 0, h1, diglen))</span>
<span id="LC77" class="line" lang="plaintext">              goto out;</span>
<span id="LC78" class="line" lang="plaintext"></span>
<span id="LC79" class="line" lang="plaintext">      if (err = mgf1(hashctx, 1, h2, diglen))</span>
<span id="LC80" class="line" lang="plaintext">              goto out;</span>
<span id="LC81" class="line" lang="plaintext"></span>
<span id="LC82" class="line" lang="plaintext">      /* This one really *does* reset it, and makes things work. But *should*</span>
<span id="LC83" class="line" lang="plaintext">       * be identical to the above?  */</span>
<span id="LC84" class="line" lang="plaintext">      gnutls_hash_deinit(hashctx, NULL);</span>
<span id="LC85" class="line" lang="plaintext">      if (err = gnutls_hash_init(&hashctx, dig))</span>
<span id="LC86" class="line" lang="plaintext">              goto out;</span>
<span id="LC87" class="line" lang="plaintext"></span>
<span id="LC88" class="line" lang="plaintext">      if (err = gnutls_hash(hashctx, mPrime, diglen))</span>
<span id="LC89" class="line" lang="plaintext">              goto out;</span>
<span id="LC90" class="line" lang="plaintext"></span>
<span id="LC91" class="line" lang="plaintext">      if (err = mgf1(hashctx, 0, h1p, diglen))</span>
<span id="LC92" class="line" lang="plaintext">              goto out;</span>
<span id="LC93" class="line" lang="plaintext"></span>
<span id="LC94" class="line" lang="plaintext">      if (err = mgf1(hashctx, 1, h2p, diglen))</span>
<span id="LC95" class="line" lang="plaintext">              goto out;</span>
<span id="LC96" class="line" lang="plaintext"></span>
<span id="LC97" class="line" lang="plaintext">      if (memcmp(h1, h1p, diglen) || memcmp(h2, h2p, diglen)) {</span>
<span id="LC98" class="line" lang="plaintext">              printf("Error: mismatch\n");</span>
<span id="LC99" class="line" lang="plaintext">              return 1;</span>
<span id="LC100" class="line" lang="plaintext">     }</span>
<span id="LC101" class="line" lang="plaintext"></span>
<span id="LC102" class="line" lang="plaintext">     return 0;</span>
<span id="LC103" class="line" lang="plaintext"> out:</span>
<span id="LC104" class="line" lang="plaintext">     printf("Error: %s\n", gnutls_strerror(err));</span>
<span id="LC105" class="line" lang="plaintext">     return 1;</span>
<span id="LC106" class="line" lang="plaintext">}</span>
<span id="LC107" class="line" lang="plaintext"></span>
<span id="LC108" class="line" lang="plaintext">int main(void)</span>
<span id="LC109" class="line" lang="plaintext">{</span>
<span id="LC110" class="line" lang="plaintext">     //psstest(GNUTLS_DIG_SHA256);</span>
<span id="LC111" class="line" lang="plaintext">     psstest(GNUTLS_DIG_SHA384);</span>
<span id="LC112" class="line" lang="plaintext">     //psstest(GNUTLS_DIG_SHA512);</span>
<span id="LC113" class="line" lang="plaintext">}</span>
<span id="LC114" class="line" lang="plaintext"></span></code></pre>

</div>
<div class="footer" style="margin-top: 10px;">
<p style="font-size: small; color: #666;">

<br>
Reply to this email directly or <a href="https://gitlab.com/gnutls/gnutls/-/issues/1257">view it on GitLab</a>.
<br>
You're receiving this email because of your account on gitlab.com.
If you'd like to receive fewer emails, you can
<a href="https://gitlab.com/-/sent_notifications/9e4343d2cc9cae082981ecb0d545e052/unsubscribe">unsubscribe</a>
from this thread or
adjust your notification settings.
<script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","action":{"@type":"ViewAction","name":"View Issue","url":"https://gitlab.com/gnutls/gnutls/-/issues/1257"}}</script>


</p>
</div>
</body>
</html>