Esempio n. 1
0
def _dgc(config_env: Dict) -> Sign1Message:
    if COSE in config_env.keys():
        cbor_bytes = unhexlify(config_env[COSE])
        cbor_object = loads(cbor_bytes, object_hook=_object_hook_e)
        if isinstance(cbor_object, CBORTag):  # Tagged Cose Object
            if isinstance(cbor_object.value,
                          CBORTag):  # Double Tagged Cose Object
                decoded = Sign1Message.from_cose_obj(cbor_object.value.value)
            else:
                decoded = Sign1Message.decode(cbor_bytes)
        else:  # Un-tagged Cose Object
            decoded = Sign1Message.from_cose_obj(cbor_object)
        return decoded
Esempio n. 2
0
def test_simple_sign1message():
    msg = Sign1Message(
        phdr={Algorithm: EdDSA, KID: b'kid2'},
        payload='signed message'.encode('utf-8')
    )

    assert str(msg) == "<COSE_Sign1: [{'Algorithm': 'EdDSA', 'KID': b'kid2'}, {}, b'signe' ... (14 B), b'' ... (0 B)]>"

    cose_key = {
        KpKty: KtyOKP,
        OKPKpCurve: Ed25519,
        KpKeyOps: [SignOp, VerifyOp],
        OKPKpD: unhexlify(b'9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60'),
        OKPKpX: unhexlify(b'd75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a')}

    cose_key = CoseKey.from_dict(cose_key)
    assert str(cose_key) == "<COSE_Key(OKPKey): {'OKPKpD': \"b'\\\\x9da\\\\xb1\\\\x9d\\\\xef' ... (32 B)\"," \
                            " 'OKPKpX': \"b'\\\\xd7Z\\\\x98\\\\x01\\\\x82' ... (32 B)\"," \
                            " 'OKPKpCurve': 'Ed25519', 'KpKty': 'KtyOKP', 'KpKeyOps': ['SignOp', 'VerifyOp']}>"

    msg.key = cose_key
    encoded = msg.encode()
    assert hexlify(encoded) == b'd28449a2012704446b696432a04e7369676e6564206d6573736167655840cc87665ffd3' \
                               b'fa33d96f3b606fcedeaef839423221872d0bfa196e069a189a607c2284924c3abb80e94' \
                               b'2466cd300cc5d18fe4e5ea1f3ebdb62ef8419109447d03'

    decoded = CoseMessage.decode(encoded)
    assert str(decoded) == "<COSE_Sign1: [{'Algorithm': 'EdDSA', 'KID': b'kid2'}, {}, b'signe' ... (14 B), " \
                           "b'\\xcc\\x87f_\\xfd' ... (64 B)]>"

    decoded.key = cose_key
    assert decoded.verify_signature()
    assert decoded.payload == b'signed message'
Esempio n. 3
0
 def _signature_or_mac(self, mac: bytes, transcript: bytes,
                       aad_cb: Callable[..., bytes]) -> bytes:
     if not self.is_static_dh(self.role):
         cose_sign = Sign1Message(
             phdr=self.cred_id,
             uhdr={headers.Algorithm: self.cipher_suite.sign_alg},
             payload=mac,
             key=self.auth_key,
             external_aad=self._external_aad(self.cred, transcript, aad_cb))
         return cose_sign.compute_signature()
     else:
         return mac
Esempio n. 4
0
    def _verify_signature_or_mac2(self, signature_or_mac2: bytes) -> bool:
        mac_2 = self._mac(self.cred_idr, self.remote_cred, self._hkdf2, 'K_2m',
                          16, 'IV_2m', 13, self._th2_input, self._prk3e2m,
                          self.aad2_cb)

        if not self.is_static_dh(self.remote_role):
            external_aad = self._external_aad(self.remote_cred,
                                              self._th2_input, self.aad2_cb)
            cose_sign = Sign1Message(
                phdr=self.cred_idr,
                uhdr={headers.Algorithm: self.cipher_suite.sign_alg},
                payload=mac_2,
                external_aad=external_aad)
            # FIXME peeking into internals (probably best resolved at pycose level)
            cose_sign.key = self.remote_authkey
            cose_sign._signature = signature_or_mac2
            return cose_sign.verify_signature()
        else:
            return signature_or_mac2 == mac_2
