LCOV - code coverage report
Current view: top level - common - fscrypt.c (source / functions) Hit Total Coverage
Test: a simple test Lines: 84 131 64.1 %
Date: 2024-06-05 20:10:43 Functions: 9 11 81.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2017 sigma star gmbh
       3             :  *
       4             :  * This program is free software; you can redistribute it and/or modify it
       5             :  * under the terms of the GNU General Public License version 2 as published by
       6             :  * the Free Software Foundation.
       7             :  *
       8             :  * This program is distributed in the hope that it will be useful, but WITHOUT
       9             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      10             :  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
      11             :  * more details.
      12             :  *
      13             :  * You should have received a copy of the GNU General Public License along with
      14             :  * this program; if not, write to the Free Software Foundation, Inc., 51
      15             :  * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      16             :  *
      17             :  * Authors: Richard Weinberger <richard@sigma-star.at>
      18             :  *          David Oberhollenzer <david.oberhollenzer@sigma-star.at>
      19             :  */
      20             : 
      21             : #include <endian.h>
      22             : 
      23             : #include "linux_types.h"
      24             : #include "fscrypt.h"
      25             : #include "defs.h"
      26             : #include "ubifs.h"
      27             : 
      28             : static __u8 fscrypt_masterkey[FS_MAX_KEY_SIZE];
      29             : static struct cipher *fscrypt_cipher;
      30             : 
      31             : 
      32      351360 : unsigned char *calc_fscrypt_subkey(struct fscrypt_context *fctx)
      33             : {
      34             :         int ret;
      35      351360 :         unsigned char *new_key = xmalloc(FS_MAX_KEY_SIZE);
      36             : 
      37      351360 :         ret = derive_key_aes(fctx->nonce, fscrypt_masterkey, fscrypt_cipher->key_length, new_key);
      38      351360 :         if (ret < 0) {
      39           0 :                 errmsg("derive_key_aes failed: %i\n", ret);
      40             : 
      41           0 :                 free(new_key);
      42           0 :                 new_key = NULL;
      43             :         }
      44             : 
      45      351360 :         return new_key;
      46             : }
      47             : 
      48       46080 : struct fscrypt_context *inherit_fscrypt_context(struct fscrypt_context *fctx)
      49             : {
      50       46080 :         struct fscrypt_context *new_fctx = NULL;
      51             : 
      52       46080 :         if (fctx) {
      53       46080 :                 new_fctx = xmalloc(sizeof(*new_fctx));
      54       46080 :                 new_fctx->format = fctx->format;
      55       46080 :                 new_fctx->contents_encryption_mode = fctx->contents_encryption_mode;
      56       46080 :                 new_fctx->filenames_encryption_mode = fctx->filenames_encryption_mode;
      57       46080 :                 new_fctx->flags = fctx->flags;
      58       46080 :                 memcpy(new_fctx->master_key_descriptor, fctx->master_key_descriptor,
      59             :                        FS_KEY_DESCRIPTOR_SIZE);
      60       46080 :                 RAND_bytes((void *)&new_fctx->nonce, FS_KEY_DERIVATION_NONCE_SIZE);
      61             :         }
      62             : 
      63       46080 :         return new_fctx;
      64             : }
      65             : 
      66       46080 : void free_fscrypt_context(struct fscrypt_context *fctx)
      67             : {
      68       46080 :         free(fctx);
      69       46080 : }
      70             : 
      71         320 : static void print_fscrypt_master_key_descriptor(__u8 *master_key_descriptor)
      72             : {
      73             :         int i;
      74             : 
      75         320 :         normsg_cont("fscrypt master key descriptor: 0x");
      76        2880 :         for (i = 0; i < FS_KEY_DESCRIPTOR_SIZE; i++) {
      77        2560 :                 printf("%02x", master_key_descriptor[i]);
      78             :         }
      79         320 :         printf("\n");
      80         320 : }
      81             : 
      82        3840 : unsigned int fscrypt_fname_encrypted_size(struct fscrypt_context *fctx,
      83             :                                           unsigned int ilen)
      84             : {
      85             :         int padding;
      86             : 
      87        3840 :         padding = 4 << (fctx->flags & FS_POLICY_FLAGS_PAD_MASK);
      88        3840 :         ilen = max_t(unsigned int, ilen, FS_CRYPTO_BLOCK_SIZE);
      89        3840 :         return round_up(ilen, padding);
      90             : }
      91             : 
      92       49920 : int encrypt_path(void **outbuf, const void *data, unsigned int data_len,
      93             :                 unsigned int max_namelen, struct fscrypt_context *fctx)
      94             : {
      95             :         void *inbuf, *crypt_key;
      96       49920 :         unsigned int padding = 4 << (fctx->flags & FS_POLICY_FLAGS_PAD_MASK);
      97             :         unsigned int cryptlen;
      98             :         int ret;
      99             : 
     100       49920 :         cryptlen = max_t(unsigned int, data_len, FS_CRYPTO_BLOCK_SIZE);
     101       49920 :         cryptlen = round_up(cryptlen, padding);
     102       49920 :         cryptlen = min(cryptlen, max_namelen);
     103             : 
     104       49920 :         inbuf = xmalloc(cryptlen);
     105             :         /* CTS mode needs a block size aligned buffer */
     106       49920 :         *outbuf = xmalloc(round_up(cryptlen, FS_CRYPTO_BLOCK_SIZE));
     107             : 
     108       49920 :         memset(inbuf, 0, cryptlen);
     109       49920 :         memcpy(inbuf, data, data_len);
     110             : 
     111       49920 :         crypt_key = calc_fscrypt_subkey(fctx);
     112       49920 :         if (!crypt_key) {
     113           0 :                 free(inbuf);
     114           0 :                 free(*outbuf);
     115           0 :                 return errmsg("could not compute subkey");
     116             :         }
     117             : 
     118       49920 :         ret = fscrypt_cipher->encrypt_fname(inbuf, cryptlen,
     119             :                                             crypt_key, *outbuf);
     120       49920 :         if (ret < 0) {
     121           0 :                 free(inbuf);
     122           0 :                 free(*outbuf);
     123           0 :                 return errmsg("could not encrypt filename");
     124             :         }
     125             : 
     126       49920 :         free(crypt_key);
     127       49920 :         free(inbuf);
     128       49920 :         return cryptlen;
     129             : }
     130             : 
     131      301440 : int encrypt_data_node(struct fscrypt_context *fctx, unsigned int block_no,
     132             :                       struct ubifs_data_node *dn, size_t length)
     133             : {
     134             :         void *inbuf, *outbuf, *crypt_key;
     135      301440 :         size_t ret, pad_len = round_up(length, FS_CRYPTO_BLOCK_SIZE);
     136             : 
     137      301440 :         dn->compr_size = cpu_to_le16(length);
     138             : 
     139      301440 :         inbuf = xzalloc(pad_len);
     140      301440 :         outbuf = xzalloc(pad_len);
     141             : 
     142      301440 :         memcpy(inbuf, &dn->data, length);
     143             : 
     144      301440 :         crypt_key = calc_fscrypt_subkey(fctx);
     145      301440 :         if (!crypt_key) {
     146           0 :                 free(inbuf);
     147           0 :                 free(outbuf);
     148           0 :                 return errmsg("could not compute subkey");
     149             :         }
     150             : 
     151      301440 :         ret = fscrypt_cipher->encrypt_block(inbuf, pad_len,
     152             :                                             crypt_key, block_no,
     153             :                                             outbuf);
     154      301440 :         if (ret != pad_len) {
     155           0 :                 free(inbuf);
     156           0 :                 free(outbuf);
     157           0 :                 free(crypt_key);
     158           0 :                 return errmsg("encrypt_block returned %zi "
     159             :                                 "instead of %zi", ret, pad_len);
     160             :         }
     161             : 
     162      301440 :         memcpy(&dn->data, outbuf, pad_len);
     163             : 
     164      301440 :         free(inbuf);
     165      301440 :         free(outbuf);
     166      301440 :         free(crypt_key);
     167      301440 :         return pad_len;
     168             : }
     169             : 
     170           0 : static int xdigit(int x)
     171             : {
     172           0 :         if (isupper(x))
     173           0 :                 return x - 'A' + 0x0A;
     174           0 :         if (islower(x))
     175           0 :                 return x - 'a' + 0x0A;
     176           0 :         return x - '0';
     177             : }
     178             : 
     179           0 : static int parse_key_descriptor(const char *desc, __u8 *dst)
     180             : {
     181             :         int i, hi, lo;
     182             : 
     183           0 :         if (desc[0] == '0' && (desc[1] == 'x' || desc[1] == 'X'))
     184           0 :                 desc += 2;
     185             : 
     186           0 :         for (i = 0; i < FS_KEY_DESCRIPTOR_SIZE; ++i) {
     187           0 :                 if (!desc[i * 2] || !desc[i * 2 + 1]) {
     188           0 :                         errmsg("key descriptor '%s' is too short", desc);
     189           0 :                         return -1;
     190             :                 }
     191           0 :                 if (!isxdigit(desc[i * 2]) || !isxdigit(desc[i * 2 + 1])) {
     192           0 :                         errmsg("invalid key descriptor '%s'", desc);
     193           0 :                         return -1;
     194             :                 }
     195             : 
     196           0 :                 hi = xdigit(desc[i * 2]);
     197           0 :                 lo = xdigit(desc[i * 2 + 1]);
     198             : 
     199           0 :                 dst[i] = (hi << 4) | lo;
     200             :         }
     201             : 
     202           0 :         if (desc[i * 2]) {
     203           0 :                 errmsg("key descriptor '%s' is too long", desc);
     204           0 :                 return -1;
     205             :         }
     206             :         return 0;
     207             : }
     208             : 
     209         320 : static int load_master_key(const char *key_file, struct cipher *fsc)
     210             : {
     211             :         int kf;
     212             :         ssize_t keysize;
     213             : 
     214         320 :         kf = open(key_file, O_RDONLY);
     215         320 :         if (kf < 0) {
     216           0 :                 sys_errmsg("open '%s'", key_file);
     217             :                 return -1;
     218             :         }
     219             : 
     220         320 :         keysize = read(kf, fscrypt_masterkey, FS_MAX_KEY_SIZE);
     221         320 :         if (keysize < 0) {
     222           0 :                 sys_errmsg("read '%s'", key_file);
     223             :                 goto fail;
     224             :         }
     225         320 :         if (keysize == 0) {
     226           0 :                 errmsg("loading key from '%s': file is empty", key_file);
     227             :                 goto fail;
     228             :         }
     229         320 :         if (keysize < fsc->key_length) {
     230           0 :                 errmsg("key '%s' is too short (at least %u bytes required)",
     231             :                         key_file, fsc->key_length);
     232             :                 goto fail;
     233             :         }
     234             : 
     235         320 :         close(kf);
     236             :         return 0;
     237           0 : fail:
     238           0 :         close(kf);
     239             :         return -1;
     240             : }
     241             : 
     242         320 : struct fscrypt_context *init_fscrypt_context(const char *cipher_name,
     243             :                                              unsigned int flags,
     244             :                                              const char *key_file,
     245             :                                              const char *key_descriptor)
     246             : {
     247             :         __u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE];
     248             :         __u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE];
     249             :         struct fscrypt_context *new_fctx;
     250             : 
     251         320 :         fscrypt_cipher = get_cipher(cipher_name);
     252             : 
     253         320 :         if (!fscrypt_cipher) {
     254           0 :                 fprintf(stderr, "Cannot find cipher '%s'\n"
     255             :                         "Try `%s --help' for more information\n",
     256             :                         cipher_name, PROGRAM_NAME);
     257           0 :                 return NULL;
     258             :         }
     259             : 
     260         320 :         if (load_master_key(key_file, fscrypt_cipher))
     261             :                 return NULL;
     262             : 
     263         320 :         if (!key_descriptor) {
     264         320 :                 if (derive_key_descriptor(fscrypt_masterkey, master_key_descriptor))
     265             :                         return NULL;
     266         320 :                 print_fscrypt_master_key_descriptor(master_key_descriptor);
     267             :         } else {
     268           0 :                 if (parse_key_descriptor(key_descriptor, master_key_descriptor))
     269             :                         return NULL;
     270             :         }
     271             : 
     272         320 :         RAND_bytes((void *)nonce, FS_KEY_DERIVATION_NONCE_SIZE);
     273             : 
     274         320 :         new_fctx = xmalloc(sizeof(*new_fctx));
     275             : 
     276         320 :         new_fctx->format = FS_ENCRYPTION_CONTEXT_FORMAT_V1;
     277         320 :         new_fctx->contents_encryption_mode = fscrypt_cipher->fscrypt_block_mode;
     278         320 :         new_fctx->filenames_encryption_mode = fscrypt_cipher->fscrypt_fname_mode;
     279         320 :         new_fctx->flags = flags;
     280             : 
     281         320 :         memcpy(&new_fctx->nonce, nonce, FS_KEY_DERIVATION_NONCE_SIZE);
     282         320 :         memcpy(&new_fctx->master_key_descriptor, master_key_descriptor,
     283             :                 FS_KEY_DESCRIPTOR_SIZE);
     284         320 :         return new_fctx;
     285             : }

Generated by: LCOV version 1.13