]> granicus.if.org Git - pdns/commitdiff
add signature verification infrastructure for RSA & GOST, test with 'pdnssec verify...
authorBert Hubert <bert.hubert@netherlabs.nl>
Thu, 27 Jan 2011 10:31:27 +0000 (10:31 +0000)
committerBert Hubert <bert.hubert@netherlabs.nl>
Thu, 27 Jan 2011 10:31:27 +0000 (10:31 +0000)
git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@1915 d19b8d6e-7fed-0310-83ef-9ca221ded41b

pdns/botan19signers.cc
pdns/dnssecinfra.cc
pdns/dnssecinfra.hh
pdns/pdnssec.cc
pdns/polarrsakeyinfra.cc

index 7b22d05af079a6a13718f438cdcbd7ccf04d2ff9..26bf7225aeddd71ba1ab6e6c31122f2e882da111 100644 (file)
@@ -33,6 +33,7 @@ public:
   std::string getPublicKeyString() const;
   int getBits() const;
   void fromISCString(DNSKEYRecordContent& drc, const std::string& content);
+  void fromPublicKeyString(unsigned int algorithm, const std::string& content);
   void fromPEMString(DNSKEYRecordContent& drc, const std::string& raw)
   {}
 
@@ -43,6 +44,7 @@ public:
 
 private:
   shared_ptr<GOST_3410_PrivateKey> d_key;
+  shared_ptr<GOST_3410_PublicKey> d_pubkey;
 };
 
 /*
@@ -142,6 +144,31 @@ void GOSTDNSPrivateKey::fromISCString(DNSKEYRecordContent& drc, const std::strin
   SecureVector<byte> buffer=BigInt::encode(x);
  // cerr<<"And out again! "<<makeHexDump(string((const char*)buffer.begin(), (const char*)buffer.end()))<<endl;
 }
+namespace {
+
+BigInt decode_le(const byte msg[], size_t msg_len)
+   {
+   SecureVector<byte> msg_le(msg, msg_len);
+
+   for(size_t i = 0; i != msg_le.size() / 2; ++i)
+      std::swap(msg_le[i], msg_le[msg_le.size()-1-i]);
+
+   return BigInt(&msg_le[0], msg_le.size());
+   }
+
+}
+void GOSTDNSPrivateKey::fromPublicKeyString(unsigned int algorithm, const std::string& input)
+{
+  BigInt x, y;
+  
+  x=decode_le((const byte*)input.c_str(), input.length()/2);
+  y=decode_le((const byte*)input.c_str() + input.length()/2, input.length()/2);
+
+  EC_Domain_Params params("1.2.643.2.2.35.1");
+  PointGFp point(params.get_curve(), x,y);
+  d_pubkey = shared_ptr<GOST_3410_PublicKey>(new GOST_3410_PublicKey(params, point));
+
+}
 
 std::string GOSTDNSPrivateKey::getPubKeyHash() const
 {
@@ -194,13 +221,26 @@ std::string GOSTDNSPrivateKey::hash(const std::string& orig) const
   
   GOST_34_11 hasher;
   result= hasher.process(orig);
-  
   return string((const char*)result.begin(), (const char*) result.end());
 }
 
+
 bool GOSTDNSPrivateKey::verify(const std::string& hash, const std::string& signature) const
 {
-  GOST_3410_Verification_Operation ops(*d_key);
+  GOST_3410_PublicKey* pk;
+  if(d_pubkey) {
+    cerr<<"Worked from the public key"<<endl;
+    pk =d_pubkey.get();
+  }
+  else
+    pk = d_key.get();
+    
+  GOST_3410_Verification_Operation ops(*pk);
+  /* 
+  string rhash(hash);
+  for(string::size_type pos = 0 ; pos < rhash.size()/2; ++pos)
+    swap(rhash[pos], rhash[rhash.size()-1-pos]);
+  */
   return ops.verify ((byte*)hash.c_str(), hash.length(), (byte*)signature.c_str(), signature.length());
 }
 
@@ -226,6 +266,7 @@ public:
   std::string getPublicKeyString() const;
   int getBits() const;
   void fromISCString(DNSKEYRecordContent& drc, const std::string& content);
+  //void fromPublicKeyString(const std::string& content);
   void fromPEMString(DNSKEYRecordContent& drc, const std::string& raw)
   {}
 
index 74696072467074465f2edae202ea98ca2c58759d..859d6e0f244a465e85b45319f390960a69864eb0 100644 (file)
@@ -70,6 +70,13 @@ DNSPrivateKey* DNSPrivateKey::makeFromISCString(DNSKEYRecordContent& drc, const
   return dpk;
 }
 
