200 {
201 if(shares.size() <= 1) {
202 throw Decoding_Error("Insufficient shares to do TSS reconstruction");
203 }
204
205 for(size_t i = 0; i != shares.size(); ++i) {
206 if(shares[i].
size() < RTSS_HEADER_SIZE + 1) {
207 throw Decoding_Error("Missing or malformed RTSS header");
208 }
209
211 throw Decoding_Error("Invalid (id = 0) RTSS share detected");
212 }
213
214 if(i > 0) {
215 if(shares[i].
size() != shares[0].
size()) {
216 throw Decoding_Error("Different sized RTSS shares detected");
217 }
218
219 if(!
CT::is_equal(&shares[0].m_contents[0], &shares[i].m_contents[0], RTSS_HEADER_SIZE).as_bool()) {
220 throw Decoding_Error("Different RTSS headers detected");
221 }
222 }
223 }
224
225 const uint8_t N = shares[0].m_contents[17];
226
227 if(shares.size() < N) {
228 throw Decoding_Error("Insufficient shares to do TSS reconstruction");
229 }
230
231 const uint16_t share_len =
make_uint16(shares[0].m_contents[18], shares[0].m_contents[19]);
232
233 const uint8_t hash_id = shares[0].m_contents[16];
234 auto hash = get_rtss_hash_by_id(hash_id);
235 const size_t hash_len = (hash ? hash->output_length() : 0);
236
237 if(shares[0].
size() != RTSS_HEADER_SIZE + share_len) {
238
239
240
241
242
243
244 if(shares[0].
size() <= RTSS_HEADER_SIZE + 1 + hash_len) {
245 throw Decoding_Error("Bad RTSS length field in header");
246 }
247 }
248
249 std::vector<uint8_t> V(shares.size());
251
252 for(size_t i = RTSS_HEADER_SIZE + 1; i != shares[0].size(); ++i) {
253 for(size_t j = 0; j != V.size(); ++j) {
254 V[j] = shares[j].m_contents[i];
255 }
256
257 uint8_t r = 0;
258 for(size_t k = 0; k != shares.size(); ++k) {
259
260 uint8_t r2 = 1;
261 for(size_t l = 0; l != shares.size(); ++l) {
262 if(k == l) {
263 continue;
264 }
265
266 uint8_t share_k = shares[k].share_id();
267 uint8_t share_l = shares[l].share_id();
268
269 if(share_k == share_l) {
270 throw Decoding_Error("Duplicate shares found in RTSS recovery");
271 }
272
273 uint8_t div = RTSS_EXP[(255 + RTSS_LOG[share_l] - RTSS_LOG[share_k ^ share_l]) % 255];
274
275 r2 = gfp_mul(r2, div);
276 }
277
278 r ^= gfp_mul(V[k], r2);
279 }
280 recovered.push_back(r);
281 }
282
283 if(hash) {
284 if(recovered.size() < hash->output_length()) {
285 throw Decoding_Error("RTSS recovered value too short to be valid");
286 }
287
288 const size_t secret_len = recovered.size() - hash->output_length();
289
290 hash->update(recovered.data(), secret_len);
292
293 if(!
CT::is_equal(hash_check.data(), &recovered[secret_len], hash->output_length()).as_bool()) {
294 throw Decoding_Error("RTSS hash check failed");
295 }
296
297
298 recovered.resize(secret_len);
299 }
300
301 return recovered;
302}
constexpr CT::Mask< T > is_equal(const T x[], const T y[], size_t len)
std::vector< T, secure_allocator< T > > secure_vector
constexpr uint16_t make_uint16(uint8_t i0, uint8_t i1)