iPXE
mdhash.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2026 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27/** @file
28 *
29 * Merkle-Damgård hash algorithms
30 *
31 */
32
33#include <stdint.h>
34#include <string.h>
35#include <assert.h>
36#include <ipxe/crypto.h>
37#include <ipxe/mdhash.h>
38
39/**
40 * Initialise algorithm
41 *
42 * @v digest Digest algorithm
43 * @v ctx MD hash context
44 */
45void mdhash_init ( struct digest_algorithm *digest, void *ctx ) {
46 const struct mdhash_algorithm *mdhash = digest->priv;
47 size_t blocksize = digest->blocksize;
48 size_t digestsize = mdhash->digestsize;
49 mdhash_context_t ( digestsize, blocksize ) *context = ctx;
50
51 /* Zero accumulated data length */
52 context->len = 0;
53
54 /* Copy initial digest values */
55 memcpy ( &context->dd.digest, mdhash->init, digestsize );
56}
57
58/**
59 * Accumulate data
60 *
61 * @v digest Digest algorithm
62 * @v ctx MD hash context
63 * @v data Data
64 * @v len Length of data
65 */
66void mdhash_update ( struct digest_algorithm *digest, void *ctx,
67 const void *data, size_t len ) {
68 const struct mdhash_algorithm *mdhash = digest->priv;
69 size_t blocksize = digest->blocksize;
70 size_t digestsize = mdhash->digestsize;
71 mdhash_context_t ( digestsize, blocksize ) *context = ctx;
72 const uint8_t *byte = data;
73 uint8_t copy[digestsize];
74 unsigned int toggle;
75 unsigned int mask;
76 size_t offset;
77
78 /* Accumulate data a byte at a time, swapping endianness as we
79 * go and performing the digest whenever we fill the data
80 * buffer.
81 */
82 toggle = mdhash->toggle;
83 mask = ( blocksize - 1 );
84 while ( len-- ) {
85 offset = ( ( context->len++ ^ toggle ) & mask );
86 context->dd.data[offset] = *(byte++);
87 if ( ( context->len & mask ) == 0 ) {
88 DBGC2 ( digest, "MDHASH %s compressing:\n",
89 digest->name );
90 DBGC2_HDA ( digest, 0, &context->dd.digest,
91 sizeof ( context->dd.digest ) );
92 DBGC2_HDA ( digest, 0, &context->dd.data,
93 sizeof ( context->dd.data ) );
94 memcpy ( copy, &context->dd.digest, digestsize );
95 mdhash->compress ( &context->dd, copy );
96 DBGC2 ( digest, "MDHASH %s compressed:\n",
97 digest->name );
98 DBGC2_HDA ( digest, 0, &context->dd.digest,
99 sizeof ( context->dd.digest ) );
100 }
101 }
102}
103
104/**
105 * Generate digest
106 *
107 * @v digest Digest algorithm
108 * @v ctx MD hash context
109 * @v out Output buffer
110 */
111void mdhash_final ( struct digest_algorithm *digest, void *ctx, void *out ) {
112 const struct mdhash_algorithm *mdhash = digest->priv;
113 size_t blocksize = digest->blocksize;
114 size_t digestsize = mdhash->digestsize;
115 mdhash_context_t ( digestsize, blocksize ) *context = ctx;
116 uint8_t *byte = out;
117 union mdhash_len len;
118 unsigned int toggle;
119 unsigned int mask;
120 unsigned int stop;
121 unsigned int i;
122 uint8_t pad;
123
124 /* Record length before pre-processing */
125 len.qword.bits = ( ( ( uint64_t ) context->len ) * 8 );
126 len.qword.pad = 0;
127
128 /* Pad with a single "1" bit followed by as many "0" bits as required */
129 mask = ( blocksize - 1 );
130 stop = ( blocksize - mdhash->len_len );
131 pad = 0x80;
132 do {
133 mdhash_update ( digest, ctx, &pad, sizeof ( pad ) );
134 pad = 0x00;
135 } while ( ( context->len & mask ) != stop );
136
137 /* Append length (in bits) */
138 toggle = mdhash->len_toggle;
139 for ( i = 0 ; i < mdhash->len_len ; i++ ) {
140 mdhash_update ( digest, ctx, &len.byte[ i ^ toggle ],
141 sizeof ( len.byte[ i ^ toggle ] ) );
142 }
143 assert ( ( context->len & mask ) == 0 );
144
145 /* Copy out final digest */
146 toggle = mdhash->toggle;
147 for ( i = 0 ; i < digest->digestsize ; i++ )
148 byte[i] = context->dd.digest[ i ^ toggle ];
149 DBGC ( digest, "MDHASH %s digested:\n", digest->name );
150 DBGC_HDA ( digest, 0, out, digest->digestsize );
151}
struct golan_eq_context ctx
Definition CIB_PRM.h:0
__be32 out[4]
Definition CIB_PRM.h:8
u32 pad[9]
Padding.
Definition ar9003_mac.h:23
unsigned long long uint64_t
Definition stdint.h:13
unsigned char uint8_t
Definition stdint.h:10
Assertions.
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
uint16_t offset
Offset to command line.
Definition bzimage.h:3
ring len
Length.
Definition dwmac.h:226
uint8_t data[48]
Additional event data.
Definition ena.h:11
#define DBGC2(...)
Definition compiler.h:547
#define DBGC2_HDA(...)
Definition compiler.h:548
#define DBGC(...)
Definition compiler.h:530
#define DBGC_HDA(...)
Definition compiler.h:531
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:921
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:951
Cryptographic API.
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void mdhash_update(struct digest_algorithm *digest, void *ctx, const void *data, size_t len)
Accumulate data.
Definition mdhash.c:66
void mdhash_final(struct digest_algorithm *digest, void *ctx, void *out)
Generate digest.
Definition mdhash.c:111
void mdhash_init(struct digest_algorithm *digest, void *ctx)
Initialise algorithm.
Definition mdhash.c:45
Merkle-Damgård hash algorithms.
#define mdhash_context_t(digestsize, blocksize)
Merkle-Damgård hash algorithm context.
Definition mdhash.h:28
uint32_t digestsize
Digest size (i.e.
Definition pccrr.h:1
A message digest algorithm.
Definition crypto.h:19
size_t digestsize
Digest size.
Definition crypto.h:27
size_t blocksize
Block size.
Definition crypto.h:25
void * priv
Algorithm private data.
Definition crypto.h:54
const char * name
Algorithm name.
Definition crypto.h:21
Merkle-Damgård hash algorithm.
Definition mdhash.h:50
const void * init
Initial digest value (as host-endian words).
Definition mdhash.h:63
uint8_t len_len
Length field length.
Definition mdhash.h:82
uint8_t digestsize
Digest size (before any final truncation).
Definition mdhash.h:65
uint8_t toggle
Data toggle (for endianness swapping).
Definition mdhash.h:76
uint8_t len_toggle
Length field toggle (for endianness swapping).
Definition mdhash.h:89
void(* compress)(void *dd, const void *digest)
Compression function.
Definition mdhash.h:61
Merkle-Damgård trailing bit-length count.
Definition mdhash.h:37