|
1 | 1 | /* |
2 | 2 | * |
| 3 | + * Copyright (c) 2019 Google LLC. |
3 | 4 | * Copyright (c) 2013-2017 Nest Labs, Inc. |
4 | 5 | * All rights reserved. |
5 | 6 | * |
|
32 | 33 |
|
33 | 34 | #include "WeaveCrypto.h" |
34 | 35 | #include "HMAC.h" |
| 36 | +#include <Weave/Support/CodeUtils.h> |
35 | 37 |
|
36 | 38 | namespace nl { |
37 | 39 | namespace Weave { |
38 | 40 | namespace Crypto { |
39 | 41 |
|
| 42 | +using namespace nl::Weave::TLV; |
| 43 | + |
40 | 44 | template <class H> |
41 | 45 | HMAC<H>::HMAC() |
42 | 46 | { |
@@ -139,6 +143,155 @@ void HMAC<H>::Reset() |
139 | 143 | template class HMAC<Platform::Security::SHA1>; |
140 | 144 | template class HMAC<Platform::Security::SHA256>; |
141 | 145 |
|
| 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 | + |
142 | 295 | } // namespace Crypto |
143 | 296 | } // namespace Weave |
144 | 297 | } // namespace nl |
0 commit comments