/
githubmirror
/
ipxe
Обзор
Документация
Войти
/
githubmirror
/
ipxe
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/crypto/mdhash.c
151 строка
4 KB
Michael Brown
[crypto] Generalise implementation of Merkle-Damgård hash algorithms
23 июн 2026, 15:24
23 июн 2026, 15:24
327378a
Код
Авторство
О чём код?
/* * Copyright (C) 2026 Michael Brown <mbrown@fensystems.co.uk>. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * * You can also choose to distribute this program under the terms of * the Unmodified Binary Distribution Licence (as given in the file * COPYING.UBDL), provided that you have satisfied its requirements. */ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); FILE_SECBOOT ( PERMITTED ); /** @file * * Merkle-Damgård hash algorithms * */ #include <stdint.h> #include <string.h> #include <assert.h> #include <ipxe/crypto.h> #include <ipxe/mdhash.h> /** * Initialise algorithm * * @v digest Digest algorithm * @v ctx MD hash context */ void mdhash_init ( struct digest_algorithm *digest, void *ctx ) { const struct mdhash_algorithm *mdhash = digest->priv; size_t blocksize = digest->blocksize; size_t digestsize = mdhash->digestsize; mdhash_context_t ( digestsize, blocksize ) *context = ctx; /* Zero accumulated data length */ context->len = 0; /* Copy initial digest values */ memcpy ( &context->dd.digest, mdhash->init, digestsize ); } /** * Accumulate data * * @v digest Digest algorithm * @v ctx MD hash context * @v data Data * @v len Length of data */ void mdhash_update ( struct digest_algorithm *digest, void *ctx, const void *data, size_t len ) { const struct mdhash_algorithm *mdhash = digest->priv; size_t blocksize = digest->blocksize; size_t digestsize = mdhash->digestsize; mdhash_context_t ( digestsize, blocksize ) *context = ctx; const uint8_t *byte = data; uint8_t copy[digestsize]; unsigned int toggle; unsigned int mask; size_t offset; /* Accumulate data a byte at a time, swapping endianness as we * go and performing the digest whenever we fill the data * buffer. */ toggle = mdhash->toggle; mask = ( blocksize - 1 ); while ( len-- ) { offset = ( ( context->len++ ^ toggle ) & mask ); context->dd.data[offset] = *(byte++); if ( ( context->len & mask ) == 0 ) { DBGC2 ( digest, "MDHASH %s compressing:\n", digest->name ); DBGC2_HDA ( digest, 0, &context->dd.digest, sizeof ( context->dd.digest ) ); DBGC2_HDA ( digest, 0, &context->dd.data, sizeof ( context->dd.data ) ); memcpy ( copy, &context->dd.digest, digestsize ); mdhash->compress ( &context->dd, copy ); DBGC2 ( digest, "MDHASH %s compressed:\n", digest->name ); DBGC2_HDA ( digest, 0, &context->dd.digest, sizeof ( context->dd.digest ) ); } } } /** * Generate digest * * @v digest Digest algorithm * @v ctx MD hash context * @v out Output buffer */ void mdhash_final ( struct digest_algorithm *digest, void *ctx, void *out ) { const struct mdhash_algorithm *mdhash = digest->priv; size_t blocksize = digest->blocksize; size_t digestsize = mdhash->digestsize; mdhash_context_t ( digestsize, blocksize ) *context = ctx; uint8_t *byte = out; union mdhash_len len; unsigned int toggle; unsigned int mask; unsigned int stop; unsigned int i; uint8_t pad; /* Record length before pre-processing */ len.qword.bits = ( ( ( uint64_t ) context->len ) * 8 ); len.qword.pad = 0; /* Pad with a single "1" bit followed by as many "0" bits as required */ mask = ( blocksize - 1 ); stop = ( blocksize - mdhash->len_len ); pad = 0x80; do { mdhash_update ( digest, ctx, &pad, sizeof ( pad ) ); pad = 0x00; } while ( ( context->len & mask ) != stop ); /* Append length (in bits) */ toggle = mdhash->len_toggle; for ( i = 0 ; i < mdhash->len_len ; i++ ) { mdhash_update ( digest, ctx, &len.byte[ i ^ toggle ], sizeof ( len.byte[ i ^ toggle ] ) ); } assert ( ( context->len & mask ) == 0 ); /* Copy out final digest */ toggle = mdhash->toggle; for ( i = 0 ; i < digest->digestsize ; i++ ) byte[i] = context->dd.digest[ i ^ toggle ]; DBGC ( digest, "MDHASH %s digested:\n", digest->name ); DBGC_HDA ( digest, 0, out, digest->digestsize ); }