/* * Copyright (c) 2008 Vreixo Formoso * * This file is part of the libisofs project; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. See COPYING file for details. */ #include "../libisofs.h" #include "../filter.h" #include "../fsource.h" /* * A simple Filter implementation for example purposes. It encrypts a file * by XORing each byte by a given key. */ static ino_t xor_ino_id = 0; typedef struct { IsoStream *orig; uint8_t key; ino_t id; } XorEncryptStreamData; static int xor_encrypt_stream_open(IsoStream *stream) { XorEncryptStreamData *data; if (stream == NULL) { return ISO_NULL_POINTER; } data = (XorEncryptStreamData*)stream->data; return iso_stream_open(data->orig); } static int xor_encrypt_stream_close(IsoStream *stream) { XorEncryptStreamData *data; if (stream == NULL) { return ISO_NULL_POINTER; } data = stream->data; return iso_stream_close(data->orig); } static off_t xor_encrypt_stream_get_size(IsoStream *stream) { XorEncryptStreamData *data; if (stream == NULL) { return ISO_NULL_POINTER; } data = stream->data; return iso_stream_get_size(data->orig); } static int xor_encrypt_stream_read(IsoStream *stream, void *buf, size_t count) { int ret, len; XorEncryptStreamData *data; uint8_t *buffer = buf; if (stream == NULL) { return ISO_NULL_POINTER; } data = stream->data; ret = iso_stream_read(data->orig, buf, count); if (ret < 0) { return ret; } /* xor */ for (len = 0; len < ret; ++len) { buffer[len] = buffer[len] ^ data->key; } return ret; } static int xor_encrypt_stream_is_repeatable(IsoStream *stream) { /* the filter can't be created if underlying stream is not repeatable */ return 1; } static void xor_encrypt_stream_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id, ino_t *ino_id) { XorEncryptStreamData *data = stream->data; *fs_id = ISO_FILTER_FS_ID; *dev_id = XOR_ENCRYPT_DEV_ID; *ino_id = data->id; } static void xor_encrypt_stream_free(IsoStream *stream) { XorEncryptStreamData *data = stream->data; iso_stream_unref(data->orig); free(data); } IsoStreamIface xor_encrypt_stream_class = { 0, "xorf", xor_encrypt_stream_open, xor_encrypt_stream_close, xor_encrypt_stream_get_size, xor_encrypt_stream_read, xor_encrypt_stream_is_repeatable, xor_encrypt_stream_get_id, xor_encrypt_stream_free }; static void xor_encrypt_filter_free(FilterContext *filter) { free(filter->data); } static int xor_encrypt_filter_get_filter(FilterContext *filter, IsoStream *original, IsoStream **filtered) { IsoStream *str; XorEncryptStreamData *data; if (filter == NULL || original == NULL || filtered == NULL) { return ISO_NULL_POINTER; } str = malloc(sizeof(IsoStream)); if (str == NULL) { return ISO_OUT_OF_MEM; } data = malloc(sizeof(XorEncryptStreamData)); if (str == NULL) { free(str); return ISO_OUT_OF_MEM; } /* fill data */ data->key = *((uint8_t*)filter->data); data->id = xor_ino_id++; /* get reference to the source */ data->orig = original; iso_stream_ref(original); str->refcount = 1; str->data = data; str->class = &xor_encrypt_stream_class; *filtered = str; return ISO_SUCCESS; } int create_xor_encrypt_filter(uint8_t key, FilterContext **filter) { FilterContext *f; uint8_t *data; f = calloc(1, sizeof(FilterContext)); if (f == NULL) { return ISO_OUT_OF_MEM; } data = malloc(sizeof(uint8_t)); if (data == NULL) { free(f); return ISO_OUT_OF_MEM; } f->refcount = 1; f->version = 0; *data = key; f->data = data; f->free = xor_encrypt_filter_free; f->get_filter = xor_encrypt_filter_get_filter; return ISO_SUCCESS; }