xref: /aosp_15_r20/external/arm-trusted-firmware/tools/encrypt_fw/src/encrypt.c (revision 54fd6939e177f8ff529b10183254802c76df6d08)
1*54fd6939SJiyong Park /*
2*54fd6939SJiyong Park  * Copyright (c) 2019, Linaro Limited. All rights reserved.
3*54fd6939SJiyong Park  * Author: Sumit Garg <[email protected]>
4*54fd6939SJiyong Park  *
5*54fd6939SJiyong Park  * SPDX-License-Identifier: BSD-3-Clause
6*54fd6939SJiyong Park  */
7*54fd6939SJiyong Park 
8*54fd6939SJiyong Park #include <firmware_encrypted.h>
9*54fd6939SJiyong Park #include <openssl/evp.h>
10*54fd6939SJiyong Park #include <stdio.h>
11*54fd6939SJiyong Park #include <string.h>
12*54fd6939SJiyong Park #include "debug.h"
13*54fd6939SJiyong Park #include "encrypt.h"
14*54fd6939SJiyong Park 
15*54fd6939SJiyong Park #define BUFFER_SIZE		256
16*54fd6939SJiyong Park #define IV_SIZE			12
17*54fd6939SJiyong Park #define IV_STRING_SIZE		24
18*54fd6939SJiyong Park #define TAG_SIZE		16
19*54fd6939SJiyong Park #define KEY_SIZE		32
20*54fd6939SJiyong Park #define KEY_STRING_SIZE		64
21*54fd6939SJiyong Park 
gcm_encrypt(unsigned short fw_enc_status,char * key_string,char * nonce_string,const char * ip_name,const char * op_name)22*54fd6939SJiyong Park static int gcm_encrypt(unsigned short fw_enc_status, char *key_string,
23*54fd6939SJiyong Park 		       char *nonce_string, const char *ip_name,
24*54fd6939SJiyong Park 		       const char *op_name)
25*54fd6939SJiyong Park {
26*54fd6939SJiyong Park 	FILE *ip_file;
27*54fd6939SJiyong Park 	FILE *op_file;
28*54fd6939SJiyong Park 	EVP_CIPHER_CTX *ctx;
29*54fd6939SJiyong Park 	unsigned char data[BUFFER_SIZE], enc_data[BUFFER_SIZE];
30*54fd6939SJiyong Park 	unsigned char key[KEY_SIZE], iv[IV_SIZE], tag[TAG_SIZE];
31*54fd6939SJiyong Park 	int bytes, enc_len = 0, i, j, ret = 0;
32*54fd6939SJiyong Park 	struct fw_enc_hdr header;
33*54fd6939SJiyong Park 
34*54fd6939SJiyong Park 	memset(&header, 0, sizeof(struct fw_enc_hdr));
35*54fd6939SJiyong Park 
36*54fd6939SJiyong Park 	if (strlen(key_string) != KEY_STRING_SIZE) {
37*54fd6939SJiyong Park 		ERROR("Unsupported key size: %lu\n", strlen(key_string));
38*54fd6939SJiyong Park 		return -1;
39*54fd6939SJiyong Park 	}
40*54fd6939SJiyong Park 
41*54fd6939SJiyong Park 	for (i = 0, j = 0; i < KEY_SIZE; i++, j += 2) {
42*54fd6939SJiyong Park 		if (sscanf(&key_string[j], "%02hhx", &key[i]) != 1) {
43*54fd6939SJiyong Park 			ERROR("Incorrect key format\n");
44*54fd6939SJiyong Park 			return -1;
45*54fd6939SJiyong Park 		}
46*54fd6939SJiyong Park 	}
47*54fd6939SJiyong Park 
48*54fd6939SJiyong Park 	if (strlen(nonce_string) != IV_STRING_SIZE) {
49*54fd6939SJiyong Park 		ERROR("Unsupported IV size: %lu\n", strlen(nonce_string));
50*54fd6939SJiyong Park 		return -1;
51*54fd6939SJiyong Park 	}
52*54fd6939SJiyong Park 
53*54fd6939SJiyong Park 	for (i = 0, j = 0; i < IV_SIZE; i++, j += 2) {
54*54fd6939SJiyong Park 		if (sscanf(&nonce_string[j], "%02hhx", &iv[i]) != 1) {
55*54fd6939SJiyong Park 			ERROR("Incorrect IV format\n");
56*54fd6939SJiyong Park 			return -1;
57*54fd6939SJiyong Park 		}
58*54fd6939SJiyong Park 	}
59*54fd6939SJiyong Park 
60*54fd6939SJiyong Park 	ip_file = fopen(ip_name, "rb");
61*54fd6939SJiyong Park 	if (ip_file == NULL) {
62*54fd6939SJiyong Park 		ERROR("Cannot read %s\n", ip_name);
63*54fd6939SJiyong Park 		return -1;
64*54fd6939SJiyong Park 	}
65*54fd6939SJiyong Park 
66*54fd6939SJiyong Park 	op_file = fopen(op_name, "wb");
67*54fd6939SJiyong Park 	if (op_file == NULL) {
68*54fd6939SJiyong Park 		ERROR("Cannot write %s\n", op_name);
69*54fd6939SJiyong Park 		fclose(ip_file);
70*54fd6939SJiyong Park 		return -1;
71*54fd6939SJiyong Park 	}
72*54fd6939SJiyong Park 
73*54fd6939SJiyong Park 	ret = fseek(op_file, sizeof(struct fw_enc_hdr), SEEK_SET);
74*54fd6939SJiyong Park 	if (ret) {
75*54fd6939SJiyong Park 		ERROR("fseek failed\n");
76*54fd6939SJiyong Park 		goto out_file;
77*54fd6939SJiyong Park 	}
78*54fd6939SJiyong Park 
79*54fd6939SJiyong Park 	ctx = EVP_CIPHER_CTX_new();
80*54fd6939SJiyong Park 	if (ctx == NULL) {
81*54fd6939SJiyong Park 		ERROR("EVP_CIPHER_CTX_new failed\n");
82*54fd6939SJiyong Park 		ret = -1;
83*54fd6939SJiyong Park 		goto out_file;
84*54fd6939SJiyong Park 	}
85*54fd6939SJiyong Park 
86*54fd6939SJiyong Park 	ret = EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
87*54fd6939SJiyong Park 	if (ret != 1) {
88*54fd6939SJiyong Park 		ERROR("EVP_EncryptInit_ex failed\n");
89*54fd6939SJiyong Park 		ret = -1;
90*54fd6939SJiyong Park 		goto out;
91*54fd6939SJiyong Park 	}
92*54fd6939SJiyong Park 
93*54fd6939SJiyong Park 	ret = EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv);
94*54fd6939SJiyong Park 	if (ret != 1) {
95*54fd6939SJiyong Park 		ERROR("EVP_EncryptInit_ex failed\n");
96*54fd6939SJiyong Park 		goto out;
97*54fd6939SJiyong Park 	}
98*54fd6939SJiyong Park 
99*54fd6939SJiyong Park 	while ((bytes = fread(data, 1, BUFFER_SIZE, ip_file)) != 0) {
100*54fd6939SJiyong Park 		ret = EVP_EncryptUpdate(ctx, enc_data, &enc_len, data, bytes);
101*54fd6939SJiyong Park 		if (ret != 1) {
102*54fd6939SJiyong Park 			ERROR("EVP_EncryptUpdate failed\n");
103*54fd6939SJiyong Park 			ret = -1;
104*54fd6939SJiyong Park 			goto out;
105*54fd6939SJiyong Park 		}
106*54fd6939SJiyong Park 
107*54fd6939SJiyong Park 		fwrite(enc_data, 1, enc_len, op_file);
108*54fd6939SJiyong Park 	}
109*54fd6939SJiyong Park 
110*54fd6939SJiyong Park 	ret = EVP_EncryptFinal_ex(ctx, enc_data, &enc_len);
111*54fd6939SJiyong Park 	if (ret != 1) {
112*54fd6939SJiyong Park 		ERROR("EVP_EncryptFinal_ex failed\n");
113*54fd6939SJiyong Park 		ret = -1;
114*54fd6939SJiyong Park 		goto out;
115*54fd6939SJiyong Park 	}
116*54fd6939SJiyong Park 
117*54fd6939SJiyong Park 	ret = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, TAG_SIZE, tag);
118*54fd6939SJiyong Park 	if (ret != 1) {
119*54fd6939SJiyong Park 		ERROR("EVP_CIPHER_CTX_ctrl failed\n");
120*54fd6939SJiyong Park 		ret = -1;
121*54fd6939SJiyong Park 		goto out;
122*54fd6939SJiyong Park 	}
123*54fd6939SJiyong Park 
124*54fd6939SJiyong Park 	header.magic = ENC_HEADER_MAGIC;
125*54fd6939SJiyong Park 	header.flags |= fw_enc_status & FW_ENC_STATUS_FLAG_MASK;
126*54fd6939SJiyong Park 	header.dec_algo = KEY_ALG_GCM;
127*54fd6939SJiyong Park 	header.iv_len = IV_SIZE;
128*54fd6939SJiyong Park 	header.tag_len = TAG_SIZE;
129*54fd6939SJiyong Park 	memcpy(header.iv, iv, IV_SIZE);
130*54fd6939SJiyong Park 	memcpy(header.tag, tag, TAG_SIZE);
131*54fd6939SJiyong Park 
132*54fd6939SJiyong Park 	ret = fseek(op_file, 0, SEEK_SET);
133*54fd6939SJiyong Park 	if (ret) {
134*54fd6939SJiyong Park 		ERROR("fseek failed\n");
135*54fd6939SJiyong Park 		goto out;
136*54fd6939SJiyong Park 	}
137*54fd6939SJiyong Park 
138*54fd6939SJiyong Park 	fwrite(&header, 1, sizeof(struct fw_enc_hdr), op_file);
139*54fd6939SJiyong Park 
140*54fd6939SJiyong Park out:
141*54fd6939SJiyong Park 	EVP_CIPHER_CTX_free(ctx);
142*54fd6939SJiyong Park 
143*54fd6939SJiyong Park out_file:
144*54fd6939SJiyong Park 	fclose(ip_file);
145*54fd6939SJiyong Park 	fclose(op_file);
146*54fd6939SJiyong Park 
147*54fd6939SJiyong Park 	/*
148*54fd6939SJiyong Park 	 * EVP_* APIs returns 1 as success but enctool considers
149*54fd6939SJiyong Park 	 * 0 as success.
150*54fd6939SJiyong Park 	 */
151*54fd6939SJiyong Park 	if (ret == 1)
152*54fd6939SJiyong Park 		ret = 0;
153*54fd6939SJiyong Park 
154*54fd6939SJiyong Park 	return ret;
155*54fd6939SJiyong Park }
156*54fd6939SJiyong Park 
encrypt_file(unsigned short fw_enc_status,int enc_alg,char * key_string,char * nonce_string,const char * ip_name,const char * op_name)157*54fd6939SJiyong Park int encrypt_file(unsigned short fw_enc_status, int enc_alg, char *key_string,
158*54fd6939SJiyong Park 		 char *nonce_string, const char *ip_name, const char *op_name)
159*54fd6939SJiyong Park {
160*54fd6939SJiyong Park 	switch (enc_alg) {
161*54fd6939SJiyong Park 	case KEY_ALG_GCM:
162*54fd6939SJiyong Park 		return gcm_encrypt(fw_enc_status, key_string, nonce_string,
163*54fd6939SJiyong Park 				   ip_name, op_name);
164*54fd6939SJiyong Park 	default:
165*54fd6939SJiyong Park 		return -1;
166*54fd6939SJiyong Park 	}
167*54fd6939SJiyong Park }
168