Esempio n. 5
0
def create_cose_1_sign_msg(payload, private_key):
    crv = P384
    d_value = private_key.private_numbers().private_value
    x_coor = private_key.public_key().public_numbers().x
    y_coor = private_key.public_key().public_numbers().y

    key = EC2Key(
        crv=crv,
        d=d_value.to_bytes(crv.size, "big"),
        x=x_coor.to_bytes(crv.size, "big"),
        y=y_coor.to_bytes(crv.size, "big"),
    )

    phdr = {1: Es384}
    msg = Sign1Message(phdr=phdr, payload=payload, key=key)

    sig = msg.compute_signature()
    msg._signature = sig

    return msg.encode(tag=False)
Esempio n. 6
0
def verify_attestation_signature(payload, cert):
    logger.debug("* Verifying attestation certificate signature...")
    cert = load_der_x509_certificate(cert)
    cert_public_numbers = cert.public_key().public_numbers()
    x = cert_public_numbers.x
    y = cert_public_numbers.y

    x = _long_to_bytes(x)
    y = _long_to_bytes(y)

    # Create the EC2 key from public key parameters
    key = EC2Key(x=x, y=y, crv=P384)

    cose_obj = cbor2.loads(payload)
    msg = Sign1Message.from_cose_obj(cose_obj, allow_unknown_attributes=True)
    msg.key = key

    # Verify the signature using the EC2 key
    verified = msg.verify_signature()
    if not verified:
        errmsg = "Malformed attestation doc: incorrect certificate signature."
        logger.error(errmsg)
        raise RuntimeError(errmsg)
    logger.debug("* Attestation certificate signature verified.")
    def test(self):
        print('\nTest: ' + __name__ + '.' + type(self).__name__)
        private_key = EC2Key(
            crv=curves.P256,
            x=binascii.unhexlify('44c1fa63b84f172b50541339c50beb0e630241ecb4eebbddb8b5e4fe0a1787a8'),
            y=binascii.unhexlify('059451c7630d95d0b550acbd02e979b3f4f74e645b74715fafbc1639960a0c7a'),
            d=binascii.unhexlify('dd6e7d8c4c0e0c0bd3ae1b4a2fa86b9a09b7efee4a233772cf5189786ea63842'),
            optional_params={
                keyparam.KpKid: b'ExampleEC2',
                keyparam.KpKeyOps: [keyops.SignOp, keyops.VerifyOp],
            }
        )
        print('Private Key: {}'.format(encode_diagnostic(cbor2.loads(private_key.encode()))))

        # Primary block
        prim_dec = self._get_primary_item()
        prim_enc = cbor2.dumps(prim_dec)
        print('Primary Block: {}'.format(encode_diagnostic(prim_dec)))
        print('Encoded: {}'.format(encode_diagnostic(prim_enc)))

        # Security target block
        target_dec = self._get_target_item()
        target_enc = cbor2.dumps(target_dec)
        content_plaintext = target_dec[4]
        print('Target Block: {}'.format(encode_diagnostic(target_dec)))
        print('Plaintext: {}'.format(encode_diagnostic(content_plaintext)))

        # Combined AAD
        ext_aad_dec = self._get_aad_item()
        ext_aad_enc = cbor2.dumps(ext_aad_dec)
        print('External AAD: {}'.format(encode_diagnostic(ext_aad_dec)))
        print('Encoded: {}'.format(encode_diagnostic(ext_aad_enc)))

        msg_obj = Sign1Message(
            phdr={
                headers.Algorithm: algorithms.Es256,
            },
            uhdr={
                headers.KID: private_key.kid,
            },
            payload=content_plaintext,
            # Non-encoded parameters
            external_aad=ext_aad_enc,
        )
        msg_obj.key = private_key

        # COSE internal structure
        cose_struct_enc = msg_obj._sig_structure
        cose_struct_dec = cbor2.loads(cose_struct_enc)
        print('COSE Structure: {}'.format(encode_diagnostic(cose_struct_dec)))
        print('Encoded: {}'.format(encode_diagnostic(cose_struct_enc)))

        # Encoded message
        message_enc = msg_obj.encode(tag=False)
        message_dec = cbor2.loads(message_enc)
        # Detach the payload
        content_signature = message_dec[2]
        message_dec[2] = None
        self._print_message(message_dec, recipient_idx=4)
        message_enc = cbor2.dumps(message_dec)

        # ASB structure
        asb_dec = self._get_asb_item([
            msg_obj.cbor_tag,
            message_enc
        ])
        asb_enc = self._get_asb_enc(asb_dec)
        print('ASB: {}'.format(encode_diagnostic(asb_dec)))
        print('Encoded: {}'.format(encode_diagnostic(asb_enc)))

        bpsec_dec = self._get_bpsec_item(
            block_type=BlockType.BIB,
            asb_dec=asb_dec,
        )
        bpsec_enc = cbor2.dumps(bpsec_dec)
        print('BPSec block: {}'.format(encode_diagnostic(bpsec_dec)))
        print('Encoded: {}'.format(encode_diagnostic(bpsec_enc)))

        # Change from detached payload
        message_dec[2] = content_signature
        decode_obj = Sign1Message.from_cose_obj(message_dec)
        decode_obj.external_aad = ext_aad_enc
        decode_obj.key = private_key

        verify_valid = decode_obj.verify_signature()
        self.assertTrue(verify_valid)
        print('Loopback verify:', verify_valid)

        bundle = self._assemble_bundle([prim_enc, bpsec_enc, target_enc])
        print('Total bundle: {}'.format(encode_diagnostic(bundle)))
