<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Why does HLS 5 (GMAC) mutual authentication fail on Server Proof verification during StoC/CtoS challenge exchange?]]></title><description><![CDATA[<blockquote>
<p dir="auto">[!WARNING]<br />
<strong>Technical Redaction &amp; Safe Harbor Notice</strong>:<br />
All communication captures, system titles, and cryptographic parameters in this thread have been sanitized and neutralized. Real utility meter identifiers, production encryption keys (GUEK/GAK/MK), SIM IMSIs, and proprietary network envelopes have been substituted with standard IEC 62056 synthetic test vectors. Do not post unredacted production captures or live cryptographic keys.</p>
</blockquote>
<p dir="auto">We are implementing High Level Security 5 (HLS 5 GMAC) mutual authentication over IEC 62056-47 TCP Wrapper for Security Suite 1 (<code>Association LN</code> OBIS <code>0.0.40.0.0.255</code>, Management Client <code>0x0001</code>).</p>
<p dir="auto">The initial <code>AARQ</code> (<code>0x60</code>) and <code>AARE</code> (<code>0x61</code>) handshake succeeds, and the meter returns a 16-byte Server-to-Client challenge (<code>StoC = 50 36 77 52 4A 32 31 46 11 22 33 44 55 66 77 88</code>).<br />
Next, our client generates the Client-to-Server challenge response (<code>CtoS</code>), encapsulates it inside <code>Action-Request-Normal</code> (Class 15 Method 1 <code>reply_to_HLS_authentication</code>), and transmits it to the meter. The meter accepts the <code>CtoS</code> response and replies with <code>Action-Response-Normal</code> containing the <strong>Server Proof</strong> (<code>StoC</code> authentication tag).</p>
<p dir="auto">However, when our HES client verifies the received Server Proof, the locally computed GMAC authentication tag fails to match the meter's returned tag, causing our HES to abort the association with an <code>invalid-password / challenge-mismatch</code> exception!</p>
<p dir="auto">Here is our client <code>Action-Request</code> (<code>CtoS</code> challenge):</p>
<pre><code class="language-hex">00 01 00 01 00 01 00 28 C3 01 C1 00 0F 00 00 28 00 00 FF 01 01 09 11 10 00 00 00 01 1A 52 FE 7D D3 E7 27 48 97 3C 1E 28
</code></pre>
<p dir="auto">And here is the meter's <code>Action-Response</code> containing the Server Proof:</p>
<pre><code class="language-hex">00 01 00 01 00 01 00 1E C7 01 C1 00 01 09 11 10 00 00 00 01 88 F0 1A 2B 3C 4D 99 11 22 33 44 55 66
</code></pre>
<p dir="auto">Why is our client failing to verify the meter's Server Proof?</p>
]]></description><link>https://dlms.sharur.org/topic/56/why-does-hls-5-gmac-mutual-authentication-fail-on-server-proof-verification-during-stoc-ctos-challenge-exchange</link><generator>RSS for Node</generator><lastBuildDate>Fri, 16 Oct 2026 19:26:01 GMT</lastBuildDate><atom:link href="https://dlms.sharur.org/topic/56.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 22 Aug 2026 17:20:04 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Why does HLS 5 (GMAC) mutual authentication fail on Server Proof verification during StoC/CtoS challenge exchange? on Sat, 22 Aug 2026 17:20:31 GMT]]></title><description><![CDATA[<p dir="auto">To synthesize this for all DLMS protocol engineers, here is the complete Python Gurux snippet demonstrating bidirectional HLS 5 verification:</p>
<pre><code class="language-python">from gurux_dlms.secure import GXSecure
from gurux_dlms.enums import Security, Authentication
from gurux_dlms.objects import GXDLMSAssociationLN

def verify_hls5_mutual_authentication(client, server_system_title, server_proof_bytes, ctos_challenge):
    # 1. Extract Server SC, Server IC, and Server GMAC Tag
    server_sc = server_proof_bytes[0]
    server_ic = int.from_bytes(server_proof_bytes[1:5], 'big')
    server_gmac_tag = server_proof_bytes[5:17] # 12 bytes
    
    # 2. Build Server IV: Server System Title (8B) || Server IC (4B)
    iv = server_system_title + server_proof_bytes[1:5]
    aad = bytes([server_sc])
    
    # 3. Calculate Expected Server Proof over original CtoS challenge using GAK
    expected_proof = GXSecure.secure(
        client.settings, client.ciphering, server_ic, ctos_challenge, server_system_title
    )
    
    assert server_proof_bytes == expected_proof, "Server Proof Mismatch! Mutual auth failed."
    print("[+] HLS 5 Mutual Authentication &amp; Server Proof verified successfully!")
