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