Esempio n. 8
0
    def apply_bib(self, ctr):
        if not self._priv_key:
            LOGGER.warning('No private key')
            return

        addl_protected_map = {}
        addl_unprotected = {}
        aad_scope = 0x3

        target_block_nums = [
            blk.block_num for blk in ctr.bundle.blocks
            if blk.type_code in self._config.integrity_for_blocks
        ]
        if not target_block_nums:
            LOGGER.warning('No target blocks have matching type')
            return

        x5chain = []
        for cert in self._cert_chain:
            x5chain.append(cert.public_bytes(serialization.Encoding.DER))
        if self._config.integrity_include_chain:
            addl_protected_map[headers.X5chain.identifier] = X5Chain(
                x5chain).encode()

        # A little switcharoo to avoid cached overload_fields on `data`
        bib = CanonicalBlock(
            type_code=BlockIntegrityBlock._overload_fields[CanonicalBlock]
            ['type_code'],
            block_num=ctr.get_block_num(),
            crc_type=AbstractBlock.CrcType.CRC32,
        )
        bib_data = BlockIntegrityBlock(
            targets=target_block_nums,
            context_id=BPSEC_COSE_CONTEXT_ID,
            context_flags=(AbstractSecurityBlock.Flag.PARAMETERS_PRESENT),
            source=self._config.node_id,
            parameters=[
                TypeValuePair(type_code=5, value=aad_scope),
            ],
        )
        # Inject optional additional headers
        addl_protected = cbor2.dumps(
            addl_protected_map) if addl_protected_map else b''
        if addl_protected:
            bib_data.parameters.append(
                TypeValuePair(type_code=3, value=addl_protected))
        if addl_unprotected:
            bib_data.parameters.append(
                TypeValuePair(type_code=4, value=addl_unprotected))

        try:
            cose_key = self.extract_cose_key(self._priv_key)
        except Exception as err:
            LOGGER.error('Cannot handle private key: %s', repr(err))
            return

        phdr = {
            headers.Algorithm: cose_key.alg,
        }
        uhdr = {
            headers.X5t:
            X5T.from_certificate(algorithms.Sha256, x5chain[0]).encode(),
        }

        # Sign each target with one result per
        target_result = []
        for blk_num in bib_data.getfieldval('targets'):
            target_blk = ctr.block_num(blk_num)
            target_blk.ensure_block_type_specific_data()
            target_plaintext = target_blk.getfieldval('btsd')

            ext_aad_enc = CoseContext.get_bpsec_cose_aad(
                ctr, target_blk, bib, aad_scope, addl_protected)
            LOGGER.debug('Signing target %d AAD %s payload %s', blk_num,
                         encode_diagnostic(ext_aad_enc),
                         encode_diagnostic(target_plaintext))
            msg_obj = Sign1Message(
                phdr=phdr,
                uhdr=uhdr,
                payload=target_plaintext,
                # Non-encoded parameters
                external_aad=ext_aad_enc,
                key=cose_key)
            LOGGER.debug('Signing with COSE key %s', repr(cose_key))
            msg_enc = msg_obj.encode(tag=False)
            # detach payload
            msg_dec = cbor2.loads(msg_enc)
            msg_dec[2] = None
            msg_enc = cbor2.dumps(msg_dec)
            LOGGER.debug('Sending COSE message %s', encode_diagnostic(msg_dec))

            target_result.append(
                TypeValuePair(type_code=msg_obj.cbor_tag, value=msg_enc))

        # One result per target
        bib_data.setfieldval(
            'results',
            [TargetResultList(results=[result]) for result in target_result])
        bib.add_payload(bib_data)
        ctr.add_block(bib)
