Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020-2023 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 : #pragma once
24 :
25 : #if CHIP_HAVE_CONFIG_H
26 : #include <crypto/CryptoBuildConfig.h>
27 : #endif // CHIP_HAVE_CONFIG_H
28 :
29 : #include <system/SystemConfig.h>
30 :
31 : #include <lib/core/CHIPError.h>
32 : #include <lib/core/CHIPVendorIdentifiers.hpp>
33 : #include <lib/core/Optional.h>
34 : #include <lib/support/BufferReader.h>
35 : #include <lib/support/CodeUtils.h>
36 : #include <lib/support/SafePointerCast.h>
37 : #include <lib/support/Span.h>
38 :
39 : #include <stddef.h>
40 : #include <string.h>
41 :
42 : namespace chip {
43 : namespace Crypto {
44 :
45 : inline constexpr size_t kMax_x509_Certificate_Length = 600;
46 :
47 : inline constexpr size_t kP256_FE_Length = 32;
48 : inline constexpr size_t kP256_ECDSA_Signature_Length_Raw = (2 * kP256_FE_Length);
49 : inline constexpr size_t kP256_Point_Length = (2 * kP256_FE_Length + 1);
50 : inline constexpr size_t kSHA256_Hash_Length = 32;
51 : inline constexpr size_t kSHA1_Hash_Length = 20;
52 : inline constexpr size_t kSubjectKeyIdentifierLength = kSHA1_Hash_Length;
53 : inline constexpr size_t kAuthorityKeyIdentifierLength = kSHA1_Hash_Length;
54 : inline constexpr size_t kMaxCertificateSerialNumberLength = 20;
55 : inline constexpr size_t kMaxCertificateDistinguishedNameLength = 200;
56 : inline constexpr size_t kMaxCRLDistributionPointURLLength = 100;
57 :
58 : inline constexpr char kValidCDPURIHttpPrefix[] = "http://";
59 : inline constexpr char kValidCDPURIHttpsPrefix[] = "https://";
60 :
61 : inline constexpr size_t CHIP_CRYPTO_GROUP_SIZE_BYTES = kP256_FE_Length;
62 : inline constexpr size_t CHIP_CRYPTO_PUBLIC_KEY_SIZE_BYTES = kP256_Point_Length;
63 :
64 : inline constexpr size_t CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES = 16;
65 : inline constexpr size_t CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES = 16;
66 :
67 : inline constexpr size_t kMax_ECDH_Secret_Length = kP256_FE_Length;
68 : inline constexpr size_t kMax_ECDSA_Signature_Length = kP256_ECDSA_Signature_Length_Raw;
69 : inline constexpr size_t kMAX_FE_Length = kP256_FE_Length;
70 : inline constexpr size_t kMAX_Point_Length = kP256_Point_Length;
71 : inline constexpr size_t kMAX_Hash_Length = kSHA256_Hash_Length;
72 :
73 : // Minimum required CSR length buffer length is relatively small since it's a single
74 : // P256 key and no metadata/extensions are expected to be honored by the CA.
75 : inline constexpr size_t kMIN_CSR_Buffer_Size = 255;
76 :
77 : [[deprecated("This constant is no longer used by common code and should be replaced by kMIN_CSR_Buffer_Size. Checks that a CSR is "
78 : "<= kMAX_CSR_Buffer_size must be updated. This remains to keep valid buffers working from previous public API "
79 : "usage.")]] constexpr size_t kMAX_CSR_Buffer_Size = 255;
80 :
81 : inline constexpr size_t CHIP_CRYPTO_HASH_LEN_BYTES = kSHA256_Hash_Length;
82 :
83 : inline constexpr size_t kSpake2p_Min_PBKDF_Salt_Length = 16;
84 : inline constexpr size_t kSpake2p_Max_PBKDF_Salt_Length = 32;
85 : inline constexpr uint32_t kSpake2p_Min_PBKDF_Iterations = 1000;
86 : inline constexpr uint32_t kSpake2p_Max_PBKDF_Iterations = 100000;
87 :
88 : inline constexpr size_t kP256_PrivateKey_Length = CHIP_CRYPTO_GROUP_SIZE_BYTES;
89 : inline constexpr size_t kP256_PublicKey_Length = CHIP_CRYPTO_PUBLIC_KEY_SIZE_BYTES;
90 :
91 : inline constexpr size_t kAES_CCM128_Key_Length = 128u / 8u;
92 : inline constexpr size_t kAES_CCM128_Block_Length = kAES_CCM128_Key_Length;
93 : inline constexpr size_t kAES_CCM128_Nonce_Length = 13;
94 : inline constexpr size_t kAES_CCM128_Tag_Length = 16;
95 : inline constexpr size_t kHMAC_CCM128_Key_Length = 128u / 8u;
96 :
97 : inline constexpr size_t CHIP_CRYPTO_AEAD_NONCE_LENGTH_BYTES = kAES_CCM128_Nonce_Length;
98 :
99 : /* These sizes are hardcoded here to remove header dependency on underlying crypto library
100 : * in a public interface file. The validity of these sizes is verified by static_assert in
101 : * the implementation files.
102 : */
103 : inline constexpr size_t kMAX_Spake2p_Context_Size = 1024;
104 : inline constexpr size_t kMAX_P256Keypair_Context_Size = 512;
105 :
106 : inline constexpr size_t kEmitDerIntegerWithoutTagOverhead = 1; // 1 sign stuffer
107 : inline constexpr size_t kEmitDerIntegerOverhead = 3; // Tag + Length byte + 1 sign stuffer
108 :
109 : inline constexpr size_t kMAX_Hash_SHA256_Context_Size = CHIP_CONFIG_SHA256_CONTEXT_SIZE;
110 :
111 : inline constexpr size_t kSpake2p_WS_Length = kP256_FE_Length + 8;
112 : inline constexpr size_t kSpake2p_VerifierSerialized_Length = kP256_FE_Length + kP256_Point_Length;
113 :
114 : inline constexpr char kVIDPrefixForCNEncoding[] = "Mvid:";
115 : inline constexpr char kPIDPrefixForCNEncoding[] = "Mpid:";
116 : inline constexpr size_t kVIDandPIDHexLength = sizeof(uint16_t) * 2;
117 : inline constexpr size_t kMax_CommonNameAttr_Length = 64;
118 :
119 : /*
120 : * Overhead to encode a raw ECDSA signature in X9.62 format in ASN.1 DER
121 : *
122 : * Ecdsa-Sig-Value ::= SEQUENCE {
123 : * r INTEGER,
124 : * s INTEGER
125 : * }
126 : *
127 : * --> SEQUENCE, universal constructed tag (0x30), length over 2 bytes, up to 255 (to support future larger sizes up to 512 bits)
128 : * -> SEQ_OVERHEAD = 3 bytes
129 : * --> INTEGER, universal primitive tag (0x02), length over 1 byte, one extra byte worst case
130 : * over max for 0x00 when MSB is set.
131 : * -> INT_OVERHEAD = 3 bytes
132 : *
133 : * There is 1 sequence of 2 integers. Overhead is SEQ_OVERHEAD + (2 * INT_OVERHEAD) = 3 + (2 * 3) = 9.
134 : */
135 : inline constexpr size_t kMax_ECDSA_X9Dot62_Asn1_Overhead = 9;
136 : inline constexpr size_t kMax_ECDSA_Signature_Length_Der = kMax_ECDSA_Signature_Length + kMax_ECDSA_X9Dot62_Asn1_Overhead;
137 :
138 : static_assert(kMax_ECDH_Secret_Length >= kP256_FE_Length, "ECDH shared secret is too short for crypto suite");
139 : static_assert(kMax_ECDSA_Signature_Length >= kP256_ECDSA_Signature_Length_Raw,
140 : "ECDSA signature buffer length is too short for crypto suite");
141 :
142 : inline constexpr size_t kCompressedFabricIdentifierSize = 8;
143 :
144 : /**
145 : * Spake2+ parameters for P256
146 : * Defined in https://www.ietf.org/id/draft-bar-cfrg-spake2plus-01.html#name-ciphersuites
147 : */
148 : const uint8_t spake2p_M_p256[] = {
149 : 0x04, 0x88, 0x6e, 0x2f, 0x97, 0xac, 0xe4, 0x6e, 0x55, 0xba, 0x9d, 0xd7, 0x24, 0x25, 0x79, 0xf2, 0x99,
150 : 0x3b, 0x64, 0xe1, 0x6e, 0xf3, 0xdc, 0xab, 0x95, 0xaf, 0xd4, 0x97, 0x33, 0x3d, 0x8f, 0xa1, 0x2f, 0x5f,
151 : 0xf3, 0x55, 0x16, 0x3e, 0x43, 0xce, 0x22, 0x4e, 0x0b, 0x0e, 0x65, 0xff, 0x02, 0xac, 0x8e, 0x5c, 0x7b,
152 : 0xe0, 0x94, 0x19, 0xc7, 0x85, 0xe0, 0xca, 0x54, 0x7d, 0x55, 0xa1, 0x2e, 0x2d, 0x20,
153 : };
154 : const uint8_t spake2p_N_p256[] = {
155 : 0x04, 0xd8, 0xbb, 0xd6, 0xc6, 0x39, 0xc6, 0x29, 0x37, 0xb0, 0x4d, 0x99, 0x7f, 0x38, 0xc3, 0x77, 0x07,
156 : 0x19, 0xc6, 0x29, 0xd7, 0x01, 0x4d, 0x49, 0xa2, 0x4b, 0x4f, 0x98, 0xba, 0xa1, 0x29, 0x2b, 0x49, 0x07,
157 : 0xd6, 0x0a, 0xa6, 0xbf, 0xad, 0xe4, 0x50, 0x08, 0xa6, 0x36, 0x33, 0x7f, 0x51, 0x68, 0xc6, 0x4d, 0x9b,
158 : 0xd3, 0x60, 0x34, 0x80, 0x8c, 0xd5, 0x64, 0x49, 0x0b, 0x1e, 0x65, 0x6e, 0xdb, 0xe7,
159 : };
160 :
161 : /**
162 : * Spake2+ state machine to ensure proper execution of the protocol.
163 : */
164 : enum class CHIP_SPAKE2P_STATE : uint8_t
165 : {
166 : PREINIT = 0, // Before any initialization
167 : INIT, // First initialization
168 : STARTED, // Prover & Verifier starts
169 : R1, // Round one complete
170 : R2, // Round two complete
171 : KC, // Key confirmation complete
172 : };
173 :
174 : /**
175 : * Spake2+ role.
176 : */
177 : enum class CHIP_SPAKE2P_ROLE : uint8_t
178 : {
179 : VERIFIER = 0, // Accessory
180 : PROVER = 1, // Commissioner
181 : };
182 :
183 : enum class SupportedECPKeyTypes : uint8_t
184 : {
185 : ECP256R1 = 0,
186 : };
187 :
188 : enum class ECPKeyTarget : uint8_t
189 : {
190 : ECDH = 0,
191 : ECDSA = 1,
192 : };
193 :
194 : /** @brief Safely clears the first `len` bytes of memory area `buf`.
195 : * @param buf Pointer to a memory buffer holding secret data that must be cleared.
196 : * @param len Specifies secret data size in bytes.
197 : **/
198 : void ClearSecretData(uint8_t * buf, size_t len);
199 :
200 : /**
201 : * Helper for clearing a C array which auto-deduces the size.
202 : */
203 : template <size_t N>
204 412936 : void ClearSecretData(uint8_t (&buf)[N])
205 : {
206 412936 : ClearSecretData(buf, N);
207 412936 : }
208 :
209 : /**
210 : * @brief Constant-time buffer comparison
211 : *
212 : * This function implements constant time memcmp. It's good practice
213 : * to use constant time functions for cryptographic functions.
214 : *
215 : * @param a Pointer to first buffer
216 : * @param b Pointer to Second buffer
217 : * @param n Number of bytes to compare
218 : * @return true if `n` first bytes of both buffers are equal, false otherwise
219 : */
220 : bool IsBufferContentEqualConstantTime(const void * a, const void * b, size_t n);
221 :
222 : template <typename Sig>
223 : class ECPKey
224 : {
225 : protected:
226 : // This base type can't be copied / assigned directly.
227 : // Sub-types should be either uncopyable or final.
228 0 : ECPKey() = default;
229 : ECPKey(const ECPKey &) = default;
230 1502 : ECPKey & operator=(const ECPKey &) = default;
231 :
232 : public:
233 808 : virtual ~ECPKey() = default;
234 :
235 : virtual SupportedECPKeyTypes Type() const = 0;
236 : virtual size_t Length() const = 0;
237 : virtual bool IsUncompressed() const = 0;
238 : virtual operator const uint8_t *() const = 0;
239 : virtual operator uint8_t *() = 0;
240 : virtual const uint8_t * ConstBytes() const = 0;
241 : virtual uint8_t * Bytes() = 0;
242 :
243 0 : virtual bool Matches(const ECPKey<Sig> & other) const
244 : {
245 0 : return (this->Length() == other.Length()) &&
246 0 : IsBufferContentEqualConstantTime(this->ConstBytes(), other.ConstBytes(), this->Length());
247 : }
248 :
249 : virtual CHIP_ERROR ECDSA_validate_msg_signature(const uint8_t * msg, const size_t msg_length, const Sig & signature) const = 0;
250 : virtual CHIP_ERROR ECDSA_validate_hash_signature(const uint8_t * hash, const size_t hash_length,
251 : const Sig & signature) const = 0;
252 : };
253 :
254 : /**
255 : * @brief Helper class for holding sensitive data that should be erased from memory after use.
256 : *
257 : * The sensitive data buffer is a variable-length, fixed-capacity buffer class that securely erases
258 : * the contents of a buffer when the buffer is destroyed.
259 : */
260 : template <size_t kCapacity>
261 : class SensitiveDataBuffer
262 : {
263 : public:
264 3488 : ~SensitiveDataBuffer()
265 : {
266 : // Sanitize after use
267 3488 : ClearSecretData(mBytes);
268 3488 : }
269 3487 : SensitiveDataBuffer() {}
270 1 : SensitiveDataBuffer(const SensitiveDataBuffer & other) { *this = other; }
271 1 : SensitiveDataBuffer & operator=(const SensitiveDataBuffer & other)
272 : {
273 : // Guard self assignment
274 1 : if (this == &other)
275 0 : return *this;
276 :
277 1 : ClearSecretData(mBytes);
278 1 : SetLength(other.Length());
279 1 : ::memcpy(Bytes(), other.ConstBytes(), other.Length());
280 1 : return *this;
281 : }
282 :
283 : /**
284 : * @brief Set current length of the buffer
285 : * @return Error if new length is exceeds capacity of the buffer
286 : */
287 3503 : CHIP_ERROR SetLength(size_t length)
288 : {
289 3503 : VerifyOrReturnError(length <= kCapacity, CHIP_ERROR_INVALID_ARGUMENT);
290 3503 : mLength = length;
291 3503 : return CHIP_NO_ERROR;
292 : }
293 :
294 : /**
295 : * @brief Returns current length of the buffer
296 : */
297 3631 : size_t Length() const { return mLength; }
298 :
299 : /**
300 : * @brief Returns non-const pointer to start of the underlying buffer
301 : */
302 4022 : uint8_t * Bytes() { return &mBytes[0]; }
303 :
304 : /**
305 : * @brief Returns const pointer to start of the underlying buffer
306 : */
307 5904 : const uint8_t * ConstBytes() const { return &mBytes[0]; }
308 :
309 : /**
310 : * @brief Constructs span from the underlying buffer
311 : */
312 21 : ByteSpan Span() const { return ByteSpan(ConstBytes(), Length()); }
313 :
314 : /**
315 : * @brief Returns capacity of the buffer
316 : */
317 1407 : static constexpr size_t Capacity() { return kCapacity; }
318 :
319 : private:
320 : uint8_t mBytes[kCapacity];
321 : size_t mLength = 0;
322 : };
323 :
324 : /**
325 : * @brief Helper class for holding fixed-sized sensitive data that should be erased from memory after use.
326 : *
327 : * The sensitive data buffer is a fixed-length, fixed-capacity buffer class that securely erases
328 : * the contents of a buffer when the buffer is destroyed.
329 : */
330 : template <size_t kCapacity>
331 : class SensitiveDataFixedBuffer
332 : {
333 : public:
334 : SensitiveDataFixedBuffer() = default;
335 :
336 : constexpr explicit SensitiveDataFixedBuffer(const uint8_t (&rawValue)[kCapacity])
337 : {
338 : memcpy(&mBytes[0], &rawValue[0], kCapacity);
339 : }
340 :
341 0 : constexpr explicit SensitiveDataFixedBuffer(const FixedByteSpan<kCapacity> & value)
342 : {
343 0 : memcpy(&mBytes[0], value.data(), kCapacity);
344 0 : }
345 :
346 135254 : ~SensitiveDataFixedBuffer()
347 : {
348 : // Sanitize after use
349 135254 : ClearSecretData(mBytes);
350 135254 : }
351 :
352 : /**
353 : * @brief Returns fixed length of the buffer
354 : */
355 : constexpr size_t Length() const { return kCapacity; }
356 :
357 : /**
358 : * @brief Returns non-const pointer to start of the underlying buffer
359 : */
360 1479 : uint8_t * Bytes() { return &mBytes[0]; }
361 :
362 : /**
363 : * @brief Returns const pointer to start of the underlying buffer
364 : */
365 : const uint8_t * ConstBytes() const { return &mBytes[0]; }
366 :
367 : /**
368 : * @brief Constructs fixed span from the underlying buffer
369 : */
370 0 : FixedByteSpan<kCapacity> Span() const { return FixedByteSpan<kCapacity>(mBytes); }
371 :
372 : /**
373 : * @brief Returns capacity of the buffer
374 : */
375 1464 : static constexpr size_t Capacity() { return kCapacity; }
376 :
377 : private:
378 : uint8_t mBytes[kCapacity];
379 : };
380 :
381 : using P256ECDSASignature = SensitiveDataBuffer<kMax_ECDSA_Signature_Length>;
382 : using P256ECDHDerivedSecret = SensitiveDataBuffer<kMax_ECDH_Secret_Length>;
383 :
384 : using IdentityProtectionKey = SensitiveDataFixedBuffer<CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES>;
385 : using IdentityProtectionKeySpan = FixedByteSpan<Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES>;
386 :
387 : using AttestationChallenge = SensitiveDataFixedBuffer<CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES>;
388 :
389 : class P256PublicKey final // final due to being copyable
390 : : public ECPKey<P256ECDSASignature>
391 : {
392 : public:
393 0 : P256PublicKey() = default;
394 :
395 : template <size_t N>
396 : constexpr P256PublicKey(const uint8_t (&raw_value)[N])
397 : {
398 : static_assert(N == kP256_PublicKey_Length, "Can only array-initialize from proper bounds");
399 : memcpy(&bytes[0], &raw_value[0], N);
400 : }
401 :
402 : template <size_t N>
403 697 : constexpr P256PublicKey(const FixedByteSpan<N> & value)
404 697 : {
405 : static_assert(N == kP256_PublicKey_Length, "Can only initialize from proper sized byte span");
406 697 : memcpy(&bytes[0], value.data(), N);
407 697 : }
408 :
409 : template <size_t N>
410 879 : P256PublicKey & operator=(const FixedByteSpan<N> & value)
411 : {
412 : static_assert(N == kP256_PublicKey_Length, "Can only initialize from proper sized byte span");
413 879 : memcpy(&bytes[0], value.data(), N);
414 879 : return *this;
415 : }
416 :
417 3934 : SupportedECPKeyTypes Type() const override { return SupportedECPKeyTypes::ECP256R1; }
418 13926 : size_t Length() const override { return kP256_PublicKey_Length; }
419 5266 : operator uint8_t *() override { return bytes; }
420 3027 : operator const uint8_t *() const override { return bytes; }
421 3032 : const uint8_t * ConstBytes() const override { return &bytes[0]; }
422 8 : uint8_t * Bytes() override { return &bytes[0]; }
423 756 : bool IsUncompressed() const override
424 : {
425 756 : constexpr uint8_t kUncompressedPointMarker = 0x04;
426 : // SEC1 definition of an uncompressed point is (0x04 || X || Y) where X and Y are
427 : // raw zero-padded big-endian large integers of the group size.
428 756 : return (Length() == ((kP256_FE_Length * 2) + 1)) && (ConstBytes()[0] == kUncompressedPointMarker);
429 : }
430 :
431 : CHIP_ERROR ECDSA_validate_msg_signature(const uint8_t * msg, size_t msg_length,
432 : const P256ECDSASignature & signature) const override;
433 : CHIP_ERROR ECDSA_validate_hash_signature(const uint8_t * hash, size_t hash_length,
434 : const P256ECDSASignature & signature) const override;
435 :
436 : private:
437 : uint8_t bytes[kP256_PublicKey_Length];
438 : };
439 :
440 : template <typename PK, typename Secret, typename Sig>
441 : class ECPKeypair
442 : {
443 : protected:
444 : // This base type can't be copied / assigned directly.
445 : // Sub-types should be either uncopyable or final.
446 1341 : ECPKeypair() = default;
447 : ECPKeypair(const ECPKeypair &) = default;
448 : ECPKeypair & operator=(const ECPKeypair &) = default;
449 :
450 : public:
451 1637 : virtual ~ECPKeypair() = default;
452 :
453 : /** @brief Generate a new Certificate Signing Request (CSR).
454 : * @param csr Newly generated CSR in DER format
455 : * @param csr_length The caller provides the length of input buffer (csr). The function returns the actual length of generated
456 : *CSR.
457 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
458 : **/
459 : virtual CHIP_ERROR NewCertificateSigningRequest(uint8_t * csr, size_t & csr_length) const = 0;
460 :
461 : /**
462 : * @brief A function to sign a msg using ECDSA
463 : * @param msg Message that needs to be signed
464 : * @param msg_length Length of message
465 : * @param out_signature Buffer that will hold the output signature. The signature consists of: 2 EC elements (r and s),
466 : * in raw <r,s> point form (see SEC1).
467 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
468 : **/
469 : virtual CHIP_ERROR ECDSA_sign_msg(const uint8_t * msg, size_t msg_length, Sig & out_signature) const = 0;
470 :
471 : /** @brief A function to derive a shared secret using ECDH
472 : * @param remote_public_key Public key of remote peer with which we are trying to establish secure channel. remote_public_key is
473 : * ASN.1 DER encoded as padded big-endian field elements as described in SEC 1: Elliptic Curve Cryptography
474 : * [https://www.secg.org/sec1-v2.pdf]
475 : * @param out_secret Buffer to write out secret into. This is a byte array representing the x coordinate of the shared secret.
476 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
477 : **/
478 : virtual CHIP_ERROR ECDH_derive_secret(const PK & remote_public_key, Secret & out_secret) const = 0;
479 :
480 : virtual const PK & Pubkey() const = 0;
481 : };
482 :
483 : struct alignas(size_t) P256KeypairContext
484 : {
485 : uint8_t mBytes[kMAX_P256Keypair_Context_Size];
486 : };
487 :
488 : /**
489 : * A serialized P256 key pair is the concatenation of the public and private keys, in that order.
490 : */
491 : using P256SerializedKeypair = SensitiveDataBuffer<kP256_PublicKey_Length + kP256_PrivateKey_Length>;
492 :
493 : class P256KeypairBase : public ECPKeypair<P256PublicKey, P256ECDHDerivedSecret, P256ECDSASignature>
494 : {
495 : protected:
496 : // This base type can't be copied / assigned directly.
497 : // Sub-types should be either uncopyable or final.
498 1341 : P256KeypairBase() = default;
499 : P256KeypairBase(const P256KeypairBase &) = default;
500 : P256KeypairBase & operator=(const P256KeypairBase &) = default;
501 :
502 : public:
503 : /**
504 : * @brief Initialize the keypair.
505 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
506 : **/
507 : virtual CHIP_ERROR Initialize(ECPKeyTarget key_target) = 0;
508 :
509 : /**
510 : * @brief Serialize the keypair.
511 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
512 : **/
513 : virtual CHIP_ERROR Serialize(P256SerializedKeypair & output) const = 0;
514 :
515 : /**
516 : * @brief Deserialize the keypair.
517 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
518 : **/
519 : virtual CHIP_ERROR Deserialize(P256SerializedKeypair & input) = 0;
520 : };
521 :
522 : class P256Keypair : public P256KeypairBase
523 : {
524 : public:
525 1341 : P256Keypair() = default;
526 : ~P256Keypair() override;
527 :
528 : // P256Keypair can't be copied / assigned.
529 : P256Keypair(const P256Keypair &) = delete;
530 : P256Keypair & operator=(const P256Keypair &) = delete;
531 :
532 : /**
533 : * @brief Initialize the keypair.
534 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
535 : **/
536 : CHIP_ERROR Initialize(ECPKeyTarget key_target) override;
537 :
538 : /**
539 : * @brief Serialize the keypair.
540 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
541 : **/
542 : CHIP_ERROR Serialize(P256SerializedKeypair & output) const override;
543 :
544 : /**
545 : * @brief Deserialize the keypair.
546 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
547 : **/
548 : CHIP_ERROR Deserialize(P256SerializedKeypair & input) override;
549 :
550 : /**
551 : * @brief Generate a new Certificate Signing Request (CSR).
552 : * @param csr Newly generated CSR in DER format
553 : * @param csr_length The caller provides the length of input buffer (csr). The function returns the actual length of generated
554 : *CSR.
555 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
556 : **/
557 : CHIP_ERROR NewCertificateSigningRequest(uint8_t * csr, size_t & csr_length) const override;
558 :
559 : /**
560 : * @brief A function to sign a msg using ECDSA
561 : * @param msg Message that needs to be signed
562 : * @param msg_length Length of message
563 : * @param out_signature Buffer that will hold the output signature. The signature consists of: 2 EC elements (r and s),
564 : * in raw <r,s> point form (see SEC1).
565 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
566 : **/
567 : CHIP_ERROR ECDSA_sign_msg(const uint8_t * msg, size_t msg_length, P256ECDSASignature & out_signature) const override;
568 :
569 : /**
570 : * @brief A function to derive a shared secret using ECDH
571 : *
572 : * This implements the CHIP_Crypto_ECDH(PrivateKey myPrivateKey, PublicKey theirPublicKey) cryptographic primitive
573 : * from the specification, using this class's private key from `mKeypair` as `myPrivateKey` and the remote
574 : * public key from `remote_public_key` as `theirPublicKey`.
575 : *
576 : * @param remote_public_key Public key of remote peer with which we are trying to establish secure channel. remote_public_key is
577 : * ASN.1 DER encoded as padded big-endian field elements as described in SEC 1: Elliptic Curve Cryptography
578 : * [https://www.secg.org/sec1-v2.pdf]
579 : * @param out_secret Buffer to write out secret into. This is a byte array representing the x coordinate of the shared secret.
580 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
581 : **/
582 : CHIP_ERROR ECDH_derive_secret(const P256PublicKey & remote_public_key, P256ECDHDerivedSecret & out_secret) const override;
583 :
584 : /** @brief Return public key for the keypair.
585 : **/
586 777 : const P256PublicKey & Pubkey() const override { return mPublicKey; }
587 :
588 : /** Release resources associated with this key pair */
589 : void Clear();
590 :
591 : protected:
592 : P256PublicKey mPublicKey;
593 : mutable P256KeypairContext mKeypair;
594 : bool mInitialized = false;
595 : };
596 :
597 : /**
598 : * @brief Platform-specific symmetric key handle
599 : *
600 : * The class represents a key used by the Matter stack either in the form of raw key material or key
601 : * reference, depending on the platform. To achieve that, it contains an opaque context that can be
602 : * cast to a concrete representation used by the given platform.
603 : *
604 : * @note SymmetricKeyHandle is an abstract class to force child classes for each key handle type.
605 : * SymmetricKeyHandle class implements all the necessary components for handles.
606 : */
607 : template <size_t ContextSize>
608 : class SymmetricKeyHandle
609 : {
610 : public:
611 : SymmetricKeyHandle(const SymmetricKeyHandle &) = delete;
612 : SymmetricKeyHandle(SymmetricKeyHandle &&) = delete;
613 : void operator=(const SymmetricKeyHandle &) = delete;
614 : void operator=(SymmetricKeyHandle &&) = delete;
615 :
616 : /**
617 : * @brief Get internal context cast to the desired key representation
618 : */
619 : template <class T>
620 20063 : const T & As() const
621 : {
622 20063 : return *SafePointerCast<const T *>(&mContext);
623 : }
624 :
625 : /**
626 : * @brief Get internal context cast to the desired, mutable key representation
627 : */
628 : template <class T>
629 7064 : T & AsMutable()
630 : {
631 7064 : return *SafePointerCast<T *>(&mContext);
632 : }
633 :
634 : protected:
635 271020 : SymmetricKeyHandle() = default;
636 271020 : ~SymmetricKeyHandle() { ClearSecretData(mContext.mOpaque); }
637 :
638 : private:
639 : struct alignas(uintptr_t) OpaqueContext
640 : {
641 : uint8_t mOpaque[ContextSize] = {};
642 : } mContext;
643 : };
644 :
645 : using Symmetric128BitsKeyByteArray = uint8_t[CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES];
646 :
647 : /**
648 : * @brief Platform-specific 128-bit symmetric key handle
649 : */
650 : class Symmetric128BitsKeyHandle : public SymmetricKeyHandle<CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES>
651 : {
652 : };
653 :
654 : /**
655 : * @brief Platform-specific 128-bit AES key handle
656 : */
657 : class Aes128KeyHandle final : public Symmetric128BitsKeyHandle
658 : {
659 : };
660 :
661 : /**
662 : * @brief Platform-specific 128-bit HMAC key handle
663 : */
664 : class Hmac128KeyHandle final : public Symmetric128BitsKeyHandle
665 : {
666 : };
667 :
668 : /**
669 : * @brief Platform-specific HKDF key handle
670 : */
671 : class HkdfKeyHandle final : public SymmetricKeyHandle<CHIP_CONFIG_HKDF_KEY_HANDLE_CONTEXT_SIZE>
672 : {
673 : };
674 :
675 : /**
676 : * @brief Convert a raw ECDSA signature to ASN.1 signature (per X9.62) as used by TLS libraries.
677 : *
678 : * Errors are:
679 : * - CHIP_ERROR_INVALID_ARGUMENT on any argument being invalid (e.g. nullptr), wrong sizes,
680 : * wrong or unsupported format,
681 : * - CHIP_ERROR_BUFFER_TOO_SMALL on running out of space at runtime.
682 : * - CHIP_ERROR_INTERNAL on any unexpected processing error.
683 : *
684 : * @param[in] fe_length_bytes Field Element length in bytes (e.g. 32 for P256 curve)
685 : * @param[in] raw_sig Raw signature of <r,s> concatenated
686 : * @param[out] out_asn1_sig ASN.1 DER signature format output buffer. Size must have space for at least
687 : * kMax_ECDSA_X9Dot62_Asn1_Overhead. On CHIP_NO_ERROR, the out_asn1_sig buffer will be re-assigned
688 : * to have the correct size based on variable-length output.
689 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
690 : */
691 : CHIP_ERROR EcdsaRawSignatureToAsn1(size_t fe_length_bytes, const ByteSpan & raw_sig, MutableByteSpan & out_asn1_sig);
692 :
693 : /**
694 : * @brief Convert an ASN.1 DER signature (per X9.62) as used by TLS libraries to SEC1 raw format
695 : *
696 : * Errors are:
697 : * - CHIP_ERROR_INVALID_ARGUMENT on any argument being invalid (e.g. nullptr), wrong sizes,
698 : * wrong or unsupported format,
699 : * - CHIP_ERROR_BUFFER_TOO_SMALL on running out of space at runtime.
700 : * - CHIP_ERROR_INTERNAL on any unexpected processing error.
701 : *
702 : * @param[in] fe_length_bytes Field Element length in bytes (e.g. 32 for P256 curve)
703 : * @param[in] asn1_sig ASN.1 DER signature input
704 : * @param[out] out_raw_sig Raw signature of <r,s> concatenated format output buffer. Size must be at
705 : * least >= `2 * fe_length_bytes`. On CHIP_NO_ERROR, the out_raw_sig buffer will be re-assigned
706 : * to have the correct size (2 * fe_length_bytes).
707 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
708 : */
709 : CHIP_ERROR EcdsaAsn1SignatureToRaw(size_t fe_length_bytes, const ByteSpan & asn1_sig, MutableByteSpan & out_raw_sig);
710 :
711 : /**
712 : * @brief Utility to read a length field after a tag in a DER-encoded stream.
713 : * @param[in] reader Reader instance from which the input will be read
714 : * @param[out] length Length of the following element read from the stream
715 : * @return CHIP_ERROR_INVALID_ARGUMENT or CHIP_ERROR_BUFFER_TOO_SMALL on error, CHIP_NO_ERROR otherwise
716 : */
717 : CHIP_ERROR ReadDerLength(chip::Encoding::LittleEndian::Reader & reader, size_t & length);
718 :
719 : /**
720 : * @brief Utility to emit a DER-encoded INTEGER given a raw unsigned large integer
721 : * in big-endian order. The `out_der_integer` span is updated to reflect the final
722 : * variable length, including tag and length, and must have at least `kEmitDerIntegerOverhead`
723 : * extra space in addition to the `raw_integer.size()`.
724 : * @param[in] raw_integer Bytes of a large unsigned integer in big-endian, possibly including leading zeroes
725 : * @param[out] out_der_integer Buffer to receive the DER-encoded integer
726 : * @return Returns CHIP_ERROR_INVALID_ARGUMENT or CHIP_ERROR_BUFFER_TOO_SMALL on error, CHIP_NO_ERROR otherwise.
727 : */
728 : CHIP_ERROR ConvertIntegerRawToDer(const ByteSpan & raw_integer, MutableByteSpan & out_der_integer);
729 :
730 : /**
731 : * @brief Utility to emit a DER-encoded INTEGER given a raw unsigned large integer
732 : * in big-endian order. The `out_der_integer` span is updated to reflect the final
733 : * variable length, excluding tag and length, and must have at least `kEmitDerIntegerWithoutTagOverhead`
734 : * extra space in addition to the `raw_integer.size()`.
735 : * @param[in] raw_integer Bytes of a large unsigned integer in big-endian, possibly including leading zeroes
736 : * @param[out] out_der_integer Buffer to receive the DER-encoded integer
737 : * @return Returns CHIP_ERROR_INVALID_ARGUMENT or CHIP_ERROR_BUFFER_TOO_SMALL on error, CHIP_NO_ERROR otherwise.
738 : */
739 : CHIP_ERROR ConvertIntegerRawToDerWithoutTag(const ByteSpan & raw_integer, MutableByteSpan & out_der_integer);
740 :
741 : /**
742 : * @brief A function that implements AES-CCM encryption
743 : *
744 : * This implements the CHIP_Crypto_AEAD_GenerateEncrypt() cryptographic primitive
745 : * from the specification. For an empty plaintext, the user of the API can provide
746 : * an empty string, or a nullptr, and provide plaintext_length as 0. The output buffer,
747 : * ciphertext can also be an empty string, or a nullptr for this case.
748 : *
749 : * @param plaintext Plaintext to encrypt
750 : * @param plaintext_length Length of plain_text
751 : * @param aad Additional authentication data
752 : * @param aad_length Length of additional authentication data
753 : * @param key Encryption key
754 : * @param nonce Encryption nonce
755 : * @param nonce_length Length of encryption nonce
756 : * @param ciphertext Buffer to write ciphertext into. Caller must ensure this is large enough to hold the ciphertext
757 : * @param tag Buffer to write tag into. Caller must ensure this is large enough to hold the tag
758 : * @param tag_length Expected length of tag
759 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
760 : * */
761 : CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, const uint8_t * aad, size_t aad_length,
762 : const Aes128KeyHandle & key, const uint8_t * nonce, size_t nonce_length, uint8_t * ciphertext,
763 : uint8_t * tag, size_t tag_length);
764 :
765 : /**
766 : * @brief A function that implements AES-CCM decryption
767 : *
768 : * This implements the CHIP_Crypto_AEAD_DecryptVerify() cryptographic primitive
769 : * from the specification. For an empty ciphertext, the user of the API can provide
770 : * an empty string, or a nullptr, and provide ciphertext_length as 0. The output buffer,
771 : * plaintext can also be an empty string, or a nullptr for this case.
772 : *
773 : * @param ciphertext Ciphertext to decrypt
774 : * @param ciphertext_length Length of ciphertext
775 : * @param aad Additional authentical data.
776 : * @param aad_length Length of additional authentication data
777 : * @param tag Tag to use to decrypt
778 : * @param tag_length Length of tag
779 : * @param key Decryption key
780 : * @param nonce Encryption nonce
781 : * @param nonce_length Length of encryption nonce
782 : * @param plaintext Buffer to write plaintext into
783 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
784 : **/
785 : CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_length, const uint8_t * aad, size_t aad_length,
786 : const uint8_t * tag, size_t tag_length, const Aes128KeyHandle & key, const uint8_t * nonce,
787 : size_t nonce_length, uint8_t * plaintext);
788 :
789 : /**
790 : * @brief A function that implements AES-CTR encryption/decryption
791 : *
792 : * This implements the AES-CTR-Encrypt/Decrypt() cryptographic primitives per sections
793 : * 3.7.1 and 3.7.2 of the specification. For an empty input, the user of the API
794 : * can provide an empty string, or a nullptr, and provide input as 0.
795 : * The output buffer can also be an empty string, or a nullptr for this case.
796 : *
797 : * @param input Input text to encrypt/decrypt
798 : * @param input_length Length of ciphertext
799 : * @param key Decryption key
800 : * @param nonce Encryption nonce
801 : * @param nonce_length Length of encryption nonce
802 : * @param output Buffer to write output into
803 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
804 : **/
805 : CHIP_ERROR AES_CTR_crypt(const uint8_t * input, size_t input_length, const Aes128KeyHandle & key, const uint8_t * nonce,
806 : size_t nonce_length, uint8_t * output);
807 :
808 : /**
809 : * @brief Generate a PKCS#10 CSR, usable for Matter, from a P256Keypair.
810 : *
811 : * This uses first principles ASN.1 encoding to avoid relying on the CHIPCryptoPAL backend
812 : * itself, other than to provide an implementation of a P256Keypair * that supports
813 : * at least `::Pubkey()` and `::ECDSA_sign_msg`. This allows using it with
814 : * OS/Platform-bridged private key handling, without requiring a specific
815 : * implementation of other bits like ASN.1.
816 : *
817 : * The CSR will have subject OU set to `CSA`. This is needed since omiting
818 : * subject altogether often trips CSR parsing code. The profile at the CA can
819 : * be configured to ignore CSR requested subject.
820 : *
821 : * @param keypair The key pair for which a CSR should be generated. Must not be null.
822 : * @param csr_span Span to hold the resulting CSR. Must have size at least kMIN_CSR_Buffer_Size.
823 : * Otherwise returns CHIP_ERROR_BUFFER_TOO_SMALL. It will get resized to
824 : * actual size needed on success.
825 :
826 : * @return Returns a CHIP_ERROR from P256Keypair or ASN.1 backend on error, CHIP_NO_ERROR otherwise
827 : **/
828 : CHIP_ERROR GenerateCertificateSigningRequest(const P256Keypair * keypair, MutableByteSpan & csr_span);
829 :
830 : /**
831 : * @brief Common code to validate ASN.1 format/size of a CSR, used by VerifyCertificateSigningRequest.
832 : *
833 : * Ensures it's not obviously malformed and doesn't have trailing garbage.
834 : *
835 : * @param csr CSR in DER format
836 : * @param csr_length The length of the CSR buffer
837 : * @return CHIP_ERROR_UNSUPPORTED_CERT_FORMAT on invalid format, CHIP_NO_ERROR otherwise.
838 : */
839 : CHIP_ERROR VerifyCertificateSigningRequestFormat(const uint8_t * csr, size_t csr_length);
840 :
841 : /**
842 : * @brief Verify the Certificate Signing Request (CSR). If successfully verified, it outputs the public key from the CSR.
843 : *
844 : * The CSR is valid if the format is correct, the signature validates with the embedded public
845 : * key, and there is no trailing garbage data.
846 : *
847 : * @param csr CSR in DER format
848 : * @param csr_length The length of the CSR
849 : * @param pubkey The public key from the verified CSR
850 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
851 : **/
852 : CHIP_ERROR VerifyCertificateSigningRequest(const uint8_t * csr, size_t csr_length, P256PublicKey & pubkey);
853 :
854 : /**
855 : * @brief A function that implements SHA-256 hash
856 : *
857 : * This implements the CHIP_Crypto_Hash() cryptographic primitive
858 : * in the the specification.
859 : *
860 : * @param data The data to hash
861 : * @param data_length Length of the data
862 : * @param out_buffer Pointer to buffer to write output into
863 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
864 : **/
865 :
866 : CHIP_ERROR Hash_SHA256(const uint8_t * data, size_t data_length, uint8_t * out_buffer);
867 :
868 : /**
869 : * @brief A function that implements SHA-1 hash
870 : * @param data The data to hash
871 : * @param data_length Length of the data
872 : * @param out_buffer Pointer to buffer to write output into
873 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
874 : **/
875 :
876 : CHIP_ERROR Hash_SHA1(const uint8_t * data, size_t data_length, uint8_t * out_buffer);
877 :
878 : /**
879 : * @brief A class that defines stream based implementation of SHA-256 hash
880 : * It's expected that the object of this class can be safely copied.
881 : * All implementations must check for std::is_trivially_copyable.
882 : **/
883 :
884 : struct alignas(CHIP_CONFIG_SHA256_CONTEXT_ALIGN) HashSHA256OpaqueContext
885 : {
886 : uint8_t mOpaque[kMAX_Hash_SHA256_Context_Size];
887 : };
888 :
889 : class Hash_SHA256_stream
890 : {
891 : public:
892 : Hash_SHA256_stream();
893 : ~Hash_SHA256_stream();
894 :
895 : /**
896 : * @brief Re-initialize digest computation to an empty context.
897 : *
898 : * @return CHIP_ERROR_INTERNAL on failure to initialize the context,
899 : * CHIP_NO_ERROR otherwise.
900 : */
901 : CHIP_ERROR Begin();
902 :
903 : /**
904 : * @brief Add some data to the digest computation, updating internal state.
905 : *
906 : * @param[in] data The span of bytes to include in the digest update process.
907 : *
908 : * @return CHIP_ERROR_INTERNAL on failure to ingest the data, CHIP_NO_ERROR otherwise.
909 : */
910 : CHIP_ERROR AddData(const ByteSpan data);
911 :
912 : /**
913 : * @brief Get the intermediate padded digest for the current state of the stream.
914 : *
915 : * More data can be added before finish is called.
916 : *
917 : * @param[in,out] out_buffer Output buffer to receive the digest. `out_buffer` must
918 : * be at least `kSHA256_Hash_Length` bytes long. The `out_buffer` size
919 : * will be set to `kSHA256_Hash_Length` on success.
920 : *
921 : * @return CHIP_ERROR_INTERNAL on failure to compute the digest, CHIP_ERROR_BUFFER_TOO_SMALL
922 : * if out_buffer is too small, CHIP_NO_ERROR otherwise.
923 : */
924 : CHIP_ERROR GetDigest(MutableByteSpan & out_buffer);
925 :
926 : /**
927 : * @brief Finalize the stream digest computation, getting the final digest.
928 : *
929 : * @param[in,out] out_buffer Output buffer to receive the digest. `out_buffer` must
930 : * be at least `kSHA256_Hash_Length` bytes long. The `out_buffer` size
931 : * will be set to `kSHA256_Hash_Length` on success.
932 : *
933 : * @return CHIP_ERROR_INTERNAL on failure to compute the digest, CHIP_ERROR_BUFFER_TOO_SMALL
934 : * if out_buffer is too small, CHIP_NO_ERROR otherwise.
935 : */
936 : CHIP_ERROR Finish(MutableByteSpan & out_buffer);
937 :
938 : /**
939 : * @brief Clear-out internal digest data to avoid lingering the state.
940 : */
941 : void Clear();
942 :
943 : private:
944 : // Check if the digest computation has been initialized; implement this if your backend needs it.
945 : bool IsInitialized();
946 :
947 : HashSHA256OpaqueContext mContext;
948 : };
949 :
950 : class HKDF_sha
951 : {
952 : public:
953 : HKDF_sha() = default;
954 3662 : virtual ~HKDF_sha() = default;
955 :
956 : /**
957 : * @brief A function that implements SHA-256 based HKDF
958 : *
959 : * This implements the CHIP_Crypto_KDF() cryptographic primitive
960 : * in the the specification.
961 : *
962 : * Error values are:
963 : * - CHIP_ERROR_INVALID_ARGUMENT: for any bad arguments or nullptr input on
964 : * any pointer.
965 : * - CHIP_ERROR_INTERNAL: for any unexpected error arising in the underlying
966 : * cryptographic layers.
967 : *
968 : * @param secret The secret to use as the key to the HKDF
969 : * @param secret_length Length of the secret
970 : * @param salt Optional salt to use as input to the HKDF
971 : * @param salt_length Length of the salt
972 : * @param info Optional info to use as input to the HKDF
973 : * @param info_length Length of the info
974 : * @param out_buffer Pointer to buffer to write output into.
975 : * @param out_length Size of the underlying out_buffer. That length of output key material will be generated in out_buffer.
976 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
977 : **/
978 :
979 : virtual CHIP_ERROR HKDF_SHA256(const uint8_t * secret, size_t secret_length, const uint8_t * salt, size_t salt_length,
980 : const uint8_t * info, size_t info_length, uint8_t * out_buffer, size_t out_length);
981 : };
982 :
983 : class HMAC_sha
984 : {
985 : public:
986 : HMAC_sha() = default;
987 92 : virtual ~HMAC_sha() = default;
988 :
989 : /**
990 : * @brief A function that implements SHA-256 based HMAC per FIPS1981.
991 : *
992 : * This implements the CHIP_Crypto_HMAC() cryptographic primitive
993 : * in the the specification.
994 : *
995 : * The `out_length` must be at least kSHA256_Hash_Length, and only
996 : * kSHA256_Hash_Length bytes are written to out_buffer.
997 : *
998 : * Error values are:
999 : * - CHIP_ERROR_INVALID_ARGUMENT: for any bad arguments or nullptr input on
1000 : * any pointer.
1001 : * - CHIP_ERROR_INTERNAL: for any unexpected error arising in the underlying
1002 : * cryptographic layers.
1003 : *
1004 : * @param key The key to use for the HMAC operation
1005 : * @param key_length Length of the key
1006 : * @param message Message over which to compute the HMAC
1007 : * @param message_length Length of the message over which to compute the HMAC
1008 : * @param out_buffer Pointer to buffer into which to write the output.
1009 : * @param out_length Underlying size of the `out_buffer`.
1010 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
1011 : **/
1012 :
1013 : virtual CHIP_ERROR HMAC_SHA256(const uint8_t * key, size_t key_length, const uint8_t * message, size_t message_length,
1014 : uint8_t * out_buffer, size_t out_length);
1015 :
1016 : /**
1017 : * @brief A function that implements SHA-256 based HMAC per FIPS1981.
1018 : *
1019 : * This implements the CHIP_Crypto_HMAC() cryptographic primitive
1020 : * in the the specification.
1021 : *
1022 : * The `out_length` must be at least kSHA256_Hash_Length, and only
1023 : * kSHA256_Hash_Length bytes are written to out_buffer.
1024 : *
1025 : * Error values are:
1026 : * - CHIP_ERROR_INVALID_ARGUMENT: for any bad arguments or nullptr input on
1027 : * any pointer.
1028 : * - CHIP_ERROR_INTERNAL: for any unexpected error arising in the underlying
1029 : * cryptographic layers.
1030 : *
1031 : * @param key The HMAC Key handle to use for the HMAC operation
1032 : * @param message Message over which to compute the HMAC
1033 : * @param message_length Length of the message over which to compute the HMAC
1034 : * @param out_buffer Pointer to buffer into which to write the output.
1035 : * @param out_length Underlying size of the `out_buffer`.
1036 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
1037 : **/
1038 : virtual CHIP_ERROR HMAC_SHA256(const Hmac128KeyHandle & key, const uint8_t * message, size_t message_length,
1039 : uint8_t * out_buffer, size_t out_length);
1040 : };
1041 :
1042 : /**
1043 : * @brief A cryptographically secure random number generator based on NIST SP800-90A
1044 : * @param out_buffer Buffer into which to write random bytes
1045 : * @param out_length Number of random bytes to generate
1046 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
1047 : **/
1048 : CHIP_ERROR DRBG_get_bytes(uint8_t * out_buffer, size_t out_length);
1049 :
1050 : /** @brief Entropy callback function
1051 : * @param data Callback-specific data pointer
1052 : * @param output Output data to fill
1053 : * @param len Length of output buffer
1054 : * @param olen The actual amount of data that was written to output buffer
1055 : * @return 0 if success
1056 : */
1057 : typedef int (*entropy_source)(void * data, uint8_t * output, size_t len, size_t * olen);
1058 :
1059 : /** @brief A function to add entropy sources to crypto library
1060 : *
1061 : * This function can be called multiple times to add multiple entropy sources. However,
1062 : * once the entropy source is added, it cannot be removed. Please make sure that the
1063 : * entropy source is valid for the lifetime of the application. Also, make sure that the
1064 : * same entropy source is not added multiple times, e.g.: by calling this function
1065 : * in class constructor or initialization function.
1066 : *
1067 : * @param fn_source Function pointer to the entropy source
1068 : * @param p_source Data that should be provided when fn_source is called
1069 : * @param threshold Minimum required from source before entropy is released
1070 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
1071 : **/
1072 : CHIP_ERROR add_entropy_source(entropy_source fn_source, void * p_source, size_t threshold);
1073 :
1074 : class PBKDF2_sha256
1075 : {
1076 : public:
1077 : PBKDF2_sha256() = default;
1078 9 : virtual ~PBKDF2_sha256() = default;
1079 :
1080 : /** @brief Function to derive key using password. SHA256 hashing algorithm is used for calculating hmac.
1081 : * @param password password used for key derivation
1082 : * @param plen length of buffer containing password
1083 : * @param salt salt to use as input to the KDF
1084 : * @param slen length of salt
1085 : * @param iteration_count number of iterations to run
1086 : * @param key_length length of output key
1087 : * @param output output buffer where the key will be written
1088 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
1089 : **/
1090 : virtual CHIP_ERROR pbkdf2_sha256(const uint8_t * password, size_t plen, const uint8_t * salt, size_t slen,
1091 : unsigned int iteration_count, uint32_t key_length, uint8_t * output);
1092 : };
1093 :
1094 : // TODO: Extract Spake2p to a separate header and replace the forward declaration with #include SessionKeystore.h
1095 : class SessionKeystore;
1096 :
1097 : /**
1098 : * The below class implements the draft 01 version of the Spake2+ protocol as
1099 : * defined in https://www.ietf.org/id/draft-bar-cfrg-spake2plus-01.html.
1100 : *
1101 : * The following describes the protocol flows:
1102 : *
1103 : * Commissioner Accessory
1104 : * ------------ ---------
1105 : *
1106 : * Init
1107 : * BeginProver
1108 : * ComputeRoundOne ------------->
1109 : * Init
1110 : * BeginVerifier
1111 : * /- ComputeRoundOne
1112 : * <------------- ComputeRoundTwo
1113 : * ComputeRoundTwo ------------->
1114 : * KeyConfirm KeyConfirm
1115 : * GetKeys GetKeys
1116 : *
1117 : **/
1118 : class Spake2p
1119 : {
1120 : public:
1121 : Spake2p(size_t fe_size, size_t point_size, size_t hash_size);
1122 19 : virtual ~Spake2p() = default;
1123 :
1124 : /**
1125 : * @brief Initialize Spake2+ with some context specific information.
1126 : *
1127 : * @param context The context is arbitrary but should include information about the
1128 : * protocol being run, contain the transcript for negotiation, include
1129 : * the PKBDF parameters, etc.
1130 : * @param context_len The length of the context.
1131 : *
1132 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
1133 : **/
1134 : virtual CHIP_ERROR Init(const uint8_t * context, size_t context_len);
1135 :
1136 : /**
1137 : * @brief Free Spake2+ underlying objects.
1138 : **/
1139 : virtual void Clear() = 0;
1140 :
1141 : /**
1142 : * @brief Start the Spake2+ process as a verifier (i.e. an accessory being provisioned).
1143 : *
1144 : * @param my_identity The verifier identity. May be NULL if identities are not established.
1145 : * @param my_identity_len The verifier identity length.
1146 : * @param peer_identity The peer identity. May be NULL if identities are not established.
1147 : * @param peer_identity_len The peer identity length.
1148 : * @param w0in The input w0 (a parameter baked into the device or computed with ComputeW0).
1149 : * @param w0in_len The input w0 length.
1150 : * @param Lin The input L (a parameter baked into the device or computed with ComputeL).
1151 : * @param Lin_len The input L length.
1152 : *
1153 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
1154 : **/
1155 : virtual CHIP_ERROR BeginVerifier(const uint8_t * my_identity, size_t my_identity_len, const uint8_t * peer_identity,
1156 : size_t peer_identity_len, const uint8_t * w0in, size_t w0in_len, const uint8_t * Lin,
1157 : size_t Lin_len);
1158 :
1159 : /**
1160 : * @brief Start the Spake2+ process as a prover (i.e. a commissioner).
1161 : *
1162 : * @param my_identity The prover identity. May be NULL if identities are not established.
1163 : * @param my_identity_len The prover identity length.
1164 : * @param peer_identity The peer identity. May be NULL if identities are not established.
1165 : * @param peer_identity_len The peer identity length.
1166 : * @param w0sin The input w0s (an output from the PBKDF).
1167 : * @param w0sin_len The input w0s length.
1168 : * @param w1sin The input w1s (an output from the PBKDF).
1169 : * @param w1sin_len The input w1s length.
1170 : *
1171 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
1172 : **/
1173 : virtual CHIP_ERROR BeginProver(const uint8_t * my_identity, size_t my_identity_len, const uint8_t * peer_identity,
1174 : size_t peer_identity_len, const uint8_t * w0sin, size_t w0sin_len, const uint8_t * w1sin,
1175 : size_t w1sin_len);
1176 :
1177 : /**
1178 : * @brief Compute the first round of the protocol.
1179 : *
1180 : * @param pab X value from commissioner.
1181 : * @param pab_len X length.
1182 : * @param out The output first round Spake2+ contribution.
1183 : * @param out_len The output first round Spake2+ contribution length.
1184 : *
1185 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
1186 : **/
1187 : virtual CHIP_ERROR ComputeRoundOne(const uint8_t * pab, size_t pab_len, uint8_t * out, size_t * out_len);
1188 :
1189 : /**
1190 : * @brief Compute the second round of the protocol.
1191 : *
1192 : * @param in The peer first round Spake2+ contribution.
1193 : * @param in_len The peer first round Spake2+ contribution length.
1194 : * @param out The output second round Spake2+ contribution.
1195 : * @param out_len The output second round Spake2+ contribution length.
1196 : *
1197 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
1198 : **/
1199 : virtual CHIP_ERROR ComputeRoundTwo(const uint8_t * in, size_t in_len, uint8_t * out, size_t * out_len);
1200 :
1201 : /**
1202 : * @brief Confirm that each party computed the same keys.
1203 : *
1204 : * @param in The peer second round Spake2+ contribution.
1205 : * @param in_len The peer second round Spake2+ contribution length.
1206 : *
1207 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
1208 : **/
1209 : virtual CHIP_ERROR KeyConfirm(const uint8_t * in, size_t in_len);
1210 :
1211 : /**
1212 : * @brief Return the shared HKDF key.
1213 : *
1214 : * Returns the shared key established during the Spake2+ process, which can be used
1215 : * to derive application-specific keys using HKDF.
1216 : *
1217 : * @param keystore The session keystore for managing the HKDF key lifetime.
1218 : * @param key The output HKDF key.
1219 : *
1220 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
1221 : **/
1222 : CHIP_ERROR GetKeys(SessionKeystore & keystore, HkdfKeyHandle & key);
1223 :
1224 : CHIP_ERROR InternalHash(const uint8_t * in, size_t in_len);
1225 : CHIP_ERROR WriteMN();
1226 : CHIP_ERROR GenerateKeys();
1227 :
1228 : /**
1229 : * @brief Load a field element.
1230 : *
1231 : * @param in The input big endian field element.
1232 : * @param in_len The size of the input buffer in bytes.
1233 : * @param fe A pointer to an initialized implementation dependant field element.
1234 : *
1235 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
1236 : **/
1237 : virtual CHIP_ERROR FELoad(const uint8_t * in, size_t in_len, void * fe) = 0;
1238 :
1239 : /**
1240 : * @brief Write a field element in big-endian format.
1241 : *
1242 : * @param fe The field element to write.
1243 : * @param out The output buffer.
1244 : * @param out_len The length of the output buffer.
1245 : *
1246 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
1247 : **/
1248 : virtual CHIP_ERROR FEWrite(const void * fe, uint8_t * out, size_t out_len) = 0;
1249 :
1250 : /**
1251 : * @brief Generate a field element.
1252 : *
1253 : * @param fe A pointer to an initialized implementation dependant field element.
1254 : *
1255 : * @note The implementation must generate a random element from [0, q) where q is the curve order.
1256 : *
1257 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
1258 : **/
1259 : virtual CHIP_ERROR FEGenerate(void * fe) = 0;
1260 :
1261 : /**
1262 : * @brief Multiply two field elements, fer = fe1 * fe2.
1263 : *
1264 : * @param fer A pointer to an initialized implementation dependant field element.
1265 : * @param fe1 A pointer to an initialized implementation dependant field element.
1266 : * @param fe2 A pointer to an initialized implementation dependant field element.
1267 : *
1268 : * @note The result must be a field element (i.e. reduced by the curve order).
1269 : *
1270 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
1271 : **/
1272 : virtual CHIP_ERROR FEMul(void * fer, const void * fe1, const void * fe2) = 0;
1273 :
1274 : /**
1275 : * @brief Load a point from 0x04 || X || Y format
1276 : *
1277 : * @param in Input buffer
1278 : * @param in_len Input buffer length
1279 : * @param R A pointer to an initialized implementation dependant point.
1280 : *
1281 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
1282 : **/
1283 : virtual CHIP_ERROR PointLoad(const uint8_t * in, size_t in_len, void * R) = 0;
1284 :
1285 : /**
1286 : * @brief Write a point in 0x04 || X || Y format
1287 : *
1288 : * @param R A pointer to an initialized implementation dependant point.
1289 : * @param out Output buffer
1290 : * @param out_len Length of the output buffer
1291 : *
1292 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
1293 : **/
1294 : virtual CHIP_ERROR PointWrite(const void * R, uint8_t * out, size_t out_len) = 0;
1295 :
1296 : /**
1297 : * @brief Scalar multiplication, R = fe1 * P1.
1298 : *
1299 : * @param R Resultant point
1300 : * @param P1 Input point
1301 : * @param fe1 Input field element.
1302 : *
1303 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
1304 : **/
1305 : virtual CHIP_ERROR PointMul(void * R, const void * P1, const void * fe1) = 0;
1306 :
1307 : /**
1308 : * @brief Scalar multiplication with addition, R = fe1 * P1 + fe2 * P2.
1309 : *
1310 : * @param R Resultant point
1311 : * @param P1 Input point
1312 : * @param fe1 Input field element.
1313 : * @param P2 Input point
1314 : * @param fe2 Input field element.
1315 : *
1316 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
1317 : **/
1318 : virtual CHIP_ERROR PointAddMul(void * R, const void * P1, const void * fe1, const void * P2, const void * fe2) = 0;
1319 :
1320 : /**
1321 : * @brief Point inversion.
1322 : *
1323 : * @param R Input/Output point to point_invert
1324 : *
1325 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
1326 : **/
1327 : virtual CHIP_ERROR PointInvert(void * R) = 0;
1328 :
1329 : /**
1330 : * @brief Multiply a point by the curve cofactor.
1331 : *
1332 : * @param R Input/Output point to point_invert
1333 : *
1334 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
1335 : **/
1336 : virtual CHIP_ERROR PointCofactorMul(void * R) = 0;
1337 :
1338 : /*
1339 : * @synopsis Check if a point is on the curve.
1340 : *
1341 : * @param R Input point to check.
1342 : *
1343 : * @return CHIP_NO_ERROR if the point is valid, CHIP_ERROR otherwise.
1344 : */
1345 : virtual CHIP_ERROR PointIsValid(void * R) = 0;
1346 :
1347 : /*
1348 : * @synopsis Compute w0sin mod p
1349 : *
1350 : * @param w0out Output field element w0
1351 : * @param w0_len Output field element length
1352 : * @param w0sin Input field element
1353 : * @param w0sin_len Input field element length
1354 : *
1355 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
1356 : **/
1357 : virtual CHIP_ERROR ComputeW0(uint8_t * w0out, size_t * w0_len, const uint8_t * w0sin, size_t w0sin_len) = 0;
1358 :
1359 : /*
1360 : * @synopsis Compute w1in*G where w1in is w1sin mod p
1361 : *
1362 : * @param Lout Output point in 0x04 || X || Y format.
1363 : * @param L_len Output point length
1364 : * @param w1sin Input field element
1365 : * @param w1sin_len Input field element size
1366 : *
1367 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
1368 : **/
1369 : virtual CHIP_ERROR ComputeL(uint8_t * Lout, size_t * L_len, const uint8_t * w1sin, size_t w1sin_len) = 0;
1370 :
1371 : void * M;
1372 : void * N;
1373 : const void * G;
1374 : void * X;
1375 : void * Y;
1376 : void * L;
1377 : void * Z;
1378 : void * V;
1379 : void * w0;
1380 : void * w1;
1381 : void * xy;
1382 : void * order;
1383 : void * tempbn;
1384 :
1385 : protected:
1386 : /**
1387 : * @brief Initialize underlying implementation curve, points, field elements, etc.
1388 : *
1389 : * @details The implementation needs to:
1390 : * 1. Initialize each of the points below and set the relevant pointers on the class:
1391 : * a. M
1392 : * b. N
1393 : * c. G
1394 : * d. X
1395 : * e. Y
1396 : * f. L
1397 : * g. Z
1398 : * h. V
1399 : *
1400 : * As an example:
1401 : * this.M = implementation_alloc_point();
1402 : * 2. Initialize each of the field elements below and set the relevant pointers on the class:
1403 : * a. w0
1404 : * b. w1
1405 : * c. xy
1406 : * d. tempbn
1407 : * 3. The hashing context should be initialized
1408 : *
1409 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
1410 : **/
1411 : virtual CHIP_ERROR InitImpl() = 0;
1412 :
1413 : /**
1414 : * @brief Hash in_len bytes of in into the internal hash context.
1415 : *
1416 : * @param in The input buffer.
1417 : * @param in_len Size of the input buffer in bytes.
1418 : *
1419 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
1420 : **/
1421 : virtual CHIP_ERROR Hash(const uint8_t * in, size_t in_len) = 0;
1422 :
1423 : /**
1424 : * @brief Return the hash.
1425 : *
1426 : * @param out_span Output buffer. The size available must be >= the hash size. It gets resized
1427 : * to hash size on success.
1428 : *
1429 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
1430 : **/
1431 : virtual CHIP_ERROR HashFinalize(MutableByteSpan & out_span) = 0;
1432 :
1433 : /**
1434 : * @brief Generate a message authentication code.
1435 : *
1436 : * @param key The MAC key buffer.
1437 : * @param key_len The size of the MAC key in bytes.
1438 : * @param in The input buffer.
1439 : * @param in_len The size of the input data to MAC in bytes.
1440 : * @param out_span The output MAC buffer span. Size must be >= the hash_size. Output size is updated to fit on success.
1441 : *
1442 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
1443 : **/
1444 : virtual CHIP_ERROR Mac(const uint8_t * key, size_t key_len, const uint8_t * in, size_t in_len, MutableByteSpan & out_span) = 0;
1445 :
1446 : /**
1447 : * @brief Verify a message authentication code.
1448 : *
1449 : * @param key The MAC key buffer.
1450 : * @param key_len The size of the MAC key in bytes.
1451 : * @param mac The input MAC buffer.
1452 : * @param mac_len The size of the MAC in bytes.
1453 : * @param in The input buffer to verify.
1454 : * @param in_len The size of the input data to verify in bytes.
1455 : *
1456 : * @return Returns a CHIP_ERROR when the MAC doesn't validate, CHIP_NO_ERROR otherwise.
1457 : **/
1458 : virtual CHIP_ERROR MacVerify(const uint8_t * key, size_t key_len, const uint8_t * mac, size_t mac_len, const uint8_t * in,
1459 : size_t in_len) = 0;
1460 :
1461 : /**
1462 : * @brief Derive an key of length out_len.
1463 : *
1464 : * @param ikm The input key material buffer.
1465 : * @param ikm_len The input key material length.
1466 : * @param salt The optional salt. This may be NULL.
1467 : * @param salt_len The size of the salt in bytes.
1468 : * @param info The info.
1469 : * @param info_len The size of the info in bytes.
1470 : * @param out The output key
1471 : * @param out_len The output key length
1472 : *
1473 : * @return Returns a CHIP_ERROR when the MAC doesn't validate, CHIP_NO_ERROR otherwise.
1474 : **/
1475 : virtual CHIP_ERROR KDF(const uint8_t * ikm, size_t ikm_len, const uint8_t * salt, size_t salt_len, const uint8_t * info,
1476 : size_t info_len, uint8_t * out, size_t out_len) = 0;
1477 :
1478 : CHIP_SPAKE2P_ROLE role;
1479 : CHIP_SPAKE2P_STATE state = CHIP_SPAKE2P_STATE::PREINIT;
1480 : size_t fe_size;
1481 : size_t hash_size;
1482 : size_t point_size;
1483 : uint8_t Kcab[kMAX_Hash_Length];
1484 : uint8_t Kae[kMAX_Hash_Length];
1485 : uint8_t * Kca;
1486 : uint8_t * Kcb;
1487 : uint8_t * Ka;
1488 : uint8_t * Ke;
1489 : };
1490 :
1491 : struct alignas(size_t) Spake2pOpaqueContext
1492 : {
1493 : uint8_t mOpaque[kMAX_Spake2p_Context_Size];
1494 : };
1495 :
1496 : class Spake2p_P256_SHA256_HKDF_HMAC : public Spake2p
1497 : {
1498 : public:
1499 4 : Spake2p_P256_SHA256_HKDF_HMAC() : Spake2p(kP256_FE_Length, kP256_Point_Length, kSHA256_Hash_Length)
1500 : {
1501 4 : memset(&mSpake2pContext, 0, sizeof(mSpake2pContext));
1502 4 : }
1503 :
1504 19 : ~Spake2p_P256_SHA256_HKDF_HMAC() override { Spake2p_P256_SHA256_HKDF_HMAC::Clear(); }
1505 :
1506 : void Clear() override;
1507 : CHIP_ERROR Mac(const uint8_t * key, size_t key_len, const uint8_t * in, size_t in_len, MutableByteSpan & out_span) override;
1508 : CHIP_ERROR MacVerify(const uint8_t * key, size_t key_len, const uint8_t * mac, size_t mac_len, const uint8_t * in,
1509 : size_t in_len) override;
1510 : CHIP_ERROR FELoad(const uint8_t * in, size_t in_len, void * fe) override;
1511 : CHIP_ERROR FEWrite(const void * fe, uint8_t * out, size_t out_len) override;
1512 : CHIP_ERROR FEGenerate(void * fe) override;
1513 : CHIP_ERROR FEMul(void * fer, const void * fe1, const void * fe2) override;
1514 :
1515 : CHIP_ERROR PointLoad(const uint8_t * in, size_t in_len, void * R) override;
1516 : CHIP_ERROR PointWrite(const void * R, uint8_t * out, size_t out_len) override;
1517 : CHIP_ERROR PointMul(void * R, const void * P1, const void * fe1) override;
1518 : CHIP_ERROR PointAddMul(void * R, const void * P1, const void * fe1, const void * P2, const void * fe2) override;
1519 : CHIP_ERROR PointInvert(void * R) override;
1520 : CHIP_ERROR PointCofactorMul(void * R) override;
1521 : CHIP_ERROR PointIsValid(void * R) override;
1522 :
1523 : CHIP_ERROR ComputeW0(uint8_t * w0out, size_t * w0_len, const uint8_t * w0sin, size_t w0sin_len) override;
1524 : CHIP_ERROR ComputeL(uint8_t * Lout, size_t * L_len, const uint8_t * w1sin, size_t w1sin_len) override;
1525 :
1526 : protected:
1527 : CHIP_ERROR InitImpl() override;
1528 : CHIP_ERROR Hash(const uint8_t * in, size_t in_len) override;
1529 : CHIP_ERROR HashFinalize(MutableByteSpan & out_span) override;
1530 : CHIP_ERROR KDF(const uint8_t * secret, size_t secret_length, const uint8_t * salt, size_t salt_length, const uint8_t * info,
1531 : size_t info_length, uint8_t * out, size_t out_length) override;
1532 :
1533 : private:
1534 : CHIP_ERROR InitInternal();
1535 : Hash_SHA256_stream sha256_hash_ctx;
1536 :
1537 : Spake2pOpaqueContext mSpake2pContext;
1538 : };
1539 :
1540 : /**
1541 : * @brief Class used for verifying PASE secure sessions.
1542 : **/
1543 : class Spake2pVerifier
1544 : {
1545 : public:
1546 : uint8_t mW0[kP256_FE_Length];
1547 : uint8_t mL[kP256_Point_Length];
1548 :
1549 : CHIP_ERROR Serialize(MutableByteSpan & outSerialized) const;
1550 : CHIP_ERROR Deserialize(const ByteSpan & inSerialized);
1551 :
1552 : /**
1553 : * @brief Generate the Spake2+ verifier.
1554 : *
1555 : * @param pbkdf2IterCount Iteration count for PBKDF2 function
1556 : * @param salt Salt to be used for Spake2+ operation
1557 : * @param setupPin Provided setup PIN (passcode)
1558 : *
1559 : * @return CHIP_ERROR The result of Spake2+ verifier generation
1560 : */
1561 : CHIP_ERROR Generate(uint32_t pbkdf2IterCount, const ByteSpan & salt, uint32_t setupPin);
1562 :
1563 : /**
1564 : * @brief Compute the initiator values (w0s, w1s) used for PAKE input.
1565 : *
1566 : * @param pbkdf2IterCount Iteration count for PBKDF2 function
1567 : * @param salt Salt to be used for Spake2+ operation
1568 : * @param setupPin Provided setup PIN (passcode)
1569 : * @param ws The output pair (w0s, w1s) stored sequentially
1570 : * @param ws_len The output length
1571 : *
1572 : * @return CHIP_ERROR The result from running PBKDF2
1573 : */
1574 : static CHIP_ERROR ComputeWS(uint32_t pbkdf2IterCount, const ByteSpan & salt, uint32_t setupPin, uint8_t * ws, uint32_t ws_len);
1575 : };
1576 :
1577 : /**
1578 : * @brief Serialized format of the Spake2+ Verifier components.
1579 : *
1580 : * This is used when the Verifier should be presented in a serialized form.
1581 : * For example, when it is generated using PBKDF function, when stored in the
1582 : * memory or when sent over the wire.
1583 : * The serialized format is concatentation of 'W0' and 'L' verifier components:
1584 : * { Spake2pVerifier.mW0[kP256_FE_Length], Spake2pVerifier.mL[kP256_Point_Length] }
1585 : **/
1586 : typedef uint8_t Spake2pVerifierSerialized[kSpake2p_VerifierSerialized_Length];
1587 :
1588 : /**
1589 : * @brief Compute the compressed fabric identifier used for operational discovery service
1590 : * records from a Node's root public key and Fabric ID. On success, out_compressed_fabric_id
1591 : * will have a size of exactly kCompressedFabricIdentifierSize.
1592 : *
1593 : * Errors are:
1594 : * - CHIP_ERROR_INVALID_ARGUMENT if root_public_key is invalid
1595 : * - CHIP_ERROR_BUFFER_TOO_SMALL if out_compressed_fabric_id is too small for serialization
1596 : * - CHIP_ERROR_INTERNAL on any unexpected crypto or data conversion errors.
1597 : *
1598 : * @param[in] root_public_key The root public key associated with the node's fabric
1599 : * @param[in] fabric_id The fabric ID associated with the node's fabric
1600 : * @param[out] out_compressed_fabric_id Span where output will be written. Its size must be >= kCompressedFabricIdentifierSize.
1601 : * @returns a CHIP_ERROR (see above) on failure or CHIP_NO_ERROR otherwise.
1602 : */
1603 : CHIP_ERROR GenerateCompressedFabricId(const Crypto::P256PublicKey & root_public_key, uint64_t fabric_id,
1604 : MutableByteSpan & out_compressed_fabric_id);
1605 :
1606 : /**
1607 : * @brief Compute the compressed fabric identifier used for operational discovery service
1608 : * records from a Node's root public key and Fabric ID. This is a conveniance
1609 : * overload that writes to a uint64_t (CompressedFabricId) type.
1610 : *
1611 : * @param[in] rootPublicKey The root public key associated with the node's fabric
1612 : * @param[in] fabricId The fabric ID associated with the node's fabric
1613 : * @param[out] compressedFabricId output location for compressed fabric ID
1614 : * @returns a CHIP_ERROR on failure or CHIP_NO_ERROR otherwise.
1615 : */
1616 : CHIP_ERROR GenerateCompressedFabricId(const Crypto::P256PublicKey & rootPublicKey, uint64_t fabricId,
1617 : uint64_t & compressedFabricId);
1618 :
1619 : enum class CertificateChainValidationResult
1620 : {
1621 : kSuccess = 0,
1622 :
1623 : kRootFormatInvalid = 100,
1624 : kRootArgumentInvalid = 101,
1625 :
1626 : kICAFormatInvalid = 200,
1627 : kICAArgumentInvalid = 201,
1628 :
1629 : kLeafFormatInvalid = 300,
1630 : kLeafArgumentInvalid = 301,
1631 :
1632 : kChainInvalid = 400,
1633 :
1634 : kNoMemory = 500,
1635 :
1636 : kInternalFrameworkError = 600,
1637 : };
1638 :
1639 : CHIP_ERROR ValidateCertificateChain(const uint8_t * rootCertificate, size_t rootCertificateLen, const uint8_t * caCertificate,
1640 : size_t caCertificateLen, const uint8_t * leafCertificate, size_t leafCertificateLen,
1641 : CertificateChainValidationResult & result);
1642 :
1643 : enum class AttestationCertType
1644 : {
1645 : kPAA = 0,
1646 : kPAI = 1,
1647 : kDAC = 2,
1648 : };
1649 :
1650 : CHIP_ERROR VerifyAttestationCertificateFormat(const ByteSpan & cert, AttestationCertType certType);
1651 :
1652 : /**
1653 : * @brief Validate notBefore timestamp of a certificate (candidateCertificate) against validity period of the
1654 : * issuer certificate (issuerCertificate).
1655 : *
1656 : * Errors are:
1657 : * - CHIP_ERROR_CERT_EXPIRED if the candidateCertificate timestamp does not satisfy the issuerCertificate's timestamp.
1658 : * - CHIP_ERROR_INVALID_ARGUMENT when passing an invalid argument.
1659 : * - CHIP_ERROR_INTERNAL on any unexpected crypto or data conversion errors.
1660 : *
1661 : * @param candidateCertificate A DER Certificate ByteSpan those notBefore timestamp to be evaluated.
1662 : * @param issuerCertificate A DER Certificate ByteSpan used to evaluate validity timestamp of the candidateCertificate.
1663 : *
1664 : * @returns a CHIP_ERROR (see above) on failure or CHIP_NO_ERROR otherwise.
1665 : **/
1666 : CHIP_ERROR IsCertificateValidAtIssuance(const ByteSpan & candidateCertificate, const ByteSpan & issuerCertificate);
1667 :
1668 : /**
1669 : * @brief Validate a certificate's validity date against current time.
1670 : *
1671 : * Errors are:
1672 : * - CHIP_ERROR_CERT_EXPIRED if the certificate has expired.
1673 : * - CHIP_ERROR_INVALID_ARGUMENT when passing an invalid argument.
1674 : * - CHIP_ERROR_INTERNAL on any unexpected crypto or data conversion errors.
1675 : *
1676 : * @param certificate A DER Certificate ByteSpan used as the validity reference to be checked against current time.
1677 : *
1678 : * @returns a CHIP_ERROR (see above) on failure or CHIP_NO_ERROR otherwise.
1679 : **/
1680 : CHIP_ERROR IsCertificateValidAtCurrentTime(const ByteSpan & certificate);
1681 :
1682 : CHIP_ERROR ExtractPubkeyFromX509Cert(const ByteSpan & certificate, Crypto::P256PublicKey & pubkey);
1683 :
1684 : /**
1685 : * @brief Extracts the Subject Key Identifier from an X509 Certificate.
1686 : **/
1687 : CHIP_ERROR ExtractSKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan & skid);
1688 :
1689 : /**
1690 : * @brief Extracts the Authority Key Identifier from an X509 Certificate.
1691 : **/
1692 : CHIP_ERROR ExtractAKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan & akid);
1693 :
1694 : /**
1695 : * @brief Extracts the CRL Distribution Point (CDP) extension from an X509 ASN.1 Encoded Certificate.
1696 : * The returned value only covers the URI of the CDP. Only a single URI distribution point
1697 : * GeneralName is supported, and only those that start with "http://" and "https://".
1698 : *
1699 : * @returns CHIP_ERROR_NOT_FOUND if not found or wrong format.
1700 : * CHIP_NO_ERROR otherwise.
1701 : **/
1702 : CHIP_ERROR ExtractCRLDistributionPointURIFromX509Cert(const ByteSpan & certificate, MutableCharSpan & cdpurl);
1703 :
1704 : /**
1705 : * @brief Extracts the CRL Distribution Point (CDP) extension's cRLIssuer Name from an X509 ASN.1 Encoded Certificate.
1706 : * The value is copied into buffer in a raw ASN.1 X.509 format. This format should be directly comparable
1707 : * with the result of ExtractSubjectFromX509Cert().
1708 : *
1709 : * @returns CHIP_ERROR_NOT_FOUND if not found or wrong format.
1710 : * CHIP_NO_ERROR otherwise.
1711 : **/
1712 : CHIP_ERROR ExtractCDPExtensionCRLIssuerFromX509Cert(const ByteSpan & certificate, MutableByteSpan & crlIssuer);
1713 :
1714 : /**
1715 : * @brief Extracts Serial Number from X509 Certificate.
1716 : **/
1717 : CHIP_ERROR ExtractSerialNumberFromX509Cert(const ByteSpan & certificate, MutableByteSpan & serialNumber);
1718 :
1719 : /**
1720 : * @brief Extracts Subject Distinguished Name from X509 Certificate. The value is copied into buffer in a raw ASN.1 X.509 format.
1721 : **/
1722 : CHIP_ERROR ExtractSubjectFromX509Cert(const ByteSpan & certificate, MutableByteSpan & subject);
1723 :
1724 : /**
1725 : * @brief Extracts Issuer Distinguished Name from X509 Certificate. The value is copied into buffer in a raw ASN.1 X.509 format.
1726 : **/
1727 : CHIP_ERROR ExtractIssuerFromX509Cert(const ByteSpan & certificate, MutableByteSpan & issuer);
1728 :
1729 : /**
1730 : * @brief Checks for resigned version of the certificate in the list and returns it.
1731 : *
1732 : * The following conditions SHOULD be satisfied for the certificate to qualify as
1733 : * a resigned version of a reference certificate:
1734 : * - SKID of the candidate and the reference certificate should match.
1735 : * - SubjectDN of the candidate and the reference certificate should match.
1736 : *
1737 : * If no resigned version is found then reference certificate itself is returned.
1738 : *
1739 : * @param referenceCertificate A DER certificate.
1740 : * @param candidateCertificates A pointer to the list of DER Certificates, which should be searched
1741 : * for the resigned version of `referenceCertificate`.
1742 : * @param candidateCertificatesCount Number of certificates in the `candidateCertificates` list.
1743 : * @param outCertificate A reference to the certificate or it's resigned version if found.
1744 : * Note that it points to either `referenceCertificate` or one of
1745 : * `candidateCertificates`, but it doesn't copy data.
1746 : *
1747 : * @returns error if there is certificate parsing/format issue or CHIP_NO_ERROR otherwise.
1748 : **/
1749 : CHIP_ERROR ReplaceCertIfResignedCertFound(const ByteSpan & referenceCertificate, const ByteSpan * candidateCertificates,
1750 : size_t candidateCertificatesCount, ByteSpan & outCertificate);
1751 :
1752 : /**
1753 : * Defines DN attribute types that can include endocing of VID/PID parameters.
1754 : */
1755 : enum class DNAttrType
1756 : {
1757 : kUnspecified = 0,
1758 : kCommonName = 1,
1759 : kMatterVID = 2,
1760 : kMatterPID = 3,
1761 : };
1762 :
1763 : /**
1764 : * @struct AttestationCertVidPid
1765 : *
1766 : * @brief
1767 : * A data structure representing Attestation Certificate VID and PID attributes.
1768 : */
1769 : struct AttestationCertVidPid
1770 : {
1771 : Optional<VendorId> mVendorId;
1772 : Optional<uint16_t> mProductId;
1773 :
1774 620 : bool Initialized() const { return (mVendorId.HasValue() || mProductId.HasValue()); }
1775 : };
1776 :
1777 : /**
1778 : * @brief Extracts VID and PID attributes from the DN Attribute string.
1779 : * If attribute is not present the corresponding output value stays uninitialized.
1780 : *
1781 : * @return CHIP_ERROR_INVALID_ARGUMENT if wrong input is provided.
1782 : * CHIP_ERROR_WRONG_CERT_DN if encoding of kMatterVID and kMatterPID attributes is wrong.
1783 : * CHIP_NO_ERROR otherwise.
1784 : **/
1785 : CHIP_ERROR ExtractVIDPIDFromAttributeString(DNAttrType attrType, const ByteSpan & attr,
1786 : AttestationCertVidPid & vidpidFromMatterAttr, AttestationCertVidPid & vidpidFromCNAttr);
1787 :
1788 : /**
1789 : * @brief Extracts VID and PID attributes from the Subject DN of an X509 Certificate.
1790 : * If attribute is not present the corresponding output value stays uninitialized.
1791 : **/
1792 : CHIP_ERROR ExtractVIDPIDFromX509Cert(const ByteSpan & x509Cert, AttestationCertVidPid & vidpid);
1793 :
1794 : /**
1795 : * @brief The set of credentials needed to operate group message security with symmetric keys.
1796 : */
1797 : typedef struct GroupOperationalCredentials
1798 : {
1799 : /// Validity start time in microseconds since 2000-01-01T00:00:00 UTC ("the Epoch")
1800 : uint64_t start_time;
1801 : /// Session Id
1802 : uint16_t hash;
1803 : /// Operational group key
1804 : uint8_t encryption_key[Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES];
1805 : /// Privacy key
1806 : uint8_t privacy_key[Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES];
1807 : } GroupOperationalCredentials;
1808 :
1809 : /**
1810 : * @brief Opaque context used to protect a symmetric key. The key operations must
1811 : * be performed without exposing the protected key value.
1812 : */
1813 : class SymmetricKeyContext
1814 : {
1815 : public:
1816 : /**
1817 : * @brief Returns the symmetric key hash
1818 : *
1819 : * TODO: Replace GetKeyHash() with DeriveGroupSessionId(SymmetricKeyContext &, uint16_t & session_id)
1820 : *
1821 : * @return Group Key Hash
1822 : */
1823 : virtual uint16_t GetKeyHash() = 0;
1824 :
1825 9 : virtual ~SymmetricKeyContext() = default;
1826 : /**
1827 : * @brief Perform the message encryption as described in 4.7.2. (Security Processing of Outgoing Messages)
1828 : * @param[in] plaintext Outgoing message payload.
1829 : * @param[in] aad Additional data (message header contents)
1830 : * @param[in] nonce Nonce (Security Flags | Message Counter | Source Node ID)
1831 : * @param[out] mic Outgoing Message Integrity Check
1832 : * @param[out] ciphertext Outgoing encrypted payload. Must be at least as big as plaintext. The same buffer may be used both
1833 : * for ciphertext, and plaintext.
1834 : * @return CHIP_ERROR
1835 : */
1836 : virtual CHIP_ERROR MessageEncrypt(const ByteSpan & plaintext, const ByteSpan & aad, const ByteSpan & nonce,
1837 : MutableByteSpan & mic, MutableByteSpan & ciphertext) const = 0;
1838 : /**
1839 : * @brief Perform the message decryption as described in 4.7.3.(Security Processing of Incoming Messages)
1840 : * @param[in] ciphertext Incoming encrypted payload
1841 : * @param[in] aad Additional data (message header contents)
1842 : * @param[in] nonce Nonce (Security Flags | Message Counter | Source Node ID)
1843 : * @param[in] mic Incoming Message Integrity Check
1844 : * @param[out] plaintext Incoming message payload. Must be at least as big as ciphertext. The same buffer may be used both
1845 : * for plaintext, and ciphertext.
1846 : * @return CHIP_ERROR
1847 : */
1848 : virtual CHIP_ERROR MessageDecrypt(const ByteSpan & ciphertext, const ByteSpan & aad, const ByteSpan & nonce,
1849 : const ByteSpan & mic, MutableByteSpan & plaintext) const = 0;
1850 :
1851 : /**
1852 : * @brief Perform privacy encoding as described in 4.8.2. (Privacy Processing of Outgoing Messages)
1853 : * @param[in] input Message header to privacy encrypt
1854 : * @param[in] nonce Privacy Nonce = session_id | mic
1855 : * @param[out] output Message header obfuscated
1856 : * @return CHIP_ERROR
1857 : */
1858 : virtual CHIP_ERROR PrivacyEncrypt(const ByteSpan & input, const ByteSpan & nonce, MutableByteSpan & output) const = 0;
1859 :
1860 : /**
1861 : * @brief Perform privacy decoding as described in 4.8.3. (Privacy Processing of Incoming Messages)
1862 : * @param[in] input Message header to privacy decrypt
1863 : * @param[in] nonce Privacy Nonce = session_id | mic
1864 : * @param[out] output Message header deobfuscated
1865 : * @return CHIP_ERROR
1866 : */
1867 : virtual CHIP_ERROR PrivacyDecrypt(const ByteSpan & input, const ByteSpan & nonce, MutableByteSpan & output) const = 0;
1868 :
1869 : /**
1870 : * @brief Release resources such as dynamic memory used to allocate this instance of the SymmetricKeyContext
1871 : */
1872 : virtual void Release() = 0;
1873 : };
1874 :
1875 : /**
1876 : * @brief Derives the Operational Group Key using the Key Derivation Function (KDF) from the given epoch key.
1877 : * @param[in] epoch_key The epoch key. Must be CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES bytes length.
1878 : * @param[in] compressed_fabric_id The compressed fabric ID for the fabric (big endian byte string)
1879 : * @param[out] out_key Symmetric key used as the encryption key during message processing for group communication.
1880 : The buffer size must be at least CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES bytes length.
1881 : * @return Returns a CHIP_NO_ERROR on succcess, or CHIP_ERROR_INTERNAL if the provided key is invalid.
1882 : **/
1883 : CHIP_ERROR DeriveGroupOperationalKey(const ByteSpan & epoch_key, const ByteSpan & compressed_fabric_id, MutableByteSpan & out_key);
1884 :
1885 : /**
1886 : * @brief Derives the Group Session ID from a given operational group key using
1887 : * the Key Derivation Function (Group Key Hash)
1888 : * @param[in] operational_key The operational group key. Must be CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES bytes length.
1889 : * @param[out] session_id Output of the Group Key Hash
1890 : * @return Returns a CHIP_NO_ERROR on succcess, or CHIP_ERROR_INVALID_ARGUMENT if the provided key is invalid.
1891 : **/
1892 : CHIP_ERROR DeriveGroupSessionId(const ByteSpan & operational_key, uint16_t & session_id);
1893 :
1894 : /**
1895 : * @brief Derives the Privacy Group Key using the Key Derivation Function (KDF) from the given epoch key.
1896 : * @param[in] epoch_key The epoch key. Must be CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES bytes length.
1897 : * @param[out] out_key Symmetric key used as the privacy key during message processing for group communication.
1898 : * The buffer size must be at least CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES bytes length.
1899 : * @return Returns a CHIP_NO_ERROR on succcess, or CHIP_ERROR_INTERNAL if the provided key is invalid.
1900 : **/
1901 : CHIP_ERROR DeriveGroupPrivacyKey(const ByteSpan & epoch_key, MutableByteSpan & out_key);
1902 :
1903 : /**
1904 : * @brief Derives the complete set of credentials needed for group security.
1905 : *
1906 : * This function will derive the Encryption Key, Group Key Hash (Session Id), and Privacy Key
1907 : * for the given Epoch Key and Compressed Fabric Id.
1908 : * @param[in] epoch_key The epoch key. Must be CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES bytes length.
1909 : * @param[in] compressed_fabric_id The compressed fabric ID for the fabric (big endian byte string)
1910 : * @param[out] operational_credentials The set of Symmetric keys used during message processing for group communication.
1911 : * @return Returns a CHIP_NO_ERROR on succcess, or CHIP_ERROR_INTERNAL if the provided key is invalid.
1912 : **/
1913 : CHIP_ERROR DeriveGroupOperationalCredentials(const ByteSpan & epoch_key, const ByteSpan & compressed_fabric_id,
1914 : GroupOperationalCredentials & operational_credentials);
1915 : } // namespace Crypto
1916 : } // namespace chip
|