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