tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

CTUtils.h (3646B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef CTUtils_h
      8 #define CTUtils_h
      9 
     10 #include <memory>
     11 
     12 #include "cryptohi.h"
     13 #include "keyhi.h"
     14 #include "keythi.h"
     15 #include "pk11pub.h"
     16 #include "mozpkix/Input.h"
     17 #include "mozpkix/Result.h"
     18 
     19 #define MOZILLA_CT_ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0]))
     20 
     21 struct DeleteHelper {
     22  void operator()(CERTSubjectPublicKeyInfo* value) {
     23    SECKEY_DestroySubjectPublicKeyInfo(value);
     24  }
     25  void operator()(PK11Context* value) { PK11_DestroyContext(value, true); }
     26  void operator()(PK11SlotInfo* value) { PK11_FreeSlot(value); }
     27  void operator()(SECKEYPublicKey* value) { SECKEY_DestroyPublicKey(value); }
     28  void operator()(SECItem* value) { SECITEM_FreeItem(value, true); }
     29 };
     30 
     31 template <class T>
     32 struct MaybeDeleteHelper {
     33  void operator()(T* ptr) {
     34    if (ptr) {
     35      DeleteHelper del;
     36      del(ptr);
     37    }
     38  }
     39 };
     40 
     41 typedef std::unique_ptr<CERTSubjectPublicKeyInfo,
     42                        MaybeDeleteHelper<CERTSubjectPublicKeyInfo>>
     43    UniqueCERTSubjectPublicKeyInfo;
     44 typedef std::unique_ptr<PK11Context, MaybeDeleteHelper<PK11Context>>
     45    UniquePK11Context;
     46 typedef std::unique_ptr<PK11SlotInfo, MaybeDeleteHelper<PK11SlotInfo>>
     47    UniquePK11SlotInfo;
     48 typedef std::unique_ptr<SECKEYPublicKey, MaybeDeleteHelper<SECKEYPublicKey>>
     49    UniqueSECKEYPublicKey;
     50 typedef std::unique_ptr<SECItem, MaybeDeleteHelper<SECItem>> UniqueSECItem;
     51 
     52 namespace mozilla {
     53 namespace ct {
     54 
     55 // Reads a TLS-encoded variable length unsigned integer from |in|.
     56 // The integer is expected to be in big-endian order, which is used by TLS.
     57 // Note: does not check if the output parameter overflows while reading.
     58 // |length| indicates the size (in bytes) of the serialized integer.
     59 inline static pkix::Result UncheckedReadUint(size_t length, pkix::Reader& in,
     60                                             uint64_t& out) {
     61  uint64_t result = 0;
     62  for (size_t i = 0; i < length; ++i) {
     63    uint8_t value;
     64    pkix::Result rv = in.Read(value);
     65    if (rv != pkix::Success) {
     66      return rv;
     67    }
     68    result = (result << 8) | value;
     69  }
     70  out = result;
     71  return pkix::Success;
     72 }
     73 
     74 // Performs overflow sanity checks and calls UncheckedReadUint.
     75 template <size_t length, typename T>
     76 pkix::Result ReadUint(pkix::Reader& in, T& out) {
     77  uint64_t value;
     78  static_assert(std::is_unsigned<T>::value, "T must be unsigned");
     79  static_assert(length <= 8, "At most 8 byte integers can be read");
     80  static_assert(sizeof(T) >= length, "T must be able to hold <length> bytes");
     81  pkix::Result rv = UncheckedReadUint(length, in, value);
     82  if (rv != pkix::Success) {
     83    return rv;
     84  }
     85  out = static_cast<T>(value);
     86  return pkix::Success;
     87 }
     88 
     89 // Reads |length| bytes from |in|.
     90 static inline pkix::Result ReadFixedBytes(size_t length, pkix::Reader& in,
     91                                          pkix::Input& out) {
     92  return in.Skip(length, out);
     93 }
     94 
     95 // Reads a length-prefixed variable amount of bytes from |in|, updating |out|
     96 // on success. |prefixLength| indicates the number of bytes needed to represent
     97 // the length.
     98 template <size_t prefixLength>
     99 pkix::Result ReadVariableBytes(pkix::Reader& in, pkix::Input& out) {
    100  size_t length;
    101  pkix::Result rv = ReadUint<prefixLength>(in, length);
    102  if (rv != pkix::Success) {
    103    return rv;
    104  }
    105  return ReadFixedBytes(length, in, out);
    106 }
    107 
    108 }  // namespace ct
    109 }  // namespace mozilla
    110 
    111 #endif  // CTUtils_h