示例#1
0
        /// <summary>
        /// Calculate values for Diffie Hellman values
        /// </summary>
        /// <param name="sigmaSequenceCheck">Service Provider Sequence (State) Check</param>
        /// <param name="m1Received">Message 1</param>
        private void CalculateDiffieHellmanExchange(SpSequenceCheck sigmaSequenceCheck, M1RequestMessage m1Received)
        {
            log.Debug("CalculateDiffieHellmanExchange(..) started.");

            if (sigmaSequenceCheck == null || m1Received == null)
            {
                HttpResponseException e = new HttpResponseException(System.Net.HttpStatusCode.InternalServerError);
                options.LogThrownException(e);
                throw e;
            }

            // (Intel Performance Primitives) IPP Wrapper
            ippApiWrapper ippWrapper = new ippApiWrapper();

            // Process message 1 and build the message 2 response.
            // Capture the GID and Base16 encode the gid field per the IAS API specificaiton:
            // "{gid} = Base 16-encoded representation of QE EPID group ID encoded as a Little Endian integer".
            // NOTE: This conversion assumes that the GID was sent without modification in the "pltfrmGid" message field.

            byte[] gidBa = m1Received.reqM1Body.pltfrmGid;

            // Required that the GID is supplied with no conversions from the SGX client and reverse the byte order
            // to convert to Big Endian integer for use later in the routine when encoding as a Base 16 string.
            Array.Reverse(gidBa);
            gidBaString = bMessage.BaToBlobStr(gidBa);

            // In crypto terms, a = Alice (Client) and b = Bob (Service provider)
            //  so ga = secret shared by client and gb = secret shared by service provide

            gaLittleEndianstr = m1Received.GetGaString();  // Received in Little Endian format

            gaXLittleEndianstr = "";
            // ga = gaX|gaY -- take the first half of ga to get gaX
            if (gaLittleEndianstr != null)
            {
                gaXLittleEndianstr = gaLittleEndianstr.Substring(0, gaLittleEndianstr.Length / 2);
            }

            gaXLittleEndian = bMessage.BlobStrToBa(gaXLittleEndianstr);
            gaXBigEndian    = bMessage.BlobStrToBa(gaXLittleEndianstr);
            Array.Reverse(gaXBigEndian, 0, gaXBigEndian.Length);
            gaXBigEndianstr = bMessage.BaToBlobStr(gaXBigEndian);

            gaYLittleEndianstr = "";
            if (gaLittleEndianstr != null)
            {
                gaYLittleEndianstr = gaLittleEndianstr.Substring(gaLittleEndianstr.Length / 2);
            }

            gaYLittleEndian = bMessage.BlobStrToBa(gaYLittleEndianstr);
            gaYBigEndian    = bMessage.BlobStrToBa(gaYLittleEndianstr);
            Array.Reverse(gaYBigEndian, 0, gaYBigEndian.Length);
            gaYBigEndianstr = bMessage.BaToBlobStr(gaYBigEndian);

            // Capture the Little Endian representation of ga for later message checking
            sigmaSequenceCheck.currentGa = bMessage.BlobStrToBa(gaXLittleEndianstr + gaYLittleEndianstr);
            {
                // Use IPP or some other alternative if the user configuration does not select MS bcrypt for Diffie-Hellman key exchange.
                // NOTE: The use of IPP allows for the use of the standard wrapper functions in the SGX SDK.
                log.Debug("Calling IPP Wrapper for Diffie-Hellman key exchange...");
                ippWrapper.InitDiffieHellman();
                ippWrapper.GetDHPublicKey(ref gbXLittleEndian, ref gbYLittleEndian);
                gbXLittleEndianstr           = bMessage.BaToBlobStr(gbXLittleEndian);
                gbYLittleEndianstr           = bMessage.BaToBlobStr(gbYLittleEndian);
                gbLittleEndianStr            = string.Concat(gbXLittleEndianstr, gbYLittleEndianstr);
                sigmaSequenceCheck.currentGb = bMessage.BlobStrToBa(gbXLittleEndianstr + gbYLittleEndianstr);
                log.DebugFormat("Server Public key: {0}", gbLittleEndianStr);
                // Derive the shared key
                byte[] sharedKey256 = new byte[Constants.SharedKeylen];
                ippWrapper.GetDHSharedSecret(gaXLittleEndian, gaYLittleEndian, ref sharedKey256);
                derivedKeyStr = bMessage.BaToBlobStr(sharedKey256);
                log.DebugFormat("Shared secret: {0}", derivedKeyStr);
            }

            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            // Use the full 256 bits of the derived DH key to further derive our smk
            //SMK is derived from the Diffie-Hellman shared secret elliptic curve field element
            // between the service provider and the
            // application enclave:
            // First compute Key Definition Key: KDK = AES-CMAC(0x00, gab x-coordinate)
            // Then SMK = AES-CMAC ( KDK, 0x01||’SMK’||0x00||0x80||0x00)

            byte[] derivedKeyBa = bMessage.BlobStrToBa(derivedKeyStr);
            // Store the KDK for further key derivation.
            sigmaSequenceCheck.currentKDK = cmacAES.Value(MsgInitValues.DS_ZERO_BA16, derivedKeyBa);
            // Store the SMK for the current session for use in processing message 3
            sigmaSequenceCheck.currentSmk = bMessage.KeyLabelToKey(Constants.SMK, sigmaSequenceCheck.currentKDK);

            /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            // Build each term by retrieving elements,
            // concatenating, converting and performing crypto operations.
            string gbgaStr = gbXLittleEndianstr + gbYLittleEndianstr + gaXLittleEndianstr + gaYLittleEndianstr;

            byte[] gbgaBa = bMessage.BlobStrToBa(gbgaStr);          // gb||ga

            // Sign the gb||ga element Service Provider -- we use sigSP to notate this Service Provider signature

            // Get the Private Key from the settings file
            byte[] privateKey;
            try
            {
                privateKey = Constants.spPrivKeyBlob;// spPrivKeyBlob;
            }
            catch (Exception e)
            {
                options.LogCaughtErrorException(e);
                log.Debug("Failed to get private key: " + e.Message);
                HttpResponseException newException = new HttpResponseException(System.Net.HttpStatusCode.InternalServerError);
                options.LogThrownException(newException);
                throw newException;
            }

            CngKey   signSgxKey = CngKey.Import(privateKey, CngKeyBlobFormat.EccPrivateBlob);
            ECDsaCng ecDsaSig   = new ECDsaCng(signSgxKey); // Elliptic Curve Digital Signature Algorithm, Signature

            ecDsaSig.HashAlgorithm = CngAlgorithm.Sha256;

            byte[] sigSPpubKey     = ecDsaSig.Key.Export(CngKeyBlobFormat.EccPublicBlob);
            string sigSPpubKeyBlob = "{ 0x" + BitConverter.ToString(sigSPpubKey).Replace("-", ", 0x") + " }";

            byte[] sigSP       = ecDsaSig.SignData(gbgaBa); // Input is LittleEndian, but output is BigEndian
            string sigSPstring = bMessage.BaToBlobStr(sigSP);

            // Separate the X and Y components of the signature -- Big Endian at this point
            string sigSPXBigEndianstr = sigSPstring.Substring(0, (sigSPstring.Length / 2));

            byte[] sigSPXBigEndian    = bMessage.BlobStrToBa(sigSPXBigEndianstr);
            string sigSPYBigEndianstr = sigSPstring.Substring(sigSPstring.Length / 2);

            byte[] sigSPYBigEndian = bMessage.BlobStrToBa(sigSPYBigEndianstr);

            // Swap the byte order of the signed data back to Little Endian and convert to combined string (X|Y)
            sigSPXLittleEndian = sigSPXBigEndian.Reverse().ToArray();
            string sigSPXLittleEndianstr = bMessage.BaToBlobStr(sigSPXLittleEndian);

            sigSPYLittleEndian = sigSPYBigEndian.Reverse().ToArray();
            string sigSPYLittleEndianstr   = bMessage.BaToBlobStr(sigSPYLittleEndian);
            string sigSPLittleEndianstring = sigSPXLittleEndianstr + sigSPYLittleEndianstr;

            // sigSPLittleEndianstring is in Little Endian format as required, ready to send to client

            // Get the signature link type
            try
            {
                if (SpStartup.iasConnectionMgr.LinkableQuotes)
                {
                    log.Debug("Using Linkable Quotes");
                    // If the SP policy setting dictates the use of linkable quotes, explicitly
                    // overwrite the default value in the sltype container.
                    // Otherwise, the default value will be an un-linkable quote type.
                    System.Buffer.BlockCopy(Constants.linkableBa, 0, Constants.sltype, 0, Constants.linkableBa.Length);
                }
            }
            catch (Exception e)
            {
                options.LogCaughtErrorException(e);
                log.Debug("Failed to get Linked Quote: " + e.Message);
                HttpResponseException newException = new HttpResponseException(System.Net.HttpStatusCode.InternalServerError);
                options.LogThrownException(newException);
                throw newException;
            }

            string sigTypeStr        = bMessage.BaToBlobStr(Constants.sltype);
            string kdfIdStr          = bMessage.BaToBlobStr(Constants.kdfId);
            string gbSpidSigSPstring = gbLittleEndianStr + bMessage.BaToBlobStr(SpStartup.iasConnectionMgr.SPID) + sigTypeStr + kdfIdStr + sigSPLittleEndianstring;

            byte[] macBlob = bMessage.BlobStrToBa(gbSpidSigSPstring);

            // Compute the CMAKsmk of (gb||SPID||Type||KDF-ID||SigSP(gb||ga))
            cMACsmk = cmacAES.Value(sigmaSequenceCheck.currentSmk, macBlob);
            string cMACsmkStr = bMessage.BaToBlobStr(cMACsmk);

            ecDsaSig.Dispose();

            log.Debug("CalculateDiffieHellmanExchange(..) returning.");
        }