Home | History | Annotate | Line # | Download | only in cgdconfig
      1  1.1  riastrad /*	$NetBSD: hkdf_hmac_sha256.c,v 1.1 2022/08/12 10:49:17 riastradh Exp $	*/
      2  1.1  riastrad 
      3  1.1  riastrad /*-
      4  1.1  riastrad  * Copyright (c) 2022 The NetBSD Foundation, Inc.
      5  1.1  riastrad  * All rights reserved.
      6  1.1  riastrad  *
      7  1.1  riastrad  * Redistribution and use in source and binary forms, with or without
      8  1.1  riastrad  * modification, are permitted provided that the following conditions
      9  1.1  riastrad  * are met:
     10  1.1  riastrad  * 1. Redistributions of source code must retain the above copyright
     11  1.1  riastrad  *    notice, this list of conditions and the following disclaimer.
     12  1.1  riastrad  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.1  riastrad  *    notice, this list of conditions and the following disclaimer in the
     14  1.1  riastrad  *    documentation and/or other materials provided with the distribution.
     15  1.1  riastrad  *
     16  1.1  riastrad  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     17  1.1  riastrad  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18  1.1  riastrad  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  1.1  riastrad  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     20  1.1  riastrad  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  1.1  riastrad  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  1.1  riastrad  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23  1.1  riastrad  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24  1.1  riastrad  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25  1.1  riastrad  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26  1.1  riastrad  * POSSIBILITY OF SUCH DAMAGE.
     27  1.1  riastrad  */
     28  1.1  riastrad 
     29  1.1  riastrad #include <sys/cdefs.h>
     30  1.1  riastrad __RCSID("$NetBSD: hkdf_hmac_sha256.c,v 1.1 2022/08/12 10:49:17 riastradh Exp $");
     31  1.1  riastrad 
     32  1.1  riastrad #include <sys/sha2.h>
     33  1.1  riastrad 
     34  1.1  riastrad #include <stdint.h>
     35  1.1  riastrad #include <string.h>
     36  1.1  riastrad 
     37  1.1  riastrad #include "hkdf_hmac_sha256.h"
     38  1.1  riastrad 
     39  1.1  riastrad /* RFC 2104: HMAC */
     40  1.1  riastrad 
     41  1.1  riastrad struct hmacsha256 {
     42  1.1  riastrad 	SHA256_CTX sha256;
     43  1.1  riastrad 	uint8_t key[SHA256_BLOCK_LENGTH];
     44  1.1  riastrad };
     45  1.1  riastrad 
     46  1.1  riastrad static void
     47  1.1  riastrad hmacsha256_init(struct hmacsha256 *H, const void *key, size_t keylen)
     48  1.1  riastrad {
     49  1.1  riastrad 	uint8_t hkey[SHA256_DIGEST_LENGTH];
     50  1.1  riastrad 	uint8_t ipad[SHA256_BLOCK_LENGTH];
     51  1.1  riastrad 	unsigned i;
     52  1.1  riastrad 
     53  1.1  riastrad 	if (keylen > SHA256_BLOCK_LENGTH) { /* XXX should not happen here */
     54  1.1  riastrad 		SHA256_Init(&H->sha256);
     55  1.1  riastrad 		SHA256_Update(&H->sha256, key, keylen);
     56  1.1  riastrad 		SHA256_Final(hkey, &H->sha256);
     57  1.1  riastrad 		key = hkey;
     58  1.1  riastrad 		keylen = sizeof(hkey);
     59  1.1  riastrad 	}
     60  1.1  riastrad 
     61  1.1  riastrad 	memset(H->key, 0, sizeof(H->key));
     62  1.1  riastrad 	memcpy(H->key, key, keylen);
     63  1.1  riastrad 
     64  1.1  riastrad 	for (i = 0; i < SHA256_BLOCK_LENGTH; i++)
     65  1.1  riastrad 		ipad[i] = 0x36 ^ H->key[i];
     66  1.1  riastrad 
     67  1.1  riastrad 	SHA256_Init(&H->sha256);
     68  1.1  riastrad 	SHA256_Update(&H->sha256, ipad, SHA256_BLOCK_LENGTH);
     69  1.1  riastrad 
     70  1.1  riastrad 	explicit_memset(hkey, 0, sizeof(hkey));
     71  1.1  riastrad 	explicit_memset(ipad, 0, sizeof(ipad));
     72  1.1  riastrad }
     73  1.1  riastrad 
     74  1.1  riastrad static void
     75  1.1  riastrad hmacsha256_update(struct hmacsha256 *H, const void *buf, size_t buflen)
     76  1.1  riastrad {
     77  1.1  riastrad 
     78  1.1  riastrad 	SHA256_Update(&H->sha256, buf, buflen);
     79  1.1  riastrad }
     80  1.1  riastrad 
     81  1.1  riastrad static void
     82  1.1  riastrad hmacsha256_final(uint8_t h[static SHA256_DIGEST_LENGTH],
     83  1.1  riastrad     struct hmacsha256 *H)
     84  1.1  riastrad {
     85  1.1  riastrad 	uint8_t opad[SHA256_BLOCK_LENGTH];
     86  1.1  riastrad 	unsigned i;
     87  1.1  riastrad 
     88  1.1  riastrad 	for (i = 0; i < SHA256_BLOCK_LENGTH; i++)
     89  1.1  riastrad 		opad[i] = 0x5c ^ H->key[i];
     90  1.1  riastrad 
     91  1.1  riastrad 	SHA256_Final(h, &H->sha256);
     92  1.1  riastrad 	SHA256_Init(&H->sha256);
     93  1.1  riastrad 	SHA256_Update(&H->sha256, opad, SHA256_BLOCK_LENGTH);
     94  1.1  riastrad 	SHA256_Update(&H->sha256, h, SHA256_DIGEST_LENGTH);
     95  1.1  riastrad 	SHA256_Final(h, &H->sha256);
     96  1.1  riastrad 
     97  1.1  riastrad 	explicit_memset(opad, 0, sizeof(opad));
     98  1.1  riastrad 	explicit_memset(H, 0, sizeof(*H));
     99  1.1  riastrad }
    100  1.1  riastrad 
    101  1.1  riastrad /* RFC 5869 HKDF, Sec. 2.3 HKDF-Expand */
    102  1.1  riastrad 
    103  1.1  riastrad int
    104  1.1  riastrad hkdf_hmac_sha256(void *okm, size_t L,
    105  1.1  riastrad     const void *prk, size_t prklen,
    106  1.1  riastrad     const void *info, size_t infolen)
    107  1.1  riastrad {
    108  1.1  riastrad 	struct hmacsha256 hmacsha256;
    109  1.1  riastrad 	size_t n, tlen;
    110  1.1  riastrad 	uint8_t T[SHA256_DIGEST_LENGTH], *p = okm;
    111  1.1  riastrad 	uint8_t i;
    112  1.1  riastrad 
    113  1.1  riastrad 	if (L > 255*SHA256_DIGEST_LENGTH)
    114  1.1  riastrad 		return -1;
    115  1.1  riastrad 	if (L == 0)
    116  1.1  riastrad 		return 0;
    117  1.1  riastrad 
    118  1.1  riastrad 	for (tlen = 0, i = 1; L > 0; i++, tlen = SHA256_DIGEST_LENGTH) {
    119  1.1  riastrad 		hmacsha256_init(&hmacsha256, prk, prklen);
    120  1.1  riastrad 		hmacsha256_update(&hmacsha256, T, tlen);
    121  1.1  riastrad 		hmacsha256_update(&hmacsha256, info, infolen);
    122  1.1  riastrad 		hmacsha256_update(&hmacsha256, &i, 1);
    123  1.1  riastrad 		hmacsha256_final(T, &hmacsha256);
    124  1.1  riastrad 		n = (L < SHA256_DIGEST_LENGTH ? L : SHA256_DIGEST_LENGTH);
    125  1.1  riastrad 		memcpy(p, T, n);
    126  1.1  riastrad 		p += n;
    127  1.1  riastrad 		L -= n;
    128  1.1  riastrad 	}
    129  1.1  riastrad 
    130  1.1  riastrad 	explicit_memset(T, 0, sizeof(T));
    131  1.1  riastrad 	return 0;
    132  1.1  riastrad }
    133  1.1  riastrad 
    134  1.1  riastrad #if 0
    135  1.1  riastrad #include <stdarg.h>
    136  1.1  riastrad #include <stdio.h>
    137  1.1  riastrad 
    138  1.1  riastrad static void
    139  1.1  riastrad hexdump(const void *buf, size_t len, const char *fmt, ...)
    140  1.1  riastrad {
    141  1.1  riastrad 	va_list va;
    142  1.1  riastrad 	const uint8_t *p = buf;
    143  1.1  riastrad 	size_t i;
    144  1.1  riastrad 
    145  1.1  riastrad 	printf("### ");
    146  1.1  riastrad 	va_start(va, fmt);
    147  1.1  riastrad 	vprintf(fmt, va);
    148  1.1  riastrad 	va_end(va);
    149  1.1  riastrad 	printf(" (%zu bytes):\n", len);
    150  1.1  riastrad 	for (i = 0; i < len; i++) {
    151  1.1  riastrad 		if (i % 8 == 0)
    152  1.1  riastrad 			printf(" ");
    153  1.1  riastrad 		printf(" %02x", p[i]);
    154  1.1  riastrad 		if (i % 16 == 15)
    155  1.1  riastrad 			printf("\n");
    156  1.1  riastrad 	}
    157  1.1  riastrad 	if (i % 16)
    158  1.1  riastrad 		printf("\n");
    159  1.1  riastrad }
    160  1.1  riastrad #endif
    161  1.1  riastrad 
    162  1.1  riastrad int
    163  1.1  riastrad hkdf_hmac_sha256_selftest(void)
    164  1.1  riastrad {
    165  1.1  riastrad 	const struct {
    166  1.1  riastrad 		size_t L;
    167  1.1  riastrad 		const uint8_t *okm;
    168  1.1  riastrad 		size_t prklen;
    169  1.1  riastrad 		const uint8_t *prk;
    170  1.1  riastrad 		size_t infolen;
    171  1.1  riastrad 		const uint8_t *info;
    172  1.1  riastrad 	} C[] = {
    173  1.1  riastrad 		[0] = {		/* A.1 Test Case 1 with SHA-256 */
    174  1.1  riastrad 			.L = 42,
    175  1.1  riastrad 			.okm = (const uint8_t[]) {
    176  1.1  riastrad 				0x3c,0xb2,0x5f,0x25, 0xfa,0xac,0xd5,0x7a,
    177  1.1  riastrad 				0x90,0x43,0x4f,0x64, 0xd0,0x36,0x2f,0x2a,
    178  1.1  riastrad 				0x2d,0x2d,0x0a,0x90, 0xcf,0x1a,0x5a,0x4c,
    179  1.1  riastrad 				0x5d,0xb0,0x2d,0x56, 0xec,0xc4,0xc5,0xbf,
    180  1.1  riastrad 				0x34,0x00,0x72,0x08, 0xd5,0xb8,0x87,0x18,
    181  1.1  riastrad 				0x58,0x65,
    182  1.1  riastrad 			},
    183  1.1  riastrad 			.prklen = 32,
    184  1.1  riastrad 			.prk = (const uint8_t[]) {
    185  1.1  riastrad 				0x07,0x77,0x09,0x36, 0x2c,0x2e,0x32,0xdf,
    186  1.1  riastrad 				0x0d,0xdc,0x3f,0x0d, 0xc4,0x7b,0xba,0x63,
    187  1.1  riastrad 				0x90,0xb6,0xc7,0x3b, 0xb5,0x0f,0x9c,0x31,
    188  1.1  riastrad 				0x22,0xec,0x84,0x4a, 0xd7,0xc2,0xb3,0xe5,
    189  1.1  riastrad 			},
    190  1.1  riastrad 			.infolen = 10,
    191  1.1  riastrad 			.info = (const uint8_t[]) {
    192  1.1  riastrad 				0xf0,0xf1,0xf2,0xf3, 0xf4,0xf5,0xf6,0xf7,
    193  1.1  riastrad 				0xf8,0xf9,
    194  1.1  riastrad 			},
    195  1.1  riastrad 		},
    196  1.1  riastrad 		[1] = {		/* A.2 Test Case 2 with SHA-256, longer I/O */
    197  1.1  riastrad 			.L = 82,
    198  1.1  riastrad 			.okm = (const uint8_t[]) {
    199  1.1  riastrad 				0xb1,0x1e,0x39,0x8d, 0xc8,0x03,0x27,0xa1,
    200  1.1  riastrad 				0xc8,0xe7,0xf7,0x8c, 0x59,0x6a,0x49,0x34,
    201  1.1  riastrad 				0x4f,0x01,0x2e,0xda, 0x2d,0x4e,0xfa,0xd8,
    202  1.1  riastrad 				0xa0,0x50,0xcc,0x4c, 0x19,0xaf,0xa9,0x7c,
    203  1.1  riastrad 				0x59,0x04,0x5a,0x99, 0xca,0xc7,0x82,0x72,
    204  1.1  riastrad 				0x71,0xcb,0x41,0xc6, 0x5e,0x59,0x0e,0x09,
    205  1.1  riastrad 				0xda,0x32,0x75,0x60, 0x0c,0x2f,0x09,0xb8,
    206  1.1  riastrad 				0x36,0x77,0x93,0xa9, 0xac,0xa3,0xdb,0x71,
    207  1.1  riastrad 				0xcc,0x30,0xc5,0x81, 0x79,0xec,0x3e,0x87,
    208  1.1  riastrad 				0xc1,0x4c,0x01,0xd5, 0xc1,0xf3,0x43,0x4f,
    209  1.1  riastrad 				0x1d,0x87,
    210  1.1  riastrad 			},
    211  1.1  riastrad 			.prklen = 32,
    212  1.1  riastrad 			.prk = (const uint8_t[]) {
    213  1.1  riastrad 				0x06,0xa6,0xb8,0x8c, 0x58,0x53,0x36,0x1a,
    214  1.1  riastrad 				0x06,0x10,0x4c,0x9c, 0xeb,0x35,0xb4,0x5c,
    215  1.1  riastrad 				0xef,0x76,0x00,0x14, 0x90,0x46,0x71,0x01,
    216  1.1  riastrad 				0x4a,0x19,0x3f,0x40, 0xc1,0x5f,0xc2,0x44,
    217  1.1  riastrad 			},
    218  1.1  riastrad 			.infolen = 80,
    219  1.1  riastrad 			.info = (const uint8_t[]) {
    220  1.1  riastrad 				0xb0,0xb1,0xb2,0xb3, 0xb4,0xb5,0xb6,0xb7,
    221  1.1  riastrad 				0xb8,0xb9,0xba,0xbb, 0xbc,0xbd,0xbe,0xbf,
    222  1.1  riastrad 				0xc0,0xc1,0xc2,0xc3, 0xc4,0xc5,0xc6,0xc7,
    223  1.1  riastrad 				0xc8,0xc9,0xca,0xcb, 0xcc,0xcd,0xce,0xcf,
    224  1.1  riastrad 				0xd0,0xd1,0xd2,0xd3, 0xd4,0xd5,0xd6,0xd7,
    225  1.1  riastrad 				0xd8,0xd9,0xda,0xdb, 0xdc,0xdd,0xde,0xdf,
    226  1.1  riastrad 				0xe0,0xe1,0xe2,0xe3, 0xe4,0xe5,0xe6,0xe7,
    227  1.1  riastrad 				0xe8,0xe9,0xea,0xeb, 0xec,0xed,0xee,0xef,
    228  1.1  riastrad 				0xf0,0xf1,0xf2,0xf3, 0xf4,0xf5,0xf6,0xf7,
    229  1.1  riastrad 				0xf8,0xf9,0xfa,0xfb, 0xfc,0xfd,0xfe,0xff,
    230  1.1  riastrad 			},
    231  1.1  riastrad 		},
    232  1.1  riastrad 		[2] = {		/* A.3 Test Case 3 with SHA-256, empty info */
    233  1.1  riastrad 			.L = 42,
    234  1.1  riastrad 			.okm = (const uint8_t[]) {
    235  1.1  riastrad 				0x8d,0xa4,0xe7,0x75, 0xa5,0x63,0xc1,0x8f,
    236  1.1  riastrad 				0x71,0x5f,0x80,0x2a, 0x06,0x3c,0x5a,0x31,
    237  1.1  riastrad 				0xb8,0xa1,0x1f,0x5c, 0x5e,0xe1,0x87,0x9e,
    238  1.1  riastrad 				0xc3,0x45,0x4e,0x5f, 0x3c,0x73,0x8d,0x2d,
    239  1.1  riastrad 				0x9d,0x20,0x13,0x95, 0xfa,0xa4,0xb6,0x1a,
    240  1.1  riastrad 				0x96,0xc8,
    241  1.1  riastrad 			},
    242  1.1  riastrad 			.prklen = 32,
    243  1.1  riastrad 			.prk = (const uint8_t[]) {
    244  1.1  riastrad 				0x19,0xef,0x24,0xa3, 0x2c,0x71,0x7b,0x16,
    245  1.1  riastrad 				0x7f,0x33,0xa9,0x1d, 0x6f,0x64,0x8b,0xdf,
    246  1.1  riastrad 				0x96,0x59,0x67,0x76, 0xaf,0xdb,0x63,0x77,
    247  1.1  riastrad 				0xac,0x43,0x4c,0x1c, 0x29,0x3c,0xcb,0x04,
    248  1.1  riastrad 			},
    249  1.1  riastrad 			.infolen = 0,
    250  1.1  riastrad 			.info = NULL,
    251  1.1  riastrad 		},
    252  1.1  riastrad 	};
    253  1.1  riastrad 	uint8_t okm[128];
    254  1.1  riastrad 	unsigned i;
    255  1.1  riastrad 
    256  1.1  riastrad 	for (i = 0; i < __arraycount(C); i++) {
    257  1.1  riastrad 		if (hkdf_hmac_sha256(okm, C[i].L, C[i].prk, C[i].prklen,
    258  1.1  riastrad 			C[i].info, C[i].infolen))
    259  1.1  riastrad 			return -1;
    260  1.1  riastrad 		if (memcmp(okm, C[i].okm, C[i].L))
    261  1.1  riastrad 			return -1;
    262  1.1  riastrad 	}
    263  1.1  riastrad 
    264  1.1  riastrad 	return 0;
    265  1.1  riastrad }
    266  1.1  riastrad 
    267  1.1  riastrad #if 0
    268  1.1  riastrad int
    269  1.1  riastrad main(void)
    270  1.1  riastrad {
    271  1.1  riastrad 	return hkdf_hmac_sha256_selftest();
    272  1.1  riastrad }
    273  1.1  riastrad #endif
    274