1 /*
2 * Copyright (C) 2015-2017 Alibaba Group Holding Limited
3 */
4 #include <string.h>
5 #include "ota_log.h"
6 #include "ota_import.h"
7 #include "ota_hal_digest.h"
8 #include "ota_hal_os.h"
9
10 #define OTA_BUF_VERIFY 512
11
ota_hash_init(ota_hash_ctx_t * ctx,unsigned char type)12 int ota_hash_init(ota_hash_ctx_t *ctx, unsigned char type)
13 {
14 int ret = 0;
15 if (ctx == NULL) {
16 OTA_LOG_E("Invalid hash param");
17 return OTA_INVALID_PARAMETER;
18 }
19 ctx->hash_method = type;
20 switch (type) {
21 case OTA_SHA256:
22 ota_sha256_init(&ctx->sha256_ctx);
23 ota_sha256_starts(&ctx->sha256_ctx, 0);
24 break;
25 case OTA_MD5:
26 ota_md5_init(&ctx->md5_ctx);
27 ota_md5_starts(&ctx->md5_ctx);
28 break;
29 default:
30 ret = OTA_INVALID_PARAMETER;
31 break;
32 }
33 return ret;
34 }
35
ota_hash_update(ota_hash_ctx_t * ctx,const unsigned char * buf,unsigned int len)36 int ota_hash_update(ota_hash_ctx_t *ctx, const unsigned char *buf, unsigned int len)
37 {
38 int ret = 0;
39 if (ctx == NULL) {
40 OTA_LOG_E("Invalid hash param");
41 return OTA_INVALID_PARAMETER;
42 }
43 switch (ctx->hash_method) {
44 case OTA_SHA256:
45 ota_sha256_update(&ctx->sha256_ctx, buf, len);
46 break;
47 case OTA_MD5:
48 ota_md5_update(&ctx->md5_ctx, buf, len);
49 break;
50 default:
51 ret = OTA_INVALID_PARAMETER;
52 break;
53 }
54 return ret;
55 }
56
ota_hash_final(ota_hash_ctx_t * ctx,unsigned char * dgst)57 int ota_hash_final(ota_hash_ctx_t *ctx, unsigned char *dgst)
58 {
59 int ret = 0;
60 if (ctx == NULL) {
61 OTA_LOG_E("Invalid hash param");
62 return OTA_INVALID_PARAMETER;
63 }
64 switch (ctx->hash_method) {
65 case OTA_SHA256:
66 ota_sha256_finish(&ctx->sha256_ctx, dgst);
67 ota_sha256_free(&ctx->sha256_ctx);
68 break;
69 case OTA_MD5:
70 ota_md5_finish(&ctx->md5_ctx, dgst);
71 ota_md5_free(&ctx->md5_ctx);
72 break;
73 default:
74 ret = OTA_INVALID_PARAMETER;
75 break;
76 }
77 return ret;
78 }
79
ota_check_hash(unsigned char type,char * src,char * dst)80 int ota_check_hash(unsigned char type, char *src, char *dst)
81 {
82 int ret = 0;
83 switch (type) {
84 case OTA_SHA256:
85 OTA_LOG_I("SHA256 src:%s dst:%s", src, dst);
86 if (strncmp(dst, src, 64) != 0) {
87 ret = OTA_VERIFY_SHA2_FAIL;
88 }
89 break;
90 case OTA_MD5:
91 OTA_LOG_I("md5 src:%s dst:%s", src, dst);
92 if (strncmp(dst, src, 32) != 0) {
93 ret = OTA_VERIFY_MD5_FAIL;
94 }
95 break;
96 default:
97 ret = OTA_INVALID_PARAMETER;
98 break;
99 }
100 return ret;
101 }
102
ota_check_image_hash(unsigned int image_len,unsigned char type,char * hash_value,int len)103 int ota_check_image_hash(unsigned int image_len, unsigned char type, char *hash_value, int len)
104 {
105 int ret = 0;
106 char *rd_buf = NULL;
107 unsigned int read_size = 0;
108 unsigned int offset = 0;
109 ota_hash_ctx_t ctx = {0};
110 ota_crc16_ctx crc_ctx = {0};
111 unsigned short crc_result = 0;
112 if (NULL == hash_value) {
113 ret = OTA_VERIFY_IMAGE_FAIL;
114 goto EXIT;
115 }
116 switch (type) {
117 case OTA_SHA256:
118 if (len < 32) {
119 ret = OTA_VERIFY_SHA2_FAIL;
120 goto EXIT;
121 }
122 break;
123 case OTA_MD5:
124 if (len < 16) {
125 ret = OTA_VERIFY_MD5_FAIL;
126 goto EXIT;
127 }
128 break;
129 default:
130 ret = OTA_INVALID_PARAMETER;
131 goto EXIT;
132 }
133
134 rd_buf = ota_malloc(OTA_BUF_VERIFY);
135 if (rd_buf == NULL) {
136 ret = OTA_VERIFY_IMAGE_FAIL;
137 goto EXIT;
138 }
139 ret = ota_hash_init(&ctx, type);
140 if (ret != 0) {
141 goto EXIT;
142 }
143 ota_crc16_init(&crc_ctx);
144 while (offset < image_len) {
145 unsigned int off = offset;
146 (image_len - offset >= OTA_BUF_VERIFY) ? (read_size = OTA_BUF_VERIFY) : (read_size = image_len - offset);
147 ret = ota_read(&off, rd_buf, read_size);
148 if (ret < 0) {
149 ret = OTA_VERIFY_IMAGE_FAIL;
150 goto EXIT;
151 }
152 ret = ota_hash_update(&ctx, (const unsigned char *)rd_buf, read_size);
153 if (ret != 0) {
154 goto EXIT;
155 }
156 ota_crc16_update(&crc_ctx, (void *)rd_buf, read_size);
157 offset += read_size;
158 ota_msleep(5);
159 }
160 memset(hash_value, 0x00, len);
161 ota_crc16_final(&crc_ctx, &crc_result);
162 OTA_LOG_I("check image_crc16 = %x\r\n", crc_result);
163 ret = ota_hash_final(&ctx, (unsigned char *)hash_value);
164 EXIT:
165 if (NULL != rd_buf) {
166 ota_free(rd_buf);
167 rd_buf = NULL;
168 }
169 if (ret != 0) {
170 OTA_LOG_E("check image hash:%d", ret);
171 }
172 return ret;
173 }
174
ota_get_image_info(unsigned int image_size,ota_image_info_t * tmp_info)175 int ota_get_image_info(unsigned int image_size, ota_image_info_t *tmp_info)
176 {
177 int ret = -1;
178 unsigned int off_set = 0;
179 if ((tmp_info == NULL) || (image_size <= sizeof(ota_image_info_t))) {
180 OTA_LOG_E("input param err for getting image info!");
181 return ret;
182 }
183 off_set = image_size - sizeof(ota_image_info_t);
184 OTA_LOG_I("bin size:%d off:%d\r\n", image_size, off_set);
185 ret = ota_read(&off_set, (char *)tmp_info, sizeof(ota_image_info_t));
186 if (ret < 0) {
187 OTA_LOG_E("read image info err!");
188 }
189 OTA_LOG_I("magic:0x%04x, size:%d, crc16:0x%02x\r\n", tmp_info->image_magic, tmp_info->image_size, tmp_info->image_crc16);
190 return ret;
191 }
192
ota_check_image(unsigned int size)193 int ota_check_image(unsigned int size)
194 {
195 int ret = 0;
196 char image_md5[16] = {0};
197 char download_md5[33] = {0};
198 char cal_md5[33] = {0};
199 ota_image_info_t image_info = {0};
200
201 ret = ota_get_image_info(size, &image_info);
202 if (ret < 0) {
203 ret = OTA_VERIFY_IMAGE_FAIL;
204 goto EXIT;
205 }
206 ret = ota_hex2str(download_md5, (const unsigned char *)image_info.image_md5, sizeof(download_md5), sizeof(image_info.image_md5));
207 if (ret != 0) {
208 ret = OTA_VERIFY_IMAGE_FAIL;
209 goto EXIT;
210 }
211 OTA_LOG_I("magic:0x%04x size:%d md5:%s crc16:0x%02x", image_info.image_magic, image_info.image_size, download_md5, image_info.image_crc16);
212 if ((image_info.image_magic != OTA_BIN_MAGIC_APP) &&
213 (image_info.image_magic != OTA_BIN_MAGIC_KERNEL) &&
214 (image_info.image_magic != OTA_BIN_MAGIC_ALL) &&
215 (image_info.image_magic != OTA_BIN_MAGIC_MCU) &&
216 (image_info.image_magic != OTA_BIN_MAGIC_FS)) {
217 ret = OTA_INVALID_PARAMETER;
218 goto EXIT;
219 }
220 if (image_info.image_size == 0) {
221 ret = OTA_VERIFY_IMAGE_FAIL;
222 goto EXIT;
223 }
224 ret = ota_check_image_hash(image_info.image_size, OTA_MD5, image_md5, 16);
225 if (ret != 0) {
226 goto EXIT;
227 }
228 ret = ota_hex2str(cal_md5, (const unsigned char *)image_md5, sizeof(cal_md5), sizeof(image_md5));
229 if (ret != 0) {
230 ret = OTA_VERIFY_IMAGE_FAIL;
231 goto EXIT;
232 }
233 ret = ota_check_hash(OTA_MD5, cal_md5, download_md5);
234 if (ret != 0) {
235 goto EXIT;
236 }
237 EXIT:
238 if (ret != 0) {
239 OTA_LOG_E("ota check_image :%d", ret);
240 }
241 return ret;
242 }
243