private static ServiceResult CheckChainStatus(X509ChainStatus status, CertificateIdentifier id, CertificateIdentifier issuer, bool isIssuer) { switch (status.Status) { case X509ChainStatusFlags.NotValidForUsage: { return(ServiceResult.Create( (isIssuer) ? StatusCodes.BadCertificateUseNotAllowed : StatusCodes.BadCertificateIssuerUseNotAllowed, "Certificate may not be used as an application instance certificate. {0}: {1}", status.Status, status.StatusInformation)); } case X509ChainStatusFlags.NoError: case X509ChainStatusFlags.OfflineRevocation: case X509ChainStatusFlags.InvalidBasicConstraints: case X509ChainStatusFlags.PartialChain: { break; } case X509ChainStatusFlags.UntrustedRoot: { // self signed cert signature validation // .Net Core ChainStatus returns NotSignatureValid only on Windows, // so we have to do the extra cert signature check on all platforms if (issuer == null && !isIssuer && id.Certificate != null && Utils.CompareDistinguishedName(id.Certificate.Subject, id.Certificate.Subject)) { if (!IsSignatureValid(id.Certificate)) { goto case X509ChainStatusFlags.NotSignatureValid; } } // ignore this error because the root check is done // by looking the certificate up in the trusted issuer stores passed to the validator. // the ChainStatus uses the trusted issuer stores. break; } case X509ChainStatusFlags.RevocationStatusUnknown: { if (issuer != null) { if ((issuer.ValidationOptions & CertificateValidationOptions.SuppressRevocationStatusUnknown) != 0) { break; } } // check for meaning less errors for self-signed certificates. if (id.Certificate != null && Utils.CompareDistinguishedName(id.Certificate.Subject, id.Certificate.Subject)) { break; } return(ServiceResult.Create( (isIssuer) ? StatusCodes.BadCertificateIssuerRevocationUnknown : StatusCodes.BadCertificateRevocationUnknown, "Certificate revocation status cannot be verified. {0}: {1}", status.Status, status.StatusInformation)); } case X509ChainStatusFlags.Revoked: { return(ServiceResult.Create( (isIssuer) ? StatusCodes.BadCertificateIssuerRevoked : StatusCodes.BadCertificateRevoked, "Certificate has been revoked. {0}: {1}", status.Status, status.StatusInformation)); } case X509ChainStatusFlags.NotTimeNested: { if (id != null && ((id.ValidationOptions & CertificateValidationOptions.SuppressCertificateExpired) != 0)) { break; } return(ServiceResult.Create( StatusCodes.BadCertificateIssuerTimeInvalid, "Certificate issuer validatity time does not overhas is expired or not yet valid. {0}: {1}", status.Status, status.StatusInformation)); } case X509ChainStatusFlags.NotTimeValid: { if (id != null && ((id.ValidationOptions & CertificateValidationOptions.SuppressCertificateExpired) != 0)) { break; } return(ServiceResult.Create( (isIssuer) ? StatusCodes.BadCertificateIssuerTimeInvalid : StatusCodes.BadCertificateTimeInvalid, "Certificate has is expired or not yet valid. {0}: {1}", status.Status, status.StatusInformation)); } case X509ChainStatusFlags.NotSignatureValid: { return(ServiceResult.Create( StatusCodes.BadCertificateUntrusted, status.StatusInformation)); } default: { return(ServiceResult.Create( StatusCodes.BadCertificateInvalid, "Certificate validation failed. {0}: {1}", status.Status, status.StatusInformation)); } } return(null); }
private void Set (X509ChainStatus[] status, ref int position, X509ChainStatusFlags flags, X509ChainStatusFlags mask) { if ((flags & mask) != 0) { status [position].Status = mask; status [position].StatusInformation = X509ChainStatus.GetInformation (mask); position++; } }
private static X509ChainStatus[] GetChainStatusInformation(CertTrustErrorStatus dwStatus) { if (dwStatus == CertTrustErrorStatus.CERT_TRUST_NO_ERROR) { return(Array.Empty <X509ChainStatus>()); } int count = 0; for (uint bits = (uint)dwStatus; bits != 0; bits = bits >> 1) { if ((bits & 0x1) != 0) { count++; } } X509ChainStatus[] chainStatus = new X509ChainStatus[count]; int index = 0; if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_IS_NOT_SIGNATURE_VALID) != 0) { chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.TRUST_E_CERT_SIGNATURE); chainStatus[index].Status = X509ChainStatusFlags.NotSignatureValid; index++; dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_IS_NOT_SIGNATURE_VALID; } if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID) != 0) { chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.TRUST_E_CERT_SIGNATURE); chainStatus[index].Status = X509ChainStatusFlags.CtlNotSignatureValid; index++; dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID; } if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_IS_UNTRUSTED_ROOT) != 0) { chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CERT_E_UNTRUSTEDROOT); chainStatus[index].Status = X509ChainStatusFlags.UntrustedRoot; index++; dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_IS_UNTRUSTED_ROOT; } if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_IS_PARTIAL_CHAIN) != 0) { chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CERT_E_CHAINING); chainStatus[index].Status = X509ChainStatusFlags.PartialChain; index++; dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_IS_PARTIAL_CHAIN; } if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_IS_REVOKED) != 0) { chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CRYPT_E_REVOKED); chainStatus[index].Status = X509ChainStatusFlags.Revoked; index++; dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_IS_REVOKED; } if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_IS_NOT_VALID_FOR_USAGE) != 0) { chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CERT_E_WRONG_USAGE); chainStatus[index].Status = X509ChainStatusFlags.NotValidForUsage; index++; dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_IS_NOT_VALID_FOR_USAGE; } if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE) != 0) { chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CERT_E_WRONG_USAGE); chainStatus[index].Status = X509ChainStatusFlags.CtlNotValidForUsage; index++; dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE; } if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_IS_NOT_TIME_VALID) != 0) { chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CERT_E_EXPIRED); chainStatus[index].Status = X509ChainStatusFlags.NotTimeValid; index++; dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_IS_NOT_TIME_VALID; } if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_CTL_IS_NOT_TIME_VALID) != 0) { chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CERT_E_EXPIRED); chainStatus[index].Status = X509ChainStatusFlags.CtlNotTimeValid; index++; dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_CTL_IS_NOT_TIME_VALID; } if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_INVALID_NAME_CONSTRAINTS) != 0) { chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CERT_E_INVALID_NAME); chainStatus[index].Status = X509ChainStatusFlags.InvalidNameConstraints; index++; dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_INVALID_NAME_CONSTRAINTS; } if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT) != 0) { chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CERT_E_INVALID_NAME); chainStatus[index].Status = X509ChainStatusFlags.HasNotSupportedNameConstraint; index++; dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT; } if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT) != 0) { chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CERT_E_INVALID_NAME); chainStatus[index].Status = X509ChainStatusFlags.HasNotDefinedNameConstraint; index++; dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT; } if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT) != 0) { chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CERT_E_INVALID_NAME); chainStatus[index].Status = X509ChainStatusFlags.HasNotPermittedNameConstraint; index++; dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT; } if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT) != 0) { chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CERT_E_INVALID_NAME); chainStatus[index].Status = X509ChainStatusFlags.HasExcludedNameConstraint; index++; dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT; } if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_INVALID_POLICY_CONSTRAINTS) != 0) { chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CERT_E_INVALID_POLICY); chainStatus[index].Status = X509ChainStatusFlags.InvalidPolicyConstraints; index++; dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_INVALID_POLICY_CONSTRAINTS; } if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY) != 0) { chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CERT_E_INVALID_POLICY); chainStatus[index].Status = X509ChainStatusFlags.NoIssuanceChainPolicy; index++; dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY; } if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_INVALID_BASIC_CONSTRAINTS) != 0) { chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.TRUST_E_BASIC_CONSTRAINTS); chainStatus[index].Status = X509ChainStatusFlags.InvalidBasicConstraints; index++; dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_INVALID_BASIC_CONSTRAINTS; } if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_IS_NOT_TIME_NESTED) != 0) { chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CERT_E_VALIDITYPERIODNESTING); chainStatus[index].Status = X509ChainStatusFlags.NotTimeNested; index++; dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_IS_NOT_TIME_NESTED; } if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_REVOCATION_STATUS_UNKNOWN) != 0) { chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CRYPT_E_NO_REVOCATION_CHECK); chainStatus[index].Status = X509ChainStatusFlags.RevocationStatusUnknown; index++; dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_REVOCATION_STATUS_UNKNOWN; } if ((dwStatus & CertTrustErrorStatus.CERT_TRUST_IS_OFFLINE_REVOCATION) != 0) { chainStatus[index].StatusInformation = GetSystemErrorString(ErrorCode.CRYPT_E_REVOCATION_OFFLINE); chainStatus[index].Status = X509ChainStatusFlags.OfflineRevocation; index++; dwStatus &= ~CertTrustErrorStatus.CERT_TRUST_IS_OFFLINE_REVOCATION; } int shiftCount = 0; for (uint bits = (uint)dwStatus; bits != 0; bits = bits >> 1) { if ((bits & 0x1) != 0) { chainStatus[index].Status = (X509ChainStatusFlags)(1 << shiftCount); chainStatus[index].StatusInformation = SR.Unknown_Error; index++; } shiftCount++; } return(chainStatus); }
public static IChainPal BuildChain( X509Certificate2 leaf, List <X509Certificate2> candidates, List <X509Certificate2> downloaded, List <X509Certificate2> systemTrusted, OidCollection applicationPolicy, OidCollection certificatePolicy, X509RevocationMode revocationMode, X509RevocationFlag revocationFlag, DateTime verificationTime, ref TimeSpan remainingDownloadTime) { X509ChainElement[] elements; List <X509ChainStatus> overallStatus = new List <X509ChainStatus>(); WorkingChain workingChain = new WorkingChain(); Interop.Crypto.X509StoreVerifyCallback workingCallback = workingChain.VerifyCallback; // An X509_STORE is more comparable to Cryptography.X509Certificate2Collection than to // Cryptography.X509Store. So read this with OpenSSL eyes, not CAPI/CNG eyes. // // (If you need to think of it as an X509Store, it's a volatile memory store) using (SafeX509StoreHandle store = Interop.Crypto.X509StoreCreate()) using (SafeX509StoreCtxHandle storeCtx = Interop.Crypto.X509StoreCtxCreate()) { Interop.Crypto.CheckValidOpenSslHandle(store); Interop.Crypto.CheckValidOpenSslHandle(storeCtx); bool lookupCrl = revocationMode != X509RevocationMode.NoCheck; foreach (X509Certificate2 cert in candidates) { OpenSslX509CertificateReader pal = (OpenSslX509CertificateReader)cert.Pal; if (!Interop.Crypto.X509StoreAddCert(store, pal.SafeHandle)) { throw Interop.Crypto.CreateOpenSslCryptographicException(); } if (lookupCrl) { CrlCache.AddCrlForCertificate( cert, store, revocationMode, verificationTime, ref remainingDownloadTime); // If we only wanted the end-entity certificate CRL then don't look up // any more of them. lookupCrl = revocationFlag != X509RevocationFlag.EndCertificateOnly; } } if (revocationMode != X509RevocationMode.NoCheck) { if (!Interop.Crypto.X509StoreSetRevocationFlag(store, revocationFlag)) { throw Interop.Crypto.CreateOpenSslCryptographicException(); } } SafeX509Handle leafHandle = ((OpenSslX509CertificateReader)leaf.Pal).SafeHandle; if (!Interop.Crypto.X509StoreCtxInit(storeCtx, store, leafHandle)) { throw Interop.Crypto.CreateOpenSslCryptographicException(); } Interop.Crypto.X509StoreCtxSetVerifyCallback(storeCtx, workingCallback); Interop.Crypto.SetX509ChainVerifyTime(storeCtx, verificationTime); int verify = Interop.Crypto.X509VerifyCert(storeCtx); if (verify < 0) { throw Interop.Crypto.CreateOpenSslCryptographicException(); } // Because our callback tells OpenSSL that every problem is ignorable, it should tell us that the // chain is just fine (unless it returned a negative code for an exception) Debug.Assert(verify == 1, "verify == 1"); using (SafeX509StackHandle chainStack = Interop.Crypto.X509StoreCtxGetChain(storeCtx)) { int chainSize = Interop.Crypto.GetX509StackFieldCount(chainStack); elements = new X509ChainElement[chainSize]; int maybeRootDepth = chainSize - 1; // The leaf cert is 0, up to (maybe) the root at chainSize - 1 for (int i = 0; i < chainSize; i++) { List <X509ChainStatus> status = new List <X509ChainStatus>(); List <Interop.Crypto.X509VerifyStatusCode> elementErrors = i < workingChain.Errors.Count ? workingChain.Errors[i] : null; if (elementErrors != null) { AddElementStatus(elementErrors, status, overallStatus); } IntPtr elementCertPtr = Interop.Crypto.GetX509StackField(chainStack, i); if (elementCertPtr == IntPtr.Zero) { throw Interop.Crypto.CreateOpenSslCryptographicException(); } // Duplicate the certificate handle X509Certificate2 elementCert = new X509Certificate2(elementCertPtr); // If the last cert is self signed then it's the root cert, do any extra checks. if (i == maybeRootDepth && IsSelfSigned(elementCert)) { // If the root certificate was downloaded or the system // doesn't trust it, it's untrusted. if (downloaded.Contains(elementCert) || !systemTrusted.Contains(elementCert)) { AddElementStatus( Interop.Crypto.X509VerifyStatusCode.X509_V_ERR_CERT_UNTRUSTED, status, overallStatus); } } elements[i] = new X509ChainElement(elementCert, status.ToArray(), ""); } } } GC.KeepAlive(workingCallback); if ((certificatePolicy != null && certificatePolicy.Count > 0) || (applicationPolicy != null && applicationPolicy.Count > 0)) { List <X509Certificate2> certsToRead = new List <X509Certificate2>(); foreach (X509ChainElement element in elements) { certsToRead.Add(element.Certificate); } CertificatePolicyChain policyChain = new CertificatePolicyChain(certsToRead); bool failsPolicyChecks = false; if (certificatePolicy != null) { if (!policyChain.MatchesCertificatePolicies(certificatePolicy)) { failsPolicyChecks = true; } } if (applicationPolicy != null) { if (!policyChain.MatchesApplicationPolicies(applicationPolicy)) { failsPolicyChecks = true; } } if (failsPolicyChecks) { X509ChainElement leafElement = elements[0]; X509ChainStatus chainStatus = new X509ChainStatus { Status = X509ChainStatusFlags.InvalidPolicyConstraints, StatusInformation = SR.Chain_NoPolicyMatch, }; var elementStatus = new List <X509ChainStatus>(leafElement.ChainElementStatus.Length + 1); elementStatus.AddRange(leafElement.ChainElementStatus); AddUniqueStatus(elementStatus, ref chainStatus); AddUniqueStatus(overallStatus, ref chainStatus); elements[0] = new X509ChainElement( leafElement.Certificate, elementStatus.ToArray(), leafElement.Information); } } return(new OpenSslX509ChainProcessor { ChainStatus = overallStatus.ToArray(), ChainElements = elements, }); }
/// <summary> /// Constructor with chainstatus as keyword /// </summary> /// <param name="chainStatus">chainstatus as keyword</param> public CertificateFailedChainValidationException(X509ChainStatus chainStatus, string subject) : base(GetKeywords(chainStatus, subject)) { }
private static Dictionary <string, string> GetKeywords(X509ChainStatus chainStatus, string subject) { return(GetKeywords(chainStatus.Status.ToString(), subject)); }
/// <summary> /// Performs the secure handshake so we can start sending messages. /// </summary> /// <returns></returns> private async Task HandshakeAsync() { // wait on semaphore await _handshakeSemaphore.WaitAsync(); // check if we got raced if (_serverEncryptionKey != null && !SecureUtils.HasTimeSlotExpired(_serverEncryptionKeyTimeSlot, false)) { return; } try { // create client key GenerateHandshakeKey(); // get certificate if we don't have it yet if (_serverCertificate == null) { // log #if DEBUG_SECURE Console.WriteLine($"[Secure] Handshake Requesting certificate..."); #endif // request certificate SecureHeader requestCertificate = new SecureHeader(SecureHeader.HeaderVersion, SecureMessageType.RequestCertificate); // send request Envelope respondCert = await _node.AskAsync(_address, new byte[0], _configuration.HandshakeTimeout, new Dictionary <string, object>() { { SecureHeader.HeaderName, requestCertificate.ToString() } }); // parse response header SecureHeader respondCertHeader = null; try { respondCertHeader = new SecureHeader(Encoding.UTF8.GetString(respondCert.Headers[SecureHeader.HeaderName] as byte[])); } catch (Exception ex) { throw new InvalidDataException("The certificate request response header was invalid", ex); } // check if the certificate response is an error or if it's an incorrect type if (respondCertHeader.Type == SecureMessageType.Error) { SecureErrorMsg errorMsg = respondCert.AsProtoBuf <SecureErrorMsg>(); throw new SecurityException($"{errorMsg.Message} ({errorMsg.Code})"); } else if (respondCertHeader.Type != SecureMessageType.RespondCertificate) { throw new InvalidDataException("The certificate request response header was invalid"); } // decode the certificate response and then check it has actual data SecureRespondCertificateMsg respondCertMsg = respondCert.AsProtoBuf <SecureRespondCertificateMsg>(); if (respondCertMsg.CertificateData == null) { throw new InvalidDataException("The certificate request response was invalid"); } // load certificate from response X509Certificate2 cert = new X509Certificate2(respondCertMsg.CertificateData); // validate it's allowed to act as this service if (_configuration.ValidateAddress) { // check extension is actually there if (cert.Extensions["HolonSecureServices"] == null) { throw new InvalidDataException("The service certificate has no claim for the invoked operation"); } // parse extension X509Extension servicesExt = cert.Extensions["HolonSecureServices"]; } else { #if DEBUG_SECURE Console.WriteLine($"[Secure] Handshake WARNING: Not validating services due to configuration!"); #endif } // validate that it's signed by ca authority if (_configuration.ValidateAuthority) { X509Chain chain = new X509Chain(); chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; chain.ChainPolicy.ExtraStore.Add(_configuration.RootAuthority); chain.Build(cert); // get status X509ChainStatus status = chain.ChainStatus.First(); if (status.Status != X509ChainStatusFlags.UntrustedRoot && status.Status != X509ChainStatusFlags.NoError) { throw new InvalidDataException("The service certificate is not signed by the root authority"); } } else { #if DEBUG_SECURE Console.WriteLine($"[Secure] Handshake WARNING: Not validating authority due to configuration!"); #endif } // log #if DEBUG_SECURE Console.WriteLine($"[Secure] Handshake Got certifcate {cert.Subject} ({cert.Thumbprint})"); #endif _serverCertificate = cert; } // log #if DEBUG_SECURE Console.WriteLine($"[Secure] Handshake Requesting key... FirstTime: {_serverEncryptionKey == null}"); #endif // key request SecureRequestKeyMsg requestKeyMsg = new SecureRequestKeyMsg() { HandshakeIV = _handshakeEncryptionIV, HandshakeKey = _handshakeEncryptionKey }; SecureHeader requestKey = new SecureHeader(SecureHeader.HeaderVersion, SecureMessageType.RequestKey); // send request Envelope respondKey = null; using (RSA rsa = _serverCertificate.GetRSAPublicKey()) { using (MemoryStream ms = new MemoryStream()) { // serialize to stream Serializer.Serialize(ms, requestKeyMsg); // encrypt with server certificate byte[] keyRequestBody = rsa.Encrypt(ms.ToArray(), RSAEncryptionPadding.Pkcs1); respondKey = await _node.AskAsync(_address, keyRequestBody, _configuration.HandshakeTimeout, new Dictionary <string, object>() { { SecureHeader.HeaderName, requestKey.ToString() } }); } } // parse response SecureHeader respondKeyHeader = null; try { respondKeyHeader = new SecureHeader(Encoding.UTF8.GetString(respondKey.Headers[SecureHeader.HeaderName] as byte[])); } catch (Exception ex) { throw new InvalidDataException("The key request response header was invalid", ex); } // check if the key response is an error or if it's an incorrect type if (respondKeyHeader.Type == SecureMessageType.Error) { SecureErrorMsg errorMsg = respondKey.AsProtoBuf <SecureErrorMsg>(); throw new SecurityException($"{errorMsg.Message} ({errorMsg.Code})"); } else if (respondKeyHeader.Type != SecureMessageType.RespondKey) { throw new InvalidDataException("The key request response header was invalid"); } // try and decrypt using (MemoryStream decryptedStream = new MemoryStream()) { using (Aes aes = Aes.Create()) { aes.Key = _handshakeEncryptionKey; aes.IV = _handshakeEncryptionIV; using (CryptoStream decryptStream = new CryptoStream(respondKey.AsStream(), aes.CreateDecryptor(), CryptoStreamMode.Read)) { decryptStream.CopyTo(decryptedStream); } } // seek to beginning decryptedStream.Seek(0, SeekOrigin.Begin); // deserialize SecureRespondKeyMsg respondKeyMsg = Serializer.Deserialize <SecureRespondKeyMsg>(decryptedStream); // validate key if (respondKeyMsg.ServerKey == null || respondKeyMsg.ServerNonce == null || respondKeyMsg.ServerKey.Length != 16) { throw new InvalidDataException("The secure key is invalid"); } // log #if DEBUG_SECURE Console.WriteLine($"[Secure] Handshake Got key Timeslot: {respondKeyMsg.KeyTimeSlot} Nonce: {BitConverter.ToString(respondKeyMsg.ServerNonce).Replace("-", "")}"); #endif // set server encryption key _serverEncryptionKey = respondKeyMsg.ServerKey; _serverNonce = respondKeyMsg.ServerNonce; _serverEncryptionKeyTimeSlot = respondKeyMsg.KeyTimeSlot; } } finally { // make sure to release semaphore no matter what _handshakeSemaphore.Release(); } }
public static IChainPal BuildChain( X509Certificate2 leaf, X509Certificate2Collection candidates, OidCollection applicationPolicy, OidCollection certificatePolicy, DateTime verificationTime) { X509ChainElement[] elements; List <X509ChainStatus> overallStatus = new List <X509ChainStatus>(); // An X509_STORE is more comparable to Cryptography.X509Certificate2Collection than to // Cryptography.X509Store. So read this with OpenSSL eyes, not CAPI/CNG eyes. // // (If you need to think of it as an X509Store, it's a volatile memory store) using (SafeX509StoreHandle store = Interop.libcrypto.X509_STORE_new()) using (SafeX509StoreCtxHandle storeCtx = Interop.libcrypto.X509_STORE_CTX_new()) { Interop.libcrypto.CheckValidOpenSslHandle(store); Interop.libcrypto.CheckValidOpenSslHandle(storeCtx); foreach (X509Certificate2 cert in candidates) { OpenSslX509CertificateReader pal = (OpenSslX509CertificateReader)cert.Pal; if (!Interop.libcrypto.X509_STORE_add_cert(store, pal.SafeHandle)) { throw Interop.libcrypto.CreateOpenSslCryptographicException(); } } // When CRL checking support is added, it should be done before the call to // X509_STORE_CTX_init (aka here) by calling X509_STORE_set_flags(store, flags); SafeX509Handle leafHandle = ((OpenSslX509CertificateReader)leaf.Pal).SafeHandle; if (!Interop.libcrypto.X509_STORE_CTX_init(storeCtx, store, leafHandle, IntPtr.Zero)) { throw Interop.libcrypto.CreateOpenSslCryptographicException(); } Interop.NativeCrypto.SetX509ChainVerifyTime(storeCtx, verificationTime); int verify = Interop.libcrypto.X509_verify_cert(storeCtx); if (verify < 0) { throw Interop.libcrypto.CreateOpenSslCryptographicException(); } using (SafeX509StackHandle chainStack = Interop.libcrypto.X509_STORE_CTX_get1_chain(storeCtx)) { int chainSize = Interop.NativeCrypto.GetX509StackFieldCount(chainStack); int errorDepth = -1; Interop.libcrypto.X509VerifyStatusCode errorCode = 0; string errorMsg = null; if (verify == 0) { errorCode = Interop.libcrypto.X509_STORE_CTX_get_error(storeCtx); errorDepth = Interop.libcrypto.X509_STORE_CTX_get_error_depth(storeCtx); errorMsg = Interop.libcrypto.X509_verify_cert_error_string(errorCode); } elements = new X509ChainElement[chainSize]; for (int i = 0; i < chainSize; i++) { List <X509ChainStatus> status = new List <X509ChainStatus>(); if (i == errorDepth) { X509ChainStatus chainStatus = new X509ChainStatus { Status = MapVerifyErrorToChainStatus(errorCode), StatusInformation = errorMsg, }; status.Add(chainStatus); AddUniqueStatus(overallStatus, ref chainStatus); } IntPtr elementCertPtr = Interop.NativeCrypto.GetX509StackField(chainStack, i); if (elementCertPtr == IntPtr.Zero) { throw Interop.libcrypto.CreateOpenSslCryptographicException(); } // Duplicate the certificate handle X509Certificate2 elementCert = new X509Certificate2(elementCertPtr); elements[i] = new X509ChainElement(elementCert, status.ToArray(), ""); } } } if ((certificatePolicy != null && certificatePolicy.Count > 0) || (applicationPolicy != null && applicationPolicy.Count > 0)) { X509Certificate2Collection certsToRead = new X509Certificate2Collection(); foreach (X509ChainElement element in elements) { certsToRead.Add(element.Certificate); } CertificatePolicyChain policyChain = new CertificatePolicyChain(certsToRead); bool failsPolicyChecks = false; if (certificatePolicy != null) { if (!policyChain.MatchesCertificatePolicies(certificatePolicy)) { failsPolicyChecks = true; } } if (applicationPolicy != null) { if (!policyChain.MatchesApplicationPolicies(applicationPolicy)) { failsPolicyChecks = true; } } if (failsPolicyChecks) { X509ChainElement leafElement = elements[0]; X509ChainStatus chainStatus = new X509ChainStatus { Status = X509ChainStatusFlags.InvalidPolicyConstraints, StatusInformation = SR.Chain_NoPolicyMatch, }; var elementStatus = new List <X509ChainStatus>(leafElement.ChainElementStatus.Length + 1); elementStatus.AddRange(leafElement.ChainElementStatus); AddUniqueStatus(elementStatus, ref chainStatus); AddUniqueStatus(overallStatus, ref chainStatus); elements[0] = new X509ChainElement( leafElement.Certificate, elementStatus.ToArray(), leafElement.Information); } } return(new OpenSslX509ChainProcessor { ChainStatus = overallStatus.ToArray(), ChainElements = elements, }); }
private bool loadSigners() { bool checkCRL = Convert.ToBoolean(assinadorRegistry.GetValue("ConsultCRL")); if (documents == null) { return(false); } this.Cursor = Cursors.WaitCursor; lstSigners.Items.Clear(); lstSigners.Groups.Clear(); if (lstDocuments.SelectedItems.Count > 0) { List <string> problematicFoundDocuments = new List <string>(); Signers commonSigners = new Signers(); List <X509Certificate2> nonconformitySigners = new List <X509Certificate2>(); List <X509Certificate2> conformitySigners = new List <X509Certificate2>(); Hashtable certificatesList = new Hashtable(); foreach (FileHistory filepath in selectedDocuments) { try { loadDigitalSignature(filepath.NewPath); if (digitalSignature.error) { if (digitalSignature.DocumentType.Equals(Types.XpsDocument)) { digitalSignature.xpsDocument.Close(); } else if (digitalSignature.DocumentType.Equals(Types.PdfDocument)) { // nothing to-do here } else { digitalSignature.package.Close(); } this.Cursor = Cursors.Arrow; return(false); } invalidSignatures.Clear(); if (!digitalSignature.Validate()) { invalidSignatures = digitalSignature.InvalidDigitalSignatureHolderNames; } ListViewGroup sigaturesGroup = new ListViewGroup(Path.GetFileName(filepath.NewPath)); lstSigners.Groups.Add(sigaturesGroup); foreach (Signer signer in digitalSignature.signers) { string[] signature = new string[5]; signature[0] = signer.name; signature[1] = signer.issuer; signature[2] = signer.uri; signature[3] = signer.date; signature[4] = signer.serialNumber; X509Certificate2 signatureCertificate = signer.signerCertificate; if ((!nonconformitySigners.Contains(signatureCertificate)) && (!conformitySigners.Contains(signatureCertificate))) { if (!CertificateUtils.ValidateCertificate(signatureCertificate, checkCRL, false) ?? true) { nonconformitySigners.Add(signatureCertificate); } else { conformitySigners.Add(signatureCertificate); } certificatesList.Add(signatureCertificate, CertificateUtils.buildStatus); } X509ChainStatus chainStatus = new X509ChainStatus(); chainStatus = (X509ChainStatus)certificatesList[signatureCertificate]; ChainDocumentStatus chainDocumentStatus = new ChainDocumentStatus(); int signatureIcon; if (!(invalidSignatures.Contains(signature[0]) && invalidSignatures.Contains(signature[1]) && invalidSignatures.Contains(signature[2]) && invalidSignatures.Contains(signature[3]))) { chainDocumentStatus = new ChainDocumentStatus(chainStatus, null); if (nonconformitySigners.Contains(signatureCertificate)) { signatureIcon = 1; } else { signatureIcon = 2; } } else { signatureIcon = 0; chainDocumentStatus = new ChainDocumentStatus(chainStatus, ChainDocumentStatus.ChainDocumentStatusFlags.CorruptedDocument); } ListViewItem newSignerItem = new ListViewItem(); //INDEX newSignerItem.Text = signature[0].ToString(); //0 signer.name newSignerItem.ImageIndex = signatureIcon; newSignerItem.Group = sigaturesGroup; newSignerItem.SubItems.Add(signature[1]); //1 signer.issuer newSignerItem.SubItems.Add(signature[3]); //2 signer.date newSignerItem.SubItems.Add(filepath.NewPath); //3 signer.path newSignerItem.SubItems.Add(signature[4]); //4 signer.serialNumber newSignerItem.SubItems.Add(signature[2]); //5 signer.URI newSignerItem.SubItems.Add(filepath.OriginalPath); //6 signer.originalPath ListViewItem.ListViewSubItem chainSt = new ListViewItem.ListViewSubItem(); chainSt.Text = ""; chainSt.Tag = (object)chainDocumentStatus; newSignerItem.SubItems.Add(chainSt); //7 Tag chainStatus newSignerItem.Tag = (object)signatureCertificate; //Tag signer.signerCertificate lstSigners.Items.Add(newSignerItem); if (lstSigners.Groups.Count == 1) { Signer sgn = new Signer(); sgn.name = signature[0].ToString(); sgn.issuer = signature[1].ToString(); sgn.serialNumber = signature[4].ToString(); sgn.signerCertificate = signatureCertificate; if (!commonSigners.Contains(sgn)) { commonSigners.Add(sgn); } } } Signers commonRecentlyFoundSigners = new Signers(); foreach (ListViewItem lst in sigaturesGroup.Items) { foreach (Signer sgn in commonSigners) { if (lst.SubItems[0].Text == sgn.name && lst.SubItems[1].Text == sgn.issuer && lst.SubItems[4].Text == sgn.serialNumber && !commonRecentlyFoundSigners.Contains(sgn)) { commonRecentlyFoundSigners.Add(sgn); } } } commonSigners = commonRecentlyFoundSigners; } #region catch catch (IOException ioex) { if ( MessageBox.Show ( "Erro ao abrir o documento " + System.IO.Path.GetFileName(filepath.NewPath) + ".\nCertifique-se de que o documento não foi movido ou está em uso por outra aplicação." + "\n\nDeseja retirá-lo da lista?" + "\n\nInformações adicionais do erro: " + ioex.Message, System.IO.Path.GetFileName(filepath.NewPath), MessageBoxButtons.YesNo, MessageBoxIcon.Question ) == DialogResult.Yes ) { foreach (ListViewItem item in lstDocuments.Items) { if (item.SubItems[2].Text == filepath.NewPath) { problematicFoundDocuments.Add(item.SubItems[2].Text); lstDocuments.Items.Remove(item); } } } else { foreach (ListViewItem item in lstDocuments.Items) { if (item.SubItems[2].Text == filepath.NewPath) { problematicFoundDocuments.Add(item.SubItems[2].Text); item.Selected = false; if (lstDocuments.SelectedItems.Count > 0) { lstDocuments.FocusedItem = lstDocuments.SelectedItems[0]; } } } } } catch (FileFormatException ffex) { if ( MessageBox.Show ( "Erro ao abrir o documento " + System.IO.Path.GetFileName(filepath.NewPath) + ".\nSeu conteúdo está corrompido, talvez seja um arquivo temporário.\n\nDeseja retirá-lo da lista?" + "\n\nInformações adicionais do erro: " + ffex.Message, System.IO.Path.GetFileName(filepath.NewPath), MessageBoxButtons.YesNo, MessageBoxIcon.Question ) == DialogResult.Yes ) { foreach (ListViewItem item in lstDocuments.Items) { if (item.SubItems[2].Text == filepath.NewPath) { problematicFoundDocuments.Add(item.SubItems[2].Text); lstDocuments.Items.Remove(item); } } } else { foreach (ListViewItem item in lstDocuments.Items) { if (item.SubItems[2].Text == filepath.NewPath) { problematicFoundDocuments.Add(item.SubItems[2].Text); item.Selected = false; if (lstDocuments.SelectedItems.Count > 0) { lstDocuments.FocusedItem = lstDocuments.SelectedItems[0]; } } } } } catch (ArgumentNullException anex) { if ( MessageBox.Show ( "O Documento " + System.IO.Path.GetFileName(filepath.NewPath) + "não está disponível para abertura.\n\nDeseja retirá-lo da lista?" + "\n\nInformações adicionais do erro: " + anex.Message, System.IO.Path.GetFileName(filepath.NewPath), MessageBoxButtons.YesNo, MessageBoxIcon.Question ) == DialogResult.Yes ) { foreach (ListViewItem item in lstDocuments.Items) { if (item.SubItems[2].Text == filepath.NewPath) { problematicFoundDocuments.Add(item.SubItems[2].Text); lstDocuments.Items.Remove(item); } } } else { foreach (ListViewItem item in lstDocuments.Items) { if (item.SubItems[2].Text == filepath.NewPath) { problematicFoundDocuments.Add(item.SubItems[2].Text); item.Selected = false; if (lstDocuments.SelectedItems.Count > 0) { lstDocuments.FocusedItem = lstDocuments.SelectedItems[0]; } } } } } catch (OpenXmlPackageException oxpex) { if ( MessageBox.Show ( "O Documento " + System.IO.Path.GetFileName(filepath.NewPath) + " não é um pacote Open XML válido.\n\nDeseja retirá-lo da lista?" + "\n\nInformações adicionais do erro: " + oxpex.Message, System.IO.Path.GetFileName(filepath.NewPath), MessageBoxButtons.YesNo, MessageBoxIcon.Question ) == DialogResult.Yes ) { foreach (ListViewItem item in lstDocuments.Items) { if (item.SubItems[2].Text == filepath.NewPath) { problematicFoundDocuments.Add(item.SubItems[2].Text); lstDocuments.Items.Remove(item); } } } else { foreach (ListViewItem item in lstDocuments.Items) { if (item.SubItems[2].Text == filepath.NewPath) { problematicFoundDocuments.Add(item.SubItems[2].Text); item.Selected = false; if (lstDocuments.SelectedItems.Count > 0) { lstDocuments.FocusedItem = lstDocuments.SelectedItems[0]; } } } } } catch (Exception err) { if ( MessageBox.Show ( "Houve um problema na listagem do seguinte documento:\n " + System.IO.Path.GetFileName(filepath.NewPath) + "\n" + err.Message.Substring(0, err.Message.IndexOf(".") + 1) + "\n\nDeseja excluí-lo da lista?", System.IO.Path.GetFileName(filepath.NewPath), MessageBoxButtons.YesNo, MessageBoxIcon.Question ) == DialogResult.Yes ) { foreach (ListViewItem item in lstDocuments.Items) { if (item.SubItems[2].Text == filepath.NewPath) { problematicFoundDocuments.Add(item.SubItems[2].Text); lstDocuments.Items.Remove(item); } } } else { foreach (ListViewItem item in lstDocuments.Items) { if (item.SubItems[2].Text == filepath.NewPath) { problematicFoundDocuments.Add(item.SubItems[2].Text); item.Selected = false; if (lstDocuments.SelectedItems.Count > 0) { lstDocuments.FocusedItem = lstDocuments.SelectedItems[0]; } } } } } #endregion } if (lstDocuments.SelectedItems.Count > 1) { ListViewGroup commonSigaturesGroup = new ListViewGroup("commonSignatures", "Assinaturas em Comum"); lstSigners.Groups.Insert(0, commonSigaturesGroup); foreach (Signer sig in commonSigners) { ListViewItem newCommonSignerItem = new ListViewItem(); newCommonSignerItem.Text = sig.name; //0 signer.name newCommonSignerItem.Group = commonSigaturesGroup; newCommonSignerItem.SubItems.Add(sig.issuer); //1 signer.issuer newCommonSignerItem.SubItems.Add(""); //2 signer.date newCommonSignerItem.SubItems.Add(""); //3 signer.path newCommonSignerItem.SubItems.Add(sig.serialNumber); //4 signer.serialNumber newCommonSignerItem.SubItems.Add(""); //5 signer.URI newCommonSignerItem.SubItems.Add(""); //6 signer.originalPath newCommonSignerItem.Tag = (object)sig.signerCertificate; //Tag signer.signerCertificate lstSigners.Items.Add(newCommonSignerItem); } } selectedDocuments.Clear(); foreach (ListViewItem lvi in lstDocuments.SelectedItems) { FileHistory fh = new FileHistory(lvi.SubItems[3].Text, lvi.SubItems[2].Text); selectedDocuments.Add(fh); } } if (lstDocuments.SelectedItems.Count > 0) { loadFileDescription(); if (digitalSignature.DocumentType.Equals(Types.XpsDocument)) { digitalSignature.xpsDocument.Close(); } else if (digitalSignature.DocumentType.Equals(Types.PdfDocument)) { // nothing to-do here } else { digitalSignature.package.Close(); } } else if (lstDocuments.Items.Count == 0) { MessageBox.Show(Constants.NotValidFormat, "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error); this.Close(); } this.Cursor = Cursors.Arrow; return(true); }
public static IChainPal BuildChain( X509Certificate2 leaf, List <X509Certificate2> candidates, List <X509Certificate2> downloaded, List <X509Certificate2> systemTrusted, OidCollection applicationPolicy, OidCollection certificatePolicy, X509RevocationMode revocationMode, X509RevocationFlag revocationFlag, DateTime verificationTime, ref TimeSpan remainingDownloadTime) { X509ChainElement[] elements; List <X509ChainStatus> overallStatus = new List <X509ChainStatus>(); // An X509_STORE is more comparable to Cryptography.X509Certificate2Collection than to // Cryptography.X509Store. So read this with OpenSSL eyes, not CAPI/CNG eyes. // // (If you need to think of it as an X509Store, it's a volatile memory store) using (SafeX509StoreHandle store = Interop.libcrypto.X509_STORE_new()) using (SafeX509StoreCtxHandle storeCtx = Interop.libcrypto.X509_STORE_CTX_new()) { Interop.Crypto.CheckValidOpenSslHandle(store); Interop.Crypto.CheckValidOpenSslHandle(storeCtx); bool lookupCrl = revocationMode != X509RevocationMode.NoCheck; foreach (X509Certificate2 cert in candidates) { OpenSslX509CertificateReader pal = (OpenSslX509CertificateReader)cert.Pal; if (!Interop.libcrypto.X509_STORE_add_cert(store, pal.SafeHandle)) { throw Interop.Crypto.CreateOpenSslCryptographicException(); } if (lookupCrl) { CrlCache.AddCrlForCertificate( cert, store, revocationMode, verificationTime, ref remainingDownloadTime); // If we only wanted the end-entity certificate CRL then don't look up // any more of them. lookupCrl = revocationFlag != X509RevocationFlag.EndCertificateOnly; } } if (revocationMode != X509RevocationMode.NoCheck) { Interop.libcrypto.X509VerifyFlags vfyFlags = Interop.libcrypto.X509VerifyFlags.X509_V_FLAG_CRL_CHECK; if (revocationFlag != X509RevocationFlag.EndCertificateOnly) { vfyFlags |= Interop.libcrypto.X509VerifyFlags.X509_V_FLAG_CRL_CHECK_ALL; } if (!Interop.libcrypto.X509_STORE_set_flags(store, vfyFlags)) { throw Interop.Crypto.CreateOpenSslCryptographicException(); } } // When CRL checking support is added, it should be done before the call to // X509_STORE_CTX_init (aka here) by calling X509_STORE_set_flags(store, flags); SafeX509Handle leafHandle = ((OpenSslX509CertificateReader)leaf.Pal).SafeHandle; if (!Interop.libcrypto.X509_STORE_CTX_init(storeCtx, store, leafHandle, IntPtr.Zero)) { throw Interop.Crypto.CreateOpenSslCryptographicException(); } Interop.Crypto.SetX509ChainVerifyTime(storeCtx, verificationTime); int verify = Interop.libcrypto.X509_verify_cert(storeCtx); if (verify < 0) { throw Interop.Crypto.CreateOpenSslCryptographicException(); } using (SafeX509StackHandle chainStack = Interop.libcrypto.X509_STORE_CTX_get1_chain(storeCtx)) { int chainSize = Interop.Crypto.GetX509StackFieldCount(chainStack); int errorDepth = -1; Interop.libcrypto.X509VerifyStatusCode errorCode = 0; if (verify == 0) { errorCode = Interop.libcrypto.X509_STORE_CTX_get_error(storeCtx); errorDepth = Interop.libcrypto.X509_STORE_CTX_get_error_depth(storeCtx); } elements = new X509ChainElement[chainSize]; int maybeRootDepth = chainSize - 1; // The leaf cert is 0, up to (maybe) the root at chainSize - 1 for (int i = 0; i < chainSize; i++) { List <X509ChainStatus> status = new List <X509ChainStatus>(); if (i == errorDepth) { AddElementStatus(errorCode, status, overallStatus); } IntPtr elementCertPtr = Interop.Crypto.GetX509StackField(chainStack, i); if (elementCertPtr == IntPtr.Zero) { throw Interop.Crypto.CreateOpenSslCryptographicException(); } // Duplicate the certificate handle X509Certificate2 elementCert = new X509Certificate2(elementCertPtr); // If the last cert is self signed then it's the root cert, do any extra checks. if (i == maybeRootDepth && IsSelfSigned(elementCert)) { // If the root certificate was downloaded or the system // doesn't trust it, it's untrusted. if (downloaded.Contains(elementCert) || !systemTrusted.Contains(elementCert)) { AddElementStatus( Interop.libcrypto.X509VerifyStatusCode.X509_V_ERR_CERT_UNTRUSTED, status, overallStatus); } } elements[i] = new X509ChainElement(elementCert, status.ToArray(), ""); } } } if ((certificatePolicy != null && certificatePolicy.Count > 0) || (applicationPolicy != null && applicationPolicy.Count > 0)) { List <X509Certificate2> certsToRead = new List <X509Certificate2>(); foreach (X509ChainElement element in elements) { certsToRead.Add(element.Certificate); } CertificatePolicyChain policyChain = new CertificatePolicyChain(certsToRead); bool failsPolicyChecks = false; if (certificatePolicy != null) { if (!policyChain.MatchesCertificatePolicies(certificatePolicy)) { failsPolicyChecks = true; } } if (applicationPolicy != null) { if (!policyChain.MatchesApplicationPolicies(applicationPolicy)) { failsPolicyChecks = true; } } if (failsPolicyChecks) { X509ChainElement leafElement = elements[0]; X509ChainStatus chainStatus = new X509ChainStatus { Status = X509ChainStatusFlags.InvalidPolicyConstraints, StatusInformation = SR.Chain_NoPolicyMatch, }; var elementStatus = new List <X509ChainStatus>(leafElement.ChainElementStatus.Length + 1); elementStatus.AddRange(leafElement.ChainElementStatus); AddUniqueStatus(elementStatus, ref chainStatus); AddUniqueStatus(overallStatus, ref chainStatus); elements[0] = new X509ChainElement( leafElement.Certificate, elementStatus.ToArray(), leafElement.Information); } } return(new OpenSslX509ChainProcessor { ChainStatus = overallStatus.ToArray(), ChainElements = elements, }); }
public X509ChainStatus2(X509ChainStatus nativeStatus) { Status = (X509ChainStatusFlags2)nativeStatus.Status; StatusInformation = nativeStatus.StatusInformation; }