コード例 #1
0
        public TpmHandle GenerateRSASigningKeyPair(AuthValue ownerAuth, out TpmPublic keyPublic, byte[] keyAuth, TpmHandle persistantHandle)
        {
            var keyTemplate = new TpmPublic(TpmAlgId.Sha1,                                      // Name algorithm
                                            ObjectAttr.UserWithAuth | ObjectAttr.Sign |         // Signing key
                                            ObjectAttr.FixedParent | ObjectAttr.FixedTPM |      // Non-migratable
                                            ObjectAttr.SensitiveDataOrigin,
                                            new byte[0],                                        // no policy
                                            new RsaParms(new SymDefObject(),                    // not a restricted decryption key
                                                         new SchemeRsassa(TpmAlgId.Sha1),       // an unrestricted signing key
                                                         2048,
                                                         0),
                                            new Tpm2bPublicKeyRsa());

            var sensCreate = new SensitiveCreate(keyAuth, new byte[0]);

            //TpmPublic keyPublic;

            byte[] outsideInfo      = Globs.GetRandomBytes(8);
            var    creationPcrArray = new PcrSelection[0];

            TpmHandle h = tpm[ownerAuth].CreatePrimary(
                TpmHandle.RhOwner,                          // In the owner-hierarchy
                sensCreate,                                 // With this auth-value
                keyTemplate,                                // Describes key
                outsideInfo,                                // For creation ticket
                creationPcrArray,                           // For creation ticket
                out keyPublic,                              // Out pubKey and attributes
                out CreationData creationData,              // Not used here
                out byte[] creationHash,                    // Not used here
                out TkCreation creationTicket);

            tpm.EvictControl(TpmHandle.RhOwner, h, persistantHandle);

            return(h);
        }
コード例 #2
0
ファイル: Limpet.cs プロジェクト: blinds52/security-1
        public void Provision(string encodedHmacKey, string hostName, string deviceId = "")
        {
            TpmHandle    nvHandle      = new TpmHandle(AIOTH_PERSISTED_URI_INDEX + logicalDeviceId);
            TpmHandle    ownerHandle   = new TpmHandle(TpmRh.Owner);
            TpmHandle    hmacKeyHandle = new TpmHandle(AIOTH_PERSISTED_KEY_HANDLE + logicalDeviceId);
            TpmHandle    srkHandle     = new TpmHandle(SRK_HANDLE);
            UTF8Encoding utf8          = new UTF8Encoding();

            byte[] nvData  = utf8.GetBytes(hostName + "/" + deviceId);
            byte[] hmacKey = System.Convert.FromBase64String(encodedHmacKey);

            // Open the TPM
            Tpm2Device tpmDevice = new TbsDevice();

            tpmDevice.Connect();
            var tpm = new Tpm2(tpmDevice);

            // Define the store
            tpm.NvDefineSpace(ownerHandle,
                              new byte[0],
                              new NvPublic(nvHandle,
                                           TpmAlgId.Sha256,
                                           NvAttr.Authwrite | NvAttr.Authread | NvAttr.NoDa,
                                           new byte[0],
                                           (ushort)nvData.Length));

            // Write the store
            tpm.NvWrite(nvHandle, nvHandle, nvData, 0);

            // Import the HMAC key under the SRK
            TpmPublic    hmacPub;
            CreationData creationData;

            byte[]     creationhash;
            TkCreation ticket;
            TpmPrivate hmacPrv = tpm.Create(srkHandle,
                                            new SensitiveCreate(new byte[0],
                                                                hmacKey),
                                            new TpmPublic(TpmAlgId.Sha256,
                                                          ObjectAttr.UserWithAuth | ObjectAttr.NoDA | ObjectAttr.Sign,
                                                          new byte[0],
                                                          new KeyedhashParms(new SchemeHmac(TpmAlgId.Sha256)),
                                                          new Tpm2bDigestKeyedhash()),
                                            new byte[0],
                                            new PcrSelection[0],
                                            out hmacPub,
                                            out creationData,
                                            out creationhash,
                                            out ticket);

            // Load the HMAC key into the TPM
            TpmHandle loadedHmacKey = tpm.Load(srkHandle, hmacPrv, hmacPub);

            // Persist the key in NV
            tpm.EvictControl(ownerHandle, loadedHmacKey, hmacKeyHandle);

            // Unload the transient copy from the TPM
            tpm.FlushContext(loadedHmacKey);
        }
