uencrypt: support all available ciphers

Modify uencrypt to support any cipher provided by ssl library.

Original tool supported only AES-128-CBC to decrypt the config
mtd of Arcadyan WG430223/WG443223.

TP-Link Deco S4 has mtd configuration encrypted with DES-ECB,
so make the cipher generic to support both routers.

Signed-off-by: Nick French <nickfrench@gmail.com>
Reviewed-by: Eneas U de Queiroz >cotequeiroz@gmail.com>
This commit is contained in:
Nick French 2022-08-13 10:23:58 -05:00 committed by Christian Marangi
parent a6b0d08060
commit 764600648f
No known key found for this signature in database
GPG Key ID: AC001D09ADBFEAD7
2 changed files with 52 additions and 18 deletions

View File

@ -22,16 +22,17 @@ CMAKE_OPTIONS+=$(if $(CONFIG_UENCRYPT_WOLFSSL),-DUSE_WOLFSSL=1)
define Package/uencrypt define Package/uencrypt
SECTION:=utils SECTION:=utils
CATEGORY:=Base system CATEGORY:=Base system
TITLE:=Decryption utility for Arcadyan WG4xx223 TITLE:=Decryption utility for Arcadyan WG4xx223 and TP-Link Deco S4
DEPENDS:=@TARGET_ramips_mt7621 +UENCRYPT_WOLFSSL:libwolfssl +UENCRYPT_OPENSSL:libopenssl DEPENDS:=+UENCRYPT_WOLFSSL:libwolfssl +UENCRYPT_OPENSSL:libopenssl
endef endef
define Package/uencrypt/description define Package/uencrypt/description
This is a small AES-128-CBC encrypton/decryption program. This is a small encrypton/decryption program. It defaults
Even though it can be used for regular encryption and to AES-128-CBC, but supports any encryption provided by
decryption operations using AES-128-CBC, it is included the available openssl/wolfssl library. Even though it can
here to unencrypt the configuration from mtd on Arcadyan be used for regular encryption and decryption operations,
WG430223 and WG443223 routers. it is included here to unencrypt the configuration from mtd
on Arcadyan WG430223/WG443223 and TP-Link Deco S4 routers
endef endef
define Package/uencrypt/config define Package/uencrypt/config

View File

@ -5,6 +5,7 @@
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <unistd.h> #include <unistd.h>
#ifdef USE_WOLFSSL #ifdef USE_WOLFSSL
@ -14,7 +15,7 @@
# include <openssl/evp.h> # include <openssl/evp.h>
#endif #endif
int do_crypt(FILE *infile, FILE *outfile, const char *key, const char *iv, int do_crypt(FILE *infile, FILE *outfile, const EVP_CIPHER *cipher, const char *key, const char *iv,
int enc, int padding) int enc, int padding)
{ {
EVP_CIPHER_CTX *ctx; EVP_CIPHER_CTX *ctx;
@ -22,7 +23,7 @@ int do_crypt(FILE *infile, FILE *outfile, const char *key, const char *iv,
int inlen, outlen; int inlen, outlen;
ctx = EVP_CIPHER_CTX_new(); ctx = EVP_CIPHER_CTX_new();
EVP_CipherInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv, enc); EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc);
EVP_CIPHER_CTX_set_padding(ctx, padding); EVP_CIPHER_CTX_set_padding(ctx, padding);
for (;;) { for (;;) {
@ -53,9 +54,27 @@ static void check_enc_dec(const int enc)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
#ifndef USE_WOLFSSL
static void print_ciphers(const OBJ_NAME *name,void *arg) {
fprintf(arg, "\t%s\n", name->name);
}
#endif
static void check_cipher(const EVP_CIPHER *cipher)
{
if (cipher == NULL) {
fprintf(stderr, "Error: invalid cipher: %s.\n", optarg);
#ifndef USE_WOLFSSL
fprintf(stderr, "Supported ciphers: \n", optarg);
OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, print_ciphers, stderr);
#endif
exit(EXIT_FAILURE);
}
}
static void show_usage(const char* name) static void show_usage(const char* name)
{ {
fprintf(stderr, "Usage: %s: [-d | -e] [-n] -k key -i iv\n" fprintf(stderr, "Usage: %s: [-d | -e] [-n] -k key [-i iv] [-c cipher]\n"
"-d = decrypt; -e = encrypt; -n = no padding\n", name); "-d = decrypt; -e = encrypt; -n = no padding\n", name);
} }
@ -67,10 +86,19 @@ int main(int argc, char *argv[])
long len; long len;
int opt; int opt;
int padding = 1; int padding = 1;
int need_iv = 1;
const EVP_CIPHER *cipher = EVP_aes_128_cbc();
int ret; int ret;
while ((opt = getopt(argc, argv, "dei:k:n")) != -1) { while ((opt = getopt(argc, argv, "c:dei:k:n")) != -1) {
switch (opt) { switch (opt) {
case 'c':
cipher = EVP_get_cipherbyname(optarg);
check_cipher(cipher);
int arglen = strlen(optarg);
if (arglen > 3 && strncmp(optarg+arglen-3, "ecb", 3) == 0) //if ends with "ecb"
need_iv = 0;
break;
case 'd': case 'd':
check_enc_dec(enc); check_enc_dec(enc);
enc = 0; enc = 0;
@ -81,16 +109,16 @@ int main(int argc, char *argv[])
break; break;
case 'i': case 'i':
iv = OPENSSL_hexstr2buf((const char *)optarg, &len); iv = OPENSSL_hexstr2buf((const char *)optarg, &len);
if (iv == NULL || len != 16) { if (iv == NULL) {
fprintf(stderr, "Error setting IV to %s. The IV should be 16 bytes, encoded in hex.\n", fprintf(stderr, "Error setting IV to %s. The IV should be encoded in hex.\n",
optarg); optarg);
exit(EINVAL); exit(EINVAL);
} }
break; break;
case 'k': case 'k':
key = OPENSSL_hexstr2buf((const char *)optarg, &len); key = OPENSSL_hexstr2buf((const char *)optarg, &len);
if (key == NULL || len != 16) { if (key == NULL) {
fprintf(stderr, "Error setting key to %s. The key should be 16 bytes, encoded in hex.\n", fprintf(stderr, "Error setting key to %s. The key should be encoded in hex.\n",
optarg); optarg);
exit(EINVAL); exit(EINVAL);
} }
@ -103,12 +131,17 @@ int main(int argc, char *argv[])
exit(EINVAL); exit(EINVAL);
} }
} }
if (iv == NULL || key == NULL) { if (need_iv && iv == NULL) {
fprintf(stderr, "Error: %s not set.\n", key ? "iv" : (iv ? "key" : "key and iv")); fprintf(stderr, "Error: iv not set.\n");
show_usage(argv[0]);
exit(EXIT_FAILURE);
}
if (key == NULL) {
fprintf(stderr, "Error: key not set.\n");
show_usage(argv[0]); show_usage(argv[0]);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
ret = do_crypt(stdin, stdout, key, iv, !!enc, padding); ret = do_crypt(stdin, stdout, cipher, key, iv, !!enc, padding);
if (ret) if (ret)
fprintf(stderr, "Error during crypt operation.\n"); fprintf(stderr, "Error during crypt operation.\n");
OPENSSL_free(iv); OPENSSL_free(iv);