iPXE
md4.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2017 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 * MD4 algorithm
30 *
31 */
32
33#include <stdint.h>
34#include <assert.h>
35#include <ipxe/rotate.h>
36#include <ipxe/crypto.h>
37#include <ipxe/md4.h>
38
39/** MD4 variables */
41 /* This layout matches that of struct md4_digest_data */
47} __attribute__ (( packed ));
48
49/** MD4 shift amounts */
50static const uint8_t r[3][4] = {
51 { 3, 7, 11, 19 },
52 { 3, 5, 9, 13 },
53 { 3, 9, 11, 15 },
54};
55
56/**
57 * f(b,c,d,w) for steps 0 to 15
58 *
59 * @v v MD4 variables
60 * @v i Index within round
61 * @ret f f(b,c,d,w)
62 */
63static uint32_t md4_f_0_15 ( struct md4_variables *v, unsigned int i ) {
64 return ( ( ( v->b & v->c ) | ( ~v->b & v->d ) ) + v->w[i] );
65}
66
67/**
68 * f(b,c,d,w) for steps 16 to 31
69 *
70 * @v v MD4 variables
71 * @v i Index within round
72 * @ret f f(b,c,d,w)
73 */
74static uint32_t md4_f_16_31 ( struct md4_variables *v, unsigned int i ) {
75 return ( ( ( v->b & v->c ) | ( v->b & v->d ) | ( v->c & v->d ) ) +
76 v->w[ ( ( i << 2 ) | ( i >> 2 ) ) % 16 ] );
77}
78
79/**
80 * f(b,c,d,w) for steps 32 to 47
81 *
82 * @v v MD4 variables
83 * @v i Index within round
84 * @ret f f(b,c,d,w)
85 */
86static uint32_t md4_f_32_47 ( struct md4_variables *v, unsigned int i ) {
87 static const uint8_t reverse[16] = {
88 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
89 };
90 return ( ( v->b ^ v->c ^ v->d ) + v->w[reverse[i]] );
91}
92
93/** An MD4 step function */
94struct md4_step {
95 /**
96 * Calculate f(b,c,d,w)
97 *
98 * @v v MD4 variables
99 * @v i Index within round
100 * @ret f f(b,c,d,w)
101 */
102 uint32_t ( * f ) ( struct md4_variables *v, unsigned int i );
103 /** Constant */
105};
106
107/** MD4 steps */
108static const struct md4_step md4_steps[4] = {
109 /** 0 to 15 */
110 { .f = md4_f_0_15, .constant = 0x00000000UL },
111 /** 16 to 31 */
112 { .f = md4_f_16_31, .constant = 0x5a827999UL },
113 /** 32 to 47 */
114 { .f = md4_f_32_47, .constant = 0x6ed9eba1UL },
115};
116
117/** MD4 initial digest values */
118static const struct md4_digest md4_init = {
119 .h = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 }
120};
121
122/**
123 * Calculate MD4 digest of accumulated data
124 *
125 * @v dd Digest and data block
126 * @v digest Copy of current digest value
127 */
128static void md4_compress ( struct md4_digest_data *dd,
129 const struct md4_digest *digest ) {
130 union {
131 struct md4_digest_data dd;
132 struct md4_variables v;
133 } *u = container_of ( dd, typeof ( *u ), dd );
134 struct md4_variables *v = &u->v;
135 const struct md4_step *step;
136 uint32_t *a = &v->a;
137 uint32_t *b = &v->b;
138 uint32_t *c = &v->c;
139 uint32_t *d = &v->d;
140 uint32_t *w = v->w;
141 uint32_t f;
142 uint32_t temp;
143 unsigned int round;
144 unsigned int i;
145
146 /* Sanity checks */
147 build_assert ( &u->dd.digest.h[0] == a );
148 build_assert ( &u->dd.digest.h[1] == b );
149 build_assert ( &u->dd.digest.h[2] == c );
150 build_assert ( &u->dd.digest.h[3] == d );
151 build_assert ( &u->dd.data.dword[0] == w );
152 build_assert ( sizeof ( u->dd ) == sizeof ( u->v ) );
153
154 /* Main loop */
155 for ( i = 0 ; i < 48 ; i++ ) {
156 round = ( i / 16 );
157 step = &md4_steps[round];
158 f = step->f ( v, ( i % 16 ) );
159 temp = *d;
160 *d = *c;
161 *c = *b;
162 *b = rol32 ( ( *a + f + step->constant ), r[round][ i % 4 ] );
163 *a = temp;
164 DBGC2 ( &md4_algorithm, "%2d : %08x %08x %08x %08x\n",
165 i, *a, *b, *c, *d );
166 }
167
168 /* Add chunk to hash */
169 for ( i = 0 ; i < 4 ; i++ )
170 dd->digest.h[i] += digest->h[i];
171}
172
173/** MD4 algorithm */
typeof(acpi_finder=acpi_find)
ACPI table finder.
Definition acpi.c:48
unsigned int uint32_t
Definition stdint.h:12
unsigned char uint8_t
Definition stdint.h:10
Assertions.
#define build_assert(condition)
Assert a condition at build time (after dead code elimination).
Definition assert.h:88
union @104331263140136355135267063077374276003064103115 u
#define DBGC2(...)
Definition compiler.h:547
#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
#define __attribute__(x)
Definition compiler.h:10
#define __LITTLE_ENDIAN
Constant representing little-endian byte order.
Definition endian.h:13
Cryptographic API.
static const uint8_t r[3][4]
MD4 shift amounts.
Definition md4.c:50
static const struct md4_digest md4_init
MD4 initial digest values.
Definition md4.c:118
static const struct md4_step md4_steps[4]
MD4 steps.
Definition md4.c:108
static uint32_t md4_f_32_47(struct md4_variables *v, unsigned int i)
f(b,c,d,w) for steps 32 to 47
Definition md4.c:86
static uint32_t md4_f_16_31(struct md4_variables *v, unsigned int i)
f(b,c,d,w) for steps 16 to 31
Definition md4.c:74
static void md4_compress(struct md4_digest_data *dd, const struct md4_digest *digest)
Calculate MD4 digest of accumulated data.
Definition md4.c:128
static uint32_t md4_f_0_15(struct md4_variables *v, unsigned int i)
f(b,c,d,w) for steps 0 to 15
Definition md4.c:63
MD4 algorithm.
#define MD4_DIGEST_SIZE
MD4 digest size.
Definition md4.h:57
struct digest_algorithm md4_algorithm
#define MDHASH_ALGORITHM(_name, _digest, _compress, _byteorder, _dd, _init, _digestsize)
Define a Merkle-Damgård hash algorithm.
Definition mdhash.h:137
void step(void)
Single-step a single process.
Definition process.c:99
Bit operations.
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
MD4 digest and data block.
Definition md4.h:43
struct md4_digest digest
Digest of data already processed.
Definition md4.h:45
An MD4 digest.
Definition md4.h:18
uint32_t h[4]
Hash output.
Definition md4.h:20
An MD4 step function.
Definition md4.c:94
uint32_t constant
Constant.
Definition md4.c:104
uint32_t(* f)(struct md4_variables *v, unsigned int i)
Calculate f(b,c,d,w).
Definition md4.c:102
MD4 variables.
Definition md4.c:40
uint32_t c
Definition md4.c:44
uint32_t b
Definition md4.c:43
uint32_t w[16]
Definition md4.c:46
uint32_t a
Definition md4.c:42
uint32_t d
Definition md4.c:45
static u32 rol32(u32 v, int bits)
Rotate 32-bit value left.
Definition wpa_tkip.c:174