コード例 #3
0
ファイル: TpmHelper.cs プロジェクト: catan85/SshOnDemand
        /// <summary>
        /// Funzione per la pulizia di una chiave e funzione HMAC precedentementi salvati nel TPM
        /// </summary>
        public static void CleanOldHmacKey()
        {
            // Apertura del TPM
            Tpm2Device tpmDevice = new TbsDevice();

            tpmDevice.Connect();
            var tpm = new Tpm2(tpmDevice);

            TpmHandle ownerHandle   = new TpmHandle(TpmRh.Owner);
            TpmHandle nvHandle      = new TpmHandle(AIOTH_PERSISTED_URI_INDEX + logicalDeviceId);
            TpmHandle hmacKeyHandle = new TpmHandle(AIOTH_PERSISTED_KEY_HANDLE + logicalDeviceId);

            // Undefine dello spazio utilizzato per la chiave HMAC
            tpm.NvUndefineSpace(ownerHandle, nvHandle);

            // Rimozione della funzione HMAC
            tpm.EvictControl(ownerHandle, hmacKeyHandle, hmacKeyHandle);
        }
コード例 #4
0
ファイル: Limpet.cs プロジェクト: blinds52/security-1
        public void Destroy()
        {
            TpmHandle nvHandle      = new TpmHandle(AIOTH_PERSISTED_URI_INDEX + logicalDeviceId);
            TpmHandle ownerHandle   = new TpmHandle(TpmRh.Owner);
            TpmHandle hmacKeyHandle = new TpmHandle(AIOTH_PERSISTED_KEY_HANDLE + logicalDeviceId);

            // Open the TPM
            Tpm2Device tpmDevice = new TbsDevice();

            tpmDevice.Connect();
            var tpm = new Tpm2(tpmDevice);

            // Destyroy the URI
            tpm.NvUndefineSpace(ownerHandle, nvHandle);

            // Destroy the HMAC key
            tpm.EvictControl(ownerHandle, hmacKeyHandle, hmacKeyHandle);

            // Dispose of the TPM
            tpm.Dispose();
        }
コード例 #5
0
    /// <summary>
    /// Provision the key in the TPM
    /// </summary>
    /// <param name="key">the access key</param>
    public void Provision(byte[] key)
    {
        TpmHandle ownerHandle   = new TpmHandle(TpmRh.Owner);
        TpmHandle hmacKeyHandle = new TpmHandle(PERSISTED_KEY_HANDLE + logicalDeviceId);
        TpmHandle srkHandle     = new TpmHandle(TPM_20_SRK_HANDLE);

        // Open the TPM
        Tpm2Device tpmDevice = new TbsDevice();

        tpmDevice.Connect();
        using (var tpm = new Tpm2(tpmDevice))
        {
#pragma warning disable IDE0059 // Value assigned to symbol is never used
            // Import the HMAC key under the SRK
            TpmPrivate hmacPrv = tpm.Create(srkHandle,
                                            new SensitiveCreate(Array.Empty <byte>(),
                                                                key),
                                            new TpmPublic(TpmAlgId.Sha256,
                                                          ObjectAttr.UserWithAuth | ObjectAttr.NoDA | ObjectAttr.Sign,
                                                          Array.Empty <byte>(),
                                                          new KeyedhashParms(new SchemeHmac(TpmAlgId.Sha256)),
                                                          new Tpm2bDigestKeyedhash()),
                                            Array.Empty <byte>(),
                                            Array.Empty <PcrSelection>(),
                                            out TpmPublic hmacPub,
                                            out CreationData creationData,
                                            out byte[] creationhash,
                                            out TkCreation ticket);
#pragma warning restore IDE0059 // Value assigned to symbol is never used

            // Load the HMAC key into the TPM
            TpmHandle loadedHmacKey = tpm.Load(srkHandle, hmacPrv, hmacPub);

            // Persist the key in NV
            tpm.EvictControl(ownerHandle, loadedHmacKey, hmacKeyHandle);

            // Unload the transient copy from the TPM
            tpm.FlushContext(loadedHmacKey);
        }
    }
