Initial commit with rough outlines Next I'll need a README. Signed-off-by: Konstantin Ryabitsev <konstantin@linuxfoundation.org>
diff --git a/.devkey/kernel.org/dev/patches.txt b/.devkey/kernel.org/dev/patches.txt new file mode 100644 index 0000000..bf3692b --- /dev/null +++ b/.devkey/kernel.org/dev/patches.txt
@@ -0,0 +1 @@ +JweccOuDZnENKbamn1QAN4tyvixYSQRl32WKmL7s1vI=
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9769964 --- /dev/null +++ b/.gitignore
@@ -0,0 +1,3 @@ +*.pyc +__pycache__ +.idea
diff --git a/dk.key b/dk.key new file mode 100644 index 0000000..bcae104 --- /dev/null +++ b/dk.key
@@ -0,0 +1 @@ +9FcEv0kKSZFagu06dp1FL1oe69XvJMzBQixRes+0cIg= \ No newline at end of file
diff --git a/emails/dev-signed-wkd-ingit.eml b/emails/dev-signed-wkd-ingit.eml new file mode 100644 index 0000000..6873f18 --- /dev/null +++ b/emails/dev-signed-wkd-ingit.eml
@@ -0,0 +1,52 @@ +Return-Path: <SRS0=87nF=CT=vger.kernel.org=linux-kernel-owner@kernel.org> +From: Dev Eloper <dev@kernel.org> +To: <linux-kernel@vger.kernel.org> +Subject: [PATCH] drm: xlnx: remove defined but not used 'scaling_factors_666' +Date: Thu, 10 Sep 2020 22:06:30 +0800 +Message-ID: <patch-attestation-examples@kernel.org> +X-Mailer: git-send-email 2.25.4 +X-Patch-Hashes: v=1; h=sha256; + i=pkD5Pg8+cndZAzQQzo3RBSOOUzZM3GYWxiFIKFGIKe0=; + m=yW4TvC/DGWCUJTa11Aw1b/2ZAXobsLD45aLA/440yQI=; + p=iJdYN6+isP/3HmQaf1IiG7OfA1vzRxXlPGZtvecS484= +X-Patch-Sig: m=wkd; d=kernel.org; i=dev@kernel.org; s=patches; + t=1600119317; a=ed25519-sha256; b=dCqdIgrVZMdTQ8Ylxu7QTH0oetC2MyNiNOVH2Axked + tMo3abcWjceSEY8GNvc8TpK4YzfVZr0Q/FKWv706maDSMxkPBiKAlOlQ+9R+bt3soEiD9Fj/BVZn + Kldakfjw6W +MIME-Version: 1.0 +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: 8bit + +This addresses the following gcc warning with "make W=1": + +drivers/gpu/drm/xlnx/zynqmp_disp.c:245:18: warning: +‘scaling_factors_666’ defined but not used [-Wunused-const-variable=] + 245 | static const u32 scaling_factors_666[] = { + | ^~~~~~~~~~~~~~~~~~~ + +Signed-off-by: Dev Eloper <dev@kernel.org> +--- + drivers/gpu/drm/xlnx/zynqmp_disp.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c b/drivers/gpu/drm/xlnx/zynqmp_disp.c +index a455cfc1bee5..98bd48f13fd1 100644 +--- a/drivers/gpu/drm/xlnx/zynqmp_disp.c ++++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c +@@ -242,12 +242,6 @@ static const u32 scaling_factors_565[] = { + ZYNQMP_DISP_AV_BUF_5BIT_SF, + }; + +-static const u32 scaling_factors_666[] = { +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +-}; +- + static const u32 scaling_factors_888[] = { + ZYNQMP_DISP_AV_BUF_8BIT_SF, + ZYNQMP_DISP_AV_BUF_8BIT_SF, +-- +2.25.4 + +
diff --git a/emails/korg-signed-dk.eml b/emails/korg-signed-dk.eml new file mode 100644 index 0000000..0dea532 --- /dev/null +++ b/emails/korg-signed-dk.eml
@@ -0,0 +1,51 @@ +Return-Path: <SRS0=87nF=CT=vger.kernel.org=linux-kernel-owner@kernel.org> +From: Dev Eloper <dev@kernel.org> +To: <linux-kernel@vger.kernel.org> +Subject: [PATCH] drm: xlnx: remove defined but not used 'scaling_factors_666' +Date: Thu, 10 Sep 2020 22:06:30 +0800 +Message-ID: <patch-attestation-examples@kernel.org> +X-Mailer: git-send-email 2.25.4 +X-Patch-Hashes: v=1; h=sha256; + i=pkD5Pg8+cndZAzQQzo3RBSOOUzZM3GYWxiFIKFGIKe0=; + m=yW4TvC/DGWCUJTa11Aw1b/2ZAXobsLD45aLA/440yQI=; + p=iJdYN6+isP/3HmQaf1IiG7OfA1vzRxXlPGZtvecS484= +X-Patch-Sig: m=dk; d=kernel.org; i=@kernel.org; s=patches; t=1600113768; + a=ed25519-sha256; b=3VrYrm6gz10GTmwoktVyCkXXDQkkoH4wslKH9jALSA8GJZfo9YguhCZN + 7nLI7IvgkPibht2iPg8EbYUKTXygDQVgrsQ4GVG7KugwLEbH25nsDESQ8NKF4fpsYp58OFA1 +MIME-Version: 1.0 +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: 8bit + +This addresses the following gcc warning with "make W=1": + +drivers/gpu/drm/xlnx/zynqmp_disp.c:245:18: warning: +‘scaling_factors_666’ defined but not used [-Wunused-const-variable=] + 245 | static const u32 scaling_factors_666[] = { + | ^~~~~~~~~~~~~~~~~~~ + +Signed-off-by: Dev Eloper <dev@kernel.org> +--- + drivers/gpu/drm/xlnx/zynqmp_disp.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c b/drivers/gpu/drm/xlnx/zynqmp_disp.c +index a455cfc1bee5..98bd48f13fd1 100644 +--- a/drivers/gpu/drm/xlnx/zynqmp_disp.c ++++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c +@@ -242,12 +242,6 @@ static const u32 scaling_factors_565[] = { + ZYNQMP_DISP_AV_BUF_5BIT_SF, + }; + +-static const u32 scaling_factors_666[] = { +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +-}; +- + static const u32 scaling_factors_888[] = { + ZYNQMP_DISP_AV_BUF_8BIT_SF, + ZYNQMP_DISP_AV_BUF_8BIT_SF, +-- +2.25.4 + +
diff --git a/emails/korg-signed-dkim-changed-subject.eml b/emails/korg-signed-dkim-changed-subject.eml new file mode 100644 index 0000000..9fb267c --- /dev/null +++ b/emails/korg-signed-dkim-changed-subject.eml
@@ -0,0 +1,54 @@ +Return-Path: <SRS0=87nF=CT=vger.kernel.org=linux-kernel-owner@kernel.org> +From: Dev Eloper <dev@kernel.org> +To: <linux-kernel@vger.kernel.org> +Subject: [PATCH] drm: xlnx: remove defined but not used 'scaling_factors_666' xxx +Date: Thu, 10 Sep 2020 22:06:30 +0800 +Message-ID: <patch-attestation-examples@kernel.org> +X-Mailer: git-send-email 2.25.4 +X-Patch-Hashes: v=1; h=sha256; + i=pkD5Pg8+cndZAzQQzo3RBSOOUzZM3GYWxiFIKFGIKe0=; + m=yW4TvC/DGWCUJTa11Aw1b/2ZAXobsLD45aLA/440yQI=; + p=iJdYN6+isP/3HmQaf1IiG7OfA1vzRxXlPGZtvecS484= +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; + i=@kernel.org; q=dns/txt; s=default; t=1600003848; h=from : date : + x-patch-hashes; bh=g2Sv1ZR+jIrWukzdXbqb+aeiqyFQOBLDQY6z0BBnGg4=; + b=0rq7ZZRMJ0MIdNHINZRIeThVajSIlpbE578GJdNfw8vHcNeGcl7SmSCMv0HJCiusa2EYN + F9T/68LPFUwJZZgSFVdIHKOqJlz4KBxZZyXrGPe5E7BOjIyaJmP9eOIcIR4mqGpcDfP5edS + 5t53aqfBCiVPdBe7bd14MlFE0a035pY= +MIME-Version: 1.0 +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: 8bit + +This addresses the following gcc warning with "make W=1": + +drivers/gpu/drm/xlnx/zynqmp_disp.c:245:18: warning: +‘scaling_factors_666’ defined but not used [-Wunused-const-variable=] + 245 | static const u32 scaling_factors_666[] = { + | ^~~~~~~~~~~~~~~~~~~ + +Signed-off-by: Dev Eloper <dev@kernel.org> +--- + drivers/gpu/drm/xlnx/zynqmp_disp.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c b/drivers/gpu/drm/xlnx/zynqmp_disp.c +index a455cfc1bee5..98bd48f13fd1 100644 +--- a/drivers/gpu/drm/xlnx/zynqmp_disp.c ++++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c +@@ -242,12 +242,6 @@ static const u32 scaling_factors_565[] = { + ZYNQMP_DISP_AV_BUF_5BIT_SF, + }; + +-static const u32 scaling_factors_666[] = { +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +-}; +- + static const u32 scaling_factors_888[] = { + ZYNQMP_DISP_AV_BUF_8BIT_SF, + ZYNQMP_DISP_AV_BUF_8BIT_SF, +-- +2.25.4 + +
diff --git a/emails/korg-signed-dkim-with-ml-junk.eml b/emails/korg-signed-dkim-with-ml-junk.eml new file mode 100644 index 0000000..ec5c6f2 --- /dev/null +++ b/emails/korg-signed-dkim-with-ml-junk.eml
@@ -0,0 +1,56 @@ +Return-Path: <SRS0=87nF=CT=vger.kernel.org=linux-kernel-owner@kernel.org> +From: Dev Eloper <dev@kernel.org> +To: <linux-kernel@vger.kernel.org> +Subject: [junky-foo] [PATCH] drm: xlnx: remove defined but not used + 'scaling_factors_666' +Date: Thu, 10 Sep 2020 22:06:30 +0800 +Message-ID: <patch-attestation-examples@kernel.org> +X-Mailer: git-send-email 2.25.4 +X-Patch-Hashes: v=1; h=sha256; + i=pkD5Pg8+cndZAzQQzo3RBSOOUzZM3GYWxiFIKFGIKe0=; + m=yW4TvC/DGWCUJTa11Aw1b/2ZAXobsLD45aLA/440yQI=; + p=iJdYN6+isP/3HmQaf1IiG7OfA1vzRxXlPGZtvecS484= +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; + i=@kernel.org; q=dns/txt; s=default; t=1600003848; h=from : date : + x-patch-hashes; bh=g2Sv1ZR+jIrWukzdXbqb+aeiqyFQOBLDQY6z0BBnGg4=; + b=0rq7ZZRMJ0MIdNHINZRIeThVajSIlpbE578GJdNfw8vHcNeGcl7SmSCMv0HJCiusa2EYN + F9T/68LPFUwJZZgSFVdIHKOqJlz4KBxZZyXrGPe5E7BOjIyaJmP9eOIcIR4mqGpcDfP5edS + 5t53aqfBCiVPdBe7bd14MlFE0a035pY= +MIME-Version: 1.0 +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: 8bit + +This addresses the following gcc warning with "make W=1": + +drivers/gpu/drm/xlnx/zynqmp_disp.c:245:18: warning: +‘scaling_factors_666’ defined but not used [-Wunused-const-variable=] + 245 | static const u32 scaling_factors_666[] = { + | ^~~~~~~~~~~~~~~~~~~ + +Signed-off-by: Dev Eloper <dev@kernel.org> +--- + drivers/gpu/drm/xlnx/zynqmp_disp.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c b/drivers/gpu/drm/xlnx/zynqmp_disp.c +index a455cfc1bee5..98bd48f13fd1 100644 +--- a/drivers/gpu/drm/xlnx/zynqmp_disp.c ++++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c +@@ -242,12 +242,6 @@ static const u32 scaling_factors_565[] = { + ZYNQMP_DISP_AV_BUF_5BIT_SF, + }; + +-static const u32 scaling_factors_666[] = { +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +-}; +- + static const u32 scaling_factors_888[] = { + ZYNQMP_DISP_AV_BUF_8BIT_SF, + ZYNQMP_DISP_AV_BUF_8BIT_SF, +-- +2.25.4 + +______________________________________________ +Mailman added junk
diff --git a/emails/korg-signed-dkim.eml b/emails/korg-signed-dkim.eml new file mode 100644 index 0000000..628bf74 --- /dev/null +++ b/emails/korg-signed-dkim.eml
@@ -0,0 +1,54 @@ +Return-Path: <SRS0=87nF=CT=vger.kernel.org=linux-kernel-owner@kernel.org> +From: Dev Eloper <dev@kernel.org> +To: <linux-kernel@vger.kernel.org> +Subject: [PATCH] drm: xlnx: remove defined but not used 'scaling_factors_666' +Date: Thu, 10 Sep 2020 22:06:30 +0800 +Message-ID: <patch-attestation-examples@kernel.org> +X-Mailer: git-send-email 2.25.4 +X-Patch-Hashes: v=1; h=sha256; + i=pkD5Pg8+cndZAzQQzo3RBSOOUzZM3GYWxiFIKFGIKe0=; + m=yW4TvC/DGWCUJTa11Aw1b/2ZAXobsLD45aLA/440yQI=; + p=iJdYN6+isP/3HmQaf1IiG7OfA1vzRxXlPGZtvecS484= +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; + i=@kernel.org; q=dns/txt; s=default; t=1600003848; h=from : date : + x-patch-hashes; bh=g2Sv1ZR+jIrWukzdXbqb+aeiqyFQOBLDQY6z0BBnGg4=; + b=0rq7ZZRMJ0MIdNHINZRIeThVajSIlpbE578GJdNfw8vHcNeGcl7SmSCMv0HJCiusa2EYN + F9T/68LPFUwJZZgSFVdIHKOqJlz4KBxZZyXrGPe5E7BOjIyaJmP9eOIcIR4mqGpcDfP5edS + 5t53aqfBCiVPdBe7bd14MlFE0a035pY= +MIME-Version: 1.0 +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: 8bit + +This addresses the following gcc warning with "make W=1": + +drivers/gpu/drm/xlnx/zynqmp_disp.c:245:18: warning: +‘scaling_factors_666’ defined but not used [-Wunused-const-variable=] + 245 | static const u32 scaling_factors_666[] = { + | ^~~~~~~~~~~~~~~~~~~ + +Signed-off-by: Dev Eloper <dev@kernel.org> +--- + drivers/gpu/drm/xlnx/zynqmp_disp.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c b/drivers/gpu/drm/xlnx/zynqmp_disp.c +index a455cfc1bee5..98bd48f13fd1 100644 +--- a/drivers/gpu/drm/xlnx/zynqmp_disp.c ++++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c +@@ -242,12 +242,6 @@ static const u32 scaling_factors_565[] = { + ZYNQMP_DISP_AV_BUF_5BIT_SF, + }; + +-static const u32 scaling_factors_666[] = { +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +-}; +- + static const u32 scaling_factors_888[] = { + ZYNQMP_DISP_AV_BUF_8BIT_SF, + ZYNQMP_DISP_AV_BUF_8BIT_SF, +-- +2.25.4 + +
diff --git a/emails/korg-signed-wk.eml b/emails/korg-signed-wk.eml new file mode 100644 index 0000000..48c512f --- /dev/null +++ b/emails/korg-signed-wk.eml
@@ -0,0 +1,51 @@ +Return-Path: <SRS0=87nF=CT=vger.kernel.org=linux-kernel-owner@kernel.org> +From: Dev Eloper <dev@kernel.org> +To: <linux-kernel@vger.kernel.org> +Subject: [PATCH] drm: xlnx: remove defined but not used 'scaling_factors_666' +Date: Thu, 10 Sep 2020 22:06:30 +0800 +Message-ID: <patch-attestation-examples@kernel.org> +X-Mailer: git-send-email 2.25.4 +X-Patch-Hashes: v=1; h=sha256; + i=pkD5Pg8+cndZAzQQzo3RBSOOUzZM3GYWxiFIKFGIKe0=; + m=yW4TvC/DGWCUJTa11Aw1b/2ZAXobsLD45aLA/440yQI=; + p=iJdYN6+isP/3HmQaf1IiG7OfA1vzRxXlPGZtvecS484= +X-Patch-Sig: m=wk; d=kernel.org; i=@kernel.org; s=patches; t=1600115115; + a=ed25519-sha256; b=E+E/0TCyJESheZ9I1DaduNOkqq9/OMuVr4pNxLgjbrmNeXa3Q0brasRi + fW6yMAykGL4AlXSX/zN9bb093rYTCf8pKxqQA5YNaNZJQuJE2e7rM9CW7VCpg8uZqNsXZmtC +MIME-Version: 1.0 +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: 8bit + +This addresses the following gcc warning with "make W=1": + +drivers/gpu/drm/xlnx/zynqmp_disp.c:245:18: warning: +‘scaling_factors_666’ defined but not used [-Wunused-const-variable=] + 245 | static const u32 scaling_factors_666[] = { + | ^~~~~~~~~~~~~~~~~~~ + +Signed-off-by: Dev Eloper <dev@kernel.org> +--- + drivers/gpu/drm/xlnx/zynqmp_disp.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c b/drivers/gpu/drm/xlnx/zynqmp_disp.c +index a455cfc1bee5..98bd48f13fd1 100644 +--- a/drivers/gpu/drm/xlnx/zynqmp_disp.c ++++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c +@@ -242,12 +242,6 @@ static const u32 scaling_factors_565[] = { + ZYNQMP_DISP_AV_BUF_5BIT_SF, + }; + +-static const u32 scaling_factors_666[] = { +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +-}; +- + static const u32 scaling_factors_888[] = { + ZYNQMP_DISP_AV_BUF_8BIT_SF, + ZYNQMP_DISP_AV_BUF_8BIT_SF, +-- +2.25.4 + +
diff --git a/emails/mricon-signed-pgp.eml b/emails/mricon-signed-pgp.eml new file mode 100644 index 0000000..ca38854 --- /dev/null +++ b/emails/mricon-signed-pgp.eml
@@ -0,0 +1,54 @@ +Return-Path: <SRS0=87nF=CT=vger.kernel.org=linux-kernel-owner@kernel.org> +From: Konstantin Ryabitsev <mricon@kernel.org> +To: <linux-kernel@vger.kernel.org> +Subject: [PATCH] drm: xlnx: remove defined but not used 'scaling_factors_666' +Date: Thu, 10 Sep 2020 22:06:30 +0800 +Message-ID: <patch-attestation-examples@kernel.org> +X-Mailer: git-send-email 2.25.4 +X-Patch-Hashes: v=1; h=sha256; + i=pkD5Pg8+cndZAzQQzo3RBSOOUzZM3GYWxiFIKFGIKe0=; + m=yW4TvC/DGWCUJTa11Aw1b/2ZAXobsLD45aLA/440yQI=; + p=iJdYN6+isP/3HmQaf1IiG7OfA1vzRxXlPGZtvecS484= +X-Patch-Sig: m=pgp; i=mricon@kernel.org; s=0xE63EDCA9329DD07E; + b=iHUEABYIAB0WIQR2vl2yUnHhSB5njDW2xBzjVmSZbAUCX1+/nQAKCRC2xBzjVmSZbFiQAQD42c + l5It3AVJbtkwbY5XZxb9I9YuvvX3L3buU+EwjumwD9HBH8t6xcavIKQF6dwKjsmhwJnDj1tCfaxg + 3WRdUllgM= +MIME-Version: 1.0 +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: 8bit + +From: Dev Eloper <dev@kernel.org> + +This addresses the following gcc warning with "make W=1": + +drivers/gpu/drm/xlnx/zynqmp_disp.c:245:18: warning: +‘scaling_factors_666’ defined but not used [-Wunused-const-variable=] + 245 | static const u32 scaling_factors_666[] = { + | ^~~~~~~~~~~~~~~~~~~ + +Signed-off-by: Dev Eloper <dev@kernel.org> +--- + drivers/gpu/drm/xlnx/zynqmp_disp.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c b/drivers/gpu/drm/xlnx/zynqmp_disp.c +index a455cfc1bee5..98bd48f13fd1 100644 +--- a/drivers/gpu/drm/xlnx/zynqmp_disp.c ++++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c +@@ -242,12 +242,6 @@ static const u32 scaling_factors_565[] = { + ZYNQMP_DISP_AV_BUF_5BIT_SF, + }; + +-static const u32 scaling_factors_666[] = { +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +-}; +- + static const u32 scaling_factors_888[] = { + ZYNQMP_DISP_AV_BUF_8BIT_SF, + ZYNQMP_DISP_AV_BUF_8BIT_SF, +-- +2.25.4 + +
diff --git a/emails/mricon-signed-wkd.eml b/emails/mricon-signed-wkd.eml new file mode 100644 index 0000000..56d512c --- /dev/null +++ b/emails/mricon-signed-wkd.eml
@@ -0,0 +1,52 @@ +Return-Path: <SRS0=87nF=CT=vger.kernel.org=linux-kernel-owner@kernel.org> +From: Dev Eloper <dev@kernel.org> +To: <linux-kernel@vger.kernel.org> +Subject: [PATCH] drm: xlnx: remove defined but not used 'scaling_factors_666' +Date: Thu, 10 Sep 2020 22:06:30 +0800 +Message-ID: <patch-attestation-examples@kernel.org> +X-Mailer: git-send-email 2.25.4 +X-Patch-Hashes: v=1; h=sha256; + i=pkD5Pg8+cndZAzQQzo3RBSOOUzZM3GYWxiFIKFGIKe0=; + m=yW4TvC/DGWCUJTa11Aw1b/2ZAXobsLD45aLA/440yQI=; + p=iJdYN6+isP/3HmQaf1IiG7OfA1vzRxXlPGZtvecS484= +X-Patch-Sig: m=wkd; d=kernel.org; i=mricon@kernel.org; s=patches; + t=1600117517; a=ed25519-sha256; b=00zhoGO6pcpiepXV/VdkGYHH/aBm9pbZ535ncnuTbg + i18AnJgVHiJBZaR30L5Fj1uCgdNGvpfrrhXgYqEoIACAEQ4TcY8Qz0krDc7TMpwkIgTUhQNwPRnJ + pcg+KwrWoa +MIME-Version: 1.0 +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: 8bit + +This addresses the following gcc warning with "make W=1": + +drivers/gpu/drm/xlnx/zynqmp_disp.c:245:18: warning: +‘scaling_factors_666’ defined but not used [-Wunused-const-variable=] + 245 | static const u32 scaling_factors_666[] = { + | ^~~~~~~~~~~~~~~~~~~ + +Signed-off-by: Dev Eloper <dev@kernel.org> +--- + drivers/gpu/drm/xlnx/zynqmp_disp.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c b/drivers/gpu/drm/xlnx/zynqmp_disp.c +index a455cfc1bee5..98bd48f13fd1 100644 +--- a/drivers/gpu/drm/xlnx/zynqmp_disp.c ++++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c +@@ -242,12 +242,6 @@ static const u32 scaling_factors_565[] = { + ZYNQMP_DISP_AV_BUF_5BIT_SF, + }; + +-static const u32 scaling_factors_666[] = { +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +-}; +- + static const u32 scaling_factors_888[] = { + ZYNQMP_DISP_AV_BUF_8BIT_SF, + ZYNQMP_DISP_AV_BUF_8BIT_SF, +-- +2.25.4 + +
diff --git a/emails/unsigned-with-hashes.eml b/emails/unsigned-with-hashes.eml new file mode 100644 index 0000000..61b4882 --- /dev/null +++ b/emails/unsigned-with-hashes.eml
@@ -0,0 +1,48 @@ +Return-Path: <SRS0=87nF=CT=vger.kernel.org=linux-kernel-owner@kernel.org> +From: Dev Eloper <dev@kernel.org> +To: <linux-kernel@vger.kernel.org> +Subject: [PATCH] drm: xlnx: remove defined but not used 'scaling_factors_666' +Date: Thu, 10 Sep 2020 22:06:30 +0800 +Message-ID: <patch-attestation-examples@kernel.org> +X-Mailer: git-send-email 2.25.4 +X-Patch-Hashes: v=1; h=sha256; + i=pkD5Pg8+cndZAzQQzo3RBSOOUzZM3GYWxiFIKFGIKe0=; + m=yW4TvC/DGWCUJTa11Aw1b/2ZAXobsLD45aLA/440yQI=; + p=iJdYN6+isP/3HmQaf1IiG7OfA1vzRxXlPGZtvecS484= +MIME-Version: 1.0 +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: 8bit + +This addresses the following gcc warning with "make W=1": + +drivers/gpu/drm/xlnx/zynqmp_disp.c:245:18: warning: +‘scaling_factors_666’ defined but not used [-Wunused-const-variable=] + 245 | static const u32 scaling_factors_666[] = { + | ^~~~~~~~~~~~~~~~~~~ + +Signed-off-by: Dev Eloper <dev@kernel.org> +--- + drivers/gpu/drm/xlnx/zynqmp_disp.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c b/drivers/gpu/drm/xlnx/zynqmp_disp.c +index a455cfc1bee5..98bd48f13fd1 100644 +--- a/drivers/gpu/drm/xlnx/zynqmp_disp.c ++++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c +@@ -242,12 +242,6 @@ static const u32 scaling_factors_565[] = { + ZYNQMP_DISP_AV_BUF_5BIT_SF, + }; + +-static const u32 scaling_factors_666[] = { +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +-}; +- + static const u32 scaling_factors_888[] = { + ZYNQMP_DISP_AV_BUF_8BIT_SF, + ZYNQMP_DISP_AV_BUF_8BIT_SF, +-- +2.25.4 + +
diff --git a/emails/unsigned.eml b/emails/unsigned.eml new file mode 100644 index 0000000..a371cc3 --- /dev/null +++ b/emails/unsigned.eml
@@ -0,0 +1,44 @@ +Return-Path: <SRS0=87nF=CT=vger.kernel.org=linux-kernel-owner@kernel.org> +From: Dev Eloper <dev@kernel.org> +To: <linux-kernel@vger.kernel.org> +Subject: [PATCH] drm: xlnx: remove defined but not used 'scaling_factors_666' +Date: Thu, 10 Sep 2020 22:06:30 +0800 +Message-ID: <patch-attestation-examples@kernel.org> +X-Mailer: git-send-email 2.25.4 +MIME-Version: 1.0 +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: 8bit + +This addresses the following gcc warning with "make W=1": + +drivers/gpu/drm/xlnx/zynqmp_disp.c:245:18: warning: +‘scaling_factors_666’ defined but not used [-Wunused-const-variable=] + 245 | static const u32 scaling_factors_666[] = { + | ^~~~~~~~~~~~~~~~~~~ + +Signed-off-by: Dev Eloper <dev@kernel.org> +--- + drivers/gpu/drm/xlnx/zynqmp_disp.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c b/drivers/gpu/drm/xlnx/zynqmp_disp.c +index a455cfc1bee5..98bd48f13fd1 100644 +--- a/drivers/gpu/drm/xlnx/zynqmp_disp.c ++++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c +@@ -242,12 +242,6 @@ static const u32 scaling_factors_565[] = { + ZYNQMP_DISP_AV_BUF_5BIT_SF, + }; + +-static const u32 scaling_factors_666[] = { +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +- ZYNQMP_DISP_AV_BUF_6BIT_SF, +-}; +- + static const u32 scaling_factors_888[] = { + ZYNQMP_DISP_AV_BUF_8BIT_SF, + ZYNQMP_DISP_AV_BUF_8BIT_SF, +-- +2.25.4 + +
diff --git a/ingit.key b/ingit.key new file mode 100644 index 0000000..14a17e2 --- /dev/null +++ b/ingit.key
@@ -0,0 +1 @@ +KvYqVCPKGQfyg1eacwoKJsH268K2rfxRTPHpbg8LIos= \ No newline at end of file
diff --git a/main.py b/main.py new file mode 100755 index 0000000..4f84adb --- /dev/null +++ b/main.py
@@ -0,0 +1,491 @@ +#!/usr/bin/env python3 +import sys +import os +import base64 +import email +import email.header +import b4 +import time +import dkim +import re +import dns.resolver +import binascii +import subprocess +import hashlib +import requests +import anybase32 +import urllib.parse + +from nacl.signing import SigningKey, VerifyKey +from nacl.encoding import Base64Encoder +from nacl.exceptions import BadSignatureError + +from tempfile import mkstemp + +from Cryptodome.Signature import pkcs1_15 +from Cryptodome.Hash import SHA256 +from Cryptodome.PublicKey import RSA + +XPH_HDR = 'X-Patch-Hashes' +XPS_HDR = 'X-Patch-Sig' + + +def _run_command(cmdargs, stdin=None): + sp = subprocess.Popen(cmdargs, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE) + (output, error) = sp.communicate(input=stdin) + return sp.returncode, output, error + + +def gpg_run_command(cmdargs, stdin=None): + gpgbin = 'gpg' + cmdargs = [gpgbin, '--batch', '--no-auto-key-retrieve', '--no-auto-check-trustdb'] + cmdargs + return _run_command(cmdargs, stdin) + + +def get_dkim_key(domain, selector, wantkey='rsa', timeout=5): + name = f'{selector}._domainkey.{domain}.' + print(f'DNS-lookup: {name}') + keydata = None + try: + a = dns.resolver.resolve(name, dns.rdatatype.TXT, raise_on_no_answer=False, lifetime=timeout) + # Find v=DKIM1 + for r in a.response.answer: + for item in r.items: + for s in item.strings: + if s.find(b'v=DKIM1') >= 0: + keydata = s.decode() + if keydata.find(wantkey) >= 0: + break + keydata = None + if keydata: + break + if keydata: + break + except dns.resolver.NXDOMAIN: + print(f'Domain {name} does not exist') + sys.exit(1) + pass + + if not keydata: + print(f'Domain {name} does not contain a DKIM record') + sys.exit(1) + + parts = get_parts_from_header(keydata) + if 'p' not in parts: + print(f'Domain {name} does not contain a DKIM key') + sys.exit(1) + + return parts['p'] + + +def get_wk_key(domain, selector, timeout=5): + wkurl = f'https://{domain}/.well-known/_domainkey/{selector}.txt' + print(f'Retrieving: {wkurl}') + res = requests.get(wkurl, timeout=timeout) + if res.status_code != 200: + print(f'Could not get {wkurl}') + sys.exit(1) + keydata = res.content.decode().strip() + parts = get_parts_from_header(keydata) + return parts['p'] + + +def get_wkd_key(domain, identity, selector, timeout=5): + identity = identity.split('@')[0] + # Attempt to load from local git dir if we are in a git dir + cmdargs = ['git', 'rev-parse', '--show-toplevel'] + ecode, out, err = _run_command(cmdargs) + if ecode == 0: + # urlencode domain/identity/selector to make sure nobody tries path-based badness + subpath = os.path.join(out.decode().strip(), '.devkey', + urllib.parse.quote_plus(domain), + urllib.parse.quote_plus(identity), + urllib.parse.quote_plus(selector) + '.txt', + ) + try: + with open(subpath) as fh: + print(f'Loading WKD key from {subpath}') + return fh.readline().strip() + except IOError: + pass + + # We use zbase32 because this is what OpenPGP uses + # I'm not convinced this is a sane choice + i = hashlib.sha1(identity.lower().encode()).digest() + zdir = anybase32.encode(i, anybase32.ZBASE32).decode() + wkurl = f'https://{domain}/.well-known/devkey/{zdir}/{selector}.txt' + print(f'Retrieving: {wkurl}') + res = requests.get(wkurl, timeout=timeout) + if res.status_code != 200: + print(f'Could not get {wkurl}') + sys.exit(1) + # For POC purposes, we are not doing caching or TOFU management, + # but this would be a required part of actual implementation + return res.content.decode().strip() + + +def get_b64_attestation(msg): + # b4 stores these as hexdigests, but it's more natural + # for email headers to use b64 encoded values, if only + # to save a few bytes of space + lmsg = b4.LoreMessage(msg) + lmsg.load_hashes() + att = lmsg.attestation + i = base64.b64encode(binascii.unhexlify(att.i)).decode() + m = base64.b64encode(binascii.unhexlify(att.m)).decode() + p = base64.b64encode(binascii.unhexlify(att.p)).decode() + return i, m, p + + +def add_hashes_header(msg): + hhdr = gen_hashes_header(msg) + msg[XPH_HDR] = hhdr + return msg + + +def gen_hashes_header(msg): + i, m, p = get_b64_attestation(msg) + # Hardcode to sha256 for the purposes of the POC + hparts = [ + 'v=1', + 'h=sha256', + f'i={i}', + f'm={m}', + f'p={p}', + ] + hval = '; '.join(hparts) + hhdr = email.header.make_header([(hval.encode(), 'us-ascii')], maxlinelen=78) + return hhdr + + +def get_parts_from_header(hstr): + hstr = re.sub(r'\s*', '', hstr) + hdata = dict() + for chunk in hstr.split(';'): + parts = chunk.split('=', 1) + if len(parts) < 2: + continue + hdata[parts[0]] = parts[1] + return hdata + + +def dkim_canonicalize_header(hname, hval): + hname = hname.lower() + hval = hval.strip() + hval = re.sub(r'\n', '', hval) + hval = re.sub(r'\s+', ' ', hval) + return hname, hval + + +def verify_attestation_hashes(msg): + hhdr = msg.get(XPH_HDR) + hdata = get_parts_from_header(str(hhdr)) + adata = dict() + desc = { + 'i': 'metadata', + 'm': 'commit message', + 'p': 'diff content', + } + adata['i'], adata['m'], adata['p'] = get_b64_attestation(msg) + for part, what in desc.items(): + if hdata[part] == adata[part]: + status = 'PASS' + else: + status = 'FAIL' + print(f'{status} | {desc[part]}') + + +def cmd_hashes_hdr(msg): + hhdr = gen_hashes_header(msg) + print(hhdr.encode()) + + +def cmd_dkim_sign(msg): + # We use dkimpy here as a demonstration of an external DKIM compliant + # implementation generating the DKIM-Signature tag, complete with bh= + # body hash that we don't consider for our purposes: + # - it will most certainly get mangled by mailing-list software + # - if it's canonicalized with "relaxed", we can no longer consider + # patch content to be trusted, as "relaxed" canonicalization modifies + # whitespace, which allows sneaking in maliciously modified patches + # in languages with syntactic whitespace. + msg = add_hashes_header(msg) + selector = b'example' + domain = b'example.org' + include_headers = [b'from', b'date', b'x-patch-hashes'] + + with open('rsa.key', 'rb') as fh: + privkey = fh.read() + + dk = dkim.DKIM(msg.as_bytes()) + bhdr = dk.sign(selector, domain, privkey, include_headers=include_headers) + dhdr = bhdr.decode() + msg['DKIM-Signature'] = dhdr.split(':', 1)[1] + print(msg.as_string()) + + +def cmd_dkim_verify(msg): + # We don't use dkimpy to verify, as it will force verification of bh=, which + # we intentionally choose not to use for reasons listed above. + # However, our implementation is simplistic and doesn't cover many aspects + # of the DKIM standard, so real-life implementations need to consider using + # feature-complete DKIM verification tools, assuming they allow ignoring the + # bh= field. + dks = msg.get('dkim-signature') + ddata = get_parts_from_header(dks) + pk = base64.b64decode(get_dkim_key(ddata['d'], ddata['s'])) + sig = base64.b64decode(ddata['b']) + headers = list() + + for header in ddata['h'].split(':'): + # For the POC, we assume 'relaxed/' + hval = msg.get(header) + if hval is None: + # Missing headers are omitted by the DKIM RFC + continue + hname, hval = dkim_canonicalize_header(header, str(msg.get(header))) + headers.append(f'{hname}:{hval}') + # Now we add the dkim-signature header itself, without b= content + dname, dval = dkim_canonicalize_header('dkim-signature', dks) + dval = dval.rsplit('; b=')[0] + '; b=' + headers.append(f'{dname}:{dval}') + payload = ('\r\n'.join(headers)).encode() + key = RSA.import_key(pk) + hashed = SHA256.new(payload) + try: + # noinspection PyTypeChecker + pkcs1_15.new(key).verify(hashed, sig) + except (ValueError, TypeError): + print('The DKIM signature did NOT verify!') + sys.exit(1) + print(f'DKIM signature verified for d={ddata["i"]} s={ddata["s"]}') + verify_attestation_hashes(msg) + + +def cmd_pgp_sign(msg, identity='mricon@kernel.org', selector='E63EDCA9329DD07E'): + # selector is the key id of the [C] public key, e.g. 0xE63EDCA9329DD07E. + # identity is the UID we should look for on the key + # The signature can be made with a subkey, so we embed the key ID into + # the header for lookup convenience. + # We don't embed signing time, as it's part of the PGP signature. + headers = list() + hhdr = gen_hashes_header(msg) + hhname, hhval = dkim_canonicalize_header(XPH_HDR, hhdr.encode()) + headers.append(f'{hhname}:{hhval}') + + hparts = [ + 'm=pgp', + f'i={identity}', + f's=0x{selector}', + 'b=', + ] + shname, shval = dkim_canonicalize_header(XPS_HDR, '; '.join(hparts)) + headers.append(f'{shname}:{shval}') + payload = '\r\n'.join(headers).encode() + gpgargs = ['-b', '-u', selector] + ecode, out, err = gpg_run_command(gpgargs, payload) + if ecode > 0: + print('Running gpg failed') + print(err.decode()) + sys.exit(ecode) + bdata = base64.b64encode(out) + shval += bdata.decode() + shdr = email.header.make_header([(shval.encode(), 'us-ascii')], maxlinelen=78) + msg[XPS_HDR] = shdr + print(msg.as_string()) + + +def cmd_pgp_verify(msg): + # For the POC purposes, we ignore key lookup and assume it's in the keyring + shdr = msg.get(XPS_HDR) + sdata = get_parts_from_header(shdr) + sig = base64.b64decode(sdata['b']) + headers = list() + hhname, hhval = dkim_canonicalize_header(XPH_HDR, str(msg.get(XPH_HDR))) + headers.append(f'{hhname}:{hhval}') + # Now we add the sig header itself, without b= content + shname, shval = dkim_canonicalize_header(XPS_HDR, shdr) + shval = shval.rsplit('; b=')[0] + '; b=' + headers.append(f'{shname}:{shval}') + payload = ('\r\n'.join(headers)).encode() + # We can't pass both the detached sig and the content on stdin, so + # use a temporary file + savefile = mkstemp('attpoc-pgp-verify')[1] + with open(savefile, 'wb') as fh: + fh.write(sig) + gpgargs = ['--verify', '--status-fd=1', savefile, '-'] + ecode, out, err = gpg_run_command(gpgargs, stdin=payload) + os.unlink(savefile) + if ecode > 0: + print('PGP signature failed to verify') + print(err.decode()) + sys.exit(1) + output = out.decode() + # We're looking for GOODSIG and VALIDSIG + # For the purposes of this POC, we're not doing the following, but normally would: + # - check UIDs to make sure that they match From: + # - check signature date to make sure its drift from Date: + # - check TRUST_ to make sure it's sufficiently trusted key + gs_matches = re.search(r'^\[GNUPG:] GOODSIG ([0-9A-F]+)\s+(.*)$', output, re.M) + vs_matches = re.search(r'^\[GNUPG:] VALIDSIG ([0-9A-F]+) (\d{4}-\d{2}-\d{2}) (\d+)', output, re.M) + if gs_matches and vs_matches: + print('PGP signature verified: %s' % gs_matches.groups()[1]) + verify_attestation_hashes(msg) + + +def cmd_dk_sign(msg, domain='kernel.org', identity='@kernel.org', selector='patches', keyfile='dk.key', mode='dk'): + # selector is the same as in DKIM, the leftmost part of foo._domainkey.example.org + # identity should match domain in from + headers = list() + hhdr = gen_hashes_header(msg) + msg[XPH_HDR] = hhdr + hhname, hhval = dkim_canonicalize_header(XPH_HDR, hhdr.encode()) + headers.append(f'{hhname}:{hhval}') + signtime = str(int(time.time())) + + hparts = [ + f'm={mode}', + f'd={domain}', + f'i={identity}', + f's={selector}', + f't={signtime}', + 'a=ed25519-sha256', + 'b=', + ] + shname, shval = dkim_canonicalize_header(XPS_HDR, '; '.join(hparts)) + headers.append(f'{shname}:{shval}') + payload = '\r\n'.join(headers).encode() + hashed = hashlib.sha256() + hashed.update(payload) + try: + with open(keyfile, 'r') as fh: + sk = SigningKey(fh.read(), encoder=Base64Encoder) + except IOError: + print('Could not open %s' % keyfile) + sys.exit(1) + + bdata = sk.sign(hashed.digest(), encoder=Base64Encoder) + shval += bdata.decode() + shdr = email.header.make_header([(shval.encode(), 'us-ascii')], maxlinelen=78) + msg[XPS_HDR] = shdr + print(msg.as_string()) + + +def cmd_dk_verify(msg, mode='dk'): + shdr = msg.get(XPS_HDR) + sdata = get_parts_from_header(shdr) + headers = list() + hhname, hhval = dkim_canonicalize_header(XPH_HDR, str(msg.get(XPH_HDR))) + headers.append(f'{hhname}:{hhval}') + # Now we add the sig header itself, without b= content + shname, shval = dkim_canonicalize_header(XPS_HDR, shdr) + shval = shval.rsplit('; b=')[0] + '; b=' + headers.append(f'{shname}:{shval}') + payload = ('\r\n'.join(headers)).encode() + hashed = hashlib.sha256() + hashed.update(payload) + if mode == 'dk': + pk = get_dkim_key(sdata['d'], sdata['s'], wantkey='ed25519') + elif mode == 'wk': + pk = get_wk_key(sdata['d'], sdata['s']) + elif mode == 'wkd': + pk = get_wkd_key(sdata['d'], sdata['i'], sdata['s']) + else: + print(f'Unknown mode: {mode}') + sys.exit(1) + + mode = mode.upper() + + vk = VerifyKey(pk, encoder=Base64Encoder) + try: + foo = vk.verify(sdata['b'].encode(), encoder=Base64Encoder) + except BadSignatureError: + print(f'{mode} signature verification FAILED for: d={sdata["d"]}, i={sdata["i"]}, s={sdata["s"]}') + sys.exit(1) + if foo != hashed.digest(): + print(f'{mode} signature verification FAILED for: d={sdata["d"]}, i={sdata["i"]}, s={sdata["s"]}') + sys.exit(1) + + print(f'{mode} signature verified for: d={sdata["d"]}, i={sdata["i"]}, s={sdata["s"]}') + verify_attestation_hashes(msg) + + +def cmd_wk_sign(msg, domain='kernel.org', identity='@kernel.org', selector='patches', keyfile='dk.key'): + cmd_dk_sign(msg, domain=domain, identity=identity, selector=selector, keyfile=keyfile, mode='wk') + + +def cmd_wk_verify(msg): + cmd_dk_verify(msg, mode='wk') + + +def cmd_wkd_sign(msg, domain='kernel.org', identity='dev@kernel.org', selector='patches', keyfile='ingit.key'): + cmd_dk_sign(msg, domain=domain, identity=identity, selector=selector, keyfile=keyfile, mode='wkd') + + +def cmd_wkd_verify(msg): + cmd_dk_verify(msg, mode='wkd') + + +def cmd_verify(msg): + # do we have a hashes header? + if not msg.get(XPH_HDR): + print(f'Message does not contain {XPH_HDR}, nothing to verify') + sys.exit(1) + # do we have a sig header? + shdr = msg.get(XPS_HDR) + if not shdr: + if not msg.get('dkim-signature'): + print(f'Message contains unsigned hashes, cannot verify') + sys.exit(1) + # Run as a plain dkim verification + cmd_dkim_verify(msg) + sys.exit(0) + sdata = get_parts_from_header(shdr) + if sdata['m'] == 'pgp': + cmd_pgp_verify(msg) + sys.exit(0) + if sdata['m'] == 'dk': + cmd_dk_verify(msg) + sys.exit(0) + if sdata['m'] == 'wk': + cmd_wk_verify(msg) + sys.exit(0) + if sdata['m'] == 'wkd': + cmd_wkd_verify(msg) + sys.exit(0) + + print(f'Unknown mode: {sdata["m"]}') + sys.exit(1) + + +if __name__ == '__main__': + message = sys.stdin.buffer.read() + if not message: + print('Pass message on stdin') + sys.exit(1) + + orig_msg = email.message_from_bytes(message) + + commands = { + 'hashes-hdr': cmd_hashes_hdr, + 'dkim-sign': cmd_dkim_sign, + 'pgp-sign': cmd_pgp_sign, + 'dk-sign': cmd_dk_sign, + 'wk-sign': cmd_wk_sign, + 'wkd-sign': cmd_wkd_sign, + 'verify': cmd_verify, + } + + command = None + if len(sys.argv) > 1: + command = sys.argv[1] + + if command not in commands: + print(f'Unknown command: {command}') + print('Known commands:') + for goodcmd in commands.keys(): + print(f' {goodcmd}') + sys.exit(1) + + execfunc = commands[command] + execfunc(orig_msg)
diff --git a/mricon.asc b/mricon.asc new file mode 100644 index 0000000..6356e68 --- /dev/null +++ b/mricon.asc
@@ -0,0 +1,937 @@ +pub rsa4096 2011-11-07 [SC] + DE0E66E32F1FDD0902666B96E63EDCA9329DD07E +uid Konstantin Ryabitsev <konstantin@linuxfoundation.org> +uid Konstantin Ryabitsev <mricon@kernel.org> +uid Konstantin Ryabitsev (Fedora) <icon@fedoraproject.org> +uid [jpeg image of size 2774] +uid Konstantin Ryabitsev <icon@mricon.com> +uid Konstantin Ryabitsev <hbic@paranoidbeavers.ca> +sub rsa4096 2015-11-02 [A] + FFEB83BD26C4CF25DDA3C50E0BED129D9916360E +sub ed25519 2018-02-09 [S] + 76BE5DB25271E1481E678C35B6C41CE35664996C +sub cv25519 2018-05-02 [E] + 61ABADEB51C3EDAAB3C9599C86D203575A83079D +sub rsa2048 2018-05-02 [A] + 0BDF1F16FD674E43778C5C613FF293496E43D963 + +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +R6XmkhimLLeuARCBn9o6oYgspqvdTRIDsSZoMgBiQV8gZP6CZyssyYe1krV6Z83p +gIlgWsxzIu7CrUdyEHloB/MM/Fo5VRY4auCE8zzWEsLXsvpr847oXuILiBylMpdd +MaJcunyzwEtmFKXSmxvYPquIBZ9PKcvVACBG9R/p2nhDGn6Ra0oGbEeElb7n8Dp8 +hhL/GOUYsgBQ6XN8DOQxS+shSLoSMNNPeuOvChhXWt+/D9TBgp8cMXvbmEhY1HXL +dRAIJuY2ZjSyWfjJp2b83nfLinlQli620jyTLPtPRQINbn0ifIRjZR/MHTYSPHC/ +EgE0YbvphIAAaLz0QBHtDtaQJc1y/PE79XSz5XwExKKVXLcfiah+k8k2JgzRyinK +JwEQAAEBAAAAAAAAAAAAAAAA/9j/4AAQSkZJRgABAgAAAQABAAD/2wBDAAUDBAQE +AwUEBAQFBQUGBwwIBwcHBw8KCwkMEQ8SEhEPERATFhwXExQaFRARGCEYGhwdHx8f +ExciJCIeJBweHx7/2wBDAQUFBQcGBw4ICA4eFBEUHh4eHh4eHh4eHh4eHh4eHh4e +Hh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh7/wAARCABkAGQDASIAAhEB +AxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIE +AwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkK +FhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4 +eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT +1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAA +AAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdh +cRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZH +SElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOk +paanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3 ++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 +STfYtyTCEq8ry+8SIcviu57TEe+ONGBrAqyesTjQGXBtKTKLRlxcIMnhjB0RDlwg +DzAKhq6QhYr2hIS6ot7kfzobiSQB0rq4siyORESNpEvBZhXCXW0Q2cd2TWCouteC +W+FzukqiXVVnmVxf5RL3KhwA1KIqQ+RX6fwQRJJtDvwjKjtcXsH1Xc6YaG6gA+iy +hrwDxCjHvTNjp61MP2TSKjIL8uB+4npMVQeT7KvbmlFxPDKQOyQrIQNSGgw77z4N +46VebkcVN599VFyX2JKW9aZO01k9IdbkaJeBDnD+P8Q3d2op4cUXwIEMjwTNFJfX +oRw8e10XUST7ShKnsac2X1e98f5Vu7FqvSEg3V/Dle5Mn7fGqmfjm/AVu/iRaCi2 +9c5aqY44L6Os0Q/ZFkaJogtlyuM63H0WxNpGwVlq6EXI9RLFv4xhUqORKyCFs3ny +sngHM4sBBp66hFF/mlNWoKRSAobKXGCLobRZS29uc3RhbnRpbiBSeWFiaXRzZXYg +KExpbnV4Rm91bmRhdGlvbi5vcmcgZW1haWwgYWRkcmVzcykgPGtvbnN0YW50aW5A +bGludXhmb3VuZGF0aW9uLm9yZz6JAicEMAECABEFAlON4esKHQBEdXBsY2F0ZQAK +CRDmPtypMp3Qfj9ID/43HgJWx83R3spmufpl5vqpIUHK4uFeuzGfHDUl2TmheoXn +TbYb+qhqowmjAy4WcVzrcGjp8uJ3TxBr2xZTlMaRn4a/aVNORlV3hgM/nAk9RoA9 +wti3CaJ3GlRkx3w/qG9toznWSK4u5JnCzrcfBr/FKKCmw7oeGHBQkPnGfXJxjG+4 +Iuknn5sdV24k075wpXL4uZRsG3U/N0cPO8Nf/8YMzeVkiTmM3W6Zy7ubKl4RpizS +WnRaYl7zxJqQ5GxSK9PtyTPCHTikHFXABipRpIWGozS1McrUp1gAM3mQSoeL7qsx +foN0Zxn0WqQFqKCrAzcwsgbWRAMIuH2ndIeP0DET6fyFRYI/XTOF/Kda8XbqAqKk +yDqWiQJ2CUl146Whkdsa2M64BLr7VBhE7QTx7pjMyEISBc2weMSvrAaH9bNLSEH0 +GiSPFBTAo+DF4wr8Gy6E0bHZ/k5+MFpwPU5hgfi2Uflo2IhmwLOpXR1UvQKJ/OPs +VQNMePNx6ItJob24NjK+vXks81nLE36Tgknq4i8yp5Tf1ifWthdXYuAygxb0L4dV +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 +=ehTz +-----END PGP PUBLIC KEY BLOCK----- \ No newline at end of file
diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e04dbb7 --- /dev/null +++ b/requirements.txt
@@ -0,0 +1,7 @@ +b4~=0.5.2 +dkimpy~=1.0.5 +dnspython~=2.0.0 +pycryptodomex~=3.9.8 +PyNaCl~=1.4.0 +requests~=2.24.0 +anybase32~=1.1.0 \ No newline at end of file
diff --git a/rsa.key b/rsa.key new file mode 100644 index 0000000..044f9ac --- /dev/null +++ b/rsa.key
@@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAssS/M3aAZ4JxgAXtwLC/CTtKs33YfVQ3lL7jhS6r0PtCCSXu +oqmdmw8lHy34ivfCXBsToxEtkzLIn6jr4snryJr2VsbRvhTxnLW2fSUXXW+xrllU +rT4d/Bf/cB0h0kw92ZK/t43LUsOgd65e5Q2N08gYe0vJPtnHRo2y8k7bi89WcvAe ++KXG6t5/5+PHtUOAtzguWqCzOLNYpcvfLD8AIdES54Bi/oCGdf09pC944zWHC2cE +7Qs++VJbT27fhE58k0AKaBvltRmFoxifPAEzE0O54x9OchZHndnhSy5hr3aL1TYI +Ui9XhN9sj9zvKjppoMcvGO0Is2lhUtws2q25dwIDAQABAoIBAA+h+uJiM3pZwtki +K5dVHW+OOssVbzAOhEnCo5zK5wWAY1bvdT3OPVUI7wMZ/wkP/3QUfhQddXHQ2BB2 +MiKD69WAD5ipDEBmDnbYwRuSeceW89++OhRoQTEBXDoOoh2Ew0faeF9xy9zx9H9i +xTOcitGBRvrJNtEDNFTsIUDlOnewRXufiVwYwuFGfAVvxS9W6fLLgwjeChfaaPiV ++xQqDU5qF7Oh7Z9IX6o1/Zu/m6mKrzaVMt7rrsJszCsiMqwaQqrmbuo/04pwmkXD +aHwneAwj0BpxmQrEctL5IXVv2FFdYUkxjGoAN8F+MNjoAPHCwENMsY/9tbpOGuDo +eNC3FXkCgYEA3b5j3uYdAsKFcdEyeaTBRyzodCIBBATh/BKoVRZ2LLxkVdknaLT2 +XNbfHEYb46YVantO3k5FEtRVTs5VaXQD1LwTl1eXkrqUZf1jGrn3/L4EJt7C2vmj +pOTrZ1bavuZPZeXRjCP1fdiV0SjnXcsiOXjV1WrMu53g2w7vOBvU08sCgYEAzmLB +5h/t/O5C7jLBFxJV8dB3ZsMM/fWSKZADnaTPU5OM5S5vytbIypVwmRfNTLvWPUsm +sVucgp6ZJEV+gwyK2xGvm17Vc/ozb62sqXgTp+ZioPyw/QknkJFbRYgrLSl5OKuu +Yr06nts8xZDSMkfsuUnktw2d9/GU+qDd6jH284UCgYA1fxBTH0sSdmGBYwn9ZO0o +QcJW+jkqgg8PJGUuGfwqsMy4FWq3jSj+nuw2wwdJdbEm/la5tUJe15E5MPhUN6QQ +98r2MTClOpRAws/dC86zUBhqVEXIVH/RcVUFmmOtuJyhJb/XQnmggdcrHeYrr60z +Fl7oXRrFjMJJtyGpdLV03wKBgQDKjAV7kY6BElxBZTI3MFmEjnEAOyC/BIjDnYDO +7/ZBMaevLFmumghJOUxeEwv66MWjNePtX9lEH95vyHwWpPKJeNv9AZ8+ySg9zBaN +4zh3KRVWpWgVjSx1JxKKNM8a7X74bRUh9lBXoxYLVsvTaN8cITcDp6uGsGLjbYkc +1Jhl+QKBgQCkjtyZ1Hl7chpJh54MxAJO/T+h5M7kHM23J/7y/5P+PGAVMBsrmQZg +Onc4PjGDPjJD/XRlmOz6hiITDI51ycZe2oibdL0kWzkIZFwlx8RKqyS7OCGH56ms +iVe4QmrG0nldxdX8q+jFJpd/CejtyYOsFS2TdqRf9ekUHiovOrQwHg== +-----END RSA PRIVATE KEY-----
diff --git a/verify-all.sh b/verify-all.sh new file mode 100755 index 0000000..3e8595a --- /dev/null +++ b/verify-all.sh
@@ -0,0 +1,27 @@ +#!/bin/bash +# This assumes you already have the venv enabled +# If not: +# python3 -mvenv .venv +# source .venv/bin/activate +# pip install -r requirements.txt +echo "--------- UNHASHED (expected to fail) ---------" +./main.py verify < emails/unsigned.eml +echo "--------- UNSIGNED (expected to fail) ---------" +./main.py verify < emails/unsigned-with-hashes.eml +echo "--------- DKIM-SIGNED (all PASS) ---------" +./main.py verify < emails/korg-signed-dkim.eml +echo "--------- DKIM-SIGNED (with ML junk) ---------" +./main.py verify < emails/korg-signed-dkim-with-ml-junk.eml +echo "--------- DKIM-SIGNED (with edited subject, metadata will FAIL) ---------" +./main.py verify < emails/korg-signed-dkim-changed-subject.eml +echo "--------- DK-SIGNED (all PASS) ---------" +./main.py verify < emails/korg-signed-dk.eml +echo "--------- WK-SIGNED (all PASS) ---------" +./main.py verify < emails/korg-signed-wk.eml +echo "--------- PGP-SIGNED (by mricon, all PASS) ---------" +# This assumes you've imported mricon.asc into your keyring +./main.py verify < emails/mricon-signed-pgp.eml +echo "--------- WKD-SIGNED (by mricon, web lookup, all PASS) ---------" +./main.py verify < emails/mricon-signed-wkd.eml +echo "--------- WKD-SIGNED (by dev, stored in git, all PASS) ---------" +./main.py verify < emails/dev-signed-wkd-ingit.eml