blob: c65ded3a23d6fb97d69c9f0471b490425e4d703a [file] [log] [blame]
Philip Tricca80d81bd2016-08-29 09:48:16 -07001#include <stdlib.h>
2#include <arpa/inet.h>
3#include <stdio.h>
4
5#include <setjmp.h>
6#include <cmocka.h>
7#include <tpm20.h>
8
9#include "sys_api_marshalUnmarshal.h"
10#include "sysapi_util.h"
11
12typedef struct {
13 uint8_t *buffer;
14 size_t buffer_size;
15 uint32_t data_host;
16 uint32_t data_net;
17 TSS2_RC rc;
18} marshal_uint32_data_t;
19
20void
21marshal_UINT32_setup (void **state)
22{
23 marshal_uint32_data_t *data;
24
25 data = calloc (1, sizeof (marshal_uint32_data_t));
26 data->buffer = calloc (1, sizeof (uint32_t));
27 data->buffer_size = sizeof (uint32_t);
28 data->data_host = 0xdeadbeef;
29 data->data_net = htonl (data->data_host);
30 data->rc = TSS2_RC_SUCCESS;
31
32 *state = data;
33}
34
35void
36marshal_UINT32_teardown (void **state)
37{
38 marshal_uint32_data_t *data;
39
40 data = (marshal_uint32_data_t*)*state;
41 if (data) {
42 if (data->buffer)
43 free (data->buffer);
44 free (data);
45 }
46}
47/**
48 * Make a call to Marshal_UINT32 function that should succeed. The *_setup
49 * function is expected to have allocated sufficient buffer to hold a
50 * uint32_t. This test just 'marshals' a known uint32_t into this data buffer
51 * and then compares the value to the expected result.
52 * The workings of the Marshal_UINT32 function is a bit complex, so we
53 * assert the expected results as well.
54 */
55void
56marshal_UINT32_good (void **state)
57{
58 marshal_uint32_data_t *data;
59
60 data = (marshal_uint32_data_t*)*state;
61 uint8_t *nextData = data->buffer;
62
63 Marshal_UINT32 (data->buffer,
64 data->buffer_size,
65 &nextData,
66 data->data_host,
67 &data->rc);
68 /**
69 * uint32_t that was marshalled into the data buffer should be equal to
70 * the expected value (data converted from host byte order to network
71 * byte order).
72 */
73 assert_int_equal (*(uint32_t*)(data->buffer), data->data_net);
74 /**
75 * The Marshal_* functions advance the 'nextData' parameter by the size of
76 * the marshalled data.
77 */
78 assert_int_equal (data->buffer, nextData - sizeof (uint32_t));
79 /* Finally the return code should indicate success. */
80 assert_return_code (data->rc, TSS2_RC_SUCCESS);
81}
82/**
83 * Attempt to marshal a uint32_t into a buffer that's only got room for a
84 * uint8_t. The call to the marshalling function should set the TSS2_RC value
85 * to TSS2_SYS_RC_INSUFFICIENT_CONTEXT and the nextData parameter should not
86 * be changed.
87 */
88void
89marshal_UINT32_too_small (void **state)
90{
91 marshal_uint32_data_t *data;
92
93 data = (marshal_uint32_data_t*)*state;
94 /**
95 * Set the locate where data will be marshalled to half way through the
96 * buffer. This only leaves us space for a uint8_t.
97 */
98 uint8_t *nextData = data->buffer + sizeof (uint8_t);
99 data->buffer_size = sizeof (uint8_t);
100
101 Marshal_UINT32 (data->buffer,
102 data->buffer_size,
103 &nextData,
104 data->data_host,
105 &data->rc);
106 /**
107 * The return code should indicate we don't have enough space and the
108 * nextData pointer shouldn't have moved.
109 */
110 assert_return_code (data->rc, TSS2_SYS_RC_INSUFFICIENT_CONTEXT);
111 assert_int_equal (data->buffer, nextData - sizeof (uint8_t));
112}
113void
114marshal_UINT32_under_ptr (void **state)
115{
116 marshal_uint32_data_t *data;
117
118 data = (marshal_uint32_data_t*)*state;
119 /**
120 * Set nextData to a byte *before* the buffer.
121 */
122 uint8_t *nextData = data->buffer - sizeof (uint8_t);
123 Marshal_UINT32 (data->buffer,
124 data->buffer_size,
125 &nextData,
126 data->data_host,
127 &data->rc);
128 /* again, not enough space, and no change to nextData */
129 assert_return_code (data->rc, TSS2_SYS_RC_INSUFFICIENT_CONTEXT);
130 assert_int_equal (data->buffer, nextData - sizeof (uint8_t));
131}
132/**
133 * Test error condition where nextData pointer is already beyond the end
134 * of the data buffer. We set this value to 1 byte past the buffers end.
135 * The expected result is the 'rc' parameter being set to indicate the
136 * size of the buffer is insufficient. The nextData pointer should also
137 * remain unchanged.
138 */
139void
140marshal_UINT32_past_end (void **state)
141{
142 marshal_uint32_data_t *data;
143
144 data = (marshal_uint32_data_t*)*state;
145 /* Set nextData beyond the end of the buffer. */
146 uint8_t *nextData = data->buffer + data->buffer_size + sizeof (uint8_t);
147 Marshal_UINT32 (data->buffer,
148 data->buffer_size,
149 &nextData,
150 data->data_host,
151 &data->rc);
152 /* rc should indicate error and no change to the pointers */
153 assert_return_code (data->rc, TSS2_SYS_RC_INSUFFICIENT_CONTEXT);
154 assert_int_equal (nextData,
155 data->buffer + data->buffer_size + sizeof (uint8_t));
156}
157/**
158 * Test an edge case where the 'rc' parameter is set to something other
159 * than TSS2_RC_SUCCESS. A pattern I see emerging is the use of the TSS2_RC
160 * member of the sapi context structure to skip over large blocks of code.
161 * Many (most?) of the functions in the guts of the serialization logic check
162 * this member data and quickly return when it's set. This is the reason
163 * these fucntions often have no return value: they're using the 'rc' member
164 * in the context structure.
165 */
166void
167marshal_UINT32_rc_previous_fail (void **state)
168{
169 /* Set 'rc' to an error condition. */
170 TSS2_RC rc = TSS2_SYS_RC_BAD_SIZE;
171 /* 'rc' is checked first, all other parameters can be NULL.*/
172 Marshal_UINT32 (NULL, 0, NULL, 0, &rc);
173 assert_return_code (rc, TSS2_SYS_RC_BAD_SIZE);
174}
175int
176main (void)
177{
178 const UnitTest tests [] = {
179 unit_test_setup_teardown (marshal_UINT32_good,
180 marshal_UINT32_setup,
181 marshal_UINT32_teardown),
182 unit_test_setup_teardown (marshal_UINT32_too_small,
183 marshal_UINT32_setup,
184 marshal_UINT32_teardown),
185 unit_test_setup_teardown (marshal_UINT32_past_end,
186 marshal_UINT32_setup,
187 marshal_UINT32_teardown),
188 unit_test (marshal_UINT32_rc_previous_fail),
189 };
190 return run_tests (tests);
191}