コード例 #6
0
        /// <summary>
        /// Activates an identity key within the TPM device.
        /// </summary>
        /// <param name="encryptedKey">The encrypted identity key.</param>
        public override void ActivateIdentityKey(byte[] encryptedKey)
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(this, $"{encryptedKey}", nameof(ActivateIdentityKey));
            }
            Destroy();

            // Take the pieces out of the container
            var           m      = new Marshaller(encryptedKey, DataRepresentation.Tpm);
            Tpm2bIdObject cred2b = m.Get <Tpm2bIdObject>();

            byte[] encryptedSecret = new byte[m.Get <ushort>()];
            encryptedSecret = m.GetArray <byte>(encryptedSecret.Length, "encryptedSecret");
            TpmPrivate dupBlob = m.Get <TpmPrivate>();

            byte[] encWrapKey = new byte[m.Get <ushort>()];
            encWrapKey = m.GetArray <byte>(encWrapKey.Length, "encWrapKey");
            UInt16 pubSize = m.Get <UInt16>();

            _idKeyPub = m.Get <TpmPublic>();
            byte[] cipherText = new byte[m.Get <ushort>()];
            cipherText = m.GetArray <byte>(cipherText.Length, "uriInfo");

            // Setup the authorization session for the EK
            var policyNode = new TpmPolicySecret(TpmHandle.RhEndorsement, false, 0, Array.Empty <byte>(), Array.Empty <byte>());
            var policy     = new PolicyTree(_ekPub.nameAlg);

            policy.SetPolicyRoot(policyNode);
            AuthSession ekSession = _tpm2.StartAuthSessionEx(TpmSe.Policy, _ekPub.nameAlg);

            ekSession.RunPolicy(_tpm2, policy);

            // Perform the activation
            ekSession.Attrs  &= ~SessionAttr.ContinueSession;
            _activationSecret = _tpm2[Array.Empty <byte>(), ekSession].ActivateCredential(
                new TpmHandle(TPM_20_SRK_HANDLE),
                new TpmHandle(TPM_20_EK_HANDLE),
                cred2b.credential,
                encryptedSecret);

            TpmPrivate importedKeyBlob = _tpm2.Import(
                new TpmHandle(TPM_20_SRK_HANDLE),
                _activationSecret,
                _idKeyPub,
                dupBlob,
                encWrapKey,
                new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb));

            _idKeyHandle = _tpm2.Load(new TpmHandle(TPM_20_SRK_HANDLE), importedKeyBlob, _idKeyPub);

            // Persist the key in NV
            TpmHandle hmacKeyHandle = new TpmHandle(AIOTH_PERSISTED_KEY_HANDLE);

            _tpm2.EvictControl(new TpmHandle(TpmRh.Owner), _idKeyHandle, hmacKeyHandle);

            // Unload the transient copy from the TPM
            _tpm2.FlushContext(_idKeyHandle);
            _idKeyHandle = hmacKeyHandle;

            if (Logging.IsEnabled)
            {
                Logging.Exit(this, $"{encryptedKey}", nameof(ActivateIdentityKey));
            }
        }
