public DtlsClientSecurityContext( SecurityPackageType packageType, CertificateCredential clientCredential, string serverPrincipal, ClientSecurityContextAttribute contextAttributes, SecurityTargetDataRepresentation targetDataRep) { if (clientCredential == null) { clientCredential = new CertificateCredential(null); } this.packageType = packageType; this.serverPrincipalName = serverPrincipal; this.securityContextAttributes = contextAttributes; this.targetDataRepresentaion = targetDataRep; SspiUtility.DtlsAcquireCredentialsHandle( packageType, clientCredential, serverPrincipal, NativeMethods.SECPKG_CRED_OUTBOUND, out this.credentialHandle); bStreamSizes = false; hasMoreFragments = false; }
/// <summary> /// Encrypts Message. User decides what SecBuffers are used. /// </summary> /// <param name="kileRole">Represents client or server</param> /// <param name="securityBuffers">The security buffers to encrypt.</param> /// <exception cref="System.ArgumentException">Thrown when the data or token is not valid.</exception> internal static void Encrypt(KileRole kileRole, params SecurityBuffer[] securityBuffers) { byte[] message = SspiUtility.ConcatenateReadWriteSecurityBuffers(securityBuffers, SecurityBufferType.Data); byte[] token = SspiUtility.ConcatenateSecurityBuffers(securityBuffers, SecurityBufferType.Token); if (token.Length == 0) { throw new ArgumentException("Token buffer is not valid."); } SGN_ALG sgnAlg = GetSgnAlg(kileRole); KilePdu pdu = kileRole.GssWrap(true, sgnAlg, message); byte[] cipherData = null; if (pdu.GetType() == typeof(Token4121)) { cipherData = pdu.ToBytes(); } else { byte[] allData = pdu.ToBytes(); byte[] paddingData = ((Token1964_4757)pdu).paddingData; cipherData = ArrayUtility.SubArray(allData, 0, allData.Length - paddingData.Length); SspiUtility.UpdateSecurityBuffers(securityBuffers, SecurityBufferType.Padding, paddingData); } SspiUtility.UpdateSecurityBuffers(securityBuffers, SecurityBufferType.Data, ArrayUtility.SubArray(cipherData, cipherData.Length - message.Length)); SspiUtility.UpdateSecurityBuffers(securityBuffers, SecurityBufferType.Token, ArrayUtility.SubArray(cipherData, 0, cipherData.Length - message.Length)); }
/// <summary> /// Decrypt a request or response /// </summary> /// <param name="securityBuffers">Security buffers containing encrypted data.</param> /// <param name="sentFromClient">True if the token is a request, false is a response</param> /// <returns>Plain-text data.</returns> private byte[] Decrypt(SecurityBuffer[] securityBuffers, bool sentFromClient) { KileContext context = sentFromClient ? (KileContext)kileDecoder.serverContext : (KileContext)kileDecoder.clientContext; KileRole.GssUnWrapEx(context, securityBuffers); return(SspiUtility.ConcatenateReadWriteSecurityBuffers(securityBuffers, SecurityBufferType.Data)); }
/// <summary> /// Verify method validates the signature against given plain-text message. /// </summary> /// <param name="securityBuffers">A list of security buffers that contains data to sign and output signature. /// </param> /// <returns> Returns true if signature is correct; otherwise, false.</returns> public override bool Verify(params SecurityBuffer[] securityBuffers) { if (null == securityBuffers || 0 == securityBuffers.Length) { throw new ArgumentNullException("securityBuffers"); } foreach (SecurityBuffer buffer in securityBuffers) { if (null == buffer) { throw new ArgumentException("one or more values in securityBuffers is NULL"); } } byte[] token = SspiUtility.ConcatenateSecurityBuffers(securityBuffers, SecurityBufferType.Token); if (0 != (Context.NegotiateFlags & NrpcNegotiateFlags.SupportsAESAndSHA2)) { this.nlnlAuthSha2Sign = TypeMarshal.ToStruct <NL_AUTH_SHA2_SIGNATURE>(token); } else { this.nlnlAuthSign = TypeMarshal.ToStruct <NL_AUTH_SIGNATURE>(token); } this.isSignatureCorrect = base.Verify(securityBuffers); return(this.isSignatureCorrect); }
/// <summary> /// Release resources. /// </summary> /// <param name="disposing">If true, release all resource, otherwise release managed resources.</param> protected virtual void Dispose(bool disposing) { if (!this.disposed) { if (disposing) { //release un-managed resources. SspiUtility.DeleteSecurityContext(ref this.contextHandle); SspiUtility.FreeCredentialsHandle(ref this.credentialHandle); } this.disposed = true; } }
/// <summary> /// This takes the given message and verifies it using SSPI(VerifySignature). The given message /// should be formatted as follow: /// |MESSAGE_LENGTH(4 bytes)|MESSAGE /// </summary> /// <param name="messageToBeVerified">Signed message to be verified</param> /// <param name="signature">Signature</param> /// <returns>If true, verify successful, otherwise failed.</returns> /// <exception cref="SspiException">If verify fail, this exception will be thrown.</exception> /// <exception cref="ArgumentNullException">If messageToBeVerified is null, this exception will be thrown. /// </exception> /// <exception cref="ArgumentException">If messageToBeVerified is not formatted as /// "MESSAGE_LENGTH(4 bytes)|MESSAGE", this exception will be thrown.</exception> public bool VerifyMessage(byte[] messageToBeVerified, byte[] signature) { if (!SspiUtility.VerifyMessageHeader(messageToBeVerified)) { throw new ArgumentException( "Value of message header is not consistent with the actual length of message.", "messageToBeVerified"); } //Remove header. byte[] messageBody = new byte[messageToBeVerified.Length - sizeof(int)]; Array.Copy(messageToBeVerified, sizeof(int), messageBody, 0, messageBody.Length); return(Verify(messageBody, signature)); }
/// <summary> /// This takes the given SecurityBuffer array, signs data part, and updates signature into token part /// </summary> /// <param name="kileRole">Represents client or server</param> /// <param name="securityBuffers">Data to sign and token to update.</param> /// <exception cref="System.ArgumentException">Thrown when the data or token is not valid.</exception> internal static void Sign(KileRole kileRole, params SecurityBuffer[] securityBuffers) { byte[] token = SspiUtility.ConcatenateReadWriteSecurityBuffers(securityBuffers, SecurityBufferType.Token); if (token.Length == 0) { throw new ArgumentException("No token can be updated for signature."); } byte[] message = GetToBeSignedDataFromSecurityBuffers(securityBuffers); SGN_ALG sgnAlg = GetSgnAlg(kileRole); KilePdu pdu = kileRole.GssGetMic(sgnAlg, message); byte[] signature = pdu.ToBytes(); SspiUtility.UpdateSecurityBuffers(securityBuffers, SecurityBufferType.Token, signature); }
/// <summary> /// Decrypts the encrypted message(contains message header) and returns decrypted message. /// Schannel is not supported. /// The given message must be formatted as follow: /// MESSAGE_LENGTH(4 bytes)|MESSAGE /// </summary> /// <param name="messageToBeDecrypted">Message to be decrypted</param> /// <returns>Decrypted message</returns> /// <exception cref="ArgumentNullException">If messageToBeDecrypted is null, this exception will be thrown. /// </exception> /// <exception cref="ArgumentException">If messageToBeDecrypted is not formatted as /// "MESSAGE_LENGTH(4 bytes)|MESSAGE", this exception will be thrown.</exception> public byte[] DecryptMessage(byte[] messageToBeDecrypted) { if (!SspiUtility.VerifyMessageHeader(messageToBeDecrypted)) { throw new ArgumentException( "Value of message header is not consistent with the actual length of message.", "messageToBeDecrypted"); } //Remove message header int messageLength = BitConverter.ToInt32(messageToBeDecrypted, 0); byte[] message = ArrayUtility.SubArray(messageToBeDecrypted, sizeof(int), messageLength); byte[] signature = ArrayUtility.SubArray(messageToBeDecrypted, sizeof(int) + messageLength); return(Decrypt(message, signature)); }
/// <summary> /// Constructor /// </summary> /// <param name="packageType">Specifies the name of the security package with which these credentials will be used /// </param> /// <param name="serverCredential">The credential of server, if null, use default user account.</param> /// <param name="serverPrincipal">Server principal name</param> /// <param name="contextAttributes">Bit flags that specify the attributes required by the server to establish /// the context</param> /// <param name="targetDataRep">The data representation, such as byte ordering, on the target. This parameter /// can be either SECURITY_NATIVE_DREP or SECURITY_NETWORK_DREP.</param> public SspiServerSecurityContext( SecurityPackageType packageType, AccountCredential serverCredential, string serverPrincipal, ServerSecurityContextAttribute contextAttributes, SecurityTargetDataRepresentation targetDataRep) { this.packageType = packageType; this.serverPrincipalName = serverPrincipal; this.securityContextAttributes = contextAttributes; this.targetDataRepresentaion = targetDataRep; SspiUtility.AcquireCredentialsHandle( packageType, serverCredential, serverPrincipal, NativeMethods.SECPKG_CRED_INBOUND, out this.credentialHandle); }
/// <summary> /// This takes the given byte array, decrypts it, and returns /// the original, unencrypted byte array. /// </summary> /// <param name="kileRole">Represents client or server</param> /// <param name="securityBuffers">The security buffers to decrypt.</param> /// <exception cref="System.ArgumentException">Thrown when the data or token is not valid.</exception> internal static bool Decrypt(KileRole kileRole, params SecurityBuffer[] securityBuffers) { KilePdu pdu = kileRole.GssUnWrapEx(securityBuffers); byte[] decryptedMessage = null; if (pdu.GetType() == typeof(Token4121)) { decryptedMessage = ((Token4121)pdu).Data; } else if (pdu.GetType() == typeof(Token1964_4757)) { Token1964_4757 tokenData = (Token1964_4757)pdu; decryptedMessage = tokenData.Data; SspiUtility.UpdateSecurityBuffers(securityBuffers, SecurityBufferType.Padding, tokenData.paddingData); } // else do nothing return(true); }
/// <summary> /// Query context attribute by Sspi QueryContextAttributes method. /// </summary> /// <param name="contextAttribute">Attribute name same as msdn: /// http://msdn.microsoft.com/en-us/library/aa379326(VS.85).aspx</param> /// <returns>The attribute value</returns> /// <exception cref="SspiException">If QueryContextAttributes fail, this exception will be thrown.</exception> public override object QueryContextAttributes(string contextAttribute) { return(SspiUtility.QueryContextAttributes(ref this.contextHandle, contextAttribute)); }
/// <summary> /// This takes the given SecBuffers, which are used by SSPI method DecryptMessage. /// </summary> /// <param name="securityBuffers">SecBuffer.Encrypted data will be filled in SecBuffers.</param> /// <returns>If successful, returns true, otherwise false.</returns> /// <exception cref="SspiException">If sign fail, this exception will be thrown.</exception> public override bool Decrypt(params SecurityBuffer[] securityBuffers) { return(SspiUtility.Decrypt(ref this.contextHandle, this.sequenceNumber, securityBuffers)); }
/// <summary> /// Encrypts Message. User decides what SecBuffers are used. /// </summary> /// <param name="securityBuffers">SecBuffers.</param> /// <exception cref="SspiException">If encrypt fail, this exception will be thrown.</exception> public override void Encrypt(params SecurityBuffer[] securityBuffers) { SspiUtility.Encrypt(ref this.contextHandle, this.sequenceNumber, this.qualityOfProtection, securityBuffers); }
/// <summary> /// Encrypts Message. User decides what SecBuffers are used. /// </summary> /// <param name="securityBuffers">SecBuffers.</param> /// <exception cref="SspiException">If encrypt fail, this exception will be thrown.</exception> public override bool Verify(params SecurityBuffer[] securityBuffers) { return(SspiUtility.VerifySignature(ref this.contextHandle, this.sequenceNumber, securityBuffers)); }
/// <summary> /// Sign data according SecBuffers. /// </summary> /// <param name="securityBuffers">SecurityBuffer array</param> /// <exception cref="SspiException">If Sign fail, this exception will be thrown.</exception> public override void Sign(params SecurityBuffer[] securityBuffers) { SspiUtility.MakeSignature(ref this.contextHandle, this.sequenceNumber, securityBuffers); }