You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: certificates.go
    path of file: ./repos/moby/vendor/github.com/moby/swarmkit/v2/ca
    
    the code of the file until where you have to start completion: package ca

import (
	"bytes"
	"context"
	"crypto"
	"crypto/ecdsa"
	"crypto/elliptic"
	cryptorand "crypto/rand"
	"crypto/rsa"
	"crypto/tls"
	"crypto/x509"
	"encoding/asn1"
	"encoding/pem"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"time"

	cfcsr "github.com/cloudflare/cfssl/csr"
	"github.com/cloudflare/cfssl/helpers"
	"github.com/cloudflare/cfssl/initca"
	cflog "github.com/cloudflare/cfssl/log"
	cfsigner "github.com/cloudflare/cfssl/signer"
	"github.com/cloudflare/cfssl/signer/local"
	"github.com/docker/go-events"
	"github.com/moby/swarmkit/v2/api"
	"github.com/moby/swarmkit/v2/ca/pkcs8"
	"github.com/moby/swarmkit/v2/connectionbroker"
	"github.com/moby/swarmkit/v2/ioutils"
	"github.com/opencontainers/go-digest"
	"github.com/pkg/errors"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/status"
)

const (
	// Security Strength Equivalence
	//
	// | ECC      | DH/DSA/RSA    |
	// |----------|---------------|
	// | 256      | 3072          |
	// | 384      | 7680          |

	// RootKeySize is the default size of the root CA key
	// It would be ideal for the root key to use P-384, but in P-384 is not optimized in go yet :(
	RootKeySize = 256
	// RootKeyAlgo defines the default algorithm for the root CA Key
	RootKeyAlgo = "ecdsa"
	// RootCAExpiration represents the default expiration for the root CA in seconds (20 years)
	RootCAExpiration = "630720000s"
	// DefaultNodeCertExpiration represents the default expiration for node certificates (3 months)
	DefaultNodeCertExpiration = 2160 * time.Hour
	// CertBackdate represents the amount of time each certificate is backdated to try to avoid
	// clock drift issues.
	CertBackdate = 1 * time.Hour
	// CertLowerRotationRange represents the minimum fraction of time that we will wait when randomly
	// choosing our next certificate rotation
    
func ValidateCertChain(rootPool *x509.CertPool, certs []byte, allowExpired bool) ([]*x509.Certificate, [][]*x509.Certificate, error) {
	// Parse all the certificates in the cert bundle
	parsedCerts, err := helpers.ParseCertificatesPEM(certs)
	if err != nil {
		return nil, nil, err
	}
	if len(parsedCerts) == 0 {
		return nil, nil, errors.New("no certificates to validate")
	}
	now := time.Now()
	// ensure that they form a chain, each one being signed by the one after it
	var intermediatePool *x509.CertPool
	for i, cert := range parsedCerts {
		// Manual expiry validation because we want more information on which certificate in the chain is expired, and
		// because this is an easier way to allow expired certs.
		if now.Before(cert.NotBefore) {
			return nil, nil, errors.Wrapf(
				x509.CertificateInvalidError{
					Cert:   cert,
					Reason: x509.Expired,
				},
				"certificate (%d - %s) not valid before %s, and it is currently %s",
				i+1, cert.Subject.CommonName, cert.NotBefore.UTC().Format(time.RFC1123), now.Format(time.RFC1123))
		}
		if !allowExpired && now.After(cert.NotAfter) {
			return nil, nil, errors.Wrapf(
				x509.CertificateInvalidError{
					Cert:   cert,
					Reason: x509.Expired,
				},
				"certificate (%d - %s) not valid after %s, and it is currently %s",
				i+1, cert.Subject.CommonName, cert.NotAfter.UTC().Format(time.RFC1123), now.Format(time.RFC1123))
		}

		if i > 0 {
			// check that the previous cert was signed by this cert
			prevCert := parsedCerts[i-1]
			if err := prevCert.CheckSignatureFrom(cert); err != nil {
				return nil, nil, errors.Wrapf(err, "certificates do not form a chain: (%d - %s) is not signed by (%d - %s)",
					i, prevCert.Subject.CommonName, i+1, cert.Subject.CommonName)
			}

			if intermediatePool == nil {
				intermediatePool = x509.NewCertPool()
			}
			intermediatePool.AddCert(cert)

		}
	}

	verifyOpts := x509.VerifyOptions{
		Roots:         rootPool,
		Intermediates: intermediatePool,
		CurrentTime:   now,
	}

	var chains [][]*x509.Certificate

	// If we accept expired certs, try to build a valid cert chain using some subset of the certs.  We start off using the
	// first certificate's NotAfter as the current time, thus ensuring that the first cert is not expired. If the chain
	// still fails to validate due to expiry issues, continue iterating over the rest of the certs.
	// If any of the other certs has an earlier NotAfter time, use that time as the current time instead. This insures that
	// particular cert, and any that came before it, are not expired.  Note that the root that the certs chain up to
	// should also not be expired at that "current" time.
	if allowExpired {
		verifyOpts.CurrentTime = parsedCerts[0].NotAfter.Add(time.Hour)
		for _, cert := range parsedCerts {
			if !cert.NotAfter.Before(verifyOpts.CurrentTime) {
				continue
			}
			verifyOpts.CurrentTime = cert.NotAfter

			chains, err = parsedCerts[0].Verify(verifyOpts)
			if err == nil {
				return parsedCerts, chains, nil
			}
		}
		if invalid, ok := err.(x509.CertificateInvalidError); ok && invalid.Reason == x509.Expired {
			return nil, nil, errors.New("there is no time span for which all of the certificates, including a root, are valid")
		}
		return nil, nil, err
	}

	chains, err = parsedCerts[0].Verify(verifyOpts)
	if err != nil {
		return nil, nil, err
	}
	return parsedCerts, chains, nil
}