summaryrefslogtreecommitdiff
path: root/board/cr50/tpm2/hkdf.c
blob: d950d865abc118ca37d0304be50c1112841c13ed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/* Copyright 2016 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "dcrypto.h"
#include "util.h"

#ifdef CRYPTO_TEST_SETUP

#include "extension.h"

enum {
	TEST_RFC = 0,
};

#define MAX_OKM_BYTES 1024

static void hkdf_command_handler(void *cmd_body,
				size_t cmd_size,
				size_t *response_size)
{
	uint8_t *cmd;
	uint8_t *out;
	uint8_t op;
	size_t salt_len;
	const uint8_t *salt;
	size_t IKM_len;
	const uint8_t *IKM;
	size_t info_len;
	const uint8_t *info;
	size_t OKM_len;
	uint8_t OKM[MAX_OKM_BYTES];

	/* Command format.
	 *
	 *   WIDTH	   FIELD
	 *   1		   OP
	 *   1             MSB SALT LEN
	 *   1             LSB SALT LEN
	 *   SALT_LEN      SALT
	 *   1             MSB IKM LEN
	 *   1             LSB IKM LEN
	 *   IKM_LEN       IKM
	 *   1             MSB INFO LEN
	 *   1             LSB INFO LEN
	 *   INFO_LEN      INFO
	 *   1             MSB OKM LEN
	 *   1             LSB OKM LEN
	 */
	cmd = (uint8_t *) cmd_body;
	out = (uint8_t *) cmd_body;
	op = *cmd++;

	salt_len = ((uint16_t) (cmd[0] << 8)) | cmd[1];
	cmd += 2;
	salt = cmd;
	cmd += salt_len;

	IKM_len = ((uint16_t) (cmd[0] << 8)) | cmd[1];
	cmd += 2;
	IKM = cmd;
	cmd += IKM_len;

	info_len = ((uint16_t) (cmd[0] << 8)) | cmd[1];
	cmd += 2;
	info = cmd;
	cmd += info_len;

	OKM_len = ((uint16_t) (cmd[0] << 8)) | cmd[1];

	if (OKM_len > MAX_OKM_BYTES) {
		*response_size = 0;
		return;
	}

	switch (op) {
	case TEST_RFC:
		if (DCRYPTO_hkdf(OKM, OKM_len, salt, salt_len,
					IKM, IKM_len, info, info_len)) {
			memcpy(out, OKM, OKM_len);
			*response_size = OKM_len;
		} else {
			*response_size = 0;
		}
		break;
	default:
		*response_size = 0;
	}
}

DECLARE_EXTENSION_COMMAND(EXTENSION_HKDF, hkdf_command_handler);

#endif   /* CRYPTO_TEST_SETUP */