kinetic-c  v0.12.0
Seagate Kinetic Protocol Client Library for C
kinetic_hmac.c
Go to the documentation of this file.
1 /*
2 * kinetic-c
3 * Copyright (C) 2015 Seagate Technology.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 *
19 */
20 
21 #include "kinetic_hmac.h"
22 #include "kinetic_nbo.h"
23 #include "kinetic_logger.h"
24 #include <string.h>
25 #include <openssl/hmac.h>
26 
27 static void KineticHMAC_Compute(KineticHMAC* hmac,
28  const Com__Seagate__Kinetic__Proto__Message* proto,
29  const ByteArray key);
30 
33 {
35  *hmac = (KineticHMAC) {
36  .algorithm = algorithm,
38  };
39  }
40  else {
41  *hmac = (KineticHMAC) {
43  };
44  }
45 }
46 
48  Com__Seagate__Kinetic__Proto__Message* msg,
49  const ByteArray key)
50 {
51  KINETIC_ASSERT(hmac != NULL);
52  KINETIC_ASSERT(hmac->data != NULL);
53  KINETIC_ASSERT(msg != NULL);
54  KINETIC_ASSERT(key.data != NULL);
55  KINETIC_ASSERT(key.len > 0);
56  KINETIC_ASSERT(msg->hmacauth->hmac.data != NULL);
57 
59  KineticHMAC_Compute(hmac, msg, key);
60 
61  // Copy computed HMAC into message
62  memcpy(msg->hmacauth->hmac.data, hmac->data, hmac->len);
63  msg->hmacauth->hmac.len = hmac->len;
64  msg->hmacauth->has_hmac = true;
65 }
66 
67 bool KineticHMAC_Validate(const Com__Seagate__Kinetic__Proto__Message* msg,
68  const ByteArray key)
69 {
70  KINETIC_ASSERT(msg != NULL);
71  KINETIC_ASSERT(key.data != NULL);
72  KINETIC_ASSERT(key.len > 0);
73 
74  bool success = false;
75  size_t i;
76  int result = 0;
77  KineticHMAC tempHMAC;
78 
79  if (!msg->has_authtype
81  || msg->hmacauth == NULL
82  || !msg->hmacauth->has_hmac
83  || msg->hmacauth->hmac.data == NULL
84  || msg->hmacauth->hmac.len == 0) {
85  return false;
86  }
87 
89  KineticHMAC_Compute(&tempHMAC, msg, key);
90  if (msg->hmacauth->hmac.len == tempHMAC.len) {
91  for (i = 0; i < tempHMAC.len; i++) {
92  result |= msg->hmacauth->hmac.data[i] ^ tempHMAC.data[i];
93  }
94  success = (result == 0);
95  }
96 
97  if (!success) {
98  LOG0("HMAC did not compare!");
99  ByteArray expected = {.data = msg->hmacauth->hmac.data, .len = msg->hmacauth->hmac.len};
100  KineticLogger_LogByteArray(1, "expected HMAC", expected);
101  ByteArray actual = {.data = tempHMAC.data, .len = tempHMAC.len};
102  KineticLogger_LogByteArray(1, "actual HMAC", actual);
103  }
104 
105  return success;
106 }
107 
108 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
109 
110 #define LOG_HMAC 0
111 
113  const Com__Seagate__Kinetic__Proto__Message* msg,
114  const ByteArray key)
115 {
116  KINETIC_ASSERT(hmac != NULL);
117  KINETIC_ASSERT(hmac->data != NULL);
118  KINETIC_ASSERT(hmac->len > 0);
119  KINETIC_ASSERT(msg != NULL);
120  KINETIC_ASSERT(msg->has_commandbytes);
121  KINETIC_ASSERT(msg->commandbytes.data != NULL);
122  KINETIC_ASSERT(msg->commandbytes.len > 0);
123 
124  uint32_t lenNBO = KineticNBO_FromHostU32(msg->commandbytes.len);
125 
126  HMAC_CTX ctx;
127  HMAC_CTX_init(&ctx);
128 #if LOG_HMAC
129  fprintf(stderr, "\n\nUsing hmac key [%zd]: '%s' and length '", key.len, key.data);
130  for (size_t i = 0; i < sizeof(uint32_t); i++) {
131  fprintf(stderr, "%02x", ((uint8_t *)&lenNBO)[i]);
132  }
133 
134  fprintf(stderr, "' on data: \n");
135  for (size_t i = 0; i < msg->commandbytes.len; i++) {
136  fprintf(stderr, "%02x", msg->commandbytes.data[i]);
137  if (i > 0 && (i & 15) == 15) { fprintf(stderr, "\n"); }
138  }
139  fprintf(stderr, "\n\n");
140 #endif
141 
142  HMAC_Init_ex(&ctx, key.data, key.len, EVP_sha1(), NULL);
143  HMAC_Update(&ctx, (uint8_t*)&lenNBO, sizeof(uint32_t));
144  HMAC_Update(&ctx, msg->commandbytes.data, msg->commandbytes.len);
145  HMAC_Final(&ctx, hmac->data, &hmac->len);
146  HMAC_CTX_cleanup(&ctx);
147 }
Structure for handling generic arrays of bytes.
Definition: byte_array.h:34
bool KineticHMAC_Validate(const Com__Seagate__Kinetic__Proto__Message *msg, const ByteArray key)
Definition: kinetic_hmac.c:67
uint32_t KineticNBO_FromHostU32(uint32_t valueHost)
Definition: kinetic_nbo.c:32
#define KINETIC_HMAC_MAX_LEN
HMAC max length.
Definition: kinetic_types.h:43
void KineticHMAC_Populate(KineticHMAC *hmac, Com__Seagate__Kinetic__Proto__Message *msg, const ByteArray key)
Definition: kinetic_hmac.c:47
#define KINETIC_ASSERT(cond)
void KineticHMAC_Init(KineticHMAC *hmac, Com__Seagate__Kinetic__Proto__Command__Security__ACL__HMACAlgorithm algorithm)
Definition: kinetic_hmac.c:31
#define LOG0(message)
size_t len
Number of bytes in the data field.
Definition: byte_array.h:35
Com__Seagate__Kinetic__Proto__Command__Security__ACL__HMACAlgorithm
Definition: kinetic.pb-c.h:176
Com__Seagate__Kinetic__Proto__Command__Security__ACL__HMACAlgorithm algorithm
uint8_t data[KINETIC_HMAC_MAX_LEN]
uint8_t * data
Pointer to an allocated array of data bytes.
Definition: byte_array.h:36
void KineticLogger_LogByteArray(int log_level, const char *title, ByteArray bytes)
static void KineticHMAC_Compute(KineticHMAC *hmac, const Com__Seagate__Kinetic__Proto__Message *proto, const ByteArray key)
Definition: kinetic_hmac.c:112