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