-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpartition.c
More file actions
153 lines (132 loc) · 3.74 KB
/
Copy pathpartition.c
File metadata and controls
153 lines (132 loc) · 3.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*
* SPDX-FileType: SOURCE
*
* SPDX-FileCopyrightText: 2026 Nick Kossifidis <mick@ics.forth.gr>
* SPDX-FileCopyrightText: 2026 ICS/FORTH
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <img.h>
#include <utils.h>
#include "res.h"
#include "crypto_ops.h"
#include "partition.h"
/*
* Forward-declare the liblz4-hc functions we need. Including <lz4hc.h>
* directly conflicts with src/include/lz4.h at the same include path.
*/
extern int LZ4_compress_HC(const char *src, char *dst, int srcSize,
int dstCapacity, int compressionLevel);
extern int LZ4_compressBound(int inputSize);
#define LZ4HC_CLEVEL_MAX 12
static inline size_t
pad8(size_t n)
{
return (n + 7) & ~(size_t)7;
}
struct part_t *
part_new(uint8_t unit_id, uint8_t type, uint16_t version,
uint8_t flags, struct cops_ctx *cops, struct res_t *res)
{
struct part_t *part = NULL;
size_t sig_sz = 0, cmp_size = 0, pad_size = 0, alloc_sz = 0;
int bound = 0;
part = malloc(sizeof(struct part_t));
if (!part)
return NULL;
memset(part, 0, sizeof(struct part_t));
part->cops = cops;
part->orig = res;
part->hdr.raw = 0;
part->hdr.version = version;
part->hdr.type = type;
part->hdr.unit_id = unit_id;
part->hdr.flags = flags;
part->hdr.image_size = (uint32_t)res->size;
sig_sz = cops_sig_size(cops);
if (flags == PART_FLAG_LZ4) {
if (res->size > (size_t)INT_MAX) {
ERR("Input too large for LZ4: %zu bytes\n", res->size);
goto cleanup;
}
bound = LZ4_compressBound((int)res->size);
alloc_sz = sizeof(part_hdr_t) + sig_sz + (size_t)bound + 8;
part->buf = calloc(alloc_sz, 1);
if (!part->buf)
goto cleanup;
cmp_size = (size_t)LZ4_compress_HC(
(const char *)res->buf,
(char *)(part->buf + sizeof(part_hdr_t) + sig_sz),
(int)res->size, bound, LZ4HC_CLEVEL_MAX);
if (!cmp_size) {
ERR("LZ4 compression failed\n");
goto cleanup;
}
part->payload_size = cmp_size;
INF(" Compressed: %zu -> %zu bytes (%.1f%%)\n",
res->size, cmp_size, 100.0 * cmp_size / res->size);
} else {
part->payload_size = res->size;
pad_size = pad8(res->size);
alloc_sz = sizeof(part_hdr_t) + sig_sz + pad_size;
part->buf = calloc(alloc_sz, 1);
if (!part->buf)
goto cleanup;
memcpy(part->buf + sizeof(part_hdr_t) + sig_sz, res->buf, res->size);
}
/* Zero padding bytes (calloc'd, but be explicit after LZ4 path) */
pad_size = pad8(part->payload_size);
memset(part->buf + sizeof(part_hdr_t) + sig_sz + part->payload_size, 0,
pad_size - part->payload_size);
part->size = sizeof(part_hdr_t) + sig_sz + pad_size;
return part;
cleanup:
free(part->buf);
free(part);
return NULL;
}
int
part_sign(struct part_t *part)
{
size_t sig_sz = cops_sig_size(part->cops);
size_t msg_len = 0;
uint8_t *msg = NULL;
int ret = 0;
if (!part->cops || sig_sz == 0)
return 0;
/* Signature covers part_hdr.raw || original uncompressed data */
msg_len = sizeof(part_hdr_t) + part->orig->size;
msg = malloc(msg_len);
if (!msg)
return -1;
memcpy(msg, &part->hdr.raw, sizeof(part_hdr_t));
memcpy(msg + sizeof(part_hdr_t), part->orig->buf, part->orig->size);
ret = cops_sign(part->cops, msg, msg_len, part->buf + sizeof(part_hdr_t));
free(msg);
if (ret == 0)
INF(" Partition sig: %02x%02x%02x%02x...\n",
part->buf[sizeof(part_hdr_t)],
part->buf[sizeof(part_hdr_t) + 1],
part->buf[sizeof(part_hdr_t) + 2],
part->buf[sizeof(part_hdr_t) + 3]);
return ret;
}
int
part_finalize(struct part_t *part)
{
/* Write the completed header into buf[0..sizeof(part_hdr_t)-1] */
memcpy(part->buf, &part->hdr.raw, sizeof(part_hdr_t));
res_release(part->orig);
part->orig = NULL;
return 0;
}
void
part_free(struct part_t *part)
{
free(part->buf);
free(part);
}