blob: 621652a6a539950decbbf7e363a16cca8636f939 [file] [log] [blame]
// Copyright 2021 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 TINK_INTERNAL_EC_UTIL_H_
#define TINK_INTERNAL_EC_UTIL_H_
#include <stdint.h>
#include <memory>
#include <string>
#include "absl/strings/string_view.h"
#include "openssl/ec.h"
#include "tink/internal/ssl_unique_ptr.h"
#include "tink/subtle/common_enums.h"
#include "tink/util/secret_data.h"
#include "tink/util/statusor.h"
namespace crypto {
namespace tink {
namespace internal {
constexpr int64_t X25519KeyPubKeySize() { return 32; }
constexpr int64_t X25519KeyPrivKeySize() { return 32; }
constexpr int64_t X25519KeySharedKeySize() { return 32; }
constexpr int64_t Ed25519KeyPubKeySize() { return 32; }
constexpr int64_t Ed25519KeyPrivKeySize() { return 32; }
struct EcKey {
subtle::EllipticCurveType curve;
// Affine coordinates in bigendian representation.
std::string pub_x;
std::string pub_y;
// Big integer in bigendian representation.
crypto::tink::util::SecretData priv;
};
struct X25519Key {
uint8_t public_value[X25519KeyPubKeySize()];
uint8_t private_key[X25519KeyPrivKeySize()];
};
struct Ed25519Key {
std::string public_key;
std::string private_key;
};
// EcKey.
// Returns a new EC key for the specified curve.
crypto::tink::util::StatusOr<EcKey> NewEcKey(
crypto::tink::subtle::EllipticCurveType curve_type);
// Returns a new EC key for the specified curve derived from a secret seed.
crypto::tink::util::StatusOr<EcKey> NewEcKey(
crypto::tink::subtle::EllipticCurveType curve_type,
const crypto::tink::util::SecretData &secret_seed);
// X25519Key Utils.
// Returns a new X25519Key key. It returns a kInternal error status if the
// OpenSSL/BoringSSL APIs fail.
crypto::tink::util::StatusOr<std::unique_ptr<X25519Key>> NewX25519Key();
// Returns a X25519Key matching the specified EcKey.
crypto::tink::util::StatusOr<std::unique_ptr<X25519Key>> X25519KeyFromEcKey(
const EcKey &ec_key);
// Returns an EcKey matching the specified X25519Key.
EcKey EcKeyFromX25519Key(const X25519Key *x25519_key);
// Given an OpenSSL/BoringSSL key EC_KEY `key` and curve type `curve` return an
// EcKey.
util::StatusOr<EcKey> EcKeyFromSslEcKey(
crypto::tink::subtle::EllipticCurveType curve, const EC_KEY &key);
// Generates a shared secret using `private_key` and `peer_public_key`; keys
// must be X25519 keys otherwise an error is returned.
crypto::tink::util::StatusOr<util::SecretData> ComputeX25519SharedSecret(
EVP_PKEY *private_key, EVP_PKEY *peer_public_key);
// Computes the corresponding public+private key for the supplied private key.
crypto::tink::util::StatusOr<std::unique_ptr<X25519Key>>
X25519KeyFromPrivateKey(const crypto::tink::util::SecretData &private_key);
// Ed25519Key Utils.
// Returns a new ED25519 key.
crypto::tink::util::StatusOr<std::unique_ptr<Ed25519Key>> NewEd25519Key();
// Returns a new ED25519 key generated from a 32-byte secret seed.
crypto::tink::util::StatusOr<std::unique_ptr<Ed25519Key>> NewEd25519Key(
const crypto::tink::util::SecretData &secret_seed);
// EC_POINT Encode/Decode.
// Given x, y as curve_size_in_bytes big-endian byte array, encoding is as
// follows:
// - The uncompressed point is encoded as 0x04 || x || y.
// - The compressed point is encoded as:
// - 0x03 || x if the least significant bit of y is 1;
// - 0x02 || x otherwise.
// Returns OpenSSL/BoringSSL's EC_POINT constructed from curve type
// `curve_type`, point `format` and encoded public key's point `encoded_point`.
crypto::tink::util::StatusOr<SslUniquePtr<EC_POINT>> EcPointDecode(
crypto::tink::subtle::EllipticCurveType curve_type,
crypto::tink::subtle::EcPointFormat format,
absl::string_view encoded_point);
// Returns the encoded public key based on curve type `curve_type`, point
// `format` and OpenSSL/BoringSSL's EC_POINT public key `point`.
crypto::tink::util::StatusOr<std::string> EcPointEncode(
crypto::tink::subtle::EllipticCurveType curve_type,
crypto::tink::subtle::EcPointFormat format, const EC_POINT *point);
// Returns the encoding size of a point on the specified elliptic curve
// `curve_type` when the given point `format` is used.
util::StatusOr<int32_t> EcPointEncodingSizeInBytes(
crypto::tink::subtle::EllipticCurveType curve_type,
crypto::tink::subtle::EcPointFormat format);
// Returns the size (in bytes) of an element of the field over which
// the curve `curve_type` is defined.
util::StatusOr<int32_t> EcFieldSizeInBytes(
crypto::tink::subtle::EllipticCurveType curve_type);
// EC_GROUP Utils.
// Returns OpenSSL/BoringSSL's EC_GROUP constructed from the given `curve_type`.
crypto::tink::util::StatusOr<SslUniquePtr<EC_GROUP>> EcGroupFromCurveType(
crypto::tink::subtle::EllipticCurveType curve_type);
// Returns the curve type associated with the given `group`.
crypto::tink::util::StatusOr<crypto::tink::subtle::EllipticCurveType>
CurveTypeFromEcGroup(const EC_GROUP *group);
// Returns OpenSSL/BoringSSL's EC_POINT constructed from the curve type,
// big-endian representation of public key's x-coordinate and y-coordinate.
crypto::tink::util::StatusOr<SslUniquePtr<EC_POINT>> GetEcPoint(
crypto::tink::subtle::EllipticCurveType curve, absl::string_view pubx,
absl::string_view puby);
// Transforms ECDSA IEEE_P1363 signature encoding to DER encoding.
//
// The IEEE_P1363 signature's format is r || s, where r and s are zero-padded
// and have the same size in bytes as the order of the curve. For example, for
// NIST P-256 curve, r and s are zero-padded to 32 bytes.
//
// The DER signature is encoded using ASN.1
// (https://tools.ietf.org/html/rfc5480#appendix-A):
// ECDSA-Sig-Value :: = SEQUENCE { r INTEGER, s INTEGER }.
// In particular, the encoding is:
// 0x30 || totalLength || 0x02 || r's length || r || 0x02 || s's length || s
util::StatusOr<std::string> EcSignatureIeeeToDer(const EC_GROUP *group,
absl::string_view ieee_sig);
// Returns the ECDH's shared secret between two peers A and B using A's private
// key `priv_key` and B's public key `pub_key`. Returns error if `pub_key`
// is not on `priv_key`'s curve `curve`.
util::StatusOr<util::SecretData> ComputeEcdhSharedSecret(
crypto::tink::subtle::EllipticCurveType curve, const BIGNUM *priv_key,
const EC_POINT *pub_key);
} // namespace internal
} // namespace tink
} // namespace crypto
#endif // TINK_INTERNAL_EC_UTIL_H_