1 /*
2  * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3  */
4 
5 #include <stdio.h>
6 #include <string.h>
7 #include <stdlib.h>
8 #include <unistd.h>
9 #include <errno.h>
10 #include <fcntl.h>
11 #include "ota_log.h"
12 #include "ota_import.h"
13 #include "ota_hal_os.h"
14 #include "ota_hal_digest.h"
15 #include "ota_hal.h"
16 #include <aos/vfs.h>
17 
18 static ota_hash_ctx_t hash_ctx  = {0};
19 static unsigned short upg_flag  = 0;
20 static unsigned char  is_header = 0;
21 #ifdef OTA_CONFIG_LOCAL_RSA
22 static unsigned int valid_image_len = 0;
23 static unsigned int calculated_len = 0;
24 #endif
25 
ota_int(ota_boot_param_t * param)26 int ota_int(ota_boot_param_t *param)
27 {
28     int ret = 0;
29     if (param == NULL) {
30         return OTA_UPGRADE_PARAM_FAIL;
31     }
32     is_header = 0;
33     upg_flag  = 0;
34 #ifdef OTA_CONFIG_LOCAL_RSA
35     calculated_len = 0;
36     valid_image_len = param->len - sizeof(ota_image_info_t) - sizeof(ota_sign_info_t);
37 #endif
38     ret = ota_hal_init(param);
39     if (ret == 0) {
40         ret = ota_hash_init(&hash_ctx, param->hash_type);
41     }
42     OTA_LOG_I("ota init ret = %d\r\n", ret);
43     return ret;
44 }
45 
ota_write(unsigned int * off,char * in_buf,unsigned int in_buf_len)46 int ota_write(unsigned int *off, char *in_buf, unsigned int in_buf_len)
47 {
48     int ret = 0;
49     if ((*off == 0) && (is_header == 0)) {
50         unsigned char xz_header[6] = { 0xFD, '7', 'z', 'X', 'Z', 0x00 };
51         if (memcmp(in_buf, "BSDIFF40", 8) == 0) {
52             upg_flag = OTA_UPGRADE_DIFF;
53         } else if (memcmp(in_buf, xz_header, 6) == 0) {
54             upg_flag = OTA_UPGRADE_XZ;
55         }
56         OTA_LOG_I("ota header:0x%x\n", upg_flag);
57         is_header = 1;
58     }
59     ret = ota_hal_write(off, in_buf, in_buf_len);
60     if (ret >= 0) {
61 #ifdef OTA_CONFIG_LOCAL_RSA
62         if (calculated_len <= valid_image_len) {
63             ota_hash_ctx_t tmp_ctx = hash_ctx;
64             unsigned int tmp_len = 0;
65             ((calculated_len + in_buf_len) <= valid_image_len) ? (tmp_len = in_buf_len) :
66                                             (tmp_len = valid_image_len - calculated_len);
67             ret = ota_hash_update(&hash_ctx, (const unsigned char *)in_buf, tmp_len);
68             if (ret >= 0) {
69                 calculated_len += in_buf_len;
70             } else {
71                 hash_ctx = tmp_ctx;
72             }
73         }
74 #else
75         ret = ota_hash_update(&hash_ctx, (const unsigned char *)in_buf, in_buf_len);
76 #endif
77     }
78     return ret;
79 }
80 
ota_read(unsigned int * off,char * out_buf,unsigned int out_buf_len)81 int ota_read(unsigned int *off, char *out_buf, unsigned int out_buf_len)
82 {
83     int ret = 0;
84     ret = ota_hal_read(off, out_buf, out_buf_len);
85     return ret;
86 }
87 
ota_clear()88 int ota_clear()
89 {
90     is_header = 0;
91     upg_flag  = 0;
92     return ota_clear_paramters();
93 }
94 
ota_verify(ota_boot_param_t * param)95 int ota_verify(ota_boot_param_t *param)
96 {
97     int ret = OTA_UPGRADE_SET_BOOT_FAIL;
98     unsigned char hash[32] = {0};
99     char dst_hash[65] = {0};
100     if (param == NULL) {
101         return ret;
102     }
103     is_header = 0;
104     if (upg_flag != 0) {
105         param->upg_flag = upg_flag;
106     } else if (param->upg_flag == 0) {
107         param->upg_flag = OTA_UPGRADE_ALL;
108     }
109     memset(hash, 0x00, sizeof(hash));
110     ret = ota_hash_final(&hash_ctx, hash);
111     if (ret == 0) {
112         ret = ota_hex2str(dst_hash, hash, sizeof(dst_hash), sizeof(hash));
113         if (ret == 0) {
114             ret = ota_check_hash(param->hash_type, param->hash, (char *)dst_hash);
115             if (ret < 0) {
116                 OTA_LOG_E("ota verify hash failed!");
117                 return ret;
118             }
119             /* verify RSA signature */
120 #if OTA_CONFIG_LOCAL_RSA
121             ret = ota_verify_rsa((unsigned char *)param->sign, (const char *)dst_hash, param->hash_type);
122             if (ret < 0) {
123                 ret = OTA_VERIFY_RSA_FAIL;
124                 return ret;
125             }
126 #else
127             if (strlen(param->sign) > 0) {
128                 ret = ota_verify_rsa((unsigned char *)param->sign, (const char *)dst_hash, param->hash_type);
129                 if (ret < 0) {
130                     ret = OTA_VERIFY_RSA_FAIL;
131                     return ret;
132                 }
133             }
134 #endif
135             /* verify image */
136 #if !defined CONFIG_PING_PONG_OTA
137             if ((param->upg_flag != OTA_UPGRADE_DIFF) && (param->upg_flag != OTA_UPGRADE_CUST)) {
138                 ret = ota_check_image(param->len);
139                 if (ret < 0) {
140                     ret = OTA_VERIFY_IMAGE_FAIL;
141                 }
142             }
143 #endif
144         }
145     }
146     OTA_LOG_I("ota boot finish ret:%d crc:0x%04x", ret, param->crc);
147     return ret;
148 }
149 
ota_verify_fsfile(ota_boot_param_t * param,char * file_path)150 int ota_verify_fsfile(ota_boot_param_t *param, char *file_path)
151 {
152     int fd = -1;
153     int ret = OTA_UPGRADE_SET_BOOT_FAIL;
154     unsigned char hash[32] = {0};
155     char dst_hash[65] = {0};
156     char tmp_buf[128] = {0};
157     unsigned int offset = 0;
158     unsigned int read_len = 0;
159     ota_hash_ctx_t tmp_hash_ctx;
160     if ((param == NULL) || (file_path == NULL)) {
161         return ret;
162     }
163     memset(hash, 0x00, sizeof(hash));
164     ret = ota_hash_init(&tmp_hash_ctx, param->hash_type);
165     if (ret < 0) {
166         OTA_LOG_E("subdev fs file hash init failed\n");
167         return ret;
168     }
169     fd = ota_fopen(file_path, O_RDONLY);
170     if (fd < 0) {
171         ret = OTA_UPGRADE_SET_BOOT_FAIL;
172         OTA_LOG_E("open %s failed\n", file_path);
173         return ret;
174     }
175     OTA_LOG_I("fs size = %d\n", param->len);
176     while (offset < param->len) {
177         (param->len - offset >= sizeof(tmp_buf)) ? (read_len = sizeof(tmp_buf)) : (read_len = param->len - offset);
178         ret = ota_fread(fd, (void *)tmp_buf, read_len);
179         if (ret < 0) {
180             OTA_LOG_E("verify fs file read file failed\r\n");
181             ret = OTA_VERIFY_IMAGE_FAIL;
182             break;
183         }
184         ret = ota_hash_update(&tmp_hash_ctx, (const unsigned char *)tmp_buf, read_len);
185         if (ret < 0) {
186             break;
187         }
188         offset += read_len;
189         ota_msleep(5);
190     }
191     if (fd >= 0) {
192         (void)ota_fclose(fd);
193     }
194     if (ret < 0) {
195         OTA_LOG_E("get fs file hash value failed\n");
196         return ret;
197     }
198     ret = ota_hash_final(&tmp_hash_ctx, hash);
199     if (ret == 0) {
200         ret = ota_hex2str(dst_hash, hash, sizeof(dst_hash), sizeof(hash));
201         if (ret == 0) {
202             ret = ota_check_hash(param->hash_type, param->hash, (char *)dst_hash);
203             if (ret < 0) {
204                 OTA_LOG_E("ota verify hash failed!");
205                 return ret;
206             }
207             /* verify RSA signature */
208 #if OTA_CONFIG_LOCAL_RSA
209             ret = ota_verify_rsa((unsigned char *)param->sign, (const char *)dst_hash, param->hash_type);
210             if (ret < 0) {
211                 ret = OTA_VERIFY_RSA_FAIL;
212                 return ret;
213             }
214 #else
215             if (strlen(param->sign) > 0) {
216                 ret = ota_verify_rsa((unsigned char *)param->sign, (const char*)dst_hash, param->hash_type);
217                 if (ret < 0) {
218                     ret = OTA_VERIFY_RSA_FAIL;
219                     return ret;
220                 }
221             }
222 #endif
223          }
224     }
225     OTA_LOG_I("verfiy fs over ret:%d\n", ret);
226     return ret;
227 }