OpenDDS  Snapshot(2023/04/07-19:43)
security/SSL/Utils.cpp
Go to the documentation of this file.
1 /*
2  * Distributed under the OpenDDS License.
3  * See: http://www.OpenDDS.org/license.html
4  */
5 
6 #include "Utils.h"
7 
8 #include "Err.h"
9 
10 #include <dds/DCPS/Serializer.h>
11 #include <dds/DCPS/GuidUtils.h>
12 
13 #include <dds/DdsDcpsCoreTypeSupportImpl.h>
14 
15 #include <openssl/evp.h>
16 #include <openssl/rand.h>
17 #include <openssl/err.h>
18 #include "../OpenSSL_legacy.h" // Must come after all other OpenSSL includes
19 
20 #include <vector>
21 #include <utility>
22 #include <cstdio>
23 
25 
26 namespace OpenDDS {
27 namespace Security {
28 namespace SSL {
29 
30 using DCPS::Serializer;
31 using DCPS::Encoding;
33 
34 namespace {
35  Encoding get_common_encoding() {
37  return encoding;
38  }
39 }
40 
43  const Certificate& target)
44 {
46  dst.entityId = src.entityId;
47 
48  std::vector<unsigned char> hash;
49  int result = target.subject_name_digest(hash);
50 
51  if (result == 0 && hash.size() >= 6) {
52  unsigned char* bytes = reinterpret_cast<unsigned char*>(&dst);
53 
54  for (size_t i = 0; i < 6; ++i) { // First 6 bytes of guid prefix
55  bytes[i] = offset_1bit(&hash[0], i);
56  }
57 
58  bytes[0] |= 0x80;
59 
60  // Last 6 bytes of guid prefix = hash of src guid (candidate guid)
61 
62  unsigned char hash2[EVP_MAX_MD_SIZE] = {0};
63  unsigned int len = 0u;
64 
65  EVP_MD_CTX* hash_ctx = EVP_MD_CTX_new();
66  if (hash_ctx) {
67  EVP_DigestInit_ex(hash_ctx, EVP_sha256(), 0);
68  EVP_DigestUpdate(hash_ctx, &src, sizeof(OpenDDS::DCPS::GUID_t));
69  EVP_DigestFinal_ex(hash_ctx, hash2, &len);
70  if (len > 5) {
71  std::memcpy(bytes + 6, hash2, 6);
72  } else {
73  result = 1;
74  }
75 
76  EVP_MD_CTX_free(hash_ctx);
77  }
78  }
79 
80  return result;
81 }
82 
83 template <size_t Bits>
84 int make_nonce(std::vector<unsigned char>& nonce)
85 {
86  nonce.clear();
87 
88  unsigned char tmp[Bits / 8] = { 0 };
89 
90  if (RAND_bytes(tmp, sizeof tmp) == 1) {
91  nonce.insert(nonce.begin(), tmp, tmp + sizeof tmp);
92 
93  return 0;
94 
95  } else {
96  unsigned long err = ERR_get_error();
97  char msg[256] = { 0 };
98  ERR_error_string_n(err, msg, sizeof(msg));
99 
101  ACE_TEXT("(%P|%t) SSL::make_nonce: ERROR '%C' returned by RAND_bytes(...)\n"),
102  msg));
103  }
104 
105  return 1;
106 }
107 
108 int make_nonce_256(std::vector<unsigned char>& nonce)
109 {
110  return make_nonce<256>(nonce);
111 }
112 
114 {
115  /* A bit slower but the impl. for vectors is already complete */
116  std::vector<unsigned char> tmp;
117  int err = make_nonce<256>(tmp);
118  if (!err) {
119  nonce.length(static_cast<unsigned int>(tmp.size()));
120  for (size_t i = 0; i < tmp.size(); ++i) {
121  nonce[static_cast<unsigned int>(i)] = tmp[i];
122  }
123  }
124  return err;
125 }
126 
127 unsigned char offset_1bit(const unsigned char array[], size_t i)
128 {
129  return (array[i] >> 1) | (i == 0 ? 0 : ((array[i - 1] & 1) ? 0x80 : 0));
130 }
131 
132 int hash(const std::vector<const DDS::OctetSeq*>& src, DDS::OctetSeq& dst)
133 {
134  EVP_MD_CTX* hash_ctx = EVP_MD_CTX_new();
135  if (!hash_ctx) {
136  OPENDDS_SSL_LOG_ERR("EVP_MD_CTX_new failed");
137  return 1;
138  }
139 
140  EVP_DigestInit_ex(hash_ctx, EVP_sha256(), 0);
141 
142  unsigned char hash[EVP_MAX_MD_SIZE] = { 0 };
143  unsigned int len = 0u;
144 
145  std::vector<const DDS::OctetSeq*>::const_iterator i, n = src.end();
146  for (i = src.begin(); i != n; ++i) {
147  EVP_DigestUpdate(hash_ctx, (*i)->get_buffer(), (*i)->length());
148  }
149 
150  EVP_DigestFinal_ex(hash_ctx, hash, &len);
151 
152  dst.length(len);
153  std::memcpy(dst.get_buffer(), hash, len);
154 
155  EVP_MD_CTX_free(hash_ctx);
156 
157  return 0;
158 }
159 
161 {
162 public:
165  {
166  if (!hash_ctx) {
167  OPENDDS_SSL_LOG_ERR("EVP_MD_CTX_new failed");
168  }
169  }
170 
172  {
173  if (hash_ctx) {
175  }
176  }
177 
179  {
180  if (!hash_ctx) return 1;
181 
182  EVP_DigestInit_ex(hash_ctx, EVP_sha256(), 0);
183 
184  const Encoding encoding = get_common_encoding();
185  size_t size = 0;
186  serialized_size(encoding, size, src);
187  ACE_Message_Block buffer(size);
188  Serializer serializer(&buffer, encoding);
189  if (serializer << src) {
190  EVP_DigestUpdate(hash_ctx, buffer.rd_ptr(), buffer.length());
191 
192  dst.length(EVP_MAX_MD_SIZE);
193 
194  unsigned int newlen = 0u;
195  EVP_DigestFinal_ex(hash_ctx, dst.get_buffer(), &newlen);
196 
197  dst.length(newlen);
198 
199  } else {
201  ACE_TEXT("(%P|%t) SSL::hash_serialized_impl::operator(): ERROR, failed to "
202  "serialize binary-property-sequence\n")));
203 
204  return 1;
205  }
206 
207  return 0;
208  }
209 
210 private:
211  EVP_MD_CTX* hash_ctx;
212 };
213 
215 {
217  return hash(src, dst);
218 }
219 
221  const PrivateKey& key, DDS::OctetSeq& dst)
222 {
223  const Encoding encoding = get_common_encoding();
224  size_t size = 0;
225  serialized_size(encoding, size, src);
226 
227  DDS::OctetSeq tmp;
228  tmp.length(static_cast<unsigned int>(size));
229  ACE_Message_Block buffer(reinterpret_cast<const char*>(tmp.get_buffer()),
230  tmp.length());
231  Serializer serializer(&buffer, encoding);
232  if (!(serializer << src)) {
234  ACE_TEXT("(%P|%t) SSL::sign_serialized: ERROR, failed to serialize "
235  "binary-property-sequence\n")));
236 
237  return 1;
238  }
239 
240  std::vector<const DDS::OctetSeq*> sign_these;
241  sign_these.push_back(&tmp);
242 
243  return key.sign(sign_these, dst);
244 }
245 
247  const Certificate& key,
248  const DDS::OctetSeq& signed_data)
249 {
250  const Encoding encoding = get_common_encoding();
251  size_t size = 0;
252  serialized_size(encoding, size, src);
253 
254  DDS::OctetSeq tmp;
255  tmp.length(static_cast<unsigned int>(size));
256  ACE_Message_Block buffer(reinterpret_cast<const char*>(tmp.get_buffer()),
257  tmp.length());
258  Serializer serializer(&buffer, encoding);
259  if (!(serializer << src)) {
261  ACE_TEXT("(%P|%t) SSL::verify_serialized: ERROR, failed to serialize binary-property-sequence\n")));
262 
263  return 1;
264  }
265 
266  std::vector<const DDS::OctetSeq*> verify_these;
267  verify_these.push_back(&tmp);
268 
269  return key.verify_signature(signed_data, verify_these);
270 }
271 
272 } // namespace SSL
273 } // namespace Security
274 } // namespace OpenDDS
275 
#define ACE_ERROR(X)
int operator()(const DDS::BinaryPropertySeq &src, DDS::OctetSeq &dst)
size_t length(void) const
key EntityId_t entityId
Definition: DdsDcpsGuid.idl:59
sequence< octet > key
#define OPENDDS_END_VERSIONED_NAMESPACE_DECL
int sign(const std::vector< const DDS::OctetSeq *> &src, DDS::OctetSeq &dst) const
Definition: PrivateKey.cpp:157
int verify_serialized(const DDS::BinaryPropertySeq &src, const Certificate &key, const DDS::OctetSeq &signed_data)
Class to serialize and deserialize data for DDS.
Definition: Serializer.h:369
const GUID_t GUID_UNKNOWN
Nil value for GUID.
Definition: GuidUtils.h:59
The Internal API and Implementation of OpenDDS.
Definition: AddressCache.h:28
int sign_serialized(const DDS::BinaryPropertySeq &src, const PrivateKey &key, DDS::OctetSeq &dst)
int verify_signature(const DDS::OctetSeq &src, const std::vector< const DDS::OctetSeq *> &expected_contents) const
char * rd_ptr(void) const
const DCPS::Encoding encoding(DCPS::Encoding::KIND_UNALIGNED_CDR, DCPS::ENDIAN_BIG)
sequence< BinaryProperty_t > BinaryPropertySeq
Definition: DdsDcpsCore.idl:94
int make_nonce(std::vector< unsigned char > &nonce)
int subject_name_digest(std::vector< CORBA::Octet > &dst) const
int hash_serialized(const DDS::BinaryPropertySeq &src, DDS::OctetSeq &dst)
void serialized_size(const Encoding &encoding, size_t &size, const SequenceNumber &)
ACE_TEXT("TCP_Factory")
#define EVP_MD_CTX_new
int make_adjusted_guid(const OpenDDS::DCPS::GUID_t &src, OpenDDS::DCPS::GUID_t &dst, const Certificate &target)
int make_nonce_256(std::vector< unsigned char > &nonce)
#define EVP_MD_CTX_free
sequence< octet > OctetSeq
Definition: DdsDcpsCore.idl:64
int hash(const std::vector< const DDS::OctetSeq *> &src, DDS::OctetSeq &dst)
unsigned char offset_1bit(const unsigned char array[], size_t i)
Gets byte from array as though it were shifted right one bit.
LM_ERROR
#define OPENDDS_SSL_LOG_ERR(MSG)
Definition: Err.h:12