private UnityTls.unitytls_x509verify_result VerifyCallback(UnityTls.unitytls_x509list_ref chain, UnityTls.unitytls_errorstate *errorState) { try { using (var chainImpl = new X509ChainImplUnityTls(chain)) using (var managedChain = new X509Chain(chainImpl)) { remoteCertificate = managedChain.ChainElements[0].Certificate; // Note that the overload of this method that takes a X509CertificateCollection will not pass on the chain to // user callbacks like ServicePointManager.ServerCertificateValidationCallback which can cause issues along the line. if (ValidateCertificate(remoteCertificate, managedChain)) { return(UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_SUCCESS); } return(UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_FLAG_NOT_TRUSTED); } } catch (Exception ex) { // handle all exceptions and store them for later since we don't want to let them go through native code. if (lastException == null) { lastException = ex; } return(UnityTls.unitytls_x509verify_result.UNITYTLS_X509VERIFY_FATAL_ERROR); } }
private size_t WriteCallback(byte *data, size_t bufferLen, UnityTls.unitytls_errorstate *errorState) { try { if (writeBuffer == null || writeBuffer.Length < (int)bufferLen) { writeBuffer = new byte[(int)bufferLen]; } Marshal.Copy((IntPtr)data, writeBuffer, 0, (int)bufferLen); if (!Parent.InternalWrite(writeBuffer, 0, (int)bufferLen)) { UnityTls.NativeInterface.unitytls_errorstate_raise_error(errorState, UnityTls.unitytls_error_code.UNITYTLS_USER_WRITE_FAILED); return((size_t)0); } return(bufferLen); } catch (Exception ex) { // handle all exceptions and store them for later since we don't want to let them go through native code. UnityTls.NativeInterface.unitytls_errorstate_raise_error(errorState, UnityTls.unitytls_error_code.UNITYTLS_USER_UNKNOWN_ERROR); if (lastException == null) { lastException = ex; } return((size_t)0); } }
public static void AddCertificateToNativeChain(UnityTls.unitytls_x509list *nativeCertificateChain, X509Certificate certificate, UnityTls.unitytls_errorstate *errorState) { var certDer = certificate.GetRawCertData(); fixed(byte *certDerPtr = certDer) { UnityTls.NativeInterface.unitytls_x509list_append_der(nativeCertificateChain, certDerPtr, (size_t)certDer.Length, errorState); } var certificateImpl2 = certificate.Impl as X509Certificate2Impl; if (certificate is X509Certificate2 cert2 && cert2.Impl != null) { var intermediates = certificateImpl2.IntermediateCertificates; if (intermediates != null && intermediates.Count > 0) { for (var i = 0; i < intermediates.Count; ++i) { AddCertificateToNativeChain(nativeCertificateChain, new X509Certificate(intermediates[i]), errorState); } } } }
private static size_t ReadCallback(void *userData, byte *buffer, size_t bufferLen, UnityTls.unitytls_errorstate *errorState) { var handle = (GCHandle)(IntPtr)userData; var context = (UnityTlsContext)handle.Target; return(context.ReadCallback(buffer, bufferLen, errorState)); }
private static void CertificateCallback(void *userData, UnityTls.unitytls_tlsctx *ctx, byte *cn, size_t cnLen, UnityTls.unitytls_x509name *caList, size_t caListLen, UnityTls.unitytls_x509list_ref *chain, UnityTls.unitytls_key_ref *key, UnityTls.unitytls_errorstate *errorState) { var handle = (GCHandle)(IntPtr)userData; var context = (UnityTlsContext)handle.Target; context.CertificateCallback(ctx, cn, cnLen, caList, caListLen, chain, key, errorState); }
private size_t ReadCallback(byte *buffer, size_t bufferLen, UnityTls.unitytls_errorstate *errorState) { try { if (readBuffer == null || readBuffer.Length < (int)bufferLen) { readBuffer = new byte [(int)bufferLen]; } bool wouldBlock; var numBytesRead = Parent.InternalRead(readBuffer, 0, (int)bufferLen, out wouldBlock); // Non graceful exit. if (numBytesRead < 0) { UnityTls.NativeInterface.unitytls_errorstate_raise_error(errorState, UnityTls.unitytls_error_code.UNITYTLS_USER_READ_FAILED); } else if (numBytesRead > 0) { Marshal.Copy(readBuffer, 0, (IntPtr)buffer, (int)bufferLen); } else { // numBytesRead == 0 // careful when rearranging this: wouldBlock might be true even if stream was closed abruptly. if (wouldBlock) { UnityTls.NativeInterface.unitytls_errorstate_raise_error(errorState, UnityTls.unitytls_error_code.UNITYTLS_USER_WOULD_BLOCK); } // indicates graceful exit. // UnityTls only accepts an exit as gracful, if it was closed via a special TLS protocol message. // Both .Net and MobileTlsContext have a different idea of this concept though! else { closedGraceful = true; UnityTls.NativeInterface.unitytls_errorstate_raise_error(errorState, UnityTls.unitytls_error_code.UNITYTLS_USER_READ_FAILED); } } // Note that UnityTls ignores this number when raising an error. return((size_t)numBytesRead); } catch (Exception ex) { // handle all exceptions and store them for later since we don't want to let them go through native code. UnityTls.NativeInterface.unitytls_errorstate_raise_error(errorState, UnityTls.unitytls_error_code.UNITYTLS_USER_UNKNOWN_ERROR); if (lastException == null) { lastException = ex; } return((size_t)0); } }
private void CertificateCallback(UnityTls.unitytls_tlsctx *ctx, byte *cn, size_t cnLen, UnityTls.unitytls_x509name *caList, size_t caListLen, UnityTls.unitytls_x509list_ref *chain, UnityTls.unitytls_key_ref *key, UnityTls.unitytls_errorstate *errorState) { try { if (remoteCertificate == null) { throw new TlsException(AlertDescription.InternalError, "Cannot request client certificate before receiving one from the server."); } localClientCertificate = SelectClientCertificate(null); if (localClientCertificate == null) { *chain = new UnityTls.unitytls_x509list_ref { handle = UnityTls.NativeInterface.UNITYTLS_INVALID_HANDLE }; *key = new UnityTls.unitytls_key_ref { handle = UnityTls.NativeInterface.UNITYTLS_INVALID_HANDLE }; } else { // Need to create native objects for client chain/key. Need to keep them cached. // Make sure we don't have old native objects still around. UnityTls.NativeInterface.unitytls_x509list_free(requestedClientCertChain); UnityTls.NativeInterface.unitytls_key_free(requestedClientKey); ExtractNativeKeyAndChainFromManagedCertificate(localClientCertificate, errorState, out requestedClientCertChain, out requestedClientKey); *chain = UnityTls.NativeInterface.unitytls_x509list_get_ref(requestedClientCertChain, errorState); *key = UnityTls.NativeInterface.unitytls_key_get_ref(requestedClientKey, errorState); } Unity.Debug.CheckAndThrow(*errorState, "Failed to retrieve certificates on request.", AlertDescription.HandshakeFailure); } catch (Exception ex) { // handle all exceptions and store them for later since we don't want to let them go through native code. UnityTls.NativeInterface.unitytls_errorstate_raise_error(errorState, UnityTls.unitytls_error_code.UNITYTLS_USER_UNKNOWN_ERROR); if (lastException == null) { lastException = ex; } } }
private static void ExtractNativeKeyAndChainFromManagedCertificate(X509Certificate cert, UnityTls.unitytls_errorstate *errorState, out UnityTls.unitytls_x509list *nativeCertChain, out UnityTls.unitytls_key *nativeKey) { if (cert == null) { throw new ArgumentNullException("cert"); } var cert2 = cert as X509Certificate2; if (cert2 == null || cert2.PrivateKey == null) { throw new ArgumentException("Certificate does not have a private key", "cert"); } nativeCertChain = null; nativeKey = null; try { nativeCertChain = UnityTls.NativeInterface.unitytls_x509list_create(errorState); CertHelper.AddCertificateToNativeChain(nativeCertChain, cert2, errorState); var privateKeyDer = PKCS8.PrivateKeyInfo.Encode(cert2.PrivateKey); fixed(byte *privateKeyDerPtr = privateKeyDer) { nativeKey = UnityTls.NativeInterface.unitytls_key_parse_der(privateKeyDerPtr, (size_t)privateKeyDer.Length, null, (size_t)0, errorState); } } catch { UnityTls.NativeInterface.unitytls_x509list_free(nativeCertChain); UnityTls.NativeInterface.unitytls_key_free(nativeKey); throw; } }
private static UnityTls.unitytls_x509verify_result VerifyCallback(void *userData, UnityTls.unitytls_x509list_ref chain, UnityTls.unitytls_errorstate *errorState) { var handle = (GCHandle)(IntPtr)userData; var context = (UnityTlsContext)handle.Target; return(context.VerifyCallback(chain, errorState)); }
public static void AddCertificatesToNativeChain(UnityTls.unitytls_x509list *nativeCertificateChain, X509CertificateCollection certificates, UnityTls.unitytls_errorstate *errorState) { foreach (var certificate in certificates) { AddCertificateToNativeChain(nativeCertificateChain, certificate, errorState); } }