summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/libgcry.c47
-rw-r--r--runtime/libgcry.h40
-rw-r--r--runtime/lmcry_gcry.c38
-rw-r--r--runtime/rsyslog.h2
-rw-r--r--tools/rscryutil.c67
-rw-r--r--tools/rscryutil.rst43
6 files changed, 188 insertions, 49 deletions
diff --git a/runtime/libgcry.c b/runtime/libgcry.c
index 5fd55360..ef94e8ac 100644
--- a/runtime/libgcry.c
+++ b/runtime/libgcry.c
@@ -49,8 +49,6 @@
#include "rsyslog.h"
#include "libgcry.h"
-#define GCRY_CIPHER GCRY_CIPHER_3DES // TODO: make configurable
-
static rsRetVal
eiWriteRec(gcryfile gf, char *recHdr, size_t lenRecHdr, char *buf, size_t lenBuf)
@@ -206,6 +204,8 @@ gcryCtxNew(void)
{
gcryctx ctx;
ctx = calloc(1, sizeof(struct gcryctx_s));
+ ctx->algo = GCRY_CIPHER_AES128;
+ ctx->mode = GCRY_CIPHER_MODE_CBC;
return ctx;
}
@@ -270,9 +270,10 @@ done: return;
int
rsgcrySetKey(gcryctx ctx, unsigned char *key, uint16_t keyLen)
{
- uint16_t reqKeyLen = gcry_cipher_get_algo_keylen(GCRY_CIPHER);
+ uint16_t reqKeyLen;
int r;
+ reqKeyLen = gcry_cipher_get_algo_keylen(ctx->algo);
if(keyLen != reqKeyLen) {
r = reqKeyLen;
goto done;
@@ -284,6 +285,36 @@ rsgcrySetKey(gcryctx ctx, unsigned char *key, uint16_t keyLen)
done: return r;
}
+rsRetVal
+rsgcrySetMode(gcryctx ctx, uchar *modename)
+{
+ int mode;
+ DEFiRet;
+
+ mode = rsgcryModename2Mode((char *)modename);
+ if(mode == GCRY_CIPHER_MODE_NONE) {
+ ABORT_FINALIZE(RS_RET_CRY_INVLD_MODE);
+ }
+ ctx->mode = mode;
+finalize_it:
+ RETiRet;
+}
+
+rsRetVal
+rsgcrySetAlgo(gcryctx ctx, uchar *algoname)
+{
+ int algo;
+ DEFiRet;
+
+ algo = rsgcryAlgoname2Algo((char *)algoname);
+ if(algo == GCRY_CIPHER_NONE) {
+ ABORT_FINALIZE(RS_RET_CRY_INVLD_ALGO);
+ }
+ ctx->algo = algo;
+finalize_it:
+ RETiRet;
+}
+
/* As of some Linux and security expert I spoke to, /dev/urandom
* provides very strong random numbers, even if it runs out of
* entropy. As far as he knew, this is save for all applications
@@ -310,7 +341,7 @@ seedIV(gcryfile gf, uchar **iv)
}
rsRetVal
-rsgcryInitCrypt(gcryctx ctx, gcryfile *pgf, int gcry_mode, uchar *fname)
+rsgcryInitCrypt(gcryctx ctx, gcryfile *pgf, uchar *fname)
{
gcry_error_t gcryError;
gcryfile gf = NULL;
@@ -319,13 +350,9 @@ rsgcryInitCrypt(gcryctx ctx, gcryfile *pgf, int gcry_mode, uchar *fname)
CHKiRet(gcryfileConstruct(ctx, &gf, fname));
- gf->blkLength = gcry_cipher_get_algo_blklen(GCRY_CIPHER);
+ gf->blkLength = gcry_cipher_get_algo_blklen(ctx->algo);
- gcryError = gcry_cipher_open(
- &gf->chd, // gcry_cipher_hd_t *
- GCRY_CIPHER, // int
- gcry_mode, // int
- 0); // unsigned int
+ gcryError = gcry_cipher_open(&gf->chd, ctx->algo, ctx->mode, 0);
if (gcryError) {
dbgprintf("gcry_cipher_open failed: %s/%s\n",
gcry_strsource(gcryError),
diff --git a/runtime/libgcry.h b/runtime/libgcry.h
index 857d2352..d699124d 100644
--- a/runtime/libgcry.h
+++ b/runtime/libgcry.h
@@ -26,6 +26,8 @@
struct gcryctx_s {
uchar *key;
size_t keyLen;
+ int algo;
+ int mode;
};
typedef struct gcryctx_s *gcryctx;
typedef struct gcryfile_s *gcryfile;
@@ -42,10 +44,12 @@ struct gcryfile_s {
int rsgcryInit(void);
void rsgcryExit(void);
int rsgcrySetKey(gcryctx ctx, unsigned char *key, uint16_t keyLen);
+rsRetVal rsgcrySetMode(gcryctx ctx, uchar *algoname);
+rsRetVal rsgcrySetAlgo(gcryctx ctx, uchar *modename);
gcryctx gcryCtxNew(void);
void rsgcryCtxDel(gcryctx ctx);
int gcryfileDestruct(gcryfile gf, off64_t offsLogfile);
-rsRetVal rsgcryInitCrypt(gcryctx ctx, gcryfile *pgf, int gcry_mode, uchar *fname);
+rsRetVal rsgcryInitCrypt(gcryctx ctx, gcryfile *pgf, uchar *fname);
int rsgcryEncrypt(gcryfile pF, uchar *buf, size_t *len);
/* error states */
@@ -57,4 +61,38 @@ int rsgcryEncrypt(gcryfile pF, uchar *buf, size_t *len);
#define RSGCRY_FILETYPE_NAME "rsyslog-enrcyption-info"
#define ENCINFO_SUFFIX ".encinfo"
+static inline int
+rsgcryAlgoname2Algo(char *algoname) {
+ if(!strcmp((char*)algoname, "3DES")) return GCRY_CIPHER_3DES;
+ if(!strcmp((char*)algoname, "CAST5")) return GCRY_CIPHER_CAST5;
+ if(!strcmp((char*)algoname, "BLOWFISH")) return GCRY_CIPHER_BLOWFISH;
+ if(!strcmp((char*)algoname, "AES128")) return GCRY_CIPHER_AES128;
+ if(!strcmp((char*)algoname, "AES192")) return GCRY_CIPHER_AES192;
+ if(!strcmp((char*)algoname, "AES256")) return GCRY_CIPHER_AES256;
+ if(!strcmp((char*)algoname, "TWOFISH")) return GCRY_CIPHER_TWOFISH;
+ if(!strcmp((char*)algoname, "TWOFISH128")) return GCRY_CIPHER_TWOFISH128;
+ if(!strcmp((char*)algoname, "ARCFOUR")) return GCRY_CIPHER_ARCFOUR;
+ if(!strcmp((char*)algoname, "DES")) return GCRY_CIPHER_DES;
+ if(!strcmp((char*)algoname, "SERPENT128")) return GCRY_CIPHER_SERPENT128;
+ if(!strcmp((char*)algoname, "SERPENT192")) return GCRY_CIPHER_SERPENT192;
+ if(!strcmp((char*)algoname, "SERPENT256")) return GCRY_CIPHER_SERPENT256;
+ if(!strcmp((char*)algoname, "RFC2268_40")) return GCRY_CIPHER_RFC2268_40;
+ if(!strcmp((char*)algoname, "SEED")) return GCRY_CIPHER_SEED;
+ if(!strcmp((char*)algoname, "CAMELLIA128")) return GCRY_CIPHER_CAMELLIA128;
+ if(!strcmp((char*)algoname, "CAMELLIA192")) return GCRY_CIPHER_CAMELLIA192;
+ if(!strcmp((char*)algoname, "CAMELLIA256")) return GCRY_CIPHER_CAMELLIA256;
+ return GCRY_CIPHER_NONE;
+}
+
+static inline int
+rsgcryModename2Mode(char *modename) {
+ if(!strcmp((char*)modename, "ECB")) return GCRY_CIPHER_MODE_ECB;
+ if(!strcmp((char*)modename, "CFB")) return GCRY_CIPHER_MODE_CFB;
+ if(!strcmp((char*)modename, "CBC")) return GCRY_CIPHER_MODE_CBC;
+ if(!strcmp((char*)modename, "STREAM")) return GCRY_CIPHER_MODE_STREAM;
+ if(!strcmp((char*)modename, "OFB")) return GCRY_CIPHER_MODE_OFB;
+ if(!strcmp((char*)modename, "CTR")) return GCRY_CIPHER_MODE_CTR;
+ if(!strcmp((char*)modename, "AESWRAP")) return GCRY_CIPHER_MODE_AESWRAP;
+ return GCRY_CIPHER_MODE_NONE;
+}
#endif /* #ifndef INCLUDED_LIBGCRY_H */
diff --git a/runtime/lmcry_gcry.c b/runtime/lmcry_gcry.c
index 881d047d..cc65051f 100644
--- a/runtime/lmcry_gcry.c
+++ b/runtime/lmcry_gcry.c
@@ -89,8 +89,9 @@ SetCnfParam(void *pT, struct nvlst *lst)
{
lmcry_gcry_t *pThis = (lmcry_gcry_t*) pT;
int i, r;
- uchar *cstr;
uchar *key = NULL;
+ uchar *algo = NULL;
+ uchar *mode = NULL;
struct cnfparamvals *pvals;
DEFiRet;
@@ -105,23 +106,30 @@ SetCnfParam(void *pT, struct nvlst *lst)
continue;
if(!strcmp(pblk.descr[i].name, "cry.key")) {
key = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
-#if 0
- } else if(!strcmp(pblk.descr[i].name, "sig.timestampservice")) {
- cstr = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
- gcrySetTimestamper(pThis->ctx, (char*) cstr);
- free(cstr);
- } else if(!strcmp(pblk.descr[i].name, "sig.block.sizelimit")) {
- gcrySetBlockSizeLimit(pThis->ctx, pvals[i].val.d.n);
- } else if(!strcmp(pblk.descr[i].name, "sig.keeprecordhashes")) {
- gcrySetKeepRecordHashes(pThis->ctx, pvals[i].val.d.n);
- } else if(!strcmp(pblk.descr[i].name, "sig.keeptreehashes")) {
- gcrySetKeepTreeHashes(pThis->ctx, pvals[i].val.d.n);
+ } else if(!strcmp(pblk.descr[i].name, "cry.mode")) {
+ mode = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(pblk.descr[i].name, "cry.algo")) {
+ algo = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
} else {
DBGPRINTF("lmcry_gcry: program error, non-handled "
"param '%s'\n", pblk.descr[i].name);
-#endif
}
}
+ if(algo != NULL) {
+ iRet = rsgcrySetAlgo(pThis->ctx, algo);
+ if(iRet != RS_RET_OK) {
+ errmsg.LogError(0, iRet, "cry.algo '%s' is not know/supported", algo);
+ FINALIZE;
+ }
+ }
+ if(mode != NULL) {
+ iRet = rsgcrySetMode(pThis->ctx, mode);
+ if(iRet != RS_RET_OK) {
+ errmsg.LogError(0, iRet, "cry.mode '%s' is not know/supported", mode);
+ FINALIZE;
+ }
+ }
+ /* note: key must be set AFTER algo/mode is set (as it depends on them) */
if(key != NULL) {
errmsg.LogError(0, RS_RET_ERR, "Note: specifying an actual key directly from the "
"config file is highly insecure - DO NOT USE FOR PRODUCTION");
@@ -138,6 +146,8 @@ SetCnfParam(void *pT, struct nvlst *lst)
memset(key, 0, strlen((char*)key));
free(key);
}
+ free(algo);
+ free(mode);
finalize_it:
RETiRet;
}
@@ -151,7 +161,7 @@ OnFileOpen(void *pT, uchar *fn, void *pGF)
DEFiRet;
dbgprintf("DDDD: cry: onFileOpen: %s\n", fn);
- CHKiRet(rsgcryInitCrypt(pThis->ctx, pgf, GCRY_CIPHER_MODE_CBC, fn));
+ CHKiRet(rsgcryInitCrypt(pThis->ctx, pgf, fn));
finalize_it:
/* TODO: enable this error message (need to cleanup loop first ;))
errmsg.LogError(0, iRet, "Encryption Provider"
diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h
index ab57eace..4cdd1c1e 100644
--- a/runtime/rsyslog.h
+++ b/runtime/rsyslog.h
@@ -408,6 +408,8 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth
RS_RET_EI_NO_EXISTS = -2323,/**< .encinfo file does not exist (status, not necessarily error!)*/
RS_RET_EI_WR_ERR = -2324,/**< error writing an .encinfo file */
RS_RET_EI_INVLD_FILE = -2325,/**< header indicates the file is no .encinfo file */
+ RS_RET_CRY_INVLD_ALGO = -2326,/**< user specified invalid (unkonwn) crypto algorithm */
+ RS_RET_CRY_INVLD_MODE = -2327,/**< user specified invalid (unkonwn) crypto mode */
/* RainerScript error messages (range 1000.. 1999) */
RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */
diff --git a/tools/rscryutil.c b/tools/rscryutil.c
index e57eb625..e1e900a7 100644
--- a/tools/rscryutil.c
+++ b/tools/rscryutil.c
@@ -40,6 +40,9 @@ static int verbose = 0;
static gcry_cipher_hd_t gcry_chd;
static size_t blkLength;
+static char *cry_key = NULL;
+static int cry_algo = GCRY_CIPHER_AES128;
+static int cry_mode = GCRY_CIPHER_MODE_CBC;
/* rectype/value must be EIF_MAX_*_LEN+1 long!
* returns 0 on success or something else on error/EOF
@@ -151,14 +154,13 @@ done: return r;
}
static int
-initCrypt(FILE *eifp, int gcry_mode, char *key)
+initCrypt(FILE *eifp)
{
- #define GCRY_CIPHER GCRY_CIPHER_3DES // TODO: make configurable
int r = 0;
- gcry_error_t gcryError;
+ gcry_error_t gcryError;
char iv[4096];
- blkLength = gcry_cipher_get_algo_blklen(GCRY_CIPHER);
+ blkLength = gcry_cipher_get_algo_blklen(cry_algo);
if(blkLength > sizeof(iv)) {
fprintf(stderr, "internal error[%s:%d]: block length %d too large for "
"iv buffer\n", __FILE__, __LINE__, blkLength);
@@ -166,15 +168,15 @@ initCrypt(FILE *eifp, int gcry_mode, char *key)
}
if((r = eiGetIV(eifp, iv, blkLength)) != 0) goto done;
- size_t keyLength = gcry_cipher_get_algo_keylen(GCRY_CIPHER);
- if(strlen(key) != keyLength) {
+ size_t keyLength = gcry_cipher_get_algo_keylen(cry_algo);
+ if(strlen(cry_key) != keyLength) {
fprintf(stderr, "invalid key length; key is %u characters, but "
- "exactly %u characters are required\n", strlen(key),
+ "exactly %u characters are required\n", strlen(cry_key),
keyLength);
r = 1; goto done;
}
- gcryError = gcry_cipher_open(&gcry_chd, GCRY_CIPHER, gcry_mode, 0);
+ gcryError = gcry_cipher_open(&gcry_chd, cry_algo, cry_mode, 0);
if (gcryError) {
printf("gcry_cipher_open failed: %s/%s\n",
gcry_strsource(gcryError),
@@ -182,7 +184,7 @@ initCrypt(FILE *eifp, int gcry_mode, char *key)
r = 1; goto done;
}
- gcryError = gcry_cipher_setkey(gcry_chd, key, keyLength);
+ gcryError = gcry_cipher_setkey(gcry_chd, cry_key, keyLength);
if (gcryError) {
printf("gcry_cipher_setkey failed: %s/%s\n",
gcry_strsource(gcryError),
@@ -225,10 +227,9 @@ done: return;
static void
decryptBlock(FILE *fpin, FILE *fpout, off64_t blkEnd, off64_t *pCurrOffs)
{
- gcry_error_t gcryError;
+ gcry_error_t gcryError;
size_t nRead, nWritten;
size_t toRead;
- size_t nPad;
size_t leftTillBlkEnd;
char buf[64*1024];
@@ -240,7 +241,6 @@ decryptBlock(FILE *fpin, FILE *fpout, off64_t blkEnd, off64_t *pCurrOffs)
if(nRead == 0)
break;
leftTillBlkEnd -= nRead, *pCurrOffs += nRead;
- nPad = (blkLength - nRead % blkLength) % blkLength;
gcryError = gcry_cipher_decrypt(
gcry_chd, // gcry_cipher_hd_t
buf, // void *
@@ -248,7 +248,7 @@ decryptBlock(FILE *fpin, FILE *fpout, off64_t blkEnd, off64_t *pCurrOffs)
NULL, // const void *
0); // size_t
if (gcryError) {
- fprintf(stderr, "gcry_cipher_encrypt failed: %s/%s\n",
+ fprintf(stderr, "gcry_cipher_decrypt failed: %s/%s\n",
gcry_strsource(gcryError),
gcry_strerror(gcryError));
return;
@@ -264,7 +264,7 @@ decryptBlock(FILE *fpin, FILE *fpout, off64_t blkEnd, off64_t *pCurrOffs)
static int
-doDecrypt(FILE *logfp, FILE *eifp, FILE *outfp, char *key)
+doDecrypt(FILE *logfp, FILE *eifp, FILE *outfp)
{
off64_t blkEnd;
off64_t currOffs = 0;
@@ -272,7 +272,7 @@ doDecrypt(FILE *logfp, FILE *eifp, FILE *outfp, char *key)
while(1) {
/* process block */
- if(initCrypt(eifp, GCRY_CIPHER_MODE_CBC, key) != 0)
+ if(initCrypt(eifp) != 0)
goto done;
if((r = eiGetEND(eifp, &blkEnd)) != 0) goto done;
decryptBlock(logfp, outfp, blkEnd, &currOffs);
@@ -283,7 +283,7 @@ done: return r;
}
static void
-decrypt(char *name, char *key)
+decrypt(char *name)
{
FILE *logfp = NULL, *eifp = NULL;
int r = 0;
@@ -307,7 +307,7 @@ decrypt(char *name, char *key)
goto err;
}
- doDecrypt(logfp, eifp, stdout, key);
+ doDecrypt(logfp, eifp, stdout);
fclose(logfp); logfp = NULL;
fclose(eifp); eifp = NULL;
@@ -326,6 +326,8 @@ static struct option long_options[] =
{"version", no_argument, NULL, 'V'},
{"decrypt", no_argument, NULL, 'd'},
{"key", required_argument, NULL, 'k'},
+ {"algo", required_argument, NULL, 'a'},
+ {"mode", required_argument, NULL, 'm'},
{NULL, 0, NULL, 0}
};
@@ -334,10 +336,10 @@ main(int argc, char *argv[])
{
int i;
int opt;
- char *key = "";
+ int temp;
while(1) {
- opt = getopt_long(argc, argv, "dk:vV", long_options, NULL);
+ opt = getopt_long(argc, argv, "a:dk:m:vV", long_options, NULL);
if(opt == -1)
break;
switch(opt) {
@@ -348,7 +350,25 @@ main(int argc, char *argv[])
fprintf(stderr, "WARNING: specifying the actual key "
"via the command line is highly insecure\n"
"Do NOT use this for PRODUCTION use.\n");
- key = optarg;
+ cry_key = optarg;
+ break;
+ case 'a':
+ temp = rsgcryAlgoname2Algo(optarg);
+ if(temp == GCRY_CIPHER_NONE) {
+ fprintf(stderr, "ERROR: algorithm \"%s\" is not "
+ "kown/supported\n", optarg);
+ exit(1);
+ }
+ cry_algo = temp;
+ break;
+ case 'm':
+ temp = rsgcryModename2Mode(optarg);
+ if(temp == GCRY_CIPHER_MODE_NONE) {
+ fprintf(stderr, "ERROR: cipher mode \"%s\" is not "
+ "kown/supported\n", optarg);
+ exit(1);
+ }
+ cry_mode = temp;
break;
case 'v':
verbose = 1;
@@ -365,13 +385,12 @@ main(int argc, char *argv[])
}
if(optind == argc)
- decrypt("-", key);
+ decrypt("-");
else {
for(i = optind ; i < argc ; ++i)
- decrypt(argv[i], key); /* currently only mode ;) */
+ decrypt(argv[i]); /* currently only mode ;) */
}
- memset(key, 0, strlen(key)); /* zero-out key store */
+ memset(cry_key, 0, strlen(cry_key)); /* zero-out key store */
return 0;
}
- //char *aesSymKey = "123456789012345678901234"; // TODO: TEST ONLY
diff --git a/tools/rscryutil.rst b/tools/rscryutil.rst
index 7e3ab5b4..3cc54f57 100644
--- a/tools/rscryutil.rst
+++ b/tools/rscryutil.rst
@@ -40,6 +40,13 @@ OPTIONS
is highly insecure. However, it can be useful for intial testing
steps. This option may be removed in the future.
+-a, --algo <algo>
+ Sets the encryption algorightm (cipher) to be used. See below
+ for supported algorithms. The default is "AES128".
+
+-m, --mode <mode>
+ Sets the ciphermode to be used. See below for supported modes.
+ The default is "CBC".
OPERATION MODES
===============
@@ -62,6 +69,42 @@ The command returns an exit code of 0 if everything went fine, and some
other code in case of failures.
+SUPPORTED ALGORITHMS
+====================
+
+We basically support what libgcrypt supports. This is:
+ 3DES
+ CAST5
+ BLOWFISH
+ AES128
+ AES192
+ AES256
+ TWOFISH
+ TWOFISH128
+ ARCFOUR
+ DES
+ SERPENT128
+ SERPENT192
+ SERPENT256
+ RFC2268_40
+ SEED
+ CAMELLIA128
+ CAMELLIA192
+ CAMELLIA256
+
+
+SUPPORTED CIPHER MODES
+======================
+
+We basically support what libgcrypt supports. This is:
+ ECB
+ CFB
+ CBC
+ STREAM
+ OFB
+ CTR
+ AESWRAP
+
EXAMPLES
========