imagehdr.h 8.91 KB
Newer Older
Mike Hibler's avatar
Mike Hibler committed
1
/*
2
 * Copyright (c) 2000-2015 University of Utah and the Flux Group.
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 * 
 * {{{EMULAB-LICENSE
 * 
 * This file is part of the Emulab network testbed software.
 * 
 * This file is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or (at
 * your option) any later version.
 * 
 * This file is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public
 * License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this file.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * }}}
Mike Hibler's avatar
Mike Hibler committed
22
 */
Mike Hibler's avatar
Mike Hibler committed
23
24
#ifndef _IMAGEHDR_H_
#define _IMAGEHDR_H_
25

Mike Hibler's avatar
Mike Hibler committed
26
#include <inttypes.h>
27
28

/*
29
 * Magic number when image is compressed
Mike Hibler's avatar
all:    
Mike Hibler committed
30
31
32
33
 *
 * This magic number has been commandeered for use as a version number.
 * None of this wimpy start at version 1 stuff either, our first version
 * is 1,768,515,945!
Mike Hibler's avatar
Mike Hibler committed
34
 *
35
 *	V2 introduced the first and last sector fields as well
36
 *	as basic relocations. Also dropped maintenance of blocktotal.
Mike Hibler's avatar
Mike Hibler committed
37
 *
38
39
40
41
42
43
44
 *	V3 introduced LILO relocations for Linux partition images.
 *	Since an older imageunzip would still work, but potentially
 *	lay down an incorrect images, I bumped the version number.
 *	Note that there is no change to the header structure however.
 *
 *	V4 of the block descriptor adds support for integrety protection
 *	and encryption.
45
 */
46
47
48
49
50
#define COMPRESSED_MAGIC_BASE		0x69696969
#define COMPRESSED_V1			(COMPRESSED_MAGIC_BASE+0)
#define COMPRESSED_V2			(COMPRESSED_MAGIC_BASE+1)
#define COMPRESSED_V3			(COMPRESSED_MAGIC_BASE+2)
#define COMPRESSED_V4			(COMPRESSED_MAGIC_BASE+3)
Mike Hibler's avatar
all:    
Mike Hibler committed
51

52
#define COMPRESSED_MAGIC_CURRENT	COMPRESSED_V4
53
54

/*
55
 * Each compressed block of the file has this little header on it.
56
 * Since each block is independently compressed, we need to know
57
58
 * its internal size (it will probably be shorter than 1MB) since we
 * have to know exactly how much to give the inflator.
59
 */
Mike Hibler's avatar
all:    
Mike Hibler committed
60
struct blockhdr_V1 {
61
62
	uint32_t	magic;		/* magic/version */
	uint32_t	size;		/* Size of compressed part */
63
64
	int32_t		blockindex;	/* which block we are */
	int32_t		blocktotal;	/* V1: total number of blocks */
65
66
	int32_t		regionsize;	/* sizeof header + regions */
	int32_t		regioncount;	/* number of regions */
Mike Hibler's avatar
all:    
Mike Hibler committed
67
68
69
70
71
72
73
74
75
76
77
};

/*
 * Version 2 of the block descriptor adds a first and last sector value.
 * These are used to describe free space which is adjacent to the allocated
 * sector data.  This is needed in order to properly zero all free space.
 * Previously free space between regions that wound up in different
 * blocks could only be handled if the blocks were presented consecutively,
 * this was not the case in frisbee.
 */
struct blockhdr_V2 {
78
79
	uint32_t	magic;		/* magic/version */
	uint32_t	size;		/* Size of compressed part */
80
81
	int32_t		blockindex;	/* which block we are */
	int32_t		blocktotal;	/* V1: total number of blocks */
82
83
84
85
	int32_t		regionsize;	/* sizeof header + regions */
	int32_t		regioncount;	/* number of regions */
	/* V2 follows */
	uint32_t	firstsect;	/* first sector described by block */
86
	uint32_t	lastsect;	/* first sector past block */
87
	int32_t		reloccount;	/* number of reloc entries */
Mike Hibler's avatar
all:    
Mike Hibler committed
88
89
};

