archive_hmac.c revision 358090
1168404Spjd/*-
2168404Spjd* Copyright (c) 2014 Michihiro NAKAJIMA
3168404Spjd* All rights reserved.
4168404Spjd*
5168404Spjd* Redistribution and use in source and binary forms, with or without
6168404Spjd* modification, are permitted provided that the following conditions
7168404Spjd* are met:
8168404Spjd* 1. Redistributions of source code must retain the above copyright
9168404Spjd*    notice, this list of conditions and the following disclaimer.
10168404Spjd* 2. Redistributions in binary form must reproduce the above copyright
11168404Spjd*    notice, this list of conditions and the following disclaimer in the
12168404Spjd*    documentation and/or other materials provided with the distribution.
13168404Spjd*
14168404Spjd* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15168404Spjd* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16168404Spjd* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17168404Spjd* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18168404Spjd* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19168404Spjd* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20168404Spjd* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21168404Spjd* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22219089Spjd* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23277826Sdelphij* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24286766Smav*/
25260835Sdelphij
26286764Smav#include "archive_platform.h"
27168404Spjd
28168404Spjd#ifdef HAVE_STRING_H
29168404Spjd#include <string.h>
30168404Spjd#endif
31168404Spjd#include "archive.h"
32168404Spjd#include "archive_hmac_private.h"
33168404Spjd
34168404Spjd/*
35168404Spjd * On systems that do not support any recognized crypto libraries,
36168404Spjd * the archive_hmac.c file is expected to define no usable symbols.
37168404Spjd *
38168404Spjd * But some compilers and linkers choke on empty object files, so
39168404Spjd * define a public symbol that will always exist.  This could
40168404Spjd * be removed someday if this file gains another always-present
41168404Spjd * symbol definition.
42168404Spjd */
43168404Spjdint __libarchive_hmac_build_hack(void) {
44168404Spjd	return 0;
45168404Spjd}
46168404Spjd
47168404Spjd
48168404Spjd#ifdef ARCHIVE_HMAC_USE_Apple_CommonCrypto
49168404Spjd
50168404Spjdstatic int
51185029Spjd__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
52185029Spjd{
53168404Spjd	CCHmacInit(ctx, kCCHmacAlgSHA1, key, key_len);
54168404Spjd	return 0;
55168404Spjd}
56168404Spjd
57185029Spjdstatic void
58168404Spjd__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data,
59168404Spjd    size_t data_len)
60168404Spjd{
61168404Spjd	CCHmacUpdate(ctx, data, data_len);
62251631Sdelphij}
63168404Spjd
64168404Spjdstatic void
65168404Spjd__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len)
66251631Sdelphij{
67168404Spjd	CCHmacFinal(ctx, out);
68168404Spjd	*out_len = 20;
69168404Spjd}
70168404Spjd
71168404Spjdstatic void
72168404Spjd__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
73168404Spjd{
74168404Spjd	memset(ctx, 0, sizeof(*ctx));
75168404Spjd}
76168404Spjd
77168404Spjd#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
78168404Spjd
79185029Spjd#ifndef BCRYPT_HASH_REUSABLE_FLAG
80168404Spjd# define BCRYPT_HASH_REUSABLE_FLAG 0x00000020
81251631Sdelphij#endif
82168404Spjd
83168404Spjdstatic int
84168404Spjd__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
85286774Smav{
86286774Smav#ifdef __GNUC__
87286774Smav#pragma GCC diagnostic ignored "-Wcast-qual"
88168404Spjd#endif
89168404Spjd	BCRYPT_ALG_HANDLE hAlg;
90168404Spjd	BCRYPT_HASH_HANDLE hHash;
91168404Spjd	DWORD hash_len;
92168404Spjd	PBYTE hash;
93168404Spjd	ULONG result;
94168404Spjd	NTSTATUS status;
95168404Spjd
96168404Spjd	ctx->hAlg = NULL;
97168404Spjd	status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA1_ALGORITHM,
98168404Spjd		MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG);
99168404Spjd	if (!BCRYPT_SUCCESS(status))
100168404Spjd		return -1;
101168404Spjd	status = BCryptGetProperty(hAlg, BCRYPT_HASH_LENGTH, (PUCHAR)&hash_len,
102168404Spjd		sizeof(hash_len), &result, 0);
103168404Spjd	if (!BCRYPT_SUCCESS(status)) {
104168404Spjd		BCryptCloseAlgorithmProvider(hAlg, 0);
105168404Spjd		return -1;
106168404Spjd	}
107168404Spjd	hash = (PBYTE)HeapAlloc(GetProcessHeap(), 0, hash_len);
108268858Sdelphij	if (hash == NULL) {
109168404Spjd		BCryptCloseAlgorithmProvider(hAlg, 0);
110168404Spjd		return -1;
111168404Spjd	}
112168404Spjd	status = BCryptCreateHash(hAlg, &hHash, NULL, 0,
113185029Spjd		(PUCHAR)key, (ULONG)key_len, BCRYPT_HASH_REUSABLE_FLAG);
114286570Smav	if (!BCRYPT_SUCCESS(status)) {
115185029Spjd		BCryptCloseAlgorithmProvider(hAlg, 0);
116185029Spjd		HeapFree(GetProcessHeap(), 0, hash);
117185029Spjd		return -1;
118185029Spjd	}
119185029Spjd
120185029Spjd	ctx->hAlg = hAlg;
121168404Spjd	ctx->hHash = hHash;
122168404Spjd	ctx->hash_len = hash_len;
123168404Spjd	ctx->hash = hash;
124168404Spjd
125251478Sdelphij	return 0;
126168404Spjd}
127168404Spjd
128168404Spjdstatic void
129185029Spjd__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data,
130219089Spjd	size_t data_len)
131258632Savg{
132286763Smav	BCryptHashData(ctx->hHash, (PUCHAR)(uintptr_t)data, (ULONG)data_len, 0);
133168404Spjd}
134168404Spjd
135297633Straszstatic void
136168404Spjd__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len)
137168404Spjd{
138168404Spjd	BCryptFinishHash(ctx->hHash, ctx->hash, ctx->hash_len, 0);
139248572Ssmh	if (ctx->hash_len == *out_len)
140219089Spjd		memcpy(out, ctx->hash, *out_len);
141168404Spjd}
142168404Spjd
143272483Ssmhstatic void
144191902Skmacy__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
145240133Smm{
146240133Smm	if (ctx->hAlg != NULL) {
147240133Smm		BCryptCloseAlgorithmProvider(ctx->hAlg, 0);
148240133Smm		HeapFree(GetProcessHeap(), 0, ctx->hash);
149240133Smm		ctx->hAlg = NULL;
150240133Smm	}
151240133Smm}
152240133Smm
153286763Smav#elif defined(HAVE_LIBMBEDCRYPTO) && defined(HAVE_MBEDTLS_MD_H)
154286763Smav
155286763Smavstatic int
156286763Smav__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
157168404Spjd{
158286763Smav        const mbedtls_md_info_t *info;
159286763Smav        int ret;
160286763Smav
161286763Smav        mbedtls_md_init(ctx);
162286625Smav        info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
163168404Spjd        if (info == NULL) {
164258632Savg                mbedtls_md_free(ctx);
165286763Smav                return (-1);
166286763Smav        }
167286763Smav        ret = mbedtls_md_setup(ctx, info, 1);
168286763Smav        if (ret != 0) {
169286763Smav                mbedtls_md_free(ctx);
170258632Savg                return (-1);
171286763Smav        }
172258632Savg	ret = mbedtls_md_hmac_starts(ctx, key, key_len);
173286763Smav	if (ret != 0) {
174286763Smav		mbedtls_md_free(ctx);
175286763Smav		return (-1);
176286763Smav	}
177286763Smav	return 0;
178286763Smav}
179286763Smav
180168404Spjdstatic void
181168404Spjd__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data,
182168404Spjd    size_t data_len)
183286763Smav{
184286763Smav	mbedtls_md_hmac_update(ctx, data, data_len);
185286763Smav}
186208373Smm
187208373Smmstatic void __hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len)
188208373Smm{
189208373Smm	(void)out_len;	/* UNUSED */
190286625Smav
191208373Smm	mbedtls_md_hmac_finish(ctx, out);
192168404Spjd}
193286625Smav
194286625Smavstatic void __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
195286625Smav{
196286625Smav	mbedtls_md_free(ctx);
197286625Smav	memset(ctx, 0, sizeof(*ctx));
198286625Smav}
199286625Smav
200286625Smav#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_HMAC_H)
201286625Smav
202286625Smavstatic int
203286625Smav__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
204286625Smav{
205168404Spjd	hmac_sha1_set_key(ctx, key_len, key);
206168404Spjd	return 0;
207168404Spjd}
208168404Spjd
209168404Spjdstatic void
210258632Savg__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data,
211258632Savg    size_t data_len)
212258632Savg{
213258632Savg	hmac_sha1_update(ctx, data_len, data);
214258632Savg}
215208373Smm
216287702Sdelphijstatic void
217168404Spjd__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len)
218168404Spjd{
219185029Spjd	hmac_sha1_digest(ctx, (unsigned)*out_len, out);
220185029Spjd}
221185029Spjd
222185029Spjdstatic void
223286762Smav__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
224286762Smav{
225286762Smav	memset(ctx, 0, sizeof(*ctx));
226185029Spjd}
227185029Spjd
228185029Spjd#elif defined(HAVE_LIBCRYPTO)
229275780Sdelphij
230208373Smmstatic int
231208373Smm__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
232208373Smm{
233242845Sdelphij	*ctx = HMAC_CTX_new();
234269230Sdelphij	if (*ctx == NULL)
235272483Ssmh		return -1;
236185029Spjd	HMAC_Init_ex(*ctx, key, key_len, EVP_sha1(), NULL);
237270759Ssmh	return 0;
238275748Sdelphij}
239270759Ssmh
240270759Ssmhstatic void
241270759Ssmh__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data,
242270759Ssmh    size_t data_len)
243270759Ssmh{
244270759Ssmh	HMAC_Update(*ctx, data, data_len);
245272483Ssmh}
246270759Ssmh
247270759Ssmhstatic void
248270759Ssmh__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len)
249270759Ssmh{
250185029Spjd	unsigned int len = (unsigned int)*out_len;
251275780Sdelphij
252273026Sdelphij	HMAC_Final(*ctx, out, &len);
253168473Spjd	*out_len = len;
254217367Smdf}
255168473Spjd
256217367Smdfstatic void
257168473Spjd__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
258269230Sdelphij{
259269230Sdelphij	HMAC_CTX_free(*ctx);
260269230Sdelphij	*ctx = NULL;
261273026Sdelphij}
262273026Sdelphij
263273026Sdelphij#else
264273026Sdelphij
265270759Ssmh/* Stub */
266270759Ssmhstatic int
267270759Ssmh__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
268270759Ssmh{
269270759Ssmh	(void)ctx;/* UNUSED */
270270759Ssmh	(void)key;/* UNUSED */
271270759Ssmh	(void)key_len;/* UNUSED */
272270759Ssmh	return -1;
273168404Spjd}
274270759Ssmh
275270759Ssmhstatic void
276270759Ssmh__hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data,
277270759Ssmh    size_t data_len)
278270759Ssmh{
279270759Ssmh	(void)ctx;/* UNUSED */
280270759Ssmh	(void)data;/* UNUSED */
281270759Ssmh	(void)data_len;/* UNUSED */
282270759Ssmh}
283270759Ssmh
284270759Ssmhstatic void
285272483Ssmh__hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len)
286270759Ssmh{
287272483Ssmh	(void)ctx;/* UNUSED */
288270759Ssmh	(void)out;/* UNUSED */
289270759Ssmh	(void)out_len;/* UNUSED */
290270759Ssmh}
291270759Ssmh
292270759Ssmhstatic void
293270759Ssmh__hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
294275748Sdelphij{
295275748Sdelphij	(void)ctx;/* UNUSED */
296275748Sdelphij}
297275748Sdelphij
298275748Sdelphij#endif
299275748Sdelphij
300275748Sdelphijconst struct archive_hmac __archive_hmac = {
301275748Sdelphij	&__hmac_sha1_init,
302275748Sdelphij	&__hmac_sha1_update,
303272483Ssmh	&__hmac_sha1_final,
304270759Ssmh	&__hmac_sha1_cleanup,
305168404Spjd};
306185029Spjd