archive_hmac.c revision 348608
1/*- 2* Copyright (c) 2014 Michihiro NAKAJIMA 3* All rights reserved. 4* 5* Redistribution and use in source and binary forms, with or without 6* modification, are permitted provided that the following conditions 7* are met: 8* 1. Redistributions of source code must retain the above copyright 9* notice, this list of conditions and the following disclaimer. 10* 2. Redistributions in binary form must reproduce the above copyright 11* notice, this list of conditions and the following disclaimer in the 12* documentation and/or other materials provided with the distribution. 13* 14* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24*/ 25 26#include "archive_platform.h" 27 28#ifdef HAVE_STRING_H 29#include <string.h> 30#endif 31#include "archive.h" 32#include "archive_hmac_private.h" 33 34/* 35 * On systems that do not support any recognized crypto libraries, 36 * the archive_hmac.c file is expected to define no usable symbols. 37 * 38 * But some compilers and linkers choke on empty object files, so 39 * define a public symbol that will always exist. This could 40 * be removed someday if this file gains another always-present 41 * symbol definition. 42 */ 43int __libarchive_hmac_build_hack(void) { 44 return 0; 45} 46 47 48#ifdef ARCHIVE_HMAC_USE_Apple_CommonCrypto 49 50static int 51__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) 52{ 53 CCHmacInit(ctx, kCCHmacAlgSHA1, key, key_len); 54 return 0; 55} 56 57static void 58__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, 59 size_t data_len) 60{ 61 CCHmacUpdate(ctx, data, data_len); 62} 63 64static void 65__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) 66{ 67 CCHmacFinal(ctx, out); 68 *out_len = 20; 69} 70 71static void 72__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) 73{ 74 memset(ctx, 0, sizeof(*ctx)); 75} 76 77#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) 78 79#ifndef BCRYPT_HASH_REUSABLE_FLAG 80# define BCRYPT_HASH_REUSABLE_FLAG 0x00000020 81#endif 82 83static int 84__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) 85{ 86#pragma GCC diagnostic ignored "-Wcast-qual" 87 BCRYPT_ALG_HANDLE hAlg; 88 BCRYPT_HASH_HANDLE hHash; 89 DWORD hash_len; 90 PBYTE hash; 91 ULONG result; 92 NTSTATUS status; 93 94 ctx->hAlg = NULL; 95 status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA1_ALGORITHM, 96 MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG); 97 if (!BCRYPT_SUCCESS(status)) 98 return -1; 99 status = BCryptGetProperty(hAlg, BCRYPT_HASH_LENGTH, (PUCHAR)&hash_len, 100 sizeof(hash_len), &result, 0); 101 if (!BCRYPT_SUCCESS(status)) { 102 BCryptCloseAlgorithmProvider(hAlg, 0); 103 return -1; 104 } 105 hash = (PBYTE)HeapAlloc(GetProcessHeap(), 0, hash_len); 106 if (hash == NULL) { 107 BCryptCloseAlgorithmProvider(hAlg, 0); 108 return -1; 109 } 110 status = BCryptCreateHash(hAlg, &hHash, NULL, 0, 111 (PUCHAR)key, (ULONG)key_len, BCRYPT_HASH_REUSABLE_FLAG); 112 if (!BCRYPT_SUCCESS(status)) { 113 BCryptCloseAlgorithmProvider(hAlg, 0); 114 HeapFree(GetProcessHeap(), 0, hash); 115 return -1; 116 } 117 118 ctx->hAlg = hAlg; 119 ctx->hHash = hHash; 120 ctx->hash_len = hash_len; 121 ctx->hash = hash; 122 123 return 0; 124} 125 126static void 127__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, 128 size_t data_len) 129{ 130 BCryptHashData(ctx->hHash, (PUCHAR)(uintptr_t)data, (ULONG)data_len, 0); 131} 132 133static void 134__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) 135{ 136 BCryptFinishHash(ctx->hHash, ctx->hash, ctx->hash_len, 0); 137 if (ctx->hash_len == *out_len) 138 memcpy(out, ctx->hash, *out_len); 139} 140 141static void 142__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) 143{ 144 if (ctx->hAlg != NULL) { 145 BCryptCloseAlgorithmProvider(ctx->hAlg, 0); 146 HeapFree(GetProcessHeap(), 0, ctx->hash); 147 ctx->hAlg = NULL; 148 } 149} 150 151#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_HMAC_H) 152 153static int 154__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) 155{ 156 hmac_sha1_set_key(ctx, key_len, key); 157 return 0; 158} 159 160static void 161__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, 162 size_t data_len) 163{ 164 hmac_sha1_update(ctx, data_len, data); 165} 166 167static void 168__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) 169{ 170 hmac_sha1_digest(ctx, (unsigned)*out_len, out); 171} 172 173static void 174__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) 175{ 176 memset(ctx, 0, sizeof(*ctx)); 177} 178 179#elif defined(HAVE_LIBCRYPTO) 180 181static int 182__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) 183{ 184 *ctx = HMAC_CTX_new(); 185 if (*ctx == NULL) 186 return -1; 187 HMAC_Init_ex(*ctx, key, key_len, EVP_sha1(), NULL); 188 return 0; 189} 190 191static void 192__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, 193 size_t data_len) 194{ 195 HMAC_Update(*ctx, data, data_len); 196} 197 198static void 199__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) 200{ 201 unsigned int len = (unsigned int)*out_len; 202 HMAC_Final(*ctx, out, &len); 203 *out_len = len; 204} 205 206static void 207__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) 208{ 209 HMAC_CTX_free(*ctx); 210 *ctx = NULL; 211} 212 213#else 214 215/* Stub */ 216static int 217__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) 218{ 219 (void)ctx;/* UNUSED */ 220 (void)key;/* UNUSED */ 221 (void)key_len;/* UNUSED */ 222 return -1; 223} 224 225static void 226__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, 227 size_t data_len) 228{ 229 (void)ctx;/* UNUSED */ 230 (void)data;/* UNUSED */ 231 (void)data_len;/* UNUSED */ 232} 233 234static void 235__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) 236{ 237 (void)ctx;/* UNUSED */ 238 (void)out;/* UNUSED */ 239 (void)out_len;/* UNUSED */ 240} 241 242static void 243__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) 244{ 245 (void)ctx;/* UNUSED */ 246} 247 248#endif 249 250const struct archive_hmac __archive_hmac = { 251 &__hmac_sha1_init, 252 &__hmac_sha1_update, 253 &__hmac_sha1_final, 254 &__hmac_sha1_cleanup, 255}; 256