iPXE
hmac_test.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2022 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 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 /** @file
27  *
28  * HMAC self-tests
29  *
30  */
31 
32 /* Forcibly enable assertions */
33 #undef NDEBUG
34 
35 #include <string.h>
36 #include <ipxe/hmac.h>
37 #include <ipxe/md5.h>
38 #include <ipxe/sha1.h>
39 #include <ipxe/sha256.h>
40 #include <ipxe/test.h>
41 
42 /** Define inline key data */
43 #define KEY(...) { __VA_ARGS__ }
44 
45 /** Define inline data */
46 #define DATA(...) { __VA_ARGS__ }
47 
48 /** Define inline expected HMAC */
49 #define EXPECTED(...) { __VA_ARGS__ }
50 
51 /** An HMAC test */
52 struct hmac_test {
53  /** Digest algorithm */
55  /** Key */
56  const void *key;
57  /** Length of key */
58  size_t key_len;
59  /** Data */
60  const void *data;
61  /** Length of data */
62  size_t data_len;
63  /** Expected HMAC */
64  const void *expected;
65  /** Length of expected HMAC */
66  size_t expected_len;
67 };
68 
69 /**
70  * Define an HMAC test
71  *
72  * @v name Test name
73  * @v DIGEST Digest algorithm
74  * @v KEY Key
75  * @v DATA Data
76  * @v EXPECTED Expected HMAC
77  * @ret test HMAC test
78  */
79 #define HMAC_TEST( name, DIGEST, KEY, DATA, EXPECTED ) \
80  static const uint8_t name ## _key[] = KEY; \
81  static const uint8_t name ## _data[] = DATA; \
82  static const uint8_t name ## _expected[] = EXPECTED; \
83  static struct hmac_test name = { \
84  .digest = DIGEST, \
85  .key = name ## _key, \
86  .key_len = sizeof ( name ## _key ), \
87  .data = name ## _data, \
88  .data_len = sizeof ( name ## _data ), \
89  .expected = name ## _expected, \
90  .expected_len = sizeof ( name ## _expected ), \
91  }
92 
93 /**
94  * Report an HMAC test result
95  *
96  * @v test HMAC test
97  * @v file Test code file
98  * @v line Test code line
99  */
100 static void hmac_okx ( struct hmac_test *test, const char *file,
101  unsigned int line ) {
102  struct digest_algorithm *digest = test->digest;
103  uint8_t ctx[ hmac_ctxsize ( digest ) ];
104  uint8_t hmac[digest->digestsize];
105 
106  /* Sanity checks */
107  okx ( sizeof ( ctx ) == ( digest->ctxsize + digest->blocksize ),
108  file, line );
109  okx ( test->expected_len == digest->digestsize, file, line );
110 
111  /* Calculate HMAC */
112  DBGC ( test, "HMAC-%s key:\n", digest->name );
113  DBGC_HDA ( test, 0, test->key, test->key_len );
114  DBGC ( test, "HMAC-%s data:\n", digest->name );
115  DBGC_HDA ( test, 0, test->data, test->data_len );
116  hmac_init ( digest, ctx, test->key, test->key_len );
117  hmac_update ( digest, ctx, test->data, test->data_len );
118  hmac_final ( digest, ctx, hmac );
119  DBGC ( test, "HMAC-%s result:\n", digest->name );
120  DBGC_HDA ( test, 0, hmac, sizeof ( hmac ) );
121 
122  /* Compare against expected result */
123  okx ( memcmp ( hmac, test->expected, test->expected_len ) == 0,
124  file, line );
125 }
126 #define hmac_ok( test ) hmac_okx ( test, __FILE__, __LINE__ )
127 
128 /* Empty key and data */
129 HMAC_TEST ( hmac_empty, &sha256_algorithm, KEY(), DATA(),
130  EXPECTED ( 0xb6, 0x13, 0x67, 0x9a, 0x08, 0x14, 0xd9, 0xec, 0x77,
131  0x2f, 0x95, 0xd7, 0x78, 0xc3, 0x5f, 0xc5, 0xff, 0x16,
132  0x97, 0xc4, 0x93, 0x71, 0x56, 0x53, 0xc6, 0xc7, 0x12,
133  0x14, 0x42, 0x92, 0xc5, 0xad ) );
134 
135 /* "Hello world" */
136 HMAC_TEST ( hmac_hw, &sha256_algorithm,
137  KEY ( 'H', 'e', 'l', 'l', 'o' ),
138  DATA ( 'W', 'o', 'r', 'l', 'd' ),
139  EXPECTED ( 0x59, 0x16, 0x8e, 0x30, 0x9f, 0x2c, 0x97, 0xdd, 0x04,
140  0xe4, 0x5b, 0xe3, 0xe7, 0x9b, 0xd9, 0xac, 0xb6, 0xd2,
141  0x2f, 0xda, 0x65, 0x46, 0xc0, 0x0c, 0x53, 0x92, 0x82,
142  0xc4, 0x1e, 0xeb, 0x91, 0x6e ) );
143 
144 /* "Hello world" using SHA-1 */
145 HMAC_TEST ( hmac_hw_sha1, &sha1_algorithm,
146  KEY ( 'H', 'e', 'l', 'l', 'o' ),
147  DATA ( 'W', 'o', 'r', 'l', 'd' ),
148  EXPECTED ( 0x9e, 0x29, 0xcf, 0x6d, 0x48, 0x90, 0x49, 0x9e, 0xf8,
149  0x5a, 0x31, 0x47, 0x55, 0x7b, 0x1a, 0x45, 0xd5, 0xae,
150  0xd1, 0x77 ) );
151 
152 /* "Hello world" using MD5 */
153 HMAC_TEST ( hmac_hw_md5, &md5_algorithm,
154  KEY ( 'H', 'e', 'l', 'l', 'o' ),
155  DATA ( 'W', 'o', 'r', 'l', 'd' ),
156  EXPECTED ( 0xc7, 0x1c, 0x0c, 0xd0, 0xdc, 0x24, 0x49, 0xbd, 0xd8,
157  0x9d, 0x28, 0xeb, 0x03, 0xbe, 0xf2, 0x04 ) );
158 
159 /* Block-length key */
160 HMAC_TEST ( hmac_maxlen, &sha256_algorithm,
161  KEY ( 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
162  0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
163  0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
164  0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
165  0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
166  0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
167  0x3c, 0x3d, 0x3e, 0x3f ),
168  DATA ( 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd' ),
169  EXPECTED ( 0xdd, 0x05, 0xcc, 0xe6, 0xd6, 0xaf, 0x91, 0x61, 0x4b,
170  0xaf, 0x35, 0x6b, 0x86, 0x0a, 0x05, 0x67, 0x25, 0x22,
171  0xf0, 0x54, 0xd2, 0x5f, 0xd7, 0xe1, 0x54, 0x26, 0x01,
172  0x16, 0xfd, 0x8a, 0xf3, 0x5b ) );
173 
174 /* Over-length key */
175 HMAC_TEST ( hmac_overlen, &sha256_algorithm,
176  KEY ( 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
177  0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
178  0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
179  0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
180  0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
181  0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
182  0x3c, 0x3d, 0x3e, 0x3f, 0x40 ),
183  DATA ( 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd' ),
184  EXPECTED ( 0x4f, 0x0f, 0x42, 0x07, 0xda, 0x84, 0x3d, 0x2a, 0x34,
185  0xae, 0x5d, 0xd9, 0x05, 0x1e, 0x96, 0xa8, 0xb6, 0xef,
186  0xa1, 0xcd, 0x49, 0x5b, 0xea, 0x30, 0xbf, 0x47, 0x3b,
187  0xdc, 0xa9, 0x86, 0xbb, 0x31 ) );
188 
189 /**
190  * Perform HMAC self-tests
191  *
192  */
193 static void hmac_test_exec ( void ) {
194 
195  hmac_ok ( &hmac_empty );
196  hmac_ok ( &hmac_hw );
197  hmac_ok ( &hmac_hw_sha1 );
198  hmac_ok ( &hmac_hw_md5 );
199  hmac_ok ( &hmac_maxlen );
200  hmac_ok ( &hmac_overlen );
201 }
202 
203 /** HMAC self-tests */
205  .name = "hmac",
206  .exec = hmac_test_exec,
207 };
#define EXPECTED(...)
Define inline expected HMAC.
Definition: hmac_test.c:49
void hmac_init(struct digest_algorithm *digest, void *ctx, const void *key, size_t key_len)
Initialise HMAC.
Definition: hmac.c:57
static void hmac_okx(struct hmac_test *test, const char *file, unsigned int line)
Report an HMAC test result.
Definition: hmac_test.c:100
size_t data_len
Length of data.
Definition: hmac_test.c:62
#define DBGC(...)
Definition: compiler.h:505
Self-test infrastructure.
const char * name
Test set name.
Definition: test.h:17
struct golan_eq_context ctx
Definition: CIB_PRM.h:28
#define DATA(...)
Define inline data.
Definition: hmac_test.c:46
A self-test set.
Definition: test.h:15
struct digest_algorithm * digest
Digest algorithm.
Definition: hmac_test.c:54
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
const void * data
Data.
Definition: hmac_test.c:60
size_t blocksize
Block size.
Definition: crypto.h:24
#define okx(success, file, line)
Report test result.
Definition: test.h:44
#define HMAC_TEST(name, DIGEST, KEY, DATA, EXPECTED)
Define an HMAC test.
Definition: hmac_test.c:79
#define KEY(...)
Define inline key data.
Definition: hmac_test.c:43
Keyed-Hashing for Message Authentication.
#define DBGC_HDA(...)
Definition: compiler.h:506
#define hmac_ok(test)
Definition: hmac_test.c:126
An HMAC test.
Definition: hmac_test.c:52
const void * key
Key.
Definition: hmac_test.c:56
static void hmac_update(struct digest_algorithm *digest, void *ctx, const void *data, size_t len)
Update HMAC.
Definition: hmac.h:42
static size_t hmac_ctxsize(struct digest_algorithm *digest)
Calculate HMAC context size.
Definition: hmac.h:28
unsigned char uint8_t
Definition: stdint.h:10
size_t expected_len
Length of expected HMAC.
Definition: hmac_test.c:66
size_t key_len
Length of key.
Definition: hmac_test.c:58
struct digest_algorithm sha256_algorithm
SHA-256 algorithm.
Definition: sha256.c:264
size_t ctxsize
Context size.
Definition: crypto.h:22
size_t digestsize
Digest size.
Definition: crypto.h:26
SHA-1 algorithm.
const char * name
Algorithm name.
Definition: crypto.h:20
const void * expected
Expected HMAC.
Definition: hmac_test.c:64
A message digest algorithm.
Definition: crypto.h:18
void hmac_final(struct digest_algorithm *digest, void *ctx, void *hmac)
Finalise HMAC.
Definition: hmac.c:87
static void hmac_test_exec(void)
Perform HMAC self-tests.
Definition: hmac_test.c:193
MD5 algorithm.
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:114
SHA-256 algorithm.
struct self_test hmac_test __self_test
HMAC self-tests.
Definition: hmac_test.c:204
String functions.
static int test
Definition: epic100.c:73
struct digest_algorithm md5_algorithm
MD5 algorithm.
Definition: md5.c:286
struct digest_algorithm sha1_algorithm
SHA-1 algorithm.
Definition: sha1.c:257