1 /*
2 * Copyright (c) 2017, Linaro Limited
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-2-Clause
6 */
7
8 #include <err.h>
9 #include <stdio.h>
10 #include <string.h>
11
12 /* OP-TEE TEE client API (built by optee_client) */
13 #include <tee_client_api.h>
14
15 /* For the UUID (found in the TA's h-file(s)) */
16 #include <hotp_ta.h>
17
18 struct test_value {
19 size_t count;
20 uint32_t expected;
21 };
22
23 /*
24 * Test values coming from the RFC4226 specification.
25 */
26 struct test_value rfc4226_test_values[] = {
27 { 0, 755224 },
28 { 1, 287082 },
29 { 2, 359152 },
30 { 3, 969429 },
31 { 4, 338314 },
32 { 5, 254676 },
33 { 6, 287922 },
34 { 7, 162583 },
35 { 8, 399871 },
36 { 9, 520489 }
37 };
38
main(void)39 int main(void)
40 {
41 TEEC_Context ctx;
42 TEEC_Operation op = { 0 };
43 TEEC_Result res;
44 TEEC_Session sess;
45 TEEC_UUID uuid = TA_HOTP_UUID;
46
47 size_t i;
48 uint32_t err_origin;
49 uint32_t hotp_value;
50
51 /*
52 * Shared key K ("12345678901234567890"), this is the key used in
53 * RFC4226 - Test Vectors.
54 */
55 uint8_t K[] = {
56 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
57 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
58 0x37, 0x38, 0x39, 0x30
59 };
60
61 /* Initialize a context connecting us to the TEE */
62 res = TEEC_InitializeContext(NULL, &ctx);
63 if (res != TEEC_SUCCESS)
64 errx(1, "TEEC_InitializeContext failed with code 0x%x", res);
65
66 res = TEEC_OpenSession(&ctx, &sess, &uuid,
67 TEEC_LOGIN_PUBLIC, NULL, NULL, &err_origin);
68 if (res != TEEC_SUCCESS)
69 errx(1, "TEEC_Opensession failed with code 0x%x origin 0x%x",
70 res, err_origin);
71
72 /* 1. Register the shared key */
73 op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
74 TEEC_NONE, TEEC_NONE, TEEC_NONE);
75 op.params[0].tmpref.buffer = K;
76 op.params[0].tmpref.size = sizeof(K);
77
78 fprintf(stdout, "Register the shared key: %s\n", K);
79 res = TEEC_InvokeCommand(&sess, TA_HOTP_CMD_REGISTER_SHARED_KEY,
80 &op, &err_origin);
81 if (res != TEEC_SUCCESS) {
82 fprintf(stderr, "TEEC_InvokeCommand failed with code 0x%x "
83 "origin 0x%x\n",
84 res, err_origin);
85 goto exit;
86 }
87
88 /* 2. Get HMAC based One Time Passwords */
89 op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_NONE,
90 TEEC_NONE, TEEC_NONE);
91
92 for (i = 0; i < sizeof(rfc4226_test_values) / sizeof(struct test_value);
93 i++) {
94 res = TEEC_InvokeCommand(&sess, TA_HOTP_CMD_GET_HOTP, &op,
95 &err_origin);
96 if (res != TEEC_SUCCESS) {
97 fprintf(stderr, "TEEC_InvokeCommand failed with code "
98 "0x%x origin 0x%x\n", res, err_origin);
99 goto exit;
100 }
101
102 hotp_value = op.params[0].value.a;
103 fprintf(stdout, "HOTP: %d\n", hotp_value);
104
105 if (hotp_value != rfc4226_test_values[i].expected) {
106 fprintf(stderr, "Got unexpected HOTP from TEE! "
107 "Expected: %d, got: %d\n",
108 rfc4226_test_values[i].expected, hotp_value);
109 }
110 }
111 exit:
112 TEEC_CloseSession(&sess);
113 TEEC_FinalizeContext(&ctx);
114
115 return 0;
116 }
117