2
* Copyright (C) 2006 International Business Machines
3
* Written by Michael A. Halcrow <mhalcrow@us.ibm.com>
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License as
7
* published by the Free Software Foundation; either version 2 of the
8
* License, or (at your option) any later version.
10
* This program is distributed in the hope that it will be useful, but
11
* WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
26
#include <sys/types.h>
34
printf("ASSERTION FAILED: %s at %s:%d (%s)\n", #EX, \
35
__FILE__, __LINE__, __FUNCTION__); \
39
struct ecryptfs_crypt_stat {
40
int header_extent_size;
41
int num_header_extents_at_front;
46
ecryptfs_extent_to_lwr_pg_idx_and_offset(unsigned long *lower_page_idx,
48
struct ecryptfs_crypt_stat *crypt_stat,
49
unsigned long extent_num,
52
unsigned long lower_extent_num;
53
int extents_occupied_by_headers_at_front;
54
int bytes_occupied_by_headers_at_front;
58
bytes_occupied_by_headers_at_front =
59
( crypt_stat->header_extent_size
60
* crypt_stat->num_header_extents_at_front );
61
extents_occupied_by_headers_at_front =
62
( bytes_occupied_by_headers_at_front
63
/ crypt_stat->extent_size );
64
lower_extent_num = extents_occupied_by_headers_at_front + extent_num;
65
extents_per_page = page_size / crypt_stat->extent_size;
66
(*lower_page_idx) = lower_extent_num / extents_per_page;
67
extent_offset = lower_extent_num % extents_per_page;
68
(*byte_offset) = extent_offset * crypt_stat->extent_size;
71
struct translation_test_vector_element {
73
unsigned long header_extent_size;
74
int num_header_extents_at_front;
75
unsigned long extent_num;
76
unsigned long lower_page_idx;
80
#define ECRYPTFS_EXTENT_SIZE 4096 /* Test vector only valid for 4096 */
82
struct translation_test_vector_element translation_test_vector[] = {
83
{4096, 8192, 1, 0, 2, 0},
84
{4096, 8192, 1, 1, 3, 0},
85
{4096, 8192, 1, 2, 4, 0},
86
{4096, 8192, 1, 3, 5, 0},
87
{8192, 8192, 1, 0, 1, 0},
88
{8192, 8192, 1, 1, 1, 4096},
89
{8192, 8192, 1, 2, 2, 0},
90
{8192, 8192, 1, 3, 2, 4096},
91
{8192, 8192, 1, 4, 3, 0},
92
{16384, 8192, 1, 0, 0, 8192},
93
{16384, 8192, 1, 1, 0, 12288},
94
{16384, 8192, 1, 2, 1, 0},
95
{16384, 8192, 1, 3, 1, 4096},
96
{16384, 8192, 1, 4, 1, 8192},
97
{16384, 8192, 1, 5, 1, 12288},
98
{16384, 8192, 1, 6, 2, 0},
101
int test_extent_translation(void)
103
struct ecryptfs_crypt_stat crypt_stat;
104
unsigned long lower_page_idx;
109
printf("Testing ecryptfs_extent_to_lwr_pg_idx_and_offset()... ");
110
crypt_stat.extent_size = ECRYPTFS_EXTENT_SIZE;
112
i < (sizeof(translation_test_vector)
113
/ sizeof(struct translation_test_vector_element));
115
crypt_stat.header_extent_size =
116
translation_test_vector[i].header_extent_size;
117
crypt_stat.num_header_extents_at_front =
118
translation_test_vector[i].num_header_extents_at_front;
119
ecryptfs_extent_to_lwr_pg_idx_and_offset(
120
&lower_page_idx, &byte_offset, &crypt_stat,
121
translation_test_vector[i].extent_num,
122
translation_test_vector[i].page_size);
124
!= translation_test_vector[i].lower_page_idx) {
126
printf("\nError on test vector entry [%d]; "
127
"lower_page_idx = [%lu]\n", i, lower_page_idx);
131
!= translation_test_vector[i].byte_offset) {
133
printf("\nError on test vector entry [%d]; "
134
"byte offset = [%d]\n", i, byte_offset);
155
struct writeback_control {
158
struct ecryptfs_page_crypt_context {
160
#define ECRYPTFS_PREPARE_COMMIT_MODE 0
161
#define ECRYPTFS_WRITEPAGE_MODE 1
164
struct file *lower_file;
165
struct writeback_control *wbc;
169
void ecryptfs_unmap_and_release_lower_page(struct page *lower_page)
171
printf("%s: Called w/ lower_page = [%p]\n", __FUNCTION__, lower_page);
176
ecryptfs_commit_lower_page(struct page *lower_page, struct inode *lower_inode,
177
struct file *lower_file, int byte_offset,
182
printf("%s: Called w/ lower_page = [%p], lower_inode = [%p], "
183
"lower_file = [%p], byte_offset = [%d], region_size = [%d]\n",
185
lower_page, lower_inode, lower_file, byte_offset, region_size);
186
ecryptfs_unmap_and_release_lower_page(lower_page);
190
int ecryptfs_writepage_and_release_lower_page(struct page *lower_page,
191
struct inode *lower_inode,
192
struct writeback_control *wbc)
194
printf("%s: Called w/ lower_page = [%p], lower_inode = [%p], wbc = "
195
"[%p]\n", __FUNCTION__, lower_page, lower_inode, wbc);
199
int ecryptfs_write_out_page(struct ecryptfs_page_crypt_context *ctx,
200
struct page *lower_page, struct inode *lower_inode,
201
int byte_offset_in_page, int bytes_to_write)
205
rc = ecryptfs_commit_lower_page(lower_page, lower_inode,
212
int ecryptfs_get_lower_page(struct page **lower_page, struct inode *lower_inode,
213
struct file *lower_file,
214
unsigned long lower_page_index, int byte_offset,
217
printf("%s: Called w/ **lower_page = [%p], lower_inode = [%p], "
218
"lower_file = [%p], lower_page_index = [%lu], byte_offset = "
219
"[%d], region_bytes = [%d]\n", __FUNCTION__, lower_page,
220
lower_inode, lower_file, lower_page_index, byte_offset,
222
printf("[Call to prepare_write]\n");
223
(*lower_page) = (struct page *)malloc(sizeof(struct page));
224
(*lower_page)->index = lower_page_index;
228
int ecryptfs_read_in_page(struct ecryptfs_page_crypt_context *ctx,
229
struct page **lower_page, struct inode *lower_inode,
230
unsigned long lower_page_idx, int byte_offset_in_page,
235
printf("%s: Called w/ **lower_page = [%p], lower_inode = [%p]; "
237
"= [%lu], byte_offset_in_page = [%d]\n", __FUNCTION__,
238
lower_page, lower_inode,
239
lower_page_idx, byte_offset_in_page);
240
rc = ecryptfs_get_lower_page(lower_page, lower_inode,
245
- byte_offset_in_page));
249
int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat,
250
unsigned long offset)
252
printf("%s: Called w/ offset = [%lu]\n", __FUNCTION__, offset);
257
ecryptfs_encrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat,
258
struct page *dst_page, int dst_offset,
259
struct page *src_page, int src_offset, int size,
262
printf("%s: Called:\n * dst_page->index = [%lu]\n * dst_offset = [%d]\n"
263
" * src_page->index = [%lu]\n * src_offset = [%d]\n",
264
__FUNCTION__, dst_page->index, dst_offset, src_page->index,
269
#define ECRYPTFS_MAX_IV_BYTES 16
271
int ecryptfs_encrypt_page(int page_cache_size, int extent_size,
272
struct page *page, int header_extent_size,
273
int num_header_extents_at_front)
275
char extent_iv[ECRYPTFS_MAX_IV_BYTES];
276
unsigned long base_extent;
277
unsigned long extent_offset = 0;
278
unsigned long lower_page_idx = 0;
279
unsigned long prior_lower_page_idx = 0;
280
struct page *lower_page;
281
struct inode *lower_inode;
282
struct ecryptfs_crypt_stat *crypt_stat;
284
int lower_byte_offset;
285
int orig_byte_offset;
286
int num_extents_per_page;
287
#define ECRYPTFS_PAGE_STATE_UNREAD 0
288
#define ECRYPTFS_PAGE_STATE_READ 1
289
#define ECRYPTFS_PAGE_STATE_MODIFIED 2
290
#define ECRYPTFS_PAGE_STATE_WRITTEN 3
293
crypt_stat = (struct ecryptfs_crypt_stat *)malloc(
294
sizeof(struct ecryptfs_crypt_stat));
299
crypt_stat->extent_size = extent_size;
300
crypt_stat->header_extent_size = header_extent_size;
301
crypt_stat->num_header_extents_at_front = num_header_extents_at_front;
304
num_extents_per_page = page_cache_size / crypt_stat->extent_size;
305
base_extent = (page->index * num_extents_per_page);
306
page_state = ECRYPTFS_PAGE_STATE_UNREAD;
307
while (extent_offset < num_extents_per_page) {
308
ecryptfs_extent_to_lwr_pg_idx_and_offset(
309
&lower_page_idx, &lower_byte_offset, crypt_stat,
310
(base_extent + extent_offset), page_cache_size);
311
if (prior_lower_page_idx != lower_page_idx
312
&& page_state == ECRYPTFS_PAGE_STATE_MODIFIED) {
313
rc = ecryptfs_write_out_page(NULL, lower_page,
317
- orig_byte_offset));
318
page_state = ECRYPTFS_PAGE_STATE_WRITTEN;
320
if (page_state == ECRYPTFS_PAGE_STATE_UNREAD
321
|| page_state == ECRYPTFS_PAGE_STATE_WRITTEN) {
322
rc = ecryptfs_read_in_page(NULL, &lower_page,
323
lower_inode, lower_page_idx,
326
orig_byte_offset = lower_byte_offset;
327
prior_lower_page_idx = lower_page_idx;
328
page_state = ECRYPTFS_PAGE_STATE_READ;
330
ASSERT(page_state == ECRYPTFS_PAGE_STATE_MODIFIED
331
|| page_state == ECRYPTFS_PAGE_STATE_READ);
332
rc = ecryptfs_derive_iv(extent_iv, crypt_stat,
333
(base_extent + extent_offset));
334
rc = ecryptfs_encrypt_page_offset(
335
crypt_stat, lower_page, lower_byte_offset, page,
336
(extent_offset * crypt_stat->extent_size),
337
crypt_stat->extent_size, extent_iv);
338
page_state = ECRYPTFS_PAGE_STATE_MODIFIED;
341
ASSERT(orig_byte_offset == 0);
342
rc = ecryptfs_write_out_page(NULL, lower_page, lower_inode, 0,
344
+ crypt_stat->extent_size));
351
int test_encrypt(void)
357
/* int ecryptfs_encrypt_page(int page_cache_size, int extent_size,
358
struct page *page, int header_extent_size,
359
int num_header_extents_at_front) */
360
rc = ecryptfs_encrypt_page(16384, /* page_cache_size */
361
4096, /* extent_size */
363
8192, /* header size */
364
1); /* num_headers */
369
upper_size_to_lower_size(struct ecryptfs_crypt_stat *crypt_stat,
370
unsigned long upper_size)
372
unsigned long lower_size;
374
lower_size = ( crypt_stat->header_extent_size
375
* crypt_stat->num_header_extents_at_front );
376
if (upper_size != 0) {
377
unsigned long num_extents;
379
num_extents = upper_size / crypt_stat->extent_size;
380
if (upper_size % crypt_stat->extent_size)
382
lower_size += (num_extents * crypt_stat->extent_size);
387
struct upper_lower_test_vector_element {
388
unsigned long header_extent_size;
389
int num_header_extents_at_front;
391
unsigned long upper_size;
392
unsigned long lower_size;
395
struct upper_lower_test_vector_element upper_lower_test_vector[] = {
396
{8192, 1, 4096, 0, 8192},
397
{8192, 1, 4096, 1, 12288},
398
{8192, 1, 4096, 2, 12288},
399
{8192, 1, 4096, 4094, 12288},
400
{8192, 1, 4096, 4095, 12288},
401
{8192, 1, 4096, 4096, 12288},
402
{8192, 1, 4096, 4097, 16384},
403
{8192, 1, 4096, 4098, 16384},
404
{8192, 1, 4096, 8191, 16384},
405
{8192, 1, 4096, 8192, 16384},
406
{8192, 1, 4096, 8193, 20480}
409
int test_upper_size_to_lower_size(void)
412
unsigned long lower_size;
413
struct ecryptfs_crypt_stat crypt_stat;
417
i < (sizeof(upper_lower_test_vector)
418
/ sizeof(struct upper_lower_test_vector_element));
420
crypt_stat.header_extent_size =
421
upper_lower_test_vector[i].header_extent_size;
422
crypt_stat.num_header_extents_at_front =
423
upper_lower_test_vector[i].num_header_extents_at_front;
424
crypt_stat.extent_size = upper_lower_test_vector[i].extent_size;
425
lower_size = upper_size_to_lower_size(
426
&crypt_stat, upper_lower_test_vector[i].upper_size);
427
if (lower_size != upper_lower_test_vector[i].lower_size) {
428
printf("Unexpected lower size [%lu] for upper size "
429
"[%lu]\n", lower_size,
430
upper_lower_test_vector[i].upper_size);
439
int test_nv_list_from_file(void)
442
struct ecryptfs_name_val_pair nv_pair_head;
443
struct ecryptfs_name_val_pair nv_pair_head_2;
444
struct ecryptfs_name_val_pair *cursor;
447
nv_pair_head.next = NULL;
448
fd = open("ecryptfsrc", O_RDONLY);
453
rc = parse_options_file(fd, &nv_pair_head);
455
cursor = nv_pair_head.next;
457
printf("cursor->name = [%s]\n", cursor->name);
458
printf("cursor->value = [%s]\n\n", cursor->value);
459
cursor = cursor->next;
469
rc = test_nv_list_from_file();
471
rc = test_extent_translation();
477
rc = test_upper_size_to_lower_size();