Motr  M0
cksum.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2020-2021 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
23 #include "lib/memory.h" /* m0_alloc, m0_free */
24 #include "lib/cksum.h"
25 
26 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_LIB
27 #include "lib/trace.h"
28 
29 
31  struct m0_md5_inc_context_pi *pi,
32  struct m0_pi_seed *seed,
33  struct m0_bufvec *bvec,
34  enum m0_pi_calc_flag flag,
35  unsigned char *curr_context,
36  unsigned char *pi_value_without_seed)
37 {
38 #ifndef __KERNEL__
39  MD5_CTX context;
40  int i, rc;
41 
42  M0_ENTRY();
43 
44  M0_PRE(pi != NULL);
46  M0_PRE(ergo(bvec != NULL && bvec->ov_vec.v_nr != 0,
47  bvec != NULL && bvec->ov_vec.v_count != NULL &&
48  bvec->ov_buf != NULL));
49 
50  /* This call is for first data unit, need to initialize prev_context */
51  if (flag & M0_PI_CALC_UNIT_ZERO) {
52  pi->pimd5c_hdr.pih_size = sizeof(struct m0_md5_inc_context_pi);
53  rc = MD5_Init((MD5_CTX *)&pi->pimd5c_prev_context);
54  if (rc != 1) {
55  return M0_ERR_INFO(rc, "MD5_Init failed.");
56  }
57  }
58 
59  /* memcpy, so that we do not change the prev_context */
60  memcpy(curr_context, &pi->pimd5c_prev_context, sizeof(MD5_CTX));
61 
62 
63  /* get the curr context by updating it*/
64  if (bvec != NULL) {
65  for (i = 0; i < bvec->ov_vec.v_nr; i++) {
66  rc = MD5_Update((MD5_CTX *)curr_context, bvec->ov_buf[i],
67  bvec->ov_vec.v_count[i]);
68  if (rc != 1) {
69  return M0_ERR_INFO(rc, "MD5_Update failed."
70  "curr_context=%p, "
71  "bvec->ov_buf[%d]=%p, "
72  "bvec->ov_vec.v_count[%d]=%lu",
73  curr_context, i,
74  bvec->ov_buf[i], i,
75  bvec->ov_vec.v_count[i]);
76  }
77  }
78  }
79 
80  /* If caller wants checksum without seed and with seed, caller needs to
81  * pass 'pi_value_without_seed'. pi_value will be used to return with
82  * seed checksum. 'pi_value_without_seed' will be used to return non
83  * seeded checksum.
84  */
85  if (pi_value_without_seed != NULL) {
86  /*
87  * NOTE: MD5_final() changes the context itself and curr_context
88  * should not be finalised, thus copy it and use it for MD5_final
89  */
90  memcpy((void *)&context, (void *)curr_context, sizeof(MD5_CTX));
91 
92  rc = MD5_Final(pi_value_without_seed, &context);
93  if (rc != 1) {
94  return M0_ERR_INFO(rc, "MD5_Final failed"
95  "pi_value_without_seed=%p"
96  "curr_context=%p",
97  pi_value_without_seed, curr_context);
98  }
99  }
100 
101  /* if seed is passed, memcpy and update the context calculated so far.
102  * calculate checksum with seed, set the pi_value with seeded checksum.
103  * If seed is not passed than memcpy context and calculate checksum
104  * without seed, set the pi_value with unseeded checksum.
105  * NOTE: curr_context will always have context without seed.
106  */
107  memcpy((void *)&context, (void *)curr_context, sizeof(MD5_CTX));
108 
109  if (seed != NULL) {
110 
111  /*
112  * seed_str have string represention for 3 uint64_t(8 bytes)
113  * range for uint64_t is 0 to 18,446,744,073,709,551,615 at
114  * max 20 chars per var, for three var it will be 3*20, +1 '\0'.
115  * seed_str needs to be 61 bytes, round off and taking 64 bytes.
116  */
117  char seed_str[64] = {'\0'};
118  snprintf(seed_str, sizeof(seed_str), "%" PRIx64 "%" PRIx64 "%"PRIx64,
119  seed->pis_obj_id.f_container, seed->pis_obj_id.f_key,
120  seed->pis_data_unit_offset);
121  rc = MD5_Update(&context, (unsigned char *)seed_str,
122  sizeof(seed_str));
123  if (rc != 1) {
124 
125  return M0_ERR_INFO(rc, "MD5_Update fail curr_context=%p"
126  "f_container 0x%" PRIx64 " f_key 0x%"PRIx64
127  " data_unit_offset 0x%" PRIx64 " seed_str %s",
128  curr_context, seed->pis_obj_id.f_container,
129  seed->pis_obj_id.f_key,
130  seed->pis_data_unit_offset,
131  (char *)seed_str);
132  }
133  }
134 
135  if (!(flag & M0_PI_SKIP_CALC_FINAL)) {
136  rc = MD5_Final(pi->pimd5c_value, &context);
137  if (rc != 1) {
138  return M0_ERR_INFO(rc, "MD5_Final fail curr_context=%p",
139  curr_context);
140  }
141  }
142 #endif
143  return M0_RC(0);
144 }
145 
146 M0_INTERNAL uint64_t m0_calculate_cksum_size(struct m0_generic_pi *pi)
147 {
148  M0_ENTRY();
149 #ifndef __KERNEL__
150  switch (pi->pi_hdr.pih_type) {
152  return sizeof(struct m0_md5_inc_context_pi);
153  break;
154  case M0_PI_TYPE_MD5:
155  return sizeof(struct m0_md5_pi);
156  break;
157  }
158 #endif
159  return 0;
160 }
161 
162 M0_INTERNAL uint64_t max_cksum_size(void)
163 {
164  return (sizeof(struct m0_md5_pi) > sizeof(struct m0_md5_inc_context_pi) ?
165  sizeof(struct m0_md5_pi) : sizeof(struct m0_md5_inc_context_pi));
166 }
167 
169  struct m0_pi_seed *seed,
170  struct m0_bufvec *bvec,
171  enum m0_pi_calc_flag flag,
172  unsigned char *curr_context,
173  unsigned char *pi_value_without_seed)
174 {
175  int rc = 0;
176  M0_ENTRY();
177 #ifndef __KERNEL__
178  switch (pi->pi_hdr.pih_type) {
180  struct m0_md5_inc_context_pi *md5_context_pi =
181  (struct m0_md5_inc_context_pi *) pi;
182  rc = m0_calculate_md5_inc_context(md5_context_pi, seed, bvec,
184  pi_value_without_seed);
185  }
186  break;
187  }
188 #endif
189  return M0_RC(rc);
190 }
191 
192 M0_EXPORTED(m0_client_calculate_pi);
193 
195  struct m0_pi_seed *seed,
196  struct m0_bufvec *bvec)
197 {
198 #ifndef __KERNEL__
199  switch (pi->pi_hdr.pih_type) {
201  {
202  struct m0_md5_inc_context_pi md5_ctx_pi;
203  unsigned char *curr_context = m0_alloc(sizeof(MD5_CTX));
204  memset(&md5_ctx_pi, 0, sizeof(struct m0_md5_inc_context_pi));
205  if (curr_context == NULL) {
206  return false;
207  }
208  memcpy(md5_ctx_pi.pimd5c_prev_context,
209  ((struct m0_md5_inc_context_pi *)pi)->pimd5c_prev_context,
210  sizeof(MD5_CTX));
212  m0_client_calculate_pi((struct m0_generic_pi *)&md5_ctx_pi,
214  curr_context, NULL);
216  if (memcmp(((struct m0_md5_inc_context_pi *)pi)->pimd5c_value,
217  md5_ctx_pi.pimd5c_value,
218  MD5_DIGEST_LENGTH) == 0) {
219  return true;
220  }
221  else {
222  M0_LOG(M0_ERROR, "checksum fail "
223  "f_container 0x%" PRIx64 " f_key 0x%"PRIx64
224  " data_unit_offset 0x%"PRIx64,
225  seed->pis_obj_id.f_container,
226  seed->pis_obj_id.f_key,
227  seed->pis_data_unit_offset);
228  return false;
229  }
230  break;
231  }
232  default:
233  M0_IMPOSSIBLE("pi_type = %d", pi->pi_hdr.pih_type);
234  }
235 #endif
236  return true;
237 }
238 
239 M0_EXPORTED(m0_calc_verify_cksum_one_unit);
240 
241 #undef M0_TRACE_SUBSYSTEM
242 
243 /*
244  * Local variables:
245  * c-indentation-style: "K&R"
246  * c-basic-offset: 8
247  * tab-width: 8
248  * fill-column: 80
249  * scroll-step: 1
250  * End:
251  */
252 /*
253  * vim: tabstop=8 shiftwidth=8 noexpandtab textwidth=80 nowrap
254  */
#define M0_PRE(cond)
#define NULL
Definition: misc.h:38
unsigned char * curr_context[DATA_UNIT_COUNT]
#define ergo(a, b)
Definition: misc.h:293
M0_INTERNAL uint64_t m0_calculate_cksum_size(struct m0_generic_pi *pi)
Definition: cksum.c:146
#define M0_LOG(level,...)
Definition: trace.h:167
int m0_client_calculate_pi(struct m0_generic_pi *pi, struct m0_pi_seed *seed, struct m0_bufvec *bvec, enum m0_pi_calc_flag flag, unsigned char *curr_context, unsigned char *pi_value_without_seed)
Definition: cksum.c:168
struct m0_vec ov_vec
Definition: vec.h:147
void ** ov_buf
Definition: vec.h:149
#define PRIx64
Definition: types.h:61
unsigned char pimd5c_value[MD5_DIGEST_LENGTH]
Definition: cksum.h:109
return M0_RC(rc)
#define M0_ENTRY(...)
Definition: trace.h:170
int i
Definition: dir.c:1033
#define M0_ERR_INFO(rc, fmt,...)
Definition: trace.h:215
static struct m0_bufvec bvec
Definition: xcode.c:169
m0_pi_calc_flag
Definition: cksum.h:65
void * m0_alloc(size_t size)
Definition: memory.c:126
struct m0_pdclust_instance pi
Definition: fd.c:107
uint32_t v_nr
Definition: vec.h:51
m0_bcount_t * v_count
Definition: vec.h:53
struct m0_pi_hdr pimd5c_hdr
Definition: cksum.h:101
M0_INTERNAL uint64_t max_cksum_size(void)
Definition: cksum.c:162
static bool flag
Definition: nucleus.c:266
uint8_t pih_type
Definition: cksum.h:80
unsigned char pimd5c_prev_context[sizeof(MD5_CTX)]
Definition: cksum.h:104
void m0_free(void *data)
Definition: memory.c:146
bool m0_calc_verify_cksum_one_unit(struct m0_generic_pi *pi, struct m0_pi_seed *seed, struct m0_bufvec *bvec)
Definition: cksum.c:194
int32_t rc
Definition: trigger_fop.h:47
M0_INTERNAL int m0_calculate_md5_inc_context(struct m0_md5_inc_context_pi *pi, struct m0_pi_seed *seed, struct m0_bufvec *bvec, enum m0_pi_calc_flag flag, unsigned char *curr_context, unsigned char *pi_value_without_seed)
Definition: cksum.c:30
Definition: vec.h:145
#define M0_IMPOSSIBLE(fmt,...)