/*
 * 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.
 */

// Utility class to parse and verify raw {@link SecureMessage} protos.
// Verifies the signature on the message, and decrypts "signcrypted" messages
// (while simultaneously verifying the signature).
//
// @see RawSecureMessageBuilder

#include "securemessage/raw_secure_message_parser.h"

#include "securemessage/secure_message_wrapper.h"
#include "securemessage/util.h"

using std::unique_ptr;

namespace securemessage {

unique_ptr<string> RawSecureMessageParser::ParseSignedCleartextMessage(
    const string& signature,
    const string& header_and_body,
    const CryptoOps::Key& verification_key,
    CryptoOps::SigType sig_type,
    const string& associated_data) {

  // suppress_associated_data is always false signed cleartext
  if (VerifyHeaderAndBody(signature, header_and_body, verification_key,
                          sig_type, CryptoOps::EncType::NONE, associated_data,
                          false)) {
    return unique_ptr<string>(new string(header_and_body));
  } else {
    return nullptr;
  }
}

unique_ptr<string> RawSecureMessageParser::ParseSignCryptedMessage(
    const string& signature,
    const string& header_and_body,
    const CryptoOps::Key& verification_key,
    CryptoOps::SigType sig_type,
    const CryptoOps::SecretKey& decryption_key,
    CryptoOps::EncType enc_type,
    const string& associated_data) {
  if (enc_type == CryptoOps::EncType::NONE) {
    Util::LogError("Not a signcrypted message");
    return nullptr;
  }

  bool tagRequired = CryptoOps::TaggedPlaintextRequired(
      verification_key, sig_type, decryption_key);
  if (!VerifyHeaderAndBody(signature, header_and_body, verification_key,
                           sig_type, enc_type, associated_data, tagRequired)) {
    return nullptr;
  }

  unique_ptr<string> header =
      SecureMessageWrapper::ParseInternalHeader(header_and_body);
  unique_ptr<string> iv =
      SecureMessageWrapper::ParseHeaderIv(header_and_body);
  unique_ptr<string> body =
      SecureMessageWrapper::ParseBody(header_and_body);

  if (header == nullptr || iv == nullptr || body == nullptr) {
    Util::LogError("Header and body missing some fields");
    return nullptr;
  }

  unique_ptr<string> raw_decrypted_body =
      CryptoOps::Decrypt(decryption_key, enc_type, *iv, *body);

  if (raw_decrypted_body == nullptr) {
    Util::LogError("Failed to decrypt body");
    return nullptr;
  }

  if (!tagRequired) {
    // No tag expected, so we're all done
    return SecureMessageWrapper::BuildHeaderAndBody(*header,
                                                    *raw_decrypted_body);
  }

  // Verify the tag that binds the ciphertext to the header, and remove it
  bool binding_is_verified = false;
  unique_ptr<string> expected_tag =
      CryptoOps::Digest(*header + associated_data);
  if (expected_tag == nullptr) {
    Util::LogError("Error computing expected tag");
    return nullptr;
  }

  if (raw_decrypted_body->length() >= CryptoOps::kDigestLength) {
    unique_ptr<ByteBuffer> actual_tag =
        ByteBuffer(*raw_decrypted_body).SubArray(0, CryptoOps::kDigestLength);

    if (actual_tag != nullptr && actual_tag->Equals(ByteBuffer(*expected_tag))) {
      binding_is_verified = true;
    }
  }
  if (!binding_is_verified) {
    Util::LogError("Signature exception");
    return nullptr;
  }

  unsigned int body_len = static_cast<unsigned int>(raw_decrypted_body->size())
      - CryptoOps::kDigestLength;

  // Remove the tag.
  unique_ptr<ByteBuffer> body_bytes =
      ByteBuffer(*raw_decrypted_body).SubArray(CryptoOps::kDigestLength,
                                               body_len);

  if (body_bytes == nullptr) {
    Util::LogError("Invalid body length");
    return nullptr;
  }

  return SecureMessageWrapper::BuildHeaderAndBody(*header,
                                                  body_bytes->String());
}

bool RawSecureMessageParser::VerifyHeaderAndBody(
    const string& signature,
    const string& header_and_body,
    const CryptoOps::Key& verification_key,
    CryptoOps::SigType sig_type,
    CryptoOps::EncType enc_type,
    const string& associated_data,
    bool suppress_associated_data /* in case it is in the tag instead */) {

  string signed_data = header_and_body;
  if (!suppress_associated_data) {
    signed_data.append(associated_data);
  }
  bool verified =
      CryptoOps::Verify(sig_type, verification_key, signature, signed_data);

  unique_ptr<string> header =
      SecureMessageWrapper::ParseHeader(header_and_body);

  if (header == nullptr) {
    Util::LogError("message must have header");
    return nullptr;
  }

  // Does not return early in order to avoid timing attacks
  verified &= SecureMessageWrapper::GetSigScheme(sig_type) ==
              SecureMessageWrapper::GetSignatureScheme(*header);
  verified &= SecureMessageWrapper::GetEncScheme(enc_type) ==
              SecureMessageWrapper::GetEncryptionScheme(*header);
  verified &= associated_data.length() ==
              SecureMessageWrapper::GetAssociatedDataLength(*header);

  // Check that either a decryption operation is expected, or no DecryptionKeyId
  // is set.
  verified &= enc_type != CryptoOps::EncType::NONE ||
              !SecureMessageWrapper::HasDecryptionKeyId(*header);

  // If encryption was used, check that either we are not using a public key
  // signature or a VerificationKeyId was set (as is required for public key
  // based signature + encryption).
  verified &= enc_type != CryptoOps::EncType::NONE ||
              CryptoOps::IsPublicKeyScheme(sig_type) ||
              !SecureMessageWrapper::HasVerificationKeyId(*header);

  return verified;
}

// Constructor and Destructor are never used
RawSecureMessageParser::RawSecureMessageParser() {}
RawSecureMessageParser::~RawSecureMessageParser() {}

}  // namespace securemessage
