class ReplicaList(SequenceOf): componentType = OctetString()
class EndGroupTypeResponseValue(Sequence): componentType = NamedTypes( OptionalNamedType('endGroupValue', OctetString()))
class GroupingControlValue(Sequence): componentType = NamedTypes(NamedType('groupingCookie', GroupCookie()), OptionalNamedType('groupValue', OctetString()))
class CreateGroupTypeResponseValue(Sequence): componentType = NamedTypes( NamedType('createGroupCookie', GroupCookie()), OptionalNamedType('createGroupValue', OctetString()))
class EndGroupTypeRequestValue(Sequence): componentType = NamedTypes( NamedType('endGroupCookie', GroupCookie()), OptionalNamedType('endGroupValue', OctetString()))
def get_symmetric_signature(options, manifestInput, enc_data): input_hash = manifestGet(manifestInput, 'signature.hash') or b'' # There should always be a signing key on create. if not hasattr(options, 'private_key') or not options.private_key: if 'psk-master-key' in manifestInput: try: options.private_key = open(manifestInput['psk-master-key'], 'rb') except: LOG.critical( 'No PSK master key specified and default key ({}) cannot be opened' .format(manifestInput['private-key'])) sys.exit(1) else: LOG.critical( 'Resource is not signed and no PSK master key is provided.') sys.exit(1) if not symmetricArgsOkay(options): LOG.critical('--mac requires:') LOG.critical( ' --private-key: The master key for generating device PSKs') # 80 chars ->| # ================================================================================ LOG.critical( ' --psk-table: the output file for PSKs. This argument is optional/ignored' ) LOG.critical(' when inline encoding is used.') LOG.critical( ' --psk-table-encoding: the encoding to use for the PSK output file.' ) LOG.critical(' Either:') LOG.critical( ' --device-urn: The device URN for the target device (Endpoint Client Name)' ) LOG.critical(' OR:') LOG.critical( ' --filter-id: The filter identifier used to gather device URNs' ) sys.exit(1) # Get SHA-256 hash of content and sign it using private key sha_content = utils.sha_hash(enc_data) # If a hash is provided in the input json, then the encoded content must match the provided hash if input_hash and sha_content != binascii.a2b_hex(input_hash): LOG.critical( 'Manifest hash provided in input file does not match hashed output' ) LOG.critical('Expected: {0}'.format(input_hash)) LOG.critical('Actual: {0}'.format(binascii.b2a_hex(sha_content))) sys.exit(1) # Load a default URN out of the settings file. devices = manifestGet(manifestInput, 'deviceURNs') or [] LOG.info('Loaded device URNs from {!r}'.format(defaults.config)) for dev in devices: LOG.info(' {!r}'.format(dev)) # Optionally load a URN out of the command-line arguments if hasattr(options, 'device_urn') and options.device_urn: cmdDevs = [options.device_urn] LOG.info('Loaded device URNs from input arguments') for dev in cmdDevs: LOG.info(' {!r}'.format(dev)) devices.extend(cmdDevs) if hasattr(options, 'filter_id') and options.filter_id: LOG.critical('Device Filters not supported yet.') sys.exit(1) # Use only unique devices devices = list(set(devices)) crypto_mode = get_crypto_mode(options, manifestInput) payload_key = b'' if hasattr(options, 'payload_key') and options.payload_key: LOG.debug('Converting payload key ({0}) to binary'.format( options.payload_key)) payload_key = bytes(binascii.a2b_hex(options.payload_key)) LOG.debug('Payload key length: {0}'.format(len(payload_key))) master_key = options.private_key.read() vendor_id = manifestGet(manifestInput, 'resource.resource.manifest.vendorId', 'vendorId') class_id = manifestGet(manifestInput, 'resource.resource.manifest.classId', 'classId') iv = os.urandom(13) deviceSymmetricInfos = {} # For each device maxIndexSize = 0 maxRecordSize = 0 LOG.info('Creating per-device validation codes...') for device in devices: LOG.info(' {!r}'.format(device)) hkdf = utils.getDevicePSK_HKDF( cryptoMode(crypto_mode).name, master_key, uuid.UUID(vendor_id).bytes, uuid.UUID(class_id).bytes, b'Authentication') psk = hkdf.derive(bytes(device, 'utf-8')) maxIndexSize = max(maxIndexSize, len(device)) # Now encrypt the hash with the selected AE algorithm. pskCipherData = getDevicePSKData(crypto_mode, psk, iv, sha_content, payload_key) recordData = der_encoder.encode( OctetString( hexValue=binascii.b2a_hex(pskCipherData).decode("ascii"))) maxRecordSize = max(maxRecordSize, len(recordData)) deviceSymmetricInfos[device] = recordData # print (deviceSymmetricInfos) def proto_encode(x): keytable = keytable_pb2.KeyTable() for k, d in x.items(): entry = keytable.entries.add() entry.urn = k entry.opaque = d return keytable.SerializeToString() # Save the symmetric info file encodedSymmertricInfos = { 'json': lambda x: json.JSONEncoder(default=binascii.b2a_base64).encode(x), 'cbor': lambda x: None, 'protobuf': proto_encode, 'text': lambda x: '\n'.join([ ','.join([binascii.b2a_hex(y) for y in (k, d)]) for k, d in x.items() ]) + '\n' # 'inline' : lambda x : None }.get(options.psk_table_encoding)(deviceSymmetricInfos) options.psk_table.write(encodedSymmertricInfos) #========================= # PSK ID is the subject key identifier (hash) of the master key. # The URI of the "certificate" is the location at which to find the key table or key query. # PSK is known only to the signer and the device # PSK Signature is AE(PSK, hash), but it is not included, since it must be distributed in the key table. shaMaster = cryptoHashes.Hash(cryptoHashes.SHA256(), cryptoBackends.default_backend()) shaMaster.update(master_key) subjectKeyIdentifier = shaMaster.finalize() mb = MacBlock(pskID=subjectKeyIdentifier, keyTableIV=iv, keyTableRef='thismessage://1', keyTableVersion=0, keyTableRecordSize=maxRecordSize, keyTableIndexSize=maxIndexSize) macs = [mb] rs = ResourceSignature(hash=sha_content, signatures=[], macs=macs) return rs
class CreateGroupTypeRequestValue(Sequence): componentType = NamedTypes( NamedType('createGroupType', LDAPOID()), OptionalNamedType('createGroupValue', OctetString()))
class NPKIPrivateKey(Sequence): componentType = NamedTypes( NamedType('meta', AlgorithmIdentifier()), NamedType('ciphertext', OctetString()), )
class AlgorithmIdentifierData(Sequence): componentType = NamedTypes(NamedType('salt', OctetString()), NamedType('iteration', Integer()))
class AuthorizationList(Sequence): """Properties of the key pair as in the Keymaster hardware abstraction layer. References: * https://developer.android.com/training/articles/security-key-attestation#certificate_schema_authorizationlist """ componentType = NamedTypes( OptionalNamedType( 'purpose', SetOf(Integer()).subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 1))), OptionalNamedType( 'algorithm', Integer().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 2))), OptionalNamedType( 'keySize', Integer().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 3))), OptionalNamedType( 'digest', SetOf(Integer()).subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 5))), OptionalNamedType( 'padding', SetOf(Integer()).subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 6))), OptionalNamedType( 'ecCurve', Integer().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 10))), OptionalNamedType( 'rsaPublicExponent', Integer().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 200))), OptionalNamedType( 'rollbackResistance', Null().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 303))), OptionalNamedType( 'activeDateTime', Integer().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 400))), OptionalNamedType( 'originationExpireDateTime', Integer().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 401))), OptionalNamedType( 'usageExpireDateTime', Integer().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 402))), OptionalNamedType( 'noAuthRequired', Null().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 503))), OptionalNamedType( 'userAuthType', Integer().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 504))), OptionalNamedType( 'authTimeout', Integer().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 505))), OptionalNamedType( 'allowWhileOnBody', Null().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 506))), OptionalNamedType( 'trustedUserPresenceRequired', Null().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 507))), OptionalNamedType( 'trustedConfirmationRequired', Null().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 508))), OptionalNamedType( 'unlockedDeviceRequired', Null().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 509))), OptionalNamedType( 'allApplications', Null().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 600))), OptionalNamedType( 'applicationId', OctetString().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 601))), OptionalNamedType( 'creationDateTime', Integer().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 701))), OptionalNamedType( 'origin', Integer().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 702))), OptionalNamedType( 'rollbackResistant', Null().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 703))), OptionalNamedType( 'rootOfTrust', RootOfTrust().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 704))), OptionalNamedType( 'osVersion', Integer().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 705))), OptionalNamedType( 'osPatchLevel', Integer().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 706))), OptionalNamedType( 'attestationApplicationId', OctetString().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 709))), OptionalNamedType( 'attestationIdBrand', OctetString().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 710))), OptionalNamedType( 'attestationIdDevice', OctetString().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 711))), OptionalNamedType( 'attestationIdProduct', OctetString().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 712))), OptionalNamedType( 'attestationIdSerial', OctetString().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 713))), OptionalNamedType( 'attestationIdImei', OctetString().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 714))), OptionalNamedType( 'attestationIdMeid', OctetString().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 715))), OptionalNamedType( 'attestationIdManufacturer', OctetString().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 716))), OptionalNamedType( 'attestationIdModel', OctetString().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 717))), OptionalNamedType( 'vendorPatchLevel', Integer().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 718))), OptionalNamedType( 'bootPatchLevel', Integer().subtype( explicitTag=Tag(tagClassContext, tagFormatSimple, 719))), )
class RsaFingerprintContents(Sequence): componentType = NamedTypes( NamedType( 'modulus', OctetString().subtype( implicitTag=Tag(tagClassContext, tagFormatSimple, 0))), )
def pkcs7_sign_msg(self, msg): """WIP: PKCS#7 sign with certificate Sign and encapsulize message """ signed = self.sign(msg) owner_cert_pub = self.pub_cert # signedData (PKCS #7) oi_pkcs7_signed = ObjectIdentifier((1, 2, 840, 113549, 1, 7, 2)) oi_pkcs7_data = ObjectIdentifier((1, 2, 840, 113549, 1, 7, 1)) oi_sha256 = ObjectIdentifier((2, 16, 840, 1, 101, 3, 4, 2, 1)) oi_pkcs7_rsa_enc = ObjectIdentifier((1, 2, 840, 113549, 1, 1, 1)) der = Sequence().setComponentByPosition(0, oi_pkcs7_signed) data = Sequence() data = data.setComponentByPosition(0, Integer(1)) data = data.setComponentByPosition( 1, Set().setComponentByPosition( 0, Sequence().setComponentByPosition( 0, oi_sha256).setComponentByPosition(1, Null('')))) data = data.setComponentByPosition( 2, Sequence().setComponentByPosition( 0, oi_pkcs7_data).setComponentByPosition( 1, Sequence().subtype(implicitTag=tag.Tag( tag.tagClassContext, tag.tagFormatSimple, 0)).setComponentByPosition( 0, OctetString(hexValue=msg.encode('hex'))))) data = data.setComponentByPosition( 3, Sequence().subtype( implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)).setComponentByPosition( 0, owner_cert_pub)) data4001 = Sequence().setComponentByPosition(0, owner_cert_pub[0][3]) data4001 = data4001.setComponentByPosition(1, owner_cert_pub[0][1]) data4002 = Sequence().setComponentByPosition( 0, oi_sha256).setComponentByPosition(1, Null('')) data4003 = Sequence().setComponentByPosition( 0, oi_pkcs7_rsa_enc).setComponentByPosition(1, Null('')) data4004 = OctetString(hexValue=signed.encode('hex')) data = data.setComponentByPosition( 4, Set().setComponentByPosition( 0, Sequence().setComponentByPosition( 0, Integer(1)).setComponentByPosition( 1, data4001).setComponentByPosition( 2, data4002).setComponentByPosition( 3, data4003).setComponentByPosition(4, data4004))) der = der.setComponentByPosition( 1, Sequence().subtype( implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0)).setComponentByPosition(0, data)) return der_encoder.encode(der)