blob: 4f2f7eadb4d13fa730ded2d1e0ad965289053a13 [file] [log] [blame]
// 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
//
// 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 THIRD_PARTY_TINK_EXPERIMENTAL_PQCRYPTO_CC_SUBTLE_CECPQ2_HKDF_RECIPIENT_KEM_BORINGSSL_H_
#define THIRD_PARTY_TINK_EXPERIMENTAL_PQCRYPTO_CC_SUBTLE_CECPQ2_HKDF_RECIPIENT_KEM_BORINGSSL_H_
#include "absl/strings/string_view.h"
#include "openssl/curve25519.h"
#include "openssl/ec.h"
#include "openssl/hrss.h"
#include "tink/internal/fips_utils.h"
#include "tink/subtle/common_enums.h"
#include "tink/util/secret_data.h"
#include "tink/util/statusor.h"
namespace crypto {
namespace tink {
namespace subtle {
// This class implements the CECPQ2 hybrid KEM from the recipient's perspective,
// using Boring SSL for the underlying cryptographic operations.
// This class is made generic enough so that extending the ECC algorithm to
// support other curves is trivial. As of now, the only supported curve is
// Curve25519.
//
// CECPQ2 combines both X25519 KEM and NTRU-HRSS KEM into a single hybrid KEM.
// The NTRU-HRSS is a structured lattice-based key encapsulation mechanism. It
// was originally proposed in [1] and submitted to the NIST Post-Quantum
// Cryptography standardization process [2].
//
// During the course of the NIST PQC standardization process, the NTRU-HRSS
// proposal merged with another proposal (NTRUEncrypt). The resulting scheme,
// simply called NTRU [3], is a 3rd round finalist of the NIST PQC
// standardization process.
//
// The implementation available in BoringSSL is based on [1] but it
// uses a different KEM construction based on [4]. Similar path has been taken
// by the NTRU team in the NIST competition which later adopted [4] as their
// QROM security proof approach. Note that the BoringSSL implementation is *not*
// compatible with the 3rd Round finalist NTRU running in the NIST Post-Quantum
// Cryptography standardization process [5].
//
// References:
// [1]: https://eprint.iacr.org/2017/667.pdf
// [2]: https://csrc.nist.gov/Projects/post-quantum-cryptography/
// [3]: https://ntru.org/
// [4]: https://eprint.iacr.org/2017/1005.pdf
// [5]: https://ntru.org/release/NIST-PQ-Submission-NTRU-20201016.tar.gz
class Cecpq2HkdfRecipientKemBoringSsl {
public:
// Constructs a recipient KEM for the specified curve, recipient's ECC
// private key, which must be a big-endian byte array, and recipient's HRSS
// private key. This method is made generic enough so that extending the ECC
// algorithm to support other curves is trivial.
static crypto::tink::util::StatusOr<
std::unique_ptr<Cecpq2HkdfRecipientKemBoringSsl>>
New(EllipticCurveType curve, util::SecretData ec_private_key,
util::SecretData hrss_private_key_seed);
virtual ~Cecpq2HkdfRecipientKemBoringSsl() = default;
// Computes the shared secret from the ECC private key and peer's ECC encoded
// public key, and the shared secret from the HRSS private key, then uses a
// hkdf to derive the symmetric key from the two shared secrets, hkdf info and
// hkdf salt. This method is made generic enough so that extending the ECC
// algorithm to support other curves is trivial.
virtual crypto::tink::util::StatusOr<util::SecretData> GenerateKey(
absl::string_view kem_bytes, HashType hash, absl::string_view hkdf_salt,
absl::string_view hkdf_info, uint32_t key_size_in_bytes,
EcPointFormat point_format) const = 0;
};
// Implementation of Cecpq2HkdfRecipientKemBoringSsl for Curve25519.
class Cecpq2HkdfX25519RecipientKemBoringSsl
: public Cecpq2HkdfRecipientKemBoringSsl {
public:
static constexpr crypto::tink::internal::FipsCompatibility kFipsStatus =
crypto::tink::internal::FipsCompatibility::kNotFips;
// Constructs a recipient CECPQ2 KEM for recipient's X25519 private key,
// which must be a big-endian byte array, and recipient's HRSS private key.
static crypto::tink::util::StatusOr<
std::unique_ptr<Cecpq2HkdfRecipientKemBoringSsl>>
New(EllipticCurveType curve, util::SecretData ec_private_key,
util::SecretData hrss_private_key_seed);
// Computes the shared secret from X25519 private key and peer's X25519
// encoded public key, and the shared secret from the HRSS private key, then
// uses a hkdf to derive the symmetric key from the two shared secrets, hkdf
// info and hkdf salt.
crypto::tink::util::StatusOr<util::SecretData> GenerateKey(
absl::string_view kem_bytes, HashType hash, absl::string_view hkdf_salt,
absl::string_view hkdf_info, uint32_t key_size_in_bytes,
EcPointFormat point_format) const override;
private:
// The private constructor only takes the X25519 and HRSS private keys and
// assign them to the class private members.
explicit Cecpq2HkdfX25519RecipientKemBoringSsl(
util::SecretData ec_private_key, util::SecretData hrss_private_key_seed)
: private_key_x25519_(std::move(ec_private_key)),
private_key_hrss_seed_(std::move(hrss_private_key_seed)) {}
// X25519 and HRSS private key containers
util::SecretData private_key_x25519_;
util::SecretData private_key_hrss_seed_;
};
} // namespace subtle
} // namespace tink
} // namespace crypto
#endif // THIRD_PARTY_TINK_EXPERIMENTAL_PQCRYPTO_CC_SUBTLE_CECPQ2_HKDF_RECIPIENT_KEM_BORINGSSL_H_