"Fossies" - the Fresh Open Source Software Archive

Member "libzip-1.6.0/lib/zip_source_winzip_aes_encode.c" (24 Jan 2020, 6964 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_source_winzip_aes_encode.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_source_winzip_aes_encode.c -- Winzip AES encryption routines
    3   Copyright (C) 2009-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 
   35 #include <stdlib.h>
   36 #include <string.h>
   37 
   38 #include "zipint.h"
   39 
   40 
   41 struct winzip_aes {
   42     char *password;
   43     zip_uint16_t encryption_method;
   44 
   45     zip_uint8_t data[ZIP_MAX(WINZIP_AES_MAX_HEADER_LENGTH, SHA1_LENGTH)];
   46     zip_buffer_t *buffer;
   47 
   48     zip_winzip_aes_t *aes_ctx;
   49     bool eof;
   50     zip_error_t error;
   51 };
   52 
   53 
   54 static int encrypt_header(zip_source_t *src, struct winzip_aes *ctx);
   55 static void winzip_aes_free(struct winzip_aes *);
   56 static zip_int64_t winzip_aes_encrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_source_cmd_t cmd);
   57 static struct winzip_aes *winzip_aes_new(zip_uint16_t encryption_method, const char *password, zip_error_t *error);
   58 
   59 
   60 zip_source_t *
   61 zip_source_winzip_aes_encode(zip_t *za, zip_source_t *src, zip_uint16_t encryption_method, int flags, const char *password) {
   62     zip_source_t *s2;
   63     struct winzip_aes *ctx;
   64 
   65     if ((encryption_method != ZIP_EM_AES_128 && encryption_method != ZIP_EM_AES_192 && encryption_method != ZIP_EM_AES_256) || password == NULL || src == NULL) {
   66     zip_error_set(&za->error, ZIP_ER_INVAL, 0);
   67     return NULL;
   68     }
   69 
   70     if ((ctx = winzip_aes_new(encryption_method, password, &za->error)) == NULL) {
   71     return NULL;
   72     }
   73 
   74     if ((s2 = zip_source_layered(za, src, winzip_aes_encrypt, ctx)) == NULL) {
   75     winzip_aes_free(ctx);
   76     return NULL;
   77     }
   78 
   79     return s2;
   80 }
   81 
   82 
   83 static int
   84 encrypt_header(zip_source_t *src, struct winzip_aes *ctx) {
   85     zip_uint16_t salt_length = SALT_LENGTH(ctx->encryption_method);
   86     if (!zip_secure_random(ctx->data, salt_length)) {
   87     zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
   88     return -1;
   89     }
   90 
   91     if ((ctx->aes_ctx = _zip_winzip_aes_new((zip_uint8_t *)ctx->password, strlen(ctx->password), ctx->data, ctx->encryption_method, ctx->data + salt_length, &ctx->error)) == NULL) {
   92     return -1;
   93     }
   94 
   95     if ((ctx->buffer = _zip_buffer_new(ctx->data, salt_length + WINZIP_AES_PASSWORD_VERIFY_LENGTH)) == NULL) {
   96     _zip_winzip_aes_free(ctx->aes_ctx);
   97     ctx->aes_ctx = NULL;
   98     zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
   99     return -1;
  100     }
  101 
  102     return 0;
  103 }
  104 
  105 
  106 static zip_int64_t
  107 winzip_aes_encrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t length, zip_source_cmd_t cmd) {
  108     struct winzip_aes *ctx;
  109     zip_int64_t ret;
  110     zip_uint64_t buffer_n;
  111 
  112     ctx = (struct winzip_aes *)ud;
  113 
  114     switch (cmd) {
  115     case ZIP_SOURCE_OPEN:
  116     ctx->eof = false;
  117     if (encrypt_header(src, ctx) < 0) {
  118         return -1;
  119     }
  120     return 0;
  121 
  122     case ZIP_SOURCE_READ:
  123     buffer_n = 0;
  124 
  125     if (ctx->buffer) {
  126         buffer_n = _zip_buffer_read(ctx->buffer, data, length);
  127 
  128         data = (zip_uint8_t *)data + buffer_n;
  129         length -= buffer_n;
  130 
  131         if (_zip_buffer_eof(ctx->buffer)) {
  132         _zip_buffer_free(ctx->buffer);
  133         ctx->buffer = NULL;
  134         }
  135     }
  136 
  137     if (ctx->eof) {
  138         return (zip_int64_t)buffer_n;
  139     }
  140 
  141     if ((ret = zip_source_read(src, data, length)) < 0) {
  142         _zip_error_set_from_source(&ctx->error, src);
  143         return -1;
  144     }
  145 
  146     if (!_zip_winzip_aes_encrypt(ctx->aes_ctx, data, (zip_uint64_t)ret)) {
  147         zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
  148         /* TODO: return partial read? */
  149         return -1;
  150     }
  151 
  152     if ((zip_uint64_t)ret < length) {
  153         ctx->eof = true;
  154         if (!_zip_winzip_aes_finish(ctx->aes_ctx, ctx->data)) {
  155         zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
  156         /* TODO: return partial read? */
  157         return -1;
  158         }
  159         _zip_winzip_aes_free(ctx->aes_ctx);
  160         ctx->aes_ctx = NULL;
  161         if ((ctx->buffer = _zip_buffer_new(ctx->data, HMAC_LENGTH)) == NULL) {
  162         zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
  163         /* TODO: return partial read? */
  164         return -1;
  165         }
  166         buffer_n += _zip_buffer_read(ctx->buffer, (zip_uint8_t *)data + ret, length - (zip_uint64_t)ret);
  167     }
  168 
  169     return (zip_int64_t)(buffer_n + (zip_uint64_t)ret);
  170 
  171     case ZIP_SOURCE_CLOSE:
  172     return 0;
  173 
  174     case ZIP_SOURCE_STAT: {
  175     zip_stat_t *st;
  176 
  177     st = (zip_stat_t *)data;
  178     st->encryption_method = ctx->encryption_method;
  179     st->valid |= ZIP_STAT_ENCRYPTION_METHOD;
  180     if (st->valid & ZIP_STAT_COMP_SIZE) {
  181         st->comp_size += 12 + SALT_LENGTH(ctx->encryption_method);
  182     }
  183 
  184     return 0;
  185     }
  186 
  187     case ZIP_SOURCE_SUPPORTS:
  188     return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1);
  189 
  190     case ZIP_SOURCE_ERROR:
  191     return zip_error_to_data(&ctx->error, data, length);
  192 
  193     case ZIP_SOURCE_FREE:
  194     winzip_aes_free(ctx);
  195     return 0;
  196 
  197     default:
  198     zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
  199     return -1;
  200     }
  201 }
  202 
  203 
  204 static void
  205 winzip_aes_free(struct winzip_aes *ctx) {
  206     if (ctx == NULL) {
  207     return;
  208     }
  209 
  210     _zip_crypto_clear(ctx->password, strlen(ctx->password));
  211     free(ctx->password);
  212     zip_error_fini(&ctx->error);
  213     _zip_buffer_free(ctx->buffer);
  214     _zip_winzip_aes_free(ctx->aes_ctx);
  215     free(ctx);
  216 }
  217 
  218 
  219 static struct winzip_aes *
  220 winzip_aes_new(zip_uint16_t encryption_method, const char *password, zip_error_t *error) {
  221     struct winzip_aes *ctx;
  222 
  223     if ((ctx = (struct winzip_aes *)malloc(sizeof(*ctx))) == NULL) {
  224     zip_error_set(error, ZIP_ER_MEMORY, 0);
  225     return NULL;
  226     }
  227 
  228     if ((ctx->password = strdup(password)) == NULL) {
  229     free(ctx);
  230     zip_error_set(error, ZIP_ER_MEMORY, 0);
  231     return NULL;
  232     }
  233 
  234     ctx->encryption_method = encryption_method;
  235     ctx->buffer = NULL;
  236     ctx->aes_ctx = NULL;
  237 
  238     zip_error_init(&ctx->error);
  239 
  240     ctx->eof = false;
  241     return ctx;
  242 }