Symlink ukey2 headers

This commit is contained in:
deling-google
2022-03-31 14:50:34 -07:00
parent 739cde0832
commit 47d07ea29f
5 changed files with 1 additions and 487 deletions
+1
View File
@@ -0,0 +1 @@
../ukey2/src/main/cpp/include/securegcm
@@ -1,89 +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.
#ifndef SECURITY_CRYPTAUTH_LIB_SECUREGCM_D2D_CONNECTION_CONTEXT_V1_H_
#define SECURITY_CRYPTAUTH_LIB_SECUREGCM_D2D_CONNECTION_CONTEXT_V1_H_
#include <memory>
#include <string>
#include "securemessage/crypto_ops.h"
namespace securegcm {
// The full context of a secure connection. This class has methods to encode and
// decode messages that are to be sent to another device.
//
// This class should be kept compatible with the Java implementation in
// java/com/google/security/cryptauth/lib/securegcm/D2DConnectionContextV1.java
class D2DConnectionContextV1 {
public:
D2DConnectionContextV1(const securemessage::CryptoOps::SecretKey& encode_key,
const securemessage::CryptoOps::SecretKey& decode_key,
uint32_t encode_sequence_number,
uint32_t decode_sequence_number);
// Once the initiator and responder have negotiated a secret key, use this
// method to encrypt and sign |payload|. Both initiator and responder devices
// can use this message.
//
// On failure, nullptr is returned.
std::unique_ptr<string> EncodeMessageToPeer(const string& payload);
// Once the initiator and responder have negotiated a secret key, use this
// method to decrypt and verify a |message| received from the other device.
// Both initiator and responder devices can use this message.
//
// On failure, nullptr is returned.
std::unique_ptr<string> DecodeMessageFromPeer(const string& message);
// Returns a cryptographic digest (SHA256) of the session keys prepended by
// the SHA256 hash of the ASCII string "D2D".
//
// On failure, nullptr is returned.
std::unique_ptr<string> GetSessionUnique();
// Creates a saved session that can be later used for resumption. Note,
// this must be stored in a secure location.
std::unique_ptr<string> SaveSession();
// Parse a saved session info and attempt to construct a resumed context.
//
// The session info passed to this method should be one that was generated
// by |SaveSession|.
//
// On failure, nullptr is returned.
static std::unique_ptr<D2DConnectionContextV1> FromSavedSession(
const string& savedSessionInfo);
private:
// The key used to encode payloads.
const securemessage::CryptoOps::SecretKey encode_key_;
// The key used to decode received messages.
const securemessage::CryptoOps::SecretKey decode_key_;
// The current sequence number for encoding.
uint32_t encode_sequence_number_;
// The current sequence number for decoding.
uint32_t decode_sequence_number_;
// A friend to access private variables for testing.
friend class D2DConnectionContextV1Peer;
};
} // namespace securegcm
#endif // SECURITY_CRYPTAUTH_LIB_SECUREGCM_D2D_CONNECTION_CONTEXT_V1_H_
-78
View File
@@ -1,78 +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.
#ifndef SECURITY_CRYPTAUTH_LIB_SECUREGCM_D2D_CRYPTO_OPS_H_
#define SECURITY_CRYPTAUTH_LIB_SECUREGCM_D2D_CRYPTO_OPS_H_
#include <memory>
#include <string>
#include "proto/securegcm.pb.h"
#include "securemessage/crypto_ops.h"
namespace securegcm {
// A collection of static utility methods for the Device to Device communication
// (D2D) library.
//
// A class is used here in preference to a namespace to provide a closer
// correspondence with the Java equivalent class:
// //java/com/google/security/cryptauth/lib/securegcm/D2DCryptoOps.java
class D2DCryptoOps {
public:
// Encapsulates a payload type specifier, and a corresponding message as the
// raw payload.
//
// Note: Type is defined in securegcm.proto.
class Payload {
public:
Payload(Type type, const std::string& message);
Type type() const { return type_; }
const std::string& message() const { return message_; }
private:
const Type type_;
const std::string message_;
};
// The salt, SHA256 of "D2D".
static const uint8_t kSalt[];
static const size_t kSaltLength;
// Used by a device to send a secure |Payload| to another device.
static std::unique_ptr<std::string> SigncryptPayload(
const Payload& payload,
const securemessage::CryptoOps::SecretKey& secret_key);
// Used by a device to recover a secure |Payload| sent by another device.
static std::unique_ptr<Payload> VerifyDecryptPayload(
const std::string& signcrypted_message,
const securemessage::CryptoOps::SecretKey& secret_key);
// Used to derive a distinct key for each initiator and responder from the
// |master_key|. Use a different |purpose| for each role.
static std::unique_ptr<securemessage::CryptoOps::SecretKey>
DeriveNewKeyForPurpose(const securemessage::CryptoOps::SecretKey& master_key,
const std::string& purpose);
private:
// Prevent instantiation.
D2DCryptoOps();
};
} // namespace securegcm
#endif // SECURITY_CRYPTAUTH_LIB_SECUREGCM_D2D_CRYPTO_OPS_H_
-57
View File
@@ -1,57 +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.
// Utility functions for Java-compatible operations.
#ifndef SECURITY_CRYPTAUTH_LIB_SECUREGCM_JAVA_UTIL_H_
#define SECURITY_CRYPTAUTH_LIB_SECUREGCM_JAVA_UTIL_H_
#include "securemessage/byte_buffer.h"
namespace securegcm {
namespace java_util {
// Perform multiplication with Java overflow semantics
// (https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html):
// If an integer multiplication overflows, then the result is the low-order
// bits of the mathematical product as represented in some sufficiently
// large two's-complement format.
int32_t JavaMultiply(int32_t lhs, int32_t rhs);
// Perform addition with Java overflow semantics:
// (https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html):
// If an integer addition overflows, then the result is the low-order bits of
// the mathematical sum as represented in some sufficiently large
// two's-complement format.
int32_t JavaAdd(int32_t lhs, int32_t rhs);
// To be compatible with the Java implementation, we need to use the same
// algorithm as the Arrays#hashCode(byte[]) function in Java:
// "The value returned by this method is the same value that would be obtained
// by invoking the hashCode method on a List containing a sequence of Byte
// instances representing the elements of a in the same order."
//
// According to List#hashCode(), this algorithm is:
// int hashCode = 1;
// for (Byte b : list) {
// hashCode = 31 * hashCode + (b == null ? b : b.hashCode());
// }
//
// Finally, Byte#hashCode() is defined as "equal to the result of invoking
// Byte#intValue()".
int32_t JavaHashCode(const securemessage::ByteBuffer& byte_buffer);
} // namespace java_util
} // namespace securegcm
#endif // SECURITY_CRYPTAUTH_LIB_SECUREGCM_JAVA_UTIL_H_
-263
View File
@@ -1,263 +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.
#ifndef SECURITY_CRYPTAUTH_LIB_SECUREGCM_UKEY2_HANDSHAKE_H_
#define SECURITY_CRYPTAUTH_LIB_SECUREGCM_UKEY2_HANDSHAKE_H_
#include <map>
#include <memory>
#include "proto/ukey.pb.h"
#include "securegcm/d2d_connection_context_v1.h"
#include "securemessage/crypto_ops.h"
namespace securegcm {
// Implements UKEY2 and produces a |D2DConnectionContextV1|.
// This class should be kept compatible with the Java implementation in
// //java/com/google/security/cryptauth/lib/securegcm/Ukey2Handshake.java
//
// For usage examples, see ukey2_shell.cc. This file contains a shell exercising
// both the initiator and responder handshake roles.
class UKey2Handshake {
public:
// Handshake states:
// kInProgress:
// The handshake is in progress, caller should use
// |GetNextHandshakeMessage()| and |ParseHandshakeMessage()| to continue
// the handshake.
//
// kVerificationNeeded:
// The handshake is complete, but pending verification of the
// authentication string. Clients should use |GetVerificationString()|
// to get the verification string and use out-of-band methods to
// authenticate the handshake.
//
// kVerificationInProgress:
// The handshake is complete, verification string has been generated,
// but has not been confirmed. After authenticating the handshake
// out-of-band, use |VerifyHandshake()| to mark the handshake as
// verified.
//
// kFinished:
// The handshake is finished, and the caller can use
// |ToConnectionContext()| to produce a |D2DConnectionContextV1|.
//
// kAlreadyUsed:
// The hanshake has already been used and should be destroyed.
//
// kError:
// The handshake produced an error and should be destroyed.
enum class State {
kInProgress,
kVerificationNeeded,
kVerificationInProgress,
kFinished,
kAlreadyUsed,
kError,
};
// Currently implemented UKEY2 handshake ciphers. Each cipher is a tuple
// consisting of a key negotiation cipher and a hash function used for a
// commitment. Currently the ciphers are:
// +-----------------------------------------------------+
// | Enum | Key negotiation | Hash function |
// +-------------+-----------------------+---------------+
// | P256_SHA512 | ECDH using NIST P-256 | SHA512 |
// +-----------------------------------------------------+
//
// Note that these should correspond to values in
// device_to_device_messages.proto.
enum class HandshakeCipher : int {
// TODO(aczeskis): add CURVE25519_SHA512
P256_SHA512 = securegcm::P256_SHA512,
};
// Creates a |UKey2Handshake| with a particular |cipher| that can be used by
// an initiator / client.
static std::unique_ptr<UKey2Handshake> ForInitiator(HandshakeCipher cipher);
// Creates a |UKey2Handshake| with a particular |cipher| that can be used by
// a responder / server.
static std::unique_ptr<UKey2Handshake> ForResponder(HandshakeCipher cipher);
// Returns the current state of the handshake.
State GetHandshakeState() const;
// Returns the last error message. Empty string if there was no error.
const string& GetLastError() const;
// Gets the next handshake message suitable for sending on the wire.
// If |nullptr| is returned, check |GetLastError()| for the error message.
std::unique_ptr<string> GetNextHandshakeMessage();
// Parses the given |handshake_message|, updating the internal state.
struct ParseResult {
// True if |handshake_message| is parsed successfully. If |false|, call
// |GetLastError()| for the error message.
bool success;
// May be set if parsing fails. This value should be sent to the remote
// device before disconnecting.
std::unique_ptr<string> alert_to_send;
};
ParseResult ParseHandshakeMessage(const string& handshake_message);
// Returns an authentication string suitable for authenticating the handshake
// out-of-band. Note that the authentication string can be short (e.g., a 6
// digit visual confirmation code).
//
// Note: This should only be called when the state returned from
// |GetHandshakeState()| is |State::VERIFICATION_NEEDED|, which means this can
// only be called once.
//
// |byte_length|: The length of the output. Min length is 1; max length is 32.
// If |nullptr| is returned, check |GetLastError()| for the error message.
std::unique_ptr<string> GetVerificationString(int byte_length);
// Invoked to let the handshake state machine know that caller has validated
// the authentication string obtained via |GetVerificationString()|.
// Note: This should only be called when the state returned by
// |GetHandshakeState()| is |State::VERIFICATION_IN_PROGRESS|.
//
// If |false| is returned, check |GetLastError()| for the error message.
bool VerifyHandshake();
// Can be called to generate a |D2DConnectionContextV1|. Returns nullptr on
// failure.
// Note: This should only be called when the state returned by
// |GetHandshakeState()| is |State::FINISHED|.
//
// If |nullptr| is returned, check |GetLastError()| for the error message.
std::unique_ptr<D2DConnectionContextV1> ToConnectionContext();
private:
// Enums for internal state machinery.
enum class InternalState : int {
CLIENT_START,
CLIENT_WAITING_FOR_SERVER_INIT,
CLIENT_AFTER_SERVER_INIT,
// Responder/server state
SERVER_START,
SERVER_AFTER_CLIENT_INIT,
SERVER_WAITING_FOR_CLIENT_FINISHED,
// Common completion state
HANDSHAKE_VERIFICATION_NEEDED,
HANDSHAKE_VERIFICATION_IN_PROGRESS,
HANDSHAKE_FINISHED,
HANDSHAKE_ALREADY_USED,
HANDSHAKE_ERROR,
};
// Helps us remember our role in the handshake.
enum class HandshakeRole {
CLIENT,
SERVER
};
// Prevent public instantiation. Callers should use |ForInitiator()| or
// |ForResponder()|.
UKey2Handshake(InternalState state, HandshakeCipher cipher);
// Attempts to parse Ukey2ClientInit, wrapped inside a Ukey2Message.
// See go/ukey2 for details.
ParseResult ParseClientInitUkey2Message(const string& handshake_message);
// Attempts to parse Ukey2ServerInit, wrapped inside a Ukey2Message.
// See go/ukey2 for details.
ParseResult ParseServerInitUkey2Message(const string& handshake_message);
// Attempts to parse Ukey2ClientFinish, wrapped inside a Ukey2Message.
// See go/ukey2 for details.
ParseResult ParseClientFinishUkey2Message(const string& handshake_message);
// Convenience function to set |last_error_| and create a ParseResult with a
// given alert.
ParseResult CreateFailedResultWithAlert(Ukey2Alert::AlertType alert_type,
const string& error_message);
// Convenience function to set |last_error_| and create a failed ParseResult
// without an alert.
ParseResult CreateFailedResultWithoutAlert(const string& error_message);
// Convenience function to create a successful ParseResult.
ParseResult CreateSuccessResult();
// Verifies that the peer's commitment stored in |peer_commitment_| is the
// same as that obtained from |handshake_message|.
bool VerifyCommitment(const string& handshake_message);
// Generates a commitment for the P256_SHA512 cipher.
std::unique_ptr<Ukey2ClientInit::CipherCommitment>
GenerateP256Sha512Commitment();
// Creates a serialized Ukey2Message, wrapping an inner ClientInit message.
std::unique_ptr<string> MakeClientInitUkey2Message();
// Creates a serialized Ukey2Message, wrapping an inner ServerInit message.
std::unique_ptr<string> MakeServerInitUkey2Message();
// Creates a serialized Ukey2Message of a given |type|, wrapping |data|.
std::unique_ptr<string> MakeUkey2Message(Ukey2Message::Type type,
const string& data);
// Called when an error occurs to set |handshake_state_| and |last_error_|.
void SetError(const string& error_message);
// The current state of the handshake.
InternalState handshake_state_;
// The cipher to use for the handshake.
const HandshakeCipher handshake_cipher_;
// The role to perform, i.e. client or server.
const HandshakeRole handshake_role_;
// A newly generated key-pair for this handshake.
std::unique_ptr<securemessage::CryptoOps::KeyPair> our_key_pair_;
// The peer's public key retrieved from a handshake message.
std::unique_ptr<securemessage::CryptoOps::PublicKey> their_public_key_;
// The secret key derived from |our_key_pair_| and |their_public_key_|.
std::unique_ptr<securemessage::CryptoOps::SecretKey> derived_secret_key_;
// The raw bytes of the Ukey2ClientInit, wrapped inside a Ukey2Message.
// Empty string if not initialized.
string wrapped_client_init_;
// The raw bytes of the Ukey2ServerInit, wrapped inside a Ukey2Message.
// Empty string if not initialized.
string wrapped_server_init_;
// The commitment of the peer retrieved from a handshake message. Empty string
// if not initialized.
string peer_commitment_;
// Map from ciphers to the raw bytes of message 3 (which is a wrapped
// Ukey2ClientFinished message).
// Note: Currently only one cipher is supported, so at most one entry exists
// in this map.
std::map<HandshakeCipher, string> raw_message3_map_;
// Contains the last error message.
string last_error_;
};
} // namespace securegcm
#endif // SECURITY_CRYPTAUTH_LIB_SECUREGCM_UKEY2_HANDSHAKE_H_