diff options
Diffstat (limited to 'src/main/cpp/src/securegcm/d2d_connection_context_v1.cc')
-rw-r--r-- | src/main/cpp/src/securegcm/d2d_connection_context_v1.cc | 228 |
1 files changed, 0 insertions, 228 deletions
diff --git a/src/main/cpp/src/securegcm/d2d_connection_context_v1.cc b/src/main/cpp/src/securegcm/d2d_connection_context_v1.cc deleted file mode 100644 index 8a9a612..0000000 --- a/src/main/cpp/src/securegcm/d2d_connection_context_v1.cc +++ /dev/null @@ -1,228 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "securegcm/d2d_connection_context_v1.h" - -#include <limits> -#include <sstream> - -#include "proto/device_to_device_messages.pb.h" -#include "proto/securegcm.pb.h" -#include "securegcm/d2d_crypto_ops.h" -#include "securegcm/java_util.h" -#include "securemessage/secure_message_builder.h" -#include "securemessage/util.h" - -namespace securegcm { - -using securemessage::CryptoOps; -using securemessage::ByteBuffer; -using securemessage::Util; - -namespace { - -// Fields to fill in the GcmMetadata proto. -const Type kGcmMetadataType = DEVICE_TO_DEVICE_MESSAGE; - -// Represents the version of this context. -const uint8_t kProtocolVersion = 1; - -// The following represent the starting positions of the each entry within -// the string representation of this D2DConnectionContextV1. -// -// The saved session has a 1 byte protocol version, two 4 byte sequence numbers, -// and two 32 byte AES keys: (1 + 4 + 4 + 32 + 32 = 73). - -// The two sequence numbers are 4 bytes each. -const int kSequenceNumberLength = 4; - -// 32 byte AES keys. -const int kAesKeyLength = 32; - -// The encode sequence number starts at 1 to account for the 1 byte version -// number. -const int kEncodeSequenceStart = 1; -const int kEncodeSequenceEnd = kEncodeSequenceStart + kSequenceNumberLength; - -const int kDecodeSequenceStart = kEncodeSequenceEnd; -const int kDecodeSequenceEnd = kDecodeSequenceStart + kSequenceNumberLength; - -const int kEncodeKeyStart = kDecodeSequenceEnd; -const int kEncodeKeyEnd = kEncodeKeyStart + kAesKeyLength; - -const int kDecodeKeyStart = kEncodeKeyEnd; -const int kSavedSessionLength = kDecodeKeyStart + kAesKeyLength; - -// Convenience function to creates a DeviceToDeviceMessage proto with |payload| -// and |sequence_number|. -DeviceToDeviceMessage CreateDeviceToDeviceMessage(const std::string& payload, - uint32_t sequence_number) { - DeviceToDeviceMessage device_to_device_message; - device_to_device_message.set_sequence_number(sequence_number); - device_to_device_message.set_message(payload); - return device_to_device_message; -} - -// Convert 4 bytes in big-endian representation into an unsigned int. -uint32_t BytesToUnsignedInt(std::vector<uint8_t> bytes) { - return bytes[0] << 24 | bytes[1] << 12 | bytes[2] << 8 | bytes[3]; -} - -// Convert an unsigned int into a 4 byte big-endian representation. -std::vector<uint8_t> UnsignedIntToBytes(uint32_t val) { - return {static_cast<uint8_t>(val >> 24), static_cast<uint8_t>(val >> 12), - static_cast<uint8_t>(val >> 8), static_cast<uint8_t>(val)}; -} - -} // namespace - -D2DConnectionContextV1::D2DConnectionContextV1( - const CryptoOps::SecretKey& encode_key, - const CryptoOps::SecretKey& decode_key, uint32_t encode_sequence_number, - uint32_t decode_sequence_number) - : encode_key_(encode_key), - decode_key_(decode_key), - encode_sequence_number_(encode_sequence_number), - decode_sequence_number_(decode_sequence_number) {} - -std::unique_ptr<std::string> D2DConnectionContextV1::EncodeMessageToPeer( - const std::string& payload) { - encode_sequence_number_++; - const DeviceToDeviceMessage message = - CreateDeviceToDeviceMessage(payload, encode_sequence_number_); - - const D2DCryptoOps::Payload payload_with_type(kGcmMetadataType, - message.SerializeAsString()); - return D2DCryptoOps::SigncryptPayload(payload_with_type, encode_key_); -} - -std::unique_ptr<std::string> D2DConnectionContextV1::DecodeMessageFromPeer( - const std::string& message) { - std::unique_ptr<D2DCryptoOps::Payload> payload = - D2DCryptoOps::VerifyDecryptPayload(message, decode_key_); - if (!payload) { - Util::LogError("DecodeMessageFromPeer: Failed to verify message."); - return nullptr; - } - - if (kGcmMetadataType != payload->type()) { - Util::LogError("DecodeMessageFromPeer: Wrong message type in D2D message."); - return nullptr; - } - - DeviceToDeviceMessage d2d_message; - if (!d2d_message.ParseFromString(payload->message())) { - Util::LogError("DecodeMessageFromPeer: Unable to parse D2D message proto."); - return nullptr; - } - - decode_sequence_number_++; - if (d2d_message.sequence_number() != decode_sequence_number_) { - std::ostringstream stream; - stream << "DecodeMessageFromPeer: Seqno in D2D message (" - << d2d_message.sequence_number() - << ") does not match expected seqno (" << decode_sequence_number_ - << ")."; - Util::LogError(stream.str()); - return nullptr; - } - - return std::unique_ptr<std::string>(d2d_message.release_message()); -} - -std::unique_ptr<std::string> D2DConnectionContextV1::GetSessionUnique() { - const ByteBuffer encode_key_data = encode_key_.data(); - const ByteBuffer decode_key_data = decode_key_.data(); - const int32_t encode_key_hash = java_util::JavaHashCode(encode_key_data); - const int32_t decode_key_hash = java_util::JavaHashCode(decode_key_data); - - const ByteBuffer& first_buffer = - encode_key_hash < decode_key_hash ? encode_key_data : decode_key_data; - const ByteBuffer& second_buffer = - encode_key_hash < decode_key_hash ? decode_key_data : encode_key_data; - - ByteBuffer data_to_hash(D2DCryptoOps::kSalt, D2DCryptoOps::kSaltLength); - data_to_hash = ByteBuffer::Concat(data_to_hash, first_buffer); - data_to_hash = ByteBuffer::Concat(data_to_hash, second_buffer); - - std::unique_ptr<ByteBuffer> hash = CryptoOps::Sha256(data_to_hash); - if (!hash) { - Util::LogError("GetSessionUnique: SHA-256 hash failed."); - return nullptr; - } - - return std::unique_ptr<std::string>(new std::string(hash->String())); -} - -// Structure of saved session is: -// -// +---------------------------------------------------------------------------+ -// | 1 Byte | 4 Bytes | 4 Bytes | 32 Bytes | 32 Bytes | -// +---------------------------------------------------------------------------+ -// | Version | encode seq number | decode seq number | encode key | decode key | -// +---------------------------------------------------------------------------+ -// -// The sequence numbers are represented in big-endian. -std::unique_ptr<std::string> D2DConnectionContextV1::SaveSession() { - ByteBuffer byteBuffer = ByteBuffer(&kProtocolVersion, static_cast<size_t>(1)); - - // Append encode sequence number. - std::vector<uint8_t> encode_sequence_number_bytes = - UnsignedIntToBytes(encode_sequence_number_); - for (int i = 0; i < encode_sequence_number_bytes.size(); i++) { - byteBuffer.Append(static_cast<size_t>(1), encode_sequence_number_bytes[i]); - } - - // Append decode sequence number. - std::vector<uint8_t> decode_sequence_number_bytes = - UnsignedIntToBytes(decode_sequence_number_); - for (int i = 0; i < decode_sequence_number_bytes.size(); i++) { - byteBuffer.Append(static_cast<size_t>(1), decode_sequence_number_bytes[i]); - } - - // Append encode key. - byteBuffer = ByteBuffer::Concat(byteBuffer, encode_key_.data()); - - // Append decode key. - byteBuffer = ByteBuffer::Concat(byteBuffer, decode_key_.data()); - - return std::unique_ptr<std::string>(new std::string(byteBuffer.String())); -} - -// static. -std::unique_ptr<D2DConnectionContextV1> -D2DConnectionContextV1::FromSavedSession(const std::string& savedSessionInfo) { - ByteBuffer byteBuffer = ByteBuffer(savedSessionInfo); - - if (byteBuffer.size() != kSavedSessionLength) { - return nullptr; - } - - uint32_t encode_sequence_number = BytesToUnsignedInt( - byteBuffer.SubArray(kEncodeSequenceStart, kEncodeSequenceEnd)->Vector()); - uint32_t decode_sequence_number = BytesToUnsignedInt( - byteBuffer.SubArray(kDecodeSequenceStart, kDecodeSequenceEnd)->Vector()); - - const CryptoOps::SecretKey encode_key = - CryptoOps::SecretKey(*byteBuffer.SubArray(kEncodeKeyStart, kAesKeyLength), - CryptoOps::KeyAlgorithm::AES_256_KEY); - const CryptoOps::SecretKey decode_key = - CryptoOps::SecretKey(*byteBuffer.SubArray(kDecodeKeyStart, kAesKeyLength), - CryptoOps::KeyAlgorithm::AES_256_KEY); - - return std::unique_ptr<D2DConnectionContextV1>(new D2DConnectionContextV1( - encode_key, decode_key, encode_sequence_number, decode_sequence_number)); -} - -} // namespace securegcm |