123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659 |
- /**
- * eCryptfs: Linux filesystem encryption layer
- *
- * Copyright (C) 1997-2004 Erez Zadok
- * Copyright (C) 2001-2004 Stony Brook University
- * Copyright (C) 2004-2006 International Business Machines Corp.
- * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
- * Michael C. Thompson <mcthomps@us.ibm.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- */
- #include <linux/fs.h>
- #include <linux/mount.h>
- #include <linux/pagemap.h>
- #include <linux/random.h>
- #include <linux/compiler.h>
- #include <linux/key.h>
- #include <linux/namei.h>
- #include <linux/crypto.h>
- #include <linux/file.h>
- #include <linux/scatterlist.h>
- #include "ecryptfs_kernel.h"
- static int
- ecryptfs_decrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat,
- struct page *dst_page, int dst_offset,
- struct page *src_page, int src_offset, int size,
- unsigned char *iv);
- static int
- ecryptfs_encrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat,
- struct page *dst_page, int dst_offset,
- struct page *src_page, int src_offset, int size,
- unsigned char *iv);
- /**
- * ecryptfs_to_hex
- * @dst: Buffer to take hex character representation of contents of
- * src; must be at least of size (src_size * 2)
- * @src: Buffer to be converted to a hex string respresentation
- * @src_size: number of bytes to convert
- */
- void ecryptfs_to_hex(char *dst, char *src, size_t src_size)
- {
- int x;
- for (x = 0; x < src_size; x++)
- sprintf(&dst[x * 2], "%.2x", (unsigned char)src[x]);
- }
- /**
- * ecryptfs_from_hex
- * @dst: Buffer to take the bytes from src hex; must be at least of
- * size (src_size / 2)
- * @src: Buffer to be converted from a hex string respresentation to raw value
- * @dst_size: size of dst buffer, or number of hex characters pairs to convert
- */
- void ecryptfs_from_hex(char *dst, char *src, int dst_size)
- {
- int x;
- char tmp[3] = { 0, };
- for (x = 0; x < dst_size; x++) {
- tmp[0] = src[x * 2];
- tmp[1] = src[x * 2 + 1];
- dst[x] = (unsigned char)simple_strtol(tmp, NULL, 16);
- }
- }
- /**
- * ecryptfs_calculate_md5 - calculates the md5 of @src
- * @dst: Pointer to 16 bytes of allocated memory
- * @crypt_stat: Pointer to crypt_stat struct for the current inode
- * @src: Data to be md5'd
- * @len: Length of @src
- *
- * Uses the allocated crypto context that crypt_stat references to
- * generate the MD5 sum of the contents of src.
- */
- static int ecryptfs_calculate_md5(char *dst,
- struct ecryptfs_crypt_stat *crypt_stat,
- char *src, int len)
- {
- int rc = 0;
- struct scatterlist sg;
- mutex_lock(&crypt_stat->cs_md5_tfm_mutex);
- sg_init_one(&sg, (u8 *)src, len);
- if (!crypt_stat->md5_tfm) {
- crypt_stat->md5_tfm =
- crypto_alloc_tfm("md5", CRYPTO_TFM_REQ_MAY_SLEEP);
- if (!crypt_stat->md5_tfm) {
- rc = -ENOMEM;
- ecryptfs_printk(KERN_ERR, "Error attempting to "
- "allocate crypto context\n");
- goto out;
- }
- }
- crypto_digest_init(crypt_stat->md5_tfm);
- crypto_digest_update(crypt_stat->md5_tfm, &sg, 1);
- crypto_digest_final(crypt_stat->md5_tfm, dst);
- mutex_unlock(&crypt_stat->cs_md5_tfm_mutex);
- out:
- return rc;
- }
- /**
- * ecryptfs_derive_iv
- * @iv: destination for the derived iv vale
- * @crypt_stat: Pointer to crypt_stat struct for the current inode
- * @offset: Offset of the page whose's iv we are to derive
- *
- * Generate the initialization vector from the given root IV and page
- * offset.
- *
- * Returns zero on success; non-zero on error.
- */
- static int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat,
- pgoff_t offset)
- {
- int rc = 0;
- char dst[MD5_DIGEST_SIZE];
- char src[ECRYPTFS_MAX_IV_BYTES + 16];
- if (unlikely(ecryptfs_verbosity > 0)) {
- ecryptfs_printk(KERN_DEBUG, "root iv:\n");
- ecryptfs_dump_hex(crypt_stat->root_iv, crypt_stat->iv_bytes);
- }
- /* TODO: It is probably secure to just cast the least
- * significant bits of the root IV into an unsigned long and
- * add the offset to that rather than go through all this
- * hashing business. -Halcrow */
- memcpy(src, crypt_stat->root_iv, crypt_stat->iv_bytes);
- memset((src + crypt_stat->iv_bytes), 0, 16);
- snprintf((src + crypt_stat->iv_bytes), 16, "%ld", offset);
- if (unlikely(ecryptfs_verbosity > 0)) {
- ecryptfs_printk(KERN_DEBUG, "source:\n");
- ecryptfs_dump_hex(src, (crypt_stat->iv_bytes + 16));
- }
- rc = ecryptfs_calculate_md5(dst, crypt_stat, src,
- (crypt_stat->iv_bytes + 16));
- if (rc) {
- ecryptfs_printk(KERN_WARNING, "Error attempting to compute "
- "MD5 while generating IV for a page\n");
- goto out;
- }
- memcpy(iv, dst, crypt_stat->iv_bytes);
- if (unlikely(ecryptfs_verbosity > 0)) {
- ecryptfs_printk(KERN_DEBUG, "derived iv:\n");
- ecryptfs_dump_hex(iv, crypt_stat->iv_bytes);
- }
- out:
- return rc;
- }
- /**
- * ecryptfs_init_crypt_stat
- * @crypt_stat: Pointer to the crypt_stat struct to initialize.
- *
- * Initialize the crypt_stat structure.
- */
- void
- ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat)
- {
- memset((void *)crypt_stat, 0, sizeof(struct ecryptfs_crypt_stat));
- mutex_init(&crypt_stat->cs_mutex);
- mutex_init(&crypt_stat->cs_tfm_mutex);
- mutex_init(&crypt_stat->cs_md5_tfm_mutex);
- ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_STRUCT_INITIALIZED);
- }
- /**
- * ecryptfs_destruct_crypt_stat
- * @crypt_stat: Pointer to the crypt_stat struct to initialize.
- *
- * Releases all memory associated with a crypt_stat struct.
- */
- void ecryptfs_destruct_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat)
- {
- if (crypt_stat->tfm)
- crypto_free_tfm(crypt_stat->tfm);
- if (crypt_stat->md5_tfm)
- crypto_free_tfm(crypt_stat->md5_tfm);
- memset(crypt_stat, 0, sizeof(struct ecryptfs_crypt_stat));
- }
- void ecryptfs_destruct_mount_crypt_stat(
- struct ecryptfs_mount_crypt_stat *mount_crypt_stat)
- {
- if (mount_crypt_stat->global_auth_tok_key)
- key_put(mount_crypt_stat->global_auth_tok_key);
- if (mount_crypt_stat->global_key_tfm)
- crypto_free_tfm(mount_crypt_stat->global_key_tfm);
- memset(mount_crypt_stat, 0, sizeof(struct ecryptfs_mount_crypt_stat));
- }
- /**
- * virt_to_scatterlist
- * @addr: Virtual address
- * @size: Size of data; should be an even multiple of the block size
- * @sg: Pointer to scatterlist array; set to NULL to obtain only
- * the number of scatterlist structs required in array
- * @sg_size: Max array size
- *
- * Fills in a scatterlist array with page references for a passed
- * virtual address.
- *
- * Returns the number of scatterlist structs in array used
- */
- int virt_to_scatterlist(const void *addr, int size, struct scatterlist *sg,
- int sg_size)
- {
- int i = 0;
- struct page *pg;
- int offset;
- int remainder_of_page;
- while (size > 0 && i < sg_size) {
- pg = virt_to_page(addr);
- offset = offset_in_page(addr);
- if (sg) {
- sg[i].page = pg;
- sg[i].offset = offset;
- }
- remainder_of_page = PAGE_CACHE_SIZE - offset;
- if (size >= remainder_of_page) {
- if (sg)
- sg[i].length = remainder_of_page;
- addr += remainder_of_page;
- size -= remainder_of_page;
- } else {
- if (sg)
- sg[i].length = size;
- addr += size;
- size = 0;
- }
- i++;
- }
- if (size > 0)
- return -ENOMEM;
- return i;
- }
- /**
- * encrypt_scatterlist
- * @crypt_stat: Pointer to the crypt_stat struct to initialize.
- * @dest_sg: Destination of encrypted data
- * @src_sg: Data to be encrypted
- * @size: Length of data to be encrypted
- * @iv: iv to use during encryption
- *
- * Returns the number of bytes encrypted; negative value on error
- */
- static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat,
- struct scatterlist *dest_sg,
- struct scatterlist *src_sg, int size,
- unsigned char *iv)
- {
- int rc = 0;
- BUG_ON(!crypt_stat || !crypt_stat->tfm
- || !ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
- ECRYPTFS_STRUCT_INITIALIZED));
- if (unlikely(ecryptfs_verbosity > 0)) {
- ecryptfs_printk(KERN_DEBUG, "Key size [%d]; key:\n",
- crypt_stat->key_size);
- ecryptfs_dump_hex(crypt_stat->key,
- crypt_stat->key_size);
- }
- /* Consider doing this once, when the file is opened */
- mutex_lock(&crypt_stat->cs_tfm_mutex);
- rc = crypto_cipher_setkey(crypt_stat->tfm, crypt_stat->key,
- crypt_stat->key_size);
- if (rc) {
- ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n",
- rc);
- mutex_unlock(&crypt_stat->cs_tfm_mutex);
- rc = -EINVAL;
- goto out;
- }
- ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes.\n", size);
- crypto_cipher_encrypt_iv(crypt_stat->tfm, dest_sg, src_sg, size, iv);
- mutex_unlock(&crypt_stat->cs_tfm_mutex);
- out:
- return rc;
- }
- static void
- ecryptfs_extent_to_lwr_pg_idx_and_offset(unsigned long *lower_page_idx,
- int *byte_offset,
- struct ecryptfs_crypt_stat *crypt_stat,
- unsigned long extent_num)
- {
- unsigned long lower_extent_num;
- int extents_occupied_by_headers_at_front;
- int bytes_occupied_by_headers_at_front;
- int extent_offset;
- int extents_per_page;
- bytes_occupied_by_headers_at_front =
- ( crypt_stat->header_extent_size
- * crypt_stat->num_header_extents_at_front );
- extents_occupied_by_headers_at_front =
- ( bytes_occupied_by_headers_at_front
- / crypt_stat->extent_size );
- lower_extent_num = extents_occupied_by_headers_at_front + extent_num;
- extents_per_page = PAGE_CACHE_SIZE / crypt_stat->extent_size;
- (*lower_page_idx) = lower_extent_num / extents_per_page;
- extent_offset = lower_extent_num % extents_per_page;
- (*byte_offset) = extent_offset * crypt_stat->extent_size;
- ecryptfs_printk(KERN_DEBUG, " * crypt_stat->header_extent_size = "
- "[%d]\n", crypt_stat->header_extent_size);
- ecryptfs_printk(KERN_DEBUG, " * crypt_stat->"
- "num_header_extents_at_front = [%d]\n",
- crypt_stat->num_header_extents_at_front);
- ecryptfs_printk(KERN_DEBUG, " * extents_occupied_by_headers_at_"
- "front = [%d]\n", extents_occupied_by_headers_at_front);
- ecryptfs_printk(KERN_DEBUG, " * lower_extent_num = [0x%.16x]\n",
- lower_extent_num);
- ecryptfs_printk(KERN_DEBUG, " * extents_per_page = [%d]\n",
- extents_per_page);
- ecryptfs_printk(KERN_DEBUG, " * (*lower_page_idx) = [0x%.16x]\n",
- (*lower_page_idx));
- ecryptfs_printk(KERN_DEBUG, " * extent_offset = [%d]\n",
- extent_offset);
- ecryptfs_printk(KERN_DEBUG, " * (*byte_offset) = [%d]\n",
- (*byte_offset));
- }
- static int ecryptfs_write_out_page(struct ecryptfs_page_crypt_context *ctx,
- struct page *lower_page,
- struct inode *lower_inode,
- int byte_offset_in_page, int bytes_to_write)
- {
- int rc = 0;
- if (ctx->mode == ECRYPTFS_PREPARE_COMMIT_MODE) {
- rc = ecryptfs_commit_lower_page(lower_page, lower_inode,
- ctx->param.lower_file,
- byte_offset_in_page,
- bytes_to_write);
- if (rc) {
- ecryptfs_printk(KERN_ERR, "Error calling lower "
- "commit; rc = [%d]\n", rc);
- goto out;
- }
- } else {
- rc = ecryptfs_writepage_and_release_lower_page(lower_page,
- lower_inode,
- ctx->param.wbc);
- if (rc) {
- ecryptfs_printk(KERN_ERR, "Error calling lower "
- "writepage(); rc = [%d]\n", rc);
- goto out;
- }
- }
- out:
- return rc;
- }
- static int ecryptfs_read_in_page(struct ecryptfs_page_crypt_context *ctx,
- struct page **lower_page,
- struct inode *lower_inode,
- unsigned long lower_page_idx,
- int byte_offset_in_page)
- {
- int rc = 0;
- if (ctx->mode == ECRYPTFS_PREPARE_COMMIT_MODE) {
- /* TODO: Limit this to only the data extents that are
- * needed */
- rc = ecryptfs_get_lower_page(lower_page, lower_inode,
- ctx->param.lower_file,
- lower_page_idx,
- byte_offset_in_page,
- (PAGE_CACHE_SIZE
- - byte_offset_in_page));
- if (rc) {
- ecryptfs_printk(
- KERN_ERR, "Error attempting to grab, map, "
- "and prepare_write lower page with index "
- "[0x%.16x]; rc = [%d]\n", lower_page_idx, rc);
- goto out;
- }
- } else {
- rc = ecryptfs_grab_and_map_lower_page(lower_page, NULL,
- lower_inode,
- lower_page_idx);
- if (rc) {
- ecryptfs_printk(
- KERN_ERR, "Error attempting to grab and map "
- "lower page with index [0x%.16x]; rc = [%d]\n",
- lower_page_idx, rc);
- goto out;
- }
- }
- out:
- return rc;
- }
- /**
- * ecryptfs_encrypt_page
- * @ctx: The context of the page
- *
- * Encrypt an eCryptfs page. This is done on a per-extent basis. Note
- * that eCryptfs pages may straddle the lower pages -- for instance,
- * if the file was created on a machine with an 8K page size
- * (resulting in an 8K header), and then the file is copied onto a
- * host with a 32K page size, then when reading page 0 of the eCryptfs
- * file, 24K of page 0 of the lower file will be read and decrypted,
- * and then 8K of page 1 of the lower file will be read and decrypted.
- *
- * The actual operations performed on each page depends on the
- * contents of the ecryptfs_page_crypt_context struct.
- *
- * Returns zero on success; negative on error
- */
- int ecryptfs_encrypt_page(struct ecryptfs_page_crypt_context *ctx)
- {
- char extent_iv[ECRYPTFS_MAX_IV_BYTES];
- unsigned long base_extent;
- unsigned long extent_offset = 0;
- unsigned long lower_page_idx = 0;
- unsigned long prior_lower_page_idx = 0;
- struct page *lower_page;
- struct inode *lower_inode;
- struct ecryptfs_inode_info *inode_info;
- struct ecryptfs_crypt_stat *crypt_stat;
- int rc = 0;
- int lower_byte_offset = 0;
- int orig_byte_offset = 0;
- int num_extents_per_page;
- #define ECRYPTFS_PAGE_STATE_UNREAD 0
- #define ECRYPTFS_PAGE_STATE_READ 1
- #define ECRYPTFS_PAGE_STATE_MODIFIED 2
- #define ECRYPTFS_PAGE_STATE_WRITTEN 3
- int page_state;
- lower_inode = ecryptfs_inode_to_lower(ctx->page->mapping->host);
- inode_info = ecryptfs_inode_to_private(ctx->page->mapping->host);
- crypt_stat = &inode_info->crypt_stat;
- if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED)) {
- rc = ecryptfs_copy_page_to_lower(ctx->page, lower_inode,
- ctx->param.lower_file);
- if (rc)
- ecryptfs_printk(KERN_ERR, "Error attempting to copy "
- "page at index [0x%.16x]\n",
- ctx->page->index);
- goto out;
- }
- num_extents_per_page = PAGE_CACHE_SIZE / crypt_stat->extent_size;
- base_extent = (ctx->page->index * num_extents_per_page);
- page_state = ECRYPTFS_PAGE_STATE_UNREAD;
- while (extent_offset < num_extents_per_page) {
- ecryptfs_extent_to_lwr_pg_idx_and_offset(
- &lower_page_idx, &lower_byte_offset, crypt_stat,
- (base_extent + extent_offset));
- if (prior_lower_page_idx != lower_page_idx
- && page_state == ECRYPTFS_PAGE_STATE_MODIFIED) {
- rc = ecryptfs_write_out_page(ctx, lower_page,
- lower_inode,
- orig_byte_offset,
- (PAGE_CACHE_SIZE
- - orig_byte_offset));
- if (rc) {
- ecryptfs_printk(KERN_ERR, "Error attempting "
- "to write out page; rc = [%d]"
- "\n", rc);
- goto out;
- }
- page_state = ECRYPTFS_PAGE_STATE_WRITTEN;
- }
- if (page_state == ECRYPTFS_PAGE_STATE_UNREAD
- || page_state == ECRYPTFS_PAGE_STATE_WRITTEN) {
- rc = ecryptfs_read_in_page(ctx, &lower_page,
- lower_inode, lower_page_idx,
- lower_byte_offset);
- if (rc) {
- ecryptfs_printk(KERN_ERR, "Error attempting "
- "to read in lower page with "
- "index [0x%.16x]; rc = [%d]\n",
- lower_page_idx, rc);
- goto out;
- }
- orig_byte_offset = lower_byte_offset;
- prior_lower_page_idx = lower_page_idx;
- page_state = ECRYPTFS_PAGE_STATE_READ;
- }
- BUG_ON(!(page_state == ECRYPTFS_PAGE_STATE_MODIFIED
- || page_state == ECRYPTFS_PAGE_STATE_READ));
- rc = ecryptfs_derive_iv(extent_iv, crypt_stat,
- (base_extent + extent_offset));
- if (rc) {
- ecryptfs_printk(KERN_ERR, "Error attempting to "
- "derive IV for extent [0x%.16x]; "
- "rc = [%d]\n",
- (base_extent + extent_offset), rc);
- goto out;
- }
- if (unlikely(ecryptfs_verbosity > 0)) {
- ecryptfs_printk(KERN_DEBUG, "Encrypting extent "
- "with iv:\n");
- ecryptfs_dump_hex(extent_iv, crypt_stat->iv_bytes);
- ecryptfs_printk(KERN_DEBUG, "First 8 bytes before "
- "encryption:\n");
- ecryptfs_dump_hex((char *)
- (page_address(ctx->page)
- + (extent_offset
- * crypt_stat->extent_size)), 8);
- }
- rc = ecryptfs_encrypt_page_offset(
- crypt_stat, lower_page, lower_byte_offset, ctx->page,
- (extent_offset * crypt_stat->extent_size),
- crypt_stat->extent_size, extent_iv);
- ecryptfs_printk(KERN_DEBUG, "Encrypt extent [0x%.16x]; "
- "rc = [%d]\n",
- (base_extent + extent_offset), rc);
- if (unlikely(ecryptfs_verbosity > 0)) {
- ecryptfs_printk(KERN_DEBUG, "First 8 bytes after "
- "encryption:\n");
- ecryptfs_dump_hex((char *)(page_address(lower_page)
- + lower_byte_offset), 8);
- }
- page_state = ECRYPTFS_PAGE_STATE_MODIFIED;
- extent_offset++;
- }
- BUG_ON(orig_byte_offset != 0);
- rc = ecryptfs_write_out_page(ctx, lower_page, lower_inode, 0,
- (lower_byte_offset
- + crypt_stat->extent_size));
- if (rc) {
- ecryptfs_printk(KERN_ERR, "Error attempting to write out "
- "page; rc = [%d]\n", rc);
- goto out;
- }
- out:
- return rc;
- }
- /**
- * ecryptfs_decrypt_page
- * @file: The ecryptfs file
- * @page: The page in ecryptfs to decrypt
- *
- * Decrypt an eCryptfs page. This is done on a per-extent basis. Note
- * that eCryptfs pages may straddle the lower pages -- for instance,
- * if the file was created on a machine with an 8K page size
- * (resulting in an 8K header), and then the file is copied onto a
- * host with a 32K page size, then when reading page 0 of the eCryptfs
- * file, 24K of page 0 of the lower file will be read and decrypted,
- * and then 8K of page 1 of the lower file will be read and decrypted.
- *
- * Returns zero on success; negative on error
- */
- int ecryptfs_decrypt_page(struct file *file, struct page *page)
- {
- char extent_iv[ECRYPTFS_MAX_IV_BYTES];
- unsigned long base_extent;
- unsigned long extent_offset = 0;
- unsigned long lower_page_idx = 0;
- unsigned long prior_lower_page_idx = 0;
- struct page *lower_page;
- char *lower_page_virt = NULL;
- struct inode *lower_inode;
- struct ecryptfs_crypt_stat *crypt_stat;
- int rc = 0;
- int byte_offset;
- int num_extents_per_page;
- int page_state;
- crypt_stat = &(ecryptfs_inode_to_private(
- page->mapping->host)->crypt_stat);
- lower_inode = ecryptfs_inode_to_lower(page->mapping->host);
- if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED)) {
- rc = ecryptfs_do_readpage(file, page, page->index);
- if (rc)
- ecryptfs_printk(KERN_ERR, "Error attempting to copy "
- "page at index [0x%.16x]\n",
- page->index);
- goto out;
- }
- num_extents_per_page = PAGE_CACHE_SIZE / crypt_stat->extent_size;
- base_extent = (page->index * num_extents_per_page);
- lower_page_virt = kmem_cache_alloc(ecryptfs_lower_page_cache,
- SLAB_KERNEL);
- if (!lower_page_virt) {
- rc = -ENOMEM;
- ecryptfs_printk(KERN_ERR, "Error getting page for encrypted "
- "lower page(s)\n");
- goto out;
- }
- lower_page = virt_to_page(lower_page_virt);
- page_state = ECRYPTFS_PAGE_STATE_UNREAD;
- while (extent_offset < num_extents_per_page) {
- ecryptfs_extent_to_lwr_pg_idx_and_offset(
- &lower_page_idx, &byte_offset, crypt_stat,
- (base_extent + extent_offset));
- if (prior_lower_page_idx != lower_page_idx
- || page_state == ECRYPTFS_PAGE_STATE_UNREAD) {
- rc = ecryptfs_do_readpage(file, lower_page,
- lower_page_idx);
- if (rc) {
- ecryptfs_printk(KERN_ERR, "Error reading "
- "lower encrypted page; rc = "
- "[%d]\n", rc);
- goto out;
- }
- prior_lower_page_idx = lower_page_idx;
- page_state = ECRYPTFS_PAGE_STATE_READ;
- }
- rc = ecryptfs_derive_iv(extent_iv, crypt_stat,
- (base_extent + extent_offset));
- if (rc) {
- ecryptfs_printk(KERN_ERR, "Error attempting to "
- "derive IV for extent [0x%.16x]; rc = "
- "[%d]\n",
- (base_extent + extent_offset), rc);
- goto out;
- }
- if (unlikely(ecryptfs_verbosity > 0)) {
- ecryptfs_printk(KERN_DEBUG, "Decrypting extent "
- "with iv:\n");
- ecryptfs_dump_hex(extent_iv, crypt_stat->iv_bytes);
- ecryptfs_printk(KERN_DEBUG, "First 8 bytes before "
- "decryption:\n");
- ecryptfs_dump_hex((lower_page_virt + byte_offset), 8);
- }
- rc = ecryptfs_decrypt_page_offset(crypt_stat, page,
- (extent_offset
- * crypt_stat->extent_size),
- lower_page, byte_offset,
- crypt_stat->extent_size,
- extent_iv);
- if (rc != crypt_stat->extent_size) {
- ecryptfs_printk(KERN_ERR, "Error attempting to "
- "decrypt extent [0x%.16x]\n",
- (base_extent + extent_offset));
- goto out;
- }
- rc = 0;
- if (unlikely(ecryptfs_verbosity > 0)) {
- ecryptfs_printk(KERN_DEBUG, "First 8 bytes after "
- "decryption:\n");
- ecryptfs_dump_hex((char *)(page_address(page)
- + byte_offset), 8);
- }
- extent_offset++;
- }
- out:
- if (lower_page_virt)
- kmem_cache_free(ecryptfs_lower_page_cache, lower_page_virt);
- return rc;
- }
- /**
- * decrypt_scatterlist
- *
- * Returns the number of bytes decrypted; negative value on error
- */
- static int decrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat,
- struct scatterlist *dest_sg,
- struct scatterlist *src_sg, int size,
- unsigned char *iv)
- {
- int rc = 0;
- /* Consider doing this once, when the file is opened */
- mutex_lock(&crypt_stat->cs_tfm_mutex);
- rc = crypto_cipher_setkey(crypt_stat->tfm, crypt_stat->key,
- crypt_stat->key_size);
- if (rc) {
- ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n",
- rc);
- mutex_unlock(&crypt_stat->cs_tfm_mutex);
- rc = -EINVAL;
- goto out;
- }
- ecryptfs_printk(KERN_DEBUG, "Decrypting [%d] bytes.\n", size);
- rc = crypto_cipher_decrypt_iv(crypt_stat->tfm, dest_sg, src_sg, size,
- iv);
- mutex_unlock(&crypt_stat->cs_tfm_mutex);
- if (rc) {
- ecryptfs_printk(KERN_ERR, "Error decrypting; rc = [%d]\n",
- rc);
- goto out;
- }
- rc = size;
- out:
- return rc;
- }
- /**
- * ecryptfs_encrypt_page_offset
- *
- * Returns the number of bytes encrypted
- */
- static int
- ecryptfs_encrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat,
- struct page *dst_page, int dst_offset,
- struct page *src_page, int src_offset, int size,
- unsigned char *iv)
- {
- struct scatterlist src_sg, dst_sg;
- src_sg.page = src_page;
- src_sg.offset = src_offset;
- src_sg.length = size;
- dst_sg.page = dst_page;
- dst_sg.offset = dst_offset;
- dst_sg.length = size;
- return encrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv);
- }
- /**
- * ecryptfs_decrypt_page_offset
- *
- * Returns the number of bytes decrypted
- */
- static int
- ecryptfs_decrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat,
- struct page *dst_page, int dst_offset,
- struct page *src_page, int src_offset, int size,
- unsigned char *iv)
- {
- struct scatterlist src_sg, dst_sg;
- src_sg.page = src_page;
- src_sg.offset = src_offset;
- src_sg.length = size;
- dst_sg.page = dst_page;
- dst_sg.offset = dst_offset;
- dst_sg.length = size;
- return decrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv);
- }
- #define ECRYPTFS_MAX_SCATTERLIST_LEN 4
- /**
- * ecryptfs_init_crypt_ctx
- * @crypt_stat: Uninitilized crypt stats structure
- *
- * Initialize the crypto context.
- *
- * TODO: Performance: Keep a cache of initialized cipher contexts;
- * only init if needed
- */
- int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat)
- {
- int rc = -EINVAL;
- if (!crypt_stat->cipher) {
- ecryptfs_printk(KERN_ERR, "No cipher specified\n");
- goto out;
- }
- ecryptfs_printk(KERN_DEBUG,
- "Initializing cipher [%s]; strlen = [%d]; "
- "key_size_bits = [%d]\n",
- crypt_stat->cipher, (int)strlen(crypt_stat->cipher),
- crypt_stat->key_size << 3);
- if (crypt_stat->tfm) {
- rc = 0;
- goto out;
- }
- mutex_lock(&crypt_stat->cs_tfm_mutex);
- crypt_stat->tfm = crypto_alloc_tfm(crypt_stat->cipher,
- ECRYPTFS_DEFAULT_CHAINING_MODE
- | CRYPTO_TFM_REQ_WEAK_KEY);
- mutex_unlock(&crypt_stat->cs_tfm_mutex);
- if (!crypt_stat->tfm) {
- ecryptfs_printk(KERN_ERR, "cryptfs: init_crypt_ctx(): "
- "Error initializing cipher [%s]\n",
- crypt_stat->cipher);
- goto out;
- }
- rc = 0;
- out:
- return rc;
- }
- static void set_extent_mask_and_shift(struct ecryptfs_crypt_stat *crypt_stat)
- {
- int extent_size_tmp;
- crypt_stat->extent_mask = 0xFFFFFFFF;
- crypt_stat->extent_shift = 0;
- if (crypt_stat->extent_size == 0)
- return;
- extent_size_tmp = crypt_stat->extent_size;
- while ((extent_size_tmp & 0x01) == 0) {
- extent_size_tmp >>= 1;
- crypt_stat->extent_mask <<= 1;
- crypt_stat->extent_shift++;
- }
- }
- void ecryptfs_set_default_sizes(struct ecryptfs_crypt_stat *crypt_stat)
- {
- /* Default values; may be overwritten as we are parsing the
- * packets. */
- crypt_stat->extent_size = ECRYPTFS_DEFAULT_EXTENT_SIZE;
- set_extent_mask_and_shift(crypt_stat);
- crypt_stat->iv_bytes = ECRYPTFS_DEFAULT_IV_BYTES;
- if (PAGE_CACHE_SIZE <= ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE) {
- crypt_stat->header_extent_size =
- ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE;
- } else
- crypt_stat->header_extent_size = PAGE_CACHE_SIZE;
- crypt_stat->num_header_extents_at_front = 1;
- }
- /**
- * ecryptfs_compute_root_iv
- * @crypt_stats
- *
- * On error, sets the root IV to all 0's.
- */
- int ecryptfs_compute_root_iv(struct ecryptfs_crypt_stat *crypt_stat)
- {
- int rc = 0;
- char dst[MD5_DIGEST_SIZE];
- BUG_ON(crypt_stat->iv_bytes > MD5_DIGEST_SIZE);
- BUG_ON(crypt_stat->iv_bytes <= 0);
- if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID)) {
- rc = -EINVAL;
- ecryptfs_printk(KERN_WARNING, "Session key not valid; "
- "cannot generate root IV\n");
- goto out;
- }
- rc = ecryptfs_calculate_md5(dst, crypt_stat, crypt_stat->key,
- crypt_stat->key_size);
- if (rc) {
- ecryptfs_printk(KERN_WARNING, "Error attempting to compute "
- "MD5 while generating root IV\n");
- goto out;
- }
- memcpy(crypt_stat->root_iv, dst, crypt_stat->iv_bytes);
- out:
- if (rc) {
- memset(crypt_stat->root_iv, 0, crypt_stat->iv_bytes);
- ECRYPTFS_SET_FLAG(crypt_stat->flags,
- ECRYPTFS_SECURITY_WARNING);
- }
- return rc;
- }
- static void ecryptfs_generate_new_key(struct ecryptfs_crypt_stat *crypt_stat)
- {
- get_random_bytes(crypt_stat->key, crypt_stat->key_size);
- ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID);
- ecryptfs_compute_root_iv(crypt_stat);
- if (unlikely(ecryptfs_verbosity > 0)) {
- ecryptfs_printk(KERN_DEBUG, "Generated new session key:\n");
- ecryptfs_dump_hex(crypt_stat->key,
- crypt_stat->key_size);
- }
- }
- /**
- * ecryptfs_set_default_crypt_stat_vals
- * @crypt_stat
- *
- * Default values in the event that policy does not override them.
- */
- static void ecryptfs_set_default_crypt_stat_vals(
- struct ecryptfs_crypt_stat *crypt_stat,
- struct ecryptfs_mount_crypt_stat *mount_crypt_stat)
- {
- ecryptfs_set_default_sizes(crypt_stat);
- strcpy(crypt_stat->cipher, ECRYPTFS_DEFAULT_CIPHER);
- crypt_stat->key_size = ECRYPTFS_DEFAULT_KEY_BYTES;
- ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID);
- crypt_stat->file_version = ECRYPTFS_FILE_VERSION;
- crypt_stat->mount_crypt_stat = mount_crypt_stat;
- }
- /**
- * ecryptfs_new_file_context
- * @ecryptfs_dentry
- *
- * If the crypto context for the file has not yet been established,
- * this is where we do that. Establishing a new crypto context
- * involves the following decisions:
- * - What cipher to use?
- * - What set of authentication tokens to use?
- * Here we just worry about getting enough information into the
- * authentication tokens so that we know that they are available.
- * We associate the available authentication tokens with the new file
- * via the set of signatures in the crypt_stat struct. Later, when
- * the headers are actually written out, we may again defer to
- * userspace to perform the encryption of the session key; for the
- * foreseeable future, this will be the case with public key packets.
- *
- * Returns zero on success; non-zero otherwise
- */
- /* Associate an authentication token(s) with the file */
- int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry)
- {
- int rc = 0;
- struct ecryptfs_crypt_stat *crypt_stat =
- &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat;
- struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
- &ecryptfs_superblock_to_private(
- ecryptfs_dentry->d_sb)->mount_crypt_stat;
- int cipher_name_len;
- ecryptfs_set_default_crypt_stat_vals(crypt_stat, mount_crypt_stat);
- /* See if there are mount crypt options */
- if (mount_crypt_stat->global_auth_tok) {
- ecryptfs_printk(KERN_DEBUG, "Initializing context for new "
- "file using mount_crypt_stat\n");
- ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED);
- ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_KEY_VALID);
- memcpy(crypt_stat->keysigs[crypt_stat->num_keysigs++],
- mount_crypt_stat->global_auth_tok_sig,
- ECRYPTFS_SIG_SIZE_HEX);
- cipher_name_len =
- strlen(mount_crypt_stat->global_default_cipher_name);
- memcpy(crypt_stat->cipher,
- mount_crypt_stat->global_default_cipher_name,
- cipher_name_len);
- crypt_stat->cipher[cipher_name_len] = '\0';
- crypt_stat->key_size =
- mount_crypt_stat->global_default_cipher_key_size;
- ecryptfs_generate_new_key(crypt_stat);
- } else
- /* We should not encounter this scenario since we
- * should detect lack of global_auth_tok at mount time
- * TODO: Applies to 0.1 release only; remove in future
- * release */
- BUG();
- rc = ecryptfs_init_crypt_ctx(crypt_stat);
- if (rc)
- ecryptfs_printk(KERN_ERR, "Error initializing cryptographic "
- "context for cipher [%s]: rc = [%d]\n",
- crypt_stat->cipher, rc);
- return rc;
- }
- /**
- * contains_ecryptfs_marker - check for the ecryptfs marker
- * @data: The data block in which to check
- *
- * Returns one if marker found; zero if not found
- */
- int contains_ecryptfs_marker(char *data)
- {
- u32 m_1, m_2;
- memcpy(&m_1, data, 4);
- m_1 = be32_to_cpu(m_1);
- memcpy(&m_2, (data + 4), 4);
- m_2 = be32_to_cpu(m_2);
- if ((m_1 ^ MAGIC_ECRYPTFS_MARKER) == m_2)
- return 1;
- ecryptfs_printk(KERN_DEBUG, "m_1 = [0x%.8x]; m_2 = [0x%.8x]; "
- "MAGIC_ECRYPTFS_MARKER = [0x%.8x]\n", m_1, m_2,
- MAGIC_ECRYPTFS_MARKER);
- ecryptfs_printk(KERN_DEBUG, "(m_1 ^ MAGIC_ECRYPTFS_MARKER) = "
- "[0x%.8x]\n", (m_1 ^ MAGIC_ECRYPTFS_MARKER));
- return 0;
- }
- struct ecryptfs_flag_map_elem {
- u32 file_flag;
- u32 local_flag;
- };
- /* Add support for additional flags by adding elements here. */
- static struct ecryptfs_flag_map_elem ecryptfs_flag_map[] = {
- {0x00000001, ECRYPTFS_ENABLE_HMAC},
- {0x00000002, ECRYPTFS_ENCRYPTED}
- };
- /**
- * ecryptfs_process_flags
- * @crypt_stat
- * @page_virt: Source data to be parsed
- * @bytes_read: Updated with the number of bytes read
- *
- * Returns zero on success; non-zero if the flag set is invalid
- */
- static int ecryptfs_process_flags(struct ecryptfs_crypt_stat *crypt_stat,
- char *page_virt, int *bytes_read)
- {
- int rc = 0;
- int i;
- u32 flags;
- memcpy(&flags, page_virt, 4);
- flags = be32_to_cpu(flags);
- for (i = 0; i < ((sizeof(ecryptfs_flag_map)
- / sizeof(struct ecryptfs_flag_map_elem))); i++)
- if (flags & ecryptfs_flag_map[i].file_flag) {
- ECRYPTFS_SET_FLAG(crypt_stat->flags,
- ecryptfs_flag_map[i].local_flag);
- } else
- ECRYPTFS_CLEAR_FLAG(crypt_stat->flags,
- ecryptfs_flag_map[i].local_flag);
- /* Version is in top 8 bits of the 32-bit flag vector */
- crypt_stat->file_version = ((flags >> 24) & 0xFF);
- (*bytes_read) = 4;
- return rc;
- }
- /**
- * write_ecryptfs_marker
- * @page_virt: The pointer to in a page to begin writing the marker
- * @written: Number of bytes written
- *
- * Marker = 0x3c81b7f5
- */
- static void write_ecryptfs_marker(char *page_virt, size_t *written)
- {
- u32 m_1, m_2;
- get_random_bytes(&m_1, (MAGIC_ECRYPTFS_MARKER_SIZE_BYTES / 2));
- m_2 = (m_1 ^ MAGIC_ECRYPTFS_MARKER);
- m_1 = cpu_to_be32(m_1);
- memcpy(page_virt, &m_1, (MAGIC_ECRYPTFS_MARKER_SIZE_BYTES / 2));
- m_2 = cpu_to_be32(m_2);
- memcpy(page_virt + (MAGIC_ECRYPTFS_MARKER_SIZE_BYTES / 2), &m_2,
- (MAGIC_ECRYPTFS_MARKER_SIZE_BYTES / 2));
- (*written) = MAGIC_ECRYPTFS_MARKER_SIZE_BYTES;
- }
- static void
- write_ecryptfs_flags(char *page_virt, struct ecryptfs_crypt_stat *crypt_stat,
- size_t *written)
- {
- u32 flags = 0;
- int i;
- for (i = 0; i < ((sizeof(ecryptfs_flag_map)
- / sizeof(struct ecryptfs_flag_map_elem))); i++)
- if (ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
- ecryptfs_flag_map[i].local_flag))
- flags |= ecryptfs_flag_map[i].file_flag;
- /* Version is in top 8 bits of the 32-bit flag vector */
- flags |= ((((u8)crypt_stat->file_version) << 24) & 0xFF000000);
- flags = cpu_to_be32(flags);
- memcpy(page_virt, &flags, 4);
- (*written) = 4;
- }
- struct ecryptfs_cipher_code_str_map_elem {
- char cipher_str[16];
- u16 cipher_code;
- };
- /* Add support for additional ciphers by adding elements here. The
- * cipher_code is whatever OpenPGP applicatoins use to identify the
- * ciphers. List in order of probability. */
- static struct ecryptfs_cipher_code_str_map_elem
- ecryptfs_cipher_code_str_map[] = {
- {"aes",RFC2440_CIPHER_AES_128 },
- {"blowfish", RFC2440_CIPHER_BLOWFISH},
- {"des3_ede", RFC2440_CIPHER_DES3_EDE},
- {"cast5", RFC2440_CIPHER_CAST_5},
- {"twofish", RFC2440_CIPHER_TWOFISH},
- {"cast6", RFC2440_CIPHER_CAST_6},
- {"aes", RFC2440_CIPHER_AES_192},
- {"aes", RFC2440_CIPHER_AES_256}
- };
- /**
- * ecryptfs_code_for_cipher_string
- * @str: The string representing the cipher name
- *
- * Returns zero on no match, or the cipher code on match
- */
- u16 ecryptfs_code_for_cipher_string(struct ecryptfs_crypt_stat *crypt_stat)
- {
- int i;
- u16 code = 0;
- struct ecryptfs_cipher_code_str_map_elem *map =
- ecryptfs_cipher_code_str_map;
- if (strcmp(crypt_stat->cipher, "aes") == 0) {
- switch (crypt_stat->key_size) {
- case 16:
- code = RFC2440_CIPHER_AES_128;
- break;
- case 24:
- code = RFC2440_CIPHER_AES_192;
- break;
- case 32:
- code = RFC2440_CIPHER_AES_256;
- }
- } else {
- for (i = 0; i < ARRAY_SIZE(ecryptfs_cipher_code_str_map); i++)
- if (strcmp(crypt_stat->cipher, map[i].cipher_str) == 0){
- code = map[i].cipher_code;
- break;
- }
- }
- return code;
- }
- /**
- * ecryptfs_cipher_code_to_string
- * @str: Destination to write out the cipher name
- * @cipher_code: The code to convert to cipher name string
- *
- * Returns zero on success
- */
- int ecryptfs_cipher_code_to_string(char *str, u16 cipher_code)
- {
- int rc = 0;
- int i;
- str[0] = '\0';
- for (i = 0; i < ARRAY_SIZE(ecryptfs_cipher_code_str_map); i++)
- if (cipher_code == ecryptfs_cipher_code_str_map[i].cipher_code)
- strcpy(str, ecryptfs_cipher_code_str_map[i].cipher_str);
- if (str[0] == '\0') {
- ecryptfs_printk(KERN_WARNING, "Cipher code not recognized: "
- "[%d]\n", cipher_code);
- rc = -EINVAL;
- }
- return rc;
- }
- /**
- * ecryptfs_read_header_region
- * @data
- * @dentry
- * @nd
- *
- * Returns zero on success; non-zero otherwise
- */
- int ecryptfs_read_header_region(char *data, struct dentry *dentry,
- struct vfsmount *mnt)
- {
- struct file *file;
- mm_segment_t oldfs;
- int rc;
- mnt = mntget(mnt);
- file = dentry_open(dentry, mnt, O_RDONLY);
- if (IS_ERR(file)) {
- ecryptfs_printk(KERN_DEBUG, "Error opening file to "
- "read header region\n");
- mntput(mnt);
- rc = PTR_ERR(file);
- goto out;
- }
- file->f_pos = 0;
- oldfs = get_fs();
- set_fs(get_ds());
- /* For releases 0.1 and 0.2, all of the header information
- * fits in the first data extent-sized region. */
- rc = file->f_op->read(file, (char __user *)data,
- ECRYPTFS_DEFAULT_EXTENT_SIZE, &file->f_pos);
- set_fs(oldfs);
- fput(file);
- rc = 0;
- out:
- return rc;
- }
- static void
- write_header_metadata(char *virt, struct ecryptfs_crypt_stat *crypt_stat,
- size_t *written)
- {
- u32 header_extent_size;
- u16 num_header_extents_at_front;
- header_extent_size = (u32)crypt_stat->header_extent_size;
- num_header_extents_at_front =
- (u16)crypt_stat->num_header_extents_at_front;
- header_extent_size = cpu_to_be32(header_extent_size);
- memcpy(virt, &header_extent_size, 4);
- virt += 4;
- num_header_extents_at_front = cpu_to_be16(num_header_extents_at_front);
- memcpy(virt, &num_header_extents_at_front, 2);
- (*written) = 6;
- }
- struct kmem_cache *ecryptfs_header_cache_0;
- struct kmem_cache *ecryptfs_header_cache_1;
- struct kmem_cache *ecryptfs_header_cache_2;
- /**
- * ecryptfs_write_headers_virt
- * @page_virt
- * @crypt_stat
- * @ecryptfs_dentry
- *
- * Format version: 1
- *
- * Header Extent:
- * Octets 0-7: Unencrypted file size (big-endian)
- * Octets 8-15: eCryptfs special marker
- * Octets 16-19: Flags
- * Octet 16: File format version number (between 0 and 255)
- * Octets 17-18: Reserved
- * Octet 19: Bit 1 (lsb): Reserved
- * Bit 2: Encrypted?
- * Bits 3-8: Reserved
- * Octets 20-23: Header extent size (big-endian)
- * Octets 24-25: Number of header extents at front of file
- * (big-endian)
- * Octet 26: Begin RFC 2440 authentication token packet set
- * Data Extent 0:
- * Lower data (CBC encrypted)
- * Data Extent 1:
- * Lower data (CBC encrypted)
- * ...
- *
- * Returns zero on success
- */
- int ecryptfs_write_headers_virt(char *page_virt,
- struct ecryptfs_crypt_stat *crypt_stat,
- struct dentry *ecryptfs_dentry)
- {
- int rc;
- size_t written;
- size_t offset;
- offset = ECRYPTFS_FILE_SIZE_BYTES;
- write_ecryptfs_marker((page_virt + offset), &written);
- offset += written;
- write_ecryptfs_flags((page_virt + offset), crypt_stat, &written);
- offset += written;
- write_header_metadata((page_virt + offset), crypt_stat, &written);
- offset += written;
- rc = ecryptfs_generate_key_packet_set((page_virt + offset), crypt_stat,
- ecryptfs_dentry, &written,
- PAGE_CACHE_SIZE - offset);
- if (rc)
- ecryptfs_printk(KERN_WARNING, "Error generating key packet "
- "set; rc = [%d]\n", rc);
- return rc;
- }
- /**
- * ecryptfs_write_headers
- * @lower_file: The lower file struct, which was returned from dentry_open
- *
- * Write the file headers out. This will likely involve a userspace
- * callout, in which the session key is encrypted with one or more
- * public keys and/or the passphrase necessary to do the encryption is
- * retrieved via a prompt. Exactly what happens at this point should
- * be policy-dependent.
- *
- * Returns zero on success; non-zero on error
- */
- int ecryptfs_write_headers(struct dentry *ecryptfs_dentry,
- struct file *lower_file)
- {
- mm_segment_t oldfs;
- struct ecryptfs_crypt_stat *crypt_stat;
- char *page_virt;
- int current_header_page;
- int header_pages;
- int rc = 0;
- crypt_stat = &ecryptfs_inode_to_private(
- ecryptfs_dentry->d_inode)->crypt_stat;
- if (likely(ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
- ECRYPTFS_ENCRYPTED))) {
- if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags,
- ECRYPTFS_KEY_VALID)) {
- ecryptfs_printk(KERN_DEBUG, "Key is "
- "invalid; bailing out\n");
- rc = -EINVAL;
- goto out;
- }
- } else {
- rc = -EINVAL;
- ecryptfs_printk(KERN_WARNING,
- "Called with crypt_stat->encrypted == 0\n");
- goto out;
- }
- /* Released in this function */
- page_virt = kmem_cache_alloc(ecryptfs_header_cache_0, SLAB_USER);
- if (!page_virt) {
- ecryptfs_printk(KERN_ERR, "Out of memory\n");
- rc = -ENOMEM;
- goto out;
- }
- memset(page_virt, 0, PAGE_CACHE_SIZE);
- rc = ecryptfs_write_headers_virt(page_virt, crypt_stat,
- ecryptfs_dentry);
- if (unlikely(rc)) {
- ecryptfs_printk(KERN_ERR, "Error whilst writing headers\n");
- memset(page_virt, 0, PAGE_CACHE_SIZE);
- goto out_free;
- }
- ecryptfs_printk(KERN_DEBUG,
- "Writing key packet set to underlying file\n");
- lower_file->f_pos = 0;
- oldfs = get_fs();
- set_fs(get_ds());
- ecryptfs_printk(KERN_DEBUG, "Calling lower_file->f_op->"
- "write() w/ header page; lower_file->f_pos = "
- "[0x%.16x]\n", lower_file->f_pos);
- lower_file->f_op->write(lower_file, (char __user *)page_virt,
- PAGE_CACHE_SIZE, &lower_file->f_pos);
- header_pages = ((crypt_stat->header_extent_size
- * crypt_stat->num_header_extents_at_front)
- / PAGE_CACHE_SIZE);
- memset(page_virt, 0, PAGE_CACHE_SIZE);
- current_header_page = 1;
- while (current_header_page < header_pages) {
- ecryptfs_printk(KERN_DEBUG, "Calling lower_file->f_op->"
- "write() w/ zero'd page; lower_file->f_pos = "
- "[0x%.16x]\n", lower_file->f_pos);
- lower_file->f_op->write(lower_file, (char __user *)page_virt,
- PAGE_CACHE_SIZE, &lower_file->f_pos);
- current_header_page++;
- }
- set_fs(oldfs);
- ecryptfs_printk(KERN_DEBUG,
- "Done writing key packet set to underlying file.\n");
- out_free:
- kmem_cache_free(ecryptfs_header_cache_0, page_virt);
- out:
- return rc;
- }
- static int parse_header_metadata(struct ecryptfs_crypt_stat *crypt_stat,
- char *virt, int *bytes_read)
- {
- int rc = 0;
- u32 header_extent_size;
- u16 num_header_extents_at_front;
- memcpy(&header_extent_size, virt, 4);
- header_extent_size = be32_to_cpu(header_extent_size);
- virt += 4;
- memcpy(&num_header_extents_at_front, virt, 2);
- num_header_extents_at_front = be16_to_cpu(num_header_extents_at_front);
- crypt_stat->header_extent_size = (int)header_extent_size;
- crypt_stat->num_header_extents_at_front =
- (int)num_header_extents_at_front;
- (*bytes_read) = 6;
- if ((crypt_stat->header_extent_size
- * crypt_stat->num_header_extents_at_front)
- < ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE) {
- rc = -EINVAL;
- ecryptfs_printk(KERN_WARNING, "Invalid header extent size: "
- "[%d]\n", crypt_stat->header_extent_size);
- }
- return rc;
- }
- /**
- * set_default_header_data
- *
- * For version 0 file format; this function is only for backwards
- * compatibility for files created with the prior versions of
- * eCryptfs.
- */
- static void set_default_header_data(struct ecryptfs_crypt_stat *crypt_stat)
- {
- crypt_stat->header_extent_size = 4096;
- crypt_stat->num_header_extents_at_front = 1;
- }
- /**
- * ecryptfs_read_headers_virt
- *
- * Read/parse the header data. The header format is detailed in the
- * comment block for the ecryptfs_write_headers_virt() function.
- *
- * Returns zero on success
- */
- static int ecryptfs_read_headers_virt(char *page_virt,
- struct ecryptfs_crypt_stat *crypt_stat,
- struct dentry *ecryptfs_dentry)
- {
- int rc = 0;
- int offset;
- int bytes_read;
- ecryptfs_set_default_sizes(crypt_stat);
- crypt_stat->mount_crypt_stat = &ecryptfs_superblock_to_private(
- ecryptfs_dentry->d_sb)->mount_crypt_stat;
- offset = ECRYPTFS_FILE_SIZE_BYTES;
- rc = contains_ecryptfs_marker(page_virt + offset);
- if (rc == 0) {
- rc = -EINVAL;
- goto out;
- }
- offset += MAGIC_ECRYPTFS_MARKER_SIZE_BYTES;
- rc = ecryptfs_process_flags(crypt_stat, (page_virt + offset),
- &bytes_read);
- if (rc) {
- ecryptfs_printk(KERN_WARNING, "Error processing flags\n");
- goto out;
- }
- if (crypt_stat->file_version > ECRYPTFS_SUPPORTED_FILE_VERSION) {
- ecryptfs_printk(KERN_WARNING, "File version is [%d]; only "
- "file version [%d] is supported by this "
- "version of eCryptfs\n",
- crypt_stat->file_version,
- ECRYPTFS_SUPPORTED_FILE_VERSION);
- rc = -EINVAL;
- goto out;
- }
- offset += bytes_read;
- if (crypt_stat->file_version >= 1) {
- rc = parse_header_metadata(crypt_stat, (page_virt + offset),
- &bytes_read);
- if (rc) {
- ecryptfs_printk(KERN_WARNING, "Error reading header "
- "metadata; rc = [%d]\n", rc);
- }
- offset += bytes_read;
- } else
- set_default_header_data(crypt_stat);
- rc = ecryptfs_parse_packet_set(crypt_stat, (page_virt + offset),
- ecryptfs_dentry);
- out:
- return rc;
- }
- /**
- * ecryptfs_read_headers
- *
- * Returns zero if valid headers found and parsed; non-zero otherwise
- */
- int ecryptfs_read_headers(struct dentry *ecryptfs_dentry,
- struct file *lower_file)
- {
- int rc = 0;
- char *page_virt = NULL;
- mm_segment_t oldfs;
- ssize_t bytes_read;
- struct ecryptfs_crypt_stat *crypt_stat =
- &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat;
- /* Read the first page from the underlying file */
- page_virt = kmem_cache_alloc(ecryptfs_header_cache_1, SLAB_USER);
- if (!page_virt) {
- rc = -ENOMEM;
- ecryptfs_printk(KERN_ERR, "Unable to allocate page_virt\n");
- goto out;
- }
- lower_file->f_pos = 0;
- oldfs = get_fs();
- set_fs(get_ds());
- bytes_read = lower_file->f_op->read(lower_file,
- (char __user *)page_virt,
- ECRYPTFS_DEFAULT_EXTENT_SIZE,
- &lower_file->f_pos);
- set_fs(oldfs);
- if (bytes_read != ECRYPTFS_DEFAULT_EXTENT_SIZE) {
- rc = -EINVAL;
- goto out;
- }
- rc = ecryptfs_read_headers_virt(page_virt, crypt_stat,
- ecryptfs_dentry);
- if (rc) {
- ecryptfs_printk(KERN_DEBUG, "Valid eCryptfs headers not "
- "found\n");
- rc = -EINVAL;
- }
- out:
- if (page_virt) {
- memset(page_virt, 0, PAGE_CACHE_SIZE);
- kmem_cache_free(ecryptfs_header_cache_1, page_virt);
- }
- return rc;
- }
- /**
- * ecryptfs_encode_filename - converts a plaintext file name to cipher text
- * @crypt_stat: The crypt_stat struct associated with the file anem to encode
- * @name: The plaintext name
- * @length: The length of the plaintext
- * @encoded_name: The encypted name
- *
- * Encrypts and encodes a filename into something that constitutes a
- * valid filename for a filesystem, with printable characters.
- *
- * We assume that we have a properly initialized crypto context,
- * pointed to by crypt_stat->tfm.
- *
- * TODO: Implement filename decoding and decryption here, in place of
- * memcpy. We are keeping the framework around for now to (1)
- * facilitate testing of the components needed to implement filename
- * encryption and (2) to provide a code base from which other
- * developers in the community can easily implement this feature.
- *
- * Returns the length of encoded filename; negative if error
- */
- int
- ecryptfs_encode_filename(struct ecryptfs_crypt_stat *crypt_stat,
- const char *name, int length, char **encoded_name)
- {
- int error = 0;
- (*encoded_name) = kmalloc(length + 2, GFP_KERNEL);
- if (!(*encoded_name)) {
- error = -ENOMEM;
- goto out;
- }
- /* TODO: Filename encryption is a scheduled feature for a
- * future version of eCryptfs. This function is here only for
- * the purpose of providing a framework for other developers
- * to easily implement filename encryption. Hint: Replace this
- * memcpy() with a call to encrypt and encode the
- * filename, the set the length accordingly. */
- memcpy((void *)(*encoded_name), (void *)name, length);
- (*encoded_name)[length] = '\0';
- error = length + 1;
- out:
- return error;
- }
- /**
- * ecryptfs_decode_filename - converts the cipher text name to plaintext
- * @crypt_stat: The crypt_stat struct associated with the file
- * @name: The filename in cipher text
- * @length: The length of the cipher text name
- * @decrypted_name: The plaintext name
- *
- * Decodes and decrypts the filename.
- *
- * We assume that we have a properly initialized crypto context,
- * pointed to by crypt_stat->tfm.
- *
- * TODO: Implement filename decoding and decryption here, in place of
- * memcpy. We are keeping the framework around for now to (1)
- * facilitate testing of the components needed to implement filename
- * encryption and (2) to provide a code base from which other
- * developers in the community can easily implement this feature.
- *
- * Returns the length of decoded filename; negative if error
- */
- int
- ecryptfs_decode_filename(struct ecryptfs_crypt_stat *crypt_stat,
- const char *name, int length, char **decrypted_name)
- {
- int error = 0;
- (*decrypted_name) = kmalloc(length + 2, GFP_KERNEL);
- if (!(*decrypted_name)) {
- error = -ENOMEM;
- goto out;
- }
- /* TODO: Filename encryption is a scheduled feature for a
- * future version of eCryptfs. This function is here only for
- * the purpose of providing a framework for other developers
- * to easily implement filename encryption. Hint: Replace this
- * memcpy() with a call to decode and decrypt the
- * filename, the set the length accordingly. */
- memcpy((void *)(*decrypted_name), (void *)name, length);
- (*decrypted_name)[length + 1] = '\0'; /* Only for convenience
- * in printing out the
- * string in debug
- * messages */
- error = length;
- out:
- return error;
- }
- /**
- * ecryptfs_process_cipher - Perform cipher initialization.
- * @tfm: Crypto context set by this function
- * @key_tfm: Crypto context for key material, set by this function
- * @cipher_name: Name of the cipher.
- * @key_size: Size of the key in bytes.
- *
- * Returns zero on success. Any crypto_tfm structs allocated here
- * should be released by other functions, such as on a superblock put
- * event, regardless of whether this function succeeds for fails.
- */
- int
- ecryptfs_process_cipher(struct crypto_tfm **tfm, struct crypto_tfm **key_tfm,
- char *cipher_name, size_t key_size)
- {
- char dummy_key[ECRYPTFS_MAX_KEY_BYTES];
- int rc;
- *tfm = *key_tfm = NULL;
- if (key_size > ECRYPTFS_MAX_KEY_BYTES) {
- rc = -EINVAL;
- printk(KERN_ERR "Requested key size is [%Zd] bytes; maximum "
- "allowable is [%d]\n", key_size, ECRYPTFS_MAX_KEY_BYTES);
- goto out;
- }
- *tfm = crypto_alloc_tfm(cipher_name, (ECRYPTFS_DEFAULT_CHAINING_MODE
- | CRYPTO_TFM_REQ_WEAK_KEY));
- if (!(*tfm)) {
- rc = -EINVAL;
- printk(KERN_ERR "Unable to allocate crypto cipher with name "
- "[%s]\n", cipher_name);
- goto out;
- }
- *key_tfm = crypto_alloc_tfm(cipher_name, CRYPTO_TFM_REQ_WEAK_KEY);
- if (!(*key_tfm)) {
- rc = -EINVAL;
- printk(KERN_ERR "Unable to allocate crypto cipher with name "
- "[%s]\n", cipher_name);
- goto out;
- }
- if (key_size < crypto_tfm_alg_min_keysize(*tfm)) {
- rc = -EINVAL;
- printk(KERN_ERR "Request key size is [%Zd]; minimum key size "
- "supported by cipher [%s] is [%d]\n", key_size,
- cipher_name, crypto_tfm_alg_min_keysize(*tfm));
- goto out;
- }
- if (key_size < crypto_tfm_alg_min_keysize(*key_tfm)) {
- rc = -EINVAL;
- printk(KERN_ERR "Request key size is [%Zd]; minimum key size "
- "supported by cipher [%s] is [%d]\n", key_size,
- cipher_name, crypto_tfm_alg_min_keysize(*key_tfm));
- goto out;
- }
- if (key_size > crypto_tfm_alg_max_keysize(*tfm)) {
- rc = -EINVAL;
- printk(KERN_ERR "Request key size is [%Zd]; maximum key size "
- "supported by cipher [%s] is [%d]\n", key_size,
- cipher_name, crypto_tfm_alg_min_keysize(*tfm));
- goto out;
- }
- if (key_size > crypto_tfm_alg_max_keysize(*key_tfm)) {
- rc = -EINVAL;
- printk(KERN_ERR "Request key size is [%Zd]; maximum key size "
- "supported by cipher [%s] is [%d]\n", key_size,
- cipher_name, crypto_tfm_alg_min_keysize(*key_tfm));
- goto out;
- }
- get_random_bytes(dummy_key, key_size);
- rc = crypto_cipher_setkey(*tfm, dummy_key, key_size);
- if (rc) {
- printk(KERN_ERR "Error attempting to set key of size [%Zd] for "
- "cipher [%s]; rc = [%d]\n", key_size, cipher_name, rc);
- rc = -EINVAL;
- goto out;
- }
- rc = crypto_cipher_setkey(*key_tfm, dummy_key, key_size);
- if (rc) {
- printk(KERN_ERR "Error attempting to set key of size [%Zd] for "
- "cipher [%s]; rc = [%d]\n", key_size, cipher_name, rc);
- rc = -EINVAL;
- goto out;
- }
- out:
- return rc;
- }
|