private _activateIdentityKey()

in security/tpm/src/tpm.ts [419:573]


  private _activateIdentityKey(activationBlob: Buffer, activateCallback: (err: Error) => void): void {



    //
    // Un-marshal components of the activation blob received from the provisioning service.
    //
    const buf: tss.TpmBuffer = activationBlob instanceof Buffer ? new tss.TpmBuffer(activationBlob) : activationBlob;

    const credentialBlob: tss.TPMS_ID_OBJECT = buf.createSizedObj(tss.TPMS_ID_OBJECT);
    const encodedSecret: tss.TPM2B_ENCRYPTED_SECRET = buf.createObj(tss.TPM2B_ENCRYPTED_SECRET);
    const idKeyDupBlob: tss.TPM2B_PRIVATE = buf.createObj(tss.TPM2B_PRIVATE);
    const encWrapKey: tss.TPM2B_ENCRYPTED_SECRET = buf.createObj(tss.TPM2B_ENCRYPTED_SECRET);
    this._idKeyPub = buf.createSizedObj(TPMT_PUBLIC);
    this._encUriData = buf.createObj(tss.TPM2B_DATA);
    debug('The value of the encUriData: ' + this._encUriData.toString());

    if (!buf.isOk())
      return activateCallback(new errors.SecurityDeviceError('Could not unmarshal activation data'));

    if (buf.curPos !== buf.size)
      debug('WARNING: Activation Blob sent by DPS has contains extra unidentified data');

    //
    // Start a policy session to be used with ActivateCredential()
    //
    this._tpm.GetRandom(TpmSecurityClient._tpmNonceSize, (err: tss.TpmError, nonce: Buffer) => {
      if (err) {
        const secErr = new errors.SecurityDeviceError('Could not get random nonce');
        (<any>secErr).tpmError = err;
        activateCallback(secErr);
      } else {
        this._tpm.StartAuthSession(null, null, nonce, null, tss.TPM_SE.POLICY, tss.NullSymDef, TPM_ALG_ID.SHA256, (err: tss.TpmError, resp: tss.StartAuthSessionResponse) => {
          const rc = err ? err.responseCode : TPM_RC.SUCCESS;
          debug('StartAuthSession(POLICY_SESS) returned ' + TPM_RC[rc] + '; sess handle: ' + resp.handle.handle.toString(16));
          if (rc !== TPM_RC.SUCCESS) {
            /*Codes_SRS_NODE_TPM_SECURITY_CLIENT_06_016: [If an error is encountered activating the identity key, the callback with be invoked with an `Error` of `SecurityDeviceError`.] */
            activateCallback(new errors.SecurityDeviceError('Authorization session unable to be created.  RC value: ' + TPM_RC[rc].toString()));
          } else {
            const policySession = new tss.Session(resp.handle, resp.nonceTPM);

            //
            // Apply the policy necessary to authorize an EK on Windows
            //

            // this._tpm.withSession(tss.NullPwSession).PolicySecret(tss.Endorsement, policySession.SessIn.sessionHandle, null, null, null, 0, (err: tss.TpmError, _resp: tss.PolicySecretResponse) => {
            this._tpm.PolicySecret(tss.Endorsement, policySession.SessIn.sessionHandle, null, null, null, 0, (err: tss.TpmError, _resp: tss.PolicySecretResponse) => {
              const rc = err ? err.responseCode : TPM_RC.SUCCESS;
              debug('PolicySecret() returned ' + TPM_RC[rc]);
              if (rc !== TPM_RC.SUCCESS) {
                /*Codes_SRS_NODE_TPM_SECURITY_CLIENT_06_016: [If an error is encountered activating the identity key, the callback with be invoked with an `Error` of `SecurityDeviceError`.] */
                activateCallback(new errors.SecurityDeviceError('Unable to apply the necessary policy to authorize the EK.  RC value: ' + TPM_RC[rc].toString()));
              } else {

                //
                // Use ActivateCredential() to decrypt symmetric key that is used as an inner protector
                // of the duplication blob of the new Device ID key generated by DRS.
                //

                this._tpm.withSessions(tss.NullPwSession, policySession).ActivateCredential(TpmSecurityClient._srkPersistentHandle, TpmSecurityClient._ekPersistentHandle, credentialBlob, encodedSecret.secret, (err: tss.TpmError, innerWrapKey: Buffer) => {
                  const rc = err ? err.responseCode : TPM_RC.SUCCESS;
                  debug('ActivateCredential() returned ' + TPM_RC[rc] + '; innerWrapKey size ' + innerWrapKey.length);
                  if (rc !== TPM_RC.SUCCESS) {
                    /*Codes_SRS_NODE_TPM_SECURITY_CLIENT_06_016: [If an error is encountered activating the identity key, the callback with be invoked with an `Error` of `SecurityDeviceError`.] */
                    activateCallback(new errors.SecurityDeviceError('Unable to decrypt the symmetric key used to protect duplication blob.  RC value: ' + TPM_RC[rc].toString()));
                  } else if (innerWrapKey.length === 0) {
                    activateCallback(new errors.SecurityDeviceError('Unable to unwrap inner key - must have administrator privilege'));
                  } else {
                    //
                    // Initialize parameters of the symmetric key used by DRS
                    // Note that the client uses the key size chosen by DRS, but other parameters are fixed (an AES key in CFB mode).
                    //
                    const symDef = new tss.TPMT_SYM_DEF_OBJECT(TPM_ALG_ID.AES, innerWrapKey.length * 8, TPM_ALG_ID.CFB); //DevSkim: ignore DS187371

                    //
                    // Import the new Device ID key issued by DRS to the device's TPM
                    //

                    this._tpm.withSession(tss.NullPwSession).Import(TpmSecurityClient._srkPersistentHandle, innerWrapKey, this._idKeyPub, idKeyDupBlob, encWrapKey.secret, symDef, (err: tss.TpmError, idKeyPrivate: TPM2B_PRIVATE) => {
                      const rc = err ? err.responseCode : TPM_RC.SUCCESS;
                      debug('Import() returned ' + TPM_RC[rc] + '; idKeyPrivate size ' + idKeyPrivate.buffer.length);
                      if (rc !== TPM_RC.SUCCESS) {
                          /*Codes_SRS_NODE_TPM_SECURITY_CLIENT_06_016: [If an error is encountered activating the identity key, the callback with be invoked with an `Error` of `SecurityDeviceError`.] */
                          activateCallback(new errors.SecurityDeviceError('Unable to import the device id key into the TPM.  RC value: ' + TPM_RC[rc].toString()));
                      } else {

                        //
                        // Load the imported key into the TPM
                        //

                        this._tpm.withSession(tss.NullPwSession).Load(TpmSecurityClient._srkPersistentHandle, idKeyPrivate, this._idKeyPub, (err: tss.TpmError, hIdKey: TPM_HANDLE) => {
                          const rc = err ? err.responseCode : TPM_RC.SUCCESS;
                          debug('Load() returned ' + TPM_RC[rc] + '; ID key handle: 0x' + hIdKey.handle.toString(16));
                          if (rc !== TPM_RC.SUCCESS) {
                            /*Codes_SRS_NODE_TPM_SECURITY_CLIENT_06_016: [If an error is encountered activating the identity key, the callback with be invoked with an `Error` of `SecurityDeviceError`.] */
                            activateCallback(new errors.SecurityDeviceError('Unable to load the device id key into the TPM.  RC value: ' + TPM_RC[rc].toString()));
                          } else {

                            //
                            // Remove possibly existing persistent instance of the previous Device ID key
                            //

                            this._tpm.allowErrors().withSession(tss.NullPwSession).EvictControl(tss.Owner, TpmSecurityClient._idKeyPersistentHandle, TpmSecurityClient._idKeyPersistentHandle, () => {

                              //
                              // Persist the new Device ID key
                              //

                              this._tpm.withSession(tss.NullPwSession).EvictControl(tss.Owner, hIdKey, TpmSecurityClient._idKeyPersistentHandle, (err: tss.TpmError) => {
                                const rc = err ? err.responseCode : TPM_RC.SUCCESS;
                                if (rc !== TPM_RC.SUCCESS) {
                                  /*Codes_SRS_NODE_TPM_SECURITY_CLIENT_06_016: [If an error is encountered activating the identity key, the callback with be invoked with an `Error` of `SecurityDeviceError`.] */
                                  activateCallback(new errors.SecurityDeviceError('Unable to persist the device id key into the TPM.  RC value: ' + TPM_RC[rc].toString()));
                                } else {

                                  //
                                  // Free the ID Key transient handle and the session object.  Doesn't matter if it "fails".  Go on at this point./
                                  //

                                  this._tpm.FlushContext(hIdKey, (err: tss.TpmError) => {
                                    const rc = err ? err.responseCode : TPM_RC.SUCCESS;
                                    debug('FlushContext(TRANS_ID_KEY) returned ' + TPM_RC[rc]);
                                    if (err) {
                                      const secErr = new errors.SecurityDeviceError('Could not get TPM capabilities');
                                      (<any>secErr).tpmError = err;
                                      activateCallback(secErr);
                                    } else {
                                      this._tpm.FlushContext(policySession.SessIn.sessionHandle, (err: tss.TpmError) => {
                                        debug('FlushContext(POLICY_SESS) returned ' + TPM_RC[rc]);
                                        if (err) {
                                          const secErr = new errors.SecurityDeviceError('Could not get TPM capabilities');
                                          (<any>secErr).tpmError = err;
                                          activateCallback(secErr);
                                        } else {
                                          activateCallback(null);
                                        }
                                      });
                                    }
                                  });
                                }
                              });
                            });
                          }
                        });
                      }
                    });
                  }
                });
              }
            });
          }
        });
      }
    });
  }