Implement HMAC Functionality.
Refactor crypto utility functions in a separate file. Add HMAC verification for file header. Add a few extra input validation checks. Include space in chunk header for HMAC.
This commit is contained in:
parent
f2d7bea902
commit
d13aad830e
11 changed files with 922 additions and 438 deletions
|
@ -26,9 +26,10 @@ MAINSRCS = main.c utils/utils.c allocator.c zlib_compress.c bzip2_compress.c \
|
|||
lzma_compress.c ppmd_compress.c adaptive_compress.c lzfx_compress.c \
|
||||
lz4_compress.c none_compress.c utils/xxhash.c utils/heapq.c utils/cpuid.c \
|
||||
crypto/aes/crypto_aes.c crypto/scrypt/crypto_scrypt-nosse.c \
|
||||
crypto/scrypt/sha256.c crypto/scrypt/crypto_aesctr.c
|
||||
crypto/scrypt/sha256.c crypto/scrypt/crypto_aesctr.c crypto/crypto_utils.c
|
||||
MAINHDRS = allocator.h pcompress.h utils/utils.h utils/xxhash.h utils/heapq.h \
|
||||
utils/cpuid.h
|
||||
utils/cpuid.h crypto/crypto_utils.h crypto/scrypt/crypto_scrypt.h \
|
||||
crypto/scrypt/sha256.h crypto/scrypt/crypto_aesctr.h crypto/aes/crypto_aes.h
|
||||
MAINOBJS = $(MAINSRCS:.c=.o)
|
||||
|
||||
RABINSRCS = rabin/rabin_dedup.c
|
||||
|
@ -92,13 +93,13 @@ LIBBSCGEN_OPT = -fopenmp
|
|||
LIBBSCCPPFLAGS = -I$(LIBBSCDIR)/libbsc -DENABLE_PC_LIBBSC
|
||||
|
||||
BAKFILES = *~ lzma/*~ lzfx/*~ lz4/*~ rabin/*~ bsdiff/*~ lzp/*~ utils/*~ crypto/sha2/*~ \
|
||||
crypto/sha2/intel/*~ crypto/aes/*~ crypto/scrypt/*~
|
||||
crypto/sha2/intel/*~ crypto/aes/*~ crypto/scrypt/*~ crypto/*~
|
||||
|
||||
RM = rm -f
|
||||
COMMON_CPPFLAGS = -I. -I./lzma -I./lzfx -I./lz4 -I./rabin -I./bsdiff -DNODEFAULT_PROPS \
|
||||
-DFILE_OFFSET_BITS=64 -D_REENTRANT -D__USE_SSE_INTRIN__ -D_LZMA_PROB32 \
|
||||
-I./lzp @LIBBSCCPPFLAGS@ -I./crypto/skein -I./utils -I@OPENSSL_INCDIR@ \
|
||||
-I./crypto/sha2 -I./crypto/scrypt -I./crypto/aes @KEYLEN@
|
||||
-I./crypto/sha2 -I./crypto/scrypt -I./crypto/aes -I./crypto @KEYLEN@
|
||||
COMMON_VEC_FLAGS = -ftree-vectorize
|
||||
COMMON_LOOP_OPTFLAGS = $(VEC_FLAGS) -floop-interchange -floop-block
|
||||
LDLIBS = -ldl -lbz2 $(ZLIB_DIR) -lz -lm @LIBBSCLFLAGS@ -L@OPENSSL_LIBDIR@ -lcrypto -lrt
|
||||
|
|
|
@ -107,11 +107,11 @@ aes_init(aes_ctx_t *ctx, uchar_t *salt, int saltlen, uchar_t *pwd, int pwd_len,
|
|||
uint64_t nonce, int enc)
|
||||
{
|
||||
int rv;
|
||||
uchar_t key[KEYLEN];
|
||||
struct timespec tp;
|
||||
uint64_t tv;
|
||||
uchar_t num[25];
|
||||
uchar_t IV[32];
|
||||
uchar_t *key = ctx->pkey;
|
||||
|
||||
#ifndef _USE_PBK
|
||||
int logN;
|
||||
|
@ -153,8 +153,6 @@ aes_init(aes_ctx_t *ctx, uchar_t *salt, int saltlen, uchar_t *pwd, int pwd_len,
|
|||
ctx->nonce = nonce;
|
||||
AES_set_encrypt_key(key, (KEYLEN << 3), &(ctx->key));
|
||||
}
|
||||
|
||||
memset(key, 0, KEYLEN);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -210,6 +208,12 @@ aes_nonce(aes_ctx_t *ctx)
|
|||
return (ctx->nonce);
|
||||
}
|
||||
|
||||
void
|
||||
aes_clean_pkey(aes_ctx_t *ctx)
|
||||
{
|
||||
memset(ctx->pkey, 0, KEYLEN);
|
||||
}
|
||||
|
||||
void
|
||||
aes_cleanup(aes_ctx_t *ctx)
|
||||
{
|
||||
|
|
|
@ -43,6 +43,7 @@ extern "C" {
|
|||
typedef struct {
|
||||
uint64_t nonce;
|
||||
AES_KEY key;
|
||||
uchar_t pkey[KEYLEN];
|
||||
} aes_ctx_t;
|
||||
|
||||
int aes_init(aes_ctx_t *ctx, uchar_t *salt, int saltlen, uchar_t *pwd, int pwd_len,
|
||||
|
@ -50,6 +51,7 @@ int aes_init(aes_ctx_t *ctx, uchar_t *salt, int saltlen, uchar_t *pwd, int pwd_l
|
|||
int aes_encrypt(aes_ctx_t *ctx, uchar_t *plaintext, uchar_t *ciphertext, ssize_t len, uint64_t id);
|
||||
int aes_decrypt(aes_ctx_t *ctx, uchar_t *ciphertext, uchar_t *plaintext, ssize_t len, uint64_t id);
|
||||
uint64_t aes_nonce(aes_ctx_t *ctx);
|
||||
void aes_clean_pkey(aes_ctx_t *ctx);
|
||||
void aes_cleanup(aes_ctx_t *ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
602
crypto/crypto_utils.c
Normal file
602
crypto/crypto_utils.c
Normal file
|
@ -0,0 +1,602 @@
|
|||
/*
|
||||
* This file is a part of Pcompress, a chunked parallel multi-
|
||||
* algorithm lossless compression and decompression program.
|
||||
*
|
||||
* Copyright (C) 2012 Moinak Ghosh. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* moinakg@belenix.org, http://moinakg.wordpress.com/
|
||||
*
|
||||
* This program includes partly-modified public domain source
|
||||
* code from the LZMA SDK: http://www.7-zip.org/sdk.html
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <skein.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <sha256.h>
|
||||
#include <crypto_aes.h>
|
||||
|
||||
#include "crypto_utils.h"
|
||||
#include "cpuid.h"
|
||||
|
||||
#define PROVIDER_OPENSSL 0
|
||||
#define PROVIDER_X64_OPT 1
|
||||
|
||||
static void init_sha256(void);
|
||||
static int geturandom_bytes(uchar_t rbytes[32]);
|
||||
/*
|
||||
* Checksum properties
|
||||
*/
|
||||
typedef void (*ckinit_func_ptr)(void);
|
||||
static struct {
|
||||
char *name;
|
||||
cksum_t cksum_id;
|
||||
int bytes, mac_bytes;
|
||||
ckinit_func_ptr init_func;
|
||||
} cksum_props[] = {
|
||||
{"CRC64", CKSUM_CRC64, 8, 32, NULL},
|
||||
{"SKEIN256", CKSUM_SKEIN256, 32, 32, NULL},
|
||||
{"SKEIN512", CKSUM_SKEIN512, 64, 64, NULL},
|
||||
{"SHA256", CKSUM_SHA256, 32, 32, init_sha256},
|
||||
{"SHA512", CKSUM_SHA512, 64, 64, NULL}
|
||||
};
|
||||
|
||||
static int cksum_provider = PROVIDER_OPENSSL, ossl_inited = 0;
|
||||
|
||||
extern uint64_t lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc);
|
||||
extern uint64_t lzma_crc64_8bchk(const uint8_t *buf, size_t size,
|
||||
uint64_t crc, uint64_t *cnt);
|
||||
|
||||
int
|
||||
compute_checksum(uchar_t *cksum_buf, int cksum, uchar_t *buf, ssize_t bytes)
|
||||
{
|
||||
if (cksum == CKSUM_CRC64) {
|
||||
uint64_t *ck = (uint64_t *)cksum_buf;
|
||||
*ck = lzma_crc64(buf, bytes, 0);
|
||||
|
||||
} else if (cksum == CKSUM_SKEIN256) {
|
||||
Skein_512_Ctxt_t ctx;
|
||||
|
||||
Skein_512_Init(&ctx, 256);
|
||||
Skein_512_Update(&ctx, buf, bytes);
|
||||
Skein_512_Final(&ctx, cksum_buf);
|
||||
|
||||
} else if (cksum == CKSUM_SKEIN512) {
|
||||
Skein_512_Ctxt_t ctx;
|
||||
|
||||
Skein_512_Init(&ctx, 512);
|
||||
Skein_512_Update(&ctx, buf, bytes);
|
||||
Skein_512_Final(&ctx, cksum_buf);
|
||||
|
||||
} else if (cksum == CKSUM_SHA256) {
|
||||
if (cksum_provider == PROVIDER_OPENSSL) {
|
||||
SHA256_CTX ctx;
|
||||
|
||||
SHA256_Init(&ctx);
|
||||
SHA256_Update(&ctx, buf, bytes);
|
||||
SHA256_Final(cksum_buf, &ctx);
|
||||
} else {
|
||||
SHA256_Context ctx;
|
||||
|
||||
opt_SHA256_Init(&ctx);
|
||||
opt_SHA256_Update(&ctx, buf, bytes);
|
||||
opt_SHA256_Final(&ctx, cksum_buf);
|
||||
}
|
||||
} else if (cksum == CKSUM_SHA512) {
|
||||
SHA512_CTX ctx;
|
||||
|
||||
SHA512_Init(&ctx);
|
||||
SHA512_Update(&ctx, buf, bytes);
|
||||
SHA512_Final(cksum_buf, &ctx);
|
||||
} else {
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
init_sha256(void)
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
cksum_provider = PROVIDER_OPENSSL;
|
||||
#else
|
||||
#ifdef __x86_64__
|
||||
processor_info_t pc;
|
||||
|
||||
cksum_provider = PROVIDER_OPENSSL;
|
||||
cpuid_basic_identify(&pc);
|
||||
if (pc.proc_type == PROC_X64_INTEL || pc.proc_type == PROC_X64_AMD) {
|
||||
if (opt_Init_SHA(&pc) == 0) {
|
||||
cksum_provider = PROVIDER_X64_OPT;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Check is either the given checksum name or id is valid and
|
||||
* return it's properties.
|
||||
*/
|
||||
int
|
||||
get_checksum_props(char *name, int *cksum, int *cksum_bytes, int *mac_bytes)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<sizeof (cksum_props); i++) {
|
||||
if ((name != NULL && strcmp(name, cksum_props[i].name) == 0) ||
|
||||
(*cksum != 0 && *cksum == cksum_props[i].cksum_id)) {
|
||||
*cksum = cksum_props[i].cksum_id;
|
||||
*cksum_bytes = cksum_props[i].bytes;
|
||||
*mac_bytes = cksum_props[i].mac_bytes;
|
||||
if (cksum_props[i].init_func)
|
||||
cksum_props[i].init_func();
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Endian independent way of storing the checksum bytes. This is actually
|
||||
* storing in little endian format and a copy can be avoided in x86 land.
|
||||
* However unsightly ifdefs are avoided here since this is not so performance
|
||||
* critical.
|
||||
*/
|
||||
void
|
||||
serialize_checksum(uchar_t *checksum, uchar_t *buf, int cksum_bytes)
|
||||
{
|
||||
int i,j;
|
||||
|
||||
j = 0;
|
||||
for (i=cksum_bytes; i>0; i--) {
|
||||
buf[j] = checksum[i-1];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
deserialize_checksum(uchar_t *checksum, uchar_t *buf, int cksum_bytes)
|
||||
{
|
||||
int i,j;
|
||||
|
||||
j = 0;
|
||||
for (i=cksum_bytes; i>0; i--) {
|
||||
checksum[i-1] = buf[j];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
hmac_init(mac_ctx_t *mctx, int cksum, crypto_ctx_t *cctx)
|
||||
{
|
||||
aes_ctx_t *actx = (aes_ctx_t *)(cctx->crypto_ctx);
|
||||
mctx->mac_cksum = cksum;
|
||||
|
||||
if (cksum == CKSUM_SKEIN256) {
|
||||
Skein_512_Ctxt_t *ctx = malloc(sizeof (Skein_512_Ctxt_t));
|
||||
if (!ctx) return (-1);
|
||||
Skein_512_InitExt(ctx, 256, SKEIN_CFG_TREE_INFO_SEQUENTIAL,
|
||||
actx->pkey, KEYLEN);
|
||||
mctx->mac_ctx = ctx;
|
||||
ctx = malloc(sizeof (Skein_512_Ctxt_t));
|
||||
if (!ctx) {
|
||||
free(mctx->mac_ctx);
|
||||
return (-1);
|
||||
}
|
||||
memcpy(ctx, mctx->mac_ctx, sizeof (Skein_512_Ctxt_t));
|
||||
mctx->mac_ctx_reinit = ctx;
|
||||
|
||||
} else if (cksum == CKSUM_SKEIN512) {
|
||||
Skein_512_Ctxt_t *ctx = malloc(sizeof (Skein_512_Ctxt_t));
|
||||
if (!ctx) return (-1);
|
||||
Skein_512_InitExt(ctx, 512, SKEIN_CFG_TREE_INFO_SEQUENTIAL,
|
||||
actx->pkey, KEYLEN);
|
||||
mctx->mac_ctx = ctx;
|
||||
ctx = malloc(sizeof (Skein_512_Ctxt_t));
|
||||
if (!ctx) {
|
||||
free(mctx->mac_ctx);
|
||||
return (-1);
|
||||
}
|
||||
memcpy(ctx, mctx->mac_ctx, sizeof (Skein_512_Ctxt_t));
|
||||
mctx->mac_ctx_reinit = ctx;
|
||||
|
||||
} else if (cksum == CKSUM_SHA256 || cksum == CKSUM_CRC64) {
|
||||
if (cksum_provider == PROVIDER_OPENSSL) {
|
||||
HMAC_CTX *ctx = malloc(sizeof (HMAC_CTX));
|
||||
if (!ctx) return (-1);
|
||||
HMAC_CTX_init(ctx);
|
||||
HMAC_Init_ex(ctx, actx->pkey, KEYLEN, EVP_sha256(), NULL);
|
||||
mctx->mac_ctx = ctx;
|
||||
|
||||
ctx = malloc(sizeof (HMAC_CTX));
|
||||
if (!ctx) {
|
||||
free(mctx->mac_ctx);
|
||||
return (-1);
|
||||
}
|
||||
if (!HMAC_CTX_copy(ctx, mctx->mac_ctx)) {
|
||||
free(ctx);
|
||||
free(mctx->mac_ctx);
|
||||
return (-1);
|
||||
}
|
||||
mctx->mac_ctx_reinit = ctx;
|
||||
} else {
|
||||
HMAC_SHA256_Context *ctx = malloc(sizeof (HMAC_SHA256_Context));
|
||||
if (!ctx) return (-1);
|
||||
opt_HMAC_SHA256_Init(ctx, actx->pkey, KEYLEN);
|
||||
mctx->mac_ctx = ctx;
|
||||
|
||||
ctx = malloc(sizeof (HMAC_SHA256_Context));
|
||||
if (!ctx) {
|
||||
free(mctx->mac_ctx);
|
||||
return (-1);
|
||||
}
|
||||
memcpy(ctx, mctx->mac_ctx, sizeof (HMAC_SHA256_Context));
|
||||
mctx->mac_ctx_reinit = ctx;
|
||||
}
|
||||
} else if (cksum == CKSUM_SHA512) {
|
||||
HMAC_CTX *ctx = malloc(sizeof (HMAC_CTX));
|
||||
if (!ctx) return (-1);
|
||||
HMAC_CTX_init(ctx);
|
||||
HMAC_Init_ex(ctx, actx->pkey, KEYLEN, EVP_sha512(), NULL);
|
||||
mctx->mac_ctx = ctx;
|
||||
|
||||
ctx = malloc(sizeof (HMAC_CTX));
|
||||
if (!ctx) {
|
||||
free(mctx->mac_ctx);
|
||||
return (-1);
|
||||
}
|
||||
if (!HMAC_CTX_copy(ctx, mctx->mac_ctx)) {
|
||||
free(ctx);
|
||||
free(mctx->mac_ctx);
|
||||
return (-1);
|
||||
}
|
||||
mctx->mac_ctx_reinit = ctx;
|
||||
} else {
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
hmac_reinit(mac_ctx_t *mctx)
|
||||
{
|
||||
int cksum = mctx->mac_cksum;
|
||||
|
||||
if (cksum == CKSUM_SKEIN256 || cksum == CKSUM_SKEIN512) {
|
||||
memcpy(mctx->mac_ctx, mctx->mac_ctx_reinit, sizeof (Skein_512_Ctxt_t));
|
||||
|
||||
} else if (cksum == CKSUM_SHA256 || cksum == CKSUM_CRC64) {
|
||||
if (cksum_provider == PROVIDER_OPENSSL) {
|
||||
HMAC_CTX_copy(mctx->mac_ctx, mctx->mac_ctx_reinit);
|
||||
} else {
|
||||
memcpy(mctx->mac_ctx, mctx->mac_ctx_reinit, sizeof (HMAC_SHA256_Context));
|
||||
}
|
||||
} else if (cksum == CKSUM_SHA512) {
|
||||
HMAC_CTX_copy(mctx->mac_ctx, mctx->mac_ctx_reinit);
|
||||
} else {
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
hmac_update(mac_ctx_t *mctx, uchar_t *data, size_t len)
|
||||
{
|
||||
int cksum = mctx->mac_cksum;
|
||||
|
||||
if (cksum == CKSUM_SKEIN256 || cksum == CKSUM_SKEIN512) {
|
||||
Skein_512_Update(mctx->mac_ctx, data, len);
|
||||
|
||||
} else if (cksum == CKSUM_SHA256 || cksum == CKSUM_CRC64) {
|
||||
if (cksum_provider == PROVIDER_OPENSSL) {
|
||||
if (HMAC_Update(mctx->mac_ctx, data, len) == 0)
|
||||
return (-1);
|
||||
} else {
|
||||
opt_HMAC_SHA256_Update(mctx->mac_ctx, data, len);
|
||||
}
|
||||
} else if (cksum == CKSUM_SHA512) {
|
||||
if (HMAC_Update(mctx->mac_ctx, data, len) == 0)
|
||||
return (-1);
|
||||
} else {
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
hmac_final(mac_ctx_t *mctx, uchar_t *hash, unsigned int *len)
|
||||
{
|
||||
int cksum = mctx->mac_cksum;
|
||||
|
||||
if (cksum == CKSUM_SKEIN256) {
|
||||
Skein_512_Final(mctx->mac_ctx, hash);
|
||||
*len = 32;
|
||||
|
||||
} else if (cksum == CKSUM_SKEIN512) {
|
||||
Skein_512_Final(mctx->mac_ctx, hash);
|
||||
*len = 64;
|
||||
|
||||
} else if (cksum == CKSUM_SHA256 || cksum == CKSUM_CRC64) {
|
||||
if (cksum_provider == PROVIDER_OPENSSL) {
|
||||
HMAC_Final(mctx->mac_ctx, hash, len);
|
||||
} else {
|
||||
opt_HMAC_SHA256_Final(mctx->mac_ctx, hash);
|
||||
*len = 32;
|
||||
}
|
||||
} else if (cksum == CKSUM_SHA512) {
|
||||
HMAC_Final(mctx->mac_ctx, hash, len);
|
||||
} else {
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
hmac_cleanup(mac_ctx_t *mctx)
|
||||
{
|
||||
int cksum = mctx->mac_cksum;
|
||||
|
||||
if (cksum == CKSUM_SKEIN256 || cksum == CKSUM_SKEIN512) {
|
||||
memset(mctx->mac_ctx, 0, sizeof (Skein_512_Ctxt_t));
|
||||
memset(mctx->mac_ctx_reinit, 0, sizeof (Skein_512_Ctxt_t));
|
||||
|
||||
} else if (cksum == CKSUM_SHA256 || cksum == CKSUM_CRC64) {
|
||||
if (cksum_provider == PROVIDER_OPENSSL) {
|
||||
HMAC_CTX_cleanup(mctx->mac_ctx);
|
||||
HMAC_CTX_cleanup(mctx->mac_ctx_reinit);
|
||||
} else {
|
||||
memset(mctx->mac_ctx, 0, sizeof (HMAC_SHA256_Context));
|
||||
memset(mctx->mac_ctx_reinit, 0, sizeof (HMAC_SHA256_Context));
|
||||
}
|
||||
} else if (cksum == CKSUM_SHA512) {
|
||||
HMAC_CTX_cleanup(mctx->mac_ctx);
|
||||
HMAC_CTX_cleanup(mctx->mac_ctx_reinit);
|
||||
} else {
|
||||
return (-1);
|
||||
}
|
||||
mctx->mac_cksum = 0;
|
||||
free(mctx->mac_ctx);
|
||||
free(mctx->mac_ctx_reinit);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
init_crypto(crypto_ctx_t *cctx, uchar_t *pwd, int pwd_len, int crypto_alg,
|
||||
uchar_t *salt, int saltlen, uint64_t nonce, int enc_dec)
|
||||
{
|
||||
if (crypto_alg == CRYPTO_ALG_AES) {
|
||||
aes_ctx_t *actx = malloc(sizeof (aes_ctx_t));
|
||||
|
||||
if (enc_dec) {
|
||||
/*
|
||||
* Encryption init.
|
||||
*/
|
||||
cctx->salt = malloc(32);
|
||||
salt = cctx->salt;
|
||||
cctx->saltlen = 32;
|
||||
if (RAND_status() != 1 || RAND_bytes(salt, 32) != 1) {
|
||||
if (geturandom_bytes(salt) != 0) {
|
||||
uchar_t sb[64];
|
||||
int b;
|
||||
struct timespec tp;
|
||||
|
||||
b = 0;
|
||||
/* No good random pool is populated/available. What to do ? */
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &tp) == -1) {
|
||||
time((time_t *)&sb[b]);
|
||||
b += 8;
|
||||
} else {
|
||||
uint64_t v;
|
||||
v = tp.tv_sec * 1000UL + tp.tv_nsec;
|
||||
*((uint64_t *)&sb[b]) = v;
|
||||
b += 8;
|
||||
}
|
||||
*((uint32_t *)&sb[b]) = rand();
|
||||
b += 4;
|
||||
*((uint32_t *)&sb[b]) = getpid();
|
||||
b += 4;
|
||||
compute_checksum(&sb[b], CKSUM_SHA256, sb, b);
|
||||
b = 8 + 4;
|
||||
*((uint32_t *)&sb[b]) = rand();
|
||||
compute_checksum(salt, CKSUM_SHA256, &sb[b], 32 + 4);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Zero nonce (arg #6) since it will be generated.
|
||||
*/
|
||||
if (aes_init(actx, salt, 32, pwd, pwd_len, 0, enc_dec) != 0) {
|
||||
fprintf(stderr, "Failed to initialize AES context\n");
|
||||
return (-1);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Decryption init.
|
||||
* Pass given nonce and salt.
|
||||
*/
|
||||
if (saltlen > MAX_SALTLEN) {
|
||||
fprintf(stderr, "Salt too long. Max allowed length is %d\n",
|
||||
MAX_SALTLEN);
|
||||
return (-1);
|
||||
}
|
||||
cctx->salt = malloc(saltlen);
|
||||
memcpy(cctx->salt, salt, saltlen);
|
||||
|
||||
if (aes_init(actx, cctx->salt, saltlen, pwd, pwd_len, nonce,
|
||||
enc_dec) != 0) {
|
||||
fprintf(stderr, "Failed to initialize AES context\n");
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
cctx->crypto_ctx = actx;
|
||||
cctx->crypto_alg = crypto_alg;
|
||||
cctx->enc_dec = enc_dec;
|
||||
} else {
|
||||
fprintf(stderr, "Unrecognized algorithm code: %d\n", crypto_alg);
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_buf(crypto_ctx_t *cctx, uchar_t *from, uchar_t *to, ssize_t bytes, uint64_t id)
|
||||
{
|
||||
if (cctx->crypto_alg == CRYPTO_ALG_AES) {
|
||||
if (cctx->enc_dec == ENCRYPT_FLAG) {
|
||||
return (aes_encrypt(cctx->crypto_ctx, from, to, bytes, id));
|
||||
} else {
|
||||
return (aes_decrypt(cctx->crypto_ctx, from, to, bytes, id));
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Unrecognized algorithm code: %d\n", cctx->crypto_alg);
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
crypto_nonce(crypto_ctx_t *cctx)
|
||||
{
|
||||
return (aes_nonce(cctx->crypto_ctx));
|
||||
}
|
||||
|
||||
void
|
||||
crypto_clean_pkey(crypto_ctx_t *cctx)
|
||||
{
|
||||
aes_clean_pkey(cctx->crypto_ctx);
|
||||
}
|
||||
|
||||
void
|
||||
cleanup_crypto(crypto_ctx_t *cctx)
|
||||
{
|
||||
aes_cleanup(cctx->crypto_ctx);
|
||||
memset(cctx->salt, 0, 32);
|
||||
free(cctx->salt);
|
||||
free(cctx);
|
||||
}
|
||||
|
||||
static int
|
||||
geturandom_bytes(uchar_t rbytes[32])
|
||||
{
|
||||
int fd;
|
||||
ssize_t lenread;
|
||||
uchar_t * buf = rbytes;
|
||||
size_t buflen = 32;
|
||||
|
||||
/* Open /dev/urandom. */
|
||||
if ((fd = open("/dev/urandom", O_RDONLY)) == -1)
|
||||
goto err0;
|
||||
|
||||
/* Read bytes until we have filled the buffer. */
|
||||
while (buflen > 0) {
|
||||
if ((lenread = read(fd, buf, buflen)) == -1)
|
||||
goto err1;
|
||||
|
||||
/* The random device should never EOF. */
|
||||
if (lenread == 0)
|
||||
goto err1;
|
||||
|
||||
/* We're partly done. */
|
||||
buf += lenread;
|
||||
buflen -= lenread;
|
||||
}
|
||||
|
||||
/* Close the device. */
|
||||
while (close(fd) == -1) {
|
||||
if (errno != EINTR)
|
||||
goto err0;
|
||||
}
|
||||
|
||||
/* Success! */
|
||||
return (0);
|
||||
err1:
|
||||
close(fd);
|
||||
err0:
|
||||
/* Failure! */
|
||||
return (4);
|
||||
}
|
||||
|
||||
int
|
||||
get_pw_string(char pw[MAX_PW_LEN], char *prompt)
|
||||
{
|
||||
int fd, len;
|
||||
FILE *input, *strm;
|
||||
struct termios oldt, newt;
|
||||
uchar_t pw1[MAX_PW_LEN], pw2[MAX_PW_LEN], *s;
|
||||
|
||||
// Try TTY first
|
||||
fd = open("/dev/tty", O_RDWR | O_NOCTTY);
|
||||
if (fd != -1) {
|
||||
input = fdopen(fd, "w+");
|
||||
strm = input;
|
||||
} else {
|
||||
// Fall back to stdin
|
||||
fd = STDIN_FILENO;
|
||||
input = stdin;
|
||||
strm = stderr;
|
||||
}
|
||||
tcgetattr(fd, &oldt);
|
||||
newt = oldt;
|
||||
newt.c_lflag &= ~ECHO;
|
||||
tcsetattr(fd, TCSANOW, &newt);
|
||||
|
||||
fprintf(stderr, "%s: ", prompt);
|
||||
fflush(stderr);
|
||||
s = fgets(pw1, MAX_PW_LEN, input);
|
||||
fputs("\n", stderr);
|
||||
|
||||
if (s == NULL) {
|
||||
tcsetattr(fd, TCSANOW, &oldt);
|
||||
fflush(strm);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s (once more): ", prompt);
|
||||
fflush(stderr);
|
||||
s = fgets(pw2, MAX_PW_LEN, input);
|
||||
tcsetattr(fd, TCSANOW, &oldt);
|
||||
fflush(strm);
|
||||
fputs("\n", stderr);
|
||||
|
||||
if (s == NULL) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (strcmp(pw1, pw2) != 0) {
|
||||
fprintf(stderr, "Passwords do not match!\n");
|
||||
memset(pw1, 0, MAX_PW_LEN);
|
||||
memset(pw2, 0, MAX_PW_LEN);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
len = strlen(pw1);
|
||||
pw1[len-1] = '\0';
|
||||
strcpy(pw, pw1);
|
||||
memset(pw1, 0, MAX_PW_LEN);
|
||||
memset(pw2, 0, MAX_PW_LEN);
|
||||
return (len);
|
||||
}
|
102
crypto/crypto_utils.h
Normal file
102
crypto/crypto_utils.h
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* This file is a part of Pcompress, a chunked parallel multi-
|
||||
* algorithm lossless compression and decompression program.
|
||||
*
|
||||
* Copyright (C) 2012 Moinak Ghosh. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* moinakg@belenix.org, http://moinakg.wordpress.com/
|
||||
*
|
||||
* This program includes partly-modified public domain source
|
||||
* code from the LZMA SDK: http://www.7-zip.org/sdk.html
|
||||
*/
|
||||
|
||||
#ifndef _CRYPTO_UTILS_H
|
||||
#define _CRYPTO_UTILS_H
|
||||
|
||||
#include <arpa/nameser_compat.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MAX_PW_LEN 16
|
||||
#define CKSUM_MASK 0x700
|
||||
#define CKSUM_MAX_BYTES 64
|
||||
#define DEFAULT_CKSUM "SKEIN256"
|
||||
|
||||
#define ENCRYPT_FLAG 1
|
||||
#define DECRYPT_FLAG 0
|
||||
#define CRYPTO_ALG_AES 0x10
|
||||
#define MAX_SALTLEN 64
|
||||
|
||||
/*
|
||||
* Public checksum properties. CKSUM_MAX_BYTES must be updated if a
|
||||
* newer larger checksum is added to the list.
|
||||
*/
|
||||
typedef enum {
|
||||
CKSUM_CRC64 = 0x100,
|
||||
CKSUM_SKEIN256 = 0x200,
|
||||
CKSUM_SKEIN512 = 0x300,
|
||||
CKSUM_SHA256 = 0x400,
|
||||
CKSUM_SHA512 = 0x500
|
||||
} cksum_t;
|
||||
|
||||
typedef struct {
|
||||
void *crypto_ctx;
|
||||
int crypto_alg;
|
||||
int enc_dec;
|
||||
uchar_t *salt;
|
||||
int saltlen;
|
||||
} crypto_ctx_t;
|
||||
|
||||
typedef struct {
|
||||
void *mac_ctx;
|
||||
void *mac_ctx_reinit;
|
||||
int mac_cksum;
|
||||
} mac_ctx_t;
|
||||
|
||||
/*
|
||||
* Generic message digest functions.
|
||||
*/
|
||||
int compute_checksum(uchar_t *cksum_buf, int cksum, uchar_t *buf, ssize_t bytes);
|
||||
int get_checksum_props(char *name, int *cksum, int *cksum_bytes, int *mac_bytes);
|
||||
void serialize_checksum(uchar_t *checksum, uchar_t *buf, int cksum_bytes);
|
||||
void deserialize_checksum(uchar_t *checksum, uchar_t *buf, int cksum_bytes);
|
||||
|
||||
/*
|
||||
* Encryption related functions.
|
||||
*/
|
||||
int init_crypto(crypto_ctx_t *cctx, uchar_t *pwd, int pwd_len, int crypto_alg,
|
||||
uchar_t *salt, int saltlen, uint64_t nonce, int enc_dec);
|
||||
int crypto_buf(crypto_ctx_t *cctx, uchar_t *from, uchar_t *to, ssize_t bytes, uint64_t id);
|
||||
uint64_t crypto_nonce(crypto_ctx_t *cctx);
|
||||
void crypto_clean_pkey(crypto_ctx_t *cctx);
|
||||
void cleanup_crypto(crypto_ctx_t *cctx);
|
||||
int get_pw_string(char pw[MAX_PW_LEN], char *prompt);
|
||||
|
||||
/*
|
||||
* HMAC functions.
|
||||
*/
|
||||
int hmac_init(mac_ctx_t *mctx, int cksum, crypto_ctx_t *cctx);
|
||||
int hmac_reinit(mac_ctx_t *mctx);
|
||||
int hmac_update(mac_ctx_t *mctx, uchar_t *data, size_t len);
|
||||
int hmac_cleanup(mac_ctx_t *mctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -105,7 +105,7 @@ static void
|
|||
_init (SHA256_Context *sc, const uint32_t iv[SHA256_HASH_WORDS])
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
/*
|
||||
* SHA256_HASH_WORDS is 8, must be 8, cannot be anything but 8!
|
||||
* So we unroll a loop here.
|
||||
|
@ -118,7 +118,7 @@ _init (SHA256_Context *sc, const uint32_t iv[SHA256_HASH_WORDS])
|
|||
sc->hash[5] = iv[5];
|
||||
sc->hash[6] = iv[6];
|
||||
sc->hash[7] = iv[7];
|
||||
|
||||
|
||||
sc->totalLength = 0LL;
|
||||
sc->bufferLength = 0L;
|
||||
}
|
||||
|
@ -130,26 +130,26 @@ APS_NAMESPACE(SHA256_Init) (SHA256_Context *sc)
|
|||
}
|
||||
|
||||
void
|
||||
APS_NAMESPACE(SHA256_Update) (SHA256_Context *sc, void *vdata, size_t len)
|
||||
APS_NAMESPACE(SHA256_Update) (SHA256_Context *sc, const void *vdata, size_t len)
|
||||
{
|
||||
const uint8_t *data = vdata;
|
||||
uint32_t bufferBytesLeft;
|
||||
size_t bytesToCopy;
|
||||
int rem;
|
||||
|
||||
|
||||
if (sc->bufferLength) {
|
||||
do {
|
||||
bufferBytesLeft = 64L - sc->bufferLength;
|
||||
bytesToCopy = bufferBytesLeft;
|
||||
if (bytesToCopy > len)
|
||||
bytesToCopy = len;
|
||||
|
||||
|
||||
memcpy (&sc->buffer.bytes[sc->bufferLength], data, bytesToCopy);
|
||||
sc->totalLength += bytesToCopy * 8L;
|
||||
sc->bufferLength += bytesToCopy;
|
||||
data += bytesToCopy;
|
||||
len -= bytesToCopy;
|
||||
|
||||
|
||||
if (sc->bufferLength == 64L) {
|
||||
sc->blocks = 1;
|
||||
sha_update_func(sc->buffer.words, sc->hash, sc->blocks);
|
||||
|
@ -160,12 +160,12 @@ APS_NAMESPACE(SHA256_Update) (SHA256_Context *sc, void *vdata, size_t len)
|
|||
} while (len > 0 && len <= 64L);
|
||||
if (!len) return;
|
||||
}
|
||||
|
||||
|
||||
sc->blocks = len >> 6;
|
||||
rem = len - (sc->blocks << 6);
|
||||
len = sc->blocks << 6;
|
||||
sc->totalLength += rem * 8L;
|
||||
|
||||
|
||||
if (len) {
|
||||
sc->totalLength += len * 8L;
|
||||
sha_update_func((uint32_t *)data, sc->hash, sc->blocks);
|
||||
|
@ -182,16 +182,16 @@ _final (SHA256_Context *sc, uint8_t *hash, int hashWords)
|
|||
uint32_t bytesToPad;
|
||||
uint64_t lengthPad;
|
||||
int i;
|
||||
|
||||
|
||||
bytesToPad = 120L - sc->bufferLength;
|
||||
if (bytesToPad > 64L)
|
||||
bytesToPad -= 64L;
|
||||
|
||||
|
||||
lengthPad = BYTESWAP64(sc->totalLength);
|
||||
|
||||
|
||||
APS_NAMESPACE(SHA256_Update) (sc, padding, bytesToPad);
|
||||
APS_NAMESPACE(SHA256_Update) (sc, &lengthPad, 8L);
|
||||
|
||||
|
||||
if (hash) {
|
||||
for (i = 0; i < hashWords; i++) {
|
||||
hash[0] = (uint8_t) (sc->hash[i] >> 24);
|
||||
|
@ -208,3 +208,66 @@ APS_NAMESPACE(SHA256_Final) (SHA256_Context *sc, uint8_t hash[SHA256_HASH_SIZE])
|
|||
{
|
||||
_final (sc, hash, SHA256_HASH_WORDS);
|
||||
}
|
||||
|
||||
/* Initialize an HMAC-SHA256 operation with the given key. */
|
||||
void
|
||||
APS_NAMESPACE(HMAC_SHA256_Init) (HMAC_SHA256_Context * ctx, const void * _K, size_t Klen)
|
||||
{
|
||||
unsigned char pad[64];
|
||||
unsigned char khash[32];
|
||||
const unsigned char * K = _K;
|
||||
size_t i;
|
||||
|
||||
/* If Klen > 64, the key is really SHA256(K). */
|
||||
if (Klen > 64) {
|
||||
APS_NAMESPACE(SHA256_Init)(&ctx->ictx);
|
||||
APS_NAMESPACE(SHA256_Update)(&ctx->ictx, K, Klen);
|
||||
APS_NAMESPACE(SHA256_Final)(&ctx->ictx, khash);
|
||||
K = khash;
|
||||
Klen = 32;
|
||||
}
|
||||
|
||||
/* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */
|
||||
APS_NAMESPACE(SHA256_Init)(&ctx->ictx);
|
||||
memset(pad, 0x36, 64);
|
||||
for (i = 0; i < Klen; i++)
|
||||
pad[i] ^= K[i];
|
||||
APS_NAMESPACE(SHA256_Update)(&ctx->ictx, pad, 64);
|
||||
|
||||
/* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */
|
||||
APS_NAMESPACE(SHA256_Init)(&ctx->octx);
|
||||
memset(pad, 0x5c, 64);
|
||||
for (i = 0; i < Klen; i++)
|
||||
pad[i] ^= K[i];
|
||||
APS_NAMESPACE(SHA256_Update)(&ctx->octx, pad, 64);
|
||||
|
||||
/* Clean the stack. */
|
||||
memset(khash, 0, 32);
|
||||
}
|
||||
|
||||
/* Add bytes to the HMAC-SHA256 operation. */
|
||||
void
|
||||
APS_NAMESPACE(HMAC_SHA256_Update) (HMAC_SHA256_Context * ctx, const void *in, size_t len)
|
||||
{
|
||||
/* Feed data to the inner SHA256 operation. */
|
||||
APS_NAMESPACE(SHA256_Update)(&ctx->ictx, in, len);
|
||||
}
|
||||
|
||||
/* Finish an HMAC-SHA256 operation. */
|
||||
void
|
||||
APS_NAMESPACE(HMAC_SHA256_Final) (HMAC_SHA256_Context * ctx, unsigned char digest[32])
|
||||
{
|
||||
unsigned char ihash[32];
|
||||
|
||||
/* Finish the inner SHA256 operation. */
|
||||
APS_NAMESPACE(SHA256_Final)(&ctx->ictx, ihash);
|
||||
|
||||
/* Feed the inner hash to the outer SHA256 operation. */
|
||||
APS_NAMESPACE(SHA256_Update)(&ctx->octx, ihash, 32);
|
||||
|
||||
/* Finish the outer SHA256 operation. */
|
||||
APS_NAMESPACE(SHA256_Final)(&ctx->octx, digest);
|
||||
|
||||
/* Clean the stack. */
|
||||
memset(ihash, 0, 32);
|
||||
}
|
||||
|
|
|
@ -53,6 +53,11 @@ typedef struct _SHA256_Context {
|
|||
} buffer;
|
||||
} SHA256_Context;
|
||||
|
||||
typedef struct HMAC_SHA256Context {
|
||||
SHA256_Context ictx;
|
||||
SHA256_Context octx;
|
||||
} HMAC_SHA256_Context;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -62,10 +67,14 @@ extern "C" {
|
|||
#endif /* !APS_NAMESPACE */
|
||||
|
||||
void APS_NAMESPACE(SHA256_Init) (SHA256_Context *sc);
|
||||
void APS_NAMESPACE(SHA256_Update) (SHA256_Context *sc, void *data, size_t len);
|
||||
void APS_NAMESPACE(SHA256_Update) (SHA256_Context *sc, const void *data, size_t len);
|
||||
void APS_NAMESPACE(SHA256_Final) (SHA256_Context *sc, uint8_t hash[SHA256_HASH_SIZE]);
|
||||
int APS_NAMESPACE(Init_SHA) (processor_info_t *pc);
|
||||
|
||||
void APS_NAMESPACE(HMAC_SHA256_Init) (HMAC_SHA256_Context * ctx, const void * _K, size_t Klen);
|
||||
void APS_NAMESPACE(HMAC_SHA256_Update) (HMAC_SHA256_Context * ctx, const void *in, size_t len);
|
||||
void APS_NAMESPACE(HMAC_SHA256_Final) (HMAC_SHA256_Context * ctx, unsigned char digest[32]);
|
||||
|
||||
/*
|
||||
* Intel's optimized SHA256 core routines. These routines are described in an
|
||||
* Intel White-Paper:
|
||||
|
|
126
main.c
126
main.c
|
@ -51,6 +51,7 @@
|
|||
* We use 5MB chunks by default.
|
||||
*/
|
||||
#define DEFAULT_CHUNKSIZE (5 * 1024 * 1024)
|
||||
#define EIGHTY_PCT(x) ((x) - ((x)/5))
|
||||
|
||||
struct wdata {
|
||||
struct cmp_data **dary;
|
||||
|
@ -88,7 +89,7 @@ static const char *exec_name;
|
|||
static const char *algo = NULL;
|
||||
static int do_compress = 0;
|
||||
static int do_uncompress = 0;
|
||||
static int cksum_bytes;
|
||||
static int cksum_bytes, mac_bytes;
|
||||
static int cksum = 0;
|
||||
static int rab_blk_size = 0;
|
||||
static dedupe_context_t *rctx;
|
||||
|
@ -291,7 +292,7 @@ redo:
|
|||
goto cont;
|
||||
}
|
||||
|
||||
cseg = tdat->compressed_chunk + cksum_bytes;
|
||||
cseg = tdat->compressed_chunk + cksum_bytes + mac_bytes;
|
||||
_chunksize = tdat->chunksize;
|
||||
deserialize_checksum(tdat->checksum, tdat->compressed_chunk, cksum_bytes);
|
||||
HDR = *cseg;
|
||||
|
@ -309,6 +310,8 @@ redo:
|
|||
* Decrypt compressed data if necessary.
|
||||
*/
|
||||
if (encrypt_type) {
|
||||
uchar_t hmac[CKSUM_MAX_BYTES];
|
||||
|
||||
/*
|
||||
* Encryption algorithm should not change the size and
|
||||
* encryption is in-place.
|
||||
|
@ -538,6 +541,25 @@ start_decompress(const char *filename, const char *to_filename)
|
|||
chunksize = ntohll(chunksize);
|
||||
level = ntohl(level);
|
||||
|
||||
/*
|
||||
* Check for ridiculous values (malicious tampering or otherwise).
|
||||
*/
|
||||
if (version > VERSION) {
|
||||
fprintf(stderr, "Cannot handle newer archive version %d, capability %d\n",
|
||||
version, VERSION);
|
||||
err = 1;
|
||||
goto uncomp_done;
|
||||
}
|
||||
if (chunksize > EIGHTY_PCT(get_total_ram())) {
|
||||
fprintf(stderr, "Chunk size must not exceed 80%% of total RAM.\n");
|
||||
err = 1;
|
||||
goto uncomp_done;
|
||||
}
|
||||
if (level > MAX_LEVEL || level < 0) {
|
||||
fprintf(stderr, "Invalid compression level in header: %d\n", level);
|
||||
err = 1;
|
||||
goto uncomp_done;
|
||||
}
|
||||
if (version < VERSION-2) {
|
||||
fprintf(stderr, "Unsupported version: %d\n", version);
|
||||
err = 1;
|
||||
|
@ -566,7 +588,7 @@ start_decompress(const char *filename, const char *to_filename)
|
|||
}
|
||||
|
||||
cksum = flags & CKSUM_MASK;
|
||||
if (get_checksum_props(NULL, &cksum, &cksum_bytes) == -1) {
|
||||
if (get_checksum_props(NULL, &cksum, &cksum_bytes, &mac_bytes) == -1) {
|
||||
fprintf(stderr, "Invalid checksum algorithm code: %d. File corrupt ?\n", cksum);
|
||||
UNCOMP_BAIL;
|
||||
}
|
||||
|
@ -580,7 +602,13 @@ start_decompress(const char *filename, const char *to_filename)
|
|||
uint64_t nonce;
|
||||
uchar_t pw[MAX_PW_LEN];
|
||||
int pw_len;
|
||||
mac_ctx_t hdr_mac;
|
||||
uchar_t hdr_hash1[mac_bytes], hdr_hash2[mac_bytes];
|
||||
unsigned int hlen;
|
||||
unsigned short d1;
|
||||
unsigned int d2;
|
||||
|
||||
compressed_chunksize += mac_bytes;
|
||||
encrypt_type = flags & MASK_CRYPTO_ALG;
|
||||
if (Read(compfd, &saltlen, sizeof (saltlen)) < sizeof (saltlen)) {
|
||||
perror("Read: ");
|
||||
|
@ -606,13 +634,21 @@ start_decompress(const char *filename, const char *to_filename)
|
|||
}
|
||||
nonce = ntohll(nonce);
|
||||
|
||||
if (Read(compfd, hdr_hash1, mac_bytes) < mac_bytes) {
|
||||
memset(salt2, 0, saltlen);
|
||||
free(salt2);
|
||||
perror("Read: ");
|
||||
UNCOMP_BAIL;
|
||||
}
|
||||
deserialize_checksum(hdr_hash2, hdr_hash1, mac_bytes);
|
||||
|
||||
if (!pwd_file) {
|
||||
pw_len = get_pw_string(pw,
|
||||
"Please enter encryption password");
|
||||
if (pw_len == -1) {
|
||||
memset(salt2, 0, saltlen);
|
||||
free(salt2);
|
||||
err_exit(1, "Failed to get password.\n");
|
||||
err_exit(0, "Failed to get password.\n");
|
||||
}
|
||||
} else {
|
||||
int fd, len;
|
||||
|
@ -644,21 +680,45 @@ start_decompress(const char *filename, const char *to_filename)
|
|||
perror(" ");
|
||||
memset(salt2, 0, saltlen);
|
||||
free(salt2);
|
||||
err_exit(1, "Failed to get password.\n");
|
||||
err_exit(0, "Failed to get password.\n");
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
if (init_crypto(&crypto_ctx, pw, pw_len, encrypt_type, salt2,
|
||||
saltlen, nonce, DECRYPT_FLAG) == -1) {
|
||||
memset(salt2, 0, saltlen);
|
||||
free(salt2);
|
||||
memset(pw, 0, MAX_PW_LEN);
|
||||
err_exit(1, "Failed to initialize crypto\n");
|
||||
err_exit(0, "Failed to initialize crypto\n");
|
||||
}
|
||||
memset(salt2, 0, saltlen);
|
||||
free(salt2);
|
||||
nonce = 0;
|
||||
memset(pw, 0, MAX_PW_LEN);
|
||||
|
||||
/*
|
||||
* Verify header HMAC.
|
||||
*/
|
||||
if (hmac_init(&hdr_mac, cksum, &crypto_ctx) == -1) {
|
||||
err_exit(0, "Cannot initialize header hmac.\n");
|
||||
}
|
||||
hmac_update(&hdr_mac, (uchar_t *)algo, ALGO_SZ);
|
||||
d1 = htons(version);
|
||||
hmac_update(&hdr_mac, (uchar_t *)&d1, sizeof (version));
|
||||
d1 = htons(flags);
|
||||
hmac_update(&hdr_mac, (uchar_t *)&d1, sizeof (version));
|
||||
nonce = htonll(chunksize);
|
||||
hmac_update(&hdr_mac, (uchar_t *)&nonce, sizeof (nonce));
|
||||
d2 = htonl(level);
|
||||
hmac_update(&hdr_mac, (uchar_t *)&d2, sizeof (level));
|
||||
hmac_final(&hdr_mac, hdr_hash1, &hlen);
|
||||
hmac_cleanup(&hdr_mac);
|
||||
if (memcmp(hdr_hash2, hdr_hash1, mac_bytes) != 0) {
|
||||
err_exit(0, "Header verification failed! File tampered.\n");
|
||||
}
|
||||
} else {
|
||||
mac_bytes = 0;
|
||||
}
|
||||
|
||||
nprocs = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
|
@ -758,6 +818,15 @@ start_decompress(const char *filename, const char *to_filename)
|
|||
}
|
||||
tdat->len_cmp = htonll(tdat->len_cmp);
|
||||
|
||||
/*
|
||||
* Check for ridiculous length.
|
||||
*/
|
||||
if (tdat->len_cmp > chunksize + 256) {
|
||||
fprintf(stderr, "Compressed length too big for chunk: %d\n",
|
||||
chunk_num);
|
||||
UNCOMP_BAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Zero compressed len means end of file.
|
||||
*/
|
||||
|
@ -799,9 +868,9 @@ start_decompress(const char *filename, const char *to_filename)
|
|||
* Now read compressed chunk including the checksum.
|
||||
*/
|
||||
tdat->rbytes = Read(compfd, tdat->compressed_chunk,
|
||||
tdat->len_cmp + cksum_bytes + CHUNK_FLAG_SZ);
|
||||
tdat->len_cmp + cksum_bytes + mac_bytes + CHUNK_FLAG_SZ);
|
||||
if (main_cancel) break;
|
||||
if (tdat->rbytes < tdat->len_cmp + cksum_bytes + CHUNK_FLAG_SZ) {
|
||||
if (tdat->rbytes < tdat->len_cmp + cksum_bytes + mac_bytes + CHUNK_FLAG_SZ) {
|
||||
if (tdat->rbytes < 0) {
|
||||
perror("Read: ");
|
||||
UNCOMP_BAIL;
|
||||
|
@ -978,6 +1047,7 @@ plain_compress:
|
|||
compressed_chunk, &_chunksize, tdat->level, 0, tdat->data);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sanity check to ensure compressed data is lesser than original.
|
||||
* If at all compression expands/does not shrink data then the chunk
|
||||
|
@ -1030,7 +1100,7 @@ plain_compress:
|
|||
serialize_checksum(tdat->checksum, tdat->cmp_seg + sizeof (tdat->len_cmp), cksum_bytes);
|
||||
tdat->len_cmp += CHUNK_FLAG_SZ;
|
||||
tdat->len_cmp += sizeof (len_cmp);
|
||||
tdat->len_cmp += cksum_bytes;
|
||||
tdat->len_cmp += (cksum_bytes + mac_bytes);
|
||||
|
||||
if (adapt_mode)
|
||||
type |= (rv << 4);
|
||||
|
@ -1159,6 +1229,7 @@ start_compress(const char *filename, uint64_t chunksize, int level)
|
|||
uchar_t pw[MAX_PW_LEN];
|
||||
int pw_len;
|
||||
|
||||
compressed_chunksize += mac_bytes;
|
||||
if (!pwd_file) {
|
||||
pw_len = get_pw_string(pw,
|
||||
"Please enter encryption password");
|
||||
|
@ -1379,16 +1450,31 @@ start_compress(const char *filename, uint64_t chunksize, int level)
|
|||
}
|
||||
|
||||
/*
|
||||
* If encryption is enabled, write the salt and nonce.
|
||||
* If encryption is enabled, compute header HMAC. Then
|
||||
* write the salt, nonce and header hmac in that order.
|
||||
*/
|
||||
pos = cread_buf;
|
||||
if (encrypt_type) {
|
||||
mac_ctx_t hdr_mac;
|
||||
uchar_t hdr_hash[mac_bytes];
|
||||
unsigned int hlen;
|
||||
|
||||
if (hmac_init(&hdr_mac, cksum, &crypto_ctx) == -1) {
|
||||
fprintf(stderr, "Cannot initialize header hmac.\n");
|
||||
COMP_BAIL;
|
||||
}
|
||||
hmac_update(&hdr_mac, cread_buf, pos - cread_buf);
|
||||
hmac_final(&hdr_mac, hdr_hash, &hlen);
|
||||
hmac_cleanup(&hdr_mac);
|
||||
|
||||
pos = cread_buf;
|
||||
*((int *)pos) = htonl(crypto_ctx.saltlen);
|
||||
pos += sizeof (int);
|
||||
serialize_checksum(crypto_ctx.salt, pos, crypto_ctx.saltlen);
|
||||
pos += crypto_ctx.saltlen;
|
||||
*((uint64_t *)pos) = htonll(crypto_nonce(&crypto_ctx));
|
||||
pos += 8;
|
||||
serialize_checksum(hdr_hash, pos, hlen);
|
||||
pos += hlen;
|
||||
if (Write(compfd, cread_buf, pos - cread_buf) != pos - cread_buf) {
|
||||
perror("Write ");
|
||||
COMP_BAIL;
|
||||
|
@ -1455,7 +1541,8 @@ start_compress(const char *filename, uint64_t chunksize, int level)
|
|||
tdat->cmp_seg = (uchar_t *)slab_alloc(NULL,
|
||||
compressed_chunksize);
|
||||
}
|
||||
tdat->compressed_chunk = tdat->cmp_seg + COMPRESSED_CHUNKSZ + cksum_bytes;
|
||||
tdat->compressed_chunk = tdat->cmp_seg + COMPRESSED_CHUNKSZ +
|
||||
cksum_bytes + mac_bytes;
|
||||
if (!tdat->cmp_seg || !tdat->uncompressed_chunk) {
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
COMP_BAIL;
|
||||
|
@ -1477,7 +1564,8 @@ start_compress(const char *filename, uint64_t chunksize, int level)
|
|||
tmp = tdat->cmp_seg;
|
||||
tdat->cmp_seg = cread_buf;
|
||||
cread_buf = tmp;
|
||||
tdat->compressed_chunk = tdat->cmp_seg + COMPRESSED_CHUNKSZ + cksum_bytes;
|
||||
tdat->compressed_chunk = tdat->cmp_seg + COMPRESSED_CHUNKSZ +
|
||||
cksum_bytes + mac_bytes;
|
||||
|
||||
/*
|
||||
* If there is data after the last rabin boundary in the chunk, then
|
||||
|
@ -1763,11 +1851,14 @@ main(int argc, char *argv[])
|
|||
if (chunksize < MIN_CHUNK) {
|
||||
err_exit(0, "Minimum chunk size is %ld\n", MIN_CHUNK);
|
||||
}
|
||||
if (chunksize > EIGHTY_PCT(get_total_ram())) {
|
||||
err_exit(0, "Chunk size must not exceed 80%% of total RAM.\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
level = atoi(optarg);
|
||||
if (level < 0 || level > 14)
|
||||
if (level < 0 || level > MAX_LEVEL)
|
||||
err_exit(0, "Compression level should be in range 0 - 14\n");
|
||||
break;
|
||||
|
||||
|
@ -1829,7 +1920,7 @@ main(int argc, char *argv[])
|
|||
break;
|
||||
|
||||
case 'S':
|
||||
if (get_checksum_props(optarg, &cksum, &cksum_bytes) == -1) {
|
||||
if (get_checksum_props(optarg, &cksum, &cksum_bytes, &mac_bytes) == -1) {
|
||||
err_exit(0, "Invalid checksum type %s", optarg);
|
||||
}
|
||||
break;
|
||||
|
@ -1873,6 +1964,7 @@ main(int argc, char *argv[])
|
|||
if (!do_compress && encrypt_type) {
|
||||
fprintf(stderr, "Encryption only makes sense when compressing!\n");
|
||||
exit(1);
|
||||
|
||||
} else if (pipe_mode && !pwd_file) {
|
||||
fprintf(stderr, "Pipe mode requires password to be provided in a file.\n");
|
||||
exit(1);
|
||||
|
@ -1922,8 +2014,10 @@ main(int argc, char *argv[])
|
|||
main_cancel = 0;
|
||||
|
||||
if (cksum == 0)
|
||||
get_checksum_props(DEFAULT_CKSUM, &cksum, &cksum_bytes);
|
||||
get_checksum_props(DEFAULT_CKSUM, &cksum, &cksum_bytes, &mac_bytes);
|
||||
|
||||
if (!encrypt_type)
|
||||
mac_bytes = 0;
|
||||
/*
|
||||
* Start the main routines.
|
||||
*/
|
||||
|
|
|
@ -33,6 +33,7 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#include <rabin_dedup.h>
|
||||
#include <crypto_utils.h>
|
||||
|
||||
#define CHUNK_FLAG_SZ 1
|
||||
#define ALGO_SZ 8
|
||||
|
@ -43,6 +44,7 @@ extern "C" {
|
|||
#define FLAG_SINGLE_CHUNK 4
|
||||
#define UTILITY_VERSION "0.8.6"
|
||||
#define MASK_CRYPTO_ALG 0x30
|
||||
#define MAX_LEVEL 14
|
||||
|
||||
#define COMPRESSED 1
|
||||
#define UNCOMPRESSED 0
|
||||
|
|
368
utils/utils.c
368
utils/utils.c
|
@ -35,44 +35,8 @@
|
|||
#include <errno.h>
|
||||
#include <link.h>
|
||||
#include <rabin_dedup.h>
|
||||
#include <skein.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <sha256.h>
|
||||
#include <crypto_aes.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "cpuid.h"
|
||||
|
||||
#define PROVIDER_OPENSSL 0
|
||||
#define PROVIDER_X64_OPT 1
|
||||
|
||||
static void init_sha256(void);
|
||||
static int geturandom_bytes(uchar_t rbytes[32]);
|
||||
/*
|
||||
* Checksum properties
|
||||
*/
|
||||
typedef void (*ckinit_func_ptr)(void);
|
||||
static struct {
|
||||
char *name;
|
||||
cksum_t cksum_id;
|
||||
int bytes;
|
||||
ckinit_func_ptr init_func;
|
||||
} cksum_props[] = {
|
||||
{"CRC64", CKSUM_CRC64, 8, NULL},
|
||||
{"SKEIN256", CKSUM_SKEIN256, 32, NULL},
|
||||
{"SKEIN512", CKSUM_SKEIN512, 64, NULL},
|
||||
{"SHA256", CKSUM_SHA256, 32, init_sha256},
|
||||
{"SHA512", CKSUM_SHA512, 64, NULL}
|
||||
};
|
||||
|
||||
|
||||
static int cksum_provider = PROVIDER_OPENSSL, ossl_inited = 0;
|
||||
|
||||
extern uint64_t lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc);
|
||||
extern uint64_t lzma_crc64_8bchk(const uint8_t *buf, size_t size,
|
||||
uint64_t crc, uint64_t *cnt);
|
||||
|
||||
void
|
||||
err_exit(int show_errno, const char *format, ...)
|
||||
|
@ -335,332 +299,12 @@ set_threadcounts(algo_props_t *props, int *nthreads, int nprocs, algo_threads_ty
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
compute_checksum(uchar_t *cksum_buf, int cksum, uchar_t *buf, ssize_t bytes)
|
||||
{
|
||||
if (cksum == CKSUM_CRC64) {
|
||||
uint64_t *ck = (uint64_t *)cksum_buf;
|
||||
*ck = lzma_crc64(buf, bytes, 0);
|
||||
|
||||
} else if (cksum == CKSUM_SKEIN256) {
|
||||
Skein_512_Ctxt_t ctx;
|
||||
|
||||
Skein_512_Init(&ctx, 256);
|
||||
Skein_512_Update(&ctx, buf, bytes);
|
||||
Skein_512_Final(&ctx, cksum_buf);
|
||||
|
||||
} else if (cksum == CKSUM_SKEIN512) {
|
||||
Skein_512_Ctxt_t ctx;
|
||||
|
||||
Skein_512_Init(&ctx, 512);
|
||||
Skein_512_Update(&ctx, buf, bytes);
|
||||
Skein_512_Final(&ctx, cksum_buf);
|
||||
|
||||
} else if (cksum == CKSUM_SHA256) {
|
||||
if (cksum_provider == PROVIDER_OPENSSL) {
|
||||
SHA256_CTX ctx;
|
||||
|
||||
SHA256_Init(&ctx);
|
||||
SHA256_Update(&ctx, buf, bytes);
|
||||
SHA256_Final(cksum_buf, &ctx);
|
||||
} else {
|
||||
SHA256_Context ctx;
|
||||
|
||||
opt_SHA256_Init(&ctx);
|
||||
opt_SHA256_Update(&ctx, buf, bytes);
|
||||
opt_SHA256_Final(&ctx, cksum_buf);
|
||||
}
|
||||
} else if (cksum == CKSUM_SHA512) {
|
||||
SHA512_CTX ctx;
|
||||
|
||||
SHA512_Init(&ctx);
|
||||
SHA512_Update(&ctx, buf, bytes);
|
||||
SHA512_Final(cksum_buf, &ctx);
|
||||
} else {
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
init_sha256(void)
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
cksum_provider = PROVIDER_OPENSSL;
|
||||
#else
|
||||
#ifdef __x86_64__
|
||||
processor_info_t pc;
|
||||
|
||||
cksum_provider = PROVIDER_OPENSSL;
|
||||
cpuid_basic_identify(&pc);
|
||||
if (pc.proc_type == PROC_X64_INTEL || pc.proc_type == PROC_X64_AMD) {
|
||||
if (opt_Init_SHA(&pc) == 0) {
|
||||
cksum_provider = PROVIDER_X64_OPT;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Check is either the given checksum name or id is valid and
|
||||
* return it's properties.
|
||||
*/
|
||||
int
|
||||
get_checksum_props(char *name, int *cksum, int *cksum_bytes)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<sizeof (cksum_props); i++) {
|
||||
if ((name != NULL && strcmp(name, cksum_props[i].name) == 0) ||
|
||||
(*cksum != 0 && *cksum == cksum_props[i].cksum_id)) {
|
||||
*cksum = cksum_props[i].cksum_id;
|
||||
*cksum_bytes = cksum_props[i].bytes;
|
||||
if (cksum_props[i].init_func)
|
||||
cksum_props[i].init_func();
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Endian independent way of storing the checksum bytes. This is actually
|
||||
* storing in little endian format and a copy can be avoided in x86 land.
|
||||
* However unsightly ifdefs are avoided here since this is not so performance
|
||||
* critical.
|
||||
*/
|
||||
void
|
||||
serialize_checksum(uchar_t *checksum, uchar_t *buf, int cksum_bytes)
|
||||
{
|
||||
int i,j;
|
||||
|
||||
j = 0;
|
||||
for (i=cksum_bytes; i>0; i--) {
|
||||
buf[j] = checksum[i-1];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
deserialize_checksum(uchar_t *checksum, uchar_t *buf, int cksum_bytes)
|
||||
{
|
||||
int i,j;
|
||||
|
||||
j = 0;
|
||||
for (i=cksum_bytes; i>0; i--) {
|
||||
checksum[i-1] = buf[j];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
init_crypto(crypto_ctx_t *cctx, uchar_t *pwd, int pwd_len, int crypto_alg,
|
||||
uchar_t *salt, int saltlen, uint64_t nonce, int enc_dec)
|
||||
{
|
||||
if (crypto_alg == CRYPTO_ALG_AES) {
|
||||
aes_ctx_t *actx = malloc(sizeof (aes_ctx_t));
|
||||
|
||||
if (enc_dec) {
|
||||
/*
|
||||
* Encryption init.
|
||||
*/
|
||||
cctx->salt = malloc(32);
|
||||
salt = cctx->salt;
|
||||
cctx->saltlen = 32;
|
||||
if (RAND_status() != 1 || RAND_bytes(salt, 32) != 1) {
|
||||
if (geturandom_bytes(salt) != 0) {
|
||||
uchar_t sb[64];
|
||||
int b;
|
||||
struct timespec tp;
|
||||
|
||||
b = 0;
|
||||
/* No good random pool is populated/available. What to do ? */
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &tp) == -1) {
|
||||
time((time_t *)&sb[b]);
|
||||
b += 8;
|
||||
} else {
|
||||
uint64_t v;
|
||||
v = tp.tv_sec * 1000UL + tp.tv_nsec;
|
||||
*((uint64_t *)&sb[b]) = v;
|
||||
b += 8;
|
||||
}
|
||||
*((uint32_t *)&sb[b]) = rand();
|
||||
b += 4;
|
||||
*((uint32_t *)&sb[b]) = getpid();
|
||||
b += 4;
|
||||
compute_checksum(&sb[b], CKSUM_SHA256, sb, b);
|
||||
b = 8 + 4;
|
||||
*((uint32_t *)&sb[b]) = rand();
|
||||
compute_checksum(salt, CKSUM_SHA256, &sb[b], 32 + 4);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Zero nonce (arg #6) since it will be generated.
|
||||
*/
|
||||
if (aes_init(actx, salt, 32, pwd, pwd_len, 0, enc_dec) != 0) {
|
||||
fprintf(stderr, "Failed to initialize AES context\n");
|
||||
return (-1);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Decryption init.
|
||||
* Pass given nonce and salt.
|
||||
*/
|
||||
if (saltlen > MAX_SALTLEN) {
|
||||
fprintf(stderr, "Salt too long. Max allowed length is %d\n",
|
||||
MAX_SALTLEN);
|
||||
return (-1);
|
||||
}
|
||||
cctx->salt = malloc(saltlen);
|
||||
memcpy(cctx->salt, salt, saltlen);
|
||||
|
||||
if (aes_init(actx, cctx->salt, saltlen, pwd, pwd_len, nonce,
|
||||
enc_dec) != 0) {
|
||||
fprintf(stderr, "Failed to initialize AES context\n");
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
cctx->crypto_ctx = actx;
|
||||
cctx->crypto_alg = crypto_alg;
|
||||
cctx->enc_dec = enc_dec;
|
||||
} else {
|
||||
fprintf(stderr, "Unrecognized algorithm code: %d\n", crypto_alg);
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
crypto_buf(crypto_ctx_t *cctx, uchar_t *from, uchar_t *to, ssize_t bytes, uint64_t id)
|
||||
{
|
||||
if (cctx->crypto_alg == CRYPTO_ALG_AES) {
|
||||
if (cctx->enc_dec == ENCRYPT_FLAG) {
|
||||
return (aes_encrypt(cctx->crypto_ctx, from, to, bytes, id));
|
||||
} else {
|
||||
return (aes_decrypt(cctx->crypto_ctx, from, to, bytes, id));
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Unrecognized algorithm code: %d\n", cctx->crypto_alg);
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
crypto_nonce(crypto_ctx_t *cctx)
|
||||
get_total_ram()
|
||||
{
|
||||
return (aes_nonce(cctx->crypto_ctx));
|
||||
}
|
||||
|
||||
void
|
||||
cleanup_crypto(crypto_ctx_t *cctx)
|
||||
{
|
||||
aes_cleanup(cctx->crypto_ctx);
|
||||
memset(cctx->salt, 0, 32);
|
||||
free(cctx->salt);
|
||||
free(cctx);
|
||||
}
|
||||
|
||||
static int
|
||||
geturandom_bytes(uchar_t rbytes[32])
|
||||
{
|
||||
int fd;
|
||||
ssize_t lenread;
|
||||
uchar_t * buf = rbytes;
|
||||
size_t buflen = 32;
|
||||
|
||||
/* Open /dev/urandom. */
|
||||
if ((fd = open("/dev/urandom", O_RDONLY)) == -1)
|
||||
goto err0;
|
||||
|
||||
/* Read bytes until we have filled the buffer. */
|
||||
while (buflen > 0) {
|
||||
if ((lenread = read(fd, buf, buflen)) == -1)
|
||||
goto err1;
|
||||
|
||||
/* The random device should never EOF. */
|
||||
if (lenread == 0)
|
||||
goto err1;
|
||||
|
||||
/* We're partly done. */
|
||||
buf += lenread;
|
||||
buflen -= lenread;
|
||||
}
|
||||
|
||||
/* Close the device. */
|
||||
while (close(fd) == -1) {
|
||||
if (errno != EINTR)
|
||||
goto err0;
|
||||
}
|
||||
|
||||
/* Success! */
|
||||
return (0);
|
||||
err1:
|
||||
close(fd);
|
||||
err0:
|
||||
/* Failure! */
|
||||
return (4);
|
||||
}
|
||||
|
||||
int
|
||||
get_pw_string(char pw[MAX_PW_LEN], char *prompt)
|
||||
{
|
||||
int fd, len;
|
||||
FILE *input, *strm;
|
||||
struct termios oldt, newt;
|
||||
uchar_t pw1[MAX_PW_LEN], pw2[MAX_PW_LEN], *s;
|
||||
|
||||
// Try TTY first
|
||||
fd = open("/dev/tty", O_RDWR | O_NOCTTY);
|
||||
if (fd != -1) {
|
||||
input = fdopen(fd, "w+");
|
||||
strm = input;
|
||||
} else {
|
||||
// Fall back to stdin
|
||||
fd = STDIN_FILENO;
|
||||
input = stdin;
|
||||
strm = stderr;
|
||||
}
|
||||
tcgetattr(fd, &oldt);
|
||||
newt = oldt;
|
||||
newt.c_lflag &= ~ECHO;
|
||||
tcsetattr(fd, TCSANOW, &newt);
|
||||
|
||||
fprintf(stderr, "%s: ", prompt);
|
||||
fflush(stderr);
|
||||
s = fgets(pw1, MAX_PW_LEN, input);
|
||||
fputs("\n", stderr);
|
||||
|
||||
if (s == NULL) {
|
||||
tcsetattr(fd, TCSANOW, &oldt);
|
||||
fflush(strm);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s (once more): ", prompt);
|
||||
fflush(stderr);
|
||||
s = fgets(pw2, MAX_PW_LEN, input);
|
||||
tcsetattr(fd, TCSANOW, &oldt);
|
||||
fflush(strm);
|
||||
fputs("\n", stderr);
|
||||
|
||||
if (s == NULL) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (strcmp(pw1, pw2) != 0) {
|
||||
fprintf(stderr, "Passwords do not match!\n");
|
||||
memset(pw1, 0, MAX_PW_LEN);
|
||||
memset(pw2, 0, MAX_PW_LEN);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
len = strlen(pw1);
|
||||
pw1[len-1] = '\0';
|
||||
strcpy(pw, pw1);
|
||||
memset(pw1, 0, MAX_PW_LEN);
|
||||
memset(pw2, 0, MAX_PW_LEN);
|
||||
return (len);
|
||||
uint64_t phys_pages, page_size;
|
||||
|
||||
page_size = sysconf(_SC_PAGESIZE);
|
||||
phys_pages = sysconf(_SC_PHYS_PAGES);
|
||||
return (phys_pages * page_size);
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@ extern "C" {
|
|||
|
||||
#define DATA_TEXT 1
|
||||
#define DATA_BINARY 2
|
||||
#define MAX_PW_LEN 16
|
||||
|
||||
#if !defined(sun) && !defined(__sun)
|
||||
#define uchar_t u_char
|
||||
|
@ -102,22 +101,6 @@ typedef ssize_t bsize_t;
|
|||
#define DEBUG_STAT_EN(...)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Public checksum properties. CKSUM_MAX_BYTES must be updated if a
|
||||
* newer larger checksum is added to the list.
|
||||
*/
|
||||
typedef enum {
|
||||
CKSUM_CRC64 = 0x100,
|
||||
CKSUM_SKEIN256 = 0x200,
|
||||
CKSUM_SKEIN512 = 0x300,
|
||||
CKSUM_SHA256 = 0x400,
|
||||
CKSUM_SHA512 = 0x500
|
||||
} cksum_t;
|
||||
|
||||
#define CKSUM_MASK 0x700
|
||||
#define CKSUM_MAX_BYTES 64
|
||||
#define DEFAULT_CKSUM "SKEIN256"
|
||||
|
||||
typedef struct {
|
||||
uint32_t buf_extra;
|
||||
int compress_mt_capable;
|
||||
|
@ -147,19 +130,6 @@ typedef struct {
|
|||
proc_type_t proc_type;
|
||||
} processor_info_t;
|
||||
|
||||
#define ENCRYPT_FLAG 1
|
||||
#define DECRYPT_FLAG 0
|
||||
#define CRYPTO_ALG_AES 0x10
|
||||
#define MAX_SALTLEN 64
|
||||
|
||||
typedef struct {
|
||||
void *crypto_ctx;
|
||||
int crypto_alg;
|
||||
int enc_dec;
|
||||
uchar_t *salt;
|
||||
int saltlen;
|
||||
} crypto_ctx_t;
|
||||
|
||||
extern void err_exit(int show_errno, const char *format, ...);
|
||||
extern const char *get_execname(const char *);
|
||||
extern int parse_numeric(ssize_t *val, const char *str);
|
||||
|
@ -170,16 +140,7 @@ extern ssize_t Read_Adjusted(int fd, uchar_t *buf, size_t count,
|
|||
extern ssize_t Write(int fd, const void *buf, size_t count);
|
||||
extern void set_threadcounts(algo_props_t *props, int *nthreads, int nprocs,
|
||||
algo_threads_type_t typ);
|
||||
extern int compute_checksum(uchar_t *cksum_buf, int cksum, uchar_t *buf, ssize_t bytes);
|
||||
extern int get_checksum_props(char *name, int *cksum, int *cksum_bytes);
|
||||
extern void serialize_checksum(uchar_t *checksum, uchar_t *buf, int cksum_bytes);
|
||||
extern void deserialize_checksum(uchar_t *checksum, uchar_t *buf, int cksum_bytes);
|
||||
extern int init_crypto(crypto_ctx_t *cctx, uchar_t *pwd, int pwd_len, int crypto_alg,
|
||||
uchar_t *salt, int saltlen, uint64_t nonce, int enc_dec);
|
||||
extern int crypto_buf(crypto_ctx_t *cctx, uchar_t *from, uchar_t *to, ssize_t bytes, uint64_t id);
|
||||
extern uint64_t crypto_nonce(crypto_ctx_t *cctx);
|
||||
extern void cleanup_crypto(crypto_ctx_t *cctx);
|
||||
extern int get_pw_string(char pw[MAX_PW_LEN], char *prompt);
|
||||
extern uint64_t get_total_ram();
|
||||
|
||||
/* Pointer type for compress and decompress functions. */
|
||||
typedef int (*compress_func_ptr)(void *src, size_t srclen, void *dst,
|
||||
|
|
Loading…
Reference in a new issue