/*
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * 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
 *
 *     http://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 SECUREMESSAGE_SECURE_MESSAGE_BUILDER_H_
#define SECUREMESSAGE_SECURE_MESSAGE_BUILDER_H_

#include <memory>

#include "securemessage.pb.h"

#include "securemessage/byte_buffer.h"
#include "securemessage/common.h"
#include "securemessage/crypto_ops.h"

namespace securemessage {

//
// Builder for {@link SecureMessage} protos. Can be used to create either signed
// messages, or "signcrypted" (encrypted then signed) messages that include a
// tight binding between the ciphertext portion and a verification key identity.
//
// All the language non-specific work is done from within the
// {@link RawSecureMessageBuilder} class.
//
// @see SecureMessageParser
// @see RawSecureMessageBuilder
//
class SecureMessageBuilder {
 public:
  SecureMessageBuilder();

  virtual ~SecureMessageBuilder();

  //
  // Resets this {@link SecureMessageBuilder} instance to a blank configuration
  // (and returns it).
  //
  SecureMessageBuilder* Reset();

  //
  // Optional metadata to be sent along with the header information in this
  // {@link SecureMessage}.
  // <p>
  // Note that this value will be sent <em>UNENCRYPTED</em> in all cases.
  // <p>
  // Can be used with either cleartext or signcrypted messages, but is intended
  // primarily for use with signcrypted messages.
  //
  SecureMessageBuilder* SetPublicMetadata(const string& public_metadata);

  //
  // The recipient of the {@link SecureMessage} should be able to uniquely
  // determine the correct verification key, given only this value.
  // <p>
  // Can be used with either cleartext or signcrypted messages. Setting this is
  // mandatory for signcrypted messages using a public key CryptoOps::SigType,
  // in order to bind the encrypted body to a specific verification key.
  // <p>
  // Note that this value is sent <em>UNENCRYPTED</em> in all cases.
  //
  SecureMessageBuilder* SetVerificationKeyId(const string& verification_key_id);

  //
  // To be used only with {@link #BuildSignCryptedMessage(CryptoOps::Key,
  // CryptoOps::SigType, CryptoOps::Key, CryptoOps::EncType, string)},
  // this value is sent <em>UNENCRYPTED</em> as part of the header. It should be
  // used by the recipient of the {@link SecureMessage} to identify an
  // appropriate key to use for decrypting the message body.
  //
  SecureMessageBuilder* SetDecryptionKeyId(const string& decryption_key_id);

  //
  // Additional data is "associated" with this {@link SecureMessage}, but will
  // not be sent as part of it. The recipient of the {@link SecureMessage} will
  // need to provide the same data in order to verify the message body. Setting
  // this to {@code null} is equivalent to using an empty array (unlike the
  // behavior of {@code VerificationKeyId} and {@code DecryptionKeyId}).
  // <p>
  // Note that the <em>size</em> (length in bytes) of the associated data will
  // be sent in the <em>UNENCRYPTED</em> header information, even if you are
  // using encryption.
  // <p>
  // If you will be using {@link #BuildSignedCleartextMessage(CryptoOps::Key,
  // CryptoOps::SigType, string)}, then anyone observing the
  // {@link SecureMessage} may be able to infer this associated data via an
  // "offline dictionary attack". That is, when no encryption is used, you will
  // not be hiding this data simply because it is not being sent over the wire.
  //
  SecureMessageBuilder* SetAssociatedData(const string& associated_data);

  //
  // Generates a signed {@link SecureMessage} with the payload {@code body} left
  // <em>UNENCRYPTED</em>.
  // <p>
  // Note that if you have used {@link #SetAssociatedData(string)}, the
  // associated data will
  // be subject to offline dictionary attacks if you use a public key {@link
  // CryptoOps::SigType}.
  // <p>
  // Doesn't currently support symmetric keys stored in a TPM
  // <p>
  // Can return nullptr on error
  //
  // @see SecureMessageParser#ParseSignedCleartextMessage
  //
  std::unique_ptr<SecureMessage> BuildSignedCleartextMessage(
      const CryptoOps::Key& signing_key, CryptoOps::SigType sig_type,
      const string& body);

  //
  // Generates a signed and encrypted {@link SecureMessage}. If the signature
  // type requires a public key, such as with ECDSA_P256_SHA256, then the caller
  // <em>must</em> set a verification id using the
  // {@link #SetVerificationKeyId(string)} method. The verification key
  // id will be bound to the encrypted {@code body}, preventing attacks that
  // involve stripping the signature and then re-signing the encrypted
  // {@code body} as if it was originally sent by the attacker.
  //
  // <p> It is safe to re-use one {@link SecretKey} as both
  // {@code signingKey} and {@code encryptionKey}, even if that key is also used
  // for {@link #buildSignedCleartextMessage(Key, SigType, byte[])}. In fact,
  // the resulting output encoding will be more compact when the same symmetric
  // key is used for both.
  //
  // <p> Note that PublicMetadata and other header fields are left
  // <em>UNENCRYPTED</em>.
  //
  // <p> Doesn't currently support symmetric keys stored in a TPM
  //
  // <p> Can return nullptr on error
  //
  // @param encType <em>must not</em> be set to {@link EncType#NONE}
  // @see SecureMessageParser#parseSignCryptedMessage(SecureMessage,
  //      CryptoOps::Key, CryptoOps::SigType, CryptoOps::Key,
  // CryptoOps::EncType)
  //
  std::unique_ptr<SecureMessage> BuildSignCryptedMessage(
      const CryptoOps::Key& signing_key, CryptoOps::SigType sig_type,
      const CryptoOps::SecretKey& encryption_key, CryptoOps::EncType enc_type,
      const string& body);

 private:
  std::unique_ptr<ByteBuffer> public_metadata_;
  std::unique_ptr<ByteBuffer> decryption_key_id_;
  std::unique_ptr<ByteBuffer> verification_key_id_;
  std::unique_ptr<ByteBuffer> associated_data_;

  // @param iv IV or {@code null} if IV to be left unset in the Header
  std::unique_ptr<Header> BuildHeader(CryptoOps::SigType sig_type,
                                      CryptoOps::EncType enc_type,
                                      const std::unique_ptr<string>& iv);

  ByteBuffer SerializeHeaderAndBody(const string& header, const string& body);

  std::unique_ptr<SecureMessage> CreateSignedResult(
      const CryptoOps::Key& signing_key, const CryptoOps::SigType& sig_type,
      const ByteBuffer& header_and_body, const ByteBuffer& associated_data);
};

}  // namespace securemessage
#endif  // SECUREMESSAGE_SECURE_MESSAGE_BUILDER_H_