Esempio n. 9
0
def test_unknown_header_attribute_encoding_decoding():
    msg = Enc0Message(phdr={
        Algorithm: AESCCM1664128,
        "Custom-Header-Attr1": 7879
    },
                      uhdr={
                          KID: 8,
                          IV: unhexlify(b'00000000000000000000000000'),
                          "Custom-Header-Attr2": 879
                      })
    msg.key = SymmetricKey.generate_key(key_len=16)

    assert "Custom-Header-Attr1" in msg.phdr
    assert "Custom-Header-Attr2" in msg.uhdr

    msg = msg.encode()

    msg_decoded = CoseMessage.decode(msg)
    assert "Custom-Header-Attr1" in msg_decoded.phdr
    assert "Custom-Header-Attr2" in msg_decoded.uhdr

    msg = EncMessage(phdr={
        Algorithm: AESCCM1664128,
        "Custom-Header-Attr1": 7879
    },
                     uhdr={
                         KID: 8,
                         IV: unhexlify(b'00000000000000000000000000'),
                         "Custom-Header-Attr2": 878
                     },
                     recipients=[
                         DirectEncryption(uhdr={
                             Algorithm: Direct,
                             "Custom-Header-Attr3": 9999
                         })
                     ])
    msg.key = SymmetricKey.generate_key(key_len=16)

    assert "Custom-Header-Attr1" in msg.phdr
    assert "Custom-Header-Attr2" in msg.uhdr
    assert "Custom-Header-Attr3" in msg.recipients[0].uhdr

    msg = msg.encode()

    msg_decoded = CoseMessage.decode(msg)
    assert "Custom-Header-Attr1" in msg_decoded.phdr
    assert "Custom-Header-Attr2" in msg_decoded.uhdr
    assert "Custom-Header-Attr3" in msg_decoded.recipients[0].uhdr

    msg = Mac0Message(phdr={
        Algorithm: HMAC256,
        "Custom-Header-Attr1": 7879
    },
                      uhdr={
                          KID: 8,
                          IV: unhexlify(b'00000000000000000000000000'),
                          "Custom-Header-Attr2": 878
                      })
    msg.key = SymmetricKey.generate_key(key_len=16)

    assert "Custom-Header-Attr1" in msg.phdr
    assert "Custom-Header-Attr2" in msg.uhdr

    msg = msg.encode()

    msg_decoded = CoseMessage.decode(msg)

    assert "Custom-Header-Attr1" in msg_decoded.phdr
    assert "Custom-Header-Attr2" in msg_decoded.uhdr

    msg = MacMessage(phdr={
        Algorithm: HMAC256,
        "Custom-Header-Attr1": 7879
    },
                     uhdr={
                         KID: 8,
                         IV: unhexlify(b'00000000000000000000000000'),
                         "Custom-Header-Attr2": 878
                     },
                     recipients=[
                         DirectEncryption(uhdr={
                             Algorithm: Direct,
                             "Custom-Header-Attr3": 9999
                         })
                     ])
    msg.key = SymmetricKey.generate_key(key_len=16)

    assert "Custom-Header-Attr1" in msg.phdr
    assert "Custom-Header-Attr2" in msg.uhdr
    assert "Custom-Header-Attr3" in msg.recipients[0].uhdr

    msg = msg.encode()

    msg_decoded = CoseMessage.decode(msg)
    assert "Custom-Header-Attr1" in msg_decoded.phdr
    assert "Custom-Header-Attr2" in msg_decoded.uhdr
    assert "Custom-Header-Attr3" in msg_decoded.recipients[0].uhdr

    msg = SignMessage(phdr={"Custom-Header-Attr1": 7879},
                      uhdr={
                          KID: 8,
                          IV: unhexlify(b'00000000000000000000000000'),
                          "Custom-Header-Attr2": 878
                      },
                      signers=[
                          CoseSignature(phdr={
                              Algorithm: Es256,
                              "Custom-Header-Attr3": 9999
                          },
                                        key=EC2Key.generate_key(crv=P256))
                      ])

    assert "Custom-Header-Attr1" in msg.phdr
    assert "Custom-Header-Attr2" in msg.uhdr

    msg = msg.encode()

    msg_decoded = CoseMessage.decode(msg)

    assert "Custom-Header-Attr1" in msg_decoded.phdr
    assert "Custom-Header-Attr2" in msg_decoded.uhdr
    assert "Custom-Header-Attr3" in msg_decoded.signers[0].phdr

    msg = Sign1Message(phdr={
        Algorithm: Es256,
        "Custom-Header-Attr1": 7879
    },
                       uhdr={
                           KID: 8,
                           "Custom-Header-Attr2": 878
                       })
    msg.key = EC2Key.generate_key(crv=P256)

    assert "Custom-Header-Attr1" in msg.phdr
    assert "Custom-Header-Attr2" in msg.uhdr

    msg = msg.encode()

    msg_decoded = CoseMessage.decode(msg)
    assert "Custom-Header-Attr1" in msg_decoded.phdr
    assert "Custom-Header-Attr2" in msg_decoded.uhdr
