ASR_BASE
Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/package/utils/uencrypt/src/uencrypt-mbedtls.c b/package/utils/uencrypt/src/uencrypt-mbedtls.c
new file mode 100644
index 0000000..119d07b
--- /dev/null
+++ b/package/utils/uencrypt/src/uencrypt-mbedtls.c
@@ -0,0 +1,238 @@
+/* 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"
+
+#if MBEDTLS_VERSION_NUMBER < 0x03010000 /* mbedtls 3.1.0 */
+static inline mbedtls_cipher_mode_t mbedtls_cipher_info_get_mode(
+ const mbedtls_cipher_info_t *info)
+{
+ if (info == NULL) {
+ return MBEDTLS_MODE_NONE;
+ } else {
+ return info->mode;
+ }
+}
+
+static inline size_t mbedtls_cipher_info_get_key_bitlen(
+ const mbedtls_cipher_info_t *info)
+{
+ if (info == NULL) {
+ return 0;
+ } else {
+ return info->key_bitlen;
+ }
+}
+
+static inline const char *mbedtls_cipher_info_get_name(
+ const mbedtls_cipher_info_t *info)
+{
+ if (info == NULL) {
+ return NULL;
+ } else {
+ return info->name;
+ }
+}
+
+static inline size_t mbedtls_cipher_info_get_iv_size(
+ const mbedtls_cipher_info_t *info)
+{
+ if (info == NULL) {
+ return 0;
+ }
+
+ return info->iv_size;
+}
+
+static inline size_t mbedtls_cipher_info_get_block_size(
+ const mbedtls_cipher_info_t *info)
+{
+ if (info == NULL) {
+ return 0;
+ }
+
+ return info->block_size;
+}
+#endif
+
+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", mbedtls_cipher_info_get_name(cipher));
+ }
+ return NULL;
+}
+
+int get_cipher_ivsize(const cipher_t *cipher)
+{
+ const mbedtls_cipher_info_t *c = cipher;
+
+ return mbedtls_cipher_info_get_iv_size(c);
+}
+
+int get_cipher_keysize(const cipher_t *cipher)
+{
+ const mbedtls_cipher_info_t *c = cipher;
+
+ return mbedtls_cipher_info_get_key_bitlen(c) >> 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 (mbedtls_cipher_info_get_mode(cipher_info) == 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 (mbedtls_cipher_info_get_block_size(cipher_info) > 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);
+ }
+}