Initial changes or the new iteration Significant rework of the proposal, which drops a lot of complexity. It is now simpler and a lot less dependent on the output of "git mailinfo" never changing (which was the part that I liked least of all). We lose some neat functionality, such as ability to track whether the change was in patch metadata, commit message, or patch itself, but on the upside we no longer have to parse the patch itself. This version also puts in-git key distribution at the center, because I believe the main difficulty with adopting developer attestation is in handling key distribution. If we borrow the idea of using git itself from did:git folks, then we sidestep a lot of complexity and reliance on external services. Dumber and simpler is always better than clever and more likely to fail, so I'm promoting this to "beta" and will work on library and b4 tooling next. Signed-off-by: Konstantin Ryabitsev <konstantin@linuxfoundation.org>
diff --git a/.keys/devkey/kernel.org/dev/patches.txt b/.keys/devkey/kernel.org/dev/patches.txt deleted file mode 100644 index bf3692b..0000000 --- a/.keys/devkey/kernel.org/dev/patches.txt +++ /dev/null
@@ -1 +0,0 @@ -JweccOuDZnENKbamn1QAN4tyvixYSQRl32WKmL7s1vI=
diff --git a/.keys/ed25519/example.org/dev/default b/.keys/ed25519/example.org/dev/default new file mode 100644 index 0000000..34a52db --- /dev/null +++ b/.keys/ed25519/example.org/dev/default
@@ -0,0 +1 @@ +4yjXNfrX1iJwtfUGC+fxrdMHCGxqptobTwrIe85Ss2I= \ No newline at end of file
diff --git a/.keys/ed25519/example.org/rev/20210101 b/.keys/ed25519/example.org/rev/20210101 new file mode 100644 index 0000000..cc6a3ec --- /dev/null +++ b/.keys/ed25519/example.org/rev/20210101
@@ -0,0 +1 @@ +fbsNqiGe7nDnZ+NiVkcXlu4eMALwD3MAfLJVAzAIgFc= \ No newline at end of file
diff --git a/.keys/openpgp/graphs/E63EDCA9329DD07E.svg b/.keys/openpgp/graphs/E63EDCA9329DD07E.svg deleted file mode 100644 index 1c50c80..0000000 --- a/.keys/openpgp/graphs/E63EDCA9329DD07E.svg +++ /dev/null
@@ -1,45 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" - "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<!-- Generated by graphviz version 2.40.1 (0) - --> -<!-- Title: G Pages: 1 --> -<svg width="216pt" height="166pt" - viewBox="0.00 0.00 216.00 166.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> -<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 162)"> -<title>G</title> -<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-162 212,-162 212,4 -4,4"/> -<g id="clust1" class="cluster"> -<title>cluster_toplevel</title> -<polygon fill="none" stroke="#ffffff" points="8,-81 8,-150 200,-150 200,-81 8,-81"/> -</g> -<!-- a_387 --> -<g id="node1" class="node"> -<title>a_387</title> -<path fill="none" stroke="#c0c0c0" d="M25,-.5C25,-.5 183,-.5 183,-.5 189,-.5 195,-6.5 195,-12.5 195,-12.5 195,-40.5 195,-40.5 195,-46.5 189,-52.5 183,-52.5 183,-52.5 25,-52.5 25,-52.5 19,-52.5 13,-46.5 13,-40.5 13,-40.5 13,-12.5 13,-12.5 13,-6.5 19,-.5 25,-.5"/> -<text text-anchor="middle" x="104" y="-39.7" font-family="droid sans,dejavu sans,helvetica" font-size="11.00" fill="#000000">Konstantin Ryabitsev</text> -<text text-anchor="middle" x="104" y="-27.7" font-family="droid sans,dejavu sans,helvetica" font-size="11.00" fill="#000000">linuxfoundation.org</text> -<polyline fill="none" stroke="#c0c0c0" points="13,-20.5 195,-20.5 "/> -<text text-anchor="middle" x="44.5" y="-7.7" font-family="droid sans,dejavu sans,helvetica" font-size="11.00" fill="#000000">RSA 4096</text> -<polyline fill="none" stroke="#c0c0c0" points="76,-.5 76,-20.5 "/> -<text text-anchor="middle" x="135.5" y="-7.7" font-family="droid sans,dejavu sans,helvetica" font-size="11.00" fill="#000000">E63EDCA9329DD07E</text> -</g> -<!-- a_211 --> -<g id="node2" class="node"> -<title>a_211</title> -<path fill="none" stroke="#c0c0c0" d="M28,-89.5C28,-89.5 180,-89.5 180,-89.5 186,-89.5 192,-95.5 192,-101.5 192,-101.5 192,-129.5 192,-129.5 192,-135.5 186,-141.5 180,-141.5 180,-141.5 28,-141.5 28,-141.5 22,-141.5 16,-135.5 16,-129.5 16,-129.5 16,-101.5 16,-101.5 16,-95.5 22,-89.5 28,-89.5"/> -<text text-anchor="middle" x="104" y="-128.7" font-family="droid sans,dejavu sans,helvetica" font-size="11.00" fill="#000000">Linus Torvalds</text> -<text text-anchor="middle" x="104" y="-116.7" font-family="droid sans,dejavu sans,helvetica" font-size="11.00" fill="#000000">kernel.org</text> -<polyline fill="none" stroke="#c0c0c0" points="16,-109.5 192,-109.5 "/> -<text text-anchor="middle" x="47.5" y="-96.7" font-family="droid sans,dejavu sans,helvetica" font-size="11.00" fill="#000000">RSA 2048</text> -<polyline fill="none" stroke="#c0c0c0" points="79,-89.5 79,-109.5 "/> -<text text-anchor="middle" x="135.5" y="-96.7" font-family="droid sans,dejavu sans,helvetica" font-size="11.00" fill="#000000">79BE3E4300411886</text> -</g> -<!-- a_211->a_387 --> -<g id="edge1" class="edge"> -<title>a_211->a_387</title> -<path fill="none" stroke="#000000" d="M104,-89.2784C104,-80.9495 104,-71.5865 104,-62.6839"/> -<polygon fill="#000000" stroke="#000000" points="107.5001,-62.5341 104,-52.5341 100.5001,-62.5342 107.5001,-62.5341"/> -</g> -</g> -</svg>
diff --git a/.keys/openpgp/keys/E63EDCA9329DD07E.asc b/.keys/openpgp/kernel.org/mricon/default similarity index 100% rename from .keys/openpgp/keys/E63EDCA9329DD07E.asc rename to .keys/openpgp/kernel.org/mricon/default
diff --git a/.keys/openpgp/pubring.kbx b/.keys/openpgp/pubring.kbx deleted file mode 100644 index 2a7c5ef..0000000 --- a/.keys/openpgp/pubring.kbx +++ /dev/null Binary files differ
diff --git a/README.rst b/README.rst index e036693..744405c 100644 --- a/README.rst +++ b/README.rst
@@ -1,7 +1,7 @@ Header-Based Patch Attestation ============================== Author: Konstantin Ryabitsev <konstantin@linuxfoundation.org> -Status: Alpha, soliciting comments +Status: Beta, soliciting comments Preamble -------- @@ -111,536 +111,277 @@ distributed code collaboration. It draws on the success of the DKIM standard in order to adapt (and adopt) it for this purpose. -Anatomy of an email patch -~~~~~~~~~~~~~~~~~~~~~~~~~ -A patch submitted via an RFC-2822 formatted message consists of the -following three significant parts: +X-Developer-Signature header +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +We largely take the DKIM standard and adopt it for developer attestation +signatures, with some steps taken to make the workflow fit better with +patches sent via mailing lists. - - *metadata*, which includes the Author, Email, Subject, and Date of - the submission - - *commit message*, which describes what the change is supposed to - accomplish - - *diff content*, which is structured data that should be applied - to the codebase in order to implement the changes proposed +Differences from DKIM: -Patch submissions also routinely provide additional content that may -have significance to the author or to the reviewer, but is not preserved -in the codebase after patches are applied, such as: + - the d= field is not used (no domain signatures involved) + - the q= field is not used (end-user tooling handles key lookup) + - the c= field is not used (git-mailinfo is used for canonicalization) + - the i= field is optional, but MUST be the canonical email address of + the sender, if not the same as the From: field - - information describing changes between revisions - - statistics about what files are changed (diffstat) - - structured data indicating tree dependencies (base-commit) - - author's signature and software version info - - mailing list subscription metadata - -Our goal is to provide attestation for the significant parts and ignore -the parts that are not preserved after code is committed to a git -repository. - -Three hashes per patch -~~~~~~~~~~~~~~~~~~~~~~ -Instead of creating a single attestation hash, we create a separate hash -for each meaningful part of the patch submission: - - - i: patch metadata - - m: commit message - - p: diff content - -This allows the person performing verification to identify which part of -the submission has been altered since being signed. A change to a commit -message may be explained by the addition of a ``Signed-off-by`` (or -similar) trailer, so the developer performing the review may ignore a -failure in the "m" hash if the other two hashes are passing. - -Similarly, a patch that goes through a chain of maintainers will -necessarily have its commit message modified by the inclusion of various -provenance trailers. Having a separate hash for the patch content and -patch metadata provides a way to track whether or not any of the -submaintainers made changes to the patch code, or just to the commit -message, as is generally expected. - -To generate the three parts, we rely on the ``git mailinfo`` command, -that does most of what we need:: - - git mailinfo m p > i < email.msg - -The above command will produce three files that closely match what we -are looking for, but require a bit of extra processing to remove content -that is likely to be altered in SMTP transmission. - -To get the "m" hash, we take the "m" file as-is:: - - sha256sum m - -To get the "i" hash, we remove the "Date" header from the output, -because it can be modified by git during format-patch or send-email -stages (or, infrequently, by SMTP relays). We only take the "Author", -"Email", and "Subject" headers:: - - egrep '^(Author|Email|Subject)' i | sha256sum - -The "p" file requires most work, as it contains data from the "below the -cut" portion of the commit message (usually, diffstat and revision -information), plus trailing content such as signatures or mailing list -subscription info. All of this is stripped away to leave just the diff -content. Unfortunately, there is no way to do it with git itself, so we -use manual parsing of the diff structure to perform this operation. - -Why not use git patch-id? -~~~~~~~~~~~~~~~~~~~~~~~~~ -Git provides a command to generate a "patch-id" that can be used to -quickly identify similar patches. To generate the patch-id hash, git -performs several canonicalization routines that make this hash -unsuitable for attestation purposes: - - - it collapses all repeating whitespace - - it removes all line numbers from diff contents - -It is possible for a malicious actor to create two patches that generate -identical patch-id hashes but have drastically different results when -applied to the codebase. For more info, see discussion here: - - - https://lore.kernel.org/git/20200210164115.x4gciujyjisivfgi@chatter.i7.local/ - -X-Patch-Hashes header -~~~~~~~~~~~~~~~~~~~~~ -After the i, m, p hashes are generated, we insert them into the email -message as a separate header. You can use the proof-of-concept code -included to generate one yourself:: - - $ ./main.py hashes-hdr - Using emails/unsigned.eml as message source - --- HEADER STARTS --- - X-Patch-Hashes: v=1; h=sha256; i=pkD5Pg8+cndZAzQQzo3RBSOOUzZM3GYWxiFIKFGIKe0=; - m=yW4TvC/DGWCUJTa11Aw1b/2ZAXobsLD45aLA/440yQI=; - p=iJdYN6+isP/3HmQaf1IiG7OfA1vzRxXlPGZtvecS484= - -Running POC code +Canonicalization ~~~~~~~~~~~~~~~~ -The POC code is written in Python and requires an extra set of libraries -in order to work. To get going, please do the following:: +We use the "relaxed/simple" canonicalization as defined by the DKIM +standard, but the message is first parsed by "git-mailinfo" in order to +achieve the following: + + - normalize any content-transfer-encoding modifications + - move any in-body git headers (From:, Subject: Date:) into the + message headers + - perform any subject-line normalization in order to strip content not + considered by git-am when applying the patch + +To achieve this, the message is passed through git-mailinfo with the +following flags:: + + cat orig.msg | git mailinfo --encoding=utf-8 m p > i + +We then use the data found in "i" to replace the From:, Subject: and +Date: headers of the original message, and concatenate "m" and "p" back +together to form the body of the message, which is normalized using CRLF +line endings and DKIM "simple" body canonicalization. + +Any other headers included in signing are canonicalized using the +"relaxed" header canonicalization routines defined in the DKIM standard. + +Algorithms +~~~~~~~~~~ +DKIM standard mostly relies on RSA signatures, though RFC 8463 extends +it to support ED25519 keys as well. Since this implementation is fully +backward compatible with the DKIM standard, it is possible to use any of +the DKIM-defined algorithms. For the purposes of this POC, we only +support the following two sign-hash algorithms: + + - ed25519-sha256: exactly as defined in RFC8463 + - openpgp-sha256: uses OpenPGP to create the signature + +POC code +-------- +The provided POC code in main.py is pretty feature-complete, though it +probably needs further improvements to properly deal with corner-cases. +You will notice that it's only a few hundred lines of Python code and +does not require any external libraries/programs except libsodium and +GnuPG for crypto and git for canonicalization. All of these are already +likely to be present on a developer's workstation. + +Running the code +~~~~~~~~~~~~~~~~ +The POC code is written in Python and requires PyNaCl libraries +in order to work. Chances are, PyNaCL is already installed on your +platform, but if it isn't, you can install it via a venv:: $ python3 -mvenv .venv $ source .venv/bin/activate $ pip install --upgrade pip $ pip install -r requirements.txt +Or you can achieve the same using OS packaging:: -Domain-level attestation ------------------------- -Once the X-Patch-Hashes header is generated and inserted into the email, -it will need to be signed in order to be useful for attestation -purposes. Adding domain-level signatures during SMTP processing is the -simplest way to accomplish this, as it would allow entire companies to -automatically attest all patches sent out via their infrastructure. + # dnf install python3-pynacl + # apt install python3-nacl -This can be easily done by introducing a patch-attestation milter that -would automatically analyze body contents and generate the -X-Patch-Hashes header if it finds that the message contains a patch -(unless this header is already present). This milter can then either -create its own cryptographic signature or let the usual DKIM-signing -infrastructure create the necessary attestation. +You should also have git and gpg available as external commands in your +PATH. -Using vanilla DKIM +ED25519 signatures ~~~~~~~~~~~~~~~~~~ -Vanilla DKIM is well-suited for this purpose, as it was specifically -created to sign email headers. The following changes will need to be -made to the configuration for it to be useful: +ED25519 is a "nothing up my sleeve" implementation of Elliptic-Curve +Cryptography (ECC) favoured by free software enthusiasts. Its primary +benefits are algorithmic speed of all crypto operations and relative +smallness of both public/private keys and generated signatures. - - add "x-patch-hashes" to the list of signed headers - - ensure that "sender" is not included - - potentially, exclude "subject" from the list of signed headers, in - order to hedge against mailing lists that add ``[topic]`` to all - email subjects +To sign an email using a bundled ed25519 key, run:: -Here's how it looks with the POC command, using the bundled rsa.key:: - - $ ./main.py sign-dkim - Signing: plain DKIM - Using emails/unsigned.eml as message source - Using rsa.key to sign - --- MESSAGE STARTS --- + $ ./main.py sign-ed25519 -k dev.key + SIGNING : ED25519 using dev.key + MSGSRC : emails/dev-unsigned.eml + --- SIGNED MESSAGE STARTS --- [...] - 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=example.org; - i=@example.org; q=dns/txt; s=patches; t=1600264001; h=from : date : - x-patch-hashes; bh=g2Sv1ZR+jIrWukzdXbqb+aeiqyFQOBLDQY6z0BBnGg4=; - b=pphhMzvqehfxDDLx/OqjbrP6HnMjhlklrQacWqwf5bpZ3cVZ00z5D+BcwpzsKnpQF7c7A - 2FmO6Mtjtn/lVRwppIF+tlph46sLE9XfdS+60X6Bzzxu1u/l0uieQ+cIT3DjUuejfxVpvIE - Zd4oAeVHD/OWRTJrWGYzrK3e+9UpIZJnxRkJLNj9OKOCwZDiGobM6+NusTWduqjYLRlMXXt - EvRbs8QXsTkoTttngM5DwSFRXC7zYSprKxbL6i/DdE+GM+iN2UQk10lpVfhYXtDBoKX1/vX - CXb77/X1ug1/ktfYU1xEDUU/NrovqnAfcJHCAL2lHomznoi/IYBC1qfR5t2w== + X-Developer-Signature: v=1; a=ed25519-sha256; h=from:subject:date:message-id; + l=1003; bh=Pfwl/zDlAoe9nkYNQPcgDFscfSQdrGvx4kAzrnQdNQ8=; + b=WyAu9nzYMUg2ntOfnvEBpa1vLQemK7axjAVu+hhYh6VyeFmB5jKzC2TcF+2IOjfG3eGl/XNY0EWc + HUh2tF02AQwiKDVDG7mTmP1/SPpNvotD0mTWQk6LyltWKFBUpRhn + +If you've ever seen email headers, you'll notice how very similar the +X-Developer-Signature is to the DKIM-Signature header. + +OpenPGP signatures +~~~~~~~~~~~~~~~~~~ +OpenPGP is not really an "algorithm," so this is merely an indicator +that the signature is created using an OpenPGP-compliant application. +Here it is in action, though you will need to use your own PGP key to +if you want to try it:: + + ./main.py -m emails/mricon-unsigned.eml sign-pgp -k B6C41CE35664996C + SIGNING : PGP using B6C41CE35664996C + MSGSRC : emails/mricon-unsigned.eml + --- SIGNED MESSAGE STARTS --- [...] + X-Developer-Signature: v=1; a=openpgp-sha256; h=from:subject:date:message-id; + l=1002; bh=g2Sv1ZR+jIrWukzdXbqb+aeiqyFQOBLDQY6z0BBnGg4=; + b=owGbwMvMwCG27YjM47CUmTmMp9WSGBK6vn316Z1bbjJ5DWNEgimHTc6Kx4HfTpzYcOzp9e/2jc/v + Lg7J7ChlYRDjYJAVU2Qp2xe7KajwoYdceo8pzBxWJpAhDFycAjCRBn5Ghrc/7otaV1yX6I4/sNf056 + vmzjen3bn2Rk8X9GTuZd2/aQ0jw7fZJ2Pi36/X2fTK4cSnX/++nbAzsm0TObX4SpbBsrRHe/gA -Note, that the b= value will be different for you since the timestamp is -included into the hashed content and will be different each time the -code runs. +OpenPGP supports ed25519 keys as well, so in reality the signature is +made with my own ed25519 subkey, but it is further wrapped in the +OpenPGP header data, which is why it is longer than the ed25519 +signature in the example above. It is created using the following GnuPG +parameters:: -This header was created by a generic DKIM implementation (dkimpy), -commonly used in production via the popular dkimpy-milter daemon. + gnupg -s -u KEYID < binary-hash-to-sign -This POC also includes a few example emails signed by the kernel.org DKIM -key. You can run the POC verification yourself:: +Distributing keys +----------------- +The difficult part of various PKI schemes is not really the +cryptography, but initial trust bootstrap and key distribution. In our +case, we sidestep trust bootstrap entirely and focus solely on developer +key distribution. We propose doing it via the git repository itself, +borrowing the idea from the people behind the did:git project. - $ ./main.py -m emails/korg-signed-dkim.eml verify - Using emails/korg-signed-dkim.eml as message source - Verifying: Plain DKIM - DNS-lookup: default._domainkey.kernel.org. - PASS : identity and domain match From header - PASS : time drift between Date and t (2 days, 23:24:18) - PASS : DKIM signature for d=kernel.org, s=default - ----- --------------- - PASS : metadata - PASS : commit message - PASS : diff content - ----- --------------- - PASS : All hashes verified +Using git to track contributor keys +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Consider the workflow of a Linux kernel subsystem maintainer. While a +single maintainer may receive patches from hundreds of people, they will +likely have a fairly small subset of developers with whom they +collaborate on an ongoing basis. As their relationship trust builds, the +maintainer may wish to implement an attestation mechanism to verify that +patches submitted by trusted lieutenants are not corrupted or modified +by malicious actors en-route. -As you can see, the verification steps will check several things: +The proposed POC offers several ways of achieving this: - - that the DKIM signature passes verification (this is done as - dictated by the RFC -- by normalizing and concatenating all signed - headers, plus the DKIM-signature header itself, minus the signature - content following b=) - - that the x-patch-hashes header is included in the content attested - by DKIM - - that the domain (d=) and identity (i=) values match what is in the - From: field of the email message - - that time drift between the Date header and the timestamp of the - signature is reasonable - - that all patch hashes that we generate match the hashes in the - signed header +- tracking the keys in a regular development branch +- tracking the keys in a special dedicated ref +- tracking the keys in a dedicated git repository -Note, that this check specifically excludes verifying the body hash -(bh=) value, for the reasons described in the previous section -concerning DKIM drawbacks. Also, since we excluded "subject" from the -list of signed headers, the verification will succeed even with usual -mailman-induced changes to the email content:: +Using the regular development branch +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Smaller projects with fewer contributors may simply choose to bundle +developer key distribution as part of its source code. The POC in +question uses the toplevel .keys directory as such location, with the +following structure:: - $ ./main.py -m emails/korg-signed-dkim-with-ml-junk.eml verify - Using emails/korg-signed-dkim-with-ml-junk.eml as message source - Verifying: Plain DKIM - DNS-lookup: default._domainkey.kernel.org. - PASS : identity and domain match From header - PASS : time drift between Date and t (2 days, 23:24:18) - PASS : DKIM signature for d=kernel.org, s=default - ----- --------------- - PASS : metadata - PASS : commit message - PASS : diff content - ----- --------------- - PASS : All hashes verified + .keys + \- sigtype + \- domain + \- local + \- selector -However, since we include the subject of the commit (as git sees it) -into the "i" hash, any changes to the subject header that aren't extra -prefixes like ``[topic]`` will result in verification failure:: +So, for a ed25519 signature from dev@example.org, the public key needed +for signature verification would be contained in:: - $ ./main.py -m emails/korg-signed-dkim-changed-subject.eml verify - Using emails/korg-signed-dkim-changed-subject.eml as message source - Verifying: Plain DKIM - DNS-lookup: default._domainkey.kernel.org. - PASS : identity and domain match From header - PASS : time drift between Date and t (2 days, 23:24:18) - PASS : DKIM signature for d=kernel.org, s=default - ----- --------------- - FAIL : metadata - PASS : commit message - PASS : diff content - ----- --------------- - FAIL : Some or all hashes failed verification + .keys + \- ed25519 + \- example.org + \- dev + \- default -Using the X-Patch-Sig header -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -There may be several reasons why you may not want to use DKIM for the -purpose of attesting the X-Patch-Hashes header: +The "default" filename is used when there is no other s= selector +specified in the signature header. - - you may not have sufficient control over the infrastructure - performing DKIM signing, for example if your company uses a - commercial upstream relayhost that performs DKIM signing for your - domain - - you may not want to exclude the "subject" header from your DKIM - configuration, as it reduces the overall scope of your email - attestation - - you may not want to rely on DNS for the purposes of public key - lookups, since DNS records are easily spoofed (and DNSSec adoption - is still very low) +NB: Since domain/local/selector values are taken from untrusted sources, +they should be urlencoded before attempting to locate the public key on +disk or via commands passed to "git show". -For these reasons, we also introduce a separate "X-Patch-Sig" header -that acts as a compatible subset of the DKIM RFC: +Using a dedicated ref +~~~~~~~~~~~~~~~~~~~~~ +In the case of the project the size of the Linux Kernel, it would be too +onerous to track the keys of contributors centrally, so individual +subsystem maintainers will likely want to track their own subsets of +keys from just the developers with whom they work on a regular basis. +Using a general development branch would be too inconvenient in this +case, since it would interfere with upstream work, so it makes sense to +use a separate branch for this purpose, e.g. "refs/heads/keys" that +contains just the keys directory with no other content. - - we only use the "x-patch-hashes" header, omitting the need for the - h= record, and always normalize it as "relaxed" - - we omit the bh= field entirely - - we omit the v= field, since we will rely on the v= value in the - X-Patch-Hashes header for versioning info - - we add the m= field to indicate the signature mode (dk, wk, pgp, - wkd, discussed below) - - for the purposes of the POC, we hardcode the algorithm to - ed25519-sha256, though other algorithms like rsa-sha256 or - rsa-sha512 can be easily implemented +Contributors can then still submit key additions and changes as regular +patches or pull requests and the maintainer merely needs to remember to +apply them to the proper branch. -The signature is generated in the exact same way as the DKIM signature, -by concatenating the x-patch-hashes header and the x-patch-sig header -(after normalizing them using the "relaxed" mode), obviously excluding -the content that follows b=. +Using a dedicated git repository +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Similarly, instead of using a dedicated branch, maintainers may choose +to use a wholly separate git repository for this purpose. This may be +useful if the same set of developers work on multiple repositories. -Here's the result of running the POC code, using the bundled dk.key:: +Key formats for ED25519 and OpenPGP +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The public keys should be in the following format: - $ ./main.py sign-dk - Signing: X-Patch-Sig header using dk mode - Using emails/unsigned.eml as message source - --- MESSAGE STARTS --- - [...] - 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=example.org; i=@example.org; s=patches; t=1600268242; - a=ed25519-sha256; - b=Ot3276T9ebQJ5Rzof7TNjz70IVpq9y/4ggevAO9iHVDg3P2tgBesuu2w/6mRIZ6m7mYuy22fNUW - 3hmxYCG9VCegq3sEw9y0B7Poj6fvA6ZBcza41HhCNxb5J44UFgnDM - [...] +- ed25519: base64-encoded string +- openpgp: any format that can be passed to "gpg --import", but + preferably an ascii-armored key export -DK Mode -~~~~~~~ -The DK mode is fully compatible with the DKIM standard and will perform -the exact same DNS query to look up the public key for the selector -specified:: +In the case of PGP signatures, the POC implementation will create a +temporary keyring containing just the imported key. - $ ./main.py -m emails/korg-signed-dk.eml verify - Using emails/korg-signed-dk.eml as message source - Verifying: X-Patch-Sig (mode=dk) - DNS-lookup: patches._domainkey.kernel.org. - PASS : identity and domain match From header - PASS : time drift between Date and t (4 days, 5:56:18) - PASS : mode=dk signature verified for: d=kernel.org, i=@kernel.org, s=patches - ----- --------------- - PASS : metadata - PASS : commit message - PASS : diff content - ----- --------------- - PASS : All hashes verified +Using the default GnuPG keyring +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +It is up to the implementation to fall back to the default GnuPG keyring +when checking openpgp signatures. The POC code will do so and will +additionally warn if the key has insufficient trust (this check is +meaningless for in-git bundled keys, so it is not performed). -WK Mode -~~~~~~~ -Instead of looking up the public key using DNS, we perform a HTTPS -lookup instead. This has the advantages of being more secure, but -requires caching, TTL expiration, and proxy configuration by the client, -plus is more fragile due to the less distributed nature of the web as -opposed to the distributed and fault-tolerant implementation of DNS. +Rotating and revoking keys +~~~~~~~~~~~~~~~~~~~~~~~~~~ +Keys can be retired or replaced at any time by merely changing it in the +repository, committing and pushing (or submitting a pull request/patch +with the change). Maintainers can then pull the change or apply the +patch and push the change to all other participating co-maintainers. -The query is performed to the domain name specified in the signature, -using the following rule:: +Contributors can have multiple valid keys if they properly specify the +selector when adding signatures -- or the verification tooling can +simply iterate through all keys listed in the directory for that +domain/local to find the matching one. - https://[domain]/.well-known/_domainkey/[selector].txt +Revoked keys can be simply deleted or moved into the revoked/ +subdirectory with perhaps an explanation why the key was revoked. -The contents of the txt file are the same as the contents of the TXT -record. We have it configured for kernel.org and you can perform a -verification lookup using the provided example:: +Verifying keys before accepting them +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +As stated earlier, bootstrapping trust remains a hard problem. We do not +aim to resolve it here and defer to the participating maintainers to +pick their key verification strategy, e.g.: - $ ./main.py -m emails/korg-signed-wk.eml verify - Using emails/korg-signed-wk.eml as message source - Verifying: X-Patch-Sig (mode=wk) - Retrieving: https://kernel.org/.well-known/_domainkey/patches.txt - PASS : identity and domain match From header - PASS : time drift between Date and t (4 days, 6:18:45) - PASS : mode=wk signature verified for: d=kernel.org, i=@kernel.org, s=patches - ----- --------------- - PASS : metadata - PASS : commit message - PASS : diff content - ----- --------------- - PASS : All hashes verified +- meeting up in person at a conference and exchanging keys +- holding a video session and reciting fingerprints (or entire keys, in + the case of ed25519) +- using an email round-trip as proof of key ownership -Developer-level attestation ---------------------------- -The domain-level attestation has significant advantages, but also -important drawbacks: +This can be as lax or as strict as maintainers choose. Obviously, if the +procedure is too lax, then the whole point of cryptographic attestation +becomes moot. - - advantage: it allows auto-enrolling entire companies, without the - need for individual developers to make any changes to their usual - routines - - advantage: it piggybacks on the existing DKIM standard, which has - a proven success record - - disadvantage: it requires changes to the IT infrastructure, including - adding a new milter daemon to the authenticated SMTP relay, which has - security and stability implications - - disadvantage: it requires explicit trust that the infrastructure - performing the hashing and signing has not been compromised by - malicious attackers - - disadvantage: it allows someone with access to a compromised account - to send out patches purporting to be coming from an official employee - of the company - - disadvantage: it is not useful to unaffiliated developers sending - patches from generic email addresses (gmail, yahoo, hotmail, etc). +Trusting the git repository +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Obviously, if keys are distributed via git, then one must trust git +itself and the commit provenance. This, again, is a "bootstrapping +trust" sort of problem that we promised to side-step, but we can at +least give the following recommendations: -These disadvantages can be mitigated by allowing individual developers -to provide their own signatures, using the "pgp" and "wkd" modes of the -X-Patch-Sig header. +- the person maintaining the keyring should PGP-sign all commits + modifying public key contents +- the repository itself should initially be cloned from trusted sources + over secure protocols -PGP mode -~~~~~~~~ -Many open-source projects already provide a mechanism for developers to -exchange and use PGP keys for the purposes of code attestation (e.g. via -signed git tags and git commits). We can easily use GnuPG to provide the -signature content of the X-Patch-Sig header. +We hope to provide a separate best-practices document aimed at keyring +maintainers, should this scheme become adopted. -Here is an example from the bundled emails/mricon-signed-pgp.eml:: +Automating patch attestation +---------------------------- +The git-send-email application supports executing a validation hook +before sending out patches. The attestation library should provide such +integration so that patches are automatically attested every time a +"git-send-email" is used. - 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= - -Since a lot of the attesting information is already embedded into the -PGP signature itself, the header structure is different from the "dk" or -"wk" mode: - - - we don't need to know the domain, since we won't be doing any - lookups on our own (GnuPG can handle this, if configured) - - the selector field identifies the public key ID of the certification - subkey, for ease of lookups - - the identity field is informational only, but can be used by GnuPG - to perform WKD lookups, if it matches the From header (not - implemented in the POC) - - the timestamp field is missing, since this data is embedded into the - PGP signature itself - -On the verification side, if the key specified by the selector is -already present in the verifier's default keyring, we will verify that -the signature is GOOD, VALID, and that it is either TRUST_FULLY or -TRUST_ULTIMATE. - -If the key is not present in the verifier's default keyring, the POC -will check if there is a matching entry in .keys/openpgp/keys/[keyid].asc, -and if so, will use .keys/openpgp/pubring.kbx for performing the -verification. In this case, TRUST_* fields are not used, as they will -always be "unknown". - -In-git key distribution is discussed further below. - -WKD mode (EXPERIMENTAL) -~~~~~~~~~~~~~~~~~~~~~~~ -I wanted to provide a way for developers to use a WK-like mode for -public key lookups as an alternative to PGP. The signature is generated -just like for the domain-level WK mode, using the ed25519 key provided -by each individual developer. - -Here's the POC running with the bundled "ingit.key":: - - $ ./main.py sign-wkd - Signing: X-Patch-Sig header using wkd mode - Using emails/unsigned.eml as message source - --- MESSAGE STARTS --- - [...] - 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=example.org; i=dev@kernel.org; s=patches; t=1600270651; - a=ed25519-sha256; - b=/s2WOrzK2tmqCYj3x22uck6Yi6V1ODX+PZiE2TLstSoVDGvTAaYoPZwmO7IKbUC148KEeGVXB0W - g+wGNtQn3AmUsvnoX0Jppqc5ei6GDzr0yMQKzEbUt0DkPrd/Y000b - [...] - -It is very similar to content created in the "dk" or "wk" mode, except -the identity field includes the entire email address of the developer. - -When we verify the attestation, we will do the following: - - - check if that key is available in .keys/devkey/[domain]/[local]/[selector].txt - - if it is not present, we perform a https query to - https://[domain]/.well-known/devkey/[zbase32-encoded-hash-of-local]/[selector].txt - -The hashing and zbase32-encoding is taken to be compatible with -openpgp's WKD implementation and is done to prevent someone from easily -finding out everyone's email addresses from unprotected directory -listings. - -You can run the verification using the POC example. Here's the run -without using the in-git matching key:: - - $ ./main.py -m emails/mricon-signed-wkd.eml verify - Using emails/mricon-signed-wkd.eml as message source - Verifying: X-Patch-Sig (mode=wkd) - Retrieving: https://kernel.org/.well-known/devkey/sapsizz4qsj4zmmscbz9f7y8cunt496y/patches.txt - PASS : identity and domain match From header - PASS : time drift between Date and t (4 days, 6:58:47) - PASS : mode=wkd signature verified for: d=kernel.org, i=mricon@kernel.org, s=patches - ----- --------------- - PASS : metadata - PASS : commit message - PASS : diff content - ----- --------------- - PASS : All hashes verified - -Here is the same, but using the public key provided in the git -repository itself:: - - $ ./main.py -m emails/dev-signed-wkd-ingit.eml verify - Using emails/dev-signed-wkd-ingit.eml as message source - Verifying: X-Patch-Sig (mode=wkd) - Loading: WKD key from /var/home/user/work/git/patch-attestation-poc/.keys/devkey/kernel.org/dev/patches.txt - PASS : identity and domain match From header - PASS : time drift between Date and t (4 days, 7:28:47) - PASS : mode=wkd signature verified for: d=kernel.org, i=dev@kernel.org, s=patches - ----- --------------- - PASS : metadata - PASS : commit message - PASS : diff content - ----- --------------- - PASS : All hashes verified - -The structure and nature of the WKD mechanism is entirely up for -discussion (along with everything else in this proposal). - -Automating developer attestation --------------------------------- -The easiest way to automate developer attestation is by providing a -sendmail-compatible "attest-and-send" utility that can be a drop-in -command settable via git's sendemail.smtpServer config setting. It would -be automatically invoked whenever git-send-email runs and would inject -the X-Patch-Hashes and X-Patch-Sig headers before sending the emails to -the SMTP server specified via the rest of the sendemail configuration -options. - -In addition to creating these headers, this tool can also automatically -add all emails going through it to the developer's personal public-inbox -archive that can act as a separate source of patch data in addition to -mail delivered via SMTP and mailing lists. - -Public keys bundled with git repos ----------------------------------- -Delegated trust is hard and securely bootstrapping your trusted -identities is even harder. There are existing proposals to include -developer keys as part of the git repository itself in order to make it -possible for someone to quickly bootstrap their keyring with trusted -identities. Obviously, this introduces a chicken-and-egg problem of -getting your source of trust from the thing you're trying to attest in -the first place. However, no mechanism short of in-person meetings is -able to provide perfect levels of assurance, so in-git key distribution -remains as good a source of bootstrap trust as any. - -The implementation in this POC is naive and shouldn't be used for -serious purposes. An emerging proposal like did:git -(https://github.com/dhuseby/did-git-spec/blob/master/did-git-spec.md) is -a more thoroughly considered approach and should probably be preferred. - -Where should verification be performed --------------------------------------- -Signature verification should be performed by the maintainer evaluating -the patches they received for inclusion into the git repository. The POC -already pulls in "b4" as a dependency for the patch hashing routines, -and I intend to add the header-based verification mechanisms in the -future release of b4, once this proposal is thoroughly discussed. - -Similarly, browser and other email client plugins can be written to -indicate to the developer whether the patches they are viewing pass -signature verification. If this proposal is adopted, we can come up with -implementations for Gmail, Mutt and Emacs, which should cover a -significant number of end-user tools. - +We aim to provide a lightweight attestation library for this purpose, as +well as implement all necessary verification routines in "b4" +client-side tooling used by many Linux developers for their patch +workflow.
diff --git a/dev.key b/dev.key new file mode 100644 index 0000000..78ebbe8 --- /dev/null +++ b/dev.key
@@ -0,0 +1 @@ +VFjCOik9b8shsk4NKYaQRERVKLoGLW+TVBxXmObp4kM= \ No newline at end of file
diff --git a/dk.key b/dk.key deleted file mode 100644 index bcae104..0000000 --- a/dk.key +++ /dev/null
@@ -1 +0,0 @@ -9FcEv0kKSZFagu06dp1FL1oe69XvJMzBQixRes+0cIg= \ No newline at end of file
diff --git a/emails/unsigned.eml b/emails/dev-signed-invalid.eml similarity index 73% copy from emails/unsigned.eml copy to emails/dev-signed-invalid.eml index a371cc3..e945b25 100644 --- a/emails/unsigned.eml +++ b/emails/dev-signed-invalid.eml
@@ -1,44 +1,47 @@ -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 - - +Return-Path: <SRS0=87nF=CT=vger.kernel.org=linux-kernel-owner@kernel.org> +From: Dev Eloper <dev@example.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-unsigned@example.org> +X-Mailer: git-send-email 2.25.4 +MIME-Version: 1.0 +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: 8bit +X-Developer-Signature: v=1; a=ed25519-sha256; h=from:subject:date:message-id; + l=1003; bh=Pfwl/zDlAoe9nkYNQPcgDFscfSQdrGvx4kAzrnQdNQ8=; + b=WyAu9nzYMUg2ntOfnvEBpa1vLQemK7axjAVu+hhYh6VyeFmB5jKzC2TcF+2IOjfG3eGl/XNY0EWc + HUh2tF02AQwiKDVDG7mTmP1/SPpNvotD0mTWQk6LyltWKFBUpRhn + +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@example.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_9BIT_SF, + ZYNQMP_DISP_AV_BUF_8BIT_SF, +-- +2.25.4 +
diff --git a/emails/korg-signed-dk.eml b/emails/dev-signed-with-ml-junk.eml similarity index 64% rename from emails/korg-signed-dk.eml rename to emails/dev-signed-with-ml-junk.eml index 0dea532..526debe 100644 --- a/emails/korg-signed-dk.eml +++ b/emails/dev-signed-with-ml-junk.eml
@@ -1,51 +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=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 - - +Return-Path: <SRS0=87nF=CT=vger.kernel.org=linux-kernel-owner@kernel.org> +From: Dev Eloper <dev@example.org> +To: <linux-kernel@vger.kernel.org> +Subject: [some-ml] [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-unsigned@example.org> +X-Mailer: git-send-email 2.25.4 +MIME-Version: 1.0 +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: 8bit +X-Developer-Signature: v=1; a=ed25519-sha256; h=from:subject:date:message-id; + l=1003; bh=Pfwl/zDlAoe9nkYNQPcgDFscfSQdrGvx4kAzrnQdNQ8=; + b=WyAu9nzYMUg2ntOfnvEBpa1vLQemK7axjAVu+hhYh6VyeFmB5jKzC2TcF+2IOjfG3eGl/XNY0EWc + HUh2tF02AQwiKDVDG7mTmP1/SPpNvotD0mTWQk6LyltWKFBUpRhn + +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@example.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 + + +_______________________________________________ +some-ml mailing list +some-ml@lists.example.org +https://lists.example.org/mailman/listinfo/some-ml
diff --git a/emails/dev-signed-wkd-ingit.eml b/emails/dev-signed-wkd-ingit.eml deleted file mode 100644 index 6873f18..0000000 --- a/emails/dev-signed-wkd-ingit.eml +++ /dev/null
@@ -1,52 +0,0 @@ -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/unsigned.eml b/emails/dev-signed.eml similarity index 75% copy from emails/unsigned.eml copy to emails/dev-signed.eml index a371cc3..b217285 100644 --- a/emails/unsigned.eml +++ b/emails/dev-signed.eml
@@ -1,44 +1,47 @@ -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 - - +Return-Path: <SRS0=87nF=CT=vger.kernel.org=linux-kernel-owner@kernel.org> +From: Dev Eloper <dev@example.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-unsigned@example.org> +X-Mailer: git-send-email 2.25.4 +MIME-Version: 1.0 +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: 8bit +X-Developer-Signature: v=1; a=ed25519-sha256; h=from:subject:date:message-id; + l=1003; bh=Pfwl/zDlAoe9nkYNQPcgDFscfSQdrGvx4kAzrnQdNQ8=; + b=WyAu9nzYMUg2ntOfnvEBpa1vLQemK7axjAVu+hhYh6VyeFmB5jKzC2TcF+2IOjfG3eGl/XNY0EWc + HUh2tF02AQwiKDVDG7mTmP1/SPpNvotD0mTWQk6LyltWKFBUpRhn + +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@example.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/dev-unsigned.eml similarity index 89% copy from emails/unsigned.eml copy to emails/dev-unsigned.eml index a371cc3..fa22c16 100644 --- a/emails/unsigned.eml +++ b/emails/dev-unsigned.eml
@@ -1,9 +1,9 @@ Return-Path: <SRS0=87nF=CT=vger.kernel.org=linux-kernel-owner@kernel.org> -From: Dev Eloper <dev@kernel.org> +From: Dev Eloper <dev@example.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> +Message-ID: <patch-attestation-examples-unsigned@example.org> X-Mailer: git-send-email 2.25.4 MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" @@ -16,7 +16,7 @@ 245 | static const u32 scaling_factors_666[] = { | ^~~~~~~~~~~~~~~~~~~ -Signed-off-by: Dev Eloper <dev@kernel.org> +Signed-off-by: Dev Eloper <dev@example.org> --- drivers/gpu/drm/xlnx/zynqmp_disp.c | 6 ------ 1 file changed, 6 deletions(-)
diff --git a/emails/korg-signed-dkim-changed-subject.eml b/emails/korg-signed-dkim-changed-subject.eml deleted file mode 100644 index 9fb267c..0000000 --- a/emails/korg-signed-dkim-changed-subject.eml +++ /dev/null
@@ -1,54 +0,0 @@ -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 deleted file mode 100644 index ec5c6f2..0000000 --- a/emails/korg-signed-dkim-with-ml-junk.eml +++ /dev/null
@@ -1,56 +0,0 @@ -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 deleted file mode 100644 index 628bf74..0000000 --- a/emails/korg-signed-dkim.eml +++ /dev/null
@@ -1,54 +0,0 @@ -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 deleted file mode 100644 index 48c512f..0000000 --- a/emails/korg-signed-wk.eml +++ /dev/null
@@ -1,51 +0,0 @@ -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-commit-message-modified.eml b/emails/mricon-signed-pgp-commit-message-modified.eml deleted file mode 100644 index 7a5c824..0000000 --- a/emails/mricon-signed-pgp-commit-message-modified.eml +++ /dev/null
@@ -1,55 +0,0 @@ -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": -xxx - -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-patch-modified.eml b/emails/mricon-signed-pgp-patch-modified.eml deleted file mode 100644 index e3a4c19..0000000 --- a/emails/mricon-signed-pgp-patch-modified.eml +++ /dev/null
@@ -1,54 +0,0 @@ -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, xxx - }; - --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 deleted file mode 100644 index ca38854..0000000 --- a/emails/mricon-signed-pgp.eml +++ /dev/null
@@ -1,54 +0,0 @@ -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-huge-drift.eml b/emails/mricon-signed-wkd-huge-drift.eml deleted file mode 100644 index a823a59..0000000 --- a/emails/mricon-signed-wkd-huge-drift.eml +++ /dev/null
@@ -1,52 +0,0 @@ -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: Wed, 01 Jul 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/mricon-signed-wkd.eml b/emails/mricon-signed-wkd.eml deleted file mode 100644 index 56d512c..0000000 --- a/emails/mricon-signed-wkd.eml +++ /dev/null
@@ -1,52 +0,0 @@ -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.eml b/emails/mricon-signed.eml similarity index 76% copy from emails/unsigned.eml copy to emails/mricon-signed.eml index a371cc3..1dbab79 100644 --- a/emails/unsigned.eml +++ b/emails/mricon-signed.eml
@@ -1,44 +1,49 @@ -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 - - +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 +MIME-Version: 1.0 +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: 8bit +X-Developer-Signature: v=1; a=openpgp-sha256; h=from:subject:date:message-id; + l=1002; bh=g2Sv1ZR+jIrWukzdXbqb+aeiqyFQOBLDQY6z0BBnGg4=; + b=owGbwMvMwCG27YjM47CUmTmMp9WSGBK6HqX59M4tN5m8hjEiwZTDJmfF48BvJ05sOPb0+nf7xud3 + F4dkdpSyMIhxMMiKKbKU7YvdFFT40EMuvccUZg4rE8gQBi5OAZiI+zVGhrN5zlGrfzm2Szwu1yrMOn + dXtCqXv9GD37Mub+KRL8XyKxj+5+1e6bXhatwym+6pUw5x7z4dE5l7yPJE+7GNPzY9a5fm4wUA + +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/mricon-unsigned.eml similarity index 96% rename from emails/unsigned.eml rename to emails/mricon-unsigned.eml index a371cc3..5a168d8 100644 --- a/emails/unsigned.eml +++ b/emails/mricon-unsigned.eml
@@ -1,5 +1,5 @@ Return-Path: <SRS0=87nF=CT=vger.kernel.org=linux-kernel-owner@kernel.org> -From: Dev Eloper <dev@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
diff --git a/emails/rev-signed.eml b/emails/rev-signed.eml new file mode 100644 index 0000000..386fbf3 --- /dev/null +++ b/emails/rev-signed.eml
@@ -0,0 +1,24 @@ +Return-Path: <SRS0=87nF=CT=vger.kernel.org=linux-kernel-owner@kernel.org> +From: Rev Ewer <rev@example.org> +To: <linux-kernel@vger.kernel.org> +Subject: Re: [PATCH] drm: xlnx: remove defined but not used 'scaling_factors_666' +Date: Sat, 12 Sep 2020 22:06:30 +0800 +Message-ID: <patch-attestation-examples-rev-unsigned@example.org> +X-Mailer: Mutt/1.2.x +MIME-Version: 1.0 +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: 8bit +X-Developer-Signature: v=1; a=ed25519-sha256; s=20210101; + h=from:subject:date:message-id; l=196; + bh=LLyXRoZEJJzwvGU7UuvMajjZMVZvUYKJdkM+qsRL7MI=; + b=nZMIxv2NXSWs3o/MzFGSCQHKYerkrUHhDvlpxbf796NXwK8h9sABkGT+OASxSujxh4UJ1uCPHicO + 1AhPu18FBdSV6ylTJoqfECNMZWlGNI17ICn3JTA92vOJEq51MSP7 + +On Thu, 11 Sep 2020 22:06:30 +0800 you wrote: +> This addresses the following gcc warning with "make W=1": + +Reviewed-By: Rev Ewer <rev@example.org> + +-- +Rev Ewer +Managementy Solutions, Inc
diff --git a/emails/rev-unsigned.eml b/emails/rev-unsigned.eml new file mode 100644 index 0000000..f61ae7a --- /dev/null +++ b/emails/rev-unsigned.eml
@@ -0,0 +1,19 @@ +Return-Path: <SRS0=87nF=CT=vger.kernel.org=linux-kernel-owner@kernel.org> +From: Rev Ewer <rev@example.org> +To: <linux-kernel@vger.kernel.org> +Subject: Re: [PATCH] drm: xlnx: remove defined but not used 'scaling_factors_666' +Date: Sat, 12 Sep 2020 22:06:30 +0800 +Message-ID: <patch-attestation-examples-rev-unsigned@example.org> +X-Mailer: Mutt/1.2.x +MIME-Version: 1.0 +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: 8bit + +On Thu, 11 Sep 2020 22:06:30 +0800 you wrote: +> This addresses the following gcc warning with "make W=1": + +Reviewed-By: Rev Ewer <rev@example.org> + +-- +Rev Ewer +Managementy Solutions, Inc
diff --git a/emails/unsigned-with-hashes.eml b/emails/unsigned-with-hashes.eml deleted file mode 100644 index 61b4882..0000000 --- a/emails/unsigned-with-hashes.eml +++ /dev/null
@@ -1,48 +0,0 @@ -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/ingit.key b/ingit.key deleted file mode 100644 index 14a17e2..0000000 --- a/ingit.key +++ /dev/null
@@ -1 +0,0 @@ -KvYqVCPKGQfyg1eacwoKJsH268K2rfxRTPHpbg8LIos= \ No newline at end of file
diff --git a/main.py b/main.py index c160859..d12844c 100755 --- a/main.py +++ b/main.py
@@ -1,43 +1,22 @@ #!/usr/bin/env python3 -# Copyright (C) 2020 by the Linux Foundation +# Copyright (C) 2020-2021 by the Linux Foundation # SPDX-License-Identifier: MIT-0 import sys import os import base64 -import email -import email.header import email.utils -import b4 -import time -import dkim import re -import dns.resolver -import binascii import subprocess import hashlib -import requests -import anybase32 import urllib.parse import logging -import datetime -from nacl.signing import SigningKey, VerifyKey -from nacl.encoding import Base64Encoder -from nacl.exceptions import BadSignatureError +import tempfile -from tempfile import mkstemp +from typing import Tuple, Optional -from Cryptodome.Signature import pkcs1_15 -from Cryptodome.Hash import SHA256 -from Cryptodome.PublicKey import RSA - -from typing import Tuple - -XPH_HDR = 'X-Patch-Hashes' -XPS_HDR = 'X-Patch-Sig' - -# For POC purposes, we hardcode maximum drift to 30 days -MAXDRIFT = datetime.timedelta(days=30) +DEVSIG_HDR = b'X-Developer-Signature' +REQ_HDRS = [b'from', b'subject', b'date', b'message-id'] logger = logging.getLogger(__name__) @@ -54,14 +33,117 @@ return _run_command(cmdargs, stdin) -def load_message(msgfile: str): +def check_gpg_status(status: bytes) -> Tuple[bool, bool, bool]: + good = False + valid = False + trusted = False + + gs_matches = re.search(rb'^\[GNUPG:] GOODSIG ([0-9A-F]+)\s+(.*)$', status, flags=re.M) + if gs_matches: + good = True + vs_matches = re.search(rb'^\[GNUPG:] VALIDSIG ([0-9A-F]+) (\d{4}-\d{2}-\d{2}) (\d+)', status, flags=re.M) + if vs_matches: + valid = True + ts_matches = re.search(rb'^\[GNUPG:] TRUST_(FULLY|ULTIMATE)', status, flags=re.M) + if ts_matches: + trusted = True + + return good, valid, trusted + + +def get_git_mailinfo(payload: bytes) -> Tuple[bytes, bytes, bytes]: + with tempfile.TemporaryDirectory(suffix='.git-mailinfo') as td: + mf = os.path.join(td, 'm') + pf = os.path.join(td, 'p') + cmdargs = ['git', 'mailinfo', '--encoding=utf-8', mf, pf] + ecode, out, err = _run_command(cmdargs, stdin=payload) + if ecode > 0: + logger.critical('FAILED : Failed running git-mailinfo:') + logger.critical(err.decode()) + sys.exit(1) + with open(mf, 'rb') as mfh: + m = mfh.read() + with open(pf, 'rb') as pfh: + p = pfh.read() + return m, p, out + + +def load_message(msgfile: str) -> Tuple[list, bytes]: + # we don't use python's email message because we don't want any processing + # done on the contents that may result in a wrong hash being generated + headers = list() + payload = list() with open(msgfile, 'rb') as fh: - logger.info('Using %s as message source', msgfile) - contents = fh.read() - return email.message_from_bytes(contents) + logger.info('MSGSRC : %s', msgfile) + in_payload = False + while True: + line = fh.readline() + if not line: + break + # strip any trailing CRLF + line = re.sub(rb'[\r\n]*$', b'', line) + if in_payload: + payload.append(line) + continue + + if not len(line): + in_payload = True + continue + + # is it a wrapped header? + if line[0] in ("\x09", "\x20", 0x09, 0x20): + if not len(headers): + # What? + logger.critical('Not valid RFC2822 message') + sys.exit(1) + # attach it to the last header + headers[-1] += b'\r\n' + line + continue + headers.append(line) + + return headers, b'\r\n'.join(payload) + b'\r\n' -def splitter(longstr: str, limit: int = 77) -> str: +def get_mailinfo_message(oheaders: list, opayload: bytes, want_hdrs: list, maxlen: Optional[int]) -> Tuple[list, bytes]: + # We pre-canonicalize using git mailinfo + origmsg = b'\r\n'.join(oheaders) + b'\r\n\r\n' + opayload + m, p, i = get_git_mailinfo(origmsg) + # we don't use python's email message because we don't want any processing + # done on the contents that may result in a wrong hash being generated + # Generate a new payload using m and p and canonicalize with \r\n endings, + # trimming any excess blank lines ("simple" DKIM canonicalization). + cpayload = b'' + for line in re.sub(rb'[\r\n]*$', b'', m + p).split(b'\n'): + cpayload += re.sub(rb'[\r\n]*$', b'', line) + b'\r\n' + + if maxlen: + logger.debug('Limiting payload length to %d bytes', maxlen) + cpayload = cpayload[:maxlen] + + idata = dict() + for line in re.sub(rb'[\r\n]*$', b'', i).split(b'\n'): + left, right = line.split(b':', 1) + idata[left.lower()] = right.strip() + + # Now substituting headers returned by mailinfo + cheaders = list() + for oheader in oheaders: + left, right = oheader.split(b':', 1) + lleft = left.lower() + if lleft not in want_hdrs: + continue + if lleft == b'from': + right = b' ' + idata.get(b'author', b'') + b' <' + idata.get(b'email', b'') + b'>' + elif lleft == b'subject': + right = b' ' + idata.get(b'subject', b'') + elif lleft == b'date': + right = b' ' + idata.get(b'date', b'') + cheaders.append(left + b':' + right) + + return cheaders, cpayload + + +def splitter(longstr: bytes, limit: int = 78) -> bytes: splitstr = list() first = True while len(longstr) > limit: @@ -72,72 +154,29 @@ splitstr.append(longstr[:at]) longstr = longstr[at:] splitstr.append(longstr) - return ' '.join(splitstr) + return b' '.join(splitstr) -def verify_identity_domain(msg, identity: str, domain: str) -> bool: - # Domain is supposed to be present in identity - if not identity.endswith(domain): - logger.critical('FAIL : domain (d=%s) is not in identity (i=%s)', domain, identity) - return False - fromeml = email.utils.getaddresses(msg.get_all('from', []))[0][1] - if identity.find('@') < 0: - logger.critical('FAIL : identity must contain @ (i=%s)', identity) - return False - ilocal, idomain = identity.split('@') - # identity is supposed to be present in from - if not fromeml.endswith(f'@{idomain}'): - logger.critical('FAIL : identity (i=%s) does not match from (from=%s)', identity, fromeml) - return False - logger.info('PASS : identity and domain match From header') - return True +def folder(longhdr: bytes, limit: int = 78) -> bytes: + lines = list() + line = b'' + for chunk in longhdr.split(b' '): + if len(line + chunk) > limit: + lines.append(line) + line = b'' + if len(chunk) > limit: + # the chunk itself is longer than limit, so append it as-is + lines.append(b' ' + chunk) + continue + if not len(lines) and not len(line): + # We're at the very start, so no need to prepend with ' ' + line += chunk + else: + line += b' ' + chunk + if len(line): + lines.append(line) - -def verify_time_drift(msg, timestamp: str) -> bool: - msgdt = email.utils.parsedate_to_datetime(str(msg['Date'])) - sigdt = datetime.datetime.utcfromtimestamp(int(timestamp)).replace(tzinfo=datetime.timezone.utc) - sdrift = sigdt - msgdt - if sdrift > MAXDRIFT: - logger.critical('FAIL : time drift between Date and t too great (%s)', sdrift) - return False - logger.info('PASS : time drift between Date and t (%s)', sdrift) - return True - - -def get_dkim_key(domain: str, selector: str, wantkey: str = 'rsa', timeout: int = 5) -> str: - name = f'{selector}._domainkey.{domain}.' - logger.info('DNS-lookup: %s', 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: - logger.critical('Domain %s does not exist', name) - sys.exit(1) - pass - - if not keydata: - logger.critical('Domain %s does not contain a DKIM record', name) - sys.exit(1) - - parts = get_parts_from_header(keydata) - if 'p' not in parts: - logger.critical('Domain %s does not contain a DKIM key', name) - sys.exit(1) - - return parts['p'] + return b'\r\n'.join(lines) def get_git_toplevel(gitdir: str = None) -> str: @@ -151,359 +190,215 @@ return '' -def get_wk_key(domain: str, selector: str, timeout: int = 5) -> str: - wkurl = f'https://{domain}/.well-known/_domainkey/{selector}.txt' - logger.info('Retrieving: %s', wkurl) - res = requests.get(wkurl, timeout=timeout) - if res.status_code != 200: - logger.info('Could not retrieve %s: %s', wkurl, res.status_code) - sys.exit(1) - keydata = res.content.decode().strip() - logger.debug('keydata: %s', keydata) - parts = get_parts_from_header(keydata) - return parts['p'] - - -def get_wkd_key(domain: str, identity: str, selector: str, timeout: int = 5) -> str: - identity = identity.split('@')[0] - # Attempt to load from local git dir if we are in a git dir - gittop = get_git_toplevel() - if gittop: - # urlencode domain/identity/selector to make sure nobody tries path-based badness - subpath = os.path.join(gittop, '.keys', 'devkey', - urllib.parse.quote_plus(domain), - urllib.parse.quote_plus(identity), - urllib.parse.quote_plus(selector) + '.txt', - ) - try: - with open(subpath) as fh: - logger.info('Loading: WKD key from %s', 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, if only because - # it has a swear word to my account record. - i = hashlib.sha1(identity.lower().encode()).digest() - zdir = anybase32.encode(i, anybase32.ZBASE32).decode() - wkurl = f'https://{domain}/.well-known/devkey/{zdir}/{selector}.txt' - logger.info('Retrieving: %s', wkurl) - res = requests.get(wkurl, timeout=timeout) - if res.status_code != 200: - logger.critical('Could not get %s: %s', wkurl, res.status_code) - 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) -> Tuple[str, str, str]: - # 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: str) -> dict: - hstr = re.sub(r'\s*', '', hstr) +def get_parts_from_header(hval: bytes) -> dict: + hval = re.sub(rb'\s*', b'', hval) hdata = dict() - for chunk in hstr.split(';'): - parts = chunk.split('=', 1) + for chunk in hval.split(b';'): + parts = chunk.split(b'=', 1) if len(parts) < 2: continue - hdata[parts[0]] = parts[1] + hdata[parts[0].decode()] = parts[1] return hdata -def dkim_canonicalize_header(hname: str, hval: str) -> Tuple[str, str]: - hname = hname.lower() - hval = hval.strip() - hval = re.sub(r'\n', '', hval) - hval = re.sub(r'\s+', ' ', hval) - return hname, hval +def dkim_canonicalize_header(hval: bytes) -> bytes: + # We only do relaxed for headers + # o Unfold all header field continuation lines as described in + # [RFC5322]; in particular, lines with terminators embedded in + # continued header field values (that is, CRLF sequences followed by + # WSP) MUST be interpreted without the CRLF. Implementations MUST + # NOT remove the CRLF at the end of the header field value. + hval = re.sub(rb'[\r\n]', b'', hval) + # o Convert all sequences of one or more WSP characters to a single SP + # character. WSP characters here include those before and after a + # line folding boundary. + hval = re.sub(rb'\s+', b' ', hval) + # o Delete all WSP characters at the end of each unfolded header field + # value. + # o Delete any WSP characters remaining before and after the colon + # separating the header field name from the header field value. The + # colon separator MUST be retained. + hval = hval.strip() + b'\r\n' + return hval -def verify_attestation_hashes(msg) -> bool: - 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) - verified = True - logger.info('----- ---------------') - for part, what in desc.items(): - if hdata[part] == adata[part]: - status = 'PASS' - else: - verified = False - status = 'FAIL' - logger.info('%s : %s', status, desc[part]) - logger.info('----- ---------------') - if verified: - logger.info('PASS : All hashes verified') - else: - logger.info('FAIL : Some or all hashes failed verification') - - return verified +def dkim_canonicalize_body(body: bytes) -> bytes: + # We only do simple for body (relaxed is unsuitable for patches), + # so we just replace all trailing blank lines with a single CRLF + body = re.sub(rb'[\r\n]*$', b'', body) + b'\r\n' + return body -def gpg_verify(smsg: bytes, dsig: bytes, keyid: str) -> bool: - # 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(dsig) - vrfyargs = ['--verify', '--status-fd=1', savefile, '-'] - # Do we have this key in our default keyring? - pubring = None - ecode, out, err = gpg_run_command(['--list-key', keyid]) - if ecode > 0: - # See if it's in git itself +def get_public_key(source: str, keytype: str, identity: str, selector: str) -> Optional[bytes]: + chunks = identity.split('@', 1) + if len(chunks) != 2: + logger.critical('identity must include both local and domain parts') + sys.exit(1) + local = chunks[0] + domain = chunks[1] + # urlencode all potentially untrusted bits to make sure nobody tries path-based badness + keypath = os.path.join(urllib.parse.quote_plus(keytype), urllib.parse.quote_plus(domain), + urllib.parse.quote_plus(local), urllib.parse.quote_plus(selector)) + + if source.find('ref:') == 0: gittop = get_git_toplevel() - if gittop: - # Do we have that key in git? - # URLencode keyid to avoid path-based badness - if os.path.exists( - os.path.join(gittop, '.keys', 'openpgp', 'keys', urllib.parse.quote_plus(keyid) + '.asc')): - pubring = os.path.join(gittop, '.keys', 'openpgp', 'pubring.kbx') - if pubring and os.path.exists(pubring): - logger.info('Loading: in-git pubring: %s', pubring) - gpgargs = ['--no-default-keyring', '--keyring', pubring] + vrfyargs + if not gittop: + logger.critical('Not in a git tree, so cannot use a ref: source') + sys.exit(1) + # format is: ref:refspec:path + # or it could omit the refspec, meaning "whatever the current ref" + # but it should always have at least two ":" + chunks = source.split(':', 2) + if len(chunks) < 3: + logger.critical('Invalid source: %s', source) + logger.critical('Must have refspec and path, e.g.: ref:refs/heads/master:.keys') + # grab the key from a fully ref'ed path + ref = chunks[1] + pathtop = chunks[2] + subpath = os.path.join(pathtop, keypath) + + if not ref: + # What is our current ref? + cmdargs = ['git', 'symbolic-ref', 'HEAD'] + ecode, out, err = _run_command(cmdargs) + if ecode == 0: + ref = out.decode().strip() + + cmdargs = ['git'] + cmdargs += ['show', f'{ref}:{subpath}'] + ecode, out, err = _run_command(cmdargs) + if ecode == 0: + logger.info('KEYSRC : %s:%s', ref, subpath) + return out + # Does it exist on disk in gittop? + fullpath = os.path.join(gittop, subpath) + if os.path.exists(fullpath): + with open(fullpath, 'rb') as fh: + logger.info('KEYSRC : %s', fullpath) + return fh.read() + + logger.info('Could not find %s in %s', subpath, ref) + # This is not a critical error for PGP + return None + + # It's a direct path, then + fullpath = os.path.join(source, keypath) + if os.path.exists(fullpath): + with open(fullpath, 'rb') as fh: + logger.info('Loaded key from %s', fullpath) + return fh.read() + + # This is not a critical error for PGP + logger.info('Could not find %s', fullpath) + return None + + +def make_devsig_header(headers: list, payload: bytes, algo: str, identity: Optional[str] = None, + selector: Optional[str] = None, maxlen: Optional[int] = None, + want_hdrs: Optional[list] = None) -> Tuple[bytes, bytes]: + if not want_hdrs: + want_hdrs = REQ_HDRS + cheaders, cpayload = get_mailinfo_message(headers, payload, want_hdrs, maxlen) + hashed = hashlib.sha256() + hashed.update(cpayload) + bh = base64.b64encode(hashed.digest()) + hparts = [ + b'v=1', + b'a=%s-sha256' % algo.encode(), + ] + if identity: + hparts.append(b'i=%s' % identity.encode()) + if selector: + hparts.append(b's=%s' % selector.encode()) + hparts.append(b'h=%s' % b':'.join(want_hdrs)) + hparts.append(b'l=%d' % len(cpayload)) + hparts.append(b'bh=%s' % bh) + hparts.append(b'b=') + dshval = b'; '.join(hparts) + + hashed = hashlib.sha256() + for cheader in cheaders: + left, right = cheader.split(b':', 1) + hname = left.strip().lower() + if hname not in want_hdrs: + continue + + hashed.update(hname + b':' + dkim_canonicalize_header(right)) + hashed.update(DEVSIG_HDR.lower() + b':' + dshval) + dshdr = DEVSIG_HDR + b': ' + dshval + + return dshdr, hashed.digest() + + +def get_devsig_header_info(headers) -> Tuple[str, str, str, list, dict]: + from_hdr = None + hdata = None + need_hdrs = [b'from', DEVSIG_HDR.lower()] + for header in headers: + left, right = header.split(b':', 1) + hname = left.strip().lower() + # We want a "from" header and a DEVSIG_HDR + if hname not in need_hdrs: + continue + if hname == b'from': + from_hdr = right + continue + hval = dkim_canonicalize_header(right) + hdata = get_parts_from_header(hval) + + if hdata is None: + logger.critical('FAILED : No "%s:" header in message', DEVSIG_HDR.decode()) + sys.exit(1) + + # make sure the required headers are in the sig + if 'h' not in hdata: + logger.critical('FAILED : h= is required but is not present in %s', DEVSIG_HDR) + sys.exit(1) + + signed_hdrs = [x.strip() for x in hdata['h'].split(b':')] + for rhdr in REQ_HDRS: + if rhdr not in signed_hdrs: + logger.critical('FAILED : %s is a required header', rhdr.decode()) + sys.exit(1) + + if 'i' not in hdata: + # Use the identity from the from header + if not from_hdr: + logger.critical('FAILED : No i= in %s, and no From: header!', DEVSIG_HDR) + sys.exit(1) + parts = email.utils.parseaddr(from_hdr.decode()) + identity = parts[1] + else: + identity = hdata['i'] + + if 'a' in hdata: + apart = hdata['a'].decode() + if apart.startswith('ed25519'): + algo = 'ed25519' + elif apart.startswith('openpgp'): + algo = 'openpgp' else: - logger.critical('Unable to find key %s', keyid) + logger.critical('FAILED : Unsupported a= in %s: %s', DEVSIG_HDR, apart) sys.exit(1) else: - gpgargs = vrfyargs - ecode, out, err = gpg_run_command(gpgargs, stdin=smsg) - os.unlink(savefile) - if ecode > 0: - logger.critical('PGP signature failed to verify') - logger.critical(err.decode()) - return False - 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 for its drift from Date: - 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: - signer = gs_matches.groups()[1] - if not pubring: - # If we're not using an in-git pubring, also check TRUST_* output - ts_matches = re.search(r'^\[GNUPG:] TRUST_(FULLY|ULTIMATE)', output, re.M) - if not ts_matches: - logger.critical('Insufficient TRUST on: %s', signer) - return False + # Default is ed25519-sha256 + algo = 'ed25519' - logger.info('PGP signature verified: %s', signer) - return True - - # Theoretically, this would have resulted in ecode > 0 - logger.critical('PGP signature failed to verify') - logger.critical(err.decode()) - return False - - -def cmd_hashes_hdr(cmdargs) -> None: - msg = load_message(cmdargs.message) - hhdr = gen_hashes_header(msg) - logger.info('--- HEADER STARTS ---') - sys.stdout.buffer.write(XPH_HDR.encode() + b': ' + hhdr.encode().encode() + b'\r\n') - - -def cmd_sign_dkim(cmdargs) -> None: - logger.info('Signing: plain DKIM') - msg = load_message(cmdargs.message) - # 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) - domain = cmdargs.domain.encode() - selector = cmdargs.selector.encode() - identity = cmdargs.identity.encode() - include_headers = [b'from', b'date', b'x-patch-hashes'] - - with open(cmdargs.privkey, 'rb') as fh: - logger.info('Using %s to sign', cmdargs.privkey) - privkey = fh.read() - - dk = dkim.DKIM(msg.as_bytes()) - bhdr = dk.sign(selector, domain, privkey, identity=identity, include_headers=include_headers) - dhdr = bhdr.decode() - msg['DKIM-Signature'] = dhdr.split(':', 1)[1] - logger.info('--- MESSAGE STARTS ---') - sys.stdout.buffer.write(msg.as_bytes()) - - -def cmd_verify_dkim(msg) -> None: - logger.info('Verifying: Plain DKIM') - # 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) - # Make sure the x-patch-hashes header is included - included = ddata['h'].split(':') - if XPH_HDR.lower() not in included: - logger.critical('%s is not included in signed headers, unable to verify!', XPH_HDR) - sys.exit(1) - 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): - logger.critical('FAIL: The DKIM signature did NOT verify!') - sys.exit(1) - if not verify_identity_domain(msg, ddata['i'], ddata['d']): - sys.exit(1) - if not verify_time_drift(msg, ddata['t']): - sys.exit(1) - logger.info('PASS : DKIM signature for d=%s, s=%s', ddata['d'], ddata['s']) - verify_attestation_hashes(msg) - - -def cmd_sign_pgp(cmdargs) -> None: - logger.info('Signing: PGP') - msg = load_message(cmdargs.message) - # 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) - msg[XPH_HDR] = hhdr - hhname, hhval = dkim_canonicalize_header(XPH_HDR, hhdr.encode()) - headers.append(f'{hhname}:{hhval}') - - hparts = [ - 'm=pgp', - f'i={cmdargs.identity}', - f's=0x{cmdargs.keyid}', - 'b=', - ] - shname, shval = dkim_canonicalize_header(XPS_HDR, '; '.join(hparts)) - headers.append(f'{shname}:{shval}') - payload = '\r\n'.join(headers).encode() - if cmdargs.subkeyid: - gpgargs = ['-b', '-u', f'{cmdargs.subkeyid}!'] + if 's' in hdata: + selector = hdata['s'].decode() else: - gpgargs = ['-b', '-u', cmdargs.keyid] - ecode, out, err = gpg_run_command(gpgargs, payload) - if ecode > 0: - logger.critical('Running gpg failed') - logger.critical(err.decode()) - sys.exit(ecode) - bdata = base64.b64encode(out) - shval += splitter(bdata.decode()) - shdr = email.header.make_header([(shval.encode(), 'us-ascii')], maxlinelen=78) - msg[XPS_HDR] = shdr - logger.info('--- MESSAGE STARTS ---') - sys.stdout.buffer.write(msg.as_bytes()) + selector = 'default' + + return identity, selector, algo, signed_hdrs, hdata -def cmd_pgp_verify(msg): - 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() - keyid = re.sub(r'^0x', '', sdata['s']) - if gpg_verify(payload, sig, keyid): - verify_attestation_hashes(msg) +def cmd_sign_ed25519(cmdargs) -> None: + from nacl.signing import SigningKey + from nacl.encoding import Base64Encoder - -def cmd_sign_dk(cmdargs, mode='dk'): - logger.info('Signing: %s header using %s mode', XPS_HDR, mode) - msg = load_message(cmdargs.message) - # 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={cmdargs.domain}', - f'i={cmdargs.identity}', - f's={cmdargs.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) + logger.info('SIGNING : ED25519 using %s', cmdargs.privkey) + headers, payload = load_message(cmdargs.message) + dshdr, digest = make_devsig_header(headers, payload, algo='ed25519', selector=cmdargs.selector) try: with open(cmdargs.privkey, 'r') as fh: sk = SigningKey(fh.read(), encoder=Base64Encoder) @@ -511,108 +406,152 @@ logger.critical('Could not open %s', cmdargs.privkey) sys.exit(1) - bdata = sk.sign(hashed.digest(), encoder=Base64Encoder) - shval += splitter(bdata.decode()) - shdr = email.header.make_header([(shval.encode(), 'us-ascii')], maxlinelen=78) - msg[XPS_HDR] = shdr - logger.info('--- MESSAGE STARTS ---') - sys.stdout.buffer.write(msg.as_bytes()) + bdata = sk.sign(digest, encoder=Base64Encoder) + dshdr = folder(dshdr + splitter(bdata)) + headers.append(dshdr) + signed = b'\r\n'.join(headers) + b'\r\n\r\n' + payload + logger.info('--- SIGNED MESSAGE STARTS ---') + sys.stdout.buffer.write(signed) -def cmd_verify_dk(msg, mode='dk'): - logger.info('Verifying: %s (mode=%s)', XPS_HDR, mode) - 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: - logger.critical('Unknown mode: %s', mode) - sys.exit(1) +def verify_ed25519(sigdata: bytes, pk: bytes) -> Optional[bytes]: + from nacl.signing import VerifyKey + from nacl.encoding import Base64Encoder + from nacl.exceptions import BadSignatureError vk = VerifyKey(pk, encoder=Base64Encoder) try: - foo = vk.verify(sdata['b'].encode(), encoder=Base64Encoder) + return vk.verify(sigdata, encoder=Base64Encoder) except BadSignatureError: - logger.critical('FAIL : mode=%s signature verification for: d=%s, i=%s, s=%s', mode, - sdata['d'], sdata['i'], sdata['s']) - sys.exit(1) - if foo != hashed.digest(): - logger.critical('FAIL : mode=%s signature verification for: d=%s, i=%s, s=%s', mode, - sdata['d'], sdata['i'], sdata['s']) - sys.exit(1) - - if not verify_identity_domain(msg, sdata['i'], sdata['d']): - sys.exit(1) - if not verify_time_drift(msg, sdata['t']): - sys.exit(1) - logger.info('PASS : mode=%s signature verified for: d=%s, i=%s, s=%s', mode, - sdata['d'], sdata['i'], sdata['s']) - verify_attestation_hashes(msg) + return None -def cmd_sign_wk(cmdargs): - cmd_sign_dk(cmdargs, mode='wk') +def cmd_sign_pgp(cmdargs) -> None: + logger.info('SIGNING : PGP using %s', cmdargs.usekey) + headers, payload = load_message(cmdargs.message) + dshdr, digest = make_devsig_header(headers, payload, algo='openpgp', selector=cmdargs.selector) + gpgargs = ['-s', '-u', cmdargs.usekey] + ecode, out, err = gpg_run_command(gpgargs, digest) + if ecode > 0: + logger.critical('Running gpg failed') + logger.critical(err.decode()) + sys.exit(ecode) + bdata = base64.b64encode(out) + dshdr = folder(dshdr + splitter(bdata)) + headers.append(dshdr) + signed = b'\r\n'.join(headers) + b'\r\n\r\n' + payload + logger.info('--- SIGNED MESSAGE STARTS ---') + sys.stdout.buffer.write(signed) -def cmd_verify_wk(msg): - cmd_verify_dk(msg, mode='wk') +def verify_openpgp(sigdata: bytes, pk: Optional[bytes]) -> Optional[bytes]: + # We can't pass both the detached sig and the content on stdin, so + # use a temporary directory + # with tempfile.TemporaryDirectory(suffix='.patch-att-poc') as tmpdir: + # + # with open(savefile, 'wb') as fh: + # fh.write(dsig) + bsigdata = base64.b64decode(sigdata) + vrfyargs = ['--verify', '--output', '-', '--status-fd=2'] + if pk is not None: + with tempfile.TemporaryFile(suffix='.patch-attest-poc') as temp_keyring: + keyringargs = ['--no-default-keyring', f'--keyring={temp_keyring}'] + gpgargs = keyringargs + ['--status-fd=1', '--import'] + ecode, out, err = gpg_run_command(gpgargs, stdin=pk) + # look for IMPORT_OK + if out.find(b'[GNUPG:] IMPORT_OK') < 0: + logger.critical('Could not import public key!') + return None + gpgargs = keyringargs + vrfyargs + ecode, out, err = gpg_run_command(gpgargs, stdin=bsigdata) + if ecode > 0: + logger.critical('FAILED : Failed to verify PGP signature') + return None + good, valid, trusted = check_gpg_status(err) + if good and valid: + return out + logger.critical('FAILED : Failed to verify PGP signature') + return None -def cmd_sign_wkd(cmdargs): - cmd_sign_dk(cmdargs, mode='wkd') + logger.info('Verifying using default keyring') + ecode, out, err = gpg_run_command(vrfyargs, stdin=bsigdata) + if ecode > 0: + logger.critical('FAILED : Failed to verify PGP signature') + return None -def cmd_verify_wkd(msg): - cmd_verify_dk(msg, mode='wkd') + good, valid, trusted = check_gpg_status(err) + if good and valid: + if not trusted: + logger.warning('WARNING : Insufficient trust on the key') + + return out + + logger.critical('FAILED : Failed to verify PGP signature') + return None def cmd_verify(cmdargs): - msg = load_message(cmdargs.message) - # do we have a hashes header? - if not msg.get(XPH_HDR): - logger.critical('Message does not contain %s, nothing to verify', XPH_HDR) - sys.exit(1) - # do we have a sig header? - shdr = msg.get(XPS_HDR) - if not shdr: - if not msg.get('dkim-signature'): - logger.critical('Message contains unsigned hashes, cannot verify') - sys.exit(1) - # Run as a plain dkim verification - cmd_verify_dkim(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_verify_dk(msg) - sys.exit(0) - if sdata['m'] == 'wk': - cmd_verify_wk(msg) - sys.exit(0) - if sdata['m'] == 'wkd': - cmd_verify_wkd(msg) - sys.exit(0) + headers, payload = load_message(cmdargs.message) + identity, selector, algo, signed_hdrs, hdata = get_devsig_header_info(headers) + # Check if we have this private key + pk = get_public_key(cmdargs.keypath, algo, identity, selector) - logger.critical('Unknown mode: %s', sdata['m']) + sdigest = None + if algo == 'ed25519': + if not pk: + sys.exit(1) + sdigest = verify_ed25519(hdata['b'], pk) + elif algo == 'openpgp': + sdigest = verify_openpgp(hdata['b'], pk) + + if not sdigest: + logger.critical('Faled to verify signature!') + sys.exit(1) + + # Now calculate our own digest and compare + dshdr, digest = make_devsig_header(headers, payload, algo, identity=hdata.get('i', b'').decode(), + selector=hdata.get('s', b'').decode(), want_hdrs=signed_hdrs) + success = False + if sdigest != digest: + # Try to limit the payload to just the number of bytes specified in the sig header + try: + maxlen = int(hdata.get('l', b'0')) + if maxlen: + dshdr, digest = make_devsig_header(headers, payload, algo, identity=hdata.get('i', b''), + selector=hdata.get('s', b''), maxlen=maxlen, want_hdrs=signed_hdrs) + if sdigest == digest: + logger.warning('WARNING : Succeeded after trimming payload; the following content was discarded:') + for line in payload[maxlen:].strip().split(b'\n'): + sys.stderr.buffer.write(b' : %s\n' % line) + success = True + except ValueError: + pass + else: + success = True + + if success: + logger.info('SUCCESS : Signature and content hashes verified') + return + + logger.critical('FAILED : Failed to verify signature') sys.exit(1) +def cmd_gen_ed25519(cmdargs): + from nacl.signing import SigningKey + logger.info('Generating: new ED25519 key') + newkey = SigningKey.generate() + with open(cmdargs.output + '.key', 'wb') as fh: + fh.write(base64.b64encode(bytes(newkey))) + logger.info('Wrote: %s.key', cmdargs.output) + with open(cmdargs.output + '.pub', 'wb') as fh: + fh.write(base64.b64encode(bytes(newkey.verify_key))) + logger.info('Wrote: %s.pub', cmdargs.output) + sys.exit(0) + + if __name__ == '__main__': import argparse @@ -622,57 +561,32 @@ description='A proof of concept tool for header-based email patch attestation', formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) - parser.add_argument('-m', '--message', default='emails/unsigned.eml', + parser.add_argument('-m', '--message', default='emails/dev-unsigned.eml', help='File with the message to work with') parser.add_argument('-v', '--verbose', default=False, help='Print extra debugging output') subparsers = parser.add_subparsers(help='sub-command help', dest='subcmd') - # hashes-hdr - sp_hhdr = subparsers.add_parser('hashes-hdr', help='Create a hashes header') - sp_hhdr.set_defaults(func=cmd_hashes_hdr) - - # sign-dkim - sp_sdkim = subparsers.add_parser('sign-dkim', help='Create a DKIM signature') - sp_sdkim.add_argument('-i', '--identity', default='@example.org') - sp_sdkim.add_argument('-d', '--domain', default='example.org') - sp_sdkim.add_argument('-s', '--selector', default='patches') - sp_sdkim.add_argument('-k', '--privkey', default='rsa.key') - sp_sdkim.set_defaults(func=cmd_sign_dkim) - - # sign-dk - sp_sdk = subparsers.add_parser('sign-dk', help='Create a mode=dk signature') - sp_sdk.add_argument('-i', '--identity', default='@example.org') - sp_sdk.add_argument('-d', '--domain', default='example.org') - sp_sdk.add_argument('-s', '--selector', default='patches') - sp_sdk.add_argument('-k', '--privkey', default='dk.key') - sp_sdk.set_defaults(func=cmd_sign_dk) - - # sign-wk - sp_swk = subparsers.add_parser('sign-wk', help='Create a mode=wk signature') - sp_swk.add_argument('-i', '--identity', default='@example.org') - sp_swk.add_argument('-d', '--domain', default='example.org') - sp_swk.add_argument('-s', '--selector', default='patches') - sp_swk.add_argument('-k', '--privkey', default='dk.key') - sp_swk.set_defaults(func=cmd_sign_wk) - - # sign-wk - sp_swkd = subparsers.add_parser('sign-wkd', help='Create a mode=wkd signature') - sp_swkd.add_argument('-i', '--identity', default='dev@kernel.org') - sp_swkd.add_argument('-d', '--domain', default='example.org') - sp_swkd.add_argument('-s', '--selector', default='patches') - sp_swkd.add_argument('-k', '--privkey', default='ingit.key') - sp_swkd.set_defaults(func=cmd_sign_wkd) - # sign-pgp - sp_spgp = subparsers.add_parser('sign-pgp', help='Create a PGP signature') - sp_spgp.add_argument('-i', '--identity', default='dev@kernel.org') - sp_spgp.add_argument('-k', '--keyid', default='AAAABBBBCCCCDDDD') - sp_spgp.add_argument('-u', '--subkeyid') + sp_spgp = subparsers.add_parser('sign-pgp', help='Sign with PGP key') + sp_spgp.add_argument('-k', '--usekey', default='AAAABBBBCCCCDDDD') + sp_spgp.add_argument('-s', '--selector') sp_spgp.set_defaults(func=cmd_sign_pgp) + # sign-ed25519 + sp_sed25519 = subparsers.add_parser('sign-ed25519', help='Sign with an ed25519 key') + sp_sed25519.add_argument('-k', '--privkey', default='dev.key') + sp_sed25519.add_argument('-s', '--selector') + sp_sed25519.set_defaults(func=cmd_sign_ed25519) + + # gen-ed25519 + sp_gened25519 = subparsers.add_parser('gen-ed25519', help='Generate an ed25519 keypair') + sp_gened25519.add_argument('-o', '--output', default='new_ed25519') + sp_gened25519.set_defaults(func=cmd_gen_ed25519) + # verify sp_verify = subparsers.add_parser('verify', help='Verify a signed message') + sp_verify.add_argument('-p', '--keypath', default='ref:refs/heads/master:.keys') sp_verify.set_defaults(func=cmd_verify) args = parser.parse_args()
diff --git a/requirements.txt b/requirements.txt index e04dbb7..7977f1f 100644 --- a/requirements.txt +++ b/requirements.txt
@@ -1,7 +1 @@ -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 +PyNaCl~=1.4.0 \ No newline at end of file
diff --git a/rev.key b/rev.key new file mode 100644 index 0000000..3b26a2d --- /dev/null +++ b/rev.key
@@ -0,0 +1 @@ +DLWuO1XMkDi0FijWr5GlrrN95hJQLpKCK0YOooUxwU4= \ No newline at end of file
diff --git a/rsa.key b/rsa.key deleted file mode 100644 index 044f9ac..0000000 --- a/rsa.key +++ /dev/null
@@ -1,27 +0,0 @@ ------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 index 228b82e..34f23e1 100755 --- a/verify-all.sh +++ b/verify-all.sh
@@ -8,42 +8,21 @@ # Copyright (C) 2020 by the Linux Foundation # SPDX-License-Identifier: MIT-0 # -echo "--------- UNHASHED (expected to fail) ---------" -./main.py -m emails/unsigned.eml verify +echo "--------- UNHASHED (FAIL) ---------" +./main.py -m emails/dev-unsigned.eml verify echo -echo "--------- UNSIGNED (expected to fail) ---------" -./main.py -m emails/unsigned-with-hashes.eml verify +echo "--------- ED25519-SIGNED by dev (PASS) ---------" +./main.py -m emails/dev-signed.eml verify echo -echo "--------- DKIM-SIGNED (all PASS) ---------" -./main.py -m emails/korg-signed-dkim.eml verify +echo "--------- ED25519-SIGNED by rev (PASS) ---------" +./main.py -m emails/rev-signed.eml verify echo -echo "--------- DKIM-SIGNED (with ML junk, all PASS) ---------" -./main.py -m emails/korg-signed-dkim-with-ml-junk.eml verify +echo "--------- PGP-SIGNED by mricon (PASS) ---------" +./main.py -m emails/mricon-signed.eml verify echo -echo "--------- DKIM-SIGNED (with edited subject, metadata will FAIL) ---------" -./main.py -m emails/korg-signed-dkim-changed-subject.eml verify +echo "--------- ED25519-SIGNED by dev (PASS, with WARNINGS) ---------" +./main.py -m emails/dev-signed-with-ml-junk.eml verify echo -echo "--------- DK-SIGNED (all PASS) ---------" -./main.py -m emails/korg-signed-dk.eml verify -echo -echo "--------- WK-SIGNED (all PASS) ---------" -./main.py -m emails/korg-signed-wk.eml verify -echo -echo "--------- PGP-SIGNED (by mricon, all PASS) ---------" -./main.py -m emails/mricon-signed-pgp.eml verify -echo -echo "--------- PGP-SIGNED (by mricon, commit message will FAIL) ---------" -./main.py -m emails/mricon-signed-pgp-commit-message-modified.eml verify -echo -echo "--------- PGP-SIGNED (by mricon, diff content will FAIL) ---------" -./main.py -m emails/mricon-signed-pgp-patch-modified.eml verify -echo -echo "--------- WKD-SIGNED (by mricon, web lookup, all PASS) ---------" -./main.py -m emails/mricon-signed-wkd.eml verify -echo -echo "--------- WKD-SIGNED (by mricon, time drift will FAIL) ---------" -./main.py -m emails/mricon-signed-wkd-huge-drift.eml verify -echo -echo "--------- WKD-SIGNED (by dev, stored in git, all PASS) ---------" -./main.py -m emails/dev-signed-wkd-ingit.eml verify +echo "--------- ED25519-SIGNED by dev (FAIL) ---------" +./main.py -m emails/dev-signed-invalid.eml verify echo