]> git.proxmox.com Git - ceph.git/blame - ceph/src/arrow/cpp/src/gandiva/hash_utils.cc
import quincy 17.2.0
[ceph.git] / ceph / src / arrow / cpp / src / gandiva / hash_utils.cc
CommitLineData
1d09f67e
TL
1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. 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,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18#include "gandiva/hash_utils.h"
19#include <cstring>
20#include "arrow/util/logging.h"
21#include "gandiva/gdv_function_stubs.h"
22#include "openssl/evp.h"
23
24namespace gandiva {
25/// Hashes a generic message using the SHA256 algorithm
26GANDIVA_EXPORT
27const char* gdv_hash_using_sha256(int64_t context, const void* message,
28 size_t message_length, int32_t* out_length) {
29 constexpr int sha256_result_length = 64;
30 return gdv_hash_using_sha(context, message, message_length, EVP_sha256(),
31 sha256_result_length, out_length);
32}
33
34/// Hashes a generic message using the SHA1 algorithm
35GANDIVA_EXPORT
36const char* gdv_hash_using_sha1(int64_t context, const void* message,
37 size_t message_length, int32_t* out_length) {
38 constexpr int sha1_result_length = 40;
39 return gdv_hash_using_sha(context, message, message_length, EVP_sha1(),
40 sha1_result_length, out_length);
41}
42
43/// \brief Hashes a generic message using SHA algorithm.
44///
45/// It uses the EVP API in the OpenSSL library to generate
46/// the hash. The type of the hash is defined by the
47/// \b hash_type \b parameter.
48GANDIVA_EXPORT
49const char* gdv_hash_using_sha(int64_t context, const void* message,
50 size_t message_length, const EVP_MD* hash_type,
51 uint32_t result_buf_size, int32_t* out_length) {
52 EVP_MD_CTX* md_ctx = EVP_MD_CTX_new();
53
54 if (md_ctx == nullptr) {
55 gdv_fn_context_set_error_msg(context,
56 "Could not create the context for SHA processing.");
57 *out_length = 0;
58 return "";
59 }
60
61 int evp_success_status = 1;
62
63 if (EVP_DigestInit_ex(md_ctx, hash_type, nullptr) != evp_success_status ||
64 EVP_DigestUpdate(md_ctx, message, message_length) != evp_success_status) {
65 gdv_fn_context_set_error_msg(context,
66 "Could not obtain the hash for the defined value.");
67 EVP_MD_CTX_free(md_ctx);
68
69 *out_length = 0;
70 return "";
71 }
72
73 // Create the temporary buffer used by the EVP to generate the hash
74 unsigned int hash_digest_size = EVP_MD_size(hash_type);
75 auto* result = static_cast<unsigned char*>(OPENSSL_malloc(hash_digest_size));
76
77 if (result == nullptr) {
78 gdv_fn_context_set_error_msg(context, "Could not allocate memory for SHA processing");
79 EVP_MD_CTX_free(md_ctx);
80 *out_length = 0;
81 return "";
82 }
83
84 unsigned int result_length;
85 EVP_DigestFinal_ex(md_ctx, result, &result_length);
86
87 if (result_length != hash_digest_size && result_buf_size != (2 * hash_digest_size)) {
88 gdv_fn_context_set_error_msg(context,
89 "Could not obtain the hash for the defined value");
90 EVP_MD_CTX_free(md_ctx);
91 OPENSSL_free(result);
92
93 *out_length = 0;
94 return "";
95 }
96
97 auto result_buffer =
98 reinterpret_cast<char*>(gdv_fn_context_arena_malloc(context, result_buf_size));
99
100 if (result_buffer == nullptr) {
101 gdv_fn_context_set_error_msg(context,
102 "Could not allocate memory for the result buffer");
103 // Free the resources used by the EVP
104 EVP_MD_CTX_free(md_ctx);
105 OPENSSL_free(result);
106
107 *out_length = 0;
108 return "";
109 }
110
111 unsigned int result_buff_index = 0;
112 for (unsigned int j = 0; j < result_length; j++) {
113 DCHECK(result_buff_index >= 0 && result_buff_index < result_buf_size);
114
115 unsigned char hex_number = result[j];
116 result_buff_index +=
117 snprintf(result_buffer + result_buff_index, result_buf_size, "%02x", hex_number);
118 }
119
120 // Free the resources used by the EVP to avoid memory leaks
121 EVP_MD_CTX_free(md_ctx);
122 OPENSSL_free(result);
123
124 *out_length = result_buf_size;
125 return result_buffer;
126}
127
128GANDIVA_EXPORT
129uint64_t gdv_double_to_long(double value) {
130 uint64_t result;
131 memcpy(&result, &value, sizeof(result));
132 return result;
133}
134} // namespace gandiva