← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~cjwatson/lp-signing:signature-mode-clear into lp-signing:master

 

Colin Watson has proposed merging ~cjwatson/lp-signing:signature-mode-clear into lp-signing:master.

Commit message:
Add SignatureMode.CLEAR

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/lp-signing/+git/lp-signing/+merge/386762

This isn't supported by any of the existing key types, but will be supported by OpenPGP.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/lp-signing:signature-mode-clear into lp-signing:master.
diff --git a/lp_signing/enums.py b/lp_signing/enums.py
index cb28194..9318223 100644
--- a/lp_signing/enums.py
+++ b/lp_signing/enums.py
@@ -61,3 +61,11 @@ class SignatureMode(EnumeratedType):
 
         The result of signing should be just the signature.
         """)
+
+    CLEAR = Item("""
+        Clear
+
+        The result of signing should consist of both the original message
+        and the signature, encapsulated in a plain-text format.  This is
+        only meaningful for OpenPGP signatures.
+        """)
diff --git a/lp_signing/model/key.py b/lp_signing/model/key.py
index d72449a..a1363ea 100644
--- a/lp_signing/model/key.py
+++ b/lp_signing/model/key.py
@@ -426,7 +426,7 @@ class Key(Storm):
             message_path = tmp / message_name
             message_path.write_bytes(message)
 
-            if mode == SignatureMode.ATTACHED:
+            if mode in (SignatureMode.ATTACHED, SignatureMode.CLEAR):
                 sig_path = Path(str(message_path) + ".signed")
             elif mode == SignatureMode.DETACHED:
                 sig_path = Path(str(message_path) + ".sig")
diff --git a/lp_signing/model/tests/test_key.py b/lp_signing/model/tests/test_key.py
index 8b945ec..1e59fa5 100644
--- a/lp_signing/model/tests/test_key.py
+++ b/lp_signing/model/tests/test_key.py
@@ -374,13 +374,19 @@ class TestKey(TestCase):
             UnsupportedSignatureMode,
             key.sign, "t.efi", b"test data", SignatureMode.DETACHED)
 
+    def test_sign_uefi_clear_unsupported(self):
+        key = factory.create_key(KeyType.UEFI)
+        self.assertRaises(
+            UnsupportedSignatureMode,
+            key.sign, "t.efi", b"test data", SignatureMode.CLEAR)
+
     def test_sign_kmod_attached_unsupported(self):
         key = factory.create_key(KeyType.KMOD)
         self.assertRaises(
             UnsupportedSignatureMode,
             key.sign, "t.ko", b"test data", SignatureMode.ATTACHED)
 
-    def test_sign_kmod(self):
+    def test_sign_kmod_detached(self):
         key = factory.create_key(KeyType.KMOD)
         fake_kmodsign = FakeKmodSign(b"test signed data")
         self.processes_fixture.add(fake_kmodsign)
@@ -397,13 +403,19 @@ class TestKey(TestCase):
             self.processes_fixture.procs,
             MatchesListwise([RanCommand(kmodsign_args)]))
 
+    def test_sign_kmod_clear_unsupported(self):
+        key = factory.create_key(KeyType.KMOD)
+        self.assertRaises(
+            UnsupportedSignatureMode,
+            key.sign, "t.ko", b"test data", SignatureMode.CLEAR)
+
     def test_sign_opal_attached_unsupported(self):
         key = factory.create_key(KeyType.OPAL)
         self.assertRaises(
             UnsupportedSignatureMode,
             key.sign, "t.opal", b"test data", SignatureMode.ATTACHED)
 
-    def test_sign_opal(self):
+    def test_sign_opal_detached(self):
         key = factory.create_key(KeyType.OPAL)
         fake_kmodsign = FakeKmodSign(b"test signed data")
         self.processes_fixture.add(fake_kmodsign)
@@ -420,13 +432,19 @@ class TestKey(TestCase):
             self.processes_fixture.procs,
             MatchesListwise([RanCommand(kmodsign_args)]))
 
+    def test_sign_opal_clear_unsupported(self):
+        key = factory.create_key(KeyType.OPAL)
+        self.assertRaises(
+            UnsupportedSignatureMode,
+            key.sign, "t.opal", b"test data", SignatureMode.CLEAR)
+
     def test_sign_sipl_attached_unsupported(self):
         key = factory.create_key(KeyType.SIPL)
         self.assertRaises(
             UnsupportedSignatureMode,
             key.sign, "t.sipl", b"test data", SignatureMode.ATTACHED)
 
-    def test_sign_sipl(self):
+    def test_sign_sipl_detached(self):
         key = factory.create_key(KeyType.SIPL)
         fake_kmodsign = FakeKmodSign(b"test signed data")
         self.processes_fixture.add(fake_kmodsign)
@@ -443,6 +461,12 @@ class TestKey(TestCase):
             self.processes_fixture.procs,
             MatchesListwise([RanCommand(kmodsign_args)]))
 
+    def test_sign_sipl_clear_unsupported(self):
+        key = factory.create_key(KeyType.SIPL)
+        self.assertRaises(
+            UnsupportedSignatureMode,
+            key.sign, "t.sipl", b"test data", SignatureMode.CLEAR)
+
     def test_sign_fit_attached(self):
         key = factory.create_key(KeyType.FIT)
         fake_mkimage = FakeMkimage(b"test signed data")
@@ -465,6 +489,12 @@ class TestKey(TestCase):
             UnsupportedSignatureMode,
             key.sign, "t.fit", b"test data", SignatureMode.DETACHED)
 
+    def test_sign_fit_clear_unsupported(self):
+        key = factory.create_key(KeyType.FIT)
+        self.assertRaises(
+            UnsupportedSignatureMode,
+            key.sign, "t.fit", b"test data", SignatureMode.CLEAR)
+
     def test_inject_uefi(self):
         private_key = factory.generate_random_bytes(size=64)
         public_key = factory.generate_random_bytes(size=64)
diff --git a/lp_signing/tests/test_webapi.py b/lp_signing/tests/test_webapi.py
index 2ad027a..10426dd 100644
--- a/lp_signing/tests/test_webapi.py
+++ b/lp_signing/tests/test_webapi.py
@@ -705,7 +705,7 @@ class TestSignView(TestCase):
         self.assertThat(
             resp,
             HasAPIError(
-                "'nonsense' is not one of ['ATTACHED', 'DETACHED']"))
+                "'nonsense' is not one of ['ATTACHED', 'DETACHED', 'CLEAR']"))
         self.assertNonceConsumed()
 
     def test_unknown_key(self):
@@ -812,6 +812,22 @@ class TestSignView(TestCase):
             resp,
             HasAPIError("Signature mode DETACHED not supported with UEFI"))
 
+    def test_sign_uefi_clear_unsupported(self):
+        key = factory.create_key(key_type=KeyType.UEFI)
+        key.addAuthorization(self.client)
+        store.commit()
+        resp = self.post_sign(
+            {
+                "key-type": "UEFI",
+                "fingerprint": key.fingerprint,
+                "message-name": "t.efi",
+                "message": base64.b64encode(b"test data").decode("UTF-8"),
+                "mode": "CLEAR",
+                })
+        self.assertThat(
+            resp,
+            HasAPIError("Signature mode CLEAR not supported with UEFI"))
+
     def test_sign_kmod_attached_unsupported(self):
         key = factory.create_key(key_type=KeyType.KMOD)
         key.addAuthorization(self.client)
@@ -828,7 +844,7 @@ class TestSignView(TestCase):
             resp,
             HasAPIError("Signature mode ATTACHED not supported with KMOD"))
 
-    def test_sign_kmod(self):
+    def test_sign_kmod_detached(self):
         key = factory.create_key(key_type=KeyType.KMOD)
         key.addAuthorization(self.client)
         store.commit()
@@ -854,6 +870,22 @@ class TestSignView(TestCase):
                 })))
         self.assertNonceConsumed()
 
+    def test_sign_kmod_clear_unsupported(self):
+        key = factory.create_key(key_type=KeyType.KMOD)
+        key.addAuthorization(self.client)
+        store.commit()
+        resp = self.post_sign(
+            {
+                "key-type": "KMOD",
+                "fingerprint": key.fingerprint,
+                "message-name": "t.ko",
+                "message": base64.b64encode(b"test data").decode("UTF-8"),
+                "mode": "CLEAR",
+                })
+        self.assertThat(
+            resp,
+            HasAPIError("Signature mode CLEAR not supported with KMOD"))
+
     def test_sign_kmod_kmodsign_error(self):
         key = factory.create_key(key_type=KeyType.KMOD)
         key.addAuthorization(self.client)
@@ -936,6 +968,22 @@ class TestSignView(TestCase):
         self.assertThat(resp, HasAPIError(MatchesRegex(error_re), 500))
         self.assertNonceConsumed()
 
+    def test_sign_opal_clear_unsupported(self):
+        key = factory.create_key(key_type=KeyType.OPAL)
+        key.addAuthorization(self.client)
+        store.commit()
+        resp = self.post_sign(
+            {
+                "key-type": "OPAL",
+                "fingerprint": key.fingerprint,
+                "message-name": "t.opal",
+                "message": base64.b64encode(b"test data").decode("UTF-8"),
+                "mode": "CLEAR",
+                })
+        self.assertThat(
+            resp,
+            HasAPIError("Signature mode CLEAR not supported with OPAL"))
+
     def test_sign_sipl_attached_unsupported(self):
         key = factory.create_key(key_type=KeyType.SIPL)
         key.addAuthorization(self.client)
@@ -998,7 +1046,23 @@ class TestSignView(TestCase):
         self.assertThat(resp, HasAPIError(MatchesRegex(error_re), 500))
         self.assertNonceConsumed()
 
-    def test_sign_fit(self):
+    def test_sign_sipl_clear_unsupported(self):
+        key = factory.create_key(key_type=KeyType.SIPL)
+        key.addAuthorization(self.client)
+        store.commit()
+        resp = self.post_sign(
+            {
+                "key-type": "SIPL",
+                "fingerprint": key.fingerprint,
+                "message-name": "t.sipl",
+                "message": base64.b64encode(b"test data").decode("UTF-8"),
+                "mode": "CLEAR",
+                })
+        self.assertThat(
+            resp,
+            HasAPIError("Signature mode CLEAR not supported with SIPL"))
+
+    def test_sign_fit_attached(self):
         key = factory.create_key(key_type=KeyType.FIT)
         key.addAuthorization(self.client)
         store.commit()
@@ -1024,7 +1088,7 @@ class TestSignView(TestCase):
                 })))
         self.assertNonceConsumed()
 
-    def test_sign_fit_sbsign_error(self):
+    def test_sign_fit_attached_sbsign_error(self):
         key = factory.create_key(key_type=KeyType.FIT)
         key.addAuthorization(self.client)
         store.commit()
@@ -1060,6 +1124,22 @@ class TestSignView(TestCase):
             resp,
             HasAPIError("Signature mode DETACHED not supported with FIT"))
 
+    def test_sign_fit_clear_unsupported(self):
+        key = factory.create_key(key_type=KeyType.FIT)
+        key.addAuthorization(self.client)
+        store.commit()
+        resp = self.post_sign(
+            {
+                "key-type": "FIT",
+                "fingerprint": key.fingerprint,
+                "message-name": "t.fit",
+                "message": base64.b64encode(b"test data").decode("UTF-8"),
+                "mode": "CLEAR",
+                })
+        self.assertThat(
+            resp,
+            HasAPIError("Signature mode CLEAR not supported with FIT"))
+
 
 class TestInjectView(TestCase):