14 #include <openssl/pem.h> 15 #include <openssl/x509v3.h> 16 #include "../OpenSSL_legacy.h" 26 const std::string& password)
27 : x_(0), original_bytes_(), dsign_algo_(
"")
30 if (!
load(ex, uri, password)) {
73 const std::string& uri,
74 const std::string& password)
76 using namespace CommonUtilities;
79 set_security_error(ex, -1, 0,
"SSL::Certificate::load: WARNING: document already loaded");
100 "(%P|%t) SSL::Certificate::load: WARNING: Unsupported URI scheme\n"));
106 std::stringstream msg;
107 msg <<
"SSL::Certificate::load: WARNING: Failed to load document supplied " 108 "with URI '" << uri <<
"'";
115 set_security_error(ex, -1, 0,
"SSL::Certificate::load: WARNING: Failed to cache signature algorithm");
125 ACE_TEXT(
"(%P|%t) SSL::Certificate::verify: WARNING, a ")
126 ACE_TEXT(
"certificate must be loaded before it can be verified\n")), 1);
131 ACE_TEXT(
"(%P|%t) SSL::Certificate::verify: WARNING, passed-in ")
132 ACE_TEXT(
"CA has not loaded a certificate\n")), 1);
135 X509_STORE*
const certs = X509_STORE_new();
141 X509_STORE_add_cert(certs, ca.
x_);
143 X509_STORE_CTX* validation_ctx = X509_STORE_CTX_new();
144 if (!validation_ctx) {
145 X509_STORE_free(certs);
149 X509_STORE_CTX_init(validation_ctx, certs,
x_, 0);
150 X509_STORE_CTX_set_flags(validation_ctx, flags);
153 X509_verify_cert(validation_ctx) == 1
157 const int err = X509_STORE_CTX_get_error(validation_ctx),
158 depth = X509_STORE_CTX_get_error_depth(validation_ctx);
160 ACE_TEXT(
"(%P|%t) SSL::Certificate::verify: WARNING '%C' occurred using cert at ")
161 ACE_TEXT(
"depth '%i', validation failed.\n"),
162 X509_verify_cert_error_string(err), depth));
166 X509_STORE_CTX_free(validation_ctx);
167 X509_STORE_free(certs);
175 : public_key(pkey), md_ctx(0), pkey_ctx(0)
182 const std::vector<const DDS::OctetSeq*>& expected_contents)
184 if (!public_key)
return 1;
187 std::vector<const DDS::OctetSeq*>::const_iterator i, n;
195 EVP_MD_CTX_init(md_ctx);
197 if (1 != EVP_DigestVerifyInit(md_ctx, &pkey_ctx, EVP_sha256(), 0,
204 pk_id = EVP_PKEY_id(public_key);
206 if (pk_id == EVP_PKEY_RSA) {
208 EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING)) {
213 if (1 != EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, EVP_sha256())) {
219 n = expected_contents.end();
220 for (i = expected_contents.begin(); i != n; ++i) {
221 if ((*i)->length() > 0) {
222 if (1 != EVP_DigestVerifyUpdate(md_ctx, (*i)->get_buffer(),
232 unsigned char* buffer =
const_cast<unsigned char*
>(src.get_buffer());
234 const unsigned char* buffer = src.get_buffer();
236 const int err = EVP_DigestVerifyFinal(md_ctx, buffer, src.length());
240 }
else if (1 != err) {
256 const std::vector<const DDS::OctetSeq*>& expected_contents)
const 259 struct EVP_PKEY_Handle {
263 ~EVP_PKEY_Handle() { EVP_PKEY_free(pkey_); }
264 } pkey(X509_get_pubkey(
x_));
269 return verify(src, expected_contents);
273 unsigned long flags)
const 281 X509_NAME*
name = X509_get_subject_name(
x_);
283 BIO* buffer = BIO_new(BIO_s_mem());
285 int len = X509_NAME_print_ex(buffer, name, 0, flags);
287 std::vector<char> tmp(len +
289 len = BIO_gets(buffer, &tmp[0], len + 1);
321 X509_NAME*
name = X509_get_subject_name(
x_);
327 std::vector<CORBA::Octet> tmp(EVP_MAX_MD_SIZE);
329 unsigned int len = 0;
330 if (1 != X509_NAME_digest(name, EVP_sha256(), &tmp[0], &len)) {
335 dst.insert(dst.begin(), tmp.begin(), tmp.begin() + len);
344 if (std::string(
"RSASSA-PSS-SHA256") ==
dsign_algo_) {
347 }
else if (std::string(
"ECDSA-SHA256") ==
dsign_algo_) {
348 return "EC-prime256v1";
357 #ifndef OPENSSL_V_3_0 361 EVP_PKEY_free(
pkey_);
369 EVP_PKEY_free(
pkey_);
373 int operator() (
X509* cert, std::string& dst)
377 "(%P|%t) SSL::Certificate::cache_dsign_algo: WARNING, failed to " 378 "get pubkey from X509 cert\n"));
382 pkey_ = X509_get_pubkey(cert);
388 #ifndef OPENSSL_V_3_0 389 rsa_ = EVP_PKEY_get1_RSA(
pkey_);
391 dst =
"RSASSA-PSS-SHA256";
395 ec_ = EVP_PKEY_get1_EC_KEY(
pkey_);
397 dst =
"ECDSA-SHA256";
401 const int ptype = EVP_PKEY_id (
pkey_);
402 if (ptype == EVP_PKEY_RSA || ptype == EVP_PKEY_RSA_PSS) {
403 dst =
"RSASSA-PSS-SHA256";
405 }
else if (ptype == EVP_PKEY_EC) {
406 dst =
"ECDSA-SHA256";
412 "(%P|%t) SSL::Certificate::cache_dsign_algo: WARNING, only RSASSA-PSS-SHA256 or " 413 "ECDSA-SHA256 are currently supported signature/verification algorithms\n"));
420 #ifndef OPENSSL_V_3_0 457 std::ifstream in(path.c_str(), std::ios::binary);
461 "(%P|%t) Certificate::load_cert_bytes:" 462 "WARNING: Failed to load file '%C'; '%m'\n",
467 const std::ifstream::pos_type begin = in.tellg();
468 in.seekg(0, std::ios::end);
469 const std::ifstream::pos_type end = in.tellg();
470 in.seekg(0, std::ios::beg);
473 in.read(reinterpret_cast<char*>(
original_bytes_.get_buffer()), end - begin);
477 "(%P|%t) Certificate::load_cert_bytes:" 478 "WARNING: Failed to load file '%C'; '%m'\n",
495 std::memcpy(
original_bytes_.get_buffer(), data.c_str() + 1, data.size());
499 const std::string& password)
503 BIO* filebuf = BIO_new_file(path.c_str(),
"r");
505 if (!password.empty()) {
507 PEM_read_bio_X509_AUX(filebuf, 0, 0, (
void*)password.c_str());
513 result = PEM_read_bio_X509_AUX(filebuf, 0, 0, 0);
522 std::stringstream errmsg;
523 errmsg <<
"failed to read file '" << path <<
"' using BIO_new_file";
531 const std::string& password)
535 BIO* filebuf = BIO_new(BIO_s_mem());
538 if (0 >= BIO_write(filebuf, bytes.get_buffer(), bytes.length())) {
542 if (!password.empty()) {
543 result = PEM_read_bio_X509_AUX(filebuf, 0, 0,
544 (
void*)password.c_str());
551 result = PEM_read_bio_X509_AUX(filebuf, 0, 0, 0);
559 std::stringstream errmsg;
560 errmsg <<
"BIO_new failed";
586 : src_(src), buffer_(BIO_new(BIO_s_mem()))
598 "(%P|%t) SSL::Certificate::deserialize: WARNING, an X509 certificate " 599 "has already been loaded\n"));
603 if (0 == src_.length()) {
605 "(%P|%t) SSL::Certificate::deserialize: WARNING, source OctetSeq contains no data"));
614 const int len = BIO_write(buffer_, src_.get_buffer(), src_.length());
620 dst = PEM_read_bio_X509_AUX(buffer_, 0, 0, 0);
647 lhs <<
"Certificate: { is_ca? '" 648 << (X509_check_ca(rhs.
x_) ?
"yes" :
"no") <<
"'; }";
658 if (lhs.
x_ && rhs.
x_) {
659 return (0 == X509_cmp(lhs.
x_, rhs.
x_)) &&
662 return (lhs.
x_ == rhs.
x_) &&
This URI abstraction is currently naive and only separates the URI scheme on the LHS from the "everyt...
int deserialize(const DDS::OctetSeq &src)
SequenceBackInsertIterator< Sequence > back_inserter(Sequence &seq)
void * memcpy(void *t, const void *s, size_t len)
bool load(DDS::Security::SecurityException &ex, const std::string &uri, const std::string &password="")
struct evp_pkey_st EVP_PKEY
int verify_signature(const DDS::OctetSeq &src, const std::vector< const DDS::OctetSeq *> &expected_contents) const
FILE * fopen(const char *filename, const char *mode)
size_t fread(void *ptr, size_t size, size_t nelems, FILE *fp)
int validate(const Certificate &ca, unsigned long int flags=0u) const
const DDS::OctetSeq & src_
std::string everything_else
friend OpenDDS_Security_Export std::ostream & operator<<(std::ostream &, const Certificate &)
verify_implementation(EVP_PKEY *pkey)
deserialize_impl(const DDS::OctetSeq &src)
friend OpenDDS_Security_Export bool operator==(const Certificate &lhs, const Certificate &rhs)
Certificate & operator=(const Certificate &rhs)
sequence< octet > OctetSeq
int subject_name_digest(std::vector< CORBA::Octet > &dst) const
void load_cert_bytes(const std::string &path)
int operator()(const DDS::OctetSeq &src, const std::vector< const DDS::OctetSeq *> &expected_contents)
DDS::ReturnCode_t copy(DDS::DynamicData_ptr dest, DDS::DynamicData_ptr src)
#define OPENDDS_END_VERSIONED_NAMESPACE_DECL
int subject_name_to_str(std::string &dst, unsigned long flags=XN_FLAG_ONELINE) const
int serialize(DDS::OctetSeq &dst) const
void load_cert_data_bytes(const std::string &data)
#define ACE_ERROR_RETURN(X, Y)
static X509 * x509_from_pem(const std::string &path, const std::string &password="")
DDS::OctetSeq original_bytes_
bool set_security_error(DDS::Security::SecurityException &ex, int code, int minor_code, const char *message)
The Internal API and Implementation of OpenDDS.
#define OPENDDS_SSL_LOG_ERR(MSG)
const char * keypair_algo() const