From: Eneas U de Queiroz Date: Sun, 19 Feb 2023 02:19:31 +0000 (-0300) Subject: uencrypt: split common and library-specific code X-Git-Tag: v23.05.0-rc1~773 X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=1781e7408a62de72193ddff5dbf5d9ff772a5847;p=openwrt%2Fopenwrt.git uencrypt: split common and library-specific code This splits the code in 4 files: - uencrypt.h - uencrypt.c - main program - uencrypt-openssl.c - OpenSSL/wolfSSL implementation - uencrypt-mbedtls - mbedTLS implementation Other changes, accounting for ~400 bytes increase in ipk size: - more error condition checking and reporting, - hide key and iv command line arguments Signed-off-by: Eneas U de Queiroz --- diff --git a/package/utils/uencrypt/Makefile b/package/utils/uencrypt/Makefile index 21d2d96f4d..70ca655b6e 100644 --- a/package/utils/uencrypt/Makefile +++ b/package/utils/uencrypt/Makefile @@ -4,7 +4,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=uencrypt -PKG_RELEASE:=4 +PKG_RELEASE:=5 PKG_LICENSE:=GPL-2.0-or-later PKG_MAINTAINER:=Eneas U de Queiroz @@ -19,6 +19,8 @@ else ifeq ($(BUILD_VARIANT),wolfssl) CMAKE_OPTIONS+=-DUSE_WOLFSSL=1 endif +TARGET_CFLAGS+=-Wall + define Package/uencrypt/default SECTION:=utils CATEGORY:=Base system diff --git a/package/utils/uencrypt/src/CMakeLists.txt b/package/utils/uencrypt/src/CMakeLists.txt index eadb2eadb3..5e09954f0a 100644 --- a/package/utils/uencrypt/src/CMakeLists.txt +++ b/package/utils/uencrypt/src/CMakeLists.txt @@ -13,9 +13,9 @@ if (USE_MBEDTLS) add_definitions(-DUSE_MBEDTLS) find_library(MBEDCRYPTO_LIBRARY mbedcrypto REQUIRED) set(CRYPTO_LIBRARIES ${MBEDCRYPTO_LIBRARY}) - add_executable(${PROJECT_NAME} ${PROJECT_NAME}-mbedtls.c) + set(CRYPTO_SOURCES ${PROJECT_NAME}-mbedtls.c) else() - add_executable(${PROJECT_NAME} ${PROJECT_NAME}-openssl.c) + set(CRYPTO_SOURCES ${PROJECT_NAME}-openssl.c) if (USE_WOLFSSL) add_definitions(-DUSE_WOLFSSL) find_library(WOLFSSL_LIBRARY wolfssl REQUIRED) @@ -25,6 +25,7 @@ else() set(CRYPTO_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) endif() endif() +add_executable(${PROJECT_NAME} ${PROJECT_NAME}.c ${PROJECT_NAME}.h ${CRYPTO_SOURCES}) target_link_libraries(${PROJECT_NAME} ${CRYPTO_LIBRARIES}) diff --git a/package/utils/uencrypt/src/uencrypt-mbedtls.c b/package/utils/uencrypt/src/uencrypt-mbedtls.c index 731beaad0f..34851261b7 100644 --- a/package/utils/uencrypt/src/uencrypt-mbedtls.c +++ b/package/utils/uencrypt/src/uencrypt-mbedtls.c @@ -3,210 +3,184 @@ */ #include -#include #include #include #include #include -#include +#include "uencrypt.h" -int do_crypt(FILE *infile, FILE *outfile, const mbedtls_cipher_info_t *cipher_info, - const unsigned char *key, const unsigned char *iv, int enc, int padding) +unsigned char *hexstr2buf(const char *str, long *len) { - mbedtls_cipher_context_t ctx; - unsigned char inbuf[1024], outbuf[1024 + MBEDTLS_MAX_BLOCK_LENGTH]; - size_t inlen, outlen; - int ret = 0; - int step; - - mbedtls_cipher_init(&ctx); - if ((ret = mbedtls_cipher_setup(&ctx, cipher_info))) { - fprintf(stderr, "Error: mbedtls_cipher_setup: %d\n", ret); - goto out; - } - step = iv ? 1024 : mbedtls_cipher_get_block_size(&ctx); - if ((ret = mbedtls_cipher_setkey(&ctx, key, (int) mbedtls_cipher_get_key_bitlen(&ctx), - enc ? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT))) { - fprintf(stderr, "Error: mbedtls_cipher_setkey: %d\n", ret); - goto out; - } - if (iv && (ret = mbedtls_cipher_set_iv(&ctx, iv, cipher_info->iv_size))) { - fprintf(stderr, "Error: mbedtls_cipher_set_iv: %d\n", ret); - goto out; - } + unsigned char *buf; + long inlen = strlen(str); - if (cipher_info->block_size > 1) { - if (cipher_info->mode == MBEDTLS_MODE_CBC) { - if ((ret = mbedtls_cipher_set_padding_mode(&ctx, - padding ? MBEDTLS_PADDING_PKCS7 - : MBEDTLS_PADDING_NONE))) { - fprintf(stderr, "Error: mbedtls_cipher_set_padding_mode: %d\n", ret); - goto out; - } - } else { - if (cipher_info->mode != MBEDTLS_MODE_CBC && padding) { - fprintf(stderr, "Error: mbedTLS only supports padding with CBC ciphers.\n"); - goto out; - } - } - } + *len = 0; + if (inlen % 2) + return NULL; - if ((ret = mbedtls_cipher_reset(&ctx))) { - fprintf(stderr, "Error: mbedtls_cipher_reset: %d\n", ret); - goto out; - } + *len = inlen >> 1; + buf = malloc(*len); + for (long x = 0; x < *len; x++) + sscanf(str + x * 2, "%2hhx", buf + x); + return buf; +} - for (;;) { - inlen = fread(inbuf, 1, step, infile); - if (inlen <= 0) - break; - if ((ret = mbedtls_cipher_update(&ctx, inbuf, inlen, outbuf, &outlen))) { - fprintf(stderr, "Error: mbedtls_cipher_update: %d\n", ret); - goto out; - } - fwrite(outbuf, 1, outlen, outfile); - } - if ((ret = mbedtls_cipher_finish(&ctx, outbuf, &outlen))) { - fprintf(stderr, "Error: mbedtls_cipher_finish: %d\n", ret); - goto out; - } - fwrite(outbuf, 1, outlen, outfile); +const cipher_t *get_default_cipher(void) +{ + return mbedtls_cipher_info_from_type (MBEDTLS_CIPHER_AES_128_CBC); +} -out: - mbedtls_cipher_free(&ctx); - return ret; +static char* upperstr(char *str) { + for (char *s = str; *s; s++) + *s = toupper((unsigned char) *s); + return str; } -static void check_enc_dec(const int enc) +const cipher_t *get_cipher_or_print_error(char *name) { - if (enc == -1) - return; - fprintf(stderr, "Error: both -d and -e were specified.\n"); - exit(EXIT_FAILURE); + const mbedtls_cipher_info_t *cipher; + + cipher = mbedtls_cipher_info_from_string(upperstr(name)); + if (cipher) + return cipher; + + fprintf(stderr, "Error: invalid cipher: %s.\n", name); + fprintf(stderr, "Supported ciphers: \n"); + for (const int *list = mbedtls_cipher_list(); *list; list++) { + cipher = mbedtls_cipher_info_from_type(*list); + if (!cipher) + continue; + fprintf(stderr, "\t%s\n", cipher->name); + } + return NULL; } -static void check_cipher(const mbedtls_cipher_info_t *cipher_info) +int get_cipher_ivsize(const cipher_t *cipher) { - const int *list; - - if (cipher_info == NULL) { - fprintf(stderr, "Error: invalid cipher: %s.\n", optarg); - fprintf(stderr, "Supported ciphers: \n"); - for (list = mbedtls_cipher_list(); *list; list++) { - cipher_info = mbedtls_cipher_info_from_type(*list); - if (!cipher_info) - continue; - fprintf(stderr, "\t%s\n", cipher_info->name); - } - exit(EXIT_FAILURE); - } + const mbedtls_cipher_info_t *c = cipher; + + return c->iv_size; } -static void show_usage(const char* name) +int get_cipher_keysize(const cipher_t *cipher) { - fprintf(stderr, "Usage: %s: [-d | -e] [-n] -k key [-i iv] [-c cipher]\n" - "-d = decrypt; -e = encrypt; -n = no padding\n", name); + const mbedtls_cipher_info_t *c = cipher; + + return c->key_bitlen >> 3; } -char *hexstr2buf(const char *str, size_t *len) +ctx_t *create_ctx(const cipher_t *cipher, const unsigned char *key, + const unsigned char *iv, int enc, int padding) { - char *buf; - size_t inlen = strlen(str); + mbedtls_cipher_context_t *ctx; + const mbedtls_cipher_info_t *cipher_info=cipher; + int ret; - *len = 0; - if (inlen % 2) + ctx = malloc(sizeof (mbedtls_cipher_context_t)); + if (!ctx) { + fprintf (stderr, "Error: create_ctx: out of memory.\n"); return NULL; + } - *len = inlen >> 1; - buf = malloc(*len); - for (size_t x = 0; x < *len; x++) - sscanf(str + x * 2, "%2hhx", buf + x); - return buf; -} + mbedtls_cipher_init(ctx); + ret = mbedtls_cipher_setup(ctx, cipher_info); + if (ret) { + fprintf(stderr, "Error: mbedtls_cipher_setup: %d\n", ret); + goto abort; + } + ret = mbedtls_cipher_setkey(ctx, key, + (int) mbedtls_cipher_get_key_bitlen(ctx), + enc ? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT); + if (ret) { + fprintf(stderr, "Error: mbedtls_cipher_setkey: %d\n", ret); + goto abort; + } + if (iv) { + ret = mbedtls_cipher_set_iv(ctx, iv, mbedtls_cipher_get_iv_size(ctx)); + if (ret) { + fprintf(stderr, "Error: mbedtls_cipher_set_iv: %d\n", ret); + goto abort; + } + } -static char* upperstr(char *str) { - for (char *s = str; *s; s++) - *s = toupper((unsigned char) *s); - return str; + if (cipher_info->mode == MBEDTLS_MODE_CBC) { + ret = mbedtls_cipher_set_padding_mode(ctx, padding ? + MBEDTLS_PADDING_PKCS7 : + MBEDTLS_PADDING_NONE); + if (ret) { + fprintf(stderr, "Error: mbedtls_cipher_set_padding_mode: %d\n", + ret); + goto abort; + } + } else { + if (cipher_info->block_size > 1 && padding) { + fprintf(stderr, + "Error: mbedTLS only allows padding with CBC ciphers.\n"); + goto abort; + } + } + + ret = mbedtls_cipher_reset(ctx); + if (ret) { + fprintf(stderr, "Error: mbedtls_cipher_reset: %d\n", ret); + goto abort; + } + return ctx; + +abort: + free_ctx(ctx); + return NULL; } -int main(int argc, char *argv[]) +int do_crypt(FILE *infile, FILE *outfile, ctx_t *ctx) { - int enc = -1; - unsigned char *iv = NULL; - unsigned char *key = NULL; - size_t keylen = 0, ivlen = 0; - int opt; - int padding = 1; - const mbedtls_cipher_info_t *cipher_info = - mbedtls_cipher_info_from_type (MBEDTLS_CIPHER_AES_128_CBC); + unsigned char inbuf[CRYPT_BUF_SIZE]; + unsigned char outbuf[CRYPT_BUF_SIZE + MBEDTLS_MAX_BLOCK_LENGTH]; + size_t inlen, outlen, step; int ret; - while ((opt = getopt(argc, argv, "c:dei:k:n")) != -1) { - switch (opt) { - case 'c': - cipher_info = mbedtls_cipher_info_from_string(upperstr(optarg)); - check_cipher(cipher_info); - break; - case 'd': - check_enc_dec(enc); - enc = 0; - break; - case 'e': - check_enc_dec(enc); - enc = 1; - break; - case 'i': - iv = (unsigned char *) hexstr2buf((const char *)optarg, &ivlen); - if (iv == NULL) { - fprintf(stderr, "Error setting IV to %s. The IV should be encoded in hex.\n", - optarg); - exit(EINVAL); - } - break; - case 'k': - key = (unsigned char *) hexstr2buf((const char *)optarg, &keylen); - if (key == NULL) { - fprintf(stderr, "Error setting key to %s. The key should be encoded in hex.\n", - optarg); - exit(EINVAL); - } - break; - case 'n': - padding = 0; - break; - default: - show_usage(argv[0]); - exit(EINVAL); + if (mbedtls_cipher_get_cipher_mode(ctx) == MBEDTLS_MODE_ECB) { + step = mbedtls_cipher_get_block_size(ctx); + if (step > CRYPT_BUF_SIZE) { + step = CRYPT_BUF_SIZE; } + } else { + step = CRYPT_BUF_SIZE; } - if (cipher_info->iv_size) { - if (iv == NULL) { - fprintf(stderr, "Error: iv not set.\n"); - show_usage(argv[0]); - exit(EXIT_FAILURE); + + for (;;) { + inlen = fread(inbuf, 1, step, infile); + if (inlen <= 0) + break; + ret = mbedtls_cipher_update(ctx, inbuf, inlen, outbuf, &outlen); + if (ret) { + fprintf(stderr, "Error: mbedtls_cipher_update: %d\n", ret); + return ret; } - if (ivlen != cipher_info->iv_size) { - fprintf(stderr, "Error: IV must be %d bytes; given IV is %zd bytes.\n", - cipher_info->iv_size, ivlen); - exit(EXIT_FAILURE); + ret = fwrite(outbuf, 1, outlen, outfile); + if (ret != outlen) { + fprintf(stderr, "Error: cipher_update short write.\n"); + return ret - outlen; } } - if (key == NULL) { - fprintf(stderr, "Error: key not set.\n"); - show_usage(argv[0]); - exit(EXIT_FAILURE); + ret = mbedtls_cipher_finish(ctx, outbuf, &outlen); + if (ret) { + fprintf(stderr, "Error: mbedtls_cipher_finish: %d\n", ret); + return ret; + } + ret = fwrite(outbuf, 1, outlen, outfile); + if (ret != outlen) { + fprintf(stderr, "Error: cipher_finish short write.\n"); + return ret - outlen; } - if (keylen != cipher_info->key_bitlen >> 3) { - fprintf(stderr, "Error: key must be %d bytes; given key is %zd bytes.\n", - cipher_info->key_bitlen >> 3, keylen); - exit(EXIT_FAILURE); + + return 0; +} + +void free_ctx(ctx_t *ctx) +{ + if (ctx) { + mbedtls_cipher_free(ctx); + free(ctx); } - ret = do_crypt(stdin, stdout, cipher_info, key, iv, !!enc, padding); - if (iv) - memset(iv, 0, ivlen); - memset(key, 0, keylen); - free(iv); - free(key); - return ret; } diff --git a/package/utils/uencrypt/src/uencrypt-openssl.c b/package/utils/uencrypt/src/uencrypt-openssl.c index ed09466443..d9182be2ba 100644 --- a/package/utils/uencrypt/src/uencrypt-openssl.c +++ b/package/utils/uencrypt/src/uencrypt-openssl.c @@ -2,56 +2,15 @@ * Copyright (C) 2022-2023 Eneas Ulir de Queiroz */ -#include #include #include #include #include +#include "uencrypt.h" -#ifdef USE_WOLFSSL -# include -# include -#else -# include -#endif - -int do_crypt(FILE *infile, FILE *outfile, const EVP_CIPHER *cipher, const unsigned char *key, - const unsigned char *iv, int enc, int padding) +const cipher_t *get_default_cipher(void) { - EVP_CIPHER_CTX *ctx; - unsigned char inbuf[1024], outbuf[1024 + EVP_MAX_BLOCK_LENGTH]; - int inlen, outlen; - - ctx = EVP_CIPHER_CTX_new(); - EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc); - EVP_CIPHER_CTX_set_padding(ctx, padding); - - for (;;) { - inlen = fread(inbuf, 1, 1024, infile); - if (inlen <= 0) - break; - if (!EVP_CipherUpdate(ctx, outbuf, &outlen, inbuf, inlen)) { - EVP_CIPHER_CTX_free(ctx); - return -1; - } - fwrite(outbuf, 1, outlen, outfile); - } - if (!EVP_CipherFinal_ex(ctx, outbuf, &outlen)) { - EVP_CIPHER_CTX_free(ctx); - return -1; - } - fwrite(outbuf, 1, outlen, outfile); - - EVP_CIPHER_CTX_free(ctx); - return 0; -} - -static void check_enc_dec(const int enc) -{ - if (enc == -1) - return; - fprintf(stderr, "Error: both -d and -e were specified.\n"); - exit(EXIT_FAILURE); + return EVP_aes_128_cbc(); } #ifndef USE_WOLFSSL @@ -60,100 +19,98 @@ static void print_ciphers(const OBJ_NAME *name,void *arg) { } #endif -static void check_cipher(const EVP_CIPHER *cipher) +const cipher_t *get_cipher_or_print_error(char *name) { - if (cipher == NULL) { - fprintf(stderr, "Error: invalid cipher: %s.\n", optarg); + const EVP_CIPHER *cipher; + + if ((cipher = EVP_get_cipherbyname(name))) + return cipher; + + fprintf(stderr, "Error: invalid cipher: %s.\n", name); #ifndef USE_WOLFSSL - fprintf(stderr, "Supported ciphers: \n"); - OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, print_ciphers, stderr); + fprintf(stderr, "Supported ciphers: \n"); + OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, print_ciphers, stderr); #endif - exit(EXIT_FAILURE); - } + return NULL; +} + +int get_cipher_ivsize(const cipher_t *cipher) +{ + return EVP_CIPHER_iv_length(cipher); } -static void show_usage(const char* name) +int get_cipher_keysize(const cipher_t *cipher) { - fprintf(stderr, "Usage: %s: [-d | -e] [-n] -k key [-i iv] [-c cipher]\n" - "-d = decrypt; -e = encrypt; -n = no padding\n", name); + return EVP_CIPHER_key_length(cipher); } -int main(int argc, char *argv[]) +ctx_t *create_ctx(const cipher_t *cipher, const unsigned char *key, + const unsigned char *iv, int enc, int padding) { - int enc = -1; - unsigned char *iv = NULL; - unsigned char *key = NULL; - long ivlen = 0, keylen = 0; - int cipher_ivlen, cipher_keylen; - int opt; - int padding = 1; - const EVP_CIPHER *cipher = EVP_aes_128_cbc(); + EVP_CIPHER_CTX *ctx; int ret; - while ((opt = getopt(argc, argv, "c:dei:k:n")) != -1) { - switch (opt) { - case 'c': - cipher = EVP_get_cipherbyname(optarg); - check_cipher(cipher); - break; - case 'd': - check_enc_dec(enc); - enc = 0; - break; - case 'e': - check_enc_dec(enc); - enc = 1; - break; - case 'i': - iv = OPENSSL_hexstr2buf((const char *)optarg, &ivlen); - if (iv == NULL) { - fprintf(stderr, "Error setting IV to %s. The IV should be encoded in hex.\n", - optarg); - exit(EINVAL); - } - break; - case 'k': - key = OPENSSL_hexstr2buf((const char *)optarg, &keylen); - if (key == NULL) { - fprintf(stderr, "Error setting key to %s. The key should be encoded in hex.\n", - optarg); - exit(EINVAL); - } - break; - case 'n': - padding = 0; - break; - default: - show_usage(argv[0]); - exit(EINVAL); - } + ctx = EVP_CIPHER_CTX_new(); + if (!ctx) { + fprintf (stderr, "Error: create_ctx: out of memory.\n"); + return NULL; } - if (key == NULL) { - fprintf(stderr, "Error: key not set.\n"); - show_usage(argv[0]); - exit(EXIT_FAILURE); + ret = EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc); + if (!ret) { + fprintf(stderr, "Error:EVP_CipherInit_ex: %d\n", ret); + goto abort; } - if ((cipher_keylen = EVP_CIPHER_key_length(cipher)) != keylen) { - fprintf(stderr, "Error: key must be %d bytes; given key is %ld bytes.\n", - cipher_keylen, keylen); - exit(EXIT_FAILURE); + ret = EVP_CIPHER_CTX_set_padding(ctx, padding); + if (!ret) { + fprintf(stderr, "Error:EVP_CIPHER_CTX_set_padding: %d\n", ret); + goto abort; } - if ((cipher_ivlen = EVP_CIPHER_iv_length(cipher))) { - if (iv == NULL) { - fprintf(stderr, "Error: IV not set.\n"); - show_usage(argv[0]); - exit(EXIT_FAILURE); + + return ctx; + +abort: + free_ctx(ctx); + return NULL; +} + + +int do_crypt(FILE *infile, FILE *outfile, ctx_t *ctx) +{ + unsigned char inbuf[CRYPT_BUF_SIZE]; + unsigned char outbuf[CRYPT_BUF_SIZE + EVP_MAX_BLOCK_LENGTH]; + int inlen, outlen; + int ret; + + for (;;) { + inlen = fread(inbuf, 1, CRYPT_BUF_SIZE, infile); + if (inlen <= 0) + break; + ret = EVP_CipherUpdate(ctx, outbuf, &outlen, inbuf, inlen); + if (!ret) { + fprintf(stderr, "Error: EVP_CipherUpdate: %d\n", ret); + return ret; } - if (cipher_ivlen != ivlen) { - fprintf(stderr, "Error: IV must be %d bytes; given IV is %ld bytes.\n", - cipher_ivlen, ivlen); - exit(EXIT_FAILURE); + ret = fwrite(outbuf, 1, outlen, outfile); + if (ret != outlen) { + fprintf(stderr, "Error: CipherUpdate short write.\n"); + return ret - outlen; } } - ret = do_crypt(stdin, stdout, cipher, key, iv, !!enc, padding); - if (ret) - fprintf(stderr, "Error during crypt operation.\n"); - OPENSSL_free(iv); - OPENSSL_free(key); - return ret; + ret = EVP_CipherFinal_ex(ctx, outbuf, &outlen); + if (!ret) { + fprintf(stderr, "Error: EVP_CipherFinal: %d\n", ret); + return ret; + } + ret = fwrite(outbuf, 1, outlen, outfile); + if (ret != outlen) { + fprintf(stderr, "Error: CipherFinal short write.\n"); + return ret - outlen; + } + + return 0; +} + +void free_ctx(ctx_t *ctx) +{ + EVP_CIPHER_CTX_free(ctx); } diff --git a/package/utils/uencrypt/src/uencrypt.c b/package/utils/uencrypt/src/uencrypt.c new file mode 100644 index 0000000000..36e17e220b --- /dev/null +++ b/package/utils/uencrypt/src/uencrypt.c @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright (C) 2023 Eneas Ulir de Queiroz + */ + +#include +#include +#include +#include +#include + +#include "uencrypt.h" + +static void check_enc_dec(const int enc) +{ + if (enc == -1) + return; + fprintf(stderr, "Error: both -d and -e were specified.\n"); + exit(EXIT_FAILURE); +} + +static void show_usage(const char* name) +{ + fprintf(stderr, "Usage: %s: [-d | -e] [-n] -k key [-i iv] [-c cipher]\n" + "-d = decrypt; -e = encrypt; -n = no padding\n", name); +} + +static void uencrypt_clear_free(void *ptr, size_t len) +{ + if (ptr) { + memset(ptr, 0, len); + free(ptr); + } +} + +int main(int argc, char *argv[]) +{ + int enc = -1; + unsigned char *iv = NULL; + unsigned char *key = NULL; + long keylen = 0, ivlen = 0; + int opt; + int padding = 1; + const cipher_t *cipher = get_default_cipher(); + ctx_t* ctx; + int ret = EXIT_FAILURE; + + while ((opt = getopt(argc, argv, "c:dei:k:n")) != -1) { + switch (opt) { + case 'c': + if (!(cipher = get_cipher_or_print_error(optarg))) + exit(EXIT_FAILURE); + break; + case 'd': + check_enc_dec(enc); + enc = 0; + break; + case 'e': + check_enc_dec(enc); + enc = 1; + break; + case 'i': + iv = hexstr2buf(optarg, &ivlen); + if (iv == NULL) { + fprintf(stderr, "Error setting IV to %s. The IV should be encoded in hex.\n", + optarg); + exit(EINVAL); + } + memset(optarg, '*', strlen(optarg)); + break; + case 'k': + key = hexstr2buf(optarg, &keylen); + if (key == NULL) { + fprintf(stderr, "Error setting key to %s. The key should be encoded in hex.\n", + optarg); + exit(EINVAL); + } + memset(optarg, '*', strlen(optarg)); + break; + case 'n': + padding = 0; + break; + default: + show_usage(argv[0]); + exit(EINVAL); + } + } + if (ivlen != get_cipher_ivsize(cipher)) { + fprintf(stderr, "Error: IV must be %d bytes; given IV is %zd bytes.\n", + get_cipher_ivsize(cipher), ivlen); + exit(EXIT_FAILURE); + } + if (keylen != get_cipher_keysize(cipher)) { + fprintf(stderr, "Error: key must be %d bytes; given key is %zd bytes.\n", + get_cipher_keysize(cipher), keylen); + exit(EXIT_FAILURE); + } + ctx = create_ctx(cipher, key, iv, !!enc, padding); + if (ctx) { + ret = do_crypt(stdin, stdout, ctx); + free_ctx(ctx); + } + uencrypt_clear_free(iv, ivlen); + uencrypt_clear_free(key, keylen); + return ret; +} diff --git a/package/utils/uencrypt/src/uencrypt.h b/package/utils/uencrypt/src/uencrypt.h new file mode 100644 index 0000000000..a4fe1f3376 --- /dev/null +++ b/package/utils/uencrypt/src/uencrypt.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright (C) 2022-2023 Eneas Ulir de Queiroz + */ + +#include + +#define CRYPT_BUF_SIZE 1024 + +#ifdef USE_MBEDTLS +# include + +# if defined(MBEDTLS_MAX_BLOCK_LENGTH) \ + && MBEDTLS_MAX_BLOCK_LENGTH > CRYPT_BUF_SIZE +# undef CRYPT_BUF_SIZE +# define CRYPT_BUF_SIZE MAX_BLOCK_LENGTH +# endif + +unsigned char *hexstr2buf(const char* str, long *len); + +#else /* USE_MBEDTLS */ +# ifdef USE_WOLFSSL +# include +# include +# else +# include +# endif + +# if defined(EVP_MAX_BLOCK_LENGTH) \ + && EVP_MAX_BLOCK_LENGTH > CRYPT_BUF_SIZE +# undef CRYPT_BUF_SIZE +# define CRYPT_BUF_SIZE EVP_MAX_BLOCK_LENGTH +# endif + +# define hexstr2buf OPENSSL_hexstr2buf + +#endif /* USE_MBEDTLS */ + +typedef void cipher_t; +typedef void ctx_t; + +const cipher_t *get_default_cipher(void); +const cipher_t *get_cipher_or_print_error(char *name); +int get_cipher_ivsize(const cipher_t *cipher); +int get_cipher_keysize(const cipher_t *cipher); + +ctx_t *create_ctx(const cipher_t *cipher, const unsigned char *key, + const unsigned char *iv, int enc, int padding); +int do_crypt(FILE *infile, FILE *outfile, ctx_t *ctx); +void free_ctx(ctx_t *ctx);