+DNSPrivateKey* DNSPrivateKey::makeFromPublicKeyString(unsigned int algorithm, const std::string& content)
+{
+  DNSPrivateKey* dpk=make(algorithm);
+  dpk->fromPublicKeyString(algorithm, content);
+  return dpk;
+}
+
 
 DNSPrivateKey* DNSPrivateKey::makeFromPEMString(DNSKEYRecordContent& drc, const std::string& raw)
 {
index 4ff91296eb9cedb15a5bfb396aa7ee5c44a3daeb..6135dc4170a769fed19825cec1e4de36d3ee418c 100644 (file)
@@ -15,15 +15,21 @@ class DNSPrivateKey
     virtual std::string getPubKeyHash()const =0;
     virtual std::string sign(const std::string& hash) const =0;
     virtual std::string hash(const std::string& hash) const =0;
+    virtual bool verify(const std::string& hash, const std::string& signature) const =0;
     virtual std::string getPublicKeyString()const =0;
     virtual int getBits() const =0;
     
     virtual void fromISCString(DNSKEYRecordContent& drc, const std::string& content)=0;
     virtual void fromPEMString(DNSKEYRecordContent& drc, const std::string& raw)=0;
+    virtual void fromPublicKeyString(unsigned algorithm, const std::string& content)
+    {
+      throw std::runtime_error("Can't import from public key string");
+    }
     
     static DNSPrivateKey* makeFromISCFile(DNSKEYRecordContent& drc, const char* fname);
     static DNSPrivateKey* makeFromISCString(DNSKEYRecordContent& drc, const std::string& content);
     static DNSPrivateKey* makeFromPEMString(DNSKEYRecordContent& drc, const std::string& raw);
+    static DNSPrivateKey* makeFromPublicKeyString(unsigned int algorithm, const std::string& raw);
     static DNSPrivateKey* make(unsigned int algorithm);
     
     typedef DNSPrivateKey* maker_t(unsigned int algorithm);
index cf2b8e5278b8056afc9a7664aa17ee56e5b99eaf..cc67d00445418251c7485153e3a3c342a023c4ac 100644 (file)
@@ -9,7 +9,7 @@
 #include "ueberbackend.hh"
 #include "arguments.hh"
 #include "packetcache.hh"
-
+#include "zoneparser-tng.hh"
 StatBag S;
 PacketCache PC;
 
@@ -176,6 +176,36 @@ void checkZone(DNSSECKeeper& dk, const std::string& zone)
   cerr<<"Checked "<<numrecords<<" records, "<<numerrors<<" errors"<<endl;
 }
 
