1// Copyright 2015 The Weave Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/crypto_hmac.h"
6
7#include <stddef.h>
8#include <stdint.h>
9#include <string.h>
10
11#include <openssl/evp.h>
12#include <openssl/hmac.h>
13
14bool uw_crypto_hmac_(const uint8_t* key,
15                     size_t key_len,
16                     const UwCryptoHmacMsg messages[],
17                     size_t num_messages,
18                     uint8_t* truncated_digest,
19                     size_t truncated_digest_len) {
20  HMAC_CTX context = {0};
21  HMAC_CTX_init(&context);
22  if (!HMAC_Init(&context, key, key_len, EVP_sha256()))
23    return false;
24
25  for (size_t i = 0; i < num_messages; ++i) {
26    if (messages[i].num_bytes &&
27        (!messages[i].bytes ||
28         !HMAC_Update(&context, messages[i].bytes, messages[i].num_bytes))) {
29      return false;
30    }
31  }
32
33  const size_t kFullDigestLen = (size_t)EVP_MD_size(EVP_sha256());
34  if (truncated_digest_len > kFullDigestLen) {
35    return false;
36  }
37
38  uint8_t digest[kFullDigestLen];
39  uint32_t len = kFullDigestLen;
40
41  bool result = HMAC_Final(&context, digest, &len) && kFullDigestLen == len;
42  HMAC_CTX_cleanup(&context);
43  if (result) {
44    memcpy(truncated_digest, digest, truncated_digest_len);
45  }
46  return result;
47}
48