Skip to content
This repository was archived by the owner on Dec 20, 2023. It is now read-only.

Commit 0d17da1

Browse files
committed
Add HMAC signature support.
Defined types, objects, and methods for working with HMAC signatures.
1 parent 0875967 commit 0d17da1

File tree

2 files changed

+196
-0
lines changed

2 files changed

+196
-0
lines changed

src/lib/support/crypto/HMAC.cpp

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
*
3+
* Copyright (c) 2019 Google LLC.
34
* Copyright (c) 2013-2017 Nest Labs, Inc.
45
* All rights reserved.
56
*
@@ -32,11 +33,14 @@
3233

3334
#include "WeaveCrypto.h"
3435
#include "HMAC.h"
36+
#include <Weave/Support/CodeUtils.h>
3537

3638
namespace nl {
3739
namespace Weave {
3840
namespace Crypto {
3941

42+
using namespace nl::Weave::TLV;
43+
4044
template <class H>
4145
HMAC<H>::HMAC()
4246
{
@@ -139,6 +143,155 @@ void HMAC<H>::Reset()
139143
template class HMAC<Platform::Security::SHA1>;
140144
template class HMAC<Platform::Security::SHA256>;
141145

146+
147+
/**
148+
* Compares with another HMAC signature.
149+
*
150+
* @param[in] other The EncodedHMACSignature object with which signature should be compared.
151+
*
152+
* @retval true The signatures are equal.
153+
* @retval false The signatures are not equal.
154+
*/
155+
bool EncodedHMACSignature::IsEqual(const EncodedHMACSignature& other) const
156+
{
157+
return (Sig != NULL &&
158+
other.Sig != NULL &&
159+
Len == other.Len &&
160+
memcmp(Sig, other.Sig, Len) == 0);
161+
}
162+
163+
/**
164+
* Reads the signature as a Weave HMACSignature structure from the specified TLV reader.
165+
*
166+
* @param[in] reader The TLVReader object from which the encoded signature should
167+
* be read.
168+
*
169+
* @retval #WEAVE_NO_ERROR If the operation succeeded.
170+
* @retval other Other Weave error codes related to signature reading.
171+
*/
172+
WEAVE_ERROR EncodedHMACSignature::ReadSignature(TLVReader& reader)
173+
{
174+
WEAVE_ERROR err;
175+
176+
VerifyOrExit(reader.GetType() == kTLVType_ByteString, err = WEAVE_ERROR_WRONG_TLV_TYPE);
177+
178+
err = reader.GetDataPtr(const_cast<const uint8_t *&>(Sig));
179+
SuccessOrExit(err);
180+
181+
Len = reader.GetLength();
182+
183+
exit:
184+
return err;
185+
}
186+
187+
/**
188+
* Generate and encode a Weave HMAC signature
189+
*
190+
* Computes an HMAC signature for a given data using secret key and writes the signature
191+
* as a Weave HMACSignature structure to the specified TLV writer with the given tag.
192+
*
193+
* @param[in] sigAlgoOID Algorithm OID to be used to generate HMAC signature.
194+
* @param[in] writer The TLVWriter object to which the encoded signature should
195+
* be written.
196+
* @param[in] tag TLV tag to be associated with the encoded signature structure.
197+
* @param[in] data A buffer containing the data to be signed.
198+
* @param[in] dataLen The length in bytes of the data.
199+
* @param[in] key A buffer containing the secret key to be used to generate HMAC
200+
* signature.
201+
* @param[in] keyLen The length in bytes of the secret key.
202+
*
203+
* @retval #WEAVE_NO_ERROR If the operation succeeded.
204+
* @retval other Other Weave error codes related to the signature encoding.
205+
*/
206+
WEAVE_ERROR GenerateAndEncodeWeaveHMACSignature(OID sigAlgoOID,
207+
TLVWriter& writer, uint64_t tag,
208+
const uint8_t * data, uint16_t dataLen,
209+
const uint8_t * key, uint16_t keyLen)
210+
{
211+
WEAVE_ERROR err;
212+
HMACSHA256 hmac;
213+
uint8_t hmacSig[HMACSHA256::kDigestLength];
214+
EncodedHMACSignature sig;
215+
216+
// Current implementation only supports HMACWithSHA256 signature algorithm.
217+
VerifyOrExit(sigAlgoOID == ASN1::kOID_SigAlgo_HMACWithSHA256, err = WEAVE_ERROR_UNSUPPORTED_SIGNATURE_TYPE);
218+
219+
// Generate the MAC.
220+
hmac.Begin(key, keyLen);
221+
hmac.AddData(data, dataLen);
222+
hmac.Finish(hmacSig);
223+
224+
sig.Sig = hmacSig;
225+
sig.Len = HMACSHA256::kDigestLength;
226+
227+
// Encode an HMACSignature value into the supplied writer.
228+
err = sig.WriteSignature(writer, tag);
229+
SuccessOrExit(err);
230+
231+
exit:
232+
return err;
233+
}
234+
235+
/**
236+
* Verify a Weave HMAC signature.
237+
*
238+
* Verifies an HMAC signature using given data and a secret key to be used to verify the signature.
239+
*
240+
* @param[in] sigAlgoOID Algorithm OID to be used to generate HMAC signature.
241+
* @param[in] data A buffer containing the data to be signed.
242+
* @param[in] dataLen The length in bytes of the data.
243+
* @param[in] sig Encoded HMAC signature to be verified.
244+
* @param[in] key A buffer containing the secret key to be used to generate HMAC
245+
* signature.
246+
* @param[in] keyLen The length in bytes of the secret key.
247+
*
248+
* @retval #WEAVE_NO_ERROR If HMAC signature verification succeeded.
249+
* @retval #WEAVE_ERROR_INVALID_SIGNATURE
250+
* If HMAC signature verification failed.
251+
*/
252+
WEAVE_ERROR VerifyHMACSignature(OID sigAlgoOID,
253+
const uint8_t * data, uint16_t dataLen,
254+
const EncodedHMACSignature& sig,
255+
const uint8_t * key, uint16_t keyLen)
256+
{
257+
WEAVE_ERROR err = WEAVE_NO_ERROR;
258+
HMACSHA256 hmac;
259+
uint8_t hmacSig[HMACSHA256::kDigestLength];
260+
EncodedHMACSignature lSig;
261+
262+
// Current implementation only supports HMACWithSHA256 signature algorithm.
263+
VerifyOrExit(sigAlgoOID == ASN1::kOID_SigAlgo_HMACWithSHA256, err = WEAVE_ERROR_UNSUPPORTED_SIGNATURE_TYPE);
264+
265+
// Generate the MAC.
266+
hmac.Begin(key, keyLen);
267+
hmac.AddData(data, dataLen);
268+
hmac.Finish(hmacSig);
269+
270+
lSig.Sig = hmacSig;
271+
lSig.Len = HMACSHA256::kDigestLength;
272+
273+
VerifyOrExit(lSig.IsEqual(sig), err = WEAVE_ERROR_INVALID_SIGNATURE);
274+
275+
exit:
276+
return err;
277+
}
278+
279+
// ==================== Documentation for Inline Public Members ====================
280+
281+
/**
282+
* @fn WEAVE_ERROR EncodedHMACSignature::WriteSignature(TLVWriter& writer, uint64_t tag) const
283+
*
284+
* Writes the signature as a Weave HMACSignature structure to the specified TLV writer
285+
* with the given tag.
286+
*
287+
* @param[in] writer The TLVWriter object to which the encoded signature should
288+
* be written.
289+
* @param[in] tag TLV tag to be associated with the encoded signature structure.
290+
291+
* @retval #WEAVE_NO_ERROR If the operation succeeded.
292+
* @retval other Other Weave error codes related to signature writing.
293+
*/
294+
142295
} // namespace Crypto
143296
} // namespace Weave
144297
} // namespace nl

src/lib/support/crypto/HMAC.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
*
3+
* Copyright (c) 2019 Google LLC.
34
* Copyright (c) 2013-2017 Nest Labs, Inc.
45
* All rights reserved.
56
*
@@ -29,11 +30,17 @@
2930

3031
#include "WeaveCrypto.h"
3132
#include "HashAlgos.h"
33+
#include <Weave/Support/ASN1.h>
34+
#include <Weave/Core/WeaveTLV.h>
3235

3336
namespace nl {
3437
namespace Weave {
3538
namespace Crypto {
3639

40+
using nl::Weave::TLV::TLVReader;
41+
using nl::Weave::TLV::TLVWriter;
42+
using nl::Weave::ASN1::OID;
43+
3744
template <class H>
3845
class NL_DLL_EXPORT HMAC
3946
{
@@ -70,6 +77,42 @@ typedef HMAC<Platform::Security::SHA1> HMACSHA1;
7077
typedef HMAC<Platform::Security::SHA256> HMACSHA256;
7178

7279

80+
class EncodedHMACSignature
81+
{
82+
public:
83+
enum
84+
{
85+
kMaxValueLength = HMACSHA256::kDigestLength
86+
};
87+
88+
uint8_t *Sig;
89+
uint8_t Len;
90+
91+
bool IsEqual(const EncodedHMACSignature& other) const;
92+
93+
WEAVE_ERROR ReadSignature(TLVReader& reader);
94+
WEAVE_ERROR WriteSignature(TLVWriter& writer, uint64_t tag) const;
95+
};
96+
97+
inline WEAVE_ERROR EncodedHMACSignature::WriteSignature(TLVWriter& writer, uint64_t tag) const
98+
{
99+
return writer.PutBytes(tag, Sig, Len);
100+
}
101+
102+
// =============================================================
103+
// Primary HMAC utility functions used by Weave security code.
104+
// =============================================================
105+
106+
extern WEAVE_ERROR GenerateAndEncodeWeaveHMACSignature(OID sigAlgoOID,
107+
TLVWriter& writer, uint64_t tag,
108+
const uint8_t * data, uint16_t dataLen,
109+
const uint8_t * key, uint16_t keyLen);
110+
111+
extern WEAVE_ERROR VerifyHMACSignature(OID sigAlgoOID,
112+
const uint8_t * data, uint16_t dataLen,
113+
const EncodedHMACSignature& sig,
114+
const uint8_t * key, uint16_t keyLen);
115+
73116
} // namespace Crypto
74117
} // namespace Weave
75118
} // namespace nl

0 commit comments

Comments
 (0)