1 /*
2  * Copyright 2020, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ANDROID_HARDWARE_IDENTITY_EIC_CBOR_H
18 #define ANDROID_HARDWARE_IDENTITY_EIC_CBOR_H
19 
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23 
24 #include "EicOps.h"
25 
26 typedef enum {
27   EIC_CBOR_DIGEST_TYPE_SHA256,
28   EIC_CBOR_DIGEST_TYPE_HMAC_SHA256,
29 } EicCborDigestType;
30 
31 /* EicCbor is a utility class to build CBOR data structures and calculate
32  * digests on the fly.
33  */
34 typedef struct {
35   // Contains the size of the built CBOR, even if it exceeds bufferSize (will
36   // never write to buffer beyond bufferSize though)
37   size_t size;
38 
39   // The size of the buffer. Is zero if no data is recorded in which case
40   // only digesting is performed.
41   size_t bufferSize;
42 
43   // Whether we're producing a SHA-256 or HMAC-SHA256 digest.
44   EicCborDigestType digestType;
45 
46   // The SHA-256 digester object.
47   union {
48     EicSha256Ctx sha256;
49     EicHmacSha256Ctx hmacSha256;
50   } digester;
51 
52   // The secondary digester, may be unset.
53   EicSha256Ctx* secondaryDigesterSha256;
54 
55   // The buffer used for building up CBOR or NULL if bufferSize is 0.
56   uint8_t* buffer;
57 } EicCbor;
58 
59 /* Initializes an EicCbor.
60  *
61  * The given buffer will be used, up to bufferSize.
62  *
63  * If bufferSize is 0, buffer may be NULL.
64  */
65 void eicCborInit(EicCbor* cbor, uint8_t* buffer, size_t bufferSize);
66 
67 /* Like eicCborInit() but uses HMAC-SHA256 instead of SHA-256.
68  */
69 void eicCborInitHmacSha256(EicCbor* cbor, uint8_t* buffer, size_t bufferSize,
70                            const uint8_t* hmacKey, size_t hmacKeySize);
71 
72 /* Enables a secondary digester.
73  *
74  * May be enabled midway through processing, this can be used to e.g. calculate
75  * a digest of Sig_structure (for COSE_Sign1) and a separate digest of its
76  * payload.
77  */
78 void eicCborEnableSecondaryDigesterSha256(EicCbor* cbor, EicSha256Ctx* sha256);
79 
80 /* Finishes building CBOR and returns the digest. */
81 void eicCborFinal(EicCbor* cbor, uint8_t digest[EIC_SHA256_DIGEST_SIZE]);
82 
83 /* Appends CBOR data to the EicCbor. */
84 void eicCborAppend(EicCbor* cbor, const uint8_t* data, size_t size);
85 
86 #define EIC_CBOR_MAJOR_TYPE_UNSIGNED 0
87 #define EIC_CBOR_MAJOR_TYPE_NEGATIVE 1
88 #define EIC_CBOR_MAJOR_TYPE_BYTE_STRING 2
89 #define EIC_CBOR_MAJOR_TYPE_STRING 3
90 #define EIC_CBOR_MAJOR_TYPE_ARRAY 4
91 #define EIC_CBOR_MAJOR_TYPE_MAP 5
92 #define EIC_CBOR_MAJOR_TYPE_SEMANTIC 6
93 #define EIC_CBOR_MAJOR_TYPE_SIMPLE 7
94 
95 #define EIC_CBOR_SIMPLE_VALUE_FALSE 20
96 #define EIC_CBOR_SIMPLE_VALUE_TRUE 21
97 
98 #define EIC_CBOR_SEMANTIC_TAG_ENCODED_CBOR 24
99 
100 /* Begins a new CBOR value. */
101 void eicCborBegin(EicCbor* cbor, int majorType, uint64_t size);
102 
103 /* Appends a bytestring. */
104 void eicCborAppendByteString(EicCbor* cbor, const uint8_t* data,
105                              size_t dataSize);
106 
107 /* Appends a UTF-8 string. */
108 void eicCborAppendString(EicCbor* cbor, const char* str, size_t strLength);
109 
110 /* Appends a NUL-terminated UTF-8 string. */
111 void eicCborAppendStringZ(EicCbor* cbor, const char* str);
112 
113 /* Appends a simple value. */
114 void eicCborAppendSimple(EicCbor* cbor, uint8_t simpleValue);
115 
116 /* Appends a boolean. */
117 void eicCborAppendBool(EicCbor* cbor, bool value);
118 
119 /* Appends a semantic */
120 void eicCborAppendSemantic(EicCbor* cbor, uint64_t value);
121 
122 /* Appends an unsigned number. */
123 void eicCborAppendUnsigned(EicCbor* cbor, uint64_t value);
124 
125 /* Appends a number. */
126 void eicCborAppendNumber(EicCbor* cbor, int64_t value);
127 
128 /* Starts appending an array.
129  *
130  * After this numElements CBOR elements must follow.
131  */
132 void eicCborAppendArray(EicCbor* cbor, size_t numElements);
133 
134 /* Starts appending a map.
135  *
136  * After this numPairs pairs of CBOR elements must follow.
137  */
138 void eicCborAppendMap(EicCbor* cbor, size_t numPairs);
139 
140 /* Calculates how many bytes are needed to store a size. */
141 size_t eicCborAdditionalLengthBytesFor(size_t size);
142 
143 bool eicCborCalcAccessControl(EicCbor* cborBuilder, int id,
144                               const uint8_t* readerCertificate,
145                               size_t readerCertificateSize,
146                               bool userAuthenticationRequired,
147                               uint64_t timeoutMillis, uint64_t secureUserId);
148 
149 bool eicCborCalcEntryAdditionalData(
150     const uint8_t* accessControlProfileIds, size_t numAccessControlProfileIds,
151     const char* nameSpace, size_t nameSpaceLength, const char* name,
152     size_t nameLength, uint8_t* cborBuffer, size_t cborBufferSize,
153     size_t* outAdditionalDataCborSize,
154     uint8_t additionalDataSha256[EIC_SHA256_DIGEST_SIZE]);
155 
156 #ifdef __cplusplus
157 }
158 #endif
159 
160 #endif  // ANDROID_HARDWARE_IDENTITY_EIC_CBOR_H
161