"Fossies" - the Fresh Open Source Software Archive

Member "libzip-1.6.0/lib/zip_winzip_aes.c" (24 Jan 2020, 4832 Bytes) of package /linux/misc/libzip-1.6.0.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "zip_winzip_aes.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.5.2_vs_1.6.0.

    1 /*
    2   zip_winzip_aes.c -- Winzip AES de/encryption backend routines
    3   Copyright (C) 2017-2019 Dieter Baron and Thomas Klausner
    4 
    5   This file is part of libzip, a library to manipulate ZIP archives.
    6   The authors can be contacted at <libzip@nih.at>
    7 
    8   Redistribution and use in source and binary forms, with or without
    9   modification, are permitted provided that the following conditions
   10   are met:
   11   1. Redistributions of source code must retain the above copyright
   12   notice, this list of conditions and the following disclaimer.
   13   2. Redistributions in binary form must reproduce the above copyright
   14   notice, this list of conditions and the following disclaimer in
   15   the documentation and/or other materials provided with the
   16   distribution.
   17   3. The names of the authors may not be used to endorse or promote
   18   products derived from this software without specific prior
   19   written permission.
   20 
   21   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   22   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   23   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
   25   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
   27   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   28   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
   29   IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   30   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
   31   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   32 */
   33 
   34 #include "zipint.h"
   35 
   36 #include "zip_crypto.h"
   37 
   38 #include <limits.h>
   39 #include <stdlib.h>
   40 #include <string.h>
   41 
   42 
   43 #define MAX_KEY_LENGTH 256
   44 #define PBKDF2_ITERATIONS 1000
   45 
   46 struct _zip_winzip_aes {
   47     _zip_crypto_aes_t *aes;
   48     _zip_crypto_hmac_t *hmac;
   49     zip_uint8_t counter[ZIP_CRYPTO_AES_BLOCK_LENGTH];
   50     zip_uint8_t pad[ZIP_CRYPTO_AES_BLOCK_LENGTH];
   51     int pad_offset;
   52 };
   53 
   54 static bool
   55 aes_crypt(zip_winzip_aes_t *ctx, zip_uint8_t *data, zip_uint64_t length) {
   56     zip_uint64_t i, j;
   57 
   58     for (i = 0; i < length; i++) {
   59     if (ctx->pad_offset == AES_BLOCK_SIZE) {
   60         for (j = 0; j < 8; j++) {
   61         ctx->counter[j]++;
   62         if (ctx->counter[j] != 0) {
   63             break;
   64         }
   65         }
   66         if (!_zip_crypto_aes_encrypt_block(ctx->aes, ctx->counter, ctx->pad)) {
   67         return false;
   68         }
   69         ctx->pad_offset = 0;
   70     }
   71     data[i] ^= ctx->pad[ctx->pad_offset++];
   72     }
   73 
   74     return true;
   75 }
   76 
   77 
   78 zip_winzip_aes_t *
   79 _zip_winzip_aes_new(const zip_uint8_t *password, zip_uint64_t password_length, const zip_uint8_t *salt, zip_uint16_t encryption_method, zip_uint8_t *password_verify, zip_error_t *error) {
   80     zip_winzip_aes_t *ctx;
   81     zip_uint8_t buffer[2 * (MAX_KEY_LENGTH / 8) + WINZIP_AES_PASSWORD_VERIFY_LENGTH];
   82     zip_uint16_t key_size = 0; /* in bits */
   83     zip_uint16_t key_length;   /* in bytes */
   84 
   85     switch (encryption_method) {
   86     case ZIP_EM_AES_128:
   87     key_size = 128;
   88     break;
   89     case ZIP_EM_AES_192:
   90     key_size = 192;
   91     break;
   92     case ZIP_EM_AES_256:
   93     key_size = 256;
   94     break;
   95     }
   96 
   97     if (key_size == 0 || salt == NULL || password == NULL || password_length == 0) {
   98     zip_error_set(error, ZIP_ER_INVAL, 0);
   99     return NULL;
  100     }
  101 
  102     key_length = key_size / 8;
  103 
  104     if ((ctx = (zip_winzip_aes_t *)malloc(sizeof(*ctx))) == NULL) {
  105     zip_error_set(error, ZIP_ER_MEMORY, 0);
  106     return NULL;
  107     }
  108 
  109     memset(ctx->counter, 0, sizeof(ctx->counter));
  110     ctx->pad_offset = ZIP_CRYPTO_AES_BLOCK_LENGTH;
  111 
  112     if (!_zip_crypto_pbkdf2(password, password_length, salt, key_length / 2, PBKDF2_ITERATIONS, buffer, 2 * key_length + WINZIP_AES_PASSWORD_VERIFY_LENGTH)) {
  113     free(ctx);
  114     return NULL;
  115     }
  116 
  117     if ((ctx->aes = _zip_crypto_aes_new(buffer, key_size, error)) == NULL) {
  118     _zip_crypto_clear(ctx, sizeof(*ctx));
  119     free(ctx);
  120     return NULL;
  121     }
  122     if ((ctx->hmac = _zip_crypto_hmac_new(buffer + key_length, key_length, error)) == NULL) {
  123     _zip_crypto_aes_free(ctx->aes);
  124     free(ctx);
  125     return NULL;
  126     }
  127 
  128     if (password_verify) {
  129     memcpy(password_verify, buffer + (2 * key_size / 8), WINZIP_AES_PASSWORD_VERIFY_LENGTH);
  130     }
  131 
  132     return ctx;
  133 }
  134 
  135 
  136 bool
  137 _zip_winzip_aes_encrypt(zip_winzip_aes_t *ctx, zip_uint8_t *data, zip_uint64_t length) {
  138     return aes_crypt(ctx, data, length) && _zip_crypto_hmac(ctx->hmac, data, length);
  139 }
  140 
  141 
  142 bool
  143 _zip_winzip_aes_decrypt(zip_winzip_aes_t *ctx, zip_uint8_t *data, zip_uint64_t length) {
  144     return _zip_crypto_hmac(ctx->hmac, data, length) && aes_crypt(ctx, data, length);
  145 }
  146 
  147 
  148 bool
  149 _zip_winzip_aes_finish(zip_winzip_aes_t *ctx, zip_uint8_t *hmac) {
  150     return _zip_crypto_hmac_output(ctx->hmac, hmac);
  151 }
  152 
  153 
  154 void
  155 _zip_winzip_aes_free(zip_winzip_aes_t *ctx) {
  156     if (ctx == NULL) {
  157     return;
  158     }
  159 
  160     _zip_crypto_aes_free(ctx->aes);
  161     _zip_crypto_hmac_free(ctx->hmac);
  162     free(ctx);
  163 }