/// <summary>
        /// Creates a new <seealso cref="BluetoothUnlockPacket"/> object from the given payload.
        /// </summary>
        /// <param name="payload">The API frame payload. It must start with the frame type corresponding
        /// to a Bluetooth Unlock packet (<c>0x2C</c>). The byte array must be in <see cref="OperatingMode.API"/>
        /// mode.</param>
        /// <returns>Parsed Bluetooth Unlock packet.</returns>
        /// <exception cref="ArgumentException">If <c>payload[0] != APIFrameType.BLE_UNLOCK.GetValue()</c>
        /// or if <c>payload.Length <![CDATA[<]]> <see cref="MIN_API_PAYLOAD_LENGTH"/></c>.</exception>
        /// <exception cref="ArgumentNullException">If <c><paramref name="payload"/> == null</c>.</exception>
        public static BluetoothUnlockPacket CreatePacket(byte[] payload)
        {
            if (payload == null)
            {
                throw new ArgumentNullException("Bluetooth Unlock packet payload cannot be null.");
            }
            // 1 (Frame type) + 1 (Step) + 32 (Hash length)
            if (payload.Length < MIN_API_PAYLOAD_LENGTH)
            {
                throw new ArgumentException("Incomplete Bluetooth Unlock packet.");
            }
            if ((payload[0] & 0xFF) != APIFrameType.BLE_UNLOCK.GetValue())
            {
                throw new ArgumentException("Payload is not a Bluetooth Unlock packet.");
            }

            // payload[0] is the frame type.
            int index = 1;

            // SRP phase.
            SrpPhase phase = SrpPhase.UNKNOWN.Get(payload[index]);

            index = index + 1;

            // Data.
            byte[] data = null;
            if (index < payload.Length)
            {
                data = new byte[payload.Length - index];
                Array.Copy(payload, index, data, 0, data.Length);
            }

            return(new BluetoothUnlockPacket(phase, data));
        }
 /// <summary>
 /// Class constructor. Instantiates a <see cref="BluetoothUnlockPacket"/> with the given parameters.
 /// </summary>
 /// <param name="phase">The SRP phase.</param>
 /// <param name="data">The data.</param>
 /// <exception cref="ArgumentException">If <paramref name="phase"/> is <see cref="SrpPhase.UNKNOWN"/>.</exception>
 /// <exception cref="ArgumentNullException">If <paramref name="data"/> is <c>null</c>.</exception>
 /// <seealso cref="Models.SrpPhase"/>
 public BluetoothUnlockPacket(SrpPhase phase, byte[] data) : base(APIFrameType.BLE_UNLOCK)
 {
     if (phase == SrpPhase.UNKNOWN)
     {
         throw new ArgumentException("SRP phase cannot be unknown.");
     }
     SrpPhase = phase;
     Data     = data ?? throw new ArgumentNullException("Data cannot be null.");
     logger   = LogManager.GetLogger <BluetoothUnlockPacket>();
 }
Example #3
0
        /// <summary>
        /// Gets the <see cref="SrpPhase"/> associated with the specified ID <paramref name="value"/>.
        /// </summary>
        /// <param name="source"></param>
        /// <param name="value">ID value to retrieve <see cref="SrpPhase"/>.</param>
        /// <returns>The <see cref="SrpPhase"/> for the specified ID <paramref name="value"/>,
        /// <see cref="SrpPhase.UNKNOWN"/> if it does not exist.</returns>
        public static SrpPhase Get(this SrpPhase source, byte value)
        {
            var values = Enum.GetValues(typeof(SrpPhase)).OfType <SrpPhase>();

            if (values.Cast <byte>().Contains(value))
            {
                return((SrpPhase)value);
            }

            return(SrpPhase.UNKNOWN);
        }
