forked from project-chip/connectedhomeip
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathEfr32OpaqueKeypair.h
224 lines (200 loc) · 8.78 KB
/
Efr32OpaqueKeypair.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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
/*
* Copyright (c) 2022 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.
*/
#pragma once
#include <crypto/CHIPCryptoPAL.h>
#include <platform/CHIPDeviceError.h>
namespace chip {
namespace DeviceLayer {
namespace Internal {
typedef uint16_t EFR32OpaqueKeyId;
inline constexpr EFR32OpaqueKeyId kEFR32OpaqueKeyIdUnknown = 0xFFFFU; // Do not modify, will impact existing deployments
inline constexpr EFR32OpaqueKeyId kEFR32OpaqueKeyIdVolatile = 0xFFFEU; // Do not modify, will impact existing deployments
inline constexpr EFR32OpaqueKeyId kEFR32OpaqueKeyIdPersistentMin = 0x0U; // Do not modify, will impact existing deployments
inline constexpr EFR32OpaqueKeyId kEFR32OpaqueKeyIdPersistentMax = 0x1FFU; // Do not decrease, will impact existing deployments
enum class EFR32OpaqueKeyUsages : uint8_t
{
ECDSA_P256_SHA256 = 0,
ECDH_P256 = 1,
};
/**
* @brief Base class for opaque keys
*
* Deriving from this class allows using it as a base class for operations
* which don't expose the private key independant of key size.
**/
class EFR32OpaqueKeypair
{
public:
EFR32OpaqueKeypair();
virtual ~EFR32OpaqueKeypair();
/**
* @brief Load a keypair with given key ID
*
* If no key exists under the given ID, an error is returned
* and the object is unusable for operations.
*
* @param key_id key ID under which this key was created
*
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR Load(EFR32OpaqueKeyId key_id);
/**
* @brief Create a new keypair with given ID and usage
*
* If a key already exists under the given ID, an error is returned
* and no new key is created.
*
* @param key_id key ID under which to store this key. Set to 0
* for a non-persistent key which gets destructed
* when the lifetime of this object ends, or set
* to any other value to store the key under that
* ID.
*
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR Create(EFR32OpaqueKeyId key_id, EFR32OpaqueKeyUsages usage);
/**
* @brief Get the public key for this keypair
*
* @param output Output buffer to put public key (in 0x04 || X || Y format)
* @param output_size Size of \p output
* @param output_length Amount of bytes put in \p output on success
*
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR GetPublicKey(uint8_t * output, size_t output_size, size_t * output_length) const;
/**
* @brief Get the key ID for this keypair
*
* @return Returns kEFR32OpaqueKeyIdUnknown for an uninitialised/invalid
* key, kEFR32OpaqueKeyIdVolatile for a volatile key, and a key
* ID in the range [kEFR32OpaqueKeyIdPersistentMin, kEFR32OpaqueKeyIdPersistentMax]
* for valid persistent keys.
**/
EFR32OpaqueKeyId GetKeyId() const;
/**
* @brief Use this keypair to sign a message using the ECDSA-SHA256 algorithm
*
* @param msg Message buffer to sign
* @param msg_len Size of \p msg in bytes
* @param output Output buffer to write signature to. Signature
* is in raw format (i.e. binary concatenation of
* r and s)
* @param output_size Size of output buffer
* @param output_length Amount of bytes written into output buffer
*
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR Sign(const uint8_t * msg, size_t msg_len, uint8_t * output, size_t output_size, size_t * output_length) const;
/**
* @brief Use this keypair to derive a key using the raw ECDH algorithm
*
* @param their_key Buffer containing raw uncompressed public key
* of party to derive with
* @param their_key_len Size of \p their_key in bytes
* @param output Output buffer to write derived bytes to
* @param output_size Size of output buffer
* @param output_length Amount of bytes written into output buffer
*
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR Derive(const uint8_t * their_key, size_t their_key_len, uint8_t * output, size_t output_size,
size_t * output_length) const;
/**
* @brief Delete the keypair from storage
*
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR DestroyKey();
protected:
void * mContext = nullptr;
bool mHasKey = false;
bool mIsPersistent = false;
uint8_t * mPubkeyRef = nullptr;
size_t mPubkeySize = 0;
size_t mPubkeyLength = 0;
};
/**
* @brief Derived class of P256Keypair for using opaque keys
*
* The signature and compiled form of this class is suboptimal due to how
* the P256Keypair isn't really an abstract interface, but rather partly
* interface / partly implementation. Future optimisation should look at
* converting P256Keypair to a fully abstract interface.
**/
class EFR32OpaqueP256Keypair : public chip::Crypto::P256Keypair, public EFR32OpaqueKeypair
{
public:
EFR32OpaqueP256Keypair();
~EFR32OpaqueP256Keypair() override;
/**
* @brief Initialize the keypair.
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR Initialize(chip::Crypto::ECPKeyTarget key_target) override;
/**
* @brief Serialize the keypair (unsupported on opaque keys)
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR Serialize(chip::Crypto::P256SerializedKeypair & output) const override;
/**
* @brief Deserialize the keypair (unsupported on opaque keys)
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR Deserialize(chip::Crypto::P256SerializedKeypair & input) override;
/**
* @brief Generate a new Certificate Signing Request (CSR).
* @param csr Newly generated CSR in DER format
* @param csr_length The caller provides the length of input buffer (csr). The function returns the actual length of generated
*CSR.
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR NewCertificateSigningRequest(uint8_t * csr, size_t & csr_length) const override;
/**
* @brief A function to sign a msg using ECDSA
* @param msg Message that needs to be signed
* @param msg_length Length of message
* @param out_signature Buffer that will hold the output signature. The signature consists of: 2 EC elements (r and s),
* in raw <r,s> point form (see SEC1).
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR ECDSA_sign_msg(const uint8_t * msg, size_t msg_length,
chip::Crypto::P256ECDSASignature & out_signature) const override;
/**
* @brief A function to derive a shared secret using ECDH
*
* This implements the CHIP_Crypto_ECDH(PrivateKey myPrivateKey, PublicKey theirPublicKey) cryptographic primitive
* from the specification, using this class's private key from `mKeypair` as `myPrivateKey` and the remote
* public key from `remote_public_key` as `theirPublicKey`.
*
* @param remote_public_key Public key of remote peer with which we are trying to establish secure channel. remote_public_key is
* ASN.1 DER encoded as padded big-endian field elements as described in SEC 1: Elliptic Curve Cryptography
* [https://www.secg.org/sec1-v2.pdf]
* @param out_secret Buffer to write out secret into. This is a byte array representing the x coordinate of the shared secret.
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR ECDH_derive_secret(const chip::Crypto::P256PublicKey & remote_public_key,
chip::Crypto::P256ECDHDerivedSecret & out_secret) const override;
/** @brief Return public key for the keypair.
**/
const chip::Crypto::P256PublicKey & Pubkey() const override;
private:
chip::Crypto::P256PublicKey mPubKey;
};
} // namespace Internal
} // namespace DeviceLayer
} // namespace chip