</code></pre>
<h3>Summary Checklist for HLS 5 GMAC:</h3>
<ol>
<li><strong>IV System Title Assignment</strong>: CtoS uses Client System Title; Server Proof verification uses Server System Title (Green Book Table 43).</li>
<li><strong>Key Separation</strong>: Use Authentication Key (GAK), not Encryption Key (GUEK).</li>
<li><strong>Data Payload</strong>: CtoS hashes <code>StoC</code>; Server Proof hashes <code>CtoS</code>.</li>
<li><strong>Anti-Replay</strong>: Guarantee monotonic $IC$ incrementation before challenge generation.</li>
</ol>
]]></description><link>https://dlms.sharur.org/post/179</link><guid isPermaLink="true">https://dlms.sharur.org/post/179</guid><dc:creator><![CDATA[david_miller]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:20:31 GMT</pubDate></item><item><title><![CDATA[Reply to Why does HLS 5 (GMAC) mutual authentication fail on Server Proof verification during StoC/CtoS challenge exchange? on Sat, 22 Aug 2026 17:20:27 GMT]]></title><description><![CDATA[<p dir="auto">Here is the verified working trace of the complete HLS 5 handshake exchange:</p>
<ol>
<li><code>AARQ</code> with Client Challenge (<code>CtoS</code><img src="https://dlms.sharur.org/assets/plugins/nodebb-plugin-emoji/emoji/android/1f61e.png?v=666d1e6b6e4" class="not-responsive emoji emoji-android emoji--disappointed" style="height:23px;width:auto;vertical-align:middle" title="):" alt="😞" /></li>
</ol>
<pre><code class="language-hex">00 01 00 01 00 01 00 3C 60 3A A1 09 06 07 60 85 74 05 08 01 03 A6 0A 04 08 4D 4D 4D 00 00 00 00 01 8A 02 07 80 8B 07 60 85 74 05 08 02 05 AC 0A 80 08 43 74 6F 53 31 32 33 34 BE 10 04 0E 01 00 00 00 06 5F 1F 04 00 00 7E 1F 04 00
</code></pre>
<ol start="2">
<li><code>AARE</code> with Server Challenge (<code>StoC</code><img src="https://dlms.sharur.org/assets/plugins/nodebb-plugin-emoji/emoji/android/1f61e.png?v=666d1e6b6e4" class="not-responsive emoji emoji-android emoji--disappointed" style="height:23px;width:auto;vertical-align:middle" title="):" alt="😞" /></li>
</ol>
<pre><code class="language-hex">00 01 00 01 00 01 00 3C 61 3A A1 09 06 07 60 85 74 05 08 01 03 A2 03 02 01 00 A3 05 A1 03 02 01 00 A6 0A 04 08 47 52 58 00 00 00 00 01 88 02 07 80 89 07 60 85 74 05 08 02 05 AA 0A 80 08 50 36 77 52 4A 32 31 46 BE 10 04 0E
</code></pre>
<ol start="3">
<li><code>CtoS</code> Action Request (Method 1) &amp; <code>StoC</code> Server Proof Action Response succeed cleanly.</li>
</ol>
]]></description><link>https://dlms.sharur.org/post/178</link><guid isPermaLink="true">https://dlms.sharur.org/post/178</guid><dc:creator><![CDATA[alex_turner]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:20:27 GMT</pubDate></item><item><title><![CDATA[Reply to Why does HLS 5 (GMAC) mutual authentication fail on Server Proof verification during StoC/CtoS challenge exchange? on Sat, 22 Aug 2026 17:20:20 GMT]]></title><description><![CDATA[<p dir="auto">From the meter firmware side, there is one more vital rule: <strong>Invocation Counter Anti-Replay on HLS</strong>.</p>
<p dir="auto">When the meter receives <code>Action-Request</code> Method 1, it checks:<br />
$$IC_{\text{CtoS}} &gt; IC_{\text{last_stored}}$$<br />
If the client retransmits <code>CtoS</code> with an old or duplicate $IC$, the meter returns <code>Action-Response-With-Service-Error: hardware-fault</code> (<code>0xC7 0x01 C1 01</code>). Always ensure the client increments its $IC$ before building CtoS!</p>
]]></description><link>https://dlms.sharur.org/post/177</link><guid isPermaLink="true">https://dlms.sharur.org/post/177</guid><dc:creator><![CDATA[elena_rostova]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:20:20 GMT</pubDate></item><item><title><![CDATA[Reply to Why does HLS 5 (GMAC) mutual authentication fail on Server Proof verification during StoC/CtoS challenge exchange? on Sat, 22 Aug 2026 17:20:18 GMT]]></title><description><![CDATA[<p dir="auto">Excellent! Here is the formal mathematical rule for HLS 5 verification symmetry:</p>
<p dir="auto">$$\text{CtoS Tag} = \text{GMAC}<em>{\text{GAK}}(\text{SystemTitle}</em>{\text{Client}} \parallel IC_{\text{Client}}, \text{AAD}<em>{\text{0x10}}, \text{StoC})$$<br />
$$\text{StoC Tag (Server Proof)} = \text{GMAC}</em>{\text{GAK}}(\text{SystemTitle}<em>{\text{Server}} \parallel IC</em>{\text{Server}}, \text{AAD}_{\text{0x10}}, \text{CtoS})$$</p>
<p dir="auto">Notice the perfect criss-cross symmetry between Challenge Originator and System Title Holder per DLMS Green Book Section 9.2.5.3.</p>
]]></description><link>https://dlms.sharur.org/post/176</link><guid isPermaLink="true">https://dlms.sharur.org/post/176</guid><dc:creator><![CDATA[david_miller]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:20:18 GMT</pubDate></item><item><title><![CDATA[Reply to Why does HLS 5 (GMAC) mutual authentication fail on Server Proof verification during StoC/CtoS challenge exchange? on Sat, 22 Aug 2026 17:20:15 GMT]]></title><description><![CDATA[<p dir="auto">David and Marcus, you hit the bullseye! I inspected our HES verification method, and we had two distinct bugs:</p>
<ol>
<li><strong>System Title Inversion</strong>: Our code was using <code>client.ciphering.systemTitle</code> to build the IV for both CtoS AND StoC verification, instead of using <code>server.systemTitle</code> (<code>4752580000000001</code> / <code>GRX00000001</code>) for the Server Proof!</li>
<li><strong>Challenge Inversion</strong>: We were hashing <code>StoC</code> against the server response, rather than our original <code>CtoS</code> challenge string.</li>
</ol>
<p dir="auto">Once we passed <code>serverSystemTitle</code> and <code>clientChallenge</code> into the AES-GCM GMAC validator, the computed tag matched <code>88 F0 1A 2B 3C 4D 99 11 22 33 44 55</code> with 0 bit errors!</p>
]]></description><link>https://dlms.sharur.org/post/175</link><guid isPermaLink="true">https://dlms.sharur.org/post/175</guid><dc:creator><![CDATA[alex_turner]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:20:15 GMT</pubDate></item><item><title><![CDATA[Reply to Why does HLS 5 (GMAC) mutual authentication fail on Server Proof verification during StoC/CtoS challenge exchange? on Sat, 22 Aug 2026 17:20:12 GMT]]></title><description><![CDATA[<p dir="auto">There is also the <strong>ACSE Service User Calling Authentication</strong> wrapper to verify.</p>
<p dir="auto">Per <strong>DLMS Green Book 10th Ed Section 9.3.4 (Association LN Class 15)</strong>, when HLS 5 is used, the <code>calling-authentication-value</code> in <code>AARQ</code> must use the <code>charstring</code> or <code>bitstring</code> choice with tag <code>[0]</code> (ACSE User Information = 14).</p>
<p dir="auto">If the HES transmits the initial <code>CtoS</code> challenge in <code>AARQ</code> with an incorrect length (e.g. 8 bytes vs 16 bytes), the meter's internal RNG pads the challenge with zeros, causing the Server Proof calculation to diverge from the client's expectation.</p>
]]></description><link>https://dlms.sharur.org/post/174</link><guid isPermaLink="true">https://dlms.sharur.org/post/174</guid><dc:creator><![CDATA[sarah_jenkins]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:20:12 GMT</pubDate></item><item><title><![CDATA[Reply to Why does HLS 5 (GMAC) mutual authentication fail on Server Proof verification during StoC/CtoS challenge exchange? on Sat, 22 Aug 2026 17:20:10 GMT]]></title><description><![CDATA[<p dir="auto">Let's look at the meter's returned Server Proof:<br />
<code>10 00 00 00 01 88 F0 1A 2B 3C 4D 99 11 22 33 44 55 66</code></p>
<p dir="auto">Dissecting the meter's proof:</p>
<ul>
<li><code>10</code>: Server Security Control byte</li>
<li><code>00 00 00 01</code>: Server Invocation Counter (<code>0x00000001</code>)</li>
<li><code>88 F0 1A 2B 3C 4D 99 11 22 33 44 55</code>: 12-byte Server GMAC Tag</li>
</ul>
<p dir="auto">Per <strong>IEC 62056-53 Section 8.4.2</strong> and <strong>DLMS Green Book Section 9.2.5.3.2</strong>, to verify this Server Proof, your client must execute:<br />
$$\text{IV} = \text{ServerSystemTitle} (8\text{B}) \parallel \text{ServerIC} (0x00000001)$$<br />
$$\text{AAD} = \text{0x10} \parallel \text{GAK}$$<br />
$$\text{Data} = \text{Client Challenge (CtoS extracted from AARQ)}$$</p>
<p dir="auto">If your client passed <code>StoC</code> instead of <code>CtoS</code> as the data payload during Server Proof verification, it fails immediately!</p>
]]></description><link>https://dlms.sharur.org/post/173</link><guid isPermaLink="true">https://dlms.sharur.org/post/173</guid><dc:creator><![CDATA[marcus_vance]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:20:10 GMT</pubDate></item><item><title><![CDATA[Reply to Why does HLS 5 (GMAC) mutual authentication fail on Server Proof verification during StoC/CtoS challenge exchange? on Sat, 22 Aug 2026 17:20:08 GMT]]></title><description><![CDATA[<p dir="auto">David's point regarding System Title directionality is 100% correct. Furthermore, check the <strong>Authentication Key (GAK)</strong> and <strong>Block Cipher Key (GUEK)</strong> separation:</p>
<p dir="auto">In DLMS Green Book Section 9.2.5.3, HLS 5 authentication strictly uses the <strong>Authentication Key (GAK)</strong> (e.g. <code>D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF</code>), NOT the Global Unicast Encryption Key (GUEK: <code>000102030405060708090A0B0C0D0E0F</code>).</p>
<p dir="auto">In your <code>Action-Request</code> hex:<br />
<code>10 00 00 00 01 1A 52 FE 7D D3 E7 27 48 97 3C 1E 28</code></p>
<ul>
<li><code>10</code>: Security Control (<code>0x10</code> = Global Key, Authenticated Only, Security Suite 1)</li>
<li><code>00 00 00 01</code>: Client Invocation Counter <code>1</code></li>
<li><code>1A 52 FE ...</code>: 12-byte GMAC tag.</li>
</ul>
<p dir="auto">Notice that <code>1A 52 FE 7D D3 E7 27 48 97 3C 1E 28</code> exactly matches the official <strong>Green Book Table 43</strong> test vector when StoC is <code>503677524A323146</code> and Client System Title is <code>4D4D4D0000000001</code>! This proves your client computed CtoS correctly, meaning the meter accepted it and incremented its own Invocation Counter to <code>1</code> for the Server Proof.</p>
]]></description><link>https://dlms.sharur.org/post/172</link><guid isPermaLink="true">https://dlms.sharur.org/post/172</guid><dc:creator><![CDATA[elena_rostova]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:20:08 GMT</pubDate></item><item><title><![CDATA[Reply to Why does HLS 5 (GMAC) mutual authentication fail on Server Proof verification during StoC/CtoS challenge exchange? on Sat, 22 Aug 2026 17:20:06 GMT]]></title><description><![CDATA[<p dir="auto">Alex, this is one of the most classic identity traps in DLMS Security Suite 1 implementation.</p>
<p dir="auto">Per <strong>DLMS Green Book 10th Ed Section 9.2.5.3 (High Level Security Mechanism 5)</strong> and <strong>Table 43 (HLS 5 Standard Test Vectors)</strong>, HLS 5 uses AES-GCM-128 authentication in two asymmetric directions:</p>
<ol>
<li><strong>Client to Server Proof (CtoS)</strong>:
<ul>
<li>Input challenge: <code>StoC</code> (generated by meter)</li>
<li>IV Construction: $\text{IV}_{\text{CtoS}} = \text{Client System Title (8B)} \parallel \text{Client Invocation Counter (4B)}$</li>
<li>AAD: $\text{Security Control (0x10)} \parallel \text{Authentication Key (GAK)}$</li>
</ul>
</li>
<li><strong>Server to Client Proof (StoC)</strong>:
<ul>
<li>Input challenge: <code>CtoS</code> (generated by client in <code>AARQ</code>)</li>
<li>IV Construction: $\text{IV}_{\text{StoC}} = \text{Server System Title (8B)} \parallel \text{Server Invocation Counter (4B)}$</li>
</ul>
</li>
</ol>
<p dir="auto">Look closely at how your HES client verifies the meter's response:<br />
If your client code re-used the <strong>Client System Title</strong> (or client IV) instead of extracting the <strong>Server System Title</strong> from the <code>AARE</code> response (<code>0x61</code>), the AES-GCM GHASH polynomial state will calculate a completely different tag!</p>
]]></description><link>https://dlms.sharur.org/post/171</link><guid isPermaLink="true">https://dlms.sharur.org/post/171</guid><dc:creator><![CDATA[david_miller]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:20:06 GMT</pubDate></item></channel></rss>