aboutsummaryrefslogtreecommitdiffstats
path: root/src/pubkey
diff options
context:
space:
mode:
authorlloyd <[email protected]>2010-03-09 00:50:46 +0000
committerlloyd <[email protected]>2010-03-09 00:50:46 +0000
commit8b21f20f0e479247b692d2795864ca2c190775c7 (patch)
treed2137e941ee06c7c54ea5a30429183f2a3f8dbd0 /src/pubkey
parentc029a2dc6afa08ad70ae464ef80c81397e19bf20 (diff)
Have PK_Signer check the validity of all signatures before releasing.
Should help against many forms of fault attacks.
Diffstat (limited to 'src/pubkey')
-rw-r--r--src/pubkey/pubkey.cpp54
-rw-r--r--src/pubkey/pubkey.h6
2 files changed, 52 insertions, 8 deletions
diff --git a/src/pubkey/pubkey.cpp b/src/pubkey/pubkey.cpp
index 5b6c7cd45..4a9f1be9d 100644
--- a/src/pubkey/pubkey.cpp
+++ b/src/pubkey/pubkey.cpp
@@ -33,7 +33,7 @@ PK_Encryptor_EME::PK_Encryptor_EME(const Public_Key& key,
break;
}
- if(op == 0)
+ if(!op)
throw Lookup_Error("PK_Encryptor_EME: No working engine for " +
key.algo_name());
@@ -86,7 +86,7 @@ PK_Decryptor_EME::PK_Decryptor_EME(const Private_Key& key,
break;
}
- if(op == 0)
+ if(!op)
throw Lookup_Error("PK_Decryptor_EME: No working engine for " +
key.algo_name());
@@ -121,14 +121,22 @@ PK_Signer::PK_Signer(const Private_Key& key,
{
Algorithm_Factory::Engine_Iterator i(global_state().algorithm_factory());
+ op = 0;
+ verify_op = 0;
+
while(const Engine* engine = i.next())
{
- op = engine->get_signature_op(key);
- if(op)
+ 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 == 0)
+ if(!op || !verify_op)
throw Lookup_Error("PK_Signer: No working engine for " +
key.algo_name());
@@ -155,6 +163,35 @@ void PK_Signer::update(const byte in[], u32bit length)
}
/*
+* Check the signature we just created, to help prevent fault attacks
+*/
+bool PK_Signer::self_test_signature(const MemoryRegion<byte>& msg,
+ const MemoryRegion<byte>& sig) const
+ {
+ if(verify_op->with_recovery())
+ {
+ SecureVector<byte> recovered =
+ verify_op->verify_mr(&sig[0], sig.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());
+ }
+
+/*
* Create a signature
*/
SecureVector<byte> PK_Signer::signature(RandomNumberGenerator& rng)
@@ -165,6 +202,9 @@ SecureVector<byte> PK_Signer::signature(RandomNumberGenerator& rng)
SecureVector<byte> plain_sig = op->sign(encoded, encoded.size(), rng);
+ 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;
@@ -205,7 +245,7 @@ PK_Verifier::PK_Verifier(const Public_Key& key,
break;
}
- if(op == 0)
+ if(!op)
throw Lookup_Error("PK_Verifier: No working engine for " +
key.algo_name());
@@ -315,7 +355,7 @@ PK_Key_Agreement::PK_Key_Agreement(const PK_Key_Agreement_Key& key,
break;
}
- if(op == 0)
+ if(!op)
throw Lookup_Error("PK_Key_Agreement: No working engine for " +
key.algo_name());
diff --git a/src/pubkey/pubkey.h b/src/pubkey/pubkey.h
index a262b51fe..d8964e1e7 100644
--- a/src/pubkey/pubkey.h
+++ b/src/pubkey/pubkey.h
@@ -179,12 +179,16 @@ class BOTAN_DLL PK_Signer
const std::string& emsa,
Signature_Format format = IEEE_1363);
- ~PK_Signer() { delete op; delete emsa; }
+ ~PK_Signer() { delete op; delete verify_op; delete emsa; }
private:
+ bool self_test_signature(const MemoryRegion<byte>& msg,
+ const MemoryRegion<byte>& sig) const;
+
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;
};