Utils.cpp

Go to the documentation of this file.
00001 /*
00002  * Distributed under the OpenDDS License.
00003  * See: http://www.OpenDDS.org/license.html
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"  // Must come after all other OpenSSL includes
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) {  // First 6 bytes of guid prefix
00038         bytes[i] = offset_1bit(&hash[0], i);
00039       }
00040 
00041       bytes[0] |= 0x80;
00042 
00043       // Last 6 bytes of guid prefix = hash of src guid (candidate guid)
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       /* Copy data to nonce */
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     /* A bit slower but the impl. for vectors is already complete */
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 }  // namespace SSL
00262 }  // namespace Security
00263 }  // namespace OpenDDS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 10 Aug 2018 for OpenDDS by  doxygen 1.6.1