1cdf63a70SMartin Matuska /*-
2cdf63a70SMartin Matuska * Copyright (c) 2014 Michihiro NAKAJIMA
3cdf63a70SMartin Matuska * All rights reserved.
4cdf63a70SMartin Matuska *
5cdf63a70SMartin Matuska * Redistribution and use in source and binary forms, with or without
6cdf63a70SMartin Matuska * modification, are permitted provided that the following conditions
7cdf63a70SMartin Matuska * are met:
8cdf63a70SMartin Matuska * 1. Redistributions of source code must retain the above copyright
9cdf63a70SMartin Matuska *    notice, this list of conditions and the following disclaimer.
10cdf63a70SMartin Matuska * 2. Redistributions in binary form must reproduce the above copyright
11cdf63a70SMartin Matuska *    notice, this list of conditions and the following disclaimer in the
12cdf63a70SMartin Matuska *    documentation and/or other materials provided with the distribution.
13cdf63a70SMartin Matuska *
14cdf63a70SMartin Matuska * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15cdf63a70SMartin Matuska * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16cdf63a70SMartin Matuska * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17cdf63a70SMartin Matuska * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18cdf63a70SMartin Matuska * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19cdf63a70SMartin Matuska * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20cdf63a70SMartin Matuska * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21cdf63a70SMartin Matuska * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22cdf63a70SMartin Matuska * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23cdf63a70SMartin Matuska * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24cdf63a70SMartin Matuska */
25cdf63a70SMartin Matuska 
26cdf63a70SMartin Matuska #include "archive_platform.h"
27cdf63a70SMartin Matuska 
28cdf63a70SMartin Matuska #ifdef HAVE_STRING_H
29cdf63a70SMartin Matuska #include <string.h>
30cdf63a70SMartin Matuska #endif
31cdf63a70SMartin Matuska #include "archive.h"
32cdf63a70SMartin Matuska #include "archive_cryptor_private.h"
33cdf63a70SMartin Matuska 
34cdf63a70SMartin Matuska /*
35cdf63a70SMartin Matuska  * On systems that do not support any recognized crypto libraries,
36cdf63a70SMartin Matuska  * this file will normally define no usable symbols.
37cdf63a70SMartin Matuska  *
38cdf63a70SMartin Matuska  * But some compilers and linkers choke on empty object files, so
39cdf63a70SMartin Matuska  * define a public symbol that will always exist.  This could
40cdf63a70SMartin Matuska  * be removed someday if this file gains another always-present
41cdf63a70SMartin Matuska  * symbol definition.
42cdf63a70SMartin Matuska  */
__libarchive_cryptor_build_hack(void)43cdf63a70SMartin Matuska int __libarchive_cryptor_build_hack(void) {
44cdf63a70SMartin Matuska 	return 0;
45cdf63a70SMartin Matuska }
46cdf63a70SMartin Matuska 
47cdf63a70SMartin Matuska #ifdef ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto
48cdf63a70SMartin Matuska 
49cdf63a70SMartin Matuska static int
pbkdf2_sha1(const char * pw,size_t pw_len,const uint8_t * salt,size_t salt_len,unsigned rounds,uint8_t * derived_key,size_t derived_key_len)50cdf63a70SMartin Matuska pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
51cdf63a70SMartin Matuska     size_t salt_len, unsigned rounds, uint8_t *derived_key,
52cdf63a70SMartin Matuska     size_t derived_key_len)
53cdf63a70SMartin Matuska {
54cdf63a70SMartin Matuska 	CCKeyDerivationPBKDF(kCCPBKDF2, (const char *)pw,
55cdf63a70SMartin Matuska 	    pw_len, salt, salt_len, kCCPRFHmacAlgSHA1, rounds,
56cdf63a70SMartin Matuska 	    derived_key, derived_key_len);
57cdf63a70SMartin Matuska 	return 0;
58cdf63a70SMartin Matuska }
59cdf63a70SMartin Matuska 
60cdf63a70SMartin Matuska #elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
61cdf63a70SMartin Matuska #ifdef _MSC_VER
62cdf63a70SMartin Matuska #pragma comment(lib, "Bcrypt.lib")
63cdf63a70SMartin Matuska #endif
64cdf63a70SMartin Matuska 
65cdf63a70SMartin Matuska static int
pbkdf2_sha1(const char * pw,size_t pw_len,const uint8_t * salt,size_t salt_len,unsigned rounds,uint8_t * derived_key,size_t derived_key_len)66cdf63a70SMartin Matuska pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
67cdf63a70SMartin Matuska 	size_t salt_len, unsigned rounds, uint8_t *derived_key,
68cdf63a70SMartin Matuska 	size_t derived_key_len)
69cdf63a70SMartin Matuska {
70cdf63a70SMartin Matuska 	NTSTATUS status;
71cdf63a70SMartin Matuska 	BCRYPT_ALG_HANDLE hAlg;
72cdf63a70SMartin Matuska 
73cdf63a70SMartin Matuska 	status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA1_ALGORITHM,
74cdf63a70SMartin Matuska 		MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG);
75cdf63a70SMartin Matuska 	if (!BCRYPT_SUCCESS(status))
76cdf63a70SMartin Matuska 		return -1;
77cdf63a70SMartin Matuska 
78cdf63a70SMartin Matuska 	status = BCryptDeriveKeyPBKDF2(hAlg,
79cdf63a70SMartin Matuska 		(PUCHAR)(uintptr_t)pw, (ULONG)pw_len,
80cdf63a70SMartin Matuska 		(PUCHAR)(uintptr_t)salt, (ULONG)salt_len, rounds,
81cdf63a70SMartin Matuska 		(PUCHAR)derived_key, (ULONG)derived_key_len, 0);
82cdf63a70SMartin Matuska 
83cdf63a70SMartin Matuska 	BCryptCloseAlgorithmProvider(hAlg, 0);
84cdf63a70SMartin Matuska 
85cdf63a70SMartin Matuska 	return (BCRYPT_SUCCESS(status)) ? 0: -1;
86cdf63a70SMartin Matuska }
87cdf63a70SMartin Matuska 
885ee98676SMartin Matuska #elif defined(HAVE_LIBMBEDCRYPTO) && defined(HAVE_MBEDTLS_PKCS5_H)
895ee98676SMartin Matuska 
905ee98676SMartin Matuska static int
pbkdf2_sha1(const char * pw,size_t pw_len,const uint8_t * salt,size_t salt_len,unsigned rounds,uint8_t * derived_key,size_t derived_key_len)915ee98676SMartin Matuska pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
925ee98676SMartin Matuska     size_t salt_len, unsigned rounds, uint8_t *derived_key,
935ee98676SMartin Matuska     size_t derived_key_len)
945ee98676SMartin Matuska {
955ee98676SMartin Matuska 	mbedtls_md_context_t ctx;
965ee98676SMartin Matuska 	const mbedtls_md_info_t *info;
975ee98676SMartin Matuska 	int ret;
985ee98676SMartin Matuska 
995ee98676SMartin Matuska 	mbedtls_md_init(&ctx);
1005ee98676SMartin Matuska 	info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
1015ee98676SMartin Matuska 	if (info == NULL) {
1025ee98676SMartin Matuska 		mbedtls_md_free(&ctx);
1035ee98676SMartin Matuska 		return (-1);
1045ee98676SMartin Matuska 	}
1055ee98676SMartin Matuska 	ret = mbedtls_md_setup(&ctx, info, 1);
1065ee98676SMartin Matuska 	if (ret != 0) {
1075ee98676SMartin Matuska 		mbedtls_md_free(&ctx);
1085ee98676SMartin Matuska 		return (-1);
1095ee98676SMartin Matuska 	}
1105ee98676SMartin Matuska 	ret = mbedtls_pkcs5_pbkdf2_hmac(&ctx, (const unsigned char *)pw,
1115ee98676SMartin Matuska 	    pw_len, salt, salt_len, rounds, derived_key_len, derived_key);
1125ee98676SMartin Matuska 
1135ee98676SMartin Matuska 	mbedtls_md_free(&ctx);
1145ee98676SMartin Matuska 	return (ret);
1155ee98676SMartin Matuska }
1165ee98676SMartin Matuska 
117cdf63a70SMartin Matuska #elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_PBKDF2_H)
118cdf63a70SMartin Matuska 
119cdf63a70SMartin Matuska static int
pbkdf2_sha1(const char * pw,size_t pw_len,const uint8_t * salt,size_t salt_len,unsigned rounds,uint8_t * derived_key,size_t derived_key_len)120cdf63a70SMartin Matuska pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
121cdf63a70SMartin Matuska     size_t salt_len, unsigned rounds, uint8_t *derived_key,
122cdf63a70SMartin Matuska     size_t derived_key_len) {
123cdf63a70SMartin Matuska 	pbkdf2_hmac_sha1((unsigned)pw_len, (const uint8_t *)pw, rounds,
124cdf63a70SMartin Matuska 	    salt_len, salt, derived_key_len, derived_key);
125cdf63a70SMartin Matuska 	return 0;
126cdf63a70SMartin Matuska }
127cdf63a70SMartin Matuska 
128cdf63a70SMartin Matuska #elif defined(HAVE_LIBCRYPTO) && defined(HAVE_PKCS5_PBKDF2_HMAC_SHA1)
129cdf63a70SMartin Matuska 
130cdf63a70SMartin Matuska static int
pbkdf2_sha1(const char * pw,size_t pw_len,const uint8_t * salt,size_t salt_len,unsigned rounds,uint8_t * derived_key,size_t derived_key_len)131cdf63a70SMartin Matuska pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
132cdf63a70SMartin Matuska     size_t salt_len, unsigned rounds, uint8_t *derived_key,
133cdf63a70SMartin Matuska     size_t derived_key_len) {
134cdf63a70SMartin Matuska 
135cdf63a70SMartin Matuska 	PKCS5_PBKDF2_HMAC_SHA1(pw, pw_len, salt, salt_len, rounds,
136cdf63a70SMartin Matuska 	    derived_key_len, derived_key);
137cdf63a70SMartin Matuska 	return 0;
138cdf63a70SMartin Matuska }
139cdf63a70SMartin Matuska 
140cdf63a70SMartin Matuska #else
141cdf63a70SMartin Matuska 
142cdf63a70SMartin Matuska /* Stub */
143cdf63a70SMartin Matuska static int
pbkdf2_sha1(const char * pw,size_t pw_len,const uint8_t * salt,size_t salt_len,unsigned rounds,uint8_t * derived_key,size_t derived_key_len)144cdf63a70SMartin Matuska pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
145cdf63a70SMartin Matuska     size_t salt_len, unsigned rounds, uint8_t *derived_key,
146cdf63a70SMartin Matuska     size_t derived_key_len) {
147cdf63a70SMartin Matuska 	(void)pw; /* UNUSED */
148cdf63a70SMartin Matuska 	(void)pw_len; /* UNUSED */
149cdf63a70SMartin Matuska 	(void)salt; /* UNUSED */
150cdf63a70SMartin Matuska 	(void)salt_len; /* UNUSED */
151cdf63a70SMartin Matuska 	(void)rounds; /* UNUSED */
152cdf63a70SMartin Matuska 	(void)derived_key; /* UNUSED */
153cdf63a70SMartin Matuska 	(void)derived_key_len; /* UNUSED */
154cdf63a70SMartin Matuska 	return -1; /* UNSUPPORTED */
155cdf63a70SMartin Matuska }
156cdf63a70SMartin Matuska 
157cdf63a70SMartin Matuska #endif
158cdf63a70SMartin Matuska 
159cdf63a70SMartin Matuska #ifdef ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto
160cdf63a70SMartin Matuska # if MAC_OS_X_VERSION_MAX_ALLOWED < 1090
161cdf63a70SMartin Matuska #  define kCCAlgorithmAES kCCAlgorithmAES128
162cdf63a70SMartin Matuska # endif
163cdf63a70SMartin Matuska 
164cdf63a70SMartin Matuska static int
aes_ctr_init(archive_crypto_ctx * ctx,const uint8_t * key,size_t key_len)165cdf63a70SMartin Matuska aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
166cdf63a70SMartin Matuska {
167cdf63a70SMartin Matuska 	CCCryptorStatus r;
168cdf63a70SMartin Matuska 
169cdf63a70SMartin Matuska 	ctx->key_len = key_len;
170cdf63a70SMartin Matuska 	memcpy(ctx->key, key, key_len);
171cdf63a70SMartin Matuska 	memset(ctx->nonce, 0, sizeof(ctx->nonce));
172cdf63a70SMartin Matuska 	ctx->encr_pos = AES_BLOCK_SIZE;
173cdf63a70SMartin Matuska 	r = CCCryptorCreateWithMode(kCCEncrypt, kCCModeECB, kCCAlgorithmAES,
174cdf63a70SMartin Matuska 	    ccNoPadding, NULL, key, key_len, NULL, 0, 0, 0, &ctx->ctx);
175cdf63a70SMartin Matuska 	return (r == kCCSuccess)? 0: -1;
176cdf63a70SMartin Matuska }
177cdf63a70SMartin Matuska 
178cdf63a70SMartin Matuska static int
aes_ctr_encrypt_counter(archive_crypto_ctx * ctx)179cdf63a70SMartin Matuska aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
180cdf63a70SMartin Matuska {
181cdf63a70SMartin Matuska 	CCCryptorRef ref = ctx->ctx;
182cdf63a70SMartin Matuska 	CCCryptorStatus r;
183cdf63a70SMartin Matuska 
184cdf63a70SMartin Matuska 	r = CCCryptorReset(ref, NULL);
185a7bc2822SMartin Matuska 	if (r != kCCSuccess && r != kCCUnimplemented)
186cdf63a70SMartin Matuska 		return -1;
187cdf63a70SMartin Matuska 	r = CCCryptorUpdate(ref, ctx->nonce, AES_BLOCK_SIZE, ctx->encr_buf,
188cdf63a70SMartin Matuska 	    AES_BLOCK_SIZE, NULL);
189cdf63a70SMartin Matuska 	return (r == kCCSuccess)? 0: -1;
190cdf63a70SMartin Matuska }
191cdf63a70SMartin Matuska 
192cdf63a70SMartin Matuska static int
aes_ctr_release(archive_crypto_ctx * ctx)193cdf63a70SMartin Matuska aes_ctr_release(archive_crypto_ctx *ctx)
194cdf63a70SMartin Matuska {
195cdf63a70SMartin Matuska 	memset(ctx->key, 0, ctx->key_len);
196cdf63a70SMartin Matuska 	memset(ctx->nonce, 0, sizeof(ctx->nonce));
197cdf63a70SMartin Matuska 	return 0;
198cdf63a70SMartin Matuska }
199cdf63a70SMartin Matuska 
200cdf63a70SMartin Matuska #elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
201cdf63a70SMartin Matuska 
202cdf63a70SMartin Matuska static int
aes_ctr_init(archive_crypto_ctx * ctx,const uint8_t * key,size_t key_len)203cdf63a70SMartin Matuska aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
204cdf63a70SMartin Matuska {
205cdf63a70SMartin Matuska 	BCRYPT_ALG_HANDLE hAlg;
206cdf63a70SMartin Matuska 	BCRYPT_KEY_HANDLE hKey;
207cdf63a70SMartin Matuska 	DWORD keyObj_len, aes_key_len;
208cdf63a70SMartin Matuska 	PBYTE keyObj;
209cdf63a70SMartin Matuska 	ULONG result;
210cdf63a70SMartin Matuska 	NTSTATUS status;
211cdf63a70SMartin Matuska 	BCRYPT_KEY_LENGTHS_STRUCT key_lengths;
212cdf63a70SMartin Matuska 
213cdf63a70SMartin Matuska 	ctx->hAlg = NULL;
214cdf63a70SMartin Matuska 	ctx->hKey = NULL;
215cdf63a70SMartin Matuska 	ctx->keyObj = NULL;
216cdf63a70SMartin Matuska 	switch (key_len) {
217cdf63a70SMartin Matuska 	case 16: aes_key_len = 128; break;
218cdf63a70SMartin Matuska 	case 24: aes_key_len = 192; break;
219cdf63a70SMartin Matuska 	case 32: aes_key_len = 256; break;
220cdf63a70SMartin Matuska 	default: return -1;
221cdf63a70SMartin Matuska 	}
222cdf63a70SMartin Matuska 	status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_AES_ALGORITHM,
223cdf63a70SMartin Matuska 		MS_PRIMITIVE_PROVIDER, 0);
224cdf63a70SMartin Matuska 	if (!BCRYPT_SUCCESS(status))
225cdf63a70SMartin Matuska 		return -1;
226cdf63a70SMartin Matuska 	status = BCryptGetProperty(hAlg, BCRYPT_KEY_LENGTHS, (PUCHAR)&key_lengths,
227cdf63a70SMartin Matuska 		sizeof(key_lengths), &result, 0);
228cdf63a70SMartin Matuska 	if (!BCRYPT_SUCCESS(status)) {
229cdf63a70SMartin Matuska 		BCryptCloseAlgorithmProvider(hAlg, 0);
230cdf63a70SMartin Matuska 		return -1;
231cdf63a70SMartin Matuska 	}
232cdf63a70SMartin Matuska 	if (key_lengths.dwMinLength > aes_key_len
233cdf63a70SMartin Matuska 		|| key_lengths.dwMaxLength < aes_key_len) {
234cdf63a70SMartin Matuska 		BCryptCloseAlgorithmProvider(hAlg, 0);
235cdf63a70SMartin Matuska 		return -1;
236cdf63a70SMartin Matuska 	}
237cdf63a70SMartin Matuska 	status = BCryptGetProperty(hAlg, BCRYPT_OBJECT_LENGTH, (PUCHAR)&keyObj_len,
238cdf63a70SMartin Matuska 		sizeof(keyObj_len), &result, 0);
239cdf63a70SMartin Matuska 	if (!BCRYPT_SUCCESS(status)) {
240cdf63a70SMartin Matuska 		BCryptCloseAlgorithmProvider(hAlg, 0);
241cdf63a70SMartin Matuska 		return -1;
242cdf63a70SMartin Matuska 	}
243cdf63a70SMartin Matuska 	keyObj = (PBYTE)HeapAlloc(GetProcessHeap(), 0, keyObj_len);
244cdf63a70SMartin Matuska 	if (keyObj == NULL) {
245cdf63a70SMartin Matuska 		BCryptCloseAlgorithmProvider(hAlg, 0);
246cdf63a70SMartin Matuska 		return -1;
247cdf63a70SMartin Matuska 	}
248cdf63a70SMartin Matuska 	status = BCryptSetProperty(hAlg, BCRYPT_CHAINING_MODE,
249cdf63a70SMartin Matuska 		(PUCHAR)BCRYPT_CHAIN_MODE_ECB, sizeof(BCRYPT_CHAIN_MODE_ECB), 0);
250cdf63a70SMartin Matuska 	if (!BCRYPT_SUCCESS(status)) {
251cdf63a70SMartin Matuska 		BCryptCloseAlgorithmProvider(hAlg, 0);
252cdf63a70SMartin Matuska 		HeapFree(GetProcessHeap(), 0, keyObj);
253cdf63a70SMartin Matuska 		return -1;
254cdf63a70SMartin Matuska 	}
255cdf63a70SMartin Matuska 	status = BCryptGenerateSymmetricKey(hAlg, &hKey,
256cdf63a70SMartin Matuska 		keyObj, keyObj_len,
257cdf63a70SMartin Matuska 		(PUCHAR)(uintptr_t)key, (ULONG)key_len, 0);
258cdf63a70SMartin Matuska 	if (!BCRYPT_SUCCESS(status)) {
259cdf63a70SMartin Matuska 		BCryptCloseAlgorithmProvider(hAlg, 0);
260cdf63a70SMartin Matuska 		HeapFree(GetProcessHeap(), 0, keyObj);
261cdf63a70SMartin Matuska 		return -1;
262cdf63a70SMartin Matuska 	}
263cdf63a70SMartin Matuska 
264cdf63a70SMartin Matuska 	ctx->hAlg = hAlg;
265cdf63a70SMartin Matuska 	ctx->hKey = hKey;
266cdf63a70SMartin Matuska 	ctx->keyObj = keyObj;
267cdf63a70SMartin Matuska 	ctx->keyObj_len = keyObj_len;
268cdf63a70SMartin Matuska 	ctx->encr_pos = AES_BLOCK_SIZE;
269cdf63a70SMartin Matuska 
270cdf63a70SMartin Matuska 	return 0;
271cdf63a70SMartin Matuska }
272cdf63a70SMartin Matuska 
273cdf63a70SMartin Matuska static int
aes_ctr_encrypt_counter(archive_crypto_ctx * ctx)274cdf63a70SMartin Matuska aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
275cdf63a70SMartin Matuska {
276cdf63a70SMartin Matuska 	NTSTATUS status;
277cdf63a70SMartin Matuska 	ULONG result;
278cdf63a70SMartin Matuska 
279cdf63a70SMartin Matuska 	status = BCryptEncrypt(ctx->hKey, (PUCHAR)ctx->nonce, AES_BLOCK_SIZE,
280cdf63a70SMartin Matuska 		NULL, NULL, 0, (PUCHAR)ctx->encr_buf, AES_BLOCK_SIZE,
281cdf63a70SMartin Matuska 		&result, 0);
282cdf63a70SMartin Matuska 	return BCRYPT_SUCCESS(status) ? 0 : -1;
283cdf63a70SMartin Matuska }
284cdf63a70SMartin Matuska 
285cdf63a70SMartin Matuska static int
aes_ctr_release(archive_crypto_ctx * ctx)286cdf63a70SMartin Matuska aes_ctr_release(archive_crypto_ctx *ctx)
287cdf63a70SMartin Matuska {
288cdf63a70SMartin Matuska 
289cdf63a70SMartin Matuska 	if (ctx->hAlg != NULL) {
290cdf63a70SMartin Matuska 		BCryptCloseAlgorithmProvider(ctx->hAlg, 0);
291cdf63a70SMartin Matuska 		ctx->hAlg = NULL;
292cdf63a70SMartin Matuska 		BCryptDestroyKey(ctx->hKey);
293cdf63a70SMartin Matuska 		ctx->hKey = NULL;
294cdf63a70SMartin Matuska 		HeapFree(GetProcessHeap(), 0, ctx->keyObj);
295cdf63a70SMartin Matuska 		ctx->keyObj = NULL;
296cdf63a70SMartin Matuska 	}
297cdf63a70SMartin Matuska 	memset(ctx, 0, sizeof(*ctx));
298cdf63a70SMartin Matuska 	return 0;
299cdf63a70SMartin Matuska }
300cdf63a70SMartin Matuska 
3015ee98676SMartin Matuska #elif defined(HAVE_LIBMBEDCRYPTO) && defined(HAVE_MBEDTLS_AES_H)
302759a578bSMartin Matuska 
3035ee98676SMartin Matuska static int
aes_ctr_init(archive_crypto_ctx * ctx,const uint8_t * key,size_t key_len)3045ee98676SMartin Matuska aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
3055ee98676SMartin Matuska {
3065ee98676SMartin Matuska 	mbedtls_aes_init(&ctx->ctx);
3075ee98676SMartin Matuska 	ctx->key_len = key_len;
3085ee98676SMartin Matuska 	memcpy(ctx->key, key, key_len);
3095ee98676SMartin Matuska 	memset(ctx->nonce, 0, sizeof(ctx->nonce));
3105ee98676SMartin Matuska 	ctx->encr_pos = AES_BLOCK_SIZE;
3115ee98676SMartin Matuska 	return 0;
3125ee98676SMartin Matuska }
3135ee98676SMartin Matuska 
3145ee98676SMartin Matuska static int
aes_ctr_encrypt_counter(archive_crypto_ctx * ctx)3155ee98676SMartin Matuska aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
3165ee98676SMartin Matuska {
3175ee98676SMartin Matuska 	if (mbedtls_aes_setkey_enc(&ctx->ctx, ctx->key,
3185ee98676SMartin Matuska 	    ctx->key_len * 8) != 0)
3195ee98676SMartin Matuska 		return (-1);
3205ee98676SMartin Matuska 	if (mbedtls_aes_crypt_ecb(&ctx->ctx, MBEDTLS_AES_ENCRYPT, ctx->nonce,
3215ee98676SMartin Matuska 	    ctx->encr_buf) != 0)
3225ee98676SMartin Matuska 		return (-1);
3235ee98676SMartin Matuska 	return 0;
3245ee98676SMartin Matuska }
3255ee98676SMartin Matuska 
3265ee98676SMartin Matuska static int
aes_ctr_release(archive_crypto_ctx * ctx)3275ee98676SMartin Matuska aes_ctr_release(archive_crypto_ctx *ctx)
3285ee98676SMartin Matuska {
3295ee98676SMartin Matuska 	mbedtls_aes_free(&ctx->ctx);
3305ee98676SMartin Matuska 	memset(ctx, 0, sizeof(*ctx));
3315ee98676SMartin Matuska 	return 0;
3325ee98676SMartin Matuska }
3335ee98676SMartin Matuska 
334cdf63a70SMartin Matuska #elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_AES_H)
335cdf63a70SMartin Matuska 
336cdf63a70SMartin Matuska static int
aes_ctr_init(archive_crypto_ctx * ctx,const uint8_t * key,size_t key_len)337cdf63a70SMartin Matuska aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
338cdf63a70SMartin Matuska {
339cdf63a70SMartin Matuska 	ctx->key_len = key_len;
340cdf63a70SMartin Matuska 	memcpy(ctx->key, key, key_len);
341cdf63a70SMartin Matuska 	memset(ctx->nonce, 0, sizeof(ctx->nonce));
342cdf63a70SMartin Matuska 	ctx->encr_pos = AES_BLOCK_SIZE;
343cdf63a70SMartin Matuska 	memset(&ctx->ctx, 0, sizeof(ctx->ctx));
344cdf63a70SMartin Matuska 	return 0;
345cdf63a70SMartin Matuska }
346cdf63a70SMartin Matuska 
347cdf63a70SMartin Matuska static int
aes_ctr_encrypt_counter(archive_crypto_ctx * ctx)348cdf63a70SMartin Matuska aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
349cdf63a70SMartin Matuska {
350c3afd20fSMartin Matuska #if NETTLE_VERSION_MAJOR < 3
351cdf63a70SMartin Matuska 	aes_set_encrypt_key(&ctx->ctx, ctx->key_len, ctx->key);
352cdf63a70SMartin Matuska 	aes_encrypt(&ctx->ctx, AES_BLOCK_SIZE, ctx->encr_buf, ctx->nonce);
353c3afd20fSMartin Matuska #else
354c3afd20fSMartin Matuska 	switch(ctx->key_len) {
355c3afd20fSMartin Matuska 	case AES128_KEY_SIZE:
356c3afd20fSMartin Matuska 		aes128_set_encrypt_key(&ctx->ctx.c128, ctx->key);
357c3afd20fSMartin Matuska 		aes128_encrypt(&ctx->ctx.c128, AES_BLOCK_SIZE, ctx->encr_buf,
358c3afd20fSMartin Matuska 		    ctx->nonce);
359c3afd20fSMartin Matuska 		break;
360c3afd20fSMartin Matuska 	case AES192_KEY_SIZE:
361c3afd20fSMartin Matuska 		aes192_set_encrypt_key(&ctx->ctx.c192, ctx->key);
362c3afd20fSMartin Matuska 		aes192_encrypt(&ctx->ctx.c192, AES_BLOCK_SIZE, ctx->encr_buf,
363c3afd20fSMartin Matuska 		    ctx->nonce);
364c3afd20fSMartin Matuska 		break;
365c3afd20fSMartin Matuska 	case AES256_KEY_SIZE:
366c3afd20fSMartin Matuska 		aes256_set_encrypt_key(&ctx->ctx.c256, ctx->key);
367c3afd20fSMartin Matuska 		aes256_encrypt(&ctx->ctx.c256, AES_BLOCK_SIZE, ctx->encr_buf,
368c3afd20fSMartin Matuska 		    ctx->nonce);
369c3afd20fSMartin Matuska 		break;
370c3afd20fSMartin Matuska 	default:
371c3afd20fSMartin Matuska 		return -1;
372c3afd20fSMartin Matuska 		break;
373c3afd20fSMartin Matuska 	}
374c3afd20fSMartin Matuska #endif
375cdf63a70SMartin Matuska 	return 0;
376cdf63a70SMartin Matuska }
377cdf63a70SMartin Matuska 
378cdf63a70SMartin Matuska static int
aes_ctr_release(archive_crypto_ctx * ctx)379cdf63a70SMartin Matuska aes_ctr_release(archive_crypto_ctx *ctx)
380cdf63a70SMartin Matuska {
381cdf63a70SMartin Matuska 	memset(ctx, 0, sizeof(*ctx));
382cdf63a70SMartin Matuska 	return 0;
383cdf63a70SMartin Matuska }
384cdf63a70SMartin Matuska 
385cdf63a70SMartin Matuska #elif defined(HAVE_LIBCRYPTO)
386cdf63a70SMartin Matuska 
387cdf63a70SMartin Matuska static int
aes_ctr_init(archive_crypto_ctx * ctx,const uint8_t * key,size_t key_len)388cdf63a70SMartin Matuska aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
389cdf63a70SMartin Matuska {
3906a414569SMartin Matuska 	if ((ctx->ctx = EVP_CIPHER_CTX_new()) == NULL)
3916a414569SMartin Matuska 		return -1;
392cdf63a70SMartin Matuska 
393cdf63a70SMartin Matuska 	switch (key_len) {
394cdf63a70SMartin Matuska 	case 16: ctx->type = EVP_aes_128_ecb(); break;
395cdf63a70SMartin Matuska 	case 24: ctx->type = EVP_aes_192_ecb(); break;
396cdf63a70SMartin Matuska 	case 32: ctx->type = EVP_aes_256_ecb(); break;
397cdf63a70SMartin Matuska 	default: ctx->type = NULL; return -1;
398cdf63a70SMartin Matuska 	}
399cdf63a70SMartin Matuska 
400cdf63a70SMartin Matuska 	ctx->key_len = key_len;
401cdf63a70SMartin Matuska 	memcpy(ctx->key, key, key_len);
402cdf63a70SMartin Matuska 	memset(ctx->nonce, 0, sizeof(ctx->nonce));
403cdf63a70SMartin Matuska 	ctx->encr_pos = AES_BLOCK_SIZE;
404cdf63a70SMartin Matuska 	return 0;
405cdf63a70SMartin Matuska }
406cdf63a70SMartin Matuska 
407cdf63a70SMartin Matuska static int
aes_ctr_encrypt_counter(archive_crypto_ctx * ctx)408cdf63a70SMartin Matuska aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
409cdf63a70SMartin Matuska {
410cdf63a70SMartin Matuska 	int outl = 0;
411cdf63a70SMartin Matuska 	int r;
412cdf63a70SMartin Matuska 
4136a414569SMartin Matuska 	r = EVP_EncryptInit_ex(ctx->ctx, ctx->type, NULL, ctx->key, NULL);
414cdf63a70SMartin Matuska 	if (r == 0)
415cdf63a70SMartin Matuska 		return -1;
4166a414569SMartin Matuska 	r = EVP_EncryptUpdate(ctx->ctx, ctx->encr_buf, &outl, ctx->nonce,
417cdf63a70SMartin Matuska 	    AES_BLOCK_SIZE);
418cdf63a70SMartin Matuska 	if (r == 0 || outl != AES_BLOCK_SIZE)
419cdf63a70SMartin Matuska 		return -1;
420cdf63a70SMartin Matuska 	return 0;
421cdf63a70SMartin Matuska }
422cdf63a70SMartin Matuska 
423cdf63a70SMartin Matuska static int
aes_ctr_release(archive_crypto_ctx * ctx)424cdf63a70SMartin Matuska aes_ctr_release(archive_crypto_ctx *ctx)
425cdf63a70SMartin Matuska {
4266a414569SMartin Matuska 	EVP_CIPHER_CTX_free(ctx->ctx);
427*b9128a37SMartin Matuska 	OPENSSL_cleanse(ctx->key, ctx->key_len);
428*b9128a37SMartin Matuska 	OPENSSL_cleanse(ctx->nonce, sizeof(ctx->nonce));
429cdf63a70SMartin Matuska 	return 0;
430cdf63a70SMartin Matuska }
431cdf63a70SMartin Matuska 
432cdf63a70SMartin Matuska #else
433cdf63a70SMartin Matuska 
434cdf63a70SMartin Matuska #define ARCHIVE_CRYPTOR_STUB
435cdf63a70SMartin Matuska /* Stub */
436cdf63a70SMartin Matuska static int
aes_ctr_init(archive_crypto_ctx * ctx,const uint8_t * key,size_t key_len)437cdf63a70SMartin Matuska aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
438cdf63a70SMartin Matuska {
439cdf63a70SMartin Matuska 	(void)ctx; /* UNUSED */
440cdf63a70SMartin Matuska 	(void)key; /* UNUSED */
441cdf63a70SMartin Matuska 	(void)key_len; /* UNUSED */
442cdf63a70SMartin Matuska 	return -1;
443cdf63a70SMartin Matuska }
444cdf63a70SMartin Matuska 
445cdf63a70SMartin Matuska static int
aes_ctr_encrypt_counter(archive_crypto_ctx * ctx)446cdf63a70SMartin Matuska aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
447cdf63a70SMartin Matuska {
448cdf63a70SMartin Matuska 	(void)ctx; /* UNUSED */
449cdf63a70SMartin Matuska 	return -1;
450cdf63a70SMartin Matuska }
451cdf63a70SMartin Matuska 
452cdf63a70SMartin Matuska static int
aes_ctr_release(archive_crypto_ctx * ctx)453cdf63a70SMartin Matuska aes_ctr_release(archive_crypto_ctx *ctx)
454cdf63a70SMartin Matuska {
455cdf63a70SMartin Matuska 	(void)ctx; /* UNUSED */
456cdf63a70SMartin Matuska 	return 0;
457cdf63a70SMartin Matuska }
458cdf63a70SMartin Matuska 
459cdf63a70SMartin Matuska #endif
460cdf63a70SMartin Matuska 
461cdf63a70SMartin Matuska #ifdef ARCHIVE_CRYPTOR_STUB
462cdf63a70SMartin Matuska static int
aes_ctr_update(archive_crypto_ctx * ctx,const uint8_t * const in,size_t in_len,uint8_t * const out,size_t * out_len)463cdf63a70SMartin Matuska aes_ctr_update(archive_crypto_ctx *ctx, const uint8_t * const in,
464cdf63a70SMartin Matuska     size_t in_len, uint8_t * const out, size_t *out_len)
465cdf63a70SMartin Matuska {
466cdf63a70SMartin Matuska 	(void)ctx; /* UNUSED */
467cdf63a70SMartin Matuska 	(void)in; /* UNUSED */
468cdf63a70SMartin Matuska 	(void)in_len; /* UNUSED */
469cdf63a70SMartin Matuska 	(void)out; /* UNUSED */
470cdf63a70SMartin Matuska 	(void)out_len; /* UNUSED */
471cdf63a70SMartin Matuska 	aes_ctr_encrypt_counter(ctx); /* UNUSED */ /* Fix unused function warning */
472cdf63a70SMartin Matuska 	return -1;
473cdf63a70SMartin Matuska }
474cdf63a70SMartin Matuska 
475cdf63a70SMartin Matuska #else
476cdf63a70SMartin Matuska static void
aes_ctr_increase_counter(archive_crypto_ctx * ctx)477cdf63a70SMartin Matuska aes_ctr_increase_counter(archive_crypto_ctx *ctx)
478cdf63a70SMartin Matuska {
479cdf63a70SMartin Matuska 	uint8_t *const nonce = ctx->nonce;
480cdf63a70SMartin Matuska 	int j;
481cdf63a70SMartin Matuska 
482cdf63a70SMartin Matuska 	for (j = 0; j < 8; j++) {
483cdf63a70SMartin Matuska 		if (++nonce[j])
484cdf63a70SMartin Matuska 			break;
485cdf63a70SMartin Matuska 	}
486cdf63a70SMartin Matuska }
487cdf63a70SMartin Matuska 
488cdf63a70SMartin Matuska static int
aes_ctr_update(archive_crypto_ctx * ctx,const uint8_t * const in,size_t in_len,uint8_t * const out,size_t * out_len)489cdf63a70SMartin Matuska aes_ctr_update(archive_crypto_ctx *ctx, const uint8_t * const in,
490cdf63a70SMartin Matuska     size_t in_len, uint8_t * const out, size_t *out_len)
491cdf63a70SMartin Matuska {
492cdf63a70SMartin Matuska 	uint8_t *const ebuf = ctx->encr_buf;
493cdf63a70SMartin Matuska 	unsigned pos = ctx->encr_pos;
494cdf63a70SMartin Matuska 	unsigned max = (unsigned)((in_len < *out_len)? in_len: *out_len);
495cdf63a70SMartin Matuska 	unsigned i;
496cdf63a70SMartin Matuska 
497cdf63a70SMartin Matuska 	for (i = 0; i < max; ) {
498cdf63a70SMartin Matuska 		if (pos == AES_BLOCK_SIZE) {
499cdf63a70SMartin Matuska 			aes_ctr_increase_counter(ctx);
500cdf63a70SMartin Matuska 			if (aes_ctr_encrypt_counter(ctx) != 0)
501cdf63a70SMartin Matuska 				return -1;
502cdf63a70SMartin Matuska 			while (max -i >= AES_BLOCK_SIZE) {
503cdf63a70SMartin Matuska 				for (pos = 0; pos < AES_BLOCK_SIZE; pos++)
504cdf63a70SMartin Matuska 					out[i+pos] = in[i+pos] ^ ebuf[pos];
505cdf63a70SMartin Matuska 				i += AES_BLOCK_SIZE;
506cdf63a70SMartin Matuska 				aes_ctr_increase_counter(ctx);
507cdf63a70SMartin Matuska 				if (aes_ctr_encrypt_counter(ctx) != 0)
508cdf63a70SMartin Matuska 					return -1;
509cdf63a70SMartin Matuska 			}
510cdf63a70SMartin Matuska 			pos = 0;
511cdf63a70SMartin Matuska 			if (i >= max)
512cdf63a70SMartin Matuska 				break;
513cdf63a70SMartin Matuska 		}
514cdf63a70SMartin Matuska 		out[i] = in[i] ^ ebuf[pos++];
515cdf63a70SMartin Matuska 		i++;
516cdf63a70SMartin Matuska 	}
517cdf63a70SMartin Matuska 	ctx->encr_pos = pos;
518cdf63a70SMartin Matuska 	*out_len = i;
519cdf63a70SMartin Matuska 
520cdf63a70SMartin Matuska 	return 0;
521cdf63a70SMartin Matuska }
522cdf63a70SMartin Matuska #endif /* ARCHIVE_CRYPTOR_STUB */
523cdf63a70SMartin Matuska 
524cdf63a70SMartin Matuska 
525cdf63a70SMartin Matuska const struct archive_cryptor __archive_cryptor =
526cdf63a70SMartin Matuska {
527cdf63a70SMartin Matuska   &pbkdf2_sha1,
528cdf63a70SMartin Matuska   &aes_ctr_init,
529cdf63a70SMartin Matuska   &aes_ctr_update,
530cdf63a70SMartin Matuska   &aes_ctr_release,
531cdf63a70SMartin Matuska   &aes_ctr_init,
532cdf63a70SMartin Matuska   &aes_ctr_update,
533cdf63a70SMartin Matuska   &aes_ctr_release,
534cdf63a70SMartin Matuska };
535