// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 2019, Softathome */ #ifdef USE_HOSTCC #include "mkimage.h" #include #else #include #include #include DECLARE_GLOBAL_DATA_PTR; #endif /* !USE_HOSdTCC*/ #include #include #include struct cipher_algo cipher_algos[] = { { .name = "aes128", .key_len = AES128_KEY_LENGTH, .iv_len = AES_BLOCK_LENGTH, #if IMAGE_ENABLE_ENCRYPT .calculate_type = EVP_aes_128_cbc, #endif .encrypt = image_aes_encrypt, .decrypt = image_aes_decrypt, .add_cipher_data = image_aes_add_cipher_data }, { .name = "aes192", .key_len = AES192_KEY_LENGTH, .iv_len = AES_BLOCK_LENGTH, #if IMAGE_ENABLE_ENCRYPT .calculate_type = EVP_aes_192_cbc, #endif .encrypt = image_aes_encrypt, .decrypt = image_aes_decrypt, .add_cipher_data = image_aes_add_cipher_data }, { .name = "aes256", .key_len = AES256_KEY_LENGTH, .iv_len = AES_BLOCK_LENGTH, #if IMAGE_ENABLE_ENCRYPT .calculate_type = EVP_aes_256_cbc, #endif .encrypt = image_aes_encrypt, .decrypt = image_aes_decrypt, .add_cipher_data = image_aes_add_cipher_data } }; struct cipher_algo *image_get_cipher_algo(const char *full_name) { int i; const char *name; for (i = 0; i < ARRAY_SIZE(cipher_algos); i++) { name = cipher_algos[i].name; if (!strncmp(name, full_name, strlen(name))) return &cipher_algos[i]; } return NULL; } static int fit_image_setup_decrypt(struct image_cipher_info *info, const void *fit, int image_noffset, int cipher_noffset) { const void *fdt = gd_fdt_blob(); const char *node_name; char node_path[128]; int noffset; char *algo_name; int ret; node_name = fit_get_name(fit, image_noffset, NULL); if (!node_name) { printf("Can't get node name\n"); return -1; } if (fit_image_cipher_get_algo(fit, cipher_noffset, &algo_name)) { printf("Can't get algo name for cipher '%s' in image '%s'\n", node_name, node_name); return -1; } info->keyname = fdt_getprop(fit, cipher_noffset, FIT_KEY_HINT, NULL); if (!info->keyname) { printf("Can't get key name\n"); return -1; } info->iv = fdt_getprop(fit, cipher_noffset, "iv", NULL); info->ivname = fdt_getprop(fit, cipher_noffset, "iv-name-hint", NULL); if (!info->iv && !info->ivname) { printf("Can't get IV or IV name\n"); return -1; } info->fit = fit; info->node_noffset = image_noffset; info->name = algo_name; info->cipher = image_get_cipher_algo(algo_name); if (!info->cipher) { printf("Can't get cipher\n"); return -1; } ret = fit_image_get_data_size_unciphered(fit, image_noffset, &info->size_unciphered); if (ret) { printf("Can't get size of unciphered data\n"); return -1; } /* * Search the cipher node in the u-boot fdt * the path should be: /cipher/key--- */ if (info->ivname) snprintf(node_path, sizeof(node_path), "/%s/key-%s-%s-%s", FIT_CIPHER_NODENAME, algo_name, info->keyname, info->ivname); else snprintf(node_path, sizeof(node_path), "/%s/key-%s-%s", FIT_CIPHER_NODENAME, algo_name, info->keyname); noffset = fdt_path_offset(fdt, node_path); if (noffset < 0) { printf("Can't found cipher node offset\n"); return -1; } /* read key */ info->key = fdt_getprop(fdt, noffset, "key", NULL); if (!info->key) { printf("Can't get key in cipher node '%s'\n", node_path); return -1; } /* read iv */ if (!info->iv) { info->iv = fdt_getprop(fdt, noffset, "iv", NULL); if (!info->iv) { printf("Can't get IV in cipher node '%s'\n", node_path); return -1; } } return 0; } int fit_image_decrypt_data(const void *fit, int image_noffset, int cipher_noffset, const void *data_ciphered, size_t size_ciphered, void **data_unciphered, size_t *size_unciphered) { struct image_cipher_info info; int ret; ret = fit_image_setup_decrypt(&info, fit, image_noffset, cipher_noffset); if (ret < 0) goto out; ret = info.cipher->decrypt(&info, data_ciphered, size_ciphered, data_unciphered, size_unciphered); out: return ret; }