aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/asn1/asn1_oid.cpp10
-rw-r--r--src/build-data/buildh.in1
-rw-r--r--src/build-data/cc/gcc.txt2
-rw-r--r--src/build-data/cc/msvc.txt2
-rw-r--r--src/build-data/makefile/nmake.in8
-rw-r--r--src/build-data/makefile/python.in8
-rw-r--r--src/cert/cvc/cvc_ado.cpp10
-rw-r--r--src/cert/cvc/cvc_ado.h5
-rw-r--r--src/cert/cvc/cvc_ca.cpp44
-rw-r--r--src/cert/cvc/cvc_ca.h51
-rw-r--r--src/cert/cvc/cvc_cert.cpp65
-rw-r--r--src/cert/cvc/cvc_cert.h37
-rw-r--r--src/cert/cvc/cvc_gen_cert.h27
-rw-r--r--src/cert/cvc/cvc_key.h53
-rw-r--r--src/cert/cvc/cvc_req.cpp18
-rw-r--r--src/cert/cvc/cvc_req.h5
-rw-r--r--src/cert/cvc/cvc_self.cpp194
-rw-r--r--src/cert/cvc/eac_asn_obj.h5
-rw-r--r--src/cert/cvc/eac_obj.h112
-rw-r--r--src/cert/cvc/ecdsa_sig.cpp50
-rw-r--r--src/cert/cvc/ecdsa_sig.h62
-rw-r--r--src/cert/cvc/info.txt4
-rw-r--r--src/cert/cvc/signed_obj.cpp41
-rw-r--r--src/cert/cvc/signed_obj.h3
-rw-r--r--src/cert/x509/info.txt1
-rw-r--r--src/cert/x509/x509_ca.cpp18
-rw-r--r--src/cert/x509/x509_obj.cpp21
-rw-r--r--src/cert/x509/x509self.cpp5
-rw-r--r--src/cert/x509/x509stor.cpp22
-rw-r--r--src/cms/cms_dalg.cpp1
-rw-r--r--src/cms/cms_ealg.cpp30
-rw-r--r--src/cms/cms_enc.h2
-rw-r--r--src/cms/info.txt2
-rw-r--r--src/engine/def_engine/def_pk_ops.cpp179
-rw-r--r--src/engine/def_engine/default_engine.h28
-rw-r--r--src/engine/engine.h76
-rw-r--r--src/engine/gnump/gmp_dh.cpp53
-rw-r--r--src/engine/gnump/gmp_dsa.cpp124
-rw-r--r--src/engine/gnump/gmp_elg.cpp92
-rw-r--r--src/engine/gnump/gmp_if.cpp81
-rw-r--r--src/engine/gnump/gmp_nr.cpp107
-rw-r--r--src/engine/gnump/gmp_wrap.h3
-rw-r--r--src/engine/gnump/gnump_engine.h26
-rw-r--r--src/engine/gnump/gnump_pk.cpp350
-rw-r--r--src/engine/gnump/info.txt6
-rw-r--r--src/engine/info.txt1
-rw-r--r--src/engine/openssl/bn_wrap.h3
-rw-r--r--src/engine/openssl/info.txt6
-rw-r--r--src/engine/openssl/openssl_engine.h26
-rw-r--r--src/engine/openssl/openssl_pk.cpp345
-rw-r--r--src/engine/openssl/ossl_dh.cpp60
-rw-r--r--src/engine/openssl/ossl_dsa.cpp126
-rw-r--r--src/engine/openssl/ossl_elg.cpp95
-rw-r--r--src/engine/openssl/ossl_if.cpp85
-rw-r--r--src/engine/openssl/ossl_nr.cpp113
-rw-r--r--src/hash/gost_3411/gost_3411.cpp18
-rw-r--r--src/libstate/info.txt6
-rw-r--r--src/libstate/look_pk.cpp76
-rw-r--r--src/libstate/look_pk.h66
-rw-r--r--src/libstate/oid_lookup/oids.cpp2
-rw-r--r--src/libstate/pk_engine.cpp133
-rw-r--r--src/libstate/pk_engine.h73
-rw-r--r--src/libstate/policy.cpp130
-rw-r--r--src/math/numbertheory/blinding.cpp49
-rw-r--r--src/math/numbertheory/blinding.h34
-rw-r--r--src/math/numbertheory/info.txt2
-rw-r--r--src/math/numbertheory/make_prm.cpp3
-rw-r--r--src/math/numbertheory/point_gfp.cpp29
-rw-r--r--src/math/numbertheory/point_gfp.h7
-rw-r--r--src/math/numbertheory/pow_mod.cpp53
-rw-r--r--src/math/numbertheory/pow_mod.h7
-rw-r--r--src/math/numbertheory/powm_fw.cpp40
-rw-r--r--src/math/numbertheory/powm_mnt.cpp34
-rw-r--r--src/math/numbertheory/reducer.h2
-rw-r--r--src/pubkey/blinding.cpp76
-rw-r--r--src/pubkey/blinding.h53
-rw-r--r--src/pubkey/dh/dh.cpp69
-rw-r--r--src/pubkey/dh/dh.h49
-rw-r--r--src/pubkey/dh/dh_core.cpp65
-rw-r--r--src/pubkey/dh/dh_core.h38
-rw-r--r--src/pubkey/dh/dh_op.h45
-rw-r--r--src/pubkey/dh/info.txt3
-rw-r--r--src/pubkey/dl_algo/dl_algo.cpp128
-rw-r--r--src/pubkey/dl_algo/dl_algo.h41
-rw-r--r--src/pubkey/dl_algo/info.txt1
-rw-r--r--src/pubkey/dlies/dlies.cpp44
-rw-r--r--src/pubkey/dlies/dlies.h7
-rw-r--r--src/pubkey/dsa/dsa.cpp143
-rw-r--r--src/pubkey/dsa/dsa.h79
-rw-r--r--src/pubkey/dsa/dsa_core.cpp63
-rw-r--r--src/pubkey/dsa/dsa_core.h37
-rw-r--r--src/pubkey/dsa/dsa_op.cpp85
-rw-r--r--src/pubkey/dsa/dsa_op.h59
-rw-r--r--src/pubkey/dsa/info.txt12
-rw-r--r--src/pubkey/ec_dompar/ec_dompar.cpp4
-rw-r--r--src/pubkey/ecc_key/ecc_key.cpp179
-rw-r--r--src/pubkey/ecc_key/ecc_key.h58
-rw-r--r--src/pubkey/ecc_key/info.txt1
-rw-r--r--src/pubkey/ecdh/ecdh.cpp36
-rw-r--r--src/pubkey/ecdh/ecdh.h50
-rw-r--r--src/pubkey/ecdsa/ecdsa.cpp81
-rw-r--r--src/pubkey/ecdsa/ecdsa.h97
-rw-r--r--src/pubkey/elgamal/elg_core.cpp93
-rw-r--r--src/pubkey/elgamal/elg_core.h44
-rw-r--r--src/pubkey/elgamal/elg_op.cpp58
-rw-r--r--src/pubkey/elgamal/elg_op.h52
-rw-r--r--src/pubkey/elgamal/elgamal.cpp132
-rw-r--r--src/pubkey/elgamal/elgamal.h66
-rw-r--r--src/pubkey/gost_3410/gost_3410.cpp196
-rw-r--r--src/pubkey/gost_3410/gost_3410.h118
-rw-r--r--src/pubkey/if_algo/if_algo.cpp229
-rw-r--r--src/pubkey/if_algo/if_algo.h40
-rw-r--r--src/pubkey/if_algo/if_core.cpp83
-rw-r--r--src/pubkey/if_algo/if_core.h45
-rw-r--r--src/pubkey/if_algo/if_op.cpp50
-rw-r--r--src/pubkey/if_algo/if_op.h52
-rw-r--r--src/pubkey/if_algo/info.txt13
-rw-r--r--src/pubkey/info.txt11
-rw-r--r--src/pubkey/keypair/keypair.cpp30
-rw-r--r--src/pubkey/keypair/keypair.h8
-rw-r--r--src/pubkey/nr/nr.cpp148
-rw-r--r--src/pubkey/nr/nr.h77
-rw-r--r--src/pubkey/nr/nr_core.cpp62
-rw-r--r--src/pubkey/nr/nr_core.h37
-rw-r--r--src/pubkey/nr/nr_op.cpp75
-rw-r--r--src/pubkey/nr/nr_op.h53
-rw-r--r--src/pubkey/pk_algs.cpp88
-rw-r--r--src/pubkey/pk_algs.h19
-rw-r--r--src/pubkey/pk_codecs/info.txt7
-rw-r--r--src/pubkey/pk_keys.h84
-rw-r--r--src/pubkey/pk_ops.h151
-rw-r--r--src/pubkey/pkcs8.cpp (renamed from src/pubkey/pk_codecs/pkcs8.cpp)26
-rw-r--r--src/pubkey/pkcs8.h (renamed from src/pubkey/pk_codecs/pkcs8.h)43
-rw-r--r--src/pubkey/pubkey.cpp338
-rw-r--r--src/pubkey/pubkey.h265
-rw-r--r--src/pubkey/rsa/rsa.cpp167
-rw-r--r--src/pubkey/rsa/rsa.h110
-rw-r--r--src/pubkey/rw/rw.cpp159
-rw-r--r--src/pubkey/rw/rw.h72
-rw-r--r--src/pubkey/x509_key.cpp (renamed from src/pubkey/pk_codecs/x509_key.cpp)44
-rw-r--r--src/pubkey/x509_key.h (renamed from src/pubkey/pk_codecs/x509_key.h)26
-rw-r--r--src/ssl/c_kex.cpp44
-rw-r--r--src/ssl/cert_ver.cpp68
-rw-r--r--src/ssl/s_kex.cpp81
-rw-r--r--src/stream/salsa20/salsa20.cpp154
-rw-r--r--src/stream/salsa20/salsa20.h11
-rw-r--r--src/utils/exceptn.h9
-rw-r--r--src/utils/simd_32/simd_32.h12
-rw-r--r--src/utils/time.cpp8
-rw-r--r--src/wrap/python/core.cpp22
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();