90
#define UUID_LENGTH		16
91

92
/*
93
 * Authentication/integrity/encryption constants for V4.
94
 */
95
96
97
#define ENC_MAX_KEYLEN		32	/* XXX same as EVP_MAX_KEY_LENGTH */
#define CSUM_MAX_LEN		64
#define SIG_MAX_KEYLEN		256	/* must be > CSUM_MAX_LEN+41 */
98
99

/*
100
101
102
 * Version 4 of the block descriptor adds support for authentication,
 * integrety protection and encryption.
 *
103
104
105
 * An optionally-signed checksum (hash) of each header+chunk is stored in
 * the header (checksum) along with the hash algorithm used (csum_type).
 * The pubkey used to sign the hash is transfered out-of-band.
106
 *
107
108
 * To ensure that all valid signed chunks are part of the same image,
 * a unique identifier is stored in the header (imageid) of each chunk
109
110
111
112
 * associated with the same image.
 *
 * Optionally, the contents of each chunk (but not the header) is encrypted
 * using the indicated cipher (enc_cipher) and initialization vector (enc_iv).
113
 */
114
115
116
struct blockhdr_V4 {
	uint32_t	magic;		/* magic/version */
	uint32_t	size;		/* Size of compressed part */
117
118
	int32_t		blockindex;	/* which block we are */
	int32_t		blocktotal;	/* V1: total number of blocks */
119
120
121
122
	int32_t		regionsize;	/* sizeof header + regions */
	int32_t		regioncount;	/* number of regions */
	/* V2 follows */
	uint32_t	firstsect;	/* first sector described by block */
123
	uint32_t	lastsect;	/* first sector past block */
124
125
	int32_t		reloccount;	/* number of reloc entries */
	/* V4 follows */
126
127
	uint16_t	enc_cipher;	/* cipher was used to encrypt */
	uint16_t	csum_type;	/* checksum algortihm used */
128
	uint8_t		enc_iv[ENC_MAX_KEYLEN];
129
130
					/* Initialization vector */
	unsigned char	checksum[SIG_MAX_KEYLEN];
131
					/* (Signed) checksum */
132
133
134
	unsigned char	imageid[UUID_LENGTH];
					/* Unique ID for the whole image */
};
135

Mike Hibler's avatar
Mike Hibler committed
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
/*
 * Coming soon in V5:
 *
 * 64-bit support.
 *   Grow blockindex, firstsect, lastsect, region descriptors, may need to
 *   grow DEFAULTREGIONSIZE to accomodate the doubling in size of regions.
 *
 * Flag field?
 *   For example, to indicate a delta image. Would probably take over the
 *   otherwise unused blocktotal field.
 *
 * Sectorsize field?
 *   To make explicit the units of sector fields; e.g., 512 vs 4096.
 *
 * Chunksize field?
 *   To support different chunksizes.
 *
 * Mandate little-endian on-disk data.
 *   Code changes only to use appropriate endian macros when reading/writing
 *   data. No data struct changes needed.
 *
 * Support for SHA256 and SHA512 checksums.
 *   Just some constants here, as checksum is already 64 bytes.
 *   Will need to grow the imagehash header to accomodate these checksums
 *   for signatures, but that is separately versioned.
 */

163
/*
164
 * Checksum types supported
165
 */
166
167
168
#define CSUM_NONE		0  /* must be zero */
#define CSUM_SHA1		1  /* SHA1: default */
#define CSUM_SHA1_LEN		20
169

170
171
172
173
174
175
/* type field */
#define CSUM_TYPE		0xFF

/* flags */
#define CSUM_SIGNED		0x8000	/* checksum is signed */

176
177
178
/*
 * Ciphers supported
 */
