| /* |
| * Copyright (c) 2024 Project CHIP Authors |
| * All rights reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #pragma once |
| |
| #include "CHIPCryptoPAL.h" |
| |
| #include <psa/crypto.h> |
| |
| namespace chip { |
| namespace Crypto { |
| |
| /** |
| * The below class implements the draft 01 version of the Spake2+ protocol as |
| * defined in https://www.ietf.org/id/draft-bar-cfrg-spake2plus-01.html. |
| * |
| * The following describes the protocol flows: |
| * |
| * Commissioner Accessory |
| * ------------ --------- |
| * |
| * Init |
| * BeginProver |
| * ComputeRoundOne -------------> |
| * Init |
| * BeginVerifier |
| * /- ComputeRoundOne |
| * <------------- ComputeRoundTwo |
| * ComputeRoundTwo -------------> |
| * KeyConfirm KeyConfirm |
| * GetKeys GetKeys |
| * |
| **/ |
| class PSASpake2p_P256_SHA256_HKDF_HMAC |
| { |
| public: |
| /** |
| * @brief Initialize Spake2+ with some context specific information. |
| * |
| * @param context The context is arbitrary but should include information about the |
| * protocol being run, contain the transcript for negotiation, include |
| * the PKBDF parameters, etc. |
| * @param context_len The length of the context. |
| * |
| * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise |
| **/ |
| CHIP_ERROR Init(const uint8_t * context, size_t context_len); |
| |
| /** |
| * @brief Free Spake2+ underlying objects. |
| **/ |
| void Clear(); |
| |
| /** |
| * @brief Start the Spake2+ process as a verifier (i.e. an accessory being provisioned). |
| * |
| * @param my_identity The verifier identity. May be NULL if identities are not established. |
| * @param my_identity_len The verifier identity length. |
| * @param peer_identity The peer identity. May be NULL if identities are not established. |
| * @param peer_identity_len The peer identity length. |
| * @param w0in The input w0 (a parameter baked into the device or computed with ComputeW0). |
| * @param w0in_len The input w0 length. |
| * @param Lin The input L (a parameter baked into the device or computed with ComputeL). |
| * @param Lin_len The input L length. |
| * |
| * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise |
| **/ |
| CHIP_ERROR BeginVerifier(const uint8_t * my_identity, size_t my_identity_len, const uint8_t * peer_identity, |
| size_t peer_identity_len, const uint8_t * w0in, size_t w0in_len, const uint8_t * Lin, size_t Lin_len); |
| |
| /** |
| * @brief Start the Spake2+ process as a prover (i.e. a commissioner). |
| * |
| * @param my_identity The prover identity. May be NULL if identities are not established. |
| * @param my_identity_len The prover identity length. |
| * @param peer_identity The peer identity. May be NULL if identities are not established. |
| * @param peer_identity_len The peer identity length. |
| * @param w0sin The input w0s (an output from the PBKDF). |
| * @param w0sin_len The input w0s length. |
| * @param w1sin The input w1s (an output from the PBKDF). |
| * @param w1sin_len The input w1s length. |
| * |
| * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise |
| **/ |
| CHIP_ERROR BeginProver(const uint8_t * my_identity, size_t my_identity_len, const uint8_t * peer_identity, |
| size_t peer_identity_len, const uint8_t * w0sin, size_t w0sin_len, const uint8_t * w1sin, |
| size_t w1sin_len); |
| |
| /** |
| * @brief Compute the first round of the protocol. |
| * |
| * @param pab X value from commissioner. |
| * @param pab_len X length. |
| * @param out The output first round Spake2+ contribution. |
| * @param out_len The output first round Spake2+ contribution length. |
| * |
| * The out_len parameter is expected to point to an integer that holds |
| * the size of the buffer to put the first round Spake2+ contribution. |
| * After successful execution of this method, the variable is set to the |
| * actual size of the generated output. |
| * |
| * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise |
| **/ |
| CHIP_ERROR ComputeRoundOne(const uint8_t * pab, size_t pab_len, uint8_t * out, size_t * out_len); |
| |
| /** |
| * @brief Compute the second round of the protocol. |
| * |
| * @param in The peer first round Spake2+ contribution. |
| * @param in_len The peer first round Spake2+ contribution length. |
| * @param out The output second round Spake2+ contribution. |
| * @param out_len The output second round Spake2+ contribution length. |
| * |
| * The out_len parameter is expected to point to an integer that holds |
| * the size of the buffer to put the second round Spake2+ contribution. |
| * After successful execution of this method, the variable is set to the |
| * actual size of the generated output. |
| * |
| * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise |
| **/ |
| CHIP_ERROR ComputeRoundTwo(const uint8_t * in, size_t in_len, uint8_t * out, size_t * out_len); |
| |
| /** |
| * @brief Confirm that each party computed the same keys. |
| * |
| * @param in The peer second round Spake2+ contribution. |
| * @param in_len The peer second round Spake2+ contribution length. |
| * |
| * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise |
| **/ |
| CHIP_ERROR KeyConfirm(const uint8_t * in, size_t in_len); |
| |
| /** |
| * @brief Return the shared secret. |
| * |
| * @param out The output secret. |
| * @param out_len The output secret length. |
| * |
| * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise |
| **/ |
| CHIP_ERROR GetKeys(SessionKeystore & keystore, HkdfKeyHandle & key); |
| |
| private: |
| psa_pake_operation_t mOperation = PSA_PAKE_OPERATION_INIT; |
| psa_key_id_t mKey = PSA_KEY_ID_NULL; |
| |
| psa_pake_role_t mRole; |
| uint8_t mContext[kSHA256_Hash_Length]; |
| size_t mContextLen; |
| }; |
| |
| } // namespace Crypto |
| } // namespace chip |