diff options
Diffstat (limited to 'src')
150 files changed, 3625 insertions, 5426 deletions
diff --git a/src/asn1/asn1_oid.cpp b/src/asn1/asn1_oid.cpp index 425df645c..4f2c70231 100644 --- a/src/asn1/asn1_oid.cpp +++ b/src/asn1/asn1_oid.cpp @@ -20,7 +20,15 @@ OID::OID(const std::string& oid_str) { if(oid_str != "") { - id = parse_asn1_oid(oid_str); + try + { + id = parse_asn1_oid(oid_str); + } + catch(...) + { + throw Invalid_OID(oid_str); + } + if(id.size() < 2 || id[0] > 2) throw Invalid_OID(oid_str); if((id[0] == 0 || id[0] == 1) && id[1] > 39) diff --git a/src/build-data/buildh.in b/src/build-data/buildh.in index 6412d8a6a..724801040 100644 --- a/src/build-data/buildh.in +++ b/src/build-data/buildh.in @@ -20,7 +20,6 @@ #define BOTAN_MP_WORD_BITS %{mp_bits} #define BOTAN_KARAT_MUL_THRESHOLD 32 #define BOTAN_KARAT_SQR_THRESHOLD 32 -#define BOTAN_PRIVATE_KEY_OP_BLINDING_BITS 64 /* PK key consistency checking toggles */ #define BOTAN_PUBLIC_KEY_STRONG_CHECKS_ON_LOAD 1 diff --git a/src/build-data/cc/gcc.txt b/src/build-data/cc/gcc.txt index 1b9f51620..14701718c 100644 --- a/src/build-data/cc/gcc.txt +++ b/src/build-data/cc/gcc.txt @@ -10,7 +10,7 @@ add_lib_option -l lang_flags "-ansi -std=c++0x" warning_flags "-W -Wall" -#warning_flags "-Wextra -Wall -Wstrict-aliasing -Wstrict-overflow=5 -Wcast-align -Wmissing-declarations -Wno-unused-parameter" +#warning_flags "-Werror -Wextra -Wall -Wstrict-aliasing -Wstrict-overflow=5 -Wcast-align -Wmissing-declarations -Wno-unused-parameter" lib_opt_flags "-O3" check_opt_flags "-O2" diff --git a/src/build-data/cc/msvc.txt b/src/build-data/cc/msvc.txt index 36437e6a2..df8d94671 100644 --- a/src/build-data/cc/msvc.txt +++ b/src/build-data/cc/msvc.txt @@ -14,7 +14,7 @@ check_opt_flags "/O2 /D_CONSOLE" lang_flags "/EHsc /GR" warning_flags "/W3" -shared_flags "/DBOTAN_DLL=__declspec(dllexport)" +shared_flags "/DBOTAN_DLL=__declspec(dllexport) /wd4275" dll_import_flags "__declspec(dllimport)" ar_command lib diff --git a/src/build-data/makefile/nmake.in b/src/build-data/makefile/nmake.in index 2d89850fd..212825131 100644 --- a/src/build-data/makefile/nmake.in +++ b/src/build-data/makefile/nmake.in @@ -64,7 +64,11 @@ $(CHECK): $(LIBRARIES) $(CHECKOBJS) $(CXX) /Fe$@ $(CHECKOBJS) $(BOTAN_LIB) $(LINK_TO) $(BOTAN_LIB): $(LIBOBJS) +!If "$(SO_OBJ_FLAGS)" == "" + $(AR) /OUT:$(BOTAN_LIB) $(LIBOBJS) +!Else $(LIB_LINK_CMD) /Fe$(LIBNAME) $(LIBOBJS) $(LINK_TO) +!Endif ### Fake Targets clean: @@ -73,7 +77,9 @@ clean: distclean: clean $(RM_R) %{build_dir} - $(RMDIR) %{build_dir}\include\botan %{build_dir}\include + $(RMDIR) %{build_dir}\include\botan\internal + $(RMDIR) %{build_dir}\include\botan + $(RMDIR) %{build_dir}\include $(RMDIR) %{build_dir}\lib %{build_dir}\checks $(RMDIR) %{build_dir} $(RM) Makefile $(LIBNAME).* $(CHECK).* diff --git a/src/build-data/makefile/python.in b/src/build-data/makefile/python.in index 9658c70ce..d3b4a122b 100644 --- a/src/build-data/makefile/python.in +++ b/src/build-data/makefile/python.in @@ -6,17 +6,15 @@ PYTHON_SITE_PACKAGE_DIR = /usr/lib/python%{python_version}/site-packages/ PYTHON_FLAGS = -Isrc/wrap/python -Os -fPIC -ftemplate-depth-255 -Wall -Wno-unused $(PYTHON_INC) -PYTHON_OBJS = %{python_objs} +BOTAN_PYTHON_MODDIR = %{python_obj_dir} -BOTAN_PYTHON_MODDIR = build/botan-python +PYTHON_OBJS = %{python_objs} all: $(BOTAN_PYTHON_MODDIR)/_botan.so %{python_build_cmds} $(BOTAN_PYTHON_MODDIR)/_botan.so: $(PYTHON_OBJS) - rm -rf $(BOTAN_PYTHON_MODDIR) - mkdir $(BOTAN_PYTHON_MODDIR) cp src/wrap/python/*.py $(BOTAN_PYTHON_MODDIR) $(CXX) -shared -o $@ $(PYTHON_OBJS) -L. -L$(PYTHON_ROOT) -lbotan -lboost_python -Wl,-rpath-link,. -Wl,-soname,$@ @@ -25,5 +23,5 @@ clean: install: mkdir -p $(PYTHON_SITE_PACKAGE_DIR)/botan - cp $(BOTAN_PYTHON_MODDIR)/* $(PYTHON_SITE_PACKAGE_DIR)/botan + cp $(BOTAN_PYTHON_MODDIR)/_botan.so $(BOTAN_PYTHON_MODDIR)/*.py $(PYTHON_SITE_PACKAGE_DIR)/botan chmod -R u=rwX,go=rX $(PYTHON_SITE_PACKAGE_DIR)/botan diff --git a/src/cert/cvc/cvc_ado.cpp b/src/cert/cvc/cvc_ado.cpp index fd5b80f13..8c38e90ae 100644 --- a/src/cert/cvc/cvc_ado.cpp +++ b/src/cert/cvc/cvc_ado.cpp @@ -45,13 +45,11 @@ void EAC1_1_ADO::force_decode() sig_algo = m_req.sig_algo; } -MemoryVector<byte> EAC1_1_ADO::make_signed( - PK_Signer& signer, - const MemoryRegion<byte>& tbs_bits, - RandomNumberGenerator& rng) +MemoryVector<byte> EAC1_1_ADO::make_signed(PK_Signer& signer, + const MemoryRegion<byte>& tbs_bits, + RandomNumberGenerator& rng) { - SecureVector<byte> concat_sig = - EAC1_1_obj<EAC1_1_ADO>::make_signature(signer, tbs_bits, rng); + SecureVector<byte> concat_sig = signer.sign_message(tbs_bits, rng); return DER_Encoder() .start_cons(ASN1_Tag(7), APPLICATION) diff --git a/src/cert/cvc/cvc_ado.h b/src/cert/cvc/cvc_ado.h index 100888d29..230ee8b8d 100644 --- a/src/cert/cvc/cvc_ado.h +++ b/src/cert/cvc/cvc_ado.h @@ -8,11 +8,8 @@ #ifndef BOTAN_EAC_CVC_ADO_H__ #define BOTAN_EAC_CVC_ADO_H__ -#include <botan/x509_key.h> -#include <botan/pubkey_enums.h> -#include <botan/pubkey.h> -#include <botan/ecdsa.h> #include <botan/eac_obj.h> +#include <botan/eac_asn_obj.h> #include <botan/cvc_req.h> #include <string> diff --git a/src/cert/cvc/cvc_ca.cpp b/src/cert/cvc/cvc_ca.cpp deleted file mode 100644 index af40fcd05..000000000 --- a/src/cert/cvc/cvc_ca.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include <botan/cvc_ca.h> -#include <botan/cvc_cert.h> -#include <botan/der_enc.h> -#include <botan/oids.h> -namespace Botan { - -EAC1_1_CVC EAC1_1_CVC_CA::make_cert(PK_Signer& signer, - MemoryRegion<byte> const& public_key, - ASN1_Car const& car, - ASN1_Chr const& chr, - byte holder_auth_templ, - ASN1_Ced ced, - ASN1_Cex cex, - RandomNumberGenerator& rng) - { - OID chat_oid(OIDS::lookup("CertificateHolderAuthorizationTemplate")); - MemoryVector<byte> enc_chat_val; - enc_chat_val.append(holder_auth_templ); - - MemoryVector<byte> enc_cpi; - enc_cpi.append(0x00); - MemoryVector<byte> tbs = DER_Encoder() - .encode(enc_cpi, OCTET_STRING, ASN1_Tag(41), APPLICATION) // cpi - .encode(car) - .raw_bytes(public_key) - .encode(chr) - .start_cons(ASN1_Tag(76), APPLICATION) - .encode(chat_oid) - .encode(enc_chat_val, OCTET_STRING, ASN1_Tag(19), APPLICATION) - .end_cons() - .encode(ced) - .encode(cex) - .get_contents(); - - MemoryVector<byte> signed_cert = - EAC1_1_CVC::make_signed(signer, - EAC1_1_CVC::build_cert_body(tbs), - rng); - - DataSource_Memory source(signed_cert); - return EAC1_1_CVC(source); - } - -} diff --git a/src/cert/cvc/cvc_ca.h b/src/cert/cvc/cvc_ca.h deleted file mode 100644 index 87699808f..000000000 --- a/src/cert/cvc/cvc_ca.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -* EAC1.1 CVC Certificate Authority -* (C) 2007 FlexSecure GmbH -* 2008 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_CVC_CA_H__ -#define BOTAN_CVC_CA_H__ - -#include <botan/pkcs8.h> -#include <botan/pkcs10.h> -#include <botan/pubkey.h> -#include <botan/cvc_cert.h> - -namespace Botan { - -/** -* This class represents a CVC CA. -*/ -class BOTAN_DLL EAC1_1_CVC_CA - { - public: - - /** - * Create an arbitrary EAC 1.1 CVC. - * The desired key encoding must be set within the key (if applicable). - * @param signer the signer used to sign the certificate - * @param public_key the DER encoded public key to appear in - * the certificate - * @param car the CAR of the certificate - * @param chr the CHR of the certificate - * @param holder_auth_templ the holder authorization value byte to - * appear in the CHAT of the certificate - * @param ced the CED to appear in the certificate - * @param ced the CEX to appear in the certificate - */ - static EAC1_1_CVC make_cert(PK_Signer& signer, - MemoryRegion<byte> const& public_key, - ASN1_Car const& car, - ASN1_Chr const& chr, - byte holder_auth_templ, - ASN1_Ced ced, - ASN1_Cex cex, - RandomNumberGenerator& rng); - }; - -} - -#endif diff --git a/src/cert/cvc/cvc_cert.cpp b/src/cert/cvc/cvc_cert.cpp index 4274e143b..9cc2bb7e5 100644 --- a/src/cert/cvc/cvc_cert.cpp +++ b/src/cert/cvc/cvc_cert.cpp @@ -1,13 +1,12 @@ /* (C) 2007 FlexSecure GmbH - 2008 Jack Lloyd + 2008-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ #include <botan/cvc_cert.h> -#include <botan/cvc_key.h> -#include <botan/ecdsa.h> +#include <botan/oids.h> namespace Botan { @@ -58,21 +57,11 @@ void EAC1_1_CVC::force_decode() if(cpi != 0) throw Decoding_Error("EAC1_1 certificate's cpi was not 0"); - // FIXME: PK algos have no notion of EAC encoder/decoder currently -#if 0 - ECDSA_PublicKey tmp_pk; - std::unique_ptr<EAC1_1_CVC_Decoder> dec = tmp_pk.cvc_eac1_1_decoder(); - sig_algo = dec->public_key(enc_pk); + m_pk = decode_eac1_1_key(enc_pk, sig_algo); - - m_pk = tmp_pk; m_chat_val = enc_chat_val[0]; - self_signed = false; - if(m_car.iso_8859() == m_chr.iso_8859()) - { - self_signed= true; - } -#endif + + self_signed = (m_car.iso_8859() == m_chr.iso_8859()); } /* @@ -99,4 +88,48 @@ bool EAC1_1_CVC::operator==(EAC1_1_CVC const& rhs) const && get_concat_sig() == rhs.get_concat_sig()); } +ECDSA_PublicKey* decode_eac1_1_key(const MemoryRegion<byte>&, + AlgorithmIdentifier&) + { + throw Internal_Error("decode_eac1_1_key: Unimplemented"); + return 0; + } + +EAC1_1_CVC make_cvc_cert(PK_Signer& signer, + MemoryRegion<byte> const& public_key, + ASN1_Car const& car, + ASN1_Chr const& chr, + byte holder_auth_templ, + ASN1_Ced ced, + ASN1_Cex cex, + RandomNumberGenerator& rng) + { + OID chat_oid(OIDS::lookup("CertificateHolderAuthorizationTemplate")); + MemoryVector<byte> enc_chat_val; + enc_chat_val.append(holder_auth_templ); + + MemoryVector<byte> enc_cpi; + enc_cpi.append(0x00); + MemoryVector<byte> tbs = DER_Encoder() + .encode(enc_cpi, OCTET_STRING, ASN1_Tag(41), APPLICATION) // cpi + .encode(car) + .raw_bytes(public_key) + .encode(chr) + .start_cons(ASN1_Tag(76), APPLICATION) + .encode(chat_oid) + .encode(enc_chat_val, OCTET_STRING, ASN1_Tag(19), APPLICATION) + .end_cons() + .encode(ced) + .encode(cex) + .get_contents(); + + MemoryVector<byte> signed_cert = + EAC1_1_CVC::make_signed(signer, + EAC1_1_CVC::build_cert_body(tbs), + rng); + + DataSource_Memory source(signed_cert); + return EAC1_1_CVC(source); + } + } diff --git a/src/cert/cvc/cvc_cert.h b/src/cert/cvc/cvc_cert.h index ae0c21d7b..12bc41a9c 100644 --- a/src/cert/cvc/cvc_cert.h +++ b/src/cert/cvc/cvc_cert.h @@ -9,14 +9,8 @@ #ifndef BOTAN_CVC_EAC_H__ #define BOTAN_CVC_EAC_H__ -#include <botan/x509_key.h> -#include <botan/pubkey_enums.h> -#include <botan/signed_obj.h> -#include <botan/pubkey.h> -#include <botan/ecdsa.h> -#include <botan/ecdsa_sig.h> -#include <botan/eac_obj.h> #include <botan/cvc_gen_cert.h> +#include <botan/ecdsa.h> #include <string> namespace Botan { @@ -70,7 +64,6 @@ class BOTAN_DLL EAC1_1_CVC : public EAC1_1_gen_CVC<EAC1_1_CVC>//Signed_Object virtual ~EAC1_1_CVC() {} private: void force_decode(); - friend class EAC1_1_CVC_CA; EAC1_1_CVC() {} ASN1_Car m_car; @@ -88,6 +81,34 @@ inline bool operator!=(EAC1_1_CVC const& lhs, EAC1_1_CVC const& rhs) return !(lhs == rhs); } +/** +* Create an arbitrary EAC 1.1 CVC. +* The desired key encoding must be set within the key (if applicable). +* @param signer the signer used to sign the certificate +* @param public_key the DER encoded public key to appear in +* the certificate +* @param car the CAR of the certificate +* @param chr the CHR of the certificate +* @param holder_auth_templ the holder authorization value byte to +* appear in the CHAT of the certificate +* @param ced the CED to appear in the certificate +* @param ced the CEX to appear in the certificate +*/ +EAC1_1_CVC BOTAN_DLL make_cvc_cert(PK_Signer& signer, + const MemoryRegion<byte>& public_key, + ASN1_Car const& car, + ASN1_Chr const& chr, + byte holder_auth_templ, + ASN1_Ced ced, + ASN1_Cex cex, + RandomNumberGenerator& rng); + +/** +* Decode an EAC encoding ECDSA key +*/ +BOTAN_DLL ECDSA_PublicKey* decode_eac1_1_key(const MemoryRegion<byte>& enc_key, + AlgorithmIdentifier& sig_algo); + } #endif diff --git a/src/cert/cvc/cvc_gen_cert.h b/src/cert/cvc/cvc_gen_cert.h index ab6e22ff0..8c3b1b989 100644 --- a/src/cert/cvc/cvc_gen_cert.h +++ b/src/cert/cvc/cvc_gen_cert.h @@ -1,7 +1,7 @@ /* * EAC1_1 general CVC * (C) 2008 Falko Strenzke -* 2008 Jack Lloyd +* 2008-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -9,13 +9,11 @@ #ifndef BOTAN_EAC_CVC_GEN_CERT_H__ #define BOTAN_EAC_CVC_GEN_CERT_H__ -#include <botan/x509_key.h> +#include <botan/eac_obj.h> #include <botan/eac_asn_obj.h> -#include <botan/pubkey_enums.h> -#include <botan/pubkey.h> #include <botan/ecdsa.h> -#include <botan/ecdsa_sig.h> -#include <string> +#include <botan/pubkey.h> +#include <memory> namespace Botan { @@ -23,7 +21,7 @@ namespace Botan { * This class represents TR03110 (EAC) v1.1 generalized CV Certificates */ template<typename Derived> -class BOTAN_DLL EAC1_1_gen_CVC : public EAC1_1_obj<Derived> // CRTP continuation from EAC1_1_obj +class EAC1_1_gen_CVC : public EAC1_1_obj<Derived> // CRTP continuation from EAC1_1_obj { friend class EAC1_1_obj<EAC1_1_gen_CVC>; @@ -78,11 +76,12 @@ class BOTAN_DLL EAC1_1_gen_CVC : public EAC1_1_obj<Derived> // CRTP continuation PK_Signer& signer, const MemoryRegion<byte>& tbs_bits, RandomNumberGenerator& rng); + virtual ~EAC1_1_gen_CVC<Derived>() - {} + { delete m_pk; } protected: - ECDSA_PublicKey m_pk; // public key + ECDSA_PublicKey* m_pk; ASN1_Chr m_chr; bool self_signed; @@ -102,12 +101,13 @@ template<typename Derived> bool EAC1_1_gen_CVC<Derived>::is_self_signed() const return self_signed; } -template<typename Derived> MemoryVector<byte> EAC1_1_gen_CVC<Derived>::make_signed( +template<typename Derived> +MemoryVector<byte> EAC1_1_gen_CVC<Derived>::make_signed( PK_Signer& signer, const MemoryRegion<byte>& tbs_bits, RandomNumberGenerator& rng) // static { - SecureVector<byte> concat_sig = EAC1_1_obj<Derived>::make_signature(signer, tbs_bits, rng); + SecureVector<byte> concat_sig = signer.sign_message(tbs_bits, rng); return DER_Encoder() .start_cons(ASN1_Tag(33), APPLICATION) @@ -117,9 +117,10 @@ template<typename Derived> MemoryVector<byte> EAC1_1_gen_CVC<Derived>::make_sign .get_contents(); } -template<typename Derived> std::unique_ptr<Public_Key> EAC1_1_gen_CVC<Derived>::subject_public_key() const +template<typename Derived> +std::unique_ptr<Public_Key> EAC1_1_gen_CVC<Derived>::subject_public_key() const { - return std::unique_ptr<Public_Key>(new ECDSA_PublicKey(m_pk)); + return std::unique_ptr<Public_Key>(new ECDSA_PublicKey(*m_pk)); } template<typename Derived> SecureVector<byte> EAC1_1_gen_CVC<Derived>::build_cert_body(MemoryRegion<byte> const& tbs) diff --git a/src/cert/cvc/cvc_key.h b/src/cert/cvc/cvc_key.h deleted file mode 100644 index a81660597..000000000 --- a/src/cert/cvc/cvc_key.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -* EAC CVC Public Key -* (C) 2008 FlexSecure Gmbh -* Falko Strenzke -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_EAC1_1_CVC_PUBLIC_KEY_H__ -#define BOTAN_EAC1_1_CVC_PUBLIC_KEY_H__ - -#include <botan/pipe.h> -#include <botan/pk_keys.h> -#include <botan/alg_id.h> - -namespace Botan { - -/** -* This class represents EAC 1.1 CVC public key encoders. -*/ -class BOTAN_DLL EAC1_1_CVC_Encoder - { - public: - /** - * Get the DER encoded CVC public key. - * @param alg_id the algorithm identifier to use in the encoding - * @return the DER encoded public key - */ - virtual MemoryVector<byte> - public_key(const AlgorithmIdentifier& enc) const = 0; - - virtual ~EAC1_1_CVC_Encoder() {} - }; - -/** -* This class represents EAC 1.1 CVC public key decoders. -*/ -class BOTAN_DLL EAC1_1_CVC_Decoder - { - public: - /** - * Decode a CVC public key. - * @param enc the DER encoded public key to decode - * @return the algorithm identifier found in the encoded public key - */ - virtual AlgorithmIdentifier const - public_key(const MemoryRegion<byte>& enc) = 0; - - virtual ~EAC1_1_CVC_Decoder() {} - }; -} - -#endif diff --git a/src/cert/cvc/cvc_req.cpp b/src/cert/cvc/cvc_req.cpp index 6df6157ad..0a33d4dca 100644 --- a/src/cert/cvc/cvc_req.cpp +++ b/src/cert/cvc/cvc_req.cpp @@ -1,19 +1,13 @@ /* (C) 2007 FlexSecure GmbH - 2008 Jack Lloyd + 2008-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ +#include <botan/cvc_req.h> #include <botan/cvc_cert.h> -#include <botan/der_enc.h> #include <botan/ber_dec.h> -#include <botan/pem.h> -#include <botan/parsing.h> -#include <botan/cvc_key.h> -#include <botan/oids.h> -#include <botan/look_pk.h> -#include <botan/cvc_req.h> namespace Botan { @@ -38,13 +32,7 @@ void EAC1_1_Req::force_decode() if(cpi != 0) throw Decoding_Error("EAC1_1 requests cpi was not 0"); - // FIXME: No EAC support in ECDSA -#if 0 - ECDSA_PublicKey tmp_pk; - std::unique_ptr<EAC1_1_CVC_Decoder> dec = tmp_pk.cvc_eac1_1_decoder(); - sig_algo = dec->public_key(enc_pk); - m_pk = tmp_pk; -#endif + m_pk = decode_eac1_1_key(enc_pk, sig_algo); } EAC1_1_Req::EAC1_1_Req(DataSource& in) diff --git a/src/cert/cvc/cvc_req.h b/src/cert/cvc/cvc_req.h index 2abc72c9a..1e8cea7f8 100644 --- a/src/cert/cvc/cvc_req.h +++ b/src/cert/cvc/cvc_req.h @@ -1,6 +1,7 @@ /* * EAC1_1 CVC Request * (C) 2008 Falko Strenzke +* 2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -8,10 +9,7 @@ #ifndef BOTAN_EAC_CVC_REQ_H__ #define BOTAN_EAC_CVC_REQ_H__ -#include <botan/x509_key.h> -#include <botan/pubkey_enums.h> #include <botan/cvc_gen_cert.h> -#include <botan/cvc_req.h> namespace Botan { @@ -21,7 +19,6 @@ namespace Botan { class BOTAN_DLL EAC1_1_Req : public EAC1_1_gen_CVC<EAC1_1_Req> { public: - friend class EAC1_1_Req_CA; friend class EAC1_1_ADO; friend class EAC1_1_obj<EAC1_1_Req>; diff --git a/src/cert/cvc/cvc_self.cpp b/src/cert/cvc/cvc_self.cpp index 1d06acd66..0c765347f 100644 --- a/src/cert/cvc/cvc_self.cpp +++ b/src/cert/cvc/cvc_self.cpp @@ -1,22 +1,16 @@ /* (C) 2007 FlexSecure GmbH - 2008 Jack Lloyd + 2008-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ #include <botan/cvc_self.h> -#include <botan/cvc_cert.h> -#include <botan/cvc_ca.h> -#include <botan/alg_id.h> -#include <botan/cvc_key.h> +#include <botan/ecc_key.h> +#include <botan/point_gfp.h> +#include <botan/time.h> #include <botan/oids.h> -#include <botan/look_pk.h> -#include <botan/cvc_req.h> -#include <botan/cvc_ado.h> -#include <chrono> #include <sstream> -#include <assert.h> namespace Botan { @@ -35,49 +29,73 @@ enum CHAT_values{ FINGERPRINT = 0x01 }; -std::string padding_and_hash_from_oid(OID const& oid) +void encode_eac_bigint(DER_Encoder& der, const BigInt& x, ASN1_Tag tag) { - std::string padding_and_hash = OIDS::lookup(oid); // use the hash - assert(padding_and_hash.substr(0,6) == "ECDSA/"); // can only be ECDSA for now - assert(padding_and_hash.find("/",0) == 5); - padding_and_hash.erase(0, padding_and_hash.find("/",0) + 1); - return padding_and_hash; + der.encode(BigInt::encode_1363(x, x.bytes()), OCTET_STRING, tag); } -std::string fixed_len_seqnr(u32bit seqnr, u32bit len) +MemoryVector<byte> eac_1_1_encoding(const EC_PublicKey* key, + const OID& sig_algo) { - std::stringstream ss; - std::string result; - ss << seqnr; - ss >> result; - if (result.size() > len) - { - throw Invalid_Argument("fixed_len_seqnr(): number too high to be encoded in provided length"); - } - while (result.size() < len) + if(key->domain_format() == EC_DOMPAR_ENC_OID) + throw Encoding_Error("CVC encoder: cannot encode parameters by OID"); + + const EC_Domain_Params& domain = key->domain(); + + // This is why we can't have nice things + + DER_Encoder enc; + enc.start_cons(ASN1_Tag(73), APPLICATION) + .encode(sig_algo); + + if(key->domain_format() == EC_DOMPAR_ENC_EXPLICIT) { - result.insert(0,"0"); + encode_eac_bigint(enc, domain.get_curve().get_p(), ASN1_Tag(1)); + encode_eac_bigint(enc, domain.get_curve().get_a(), ASN1_Tag(2)); + encode_eac_bigint(enc, domain.get_curve().get_b(), ASN1_Tag(3)); + + enc.encode(EC2OSP(domain.get_base_point(), PointGFp::UNCOMPRESSED), + OCTET_STRING, ASN1_Tag(4)); + + encode_eac_bigint(enc, domain.get_order(), ASN1_Tag(4)); } - return result; + + enc.encode(EC2OSP(key->public_point(), PointGFp::UNCOMPRESSED), + OCTET_STRING, ASN1_Tag(6)); + + if(key->domain_format() == EC_DOMPAR_ENC_EXPLICIT) + encode_eac_bigint(enc, domain.get_cofactor(), ASN1_Tag(7)); + + enc.end_cons(); + + return enc.get_contents(); + } + +std::string padding_and_hash_from_oid(OID const& oid) + { + std::string padding_and_hash = OIDS::lookup(oid); // use the hash + + if(padding_and_hash.substr(0,6) != "ECDSA/") + throw Invalid_State("CVC: Can only use ECDSA, not " + padding_and_hash); + + padding_and_hash.erase(0, padding_and_hash.find("/") + 1); + return padding_and_hash; } } -namespace CVC_EAC -{ + +namespace CVC_EAC { EAC1_1_CVC create_self_signed_cert(Private_Key const& key, EAC1_1_CVC_Options const& opt, RandomNumberGenerator& rng) { - // NOTE: we ignore - // the value - // of opt.chr - ECDSA_PrivateKey const* priv_key = dynamic_cast<ECDSA_PrivateKey const*>(&key); + // NOTE: we ignore the value of opt.chr - if (priv_key == 0) - { + const ECDSA_PrivateKey* priv_key = dynamic_cast<const ECDSA_PrivateKey*>(&key); + + if(priv_key == 0) throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type"); - } ASN1_Chr chr(opt.car.value()); @@ -86,19 +104,15 @@ EAC1_1_CVC create_self_signed_cert(Private_Key const& key, sig_algo.oid = OIDS::lookup(priv_key->algo_name() + "/" + padding_and_hash); sig_algo = AlgorithmIdentifier(sig_algo.oid, AlgorithmIdentifier::USE_NULL_PARAM); - std::unique_ptr<Botan::PK_Signer> signer(get_pk_signer(*priv_key, padding_and_hash)); - -#if 0 // FIXME - std::unique_ptr<EAC1_1_CVC_Encoder> enc(priv_key->cvc_eac1_1_encoder()); - MemoryVector<byte> enc_public_key = enc->public_key(sig_algo); -#else - MemoryVector<byte> enc_public_key; -#endif + PK_Signer signer(*priv_key, padding_and_hash); - return EAC1_1_CVC_CA::make_cert(*signer.get(), enc_public_key, - opt.car, chr, opt.holder_auth_templ, - opt.ced, opt.cex, rng); + MemoryVector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid); + return make_cvc_cert(signer, + enc_public_key, + opt.car, chr, + opt.holder_auth_templ, + opt.ced, opt.cex, rng); } EAC1_1_Req create_cvc_req(Private_Key const& key, @@ -117,14 +131,9 @@ EAC1_1_Req create_cvc_req(Private_Key const& key, sig_algo.oid = OIDS::lookup(priv_key->algo_name() + "/" + padding_and_hash); sig_algo = AlgorithmIdentifier(sig_algo.oid, AlgorithmIdentifier::USE_NULL_PARAM); - std::unique_ptr<Botan::PK_Signer> signer(get_pk_signer(*priv_key, padding_and_hash)); + PK_Signer signer(*priv_key, padding_and_hash); -#if 0 // FIXME - std::unique_ptr<EAC1_1_CVC_Encoder> enc(priv_key->cvc_eac1_1_encoder()); - MemoryVector<byte> enc_public_key = enc->public_key(sig_algo); -#else - MemoryVector<byte> enc_public_key; -#endif + MemoryVector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid); MemoryVector<byte> enc_cpi; enc_cpi.append(0x00); @@ -134,7 +143,10 @@ EAC1_1_Req create_cvc_req(Private_Key const& key, .encode(chr) .get_contents(); - MemoryVector<byte> signed_cert = EAC1_1_gen_CVC<EAC1_1_Req>::make_signed(*signer.get(), EAC1_1_gen_CVC<EAC1_1_Req>::build_cert_body(tbs), rng); + MemoryVector<byte> signed_cert = + EAC1_1_gen_CVC<EAC1_1_Req>::make_signed(signer, + EAC1_1_gen_CVC<EAC1_1_Req>::build_cert_body(tbs), + rng); DataSource_Memory source(signed_cert); return EAC1_1_Req(source); @@ -153,9 +165,7 @@ EAC1_1_ADO create_ado_req(Private_Key const& key, } std::string padding_and_hash = padding_and_hash_from_oid(req.signature_algorithm().oid); - - std::unique_ptr<Botan::PK_Signer> signer(get_pk_signer(*priv_key, padding_and_hash)); - + PK_Signer signer(*priv_key, padding_and_hash); SecureVector<byte> tbs_bits = req.BER_encode(); tbs_bits.append(DER_Encoder().encode(car).get_contents()); MemoryVector<byte> signed_cert = EAC1_1_ADO::make_signed(*signer.get(), tbs_bits, rng); @@ -187,7 +197,7 @@ EAC1_1_CVC create_cvca(Private_Key const& key, opts.cex.add_months(cvca_validity_months); opts.holder_auth_templ = (CVCA | (iris * IRIS) | (fingerpr * FINGERPRINT)); opts.hash_alg = hash; - return Botan::CVC_EAC::create_self_signed_cert(*priv_key, opts, rng); + return CVC_EAC::create_self_signed_cert(*priv_key, opts, rng); } @@ -218,25 +228,19 @@ EAC1_1_CVC link_cvca(EAC1_1_CVC const& signer, } AlgorithmIdentifier sig_algo = signer.signature_algorithm(); std::string padding_and_hash = padding_and_hash_from_oid(sig_algo.oid); - std::unique_ptr<Botan::PK_Signer> pk_signer(get_pk_signer(*priv_key, padding_and_hash)); - std::unique_ptr<Public_Key> pk = signee.subject_public_key(); - ECDSA_PublicKey* subj_pk = dynamic_cast<ECDSA_PublicKey*>(pk.get()); + PK_Signer pk_signer(*priv_key, padding_and_hash); + std::auto_ptr<Public_Key> pk = signee.subject_public_key(); + ECDSA_PublicKey* subj_pk = dynamic_cast<ECDSA_PublicKey*>(pk.get()); subj_pk->set_parameter_encoding(EC_DOMPAR_ENC_EXPLICIT); -#if 0 // FIXME - std::unique_ptr<EAC1_1_CVC_Encoder> enc(subj_pk->cvc_eac1_1_encoder()); - MemoryVector<byte> enc_public_key = enc->public_key(sig_algo); -#else - MemoryVector<byte> enc_public_key; -#endif - - return EAC1_1_CVC_CA::make_cert(*pk_signer.get(), enc_public_key, - signer.get_car(), - signee.get_chr(), - signer.get_chat_value(), - ced, - cex, - rng); + MemoryVector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid); + + return make_cvc_cert(pk_signer, enc_public_key, + signer.get_car(), + signee.get_chr(), + signer.get_chat_value(), + ced, cex, + rng); } EAC1_1_CVC sign_request(EAC1_1_CVC const& signer_cert, @@ -255,11 +259,11 @@ EAC1_1_CVC sign_request(EAC1_1_CVC const& signer_cert, throw Invalid_Argument("CVC_EAC::create_self_signed_cert(): unsupported key type"); } std::string chr_str = signee.get_chr().value(); - chr_str.append(fixed_len_seqnr(seqnr, seqnr_len)); + chr_str += to_string(seqnr, seqnr_len); ASN1_Chr chr(chr_str); std::string padding_and_hash = padding_and_hash_from_oid(signee.signature_algorithm().oid); - std::unique_ptr<Botan::PK_Signer> pk_signer(get_pk_signer(*priv_key, padding_and_hash)); - std::unique_ptr<Public_Key> pk = signee.subject_public_key(); + PK_Signer pk_signer(*priv_key, padding_and_hash); + std::auto_ptr<Public_Key> pk = signee.subject_public_key(); ECDSA_PublicKey* subj_pk = dynamic_cast<ECDSA_PublicKey*>(pk.get()); std::unique_ptr<Public_Key> signer_pk = signer_cert.subject_public_key(); @@ -269,13 +273,6 @@ EAC1_1_CVC sign_request(EAC1_1_CVC const& signer_cert, subj_pk->set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA); -#if 0 // FIXME - std::unique_ptr<EAC1_1_CVC_Encoder> enc(subj_pk->cvc_eac1_1_encoder()); - MemoryVector<byte> enc_public_key = enc->public_key(sig_algo); -#else - MemoryVector<byte> enc_public_key; -#endif - AlgorithmIdentifier sig_algo(signer_cert.signature_algorithm()); ASN1_Ced ced(std::chrono::system_clock::now()); @@ -288,13 +285,9 @@ EAC1_1_CVC sign_request(EAC1_1_CVC const& signer_cert, // we sign a dvca cex.add_months(dvca_validity_months); if (domestic) - { chat_val = DVCA_domestic | chat_low; - } else - { chat_val = DVCA_foreign | chat_low; - } } else if ((signer_cert.get_chat_value() & DVCA_domestic) == DVCA_domestic || (signer_cert.get_chat_value() & DVCA_foreign) == DVCA_foreign) @@ -307,13 +300,16 @@ EAC1_1_CVC sign_request(EAC1_1_CVC const& signer_cert, throw Invalid_Argument("sign_request(): encountered illegal value for CHAT"); // (IS cannot sign certificates) } - return EAC1_1_CVC_CA::make_cert(*pk_signer.get(), enc_public_key, - ASN1_Car(signer_cert.get_chr().iso_8859()), - chr, - chat_val, - ced, - cex, - rng); + + MemoryVector<byte> enc_public_key = eac_1_1_encoding(priv_key, sig_algo.oid); + + return make_cvc_cert(pk_signer, enc_public_key, + ASN1_Car(signer_cert.get_chr().iso_8859()), + chr, + chat_val, + ced, + cex, + rng); } EAC1_1_Req create_cvc_req(Private_Key const& prkey, @@ -328,7 +324,7 @@ EAC1_1_Req create_cvc_req(Private_Key const& prkey, } ECDSA_PrivateKey key(*priv_key); key.set_parameter_encoding(EC_DOMPAR_ENC_IMPLICITCA); - return Botan::CVC_EAC::create_cvc_req(key, chr, hash_alg, rng); + return CVC_EAC::create_cvc_req(key, chr, hash_alg, rng); } } // namespace DE_EAC diff --git a/src/cert/cvc/eac_asn_obj.h b/src/cert/cvc/eac_asn_obj.h index 79802951c..3ab57d7e4 100644 --- a/src/cert/cvc/eac_asn_obj.h +++ b/src/cert/cvc/eac_asn_obj.h @@ -1,7 +1,7 @@ /* * EAC ASN.1 Objects * (C) 2007-2008 FlexSecure GmbH -* 2008-2009 Jack Lloyd +* 2008-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -10,9 +10,6 @@ #define BOTAN_EAC_ASN1_OBJ_H__ #include <botan/asn1_obj.h> -#include <vector> -#include <map> -#include <chrono> namespace Botan { diff --git a/src/cert/cvc/eac_obj.h b/src/cert/cvc/eac_obj.h index 419929a19..66752b10c 100644 --- a/src/cert/cvc/eac_obj.h +++ b/src/cert/cvc/eac_obj.h @@ -8,17 +8,8 @@ #ifndef BOTAN_EAC_OBJ_H__ #define BOTAN_EAC_OBJ_H__ -#include <botan/pubkey.h> -#include <botan/x509_key.h> #include <botan/signed_obj.h> -#include <botan/pubkey_enums.h> -#include <botan/pubkey.h> -#include <botan/parsing.h> -#include <botan/pem.h> -#include <botan/oids.h> -#include <botan/look_pk.h> #include <botan/ecdsa_sig.h> -#include <string> namespace Botan { @@ -26,103 +17,38 @@ namespace Botan { * TR03110 v1.1 EAC CV Certificate */ template<typename Derived> // CRTP is used enable the call sequence: -class BOTAN_DLL EAC1_1_obj : public EAC_Signed_Object +class EAC1_1_obj : public EAC_Signed_Object { - // data members first: - protected: - - ECDSA_Signature m_sig; - - // member functions here: public: /** * Return the signature as a concatenation of the encoded parts. * @result the concatenated signature */ - SecureVector<byte> get_concat_sig() const; + SecureVector<byte> get_concat_sig() const + { return m_sig.get_concatenation(); } - /** - * Verify the signature of this objects. - * @param pub_key the public key to verify the signature with - * @result true if the verification succeeded - */ - virtual bool check_signature(Public_Key& pub_key) const; + bool check_signature(class Public_Key& key) const + { + return EAC_Signed_Object::check_signature(key, m_sig.DER_encode()); + } protected: - void init(DataSource& in); - - static SecureVector<byte> make_signature(PK_Signer& signer, - const MemoryRegion<byte>& tbs_bits, - RandomNumberGenerator& rng); - - virtual ~EAC1_1_obj<Derived>(){} - - }; - -template<typename Derived> SecureVector<byte> EAC1_1_obj<Derived>::get_concat_sig() const - { - return m_sig.get_concatenation(); - } - -template<typename Derived> SecureVector<byte> -EAC1_1_obj<Derived>::make_signature(PK_Signer& signer, - const MemoryRegion<byte>& tbs_bits, - RandomNumberGenerator& rng) - { - // this is the signature as a der sequence - SecureVector<byte> seq_sig = signer.sign_message(tbs_bits, rng); - - ECDSA_Signature sig(decode_seq(seq_sig)); - SecureVector<byte> concat_sig(sig.get_concatenation()); - return concat_sig; - } - -template<typename Derived> -void EAC1_1_obj<Derived>::init(DataSource& in) - { - try - { - Derived::decode_info(in, tbs_bits, m_sig); - } - catch(Decoding_Error) - { - throw Decoding_Error(PEM_label_pref + " decoding failed"); - } - } - -template<typename Derived> -bool EAC1_1_obj<Derived>::check_signature(Public_Key& pub_key) const - { - try - { - std::vector<std::string> sig_info = - split_on(OIDS::lookup(sig_algo.oid), '/'); + ECDSA_Signature m_sig; - if(sig_info.size() != 2 || sig_info[0] != pub_key.algo_name()) + void init(DataSource& in) { - return false; + try + { + Derived::decode_info(in, tbs_bits, m_sig); + } + catch(Decoding_Error) + { + throw Decoding_Error(PEM_label_pref + " decoding failed"); + } } - std::string padding = sig_info[1]; - Signature_Format format = - (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363; - - if(!dynamic_cast<PK_Verifying_wo_MR_Key*>(&pub_key)) - return false; - - std::unique_ptr<ECDSA_Signature_Encoder> enc(new ECDSA_Signature_Encoder(&m_sig)); - SecureVector<byte> seq_sig = enc->signature_bits(); - SecureVector<byte> to_sign = tbs_data(); - - PK_Verifying_wo_MR_Key& sig_key = dynamic_cast<PK_Verifying_wo_MR_Key&>(pub_key); - std::unique_ptr<PK_Verifier> verifier(get_pk_verifier(sig_key, padding, format)); - return verifier->verify_message(to_sign, seq_sig); - } - catch(...) - { - return false; - } - } + virtual ~EAC1_1_obj<Derived>(){} + }; } diff --git a/src/cert/cvc/ecdsa_sig.cpp b/src/cert/cvc/ecdsa_sig.cpp index 1a60f7aa8..e003bb369 100644 --- a/src/cert/cvc/ecdsa_sig.cpp +++ b/src/cert/cvc/ecdsa_sig.cpp @@ -1,31 +1,36 @@ +/* +* ECDSA Signature +* (C) 2007 Falko Strenzke, FlexSecure GmbH +* (C) 2008-2010 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ #include <botan/ecdsa_sig.h> -#include <memory> namespace Botan { -ECDSA_Signature::ECDSA_Signature(const BigInt& r, const BigInt& s) - : m_r(r), - m_s(s) - {} - -ECDSA_Signature::ECDSA_Signature(const ECDSA_Signature& other) - : m_r(other.m_r), m_s(other.m_s) - {} - -ECDSA_Signature const& ECDSA_Signature::operator=(const ECDSA_Signature& other) +ECDSA_Signature::ECDSA_Signature(const MemoryRegion<byte>& ber) { - m_r = other.m_r; - m_s = other.m_s; - return *this; + BER_Decoder(ber) + .start_cons(SEQUENCE) + .decode(m_r) + .decode(m_s) + .end_cons() + .verify_end(); } -bool operator==(const ECDSA_Signature& lhs, const ECDSA_Signature& rhs) +MemoryVector<byte> ECDSA_Signature::DER_encode() const { - return (lhs.get_r() == rhs.get_r() && lhs.get_s() == rhs.get_s()); + return DER_Encoder() + .start_cons(SEQUENCE) + .encode(get_r()) + .encode(get_s()) + .end_cons() + .get_contents(); } -SecureVector<byte> const ECDSA_Signature::get_concatenation() const +MemoryVector<byte> ECDSA_Signature::get_concatenation() const { u32bit enc_len = m_r > m_s ? m_r.bytes() : m_s.bytes(); // use the larger @@ -37,16 +42,7 @@ SecureVector<byte> const ECDSA_Signature::get_concatenation() const return result; } -ECDSA_Signature const decode_seq(MemoryRegion<byte> const& seq) - { - ECDSA_Signature sig; - - std::unique_ptr<ECDSA_Signature_Decoder> dec(new ECDSA_Signature_Decoder(&sig)); - dec->signature_bits(seq); - return sig; - } - -ECDSA_Signature const decode_concatenation(MemoryRegion<byte> const& concat) +ECDSA_Signature decode_concatenation(const MemoryRegion<byte>& concat) { if(concat.size() % 2 != 0) throw Invalid_Argument("Erroneous length of signature"); diff --git a/src/cert/cvc/ecdsa_sig.h b/src/cert/cvc/ecdsa_sig.h index 15015c76d..1397a92b1 100644 --- a/src/cert/cvc/ecdsa_sig.h +++ b/src/cert/cvc/ecdsa_sig.h @@ -1,7 +1,7 @@ /* -* ECDSA +* ECDSA Signature * (C) 2007 Falko Strenzke, FlexSecure GmbH -* (C) 2008 Jack Lloyd +* (C) 2008-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -21,9 +21,10 @@ class BOTAN_DLL ECDSA_Signature friend class ECDSA_Signature_Decoder; ECDSA_Signature() {} - ECDSA_Signature(const BigInt& r, const BigInt& s); - ECDSA_Signature(ECDSA_Signature const& other); - ECDSA_Signature const& operator=(ECDSA_Signature const& other); + ECDSA_Signature(const BigInt& r, const BigInt& s) : + m_r(r), m_s(s) {} + + ECDSA_Signature(const MemoryRegion<byte>& ber); const BigInt& get_r() const { return m_r; } const BigInt& get_s() const { return m_s; } @@ -31,57 +32,26 @@ class BOTAN_DLL ECDSA_Signature /** * return the r||s */ - SecureVector<byte> const get_concatenation() const; + MemoryVector<byte> get_concatenation() const; + + MemoryVector<byte> DER_encode() const; + + bool operator==(const ECDSA_Signature& other) const + { + return (get_r() == other.get_r() && get_s() == other.get_s()); + } + private: BigInt m_r; BigInt m_s; }; -/* Equality of ECDSA_Signature */ -bool operator==(const ECDSA_Signature& lhs, const ECDSA_Signature& rhs); inline bool operator!=(const ECDSA_Signature& lhs, const ECDSA_Signature& rhs) { return !(lhs == rhs); } -class BOTAN_DLL ECDSA_Signature_Decoder - { - public: - void signature_bits(const MemoryRegion<byte>& bits) - { - BER_Decoder(bits) - .start_cons(SEQUENCE) - .decode(m_signature->m_r) - .decode(m_signature->m_s) - .verify_end() - .end_cons(); - } - ECDSA_Signature_Decoder(ECDSA_Signature* signature) : m_signature(signature) - {} - private: - ECDSA_Signature* m_signature; - }; - -class BOTAN_DLL ECDSA_Signature_Encoder - { - public: - MemoryVector<byte> signature_bits() const - { - return DER_Encoder() - .start_cons(SEQUENCE) - .encode(m_signature->get_r()) - .encode(m_signature->get_s()) - .end_cons() - .get_contents(); - } - ECDSA_Signature_Encoder(const ECDSA_Signature* signature) : m_signature(signature) - {} - private: - const ECDSA_Signature* m_signature; - }; - -ECDSA_Signature const decode_seq(MemoryRegion<byte> const& seq); -ECDSA_Signature const decode_concatenation(MemoryRegion<byte> const& concatenation); +ECDSA_Signature decode_concatenation(const MemoryRegion<byte>& concatenation); } diff --git a/src/cert/cvc/info.txt b/src/cert/cvc/info.txt index 285838379..91de3bc19 100644 --- a/src/cert/cvc/info.txt +++ b/src/cert/cvc/info.txt @@ -3,10 +3,8 @@ load_on auto <header:public> cvc_ado.h -cvc_ca.h cvc_cert.h cvc_gen_cert.h -cvc_key.h cvc_req.h cvc_self.h eac_asn_obj.h @@ -20,7 +18,6 @@ asn1_eac_str.cpp asn1_eac_tm.cpp ecdsa_sig.cpp cvc_ado.cpp -cvc_ca.cpp cvc_cert.cpp cvc_req.cpp cvc_self.cpp @@ -35,7 +32,6 @@ filters libstate oid_lookup pem -pk_codecs pubkey x509 </requires> diff --git a/src/cert/cvc/signed_obj.cpp b/src/cert/cvc/signed_obj.cpp index 4a08ed0ac..d6aa2f02b 100644 --- a/src/cert/cvc/signed_obj.cpp +++ b/src/cert/cvc/signed_obj.cpp @@ -1,12 +1,15 @@ /* -* X.509 SIGNED Object -* (C) 1999-2007 Jack Lloyd +* EAC SIGNED Object +* (C) 1999-2010 Jack Lloyd * 2007 FlexSecure GmbH * * Distributed under the terms of the Botan license */ #include <botan/signed_obj.h> +#include <botan/pubkey.h> +#include <botan/oids.h> +#include <memory> namespace Botan { @@ -42,6 +45,34 @@ AlgorithmIdentifier EAC_Signed_Object::signature_algorithm() const return sig_algo; } +bool EAC_Signed_Object::check_signature(Public_Key& pub_key, + const MemoryRegion<byte>& sig) const + { + try + { + std::vector<std::string> sig_info = + split_on(OIDS::lookup(sig_algo.oid), '/'); + + if(sig_info.size() != 2 || sig_info[0] != pub_key.algo_name()) + { + return false; + } + + std::string padding = sig_info[1]; + Signature_Format format = + (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363; + + SecureVector<byte> to_sign = tbs_data(); + + PK_Verifier verifier(pub_key, padding, format); + return verifier.verify_message(to_sign, sig); + } + catch(...) + { + return false; + } + } + /* * Try to decode the actual information */ @@ -53,14 +84,12 @@ void EAC_Signed_Object::do_decode() catch(Decoding_Error& e) { const std::string what = e.what(); - throw Decoding_Error(PEM_label_pref + " decoding failed (" + - what.substr(23, std::string::npos) + ")"); + throw Decoding_Error(PEM_label_pref + " decoding failed (" + what + ")"); } catch(Invalid_Argument& e) { const std::string what = e.what(); - throw Decoding_Error(PEM_label_pref + " decoding failed (" + - what.substr(7, std::string::npos) + ")"); + throw Decoding_Error(PEM_label_pref + " decoding failed (" + what + ")"); } } diff --git a/src/cert/cvc/signed_obj.h b/src/cert/cvc/signed_obj.h index 17b75a08a..0e7dd6bdb 100644 --- a/src/cert/cvc/signed_obj.h +++ b/src/cert/cvc/signed_obj.h @@ -53,7 +53,8 @@ class BOTAN_DLL EAC_Signed_Object * @return true if the signature was created by the private key * associated with this public key */ - virtual bool check_signature(class Public_Key&) const = 0; + bool check_signature(class Public_Key& key, + const MemoryRegion<byte>& sig) const; /** * Write this object DER encoded into a specified pipe. diff --git a/src/cert/x509/info.txt b/src/cert/x509/info.txt index a5cd973a4..510163e69 100644 --- a/src/cert/x509/info.txt +++ b/src/cert/x509/info.txt @@ -39,7 +39,6 @@ filters libstate oid_lookup pem -pk_codecs pubkey rng sha1 diff --git a/src/cert/x509/x509_ca.cpp b/src/cert/x509/x509_ca.cpp index 59a5bbaf8..3eb7ff77e 100644 --- a/src/cert/x509/x509_ca.cpp +++ b/src/cert/x509/x509_ca.cpp @@ -7,12 +7,12 @@ #include <botan/x509_ca.h> #include <botan/x509stor.h> +#include <botan/pubkey.h> #include <botan/der_enc.h> #include <botan/ber_dec.h> #include <botan/bigint.h> #include <botan/parsing.h> #include <botan/lookup.h> -#include <botan/look_pk.h> #include <botan/oids.h> #include <memory> #include <set> @@ -26,10 +26,6 @@ X509_CA::X509_CA(const X509_Certificate& c, const Private_Key& key, const std::string& hash_fn) : cert(c) { - // Use pointer dynamic_cast to avoid exception if cast fails - if(!dynamic_cast<const PK_Signing_Key*>(&key)) - throw Invalid_Argument("X509_CA: " + key.algo_name() + " cannot sign"); - if(!cert.is_CA_cert()) throw Invalid_Argument("X509_CA: This certificate is not for a CA"); @@ -270,17 +266,9 @@ PK_Signer* choose_sig_format(const Private_Key& key, padding = padding + '(' + proto_hash->name() + ')'; sig_algo.oid = OIDS::lookup(algo_name + "/" + padding); + sig_algo.parameters = key.algorithm_identifier().parameters; - std::unique_ptr<X509_Encoder> encoding(key.x509_encoder()); - if(!encoding.get()) - throw Encoding_Error("Key " + algo_name + " does not support " - "X.509 encoding"); - - sig_algo.parameters = encoding->alg_id().parameters; - - const PK_Signing_Key& sig_key = dynamic_cast<const PK_Signing_Key&>(key); - - return get_pk_signer(sig_key, padding, format); + return new PK_Signer(key, padding, format); } } diff --git a/src/cert/x509/x509_obj.cpp b/src/cert/x509/x509_obj.cpp index 95a1c1cca..820972614 100644 --- a/src/cert/x509/x509_obj.cpp +++ b/src/cert/x509/x509_obj.cpp @@ -7,7 +7,7 @@ #include <botan/x509_obj.h> #include <botan/x509_key.h> -#include <botan/look_pk.h> +#include <botan/pubkey.h> #include <botan/oids.h> #include <botan/der_enc.h> #include <botan/ber_dec.h> @@ -168,24 +168,9 @@ bool X509_Object::check_signature(Public_Key& pub_key) const Signature_Format format = (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363; - std::unique_ptr<PK_Verifier> verifier; + PK_Verifier verifier(pub_key, padding, format); - if(dynamic_cast<PK_Verifying_with_MR_Key*>(&pub_key)) - { - PK_Verifying_with_MR_Key& sig_key = - dynamic_cast<PK_Verifying_with_MR_Key&>(pub_key); - verifier.reset(get_pk_verifier(sig_key, padding, format)); - } - else if(dynamic_cast<PK_Verifying_wo_MR_Key*>(&pub_key)) - { - PK_Verifying_wo_MR_Key& sig_key = - dynamic_cast<PK_Verifying_wo_MR_Key&>(pub_key); - verifier.reset(get_pk_verifier(sig_key, padding, format)); - } - else - return false; - - return verifier->verify_message(tbs_data(), signature()); + return verifier.verify_message(tbs_data(), signature()); } catch(...) { diff --git a/src/cert/x509/x509self.cpp b/src/cert/x509/x509self.cpp index df31897bb..1f647f8bb 100644 --- a/src/cert/x509/x509self.cpp +++ b/src/cert/x509/x509self.cpp @@ -9,7 +9,6 @@ #include <botan/x509_ext.h> #include <botan/x509_ca.h> #include <botan/der_enc.h> -#include <botan/look_pk.h> #include <botan/oids.h> #include <botan/pipe.h> #include <memory> @@ -24,10 +23,6 @@ namespace { MemoryVector<byte> shared_setup(const X509_Cert_Options& opts, const Private_Key& key) { - const Private_Key* key_pointer = &key; - if(!dynamic_cast<const PK_Signing_Key*>(key_pointer)) - throw Invalid_Argument("Key type " + key.algo_name() + " cannot sign"); - opts.sanity_check(); Pipe key_encoder; diff --git a/src/cert/x509/x509stor.cpp b/src/cert/x509/x509stor.cpp index 80507c1dd..6b2c0eee0 100644 --- a/src/cert/x509/x509stor.cpp +++ b/src/cert/x509/x509stor.cpp @@ -8,7 +8,6 @@ #include <botan/x509stor.h> #include <botan/parsing.h> #include <botan/pubkey.h> -#include <botan/look_pk.h> #include <botan/oids.h> #include <algorithm> #include <chrono> @@ -384,7 +383,6 @@ X509_Code X509_Store::check_sig(const Cert_Info& cert_info, X509_Code X509_Store::check_sig(const X509_Object& object, Public_Key* key) { std::unique_ptr<Public_Key> pub_key(key); - std::unique_ptr<PK_Verifier> verifier; try { std::vector<std::string> sig_info = @@ -398,29 +396,17 @@ X509_Code X509_Store::check_sig(const X509_Object& object, Public_Key* key) if(key->message_parts() >= 2) format = DER_SEQUENCE; else format = IEEE_1363; - if(dynamic_cast<PK_Verifying_with_MR_Key*>(pub_key.get())) - { - PK_Verifying_with_MR_Key* sig_key = - dynamic_cast<PK_Verifying_with_MR_Key*>(pub_key.get()); - verifier.reset(get_pk_verifier(*sig_key, padding, format)); - } - else if(dynamic_cast<PK_Verifying_wo_MR_Key*>(pub_key.get())) - { - PK_Verifying_wo_MR_Key* sig_key = - dynamic_cast<PK_Verifying_wo_MR_Key*>(pub_key.get()); - verifier.reset(get_pk_verifier(*sig_key, padding, format)); - } - else - return CA_CERT_CANNOT_SIGN; + PK_Verifier verifier(*pub_key.get(), padding, format); - bool valid = verifier->verify_message(object.tbs_data(), - object.signature()); + bool valid = verifier.verify_message(object.tbs_data(), + object.signature()); if(valid) return VERIFIED; else return SIGNATURE_ERROR; } + catch(Lookup_Error) { return CA_CERT_CANNOT_SIGN; } catch(Decoding_Error) { return CERT_FORMAT_ERROR; } catch(Exception) {} diff --git a/src/cms/cms_dalg.cpp b/src/cms/cms_dalg.cpp index 8d559f9a9..2a380b596 100644 --- a/src/cms/cms_dalg.cpp +++ b/src/cms/cms_dalg.cpp @@ -10,7 +10,6 @@ #include <botan/ber_dec.h> #include <botan/oids.h> #include <botan/hash.h> -#include <botan/look_pk.h> #include <botan/bigint.h> #include <botan/libstate.h> #include <memory> diff --git a/src/cms/cms_ealg.cpp b/src/cms/cms_ealg.cpp index 60479a820..3ddf8a39e 100644 --- a/src/cms/cms_ealg.cpp +++ b/src/cms/cms_ealg.cpp @@ -6,15 +6,15 @@ */ #include <botan/cms_enc.h> -#include <botan/der_enc.h> -#include <botan/x509find.h> #include <botan/bigint.h> -#include <botan/oids.h> #include <botan/cbc.h> +#include <botan/der_enc.h> #include <botan/hash.h> -#include <botan/look_pk.h> #include <botan/libstate.h> +#include <botan/oids.h> #include <botan/pipe.h> +#include <botan/pubkey.h> +#include <botan/x509find.h> #include <memory> namespace Botan { @@ -107,12 +107,7 @@ void CMS_Encoder::encrypt(RandomNumberGenerator& rng, if(constraints != NO_CONSTRAINTS && !(constraints & KEY_ENCIPHERMENT)) throw Invalid_Argument("CMS: Constraints not set for encryption"); - PK_Encrypting_Key* enc_key = dynamic_cast<PK_Encrypting_Key*>(key.get()); - if(enc_key == 0) - throw Internal_Error("CMS_Encoder::encrypt: " + algo + - " can't encrypt"); - - encrypt_ktri(rng, to, enc_key, cipher); + encrypt_ktri(rng, to, key.get(), cipher); } else if(algo == "DH") { @@ -130,12 +125,13 @@ void CMS_Encoder::encrypt(RandomNumberGenerator& rng, */ void CMS_Encoder::encrypt_ktri(RandomNumberGenerator& rng, const X509_Certificate& to, - PK_Encrypting_Key* pub_key, + Public_Key* pub_key, const std::string& cipher) { const std::string padding = "EME-PKCS1-v1_5"; const std::string pk_algo = pub_key->algo_name(); - std::auto_ptr<PK_Encryptor> enc(get_pk_encryptor(*pub_key, padding)); + + PK_Encryptor_EME encryptor(*pub_key, padding); SymmetricKey cek = setup_key(rng, cipher); @@ -151,7 +147,7 @@ void CMS_Encoder::encrypt_ktri(RandomNumberGenerator& rng, .encode((u32bit)0); encode_si(encoder, to) .encode(alg_id) - .encode(enc->encrypt(cek.bits_of(), rng), OCTET_STRING) + .encode(encryptor.encrypt(cek.bits_of(), rng), OCTET_STRING) .end_cons() .end_cons() .raw_bytes(do_encrypt(rng, cek, cipher)) @@ -295,18 +291,16 @@ void CMS_Encoder::sign(const X509_Certificate& cert, { std::string padding = pad_algo + "(" + hash + ")"; - // FIXME: Add new get_format() func to PK_Signing_Key, PK_Verifying_*_Key Signature_Format format = IEEE_1363; - const PK_Signing_Key& sig_key = dynamic_cast<const PK_Signing_Key&>(key); - std::auto_ptr<PK_Signer> signer(get_pk_signer(sig_key, padding, format)); + PK_Signer signer(key, padding, format); AlgorithmIdentifier sig_algo(OIDS::lookup(key.algo_name() + "/" + padding), AlgorithmIdentifier::USE_NULL_PARAM); SecureVector<byte> signed_attr = encode_attr(data, type, hash); - signer->update(signed_attr); - SecureVector<byte> signature = signer->signature(rng); + signer.update(signed_attr); + SecureVector<byte> signature = signer.signature(rng); signed_attr[0] = 0xA0; const u32bit SI_VERSION = cert.subject_key_id().size() ? 3 : 1; diff --git a/src/cms/cms_enc.h b/src/cms/cms_enc.h index b1e18ef7d..ec2fdf3b3 100644 --- a/src/cms/cms_enc.h +++ b/src/cms/cms_enc.h @@ -59,7 +59,7 @@ class BOTAN_DLL CMS_Encoder void add_layer(const std::string&, DER_Encoder&); void encrypt_ktri(RandomNumberGenerator&, - const X509_Certificate&, PK_Encrypting_Key*, + const X509_Certificate&, Public_Key*, const std::string&); void encrypt_kari(RandomNumberGenerator&, const X509_Certificate&, Public_Key*, diff --git a/src/cms/info.txt b/src/cms/info.txt index 44c5811f8..b863a9a26 100644 --- a/src/cms/info.txt +++ b/src/cms/info.txt @@ -9,7 +9,7 @@ hash libstate oid_lookup pem -pk_codecs +pubkey sha1 sym_algo x509 diff --git a/src/engine/def_engine/def_pk_ops.cpp b/src/engine/def_engine/def_pk_ops.cpp index e1040142e..d3264e67e 100644 --- a/src/engine/def_engine/def_pk_ops.cpp +++ b/src/engine/def_engine/def_pk_ops.cpp @@ -1,89 +1,170 @@ /* * PK Operations -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ #include <botan/internal/default_engine.h> -#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY) - #include <botan/if_op.h> +#if defined(BOTAN_HAS_RSA) + #include <botan/rsa.h> +#endif + +#if defined(BOTAN_HAS_RW) + #include <botan/rw.h> #endif #if defined(BOTAN_HAS_DSA) - #include <botan/dsa_op.h> + #include <botan/dsa.h> #endif -#if defined(BOTAN_HAS_NYBERG_RUEPPEL) - #include <botan/nr_op.h> +#if defined(BOTAN_HAS_ECDSA) + #include <botan/ecdsa.h> #endif #if defined(BOTAN_HAS_ELGAMAL) - #include <botan/elg_op.h> + #include <botan/elgamal.h> +#endif + +#if defined(BOTAN_HAS_GOST_3410_2001) + #include <botan/gost_3410.h> +#endif + +#if defined(BOTAN_HAS_NYBERG_RUEPPEL) + #include <botan/nr.h> #endif #if defined(BOTAN_HAS_DIFFIE_HELLMAN) - #include <botan/dh_op.h> + #include <botan/dh.h> +#endif + +#if defined(BOTAN_HAS_ECDH) + #include <botan/ecdh.h> #endif namespace Botan { -#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY) -/* -* Acquire an IF op -*/ -IF_Operation* Default_Engine::if_op(const BigInt& e, const BigInt& n, - const BigInt& d, const BigInt& p, - const BigInt& q, const BigInt& d1, - const BigInt& d2, const BigInt& c) const +PK_Ops::Encryption* +Default_Engine::get_encryption_op(const Public_Key& key) const { - return new Default_IF_Op(e, n, d, p, q, d1, d2, c); - } +#if defined(BOTAN_HAS_RSA) + if(const RSA_PublicKey* s = dynamic_cast<const RSA_PublicKey*>(&key)) + return new RSA_Public_Operation(*s); #endif -#if defined(BOTAN_HAS_DSA) -/* -* Acquire a DSA op -*/ -DSA_Operation* Default_Engine::dsa_op(const DL_Group& group, const BigInt& y, - const BigInt& x) const - { - return new Default_DSA_Op(group, y, x); - } +#if defined(BOTAN_HAS_ELGAMAL) + if(const ElGamal_PublicKey* s = dynamic_cast<const ElGamal_PublicKey*>(&key)) + return new ElGamal_Encryption_Operation(*s); #endif -#if defined(BOTAN_HAS_NYBERG_RUEPPEL) -/* -* Acquire a NR op -*/ -NR_Operation* Default_Engine::nr_op(const DL_Group& group, const BigInt& y, - const BigInt& x) const - { - return new Default_NR_Op(group, y, x); + return 0; } + +PK_Ops::Decryption* +Default_Engine::get_decryption_op(const Private_Key& key) const + { +#if defined(BOTAN_HAS_RSA) + if(const RSA_PrivateKey* s = dynamic_cast<const RSA_PrivateKey*>(&key)) + return new RSA_Private_Operation(*s); #endif #if defined(BOTAN_HAS_ELGAMAL) -/* -* Acquire an ElGamal op -*/ -ELG_Operation* Default_Engine::elg_op(const DL_Group& group, const BigInt& y, - const BigInt& x) const - { - return new Default_ELG_Op(group, y, x); - } + if(const ElGamal_PrivateKey* s = dynamic_cast<const ElGamal_PrivateKey*>(&key)) + return new ElGamal_Decryption_Operation(*s); #endif + return 0; + } + +PK_Ops::Key_Agreement* +Default_Engine::get_key_agreement_op(const Private_Key& key) const + { #if defined(BOTAN_HAS_DIFFIE_HELLMAN) -/* -* Acquire a DH op -*/ -DH_Operation* Default_Engine::dh_op(const DL_Group& group, - const BigInt& x) const + if(const DH_PrivateKey* dh = dynamic_cast<const DH_PrivateKey*>(&key)) + return new DH_KA_Operation(*dh); +#endif + +#if defined(BOTAN_HAS_ECDH) + if(const ECDH_PrivateKey* ecdh = dynamic_cast<const ECDH_PrivateKey*>(&key)) + return new ECDH_KA_Operation(*ecdh); +#endif + + return 0; + } + +PK_Ops::Signature* +Default_Engine::get_signature_op(const Private_Key& key) const { - return new Default_DH_Op(group, x); +#if defined(BOTAN_HAS_RSA) + if(const RSA_PrivateKey* s = dynamic_cast<const RSA_PrivateKey*>(&key)) + return new RSA_Private_Operation(*s); +#endif + +#if defined(BOTAN_HAS_RW) + if(const RW_PrivateKey* s = dynamic_cast<const RW_PrivateKey*>(&key)) + return new RW_Signature_Operation(*s); +#endif + +#if defined(BOTAN_HAS_DSA) + if(const DSA_PrivateKey* s = dynamic_cast<const DSA_PrivateKey*>(&key)) + return new DSA_Signature_Operation(*s); +#endif + +#if defined(BOTAN_HAS_ECDSA) + if(const ECDSA_PrivateKey* s = dynamic_cast<const ECDSA_PrivateKey*>(&key)) + return new ECDSA_Signature_Operation(*s); +#endif + +#if defined(BOTAN_HAS_GOST_3410_2001) + if(const GOST_3410_PrivateKey* s = + dynamic_cast<const GOST_3410_PrivateKey*>(&key)) + return new GOST_3410_Signature_Operation(*s); +#endif + +#if defined(BOTAN_HAS_NYBERG_RUEPPEL) + if(const NR_PrivateKey* s = dynamic_cast<const NR_PrivateKey*>(&key)) + return new NR_Signature_Operation(*s); +#endif + + return 0; } + +PK_Ops::Verification* +Default_Engine::get_verify_op(const Public_Key& key) const + { +#if defined(BOTAN_HAS_RSA) + if(const RSA_PublicKey* s = dynamic_cast<const RSA_PublicKey*>(&key)) + return new RSA_Public_Operation(*s); +#endif + +#if defined(BOTAN_HAS_RW) + if(const RW_PublicKey* s = dynamic_cast<const RW_PublicKey*>(&key)) + return new RW_Verification_Operation(*s); #endif +#if defined(BOTAN_HAS_DSA) + if(const DSA_PublicKey* s = dynamic_cast<const DSA_PublicKey*>(&key)) + return new DSA_Verification_Operation(*s); +#endif + +#if defined(BOTAN_HAS_ECDSA) + if(const ECDSA_PublicKey* s = dynamic_cast<const ECDSA_PublicKey*>(&key)) + return new ECDSA_Verification_Operation(*s); +#endif + +#if defined(BOTAN_HAS_GOST_3410_2001) + if(const GOST_3410_PublicKey* s = + dynamic_cast<const GOST_3410_PublicKey*>(&key)) + return new GOST_3410_Verification_Operation(*s); +#endif + +#if defined(BOTAN_HAS_NYBERG_RUEPPEL) + if(const NR_PublicKey* s = dynamic_cast<const NR_PublicKey*>(&key)) + return new NR_Verification_Operation(*s); +#endif + + return 0; + } + } diff --git a/src/engine/def_engine/default_engine.h b/src/engine/def_engine/default_engine.h index aa753fadb..1e40cfe46 100644 --- a/src/engine/def_engine/default_engine.h +++ b/src/engine/def_engine/default_engine.h @@ -20,31 +20,19 @@ class Default_Engine : public Engine public: std::string provider_name() const { return "core"; } -#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY) - IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&, - const BigInt&, const BigInt&, const BigInt&, - const BigInt&, const BigInt&) const; -#endif + PK_Ops::Key_Agreement* + get_key_agreement_op(const Private_Key& key) const; -#if defined(BOTAN_HAS_DSA) - DSA_Operation* dsa_op(const DL_Group&, const BigInt&, - const BigInt&) const; -#endif + PK_Ops::Signature* + get_signature_op(const Private_Key& key) const; -#if defined(BOTAN_HAS_NYBERG_RUEPPEL) - NR_Operation* nr_op(const DL_Group&, const BigInt&, const BigInt&) const; -#endif + PK_Ops::Verification* get_verify_op(const Public_Key& key) const; -#if defined(BOTAN_HAS_ELGAMAL) - ELG_Operation* elg_op(const DL_Group&, const BigInt&, - const BigInt&) const; -#endif + PK_Ops::Encryption* get_encryption_op(const Public_Key& key) const; -#if defined(BOTAN_HAS_DIFFIE_HELLMAN) - DH_Operation* dh_op(const DL_Group&, const BigInt&) const; -#endif + PK_Ops::Decryption* get_decryption_op(const Private_Key& key) const; - Modular_Exponentiator* mod_exp(const BigInt&, + Modular_Exponentiator* mod_exp(const BigInt& n, Power_Mod::Usage_Hints) const; virtual bool can_add_algorithms() { return true; } diff --git a/src/engine/engine.h b/src/engine/engine.h index ba5f95c27..69592886c 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -15,30 +15,12 @@ #include <botan/hash.h> #include <botan/mac.h> #include <botan/pow_mod.h> +#include <botan/pk_keys.h> +#include <botan/pk_ops.h> #include <utility> #include <map> -#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY) - #include <botan/if_op.h> -#endif - -#if defined(BOTAN_HAS_DSA) - #include <botan/dsa_op.h> -#endif - -#if defined(BOTAN_HAS_DIFFIE_HELLMAN) - #include <botan/dh_op.h> -#endif - -#if defined(BOTAN_HAS_NYBERG_RUEPPEL) - #include <botan/nr_op.h> -#endif - -#if defined(BOTAN_HAS_ELGAMAL) - #include <botan/elg_op.h> -#endif - namespace Botan { class Algorithm_Factory; @@ -80,35 +62,31 @@ class BOTAN_DLL Engine Algorithm_Factory&) { return 0; } -#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY) - virtual IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&, - const BigInt&, const BigInt&, const BigInt&, - const BigInt&, const BigInt&) const - { return 0; } -#endif - -#if defined(BOTAN_HAS_DSA) - virtual DSA_Operation* dsa_op(const DL_Group&, const BigInt&, - const BigInt&) const - { return 0; } -#endif - -#if defined(BOTAN_HAS_NYBERG_RUEPPEL) - virtual NR_Operation* nr_op(const DL_Group&, const BigInt&, - const BigInt&) const - { return 0; } -#endif - -#if defined(BOTAN_HAS_ELGAMAL) - virtual ELG_Operation* elg_op(const DL_Group&, const BigInt&, - const BigInt&) const - { return 0; } -#endif - -#if defined(BOTAN_HAS_DIFFIE_HELLMAN) - virtual DH_Operation* dh_op(const DL_Group&, const BigInt&) const - { return 0; } -#endif + virtual PK_Ops::Key_Agreement* + get_key_agreement_op(const Private_Key&) const + { + return 0; + } + + virtual PK_Ops::Signature* get_signature_op(const Private_Key&) const + { + return 0; + } + + virtual PK_Ops::Verification* get_verify_op(const Public_Key&) const + { + return 0; + } + + virtual PK_Ops::Encryption* get_encryption_op(const Public_Key&) const + { + return 0; + } + + virtual PK_Ops::Decryption* get_decryption_op(const Private_Key&) const + { + return 0; + } }; } diff --git a/src/engine/gnump/gmp_dh.cpp b/src/engine/gnump/gmp_dh.cpp deleted file mode 100644 index 430530dd3..000000000 --- a/src/engine/gnump/gmp_dh.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* -* GMP Engine -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/gnump_engine.h> -#include <botan/internal/gmp_wrap.h> -#include <gmp.h> - -namespace Botan { - -#if defined(BOTAN_HAS_DIFFIE_HELLMAN) -namespace { - -/* -* GMP DH Operation -*/ -class GMP_DH_Op : public DH_Operation - { - public: - BigInt agree(const BigInt& i) const; - DH_Operation* clone() const { return new GMP_DH_Op(*this); } - - GMP_DH_Op(const DL_Group& group, const BigInt& x_bn) : - x(x_bn), p(group.get_p()) {} - private: - GMP_MPZ x, p; - }; - -/* -* GMP DH Key Agreement Operation -*/ -BigInt GMP_DH_Op::agree(const BigInt& i_bn) const - { - GMP_MPZ i(i_bn); - mpz_powm(i.value, i.value, x.value, p.value); - return i.to_bigint(); - } - -} - -/* -* Acquire a DH op -*/ -DH_Operation* GMP_Engine::dh_op(const DL_Group& group, const BigInt& x) const - { - return new GMP_DH_Op(group, x); - } -#endif - -} diff --git a/src/engine/gnump/gmp_dsa.cpp b/src/engine/gnump/gmp_dsa.cpp deleted file mode 100644 index b350a2075..000000000 --- a/src/engine/gnump/gmp_dsa.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* -* GMP DSA Engine -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/gnump_engine.h> -#include <botan/internal/gmp_wrap.h> -#include <gmp.h> - -namespace Botan { - -#if defined(BOTAN_HAS_DSA) - -namespace { - -/* -* GMP DSA Operation -*/ -class GMP_DSA_Op : public DSA_Operation - { - public: - bool verify(const byte[], u32bit, const byte[], u32bit) const; - SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const; - - DSA_Operation* clone() const { return new GMP_DSA_Op(*this); } - - GMP_DSA_Op(const DL_Group& group, const BigInt& y1, const BigInt& x1) : - x(x1), y(y1), p(group.get_p()), q(group.get_q()), g(group.get_g()) {} - private: - const GMP_MPZ x, y, p, q, g; - }; - -/* -* GMP DSA Verify Operation -*/ -bool GMP_DSA_Op::verify(const byte msg[], u32bit msg_len, - const byte sig[], u32bit sig_len) const - { - const u32bit q_bytes = q.bytes(); - - if(sig_len != 2*q_bytes || msg_len > q_bytes) - return false; - - GMP_MPZ r(sig, q_bytes); - GMP_MPZ s(sig + q_bytes, q_bytes); - GMP_MPZ i(msg, msg_len); - - if(mpz_cmp_ui(r.value, 0) <= 0 || mpz_cmp(r.value, q.value) >= 0) - return false; - if(mpz_cmp_ui(s.value, 0) <= 0 || mpz_cmp(s.value, q.value) >= 0) - return false; - - if(mpz_invert(s.value, s.value, q.value) == 0) - return false; - - GMP_MPZ si; - mpz_mul(si.value, s.value, i.value); - mpz_mod(si.value, si.value, q.value); - mpz_powm(si.value, g.value, si.value, p.value); - - GMP_MPZ sr; - mpz_mul(sr.value, s.value, r.value); - mpz_mod(sr.value, sr.value, q.value); - mpz_powm(sr.value, y.value, sr.value, p.value); - - mpz_mul(si.value, si.value, sr.value); - mpz_mod(si.value, si.value, p.value); - mpz_mod(si.value, si.value, q.value); - - if(mpz_cmp(si.value, r.value) == 0) - return true; - return false; - } - -/* -* GMP DSA Sign Operation -*/ -SecureVector<byte> GMP_DSA_Op::sign(const byte in[], u32bit length, - const BigInt& k_bn) const - { - if(mpz_cmp_ui(x.value, 0) == 0) - throw Internal_Error("GMP_DSA_Op::sign: No private key"); - - GMP_MPZ i(in, length); - GMP_MPZ k(k_bn); - - GMP_MPZ r; - mpz_powm(r.value, g.value, k.value, p.value); - mpz_mod(r.value, r.value, q.value); - - mpz_invert(k.value, k.value, q.value); - - GMP_MPZ s; - mpz_mul(s.value, x.value, r.value); - mpz_add(s.value, s.value, i.value); - mpz_mul(s.value, s.value, k.value); - mpz_mod(s.value, s.value, q.value); - - if(mpz_cmp_ui(r.value, 0) == 0 || mpz_cmp_ui(s.value, 0) == 0) - throw Internal_Error("GMP_DSA_Op::sign: r or s was zero"); - - const u32bit q_bytes = q.bytes(); - - SecureVector<byte> output(2*q_bytes); - r.encode(output, q_bytes); - s.encode(output + q_bytes, q_bytes); - return output; - } - -} - -/* -* Acquire a DSA op -*/ -DSA_Operation* GMP_Engine::dsa_op(const DL_Group& group, const BigInt& y, - const BigInt& x) const - { - return new GMP_DSA_Op(group, y, x); - } -#endif - -} diff --git a/src/engine/gnump/gmp_elg.cpp b/src/engine/gnump/gmp_elg.cpp deleted file mode 100644 index 539804a23..000000000 --- a/src/engine/gnump/gmp_elg.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* -* GMP ElGamal Engine -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/gnump_engine.h> -#include <botan/internal/gmp_wrap.h> -#include <gmp.h> - -namespace Botan { - -#if defined(BOTAN_HAS_ELGAMAL) - -namespace { - -/* -* GMP ElGamal Operation -*/ -class GMP_ELG_Op : public ELG_Operation - { - public: - SecureVector<byte> encrypt(const byte[], u32bit, const BigInt&) const; - BigInt decrypt(const BigInt&, const BigInt&) const; - - ELG_Operation* clone() const { return new GMP_ELG_Op(*this); } - - GMP_ELG_Op(const DL_Group& group, const BigInt& y1, const BigInt& x1) : - x(x1), y(y1), g(group.get_g()), p(group.get_p()) {} - private: - GMP_MPZ x, y, g, p; - }; - -/* -* GMP ElGamal Encrypt Operation -*/ -SecureVector<byte> GMP_ELG_Op::encrypt(const byte in[], u32bit length, - const BigInt& k_bn) const - { - GMP_MPZ i(in, length); - - if(mpz_cmp(i.value, p.value) >= 0) - throw Invalid_Argument("GMP_ELG_Op: Input is too large"); - - GMP_MPZ a, b, k(k_bn); - - mpz_powm(a.value, g.value, k.value, p.value); - mpz_powm(b.value, y.value, k.value, p.value); - mpz_mul(b.value, b.value, i.value); - mpz_mod(b.value, b.value, p.value); - - const u32bit p_bytes = p.bytes(); - SecureVector<byte> output(2*p_bytes); - a.encode(output, p_bytes); - b.encode(output + p_bytes, p_bytes); - return output; - } - -/* -* GMP ElGamal Decrypt Operation -*/ -BigInt GMP_ELG_Op::decrypt(const BigInt& a_bn, const BigInt& b_bn) const - { - if(mpz_cmp_ui(x.value, 0) == 0) - throw Internal_Error("GMP_ELG_Op::decrypt: No private key"); - - GMP_MPZ a(a_bn), b(b_bn); - - if(mpz_cmp(a.value, p.value) >= 0 || mpz_cmp(b.value, p.value) >= 0) - throw Invalid_Argument("GMP_ELG_Op: Invalid message"); - - mpz_powm(a.value, a.value, x.value, p.value); - mpz_invert(a.value, a.value, p.value); - mpz_mul(a.value, a.value, b.value); - mpz_mod(a.value, a.value, p.value); - return a.to_bigint(); - } - -} - -/* -* Acquire an ElGamal op -*/ -ELG_Operation* GMP_Engine::elg_op(const DL_Group& group, const BigInt& y, - const BigInt& x) const - { - return new GMP_ELG_Op(group, y, x); - } -#endif - -} diff --git a/src/engine/gnump/gmp_if.cpp b/src/engine/gnump/gmp_if.cpp deleted file mode 100644 index 64fbe386a..000000000 --- a/src/engine/gnump/gmp_if.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* -* GMP IF Engine -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/gnump_engine.h> -#include <botan/internal/gmp_wrap.h> -#include <gmp.h> - -namespace Botan { - -#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY) - -namespace { - -/* -* GMP IF Operation -*/ -class GMP_IF_Op : public IF_Operation - { - public: - BigInt public_op(const BigInt&) const; - BigInt private_op(const BigInt&) const; - - IF_Operation* clone() const { return new GMP_IF_Op(*this); } - - GMP_IF_Op(const BigInt& e_bn, const BigInt& n_bn, const BigInt&, - const BigInt& p_bn, const BigInt& q_bn, const BigInt& d1_bn, - const BigInt& d2_bn, const BigInt& c_bn) : - e(e_bn), n(n_bn), p(p_bn), q(q_bn), d1(d1_bn), d2(d2_bn), c(c_bn) {} - private: - const GMP_MPZ e, n, p, q, d1, d2, c; - }; - -/* -* GMP IF Public Operation -*/ -BigInt GMP_IF_Op::public_op(const BigInt& i_bn) const - { - GMP_MPZ i(i_bn); - mpz_powm(i.value, i.value, e.value, n.value); - return i.to_bigint(); - } - -/* -* GMP IF Private Operation -*/ -BigInt GMP_IF_Op::private_op(const BigInt& i_bn) const - { - if(mpz_cmp_ui(p.value, 0) == 0) - throw Internal_Error("GMP_IF_Op::private_op: No private key"); - - GMP_MPZ j1, j2, h(i_bn); - - mpz_powm(j1.value, h.value, d1.value, p.value); - mpz_powm(j2.value, h.value, d2.value, q.value); - mpz_sub(h.value, j1.value, j2.value); - mpz_mul(h.value, h.value, c.value); - mpz_mod(h.value, h.value, p.value); - mpz_mul(h.value, h.value, q.value); - mpz_add(h.value, h.value, j2.value); - return h.to_bigint(); - } - -} - -/* -* Acquire an IF op -*/ -IF_Operation* GMP_Engine::if_op(const BigInt& e, const BigInt& n, - const BigInt& d, const BigInt& p, - const BigInt& q, const BigInt& d1, - const BigInt& d2, const BigInt& c) const - { - return new GMP_IF_Op(e, n, d, p, q, d1, d2, c); - } -#endif - -} diff --git a/src/engine/gnump/gmp_nr.cpp b/src/engine/gnump/gmp_nr.cpp deleted file mode 100644 index 7d6fe536d..000000000 --- a/src/engine/gnump/gmp_nr.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* -* GMP NR Engine -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/gnump_engine.h> -#include <botan/internal/gmp_wrap.h> -#include <gmp.h> - -namespace Botan { - -#if defined(BOTAN_HAS_NYBERG_RUEPPEL) - -namespace { - -/* -* GMP NR Operation -*/ -class GMP_NR_Op : public NR_Operation - { - public: - SecureVector<byte> verify(const byte[], u32bit) const; - SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const; - - NR_Operation* clone() const { return new GMP_NR_Op(*this); } - - GMP_NR_Op(const DL_Group& group, const BigInt& y1, const BigInt& x1) : - x(x1), y(y1), p(group.get_p()), q(group.get_q()), g(group.get_g()) {} - private: - const GMP_MPZ x, y, p, q, g; - }; - -/* -* GMP NR Verify Operation -*/ -SecureVector<byte> GMP_NR_Op::verify(const byte sig[], u32bit sig_len) const - { - const u32bit q_bytes = q.bytes(); - - if(sig_len != 2*q_bytes) - return false; - - GMP_MPZ c(sig, q_bytes); - GMP_MPZ d(sig + q_bytes, q_bytes); - - if(mpz_cmp_ui(c.value, 0) <= 0 || mpz_cmp(c.value, q.value) >= 0 || - mpz_cmp(d.value, q.value) >= 0) - throw Invalid_Argument("GMP_NR_Op::verify: Invalid signature"); - - GMP_MPZ i1, i2; - mpz_powm(i1.value, g.value, d.value, p.value); - mpz_powm(i2.value, y.value, c.value, p.value); - mpz_mul(i1.value, i1.value, i2.value); - mpz_mod(i1.value, i1.value, p.value); - mpz_sub(i1.value, c.value, i1.value); - mpz_mod(i1.value, i1.value, q.value); - return BigInt::encode(i1.to_bigint()); - } - -/* -* GMP NR Sign Operation -*/ -SecureVector<byte> GMP_NR_Op::sign(const byte in[], u32bit length, - const BigInt& k_bn) const - { - if(mpz_cmp_ui(x.value, 0) == 0) - throw Internal_Error("GMP_NR_Op::sign: No private key"); - - GMP_MPZ f(in, length); - GMP_MPZ k(k_bn); - - if(mpz_cmp(f.value, q.value) >= 0) - throw Invalid_Argument("GMP_NR_Op::sign: Input is out of range"); - - GMP_MPZ c, d; - mpz_powm(c.value, g.value, k.value, p.value); - mpz_add(c.value, c.value, f.value); - mpz_mod(c.value, c.value, q.value); - mpz_mul(d.value, x.value, c.value); - mpz_sub(d.value, k.value, d.value); - mpz_mod(d.value, d.value, q.value); - - if(mpz_cmp_ui(c.value, 0) == 0) - throw Internal_Error("Default_NR_Op::sign: c was zero"); - - const u32bit q_bytes = q.bytes(); - SecureVector<byte> output(2*q_bytes); - c.encode(output, q_bytes); - d.encode(output + q_bytes, q_bytes); - return output; - } - -} - -/* -* Acquire a NR op -*/ -NR_Operation* GMP_Engine::nr_op(const DL_Group& group, const BigInt& y, - const BigInt& x) const - { - return new GMP_NR_Op(group, y, x); - } -#endif - -} diff --git a/src/engine/gnump/gmp_wrap.h b/src/engine/gnump/gmp_wrap.h index f8d9cf365..82437ceba 100644 --- a/src/engine/gnump/gmp_wrap.h +++ b/src/engine/gnump/gmp_wrap.h @@ -25,6 +25,9 @@ class GMP_MPZ void encode(byte[], u32bit) const; u32bit bytes() const; + SecureVector<byte> to_bytes() const + { return BigInt::encode(to_bigint()); } + GMP_MPZ& operator=(const GMP_MPZ&); GMP_MPZ(const GMP_MPZ&); diff --git a/src/engine/gnump/gnump_engine.h b/src/engine/gnump/gnump_engine.h index d0b070441..1ca5a3548 100644 --- a/src/engine/gnump/gnump_engine.h +++ b/src/engine/gnump/gnump_engine.h @@ -23,29 +23,17 @@ class GMP_Engine : public Engine std::string provider_name() const { return "gmp"; } -#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY) - IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&, - const BigInt&, const BigInt&, const BigInt&, - const BigInt&, const BigInt&) const; -#endif + PK_Ops::Key_Agreement* + get_key_agreement_op(const Private_Key& key) const; -#if defined(BOTAN_HAS_DSA) - DSA_Operation* dsa_op(const DL_Group&, const BigInt&, - const BigInt&) const; -#endif + PK_Ops::Signature* + get_signature_op(const Private_Key& key) const; -#if defined(BOTAN_HAS_NYBERG_RUEPPEL) - NR_Operation* nr_op(const DL_Group&, const BigInt&, const BigInt&) const; -#endif + PK_Ops::Verification* get_verify_op(const Public_Key& key) const; -#if defined(BOTAN_HAS_ELGAMAL) - ELG_Operation* elg_op(const DL_Group&, const BigInt&, - const BigInt&) const; -#endif + PK_Ops::Encryption* get_encryption_op(const Public_Key& key) const; -#if defined(BOTAN_HAS_DIFFIE_HELLMAN) - DH_Operation* dh_op(const DL_Group&, const BigInt&) const; -#endif + PK_Ops::Decryption* get_decryption_op(const Private_Key& key) const; Modular_Exponentiator* mod_exp(const BigInt&, Power_Mod::Usage_Hints) const; diff --git a/src/engine/gnump/gnump_pk.cpp b/src/engine/gnump/gnump_pk.cpp new file mode 100644 index 000000000..8d003a5d4 --- /dev/null +++ b/src/engine/gnump/gnump_pk.cpp @@ -0,0 +1,350 @@ +/* +* GnuMP PK operations +* (C) 1999-2010 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/internal/gnump_engine.h> +#include <botan/internal/gmp_wrap.h> +#include <gmp.h> + +/* GnuMP 5.0 and later have a side-channel resistent powm */ +#if defined(HAVE_MPZ_POWM_SEC) + #undef mpz_powm + #define mpz_powm mpz_powm_sec +#endif + +#if defined(BOTAN_HAS_RSA) + #include <botan/rsa.h> +#endif + +#if defined(BOTAN_HAS_RW) + #include <botan/rw.h> +#endif + +#if defined(BOTAN_HAS_DSA) + #include <botan/dsa.h> +#endif + +#if defined(BOTAN_HAS_ELGAMAL) + #include <botan/elgamal.h> +#endif + +#if defined(BOTAN_HAS_NYBERG_RUEPPEL) + #include <botan/nr.h> +#endif + +#if defined(BOTAN_HAS_DIFFIE_HELLMAN) + #include <botan/dh.h> +#endif + +namespace Botan { + +namespace { + +#if defined(BOTAN_HAS_DIFFIE_HELLMAN) +class GMP_DH_KA_Operation : public PK_Ops::Key_Agreement + { + public: + GMP_DH_KA_Operation(const DH_PrivateKey& dh) : + x(dh.get_x()), p(dh.group_p()) {} + + SecureVector<byte> agree(const byte w[], u32bit w_len) + { + GMP_MPZ z(w, w_len); + mpz_powm(z.value, z.value, x.value, p.value); + return z.to_bytes(); + } + + private: + GMP_MPZ x, p; + }; +#endif + +#if defined(BOTAN_HAS_DSA) + +class GMP_DSA_Signature_Operation : public PK_Ops::Signature + { + public: + GMP_DSA_Signature_Operation(const DSA_PrivateKey& dsa) : + x(dsa.get_x()), + p(dsa.group_p()), + q(dsa.group_q()), + g(dsa.group_g()), + q_bits(dsa.group_q().bits()) {} + + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return (q_bits + 7) / 8; } + u32bit max_input_bits() const { return q_bits; } + + SecureVector<byte> sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng); + private: + const GMP_MPZ x, p, q, g; + u32bit q_bits; + }; + +SecureVector<byte> +GMP_DSA_Signature_Operation::sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng) + { + const u32bit q_bytes = (q_bits + 7) / 8; + + rng.add_entropy(msg, msg_len); + + BigInt k_bn; + do + k_bn.randomize(rng, q_bits); + while(k_bn >= q.to_bigint()); + + GMP_MPZ i(msg, msg_len); + GMP_MPZ k(k_bn); + + GMP_MPZ r; + mpz_powm(r.value, g.value, k.value, p.value); + mpz_mod(r.value, r.value, q.value); + + mpz_invert(k.value, k.value, q.value); + + GMP_MPZ s; + mpz_mul(s.value, x.value, r.value); + mpz_add(s.value, s.value, i.value); + mpz_mul(s.value, s.value, k.value); + mpz_mod(s.value, s.value, q.value); + + if(mpz_cmp_ui(r.value, 0) == 0 || mpz_cmp_ui(s.value, 0) == 0) + throw Internal_Error("GMP_DSA_Op::sign: r or s was zero"); + + SecureVector<byte> output(2*q_bytes); + r.encode(output, q_bytes); + s.encode(output + q_bytes, q_bytes); + return output; + } + +class GMP_DSA_Verification_Operation : public PK_Ops::Verification + { + public: + GMP_DSA_Verification_Operation(const DSA_PublicKey& dsa) : + y(dsa.get_y()), + p(dsa.group_p()), + q(dsa.group_q()), + g(dsa.group_g()), + q_bits(dsa.group_q().bits()) {} + + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return (q_bits + 7) / 8; } + u32bit max_input_bits() const { return q_bits; } + + bool with_recovery() const { return false; } + + bool verify(const byte msg[], u32bit msg_len, + const byte sig[], u32bit sig_len); + private: + const GMP_MPZ y, p, q, g; + u32bit q_bits; + }; + +bool GMP_DSA_Verification_Operation::verify(const byte msg[], u32bit msg_len, + const byte sig[], u32bit sig_len) + { + const u32bit q_bytes = q.bytes(); + + if(sig_len != 2*q_bytes || msg_len > q_bytes) + return false; + + GMP_MPZ r(sig, q_bytes); + GMP_MPZ s(sig + q_bytes, q_bytes); + GMP_MPZ i(msg, msg_len); + + if(mpz_cmp_ui(r.value, 0) <= 0 || mpz_cmp(r.value, q.value) >= 0) + return false; + if(mpz_cmp_ui(s.value, 0) <= 0 || mpz_cmp(s.value, q.value) >= 0) + return false; + + if(mpz_invert(s.value, s.value, q.value) == 0) + return false; + + GMP_MPZ si; + mpz_mul(si.value, s.value, i.value); + mpz_mod(si.value, si.value, q.value); + mpz_powm(si.value, g.value, si.value, p.value); + + GMP_MPZ sr; + mpz_mul(sr.value, s.value, r.value); + mpz_mod(sr.value, sr.value, q.value); + mpz_powm(sr.value, y.value, sr.value, p.value); + + mpz_mul(si.value, si.value, sr.value); + mpz_mod(si.value, si.value, p.value); + mpz_mod(si.value, si.value, q.value); + + if(mpz_cmp(si.value, r.value) == 0) + return true; + return false; + } + +#endif + +#if defined(BOTAN_HAS_RSA) + +class GMP_RSA_Private_Operation : public PK_Ops::Signature, + public PK_Ops::Decryption + { + public: + GMP_RSA_Private_Operation(const RSA_PrivateKey& rsa) : + mod(rsa.get_n()), + p(rsa.get_p()), + q(rsa.get_q()), + d1(rsa.get_d1()), + d2(rsa.get_d2()), + c(rsa.get_c()), + n_bits(rsa.get_n().bits()) + {} + + u32bit max_input_bits() const { return (n_bits - 1); } + + SecureVector<byte> sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator&) + { + BigInt m(msg, msg_len); + BigInt x = private_op(m); + return BigInt::encode_1363(x, (n_bits + 7) / 8); + } + + SecureVector<byte> decrypt(const byte msg[], u32bit msg_len) + { + BigInt m(msg, msg_len); + return BigInt::encode(private_op(m)); + } + + private: + BigInt private_op(const BigInt& m) const; + + GMP_MPZ mod, p, q, d1, d2, c; + u32bit n_bits; + }; + +BigInt GMP_RSA_Private_Operation::private_op(const BigInt& m) const + { + GMP_MPZ j1, j2, h(m); + + mpz_powm(j1.value, h.value, d1.value, p.value); + mpz_powm(j2.value, h.value, d2.value, q.value); + mpz_sub(h.value, j1.value, j2.value); + mpz_mul(h.value, h.value, c.value); + mpz_mod(h.value, h.value, p.value); + mpz_mul(h.value, h.value, q.value); + mpz_add(h.value, h.value, j2.value); + return h.to_bigint(); + } + +class GMP_RSA_Public_Operation : public PK_Ops::Verification, + public PK_Ops::Encryption + { + public: + GMP_RSA_Public_Operation(const RSA_PublicKey& rsa) : + n(rsa.get_n()), e(rsa.get_e()), mod(rsa.get_n()) + {} + + u32bit max_input_bits() const { return (n.bits() - 1); } + bool with_recovery() const { return true; } + + SecureVector<byte> encrypt(const byte msg[], u32bit msg_len, + RandomNumberGenerator&) + { + BigInt m(msg, msg_len); + return BigInt::encode_1363(public_op(m), n.bytes()); + } + + SecureVector<byte> verify_mr(const byte msg[], u32bit msg_len) + { + BigInt m(msg, msg_len); + return BigInt::encode(public_op(m)); + } + + private: + BigInt public_op(const BigInt& m) const + { + if(m >= n) + throw Invalid_Argument("RSA public op - input is too large"); + + GMP_MPZ m_gmp(m); + mpz_powm(m_gmp.value, m_gmp.value, e.value, mod.value); + return m_gmp.to_bigint(); + } + + const BigInt& n; + const GMP_MPZ e, mod; + }; + +#endif + +} + +PK_Ops::Key_Agreement* +GMP_Engine::get_key_agreement_op(const Private_Key& key) const + { +#if defined(BOTAN_HAS_DIFFIE_HELLMAN) + if(const DH_PrivateKey* dh = dynamic_cast<const DH_PrivateKey*>(&key)) + return new GMP_DH_KA_Operation(*dh); +#endif + + return 0; + } + +PK_Ops::Signature* +GMP_Engine::get_signature_op(const Private_Key& key) const + { +#if defined(BOTAN_HAS_RSA) + if(const RSA_PrivateKey* s = dynamic_cast<const RSA_PrivateKey*>(&key)) + return new GMP_RSA_Private_Operation(*s); +#endif + +#if defined(BOTAN_HAS_DSA) + if(const DSA_PrivateKey* s = dynamic_cast<const DSA_PrivateKey*>(&key)) + return new GMP_DSA_Signature_Operation(*s); +#endif + + return 0; + } + +PK_Ops::Verification* +GMP_Engine::get_verify_op(const Public_Key& key) const + { +#if defined(BOTAN_HAS_RSA) + if(const RSA_PublicKey* s = dynamic_cast<const RSA_PublicKey*>(&key)) + return new GMP_RSA_Public_Operation(*s); +#endif + +#if defined(BOTAN_HAS_DSA) + if(const DSA_PublicKey* s = dynamic_cast<const DSA_PublicKey*>(&key)) + return new GMP_DSA_Verification_Operation(*s); +#endif + + return 0; + } + +PK_Ops::Encryption* +GMP_Engine::get_encryption_op(const Public_Key& key) const + { +#if defined(BOTAN_HAS_RSA) + if(const RSA_PublicKey* s = dynamic_cast<const RSA_PublicKey*>(&key)) + return new GMP_RSA_Public_Operation(*s); +#endif + + return 0; + } + +PK_Ops::Decryption* +GMP_Engine::get_decryption_op(const Private_Key& key) const + { +#if defined(BOTAN_HAS_RSA) + if(const RSA_PrivateKey* s = dynamic_cast<const RSA_PrivateKey*>(&key)) + return new GMP_RSA_Private_Operation(*s); +#endif + + return 0; + } + +} diff --git a/src/engine/gnump/info.txt b/src/engine/gnump/info.txt index bd5c15f7f..7a789681e 100644 --- a/src/engine/gnump/info.txt +++ b/src/engine/gnump/info.txt @@ -12,14 +12,10 @@ gmp_wrap.h </header:internal> <source> -gmp_dh.cpp -gmp_dsa.cpp -gmp_elg.cpp -gmp_if.cpp gmp_mem.cpp -gmp_nr.cpp gmp_powm.cpp gmp_wrap.cpp +gnump_pk.cpp </source> <requires> diff --git a/src/engine/info.txt b/src/engine/info.txt index b270edaa5..32fcf21c2 100644 --- a/src/engine/info.txt +++ b/src/engine/info.txt @@ -10,5 +10,6 @@ hash libstate mac numbertheory +pubkey stream </requires> diff --git a/src/engine/openssl/bn_wrap.h b/src/engine/openssl/bn_wrap.h index 0307189a9..02a229fdd 100644 --- a/src/engine/openssl/bn_wrap.h +++ b/src/engine/openssl/bn_wrap.h @@ -25,6 +25,9 @@ class OSSL_BN void encode(byte[], u32bit) const; u32bit bytes() const; + SecureVector<byte> to_bytes() const + { return BigInt::encode(to_bigint()); } + OSSL_BN& operator=(const OSSL_BN&); OSSL_BN(const OSSL_BN&); diff --git a/src/engine/openssl/info.txt b/src/engine/openssl/info.txt index c65f80a29..38322bfff 100644 --- a/src/engine/openssl/info.txt +++ b/src/engine/openssl/info.txt @@ -16,12 +16,8 @@ arc4_openssl.cpp bn_powm.cpp bn_wrap.cpp ossl_bc.cpp -ossl_dh.cpp -ossl_dsa.cpp -ossl_elg.cpp -ossl_if.cpp ossl_md.cpp -ossl_nr.cpp +openssl_pk.cpp </source> <requires> diff --git a/src/engine/openssl/openssl_engine.h b/src/engine/openssl/openssl_engine.h index 4ee2be2c0..1ee7e4c11 100644 --- a/src/engine/openssl/openssl_engine.h +++ b/src/engine/openssl/openssl_engine.h @@ -23,29 +23,17 @@ class OpenSSL_Engine : public Engine */ std::string provider_name() const { return "openssl"; } -#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY) - IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&, - const BigInt&, const BigInt&, const BigInt&, - const BigInt&, const BigInt&) const; -#endif + PK_Ops::Key_Agreement* + get_key_agreement_op(const Private_Key& key) const; -#if defined(BOTAN_HAS_DSA) - DSA_Operation* dsa_op(const DL_Group&, const BigInt&, - const BigInt&) const; -#endif + PK_Ops::Signature* + get_signature_op(const Private_Key& key) const; -#if defined(BOTAN_HAS_NYBERG_RUEPPEL) - NR_Operation* nr_op(const DL_Group&, const BigInt&, const BigInt&) const; -#endif + PK_Ops::Verification* get_verify_op(const Public_Key& key) const; -#if defined(BOTAN_HAS_ELGAMAL) - ELG_Operation* elg_op(const DL_Group&, const BigInt&, - const BigInt&) const; -#endif + PK_Ops::Encryption* get_encryption_op(const Public_Key& key) const; -#if defined(BOTAN_HAS_DIFFIE_HELLMAN) - DH_Operation* dh_op(const DL_Group&, const BigInt&) const; -#endif + PK_Ops::Decryption* get_decryption_op(const Private_Key& key) const; Modular_Exponentiator* mod_exp(const BigInt&, Power_Mod::Usage_Hints) const; diff --git a/src/engine/openssl/openssl_pk.cpp b/src/engine/openssl/openssl_pk.cpp new file mode 100644 index 000000000..8b8e83ebe --- /dev/null +++ b/src/engine/openssl/openssl_pk.cpp @@ -0,0 +1,345 @@ +/* +* OpenSSL PK operations +* (C) 1999-2010 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/internal/openssl_engine.h> +#include <botan/internal/bn_wrap.h> + +#if defined(BOTAN_HAS_RSA) + #include <botan/rsa.h> +#endif + +#if defined(BOTAN_HAS_RW) + #include <botan/rw.h> +#endif + +#if defined(BOTAN_HAS_DSA) + #include <botan/dsa.h> +#endif + +#if defined(BOTAN_HAS_ELGAMAL) + #include <botan/elgamal.h> +#endif + +#if defined(BOTAN_HAS_NYBERG_RUEPPEL) + #include <botan/nr.h> +#endif + +#if defined(BOTAN_HAS_DIFFIE_HELLMAN) + #include <botan/dh.h> +#endif + +namespace Botan { + +namespace { + +#if defined(BOTAN_HAS_DIFFIE_HELLMAN) +class OSSL_DH_KA_Operation : public PK_Ops::Key_Agreement + { + public: + OSSL_DH_KA_Operation(const DH_PrivateKey& dh) : + x(dh.get_x()), p(dh.group_p()) {} + + SecureVector<byte> agree(const byte w[], u32bit w_len) + { + OSSL_BN i(w, w_len), r; + BN_mod_exp(r.value, i.value, x.value, p.value, ctx.value); + return r.to_bytes(); + } + + private: + const OSSL_BN x, p; + OSSL_BN_CTX ctx; + }; +#endif + +#if defined(BOTAN_HAS_DSA) + +class OSSL_DSA_Signature_Operation : public PK_Ops::Signature + { + public: + OSSL_DSA_Signature_Operation(const DSA_PrivateKey& dsa) : + x(dsa.get_x()), + p(dsa.group_p()), + q(dsa.group_q()), + g(dsa.group_g()), + q_bits(dsa.group_q().bits()) {} + + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return (q_bits + 7) / 8; } + u32bit max_input_bits() const { return q_bits; } + + SecureVector<byte> sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng); + private: + const OSSL_BN x, p, q, g; + const OSSL_BN_CTX ctx; + u32bit q_bits; + }; + +SecureVector<byte> +OSSL_DSA_Signature_Operation::sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng) + { + const u32bit q_bytes = (q_bits + 7) / 8; + + rng.add_entropy(msg, msg_len); + + BigInt k_bn; + do + k_bn.randomize(rng, q_bits); + while(k_bn >= q.to_bigint()); + + OSSL_BN i(msg, msg_len); + OSSL_BN k(k_bn); + + OSSL_BN r; + BN_mod_exp(r.value, g.value, k.value, p.value, ctx.value); + BN_nnmod(r.value, r.value, q.value, ctx.value); + + BN_mod_inverse(k.value, k.value, q.value, ctx.value); + + OSSL_BN s; + BN_mul(s.value, x.value, r.value, ctx.value); + BN_add(s.value, s.value, i.value); + BN_mod_mul(s.value, s.value, k.value, q.value, ctx.value); + + if(BN_is_zero(r.value) || BN_is_zero(s.value)) + throw Internal_Error("OpenSSL_DSA_Op::sign: r or s was zero"); + + SecureVector<byte> output(2*q_bytes); + r.encode(output, q_bytes); + s.encode(output + q_bytes, q_bytes); + return output; + } + +class OSSL_DSA_Verification_Operation : public PK_Ops::Verification + { + public: + OSSL_DSA_Verification_Operation(const DSA_PublicKey& dsa) : + y(dsa.get_y()), + p(dsa.group_p()), + q(dsa.group_q()), + g(dsa.group_g()), + q_bits(dsa.group_q().bits()) {} + + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return (q_bits + 7) / 8; } + u32bit max_input_bits() const { return q_bits; } + + bool with_recovery() const { return false; } + + bool verify(const byte msg[], u32bit msg_len, + const byte sig[], u32bit sig_len); + private: + const OSSL_BN y, p, q, g; + const OSSL_BN_CTX ctx; + u32bit q_bits; + }; + +bool OSSL_DSA_Verification_Operation::verify(const byte msg[], u32bit msg_len, + const byte sig[], u32bit sig_len) + { + const u32bit q_bytes = q.bytes(); + + if(sig_len != 2*q_bytes || msg_len > q_bytes) + return false; + + OSSL_BN r(sig, q_bytes); + OSSL_BN s(sig + q_bytes, q_bytes); + OSSL_BN i(msg, msg_len); + + if(BN_is_zero(r.value) || BN_cmp(r.value, q.value) >= 0) + return false; + if(BN_is_zero(s.value) || BN_cmp(s.value, q.value) >= 0) + return false; + + if(BN_mod_inverse(s.value, s.value, q.value, ctx.value) == 0) + return false; + + OSSL_BN si; + BN_mod_mul(si.value, s.value, i.value, q.value, ctx.value); + BN_mod_exp(si.value, g.value, si.value, p.value, ctx.value); + + OSSL_BN sr; + BN_mod_mul(sr.value, s.value, r.value, q.value, ctx.value); + BN_mod_exp(sr.value, y.value, sr.value, p.value, ctx.value); + + BN_mod_mul(si.value, si.value, sr.value, p.value, ctx.value); + BN_nnmod(si.value, si.value, q.value, ctx.value); + + if(BN_cmp(si.value, r.value) == 0) + return true; + return false; + + return false; + } + +#endif + +#if defined(BOTAN_HAS_RSA) + +class OSSL_RSA_Private_Operation : public PK_Ops::Signature, + public PK_Ops::Decryption + { + public: + OSSL_RSA_Private_Operation(const RSA_PrivateKey& rsa) : + mod(rsa.get_n()), + p(rsa.get_p()), + q(rsa.get_q()), + d1(rsa.get_d1()), + d2(rsa.get_d2()), + c(rsa.get_c()), + n_bits(rsa.get_n().bits()) + {} + + u32bit max_input_bits() const { return (n_bits - 1); } + + SecureVector<byte> sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng) + { + BigInt m(msg, msg_len); + BigInt x = private_op(m); + return BigInt::encode_1363(x, (n_bits + 7) / 8); + } + + SecureVector<byte> decrypt(const byte msg[], u32bit msg_len) + { + BigInt m(msg, msg_len); + return BigInt::encode(private_op(m)); + } + + private: + BigInt private_op(const BigInt& m) const; + + const OSSL_BN mod, p, q, d1, d2, c; + const OSSL_BN_CTX ctx; + u32bit n_bits; + }; + +BigInt OSSL_RSA_Private_Operation::private_op(const BigInt& m) const + { + OSSL_BN j1, j2, h(m); + + BN_mod_exp(j1.value, h.value, d1.value, p.value, ctx.value); + BN_mod_exp(j2.value, h.value, d2.value, q.value, ctx.value); + BN_sub(h.value, j1.value, j2.value); + BN_mod_mul(h.value, h.value, c.value, p.value, ctx.value); + BN_mul(h.value, h.value, q.value, ctx.value); + BN_add(h.value, h.value, j2.value); + return h.to_bigint(); + } + +class OSSL_RSA_Public_Operation : public PK_Ops::Verification, + public PK_Ops::Encryption + { + public: + OSSL_RSA_Public_Operation(const RSA_PublicKey& rsa) : + n(rsa.get_n()), e(rsa.get_e()), mod(rsa.get_n()) + {} + + u32bit max_input_bits() const { return (n.bits() - 1); } + bool with_recovery() const { return true; } + + SecureVector<byte> encrypt(const byte msg[], u32bit msg_len, + RandomNumberGenerator&) + { + BigInt m(msg, msg_len); + return BigInt::encode_1363(public_op(m), n.bytes()); + } + + SecureVector<byte> verify_mr(const byte msg[], u32bit msg_len) + { + BigInt m(msg, msg_len); + return BigInt::encode(public_op(m)); + } + + private: + BigInt public_op(const BigInt& m) const + { + if(m >= n) + throw Invalid_Argument("RSA public op - input is too large"); + + OSSL_BN m_bn(m), r; + BN_mod_exp(r.value, m_bn.value, e.value, mod.value, ctx.value); + return r.to_bigint(); + } + + const BigInt& n; + const OSSL_BN e, mod; + const OSSL_BN_CTX ctx; + }; + +#endif + +} + +PK_Ops::Key_Agreement* +OpenSSL_Engine::get_key_agreement_op(const Private_Key& key) const + { +#if defined(BOTAN_HAS_DIFFIE_HELLMAN) + if(const DH_PrivateKey* dh = dynamic_cast<const DH_PrivateKey*>(&key)) + return new OSSL_DH_KA_Operation(*dh); +#endif + + return 0; + } + +PK_Ops::Signature* +OpenSSL_Engine::get_signature_op(const Private_Key& key) const + { +#if defined(BOTAN_HAS_RSA) + if(const RSA_PrivateKey* s = dynamic_cast<const RSA_PrivateKey*>(&key)) + return new OSSL_RSA_Private_Operation(*s); +#endif + +#if defined(BOTAN_HAS_DSA) + if(const DSA_PrivateKey* s = dynamic_cast<const DSA_PrivateKey*>(&key)) + return new OSSL_DSA_Signature_Operation(*s); +#endif + + return 0; + } + +PK_Ops::Verification* +OpenSSL_Engine::get_verify_op(const Public_Key& key) const + { +#if defined(BOTAN_HAS_RSA) + if(const RSA_PublicKey* s = dynamic_cast<const RSA_PublicKey*>(&key)) + return new OSSL_RSA_Public_Operation(*s); +#endif + +#if defined(BOTAN_HAS_DSA) + if(const DSA_PublicKey* s = dynamic_cast<const DSA_PublicKey*>(&key)) + return new OSSL_DSA_Verification_Operation(*s); +#endif + + return 0; + } + +PK_Ops::Encryption* +OpenSSL_Engine::get_encryption_op(const Public_Key& key) const + { +#if defined(BOTAN_HAS_RSA) + if(const RSA_PublicKey* s = dynamic_cast<const RSA_PublicKey*>(&key)) + return new OSSL_RSA_Public_Operation(*s); +#endif + + return 0; + } + +PK_Ops::Decryption* +OpenSSL_Engine::get_decryption_op(const Private_Key& key) const + { +#if defined(BOTAN_HAS_RSA) + if(const RSA_PrivateKey* s = dynamic_cast<const RSA_PrivateKey*>(&key)) + return new OSSL_RSA_Private_Operation(*s); +#endif + + return 0; + } + +} diff --git a/src/engine/openssl/ossl_dh.cpp b/src/engine/openssl/ossl_dh.cpp deleted file mode 100644 index 7cbe6477d..000000000 --- a/src/engine/openssl/ossl_dh.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* -* OpenSSL Engine -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/openssl_engine.h> -#include <botan/internal/bn_wrap.h> -#include <openssl/opensslv.h> - -#if OPENSSL_VERSION_NUMBER < 0x0090700F - #error Your OpenSSL install is too old, upgrade to 0.9.7 or later -#endif - -namespace Botan { - -#if defined(BOTAN_HAS_DIFFIE_HELLMAN) - -namespace { - -/* -* OpenSSL DH Operation -*/ -class OpenSSL_DH_Op : public DH_Operation - { - public: - BigInt agree(const BigInt& i) const; - DH_Operation* clone() const { return new OpenSSL_DH_Op(*this); } - - OpenSSL_DH_Op(const DL_Group& group, const BigInt& x_bn) : - x(x_bn), p(group.get_p()) {} - private: - OSSL_BN x, p; - OSSL_BN_CTX ctx; - }; - -/* -* OpenSSL DH Key Agreement Operation -*/ -BigInt OpenSSL_DH_Op::agree(const BigInt& i_bn) const - { - OSSL_BN i(i_bn), r; - BN_mod_exp(r.value, i.value, x.value, p.value, ctx.value); - return r.to_bigint(); - } - -} - -/* -* Acquire a DH op -*/ -DH_Operation* OpenSSL_Engine::dh_op(const DL_Group& group, - const BigInt& x) const - { - return new OpenSSL_DH_Op(group, x); - } -#endif - -} diff --git a/src/engine/openssl/ossl_dsa.cpp b/src/engine/openssl/ossl_dsa.cpp deleted file mode 100644 index 66529bcec..000000000 --- a/src/engine/openssl/ossl_dsa.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* -* OpenSSL DSA Engine -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/openssl_engine.h> -#include <botan/internal/bn_wrap.h> -#include <openssl/opensslv.h> - -#if OPENSSL_VERSION_NUMBER < 0x0090700F - #error Your OpenSSL install is too old, upgrade to 0.9.7 or later -#endif - -namespace Botan { - -#if defined(BOTAN_HAS_DSA) - -namespace { - -/* -* OpenSSL DSA Operation -*/ -class OpenSSL_DSA_Op : public DSA_Operation - { - public: - bool verify(const byte[], u32bit, const byte[], u32bit) const; - SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const; - - DSA_Operation* clone() const { return new OpenSSL_DSA_Op(*this); } - - OpenSSL_DSA_Op(const DL_Group& group, const BigInt& y1, - const BigInt& x1) : - x(x1), y(y1), p(group.get_p()), q(group.get_q()), g(group.get_g()) {} - private: - const OSSL_BN x, y, p, q, g; - OSSL_BN_CTX ctx; - }; - -/* -* OpenSSL DSA Verify Operation -*/ -bool OpenSSL_DSA_Op::verify(const byte msg[], u32bit msg_len, - const byte sig[], u32bit sig_len) const - { - const u32bit q_bytes = q.bytes(); - - if(sig_len != 2*q_bytes || msg_len > q_bytes) - return false; - - OSSL_BN r(sig, q_bytes); - OSSL_BN s(sig + q_bytes, q_bytes); - OSSL_BN i(msg, msg_len); - - if(BN_is_zero(r.value) || BN_cmp(r.value, q.value) >= 0) - return false; - if(BN_is_zero(s.value) || BN_cmp(s.value, q.value) >= 0) - return false; - - if(BN_mod_inverse(s.value, s.value, q.value, ctx.value) == 0) - return false; - - OSSL_BN si; - BN_mod_mul(si.value, s.value, i.value, q.value, ctx.value); - BN_mod_exp(si.value, g.value, si.value, p.value, ctx.value); - - OSSL_BN sr; - BN_mod_mul(sr.value, s.value, r.value, q.value, ctx.value); - BN_mod_exp(sr.value, y.value, sr.value, p.value, ctx.value); - - BN_mod_mul(si.value, si.value, sr.value, p.value, ctx.value); - BN_nnmod(si.value, si.value, q.value, ctx.value); - - if(BN_cmp(si.value, r.value) == 0) - return true; - return false; - } - -/* -* OpenSSL DSA Sign Operation -*/ -SecureVector<byte> OpenSSL_DSA_Op::sign(const byte in[], u32bit length, - const BigInt& k_bn) const - { - if(BN_is_zero(x.value)) - throw Internal_Error("OpenSSL_DSA_Op::sign: No private key"); - - OSSL_BN i(in, length); - OSSL_BN k(k_bn); - - OSSL_BN r; - BN_mod_exp(r.value, g.value, k.value, p.value, ctx.value); - BN_nnmod(r.value, r.value, q.value, ctx.value); - - BN_mod_inverse(k.value, k.value, q.value, ctx.value); - - OSSL_BN s; - BN_mul(s.value, x.value, r.value, ctx.value); - BN_add(s.value, s.value, i.value); - BN_mod_mul(s.value, s.value, k.value, q.value, ctx.value); - - if(BN_is_zero(r.value) || BN_is_zero(s.value)) - throw Internal_Error("OpenSSL_DSA_Op::sign: r or s was zero"); - - const u32bit q_bytes = q.bytes(); - - SecureVector<byte> output(2*q_bytes); - r.encode(output, q_bytes); - s.encode(output + q_bytes, q_bytes); - return output; - } - -} - -/* -* Acquire a DSA op -*/ -DSA_Operation* OpenSSL_Engine::dsa_op(const DL_Group& group, const BigInt& y, - const BigInt& x) const - { - return new OpenSSL_DSA_Op(group, y, x); - } -#endif - -} diff --git a/src/engine/openssl/ossl_elg.cpp b/src/engine/openssl/ossl_elg.cpp deleted file mode 100644 index 35c59a7ff..000000000 --- a/src/engine/openssl/ossl_elg.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* -* OpenSSL Engine -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/openssl_engine.h> -#include <botan/internal/bn_wrap.h> -#include <openssl/opensslv.h> - -#if OPENSSL_VERSION_NUMBER < 0x0090700F - #error Your OpenSSL install is too old, upgrade to 0.9.7 or later -#endif - -namespace Botan { - -#if defined(BOTAN_HAS_ELGAMAL) - -namespace { - -/* -* OpenSSL ElGamal Operation -*/ -class OpenSSL_ELG_Op : public ELG_Operation - { - public: - SecureVector<byte> encrypt(const byte[], u32bit, const BigInt&) const; - BigInt decrypt(const BigInt&, const BigInt&) const; - - ELG_Operation* clone() const { return new OpenSSL_ELG_Op(*this); } - OpenSSL_ELG_Op(const DL_Group& group, const BigInt& y1, - const BigInt& x1) : - x(x1), y(y1), g(group.get_g()), p(group.get_p()) {} - private: - OSSL_BN x, y, g, p; - OSSL_BN_CTX ctx; - }; - -/* -* OpenSSL ElGamal Encrypt Operation -*/ -SecureVector<byte> OpenSSL_ELG_Op::encrypt(const byte in[], u32bit length, - const BigInt& k_bn) const - { - OSSL_BN i(in, length); - - if(BN_cmp(i.value, p.value) >= 0) - throw Invalid_Argument("OpenSSL_ELG_Op: Input is too large"); - - OSSL_BN a, b, k(k_bn); - - BN_mod_exp(a.value, g.value, k.value, p.value, ctx.value); - BN_mod_exp(b.value, y.value, k.value, p.value, ctx.value); - BN_mod_mul(b.value, b.value, i.value, p.value, ctx.value); - - const u32bit p_bytes = p.bytes(); - SecureVector<byte> output(2*p_bytes); - a.encode(output, p_bytes); - b.encode(output + p_bytes, p_bytes); - return output; - } - -/* -* OpenSSL ElGamal Decrypt Operation -*/ -BigInt OpenSSL_ELG_Op::decrypt(const BigInt& a_bn, const BigInt& b_bn) const - { - if(BN_is_zero(x.value)) - throw Internal_Error("OpenSSL_ELG_Op::decrypt: No private key"); - - OSSL_BN a(a_bn), b(b_bn), t; - - if(BN_cmp(a.value, p.value) >= 0 || BN_cmp(b.value, p.value) >= 0) - throw Invalid_Argument("OpenSSL_ELG_Op: Invalid message"); - - BN_mod_exp(t.value, a.value, x.value, p.value, ctx.value); - BN_mod_inverse(a.value, t.value, p.value, ctx.value); - BN_mod_mul(a.value, a.value, b.value, p.value, ctx.value); - return a.to_bigint(); - } - -} - -/* -* Acquire an ElGamal op -*/ -ELG_Operation* OpenSSL_Engine::elg_op(const DL_Group& group, const BigInt& y, - const BigInt& x) const - { - return new OpenSSL_ELG_Op(group, y, x); - } -#endif - -} diff --git a/src/engine/openssl/ossl_if.cpp b/src/engine/openssl/ossl_if.cpp deleted file mode 100644 index a30a4d8b4..000000000 --- a/src/engine/openssl/ossl_if.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* -* OpenSSL IF Engine -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/openssl_engine.h> -#include <botan/internal/bn_wrap.h> -#include <openssl/opensslv.h> - -#if OPENSSL_VERSION_NUMBER < 0x0090700F - #error Your OpenSSL install is too old, upgrade to 0.9.7 or later -#endif - -namespace Botan { - -#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY) - -namespace { - -/* -* OpenSSL IF Operation -*/ -class OpenSSL_IF_Op : public IF_Operation - { - public: - BigInt public_op(const BigInt&) const; - BigInt private_op(const BigInt&) const; - - IF_Operation* clone() const { return new OpenSSL_IF_Op(*this); } - - OpenSSL_IF_Op(const BigInt& e_bn, const BigInt& n_bn, const BigInt&, - const BigInt& p_bn, const BigInt& q_bn, const BigInt& d1_bn, - const BigInt& d2_bn, const BigInt& c_bn) : - e(e_bn), n(n_bn), p(p_bn), q(q_bn), d1(d1_bn), d2(d2_bn), c(c_bn) {} - private: - const OSSL_BN e, n, p, q, d1, d2, c; - OSSL_BN_CTX ctx; - }; - -/* -* OpenSSL IF Public Operation -*/ -BigInt OpenSSL_IF_Op::public_op(const BigInt& i_bn) const - { - OSSL_BN i(i_bn), r; - BN_mod_exp(r.value, i.value, e.value, n.value, ctx.value); - return r.to_bigint(); - } - -/* -* OpenSSL IF Private Operation -*/ -BigInt OpenSSL_IF_Op::private_op(const BigInt& i_bn) const - { - if(BN_is_zero(p.value)) - throw Internal_Error("OpenSSL_IF_Op::private_op: No private key"); - - OSSL_BN j1, j2, h(i_bn); - - BN_mod_exp(j1.value, h.value, d1.value, p.value, ctx.value); - BN_mod_exp(j2.value, h.value, d2.value, q.value, ctx.value); - BN_sub(h.value, j1.value, j2.value); - BN_mod_mul(h.value, h.value, c.value, p.value, ctx.value); - BN_mul(h.value, h.value, q.value, ctx.value); - BN_add(h.value, h.value, j2.value); - return h.to_bigint(); - } - -} - -/* -* Acquire an IF op -*/ -IF_Operation* OpenSSL_Engine::if_op(const BigInt& e, const BigInt& n, - const BigInt& d, const BigInt& p, - const BigInt& q, const BigInt& d1, - const BigInt& d2, const BigInt& c) const - { - return new OpenSSL_IF_Op(e, n, d, p, q, d1, d2, c); - } -#endif - -} diff --git a/src/engine/openssl/ossl_nr.cpp b/src/engine/openssl/ossl_nr.cpp deleted file mode 100644 index b14ec7f8c..000000000 --- a/src/engine/openssl/ossl_nr.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/* -* OpenSSL NR Engine -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/openssl_engine.h> -#include <botan/internal/bn_wrap.h> -#include <openssl/opensslv.h> - -#if OPENSSL_VERSION_NUMBER < 0x0090700F - #error Your OpenSSL install is too old, upgrade to 0.9.7 or later -#endif - -namespace Botan { - -#if defined(BOTAN_HAS_NYBERG_RUEPPEL) - -namespace { - -/* -* OpenSSL NR Operation -*/ -class OpenSSL_NR_Op : public NR_Operation - { - public: - SecureVector<byte> verify(const byte[], u32bit) const; - SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const; - - NR_Operation* clone() const { return new OpenSSL_NR_Op(*this); } - - OpenSSL_NR_Op(const DL_Group& group, const BigInt& y1, - const BigInt& x1) : - x(x1), y(y1), p(group.get_p()), q(group.get_q()), g(group.get_g()) {} - private: - const OSSL_BN x, y, p, q, g; - OSSL_BN_CTX ctx; - }; - -/* -* OpenSSL NR Verify Operation -*/ -SecureVector<byte> OpenSSL_NR_Op::verify(const byte sig[], - u32bit sig_len) const - { - const u32bit q_bytes = q.bytes(); - - if(sig_len != 2*q_bytes) - return false; - - OSSL_BN c(sig, q_bytes); - OSSL_BN d(sig + q_bytes, q_bytes); - - if(BN_is_zero(c.value) || BN_cmp(c.value, q.value) >= 0 || - BN_cmp(d.value, q.value) >= 0) - throw Invalid_Argument("OpenSSL_NR_Op::verify: Invalid signature"); - - OSSL_BN i1, i2; - BN_mod_exp(i1.value, g.value, d.value, p.value, ctx.value); - BN_mod_exp(i2.value, y.value, c.value, p.value, ctx.value); - BN_mod_mul(i1.value, i1.value, i2.value, p.value, ctx.value); - BN_sub(i1.value, c.value, i1.value); - BN_nnmod(i1.value, i1.value, q.value, ctx.value); - return BigInt::encode(i1.to_bigint()); - } - -/* -* OpenSSL NR Sign Operation -*/ -SecureVector<byte> OpenSSL_NR_Op::sign(const byte in[], u32bit length, - const BigInt& k_bn) const - { - if(BN_is_zero(x.value)) - throw Internal_Error("OpenSSL_NR_Op::sign: No private key"); - - OSSL_BN f(in, length); - OSSL_BN k(k_bn); - - if(BN_cmp(f.value, q.value) >= 0) - throw Invalid_Argument("OpenSSL_NR_Op::sign: Input is out of range"); - - OSSL_BN c, d; - BN_mod_exp(c.value, g.value, k.value, p.value, ctx.value); - BN_add(c.value, c.value, f.value); - BN_nnmod(c.value, c.value, q.value, ctx.value); - BN_mul(d.value, x.value, c.value, ctx.value); - BN_sub(d.value, k.value, d.value); - BN_nnmod(d.value, d.value, q.value, ctx.value); - - if(BN_is_zero(c.value)) - throw Internal_Error("Default_NR_Op::sign: c was zero"); - - const u32bit q_bytes = q.bytes(); - SecureVector<byte> output(2*q_bytes); - c.encode(output, q_bytes); - d.encode(output + q_bytes, q_bytes); - return output; - } - -} - -/* -* Acquire a NR op -*/ -NR_Operation* OpenSSL_Engine::nr_op(const DL_Group& group, const BigInt& y, - const BigInt& x) const - { - return new OpenSSL_NR_Op(group, y, x); - } -#endif - -} diff --git a/src/hash/gost_3411/gost_3411.cpp b/src/hash/gost_3411/gost_3411.cpp index 01d8a0d46..244a3fddf 100644 --- a/src/hash/gost_3411/gost_3411.cpp +++ b/src/hash/gost_3411/gost_3411.cpp @@ -191,12 +191,18 @@ void GOST_34_11::compress_n(const byte input[], u32bit blocks) S2[19] = S[ 5] ^ S[ 7] ^ S[11] ^ S[13] ^ S[15] ^ S[17] ^ S[23] ^ S[25] ^ S[29]; S2[20] = S[ 6] ^ S[ 8] ^ S[12] ^ S[14] ^ S[16] ^ S[18] ^ S[24] ^ S[26] ^ S[30]; S2[21] = S[ 7] ^ S[ 9] ^ S[13] ^ S[15] ^ S[17] ^ S[19] ^ S[25] ^ S[27] ^ S[31]; - S2[22] = S[ 0] ^ S[ 2] ^ S[ 4] ^ S[ 6] ^ S[ 8] ^ S[10] ^ S[14] ^ S[16] ^ S[18] ^ S[20] ^ S[24] ^ S[26] ^ S[28] ^ S[30]; - S2[23] = S[ 1] ^ S[ 3] ^ S[ 5] ^ S[ 7] ^ S[ 9] ^ S[11] ^ S[15] ^ S[17] ^ S[19] ^ S[21] ^ S[25] ^ S[27] ^ S[29] ^ S[31]; - S2[24] = S[ 0] ^ S[ 8] ^ S[10] ^ S[12] ^ S[16] ^ S[18] ^ S[20] ^ S[22] ^ S[24] ^ S[26] ^ S[28]; - S2[25] = S[ 1] ^ S[ 9] ^ S[11] ^ S[13] ^ S[17] ^ S[19] ^ S[21] ^ S[23] ^ S[25] ^ S[27] ^ S[29]; - S2[26] = S[ 2] ^ S[10] ^ S[12] ^ S[14] ^ S[18] ^ S[20] ^ S[22] ^ S[24] ^ S[26] ^ S[28] ^ S[30]; - S2[27] = S[ 3] ^ S[11] ^ S[13] ^ S[15] ^ S[19] ^ S[21] ^ S[23] ^ S[25] ^ S[27] ^ S[29] ^ S[31]; + S2[22] = S[ 0] ^ S[ 2] ^ S[ 4] ^ S[ 6] ^ S[ 8] ^ S[10] ^ S[14] ^ S[16] ^ + S[18] ^ S[20] ^ S[24] ^ S[26] ^ S[28] ^ S[30]; + S2[23] = S[ 1] ^ S[ 3] ^ S[ 5] ^ S[ 7] ^ S[ 9] ^ S[11] ^ S[15] ^ S[17] ^ + S[19] ^ S[21] ^ S[25] ^ S[27] ^ S[29] ^ S[31]; + S2[24] = S[ 0] ^ S[ 8] ^ S[10] ^ S[12] ^ S[16] ^ S[18] ^ S[20] ^ S[22] ^ + S[24] ^ S[26] ^ S[28]; + S2[25] = S[ 1] ^ S[ 9] ^ S[11] ^ S[13] ^ S[17] ^ S[19] ^ S[21] ^ S[23] ^ + S[25] ^ S[27] ^ S[29]; + S2[26] = S[ 2] ^ S[10] ^ S[12] ^ S[14] ^ S[18] ^ S[20] ^ S[22] ^ S[24] ^ + S[26] ^ S[28] ^ S[30]; + S2[27] = S[ 3] ^ S[11] ^ S[13] ^ S[15] ^ S[19] ^ S[21] ^ S[23] ^ S[25] ^ + S[27] ^ S[29] ^ S[31]; S2[28] = S[ 0] ^ S[ 2] ^ S[ 6] ^ S[12] ^ S[14] ^ S[16] ^ S[20] ^ S[22] ^ S[26] ^ S[28]; S2[29] = S[ 1] ^ S[ 3] ^ S[ 7] ^ S[13] ^ S[15] ^ S[17] ^ S[21] ^ S[23] ^ S[27] ^ S[29]; S2[30] = S[ 2] ^ S[ 4] ^ S[ 8] ^ S[14] ^ S[16] ^ S[18] ^ S[22] ^ S[24] ^ S[28] ^ S[30]; diff --git a/src/libstate/info.txt b/src/libstate/info.txt index cb584f4d8..f50b7f3dc 100644 --- a/src/libstate/info.txt +++ b/src/libstate/info.txt @@ -11,17 +11,11 @@ lookup.h scan_name.h </header:public> -<header:internal> -pk_engine.h -</header:internal> - <source> get_enc.cpp init.cpp libstate.cpp -look_pk.cpp lookup.cpp -pk_engine.cpp policy.cpp scan_name.cpp </source> diff --git a/src/libstate/look_pk.cpp b/src/libstate/look_pk.cpp deleted file mode 100644 index 8eb473858..000000000 --- a/src/libstate/look_pk.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* -* PK Algorithm Lookup -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/look_pk.h> -#include <botan/lookup.h> - -namespace Botan { - -/* -* Get a PK_Encryptor object -*/ -PK_Encryptor* get_pk_encryptor(const PK_Encrypting_Key& key, - const std::string& eme) - { - return new PK_Encryptor_MR_with_EME(key, get_eme(eme)); - } - -/* -* Get a PK_Decryptor object -*/ -PK_Decryptor* get_pk_decryptor(const PK_Decrypting_Key& key, - const std::string& eme) - { - return new PK_Decryptor_MR_with_EME(key, get_eme(eme)); - } - -/* -* Get a PK_Signer object -*/ -PK_Signer* get_pk_signer(const PK_Signing_Key& key, - const std::string& emsa, - Signature_Format sig_format) - { - PK_Signer* signer = new PK_Signer(key, get_emsa(emsa)); - signer->set_output_format(sig_format); - return signer; - } - -/* -* Get a PK_Verifier object -*/ -PK_Verifier* get_pk_verifier(const PK_Verifying_with_MR_Key& key, - const std::string& emsa, - Signature_Format sig_format) - { - PK_Verifier* verifier = new PK_Verifier_with_MR(key, get_emsa(emsa)); - verifier->set_input_format(sig_format); - return verifier; - } - -/* -* Get a PK_Verifier object -*/ -PK_Verifier* get_pk_verifier(const PK_Verifying_wo_MR_Key& key, - const std::string& emsa, - Signature_Format sig_format) - { - PK_Verifier* verifier = new PK_Verifier_wo_MR(key, get_emsa(emsa)); - verifier->set_input_format(sig_format); - return verifier; - } - -/* -* Get a PK_Key_Agreement object -*/ -PK_Key_Agreement* get_pk_kas(const PK_Key_Agreement_Key& key, - const std::string& kdf) - { - return new PK_Key_Agreement(key, get_kdf(kdf)); - } - -} diff --git a/src/libstate/look_pk.h b/src/libstate/look_pk.h index 27b67dc5b..833b28f67 100644 --- a/src/libstate/look_pk.h +++ b/src/libstate/look_pk.h @@ -1,6 +1,6 @@ /* * PK Algorithm Lookup -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -8,7 +8,7 @@ #ifndef BOTAN_PK_LOOKUP_H__ #define BOTAN_PK_LOOKUP_H__ -#include <botan/build.h> +#include <botan/lookup.h> #include <botan/pubkey.h> namespace Botan { @@ -16,62 +16,66 @@ namespace Botan { /** * Public key encryptor factory method. * @param key the key that will work inside the encryptor -* @param pad determines the algorithm and encoding +* @param eme determines the algorithm and encoding * @return the public key encryptor object */ -BOTAN_DLL PK_Encryptor* get_pk_encryptor(const PK_Encrypting_Key& key, - const std::string& pad); +inline PK_Encryptor* get_pk_encryptor(const Public_Key& key, + const std::string& eme) + { + return new PK_Encryptor_EME(key, eme); + } /** * Public key decryptor factory method. * @param key the key that will work inside the decryptor -* @param pad determines the algorithm and encoding +* @param eme determines the algorithm and encoding * @return the public key decryptor object */ -BOTAN_DLL PK_Decryptor* get_pk_decryptor(const PK_Decrypting_Key& key, - const std::string& pad); +inline PK_Decryptor* get_pk_decryptor(const Private_Key& key, + const std::string& eme) + { + return new PK_Decryptor_EME(key, eme); + } /** * Public key signer factory method. * @param key the key that will work inside the signer -* @param pad determines the algorithm, encoding and hash algorithm +* @param emsa determines the algorithm, encoding and hash algorithm * @param sig_format the signature format to be used * @return the public key signer object */ -BOTAN_DLL PK_Signer* get_pk_signer(const PK_Signing_Key& key, - const std::string& pad, - Signature_Format = IEEE_1363); +inline PK_Signer* get_pk_signer(const Private_Key& key, + const std::string& emsa, + Signature_Format sig_format = IEEE_1363) + { + return new PK_Signer(key, emsa, sig_format); + } /** * Public key verifier factory method. * @param key the key that will work inside the verifier -* @param pad determines the algorithm, encoding and hash algorithm +* @param emsa determines the algorithm, encoding and hash algorithm * @param sig_format the signature format to be used * @return the public key verifier object */ -BOTAN_DLL PK_Verifier* get_pk_verifier(const PK_Verifying_with_MR_Key& key, - const std::string& pad, - Signature_Format = IEEE_1363); - -/** -* Public key verifier factory method. -* @param key the key that will work inside the verifier -* @param pad determines the algorithm, encoding and hash algorithm -* @param sig_form the signature format to be used -* @return the public key verifier object -*/ -BOTAN_DLL PK_Verifier* get_pk_verifier(const PK_Verifying_wo_MR_Key& key, - const std::string& pad, - Signature_Format sig_form = IEEE_1363); +inline PK_Verifier* get_pk_verifier(const Public_Key& key, + const std::string& emsa, + Signature_Format sig_format = IEEE_1363) + { + return new PK_Verifier(key, emsa, sig_format); + } /** * Public key key agreement factory method. * @param key the key that will work inside the key agreement -* @param pad determines the algorithm, encoding and hash algorithm -* @return the public key verifier object +* @param kdf the kdf algorithm to use +* @return the key agreement algorithm */ -BOTAN_DLL PK_Key_Agreement* get_pk_kas(const PK_Key_Agreement_Key& key, - const std::string& pad); +inline PK_Key_Agreement* get_pk_kas(const PK_Key_Agreement_Key& key, + const std::string& kdf) + { + return new PK_Key_Agreement(key, kdf); + } } diff --git a/src/libstate/oid_lookup/oids.cpp b/src/libstate/oid_lookup/oids.cpp index 232c63360..c54762c58 100644 --- a/src/libstate/oid_lookup/oids.cpp +++ b/src/libstate/oid_lookup/oids.cpp @@ -49,7 +49,7 @@ OID lookup(const std::string& name) { return OID(name); } - catch(Exception) + catch(...) { throw Lookup_Error("No object identifier found for " + name); } diff --git a/src/libstate/pk_engine.cpp b/src/libstate/pk_engine.cpp deleted file mode 100644 index ac2fa68b0..000000000 --- a/src/libstate/pk_engine.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* -* PK Engine Lookup -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/internal/pk_engine.h> -#include <botan/libstate.h> -#include <botan/engine.h> - -namespace Botan { - -namespace Engine_Core { - -#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY) -/* -* Acquire an IF op -*/ -IF_Operation* if_op(const BigInt& e, const BigInt& n, const BigInt& d, - const BigInt& p, const BigInt& q, const BigInt& d1, - const BigInt& d2, const BigInt& c) - { - Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory()); - - while(const Engine* engine = i.next()) - { - IF_Operation* op = engine->if_op(e, n, d, p, q, d1, d2, c); - if(op) - return op; - } - - throw Lookup_Error("Engine_Core::if_op: Unable to find a working engine"); - } -#endif - -#if defined(BOTAN_HAS_DSA) -/* -* Acquire a DSA op -*/ -DSA_Operation* dsa_op(const DL_Group& group, const BigInt& y, const BigInt& x) - { - Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory()); - - while(const Engine* engine = i.next()) - { - DSA_Operation* op = engine->dsa_op(group, y, x); - if(op) - return op; - } - - throw Lookup_Error("Engine_Core::dsa_op: Unable to find a working engine"); - } -#endif - -#if defined(BOTAN_HAS_NYBERG_RUEPPEL) -/* -* Acquire a NR op -*/ -NR_Operation* nr_op(const DL_Group& group, const BigInt& y, const BigInt& x) - { - Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory()); - - while(const Engine* engine = i.next()) - { - NR_Operation* op = engine->nr_op(group, y, x); - if(op) - return op; - } - - throw Lookup_Error("Engine_Core::nr_op: Unable to find a working engine"); - } -#endif - -#if defined(BOTAN_HAS_ELGAMAL) -/* -* Acquire an ElGamal op -*/ -ELG_Operation* elg_op(const DL_Group& group, const BigInt& y, const BigInt& x) - { - Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory()); - - while(const Engine* engine = i.next()) - { - ELG_Operation* op = engine->elg_op(group, y, x); - if(op) - return op; - } - - throw Lookup_Error("Engine_Core::elg_op: Unable to find a working engine"); - } -#endif - -#if defined(BOTAN_HAS_DIFFIE_HELLMAN) -/* -* Acquire a DH op -*/ -DH_Operation* dh_op(const DL_Group& group, const BigInt& x) - { - Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory()); - - while(const Engine* engine = i.next()) - { - DH_Operation* op = engine->dh_op(group, x); - if(op) - return op; - } - - throw Lookup_Error("Engine_Core::dh_op: Unable to find a working engine"); - } -#endif - -/* -* Acquire a modular exponentiator -*/ -Modular_Exponentiator* mod_exp(const BigInt& n, Power_Mod::Usage_Hints hints) - { - Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory()); - - while(const Engine* engine = i.next()) - { - Modular_Exponentiator* op = engine->mod_exp(n, hints); - - if(op) - return op; - } - - throw Lookup_Error("Engine_Core::mod_exp: Unable to find a working engine"); - } - -} - -} diff --git a/src/libstate/pk_engine.h b/src/libstate/pk_engine.h deleted file mode 100644 index 25f326ef0..000000000 --- a/src/libstate/pk_engine.h +++ /dev/null @@ -1,73 +0,0 @@ -/** -* Engine for PK -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_ENGINE_PK_LOOKUP_H__ -#define BOTAN_ENGINE_PK_LOOKUP_H__ - -#include <botan/bigint.h> -#include <botan/pow_mod.h> - -#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY) - #include <botan/if_op.h> -#endif - -#if defined(BOTAN_HAS_DSA) - #include <botan/dsa_op.h> -#endif - -#if defined(BOTAN_HAS_DIFFIE_HELLMAN) - #include <botan/dh_op.h> -#endif - -#if defined(BOTAN_HAS_NYBERG_RUEPPEL) - #include <botan/nr_op.h> -#endif - -#if defined(BOTAN_HAS_ELGAMAL) - #include <botan/elg_op.h> -#endif - -namespace Botan { - -class Algorithm_Factory; -class Keyed_Filter; -class Modular_Exponentiator; - -namespace Engine_Core { - -/* -* Get an operation from an Engine -*/ -Modular_Exponentiator* mod_exp(const BigInt&, Power_Mod::Usage_Hints); - -#if defined(BOTAN_HAS_IF_PUBLIC_KEY_FAMILY) -IF_Operation* if_op(const BigInt&, const BigInt&, const BigInt&, - const BigInt&, const BigInt&, const BigInt&, - const BigInt&, const BigInt&); -#endif - -#if defined(BOTAN_HAS_DSA) -DSA_Operation* dsa_op(const DL_Group&, const BigInt&, const BigInt&); -#endif - -#if defined(BOTAN_HAS_NYBERG_RUEPPEL) -NR_Operation* nr_op(const DL_Group&, const BigInt&, const BigInt&); -#endif - -#if defined(BOTAN_HAS_ELGAMAL) -ELG_Operation* elg_op(const DL_Group&, const BigInt&, const BigInt&); -#endif - -#if defined(BOTAN_HAS_DIFFIE_HELLMAN) -DH_Operation* dh_op(const DL_Group&, const BigInt&); -#endif - -} - -} - -#endif diff --git a/src/libstate/policy.cpp b/src/libstate/policy.cpp index bb775b049..d792443a0 100644 --- a/src/libstate/policy.cpp +++ b/src/libstate/policy.cpp @@ -34,7 +34,7 @@ void set_default_oids(Library_State& config) add_oid(config, "2.5.8.1.1", "RSA"); // RSA alternate add_oid(config, "1.2.840.10040.4.1", "DSA"); add_oid(config, "1.2.840.10046.2.1", "DH"); - add_oid(config, "1.3.6.1.4.1.3029.1.2.1", "ELG"); + add_oid(config, "1.3.6.1.4.1.3029.1.2.1", "ElGamal"); add_oid(config, "1.3.6.1.4.1.25258.1.1", "RW"); add_oid(config, "1.3.6.1.4.1.25258.1.2", "NR"); add_oid(config, "1.2.840.10045.2.1", "ECDSA"); // X9.62 @@ -93,12 +93,14 @@ void set_default_oids(Library_State& config) add_oid(config, "2.16.840.1.101.3.4.3.1", "DSA/EMSA1(SHA-224)"); add_oid(config, "2.16.840.1.101.3.4.3.2", "DSA/EMSA1(SHA-256)"); - add_oid(config, "1.2.840.10045.4.1", "ECDSA/EMSA1_BSI(SHA-160)"); - add_oid(config, "1.2.840.10045.4.3.1", "ECDSA/EMSA1_BSI(SHA-224)"); - add_oid(config, "1.2.840.10045.4.3.2", "ECDSA/EMSA1_BSI(SHA-256)"); - add_oid(config, "1.2.840.10045.4.3.3", "ECDSA/EMSA1_BSI(SHA-384)"); - add_oid(config, "1.2.840.10045.4.3.4", "ECDSA/EMSA1_BSI(SHA-512)"); + add_oid(config, "0.4.0.127.0.7.1.1.4.1.1", "ECDSA/EMSA1_BSI(SHA-160)"); + add_oid(config, "0.4.0.127.0.7.1.1.4.1.2", "ECDSA/EMSA1_BSI(SHA-224)"); + add_oid(config, "0.4.0.127.0.7.1.1.4.1.3", "ECDSA/EMSA1_BSI(SHA-256)"); + add_oid(config, "0.4.0.127.0.7.1.1.4.1.4", "ECDSA/EMSA1_BSI(SHA-384)"); + add_oid(config, "0.4.0.127.0.7.1.1.4.1.5", "ECDSA/EMSA1_BSI(SHA-512)"); + add_oid(config, "0.4.0.127.0.7.1.1.4.1.6", "ECDSA/EMSA1_BSI(RIPEMD-160)"); + add_oid(config, "1.2.840.10045.4.1", "ECDSA/EMSA1(SHA-160)"); add_oid(config, "1.2.840.10045.4.3.1", "ECDSA/EMSA1(SHA-224)"); add_oid(config, "1.2.840.10045.4.3.2", "ECDSA/EMSA1(SHA-256)"); add_oid(config, "1.2.840.10045.4.3.3", "ECDSA/EMSA1(SHA-384)"); @@ -543,111 +545,111 @@ void set_default_dl_groups(Library_State& config) "-----END DSA PARAMETERS-----"); config.set("ec", "secp112r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MHQCAQEwGgYHKoZIzj0BAQIPANt8Kr9i415mgHa+rSCLMCAEDtt8Kr9i415mgHa+" "rSCIBA5lnvi6BDkW7t6JEXArIgQdBAlIcjmZWl7na1X5wvCYqJzlr4ckwKI+Dg/3" "dQACDwDbfCq/YuNedijfrGVhxQIBAQ==" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "secp112r2", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MHMCAQEwGgYHKoZIzj0BAQIPANt8Kr9i415mgHa+rSCLMCAEDmEnwkwF84oKqvZc" "DvAsBA5R3vGBXbXtdPzDTIXXCQQdBEujCrXokrThZJ3QkoZDrc1G9YguN0fe826V" "bpcCDjbfCq/YuNdZfKEFINBLAgEB" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "secp128r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIGAAgEBMBwGByqGSM49AQECEQD////9////////////////MCQEEP////3/////" "//////////wEEOh1ecEQefQ92CSZPCzuXtMEIQQWH/dSi4mbLQwoYHylLFuGz1rI" "OVuv6xPALaKS3e16gwIRAP////4AAAAAdaMNG5A4oRUCAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "secp128r2", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MH8CAQEwHAYHKoZIzj0BAQIRAP////3///////////////8wJAQQ1gMZmNGzu/6/" "Wcybv/mu4QQQXu78o4DQKRncLGVYu22KXQQhBHtqpdheVymD5vsyp83rwUAntpFq" "iU067nEG/oBfw0tEAhA/////f////74AJHIGE7WjAgEE" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "secp160k1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIGYAgEBMCAGByqGSM49AQECFQD////////////////////+//+sczAsBBQAAAAA" "AAAAAAAAAAAAAAAAAAAAAAQUAAAAAAAAAAAAAAAAAAAAAAAAAAcEKQQ7TDgs43qh" "kqQBnnYwNvT13U1+u5OM+TUxj9zta8KChlMXM8PwPE/uAhUBAAAAAAAAAAAAAbj6" "Ft+rmsoWtrMCAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "secp160r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIGYAgEBMCAGByqGSM49AQECFQD/////////////////////f////zAsBBT/////" "////////////////f////AQUHJe+/FS9eotlrPifgdTUrcVl+kUEKQRKlrVojvVz" "KEZkaYlow4u5E8v8giOmKFUxaJR9WdzJEgQjUTd6xfsyAhUBAAAAAAAAAAAAAfTI" "+Seu08p1IlcCAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "secp160r2", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIGYAgEBMCAGByqGSM49AQECFQD////////////////////+//+sczAsBBT/////" "///////////////+//+scAQUtOE00/tZ64urVydJBGZNWvUDiLoEKQRS3LA0KToR" "fh9P8Rsw9xmdMUTObf6v/vLjMfKW4HH6DfmYLP6n1D8uAhUBAAAAAAAAAAAAADUe" "54aoGPOhoWsCAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "secp192k1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIGwAgEBMCQGByqGSM49AQECGQD//////////////////////////v//7jcwNAQY" "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" "AAMEMQTbT/EOwFfpriawfQKAt/Q0HaXRsergbH2bLy9tnFYop4RBY9AVvoY0QIKq" "iNleL50CGQD///////////////4m8vwXD2lGanTe/Y0CAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "secp192r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIGwAgEBMCQGByqGSM49AQECGQD////////////////////+//////////8wNAQY" "/////////////////////v/////////8BBhkIQUZ5ZyA5w+n6atyJDBJ/rje7MFG" "ubEEMQQYjagOsDCQ9ny/IOtDoYgA9P8K/YL/EBIHGSuV/8jaeGMQEe1rJM3Vc/l3" "oR55SBECGQD///////////////+Z3vg2FGvJsbTSKDECAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "secp224k1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIHIAgEBMCgGByqGSM49AQECHQD///////////////////////////////7//+Vt" "MDwEHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEHAAAAAAAAAAAAAAAAAAA" "AAAAAAAAAAAAAAAAAAUEOQShRVszTfCZ3zD8KKFppGfp5HB1qQ9+ZQ62t6Rcfgif" "7X+6NEKCyvvW9+MZ98CwvVniykvbVW1hpQIdAQAAAAAAAAAAAAAAAAAB3OjS7GGE" "yvCpcXafsfcCAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "secp224r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIHIAgEBMCgGByqGSM49AQECHQD/////////////////////AAAAAAAAAAAAAAAB" "MDwEHP////////////////////7///////////////4EHLQFCoUMBLOr9UEyVlBE" "sLfXv9i6Jws5QyNV/7QEOQS3Dgy9a7S/fzITkLlKA8HTVsIRIjQygNYRXB0hvTdj" "iLX3I/tMIt/mzUN1oFoHR2RE1YGZhQB+NAIdAP//////////////////FqLguPA+" "E90pRVxcKj0CAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "secp256k1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIHgAgEBMCwGByqGSM49AQECIQD////////////////////////////////////+" "///8LzBEBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQgAAAAAAAA" "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcEQQR5vmZ++dy7rFWgYpXOhwsHApv8" "2y3OKNlZ8oFbFvgXmEg62ncmo8RlXaT7/A4RCKj9F7RIpoVUGZxH0I/7ENS4AiEA" "/////////////////////rqu3OavSKA7v9JejNA2QUECAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "secp256r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIHgAgEBMCwGByqGSM49AQECIQD/////AAAAAQAAAAAAAAAAAAAAAP//////////" "/////zBEBCD/////AAAAAQAAAAAAAAAAAAAAAP///////////////AQgWsY12Ko6" "k+ez671VdpiGvGUdBrDMU7D2O848PifSYEsEQQRrF9Hy4SxCR/i85uVjpEDydwN9" "gS3rM6D0oTlF2JjClk/jQuL+Gn+bjufrSnwPnhYrzjNXazFezsu2QGg3v1H1AiEA" "/////wAAAAD//////////7zm+q2nF56E87nKwvxjJVECAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "secp384r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIIBQAIBATA8BgcqhkjOPQEBAjEA////////////////////////////////////" "//////7/////AAAAAAAAAAD/////MGQEMP//////////////////////////////" "///////////+/////wAAAAAAAAAA/////AQwszEvp+I+5+SYjgVr4/gtGRgdnG7+" @@ -655,10 +657,10 @@ void set_default_dl_groups(Library_State& config) "O2KLp5uYWfdB4IJUKjhVAvJdv1UpbDpUXjhydgq3NhfeSpYmLG9dnpi/kpLcKfj0" "Hb0omhR86doxE7XwuMAKYLHOHX6BnXpDHXyQ6g5fAjEA////////////////////" "////////////x2NNgfQ3Ld9YGg2ySLCneuzsGWrMxSlzAgEB" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "secp521r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIIBrAIBATBNBgcqhkjOPQEBAkIB////////////////////////////////////" "//////////////////////////////////////////////////8wgYgEQgH/////" "////////////////////////////////////////////////////////////////" @@ -668,10 +670,10 @@ void set_default_dl_groups(Library_State& config) "fn4xwuW9ZgEYOSlqeJo7wARcil+0LH0b2Zj1RElXm0RoF6+9Fyc+ZiyX7nKZXvQm" "QMVQuQE/rQdhNTxwhqJywkCIvpR2n9FmUAJCAf//////////////////////////" "////////////////+lGGh4O/L5Zrf8wBSPcJpdA7tcm4iZxHrrtvtx6ROGQJAgEB" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "1.3.6.1.4.1.8301.3.1.2.9.0.38", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIIBrAIBATBNBgcqhkjOPQEBAkIB////////////////////////////////////" "//////////////////////////////////////////////////8wgYgEQgH/////" "////////////////////////////////////////////////////////////////" @@ -681,54 +683,54 @@ void set_default_dl_groups(Library_State& config) "fn4xwuW9ZgEYOSlqeJo7wARcil+0LH0b2Zj1RElXm0RoF6+9Fyc+ZiyX7nKZXvQm" "QMVQuQE/rQdhNTxwhqJywkCIvpR2n9FmUAJCAf//////////////////////////" "////////////////+lGGh4O/L5Zrf8wBSPcJpdA7tcm4iZxHrrtvtx6ROGQJAgEB" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "brainpool160r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIGYAgEBMCAGByqGSM49AQECFQDpXkpfc3BZ3GDfx62Vs9gTlRViDzAsBBQ0Dnvi" "ooDrdOK+YbradF2X6PfDAAQUHliahZVCNBITT6otveyVyNhnXlgEKQS+1a8W6j9q" "T2KTjEYx61r3vbzbwxZny0d6Go7DOPlHQWacl2MW2mMhAhUA6V5KX3NwWdxg31mR" "1FApQJ5g/AkCAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "brainpool192r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIGwAgEBMCQGByqGSM49AQECGQDDAvQdkyo2zaejRjCT0Y23j85HbeGoYpcwNAQY" "apEXQHax4OGcOcAx/oaFwcrgQOXGmijvBBhGmijvfCjMo9xyHQRPRJa8yn70FG+/" "JckEMQTAoGR+qrakh1OwM8VssPCQCi9cSFM3X9YUtpCGar1buItfSCjBSQAC5nc/" "ovopm48CGQDDAvQdkyo2zaejRi+enpFrW+jxAprErMECAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "brainpool224r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIHIAgEBMCgGByqGSM49AQECHQDXwTSqJkNmhioYMCV10deHsJ8HV5faifV+yMD/" "MDwEHGil5iypzmwcKZgDpsFTC1FOGCrYsAQqWcrSn0MEHCWA9jzP5EE4hwcTsakj" "aeM+ITXSZtuzcjhsQAsEOQQNkCmtLH5c9DQII7KofcaMnkzjF0webv3uEsB9WKpW" "93LAcm8kxrieTs2sJDVLnpnKo/bTdhQCzQIdANfBNKomQ2aGKhgwJXXQ+5jRFrxL" "bd68o6Wnk58CAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "brainpool256r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIHgAgEBMCwGByqGSM49AQECIQCp+1fboe6pvD5mCpCdg41ybjv2I9UmICggE0gd" "H25TdzBEBCB9Wgl1/CwwV+72dTBBev/n+4BVwSbcXGzpSktE8zC12QQgJtxcbOlK" "S0TzMLXZu9d8v5WEFilc9+HOa8zcGP+MB7YEQQSL0q65y35XyyxLSC/8gbevud4n" "4eO9I8I6RFO9ms4yYlR++DXD2sT9l/hGGhRhHcnCd0UTLe2OVFwdVMcvBGmXAiEA" "qftX26Huqbw+ZgqQnYONcYw5eqO1Yab3kB4OgpdIVqcCAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "brainpool320r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIIBEAIBATA0BgcqhkjOPQEBAikA015HIDa8T7fhPHhe0gHgZfmPz6b29A3vT5K5" "7HiT7Cj81BKx8bMuJzBUBCg+4wtWj7qw+IPM69RtPzu4oqc1E/XredpmGQ6whf+p" "9JLzdal9hg60BChSCIOUnf28QtOtGYZAaIpv4T9BNJVUtJrMMdzNiEU5gW9etKyP" "sfGmBFEEQ71+mvtT2LhSibzEjuW/5vIBN9EKCH6254ceKhClmccQr40NOeIGERT9" "0FVF7BzIq0CTJH93J14HQ//tEXGC6qnHeHeqrGrH01JF0WkujuECKQDTXkcgNrxP" "t+E8eF7SAeBl+Y/PpbaPEqMtSC7H7oZY6YaRVVtExZMRAgEB" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "brainpool384r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIIBQAIBATA8BgcqhkjOPQEBAjEAjLkegqM4bSgPXW9+UOZB3xUvcQntVFa0ErHa" "GX+3ESOs06cpkB0acYdHABMxB+xTMGQEMHvDgsY9jBUMPHIICs4Fr6DCvqKOT7In" "hxORZe+6kfkPiqWBSlA61OsEqMfdIs4oJgQwBKjH3SLOKCaLObVUFvBEfC+3feEH" @@ -736,10 +738,10 @@ void set_default_dl_groups(Library_State& config) "o+d+8U/j23/K/gy9EOjoJuA0NtZGqu+HsuJH1K8eir4ddSD5wqRcseuOlc/VUmK3" "Cyn+7Fhk4ZwFT/mRKSgORkYhd5GBEUKCA0EmPFMVAjEAjLkegqM4bSgPXW9+UOZB" "3xUvcQntVFazHxZubKwEJafPOrava3/DEDuIMgLpBGVlAgEB" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "brainpool512r1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIIBogIBATBMBgcqhkjOPQEBAkEAqt2duNvpxIs/1OauM8n8B8swjbOzydIO1mOc" "ynAzCHF9TZsAm8ZoQq7NoSrmo4DmKIH/Ly2CxoUoqmBWWDpI8zCBhARAeDCjMYtg" "O4niMnFFrCNMxZTL3Y09+RYQqDRByuqYY7wt7V1aqCU6oQou8cmLmsi1fxEXpyvy" @@ -749,59 +751,59 @@ void set_default_dl_groups(Library_State& config) "fd44XVZjMuzA6r+pz3gi/fIJ9wAkpXsaoADFW4gfgRGy3N5JSl9IXlvKS9iKJ2Ou" "0corL6jwVAZ4zR4POtgIkgJBAKrdnbjb6cSLP9TmrjPJ/AfLMI2zs8nSDtZjnMpw" "MwhwVT5cQUypJhlBhmEZf6wQRx2x04EIXdrdtYeWgpypAGkCAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "x962_p192v2", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIGwAgEBMCQGByqGSM49AQECGQD////////////////////+//////////8wNAQY" "/////////////////////v/////////8BBjMItbfuVxrJeScDWNkpOWYDDk6ohZo" "2VMEMQTuorrn4Ul4QvLed2nP6cmJwHKtaW9IA0pldNEdabbsemcruCoIPfLysIR9" "6XCy3hUCGQD///////////////5fsack3IBBhkjY3TECAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "x962_p192v3", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIGwAgEBMCQGByqGSM49AQECGQD////////////////////+//////////8wNAQY" "/////////////////////v/////////8BBgiEj3COVoFyqdCPa7MyUdgp9RiJWvV" "aRYEMQR9KXeBAMZaHaF4NxZYjc4ri0rujiKPGJY4qQ8iY3M3M0tJ3LZqbcj5l4rK" "dkipQ7ACGQD///////////////96YtAxyD9ClPZA7BMCAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "x962_p239v1", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIHSAgEBMCkGByqGSM49AQECHn///////////////3///////4AAAAAAAH//////" "/zBABB5///////////////9///////+AAAAAAAB///////wEHmsBbDvc8YlB0NZU" "khR1ynGp2y+yfR03eWGFwpQsCgQ9BA/6ljzcqIFszDO4ZCvt+QXD01hXPT8n+707" "PLmqr33r6OTpCl2ubkBUylMLoEZUs2gYziJrOfzLewLxrgIef///////////////" "f///nl6an12QcfvRUiaIkJ0LAgEB" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "x962_p239v2", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIHSAgEBMCkGByqGSM49AQECHn///////////////3///////4AAAAAAAH//////" "/zBABB5///////////////9///////+AAAAAAAB///////wEHmF/q2gyV2y7/tUN" "mfAknD/uWLlLoAOMeuhMjIMvLAQ9BDivCdmHJ3BRIMkhu16eJilqPNzy81dXoOr9" "h7gw51sBJeTb6g7HIG2g/AHZsIEyn7VV3m70YCN9/4vkugIef///////////////" "gAAAz6foWUN31BTAOCG8WCBjAgEB" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "x962_p239v3", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIHSAgEBMCkGByqGSM49AQECHn///////////////3///////4AAAAAAAH//////" "/zBABB5///////////////9///////+AAAAAAAB///////wEHiVXBfoqMGZUsfTL" "A9anUKMMJQEC1JiHF9m6FattPgQ9BGdoro4Yu5LPzwBclJqixtlIU9DmYLv4VLHJ" "UF/pWhYH5omPOQwGvB1VK60ibztvz+SLboGEma8Y4+1s8wIef///////////////" "f///l13rQbOmBXw8QyFGUmVRAgEB" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); config.set("ec", "gost_256A", - "-----BEGIN ECC DOMAIN PARAMETERS-----" + "-----BEGIN EC PARAMETERS-----" "MIHgAgEBMCwGByqGSM49AQECIQD/////////////////////////////////////" "///9lzBEBCD////////////////////////////////////////9lAQgAAAAAAAA" "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKYEQQQAAAAAAAAAAAAAAAAAAAAAAAAA" "AAAAAAAAAAAAAAAAAY2R5HHgmJzaJ99QWkU/K3Y1KU8t3yPjsSKsyZyenx4UAiEA" "/////////////////////2xhEHCZWtEARYQbCbdhuJMCAQE=" - "-----END ECC DOMAIN PARAMETERS-----"); + "-----END EC PARAMETERS-----"); } } diff --git a/src/math/numbertheory/blinding.cpp b/src/math/numbertheory/blinding.cpp deleted file mode 100644 index c6a3fd1bd..000000000 --- a/src/math/numbertheory/blinding.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* -* Blinder -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/blinding.h> -#include <botan/numthry.h> - -namespace Botan { - -/* -* Blinder Constructor -*/ -Blinder::Blinder(const BigInt& e, const BigInt& d, const BigInt& n) - { - if(e < 1 || d < 1 || n < 1) - throw Invalid_Argument("Blinder: Arguments too small"); - - reducer = Modular_Reducer(n); - this->e = e; - this->d = d; - } - -/* -* Blind a number -*/ -BigInt Blinder::blind(const BigInt& i) const - { - if(!reducer.initialized()) - return i; - - e = reducer.square(e); - d = reducer.square(d); - return reducer.multiply(i, e); - } - -/* -* Unblind a number -*/ -BigInt Blinder::unblind(const BigInt& i) const - { - if(!reducer.initialized()) - return i; - return reducer.multiply(i, d); - } - -} diff --git a/src/math/numbertheory/blinding.h b/src/math/numbertheory/blinding.h deleted file mode 100644 index 5f7f9e6b7..000000000 --- a/src/math/numbertheory/blinding.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -* Blinder -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_BLINDER_H__ -#define BOTAN_BLINDER_H__ - -#include <botan/bigint.h> -#include <botan/reducer.h> - -namespace Botan { - -/* -* Blinding Function Object -*/ -class BOTAN_DLL Blinder - { - public: - BigInt blind(const BigInt&) const; - BigInt unblind(const BigInt&) const; - - Blinder() {} - Blinder(const BigInt&, const BigInt&, const BigInt&); - private: - Modular_Reducer reducer; - mutable BigInt e, d; - }; - -} - -#endif diff --git a/src/math/numbertheory/info.txt b/src/math/numbertheory/info.txt index 58851e055..18349ef78 100644 --- a/src/math/numbertheory/info.txt +++ b/src/math/numbertheory/info.txt @@ -3,7 +3,6 @@ load_on auto define BIGINT_MATH <header:public> -blinding.h curve_gfp.h numthry.h point_gfp.h @@ -16,7 +15,6 @@ def_powm.h </header:internal> <source> -blinding.cpp dsa_gen.cpp jacobi.cpp make_prm.cpp diff --git a/src/math/numbertheory/make_prm.cpp b/src/math/numbertheory/make_prm.cpp index 3eb01cd42..23b8cf549 100644 --- a/src/math/numbertheory/make_prm.cpp +++ b/src/math/numbertheory/make_prm.cpp @@ -38,6 +38,9 @@ BigInt random_prime(RandomNumberGenerator& rng, while(true) { BigInt p(rng, bits); + + // Force lowest and two top bits on + p.set_bit(bits - 1); p.set_bit(bits - 2); p.set_bit(0); diff --git a/src/math/numbertheory/point_gfp.cpp b/src/math/numbertheory/point_gfp.cpp index bed08eb39..db422c8aa 100644 --- a/src/math/numbertheory/point_gfp.cpp +++ b/src/math/numbertheory/point_gfp.cpp @@ -202,7 +202,7 @@ void PointGFp::mult2() BigInt PointGFp::get_affine_x() const { if(is_zero()) - throw Illegal_Transformation("cannot convert to affine"); + throw Illegal_Transformation("Cannot convert zero point to affine"); const Modular_Reducer& mod_p = curve.mod_p(); @@ -213,7 +213,7 @@ BigInt PointGFp::get_affine_x() const BigInt PointGFp::get_affine_y() const { if(is_zero()) - throw Illegal_Transformation("cannot convert to affine"); + throw Illegal_Transformation("Cannot convert zero point to affine"); const Modular_Reducer& mod_p = curve.mod_p(); @@ -326,38 +326,39 @@ SecureVector<byte> EC2OSP(const PointGFp& point, byte format) throw Invalid_Argument("illegal point encoding format specification"); } -PointGFp OS2ECP(const MemoryRegion<byte>& os, const CurveGFp& curve) +PointGFp OS2ECP(const byte data[], u32bit data_len, + const CurveGFp& curve) { - if(os.size() == 1 && os[0] == 0) + if(data_len <= 1) return PointGFp(curve); // return zero - const byte pc = os[0]; + const byte pc = data[0]; BigInt x, y; if(pc == 2 || pc == 3) { //compressed form - x = BigInt::decode(&os[1], os.size() - 1); + x = BigInt::decode(&data[1], data_len - 1); bool yMod2 = ((pc & 0x01) == 1); y = decompress_point(yMod2, x, curve); } else if(pc == 4) { - // uncompressed form - u32bit l = (os.size() - 1) / 2; + const u32bit l = (data_len - 1) / 2; - x = BigInt::decode(&os[1], l); - y = BigInt::decode(&os[l+1], l); + // uncompressed form + x = BigInt::decode(&data[1], l); + y = BigInt::decode(&data[l+1], l); } else if(pc == 6 || pc == 7) { - // hybrid form - u32bit l = (os.size() - 1) / 2; + const u32bit l = (data_len - 1) / 2; - x = BigInt::decode(&os[1], l); - y = BigInt::decode(&os[l+1], l); + // hybrid form + x = BigInt::decode(&data[1], l); + y = BigInt::decode(&data[l+1], l); bool yMod2 = ((pc & 0x01) == 1); diff --git a/src/math/numbertheory/point_gfp.h b/src/math/numbertheory/point_gfp.h index 3bb763d44..2f31421fc 100644 --- a/src/math/numbertheory/point_gfp.h +++ b/src/math/numbertheory/point_gfp.h @@ -219,7 +219,12 @@ inline PointGFp operator*(const PointGFp& point, const BigInt& scalar) // encoding and decoding SecureVector<byte> BOTAN_DLL EC2OSP(const PointGFp& point, byte format); -PointGFp BOTAN_DLL OS2ECP(const MemoryRegion<byte>& os, const CurveGFp& curve); + +PointGFp BOTAN_DLL OS2ECP(const byte data[], u32bit data_len, + const CurveGFp& curve); + +inline PointGFp OS2ECP(const MemoryRegion<byte>& data, const CurveGFp& curve) + { return OS2ECP(&data[0], data.size(), curve); } } diff --git a/src/math/numbertheory/pow_mod.cpp b/src/math/numbertheory/pow_mod.cpp index 8d6bac699..5ab5638ea 100644 --- a/src/math/numbertheory/pow_mod.cpp +++ b/src/math/numbertheory/pow_mod.cpp @@ -6,7 +6,8 @@ */ #include <botan/pow_mod.h> -#include <botan/internal/pk_engine.h> +#include <botan/libstate.h> +#include <botan/engine.h> namespace Botan { @@ -55,7 +56,23 @@ Power_Mod::~Power_Mod() void Power_Mod::set_modulus(const BigInt& n, Usage_Hints hints) const { delete core; - core = ((n == 0) ? 0 : Engine_Core::mod_exp(n, hints)); + core = 0; + + if(n != 0) + { + Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory()); + + while(const Engine* engine = i.next()) + { + core = engine->mod_exp(n, hints); + + if(core) + break; + } + + if(!core) + throw Lookup_Error("Power_Mod: Unable to find a working engine"); + } } /* @@ -94,6 +111,38 @@ BigInt Power_Mod::execute() const return core->execute(); } +/* +* Try to choose a good window size +*/ +u32bit Power_Mod::window_bits(u32bit exp_bits, u32bit, + Power_Mod::Usage_Hints hints) + { + static const u32bit wsize[][2] = { + { 2048, 7 }, { 1024, 6 }, { 256, 5 }, { 128, 4 }, { 64, 3 }, { 0, 0 } + }; + + u32bit window_bits = 1; + + if(exp_bits) + { + for(u32bit j = 0; wsize[j][0]; ++j) + { + if(exp_bits >= wsize[j][0]) + { + window_bits += wsize[j][1]; + break; + } + } + } + + if(hints & Power_Mod::BASE_IS_FIXED) + window_bits += 2; + if(hints & Power_Mod::EXP_IS_LARGE) + ++window_bits; + + return window_bits; + } + namespace { /* diff --git a/src/math/numbertheory/pow_mod.h b/src/math/numbertheory/pow_mod.h index 6952dcd1b..7b92f0ec4 100644 --- a/src/math/numbertheory/pow_mod.h +++ b/src/math/numbertheory/pow_mod.h @@ -31,6 +31,7 @@ class BOTAN_DLL Modular_Exponentiator class BOTAN_DLL Power_Mod { public: + enum Usage_Hints { NO_HINTS = 0x0000, @@ -44,6 +45,12 @@ class BOTAN_DLL Power_Mod EXP_IS_LARGE = 0x0400 }; + /* + * Try to choose a good window size + */ + static u32bit window_bits(u32bit exp_bits, u32bit base_bits, + Power_Mod::Usage_Hints hints); + void set_modulus(const BigInt&, Usage_Hints = NO_HINTS) const; void set_base(const BigInt&) const; void set_exponent(const BigInt&) const; diff --git a/src/math/numbertheory/powm_fw.cpp b/src/math/numbertheory/powm_fw.cpp index 1cfcdcd66..68dabc332 100644 --- a/src/math/numbertheory/powm_fw.cpp +++ b/src/math/numbertheory/powm_fw.cpp @@ -11,44 +11,6 @@ namespace Botan { -namespace { - -/* -* Try to choose a good window size -*/ -u32bit fw_powm_window_bits(u32bit exp_bits, u32bit, - Power_Mod::Usage_Hints hints) - { - static const u32bit wsize[][2] = { - { 2048, 7 }, { 1024, 6 }, { 256, 5 }, { 128, 4 }, { 64, 3 }, { 0, 0 } - }; - - u32bit window_bits = 3; - - if(exp_bits) - { - for(u32bit j = 0; wsize[j][0]; ++j) - { - if(exp_bits >= wsize[j][0]) - { - window_bits += wsize[j][1]; - break; - } - } - } - - if(hints & Power_Mod::EXP_IS_FIXED) - window_bits += 2; - if(hints & Power_Mod::EXP_IS_LARGE) - window_bits += 2; - if(hints & Power_Mod::BASE_IS_FIXED) - ++window_bits; - - return window_bits; - } - -} - /* * Set the exponent */ @@ -62,7 +24,7 @@ void Fixed_Window_Exponentiator::set_exponent(const BigInt& e) */ void Fixed_Window_Exponentiator::set_base(const BigInt& base) { - window_bits = fw_powm_window_bits(exp.bits(), base.bits(), hints); + window_bits = Power_Mod::window_bits(exp.bits(), base.bits(), hints); g.resize((1 << window_bits) - 1); g[0] = base; diff --git a/src/math/numbertheory/powm_mnt.cpp b/src/math/numbertheory/powm_mnt.cpp index 2d18ccdef..cce142020 100644 --- a/src/math/numbertheory/powm_mnt.cpp +++ b/src/math/numbertheory/powm_mnt.cpp @@ -14,38 +14,6 @@ namespace Botan { namespace { /* -* Try to choose a good window size -*/ -u32bit montgomery_powm_window_bits(u32bit exp_bits, u32bit, - Power_Mod::Usage_Hints hints) - { - static const u32bit wsize[][2] = { - { 2048, 4 }, { 1024, 3 }, { 256, 2 }, { 128, 1 }, { 0, 0 } - }; - - u32bit window_bits = 1; - - if(exp_bits) - { - for(u32bit j = 0; wsize[j][0]; ++j) - { - if(exp_bits >= wsize[j][0]) - { - window_bits += wsize[j][1]; - break; - } - } - } - - if(hints & Power_Mod::BASE_IS_FIXED) - window_bits += 2; - if(hints & Power_Mod::EXP_IS_LARGE) - ++window_bits; - - return window_bits; - } - -/* * Montgomery Reduction */ inline void montgomery_reduce(BigInt& out, MemoryRegion<word>& z_buf, @@ -76,7 +44,7 @@ void Montgomery_Exponentiator::set_exponent(const BigInt& exp) */ void Montgomery_Exponentiator::set_base(const BigInt& base) { - window_bits = montgomery_powm_window_bits(exp.bits(), base.bits(), hints); + window_bits = Power_Mod::window_bits(exp.bits(), base.bits(), hints); g.resize((1 << window_bits) - 1); diff --git a/src/math/numbertheory/reducer.h b/src/math/numbertheory/reducer.h index 80c0f27e1..c121f1499 100644 --- a/src/math/numbertheory/reducer.h +++ b/src/math/numbertheory/reducer.h @@ -18,6 +18,8 @@ namespace Botan { class BOTAN_DLL Modular_Reducer { public: + const BigInt& get_modulus() const { return modulus; } + BigInt reduce(const BigInt& x) const; /** diff --git a/src/pubkey/blinding.cpp b/src/pubkey/blinding.cpp new file mode 100644 index 000000000..819d0dd20 --- /dev/null +++ b/src/pubkey/blinding.cpp @@ -0,0 +1,76 @@ +/* +* Blinding for public key operations +* (C) 1999-2010 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/blinding.h> +#include <botan/numthry.h> +#include <botan/libstate.h> +#include <botan/hash.h> +#include <botan/time.h> +#include <botan/loadstor.h> +#include <memory> + +namespace Botan { + +/* +* Blinder Constructor +*/ +Blinder::Blinder(const BigInt& e, const BigInt& d, const BigInt& n) + { + if(e < 1 || d < 1 || n < 1) + throw Invalid_Argument("Blinder: Arguments too small"); + + reducer = Modular_Reducer(n); + this->e = e; + this->d = d; + } + +BigInt Blinder::choose_nonce(const BigInt& x, const BigInt& mod) + { + Algorithm_Factory& af = global_state().algorithm_factory(); + + std::auto_ptr<HashFunction> hash(af.make_hash_function("SHA-512")); + + u64bit ns_clock = get_nanoseconds_clock(); + for(size_t i = 0; i != sizeof(ns_clock); ++i) + hash->update(get_byte(i, ns_clock)); + + hash->update(BigInt::encode(x)); + hash->update(BigInt::encode(mod)); + + u64bit timestamp = system_time(); + for(size_t i = 0; i != sizeof(timestamp); ++i) + hash->update(get_byte(i, timestamp)); + + SecureVector<byte> r = hash->final(); + + return BigInt::decode(r) % mod; + } + +/* +* Blind a number +*/ +BigInt Blinder::blind(const BigInt& i) const + { + if(!reducer.initialized()) + return i; + + e = reducer.square(e); + d = reducer.square(d); + return reducer.multiply(i, e); + } + +/* +* Unblind a number +*/ +BigInt Blinder::unblind(const BigInt& i) const + { + if(!reducer.initialized()) + return i; + return reducer.multiply(i, d); + } + +} diff --git a/src/pubkey/blinding.h b/src/pubkey/blinding.h new file mode 100644 index 000000000..3398f8c6f --- /dev/null +++ b/src/pubkey/blinding.h @@ -0,0 +1,53 @@ +/* +* Blinding for public key operations +* (C) 1999-2010 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_BLINDER_H__ +#define BOTAN_BLINDER_H__ + +#include <botan/bigint.h> +#include <botan/reducer.h> + +namespace Botan { + +/* +* Blinding Function Object +*/ +class BOTAN_DLL Blinder + { + public: + BigInt blind(const BigInt& x) const; + BigInt unblind(const BigInt& x) const; + + bool initialized() const { return reducer.initialized(); } + + /** + * Choose a nonce to use for blinding + * @param x a secret seed value + * @param mod the modulus + */ + static BigInt choose_nonce(const BigInt& x, const BigInt& mod); + + Blinder() {} + + /** + * Construct a blinder + * @param mask the forward (blinding) mask + * @param inverse_mask the inverse of mask (depends on algo) + * @param modulus of the group operations are performed in + */ + Blinder(const BigInt& mask, + const BigInt& inverse_mask, + const BigInt& modulus); + + private: + Modular_Reducer reducer; + mutable BigInt e, d; + }; + +} + +#endif diff --git a/src/pubkey/dh/dh.cpp b/src/pubkey/dh/dh.cpp index baaa31126..b491be7bc 100644 --- a/src/pubkey/dh/dh.cpp +++ b/src/pubkey/dh/dh.cpp @@ -18,22 +18,6 @@ DH_PublicKey::DH_PublicKey(const DL_Group& grp, const BigInt& y1) { group = grp; y = y1; - X509_load_hook(); - } - -/* -* Algorithm Specific X.509 Initialization Code -*/ -void DH_PublicKey::X509_load_hook() - { - } - -/* -* Return the maximum input size in bits -*/ -u32bit DH_PublicKey::max_input_bits() const - { - return group_p().bits(); } /* @@ -58,26 +42,29 @@ DH_PrivateKey::DH_PrivateKey(RandomNumberGenerator& rng, { const BigInt& p = group_p(); x.randomize(rng, 2 * dl_work_factor(p.bits())); - PKCS8_load_hook(rng, true); } + + if(y == 0) + y = power_mod(group_g(), x, group_p()); + + if(x == 0) + gen_check(rng); else - PKCS8_load_hook(rng, false); + load_check(rng); } /* -* Algorithm Specific PKCS #8 Initialization Code +* Load a DH private key */ -void DH_PrivateKey::PKCS8_load_hook(RandomNumberGenerator& rng, - bool generated) +DH_PrivateKey::DH_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + RandomNumberGenerator& rng) : + DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_42) { if(y == 0) y = power_mod(group_g(), x, group_p()); - core = DH_Core(rng, group, x); - if(generated) - gen_check(rng); - else - load_check(rng); + load_check(rng); } /* @@ -88,32 +75,20 @@ MemoryVector<byte> DH_PrivateKey::public_value() const return DH_PublicKey::public_value(); } -/* -* Derive a key -*/ -SecureVector<byte> DH_PrivateKey::derive_key(const byte w[], - u32bit w_len) const +DH_KA_Operation::DH_KA_Operation(const DH_PrivateKey& dh) : + p(dh.group_p()), powermod_x_p(dh.get_x(), p) { - return derive_key(BigInt::decode(w, w_len)); + BigInt k = Blinder::choose_nonce(powermod_x_p(2), p); + blinder = Blinder(k, powermod_x_p(inverse_mod(k, p)), p); } -/* -* Derive a key -*/ -SecureVector<byte> DH_PrivateKey::derive_key(const DH_PublicKey& key) const +SecureVector<byte> DH_KA_Operation::agree(const byte w[], u32bit w_len) { - return derive_key(key.get_y()); - } + BigInt input = BigInt::decode(w, w_len); -/* -* Derive a key -*/ -SecureVector<byte> DH_PrivateKey::derive_key(const BigInt& w) const - { - const BigInt& p = group_p(); - if(w <= 1 || w >= p-1) - throw Invalid_Argument(algo_name() + "::derive_key: Invalid key input"); - return BigInt::encode_1363(core.agree(w), p.bytes()); + BigInt r = blinder.unblind(powermod_x_p(blinder.blind(input))); + + return BigInt::encode_1363(r, p.bytes()); } } diff --git a/src/pubkey/dh/dh.h b/src/pubkey/dh/dh.h index fa558bce2..738b3f9c4 100644 --- a/src/pubkey/dh/dh.h +++ b/src/pubkey/dh/dh.h @@ -9,7 +9,9 @@ #define BOTAN_DIFFIE_HELLMAN_H__ #include <botan/dl_algo.h> -#include <botan/dh_core.h> +#include <botan/pow_mod.h> +#include <botan/blinding.h> +#include <botan/pk_ops.h> namespace Botan { @@ -22,15 +24,13 @@ class BOTAN_DLL DH_PublicKey : public virtual DL_Scheme_PublicKey std::string algo_name() const { return "DH"; } MemoryVector<byte> public_value() const; - u32bit max_input_bits() const; + u32bit max_input_bits() const { return group_p().bits(); } DL_Group::Format group_format() const { return DL_Group::ANSI_X9_42; } - /** - * Construct an uninitialized key. Use this constructor if you wish - * to decode an encoded key into the new instance. - */ - DH_PublicKey() {} + DH_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) : + DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_42) {} /** * Construct a public key with the specified parameters. @@ -38,8 +38,8 @@ class BOTAN_DLL DH_PublicKey : public virtual DL_Scheme_PublicKey * @param y the public value y */ DH_PublicKey(const DL_Group& grp, const BigInt& y); - private: - void X509_load_hook(); + protected: + DH_PublicKey() {} }; /** @@ -50,17 +50,17 @@ class BOTAN_DLL DH_PrivateKey : public DH_PublicKey, public virtual DL_Scheme_PrivateKey { public: - SecureVector<byte> derive_key(const byte other[], u32bit length) const; - SecureVector<byte> derive_key(const DH_PublicKey& other) const; - SecureVector<byte> derive_key(const BigInt& other) const; - MemoryVector<byte> public_value() const; /** - * Construct an uninitialized key. Use this constructor if you wish - * to decode an encoded key into the new instance. + * Load a DH private key + * @param alg_id the algorithm id + * @param key_bits the subject public key + * @rng a random number generator */ - DH_PrivateKey() {} + DH_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + RandomNumberGenerator& rng); /** * Construct a private key with predetermined value. @@ -70,9 +70,22 @@ class BOTAN_DLL DH_PrivateKey : public DH_PublicKey, */ DH_PrivateKey(RandomNumberGenerator& rng, const DL_Group& grp, const BigInt& x = 0); + }; + +/** +* DH operation +*/ +class BOTAN_DLL DH_KA_Operation : public PK_Ops::Key_Agreement + { + public: + DH_KA_Operation(const DH_PrivateKey& key); + + SecureVector<byte> agree(const byte w[], u32bit w_len); private: - void PKCS8_load_hook(RandomNumberGenerator& rng, bool = false); - DH_Core core; + const BigInt& p; + + Fixed_Exponent_Power_Mod powermod_x_p; + Blinder blinder; }; } diff --git a/src/pubkey/dh/dh_core.cpp b/src/pubkey/dh/dh_core.cpp deleted file mode 100644 index cbe2dc9f1..000000000 --- a/src/pubkey/dh/dh_core.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* -* PK Algorithm Core -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/dh_core.h> -#include <botan/numthry.h> -#include <botan/internal/pk_engine.h> -#include <botan/parsing.h> -#include <algorithm> - -namespace Botan { - -/* -* DH_Core Constructor -*/ -DH_Core::DH_Core(RandomNumberGenerator& rng, - const DL_Group& group, const BigInt& x) - { - const u32bit BLINDING_BITS = BOTAN_PRIVATE_KEY_OP_BLINDING_BITS; - - op = Engine_Core::dh_op(group, x); - - const BigInt& p = group.get_p(); - - BigInt k(rng, std::min(p.bits()-1, BLINDING_BITS)); - - if(k != 0) - blinder = Blinder(k, power_mod(inverse_mod(k, p), x, p), p); - } - -/* -* DH_Core Copy Constructor -*/ -DH_Core::DH_Core(const DH_Core& core) - { - op = 0; - if(core.op) - op = core.op->clone(); - blinder = core.blinder; - } - -/* -* DH_Core Assignment Operator -*/ -DH_Core& DH_Core::operator=(const DH_Core& core) - { - delete op; - if(core.op) - op = core.op->clone(); - blinder = core.blinder; - return (*this); - } - -/* -* DH Operation -*/ -BigInt DH_Core::agree(const BigInt& i) const - { - return blinder.unblind(op->agree(blinder.blind(i))); - } - -} diff --git a/src/pubkey/dh/dh_core.h b/src/pubkey/dh/dh_core.h deleted file mode 100644 index 91b50a27a..000000000 --- a/src/pubkey/dh/dh_core.h +++ /dev/null @@ -1,38 +0,0 @@ -/* -* DH Core -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_DH_CORE_H__ -#define BOTAN_DH_CORE_H__ - -#include <botan/dh_op.h> -#include <botan/blinding.h> - -namespace Botan { - -/* -* DH Core -*/ -class BOTAN_DLL DH_Core - { - public: - BigInt agree(const BigInt&) const; - - DH_Core& operator=(const DH_Core&); - - DH_Core() { op = 0; } - DH_Core(const DH_Core&); - DH_Core(RandomNumberGenerator& rng, - const DL_Group&, const BigInt&); - ~DH_Core() { delete op; } - private: - DH_Operation* op; - Blinder blinder; - }; - -} - -#endif diff --git a/src/pubkey/dh/dh_op.h b/src/pubkey/dh/dh_op.h deleted file mode 100644 index 50f3d7825..000000000 --- a/src/pubkey/dh/dh_op.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -* DH Operations -* (C) 1999-2008 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_DH_OPS_H__ -#define BOTAN_DH_OPS_H__ - -#include <botan/dl_group.h> -#include <botan/reducer.h> -#include <botan/pow_mod.h> - -namespace Botan { - -/* -* DH Operation Interface -*/ -class BOTAN_DLL DH_Operation - { - public: - virtual BigInt agree(const BigInt&) const = 0; - virtual DH_Operation* clone() const = 0; - virtual ~DH_Operation() {} - }; - -/* -* Botan's Default DH Operation -*/ -class BOTAN_DLL Default_DH_Op : public DH_Operation - { - public: - BigInt agree(const BigInt& i) const { return powermod_x_p(i); } - DH_Operation* clone() const { return new Default_DH_Op(*this); } - - Default_DH_Op(const DL_Group& group, const BigInt& x) : - powermod_x_p(x, group.get_p()) {} - private: - Fixed_Exponent_Power_Mod powermod_x_p; - }; - -} - -#endif diff --git a/src/pubkey/dh/info.txt b/src/pubkey/dh/info.txt index ca8f74fa1..e1e460cd0 100644 --- a/src/pubkey/dh/info.txt +++ b/src/pubkey/dh/info.txt @@ -1,14 +1,11 @@ define DIFFIE_HELLMAN <header:public> -dh_core.h -dh_op.h dh.h </header:public> <source> dh.cpp -dh_core.cpp </source> <requires> diff --git a/src/pubkey/dl_algo/dl_algo.cpp b/src/pubkey/dl_algo/dl_algo.cpp index 8ce34465a..8e326ef6a 100644 --- a/src/pubkey/dl_algo/dl_algo.cpp +++ b/src/pubkey/dl_algo/dl_algo.cpp @@ -12,120 +12,40 @@ namespace Botan { -/* -* Return the X.509 public key encoder -*/ -X509_Encoder* DL_Scheme_PublicKey::x509_encoder() const +AlgorithmIdentifier DL_Scheme_PublicKey::algorithm_identifier() const { - class DL_Scheme_Encoder : public X509_Encoder - { - public: - AlgorithmIdentifier alg_id() const - { - MemoryVector<byte> group = - key->group.DER_encode(key->group_format()); - - return AlgorithmIdentifier(key->get_oid(), group); - } - - MemoryVector<byte> key_bits() const - { - return DER_Encoder().encode(key->y).get_contents(); - } - - DL_Scheme_Encoder(const DL_Scheme_PublicKey* k) : key(k) {} - private: - const DL_Scheme_PublicKey* key; - }; - - return new DL_Scheme_Encoder(this); + return AlgorithmIdentifier(get_oid(), + group.DER_encode(group_format())); } -/* -* Return the X.509 public key decoder -*/ -X509_Decoder* DL_Scheme_PublicKey::x509_decoder() +MemoryVector<byte> DL_Scheme_PublicKey::x509_subject_public_key() const { - class DL_Scheme_Decoder : public X509_Decoder - { - public: - void alg_id(const AlgorithmIdentifier& alg_id) - { - DataSource_Memory source(alg_id.parameters); - key->group.BER_decode(source, key->group_format()); - } - - void key_bits(const MemoryRegion<byte>& bits) - { - BER_Decoder(bits).decode(key->y); - key->X509_load_hook(); - } - - DL_Scheme_Decoder(DL_Scheme_PublicKey* k) : key(k) {} - private: - DL_Scheme_PublicKey* key; - }; - - return new DL_Scheme_Decoder(this); + return DER_Encoder().encode(y).get_contents(); } -/* -* Return the PKCS #8 private key encoder -*/ -PKCS8_Encoder* DL_Scheme_PrivateKey::pkcs8_encoder() const +DL_Scheme_PublicKey::DL_Scheme_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + DL_Group::Format format) { - class DL_Scheme_Encoder : public PKCS8_Encoder - { - public: - AlgorithmIdentifier alg_id() const - { - MemoryVector<byte> group = - key->group.DER_encode(key->group_format()); - - return AlgorithmIdentifier(key->get_oid(), group); - } - - MemoryVector<byte> key_bits() const - { - return DER_Encoder().encode(key->x).get_contents(); - } - - DL_Scheme_Encoder(const DL_Scheme_PrivateKey* k) : key(k) {} - private: - const DL_Scheme_PrivateKey* key; - }; - - return new DL_Scheme_Encoder(this); + DataSource_Memory source(alg_id.parameters); + group.BER_decode(source, format); + + BER_Decoder(key_bits).decode(y); } -/* -* Return the PKCS #8 private key decoder -*/ -PKCS8_Decoder* DL_Scheme_PrivateKey::pkcs8_decoder(RandomNumberGenerator& rng) +MemoryVector<byte> DL_Scheme_PrivateKey::pkcs8_private_key() const + { + return DER_Encoder().encode(x).get_contents(); + } + +DL_Scheme_PrivateKey::DL_Scheme_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + DL_Group::Format format) { - class DL_Scheme_Decoder : public PKCS8_Decoder - { - public: - void alg_id(const AlgorithmIdentifier& alg_id) - { - DataSource_Memory source(alg_id.parameters); - key->group.BER_decode(source, key->group_format()); - } - - void key_bits(const MemoryRegion<byte>& bits) - { - BER_Decoder(bits).decode(key->x); - key->PKCS8_load_hook(rng); - } - - DL_Scheme_Decoder(DL_Scheme_PrivateKey* k, RandomNumberGenerator& r) : - key(k), rng(r) {} - private: - DL_Scheme_PrivateKey* key; - RandomNumberGenerator& rng; - }; - - return new DL_Scheme_Decoder(this, rng); + DataSource_Memory source(alg_id.parameters); + group.BER_decode(source, format); + + BER_Decoder(key_bits).decode(x); } /* diff --git a/src/pubkey/dl_algo/dl_algo.h b/src/pubkey/dl_algo/dl_algo.h index 256ce96ee..bb594a393 100644 --- a/src/pubkey/dl_algo/dl_algo.h +++ b/src/pubkey/dl_algo/dl_algo.h @@ -23,6 +23,10 @@ class BOTAN_DLL DL_Scheme_PublicKey : public virtual Public_Key public: bool check_key(RandomNumberGenerator& rng, bool) const; + AlgorithmIdentifier algorithm_identifier() const; + + MemoryVector<byte> x509_subject_public_key() const; + /** * Get the DL domain parameters of this key. * @return the DL domain parameters of this key @@ -58,23 +62,14 @@ class BOTAN_DLL DL_Scheme_PublicKey : public virtual Public_Key */ virtual DL_Group::Format group_format() const = 0; - /** - * Get an X509 encoder for this key. - * @return an encoder usable to encode this key. - */ - X509_Encoder* x509_encoder() const; + DL_Scheme_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + DL_Group::Format group_format); - /** - * Get an X509 decoder for this key. - * @return an decoder usable to decode a DL key and store the - * values in this instance. - */ - X509_Decoder* x509_decoder(); protected: + DL_Scheme_PublicKey() {} BigInt y; DL_Group group; - private: - virtual void X509_load_hook() {} }; /** @@ -92,23 +87,15 @@ class BOTAN_DLL DL_Scheme_PrivateKey : public virtual DL_Scheme_PublicKey, */ const BigInt& get_x() const { return x; } - /** - * Get an PKCS#8 encoder for this key. - * @return an encoder usable to encode this key. - */ - PKCS8_Encoder* pkcs8_encoder() const; + MemoryVector<byte> pkcs8_private_key() const; + + DL_Scheme_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + DL_Group::Format group_format); - /** - * Get an PKCS#8 decoder for this key. - * @param rng the rng to use - * @return an decoder usable to decode a DL key and store the - * values in this instance. - */ - PKCS8_Decoder* pkcs8_decoder(RandomNumberGenerator& rng); protected: + DL_Scheme_PrivateKey() {} BigInt x; - private: - virtual void PKCS8_load_hook(RandomNumberGenerator&, bool = false) {} }; } diff --git a/src/pubkey/dl_algo/info.txt b/src/pubkey/dl_algo/info.txt index 21829fa42..f6e609062 100644 --- a/src/pubkey/dl_algo/info.txt +++ b/src/pubkey/dl_algo/info.txt @@ -4,6 +4,5 @@ define DL_PUBLIC_KEY_FAMILY asn1 dl_group numbertheory -pk_codecs rng </requires> diff --git a/src/pubkey/dlies/dlies.cpp b/src/pubkey/dlies/dlies.cpp index 6ef3292e1..07477fd5d 100644 --- a/src/pubkey/dlies/dlies.cpp +++ b/src/pubkey/dlies/dlies.cpp @@ -6,7 +6,6 @@ */ #include <botan/dlies.h> -#include <botan/look_pk.h> #include <botan/internal/xor_buf.h> namespace Botan { @@ -14,12 +13,16 @@ namespace Botan { /* * DLIES_Encryptor Constructor */ -DLIES_Encryptor::DLIES_Encryptor(const PK_Key_Agreement_Key& k, +DLIES_Encryptor::DLIES_Encryptor(const PK_Key_Agreement_Key& key, KDF* kdf_obj, MessageAuthenticationCode* mac_obj, u32bit mac_kl) : - key(k), kdf(kdf_obj), mac(mac_obj), mac_keylen(mac_kl) + ka(key, "Raw"), + kdf(kdf_obj), + mac(mac_obj), + mac_keylen(mac_kl) { + my_key = key.public_value(); } DLIES_Encryptor::~DLIES_Encryptor() @@ -39,19 +42,18 @@ SecureVector<byte> DLIES_Encryptor::enc(const byte in[], u32bit length, if(other_key.empty()) throw Invalid_State("DLIES: The other key was never set"); - MemoryVector<byte> v = key.public_value(); + SecureVector<byte> out(my_key.size() + length + mac->OUTPUT_LENGTH); + out.copy(my_key, my_key.size()); + out.copy(my_key.size(), in, length); - SecureVector<byte> out(v.size() + length + mac->OUTPUT_LENGTH); - out.copy(v, v.size()); - out.copy(v.size(), in, length); - - SecureVector<byte> vz(v, key.derive_key(other_key, other_key.size())); + SecureVector<byte> vz(my_key, ka.derive_key(0, other_key).bits_of()); const u32bit K_LENGTH = length + mac_keylen; OctetString K = kdf->derive_key(K_LENGTH, vz, vz.size()); + if(K.length() != K_LENGTH) throw Encoding_Error("DLIES: KDF did not provide sufficient output"); - byte* C = out + v.size(); + byte* C = out + my_key.size(); xor_buf(C, K.begin() + mac_keylen, length); mac->set_key(K.begin(), mac_keylen); @@ -84,12 +86,16 @@ u32bit DLIES_Encryptor::maximum_input_size() const /* * DLIES_Decryptor Constructor */ -DLIES_Decryptor::DLIES_Decryptor(const PK_Key_Agreement_Key& k, +DLIES_Decryptor::DLIES_Decryptor(const PK_Key_Agreement_Key& key, KDF* kdf_obj, MessageAuthenticationCode* mac_obj, u32bit mac_kl) : - key(k), kdf(kdf_obj), mac(mac_obj), mac_keylen(mac_kl) + ka(key, "Raw"), + kdf(kdf_obj), + mac(mac_obj), + mac_keylen(mac_kl) { + my_key = key.public_value(); } DLIES_Decryptor::~DLIES_Decryptor() @@ -103,18 +109,16 @@ DLIES_Decryptor::~DLIES_Decryptor() */ SecureVector<byte> DLIES_Decryptor::dec(const byte msg[], u32bit length) const { - const u32bit public_len = key.public_value().size(); - - if(length < public_len + mac->OUTPUT_LENGTH) + if(length < my_key.size() + mac->OUTPUT_LENGTH) throw Decoding_Error("DLIES decryption: ciphertext is too short"); - const u32bit CIPHER_LEN = length - public_len - mac->OUTPUT_LENGTH; + const u32bit CIPHER_LEN = length - my_key.size() - mac->OUTPUT_LENGTH; - SecureVector<byte> v(msg, public_len); - SecureVector<byte> C(msg + public_len, CIPHER_LEN); - SecureVector<byte> T(msg + public_len + CIPHER_LEN, mac->OUTPUT_LENGTH); + SecureVector<byte> v(msg, my_key.size()); + SecureVector<byte> C(msg + my_key.size(), CIPHER_LEN); + SecureVector<byte> T(msg + my_key.size() + CIPHER_LEN, mac->OUTPUT_LENGTH); - SecureVector<byte> vz(v, key.derive_key(v, v.size())); + SecureVector<byte> vz(v, ka.derive_key(0, v).bits_of()); const u32bit K_LENGTH = C.size() + mac_keylen; OctetString K = kdf->derive_key(K_LENGTH, vz, vz.size()); diff --git a/src/pubkey/dlies/dlies.h b/src/pubkey/dlies/dlies.h index 88a22b9de..fd2cefe4a 100644 --- a/src/pubkey/dlies/dlies.h +++ b/src/pubkey/dlies/dlies.h @@ -33,9 +33,9 @@ class BOTAN_DLL DLIES_Encryptor : public PK_Encryptor RandomNumberGenerator&) const; u32bit maximum_input_size() const; - const PK_Key_Agreement_Key& key; - SecureVector<byte> other_key; + SecureVector<byte> other_key, my_key; + PK_Key_Agreement ka; KDF* kdf; MessageAuthenticationCode* mac; u32bit mac_keylen; @@ -57,8 +57,9 @@ class BOTAN_DLL DLIES_Decryptor : public PK_Decryptor private: SecureVector<byte> dec(const byte[], u32bit) const; - const PK_Key_Agreement_Key& key; + SecureVector<byte> my_key; + PK_Key_Agreement ka; KDF* kdf; MessageAuthenticationCode* mac; u32bit mac_keylen; diff --git a/src/pubkey/dsa/dsa.cpp b/src/pubkey/dsa/dsa.cpp index 5be3e1d48..feac712b8 100644 --- a/src/pubkey/dsa/dsa.cpp +++ b/src/pubkey/dsa/dsa.cpp @@ -1,6 +1,6 @@ /* * DSA -* (C) 1999-2008 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -8,7 +8,6 @@ #include <botan/dsa.h> #include <botan/numthry.h> #include <botan/keypair.h> -#include <botan/look_pk.h> namespace Botan { @@ -19,40 +18,6 @@ DSA_PublicKey::DSA_PublicKey(const DL_Group& grp, const BigInt& y1) { group = grp; y = y1; - X509_load_hook(); - } - -/* -* Algorithm Specific X.509 Initialization Code -*/ -void DSA_PublicKey::X509_load_hook() - { - core = DSA_Core(group, y); - } - -/* -* DSA Verification Function -*/ -bool DSA_PublicKey::verify(const byte msg[], u32bit msg_len, - const byte sig[], u32bit sig_len) const - { - return core.verify(msg, msg_len, sig, sig_len); - } - -/* -* Return the maximum input size in bits -*/ -u32bit DSA_PublicKey::max_input_bits() const - { - return group_q().bits(); - } - -/* -* Return the size of each portion of the sig -*/ -u32bit DSA_PublicKey::message_part_size() const - { - return group_q().bytes(); } /* @@ -66,45 +31,24 @@ DSA_PrivateKey::DSA_PrivateKey(RandomNumberGenerator& rng, x = x_arg; if(x == 0) - { x = BigInt::random_integer(rng, 2, group_q() - 1); - PKCS8_load_hook(rng, true); - } - else - PKCS8_load_hook(rng, false); - } -/* -* Algorithm Specific PKCS #8 Initialization Code -*/ -void DSA_PrivateKey::PKCS8_load_hook(RandomNumberGenerator& rng, - bool generated) - { y = power_mod(group_g(), x, group_p()); - core = DSA_Core(group, y, x); - if(generated) + if(x_arg == 0) gen_check(rng); else load_check(rng); } -/* -* DSA Signature Operation -*/ -SecureVector<byte> DSA_PrivateKey::sign(const byte in[], u32bit length, - RandomNumberGenerator& rng) const +DSA_PrivateKey::DSA_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + RandomNumberGenerator& rng) : + DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_57) { - const BigInt& q = group_q(); - - rng.add_entropy(in, length); - - BigInt k; - do - k.randomize(rng, q.bits()); - while(k >= q); + y = power_mod(group_g(), x, group_p()); - return core.sign(in, length, k); + load_check(rng); } /* @@ -120,10 +64,9 @@ bool DSA_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const try { - KeyPair::check_key(rng, - get_pk_signer(*this, "EMSA1(SHA-1)"), - get_pk_verifier(*this, "EMSA1(SHA-1)") - ); + PK_Signer this_signer(*this, "EMSA1(SHA-1)"); + PK_Verifier this_verifier(*this, "EMSA1(SHA-1)"); + KeyPair::check_key(rng, this_signer, this_verifier); } catch(Self_Test_Failure) { @@ -133,4 +76,68 @@ bool DSA_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const return true; } +DSA_Signature_Operation::DSA_Signature_Operation(const DSA_PrivateKey& dsa) : + q(dsa.group_q()), + x(dsa.get_x()), + powermod_g_p(dsa.group_g(), dsa.group_p()), + mod_q(dsa.group_q()) + { + } + +SecureVector<byte> +DSA_Signature_Operation::sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng) + { + rng.add_entropy(msg, msg_len); + + BigInt k; + do + k.randomize(rng, q.bits()); + while(k >= q); + + BigInt i(msg, msg_len); + + BigInt r = mod_q.reduce(powermod_g_p(k)); + BigInt s = mod_q.multiply(inverse_mod(k, q), mul_add(x, r, i)); + + if(r.is_zero() || s.is_zero()) + throw Internal_Error("DSA signature gen failure: r or s was zero"); + + SecureVector<byte> output(2*q.bytes()); + r.binary_encode(output + (output.size() / 2 - r.bytes())); + s.binary_encode(output + (output.size() - s.bytes())); + return output; + } + +DSA_Verification_Operation::DSA_Verification_Operation(const DSA_PublicKey& dsa) : + q(dsa.group_q()), y(dsa.get_y()) + { + powermod_g_p = Fixed_Base_Power_Mod(dsa.group_g(), dsa.group_p()); + powermod_y_p = Fixed_Base_Power_Mod(y, dsa.group_p()); + mod_p = Modular_Reducer(dsa.group_p()); + mod_q = Modular_Reducer(dsa.group_q()); + } + +bool DSA_Verification_Operation::verify(const byte msg[], u32bit msg_len, + const byte sig[], u32bit sig_len) + { + const BigInt& q = mod_q.get_modulus(); + + if(sig_len != 2*q.bytes() || msg_len > q.bytes()) + return false; + + BigInt r(sig, q.bytes()); + BigInt s(sig + q.bytes(), q.bytes()); + BigInt i(msg, msg_len); + + if(r <= 0 || r >= q || s <= 0 || s >= q) + return false; + + s = inverse_mod(s, q); + s = mod_p.multiply(powermod_g_p(mod_q.multiply(s, i)), + powermod_y_p(mod_q.multiply(s, r))); + + return (mod_q.reduce(s) == r); + } + } diff --git a/src/pubkey/dsa/dsa.h b/src/pubkey/dsa/dsa.h index 4c9b708f4..8121cfbbc 100644 --- a/src/pubkey/dsa/dsa.h +++ b/src/pubkey/dsa/dsa.h @@ -1,6 +1,6 @@ /* * DSA -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -9,52 +9,91 @@ #define BOTAN_DSA_H__ #include <botan/dl_algo.h> -#include <botan/dsa_core.h> +#include <botan/pk_ops.h> +#include <botan/reducer.h> +#include <botan/pow_mod.h> namespace Botan { /* * DSA Public Key */ -class BOTAN_DLL DSA_PublicKey : public PK_Verifying_wo_MR_Key, - public virtual DL_Scheme_PublicKey +class BOTAN_DLL DSA_PublicKey : public virtual DL_Scheme_PublicKey { public: std::string algo_name() const { return "DSA"; } DL_Group::Format group_format() const { return DL_Group::ANSI_X9_57; } u32bit message_parts() const { return 2; } - u32bit message_part_size() const; + u32bit message_part_size() const { return group_q().bytes(); } + u32bit max_input_bits() const { return group_q().bits(); } - bool verify(const byte[], u32bit, const byte[], u32bit) const; - u32bit max_input_bits() const; + DSA_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) : + DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_57) + { + } - DSA_PublicKey() {} - DSA_PublicKey(const DL_Group&, const BigInt&); + DSA_PublicKey(const DL_Group& group, const BigInt& y); protected: - DSA_Core core; - private: - void X509_load_hook(); + DSA_PublicKey() {} }; /* * DSA Private Key */ class BOTAN_DLL DSA_PrivateKey : public DSA_PublicKey, - public PK_Signing_Key, public virtual DL_Scheme_PrivateKey { public: - SecureVector<byte> sign(const byte[], u32bit, - RandomNumberGenerator& rng) const; + DSA_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + RandomNumberGenerator& rng); + + DSA_PrivateKey(RandomNumberGenerator& rng, + const DL_Group& group, + const BigInt& private_key = 0); + + bool check_key(RandomNumberGenerator& rng, bool strong) const; + }; + +class BOTAN_DLL DSA_Signature_Operation : public PK_Ops::Signature + { + public: + DSA_Signature_Operation(const DSA_PrivateKey& dsa); + + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return q.bytes(); } + u32bit max_input_bits() const { return q.bits(); } + + SecureVector<byte> sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng); + private: + const BigInt& q; + const BigInt& x; + Fixed_Base_Power_Mod powermod_g_p; + Modular_Reducer mod_q; + }; + +class BOTAN_DLL DSA_Verification_Operation : public PK_Ops::Verification + { + public: + DSA_Verification_Operation(const DSA_PublicKey& dsa); - bool check_key(RandomNumberGenerator& rng, bool) const; + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return q.bytes(); } + u32bit max_input_bits() const { return q.bits(); } - DSA_PrivateKey() {} - DSA_PrivateKey(RandomNumberGenerator&, const DL_Group&, - const BigInt& = 0); + bool with_recovery() const { return false; } + + bool verify(const byte msg[], u32bit msg_len, + const byte sig[], u32bit sig_len); private: - void PKCS8_load_hook(RandomNumberGenerator& rng, bool = false); + const BigInt& q; + const BigInt& y; + + Fixed_Base_Power_Mod powermod_g_p, powermod_y_p; + Modular_Reducer mod_p, mod_q; }; } diff --git a/src/pubkey/dsa/dsa_core.cpp b/src/pubkey/dsa/dsa_core.cpp deleted file mode 100644 index d952e10eb..000000000 --- a/src/pubkey/dsa/dsa_core.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* -* DSA Core -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/dsa_core.h> -#include <botan/numthry.h> -#include <botan/internal/pk_engine.h> -#include <botan/parsing.h> -#include <algorithm> - -namespace Botan { - -/* -* DSA_Core Constructor -*/ -DSA_Core::DSA_Core(const DL_Group& group, const BigInt& y, const BigInt& x) - { - op = Engine_Core::dsa_op(group, y, x); - } - -/* -* DSA_Core Copy Constructor -*/ -DSA_Core::DSA_Core(const DSA_Core& core) - { - op = 0; - if(core.op) - op = core.op->clone(); - } - -/* -* DSA_Core Assignment Operator -*/ -DSA_Core& DSA_Core::operator=(const DSA_Core& core) - { - delete op; - if(core.op) - op = core.op->clone(); - return (*this); - } - -/* -* DSA Verification Operation -*/ -bool DSA_Core::verify(const byte msg[], u32bit msg_length, - const byte sig[], u32bit sig_length) const - { - return op->verify(msg, msg_length, sig, sig_length); - } - -/* -* DSA Signature Operation -*/ -SecureVector<byte> DSA_Core::sign(const byte in[], u32bit length, - const BigInt& k) const - { - return op->sign(in, length, k); - } - -} diff --git a/src/pubkey/dsa/dsa_core.h b/src/pubkey/dsa/dsa_core.h deleted file mode 100644 index 8bb16211f..000000000 --- a/src/pubkey/dsa/dsa_core.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -* DSA Core -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_DSA_CORE_H__ -#define BOTAN_DSA_CORE_H__ - -#include <botan/dsa_op.h> -#include <botan/dl_group.h> - -namespace Botan { - -/* -* DSA Core -*/ -class BOTAN_DLL DSA_Core - { - public: - SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const; - bool verify(const byte[], u32bit, const byte[], u32bit) const; - - DSA_Core& operator=(const DSA_Core&); - - DSA_Core() { op = 0; } - DSA_Core(const DSA_Core&); - DSA_Core(const DL_Group&, const BigInt&, const BigInt& = 0); - ~DSA_Core() { delete op; } - private: - DSA_Operation* op; - }; - -} - -#endif diff --git a/src/pubkey/dsa/dsa_op.cpp b/src/pubkey/dsa/dsa_op.cpp deleted file mode 100644 index e83fd83b7..000000000 --- a/src/pubkey/dsa/dsa_op.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* -* DSA Operations -* (C) 1999-2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/dsa_op.h> -#include <future> - -namespace Botan { - -/* -* Default_DSA_Op Constructor -*/ -Default_DSA_Op::Default_DSA_Op(const DL_Group& grp, const BigInt& y1, - const BigInt& x1) : x(x1), y(y1), group(grp) - { - powermod_g_p = Fixed_Base_Power_Mod(group.get_g(), group.get_p()); - powermod_y_p = Fixed_Base_Power_Mod(y, group.get_p()); - mod_p = Modular_Reducer(group.get_p()); - mod_q = Modular_Reducer(group.get_q()); - } - -/* -* Default DSA Verify Operation -*/ -bool Default_DSA_Op::verify(const byte msg[], u32bit msg_len, - const byte sig[], u32bit sig_len) const - { - const BigInt& q = group.get_q(); - - if(sig_len != 2*q.bytes() || msg_len > q.bytes()) - return false; - - BigInt r(sig, q.bytes()); - BigInt s(sig + q.bytes(), q.bytes()); - BigInt i(msg, msg_len); - - if(r <= 0 || r >= q || s <= 0 || s >= q) - return false; - - s = inverse_mod(s, q); - - auto future_s_i = std::async(std::launch::async, - [&]() { return powermod_g_p(mod_q.multiply(s, i)); }); - - BigInt s_r = powermod_y_p(mod_q.multiply(s, r)); - BigInt s_i = future_s_i.get(); - - s = mod_p.multiply(s_i, s_r); - - return (mod_q.reduce(s) == r); - } - -/* -* Default DSA Sign Operation -*/ -SecureVector<byte> Default_DSA_Op::sign(const byte in[], u32bit length, - const BigInt& k) const - { - if(x == 0) - throw Internal_Error("Default_DSA_Op::sign: No private key"); - - auto future_r = std::async(std::launch::async, - [&]() { return mod_q.reduce(powermod_g_p(k)); }); - - const BigInt& q = group.get_q(); - BigInt i(in, length); - - BigInt s = inverse_mod(k, q); - BigInt r = future_r.get(); - - s = mod_q.multiply(s, mul_add(x, r, i)); - - if(r.is_zero() || s.is_zero()) - throw Internal_Error("Default_DSA_Op::sign: r or s was zero"); - - SecureVector<byte> output(2*q.bytes()); - r.binary_encode(output + (output.size() / 2 - r.bytes())); - s.binary_encode(output + (output.size() - s.bytes())); - return output; - } - -} diff --git a/src/pubkey/dsa/dsa_op.h b/src/pubkey/dsa/dsa_op.h deleted file mode 100644 index 47a9d09e1..000000000 --- a/src/pubkey/dsa/dsa_op.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -* DSA Operations -* (C) 1999-2008 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_DSA_OPS_H__ -#define BOTAN_DSA_OPS_H__ - -#include <botan/numthry.h> -#include <botan/pow_mod.h> -#include <botan/reducer.h> -#include <botan/dl_group.h> - -namespace Botan { - -/* -* DSA Operation -*/ -class BOTAN_DLL DSA_Operation - { - public: - virtual bool verify(const byte msg[], u32bit msg_len, - const byte sig[], u32bit sig_len) const = 0; - - virtual SecureVector<byte> sign(const byte msg[], u32bit msg_len, - const BigInt& k) const = 0; - - virtual DSA_Operation* clone() const = 0; - - virtual ~DSA_Operation() {} - }; - -/* -* Botan's Default DSA Operation -*/ -class BOTAN_DLL Default_DSA_Op : public DSA_Operation - { - public: - bool verify(const byte msg[], u32bit msg_len, - const byte sig[], u32bit sig_len) const; - - SecureVector<byte> sign(const byte msg[], u32bit msg_len, - const BigInt& k) const; - - DSA_Operation* clone() const { return new Default_DSA_Op(*this); } - - Default_DSA_Op(const DL_Group&, const BigInt&, const BigInt&); - private: - const BigInt x, y; - const DL_Group group; - Fixed_Base_Power_Mod powermod_g_p, powermod_y_p; - Modular_Reducer mod_p, mod_q; - }; - -} - -#endif diff --git a/src/pubkey/dsa/info.txt b/src/pubkey/dsa/info.txt index 1248cf68d..d59fe7aa7 100644 --- a/src/pubkey/dsa/info.txt +++ b/src/pubkey/dsa/info.txt @@ -1,17 +1,5 @@ define DSA -<header:public> -dsa.h -dsa_core.h -dsa_op.h -</header:public> - -<source> -dsa.cpp -dsa_core.cpp -dsa_op.cpp -</source> - <requires> dl_algo dl_group diff --git a/src/pubkey/ec_dompar/ec_dompar.cpp b/src/pubkey/ec_dompar/ec_dompar.cpp index 7910e898f..42ae9211e 100644 --- a/src/pubkey/ec_dompar/ec_dompar.cpp +++ b/src/pubkey/ec_dompar/ec_dompar.cpp @@ -35,7 +35,7 @@ EC_Domain_Params::EC_Domain_Params(const std::string& pem) DataSource_Memory input(pem); *this = EC_Domain_Params( - PEM_Code::decode_check_label(input, "ECC DOMAIN PARAMETERS")); + PEM_Code::decode_check_label(input, "EC PARAMETERS")); } } @@ -136,7 +136,7 @@ EC_Domain_Params::DER_encode(EC_Domain_Params_Encoding form) const std::string EC_Domain_Params::PEM_encode() const { SecureVector<byte> der = DER_encode(EC_DOMPAR_ENC_EXPLICIT); - return PEM_Code::encode(der, "ECC DOMAIN PARAMETERS"); + return PEM_Code::encode(der, "EC PARAMETERS"); } } diff --git a/src/pubkey/ecc_key/ecc_key.cpp b/src/pubkey/ecc_key/ecc_key.cpp index 10968fa7e..a4bd9b635 100644 --- a/src/pubkey/ecc_key/ecc_key.cpp +++ b/src/pubkey/ecc_key/ecc_key.cpp @@ -35,8 +35,14 @@ EC_PublicKey::EC_PublicKey(const EC_Domain_Params& dom_par, } } -void EC_PublicKey::X509_load_hook() +EC_PublicKey::EC_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) { + domain_params = EC_Domain_Params(alg_id.parameters); + domain_encoding = EC_DOMPAR_ENC_EXPLICIT; + + public_key = PointGFp(OS2ECP(key_bits, domain().get_curve())); + try { public_point().check_invariants(); @@ -47,54 +53,14 @@ void EC_PublicKey::X509_load_hook() } } -X509_Encoder* EC_PublicKey::x509_encoder() const +AlgorithmIdentifier EC_PublicKey::algorithm_identifier() const { - class EC_Key_Encoder : public X509_Encoder - { - public: - AlgorithmIdentifier alg_id() const - { - return AlgorithmIdentifier(key->get_oid(), - key->domain().DER_encode(key->domain_format())); - } - - MemoryVector<byte> key_bits() const - { - return EC2OSP(key->public_point(), PointGFp::COMPRESSED); - } - - EC_Key_Encoder(const EC_PublicKey* k): key(k) {} - private: - const EC_PublicKey* key; - }; - - return new EC_Key_Encoder(this); + return AlgorithmIdentifier(get_oid(), DER_domain()); } -X509_Decoder* EC_PublicKey::x509_decoder() +MemoryVector<byte> EC_PublicKey::x509_subject_public_key() const { - class EC_Key_Decoder : public X509_Decoder - { - public: - void alg_id(const AlgorithmIdentifier& alg_id) - { - key->domain_params = EC_Domain_Params(alg_id.parameters); - } - - void key_bits(const MemoryRegion<byte>& bits) - { - key->public_key = PointGFp( - OS2ECP(bits, key->domain().get_curve())); - - key->X509_load_hook(); - } - - EC_Key_Decoder(EC_PublicKey* k): key(k) {} - private: - EC_PublicKey* key; - }; - - return new EC_Key_Decoder(this); + return EC2OSP(public_point(), PointGFp::COMPRESSED); } void EC_PublicKey::set_parameter_encoding(EC_Domain_Params_Encoding form) @@ -122,21 +88,25 @@ const BigInt& EC_PrivateKey::private_value() const /** * EC_PrivateKey generator -**/ +*/ EC_PrivateKey::EC_PrivateKey(const EC_Domain_Params& dom_par, - const BigInt& priv_key) : - EC_PublicKey(dom_par, dom_par.get_base_point() * private_key), - private_key(priv_key) + const BigInt& priv_key) { + domain_params = dom_par; + domain_encoding = EC_DOMPAR_ENC_EXPLICIT; + + public_key = domain().get_base_point() * priv_key; + private_key = priv_key; } /** * EC_PrivateKey generator -**/ +*/ EC_PrivateKey::EC_PrivateKey(RandomNumberGenerator& rng, const EC_Domain_Params& dom_par) { domain_params = dom_par; + domain_encoding = EC_DOMPAR_ENC_EXPLICIT; private_key = BigInt::random_integer(rng, 1, domain().get_order()); public_key = domain().get_base_point() * private_key; @@ -145,89 +115,54 @@ EC_PrivateKey::EC_PrivateKey(RandomNumberGenerator& rng, { public_key.check_invariants(); } - catch(Illegal_Point& e) + catch(Illegal_Point) { throw Internal_Error("ECC private key generation failed"); } } -/** -* Return the PKCS #8 public key encoder -**/ -PKCS8_Encoder* EC_PrivateKey::pkcs8_encoder() const +MemoryVector<byte> EC_PrivateKey::pkcs8_private_key() const { - class EC_Key_Encoder : public PKCS8_Encoder - { - public: - AlgorithmIdentifier alg_id() const - { - return AlgorithmIdentifier(key->get_oid(), - key->domain().DER_encode(EC_DOMPAR_ENC_EXPLICIT)); - } - - MemoryVector<byte> key_bits() const - { - return DER_Encoder() - .start_cons(SEQUENCE) - .encode(BigInt(1)) - .encode(BigInt::encode_1363(key->private_key, key->private_key.bytes()), - OCTET_STRING) - .end_cons() - .get_contents(); - } - - EC_Key_Encoder(const EC_PrivateKey* k): key(k) {} - private: - const EC_PrivateKey* key; - }; - - return new EC_Key_Encoder(this); + return DER_Encoder() + .start_cons(SEQUENCE) + .encode(BigInt(1)) + .encode(BigInt::encode_1363(private_key, private_key.bytes()), + OCTET_STRING) + .end_cons() + .get_contents(); } -/** -* Return the PKCS #8 public key decoder -*/ -PKCS8_Decoder* EC_PrivateKey::pkcs8_decoder(RandomNumberGenerator&) +EC_PrivateKey::EC_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) { - class EC_Key_Decoder : public PKCS8_Decoder - { - public: - void alg_id(const AlgorithmIdentifier& alg_id) - { - key->domain_params = EC_Domain_Params(alg_id.parameters); - } - - void key_bits(const MemoryRegion<byte>& bits) - { - u32bit version; - SecureVector<byte> octstr_secret; - - BER_Decoder(bits) - .start_cons(SEQUENCE) - .decode(version) - .decode(octstr_secret, OCTET_STRING) - .verify_end() - .end_cons(); - - key->private_key = BigInt::decode(octstr_secret, octstr_secret.size()); - - if(version != 1) - throw Decoding_Error("Wrong PKCS #1 key format version for EC key"); - - key->PKCS8_load_hook(); - } - - EC_Key_Decoder(EC_PrivateKey* k): key(k) {} - private: - EC_PrivateKey* key; - }; - - return new EC_Key_Decoder(this); - } + domain_params = EC_Domain_Params(alg_id.parameters); + domain_encoding = EC_DOMPAR_ENC_EXPLICIT; + + u32bit version; + SecureVector<byte> octstr_secret; + + BER_Decoder(key_bits) + .start_cons(SEQUENCE) + .decode(version) + .decode(octstr_secret, OCTET_STRING) + .verify_end() + .end_cons(); + + if(version != 1) + throw Decoding_Error("Wrong key format version for EC key"); + + private_key = BigInt::decode(octstr_secret, octstr_secret.size()); -void EC_PrivateKey::PKCS8_load_hook(bool) - { public_key = domain().get_base_point() * private_key; + + try + { + public_key.check_invariants(); + } + catch(Illegal_Point) + { + throw Internal_Error("Loaded ECC private key failed self test"); + } } } diff --git a/src/pubkey/ecc_key/ecc_key.h b/src/pubkey/ecc_key/ecc_key.h index 653f97cab..92f02613c 100644 --- a/src/pubkey/ecc_key/ecc_key.h +++ b/src/pubkey/ecc_key/ecc_key.h @@ -31,6 +31,11 @@ namespace Botan { class BOTAN_DLL EC_PublicKey : public virtual Public_Key { public: + EC_PublicKey(const EC_Domain_Params& dom_par, + const PointGFp& pub_point); + + EC_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits); /** * Get the public point of this key. @@ -40,6 +45,10 @@ class BOTAN_DLL EC_PublicKey : public virtual Public_Key */ const PointGFp& public_point() const { return public_key; } + AlgorithmIdentifier algorithm_identifier() const; + + MemoryVector<byte> x509_subject_public_key() const; + /** * Get the domain parameters of this key. * @throw Invalid_State is thrown if the @@ -55,33 +64,20 @@ class BOTAN_DLL EC_PublicKey : public virtual Public_Key void set_parameter_encoding(EC_Domain_Params_Encoding enc); /** + * Return the DER encoding of this keys domain in whatever format + * is preset for this particular key + */ + MemoryVector<byte> DER_domain() const + { return domain().DER_encode(domain_format()); } + + /** * Get the domain parameter encoding to be used when encoding this key. * @result the encoding to use */ EC_Domain_Params_Encoding domain_format() const { return domain_encoding; } - - /** - * Get an x509_encoder that can be used to encode this key. - * @result an x509_encoder for this key - */ - X509_Encoder* x509_encoder() const; - - /** - * Get an x509_decoder that can be used to decode a stored key into - * this key. - * @result an x509_decoder for this key - */ - X509_Decoder* x509_decoder(); - - EC_PublicKey() : domain_encoding(EC_DOMPAR_ENC_EXPLICIT) {} - - EC_PublicKey(const EC_Domain_Params& dom_par, - const PointGFp& pub_point); - - virtual ~EC_PublicKey() {} protected: - virtual void X509_load_hook(); + EC_PublicKey() : domain_encoding(EC_DOMPAR_ENC_EXPLICIT) {} EC_Domain_Params domain_params; PointGFp public_key; @@ -95,28 +91,16 @@ class BOTAN_DLL EC_PrivateKey : public virtual EC_PublicKey, public virtual Private_Key { public: - EC_PrivateKey() {} - EC_PrivateKey(const EC_Domain_Params& domain, const BigInt& private_key); EC_PrivateKey(RandomNumberGenerator& rng, const EC_Domain_Params& domain); - virtual ~EC_PrivateKey() {} + EC_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits); - /** - * Get an PKCS#8 encoder that can be used to encoded this key. - * @result an PKCS#8 encoder for this key - */ - PKCS8_Encoder* pkcs8_encoder() const; - - /** - * Get an PKCS#8 decoder that can be used to decoded a stored key into - * this key. - * @result an PKCS#8 decoder for this key - */ - PKCS8_Decoder* pkcs8_decoder(RandomNumberGenerator&); + MemoryVector<byte> pkcs8_private_key() const; /** * Get the private key value of this key object. @@ -124,7 +108,7 @@ class BOTAN_DLL EC_PrivateKey : public virtual EC_PublicKey, */ const BigInt& private_value() const; protected: - virtual void PKCS8_load_hook(bool = false); + EC_PrivateKey() {} BigInt private_key; }; diff --git a/src/pubkey/ecc_key/info.txt b/src/pubkey/ecc_key/info.txt index 4650fb612..e08a4231d 100644 --- a/src/pubkey/ecc_key/info.txt +++ b/src/pubkey/ecc_key/info.txt @@ -6,5 +6,4 @@ asn1 bigint ec_dompar numbertheory -pk_codecs </requires> diff --git a/src/pubkey/ecdh/ecdh.cpp b/src/pubkey/ecdh/ecdh.cpp index 7577a8569..bf8a57b3b 100644 --- a/src/pubkey/ecdh/ecdh.cpp +++ b/src/pubkey/ecdh/ecdh.cpp @@ -11,41 +11,23 @@ namespace Botan { -/** -* Derive a key -*/ -SecureVector<byte> ECDH_PrivateKey::derive_key(const byte key[], - u32bit key_len) const - { - MemoryVector<byte> key_x(key, key_len); // FIXME: nasty/slow - PointGFp point = OS2ECP(key_x, public_point().get_curve()); - - return derive_key(point); - } - -/** -* Derive a key -*/ -SecureVector<byte> ECDH_PrivateKey::derive_key(const ECDH_PublicKey& key) const +ECDH_KA_Operation::ECDH_KA_Operation(const ECDH_PrivateKey& key) : + curve(key.domain().get_curve()), + cofactor(key.domain().get_cofactor()) { - return derive_key(key.public_point()); + l_times_priv = inverse_mod(cofactor, key.domain().get_order()) * + key.private_value(); } -/** -* Derive a key -*/ -SecureVector<byte> ECDH_PrivateKey::derive_key(const PointGFp& point) const +SecureVector<byte> ECDH_KA_Operation::agree(const byte w[], u32bit w_len) { - const BigInt& cofactor = domain().get_cofactor(); - const BigInt& n = domain().get_order(); - - BigInt l = inverse_mod(cofactor, n); // can precompute this + PointGFp point = OS2ECP(w, w_len, curve); - PointGFp S = (cofactor * point) * (private_value() * l); + PointGFp S = (cofactor * point) * l_times_priv; S.check_invariants(); return BigInt::encode_1363(S.get_affine_x(), - point.get_curve().get_p().bytes()); + curve.get_p().bytes()); } } diff --git a/src/pubkey/ecdh/ecdh.h b/src/pubkey/ecdh/ecdh.h index 630237edf..d670361f6 100644 --- a/src/pubkey/ecdh/ecdh.h +++ b/src/pubkey/ecdh/ecdh.h @@ -11,6 +11,7 @@ #define BOTAN_ECDH_KEY_H__ #include <botan/ecc_key.h> +#include <botan/pk_ops.h> namespace Botan { @@ -21,11 +22,10 @@ class BOTAN_DLL ECDH_PublicKey : public virtual EC_PublicKey { public: - /** - * Default constructor. Use this one if you want to later fill - * this object with data from an encoded key. - */ - ECDH_PublicKey() {} + + ECDH_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) : + EC_PublicKey(alg_id, key_bits) {} /** * Construct a public key from a given public point. @@ -49,6 +49,8 @@ class BOTAN_DLL ECDH_PublicKey : public virtual EC_PublicKey * @result the maximum number of input bits */ u32bit max_input_bits() const { return domain().get_order().bits(); } + protected: + ECDH_PublicKey() {} }; /** @@ -60,11 +62,9 @@ class BOTAN_DLL ECDH_PrivateKey : public ECDH_PublicKey, { public: - /** - * Default constructor. Use this one if you want to later fill - * this object with data from an encoded key. - */ - ECDH_PrivateKey() {} + ECDH_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) : + EC_PrivateKey(alg_id, key_bits) {} /** * Generate a new private key @@ -76,25 +76,21 @@ class BOTAN_DLL ECDH_PrivateKey : public ECDH_PublicKey, MemoryVector<byte> public_value() const { return EC2OSP(public_point(), PointGFp::UNCOMPRESSED); } + }; - /** - * Derive a shared key with the other parties public key. - * @param key the other partys public key - * @param key_len the other partys public key - */ - SecureVector<byte> derive_key(const byte key[], u32bit key_len) const; - - /** - * Derive a shared key with the other parties public key. - * @param other the other partys public key - */ - SecureVector<byte> derive_key(const ECDH_PublicKey& other) const; +/** +* ECDH operation +*/ +class BOTAN_DLL ECDH_KA_Operation : public PK_Ops::Key_Agreement + { + public: + ECDH_KA_Operation(const ECDH_PrivateKey& key); - /** - * Derive a shared key with the other parties public key. - * @param point the public point of the other parties key - */ - SecureVector<byte> derive_key(const PointGFp& point) const; + SecureVector<byte> agree(const byte w[], u32bit w_len); + private: + const CurveGFp& curve; + const BigInt& cofactor; + BigInt l_times_priv; }; } diff --git a/src/pubkey/ecdsa/ecdsa.cpp b/src/pubkey/ecdsa/ecdsa.cpp index d245543f7..afca6cc73 100644 --- a/src/pubkey/ecdsa/ecdsa.cpp +++ b/src/pubkey/ecdsa/ecdsa.cpp @@ -11,64 +11,71 @@ namespace Botan { -bool ECDSA_PublicKey::verify(const byte msg[], u32bit msg_len, - const byte sig[], u32bit sig_len) const +ECDSA_Signature_Operation::ECDSA_Signature_Operation(const ECDSA_PrivateKey& ecdsa) : + base_point(ecdsa.domain().get_base_point()), + order(ecdsa.domain().get_order()), + x(ecdsa.private_value()) { - const BigInt& n = domain().get_order(); + } - if(n == 0) - throw Invalid_State("ECDSA_PublicKey::verify: Not initialized"); +SecureVector<byte> +ECDSA_Signature_Operation::sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng) + { + rng.add_entropy(msg, msg_len); - if(sig_len != n.bytes()*2) - return false; + BigInt k; + k.randomize(rng, order.bits()); + + while(k >= order) + k.randomize(rng, order.bits() - 1); BigInt e(msg, msg_len); - BigInt r(sig, sig_len / 2); - BigInt s(sig + sig_len / 2, sig_len / 2); + PointGFp k_times_P = base_point * k; + BigInt r = k_times_P.get_affine_x() % order; - if(r < 0 || r >= n || s < 0 || s >= n) - return false; + if(r == 0) + throw Internal_Error("ECDSA_Signature_Operation: r was zero"); - BigInt w = inverse_mod(s, n); + BigInt k_inv = inverse_mod(k, order); - PointGFp R = w * (e * domain().get_base_point() + r*public_point()); - if(R.is_zero()) - return false; + BigInt s = (((r * x) + e) * k_inv) % order; - return (R.get_affine_x() % n == r); + SecureVector<byte> output(2*order.bytes()); + r.binary_encode(output + (output.size() / 2 - r.bytes())); + s.binary_encode(output + (output.size() - s.bytes())); + return output; } -SecureVector<byte> ECDSA_PrivateKey::sign(const byte msg[], - u32bit msg_len, - RandomNumberGenerator& rng) const +ECDSA_Verification_Operation::ECDSA_Verification_Operation(const ECDSA_PublicKey& ecdsa) : + base_point(ecdsa.domain().get_base_point()), + public_point(ecdsa.public_point()), + order(ecdsa.domain().get_order()) { - const BigInt& n = domain().get_order(); - - if(n == 0 || private_value() == 0) - throw Invalid_State("ECDSA_PrivateKey::sign: Not initialized"); + } - BigInt k; - do - k.randomize(rng, n.bits()-1); - while(k >= n); +bool ECDSA_Verification_Operation::verify(const byte msg[], u32bit msg_len, + const byte sig[], u32bit sig_len) + { + if(sig_len != order.bytes()*2) + return false; BigInt e(msg, msg_len); - PointGFp k_times_P = domain().get_base_point() * k; - BigInt r = k_times_P.get_affine_x() % n; + BigInt r(sig, sig_len / 2); + BigInt s(sig + sig_len / 2, sig_len / 2); - if(r == 0) - throw Internal_Error("Default_ECDSA_Op::sign: r was zero"); + if(r < 0 || r >= order || s < 0 || s >= order) + return false; - BigInt k_inv = inverse_mod(k, n); + BigInt w = inverse_mod(s, order); - BigInt s = (((r * private_value()) + e) * k_inv) % n; + PointGFp R = w * (e * base_point + r * public_point); + if(R.is_zero()) + return false; - SecureVector<byte> output(2*n.bytes()); - r.binary_encode(output + (output.size() / 2 - r.bytes())); - s.binary_encode(output + (output.size() - s.bytes())); - return output; + return (R.get_affine_x() % order == r); } } diff --git a/src/pubkey/ecdsa/ecdsa.h b/src/pubkey/ecdsa/ecdsa.h index e7f29b600..e20a234fc 100644 --- a/src/pubkey/ecdsa/ecdsa.h +++ b/src/pubkey/ecdsa/ecdsa.h @@ -11,18 +11,31 @@ #define BOTAN_ECDSA_KEY_H__ #include <botan/ecc_key.h> +#include <botan/pk_ops.h> namespace Botan { /** * This class represents ECDSA Public Keys. */ -class BOTAN_DLL ECDSA_PublicKey : public virtual EC_PublicKey, - public PK_Verifying_wo_MR_Key +class BOTAN_DLL ECDSA_PublicKey : public virtual EC_PublicKey { public: /** + * Construct a public key from a given public point. + * @param dom_par the domain parameters associated with this key + * @param public_point the public point defining this key + */ + ECDSA_PublicKey(const EC_Domain_Params& dom_par, + const PointGFp& public_point) : + EC_PublicKey(dom_par, public_point) {} + + ECDSA_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) : + EC_PublicKey(alg_id, key_bits) {} + + /** * Get this keys algorithm name. * @result this keys algorithm name ("ECDSA") */ @@ -40,46 +53,21 @@ class BOTAN_DLL ECDSA_PublicKey : public virtual EC_PublicKey, u32bit message_part_size() const { return domain().get_order().bytes(); } - /** - * Verify a message with this key. - * @param message the byte array containing the message - * @param mess_len the number of bytes in the message byte array - * @param signature the byte array containing the signature - * @param sig_len the number of bytes in the signature byte array - */ - bool verify(const byte message[], u32bit mess_len, - const byte signature[], u32bit sig_len) const; - - /** - * Default constructor. Use this one if you want to later fill - * this object with data from an encoded key. - */ + protected: ECDSA_PublicKey() {} - - /** - * Construct a public key from a given public point. - * @param dom_par the domain parameters associated with this key - * @param public_point the public point defining this key - */ - ECDSA_PublicKey(const EC_Domain_Params& dom_par, - const PointGFp& public_point) : - EC_PublicKey(dom_par, public_point) {} - }; /** * This class represents ECDSA Private Keys */ class BOTAN_DLL ECDSA_PrivateKey : public ECDSA_PublicKey, - public EC_PrivateKey, - public PK_Signing_Key + public EC_PrivateKey { public: - /** - * Default constructor. Use this one if you want to later fill - * this object with data from an encoded key. - */ - ECDSA_PrivateKey() {} + + ECDSA_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) : + EC_PrivateKey(alg_id, key_bits) {} /** * Generate a new private key @@ -96,16 +84,43 @@ class BOTAN_DLL ECDSA_PrivateKey : public ECDSA_PublicKey, */ ECDSA_PrivateKey(const EC_Domain_Params& domain, const BigInt& x) : EC_PrivateKey(domain, x) {} + }; - /** - * Sign a message with this key. - * @param message the byte array representing the message to be signed - * @param mess_len the length of the message byte array - * @result the signature - */ +class BOTAN_DLL ECDSA_Signature_Operation : public PK_Ops::Signature + { + public: + ECDSA_Signature_Operation(const ECDSA_PrivateKey& ecdsa); + + SecureVector<byte> sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng); + + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return order.bytes(); } + u32bit max_input_bits() const { return order.bits(); } + + private: + const PointGFp& base_point; + const BigInt& order; + const BigInt& x; + }; + +class BOTAN_DLL ECDSA_Verification_Operation : public PK_Ops::Verification + { + public: + ECDSA_Verification_Operation(const ECDSA_PublicKey& ecdsa); + + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return order.bytes(); } + u32bit max_input_bits() const { return order.bits(); } + + bool with_recovery() const { return false; } - SecureVector<byte> sign(const byte message[], u32bit mess_len, - RandomNumberGenerator& rng) const; + bool verify(const byte msg[], u32bit msg_len, + const byte sig[], u32bit sig_len); + private: + const PointGFp& base_point; + const PointGFp& public_point; + const BigInt& order; }; } diff --git a/src/pubkey/elgamal/elg_core.cpp b/src/pubkey/elgamal/elg_core.cpp deleted file mode 100644 index 0005c4ffc..000000000 --- a/src/pubkey/elgamal/elg_core.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* -* ElGamal Core -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/elg_core.h> -#include <botan/numthry.h> -#include <botan/internal/pk_engine.h> -#include <botan/parsing.h> -#include <algorithm> - -namespace Botan { - -/* -* ELG_Core Constructor -*/ -ELG_Core::ELG_Core(const DL_Group& group, const BigInt& y) - { - op = Engine_Core::elg_op(group, y, 0); - p_bytes = 0; - } - -/* -* ELG_Core Constructor -*/ -ELG_Core::ELG_Core(RandomNumberGenerator& rng, - const DL_Group& group, const BigInt& y, const BigInt& x) - { - const u32bit BLINDING_BITS = BOTAN_PRIVATE_KEY_OP_BLINDING_BITS; - - op = Engine_Core::elg_op(group, y, x); - - const BigInt& p = group.get_p(); - p_bytes = p.bytes(); - - if(BLINDING_BITS) - { - BigInt k(rng, std::min(p.bits()-1, BLINDING_BITS)); - blinder = Blinder(k, power_mod(k, x, p), p); - } - } - -/* -* ELG_Core Copy Constructor -*/ -ELG_Core::ELG_Core(const ELG_Core& core) - { - op = 0; - if(core.op) - op = core.op->clone(); - blinder = core.blinder; - p_bytes = core.p_bytes; - } - -/* -* ELG_Core Assignment Operator -*/ -ELG_Core& ELG_Core::operator=(const ELG_Core& core) - { - delete op; - if(core.op) - op = core.op->clone(); - blinder = core.blinder; - p_bytes = core.p_bytes; - return (*this); - } - -/* -* ElGamal Encrypt Operation -*/ -SecureVector<byte> ELG_Core::encrypt(const byte in[], u32bit length, - const BigInt& k) const - { - return op->encrypt(in, length, k); - } - -/* -* ElGamal Decrypt Operation -*/ -SecureVector<byte> ELG_Core::decrypt(const byte in[], u32bit length) const - { - if(length != 2*p_bytes) - throw Invalid_Argument("ELG_Core::decrypt: Invalid message"); - - BigInt a(in, p_bytes); - BigInt b(in + p_bytes, p_bytes); - - return BigInt::encode(blinder.unblind(op->decrypt(blinder.blind(a), b))); - } - -} diff --git a/src/pubkey/elgamal/elg_core.h b/src/pubkey/elgamal/elg_core.h deleted file mode 100644 index a7768a6ae..000000000 --- a/src/pubkey/elgamal/elg_core.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -* ElGamal Core -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_ELGAMAL_CORE_H__ -#define BOTAN_ELGAMAL_CORE_H__ - -#include <botan/elg_op.h> -#include <botan/blinding.h> -#include <botan/dl_group.h> - -namespace Botan { - -/* -* ElGamal Core -*/ -class BOTAN_DLL ELG_Core - { - public: - SecureVector<byte> encrypt(const byte[], u32bit, const BigInt&) const; - SecureVector<byte> decrypt(const byte[], u32bit) const; - - ELG_Core& operator=(const ELG_Core&); - - ELG_Core() { op = 0; } - ELG_Core(const ELG_Core&); - - ELG_Core(const DL_Group&, const BigInt&); - ELG_Core(RandomNumberGenerator&, const DL_Group&, - const BigInt&, const BigInt&); - - ~ELG_Core() { delete op; } - private: - ELG_Operation* op; - Blinder blinder; - u32bit p_bytes; - }; - -} - -#endif diff --git a/src/pubkey/elgamal/elg_op.cpp b/src/pubkey/elgamal/elg_op.cpp deleted file mode 100644 index 4bde60bee..000000000 --- a/src/pubkey/elgamal/elg_op.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* -* ElGamal Operations -* (C) 1999-2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/elg_op.h> -#include <future> - -namespace Botan { - -/* -* Default_ELG_Op Constructor -*/ -Default_ELG_Op::Default_ELG_Op(const DL_Group& group, const BigInt& y, - const BigInt& x) : p(group.get_p()) - { - powermod_g_p = Fixed_Base_Power_Mod(group.get_g(), p); - powermod_y_p = Fixed_Base_Power_Mod(y, p); - mod_p = Modular_Reducer(p); - - if(x != 0) - powermod_x_p = Fixed_Exponent_Power_Mod(x, p); - } - -/* -* Default ElGamal Encrypt Operation -*/ -SecureVector<byte> Default_ELG_Op::encrypt(const byte in[], u32bit length, - const BigInt& k) const - { - BigInt m(in, length); - if(m >= p) - throw Invalid_Argument("Default_ELG_Op::encrypt: Input is too large"); - - auto future_a = std::async(std::launch::async, powermod_g_p, k); - BigInt b = mod_p.multiply(m, powermod_y_p(k)); - BigInt a = future_a.get(); - - SecureVector<byte> output(2*p.bytes()); - a.binary_encode(output + (p.bytes() - a.bytes())); - b.binary_encode(output + output.size() / 2 + (p.bytes() - b.bytes())); - return output; - } - -/* -* Default ElGamal Decrypt Operation -*/ -BigInt Default_ELG_Op::decrypt(const BigInt& a, const BigInt& b) const - { - if(a >= p || b >= p) - throw Invalid_Argument("Default_ELG_Op: Invalid message"); - - return mod_p.multiply(b, inverse_mod(powermod_x_p(a), p)); - } - -} diff --git a/src/pubkey/elgamal/elg_op.h b/src/pubkey/elgamal/elg_op.h deleted file mode 100644 index 39ed897f4..000000000 --- a/src/pubkey/elgamal/elg_op.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -* ElGamal Operations -* (C) 1999-2008 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_ELGAMAL_OPS_H__ -#define BOTAN_ELGAMAL_OPS_H__ - -#include <botan/pow_mod.h> -#include <botan/numthry.h> -#include <botan/reducer.h> -#include <botan/dl_group.h> - -namespace Botan { - -/* -* ElGamal Operation -*/ -class BOTAN_DLL ELG_Operation - { - public: - virtual SecureVector<byte> encrypt(const byte[], u32bit, - const BigInt&) const = 0; - virtual BigInt decrypt(const BigInt&, const BigInt&) const = 0; - virtual ELG_Operation* clone() const = 0; - virtual ~ELG_Operation() {} - }; - -/* -* Botan's Default ElGamal Operation -*/ -class BOTAN_DLL Default_ELG_Op : public ELG_Operation - { - public: - SecureVector<byte> encrypt(const byte[], u32bit, const BigInt&) const; - BigInt decrypt(const BigInt&, const BigInt&) const; - - ELG_Operation* clone() const { return new Default_ELG_Op(*this); } - - Default_ELG_Op(const DL_Group&, const BigInt&, const BigInt&); - private: - const BigInt p; - Fixed_Base_Power_Mod powermod_g_p, powermod_y_p; - Fixed_Exponent_Power_Mod powermod_x_p; - Modular_Reducer mod_p; - }; - -} - -#endif diff --git a/src/pubkey/elgamal/elgamal.cpp b/src/pubkey/elgamal/elgamal.cpp index e3215f757..b9c4803f3 100644 --- a/src/pubkey/elgamal/elgamal.cpp +++ b/src/pubkey/elgamal/elgamal.cpp @@ -8,7 +8,6 @@ #include <botan/elgamal.h> #include <botan/numthry.h> #include <botan/keypair.h> -#include <botan/look_pk.h> #include <botan/internal/workfactor.h> namespace Botan { @@ -20,34 +19,6 @@ ElGamal_PublicKey::ElGamal_PublicKey(const DL_Group& grp, const BigInt& y1) { group = grp; y = y1; - X509_load_hook(); - } - -/* -* Algorithm Specific X.509 Initialization Code -*/ -void ElGamal_PublicKey::X509_load_hook() - { - core = ELG_Core(group, y); - } - -/* -* ElGamal Encryption Function -*/ -SecureVector<byte> -ElGamal_PublicKey::encrypt(const byte in[], u32bit length, - RandomNumberGenerator& rng) const - { - BigInt k(rng, 2 * dl_work_factor(group_p().bits())); - return core.encrypt(in, length, k); - } - -/* -* Return the maximum input size in bits -*/ -u32bit ElGamal_PublicKey::max_input_bits() const - { - return (group_p().bits() - 1); } /* @@ -61,37 +32,23 @@ ElGamal_PrivateKey::ElGamal_PrivateKey(RandomNumberGenerator& rng, x = x_arg; if(x == 0) - { x.randomize(rng, 2 * dl_work_factor(group_p().bits())); - PKCS8_load_hook(rng, true); - } - else - PKCS8_load_hook(rng, false); - } -/* -* Algorithm Specific PKCS #8 Initialization Code -*/ -void ElGamal_PrivateKey::PKCS8_load_hook(RandomNumberGenerator& rng, - bool generated) - { - if(y == 0) - y = power_mod(group_g(), x, group_p()); - core = ELG_Core(rng, group, y, x); + y = power_mod(group_g(), x, group_p()); - if(generated) + if(x_arg == 0) gen_check(rng); else load_check(rng); } -/* -* ElGamal Decryption Function -*/ -SecureVector<byte> ElGamal_PrivateKey::decrypt(const byte in[], - u32bit length) const +ElGamal_PrivateKey::ElGamal_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + RandomNumberGenerator& rng) : + DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_42) { - return core.decrypt(in, length); + y = power_mod(group_g(), x, group_p()); + load_check(rng); } /* @@ -108,10 +65,12 @@ bool ElGamal_PrivateKey::check_key(RandomNumberGenerator& rng, try { + PK_Encryptor_EME this_encryptor(*this, "EME1(SHA-1)"); + PK_Decryptor_EME this_decryptor(*this, "EME1(SHA-1)"); + KeyPair::check_key(rng, - get_pk_encryptor(*this, "EME1(SHA-1)"), - get_pk_decryptor(*this, "EME1(SHA-1)") - ); + this_encryptor, + this_decryptor); } catch(Self_Test_Failure) { @@ -121,4 +80,69 @@ bool ElGamal_PrivateKey::check_key(RandomNumberGenerator& rng, return true; } +ElGamal_Encryption_Operation::ElGamal_Encryption_Operation(const ElGamal_PublicKey& key) + { + const BigInt& p = key.group_p(); + + powermod_g_p = Fixed_Base_Power_Mod(key.group_g(), p); + powermod_y_p = Fixed_Base_Power_Mod(key.get_y(), p); + mod_p = Modular_Reducer(p); + } + +SecureVector<byte> +ElGamal_Encryption_Operation::encrypt(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng) + { + const BigInt& p = mod_p.get_modulus(); + + BigInt m(msg, msg_len); + + if(m >= p) + throw Invalid_Argument("ElGamal encryption: Input is too large"); + + BigInt k(rng, 2 * dl_work_factor(p.bits())); + + BigInt a = powermod_g_p(k); + BigInt b = mod_p.multiply(m, powermod_y_p(k)); + + SecureVector<byte> output(2*p.bytes()); + a.binary_encode(output + (p.bytes() - a.bytes())); + b.binary_encode(output + output.size() / 2 + (p.bytes() - b.bytes())); + return output; + } + +ElGamal_Decryption_Operation::ElGamal_Decryption_Operation(const ElGamal_PrivateKey& key) + { + const BigInt& p = key.group_p(); + + powermod_x_p = Fixed_Exponent_Power_Mod(key.get_x(), p); + mod_p = Modular_Reducer(p); + + BigInt k = Blinder::choose_nonce(powermod_x_p(2), p); + blinder = Blinder(k, powermod_x_p(k), p); + } + +SecureVector<byte> +ElGamal_Decryption_Operation::decrypt(const byte msg[], u32bit msg_len) + { + const BigInt& p = mod_p.get_modulus(); + + const u32bit p_bytes = p.bytes(); + + if(msg_len != 2 * p_bytes) + throw Invalid_Argument("ElGamal decryption: Invalid message"); + + BigInt a(msg, p_bytes); + BigInt b(msg + p_bytes, p_bytes); + + if(a >= p || b >= p) + throw Invalid_Argument("ElGamal decryption: Invalid message"); + + a = blinder.blind(a); + + BigInt r = mod_p.multiply(b, inverse_mod(powermod_x_p(a), p)); + + return BigInt::encode(blinder.unblind(r)); + } + } diff --git a/src/pubkey/elgamal/elgamal.h b/src/pubkey/elgamal/elgamal.h index 93e640f09..143b417ec 100644 --- a/src/pubkey/elgamal/elgamal.h +++ b/src/pubkey/elgamal/elgamal.h @@ -9,49 +9,79 @@ #define BOTAN_ELGAMAL_H__ #include <botan/dl_algo.h> -#include <botan/elg_core.h> +#include <botan/numthry.h> +#include <botan/reducer.h> +#include <botan/blinding.h> +#include <botan/pk_ops.h> namespace Botan { /* * ElGamal Public Key */ -class BOTAN_DLL ElGamal_PublicKey : public PK_Encrypting_Key, - public virtual DL_Scheme_PublicKey +class BOTAN_DLL ElGamal_PublicKey : public virtual DL_Scheme_PublicKey { public: std::string algo_name() const { return "ElGamal"; } DL_Group::Format group_format() const { return DL_Group::ANSI_X9_42; } - SecureVector<byte> encrypt(const byte[], u32bit, - RandomNumberGenerator& rng) const; - u32bit max_input_bits() const; + u32bit max_input_bits() const { return (group_p().bits() - 1); } - ElGamal_PublicKey() {} - ElGamal_PublicKey(const DL_Group&, const BigInt&); + ElGamal_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) : + DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_42) + {} + + ElGamal_PublicKey(const DL_Group& group, const BigInt& y); protected: - ELG_Core core; - private: - void X509_load_hook(); + ElGamal_PublicKey() {} }; /* * ElGamal Private Key */ class BOTAN_DLL ElGamal_PrivateKey : public ElGamal_PublicKey, - public PK_Decrypting_Key, public virtual DL_Scheme_PrivateKey { public: - SecureVector<byte> decrypt(const byte[], u32bit) const; - bool check_key(RandomNumberGenerator& rng, bool) const; - ElGamal_PrivateKey() {} - ElGamal_PrivateKey(RandomNumberGenerator&, const DL_Group&, - const BigInt& = 0); + ElGamal_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + RandomNumberGenerator& rng); + + ElGamal_PrivateKey(RandomNumberGenerator& rng, + const DL_Group& group, + const BigInt& priv_key = 0); + }; + +class BOTAN_DLL ElGamal_Encryption_Operation : public PK_Ops::Encryption + { + public: + u32bit max_input_bits() const { return mod_p.get_modulus().bits() - 1; } + + ElGamal_Encryption_Operation(const ElGamal_PublicKey& key); + + SecureVector<byte> encrypt(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng); + + private: + Fixed_Base_Power_Mod powermod_g_p, powermod_y_p; + Modular_Reducer mod_p; + }; + +class BOTAN_DLL ElGamal_Decryption_Operation : public PK_Ops::Decryption + { + public: + u32bit max_input_bits() const { return mod_p.get_modulus().bits() - 1; } + + ElGamal_Decryption_Operation(const ElGamal_PrivateKey& key); + + SecureVector<byte> decrypt(const byte msg[], u32bit msg_len); private: - void PKCS8_load_hook(RandomNumberGenerator&, bool = false); + Fixed_Exponent_Power_Mod powermod_x_p; + Modular_Reducer mod_p; + Blinder blinder; }; } diff --git a/src/pubkey/gost_3410/gost_3410.cpp b/src/pubkey/gost_3410/gost_3410.cpp index 8dd72dfc1..c5cc1ddbd 100644 --- a/src/pubkey/gost_3410/gost_3410.cpp +++ b/src/pubkey/gost_3410/gost_3410.cpp @@ -8,170 +8,140 @@ */ #include <botan/gost_3410.h> -#include <botan/numthry.h> #include <botan/der_enc.h> #include <botan/ber_dec.h> -#include <botan/secmem.h> -#include <botan/point_gfp.h> namespace Botan { -X509_Encoder* GOST_3410_PublicKey::x509_encoder() const +MemoryVector<byte> GOST_3410_PublicKey::x509_subject_public_key() const { - class GOST_3410_Key_Encoder : public X509_Encoder - { - public: - AlgorithmIdentifier alg_id() const - { - return AlgorithmIdentifier(key->get_oid(), - key->domain().DER_encode(key->domain_format())); - } - - MemoryVector<byte> key_bits() const - { - // Trust CryptoPro to come up with something obnoxious - const BigInt x = key->public_point().get_affine_x(); - const BigInt y = key->public_point().get_affine_y(); - - SecureVector<byte> bits(2*std::max(x.bytes(), y.bytes())); + // Trust CryptoPro to come up with something obnoxious + const BigInt& x = public_point().get_affine_x(); + const BigInt& y = public_point().get_affine_y(); - y.binary_encode(bits + (bits.size() / 2 - y.bytes())); - x.binary_encode(bits + (bits.size() - y.bytes())); + MemoryVector<byte> bits(2*std::max(x.bytes(), y.bytes())); - return DER_Encoder().encode(bits, OCTET_STRING).get_contents(); - } + y.binary_encode(bits + (bits.size() / 2 - y.bytes())); + x.binary_encode(bits + (bits.size() - x.bytes())); - GOST_3410_Key_Encoder(const GOST_3410_PublicKey* k): key(k) {} - private: - const GOST_3410_PublicKey* key; - }; - - return new GOST_3410_Key_Encoder(this); + return DER_Encoder().encode(bits, OCTET_STRING).get_contents(); } -X509_Decoder* GOST_3410_PublicKey::x509_decoder() +AlgorithmIdentifier GOST_3410_PublicKey::algorithm_identifier() const { - class GOST_3410_Key_Decoder : public X509_Decoder - { - public: - void alg_id(const AlgorithmIdentifier& alg_id) - { - // Also includes hash and cipher OIDs... brilliant design guys - OID ecc_param_id; + MemoryVector<byte> params = + DER_Encoder().start_cons(SEQUENCE) + .encode(OID(domain().get_oid())) + .end_cons() + .get_contents(); - BER_Decoder ber(alg_id.parameters); - ber.start_cons(SEQUENCE).decode(ecc_param_id); + return AlgorithmIdentifier(get_oid(), params); + } - key->domain_params = EC_Domain_Params(ecc_param_id); - } +GOST_3410_PublicKey::GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) + { + OID ecc_param_id; - void key_bits(const MemoryRegion<byte>& bits) - { + // Also includes hash and cipher OIDs... brilliant design guys + BER_Decoder(alg_id.parameters).start_cons(SEQUENCE).decode(ecc_param_id); - SecureVector<byte> key_bits; - BER_Decoder ber(bits); - ber.decode(key_bits, OCTET_STRING); + domain_params = EC_Domain_Params(ecc_param_id); - const u32bit part_size = key_bits.size() / 2; + SecureVector<byte> bits; + BER_Decoder(key_bits).decode(bits, OCTET_STRING); - BigInt y(key_bits, part_size); - BigInt x(key_bits + part_size, part_size); + const u32bit part_size = bits.size() / 2; - const BigInt p = key->domain().get_curve().get_p(); + BigInt y(bits, part_size); + BigInt x(bits + part_size, part_size); - key->public_key = PointGFp(key->domain().get_curve(), x, y); + public_key = PointGFp(domain().get_curve(), x, y); - key->X509_load_hook(); - } + try + { + public_key.check_invariants(); + } + catch(Illegal_Point) + { + throw Internal_Error("Loaded ECC public key failed self test"); + } + } - GOST_3410_Key_Decoder(GOST_3410_PublicKey* k): key(k) {} - private: - GOST_3410_PublicKey* key; - }; +GOST_3410_Signature_Operation::GOST_3410_Signature_Operation( + const GOST_3410_PrivateKey& gost_3410) : - return new GOST_3410_Key_Decoder(this); + base_point(gost_3410.domain().get_base_point()), + order(gost_3410.domain().get_order()), + x(gost_3410.private_value()) + { } -bool GOST_3410_PublicKey::verify(const byte msg[], u32bit msg_len, - const byte sig[], u32bit sig_len) const +SecureVector<byte> +GOST_3410_Signature_Operation::sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng) const { - const BigInt& n = domain().get_order(); - - if(sig_len != n.bytes()*2) - return false; - - // NOTE: it is not checked whether the public point is set - if(domain().get_curve().get_p() == 0) - throw Internal_Error("domain parameters not set"); + BigInt k; + do + k.randomize(rng, order.bits()-1); + while(k >= order); BigInt e(msg, msg_len); - BigInt r(sig, sig_len / 2); - BigInt s(sig + sig_len / 2, sig_len / 2); - - if(r < 0 || r >= n || s < 0 || s >= n) - return false; - - e %= n; + e %= order; if(e == 0) e = 1; - BigInt v = inverse_mod(e, n); + PointGFp k_times_P = base_point * k; + k_times_P.check_invariants(); - BigInt z1 = (s*v) % n; - BigInt z2 = (-r*v) % n; + BigInt r = k_times_P.get_affine_x() % order; - PointGFp R = (z1 * domain().get_base_point() + z2 * public_point()); + BigInt s = (r*x + k*e) % order; - return (R.get_affine_x() == r); + if(r == 0 || s == 0) + throw Invalid_State("GOST 34.10: r == 0 || s == 0"); + + SecureVector<byte> output(2*order.bytes()); + r.binary_encode(output + (output.size() / 2 - r.bytes())); + s.binary_encode(output + (output.size() - s.bytes())); + return output; } -GOST_3410_PublicKey::GOST_3410_PublicKey(const EC_Domain_Params& dom_par, - const PointGFp& pub_point) + +GOST_3410_Verification_Operation::GOST_3410_Verification_Operation(const GOST_3410_PublicKey& gost) : + base_point(gost.domain().get_base_point()), + public_point(gost.public_point()), + order(gost.domain().get_order()) { - domain_params = dom_par; - public_key = pub_point; - domain_encoding = EC_DOMPAR_ENC_EXPLICIT; } -SecureVector<byte> -GOST_3410_PrivateKey::sign(const byte msg[], - u32bit msg_len, - RandomNumberGenerator& rng) const +bool GOST_3410_Verification_Operation::verify(const byte msg[], u32bit msg_len, + const byte sig[], u32bit sig_len) const { - const BigInt& n = domain().get_order(); - - BigInt k; - do - k.randomize(rng, n.bits()-1); - while(k >= n); + if(sig_len != order.bytes()*2) + return false; - if(private_value() == 0) - throw Internal_Error("GOST_3410::sign(): no private key"); + BigInt e(msg, msg_len); - if(n == 0) - throw Internal_Error("GOST_3410::sign(): domain parameters not set"); + BigInt r(sig, sig_len / 2); + BigInt s(sig + sig_len / 2, sig_len / 2); - BigInt e(msg, msg_len); + if(r < 0 || r >= order || s < 0 || s >= order) + return false; - e %= n; + e %= order; if(e == 0) e = 1; - PointGFp k_times_P = domain().get_base_point() * k; - k_times_P.check_invariants(); + BigInt v = inverse_mod(e, order); - BigInt r = k_times_P.get_affine_x() % n; + BigInt z1 = (s*v) % order; + BigInt z2 = (-r*v) % order; - if(r == 0) - throw Internal_Error("GOST_3410::sign: r was zero"); + PointGFp R = (z1 * base_point + z2 * public_point); - BigInt s = (r*private_value() + k*e) % n; - - SecureVector<byte> output(2*n.bytes()); - r.binary_encode(output + (output.size() / 2 - r.bytes())); - s.binary_encode(output + (output.size() - s.bytes())); - return output; + return (R.get_affine_x() == r); } } diff --git a/src/pubkey/gost_3410/gost_3410.h b/src/pubkey/gost_3410/gost_3410.h index 8104cbb75..ffdbc6e19 100644 --- a/src/pubkey/gost_3410/gost_3410.h +++ b/src/pubkey/gost_3410/gost_3410.h @@ -2,7 +2,7 @@ * GOST 34.10-2001 * (C) 2007 Falko Strenzke, FlexSecure GmbH * Manuel Hartl, FlexSecure GmbH -* (C) 2008-2009 Jack Lloyd +* (C) 2008-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -11,23 +11,42 @@ #define BOTAN_GOST_3410_KEY_H__ #include <botan/ecc_key.h> +#include <botan/pk_ops.h> namespace Botan { /** * This class represents GOST_3410 Public Keys. */ -class BOTAN_DLL GOST_3410_PublicKey : public virtual EC_PublicKey, - public PK_Verifying_wo_MR_Key +class BOTAN_DLL GOST_3410_PublicKey : public virtual EC_PublicKey { public: /** + * Construct a public key from a given public point. + * @param dom_par the domain parameters associated with this key + * @param public_point the public point defining this key + */ + GOST_3410_PublicKey(const EC_Domain_Params& dom_par, + const PointGFp& public_point) : + EC_PublicKey(dom_par, public_point) {} + + /** + * Construct from X.509 algorithm id and subject public key bits + */ + GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits); + + /** * Get this keys algorithm name. * @result this keys algorithm name */ std::string algo_name() const { return "GOST-34.10"; } + AlgorithmIdentifier algorithm_identifier() const; + + MemoryVector<byte> x509_subject_public_key() const; + /** * Get the maximum number of bits allowed to be fed to this key. * This is the bitlength of the order of the base point. @@ -41,57 +60,21 @@ class BOTAN_DLL GOST_3410_PublicKey : public virtual EC_PublicKey, u32bit message_part_size() const { return domain().get_order().bytes(); } - /** - * Verify a message with this key. - * @param message the byte array containing the message - * @param mess_len the number of bytes in the message byte array - * @param signature the byte array containing the signature - * @param sig_len the number of bytes in the signature byte array - */ - bool verify(const byte message[], u32bit mess_len, - const byte signature[], u32bit sig_len) const; - - /** - * Default constructor. Use this one if you want to later fill - * this object with data from an encoded key. - */ + protected: GOST_3410_PublicKey() {} - - /** - * Construct a public key from a given public point. - * @param dom_par the domain parameters associated with this key - * @param public_point the public point defining this key - */ - GOST_3410_PublicKey(const EC_Domain_Params& dom_par, - const PointGFp& public_point); - - /** - * Get an x509_encoder that can be used to encode this key. - * @result an x509_encoder for this key - */ - X509_Encoder* x509_encoder() const; - - /** - * Get an x509_decoder that can be used to decode a stored key into - * this key. - * @result an x509_decoder for this key - */ - X509_Decoder* x509_decoder(); }; /** * This class represents GOST_3410 Private Keys */ class BOTAN_DLL GOST_3410_PrivateKey : public GOST_3410_PublicKey, - public EC_PrivateKey, - public PK_Signing_Key + public EC_PrivateKey { public: - /** - * Default constructor. Use this one if you want to later fill - * this object with data from an encoded key. - */ - GOST_3410_PrivateKey() {} + + GOST_3410_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) : + EC_PrivateKey(alg_id, key_bits) {} /** * Generate a new private key @@ -109,14 +92,45 @@ class BOTAN_DLL GOST_3410_PrivateKey : public GOST_3410_PublicKey, GOST_3410_PrivateKey(const EC_Domain_Params& domain, const BigInt& x) : EC_PrivateKey(domain, x) {} - /** - * Sign a message with this key. - * @param message the byte array representing the message to be signed - * @param mess_len the length of the message byte array - * @result the signature - */ - SecureVector<byte> sign(const byte message[], u32bit mess_len, + AlgorithmIdentifier pkcs8_algorithm_identifier() const + { return EC_PublicKey::algorithm_identifier(); } + }; + +class BOTAN_DLL GOST_3410_Signature_Operation : public PK_Ops::Signature + { + public: + GOST_3410_Signature_Operation(const GOST_3410_PrivateKey& gost_3410); + + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return order.bytes(); } + u32bit max_input_bits() const { return order.bits(); } + + SecureVector<byte> sign(const byte msg[], u32bit msg_len, RandomNumberGenerator& rng) const; + + private: + const PointGFp& base_point; + const BigInt& order; + const BigInt& x; + }; + +class BOTAN_DLL GOST_3410_Verification_Operation : public PK_Ops::Verification + { + public: + GOST_3410_Verification_Operation(const GOST_3410_PublicKey& gost); + + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return order.bytes(); } + u32bit max_input_bits() const { return order.bits(); } + + bool with_recovery() const { return false; } + + bool verify(const byte msg[], u32bit msg_len, + const byte sig[], u32bit sig_len) const; + private: + const PointGFp& base_point; + const PointGFp& public_point; + const BigInt& order; }; } diff --git a/src/pubkey/if_algo/if_algo.cpp b/src/pubkey/if_algo/if_algo.cpp index 556c86f6f..759c30c61 100644 --- a/src/pubkey/if_algo/if_algo.cpp +++ b/src/pubkey/if_algo/if_algo.cpp @@ -12,175 +12,102 @@ namespace Botan { -/* -* Return the X.509 public key encoder -*/ -X509_Encoder* IF_Scheme_PublicKey::x509_encoder() const +AlgorithmIdentifier IF_Scheme_PublicKey::algorithm_identifier() const { - class IF_Scheme_Encoder : public X509_Encoder - { - public: - AlgorithmIdentifier alg_id() const - { - return AlgorithmIdentifier(key->get_oid(), - AlgorithmIdentifier::USE_NULL_PARAM); - } - - MemoryVector<byte> key_bits() const - { - return DER_Encoder() - .start_cons(SEQUENCE) - .encode(key->n) - .encode(key->e) - .end_cons() - .get_contents(); - } - - IF_Scheme_Encoder(const IF_Scheme_PublicKey* k) : key(k) {} - private: - const IF_Scheme_PublicKey* key; - }; - - return new IF_Scheme_Encoder(this); + return AlgorithmIdentifier(get_oid(), + AlgorithmIdentifier::USE_NULL_PARAM); } -/* -* Return the X.509 public key decoder -*/ -X509_Decoder* IF_Scheme_PublicKey::x509_decoder() +MemoryVector<byte> IF_Scheme_PublicKey::x509_subject_public_key() const { - class IF_Scheme_Decoder : public X509_Decoder - { - public: - void alg_id(const AlgorithmIdentifier&) {} - - void key_bits(const MemoryRegion<byte>& bits) - { - BER_Decoder(bits) - .start_cons(SEQUENCE) - .decode(key->n) - .decode(key->e) - .verify_end() - .end_cons(); - - key->X509_load_hook(); - } - - IF_Scheme_Decoder(IF_Scheme_PublicKey* k) : key(k) {} - private: - IF_Scheme_PublicKey* key; - }; - - return new IF_Scheme_Decoder(this); + return DER_Encoder() + .start_cons(SEQUENCE) + .encode(n) + .encode(e) + .end_cons() + .get_contents(); } -/* -* Return the PKCS #8 public key encoder -*/ -PKCS8_Encoder* IF_Scheme_PrivateKey::pkcs8_encoder() const +IF_Scheme_PublicKey::IF_Scheme_PublicKey(const AlgorithmIdentifier&, + const MemoryRegion<byte>& key_bits) { - class IF_Scheme_Encoder : public PKCS8_Encoder - { - public: - AlgorithmIdentifier alg_id() const - { - return AlgorithmIdentifier(key->get_oid(), - AlgorithmIdentifier::USE_NULL_PARAM); - } - - MemoryVector<byte> key_bits() const - { - return DER_Encoder() - .start_cons(SEQUENCE) - .encode(static_cast<u32bit>(0)) - .encode(key->n) - .encode(key->e) - .encode(key->d) - .encode(key->p) - .encode(key->q) - .encode(key->d1) - .encode(key->d2) - .encode(key->c) - .end_cons() - .get_contents(); - } - - IF_Scheme_Encoder(const IF_Scheme_PrivateKey* k) : key(k) {} - private: - const IF_Scheme_PrivateKey* key; - }; - - return new IF_Scheme_Encoder(this); + BER_Decoder(key_bits) + .start_cons(SEQUENCE) + .decode(n) + .decode(e) + .verify_end() + .end_cons(); } -/* -* Return the PKCS #8 public key decoder -*/ -PKCS8_Decoder* IF_Scheme_PrivateKey::pkcs8_decoder(RandomNumberGenerator& rng) +MemoryVector<byte> IF_Scheme_PrivateKey::pkcs8_private_key() const { - class IF_Scheme_Decoder : public PKCS8_Decoder - { - public: - void alg_id(const AlgorithmIdentifier&) {} - - void key_bits(const MemoryRegion<byte>& bits) - { - u32bit version; - - BER_Decoder(bits) - .start_cons(SEQUENCE) - .decode(version) - .decode(key->n) - .decode(key->e) - .decode(key->d) - .decode(key->p) - .decode(key->q) - .decode(key->d1) - .decode(key->d2) - .decode(key->c) - .end_cons(); - - if(version != 0) - throw Decoding_Error("Unknown PKCS #1 key format version"); - - key->PKCS8_load_hook(rng); - } - - IF_Scheme_Decoder(IF_Scheme_PrivateKey* k, RandomNumberGenerator& r) : - key(k), rng(r) {} - private: - IF_Scheme_PrivateKey* key; - RandomNumberGenerator& rng; - }; - - return new IF_Scheme_Decoder(this, rng); + return DER_Encoder() + .start_cons(SEQUENCE) + .encode(static_cast<u32bit>(0)) + .encode(n) + .encode(e) + .encode(d) + .encode(p) + .encode(q) + .encode(d1) + .encode(d2) + .encode(c) + .end_cons() + .get_contents(); } -/* -* Algorithm Specific X.509 Initialization Code -*/ -void IF_Scheme_PublicKey::X509_load_hook() +IF_Scheme_PrivateKey::IF_Scheme_PrivateKey(RandomNumberGenerator& rng, + const AlgorithmIdentifier&, + const MemoryRegion<byte>& key_bits) { - core = IF_Core(e, n); + u32bit version; + + BER_Decoder(key_bits) + .start_cons(SEQUENCE) + .decode(version) + .decode(n) + .decode(e) + .decode(d) + .decode(p) + .decode(q) + .decode(d1) + .decode(d2) + .decode(c) + .end_cons(); + + if(version != 0) + throw Decoding_Error("Unknown PKCS #1 key format version"); + + load_check(rng); } -/* -* Algorithm Specific PKCS #8 Initialization Code -*/ -void IF_Scheme_PrivateKey::PKCS8_load_hook(RandomNumberGenerator& rng, - bool generated) +IF_Scheme_PrivateKey::IF_Scheme_PrivateKey(RandomNumberGenerator& rng, + const BigInt& prime1, + const BigInt& prime2, + const BigInt& exp, + const BigInt& d_exp, + const BigInt& mod) { - if(n == 0) n = p * q; - if(d1 == 0) d1 = d % (p - 1); - if(d2 == 0) d2 = d % (q - 1); - if(c == 0) c = inverse_mod(q, p); + p = prime1; + q = prime2; + e = exp; + d = d_exp; + n = mod.is_nonzero() ? mod : p * q; + + if(d == 0) + { + BigInt inv_for_d = lcm(p - 1, q - 1); + if(e.is_even()) + inv_for_d >>= 1; + + d = inverse_mod(e, inv_for_d); + } - core = IF_Core(rng, e, n, d, p, q, d1, d2, c); + d1 = d % (p - 1); + d2 = d % (q - 1); + c = inverse_mod(q, p); - if(generated) - gen_check(rng); - else - load_check(rng); + load_check(rng); } /* diff --git a/src/pubkey/if_algo/if_algo.h b/src/pubkey/if_algo/if_algo.h index 32a29be49..65bb8aed4 100644 --- a/src/pubkey/if_algo/if_algo.h +++ b/src/pubkey/if_algo/if_algo.h @@ -8,9 +8,10 @@ #ifndef BOTAN_IF_ALGO_H__ #define BOTAN_IF_ALGO_H__ -#include <botan/if_core.h> +#include <botan/bigint.h> #include <botan/x509_key.h> #include <botan/pkcs8.h> +#include <botan/pk_ops.h> namespace Botan { @@ -21,8 +22,18 @@ namespace Botan { class BOTAN_DLL IF_Scheme_PublicKey : public virtual Public_Key { public: + IF_Scheme_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits); + + IF_Scheme_PublicKey(const BigInt& n, const BigInt& e) : + n(n), e(e) {} + bool check_key(RandomNumberGenerator& rng, bool) const; + AlgorithmIdentifier algorithm_identifier() const; + + MemoryVector<byte> x509_subject_public_key() const; + /** * Get n = p * q. * @return n @@ -37,12 +48,10 @@ class BOTAN_DLL IF_Scheme_PublicKey : public virtual Public_Key u32bit max_input_bits() const { return (n.bits() - 1); } - X509_Encoder* x509_encoder() const; - X509_Decoder* x509_decoder(); protected: - virtual void X509_load_hook(); + IF_Scheme_PublicKey() {} + BigInt n, e; - IF_Core core; }; /** @@ -53,6 +62,16 @@ class BOTAN_DLL IF_Scheme_PrivateKey : public virtual IF_Scheme_PublicKey, public virtual Private_Key { public: + + IF_Scheme_PrivateKey(RandomNumberGenerator& rng, + const BigInt& prime1, const BigInt& prime2, + const BigInt& exp, const BigInt& d_exp, + const BigInt& mod); + + IF_Scheme_PrivateKey(RandomNumberGenerator& rng, + const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits); + bool check_key(RandomNumberGenerator& rng, bool) const; /** @@ -73,10 +92,15 @@ class BOTAN_DLL IF_Scheme_PrivateKey : public virtual IF_Scheme_PublicKey, */ const BigInt& get_d() const { return d; } - PKCS8_Encoder* pkcs8_encoder() const; - PKCS8_Decoder* pkcs8_decoder(RandomNumberGenerator&); + const BigInt& get_c() const { return c; } + const BigInt& get_d1() const { return d1; } + const BigInt& get_d2() const { return d2; } + + MemoryVector<byte> pkcs8_private_key() const; + protected: - virtual void PKCS8_load_hook(RandomNumberGenerator&, bool = false); + IF_Scheme_PrivateKey() {} + BigInt d, p, q, d1, d2, c; }; diff --git a/src/pubkey/if_algo/if_core.cpp b/src/pubkey/if_algo/if_core.cpp deleted file mode 100644 index 41ebfe8dd..000000000 --- a/src/pubkey/if_algo/if_core.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* -* IF Algorithm Core -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/if_core.h> -#include <botan/numthry.h> -#include <botan/internal/pk_engine.h> -#include <botan/parsing.h> -#include <algorithm> - -namespace Botan { - -/* -* IF_Core Constructor -*/ -IF_Core::IF_Core(const BigInt& e, const BigInt& n) - { - op = Engine_Core::if_op(e, n, 0, 0, 0, 0, 0, 0); - } - - -/* -* IF_Core Constructor -*/ -IF_Core::IF_Core(RandomNumberGenerator& rng, - const BigInt& e, const BigInt& n, const BigInt& d, - const BigInt& p, const BigInt& q, - const BigInt& d1, const BigInt& d2, const BigInt& c) - { - const u32bit BLINDING_BITS = BOTAN_PRIVATE_KEY_OP_BLINDING_BITS; - - op = Engine_Core::if_op(e, n, d, p, q, d1, d2, c); - - if(BLINDING_BITS) - { - BigInt k(rng, std::min(n.bits()-1, BLINDING_BITS)); - blinder = Blinder(power_mod(k, e, n), inverse_mod(k, n), n); - } - } - -/* -* IF_Core Copy Constructor -*/ -IF_Core::IF_Core(const IF_Core& core) - { - op = 0; - if(core.op) - op = core.op->clone(); - blinder = core.blinder; - } - -/* -* IF_Core Assignment Operator -*/ -IF_Core& IF_Core::operator=(const IF_Core& core) - { - delete op; - if(core.op) - op = core.op->clone(); - blinder = core.blinder; - return (*this); - } - -/* -* IF Public Operation -*/ -BigInt IF_Core::public_op(const BigInt& i) const - { - return op->public_op(i); - } - -/* -* IF Private Operation -*/ -BigInt IF_Core::private_op(const BigInt& i) const - { - return blinder.unblind(op->private_op(blinder.blind(i))); - } - -} diff --git a/src/pubkey/if_algo/if_core.h b/src/pubkey/if_algo/if_core.h deleted file mode 100644 index b7f487706..000000000 --- a/src/pubkey/if_algo/if_core.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -* IF Algorithm Core -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_IF_CORE_H__ -#define BOTAN_IF_CORE_H__ - -#include <botan/if_op.h> -#include <botan/blinding.h> - -namespace Botan { - -/* -* IF Core -*/ -class BOTAN_DLL IF_Core - { - public: - BigInt public_op(const BigInt&) const; - BigInt private_op(const BigInt&) const; - - IF_Core& operator=(const IF_Core&); - - IF_Core() { op = 0; } - IF_Core(const IF_Core&); - - IF_Core(const BigInt&, const BigInt&); - - IF_Core(RandomNumberGenerator& rng, - const BigInt&, const BigInt&, - const BigInt&, const BigInt&, const BigInt&, - const BigInt&, const BigInt&, const BigInt&); - - ~IF_Core() { delete op; } - private: - IF_Operation* op; - Blinder blinder; - }; - -} - -#endif diff --git a/src/pubkey/if_algo/if_op.cpp b/src/pubkey/if_algo/if_op.cpp deleted file mode 100644 index 99f68400d..000000000 --- a/src/pubkey/if_algo/if_op.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* -* Integer Factorization Scheme (RSA/RW) Operation -* (C) 1999-2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/if_op.h> -#include <botan/numthry.h> -#include <future> - -namespace Botan { - -/* -* Default_IF_Op Constructor -*/ -Default_IF_Op::Default_IF_Op(const BigInt& e, const BigInt& n, const BigInt&, - const BigInt& p, const BigInt& q, - const BigInt& d1, const BigInt& d2, - const BigInt& c) - { - powermod_e_n = Fixed_Exponent_Power_Mod(e, n); - - if(d1 != 0 && d2 != 0 && p != 0 && q != 0) - { - powermod_d1_p = Fixed_Exponent_Power_Mod(d1, p); - powermod_d2_q = Fixed_Exponent_Power_Mod(d2, q); - reducer = Modular_Reducer(p); - this->c = c; - this->q = q; - } - } - -/* -* Default IF Private Operation -*/ -BigInt Default_IF_Op::private_op(const BigInt& i) const - { - if(q == 0) - throw Internal_Error("Default_IF_Op::private_op: No private key"); - - auto future_j1 = std::async(std::launch::async, powermod_d1_p, i); - BigInt j2 = powermod_d2_q(i); - BigInt j1 = future_j1.get(); - - j1 = reducer.reduce(sub_mul(j1, j2, c)); - return mul_add(j1, q, j2); - } - -} diff --git a/src/pubkey/if_algo/if_op.h b/src/pubkey/if_algo/if_op.h deleted file mode 100644 index 516902fd9..000000000 --- a/src/pubkey/if_algo/if_op.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -* IF Operations -* (C) 1999-2008 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_IF_OP_H__ -#define BOTAN_IF_OP_H__ - -#include <botan/bigint.h> -#include <botan/pow_mod.h> -#include <botan/reducer.h> - -namespace Botan { - -/* -* IF Operation -*/ -class BOTAN_DLL IF_Operation - { - public: - virtual BigInt public_op(const BigInt&) const = 0; - virtual BigInt private_op(const BigInt&) const = 0; - virtual IF_Operation* clone() const = 0; - virtual ~IF_Operation() {} - }; - -/* -* Default IF Operation -*/ -class BOTAN_DLL Default_IF_Op : public IF_Operation - { - public: - BigInt public_op(const BigInt& i) const - { return powermod_e_n(i); } - BigInt private_op(const BigInt&) const; - - IF_Operation* clone() const { return new Default_IF_Op(*this); } - - Default_IF_Op(const BigInt&, const BigInt&, const BigInt&, - const BigInt&, const BigInt&, const BigInt&, - const BigInt&, const BigInt&); - private: - Fixed_Exponent_Power_Mod powermod_e_n, powermod_d1_p, powermod_d2_q; - Modular_Reducer reducer; - BigInt c, q; - }; - -} - -#endif diff --git a/src/pubkey/if_algo/info.txt b/src/pubkey/if_algo/info.txt index 833117819..32e50e684 100644 --- a/src/pubkey/if_algo/info.txt +++ b/src/pubkey/if_algo/info.txt @@ -2,22 +2,9 @@ define IF_PUBLIC_KEY_FAMILY load_on dep -<header:public> -if_algo.h -if_core.h -if_op.h -</header:public> - -<source> -if_algo.cpp -if_core.cpp -if_op.cpp -</source> - <requires> asn1 bigint libstate numbertheory -pk_codecs </requires> diff --git a/src/pubkey/info.txt b/src/pubkey/info.txt index b28bd1868..956a5e369 100644 --- a/src/pubkey/info.txt +++ b/src/pubkey/info.txt @@ -1,17 +1,24 @@ define PUBLIC_KEY_CRYPTO <source> +blinding.cpp pk_algs.cpp pk_keys.cpp +pkcs8.cpp pubkey.cpp pubkey_enums.cpp workfactor.cpp +x509_key.cpp </source> <header:public> +blinding.h pk_keys.h +pk_ops.h +pkcs8.h pubkey.h pubkey_enums.h +x509_key.h </header:public> <header:internal> @@ -23,9 +30,13 @@ workfactor.h alloc asn1 bigint +engine filters kdf +libstate oid_lookup +pbe +pem pk_pad rng sym_algo diff --git a/src/pubkey/keypair/keypair.cpp b/src/pubkey/keypair/keypair.cpp index 7eaa33395..d54d8e442 100644 --- a/src/pubkey/keypair/keypair.cpp +++ b/src/pubkey/keypair/keypair.cpp @@ -1,13 +1,11 @@ /* * Keypair Checks -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ #include <botan/keypair.h> -#include <botan/look_pk.h> -#include <memory> namespace Botan { @@ -17,22 +15,20 @@ namespace KeyPair { * Check an encryption key pair for consistency */ void check_key(RandomNumberGenerator& rng, - PK_Encryptor* encryptor, PK_Decryptor* decryptor) + PK_Encryptor& encryptor, + PK_Decryptor& decryptor) { - if(encryptor->maximum_input_size() == 0) + if(encryptor.maximum_input_size() == 0) return; - std::unique_ptr<PK_Encryptor> enc(encryptor); - std::unique_ptr<PK_Decryptor> dec(decryptor); - - SecureVector<byte> message(enc->maximum_input_size() - 1); + SecureVector<byte> message(encryptor.maximum_input_size() - 1); rng.randomize(message, message.size()); - SecureVector<byte> ciphertext = enc->encrypt(message, rng); + SecureVector<byte> ciphertext = encryptor.encrypt(message, rng); if(ciphertext == message) throw Self_Test_Failure("Encryption key pair consistency failure"); - SecureVector<byte> message2 = dec->decrypt(ciphertext); + SecureVector<byte> message2 = decryptor.decrypt(ciphertext); if(message != message2) throw Self_Test_Failure("Encryption key pair consistency failure"); } @@ -41,11 +37,9 @@ void check_key(RandomNumberGenerator& rng, * Check a signature key pair for consistency */ void check_key(RandomNumberGenerator& rng, - PK_Signer* signer, PK_Verifier* verifier) + PK_Signer& signer, + PK_Verifier& verifier) { - std::unique_ptr<PK_Signer> sig(signer); - std::unique_ptr<PK_Verifier> ver(verifier); - SecureVector<byte> message(16); rng.randomize(message, message.size()); @@ -53,18 +47,18 @@ void check_key(RandomNumberGenerator& rng, try { - signature = sig->sign_message(message, rng); + signature = signer.sign_message(message, rng); } catch(Encoding_Error) { return; } - if(!ver->verify_message(message, signature)) + if(!verifier.verify_message(message, signature)) throw Self_Test_Failure("Signature key pair consistency failure"); ++message[0]; - if(ver->verify_message(message, signature)) + if(verifier.verify_message(message, signature)) throw Self_Test_Failure("Signature key pair consistency failure"); } diff --git a/src/pubkey/keypair/keypair.h b/src/pubkey/keypair/keypair.h index b1d5c2da0..22dcca0ea 100644 --- a/src/pubkey/keypair/keypair.h +++ b/src/pubkey/keypair/keypair.h @@ -24,8 +24,8 @@ namespace KeyPair { * @throw Self_Test_Failure if the arguments are not related to each other */ BOTAN_DLL void check_key(RandomNumberGenerator& rng, - PK_Encryptor* enc, - PK_Decryptor* dec); + PK_Encryptor& enc, + PK_Decryptor& dec); /** * Tests whether the specified signer and verifier are related to each other, @@ -37,8 +37,8 @@ BOTAN_DLL void check_key(RandomNumberGenerator& rng, * @throw Self_Test_Failure if the arguments are not related to each other */ BOTAN_DLL void check_key(RandomNumberGenerator& rng, - PK_Signer* sig, - PK_Verifier* ver); + PK_Signer& sig, + PK_Verifier& ver); } diff --git a/src/pubkey/nr/nr.cpp b/src/pubkey/nr/nr.cpp index ad4ae78d3..cf59615da 100644 --- a/src/pubkey/nr/nr.cpp +++ b/src/pubkey/nr/nr.cpp @@ -1,6 +1,6 @@ /* * Nyberg-Rueppel -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -8,10 +8,15 @@ #include <botan/nr.h> #include <botan/numthry.h> #include <botan/keypair.h> -#include <botan/look_pk.h> namespace Botan { +NR_PublicKey::NR_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) : + DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_57) + { + } + /* * NR_PublicKey Constructor */ @@ -19,39 +24,6 @@ NR_PublicKey::NR_PublicKey(const DL_Group& grp, const BigInt& y1) { group = grp; y = y1; - X509_load_hook(); - } - -/* -* Algorithm Specific X.509 Initialization Code -*/ -void NR_PublicKey::X509_load_hook() - { - core = NR_Core(group, y); - } - -/* -* Nyberg-Rueppel Verification Function -*/ -SecureVector<byte> NR_PublicKey::verify(const byte sig[], u32bit sig_len) const - { - return core.verify(sig, sig_len); - } - -/* -* Return the maximum input size in bits -*/ -u32bit NR_PublicKey::max_input_bits() const - { - return (group_q().bits() - 1); - } - -/* -* Return the size of each portion of the sig -*/ -u32bit NR_PublicKey::message_part_size() const - { - return group_q().bytes(); } /* @@ -65,44 +37,24 @@ NR_PrivateKey::NR_PrivateKey(RandomNumberGenerator& rng, x = x_arg; if(x == 0) - { x = BigInt::random_integer(rng, 2, group_q() - 1); - PKCS8_load_hook(rng, true); - } - else - PKCS8_load_hook(rng, false); - } -/* -* Algorithm Specific PKCS #8 Initialization Code -*/ -void NR_PrivateKey::PKCS8_load_hook(RandomNumberGenerator& rng, - bool generated) - { - if(y == 0) - y = power_mod(group_g(), x, group_p()); - core = NR_Core(group, y, x); + y = power_mod(group_g(), x, group_p()); - if(generated) + if(x_arg == 0) gen_check(rng); else load_check(rng); } -/* -* Nyberg-Rueppel Signature Operation -*/ -SecureVector<byte> NR_PrivateKey::sign(const byte in[], u32bit length, - RandomNumberGenerator& rng) const +NR_PrivateKey::NR_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + RandomNumberGenerator& rng) : + DL_Scheme_PrivateKey(alg_id, key_bits, DL_Group::ANSI_X9_57) { - const BigInt& q = group_q(); + y = power_mod(group_g(), x, group_p()); - BigInt k; - do - k.randomize(rng, q.bits()); - while(k >= q); - - return core.sign(in, length, k); + load_check(rng); } /* @@ -118,10 +70,12 @@ bool NR_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const try { + PK_Signer this_signer(*this, "EMSA1(SHA-1)"); + PK_Verifier this_verifier(*this, "EMSA1(SHA-1)"); + KeyPair::check_key(rng, - get_pk_signer(*this, "EMSA1(SHA-1)"), - get_pk_verifier(*this, "EMSA1(SHA-1)") - ); + this_signer, + this_verifier); } catch(Self_Test_Failure) { @@ -131,4 +85,66 @@ bool NR_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const return true; } +NR_Signature_Operation::NR_Signature_Operation(const NR_PrivateKey& nr) : + q(nr.group_q()), + x(nr.get_x()), + powermod_g_p(nr.group_g(), nr.group_p()), + mod_q(nr.group_q()) + { + } + +SecureVector<byte> +NR_Signature_Operation::sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng) + { + rng.add_entropy(msg, msg_len); + + BigInt k; + do + k.randomize(rng, q.bits()); + while(k >= q); + + BigInt f(msg, msg_len); + + if(f >= q) + throw Invalid_Argument("NR_Signature_Operation: Input is out of range"); + + BigInt c = mod_q.reduce(powermod_g_p(k) + f); + if(c.is_zero()) + throw Internal_Error("NR_Signature_Operation: c was zero"); + BigInt d = mod_q.reduce(k - x * c); + + SecureVector<byte> output(2*q.bytes()); + c.binary_encode(output + (output.size() / 2 - c.bytes())); + d.binary_encode(output + (output.size() - d.bytes())); + return output; + } + +NR_Verification_Operation::NR_Verification_Operation(const NR_PublicKey& nr) : + q(nr.group_q()), y(nr.get_y()) + { + powermod_g_p = Fixed_Base_Power_Mod(nr.group_g(), nr.group_p()); + powermod_y_p = Fixed_Base_Power_Mod(y, nr.group_p()); + mod_p = Modular_Reducer(nr.group_p()); + mod_q = Modular_Reducer(nr.group_q()); + } + +SecureVector<byte> +NR_Verification_Operation::verify_mr(const byte msg[], u32bit msg_len) + { + const BigInt& q = mod_q.get_modulus(); + + if(msg_len != 2*q.bytes()) + return false; + + BigInt c(msg, q.bytes()); + BigInt d(msg + q.bytes(), q.bytes()); + + if(c.is_zero() || c >= q || d >= q) + throw Invalid_Argument("NR verification: Invalid signature"); + + BigInt i = mod_p.multiply(powermod_g_p(d), powermod_y_p(c)); + return BigInt::encode(mod_q.reduce(c - i)); + } + } diff --git a/src/pubkey/nr/nr.h b/src/pubkey/nr/nr.h index 144c5ec2a..bd125ab92 100644 --- a/src/pubkey/nr/nr.h +++ b/src/pubkey/nr/nr.h @@ -1,6 +1,6 @@ /* * Nyberg-Rueppel -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -9,53 +9,88 @@ #define BOTAN_NYBERG_RUEPPEL_H__ #include <botan/dl_algo.h> -#include <botan/nr_core.h> +#include <botan/pk_ops.h> +#include <botan/numthry.h> +#include <botan/reducer.h> namespace Botan { /* * Nyberg-Rueppel Public Key */ -class BOTAN_DLL NR_PublicKey : public PK_Verifying_with_MR_Key, - public virtual DL_Scheme_PublicKey +class BOTAN_DLL NR_PublicKey : public virtual DL_Scheme_PublicKey { public: std::string algo_name() const { return "NR"; } - SecureVector<byte> verify(const byte[], u32bit) const; - u32bit max_input_bits() const; - DL_Group::Format group_format() const { return DL_Group::ANSI_X9_57; } + u32bit message_parts() const { return 2; } - u32bit message_part_size() const; + u32bit message_part_size() const { return group_q().bytes(); } + u32bit max_input_bits() const { return (group_q().bits() - 1); } - NR_PublicKey() {} - NR_PublicKey(const DL_Group&, const BigInt&); + NR_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits); + + NR_PublicKey(const DL_Group& group, const BigInt& pub_key); protected: - NR_Core core; - private: - void X509_load_hook(); + NR_PublicKey() {} }; /* * Nyberg-Rueppel Private Key */ class BOTAN_DLL NR_PrivateKey : public NR_PublicKey, - public PK_Signing_Key, public virtual DL_Scheme_PrivateKey { public: - SecureVector<byte> sign(const byte[], u32bit, - RandomNumberGenerator& rng) const; + bool check_key(RandomNumberGenerator& rng, bool strong) const; + + NR_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + RandomNumberGenerator& rng); + + NR_PrivateKey(RandomNumberGenerator& rng, + const DL_Group& group, + const BigInt& x = 0); + }; + +class BOTAN_DLL NR_Signature_Operation : public PK_Ops::Signature + { + public: + NR_Signature_Operation(const NR_PrivateKey& nr); - bool check_key(RandomNumberGenerator& rng, bool) const; + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return q.bytes(); } + u32bit max_input_bits() const { return (q.bits() - 1); } - NR_PrivateKey() {} + SecureVector<byte> sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng); + private: + const BigInt& q; + const BigInt& x; + Fixed_Base_Power_Mod powermod_g_p; + Modular_Reducer mod_q; + }; - NR_PrivateKey(RandomNumberGenerator&, const DL_Group&, - const BigInt& = 0); +class BOTAN_DLL NR_Verification_Operation : public PK_Ops::Verification + { + public: + NR_Verification_Operation(const NR_PublicKey& nr); + + u32bit message_parts() const { return 2; } + u32bit message_part_size() const { return q.bytes(); } + u32bit max_input_bits() const { return (q.bits() - 1); } + + bool with_recovery() const { return true; } + + SecureVector<byte> verify_mr(const byte msg[], u32bit msg_len); private: - void PKCS8_load_hook(RandomNumberGenerator&, bool = false); + const BigInt& q; + const BigInt& y; + + Fixed_Base_Power_Mod powermod_g_p, powermod_y_p; + Modular_Reducer mod_p, mod_q; }; } diff --git a/src/pubkey/nr/nr_core.cpp b/src/pubkey/nr/nr_core.cpp deleted file mode 100644 index a87c32d60..000000000 --- a/src/pubkey/nr/nr_core.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* -* NR Core -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/nr_core.h> -#include <botan/numthry.h> -#include <botan/internal/pk_engine.h> -#include <botan/parsing.h> -#include <algorithm> - -namespace Botan { - -/* -* NR_Core Constructor -*/ -NR_Core::NR_Core(const DL_Group& group, const BigInt& y, const BigInt& x) - { - op = Engine_Core::nr_op(group, y, x); - } - -/* -* NR_Core Copy Constructor -*/ -NR_Core::NR_Core(const NR_Core& core) - { - op = 0; - if(core.op) - op = core.op->clone(); - } - -/* -* NR_Core Assignment Operator -*/ -NR_Core& NR_Core::operator=(const NR_Core& core) - { - delete op; - if(core.op) - op = core.op->clone(); - return (*this); - } - -/* -* NR Verification Operation -*/ -SecureVector<byte> NR_Core::verify(const byte in[], u32bit length) const - { - return op->verify(in, length); - } - -/* -* NR Signature Operation -*/ -SecureVector<byte> NR_Core::sign(const byte in[], u32bit length, - const BigInt& k) const - { - return op->sign(in, length, k); - } - -} diff --git a/src/pubkey/nr/nr_core.h b/src/pubkey/nr/nr_core.h deleted file mode 100644 index 483773622..000000000 --- a/src/pubkey/nr/nr_core.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -* NR Core -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_NR_CORE_H__ -#define BOTAN_NR_CORE_H__ - -#include <botan/nr_op.h> -#include <botan/dl_group.h> - -namespace Botan { - -/* -* NR Core -*/ -class BOTAN_DLL NR_Core - { - public: - SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const; - SecureVector<byte> verify(const byte[], u32bit) const; - - NR_Core& operator=(const NR_Core&); - - NR_Core() { op = 0; } - NR_Core(const NR_Core&); - NR_Core(const DL_Group&, const BigInt&, const BigInt& = 0); - ~NR_Core() { delete op; } - private: - NR_Operation* op; - }; - -} - -#endif diff --git a/src/pubkey/nr/nr_op.cpp b/src/pubkey/nr/nr_op.cpp deleted file mode 100644 index 10890a127..000000000 --- a/src/pubkey/nr/nr_op.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* -* NR Operations -* (C) 1999-2009 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/nr_op.h> -#include <future> - -namespace Botan { - -/* -* Default_NR_Op Constructor -*/ -Default_NR_Op::Default_NR_Op(const DL_Group& grp, const BigInt& y1, - const BigInt& x1) : x(x1), y(y1), group(grp) - { - powermod_g_p = Fixed_Base_Power_Mod(group.get_g(), group.get_p()); - powermod_y_p = Fixed_Base_Power_Mod(y, group.get_p()); - mod_p = Modular_Reducer(group.get_p()); - mod_q = Modular_Reducer(group.get_q()); - } - -/* -* Default NR Verify Operation -*/ -SecureVector<byte> Default_NR_Op::verify(const byte in[], u32bit length) const - { - const BigInt& q = group.get_q(); - - if(length != 2*q.bytes()) - return false; - - BigInt c(in, q.bytes()); - BigInt d(in + q.bytes(), q.bytes()); - - if(c.is_zero() || c >= q || d >= q) - throw Invalid_Argument("Default_NR_Op::verify: Invalid signature"); - - auto future_y_c = std::async(std::launch::async, powermod_y_p, c); - BigInt g_d = powermod_g_p(d); - - BigInt i = mod_p.multiply(g_d, future_y_c.get()); - return BigInt::encode(mod_q.reduce(c - i)); - } - -/* -* Default NR Sign Operation -*/ -SecureVector<byte> Default_NR_Op::sign(const byte in[], u32bit length, - const BigInt& k) const - { - if(x == 0) - throw Internal_Error("Default_NR_Op::sign: No private key"); - - const BigInt& q = group.get_q(); - - BigInt f(in, length); - - if(f >= q) - throw Invalid_Argument("Default_NR_Op::sign: Input is out of range"); - - BigInt c = mod_q.reduce(powermod_g_p(k) + f); - if(c.is_zero()) - throw Internal_Error("Default_NR_Op::sign: c was zero"); - BigInt d = mod_q.reduce(k - x * c); - - SecureVector<byte> output(2*q.bytes()); - c.binary_encode(output + (output.size() / 2 - c.bytes())); - d.binary_encode(output + (output.size() - d.bytes())); - return output; - } - -} diff --git a/src/pubkey/nr/nr_op.h b/src/pubkey/nr/nr_op.h deleted file mode 100644 index cba1465f2..000000000 --- a/src/pubkey/nr/nr_op.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -* NR Operations -* (C) 1999-2008 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_NR_OPS_H__ -#define BOTAN_NR_OPS_H__ - -#include <botan/pow_mod.h> -#include <botan/numthry.h> -#include <botan/reducer.h> -#include <botan/dl_group.h> - -namespace Botan { - -/* -* NR Operation -*/ -class BOTAN_DLL NR_Operation - { - public: - virtual SecureVector<byte> verify(const byte[], u32bit) const = 0; - virtual SecureVector<byte> sign(const byte[], u32bit, - const BigInt&) const = 0; - virtual NR_Operation* clone() const = 0; - virtual ~NR_Operation() {} - }; - -/* -* Botan's Default NR Operation -*/ -class BOTAN_DLL Default_NR_Op : public NR_Operation - { - public: - SecureVector<byte> verify(const byte[], u32bit) const; - SecureVector<byte> sign(const byte[], u32bit, const BigInt&) const; - - NR_Operation* clone() const { return new Default_NR_Op(*this); } - - Default_NR_Op(const DL_Group&, const BigInt&, const BigInt&); - private: - const BigInt x, y; - const DL_Group group; - Fixed_Base_Power_Mod powermod_g_p, powermod_y_p; - Modular_Reducer mod_p, mod_q; - }; - - -} - -#endif diff --git a/src/pubkey/pk_algs.cpp b/src/pubkey/pk_algs.cpp index dd62eb5ac..18e08f82e 100644 --- a/src/pubkey/pk_algs.cpp +++ b/src/pubkey/pk_algs.cpp @@ -1,11 +1,12 @@ /* * PK Key -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ #include <botan/internal/pk_algs.h> +#include <botan/oids.h> #if defined(BOTAN_HAS_RSA) #include <botan/rsa.h> @@ -41,81 +42,102 @@ namespace Botan { -/* -* Get an PK public key object -*/ -Public_Key* get_public_key(const std::string& alg_name) +BOTAN_DLL Public_Key* make_public_key(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) { + const std::string alg_name = OIDS::lookup(alg_id.oid); + if(alg_name == "") + throw Decoding_Error("Unknown algorithm OID: " + alg_id.oid.as_string()); + #if defined(BOTAN_HAS_RSA) - if(alg_name == "RSA") return new RSA_PublicKey; + if(alg_name == "RSA") + return new RSA_PublicKey(alg_id, key_bits); +#endif + +#if defined(BOTAN_HAS_RW) + if(alg_name == "RW") + return new RW_PublicKey(alg_id, key_bits); #endif #if defined(BOTAN_HAS_DSA) - if(alg_name == "DSA") return new DSA_PublicKey; + if(alg_name == "DSA") + return new DSA_PublicKey(alg_id, key_bits); #endif #if defined(BOTAN_HAS_DIFFIE_HELLMAN) - if(alg_name == "DH") return new DH_PublicKey; + if(alg_name == "DH") + return new DH_PublicKey(alg_id, key_bits); #endif #if defined(BOTAN_HAS_NYBERG_RUEPPEL) - if(alg_name == "NR") return new NR_PublicKey; + if(alg_name == "NR") + return new NR_PublicKey(alg_id, key_bits); #endif -#if defined(BOTAN_HAS_RW) - if(alg_name == "RW") return new RW_PublicKey; -#endif - -#if defined(BOTAN_HAS_ELG) - if(alg_name == "ELG") return new ElGamal_PublicKey; +#if defined(BOTAN_HAS_ELGAMAL) + if(alg_name == "ElGamal") + return new ElGamal_PublicKey(alg_id, key_bits); #endif #if defined(BOTAN_HAS_ECDSA) - if(alg_name == "ECDSA") return new ECDSA_PublicKey; + if(alg_name == "ECDSA") + return new ECDSA_PublicKey(alg_id, key_bits); #endif #if defined(BOTAN_HAS_GOST_34_10_2001) - if(alg_name == "GOST-34.10") return new GOST_3410_PublicKey; + if(alg_name == "GOST-34.10") + return new GOST_3410_PublicKey(alg_id, key_bits); #endif return 0; } -/* -* Get an PK private key object -*/ -Private_Key* get_private_key(const std::string& alg_name) +BOTAN_DLL Private_Key* make_private_key(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + RandomNumberGenerator& rng) { + const std::string alg_name = OIDS::lookup(alg_id.oid); + if(alg_name == "") + throw Decoding_Error("Unknown algorithm OID: " + alg_id.oid.as_string()); + #if defined(BOTAN_HAS_RSA) - if(alg_name == "RSA") return new RSA_PrivateKey; + if(alg_name == "RSA") + return new RSA_PrivateKey(alg_id, key_bits, rng); +#endif + +#if defined(BOTAN_HAS_RW) + if(alg_name == "RW") + return new RW_PrivateKey(alg_id, key_bits, rng); #endif #if defined(BOTAN_HAS_DSA) - if(alg_name == "DSA") return new DSA_PrivateKey; + if(alg_name == "DSA") + return new DSA_PrivateKey(alg_id, key_bits, rng); #endif #if defined(BOTAN_HAS_DIFFIE_HELLMAN) - if(alg_name == "DH") return new DH_PrivateKey; + if(alg_name == "DH") + return new DH_PrivateKey(alg_id, key_bits, rng); #endif #if defined(BOTAN_HAS_NYBERG_RUEPPEL) - if(alg_name == "NR") return new NR_PrivateKey; + if(alg_name == "NR") + return new NR_PrivateKey(alg_id, key_bits, rng); #endif -#if defined(BOTAN_HAS_RW) - if(alg_name == "RW") return new RW_PrivateKey; -#endif - -#if defined(BOTAN_HAS_ELG) - if(alg_name == "ELG") return new ElGamal_PrivateKey; +#if defined(BOTAN_HAS_ELGAMAL) + if(alg_name == "ElGamal") + return new ElGamal_PrivateKey(alg_id, key_bits, rng); #endif #if defined(BOTAN_HAS_ECDSA) - if(alg_name == "ECDSA") return new ECDSA_PrivateKey; + if(alg_name == "ECDSA") + return new ECDSA_PrivateKey(alg_id, key_bits); #endif #if defined(BOTAN_HAS_GOST_34_10_2001) - if(alg_name == "GOST-34.10") return new GOST_3410_PrivateKey; + if(alg_name == "GOST-34.10") + return new GOST_3410_PrivateKey(alg_id, key_bits); #endif return 0; diff --git a/src/pubkey/pk_algs.h b/src/pubkey/pk_algs.h index c41bf1a63..3fbaed234 100644 --- a/src/pubkey/pk_algs.h +++ b/src/pubkey/pk_algs.h @@ -1,6 +1,6 @@ /* * PK Key Factory -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -12,19 +12,12 @@ namespace Botan { -/** -* Get an empty public key object. -* @param name the name of the desired public key algorithm -* @return the public key object -*/ -BOTAN_DLL Public_Key* get_public_key(const std::string&); +BOTAN_DLL Public_Key* make_public_key(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits); -/** -* Get an empty private key object. -* @param name the name of the desired public key algorithm -* @return the private key object -*/ -BOTAN_DLL Private_Key* get_private_key(const std::string&); +BOTAN_DLL Private_Key* make_private_key(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + RandomNumberGenerator& rng); } diff --git a/src/pubkey/pk_codecs/info.txt b/src/pubkey/pk_codecs/info.txt deleted file mode 100644 index 64fb10b8a..000000000 --- a/src/pubkey/pk_codecs/info.txt +++ /dev/null @@ -1,7 +0,0 @@ -<requires> -asn1 -filters -oid_lookup -pbe -pem -</requires> diff --git a/src/pubkey/pk_keys.h b/src/pubkey/pk_keys.h index 5b612577d..da73db0ee 100644 --- a/src/pubkey/pk_keys.h +++ b/src/pubkey/pk_keys.h @@ -10,6 +10,7 @@ #include <botan/secmem.h> #include <botan/asn1_oid.h> +#include <botan/alg_id.h> #include <botan/rng.h> namespace Botan { @@ -61,17 +62,14 @@ class BOTAN_DLL Public_Key virtual u32bit max_input_bits() const = 0; /** - * Get an X509 encoder that can be used to encode this key in X509 format. - * @return an X509 encoder for this key + * @return X.509 AlgorithmIdentifier for this key */ - virtual class X509_Encoder* x509_encoder() const = 0; + virtual AlgorithmIdentifier algorithm_identifier() const = 0; /** - * Get an X509 decoder that can be used to set the values of this - * key based on an X509 encoded key object. - * @return an X509 decoder for this key + * @return X.509 subject key encoding for this key object */ - virtual class X509_Decoder* x509_decoder() = 0; + virtual MemoryVector<byte> x509_subject_public_key() const = 0; virtual ~Public_Key() {} protected: @@ -85,86 +83,30 @@ class BOTAN_DLL Private_Key : public virtual Public_Key { public: /** - * Get a PKCS#8 encoder that can be used to encode this key in - * PKCS#8 format. - * @return an PKCS#8 encoder for this key + * @return PKCS #8 private key encoding for this key object */ - virtual class PKCS8_Encoder* pkcs8_encoder() const - { return 0; } + virtual MemoryVector<byte> pkcs8_private_key() const = 0; /** - * Get an PKCS#8 decoder that can be used to set the values of this key - * based on an PKCS#8 encoded key object. - * @return an PKCS#8 decoder for this key + * @return PKCS #8 AlgorithmIdentifier for this key + * Might be different from the X.509 identifier, but normally is not */ - virtual class PKCS8_Decoder* pkcs8_decoder(RandomNumberGenerator&) - { return 0; } + virtual AlgorithmIdentifier pkcs8_algorithm_identifier() const + { return algorithm_identifier(); } + protected: void load_check(RandomNumberGenerator&) const; void gen_check(RandomNumberGenerator&) const; }; /** -* PK Encrypting Key. -*/ -class BOTAN_DLL PK_Encrypting_Key : public virtual Public_Key - { - public: - virtual SecureVector<byte> encrypt(const byte[], u32bit, - RandomNumberGenerator&) const = 0; - virtual ~PK_Encrypting_Key() {} - }; - -/** -* PK Decrypting Key -*/ -class BOTAN_DLL PK_Decrypting_Key : public virtual Private_Key - { - public: - virtual SecureVector<byte> decrypt(const byte[], u32bit) const = 0; - virtual ~PK_Decrypting_Key() {} - }; - -/** -* PK Signing Key -*/ -class BOTAN_DLL PK_Signing_Key : public virtual Private_Key - { - public: - virtual SecureVector<byte> sign(const byte[], u32bit, - RandomNumberGenerator& rng) const = 0; - virtual ~PK_Signing_Key() {} - }; - -/** -* PK Verifying Key, Message Recovery Version -*/ -class BOTAN_DLL PK_Verifying_with_MR_Key : public virtual Public_Key - { - public: - virtual SecureVector<byte> verify(const byte[], u32bit) const = 0; - virtual ~PK_Verifying_with_MR_Key() {} - }; - -/** -* PK Verifying Key, No Message Recovery Version -*/ -class BOTAN_DLL PK_Verifying_wo_MR_Key : public virtual Public_Key - { - public: - virtual bool verify(const byte[], u32bit, - const byte[], u32bit) const = 0; - virtual ~PK_Verifying_wo_MR_Key() {} - }; - -/** * PK Secret Value Derivation Key */ class BOTAN_DLL PK_Key_Agreement_Key : public virtual Private_Key { public: - virtual SecureVector<byte> derive_key(const byte[], u32bit) const = 0; virtual MemoryVector<byte> public_value() const = 0; + virtual ~PK_Key_Agreement_Key() {} }; diff --git a/src/pubkey/pk_ops.h b/src/pubkey/pk_ops.h new file mode 100644 index 000000000..97ba372c2 --- /dev/null +++ b/src/pubkey/pk_ops.h @@ -0,0 +1,151 @@ +/* +* PK Operation Types +* (C) 2010 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_PK_OPERATIONS_H__ +#define BOTAN_PK_OPERATIONS_H__ + +#include <botan/secmem.h> +#include <botan/rng.h> + +namespace Botan { + +namespace PK_Ops { + +class BOTAN_DLL Encryption + { + public: + virtual u32bit max_input_bits() const = 0; + + virtual SecureVector<byte> encrypt(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng) = 0; + + virtual ~Encryption() {} + }; + +class BOTAN_DLL Decryption + { + public: + virtual u32bit max_input_bits() const = 0; + + virtual SecureVector<byte> decrypt(const byte msg[], + u32bit msg_len) = 0; + + virtual ~Decryption() {} + }; + +class BOTAN_DLL Signature + { + public: + /** + * Find out the number of message parts supported by this scheme. + * @return the number of message parts + */ + virtual u32bit message_parts() const { return 1; } + + /** + * Find out the message part size supported by this scheme/key. + * @return the size of the message parts + */ + virtual u32bit message_part_size() const { return 0; } + + /** + * Get the maximum message size in bits supported by this public key. + * @return the maximum message in bits + */ + virtual u32bit max_input_bits() const = 0; + + /* + * Perform a signature operation + * @param msg the message + * @param msg_len the length of msg in bytes + * @param rng a random number generator + */ + virtual SecureVector<byte> sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng) = 0; + + virtual ~Signature() {} + }; + +class BOTAN_DLL Verification + { + public: + /** + * Get the maximum message size in bits supported by this public key. + * @return the maximum message in bits + */ + virtual u32bit max_input_bits() const = 0; + + /** + * Find out the number of message parts supported by this scheme. + * @return the number of message parts + */ + virtual u32bit message_parts() const { return 1; } + + /** + * Find out the message part size supported by this scheme/key. + * @return the size of the message parts + */ + virtual u32bit message_part_size() const { return 0; } + + /** + * @return boolean specifying if this key type supports message + * recovery and thus if you need to call verify() or verify_mr() + */ + virtual bool with_recovery() const = 0; + + /* + * Perform a signature check operation + * @param msg the message + * @param msg_len the length of msg in bytes + * @param sig the signature + * @param sig_len the length of sig in bytes + * @returns if signature is a valid one for message + */ + virtual bool verify(const byte[], u32bit, + const byte[], u32bit) + { + throw Invalid_State("Message recovery required"); + } + + /* + * Perform a signature operation (with message recovery) + * Only call this if with_recovery() returns true + * @param msg the message + * @param msg_len the length of msg in bytes + * @returns recovered message + */ + virtual SecureVector<byte> verify_mr(const byte[], + u32bit) + { + throw Invalid_State("Message recovery not supported"); + } + + virtual ~Verification() {} + }; + +/* +* A generic Key Agreement Operation (eg DH or ECDH) +*/ +class BOTAN_DLL Key_Agreement + { + public: + /* + * Perform a key agreement operation + * @param w the other key value + * @param w_len the length of w in bytes + * @returns the agreed key + */ + virtual SecureVector<byte> agree(const byte w[], u32bit w_len) = 0; + + virtual ~Key_Agreement() {} + }; + +} + +} + +#endif diff --git a/src/pubkey/pk_codecs/pkcs8.cpp b/src/pubkey/pkcs8.cpp index 830f3a10d..d3a62aa01 100644 --- a/src/pubkey/pk_codecs/pkcs8.cpp +++ b/src/pubkey/pkcs8.cpp @@ -1,6 +1,6 @@ /* * PKCS #8 -* (C) 1999-2008 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -138,18 +138,14 @@ SecureVector<byte> PKCS8_decode(DataSource& source, const User_Interface& ui, */ void encode(const Private_Key& key, Pipe& pipe, X509_Encoding encoding) { - std::unique_ptr<PKCS8_Encoder> encoder(key.pkcs8_encoder()); - if(!encoder.get()) - throw Encoding_Error("PKCS8::encode: Key does not support encoding"); - const u32bit PKCS8_VERSION = 0; SecureVector<byte> contents = DER_Encoder() .start_cons(SEQUENCE) .encode(PKCS8_VERSION) - .encode(encoder->alg_id()) - .encode(encoder->key_bits(), OCTET_STRING) + .encode(key.pkcs8_algorithm_identifier()) + .encode(key.pkcs8_private_key(), OCTET_STRING) .end_cons() .get_contents(); @@ -244,21 +240,7 @@ Private_Key* load_key(DataSource& source, throw PKCS8_Exception("Unknown algorithm OID: " + alg_id.oid.as_string()); - std::unique_ptr<Private_Key> key(get_private_key(alg_name)); - - if(!key.get()) - throw PKCS8_Exception("Unknown PK algorithm/OID: " + alg_name + ", " + - alg_id.oid.as_string()); - - std::unique_ptr<PKCS8_Decoder> decoder(key->pkcs8_decoder(rng)); - - if(!decoder.get()) - throw Decoding_Error("Key does not support PKCS #8 decoding"); - - decoder->alg_id(alg_id); - decoder->key_bits(pkcs8_key); - - return key.release(); + return make_private_key(alg_id, pkcs8_key, rng); } /* diff --git a/src/pubkey/pk_codecs/pkcs8.h b/src/pubkey/pkcs8.h index adfad0e63..920f8c24a 100644 --- a/src/pubkey/pk_codecs/pkcs8.h +++ b/src/pubkey/pkcs8.h @@ -14,49 +14,6 @@ namespace Botan { /** -* PKCS #8 Private Key Encoder. -*/ -class BOTAN_DLL PKCS8_Encoder - { - public: - /** - * Get the algorithm identifier associated with the scheme - * this encoders key is part of. - * @return the algorithm identifier - */ - virtual AlgorithmIdentifier alg_id() const = 0; - - /** - * Get the DER encoded key. - * @return the DER encoded key - */ - // FIXME: Why not SecureVector? - virtual MemoryVector<byte> key_bits() const = 0; - virtual ~PKCS8_Encoder() {} - }; - -/* -* PKCS #8 Private Key Decoder -*/ -class BOTAN_DLL PKCS8_Decoder - { - public: - /** - * Set the algorithm identifier associated with the scheme - * this decoders key is part of. - * @param alg_id the algorithm identifier - */ - virtual void alg_id(const AlgorithmIdentifier&) = 0; - - /** - * Set the DER encoded key. - * @param key the DER encoded key - */ - virtual void key_bits(const MemoryRegion<byte>&) = 0; - virtual ~PKCS8_Decoder() {} - }; - -/** * PKCS #8 General Exception */ struct BOTAN_DLL PKCS8_Exception : public Decoding_Error diff --git a/src/pubkey/pubkey.cpp b/src/pubkey/pubkey.cpp index 69002207f..751f20583 100644 --- a/src/pubkey/pubkey.cpp +++ b/src/pubkey/pubkey.cpp @@ -1,6 +1,6 @@ /* * Public Key Base -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -10,130 +10,137 @@ #include <botan/ber_dec.h> #include <botan/bigint.h> #include <botan/parsing.h> +#include <botan/libstate.h> +#include <botan/engine.h> +#include <botan/lookup.h> #include <botan/internal/bit_ops.h> #include <memory> namespace Botan { /* -* Encrypt a message -*/ -SecureVector<byte> PK_Encryptor::encrypt(const byte in[], u32bit len, - RandomNumberGenerator& rng) const - { - return enc(in, len, rng); - } - -/* -* Encrypt a message +* PK_Encryptor_EME Constructor */ -SecureVector<byte> PK_Encryptor::encrypt(const MemoryRegion<byte>& in, - RandomNumberGenerator& rng) const +PK_Encryptor_EME::PK_Encryptor_EME(const Public_Key& key, + const std::string& eme_name) { - return enc(in.begin(), in.size(), rng); - } + Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory()); -/* -* Decrypt a message -*/ -SecureVector<byte> PK_Decryptor::decrypt(const byte in[], u32bit len) const - { - return dec(in, len); - } + while(const Engine* engine = i.next()) + { + op = engine->get_encryption_op(key); + if(op) + break; + } -/* -* Decrypt a message -*/ -SecureVector<byte> PK_Decryptor::decrypt(const MemoryRegion<byte>& in) const - { - return dec(in.begin(), in.size()); - } + if(!op) + throw Lookup_Error("PK_Encryptor_EME: No working engine for " + + key.algo_name()); -/* -* PK_Encryptor_MR_with_EME Constructor -*/ -PK_Encryptor_MR_with_EME::PK_Encryptor_MR_with_EME(const PK_Encrypting_Key& k, - EME* eme_obj) : - key(k), encoder(eme_obj) - { + eme = get_eme(eme_name); } /* * Encrypt a message */ SecureVector<byte> -PK_Encryptor_MR_with_EME::enc(const byte msg[], - u32bit length, - RandomNumberGenerator& rng) const +PK_Encryptor_EME::enc(const byte msg[], + u32bit length, + RandomNumberGenerator& rng) const { SecureVector<byte> message; - if(encoder) - message = encoder->encode(msg, length, key.max_input_bits(), rng); + if(eme) + message = eme->encode(msg, length, op->max_input_bits(), rng); else message.set(msg, length); - if(8*(message.size() - 1) + high_bit(message[0]) > key.max_input_bits()) - throw Invalid_Argument("PK_Encryptor_MR_with_EME: Input is too large"); + if(8*(message.size() - 1) + high_bit(message[0]) > op->max_input_bits()) + throw Invalid_Argument("PK_Encryptor_EME: Input is too large"); - return key.encrypt(message, message.size(), rng); + return op->encrypt(message, message.size(), rng); } /* * Return the max size, in bytes, of a message */ -u32bit PK_Encryptor_MR_with_EME::maximum_input_size() const +u32bit PK_Encryptor_EME::maximum_input_size() const { - if(!encoder) - return (key.max_input_bits() / 8); + if(!eme) + return (op->max_input_bits() / 8); else - return encoder->maximum_input_size(key.max_input_bits()); + return eme->maximum_input_size(op->max_input_bits()); } /* -* PK_Decryptor_MR_with_EME Constructor +* PK_Decryptor_EME Constructor */ -PK_Decryptor_MR_with_EME::PK_Decryptor_MR_with_EME(const PK_Decrypting_Key& k, - EME* eme_obj) : - key(k), encoder(eme_obj) +PK_Decryptor_EME::PK_Decryptor_EME(const Private_Key& key, + const std::string& eme_name) { + Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory()); + + while(const Engine* engine = i.next()) + { + op = engine->get_decryption_op(key); + if(op) + break; + } + + if(!op) + throw Lookup_Error("PK_Decryptor_EME: No working engine for " + + key.algo_name()); + + eme = get_eme(eme_name); } /* * Decrypt a message */ -SecureVector<byte> PK_Decryptor_MR_with_EME::dec(const byte msg[], - u32bit length) const +SecureVector<byte> PK_Decryptor_EME::dec(const byte msg[], + u32bit length) const { try { - SecureVector<byte> decrypted = key.decrypt(msg, length); - if(encoder) - return encoder->decode(decrypted, key.max_input_bits()); + SecureVector<byte> decrypted = op->decrypt(msg, length); + if(eme) + return eme->decode(decrypted, op->max_input_bits()); else return decrypted; } catch(Invalid_Argument) { - throw Decoding_Error("PK_Decryptor_MR_with_EME: Input is invalid"); + throw Decoding_Error("PK_Decryptor_EME: Input is invalid"); } } /* * PK_Signer Constructor */ -PK_Signer::PK_Signer(const PK_Signing_Key& k, EMSA* emsa_obj) : - key(k), emsa(emsa_obj) +PK_Signer::PK_Signer(const Private_Key& key, + const std::string& emsa_name, + Signature_Format format) { - sig_format = IEEE_1363; - } + Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory()); -/* -* Set the signature format -*/ -void PK_Signer::set_output_format(Signature_Format format) - { - if(key.message_parts() == 1 && format != IEEE_1363) - throw Invalid_State("PK_Signer: Cannot set the output format for " + - key.algo_name() + " keys"); + op = 0; + verify_op = 0; + + while(const Engine* engine = i.next()) + { + if(!op) + op = engine->get_signature_op(key); + + if(!verify_op) + verify_op = engine->get_verify_op(key); + + if(op && verify_op) + break; + } + + if(!op || !verify_op) + throw Lookup_Error("PK_Signer: No working engine for " + + key.algo_name()); + + emsa = get_emsa(emsa_name); sig_format = format; } @@ -148,15 +155,6 @@ SecureVector<byte> PK_Signer::sign_message(const byte msg[], u32bit length, } /* -* Sign a message -*/ -SecureVector<byte> PK_Signer::sign_message(const MemoryRegion<byte>& msg, - RandomNumberGenerator& rng) - { - return sign_message(msg, msg.size(), rng); - } - -/* * Add more to the message to be signed */ void PK_Signer::update(const byte in[], u32bit length) @@ -165,19 +163,32 @@ void PK_Signer::update(const byte in[], u32bit length) } /* -* Add more to the message to be signed +* Check the signature we just created, to help prevent fault attacks */ -void PK_Signer::update(byte in) +bool PK_Signer::self_test_signature(const MemoryRegion<byte>& msg, + const MemoryRegion<byte>& sig) const { - update(&in, 1); - } + if(verify_op->with_recovery()) + { + SecureVector<byte> recovered = + verify_op->verify_mr(&sig[0], sig.size()); -/* -* Add more to the message to be signed -*/ -void PK_Signer::update(const MemoryRegion<byte>& in) - { - update(in, in.size()); + if(msg.size() > recovered.size()) + { + u32bit extra_0s = msg.size() - recovered.size(); + + for(size_t i = 0; i != extra_0s; ++i) + if(msg[i] != 0) + return false; + + return same_mem(&msg[extra_0s], &recovered[0], recovered.size()); + } + + return (recovered == msg); + } + else + return verify_op->verify(&msg[0], msg.size(), + &sig[0], sig.size()); } /* @@ -186,21 +197,24 @@ void PK_Signer::update(const MemoryRegion<byte>& in) SecureVector<byte> PK_Signer::signature(RandomNumberGenerator& rng) { SecureVector<byte> encoded = emsa->encoding_of(emsa->raw_data(), - key.max_input_bits(), + op->max_input_bits(), rng); - SecureVector<byte> plain_sig = key.sign(encoded, encoded.size(), rng); + SecureVector<byte> plain_sig = op->sign(encoded, encoded.size(), rng); - if(key.message_parts() == 1 || sig_format == IEEE_1363) + if(!self_test_signature(encoded, plain_sig)) + throw Internal_Error("PK_Signer consistency check failed"); + + if(op->message_parts() == 1 || sig_format == IEEE_1363) return plain_sig; if(sig_format == DER_SEQUENCE) { - if(plain_sig.size() % key.message_parts()) + if(plain_sig.size() % op->message_parts()) throw Encoding_Error("PK_Signer: strange signature size found"); - const u32bit SIZE_OF_PART = plain_sig.size() / key.message_parts(); + const u32bit SIZE_OF_PART = plain_sig.size() / op->message_parts(); - std::vector<BigInt> sig_parts(key.message_parts()); + std::vector<BigInt> sig_parts(op->message_parts()); for(u32bit j = 0; j != sig_parts.size(); ++j) sig_parts[j].binary_decode(plain_sig + SIZE_OF_PART*j, SIZE_OF_PART); @@ -218,18 +232,25 @@ SecureVector<byte> PK_Signer::signature(RandomNumberGenerator& rng) /* * PK_Verifier Constructor */ -PK_Verifier::PK_Verifier(EMSA* emsa_obj) +PK_Verifier::PK_Verifier(const Public_Key& key, + const std::string& emsa_name, + Signature_Format format) { - emsa = emsa_obj; - sig_format = IEEE_1363; - } + Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory()); -/* -* PK_Verifier Destructor -*/ -PK_Verifier::~PK_Verifier() - { - delete emsa; + while(const Engine* engine = i.next()) + { + op = engine->get_verify_op(key); + if(op) + break; + } + + if(!op) + throw Lookup_Error("PK_Verifier: No working engine for " + + key.algo_name()); + + emsa = get_emsa(emsa_name); + sig_format = format; } /* @@ -237,7 +258,7 @@ PK_Verifier::~PK_Verifier() */ void PK_Verifier::set_input_format(Signature_Format format) { - if(key_message_parts() == 1 && format != IEEE_1363) + if(op->message_parts() == 1 && format != IEEE_1363) throw Invalid_State("PK_Verifier: This algorithm always uses IEEE 1363"); sig_format = format; } @@ -245,15 +266,6 @@ void PK_Verifier::set_input_format(Signature_Format format) /* * Verify a message */ -bool PK_Verifier::verify_message(const MemoryRegion<byte>& msg, - const MemoryRegion<byte>& sig) - { - return verify_message(msg, msg.size(), sig, sig.size()); - } - -/* -* Verify a message -*/ bool PK_Verifier::verify_message(const byte msg[], u32bit msg_length, const byte sig[], u32bit sig_length) { @@ -270,30 +282,6 @@ void PK_Verifier::update(const byte in[], u32bit length) } /* -* Append to the message -*/ -void PK_Verifier::update(byte in) - { - update(&in, 1); - } - -/* -* Append to the message -*/ -void PK_Verifier::update(const MemoryRegion<byte>& in) - { - update(in, in.size()); - } - -/* -* Check a signature -*/ -bool PK_Verifier::check_signature(const MemoryRegion<byte>& sig) - { - return check_signature(sig, sig.size()); - } - -/* * Check a signature */ bool PK_Verifier::check_signature(const byte sig[], u32bit length) @@ -313,10 +301,11 @@ bool PK_Verifier::check_signature(const byte sig[], u32bit length) BigInt sig_part; ber_sig.decode(sig_part); real_sig.append(BigInt::encode_1363(sig_part, - key_message_part_size())); + op->message_part_size())); ++count; } - if(count != key_message_parts()) + + if(count != op->message_parts()) throw Decoding_Error("PK_Verifier: signature size invalid"); return validate_signature(emsa->raw_data(), @@ -332,60 +321,57 @@ bool PK_Verifier::check_signature(const byte sig[], u32bit length) /* * Verify a signature */ -bool PK_Verifier_with_MR::validate_signature(const MemoryRegion<byte>& msg, - const byte sig[], u32bit sig_len) +bool PK_Verifier::validate_signature(const MemoryRegion<byte>& msg, + const byte sig[], u32bit sig_len) { - SecureVector<byte> output_of_key = key.verify(sig, sig_len); - return emsa->verify(output_of_key, msg, key.max_input_bits()); - } - -/* -* Verify a signature -*/ -bool PK_Verifier_wo_MR::validate_signature(const MemoryRegion<byte>& msg, - const byte sig[], u32bit sig_len) - { - Null_RNG rng; + if(op->with_recovery()) + { + SecureVector<byte> output_of_key = op->verify_mr(sig, sig_len); + return emsa->verify(output_of_key, msg, op->max_input_bits()); + } + else + { + Null_RNG rng; - SecureVector<byte> encoded = - emsa->encoding_of(msg, key.max_input_bits(), rng); + SecureVector<byte> encoded = + emsa->encoding_of(msg, op->max_input_bits(), rng); - return key.verify(encoded, encoded.size(), sig, sig_len); + return op->verify(encoded, encoded.size(), sig, sig_len); + } } /* * PK_Key_Agreement Constructor */ -PK_Key_Agreement::PK_Key_Agreement(const PK_Key_Agreement_Key& k, - KDF* kdf_obj) : - key(k), kdf(kdf_obj) +PK_Key_Agreement::PK_Key_Agreement(const PK_Key_Agreement_Key& key, + const std::string& kdf_name) { - } + Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory()); -/* -* Perform Key Agreement Operation -*/ -SymmetricKey PK_Key_Agreement::derive_key(u32bit key_len, - const byte in[], u32bit in_len, - const std::string& params) const - { - return derive_key(key_len, in, in_len, - reinterpret_cast<const byte*>(params.data()), - params.length()); + while(const Engine* engine = i.next()) + { + op = engine->get_key_agreement_op(key); + if(op) + break; + } + + if(!op) + throw Lookup_Error("PK_Key_Agreement: No working engine for " + + key.algo_name()); + + kdf = get_kdf(kdf_name); } -/* -* Perform Key Agreement Operation -*/ SymmetricKey PK_Key_Agreement::derive_key(u32bit key_len, const byte in[], u32bit in_len, const byte params[], u32bit params_len) const { - OctetString z = key.derive_key(in, in_len); + SecureVector<byte> z = op->agree(in, in_len); + if(!kdf) return z; - return kdf->derive_key(key_len, z.bits_of(), params, params_len); + return kdf->derive_key(key_len, z, params, params_len); } } diff --git a/src/pubkey/pubkey.h b/src/pubkey/pubkey.h index c73a54d35..c31aed67b 100644 --- a/src/pubkey/pubkey.h +++ b/src/pubkey/pubkey.h @@ -1,6 +1,6 @@ /* * Public Key Interface -* (C) 1999-2007 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -9,6 +9,7 @@ #define BOTAN_PUBKEY_H__ #include <botan/pk_keys.h> +#include <botan/pk_ops.h> #include <botan/symkey.h> #include <botan/rng.h> #include <botan/eme.h> @@ -37,7 +38,10 @@ class BOTAN_DLL PK_Encryptor * @return the encrypted message */ SecureVector<byte> encrypt(const byte in[], u32bit length, - RandomNumberGenerator& rng) const; + RandomNumberGenerator& rng) const + { + return enc(in, length, rng); + } /** * Encrypt a message. @@ -46,7 +50,10 @@ class BOTAN_DLL PK_Encryptor * @return the encrypted message */ SecureVector<byte> encrypt(const MemoryRegion<byte>& in, - RandomNumberGenerator& rng) const; + RandomNumberGenerator& rng) const + { + return enc(&in[0], in.size(), rng); + } /** * Return the maximum allowed message size in bytes. @@ -54,8 +61,12 @@ class BOTAN_DLL PK_Encryptor */ virtual u32bit maximum_input_size() const = 0; + PK_Encryptor() {} virtual ~PK_Encryptor() {} private: + PK_Encryptor(const PK_Encryptor&) {} + PK_Encryptor& operator=(const PK_Encryptor&) { return *this; } + virtual SecureVector<byte> enc(const byte[], u32bit, RandomNumberGenerator&) const = 0; }; @@ -72,17 +83,27 @@ class BOTAN_DLL PK_Decryptor * @param length the length of the above byte array * @return the decrypted message */ - SecureVector<byte> decrypt(const byte in[], u32bit length) const; + SecureVector<byte> decrypt(const byte in[], u32bit length) const + { + return dec(in, length); + } /** * Decrypt a ciphertext. * @param in the ciphertext * @return the decrypted message */ - SecureVector<byte> decrypt(const MemoryRegion<byte>& in) const; + SecureVector<byte> decrypt(const MemoryRegion<byte>& in) const + { + return dec(&in[0], in.size()); + } + PK_Decryptor() {} virtual ~PK_Decryptor() {} private: + PK_Decryptor(const PK_Decryptor&) {} + PK_Decryptor& operator=(const PK_Decryptor&) { return *this; } + virtual SecureVector<byte> dec(const byte[], u32bit) const = 0; }; @@ -111,13 +132,14 @@ class BOTAN_DLL PK_Signer * @return the signature */ SecureVector<byte> sign_message(const MemoryRegion<byte>& in, - RandomNumberGenerator& rng); + RandomNumberGenerator& rng) + { return sign_message(&in[0], in.size(), rng); } /** * Add a message part (single byte). * @param the byte to add */ - void update(byte in); + void update(byte in) { update(&in, 1); } /** * Add a message part. @@ -130,7 +152,7 @@ class BOTAN_DLL PK_Signer * Add a message part. * @param in the message part to add */ - void update(const MemoryRegion<byte>& in); + void update(const MemoryRegion<byte>& in) { update(&in[0], in.size()); } /** * Get the signature of the so far processed message (provided by the @@ -144,24 +166,31 @@ class BOTAN_DLL PK_Signer * Set the output format of the signature. * @param format the signature format to use */ - void set_output_format(Signature_Format format); + void set_output_format(Signature_Format format) { sig_format = format; } /** * Construct a PK Signer. * @param key the key to use inside this signer * @param emsa the EMSA to use * An example would be "EMSA1(SHA-224)". + * @param format the signature format to use */ - PK_Signer(const PK_Signing_Key& key, EMSA* emsa); + PK_Signer(const Private_Key& key, + const std::string& emsa, + Signature_Format format = IEEE_1363); - ~PK_Signer() { delete emsa; } + ~PK_Signer() { delete op; delete verify_op; delete emsa; } private: - PK_Signer(const PK_Signer&); - PK_Signer& operator=(const PK_Signer&); + bool self_test_signature(const MemoryRegion<byte>& msg, + const MemoryRegion<byte>& sig) const; - const PK_Signing_Key& key; - Signature_Format sig_format; + PK_Signer(const PK_Signer&) {} + PK_Signer& operator=(const PK_Signer&) { return *this; } + + PK_Ops::Signature* op; + PK_Ops::Verification* verify_op; EMSA* emsa; + Signature_Format sig_format; }; /** @@ -189,14 +218,17 @@ class BOTAN_DLL PK_Verifier * @return true if the signature is valid */ bool verify_message(const MemoryRegion<byte>& msg, - const MemoryRegion<byte>& sig); + const MemoryRegion<byte>& sig) + { + return verify_message(msg, msg.size(), sig, sig.size()); + } /** * Add a message part (single byte) of the message corresponding to the * signature to be verified. - * @param msg_part the byte to add + * @param in the byte to add */ - void update(byte msg_part); + void update(byte in) { update(&in, 1); } /** * Add a message part of the message corresponding to the @@ -209,9 +241,10 @@ class BOTAN_DLL PK_Verifier /** * Add a message part of the message corresponding to the * signature to be verified. - * @param msg_part the new message part + * @param in the new message part */ - void update(const MemoryRegion<byte>& msg_part); + void update(const MemoryRegion<byte>& in) + { update(&in[0], in.size()); } /** * Check the signature of the buffered message, i.e. the one build @@ -228,7 +261,10 @@ class BOTAN_DLL PK_Verifier * @param sig the signature to be verified * @return true if the signature is valid, false otherwise */ - bool check_signature(const MemoryRegion<byte>& sig); + bool check_signature(const MemoryRegion<byte>& sig) + { + return check_signature(&sig[0], sig.size()); + } /** * Set the format of the signatures fed to this verifier. @@ -238,23 +274,25 @@ class BOTAN_DLL PK_Verifier /** * Construct a PK Verifier. - * @param emsa the EMSA to use - * An example would be new EMSA1(new SHA_224) + * @param pub_key the public key to verify against + * @param emsa the EMSA to use (eg "EMSA3(SHA-1)") + * @param format the signature format to use */ - PK_Verifier(EMSA* emsa); + PK_Verifier(const Public_Key& pub_key, + const std::string& emsa, + Signature_Format format = IEEE_1363); - virtual ~PK_Verifier(); - protected: - virtual bool validate_signature(const MemoryRegion<byte>&, - const byte[], u32bit) = 0; - virtual u32bit key_message_parts() const = 0; - virtual u32bit key_message_part_size() const = 0; + ~PK_Verifier() { delete op; delete emsa; } + private: + PK_Verifier(const PK_Verifier&) {} + PK_Verifier& operator=(const PK_Verifier&) { return *this; } - Signature_Format sig_format; + bool validate_signature(const MemoryRegion<byte>& msg, + const byte sig[], u32bit sig_len); + + PK_Ops::Verification* op; EMSA* emsa; - private: - PK_Verifier(const PK_Verifier&); - PK_Verifier& operator=(const PK_Verifier&); + Signature_Format sig_format; }; /* @@ -263,31 +301,90 @@ class BOTAN_DLL PK_Verifier class BOTAN_DLL PK_Key_Agreement { public: - SymmetricKey derive_key(u32bit, const byte[], u32bit, - const std::string& = "") const; - SymmetricKey derive_key(u32bit, const byte[], u32bit, - const byte[], u32bit) const; + + /* + * Perform Key Agreement Operation + * @param key_len the desired key output size + * @param in the other parties key + * @param in_len the length of in in bytes + * @param params extra derivation params + * @param params_len the length of params in bytes + */ + SymmetricKey derive_key(u32bit key_len, + const byte in[], + u32bit in_len, + const byte params[], + u32bit params_len) const; + + /* + * Perform Key Agreement Operation + * @param key_len the desired key output size + * @param in the other parties key + * @param in_len the length of in in bytes + * @param params extra derivation params + * @param params_len the length of params in bytes + */ + SymmetricKey derive_key(u32bit key_len, + const MemoryRegion<byte>& in, + const byte params[], + u32bit params_len) const + { + return derive_key(key_len, &in[0], in.size(), + params, params_len); + } + + /* + * Perform Key Agreement Operation + * @param key_len the desired key output size + * @param in the other parties key + * @param in_len the length of in in bytes + * @param params extra derivation params + */ + SymmetricKey derive_key(u32bit key_len, + const byte in[], u32bit in_len, + const std::string& params = "") const + { + return derive_key(key_len, in, in_len, + reinterpret_cast<const byte*>(params.data()), + params.length()); + } + + /* + * Perform Key Agreement Operation + * @param key_len the desired key output size + * @param in the other parties key + * @param params extra derivation params + */ + SymmetricKey derive_key(u32bit key_len, + const MemoryRegion<byte>& in, + const std::string& params = "") const + { + return derive_key(key_len, &in[0], in.size(), + reinterpret_cast<const byte*>(params.data()), + params.length()); + } /** * Construct a PK Key Agreement. * @param key the key to use - * @param kdf the KDF to use + * @param kdf name of the KDF to use (or 'Raw' for no KDF) */ - PK_Key_Agreement(const PK_Key_Agreement_Key& key, KDF* kdf); + PK_Key_Agreement(const PK_Key_Agreement_Key& key, + const std::string& kdf); - ~PK_Key_Agreement() { delete kdf; } + ~PK_Key_Agreement() { delete op; delete kdf; } private: - PK_Key_Agreement(const PK_Key_Agreement_Key&); - PK_Key_Agreement& operator=(const PK_Key_Agreement&); + PK_Key_Agreement(const PK_Key_Agreement_Key&) {} + PK_Key_Agreement& operator=(const PK_Key_Agreement&) { return *this; } - const PK_Key_Agreement_Key& key; + PK_Ops::Key_Agreement* op; KDF* kdf; }; /** * Encryption with an MR algorithm and an EME. */ -class BOTAN_DLL PK_Encryptor_MR_with_EME : public PK_Encryptor +class BOTAN_DLL PK_Encryptor_EME : public PK_Encryptor { public: u32bit maximum_input_size() const; @@ -297,25 +394,22 @@ class BOTAN_DLL PK_Encryptor_MR_with_EME : public PK_Encryptor * @param key the key to use inside the decryptor * @param eme the EME to use */ - PK_Encryptor_MR_with_EME(const PK_Encrypting_Key& key, - EME* eme); + PK_Encryptor_EME(const Public_Key& key, + const std::string& eme); - ~PK_Encryptor_MR_with_EME() { delete encoder; } + ~PK_Encryptor_EME() { delete op; delete eme; } private: - PK_Encryptor_MR_with_EME(const PK_Encryptor_MR_with_EME&); - PK_Encryptor_MR_with_EME& operator=(const PK_Encryptor_MR_with_EME&); - SecureVector<byte> enc(const byte[], u32bit, RandomNumberGenerator& rng) const; - const PK_Encrypting_Key& key; - const EME* encoder; + PK_Ops::Encryption* op; + const EME* eme; }; /** * Decryption with an MR algorithm and an EME. */ -class BOTAN_DLL PK_Decryptor_MR_with_EME : public PK_Decryptor +class BOTAN_DLL PK_Decryptor_EME : public PK_Decryptor { public: /** @@ -323,68 +417,15 @@ class BOTAN_DLL PK_Decryptor_MR_with_EME : public PK_Decryptor * @param key the key to use inside the encryptor * @param eme the EME to use */ - PK_Decryptor_MR_with_EME(const PK_Decrypting_Key& key, - EME* eme); + PK_Decryptor_EME(const Private_Key& key, + const std::string& eme); - ~PK_Decryptor_MR_with_EME() { delete encoder; } + ~PK_Decryptor_EME() { delete op; delete eme; } private: - PK_Decryptor_MR_with_EME(const PK_Decryptor_MR_with_EME&); - PK_Decryptor_MR_with_EME& operator=(const PK_Decryptor_MR_with_EME&); - SecureVector<byte> dec(const byte[], u32bit) const; - const PK_Decrypting_Key& key; - const EME* encoder; - }; - -/** -* Public Key Verifier with Message Recovery. -*/ -class BOTAN_DLL PK_Verifier_with_MR : public PK_Verifier - { - public: - /** - * Construct an instance. - * @param key the key to use inside the verifier - * @param emsa_name the name of the EMSA to use - */ - PK_Verifier_with_MR(const PK_Verifying_with_MR_Key& k, - EMSA* emsa_obj) : PK_Verifier(emsa_obj), key(k) {} - - private: - PK_Verifier_with_MR(const PK_Verifying_with_MR_Key&); - PK_Verifier_with_MR& operator=(const PK_Verifier_with_MR&); - - bool validate_signature(const MemoryRegion<byte>&, const byte[], u32bit); - u32bit key_message_parts() const { return key.message_parts(); } - u32bit key_message_part_size() const { return key.message_part_size(); } - - const PK_Verifying_with_MR_Key& key; - }; - -/** -* Public Key Verifier without Message Recovery -*/ -class BOTAN_DLL PK_Verifier_wo_MR : public PK_Verifier - { - public: - /** - * Construct an instance. - * @param key the key to use inside the verifier - * @param emsa_name the name of the EMSA to use - */ - PK_Verifier_wo_MR(const PK_Verifying_wo_MR_Key& k, - EMSA* emsa_obj) : PK_Verifier(emsa_obj), key(k) {} - - private: - PK_Verifier_wo_MR(const PK_Verifying_wo_MR_Key&); - PK_Verifier_wo_MR& operator=(const PK_Verifier_wo_MR&); - - bool validate_signature(const MemoryRegion<byte>&, const byte[], u32bit); - u32bit key_message_parts() const { return key.message_parts(); } - u32bit key_message_part_size() const { return key.message_part_size(); } - - const PK_Verifying_wo_MR_Key& key; + PK_Ops::Decryption* op; + const EME* eme; }; } diff --git a/src/pubkey/rsa/rsa.cpp b/src/pubkey/rsa/rsa.cpp index 38ea1eeca..200e92821 100644 --- a/src/pubkey/rsa/rsa.cpp +++ b/src/pubkey/rsa/rsa.cpp @@ -1,6 +1,6 @@ /* * RSA -* (C) 1999-2008 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -9,50 +9,10 @@ #include <botan/parsing.h> #include <botan/numthry.h> #include <botan/keypair.h> -#include <botan/look_pk.h> namespace Botan { /* -* RSA_PublicKey Constructor -*/ -RSA_PublicKey::RSA_PublicKey(const BigInt& mod, const BigInt& exp) - { - n = mod; - e = exp; - X509_load_hook(); - } - -/* -* RSA Public Operation -*/ -BigInt RSA_PublicKey::public_op(const BigInt& i) const - { - if(i >= n) - throw Invalid_Argument(algo_name() + "::public_op: input is too large"); - return core.public_op(i); - } - -/* -* RSA Encryption Function -*/ -SecureVector<byte> RSA_PublicKey::encrypt(const byte in[], u32bit len, - RandomNumberGenerator&) const - { - BigInt i(in, len); - return BigInt::encode_1363(public_op(i), n.bytes()); - } - -/* -* RSA Verification Function -*/ -SecureVector<byte> RSA_PublicKey::verify(const byte in[], u32bit len) const - { - BigInt i(in, len); - return BigInt::encode(public_op(i)); - } - -/* * Create a RSA private key */ RSA_PrivateKey::RSA_PrivateKey(RandomNumberGenerator& rng, @@ -67,64 +27,17 @@ RSA_PrivateKey::RSA_PrivateKey(RandomNumberGenerator& rng, e = exp; p = random_prime(rng, (bits + 1) / 2, e); q = random_prime(rng, bits - p.bits(), e); - d = inverse_mod(e, lcm(p - 1, q - 1)); - - PKCS8_load_hook(rng, true); + n = p * q; if(n.bits() != bits) throw Self_Test_Failure(algo_name() + " private key generation failed"); - } - -/* -* RSA_PrivateKey Constructor -*/ -RSA_PrivateKey::RSA_PrivateKey(RandomNumberGenerator& rng, - const BigInt& prime1, const BigInt& prime2, - const BigInt& exp, const BigInt& d_exp, - const BigInt& mod) - { - p = prime1; - q = prime2; - e = exp; - d = d_exp; - n = mod; - - if(d == 0) - d = inverse_mod(e, lcm(p - 1, q - 1)); - - PKCS8_load_hook(rng); - } - -/* -* RSA Private Operation -*/ -BigInt RSA_PrivateKey::private_op(const byte in[], u32bit length) const - { - BigInt i(in, length); - if(i >= n) - throw Invalid_Argument(algo_name() + "::private_op: input is too large"); - - BigInt r = core.private_op(i); - if(i != public_op(r)) - throw Self_Test_Failure(algo_name() + " private operation check failed"); - return r; - } -/* -* RSA Decryption Operation -*/ -SecureVector<byte> RSA_PrivateKey::decrypt(const byte in[], u32bit len) const - { - return BigInt::encode(private_op(in, len)); - } + d = inverse_mod(e, lcm(p - 1, q - 1)); + d1 = d % (p - 1); + d2 = d % (q - 1); + c = inverse_mod(q, p); -/* -* RSA Signature Operation -*/ -SecureVector<byte> RSA_PrivateKey::sign(const byte in[], u32bit len, - RandomNumberGenerator&) const - { - return BigInt::encode_1363(private_op(in, len), n.bytes()); + gen_check(rng); } /* @@ -143,15 +56,12 @@ bool RSA_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const try { - KeyPair::check_key(rng, - get_pk_encryptor(*this, "EME1(SHA-1)"), - get_pk_decryptor(*this, "EME1(SHA-1)") - ); + PK_Signer this_signer(*this, "EMSA4(SHA-1)"); + PK_Verifier this_verifier(*this, "EMSA4(SHA-1)"); KeyPair::check_key(rng, - get_pk_signer(*this, "EMSA4(SHA-1)"), - get_pk_verifier(*this, "EMSA4(SHA-1)") - ); + this_signer, + this_verifier); } catch(Self_Test_Failure) { @@ -161,4 +71,59 @@ bool RSA_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const return true; } +RSA_Private_Operation::RSA_Private_Operation(const RSA_PrivateKey& rsa) : + n(rsa.get_n()), + q(rsa.get_q()), + c(rsa.get_c()), + powermod_e_n(rsa.get_e(), rsa.get_n()), + powermod_d1_p(rsa.get_d1(), rsa.get_p()), + powermod_d2_q(rsa.get_d2(), rsa.get_q()), + mod_p(rsa.get_p()) + { + BigInt k = Blinder::choose_nonce(powermod_e_n(q), n); + blinder = Blinder(powermod_e_n(k), inverse_mod(k, n), n); + } + +BigInt RSA_Private_Operation::private_op(const BigInt& m) const + { + if(m >= n) + throw Invalid_Argument("RSA private op - input is too large"); + + BigInt j1 = powermod_d1_p(m); + BigInt j2 = powermod_d2_q(m); + + j1 = mod_p.reduce(sub_mul(j1, j2, c)); + + return mul_add(j1, q, j2); + } + +SecureVector<byte> +RSA_Private_Operation::sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng) + { + /* We don't check signatures against powermod_e_n here because + PK_Signer checks verification consistency for all signature + algorithms. + */ + + BigInt m(msg, msg_len); + BigInt x = blinder.unblind(private_op(blinder.blind(m))); + return BigInt::encode_1363(x, n.bytes()); + } + +/* +* RSA Decryption Operation +*/ +SecureVector<byte> +RSA_Private_Operation::decrypt(const byte msg[], u32bit msg_len) + { + BigInt m(msg, msg_len); + BigInt x = blinder.unblind(private_op(blinder.blind(m))); + + if(m != powermod_e_n(x)) + throw Internal_Error("RSA private op failed consistency check"); + + return BigInt::encode(x); + } + } diff --git a/src/pubkey/rsa/rsa.h b/src/pubkey/rsa/rsa.h index 0580fe8eb..72cd80fef 100644 --- a/src/pubkey/rsa/rsa.h +++ b/src/pubkey/rsa/rsa.h @@ -9,15 +9,15 @@ #define BOTAN_RSA_H__ #include <botan/if_algo.h> +#include <botan/reducer.h> +#include <botan/blinding.h> namespace Botan { /** * RSA Public Key */ -class BOTAN_DLL RSA_PublicKey : public PK_Encrypting_Key, - public PK_Verifying_with_MR_Key, - public virtual IF_Scheme_PublicKey +class BOTAN_DLL RSA_PublicKey : public virtual IF_Scheme_PublicKey { public: std::string algo_name() const { return "RSA"; } @@ -25,57 +25,57 @@ class BOTAN_DLL RSA_PublicKey : public PK_Encrypting_Key, SecureVector<byte> encrypt(const byte[], u32bit, RandomNumberGenerator& rng) const; - SecureVector<byte> verify(const byte[], u32bit) const; - - RSA_PublicKey() {} + RSA_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) : + IF_Scheme_PublicKey(alg_id, key_bits) + {} /** * Create a RSA_PublicKey * @arg n the modulus * @arg e the exponent */ - RSA_PublicKey(const BigInt& n, const BigInt& e); + RSA_PublicKey(const BigInt& n, const BigInt& e) : + IF_Scheme_PublicKey(n, e) + {} + protected: - BigInt public_op(const BigInt&) const; + RSA_PublicKey() {} }; /** * RSA Private Key class. */ class BOTAN_DLL RSA_PrivateKey : public RSA_PublicKey, - public PK_Decrypting_Key, - public PK_Signing_Key, public IF_Scheme_PrivateKey { public: - SecureVector<byte> sign(const byte[], u32bit, - RandomNumberGenerator&) const; - SecureVector<byte> decrypt(const byte[], u32bit) const; bool check_key(RandomNumberGenerator& rng, bool) const; - /** - * Default constructor, does not set any internal values. Use this - * constructor if you wish to decode a DER or PEM encoded key. - */ - RSA_PrivateKey() {} + RSA_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + RandomNumberGenerator& rng) : + IF_Scheme_PrivateKey(rng, alg_id, key_bits) {} /** * Construct a private key from the specified parameters. - * @param rng the random number generator to use - * @param prime1 the first prime - * @param prime2 the second prime - * @param exp the exponent - * @param d_exp if specified, this has to be d with + * @param rng a random number generator + * @param p the first prime + * @param q the second prime + * @param e the exponent + * @param d if specified, this has to be d with * exp * d = 1 mod (p - 1, q - 1). Leave it as 0 if you wish to * the constructor to calculate it. * @param n if specified, this must be n = p * q. Leave it as 0 * if you wish to the constructor to calculate it. */ RSA_PrivateKey(RandomNumberGenerator& rng, - const BigInt& p, const BigInt& q, const BigInt& e, - const BigInt& d = 0, const BigInt& n = 0); + const BigInt& p, const BigInt& q, + const BigInt& e, const BigInt& d = 0, + const BigInt& n = 0) : + IF_Scheme_PrivateKey(rng, p, q, e, d, n) {} /** * Create a new private key with the specified bit length @@ -85,8 +85,66 @@ class BOTAN_DLL RSA_PrivateKey : public RSA_PublicKey, */ RSA_PrivateKey(RandomNumberGenerator& rng, u32bit bits, u32bit exp = 65537); + }; + +class BOTAN_DLL RSA_Private_Operation : public PK_Ops::Signature, + public PK_Ops::Decryption + { + public: + RSA_Private_Operation(const RSA_PrivateKey& rsa); + + u32bit max_input_bits() const { return (n.bits() - 1); } + + SecureVector<byte> sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng); + + SecureVector<byte> decrypt(const byte msg[], u32bit msg_len); + + private: + BigInt private_op(const BigInt& m) const; + + const BigInt& n; + const BigInt& q; + const BigInt& c; + Fixed_Exponent_Power_Mod powermod_e_n, powermod_d1_p, powermod_d2_q; + Modular_Reducer mod_p; + Blinder blinder; + }; + +class BOTAN_DLL RSA_Public_Operation : public PK_Ops::Verification, + public PK_Ops::Encryption + { + public: + RSA_Public_Operation(const RSA_PublicKey& rsa) : + n(rsa.get_n()), powermod_e_n(rsa.get_e(), rsa.get_n()) + {} + + u32bit max_input_bits() const { return (n.bits() - 1); } + bool with_recovery() const { return true; } + + SecureVector<byte> encrypt(const byte msg[], u32bit msg_len, + RandomNumberGenerator&) + { + BigInt m(msg, msg_len); + return BigInt::encode_1363(public_op(m), n.bytes()); + } + + SecureVector<byte> verify_mr(const byte msg[], u32bit msg_len) + { + BigInt m(msg, msg_len); + return BigInt::encode(public_op(m)); + } + private: - BigInt private_op(const byte[], u32bit) const; + BigInt public_op(const BigInt& m) const + { + if(m >= n) + throw Invalid_Argument("RSA public op - input is too large"); + return powermod_e_n(m); + } + + const BigInt& n; + Fixed_Exponent_Power_Mod powermod_e_n; }; } diff --git a/src/pubkey/rw/rw.cpp b/src/pubkey/rw/rw.cpp index 460c740ab..9600ae709 100644 --- a/src/pubkey/rw/rw.cpp +++ b/src/pubkey/rw/rw.cpp @@ -8,51 +8,12 @@ #include <botan/rw.h> #include <botan/numthry.h> #include <botan/keypair.h> -#include <botan/look_pk.h> #include <botan/parsing.h> #include <algorithm> namespace Botan { /* -* RW_PublicKey Constructor -*/ -RW_PublicKey::RW_PublicKey(const BigInt& mod, const BigInt& exp) - { - n = mod; - e = exp; - X509_load_hook(); - } - -/* -* Rabin-Williams Public Operation -*/ -BigInt RW_PublicKey::public_op(const BigInt& i) const - { - if((i > (n >> 1)) || i.is_negative()) - throw Invalid_Argument(algo_name() + "::public_op: i > n / 2 || i < 0"); - - BigInt r = core.public_op(i); - if(r % 16 == 12) return r; - if(r % 8 == 6) return 2*r; - - r = n - r; - if(r % 16 == 12) return r; - if(r % 8 == 6) return 2*r; - - throw Invalid_Argument(algo_name() + "::public_op: Invalid input"); - } - -/* -* Rabin-Williams Verification Function -*/ -SecureVector<byte> RW_PublicKey::verify(const byte in[], u32bit len) const - { - BigInt i(in, len); - return BigInt::encode(public_op(i)); - } - -/* * Create a Rabin-Williams private key */ RW_PrivateKey::RW_PrivateKey(RandomNumberGenerator& rng, @@ -67,53 +28,18 @@ RW_PrivateKey::RW_PrivateKey(RandomNumberGenerator& rng, e = exp; p = random_prime(rng, (bits + 1) / 2, e / 2, 3, 4); q = random_prime(rng, bits - p.bits(), e / 2, ((p % 8 == 3) ? 7 : 3), 8); - d = inverse_mod(e, lcm(p - 1, q - 1) >> 1); - PKCS8_load_hook(rng, true); + n = p * q; if(n.bits() != bits) throw Self_Test_Failure(algo_name() + " private key generation failed"); - } - -/* -* RW_PrivateKey Constructor -*/ -RW_PrivateKey::RW_PrivateKey(RandomNumberGenerator& rng, - const BigInt& prime1, const BigInt& prime2, - const BigInt& exp, const BigInt& d_exp, - const BigInt& mod) - { - p = prime1; - q = prime2; - e = exp; - d = d_exp; - n = mod; - - if(d == 0) - d = inverse_mod(e, lcm(p - 1, q - 1) >> 1); - - PKCS8_load_hook(rng); - } - -/* -* Rabin-Williams Signature Operation -*/ -SecureVector<byte> RW_PrivateKey::sign(const byte in[], u32bit len, - RandomNumberGenerator&) const - { - BigInt i(in, len); - if(i >= n || i % 16 != 12) - throw Invalid_Argument(algo_name() + "::sign: Invalid input"); - - BigInt r; - if(jacobi(i, n) == 1) r = core.private_op(i); - else r = core.private_op(i >> 1); - r = std::min(r, n - r); - if(i != public_op(r)) - throw Self_Test_Failure(algo_name() + " private operation check failed"); + d = inverse_mod(e, lcm(p - 1, q - 1) >> 1); + d1 = d % (p - 1); + d2 = d % (q - 1); + c = inverse_mod(q, p); - return BigInt::encode_1363(r, n.bytes()); + gen_check(rng); } /* @@ -132,10 +58,12 @@ bool RW_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const try { + PK_Signer this_signer(*this, "EMSA2(SHA-1)"); + PK_Verifier this_verifier(*this, "EMSA2(SHA-1)"); + KeyPair::check_key(rng, - get_pk_signer(*this, "EMSA2(SHA-1)"), - get_pk_verifier(*this, "EMSA2(SHA-1)") - ); + this_signer, + this_verifier); } catch(Self_Test_Failure) { @@ -145,4 +73,69 @@ bool RW_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const return true; } +RW_Signature_Operation::RW_Signature_Operation(const RW_PrivateKey& rw) : + n(rw.get_n()), + e(rw.get_e()), + q(rw.get_q()), + c(rw.get_c()), + powermod_d1_p(rw.get_d1(), rw.get_p()), + powermod_d2_q(rw.get_d2(), rw.get_q()), + mod_p(rw.get_p()) + { + } + +SecureVector<byte> +RW_Signature_Operation::sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng) + { + if(!blinder.initialized()) + { + BigInt k(rng, n.bits() / 2); + blinder = Blinder(power_mod(k, e, n), inverse_mod(k, n), n); + } + + BigInt i(msg, msg_len); + + if(i >= n || i % 16 != 12) + throw Invalid_Argument("Rabin-Williams: invalid input"); + + if(jacobi(i, n) != 1) + i >>= 1; + + i = blinder.blind(i); + + BigInt j1 = powermod_d1_p(i); + BigInt j2 = powermod_d2_q(i); + j1 = mod_p.reduce(sub_mul(j1, j2, c)); + + BigInt r = blinder.unblind(mul_add(j1, q, j2)); + + r = std::min(r, n - r); + + return BigInt::encode_1363(r, n.bytes()); + } + +SecureVector<byte> +RW_Verification_Operation::verify_mr(const byte msg[], u32bit msg_len) + { + BigInt m(msg, msg_len); + + if((m > (n >> 1)) || m.is_negative()) + throw Invalid_Argument("RW signature verification: m > n / 2 || m < 0"); + + BigInt r = powermod_e_n(m); + if(r % 16 == 12) + return BigInt::encode(r); + if(r % 8 == 6) + return BigInt::encode(2*r); + + r = n - r; + if(r % 16 == 12) + return BigInt::encode(r); + if(r % 8 == 6) + return BigInt::encode(2*r); + + throw Invalid_Argument("RW signature verification: Invalid signature"); + } + } diff --git a/src/pubkey/rw/rw.h b/src/pubkey/rw/rw.h index 900e5ebda..3ca9bb722 100644 --- a/src/pubkey/rw/rw.h +++ b/src/pubkey/rw/rw.h @@ -9,46 +9,90 @@ #define BOTAN_RW_H__ #include <botan/if_algo.h> +#include <botan/reducer.h> +#include <botan/blinding.h> namespace Botan { /* * Rabin-Williams Public Key */ -class BOTAN_DLL RW_PublicKey : public PK_Verifying_with_MR_Key, - public virtual IF_Scheme_PublicKey +class BOTAN_DLL RW_PublicKey : public virtual IF_Scheme_PublicKey { public: std::string algo_name() const { return "RW"; } - SecureVector<byte> verify(const byte[], u32bit) const; + RW_PublicKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits) : + IF_Scheme_PublicKey(alg_id, key_bits) + {} + + RW_PublicKey(const BigInt& mod, const BigInt& exponent) : + IF_Scheme_PublicKey(mod, exponent) + {} - RW_PublicKey() {} - RW_PublicKey(const BigInt&, const BigInt&); protected: - BigInt public_op(const BigInt&) const; + RW_PublicKey() {} }; /* * Rabin-Williams Private Key */ class BOTAN_DLL RW_PrivateKey : public RW_PublicKey, - public PK_Signing_Key, public IF_Scheme_PrivateKey { public: - SecureVector<byte> sign(const byte[], u32bit, - RandomNumberGenerator& rng) const; + RW_PrivateKey(const AlgorithmIdentifier& alg_id, + const MemoryRegion<byte>& key_bits, + RandomNumberGenerator& rng) : + IF_Scheme_PrivateKey(rng, alg_id, key_bits) {} + + RW_PrivateKey(RandomNumberGenerator& rng, + const BigInt& p, const BigInt& q, + const BigInt& e, const BigInt& d = 0, + const BigInt& n = 0) : + IF_Scheme_PrivateKey(rng, p, q, e, d, n) {} + + RW_PrivateKey(RandomNumberGenerator& rng, u32bit bits, u32bit = 2); bool check_key(RandomNumberGenerator& rng, bool) const; + }; + +class BOTAN_DLL RW_Signature_Operation : public PK_Ops::Signature + { + public: + RW_Signature_Operation(const RW_PrivateKey& rw); - RW_PrivateKey() {} + u32bit max_input_bits() const { return (n.bits() - 1); } - RW_PrivateKey(RandomNumberGenerator&, - const BigInt&, const BigInt&, const BigInt&, - const BigInt& = 0, const BigInt& = 0); + SecureVector<byte> sign(const byte msg[], u32bit msg_len, + RandomNumberGenerator& rng); + private: + const BigInt& n; + const BigInt& e; + const BigInt& q; + const BigInt& c; - RW_PrivateKey(RandomNumberGenerator& rng, u32bit bits, u32bit = 2); + Fixed_Exponent_Power_Mod powermod_d1_p, powermod_d2_q; + Modular_Reducer mod_p; + Blinder blinder; + }; + +class BOTAN_DLL RW_Verification_Operation : public PK_Ops::Verification + { + public: + RW_Verification_Operation(const RW_PublicKey& rw) : + n(rw.get_n()), powermod_e_n(rw.get_e(), rw.get_n()) + {} + + u32bit max_input_bits() const { return (n.bits() - 1); } + bool with_recovery() const { return true; } + + SecureVector<byte> verify_mr(const byte msg[], u32bit msg_len); + + private: + const BigInt& n; + Fixed_Exponent_Power_Mod powermod_e_n; }; } diff --git a/src/pubkey/pk_codecs/x509_key.cpp b/src/pubkey/x509_key.cpp index 4cd6371d8..babeb517f 100644 --- a/src/pubkey/pk_codecs/x509_key.cpp +++ b/src/pubkey/x509_key.cpp @@ -10,7 +10,6 @@ #include <botan/asn1_obj.h> #include <botan/der_enc.h> #include <botan/ber_dec.h> -#include <botan/oids.h> #include <botan/pem.h> #include <botan/internal/pk_algs.h> #include <memory> @@ -24,15 +23,11 @@ namespace X509 { */ void encode(const Public_Key& key, Pipe& pipe, X509_Encoding encoding) { - std::unique_ptr<X509_Encoder> encoder(key.x509_encoder()); - if(!encoder.get()) - throw Encoding_Error("X509::encode: Key does not support encoding"); - MemoryVector<byte> der = DER_Encoder() .start_cons(SEQUENCE) - .encode(encoder->alg_id()) - .encode(encoder->key_bits(), BIT_STRING) + .encode(key.algorithm_identifier()) + .encode(key.x509_subject_public_key(), BIT_STRING) .end_cons() .get_contents(); @@ -89,25 +84,7 @@ Public_Key* load_key(DataSource& source) if(key_bits.empty()) throw Decoding_Error("X.509 public key decoding failed"); - const std::string alg_name = OIDS::lookup(alg_id.oid); - if(alg_name == "") - throw Decoding_Error("Unknown algorithm OID: " + - alg_id.oid.as_string()); - - std::unique_ptr<Public_Key> key_obj(get_public_key(alg_name)); - if(!key_obj.get()) - throw Decoding_Error("Unknown PK algorithm/OID: " + alg_name + ", " + - alg_id.oid.as_string()); - - std::unique_ptr<X509_Decoder> decoder(key_obj->x509_decoder()); - - if(!decoder.get()) - throw Decoding_Error("Key does not support X.509 decoding"); - - decoder->alg_id(alg_id); - decoder->key_bits(key_bits); - - return key_obj.release(); + return make_public_key(alg_id, key_bits); } catch(Decoding_Error) { @@ -152,17 +129,18 @@ Public_Key* copy_key(const Public_Key& key) Key_Constraints find_constraints(const Public_Key& pub_key, Key_Constraints limits) { - const Public_Key* key = &pub_key; - u32bit constraints = 0; + const std::string name = pub_key.algo_name(); - if(dynamic_cast<const PK_Encrypting_Key*>(key)) - constraints |= KEY_ENCIPHERMENT | DATA_ENCIPHERMENT; + u32bit constraints = 0; - if(dynamic_cast<const PK_Key_Agreement_Key*>(key)) + if(name == "DH" || name == "ECDH") constraints |= KEY_AGREEMENT; - if(dynamic_cast<const PK_Verifying_wo_MR_Key*>(key) || - dynamic_cast<const PK_Verifying_with_MR_Key*>(key)) + if(name == "RSA" || name == "ElGamal") + constraints |= KEY_ENCIPHERMENT | DATA_ENCIPHERMENT; + + if(name == "RSA" || name == "RW" || name == "NR" || + name == "DSA" || name == "ECDSA") constraints |= DIGITAL_SIGNATURE | NON_REPUDIATION; if(limits) diff --git a/src/pubkey/pk_codecs/x509_key.h b/src/pubkey/x509_key.h index 9404b7ecc..13f11646e 100644 --- a/src/pubkey/pk_codecs/x509_key.h +++ b/src/pubkey/x509_key.h @@ -16,36 +16,10 @@ namespace Botan { /** -* This class represents abstract X.509 public key encoders. -*/ -class BOTAN_DLL X509_Encoder - { - public: - virtual AlgorithmIdentifier alg_id() const = 0; - virtual MemoryVector<byte> key_bits() const = 0; - virtual ~X509_Encoder() {} - }; - -/** -* This class represents abstract X.509 public key decoders. -*/ -class BOTAN_DLL X509_Decoder - { - public: - virtual void alg_id(const AlgorithmIdentifier&) = 0; - virtual void key_bits(const MemoryRegion<byte>&) = 0; - virtual ~X509_Decoder() {} - }; - -/** * This namespace contains functions for handling X509 objects. */ namespace X509 { -/* -* X.509 Public Key Encoding/Decoding -*/ - /** * Encode a key into a pipe. * @param key the public key to encode diff --git a/src/ssl/c_kex.cpp b/src/ssl/c_kex.cpp index 802946bb9..9e59beefc 100644 --- a/src/ssl/c_kex.cpp +++ b/src/ssl/c_kex.cpp @@ -1,15 +1,15 @@ /** -* Client Key Exchange Message -* (C) 2004-2008 Jack Lloyd +* Client Key Exchange Message +* (C) 2004-2010 Jack Lloyd * * Released under the terms of the Botan license */ #include <botan/tls_messages.h> +#include <botan/pubkey.h> #include <botan/dh.h> #include <botan/rsa.h> #include <botan/rng.h> -#include <botan/look_pk.h> #include <botan/loadstor.h> #include <memory> @@ -25,28 +25,28 @@ Client_Key_Exchange::Client_Key_Exchange(RandomNumberGenerator& rng, Version_Code using_version, Version_Code pref_version) { - const DH_PublicKey* dh_pub = dynamic_cast<const DH_PublicKey*>(pub_key); - const RSA_PublicKey* rsa_pub = dynamic_cast<const RSA_PublicKey*>(pub_key); - include_length = true; - if(dh_pub) + if(const DH_PublicKey* dh_pub = dynamic_cast<const DH_PublicKey*>(pub_key)) { DH_PrivateKey priv_key(rng, dh_pub->get_domain()); - pre_master = priv_key.derive_key(dh_pub->get_y()); + + PK_Key_Agreement ka(priv_key, "Raw"); + + pre_master = ka.derive_key(0, dh_pub->public_value()).bits_of(); + key_material = priv_key.public_value(); } - else if(rsa_pub) + else if(const RSA_PublicKey* rsa_pub = dynamic_cast<const RSA_PublicKey*>(pub_key)) { pre_master.resize(48); rng.randomize(pre_master, 48); pre_master[0] = (pref_version >> 8) & 0xFF; pre_master[1] = (pref_version ) & 0xFF; - std::auto_ptr<PK_Encryptor> encryptor(get_pk_encryptor(*rsa_pub, - "PKCS1v15")); + PK_Encryptor_EME encryptor(*rsa_pub, "PKCS1v15"); - key_material = encryptor->encrypt(pre_master, rng); + key_material = encryptor.encrypt(pre_master, rng); if(using_version == SSL_V3) include_length = false; @@ -120,16 +120,15 @@ Client_Key_Exchange::pre_master_secret(RandomNumberGenerator& rng, const Private_Key* priv_key, Version_Code version) { - const DH_PrivateKey* dh_priv = dynamic_cast<const DH_PrivateKey*>(priv_key); - const RSA_PrivateKey* rsa_priv = - dynamic_cast<const RSA_PrivateKey*>(priv_key); - if(dh_priv) + if(const DH_PrivateKey* dh_priv = dynamic_cast<const DH_PrivateKey*>(priv_key)) { try { - pre_master = dh_priv->derive_key(key_material, key_material.size()); + PK_Key_Agreement ka(*dh_priv, "Raw"); + + pre_master = ka.derive_key(0, key_material).bits_of(); } - catch(std::exception& e) + catch(...) { pre_master.resize(dh_priv->public_value().size()); rng.randomize(pre_master, pre_master.size()); @@ -137,19 +136,18 @@ Client_Key_Exchange::pre_master_secret(RandomNumberGenerator& rng, return pre_master; } - else if(rsa_priv) + else if(const RSA_PrivateKey* rsa_priv = dynamic_cast<const RSA_PrivateKey*>(priv_key)) { - std::auto_ptr<PK_Decryptor> decryptor(get_pk_decryptor(*rsa_priv, - "PKCS1v15")); + PK_Decryptor_EME decryptor(*rsa_priv, "PKCS1v15"); try { - pre_master = decryptor->decrypt(key_material); + pre_master = decryptor.decrypt(key_material); if(pre_master.size() != 48 || make_u16bit(pre_master[0], pre_master[1]) != version) throw Decoding_Error("Client_Key_Exchange: Secret corrupted"); } - catch(std::exception) + catch(...) { pre_master.resize(48); rng.randomize(pre_master, pre_master.size()); diff --git a/src/ssl/cert_ver.cpp b/src/ssl/cert_ver.cpp index 5ac28dd2e..7e17dbfab 100644 --- a/src/ssl/cert_ver.cpp +++ b/src/ssl/cert_ver.cpp @@ -1,12 +1,12 @@ /** -* Certificate Verify Message -* (C) 2004-2006 Jack Lloyd +* Certificate Verify Message +* (C) 2004-2010 Jack Lloyd * * Released under the terms of the Botan license */ #include <botan/tls_messages.h> -#include <botan/look_pk.h> +#include <botan/pubkey.h> #include <botan/rsa.h> #include <botan/dsa.h> #include <botan/loadstor.h> @@ -22,32 +22,24 @@ Certificate_Verify::Certificate_Verify(RandomNumberGenerator& rng, HandshakeHash& hash, const Private_Key* priv_key) { - const PK_Signing_Key* sign_key = - dynamic_cast<const PK_Signing_Key*>(priv_key); + std::string padding = ""; + Signature_Format format = IEEE_1363; - if(sign_key) + if(priv_key->algo_name() == "RSA") + padding = "EMSA3(TLS.Digest.0)"; + else if(priv_key->algo_name() == "DSA") { - PK_Signer* signer = 0; - try - { - if(dynamic_cast<const RSA_PrivateKey*>(sign_key)) - signer = get_pk_signer(*sign_key, "EMSA3(TLS.Digest.0)"); - else if(dynamic_cast<const DSA_PrivateKey*>(sign_key)) - signer = get_pk_signer(*sign_key, "EMSA1(SHA-1)"); - else - throw Invalid_Argument("Unknown PK algo for TLS signature"); - - signature = signer->sign_message(hash.final(), rng); - delete signer; - } - catch(...) - { - delete signer; - throw; - } - - send(writer, hash); + padding == "EMSA1(SHA-1)"; + format = DER_SEQUENCE; } + else + throw Invalid_Argument(priv_key->algo_name() + + " is invalid/unknown for TLS signatures"); + + PK_Signer signer(*priv_key, padding, format); + + signature = signer.sign_message(hash.final(), rng); + send(writer, hash); } /** @@ -90,20 +82,22 @@ bool Certificate_Verify::verify(const X509_Certificate& cert, std::auto_ptr<Public_Key> key(cert.subject_public_key()); - DSA_PublicKey* dsa_pub = dynamic_cast<DSA_PublicKey*>(key.get()); - RSA_PublicKey* rsa_pub = dynamic_cast<RSA_PublicKey*>(key.get()); + std::string padding = ""; + Signature_Format format = IEEE_1363; - std::auto_ptr<PK_Verifier> verifier; - - if(dsa_pub) - verifier.reset(get_pk_verifier(*dsa_pub, "EMSA1(SHA-1)", DER_SEQUENCE)); - else if(rsa_pub) - verifier.reset(get_pk_verifier(*rsa_pub, "EMSA3(TLS.Digest.0)")); + if(key->algo_name() == "RSA") + padding = "EMSA3(TLS.Digest.0)"; + else if(key->algo_name() == "DSA") + { + padding == "EMSA1(SHA-1)"; + format = DER_SEQUENCE; + } else - throw Invalid_Argument("Client did not provide a RSA/DSA cert"); + throw Invalid_Argument(key->algo_name() + + " is invalid/unknown for TLS signatures"); - // FIXME: WRONG - return verifier->verify_message(hash.final(), signature); + PK_Verifier verifier(*key, padding, format); + return verifier.verify_message(hash.final(), signature); } } diff --git a/src/ssl/s_kex.cpp b/src/ssl/s_kex.cpp index fd49fcb8c..94b17cb7e 100644 --- a/src/ssl/s_kex.cpp +++ b/src/ssl/s_kex.cpp @@ -6,10 +6,10 @@ */ #include <botan/tls_messages.h> +#include <botan/pubkey.h> #include <botan/dh.h> #include <botan/rsa.h> #include <botan/dsa.h> -#include <botan/look_pk.h> #include <botan/loadstor.h> #include <memory> @@ -43,38 +43,27 @@ Server_Key_Exchange::Server_Key_Exchange(RandomNumberGenerator& rng, else throw Invalid_Argument("Bad key for TLS key exchange: not DH or RSA"); - // FIXME: dup of stuff in cert_ver.cpp - // FIXME: it's OK for the server to be anonymous.... - const PK_Signing_Key* sign_key = - dynamic_cast<const PK_Signing_Key*>(priv_key); - - if(!sign_key) - throw Invalid_Argument("Server Kex: Private key not for signing"); - - PK_Signer* signer = 0; - try { - if(dynamic_cast<const RSA_PrivateKey*>(sign_key)) - signer = get_pk_signer(*sign_key, "EMSA3(TLS.Digest.0)"); - else if(dynamic_cast<const DSA_PrivateKey*>(sign_key)) - { - signer = get_pk_signer(*sign_key, "EMSA1(SHA-1)"); - signer->set_output_format(DER_SEQUENCE); - } - else - throw Invalid_Argument("Bad key for TLS signature: not RSA or DSA"); - - signer->update(c_random); - signer->update(s_random); - signer->update(serialize_params()); - signature = signer->signature(rng); - - delete signer; - } - catch(...) + + std::string padding = ""; + Signature_Format format = IEEE_1363; + + if(priv_key->algo_name() == "RSA") + padding = "EMSA3(TLS.Digest.0)"; + else if(priv_key->algo_name() == "DSA") { - delete signer; - throw; + padding == "EMSA1(SHA-1)"; + format = DER_SEQUENCE; } + else + throw Invalid_Argument(priv_key->algo_name() + + " is invalid/unknown for TLS signatures"); + + PK_Signer signer(*priv_key, padding, format); + + signer.update(c_random); + signer.update(s_random); + signer.update(serialize_params()); + signature = signer.signature(rng); send(writer, hash); } @@ -167,29 +156,31 @@ bool Server_Key_Exchange::verify(const X509_Certificate& cert, const MemoryRegion<byte>& c_random, const MemoryRegion<byte>& s_random) const { - std::auto_ptr<Public_Key> key(cert.subject_public_key()); - DSA_PublicKey* dsa_pub = dynamic_cast<DSA_PublicKey*>(key.get()); - RSA_PublicKey* rsa_pub = dynamic_cast<RSA_PublicKey*>(key.get()); + std::auto_ptr<Public_Key> key(cert.subject_public_key()); - std::auto_ptr<PK_Verifier> verifier; + std::string padding = ""; + Signature_Format format = IEEE_1363; - if(dsa_pub) + if(key->algo_name() == "RSA") + padding = "EMSA3(TLS.Digest.0)"; + else if(key->algo_name() == "DSA") { - verifier.reset(get_pk_verifier(*dsa_pub, "EMSA1(SHA-1)", DER_SEQUENCE)); - verifier->set_input_format(DER_SEQUENCE); + padding == "EMSA1(SHA-1)"; + format = DER_SEQUENCE; } - else if(rsa_pub) - verifier.reset(get_pk_verifier(*rsa_pub, "EMSA3(TLS.Digest.0)")); else - throw Invalid_Argument("Server did not provide a RSA/DSA cert"); + throw Invalid_Argument(key->algo_name() + + " is invalid/unknown for TLS signatures"); + + PK_Verifier verifier(*key, padding, format); SecureVector<byte> params_got = serialize_params(); - verifier->update(c_random); - verifier->update(s_random); - verifier->update(params_got); + verifier.update(c_random); + verifier.update(s_random); + verifier.update(params_got); - return verifier->check_signature(signature, signature.size()); + return verifier.check_signature(signature, signature.size()); } } diff --git a/src/stream/salsa20/salsa20.cpp b/src/stream/salsa20/salsa20.cpp index 1b97f4421..a38e6e305 100644 --- a/src/stream/salsa20/salsa20.cpp +++ b/src/stream/salsa20/salsa20.cpp @@ -1,6 +1,6 @@ /* -* Salsa20 -* (C) 1999-2008 Jack Lloyd +* Salsa20 / XSalsa20 +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -14,63 +14,68 @@ namespace Botan { namespace { +#define SALSA20_QUARTER_ROUND(x1, x2, x3, x4) \ + do { \ + x2 ^= rotate_left(x1 + x4, 7); \ + x3 ^= rotate_left(x2 + x1, 9); \ + x4 ^= rotate_left(x3 + x2, 13); \ + x1 ^= rotate_left(x4 + x3, 18); \ + } while(0) + +/* +* Generate HSalsa20 cipher stream (for XSalsa20 IV setup) +*/ +void hsalsa20(u32bit output[8], const u32bit input[16]) + { + u32bit x00 = input[ 0], x01 = input[ 1], x02 = input[ 2], x03 = input[ 3], + x04 = input[ 4], x05 = input[ 5], x06 = input[ 6], x07 = input[ 7], + x08 = input[ 8], x09 = input[ 9], x10 = input[10], x11 = input[11], + x12 = input[12], x13 = input[13], x14 = input[14], x15 = input[15]; + + for(u32bit i = 0; i != 10; ++i) + { + SALSA20_QUARTER_ROUND(x00, x04, x08, x12); + SALSA20_QUARTER_ROUND(x05, x09, x13, x01); + SALSA20_QUARTER_ROUND(x10, x14, x02, x06); + SALSA20_QUARTER_ROUND(x15, x03, x07, x11); + + SALSA20_QUARTER_ROUND(x00, x01, x02, x03); + SALSA20_QUARTER_ROUND(x05, x06, x07, x04); + SALSA20_QUARTER_ROUND(x10, x11, x08, x09); + SALSA20_QUARTER_ROUND(x15, x12, x13, x14); + } + + output[0] = x00; + output[1] = x05; + output[2] = x10; + output[3] = x15; + output[4] = x06; + output[5] = x07; + output[6] = x08; + output[7] = x09; + } + /* * Generate Salsa20 cipher stream */ void salsa20(byte output[64], const u32bit input[16]) { - u32bit x00 = input[0]; - u32bit x01 = input[1]; - u32bit x02 = input[2]; - u32bit x03 = input[3]; - u32bit x04 = input[4]; - u32bit x05 = input[5]; - u32bit x06 = input[6]; - u32bit x07 = input[7]; - u32bit x08 = input[8]; - u32bit x09 = input[9]; - u32bit x10 = input[10]; - u32bit x11 = input[11]; - u32bit x12 = input[12]; - u32bit x13 = input[13]; - u32bit x14 = input[14]; - u32bit x15 = input[15]; + u32bit x00 = input[ 0], x01 = input[ 1], x02 = input[ 2], x03 = input[ 3], + x04 = input[ 4], x05 = input[ 5], x06 = input[ 6], x07 = input[ 7], + x08 = input[ 8], x09 = input[ 9], x10 = input[10], x11 = input[11], + x12 = input[12], x13 = input[13], x14 = input[14], x15 = input[15]; for(u32bit i = 0; i != 10; ++i) { - x04 ^= rotate_left(x00 + x12, 7); - x08 ^= rotate_left(x04 + x00, 9); - x12 ^= rotate_left(x08 + x04, 13); - x00 ^= rotate_left(x12 + x08, 18); - x09 ^= rotate_left(x05 + x01, 7); - x13 ^= rotate_left(x09 + x05, 9); - x01 ^= rotate_left(x13 + x09, 13); - x05 ^= rotate_left(x01 + x13, 18); - x14 ^= rotate_left(x10 + x06, 7); - x02 ^= rotate_left(x14 + x10, 9); - x06 ^= rotate_left(x02 + x14, 13); - x10 ^= rotate_left(x06 + x02, 18); - x03 ^= rotate_left(x15 + x11, 7); - x07 ^= rotate_left(x03 + x15, 9); - x11 ^= rotate_left(x07 + x03, 13); - x15 ^= rotate_left(x11 + x07, 18); - - x01 ^= rotate_left(x00 + x03, 7); - x02 ^= rotate_left(x01 + x00, 9); - x03 ^= rotate_left(x02 + x01, 13); - x00 ^= rotate_left(x03 + x02, 18); - x06 ^= rotate_left(x05 + x04, 7); - x07 ^= rotate_left(x06 + x05, 9); - x04 ^= rotate_left(x07 + x06, 13); - x05 ^= rotate_left(x04 + x07, 18); - x11 ^= rotate_left(x10 + x09, 7); - x08 ^= rotate_left(x11 + x10, 9); - x09 ^= rotate_left(x08 + x11, 13); - x10 ^= rotate_left(x09 + x08, 18); - x12 ^= rotate_left(x15 + x14, 7); - x13 ^= rotate_left(x12 + x15, 9); - x14 ^= rotate_left(x13 + x12, 13); - x15 ^= rotate_left(x14 + x13, 18); + SALSA20_QUARTER_ROUND(x00, x04, x08, x12); + SALSA20_QUARTER_ROUND(x05, x09, x13, x01); + SALSA20_QUARTER_ROUND(x10, x14, x02, x06); + SALSA20_QUARTER_ROUND(x15, x03, x07, x11); + + SALSA20_QUARTER_ROUND(x00, x01, x02, x03); + SALSA20_QUARTER_ROUND(x05, x06, x07, x04); + SALSA20_QUARTER_ROUND(x10, x11, x08, x09); + SALSA20_QUARTER_ROUND(x15, x12, x13, x14); } store_le(x00 + input[ 0], output + 4 * 0); @@ -100,11 +105,11 @@ void Salsa20::cipher(const byte in[], byte out[], u32bit length) { while(length >= buffer.size() - position) { - xor_buf(out, in, buffer.begin() + position, buffer.size() - position); + xor_buf(out, in, &buffer[position], buffer.size() - position); length -= (buffer.size() - position); in += (buffer.size() - position); out += (buffer.size() - position); - salsa20(buffer.begin(), state); + salsa20(&buffer[0], state); ++state[8]; if(!state[8]) // if overflow in state[8] @@ -113,7 +118,7 @@ void Salsa20::cipher(const byte in[], byte out[], u32bit length) position = 0; } - xor_buf(out, in, buffer.begin() + position, length); + xor_buf(out, in, &buffer[position], length); position += length; } @@ -174,12 +179,39 @@ void Salsa20::set_iv(const byte iv[], u32bit length) if(!valid_iv_length(length)) throw Invalid_IV_Length(name(), length); - state[6] = load_le<u32bit>(iv, 0); - state[7] = load_le<u32bit>(iv, 1); + if(length == 8) + { + // Salsa20 + state[6] = load_le<u32bit>(iv, 0); + state[7] = load_le<u32bit>(iv, 1); + } + else + { + // XSalsa20 + state[6] = load_le<u32bit>(iv, 0); + state[7] = load_le<u32bit>(iv, 1); + state[8] = load_le<u32bit>(iv, 2); + state[9] = load_le<u32bit>(iv, 3); + + SecureVector<u32bit> hsalsa(8); + hsalsa20(hsalsa, state); + + state[ 1] = hsalsa[0]; + state[ 2] = hsalsa[1]; + state[ 3] = hsalsa[2]; + state[ 4] = hsalsa[3]; + state[ 6] = load_le<u32bit>(iv, 4); + state[ 7] = load_le<u32bit>(iv, 5); + state[11] = hsalsa[4]; + state[12] = hsalsa[5]; + state[13] = hsalsa[6]; + state[14] = hsalsa[7]; + } + state[8] = 0; state[9] = 0; - salsa20(buffer.begin(), state); + salsa20(&buffer[0], state); ++state[8]; if(!state[8]) // if overflow in state[8] ++state[9]; // carry to state[9] @@ -205,12 +237,4 @@ void Salsa20::clear() position = 0; } -/* -* Salsa20 Constructor -*/ -Salsa20::Salsa20() : StreamCipher(16, 32, 16) - { - clear(); - } - } diff --git a/src/stream/salsa20/salsa20.h b/src/stream/salsa20/salsa20.h index 3ca781ea2..af7ddd145 100644 --- a/src/stream/salsa20/salsa20.h +++ b/src/stream/salsa20/salsa20.h @@ -1,6 +1,6 @@ /* -* Salsa20 -* (C) 1999-2008 Jack Lloyd +* Salsa20 / XSalsa20 +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -13,7 +13,7 @@ namespace Botan { /* -* Salsa20 +* Salsa20 (and XSalsa20) */ class BOTAN_DLL Salsa20 : public StreamCipher { @@ -23,19 +23,18 @@ class BOTAN_DLL Salsa20 : public StreamCipher void set_iv(const byte iv[], u32bit iv_len); bool valid_iv_length(u32bit iv_len) const - { return (iv_len == 8); } + { return (iv_len == 8 || iv_len == 24); } void clear(); std::string name() const; StreamCipher* clone() const { return new Salsa20; } - Salsa20(); + Salsa20() : StreamCipher(16, 32, 16) { position = 0; } ~Salsa20() { clear(); } private: void key_schedule(const byte key[], u32bit key_len); SecureBuffer<u32bit, 16> state; - SecureBuffer<byte, 64> buffer; u32bit position; }; diff --git a/src/utils/exceptn.h b/src/utils/exceptn.h index 39b18cb0b..2ac88aaf6 100644 --- a/src/utils/exceptn.h +++ b/src/utils/exceptn.h @@ -142,6 +142,15 @@ struct BOTAN_DLL Decoding_Error : public Invalid_Argument }; /* +* Integrity_Failure Exception +*/ +struct BOTAN_DLL Integrity_Failure : public Exception + { + Integrity_Failure(const std::string& what) : + Exception("Integrity failure: " + what) {} + }; + +/* * Invalid_OID Exception */ struct BOTAN_DLL Invalid_OID : public Decoding_Error diff --git a/src/utils/simd_32/simd_32.h b/src/utils/simd_32/simd_32.h index 4bd983f5e..23dce0305 100644 --- a/src/utils/simd_32/simd_32.h +++ b/src/utils/simd_32/simd_32.h @@ -29,16 +29,16 @@ namespace Botan { -inline SIMD_32 rotate_left(SIMD_32 x, u32bit rot) +inline SIMD_32 rotate_left(const SIMD_32& x, u32bit rot) { - x.rotate_left(rot); - return x; + SIMD_32 y = x; + y.rotate_left(rot); + return y; } -inline SIMD_32 rotate_right(SIMD_32 x, u32bit rot) +inline SIMD_32 rotate_right(const SIMD_32& x, u32bit rot) { - x.rotate_right(rot); - return x; + return rotate_left(x, 32 - rot); } } diff --git a/src/utils/time.cpp b/src/utils/time.cpp index 77ad0eec5..bc9aa8a2f 100644 --- a/src/utils/time.cpp +++ b/src/utils/time.cpp @@ -1,6 +1,6 @@ /** * Time Functions -* (C) 1999-2009 Jack Lloyd +* (C) 1999-2010 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -86,11 +86,13 @@ calendar_point calendar_value( u64bit get_nanoseconds_clock() { #if defined(BOTAN_TARGET_OS_HAS_CLOCK_GETTIME) + struct ::timespec tv; ::clock_gettime(CLOCK_REALTIME, &tv); return combine_timers(tv.tv_sec, tv.tv_nsec, 1000000000); #elif defined(BOTAN_TARGET_OS_HAS_GETTIMEOFDAY) + struct ::timeval tv; ::gettimeofday(&tv, 0); return combine_timers(tv.tv_sec, tv.tv_usec, 1000000); @@ -106,7 +108,9 @@ u64bit get_nanoseconds_clock() return (tstamp * 100); // Scale to 1 nanosecond units #else - return combine_timers(std::time(0), std::clock(), CLOCKS_PER_SEC); + + return combine_timers(static_cast<u32bit>(std::time(0)), + std::clock(), CLOCKS_PER_SEC); #endif } diff --git a/src/wrap/python/core.cpp b/src/wrap/python/core.cpp index fe26e16ee..b1be3b71f 100644 --- a/src/wrap/python/core.cpp +++ b/src/wrap/python/core.cpp @@ -166,10 +166,25 @@ std::string python_pbkdf2(const std::string& passphrase, { PKCS5_PBKDF2 pbkdf2(new HMAC(get_hash(hash_fn))); - pbkdf2.set_iterations(iterations); - pbkdf2.change_salt(reinterpret_cast<const byte*>(salt.data()), salt.size()); + return make_string( + pbkdf2.derive_key(output_size, + passphrase, + reinterpret_cast<const byte*>(salt.data()), + salt.size(), + iterations).bits_of()); + } + +std::string python_kdf2(const std::string& param, + const std::string& masterkey, + u32bit outputlength) + { + std::auto_ptr<KDF> kdf(get_kdf("KDF2(SHA-1)")); - return make_string(pbkdf2.derive_key(output_size, passphrase).bits_of()); + return make_string( + kdf->derive_key(outputlength, + reinterpret_cast<const byte*>(masterkey.data()), + masterkey.length(), + param)); } BOOST_PYTHON_MODULE(_botan) @@ -209,6 +224,7 @@ BOOST_PYTHON_MODULE(_botan) python::def("cryptobox_encrypt", cryptobox_encrypt); python::def("cryptobox_decrypt", cryptobox_decrypt); python::def("pbkdf2", python_pbkdf2); + python::def("derive_key", python_kdf2); export_filters(); export_rsa(); |