]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
- scary commit -
authorBert Hubert <bert.hubert@netherlabs.nl>
Mon, 31 Jan 2011 21:59:45 +0000 (21:59 +0000)
committerBert Hubert <bert.hubert@netherlabs.nl>
Mon, 31 Jan 2011 21:59:45 +0000 (21:59 +0000)
add a generic botan1.8/botan1.9 signer/verifier for RSA
refactor the signer/verifier API so the more code moves out of the per-engine interface
add the ability to have multiple enginers for a single algorithm, plus add the notion of a 'fallback' engine, in our case polarssl
update some copyright statements

git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@1951 d19b8d6e-7fed-0310-83ef-9ca221ded41b

pdns/Makefile.am
pdns/botan18signers.cc
pdns/botan19signers.cc
pdns/botansigners.cc [new file with mode: 0644]
pdns/communicator.cc
pdns/dnssecinfra.cc
pdns/dnssecinfra.hh
pdns/dnssecsigner.cc
pdns/mastercommunicator.cc
pdns/pdnssec.cc
pdns/polarrsakeyinfra.cc

index 1e0f2ad5bab3d86c89487d3c32bc761538245b3c..29fe6e5e70febf7a1d3f1bea76220f6b827911cd 100644 (file)
@@ -47,12 +47,12 @@ pdns_server_LDFLAGS=@moduleobjects@ @modulelibs@ @DYNLINKFLAGS@ @LIBDL@ @THREADF
 pdns_server_LDADD= -lpolarssl
 
 if BOTAN19
-pdns_server_SOURCES += botan19signers.cc
+pdns_server_SOURCES += botan19signers.cc botansigners.cc
 pdns_server_LDADD += -lbotan -lgmp
 endif
 
 if BOTAN18
-pdns_server_SOURCES += botan18signers.cc
+pdns_server_SOURCES += botan18signers.cc botansigners.cc
 pdns_server_LDADD += -lbotan -lgmp
 endif
 
@@ -71,12 +71,12 @@ pdnssec_LDFLAGS=@moduleobjects@ @modulelibs@ @DYNLINKFLAGS@ @LIBDL@ @THREADFLAGS
 pdnssec_LDADD= -lpolarssl $(BOOST_PROGRAM_OPTIONS_LIBS)
 
 if BOTAN19
-pdnssec_SOURCES += botan19signers.cc
+pdnssec_SOURCES += botan19signers.cc botansigners.cc
 pdnssec_LDADD += -lbotan -lgmp
 endif
 
 if BOTAN18
-pdnssec_SOURCES += botan18signers.cc
+pdnssec_SOURCES += botan18signers.cc botansigners.cc
 pdnssec_LDADD += -lbotan -lgmp
 endif
 
index c250990c8c6064fbd1efa26aae2479444e1db050..55aec7341d1b95e22cd6e75674cb29be9f54d992 100644 (file)
@@ -10,8 +10,6 @@
 
 using namespace Botan;
 
-//////////////////////////////
-
 class ECDSADNSPrivateKey : public DNSPrivateKey
 {
 public:
@@ -22,10 +20,10 @@ 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;
+  bool verify(const std::string& msg, const std::string& signature) const;
   std::string getPublicKeyString() const;
   int getBits() const;
-  void fromISCString(DNSKEYRecordContent& drc, const std::string& content);
+  void fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap);
   void fromPublicKeyString(unsigned int algorithm, const std::string& content);
   void fromPEMString(DNSKEYRecordContent& drc, const std::string& raw)
   {}
@@ -60,7 +58,6 @@ void ECDSADNSPrivateKey::create(unsigned int bits)
   }
   d_key = shared_ptr<ECDSA_PrivateKey>(new ECDSA_PrivateKey(rng, getECParams((bits == 256) ? 13 : 14)));
   
-  
   PKCS8_Encoder* pk8e= d_key->pkcs8_encoder();
   MemoryVector<byte> getbits=pk8e->key_bits();
   cerr<<makeHexDump(string((char*)&*getbits.begin(), (char*)&*getbits.end()))<<endl;
@@ -105,29 +102,15 @@ std::string ECDSADNSPrivateKey::convertToISC(unsigned int algorithm) const
   return ret.str();
 }
 
