blob: 943e28042cc270a9a8d33fc41bee578d0dac3fc7 [file] [log] [blame]
/*
* 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_