[systemd-commits] 3 commits - src/journal
Lennart Poettering
lennart at kemper.freedesktop.org
Thu Aug 16 15:51:36 PDT 2012
src/journal/journal-authenticate.c | 138 ++++++++++++++++++----------
src/journal/journal-authenticate.h | 10 +-
src/journal/journal-def.h | 17 +--
src/journal/journal-file.c | 50 +++++-----
src/journal/journal-file.h | 18 +--
src/journal/journal-verify.c | 180 ++++++++++++++++++++++++-------------
src/journal/journalctl.c | 116 +++++++++++++----------
src/journal/test-journal-verify.c | 5 -
8 files changed, 328 insertions(+), 206 deletions(-)
New commits:
commit baed47c3c20512507e497058d388782400a072f6
Author: Lennart Poettering <lennart at poettering.net>
Date: Fri Aug 17 00:45:18 2012 +0200
journal: rework terminology
Let's clean up our terminology a bit. New terminology:
FSS = Forward Secure Sealing
FSPRG = Forward Secure Pseudo-Random Generator
FSS is the combination of FSPRG and a HMAC.
Sealing = process of adding authentication tags to the journal.
Verification = process of checking authentication tags to the journal.
Sealing Key = The key used for adding authentication tags to the journal.
Verification Key = The key used for checking authentication tags of the journal.
Key pair = The pair of Sealing Key and Verification Key
Internally, the Sealing Key is the combination of the FSPRG State plus
change interval/start time.
Internally, the Verification Key is the combination of the FSPRG Seed
plus change interval/start time.
diff --git a/src/journal/journal-authenticate.c b/src/journal/journal-authenticate.c
index c087ad4..ae64d3c 100644
--- a/src/journal/journal-authenticate.c
+++ b/src/journal/journal-authenticate.c
@@ -45,7 +45,7 @@ int journal_file_append_tag(JournalFile *f) {
assert(f);
- if (!f->authenticate)
+ if (!f->seal)
return 0;
if (!f->hmac_running)
@@ -79,7 +79,7 @@ int journal_file_hmac_start(JournalFile *f) {
uint8_t key[256 / 8]; /* Let's pass 256 bit from FSPRG to HMAC */
assert(f);
- if (!f->authenticate)
+ if (!f->seal)
return 0;
if (f->hmac_running)
@@ -100,28 +100,28 @@ static int journal_file_get_epoch(JournalFile *f, uint64_t realtime, uint64_t *e
assert(f);
assert(epoch);
- assert(f->authenticate);
+ assert(f->seal);
- if (f->fsprg_start_usec == 0 ||
- f->fsprg_interval_usec == 0)
+ if (f->fss_start_usec == 0 ||
+ f->fss_interval_usec == 0)
return -ENOTSUP;
- if (realtime < f->fsprg_start_usec)
+ if (realtime < f->fss_start_usec)
return -ESTALE;
- t = realtime - f->fsprg_start_usec;
- t = t / f->fsprg_interval_usec;
+ t = realtime - f->fss_start_usec;
+ t = t / f->fss_interval_usec;
*epoch = t;
return 0;
}
-static int journal_file_need_evolve(JournalFile *f, uint64_t realtime) {
+static int journal_file_fsprg_need_evolve(JournalFile *f, uint64_t realtime) {
uint64_t goal, epoch;
int r;
assert(f);
- if (!f->authenticate)
+ if (!f->seal)
return 0;
r = journal_file_get_epoch(f, realtime, &goal);
@@ -135,13 +135,13 @@ static int journal_file_need_evolve(JournalFile *f, uint64_t realtime) {
return epoch != goal;
}
-static int journal_file_evolve(JournalFile *f, uint64_t realtime) {
+int journal_file_fsprg_evolve(JournalFile *f, uint64_t realtime) {
uint64_t goal, epoch;
int r;
assert(f);
- if (!f->authenticate)
+ if (!f->seal)
return 0;
r = journal_file_get_epoch(f, realtime, &goal);
@@ -169,7 +169,7 @@ int journal_file_fsprg_seek(JournalFile *f, uint64_t goal) {
assert(f);
- if (!f->authenticate)
+ if (!f->seal)
return 0;
assert(f->fsprg_seed);
@@ -206,10 +206,10 @@ int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime) {
assert(f);
- if (!f->authenticate)
+ if (!f->seal)
return 0;
- r = journal_file_need_evolve(f, realtime);
+ r = journal_file_fsprg_need_evolve(f, realtime);
if (r <= 0)
return 0;
@@ -217,7 +217,7 @@ int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime) {
if (r < 0)
return r;
- r = journal_file_evolve(f, realtime);
+ r = journal_file_fsprg_evolve(f, realtime);
if (r < 0)
return r;
@@ -234,7 +234,7 @@ int journal_file_hmac_put_object(JournalFile *f, int type, uint64_t p) {
assert(f);
- if (!f->authenticate)
+ if (!f->seal)
return 0;
r = journal_file_hmac_start(f);
@@ -283,7 +283,7 @@ int journal_file_hmac_put_header(JournalFile *f) {
assert(f);
- if (!f->authenticate)
+ if (!f->seal)
return 0;
r = journal_file_hmac_start(f);
@@ -305,23 +305,23 @@ int journal_file_hmac_put_header(JournalFile *f) {
return 0;
}
-int journal_file_load_fsprg(JournalFile *f) {
+int journal_file_fss_load(JournalFile *f) {
int r, fd = -1;
char *p = NULL;
struct stat st;
- FSPRGHeader *m = NULL;
+ FSSHeader *m = NULL;
sd_id128_t machine;
assert(f);
- if (!f->authenticate)
+ if (!f->seal)
return 0;
r = sd_id128_get_machine(&machine);
if (r < 0)
return r;
- if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fsprg",
+ if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
SD_ID128_FORMAT_VAL(machine)) < 0)
return -ENOMEM;
@@ -337,19 +337,19 @@ int journal_file_load_fsprg(JournalFile *f) {
goto finish;
}
- if (st.st_size < (off_t) sizeof(FSPRGHeader)) {
+ if (st.st_size < (off_t) sizeof(FSSHeader)) {
r = -ENODATA;
goto finish;
}
- m = mmap(NULL, PAGE_ALIGN(sizeof(FSPRGHeader)), PROT_READ, MAP_SHARED, fd, 0);
+ m = mmap(NULL, PAGE_ALIGN(sizeof(FSSHeader)), PROT_READ, MAP_SHARED, fd, 0);
if (m == MAP_FAILED) {
m = NULL;
r = -errno;
goto finish;
}
- if (memcmp(m->signature, FSPRG_HEADER_SIGNATURE, 8) != 0) {
+ if (memcmp(m->signature, FSS_HEADER_SIGNATURE, 8) != 0) {
r = -EBADMSG;
goto finish;
}
@@ -359,18 +359,18 @@ int journal_file_load_fsprg(JournalFile *f) {
goto finish;
}
- if (le64toh(m->header_size) < sizeof(FSPRGHeader)) {
+ if (le64toh(m->header_size) < sizeof(FSSHeader)) {
r = -EBADMSG;
goto finish;
}
- if (le64toh(m->state_size) != FSPRG_stateinbytes(m->secpar)) {
+ if (le64toh(m->fsprg_state_size) != FSPRG_stateinbytes(m->fsprg_secpar)) {
r = -EBADMSG;
goto finish;
}
- f->fsprg_file_size = le64toh(m->header_size) + le64toh(m->state_size);
- if ((uint64_t) st.st_size < f->fsprg_file_size) {
+ f->fss_file_size = le64toh(m->header_size) + le64toh(m->fsprg_state_size);
+ if ((uint64_t) st.st_size < f->fss_file_size) {
r = -ENODATA;
goto finish;
}
@@ -380,30 +380,30 @@ int journal_file_load_fsprg(JournalFile *f) {
goto finish;
}
- if (le64toh(m->fsprg_start_usec) <= 0 ||
- le64toh(m->fsprg_interval_usec) <= 0) {
+ if (le64toh(m->start_usec) <= 0 ||
+ le64toh(m->interval_usec) <= 0) {
r = -EBADMSG;
goto finish;
}
- f->fsprg_file = mmap(NULL, PAGE_ALIGN(f->fsprg_file_size), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
- if (f->fsprg_file == MAP_FAILED) {
- f->fsprg_file = NULL;
+ f->fss_file = mmap(NULL, PAGE_ALIGN(f->fss_file_size), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ if (f->fss_file == MAP_FAILED) {
+ f->fss_file = NULL;
r = -errno;
goto finish;
}
- f->fsprg_start_usec = le64toh(f->fsprg_file->fsprg_start_usec);
- f->fsprg_interval_usec = le64toh(f->fsprg_file->fsprg_interval_usec);
+ f->fss_start_usec = le64toh(f->fss_file->start_usec);
+ f->fss_interval_usec = le64toh(f->fss_file->interval_usec);
- f->fsprg_state = (uint8_t*) f->fsprg_file + le64toh(f->fsprg_file->header_size);
- f->fsprg_state_size = le64toh(f->fsprg_file->state_size);
+ f->fsprg_state = (uint8_t*) f->fss_file + le64toh(f->fss_file->header_size);
+ f->fsprg_state_size = le64toh(f->fss_file->fsprg_state_size);
r = 0;
finish:
if (m)
- munmap(m, PAGE_ALIGN(sizeof(FSPRGHeader)));
+ munmap(m, PAGE_ALIGN(sizeof(FSSHeader)));
if (fd >= 0)
close_nointr_nofail(fd);
@@ -412,10 +412,10 @@ finish:
return r;
}
-int journal_file_setup_hmac(JournalFile *f) {
+int journal_file_hmac_setup(JournalFile *f) {
gcry_error_t e;
- if (!f->authenticate)
+ if (!f->seal)
return 0;
e = gcry_md_open(&f->hmac, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
@@ -429,7 +429,7 @@ int journal_file_append_first_tag(JournalFile *f) {
int r;
uint64_t p;
- if (!f->authenticate)
+ if (!f->seal)
return 0;
log_debug("Calculating first tag...");
@@ -463,8 +463,8 @@ int journal_file_append_first_tag(JournalFile *f) {
return 0;
}
-bool journal_file_fsprg_enabled(JournalFile *f) {
+bool journal_file_fss_enabled(JournalFile *f) {
assert(f);
- return !!(le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_AUTHENTICATED);
+ return !!(le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_SEALED);
}
diff --git a/src/journal/journal-authenticate.h b/src/journal/journal-authenticate.h
index 282c73f..4f4f45b 100644
--- a/src/journal/journal-authenticate.h
+++ b/src/journal/journal-authenticate.h
@@ -30,14 +30,13 @@ int journal_file_append_tag(JournalFile *f);
int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime);
int journal_file_append_first_tag(JournalFile *f);
+int journal_file_hmac_setup(JournalFile *f);
int journal_file_hmac_start(JournalFile *f);
int journal_file_hmac_put_header(JournalFile *f);
int journal_file_hmac_put_object(JournalFile *f, int type, uint64_t p);
-int journal_file_load_fsprg(JournalFile *f);
-
-int journal_file_setup_hmac(JournalFile *f);
-
-bool journal_file_fsprg_enabled(JournalFile *f);
+int journal_file_fss_load(JournalFile *f);
+bool journal_file_fss_enabled(JournalFile *f);
+int journal_file_fsprg_evolve(JournalFile *f, uint64_t realtime);
int journal_file_fsprg_seek(JournalFile *f, uint64_t epoch);
diff --git a/src/journal/journal-def.h b/src/journal/journal-def.h
index ab49880..52c55ab 100644
--- a/src/journal/journal-def.h
+++ b/src/journal/journal-def.h
@@ -42,7 +42,7 @@ typedef struct TagObject TagObject;
typedef struct EntryItem EntryItem;
typedef struct HashItem HashItem;
-typedef struct FSPRGHeader FSPRGHeader;
+typedef struct FSSHeader FSSHeader;
/* Object types */
enum {
@@ -151,7 +151,7 @@ enum {
};
enum {
- HEADER_COMPATIBLE_AUTHENTICATED = 1
+ HEADER_COMPATIBLE_SEALED = 1
};
#define HEADER_SIGNATURE ((char[]) { 'L', 'P', 'K', 'S', 'H', 'H', 'R', 'H' })
@@ -189,18 +189,18 @@ _packed_ struct Header {
le64_t n_entry_arrays;
};
-#define FSPRG_HEADER_SIGNATURE ((char[]) { 'K', 'S', 'H', 'H', 'R', 'H', 'L', 'P' })
+#define FSS_HEADER_SIGNATURE ((char[]) { 'K', 'S', 'H', 'H', 'R', 'H', 'L', 'P' })
-_packed_ struct FSPRGHeader {
+_packed_ struct FSSHeader {
uint8_t signature[8]; /* "KSHHRHLP" */
le32_t compatible_flags;
le32_t incompatible_flags;
sd_id128_t machine_id;
sd_id128_t boot_id; /* last writer */
le64_t header_size;
- le64_t fsprg_start_usec;
- le64_t fsprg_interval_usec;
- le16_t secpar;
+ le64_t start_usec;
+ le64_t interval_usec;
+ le16_t fsprg_secpar;
le16_t reserved[3];
- le64_t state_size;
+ le64_t fsprg_state_size;
};
diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
index 274f22d..76bf0e5 100644
--- a/src/journal/journal-file.c
+++ b/src/journal/journal-file.c
@@ -65,7 +65,7 @@ void journal_file_close(JournalFile *f) {
assert(f);
/* Write the final tag */
- if (f->authenticate)
+ if (f->seal)
journal_file_append_tag(f);
/* Sync everything to disk, before we mark the file offline */
@@ -96,8 +96,8 @@ void journal_file_close(JournalFile *f) {
#endif
#ifdef HAVE_GCRYPT
- if (f->fsprg_file)
- munmap(f->fsprg_file, PAGE_ALIGN(f->fsprg_file_size));
+ if (f->fss_file)
+ munmap(f->fss_file, PAGE_ALIGN(f->fss_file_size));
else if (f->fsprg_state)
free(f->fsprg_state);
@@ -125,7 +125,7 @@ static int journal_file_init_header(JournalFile *f, JournalFile *template) {
htole32(f->compress ? HEADER_INCOMPATIBLE_COMPRESSED : 0);
h.compatible_flags =
- htole32(f->authenticate ? HEADER_COMPATIBLE_AUTHENTICATED : 0);
+ htole32(f->seal ? HEADER_COMPATIBLE_SEALED : 0);
r = sd_id128_randomize(&h.file_id);
if (r < 0)
@@ -195,7 +195,7 @@ static int journal_file_verify_header(JournalFile *f) {
* compatible flags, too */
if (f->writable) {
#ifdef HAVE_GCRYPT
- if ((le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_AUTHENTICATED) != 0)
+ if ((le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_SEALED) != 0)
return -EPROTONOSUPPORT;
#else
if (f->header->compatible_flags != 0)
@@ -207,8 +207,8 @@ static int journal_file_verify_header(JournalFile *f) {
if (le64toh(f->header->header_size) < HEADER_SIZE_MIN)
return -EBADMSG;
- if ((le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_AUTHENTICATED) &&
- !JOURNAL_HEADER_CONTAINS(f->header, n_tags))
+ if ((le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_SEALED) &&
+ !JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays))
return -EBADMSG;
if ((uint64_t) f->last_stat.st_size < (le64toh(f->header->header_size) + le64toh(f->header->arena_size)))
@@ -240,7 +240,7 @@ static int journal_file_verify_header(JournalFile *f) {
}
f->compress = !!(le32toh(f->header->incompatible_flags) & HEADER_INCOMPATIBLE_COMPRESSED);
- f->authenticate = !!(le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_AUTHENTICATED);
+ f->seal = !!(le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_SEALED);
return 0;
}
@@ -1900,8 +1900,8 @@ void journal_file_print_header(JournalFile *f) {
f->header->state == STATE_OFFLINE ? "offline" :
f->header->state == STATE_ONLINE ? "online" :
f->header->state == STATE_ARCHIVED ? "archived" : "unknown",
- (f->header->compatible_flags & HEADER_COMPATIBLE_AUTHENTICATED) ? " AUTHENTICATED" : "",
- (f->header->compatible_flags & ~HEADER_COMPATIBLE_AUTHENTICATED) ? " ???" : "",
+ (f->header->compatible_flags & HEADER_COMPATIBLE_SEALED) ? " SEALED" : "",
+ (f->header->compatible_flags & ~HEADER_COMPATIBLE_SEALED) ? " ???" : "",
(f->header->incompatible_flags & HEADER_INCOMPATIBLE_COMPRESSED) ? " COMPRESSED" : "",
(f->header->incompatible_flags & ~HEADER_INCOMPATIBLE_COMPRESSED) ? " ???" : "",
(unsigned long long) le64toh(f->header->header_size),
@@ -1934,7 +1934,7 @@ int journal_file_open(
int flags,
mode_t mode,
bool compress,
- bool authenticate,
+ bool seal,
JournalMetrics *metrics,
MMapCache *mmap_cache,
JournalFile *template,
@@ -1964,7 +1964,7 @@ int journal_file_open(
f->prot = prot_from_flags(flags);
f->writable = (flags & O_ACCMODE) != O_RDONLY;
f->compress = compress;
- f->authenticate = authenticate;
+ f->seal = seal;
if (mmap_cache)
f->mmap = mmap_cache_ref(mmap_cache);
@@ -2000,10 +2000,10 @@ int journal_file_open(
newly_created = true;
/* Try to load the FSPRG state, and if we can't, then
- * just don't do authentication */
- r = journal_file_load_fsprg(f);
+ * just don't do sealing */
+ r = journal_file_fss_load(f);
if (r < 0)
- f->authenticate = false;
+ f->seal = false;
r = journal_file_init_header(f, template);
if (r < 0)
@@ -2034,7 +2034,7 @@ int journal_file_open(
}
if (!newly_created && f->writable) {
- r = journal_file_load_fsprg(f);
+ r = journal_file_fss_load(f);
if (r < 0)
goto fail;
}
@@ -2051,7 +2051,7 @@ int journal_file_open(
goto fail;
}
- r = journal_file_setup_hmac(f);
+ r = journal_file_hmac_setup(f);
if (r < 0)
goto fail;
@@ -2088,7 +2088,7 @@ fail:
return r;
}
-int journal_file_rotate(JournalFile **f, bool compress, bool authenticate) {
+int journal_file_rotate(JournalFile **f, bool compress, bool seal) {
char *p;
size_t l;
JournalFile *old_file, *new_file = NULL;
@@ -2127,7 +2127,7 @@ int journal_file_rotate(JournalFile **f, bool compress, bool authenticate) {
old_file->header->state = STATE_ARCHIVED;
- r = journal_file_open(old_file->path, old_file->flags, old_file->mode, compress, authenticate, NULL, old_file->mmap, old_file, &new_file);
+ r = journal_file_open(old_file->path, old_file->flags, old_file->mode, compress, seal, NULL, old_file->mmap, old_file, &new_file);
journal_file_close(old_file);
*f = new_file;
@@ -2139,7 +2139,7 @@ int journal_file_open_reliably(
int flags,
mode_t mode,
bool compress,
- bool authenticate,
+ bool seal,
JournalMetrics *metrics,
MMapCache *mmap_cache,
JournalFile *template,
@@ -2149,7 +2149,7 @@ int journal_file_open_reliably(
size_t l;
char *p;
- r = journal_file_open(fname, flags, mode, compress, authenticate,
+ r = journal_file_open(fname, flags, mode, compress, seal,
metrics, mmap_cache, template, ret);
if (r != -EBADMSG && /* corrupted */
r != -ENODATA && /* truncated */
@@ -2184,7 +2184,7 @@ int journal_file_open_reliably(
log_warning("File %s corrupted or uncleanly shut down, renaming and replacing.", fname);
- return journal_file_open(fname, flags, mode, compress, authenticate,
+ return journal_file_open(fname, flags, mode, compress, seal,
metrics, mmap_cache, template, ret);
}
diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h
index 9d437ae..58de214 100644
--- a/src/journal/journal-file.h
+++ b/src/journal/journal-file.h
@@ -51,7 +51,7 @@ typedef struct JournalFile {
int prot;
bool writable;
bool compress;
- bool authenticate;
+ bool seal;
bool tail_entry_monotonic_valid;
@@ -73,17 +73,17 @@ typedef struct JournalFile {
gcry_md_hd_t hmac;
bool hmac_running;
- FSPRGHeader *fsprg_file;
- size_t fsprg_file_size;
+ FSSHeader *fss_file;
+ size_t fss_file_size;
+
+ uint64_t fss_start_usec;
+ uint64_t fss_interval_usec;
void *fsprg_state;
size_t fsprg_state_size;
void *fsprg_seed;
size_t fsprg_seed_size;
-
- uint64_t fsprg_start_usec;
- uint64_t fsprg_interval_usec;
#endif
} JournalFile;
@@ -97,7 +97,7 @@ int journal_file_open(
int flags,
mode_t mode,
bool compress,
- bool authenticate,
+ bool seal,
JournalMetrics *metrics,
MMapCache *mmap_cache,
JournalFile *template,
@@ -110,7 +110,7 @@ int journal_file_open_reliably(
int flags,
mode_t mode,
bool compress,
- bool authenticate,
+ bool seal,
JournalMetrics *metrics,
MMapCache *mmap_cache,
JournalFile *template,
@@ -152,7 +152,7 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6
void journal_file_dump(JournalFile *f);
void journal_file_print_header(JournalFile *f);
-int journal_file_rotate(JournalFile **f, bool compress, bool authenticate);
+int journal_file_rotate(JournalFile **f, bool compress, bool seal);
void journal_file_post_change(JournalFile *f);
diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c
index e646e38..b7097e7 100644
--- a/src/journal/journal-verify.c
+++ b/src/journal/journal-verify.c
@@ -38,6 +38,7 @@
* - write tag only if non-tag objects have been written
* - change terms
* - write bit mucking test
+ * - tag timestamps should be between entry timestamps
*
* - Allow building without libgcrypt
* - check with sparse
@@ -595,7 +596,7 @@ static int verify_entry_array(
return 0;
}
-static int journal_file_parse_seed(JournalFile *f, const char *s) {
+static int journal_file_parse_verification_key(JournalFile *f, const char *key) {
uint8_t *seed;
size_t seed_size, c;
const char *k;
@@ -607,7 +608,7 @@ static int journal_file_parse_seed(JournalFile *f, const char *s) {
if (!seed)
return -ENOMEM;
- k = s;
+ k = key;
for (c = 0; c < seed_size; c++) {
int x, y;
@@ -644,13 +645,14 @@ static int journal_file_parse_seed(JournalFile *f, const char *s) {
f->fsprg_seed = seed;
f->fsprg_seed_size = seed_size;
- f->fsprg_start_usec = start;
- f->fsprg_interval_usec = interval;
+
+ f->fss_start_usec = start;
+ f->fss_interval_usec = interval;
return 0;
}
-int journal_file_verify(JournalFile *f, const char *seed) {
+int journal_file_verify(JournalFile *f, const char *key) {
int r;
Object *o;
uint64_t p = 0, last_tag = 0, last_epoch = 0;
@@ -666,8 +668,8 @@ int journal_file_verify(JournalFile *f, const char *seed) {
assert(f);
- if (seed) {
- r = journal_file_parse_seed(f, seed);
+ if (key) {
+ r = journal_file_parse_verification_key(f, key);
if (r < 0) {
log_error("Failed to parse seed.");
return r;
@@ -848,8 +850,8 @@ int journal_file_verify(JournalFile *f, const char *seed) {
case OBJECT_TAG: {
uint64_t q;
- if (!(le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_AUTHENTICATED)) {
- log_error("Tag object without authentication at %llu", (unsigned long long) p);
+ if (!(le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_SEALED)) {
+ log_error("Tag object without sealing at %llu", (unsigned long long) p);
r = -EBADMSG;
goto fail;
}
@@ -904,7 +906,7 @@ int journal_file_verify(JournalFile *f, const char *seed) {
goto fail;
if (memcmp(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH) != 0) {
- log_error("Tag did not authenticate at %llu", (unsigned long long) p);
+ log_error("Tag failed verification at %llu", (unsigned long long) p);
r = -EBADMSG;
goto fail;
}
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index f0654fe..0df8ce5 100644
--- a/src/journal/journalctl.c
+++ b/src/journal/journalctl.c
@@ -46,7 +46,7 @@
#include "journal-authenticate.h"
#include "fsprg.h"
-#define DEFAULT_FSPRG_INTERVAL_USEC (15*USEC_PER_MINUTE)
+#define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
static OutputMode arg_output = OUTPUT_SHORT;
static bool arg_follow = false;
@@ -59,8 +59,8 @@ static bool arg_local = false;
static bool arg_this_boot = false;
static const char *arg_directory = NULL;
static int arg_priorities = 0xFF;
-static const char *arg_verify_seed = NULL;
-static usec_t arg_evolve = DEFAULT_FSPRG_INTERVAL_USEC;
+static const char *arg_verify_key = NULL;
+static usec_t arg_interval = DEFAULT_FSS_INTERVAL_USEC;
static enum {
ACTION_SHOW,
@@ -74,27 +74,27 @@ static int help(void) {
printf("%s [OPTIONS...] [MATCH]\n\n"
"Send control commands to or query the journal.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --no-pager Do not pipe output into a pager\n"
- " -a --all Show all fields, including long and unprintable\n"
- " -f --follow Follow journal\n"
- " -n --lines=INTEGER Journal entries to show\n"
- " --no-tail Show all lines, even in follow mode\n"
- " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
- " verbose, export, json, cat)\n"
- " -q --quiet Don't show privilege warning\n"
- " -l --local Only local entries\n"
- " -b --this-boot Show data only from current boot\n"
- " -D --directory=PATH Show journal files from directory\n"
- " -p --priority=RANGE Show only messages within the specified priority range\n\n"
+ " -h --help Show this help\n"
+ " --version Show package version\n"
+ " --no-pager Do not pipe output into a pager\n"
+ " -a --all Show all fields, including long and unprintable\n"
+ " -f --follow Follow journal\n"
+ " -n --lines=INTEGER Journal entries to show\n"
+ " --no-tail Show all lines, even in follow mode\n"
+ " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
+ " verbose, export, json, cat)\n"
+ " -q --quiet Don't show privilege warning\n"
+ " -l --local Only local entries\n"
+ " -b --this-boot Show data only from current boot\n"
+ " -D --directory=PATH Show journal files from directory\n"
+ " -p --priority=RANGE Show only messages within the specified priority range\n\n"
"Commands:\n"
- " --new-id128 Generate a new 128 Bit ID\n"
- " --header Show journal header information\n"
- " --verify Verify journal file consistency\n"
- " --verify-seed=SEED Specify FSPRG seed for verification\n"
- " --setup-keys Generate new FSPRG key and seed\n"
- " --evolve=TIME How of to evolve FSPRG keys\n",
+ " --new-id128 Generate a new 128 Bit ID\n"
+ " --header Show journal header information\n"
+ " --setup-keys Generate new FSS key pair\n"
+ " --interval=TIME Time interval for changing the FSS sealing key\n"
+ " --verify Verify journal file consistency\n"
+ " --verify-key=KEY Specify FSS verification key\n",
program_invocation_short_name);
return 0;
@@ -109,32 +109,32 @@ static int parse_argv(int argc, char *argv[]) {
ARG_NEW_ID128,
ARG_HEADER,
ARG_SETUP_KEYS,
+ ARG_INTERVAL,
ARG_VERIFY,
- ARG_VERIFY_SEED,
- ARG_EVOLVE
+ ARG_VERIFY_KEY
};
static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version" , no_argument, NULL, ARG_VERSION },
- { "no-pager", no_argument, NULL, ARG_NO_PAGER },
- { "follow", no_argument, NULL, 'f' },
- { "output", required_argument, NULL, 'o' },
- { "all", no_argument, NULL, 'a' },
- { "lines", required_argument, NULL, 'n' },
- { "no-tail", no_argument, NULL, ARG_NO_TAIL },
- { "new-id128", no_argument, NULL, ARG_NEW_ID128 },
- { "quiet", no_argument, NULL, 'q' },
- { "local", no_argument, NULL, 'l' },
- { "this-boot", no_argument, NULL, 'b' },
- { "directory", required_argument, NULL, 'D' },
- { "header", no_argument, NULL, ARG_HEADER },
- { "priority", no_argument, NULL, 'p' },
- { "setup-keys", no_argument, NULL, ARG_SETUP_KEYS },
- { "verify", no_argument, NULL, ARG_VERIFY },
- { "verify-seed", required_argument, NULL, ARG_VERIFY_SEED },
- { "evolve", required_argument, NULL, ARG_EVOLVE },
- { NULL, 0, NULL, 0 }
+ { "help", no_argument, NULL, 'h' },
+ { "version" , no_argument, NULL, ARG_VERSION },
+ { "no-pager", no_argument, NULL, ARG_NO_PAGER },
+ { "follow", no_argument, NULL, 'f' },
+ { "output", required_argument, NULL, 'o' },
+ { "all", no_argument, NULL, 'a' },
+ { "lines", required_argument, NULL, 'n' },
+ { "no-tail", no_argument, NULL, ARG_NO_TAIL },
+ { "new-id128", no_argument, NULL, ARG_NEW_ID128 },
+ { "quiet", no_argument, NULL, 'q' },
+ { "local", no_argument, NULL, 'l' },
+ { "this-boot", no_argument, NULL, 'b' },
+ { "directory", required_argument, NULL, 'D' },
+ { "header", no_argument, NULL, ARG_HEADER },
+ { "priority", no_argument, NULL, 'p' },
+ { "setup-keys", no_argument, NULL, ARG_SETUP_KEYS },
+ { "interval", required_argument, NULL, ARG_INTERVAL },
+ { "verify", no_argument, NULL, ARG_VERIFY },
+ { "verify-key", required_argument, NULL, ARG_VERIFY_KEY },
+ { NULL, 0, NULL, 0 }
};
int c, r;
@@ -221,15 +221,15 @@ static int parse_argv(int argc, char *argv[]) {
arg_action = ACTION_VERIFY;
break;
- case ARG_VERIFY_SEED:
+ case ARG_VERIFY_KEY:
arg_action = ACTION_VERIFY;
- arg_verify_seed = optarg;
+ arg_verify_key = optarg;
break;
- case ARG_EVOLVE:
- r = parse_usec(optarg, &arg_evolve);
- if (r < 0 || arg_evolve <= 0) {
- log_error("Failed to parse evolve interval: %s", optarg);
+ case ARG_INTERVAL:
+ r = parse_usec(optarg, &arg_interval);
+ if (r < 0 || arg_interval <= 0) {
+ log_error("Failed to parse sealing key change interval: %s", optarg);
return -EINVAL;
}
break;
@@ -456,7 +456,7 @@ static int setup_keys(void) {
int fd = -1, r;
sd_id128_t machine, boot;
char *p = NULL, *k = NULL;
- struct FSPRGHeader h;
+ struct FSSHeader h;
uint64_t n;
r = sd_id128_get_machine(&machine);
@@ -471,7 +471,7 @@ static int setup_keys(void) {
return r;
}
- if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fsprg",
+ if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss",
SD_ID128_FORMAT_VAL(machine)) < 0)
return log_oom();
@@ -481,7 +481,7 @@ static int setup_keys(void) {
goto finish;
}
- if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fsprg.tmp.XXXXXX",
+ if (asprintf(&k, "/var/log/journal/" SD_ID128_FORMAT_STR "/fss.tmp.XXXXXX",
SD_ID128_FORMAT_VAL(machine)) < 0) {
r = log_oom();
goto finish;
@@ -514,11 +514,13 @@ static int setup_keys(void) {
log_info("Generating key pair...");
FSPRG_GenMK(NULL, mpk, seed, seed_size, FSPRG_RECOMMENDED_SECPAR);
- log_info("Generating evolving key...");
+ log_info("Generating sealing key...");
FSPRG_GenState0(state, mpk, seed, seed_size);
+ assert(arg_interval > 0);
+
n = now(CLOCK_REALTIME);
- n /= arg_evolve;
+ n /= arg_interval;
close_nointr_nofail(fd);
fd = mkostemp(k, O_WRONLY|O_CLOEXEC|O_NOCTTY);
@@ -533,10 +535,10 @@ static int setup_keys(void) {
h.machine_id = machine;
h.boot_id = boot;
h.header_size = htole64(sizeof(h));
- h.fsprg_start_usec = htole64(n * arg_evolve);
- h.fsprg_interval_usec = htole64(arg_evolve);
- h.secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
- h.state_size = htole64(state_size);
+ h.start_usec = htole64(n * arg_interval);
+ h.interval_usec = htole64(arg_interval);
+ h.fsprg_secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
+ h.fsprg_state_size = htole64(state_size);
l = loop_write(fd, &h, sizeof(h), false);
if (l < 0 || (size_t) l != sizeof(h)) {
@@ -561,14 +563,13 @@ static int setup_keys(void) {
if (isatty(STDOUT_FILENO)) {
fprintf(stderr,
"\n"
- "The new key pair has been generated. The evolving key has been written to the\n"
- "following file. It will be used to protect local journal files. This file\n"
- "should be kept secret. It should not be used on multiple hosts.\n"
+ "The new key pair has been generated. The " ANSI_HIGHLIGHT_ON "secret sealing key" ANSI_HIGHLIGHT_OFF " has been written to\n"
+ "the following local file. It should not be used on multiple hosts.\n"
"\n"
"\t%s\n"
"\n"
- "Please write down the following " ANSI_HIGHLIGHT_ON "secret" ANSI_HIGHLIGHT_OFF " seed value. It should not be stored\n"
- "locally on disk, and may be used to verify journal files from this host.\n"
+ "Please write down the following " ANSI_HIGHLIGHT_ON "secret verification key" ANSI_HIGHLIGHT_OFF ". It should be stored\n"
+ "at a safe location and should not be saved locally on disk.\n"
"\n\t" ANSI_HIGHLIGHT_RED_ON, p);
fflush(stderr);
}
@@ -578,10 +579,16 @@ static int setup_keys(void) {
printf("%02x", ((uint8_t*) seed)[i]);
}
- printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_evolve);
+ printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_interval);
+
+ if (isatty(STDOUT_FILENO)) {
+ char tsb[FORMAT_TIMESPAN_MAX];
- if (isatty(STDOUT_FILENO))
- fputs(ANSI_HIGHLIGHT_OFF "\n", stderr);
+ fprintf(stderr,
+ ANSI_HIGHLIGHT_OFF "\n"
+ "The sealing key is automatically changed every %s.\n",
+ format_timespan(tsb, sizeof(tsb), arg_interval));
+ }
r = 0;
@@ -613,13 +620,13 @@ static int verify(sd_journal *j) {
int k;
#ifdef HAVE_GCRYPT
- if (!arg_verify_seed && journal_file_fsprg_enabled(f))
- log_warning("Journal file %s has authentication enabled but verification seed has not been passed using --verify-seed=.", f->path);
+ if (!arg_verify_key && journal_file_fss_enabled(f))
+ log_warning("Journal file %s has sealing enabled but verification key has not been passed using --verify-key=.", f->path);
#endif
- k = journal_file_verify(f, arg_verify_seed);
+ k = journal_file_verify(f, arg_verify_key);
if (k == -EINVAL) {
- /* If the seed was invalid give up right-away. */
+ /* If the key was invalid give up right-away. */
return k;
} else if (k < 0) {
log_warning("FAIL: %s (%s)", f->path, strerror(-k));
commit 14d10188de1fd58e663d73683a400d8d7dc67dba
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Aug 16 23:58:14 2012 +0200
journal: add FSPRG journal authentication
diff --git a/src/journal/journal-authenticate.c b/src/journal/journal-authenticate.c
index 809655e..c087ad4 100644
--- a/src/journal/journal-authenticate.c
+++ b/src/journal/journal-authenticate.c
@@ -60,6 +60,7 @@ int journal_file_append_tag(JournalFile *f) {
return r;
o->tag.seqnum = htole64(journal_file_tag_seqnum(f));
+ o->tag.epoch = htole64(FSPRG_GetEpoch(f->fsprg_state));
/* Add the tag object itself, so that we can protect its
* header. This will exclude the actual hash value in it */
@@ -74,9 +75,8 @@ int journal_file_append_tag(JournalFile *f) {
return 0;
}
-static int journal_file_hmac_start(JournalFile *f) {
+int journal_file_hmac_start(JournalFile *f) {
uint8_t key[256 / 8]; /* Let's pass 256 bit from FSPRG to HMAC */
-
assert(f);
if (!f->authenticate)
@@ -163,6 +163,44 @@ static int journal_file_evolve(JournalFile *f, uint64_t realtime) {
}
}
+int journal_file_fsprg_seek(JournalFile *f, uint64_t goal) {
+ void *msk;
+ uint64_t epoch;
+
+ assert(f);
+
+ if (!f->authenticate)
+ return 0;
+
+ assert(f->fsprg_seed);
+
+ if (f->fsprg_state) {
+ /* Cheaper... */
+
+ epoch = FSPRG_GetEpoch(f->fsprg_state);
+ if (goal == epoch)
+ return 0;
+
+ if (goal == epoch+1) {
+ FSPRG_Evolve(f->fsprg_state);
+ return 0;
+ }
+ } else {
+ f->fsprg_state_size = FSPRG_stateinbytes(FSPRG_RECOMMENDED_SECPAR);
+ f->fsprg_state = malloc(f->fsprg_state_size);
+
+ if (!f->fsprg_state)
+ return -ENOMEM;
+ }
+
+ log_debug("Seeking FSPRG key to %llu.", (unsigned long long) goal);
+
+ msk = alloca(FSPRG_mskinbytes(FSPRG_RECOMMENDED_SECPAR));
+ FSPRG_GenMK(msk, NULL, f->fsprg_seed, f->fsprg_seed_size, FSPRG_RECOMMENDED_SECPAR);
+ FSPRG_Seek(f->fsprg_state, goal, msk, f->fsprg_seed, f->fsprg_seed_size);
+ return 0;
+}
+
int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime) {
int r;
@@ -212,7 +250,7 @@ int journal_file_hmac_put_object(JournalFile *f, int type, uint64_t p) {
switch (o->object.type) {
case OBJECT_DATA:
- /* All but: hash and payload are mutable */
+ /* All but hash and payload are mutable */
gcry_md_write(f->hmac, &o->data.hash, sizeof(o->data.hash));
gcry_md_write(f->hmac, o->data.payload, le64toh(o->object.size) - offsetof(DataObject, payload));
break;
@@ -231,6 +269,7 @@ int journal_file_hmac_put_object(JournalFile *f, int type, uint64_t p) {
case OBJECT_TAG:
/* All but the tag itself */
gcry_md_write(f->hmac, &o->tag.seqnum, sizeof(o->tag.seqnum));
+ gcry_md_write(f->hmac, &o->tag.epoch, sizeof(o->tag.epoch));
break;
default:
return -EINVAL;
@@ -252,15 +291,16 @@ int journal_file_hmac_put_header(JournalFile *f) {
return r;
/* All but state+reserved, boot_id, arena_size,
- * tail_object_offset, n_objects, n_entries, tail_seqnum,
+ * tail_object_offset, n_objects, n_entries,
+ * tail_entry_seqnum, head_entry_seqnum, entry_array_offset,
* head_entry_realtime, tail_entry_realtime,
- * tail_entry_monotonic, n_data, n_fields, header_tag */
+ * tail_entry_monotonic, n_data, n_fields, n_tags,
+ * n_entry_arrays. */
gcry_md_write(f->hmac, f->header->signature, offsetof(Header, state) - offsetof(Header, signature));
gcry_md_write(f->hmac, &f->header->file_id, offsetof(Header, boot_id) - offsetof(Header, file_id));
gcry_md_write(f->hmac, &f->header->seqnum_id, offsetof(Header, arena_size) - offsetof(Header, seqnum_id));
gcry_md_write(f->hmac, &f->header->data_hash_table_offset, offsetof(Header, tail_object_offset) - offsetof(Header, data_hash_table_offset));
- gcry_md_write(f->hmac, &f->header->head_entry_seqnum, offsetof(Header, head_entry_realtime) - offsetof(Header, head_entry_seqnum));
return 0;
}
diff --git a/src/journal/journal-authenticate.h b/src/journal/journal-authenticate.h
index 566d7a8..282c73f 100644
--- a/src/journal/journal-authenticate.h
+++ b/src/journal/journal-authenticate.h
@@ -30,6 +30,7 @@ int journal_file_append_tag(JournalFile *f);
int journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime);
int journal_file_append_first_tag(JournalFile *f);
+int journal_file_hmac_start(JournalFile *f);
int journal_file_hmac_put_header(JournalFile *f);
int journal_file_hmac_put_object(JournalFile *f, int type, uint64_t p);
@@ -38,3 +39,5 @@ int journal_file_load_fsprg(JournalFile *f);
int journal_file_setup_hmac(JournalFile *f);
bool journal_file_fsprg_enabled(JournalFile *f);
+
+int journal_file_fsprg_seek(JournalFile *f, uint64_t epoch);
diff --git a/src/journal/journal-def.h b/src/journal/journal-def.h
index 660a92c..ab49880 100644
--- a/src/journal/journal-def.h
+++ b/src/journal/journal-def.h
@@ -125,6 +125,7 @@ _packed_ struct EntryArrayObject {
_packed_ struct TagObject {
ObjectHeader object;
uint64_t seqnum;
+ uint64_t epoch;
uint8_t tag[TAG_LENGTH]; /* SHA-256 HMAC */
};
diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
index 3bb1e90..274f22d 100644
--- a/src/journal/journal-file.c
+++ b/src/journal/journal-file.c
@@ -2049,12 +2049,12 @@ int journal_file_open(
r = journal_file_refresh_header(f);
if (r < 0)
goto fail;
-
- r = journal_file_setup_hmac(f);
- if (r < 0)
- goto fail;
}
+ r = journal_file_setup_hmac(f);
+ if (r < 0)
+ goto fail;
+
if (newly_created) {
r = journal_file_setup_field_hash_table(f);
if (r < 0)
diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c
index 94f90b6..e646e38 100644
--- a/src/journal/journal-verify.c
+++ b/src/journal/journal-verify.c
@@ -35,7 +35,10 @@
/* FIXME:
*
- * - verify FSPRG
+ * - write tag only if non-tag objects have been written
+ * - change terms
+ * - write bit mucking test
+ *
* - Allow building without libgcrypt
* - check with sparse
* - 64bit conversions
@@ -650,11 +653,11 @@ static int journal_file_parse_seed(JournalFile *f, const char *s) {
int journal_file_verify(JournalFile *f, const char *seed) {
int r;
Object *o;
- uint64_t p = 0, last_tag = 0;
- uint64_t n_tags = 0, entry_seqnum = 0, entry_monotonic = 0, entry_realtime = 0;
+ uint64_t p = 0, last_tag = 0, last_epoch = 0;
+ uint64_t entry_seqnum = 0, entry_monotonic = 0, entry_realtime = 0;
sd_id128_t entry_boot_id;
bool entry_seqnum_set = false, entry_monotonic_set = false, entry_realtime_set = false, found_main_entry_array = false;
- uint64_t n_weird = 0, n_objects = 0, n_entries = 0, n_data = 0, n_fields = 0, n_data_hash_tables = 0, n_field_hash_tables = 0, n_entry_arrays = 0;
+ uint64_t n_weird = 0, n_objects = 0, n_entries = 0, n_data = 0, n_fields = 0, n_data_hash_tables = 0, n_field_hash_tables = 0, n_entry_arrays = 0, n_tags = 0;
usec_t last_usec = 0;
int data_fd = -1, entry_fd = -1, entry_array_fd = -1;
char data_path[] = "/var/tmp/journal-data-XXXXXX",
@@ -842,7 +845,9 @@ int journal_file_verify(JournalFile *f, const char *seed) {
n_entry_arrays++;
break;
- case OBJECT_TAG:
+ case OBJECT_TAG: {
+ uint64_t q;
+
if (!(le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_AUTHENTICATED)) {
log_error("Tag object without authentication at %llu", (unsigned long long) p);
r = -EBADMSG;
@@ -855,8 +860,61 @@ int journal_file_verify(JournalFile *f, const char *seed) {
goto fail;
}
+ if (le64toh(o->tag.epoch) < last_epoch) {
+ log_error("Epoch sequence out of synchronization at %llu", (unsigned long long) p);
+ r = -EBADMSG;
+ goto fail;
+ }
+
+ /* OK, now we know the epoch. So let's now set
+ * it, and calculate the HMAC for everything
+ * since the last tag. */
+ r = journal_file_fsprg_seek(f, le64toh(o->tag.epoch));
+ if (r < 0)
+ goto fail;
+
+ r = journal_file_hmac_start(f);
+ if (r < 0)
+ goto fail;
+
+ if (last_tag == 0) {
+ r = journal_file_hmac_put_header(f);
+ if (r < 0)
+ goto fail;
+
+ q = le64toh(f->header->header_size);
+ } else
+ q = last_tag;
+
+ while (q <= p) {
+ r = journal_file_move_to_object(f, -1, q, &o);
+ if (r < 0)
+ goto fail;
+
+ r = journal_file_hmac_put_object(f, -1, q);
+ if (r < 0)
+ goto fail;
+
+ q = q + ALIGN64(le64toh(o->object.size));
+ }
+
+ /* Position might have changed, let's reposition things */
+ r = journal_file_move_to_object(f, -1, p, &o);
+ if (r < 0)
+ goto fail;
+
+ if (memcmp(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH) != 0) {
+ log_error("Tag did not authenticate at %llu", (unsigned long long) p);
+ r = -EBADMSG;
+ goto fail;
+ }
+
+ f->hmac_running = false;
+
+ last_tag = p + ALIGN64(le64toh(o->object.size));
n_tags ++;
break;
+ }
default:
n_weird ++;
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
index 25e441b..f0654fe 100644
--- a/src/journal/journalctl.c
+++ b/src/journal/journalctl.c
@@ -60,6 +60,7 @@ static bool arg_this_boot = false;
static const char *arg_directory = NULL;
static int arg_priorities = 0xFF;
static const char *arg_verify_seed = NULL;
+static usec_t arg_evolve = DEFAULT_FSPRG_INTERVAL_USEC;
static enum {
ACTION_SHOW,
@@ -73,26 +74,27 @@ static int help(void) {
printf("%s [OPTIONS...] [MATCH]\n\n"
"Send control commands to or query the journal.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " --no-pager Do not pipe output into a pager\n"
- " -a --all Show all fields, including long and unprintable\n"
- " -f --follow Follow journal\n"
- " -n --lines=INTEGER Journal entries to show\n"
- " --no-tail Show all lines, even in follow mode\n"
- " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
- " verbose, export, json, cat)\n"
- " -q --quiet Don't show privilege warning\n"
- " -l --local Only local entries\n"
- " -b --this-boot Show data only from current boot\n"
- " -D --directory=PATH Show journal files from directory\n"
- " -p --priority=RANGE Show only messages within the specified priority range\n\n"
+ " -h --help Show this help\n"
+ " --version Show package version\n"
+ " --no-pager Do not pipe output into a pager\n"
+ " -a --all Show all fields, including long and unprintable\n"
+ " -f --follow Follow journal\n"
+ " -n --lines=INTEGER Journal entries to show\n"
+ " --no-tail Show all lines, even in follow mode\n"
+ " -o --output=STRING Change journal output mode (short, short-monotonic,\n"
+ " verbose, export, json, cat)\n"
+ " -q --quiet Don't show privilege warning\n"
+ " -l --local Only local entries\n"
+ " -b --this-boot Show data only from current boot\n"
+ " -D --directory=PATH Show journal files from directory\n"
+ " -p --priority=RANGE Show only messages within the specified priority range\n\n"
"Commands:\n"
- " --new-id128 Generate a new 128 Bit ID\n"
- " --header Show journal header information\n"
- " --verify Verify journal file consistency\n"
- " --verify-seed=SEED Specify FSPRG seed for verification\n"
- " --setup-keys Generate new FSPRG key and seed\n",
+ " --new-id128 Generate a new 128 Bit ID\n"
+ " --header Show journal header information\n"
+ " --verify Verify journal file consistency\n"
+ " --verify-seed=SEED Specify FSPRG seed for verification\n"
+ " --setup-keys Generate new FSPRG key and seed\n"
+ " --evolve=TIME How of to evolve FSPRG keys\n",
program_invocation_short_name);
return 0;
@@ -108,7 +110,8 @@ static int parse_argv(int argc, char *argv[]) {
ARG_HEADER,
ARG_SETUP_KEYS,
ARG_VERIFY,
- ARG_VERIFY_SEED
+ ARG_VERIFY_SEED,
+ ARG_EVOLVE
};
static const struct option options[] = {
@@ -130,6 +133,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "setup-keys", no_argument, NULL, ARG_SETUP_KEYS },
{ "verify", no_argument, NULL, ARG_VERIFY },
{ "verify-seed", required_argument, NULL, ARG_VERIFY_SEED },
+ { "evolve", required_argument, NULL, ARG_EVOLVE },
{ NULL, 0, NULL, 0 }
};
@@ -222,6 +226,14 @@ static int parse_argv(int argc, char *argv[]) {
arg_verify_seed = optarg;
break;
+ case ARG_EVOLVE:
+ r = parse_usec(optarg, &arg_evolve);
+ if (r < 0 || arg_evolve <= 0) {
+ log_error("Failed to parse evolve interval: %s", optarg);
+ return -EINVAL;
+ }
+ break;
+
case 'p': {
const char *dots;
@@ -445,7 +457,7 @@ static int setup_keys(void) {
sd_id128_t machine, boot;
char *p = NULL, *k = NULL;
struct FSPRGHeader h;
- uint64_t n, interval;
+ uint64_t n;
r = sd_id128_get_machine(&machine);
if (r < 0) {
@@ -505,9 +517,8 @@ static int setup_keys(void) {
log_info("Generating evolving key...");
FSPRG_GenState0(state, mpk, seed, seed_size);
- interval = DEFAULT_FSPRG_INTERVAL_USEC;
n = now(CLOCK_REALTIME);
- n /= interval;
+ n /= arg_evolve;
close_nointr_nofail(fd);
fd = mkostemp(k, O_WRONLY|O_CLOEXEC|O_NOCTTY);
@@ -522,8 +533,8 @@ static int setup_keys(void) {
h.machine_id = machine;
h.boot_id = boot;
h.header_size = htole64(sizeof(h));
- h.fsprg_start_usec = htole64(n * interval);
- h.fsprg_interval_usec = htole64(interval);
+ h.fsprg_start_usec = htole64(n * arg_evolve);
+ h.fsprg_interval_usec = htole64(arg_evolve);
h.secpar = htole16(FSPRG_RECOMMENDED_SECPAR);
h.state_size = htole64(state_size);
@@ -567,7 +578,7 @@ static int setup_keys(void) {
printf("%02x", ((uint8_t*) seed)[i]);
}
- printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) interval);
+ printf("/%llx-%llx\n", (unsigned long long) n, (unsigned long long) arg_evolve);
if (isatty(STDOUT_FILENO))
fputs(ANSI_HIGHLIGHT_OFF "\n", stderr);
diff --git a/src/journal/test-journal-verify.c b/src/journal/test-journal-verify.c
index bada498..8a7d998 100644
--- a/src/journal/test-journal-verify.c
+++ b/src/journal/test-journal-verify.c
@@ -35,6 +35,7 @@ int main(int argc, char *argv[]) {
char t[] = "/tmp/journal-XXXXXX";
unsigned n;
JournalFile *f;
+ const char *verification_key = argv[1];
log_set_max_level(LOG_DEBUG);
@@ -43,7 +44,7 @@ int main(int argc, char *argv[]) {
log_info("Generating...");
- assert_se(journal_file_open("test.journal", O_RDWR|O_CREAT, 0666, true, true, NULL, NULL, NULL, &f) == 0);
+ assert_se(journal_file_open("test.journal", O_RDWR|O_CREAT, 0666, true, !!verification_key, NULL, NULL, NULL, &f) == 0);
for (n = 0; n < N_ENTRIES; n++) {
struct iovec iovec;
@@ -67,7 +68,7 @@ int main(int argc, char *argv[]) {
log_info("Verifying...");
assert_se(journal_file_open("test.journal", O_RDONLY, 0666, false, false, NULL, NULL, NULL, &f) == 0);
- assert_se(journal_file_verify(f, NULL) >= 0);
+ assert_se(journal_file_verify(f, verification_key) >= 0);
journal_file_close(f);
log_info("Exiting...");
commit a8e5f51484ba832e299a38f2a54e455e445d2896
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Aug 16 21:22:11 2012 +0200
journal: fix tag sequence number verification
diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c
index 6871433..94f90b6 100644
--- a/src/journal/journal-verify.c
+++ b/src/journal/journal-verify.c
@@ -650,8 +650,8 @@ static int journal_file_parse_seed(JournalFile *f, const char *s) {
int journal_file_verify(JournalFile *f, const char *seed) {
int r;
Object *o;
- uint64_t p = 0;
- uint64_t tag_seqnum = 0, entry_seqnum = 0, entry_monotonic = 0, entry_realtime = 0;
+ uint64_t p = 0, last_tag = 0;
+ uint64_t n_tags = 0, entry_seqnum = 0, entry_monotonic = 0, entry_realtime = 0;
sd_id128_t entry_boot_id;
bool entry_seqnum_set = false, entry_monotonic_set = false, entry_realtime_set = false, found_main_entry_array = false;
uint64_t n_weird = 0, n_objects = 0, n_entries = 0, n_data = 0, n_fields = 0, n_data_hash_tables = 0, n_field_hash_tables = 0, n_entry_arrays = 0;
@@ -698,12 +698,6 @@ int journal_file_verify(JournalFile *f, const char *seed) {
/* First iteration: we go through all objects, verify the
* superficial structure, headers, hashes. */
- r = journal_file_hmac_put_header(f);
- if (r < 0) {
- log_error("Failed to calculate HMAC of header.");
- goto fail;
- }
-
p = le64toh(f->header->header_size);
while (p != 0) {
draw_progress(0x7FFF * p / le64toh(f->header->tail_object_offset), &last_usec);
@@ -735,28 +729,21 @@ int journal_file_verify(JournalFile *f, const char *seed) {
goto fail;
}
- r = journal_file_hmac_put_object(f, -1, p);
- if (r < 0) {
- log_error("Failed to calculate HMAC at %llu", (unsigned long long) p);
- goto fail;
- }
+ switch (o->object.type) {
- if (o->object.type == OBJECT_TAG) {
-
- if (!(le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_AUTHENTICATED)) {
- log_error("Tag object without authentication at %llu", (unsigned long long) p);
- r = -EBADMSG;
+ case OBJECT_DATA:
+ r = write_uint64(data_fd, p);
+ if (r < 0)
goto fail;
- }
- if (le64toh(o->tag.seqnum) != tag_seqnum) {
- log_error("Tag sequence number out of synchronization at %llu", (unsigned long long) p);
- r = -EBADMSG;
- goto fail;
- }
+ n_data++;
+ break;
- } else if (o->object.type == OBJECT_ENTRY) {
+ case OBJECT_FIELD:
+ n_fields++;
+ break;
+ case OBJECT_ENTRY:
r = write_uint64(entry_fd, p);
if (r < 0)
goto fail;
@@ -801,37 +788,9 @@ int journal_file_verify(JournalFile *f, const char *seed) {
entry_realtime_set = true;
n_entries ++;
- } else if (o->object.type == OBJECT_ENTRY_ARRAY) {
-
- r = write_uint64(entry_array_fd, p);
- if (r < 0)
- goto fail;
-
- if (p == le64toh(f->header->entry_array_offset)) {
- if (found_main_entry_array) {
- log_error("More than one main entry array at %llu", (unsigned long long) p);
- r = -EBADMSG;
- goto fail;
- }
-
- found_main_entry_array = true;
- }
-
- n_entry_arrays++;
-
- } else if (o->object.type == OBJECT_DATA) {
-
- r = write_uint64(data_fd, p);
- if (r < 0)
- goto fail;
-
- n_data++;
-
- } else if (o->object.type == OBJECT_FIELD)
- n_fields++;
- else if (o->object.type == OBJECT_DATA_HASH_TABLE) {
- n_data_hash_tables++;
+ break;
+ case OBJECT_DATA_HASH_TABLE:
if (n_data_hash_tables > 1) {
log_error("More than one data hash table at %llu", (unsigned long long) p);
r = -EBADMSG;
@@ -844,9 +803,11 @@ int journal_file_verify(JournalFile *f, const char *seed) {
r = -EBADMSG;
goto fail;
}
- } else if (o->object.type == OBJECT_FIELD_HASH_TABLE) {
- n_field_hash_tables++;
+ n_data_hash_tables++;
+ break;
+
+ case OBJECT_FIELD_HASH_TABLE:
if (n_field_hash_tables > 1) {
log_error("More than one field hash table at %llu", (unsigned long long) p);
r = -EBADMSG;
@@ -859,8 +820,47 @@ int journal_file_verify(JournalFile *f, const char *seed) {
r = -EBADMSG;
goto fail;
}
- } else if (o->object.type >= _OBJECT_TYPE_MAX)
+
+ n_field_hash_tables++;
+ break;
+
+ case OBJECT_ENTRY_ARRAY:
+ r = write_uint64(entry_array_fd, p);
+ if (r < 0)
+ goto fail;
+
+ if (p == le64toh(f->header->entry_array_offset)) {
+ if (found_main_entry_array) {
+ log_error("More than one main entry array at %llu", (unsigned long long) p);
+ r = -EBADMSG;
+ goto fail;
+ }
+
+ found_main_entry_array = true;
+ }
+
+ n_entry_arrays++;
+ break;
+
+ case OBJECT_TAG:
+ if (!(le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_AUTHENTICATED)) {
+ log_error("Tag object without authentication at %llu", (unsigned long long) p);
+ r = -EBADMSG;
+ goto fail;
+ }
+
+ if (le64toh(o->tag.seqnum) != n_tags + 1) {
+ log_error("Tag sequence number out of synchronization at %llu", (unsigned long long) p);
+ r = -EBADMSG;
+ goto fail;
+ }
+
+ n_tags ++;
+ break;
+
+ default:
n_weird ++;
+ }
if (p == le64toh(f->header->tail_object_offset))
p = 0;
@@ -895,7 +895,7 @@ int journal_file_verify(JournalFile *f, const char *seed) {
}
if (JOURNAL_HEADER_CONTAINS(f->header, n_tags) &&
- tag_seqnum != le64toh(f->header->n_tags)) {
+ n_tags != le64toh(f->header->n_tags)) {
log_error("Tag number mismatch");
r = -EBADMSG;
goto fail;
More information about the systemd-commits
mailing list