-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsif.go
338 lines (296 loc) · 13.9 KB
/
sif.go
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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
// Copyright (c) 2018-2019, Sylabs Inc. All rights reserved.
// Copyright (c) 2017, SingularityWare, LLC. All rights reserved.
// Copyright (c) 2017, Yannick Cote <[email protected]> All rights reserved.
// This software is licensed under a 3-clause BSD license. Please consult the
// LICENSE file distributed with the sources of this project regarding your
// rights to use or distribute this software.
// Package sif implements data structures and routines to create
// and access SIF files.
// - sif.go contains the data definition the file format.
// - create.go implements the core functionality for the creation of
// of new SIF files.
// - load.go implements the core functionality for the loading of
// existing SIF files.
// - lookup.go mostly implements search/lookup and printing routines
// and access to specific descriptor/data found in SIF container files.
//
// Layout of a SIF file (example):
//
// .================================================.
// | GLOBAL HEADER: Sifheader |
// | - launch: "#!/usr/bin/env..." |
// | - magic: "SIF_MAGIC" |
// | - version: "1" |
// | - arch: "4" |
// | - uuid: b2659d4e-bd50-4ea5-bd17-eec5e54f918e |
// | - ctime: 1504657553 |
// | - mtime: 1504657653 |
// | - ndescr: 3 |
// | - descroff: 120 | --.
// | - descrlen: 432 | |
// | - dataoff: 4096 | |
// | - datalen: 619362 | |
// |------------------------------------------------| <-'
// | DESCR[0]: Sifdeffile |
// | - Sifcommon |
// | - datatype: DATA_DEFFILE |
// | - id: 1 |
// | - groupid: 1 |
// | - link: NONE |
// | - fileoff: 4096 | --.
// | - filelen: 222 | |
// |------------------------------------------------| <-----.
// | DESCR[1]: Sifpartition | | |
// | - Sifcommon | | |
// | - datatype: DATA_PARTITION | | |
// | - id: 2 | | |
// | - groupid: 1 | | |
// | - link: NONE | | |
// | - fileoff: 4318 | ----. |
// | - filelen: 618496 | | | |
// | - fstype: Squashfs | | | |
// | - parttype: System | | | |
// | - content: Linux | | | |
// |------------------------------------------------| | | |
// | DESCR[2]: Sifsignature | | | |
// | - Sifcommon | | | |
// | - datatype: DATA_SIGNATURE | | | |
// | - id: 3 | | | |
// | - groupid: NONE | | | |
// | - link: 2 | ------'
// | - fileoff: 622814 | ------.
// | - filelen: 644 | | | |
// | - hashtype: SHA384 | | | |
// | - entity: @ | | | |
// |------------------------------------------------| <-' | |
// | Definition file data | | |
// | . | | |
// | . | | |
// | . | | |
// |------------------------------------------------| <---' |
// | File system partition image | |
// | . | |
// | . | |
// | . | |
// |------------------------------------------------| <-----'
// | Signed verification data |
// | . |
// | . |
// | . |
// `================================================'
//
package main
import (
"bytes"
"io"
"os"
uuid "github.com/google/uuid"
)
// SIF header constants and quantities.
const (
HdrLaunch = "#!/usr/bin/env run-singularity\n"
HdrMagic = "SIF_MAGIC" // SIF identification
HdrVersion = "01" // SIF SPEC VERSION
HdrArchUnknown = "00" // Undefined/Unsupported arch
HdrArch386 = "01" // 386 (i[3-6]86) arch code
HdrArchAMD64 = "02" // AMD64 arch code
HdrArchARM = "03" // ARM arch code
HdrArchARM64 = "04" // AARCH64 arch code
HdrArchPPC64 = "05" // PowerPC 64 arch code
HdrArchPPC64le = "06" // PowerPC 64 little-endian arch code
HdrArchMIPS = "07" // MIPS arch code
HdrArchMIPSle = "08" // MIPS little-endian arch code
HdrArchMIPS64 = "09" // MIPS64 arch code
HdrArchMIPS64le = "10" // MIPS64 little-endian arch code
HdrArchS390x = "11" // IBM s390x arch code
HdrLaunchLen = 32 // len("#!/usr/bin/env... ")
HdrMagicLen = 10 // len("SIF_MAGIC")
HdrVersionLen = 3 // len("99")
HdrArchLen = 3 // len("99")
DescrNumEntries = 48 // the default total number of available descriptors
DescrGroupMask = 0xf0000000 // groups start at that offset
DescrUnusedGroup = DescrGroupMask // descriptor without a group
DescrDefaultGroup = DescrGroupMask | 1 // first groupid number created
DescrUnusedLink = 0 // descriptor without link to other
DescrEntityLen = 256 // len("Joe Bloe <[email protected]>...")
DescrNameLen = 128 // descriptor name (string identifier)
DescrMaxPrivLen = 384 // size reserved for descriptor specific data
DescrStartOffset = 4096 // where descriptors start after global header
DataStartOffset = 32768 // where data object start after descriptors
)
// Datatype represents the different SIF data object types stored in the image.
type Datatype int32
// List of supported SIF data types.
const (
DataDeffile Datatype = iota + 0x4001 // definition file data object
DataEnvVar // environment variables data object
DataLabels // JSON labels data object
DataPartition // file system data object
DataSignature // signing/verification data object
DataGenericJSON // generic JSON meta-data
DataGeneric // generic / raw data
DataCryptoMessage // cryptographic message data object
)
// Fstype represents the different SIF file system types found in partition data objects.
type Fstype int32
// List of supported file systems.
const (
FsSquash Fstype = iota + 1 // Squashfs file system, RDONLY
FsExt3 // EXT3 file system, RDWR (deprecated)
FsImmuObj // immutable data object archive
FsRaw // raw data
FsEncryptedSquashfs // Encrypted Squashfs file system, RDONLY
)
// Parttype represents the different SIF container partition types (system and data).
type Parttype int32
// List of supported partition types.
const (
PartSystem Parttype = iota + 1 // partition hosts an operating system
PartPrimSys // partition hosts the primary operating system
PartData // partition hosts data only
PartOverlay // partition hosts an overlay
)
// Hashtype represents the different SIF hashing function types used to fingerprint data objects.
type Hashtype int32
// List of supported hash functions.
const (
HashSHA256 Hashtype = iota + 1
HashSHA384
HashSHA512
HashBLAKE2S
HashBLAKE2B
)
// Formattype represents the different formats used to store cryptographic message objects.
type Formattype int32
// List of supported cryptographic message formats.
const (
FormatOpenPGP Formattype = iota + 1
FormatPEM
)
// Messagetype represents the different messages stored within cryptographic message objects.
type Messagetype int32
// List of supported cryptographic message formats.
const (
// openPGP formatted messages
MessageClearSignature Messagetype = 0x100
// PEM formatted messages
MessageRSAOAEP Messagetype = 0x200
)
// SIF data object deletion strategies.
const (
DelZero = iota + 1 // zero the data object bytes
DelCompact // free the space used by data object
)
// Descriptor represents the SIF descriptor type.
type Descriptor struct {
Datatype Datatype // informs of descriptor type
Used bool // is the descriptor in use
ID uint32 // a unique id for this data object
Groupid uint32 // object group this data object is related to
Link uint32 // special link or relation to an id or group
Fileoff int64 // offset from start of image file
Filelen int64 // length of data in file
Storelen int64 // length of data + alignment to store data in file
Ctime int64 // image creation time
Mtime int64 // last modification time
UID int64 // system user owning the file
Gid int64 // system group owning the file
Name [DescrNameLen]byte // descriptor name (string identifier)
Extra [DescrMaxPrivLen]byte // big enough for extra data below
}
// Deffile represents the SIF definition-file data object descriptor.
type Deffile struct {
}
// Labels represents the SIF JSON-labels data object descriptor.
type Labels struct {
}
// Envvar represents the SIF envvar data object descriptor.
type Envvar struct {
}
// Partition represents the SIF partition data object descriptor.
type Partition struct {
Fstype Fstype
Parttype Parttype
Arch [HdrArchLen]byte // arch the image is built for
}
// Signature represents the SIF signature data object descriptor.
type Signature struct {
Hashtype Hashtype
Entity [DescrEntityLen]byte
}
// GenericJSON represents the SIF generic JSON meta-data data object descriptor.
type GenericJSON struct {
}
// Generic represents the SIF generic data object descriptor.
type Generic struct {
}
// CryptoMessage represents the SIF crypto message object descriptor.
type CryptoMessage struct {
Formattype Formattype
Messagetype Messagetype
}
// Header describes a loaded SIF file.
type Header struct {
Launch [HdrLaunchLen]byte // #! shell execution line
Magic [HdrMagicLen]byte // look for "SIF_MAGIC"
Version [HdrVersionLen]byte // SIF version
Arch [HdrArchLen]byte // arch the primary partition is built for
ID uuid.UUID // image unique identifier
Ctime int64 // image creation time
Mtime int64 // last modification time
Dfree int64 // # of unused data object descr.
Dtotal int64 // # of total available data object descr.
Descroff int64 // bytes into file where descs start
Descrlen int64 // bytes used by all current descriptors
Dataoff int64 // bytes into file where data starts
Datalen int64 // bytes used by all data objects
}
//
// This section describes SIF creation/loading data structures used when
// building or opening a SIF file. Transient data not found in the final
// SIF file. Those data structures are internal.
//
// ReadWriter describes the operations needed to support reading and
// writing SIF files.
type ReadWriter interface {
io.ReadWriteSeeker
io.Closer
Name() string
Fd() uintptr
Stat() (os.FileInfo, error)
Sync() error
Truncate(size int64) error
}
// FileImage describes the representation of a SIF file in memory.
type FileImage struct {
Header Header // the loaded SIF global header
Fp ReadWriter // file pointer of opened SIF file
Filesize int64 // file size of the opened SIF file
Filedata []byte // the content of the opened file
Amodebuf bool // access mode: mmap = false, buffered = true
Reader *bytes.Reader // reader on top of Mapdata
DescrArr []Descriptor // slice of loaded descriptors from SIF file
PrimPartID uint32 // ID of primary system partition if present
}
// CreateInfo wraps all SIF file creation info needed.
type CreateInfo struct {
Pathname string // the end result output filename
Launchstr string // the shell run command
Sifversion string // the SIF specification version used
ID uuid.UUID // image unique identifier
InputDescr []DescriptorInput // slice of input info for descriptor creation
}
// DescriptorInput describes the common info needed to create a data object descriptor.
type DescriptorInput struct {
Datatype Datatype // datatype being harvested for new descriptor
Groupid uint32 // group to be set for new descriptor
Link uint32 // link to be set for new descriptor
Size int64 // size of the data object for the new descriptor
Alignment int // Align requirement for data object
Fname string // file containing data associated with the new descriptor
Fp io.Reader // file pointer to opened 'fname'
Data []byte // loaded data from file
Image *FileImage // loaded SIF file in memory
Descr *Descriptor // created end result descriptor
Extra bytes.Buffer // where specific input type store their data
}