aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--news.rst5
-rw-r--r--src/cli/speed.cpp4
-rw-r--r--src/lib/prov/bearssl/bearssl_ec.cpp4
-rw-r--r--src/lib/prov/openssl/openssl_ec.cpp4
-rw-r--r--src/lib/prov/pkcs11/p11_ecc_key.cpp2
-rw-r--r--src/lib/prov/pkcs11/p11_ecdh.h2
-rw-r--r--src/lib/pubkey/ec_group/ec_group.cpp2
-rw-r--r--src/lib/pubkey/ec_group/point_gfp.cpp48
-rw-r--r--src/lib/pubkey/ec_group/point_gfp.h29
-rw-r--r--src/lib/pubkey/ecc_key/ecc_key.cpp12
-rw-r--r--src/lib/pubkey/ecc_key/ecc_key.h14
-rw-r--r--src/lib/pubkey/ecdh/ecdh.h6
-rw-r--r--src/lib/pubkey/ecies/ecies.cpp5
-rw-r--r--src/tests/test_ecies.cpp3
-rw-r--r--src/tests/test_pkcs11_high_level.cpp33
-rw-r--r--src/tests/unit_ecc.cpp16
-rw-r--r--src/tests/unit_ecdsa.cpp53
17 files changed, 166 insertions, 76 deletions
diff --git a/news.rst b/news.rst
index f958c72d0..df99382d1 100644
--- a/news.rst
+++ b/news.rst
@@ -26,6 +26,11 @@ Version 2.5.0, Not Yet Released
* Add support for POWER8 AES instructions (GH #1459 #1393 #1206)
+* The default encoding of ECC public keys has changed from compressed
+ to uncompressed point representation. This improves compatability with
+ some common software packages including Golang's standard library.
+ (GH #1480)
+
* Change DL_Group and EC_Group to store their data as shared_ptr for
fast copying. Also both classes precompute additional useful values
(eg for modular reductions). (GH #1435 #1454)
diff --git a/src/cli/speed.cpp b/src/cli/speed.cpp
index a991633e7..fb47581eb 100644
--- a/src/cli/speed.cpp
+++ b/src/cli/speed.cpp
@@ -1344,8 +1344,8 @@ class Speed final : public Command
{
const Botan::BigInt k(rng(), 256);
const Botan::PointGFp p = group.get_base_point() * k;
- const Botan::secure_vector<uint8_t> os_cmp = Botan::EC2OSP(p, Botan::PointGFp::COMPRESSED);
- const Botan::secure_vector<uint8_t> os_uncmp = Botan::EC2OSP(p, Botan::PointGFp::UNCOMPRESSED);
+ const std::vector<uint8_t> os_cmp = p.encode(Botan::PointGFp::COMPRESSED);
+ const std::vector<uint8_t> os_uncmp = p.encode(Botan::PointGFp::UNCOMPRESSED);
uncmp_timer->run([&]() { group.OS2ECP(os_uncmp); });
cmp_timer->run([&]() { group.OS2ECP(os_cmp); });
diff --git a/src/lib/prov/bearssl/bearssl_ec.cpp b/src/lib/prov/bearssl/bearssl_ec.cpp
index 29ff1b5ad..23f566043 100644
--- a/src/lib/prov/bearssl/bearssl_ec.cpp
+++ b/src/lib/prov/bearssl/bearssl_ec.cpp
@@ -92,7 +92,7 @@ class BearSSL_ECDSA_Verification_Operation final : public PK_Ops::Verification
if (m_hf == nullptr)
throw Lookup_Error("BearSSL ECDSA does not support hash " + req.arg(0));
- m_q_buf = EC2OSP(ecdsa.public_point(), PointGFp::UNCOMPRESSED);
+ m_q_buf = ecdsa.public_point().encode(PointGFp::UNCOMPRESSED);
m_key.qlen = m_q_buf.size();
m_key.q = m_q_buf.data();
@@ -123,7 +123,7 @@ class BearSSL_ECDSA_Verification_Operation final : public PK_Ops::Verification
private:
br_ec_public_key m_key;
std::unique_ptr<HashFunction> m_hf;
- secure_vector<uint8_t> m_q_buf;
+ std::vector<uint8_t> m_q_buf;
const br_hash_class *m_hash;
size_t m_order_bits;
};
diff --git a/src/lib/prov/openssl/openssl_ec.cpp b/src/lib/prov/openssl/openssl_ec.cpp
index 90b5e2023..c61f83d02 100644
--- a/src/lib/prov/openssl/openssl_ec.cpp
+++ b/src/lib/prov/openssl/openssl_ec.cpp
@@ -56,7 +56,7 @@ secure_vector<uint8_t> PKCS8_for_openssl(const EC_PrivateKey& ec)
.raw_bytes(ec.domain().DER_encode(EC_DOMPAR_ENC_OID))
.end_cons()
.start_cons(ASN1_Tag(1), PRIVATE)
- .encode(EC2OSP(pub_key, PointGFp::UNCOMPRESSED), BIT_STRING)
+ .encode(pub_key.encode(PointGFp::UNCOMPRESSED), BIT_STRING)
.end_cons()
.end_cons()
.get_contents();
@@ -147,7 +147,7 @@ class OpenSSL_ECDSA_Verification_Operation final : public PK_Ops::Verification_w
if(!::EC_KEY_set_group(m_ossl_ec.get(), grp.get()))
throw OpenSSL_Error("EC_KEY_set_group");
- const secure_vector<uint8_t> enc = EC2OSP(ecdsa.public_point(), PointGFp::UNCOMPRESSED);
+ const std::vector<uint8_t> enc = ecdsa.public_point().encode(PointGFp::UNCOMPRESSED);
const uint8_t* enc_ptr = enc.data();
EC_KEY* key_ptr = m_ossl_ec.get();
if(!::o2i_ECPublicKey(&key_ptr, &enc_ptr, enc.size()))
diff --git a/src/lib/prov/pkcs11/p11_ecc_key.cpp b/src/lib/prov/pkcs11/p11_ecc_key.cpp
index d5a9a2b76..2bcf41a2c 100644
--- a/src/lib/prov/pkcs11/p11_ecc_key.cpp
+++ b/src/lib/prov/pkcs11/p11_ecc_key.cpp
@@ -111,7 +111,7 @@ size_t PKCS11_EC_PrivateKey::key_length() const
std::vector<uint8_t> PKCS11_EC_PrivateKey::public_key_bits() const
{
- return unlock(EC2OSP(public_point(), PointGFp::COMPRESSED));
+ return public_point().encode(PointGFp::COMPRESSED);
}
size_t PKCS11_EC_PrivateKey::estimated_strength() const
diff --git a/src/lib/prov/pkcs11/p11_ecdh.h b/src/lib/prov/pkcs11/p11_ecdh.h
index 203e5ea5f..bbef9a3e5 100644
--- a/src/lib/prov/pkcs11/p11_ecdh.h
+++ b/src/lib/prov/pkcs11/p11_ecdh.h
@@ -95,7 +95,7 @@ class BOTAN_PUBLIC_API(2,0) PKCS11_ECDH_PrivateKey final : public virtual PKCS11
inline std::vector<uint8_t> public_value() const override
{
- return unlock(EC2OSP(public_point(), PointGFp::UNCOMPRESSED));
+ return public_point().encode(PointGFp::UNCOMPRESSED);
}
/// @return the exported ECDH private key
diff --git a/src/lib/pubkey/ec_group/ec_group.cpp b/src/lib/pubkey/ec_group/ec_group.cpp
index 5fb79c923..ccf1969d2 100644
--- a/src/lib/pubkey/ec_group/ec_group.cpp
+++ b/src/lib/pubkey/ec_group/ec_group.cpp
@@ -528,7 +528,7 @@ EC_Group::DER_encode(EC_Group_Encoding form) const
.encode(BigInt::encode_1363(get_b(), p_bytes),
OCTET_STRING)
.end_cons()
- .encode(EC2OSP(get_base_point(), PointGFp::UNCOMPRESSED), OCTET_STRING)
+ .encode(get_base_point().encode(PointGFp::UNCOMPRESSED), OCTET_STRING)
.encode(get_order())
.encode(get_cofactor())
.end_cons()
diff --git a/src/lib/pubkey/ec_group/point_gfp.cpp b/src/lib/pubkey/ec_group/point_gfp.cpp
index c71a6cffe..47ca0527d 100644
--- a/src/lib/pubkey/ec_group/point_gfp.cpp
+++ b/src/lib/pubkey/ec_group/point_gfp.cpp
@@ -618,50 +618,42 @@ bool PointGFp::operator==(const PointGFp& other) const
}
// encoding and decoding
-secure_vector<uint8_t> EC2OSP(const PointGFp& point, uint8_t format)
+std::vector<uint8_t> PointGFp::encode(PointGFp::Compression_Type format) const
{
- if(point.is_zero())
- return secure_vector<uint8_t>(1); // single 0 byte
+ if(is_zero())
+ return std::vector<uint8_t>(1); // single 0 byte
- const size_t p_bytes = point.get_curve().get_p().bytes();
+ const size_t p_bytes = m_curve.get_p().bytes();
- BigInt x = point.get_affine_x();
- BigInt y = point.get_affine_y();
+ const BigInt x = get_affine_x();
+ const BigInt y = get_affine_y();
- secure_vector<uint8_t> bX = BigInt::encode_1363(x, p_bytes);
- secure_vector<uint8_t> bY = BigInt::encode_1363(y, p_bytes);
+ std::vector<uint8_t> result;
if(format == PointGFp::UNCOMPRESSED)
{
- secure_vector<uint8_t> result;
- result.push_back(0x04);
-
- result += bX;
- result += bY;
-
- return result;
+ result.resize(1 + 2*p_bytes);
+ result[0] = 0x04;
+ BigInt::encode_1363(&result[1], p_bytes, x);
+ BigInt::encode_1363(&result[1+p_bytes], p_bytes, y);
}
else if(format == PointGFp::COMPRESSED)
{
- secure_vector<uint8_t> result;
- result.push_back(0x02 | static_cast<uint8_t>(y.get_bit(0)));
-
- result += bX;
-
- return result;
+ result.resize(1 + p_bytes);
+ result[0] = 0x02 | static_cast<uint8_t>(y.get_bit(0));
+ BigInt::encode_1363(&result[1], p_bytes, x);
}
else if(format == PointGFp::HYBRID)
{
- secure_vector<uint8_t> result;
- result.push_back(0x06 | static_cast<uint8_t>(y.get_bit(0)));
-
- result += bX;
- result += bY;
-
- return result;
+ result.resize(1 + 2*p_bytes);
+ result[0] = 0x06 | static_cast<uint8_t>(y.get_bit(0));
+ BigInt::encode_1363(&result[1], p_bytes, x);
+ BigInt::encode_1363(&result[1+p_bytes], p_bytes, y);
}
else
throw Invalid_Argument("EC2OSP illegal point encoding");
+
+ return result;
}
namespace {
diff --git a/src/lib/pubkey/ec_group/point_gfp.h b/src/lib/pubkey/ec_group/point_gfp.h
index 6f2e34f27..81e34c634 100644
--- a/src/lib/pubkey/ec_group/point_gfp.h
+++ b/src/lib/pubkey/ec_group/point_gfp.h
@@ -99,6 +99,12 @@ class BOTAN_PUBLIC_API(2,0) PointGFp final
PointGFp(const CurveGFp& curve, const BigInt& x, const BigInt& y);
/**
+ * EC2OSP - elliptic curve to octet string primitive
+ * @param format which format to encode using
+ */
+ std::vector<uint8_t> encode(PointGFp::Compression_Type format) const;
+
+ /**
* += Operator
* @param rhs the PointGFp to add to the local value
* @result resulting PointGFp
@@ -131,12 +137,6 @@ class BOTAN_PUBLIC_API(2,0) PointGFp final
}
/**
- * Return base curve of this point
- * @result the curve over GF(p) of this point
- */
- const CurveGFp& get_curve() const { return m_curve; }
-
- /**
* get affine x coordinate
* @result affine x coordinate
*/
@@ -199,7 +199,7 @@ class BOTAN_PUBLIC_API(2,0) PointGFp final
/**
* Point addition - mixed J+A
- * @param other affine point to add
+ * @param other affine point to add - assumed to be affine!
* @param workspace temp space, at least WORKSPACE_SIZE elements
*/
void add_affine(const PointGFp& other, std::vector<BigInt>& workspace);
@@ -226,6 +226,14 @@ class BOTAN_PUBLIC_API(2,0) PointGFp final
*/
PointGFp zero() const { return PointGFp(m_curve); }
+ /**
+ * Return base curve of this point
+ * @result the curve over GF(p) of this point
+ *
+ * You should not need to use this
+ */
+ const CurveGFp& get_curve() const { return m_curve; }
+
private:
CurveGFp m_curve;
BigInt m_coord_x, m_coord_y, m_coord_z;
@@ -281,7 +289,12 @@ inline PointGFp operator*(const PointGFp& point, const BigInt& scalar)
}
// encoding and decoding
-secure_vector<uint8_t> BOTAN_PUBLIC_API(2,0) EC2OSP(const PointGFp& point, uint8_t format);
+inline secure_vector<uint8_t> BOTAN_DEPRECATED("Use PointGFp::encode")
+ EC2OSP(const PointGFp& point, uint8_t format)
+ {
+ std::vector<uint8_t> enc = point.encode(static_cast<PointGFp::Compression_Type>(format));
+ return secure_vector<uint8_t>(enc.begin(), enc.end());
+ }
PointGFp BOTAN_PUBLIC_API(2,0) OS2ECP(const uint8_t data[], size_t data_len,
const CurveGFp& curve);
diff --git a/src/lib/pubkey/ecc_key/ecc_key.cpp b/src/lib/pubkey/ecc_key/ecc_key.cpp
index 4b591ff56..7b00d3209 100644
--- a/src/lib/pubkey/ecc_key/ecc_key.cpp
+++ b/src/lib/pubkey/ecc_key/ecc_key.cpp
@@ -68,7 +68,17 @@ AlgorithmIdentifier EC_PublicKey::algorithm_identifier() const
std::vector<uint8_t> EC_PublicKey::public_key_bits() const
{
- return unlock(EC2OSP(public_point(), PointGFp::COMPRESSED));
+ return public_point().encode(point_encoding());
+ }
+
+void EC_PublicKey::set_point_encoding(PointGFp::Compression_Type enc)
+ {
+ if(enc != PointGFp::COMPRESSED &&
+ enc != PointGFp::UNCOMPRESSED &&
+ enc != PointGFp::HYBRID)
+ throw Invalid_Argument("Invalid point encoding for EC_PublicKey");
+
+ m_point_encoding = enc;
}
void EC_PublicKey::set_parameter_encoding(EC_Group_Encoding form)
diff --git a/src/lib/pubkey/ecc_key/ecc_key.h b/src/lib/pubkey/ecc_key/ecc_key.h
index 427be56ef..ec2b5f9be 100644
--- a/src/lib/pubkey/ecc_key/ecc_key.h
+++ b/src/lib/pubkey/ecc_key/ecc_key.h
@@ -78,6 +78,12 @@ class BOTAN_PUBLIC_API(2,0) EC_PublicKey : public virtual Public_Key
void set_parameter_encoding(EC_Group_Encoding enc);
/**
+ * Set the point encoding method to be used when encoding this key.
+ * @param enc the encoding to use
+ */
+ void set_point_encoding(PointGFp::Compression_Type enc);
+
+ /**
* Return the DER encoding of this keys domain in whatever format
* is preset for this particular key
*/
@@ -91,6 +97,13 @@ class BOTAN_PUBLIC_API(2,0) EC_PublicKey : public virtual Public_Key
EC_Group_Encoding domain_format() const
{ return m_domain_encoding; }
+ /**
+ * Get the point encoding method to be used when encoding this key.
+ * @result the encoding to use
+ */
+ PointGFp::Compression_Type point_encoding() const
+ { return m_point_encoding; }
+
size_t key_length() const override;
size_t estimated_strength() const override;
@@ -101,6 +114,7 @@ class BOTAN_PUBLIC_API(2,0) EC_PublicKey : public virtual Public_Key
EC_Group m_domain_params;
PointGFp m_public_key;
EC_Group_Encoding m_domain_encoding;
+ PointGFp::Compression_Type m_point_encoding = PointGFp::UNCOMPRESSED;
};
/**
diff --git a/src/lib/pubkey/ecdh/ecdh.h b/src/lib/pubkey/ecdh/ecdh.h
index d967c749f..f88955ac4 100644
--- a/src/lib/pubkey/ecdh/ecdh.h
+++ b/src/lib/pubkey/ecdh/ecdh.h
@@ -48,13 +48,13 @@ class BOTAN_PUBLIC_API(2,0) ECDH_PublicKey : public virtual EC_PublicKey
* @return public point value
*/
std::vector<uint8_t> public_value() const
- { return unlock(EC2OSP(public_point(), PointGFp::UNCOMPRESSED)); }
+ { return public_point().encode(PointGFp::UNCOMPRESSED); }
/**
* @return public point value
*/
- std::vector<uint8_t> public_value(PointGFp::Compression_Type type) const
- { return unlock(EC2OSP(public_point(), static_cast<uint8_t>(type))); }
+ std::vector<uint8_t> public_value(PointGFp::Compression_Type format) const
+ { return public_point().encode(format); }
protected:
ECDH_PublicKey() = default;
diff --git a/src/lib/pubkey/ecies/ecies.cpp b/src/lib/pubkey/ecies/ecies.cpp
index 06d5cfeee..8bc4e2600 100644
--- a/src/lib/pubkey/ecies/ecies.cpp
+++ b/src/lib/pubkey/ecies/ecies.cpp
@@ -168,7 +168,7 @@ SymmetricKey ECIES_KA_Operation::derive_secret(const std::vector<uint8_t>& eph_p
}
// ISO 18033: encryption step f / decryption step h
- secure_vector<uint8_t> other_public_key_bin = EC2OSP(other_point, static_cast<uint8_t>(m_params.compression_type()));
+ std::vector<uint8_t> other_public_key_bin = other_point.encode(m_params.compression_type());
// Note: the argument `m_params.secret_length()` passed for `key_len` will only be used by providers because
// "Raw" is passed to the `PK_Key_Agreement` if the implementation of botan is used.
const SymmetricKey peh = m_ka.derive_key(m_params.domain().get_order().bytes(), other_public_key_bin.data(), other_public_key_bin.size());
@@ -247,8 +247,7 @@ ECIES_Encryptor::ECIES_Encryptor(const PK_Key_Agreement_Key& private_key,
{
// ISO 18033: step d
// convert only if necessary; m_eph_public_key_bin has been initialized with the uncompressed format
- m_eph_public_key_bin = unlock(EC2OSP(m_params.domain().OS2ECP(m_eph_public_key_bin),
- static_cast<uint8_t>(ecies_params.compression_type())));
+ m_eph_public_key_bin = m_params.domain().OS2ECP(m_eph_public_key_bin).encode(ecies_params.compression_type());
}
}
diff --git a/src/tests/test_ecies.cpp b/src/tests/test_ecies.cpp
index 2ce931bae..911d0c3a3 100644
--- a/src/tests/test_ecies.cpp
+++ b/src/tests/test_ecies.cpp
@@ -137,8 +137,7 @@ class ECIES_ISO_Tests final : public Text_Based_Test
// (ephemeral) keys of alice
const Botan::ECDH_PrivateKey eph_private_key(Test::rng(), domain, r);
const Botan::PointGFp eph_public_key_point = eph_private_key.public_point();
- const std::vector<uint8_t> eph_public_key_bin = Botan::unlock(
- Botan::EC2OSP(eph_public_key_point, compression_type));
+ const std::vector<uint8_t> eph_public_key_bin = eph_public_key_point.encode(compression_type);
result.test_eq("encoded (ephemeral) public key", eph_public_key_bin, c0);
// test secret derivation: ISO 18033 test vectors use KDF1 from ISO 18033
diff --git a/src/tests/test_pkcs11_high_level.cpp b/src/tests/test_pkcs11_high_level.cpp
index e89715189..b8ed97a54 100644
--- a/src/tests/test_pkcs11_high_level.cpp
+++ b/src/tests/test_pkcs11_high_level.cpp
@@ -980,9 +980,12 @@ Test::Result test_ecdsa_pubkey_import()
ECDSA_PrivateKey priv_key(Test::rng(), EC_Group("secp256r1"));
priv_key.set_parameter_encoding(EC_Group_Encoding::EC_DOMPAR_ENC_OID);
+ const std::vector<uint8_t> enc_point = DER_Encoder().encode(
+ priv_key.public_point().encode(PointGFp::UNCOMPRESSED), OCTET_STRING).
+ get_contents_unlocked();
+
// import to card
- EC_PublicKeyImportProperties props(priv_key.DER_domain(), DER_Encoder().encode(EC2OSP(priv_key.public_point(),
- PointGFp::UNCOMPRESSED), OCTET_STRING).get_contents_unlocked());
+ EC_PublicKeyImportProperties props(priv_key.DER_domain(), enc_point);
props.set_token(true);
props.set_verify(true);
props.set_private(false);
@@ -1008,9 +1011,12 @@ Test::Result test_ecdsa_pubkey_export()
ECDSA_PrivateKey priv_key(Test::rng(), EC_Group("secp256r1"));
priv_key.set_parameter_encoding(EC_Group_Encoding::EC_DOMPAR_ENC_OID);
+ const std::vector<uint8_t> enc_point = DER_Encoder().encode(
+ priv_key.public_point().encode(PointGFp::UNCOMPRESSED), OCTET_STRING).
+ get_contents_unlocked();
+
// import to card
- EC_PublicKeyImportProperties props(priv_key.DER_domain(), DER_Encoder().encode(EC2OSP(priv_key.public_point(),
- PointGFp::UNCOMPRESSED), OCTET_STRING).get_contents_unlocked());
+ EC_PublicKeyImportProperties props(priv_key.DER_domain(), enc_point);
props.set_token(true);
props.set_verify(true);
props.set_private(false);
@@ -1216,9 +1222,12 @@ Test::Result test_ecdh_pubkey_import()
ECDH_PrivateKey priv_key(Test::rng(), EC_Group("secp256r1"));
priv_key.set_parameter_encoding(EC_Group_Encoding::EC_DOMPAR_ENC_OID);
+ const std::vector<uint8_t> enc_point = DER_Encoder().encode(
+ priv_key.public_point().encode(PointGFp::UNCOMPRESSED), OCTET_STRING).
+ get_contents_unlocked();
+
// import to card
- EC_PublicKeyImportProperties props(priv_key.DER_domain(), DER_Encoder().encode(EC2OSP(priv_key.public_point(),
- PointGFp::UNCOMPRESSED), OCTET_STRING).get_contents_unlocked());
+ EC_PublicKeyImportProperties props(priv_key.DER_domain(), enc_point);
props.set_token(true);
props.set_private(false);
props.set_derive(true);
@@ -1244,9 +1253,12 @@ Test::Result test_ecdh_pubkey_export()
ECDH_PrivateKey priv_key(Test::rng(), EC_Group("secp256r1"));
priv_key.set_parameter_encoding(EC_Group_Encoding::EC_DOMPAR_ENC_OID);
+ const std::vector<uint8_t> enc_point = DER_Encoder().encode(
+ priv_key.public_point().encode(PointGFp::UNCOMPRESSED), OCTET_STRING).
+ get_contents_unlocked();
+
// import to card
- EC_PublicKeyImportProperties props(priv_key.DER_domain(), DER_Encoder().encode(EC2OSP(priv_key.public_point(),
- PointGFp::UNCOMPRESSED), OCTET_STRING).get_contents_unlocked());
+ EC_PublicKeyImportProperties props(priv_key.DER_domain(), enc_point);
props.set_token(true);
props.set_derive(true);
props.set_private(false);
@@ -1332,9 +1344,8 @@ Test::Result test_ecdh_derive()
Botan::PK_Key_Agreement ka(keypair.second, Test::rng(), "Raw");
Botan::PK_Key_Agreement kb(keypair2.second, Test::rng(), "Raw");
- Botan::SymmetricKey alice_key = ka.derive_key(32, unlock(EC2OSP(keypair2.first.public_point(),
- PointGFp::UNCOMPRESSED)));
- Botan::SymmetricKey bob_key = kb.derive_key(32, unlock(EC2OSP(keypair.first.public_point(), PointGFp::UNCOMPRESSED)));
+ Botan::SymmetricKey alice_key = ka.derive_key(32, keypair2.first.public_point().encode(PointGFp::UNCOMPRESSED));
+ Botan::SymmetricKey bob_key = kb.derive_key(32, keypair.first.public_point().encode(PointGFp::UNCOMPRESSED));
bool eq = alice_key == bob_key;
result.test_eq("same secret key derived", eq, true);
diff --git a/src/tests/unit_ecc.cpp b/src/tests/unit_ecc.cpp
index cbff3ff4f..f3a163435 100644
--- a/src/tests/unit_ecc.cpp
+++ b/src/tests/unit_ecc.cpp
@@ -429,13 +429,13 @@ Test::Result test_zeropoint_enc_dec()
Botan::PointGFp p = secp160r1.zero_point();
result.confirm("zero point is zero", p.is_zero());
- std::vector<uint8_t> sv_p = unlock(EC2OSP(p, Botan::PointGFp::UNCOMPRESSED));
+ std::vector<uint8_t> sv_p = p.encode(Botan::PointGFp::UNCOMPRESSED);
result.test_eq("encoded/decode rt works", secp160r1.OS2ECP(sv_p), p);
- sv_p = unlock(EC2OSP(p, Botan::PointGFp::COMPRESSED));
+ sv_p = p.encode(Botan::PointGFp::COMPRESSED);
result.test_eq("encoded/decode compressed rt works", secp160r1.OS2ECP(sv_p), p);
- sv_p = unlock(EC2OSP(p, Botan::PointGFp::HYBRID));
+ sv_p = p.encode(Botan::PointGFp::HYBRID);
result.test_eq("encoded/decode hybrid rt works", secp160r1.OS2ECP(sv_p), p);
return result;
}
@@ -572,7 +572,7 @@ Test::Result test_enc_dec_compressed_160()
const Botan::PointGFp p = secp160r1.OS2ECP(G_comp);
- std::vector<uint8_t> sv_result = unlock(Botan::EC2OSP(p, Botan::PointGFp::COMPRESSED));
+ std::vector<uint8_t> sv_result = p.encode(Botan::PointGFp::COMPRESSED);
result.test_eq("result", sv_result, G_comp);
return result;
@@ -588,7 +588,7 @@ Test::Result test_enc_dec_compressed_256()
const std::vector<uint8_t> sv_G_secp_comp = Botan::hex_decode(G_secp_comp);
Botan::PointGFp p_G = group.OS2ECP(sv_G_secp_comp);
- std::vector<uint8_t> sv_result = unlock(EC2OSP(p_G, Botan::PointGFp::COMPRESSED));
+ std::vector<uint8_t> sv_result = p_G.encode(Botan::PointGFp::COMPRESSED);
result.test_eq("compressed_256", sv_result, sv_G_secp_comp);
return result;
@@ -619,7 +619,7 @@ Test::Result test_enc_dec_uncompressed_112()
const std::vector<uint8_t> sv_G_secp_uncomp = Botan::hex_decode(G_secp_uncomp);
Botan::PointGFp p_G = group.OS2ECP(sv_G_secp_uncomp);
- std::vector<uint8_t> sv_result = unlock(EC2OSP(p_G, Botan::PointGFp::UNCOMPRESSED));
+ std::vector<uint8_t> sv_result = p_G.encode(Botan::PointGFp::UNCOMPRESSED);
result.test_eq("uncompressed_112", sv_result, sv_G_secp_uncomp);
return result;
@@ -640,7 +640,7 @@ Test::Result test_enc_dec_uncompressed_521()
Botan::PointGFp p_G = group.OS2ECP(sv_G_secp_uncomp);
- std::vector<uint8_t> sv_result = unlock(EC2OSP(p_G, Botan::PointGFp::UNCOMPRESSED));
+ std::vector<uint8_t> sv_result = p_G.encode(Botan::PointGFp::UNCOMPRESSED);
result.test_eq("expected", sv_result, sv_G_secp_uncomp);
return result;
@@ -654,7 +654,7 @@ Test::Result test_gfp_store_restore()
Botan::EC_Group dom_pars("secp160r1");
Botan::PointGFp p = dom_pars.get_base_point();
- std::vector<uint8_t> sv_mes = unlock(EC2OSP(p, Botan::PointGFp::COMPRESSED));
+ std::vector<uint8_t> sv_mes = p.encode(Botan::PointGFp::COMPRESSED);
Botan::PointGFp new_p = dom_pars.OS2ECP(sv_mes);
result.test_eq("original and restored points are same", p, new_p);
diff --git a/src/tests/unit_ecdsa.cpp b/src/tests/unit_ecdsa.cpp
index 081b686e6..f91c1b345 100644
--- a/src/tests/unit_ecdsa.cpp
+++ b/src/tests/unit_ecdsa.cpp
@@ -122,7 +122,7 @@ Test::Result test_sign_then_ver()
{
Test::Result result("ECDSA Unit");
- Botan::EC_Group dom_pars(Botan::OID("1.3.132.0.8"));
+ Botan::EC_Group dom_pars("secp160r1");
Botan::ECDSA_PrivateKey ecdsa(Test::rng(), dom_pars);
Botan::PK_Signer signer(ecdsa, Test::rng(), "EMSA1(SHA-256)");
@@ -145,7 +145,7 @@ Test::Result test_ec_sign()
try
{
- Botan::EC_Group dom_pars(Botan::OID("1.3.132.0.8"));
+ Botan::EC_Group dom_pars("secp160r1");
Botan::ECDSA_PrivateKey priv_key(Test::rng(), dom_pars);
Botan::PK_Signer signer(priv_key, Test::rng(), "EMSA1(SHA-224)");
Botan::PK_Verifier verifier(priv_key, "EMSA1(SHA-224)");
@@ -199,7 +199,7 @@ Test::Result test_ecdsa_create_save_load()
try
{
- Botan::EC_Group dom_pars(Botan::OID("1.3.132.0.8"));
+ Botan::EC_Group dom_pars("secp160r1");
Botan::ECDSA_PrivateKey key(Test::rng(), dom_pars);
Botan::PK_Signer signer(key, Test::rng(), "EMSA1(SHA-256)");
@@ -262,6 +262,52 @@ Test::Result test_unusual_curve()
return result;
}
+Test::Result test_encoding_options()
+ {
+ Test::Result result("ECDSA Unit");
+
+ Botan::EC_Group group("secp256r1");
+ Botan::ECDSA_PrivateKey key(Test::rng(), group);
+
+ result.confirm("Default encoding is uncompressed",
+ key.point_encoding() == Botan::PointGFp::UNCOMPRESSED);
+
+ const std::vector<uint8_t> enc_uncompressed = key.public_key_bits();
+
+ key.set_point_encoding(Botan::PointGFp::COMPRESSED);
+
+ result.confirm("set_point_encoding works",
+ key.point_encoding() == Botan::PointGFp::COMPRESSED);
+
+ const std::vector<uint8_t> enc_compressed = key.public_key_bits();
+
+ result.test_lt("Comprssed points are smaller",
+ enc_compressed.size(), enc_uncompressed.size());
+
+ size_t size_diff = enc_uncompressed.size() - enc_compressed.size();
+
+ result.test_gte("Compressed points smaller by group size",
+ size_diff, 32);
+
+ key.set_point_encoding(Botan::PointGFp::HYBRID);
+
+ result.confirm("set_point_encoding works",
+ key.point_encoding() == Botan::PointGFp::HYBRID);
+
+ const std::vector<uint8_t> enc_hybrid = key.public_key_bits();
+
+ result.test_eq("Hybrid point same size as uncompressed",
+ enc_uncompressed.size(), enc_hybrid.size());
+
+ auto invalid_format = static_cast<Botan::PointGFp::Compression_Type>(99);
+
+ result.test_throws("Invalid point format throws",
+ "Invalid argument Invalid point encoding for EC_PublicKey",
+ [&] { key.set_point_encoding(invalid_format); });
+
+ return result;
+ }
+
#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
Test::Result test_read_pkcs8()
@@ -435,6 +481,7 @@ class ECDSA_Unit_Tests final : public Test
results.push_back(test_ecdsa_create_save_load());
results.push_back(test_unusual_curve());
results.push_back(test_curve_registry());
+ results.push_back(test_encoding_options());
return results;
}
};