3 * Copyright (c) 2020 Project CHIP Authors
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 * Header that exposes the platform agnostic CHIP crypto primitives
23 #ifndef _CHIP_CRYPTO_PAL_H_
24 #define _CHIP_CRYPTO_PAL_H_
26 #if CHIP_HAVE_CONFIG_H
27 #include <crypto/CryptoBuildConfig.h>
30 #include <core/CHIPError.h>
31 #include <support/CodeUtils.h>
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;
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;
50 const size_t kMin_Salt_Length = 8;
51 const size_t kMax_Salt_Length = 16;
53 const size_t kP256_PrivateKey_Length = 32;
54 const size_t kP256_PublicKey_Length = 65;
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.
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;
65 * Spake2+ parameters for P256
66 * Defined in https://www.ietf.org/id/draft-bar-cfrg-spake2plus-01.html#name-ciphersuites
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,
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,
82 * Spake2+ state machine to ensure proper execution of the protocol.
84 enum class CHIP_SPAKE2P_STATE : uint8_t
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
97 enum class CHIP_SPAKE2P_ROLE : uint8_t
99 VERIFIER = 0, // Accessory
100 PROVER = 1, // Commissioner
103 enum class SupportedECPKeyTypes : uint8_t
108 template <typename Sig>
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;
118 virtual CHIP_ERROR ECDSA_validate_msg_signature(const uint8_t * msg, const size_t msg_length, const Sig & signature) const
120 return CHIP_ERROR_NOT_IMPLEMENTED;
122 virtual CHIP_ERROR ECDSA_validate_hash_signature(const uint8_t * hash, const size_t hash_length, const Sig & signature) const
124 return CHIP_ERROR_NOT_IMPLEMENTED;
128 template <size_t Cap>
129 class CapacityBoundBuffer
132 /** @brief Set current length of the buffer that's being used
133 * @return Returns error if new length is > capacity
135 CHIP_ERROR SetLength(size_t len)
137 CHIP_ERROR error = CHIP_NO_ERROR;
138 VerifyOrExit(len <= sizeof(bytes), error = CHIP_ERROR_INVALID_ARGUMENT);
144 /** @brief Returns current length of the buffer that's being used
145 * @return Returns 0 if SetLength() was never called
147 size_t Length() const { return length; }
149 /** @brief Returns max capacity of the buffer
151 size_t Capacity() const { return sizeof(bytes); }
153 /** @brief Returns buffer pointer
155 operator uint8_t *() { return bytes; }
156 operator const uint8_t *() const { return bytes; }
163 typedef CapacityBoundBuffer<kMax_ECDSA_Signature_Length> P256ECDSASignature;
165 typedef CapacityBoundBuffer<kMax_ECDH_Secret_Length> P256ECDHDerivedSecret;
167 class P256PublicKey : public ECPKey<P256ECDSASignature>
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; }
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;
181 uint8_t bytes[kP256_PublicKey_Length];
184 template <typename PK, typename Secret, typename Sig>
188 virtual ~ECPKeypair() {}
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
194 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
196 virtual CHIP_ERROR NewCertificateSigningRequest(uint8_t * csr, size_t & csr_length) = 0;
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
206 virtual CHIP_ERROR ECDSA_sign_msg(const uint8_t * msg, size_t msg_length, Sig & out_signature) = 0;
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
216 virtual CHIP_ERROR ECDSA_sign_hash(const uint8_t * hash, size_t hash_length, Sig & out_signature) = 0;
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
225 virtual CHIP_ERROR ECDH_derive_secret(const PK & remote_public_key, Secret & out_secret) const = 0;
227 virtual const PK & Pubkey() = 0;
230 struct alignas(size_t) P256KeypairContext
232 uint8_t mBytes[kMAX_P256Keypair_Context_Size];
235 typedef CapacityBoundBuffer<kP256_PublicKey_Length + kP256_PrivateKey_Length> P256SerializedKeypair;
237 class P256Keypair : public ECPKeypair<P256PublicKey, P256ECDHDerivedSecret, P256ECDSASignature>
243 /** @brief Initialize the keypair.
244 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
246 CHIP_ERROR Initialize();
248 /** @brief Serialize the keypair.
249 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
251 CHIP_ERROR Serialize(P256SerializedKeypair & output);
253 /** @brief Deserialize the keypair.
254 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
256 CHIP_ERROR Deserialize(P256SerializedKeypair & input);
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
262 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
264 CHIP_ERROR NewCertificateSigningRequest(uint8_t * csr, size_t & csr_length) override;
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
274 CHIP_ERROR ECDSA_sign_msg(const uint8_t * msg, size_t msg_length, P256ECDSASignature & out_signature) override;
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
284 CHIP_ERROR ECDSA_sign_hash(const uint8_t * hash, size_t hash_length, P256ECDSASignature & out_signature) override;
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
293 CHIP_ERROR ECDH_derive_secret(const P256PublicKey & remote_public_key, P256ECDHDerivedSecret & out_secret) const override;
295 /** @brief Return public key for the keypair.
297 const P256PublicKey & Pubkey() override { return mPublicKey; }
300 P256PublicKey mPublicKey;
301 P256KeypairContext mKeypair;
302 bool mInitialized = false;
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
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);
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
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);
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
352 CHIP_ERROR Hash_SHA256(const uint8_t * data, size_t data_length, uint8_t * out_buffer);
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.
360 struct alignas(size_t) HashSHA256OpaqueContext
362 uint8_t mOpaque[kMAX_Hash_SHA256_Context_Size];
365 class Hash_SHA256_stream
368 Hash_SHA256_stream();
369 ~Hash_SHA256_stream();
372 CHIP_ERROR AddData(const uint8_t * data, size_t data_length);
373 CHIP_ERROR Finish(uint8_t * out_buffer);
377 HashSHA256OpaqueContext mContext;
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
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);
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
402 CHIP_ERROR DRBG_get_bytes(uint8_t * out_buffer, size_t out_length);
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
411 typedef int (*entropy_source)(void * data, uint8_t * output, size_t len, size_t * olen);
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
419 CHIP_ERROR add_entropy_source(entropy_source fn_source, void * p_source, size_t threshold);
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
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);
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.
438 * The following describes the protocol flows:
440 * Commissioner Accessory
441 * ------------ ---------
445 * ComputeRoundOne ------------->
449 * <------------- ComputeRoundTwo
450 * ComputeRoundTwo ------------->
451 * KeyConfirm KeyConfirm
458 Spake2p(size_t fe_size, size_t point_size, size_t hash_size);
459 virtual ~Spake2p() {}
462 * @brief Initialize Spake2+ with some context specific information.
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.
469 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
471 CHIP_ERROR Init(const uint8_t * context, size_t context_len);
474 * @brief Start the Spake2+ process as a verifier (i.e. an accessory being provisioned).
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.
485 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
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);
491 * @brief Start the Spake2+ process as a prover (i.e. a commisioner).
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.
502 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
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);
508 * @brief Compute the first round of the protocol.
510 * @param out The output first round Spake2+ contribution.
511 * @param out_len The output first round Spake2+ contribution length.
513 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
515 CHIP_ERROR ComputeRoundOne(uint8_t * out, size_t * out_len);
518 * @brief Compute the second round of the protocol.
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.
525 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
527 CHIP_ERROR ComputeRoundTwo(const uint8_t * in, size_t in_len, uint8_t * out, size_t * out_len);
530 * @brief Confirm that each party computed the same keys.
532 * @param in The peer second round Spake2+ contribution.
533 * @param in_len The peer second round Spake2+ contribution length.
535 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
537 CHIP_ERROR KeyConfirm(const uint8_t * in, size_t in_len);
540 * @brief Return the shared secret.
542 * @param out The output secret.
543 * @param out_len The output secret length.
545 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
547 CHIP_ERROR GetKeys(uint8_t * out, size_t * out_len);
549 CHIP_ERROR InternalHash(const uint8_t * in, size_t in_len);
550 CHIP_ERROR WriteMN();
551 CHIP_ERROR GenerateKeys();
554 * @brief Load a field element.
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.
560 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
562 virtual CHIP_ERROR FELoad(const uint8_t * in, size_t in_len, void * fe) = 0;
565 * @brief Write a field element in big-endian format.
567 * @param fe The field element to write.
568 * @param out The output buffer.
569 * @param out_len The length of the output buffer.
571 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
573 virtual CHIP_ERROR FEWrite(const void * fe, uint8_t * out, size_t out_len) = 0;
576 * @brief Generate a field element.
578 * @param fe A pointer to an initialized implementation dependant field element.
580 * @note The implementation must generate a random element from [0, q) where q is the curve order.
582 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
584 virtual CHIP_ERROR FEGenerate(void * fe) = 0;
587 * @brief Multiply two field elements, fer = fe1 * fe2.
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.
593 * @note The result must be a field element (i.e. reduced by the curve order).
595 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
597 virtual CHIP_ERROR FEMul(void * fer, const void * fe1, const void * fe2) = 0;
600 * @brief Load a point from 0x04 || X || Y format
602 * @param in Input buffer
603 * @param in_len Input buffer length
604 * @param R A pointer to an initialized implementation dependant point.
606 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
608 virtual CHIP_ERROR PointLoad(const uint8_t * in, size_t in_len, void * R) = 0;
611 * @brief Write a point in 0x04 || X || Y format
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
617 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
619 virtual CHIP_ERROR PointWrite(const void * R, uint8_t * out, size_t out_len) = 0;
622 * @brief Scalar multiplication, R = fe1 * P1.
624 * @param R Resultant point
625 * @param P1 Input point
626 * @param fe1 Input field element.
628 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
630 virtual CHIP_ERROR PointMul(void * R, const void * P1, const void * fe1) = 0;
633 * @brief Scalar multiplication with addition, R = fe1 * P1 + fe2 * P2.
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.
641 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
643 virtual CHIP_ERROR PointAddMul(void * R, const void * P1, const void * fe1, const void * P2, const void * fe2) = 0;
646 * @brief Point inversion.
648 * @param R Input/Output point to point_invert
650 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
652 virtual CHIP_ERROR PointInvert(void * R) = 0;
655 * @brief Multiply a point by the curve cofactor.
657 * @param R Input/Output point to point_invert
659 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
661 virtual CHIP_ERROR PointCofactorMul(void * R) = 0;
664 * @synopsis Check if a point is on the curve.
666 * @param R Input point to check.
668 * @return CHIP_NO_ERROR if the point is valid, CHIP_ERROR otherwise.
670 virtual CHIP_ERROR PointIsValid(void * R) = 0;
673 * @synopsis Compute w1in*G
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
680 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
682 virtual CHIP_ERROR ComputeL(uint8_t * Lout, size_t * L_len, const uint8_t * w1in, size_t w1in_len) = 0;
700 * @brief Initialize underlying implementation curve, points, field elements, etc.
702 * @details The implementation needs to:
703 * 1. Initialize each of the points below and set the relevant pointers on the class:
714 * this.M = implementation_alloc_point();
715 * 2. Initialize each of the field elements below and set the relevant pointers on the class:
720 * 3. The hashing context should be initialized
722 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
724 virtual CHIP_ERROR InitImpl() = 0;
727 * @brief Hash in_len bytes of in into the internal hash context.
729 * @param in The input buffer.
730 * @param in_len Size of the input buffer in bytes.
732 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
734 virtual CHIP_ERROR Hash(const uint8_t * in, size_t in_len) = 0;
737 * @brief Return the hash.
739 * @param out Output buffer. The size is implicit and is determined by the hash used.
741 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
743 virtual CHIP_ERROR HashFinalize(uint8_t * out) = 0;
746 * @brief Generate a message authentication code.
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.
754 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
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;
759 * @brief Verify a message authentication code.
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.
768 * @return Returns a CHIP_ERROR when the MAC doesn't validate, CHIP_NO_ERROR otherwise.
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,
774 * @brief Derive an key of length out_len.
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
785 * @return Returns a CHIP_ERROR when the MAC doesn't validate, CHIP_NO_ERROR otherwise.
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;
790 CHIP_SPAKE2P_ROLE role;
791 CHIP_SPAKE2P_STATE state;
795 uint8_t Kcab[kMAX_Hash_Length];
796 uint8_t Kae[kMAX_Hash_Length];
803 struct alignas(size_t) Spake2pOpaqueContext
805 uint8_t mOpaque[kMAX_Spake2p_Context_Size];
808 class Spake2p_P256_SHA256_HKDF_HMAC : public Spake2p
811 Spake2p_P256_SHA256_HKDF_HMAC() : Spake2p(kP256_FE_Length, kP256_Point_Length, kSHA256_Hash_Length)
813 memset(&mSpake2pContext, 0, sizeof(mSpake2pContext));
816 ~Spake2p_P256_SHA256_HKDF_HMAC() override { FreeImpl(); }
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;
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;
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;
844 * @brief Free any underlying implementation curve, points, field elements, etc.
848 CHIP_ERROR InitInternal();
849 Hash_SHA256_stream sha256_hash_ctx;
851 Spake2pOpaqueContext mSpake2pContext;
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.
858 void ClearSecretData(uint8_t * buf, uint32_t len);
860 } // namespace Crypto