179
180
#define ENC_NONE		0  /* must be zero */
#define ENC_BLOWFISH_CBC	1
181

182
183
184
185
/*
 * Authentication ciphers supported
 */
#define AUTH_RSA		0
186

Mike Hibler's avatar
all:    
Mike Hibler committed
187
188
189
190
191
192
/*
 * Relocation descriptor.
 * Certain data structures like BSD disklabels and LILO boot blocks require
 * absolute block numbers.  This descriptor tells the unzipper what the
 * data structure is and where it is located in the block.
 *
193
 * Relocation descriptors follow the region descriptors in the header area.
Mike Hibler's avatar
all:    
Mike Hibler committed
194
195
 */
struct blockreloc {
196
197
198
199
	uint32_t	type;		/* relocation type (below) */
	uint32_t	sector;		/* sector it applies to */
	uint32_t	sectoff;	/* offset within the sector */
	uint32_t	size;		/* size of data affected */
200
};
201
202
203
204
205
206
207
#define RELOC_NONE		0
#define RELOC_FBSDDISKLABEL	1	/* FreeBSD disklabel */
#define RELOC_OBSDDISKLABEL	2	/* OpenBSD disklabel */
#define RELOC_LILOSADDR		3	/* LILO sector address */
#define RELOC_LILOMAPSECT	4	/* LILO map sector */
#define RELOC_LILOCKSUM		5	/* LILO descriptor block cksum */
#define RELOC_SHORTSECTOR	6	/* indicated sector < sectsize */
Mike Hibler's avatar
all:    
Mike Hibler committed
208
209

/* XXX potential future alternatives to hard-wiring BSD disklabel knowledge */
210
211
212
#define RELOC_ADDPARTOFFSET	100	/* add partition offset to location */
#define RELOC_XOR16CKSUM	101	/* 16-bit XOR checksum */
#define RELOC_CKSUMRANGE	102	/* range of previous checksum */
Mike Hibler's avatar
all:    
Mike Hibler committed
213

214
typedef struct blockhdr_V4 blockhdr_t;
215
216
217
218

/*
 * This little struct defines the pair. Each number is in sectors. An array
 * of these come after the header above, and is padded to a 1K boundry.
219
220
221
 * The region says where to write the next part of the input file, which is
 * how we skip over parts of the disk that do not need to be written
 * (swap, free FS blocks).
222
223
 */
struct region {
224
225
	uint32_t	start;
	uint32_t	size;
226
227
228
};

/*
229
 * Each block has its own region header info.
230
 *
231
232
233
234
235
236
237
238
239
240
 * Since there is no easy way to tell how many regions will fit before
 * we have compressed the region data, we just have to pick a size here.
 * If this area is too small, it is possible that a highly fragmented image
 * will fill this header before filling the data area of a block.  If the
 * region header area is too large, we will almost always fill up the data
 * area before filling the region header.  Since the latter is more likely
 * to be common, we tend to the small-ish side.
 *
 * At 4K with 8 byte region descriptors, we can fix 512 regions into a
 * single chunk.
241
 */
242
#define DEFAULTREGIONSIZE	4096
243

244
245
/*
 * Ah, the frisbee protocol. The new world order is to break up the
246
 * file into fixed chunks, with the region info prepended to each
247
 * chunk so that it can be layed down on disk independently of all the
248
 * chunks in the file. 
249
 */
250
251
252
253
254
255
#define F_BLOCKSIZE		1024
#define F_BLOCKSPERCHUNK	1024

#define CHUNKSIZE		(F_BLOCKSIZE * F_BLOCKSPERCHUNK)
#define CHUNKMAX		(CHUNKSIZE - DEFAULTREGIONSIZE)

Mike Hibler's avatar
all:    
Mike Hibler committed
256
257
258
259

/*
 * Assumed sector (block) size
 */
260
#define SECSIZE			512
261

Mike Hibler's avatar
Mike Hibler committed
262
#endif /* _IMAGEHDR_H_ */