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