Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020 Project CHIP Authors
4 : * All rights reserved.
5 : *
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : */
18 :
19 : /**
20 : * @file
21 : * This file defines the CHIP Secure Session object that provides
22 : * APIs for encrypting/decryting data using cryptographic keys.
23 : *
24 : */
25 :
26 : #pragma once
27 :
28 : #include <crypto/CHIPCryptoPAL.h>
29 : #include <crypto/SessionKeystore.h>
30 : #include <lib/core/CHIPCore.h>
31 : #include <lib/support/Span.h>
32 : #include <transport/raw/MessageHeader.h>
33 :
34 : namespace chip {
35 :
36 : class DLL_EXPORT CryptoContext
37 : {
38 : public:
39 : static constexpr size_t kPrivacyNonceMicFragmentOffset = 5;
40 : static constexpr size_t kPrivacyNonceMicFragmentLength = 11;
41 : static constexpr size_t kAESCCMNonceLen = 13;
42 : using NonceStorage = std::array<uint8_t, kAESCCMNonceLen>;
43 : using NonceView = FixedSpan<uint8_t, kAESCCMNonceLen>;
44 : using ConstNonceView = FixedSpan<const uint8_t, kAESCCMNonceLen>;
45 :
46 : CryptoContext();
47 : ~CryptoContext();
48 : CryptoContext(CryptoContext &&) = delete;
49 : CryptoContext(const CryptoContext &) = delete;
50 18 : explicit CryptoContext(Crypto::SymmetricKeyContext * context) : mKeyContext(context) {}
51 : CryptoContext & operator=(const CryptoContext &) = delete;
52 : CryptoContext & operator=(CryptoContext &&) = delete;
53 :
54 : /**
55 : * Whether the current node initiated the session, or it is responded to a session request.
56 : */
57 : enum class SessionRole : uint8_t
58 : {
59 : kInitiator, /**< We initiated the session. */
60 : kResponder, /**< We responded to the session request. */
61 : };
62 :
63 : enum class SessionInfoType : uint8_t
64 : {
65 : kSessionEstablishment, /**< A new secure session is established. */
66 : kSessionResumption, /**< An old session is being resumed. */
67 : };
68 :
69 : /**
70 : * @brief
71 : * Derive a shared key. The derived key will be used for encrypting/decrypting
72 : * data exchanged on the secure channel.
73 : *
74 : * @param keystore Session keystore for management of symmetric encryption keys
75 : * @param local_keypair A reference to local ECP keypair
76 : * @param remote_public_key A reference to peer's public key
77 : * @param salt A reference to the initial salt used for deriving the keys
78 : * @param infoType The info buffer to use for deriving session keys
79 : * @param role Role of the new session (initiator or responder)
80 : * @return CHIP_ERROR The result of key derivation
81 : */
82 : CHIP_ERROR InitFromKeyPair(Crypto::SessionKeystore & keystore, const Crypto::P256Keypair & local_keypair,
83 : const Crypto::P256PublicKey & remote_public_key, const ByteSpan & salt, SessionInfoType infoType,
84 : SessionRole role);
85 :
86 : /**
87 : * @brief Derive session keys and the attestation challenge from the shared secret.
88 : *
89 : * @param keystore Session keystore for management of symmetric encryption keys
90 : * @param secret A reference to the shared secret
91 : * @param salt A reference to the initial salt used for deriving the keys
92 : * @param infoType The info buffer to use for deriving session keys
93 : * @param role Role of the new session (initiator or responder)
94 : * @return CHIP_ERROR The result of key derivation
95 : */
96 : CHIP_ERROR InitFromSecret(Crypto::SessionKeystore & keystore, const ByteSpan & secret, const ByteSpan & salt,
97 : SessionInfoType infoType, SessionRole role);
98 :
99 : /**
100 : * @brief Derive session keys and the attestation challenge from the HKDF key.
101 : *
102 : * @param keystore Session keystore for management of symmetric encryption keys
103 : * @param hkdfKey HKDF key handle
104 : * @param salt A reference to the initial salt used for deriving the keys
105 : * @param infoType The info buffer to use for deriving session keys
106 : * @param role Role of the new session (initiator or responder)
107 : * @return CHIP_ERROR The result of key derivation
108 : */
109 : CHIP_ERROR InitFromSecret(Crypto::SessionKeystore & keystore, const Crypto::HkdfKeyHandle & hkdfKey, const ByteSpan & salt,
110 : SessionInfoType infoType, SessionRole role);
111 :
112 : /** @brief Build a Nonce buffer using given parameters for encrypt or decrypt. */
113 : static CHIP_ERROR BuildNonce(NonceView nonce, uint8_t securityFlags, uint32_t messageCounter, NodeId nodeId);
114 :
115 : /** @brief Build a Nonce buffer using given parameters for encrypt or decrypt. */
116 : static CHIP_ERROR BuildPrivacyNonce(NonceView nonce, uint16_t sessionId, const MessageAuthenticationCode & mac);
117 :
118 : /**
119 : * @brief
120 : * Encrypt the input data using keys established in the secure channel
121 : *
122 : * @param[in] input Unencrypted input data
123 : * @param input_length Length of the input data
124 : * @param[out] output Output buffer for encrypted data
125 : * @param[in] nonce Nonce buffer for encrypt
126 : * @param[in] header message header structure. Encryption type will be set on the header.
127 : * @param[out] mac - output the resulting mac
128 : *
129 : * @return CHIP_ERROR The result of encryption
130 : */
131 : CHIP_ERROR Encrypt(const uint8_t * input, size_t input_length, uint8_t * output, ConstNonceView nonce,
132 : const PacketHeader & header, MessageAuthenticationCode & mac) const;
133 :
134 : /**
135 : * @brief
136 : * Decrypt the input data using keys established in the secure channel
137 : *
138 : * @param[in] input Encrypted input data
139 : * @param input_length Length of the input data
140 : * @param[out] output Output buffer for decrypted data
141 : * @param[in] nonce Nonce buffer for decrypt
142 : * @param[in] header message header structure
143 : * @param[in] mac Input mac
144 : * @return CHIP_ERROR The result of decryption
145 : */
146 : CHIP_ERROR Decrypt(const uint8_t * input, size_t input_length, uint8_t * output, ConstNonceView nonce,
147 : const PacketHeader & header, const MessageAuthenticationCode & mac) const;
148 :
149 : CHIP_ERROR PrivacyEncrypt(const uint8_t * input, size_t input_length, uint8_t * output, PacketHeader & header,
150 : MessageAuthenticationCode & mac) const;
151 :
152 : CHIP_ERROR PrivacyDecrypt(const uint8_t * input, size_t input_length, uint8_t * output, const PacketHeader & header,
153 : const MessageAuthenticationCode & mac) const;
154 :
155 0 : ByteSpan GetAttestationChallenge() const { return mAttestationChallenge.Span(); }
156 :
157 : bool IsInitiator() const { return mKeyAvailable && mSessionRole == SessionRole::kInitiator; }
158 :
159 0 : bool IsResponder() const { return mKeyAvailable && mSessionRole == SessionRole::kResponder; }
160 :
161 : private:
162 : CHIP_ERROR InitTestMode(Crypto::SessionKeystore & keystore, Crypto::Aes128KeyHandle & i2rKey, Crypto::Aes128KeyHandle & r2iKey);
163 :
164 : SessionRole mSessionRole;
165 :
166 : bool mKeyAvailable;
167 : Crypto::Aes128KeyHandle mEncryptionKey;
168 : Crypto::Aes128KeyHandle mDecryptionKey;
169 : Crypto::AttestationChallenge mAttestationChallenge;
170 : Crypto::SessionKeystore * mKeystore = nullptr;
171 : Crypto::SymmetricKeyContext * mKeyContext = nullptr;
172 :
173 : // Use unencrypted header as additional authenticated data (AAD) during encryption and decryption.
174 : // The encryption operations includes AAD when message authentication tag is generated. This tag
175 : // is used at the time of decryption to integrity check the received data.
176 : static CHIP_ERROR GetAdditionalAuthData(const PacketHeader & header, uint8_t * aad, uint16_t & len);
177 : };
178 :
179 : } // namespace chip
|