]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
update Ed25519 algorithm number and mnemonic
authorKees Monshouwer <mind04@monshouwer.org>
Tue, 10 Jan 2017 15:04:22 +0000 (16:04 +0100)
committerPieter Lexis <pieter.lexis@powerdns.com>
Tue, 9 May 2017 09:46:00 +0000 (11:46 +0200)
http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml

(cherry picked from commit 9d3727e0471f132f0294d6944349eb6afb2ba2ab)

pdns/dbdnsseckeeper.cc
pdns/dnssecinfra.cc
pdns/dnsseckeeper.hh
pdns/pdnsutil.cc
pdns/sodiumsigners.cc
regression-tests.api/test_cryptokeys.py [new file with mode: 0644]

index 14e47373d4a12684d2c50c44fb9a52688481dfc5..37bd27c0d09656bcf80a2ecbc7e332296adbab59 100644 (file)
@@ -79,7 +79,7 @@ bool DNSSECKeeper::addKey(const DNSName& name, bool setSEPBit, int algorithm, in
     if(algorithm <= 10)
       throw runtime_error("Creating an algorithm " +std::to_string(algorithm)+" ("+algorithm2name(algorithm)+") key requires the size (in bits) to be passed");
     else {
-      if(algorithm == 12 || algorithm == 13 || algorithm == 250) // GOST, ECDSAP256SHA256, ED25519SHA512
+      if(algorithm == 12 || algorithm == 13 || algorithm == 15) // GOST, ECDSAP256SHA256, ED25519
         bits = 256;
       else if(algorithm == 14) // ECDSAP384SHA384
         bits = 384;
index 54f6b8e79f0f1e83b190739dfe3e6deead3481be..8a17cac035d0e509fa70999c3fe3299c23726326 100644 (file)
@@ -236,7 +236,7 @@ pair<unsigned int, unsigned int> DNSCryptoKeyEngine::testMakers(unsigned int alg
   unsigned int bits;
   if(algo <= 10)
     bits=1024;
-  else if(algo == 12 || algo == 13 || algo == 250) // ECC-GOST or ECDSAP256SHA256 or ED25519SHA512
+  else if(algo == 12 || algo == 13 || algo == 15) // ECC-GOST or ECDSAP256SHA256 or ED25519
     bits=256;
   else if(algo == 14) // ECDSAP384SHA384
     bits = 384;
index 38dbc56464edef7ba13023088bde00eca433d570..9c8582f3cfda4fbb6dc3aa4d41e589c804ce135d 100644 (file)
@@ -51,7 +51,7 @@ public:
     ECCGOST=12,
     ECDSA256=13,
     ECDSA384=14,
-    EXPERIMENTALED25519=250
+    ED25519=15
   };
 
   struct KeyMetaData
@@ -91,7 +91,7 @@ public:
     if (!algorithm.compare("gost")) return ECCGOST;
     if (!algorithm.compare("ecdsa256")) return ECDSA256;
     if (!algorithm.compare("ecdsa384")) return ECDSA384;
-    if (!algorithm.compare("experimental-ed25519")) return EXPERIMENTALED25519;
+    if (!algorithm.compare("ed25519")) return ED25519;
     return -1;
   }
 
@@ -124,8 +124,8 @@ public:
         return "ECDSAP256SHA256";
       case ECDSA384:
         return "ECDSAP384SHA384";
-      case EXPERIMENTALED25519:
-        return "ED25519SHA512";
+      case ED25519:
+        return "ED25519";
       case 252:
         return "INDIRECT";
       case 253:
index c2d72f86a1a6d072808a239085485c2386d5dac8..5a1bd4dd819a77832e8d9e8d899e97bfcc6c443f 100644 (file)
@@ -1906,7 +1906,7 @@ try
     cout<<"add-zone-key ZONE {zsk|ksk} [BITS] [active|inactive]"<<endl;
     cout<<"             [rsasha1|rsasha256|rsasha512|gost|ecdsa256|ecdsa384";
 #ifdef HAVE_LIBSODIUM
-    cout<<"|experimental-ed25519";
+    cout<<"|ed25519";
 #endif
     cout<<"]"<<endl;
     cout<<"                                   Add a ZSK or KSK to zone and specify algo&bits"<<endl;
@@ -2694,7 +2694,7 @@ loadMainConfig(g_vm["config-dir"].as<string>());
       if(algorithm <= 10)
         bits = keyOrZone ? 2048 : 1024;
       else {
-        if(algorithm == 12 || algorithm == 13 || algorithm == 250) // ECDSA, GOST, ED25519
+        if(algorithm == 12 || algorithm == 13 || algorithm == 15) // ECDSA, GOST, ED25519
           bits = 256;
         else if(algorithm == 14)
           bits = 384;
index 7c6d744dae6547b285002b40c049df7e1edd50c5..a937484aa4ca4cf2f0f26f3ad3152c685853c4c5 100644 (file)
@@ -52,12 +52,12 @@ DNSCryptoKeyEngine::storvector_t SodiumED25519DNSCryptoKeyEngine::convertToISCVe
 {
   /*
     Private-key-format: v1.2
-    Algorithm: 250 (ED25519SHA512)
+    Algorithm: 15 (ED25519)
     PrivateKey: GU6SnQ/Ou+xC5RumuIUIuJZteXT2z0O/ok1s38Et6mQ=
   */
 
   storvector_t storvector;
-  string algorithm = "250 (ED25519SHA512)";
+  string algorithm = "15 (ED25519)";
 
   storvector.push_back(make_pair("Algorithm", algorithm));
 
@@ -70,7 +70,7 @@ void SodiumED25519DNSCryptoKeyEngine::fromISCMap(DNSKEYRecordContent& drc, std::
 {
   /*
     Private-key-format: v1.2
-    Algorithm: 250 (ED25519SHA512)
+    Algorithm: 15 (ED25519)
     PrivateKey: GU6SnQ/Ou+xC5RumuIUIuJZteXT2z0O/ok1s38Et6mQ=
   */
 
@@ -146,7 +146,7 @@ struct LoaderSodiumStruct
 {
   LoaderSodiumStruct()
   {
-    DNSCryptoKeyEngine::report(250, &SodiumED25519DNSCryptoKeyEngine::maker);
+    DNSCryptoKeyEngine::report(15, &SodiumED25519DNSCryptoKeyEngine::maker);
   }
 } loadersodium;
 }
diff --git a/regression-tests.api/test_cryptokeys.py b/regression-tests.api/test_cryptokeys.py
new file mode 100644 (file)
index 0000000..cf249be
--- /dev/null
@@ -0,0 +1,267 @@
+import subprocess
+import json
+import unittest
+import os
+
+from test_helper import ApiTestCase, is_auth
+
+@unittest.skipIf(not is_auth(), "Not applicable")
+class Cryptokeys(ApiTestCase):
+
+    def __init__(self, *args, **kwds):
+        super(Cryptokeys, self).__init__(*args, **kwds)
+        self.keyid = 0
+        self.zone = "cryptokeys.org"
+
+    def tearDown(self):
+        super(Cryptokeys,self).tearDown()
+        self.remove_zone_key(self.keyid)
+
+    # Adding a key to self.zone using the pdnsutil command
+    def add_zone_key(self, status='inactive'):
+        try:
+            return subprocess.check_output(["../pdns/pdnsutil", "--config-dir=.", "add-zone-key", self.zone, "ksk", status], stderr=open(os.devnull, 'wb'))
+        except subprocess.CalledProcessError as e:
+            self.fail("pdnsutil add-zone-key failed: "+e.output)
+
+    # Removes a key from self.zone by id using the pdnsutil command
+    def remove_zone_key(self, key_id):
+        try:
+            subprocess.check_output(["../pdns/pdnsutil", "--config-dir=.", "remove-zone-key", self.zone, str(key_id)])
+        except subprocess.CalledProcessError as e:
+            self.fail("pdnsutil remove-zone-key failed: "+e.output)
+
+    # This method tests the DELETE api call.
+    def test_delete(self):
+        self.keyid = self.add_zone_key()
+
+        #checks the status code. I don't know how to test explicit that the backend fail removing a key.
+        r = self.session.delete(self.url("/api/v1/servers/localhost/zones/"+self.zone+"/cryptokeys/"+self.keyid))
+        self.assertEquals(r.status_code, 200)
+        self.assertEquals(r.content, "")
+
+        # Check that the key is actually deleted
+        try:
+            out = subprocess.check_output(["../pdns/pdnsutil", "--config-dir=.", "list-keys", self.zone])
+            self.assertNotIn(self.zone, out)
+        except subprocess.CalledProcessError as e:
+            self.fail("pdnsutil list-keys failed: " + e.output)
+
+    def test_delete_wrong_zone(self):
+        self.keyid = self.add_zone_key()
+        #checks for not covered zonename
+        r = self.session.delete(self.url("/api/v1/servers/localhost/zones/"+self.zone+"fail/cryptokeys/"+self.keyid))
+        self.assertEquals(r.status_code, 400)
+
+    def test_delete_key_is_gone(self):
+        self.keyid = self.add_zone_key()
+        self.remove_zone_key(self.keyid)
+        #checks for key is gone. Its ok even if no key had to be deleted. Or something went wrong with the backend.
+        r = self.session.delete(self.url("/api/v1/servers/localhost/zones/"+self.zone+"/cryptokeys/"+self.keyid))
+        self.assertEquals(r.status_code, 200)
+        self.assertEquals(r.content, "")
+
+    # Prepares the json object for Post and sends it to the server
+    def add_key(self, content='', type='ksk', active='true' , algo='', bits=0):
+        if algo == '':
+            payload = {
+                'keytype': type,
+                'active' : active
+            }
+        else:
+            payload = {
+                'keytype': type,
+                'active' : active,
+                'algo' : algo
+            }
+        if bits > 0:
+            payload['bits'] = bits
+        if content != '':
+            payload['content'] = content
+        r = self.session.post(
+            self.url("/api/v1/servers/localhost/zones/"+self.zone+"/cryptokeys"),
+            data=json.dumps(payload),
+            headers={'content-type': 'application/json'})
+
+        return r
+
+    # Test POST for a positive result and delete the added key
+    def post_helper(self,content='', algo='', bits=0):
+        r = self.add_key(content=content, algo=algo, bits=bits)
+        self.assert_success_json(r)
+        self.assertEquals(r.status_code, 201)
+        response = r.json()
+        # Only a ksk added, so expected type is csk
+        self.assertEquals(response['keytype'], 'csk')
+        self.keyid = response['id']
+        # Check if the key is actually added
+        try:
+            out = subprocess.check_output(["../pdns/pdnsutil", "--config-dir=.", "list-keys", self.zone])
+            self.assertIn(self.zone, out)
+        except subprocess.CalledProcessError as e:
+            self.fail("pdnsutil list-keys failed: " + e.output)
+
+    # Test POST to add a key with default algorithm
+    def test_post(self):
+        self.post_helper()
+
+    # Test POST to add a key with specific algorithm number
+    def test_post_specific_number(self):
+        self.post_helper(algo=10, bits=512)
+
+    # Test POST to add a key with specific name and bits
+    def test_post_specific_name_bits(self):
+        self.post_helper(algo="rsasha256", bits=256)
+
+    # Test POST to add a key with specific name
+    def test_post_specific_name(self):
+        self.post_helper(algo='ecdsa256')
+
+    # Test POST to add a private key from external resource
+    def test_post_content(self):
+        self.post_helper(content="Private-key-format: v1.2\n"+
+                                 "Algorithm: 8 (RSASHA256)\n"+
+                                 "Modulus: 4GlYLGgDI7ohnP8SmEW8EBERbNRusDcg0VQda/EPVHU=\n"+
+                                 "PublicExponent: AQAB\n"+
+                                 "PrivateExponent: JBnuXF5zOtkjtSz3odV+Fk5UNUTTeCsiI16dkcM7TVU=\n"+
+                                 "Prime1: /w7TM4118RoSEvP8+dgnCw==\n"+
+                                 "Prime2: 4T2KhkYLa3w7rdK3Cb2ifw==\n"+
+                                 "Exponent1: 3aeKj9Ct4JuhfWsgPBhGxQ==\n"+
+                                 "Exponent2: tfh1OMPQKBdnU6iATjNR2w==\n"+
+                                 "Coefficient: eVrHe/kauqOewSKndIImrg==)\n")
+
+    def test_post_wrong_key_format(self):
+        r = self.add_key(content="trollololoooolll")
+        self.assert_error_json(r)
+        self.assertEquals(r.status_code, 422)
+        self.assertIn("Key could not be parsed. Make sure your key format is correct.",r.json()['error'])
+
+    def test_post_wrong_keytype(self):
+        r = self.add_key(type='sdfdhhgj')
+        self.assert_error_json(r)
+        self.assertEquals(r.status_code, 422)
+        self.assertIn("Invalid keytype",r.json()['error'])
+
+    def test_post_wrong_bits_format(self):
+        r = self.add_key(bits='sdfdhhgj')
+        self.assert_error_json(r)
+        self.assertEquals(r.status_code, 422)
+        self.assertIn("'bits' must be a positive integer value",r.json()['error'])
+
+        r = self.add_key(bits='5.5')
+        self.assert_error_json(r)
+        self.assertEquals(r.status_code, 422)
+        self.assertIn("'bits' must be a positive integer value",r.json()['error'])
+
+        r = self.add_key(bits='-6')
+        self.assert_error_json(r)
+        self.assertEquals(r.status_code, 422)
+        self.assertIn("'bits' must be a positive integer value",r.json()['error'])
+
+    def test_post_unsupported_algorithm(self):
+        r = self.add_key(algo='lkjhgf')
+        self.assert_error_json(r)
+        self.assertEquals(r.status_code, 422)
+        self.assertIn("Unknown algorithm:",r.json()['error'])
+
+    def test_post_forgot_bits(self):
+        r = self.add_key(algo="rsasha256")
+        self.assert_error_json(r)
+        self.assertEquals(r.status_code, 422)
+        self.assertIn("key requires the size (in bits) to be passed", r.json()['error'])
+
+    def test_post_wrong_bit_size(self):
+        r = self.add_key(algo=10, bits=30)
+        self.assert_error_json(r)
+        self.assertEquals(r.status_code,422)
+        self.assertIn("The algorithm does not support the given bit size.", r.json()['error'])
+
+    def test_post_can_not_guess_key_size(self):
+        r = self.add_key(algo=17)
+        self.assert_error_json(r)
+        self.assertEquals(r.status_code,422)
+        self.assertIn("Can not guess key size for algorithm", r.json()['error'])
+
+    def test_put_activate_key(self):
+        self.keyid = self.add_zone_key()
+
+        payload = {
+            'active': True
+        }
+        r = self.session.put(
+            self.url("/api/v1/servers/localhost/zones/"+self.zone+"/cryptokeys/"+self.keyid),
+            data=json.dumps(payload),
+            headers={'content-type': 'application/json'})
+        self.assertEquals(r.status_code, 204)
+        self.assertEquals(r.content, "")
+
+        # check if key is activated
+        try:
+            out = subprocess.check_output(["../pdns/pdnsutil", "--config-dir=.", "show-zone", self.zone])
+            self.assertIn("Active", out)
+        except subprocess.CalledProcessError as e:
+            self.fail("pdnsutil show-zone failed: " + e.output)
+
+    def test_put_deactivate_key(self):
+        self.keyid= self.add_zone_key(status='active')
+        # deactivate key
+        payload2 = {
+            'active': False
+        }
+
+        r = self.session.put(
+            self.url("/api/v1/servers/localhost/zones/"+self.zone+"/cryptokeys/"+self.keyid),
+            data=json.dumps(payload2),
+            headers={'content-type': 'application/json'})
+        self.assertEquals(r.status_code, 204)
+        self.assertEquals(r.content, "")
+
+        # check if key is deactivated
+        try:
+            out = subprocess.check_output(["../pdns/pdnsutil", "--config-dir=.", "show-zone", self.zone])
+            self.assertIn("Inactive", out)
+        except subprocess.CalledProcessError as e:
+            self.fail("pdnsutil show-zone failed: " + e.output)
+
+    def test_put_deactivate_inactive_key(self):
+        self.keyid = self.add_zone_key()
+
+        # deactivate key
+        payload = {
+            'active': False
+        }
+
+        r = self.session.put(
+            self.url("/api/v1/servers/localhost/zones/"+self.zone+"/cryptokeys/"+self.keyid),
+            data=json.dumps(payload),
+            headers={'content-type': 'application/json'})
+        self.assertEquals(r.status_code, 204)
+        self.assertEquals(r.content, "")
+
+        # check if key is still deactivated
+        try:
+            out = subprocess.check_output(["../pdns/pdnsutil", "--config-dir=.", "show-zone", self.zone])
+            self.assertIn("Inactive", out)
+        except subprocess.CalledProcessError as e:
+            self.fail("pdnsutil show-zone failed: " + e.output)
+
+    def test_put_activate_active_key(self):
+        self.keyid =self.add_zone_key(status='active')
+
+        # activate key
+        payload2 = {
+            'active': True
+        }
+        r = self.session.put(
+            self.url("/api/v1/servers/localhost/zones/"+self.zone+"/cryptokeys/"+self.keyid),
+            data=json.dumps(payload2),
+            headers={'content-type': 'application/json'})
+        self.assertEquals(r.status_code, 204)
+        self.assertEquals(r.content, "")
+
+        # check if key is activated
+        try:
+            out = subprocess.check_output(["../pdns/pdnsutil", "--config-dir=.", "show-zone", self.zone])
+            self.assertIn("Active", out)
+        except subprocess.CalledProcessError as e:
+            self.fail("pdnsutil show-zone failed: " + e.output)
\ No newline at end of file