Blame SOURCES/0004-tpm2_ptool-do-not-re-encode-the-signed-data-when-imp.patch

32281e
From 5bf5d6c22b9461321cec9ddeaae5795a5465bb03 Mon Sep 17 00:00:00 2001
32281e
From: Nicolas Iooss <nicolas.iooss@ledger.fr>
32281e
Date: Thu, 23 Sep 2021 21:34:03 +0200
32281e
Subject: [PATCH 4/6] tpm2_ptool: do not re-encode the signed data when
32281e
 importing a certificate
32281e
32281e
When using `tpm2_ptool addcert`, several users experienced issues
32281e
because the signed data of the certificate was re-encoded when being
32281e
added to the database. More precisely, the encoded certificate data is
32281e
encoded using a BER encoder which encodes booleans using 1 of True (cf.
32281e
https://github.com/etingof/pyasn1/blob/v0.4.8/pyasn1/codec/ber/encoder.py#L164
32281e
). But in DER, the encoding of "True" is 0xff, and changing the signed
32281e
data made the signature of the certificate no longer valid.
32281e
32281e
To fix this issue:
32281e
32281e
- Directly use the result of `pem.readPemFromFile(f)` in attribute
32281e
  `CKA_VALUE`: this is directly the encoded form of the certificate.
32281e
- Remove `pyasn1.codec.ber`, as this encoder is no longer used.
32281e
- Rename the DER decoder from `decoder` to `derdecoder` and the encoder
32281e
  from `derenc` to `derencoder`, to make the code easier to read.
32281e
32281e
While at it:
32281e
32281e
- Reindent the code to 4-space indentation
32281e
- Use `hashlib.sha1(bercert).digest()` directly to compute a SHA1
32281e
  digest, instead of using `m.update()`.
32281e
32281e
Fixes: https://github.com/tpm2-software/tpm2-pkcs11/issues/700
32281e
Signed-off-by: Nicolas Iooss <nicolas.iooss@ledger.fr>
32281e
---
32281e
 tools/tpm2_pkcs11/utils.py | 126 ++++++++++++++++++-------------------
32281e
 1 file changed, 60 insertions(+), 66 deletions(-)
32281e
32281e
diff --git a/tools/tpm2_pkcs11/utils.py b/tools/tpm2_pkcs11/utils.py
32281e
index b803f4c..91eab9a 100644
32281e
--- a/tools/tpm2_pkcs11/utils.py
32281e
+++ b/tools/tpm2_pkcs11/utils.py
32281e
@@ -15,9 +15,7 @@ from cryptography.hazmat.primitives.asymmetric import (rsa, padding)
32281e
 from cryptography.hazmat.primitives import hashes
32281e
 
32281e
 from pyasn1_modules import pem, rfc2459
32281e
-from pyasn1.codec.der import decoder
32281e
-from pyasn1.codec.ber import encoder as berenc
32281e
-from pyasn1.codec.der import encoder as derenc
32281e
+from pyasn1.codec.der import decoder as derdecoder, encoder as derencoder
32281e
 from pyasn1.type import namedtype, tag, univ
32281e
 
32281e
 from .pkcs11t import *  # noqa
32281e
@@ -247,68 +245,64 @@ def asn1_format_ec_point_uncompressed(x, y):
32281e
     return s
32281e
 
32281e
 def pemcert_to_attrs(certpath):
