From: Bert Hubert Date: Tue, 25 Jan 2011 07:51:55 +0000 (+0000) Subject: 'multi-algorithm support' - for now we still only do RSA, but the whole signer stuff... X-Git-Tag: auth-3.0~342 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=699e6e377b575175d7143d3a006b10067182a791;p=thirdparty%2Fpdns.git 'multi-algorithm support' - for now we still only do RSA, but the whole signer stuff has been abstracted out, and we could in theory add KnapsackCRC32 code! Or of course ECDSA or GOST ;-) git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@1905 d19b8d6e-7fed-0310-83ef-9ca221ded41b --- diff --git a/pdns/dbdnsseckeeper.cc b/pdns/dbdnsseckeeper.cc index a1c6d32b6d..f60b168ad6 100644 --- a/pdns/dbdnsseckeeper.cc +++ b/pdns/dbdnsseckeeper.cc @@ -80,11 +80,13 @@ void DNSSECKeeper::addKey(const std::string& name, bool keyOrZone, int algorithm { if(!bits) bits = keyOrZone ? 2048 : 1024; - DNSSECPrivateKey dpk; - dpk.d_key.create(bits); - dpk.d_algorithm = algorithm; - dpk.d_flags = keyOrZone ? 257 : 256; - addKey(name, dpk, active); + DNSSECPrivateKey dspk; + shared_ptr dpk(new RSADNSPrivateKey); // defaults to RSA for now, could be smart w/algorithm! XXX FIXME + dpk->create(bits); + dspk.setKey(dpk); + dspk.d_algorithm = algorithm; + dspk.d_flags = keyOrZone ? 257 : 256; + addKey(name, dspk, active); } void DNSSECKeeper::clearCaches(const std::string& name) @@ -106,7 +108,7 @@ void DNSSECKeeper::addKey(const std::string& name, const DNSSECPrivateKey& dpk, DNSBackend::KeyData kd; kd.flags = dpk.d_flags; // the dpk doesn't get stored, only they key part kd.active = active; - kd.content = dpk.d_key.convertToISC(dpk.d_algorithm); + kd.content = dpk.getKey()->convertToISC(dpk.d_algorithm); // now store it d_db.addDomainKey(name, kd); } @@ -127,7 +129,8 @@ DNSSECPrivateKey DNSSECKeeper::getKeyById(const std::string& zname, unsigned int continue; DNSSECPrivateKey dpk; - DNSKEYRecordContent dkrc = getRSAKeyFromISCString(&dpk.d_key.getContext(), kd.content); + DNSKEYRecordContent dkrc; + dpk.setKey(shared_ptr(DNSPrivateKey::fromISCString(dkrc, kd.content))); dpk.d_flags = kd.flags; dpk.d_algorithm = dkrc.d_algorithm; @@ -272,7 +275,8 @@ DNSSECKeeper::keyset_t DNSSECKeeper::getKeys(const std::string& zone, boost::tri { DNSSECPrivateKey dpk; - DNSKEYRecordContent dkrc=getRSAKeyFromISCString(&dpk.d_key.getContext(), kd.content); + DNSKEYRecordContent dkrc; + dpk.setKey(shared_ptr(DNSPrivateKey::fromISCString(dkrc, kd.content))); dpk.d_flags = kd.flags; dpk.d_algorithm = dkrc.d_algorithm; if(dpk.d_algorithm == 5 && getNSEC3PARAM(zone)) diff --git a/pdns/dnssecinfra.cc b/pdns/dnssecinfra.cc index 2d652e315c..7835d428c7 100644 --- a/pdns/dnssecinfra.cc +++ b/pdns/dnssecinfra.cc @@ -22,7 +22,7 @@ using namespace boost; using namespace std; using namespace boost::assign; -void RSAContext::create(unsigned int bits) +void RSADNSPrivateKey::create(unsigned int bits) { havege_state hs; havege_init( &hs ); @@ -33,7 +33,7 @@ void RSAContext::create(unsigned int bits) throw runtime_error("Key generation failed"); } -std::string RSAContext::getPubKeyHash() +std::string RSADNSPrivateKey::getPubKeyHash() const { unsigned char hash[20]; unsigned char N[mpi_size(&d_context.N)]; @@ -49,7 +49,22 @@ std::string RSAContext::getPubKeyHash() return string((char*)hash, sizeof(hash)); } -std::string RSAContext::convertToISC(unsigned int algorithm) const +std::string RSADNSPrivateKey::sign(const std::string& hash) const +{ + unsigned char signature[mpi_size(&d_context.N)]; + int ret=rsa_pkcs1_sign(const_cast(&d_context), RSA_PRIVATE, + hash.size()==20 ? SIG_RSA_SHA1 : SIG_RSA_SHA256, + hash.size(), + (const unsigned char*) hash.c_str(), signature); + + if(ret!=0) { + cerr<<"signing returned: "< > outputs_t; @@ -89,95 +104,81 @@ std::string RSAContext::convertToISC(unsigned int algorithm) const } -DNSKEYRecordContent getRSAKeyFromISC(rsa_context* rsa, const char* fname) +DNSPrivateKey* DNSPrivateKey::fromISCFile(DNSKEYRecordContent& drc, const char* fname) { - string sline; - string key,value; - map places; - + string sline, isc, key, value; FILE *fp=fopen(fname, "r"); - if(!fp) - unixDie("opening file '"+string(fname)+"'"); - - rsa_init(rsa, RSA_PKCS_V15, 0, NULL, NULL ); + 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); + } + fclose(fp); - places["Modulus"]=&rsa->N; - places["PublicExponent"]=&rsa->E; - places["PrivateExponent"]=&rsa->D; - places["Prime1"]=&rsa->P; - places["Prime2"]=&rsa->Q; - places["Exponent1"]=&rsa->DP; - places["Exponent2"]=&rsa->DQ; - places["Coefficient"]=&rsa->QP; + switch(algorithm) { + case 5: + case 7: + case 8: + case 10: + return RSADNSPrivateKey::fromISCString(drc, isc); + break; + default: + throw runtime_error("Unknown DNSSEC signature algorithm number "+lexical_cast(algorithm)); + break; + } + return 0; +} - unsigned char decoded[1024]; - DNSKEYRecordContent drc; - string modulus, exponent; - while(stringfgets(fp, sline)) { +DNSPrivateKey* DNSPrivateKey::fromISCString(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, ':'); - trim(value); - trim(key); - if(key.empty()) - continue; - 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 '"<len = ( mpi_msb( &rsa->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); + switch(algorithm) { + case 5: + case 7: + case 8: + case 10: + return RSADNSPrivateKey::fromISCString(drc, content); + break; + default: + throw runtime_error("Unknown DNSSEC signature algorithm number "+lexical_cast(algorithm)); + break; } - drc.d_key.append(exponent); - drc.d_key.append(modulus); - drc.d_protocol=3; - fclose(fp); - return drc; + return 0; } -DNSKEYRecordContent getRSAKeyFromISCString(rsa_context* rsa, const std::string& content) +DNSPrivateKey* RSADNSPrivateKey::fromISCString(DNSKEYRecordContent& drc, const std::string& content) { + RSADNSPrivateKey* ret = new RSADNSPrivateKey(); + string sline; string key,value; map places; - - rsa_init(rsa, RSA_PKCS_V15, 0, NULL, NULL ); + rsa_init(&ret->d_context, RSA_PKCS_V15, 0, NULL, NULL ); - places["Modulus"]=&rsa->N; - places["PublicExponent"]=&rsa->E; - places["PrivateExponent"]=&rsa->D; - places["Prime1"]=&rsa->P; - places["Prime2"]=&rsa->Q; - places["Exponent1"]=&rsa->DP; - places["Exponent2"]=&rsa->DQ; - places["Coefficient"]=&rsa->QP; + places["Modulus"]=&ret->d_context.N; + places["PublicExponent"]=&ret->d_context.E; + places["PrivateExponent"]=&ret->d_context.D; + places["Prime1"]=&ret->d_context.P; + places["Prime2"]=&ret->d_context.Q; + places["Exponent1"]=&ret->d_context.DP; + places["Exponent2"]=&ret->d_context.DQ; + places["Coefficient"]=&ret->d_context.QP; - DNSKEYRecordContent drc; string modulus, exponent; istringstream str(content); unsigned char decoded[1024]; @@ -208,7 +209,7 @@ DNSKEYRecordContent getRSAKeyFromISCString(rsa_context* rsa, const std::string& cerr<<"Unknown field '"<len = ( mpi_msb( &rsa->N ) + 7 ) >> 3; // no clue what this does + ret->d_context.len = ( mpi_msb( &ret->d_context.N ) + 7 ) >> 3; // no clue what this does if(exponent.length() < 255) drc.d_key.assign(1, (char) (unsigned int) exponent.length()); @@ -221,28 +222,34 @@ DNSKEYRecordContent getRSAKeyFromISCString(rsa_context* rsa, const std::string& drc.d_key.append(modulus); drc.d_protocol=3; - return drc; + return ret; +} + +DNSPrivateKey* DNSPrivateKey::fromPEMString(DNSKEYRecordContent& drc, const std::string& raw) +{ + return RSADNSPrivateKey::fromPEMString(drc, raw); } -DNSKEYRecordContent getRSAKeyFromPEMString(rsa_context* rsa, const std::string& raw) +DNSPrivateKey* RSADNSPrivateKey::fromPEMString(DNSKEYRecordContent& drc, const std::string& raw) { vector integers; decodeDERIntegerSequence(raw, integers); cerr<<"Got "< places; - rsa_init(rsa, RSA_PKCS_V15, 0, NULL, NULL ); + RSADNSPrivateKey* ret = new RSADNSPrivateKey; + + rsa_init(&ret->d_context, RSA_PKCS_V15, 0, NULL, NULL ); - places[1]=&rsa->N; - places[2]=&rsa->E; - places[3]=&rsa->D; - places[4]=&rsa->P; - places[5]=&rsa->Q; - places[6]=&rsa->DP; - places[7]=&rsa->DQ; - places[8]=&rsa->QP; + places[1]=&ret->d_context.N; + places[2]=&ret->d_context.E; + places[3]=&ret->d_context.D; + places[4]=&ret->d_context.P; + places[5]=&ret->d_context.Q; + places[6]=&ret->d_context.DP; + places[7]=&ret->d_context.DQ; + places[8]=&ret->d_context.QP; - DNSKEYRecordContent drc; string modulus, exponent; for(int n = 0; n < 9 ; ++n) { @@ -256,7 +263,7 @@ DNSKEYRecordContent getRSAKeyFromPEMString(rsa_context* rsa, const std::string& } } } - rsa->len = ( mpi_msb( &rsa->N ) + 7 ) >> 3; // no clue what this does + ret->d_context.len = ( mpi_msb( &ret->d_context.N ) + 7 ) >> 3; // no clue what this does if(exponent.length() < 255) drc.d_key.assign(1, (char) (unsigned int) exponent.length()); @@ -269,10 +276,9 @@ DNSKEYRecordContent getRSAKeyFromPEMString(rsa_context* rsa, const std::string& drc.d_key.append(modulus); drc.d_protocol=3; - return drc; + return ret; } - void makeRSAPublicKeyFromDNS(rsa_context* rc, const DNSKEYRecordContent& dkrc) { rsa_init(rc, RSA_PKCS_V15, 0, NULL, NULL ); @@ -340,34 +346,39 @@ DSRecordContent makeDSFromDNSKey(const std::string& qname, const DNSKEYRecordCon return dsrc; } -DNSKEYRecordContent makeDNSKEYFromRSAKey(const rsa_context* rc, uint8_t algorithm, uint16_t flags) +string RSADNSPrivateKey::getPublicKeyString() const { - DNSKEYRecordContent drc; - char tmp[max(mpi_size(&rc->E), mpi_size(&rc->N))]; - - // cerr<<"in makeDNSKEY rsa_check_pubkey: "<sign(realhash); Lock l(&g_signatures_lock); g_signatures[lookup] = rrc.d_signature; diff --git a/pdns/nsecrecords.cc b/pdns/nsecrecords.cc index bda4b250b2..670c755b0e 100644 --- a/pdns/nsecrecords.cc +++ b/pdns/nsecrecords.cc @@ -65,9 +65,9 @@ NSECRecordContent::DNSRecordContent* NSECRecordContent::make(const DNSRecord &dr for(unsigned int n=0 ; n < len ; ++n) { uint8_t val=bitmap[2+n]; - for(int bit = 0; bit < 8 ; ++bit , val>>=1) + for(int bit = 0; bit < 8 ; ++bit , val>>=1) if(val & 1) { - ret->d_set.insert((7-bit) + 8*(n)); + ret->d_set.insert((7-bit) + 8*(n)); } } diff --git a/pdns/pdnssec.cc b/pdns/pdnssec.cc index ca3e51413e..500112e080 100644 --- a/pdns/pdnssec.cc +++ b/pdns/pdnssec.cc @@ -200,7 +200,7 @@ void showZone(DNSSECKeeper& dk, const std::string& zone) cout << "keys: "<convertToISC(dpk.d_algorithm) < key(DNSPrivateKey::fromPEMString(drc, raw)); + dpk.setKey(key); dpk.d_algorithm = atoi(cmds[3].c_str()); @@ -466,7 +468,9 @@ try string zone=cmds[1]; string fname=cmds[2]; DNSSECPrivateKey dpk; - DNSKEYRecordContent drc = getRSAKeyFromISC(&dpk.d_key.getContext(), fname.c_str()); + DNSKEYRecordContent drc; + shared_ptr key(DNSPrivateKey::fromISCFile(drc, fname.c_str())); + dpk.setKey(key); dpk.d_algorithm = drc.d_algorithm; if(dpk.d_algorithm == 7)