Skip to content

Commit

Permalink
Authentication via SPAKE2
Browse files Browse the repository at this point in the history
  • Loading branch information
Max Yakimakha authored and mfoltzgoogle committed Aug 21, 2019
1 parent b7fd6a4 commit 94d17d8
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 127 deletions.
112 changes: 36 additions & 76 deletions index.bs
Expand Up @@ -445,103 +445,63 @@ pre-shared key (PSK) ease of input for the user and supported PSK input methods.
The agent with the lowest PSK ease of input presents a PSK to the user when the agent
either sends or receives an authentication request. In case both agents have the same
PSK ease of input value, the server presents the PSK to the user. The same pre-shared key
is used by both agents to issue an authentication request.
is used by both agents. The agent presenting the PSK to the user is the PSK-presenter,
the agent requiring the user to input the PSK is the PSK-consumer.

PSK ease of input is an integer in the range from 0 to 100 inclusive, where 0 means
it is not possible for the user to input PSK on this device and 100 means
that it's easy for the user to input PSK on the device. Supported PSK input methods
are numeric and scanning a QR-code. Devices with non-zero PSK ease of input must
support the numeric PSK input method.

In order for one agent (the challenger) to authenticate another (the responder),
the challenger may send an authentication-request message and expect an
authentication-response message to be sent back from the responder. To
mutually authenticate, this mechanism is used twice, once by each side acting as
the challenger. This mechanism assumes the agents share a low-entropy secret,
such as a number or a short password that could be entered by a user on a
keyboard or TV remote control.

For all messages and objects defined in this section, see Appendix A for the full
CDDL definitions.

The challenger sends an auth-request-hkdf-scrypt-psk message with the following values:

- salt: 32 random bytes. This salt is used in HKDF, so see
https://tools.ietf.org/html/rfc5869#section-3.1 for more details on how this
value should be generated.

