From: Michihiro NAKAJIMA Date: Sun, 7 Sep 2014 12:34:33 +0000 (+0900) Subject: Move cryptographic functions into archive_cryptor.c. X-Git-Tag: v3.1.900a~228 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a35a8d3b249a3b8114158c7f1e2ea1c276e57aac;p=thirdparty%2Flibarchive.git Move cryptographic functions into archive_cryptor.c. I will rename archive_crypto.c to archive_digest.c. --- diff --git a/Makefile.am b/Makefile.am index 2d2521a2b..ae826c8de 100644 --- a/Makefile.am +++ b/Makefile.am @@ -100,6 +100,8 @@ libarchive_la_SOURCES= \ libarchive/archive_crc32.h \ libarchive/archive_crypto.c \ libarchive/archive_crypto_private.h \ + libarchive/archive_cryptor.c \ + libarchive/archive_cryptor_private.h \ libarchive/archive_endian.h \ libarchive/archive_entry.c \ libarchive/archive_entry.h \ diff --git a/libarchive/CMakeLists.txt b/libarchive/CMakeLists.txt index 10036e5f6..6a8771e31 100644 --- a/libarchive/CMakeLists.txt +++ b/libarchive/CMakeLists.txt @@ -20,6 +20,8 @@ SET(libarchive_SOURCES archive_crc32.h archive_crypto.c archive_crypto_private.h + archive_cryptor.c + archive_cryptor_private.h archive_endian.h archive_entry.c archive_entry.h diff --git a/libarchive/archive_crypto.c b/libarchive/archive_crypto.c index 107274e22..0efdf7c39 100644 --- a/libarchive/archive_crypto.c +++ b/libarchive/archive_crypto.c @@ -1,7 +1,7 @@ /*- * Copyright (c) 2003-2007 Tim Kientzle * Copyright (c) 2011 Andres Mejia -* Copyright (c) 2011,2014 Michihiro NAKAJIMA +* Copyright (c) 2011 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,9 +27,6 @@ #include "archive_platform.h" -#ifdef HAVE_STRING_H -#include -#endif #include "archive.h" #include "archive_crypto_private.h" @@ -1219,253 +1216,6 @@ __archive_stub_sha512final(archive_sha512_ctx *ctx, void *md) #endif -#ifdef __APPLE__ - -static int -pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt, - size_t salt_len, unsigned rounds, uint8_t *derived_key, - size_t derived_key_len) -{ - CCKeyDerivationPBKDF(kCCPBKDF2, (const char *)pw, - pw_len, salt, salt_len, kCCPRFHmacAlgSHA1, rounds, - derived_key, derived_key_len); - return 0; -} - -#elif defined(HAVE_LIBNETTLE) - -static int -pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt, - size_t salt_len, unsigned rounds, uint8_t *derived_key, - size_t derived_key_len) { - pbkdf2_hmac_sha1((unsigned)pw_len, (const uint8_t *)pw, rounds, - salt_len, salt, derived_key_len, derived_key); - return 0; -} - -#elif defined(HAVE_LIBCRYPTO) - -static int -pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt, - size_t salt_len, unsigned rounds, uint8_t *derived_key, - size_t derived_key_len) { - - PKCS5_PBKDF2_HMAC_SHA1(pw, pw_len, salt, salt_len, rounds, - derived_key_len, derived_key); - return 0; -} - -#else - -/* Stub */ -static int -pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt, - size_t salt_len, unsigned rounds, uint8_t *derived_key, - size_t derived_key_len) { - (void)pw; /* UNUSED */ - (void)pw_len; /* UNUSED */ - (void)salt; /* UNUSED */ - (void)salt_len; /* UNUSED */ - (void)rounds; /* UNUSED */ - (void)derived_key; /* UNUSED */ - (void)derived_key_len; /* UNUSED */ - return -1; /* UNSUPPORTED */ -} - -#endif - -#ifdef __APPLE__ - -static int -decrypto_aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, - size_t key_len) -{ - CCCryptorStatus r; - - ctx->key_len = key_len; - memcpy(ctx->key, key, key_len); - memset(ctx->nonce, 0, sizeof(ctx->nonce)); - ctx->encr_pos = AES_BLOCK_SIZE; - r = CCCryptorCreateWithMode(kCCEncrypt, kCCModeECB, kCCAlgorithmAES, - ccNoPadding, NULL, key, key_len, NULL, 0, 0, 0, &ctx->ctx); - return (r == kCCSuccess)? 0: -1; -} - -static int -aes_ctr_encrypt_counter(archive_crypto_ctx *ctx) -{ - CCCryptorRef ref = ctx->ctx; - CCCryptorStatus r; - - r = CCCryptorReset(ref, NULL); - if (r != kCCSuccess) - return -1; - r = CCCryptorUpdate(ref, ctx->nonce, AES_BLOCK_SIZE, ctx->encr_buf, - AES_BLOCK_SIZE, NULL); - return (r == kCCSuccess)? 0: -1; -} - -static int -decrypto_aes_ctr_release(archive_crypto_ctx *ctx) -{ - memset(ctx->key, 0, ctx->key_len); - memset(ctx->nonce, 0, sizeof(ctx->nonce)); - return 0; -} - -#elif defined(HAVE_LIBNETTLE) - -static int -decrypto_aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, - size_t key_len) -{ - ctx->key_len = key_len; - memcpy(ctx->key, key, key_len); - memset(ctx->nonce, 0, sizeof(ctx->nonce)); - ctx->encr_pos = AES_BLOCK_SIZE; - memset(&ctx->ctx, 0, sizeof(ctx->ctx)); - return 0; -} - -static int -aes_ctr_encrypt_counter(archive_crypto_ctx *ctx) -{ - aes_set_encrypt_key(&ctx->ctx, ctx->key_len, ctx->key); - aes_encrypt(&ctx->ctx, AES_BLOCK_SIZE, ctx->encr_buf, ctx->nonce); - return 0; -} - -static int -decrypto_aes_ctr_release(archive_crypto_ctx *ctx) -{ - memset(ctx, 0, sizeof(*ctx)); - return 0; -} - -#elif defined(HAVE_LIBCRYPTO) - -static int -decrypto_aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, - size_t key_len) -{ - - switch (key_len) { - case 16: ctx->type = EVP_aes_128_ecb(); break; - case 24: ctx->type = EVP_aes_192_ecb(); break; - case 32: ctx->type = EVP_aes_256_ecb(); break; - default: ctx->type = NULL; return -1; - } - - ctx->key_len = key_len; - memcpy(ctx->key, key, key_len); - memset(ctx->nonce, 0, sizeof(ctx->nonce)); - ctx->encr_pos = AES_BLOCK_SIZE; - EVP_CIPHER_CTX_init(&ctx->ctx); - return 0; -} - -static int -aes_ctr_encrypt_counter(archive_crypto_ctx *ctx) -{ - int outl = 0; - int r; - - r = EVP_EncryptInit_ex(&ctx->ctx, ctx->type, NULL, ctx->key, NULL); - if (r == 0) - return -1; - r = EVP_EncryptUpdate(&ctx->ctx, ctx->encr_buf, &outl, ctx->nonce, - AES_BLOCK_SIZE); - if (r == 0 || outl != AES_BLOCK_SIZE) - return -1; - return 0; -} - -static int -decrypto_aes_ctr_release(archive_crypto_ctx *ctx) -{ - EVP_CIPHER_CTX_cleanup(&ctx->ctx); - memset(ctx->key, 0, ctx->key_len); - memset(ctx->nonce, 0, sizeof(ctx->nonce)); - return 0; -} - -#else - -/* Stub */ -static int -decrypto_aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, - size_t key_len) -{ - (void)ctx; /* UNUSED */ - (void)key; /* UNUSED */ - (void)key_len; /* UNUSED */ - return -1; -} - -static int -aes_ctr_encrypt_counter(archive_crypto_ctx *ctx) -{ - (void)ctx; /* UNUSED */ -} - -static int -decrypto_aes_ctr_release(archive_crypto_ctx *ctx) -{ - (void)ctx; /* UNUSED */ - return 0; -} - -#endif - -static void -aes_ctr_increase_counter(archive_crypto_ctx *ctx) -{ - uint8_t *const nonce = ctx->nonce; - int j; - - for (j = 0; j < 8; j++) { - if (++nonce[j]) - break; - } -} - -static int -decrypto_aes_ctr_update(archive_crypto_ctx *ctx, const uint8_t * const in, - size_t in_len, uint8_t * const out, size_t *out_len) -{ - uint8_t *const ebuf = ctx->encr_buf; - unsigned pos = ctx->encr_pos; - unsigned max = (unsigned)((in_len < *out_len)? in_len: *out_len); - unsigned i; - - for (i = 0; i < max; ) { - if (pos == AES_BLOCK_SIZE) { - aes_ctr_increase_counter(ctx); - if (aes_ctr_encrypt_counter(ctx) != 0) - return -1; - while (max -i >= AES_BLOCK_SIZE) { - for (pos = 0; pos < AES_BLOCK_SIZE; pos++) - out[i+pos] = in[i+pos] ^ ebuf[pos]; - i += AES_BLOCK_SIZE; - aes_ctr_increase_counter(ctx); - if (aes_ctr_encrypt_counter(ctx) != 0) - return -1; - } - pos = 0; - if (i >= max) - break; - } - out[i] = in[i] ^ ebuf[pos++]; - i++; - } - ctx->encr_pos = pos; - *out_len = i; - - return 0; -} - - - /* NOTE: Crypto functions are set based on availability and by the following * order of preference. * 1. libc @@ -1642,43 +1392,38 @@ const struct archive_crypto __archive_crypto = #if defined(ARCHIVE_CRYPTO_SHA512_LIBC) &__archive_libc_sha512init, &__archive_libc_sha512update, - &__archive_libc_sha512final, + &__archive_libc_sha512final #elif defined(ARCHIVE_CRYPTO_SHA512_LIBC2) &__archive_libc2_sha512init, &__archive_libc2_sha512update, - &__archive_libc2_sha512final, + &__archive_libc2_sha512final #elif defined(ARCHIVE_CRYPTO_SHA512_LIBC3) &__archive_libc3_sha512init, &__archive_libc3_sha512update, - &__archive_libc3_sha512final, + &__archive_libc3_sha512final #elif defined(ARCHIVE_CRYPTO_SHA512_LIBMD) &__archive_libmd_sha512init, &__archive_libmd_sha512update, - &__archive_libmd_sha512final, + &__archive_libmd_sha512final #elif defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM) &__archive_libsystem_sha512init, &__archive_libsystem_sha512update, - &__archive_libsystem_sha512final, + &__archive_libsystem_sha512final #elif defined(ARCHIVE_CRYPTO_SHA512_NETTLE) &__archive_nettle_sha512init, &__archive_nettle_sha512update, - &__archive_nettle_sha512final, + &__archive_nettle_sha512final #elif defined(ARCHIVE_CRYPTO_SHA512_OPENSSL) &__archive_openssl_sha512init, &__archive_openssl_sha512update, - &__archive_openssl_sha512final, + &__archive_openssl_sha512final #elif defined(ARCHIVE_CRYPTO_SHA512_WIN) &__archive_windowsapi_sha512init, &__archive_windowsapi_sha512update, - &__archive_windowsapi_sha512final, + &__archive_windowsapi_sha512final #elif !defined(ARCHIVE_SHA512_COMPILE_TEST) &__archive_stub_sha512init, &__archive_stub_sha512update, - &__archive_stub_sha512final, + &__archive_stub_sha512final #endif - &pbkdf2_sha1, - &decrypto_aes_ctr_init, - &decrypto_aes_ctr_update, - &decrypto_aes_ctr_release, - }; diff --git a/libarchive/archive_crypto_private.h b/libarchive/archive_crypto_private.h index 30d77047e..f8b1fb3c3 100644 --- a/libarchive/archive_crypto_private.h +++ b/libarchive/archive_crypto_private.h @@ -1,7 +1,6 @@ /*- * Copyright (c) 2003-2007 Tim Kientzle * Copyright (c) 2011 Andres Mejia -* Copyright (c) 2014 Michihiro NAKAJIMA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -255,51 +254,6 @@ typedef Digest_CTX archive_sha512_ctx; typedef unsigned char archive_sha512_ctx; #endif -#ifdef __APPLE__ -#include -#include -#define AES_BLOCK_SIZE 16 -#define AES_MAX_KEY_SIZE kCCKeySizeAES256 - -typedef struct { - CCCryptorRef ctx; - uint8_t key[AES_MAX_KEY_SIZE]; - unsigned key_len; - uint8_t nonce[AES_BLOCK_SIZE]; - uint8_t encr_buf[AES_BLOCK_SIZE]; - unsigned encr_pos; -} archive_crypto_ctx; - -#elif defined(HAVE_LIBNETTLE) -#include -#include - -typedef struct { - struct aes_ctx ctx; - uint8_t key[AES_MAX_KEY_SIZE]; - unsigned key_len; - uint8_t nonce[AES_BLOCK_SIZE]; - uint8_t encr_buf[AES_BLOCK_SIZE]; - unsigned encr_pos; -} archive_crypto_ctx; - -#elif defined(HAVE_LIBCRYPTO) -#include -#define AES_BLOCK_SIZE 16 -#define AES_MAX_KEY_SIZE 32 - -typedef struct { - EVP_CIPHER_CTX ctx; - const EVP_CIPHER *type; - uint8_t key[AES_MAX_KEY_SIZE]; - unsigned key_len; - uint8_t nonce[AES_BLOCK_SIZE]; - uint8_t encr_buf[AES_BLOCK_SIZE]; - unsigned encr_pos; -} archive_crypto_ctx; - -#endif - /* defines */ #if defined(ARCHIVE_CRYPTO_MD5_LIBC) ||\ defined(ARCHIVE_CRYPTO_MD5_LIBMD) || \ @@ -393,18 +347,6 @@ typedef struct { #define archive_sha512_update(ctx, buf, n)\ __archive_crypto.sha512update(ctx, buf, n) - -#define archive_pbkdf2_sha1(pw, pw_len, salt, salt_len, rounds, dk, dk_len)\ - __archive_crypto.pbkdf2sha1(pw, pw_len, salt, salt_len, rounds, dk, dk_len) - -#define archive_decrypto_aes_ctr_init(ctx, key, key_len) \ - __archive_crypto.decrypto_aes_ctr_init(ctx, key, key_len) -#define archive_decrypto_aes_ctr_update(ctx, in, in_len, out, out_len) \ - __archive_crypto.decrypto_aes_ctr_update(ctx, in, in_len, out, out_len) -#define archive_decrypto_aes_ctr_release(ctx) \ - __archive_crypto.decrypto_aes_ctr_release(ctx) - - /* Minimal interface to crypto functionality for internal use in libarchive */ struct archive_crypto { @@ -427,15 +369,6 @@ struct archive_crypto int (*sha512init)(archive_sha512_ctx *); int (*sha512update)(archive_sha512_ctx *, const void *, size_t); int (*sha512final)(archive_sha512_ctx *, void *); - /* PKCS5 PBKDF2 HMAC-SHA1 */ - int (*pbkdf2sha1)(const char *pw, size_t pw_len, const uint8_t *salt, - size_t salt_len, unsigned rounds, uint8_t *derived_key, - size_t derived_key_len); - /* AES CTR mode */ - int (*decrypto_aes_ctr_init)(archive_crypto_ctx *, const uint8_t *, size_t); - int (*decrypto_aes_ctr_update)(archive_crypto_ctx *, const uint8_t *, - size_t, uint8_t *, size_t *); - int (*decrypto_aes_ctr_release)(archive_crypto_ctx *); }; extern const struct archive_crypto __archive_crypto; diff --git a/libarchive/archive_cryptor.c b/libarchive/archive_cryptor.c new file mode 100644 index 000000000..e204b94d6 --- /dev/null +++ b/libarchive/archive_cryptor.c @@ -0,0 +1,287 @@ +/*- +* Copyright (c) 2014 Michihiro NAKAJIMA +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "archive_platform.h" + +#ifdef HAVE_STRING_H +#include +#endif +#include "archive.h" +#include "archive_cryptor_private.h" + +#ifdef __APPLE__ + +static int +pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt, + size_t salt_len, unsigned rounds, uint8_t *derived_key, + size_t derived_key_len) +{ + CCKeyDerivationPBKDF(kCCPBKDF2, (const char *)pw, + pw_len, salt, salt_len, kCCPRFHmacAlgSHA1, rounds, + derived_key, derived_key_len); + return 0; +} + +#elif defined(HAVE_LIBNETTLE) + +static int +pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt, + size_t salt_len, unsigned rounds, uint8_t *derived_key, + size_t derived_key_len) { + pbkdf2_hmac_sha1((unsigned)pw_len, (const uint8_t *)pw, rounds, + salt_len, salt, derived_key_len, derived_key); + return 0; +} + +#elif defined(HAVE_LIBCRYPTO) + +static int +pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt, + size_t salt_len, unsigned rounds, uint8_t *derived_key, + size_t derived_key_len) { + + PKCS5_PBKDF2_HMAC_SHA1(pw, pw_len, salt, salt_len, rounds, + derived_key_len, derived_key); + return 0; +} + +#else + +/* Stub */ +static int +pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt, + size_t salt_len, unsigned rounds, uint8_t *derived_key, + size_t derived_key_len) { + (void)pw; /* UNUSED */ + (void)pw_len; /* UNUSED */ + (void)salt; /* UNUSED */ + (void)salt_len; /* UNUSED */ + (void)rounds; /* UNUSED */ + (void)derived_key; /* UNUSED */ + (void)derived_key_len; /* UNUSED */ + return -1; /* UNSUPPORTED */ +} + +#endif + +#ifdef __APPLE__ + +static int +decrypto_aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, + size_t key_len) +{ + CCCryptorStatus r; + + ctx->key_len = key_len; + memcpy(ctx->key, key, key_len); + memset(ctx->nonce, 0, sizeof(ctx->nonce)); + ctx->encr_pos = AES_BLOCK_SIZE; + r = CCCryptorCreateWithMode(kCCEncrypt, kCCModeECB, kCCAlgorithmAES, + ccNoPadding, NULL, key, key_len, NULL, 0, 0, 0, &ctx->ctx); + return (r == kCCSuccess)? 0: -1; +} + +static int +aes_ctr_encrypt_counter(archive_crypto_ctx *ctx) +{ + CCCryptorRef ref = ctx->ctx; + CCCryptorStatus r; + + r = CCCryptorReset(ref, NULL); + if (r != kCCSuccess) + return -1; + r = CCCryptorUpdate(ref, ctx->nonce, AES_BLOCK_SIZE, ctx->encr_buf, + AES_BLOCK_SIZE, NULL); + return (r == kCCSuccess)? 0: -1; +} + +static int +decrypto_aes_ctr_release(archive_crypto_ctx *ctx) +{ + memset(ctx->key, 0, ctx->key_len); + memset(ctx->nonce, 0, sizeof(ctx->nonce)); + return 0; +} + +#elif defined(HAVE_LIBNETTLE) + +static int +decrypto_aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, + size_t key_len) +{ + ctx->key_len = key_len; + memcpy(ctx->key, key, key_len); + memset(ctx->nonce, 0, sizeof(ctx->nonce)); + ctx->encr_pos = AES_BLOCK_SIZE; + memset(&ctx->ctx, 0, sizeof(ctx->ctx)); + return 0; +} + +static int +aes_ctr_encrypt_counter(archive_crypto_ctx *ctx) +{ + aes_set_encrypt_key(&ctx->ctx, ctx->key_len, ctx->key); + aes_encrypt(&ctx->ctx, AES_BLOCK_SIZE, ctx->encr_buf, ctx->nonce); + return 0; +} + +static int +decrypto_aes_ctr_release(archive_crypto_ctx *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); + return 0; +} + +#elif defined(HAVE_LIBCRYPTO) + +static int +decrypto_aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, + size_t key_len) +{ + + switch (key_len) { + case 16: ctx->type = EVP_aes_128_ecb(); break; + case 24: ctx->type = EVP_aes_192_ecb(); break; + case 32: ctx->type = EVP_aes_256_ecb(); break; + default: ctx->type = NULL; return -1; + } + + ctx->key_len = key_len; + memcpy(ctx->key, key, key_len); + memset(ctx->nonce, 0, sizeof(ctx->nonce)); + ctx->encr_pos = AES_BLOCK_SIZE; + EVP_CIPHER_CTX_init(&ctx->ctx); + return 0; +} + +static int +aes_ctr_encrypt_counter(archive_crypto_ctx *ctx) +{ + int outl = 0; + int r; + + r = EVP_EncryptInit_ex(&ctx->ctx, ctx->type, NULL, ctx->key, NULL); + if (r == 0) + return -1; + r = EVP_EncryptUpdate(&ctx->ctx, ctx->encr_buf, &outl, ctx->nonce, + AES_BLOCK_SIZE); + if (r == 0 || outl != AES_BLOCK_SIZE) + return -1; + return 0; +} + +static int +decrypto_aes_ctr_release(archive_crypto_ctx *ctx) +{ + EVP_CIPHER_CTX_cleanup(&ctx->ctx); + memset(ctx->key, 0, ctx->key_len); + memset(ctx->nonce, 0, sizeof(ctx->nonce)); + return 0; +} + +#else + +/* Stub */ +static int +decrypto_aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, + size_t key_len) +{ + (void)ctx; /* UNUSED */ + (void)key; /* UNUSED */ + (void)key_len; /* UNUSED */ + return -1; +} + +static int +aes_ctr_encrypt_counter(archive_crypto_ctx *ctx) +{ + (void)ctx; /* UNUSED */ +} + +static int +decrypto_aes_ctr_release(archive_crypto_ctx *ctx) +{ + (void)ctx; /* UNUSED */ + return 0; +} + +#endif + +static void +aes_ctr_increase_counter(archive_crypto_ctx *ctx) +{ + uint8_t *const nonce = ctx->nonce; + int j; + + for (j = 0; j < 8; j++) { + if (++nonce[j]) + break; + } +} + +static int +decrypto_aes_ctr_update(archive_crypto_ctx *ctx, const uint8_t * const in, + size_t in_len, uint8_t * const out, size_t *out_len) +{ + uint8_t *const ebuf = ctx->encr_buf; + unsigned pos = ctx->encr_pos; + unsigned max = (unsigned)((in_len < *out_len)? in_len: *out_len); + unsigned i; + + for (i = 0; i < max; ) { + if (pos == AES_BLOCK_SIZE) { + aes_ctr_increase_counter(ctx); + if (aes_ctr_encrypt_counter(ctx) != 0) + return -1; + while (max -i >= AES_BLOCK_SIZE) { + for (pos = 0; pos < AES_BLOCK_SIZE; pos++) + out[i+pos] = in[i+pos] ^ ebuf[pos]; + i += AES_BLOCK_SIZE; + aes_ctr_increase_counter(ctx); + if (aes_ctr_encrypt_counter(ctx) != 0) + return -1; + } + pos = 0; + if (i >= max) + break; + } + out[i] = in[i] ^ ebuf[pos++]; + i++; + } + ctx->encr_pos = pos; + *out_len = i; + + return 0; +} + + +const struct archive_cryptor __archive_cryptor = +{ + &pbkdf2_sha1, + &decrypto_aes_ctr_init, + &decrypto_aes_ctr_update, + &decrypto_aes_ctr_release, + +}; diff --git a/libarchive/archive_cryptor_private.h b/libarchive/archive_cryptor_private.h new file mode 100644 index 000000000..4278bc384 --- /dev/null +++ b/libarchive/archive_cryptor_private.h @@ -0,0 +1,106 @@ +/*- +* Copyright (c) 2014 Michihiro NAKAJIMA +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif + +#ifndef ARCHIVE_CRYPTOR_PRIVATE_H_INCLUDED +#define ARCHIVE_CRYPTOR_PRIVATE_H_INCLUDED + +#ifdef __APPLE__ +#include +#include +#define AES_BLOCK_SIZE 16 +#define AES_MAX_KEY_SIZE kCCKeySizeAES256 + +typedef struct { + CCCryptorRef ctx; + uint8_t key[AES_MAX_KEY_SIZE]; + unsigned key_len; + uint8_t nonce[AES_BLOCK_SIZE]; + uint8_t encr_buf[AES_BLOCK_SIZE]; + unsigned encr_pos; +} archive_crypto_ctx; + +#elif defined(HAVE_LIBNETTLE) +#include +#include + +typedef struct { + struct aes_ctx ctx; + uint8_t key[AES_MAX_KEY_SIZE]; + unsigned key_len; + uint8_t nonce[AES_BLOCK_SIZE]; + uint8_t encr_buf[AES_BLOCK_SIZE]; + unsigned encr_pos; +} archive_crypto_ctx; + +#elif defined(HAVE_LIBCRYPTO) +#include +#define AES_BLOCK_SIZE 16 +#define AES_MAX_KEY_SIZE 32 + +typedef struct { + EVP_CIPHER_CTX ctx; + const EVP_CIPHER *type; + uint8_t key[AES_MAX_KEY_SIZE]; + unsigned key_len; + uint8_t nonce[AES_BLOCK_SIZE]; + uint8_t encr_buf[AES_BLOCK_SIZE]; + unsigned encr_pos; +} archive_crypto_ctx; + +#endif + +/* defines */ +#define archive_pbkdf2_sha1(pw, pw_len, salt, salt_len, rounds, dk, dk_len)\ + __archive_cryptor.pbkdf2sha1(pw, pw_len, salt, salt_len, rounds, dk, dk_len) + +#define archive_decrypto_aes_ctr_init(ctx, key, key_len) \ + __archive_cryptor.decrypto_aes_ctr_init(ctx, key, key_len) +#define archive_decrypto_aes_ctr_update(ctx, in, in_len, out, out_len) \ + __archive_cryptor.decrypto_aes_ctr_update(ctx, in, in_len, out, out_len) +#define archive_decrypto_aes_ctr_release(ctx) \ + __archive_cryptor.decrypto_aes_ctr_release(ctx) + +/* Minimal interface to cryptography functionality for internal use in + * libarchive */ +struct archive_cryptor +{ + /* PKCS5 PBKDF2 HMAC-SHA1 */ + int (*pbkdf2sha1)(const char *pw, size_t pw_len, const uint8_t *salt, + size_t salt_len, unsigned rounds, uint8_t *derived_key, + size_t derived_key_len); + /* AES CTR mode */ + int (*decrypto_aes_ctr_init)(archive_crypto_ctx *, const uint8_t *, size_t); + int (*decrypto_aes_ctr_update)(archive_crypto_ctx *, const uint8_t *, + size_t, uint8_t *, size_t *); + int (*decrypto_aes_ctr_release)(archive_crypto_ctx *); +}; + +extern const struct archive_cryptor __archive_cryptor; + +#endif diff --git a/libarchive/archive_read_support_format_zip.c b/libarchive/archive_read_support_format_zip.c index a3c3564dd..68a5bb0fd 100644 --- a/libarchive/archive_read_support_format_zip.c +++ b/libarchive/archive_read_support_format_zip.c @@ -54,6 +54,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_zip.c 201102 #include "archive.h" #include "archive_crypto_private.h" +#include "archive_cryptor_private.h" #include "archive_endian.h" #include "archive_entry.h" #include "archive_entry_locale.h"