File: serializer_v2.cc

package info (click to toggle)
golang-github-google-certificate-transparency 0.0~git20160709.0.0f6e3d1~ds1-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, buster
  • size: 5,676 kB
  • sloc: cpp: 35,278; python: 11,838; java: 1,911; sh: 1,885; makefile: 950; xml: 520; ansic: 225
file content (117 lines) | stat: -rw-r--r-- 3,271 bytes parent folder | download
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