226 {
227 if(shares.size() <= 1)
228 throw Decoding_Error("Insufficient shares to do TSS reconstruction");
229
230 for(size_t i = 0; i != shares.size(); ++i)
231 {
232 if(shares[i].
size() < RTSS_HEADER_SIZE + 1)
233 throw Decoding_Error("Missing or malformed RTSS header");
234
236 throw Decoding_Error("Invalid (id = 0) RTSS share detected");
237
238 if(i > 0)
239 {
240 if(shares[i].
size() != shares[0].
size())
241 throw Decoding_Error("Different sized RTSS shares detected");
242
243 if(!
same_mem(&shares[0].m_contents[0],
244 &shares[i].m_contents[0], RTSS_HEADER_SIZE))
245 throw Decoding_Error("Different RTSS headers detected");
246 }
247 }
248
249 const uint8_t N = shares[0].m_contents[17];
250
251 if(shares.size() < N)
252 throw Decoding_Error("Insufficient shares to do TSS reconstruction");
253
254 const uint16_t share_len =
make_uint16(shares[0].m_contents[18],
255 shares[0].m_contents[19]);
256
257 const uint8_t hash_id = shares[0].m_contents[16];
258 auto hash = get_rtss_hash_by_id(hash_id);
259 const size_t hash_len = (hash ? hash->output_length() : 0);
260
261 if(shares[0].
size() != RTSS_HEADER_SIZE + share_len)
262 {
263
264
265
266
267
268
269 if(shares[0].
size() <= RTSS_HEADER_SIZE + 1 + hash_len)
270 throw Decoding_Error("Bad RTSS length field in header");
271 }
272
273 std::vector<uint8_t> V(shares.size());
274 secure_vector<uint8_t> recovered;
275
276 for(size_t i = RTSS_HEADER_SIZE + 1; i != shares[0].size(); ++i)
277 {
278 for(size_t j = 0; j != V.size(); ++j)
279 V[j] = shares[j].m_contents[i];
280
281 uint8_t r = 0;
282 for(size_t k = 0; k != shares.size(); ++k)
283 {
284
285 uint8_t r2 = 1;
286 for(size_t l = 0; l != shares.size(); ++l)
287 {
288 if(k == l)
289 continue;
290
291 uint8_t share_k = shares[k].share_id();
292 uint8_t share_l = shares[l].share_id();
293
294 if(share_k == share_l)
295 throw Decoding_Error("Duplicate shares found in RTSS recovery");
296
297 uint8_t div = RTSS_EXP[(255 +
298 RTSS_LOG[share_l] -
299 RTSS_LOG[share_k ^ share_l]) % 255];
300
301 r2 = gfp_mul(r2, div);
302 }
303
304 r ^= gfp_mul(V[k], r2);
305 }
306 recovered.push_back(r);
307 }
308
309 if(hash)
310 {
311 if(recovered.size() < hash->output_length())
312 throw Decoding_Error("RTSS recovered value too short to be valid");
313
314 const size_t secret_len = recovered.size() - hash->output_length();
315
316 hash->update(recovered.data(), secret_len);
317 secure_vector<uint8_t> hash_check = hash->final();
318
320 &recovered[secret_len],
321 hash->output_length()))
322 {
323 throw Decoding_Error("RTSS hash check failed");
324 }
325
326
327 recovered.resize(secret_len);
328 }
329
330 return recovered;
331 }
bool constant_time_compare(const uint8_t x[], const uint8_t y[], size_t len)
bool same_mem(const T *p1, const T *p2, size_t n)
constexpr uint16_t make_uint16(uint8_t i0, uint8_t i1)