Example #4
0
 /// <summary>
 /// Returns the <see cref="SrpPhase"/> in string format.
 /// </summary>
 /// <param name="source"></param>
 /// <returns>The <see cref="SrpPhase"/> in string format.</returns>
 public static string ToDisplayString(this SrpPhase source)
 {
     return(string.Format("({0}) {1}", HexUtils.ByteArrayToHexString(ByteUtils.IntToByteArray((byte)source)), GetName(source)));
 }
Example #5
0
 /// <summary>
 /// Gets the SRP phase name.
 /// </summary>
 /// <param name="source"></param>
 /// <returns>The SRP phase name.</returns>
 public static string GetName(this SrpPhase source)
 {
     return(lookupTable.ContainsKey(source) ? lookupTable[source] : source.ToString());
 }
Example #6
0
 /// <summary>
 /// Gets the SRP phase value.
 /// </summary>
 /// <param name="source"></param>
 /// <returns>The SRP phase value.</returns>
 public static byte GetValue(this SrpPhase source)
 {
     return((byte)source);
 }
Example #7
0
        /// <summary>
        /// Starts the bluetooth authentication with the XBee device.
        /// </summary>
        /// <exception cref="BluetoothAuthenticationException">If there is any error performing the
        /// bluetooth authentication.</exception>
        /// <exception cref="InterfaceNotOpenException">If the connection interface is not open.</exception>
        /// <exception cref="XBeeException">If there is any error in the communication process.</exception>
        public void Authenticate()
        {
            // Check connection.
            if (!device.IsOpen)
            {
                throw new InterfaceNotOpenException();
            }

            device.PacketReceived += ReceiveBLEPacket;

            try
            {
                User user = new User(API_USERNAME, password);

                // Phase 1.
                byte[] clientEphemeral = user.StartAuthentication();
                expectedPhase  = SrpPhase.PHASE_2;
                unlockResponse = null;
                device.SendPacketAsync(new BluetoothUnlockPacket(SrpPhase.PHASE_1, clientEphemeral));
                lock (unlockLock)
                {
                    Monitor.Wait(unlockLock, TIMEOUT_AUTH);
                }
                CheckResponsePacket();

                // Phase 2.
                int    index = 0;
                byte[] salt  = new byte[LENGTH_SALT];
                Array.Copy(unlockResponse.Data, index, salt, 0, salt.Length);
                index += LENGTH_SALT;
                byte[] serverEphemeral = new byte[LENGTH_EPHEMERAL];
                Array.Copy(unlockResponse.Data, index, serverEphemeral, 0, serverEphemeral.Length);

                // Phase 3.
                byte[] clientSessionProof = user.ProcessChallenge(salt, serverEphemeral);
                expectedPhase  = SrpPhase.PHASE_4;
                unlockResponse = null;
                device.SendPacketAsync(new BluetoothUnlockPacket(SrpPhase.PHASE_3, clientSessionProof));
                lock (unlockLock)
                {
                    Monitor.Wait(unlockLock, TIMEOUT_AUTH);
                }
                CheckResponsePacket();

                // Phase 4.
                index = 0;
                byte[] serverSessionProof = new byte[LENGTH_SESSION_PROOF];
                Array.Copy(unlockResponse.Data, index, serverSessionProof, 0, serverSessionProof.Length);
                index  += LENGTH_SESSION_PROOF;
                TxNonce = new byte[LENGTH_NONCE];
                Array.Copy(unlockResponse.Data, index, TxNonce, 0, TxNonce.Length);
                index  += LENGTH_NONCE;
                RxNonce = new byte[LENGTH_NONCE];
                Array.Copy(unlockResponse.Data, index, RxNonce, 0, RxNonce.Length);

                user.VerifySession(serverSessionProof);

                if (!user.authenticated)
                {
                    throw new BluetoothAuthenticationException(string.Format(ERROR_AUTH_EXTENDED, ERROR_BAD_PROOF));
                }

                // Save the sesion key.
                Key = user.SessionKey;
            }
            catch (IOException e)
            {
                throw new XBeeException(ERROR_WRITING, e);
            }
            finally
            {
                device.PacketReceived -= ReceiveBLEPacket;
            }
        }