コード例 #7
0
ファイル: Program.cs プロジェクト: rgl/TSS.MSR
        } // QuotePcrs()

        /// <summary>
        /// This sample demonstrates the creation and use of a storage root key that
        /// behaves like the Storage Root Key (SRK) defined in TPM1.2.
        /// To do this we need to create a new primary, and then use EvictControl
        /// to make it NV-resident.
        /// </summary>
        /// <param name="tpm">Reference to TPM object</param>
        static void StorageRootKey(Tpm2 tpm)
        {
            Console.WriteLine("\nStorageRootKey sample started.");

            //
            // This template asks the TPM to create an 2048 bit RSA storage key
            // with an associated AES key for symmetric protection of its child keys.
            // NOTE - The term SRK is not used in TPM 2.0 spec, but is widely used
            // in other documents.
            //
            var srkTemplate = new TpmPublic(TpmAlgId.Sha256,                               // Name algorithm
                                            ObjectAttr.Restricted |                        // Storage keys must be restricted
                                            ObjectAttr.Decrypt |                           // Storage keys are Decrypt keys
                                            ObjectAttr.FixedParent | ObjectAttr.FixedTPM | // Non-duplicable (like 1.2)
                                            ObjectAttr.UserWithAuth | ObjectAttr.SensitiveDataOrigin,
                                            null,                                          // No policy
                                            new RsaParms(new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb),
                                                         new NullAsymScheme(),             // No signing or decryption scheme
                                                         2048, 0),                         // 2048-bit RSA
                                            new Tpm2bPublicKeyRsa());

            AuthValue childAuthVal = AuthValue.FromRandom(8);
            TssObject swKey        = TssObject.Create(srkTemplate, childAuthVal);

            TpmPublic    srkPublic;
            CreationData srkCreationData;
            TkCreation   srkCreationTicket;

            byte[] srkCreationHash;

            //
            // Ask the TPM to create a new primary RSA/AES primary storage key
            //
            TpmHandle keyHandle = tpm.CreatePrimary(TpmRh.Owner,                     // In the owner-hierarchy
                                                    new SensitiveCreate(null, null), // Empty auth-value
                                                    srkTemplate,                     // Key template (params)
                                                    null,                            // For creation ticket
                                                    new PcrSelection[0],             // For creation ticket
                                                    out srkPublic,                   // Out pubKey and attrs
                                                    out srkCreationData,             // Not used here
                                                    out srkCreationHash,             // Ibid
                                                    out srkCreationTicket);          // Ibid

            //
            // print out text-versions of the public key just created
            //
            Console.WriteLine("New SRK public key\n" + srkPublic.ToString());

            //
            // The caller provides the handle for persistent keys
            //
            TpmHandle srkHandle = TpmHandle.Persistent(0x5000);

            //
            // Ae will make the "SRK" persistent in an NV-slot, so clean up anything
            // that is already there
            //
            tpm._AllowErrors()
            .EvictControl(TpmRh.Owner, srkHandle, srkHandle);
            if (tpm._LastCommandSucceeded())
            {
                Console.WriteLine("Removed previous persistent SRK.");
            }

            //
            // Make the SRK NV-resident
            //
            tpm.EvictControl(TpmRh.Owner, keyHandle, srkHandle);
            Console.WriteLine("SRK is persistent now.");
            Console.WriteLine("\nStorageRootKey sample finished.");
        } // StorageRootKey()
コード例 #8
0
ファイル: TpmHelper.cs プロジェクト: catan85/SshOnDemand
        /// <summary>
        /// Funzione per il salvataggio della chiave privata da utilizzare per firmare con HMAC tramite TPM
        /// </summary>
        /// <param name="encodedHmacKey"></param>
        public static void SaveHmacKey(string encodedHmacKey)
        {
            // Definizione area di memoria non volatile nel TPM
            TpmHandle nvHandle = new TpmHandle(AIOTH_PERSISTED_URI_INDEX + logicalDeviceId);

            // Definizione dell'handle contenente l'Owner nel TPM
            TpmHandle ownerHandle = new TpmHandle(TpmRh.Owner);

            // Definizione dell'handle per la memorizzazione dell'oggetto HMAC
            TpmHandle hmacKeyHandle = new TpmHandle(AIOTH_PERSISTED_KEY_HANDLE + logicalDeviceId);

            // Definizione dell'handle della Storage Root Key, si tratta della chiave
            // principale utilizzata per il salvataggio di altre chiavi. Ogni chiave salvata
            // nel TPM infatti viene cifrata utilizzando la sua chiave "padre".
            // La SRK è la chiave più alta dell'albero
            TpmHandle    srkHandle = new TpmHandle(SRK_HANDLE);
            UTF8Encoding utf8      = new UTF8Encoding();

            // dati descrittivi dell'host e del device id
            byte[] nvData = utf8.GetBytes(hostName + "/" + deviceId);

            // chiave privata che intendiamo memorizzare nel TPM
            byte[] hmacKey = System.Convert.FromBase64String(encodedHmacKey);

            // Apertura del TPM
            Tpm2Device tpmDevice = new TbsDevice();

            tpmDevice.Connect();
            var tpm = new Tpm2(tpmDevice);

            // Definizione dello store Non volatile
            // Il primo parametro è l'Owner TPM
            // il terzo parametro è la funzione HMAC che intendiamo salvare
            // (NvPublic sta per Non volatile public area)
            tpm.NvDefineSpace(ownerHandle,
                              new byte[0],
                              new NvPublic(
                                  nvHandle,
                                  TpmAlgId.Sha256,
                                  NvAttr.Authwrite | NvAttr.Authread | NvAttr.NoDa,
                                  new byte[0],
                                  (ushort)nvData.Length));

            // Scrittura nello store non volatile della funzione HMAC
            tpm.NvWrite(nvHandle, nvHandle, nvData, 0);

            // Importazione della chiave HMAC sotto la Storage Root Key
            TpmPublic    hmacPub;
            CreationData creationData;

            byte[]     creationhash;
            TkCreation ticket;

            // Passaggio della chiave privata
            var sensitiveCreate = new SensitiveCreate(new byte[0], hmacKey);

            // Definizione dell'uso che si farà della chiave
            var tpmPublic = new TpmPublic(
                TpmAlgId.Sha256,
                ObjectAttr.UserWithAuth | ObjectAttr.NoDA | ObjectAttr.Sign,
                new byte[0],
                new KeyedhashParms(new SchemeHmac(TpmAlgId.Sha256)),
                new Tpm2bDigestKeyedhash());

            // Salvataggio della chiave privata nel tpm
            TpmPrivate hmacPrv = tpm.Create(
                srkHandle,
                sensitiveCreate,
                tpmPublic,
                new byte[0],
                new PcrSelection[0],
                out hmacPub,
                out creationData,
                out creationhash,
                out ticket);

            // Caricamento della chiave HMAC nel TPM
            TpmHandle loadedHmacKey = tpm.Load(srkHandle, hmacPrv, hmacPub);

            // Salvataggio della chiave nella memoria Non Volatile
            tpm.EvictControl(ownerHandle, loadedHmacKey, hmacKeyHandle);

            // Flush degli oggetti transienti dal tpm
            tpm.FlushContext(loadedHmacKey);
        }
