diff options
Diffstat (limited to 'package/utils/uencrypt/src')
| -rw-r--r-- | package/utils/uencrypt/src/CMakeLists.txt | 32 | ||||
| -rw-r--r-- | package/utils/uencrypt/src/uencrypt-mbedtls.c | 186 | ||||
| -rw-r--r-- | package/utils/uencrypt/src/uencrypt-openssl.c | 116 | ||||
| -rw-r--r-- | package/utils/uencrypt/src/uencrypt.c | 105 | ||||
| -rw-r--r-- | package/utils/uencrypt/src/uencrypt.h | 49 |
5 files changed, 488 insertions, 0 deletions
diff --git a/package/utils/uencrypt/src/CMakeLists.txt b/package/utils/uencrypt/src/CMakeLists.txt new file mode 100644 index 00000000000..5e09954f0a2 --- /dev/null +++ b/package/utils/uencrypt/src/CMakeLists.txt @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2022 Eneas Ulir de Queiroz + +cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR) +project(uencrypt LANGUAGES C) + +option(USE_WOLFSSL "Use WolfSSL as crypto provider" OFF) +option(USE_MBEDTLS "Use mbedTLS as crypto provider" OFF) +if (USE_MBEDTLS) + if (USE_WOLFSSL) + message(WARNING "USE_MBEDTLS and USE_WOLFSSL are both set. Building with USE_MBEDTLS.") + endif() + add_definitions(-DUSE_MBEDTLS) + find_library(MBEDCRYPTO_LIBRARY mbedcrypto REQUIRED) + set(CRYPTO_LIBRARIES ${MBEDCRYPTO_LIBRARY}) + set(CRYPTO_SOURCES ${PROJECT_NAME}-mbedtls.c) +else() + set(CRYPTO_SOURCES ${PROJECT_NAME}-openssl.c) + if (USE_WOLFSSL) + add_definitions(-DUSE_WOLFSSL) + find_library(WOLFSSL_LIBRARY wolfssl REQUIRED) + set(CRYPTO_LIBRARIES ${WOLFSSL_LIBRARY}) + else() + find_package(OpenSSL REQUIRED) + 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}) + +install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin) diff --git a/package/utils/uencrypt/src/uencrypt-mbedtls.c b/package/utils/uencrypt/src/uencrypt-mbedtls.c new file mode 100644 index 00000000000..34851261b79 --- /dev/null +++ b/package/utils/uencrypt/src/uencrypt-mbedtls.c @@ -0,0 +1,186 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright (C) 2023 Eneas Ulir de Queiroz + */ + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "uencrypt.h" + +unsigned char *hexstr2buf(const char *str, long *len) +{ + unsigned char *buf; + long inlen = strlen(str); + + *len = 0; + if (inlen % 2) + return NULL; + + *len = inlen >> 1; + buf = malloc(*len); + for (long x = 0; x < *len; x++) + sscanf(str + x * 2, "%2hhx", buf + x); + return buf; +} + +const cipher_t *get_default_cipher(void) +{ + return mbedtls_cipher_info_from_type (MBEDTLS_CIPHER_AES_128_CBC); +} + +static char* upperstr(char *str) { + for (char *s = str; *s; s++) + *s = toupper((unsigned char) *s); + return str; +} + +const cipher_t *get_cipher_or_print_error(char *name) +{ + 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; +} + +int get_cipher_ivsize(const cipher_t *cipher) +{ + const mbedtls_cipher_info_t *c = cipher; + + return c->iv_size; +} + +int get_cipher_keysize(const cipher_t *cipher) +{ + const mbedtls_cipher_info_t *c = cipher; + + return c->key_bitlen >> 3; +} + +ctx_t *create_ctx(const cipher_t *cipher, const unsigned char *key, + const unsigned char *iv, int enc, int padding) +{ + mbedtls_cipher_context_t *ctx; + const mbedtls_cipher_info_t *cipher_info=cipher; + int ret; + + ctx = malloc(sizeof (mbedtls_cipher_context_t)); + if (!ctx) { + fprintf (stderr, "Error: create_ctx: out of memory.\n"); + return NULL; + } + + 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; + } + } + + 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 do_crypt(FILE *infile, FILE *outfile, ctx_t *ctx) +{ + unsigned char inbuf[CRYPT_BUF_SIZE]; + unsigned char outbuf[CRYPT_BUF_SIZE + MBEDTLS_MAX_BLOCK_LENGTH]; + size_t inlen, outlen, step; + int ret; + + 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; + } + + 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; + } + ret = fwrite(outbuf, 1, outlen, outfile); + if (ret != outlen) { + fprintf(stderr, "Error: cipher_update short write.\n"); + return ret - outlen; + } + } + 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; + } + + return 0; +} + +void free_ctx(ctx_t *ctx) +{ + if (ctx) { + mbedtls_cipher_free(ctx); + free(ctx); + } +} diff --git a/package/utils/uencrypt/src/uencrypt-openssl.c b/package/utils/uencrypt/src/uencrypt-openssl.c new file mode 100644 index 00000000000..d9182be2bae --- /dev/null +++ b/package/utils/uencrypt/src/uencrypt-openssl.c @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright (C) 2022-2023 Eneas Ulir de Queiroz + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "uencrypt.h" + +const cipher_t *get_default_cipher(void) +{ + return EVP_aes_128_cbc(); +} + +#ifndef USE_WOLFSSL +static void print_ciphers(const OBJ_NAME *name,void *arg) { + fprintf(arg, "\t%s\n", name->name); +} +#endif + +const cipher_t *get_cipher_or_print_error(char *name) +{ + 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); +#endif + return NULL; +} + +int get_cipher_ivsize(const cipher_t *cipher) +{ + return EVP_CIPHER_iv_length(cipher); +} + +int get_cipher_keysize(const cipher_t *cipher) +{ + return EVP_CIPHER_key_length(cipher); +} + +ctx_t *create_ctx(const cipher_t *cipher, const unsigned char *key, + const unsigned char *iv, int enc, int padding) +{ + EVP_CIPHER_CTX *ctx; + int ret; + + ctx = EVP_CIPHER_CTX_new(); + if (!ctx) { + fprintf (stderr, "Error: create_ctx: out of memory.\n"); + return NULL; + } + ret = EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc); + if (!ret) { + fprintf(stderr, "Error:EVP_CipherInit_ex: %d\n", ret); + goto abort; + } + ret = EVP_CIPHER_CTX_set_padding(ctx, padding); + if (!ret) { + fprintf(stderr, "Error:EVP_CIPHER_CTX_set_padding: %d\n", ret); + goto abort; + } + + 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; + } + ret = fwrite(outbuf, 1, outlen, outfile); + if (ret != outlen) { + fprintf(stderr, "Error: CipherUpdate short write.\n"); + return ret - outlen; + } + } + 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 00000000000..36e17e220bb --- /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 <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#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 00000000000..a4fe1f33762 --- /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 <stdio.h> + +#define CRYPT_BUF_SIZE 1024 + +#ifdef USE_MBEDTLS +# include <mbedtls/cipher.h> + +# 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 <wolfssl/options.h> +# include <wolfssl/openssl/evp.h> +# else +# include <openssl/evp.h> +# 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); |
