-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapi.c
252 lines (212 loc) · 7.62 KB
/
api.c
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
#include <string.h> // for memset()
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdarg.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/socket.h>
#include "api.h"
#include "../tinycbor/src/cbor.h"
extern CborError cbor_vget(CborValue *it, const char *ptype, ...);
// MARS state ------------------------------------------------
// Initialized by _MARS_Init()
static struct {
pthread_mutex_t mx; // mutex for Lock and Unlock
pthread_t tid; // thread ID of mx lock owner; 0 if unlocked
uint16_t diglen, siglen, keylen;
void * txrx_ctx;
} mz;
// ---------------------------------------------------------
static void hexout(const char *msg, const void *buf, uint16_t len)
{
typeof(len) i;
if (msg)
printf("%s: ", msg);
for (i=0; i<len; i++)
printf("%02x", ((uint8_t *)buf)[i]);
printf("\n");
}
// determine if already locked by the caller
static bool mz_locked()
{
return mz.tid == pthread_self();
}
MARS_RC MARS_Lock()
{
if (mz_locked() || pthread_mutex_lock(&mz.mx))
return MARS_RC_LOCK;
mz.tid = pthread_self();
return MARS_RC_SUCCESS;
}
MARS_RC MARS_Unlock()
{
if (!mz_locked()) return MARS_RC_LOCK;
mz.tid = 0;
return pthread_mutex_unlock(&mz.mx) ? MARS_RC_LOCK : MARS_RC_SUCCESS;
}
// mz_xqt - Execute a MARS Command and write the reply
// Writes command parameters to CBOR cmdblob,
// sends cmdblob to dispatcher,
// receives response in rspblob,
// parses rspblob to pass results to caller.
// ptype characters indicate the type of parameter to process
// 'b' is boolean
// 'w' is word (32-bit) integer
// 'h' is half word (16-bit) integer
// 'x' is byte string taking 2 parameters, buffer pointer and length pointer
// 1st ptype char is return type, or '-' for no returned data
// can use captial 'X' for buffer pointer and mandatory length
// 1st char is processed by cbor_vget()
// 2nd ptype char must be 'h' for the Command Code
// remaining chars specify parameter types for the MARS Command
// After the ptype are the matching parameters
// The last parameter is the address(es) to hold the return value(s).
MARS_RC mz_xqt(const char *ptype, ...)
{
MARS_RC rc;
char rettype = *ptype++;
va_list ap;
uint32_t i;
uint8_t *xp; // byte string pointer
CborError err = CborNoError;
uint8_t cmdblob[1024];
#define rspblob cmdblob
size_t cmdlen, rsplen;
#define va_get(Z) Z = va_arg(ap, typeof(Z))
if (!mz_locked()) return MARS_RC_LOCK;
CborEncoder in, out, array;
cbor_encoder_init(&out, cmdblob, sizeof(cmdblob), 0);
for (i=0; ptype[i]; ++i) ;
cbor_encoder_create_array(&out, &array, i); // CborIndefiniteLength);
va_start(ap, ptype);
while (!err && *ptype) // walk through parameter types
switch (*ptype++) {
case 'b': // boolean parameter
va_get(i); // "..." passes boolean as int
err = cbor_encode_boolean(&array, i);
break;
case 'h': // half-word int parameter
va_get(i);
err = cbor_encode_uint(&array, (uint16_t)i);
break;
case 'w': // word int parameter
va_get(i);
err = cbor_encode_uint(&array, (uint32_t)i);
break;
case 'x': // byte string parameter
va_get(xp);
va_get(i);
err = xp
? cbor_encode_byte_string(&array, xp, i)
: cbor_encode_null(&array);
break;
default:
err = CborUnknownError;
}
if (err) {
printf("VPUT err %d\n", err);
cmdlen = 0;
rc = MARS_RC_IO;
} else {
cbor_encoder_close_container(&out, &array);
cmdlen = cbor_encoder_get_buffer_size(&out, cmdblob);
// pretty print the command
CborParser parser;
CborValue it;
cbor_parser_init(cmdblob, cmdlen, 0, &parser, &it);
printf(" Command: ");
cbor_value_to_pretty_advance(stdout, &it);
printf("\n");
rsplen = sizeof(rspblob);
// dispatcher(cmdblob, cmdlen, rspblob, &rsplen);
rsplen = MARS_Transport(mz.txrx_ctx, cmdblob, cmdlen, rspblob, rsplen);
// pretty print the response
cbor_parser_init(rspblob, rsplen, 0, &parser, &it);
printf("Response: ");
cbor_value_to_pretty_advance(stdout, &it);
printf("\n");
// get the Response Code and result, if any
if (cbor_parser_init(rspblob, rsplen, 0, &parser, &it)
|| cbor_value_enter_container(&it, &it)
|| cbor_vget(&it, "h", &rc))
rc = MARS_RC_IO;
else if (!rc && (rettype != '-')) {
void *p1, *p2;
char f[] = "-";
f[0] = rettype;
va_get(p1);
va_get(p2); // in case retype is 'x'
if (cbor_vget(&it, f, p1, p2))
rc = MARS_RC_IO;
}
if (!cbor_value_at_end(&it))
rc = MARS_RC_IO;
}
va_end(ap);
return rc;
}
MARS_RC MARS_SelfTest (bool fullTest)
{ return mz_xqt("-hb", MARS_CC_SelfTest, fullTest); }
MARS_RC MARS_CapabilityGet ( uint16_t pt, void * cap, uint16_t caplen)
{ return mz_xqt("hhh", MARS_CC_CapabilityGet, pt, cap); }
MARS_RC MARS_SequenceHash ()
{ return mz_xqt("-h", MARS_CC_SequenceHash); }
MARS_RC MARS_SequenceUpdate( const void * in, size_t inlen, void * out, size_t * outlen_p)
{ return mz_xqt("xhx", MARS_CC_SequenceUpdate, in, inlen, out, outlen_p); }
MARS_RC MARS_SequenceComplete( void * out, size_t * outlen_p)
{ return mz_xqt("xh", MARS_CC_SequenceComplete, out, outlen_p); }
MARS_RC MARS_PcrExtend ( uint16_t pcrIndex, const void * dig)
{ return mz_xqt("-hhx", MARS_CC_PcrExtend, pcrIndex, dig, mz.diglen); }
MARS_RC MARS_RegRead ( uint16_t regIndex, void * dig)
{ return mz_xqt("Xhh", MARS_CC_RegRead, regIndex, dig, mz.diglen); }
MARS_RC MARS_Derive ( uint32_t regSelect, const void * ctx, uint16_t ctxlen, void * out)
{ return mz_xqt("Xhwx", MARS_CC_Derive, regSelect, ctx, ctxlen, out, mz.keylen); }
MARS_RC MARS_DpDerive ( uint32_t regSelect, const void * ctx, uint16_t ctxlen)
{ return mz_xqt("-hwx", MARS_CC_DpDerive, regSelect, ctx, ctxlen); }
MARS_RC MARS_PublicRead ( bool restricted, const void * ctx, uint16_t ctxlen, void * pub)
{
// return mz_xqt("xhbx", MARS_CC_PublicRead,
return MARS_RC_COMMAND;
}
MARS_RC MARS_Quote (
uint32_t regSelect,
const void * nonce,
uint16_t nlen,
const void * ctx,
uint16_t ctxlen,
void * sig)
{
return mz_xqt("Xhwxx", MARS_CC_Quote, regSelect, nonce, nlen, ctx, ctxlen, sig, mz.siglen);
}
MARS_RC MARS_Sign ( const void * ctx, uint16_t ctxlen, const void * dig, void * sig)
{ return mz_xqt("Xhxx", MARS_CC_Sign, ctx, ctxlen, dig, mz.diglen, sig, mz.siglen); }
MARS_RC MARS_SignatureVerify (
bool restricted,
const void * ctx,
uint16_t ctxlen,
const void * dig,
const void * sig,
bool * result)
{
return mz_xqt("bhbxxx", MARS_CC_SignatureVerify,
restricted, ctx, ctxlen, dig, mz.diglen, sig, mz.siglen, result);
}
MARS_RC MARS_ApiInit(void *txrx_ctx)
{
bool err;
printf("MARS_ApiInit\n");
pthread_mutex_init(&mz.mx, NULL);
mz.tid = 0; // thread ID of mx lock owner; 0 if unlocked
MARS_Lock();
mz.txrx_ctx = txrx_ctx;
err = MARS_CapabilityGet(MARS_PT_LEN_DIGEST, &mz.diglen, sizeof(mz.diglen))
|| MARS_CapabilityGet(MARS_PT_LEN_SIGN, &mz.siglen, sizeof(mz.siglen))
|| MARS_CapabilityGet(MARS_PT_LEN_KSYM, &mz.keylen, sizeof(mz.keylen));
if (err) {
mz.tid = -1; // nothing can unlock
return MARS_RC_IO;
}
MARS_Unlock();
return MARS_RC_SUCCESS;
}