Esempio n. 10
0
    def test(self):
        print('\nTest: ' + __name__ + '.' + type(self).__name__)
        private_key = OKPKey(
            crv=curves.Ed25519,
            x=binascii.unhexlify('64f38ea84b153c7be87349f78261ca46e90f1613a3ceb2ae02c010193631e07d'),
            d=binascii.unhexlify('6820977a9be08d676dac7ee19e1595d0552894ee2d71feb1d7b1d2a9f31754fd'),
            optional_params={
                keyparam.KpKid: b'ExampleEd25519',
                keyparam.KpKeyOps: [keyops.SignOp, keyops.VerifyOp],
            }
        )
        print('Private Key: {}'.format(encode_diagnostic(cbor2.loads(private_key.encode()))))

        # Primary block
        prim_dec = self._get_primary_item()
        prim_enc = cbor2.dumps(prim_dec)
        print('Primary Block: {}'.format(encode_diagnostic(prim_dec)))
        print('Encoded: {}'.format(encode_diagnostic(prim_enc)))

        # Security target block
        target_dec = self._get_target_item()
        target_enc = cbor2.dumps(target_dec)
        content_plaintext = target_dec[4]
        print('Target Block: {}'.format(encode_diagnostic(target_dec)))
        print('Plaintext: {}'.format(encode_diagnostic(content_plaintext)))

        # Combined AAD
        ext_aad_dec = self._get_aad_item()
        ext_aad_enc = cbor2.dumps(ext_aad_dec)
        print('External AAD: {}'.format(encode_diagnostic(ext_aad_dec)))
        print('Encoded: {}'.format(encode_diagnostic(ext_aad_enc)))

        msg_obj = Sign1Message(
            phdr={
                headers.Algorithm: algorithms.EdDSA,
            },
            uhdr={
                headers.KID: private_key.kid,
            },
            payload=content_plaintext,
            # Non-encoded parameters
            external_aad=ext_aad_enc,
        )
        msg_obj.key = private_key

        # COSE internal structure
        cose_struct_enc = msg_obj._sig_structure
        cose_struct_dec = cbor2.loads(cose_struct_enc)
        print('COSE Structure: {}'.format(encode_diagnostic(cose_struct_dec)))
        print('Encoded: {}'.format(encode_diagnostic(cose_struct_enc)))

        # Encoded message
        message_enc = msg_obj.encode(tag=False)
        message_dec = cbor2.loads(message_enc)
        # Detach the payload
        content_signature = message_dec[2]
        message_dec[2] = None
        self._print_message(message_dec, recipient_idx=4)
        message_enc = cbor2.dumps(message_dec)

        # ASB structure
        asb_dec = self._get_asb_item([
            msg_obj.cbor_tag,
            message_enc
        ])
        asb_enc = self._get_asb_enc(asb_dec)
        print('ASB: {}'.format(encode_diagnostic(asb_dec)))
        print('Encoded: {}'.format(encode_diagnostic(asb_enc)))

        bpsec_dec = self._get_bpsec_item(
            block_type=BlockType.BIB,
            asb_dec=asb_dec,
        )
        bpsec_enc = cbor2.dumps(bpsec_dec)
        print('BPSec block: {}'.format(encode_diagnostic(bpsec_dec)))
        print('Encoded: {}'.format(encode_diagnostic(bpsec_enc)))

        # Change from detached payload
        message_dec[2] = content_signature
        decode_obj = Sign1Message.from_cose_obj(message_dec)
        decode_obj.external_aad = ext_aad_enc
        decode_obj.key = private_key

        verify_valid = decode_obj.verify_signature()
        self.assertTrue(verify_valid)
        print('Loopback verify:', verify_valid)

        bundle = self._assemble_bundle([prim_enc, bpsec_enc, target_enc])
        print('Total bundle: {}'.format(encode_diagnostic(bundle)))
