Пример #1
0
        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);
            }
        }
Пример #2
0
        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);
            }
        }
Пример #3
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);
                    }
                }
            }
        }
Пример #4
0
        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));
        }
Пример #5
0
        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);
        }
Пример #6
0
        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);
            }
        }
Пример #7
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;
                }
            }
        }
Пример #8
0
        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;
            }
        }
Пример #9
0
        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));
        }
Пример #10
0
 public static void AddCertificatesToNativeChain(UnityTls.unitytls_x509list *nativeCertificateChain,
                                                 X509CertificateCollection certificates, UnityTls.unitytls_errorstate *errorState)
 {
     foreach (var certificate in certificates)
     {
         AddCertificateToNativeChain(nativeCertificateChain, certificate, errorState);
     }
 }