diff options
-rw-r--r-- | news.rst | 5 | ||||
-rw-r--r-- | src/cli/speed.cpp | 4 | ||||
-rw-r--r-- | src/lib/prov/bearssl/bearssl_ec.cpp | 4 | ||||
-rw-r--r-- | src/lib/prov/openssl/openssl_ec.cpp | 4 | ||||
-rw-r--r-- | src/lib/prov/pkcs11/p11_ecc_key.cpp | 2 | ||||
-rw-r--r-- | src/lib/prov/pkcs11/p11_ecdh.h | 2 | ||||
-rw-r--r-- | src/lib/pubkey/ec_group/ec_group.cpp | 2 | ||||
-rw-r--r-- | src/lib/pubkey/ec_group/point_gfp.cpp | 48 | ||||
-rw-r--r-- | src/lib/pubkey/ec_group/point_gfp.h | 29 | ||||
-rw-r--r-- | src/lib/pubkey/ecc_key/ecc_key.cpp | 12 | ||||
-rw-r--r-- | src/lib/pubkey/ecc_key/ecc_key.h | 14 | ||||
-rw-r--r-- | src/lib/pubkey/ecdh/ecdh.h | 6 | ||||
-rw-r--r-- | src/lib/pubkey/ecies/ecies.cpp | 5 | ||||
-rw-r--r-- | src/tests/test_ecies.cpp | 3 | ||||
-rw-r--r-- | src/tests/test_pkcs11_high_level.cpp | 33 | ||||
-rw-r--r-- | src/tests/unit_ecc.cpp | 16 | ||||
-rw-r--r-- | src/tests/unit_ecdsa.cpp | 53 |
17 files changed, 166 insertions, 76 deletions
@@ -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; } }; |