- cost: log base 2 of the cost parameter (N) for scrypt defined in [RFC
7914 section 2](https://tools.ietf.org/html/rfc7914#section-2). It must be
greater than or equal to 14 (to avoid being too weak) and less than or equal
to 128 (the limit defined by scrypt). A value of 15 is recommended (an
scrypt N of 2^15 or 32768).

The responder replies with an auth-response-hkdf-scrypt-psk-result message with
the following values:

- result: If the responder was able to calculate proof of possession of the
shared secret, and if it failed, why it failed.

- proof: The result of running the authentication mechanism. The steps for
hkdf-of-scrypt-of-psk are described below.

The challenger verifies the proof and sends the responder an auth-status message
with the following values:
The default authentication method is
[\SPAKE2](https://tools.ietf.org/html/draft-irtf-cfrg-spake2-08) with the following
cipher suite:

- result: If the challenger was able to authenticate the responder or not,
and if not, why not.
1. Elliptic curve is Curve25519
2. Hash function is SHA-512.
3. Key derivation function is HKDF.
4. Message authentication code is HMAC.
5. Password hash function is SHA-512.

The challenger must limit the time the responder has to send a response to 60
seconds (to avoid the possibility of brute-force attacks.)
Open Screen Protocol does not use a memory-hard hash function to hash PSKs
with SPAKE2 and uses SHA-512 instead as the PSK is one-time use and
is not stored in any form.

SPAKE2 provides explicit mutual authentication.

For hkdf-of-scrypt-of-psk, the proof is calculated using the following steps:

1. Let secret be the pre-shared secret.

2. Let N be 2 to the power of of the cost from the authentication-request
message.

3. Let r be 8.

4. Let p be 1.

5. Let keyLength be 32.

6. Let scryptResult be the result of running
[scrypt](https://tools.ietf.org/html/rfc7914) on secret with cost parameter N,
block size r, parallelization parameter p, and derived key length of
keyLength.

7. Let hashFunction be sha-256.
This authentication method assumes the agents share a low-entropy secret,
such as a number or a short password that could be entered by a user on a
phone, a keyboard or a TV remote control.

8. Let salt be the salt from the authentication-request message.
SPAKE2 is not symmetric and has two roles, Alice (A) and Bob (B).
The client acts as Alice, the server acts as Bob.

9. Let info be a 64-byte array containing certificate fingerprint pair with the following values:
The messages used in this authentication method are: auth-spake2-need-psk,
auth-spake2-message, auth-spake2-confirmation and auth-status.
[\SPAKE2](https://tools.ietf.org/html/draft-irtf-cfrg-spake2-08) describes in detail
how auth-spake2-message and auth-spake2-confirmation are computed.

- Bytes 0-31 of the array are the challenger's fingerprint: The result of running
sha-256 on the Distinguished Encoding Rules (DER) form (see
https://tools.ietf.org/html/rfc8122#section-5) of the certificate used by
the challenger in the QUIC crypto handshake during connection establishment.
If the PSK-presenter wants to perform authentication, the PSK-presenter
starts authentication process by presenting the PSK to the user and sending
auth-spake2-message message.

- Bytes 32-63 of the array are the responder's fingerprint: The result of running
sha-256 on the Distinguished Encoding Rules (DER) form (see
https://tools.ietf.org/html/rfc8122#section-5) of the certificate used by
the responder in the QUIC crypto handshake during connection establishment.
If the PSK-consumer wants to perform authentication, the PSK-consumer
sends auth-spake2-need-psk message to the PSK-presenter to start authentication
process. After the user inputs the PSK into the PSK-consumer,
the PSK-consumer computes and sends auth-spake2-message.

9. Let proof be the result of running
[\HKDF](https://tools.ietf.org/html/rfc5869) on scryptResult with
both the extract and expand steps, hash function hashFunction,
application-specific info, and output key length keyLength.
If the PSK-presenter receives a auth-spake2-need-psk message after starting authentication
from their side, the PSK-presenter ignores the auth-spake2-need-psk message.

To verify that the responder's proof is correct, the challenger makes the same
calculation of the proof and compares the result. If the results are the same,
the challenger considers the responder authenticated, and considers it
unauthenticated otherwise.
When either agent knows PSK and has received a auth-spake2-message message,
the agent computes and sends a auth-spake2-confirmation message.

Note: the values of 32 above (for salt length, keyLength) are based on the
output size of sha-256. If a different hash mechanism is used in the future,
these values should be updated as well.
When either agent has received both auth-spake2-message and auth-spake2-confirmation messages,
the agent validates the confirmation message and sends the auth-status authenticated message.

Control Protocols {#control-protocols}
============================
Expand Down
37 changes: 16 additions & 21 deletions messages_appendix.cddl
Expand Up @@ -42,37 +42,32 @@ request-id = uint

microseconds = uint

; type key 104
; type key 1001
auth-capabilities = {
0: uint ; psk-ease-of-input
1: [* psk-input-method] ; psk-input-methods
}

; type key 105
auth-request-hkdf-scrypt-psk = {
request
1 : bytes .size 32 ; salt
2 : uint ; cost
psk-input-method = &(
numeric: 0
qr-code: 1
)

; type key 1002
auth-spake2-need-psk = {
}

; type key 106
auth-response-hkdf-scrypt-psk = {
response
1 : auth-response-hkdf-scrypt-psk-result ; result
2 : bytes .size 32 ; proof
; type key 1003
auth-spake2-message = {
1 : bytes .size 32 ; message
}

auth-response-hkdf-scrypt-psk-result = &(
success: 0
unknown-error: 1
timeout: 2
secret-unknown: 3
calculation-took-too-long : 4
cost-too-low: 5
cost-too-high: 6
)
; type key 1004
auth-spake2-confirmation = {
1 : bytes .size 32 ; confirmation
}

; type key 107
; type key 1005
auth-status = {
1 : auth-status-result ; result
}
Expand Down
49 changes: 19 additions & 30 deletions messages_appendix.html
Expand Up @@ -43,30 +43,31 @@
<span class="nx">microseconds </span><span class="p">=</span> <span class="kt">uint</span>

<span class="c1">; type key 1001</span>
<span class="nx">auth-request-hkdf-scrypt-psk </span><span class="p">=</span> <span class="p">{</span>
<span class="nx">request</span>
<span class="nx"> 1 </span><span class="p">:</span> <span class="nx">bytes .size 32 </span><span class="c1">; salt</span>
<span class="mi">2</span> <span class="p">:</span> <span class="kt">uint</span> <span class="c1">; cost</span>
<span class="nx">auth-capabilities </span><span class="p">=</span> <span class="p">{</span>
<span class="mi">0</span><span class="p">:</span> <span class="kt">uint</span> <span class="c1">; psk-ease-of-input</span>
<span class="mi">1</span><span class="p">:</span> <span class="p">[</span><span class="o">*</span> <span class="nx">psk-input-method</span><span class="p">]</span> <span class="c1">; psk-input-methods</span>
<span class="p">}</span>

<span class="nx">psk-input-method </span><span class="p">=</span> <span class="o">&amp;</span><span class="p">(</span>
<span class="nx">numeric</span><span class="p">:</span> <span class="mi">0</span>
<span class="nx">qr-code</span><span class="p">:</span> <span class="mi">1</span>
<span class="p">)</span>

<span class="c1">; type key 1002</span>
<span class="nx">auth-response-hkdf-scrypt-psk </span><span class="p">=</span> <span class="p">{</span>
<span class="nx">response</span>
<span class="nx"> 1 </span><span class="p">:</span> <span class="nx">auth-response-hkdf-scrypt-psk-result </span><span class="c1">; result</span>
<span class="mi">2</span> <span class="p">:</span> <span class="nx">bytes .size 32 </span><span class="c1">; proof</span>
<span class="nx">auth-spake2-need-psk </span><span class="p">=</span> <span class="p">{</span>
<span class="p">}</span>

<span class="nx">auth-response-hkdf-scrypt-psk-result </span><span class="p">=</span> <span class="o">&amp;</span><span class="p">(</span>
<span class="nx">success</span><span class="p">:</span> <span class="mi">0</span>
<span class="nx">unknown-error</span><span class="p">:</span> <span class="mi">1</span>
<span class="nx">timeout</span><span class="p">:</span> <span class="mi">2</span>
<span class="nx">secret-unknown</span><span class="p">:</span> <span class="mi">3</span>
<span class="nx">calculation-took-too-long </span><span class="p">:</span> <span class="mi">4</span>
<span class="nx">cost-too-low</span><span class="p">:</span> <span class="mi">5</span>
<span class="nx">cost-too-high</span><span class="p">:</span> <span class="mi">6</span>
<span class="p">)</span>

<span class="c1">; type key 1003</span>
<span class="nx">auth-spake2-message </span><span class="p">=</span> <span class="p">{</span>
<span class="mi">1</span> <span class="p">:</span> <span class="nx">bytes .size 32 </span><span class="c1">; message</span>
<span class="p">}</span>

<span class="c1">; type key 1004</span>
<span class="nx">auth-spake2-confirmation </span><span class="p">=</span> <span class="p">{</span>
<span class="mi">1</span> <span class="p">:</span> <span class="nx">bytes .size 32 </span><span class="c1">; confirmation</span>
<span class="p">}</span>

<span class="c1">; type key 1005</span>
<span class="nx">auth-status </span><span class="p">=</span> <span class="p">{</span>
<span class="mi">1</span> <span class="p">:</span> <span class="nx">auth-status-result </span><span class="c1">; result</span>
<span class="p">}</span>
Expand All @@ -80,18 +81,6 @@
<span class="nx">proof-invalid</span><span class="p">:</span> <span class="mi">5</span>
<span class="p">)</span>

<span class="c1">; type key 1004</span>
<span class="nx">auth-capabilities </span><span class="p">=</span> <span class="p">{</span>
<span class="mi">0</span><span class="p">:</span> <span class="kt">uint</span> <span class="c1">; psk-ease-of-input</span>
<span class="mi">1</span><span class="p">:</span> <span class="p">[</span><span class="o">*</span> <span class="nx">psk-input-method</span><span class="p">]</span> <span class="c1">; psk-input-methods</span>
<span class="p">}</span>

<span class="nx">psk-input-method </span><span class="p">=</span> <span class="o">&amp;</span><span class="p">(</span>
<span class="nx">numeric</span><span class="p">:</span> <span class="mi">0</span>
<span class="nx">alphanumeric</span><span class="p">:</span> <span class="mi">1</span>
<span class="nx">qr-code</span><span class="p">:</span> <span class="mi">2</span>
<span class="p">)</span>

<span class="c1">; type key 14</span>
<span class="nx">presentation-url-availability-request </span><span class="p">=</span> <span class="p">{</span>
<span class="nx">request</span>
Expand Down

0 comments on commit 94d17d8

Please sign in to comment.