|  | // Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | // you may not use this file except in compliance with the License. | 
|  | // You may obtain a copy of the License at | 
|  | // | 
|  | //     https://www.apache.org/licenses/LICENSE-2.0 | 
|  | // | 
|  | // Unless required by applicable law or agreed to in writing, software | 
|  | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | // See the License for the specific language governing permissions and | 
|  | // limitations under the License. | 
|  |  | 
|  | #include <ctype.h> | 
|  | #include <limits.h> | 
|  | #include <string.h> | 
|  |  | 
|  | #include <utility> | 
|  |  | 
|  | #include <openssl/asn1.h> | 
|  | #include <openssl/asn1t.h> | 
|  | #include <openssl/buf.h> | 
|  | #include <openssl/err.h> | 
|  | #include <openssl/mem.h> | 
|  | #include <openssl/obj.h> | 
|  | #include <openssl/stack.h> | 
|  | #include <openssl/x509.h> | 
|  |  | 
|  | #include "../asn1/internal.h" | 
|  | #include "../bytestring/internal.h" | 
|  | #include "../internal.h" | 
|  | #include "../mem_internal.h" | 
|  | #include "internal.h" | 
|  |  | 
|  |  | 
|  | // X509_NAME_MAX is the length of the maximum encoded |X509_NAME| we accept. | 
|  | #define X509_NAME_MAX (1024 * 1024) | 
|  |  | 
|  | static int asn1_marshal_string_canon(CBB *cbb, const ASN1_STRING *in); | 
|  |  | 
|  | X509_NAME_ENTRY *X509_NAME_ENTRY_new(void) { | 
|  | bssl::UniquePtr<X509_NAME_ENTRY> ret = bssl::MakeUnique<X509_NAME_ENTRY>(); | 
|  | if (ret == nullptr) { | 
|  | return nullptr; | 
|  | } | 
|  | ret->object = const_cast<ASN1_OBJECT *>(OBJ_get_undef()); | 
|  | asn1_string_init(&ret->value, -1); | 
|  | ret->set = 0; | 
|  | return ret.release(); | 
|  | } | 
|  |  | 
|  | void X509_NAME_ENTRY_free(X509_NAME_ENTRY *entry) { | 
|  | if (entry != nullptr) { | 
|  | ASN1_OBJECT_free(entry->object); | 
|  | asn1_string_cleanup(&entry->value); | 
|  | OPENSSL_free(entry); | 
|  | } | 
|  | } | 
|  |  | 
|  | static int x509_parse_name_entry(CBS *cbs, X509_NAME_ENTRY *out) { | 
|  | CBS seq; | 
|  | if (!CBS_get_asn1(cbs, &seq, CBS_ASN1_SEQUENCE)) { | 
|  | OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); | 
|  | return 0; | 
|  | } | 
|  | ASN1_OBJECT_free(out->object); | 
|  | out->object = asn1_parse_object(&seq, /*tag=*/0); | 
|  | if (out->object == nullptr ||                        // | 
|  | !asn1_parse_any_as_string(&seq, &out->value) ||  // | 
|  | CBS_len(&seq) != 0) { | 
|  | OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); | 
|  | return 0; | 
|  | } | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | static int x509_marshal_name_entry(CBB *cbb, const X509_NAME_ENTRY *entry, | 
|  | int canonicalize) { | 
|  | CBB seq; | 
|  | if (!CBB_add_asn1(cbb, &seq, CBS_ASN1_SEQUENCE) || | 
|  | !asn1_marshal_object(&seq, entry->object, /*tag=*/0)) { | 
|  | return 0; | 
|  | } | 
|  | int ok = canonicalize ? asn1_marshal_string_canon(&seq, &entry->value) | 
|  | : asn1_marshal_any_string(&seq, &entry->value); | 
|  | if (!ok) { | 
|  | return 0; | 
|  | } | 
|  | return CBB_flush(cbb); | 
|  | } | 
|  |  | 
|  | static int i2d_x509_name_entry(const X509_NAME_ENTRY *entry, uint8_t **out) { | 
|  | return bssl::I2DFromCBB(/*initial_capacity=*/16, out, [&](CBB *cbb) -> bool { | 
|  | return x509_marshal_name_entry(cbb, entry, /*canonicalize=*/0); | 
|  | }); | 
|  | } | 
|  |  | 
|  | IMPLEMENT_EXTERN_ASN1_SIMPLE(X509_NAME_ENTRY, X509_NAME_ENTRY_new, | 
|  | X509_NAME_ENTRY_free, CBS_ASN1_SEQUENCE, | 
|  | x509_parse_name_entry, i2d_x509_name_entry) | 
|  |  | 
|  | X509_NAME_ENTRY *X509_NAME_ENTRY_dup(const X509_NAME_ENTRY *entry) { | 
|  | bssl::ScopedCBB cbb; | 
|  | if (!CBB_init(cbb.get(), 16) || | 
|  | !x509_marshal_name_entry(cbb.get(), entry, /*canonicalize=*/0)) { | 
|  | return nullptr; | 
|  | } | 
|  | CBS cbs; | 
|  | CBS_init(&cbs, CBB_data(cbb.get()), CBB_len(cbb.get())); | 
|  | bssl::UniquePtr<X509_NAME_ENTRY> copy(X509_NAME_ENTRY_new()); | 
|  | if (copy == nullptr || !x509_parse_name_entry(&cbs, copy.get())) { | 
|  | return nullptr; | 
|  | } | 
|  | return copy.release(); | 
|  | } | 
|  |  | 
|  | static void x509_name_cache_free(X509_NAME_CACHE *cache) { | 
|  | if (cache != nullptr) { | 
|  | OPENSSL_free(cache->canon); | 
|  | OPENSSL_free(cache->der); | 
|  | OPENSSL_free(cache); | 
|  | } | 
|  | } | 
|  |  | 
|  | void x509_name_init(X509_NAME *name) { | 
|  | OPENSSL_memset(name, 0, sizeof(X509_NAME)); | 
|  | } | 
|  |  | 
|  | void x509_name_cleanup(X509_NAME *name) { | 
|  | sk_X509_NAME_ENTRY_pop_free(name->entries, X509_NAME_ENTRY_free); | 
|  | x509_name_cache_free(name->cache.exchange(nullptr)); | 
|  | } | 
|  |  | 
|  | X509_NAME *X509_NAME_new(void) { | 
|  | return static_cast<X509_NAME *>(OPENSSL_zalloc(sizeof(X509_NAME))); | 
|  | } | 
|  |  | 
|  | void X509_NAME_free(X509_NAME *name) { | 
|  | if (name != nullptr) { | 
|  | x509_name_cleanup(name); | 
|  | OPENSSL_free(name); | 
|  | } | 
|  | } | 
|  |  | 
|  | int x509_parse_name(CBS *cbs, X509_NAME *out) { | 
|  | // Reset the old state. | 
|  | x509_name_cleanup(out); | 
|  | x509_name_init(out); | 
|  |  | 
|  | out->entries = sk_X509_NAME_ENTRY_new_null(); | 
|  | if (out->entries == nullptr) { | 
|  | return 0; | 
|  | } | 
|  | CBS seq, rdn; | 
|  | if (!CBS_get_asn1(cbs, &seq, CBS_ASN1_SEQUENCE) || | 
|  | // Bound the size of an X509_NAME we are willing to parse. | 
|  | CBS_len(&seq) > X509_NAME_MAX) { | 
|  | OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); | 
|  | return 0; | 
|  | } | 
|  | static_assert(X509_NAME_MAX <= INT_MAX, "set may overflow"); | 
|  | for (int set = 0; CBS_len(&seq) > 0; set++) { | 
|  | if (!CBS_get_asn1(&seq, &rdn, CBS_ASN1_SET) ||  // | 
|  | CBS_len(&rdn) == 0) { | 
|  | OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); | 
|  | return 0; | 
|  | } | 
|  | while (CBS_len(&rdn) != 0) { | 
|  | bssl::UniquePtr<X509_NAME_ENTRY> entry(X509_NAME_ENTRY_new()); | 
|  | if (entry == nullptr || !x509_parse_name_entry(&rdn, entry.get())) { | 
|  | return 0; | 
|  | } | 
|  | entry->set = set; | 
|  | if (!bssl::PushToStack(out->entries, std::move(entry))) { | 
|  | return 0; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // While we are single-threaded, also fill in the cached state. | 
|  | return x509_name_get_cache(out) != nullptr; | 
|  | } | 
|  |  | 
|  | static int x509_marshal_name_entries(CBB *out, const X509_NAME *name, | 
|  | int canonicalize) { | 
|  | if (sk_X509_NAME_ENTRY_num(name->entries) == 0) { | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | // Bootstrap the first RDN. | 
|  | int set = sk_X509_NAME_ENTRY_value(name->entries, 0)->set; | 
|  | CBB rdn; | 
|  | if (!CBB_add_asn1(out, &rdn, CBS_ASN1_SET)) { | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | for (const X509_NAME_ENTRY *entry : name->entries) { | 
|  | if (entry->set != set) { | 
|  | // Flush the previous RDN and start a new one. | 
|  | if (!CBB_flush_asn1_set_of(&rdn) || | 
|  | !CBB_add_asn1(out, &rdn, CBS_ASN1_SET)) { | 
|  | return 0; | 
|  | } | 
|  | set = entry->set; | 
|  | } | 
|  | if (!x509_marshal_name_entry(&rdn, entry, canonicalize)) { | 
|  | return 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | return CBB_flush_asn1_set_of(&rdn) && CBB_flush(out); | 
|  | } | 
|  |  | 
|  | const X509_NAME_CACHE *x509_name_get_cache(const X509_NAME *name) { | 
|  | const X509_NAME_CACHE *cache = name->cache.load(); | 
|  | if (cache != nullptr) { | 
|  | return cache; | 
|  | } | 
|  |  | 
|  | X509_NAME_CACHE *new_cache = | 
|  | static_cast<X509_NAME_CACHE *>(OPENSSL_zalloc(sizeof(X509_NAME_CACHE))); | 
|  | // Cache the DER encoding, including the outer TLV. | 
|  | bssl::ScopedCBB cbb; | 
|  | CBB seq; | 
|  | if (!CBB_init(cbb.get(), 16) || | 
|  | !CBB_add_asn1(cbb.get(), &seq, CBS_ASN1_SEQUENCE) || | 
|  | !x509_marshal_name_entries(&seq, name, /*canonicalize=*/0) || | 
|  | !CBB_finish(cbb.get(), &new_cache->der, &new_cache->der_len)) { | 
|  | x509_name_cache_free(new_cache); | 
|  | return 0; | 
|  | } | 
|  | // Cache the canonicalized form, without the outer TLV. | 
|  | if (!CBB_init(cbb.get(), 16) || | 
|  | !x509_marshal_name_entries(cbb.get(), name, /*canonicalize=*/1) || | 
|  | !CBB_finish(cbb.get(), &new_cache->canon, &new_cache->canon_len)) { | 
|  | x509_name_cache_free(new_cache); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | X509_NAME_CACHE *expected = nullptr; | 
|  | if (name->cache.compare_exchange_strong(expected, new_cache)) { | 
|  | // We won the race. |name| now owns |new_cache|. | 
|  | return new_cache; | 
|  | } | 
|  |  | 
|  | // Some other thread installed a (presumably identical) cache. Release the one | 
|  | // we made and return the winning one. | 
|  | assert(expected != nullptr); | 
|  | x509_name_cache_free(new_cache); | 
|  | return expected; | 
|  | } | 
|  |  | 
|  | void x509_name_invalidate_cache(X509_NAME *name) { | 
|  | x509_name_cache_free(name->cache.exchange(nullptr)); | 
|  | } | 
|  |  | 
|  | int x509_marshal_name(CBB *out, const X509_NAME *in) { | 
|  | const X509_NAME_CACHE *cache = x509_name_get_cache(in); | 
|  | if (cache == nullptr) { | 
|  | return 0; | 
|  | } | 
|  | return CBB_add_bytes(out, cache->der, cache->der_len); | 
|  | } | 
|  |  | 
|  | X509_NAME *X509_NAME_dup(const X509_NAME *name) { | 
|  | const X509_NAME_CACHE *cache = x509_name_get_cache(name); | 
|  | if (cache == nullptr) { | 
|  | return nullptr; | 
|  | } | 
|  | CBS cbs; | 
|  | CBS_init(&cbs, cache->der, cache->der_len); | 
|  | bssl::UniquePtr<X509_NAME> copy(X509_NAME_new()); | 
|  | if (copy == nullptr || !x509_parse_name(&cbs, copy.get())) { | 
|  | return nullptr; | 
|  | } | 
|  | assert(CBS_len(&cbs) == 0); | 
|  | return copy.release(); | 
|  | } | 
|  |  | 
|  | X509_NAME *d2i_X509_NAME(X509_NAME **out, const uint8_t **inp, long len) { | 
|  | return bssl::D2IFromCBS( | 
|  | out, inp, len, [](CBS *cbs) -> bssl::UniquePtr<X509_NAME> { | 
|  | bssl::UniquePtr<X509_NAME> name(X509_NAME_new()); | 
|  | if (name == nullptr || !x509_parse_name(cbs, name.get())) { | 
|  | return nullptr; | 
|  | } | 
|  | return name; | 
|  | }); | 
|  | } | 
|  |  | 
|  | int i2d_X509_NAME(const X509_NAME *in, uint8_t **outp) { | 
|  | const X509_NAME_CACHE *cache = x509_name_get_cache(in); | 
|  | if (cache == nullptr) { | 
|  | return -1; | 
|  | } | 
|  | if (cache->der_len > INT_MAX) { | 
|  | OPENSSL_PUT_ERROR(X509, ERR_R_OVERFLOW); | 
|  | return -1; | 
|  | } | 
|  | int len = static_cast<int>(cache->der_len); | 
|  | if (outp == nullptr) { | 
|  | return len; | 
|  | } | 
|  | if (*outp == nullptr) { | 
|  | *outp = static_cast<uint8_t*>(OPENSSL_memdup(cache->der, cache->der_len)); | 
|  | return *outp != nullptr ? len : -1; | 
|  | } | 
|  | OPENSSL_memcpy(*outp, cache->der, cache->der_len); | 
|  | *outp += cache->der_len; | 
|  | return len; | 
|  | } | 
|  |  | 
|  | IMPLEMENT_EXTERN_ASN1_SIMPLE(X509_NAME, X509_NAME_new, X509_NAME_free, | 
|  | CBS_ASN1_SEQUENCE, x509_parse_name, i2d_X509_NAME) | 
|  |  | 
|  | static int asn1_marshal_string_canon(CBB *cbb, const ASN1_STRING *in) { | 
|  | int (*decode_func)(CBS *, uint32_t *); | 
|  | int error; | 
|  | switch (in->type) { | 
|  | case V_ASN1_UTF8STRING: | 
|  | decode_func = CBS_get_utf8; | 
|  | error = ASN1_R_INVALID_UTF8STRING; | 
|  | break; | 
|  | case V_ASN1_BMPSTRING: | 
|  | decode_func = CBS_get_ucs2_be; | 
|  | error = ASN1_R_INVALID_BMPSTRING; | 
|  | break; | 
|  | case V_ASN1_UNIVERSALSTRING: | 
|  | decode_func = CBS_get_utf32_be; | 
|  | error = ASN1_R_INVALID_UNIVERSALSTRING; | 
|  | break; | 
|  | case V_ASN1_PRINTABLESTRING: | 
|  | case V_ASN1_T61STRING: | 
|  | case V_ASN1_IA5STRING: | 
|  | case V_ASN1_VISIBLESTRING: | 
|  | decode_func = CBS_get_latin1; | 
|  | error = ERR_R_INTERNAL_ERROR;  // Latin-1 inputs are never invalid. | 
|  | break; | 
|  | default: | 
|  | // Other string types are not canonicalized. | 
|  | return asn1_marshal_any_string(cbb, in); | 
|  | } | 
|  |  | 
|  | CBB child; | 
|  | if (!CBB_add_asn1(cbb, &child, CBS_ASN1_UTF8STRING)) { | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | bool empty = true; | 
|  | bool in_whitespace = false; | 
|  | CBS cbs; | 
|  | CBS_init(&cbs, in->data, in->length); | 
|  | while (CBS_len(&cbs) != 0) { | 
|  | uint32_t c; | 
|  | if (!decode_func(&cbs, &c)) { | 
|  | OPENSSL_PUT_ERROR(ASN1, error); | 
|  | return 0; | 
|  | } | 
|  | if (OPENSSL_isspace(c)) { | 
|  | if (empty) { | 
|  | continue;  // Trim leading whitespace. | 
|  | } | 
|  | in_whitespace = true; | 
|  | } else { | 
|  | if (in_whitespace) { | 
|  | // Collapse the previous run of whitespace into one space. | 
|  | if (!CBB_add_u8(&child, ' ')) { | 
|  | return 0; | 
|  | } | 
|  | } | 
|  | in_whitespace = false; | 
|  | // Lowecase ASCII codepoints. | 
|  | if (c <= 0x7f) { | 
|  | c = OPENSSL_tolower(c); | 
|  | } | 
|  | if (!CBB_add_utf8(&child, c)) { | 
|  | return 0; | 
|  | } | 
|  | empty = false; | 
|  | } | 
|  | } | 
|  |  | 
|  | return CBB_flush(cbb); | 
|  | } | 
|  |  | 
|  | int X509_NAME_set(X509_NAME **xn, const X509_NAME *name) { | 
|  | bssl::UniquePtr<X509_NAME> copy(X509_NAME_dup(name)); | 
|  | if (copy == nullptr) { | 
|  | return 0; | 
|  | } | 
|  | X509_NAME_free(*xn); | 
|  | *xn = copy.release(); | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne) { return ne->set; } | 
|  |  | 
|  | int X509_NAME_get0_der(const X509_NAME *nm, const unsigned char **out_der, | 
|  | size_t *out_der_len) { | 
|  | const X509_NAME_CACHE *cache = x509_name_get_cache(nm); | 
|  | if (cache == nullptr) { | 
|  | return 0; | 
|  | } | 
|  | if (out_der != nullptr) { | 
|  | *out_der = cache->der; | 
|  | } | 
|  | if (out_der_len != nullptr) { | 
|  | *out_der_len = cache->der_len; | 
|  | } | 
|  | return 1; | 
|  | } |