]>
git.zerfleddert.de Git - proxmark3-svn/blob - client/fido/cbortools.c
1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2018 Merlok
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
7 //-----------------------------------------------------------------------------
8 // Tools for work with CBOR format http://cbor.io/spec.html
9 // via Intel tinycbor (https://github.com/intel/tinycbor) library
10 //-----------------------------------------------------------------------------
13 #include "cbortools.h"
18 #include "emv/emvjson.h"
22 static void indent(int nestingLevel
) {
23 while (nestingLevel
--)
27 static CborError
dumpelm(CborValue
*it
, bool *got_next
, int nestingLevel
) {
31 CborType type
= cbor_value_get_type(it
);
36 printf(type
== CborArrayType
? "Array[" : "Map[");
40 case CborIntegerType
: {
42 cbor_value_get_int64(it
, &val
); // can't fail
43 printf("%" PRIi64
, val
);
47 case CborByteStringType
: {
50 err
= cbor_value_dup_byte_string(it
, &buf
, &n
, it
);
53 return err
; // parse error
54 printf("%s", sprint_hex(buf
, n
));
59 case CborTextStringType
: {
62 err
= cbor_value_dup_text_string(it
, &buf
, &n
, it
);
65 return err
; // parse error
73 cbor_value_get_tag(it
, &tag
);
74 printf("Tag(%" PRIu64
, tag
);
78 case CborSimpleType
: {
80 cbor_value_get_simple_type(it
, &type
);
81 printf("simple(%u)", type
);
89 case CborUndefinedType
:
93 case CborBooleanType
: {
95 cbor_value_get_boolean(it
, &val
); // can't fail
96 printf("%s", val
? "true" : "false");
100 case CborDoubleType
: {
105 cbor_value_get_float(it
, &f
);
108 cbor_value_get_double(it
, &val
);
113 case CborHalfFloatType
: {
115 cbor_value_get_half_float(it
, &val
);
116 printf("__f16(%04x)", val
);
120 case CborInvalidType
:
121 printf("CborInvalidType!!!");
128 static CborError
dumprecursive(uint8_t cmdCode
, bool isResponse
, CborValue
*it
, bool isMapType
, int nestingLevel
) {
130 while (!cbor_value_at_end(it
)) {
132 CborType type
= cbor_value_get_type(it
);
133 //printf("^%x^", type);
138 case CborArrayType
: {
141 assert(cbor_value_is_container(it
));
142 if (!(isMapType
&& (elmCount
% 2)))
143 indent(nestingLevel
);
144 printf(type
== CborArrayType
? "Array[\n" : "Map[\n");
145 err
= cbor_value_enter_container(it
, &recursed
);
147 return err
; // parse error
148 err
= dumprecursive(cmdCode
, isResponse
, &recursed
, (type
== CborMapType
), nestingLevel
+ 1);
150 return err
; // parse error
151 err
= cbor_value_leave_container(it
, &recursed
);
153 return err
; // parse error
154 indent(nestingLevel
);
161 err
= dumpelm(it
, &got_next
, (isMapType
&& (elmCount
% 2)) ? 0 : nestingLevel
);
164 if (cmdCode
> 0 && nestingLevel
== 1 && isMapType
&& !(elmCount
% 2)) {
166 cbor_value_get_int64(it
, &val
);
167 char *desc
= fido2GetCmdMemberDescription(cmdCode
, isResponse
, val
);
169 printf(" (%s)", desc
);
176 err
= cbor_value_advance_fixed(it
);
180 if (isMapType
&& !(elmCount
% 2)) {
190 int TinyCborInit(uint8_t *data
, size_t length
, CborValue
*cb
) {
192 CborError err
= cbor_parser_init(data
, length
, 0, &parser
, cb
);
199 int TinyCborPrintFIDOPackage(uint8_t cmdCode
, bool isResponse
, uint8_t *data
, size_t length
) {
202 res
= TinyCborInit(data
, length
, &cb
);
206 CborError err
= dumprecursive(cmdCode
, isResponse
, &cb
, false, 0);
209 fprintf(stderr
, "CBOR parsing failure at offset %td : %s\n", cb
.ptr
- data
, cbor_error_string(err
));
216 int JsonObjElmCount(json_t
*elm
) {
221 if (!json_is_object(elm
))
224 json_object_foreach(elm
, key
, value
) {
225 if (strlen(key
) > 0 && key
[0] != '.')
232 int JsonToCbor(json_t
*elm
, CborEncoder
*encoder
) {
233 if (!elm
|| !encoder
)
238 // CBOR map == JSON object
239 if (json_is_object(elm
)) {
244 res
= cbor_encoder_create_map(encoder
, &map
, JsonObjElmCount(elm
));
247 json_object_foreach(elm
, key
, value
) {
248 if (strlen(key
) > 0 && key
[0] != '.') {
249 res
= cbor_encode_text_stringz(&map
, key
);
253 JsonToCbor(value
, &map
);
257 res
= cbor_encoder_close_container(encoder
, &map
);
261 // CBOR array == JSON array
262 if (json_is_array(elm
)) {
267 res
= cbor_encoder_create_array(encoder
, &array
, json_array_size(elm
));
270 json_array_foreach(elm
, index
, value
) {
272 JsonToCbor(value
, &array
);
275 res
= cbor_encoder_close_container(encoder
, &array
);
279 if (json_is_boolean(elm
)) {
280 res
= cbor_encode_boolean(encoder
, json_is_true(elm
));
284 if (json_is_integer(elm
)) {
285 res
= cbor_encode_int(encoder
, json_integer_value(elm
));
289 if (json_is_real(elm
)) {
290 res
= cbor_encode_float(encoder
, json_real_value(elm
));
294 if (json_is_string(elm
)) {
295 const char * val
= json_string_value(elm
);
296 if (CheckStringIsHEXValue(val
)) {
298 uint8_t data
[4096] = {0};
299 res
= JsonLoadBufAsHex(elm
, "$", data
, sizeof(data
), &datalen
);
303 res
= cbor_encode_byte_string(encoder
, data
, datalen
);
306 res
= cbor_encode_text_stringz(encoder
, val
);
316 int CborMapGetKeyById(CborParser
*parser
, CborValue
*map
, uint8_t *data
, size_t dataLen
, int key
) {
319 CborError err
= cbor_parser_init(data
, dataLen
, 0, parser
, &cb
);
322 if (cbor_value_get_type(&cb
) != CborMapType
)
325 err
= cbor_value_enter_container(&cb
, map
);
329 while (!cbor_value_at_end(map
)) {
331 if (cbor_value_get_type(map
) != CborIntegerType
)
334 cbor_value_get_int64(map
, &indx
);
336 err
= cbor_value_advance(map
);
343 err
= cbor_value_advance(map
);
347 err
= cbor_value_leave_container(&cb
, map
);
353 CborError
CborGetArrayBinStringValue(CborValue
*elm
, uint8_t *data
, size_t maxdatalen
, size_t *datalen
) {
354 return CborGetArrayBinStringValueEx(elm
, data
, maxdatalen
, datalen
, NULL
, 0);
357 CborError
CborGetArrayBinStringValueEx(CborValue
*elm
, uint8_t *data
, size_t maxdatalen
, size_t *datalen
, uint8_t *delimeter
, size_t delimeterlen
) {
362 size_t slen
= maxdatalen
;
365 CborError res
= cbor_value_enter_container(elm
, &array
);
368 while (!cbor_value_at_end(&array
)) {
369 res
= cbor_value_copy_byte_string(&array
, &data
[totallen
], &slen
, &array
);
374 memcpy(&data
[totallen
], delimeter
, delimeterlen
);
375 totallen
+= delimeterlen
;
377 slen
= maxdatalen
- totallen
;
380 res
= cbor_value_leave_container(elm
, &array
);
389 CborError
CborGetBinStringValue(CborValue
*elm
, uint8_t *data
, size_t maxdatalen
, size_t *datalen
) {
393 size_t slen
= maxdatalen
;
395 CborError res
= cbor_value_copy_byte_string(elm
, data
, &slen
, elm
);
404 CborError
CborGetArrayStringValue(CborValue
*elm
, char *data
, size_t maxdatalen
, size_t *datalen
, char *delimeter
) {
409 size_t slen
= maxdatalen
;
412 CborError res
= cbor_value_enter_container(elm
, &array
);
415 while (!cbor_value_at_end(&array
)) {
416 res
= cbor_value_copy_text_string(&array
, &data
[totallen
], &slen
, &array
);
421 strcat(data
, delimeter
);
422 totallen
+= strlen(delimeter
);
424 slen
= maxdatalen
- totallen
;
425 data
[totallen
] = 0x00;
428 res
= cbor_value_leave_container(elm
, &array
);
437 CborError
CborGetStringValue(CborValue
*elm
, char *data
, size_t maxdatalen
, size_t *datalen
) {
441 size_t slen
= maxdatalen
;
443 CborError res
= cbor_value_copy_text_string(elm
, data
, &slen
, elm
);
452 CborError
CborGetStringValueBuf(CborValue
*elm
) {
453 static char stringBuf
[2048];
454 memset(stringBuf
, 0x00, sizeof(stringBuf
));
456 return CborGetStringValue(elm
, stringBuf
, sizeof(stringBuf
), NULL
);
459 int CBOREncodeElm(json_t
*root
, char *rootElmId
, CborEncoder
*encoder
) {
461 if (rootElmId
&& strlen(rootElmId
) && rootElmId
[0] == '$')
462 elm
= json_path_get(root
, rootElmId
);
464 elm
= json_object_get(root
, rootElmId
);
469 int res
= JsonToCbor(elm
, encoder
);
474 CborError
CBOREncodeClientDataHash(json_t
*root
, CborEncoder
*encoder
) {
475 uint8_t buf
[100] = {0};
478 JsonLoadBufAsHex(root
, "$.ClientDataHash", buf
, sizeof(buf
), &jlen
);
480 // fill with 0x00 if not found
484 int res
= cbor_encode_byte_string(encoder
, buf
, jlen
);