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) && _WIN32_WINNT >= _WIN32_WINNT_VISTA 78 79 #ifndef BCRYPT_HASH_REUSABLE_FLAG 80 # define BCRYPT_HASH_REUSABLE_FLAG 0x00000020 81 #endif 82 83 static int 84 __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) 85 { 86 #ifdef __GNUC__ 87 #pragma GCC diagnostic ignored "-Wcast-qual" 88 #endif 89 BCRYPT_ALG_HANDLE hAlg; 90 BCRYPT_HASH_HANDLE hHash; 91 DWORD hash_len; 92 PBYTE hash; 93 ULONG result; 94 NTSTATUS status; 95 96 ctx->hAlg = NULL; 97 status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA1_ALGORITHM, 98 MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG); 99 if (!BCRYPT_SUCCESS(status)) 100 return -1; 101 status = BCryptGetProperty(hAlg, BCRYPT_HASH_LENGTH, (PUCHAR)&hash_len, 102 sizeof(hash_len), &result, 0); 103 if (!BCRYPT_SUCCESS(status)) { 104 BCryptCloseAlgorithmProvider(hAlg, 0); 105 return -1; 106 } 107 hash = (PBYTE)HeapAlloc(GetProcessHeap(), 0, hash_len); 108 if (hash == NULL) { 109 BCryptCloseAlgorithmProvider(hAlg, 0); 110 return -1; 111 } 112 status = BCryptCreateHash(hAlg, &hHash, NULL, 0, 113 (PUCHAR)key, (ULONG)key_len, BCRYPT_HASH_REUSABLE_FLAG); 114 if (!BCRYPT_SUCCESS(status)) { 115 BCryptCloseAlgorithmProvider(hAlg, 0); 116 HeapFree(GetProcessHeap(), 0, hash); 117 return -1; 118 } 119 120 ctx->hAlg = hAlg; 121 ctx->hHash = hHash; 122 ctx->hash_len = hash_len; 123 ctx->hash = hash; 124 125 return 0; 126 } 127 128 static void 129 __hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, 130 size_t data_len) 131 { 132 BCryptHashData(ctx->hHash, (PUCHAR)(uintptr_t)data, (ULONG)data_len, 0); 133 } 134 135 static void 136 __hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) 137 { 138 BCryptFinishHash(ctx->hHash, ctx->hash, ctx->hash_len, 0); 139 if (ctx->hash_len == *out_len) 140 memcpy(out, ctx->hash, *out_len); 141 } 142 143 static void 144 __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) 145 { 146 if (ctx->hAlg != NULL) { 147 BCryptCloseAlgorithmProvider(ctx->hAlg, 0); 148 HeapFree(GetProcessHeap(), 0, ctx->hash); 149 ctx->hAlg = NULL; 150 } 151 } 152 153 #elif defined(HAVE_LIBMBEDCRYPTO) && defined(HAVE_MBEDTLS_MD_H) 154 155 static int 156 __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) 157 { 158 const mbedtls_md_info_t *info; 159 int ret; 160 161 mbedtls_md_init(ctx); 162 info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); 163 if (info == NULL) { 164 mbedtls_md_free(ctx); 165 return (-1); 166 } 167 ret = mbedtls_md_setup(ctx, info, 1); 168 if (ret != 0) { 169 mbedtls_md_free(ctx); 170 return (-1); 171 } 172 ret = mbedtls_md_hmac_starts(ctx, key, key_len); 173 if (ret != 0) { 174 mbedtls_md_free(ctx); 175 return (-1); 176 } 177 return 0; 178 } 179 180 static void 181 __hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, 182 size_t data_len) 183 { 184 mbedtls_md_hmac_update(ctx, data, data_len); 185 } 186 187 static void __hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) 188 { 189 (void)out_len; /* UNUSED */ 190 191 mbedtls_md_hmac_finish(ctx, out); 192 } 193 194 static void __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) 195 { 196 mbedtls_md_free(ctx); 197 memset(ctx, 0, sizeof(*ctx)); 198 } 199 200 #elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_HMAC_H) 201 #include <nettle/version.h> 202 203 static int 204 __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) 205 { 206 hmac_sha1_set_key(ctx, key_len, key); 207 return 0; 208 } 209 210 static void 211 __hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, 212 size_t data_len) 213 { 214 hmac_sha1_update(ctx, data_len, data); 215 } 216 217 static void 218 __hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) 219 { 220 #if NETTLE_VERSION_MAJOR < 4 221 hmac_sha1_digest(ctx, (unsigned)*out_len, out); 222 #else 223 hmac_sha1_digest(ctx, out); 224 *out_len = SHA1_DIGEST_SIZE; 225 #endif 226 } 227 228 static void 229 __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) 230 { 231 memset(ctx, 0, sizeof(*ctx)); 232 } 233 234 #elif defined(HAVE_LIBCRYPTO) 235 236 static int 237 __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) 238 { 239 #if OPENSSL_VERSION_NUMBER >= 0x30000000L 240 EVP_MAC *mac; 241 242 char sha1[] = "SHA1"; 243 OSSL_PARAM params[] = { 244 OSSL_PARAM_utf8_string("digest", sha1, sizeof(sha1) - 1), 245 OSSL_PARAM_END 246 }; 247 248 mac = EVP_MAC_fetch(NULL, "HMAC", NULL); 249 *ctx = EVP_MAC_CTX_new(mac); 250 EVP_MAC_free(mac); 251 if (*ctx == NULL) 252 return -1; 253 254 EVP_MAC_init(*ctx, key, key_len, params); 255 #else 256 *ctx = HMAC_CTX_new(); 257 if (*ctx == NULL) 258 return -1; 259 HMAC_Init_ex(*ctx, key, key_len, EVP_sha1(), NULL); 260 #endif 261 return 0; 262 } 263 264 static void 265 __hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, 266 size_t data_len) 267 { 268 #if OPENSSL_VERSION_NUMBER >= 0x30000000L 269 EVP_MAC_update(*ctx, data, data_len); 270 #else 271 HMAC_Update(*ctx, data, data_len); 272 #endif 273 } 274 275 static void 276 __hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) 277 { 278 #if OPENSSL_VERSION_NUMBER >= 0x30000000L 279 size_t len = *out_len; 280 #else 281 unsigned int len = (unsigned int)*out_len; 282 #endif 283 284 #if OPENSSL_VERSION_NUMBER >= 0x30000000L 285 EVP_MAC_final(*ctx, out, &len, *out_len); 286 #else 287 HMAC_Final(*ctx, out, &len); 288 #endif 289 *out_len = len; 290 } 291 292 static void 293 __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) 294 { 295 #if OPENSSL_VERSION_NUMBER >= 0x30000000L 296 EVP_MAC_CTX_free(*ctx); 297 #else 298 HMAC_CTX_free(*ctx); 299 #endif 300 *ctx = NULL; 301 } 302 303 #else 304 305 /* Stub */ 306 static int 307 __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) 308 { 309 (void)ctx;/* UNUSED */ 310 (void)key;/* UNUSED */ 311 (void)key_len;/* UNUSED */ 312 return -1; 313 } 314 315 static void 316 __hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, 317 size_t data_len) 318 { 319 (void)ctx;/* UNUSED */ 320 (void)data;/* UNUSED */ 321 (void)data_len;/* UNUSED */ 322 } 323 324 static void 325 __hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) 326 { 327 (void)ctx;/* UNUSED */ 328 (void)out;/* UNUSED */ 329 (void)out_len;/* UNUSED */ 330 } 331 332 static void 333 __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) 334 { 335 (void)ctx;/* UNUSED */ 336 } 337 338 #endif 339 340 const struct archive_hmac __archive_hmac = { 341 &__hmac_sha1_init, 342 &__hmac_sha1_update, 343 &__hmac_sha1_final, 344 &__hmac_sha1_cleanup, 345 }; 346