LCOV - code coverage report
Current view: top level - common - crypto.c (source / functions) Hit Total Coverage
Test: a simple test Lines: 93 146 63.7 %
Date: 2024-06-05 20:10:43 Functions: 13 17 76.5 %
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: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
      18             :  */
      19             : 
      20             : #include <openssl/evp.h>
      21             : #include <openssl/err.h>
      22             : #include <openssl/rand.h>
      23             : #include <string.h>
      24             : #include <assert.h>
      25             : 
      26             : #include "linux_types.h"
      27             : #include "fscrypt.h"
      28             : #include "defs.h"
      29             : #include "ubifs.h"
      30             : 
      31         640 : static int do_hash(const EVP_MD *md, const unsigned char *in, size_t len, unsigned char *out)
      32             : {
      33             :         unsigned int out_len;
      34         640 :         EVP_MD_CTX *mdctx = EVP_MD_CTX_create();
      35             : 
      36         640 :         if (!mdctx)
      37             :                 return -1;
      38             : 
      39         640 :         if (EVP_DigestInit_ex(mdctx, md, NULL) != 1)
      40             :                 return -1;
      41             : 
      42         640 :         if(EVP_DigestUpdate(mdctx, in, len) != 1)
      43             :                 return -1;
      44             : 
      45         640 :         if(EVP_DigestFinal_ex(mdctx, out, &out_len) != 1)
      46             :                 return -1;
      47             : 
      48         640 :         EVP_MD_CTX_destroy(mdctx);
      49             : 
      50         640 :         return 0;
      51             : }
      52             : 
      53      702720 : static int check_iv_key_size(const EVP_CIPHER *cipher, size_t key_len,
      54             :                                 size_t iv_len)
      55             : {
      56      702720 :         if ((size_t)EVP_CIPHER_key_length(cipher) != key_len) {
      57           0 :                 errmsg("Cipher key length mismatch. Expected %lu, got %d",
      58             :                         (unsigned long)key_len, EVP_CIPHER_key_length(cipher));
      59           0 :                 return -1;
      60             :         }
      61             : 
      62      702720 :         if (iv_len && (size_t)EVP_CIPHER_iv_length(cipher) != iv_len) {
      63           0 :                 errmsg("Cipher IV length mismatch. Expected %lu, got %d",
      64             :                         (unsigned long)iv_len, EVP_CIPHER_key_length(cipher));
      65           0 :                 return -1;
      66             :         }
      67             : 
      68             :         return 0;
      69             : }
      70             : 
      71      702720 : static ssize_t do_encrypt(const EVP_CIPHER *cipher,
      72             :                                 const void *plaintext, size_t size,
      73             :                                 const void *key, size_t key_len,
      74             :                                 const void *iv, size_t iv_len,
      75             :                                 void *ciphertext)
      76             : {
      77             :         int ciphertext_len, len;
      78             :         EVP_CIPHER_CTX *ctx;
      79             : 
      80      702720 :         if (check_iv_key_size(cipher, key_len, iv_len))
      81             :                 return -1;
      82             : 
      83      702720 :         if (!(ctx = EVP_CIPHER_CTX_new()))
      84             :                 goto fail;
      85             : 
      86      702720 :         EVP_CIPHER_CTX_set_padding(ctx, 0);
      87             : 
      88      702720 :         if (EVP_EncryptInit_ex(ctx, cipher, NULL, key, iv) != 1)
      89             :                 goto fail_ctx;
      90             : 
      91      702720 :         if (EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, size) != 1)
      92             :                 goto fail_ctx;
      93             : 
      94      702720 :         ciphertext_len = len;
      95             : 
      96      702720 :         if (cipher == EVP_aes_256_xts()) {
      97      301440 :                 if (EVP_EncryptFinal(ctx, ciphertext + ciphertext_len, &len) != 1)
      98             :                         goto fail_ctx;
      99             : 
     100      301440 :                 ciphertext_len += len;
     101             :         }
     102             : 
     103      702720 :         EVP_CIPHER_CTX_free(ctx);
     104      702720 :         return ciphertext_len;
     105           0 : fail_ctx:
     106           0 :         ERR_print_errors_fp(stderr);
     107           0 :         EVP_CIPHER_CTX_free(ctx);
     108           0 :         return -1;
     109           0 : fail:
     110           0 :         ERR_print_errors_fp(stderr);
     111           0 :         return -1;
     112             : }
     113             : 
     114           0 : static ssize_t gen_essiv_salt(const void *iv, size_t iv_len, const void *key, size_t key_len, void *salt)
     115             : {
     116             :         size_t ret;
     117             :         const EVP_CIPHER *cipher;
     118           0 :         void *sha256 = xzalloc(EVP_MD_size(EVP_sha256()));
     119             : 
     120           0 :         cipher = EVP_aes_256_ecb();
     121           0 :         if (!cipher) {
     122           0 :                 errmsg("OpenSSL: Cipher AES-256-ECB is not supported");
     123           0 :                 goto fail;
     124             :         }
     125             : 
     126           0 :         if (do_hash(EVP_sha256(), key, key_len, sha256) != 0) {
     127           0 :                 errmsg("sha256 failed");
     128           0 :                 goto fail;
     129             :         }
     130             : 
     131           0 :         ret = do_encrypt(cipher, iv, iv_len, sha256, EVP_MD_size(EVP_sha256()), NULL, 0, salt);
     132           0 :         if (ret != iv_len) {
     133           0 :                 errmsg("Unable to compute ESSIV salt, return value %zi instead of %zi", ret, iv_len);
     134           0 :                 goto fail;
     135             :         }
     136             : 
     137           0 :         free(sha256);
     138             : 
     139           0 :         return ret;
     140           0 : fail:
     141           0 :         free(sha256);
     142           0 :         return -1;
     143             : }
     144             : 
     145      301440 : static ssize_t encrypt_block(const void *plaintext, size_t size,
     146             :                              const void *key, uint64_t block_index,
     147             :                              void *ciphertext, const EVP_CIPHER *cipher)
     148             : {
     149             :         size_t key_len, ivsize;
     150             :         void *tweak;
     151             :         struct {
     152             :                 uint64_t index;
     153             :                 uint8_t padding[FS_IV_SIZE - sizeof(uint64_t)];
     154             :         } iv;
     155             : 
     156      301440 :         ivsize = EVP_CIPHER_iv_length(cipher);
     157      301440 :         key_len = EVP_CIPHER_key_length(cipher);
     158             : 
     159      301440 :         iv.index = cpu_to_le64(block_index);
     160      301440 :         memset(iv.padding, 0, sizeof(iv.padding));
     161             : 
     162      301440 :         if (cipher == EVP_aes_128_cbc()) {
     163           0 :                 tweak = alloca(ivsize);
     164           0 :                 if (gen_essiv_salt(&iv, FS_IV_SIZE, key, key_len, tweak) < 0)
     165             :                         return -1;
     166             :         } else {
     167             :                 tweak = &iv;
     168             :         }
     169             : 
     170      301440 :         return do_encrypt(cipher, plaintext, size, key, key_len, tweak,
     171             :                           ivsize, ciphertext);
     172             : }
     173             : 
     174           0 : static ssize_t encrypt_block_aes128_cbc(const void *plaintext, size_t size,
     175             :                                         const void *key, uint64_t block_index,
     176             :                                         void *ciphertext)
     177             : {
     178           0 :         const EVP_CIPHER *cipher = EVP_aes_128_cbc();
     179             : 
     180           0 :         if (!cipher) {
     181           0 :                 errmsg("OpenSSL: Cipher AES-128-CBC is not supported");
     182           0 :                 return -1;
     183             :         }
     184           0 :         return encrypt_block(plaintext, size, key, block_index,
     185             :                              ciphertext, cipher);
     186             : }
     187             : 
     188      301440 : static ssize_t encrypt_block_aes256_xts(const void *plaintext, size_t size,
     189             :                                         const void *key, uint64_t block_index,
     190             :                                         void *ciphertext)
     191             : {
     192      301440 :         const EVP_CIPHER *cipher = EVP_aes_256_xts();
     193             : 
     194      301440 :         if (!cipher) {
     195           0 :                 errmsg("OpenSSL: Cipher AES-256-XTS is not supported");
     196           0 :                 return -1;
     197             :         }
     198      301440 :         return encrypt_block(plaintext, size, key, block_index,
     199             :                              ciphertext, cipher);
     200             : }
     201             : 
     202        3840 : static void block_swap(uint8_t *ciphertext, size_t i0, size_t i1,
     203             :                         size_t size)
     204        3840 : {
     205        3840 :         uint8_t temp[size], *p0, *p1;
     206             : 
     207        3840 :         p0 = ciphertext + i0 * size;
     208        3840 :         p1 = ciphertext + i1 * size;
     209             : 
     210        3840 :         memcpy(temp, p0, size);
     211        3840 :         memcpy(p0, p1, size);
     212        3840 :         memcpy(p1, temp, size);
     213        3840 : }
     214             : 
     215       49920 : static ssize_t encrypt_cbc_cts(const void *plaintext, size_t size,
     216             :                                const void *key, void *ciphertext,
     217             :                                const EVP_CIPHER *cipher)
     218             : {
     219             :         size_t diff, padded_size, count, ivsize;
     220             :         uint8_t iv[EVP_MAX_IV_LENGTH], *padded;
     221             :         ssize_t ret, key_len;
     222             : 
     223       49920 :         key_len = EVP_CIPHER_key_length(cipher);
     224       49920 :         ivsize = EVP_CIPHER_iv_length(cipher);
     225             : 
     226       49920 :         memset(iv, 0, ivsize);
     227             : 
     228       49920 :         diff = size % ivsize;
     229             : 
     230       49920 :         if (diff) {
     231        3520 :                 padded_size = size - diff + ivsize;
     232        3520 :                 padded = size > 256 ? malloc(padded_size) : alloca(padded_size);
     233             : 
     234        3520 :                 memcpy(padded, plaintext, size);
     235        3520 :                 memset(padded + size, 0, padded_size - size);
     236             : 
     237        3520 :                 ret = do_encrypt(cipher, padded, padded_size, key, key_len,
     238             :                                  iv, ivsize, ciphertext);
     239             : 
     240        3520 :                 if (size > 256)
     241        2880 :                         free(padded);
     242             :         } else {
     243       46400 :                 ret = do_encrypt(cipher, plaintext, size, key, key_len,
     244             :                                  iv, ivsize, ciphertext);
     245             :         }
     246             : 
     247       49920 :         if (ret < 0)
     248             :                 return ret;
     249             : 
     250       49920 :         count = ret / ivsize;
     251             : 
     252       49920 :         if (count > 1)
     253        3840 :                 block_swap(ciphertext, count - 2, count - 1, ivsize);
     254             : 
     255       49920 :         return size;
     256             : }
     257             : 
     258           0 : static ssize_t encrypt_aes128_cbc_cts(const void *plaintext, size_t size,
     259             :                                       const void *key, void *ciphertext)
     260             : {
     261           0 :         const EVP_CIPHER *cipher = EVP_aes_128_cbc();
     262           0 :         if (!cipher) {
     263           0 :                 errmsg("OpenSSL: Cipher AES-128-CBC is not supported");
     264           0 :                 return -1;
     265             :         }
     266             : 
     267           0 :         return encrypt_cbc_cts(plaintext, size, key, ciphertext, cipher);
     268             : }
     269             : 
     270       49920 : static ssize_t encrypt_aes256_cbc_cts(const void *plaintext, size_t size,
     271             :                                       const void *key, void *ciphertext)
     272             : {
     273       49920 :         const EVP_CIPHER *cipher = EVP_aes_256_cbc();
     274       49920 :         if (!cipher) {
     275           0 :                 errmsg("OpenSSL: Cipher AES-256-CBC is not supported");
     276           0 :                 return -1;
     277             :         }
     278             : 
     279       49920 :         return encrypt_cbc_cts(plaintext, size, key, ciphertext, cipher);
     280             : }
     281             : 
     282      351360 : ssize_t derive_key_aes(const void *deriving_key, const void *source_key,
     283             :                        size_t source_key_len, void *derived_key)
     284             : {
     285             :         const EVP_CIPHER *cipher;
     286             :         size_t aes_key_len;
     287             : 
     288      351360 :         cipher = EVP_aes_128_ecb();
     289      351360 :         if (!cipher) {
     290           0 :                 errmsg("OpenSSL: Cipher AES-128-ECB is not supported");
     291           0 :                 return -1;
     292             :         }
     293      351360 :         aes_key_len = EVP_CIPHER_key_length(cipher);
     294             : 
     295      351360 :         return do_encrypt(cipher, source_key, source_key_len, deriving_key,
     296             :                           aes_key_len, NULL, 0, derived_key);
     297             : }
     298             : 
     299         320 : int derive_key_descriptor(const void *source_key, void *descriptor)
     300             : {
     301         320 :         int ret = -1;
     302         640 :         void *hash1 = xzalloc(EVP_MD_size(EVP_sha512()));
     303         640 :         void *hash2 = xzalloc(EVP_MD_size(EVP_sha512()));
     304             : 
     305         320 :         if (do_hash(EVP_sha512(), source_key, FS_MAX_KEY_SIZE, hash1) != 0)
     306             :                 goto out;
     307             : 
     308         320 :         if (do_hash(EVP_sha512(), hash1, EVP_MD_size(EVP_sha512()), hash2) != 0)
     309             :                 goto out;
     310             : 
     311         320 :         memcpy(descriptor, hash2, FS_KEY_DESCRIPTOR_SIZE);
     312             : 
     313         320 :         ret = 0;
     314         320 : out:
     315         320 :         free(hash1);
     316         320 :         free(hash2);
     317         320 :         return ret;
     318             : }
     319             : 
     320             : static struct cipher ciphers[] = {
     321             :         {
     322             :                 .name = "AES-128-CBC",
     323             :                 .key_length = 16,
     324             :                 .encrypt_block = encrypt_block_aes128_cbc,
     325             :                 .encrypt_fname = encrypt_aes128_cbc_cts,
     326             :                 .fscrypt_block_mode = FS_ENCRYPTION_MODE_AES_128_CBC,
     327             :                 .fscrypt_fname_mode = FS_ENCRYPTION_MODE_AES_128_CTS,
     328             :         }, {
     329             :                 .name = "AES-256-XTS",
     330             :                 .key_length = 64,
     331             :                 .encrypt_block = encrypt_block_aes256_xts,
     332             :                 .encrypt_fname = encrypt_aes256_cbc_cts,
     333             :                 .fscrypt_block_mode = FS_ENCRYPTION_MODE_AES_256_XTS,
     334             :                 .fscrypt_fname_mode = FS_ENCRYPTION_MODE_AES_256_CTS,
     335             :         }
     336             : };
     337             : 
     338         640 : int crypto_init(void)
     339             : {
     340         640 :         ERR_load_crypto_strings();
     341         640 :         RAND_poll();
     342         640 :         return 0;
     343             : }
     344             : 
     345         640 : void crypto_cleanup(void)
     346             : {
     347             :         EVP_cleanup();
     348             :         ERR_free_strings();
     349         640 : }
     350             : 
     351         320 : struct cipher *get_cipher(const char *name)
     352             : {
     353             :         size_t i;
     354             : 
     355         640 :         for (i = 0; i < sizeof(ciphers) / sizeof(ciphers[0]); ++i) {
     356         640 :                 if (!strcmp(ciphers[i].name, name))
     357         320 :                         return ciphers + i;
     358             :         }
     359             : 
     360             :         return NULL;
     361             : }
     362             : 
     363           0 : void list_ciphers(FILE *fp)
     364             : {
     365             :         size_t i;
     366             : 
     367           0 :         for (i = 0; i < sizeof(ciphers) / sizeof(ciphers[0]); ++i) {
     368           0 :                 fprintf(fp, "\t%s\n", ciphers[i].name);
     369             :         }
     370           0 : }

Generated by: LCOV version 1.13