+void verifyCrypto(const string& zone)
+{
+  ZoneParserTNG zpt(zone);
+  DNSResourceRecord rr;
+  DNSKEYRecordContent drc;
+  RRSIGRecordContent rrc;
+  vector<shared_ptr<DNSRecordContent> > toSign;
+  unsigned int ttl;
+  string qname;
+  
+  while(zpt.get(rr)) {
+    if(rr.qtype.getCode() == QType::DNSKEY) {
+      cerr<<"got DNSKEY!"<<endl;
+      drc = *dynamic_cast<DNSKEYRecordContent*>(DNSRecordContent::mastermake(QType::DNSKEY, 1, rr.content));
+    }
+    else if(rr.qtype.getCode() == QType::RRSIG) {
+      cerr<<"got RRSIG"<<endl;
+      rrc = *dynamic_cast<RRSIGRecordContent*>(DNSRecordContent::mastermake(QType::RRSIG, 1, rr.content));
+    }
+    else {
+      qname = rr.qname;
+      ttl = rr.ttl;
+      toSign.push_back(shared_ptr<DNSRecordContent>(DNSRecordContent::mastermake(rr.qtype.getCode(), 1, rr.content)));
+    }
+  }
+  DNSPrivateKey* dpk = DNSPrivateKey::makeFromPublicKeyString(drc.d_algorithm, drc.d_key);
+  string hash = getHashForRRSET(qname, rrc, toSign);        
+  cerr<<"Verify: "<<dpk->verify(hash, rrc.d_signature)<<endl;
+}
+
 void showZone(DNSSECKeeper& dk, const std::string& zone)
 {
   if(!dk.isSecuredZone(zone)) {
@@ -202,7 +232,7 @@ void showZone(DNSSECKeeper& dk, const std::string& zone)
     cout << "keys: "<<endl;
     BOOST_FOREACH(DNSSECKeeper::keyset_t::value_type value, keyset) {
       cout<<"ID = "<<value.second.id<<" ("<<(value.second.keyOrZone ? "KSK" : "ZSK")<<"), tag = "<<value.first.getDNSKEY().getTag();
-      cout<<", algo = "<<(int)value.first.d_algorithm<<", bits = "<<value.first.getKey()->getBits()<<"\tActive: "<<value.second.active<< endl; // humanTime(value.second.beginValidity)<<" - "<<humanTime(value.second.endValidity)<<endl;
+      cout<<", algo = "<<(int)value.first.d_algorithm<<", bits = "<<value.first.getKey()->getBits()<<"\tActive: "<<value.second.active<< endl; 
       if(value.second.keyOrZone) {
         cout<<"KSK DNSKEY = "<<zone<<" IN DNSKEY "<< value.first.getDNSKEY().getZoneRepresentation() << endl;
         cout<<"DS = "<<zone<<" IN DS "<<makeDSFromDNSKey(zone, value.first.getDNSKEY(), 1).getZoneRepresentation() << endl;
@@ -278,6 +308,13 @@ try
     }
     checkZone(dk, cmds[1]);
   }
+  else if(cmds[0] == "verify-crypto") {
+    if(cmds.size() != 2) {
+      cerr << "Error: "<<cmds[0]<<" takes exactly 1 parameter"<<endl;
+      return 0;
+    }
+    verifyCrypto(cmds[1]);
+  }
 
   else if(cmds[0] == "show-zone") {
     if(cmds.size() != 2) {
index f204ed53212874b7b095ca7f14b761a405125b6c..38a4fb7920b045b8123a0726e860035765fdd4c8 100644 (file)
@@ -86,6 +86,7 @@ public:
   std::string getPubKeyHash() const;
   std::string sign(const std::string& hash) const; 
   std::string hash(const std::string& hash) const; 
+  bool verify(const std::string& hash, const std::string& signature) const;
   std::string getPublicKeyString() const;
   int getBits() const
   {
@@ -93,7 +94,7 @@ public:
   }
   void fromISCString(DNSKEYRecordContent& drc, const std::string& content);
   void fromPEMString(DNSKEYRecordContent& drc, const std::string& raw);
-
+  void fromPublicKeyString(unsigned int algorithm, const std::string& raw);
   static DNSPrivateKey* maker(unsigned int algorithm)
   {
     return new RSADNSPrivateKey(algorithm);
@@ -166,6 +167,25 @@ std::string RSADNSPrivateKey::sign(const std::string& hash) const
   return string((char*) signature, sizeof(signature));
 }
 
+bool RSADNSPrivateKey::verify(const std::string& hash, const std::string& signature) const
+{
+  int hashKind;
+  if(hash.size()==20)
+    hashKind= SIG_RSA_SHA1;
+  else if(hash.size()==32) 
+    hashKind= SIG_RSA_SHA256;
+  else
+    hashKind = SIG_RSA_SHA512;
+  
+  int ret=rsa_pkcs1_verify(const_cast<rsa_context*>(&d_context), RSA_PUBLIC, 
+    hashKind,
+    hash.size(),
+    (const unsigned char*) hash.c_str(), (unsigned char*) signature.c_str());
+  cerr<<"verification returned: "<<ret<<endl;
+  return ret==0; // 0 really IS ok ;-)
+}
+
+
 std::string RSADNSPrivateKey::hash(const std::string& toHash) const
 {
   if(d_algorithm <= 7 ) {  // RSASHA1
@@ -332,16 +352,25 @@ void RSADNSPrivateKey::fromPEMString(DNSKEYRecordContent& drc, const std::string
   drc.d_key.append(modulus);
   drc.d_protocol=3;
 }
-#if 0
-void makeRSAPublicKeyFromDNS(rsa_context* rc, const DNSKEYRecordContent& dkrc)
-{
-  rsa_init(rc, RSA_PKCS_V15, 0, NULL, NULL );
 
-  mpi_read_binary(&rc->E, (unsigned char*)dkrc.getExponent().c_str(), dkrc.getExponent().length());    // exponent
-  mpi_read_binary(&rc->N, (unsigned char*)dkrc.getModulus().c_str(), dkrc.getModulus().length());    // modulus
-  rc->len = ( mpi_msb( &rc->N ) + 7 ) >> 3; // no clue what this does
+void RSADNSPrivateKey::fromPublicKeyString(unsigned int algorithm, const std::string& rawString)
+{
+  rsa_init(&d_context, RSA_PKCS_V15, 0, NULL, NULL );
+  string exponent, modulus;
+  const unsigned char* raw = (const unsigned char*)rawString.c_str();
+  
+  if(raw[0] != 0) {
+    exponent=rawString.substr(1, raw[0]);
+    modulus=rawString.substr(raw[0]+1);
+  } else {
+    exponent=rawString.substr(3, raw[1]*0xff + raw[2]);
+    modulus = rawString.substr(3+ raw[1]*0xff + raw[2]);
+  }
+  mpi_read_binary(&d_context.E, (unsigned char*)exponent.c_str(), exponent.length());   
+  mpi_read_binary(&d_context.N, (unsigned char*)modulus.c_str(), modulus.length());    
+  d_context.len = ( mpi_msb( &d_context.N ) + 7 ) >> 3; // no clue what this does
 }
-#endif
+
 string RSADNSPrivateKey::getPublicKeyString()  const
 {
   string keystring;