Skip to content

Commit 4185aab

Browse files
committed
Add SPAKE2+ password authenticated key exchange (RFC 9383)
1 parent 3e1175b commit 4185aab

17 files changed

Lines changed: 3793 additions & 3 deletions

File tree

doc/api_ref/contents.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ API Reference
2424
keywrap
2525
passhash
2626
cryptobox
27+
spake2p
2728
srp
2829
psk_db
2930
filters

doc/api_ref/ffi.rst

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2435,6 +2435,175 @@ All available value types of the generic X.509 object getters are:
24352435
The URLs of the issuing CA certificate of a certificate as a character array.
24362436
There might be more than one such URL defined in a certificate.
24372437

2438+
SPAKE2+ Password Authenticated Key Exchange
2439+
--------------------------------------------
2440+
2441+
.. versionadded:: 3.13.0
2442+
2443+
An implementation of the SPAKE2+ password authenticated key exchange
2444+
(RFC 9383). The *prover* knows the password itself, while the *verifier*
2445+
stores only a registration record derived from the password. See
2446+
:doc:`spake2p` for a description of the protocol and the expected
2447+
message flow.
2448+
2449+
The identity, salt, and context parameters of these functions may be null,
2450+
if the corresponding length is zero. Since the lengths of the outputs vary
2451+
with the system parameters, all outputs are produced using view callbacks.
2452+
2453+
.. cpp:type:: opaque* botan_spake2p_params_t
2454+
2455+
An opaque data type for SPAKE2+ system parameters, which select the
2456+
elliptic curve group, the SPAKE2+ M/N group elements, and the hash
2457+
function. Objects created from the system parameters hold their own
2458+
copy, so the parameters may be destroyed at any time.
2459+
2460+
.. cpp:function:: int botan_spake2p_params_init(botan_spake2p_params_t* params, const char* ciphersuite)
2461+
2462+
Create system parameters from an RFC 9383 ciphersuite name, one of
2463+
"P256-SHA256", "P256-SHA512", "P384-SHA256", "P384-SHA512", or
2464+
"P521-SHA512", all using HMAC key confirmation.
2465+
2466+
.. cpp:function:: int botan_spake2p_params_init_custom(botan_spake2p_params_t* params, \
2467+
botan_ec_group_t group, const uint8_t seed[], size_t seed_len, \
2468+
const char* hash_fn)
2469+
2470+
Create custom system parameters for an arbitrary group, deriving the
2471+
M/N group elements from the seed using hash to curve; returns
2472+
``BOTAN_FFI_ERROR_NOT_IMPLEMENTED`` if the group does not support hash
2473+
to curve. Both peers must use the same group, seed, and hash.
2474+
2475+
.. cpp:function:: int botan_spake2p_params_destroy(botan_spake2p_params_t params)
2476+
2477+
Destroy an object.
2478+
2479+
.. cpp:function:: int botan_spake2p_params_share_size(botan_spake2p_params_t params, size_t* share_size)
2480+
2481+
Return the size in bytes of a key share (shareP or shareV).
2482+
2483+
.. cpp:function:: int botan_spake2p_params_confirmation_size(botan_spake2p_params_t params, size_t* confirmation_size)
2484+
2485+
Return the size in bytes of a key confirmation message (confirmP or confirmV).
2486+
2487+
.. cpp:function:: int botan_spake2p_derive_secret(botan_spake2p_params_t params, \
2488+
const char* password, \
2489+
const uint8_t prover_id[], size_t prover_id_len, \
2490+
const uint8_t verifier_id[], size_t verifier_id_len, \
2491+
const uint8_t salt[], size_t salt_len, \
2492+
botan_view_ctx ctx, botan_view_bin_fn view)
2493+
2494+
Derive a prover secret (w0 and w1) from a password, using Argon2id.
2495+
The view callback is invoked with the serialized prover secret, which
2496+
is password equivalent and must be protected accordingly. It is used
2497+
with ``botan_spake2p_registration_record`` and
2498+
``botan_spake2p_prover_init``.
2499+
2500+
.. cpp:function:: int botan_spake2p_registration_record(botan_spake2p_params_t params, \
2501+
botan_rng_t rng, const uint8_t secret[], size_t secret_len, \
2502+
botan_view_ctx ctx, botan_view_bin_fn view)
2503+
2504+
Compute a registration record (w0 and L) from a serialized prover
2505+
secret. The record is provided to the verifier during registration.
2506+
While it does not allow directly impersonating the prover, it does
2507+
allow offline password guessing attacks, so it should be protected.
2508+
2509+
.. cpp:type:: opaque* botan_spake2p_prover_t
2510+
2511+
An opaque data type for a SPAKE2+ prover.
2512+
2513+
.. cpp:function:: int botan_spake2p_prover_init(botan_spake2p_prover_t* prover, \
2514+
botan_spake2p_params_t params, \
2515+
const uint8_t secret[], size_t secret_len, \
2516+
const uint8_t prover_id[], size_t prover_id_len, \
2517+
const uint8_t verifier_id[], size_t verifier_id_len, \
2518+
const uint8_t context[], size_t context_len)
2519+
2520+
Initialize a prover from a serialized prover secret. The identities
2521+
and context must be agreed upon by both parties; the identities must
2522+
additionally match the values used when deriving the prover secret.
2523+
2524+
.. cpp:function:: int botan_spake2p_prover_destroy(botan_spake2p_prover_t prover)
2525+
2526+
Destroy an object.
2527+
2528+
.. cpp:function:: int botan_spake2p_prover_generate_message(botan_spake2p_prover_t prover, \
2529+
botan_rng_t rng, botan_view_ctx ctx, botan_view_bin_fn view)
2530+
2531+
Generate the prover's key share (shareP), which is sent to the
2532+
verifier. This can be called only once per prover object.
2533+
2534+
.. cpp:function:: int botan_spake2p_prover_process_message(botan_spake2p_prover_t prover, \
2535+
botan_rng_t rng, const uint8_t peer_message[], size_t peer_message_len, \
2536+
botan_view_ctx ctx, botan_view_bin_fn view)
2537+
2538+
Consume the verifier's response (shareV followed by confirmV) and
2539+
produce the prover's key confirmation (confirmP), which is sent to the
2540+
verifier. Returns ``BOTAN_FFI_ERROR_BAD_MAC`` if the verifier's key
2541+
confirmation is wrong, typically meaning the passwords do not match.
2542+
2543+
.. cpp:function:: int botan_spake2p_prover_shared_secret(botan_spake2p_prover_t prover, \
2544+
botan_view_ctx ctx, botan_view_bin_fn view)
2545+
2546+
Return the shared secret (K_shared). This may be called only after
2547+
``botan_spake2p_prover_process_message`` has succeeded.
2548+
2549+
.. cpp:type:: opaque* botan_spake2p_verifier_t
2550+
2551+
An opaque data type for a SPAKE2+ verifier.
2552+
2553+
.. cpp:function:: int botan_spake2p_verifier_init(botan_spake2p_verifier_t* verifier, \
2554+
botan_spake2p_params_t params, \
2555+
const uint8_t record[], size_t record_len, \
2556+
const uint8_t prover_id[], size_t prover_id_len, \
2557+
const uint8_t verifier_id[], size_t verifier_id_len, \
2558+
const uint8_t context[], size_t context_len)
2559+
2560+
Initialize a verifier from a serialized registration record. See
2561+
``botan_spake2p_prover_init`` for the requirements on the identities
2562+
and context.
2563+
2564+
.. cpp:function:: int botan_spake2p_verifier_destroy(botan_spake2p_verifier_t verifier)
2565+
2566+
Destroy an object.
2567+
2568+
.. cpp:function:: int botan_spake2p_verifier_process_message(botan_spake2p_verifier_t verifier, \
2569+
botan_rng_t rng, const uint8_t peer_message[], size_t peer_message_len, \
2570+
botan_view_ctx ctx, botan_view_bin_fn view)
2571+
2572+
Consume the prover's key share (shareP) and produce the verifier's
2573+
response (shareV followed by confirmV), which is sent to the prover.
2574+
This can be called only once per verifier object.
2575+
2576+
.. cpp:function:: int botan_spake2p_verifier_verify_confirmation(botan_spake2p_verifier_t verifier, \
2577+
const uint8_t confirmation[], size_t confirmation_len)
2578+
2579+
Check the prover's key confirmation (confirmP). Returns
2580+
``BOTAN_FFI_ERROR_BAD_MAC`` if the confirmation is wrong, meaning the
2581+
prover does not know the password.
2582+
2583+
.. cpp:function:: int botan_spake2p_verifier_skip_confirmation(botan_spake2p_verifier_t verifier)
2584+
2585+
Can be called after ``botan_spake2p_verifier_process_message``, in
2586+
place of ``botan_spake2p_verifier_verify_confirmation``, to allow
2587+
extracting the shared secret without having checked the prover's key
2588+
confirmation.
2589+
2590+
.. warning::
2591+
2592+
After calling this, nothing is known about the peer; only a prover
2593+
which knows the password can compute the same shared secret, but no
2594+
evidence of this has been received. It is intended solely for
2595+
protocols which embed SPAKE2+ and perform the prover's key
2596+
confirmation themselves, such as the proposed PAKE extension for
2597+
TLS 1.3, where the TLS handshake takes the place of confirmP.
2598+
Anywhere else, use ``botan_spake2p_verifier_verify_confirmation``.
2599+
2600+
.. cpp:function:: int botan_spake2p_verifier_shared_secret(botan_spake2p_verifier_t verifier, \
2601+
botan_view_ctx ctx, botan_view_bin_fn view)
2602+
2603+
Return the shared secret (K_shared). This may be called only after
2604+
``botan_spake2p_verifier_verify_confirmation`` has succeeded, or after
2605+
``botan_spake2p_verifier_skip_confirmation``.
2606+
24382607
ZFEC (Forward Error Correction)
24392608
----------------------------------------
24402609