-void ECDSADNSPrivateKey::fromISCString(DNSKEYRecordContent& drc, const std::string& content )
+void ECDSADNSPrivateKey::fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap )
 {
   /*Private-key-format: v1.2
    Algorithm: 13 (ECDSAP256SHA256)
    PrivateKey: GU6SnQ/Ou+xC5RumuIUIuJZteXT2z0O/ok1s38Et6mQ= */
+     
+  d_algorithm = drc.d_algorithm = atoi(stormap["algorithm"].c_str());
+  string privateKey = stormap["privatekey"];
   
-  istringstream input(content);
-  string sline, key, value, privateKey;
-  while(getline(input, sline)) {
-    tie(key,value)=splitField(sline, ':');
-    trim(value);
-    if(pdns_iequals(key,"Private-key-format")) {}
-    else if(key=="Algorithm")
-      drc.d_algorithm = atoi(value.c_str());
-    else if(key=="PrivateKey") {
-      Pipe pipe(new Base64_Decoder);
-      pipe.process_msg(value);
-      privateKey=pipe.read_all_as_string();
-    }
-    else
-      throw runtime_error("Unknown field '"+key+"' in Private Key Representation of ECDSA");
-  }
-  d_algorithm = drc.d_algorithm;
   BigInt bigint((byte*)privateKey.c_str(), privateKey.length());
   
   EC_Domain_Params params=getECParams(drc.d_algorithm);
@@ -149,9 +132,7 @@ void ECDSADNSPrivateKey::fromISCString(DNSKEYRecordContent& drc, const std::stri
   noIdea.append(privateKey);
   
   MemoryVector<byte> tmp((byte*)noIdea.c_str(), noIdea.length());
-  cerr<<"key_bits"<<endl;
   p8e->key_bits(tmp);
-  cerr<<"Done reading"<<endl;
   delete p8e;
 }
 
@@ -192,10 +173,10 @@ void ECDSADNSPrivateKey::fromPublicKeyString(unsigned int algorithm, const std::
   d_key.reset();
 }
 
-
-std::string ECDSADNSPrivateKey::sign(const std::string& hash) const
+std::string ECDSADNSPrivateKey::sign(const std::string& msg) const
 {
   AutoSeeded_RNG rng;
+  string hash = this->hash(msg);
   SecureVector<byte> signature=d_key->sign((byte*)hash.c_str(), hash.length(), rng);
   
   return string((const char*)signature.begin(), (const char*) signature.end());
@@ -216,18 +197,12 @@ std::string ECDSADNSPrivateKey::hash(const std::string& orig) const
   return string((const char*)result.begin(), (const char*) result.end());
 }
 
-
-bool ECDSADNSPrivateKey::verify(const std::string& hash, const std::string& signature) const
+bool ECDSADNSPrivateKey::verify(const std::string& msg, const std::string& signature) const
 {
-  ECDSA_PublicKey* key;
-  if(d_key)
-    key = d_key.get();
-  else
-    key = d_pubkey.get();
-    
+  string hash = this->hash(msg);
+  ECDSA_PublicKey* key = d_key ? d_key.get() : d_pubkey.get();
   return key->verify((byte*)hash.c_str(), hash.length(), (byte*)signature.c_str(), signature.length());
 }
-
 namespace {
 struct LoaderStruct
 {
index 7ce6ed8a8c5beebada3a3709b0d119a7ee147643..81b6aeafedbf2951e104f1ac967870e908650569 100644 (file)
@@ -32,7 +32,7 @@ public:
   bool verify(const std::string& hash, const std::string& signature) const;
   std::string getPublicKeyString() const;
   int getBits() const;
-  void fromISCString(DNSKEYRecordContent& drc, const std::string& content);
+  void fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& content);
   void fromPublicKeyString(unsigned int algorithm, const std::string& content);
   void fromPEMString(DNSKEYRecordContent& drc, const std::string& raw)
   {}
@@ -105,24 +105,10 @@ std::string GOSTDNSPrivateKey::convertToISC(unsigned int algorithm) const
 */
 
 
-void GOSTDNSPrivateKey::fromISCString(DNSKEYRecordContent& drc, const std::string& content )
+void GOSTDNSPrivateKey::fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap )
 { 
-  istringstream input(content);
-  string sline, key, value, privateKey;
-  while(getline(input, sline)) {
-    tie(key,value)=splitField(sline, ':');
-    trim(value);
-    if(pdns_iequals(key,"Private-key-format")) {}
-    else if(key=="Algorithm")
-      drc.d_algorithm = atoi(value.c_str());
-    else if(key=="GostAsn1") {
-      Pipe pipe(new Base64_Decoder);
-      pipe.process_msg(value);
-      privateKey=pipe.read_all_as_string();
-    }
-    else
-      throw runtime_error("Unknown field '"+key+"' in Private Key Representation of GOST");
-  }
+  drc.d_algorithm = atoi(stormap["algorithm"].c_str());
+  string privateKey=stormap["gostasn1"];
   //cerr<<"PrivateKey.size() = "<<privateKey.size()<<endl;
   //cerr<<makeHexDump(string(privateKey.c_str(), 39))<<endl;
   string rawKey(privateKey.c_str()+39, privateKey.length()-39);
@@ -206,10 +192,13 @@ std::string GOSTDNSPrivateKey::getPublicKeyString() const
  ~ Tak bylo, tak yest' i tak budet vsegda!     ~  
  */
 
-std::string GOSTDNSPrivateKey::sign(const std::string& hash) const
+std::string GOSTDNSPrivateKey::sign(const std::string& msg) const
 {
   GOST_3410_Signature_Operation ops(*d_key);
   AutoSeeded_RNG rng;
+  
+  string hash= this->hash(msg);
+  
   SecureVector<byte> signature=ops.sign((byte*)hash.c_str(), hash.length(), rng);
 
 #if BOTAN_VERSION_CODE <= BOTAN_VERSION_CODE_FOR(1,9,12)  // see http://bit.ly/gTytUf
@@ -231,8 +220,9 @@ std::string GOSTDNSPrivateKey::hash(const std::string& orig) const
 }
 
 
-bool GOSTDNSPrivateKey::verify(const std::string& hash, const std::string& signature) const
+bool GOSTDNSPrivateKey::verify(const std::string& message, const std::string& signature) const
 {
+  string hash = this->hash(message);
   GOST_3410_PublicKey* pk;
   if(d_pubkey) {
     pk =d_pubkey.get();
@@ -273,7 +263,7 @@ public:
   bool verify(const std::string& hash, const std::string& signature) const;
   std::string getPublicKeyString() const;
   int getBits() const;
-  void fromISCString(DNSKEYRecordContent& drc, const std::string& content);
+  void fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap);
   void fromPublicKeyString(unsigned int algorithm, const std::string& content);
   void fromPEMString(DNSKEYRecordContent& drc, const std::string& raw)
   {}
@@ -351,34 +341,20 @@ std::string ECDSADNSPrivateKey::convertToISC(unsigned int algorithm) const
   return ret.str();
 }
 
-void ECDSADNSPrivateKey::fromISCString(DNSKEYRecordContent& drc, const std::string& content )
+void ECDSADNSPrivateKey::fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap)
 {
   /*Private-key-format: v1.2
    Algorithm: 13 (ECDSAP256SHA256)
    PrivateKey: GU6SnQ/Ou+xC5RumuIUIuJZteXT2z0O/ok1s38Et6mQ= */
   
-  istringstream input(content);
-  string sline, key, value, privateKey;
-  while(getline(input, sline)) {
-    tie(key,value)=splitField(sline, ':');
-    trim(value);
-    if(pdns_iequals(key,"Private-key-format")) {}
-    else if(key=="Algorithm")
-      drc.d_algorithm = atoi(value.c_str());
-    else if(key=="PrivateKey") {
-      Pipe pipe(new Base64_Decoder);
-      pipe.process_msg(value);
-      privateKey=pipe.read_all_as_string();
-    }
-    else
-      throw runtime_error("Unknown field '"+key+"' in Private Key Representation of ECDSA");
-  }
+  drc.d_algorithm = atoi(stormap["algorithm"].c_str());
+  string privateKey=stormap["privatekey"];
+  
   d_algorithm = drc.d_algorithm;
   BigInt bigint((byte*)privateKey.c_str(), privateKey.length());
   
   EC_Domain_Params params=getECParams(drc.d_algorithm);
   d_key=shared_ptr<ECDSA_PrivateKey>(new ECDSA_PrivateKey(params, bigint));
-  
 }
 
 std::string ECDSADNSPrivateKey::getPubKeyHash() const
@@ -417,8 +393,9 @@ void ECDSADNSPrivateKey::fromPublicKeyString(unsigned int algorithm, const std::
 }
 
 
-std::string ECDSADNSPrivateKey::sign(const std::string& hash) const
+std::string ECDSADNSPrivateKey::sign(const std::string& msg) const
 {
+  string hash = this->hash(msg);
   ECDSA_Signature_Operation ops(*d_key);
   AutoSeeded_RNG rng;
   SecureVector<byte> signature=ops.sign((byte*)hash.c_str(), hash.length(), rng);
diff --git a/pdns/botansigners.cc b/pdns/botansigners.cc
new file mode 100644 (file)
index 0000000..452431a
--- /dev/null
@@ -0,0 +1,261 @@
+#include <botan/botan.h>
+#include <botan/sha160.h>
+#include <botan/sha2_32.h>
+#include <botan/sha2_64.h>
+#include <botan/emsa3.h>
+#include <botan/rsa.h>
+#include <botan/pubkey.h>
+#include <botan/look_pk.h>
+#include "dnssecinfra.hh"
+
+using namespace Botan;
+
+class BotanRSADNSPrivateKey : public DNSPrivateKey
+{
+public:
+  explicit BotanRSADNSPrivateKey(unsigned int algo) :d_algorithm(algo)
+  {}
+  void create(unsigned int bits);
+  std::string convertToISC(unsigned int algorithm) const;
+  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;
+  void fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap);
+  void fromPublicKeyString(unsigned int algorithm, const std::string& content);
+  void fromPEMString(DNSKEYRecordContent& drc, const std::string& raw)
+  {}
+
+  static DNSPrivateKey* maker(unsigned int algorithm)
+  {
+    return new BotanRSADNSPrivateKey(algorithm);
+  }
+
+private:
+  shared_ptr<RSA_PrivateKey> d_key;
+  shared_ptr<RSA_PublicKey> d_pubkey;
+  unsigned int d_algorithm;
+};
+
+void BotanRSADNSPrivateKey::create(unsigned int bits)
+{
+  AutoSeeded_RNG rng;
+  d_key = shared_ptr<RSA_PrivateKey>(new RSA_PrivateKey(rng, bits));
+}
+
+int BotanRSADNSPrivateKey::getBits() const
+{
+  return d_key->max_input_bits() + 1;
+}
+
+namespace {
+string asBase64(const BigInt& x)
+{
+  SecureVector<byte> buffer=BigInt::encode(x);
+  
+  Pipe pipe(new Base64_Encoder);
+  pipe.process_msg(buffer);
+  return pipe.read_all_as_string();
+}
+
+BigInt fromRaw(const std::string& raw)
+{
+  if(raw.empty())
+    throw runtime_error("Unable to decode empty value");
+  return BigInt::decode((byte*)raw.c_str(), raw.length());
+}
+}
+std::string BotanRSADNSPrivateKey::convertToISC(unsigned int algorithm) const
+{
+  ostringstream ret;
+  ret<<"Private-key-format: v1.2\nAlgorithm: "<<d_algorithm;
+  switch(algorithm) {
+    case 5:
+    case 7 :
+      ret << " (RSASHA1)\n";
+      break;
+    case 8:
+      ret << " (RSASHA256)\n";
+      break;
+    default:
+      ret <<" (?)\n";
+      break;
+  }
+  
+  ret<<"Modulus: " << asBase64(d_key->get_n())<<endl;
+  ret<<"PublicExponent: " << asBase64(d_key->get_e())<<endl;
+  ret<<"PrivateExponent: " << asBase64(d_key->get_d())<<endl;
+  ret<<"Prime1: " << asBase64(d_key->get_p())<<endl;
+  ret<<"Prime2: " << asBase64(d_key->get_q())<<endl;
+  
+#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,9,0)  
+  BigInt d1 = d_key->get_d() % (d_key->get_p() - 1);
+  BigInt d2 = d_key->get_d() % (d_key->get_q() - 1);
+#else
+  BigInt d1 = d_key->get_d1();
+  BigInt d2 = d_key->get_d2();
+#endif
+  ret<<"Exponent1: " << asBase64(d1)<<endl;
+  ret<<"Exponent2: " << asBase64(d2)<<endl;
+  ret<<"Coefficient: " << asBase64(d_key->get_q())<<endl;
+  return ret.str();
+}
+
+void BotanRSADNSPrivateKey::fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap )
+{
+  // wants p (Prime1), q (Prime2), d (PrivateExponent), e (PublicExponent) & n Modulus
+  BigInt n, e, d, p, q;
+  
+  p=fromRaw(stormap["prime1"]);
+  q=fromRaw(stormap["prime2"]);
+  d=fromRaw(stormap["privateexponent"]);
+  e=fromRaw(stormap["publicexponent"]);
+  n=fromRaw(stormap["modulus"]);
+  
+  d_algorithm = drc.d_algorithm = atoi(stormap["algorithm"].c_str());
+  AutoSeeded_RNG rng;
+  d_key = shared_ptr<RSA_PrivateKey>(new RSA_PrivateKey(rng, p, q, e, d, n));
+  d_pubkey.reset();
+}
+
+std::string BotanRSADNSPrivateKey::getPubKeyHash() const
+{
+  const BigInt& n = d_key->get_n();
+  const BigInt& e = d_key->get_e();
+  SecureVector<byte> buffer=BigInt::encode(n);
+  
+  SHA_160 hasher;
+  hasher.update(buffer);
+  buffer=BigInt::encode(e);
+  hasher.update(buffer);
+  SecureVector<byte> hash=hasher.final();
+  return string((const char*)hash.begin(), (const char*)hash.end());
+}
+
+std::string BotanRSADNSPrivateKey::getPublicKeyString() const
+{
+  MemoryVector<byte> bits = BigInt::encode(d_key->get_e());
+  string exponent(&*bits.begin(), &*bits.end());
+  bits = BigInt::encode(d_key->get_n());
+  string modulus(&*bits.begin(), &*bits.end());
+  
+  string keystring;
+  if(exponent.length() < 255) 
+    keystring.assign(1, (char) (unsigned int) exponent.length());
+  else {
+    keystring.assign(1, 0);
+    uint16_t len=htons(exponent.length());
+    keystring.append((char*)&len, 2);
+  }
+  keystring.append(exponent);
+  keystring.append(modulus);
+  return keystring;
+}
+
+void BotanRSADNSPrivateKey::fromPublicKeyString(unsigned int algorithm, const std::string& rawString) 
+{
+  d_algorithm = algorithm;
+  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]);
+  }
+  
+  BigInt e = BigInt::decode((const byte*)exponent.c_str(), exponent.length());
+  BigInt n = BigInt::decode((const byte*)modulus.c_str(), modulus.length());
+  
+  d_pubkey = shared_ptr<RSA_PublicKey>(new RSA_PublicKey(e,n));
+  d_key.reset();
+}
+
+std::string BotanRSADNSPrivateKey::sign(const std::string& msg) const
+{  
+#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,9,0)  
+  EMSA* emsaptr;
+  if(d_algorithm == 5 || d_algorithm ==7) 
+    emsaptr=new EMSA3(new SHA_160);
+  else if(d_algorithm==8)
+    emsaptr=new EMSA3(new SHA_256);
+  else 
+    emsaptr=new EMSA3(new SHA_512);
+  PK_Signer pks(*d_key, emsaptr);
+#else
+  string emsa;
+  if(d_algorithm == 5 || d_algorithm ==7)
+    emsa="EMSA3(SHA-160)";
+  else if(d_algorithm==8)
+    emsa="EMSA3(SHA-256)";
+  else 
+    emsa="EMSA3(SHA-512)";
+  PK_Signer pks(*d_key, emsa);
+#endif
+
+  AutoSeeded_RNG rng;
+  SecureVector<byte> signature= pks.sign_message((byte*)msg.c_str(), msg.length(), rng);
+  return string((const char*)signature.begin(), (const char*) signature.end());
+}
+
+std::string BotanRSADNSPrivateKey::hash(const std::string& orig) const
+{
+  SecureVector<byte> result;
+  if(d_algorithm == 5 || d_algorithm ==7 ) { // SHA160
+    SHA_160 hasher;
+    result= hasher.process(orig);
+  }
+  if(d_algorithm == 8) { // SHA256
+    SHA_256 hasher;
+    result= hasher.process(orig);
+  }
+  else if(d_algorithm==10) { // SHA512
+    SHA_512 hasher;
+    result = hasher.process(orig);
+  }
+  
+  return string((const char*)result.begin(), (const char*) result.end());
+}
+
+
+bool BotanRSADNSPrivateKey::verify(const std::string& msg, const std::string& signature) const
+{
+  RSA_PublicKey* key = d_key ? d_key.get() : d_pubkey.get();
+  
+  string emsa;
+  
+  if(d_algorithm == 5 || d_algorithm ==7)
+    emsa = "EMSA3(SHA-1)";
+  else if(d_algorithm==8)
+    emsa = "EMSA3(SHA-256)";
+  else 
+    emsa = "EMSA3(SHA-512)";
+    
+#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,9,0) 
+  std::auto_ptr<PK_Verifier> ver(get_pk_verifier(*key, emsa));
+  return ver->verify_message((byte*)msg.c_str(), msg.length(), (byte*)signature.c_str(), signature.length());
+#else
+  RSA_Public_Operation ops(*key);
+  return ops.verify((byte*)msg.c_str(), msg.length(), (byte*)signature.c_str(), signature.length());
+#endif
+}
+
+namespace {
+struct LoaderStruct
+{
+  LoaderStruct()
+  {
+    Botan::LibraryInitializer init;
+
+    DNSPrivateKey::report(5, &BotanRSADNSPrivateKey::maker);
+    DNSPrivateKey::report(7, &BotanRSADNSPrivateKey::maker);
+    DNSPrivateKey::report(8, &BotanRSADNSPrivateKey::maker);
+    DNSPrivateKey::report(10, &BotanRSADNSPrivateKey::maker);
+  }
+} loader;
+}
+
index e5f0dd0969218045c3d1e8d7363f67c67a8afafa..59adf0497397a43bbfd773a6cb33951d6c65abbe 100644 (file)
@@ -1,6 +1,6 @@
 /*
     PowerDNS Versatile Database Driven Nameserver
-    Copyright (C) 2002-2009  PowerDNS.COM BV
+    Copyright (C) 2002-2011  PowerDNS.COM BV
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License version 2 as 
index 11127900390b449436ac600230a642fcde8b138f..b0a95e6ebc3b9ac8e9f5fa083b8b6a6778b2e2b5 100644 (file)
@@ -12,6 +12,7 @@
 #include "polarssl/sha1.h"
 #include <boost/assign/std/vector.hpp> // for 'operator+=()'
 #include <boost/assign/list_inserter.hpp>
+#include "base64.hh"
 
 using namespace boost;
 using namespace std;
@@ -19,25 +20,45 @@ using namespace boost::assign;
 
 DNSPrivateKey* DNSPrivateKey::makeFromISCFile(DNSKEYRecordContent& drc, const char* fname)
 {
-  string sline, isc, key, value;
+  string sline, isc;
   FILE *fp=fopen(fname, "r");
   if(!fp) {
     throw runtime_error("Unable to read file '"+string(fname)+"' for generating DNS Private Key");
   }
-  int algorithm=0;
+  
   while(stringfgets(fp, sline)) {
-    tie(key,value)=splitField(sline, ':');
-    if(pdns_iequals(key,"algorithm"))
-      algorithm = atoi(value.c_str());
-    isc.append(sline);
+    isc += sline;
   }
   fclose(fp);
+  return makeFromISCString(drc, isc);
+}
 
+DNSPrivateKey* DNSPrivateKey::makeFromISCString(DNSKEYRecordContent& drc, const std::string& content)
+{
+  int algorithm = 0;
+  string sline, key, value, raw;
+  istringstream str(content);
+  map<string, string> stormap;
+  while(getline(str, sline)) {
+    tie(key,value)=splitField(sline, ':');
+    trim(value);
+    if(pdns_iequals(key,"algorithm")) {
+      algorithm = atoi(value.c_str());
+      stormap["algorithm"]=lexical_cast<string>(algorithm);
+      continue;
+    }
+    else if(pdns_iequals(key, "Private-key-format"))
+      continue;
+    raw.clear();
+    B64Decode(value, raw);
+    stormap[toLower(key)]=raw;
+  }
   DNSPrivateKey* dpk=make(algorithm);
-  dpk->fromISCString(drc, isc);
+  dpk->fromISCMap(drc, stormap);
   return dpk;
 }
 
+
 DNSPrivateKey* DNSPrivateKey::make(unsigned int algo)
 {
   makers_t& makers = getMakers();
@@ -49,25 +70,12 @@ DNSPrivateKey* DNSPrivateKey::make(unsigned int algo)
   }
 }
 
-void DNSPrivateKey::report(unsigned int algo, maker_t* maker)
+void DNSPrivateKey::report(unsigned int algo, maker_t* maker, bool fallback)
 {
-  getMakers()[algo]=maker;
-}
-DNSPrivateKey* DNSPrivateKey::makeFromISCString(DNSKEYRecordContent& drc, const std::string& content)
-{
-  int algorithm = 0;
-  string sline, key, value;
-  istringstream str(content);
-  while(getline(str, sline)) {
-    tie(key,value)=splitField(sline, ':');
-    if(pdns_iequals(key,"algorithm")) {
-      algorithm = atoi(value.c_str());
-      break;
-    }
+  if(getMakers().count(algo) && fallback) {
+    return;
   }
-  DNSPrivateKey* dpk=make(algorithm);
-  dpk->fromISCString(drc, content);
-  return dpk;
+  getMakers()[algo]=maker;
 }
 
 DNSPrivateKey* DNSPrivateKey::makeFromPublicKeyString(unsigned int algorithm, const std::string& content)
@@ -103,7 +111,7 @@ bool sharedDNSSECCompare(const shared_ptr<DNSRecordContent>& a, const shared_ptr
   return a->serialize("", true, true) < b->serialize("", true, true);
 }
 
-string getHashForRRSET(const std::string& qname, const RRSIGRecordContent& rrc, vector<shared_ptr<DNSRecordContent> >& signRecords) 
+string getMessageForRRSET(const std::string& qname, const RRSIGRecordContent& rrc, vector<shared_ptr<DNSRecordContent> >& signRecords) 
 {
   sort(signRecords.begin(), signRecords.end(), sharedDNSSECCompare);
 
@@ -125,8 +133,7 @@ string getHashForRRSET(const std::string& qname, const RRSIGRecordContent& rrc,
     toHash.append(rdata);
   }
   
-  shared_ptr<DNSPrivateKey> dpk(DNSPrivateKey::make(rrc.d_algorithm));
-  return dpk->hash(toHash);
+  return toHash;
 }
 
 DSRecordContent makeDSFromDNSKey(const std::string& qname, const DNSKEYRecordContent& drc, int digest)
index 9fcd58cf8ceb27fcf36f7a9a130dd5d93a5eb9b6..02e18a70e7faefd02bb3321412078d266dcada31 100644 (file)
@@ -19,7 +19,7 @@ class DNSPrivateKey
     virtual std::string getPublicKeyString()const =0;
     virtual int getBits() const =0;
     
-    virtual void fromISCString(DNSKEYRecordContent& drc, const std::string& content)=0;
+    virtual void fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap)=0;
     virtual void fromPEMString(DNSKEYRecordContent& drc, const std::string& raw)=0;
     virtual void fromPublicKeyString(unsigned algorithm, const std::string& content)
     {
@@ -34,7 +34,7 @@ class DNSPrivateKey
     
     typedef DNSPrivateKey* maker_t(unsigned int algorithm);
     
-    static void report(unsigned int algorithm, maker_t* maker);
+    static void report(unsigned int algorithm, maker_t* maker, bool fallback=false);
   private:
     
     typedef std::map<unsigned int, maker_t*> makers_t;
@@ -86,7 +86,7 @@ struct CanonicalCompare: public binary_function<string, string, bool>
 };
 
 bool sharedDNSSECCompare(const boost::shared_ptr<DNSRecordContent>& a, const shared_ptr<DNSRecordContent>& b);
-string getHashForRRSET(const std::string& qname, const RRSIGRecordContent& rrc, std::vector<boost::shared_ptr<DNSRecordContent> >& signRecords);
+string getMessageForRRSET(const std::string& qname, const RRSIGRecordContent& rrc, std::vector<boost::shared_ptr<DNSRecordContent> >& signRecords);
 
 DSRecordContent makeDSFromDNSKey(const std::string& qname, const DNSKEYRecordContent& drc, int digest=1);
 
index 2e6822631cf1337ede62159dcac5ac39b626dfde..53e7d6ace30e87126ccbdbb240f04481e95b4729 100644 (file)
@@ -114,9 +114,10 @@ void fillOutRRSIG(DNSSECPrivateKey& dpk, const std::string& signQName, RRSIGReco
   const DNSPrivateKey* rc = dpk.getKey();
   rrc.d_tag = drc.getTag();
   rrc.d_algorithm = drc.d_algorithm;
-  string realhash=getHashForRRSET(signQName, rrc, toSign); // this is what we sign
 
-  pair<string, string> lookup(rc->getPubKeyHash(), realhash);
+  string msg=getMessageForRRSET(signQName, rrc, toSign); // this is what we will hash & sign
+
+  pair<string, string> lookup(rc->getPubKeyHash(), msg); // we key on the whole message now!
   
   {
     Lock l(&g_signatures_lock);
@@ -129,7 +130,10 @@ void fillOutRRSIG(DNSSECPrivateKey& dpk, const std::string& signQName, RRSIGReco
       ; // cerr<<"Miss!"<<endl;
   }
   
-  rrc.d_signature = rc->sign(realhash);
+  //DTime dt;
+  //dt.set();
+  rrc.d_signature = rc->sign(msg);
+  //cerr<<dt.udiff()<<endl;
 
   Lock l(&g_signatures_lock);
   g_signatures[lookup] = rrc.d_signature;
index 781ee59a4f5df719a6d8e487b0baa4309a5fa0ca..d9294453afc95c5ec347109b795aba81372031d7 100644 (file)
@@ -1,6 +1,6 @@
 /*
     PowerDNS Versatile Database Driven Nameserver
-    Copyright (C) 2002-2009  PowerDNS.COM BV
+    Copyright (C) 2002-2011  PowerDNS.COM BV
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License version 2 as 
index 959b673e5c96116c988857d6e9fe4ef82375bc6c..3dbdb7fd58f7289412717bbec44f312a18a63108 100644 (file)
@@ -208,7 +208,9 @@ void verifyCrypto(const string& zone)
     }
   }
   
-  string hash = getHashForRRSET(qname, rrc, toSign);        
+  string msg = getMessageForRRSET(qname, rrc, toSign);        
+  DNSPrivateKey* dpk = DNSPrivateKey::make(rrc.d_algorithm);
+  string hash = dpk->sign(msg);
   cerr<<"Verify: "<<DNSPrivateKey::makeFromPublicKeyString(drc.d_algorithm, drc.d_key)->verify(hash, rrc.d_signature)<<endl;
   if(dsrc.d_digesttype) {
     cerr<<"Calculated DS: "<<apex<<" IN DS "<<makeDSFromDNSKey(apex, drc, dsrc.d_digesttype).getZoneRepresentation()<<endl;
index 38a4fb7920b045b8123a0726e860035765fdd4c8..6e7ba6ebb0cc30148bf6f99438ae90b1e63cde9d 100644 (file)
@@ -92,7 +92,7 @@ public:
   {
     return mpi_size(&d_context.N)*8;
   }
-  void fromISCString(DNSKEYRecordContent& drc, const std::string& content);
+  void fromISCMap(DNSKEYRecordContent& drc, std::map<std::string, std::string>& stormap);
   void fromPEMString(DNSKEYRecordContent& drc, const std::string& raw);
   void fromPublicKeyString(unsigned int algorithm, const std::string& raw);
   static DNSPrivateKey* maker(unsigned int algorithm)
@@ -144,8 +144,9 @@ std::string RSADNSPrivateKey::getPubKeyHash() const
   return string((char*)hash, sizeof(hash));
 }
 
-std::string RSADNSPrivateKey::sign(const std::string& hash) const
+std::string RSADNSPrivateKey::sign(const std::string& msg) const
 {
+  string hash = this->hash(msg);
   unsigned char signature[mpi_size(&d_context.N)];
   int hashKind;
   if(hash.size()==20)
@@ -167,9 +168,10 @@ 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
+bool RSADNSPrivateKey::verify(const std::string& msg, const std::string& signature) const
 {
   int hashKind;
+  string hash=this->hash(msg);
   if(hash.size()==20)
     hashKind= SIG_RSA_SHA1;
   else if(hash.size()==32) 
@@ -177,6 +179,8 @@ bool RSADNSPrivateKey::verify(const std::string& hash, const std::string& signat
   else
     hashKind = SIG_RSA_SHA512;
   
+  
+  
   int ret=rsa_pkcs1_verify(const_cast<rsa_context*>(&d_context), RSA_PUBLIC, 
     hashKind,
     hash.size(),
@@ -247,11 +251,12 @@ std::string RSADNSPrivateKey::convertToISC(unsigned int algorithm) const
 }
 
 
-void RSADNSPrivateKey::fromISCString(DNSKEYRecordContent& drc, const std::string& content)
+void RSADNSPrivateKey::fromISCMap(DNSKEYRecordContent& drc,  std::map<std::string, std::string>& stormap)
 {
   string sline;
   string key,value;
-  map<string, mpi*> places;
+  typedef map<string, mpi*> places_t;
+  places_t places;
   
   rsa_init(&d_context, RSA_PKCS_V15, 0, NULL, NULL );
 
@@ -263,48 +268,17 @@ void RSADNSPrivateKey::fromISCString(DNSKEYRecordContent& drc, const std::string
   places["Exponent1"]=&d_context.DP;
   places["Exponent2"]=&d_context.DQ;
   places["Coefficient"]=&d_context.QP;
-
-  string modulus, exponent;
-  istringstream str(content);
-  unsigned char decoded[1024];
-  while(getline(str, sline)) {
-    tie(key,value)=splitField(sline, ':');
-    trim(value);
-
-    if(places.count(key)) {
-      if(places[key]) {
-        int len=sizeof(decoded);
-        if(base64_decode(decoded, &len, (unsigned char*)value.c_str(), value.length()) < 0) {
-          cerr<<"Error base64 decoding '"<<value<<"'\n";
-          exit(1);
-        }
-        //     B64Decode(value, decoded);
-        //     cerr<<key<<" decoded.length(): "<<8*len<<endl;
-        mpi_read_binary(places[key], decoded, len);
-        if(key=="Modulus")
-          modulus.assign((const char*)decoded,len);
-        if(key=="PublicExponent")
-          exponent.assign((const char*)decoded,len);
-      }
-    }
-    else {
-      if(key == "Algorithm") 
-        drc.d_algorithm = atoi(value.c_str());
-      else if(key != "Private-key-format")
-        cerr<<"Unknown field '"<<key<<"'\n";
-    }
+  
+  drc.d_algorithm = atoi(stormap["algorithm"].c_str());
+  
+  string raw;
+  BOOST_FOREACH(const places_t::value_type& val, places) {
+    raw=stormap[toLower(val.first)];
+    mpi_read_binary(val.second, (unsigned char*) raw.c_str(), raw.length());
   }
-  d_context.len = ( mpi_msb( &d_context.N ) + 7 ) >> 3; // no clue what this does
 
-  if(exponent.length() < 255) 
-    drc.d_key.assign(1, (char) (unsigned int) exponent.length());
-  else {
-    drc.d_key.assign(1, 0);
-    uint16_t len=htons(exponent.length());
-    drc.d_key.append((char*)&len, 2);
-  }
-  drc.d_key.append(exponent);
-  drc.d_key.append(modulus);
+  d_context.len = ( mpi_msb( &d_context.N ) + 7 ) >> 3; // no clue what this does
+  drc.d_key = this->getPublicKeyString();
   drc.d_protocol=3;
 }
 
@@ -393,15 +367,17 @@ string RSADNSPrivateKey::getPublicKeyString()  const
   keystring.append(modulus);
   return keystring;
 }
+
 namespace {
 struct LoaderStruct
 {
   LoaderStruct()
   {
-    DNSPrivateKey::report(5, &RSADNSPrivateKey::maker);
-    DNSPrivateKey::report(7, &RSADNSPrivateKey::maker);
-    DNSPrivateKey::report(8, &RSADNSPrivateKey::maker);
-    DNSPrivateKey::report(10, &RSADNSPrivateKey::maker);
+    DNSPrivateKey::report(5, &RSADNSPrivateKey::maker, true);
+    DNSPrivateKey::report(7, &RSADNSPrivateKey::maker, true);
+    DNSPrivateKey::report(8, &RSADNSPrivateKey::maker, true);
+    DNSPrivateKey::report(10, &RSADNSPrivateKey::maker, true);
   }
 } loader;
 }
+