1 // Copyright 2021 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14
15 #ifndef DICE_CBOR_READER_H_
16 #define DICE_CBOR_READER_H_
17
18 #include <stdbool.h>
19 #include <stddef.h>
20 #include <stdint.h>
21
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25
26 struct CborIn {
27 const uint8_t* buffer;
28 size_t buffer_size;
29 size_t cursor;
30 };
31
32 enum CborReadResult {
33 CBOR_READ_RESULT_OK,
34 // The end of the input was reached before the token was fully read.
35 CBOR_READ_RESULT_END,
36 // A malformed or unsupported token was found.
37 CBOR_READ_RESULT_MALFORMED,
38 // The requested token was not found.
39 CBOR_READ_RESULT_NOT_FOUND,
40 };
41
42 // Initializes an input stream for reading CBOR tokens.
CborInInit(const uint8_t * buffer,size_t buffer_size,struct CborIn * in)43 static inline void CborInInit(const uint8_t* buffer, size_t buffer_size,
44 struct CborIn* in) {
45 in->buffer = buffer;
46 in->buffer_size = buffer_size;
47 in->cursor = 0;
48 }
49
50 // Returns the number of bytes that have been read from the input.
CborInOffset(const struct CborIn * in)51 static inline size_t CborInOffset(const struct CborIn* in) {
52 return in->cursor;
53 }
54
55 // Returns whether the input stream has been fully consumed.
CborInAtEnd(const struct CborIn * in)56 static inline bool CborInAtEnd(const struct CborIn* in) {
57 return in->cursor == in->buffer_size;
58 }
59
60 // These functions read simple CBOR tokens from the input stream. Interpreting
61 // the greater structure of the data left to the caller and it is expected that
62 // these functions are just being used to validate and extract data from a known
63 // structure.
64 enum CborReadResult CborReadInt(struct CborIn* in, int64_t* val);
65 enum CborReadResult CborReadUint(struct CborIn* in, uint64_t* val);
66 enum CborReadResult CborReadBstr(struct CborIn* in, size_t* data_size,
67 const uint8_t** data);
68 enum CborReadResult CborReadTstr(struct CborIn* in, size_t* size,
69 const char** str);
70 enum CborReadResult CborReadArray(struct CborIn* in, size_t* num_elements);
71 enum CborReadResult CborReadMap(struct CborIn* in, size_t* num_pairs);
72 enum CborReadResult CborReadFalse(struct CborIn* in);
73 enum CborReadResult CborReadTrue(struct CborIn* in);
74 enum CborReadResult CborReadNull(struct CborIn* in);
75 // Returns CBOR_READ_RESULT_OK even if the value read does not correspond to
76 // a valid tag. See https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml
77 // for a registry of reserved and invalid tag values.
78 enum CborReadResult CborReadTag(struct CborIn* in, uint64_t* tag);
79
80 // Skips over the next CBOR item in the input. The item may contain nested
81 // items, in the case of an array, map, or tag, and this function will attempt
82 // to descend and skip all nested items in order to skip the parent item. There
83 // is a limit on the level of nesting, after which this function will fail with
84 // CBOR_READ_RESULT_MALFORMED.
85 #define CBOR_READ_SKIP_STACK_SIZE 10
86 enum CborReadResult CborReadSkip(struct CborIn* in);
87
88 #ifdef __cplusplus
89 } // extern "C"
90 #endif
91
92 #endif // DICE_CBOR_READER_H_
93