Пример #1
0
 private static unsafe partial int CryptoNative_X509DecodeOcspToExpiration(
     byte *buf,
     int len,
     SafeOcspRequestHandle req,
     IntPtr subject,
     IntPtr issuer,
     ref long expiration);
Пример #2
0
        internal static SafeOcspRequestHandle X509ChainBuildOcspRequest(SafeX509StoreCtxHandle storeCtx, int chainDepth)
        {
            SafeOcspRequestHandle req = CryptoNative_X509ChainBuildOcspRequest(storeCtx, chainDepth);

            if (req.IsInvalid)
            {
                req.Dispose();
                throw CreateOpenSslCryptographicException();
            }

            return(req);
        }
Пример #3
0
        internal static X509VerifyStatusCode X509ChainVerifyOcsp(
            SafeX509StoreCtxHandle ctx,
            SafeOcspRequestHandle req,
            SafeOcspResponseHandle resp,
            string cachePath)
        {
            X509VerifyStatusCode response = CryptoNative_X509ChainVerifyOcsp(ctx, req, resp, cachePath);

            if (response < 0)
            {
                Debug.Fail($"Unexpected response from X509ChainGetCachedOcspSuccess: {response}");
                throw new CryptographicException();
            }

            return(response);
        }
Пример #4
0
        internal static unsafe bool X509DecodeOcspToExpiration(
            ReadOnlySpan <byte> buf,
            SafeOcspRequestHandle request,
            IntPtr x509Subject,
            IntPtr x509Issuer,
            out DateTimeOffset expiration)
        {
            long timeT = 0;
            int  ret;

            fixed(byte *pBuf = buf)
            {
                ret = CryptoNative_X509DecodeOcspToExpiration(
                    pBuf,
                    buf.Length,
                    request,
                    x509Subject,
                    x509Issuer,
                    ref timeT);
            }

            if (ret == 1)
            {
                if (timeT != 0)
                {
                    expiration = DateTimeOffset.FromUnixTimeSeconds(timeT);
                }
                else
                {
                    // Something went wrong during the determination of when the response
                    // should not be used any longer.
                    // Half an hour sounds fair?
                    expiration = DateTimeOffset.UtcNow.AddMinutes(30);
                }

                return(true);
            }

            Debug.Assert(ret == 0, $"Unexpected response from X509DecodeOcspToExpiration: {ret}");
            expiration = DateTimeOffset.MinValue;
            return(false);
        }
Пример #5
0
 private static partial int CryptoNative_X509ChainVerifyOcsp(
     SafeX509StoreCtxHandle ctx,
     SafeOcspRequestHandle req,
     SafeOcspResponseHandle resp,
     string cachePath,
     int chainDepth);
Пример #6
0
 internal static partial int EncodeOcspRequest(SafeOcspRequestHandle req, byte[] buf);
Пример #7
0
 internal static partial int GetOcspRequestDerSize(SafeOcspRequestHandle req);
Пример #8
0
 private static extern X509VerifyStatusCode CryptoNative_X509ChainVerifyOcsp(
     SafeX509StoreCtxHandle ctx,
     SafeOcspRequestHandle req,
     SafeOcspResponseHandle resp,
     string cachePath,
     int chainDepth);
Пример #9
0
 internal static extern int EncodeOcspRequest(SafeOcspRequestHandle req, byte[] buf);
Пример #10
0
 internal static extern int GetOcspRequestDerSize(SafeOcspRequestHandle req);
Пример #11
0
        private async Task <byte[]?> FetchOcspAsync()
        {
            X509Certificate2?caCert = _ca;

            Debug.Assert(_ocspUrls is not null);
            Debug.Assert(_ocspUrls.Count > 0);
            Debug.Assert(caCert is not null);

            IntPtr subject = Certificate.Handle;
            IntPtr issuer  = caCert.Handle;

            using (SafeOcspRequestHandle ocspRequest = Interop.Crypto.X509BuildOcspRequest(subject, issuer))
            {
                byte[] rentedBytes = ArrayPool <byte> .Shared.Rent(Interop.Crypto.GetOcspRequestDerSize(ocspRequest));

                int encodingSize            = Interop.Crypto.EncodeOcspRequest(ocspRequest, rentedBytes);
                ArraySegment <byte> encoded = new ArraySegment <byte>(rentedBytes, 0, encodingSize);

                ArraySegment <char> rentedChars = UrlBase64Encoding.RentEncode(encoded);
                byte[]? ret = null;

                for (int i = 0; i < _ocspUrls.Count; i++)
                {
                    string url = MakeUrl(_ocspUrls[i], rentedChars);
                    ret = await System.Net.Http.X509ResourceClient.DownloadAssetAsync(url, TimeSpan.MaxValue).ConfigureAwait(false);

                    if (ret is not null)
                    {
                        if (!Interop.Crypto.X509DecodeOcspToExpiration(ret, ocspRequest, subject, issuer, out DateTimeOffset expiration))
                        {
                            continue;
                        }

                        // Swap the working URL in as the first one we'll try next time.
                        if (i != 0)
                        {
                            string tmp = _ocspUrls[0];
                            _ocspUrls[0] = _ocspUrls[i];
                            _ocspUrls[i] = tmp;
                        }

                        DateTimeOffset nextCheckA = DateTimeOffset.UtcNow.AddDays(1);
                        DateTimeOffset nextCheckB = expiration.AddMinutes(-5);

                        _ocspResponse    = ret;
                        _ocspExpiration  = expiration;
                        _nextDownload    = nextCheckA < nextCheckB ? nextCheckA : nextCheckB;
                        _pendingDownload = null;
                        break;
                    }
                }

                ArrayPool <byte> .Shared.Return(rentedBytes);

                ArrayPool <char> .Shared.Return(rentedChars.Array !);

                GC.KeepAlive(Certificate);
                GC.KeepAlive(caCert);
                return(ret);
            }
        }