blob: 70afda156d1a6534083b4cbeb15a3d7c6b013271 [file] [log] [blame]
Vitaly Buka45dc9df2015-12-07 21:30:19 -08001// Copyright 2015 The Weave Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/macaroon.h"
6
7#include <string.h>
8
9#include "src/crypto_utils.h"
Vitaly Buka6a8bd5d2015-12-08 21:06:59 -080010#include "src/macaroon_caveat.h"
11#include "src/macaroon_encoding.h"
Vitaly Buka45dc9df2015-12-07 21:30:19 -080012
13static bool create_mac_tag_(const uint8_t* key, size_t key_len,
14 const UwMacaroonCaveat* caveats, size_t num_caveats,
15 uint8_t mac_tag[UW_MACAROON_MAC_LEN]) {
16 if (key == NULL || key_len == 0 || caveats == NULL || num_caveats == 0 ||
17 mac_tag == NULL) {
18 return false;
19 }
20
21 // Store the intermediate MAC tags in an internal buffer before we finish the
22 // whole computation.
23 // If we use the output buffer mac_tag directly and certain errors happen in
24 // the middle of this computation, mac_tag will probably contain a valid
25 // macaroon tag with large scope than expected.
26 uint8_t mac_tag_buff[UW_MACAROON_MAC_LEN];
27
28 // Compute the first tag by using the key
29 if (!uw_macaroon_caveat_sign_(key, key_len, &(caveats[0]), mac_tag_buff,
30 UW_MACAROON_MAC_LEN)) {
31 return false;
32 }
33
34 // Compute the rest of the tags by using the tag as the key
35 for (size_t i = 1; i < num_caveats; i++) {
36 if (!uw_macaroon_caveat_sign_(mac_tag_buff, UW_MACAROON_MAC_LEN,
37 &(caveats[i]), mac_tag_buff,
38 UW_MACAROON_MAC_LEN)) {
39 return false;
40 }
41 }
42
43 memcpy(mac_tag, mac_tag_buff, UW_MACAROON_MAC_LEN);
44 return true;
45}
46
47bool uw_macaroon_new_from_mac_tag_(UwMacaroon* new_macaroon,
48 const uint8_t mac_tag[UW_MACAROON_MAC_LEN],
49 const UwMacaroonCaveat* caveats,
50 size_t num_caveats) {
51 if (new_macaroon == NULL || mac_tag == NULL || caveats == NULL ||
52 num_caveats == 0) {
53 return false;
54 }
55
56 memcpy(new_macaroon->mac_tag, mac_tag, UW_MACAROON_MAC_LEN);
57 new_macaroon->num_caveats = num_caveats;
58 new_macaroon->caveats = caveats;
59
60 return true;
61}
62
63bool uw_macaroon_new_from_root_key_(UwMacaroon* new_macaroon,
64 const uint8_t* root_key,
65 size_t root_key_len,
66 const UwMacaroonCaveat* caveats,
67 size_t num_caveats) {
68 if (new_macaroon == NULL || root_key == NULL || root_key_len == 0 ||
69 caveats == NULL || num_caveats == 0) {
70 return false;
71 }
72
73 if (!create_mac_tag_(root_key, root_key_len, caveats, num_caveats,
74 new_macaroon->mac_tag)) {
75 return false;
76 }
77
78 new_macaroon->num_caveats = num_caveats;
79 new_macaroon->caveats = caveats;
80
81 return true;
82}
83
84bool uw_macaroon_verify_(const UwMacaroon* macaroon,
85 const uint8_t* root_key,
86 size_t root_key_len) {
87 if (macaroon == NULL || root_key == NULL) {
88 return false;
89 }
90
91 uint8_t mac_tag[UW_MACAROON_MAC_LEN] = {0};
92 if (!create_mac_tag_(root_key, root_key_len, macaroon->caveats,
93 macaroon->num_caveats, mac_tag)) {
94 return false;
95 }
96
97 return uw_crypto_utils_equal_(mac_tag, macaroon->mac_tag,
98 UW_MACAROON_MAC_LEN);
99}
100
101bool uw_macaroon_extend_(const UwMacaroon* old_macaroon,
102 UwMacaroon* new_macaroon,
103 const UwMacaroonCaveat* additional_caveat,
104 uint8_t* buffer, size_t buffer_size) {
105 if (old_macaroon == NULL || new_macaroon == NULL ||
106 additional_caveat == NULL || buffer == NULL || buffer_size == 0) {
107 return false;
108 }
109
110 new_macaroon->num_caveats = old_macaroon->num_caveats + 1;
111
112 // Extend the caveat list
113 if ((new_macaroon->num_caveats) * sizeof(UwMacaroonCaveat) > buffer_size) {
114 // Not enough memory to store the extended caveat list
115 return false;
116 }
117 UwMacaroonCaveat* extended_list = (UwMacaroonCaveat*)buffer;
118 if (old_macaroon->caveats != NULL && extended_list != old_macaroon->caveats) {
119 memcpy(extended_list, old_macaroon->caveats,
120 (old_macaroon->num_caveats) * sizeof(UwMacaroonCaveat));
121 }
122 extended_list[old_macaroon->num_caveats] = *additional_caveat;
123 new_macaroon->caveats = extended_list;
124
125 // Compute the new MAC tag
126 return create_mac_tag_(old_macaroon->mac_tag, UW_MACAROON_MAC_LEN,
127 additional_caveat, 1, new_macaroon->mac_tag);
128}
Vitaly Buka6a8bd5d2015-12-08 21:06:59 -0800129
130// Encode a Macaroon to a byte string
131bool uw_macaroon_dump_(const UwMacaroon* macaroon,
132 uint8_t* out,
133 size_t out_len,
134 size_t* resulting_str_len) {
135 if (macaroon == NULL || out == NULL || out_len == 0 ||
136 resulting_str_len == NULL) {
137 return false;
138 }
139
140 size_t offset = 0, item_len;
141
142 if (!uw_macaroon_encoding_encode_byte_str_(
143 macaroon->mac_tag, UW_MACAROON_MAC_LEN, out, out_len, &item_len)) {
144 return false;
145 }
146 offset += item_len;
147
148 if (!uw_macaroon_encoding_encode_array_len_(
149 (uint32_t)(macaroon->num_caveats), out + offset, out_len - offset, &item_len)) {
150 return false;
151 }
152 offset += item_len;
153
154 for (size_t i = 0; i < macaroon->num_caveats; i++) {
155 if (!uw_macaroon_encoding_encode_byte_str_(
156 macaroon->caveats[i].bytes, macaroon->caveats[i].num_bytes,
157 out + offset, out_len - offset, &item_len)) {
158 return false;
159 }
160 offset += item_len;
161 }
162
163 *resulting_str_len = offset;
164 return true;
165}
166
167// Decode a byte string to a Macaroon
168bool uw_macaroon_load_(const uint8_t* in,
169 size_t in_len,
170 uint8_t* caveats_buffer,
171 size_t caveats_buffer_size,
172 UwMacaroon* macaroon) {
173 if (in == NULL || in_len == 0 || caveats_buffer == NULL ||
174 caveats_buffer_size == 0 || macaroon == NULL) {
175 return false;
176 }
177
178 const uint8_t* tag;
179 size_t tag_len;
180 if (!uw_macaroon_encoding_decode_byte_str_(in, in_len, &tag, &tag_len) ||
181 tag_len != UW_MACAROON_MAC_LEN) {
182 return false;
183 }
184 memcpy(macaroon->mac_tag, tag, UW_MACAROON_MAC_LEN);
185
186 size_t offset = 0, cbor_item_len;
187 if (!uw_macaroon_encoding_get_item_len_(in, in_len, &cbor_item_len)) {
188 return false;
189 }
190 offset += cbor_item_len;
191
192 uint32_t array_len;
193 if (!uw_macaroon_encoding_decode_array_len_(in + offset, in_len - offset,
194 &array_len)) {
195 return false;
196 }
197 macaroon->num_caveats = (size_t)array_len;
198 if (caveats_buffer_size < array_len * sizeof(UwMacaroonCaveat)) {
199 return false;
200 }
201
202 UwMacaroonCaveat* caveats = (UwMacaroonCaveat*)caveats_buffer;
203 for (size_t i = 0; i < array_len; i++) {
204 if (!uw_macaroon_encoding_get_item_len_(in + offset, in_len - offset,
205 &cbor_item_len)) {
206 return false;
207 }
208 offset += cbor_item_len;
209
210 if (!uw_macaroon_encoding_decode_byte_str_(in + offset, in_len - offset,
211 &(caveats[i].bytes),
212 &(caveats[i].num_bytes))) {
213 return false;
214 }
215 }
216 macaroon->caveats = caveats;
217
218 return true;
219}