コード例 #9
0
    /// <summary>
    /// Get the endorsement key from the TPM. If the key has not yet been set, a new one is generated
    /// </summary>
    /// <returns></returns>
    /// <remarks>
    /// Picked from https://github.com/Azure/azure-iot-sdk-csharp/blob/e1dd08eacd1caf58f3b318d8ad5ad94dde961d78/security/tpm/src/SecurityProviderTpmHsm.cs#L258-L324
    /// </remarks>
    public static byte[] GetEndorsementKey()
    {
        TpmHandle ekHandle = new TpmHandle(TPM_20_EK_HANDLE);

        byte[] result = Array.Empty <byte>();

        try
        {
            // Open the TPM
            Tpm2Device tpmDevice = new TbsDevice();
            tpmDevice.Connect();
            using (var tpm = new Tpm2(tpmDevice))
            {
                // Read EK from the TPM, temporarily allowing errors
                TpmPublic ekPub = tpm.
                                  _AllowErrors()
                                  .ReadPublic(ekHandle, out byte[] name, out byte[] qualifiedName);

                // if the last command did not succeed, we do not have an endorsement key yet, so create it
                if (!tpm._LastCommandSucceeded())
                {
                    // Get the real EK ready.
                    TpmPublic ekTemplate = new TpmPublic(
                        TpmAlgId.Sha256,
                        ObjectAttr.FixedTPM | ObjectAttr.FixedParent | ObjectAttr.SensitiveDataOrigin |
                        ObjectAttr.AdminWithPolicy | ObjectAttr.Restricted | ObjectAttr.Decrypt,
                        new byte[] {
                        0x83, 0x71, 0x97, 0x67, 0x44, 0x84, 0xb3, 0xf8, 0x1a, 0x90, 0xcc, 0x8d, 0x46, 0xa5, 0xd7, 0x24,
                        0xfd, 0x52, 0xd7, 0x6e, 0x06, 0x52, 0x0b, 0x64, 0xf2, 0xa1, 0xda, 0x1b, 0x33, 0x14, 0x69, 0xaa
                    },
                        new RsaParms(
                            new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb),
                            new NullAsymScheme(),
                            2048,
                            0),
                        new Tpm2bPublicKeyRsa(new byte[2048 / 8]));

                    TpmHandle keyHandle = tpm.CreatePrimary(
                        new TpmHandle(TpmHandle.RhEndorsement),
                        new SensitiveCreate(),
                        ekTemplate,
                        Array.Empty <byte>(),
                        Array.Empty <PcrSelection>(),
                        out ekPub,
                        out CreationData creationData,
                        out byte[] creationHash,
                        out TkCreation creationTicket);

                    tpm.EvictControl(TpmHandle.RhOwner, keyHandle, ekHandle);
                    tpm.FlushContext(keyHandle);
                }

                // Get the EK representation
                result = ekPub.GetTpm2BRepresentation();
            }
        }
        catch { }


        return(result);
    }
