diff options
Diffstat (limited to 'libarchive')
-rw-r--r-- | libarchive/archive_cryptor.c | 129 | ||||
-rw-r--r-- | libarchive/archive_cryptor_private.h | 14 | ||||
-rw-r--r-- | libarchive/archive_hmac.c | 69 | ||||
-rw-r--r-- | libarchive/archive_hmac_private.h | 13 |
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 |