Introduced internal pseudo-random generators iso_random_uuid() and

iso_random_8byte().
This commit is contained in:
Thomas Schmitt 2012-05-27 16:05:56 +02:00
parent 3e2479c095
commit 1ed3ba7933
3 changed files with 161 additions and 123 deletions

View File

@ -23,17 +23,6 @@
/* for gettimeofday() */
#include <sys/time.h>
/* >>> ISOHYBRID : Need ./configure test for uuid_generate() which checks for:
uuid_t, uuid_generate, the need for -luuid
*/
/* <<<
#define Libisofs_with_uuid_generatE 1
*/
#ifdef Libisofs_with_uuid_generatE
#include <uuid/uuid.h>
#endif
#include "filesrc.h"
#include "ecma119.h"
#include "eltorito.h"
@ -455,106 +444,6 @@ static int insert_apm_head(uint8_t *buf, int apm_count)
}
#ifdef Libisofs_with_uuid_generatE
static void swap_uuid(void *u_pt)
{
uint8_t tr, *u;
u = (uint8_t *) u_pt;
tr = u[0]; u[0] = u[3]; u[3] = tr;
tr = u[1]; u[1] = u[2]; u[2] = tr;
tr = u[4]; u[4] = u[5]; u[5] = tr;
tr = u[6]; u[6] = u[7]; u[7] = tr;
}
#endif /* Libisofs_with_uuid_generatE */
/* CRC-32 as of GPT and Ethernet.
Parameters are deduced from a table driven implementation in isohybrid.c
*/
static unsigned int crc32_gpt(unsigned char *data, int count, int flag)
{
unsigned int acc, top, result = 0;
long int i;
/* Chosen so that the CRC of 0 bytes of input is 0x00000000 */
acc = 0x46af6449;
/* Process data bits and flush numerator by 32 zero bits */
for (i = 0; i < count * 8 + 32; i++) {
top = acc & 0x80000000;
acc = (acc << 1);
if (i < count * 8)
/* The least significant bits of input bytes get processed first */
acc |= ((data[i / 8] >> (i % 8)) & 1);
if (top)
/* Division by the generating polynomial */
acc ^= 0x04c11db7;
}
/* Mirror residue bits */
for (i = 0; i < 32; i++)
if (acc & (1 << i))
result |= 1 << (31 - i);
/* Return bit complement */
return result ^ 0xffffffff;
}
static void random_uuid(Ecma119Image *t, uint8_t *uuid)
{
#ifdef Libisofs_with_uuid_generatE
uuid_t u;
#else
uint8_t u[16];
/* produced by uuidgen(1) by Andreas Dilger */
static uint8_t uuid_template[16] = {
0x6e, 0xf5, 0xa3, 0x8b, 0xcb, 0xfa, 0xdd, 0x4e,
0x36, 0x9f, 0x0b, 0x12, 0x51, 0xc3, 0x7d, 0x1a
};
uint32_t rnd, salt;
struct timeval tv;
struct timezone tz;
static int counter = 0;
int i;
#endif
#ifdef Libisofs_with_uuid_generatE
uuid_generate(u);
swap_uuid((void *) u);
memcpy(wpt, u, 16);
#else
salt = crc32_gpt((unsigned char *) t, sizeof(Ecma119Image), 0);
/* This relies on the uniqueness of the template and the rareness of
bootable ISO image production via libisofs. Estimated 53 bits of
entropy should influence the production of a single day.
So first collisions are to be expected with about 100 million images
per day.
*/
memcpy(u, uuid_template, 16);
gettimeofday(&tv, &tz);
for (i = 0; i < 4; i++)
u[3 + i] = (salt >> (8 * i)) & 0xff;
u[8] = (salt >> 8) & 0xff;
rnd = ((0xffffffffff & tv.tv_sec) << 8) |
(((tv.tv_usec >> 16) ^ (salt & 0xf0)) & 0xff);
u[9] ^= counter & 0xff;
for (i = 0; i < 4; i++)
u[10 + i] ^= (rnd >> (8 * i)) & 0xff;
u[14] ^= (tv.tv_usec >> 8) & 0xff;
u[15] ^= tv.tv_usec & 0xff;
counter++;
#endif /* ! Libisofs_with_uuid_generatE */
}
/* Describe the first three GPT boot images as MBR partitions */
static int gpt_images_as_mbr_partitions(Ecma119Image *t, char *wpt,
int gpt_idx[128], int *gpt_cursor)
@ -598,7 +487,7 @@ static void write_gpt_entry(Ecma119Image *t, char *buf, uint8_t type_guid[16],
memcpy(wpt, type_guid, 16);
wpt += 16;
random_uuid(t, (uint8_t *) wpt);
iso_random_uuid(t, (uint8_t *) wpt);
wpt += 16;
lsb_to_buf(&wpt, start_lba & 0xffffffff, 32, 0);
lsb_to_buf(&wpt, (start_lba >> 32) & 0xffffffff, 32, 0);
@ -692,7 +581,7 @@ static int write_gpt_header_block(Ecma119Image *t, char *buf,
lsb_to_buf(&wpt, (uint32_t) ((back_lba - 32) >> 32), 32, 1);
/* Disk GUID */
random_uuid(t, (uint8_t *) wpt);
iso_random_uuid(t, (uint8_t *) wpt);
wpt += 16;
/* Partition entries start */
@ -720,7 +609,7 @@ static int write_gpt_header_block(Ecma119Image *t, char *buf,
/* CRC-32 of this header while head_crc is 0 */
wpt = buf + 16;
crc = crc32_gpt((unsigned char *) buf, wpt - buf, 0);
crc = iso_crc32_gpt((unsigned char *) buf, wpt - buf, 0);
lsb_to_buf(&wpt, crc, 32, 0);
return ISO_SUCCESS;

View File

@ -27,6 +27,19 @@
#include <sys/stat.h>
#include <unistd.h>
/* for gettimeofday() */
#include <sys/time.h>
/* >>> Need ./configure test for uuid_generate() which checks for:
uuid_t, uuid_generate, the need for -luuid
*/
/*
#define Libisofs_with_uuid_generatE 1
*/
#ifdef Libisofs_with_uuid_generatE
#include <uuid/uuid.h>
#endif
/*
* Create a MBR for an isohybrid enabled ISOLINUX boot image.
@ -834,7 +847,8 @@ static int iso_write_apm(Ecma119Image *t, uint32_t img_blocks, uint8_t *buf)
}
if (part_end > goal) {
/* >>> Overlapping partition. ??? Warn ??? Bail out ??? */;
/* >>> Overlapping partition. */;
/* >>> Vladimir: "Throw error." */;
}
if (part_end < goal) {
@ -924,14 +938,6 @@ int iso_write_system_area(Ecma119Image *t, uint8_t *buf)
Note that Block0 of the APM is not written but is in the responsibility
of the MBR template. Its block size MUST match t->apm_block_size.
>>> ts B20526
>>> ??? Shall i check t->system_area_data whether there are the first
>>> ??? four bytes of a Block0 and what block size they announce ?
>>> pro: That would prevent cruel mishaps
>>> con: t->system_area_data is totally opaque up to now.
>>> I cannot easily predict whether the first bytes get altered
>>> in the course of processing.
>>> ts B20526
>>> This does not care for eventual image enlargements in last minute.
>>> A sa_type, that does this, will have to adjust the last APM entry
@ -1170,3 +1176,123 @@ int iso_register_apm_entry(Ecma119Image *t,
return ISO_SUCCESS;
}
#ifdef Libisofs_with_uuid_generatE
static void swap_uuid(void *u_pt)
{
uint8_t tr, *u;
u = (uint8_t *) u_pt;
tr = u[0]; u[0] = u[3]; u[3] = tr;
tr = u[1]; u[1] = u[2]; u[2] = tr;
tr = u[4]; u[4] = u[5]; u[5] = tr;
tr = u[6]; u[6] = u[7]; u[7] = tr;
}
#endif /* Libisofs_with_uuid_generatE */
/* CRC-32 as of GPT and Ethernet.
Parameters are deduced from a table driven implementation in isohybrid.c
*/
unsigned int iso_crc32_gpt(unsigned char *data, int count, int flag)
{
unsigned int acc, top, result = 0;
long int i;
/* Chosen so that the CRC of 0 bytes of input is 0x00000000 */
acc = 0x46af6449;
/* Process data bits and flush numerator by 32 zero bits */
for (i = 0; i < count * 8 + 32; i++) {
top = acc & 0x80000000;
acc = (acc << 1);
if (i < count * 8)
/* The least significant bits of input bytes get processed first */
acc |= ((data[i / 8] >> (i % 8)) & 1);
if (top)
/* Division by the generating polynomial */
acc ^= 0x04c11db7;
}
/* Mirror residue bits */
for (i = 0; i < 32; i++)
if (acc & (1 << i))
result |= 1 << (31 - i);
/* Return bit complement */
return result ^ 0xffffffff;
}
void iso_random_uuid(Ecma119Image *t, uint8_t uuid[16])
{
#ifdef Libisofs_with_uuid_generatE
uuid_t u;
#else
uint8_t u[16];
/* produced by uuid_generate() and byte-swapped to isohybrid.c habits */
static uint8_t uuid_template[16] = {
0xee, 0x29, 0x9d, 0xfc, 0x65, 0xcc, 0x7c, 0x40,
0x92, 0x61, 0x5b, 0xcd, 0x6f, 0xed, 0x08, 0x34
};
uint32_t rnd, salt;
struct timeval tv;
struct timezone tz;
pid_t pid;
static int counter = 0;
int i;
#endif
#ifdef Libisofs_with_uuid_generatE
uuid_generate(u);
swap_uuid((void *) u);
memcpy(uuid, u, 16);
#else
salt = iso_crc32_gpt((unsigned char *) t, sizeof(Ecma119Image), 0);
salt ^= getpid();
/* This relies on the uniqueness of the template and the rareness of
bootable ISO image production via libisofs. Estimated 53 bits of
entropy should influence the production of a single day.
So first collisions are to be expected with about 100 million images
per day.
*/
memcpy(u, uuid_template, 16);
gettimeofday(&tv, &tz);
for (i = 0; i < 4; i++)
u[i] = (salt >> (8 * i)) & 0xff;
for (i = 0; i < 2; i++)
u[4 + i] = (pid >> (8 * i)) & 0xff;
u[6] = ((salt >> 8) | (pid >> 16)) & 0xff;
rnd = ((0xffffffffff & tv.tv_sec) << 8) |
(((tv.tv_usec >> 16) ^ (salt & 0xf0)) & 0xff);
u[9] ^= counter & 0xff;
for (i = 0; i < 4; i++)
u[10 + i] ^= (rnd >> (8 * i)) & 0xff;
u[14] ^= (tv.tv_usec >> 8) & 0xff;
u[15] ^= tv.tv_usec & 0xff;
counter++;
memcpy(uuid, u, 16);
#endif /* ! Libisofs_with_uuid_generatE */
}
void iso_random_8byte(Ecma119Image *t, uint8_t result[8])
{
uint8_t uuid[16];
int i;
iso_random_uuid(t, uuid);
for (i = 0; i < 8; i++) {
if (i == 1)
result[i] = uuid[9]; /* The intra-process counter */
else
result[i] = uuid[i] ^ uuid[i + 8];
}
}

View File

@ -103,4 +103,27 @@ int iso_quick_apm_entry(Ecma119Image *t,
uint32_t start_block, uint32_t block_count, char *name, char *type);
/* CRC-32 as of GPT and Ethernet.
*/
unsigned int iso_crc32_gpt(unsigned char *data, int count, int flag);
/* These two pseudo-random generators produce byte strings which will
surely not duplicate in the first 256 calls. If more calls are necessary
in the same process, then one must wait until the output of
gettimeofday(2) changes.
It is advised to obtain them as late as possible, so that Ecma119Image *t
can distinguish itself from other image production setups which might be
run on other machines with the same process number at the same time.
*/
/* Produces a weakly random variation of a hardcoded real random uuid
*/
void iso_random_uuid(Ecma119Image *t, uint8_t uuid[16]);
/* Produces a weakly random variation of a hardcoded real random template
*/
void iso_random_8byte(Ecma119Image *t, uint8_t result[8]);
#endif /* SYSTEM_AREA_H_ */