private void ValidateAttestationClaims(EnclaveType enclaveType, string attestationToken, EnclavePublicKey enclavePublicKey, byte[] nonce) { // Read the json token JsonWebToken token = null; try { JsonWebTokenHandler tokenHandler = new JsonWebTokenHandler(); token = tokenHandler.ReadJsonWebToken(attestationToken); } catch (ArgumentException argumentException) { throw new AlwaysEncryptedAttestationException(String.Format(Strings.FailToParseAttestationToken, argumentException.Message)); } // Get all the claims from the token Dictionary <string, string> claims = new Dictionary <string, string>(); foreach (Claim claim in token.Claims.ToList()) { claims.Add(claim.Type, claim.Value); } // Get Enclave held data claim and validate it with the Base64UrlEncode(enclave public key) ValidateClaim(claims, "aas-ehd", enclavePublicKey.PublicKey); if (enclaveType == EnclaveType.Vbs) { // Get rp_data claim and validate it with the Base64UrlEncode(nonce) ValidateClaim(claims, "rp_data", nonce); } }
private void VerifyAzureAttestationInfo(string attestationUrl, EnclaveType enclaveType, string attestationToken, EnclavePublicKey enclavePublicKey, byte[] nonce) { bool shouldForceUpdateSigningKeys = false; string attestationInstanceUrl = GetAttestationInstanceUrl(attestationUrl); bool shouldRetryValidation; bool isSignatureValid; string exceptionMessage = string.Empty; do { shouldRetryValidation = false; // Get the OpenId config object for the signing keys OpenIdConnectConfiguration openIdConfig = GetOpenIdConfigForSigningKeys(attestationInstanceUrl, shouldForceUpdateSigningKeys); // Verify the token signature against the signing keys downloaded from meta data end point bool isKeySigningExpired; isSignatureValid = VerifyTokenSignature(attestationToken, attestationInstanceUrl, openIdConfig.SigningKeys, out isKeySigningExpired, out exceptionMessage); // In cases if we fail to validate the token, since we are using the old signing keys // let's re-download the signing keys again and re-validate the token signature if (!isSignatureValid && isKeySigningExpired && !shouldForceUpdateSigningKeys) { shouldForceUpdateSigningKeys = true; shouldRetryValidation = true; } }while (shouldRetryValidation); if (!isSignatureValid) { throw new AlwaysEncryptedAttestationException(String.Format(Strings.AttestationTokenSignatureValidationFailed, exceptionMessage)); } // Validate claims in the token ValidateAttestationClaims(enclaveType, attestationToken, enclavePublicKey, nonce); }
private byte[] GetSharedSecret(EnclavePublicKey enclavePublicKey, byte[] nonce, EnclaveType enclaveType, EnclaveDiffieHellmanInfo enclaveDHInfo, ECDiffieHellmanCng clientDHKey) { byte[] enclaveRsaPublicKey = enclavePublicKey.PublicKey; // For SGX enclave we Sql server sends the enclave public key XOR'ed with Nonce. // In case if Sql server replayed old JWT then shared secret will not match and hence client will not able to determine the updated enclave keys. if (enclaveType == EnclaveType.Sgx) { for (int iterator = 0; iterator < enclaveRsaPublicKey.Length; iterator++) { enclaveRsaPublicKey[iterator] = (byte)(enclaveRsaPublicKey[iterator] ^ nonce[iterator % nonce.Length]); } } // Perform signature verification. The enclave's DiffieHellman public key was signed by the enclave's RSA public key. CngKey cngkey = CngKey.Import(enclaveRsaPublicKey, CngKeyBlobFormat.GenericPublicBlob); using (RSACng rsacng = new RSACng(cngkey)) { if (!rsacng.VerifyData(enclaveDHInfo.PublicKey, enclaveDHInfo.PublicKeySignature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)) { throw new ArgumentException(Strings.GetSharedSecretFailed); } } CngKey key = CngKey.Import(enclaveDHInfo.PublicKey, CngKeyBlobFormat.GenericPublicBlob); return(clientDHKey.DeriveKeyMaterial(key)); }
public static extern bool IsEnclaveTypeSupported(EnclaveType flEnclaveType);
public static extern void CreateEnclave(HPROCESS hProcess, IntPtr lpAddress, SizeT dwSize, SizeT dwInitialCommittment, EnclaveType flEnclaveType, IntPtr lpEnclaveInformation, uint dwInfoLength, out uint lpEnclaveError);
private byte[] GetSharedSecret(EnclavePublicKey enclavePublicKey, byte[] nonce, EnclaveType enclaveType, EnclaveDiffieHellmanInfo enclaveDHInfo, ECDiffieHellman clientDHKey) { byte[] enclaveRsaPublicKey = enclavePublicKey.PublicKey; // For SGX enclave we Sql server sends the enclave public key XOR'ed with Nonce. // In case if Sql server replayed old JWT then shared secret will not match and hence client will not able to determine the updated enclave keys. if (enclaveType == EnclaveType.Sgx) { for (int iterator = 0; iterator < enclaveRsaPublicKey.Length; iterator++) { enclaveRsaPublicKey[iterator] = (byte)(enclaveRsaPublicKey[iterator] ^ nonce[iterator % nonce.Length]); } } // Perform signature verification. The enclave's DiffieHellman public key was signed by the enclave's RSA public key. RSAParameters rsaParams = KeyConverter.RSAPublicKeyBlobToParams(enclaveRsaPublicKey); using (RSA rsa = RSA.Create(rsaParams)) { if (!rsa.VerifyData(enclaveDHInfo.PublicKey, enclaveDHInfo.PublicKeySignature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)) { throw new ArgumentException(Strings.GetSharedSecretFailed); } } ECParameters ecParams = KeyConverter.ECCPublicKeyBlobToParams(enclaveDHInfo.PublicKey); ECDiffieHellman enclaveDHKey = ECDiffieHellman.Create(ecParams); return(clientDHKey.DeriveKeyFromHash(enclaveDHKey.PublicKey, HashAlgorithmName.SHA256)); }
public static extern SafeEnclaveHandle CreateEnclave(HPROCESS hProcess, IntPtr lpAddress, SizeT dwSize, SizeT dwInitialCommittment, EnclaveType flEnclaveType, in ENCLAVE_CREATE_INFO_SGX lpEnclaveInformation, uint dwInfoLength, out uint lpEnclaveError);