Skip to content

Commit

Permalink
tpm2_ptool: fix python 3 behavior
Browse files Browse the repository at this point in the history
python2 and python3 differ in behavior on reading from a file that was
opened with the binary flag. In python2 the read data is a str, in
python3 its bytes. This is posing an issue in the asn1 calls as outlined
in bug:
  - etingof/pyasn1#185

We can work around this for now, since pem files are always string,
remove the binary flag and open pem w/o binary mode flag

Additionally, python3 and python 2 differe in handling str and bytes and
python3 requires more type correctness. Fix all this in a way that works
with python2 and python3

Releates to bug #327

Signed-off-by: William Roberts <[email protected]>
  • Loading branch information
William Roberts committed Nov 27, 2019
1 parent 3bdeb65 commit 3bf1b8e
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 7 deletions.
21 changes: 14 additions & 7 deletions tools/tpm2_pkcs11/commandlets_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from .utils import get_ec_params
from .utils import asn1_format_ec_point_uncompressed
from .utils import list_dict_from_kvp
from .utils import str2bytes

from .tpm2 import Tpm2

Expand Down Expand Up @@ -523,7 +524,7 @@ def __call__(self, args):

# rather than use pycryptography x509 parser, which gives native type access to certficiate
# fields use pyASN1 to get raw ASN1 encoded values for the fields as the spec requires them
with open(certpath, "rb") as f:
with open(certpath, "r") as f:
substrate = pem.readPemFromFile(f)
cert = decoder.decode(substrate, asn1Spec=rfc2459.Certificate())[0]

Expand All @@ -536,12 +537,18 @@ def __call__(self, args):
d = derenc.encode

bercert = b(cert)
hexbercert = h(bercert).decode()

# the CKA_CHECKSUM value is the first 3 bytes of a sha1hash
m = hashlib.sha1()
m.update(bercert)
bercertchecksum = m.digest()[0:3]
bercertchecksum = h(bercertchecksum)
hexbercertchecksum = h(bercertchecksum).decode()

subj = c['subject']
hexsubj=h(d(str2bytes(subj))).decode()

hexkeylabel = h(str2bytes(keylabel)).decode()

attrs = [
{ CKA_CLASS : CKO_CERTIFICATE },
Expand All @@ -550,7 +557,7 @@ def __call__(self, args):
{ CKA_CERTIFICATE_CATEGORY: CK_CERTIFICATE_CATEGORY_UNSPECIFIED },
# The value of this attribute is derived by taking the first 3 bytes of the CKA_VALUE
# field.
{ CKA_CHECK_VALUE: bercertchecksum },
{ CKA_CHECK_VALUE: hexbercertchecksum },
# Start date for the certificate (default empty)
{ CKA_START_DATE : "" },
# End date for the certificate (default empty)
Expand All @@ -559,15 +566,15 @@ def __call__(self, args):
# contained in this certificate (default empty)
{ CKA_PUBLIC_KEY_INFO : "" },
# DER encoded subject
{ CKA_SUBJECT : h(d(c['subject'])) },
{ CKA_SUBJECT : hexsubj },
# "label of keypair associated, default empty
{ CKA_LABEL : h(keylabel) },
{ CKA_LABEL : hexkeylabel },
# der encoding of issuer, default empty
{ CKA_ISSUER : '' },
# der encoding of the cert serial, default empty
{ CKA_SERIAL_NUMBER : '' },
# BER encoding of the certificate
{ CKA_VALUE : h(bercert) },
{ CKA_VALUE : hexbercert },
# RFC2279 string to URL where cert can be found, default empty
{ CKA_URL : '' },
# hash of pub key subj, default empty
Expand Down Expand Up @@ -616,7 +623,7 @@ def get_id_by_label(tobj, keylabel):

for a in attrs:
if str(CKA_LABEL) in a:
x = binascii.unhexlify(a[str(CKA_LABEL)])
x = binascii.unhexlify(a[str(CKA_LABEL)]).decode()
if x == keylabel:
return a[str(CKA_LABEL)]

Expand Down
4 changes: 4 additions & 0 deletions tools/tpm2_pkcs11/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
if sys.version_info.major < 3:
input = raw_input

def str2bytes(s):
if isinstance(s, str):
return s.encode()
return s

# The delimiter changes based on nesting level to make parsing easier. We assume one key-value entry per line
# where a key can have N KVPs as a CSV.
Expand Down

0 comments on commit 3bf1b8e

Please sign in to comment.