SET(SRCS
ss_engine/SS_Common.c
- ss_patch/sha1.c
+ ss_engine/sha1.c
ss_engine/SS_UPI.c
ss_engine/SS_FSUpdate.c
ss_engine/fota_tar.c
- ss_patch/ss_bspatch.c
- ss_patch/ss_patchdelta.c
+ ss_engine/SS_ApplyPatch.c
+ ss_engine/SS_PatchDelta.c
bsdiff/ss_bspatch_common.c
)
SET(HEADERS
#INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/ss_engine)
-INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/ss_patch)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/bsdiff)
INCLUDE(FindPkgConfig)
Name: libtota
Summary: fota update library
ExclusiveArch: %{arm}
-Version: 0.1.3
-Release: 4
+Version: 0.1.4
+Release: 5
Group: System
License: Apache-2.0 and BSD-2-Clause and BSD-3-Clause and PD
Source0: %{name}-%{version}.tar.gz
--- /dev/null
+/*-
+ * Copyright 2003-2005 Colin Percival
+ * Copyright 2012 Matthew Endsley
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Modifications are made in reimplementing suffix sort array generation
+ * and how the data is read and written to.Iterative part replaced the
+ * recursive implementation to avoid buffer overflow problems
+ */
+#include <string.h>
+#include <err.h>
+#include "SS_PatchDelta.h"
+#include "fota_common.h"
+#include "sha1.h"
+#include "SS_Engine_Errors.h"
+
+#include "ss_bspatch_common.h"
+#include <Alloc.h>
+#include <7zFile.h>
+#include <7zVersion.h>
+#include <LzmaDec.h>
+#include <LzmaEnc.h>
+
+
+int SS_ApplyBsdiff(char *oldfile, char *newfile, char *patch, SinkFn sink, void *token, sha1_ctx_t * ctx1)
+{
+
+ UInt64 unpackSize = 0;
+ CFileSeqInStream inStream;
+ ISeqOutStream outStream;
+ char *buf_res = NULL;
+ unsigned char *new_data = NULL;
+ ssize_t new_size = 0;
+ int result = E_SS_FAILURE;
+
+ FileSeqInStream_CreateVTable(&inStream);
+ File_Construct(&inStream.file);
+ FileOutStream_CreateVTable((CFileOutStream *) & outStream);
+
+ if (InFile_Open(&inStream.file, patch) != 0)
+ return E_SS_FAILURE;
+
+ UInt64 i;
+ CLzmaDec state;
+ unsigned char header[LZMA_PROPS_SIZE + 8];
+
+ RINOK(SeqInStream_Read(&inStream.s, header, sizeof(header)));
+
+ unpackSize = 0;
+ for (i = 0; i < 8; i++)
+ unpackSize += (UInt64) header[LZMA_PROPS_SIZE + i] << (i * 8);
+
+ LzmaDec_Construct(&state);
+ RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc));
+
+ //decompress the patch file into buf_res
+ buf_res = (char *)SS_Malloc(unpackSize);
+ if (!buf_res) {
+ LOGE("Bad memory allocation\n");
+ goto Cleanup;
+ }
+ result = Decode2(&state, &outStream, &inStream.s, &unpackSize, (unsigned char *)buf_res);
+
+ LzmaDec_Free(&state, &g_Alloc);
+ File_Close(&inStream.file);
+
+ if (result != S_SS_SUCCESS) {
+ LOGE("Error decompression failed with code : [%d]\n", result);
+ goto Cleanup;
+ }
+ //apply patch using buffer decoded by Decode2
+ result = apply_patch(oldfile, buf_res, &new_data, &new_size);
+ if (result != S_SS_SUCCESS) {
+ goto Cleanup;
+ }
+
+ result = (sink(new_data, new_size, token) < new_size) ? E_SS_FAILURE : S_SS_SUCCESS;
+ if (result != S_SS_SUCCESS) {
+ LOGE("short write of output: %d (%s)\n", errno, strerror(errno));
+ goto Cleanup;
+ }
+
+ if (ctx1) {
+ sha1_update(ctx1, new_data, new_size);
+ }
+ Cleanup:
+ if (new_data)
+ SS_Free(new_data);
+ if (buf_res)
+ SS_Free(buf_res);
+ File_Close(&inStream.file);//wgid: 27007
+ return result;
+
+}
--- /dev/null
+/*
+ * libtota
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "ua.h"
+#include "sha1.h"
+#include "SS_PatchDelta.h"
+#include "fota_common.h"
+#include "SS_Engine_Errors.h"
+
+extern void *SS_Malloc(unsigned int size);
+
+typedef struct {
+ unsigned char *buffer;
+ ssize_t size;
+ ssize_t pos;
+} MemorySinkInfo;
+
+ssize_t ss_memorySink(unsigned char *data, ssize_t len, void *token)
+{
+ MemorySinkInfo *msi = (MemorySinkInfo *) token;
+ if (msi->size - msi->pos < len) {
+ return -1;
+ }
+ memcpy(msi->buffer + msi->pos, data, len);
+ msi->pos += len;
+ return len;
+}
+
+ssize_t ss_fileSink(unsigned char *data, ssize_t len, void *token)
+{
+ int ss_fd = *(int *)token;
+ ssize_t done = 0;
+ ssize_t wrote;
+ while (done < (ssize_t) len) {
+ wrote = write(ss_fd, data + done, len - done);
+ if (wrote <= 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue; // try again
+ LOGE("error writing %d bytes: %s\n", (int)(len - done), strerror(errno));
+ return done;
+ }
+ done += wrote;
+ }
+ return done;
+}
+
+// Take a string 'str' of 40 hex digits and parse it into the 20
+// byte array 'digest'. 'str' may contain only the digest or be of
+// the form "<digest>:<anything>". Return 0 on success, -1 on any
+// error.
+int ParseSha1(const char *str, uint8_t * digest)
+{
+ int i;
+ const char *ps = str;
+ uint8_t *pd = digest;
+ for (i = 0; i < SHA_DIGEST_SIZE * 2; ++i, ++ps) {
+ int digit;
+ if (*ps >= '0' && *ps <= '9') {
+ digit = *ps - '0';
+ } else if (*ps >= 'a' && *ps <= 'f') {
+ digit = *ps - 'a' + 10;
+ } else if (*ps >= 'A' && *ps <= 'F') {
+ digit = *ps - 'A' + 10;
+ } else {
+ return -1;
+ }
+ if (i % 2 == 0) {
+ *pd = digit << 4;
+ } else {
+ *pd |= digit;
+ ++pd;
+ }
+ }
+ if (*ps != '\0')
+ return -1;
+ return 0;
+}
+
+//Function to find the start of gzipped part in compressed kernel
+int getOffset(char *zimage_path)
+{
+ char gzip_header[] = { 31, -117, 8 }; //header value for gzip which needs to be checked
+ char buf[4] = { 0, };
+ int offset = 0;//wgid:14074
+
+ FILE *f = fopen(zimage_path, "r");
+ if(!f){
+ LOGE("Fopen failed for path %s\n", zimage_path);
+ SS_SetUpgradeState(E_SS_OPENFILE_ONLYR);
+ return -1;
+ }
+ fseek(f, 0, SEEK_SET);
+ while (fread(buf, 1, 3, f) > 0) {
+ if (gzip_header[0] == buf[0] && gzip_header[1] == buf[1] && gzip_header[2] == buf[2]) {
+ LOGL(LOG_SSENGINE, "match for %d %d %d found at %d\n", buf[0], buf[1], buf[2], ftell(f) - 3);
+ break;
+ } else {
+ fseek(f, -2, SEEK_CUR);
+ }
+ }
+ offset = ftell(f) - 3;
+ fclose(f);
+ return offset;
+}
+
+int SS_LoadPartition(const char *filename, FileInfo * file)
+{
+ size_t read = 0;
+ FILE *dev = NULL;
+ int i;
+
+ dev = fopen(filename, "rb");
+ if (dev == NULL) {
+ LOGE("failed to open partition \"%s\": %s\n", filename, strerror(errno));
+ return -1;
+ }
+
+ sha1_ctx_t sha_ctx;
+ sha1_init(&sha_ctx);
+
+ file->data = SS_Malloc(file->size);
+ if (file->data) {
+ read = fread(file->data, 1, file->size, dev);
+ LOGL(LOG_SSENGINE, "Partition size read %d\n", read);
+ sha1_update(&sha_ctx, file->data, read);
+ file->size = read;
+ }
+
+ const uint8_t sha_final[SHA_DIGEST_SIZE] = { 0, };
+ sha1_final(&sha_ctx, (uint32_t *) & sha_final);
+ for (i = 0; i < SHA_DIGEST_SIZE; ++i) {
+ file->sha1[i] = sha_final[i];
+ }
+ //LOGL(LOG_SSENGINE, "Final SHA of Source (%s)\n", sha_final);
+
+ file->st.st_mode = 0644;
+ file->st.st_uid = 0;
+ file->st.st_gid = 0;
+ fclose(dev);
+ return 0;
+}
+
+//extern int write_data_to_blkdev(char* dev_name, int blk_start, int blk_cnt, char* data);
+
+int SS_LoadFile(const char *filename, FileInfo * file)
+{
+
+ file->data = NULL;
+ //LOGL(LOG_SSENGINE,"SS_LoadFile --- [File name %s]\n",filename);
+
+ if (stat(filename, &file->st) != 0) {
+ LOGE("failed to stat \"%s\": %s\n", filename, strerror(errno));
+ return -1;
+ }
+
+ file->size = file->st.st_size;
+ file->data = SS_Malloc(file->size);
+ if (!file->data) {
+ LOGE("failed to allocate memory for \"%s\": %s\n", filename, strerror(errno));
+ return -1;
+ }
+
+ FILE *f = fopen(filename, "rb");
+ if (f == NULL) {
+ LOGE("failed to open \"%s\": %s\n", filename, strerror(errno));
+ SS_Free(file->data);
+ file->data = NULL;
+ return -1;
+ }
+
+ ssize_t bytes_read = fread(file->data, 1, file->size, f);
+ if (bytes_read != file->size) {
+ LOGE("short read of \"%s\" (%ld bytes of %ld)\n", filename, (long)bytes_read, (long)file->size);
+ SS_Free(file->data);
+ file->data = NULL;
+ fclose(f);
+ return -1;
+ }
+ fclose(f);
+ //LOGL(LOG_SSENGINE,"SS_LoadFile --- [bytes_read %d]\n",bytes_read);
+ sha1(file->data, file->size, (uint32_t *) file->sha1);
+ return 0;
+}
+
+extern int gvalid_session;
+extern void create_dir(char *pathname, int mode);
+#ifdef SUPPORT_CONTAINER
+//unzip source archive , apply patch from extracted delta folder and repack the source archive
+int SS_UpdateArchive(ua_dataSS_t * ua_dataSS, const char *source_filename, const char *target_filename,
+ const char *source_sha1_str, const char *target_sha1_str)
+{
+ FILE *fp;
+ char *line = NULL, *token = NULL, *source_file = NULL, *new_file = NULL, *dir_to_create = NULL, *patch_file = NULL;
+ char patch_path_full[MAX_FILE_PATH] = { 0, }; //absolute path for patches
+ char source_path_full[MAX_FILE_PATH] = { 0, }; //absolute path for uncompressed source files
+ char target_path_full[MAX_FILE_PATH] = { 0, };
+ char patchlist[MAX_FILE_PATH] = { 0, };
+ char cmd[2 * MAX_FILE_PATH] = { 0, };
+ size_t len = 0, read = 0;
+ int result = S_SS_SUCCESS;
+ uint8_t target_sha1[SHA_DIGEST_SIZE];
+ uint8_t source_sha1[SHA_DIGEST_SIZE] = { 0, };
+ FileInfo source_data = { 0, };
+ int backupsrc = -1;
+ SinkFn sink = NULL;
+ void *tok = NULL;
+ int output = -1;
+ char *outname = NULL;
+
+ if (ParseSha1(target_sha1_str, target_sha1) != 0) {
+ LOGE("failed to parse tgt-sha1 \"%s\"\n", target_sha1_str);
+ return E_SS_FAILURE;
+ }
+
+ if (0 == gvalid_session) {
+ if (ParseSha1(source_sha1_str, source_sha1) != 0) {
+ LOGE("failed to parse tgt-sha1 \"%s\"\n", source_sha1_str);
+ return E_SS_FAILURE;
+ }
+ if (SS_LoadFile(source_filename, &source_data) == 0) {
+ if (memcmp(source_data.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
+ LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Patch Can be applied\n");
+ if (source_data.data)
+ SS_Free(source_data.data);
+ } else if (memcmp(source_data.sha1, target_sha1, SHA_DIGEST_SIZE) == 0) {
+ LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Patch Already applied\n");
+ if (source_data.data)
+ SS_Free(source_data.data);
+ return S_SS_SUCCESS;
+ } else {
+ //Check for backup file SHA
+ SS_Free(source_data.data);
+ source_data.data = NULL;
+ LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Source was currupted, Try loading from backup source\n");
+ if (SS_LoadFile(SS_BACKUP_SOURCE, &source_data) == 0) {
+ if (memcmp(source_data.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
+ if (SS_CopyFile(NULL, SS_BACKUP_SOURCE, source_filename) != 0) {
+ LOGE("copy of backup to \"%s\" failed: %s\n", source_filename, strerror(errno));
+ SS_SetUpgradeState(E_SS_FSUPDATEFAILED);
+ if (source_data.data)
+ SS_Free(source_data.data);
+ return E_SS_FAILURE;
+ }
+ LOGL(LOG_SSENGINE,
+ "SS_UpdateDeltaFS - Patch Can be applied from using backup file as source\n");
+ } else {
+ SS_SetUpgradeState(E_SS_FSSRCCURRUPTED);
+ if (source_data.data)
+ SS_Free(source_data.data);
+ return E_SS_FAILURE;
+ }
+ } else {
+ SS_SetUpgradeState(E_SS_FSSRCCURRUPTED);
+ if (source_data.data)
+ SS_Free(source_data.data);
+ return E_SS_FAILURE;
+ }
+ }
+ } else {
+ LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Source was deleted, Try loading from backup source\n");
+ if (SS_LoadFile(SS_BACKUP_SOURCE, &source_data) == 0) {
+ if (memcmp(source_data.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
+ if (SS_CopyFile(NULL, SS_BACKUP_SOURCE, source_filename) != 0) {
+ LOGE("copy of backup to \"%s\" failed: %s\n", source_filename, strerror(errno));
+ SS_SetUpgradeState(E_SS_FSUPDATEFAILED);
+ if (source_data.data)
+ SS_Free(source_data.data);
+ return E_SS_FAILURE;
+ }
+ LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Patch Can be applied from using backup file as source\n");
+ } else {
+ SS_SetUpgradeState(E_SS_FSSRCCURRUPTED);
+ if (source_data.data)
+ SS_Free(source_data.data);
+ return E_SS_FAILURE;
+ }
+ } else {
+ SS_SetUpgradeState(E_SS_FSSRCCURRUPTED);
+ if (source_data.data)
+ SS_Free(source_data.data);
+ return E_SS_FAILURE;
+ }
+ }
+ }
+#ifndef ENHANCED_BSDIFF
+ backupsrc = SS_BackupSource(source_filename);
+ if (backupsrc != 0) {
+ LOGE("failed to Backup source File:[%s] \n", source_filename);
+ SS_SetUpgradeState(E_SS_FSSRCBACKUPFAILED);
+ return E_SS_FAILURE;
+ }
+#endif
+ //create workspace for processing container upgrade
+ SS_CreateFolder(NULL, SS_ARCHIVE_WORK_FOLDER);
+ SS_CreateFolder(NULL, SS_ARCHIVE_UNPACK_FOLDER);
+
+ //unpack the source container to the unpack workspace
+ snprintf(cmd, sizeof(cmd) - 1, "%s -qo %s -d %s", SS_UNZIP_COMMAND, source_filename, SS_ARCHIVE_UNPACK_FOLDER);
+ result = _system_cmd_wait(cmd);
+ if (result != S_SS_SUCCESS) {
+ LOGE("zip extraction for [%s] failed, code [%d]\n", cmd, result);
+ return E_SS_FAILURE;
+ }
+ //extract unpack scipt from delta.tar to process containers later
+ if (tar_get_item_size(ua_dataSS->update_data->ua_delta_path, SS_KERNEL_UNPACK_SCRIPT) > 0)
+ if (tar_extract_file(ua_dataSS->update_data->ua_delta_path, SS_KERNEL_UNPACK_SCRIPT, SS_KERN_UNPK_SCRIPT_PATH) >
+ 0)
+ LOGL(LOG_SSENGINE, "Extracted %s successfully\n", SS_KERNEL_UNPACK_SCRIPT);
+ else {
+ LOGE("Error in fn tar_extract_file for item %s", SS_KERNEL_UNPACK_SCRIPT);
+ SS_SetUpgradeState(E_SS_DELTA_IS_CORRUPT);
+ result = E_SS_FAILURE;
+ }
+ //move new tpk extracted in the delta folder to the work folder
+ new_file = strrchr(target_filename, '/');
+ snprintf(source_path_full, sizeof(source_path_full) - 1, "%s/%s", SS_ARCHIVE_DELTA_FOLDER, new_file + 1);
+ snprintf(target_path_full, sizeof(target_path_full) - 1, "%s/%s", SS_ARCHIVE_WORK_FOLDER, new_file + 1);
+
+ result = rename(source_path_full, target_path_full);
+ if (result != 0) {
+ LOGE("fatal error in moving %s to %s\n", source_path_full, target_path_full);
+ return E_SS_FAILURE;
+ }
+ snprintf(cmd, sizeof(cmd) - 1, "%s -qo %s -d %s", SS_UNZIP_COMMAND, target_path_full, SS_ARCHIVE_WORK_FOLDER);
+ result = _system_cmd_wait(cmd);
+ if (result != S_SS_SUCCESS) {
+ LOGE("zip extraction for [%s] failed, code [%d]\n", cmd, result);
+ return E_SS_FAILURE;
+ } else
+ LOGL(LOG_SSENGINE, "Thin zip extracted successfully\n");
+ // open the patch list and start iterating through the changes and the same files
+ snprintf(patchlist, MAX_FILE_PATH, "%s/%s", SS_ARCHIVE_DELTA_FOLDER, SS_CONTAINER_INFO_FILE);
+ fp = fopen(patchlist, "r");
+ if (!fp) {
+ LOGE("file open error [%s]\n", patchlist);
+ return E_SS_FAILURE;
+ }
+
+ while ((read = getline(&line, &len, fp)) != -1) {
+
+ switch (line[0]) { // '-' == Delete File, 's' == same File, 'c' == Changed File
+ case 's': //for same files case, just extract from old tpk to the work folder, update new tpk in the end
+ token = strtok(line, SS_SEPARATOR_TOKEN);
+
+ source_file = strtok(NULL, SS_NEWLINE_TOKEN);
+
+ snprintf(source_path_full, sizeof(source_path_full) - 1, "%s/%s", SS_ARCHIVE_UNPACK_FOLDER, source_file);
+ snprintf(target_path_full, sizeof(target_path_full) - 1, "%s/%s", SS_ARCHIVE_WORK_FOLDER, source_file);
+ LOGL(LOG_SSENGINE, "copy %s\n", source_file);
+ result = SS_MoveFile(NULL, source_path_full, target_path_full);
+ if (result != S_SS_SUCCESS) {
+ LOGE("fatal error [%d]\n", errno);
+ goto Cleanup;
+ }
+ break;
+ case 'c':
+ token = strtok(line, SS_SEPARATOR_TOKEN);
+
+ source_file = strtok(NULL, SS_SEPARATOR_TOKEN);
+ patch_file = strtok(NULL, SS_NEWLINE_TOKEN);
+
+ snprintf(source_path_full, sizeof(source_path_full) - 1, "%s/%s", SS_ARCHIVE_UNPACK_FOLDER, source_file);
+ snprintf(target_path_full, sizeof(target_path_full) - 1, "%s/%s", SS_ARCHIVE_WORK_FOLDER, source_file);
+ LOGL(LOG_SSENGINE, "copy %s\n", source_file);
+ result = SS_MoveFile(NULL, source_path_full, target_path_full);
+ if (result != S_SS_SUCCESS) {
+ LOGE("fatal error [%d]\n", errno);
+ }
+
+ snprintf(patch_path_full, sizeof(patch_path_full) - 1, "%s/%s", SS_ARCHIVE_DELTA_FOLDER, patch_file);
+ snprintf(source_path_full, sizeof(source_path_full) - 1, "%s/%s", SS_ARCHIVE_WORK_FOLDER, source_file);
+
+ {
+ // We write the decoded output to "<tgt-file>.patch".
+ //allocate some extra space to allow for concatinating ".patch" with the name
+ outname = (char *)SS_Malloc(strlen(source_path_full) + 10);
+ if (outname == NULL)
+ goto Cleanup;
+ strcpy(outname, source_path_full);
+ strcat(outname, ".patch");
+
+ output = open(outname, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
+ if (output < 0) {
+ LOGE("failed to open output file %s: %s\n", outname, strerror(errno));
+ SS_Free(outname);
+ goto Cleanup;
+ }
+ sink = ss_fileSink;
+ tok = &output;
+ }
+ result = SS_ApplyBsdiff((char *)source_path_full, outname, patch_path_full, sink, tok, NULL);
+ LOGL(LOG_SSENGINE, "GenerateTarget Output is %d and result is %d\n", output, result);
+ if (output >= 0) {
+ fsync(output);
+ close(output);
+ }
+
+ if (result != 0) {
+ LOGE("applying patch failed %s\n", source_path_full);
+ if (outname != NULL) {
+ unlink(outname);
+ }
+ goto Cleanup;
+ }
+ result = rename(outname, source_path_full);
+ if (result != 0) {
+ LOGE("fatal error %s\n", source_path_full);
+ goto Cleanup;
+ } else {
+ LOGL(LOG_SSENGINE, "Successfully applied patch for [%s]\n", source_path_full);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ new_file = strrchr(target_filename, '/');
+ snprintf(cmd, sizeof(cmd) - 1, "%s -p %s %s /opt/data/fota", SS_KERN_UNPK_SCRIPT_PATH, SS_ARCHIVE_WORK_FOLDER,
+ new_file + 1);
+ int ret = _system_cmd_wait(cmd);
+ LOGL(LOG_SSENGINE, "ret for %s is %d\n", cmd, ret);
+
+ //Apply diff between intermediate new tpk and the new tpk which contains central dir changes only
+ snprintf(patch_path_full, sizeof(patch_path_full) - 1, "%s/New_%s.delta", SS_ARCHIVE_DELTA_FOLDER, new_file + 1);
+ snprintf(source_path_full, sizeof(source_path_full) - 1, "%s/%s", SS_ARCHIVE_WORK_FOLDER, new_file + 1);
+
+ {
+ // We write the decoded output to "<tgt-file>.patch".
+ //allocate some extra space to allow for concatinating ".patch" with the name
+ outname = (char *)SS_Malloc(strlen(source_path_full) + 10);
+ if (outname == NULL)
+ return E_SS_FAILURE;
+ strcpy(outname, source_path_full);
+ strcat(outname, ".patch");
+
+ output = open(outname, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
+ if (output < 0) {
+ LOGE("failed to open output file %s: %s\n", outname, strerror(errno));
+ SS_Free(outname);
+ goto Cleanup;
+ }
+ sink = ss_fileSink;
+ tok = &output;
+ }
+ result = SS_ApplyBsdiff((char *)source_path_full, outname, patch_path_full, sink, tok, NULL);
+ LOGL(LOG_SSENGINE, "GenerateTarget Output is %d and result is %d\n", output, result);
+ if (output >= 0) {
+ fsync(output);
+ close(output);
+ }
+
+ if (result != 0) {
+ LOGE("applying patch failed %s\n", source_path_full);
+ if (outname != NULL) {
+ unlink(outname);
+ }
+ goto Cleanup;
+ }
+
+ if (SS_LoadFile(outname, &source_data) == 0)
+ result = memcmp(source_data.sha1, target_sha1, SHA_DIGEST_SIZE);
+ if (result != S_SS_SUCCESS) {
+ LOGE("patch did not produce expected sha1 \n");
+ SS_SetUpgradeState(E_SS_IMGSHA_MISMATCH);
+ goto Cleanup;
+ }
+
+ result = rename(outname, source_path_full);
+ if (result != 0) {
+ LOGE("fatal error %s\n", source_path_full);
+ goto Cleanup;
+ }
+ //Delete old file and copy patched archive, cant use rename as partitions may be different
+ unlink(source_filename);
+ if (result != 0) {
+ LOGE("failed to unlink [%s] code [%d]\n", source_filename, errno);
+ goto Cleanup;
+ }
+ result = (int)SS_CopyFile(NULL, source_path_full, target_filename);
+ if (result != S_SS_SUCCESS) {
+ LOGE("failed to copy file [%s] result [%d]\n", source_path_full, result);
+ goto Cleanup;
+ }
+
+ Cleanup:
+ fclose(fp);
+ if (line)
+ SS_Free(line);
+ if (outname)
+ SS_Free(outname);
+ SS_DeleteFile(NULL, SS_KERN_UNPK_SCRIPT_PATH);
+ SS_DeleteFile(NULL, SS_FIND_CMD_TARGET);
+ SS_DeleteFolder(NULL, SS_CONTAINER_WORKSPACE);
+ return result;
+}
+#endif
+/*!
+ *********************************************************************************
+ * SS_UpdateDeltaFS
+ *********************************************************************************
+ *
+ * @brief
+ * This is used to apply patch for a file during delta FS upgrade
+ *
+ *
+ * @param
+ *
+ * @return 0 - in case of success
+ * 1 - in case of error during patch application
+ *
+ *********************************************************************************
+ */
+
+int SS_UpdateDeltaFS(const char *source_filename, const char *target_filename,
+ const char *source_sha1_str, const char *target_sha1_str, int patch_data_size)
+{
+ uint8_t target_sha1[SHA_DIGEST_SIZE];
+ sha1_ctx_t ctx1;
+ int output;
+ int retry = 1;
+ int use_backup = 0;
+ char *outname = NULL;
+ int backupsrc = -1;
+ int result = 0;
+ FileInfo source_file;
+ uint8_t source_sha1[SHA_DIGEST_SIZE] = { 0, };
+
+ if (ParseSha1(target_sha1_str, target_sha1) != 0) {
+ LOGE("failed to parse tgt-sha1 \"%s\"\n", target_sha1_str);
+ return E_SS_FAILURE;
+ }
+
+ /*
+ if battery removed in between update gvalid_session becomes 0
+ need to check file integrity in that case
+ */
+ if (0 == gvalid_session) {
+ if (ParseSha1(source_sha1_str, source_sha1) != 0) {
+ LOGE("failed to parse tgt-sha1 \"%s\"\n", source_sha1_str);
+ return E_SS_FAILURE;
+ }
+ if (SS_LoadFile(source_filename, &source_file) == 0) {
+ if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
+ LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Patch Can be applied\n");
+ if (source_file.data)
+ SS_Free(source_file.data);
+ } else if (memcmp(source_file.sha1, target_sha1, SHA_DIGEST_SIZE) == 0) {
+ LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Patch Already applied\n");
+ if (source_file.data)
+ SS_Free(source_file.data);
+ return S_SS_SUCCESS;
+ } else {
+ //Check for backup file SHA
+ SS_Free(source_file.data);
+ source_file.data = NULL;
+ LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Source was currupted, Try loading from backup source\n");
+ if (SS_LoadFile(SS_BACKUP_SOURCE, &source_file) == 0) {
+ if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
+ if (SS_CopyFile(NULL, SS_BACKUP_SOURCE, source_filename) != S_SS_SUCCESS) {
+ LOGE("copy of backup to \"%s\" failed: %s\n", source_filename, strerror(errno));
+ SS_SetUpgradeState(E_SS_FSUPDATEFAILED);
+ if (source_file.data)
+ SS_Free(source_file.data);
+ return E_SS_FAILURE;
+ }
+ LOGL(LOG_SSENGINE,
+ "SS_UpdateDeltaFS - Patch Can be applied from using backup file as source\n");
+ } else {
+ SS_SetUpgradeState(E_SS_FSSRCCURRUPTED);
+ if (source_file.data)
+ SS_Free(source_file.data);
+ return E_SS_FAILURE;
+ }
+ } else {
+ SS_SetUpgradeState(E_SS_FSSRCCURRUPTED);
+ if (source_file.data)
+ SS_Free(source_file.data);
+ return E_SS_FAILURE;
+ }
+ }
+ } else {
+ LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Source was deleted, Try loading from backup source\n");
+ if (SS_LoadFile(SS_BACKUP_SOURCE, &source_file) == 0) {
+ if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
+ use_backup = 1;
+ LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Patch Can be applied from using backup file as source\n");
+ } else {
+ SS_SetUpgradeState(E_SS_FSSRCCURRUPTED);
+ if (source_file.data)
+ SS_Free(source_file.data);
+ return E_SS_FAILURE;
+ }
+ } else {
+ SS_SetUpgradeState(E_SS_FSSRCCURRUPTED);
+ if (source_file.data)
+ SS_Free(source_file.data);
+ return E_SS_FAILURE;
+ }
+ }
+ }
+ //Now proceed wit patch application since patch can be applied
+ do {
+ int enough_space = 0;
+ size_t free_space;
+ char *tok;
+
+ if (retry > 0) {
+ if (use_backup) {
+ tok = strrchr(source_filename, '/');
+ *tok = '\0';
+ }
+ SS_GetAvailableFreeSpace(NULL, source_filename, &free_space);
+ enough_space = (free_space > (256 << 10)) && // 256k (two-block) minimum
+ (free_space > (patch_data_size * 3 / 2)); // 50% margin of error
+ if (use_backup)
+ *tok = '/';
+ }
+
+ if (!use_backup) {
+#ifndef ENHANCED_BSDIFF
+ backupsrc = SS_BackupSource(source_filename);
+ if (backupsrc != 0) {
+ LOGE("failed to Backup source File:[%s] \n", source_filename);
+ SS_SetUpgradeState(E_SS_FSSRCBACKUPFAILED);
+ return E_SS_FAILURE;
+ }
+#endif
+ }
+ if (!enough_space) {
+ LOGL(LOG_SSENGINE, "For %s: free space %ld bytes; enough %d\n", source_filename, (long)free_space,
+ enough_space);
+ retry = 0;
+ use_backup = 1;
+ unlink(source_filename);
+ }
+ //LOGL(LOG_SSENGINE, "For %s: target %ld bytes; free space %ld bytes; enough %d\n",
+ // source_filename, (long)patch_data_size, (long)free_space, enough_space);
+ //LOGL(LOG_SSENGINE,"Generate Target Space availabitiy [%d]\n", enough_space);
+
+ SinkFn sink = NULL;
+ void *token = NULL;
+ output = -1;
+ outname = NULL;
+
+ {
+ // We write the decoded output to "<tgt-file>.patch".
+ //allocate some extra space to allow for concatinating ".patch" with the name
+ outname = (char *)SS_Malloc(strlen(target_filename) + 10);
+ if (outname == NULL)
+ return -1;
+ strcpy(outname, target_filename);
+ strcat(outname, ".patch");
+
+ output = open(outname, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
+ if (output < 0) {
+ if (errno == 2) {
+ char *dir_path = strrchr(outname, '/');
+ *dir_path = '\0';
+ // need to create directory as the target may be different from source
+ LOGL(LOG_SSENGINE, "need to create directory [%s]\n", outname);
+ create_dir(outname, 0755);
+ *dir_path = '/';
+ output = open(outname, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
+ if (output < 0) {
+ LOGE("failed to open output file %s: %s\n", outname, strerror(errno));
+ SS_Free(outname);
+ return E_SS_FAILURE;
+ }
+ }
+ }
+ sink = ss_fileSink;
+ token = &output;
+ }
+ sha1_init(&ctx1);
+ if (use_backup)
+ result = SS_ApplyBsdiff(SS_BACKUP_SOURCE, outname, SS_PATCHFILE_SOURCE, sink, token, &ctx1);
+ else
+ result = SS_ApplyBsdiff((char *)source_filename, outname, SS_PATCHFILE_SOURCE, sink, token, &ctx1);
+ if (output >= 0) {
+ fsync(output);
+ close(output);
+ }
+
+ if (result != 0) {
+ if (retry == 0) {
+ LOGE("applying patch failed result : [%d]\n", result);
+ SS_Free(outname);//wgid: 20739
+ SS_SetUpgradeState(E_SS_FSUPDATEFAILED);
+ return E_SS_FAILURE;
+ } else {
+ LOGE("applying patch failed; retrying\n");
+ SS_Free(outname);//wgid: 20739
+ }
+ if (outname != NULL) {
+ unlink(outname);
+ }
+ } else {
+ // succeeded; no need to retry
+ break;
+ }
+ } while (retry-- > 0);
+ const uint8_t current_target_sha1[SHA_DIGEST_SIZE] = { 0, };
+ sha1_final(&ctx1, (uint32_t *) & current_target_sha1);
+ if (memcmp(current_target_sha1, target_sha1, SHA_DIGEST_SIZE) != 0) {
+ LOGE("patch did not produce expected sha1\n");
+ SS_SetUpgradeState(E_SS_FSSHA_MISMATCH);
+ if (outname != NULL) {
+ SS_Free(outname);
+ }
+ return E_SS_FAILURE;
+ }
+ // Finally, rename the .patch file to replace the target file.
+#ifdef ENHANCED_BSDIFF
+ if (SS_rename1(outname, target_filename) != 0) {
+ LOGE("rename of .patch to \"%s\" failed: %s\n", target_filename, strerror(errno));
+ SS_SetUpgradeState(E_SS_FSUPDATEFAILED);
+ if (outname != NULL) {
+ SS_Free(outname);
+ }
+ return E_SS_FAILURE;
+ }
+#else
+ if (rename(outname, target_filename) != 0) {
+ LOGE("rename of .patch to \"%s\" failed: %s\n", target_filename, strerror(errno));
+ SS_SetUpgradeState(E_SS_FSUPDATEFAILED);
+ if (outname != NULL) {
+ SS_Free(outname);
+ }
+ return E_SS_FAILURE;
+ }
+ //remove source file if target is not same
+ if (strcmp(source_filename, target_filename) != 0)
+ unlink(source_filename);
+ SS_BackupSourceClear();
+#endif
+ SS_PatchSourceClear();
+ SS_Free(outname);
+
+ return result;
+}
+
+/*!
+ *********************************************************************************
+ * SS_UpdateDeltaKernel
+ *********************************************************************************
+ *
+ * @brief
+ * This is used to apply patch for kernel delta during delta Image upgrade
+ *
+ *
+ * @param
+ *
+ * @return 0 - in case of success
+ * 1 - in case of error during patch application
+ *
+ *********************************************************************************
+ */
+
+int SS_UpdateDeltaKernel(ua_dataSS_t * ua_dataSS, int (*write_to_blkdev) (char *, int, int, char *))
+{
+ uint8_t target_sha1[SHA_DIGEST_SIZE];
+ uint8_t source_sha1[SHA_DIGEST_SIZE];
+ FileInfo source_file;
+ int result = S_SS_SUCCESS;
+ int blk_cnt, read_count = 0;
+ int blk_start = 0;
+ int backupsrc = -1;
+ int use_backup_img = -1;
+ FILE *fp = NULL, *wp = NULL, *kp = NULL;
+ int i = 0, j = 0, file_len = 0;
+ char *magic = NULL, *file_name = NULL, *buf = NULL, a = '0';
+ char cmd[1024] = { 0, };
+ char source_filename[MAX_FILE_PATH] = { 0, };
+ char part_filename[MAX_FILE_PATH] = { 0, };
+ int file_num = 0;
+ SinkFn sink = NULL;
+ void *tok = NULL;
+ int output = -1;
+ char *outname = NULL;
+ //Kernel Parts are created on unpacking kernel which is then used to apply delta
+ char *kernel_parts[] = { "decompression_code",
+ "piggy.gz",
+ "padding_piggy",
+ "piggy_trailer"
+ };
+
+ if (ParseSha1(ua_dataSS->update_cfg->target_sha1, target_sha1) != 0) {
+ LOGE("failed to parse tgt-sha1 \"%s\"\n", ua_dataSS->update_cfg->target_sha1);
+ return E_SS_FAILURE;
+ }
+
+ source_file.size = ua_dataSS->update_cfg->soure_img_size;
+ source_file.data = NULL;
+ if (0 == gvalid_session) {
+
+ if (ParseSha1(ua_dataSS->update_cfg->soure_sha1, source_sha1) != 0) {
+ LOGE("failed to parse Src-sha1 \"%s\"\n", ua_dataSS->update_cfg->soure_sha1);
+ return E_SS_FAILURE;
+ }
+
+ if (SS_LoadPartition(ua_dataSS->parti_info->ua_blk_name, &source_file) == 0) {
+ if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
+ LOGL(LOG_SSENGINE, "SS_UpdateDeltaIMG - Patch Can be applied\n");
+
+ } else if (memcmp(source_file.sha1, target_sha1, SHA_DIGEST_SIZE) == 0) {
+ LOGL(LOG_SSENGINE, "SS_UpdateDeltaIMG - Patch Already applied\n");
+ SS_Free(source_file.data);
+ return S_SS_SUCCESS;
+ } else {
+ SS_Free(source_file.data);
+ source_file.data = NULL;
+ LOGL(LOG_SSENGINE, "SS_UpdateDeltaIMG - Source was currupted, Try loading from backup source\n");
+ if (SS_LoadPartition(SS_BACKUP_SOURCE, &source_file) == 0) {
+ if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
+ use_backup_img = 1;
+
+ LOGL(LOG_SSENGINE,
+ "SS_UpdateDeltaIMG - Patch Can be applied from using backup file as source\n");
+ } else {
+ SS_SetUpgradeState(E_SS_IMGSRCCURRUPTED);
+ SS_Free(source_file.data);
+ return E_SS_FAILURE;
+ }
+ }
+ }
+ }
+ } else { //in case of kernel delta need to copy kernel data from blk to buffer
+ if (SS_LoadPartition(ua_dataSS->parti_info->ua_blk_name, &source_file) != 0) {
+ SS_SetUpgradeState(E_SS_IMGSRCCURRUPTED);
+ LOGE("Fatal Error : Kernel block is corrupted\n");
+ return E_SS_FAILURE;
+ }
+ }
+ if (use_backup_img == -1) {
+ backupsrc = SS_BackupSource(ua_dataSS->parti_info->ua_blk_name);
+ if (backupsrc != 0) {
+ LOGE("failed to Backup source File:[%s] \n", ua_dataSS->parti_info->ua_blk_name);
+ SS_SetUpgradeState(E_SS_IMGSRCBACKUPFAILED);
+ return E_SS_FAILURE;
+ }
+ }
+ //Cleanup workspace and copy helper executables to it before proceeding
+ SS_DeleteFolder(NULL, SS_KERNEL_WORKSPACE);
+ create_dir(SS_KERNEL_WORKSPACE, 0755);
+ SS_CopyFile(NULL, SS_GZIP_SOURCE, SS_GZIP_TARGET);
+ SS_CopyFile(NULL, SS_STAT_SOURCE, SS_STAT_TARGET);
+ SS_CopyFile(NULL, SS_DD_SOURCE, SS_DD_TARGET);
+
+ if (tar_get_item_size(ua_dataSS->update_data->ua_delta_path, SS_KERNEL_UNPACK_SCRIPT) > 0)
+ if (tar_extract_file(ua_dataSS->update_data->ua_delta_path, SS_KERNEL_UNPACK_SCRIPT, SS_KERN_UNPK_SCRIPT_PATH) >
+ 0)
+ LOGL(LOG_SSENGINE, "Extracted %s successfully\n", SS_KERNEL_UNPACK_SCRIPT);
+ else {
+ LOGE("Error in fn tar_extract_file for item %s", SS_KERNEL_UNPACK_SCRIPT);
+ SS_SetUpgradeState(E_SS_DELTA_IS_CORRUPT);
+ result = E_SS_FAILURE;
+ goto Cleanup;
+ } else {
+ LOGE("Error size is not positive for item %s", SS_KERNEL_UNPACK_SCRIPT);
+ SS_SetUpgradeState(E_SS_DELTA_IS_CORRUPT);
+ result = E_SS_FAILURE;
+ goto Cleanup;
+ }
+ //Now write the kernel data to the workplace and start applying patch
+ snprintf(source_filename, sizeof(source_filename) - 1, "%s/%s", SS_KERNEL_WORKSPACE, SS_KERNEL_NAME);
+ fp = fopen(source_filename, "w");
+ if (!fp) {
+ LOGE("file open error [%s] code [%d]\n", source_filename, errno);
+ SS_Free(source_file.data);
+ result = E_SS_FAILURE;
+ goto Cleanup;
+ }
+ //write source kernel data to workspace
+ read_count = fwrite(source_file.data, 1, source_file.size, fp);
+ if (read_count != source_file.size) {
+ LOGE("file write error read_count = %d for [%s]\n", read_count, source_filename);
+ SS_Free(source_file.data);
+ result = E_SS_FAILURE;
+ goto Cleanup;
+ }
+ SS_Free(source_file.data);
+ fclose(fp);
+ fp = NULL;//wgid: 59313
+
+ //Unpack source kernel
+ int offset = getOffset(source_filename);
+ if(offset < 0){
+ LOGE("Failed to get offset\n");
+ result = E_SS_FAILURE;
+ goto Cleanup;
+ }
+ snprintf(cmd, sizeof(cmd) - 1, "%s -u %s %s %d", SS_KERN_UNPK_SCRIPT_PATH, SS_KERNEL_WORKSPACE, SS_KERNEL_NAME,
+ offset);
+ int ret = _system_cmd_wait(cmd);
+ LOGL(LOG_SSENGINE, "ret for %s is %d\n", cmd, ret);
+
+ //open delta file, extract kernel delta parts and apply patch to previously unpacked kernel
+ fp = fopen(SS_PATCHFILE_SOURCE, "r");
+ if (fp == NULL) {
+ LOGE("Failed to open kernel delta patch\n");
+ result = E_SS_FAILURE;
+ goto Cleanup;
+ }
+ //read kernel delta header for delta names and size
+ buf = SS_Malloc(SS_KERNEL_DELTA_HEADER);
+ if(!buf){//wgid: 13099
+ LOGE("Failed to allocate memory\n");
+ result = E_SS_MALLOC_ERROR;
+ goto Cleanup;
+ }
+ fread(buf, 1, SS_KERNEL_DELTA_HEADER, fp);
+ magic = strtok(buf, ":");
+ file_num = atoi(strtok(NULL, ":"));
+
+ //adjust offset to start of data section before proceeding
+ fseek(fp, SS_KERNEL_DELTA_HEADER, SEEK_SET);
+
+ while (file_num-- > 0) {
+ file_name = strtok(NULL, ":");
+ file_len = atoi(strtok(NULL, ":"));
+ j = file_len;
+ snprintf(source_filename, sizeof(source_filename) - 1, "%s/%s_unpacked/%s", SS_KERNEL_WORKSPACE, SS_KERNEL_NAME,
+ file_name);
+ snprintf(part_filename, sizeof(part_filename) - 1, "%s/%s", SS_KERNEL_WORKSPACE, file_name);
+ wp = fopen(part_filename, "w");
+ while (j-- > 0) {
+ a = fgetc(fp);
+ fputc(a, wp);
+ }
+ fclose(wp);
+
+ //apply bspatch to the unpacked kernel parts
+
+ {
+ // We write the decoded output to "<tgt-file>.patch".
+ //allocate some extra space to allow for concatinating ".patch" with the name
+ outname = (char *)SS_Malloc(strlen(source_filename) + 10);
+ if (outname == NULL) {
+ SS_SetUpgradeState(E_SS_MALLOC_ERROR);
+ result = E_SS_FAILURE;
+ goto Cleanup;
+ }
+ strcpy(outname, source_filename);
+ strcat(outname, ".patch");
+
+ output = open(outname, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
+ if (output < 0) {
+ LOGE("failed to open output file %s: %s\n", outname, strerror(errno));
+ SS_Free(outname);
+ result = E_SS_FAILURE;
+ goto Cleanup;
+ }
+ sink = ss_fileSink;
+ tok = &output;
+ }
+ result = SS_ApplyBsdiff(source_filename, outname, part_filename, sink, tok, NULL);
+ LOGL(LOG_SSENGINE, "GenerateTarget Output is %d and result is %d\n", output, result);
+ if (output >= 0) {
+ fsync(output);
+ close(output);
+ }
+
+ if (result != S_SS_SUCCESS) {
+ LOGE("applying patch failed %s\n", source_filename);
+ if (outname != NULL) {
+ unlink(outname);
+ }
+ goto Cleanup;
+ }
+ result = rename(outname, source_filename);
+ if (result != S_SS_SUCCESS) {
+ LOGE("fatal error %s\n", source_filename);
+ goto Cleanup;
+ }
+ if (strcmp(file_name, "piggy") == 0) {
+ snprintf(cmd, sizeof(cmd) - 1,
+ "%s/gzip -n -9 -c %s/%s/%s > %s/%s/%s.gz",
+ SS_KERNEL_WORKSPACE, SS_KERNEL_WORKSPACE, SS_KERNEL_UNPACK_DIR, file_name,
+ SS_KERNEL_WORKSPACE, SS_KERNEL_UNPACK_DIR, file_name);
+ result = _system_cmd_wait(cmd);
+ LOGL(LOG_SSENGINE, "ret for %s = %d\n", cmd, result);
+ unlink(source_filename);
+ }
+ unlink(part_filename);
+ }
+ //open new kernel file and append kernel parts to it in
+ snprintf(source_filename, sizeof(source_filename) - 1, "%s/%s", SS_KERNEL_WORKSPACE, SS_KERNEL_TARGET_NAME);
+ kp = fopen(source_filename, "w");
+ for (i = 0; i < 4; i++) {
+ snprintf(part_filename, sizeof(part_filename) - 1, "%s/%s/%s", SS_KERNEL_WORKSPACE, SS_KERNEL_UNPACK_DIR,
+ kernel_parts[i]);
+ wp = fopen(part_filename, "r");
+ fseek(wp, SEEK_SET, SEEK_END);
+ j = ftell(wp);
+ fseek(wp, SEEK_SET, SEEK_SET);
+ while (j-- > 0) {
+ a = fgetc(wp);
+ if(a != EOF)//wgid: 4428
+ fputc(a, kp);
+ else
+ break;
+ }
+ fclose(wp);
+ unlink(part_filename);
+ }
+ fclose(fp);
+ fp = NULL;
+ fclose(kp);
+
+ if (SS_LoadFile(source_filename, &source_file) == 0)
+ result = memcmp(source_file.sha1, target_sha1, SHA_DIGEST_SIZE);
+ if (result != S_SS_SUCCESS) {
+ LOGE("patch did not produce expected sha1 \n");
+ SS_SetUpgradeState(E_SS_IMGSHA_MISMATCH);
+ goto Cleanup;
+ }
+ //Considering EMMC partition by deafult
+
+ blk_cnt = ((ua_dataSS->update_cfg->target_img_size - 1) / SECTOR_SIZE) + 1;
+ result = write_to_blkdev((char *)ua_dataSS->parti_info->ua_blk_name, blk_start, blk_cnt, (char *)source_file.data);
+ if (result != S_SS_SUCCESS) {
+ LOGE("write of patched data to %s failed\n", ua_dataSS->parti_info->ua_blk_name); // All returns should go to CLEAN UP.
+ SS_SetUpgradeState(E_SS_IMGFLASHWRITEFAIL);
+ goto Cleanup;
+ }
+
+ Cleanup:
+ SS_BackupSourceClear();
+ SS_PatchSourceClear();
+ SS_DeleteFile(NULL, SS_KERN_UNPK_SCRIPT_PATH);
+ SS_DeleteFolder(NULL, SS_KERNEL_WORKSPACE);
+ SS_Free(buf);
+ SS_Free(outname);//wgid: 20740
+ if (result == S_SS_SUCCESS)
+ LOGL(LOG_SSENGINE, "************* SS_UpdateDeltaKernel SUCCESS *****************\n");
+ else{
+ LOGL(LOG_SSENGINE, "************* SS_UpdateDeltaKernel FAILED *****************\n");
+ if(fp)
+ fclose(fp);//wgid:14711
+ }
+ return result;
+
+}
+
+/*!
+ *********************************************************************************
+ * SS_UpdateDeltaIMG
+ *********************************************************************************
+ *
+ * @brief
+ * This is used to apply patch for an image during delta Image upgrade
+ *
+ *
+ * @param
+ *
+ * @return 0 - in case of success
+ * 1 - in case of error during patch application
+ *
+ *********************************************************************************
+ */
+
+int SS_UpdateDeltaIMG(ua_dataSS_t * ua_dataSS, int (*write_to_blkdev) (char *, int, int, char *))
+{
+ uint8_t target_sha1[SHA_DIGEST_SIZE];
+ uint8_t source_sha1[SHA_DIGEST_SIZE];
+ const uint8_t current_target_sha1[SHA_DIGEST_SIZE];
+ FileInfo source_file;
+ sha1_ctx_t ctx1;
+ MemorySinkInfo msi;
+ int result = S_SS_SUCCESS;
+ int blk_cnt;
+ int blk_start = 0;
+ int backupsrc = -1;
+ int use_backup_img = -1;
+ int fd = -1;
+ if (ParseSha1(ua_dataSS->update_cfg->target_sha1, target_sha1) != 0) {
+ LOGE("failed to parse tgt-sha1 \"%s\"\n", ua_dataSS->update_cfg->target_sha1);
+ return E_SS_FAILURE;
+ }
+
+ source_file.size = ua_dataSS->update_cfg->soure_img_size;
+ source_file.data = NULL;
+ if (0 == gvalid_session) {
+
+ if (ParseSha1(ua_dataSS->update_cfg->soure_sha1, source_sha1) != 0) {
+ LOGE("failed to parse Src-sha1 \"%s\"\n", ua_dataSS->update_cfg->soure_sha1);
+ return E_SS_FAILURE;
+ }
+
+ if (SS_LoadPartition(ua_dataSS->parti_info->ua_blk_name, &source_file) == 0) {
+ if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
+ LOGL(LOG_SSENGINE, "SS_UpdateDeltaIMG - Patch Can be applied\n");
+ SS_Free(source_file.data);
+ } else if (memcmp(source_file.sha1, target_sha1, SHA_DIGEST_SIZE) == 0) {
+ LOGL(LOG_SSENGINE, "SS_UpdateDeltaIMG - Patch Already applied\n");
+ SS_Free(source_file.data);
+ return S_SS_SUCCESS;
+ } else {
+ SS_Free(source_file.data);
+ source_file.data = NULL;
+ LOGL(LOG_SSENGINE, "SS_UpdateDeltaIMG - Source was currupted, Try loading from backup source\n");
+ if (SS_LoadPartition(SS_BACKUP_SOURCE, &source_file) == 0) {
+ if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
+ use_backup_img = 1;
+ SS_Free(source_file.data);
+ LOGL(LOG_SSENGINE,
+ "SS_UpdateDeltaIMG - Patch Can be applied from using backup file as source\n");
+ } else {
+ SS_SetUpgradeState(E_SS_IMGSRCCURRUPTED);
+ SS_Free(source_file.data);
+ return E_SS_FAILURE;
+ }
+ }
+ }
+ }
+ }
+ if (use_backup_img == -1) {
+ backupsrc = SS_BackupSource(ua_dataSS->parti_info->ua_blk_name);
+ if (backupsrc != 0) {
+ LOGE("failed to Backup source File:[%s] \n", ua_dataSS->parti_info->ua_blk_name);
+ SS_SetUpgradeState(E_SS_IMGSRCBACKUPFAILED);
+ return E_SS_FAILURE;
+ }
+ }
+ SinkFn sink = NULL;
+ void *token = NULL;
+
+ blk_cnt = ((ua_dataSS->update_cfg->target_img_size - 1) / SECTOR_SIZE) + 1;
+
+ msi.buffer = SS_Malloc(blk_cnt * SECTOR_SIZE);
+ if (msi.buffer == NULL) {
+ LOGE("failed to alloc %ld bytes for output\n", (long)ua_dataSS->update_cfg->target_img_size);
+ SS_SetUpgradeState(E_SS_MALLOC_ERROR);
+ return E_SS_FAILURE;
+ }
+ msi.pos = 0;
+ msi.size = ua_dataSS->update_cfg->target_img_size;
+ sink = ss_memorySink;
+ token = &msi;
+
+ sha1_init(&ctx1);
+ //if souce was corrupted, use backup to apply diff
+ if (use_backup_img == -1)
+ result =
+ SS_ApplyBsdiff((char *)ua_dataSS->parti_info->ua_blk_name, NULL, SS_PATCHFILE_SOURCE, sink, token, &ctx1);
+ else
+ result = SS_ApplyBsdiff(SS_BACKUP_SOURCE, NULL, SS_PATCHFILE_SOURCE, sink, token, &ctx1);
+ if (result != S_SS_SUCCESS) {
+ LOGE("failed to SS_ApplyBsdiff\n");
+ SS_SetUpgradeState(E_SS_IMGRECOVERYWRITEFAILED);
+ goto Cleanup;
+ }
+
+ sha1_final(&ctx1, (uint32_t *) & current_target_sha1);
+ result = memcmp(current_target_sha1, target_sha1, SHA_DIGEST_SIZE);
+ if (result != S_SS_SUCCESS) {
+ LOGE("patch did not produce expected sha1 \n");
+ SS_SetUpgradeState(E_SS_IMGSHA_MISMATCH);
+ goto Cleanup;
+ }
+ //Considering EMMC partition by deafult
+
+ if (ua_dataSS->update_cfg->update_type == DELTA_IMG) {
+ blk_cnt = ((ua_dataSS->update_cfg->target_img_size - 1) / SECTOR_SIZE) + 1;
+ result = write_to_blkdev((char *)ua_dataSS->parti_info->ua_blk_name, blk_start, blk_cnt, (char *)msi.buffer);
+ if (result != S_SS_SUCCESS) {
+ LOGE("write of patched data to %s failed\n", ua_dataSS->parti_info->ua_blk_name); // All returns should go to CLEAN UP.
+ SS_SetUpgradeState(E_SS_IMGFLASHWRITEFAIL);
+ goto Cleanup;
+ }
+ } else if (ua_dataSS->update_cfg->update_type == EXTRA && ua_dataSS->update_data->ua_temp_path) {
+ fd = open(ua_dataSS->update_data->ua_temp_path, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
+ if (fd < 0) {
+ LOGE("failed to open %s for write: %s\n", ua_dataSS->update_data->ua_temp_path, strerror(errno));
+ SS_SetUpgradeState(E_SS_IMGRECOVERYWRITEFAILED);
+ result = E_SS_FAILURE;
+ goto Cleanup;
+ }
+ result = SS_WriteFile(NULL, fd, 0, msi.buffer, msi.size);
+ if (result != S_SS_SUCCESS) {
+ LOGE("failed to write\n");
+ SS_SetUpgradeState(E_SS_IMGRECOVERYWRITEFAILED);
+ goto Cleanup;
+ }
+ fsync(fd);
+ }
+ else {
+ SS_SetUpgradeState(E_SS_IMGUPDATEFAILED);
+ result = E_SS_FAILURE;
+ LOGE("failed to apply patch - Invalid Update type params \n");
+ }
+
+ Cleanup:
+ SS_BackupSourceClear();
+ SS_PatchSourceClear();
+ if (msi.buffer)
+ SS_Free(msi.buffer);
+ if (fd >= 0)
+ close(fd);
+ if (result == S_SS_SUCCESS)
+ LOGL(LOG_SSENGINE, "************* SS_UpdateDeltaIMG SUCCESS *****************\n");
+ return result;
+
+}
--- /dev/null
+/*
+ * libtota
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _SS_PATCHDELTA_H
+#define _SS_PATCHDELTA_H
+
+#include <stdint.h>
+#include "sha1.h"
+#include "unistd.h"
+#include "fcntl.h"
+#include "errno.h"
+#include "SS_Engine_Update.h"
+
+//#define ENHANCED_BSDIFF
+#define SS_UPDATE_FS 0
+#define SS_UPDATE_IMG 1
+//#define SHA_DIGEST_SIZE 20
+typedef struct {
+ int type;
+ ssize_t size;
+ char *data;
+} Value;
+typedef struct _Patch {
+ uint8_t sha1[SHA_DIGEST_SIZE];
+ const char *patch_filename;
+} Patch;
+
+typedef struct _FileInfo {
+ unsigned char sha1[20]; //SHA_DIGEST_SIZE 20
+ unsigned char *data;
+ int size;
+ struct stat st;
+} FileInfo;
+
+typedef ssize_t(*SinkFn) (unsigned char *, ssize_t, void *);
+
+int ParseSha1(const char *str, uint8_t * digest);
+
+void ShowBSDiffLicense();
+int ApplyBSDiffPatch(const unsigned char *old_data, ssize_t old_size,
+ const Value * patch, ssize_t patch_offset, SinkFn sink, void *token, sha1_ctx_t * ctx1);
+int ApplyBSDiffPatchMem(const unsigned char *old_data, ssize_t old_size,
+ const Value * patch, ssize_t patch_offset, unsigned char **new_data, ssize_t * new_size);
+//int ApplyOptimizedBSDiffPatch(const unsigned char* old_data,void* token,
+// const Value* patch, SinkFn sink,sha1_ctx_t* ctx1);
+
+int SS_LoadPartition(const char *filename, FileInfo * file);
+int SS_LoadFile(const char *filename, FileInfo * file);
+extern void SS_SetUpgradeState(int Val);
+extern long SS_GetAvailableFreeSpace(void *pbUserData, const char *partition_name, SS_UINT32 * available_flash_size);
+extern int SS_BackupSource(const char *source_filename);
+extern int SS_ApplyBsdiff(char *oldfile, char *newfile, char *patch, SinkFn sink, void *token, sha1_ctx_t * ctx1);
+extern int SS_BackupSourceClear();
+extern int SS_PatchSourceClear();
+extern long SS_WriteFile(void *pbUserData,
+ long wHandle, SS_UINT32 dwPosition, unsigned char *pbBuffer, SS_UINT32 dwSize);
+extern void SS_Free(void * pMemBlock);
+extern long SS_CopyFile(void * pbUserData, const char * strFromPath, const char * strToPath);
+extern long SS_DeleteFolder(void * pbUserData, const char * strPath);
+extern long SS_DeleteFile(void * pbUserData, const char * strPath);
+extern int tar_get_item_size(char * tar, char * item);
+extern int tar_extract_file(char * tar, char * item, char * pathname);
+extern int _system_cmd_wait(const char * command);
+#endif
#include "SS_Common.h"
#include "fota_common.h"
#include "SS_UPI.h"
-#include "ss_patchdelta.h"
+#include "SS_PatchDelta.h"
#include "SS_Engine_Errors.h"
#include "SS_FSUpdate.h"
--- /dev/null
+/*
+ * sha1.c
+ *
+ * an implementation of the Secure Hash Algorithm v.1 (SHA-1),
+ * specified in FIPS 180-1
+ *
+ * David A. McGrew
+ * Cisco Systems, Inc.
+ */
+
+/*
+ *
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * Neither the name of the Cisco Systems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include "sha1.h"
+
+
+
+/* SN == Rotate left N bits */
+#define S1(X) ((X << 1) | (X >> 31))
+#define S5(X) ((X << 5) | (X >> 27))
+#define S30(X) ((X << 30) | (X >> 2))
+
+#define f0(B,C,D) ((B & C) | (~B & D))
+#define f1(B,C,D) (B ^ C ^ D)
+#define f2(B,C,D) ((B & C) | (B & D) | (C & D))
+#define f3(B,C,D) (B ^ C ^ D)
+
+
+
+/*
+ * nota bene: the variable K0 appears in the curses library, so we
+ * give longer names to these variables to avoid spurious warnings
+ * on systems that uses curses
+ */
+
+uint32_t SHA_K0 = 0x5A827999; /* Kt for 0 <= t <= 19 */
+uint32_t SHA_K1 = 0x6ED9EBA1; /* Kt for 20 <= t <= 39 */
+uint32_t SHA_K2 = 0x8F1BBCDC; /* Kt for 40 <= t <= 59 */
+uint32_t SHA_K3 = 0xCA62C1D6; /* Kt for 60 <= t <= 79 */
+
+void
+sha1(const uint8_t *msg, int octets_in_msg, uint32_t hash_value[5]) {
+ sha1_ctx_t ctx;
+
+ sha1_init(&ctx);
+ sha1_update(&ctx, msg, octets_in_msg);
+ sha1_final(&ctx, hash_value);
+
+}
+
+/*
+ * sha1_core(M, H) computes the core compression function, where M is
+ * the next part of the message (in network byte order) and H is the
+ * intermediate state { H0, H1, ...} (in host byte order)
+ *
+ * this function does not do any of the padding required in the
+ * complete SHA1 function
+ *
+ * this function is used in the SEAL 3.0 key setup routines
+ * (crypto/cipher/seal.c)
+ */
+
+void
+sha1_core(const uint32_t M[16], uint32_t hash_value[5]) {
+ uint32_t H0;
+ uint32_t H1;
+ uint32_t H2;
+ uint32_t H3;
+ uint32_t H4;
+ uint32_t W[80];
+ uint32_t A, B, C, D, E, TEMP;
+ int t;
+
+ /* copy hash_value into H0, H1, H2, H3, H4 */
+ H0 = hash_value[0];
+ H1 = hash_value[1];
+ H2 = hash_value[2];
+ H3 = hash_value[3];
+ H4 = hash_value[4];
+
+ /* copy/xor message into array */
+
+ W[0] = be32_to_cpu(M[0]);
+ W[1] = be32_to_cpu(M[1]);
+ W[2] = be32_to_cpu(M[2]);
+ W[3] = be32_to_cpu(M[3]);
+ W[4] = be32_to_cpu(M[4]);
+ W[5] = be32_to_cpu(M[5]);
+ W[6] = be32_to_cpu(M[6]);
+ W[7] = be32_to_cpu(M[7]);
+ W[8] = be32_to_cpu(M[8]);
+ W[9] = be32_to_cpu(M[9]);
+ W[10] = be32_to_cpu(M[10]);
+ W[11] = be32_to_cpu(M[11]);
+ W[12] = be32_to_cpu(M[12]);
+ W[13] = be32_to_cpu(M[13]);
+ W[14] = be32_to_cpu(M[14]);
+ W[15] = be32_to_cpu(M[15]);
+ TEMP = W[13] ^ W[8] ^ W[2] ^ W[0]; W[16] = S1(TEMP);
+ TEMP = W[14] ^ W[9] ^ W[3] ^ W[1]; W[17] = S1(TEMP);
+ TEMP = W[15] ^ W[10] ^ W[4] ^ W[2]; W[18] = S1(TEMP);
+ TEMP = W[16] ^ W[11] ^ W[5] ^ W[3]; W[19] = S1(TEMP);
+ TEMP = W[17] ^ W[12] ^ W[6] ^ W[4]; W[20] = S1(TEMP);
+ TEMP = W[18] ^ W[13] ^ W[7] ^ W[5]; W[21] = S1(TEMP);
+ TEMP = W[19] ^ W[14] ^ W[8] ^ W[6]; W[22] = S1(TEMP);
+ TEMP = W[20] ^ W[15] ^ W[9] ^ W[7]; W[23] = S1(TEMP);
+ TEMP = W[21] ^ W[16] ^ W[10] ^ W[8]; W[24] = S1(TEMP);
+ TEMP = W[22] ^ W[17] ^ W[11] ^ W[9]; W[25] = S1(TEMP);
+ TEMP = W[23] ^ W[18] ^ W[12] ^ W[10]; W[26] = S1(TEMP);
+ TEMP = W[24] ^ W[19] ^ W[13] ^ W[11]; W[27] = S1(TEMP);
+ TEMP = W[25] ^ W[20] ^ W[14] ^ W[12]; W[28] = S1(TEMP);
+ TEMP = W[26] ^ W[21] ^ W[15] ^ W[13]; W[29] = S1(TEMP);
+ TEMP = W[27] ^ W[22] ^ W[16] ^ W[14]; W[30] = S1(TEMP);
+ TEMP = W[28] ^ W[23] ^ W[17] ^ W[15]; W[31] = S1(TEMP);
+
+ /* process the remainder of the array */
+ for (t=32; t < 80; t++) {
+ TEMP = W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16];
+ W[t] = S1(TEMP);
+ }
+
+ A = H0; B = H1; C = H2; D = H3; E = H4;
+
+ for (t=0; t < 20; t++) {
+ TEMP = S5(A) + f0(B,C,D) + E + W[t] + SHA_K0;
+ E = D; D = C; C = S30(B); B = A; A = TEMP;
+ }
+ for ( ; t < 40; t++) {
+ TEMP = S5(A) + f1(B,C,D) + E + W[t] + SHA_K1;
+ E = D; D = C; C = S30(B); B = A; A = TEMP;
+ }
+ for ( ; t < 60; t++) {
+ TEMP = S5(A) + f2(B,C,D) + E + W[t] + SHA_K2;
+ E = D; D = C; C = S30(B); B = A; A = TEMP;
+ }
+ for ( ; t < 80; t++) {
+ TEMP = S5(A) + f3(B,C,D) + E + W[t] + SHA_K3;
+ E = D; D = C; C = S30(B); B = A; A = TEMP;
+ }
+
+ hash_value[0] = H0 + A;
+ hash_value[1] = H1 + B;
+ hash_value[2] = H2 + C;
+ hash_value[3] = H3 + D;
+ hash_value[4] = H4 + E;
+
+ return;
+}
+
+void
+sha1_init(sha1_ctx_t *ctx) {
+
+ /* initialize state vector */
+ ctx->H[0] = 0x67452301;
+ ctx->H[1] = 0xefcdab89;
+ ctx->H[2] = 0x98badcfe;
+ ctx->H[3] = 0x10325476;
+ ctx->H[4] = 0xc3d2e1f0;
+
+ /* indicate that message buffer is empty */
+ ctx->octets_in_buffer = 0;
+
+ /* reset message bit-count to zero */
+ ctx->num_bits_in_msg = 0;
+
+}
+
+void
+sha1_update(sha1_ctx_t *ctx, const uint8_t *msg, int octets_in_msg) {
+ int i;
+ uint8_t *buf = (uint8_t *)ctx->M;
+
+ /* update message bit-count */
+ ctx->num_bits_in_msg += octets_in_msg * 8;
+
+ /* loop over 16-word blocks of M */
+ while (octets_in_msg > 0) {
+
+ if (octets_in_msg + ctx->octets_in_buffer >= 64) {
+
+ /*
+ * copy words of M into msg buffer until that buffer is full,
+ * converting them into host byte order as needed
+ */
+ octets_in_msg -= (64 - ctx->octets_in_buffer);
+ for (i=ctx->octets_in_buffer; i < 64; i++)
+ buf[i] = *msg++;
+ ctx->octets_in_buffer = 0;
+
+ /* process a whole block */
+
+ //debug_print(mod_sha1, "(update) running sha1_core()", NULL);
+
+ sha1_core(ctx->M, ctx->H);
+
+ } else {
+
+ //debug_print(mod_sha1, "(update) not running sha1_core()", NULL);
+
+ for (i=ctx->octets_in_buffer;
+ i < (ctx->octets_in_buffer + octets_in_msg); i++)
+ buf[i] = *msg++;
+ ctx->octets_in_buffer += octets_in_msg;
+ octets_in_msg = 0;
+ }
+
+ }
+
+}
+
+/*
+ * sha1_final(ctx, output) computes the result for ctx and copies it
+ * into the twenty octets located at *output
+ */
+
+void
+sha1_final(sha1_ctx_t *ctx, uint32_t *output) {
+ uint32_t A, B, C, D, E, TEMP;
+ uint32_t W[80];
+ int i, t;
+
+ /*
+ * process the remaining octets_in_buffer, padding and terminating as
+ * necessary
+ */
+ {
+ int tail = ctx->octets_in_buffer % 4;
+
+ /* copy/xor message into array */
+ for (i=0; i < (ctx->octets_in_buffer+3)/4; i++)
+ W[i] = be32_to_cpu(ctx->M[i]);
+
+ /* set the high bit of the octet immediately following the message */
+ switch (tail) {
+ case (3):
+ W[i-1] = (be32_to_cpu(ctx->M[i-1]) & 0xffffff00) | 0x80;
+ W[i] = 0x0;
+ break;
+ case (2):
+ W[i-1] = (be32_to_cpu(ctx->M[i-1]) & 0xffff0000) | 0x8000;
+ W[i] = 0x0;
+ break;
+ case (1):
+ W[i-1] = (be32_to_cpu(ctx->M[i-1]) & 0xff000000) | 0x800000;
+ W[i] = 0x0;
+ break;
+ case (0):
+ W[i] = 0x80000000;
+ break;
+ }
+
+ /* zeroize remaining words */
+ for (i++ ; i < 15; i++)
+ W[i] = 0x0;
+
+ /*
+ * if there is room at the end of the word array, then set the
+ * last word to the bit-length of the message; otherwise, set that
+ * word to zero and then we need to do one more run of the
+ * compression algo.
+ */
+ if (ctx->octets_in_buffer < 56)
+ W[15] = ctx->num_bits_in_msg;
+ else if (ctx->octets_in_buffer < 60)
+ W[15] = 0x0;
+
+ /* process the word array */
+ for (t=16; t < 80; t++) {
+ TEMP = W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16];
+ W[t] = S1(TEMP);
+ }
+
+ A = ctx->H[0];
+ B = ctx->H[1];
+ C = ctx->H[2];
+ D = ctx->H[3];
+ E = ctx->H[4];
+
+ for (t=0; t < 20; t++) {
+ TEMP = S5(A) + f0(B,C,D) + E + W[t] + SHA_K0;
+ E = D; D = C; C = S30(B); B = A; A = TEMP;
+ }
+ for ( ; t < 40; t++) {
+ TEMP = S5(A) + f1(B,C,D) + E + W[t] + SHA_K1;
+ E = D; D = C; C = S30(B); B = A; A = TEMP;
+ }
+ for ( ; t < 60; t++) {
+ TEMP = S5(A) + f2(B,C,D) + E + W[t] + SHA_K2;
+ E = D; D = C; C = S30(B); B = A; A = TEMP;
+ }
+ for ( ; t < 80; t++) {
+ TEMP = S5(A) + f3(B,C,D) + E + W[t] + SHA_K3;
+ E = D; D = C; C = S30(B); B = A; A = TEMP;
+ }
+
+ ctx->H[0] += A;
+ ctx->H[1] += B;
+ ctx->H[2] += C;
+ ctx->H[3] += D;
+ ctx->H[4] += E;
+
+ }
+
+ //debug_print(mod_sha1, "(final) running sha1_core()", NULL);
+
+ if (ctx->octets_in_buffer >= 56) {
+
+
+ //debug_print(mod_sha1, "(final) running sha1_core() again", NULL);
+
+ /* we need to do one final run of the compression algo */
+
+ /*
+ * set initial part of word array to zeros, and set the
+ * final part to the number of bits in the message
+ */
+ for (i=0; i < 15; i++)
+ W[i] = 0x0;
+ W[15] = ctx->num_bits_in_msg;
+
+ /* process the word array */
+ for (t=16; t < 80; t++) {
+ TEMP = W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16];
+ W[t] = S1(TEMP);
+ }
+
+ A = ctx->H[0];
+ B = ctx->H[1];
+ C = ctx->H[2];
+ D = ctx->H[3];
+ E = ctx->H[4];
+
+ for (t=0; t < 20; t++) {
+ TEMP = S5(A) + f0(B,C,D) + E + W[t] + SHA_K0;
+ E = D; D = C; C = S30(B); B = A; A = TEMP;
+ }
+ for ( ; t < 40; t++) {
+ TEMP = S5(A) + f1(B,C,D) + E + W[t] + SHA_K1;
+ E = D; D = C; C = S30(B); B = A; A = TEMP;
+ }
+ for ( ; t < 60; t++) {
+ TEMP = S5(A) + f2(B,C,D) + E + W[t] + SHA_K2;
+ E = D; D = C; C = S30(B); B = A; A = TEMP;
+ }
+ for ( ; t < 80; t++) {
+ TEMP = S5(A) + f3(B,C,D) + E + W[t] + SHA_K3;
+ E = D; D = C; C = S30(B); B = A; A = TEMP;
+ }
+
+ ctx->H[0] += A;
+ ctx->H[1] += B;
+ ctx->H[2] += C;
+ ctx->H[3] += D;
+ ctx->H[4] += E;
+ }
+
+ /* copy result into output buffer */
+ output[0] = be32_to_cpu(ctx->H[0]);
+ output[1] = be32_to_cpu(ctx->H[1]);
+ output[2] = be32_to_cpu(ctx->H[2]);
+ output[3] = be32_to_cpu(ctx->H[3]);
+ output[4] = be32_to_cpu(ctx->H[4]);
+
+ /* indicate that message buffer in context is empty */
+ ctx->octets_in_buffer = 0;
+
+ return;
+}
+
+
+
--- /dev/null
+/*
+ * sha1.h
+ *
+ * interface to the Secure Hash Algorithm v.1 (SHA-1), specified in
+ * FIPS 180-1
+ *
+ * David A. McGrew
+ * Cisco Systems, Inc.
+ */
+
+/*
+ *
+ * Copyright (c) 2001-2006, Cisco Systems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * Neither the name of the Cisco Systems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef SHA1_H
+#define SHA1_H
+#define SHA_DIGEST_SIZE 20
+#define be32_to_cpu(x) (uint32_t) ( \
+ (((uint32_t)(x) & 0xff000000u) >> 24) | \
+ (((uint32_t)(x) & 0x00ff0000u) >> 8) | \
+ (((uint32_t)(x) & 0x0000ff00u) << 8) | \
+ (((uint32_t)(x) & 0x000000ffu) << 24))
+
+
+typedef unsigned int uint32_t;
+typedef unsigned char uint8_t;
+typedef struct {
+ uint32_t H[5]; /* state vector */
+ uint32_t M[16]; /* message buffer */
+ int octets_in_buffer; /* octets of message in buffer */
+ uint32_t num_bits_in_msg; /* total number of bits in message */
+} sha1_ctx_t;
+
+/*
+ * sha1(&ctx, msg, len, output) hashes the len octets starting at msg
+ * into the SHA1 context, then writes the result to the 20 octets at
+ * output
+ *
+ */
+
+void
+sha1(const uint8_t *message, int octets_in_msg, uint32_t output[5]);
+
+/*
+ * sha1_init(&ctx) initializes the SHA1 context ctx
+ *
+ * sha1_update(&ctx, msg, len) hashes the len octets starting at msg
+ * into the SHA1 context
+ *
+ * sha1_final(&ctx, output) performs the final processing of the SHA1
+ * context and writes the result to the 20 octets at output
+ *
+ */
+
+void
+sha1_init(sha1_ctx_t *ctx);
+
+void
+sha1_update(sha1_ctx_t *ctx, const uint8_t *M, int octets_in_msg);
+
+void
+sha1_final(sha1_ctx_t *ctx, uint32_t output[5]);
+
+/*
+ * The sha1_core function is INTERNAL to SHA-1, but it is declared
+ * here because it is also used by the cipher SEAL 3.0 in its key
+ * setup algorithm.
+ */
+
+/*
+ * sha1_core(M, H) computes the core sha1 compression function, where M is
+ * the next part of the message and H is the intermediate state {H0,
+ * H1, ...}
+ *
+ * this function does not do any of the padding required in the
+ * complete sha1 function
+ */
+
+void
+sha1_core(const uint32_t M[16], uint32_t hash_value[5]);
+
+#endif /* SHA1_H */
+++ /dev/null
-/*
- * sha1.c
- *
- * an implementation of the Secure Hash Algorithm v.1 (SHA-1),
- * specified in FIPS 180-1
- *
- * David A. McGrew
- * Cisco Systems, Inc.
- */
-
-/*
- *
- * Copyright (c) 2001-2006, Cisco Systems, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * Neither the name of the Cisco Systems, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#include "sha1.h"
-
-
-
-/* SN == Rotate left N bits */
-#define S1(X) ((X << 1) | (X >> 31))
-#define S5(X) ((X << 5) | (X >> 27))
-#define S30(X) ((X << 30) | (X >> 2))
-
-#define f0(B,C,D) ((B & C) | (~B & D))
-#define f1(B,C,D) (B ^ C ^ D)
-#define f2(B,C,D) ((B & C) | (B & D) | (C & D))
-#define f3(B,C,D) (B ^ C ^ D)
-
-
-
-/*
- * nota bene: the variable K0 appears in the curses library, so we
- * give longer names to these variables to avoid spurious warnings
- * on systems that uses curses
- */
-
-uint32_t SHA_K0 = 0x5A827999; /* Kt for 0 <= t <= 19 */
-uint32_t SHA_K1 = 0x6ED9EBA1; /* Kt for 20 <= t <= 39 */
-uint32_t SHA_K2 = 0x8F1BBCDC; /* Kt for 40 <= t <= 59 */
-uint32_t SHA_K3 = 0xCA62C1D6; /* Kt for 60 <= t <= 79 */
-
-void
-sha1(const uint8_t *msg, int octets_in_msg, uint32_t hash_value[5]) {
- sha1_ctx_t ctx;
-
- sha1_init(&ctx);
- sha1_update(&ctx, msg, octets_in_msg);
- sha1_final(&ctx, hash_value);
-
-}
-
-/*
- * sha1_core(M, H) computes the core compression function, where M is
- * the next part of the message (in network byte order) and H is the
- * intermediate state { H0, H1, ...} (in host byte order)
- *
- * this function does not do any of the padding required in the
- * complete SHA1 function
- *
- * this function is used in the SEAL 3.0 key setup routines
- * (crypto/cipher/seal.c)
- */
-
-void
-sha1_core(const uint32_t M[16], uint32_t hash_value[5]) {
- uint32_t H0;
- uint32_t H1;
- uint32_t H2;
- uint32_t H3;
- uint32_t H4;
- uint32_t W[80];
- uint32_t A, B, C, D, E, TEMP;
- int t;
-
- /* copy hash_value into H0, H1, H2, H3, H4 */
- H0 = hash_value[0];
- H1 = hash_value[1];
- H2 = hash_value[2];
- H3 = hash_value[3];
- H4 = hash_value[4];
-
- /* copy/xor message into array */
-
- W[0] = be32_to_cpu(M[0]);
- W[1] = be32_to_cpu(M[1]);
- W[2] = be32_to_cpu(M[2]);
- W[3] = be32_to_cpu(M[3]);
- W[4] = be32_to_cpu(M[4]);
- W[5] = be32_to_cpu(M[5]);
- W[6] = be32_to_cpu(M[6]);
- W[7] = be32_to_cpu(M[7]);
- W[8] = be32_to_cpu(M[8]);
- W[9] = be32_to_cpu(M[9]);
- W[10] = be32_to_cpu(M[10]);
- W[11] = be32_to_cpu(M[11]);
- W[12] = be32_to_cpu(M[12]);
- W[13] = be32_to_cpu(M[13]);
- W[14] = be32_to_cpu(M[14]);
- W[15] = be32_to_cpu(M[15]);
- TEMP = W[13] ^ W[8] ^ W[2] ^ W[0]; W[16] = S1(TEMP);
- TEMP = W[14] ^ W[9] ^ W[3] ^ W[1]; W[17] = S1(TEMP);
- TEMP = W[15] ^ W[10] ^ W[4] ^ W[2]; W[18] = S1(TEMP);
- TEMP = W[16] ^ W[11] ^ W[5] ^ W[3]; W[19] = S1(TEMP);
- TEMP = W[17] ^ W[12] ^ W[6] ^ W[4]; W[20] = S1(TEMP);
- TEMP = W[18] ^ W[13] ^ W[7] ^ W[5]; W[21] = S1(TEMP);
- TEMP = W[19] ^ W[14] ^ W[8] ^ W[6]; W[22] = S1(TEMP);
- TEMP = W[20] ^ W[15] ^ W[9] ^ W[7]; W[23] = S1(TEMP);
- TEMP = W[21] ^ W[16] ^ W[10] ^ W[8]; W[24] = S1(TEMP);
- TEMP = W[22] ^ W[17] ^ W[11] ^ W[9]; W[25] = S1(TEMP);
- TEMP = W[23] ^ W[18] ^ W[12] ^ W[10]; W[26] = S1(TEMP);
- TEMP = W[24] ^ W[19] ^ W[13] ^ W[11]; W[27] = S1(TEMP);
- TEMP = W[25] ^ W[20] ^ W[14] ^ W[12]; W[28] = S1(TEMP);
- TEMP = W[26] ^ W[21] ^ W[15] ^ W[13]; W[29] = S1(TEMP);
- TEMP = W[27] ^ W[22] ^ W[16] ^ W[14]; W[30] = S1(TEMP);
- TEMP = W[28] ^ W[23] ^ W[17] ^ W[15]; W[31] = S1(TEMP);
-
- /* process the remainder of the array */
- for (t=32; t < 80; t++) {
- TEMP = W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16];
- W[t] = S1(TEMP);
- }
-
- A = H0; B = H1; C = H2; D = H3; E = H4;
-
- for (t=0; t < 20; t++) {
- TEMP = S5(A) + f0(B,C,D) + E + W[t] + SHA_K0;
- E = D; D = C; C = S30(B); B = A; A = TEMP;
- }
- for ( ; t < 40; t++) {
- TEMP = S5(A) + f1(B,C,D) + E + W[t] + SHA_K1;
- E = D; D = C; C = S30(B); B = A; A = TEMP;
- }
- for ( ; t < 60; t++) {
- TEMP = S5(A) + f2(B,C,D) + E + W[t] + SHA_K2;
- E = D; D = C; C = S30(B); B = A; A = TEMP;
- }
- for ( ; t < 80; t++) {
- TEMP = S5(A) + f3(B,C,D) + E + W[t] + SHA_K3;
- E = D; D = C; C = S30(B); B = A; A = TEMP;
- }
-
- hash_value[0] = H0 + A;
- hash_value[1] = H1 + B;
- hash_value[2] = H2 + C;
- hash_value[3] = H3 + D;
- hash_value[4] = H4 + E;
-
- return;
-}
-
-void
-sha1_init(sha1_ctx_t *ctx) {
-
- /* initialize state vector */
- ctx->H[0] = 0x67452301;
- ctx->H[1] = 0xefcdab89;
- ctx->H[2] = 0x98badcfe;
- ctx->H[3] = 0x10325476;
- ctx->H[4] = 0xc3d2e1f0;
-
- /* indicate that message buffer is empty */
- ctx->octets_in_buffer = 0;
-
- /* reset message bit-count to zero */
- ctx->num_bits_in_msg = 0;
-
-}
-
-void
-sha1_update(sha1_ctx_t *ctx, const uint8_t *msg, int octets_in_msg) {
- int i;
- uint8_t *buf = (uint8_t *)ctx->M;
-
- /* update message bit-count */
- ctx->num_bits_in_msg += octets_in_msg * 8;
-
- /* loop over 16-word blocks of M */
- while (octets_in_msg > 0) {
-
- if (octets_in_msg + ctx->octets_in_buffer >= 64) {
-
- /*
- * copy words of M into msg buffer until that buffer is full,
- * converting them into host byte order as needed
- */
- octets_in_msg -= (64 - ctx->octets_in_buffer);
- for (i=ctx->octets_in_buffer; i < 64; i++)
- buf[i] = *msg++;
- ctx->octets_in_buffer = 0;
-
- /* process a whole block */
-
- //debug_print(mod_sha1, "(update) running sha1_core()", NULL);
-
- sha1_core(ctx->M, ctx->H);
-
- } else {
-
- //debug_print(mod_sha1, "(update) not running sha1_core()", NULL);
-
- for (i=ctx->octets_in_buffer;
- i < (ctx->octets_in_buffer + octets_in_msg); i++)
- buf[i] = *msg++;
- ctx->octets_in_buffer += octets_in_msg;
- octets_in_msg = 0;
- }
-
- }
-
-}
-
-/*
- * sha1_final(ctx, output) computes the result for ctx and copies it
- * into the twenty octets located at *output
- */
-
-void
-sha1_final(sha1_ctx_t *ctx, uint32_t *output) {
- uint32_t A, B, C, D, E, TEMP;
- uint32_t W[80];
- int i, t;
-
- /*
- * process the remaining octets_in_buffer, padding and terminating as
- * necessary
- */
- {
- int tail = ctx->octets_in_buffer % 4;
-
- /* copy/xor message into array */
- for (i=0; i < (ctx->octets_in_buffer+3)/4; i++)
- W[i] = be32_to_cpu(ctx->M[i]);
-
- /* set the high bit of the octet immediately following the message */
- switch (tail) {
- case (3):
- W[i-1] = (be32_to_cpu(ctx->M[i-1]) & 0xffffff00) | 0x80;
- W[i] = 0x0;
- break;
- case (2):
- W[i-1] = (be32_to_cpu(ctx->M[i-1]) & 0xffff0000) | 0x8000;
- W[i] = 0x0;
- break;
- case (1):
- W[i-1] = (be32_to_cpu(ctx->M[i-1]) & 0xff000000) | 0x800000;
- W[i] = 0x0;
- break;
- case (0):
- W[i] = 0x80000000;
- break;
- }
-
- /* zeroize remaining words */
- for (i++ ; i < 15; i++)
- W[i] = 0x0;
-
- /*
- * if there is room at the end of the word array, then set the
- * last word to the bit-length of the message; otherwise, set that
- * word to zero and then we need to do one more run of the
- * compression algo.
- */
- if (ctx->octets_in_buffer < 56)
- W[15] = ctx->num_bits_in_msg;
- else if (ctx->octets_in_buffer < 60)
- W[15] = 0x0;
-
- /* process the word array */
- for (t=16; t < 80; t++) {
- TEMP = W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16];
- W[t] = S1(TEMP);
- }
-
- A = ctx->H[0];
- B = ctx->H[1];
- C = ctx->H[2];
- D = ctx->H[3];
- E = ctx->H[4];
-
- for (t=0; t < 20; t++) {
- TEMP = S5(A) + f0(B,C,D) + E + W[t] + SHA_K0;
- E = D; D = C; C = S30(B); B = A; A = TEMP;
- }
- for ( ; t < 40; t++) {
- TEMP = S5(A) + f1(B,C,D) + E + W[t] + SHA_K1;
- E = D; D = C; C = S30(B); B = A; A = TEMP;
- }
- for ( ; t < 60; t++) {
- TEMP = S5(A) + f2(B,C,D) + E + W[t] + SHA_K2;
- E = D; D = C; C = S30(B); B = A; A = TEMP;
- }
- for ( ; t < 80; t++) {
- TEMP = S5(A) + f3(B,C,D) + E + W[t] + SHA_K3;
- E = D; D = C; C = S30(B); B = A; A = TEMP;
- }
-
- ctx->H[0] += A;
- ctx->H[1] += B;
- ctx->H[2] += C;
- ctx->H[3] += D;
- ctx->H[4] += E;
-
- }
-
- //debug_print(mod_sha1, "(final) running sha1_core()", NULL);
-
- if (ctx->octets_in_buffer >= 56) {
-
-
- //debug_print(mod_sha1, "(final) running sha1_core() again", NULL);
-
- /* we need to do one final run of the compression algo */
-
- /*
- * set initial part of word array to zeros, and set the
- * final part to the number of bits in the message
- */
- for (i=0; i < 15; i++)
- W[i] = 0x0;
- W[15] = ctx->num_bits_in_msg;
-
- /* process the word array */
- for (t=16; t < 80; t++) {
- TEMP = W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16];
- W[t] = S1(TEMP);
- }
-
- A = ctx->H[0];
- B = ctx->H[1];
- C = ctx->H[2];
- D = ctx->H[3];
- E = ctx->H[4];
-
- for (t=0; t < 20; t++) {
- TEMP = S5(A) + f0(B,C,D) + E + W[t] + SHA_K0;
- E = D; D = C; C = S30(B); B = A; A = TEMP;
- }
- for ( ; t < 40; t++) {
- TEMP = S5(A) + f1(B,C,D) + E + W[t] + SHA_K1;
- E = D; D = C; C = S30(B); B = A; A = TEMP;
- }
- for ( ; t < 60; t++) {
- TEMP = S5(A) + f2(B,C,D) + E + W[t] + SHA_K2;
- E = D; D = C; C = S30(B); B = A; A = TEMP;
- }
- for ( ; t < 80; t++) {
- TEMP = S5(A) + f3(B,C,D) + E + W[t] + SHA_K3;
- E = D; D = C; C = S30(B); B = A; A = TEMP;
- }
-
- ctx->H[0] += A;
- ctx->H[1] += B;
- ctx->H[2] += C;
- ctx->H[3] += D;
- ctx->H[4] += E;
- }
-
- /* copy result into output buffer */
- output[0] = be32_to_cpu(ctx->H[0]);
- output[1] = be32_to_cpu(ctx->H[1]);
- output[2] = be32_to_cpu(ctx->H[2]);
- output[3] = be32_to_cpu(ctx->H[3]);
- output[4] = be32_to_cpu(ctx->H[4]);
-
- /* indicate that message buffer in context is empty */
- ctx->octets_in_buffer = 0;
-
- return;
-}
-
-
-
+++ /dev/null
-/*
- * sha1.h
- *
- * interface to the Secure Hash Algorithm v.1 (SHA-1), specified in
- * FIPS 180-1
- *
- * David A. McGrew
- * Cisco Systems, Inc.
- */
-
-/*
- *
- * Copyright (c) 2001-2006, Cisco Systems, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * Neither the name of the Cisco Systems, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#ifndef SHA1_H
-#define SHA1_H
-#define SHA_DIGEST_SIZE 20
-#define be32_to_cpu(x) (uint32_t) ( \
- (((uint32_t)(x) & 0xff000000u) >> 24) | \
- (((uint32_t)(x) & 0x00ff0000u) >> 8) | \
- (((uint32_t)(x) & 0x0000ff00u) << 8) | \
- (((uint32_t)(x) & 0x000000ffu) << 24))
-
-
-typedef unsigned int uint32_t;
-typedef unsigned char uint8_t;
-typedef struct {
- uint32_t H[5]; /* state vector */
- uint32_t M[16]; /* message buffer */
- int octets_in_buffer; /* octets of message in buffer */
- uint32_t num_bits_in_msg; /* total number of bits in message */
-} sha1_ctx_t;
-
-/*
- * sha1(&ctx, msg, len, output) hashes the len octets starting at msg
- * into the SHA1 context, then writes the result to the 20 octets at
- * output
- *
- */
-
-void
-sha1(const uint8_t *message, int octets_in_msg, uint32_t output[5]);
-
-/*
- * sha1_init(&ctx) initializes the SHA1 context ctx
- *
- * sha1_update(&ctx, msg, len) hashes the len octets starting at msg
- * into the SHA1 context
- *
- * sha1_final(&ctx, output) performs the final processing of the SHA1
- * context and writes the result to the 20 octets at output
- *
- */
-
-void
-sha1_init(sha1_ctx_t *ctx);
-
-void
-sha1_update(sha1_ctx_t *ctx, const uint8_t *M, int octets_in_msg);
-
-void
-sha1_final(sha1_ctx_t *ctx, uint32_t output[5]);
-
-/*
- * The sha1_core function is INTERNAL to SHA-1, but it is declared
- * here because it is also used by the cipher SEAL 3.0 in its key
- * setup algorithm.
- */
-
-/*
- * sha1_core(M, H) computes the core sha1 compression function, where M is
- * the next part of the message and H is the intermediate state {H0,
- * H1, ...}
- *
- * this function does not do any of the padding required in the
- * complete sha1 function
- */
-
-void
-sha1_core(const uint32_t M[16], uint32_t hash_value[5]);
-
-#endif /* SHA1_H */
+++ /dev/null
-/*-
- * Copyright 2003-2005 Colin Percival
- * Copyright 2012 Matthew Endsley
- * All rights reserved
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted providing that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * Modifications are made in reimplementing suffix sort array generation
- * and how the data is read and written to.Iterative part replaced the
- * recursive implementation to avoid buffer overflow problems
- */
-#include <string.h>
-#include <err.h>
-#include "ss_patchdelta.h"
-#include "fota_common.h"
-#include "sha1.h"
-#include "SS_Engine_Errors.h"
-
-#include "ss_bspatch_common.h"
-#include <Alloc.h>
-#include <7zFile.h>
-#include <7zVersion.h>
-#include <LzmaDec.h>
-#include <LzmaEnc.h>
-
-
-int SS_ApplyBsdiff(char *oldfile, char *newfile, char *patch, SinkFn sink, void *token, sha1_ctx_t * ctx1)
-{
-
- UInt64 unpackSize = 0;
- CFileSeqInStream inStream;
- ISeqOutStream outStream;
- char *buf_res = NULL;
- unsigned char *new_data = NULL;
- ssize_t new_size = 0;
- int result = E_SS_FAILURE;
-
- FileSeqInStream_CreateVTable(&inStream);
- File_Construct(&inStream.file);
- FileOutStream_CreateVTable((CFileOutStream *) & outStream);
-
- if (InFile_Open(&inStream.file, patch) != 0)
- return E_SS_FAILURE;
-
- UInt64 i;
- CLzmaDec state;
- unsigned char header[LZMA_PROPS_SIZE + 8];
-
- RINOK(SeqInStream_Read(&inStream.s, header, sizeof(header)));
-
- unpackSize = 0;
- for (i = 0; i < 8; i++)
- unpackSize += (UInt64) header[LZMA_PROPS_SIZE + i] << (i * 8);
-
- LzmaDec_Construct(&state);
- RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc));
-
- //decompress the patch file into buf_res
- buf_res = (char *)SS_Malloc(unpackSize);
- if (!buf_res) {
- LOGE("Bad memory allocation\n");
- goto Cleanup;
- }
- result = Decode2(&state, &outStream, &inStream.s, &unpackSize, (unsigned char *)buf_res);
-
- LzmaDec_Free(&state, &g_Alloc);
- File_Close(&inStream.file);
-
- if (result != S_SS_SUCCESS) {
- LOGE("Error decompression failed with code : [%d]\n", result);
- goto Cleanup;
- }
- //apply patch using buffer decoded by Decode2
- result = apply_patch(oldfile, buf_res, &new_data, &new_size);
- if (result != S_SS_SUCCESS) {
- goto Cleanup;
- }
-
- result = (sink(new_data, new_size, token) < new_size) ? E_SS_FAILURE : S_SS_SUCCESS;
- if (result != S_SS_SUCCESS) {
- LOGE("short write of output: %d (%s)\n", errno, strerror(errno));
- goto Cleanup;
- }
-
- if (ctx1) {
- sha1_update(ctx1, new_data, new_size);
- }
- Cleanup:
- if (new_data)
- SS_Free(new_data);
- if (buf_res)
- SS_Free(buf_res);
- File_Close(&inStream.file);//wgid: 27007
- return result;
-
-}
+++ /dev/null
-/*
- * libtota
- *
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <errno.h>
-#include <libgen.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/statfs.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include "ua.h"
-#include "sha1.h"
-#include "ss_patchdelta.h"
-#include "fota_common.h"
-#include "SS_Engine_Errors.h"
-
-extern void *SS_Malloc(unsigned int size);
-
-typedef struct {
- unsigned char *buffer;
- ssize_t size;
- ssize_t pos;
-} MemorySinkInfo;
-
-ssize_t ss_memorySink(unsigned char *data, ssize_t len, void *token)
-{
- MemorySinkInfo *msi = (MemorySinkInfo *) token;
- if (msi->size - msi->pos < len) {
- return -1;
- }
- memcpy(msi->buffer + msi->pos, data, len);
- msi->pos += len;
- return len;
-}
-
-ssize_t ss_fileSink(unsigned char *data, ssize_t len, void *token)
-{
- int ss_fd = *(int *)token;
- ssize_t done = 0;
- ssize_t wrote;
- while (done < (ssize_t) len) {
- wrote = write(ss_fd, data + done, len - done);
- if (wrote <= 0) {
- if (errno == EINTR || errno == EAGAIN)
- continue; // try again
- LOGE("error writing %d bytes: %s\n", (int)(len - done), strerror(errno));
- return done;
- }
- done += wrote;
- }
- return done;
-}
-
-// Take a string 'str' of 40 hex digits and parse it into the 20
-// byte array 'digest'. 'str' may contain only the digest or be of
-// the form "<digest>:<anything>". Return 0 on success, -1 on any
-// error.
-int ParseSha1(const char *str, uint8_t * digest)
-{
- int i;
- const char *ps = str;
- uint8_t *pd = digest;
- for (i = 0; i < SHA_DIGEST_SIZE * 2; ++i, ++ps) {
- int digit;
- if (*ps >= '0' && *ps <= '9') {
- digit = *ps - '0';
- } else if (*ps >= 'a' && *ps <= 'f') {
- digit = *ps - 'a' + 10;
- } else if (*ps >= 'A' && *ps <= 'F') {
- digit = *ps - 'A' + 10;
- } else {
- return -1;
- }
- if (i % 2 == 0) {
- *pd = digit << 4;
- } else {
- *pd |= digit;
- ++pd;
- }
- }
- if (*ps != '\0')
- return -1;
- return 0;
-}
-
-//Function to find the start of gzipped part in compressed kernel
-int getOffset(char *zimage_path)
-{
- char gzip_header[] = { 31, -117, 8 }; //header value for gzip which needs to be checked
- char buf[4] = { 0, };
- int offset = 0;//wgid:14074
-
- FILE *f = fopen(zimage_path, "r");
- if(!f){
- LOGE("Fopen failed for path %s\n", zimage_path);
- SS_SetUpgradeState(E_SS_OPENFILE_ONLYR);
- return -1;
- }
- fseek(f, 0, SEEK_SET);
- while (fread(buf, 1, 3, f) > 0) {
- if (gzip_header[0] == buf[0] && gzip_header[1] == buf[1] && gzip_header[2] == buf[2]) {
- LOGL(LOG_SSENGINE, "match for %d %d %d found at %d\n", buf[0], buf[1], buf[2], ftell(f) - 3);
- break;
- } else {
- fseek(f, -2, SEEK_CUR);
- }
- }
- offset = ftell(f) - 3;
- fclose(f);
- return offset;
-}
-
-int SS_LoadPartition(const char *filename, FileInfo * file)
-{
- size_t read = 0;
- FILE *dev = NULL;
- int i;
-
- dev = fopen(filename, "rb");
- if (dev == NULL) {
- LOGE("failed to open partition \"%s\": %s\n", filename, strerror(errno));
- return -1;
- }
-
- sha1_ctx_t sha_ctx;
- sha1_init(&sha_ctx);
-
- file->data = SS_Malloc(file->size);
- if (file->data) {
- read = fread(file->data, 1, file->size, dev);
- LOGL(LOG_SSENGINE, "Partition size read %d\n", read);
- sha1_update(&sha_ctx, file->data, read);
- file->size = read;
- }
-
- const uint8_t sha_final[SHA_DIGEST_SIZE] = { 0, };
- sha1_final(&sha_ctx, (uint32_t *) & sha_final);
- for (i = 0; i < SHA_DIGEST_SIZE; ++i) {
- file->sha1[i] = sha_final[i];
- }
- //LOGL(LOG_SSENGINE, "Final SHA of Source (%s)\n", sha_final);
-
- file->st.st_mode = 0644;
- file->st.st_uid = 0;
- file->st.st_gid = 0;
- fclose(dev);
- return 0;
-}
-
-//extern int write_data_to_blkdev(char* dev_name, int blk_start, int blk_cnt, char* data);
-
-int SS_LoadFile(const char *filename, FileInfo * file)
-{
-
- file->data = NULL;
- //LOGL(LOG_SSENGINE,"SS_LoadFile --- [File name %s]\n",filename);
-
- if (stat(filename, &file->st) != 0) {
- LOGE("failed to stat \"%s\": %s\n", filename, strerror(errno));
- return -1;
- }
-
- file->size = file->st.st_size;
- file->data = SS_Malloc(file->size);
- if (!file->data) {
- LOGE("failed to allocate memory for \"%s\": %s\n", filename, strerror(errno));
- return -1;
- }
-
- FILE *f = fopen(filename, "rb");
- if (f == NULL) {
- LOGE("failed to open \"%s\": %s\n", filename, strerror(errno));
- SS_Free(file->data);
- file->data = NULL;
- return -1;
- }
-
- ssize_t bytes_read = fread(file->data, 1, file->size, f);
- if (bytes_read != file->size) {
- LOGE("short read of \"%s\" (%ld bytes of %ld)\n", filename, (long)bytes_read, (long)file->size);
- SS_Free(file->data);
- file->data = NULL;
- fclose(f);
- return -1;
- }
- fclose(f);
- //LOGL(LOG_SSENGINE,"SS_LoadFile --- [bytes_read %d]\n",bytes_read);
- sha1(file->data, file->size, (uint32_t *) file->sha1);
- return 0;
-}
-
-extern int gvalid_session;
-extern void create_dir(char *pathname, int mode);
-#ifdef SUPPORT_CONTAINER
-//unzip source archive , apply patch from extracted delta folder and repack the source archive
-int SS_UpdateArchive(ua_dataSS_t * ua_dataSS, const char *source_filename, const char *target_filename,
- const char *source_sha1_str, const char *target_sha1_str)
-{
- FILE *fp;
- char *line = NULL, *token = NULL, *source_file = NULL, *new_file = NULL, *dir_to_create = NULL, *patch_file = NULL;
- char patch_path_full[MAX_FILE_PATH] = { 0, }; //absolute path for patches
- char source_path_full[MAX_FILE_PATH] = { 0, }; //absolute path for uncompressed source files
- char target_path_full[MAX_FILE_PATH] = { 0, };
- char patchlist[MAX_FILE_PATH] = { 0, };
- char cmd[2 * MAX_FILE_PATH] = { 0, };
- size_t len = 0, read = 0;
- int result = S_SS_SUCCESS;
- uint8_t target_sha1[SHA_DIGEST_SIZE];
- uint8_t source_sha1[SHA_DIGEST_SIZE] = { 0, };
- FileInfo source_data = { 0, };
- int backupsrc = -1;
- SinkFn sink = NULL;
- void *tok = NULL;
- int output = -1;
- char *outname = NULL;
-
- if (ParseSha1(target_sha1_str, target_sha1) != 0) {
- LOGE("failed to parse tgt-sha1 \"%s\"\n", target_sha1_str);
- return E_SS_FAILURE;
- }
-
- if (0 == gvalid_session) {
- if (ParseSha1(source_sha1_str, source_sha1) != 0) {
- LOGE("failed to parse tgt-sha1 \"%s\"\n", source_sha1_str);
- return E_SS_FAILURE;
- }
- if (SS_LoadFile(source_filename, &source_data) == 0) {
- if (memcmp(source_data.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
- LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Patch Can be applied\n");
- if (source_data.data)
- SS_Free(source_data.data);
- } else if (memcmp(source_data.sha1, target_sha1, SHA_DIGEST_SIZE) == 0) {
- LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Patch Already applied\n");
- if (source_data.data)
- SS_Free(source_data.data);
- return S_SS_SUCCESS;
- } else {
- //Check for backup file SHA
- SS_Free(source_data.data);
- source_data.data = NULL;
- LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Source was currupted, Try loading from backup source\n");
- if (SS_LoadFile(SS_BACKUP_SOURCE, &source_data) == 0) {
- if (memcmp(source_data.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
- if (SS_CopyFile(NULL, SS_BACKUP_SOURCE, source_filename) != 0) {
- LOGE("copy of backup to \"%s\" failed: %s\n", source_filename, strerror(errno));
- SS_SetUpgradeState(E_SS_FSUPDATEFAILED);
- if (source_data.data)
- SS_Free(source_data.data);
- return E_SS_FAILURE;
- }
- LOGL(LOG_SSENGINE,
- "SS_UpdateDeltaFS - Patch Can be applied from using backup file as source\n");
- } else {
- SS_SetUpgradeState(E_SS_FSSRCCURRUPTED);
- if (source_data.data)
- SS_Free(source_data.data);
- return E_SS_FAILURE;
- }
- } else {
- SS_SetUpgradeState(E_SS_FSSRCCURRUPTED);
- if (source_data.data)
- SS_Free(source_data.data);
- return E_SS_FAILURE;
- }
- }
- } else {
- LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Source was deleted, Try loading from backup source\n");
- if (SS_LoadFile(SS_BACKUP_SOURCE, &source_data) == 0) {
- if (memcmp(source_data.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
- if (SS_CopyFile(NULL, SS_BACKUP_SOURCE, source_filename) != 0) {
- LOGE("copy of backup to \"%s\" failed: %s\n", source_filename, strerror(errno));
- SS_SetUpgradeState(E_SS_FSUPDATEFAILED);
- if (source_data.data)
- SS_Free(source_data.data);
- return E_SS_FAILURE;
- }
- LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Patch Can be applied from using backup file as source\n");
- } else {
- SS_SetUpgradeState(E_SS_FSSRCCURRUPTED);
- if (source_data.data)
- SS_Free(source_data.data);
- return E_SS_FAILURE;
- }
- } else {
- SS_SetUpgradeState(E_SS_FSSRCCURRUPTED);
- if (source_data.data)
- SS_Free(source_data.data);
- return E_SS_FAILURE;
- }
- }
- }
-#ifndef ENHANCED_BSDIFF
- backupsrc = SS_BackupSource(source_filename);
- if (backupsrc != 0) {
- LOGE("failed to Backup source File:[%s] \n", source_filename);
- SS_SetUpgradeState(E_SS_FSSRCBACKUPFAILED);
- return E_SS_FAILURE;
- }
-#endif
- //create workspace for processing container upgrade
- SS_CreateFolder(NULL, SS_ARCHIVE_WORK_FOLDER);
- SS_CreateFolder(NULL, SS_ARCHIVE_UNPACK_FOLDER);
-
- //unpack the source container to the unpack workspace
- snprintf(cmd, sizeof(cmd) - 1, "%s -qo %s -d %s", SS_UNZIP_COMMAND, source_filename, SS_ARCHIVE_UNPACK_FOLDER);
- result = _system_cmd_wait(cmd);
- if (result != S_SS_SUCCESS) {
- LOGE("zip extraction for [%s] failed, code [%d]\n", cmd, result);
- return E_SS_FAILURE;
- }
- //extract unpack scipt from delta.tar to process containers later
- if (tar_get_item_size(ua_dataSS->update_data->ua_delta_path, SS_KERNEL_UNPACK_SCRIPT) > 0)
- if (tar_extract_file(ua_dataSS->update_data->ua_delta_path, SS_KERNEL_UNPACK_SCRIPT, SS_KERN_UNPK_SCRIPT_PATH) >
- 0)
- LOGL(LOG_SSENGINE, "Extracted %s successfully\n", SS_KERNEL_UNPACK_SCRIPT);
- else {
- LOGE("Error in fn tar_extract_file for item %s", SS_KERNEL_UNPACK_SCRIPT);
- SS_SetUpgradeState(E_SS_DELTA_IS_CORRUPT);
- result = E_SS_FAILURE;
- }
- //move new tpk extracted in the delta folder to the work folder
- new_file = strrchr(target_filename, '/');
- snprintf(source_path_full, sizeof(source_path_full) - 1, "%s/%s", SS_ARCHIVE_DELTA_FOLDER, new_file + 1);
- snprintf(target_path_full, sizeof(target_path_full) - 1, "%s/%s", SS_ARCHIVE_WORK_FOLDER, new_file + 1);
-
- result = rename(source_path_full, target_path_full);
- if (result != 0) {
- LOGE("fatal error in moving %s to %s\n", source_path_full, target_path_full);
- return E_SS_FAILURE;
- }
- snprintf(cmd, sizeof(cmd) - 1, "%s -qo %s -d %s", SS_UNZIP_COMMAND, target_path_full, SS_ARCHIVE_WORK_FOLDER);
- result = _system_cmd_wait(cmd);
- if (result != S_SS_SUCCESS) {
- LOGE("zip extraction for [%s] failed, code [%d]\n", cmd, result);
- return E_SS_FAILURE;
- } else
- LOGL(LOG_SSENGINE, "Thin zip extracted successfully\n");
- // open the patch list and start iterating through the changes and the same files
- snprintf(patchlist, MAX_FILE_PATH, "%s/%s", SS_ARCHIVE_DELTA_FOLDER, SS_CONTAINER_INFO_FILE);
- fp = fopen(patchlist, "r");
- if (!fp) {
- LOGE("file open error [%s]\n", patchlist);
- return E_SS_FAILURE;
- }
-
- while ((read = getline(&line, &len, fp)) != -1) {
-
- switch (line[0]) { // '-' == Delete File, 's' == same File, 'c' == Changed File
- case 's': //for same files case, just extract from old tpk to the work folder, update new tpk in the end
- token = strtok(line, SS_SEPARATOR_TOKEN);
-
- source_file = strtok(NULL, SS_NEWLINE_TOKEN);
-
- snprintf(source_path_full, sizeof(source_path_full) - 1, "%s/%s", SS_ARCHIVE_UNPACK_FOLDER, source_file);
- snprintf(target_path_full, sizeof(target_path_full) - 1, "%s/%s", SS_ARCHIVE_WORK_FOLDER, source_file);
- LOGL(LOG_SSENGINE, "copy %s\n", source_file);
- result = SS_MoveFile(NULL, source_path_full, target_path_full);
- if (result != S_SS_SUCCESS) {
- LOGE("fatal error [%d]\n", errno);
- goto Cleanup;
- }
- break;
- case 'c':
- token = strtok(line, SS_SEPARATOR_TOKEN);
-
- source_file = strtok(NULL, SS_SEPARATOR_TOKEN);
- patch_file = strtok(NULL, SS_NEWLINE_TOKEN);
-
- snprintf(source_path_full, sizeof(source_path_full) - 1, "%s/%s", SS_ARCHIVE_UNPACK_FOLDER, source_file);
- snprintf(target_path_full, sizeof(target_path_full) - 1, "%s/%s", SS_ARCHIVE_WORK_FOLDER, source_file);
- LOGL(LOG_SSENGINE, "copy %s\n", source_file);
- result = SS_MoveFile(NULL, source_path_full, target_path_full);
- if (result != S_SS_SUCCESS) {
- LOGE("fatal error [%d]\n", errno);
- }
-
- snprintf(patch_path_full, sizeof(patch_path_full) - 1, "%s/%s", SS_ARCHIVE_DELTA_FOLDER, patch_file);
- snprintf(source_path_full, sizeof(source_path_full) - 1, "%s/%s", SS_ARCHIVE_WORK_FOLDER, source_file);
-
- {
- // We write the decoded output to "<tgt-file>.patch".
- //allocate some extra space to allow for concatinating ".patch" with the name
- outname = (char *)SS_Malloc(strlen(source_path_full) + 10);
- if (outname == NULL)
- goto Cleanup;
- strcpy(outname, source_path_full);
- strcat(outname, ".patch");
-
- output = open(outname, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
- if (output < 0) {
- LOGE("failed to open output file %s: %s\n", outname, strerror(errno));
- SS_Free(outname);
- goto Cleanup;
- }
- sink = ss_fileSink;
- tok = &output;
- }
- result = SS_ApplyBsdiff((char *)source_path_full, outname, patch_path_full, sink, tok, NULL);
- LOGL(LOG_SSENGINE, "GenerateTarget Output is %d and result is %d\n", output, result);
- if (output >= 0) {
- fsync(output);
- close(output);
- }
-
- if (result != 0) {
- LOGE("applying patch failed %s\n", source_path_full);
- if (outname != NULL) {
- unlink(outname);
- }
- goto Cleanup;
- }
- result = rename(outname, source_path_full);
- if (result != 0) {
- LOGE("fatal error %s\n", source_path_full);
- goto Cleanup;
- } else {
- LOGL(LOG_SSENGINE, "Successfully applied patch for [%s]\n", source_path_full);
- }
- break;
- default:
- break;
- }
- }
-
- new_file = strrchr(target_filename, '/');
- snprintf(cmd, sizeof(cmd) - 1, "%s -p %s %s /opt/data/fota", SS_KERN_UNPK_SCRIPT_PATH, SS_ARCHIVE_WORK_FOLDER,
- new_file + 1);
- int ret = _system_cmd_wait(cmd);
- LOGL(LOG_SSENGINE, "ret for %s is %d\n", cmd, ret);
-
- //Apply diff between intermediate new tpk and the new tpk which contains central dir changes only
- snprintf(patch_path_full, sizeof(patch_path_full) - 1, "%s/New_%s.delta", SS_ARCHIVE_DELTA_FOLDER, new_file + 1);
- snprintf(source_path_full, sizeof(source_path_full) - 1, "%s/%s", SS_ARCHIVE_WORK_FOLDER, new_file + 1);
-
- {
- // We write the decoded output to "<tgt-file>.patch".
- //allocate some extra space to allow for concatinating ".patch" with the name
- outname = (char *)SS_Malloc(strlen(source_path_full) + 10);
- if (outname == NULL)
- return E_SS_FAILURE;
- strcpy(outname, source_path_full);
- strcat(outname, ".patch");
-
- output = open(outname, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
- if (output < 0) {
- LOGE("failed to open output file %s: %s\n", outname, strerror(errno));
- SS_Free(outname);
- goto Cleanup;
- }
- sink = ss_fileSink;
- tok = &output;
- }
- result = SS_ApplyBsdiff((char *)source_path_full, outname, patch_path_full, sink, tok, NULL);
- LOGL(LOG_SSENGINE, "GenerateTarget Output is %d and result is %d\n", output, result);
- if (output >= 0) {
- fsync(output);
- close(output);
- }
-
- if (result != 0) {
- LOGE("applying patch failed %s\n", source_path_full);
- if (outname != NULL) {
- unlink(outname);
- }
- goto Cleanup;
- }
-
- if (SS_LoadFile(outname, &source_data) == 0)
- result = memcmp(source_data.sha1, target_sha1, SHA_DIGEST_SIZE);
- if (result != S_SS_SUCCESS) {
- LOGE("patch did not produce expected sha1 \n");
- SS_SetUpgradeState(E_SS_IMGSHA_MISMATCH);
- goto Cleanup;
- }
-
- result = rename(outname, source_path_full);
- if (result != 0) {
- LOGE("fatal error %s\n", source_path_full);
- goto Cleanup;
- }
- //Delete old file and copy patched archive, cant use rename as partitions may be different
- unlink(source_filename);
- if (result != 0) {
- LOGE("failed to unlink [%s] code [%d]\n", source_filename, errno);
- goto Cleanup;
- }
- result = (int)SS_CopyFile(NULL, source_path_full, target_filename);
- if (result != S_SS_SUCCESS) {
- LOGE("failed to copy file [%s] result [%d]\n", source_path_full, result);
- goto Cleanup;
- }
-
- Cleanup:
- fclose(fp);
- if (line)
- SS_Free(line);
- if (outname)
- SS_Free(outname);
- SS_DeleteFile(NULL, SS_KERN_UNPK_SCRIPT_PATH);
- SS_DeleteFile(NULL, SS_FIND_CMD_TARGET);
- SS_DeleteFolder(NULL, SS_CONTAINER_WORKSPACE);
- return result;
-}
-#endif
-/*!
- *********************************************************************************
- * SS_UpdateDeltaFS
- *********************************************************************************
- *
- * @brief
- * This is used to apply patch for a file during delta FS upgrade
- *
- *
- * @param
- *
- * @return 0 - in case of success
- * 1 - in case of error during patch application
- *
- *********************************************************************************
- */
-
-int SS_UpdateDeltaFS(const char *source_filename, const char *target_filename,
- const char *source_sha1_str, const char *target_sha1_str, int patch_data_size)
-{
- uint8_t target_sha1[SHA_DIGEST_SIZE];
- sha1_ctx_t ctx1;
- int output;
- int retry = 1;
- int use_backup = 0;
- char *outname = NULL;
- int backupsrc = -1;
- int result = 0;
- FileInfo source_file;
- uint8_t source_sha1[SHA_DIGEST_SIZE] = { 0, };
-
- if (ParseSha1(target_sha1_str, target_sha1) != 0) {
- LOGE("failed to parse tgt-sha1 \"%s\"\n", target_sha1_str);
- return E_SS_FAILURE;
- }
-
- /*
- if battery removed in between update gvalid_session becomes 0
- need to check file integrity in that case
- */
- if (0 == gvalid_session) {
- if (ParseSha1(source_sha1_str, source_sha1) != 0) {
- LOGE("failed to parse tgt-sha1 \"%s\"\n", source_sha1_str);
- return E_SS_FAILURE;
- }
- if (SS_LoadFile(source_filename, &source_file) == 0) {
- if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
- LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Patch Can be applied\n");
- if (source_file.data)
- SS_Free(source_file.data);
- } else if (memcmp(source_file.sha1, target_sha1, SHA_DIGEST_SIZE) == 0) {
- LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Patch Already applied\n");
- if (source_file.data)
- SS_Free(source_file.data);
- return S_SS_SUCCESS;
- } else {
- //Check for backup file SHA
- SS_Free(source_file.data);
- source_file.data = NULL;
- LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Source was currupted, Try loading from backup source\n");
- if (SS_LoadFile(SS_BACKUP_SOURCE, &source_file) == 0) {
- if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
- if (SS_CopyFile(NULL, SS_BACKUP_SOURCE, source_filename) != S_SS_SUCCESS) {
- LOGE("copy of backup to \"%s\" failed: %s\n", source_filename, strerror(errno));
- SS_SetUpgradeState(E_SS_FSUPDATEFAILED);
- if (source_file.data)
- SS_Free(source_file.data);
- return E_SS_FAILURE;
- }
- LOGL(LOG_SSENGINE,
- "SS_UpdateDeltaFS - Patch Can be applied from using backup file as source\n");
- } else {
- SS_SetUpgradeState(E_SS_FSSRCCURRUPTED);
- if (source_file.data)
- SS_Free(source_file.data);
- return E_SS_FAILURE;
- }
- } else {
- SS_SetUpgradeState(E_SS_FSSRCCURRUPTED);
- if (source_file.data)
- SS_Free(source_file.data);
- return E_SS_FAILURE;
- }
- }
- } else {
- LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Source was deleted, Try loading from backup source\n");
- if (SS_LoadFile(SS_BACKUP_SOURCE, &source_file) == 0) {
- if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
- use_backup = 1;
- LOGL(LOG_SSENGINE, "SS_UpdateDeltaFS - Patch Can be applied from using backup file as source\n");
- } else {
- SS_SetUpgradeState(E_SS_FSSRCCURRUPTED);
- if (source_file.data)
- SS_Free(source_file.data);
- return E_SS_FAILURE;
- }
- } else {
- SS_SetUpgradeState(E_SS_FSSRCCURRUPTED);
- if (source_file.data)
- SS_Free(source_file.data);
- return E_SS_FAILURE;
- }
- }
- }
- //Now proceed wit patch application since patch can be applied
- do {
- int enough_space = 0;
- size_t free_space;
- char *tok;
-
- if (retry > 0) {
- if (use_backup) {
- tok = strrchr(source_filename, '/');
- *tok = '\0';
- }
- SS_GetAvailableFreeSpace(NULL, source_filename, &free_space);
- enough_space = (free_space > (256 << 10)) && // 256k (two-block) minimum
- (free_space > (patch_data_size * 3 / 2)); // 50% margin of error
- if (use_backup)
- *tok = '/';
- }
-
- if (!use_backup) {
-#ifndef ENHANCED_BSDIFF
- backupsrc = SS_BackupSource(source_filename);
- if (backupsrc != 0) {
- LOGE("failed to Backup source File:[%s] \n", source_filename);
- SS_SetUpgradeState(E_SS_FSSRCBACKUPFAILED);
- return E_SS_FAILURE;
- }
-#endif
- }
- if (!enough_space) {
- LOGL(LOG_SSENGINE, "For %s: free space %ld bytes; enough %d\n", source_filename, (long)free_space,
- enough_space);
- retry = 0;
- use_backup = 1;
- unlink(source_filename);
- }
- //LOGL(LOG_SSENGINE, "For %s: target %ld bytes; free space %ld bytes; enough %d\n",
- // source_filename, (long)patch_data_size, (long)free_space, enough_space);
- //LOGL(LOG_SSENGINE,"Generate Target Space availabitiy [%d]\n", enough_space);
-
- SinkFn sink = NULL;
- void *token = NULL;
- output = -1;
- outname = NULL;
-
- {
- // We write the decoded output to "<tgt-file>.patch".
- //allocate some extra space to allow for concatinating ".patch" with the name
- outname = (char *)SS_Malloc(strlen(target_filename) + 10);
- if (outname == NULL)
- return -1;
- strcpy(outname, target_filename);
- strcat(outname, ".patch");
-
- output = open(outname, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
- if (output < 0) {
- if (errno == 2) {
- char *dir_path = strrchr(outname, '/');
- *dir_path = '\0';
- // need to create directory as the target may be different from source
- LOGL(LOG_SSENGINE, "need to create directory [%s]\n", outname);
- create_dir(outname, 0755);
- *dir_path = '/';
- output = open(outname, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
- if (output < 0) {
- LOGE("failed to open output file %s: %s\n", outname, strerror(errno));
- SS_Free(outname);
- return E_SS_FAILURE;
- }
- }
- }
- sink = ss_fileSink;
- token = &output;
- }
- sha1_init(&ctx1);
- if (use_backup)
- result = SS_ApplyBsdiff(SS_BACKUP_SOURCE, outname, SS_PATCHFILE_SOURCE, sink, token, &ctx1);
- else
- result = SS_ApplyBsdiff((char *)source_filename, outname, SS_PATCHFILE_SOURCE, sink, token, &ctx1);
- if (output >= 0) {
- fsync(output);
- close(output);
- }
-
- if (result != 0) {
- if (retry == 0) {
- LOGE("applying patch failed result : [%d]\n", result);
- SS_Free(outname);//wgid: 20739
- SS_SetUpgradeState(E_SS_FSUPDATEFAILED);
- return E_SS_FAILURE;
- } else {
- LOGE("applying patch failed; retrying\n");
- SS_Free(outname);//wgid: 20739
- }
- if (outname != NULL) {
- unlink(outname);
- }
- } else {
- // succeeded; no need to retry
- break;
- }
- } while (retry-- > 0);
- const uint8_t current_target_sha1[SHA_DIGEST_SIZE] = { 0, };
- sha1_final(&ctx1, (uint32_t *) & current_target_sha1);
- if (memcmp(current_target_sha1, target_sha1, SHA_DIGEST_SIZE) != 0) {
- LOGE("patch did not produce expected sha1\n");
- SS_SetUpgradeState(E_SS_FSSHA_MISMATCH);
- if (outname != NULL) {
- SS_Free(outname);
- }
- return E_SS_FAILURE;
- }
- // Finally, rename the .patch file to replace the target file.
-#ifdef ENHANCED_BSDIFF
- if (SS_rename1(outname, target_filename) != 0) {
- LOGE("rename of .patch to \"%s\" failed: %s\n", target_filename, strerror(errno));
- SS_SetUpgradeState(E_SS_FSUPDATEFAILED);
- if (outname != NULL) {
- SS_Free(outname);
- }
- return E_SS_FAILURE;
- }
-#else
- if (rename(outname, target_filename) != 0) {
- LOGE("rename of .patch to \"%s\" failed: %s\n", target_filename, strerror(errno));
- SS_SetUpgradeState(E_SS_FSUPDATEFAILED);
- if (outname != NULL) {
- SS_Free(outname);
- }
- return E_SS_FAILURE;
- }
- //remove source file if target is not same
- if (strcmp(source_filename, target_filename) != 0)
- unlink(source_filename);
- SS_BackupSourceClear();
-#endif
- SS_PatchSourceClear();
- SS_Free(outname);
-
- return result;
-}
-
-/*!
- *********************************************************************************
- * SS_UpdateDeltaKernel
- *********************************************************************************
- *
- * @brief
- * This is used to apply patch for kernel delta during delta Image upgrade
- *
- *
- * @param
- *
- * @return 0 - in case of success
- * 1 - in case of error during patch application
- *
- *********************************************************************************
- */
-
-int SS_UpdateDeltaKernel(ua_dataSS_t * ua_dataSS, int (*write_to_blkdev) (char *, int, int, char *))
-{
- uint8_t target_sha1[SHA_DIGEST_SIZE];
- uint8_t source_sha1[SHA_DIGEST_SIZE];
- FileInfo source_file;
- int result = S_SS_SUCCESS;
- int blk_cnt, read_count = 0;
- int blk_start = 0;
- int backupsrc = -1;
- int use_backup_img = -1;
- FILE *fp = NULL, *wp = NULL, *kp = NULL;
- int i = 0, j = 0, file_len = 0;
- char *magic = NULL, *file_name = NULL, *buf = NULL, a = '0';
- char cmd[1024] = { 0, };
- char source_filename[MAX_FILE_PATH] = { 0, };
- char part_filename[MAX_FILE_PATH] = { 0, };
- int file_num = 0;
- SinkFn sink = NULL;
- void *tok = NULL;
- int output = -1;
- char *outname = NULL;
- //Kernel Parts are created on unpacking kernel which is then used to apply delta
- char *kernel_parts[] = { "decompression_code",
- "piggy.gz",
- "padding_piggy",
- "piggy_trailer"
- };
-
- if (ParseSha1(ua_dataSS->update_cfg->target_sha1, target_sha1) != 0) {
- LOGE("failed to parse tgt-sha1 \"%s\"\n", ua_dataSS->update_cfg->target_sha1);
- return E_SS_FAILURE;
- }
-
- source_file.size = ua_dataSS->update_cfg->soure_img_size;
- source_file.data = NULL;
- if (0 == gvalid_session) {
-
- if (ParseSha1(ua_dataSS->update_cfg->soure_sha1, source_sha1) != 0) {
- LOGE("failed to parse Src-sha1 \"%s\"\n", ua_dataSS->update_cfg->soure_sha1);
- return E_SS_FAILURE;
- }
-
- if (SS_LoadPartition(ua_dataSS->parti_info->ua_blk_name, &source_file) == 0) {
- if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
- LOGL(LOG_SSENGINE, "SS_UpdateDeltaIMG - Patch Can be applied\n");
-
- } else if (memcmp(source_file.sha1, target_sha1, SHA_DIGEST_SIZE) == 0) {
- LOGL(LOG_SSENGINE, "SS_UpdateDeltaIMG - Patch Already applied\n");
- SS_Free(source_file.data);
- return S_SS_SUCCESS;
- } else {
- SS_Free(source_file.data);
- source_file.data = NULL;
- LOGL(LOG_SSENGINE, "SS_UpdateDeltaIMG - Source was currupted, Try loading from backup source\n");
- if (SS_LoadPartition(SS_BACKUP_SOURCE, &source_file) == 0) {
- if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
- use_backup_img = 1;
-
- LOGL(LOG_SSENGINE,
- "SS_UpdateDeltaIMG - Patch Can be applied from using backup file as source\n");
- } else {
- SS_SetUpgradeState(E_SS_IMGSRCCURRUPTED);
- SS_Free(source_file.data);
- return E_SS_FAILURE;
- }
- }
- }
- }
- } else { //in case of kernel delta need to copy kernel data from blk to buffer
- if (SS_LoadPartition(ua_dataSS->parti_info->ua_blk_name, &source_file) != 0) {
- SS_SetUpgradeState(E_SS_IMGSRCCURRUPTED);
- LOGE("Fatal Error : Kernel block is corrupted\n");
- return E_SS_FAILURE;
- }
- }
- if (use_backup_img == -1) {
- backupsrc = SS_BackupSource(ua_dataSS->parti_info->ua_blk_name);
- if (backupsrc != 0) {
- LOGE("failed to Backup source File:[%s] \n", ua_dataSS->parti_info->ua_blk_name);
- SS_SetUpgradeState(E_SS_IMGSRCBACKUPFAILED);
- return E_SS_FAILURE;
- }
- }
- //Cleanup workspace and copy helper executables to it before proceeding
- SS_DeleteFolder(NULL, SS_KERNEL_WORKSPACE);
- create_dir(SS_KERNEL_WORKSPACE, 0755);
- SS_CopyFile(NULL, SS_GZIP_SOURCE, SS_GZIP_TARGET);
- SS_CopyFile(NULL, SS_STAT_SOURCE, SS_STAT_TARGET);
- SS_CopyFile(NULL, SS_DD_SOURCE, SS_DD_TARGET);
-
- if (tar_get_item_size(ua_dataSS->update_data->ua_delta_path, SS_KERNEL_UNPACK_SCRIPT) > 0)
- if (tar_extract_file(ua_dataSS->update_data->ua_delta_path, SS_KERNEL_UNPACK_SCRIPT, SS_KERN_UNPK_SCRIPT_PATH) >
- 0)
- LOGL(LOG_SSENGINE, "Extracted %s successfully\n", SS_KERNEL_UNPACK_SCRIPT);
- else {
- LOGE("Error in fn tar_extract_file for item %s", SS_KERNEL_UNPACK_SCRIPT);
- SS_SetUpgradeState(E_SS_DELTA_IS_CORRUPT);
- result = E_SS_FAILURE;
- goto Cleanup;
- } else {
- LOGE("Error size is not positive for item %s", SS_KERNEL_UNPACK_SCRIPT);
- SS_SetUpgradeState(E_SS_DELTA_IS_CORRUPT);
- result = E_SS_FAILURE;
- goto Cleanup;
- }
- //Now write the kernel data to the workplace and start applying patch
- snprintf(source_filename, sizeof(source_filename) - 1, "%s/%s", SS_KERNEL_WORKSPACE, SS_KERNEL_NAME);
- fp = fopen(source_filename, "w");
- if (!fp) {
- LOGE("file open error [%s] code [%d]\n", source_filename, errno);
- SS_Free(source_file.data);
- result = E_SS_FAILURE;
- goto Cleanup;
- }
- //write source kernel data to workspace
- read_count = fwrite(source_file.data, 1, source_file.size, fp);
- if (read_count != source_file.size) {
- LOGE("file write error read_count = %d for [%s]\n", read_count, source_filename);
- SS_Free(source_file.data);
- result = E_SS_FAILURE;
- goto Cleanup;
- }
- SS_Free(source_file.data);
- fclose(fp);
- fp = NULL;//wgid: 59313
-
- //Unpack source kernel
- int offset = getOffset(source_filename);
- if(offset < 0){
- LOGE("Failed to get offset\n");
- result = E_SS_FAILURE;
- goto Cleanup;
- }
- snprintf(cmd, sizeof(cmd) - 1, "%s -u %s %s %d", SS_KERN_UNPK_SCRIPT_PATH, SS_KERNEL_WORKSPACE, SS_KERNEL_NAME,
- offset);
- int ret = _system_cmd_wait(cmd);
- LOGL(LOG_SSENGINE, "ret for %s is %d\n", cmd, ret);
-
- //open delta file, extract kernel delta parts and apply patch to previously unpacked kernel
- fp = fopen(SS_PATCHFILE_SOURCE, "r");
- if (fp == NULL) {
- LOGE("Failed to open kernel delta patch\n");
- result = E_SS_FAILURE;
- goto Cleanup;
- }
- //read kernel delta header for delta names and size
- buf = SS_Malloc(SS_KERNEL_DELTA_HEADER);
- if(!buf){//wgid: 13099
- LOGE("Failed to allocate memory\n");
- result = E_SS_MALLOC_ERROR;
- goto Cleanup;
- }
- fread(buf, 1, SS_KERNEL_DELTA_HEADER, fp);
- magic = strtok(buf, ":");
- file_num = atoi(strtok(NULL, ":"));
-
- //adjust offset to start of data section before proceeding
- fseek(fp, SS_KERNEL_DELTA_HEADER, SEEK_SET);
-
- while (file_num-- > 0) {
- file_name = strtok(NULL, ":");
- file_len = atoi(strtok(NULL, ":"));
- j = file_len;
- snprintf(source_filename, sizeof(source_filename) - 1, "%s/%s_unpacked/%s", SS_KERNEL_WORKSPACE, SS_KERNEL_NAME,
- file_name);
- snprintf(part_filename, sizeof(part_filename) - 1, "%s/%s", SS_KERNEL_WORKSPACE, file_name);
- wp = fopen(part_filename, "w");
- while (j-- > 0) {
- a = fgetc(fp);
- fputc(a, wp);
- }
- fclose(wp);
-
- //apply bspatch to the unpacked kernel parts
-
- {
- // We write the decoded output to "<tgt-file>.patch".
- //allocate some extra space to allow for concatinating ".patch" with the name
- outname = (char *)SS_Malloc(strlen(source_filename) + 10);
- if (outname == NULL) {
- SS_SetUpgradeState(E_SS_MALLOC_ERROR);
- result = E_SS_FAILURE;
- goto Cleanup;
- }
- strcpy(outname, source_filename);
- strcat(outname, ".patch");
-
- output = open(outname, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
- if (output < 0) {
- LOGE("failed to open output file %s: %s\n", outname, strerror(errno));
- SS_Free(outname);
- result = E_SS_FAILURE;
- goto Cleanup;
- }
- sink = ss_fileSink;
- tok = &output;
- }
- result = SS_ApplyBsdiff(source_filename, outname, part_filename, sink, tok, NULL);
- LOGL(LOG_SSENGINE, "GenerateTarget Output is %d and result is %d\n", output, result);
- if (output >= 0) {
- fsync(output);
- close(output);
- }
-
- if (result != S_SS_SUCCESS) {
- LOGE("applying patch failed %s\n", source_filename);
- if (outname != NULL) {
- unlink(outname);
- }
- goto Cleanup;
- }
- result = rename(outname, source_filename);
- if (result != S_SS_SUCCESS) {
- LOGE("fatal error %s\n", source_filename);
- goto Cleanup;
- }
- if (strcmp(file_name, "piggy") == 0) {
- snprintf(cmd, sizeof(cmd) - 1,
- "%s/gzip -n -9 -c %s/%s/%s > %s/%s/%s.gz",
- SS_KERNEL_WORKSPACE, SS_KERNEL_WORKSPACE, SS_KERNEL_UNPACK_DIR, file_name,
- SS_KERNEL_WORKSPACE, SS_KERNEL_UNPACK_DIR, file_name);
- result = _system_cmd_wait(cmd);
- LOGL(LOG_SSENGINE, "ret for %s = %d\n", cmd, result);
- unlink(source_filename);
- }
- unlink(part_filename);
- }
- //open new kernel file and append kernel parts to it in
- snprintf(source_filename, sizeof(source_filename) - 1, "%s/%s", SS_KERNEL_WORKSPACE, SS_KERNEL_TARGET_NAME);
- kp = fopen(source_filename, "w");
- for (i = 0; i < 4; i++) {
- snprintf(part_filename, sizeof(part_filename) - 1, "%s/%s/%s", SS_KERNEL_WORKSPACE, SS_KERNEL_UNPACK_DIR,
- kernel_parts[i]);
- wp = fopen(part_filename, "r");
- fseek(wp, SEEK_SET, SEEK_END);
- j = ftell(wp);
- fseek(wp, SEEK_SET, SEEK_SET);
- while (j-- > 0) {
- a = fgetc(wp);
- if(a != EOF)//wgid: 4428
- fputc(a, kp);
- else
- break;
- }
- fclose(wp);
- unlink(part_filename);
- }
- fclose(fp);
- fp = NULL;
- fclose(kp);
-
- if (SS_LoadFile(source_filename, &source_file) == 0)
- result = memcmp(source_file.sha1, target_sha1, SHA_DIGEST_SIZE);
- if (result != S_SS_SUCCESS) {
- LOGE("patch did not produce expected sha1 \n");
- SS_SetUpgradeState(E_SS_IMGSHA_MISMATCH);
- goto Cleanup;
- }
- //Considering EMMC partition by deafult
-
- blk_cnt = ((ua_dataSS->update_cfg->target_img_size - 1) / SECTOR_SIZE) + 1;
- result = write_to_blkdev((char *)ua_dataSS->parti_info->ua_blk_name, blk_start, blk_cnt, (char *)source_file.data);
- if (result != S_SS_SUCCESS) {
- LOGE("write of patched data to %s failed\n", ua_dataSS->parti_info->ua_blk_name); // All returns should go to CLEAN UP.
- SS_SetUpgradeState(E_SS_IMGFLASHWRITEFAIL);
- goto Cleanup;
- }
-
- Cleanup:
- SS_BackupSourceClear();
- SS_PatchSourceClear();
- SS_DeleteFile(NULL, SS_KERN_UNPK_SCRIPT_PATH);
- SS_DeleteFolder(NULL, SS_KERNEL_WORKSPACE);
- SS_Free(buf);
- SS_Free(outname);//wgid: 20740
- if (result == S_SS_SUCCESS)
- LOGL(LOG_SSENGINE, "************* SS_UpdateDeltaKernel SUCCESS *****************\n");
- else{
- LOGL(LOG_SSENGINE, "************* SS_UpdateDeltaKernel FAILED *****************\n");
- if(fp)
- fclose(fp);//wgid:14711
- }
- return result;
-
-}
-
-/*!
- *********************************************************************************
- * SS_UpdateDeltaIMG
- *********************************************************************************
- *
- * @brief
- * This is used to apply patch for an image during delta Image upgrade
- *
- *
- * @param
- *
- * @return 0 - in case of success
- * 1 - in case of error during patch application
- *
- *********************************************************************************
- */
-
-int SS_UpdateDeltaIMG(ua_dataSS_t * ua_dataSS, int (*write_to_blkdev) (char *, int, int, char *))
-{
- uint8_t target_sha1[SHA_DIGEST_SIZE];
- uint8_t source_sha1[SHA_DIGEST_SIZE];
- const uint8_t current_target_sha1[SHA_DIGEST_SIZE];
- FileInfo source_file;
- sha1_ctx_t ctx1;
- MemorySinkInfo msi;
- int result = S_SS_SUCCESS;
- int blk_cnt;
- int blk_start = 0;
- int backupsrc = -1;
- int use_backup_img = -1;
- int fd = -1;
- if (ParseSha1(ua_dataSS->update_cfg->target_sha1, target_sha1) != 0) {
- LOGE("failed to parse tgt-sha1 \"%s\"\n", ua_dataSS->update_cfg->target_sha1);
- return E_SS_FAILURE;
- }
-
- source_file.size = ua_dataSS->update_cfg->soure_img_size;
- source_file.data = NULL;
- if (0 == gvalid_session) {
-
- if (ParseSha1(ua_dataSS->update_cfg->soure_sha1, source_sha1) != 0) {
- LOGE("failed to parse Src-sha1 \"%s\"\n", ua_dataSS->update_cfg->soure_sha1);
- return E_SS_FAILURE;
- }
-
- if (SS_LoadPartition(ua_dataSS->parti_info->ua_blk_name, &source_file) == 0) {
- if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
- LOGL(LOG_SSENGINE, "SS_UpdateDeltaIMG - Patch Can be applied\n");
- SS_Free(source_file.data);
- } else if (memcmp(source_file.sha1, target_sha1, SHA_DIGEST_SIZE) == 0) {
- LOGL(LOG_SSENGINE, "SS_UpdateDeltaIMG - Patch Already applied\n");
- SS_Free(source_file.data);
- return S_SS_SUCCESS;
- } else {
- SS_Free(source_file.data);
- source_file.data = NULL;
- LOGL(LOG_SSENGINE, "SS_UpdateDeltaIMG - Source was currupted, Try loading from backup source\n");
- if (SS_LoadPartition(SS_BACKUP_SOURCE, &source_file) == 0) {
- if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) {
- use_backup_img = 1;
- SS_Free(source_file.data);
- LOGL(LOG_SSENGINE,
- "SS_UpdateDeltaIMG - Patch Can be applied from using backup file as source\n");
- } else {
- SS_SetUpgradeState(E_SS_IMGSRCCURRUPTED);
- SS_Free(source_file.data);
- return E_SS_FAILURE;
- }
- }
- }
- }
- }
- if (use_backup_img == -1) {
- backupsrc = SS_BackupSource(ua_dataSS->parti_info->ua_blk_name);
- if (backupsrc != 0) {
- LOGE("failed to Backup source File:[%s] \n", ua_dataSS->parti_info->ua_blk_name);
- SS_SetUpgradeState(E_SS_IMGSRCBACKUPFAILED);
- return E_SS_FAILURE;
- }
- }
- SinkFn sink = NULL;
- void *token = NULL;
-
- blk_cnt = ((ua_dataSS->update_cfg->target_img_size - 1) / SECTOR_SIZE) + 1;
-
- msi.buffer = SS_Malloc(blk_cnt * SECTOR_SIZE);
- if (msi.buffer == NULL) {
- LOGE("failed to alloc %ld bytes for output\n", (long)ua_dataSS->update_cfg->target_img_size);
- SS_SetUpgradeState(E_SS_MALLOC_ERROR);
- return E_SS_FAILURE;
- }
- msi.pos = 0;
- msi.size = ua_dataSS->update_cfg->target_img_size;
- sink = ss_memorySink;
- token = &msi;
-
- sha1_init(&ctx1);
- //if souce was corrupted, use backup to apply diff
- if (use_backup_img == -1)
- result =
- SS_ApplyBsdiff((char *)ua_dataSS->parti_info->ua_blk_name, NULL, SS_PATCHFILE_SOURCE, sink, token, &ctx1);
- else
- result = SS_ApplyBsdiff(SS_BACKUP_SOURCE, NULL, SS_PATCHFILE_SOURCE, sink, token, &ctx1);
- if (result != S_SS_SUCCESS) {
- LOGE("failed to SS_ApplyBsdiff\n");
- SS_SetUpgradeState(E_SS_IMGRECOVERYWRITEFAILED);
- goto Cleanup;
- }
-
- sha1_final(&ctx1, (uint32_t *) & current_target_sha1);
- result = memcmp(current_target_sha1, target_sha1, SHA_DIGEST_SIZE);
- if (result != S_SS_SUCCESS) {
- LOGE("patch did not produce expected sha1 \n");
- SS_SetUpgradeState(E_SS_IMGSHA_MISMATCH);
- goto Cleanup;
- }
- //Considering EMMC partition by deafult
-
- if (ua_dataSS->update_cfg->update_type == DELTA_IMG) {
- blk_cnt = ((ua_dataSS->update_cfg->target_img_size - 1) / SECTOR_SIZE) + 1;
- result = write_to_blkdev((char *)ua_dataSS->parti_info->ua_blk_name, blk_start, blk_cnt, (char *)msi.buffer);
- if (result != S_SS_SUCCESS) {
- LOGE("write of patched data to %s failed\n", ua_dataSS->parti_info->ua_blk_name); // All returns should go to CLEAN UP.
- SS_SetUpgradeState(E_SS_IMGFLASHWRITEFAIL);
- goto Cleanup;
- }
- } else if (ua_dataSS->update_cfg->update_type == EXTRA && ua_dataSS->update_data->ua_temp_path) {
- fd = open(ua_dataSS->update_data->ua_temp_path, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
- if (fd < 0) {
- LOGE("failed to open %s for write: %s\n", ua_dataSS->update_data->ua_temp_path, strerror(errno));
- SS_SetUpgradeState(E_SS_IMGRECOVERYWRITEFAILED);
- result = E_SS_FAILURE;
- goto Cleanup;
- }
- result = SS_WriteFile(NULL, fd, 0, msi.buffer, msi.size);
- if (result != S_SS_SUCCESS) {
- LOGE("failed to write\n");
- SS_SetUpgradeState(E_SS_IMGRECOVERYWRITEFAILED);
- goto Cleanup;
- }
- fsync(fd);
- }
- else {
- SS_SetUpgradeState(E_SS_IMGUPDATEFAILED);
- result = E_SS_FAILURE;
- LOGE("failed to apply patch - Invalid Update type params \n");
- }
-
- Cleanup:
- SS_BackupSourceClear();
- SS_PatchSourceClear();
- if (msi.buffer)
- SS_Free(msi.buffer);
- if (fd >= 0)
- close(fd);
- if (result == S_SS_SUCCESS)
- LOGL(LOG_SSENGINE, "************* SS_UpdateDeltaIMG SUCCESS *****************\n");
- return result;
-
-}
+++ /dev/null
-/*
- * libtota
- *
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _SS_PATCHDELTA_H
-#define _SS_PATCHDELTA_H
-
-#include <stdint.h>
-#include "sha1.h"
-#include "unistd.h"
-#include "fcntl.h"
-#include "errno.h"
-#include "SS_Engine_Update.h"
-
-//#define ENHANCED_BSDIFF
-#define SS_UPDATE_FS 0
-#define SS_UPDATE_IMG 1
-//#define SHA_DIGEST_SIZE 20
-typedef struct {
- int type;
- ssize_t size;
- char *data;
-} Value;
-typedef struct _Patch {
- uint8_t sha1[SHA_DIGEST_SIZE];
- const char *patch_filename;
-} Patch;
-
-typedef struct _FileInfo {
- unsigned char sha1[20]; //SHA_DIGEST_SIZE 20
- unsigned char *data;
- int size;
- struct stat st;
-} FileInfo;
-
-typedef ssize_t(*SinkFn) (unsigned char *, ssize_t, void *);
-
-int ParseSha1(const char *str, uint8_t * digest);
-
-void ShowBSDiffLicense();
-int ApplyBSDiffPatch(const unsigned char *old_data, ssize_t old_size,
- const Value * patch, ssize_t patch_offset, SinkFn sink, void *token, sha1_ctx_t * ctx1);
-int ApplyBSDiffPatchMem(const unsigned char *old_data, ssize_t old_size,
- const Value * patch, ssize_t patch_offset, unsigned char **new_data, ssize_t * new_size);
-//int ApplyOptimizedBSDiffPatch(const unsigned char* old_data,void* token,
-// const Value* patch, SinkFn sink,sha1_ctx_t* ctx1);
-
-int SS_LoadPartition(const char *filename, FileInfo * file);
-int SS_LoadFile(const char *filename, FileInfo * file);
-extern void SS_SetUpgradeState(int Val);
-extern long SS_GetAvailableFreeSpace(void *pbUserData, const char *partition_name, SS_UINT32 * available_flash_size);
-extern int SS_BackupSource(const char *source_filename);
-extern int SS_ApplyBsdiff(char *oldfile, char *newfile, char *patch, SinkFn sink, void *token, sha1_ctx_t * ctx1);
-extern int SS_BackupSourceClear();
-extern int SS_PatchSourceClear();
-extern long SS_WriteFile(void *pbUserData,
- long wHandle, SS_UINT32 dwPosition, unsigned char *pbBuffer, SS_UINT32 dwSize);
-extern void SS_Free(void * pMemBlock);
-extern long SS_CopyFile(void * pbUserData, const char * strFromPath, const char * strToPath);
-extern long SS_DeleteFolder(void * pbUserData, const char * strPath);
-extern long SS_DeleteFile(void * pbUserData, const char * strPath);
-extern int tar_get_item_size(char * tar, char * item);
-extern int tar_extract_file(char * tar, char * item, char * pathname);
-extern int _system_cmd_wait(const char * command);
-#endif