doc/api_ref/python.rst

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,99 @@ HOTP
723723
in. If the code did verify and resync_range was zero, then the
724724
next counter will always be counter+1.
725725
726+
SPAKE2+
727+
-----------------------------------------
728+
.. versionadded:: 3.13.0
729+
730+
An implementation of the SPAKE2+ password authenticated key exchange
731+
(RFC 9383). The prover knows the password itself, while the verifier
732+
stores only a registration record derived from the password.
733+
734+
.. py:class:: Spake2pParams(ciphersuite)
735+
736+
The system parameters, selecting the elliptic curve group, the SPAKE2+
737+
M/N group elements, and the hash function. The ciphersuite is one of
738+
"P256-SHA256", "P256-SHA512", "P384-SHA256", "P384-SHA512", or
739+
"P521-SHA512".
740+
741+
.. py:classmethod:: custom(group, seed, hash_fn)
742+
743+
Create custom system parameters for an arbitrary ``ECGroup``,
744+
deriving the M/N group elements from the seed using hash to curve
745+
(which not all groups support). Both peers must use the same group,
746+
seed, and hash.
747+
748+
.. py:method:: share_size()
749+
750+
Return the size in bytes of a key share.
751+
752+
.. py:method:: confirmation_size()
753+
754+
Return the size in bytes of a key confirmation message.
755+
756+
.. py:function:: spake2p_derive_secret(params, password, prover_id=b'', verifier_id=b'', salt=b'')
757+
758+
Derive the prover secret from a password, using Argon2id. The returned
759+
secret is password equivalent, and must be protected accordingly.
760+
761+
.. py:function:: spake2p_registration_record(params, secret, rng)
762+
763+
Compute the registration record for a prover secret, which is provided
764+
to the verifier during registration.
765+
766+
.. py:class:: Spake2pProver(params, secret, prover_id=b'', verifier_id=b'', context=b'')
767+
768+
The identities and context must be agreed upon by both parties; the
769+
identities must additionally match the values used when deriving the
770+
prover secret.
771+
772+
.. py:method:: generate_message(rng)
773+
774+
Generate the prover's key share, which is sent to the verifier.
775+
Can be called only once.
776+
777+
.. py:method:: process_message(peer_message, rng)
778+
779+
Consume the verifier's response and return the prover's key
780+
confirmation, which is sent to the verifier. Raises an exception if
781+
the verifier's key confirmation is wrong, typically meaning the
782+
passwords do not match.
783+
784+
.. py:method:: shared_secret()
785+
786+
Return the shared secret. Only valid after ``process_message``
787+
succeeded.
788+
789+
.. py:class:: Spake2pVerifier(params, record, prover_id=b'', verifier_id=b'', context=b'')
790+
791+
The verifier side of the exchange, using the registration record.
792+
793+
.. py:method:: process_message(peer_message, rng)
794+
795+
Consume the prover's key share and return the verifier's response
796+
(its own key share followed by a key confirmation), which is sent to
797+
the prover. Can be called only once.
798+
799+
.. py:method:: verify_confirmation(confirmation)
800+
801+
Check the prover's key confirmation. Raises an exception if the
802+
confirmation is wrong, meaning the prover does not know the
803+
password.
804+
805+
.. py:method:: skip_confirmation()
806+
807+
Skip checking the prover's key confirmation, allowing
808+
``shared_secret`` to be called without ``verify_confirmation``.
809+
After calling this, no evidence has been received that the peer
810+
knows the password; it is intended solely for protocols which
811+
embed SPAKE2+ and perform the prover's key confirmation
812+
themselves.
813+
814+
.. py:method:: shared_secret()
815+
816+
Return the shared secret. Only valid after ``verify_confirmation``
817+
succeeded, or after ``skip_confirmation``.
818+
726819
X509Cert
727820
-----------------------------------------
728821

0 commit comments

Comments
 (0)