Esempio n. 11
0
    def test(self):
        print('\nTest: ' + __name__ + '.' + type(self).__name__)
        # 1024-bit key
        private_key = RSAKey(
            n=binascii.unhexlify(
                b'b0b5fd85f52c91844007443c9f9371980025f76d51fc9c67681231da610cb291ba637ce813bffdb2e9c653258607389ec97dad3db295fded67744ed620707db36804e74e56a494030a73608fc8d92f2f0578d2d85cc201ef0ff22d7835d2d147d3b90a6884276235a01c2be99dfc597f79554362fc1eb03639cac5ccaddb2925'
            ),
            e=binascii.unhexlify(b'010001'),
            d=binascii.unhexlify(
                b'9b5d26ad6445ef1aab80b809e4f329684e9912d556c4166f041d1b1fb93c04b4037ffd0dbe6f8a8a86e70bab6e0f6344983a9ada27ed9ff7de816fdeeb5e7be48e607ce5fda4581ca6338a9e019fb3689b28934192b6a190cdda910abb5a86a2f7b6f9cd5011049d8de52ddfef73aa06df401c55623ec196720f54920deb4f01'
            ),
            p=binascii.unhexlify(
                b'db22d94e7784a27b568cbf985307ea8d6430ff6b88c18a7086fd4f57a326572f2250c39e48a6f8e2201661c2dfe12c7386835b649714d050aa36123ec3d00e75'
            ),
            q=binascii.unhexlify(
                b'ce7016adc5f326b7520397c5978ee2f50e69279983d54c5d76f05bcd61de0879d7056c923540dff9cbae95dcc0e5e86b52b3c902dc9669c8021c69557effb9f1'
            ),
            dp=binascii.unhexlify(
                b'6a6fcaccea106a3b2e16bf18e57b7ad9a2488a4758ed68a8af686a194f0d585b7477760c738d6665aee0302bcf4237ad0530d83b4b86b887f5a4bdc7eea427e1'
            ),
            dq=binascii.unhexlify(
                b'28a4cae245b1dcb285142e027a1768b9c4af915b59285a93a0422c60e05edd9e57663afd023d169bd0ad3bd62da8563d231840802ebbf271ad70b8905ba3af91'
            ),
            qinv=binascii.unhexlify(
                b'07b5a61733896270a6bd2bb1654194c54e2bc0e061b543a4ed9fa73c4bc79c87148aa92a451c4ab8262b6377a9c7b97f869160ca6f5d853ee4b65f4f92865ca3'
            ),
            optional_params={
                keyparam.KpKid: b'ExampleRSA',
                keyparam.KpKeyOps: [keyops.SignOp, keyops.VerifyOp],
            })
        print('Private Key: {}'.format(
            encode_diagnostic(cbor2.loads(private_key.encode()))))

        # Primary block
        prim_dec = self._get_primary_item()
        prim_enc = cbor2.dumps(prim_dec)
        print('Primary Block: {}'.format(encode_diagnostic(prim_dec)))
        print('Encoded: {}'.format(encode_diagnostic(prim_enc)))

        # Security target block
        target_dec = self._get_target_item()
        target_enc = cbor2.dumps(target_dec)
        content_plaintext = target_dec[4]
        print('Target Block: {}'.format(encode_diagnostic(target_dec)))
        print('Plaintext: {}'.format(encode_diagnostic(content_plaintext)))

        # Combined AAD
        ext_aad_dec = self._get_aad_item()
        ext_aad_enc = cbor2.dumps(ext_aad_dec)
        print('External AAD: {}'.format(encode_diagnostic(ext_aad_dec)))
        print('Encoded: {}'.format(encode_diagnostic(ext_aad_enc)))

        msg_obj = Sign1Message(
            phdr={
                headers.Algorithm: algorithms.Ps256,
            },
            uhdr={
                headers.KID: private_key.kid,
            },
            payload=content_plaintext,
            # Non-encoded parameters
            external_aad=ext_aad_enc,
        )
        msg_obj.key = private_key

        # COSE internal structure
        cose_struct_enc = msg_obj._sig_structure
        cose_struct_dec = cbor2.loads(cose_struct_enc)
        print('COSE Structure: {}'.format(encode_diagnostic(cose_struct_dec)))
        print('Encoded: {}'.format(encode_diagnostic(cose_struct_enc)))

        # Encoded message
        message_enc = msg_obj.encode(tag=False)
        message_dec = cbor2.loads(message_enc)
        # Detach the payload
        content_signature = message_dec[2]
        message_dec[2] = None
        self._print_message(message_dec, recipient_idx=4)
        message_enc = cbor2.dumps(message_dec)

        # ASB structure
        asb_dec = self._get_asb_item([msg_obj.cbor_tag, message_enc])
        asb_enc = self._get_asb_enc(asb_dec)
        print('ASB: {}'.format(encode_diagnostic(asb_dec)))
        print('Encoded: {}'.format(encode_diagnostic(asb_enc)))

        bpsec_dec = self._get_bpsec_item(
            block_type=BlockType.BIB,
            asb_dec=asb_dec,
        )
        bpsec_enc = cbor2.dumps(bpsec_dec)
        print('BPSec block: {}'.format(encode_diagnostic(bpsec_dec)))
        print('Encoded: {}'.format(encode_diagnostic(bpsec_enc)))

        # Change from detached payload
        message_dec[2] = content_signature
        decode_obj = Sign1Message.from_cose_obj(message_dec)
        decode_obj.external_aad = ext_aad_enc
        decode_obj.key = private_key

        verify_valid = decode_obj.verify_signature()
        self.assertTrue(verify_valid)
        print('Loopback verify:', verify_valid)

        bundle = self._assemble_bundle([prim_enc, bpsec_enc, target_enc])
        print('Total bundle: {}'.format(encode_diagnostic(bundle)))