32281e
-            # rather than use pycryptography x509 parser, which gives native type access to certificate
32281e
-        # fields use pyASN1 to get raw ASN1 encoded values for the fields as the spec requires them
32281e
-        with open(certpath, "r") as f:
32281e
-            substrate = pem.readPemFromFile(f)
32281e
-            cert = decoder.decode(substrate, asn1Spec=rfc2459.Certificate())[0]
32281e
-
32281e
-        c = cert['tbsCertificate']
32281e
-
32281e
-        # print(cert.prettyPrint())
32281e
-
32281e
-        h = binascii.hexlify
32281e
-        b = berenc.encode
32281e
-        d = derenc.encode
32281e
-
32281e
-        bercert = b(cert)
32281e
-        hexbercert = h(bercert).decode()
32281e
-
32281e
-        # the CKA_CHECKSUM attrs is the first 3 bytes of a sha1hash
32281e
-        m = hashlib.sha1()
32281e
-        m.update(bercert)
32281e
-        bercertchecksum = m.digest()[0:3]
32281e
-        hexbercertchecksum = h(bercertchecksum).decode()
32281e
-
32281e
-        subj = c['subject']
32281e
-        hexsubj = h(d(str2bytes(subj))).decode()
32281e
-
32281e
-        issuer = c['issuer']
32281e
-        hexissuer = h(d(str2bytes(issuer))).decode()
32281e
-
32281e
-        serial = c['serialNumber']
32281e
-        hexserial = h(d(str2bytes(serial))).decode()
32281e
-
32281e
-        return {
32281e
-            # The attrs of this attribute is derived by taking the first 3 bytes of the CKA_VALUE
32281e
-            # field.
32281e
-            CKA_CHECK_VALUE: hexbercertchecksum,
32281e
-            # Start date for the certificate (default empty)
32281e
-            CKA_START_DATE : "",
32281e
-            # End date for the certificate (default empty)
32281e
-            CKA_END_DATE : "",
32281e
-            # DER-encoding of the SubjectPublicKeyInfo for the public key
32281e
-            # contained in this certificate (default empty)
32281e
-            CKA_PUBLIC_KEY_INFO : "",
32281e
-            # DER encoded subject
32281e
-            CKA_SUBJECT : hexsubj,
32281e
-            # DER encoding of issuer
32281e
-            CKA_ISSUER : hexissuer,
32281e
-            # DER encoding of the cert serial
32281e
-            CKA_SERIAL_NUMBER : hexserial,
32281e
-            # BER encoding of the certificate
32281e
-            CKA_VALUE : hexbercert,
32281e
-            # RFC2279 string to URL where cert can be found, default empty
32281e
-            CKA_URL : '',
32281e
-            # hash of pub key subj, default empty
32281e
-            CKA_HASH_OF_SUBJECT_PUBLIC_KEY : '',
32281e
-            # Hash of pub key, default empty
32281e
-            CKA_HASH_OF_ISSUER_PUBLIC_KEY : '',
32281e
-            # Java security domain, default CK_SECURITY_DOMAIN_UNSPECIFIED
32281e
-            CKA_JAVA_MIDP_SECURITY_DOMAIN : CK_SECURITY_DOMAIN_UNSPECIFIED,
32281e
-            # Name hash algorithm, defaults to SHA1
32281e
-            CKA_NAME_HASH_ALGORITHM : CKM_SHA_1
32281e
-        }
32281e
+    # rather than using pycryptography x509 parser, which gives native type access to certificate
32281e
+    # fields use pyASN1 to get raw ASN1 encoded values for the fields as the spec requires them
32281e
+    with open(certpath, "r") as f:
32281e
+        bercert = pem.readPemFromFile(f)
32281e
+
32281e
+    cert = derdecoder.decode(bercert, asn1Spec=rfc2459.Certificate())[0]
32281e
+    c = cert['tbsCertificate']
32281e
+
32281e
+    # print(cert.prettyPrint())
32281e
+
32281e
+    h = binascii.hexlify
32281e
+    d = derencoder.encode
32281e
+
32281e
+    hexbercert = h(bercert).decode()
32281e
+
32281e
+    # the CKA_CHECKSUM attrs is the first 3 bytes of a sha1hash
32281e
+    bercertchecksum = hashlib.sha1(bercert).digest()[0:3]
32281e
+    hexbercertchecksum = h(bercertchecksum).decode()
32281e
+
32281e
+    subj = c['subject']
32281e
+    hexsubj = h(d(str2bytes(subj))).decode()
32281e
+
32281e
+    issuer = c['issuer']
32281e
+    hexissuer = h(d(str2bytes(issuer))).decode()
32281e
+
32281e
+    serial = c['serialNumber']
32281e
+    hexserial = h(d(str2bytes(serial))).decode()
32281e
+
32281e
+    return {
32281e
+        # The attrs of this attribute is derived by taking the first 3 bytes of the CKA_VALUE
32281e
+        # field.
32281e
+        CKA_CHECK_VALUE: hexbercertchecksum,
32281e
+        # Start date for the certificate (default empty)
32281e
+        CKA_START_DATE: "",
32281e
+        # End date for the certificate (default empty)
32281e
+        CKA_END_DATE: "",
32281e
+        # DER-encoding of the SubjectPublicKeyInfo for the public key
32281e
+        # contained in this certificate (default empty)
32281e
+        CKA_PUBLIC_KEY_INFO: "",
32281e
+        # DER encoded subject
32281e
+        CKA_SUBJECT: hexsubj,
32281e
+        # DER encoding of issuer
32281e
+        CKA_ISSUER: hexissuer,
32281e
+        # DER encoding of the cert serial
32281e
+        CKA_SERIAL_NUMBER: hexserial,
32281e
+        # BER encoding of the certificate
32281e
+        CKA_VALUE: hexbercert,
32281e
+        # RFC2279 string to URL where cert can be found, default empty
32281e
+        CKA_URL: '',
32281e
+        # hash of pub key subj, default empty
32281e
+        CKA_HASH_OF_SUBJECT_PUBLIC_KEY: '',
32281e
+        # Hash of pub key, default empty
32281e
+        CKA_HASH_OF_ISSUER_PUBLIC_KEY: '',
32281e
+        # Java security domain, default CK_SECURITY_DOMAIN_UNSPECIFIED
32281e
+        CKA_JAVA_MIDP_SECURITY_DOMAIN: CK_SECURITY_DOMAIN_UNSPECIFIED,
32281e
+        # Name hash algorithm, defaults to SHA1
32281e
+        CKA_NAME_HASH_ALGORITHM: CKM_SHA_1
32281e
+    }
32281e
 
32281e
 def _pkcs11_to_str(value, prefix):
32281e
 
32281e
@@ -407,7 +401,7 @@ def asn1parse_tss_key(keypath):
32281e
         if len(substrate) == 0:
32281e
             sys.exit('Did not find key in tss key file: {}'.format(keypath))
32281e
 
32281e
-        tss2_privkey, _ = decoder.decode(substrate, asn1Spec=TSSPrivKey())
32281e
+        tss2_privkey, _ = derdecoder.decode(substrate, asn1Spec=TSSPrivKey())
32281e
 
32281e
         return tss2_privkey
32281e
 
32281e
-- 
32281e
2.38.1
32281e