コード例 #1
0
        /// <summary>
        /// This method performs the full PLAID authentication sequence, given a valid, selected PLAID SAM
        /// and a collection of keysets
        /// </summary>
        /// <param name="sam">The instance of a PLAID SAM</param>
        /// <param name="keysets">The collection of keyset identifiers to request</param>
        /// <param name="opMode">The requested opMode</param>
        /// <returns>The ACSRecord associated with the requested OpMode</returns>
        public byte[] Authenticate(IPlaidSAM sam, KeysetList keysets, short samId, short opMode)
        {
            // Initial Authenticate
#if PLAIDEXPLICITSELECT
            SelectApplication();
#endif
            byte[] estr1 = InitialAuthenticate(keysets);
#if PLAIDEXPLICITSELECT
            sam.SelectApplication(); // REMOVE
#endif
            byte[] estr2 = sam.InitialAuthenticate(samId, estr1, opMode);

            // Final Authenticate
#if PLAIDEXPLICITSELECT
            SelectApplication();
#endif
            byte[] estr3 = FinalAuthenticate(estr2);
#if PLAIDEXPLICITSELECT
            sam.SelectApplication(); // REMOVE
#endif

            return(sam.FinalAuthenticate(estr3));
        }
コード例 #2
0
        public void Personalise(IPlaidSAM sam, PlaidTemplate template, Dictionary <string, byte[]> parameters = null)
        {
            SelectApplication();

            // Validate the PLAID applet status is STATE_SELECTABLE
            var status = GetStatus();

            if (status.AppletState != PlaidAppletState.Selectable)
            {
                RaiseOnMessage(@"PLAID: Already personalised (performing factory reset)");
                // During debugging, perform a factory reset
                if (status.AppletState == PlaidAppletState.Terminated)
                {
                    throw new ApplicationException(@"Invalid applet state for factory reset");
                }

                // Authenticate using the administrative key
                var adminKeyset = template.Keysets.First(x => x.Id == PlaidApplication.KEYSET_ADMIN);
                Authenticate(sam, adminKeyset.Id, adminKeyset.SamId, 0);

                // Perform a FACTORY_RESET command
                {
                    var request = new FactoryResetRequest();

#if PLAIDEXPLICITSELECT
                    sam.SelectApplication();
#endif
                    byte[] cryptogram = sam.SetData(request.Encode());

#if PLAIDEXPLICITSELECT
                    SelectApplication();
#endif
                    SetData(cryptogram);
                }
            }

            // Retrieve and load the FA KEY cryptogram
            RaiseOnMessage(@"PLAID: Retrieving transport cryptogram");
            byte[] faKey = GetData(0x00);
#if PLAIDEXPLICITSELECT
            sam.SelectApplication();
#endif
            sam.LoadFAKey(template.TransportKey.SamId, faKey);

            // Authenticate using the TransportKey key
            // NOTE: We don't care which OpMode we request since this is an administrative authentication
            RaiseOnMessage(@"PLAID: Authenticating with transport admin keyset");
            byte[] acsRecord = Authenticate(sam, template.TransportKey.Id, template.TransportKey.SamId, 0);

            // Load all ACSRecords
            foreach (var record in template.ACSRecords)
            {
                // Create the request object
                var request = new AcsrCreateRequest();
                request.Id = record.OpModeId;

                if (record.IsTemplate())
                {
                    request.Data = parameters[record.Data];
                }
                else
                {
                    request.Data = record.DataToArray();
                }

                RaiseOnMessage($"PLAID: Writing ACSRecord {request.Id} ({request.Data.ToHexString()})");

                // Generate the cryptogram
#if PLAIDEXPLICITSELECT
                sam.SelectApplication();
#endif
                byte[] cryptogram = sam.SetData(request.Encode());

                // Transmit to the ICC
#if PLAIDEXPLICITSELECT
                SelectApplication();
#endif
                SetData(cryptogram);
            }

            // Load all Keysets in descending order so that KEYSET_ADMIN is last
            foreach (var keyset in template.Keysets.OrderByDescending(x => x.Id))
            {
                // Create the request object
                var request = new KeyCreateRequest();

                request.Id    = keyset.Id;
                request.SamId = keyset.SamId;

                foreach (var rule in keyset.AccessRules)
                {
                    request.Rules.Add(rule);
                }

                // Generate the cryptogram
#if PLAIDEXPLICITSELECT
                sam.SelectApplication();
#endif
                RaiseOnMessage($"PLAID: Loading keyset {keyset.Id:X4}");
                byte[] cryptogram = sam.SetData(request.Encode());

                // Transmit to the ICC
#if PLAIDEXPLICITSELECT
                SelectApplication();
#endif
                SetData(cryptogram);
            }

            // Re-authenticate with the Administrative key
            // NOTE: We don't care which OpMode we request since this is an administrative authentication
            RaiseOnMessage(@"PLAID: Authenticating with admin keyset");
            Authenticate(sam, template.AdminKey.Id, template.AdminKey.SamId, 0);

            // Activate the instance
            {
                RaiseOnMessage(@"PLAID: Updating applet state to PERSONALISED");
                var request = new ActivateRequest();

#if PLAIDEXPLICITSELECT
                sam.SelectApplication();
#endif
                byte[] cryptogram = sam.SetData(request.Encode());

#if PLAIDEXPLICITSELECT
                SelectApplication();
#endif
                SetData(cryptogram);
            }

            // If required, Block the instance
            if (template.Blocked)
            {
                RaiseOnMessage(@"PLAID: Updating applet state to BLOCKED");
                var request = new BlockRequest();

#if PLAIDEXPLICITSELECT
                sam.SelectApplication();
#endif
                byte[] cryptogram = sam.SetData(request.Encode());

#if PLAIDEXPLICITSELECT
                SelectApplication();
#endif
                SetData(cryptogram);
            }

            // Done!
        }