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 */ 43 int __libarchive_hmac_build_hack(void) { 44 return 0; 45 } 46 47 48 #ifdef ARCHIVE_HMAC_USE_Apple_CommonCrypto 49 50 static 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 57 static 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 64 static 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 71 static 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 static int 80 __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) 81 { 82 BCRYPT_ALG_HANDLE hAlg; 83 BCRYPT_HASH_HANDLE hHash; 84 DWORD hash_len; 85 PBYTE hash; 86 ULONG result; 87 NTSTATUS status; 88 89 ctx->hAlg = NULL; 90 status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA1_ALGORITHM, 91 MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG); 92 if (!BCRYPT_SUCCESS(status)) 93 return -1; 94 status = BCryptGetProperty(hAlg, BCRYPT_HASH_LENGTH, (PUCHAR)&hash_len, 95 sizeof(hash_len), &result, 0); 96 if (!BCRYPT_SUCCESS(status)) { 97 BCryptCloseAlgorithmProvider(hAlg, 0); 98 return -1; 99 } 100 hash = (PBYTE)HeapAlloc(GetProcessHeap(), 0, hash_len); 101 if (hash == NULL) { 102 BCryptCloseAlgorithmProvider(hAlg, 0); 103 return -1; 104 } 105 status = BCryptCreateHash(hAlg, &hHash, NULL, 0, 106 (PUCHAR)key, (ULONG)key_len, BCRYPT_HASH_REUSABLE_FLAG); 107 if (!BCRYPT_SUCCESS(status)) { 108 BCryptCloseAlgorithmProvider(hAlg, 0); 109 HeapFree(GetProcessHeap(), 0, hash); 110 return -1; 111 } 112 113 ctx->hAlg = hAlg; 114 ctx->hHash = hHash; 115 ctx->hash_len = hash_len; 116 ctx->hash = hash; 117 118 return 0; 119 } 120 121 static void 122 __hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, 123 size_t data_len) 124 { 125 BCryptHashData(ctx->hHash, (PUCHAR)(uintptr_t)data, (ULONG)data_len, 0); 126 } 127 128 static void 129 __hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) 130 { 131 BCryptFinishHash(ctx->hHash, ctx->hash, ctx->hash_len, 0); 132 if (ctx->hash_len == *out_len) 133 memcpy(out, ctx->hash, *out_len); 134 } 135 136 static void 137 __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) 138 { 139 if (ctx->hAlg != NULL) { 140 BCryptCloseAlgorithmProvider(ctx->hAlg, 0); 141 HeapFree(GetProcessHeap(), 0, ctx->hash); 142 ctx->hAlg = NULL; 143 } 144 } 145 146 #elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_HMAC_H) 147 148 static int 149 __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) 150 { 151 hmac_sha1_set_key(ctx, key_len, key); 152 return 0; 153 } 154 155 static void 156 __hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, 157 size_t data_len) 158 { 159 hmac_sha1_update(ctx, data_len, data); 160 } 161 162 static void 163 __hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) 164 { 165 hmac_sha1_digest(ctx, (unsigned)*out_len, out); 166 } 167 168 static void 169 __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) 170 { 171 memset(ctx, 0, sizeof(*ctx)); 172 } 173 174 #elif defined(HAVE_LIBCRYPTO) 175 176 static int 177 __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) 178 { 179 HMAC_CTX_init(ctx); 180 HMAC_Init(ctx, key, key_len, EVP_sha1()); 181 return 0; 182 } 183 184 static void 185 __hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, 186 size_t data_len) 187 { 188 HMAC_Update(ctx, data, data_len); 189 } 190 191 static void 192 __hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) 193 { 194 unsigned int len = (unsigned int)*out_len; 195 HMAC_Final(ctx, out, &len); 196 *out_len = len; 197 } 198 199 static void 200 __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) 201 { 202 HMAC_CTX_cleanup(ctx); 203 memset(ctx, 0, sizeof(*ctx)); 204 } 205 206 #else 207 208 /* Stub */ 209 static int 210 __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) 211 { 212 (void)ctx;/* UNUSED */ 213 (void)key;/* UNUSED */ 214 (void)key_len;/* UNUSED */ 215 return -1; 216 } 217 218 static void 219 __hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, 220 size_t data_len) 221 { 222 (void)ctx;/* UNUSED */ 223 (void)data;/* UNUSED */ 224 (void)data_len;/* UNUSED */ 225 } 226 227 static void 228 __hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) 229 { 230 (void)ctx;/* UNUSED */ 231 (void)out;/* UNUSED */ 232 (void)out_len;/* UNUSED */ 233 } 234 235 static void 236 __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) 237 { 238 (void)ctx;/* UNUSED */ 239 } 240 241 #endif 242 243 const struct archive_hmac __archive_hmac = { 244 &__hmac_sha1_init, 245 &__hmac_sha1_update, 246 &__hmac_sha1_final, 247 &__hmac_sha1_cleanup, 248 }; 249