00001
00002
00003
00004
00005
00006 #include "Utils.h"
00007 #include "Err.h"
00008 #include "dds/DCPS/GuidUtils.h"
00009 #include <vector>
00010 #include <utility>
00011 #include <cstdio>
00012 #include <openssl/evp.h>
00013 #include <openssl/rand.h>
00014 #include <openssl/err.h>
00015 #include "../OpenSSL_legacy.h"
00016
00017 #include "dds/DCPS/Serializer.h"
00018 #include "dds/DdsDcpsCoreTypeSupportImpl.h"
00019
00020 namespace OpenDDS {
00021 namespace Security {
00022 namespace SSL {
00023
00024 int make_adjusted_guid(const OpenDDS::DCPS::GUID_t& src,
00025 OpenDDS::DCPS::GUID_t& dst,
00026 const Certificate& target)
00027 {
00028 dst = OpenDDS::DCPS::GUID_UNKNOWN;
00029 dst.entityId = src.entityId;
00030
00031 std::vector<unsigned char> hash;
00032 int result = target.subject_name_digest(hash);
00033
00034 if (result == 0 && hash.size() >= 6) {
00035 unsigned char* bytes = reinterpret_cast<unsigned char*>(&dst);
00036
00037 for (size_t i = 0; i < 6; ++i) {
00038 bytes[i] = offset_1bit(&hash[0], i);
00039 }
00040
00041 bytes[0] |= 0x80;
00042
00043
00044
00045 unsigned char hash2[EVP_MAX_MD_SIZE] = { 0 };
00046 unsigned int len = 0u;
00047
00048 EVP_MD_CTX* hash_ctx = EVP_MD_CTX_new();
00049 if (hash_ctx) {
00050 EVP_DigestInit_ex(hash_ctx, EVP_sha256(), NULL);
00051 EVP_DigestUpdate(hash_ctx, &src, sizeof(OpenDDS::DCPS::GUID_t));
00052 EVP_DigestFinal_ex(hash_ctx, hash2, &len);
00053 if (len > 5) {
00054 std::memcpy(bytes + 6, hash2, 6);
00055 } else {
00056 result = 1;
00057 }
00058
00059 EVP_MD_CTX_free(hash_ctx);
00060 }
00061 }
00062
00063 return result;
00064 }
00065
00066 template <size_t Bits>
00067 int make_nonce(std::vector<unsigned char>& nonce)
00068 {
00069 nonce.clear();
00070
00071 unsigned char tmp[Bits / 8] = { 0 };
00072
00073 int result = RAND_bytes(tmp, sizeof(tmp));
00074 if (1 == result) {
00075
00076 nonce.insert(nonce.begin(), tmp, tmp + sizeof(tmp));
00077
00078 return 0;
00079
00080 } else {
00081 unsigned long err = ERR_get_error();
00082 char msg[256] = { 0 };
00083 ERR_error_string_n(err, msg, sizeof(msg));
00084
00085 ACE_ERROR((LM_ERROR,
00086 ACE_TEXT("(%P|%t) SSL::make_nonce: ERROR '%C' returned by RAND_bytes(...)\n"),
00087 msg));
00088 }
00089
00090 return 1;
00091 }
00092
00093 int make_nonce_256(std::vector<unsigned char>& nonce)
00094 {
00095 return make_nonce<256>(nonce);
00096 }
00097
00098 int make_nonce_256(DDS::OctetSeq& nonce)
00099 {
00100
00101 std::vector<unsigned char> tmp;
00102 int err = make_nonce<256>(tmp);
00103 if (!err) {
00104 nonce.length(tmp.size());
00105 for (size_t i = 0; i < tmp.size(); ++i) {
00106 nonce[i] = tmp[i];
00107 }
00108 }
00109 return err;
00110 }
00111
00112 unsigned char offset_1bit(const unsigned char array[], size_t i)
00113 {
00114 return (array[i] >> 1) | (i == 0 ? 0 : ((array[i - 1] & 1) ? 0x80 : 0));
00115 }
00116
00117 int hash(const std::vector<const DDS::OctetSeq*>& src, DDS::OctetSeq& dst)
00118 {
00119 EVP_MD_CTX* hash_ctx = EVP_MD_CTX_new();
00120 if (!hash_ctx) {
00121 OPENDDS_SSL_LOG_ERR("EVP_MD_CTX_new failed");
00122 return 1;
00123 }
00124
00125 EVP_DigestInit_ex(hash_ctx, EVP_sha256(), NULL);
00126
00127 unsigned char hash[EVP_MAX_MD_SIZE] = { 0 };
00128 unsigned int len = 0u;
00129
00130 std::vector<const DDS::OctetSeq*>::const_iterator i, n = src.end();
00131 for (i = src.begin(); i != n; ++i) {
00132 EVP_DigestUpdate(hash_ctx, (*i)->get_buffer(), (*i)->length());
00133 }
00134
00135 EVP_DigestFinal_ex(hash_ctx, hash, &len);
00136
00137 dst.length(len);
00138 std::memcpy(dst.get_buffer(), hash, len);
00139
00140 EVP_MD_CTX_free(hash_ctx);
00141
00142 return 0;
00143 }
00144
00145 class hash_serialized_impl
00146 {
00147 public:
00148 hash_serialized_impl() : hash_ctx(NULL)
00149 {
00150 hash_ctx = EVP_MD_CTX_new();
00151 if (!hash_ctx) {
00152 OPENDDS_SSL_LOG_ERR("EVP_MD_CTX_new failed");
00153 }
00154 }
00155
00156 ~hash_serialized_impl()
00157 {
00158 if (hash_ctx) EVP_MD_CTX_free(hash_ctx);
00159 }
00160
00161 int operator()(const DDS::BinaryPropertySeq& src, DDS::OctetSeq& dst)
00162 {
00163 if (!hash_ctx) return 1;
00164
00165 EVP_DigestInit_ex(hash_ctx, EVP_sha256(), NULL);
00166
00167 size_t size = 0u, padding = 0u;
00168 DCPS::gen_find_size(src, size, padding);
00169 ACE_Message_Block buffer(size + padding);
00170
00171 OpenDDS::DCPS::Serializer serializer(
00172 &buffer, OpenDDS::DCPS::Serializer::SWAP_BE,
00173 OpenDDS::DCPS::Serializer::ALIGN_INITIALIZE);
00174 if (serializer << src) {
00175 EVP_DigestUpdate(hash_ctx, buffer.rd_ptr(), buffer.length());
00176
00177 dst.length(EVP_MAX_MD_SIZE);
00178
00179 unsigned int newlen = 0u;
00180 EVP_DigestFinal_ex(hash_ctx, dst.get_buffer(), &newlen);
00181
00182 dst.length(newlen);
00183
00184 } else {
00185 ACE_ERROR((LM_ERROR,
00186 ACE_TEXT("(%P|%t) SSL::hash_serialized_impl::operator(): ERROR, failed to "
00187 "serialize binary-property-sequence\n")));
00188
00189 return 1;
00190 }
00191
00192 return 0;
00193 }
00194
00195 private:
00196 EVP_MD_CTX* hash_ctx;
00197 };
00198
00199 int hash_serialized(const DDS::BinaryPropertySeq& src, DDS::OctetSeq& dst)
00200 {
00201 hash_serialized_impl hash;
00202 return hash(src, dst);
00203 }
00204
00205 int sign_serialized(const DDS::BinaryPropertySeq& src,
00206 const PrivateKey& key, DDS::OctetSeq& dst)
00207 {
00208 size_t size = 0u, padding = 0u;
00209 DCPS::gen_find_size(src, size, padding);
00210
00211 DDS::OctetSeq tmp;
00212 tmp.length(size + padding);
00213 ACE_Message_Block buffer(reinterpret_cast<const char*>(tmp.get_buffer()),
00214 tmp.length());
00215
00216 OpenDDS::DCPS::Serializer serializer(
00217 &buffer, OpenDDS::DCPS::Serializer::SWAP_BE,
00218 OpenDDS::DCPS::Serializer::ALIGN_INITIALIZE);
00219 if (!(serializer << src)) {
00220 ACE_ERROR((LM_ERROR,
00221 ACE_TEXT("(%P|%t) SSL::sign_serialized: ERROR, failed to serialize "
00222 "binary-property-sequence\n")));
00223
00224 return 1;
00225 }
00226
00227 std::vector<const DDS::OctetSeq*> sign_these;
00228 sign_these.push_back(&tmp);
00229
00230 return key.sign(sign_these, dst);
00231 }
00232
00233 int verify_serialized(const DDS::BinaryPropertySeq& src,
00234 const Certificate& key,
00235 const DDS::OctetSeq& signed_data)
00236 {
00237 size_t size = 0u, padding = 0u;
00238 DCPS::gen_find_size(src, size, padding);
00239
00240 DDS::OctetSeq tmp;
00241 tmp.length(size + padding);
00242 ACE_Message_Block buffer(reinterpret_cast<const char*>(tmp.get_buffer()),
00243 tmp.length());
00244
00245 OpenDDS::DCPS::Serializer serializer(
00246 &buffer, OpenDDS::DCPS::Serializer::SWAP_BE,
00247 OpenDDS::DCPS::Serializer::ALIGN_INITIALIZE);
00248 if (!(serializer << src)) {
00249 ACE_ERROR((LM_ERROR,
00250 ACE_TEXT("(%P|%t) SSL::verify_serialized: ERROR, failed to serialize binary-property-sequence\n")));
00251
00252 return 1;
00253 }
00254
00255 std::vector<const DDS::OctetSeq*> verify_these;
00256 verify_these.push_back(&tmp);
00257
00258 return key.verify_signature(signed_data, verify_these);
00259 }
00260
00261 }
00262 }
00263 }