summaryrefslogtreecommitdiff
path: root/libarchive
diff options
context:
space:
mode:
authorMichihiro NAKAJIMA <ggcueroad@gmail.com>2014-10-13 14:41:21 +0900
committerMichihiro NAKAJIMA <ggcueroad@gmail.com>2014-10-13 14:41:21 +0900
commit178bf9b890c71f8a64e1960e5449faa84a84c4eb (patch)
tree4ef755c22fbb727c5174ba61083272757ddb1fc4 /libarchive
parent982da0b48919db6adcdddb2efcc8b1e685b9f218 (diff)
downloadlibarchive-178bf9b890c71f8a64e1960e5449faa84a84c4eb.tar.gz
Implement HMAC, PBKDF2 and AES support on Windows using CNG for
Zip encryption and decryption.
Diffstat (limited to 'libarchive')
-rw-r--r--libarchive/archive_cryptor.c129
-rw-r--r--libarchive/archive_cryptor_private.h14
-rw-r--r--libarchive/archive_hmac.c69
-rw-r--r--libarchive/archive_hmac_private.h13
4 files changed, 220 insertions, 5 deletions
diff --git a/libarchive/archive_cryptor.c b/libarchive/archive_cryptor.c
index 1d819fd4..94dce5ac 100644
--- a/libarchive/archive_cryptor.c
+++ b/libarchive/archive_cryptor.c
@@ -44,6 +44,34 @@ pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
return 0;
}
+#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
+#ifdef _MSC_VER
+#pragma comment(lib, "Bcrypt.lib")
+#endif
+
+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)
+{
+ NTSTATUS status;
+ BCRYPT_ALG_HANDLE hAlg;
+
+ status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA1_ALGORITHM,
+ MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG);
+ if (!BCRYPT_SUCCESS(status))
+ return -1;
+
+ status = BCryptDeriveKeyPBKDF2(hAlg,
+ (PUCHAR)(uintptr_t)pw, (ULONG)pw_len,
+ (PUCHAR)(uintptr_t)salt, (ULONG)salt_len, rounds,
+ (PUCHAR)derived_key, (ULONG)derived_key_len, 0);
+
+ BCryptCloseAlgorithmProvider(hAlg, 0);
+
+ return (BCRYPT_SUCCESS(status)) ? 0: -1;
+}
+
#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_PBKDF2_H)
static int
@@ -124,6 +152,107 @@ aes_ctr_release(archive_crypto_ctx *ctx)
return 0;
}
+#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
+
+static int
+aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
+{
+ BCRYPT_ALG_HANDLE hAlg;
+ BCRYPT_KEY_HANDLE hKey;
+ DWORD keyObj_len, aes_key_len;
+ PBYTE keyObj;
+ ULONG result;
+ NTSTATUS status;
+ BCRYPT_KEY_LENGTHS_STRUCT key_lengths;
+
+ ctx->hAlg = NULL;
+ ctx->hKey = NULL;
+ ctx->keyObj = NULL;
+ switch (key_len) {
+ case 16: aes_key_len = 128; break;
+ case 24: aes_key_len = 192; break;
+ case 32: aes_key_len = 256; break;
+ default: return -1;
+ }
+ status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_AES_ALGORITHM,
+ MS_PRIMITIVE_PROVIDER, 0);
+ if (!BCRYPT_SUCCESS(status))
+ return -1;
+ status = BCryptGetProperty(hAlg, BCRYPT_KEY_LENGTHS, (PUCHAR)&key_lengths,
+ sizeof(key_lengths), &result, 0);
+ if (!BCRYPT_SUCCESS(status)) {
+ BCryptCloseAlgorithmProvider(hAlg, 0);
+ return -1;
+ }
+ if (key_lengths.dwMinLength > aes_key_len
+ || key_lengths.dwMaxLength < aes_key_len) {
+ BCryptCloseAlgorithmProvider(hAlg, 0);
+ return -1;
+ }
+ status = BCryptGetProperty(hAlg, BCRYPT_OBJECT_LENGTH, (PUCHAR)&keyObj_len,
+ sizeof(keyObj_len), &result, 0);
+ if (!BCRYPT_SUCCESS(status)) {
+ BCryptCloseAlgorithmProvider(hAlg, 0);
+ return -1;
+ }
+ keyObj = (PBYTE)HeapAlloc(GetProcessHeap(), 0, keyObj_len);
+ if (keyObj == NULL) {
+ BCryptCloseAlgorithmProvider(hAlg, 0);
+ return -1;
+ }
+ status = BCryptSetProperty(hAlg, BCRYPT_CHAINING_MODE,
+ (PUCHAR)BCRYPT_CHAIN_MODE_ECB, sizeof(BCRYPT_CHAIN_MODE_ECB), 0);
+ if (!BCRYPT_SUCCESS(status)) {
+ BCryptCloseAlgorithmProvider(hAlg, 0);
+ HeapFree(GetProcessHeap(), 0, keyObj);
+ return -1;
+ }
+ status = BCryptGenerateSymmetricKey(hAlg, &hKey,
+ keyObj, keyObj_len,
+ (PUCHAR)(uintptr_t)key, (ULONG)key_len, 0);
+ if (!BCRYPT_SUCCESS(status)) {
+ BCryptCloseAlgorithmProvider(hAlg, 0);
+ HeapFree(GetProcessHeap(), 0, keyObj);
+ return -1;
+ }
+
+ ctx->hAlg = hAlg;
+ ctx->hKey = hKey;
+ ctx->keyObj = keyObj;
+ ctx->keyObj_len = keyObj_len;
+ ctx->encr_pos = AES_BLOCK_SIZE;
+
+ return 0;
+}
+
+static int
+aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
+{
+ NTSTATUS status;
+ ULONG result;
+
+ status = BCryptEncrypt(ctx->hKey, (PUCHAR)ctx->nonce, AES_BLOCK_SIZE,
+ NULL, NULL, 0, (PUCHAR)ctx->encr_buf, AES_BLOCK_SIZE,
+ &result, 0);
+ return BCRYPT_SUCCESS(status) ? 0 : -1;
+}
+
+static int
+aes_ctr_release(archive_crypto_ctx *ctx)
+{
+
+ if (ctx->hAlg != NULL) {
+ BCryptCloseAlgorithmProvider(ctx->hAlg, 0);
+ ctx->hAlg = NULL;
+ BCryptDestroyKey(ctx->hKey);
+ ctx->hKey = NULL;
+ HeapFree(GetProcessHeap(), 0, ctx->keyObj);
+ ctx->keyObj = NULL;
+ }
+ memset(ctx, 0, sizeof(*ctx));
+ return 0;
+}
+
#elif defined(HAVE_LIBNETTLE)
static int
diff --git a/libarchive/archive_cryptor_private.h b/libarchive/archive_cryptor_private.h
index 35b3385e..88c208db 100644
--- a/libarchive/archive_cryptor_private.h
+++ b/libarchive/archive_cryptor_private.h
@@ -45,14 +45,16 @@ typedef struct {
unsigned encr_pos;
} archive_crypto_ctx;
-#elif defined(_WIN32) && !defined(__CYGWIN__)
+#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
+#include <Bcrypt.h>
#define AES_MAX_KEY_SIZE 32
#define AES_BLOCK_SIZE 16
typedef struct {
- int ctx;
- uint8_t key[AES_MAX_KEY_SIZE];
- unsigned key_len;
+ BCRYPT_ALG_HANDLE hAlg;
+ BCRYPT_KEY_HANDLE hKey;
+ PBYTE keyObj;
+ DWORD keyObj_len;
uint8_t nonce[AES_BLOCK_SIZE];
uint8_t encr_buf[AES_BLOCK_SIZE];
unsigned encr_pos;
@@ -88,6 +90,10 @@ typedef struct {
unsigned encr_pos;
} archive_crypto_ctx;
+#else
+
+typedef int archive_crypto_ctx;
+
#endif
/* defines */
diff --git a/libarchive/archive_hmac.c b/libarchive/archive_hmac.c
index 9e6834ec..898853bd 100644
--- a/libarchive/archive_hmac.c
+++ b/libarchive/archive_hmac.c
@@ -60,6 +60,75 @@ __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
memset(ctx, 0, sizeof(*ctx));
}
+#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
+
+static int
+__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
+{
+ BCRYPT_ALG_HANDLE hAlg;
+ BCRYPT_HASH_HANDLE hHash;
+ DWORD hash_len;
+ PBYTE hash;
+ ULONG result;
+ NTSTATUS status;
+
+ ctx->hAlg = NULL;
+ status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA1_ALGORITHM,
+ MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG);
+ if (!BCRYPT_SUCCESS(status))
+ return -1;
+ status = BCryptGetProperty(hAlg, BCRYPT_HASH_LENGTH, (PUCHAR)&hash_len,
+ sizeof(hash_len), &result, 0);
+ if (!BCRYPT_SUCCESS(status)) {
+ BCryptCloseAlgorithmProvider(hAlg, 0);
+ return -1;
+ }
+ hash = (PBYTE)HeapAlloc(GetProcessHeap(), 0, hash_len);
+ if (hash == NULL) {
+ BCryptCloseAlgorithmProvider(hAlg, 0);
+ return -1;
+ }
+ status = BCryptCreateHash(hAlg, &hHash, NULL, 0,
+ (PUCHAR)key, (ULONG)key_len, BCRYPT_HASH_REUSABLE_FLAG);
+ if (!BCRYPT_SUCCESS(status)) {
+ BCryptCloseAlgorithmProvider(hAlg, 0);
+ HeapFree(GetProcessHeap(), 0, hash);
+ return -1;
+ }
+
+ ctx->hAlg = hAlg;
+ ctx->hHash = hHash;
+ ctx->hash_len = hash_len;
+ ctx->hash = hash;
+
+ return 0;
+}
+
+static void
+__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data,
+ size_t data_len)
+{
+ BCryptHashData(ctx->hHash, (PUCHAR)(uintptr_t)data, (ULONG)data_len, 0);
+}
+
+static void
+__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len)
+{
+ BCryptFinishHash(ctx->hHash, ctx->hash, ctx->hash_len, 0);
+ if (ctx->hash_len == *out_len)
+ memcpy(out, ctx->hash, *out_len);
+}
+
+static void
+__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
+{
+ if (ctx->hAlg != NULL) {
+ BCryptCloseAlgorithmProvider(ctx->hAlg, 0);
+ HeapFree(GetProcessHeap(), 0, ctx->hash);
+ ctx->hAlg = NULL;
+ }
+}
+
#elif defined(HAVE_LIBNETTLE)
static int
diff --git a/libarchive/archive_hmac_private.h b/libarchive/archive_hmac_private.h
index 223e7ca6..e5be3dc7 100644
--- a/libarchive/archive_hmac_private.h
+++ b/libarchive/archive_hmac_private.h
@@ -36,8 +36,15 @@
typedef CCHmacContext archive_hmac_sha1_ctx;
#elif defined(_WIN32) && !defined(__CYGWIN__)
+#include <Bcrypt.h>
-typedef int archive_hmac_sha1_ctx;
+typedef struct {
+ BCRYPT_ALG_HANDLE hAlg;
+ BCRYPT_HASH_HANDLE hHash;
+ DWORD hash_len;
+ PBYTE hash;
+
+} archive_hmac_sha1_ctx;
#elif defined(HAVE_LIBNETTLE)
#include <nettle/hmac.h>
@@ -49,6 +56,10 @@ typedef struct hmac_sha1_ctx archive_hmac_sha1_ctx;
typedef HMAC_CTX archive_hmac_sha1_ctx;
+#else
+
+typedef int archive_hmac_sha1_ctx;
+
#endif