Esempio n. 12
0
def verify_attestation_doc(attestation_doc, root_cert_pem = None, bech32hrp = "crocnclconspub"):
    """
    Verify the attestation document
    If invalid, raise an exception
    """
    # Decode CBOR attestation document
    data = cbor2.loads(attestation_doc)

    # Load and decode document payload
    doc = data[2]
    doc_obj = cbor2.loads(doc)

    # https://github.com/aws/aws-nitro-enclaves-nsm-api/blob/main/docs/attestation_process.md
    # 3.2
    if 'module_id' not in doc_obj or len(doc_obj["module_id"]) == 0:
        raise Exception("module_id error")
    if 'digest' not in doc_obj or doc_obj["digest"] != "SHA384":
        raise Exception("digest error")
    if 'timestamp' not in doc_obj or doc_obj["timestamp"] == 0:
        raise Exception("timestamp error")
    time = datetime.fromtimestamp(doc_obj["timestamp"] / 1000)
    print(f"timestamp: {time}")
    # PCRs are printed for verification below
    if 'pcrs' not in doc_obj or len(doc_obj["pcrs"]) > 32 or len(doc_obj["pcrs"]) == 0:
        raise Exception("pcrs error")
    if 'certificate' not in doc_obj:
        raise Exception("certificate error")
    if 'cabundle' not in doc_obj or len(doc_obj["cabundle"]) == 0:
        raise Exception("cabundle error")
    # we also expect user data
    if 'user_data' not in doc_obj:
        raise Exception("user_data error")
    user_data = json.loads(doc_obj['user_data'])
    if 'pubkey' not in user_data or 'key_id' not in user_data:
        raise Exception("user_data error")
    key_id = base64.b64decode(user_data["key_id"])
    pubkey = base64.b64decode(user_data["pubkey"])
    pubkeyb64 = user_data["pubkey"]
    pubkeyb32 = bech32_encode(bech32hrp, list(pubkey))
    print("*** VERIFY user_data below (used AWS KMS key and generated pubkey) ***")
    print(f"AWS KMS key id: {key_id}")
    print(f"validator pubkey (base64): {pubkeyb64}")
    print(f"validator pubkey (bech32): {pubkeyb32}")

    # Get PCRs from attestation document
    document_pcrs_arr = doc_obj['pcrs']

    ###########################
    # Part 1: Validating PCRs #
    ###########################
    print("*** VERIFY PCRs below are complete and correct ***")
    for index in document_pcrs_arr.keys():

        # Get PCR hexcode
        doc_pcr = document_pcrs_arr[index].hex()

        print(f"PCR{index}: {doc_pcr}")


    ################################
    # Part 2: Validating signature #
    ################################

    # Get signing certificate from attestation document
    cert = crypto.load_certificate(crypto.FILETYPE_ASN1, doc_obj['certificate'])
    # Get the key parameters from the cert public key
    cert_public_numbers = cert.get_pubkey().to_cryptography_key().public_numbers()
    x = cert_public_numbers.x
    y = cert_public_numbers.y
    curve = cert_public_numbers.curve
    if curve != P384:
        Exception("Incorrect curve")
    x = long_to_bytes(x)
    y = long_to_bytes(y)

    # Create the EC2 key from public key parameters
    key = EC2(x = x, y = y, crv = P384)


    # Get the protected header from attestation document
    phdr = cbor2.loads(data[0])

    # Construct the Sign1 message
    msg = Sign1Message(phdr = phdr, uhdr = data[1], payload = doc, key = key)
    msg._signature = data[3]
    # Verify the signature using the EC2 key
    if not msg.verify_signature():
        raise Exception("Wrong signature")


    ##############################################
    # Part 3: Validating signing certificate PKI #
    ##############################################
    if root_cert_pem is not None:
        # Create an X509Store object for the CA bundles
        store = crypto.X509Store()

        # Create the CA cert object from PEM string, and store into X509Store
        _cert = crypto.load_certificate(crypto.FILETYPE_PEM, root_cert_pem)
        store.add_cert(_cert)

        # Get the CA bundle from attestation document and store into X509Store
        # Except the first certificate, which is the root certificate
        for _cert_binary in doc_obj['cabundle'][1:]:
            _cert = crypto.load_certificate(crypto.FILETYPE_ASN1, _cert_binary)
            store.add_cert(_cert)

        # Get the X509Store context
        store_ctx = crypto.X509StoreContext(store, cert)
        
        # Validate the certificate
        # If the cert is invalid, it will raise exception
        # assuming this checks all items specified in 3.2.3.1. Certificates validity
        store_ctx.verify_certificate()
    return