1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
|
/* -*- indent-tabs-mode: nil -*- */
#include "proto/serializer_v2.h"
#include <glog/logging.h>
#include "util/status.h"
#include "util/openssl_util.h"
#include "util/openssl_scoped_types.h"
#if defined(OPENSSL_IS_BORINGSSL)
#include <openssl/asn1.h>
#endif
namespace rfc6962_bis {
using util::StatusOr;
using util::Status;
using cert_trans::ScopedOpenSSLBytes;
namespace {
const char kDerOIDTag = 0x06;
// OpenSSL documentation recommends 80, see the BUGS section in:
// https://www.openssl.org/docs/manmaster/crypto/OBJ_obj2txt.html
const size_t kTextOIDMaxSize = 80;
}
OID::OID() : oid_(nullptr) {
}
OID::OID(ASN1_OBJECT* oid) : oid_(oid) {
CHECK_NOTNULL(oid_);
}
OID::OID(const OID& other) : oid_(nullptr) {
if (other.oid_ != nullptr) {
oid_ = OBJ_dup(other.oid_);
}
}
OID::~OID() {
if (oid_ != nullptr) {
ASN1_OBJECT_free(oid_);
}
}
util::StatusOr<std::string> OID::ToTagMissingDER() const {
if(oid_ == nullptr) {
// Uninitialized.
return Status(util::error::INVALID_ARGUMENT,
std::string("OID not initialized."));
}
int encoded_length = i2d_ASN1_OBJECT(oid_, NULL);
if (encoded_length <= 0) {
return Status(util::error::INVALID_ARGUMENT,
std::string("Failed to encode OID: ") +
util::DumpOpenSSLErrorStack());
}
ScopedOpenSSLBytes encoded_oid(
reinterpret_cast<uint8_t*>(OPENSSL_malloc(encoded_length)));
// i2d_ASN1_OBJECT will change the pointer, so have to use a temporary.
unsigned char* tmp_ptr = encoded_oid.get();
encoded_length = i2d_ASN1_OBJECT(oid_, &tmp_ptr);
if (encoded_length <= 0) {
return Status(util::error::INVALID_ARGUMENT,
std::string("Failed to encode OID: ") +
util::DumpOpenSSLErrorStack());
}
// If the first byte, the tag, does not indicate an OID, then OpenSSL was not
// used correctly.
CHECK_EQ(encoded_oid.get()[0], kDerOIDTag);
// Skip the tag byte.
std::string out(reinterpret_cast<char*>(encoded_oid.get() + 1), encoded_length - 1);
return std::move(out);
}
std::string OID::ToString() const {
if (oid_ == nullptr) {
return "";
}
char output_buffer[kTextOIDMaxSize];
int encoded_length = i2t_ASN1_OBJECT(output_buffer, kTextOIDMaxSize, oid_);
return std::string(output_buffer, encoded_length);
}
// static
util::StatusOr<OID> OID::FromString(const std::string& oid_string) {
ASN1_OBJECT *oid = OBJ_txt2obj(oid_string.c_str(), 0);
if (oid == nullptr) {
return Status(util::error::INVALID_ARGUMENT,
std::string("Bad OID: ") + oid_string + " "
+ util::DumpOpenSSLErrorStack());
}
return std::move(OID(oid));
}
// static
util::StatusOr<OID> OID::FromTagMissingDER(
const std::string& missing_tag_oid_der) {
std::string oid_der = std::string(1, kDerOIDTag) + missing_tag_oid_der;
const unsigned char* data_ptr =
reinterpret_cast<const unsigned char*>(oid_der.data());
ASN1_OBJECT *oid = d2i_ASN1_OBJECT(NULL, &data_ptr, oid_der.size());
if (oid == nullptr) {
return Status(util::error::INVALID_ARGUMENT,
std::string("Bad DER in OID: ") +
util::DumpOpenSSLErrorStack());
}
return std::move(OID(oid));
}
} // namespace rfc6962_bis
|