chore(iatverifier): update pycose (0.0.1->1.1.0)
This change is in preparation for updating the CCA realm token to encode
the RAK as COSE_Key.
Change-Id: I745207a8d2d1d20e36503cbbc4ad38b6379e3a28
Co-authored-by: Mate Toth-Pal <mate.toth-pal@arm.com>
Co-authored-by: Thomas Fossati <thomas.fossati@linaro.org>
Signed-off-by: Thomas Fossati <thomas.fossati@linaro.org>
diff --git a/iat-verifier/dev_scripts/generate-sample-iat.py b/iat-verifier/dev_scripts/generate-sample-iat.py
index cf0f700..7e61605 100755
--- a/iat-verifier/dev_scripts/generate-sample-iat.py
+++ b/iat-verifier/dev_scripts/generate-sample-iat.py
@@ -25,6 +25,7 @@
from iatverifier.psa_iot_profile1_token_claims import MeasurementValueClaim
from iatverifier.psa_iot_profile1_token_claims import MeasurementDescriptionClaim
from iatverifier.psa_iot_profile1_token_verifier import PSAIoTProfile1TokenVerifier
+from pycose.algorithms import Es256, Es384, Es512
# First byte indicates "GUID"
GUID = b'\x01' + struct.pack('QQQQ', 0x0001020304050607, 0x08090A0B0C0D0E0F,
@@ -94,7 +95,7 @@
method=AttestationTokenVerifier.SIGN_METHOD_SIGN1)
verifier = PSAIoTProfile1TokenVerifier(signing_key=key,
method=AttestationTokenVerifier.SIGN_METHOD_SIGN1,
- cose_alg=AttestationTokenVerifier.COSE_ALG_ES256,
+ cose_alg=Es256,
configuration=None)
with open(outfile, 'wb') as wfh:
convert_map_to_token(token_map, verifier, wfh,
diff --git a/iat-verifier/iatverifier/attest_token_verifier.py b/iat-verifier/iatverifier/attest_token_verifier.py
index 98b162f..beed405 100644
--- a/iat-verifier/iatverifier/attest_token_verifier.py
+++ b/iat-verifier/iatverifier/attest_token_verifier.py
@@ -15,9 +15,8 @@
from dataclasses import dataclass
from io import BytesIO
-from pycose.attributes import CoseAttrs
-from pycose.sign1message import Sign1Message
-from pycose.mac0message import Mac0Message
+from pycose.messages.sign1message import Sign1Message
+from pycose.messages.mac0message import Mac0Message
import cbor2
from cbor2 import CBOREncoder
@@ -484,21 +483,9 @@
SIGN_METHOD_MAC0 = "mac"
SIGN_METHOD_RAW = "raw"
- COSE_ALG_ES256="ES256"
- COSE_ALG_ES384="ES384"
- COSE_ALG_ES512="ES512"
- COSE_ALG_HS256_64="HS256/64"
- COSE_ALG_HS256="HS256"
- COSE_ALG_HS384="HS384"
- COSE_ALG_HS512="HS512"
-
@abstractmethod
def _get_p_header(self):
- """Return the protected header for this Token
-
- Return a dictionary if p_header should be present, and None if the token
- doesn't defines a protected header.
- """
+ """Return the protected header for this Token"""
raise NotImplementedError
@abstractmethod
@@ -555,27 +542,16 @@
raise ValueError(err_msg.format(self.method))
def _sign_eat(self, token):
- protected_header = CoseAttrs()
p_header=self._get_p_header()
key=self._get_signing_key()
- if p_header is not None and key:
- protected_header.update(p_header)
- signed_msg = Sign1Message(p_header=protected_header)
- signed_msg.payload = token
- if key:
- signed_msg.key = key
- signed_msg.signature = signed_msg.compute_signature(alg=self._get_cose_alg())
+ signed_msg = Sign1Message(payload=token, key=key, phdr=p_header)
return signed_msg.encode()
def _hmac_eat(self, token):
- protected_header = CoseAttrs()
p_header=self._get_p_header()
key=self._get_signing_key()
- if p_header is not None and key:
- protected_header.update(p_header)
- hmac_msg = Mac0Message(payload=token, key=key, p_header=protected_header)
- hmac_msg.compute_auth_tag(alg=self.cose_alg)
+ hmac_msg = Mac0Message(payload=token, key=key, phdr=p_header)
return hmac_msg.encode()
@@ -588,12 +564,9 @@
except Exception as exc:
self.error(f'Invalid Protected header: {exc}', exception=exc)
msg.key = key
- msg.signature = msg.signers
- try:
- msg.verify_signature(alg=self._get_cose_alg())
- except Exception as exc:
- raise ValueError(f'Bad signature ({exc})') from exc
- return msg.payload, msg.protected_header
+ if not msg.verify_signature():
+ raise ValueError('Bad signature')
+ return msg.payload, msg.phdr
def _get_cose_mac0_payload(self, cose, *, verify_signature):
@@ -605,11 +578,9 @@
except Exception as exc:
self.error(f'Invalid Protected header: {exc}', exception=exc)
msg.key = key
- try:
- msg.verify_auth_tag(alg=self._get_cose_alg())
- except Exception as exc:
- raise ValueError(f'Bad signature ({exc})') from exc
- return msg.payload, msg.protected_header
+ if not msg.verify_tag(alg=self._get_cose_alg()):
+ raise ValueError('Bad signature')
+ return msg.payload, msg.phdr
def _get_cose_payload(self, cose, *, verify_signature):
@@ -668,13 +639,14 @@
payload = token
protected_header = None
else:
+ verify_signature = False
try:
payload, protected_header = self._get_cose_payload(
token,
# signature verification is done in the verify function
- verify_signature=False)
+ verify_signature=verify_signature)
except Exception as exc:
- msg = f'Bad COSE: {exc}'
+ msg = f'Parse (verify_signature={verify_signature}): Bad COSE: {exc}'
self.error(msg)
try:
@@ -701,12 +673,13 @@
def verify(self, token_item):
if self._get_method() != AttestationTokenVerifier.SIGN_METHOD_RAW:
+ verify_signature = self._get_signing_key() is not None
try:
self._get_cose_payload(
token_item.token,
- verify_signature=(self._get_signing_key() is not None))
+ verify_signature=verify_signature)
except Exception as exc:
- msg = f'Bad COSE: {exc}'
+ msg = f'Verify (verify_signature={verify_signature}): Bad COSE: {exc}'
raise ValueError(msg) from exc
wrapping_tag = self._get_wrapping_tag()
diff --git a/iat-verifier/iatverifier/cca_token_verifier.py b/iat-verifier/iatverifier/cca_token_verifier.py
index df9ddab..fc05d9a 100644
--- a/iat-verifier/iatverifier/cca_token_verifier.py
+++ b/iat-verifier/iatverifier/cca_token_verifier.py
@@ -10,6 +10,8 @@
from ecdsa.keys import VerifyingKey
from ecdsa.curves import NIST256p, NIST384p, NIST521p
from hashlib import sha1
+from pycose.headers import Algorithm
+from pycose.algorithms import Es256, Es384, Es512
from iatverifier.attest_token_verifier import AttestationTokenVerifier as Verifier
from iatverifier.attest_token_verifier import AttestationClaim as Claim
@@ -24,12 +26,13 @@
from iatverifier.cca_claims import CCASwCompHashAlgIdClaim, CCASwCompHashAlgIdClaim
from iatverifier.psa_iot_profile1_token_claims import SWComponentTypeClaim, SwComponentVersionClaim
from iatverifier.psa_iot_profile1_token_claims import MeasurementValueClaim, SignerIdClaim
+from iatverifier.util import es384_cose_key_from_raw_ecdsa
_Algorithm = namedtuple("Algorithm", "ecdsa_curve pub_key_len")
_algorithms = {
- Verifier.COSE_ALG_ES256: _Algorithm(NIST256p, 65),
- Verifier.COSE_ALG_ES384: _Algorithm(NIST384p, 97),
- Verifier.COSE_ALG_ES512: _Algorithm(NIST521p, 133),
+ Es256: _Algorithm(NIST256p, 65),
+ Es384: _Algorithm(NIST384p, 97),
+ Es512: _Algorithm(NIST521p, 133),
}
class CCATokenVerifier(Verifier):
@@ -41,13 +44,19 @@
return 'CCA_TOKEN'
def _get_p_header(self):
- None
+ return {Algorithm: self._get_cose_alg()}
def _get_wrapping_tag(self):
return 399
def _parse_p_header(self, msg):
- pass
+ alg = self._get_cose_alg()
+ try:
+ msg_alg = msg.get_attr(Algorithm)
+ except AttributeError:
+ raise ValueError('Missing alg from protected header (expected {})'.format(alg))
+ if alg != msg_alg:
+ raise ValueError('Unexpected alg in protected header (expected {} instead of {})'.format(alg, msg_alg))
def __init__(self, *,
realm_token_method,
@@ -76,7 +85,7 @@
configuration=configuration,
necessity=Claim.MANDATORY,
method=Verifier.SIGN_METHOD_RAW,
- cose_alg=Verifier.COSE_ALG_ES256,
+ cose_alg=Es256,
signing_key=None)
def verify(self, token_item):
@@ -107,7 +116,7 @@
return 'CCA_REALM_DELEGATED_TOKEN'
def _get_p_header(self):
- return {'alg': self._get_cose_alg()}
+ return {Algorithm: self._get_cose_alg()}
def _get_wrapping_tag(self):
return None
@@ -115,8 +124,8 @@
def _parse_p_header(self, msg):
alg = self._get_cose_alg()
try:
- msg_alg = msg.protected_header['alg']
- except KeyError:
+ msg_alg = msg.get_attr(Algorithm)
+ except AttributeError:
raise ValueError('Missing alg from protected header (expected {})'.format(alg))
if alg != msg_alg:
raise ValueError('Unexpected alg in protected header (expected {} instead of {})'.format(alg, msg_alg))
@@ -159,7 +168,7 @@
self.error("No protected header in realm token, failed to parse signature curve.")
return
- alg = token_item.protected_header['alg']
+ alg = token_item.protected_header[Algorithm]
if alg not in _algorithms:
self.error(f"Unknown alg '{alg}' in realm token's protected header.")
return
@@ -171,10 +180,13 @@
return
# Set the signing key in the parsed CCARealmTokenVerifier object
- token_item.claim_type.signing_key = VerifyingKey.from_string(
- cca_realm_public_key,
- curve=alg_info.ecdsa_curve,
- hashfunc=sha1)
+ token_item.claim_type.signing_key = es384_cose_key_from_raw_ecdsa(
+ VerifyingKey.from_string(
+ cca_realm_public_key,
+ curve=alg_info.ecdsa_curve,
+ hashfunc=sha1
+ )
+ )
# call the '_get_cose_payload' of AttestationTokenVerifier to verify the
# signature
@@ -193,7 +205,7 @@
return 'CCA_PLATFORM_TOKEN'
def _get_p_header(self):
- return {'alg': self._get_cose_alg()}
+ return {Algorithm: self._get_cose_alg()}
def _get_wrapping_tag(self):
return None
@@ -201,8 +213,8 @@
def _parse_p_header(self, msg):
alg = self._get_cose_alg()
try:
- msg_alg = msg.protected_header['alg']
- except KeyError:
+ msg_alg = msg.get_attr(Algorithm)
+ except AttributeError:
raise ValueError('Missing alg from protected header (expected {})'.format(alg))
if alg != msg_alg:
raise ValueError('Unexpected alg in protected header (expected {} instead of {})'.format(alg, msg_alg))
diff --git a/iat-verifier/iatverifier/psa_2_0_0_token_verifier.py b/iat-verifier/iatverifier/psa_2_0_0_token_verifier.py
index 0e9a350..3a36540 100644
--- a/iat-verifier/iatverifier/psa_2_0_0_token_verifier.py
+++ b/iat-verifier/iatverifier/psa_2_0_0_token_verifier.py
@@ -5,6 +5,8 @@
#
# -----------------------------------------------------------------------------
+from pycose.headers import Algorithm
+
from iatverifier.attest_token_verifier import AttestationTokenVerifier as Verifier
from iatverifier.attest_token_verifier import AttestationClaim as Claim
from iatverifier.psa_2_0_0_token_claims import ProfileIdClaim, ClientIdClaim, SecurityLifecycleClaim
@@ -24,7 +26,7 @@
return 'PSA_2_0_0_TOKEN'
def _get_p_header(self):
- return {'alg': self._get_cose_alg()}
+ return {Algorithm: self._get_cose_alg()}
def _get_wrapping_tag(self):
return None
@@ -32,8 +34,8 @@
def _parse_p_header(self, msg):
alg = self._get_cose_alg()
try:
- msg_alg = msg.protected_header['alg']
- except KeyError:
+ msg_alg = msg.get_attr(Algorithm)
+ except AttributeError:
raise ValueError('Missing alg from protected header (expected {})'.format(alg))
if alg != msg_alg:
raise ValueError('Unexpected alg in protected header (expected {} instead of {})'.format(alg, msg_alg))
diff --git a/iat-verifier/iatverifier/psa_iot_profile1_token_verifier.py b/iat-verifier/iatverifier/psa_iot_profile1_token_verifier.py
index 96f721e..f75c6c4 100644
--- a/iat-verifier/iatverifier/psa_iot_profile1_token_verifier.py
+++ b/iat-verifier/iatverifier/psa_iot_profile1_token_verifier.py
@@ -7,6 +7,8 @@
"""Contains class for verifying PSA Attestation Token profile PSA_IOT_PROFILE_1"""
+from pycose.headers import Algorithm
+
from iatverifier.attest_token_verifier import AttestationTokenVerifier as Verifier
from iatverifier.attest_token_verifier import AttestationClaim as Claim
from iatverifier.psa_iot_profile1_token_claims import ProfileIdClaim, ClientIdClaim
@@ -28,7 +30,7 @@
return 'PSA_IOT_PROFILE1_TOKEN'
def _get_p_header(self):
- return {'alg': self._get_cose_alg()}
+ return {Algorithm: self._get_cose_alg()}
def _get_wrapping_tag(self):
return None
@@ -36,8 +38,8 @@
def _parse_p_header(self, msg):
alg = self._get_cose_alg()
try:
- msg_alg = msg.protected_header['alg']
- except KeyError as exc:
+ msg_alg = msg.get_attr(Algorithm)
+ except AttributeError as exc:
raise ValueError(f'Missing algorithm from protected header (expected {alg})') from exc
if alg != msg_alg:
raise ValueError(f'Unexpected algorithm in protected header (expected {alg} ' +
diff --git a/iat-verifier/iatverifier/util.py b/iat-verifier/iatverifier/util.py
index a95eade..ea152c7 100644
--- a/iat-verifier/iatverifier/util.py
+++ b/iat-verifier/iatverifier/util.py
@@ -15,18 +15,35 @@
import base64
import yaml
import yaml_include
-from ecdsa import SigningKey, VerifyingKey
+from pycose.keys import CoseKey
+from pycose.keys.curves import P256, P384, P521
+from pycose.keys.keytype import KtyEC2
+from pycose.algorithms import Es256, Es384, Es512, HMAC256
from iatverifier.attest_token_verifier import AttestationTokenVerifier
from cbor2 import CBOREncoder
+from pycose.keys import CoseKey
+from ecdsa.util import number_to_string
_logger = logging.getLogger("util")
_known_curves = {
- "NIST256p": AttestationTokenVerifier.COSE_ALG_ES256,
- "NIST384p": AttestationTokenVerifier.COSE_ALG_ES384,
- "NIST521p": AttestationTokenVerifier.COSE_ALG_ES512,
+ P256: Es256,
+ P384: Es384,
+ P521: Es512,
}
+
+def es384_cose_key_from_raw_ecdsa(raw_key):
+ d = {
+ 'KTY': 'EC2',
+ 'CURVE': 'P_384',
+ 'ALG': 'ES384',
+ 'X': number_to_string(raw_key.pubkey.point.x(), raw_key.curve.generator.order()),
+ 'Y': number_to_string(raw_key.pubkey.point.y(), raw_key.curve.generator.order()),
+ }
+
+ return CoseKey.from_dict(d)
+
def convert_map_to_token(token_map, verifier, wfh, *, name_as_key, parse_raw_value):
"""
Convert a map to token and write the result to a file.
@@ -101,20 +118,24 @@
"""
if key is None:
return default
- if not hasattr(key, "curve"):
- raise ValueError("Key has no curve specified in it.")
- return _known_curves[key.curve.name]
+ if key.kty is not KtyEC2:
+ err_msg = 'Unexpected key type "{}"; must be KtyEC2'
+ raise ValueError(err_msg.format(key.kty))
+ if key.alg is not None:
+ return key.alg
+ return _known_curves[key.crv]
def _read_sign1_key(keyfile):
with open(keyfile, 'rb') as file_obj:
- raw_key = file_obj.read()
+ s = file_obj.read()
+ raw_key = s.decode("utf-8") # assume PEM-encoded key
try:
- key = SigningKey.from_pem(raw_key)
+ key = CoseKey.from_pem_private_key(raw_key)
except Exception as exc:
signing_key_error = str(exc)
try:
- key = VerifyingKey.from_pem(raw_key)
+ key = CoseKey.from_pem_public_key(raw_key)
except Exception as vexc:
verifying_key_error = str(vexc)
@@ -124,4 +145,10 @@
def _read_hmac_key(keyfile):
- return open(keyfile, 'rb').read()
+ k = open(keyfile, 'rb').read()
+ d = {
+ 'KTY': 'SYMMETRIC',
+ 'ALG': HMAC256,
+ 'K': k,
+ }
+ return CoseKey.from_dict(d)
\ No newline at end of file
diff --git a/iat-verifier/scripts/check_iat b/iat-verifier/scripts/check_iat
index ca47e91..5cd1e81 100755
--- a/iat-verifier/scripts/check_iat
+++ b/iat-verifier/scripts/check_iat
@@ -13,6 +13,8 @@
import logging
import sys
+from pycose.algorithms import Es256, Es384, HMAC256
+
from iatverifier.util import recursive_bytes_to_strings, read_keyfile, get_cose_alg_from_key
from iatverifier.psa_iot_profile1_token_verifier import PSAIoTProfile1TokenVerifier
from iatverifier.psa_2_0_0_token_verifier import PSA_2_0_0_TokenVerifier
@@ -91,9 +93,9 @@
key_checked = args.key
key = read_keyfile(keyfile=args.key, method=method)
if method == AttestationTokenVerifier.SIGN_METHOD_SIGN1:
- cose_alg = get_cose_alg_from_key(key, AttestationTokenVerifier.COSE_ALG_ES256)
+ cose_alg = get_cose_alg_from_key(key, Es256)
else:
- cose_alg = AttestationTokenVerifier.COSE_ALG_HS256
+ cose_alg = HMAC256
verifier = PSAIoTProfile1TokenVerifier(
method=method,
cose_alg=cose_alg,
@@ -107,12 +109,8 @@
platform_token_key = read_keyfile(args.key, method)
realm_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
platform_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
- realm_token_cose_alg = get_cose_alg_from_key(
- None,
- AttestationTokenVerifier.COSE_ALG_ES384)
- platform_token_cose_alg = get_cose_alg_from_key(
- platform_token_key,
- AttestationTokenVerifier.COSE_ALG_ES384)
+ realm_token_cose_alg = get_cose_alg_from_key(None, Es384)
+ platform_token_cose_alg = get_cose_alg_from_key(platform_token_key, Es384)
verifier = CCATokenVerifier(
realm_token_method=realm_token_method,
realm_token_cose_alg=realm_token_cose_alg,
@@ -123,7 +121,7 @@
elif verifier_class == CCAPlatformTokenVerifier:
key_checked = args.key
key = read_keyfile(args.key, method)
- cose_alg = get_cose_alg_from_key(key, AttestationTokenVerifier.COSE_ALG_ES384)
+ cose_alg = get_cose_alg_from_key(key, Es384)
verifier = CCAPlatformTokenVerifier(
method=AttestationTokenVerifier.SIGN_METHOD_SIGN1,
cose_alg=cose_alg,
@@ -134,9 +132,9 @@
key_checked = args.key
key = read_keyfile(keyfile=args.key, method=method)
if method == AttestationTokenVerifier.SIGN_METHOD_SIGN1:
- cose_alg = get_cose_alg_from_key(key, AttestationTokenVerifier.COSE_ALG_ES256)
+ cose_alg = get_cose_alg_from_key(key, Es256)
else:
- cose_alg = AttestationTokenVerifier.COSE_ALG_HS256
+ cose_alg = HMAC256
verifier = PSA_2_0_0_TokenVerifier(method=method, cose_alg=cose_alg, signing_key=key, configuration=config)
else:
logger.error(f'Invalid token type:{verifier_class}\n\t')
diff --git a/iat-verifier/scripts/compile_token b/iat-verifier/scripts/compile_token
index 8ac2ccd..34ec781 100755
--- a/iat-verifier/scripts/compile_token
+++ b/iat-verifier/scripts/compile_token
@@ -13,6 +13,8 @@
import os
import sys
+from pycose.algorithms import Es256, Es384, HMAC256
+
from iatverifier.util import read_token_map, convert_map_to_token, read_keyfile
from iatverifier.util import get_cose_alg_from_key
from iatverifier.psa_iot_profile1_token_verifier import PSAIoTProfile1TokenVerifier
@@ -77,11 +79,9 @@
if verifier_class == PSAIoTProfile1TokenVerifier:
key = read_keyfile(args.key, METHOD)
if METHOD == AttestationTokenVerifier.SIGN_METHOD_SIGN1:
- cose_alg = get_cose_alg_from_key(
- key,
- AttestationTokenVerifier.COSE_ALG_ES256)
+ cose_alg = get_cose_alg_from_key(key, Es256)
else:
- cose_alg = AttestationTokenVerifier.COSE_ALG_HS256
+ cose_alg = HMAC256
verifier = PSAIoTProfile1TokenVerifier(
method=METHOD,
cose_alg=cose_alg,
@@ -95,12 +95,8 @@
realm_token_key = read_keyfile(args.realm_key, METHOD)
realm_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
platform_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
- realm_token_cose_alg = get_cose_alg_from_key(
- realm_token_key,
- AttestationTokenVerifier.COSE_ALG_ES384)
- platform_token_cose_alg = get_cose_alg_from_key(
- platform_token_key,
- AttestationTokenVerifier.COSE_ALG_ES384)
+ realm_token_cose_alg = get_cose_alg_from_key(realm_token_key, Es384)
+ platform_token_cose_alg = get_cose_alg_from_key(platform_token_key, Es384)
verifier = CCATokenVerifier(
realm_token_method=realm_token_method,
realm_token_cose_alg=realm_token_cose_alg,
@@ -112,7 +108,7 @@
elif verifier_class == CCAPlatformTokenVerifier:
key_checked = args.platform_key
key = read_keyfile(args.platform_key, METHOD)
- cose_alg = get_cose_alg_from_key(key, AttestationTokenVerifier.COSE_ALG_ES384)
+ cose_alg = get_cose_alg_from_key(key, Es384)
verifier = CCAPlatformTokenVerifier(
method=AttestationTokenVerifier.SIGN_METHOD_SIGN1,
cose_alg=cose_alg,
@@ -123,9 +119,9 @@
key_checked = args.key
key = read_keyfile(keyfile=args.key, method=METHOD)
if METHOD == AttestationTokenVerifier.SIGN_METHOD_SIGN1:
- cose_alg = get_cose_alg_from_key(key, AttestationTokenVerifier.COSE_ALG_ES256)
+ cose_alg = get_cose_alg_from_key(key, Es256)
else:
- cose_alg = AttestationTokenVerifier.COSE_ALG_HS256
+ cose_alg = HMAC256
verifier = PSA_2_0_0_TokenVerifier(
method=METHOD,
cose_alg=cose_alg,
diff --git a/iat-verifier/scripts/decompile_token b/iat-verifier/scripts/decompile_token
index ae75053..6bcb26f 100755
--- a/iat-verifier/scripts/decompile_token
+++ b/iat-verifier/scripts/decompile_token
@@ -12,6 +12,7 @@
import logging
import sys
+from pycose.algorithms import Es256, Es384
import yaml
from iatverifier.psa_iot_profile1_token_verifier import PSAIoTProfile1TokenVerifier
from iatverifier.psa_2_0_0_token_verifier import PSA_2_0_0_TokenVerifier
@@ -44,14 +45,14 @@
if verifier_class == PSAIoTProfile1TokenVerifier:
verifier = PSAIoTProfile1TokenVerifier(
method=AttestationTokenVerifier.SIGN_METHOD_SIGN1,
- cose_alg=AttestationTokenVerifier.COSE_ALG_ES256,
+ cose_alg=Es256,
signing_key=None,
configuration=None)
elif verifier_class == CCATokenVerifier:
realm_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
platform_token_method = AttestationTokenVerifier.SIGN_METHOD_SIGN1
- realm_token_cose_alg = AttestationTokenVerifier.COSE_ALG_ES384
- platform_token_cose_alg = AttestationTokenVerifier.COSE_ALG_ES384
+ realm_token_cose_alg = Es384
+ platform_token_cose_alg = Es384
verifier = CCATokenVerifier(
realm_token_method=realm_token_method,
realm_token_cose_alg=realm_token_cose_alg,
@@ -60,7 +61,7 @@
platform_token_key=None,
configuration=None)
elif verifier_class == CCAPlatformTokenVerifier:
- cose_alg = AttestationTokenVerifier.COSE_ALG_ES384
+ cose_alg = Es384
verifier = CCAPlatformTokenVerifier(
method=AttestationTokenVerifier.SIGN_METHOD_SIGN1,
cose_alg=cose_alg,
@@ -70,7 +71,7 @@
elif verifier_class == PSA_2_0_0_TokenVerifier:
verifier = PSA_2_0_0_TokenVerifier(
method=AttestationTokenVerifier.SIGN_METHOD_SIGN1,
- cose_alg=AttestationTokenVerifier.COSE_ALG_ES256,
+ cose_alg=Es256,
signing_key=None,
configuration=None)
else:
diff --git a/iat-verifier/setup.py b/iat-verifier/setup.py
index ed5f4d3..b7dcbe8 100644
--- a/iat-verifier/setup.py
+++ b/iat-verifier/setup.py
@@ -23,7 +23,7 @@
'cbor2',
'cryptography',
'ecdsa',
- 'pycose==0.1.2',
+ 'pycose==1.1.0',
'pyyaml',
'pyyaml-include',
],
diff --git a/iat-verifier/tests/data/hmac.key b/iat-verifier/tests/data/hmac.key
index e9569f1..daca3d9 100644
--- a/iat-verifier/tests/data/hmac.key
+++ b/iat-verifier/tests/data/hmac.key
Binary files differ
diff --git a/iat-verifier/tests/data/iat-hmac.cbor b/iat-verifier/tests/data/iat-hmac.cbor
index eb163b0..afd8828 100644
--- a/iat-verifier/tests/data/iat-hmac.cbor
+++ b/iat-verifier/tests/data/iat-hmac.cbor
Binary files differ
diff --git a/iat-verifier/tests/data/iat.yaml b/iat-verifier/tests/data/iat.yaml
index 8c53d1a..7554a99 100644
--- a/iat-verifier/tests/data/iat.yaml
+++ b/iat-verifier/tests/data/iat.yaml
@@ -15,7 +15,7 @@
instance_id: !!binary |
AQcGBQQDAgEADw4NDAsKCQgXFhUUExIREB8eHRwbGhkY
profile_id: http://example.com
-security_lifecycle: SL_SECURED
+security_lifecycle: sl_secured
sw_components:
- measurement_description: TF-M_SHA256MemPreXIP
measurement_value: !!binary |
diff --git a/iat-verifier/tests/data/psa-2_0_0_token.yaml b/iat-verifier/tests/data/psa-2_0_0_token.yaml
index 166ab3b..9b180b7 100644
--- a/iat-verifier/tests/data/psa-2_0_0_token.yaml
+++ b/iat-verifier/tests/data/psa-2_0_0_token.yaml
@@ -10,7 +10,7 @@
instance_id: !!binary |
AfpYdV9lhifOVGDym3UpZxMkjK562eKYS5AoDvy8tQJI
profile_id: http://arm.com/psa/2.0.0
-security_lifecycle: SL_SECURED
+security_lifecycle: sl_secured
sw_components:
- measurement_description: sha-256
measurement_value: !!binary |
diff --git a/iat-verifier/tests/synthetic_data/correct_tagging.cbor b/iat-verifier/tests/synthetic_data/correct_tagging.cbor
index e25fcdb..db837a3 100644
--- a/iat-verifier/tests/synthetic_data/correct_tagging.cbor
+++ b/iat-verifier/tests/synthetic_data/correct_tagging.cbor
Binary files differ
diff --git a/iat-verifier/tests/synthetic_data/invalid_tags.cbor b/iat-verifier/tests/synthetic_data/invalid_tags.cbor
index d155d1a..9f56e3e 100644
--- a/iat-verifier/tests/synthetic_data/invalid_tags.cbor
+++ b/iat-verifier/tests/synthetic_data/invalid_tags.cbor
Binary files differ
diff --git a/iat-verifier/tests/synthetic_data/inverted_p_header.cbor b/iat-verifier/tests/synthetic_data/inverted_p_header.cbor
deleted file mode 100644
index f5c2bb0..0000000
--- a/iat-verifier/tests/synthetic_data/inverted_p_header.cbor
+++ /dev/null
Binary files differ
diff --git a/iat-verifier/tests/synthetic_data/inverted_p_header2.cbor b/iat-verifier/tests/synthetic_data/inverted_p_header2.cbor
deleted file mode 100644
index 7969e64..0000000
--- a/iat-verifier/tests/synthetic_data/inverted_p_header2.cbor
+++ /dev/null
Binary files differ
diff --git a/iat-verifier/tests/synthetic_data/missing_tags.cbor b/iat-verifier/tests/synthetic_data/missing_tags.cbor
index f9f2fb6..f964449 100644
--- a/iat-verifier/tests/synthetic_data/missing_tags.cbor
+++ b/iat-verifier/tests/synthetic_data/missing_tags.cbor
Binary files differ
diff --git a/iat-verifier/tests/synthetic_data/p_header_on.cbor b/iat-verifier/tests/synthetic_data/p_header_on.cbor
deleted file mode 100644
index 3b628c0..0000000
--- a/iat-verifier/tests/synthetic_data/p_header_on.cbor
+++ /dev/null
Binary files differ
diff --git a/iat-verifier/tests/synthetic_data/unexpected_tags.cbor b/iat-verifier/tests/synthetic_data/unexpected_tags.cbor
index 172bf82..b514754 100644
--- a/iat-verifier/tests/synthetic_data/unexpected_tags.cbor
+++ b/iat-verifier/tests/synthetic_data/unexpected_tags.cbor
Binary files differ
diff --git a/iat-verifier/tests/synthetic_data/unknown_claims.cbor b/iat-verifier/tests/synthetic_data/unknown_claims.cbor
index 58987a2..3bd8ac4 100644
--- a/iat-verifier/tests/synthetic_data/unknown_claims.cbor
+++ b/iat-verifier/tests/synthetic_data/unknown_claims.cbor
Binary files differ
diff --git a/iat-verifier/tests/synthetic_token_verifier.py b/iat-verifier/tests/synthetic_token_verifier.py
index 96d9a8c..80d9f8a 100644
--- a/iat-verifier/tests/synthetic_token_verifier.py
+++ b/iat-verifier/tests/synthetic_token_verifier.py
@@ -10,6 +10,9 @@
token types.
"""
+from pycose.headers import Algorithm
+from pycose.algorithms import Es256
+
from iatverifier.attest_token_verifier import AttestationTokenVerifier as Verifier
from iatverifier.attest_token_verifier import AttestationClaim as Claim
from tests.synthetic_token_claims import SynClaimInt, SynBoxesClaim, BoxWidthClaim
@@ -24,14 +27,19 @@
return 'SYNTHETIC_TOKEN'
def _get_p_header(self):
- return None
+ return {Algorithm: self._get_cose_alg()}
def _get_wrapping_tag(self):
return None
def _parse_p_header(self, msg):
- if (len(msg.protected_header) > 0):
- raise ValueError('Unexpected protected header')
+ alg = self._get_cose_alg()
+ try:
+ msg_alg = msg.get_attr(Algorithm)
+ except AttributeError:
+ raise ValueError('Missing alg from protected header (expected {})'.format(alg))
+ if alg != msg_alg:
+ raise ValueError('Unexpected alg in protected header (expected {} instead of {})'.format(alg, msg_alg))
def __init__(self, *, method, cose_alg, signing_key, configuration, internal_signing_key):
# First prepare the claim hierarchy for this token
@@ -61,7 +69,7 @@
(BoxColorClaim, {'verifier': self, 'necessity': Claim.MANDATORY}),
(SyntheticInternalTokenVerifier, {'necessity': Claim.OPTIONAL,
'method': Verifier.SIGN_METHOD_SIGN1,
- 'cose_alg': Verifier.COSE_ALG_ES256,
+ 'cose_alg': Es256,
'claims': internal_verifier_claims,
'configuration': configuration,
'signing_key': internal_signing_key}),
@@ -94,13 +102,13 @@
return 'SYNTHETIC_TOKEN_2'
def _get_p_header(self):
- return {'alg': self.cose_alg}
+ return {Algorithm: self._get_cose_alg()}
def _parse_p_header(self, msg):
alg = self._get_cose_alg()
try:
- msg_alg = msg.protected_header['alg']
- except KeyError as exc:
+ msg_alg = msg.get_attr(Algorithm)
+ except AttributeError as exc:
raise ValueError(f'Missing alg from protected header (expected {alg})') from exc
if alg != msg_alg:
raise ValueError('Unexpected alg in protected header ' +
@@ -137,7 +145,7 @@
(BoxColorClaim, {'verifier': self, 'necessity': Claim.MANDATORY}),
(SyntheticInternalTokenVerifier2, {'necessity': Claim.OPTIONAL,
'method': Verifier.SIGN_METHOD_SIGN1,
- 'cose_alg': Verifier.COSE_ALG_ES256,
+ 'cose_alg': Es256,
'claims': internal_verifier_claims,
'configuration': configuration,
'signing_key': internal_signing_key}),
@@ -171,13 +179,13 @@
return 'SYNTHETIC_INTERNAL_TOKEN'
def _get_p_header(self):
- return {'alg': self.cose_alg}
+ return {Algorithm: self._get_cose_alg()}
def _parse_p_header(self, msg):
alg = self._get_cose_alg()
try:
- msg_alg = msg.protected_header['alg']
- except KeyError as exc:
+ msg_alg = msg.get_attr(Algorithm)
+ except AttributeError as exc:
raise ValueError(f'Missing alg from protected header (expected {alg})') from exc
if alg != msg_alg:
raise ValueError('Unexpected alg in protected header ' +
@@ -213,11 +221,16 @@
return 'SYNTHETIC_INTERNAL_TOKEN_2'
def _get_p_header(self):
- return None
+ return {Algorithm: self._get_cose_alg()}
def _parse_p_header(self, msg):
- if (len(msg.protected_header) > 0):
- raise ValueError('Unexpected protected header')
+ alg = self._get_cose_alg()
+ try:
+ msg_alg = msg.get_attr(Algorithm)
+ except AttributeError:
+ raise ValueError('Missing alg from protected header (expected {})'.format(alg))
+ if alg != msg_alg:
+ raise ValueError('Unexpected alg in protected header (expected {} instead of {})'.format(alg, msg_alg))
def _get_wrapping_tag(self):
return 0xbbaa
diff --git a/iat-verifier/tests/test_synthetic.py b/iat-verifier/tests/test_synthetic.py
index 796e845..89d529d 100644
--- a/iat-verifier/tests/test_synthetic.py
+++ b/iat-verifier/tests/test_synthetic.py
@@ -13,6 +13,8 @@
import os
import unittest
+from pycose.algorithms import Es256, Es384
+
from iatverifier.util import read_token_map, read_keyfile
from iatverifier.attest_token_verifier import VerifierConfiguration, AttestationTokenVerifier
from tests.synthetic_token_verifier import SyntheticTokenVerifier2, SyntheticTokenVerifier
@@ -35,7 +37,7 @@
def test_composite(self):
"""Test cross claim checking in composite claim"""
method=AttestationTokenVerifier.SIGN_METHOD_SIGN1
- cose_alg=AttestationTokenVerifier.COSE_ALG_ES256
+ cose_alg=Es256
signing_key = read_keyfile(KEYFILE, method)
create_and_read_iat(
@@ -83,57 +85,9 @@
self.assertIn(
'Invalid IAT: Box size must have all 3 dimensions', test_ctx.exception.args[0])
- def test_protected_header(self):
- """Test protected header detection"""
- source_path = os.path.join(DATA_DIR, 'synthetic_token_another_token.yaml')
- token_map = read_token_map(source_path)
-
- method=AttestationTokenVerifier.SIGN_METHOD_SIGN1
- cose_alg=AttestationTokenVerifier.COSE_ALG_ES256
- signing_key = read_keyfile(KEYFILE, method)
- config = VerifierConfiguration(keep_going=True, strict=True)
-
- verifier = SyntheticTokenVerifier(
- method=method,
- cose_alg=cose_alg,
- signing_key=signing_key,
- configuration=self.config,
- internal_signing_key=signing_key)
-
- token_p_header = convert_map_to_token_bytes(token_map, verifier)
-
- self.assertTrue(
- bytes_equal_to_file(token_p_header, os.path.join(DATA_DIR, 'p_header_on.cbor')))
-
- with self.assertLogs() as test_ctx:
- read_iat(
- DATA_DIR,
- 'inverted_p_header.cbor',
- SyntheticTokenVerifier(method=method,
- cose_alg=cose_alg,
- signing_key=signing_key,
- configuration=config,
- internal_signing_key=signing_key))
- self.assertEquals(2, len(test_ctx.output))
- self.assertIn('Unexpected protected header', test_ctx.output[0])
- self.assertIn('Missing alg from protected header (expected ES256)', test_ctx.output[1])
-
- with self.assertLogs() as test_ctx:
- read_iat(
- DATA_DIR,
- 'inverted_p_header2.cbor',
- SyntheticTokenVerifier2(method=method,
- cose_alg=cose_alg,
- signing_key=signing_key,
- configuration=config,
- internal_signing_key=signing_key))
- self.assertEquals(2, len(test_ctx.output))
- self.assertIn('Missing alg from protected header (expected ES256)', test_ctx.output[0])
- self.assertIn('Unexpected protected header', test_ctx.output[1])
-
def test_tagging_support(self):
method=AttestationTokenVerifier.SIGN_METHOD_SIGN1
- cose_alg=AttestationTokenVerifier.COSE_ALG_ES256
+ cose_alg=Es256
signing_key = read_keyfile(KEYFILE, method)
config = VerifierConfiguration(keep_going=True, strict=True)
@@ -148,10 +102,9 @@
signing_key=signing_key,
configuration=config,
internal_signing_key=signing_key))
- self.assertEquals(3, len(test_ctx.output))
+ self.assertEquals(2, len(test_ctx.output))
self.assertIn('Unexpected tag (0xcdcd) in token SYNTHETIC_TOKEN', test_ctx.output[0])
- self.assertIn('Invalid Protected header: Missing alg from protected header (expected ES256)', test_ctx.output[1])
- self.assertIn('Unexpected tag (0xabab) in token SYNTHETIC_INTERNAL_TOKEN', test_ctx.output[2])
+ self.assertIn('Unexpected tag (0xabab) in token SYNTHETIC_INTERNAL_TOKEN', test_ctx.output[1])
# test with missing tag
with self.assertLogs() as test_ctx:
@@ -194,7 +147,7 @@
def test_unknown_claims(self):
method=AttestationTokenVerifier.SIGN_METHOD_SIGN1
- cose_alg=AttestationTokenVerifier.COSE_ALG_ES256
+ cose_alg=Es256
signing_key = read_keyfile(KEYFILE, method)
config = VerifierConfiguration(keep_going=True, strict=False)
diff --git a/iat-verifier/tests/test_utils.py b/iat-verifier/tests/test_utils.py
index c769644..ab7c182 100644
--- a/iat-verifier/tests/test_utils.py
+++ b/iat-verifier/tests/test_utils.py
@@ -39,7 +39,7 @@
return bytes_io.getvalue()
def create_token(data_dir, source_name, verifier):
- """Creats a cbor token from a yaml file."""
+ """Create a cbor token from a yaml file."""
source_path = os.path.join(data_dir, source_name)
token_map = read_token_map(source_path)
return convert_map_to_token_bytes(token_map, verifier)
diff --git a/iat-verifier/tests/test_verifier.py b/iat-verifier/tests/test_verifier.py
index 2b7fe92..48604b1 100644
--- a/iat-verifier/tests/test_verifier.py
+++ b/iat-verifier/tests/test_verifier.py
@@ -10,6 +10,8 @@
import os
import unittest
+from pycose.algorithms import Es256, Es384
+
from iatverifier.psa_iot_profile1_token_verifier import PSAIoTProfile1TokenVerifier
from iatverifier.cca_token_verifier import CCATokenVerifier, CCAPlatformTokenVerifier
from iatverifier.util import read_keyfile
@@ -38,7 +40,7 @@
def test_validate_signature(self):
"""Testing Signature validation"""
method=AttestationTokenVerifier.SIGN_METHOD_SIGN1
- cose_alg=AttestationTokenVerifier.COSE_ALG_ES256
+ cose_alg=Es256
signing_key = read_keyfile(KEYFILE, method)
verifier_good_sig = PSAIoTProfile1TokenVerifier(
@@ -77,7 +79,7 @@
"""Testing IAT structure validation"""
keep_going_conf = VerifierConfiguration(keep_going=True)
method=AttestationTokenVerifier.SIGN_METHOD_SIGN1
- cose_alg=AttestationTokenVerifier.COSE_ALG_ES256
+ cose_alg=Es256
signing_key = read_keyfile(KEYFILE, method)
realm_token_key = read_keyfile(KEYFILE_CCA_REALM, method)
realm_token_key2 = read_keyfile(KEYFILE_CCA_REALM2, method)
@@ -97,10 +99,10 @@
'valid-cca-token.yaml',
CCATokenVerifier(
realm_token_method=method,
- realm_token_cose_alg=AttestationTokenVerifier.COSE_ALG_ES384,
+ realm_token_cose_alg=Es384,
realm_token_key=realm_token_key,
platform_token_method=method,
- platform_token_cose_alg=AttestationTokenVerifier.COSE_ALG_ES384,
+ platform_token_cose_alg=Es384,
platform_token_key=platform_token_key,
configuration=self.config))
@@ -109,7 +111,7 @@
'cca_platform_token.yaml',
CCAPlatformTokenVerifier(
method=method,
- cose_alg=AttestationTokenVerifier.COSE_ALG_ES384,
+ cose_alg=Es384,
signing_key=platform_token_key,
configuration=self.config,
necessity=AttestationClaim.MANDATORY))
@@ -120,10 +122,10 @@
'cca-invalid-plat-challenge.yaml',
CCATokenVerifier(
realm_token_method=method,
- realm_token_cose_alg=AttestationTokenVerifier.COSE_ALG_ES384,
+ realm_token_cose_alg=Es384,
realm_token_key=realm_token_key,
platform_token_method=method,
- platform_token_cose_alg=AttestationTokenVerifier.COSE_ALG_ES384,
+ platform_token_cose_alg=Es384,
platform_token_key=platform_token_key,
configuration=self.config))
self.assertIn("Invalid CCA_PLATFORM_CHALLENGE byte at 16: 0x00 instead of 0xe4", test_ctx.exception.args[0])
@@ -134,10 +136,10 @@
'valid-cca-token.yaml',
CCATokenVerifier(
realm_token_method=method,
- realm_token_cose_alg=AttestationTokenVerifier.COSE_ALG_ES384,
+ realm_token_cose_alg=Es384,
realm_token_key=realm_token_key2,
platform_token_method=method,
- platform_token_cose_alg=AttestationTokenVerifier.COSE_ALG_ES384,
+ platform_token_cose_alg=Es384,
platform_token_key=platform_token_key,
configuration=self.config))
self.assertIn("Realm signature doesn't match Realm Public Key claim in Realm token", test_ctx.exception.args[0])
@@ -243,7 +245,7 @@
def test_binary_string_decoding(self):
"""Test binary_string decoding"""
method=AttestationTokenVerifier.SIGN_METHOD_SIGN1
- cose_alg=AttestationTokenVerifier.COSE_ALG_ES256
+ cose_alg=Es256
signing_key = read_keyfile(KEYFILE, method)
iat = create_and_read_iat(
DATA_DIR,
@@ -257,7 +259,7 @@
def test_security_lifecycle_decoding(self):
"""Test security lifecycle decoding"""
method=AttestationTokenVerifier.SIGN_METHOD_SIGN1
- cose_alg=AttestationTokenVerifier.COSE_ALG_ES256
+ cose_alg=Es256
signing_key = read_keyfile(KEYFILE, method)
iat = create_and_read_iat(
DATA_DIR,