1109998Smarkm/*-
2109998Smarkm* Copyright (c) 2014 Michihiro NAKAJIMA
3160814Ssimon* All rights reserved.
4160814Ssimon*
5160814Ssimon* Redistribution and use in source and binary forms, with or without
6109998Smarkm* modification, are permitted provided that the following conditions
7160814Ssimon* are met:
8109998Smarkm* 1. Redistributions of source code must retain the above copyright
9109998Smarkm*    notice, this list of conditions and the following disclaimer.
10109998Smarkm* 2. Redistributions in binary form must reproduce the above copyright
11109998Smarkm*    notice, this list of conditions and the following disclaimer in the
12109998Smarkm*    documentation and/or other materials provided with the distribution.
13109998Smarkm*
14109998Smarkm* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15109998Smarkm* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16109998Smarkm* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17109998Smarkm* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18109998Smarkm* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19109998Smarkm* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20109998Smarkm* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21109998Smarkm* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22109998Smarkm* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23109998Smarkm* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24109998Smarkm*/
25109998Smarkm
26109998Smarkm#include "archive_platform.h"
27109998Smarkm
28109998Smarkm#ifdef HAVE_STRING_H
29109998Smarkm#include <string.h>
30109998Smarkm#endif
31109998Smarkm#include "archive.h"
32109998Smarkm#include "archive_cryptor_private.h"
33109998Smarkm
34109998Smarkm/*
35109998Smarkm * On systems that do not support any recognized crypto libraries,
36109998Smarkm * this file will normally define no usable symbols.
37109998Smarkm *
38109998Smarkm * But some compilers and linkers choke on empty object files, so
39109998Smarkm * define a public symbol that will always exist.  This could
40109998Smarkm * be removed someday if this file gains another always-present
41109998Smarkm * symbol definition.
42109998Smarkm */
43109998Smarkmint __libarchive_cryptor_build_hack(void) {
44109998Smarkm	return 0;
45109998Smarkm}
46109998Smarkm
47109998Smarkm#ifdef ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto
48109998Smarkm
49109998Smarkmstatic int
50109998Smarkmpbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
51109998Smarkm    size_t salt_len, unsigned rounds, uint8_t *derived_key,
52109998Smarkm    size_t derived_key_len)
53109998Smarkm{
54109998Smarkm	CCKeyDerivationPBKDF(kCCPBKDF2, (const char *)pw,
55109998Smarkm	    pw_len, salt, salt_len, kCCPRFHmacAlgSHA1, rounds,
56109998Smarkm	    derived_key, derived_key_len);
57109998Smarkm	return 0;
58109998Smarkm}
59160814Ssimon
60160814Ssimon#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
61160814Ssimon#ifdef _MSC_VER
62160814Ssimon#pragma comment(lib, "Bcrypt.lib")
63160814Ssimon#endif
64109998Smarkm
65109998Smarkmstatic int
66160814Ssimonpbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
67109998Smarkm	size_t salt_len, unsigned rounds, uint8_t *derived_key,
68238405Sjkim	size_t derived_key_len)
69238405Sjkim{
70238405Sjkim	NTSTATUS status;
71238405Sjkim	BCRYPT_ALG_HANDLE hAlg;
72109998Smarkm
73109998Smarkm	status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA1_ALGORITHM,
74109998Smarkm		MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG);
75109998Smarkm	if (!BCRYPT_SUCCESS(status))
76109998Smarkm		return -1;
77238405Sjkim
78160814Ssimon	status = BCryptDeriveKeyPBKDF2(hAlg,
79109998Smarkm		(PUCHAR)(uintptr_t)pw, (ULONG)pw_len,
80109998Smarkm		(PUCHAR)(uintptr_t)salt, (ULONG)salt_len, rounds,
81109998Smarkm		(PUCHAR)derived_key, (ULONG)derived_key_len, 0);
82109998Smarkm
83160814Ssimon	BCryptCloseAlgorithmProvider(hAlg, 0);
84160814Ssimon
85160814Ssimon	return (BCRYPT_SUCCESS(status)) ? 0: -1;
86160814Ssimon}
87109998Smarkm
88109998Smarkm#elif defined(HAVE_LIBMBEDCRYPTO) && defined(HAVE_MBEDTLS_PKCS5_H)
89109998Smarkm
90109998Smarkmstatic int
91109998Smarkmpbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
92109998Smarkm    size_t salt_len, unsigned rounds, uint8_t *derived_key,
93109998Smarkm    size_t derived_key_len)
94160814Ssimon{
95160814Ssimon	mbedtls_md_context_t ctx;
96238405Sjkim	const mbedtls_md_info_t *info;
97109998Smarkm	int ret;
98109998Smarkm
99109998Smarkm	mbedtls_md_init(&ctx);
100109998Smarkm	info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
101109998Smarkm	if (info == NULL) {
102109998Smarkm		mbedtls_md_free(&ctx);
103109998Smarkm		return (-1);
104109998Smarkm	}
105160814Ssimon	ret = mbedtls_md_setup(&ctx, info, 1);
106160814Ssimon	if (ret != 0) {
107160814Ssimon		mbedtls_md_free(&ctx);
108109998Smarkm		return (-1);
109109998Smarkm	}
110160814Ssimon	ret = mbedtls_pkcs5_pbkdf2_hmac(&ctx, (const unsigned char *)pw,
111109998Smarkm	    pw_len, salt, salt_len, rounds, derived_key_len, derived_key);
112109998Smarkm
113109998Smarkm	mbedtls_md_free(&ctx);
114109998Smarkm	return (ret);
115279264Sdelphij}
116279264Sdelphij
117279264Sdelphij#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_PBKDF2_H)
118279264Sdelphij
119279264Sdelphijstatic int
120109998Smarkmpbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
121109998Smarkm    size_t salt_len, unsigned rounds, uint8_t *derived_key,
122109998Smarkm    size_t derived_key_len) {
123109998Smarkm	pbkdf2_hmac_sha1((unsigned)pw_len, (const uint8_t *)pw, rounds,
124160814Ssimon	    salt_len, salt, derived_key_len, derived_key);
125160814Ssimon	return 0;
126160814Ssimon}
127160814Ssimon
128160814Ssimon#elif defined(HAVE_LIBCRYPTO) && defined(HAVE_PKCS5_PBKDF2_HMAC_SHA1)
129160814Ssimon
130160814Ssimonstatic int
131160814Ssimonpbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
132160814Ssimon    size_t salt_len, unsigned rounds, uint8_t *derived_key,
133160814Ssimon    size_t derived_key_len) {
134160814Ssimon
135160814Ssimon	PKCS5_PBKDF2_HMAC_SHA1(pw, pw_len, salt, salt_len, rounds,
136160814Ssimon	    derived_key_len, derived_key);
137160814Ssimon	return 0;
138109998Smarkm}
139109998Smarkm
140109998Smarkm#else
141109998Smarkm
142109998Smarkm/* Stub */
143109998Smarkmstatic int
144109998Smarkmpbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
145109998Smarkm    size_t salt_len, unsigned rounds, uint8_t *derived_key,
146109998Smarkm    size_t derived_key_len) {
147109998Smarkm	(void)pw; /* UNUSED */
148109998Smarkm	(void)pw_len; /* UNUSED */
149109998Smarkm	(void)salt; /* UNUSED */
150109998Smarkm	(void)salt_len; /* UNUSED */
151109998Smarkm	(void)rounds; /* UNUSED */
152109998Smarkm	(void)derived_key; /* UNUSED */
153109998Smarkm	(void)derived_key_len; /* UNUSED */
154109998Smarkm	return -1; /* UNSUPPORTED */
155109998Smarkm}
156109998Smarkm
157109998Smarkm#endif
158109998Smarkm
159109998Smarkm#ifdef ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto
160109998Smarkm# if MAC_OS_X_VERSION_MAX_ALLOWED < 1090
161109998Smarkm#  define kCCAlgorithmAES kCCAlgorithmAES128
162109998Smarkm# endif
163109998Smarkm
164109998Smarkmstatic int
165109998Smarkmaes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
166109998Smarkm{
167109998Smarkm	CCCryptorStatus r;
168109998Smarkm
169109998Smarkm	ctx->key_len = key_len;
170109998Smarkm	memcpy(ctx->key, key, key_len);
171109998Smarkm	memset(ctx->nonce, 0, sizeof(ctx->nonce));
172109998Smarkm	ctx->encr_pos = AES_BLOCK_SIZE;
173109998Smarkm	r = CCCryptorCreateWithMode(kCCEncrypt, kCCModeECB, kCCAlgorithmAES,
174109998Smarkm	    ccNoPadding, NULL, key, key_len, NULL, 0, 0, 0, &ctx->ctx);
175109998Smarkm	return (r == kCCSuccess)? 0: -1;
176160814Ssimon}
177109998Smarkm
178109998Smarkmstatic int
179109998Smarkmaes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
180109998Smarkm{
181109998Smarkm	CCCryptorRef ref = ctx->ctx;
182109998Smarkm	CCCryptorStatus r;
183109998Smarkm
184109998Smarkm	r = CCCryptorReset(ref, NULL);
185109998Smarkm	if (r != kCCSuccess && r != kCCUnimplemented)
186160814Ssimon		return -1;
187109998Smarkm	r = CCCryptorUpdate(ref, ctx->nonce, AES_BLOCK_SIZE, ctx->encr_buf,
188109998Smarkm	    AES_BLOCK_SIZE, NULL);
189109998Smarkm	return (r == kCCSuccess)? 0: -1;
190109998Smarkm}
191109998Smarkm
192109998Smarkmstatic int
193109998Smarkmaes_ctr_release(archive_crypto_ctx *ctx)
194109998Smarkm{
195109998Smarkm	memset(ctx->key, 0, ctx->key_len);
196109998Smarkm	memset(ctx->nonce, 0, sizeof(ctx->nonce));
197109998Smarkm	return 0;
198109998Smarkm}
199109998Smarkm
200109998Smarkm#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
201109998Smarkm
202109998Smarkmstatic int
203160814Ssimonaes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
204109998Smarkm{
205109998Smarkm	BCRYPT_ALG_HANDLE hAlg;
206109998Smarkm	BCRYPT_KEY_HANDLE hKey;
207109998Smarkm	DWORD keyObj_len, aes_key_len;
208109998Smarkm	PBYTE keyObj;
209109998Smarkm	ULONG result;
210109998Smarkm	NTSTATUS status;
211109998Smarkm	BCRYPT_KEY_LENGTHS_STRUCT key_lengths;
212109998Smarkm
213109998Smarkm	ctx->hAlg = NULL;
214109998Smarkm	ctx->hKey = NULL;
215109998Smarkm	ctx->keyObj = NULL;
216109998Smarkm	switch (key_len) {
217109998Smarkm	case 16: aes_key_len = 128; break;
218109998Smarkm	case 24: aes_key_len = 192; break;
219109998Smarkm	case 32: aes_key_len = 256; break;
220109998Smarkm	default: return -1;
221109998Smarkm	}
222109998Smarkm	status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_AES_ALGORITHM,
223109998Smarkm		MS_PRIMITIVE_PROVIDER, 0);
224109998Smarkm	if (!BCRYPT_SUCCESS(status))
225109998Smarkm		return -1;
226109998Smarkm	status = BCryptGetProperty(hAlg, BCRYPT_KEY_LENGTHS, (PUCHAR)&key_lengths,
227109998Smarkm		sizeof(key_lengths), &result, 0);
228109998Smarkm	if (!BCRYPT_SUCCESS(status)) {
229109998Smarkm		BCryptCloseAlgorithmProvider(hAlg, 0);
230109998Smarkm		return -1;
231160814Ssimon	}
232109998Smarkm	if (key_lengths.dwMinLength > aes_key_len
233109998Smarkm		|| key_lengths.dwMaxLength < aes_key_len) {
234109998Smarkm		BCryptCloseAlgorithmProvider(hAlg, 0);
235109998Smarkm		return -1;
236109998Smarkm	}
237109998Smarkm	status = BCryptGetProperty(hAlg, BCRYPT_OBJECT_LENGTH, (PUCHAR)&keyObj_len,
238109998Smarkm		sizeof(keyObj_len), &result, 0);
239109998Smarkm	if (!BCRYPT_SUCCESS(status)) {
240109998Smarkm		BCryptCloseAlgorithmProvider(hAlg, 0);
241109998Smarkm		return -1;
242109998Smarkm	}
243109998Smarkm	keyObj = (PBYTE)HeapAlloc(GetProcessHeap(), 0, keyObj_len);
244109998Smarkm	if (keyObj == NULL) {
245109998Smarkm		BCryptCloseAlgorithmProvider(hAlg, 0);
246109998Smarkm		return -1;
247109998Smarkm	}
248109998Smarkm	status = BCryptSetProperty(hAlg, BCRYPT_CHAINING_MODE,
249109998Smarkm		(PUCHAR)BCRYPT_CHAIN_MODE_ECB, sizeof(BCRYPT_CHAIN_MODE_ECB), 0);
250109998Smarkm	if (!BCRYPT_SUCCESS(status)) {
251109998Smarkm		BCryptCloseAlgorithmProvider(hAlg, 0);
252109998Smarkm		HeapFree(GetProcessHeap(), 0, keyObj);
253109998Smarkm		return -1;
254109998Smarkm	}
255109998Smarkm	status = BCryptGenerateSymmetricKey(hAlg, &hKey,
256109998Smarkm		keyObj, keyObj_len,
257109998Smarkm		(PUCHAR)(uintptr_t)key, (ULONG)key_len, 0);
258109998Smarkm	if (!BCRYPT_SUCCESS(status)) {
259109998Smarkm		BCryptCloseAlgorithmProvider(hAlg, 0);
260109998Smarkm		HeapFree(GetProcessHeap(), 0, keyObj);
261109998Smarkm		return -1;
262109998Smarkm	}
263109998Smarkm
264109998Smarkm	ctx->hAlg = hAlg;
265109998Smarkm	ctx->hKey = hKey;
266109998Smarkm	ctx->keyObj = keyObj;
267109998Smarkm	ctx->keyObj_len = keyObj_len;
268109998Smarkm	ctx->encr_pos = AES_BLOCK_SIZE;
269109998Smarkm
270109998Smarkm	return 0;
271109998Smarkm}
272109998Smarkm
273109998Smarkmstatic int
274109998Smarkmaes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
275109998Smarkm{
276109998Smarkm	NTSTATUS status;
277109998Smarkm	ULONG result;
278109998Smarkm
279109998Smarkm	status = BCryptEncrypt(ctx->hKey, (PUCHAR)ctx->nonce, AES_BLOCK_SIZE,
280109998Smarkm		NULL, NULL, 0, (PUCHAR)ctx->encr_buf, AES_BLOCK_SIZE,
281109998Smarkm		&result, 0);
282160814Ssimon	return BCRYPT_SUCCESS(status) ? 0 : -1;
283160814Ssimon}
284160814Ssimon
285160814Ssimonstatic int
286109998Smarkmaes_ctr_release(archive_crypto_ctx *ctx)
287160814Ssimon{
288160814Ssimon
289109998Smarkm	if (ctx->hAlg != NULL) {
290160814Ssimon		BCryptCloseAlgorithmProvider(ctx->hAlg, 0);
291160814Ssimon		ctx->hAlg = NULL;
292160814Ssimon		BCryptDestroyKey(ctx->hKey);
293160814Ssimon		ctx->hKey = NULL;
294160814Ssimon		HeapFree(GetProcessHeap(), 0, ctx->keyObj);
295160814Ssimon		ctx->keyObj = NULL;
296109998Smarkm	}
297160814Ssimon	memset(ctx, 0, sizeof(*ctx));
298160814Ssimon	return 0;
299160814Ssimon}
300160814Ssimon
301160814Ssimon#elif defined(HAVE_LIBMBEDCRYPTO) && defined(HAVE_MBEDTLS_AES_H)
302160814Ssimon
303109998Smarkmstatic int
304160814Ssimonaes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
305160814Ssimon{
306160814Ssimon	mbedtls_aes_init(&ctx->ctx);
307160814Ssimon	ctx->key_len = key_len;
308160814Ssimon	memcpy(ctx->key, key, key_len);
309160814Ssimon	memset(ctx->nonce, 0, sizeof(ctx->nonce));
310160814Ssimon	ctx->encr_pos = AES_BLOCK_SIZE;
311109998Smarkm	return 0;
312160814Ssimon}
313109998Smarkm
314160814Ssimonstatic int
315160814Ssimonaes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
316109998Smarkm{
317109998Smarkm	if (mbedtls_aes_setkey_enc(&ctx->ctx, ctx->key,
318160814Ssimon	    ctx->key_len * 8) != 0)
319160814Ssimon		return (-1);
320160814Ssimon	if (mbedtls_aes_crypt_ecb(&ctx->ctx, MBEDTLS_AES_ENCRYPT, ctx->nonce,
321160814Ssimon	    ctx->encr_buf) != 0)
322160814Ssimon		return (-1);
323160814Ssimon	return 0;
324160814Ssimon}
325160814Ssimon
326160814Ssimonstatic int
327160814Ssimonaes_ctr_release(archive_crypto_ctx *ctx)
328160814Ssimon{
329160814Ssimon	mbedtls_aes_free(&ctx->ctx);
330160814Ssimon	memset(ctx, 0, sizeof(*ctx));
331160814Ssimon	return 0;
332160814Ssimon}
333160814Ssimon
334160814Ssimon#elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_AES_H)
335160814Ssimon
336109998Smarkmstatic int
337160814Ssimonaes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
338160814Ssimon{
339160814Ssimon	ctx->key_len = key_len;
340109998Smarkm	memcpy(ctx->key, key, key_len);
341160814Ssimon	memset(ctx->nonce, 0, sizeof(ctx->nonce));
342160814Ssimon	ctx->encr_pos = AES_BLOCK_SIZE;
343160814Ssimon	memset(&ctx->ctx, 0, sizeof(ctx->ctx));
344160814Ssimon	return 0;
345109998Smarkm}
346160814Ssimon
347160814Ssimonstatic int
348160814Ssimonaes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
349160814Ssimon{
350160814Ssimon#if NETTLE_VERSION_MAJOR < 3
351160814Ssimon	aes_set_encrypt_key(&ctx->ctx, ctx->key_len, ctx->key);
352109998Smarkm	aes_encrypt(&ctx->ctx, AES_BLOCK_SIZE, ctx->encr_buf, ctx->nonce);
353109998Smarkm#else
354109998Smarkm	switch(ctx->key_len) {
355109998Smarkm	case AES128_KEY_SIZE:
356109998Smarkm		aes128_set_encrypt_key(&ctx->ctx.c128, ctx->key);
357109998Smarkm		aes128_encrypt(&ctx->ctx.c128, AES_BLOCK_SIZE, ctx->encr_buf,
358109998Smarkm		    ctx->nonce);
359109998Smarkm		break;
360109998Smarkm	case AES192_KEY_SIZE:
361109998Smarkm		aes192_set_encrypt_key(&ctx->ctx.c192, ctx->key);
362109998Smarkm		aes192_encrypt(&ctx->ctx.c192, AES_BLOCK_SIZE, ctx->encr_buf,
363109998Smarkm		    ctx->nonce);
364109998Smarkm		break;
365109998Smarkm	case AES256_KEY_SIZE:
366109998Smarkm		aes256_set_encrypt_key(&ctx->ctx.c256, ctx->key);
367109998Smarkm		aes256_encrypt(&ctx->ctx.c256, AES_BLOCK_SIZE, ctx->encr_buf,
368109998Smarkm		    ctx->nonce);
369109998Smarkm		break;
370109998Smarkm	default:
371109998Smarkm		return -1;
372109998Smarkm		break;
373109998Smarkm	}
374109998Smarkm#endif
375109998Smarkm	return 0;
376109998Smarkm}
377109998Smarkm
378109998Smarkmstatic int
379109998Smarkmaes_ctr_release(archive_crypto_ctx *ctx)
380109998Smarkm{
381109998Smarkm	memset(ctx, 0, sizeof(*ctx));
382109998Smarkm	return 0;
383109998Smarkm}
384109998Smarkm
385109998Smarkm#elif defined(HAVE_LIBCRYPTO)
386109998Smarkm
387109998Smarkmstatic int
388109998Smarkmaes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
389109998Smarkm{
390109998Smarkm	if ((ctx->ctx = EVP_CIPHER_CTX_new()) == NULL)
391109998Smarkm		return -1;
392109998Smarkm
393109998Smarkm	switch (key_len) {
394109998Smarkm	case 16: ctx->type = EVP_aes_128_ecb(); break;
395109998Smarkm	case 24: ctx->type = EVP_aes_192_ecb(); break;
396109998Smarkm	case 32: ctx->type = EVP_aes_256_ecb(); break;
397160814Ssimon	default: ctx->type = NULL; return -1;
398160814Ssimon	}
399109998Smarkm
400109998Smarkm	ctx->key_len = key_len;
401109998Smarkm	memcpy(ctx->key, key, key_len);
402109998Smarkm	memset(ctx->nonce, 0, sizeof(ctx->nonce));
403109998Smarkm	ctx->encr_pos = AES_BLOCK_SIZE;
404109998Smarkm#if OPENSSL_VERSION_NUMBER  >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
405109998Smarkm	if (!EVP_CIPHER_CTX_reset(ctx->ctx)) {
406109998Smarkm		EVP_CIPHER_CTX_free(ctx->ctx);
407109998Smarkm		ctx->ctx = NULL;
408109998Smarkm	}
409109998Smarkm#else
410109998Smarkm	EVP_CIPHER_CTX_init(ctx->ctx);
411109998Smarkm#endif
412109998Smarkm	return 0;
413109998Smarkm}
414109998Smarkm
415109998Smarkmstatic int
416109998Smarkmaes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
417109998Smarkm{
418109998Smarkm	int outl = 0;
419109998Smarkm	int r;
420109998Smarkm
421109998Smarkm	r = EVP_EncryptInit_ex(ctx->ctx, ctx->type, NULL, ctx->key, NULL);
422109998Smarkm	if (r == 0)
423109998Smarkm		return -1;
424109998Smarkm	r = EVP_EncryptUpdate(ctx->ctx, ctx->encr_buf, &outl, ctx->nonce,
425109998Smarkm	    AES_BLOCK_SIZE);
426109998Smarkm	if (r == 0 || outl != AES_BLOCK_SIZE)
427109998Smarkm		return -1;
428109998Smarkm	return 0;
429109998Smarkm}
430109998Smarkm
431109998Smarkmstatic int
432109998Smarkmaes_ctr_release(archive_crypto_ctx *ctx)
433109998Smarkm{
434109998Smarkm	EVP_CIPHER_CTX_free(ctx->ctx);
435109998Smarkm	memset(ctx->key, 0, ctx->key_len);
436109998Smarkm	memset(ctx->nonce, 0, sizeof(ctx->nonce));
437109998Smarkm	return 0;
438109998Smarkm}
439109998Smarkm
440109998Smarkm#else
441109998Smarkm
442109998Smarkm#define ARCHIVE_CRYPTOR_STUB
443109998Smarkm/* Stub */
444109998Smarkmstatic int
445109998Smarkmaes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
446109998Smarkm{
447109998Smarkm	(void)ctx; /* UNUSED */
448109998Smarkm	(void)key; /* UNUSED */
449109998Smarkm	(void)key_len; /* UNUSED */
450109998Smarkm	return -1;
451109998Smarkm}
452109998Smarkm
453109998Smarkmstatic int
454109998Smarkmaes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
455109998Smarkm{
456109998Smarkm	(void)ctx; /* UNUSED */
457109998Smarkm	return -1;
458109998Smarkm}
459109998Smarkm
460109998Smarkmstatic int
461109998Smarkmaes_ctr_release(archive_crypto_ctx *ctx)
462109998Smarkm{
463109998Smarkm	(void)ctx; /* UNUSED */
464109998Smarkm	return 0;
465109998Smarkm}
466109998Smarkm
467109998Smarkm#endif
468109998Smarkm
469109998Smarkm#ifdef ARCHIVE_CRYPTOR_STUB
470109998Smarkmstatic int
471109998Smarkmaes_ctr_update(archive_crypto_ctx *ctx, const uint8_t * const in,
472109998Smarkm    size_t in_len, uint8_t * const out, size_t *out_len)
473109998Smarkm{
474109998Smarkm	(void)ctx; /* UNUSED */
475109998Smarkm	(void)in; /* UNUSED */
476109998Smarkm	(void)in_len; /* UNUSED */
477109998Smarkm	(void)out; /* UNUSED */
478109998Smarkm	(void)out_len; /* UNUSED */
479109998Smarkm	aes_ctr_encrypt_counter(ctx); /* UNUSED */ /* Fix unused function warning */
480109998Smarkm	return -1;
481109998Smarkm}
482109998Smarkm
483109998Smarkm#else
484109998Smarkmstatic void
485109998Smarkmaes_ctr_increase_counter(archive_crypto_ctx *ctx)
486109998Smarkm{
487109998Smarkm	uint8_t *const nonce = ctx->nonce;
488109998Smarkm	int j;
489109998Smarkm
490109998Smarkm	for (j = 0; j < 8; j++) {
491109998Smarkm		if (++nonce[j])
492109998Smarkm			break;
493109998Smarkm	}
494109998Smarkm}
495109998Smarkm
496109998Smarkmstatic int
497109998Smarkmaes_ctr_update(archive_crypto_ctx *ctx, const uint8_t * const in,
498109998Smarkm    size_t in_len, uint8_t * const out, size_t *out_len)
499109998Smarkm{
500109998Smarkm	uint8_t *const ebuf = ctx->encr_buf;
501109998Smarkm	unsigned pos = ctx->encr_pos;
502109998Smarkm	unsigned max = (unsigned)((in_len < *out_len)? in_len: *out_len);
503109998Smarkm	unsigned i;
504109998Smarkm
505109998Smarkm	for (i = 0; i < max; ) {
506109998Smarkm		if (pos == AES_BLOCK_SIZE) {
507109998Smarkm			aes_ctr_increase_counter(ctx);
508109998Smarkm			if (aes_ctr_encrypt_counter(ctx) != 0)
509109998Smarkm				return -1;
510109998Smarkm			while (max -i >= AES_BLOCK_SIZE) {
511109998Smarkm				for (pos = 0; pos < AES_BLOCK_SIZE; pos++)
512109998Smarkm					out[i+pos] = in[i+pos] ^ ebuf[pos];
513109998Smarkm				i += AES_BLOCK_SIZE;
514109998Smarkm				aes_ctr_increase_counter(ctx);
515160814Ssimon				if (aes_ctr_encrypt_counter(ctx) != 0)
516109998Smarkm					return -1;
517109998Smarkm			}
518109998Smarkm			pos = 0;
519109998Smarkm			if (i >= max)
520109998Smarkm				break;
521160814Ssimon		}
522109998Smarkm		out[i] = in[i] ^ ebuf[pos++];
523109998Smarkm		i++;
524109998Smarkm	}
525109998Smarkm	ctx->encr_pos = pos;
526109998Smarkm	*out_len = i;
527109998Smarkm
528109998Smarkm	return 0;
529160814Ssimon}
530109998Smarkm#endif /* ARCHIVE_CRYPTOR_STUB */
531109998Smarkm
532109998Smarkm
533160814Ssimonconst struct archive_cryptor __archive_cryptor =
534160814Ssimon{
535109998Smarkm  &pbkdf2_sha1,
536109998Smarkm  &aes_ctr_init,
537109998Smarkm  &aes_ctr_update,
538109998Smarkm  &aes_ctr_release,
539160814Ssimon  &aes_ctr_init,
540109998Smarkm  &aes_ctr_update,
541109998Smarkm  &aes_ctr_release,
542109998Smarkm};
543109998Smarkm