1*14675a02SAndroid Build Coastguard Worker // Copyright 2021 Google LLC
2*14675a02SAndroid Build Coastguard Worker //
3*14675a02SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*14675a02SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*14675a02SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*14675a02SAndroid Build Coastguard Worker //
7*14675a02SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
8*14675a02SAndroid Build Coastguard Worker //
9*14675a02SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*14675a02SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*14675a02SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*14675a02SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*14675a02SAndroid Build Coastguard Worker // limitations under the License.
14*14675a02SAndroid Build Coastguard Worker
15*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/shared/aes_key.h"
16*14675a02SAndroid Build Coastguard Worker
17*14675a02SAndroid Build Coastguard Worker #include <string>
18*14675a02SAndroid Build Coastguard Worker
19*14675a02SAndroid Build Coastguard Worker #include "fcp/base/monitoring.h"
20*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/shared/shamir_secret_sharing.h"
21*14675a02SAndroid Build Coastguard Worker
22*14675a02SAndroid Build Coastguard Worker static constexpr int kLegacyKeySize = 17;
23*14675a02SAndroid Build Coastguard Worker
24*14675a02SAndroid Build Coastguard Worker namespace fcp {
25*14675a02SAndroid Build Coastguard Worker namespace secagg {
26*14675a02SAndroid Build Coastguard Worker
AesKey(const uint8_t * data,int key_size)27*14675a02SAndroid Build Coastguard Worker AesKey::AesKey(const uint8_t* data, int key_size) : Key(data, key_size) {
28*14675a02SAndroid Build Coastguard Worker FCP_CHECK((key_size > 0 && key_size <= 17) || (key_size == 32));
29*14675a02SAndroid Build Coastguard Worker }
30*14675a02SAndroid Build Coastguard Worker
CreateFromShares(const std::vector<ShamirShare> & shares,int threshold)31*14675a02SAndroid Build Coastguard Worker StatusOr<AesKey> AesKey::CreateFromShares(
32*14675a02SAndroid Build Coastguard Worker const std::vector<ShamirShare>& shares, int threshold) {
33*14675a02SAndroid Build Coastguard Worker ShamirSecretSharing reconstructor;
34*14675a02SAndroid Build Coastguard Worker // TODO(team): Once Java support is removed, assume 32 byte keys.
35*14675a02SAndroid Build Coastguard Worker int key_length = 0;
36*14675a02SAndroid Build Coastguard Worker // For compatibility, we need to know if the key that was shared was 128 or
37*14675a02SAndroid Build Coastguard Worker // 256 bits long. It can only have been one of those two lengths, so the
38*14675a02SAndroid Build Coastguard Worker // shares should be either 20 or 36 bytes long respectively.
39*14675a02SAndroid Build Coastguard Worker for (int i = 0; i < shares.size() && key_length == 0; ++i) {
40*14675a02SAndroid Build Coastguard Worker if (shares[i].data.size() == 36) {
41*14675a02SAndroid Build Coastguard Worker key_length = kSize;
42*14675a02SAndroid Build Coastguard Worker } else if (shares[i].data.size() == 20) {
43*14675a02SAndroid Build Coastguard Worker key_length = kLegacyKeySize; // May be 17 bytes or shorter, see below
44*14675a02SAndroid Build Coastguard Worker } else {
45*14675a02SAndroid Build Coastguard Worker // Key share must be missing if it's not one of those lengths.
46*14675a02SAndroid Build Coastguard Worker FCP_CHECK(shares[i].data.empty());
47*14675a02SAndroid Build Coastguard Worker }
48*14675a02SAndroid Build Coastguard Worker }
49*14675a02SAndroid Build Coastguard Worker FCP_CHECK(key_length != 0);
50*14675a02SAndroid Build Coastguard Worker std::string reconstructed;
51*14675a02SAndroid Build Coastguard Worker FCP_ASSIGN_OR_RETURN(
52*14675a02SAndroid Build Coastguard Worker reconstructed, reconstructor.Reconstruct(threshold, shares, key_length));
53*14675a02SAndroid Build Coastguard Worker
54*14675a02SAndroid Build Coastguard Worker if (key_length == kLegacyKeySize) {
55*14675a02SAndroid Build Coastguard Worker // The key produced on Java side normally has 16 bytes, however when
56*14675a02SAndroid Build Coastguard Worker // exporting the key from BigInteger to byte array an extra zero byte is
57*14675a02SAndroid Build Coastguard Worker // added at the front if the high-order bit was '1' to indicate that the
58*14675a02SAndroid Build Coastguard Worker // BigInteger value was positive (to avoid treating the high order bit
59*14675a02SAndroid Build Coastguard Worker // as the sign bit). However the byte array may also be shorter than
60*14675a02SAndroid Build Coastguard Worker // 16 bytes if the BigInteger value was smaller.
61*14675a02SAndroid Build Coastguard Worker // For compatibility with Java behavior any leading zero byte that isn't
62*14675a02SAndroid Build Coastguard Worker // followed by a byte with '1' in the high-order bit need to be removed.
63*14675a02SAndroid Build Coastguard Worker int index = 0;
64*14675a02SAndroid Build Coastguard Worker while (index < kLegacyKeySize - 1 &&
65*14675a02SAndroid Build Coastguard Worker static_cast<uint8_t>(reconstructed[index]) == 0 &&
66*14675a02SAndroid Build Coastguard Worker static_cast<uint8_t>(reconstructed[index + 1]) <= 127) {
67*14675a02SAndroid Build Coastguard Worker index++;
68*14675a02SAndroid Build Coastguard Worker }
69*14675a02SAndroid Build Coastguard Worker
70*14675a02SAndroid Build Coastguard Worker if (index > 0) {
71*14675a02SAndroid Build Coastguard Worker reconstructed.erase(0, index);
72*14675a02SAndroid Build Coastguard Worker key_length -= index;
73*14675a02SAndroid Build Coastguard Worker }
74*14675a02SAndroid Build Coastguard Worker }
75*14675a02SAndroid Build Coastguard Worker return AesKey(reinterpret_cast<const uint8_t*>(reconstructed.c_str()),
76*14675a02SAndroid Build Coastguard Worker key_length);
77*14675a02SAndroid Build Coastguard Worker }
78*14675a02SAndroid Build Coastguard Worker
79*14675a02SAndroid Build Coastguard Worker } // namespace secagg
80*14675a02SAndroid Build Coastguard Worker } // namespace fcp
81