1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
|
// Copyright The Notary Project Authors.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package ocsp provides methods for checking the OCSP revocation status of a
// certificate chain, as well as errors related to these checks
package ocsp
import (
"context"
"crypto/x509"
"errors"
"net/http"
"sync"
"time"
"github.com/notaryproject/notation-core-go/revocation/internal/ocsp"
"github.com/notaryproject/notation-core-go/revocation/internal/x509util"
"github.com/notaryproject/notation-core-go/revocation/purpose"
"github.com/notaryproject/notation-core-go/revocation/result"
)
// Options specifies values that are needed to check OCSP revocation
type Options struct {
CertChain []*x509.Certificate
// CertChainPurpose is the purpose of the certificate chain. Supported
// values are CodeSigning and Timestamping.
// When not provided, the default value is CodeSigning.
CertChainPurpose purpose.Purpose
SigningTime time.Time
HTTPClient *http.Client
}
// CheckStatus checks OCSP based on the passed options and returns an array of
// result.CertRevocationResult objects that contains the results and error. The
// length of this array will always be equal to the length of the certificate
// chain.
func CheckStatus(opts Options) ([]*result.CertRevocationResult, error) {
if len(opts.CertChain) == 0 {
return nil, result.InvalidChainError{Err: errors.New("chain does not contain any certificates")}
}
if err := x509util.ValidateChain(opts.CertChain, opts.CertChainPurpose); err != nil {
return nil, err
}
certResults := make([]*result.CertRevocationResult, len(opts.CertChain))
certCheckStatusOptions := ocsp.CertCheckStatusOptions{
SigningTime: opts.SigningTime,
HTTPClient: opts.HTTPClient,
}
// Check status for each cert in cert chain
var wg sync.WaitGroup
ctx := context.Background()
for i, cert := range opts.CertChain[:len(opts.CertChain)-1] {
wg.Add(1)
// Assume cert chain is accurate and next cert in chain is the issuer
go func(i int, cert *x509.Certificate) {
defer wg.Done()
certResults[i] = ocsp.CertCheckStatus(ctx, cert, opts.CertChain[i+1], certCheckStatusOptions)
}(i, cert)
}
// Last is root cert, which will never be revoked by OCSP
certResults[len(opts.CertChain)-1] = &result.CertRevocationResult{
Result: result.ResultNonRevokable,
ServerResults: []*result.ServerResult{{
Result: result.ResultNonRevokable,
Error: nil,
}},
}
wg.Wait()
return certResults, nil
}
|