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 15 : 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 input Unencrypted input data 123 : * @param input_length Length of the input data 124 : * @param output Output buffer for encrypted data 125 : * @param nonce Nonce buffer for encrypt 126 : * @param header message header structure. Encryption type will be set on the header. 127 : * @param 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, PacketHeader & header, 132 : MessageAuthenticationCode & mac) const; 133 : 134 : /** 135 : * @brief 136 : * Decrypt the input data using keys established in the secure channel 137 : * 138 : * @param input Encrypted input data 139 : * @param input_length Length of the input data 140 : * @param output Output buffer for decrypted data 141 : * @param nonce Nonce buffer for decrypt 142 : * @param header message header structure 143 : * @return CHIP_ERROR The result of decryption 144 : * @param mac Input mac 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 : /** 158 : * @brief 159 : * Memory overhead of encrypting data. The overhead is independent of size of 160 : * the data being encrypted. The extra space is used for storing the common header. 161 : * 162 : * @return number of bytes. 163 : */ 164 : size_t EncryptionOverhead(); 165 : 166 : bool IsInitiator() const { return mKeyAvailable && mSessionRole == SessionRole::kInitiator; } 167 : 168 0 : bool IsResponder() const { return mKeyAvailable && mSessionRole == SessionRole::kResponder; } 169 : 170 : private: 171 : CHIP_ERROR InitTestMode(Crypto::SessionKeystore & keystore, Crypto::Aes128KeyHandle & i2rKey, Crypto::Aes128KeyHandle & r2iKey); 172 : 173 : SessionRole mSessionRole; 174 : 175 : bool mKeyAvailable; 176 : Crypto::Aes128KeyHandle mEncryptionKey; 177 : Crypto::Aes128KeyHandle mDecryptionKey; 178 : Crypto::AttestationChallenge mAttestationChallenge; 179 : Crypto::SessionKeystore * mKeystore = nullptr; 180 : Crypto::SymmetricKeyContext * mKeyContext = nullptr; 181 : 182 : // Use unencrypted header as additional authenticated data (AAD) during encryption and decryption. 183 : // The encryption operations includes AAD when message authentication tag is generated. This tag 184 : // is used at the time of decryption to integrity check the received data. 185 : static CHIP_ERROR GetAdditionalAuthData(const PacketHeader & header, uint8_t * aad, uint16_t & len); 186 : }; 187 : 188 : } // namespace chip