コード例 #10
0
        /// <summary>
        /// Activates a symmetric identity within the Hardware Security Module.
        /// </summary>
        /// <param name="activation">The authentication challenge key supplied by the service.</param>
        public override void ActivateSymmetricIdentity(byte[] activation)
        {
            Destroy();

            // Take the pieces out of the container
            var m = new Marshaller(activation, DataRepresentation.Tpm);

            byte[] credentialBlob = new byte[m.Get <ushort>()];
            credentialBlob = m.GetArray <byte>(credentialBlob.Length, "credentialBlob");
            byte[] encryptedSecret = new byte[m.Get <ushort>()];
            encryptedSecret = m.GetArray <byte>(encryptedSecret.Length, "encryptedSecret");
            TpmPrivate dupBlob = m.Get <TpmPrivate>();

            byte[] encWrapKey = new byte[m.Get <ushort>()];
            encWrapKey = m.GetArray <byte>(encryptedSecret.Length, "encWrapKey");
            UInt16 pubSize = m.Get <UInt16>();

            _idKeyPub = m.Get <TpmPublic>();
            byte[] cipherText = new byte[m.Get <ushort>()];
            cipherText = m.GetArray <byte>(cipherText.Length, "uriInfo");

            // Setup the authorization session for the EK
            var policyNode = new TpmPolicySecret(
                TpmHandle.RhEndorsement, _ekAuth ?? Array.Empty <byte>(),
                new AuthValue(),
                false,
                0,
                Array.Empty <byte>(),
                Array.Empty <byte>());

            var policy = new PolicyTree(_ekPub.nameAlg);

            policy.SetPolicyRoot(policyNode);
            AuthSession ekSession = _tpm2.StartAuthSessionEx(TpmSe.Policy, _ekPub.nameAlg);

            ekSession.RunPolicy(_tpm2, policy);

            // Perform the activation
            ekSession.Attrs  &= ~SessionAttr.ContinueSession;
            _activationSecret = _tpm2[Array.Empty <byte>(), ekSession].ActivateCredential(
                new TpmHandle(TPM_20_SRK_HANDLE),
                new TpmHandle(TPM_20_EK_HANDLE),
                credentialBlob,
                encryptedSecret);

            TpmPrivate importedKeyBlob = _tpm2.Import(
                new TpmHandle(TPM_20_SRK_HANDLE),
                _activationSecret,
                _idKeyPub,
                dupBlob,
                encWrapKey,
                new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb));

            _idKeyHandle = _tpm2.Load(new TpmHandle(TPM_20_SRK_HANDLE), importedKeyBlob, _idKeyPub);

            // Persist the key in NV
            TpmHandle hmacKeyHandle = new TpmHandle(AIOTH_PERSISTED_KEY_HANDLE);

            _tpm2.EvictControl(new TpmHandle(TpmRh.Owner), _idKeyHandle, hmacKeyHandle);

            // Unload the transient copy from the TPM
            _tpm2.FlushContext(_idKeyHandle);
            _idKeyHandle = hmacKeyHandle;

            // Unwrap the URI
            byte[] clearText = SymmCipher.Decrypt(
                new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb),
                _activationSecret,
                new byte[16],
                cipherText);

            UnicodeEncoding unicode = new UnicodeEncoding();
            string          uriData = unicode.GetString(clearText);
            int             idx     = uriData.IndexOf('/');

            if (idx > 0)
            {
                string hostName = uriData.Substring(0, idx);
                string deviceId = uriData.Substring(idx + 1);

                // Persist the URI
                ProvisionUri(hostName, deviceId);
            }
        }