]>
cvs.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" 
  15 #include "emv/emvjson.h" 
  19 static void indent(int nestingLevel
) { 
  20         while (nestingLevel
--) 
  24 static CborError 
dumpelm(CborValue 
*it
, bool *got_next
, int nestingLevel
) { 
  28         CborType type 
= cbor_value_get_type(it
); 
  33                 printf(type 
== CborArrayType 
? "Array[" : "Map["); 
  37         case CborIntegerType
: { 
  39                 cbor_value_get_int64(it
, &val
);     // can't fail 
  40                 printf("%lld", (long long)val
); 
  44         case CborByteStringType
: { 
  47                 err 
= cbor_value_dup_byte_string(it
, &buf
, &n
, it
); 
  50                         return err
;     // parse error 
  51                 printf("%s", sprint_hex(buf
, n
)); 
  56         case CborTextStringType
: { 
  59                 err 
= cbor_value_dup_text_string(it
, &buf
, &n
, it
); 
  62                         return err
;     // parse error 
  70                 cbor_value_get_tag(it
, &tag
);      
  71                 printf("Tag(%lld)", (long long)tag
); 
  75         case CborSimpleType
: { 
  77                 cbor_value_get_simple_type(it
, &type
);  
  78                 printf("simple(%u)", type
); 
  86         case CborUndefinedType
: 
  90         case CborBooleanType
: { 
  92                 cbor_value_get_boolean(it
, &val
);       // can't fail 
  93                 printf("%s", val 
? "true" : "false"); 
  97         case CborDoubleType
: { 
 102                         cbor_value_get_float(it
, &f
); 
 105                         cbor_value_get_double(it
, &val
); 
 110         case CborHalfFloatType
: { 
 112                 cbor_value_get_half_float(it
, &val
); 
 113                 printf("__f16(%04x)", val
); 
 117         case CborInvalidType
: 
 118                 printf("CborInvalidType!!!"); 
 125 static CborError 
dumprecursive(uint8_t cmdCode
, bool isResponse
, CborValue 
*it
, bool isMapType
, int nestingLevel
) { 
 127         while (!cbor_value_at_end(it
)) { 
 129                 CborType type 
= cbor_value_get_type(it
); 
 130 //printf("^%x^", type); 
 135                 case CborArrayType
: { 
 138                         assert(cbor_value_is_container(it
)); 
 139                         if (!(isMapType 
&& (elmCount 
% 2))) 
 140                                 indent(nestingLevel
); 
 141                         printf(type 
== CborArrayType 
? "Array[\n" : "Map[\n"); 
 142                         err 
= cbor_value_enter_container(it
, &recursed
); 
 144                                 return err
;       // parse error 
 145                         err 
= dumprecursive(cmdCode
, isResponse
, &recursed
, (type 
== CborMapType
), nestingLevel 
+ 1); 
 147                                 return err
;       // parse error 
 148                         err 
= cbor_value_leave_container(it
, &recursed
); 
 150                                 return err
;       // parse error 
 151                         indent(nestingLevel
); 
 158                         err 
= dumpelm(it
, &got_next
, (isMapType 
&& (elmCount 
% 2)) ? 0 : nestingLevel
); 
 161                         if (cmdCode 
> 0 && nestingLevel 
== 1 && isMapType 
&& !(elmCount 
% 2)) { 
 163                                 cbor_value_get_int64(it
, &val
); 
 164                                 char *desc 
= fido2GetCmdMemberDescription(cmdCode
, isResponse
, val
); 
 166                                         printf(" (%s)", desc
); 
 173                         err 
= cbor_value_advance_fixed(it
); 
 177                 if (isMapType 
&& !(elmCount 
% 2)) { 
 187 int TinyCborInit(uint8_t *data
, size_t length
, CborValue 
*cb
) { 
 189         CborError err 
= cbor_parser_init(data
, length
, 0, &parser
, cb
); 
 196 int TinyCborPrintFIDOPackage(uint8_t cmdCode
, bool isResponse
, uint8_t *data
, size_t length
) { 
 199         res 
= TinyCborInit(data
, length
, &cb
); 
 203     CborError err 
= dumprecursive(cmdCode
, isResponse
, &cb
, false, 0); 
 208                 "CBOR parsing failure at offset %" PRId64 
" : %s\n", 
 210                 "CBOR parsing failure at offset %" PRId32 
" : %s\n",     
 212                 cb
.ptr 
- data
, cbor_error_string(err
)); 
 219 int JsonObjElmCount(json_t 
*elm
) { 
 224         if (!json_is_object(elm
)) 
 227         json_object_foreach(elm
, key
, value
) { 
 228                 if (strlen(key
) > 0 && key
[0] != '.') 
 235 int JsonToCbor(json_t 
*elm
, CborEncoder 
*encoder
) { 
 236         if (!elm 
|| !encoder
) 
 241         // CBOR map == JSON object 
 242         if (json_is_object(elm
)) { 
 247                 res 
= cbor_encoder_create_map(encoder
, &map
, JsonObjElmCount(elm
)); 
 250                 json_object_foreach(elm
, key
, value
) { 
 251                         if (strlen(key
) > 0 && key
[0] != '.') { 
 252                                 res 
= cbor_encode_text_stringz(&map
, key
);               
 256                                 JsonToCbor(value
, &map
); 
 260                 res 
= cbor_encoder_close_container(encoder
, &map
); 
 264         // CBOR array == JSON array 
 265         if (json_is_array(elm
)) { 
 270                 res 
= cbor_encoder_create_array(encoder
, &array
, json_array_size(elm
)); 
 273                 json_array_foreach(elm
, index
, value
) { 
 275                         JsonToCbor(value
, &array
); 
 278                 res 
= cbor_encoder_close_container(encoder
, &array
); 
 282         if (json_is_boolean(elm
)) { 
 283                 res 
= cbor_encode_boolean(encoder
, json_is_true(elm
)); 
 287         if (json_is_integer(elm
)) { 
 288                 res 
= cbor_encode_int(encoder
, json_integer_value(elm
)); 
 292         if (json_is_real(elm
)) { 
 293                 res 
= cbor_encode_float(encoder
, json_real_value(elm
)); 
 297         if (json_is_string(elm
)) { 
 298                 const char * val 
= json_string_value(elm
); 
 299                 if (CheckStringIsHEXValue(val
)) { 
 301                         uint8_t data
[4096] = {0}; 
 302                         res 
= JsonLoadBufAsHex(elm
, "$", data
, sizeof(data
), &datalen
); 
 306                         res 
= cbor_encode_byte_string(encoder
, data
, datalen
); 
 309                         res 
= cbor_encode_text_stringz(encoder
, val
); 
 319 int CborMapGetKeyById(CborParser 
*parser
, CborValue 
*map
, uint8_t *data
, size_t dataLen
, int key
) { 
 322         CborError err 
= cbor_parser_init(data
, dataLen
, 0, parser
, &cb
); 
 325         if (cbor_value_get_type(&cb
) != CborMapType
) 
 328         err 
= cbor_value_enter_container(&cb
, map
); 
 332         while (!cbor_value_at_end(map
)) { 
 334                 if (cbor_value_get_type(map
) != CborIntegerType
) 
 337                 cbor_value_get_int64(map
, &indx
); 
 339                 err 
= cbor_value_advance(map
); 
 346                 err 
= cbor_value_advance(map
); 
 350         err 
= cbor_value_leave_container(&cb
, map
); 
 356 CborError 
CborGetArrayBinStringValue(CborValue 
*elm
, uint8_t *data
, size_t maxdatalen
, size_t *datalen
) { 
 357         return CborGetArrayBinStringValueEx(elm
, data
, maxdatalen
, datalen
, NULL
, 0); 
 360 CborError 
CborGetArrayBinStringValueEx(CborValue 
*elm
, uint8_t *data
, size_t maxdatalen
, size_t *datalen
, uint8_t *delimeter
, size_t delimeterlen
) { 
 365         size_t slen 
= maxdatalen
; 
 368         CborError res 
= cbor_value_enter_container(elm
, &array
); 
 371         while (!cbor_value_at_end(&array
)) { 
 372                 res 
= cbor_value_copy_byte_string(&array
, &data
[totallen
], &slen
, &array
); 
 377                         memcpy(&data
[totallen
], delimeter
, delimeterlen
); 
 378                         totallen 
+= delimeterlen
; 
 380                 slen 
= maxdatalen 
- totallen
; 
 383         res 
= cbor_value_leave_container(elm
, &array
); 
 392 CborError 
CborGetBinStringValue(CborValue 
*elm
, uint8_t *data
, size_t maxdatalen
, size_t *datalen
) { 
 396         size_t slen 
= maxdatalen
; 
 398         CborError res 
= cbor_value_copy_byte_string(elm
, data
, &slen
, elm
); 
 407 CborError 
CborGetArrayStringValue(CborValue 
*elm
, char *data
, size_t maxdatalen
, size_t *datalen
, char *delimeter
) { 
 412         size_t slen 
= maxdatalen
; 
 415         CborError res 
= cbor_value_enter_container(elm
, &array
); 
 418         while (!cbor_value_at_end(&array
)) { 
 419                 res 
= cbor_value_copy_text_string(&array
, &data
[totallen
], &slen
, &array
); 
 424                         strcat(data
, delimeter
); 
 425                         totallen 
+= strlen(delimeter
); 
 427                 slen 
= maxdatalen 
- totallen
; 
 428                 data
[totallen
] = 0x00; 
 431         res 
= cbor_value_leave_container(elm
, &array
); 
 440 CborError 
CborGetStringValue(CborValue 
*elm
, char *data
, size_t maxdatalen
, size_t *datalen
) { 
 444         size_t slen 
= maxdatalen
; 
 446         CborError res 
= cbor_value_copy_text_string(elm
, data
, &slen
, elm
); 
 455 CborError 
CborGetStringValueBuf(CborValue 
*elm
) { 
 456         static char stringBuf
[2048]; 
 457         memset(stringBuf
, 0x00, sizeof(stringBuf
)); 
 459         return CborGetStringValue(elm
, stringBuf
, sizeof(stringBuf
), NULL
); 
 462 int CBOREncodeElm(json_t 
*root
, char *rootElmId
, CborEncoder 
*encoder
) { 
 464         if (rootElmId 
&& strlen(rootElmId
) && rootElmId
[0] == '$') 
 465                 elm 
= json_path_get(root
, rootElmId
); 
 467                 elm 
= json_object_get(root
, rootElmId
); 
 472         int res 
= JsonToCbor(elm
, encoder
); 
 477 CborError 
CBOREncodeClientDataHash(json_t 
*root
, CborEncoder 
*encoder
) { 
 478         uint8_t buf
[100] = {0}; 
 481         JsonLoadBufAsHex(root
, "$.ClientDataHash", buf
, sizeof(buf
), &jlen
); 
 483         // fill with 0x00 if not found 
 487         int res 
= cbor_encode_byte_string(encoder
, buf
, jlen
);