Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / crypto / CHIPCryptoPAL.h
1 /*
2  *
3  *    Copyright (c) 2020 Project CHIP Authors
4  *
5  *    Licensed under the Apache License, Version 2.0 (the "License");
6  *    you may not use this file except in compliance with the License.
7  *    You may obtain a copy of the License at
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *    Unless required by applicable law or agreed to in writing, software
12  *    distributed under the License is distributed on an "AS IS" BASIS,
13  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *    See the License for the specific language governing permissions and
15  *    limitations under the License.
16  */
17
18 /**
19  *    @file
20  *      Header that exposes the platform agnostic CHIP crypto primitives
21  */
22
23 #ifndef _CHIP_CRYPTO_PAL_H_
24 #define _CHIP_CRYPTO_PAL_H_
25
26 #if CHIP_HAVE_CONFIG_H
27 #include <crypto/CryptoBuildConfig.h>
28 #endif
29
30 #include <core/CHIPError.h>
31 #include <support/CodeUtils.h>
32
33 #include <stddef.h>
34 #include <string.h>
35
36 namespace chip {
37 namespace Crypto {
38
39 const size_t kP256_FE_Length     = 32;
40 const size_t kP256_Point_Length  = (2 * kP256_FE_Length + 1);
41 const size_t kSHA256_Hash_Length = 32;
42
43 const size_t kMax_ECDH_Secret_Length     = kP256_FE_Length;
44 const size_t kMax_ECDSA_Signature_Length = 72;
45 const size_t kMAX_FE_Length              = kP256_FE_Length;
46 const size_t kMAX_Point_Length           = kP256_Point_Length;
47 const size_t kMAX_Hash_Length            = kSHA256_Hash_Length;
48 const size_t kMAX_CSR_Length             = 512;
49
50 const size_t kMin_Salt_Length = 8;
51 const size_t kMax_Salt_Length = 16;
52
53 const size_t kP256_PrivateKey_Length = 32;
54 const size_t kP256_PublicKey_Length  = 65;
55
56 /* These sizes are hardcoded here to remove header dependency on underlying crypto library
57  * in a public interface file. The validity of these sizes is verified by static_assert in
58  * the implementation files.
59  */
60 const size_t kMAX_Spake2p_Context_Size     = 1024;
61 const size_t kMAX_Hash_SHA256_Context_Size = 296;
62 const size_t kMAX_P256Keypair_Context_Size = 512;
63
64 /**
65  * Spake2+ parameters for P256
66  * Defined in https://www.ietf.org/id/draft-bar-cfrg-spake2plus-01.html#name-ciphersuites
67  */
68 const uint8_t spake2p_M_p256[65] = {
69     0x04, 0x88, 0x6e, 0x2f, 0x97, 0xac, 0xe4, 0x6e, 0x55, 0xba, 0x9d, 0xd7, 0x24, 0x25, 0x79, 0xf2, 0x99,
70     0x3b, 0x64, 0xe1, 0x6e, 0xf3, 0xdc, 0xab, 0x95, 0xaf, 0xd4, 0x97, 0x33, 0x3d, 0x8f, 0xa1, 0x2f, 0x5f,
71     0xf3, 0x55, 0x16, 0x3e, 0x43, 0xce, 0x22, 0x4e, 0x0b, 0x0e, 0x65, 0xff, 0x02, 0xac, 0x8e, 0x5c, 0x7b,
72     0xe0, 0x94, 0x19, 0xc7, 0x85, 0xe0, 0xca, 0x54, 0x7d, 0x55, 0xa1, 0x2e, 0x2d, 0x20,
73 };
74 const uint8_t spake2p_N_p256[65] = {
75     0x04, 0xd8, 0xbb, 0xd6, 0xc6, 0x39, 0xc6, 0x29, 0x37, 0xb0, 0x4d, 0x99, 0x7f, 0x38, 0xc3, 0x77, 0x07,
76     0x19, 0xc6, 0x29, 0xd7, 0x01, 0x4d, 0x49, 0xa2, 0x4b, 0x4f, 0x98, 0xba, 0xa1, 0x29, 0x2b, 0x49, 0x07,
77     0xd6, 0x0a, 0xa6, 0xbf, 0xad, 0xe4, 0x50, 0x08, 0xa6, 0x36, 0x33, 0x7f, 0x51, 0x68, 0xc6, 0x4d, 0x9b,
78     0xd3, 0x60, 0x34, 0x80, 0x8c, 0xd5, 0x64, 0x49, 0x0b, 0x1e, 0x65, 0x6e, 0xdb, 0xe7,
79 };
80
81 /**
82  * Spake2+ state machine to ensure proper execution of the protocol.
83  */
84 enum class CHIP_SPAKE2P_STATE : uint8_t
85 {
86     PREINIT = 0, // Before any initialization
87     INIT,        // First initialization
88     STARTED,     // Prover & Verifier starts
89     R1,          // Round one complete
90     R2,          // Round two complete
91     KC,          // Key confirmation complete
92 };
93
94 /**
95  * Spake2+ role.
96  */
97 enum class CHIP_SPAKE2P_ROLE : uint8_t
98 {
99     VERIFIER = 0, // Accessory
100     PROVER   = 1, // Commissioner
101 };
102
103 enum class SupportedECPKeyTypes : uint8_t
104 {
105     ECP256R1 = 0,
106 };
107
108 template <typename Sig>
109 class ECPKey
110 {
111 public:
112     virtual ~ECPKey() {}
113     virtual SupportedECPKeyTypes Type() const = 0;
114     virtual size_t Length() const             = 0;
115     virtual operator const uint8_t *() const  = 0;
116     virtual operator uint8_t *()              = 0;
117
118     virtual CHIP_ERROR ECDSA_validate_msg_signature(const uint8_t * msg, const size_t msg_length, const Sig & signature) const
119     {
120         return CHIP_ERROR_NOT_IMPLEMENTED;
121     }
122     virtual CHIP_ERROR ECDSA_validate_hash_signature(const uint8_t * hash, const size_t hash_length, const Sig & signature) const
123     {
124         return CHIP_ERROR_NOT_IMPLEMENTED;
125     }
126 };
127
128 template <size_t Cap>
129 class CapacityBoundBuffer
130 {
131 public:
132     /** @brief Set current length of the buffer that's being used
133      * @return Returns error if new length is > capacity
134      **/
135     CHIP_ERROR SetLength(size_t len)
136     {
137         CHIP_ERROR error = CHIP_NO_ERROR;
138         VerifyOrExit(len <= sizeof(bytes), error = CHIP_ERROR_INVALID_ARGUMENT);
139         length = len;
140     exit:
141         return error;
142     }
143
144     /** @brief Returns current length of the buffer that's being used
145      * @return Returns 0 if SetLength() was never called
146      **/
147     size_t Length() const { return length; }
148
149     /** @brief Returns max capacity of the buffer
150      **/
151     size_t Capacity() const { return sizeof(bytes); }
152
153     /** @brief Returns buffer pointer
154      **/
155     operator uint8_t *() { return bytes; }
156     operator const uint8_t *() const { return bytes; }
157
158 private:
159     uint8_t bytes[Cap];
160     size_t length = 0;
161 };
162
163 typedef CapacityBoundBuffer<kMax_ECDSA_Signature_Length> P256ECDSASignature;
164
165 typedef CapacityBoundBuffer<kMax_ECDH_Secret_Length> P256ECDHDerivedSecret;
166
167 class P256PublicKey : public ECPKey<P256ECDSASignature>
168 {
169 public:
170     SupportedECPKeyTypes Type() const override { return SupportedECPKeyTypes::ECP256R1; }
171     size_t Length() const override { return kP256_PublicKey_Length; }
172     operator uint8_t *() override { return bytes; }
173     operator const uint8_t *() const override { return bytes; }
174
175     CHIP_ERROR ECDSA_validate_msg_signature(const uint8_t * msg, size_t msg_length,
176                                             const P256ECDSASignature & signature) const override;
177     CHIP_ERROR ECDSA_validate_hash_signature(const uint8_t * hash, size_t hash_length,
178                                              const P256ECDSASignature & signature) const override;
179
180 private:
181     uint8_t bytes[kP256_PublicKey_Length];
182 };
183
184 template <typename PK, typename Secret, typename Sig>
185 class ECPKeypair
186 {
187 public:
188     virtual ~ECPKeypair() {}
189
190     /** @brief Generate a new Certificate Signing Request (CSR).
191      * @param csr Newly generated CSR
192      * @param csr_length The caller provides the length of input buffer (csr). The function returns the actual length of generated
193      *CSR.
194      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
195      **/
196     virtual CHIP_ERROR NewCertificateSigningRequest(uint8_t * csr, size_t & csr_length) = 0;
197
198     /**
199      * @brief A function to sign a msg using ECDSA
200      * @param msg Message that needs to be signed
201      * @param msg_length Length of message
202      * @param out_signature Buffer that will hold the output signature. The signature consists of: 2 EC elements (r and s),
203      *represented as ASN.1 DER integers, plus the ASN.1 sequence Header
204      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
205      **/
206     virtual CHIP_ERROR ECDSA_sign_msg(const uint8_t * msg, size_t msg_length, Sig & out_signature) = 0;
207
208     /**
209      * @brief A function to sign a hash using ECDSA
210      * @param hash Hash that needs to be signed
211      * @param hash_length Length of hash
212      * @param out_signature Buffer that will hold the output signature. The signature consists of: 2 EC elements (r and s),
213      *represented as ASN.1 DER integers, plus the ASN.1 sequence Header
214      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
215      **/
216     virtual CHIP_ERROR ECDSA_sign_hash(const uint8_t * hash, size_t hash_length, Sig & out_signature) = 0;
217
218     /** @brief A function to derive a shared secret using ECDH
219      * @param remote_public_key Public key of remote peer with which we are trying to establish secure channel. remote_public_key is
220      * ASN.1 DER encoded as padded big-endian field elements as described in SEC 1: Elliptic Curve Cryptography
221      * [https://www.secg.org/sec1-v2.pdf]
222      * @param out_secret Buffer to write out secret into. This is a byte array representing the x coordinate of the shared secret.
223      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
224      **/
225     virtual CHIP_ERROR ECDH_derive_secret(const PK & remote_public_key, Secret & out_secret) const = 0;
226
227     virtual const PK & Pubkey() = 0;
228 };
229
230 struct alignas(size_t) P256KeypairContext
231 {
232     uint8_t mBytes[kMAX_P256Keypair_Context_Size];
233 };
234
235 typedef CapacityBoundBuffer<kP256_PublicKey_Length + kP256_PrivateKey_Length> P256SerializedKeypair;
236
237 class P256Keypair : public ECPKeypair<P256PublicKey, P256ECDHDerivedSecret, P256ECDSASignature>
238 {
239 public:
240     P256Keypair() {}
241     ~P256Keypair();
242
243     /** @brief Initialize the keypair.
244      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
245      **/
246     CHIP_ERROR Initialize();
247
248     /** @brief Serialize the keypair.
249      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
250      **/
251     CHIP_ERROR Serialize(P256SerializedKeypair & output);
252
253     /** @brief Deserialize the keypair.
254      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
255      **/
256     CHIP_ERROR Deserialize(P256SerializedKeypair & input);
257
258     /** @brief Generate a new Certificate Signing Request (CSR).
259      * @param csr Newly generated CSR
260      * @param csr_length The caller provides the length of input buffer (csr). The function returns the actual length of generated
261      *CSR.
262      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
263      **/
264     CHIP_ERROR NewCertificateSigningRequest(uint8_t * csr, size_t & csr_length) override;
265
266     /**
267      * @brief A function to sign a msg using ECDSA
268      * @param msg Message that needs to be signed
269      * @param msg_length Length of message
270      * @param out_signature Buffer that will hold the output signature. The signature consists of: 2 EC elements (r and s),
271      *represented as ASN.1 DER integers, plus the ASN.1 sequence Header
272      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
273      **/
274     CHIP_ERROR ECDSA_sign_msg(const uint8_t * msg, size_t msg_length, P256ECDSASignature & out_signature) override;
275
276     /**
277      * @brief A function to sign a hash using ECDSA
278      * @param hash Hash that needs to be signed
279      * @param hash_length Length of hash
280      * @param out_signature Buffer that will hold the output signature. The signature consists of: 2 EC elements (r and s),
281      *represented as ASN.1 DER integers, plus the ASN.1 sequence Header
282      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
283      **/
284     CHIP_ERROR ECDSA_sign_hash(const uint8_t * hash, size_t hash_length, P256ECDSASignature & out_signature) override;
285
286     /** @brief A function to derive a shared secret using ECDH
287      * @param remote_public_key Public key of remote peer with which we are trying to establish secure channel. remote_public_key is
288      * ASN.1 DER encoded as padded big-endian field elements as described in SEC 1: Elliptic Curve Cryptography
289      * [https://www.secg.org/sec1-v2.pdf]
290      * @param out_secret Buffer to write out secret into. This is a byte array representing the x coordinate of the shared secret.
291      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
292      **/
293     CHIP_ERROR ECDH_derive_secret(const P256PublicKey & remote_public_key, P256ECDHDerivedSecret & out_secret) const override;
294
295     /** @brief Return public key for the keypair.
296      **/
297     const P256PublicKey & Pubkey() override { return mPublicKey; }
298
299 private:
300     P256PublicKey mPublicKey;
301     P256KeypairContext mKeypair;
302     bool mInitialized = false;
303 };
304
305 /**
306  * @brief A function that implements AES-CCM encryption
307  * @param plaintext Plaintext to encrypt
308  * @param plaintext_length Length of plain_text
309  * @param aad Additional authentication data
310  * @param aad_length Length of additional authentication data
311  * @param key Encryption key
312  * @param key_length Length of encryption key (in bytes)
313  * @param iv Initial vector
314  * @param iv_length Length of initial vector
315  * @param ciphertext Buffer to write ciphertext into. Caller must ensure this is large enough to hold the ciphertext
316  * @param tag Buffer to write tag into. Caller must ensure this is large enough to hold the tag
317  * @param tag_length Expected length of tag
318  * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
319  * */
320 CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, const uint8_t * aad, size_t aad_length,
321                            const uint8_t * key, size_t key_length, const uint8_t * iv, size_t iv_length, uint8_t * ciphertext,
322                            uint8_t * tag, size_t tag_length);
323
324 /**
325  * @brief A function that implements AES-CCM decryption
326  * @param ciphertext Ciphertext to decrypt
327  * @param ciphertext_length Length of ciphertext
328  * @param aad Additional authentical data.
329  * @param aad_length Length of additional authentication data
330  * @param tag Tag to use to decrypt
331  * @param tag_length Length of tag
332  * @param key Decryption key
333  * @param key_length Length of Decryption key (in bytes)
334  * @param iv Initial vector
335  * @param iv_length Length of initial vector
336  * @param plaintext Buffer to write plaintext into
337  * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
338  **/
339
340 CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_length, const uint8_t * aad, size_t aad_length,
341                            const uint8_t * tag, size_t tag_length, const uint8_t * key, size_t key_length, const uint8_t * iv,
342                            size_t iv_length, uint8_t * plaintext);
343
344 /**
345  * @brief A function that implements SHA-256 hash
346  * @param data The data to hash
347  * @param data_length Length of the data
348  * @param out_buffer Pointer to buffer to write output into
349  * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
350  **/
351
352 CHIP_ERROR Hash_SHA256(const uint8_t * data, size_t data_length, uint8_t * out_buffer);
353
354 /**
355  * @brief A class that defines stream based implementation of SHA-256 hash
356  *        It's expected that the object of this class can be safely copied.
357  *        All implementations must check for std::is_trivially_copyable.
358  **/
359
360 struct alignas(size_t) HashSHA256OpaqueContext
361 {
362     uint8_t mOpaque[kMAX_Hash_SHA256_Context_Size];
363 };
364
365 class Hash_SHA256_stream
366 {
367 public:
368     Hash_SHA256_stream();
369     ~Hash_SHA256_stream();
370
371     CHIP_ERROR Begin();
372     CHIP_ERROR AddData(const uint8_t * data, size_t data_length);
373     CHIP_ERROR Finish(uint8_t * out_buffer);
374     void Clear();
375
376 private:
377     HashSHA256OpaqueContext mContext;
378 };
379
380 /**
381  * @brief A function that implements SHA-256 based HKDF
382  * @param secret The secret to use as the key to the HKDF
383  * @param secret_length Length of the secret
384  * @param salt Optional salt to use as input to the HKDF
385  * @param salt_length Length of the salt
386  * @param info Optional info to use as input to the HKDF
387  * @param info_length Length of the info
388  * @param out_buffer Pointer to buffer to write output into.
389  * @param out_length Resulting length of out_buffer
390  * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
391  **/
392
393 CHIP_ERROR HKDF_SHA256(const uint8_t * secret, size_t secret_length, const uint8_t * salt, size_t salt_length, const uint8_t * info,
394                        size_t info_length, uint8_t * out_buffer, size_t out_length);
395
396 /**
397  * @brief A cryptographically secure random number generator based on NIST SP800-90A
398  * @param out_buffer Buffer to write random bytes into
399  * @param out_length Number of random bytes to generate
400  * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
401  **/
402 CHIP_ERROR DRBG_get_bytes(uint8_t * out_buffer, size_t out_length);
403
404 /** @brief Entropy callback function
405  * @param data Callback-specific data pointer
406  * @param output Output data to fill
407  * @param len Length of output buffer
408  * @param olen The actual amount of data that was written to output buffer
409  * @return 0 if success
410  */
411 typedef int (*entropy_source)(void * data, uint8_t * output, size_t len, size_t * olen);
412
413 /** @brief A function to add entropy sources to crypto library
414  * @param fn_source Function pointer to the entropy source
415  * @param p_source  Data that should be provided when fn_source is called
416  * @param threshold Minimum required from source before entropy is released
417  * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
418  **/
419 CHIP_ERROR add_entropy_source(entropy_source fn_source, void * p_source, size_t threshold);
420
421 /** @brief Function to derive key using password. SHA256 hashing algorithm is used for calculating hmac.
422  * @param password password used for key derivation
423  * @param plen length of buffer containing password
424  * @param salt salt to use as input to the KDF
425  * @param slen length of salt
426  * @param iteration_count number of iterations to run
427  * @param key_length length of output key
428  * @param output output buffer where the key will be written
429  * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
430  **/
431 CHIP_ERROR pbkdf2_sha256(const uint8_t * password, size_t plen, const uint8_t * salt, size_t slen, unsigned int iteration_count,
432                          uint32_t key_length, uint8_t * output);
433
434 /**
435  * The below class implements the draft 01 version of the Spake2+ protocol as
436  * defined in https://www.ietf.org/id/draft-bar-cfrg-spake2plus-01.html.
437  *
438  * The following describes the protocol flows:
439  *
440  *     Commissioner                     Accessory
441  *     ------------                     ---------
442  *
443  *     Init
444  *     BeginProver
445  *     ComputeRoundOne  ------------->
446  *                                      Init
447  *                                      BeginVerifier
448  *                                  /-  ComputeRoundOne
449  *                      <-------------  ComputeRoundTwo
450  *     ComputeRoundTwo  ------------->
451  *     KeyConfirm                       KeyConfirm
452  *     GetKeys                          GetKeys
453  *
454  **/
455 class Spake2p
456 {
457 public:
458     Spake2p(size_t fe_size, size_t point_size, size_t hash_size);
459     virtual ~Spake2p() {}
460
461     /**
462      * @brief Initialize Spake2+ with some context specific information.
463      *
464      * @param context     The context is arbitrary but should include information about the
465      *                    protocol being run, contain the transcript for negotiation, include
466      *                    the PKBDF parameters, etc.
467      * @param context_len The length of the context.
468      *
469      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
470      **/
471     CHIP_ERROR Init(const uint8_t * context, size_t context_len);
472
473     /**
474      * @brief Start the Spake2+ process as a verifier (i.e. an accessory being provisioned).
475      *
476      * @param my_identity       The verifier identity. May be NULL if identities are not established.
477      * @param my_identity_len   The verifier identity length.
478      * @param peer_identity     The peer identity. May be NULL if identities are not established.
479      * @param peer_identity_len The peer identity length.
480      * @param w0in              The input w0 (an output from the PBKDF).
481      * @param w0in_len          The input w0 length.
482      * @param Lin               The input L (a parameter baked into the device or computed with ComputeL).
483      * @param Lin_len           The input L length.
484      *
485      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
486      **/
487     CHIP_ERROR BeginVerifier(const uint8_t * my_identity, size_t my_identity_len, const uint8_t * peer_identity,
488                              size_t peer_identity_len, const uint8_t * w0in, size_t w0in_len, const uint8_t * Lin, size_t Lin_len);
489
490     /**
491      * @brief Start the Spake2+ process as a prover (i.e. a commisioner).
492      *
493      * @param my_identity       The prover identity. May be NULL if identities are not established.
494      * @param my_identity_len   The prover identity length.
495      * @param peer_identity     The peer identity. May be NULL if identities are not established.
496      * @param peer_identity_len The peer identity length.
497      * @param w0in              The input w0 (an output from the PBKDF).
498      * @param w0in_len          The input w0 length.
499      * @param w1in              The input w1 (an output from the PBKDF).
500      * @param w1in_len          The input w1 length.
501      *
502      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
503      **/
504     CHIP_ERROR BeginProver(const uint8_t * my_identity, size_t my_identity_len, const uint8_t * peer_identity,
505                            size_t peer_identity_len, const uint8_t * w0in, size_t w0in_len, const uint8_t * w1in, size_t w1in_len);
506
507     /**
508      * @brief Compute the first round of the protocol.
509      *
510      * @param out     The output first round Spake2+ contribution.
511      * @param out_len The output first round Spake2+ contribution length.
512      *
513      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
514      **/
515     CHIP_ERROR ComputeRoundOne(uint8_t * out, size_t * out_len);
516
517     /**
518      * @brief Compute the second round of the protocol.
519      *
520      * @param in      The peer first round Spake2+ contribution.
521      * @param in_len  The peer first round Spake2+ contribution length.
522      * @param out     The output second round Spake2+ contribution.
523      * @param out_len The output second round Spake2+ contribution length.
524      *
525      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
526      **/
527     CHIP_ERROR ComputeRoundTwo(const uint8_t * in, size_t in_len, uint8_t * out, size_t * out_len);
528
529     /**
530      * @brief Confirm that each party computed the same keys.
531      *
532      * @param in     The peer second round Spake2+ contribution.
533      * @param in_len The peer second round Spake2+ contribution length.
534      *
535      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
536      **/
537     CHIP_ERROR KeyConfirm(const uint8_t * in, size_t in_len);
538
539     /**
540      * @brief Return the shared secret.
541      *
542      * @param out     The output secret.
543      * @param out_len The output secret length.
544      *
545      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
546      **/
547     CHIP_ERROR GetKeys(uint8_t * out, size_t * out_len);
548
549     CHIP_ERROR InternalHash(const uint8_t * in, size_t in_len);
550     CHIP_ERROR WriteMN();
551     CHIP_ERROR GenerateKeys();
552
553     /**
554      * @brief Load a field element.
555      *
556      *  @param in     The input big endian field element.
557      *  @param in_len The size of the input buffer in bytes.
558      *  @param fe     A pointer to an initialized implementation dependant field element.
559      *
560      *  @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
561      **/
562     virtual CHIP_ERROR FELoad(const uint8_t * in, size_t in_len, void * fe) = 0;
563
564     /**
565      * @brief Write a field element in big-endian format.
566      *
567      *  @param fe      The field element to write.
568      *  @param out     The output buffer.
569      *  @param out_len The length of the output buffer.
570      *
571      *  @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
572      **/
573     virtual CHIP_ERROR FEWrite(const void * fe, uint8_t * out, size_t out_len) = 0;
574
575     /**
576      * @brief Generate a field element.
577      *
578      *  @param fe  A pointer to an initialized implementation dependant field element.
579      *
580      *  @note The implementation must generate a random element from [0, q) where q is the curve order.
581      *
582      *  @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
583      **/
584     virtual CHIP_ERROR FEGenerate(void * fe) = 0;
585
586     /**
587      * @brief Multiply two field elements, fer = fe1 * fe2.
588      *
589      *  @param fer   A pointer to an initialized implementation dependant field element.
590      *  @param fe1  A pointer to an initialized implementation dependant field element.
591      *  @param fe2  A pointer to an initialized implementation dependant field element.
592      *
593      *  @note The result must be a field element (i.e. reduced by the curve order).
594      *
595      *  @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
596      **/
597     virtual CHIP_ERROR FEMul(void * fer, const void * fe1, const void * fe2) = 0;
598
599     /**
600      * @brief Load a point from 0x04 || X || Y format
601      *
602      * @param in     Input buffer
603      * @param in_len Input buffer length
604      * @param R      A pointer to an initialized implementation dependant point.
605      *
606      *  @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
607      **/
608     virtual CHIP_ERROR PointLoad(const uint8_t * in, size_t in_len, void * R) = 0;
609
610     /**
611      * @brief Write a point in 0x04 || X || Y format
612      *
613      * @param R       A pointer to an initialized implementation dependant point.
614      * @param out     Output buffer
615      * @param out_len Length of the output buffer
616      *
617      *  @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
618      **/
619     virtual CHIP_ERROR PointWrite(const void * R, uint8_t * out, size_t out_len) = 0;
620
621     /**
622      * @brief Scalar multiplication, R = fe1 * P1.
623      *
624      * @param R   Resultant point
625      * @param P1  Input point
626      * @param fe1  Input field element.
627      *
628      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
629      **/
630     virtual CHIP_ERROR PointMul(void * R, const void * P1, const void * fe1) = 0;
631
632     /**
633      * @brief Scalar multiplication with addition, R = fe1 * P1 + fe2 * P2.
634      *
635      * @param R   Resultant point
636      * @param P1  Input point
637      * @param fe1  Input field element.
638      * @param P2  Input point
639      * @param fe2  Input field element.
640      *
641      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
642      **/
643     virtual CHIP_ERROR PointAddMul(void * R, const void * P1, const void * fe1, const void * P2, const void * fe2) = 0;
644
645     /**
646      * @brief Point inversion.
647      *
648      * @param R   Input/Output point to point_invert
649      *
650      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
651      **/
652     virtual CHIP_ERROR PointInvert(void * R) = 0;
653
654     /**
655      * @brief Multiply a point by the curve cofactor.
656      *
657      * @param R   Input/Output point to point_invert
658      *
659      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
660      **/
661     virtual CHIP_ERROR PointCofactorMul(void * R) = 0;
662
663     /*
664      *   @synopsis Check if a point is on the curve.
665      *
666      *   @param R   Input point to check.
667      *
668      *   @return CHIP_NO_ERROR if the point is valid, CHIP_ERROR otherwise.
669      */
670     virtual CHIP_ERROR PointIsValid(void * R) = 0;
671
672     /*
673      *   @synopsis Compute w1in*G
674      *
675      *   @param Lout        Output point in 0x04 || X || Y format.
676      *   @param L_len       Output point length
677      *   @param w1in        Input field element
678      *   @param w1in_len    Input field element size
679      *
680      *   @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
681      **/
682     virtual CHIP_ERROR ComputeL(uint8_t * Lout, size_t * L_len, const uint8_t * w1in, size_t w1in_len) = 0;
683
684     void * M;
685     void * N;
686     const void * G;
687     void * X;
688     void * Y;
689     void * L;
690     void * Z;
691     void * V;
692     void * w0;
693     void * w1;
694     void * xy;
695     void * order;
696     void * tempbn;
697
698 protected:
699     /**
700      * @brief Initialize underlying implementation curve, points, field elements, etc.
701      *
702      * @details The implementation needs to:
703      *     1. Initialize each of the points below and set the relevant pointers on the class:
704      *        a. M
705      *        b. N
706      *        c. G
707      *        d. X
708      *        e. Y
709      *        f. L
710      *        g. Z
711      *        h. V
712      *
713      *        As an example:
714      *           this.M = implementation_alloc_point();
715      *     2. Initialize each of the field elements below and set the relevant pointers on the class:
716      *        a. w0
717      *        b. w1
718      *        c. xy
719      *        d. tempbn
720      *     3. The hashing context should be initialized
721      *
722      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
723      **/
724     virtual CHIP_ERROR InitImpl() = 0;
725
726     /**
727      * @brief Hash in_len bytes of in into the internal hash context.
728      *
729      * @param in     The input buffer.
730      * @param in_len Size of the input buffer in bytes.
731      *
732      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
733      **/
734     virtual CHIP_ERROR Hash(const uint8_t * in, size_t in_len) = 0;
735
736     /**
737      * @brief Return the hash.
738      *
739      * @param out    Output buffer. The size is implicit and is determined by the hash used.
740      *
741      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
742      **/
743     virtual CHIP_ERROR HashFinalize(uint8_t * out) = 0;
744
745     /**
746      * @brief Generate a message authentication code.
747      *
748      * @param key     The MAC key buffer.
749      * @param key_len The size of the MAC key in bytes.
750      * @param in      The input buffer.
751      * @param in_len  The size of the input data to MAC in bytes.
752      * @param out     The output MAC buffer. Size is implicit and is determined by the hash used.
753      *
754      * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
755      **/
756     virtual CHIP_ERROR Mac(const uint8_t * key, size_t key_len, const uint8_t * in, size_t in_len, uint8_t * out) = 0;
757
758     /**
759      * @brief Verify a message authentication code.
760      *
761      *  @param key     The MAC key buffer.
762      *  @param key_len The size of the MAC key in bytes.
763      *  @param mac     The input MAC buffer.
764      *  @param mac_len The size of the MAC in bytes.
765      *  @param in      The input buffer to verify.
766      *  @param in_len  The size of the input data to verify in bytes.
767      *
768      *  @return Returns a CHIP_ERROR when the MAC doesn't validate, CHIP_NO_ERROR otherwise.
769      **/
770     virtual CHIP_ERROR MacVerify(const uint8_t * key, size_t key_len, const uint8_t * mac, size_t mac_len, const uint8_t * in,
771                                  size_t in_len) = 0;
772
773     /**
774      * @brief Derive an key of length out_len.
775      *
776      * @param ikm      The input key material buffer.
777      * @param ikm_len  The input key material length.
778      * @param salt     The optional salt. This may be NULL.
779      * @param salt_len The size of the salt in bytes.
780      * @param info     The info.
781      * @param info_len The size of the info in bytes.
782      * @param out      The output key
783      * @param out_len  The output key length
784      *
785      * @return Returns a CHIP_ERROR when the MAC doesn't validate, CHIP_NO_ERROR otherwise.
786      **/
787     virtual CHIP_ERROR KDF(const uint8_t * ikm, size_t ikm_len, const uint8_t * salt, size_t salt_len, const uint8_t * info,
788                            size_t info_len, uint8_t * out, size_t out_len) = 0;
789
790     CHIP_SPAKE2P_ROLE role;
791     CHIP_SPAKE2P_STATE state;
792     size_t fe_size;
793     size_t hash_size;
794     size_t point_size;
795     uint8_t Kcab[kMAX_Hash_Length];
796     uint8_t Kae[kMAX_Hash_Length];
797     uint8_t * Kca;
798     uint8_t * Kcb;
799     uint8_t * Ka;
800     uint8_t * Ke;
801 };
802
803 struct alignas(size_t) Spake2pOpaqueContext
804 {
805     uint8_t mOpaque[kMAX_Spake2p_Context_Size];
806 };
807
808 class Spake2p_P256_SHA256_HKDF_HMAC : public Spake2p
809 {
810 public:
811     Spake2p_P256_SHA256_HKDF_HMAC() : Spake2p(kP256_FE_Length, kP256_Point_Length, kSHA256_Hash_Length)
812     {
813         memset(&mSpake2pContext, 0, sizeof(mSpake2pContext));
814     }
815
816     ~Spake2p_P256_SHA256_HKDF_HMAC() override { FreeImpl(); }
817
818     CHIP_ERROR Mac(const uint8_t * key, size_t key_len, const uint8_t * in, size_t in_len, uint8_t * out) override;
819     CHIP_ERROR MacVerify(const uint8_t * key, size_t key_len, const uint8_t * mac, size_t mac_len, const uint8_t * in,
820                          size_t in_len) override;
821     CHIP_ERROR FELoad(const uint8_t * in, size_t in_len, void * fe) override;
822     CHIP_ERROR FEWrite(const void * fe, uint8_t * out, size_t out_len) override;
823     CHIP_ERROR FEGenerate(void * fe) override;
824     CHIP_ERROR FEMul(void * fer, const void * fe1, const void * fe2) override;
825
826     CHIP_ERROR PointLoad(const uint8_t * in, size_t in_len, void * R) override;
827     CHIP_ERROR PointWrite(const void * R, uint8_t * out, size_t out_len) override;
828     CHIP_ERROR PointMul(void * R, const void * P1, const void * fe1) override;
829     CHIP_ERROR PointAddMul(void * R, const void * P1, const void * fe1, const void * P2, const void * fe2) override;
830     CHIP_ERROR PointInvert(void * R) override;
831     CHIP_ERROR PointCofactorMul(void * R) override;
832     CHIP_ERROR PointIsValid(void * R) override;
833     CHIP_ERROR ComputeL(uint8_t * Lout, size_t * L_len, const uint8_t * w1in, size_t w1in_len) override;
834
835 protected:
836     CHIP_ERROR InitImpl() override;
837     CHIP_ERROR Hash(const uint8_t * in, size_t in_len) override;
838     CHIP_ERROR HashFinalize(uint8_t * out) override;
839     CHIP_ERROR KDF(const uint8_t * secret, size_t secret_length, const uint8_t * salt, size_t salt_length, const uint8_t * info,
840                    size_t info_length, uint8_t * out, size_t out_length) override;
841
842 private:
843     /**
844      * @brief Free any underlying implementation curve, points, field elements, etc.
845      **/
846     void FreeImpl();
847
848     CHIP_ERROR InitInternal();
849     Hash_SHA256_stream sha256_hash_ctx;
850
851     Spake2pOpaqueContext mSpake2pContext;
852 };
853
854 /** @brief Clears the first `len` bytes of memory area `buf`.
855  * @param buf Pointer to a memory buffer holding secret data that should be cleared.
856  * @param len Specifies secret data size in bytes.
857  **/
858 void ClearSecretData(uint8_t * buf, uint32_t len);
859
860 } // namespace Crypto
861 } // namespace chip
862
863 #endif