libaaruformat 1.0
Aaru Data Preservation Suite - Format Library
Loading...
Searching...
No Matches
checksum.c
Go to the documentation of this file.
1/*
2 * This file is part of the Aaru Data Preservation Suite.
3 * Copyright (c) 2019-2026 Natalia Portillo.
4 *
5 * This library is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as
7 * published by the Free Software Foundation; either version 2.1 of the
8 * License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <inttypes.h>
20#include <stdint.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24
25#include "aaruformat/context.h"
26#include "aaruformat/enums.h"
29#include "internal.h"
30#include "log.h"
31
41{
42 TRACE("Entering process_checksum_block(%p, %p)", ctx, entry);
43
44 int seek_result = 0;
45 size_t read_bytes = 0;
46 ChecksumHeader checksum_header;
47 ChecksumEntry const *checksum_entry = NULL;
48 uint8_t *data = NULL;
49 int j = 0;
50 size_t payload_pos = 0;
51
52 // Check if the context and image stream are valid
53 if(ctx == NULL || ctx->imageStream == NULL)
54 {
55 FATAL("Invalid context or image stream.");
56 return;
57 }
58
59 // Seek to block
60 seek_result = aaruf_fseek(ctx->imageStream, (aaru_off_t)entry->offset, SEEK_SET);
61 if(seek_result < 0 || aaruf_ftell(ctx->imageStream) != (aaru_off_t)entry->offset)
62 {
63 FATAL("Could not seek to %" PRIu64 " as indicated by index entry...", entry->offset);
64
65 return;
66 }
67
68 // Even if those two checks shall have been done before
69 TRACE("Reading checksum block header at position %" PRIu64, entry->offset);
70 read_bytes = fread(&checksum_header, 1, sizeof(ChecksumHeader), ctx->imageStream);
71
72 if(read_bytes != sizeof(ChecksumHeader))
73 {
74 memset(&checksum_header, 0, sizeof(ChecksumHeader));
75 FATAL("Could not read checksums block header, continuing...\n");
76 return;
77 }
78
79 if(checksum_header.identifier != ChecksumBlock)
80 {
81 memset(&checksum_header, 0, sizeof(ChecksumHeader));
82 FATAL("Incorrect identifier for checksum block at position %" PRIu64 "\n", entry->offset);
83 return;
84 }
85
86 TRACE("Allocating %u bytes for checksum block", checksum_header.length);
87 data = (uint8_t *)malloc(checksum_header.length);
88
89 if(data == NULL)
90 {
91 memset(&checksum_header, 0, sizeof(ChecksumHeader));
92 FATAL("Could not allocate memory for checksum block, continuing...\n");
93 return;
94 }
95
96 TRACE("Reading checksum block data at position %" PRIu64, entry->offset + sizeof(ChecksumHeader));
97 read_bytes = fread(data, 1, checksum_header.length, ctx->imageStream);
98
99 if(read_bytes != checksum_header.length)
100 {
101 memset(&checksum_header, 0, sizeof(ChecksumHeader));
102 free(data);
103 FATAL("Could not read checksums block, continuing...\n");
104 return;
105 }
106
107 payload_pos = 0;
108 TRACE("Processing %u checksum entries", checksum_header.entries);
109 for(j = 0; j < checksum_header.entries; j++)
110 {
111 if(payload_pos + sizeof(ChecksumEntry) > checksum_header.length)
112 {
113 FATAL("Checksum entry %d exceeds block payload size", j);
114 break;
115 }
116
117 checksum_entry = (const ChecksumEntry *)&data[payload_pos];
118 payload_pos += sizeof(ChecksumEntry);
119
120 if(payload_pos + checksum_entry->length > checksum_header.length)
121 {
122 FATAL("Checksum payload for entry %d exceeds block payload size", j);
123 break;
124 }
125
126 switch(checksum_entry->type)
127 {
128 case Md5:
129 if(checksum_entry->length != MD5_DIGEST_LENGTH)
130 {
131 FATAL("MD5 checksum entry has invalid length %u", checksum_entry->length);
132 break;
133 }
134
135 TRACE("Found MD5 checksum");
136 memcpy(ctx->checksums.md5, &data[payload_pos], MD5_DIGEST_LENGTH);
137 ctx->checksums.hasMd5 = true;
138 break;
139 case Sha1:
140 if(checksum_entry->length != SHA1_DIGEST_LENGTH)
141 {
142 FATAL("SHA1 checksum entry has invalid length %u", checksum_entry->length);
143 break;
144 }
145
146 TRACE("Found SHA1 checksum");
147 memcpy(ctx->checksums.sha1, &data[payload_pos], SHA1_DIGEST_LENGTH);
148 ctx->checksums.hasSha1 = true;
149 break;
150 case Sha256:
151 if(checksum_entry->length != SHA256_DIGEST_LENGTH)
152 {
153 FATAL("SHA256 checksum entry has invalid length %u", checksum_entry->length);
154 break;
155 }
156
157 TRACE("Found SHA256 checksum");
158 memcpy(ctx->checksums.sha256, &data[payload_pos], SHA256_DIGEST_LENGTH);
159 ctx->checksums.hasSha256 = true;
160 break;
161 case SpamSum:
162 TRACE("Found SpamSum checksum of size %u", checksum_entry->length);
163 free(ctx->checksums.spamsum);
164 ctx->checksums.spamsum = NULL;
165
166 ctx->checksums.spamsum = malloc(checksum_entry->length + 1);
167
168 if(ctx->checksums.spamsum == NULL)
169 {
170 FATAL("Could not allocate memory for SpamSum digest");
171 break;
172 }
173
174 memcpy(ctx->checksums.spamsum, &data[payload_pos], checksum_entry->length);
175 ctx->checksums.spamsum[checksum_entry->length] = '\0';
176 ctx->checksums.hasSpamSum = true;
177 break;
178 default:
179 TRACE("Unknown checksum type %u, skipping", checksum_entry->type);
180 break;
181 }
182
183 payload_pos += checksum_entry->length;
184 }
185
186 checksum_entry = NULL;
187 free(data);
188
189 TRACE("Exiting process_checksum_block()");
190}
void process_checksum_block(aaruformat_context *ctx, const IndexEntry *entry)
Processes a checksum block from the image stream.
Definition checksum.c:40
On-disk layout definitions for the checksum block (BlockType::ChecksumBlock).
Central runtime context structures for libaaruformat (image state, caches, checksum buffers).
#define MD5_DIGEST_LENGTH
Definition context.h:72
@ ChecksumBlock
Block containing contents checksums.
Definition enums.h:176
@ Sha1
SHA-1 hash.
Definition enums.h:198
@ Md5
MD5 hash.
Definition enums.h:197
@ Sha256
SHA-256 hash.
Definition enums.h:199
@ SpamSum
SpamSum (context-triggered piecewise hash).
Definition enums.h:200
On‑disk index block header and entry structures (versions 1, 2 and 3).
static int aaruf_fseek(FILE *stream, aaru_off_t offset, int origin)
Definition internal.h:46
static aaru_off_t aaruf_ftell(FILE *stream)
Definition internal.h:52
int64_t aaru_off_t
Definition internal.h:42
#define FATAL(fmt,...)
Definition log.h:40
#define TRACE(fmt,...)
Definition log.h:25
#define SHA1_DIGEST_LENGTH
Definition sha1.h:39
#define SHA256_DIGEST_LENGTH
Definition sha256.h:38
Per-checksum metadata immediately followed by the digest / signature bytes.
Definition checksum.h:91
uint32_t length
Length in bytes of the digest that immediately follows this structure.
Definition checksum.h:93
uint8_t type
Algorithm used (value from ChecksumAlgorithm).
Definition checksum.h:92
Header that precedes the sequence of checksum entries for a checksum block.
Definition checksum.h:74
uint32_t identifier
Block identifier, must be BlockType::ChecksumBlock.
Definition checksum.h:75
uint32_t length
Length in bytes of the payload (all entries + their digest data, excluding this header).
Definition checksum.h:76
uint8_t entries
Number of checksum entries that follow in the payload.
Definition checksum.h:77
uint8_t * spamsum
SpamSum fuzzy hash (ASCII), allocated length+1 with trailing 0.
Definition context.h:113
bool hasSha256
True if sha256[] buffer populated.
Definition context.h:106
uint8_t sha1[20]
SHA-1 digest (20 bytes).
Definition context.h:110
uint8_t sha256[32]
SHA-256 digest (32 bytes).
Definition context.h:111
uint8_t md5[16]
MD5 digest (16 bytes).
Definition context.h:109
bool hasSpamSum
True if spamsum pointer allocated and signature read.
Definition context.h:108
bool hasSha1
True if sha1[] buffer populated.
Definition context.h:105
bool hasMd5
True if md5[] buffer populated.
Definition context.h:104
Single index entry describing a block's type, (optional) data classification, and file offset.
Definition index.h:109
uint64_t offset
Absolute byte offset in the image where the referenced block header begins.
Definition index.h:112
Master context representing an open or in‑creation Aaru image.
Definition context.h:175
Checksums checksums
Whole-image checksums discovered.
Definition context.h:272
FILE * imageStream
Underlying FILE* stream (binary mode).
Definition context.h:179