journal-authenticate.c revision 4da416aa20b956571d74720bc91222881443e24b
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering/***
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering This file is part of systemd.
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering Copyright 2012 Lennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering systemd is free software; you can redistribute it and/or modify it
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering under the terms of the GNU Lesser General Public License as published by
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering (at your option) any later version.
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering systemd is distributed in the hope that it will be useful, but
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering Lesser General Public License for more details.
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering You should have received a copy of the GNU Lesser General Public License
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering***/
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering#include <fcntl.h>
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering#include <sys/mman.h>
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering#include "journal-def.h"
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering#include "journal-file.h"
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering#include "journal-authenticate.h"
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering#include "fsprg.h"
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic void *fsprg_state(JournalFile *f) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering uint64_t a, b;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert(f);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (!f->authenticate)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return NULL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering a = le64toh(f->fsprg_header->header_size);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering b = le64toh(f->fsprg_header->state_size);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (a + b > f->fsprg_size)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return NULL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return (uint8_t*) f->fsprg_header + a;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering}
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic uint64_t journal_file_tag_seqnum(JournalFile *f) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering uint64_t r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert(f);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = le64toh(f->header->n_tags) + 1;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering f->header->n_tags = htole64(r);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering}
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringint journal_file_append_tag(JournalFile *f) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering Object *o;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering uint64_t p;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering int r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert(f);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (!f->authenticate)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (!f->hmac_running)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering log_debug("Writing tag for epoch %llu\n", (unsigned long long) FSPRG_GetEpoch(fsprg_state(f)));
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert(f->hmac);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = journal_file_append_object(f, OBJECT_TAG, sizeof(struct TagObject), &o, &p);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering o->tag.seqnum = htole64(journal_file_tag_seqnum(f));
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering /* Add the tag object itself, so that we can protect its
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering * header. This will exclude the actual hash value in it */
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = journal_file_hmac_put_object(f, OBJECT_TAG, p);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering /* Get the HMAC tag and store it in the object */
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering memcpy(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering f->hmac_running = false;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering}
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic int journal_file_hmac_start(JournalFile *f) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering uint8_t key[256 / 8]; /* Let's pass 256 bit from FSPRG to HMAC */
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert(f);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (!f->authenticate)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (f->hmac_running)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering /* Prepare HMAC for next cycle */
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering gcry_md_reset(f->hmac);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering FSPRG_GetKey(fsprg_state(f), key, sizeof(key), 0);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering gcry_md_setkey(f->hmac, key, sizeof(key));
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering f->hmac_running = true;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering}
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic int journal_file_get_epoch(JournalFile *f, uint64_t realtime, uint64_t *epoch) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering uint64_t t;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert(f);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert(epoch);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert(f->authenticate);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (le64toh(f->fsprg_header->fsprg_start_usec) == 0 ||
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering le64toh(f->fsprg_header->fsprg_interval_usec) == 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return -ENOTSUP;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (realtime < le64toh(f->fsprg_header->fsprg_start_usec))
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return -ESTALE;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering t = realtime - le64toh(f->fsprg_header->fsprg_start_usec);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering t = t / le64toh(f->fsprg_header->fsprg_interval_usec);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering *epoch = t;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering}
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic int journal_file_need_evolve(JournalFile *f, uint64_t realtime) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering uint64_t goal, epoch;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering int r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert(f);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (!f->authenticate)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = journal_file_get_epoch(f, realtime, &goal);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering epoch = FSPRG_GetEpoch(fsprg_state(f));
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (epoch > goal)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return -ESTALE;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return epoch != goal;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering}
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringstatic int journal_file_evolve(JournalFile *f, uint64_t realtime) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering uint64_t goal, epoch;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering int r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert(f);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (!f->authenticate)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = journal_file_get_epoch(f, realtime, &goal);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering epoch = FSPRG_GetEpoch(fsprg_state(f));
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (epoch < goal)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering log_debug("Evolving FSPRG key from epoch %llu to %llu.", (unsigned long long) epoch, (unsigned long long) goal);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering for (;;) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (epoch > goal)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return -ESTALE;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (epoch == goal)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering FSPRG_Evolve(fsprg_state(f));
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering epoch = FSPRG_GetEpoch(fsprg_state(f));
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering}
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringint journal_file_maybe_append_tag(JournalFile *f, uint64_t realtime) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering int r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert(f);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (!f->authenticate)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = journal_file_need_evolve(f, realtime);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r <= 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = journal_file_append_tag(f);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = journal_file_evolve(f, realtime);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = journal_file_hmac_start(f);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering}
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringint journal_file_hmac_put_object(JournalFile *f, int type, uint64_t p) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering int r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering Object *o;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert(f);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (!f->authenticate)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = journal_file_hmac_start(f);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = journal_file_move_to_object(f, type, p, &o);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering gcry_md_write(f->hmac, o, offsetof(ObjectHeader, payload));
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering switch (o->object.type) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering case OBJECT_DATA:
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering /* All but: hash and payload are mutable */
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering gcry_md_write(f->hmac, &o->data.hash, sizeof(o->data.hash));
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering gcry_md_write(f->hmac, o->data.payload, le64toh(o->object.size) - offsetof(DataObject, payload));
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering break;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering case OBJECT_ENTRY:
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering /* All */
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering gcry_md_write(f->hmac, &o->entry.seqnum, le64toh(o->object.size) - offsetof(EntryObject, seqnum));
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering break;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering case OBJECT_FIELD_HASH_TABLE:
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering case OBJECT_DATA_HASH_TABLE:
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering case OBJECT_ENTRY_ARRAY:
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering /* Nothing: everything is mutable */
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering break;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering case OBJECT_TAG:
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering /* All but the tag itself */
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering gcry_md_write(f->hmac, &o->tag.seqnum, sizeof(o->tag.seqnum));
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering break;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering default:
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return -EINVAL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering}
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringint journal_file_hmac_put_header(JournalFile *f) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering int r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert(f);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (!f->authenticate)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = journal_file_hmac_start(f);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering /* All but state+reserved, boot_id, arena_size,
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering * tail_object_offset, n_objects, n_entries, tail_seqnum,
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering * head_entry_realtime, tail_entry_realtime,
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering * tail_entry_monotonic, n_data, n_fields, header_tag */
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering gcry_md_write(f->hmac, f->header->signature, offsetof(Header, state) - offsetof(Header, signature));
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering gcry_md_write(f->hmac, &f->header->file_id, offsetof(Header, boot_id) - offsetof(Header, file_id));
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering gcry_md_write(f->hmac, &f->header->seqnum_id, offsetof(Header, arena_size) - offsetof(Header, seqnum_id));
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering gcry_md_write(f->hmac, &f->header->data_hash_table_offset, offsetof(Header, tail_object_offset) - offsetof(Header, data_hash_table_offset));
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering gcry_md_write(f->hmac, &f->header->head_entry_seqnum, offsetof(Header, head_entry_realtime) - offsetof(Header, head_entry_seqnum));
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering}
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringint journal_file_load_fsprg(JournalFile *f) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering int r, fd = -1;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering char *p = NULL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering struct stat st;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering FSPRGHeader *m = NULL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering sd_id128_t machine;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering assert(f);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (!f->authenticate)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = sd_id128_get_machine(&machine);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (asprintf(&p, "/var/log/journal/" SD_ID128_FORMAT_STR "/fsprg",
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering SD_ID128_FORMAT_VAL(machine)) < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return -ENOMEM;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY, 0600);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (fd < 0) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering log_error("Failed to open %s: %m", p);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = -errno;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering goto finish;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (fstat(fd, &st) < 0) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = -errno;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering goto finish;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (st.st_size < (off_t) sizeof(FSPRGHeader)) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = -ENODATA;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering goto finish;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering m = mmap(NULL, PAGE_ALIGN(sizeof(FSPRGHeader)), PROT_READ, MAP_SHARED, fd, 0);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (m == MAP_FAILED) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering m = NULL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = -errno;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering goto finish;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (memcmp(m->signature, FSPRG_HEADER_SIGNATURE, 8) != 0) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = -EBADMSG;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering goto finish;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (m->incompatible_flags != 0) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = -EPROTONOSUPPORT;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering goto finish;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (le64toh(m->header_size) < sizeof(FSPRGHeader)) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = -EBADMSG;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering goto finish;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (le64toh(m->state_size) != FSPRG_stateinbytes(m->secpar)) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = -EBADMSG;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering goto finish;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering f->fsprg_size = le64toh(m->header_size) + le64toh(m->state_size);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if ((uint64_t) st.st_size < f->fsprg_size) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = -ENODATA;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering goto finish;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (!sd_id128_equal(machine, m->machine_id)) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = -EHOSTDOWN;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering goto finish;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (le64toh(m->fsprg_start_usec) <= 0 ||
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering le64toh(m->fsprg_interval_usec) <= 0) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = -EBADMSG;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering goto finish;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering f->fsprg_header = mmap(NULL, PAGE_ALIGN(f->fsprg_size), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (f->fsprg_header == MAP_FAILED) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering f->fsprg_header = NULL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = -errno;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering goto finish;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering }
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringfinish:
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (m)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering munmap(m, PAGE_ALIGN(sizeof(FSPRGHeader)));
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (fd >= 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering close_nointr_nofail(fd);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering free(p);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering}
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringint journal_file_setup_hmac(JournalFile *f) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering gcry_error_t e;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (!f->authenticate)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering e = gcry_md_open(&f->hmac, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (e != 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return -ENOTSUP;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering}
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poetteringint journal_file_append_first_tag(JournalFile *f) {
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering int r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering uint64_t p;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (!f->authenticate)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering log_debug("Calculating first tag...");
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = journal_file_hmac_put_header(f);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering p = le64toh(f->header->field_hash_table_offset);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (p < offsetof(Object, hash_table.items))
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return -EINVAL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering p -= offsetof(Object, hash_table.items);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = journal_file_hmac_put_object(f, OBJECT_FIELD_HASH_TABLE, p);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering p = le64toh(f->header->data_hash_table_offset);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (p < offsetof(Object, hash_table.items))
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return -EINVAL;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering p -= offsetof(Object, hash_table.items);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = journal_file_hmac_put_object(f, OBJECT_DATA_HASH_TABLE, p);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering r = journal_file_append_tag(f);
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering if (r < 0)
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return r;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering return 0;
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering}
4da416aa20b956571d74720bc91222881443e24bLennart Poettering
4da416aa20b956571d74720bc91222881443e24bLennart Poetteringbool journal_file_fsprg_enabled(JournalFile *f) {
4da416aa20b956571d74720bc91222881443e24bLennart Poettering assert(f);
4da416aa20b956571d74720bc91222881443e24bLennart Poettering
4da416aa20b956571d74720bc91222881443e24bLennart Poettering return !!(le32toh(f->header->compatible_flags) & HEADER_COMPATIBLE_AUTHENTICATED);
4da416aa20b956571d74720bc91222881443e24bLennart Poettering}