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/. */
16 #include "mozpkix/Input.h"
17 #include "mozpkix/Result.h"
19 #define MOZILLA_CT_ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0]))
22 void operator()(CERTSubjectPublicKeyInfo
* value
) {
23 SECKEY_DestroySubjectPublicKeyInfo(value
);
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); }
32 struct MaybeDeleteHelper
{
33 void operator()(T
* ptr
) {
41 typedef std::unique_ptr
<CERTSubjectPublicKeyInfo
,
42 MaybeDeleteHelper
<CERTSubjectPublicKeyInfo
>>
43 UniqueCERTSubjectPublicKeyInfo
;
44 typedef std::unique_ptr
<PK11Context
, MaybeDeleteHelper
<PK11Context
>>
46 typedef std::unique_ptr
<PK11SlotInfo
, MaybeDeleteHelper
<PK11SlotInfo
>>
48 typedef std::unique_ptr
<SECKEYPublicKey
, MaybeDeleteHelper
<SECKEYPublicKey
>>
49 UniqueSECKEYPublicKey
;
50 typedef std::unique_ptr
<SECItem
, MaybeDeleteHelper
<SECItem
>> UniqueSECItem
;
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
,
62 for (size_t i
= 0; i
< length
; ++i
) {
64 pkix::Result rv
= in
.Read(value
);
65 if (rv
!= pkix::Success
) {
68 result
= (result
<< 8) | value
;
74 // Performs overflow sanity checks and calls UncheckedReadUint.
75 template <size_t length
, typename T
>
76 pkix::Result
ReadUint(pkix::Reader
& in
, T
& out
) {
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
) {
85 out
= static_cast<T
>(value
);
89 // Reads |length| bytes from |in|.
90 static inline pkix::Result
ReadFixedBytes(size_t length
, pkix::Reader
& in
,
92 return in
.Skip(length
, out
);
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
98 template <size_t prefixLength
>
99 pkix::Result
ReadVariableBytes(pkix::Reader
& in
, pkix::Input
& out
) {
101 pkix::Result rv
= ReadUint
<prefixLength
>(in
, length
);
102 if (rv
!= pkix::Success
) {
105 return ReadFixedBytes(length
, in
, out
);
109 } // namespace mozilla