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