summaryrefslogtreecommitdiffstats
path: root/src/liblzma/check/check.h
blob: 8ae95d59019f7b3a59d6a71be188180fc9de79a0 (plain)
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
///////////////////////////////////////////////////////////////////////////////
//
/// \file       check.h
/// \brief      Internal API to different integrity check functions
//
//  Author:     Lasse Collin
//
//  This file has been put into the public domain.
//  You can do whatever you want with this file.
//
///////////////////////////////////////////////////////////////////////////////

#ifndef LZMA_CHECK_H
#define LZMA_CHECK_H

#include "common.h"

// If the function for external SHA-256 is missing, use the internal SHA-256
// code. Due to how configure works, these defines can only get defined when
// both a usable header and a type have already been found.
#if !(defined(HAVE_CC_SHA256_INIT) \
		|| defined(HAVE_SHA256_INIT) \
		|| defined(HAVE_SHA256INIT))
#	define HAVE_INTERNAL_SHA256 1
#endif

#if defined(HAVE_INTERNAL_SHA256)
// Nothing
#elif defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H)
#	include <CommonCrypto/CommonDigest.h>
#elif defined(HAVE_SHA256_H)
#	include <sys/types.h>
#	include <sha256.h>
#elif defined(HAVE_SHA2_H)
#	include <sys/types.h>
#	include <sha2.h>
#endif

#if defined(HAVE_INTERNAL_SHA256)
/// State for the internal SHA-256 implementation
typedef struct {
	/// Internal state
	uint32_t state[8];

	/// Size of the message excluding padding
	uint64_t size;
} lzma_sha256_state;
#elif defined(HAVE_CC_SHA256_CTX)
typedef CC_SHA256_CTX lzma_sha256_state;
#elif defined(HAVE_SHA256_CTX)
typedef SHA256_CTX lzma_sha256_state;
#elif defined(HAVE_SHA2_CTX)
typedef SHA2_CTX lzma_sha256_state;
#endif

#if defined(HAVE_INTERNAL_SHA256)
// Nothing
#elif defined(HAVE_CC_SHA256_INIT)
#	define LZMA_SHA256FUNC(x) CC_SHA256_ ## x
#elif defined(HAVE_SHA256_INIT)
#	define LZMA_SHA256FUNC(x) SHA256_ ## x
#elif defined(HAVE_SHA256INIT)
#	define LZMA_SHA256FUNC(x) SHA256 ## x
#endif

// Index hashing needs the best possible hash function (preferably
// a cryptographic hash) for maximum reliability.
#if defined(HAVE_CHECK_SHA256)
#	define LZMA_CHECK_BEST LZMA_CHECK_SHA256
#elif defined(HAVE_CHECK_CRC64)
#	define LZMA_CHECK_BEST LZMA_CHECK_CRC64
#else
#	define LZMA_CHECK_BEST LZMA_CHECK_CRC32
#endif


/// \brief      Structure to hold internal state of the check being calculated
///
/// \note       This is not in the public API because this structure may
///             change in future if new integrity check algorithms are added.
typedef struct {
	/// Buffer to hold the final result and a temporary buffer for SHA256.
	union {
		uint8_t u8[64];
		uint32_t u32[16];
		uint64_t u64[8];
	} buffer;

	/// Check-specific data
	union {
		uint32_t crc32;
		uint64_t crc64;
		lzma_sha256_state sha256;
	} state;

} lzma_check_state;


/// lzma_crc32_table[0] is needed by LZ encoder so we need to keep
/// the array two-dimensional.
#ifdef HAVE_SMALL
lzma_attr_visibility_hidden
extern uint32_t lzma_crc32_table[1][256];

extern void lzma_crc32_init(void);

#else

lzma_attr_visibility_hidden
extern const uint32_t lzma_crc32_table[8][256];

lzma_attr_visibility_hidden
extern const uint64_t lzma_crc64_table[4][256];
#endif


/// \brief      Initialize *check depending on type
extern void lzma_check_init(lzma_check_state *check, lzma_check type);

/// Update the check state
extern void lzma_check_update(lzma_check_state *check, lzma_check type,
		const uint8_t *buf, size_t size);

/// Finish the check calculation and store the result to check->buffer.u8.
extern void lzma_check_finish(lzma_check_state *check, lzma_check type);


#ifndef LZMA_SHA256FUNC

/// Prepare SHA-256 state for new input.
extern void lzma_sha256_init(lzma_check_state *check);

/// Update the SHA-256 hash state
extern void lzma_sha256_update(
		const uint8_t *buf, size_t size, lzma_check_state *check);

/// Finish the SHA-256 calculation and store the result to check->buffer.u8.
extern void lzma_sha256_finish(lzma_check_state *check);


#else

static inline void
lzma_sha256_init(lzma_check_state *check)
{
	LZMA_SHA256FUNC(Init)(&check->state.sha256);
}


static inline void
lzma_sha256_update(const uint8_t *buf, size_t size, lzma_check_state *check)
{
#if defined(HAVE_CC_SHA256_INIT) && SIZE_MAX > UINT32_MAX
	// Darwin's CC_SHA256_Update takes uint32_t as the buffer size,
	// so use a loop to support size_t.
	while (size > UINT32_MAX) {
		LZMA_SHA256FUNC(Update)(&check->state.sha256, buf, UINT32_MAX);
		buf += UINT32_MAX;
		size -= UINT32_MAX;
	}
#endif

	LZMA_SHA256FUNC(Update)(&check->state.sha256, buf, size);
}


static inline void
lzma_sha256_finish(lzma_check_state *check)
{
	LZMA_SHA256FUNC(Final)(check->buffer.u8, &check->state.sha256);
}

#endif

#endif