From: Michihiro NAKAJIMA Date: Mon, 2 Feb 2009 12:18:15 +0000 (-0500) Subject: Add support MD5/SHA1/SHA256/SHA384/SHA512 on Windows. X-Git-Tag: v2.7.0~358 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d3ee3530078c4982a00ab54d0c57746459d374e8;p=thirdparty%2Flibarchive.git Add support MD5/SHA1/SHA256/SHA384/SHA512 on Windows. It use CryptoAPI. Unfortunately, SHA256 nor SHA384 nor SHA512 are not supported on Windows XP and Windows 2000, and therefore I haven't tested those functions yet. SVN-Revision: 535 --- diff --git a/libarchive/archive_windows.c b/libarchive/archive_windows.c index 47e720ca4..c91ebdfee 100644 --- a/libarchive/archive_windows.c +++ b/libarchive/archive_windows.c @@ -918,4 +918,103 @@ la_write(int fd, const void *buf, size_t nbytes) return (bytes_written); } +#if !defined(HAVE_OPENSSL_MD5_H) && !defined(HAVE_OPENSSL_SHA_H) +/* + * Message digest functions. + */ +static void +Digest_Init(Digest_CTX *ctx, ALG_ID algId) +{ + + ctx->valid = 0; + if (!CryptAcquireContext(&ctx->cryptProv, NULL, NULL, + PROV_RSA_FULL, 0)) { + if (GetLastError() != NTE_BAD_KEYSET) + return; + if (!CryptAcquireContext(&ctx->cryptProv, NULL, NULL, + PROV_RSA_FULL, CRYPT_NEWKEYSET)) + return; + } + + if (!CryptCreateHash(ctx->cryptProv, algId, 0, 0, &ctx->hash)) { + CryptReleaseContext(ctx->cryptProv, 0); + return; + } + + ctx->valid = 1; +} + +static void +Digest_Update(Digest_CTX *ctx, const unsigned char *buf, size_t len) +{ + + if (!ctx->valid) + return; + + CryptHashData(ctx->hash, buf, (DWORD)len, 0); +} + +static void +Digest_Final(unsigned char *buf, int bufsize, Digest_CTX *ctx) +{ + DWORD siglen = bufsize; + + if (!ctx->valid) + return; + + CryptGetHashParam(ctx->hash, HP_HASHVAL, buf, &siglen, 0); + CryptDestroyHash(ctx->hash); + CryptReleaseContext(ctx->cryptProv, 0); + ctx->valid = 0; +} + +#define DIGEST_INIT(name, algid) \ +void name ## _Init(Digest_CTX *ctx)\ +{\ + Digest_Init(ctx, algid);\ +} + +#define DIGEST_UPDATE(name) \ +void name ## _Update(Digest_CTX *ctx, const unsigned char *buf, size_t len)\ +{\ + Digest_Update(ctx, buf, len);\ +} + +#define DIGEST_FINAL(name, size) \ +void name ## _Final(unsigned char buf[size], Digest_CTX *ctx)\ +{\ + Digest_Final(buf, size, ctx);\ +} + +DIGEST_INIT(MD5, CALG_MD5) +DIGEST_UPDATE(MD5) +DIGEST_FINAL(MD5, MD5_DIGEST_LENGTH) + +DIGEST_INIT(SHA1, CALG_SHA1) +DIGEST_UPDATE(SHA1) +DIGEST_FINAL(SHA1, SHA1_DIGEST_LENGTH) + +/* + * SHA256 nor SHA384 nor SHA512 are not supported on Windows XP and Windows 2000. + */ +#ifdef CALG_SHA256 +DIGEST_INIT(SHA256, CALG_SHA256) +DIGEST_UPDATE(SHA256) +DIGEST_FINAL(SHA256, SHA256_DIGEST_LENGTH) +#endif + +#ifdef CALG_SHA384 +DIGEST_INIT(SHA384, CALG_SHA384) +DIGEST_UPDATE(SHA384) +DIGEST_FINAL(SHA384, SHA384_DIGEST_LENGTH) +#endif + +#ifdef CALG_SHA512 +DIGEST_INIT(SHA512, CALG_SHA512) +DIGEST_UPDATE(SHA512) +DIGEST_FINAL(SHA512, SHA384_DIGEST_LENGTH) +#endif + +#endif /* !HAVE_OPENSSL_MD5_H && !HAVE_OPENSSL_SHA_H */ + #endif /* _WIN32 */ diff --git a/libarchive/archive_windows.h b/libarchive/archive_windows.h index 956d1dde3..02455d91c 100644 --- a/libarchive/archive_windows.h +++ b/libarchive/archive_windows.h @@ -1,4 +1,5 @@ /*- + * Copyright (c) 2009 Michihiro NAKAJIMA * Copyright (c) 2003-2006 Tim Kientzle * All rights reserved. * @@ -39,7 +40,7 @@ #include #include #include - +#include //#define EFTYPE 7 #if !defined(STDIN_FILENO) @@ -252,6 +253,43 @@ struct _timeval64i32 { #define SYSTEM_PATH_CHAR '\\' +/* Message digest define */ +#if !defined(HAVE_OPENSSL_MD5_H) && !defined(HAVE_OPENSSL_SHA_H) +typedef struct { + int valid; + HCRYPTPROV cryptProv; + HCRYPTHASH hash; +} Digest_CTX; +#endif + +#if !defined(HAVE_OPENSSL_MD5_H) && defined(CALG_MD5) +#define MD5_DIGEST_LENGTH 16 +#define HAVE_MD5 1 +#define MD5_CTX Digest_CTX +#endif +#ifndef HAVE_OPENSSL_SHA_H +#ifdef CALG_SHA1 +#define SHA1_DIGEST_LENGTH 20 +#define HAVE_SHA1 1 +#define SHA1_CTX Digest_CTX +#endif +#ifdef CALG_SHA256 +#define SHA256_DIGEST_LENGTH 32 +#define HAVE_SHA256 1 +#define SHA256_CTX Digest_CTX +#endif +#ifdef CALG_SHA384 +#define SHA384_DIGEST_LENGTH 48 +#define HAVE_SHA384 1 +#define SHA384_CTX Digest_CTX +#endif +#ifdef CALG_SHA512 +#define SHA512_DIGEST_LENGTH 64 +#define HAVE_SHA512 1 +#define SHA512_CTX Digest_CTX +#endif +#endif /* HAVE_OPENSSL_SHA_H */ + /* End of Win32 definitions. */ #ifdef __cplusplus @@ -285,6 +323,45 @@ extern ssize_t la_write(int fd, const void *buf, size_t nbytes); /* Convertion a Win32 API error code */ extern int _dosmaperr(unsigned long); +/* Message digest function */ +#if !defined(HAVE_OPENSSL_MD5_H) && !defined(HAVE_OPENSSL_SHA_H) +#ifdef MD5_DIGEST_LENGTH +extern void MD5_Init(Digest_CTX *ctx); +extern void MD5_Update(Digest_CTX *ctx, const unsigned char *buf, + size_t len); +extern void MD5_Final(unsigned char buf[MD5_DIGEST_LENGTH], + Digest_CTX *ctx); +#endif +#ifdef SHA1_DIGEST_LENGTH +extern void SHA1_Init(Digest_CTX *ctx); +extern void SHA1_Update(Digest_CTX *ctx, const unsigned char *buf, + size_t len); +extern void SHA1_Final(unsigned char buf[SHA1_DIGEST_LENGTH], + Digest_CTX *ctx); +#endif +#ifdef SHA256_DIGEST_LENGTH +extern void SHA256_Init(Digest_CTX *ctx); +extern void SHA256_Update(Digest_CTX *ctx, const unsigned char *buf, + size_t len); +extern void SHA256_Final(unsigned char buf[SHA256_DIGEST_LENGTH], + Digest_CTX *ctx); +#endif +#ifdef SHA384_DIGEST_LENGTH +extern void SHA384_Init(Digest_CTX *ctx); +extern void SHA384_Update(Digest_CTX *ctx, const unsigned char *buf, + size_t len); +extern void SHA384_Final(unsigned char buf[SHA384_DIGEST_LENGTH], + Digest_CTX *ctx); +#endif +#ifdef SHA512_DIGEST_LENGTH +extern void SHA512_Init(Digest_CTX *ctx); +extern void SHA512_Update(Digest_CTX *ctx, const unsigned char *buf, + size_t len); +extern void SHA512_Final(unsigned char buf[SHA512_DIGEST_LENGTH], + Digest_CTX *ctx); +#endif +#endif + #ifdef __cplusplus } #endif