Beispiel #1
0
func NewS3Session(auth *aws.Auth, region aws.Region) *s3.S3 {
	var s3Session *s3.S3
	cert := x509.Certificate{}
	// go's systemVerify panics with no verify options set
	// TODO: EVG-483
	if runtime.GOOS == "windows" {
		s3Session = s3.New(*auth, region)
		s3Session.ReadTimeout = S3ReadTimeout
		s3Session.WriteTimeout = S3WriteTimeout
		s3Session.ConnectTimeout = S3ConnectTimeout
		return s3Session
	}
	// no verify options so system root ca will be used
	_, err := cert.Verify(x509.VerifyOptions{})
	rootsError := x509.SystemRootsError{}
	if err != nil && err.Error() == rootsError.Error() {
		// create a Transport which includes our TLSConfig with InsecureSkipVerify
		// and client timeouts.
		tlsConfig := tls.Config{InsecureSkipVerify: true}
		tr := http.Transport{
			TLSClientConfig: &tlsConfig}
		// add the Transport to our http client
		client := &http.Client{Transport: &tr}
		s3Session = s3.New(*auth, region, client)
	} else {
		s3Session = s3.New(*auth, region)
	}
	s3Session.ReadTimeout = S3ReadTimeout
	s3Session.WriteTimeout = S3WriteTimeout
	s3Session.ConnectTimeout = S3ConnectTimeout
	return s3Session
}
Beispiel #2
0
func Verify(options x509.VerifyOptions, cert *x509.Certificate) Result {
	result := Result{Certificate: cert}
	chains, err := cert.Verify(options)
	result.Error = err
	for _, chain := range chains {
		result.Chains = append(result.Chains, CommonNamesFromChain(chain))
	}

	return result
}
func (CertificateValidator) validateCertAndChain(certificate *x509.Certificate, certPool *x509.CertPool) error {
	opts := x509.VerifyOptions{
		Roots: certPool,
	}

	if _, err := certificate.Verify(opts); err != nil {
		return fmt.Errorf("certificate and chain mismatch: %s", err.Error())
	}

	return nil
}
Beispiel #4
0
// Verify operates on an X509Store and validates the existence of a chain of trust
// between a leafCertificate and a CA present inside of the X509 Store.
// It requires at least two certificates in certList, a leaf Certificate and an
// intermediate CA certificate.
func Verify(s X509Store, dnsName string, certList []*x509.Certificate) error {
	// If we have no Certificates loaded return error (we don't want to revert to using
	// system CAs).
	if len(s.GetCertificates()) == 0 {
		return errors.New("no root CAs available")
	}

	// At a minimum we should be provided a leaf cert and an intermediate.
	if len(certList) < 2 {
		return errors.New("certificate and at least one intermediate needed")
	}

	// Get the VerifyOptions from the keystore for a base dnsName
	opts, err := s.GetVerifyOptions(dnsName)
	if err != nil {
		return err
	}

	// Create a Certificate Pool for our intermediate certificates
	intPool := x509.NewCertPool()
	var leafCert *x509.Certificate

	// Iterate through all the certificates
	for _, c := range certList {
		// If the cert is a CA, we add it to the intermediates pool. If not, we call
		// it the leaf cert
		if c.IsCA {
			intPool.AddCert(c)
			continue
		}
		// Certificate is not a CA, it must be our leaf certificate.
		// If we already found one, bail with error
		if leafCert != nil {
			return errors.New("more than one leaf certificate found")
		}
		leafCert = c
	}

	// We exited the loop with no leaf certificates
	if leafCert == nil {
		return errors.New("no leaf certificates found")
	}

	// We have one leaf certificate and at least one intermediate. Lets add this
	// Cert Pool as the Intermediates list on our VerifyOptions
	opts.Intermediates = intPool

	// Finally, let's call Verify on our leafCert with our fully configured options
	chains, err := leafCert.Verify(opts)
	if len(chains) == 0 || err != nil {
		return fmt.Errorf("certificate verification failed: %v", err)
	}
	return nil
}
Beispiel #5
0
func verifyX509Cert(cert *x509.Certificate, dnsName string, roots *x509.CertPool) error {
	verifyOptions := x509.VerifyOptions{
		DNSName: dnsName,
		Roots:   roots,
		KeyUsages: []x509.ExtKeyUsage{
			x509.ExtKeyUsageServerAuth,
			x509.ExtKeyUsageClientAuth,
		},
	}
	_, err := cert.Verify(verifyOptions)
	return err
}
Beispiel #6
0
func (t trustPinChecker) caCheck(leafCert *x509.Certificate, intCerts []*x509.Certificate) bool {
	// Use intermediate certificates included in the root TUF metadata for our validation
	caIntPool := x509.NewCertPool()
	for _, intCert := range intCerts {
		caIntPool.AddCert(intCert)
	}
	// Attempt to find a valid certificate chain from the leaf cert to CA root
	// Use this certificate if such a valid chain exists (possibly using intermediates)
	if _, err := leafCert.Verify(x509.VerifyOptions{Roots: t.pinnedCAPool, Intermediates: caIntPool}); err == nil {
		return true
	}
	return false
}
Beispiel #7
0
func checkCertificate(probeURL *url.URL) (probeResult, *x509.Certificate) {
	req, _ := http.NewRequest("HEAD", probeURL.String(), nil)
	req.Header.Set("User-Agent", fmt.Sprintf("Mozilla/5.0 (compatible; PromCertcheck/%s; +https://github.com/Luzifer/promcertcheck)", version))

	resp, err := http.DefaultClient.Do(req)
	switch err.(type) {
	case nil, redirectFoundError:
	default:
		if !strings.Contains(err.Error(), "Found a redirect.") {
			return generalFailure, nil
		}
	}
	resp.Body.Close()

	intermediatePool := x509.NewCertPool()
	var verifyCert *x509.Certificate

	hostPort := strings.Split(probeURL.Host, ":")
	host := hostPort[0]

	for _, cert := range resp.TLS.PeerCertificates {
		wildHost := "*" + host[strings.Index(host, "."):]
		if !inSlice(cert.DNSNames, host) && !inSlice(cert.DNSNames, wildHost) {
			intermediatePool.AddCert(cert)
			continue
		}

		verifyCert = cert
	}

	if verifyCert == nil {
		return certificateNotFound, nil
	}

	verificationResult := false
	if _, err := verifyCert.Verify(x509.VerifyOptions{
		Intermediates: intermediatePool,
	}); err == nil {
		verificationResult = true
	}

	if !verificationResult {
		return certificateInvalid, verifyCert
	}

	if verifyCert.NotAfter.Sub(time.Now()) < config.expireWarning {
		return certificateExpiresSoon, verifyCert
	}

	return certificateOK, verifyCert
}
Beispiel #8
0
// Normally we can just call cert.Verify(opts), but since we actually want more information about
// whether a certificate is not yet valid or expired, we also need to perform the expiry checks ourselves.
func verifyCertificate(cert *x509.Certificate, opts x509.VerifyOptions, allowExpired bool) error {
	_, err := cert.Verify(opts)
	if invalidErr, ok := err.(x509.CertificateInvalidError); ok && invalidErr.Reason == x509.Expired {
		now := time.Now().UTC()
		if now.Before(cert.NotBefore) {
			return errors.Wrapf(err, "certificate not valid before %s, and it is currently %s",
				cert.NotBefore.UTC().Format(time.RFC1123), now.Format(time.RFC1123))
		}
		if allowExpired {
			return nil
		}
		return errors.Wrapf(err, "certificate expires at %s, and it is currently %s",
			cert.NotAfter.UTC().Format(time.RFC1123), now.Format(time.RFC1123))
	}
	return err
}
Beispiel #9
0
func verify(t *testing.T, cert *x509.Certificate, opts x509.VerifyOptions, success bool, chainLength int) {
	validChains, err := cert.Verify(opts)
	if success {
		if err != nil {
			t.Fatalf("Unexpected error: %#v", err)
		}
		if len(validChains) != 1 {
			t.Fatalf("Expected a valid chain")
		}
		if len(validChains[0]) != chainLength {
			t.Fatalf("Expected a valid chain of length %d, got %d", chainLength, len(validChains[0]))
		}
	} else if err == nil && len(validChains) > 0 {
		t.Fatalf("Expected failure, got success")
	}
}
Beispiel #10
0
func verifyCertificate(cert *x509.Certificate, rootCerts []*x509.Certificate) bool {
	roots := x509.NewCertPool()
	for _, root := range rootCerts {
		roots.AddCert(root)
	}

	opts := x509.VerifyOptions{
		Roots: roots,
	}

	if _, err := cert.Verify(opts); err != nil {
		fmt.Printf("failed to verify certificate: %s\n", err)
		return false
	}
	fmt.Println("succeeded to verify certificate")
	return true
}
Beispiel #11
0
// Checks the following:
// (1) cert is valid according to one of the rootCerts.
// (2) the subject key of cert corresponds to kPrin.
// (3) the subject CommonName of cert is allowed by guard.
func validateEndorsementCertificate(cert *x509.Certificate, guard tao.Guard,
	kPrin *auth.Prin, rootCerts *x509.CertPool) error {
	verifyOptions := x509.VerifyOptions{Roots: rootCerts}
	_, err := cert.Verify(verifyOptions)
	if err != nil {
		return err
	}
	var hwPublicKey *rsa.PublicKey
	hwPublicKey, ok := cert.PublicKey.(*rsa.PublicKey)
	if !ok {
		key, ok := cert.PublicKey.(rsa.PublicKey)
		if !ok {
			return errors.New("endorsement cert does not contain a valid RSA public key")
		}
		hwPublicKey = &key
	}
	ek, err := x509.MarshalPKIXPublicKey(hwPublicKey)
	if err != nil {
		return err
	}
	hashedCertKey := sha256.Sum256(ek)
	if kPrin.Type != "tpm" && kPrin.Type != "tpm2" {
		return errors.New("key principal to be endorsed is not a TPM key, but it's expected to be")
	}
	hashedBytes, ok := kPrin.KeyHash.(auth.Bytes)
	if !ok {
		return errors.New("key principal to be endorsed does not have bytes as its auth.Term")
	}
	if !bytes.Equal(hashedBytes, hashedCertKey[:]) {
		return errors.New(fmt.Sprintf(
			"endorsement cert endorses %v but needs to endorse %v", hashedCertKey, hashedBytes))
	}
	machinePrin := auth.Prin{
		Type:    "MachineInfo",
		KeyHash: auth.Str(cert.Subject.CommonName),
	}
	if !guard.IsAuthorized(machinePrin, "Root", []string{}) {
		return errors.New(
			"machine endorsed by certificate is not authorized by policy")
	}
	return nil
}
Beispiel #12
0
// verify checks if a certificate has expired
func verify(cert *x509.Certificate) error {
	_, err := cert.Verify(x509.VerifyOptions{})
	if err == nil {
		return nil
	}

	switch e := err.(type) {
	case x509.CertificateInvalidError:
		switch e.Reason {
		case x509.Expired:
			return ErrExpired
		default:
			return err
		}
	case x509.UnknownAuthorityError:
		// Apple cert isn't in the cert pool
		// ignoring this error
		return nil
	default:
		return err
	}
}
Beispiel #13
0
// given a set of IP addresses this will determine what address, if any, can be used to
// connect to the host certificate
// if none can be found, will return empty string and an err
func addrToUse(candidateIPs []net.IP, cert *x509.Certificate, cas []byte) (string, error) {
	if cert == nil {
		return "", errors.New("unable to determine suitable address with nil certificate")
	}

	log.Debug("Loading CAs for client auth")
	pool := x509.NewCertPool()
	pool.AppendCertsFromPEM(cas)

	// update target to use FQDN
	for _, ip := range candidateIPs {
		names, err := net.LookupAddr(ip.String())
		if err != nil {
			log.Debugf("Unable to perform reverse lookup of IP address: %s", err)
		}

		// check all the returned names, and lastly the raw IP
		for _, n := range append(names, ip.String()) {
			opts := x509.VerifyOptions{
				Roots:   pool,
				DNSName: n,
			}

			_, err := cert.Verify(opts)
			if err == nil {
				// this identifier will work
				log.Debugf("Matched %s for use against host certificate", n)
				// trim '.' fqdn suffix if fqdn
				return strings.TrimSuffix(n, "."), nil
			}

			log.Debugf("Checked %s, no match for host cert", n)
		}
	}

	// no viable address
	return "", errors.New("unable to determine viable address")
}
Beispiel #14
0
func main() {
	interPEMPtr := flag.String("inter", "", "a PEM file containing intermediates")
	rootPEMPtr := flag.String("roots", "", "a PEM file containing roots")
	crlPtr := flag.String("crl", "", "a CRL file")

	flag.Parse()

	var rootPool, intermediatePool *x509.CertPool
	var roots, intermediates []*x509.Certificate

	if nil != rootPEMPtr && len(*rootPEMPtr) > 0 {
		rootPool, roots = loadCertPool(*rootPEMPtr)
	}
	if nil != interPEMPtr && len(*interPEMPtr) > 0 {
		intermediatePool, intermediates = loadCertPool(*interPEMPtr)
	}

	var crlData []byte
	if nil != crlPtr && len(*crlPtr) > 0 {
		// Get the crl from the args
		var err error
		crlData, err = ioutil.ReadFile(*crlPtr)
		check(err)
	}

	if len(crlData) > 0 {
		// Maybe it's PEM; try to parse as PEM, if that fails, just use the bytes
		block, _ := pem.Decode(crlData)
		if block != nil {
			crlData = block.Bytes
		}

		crl, err := x509.ParseCRL(crlData)
		if err != nil {
			panic("could not parse CRL")
		}

		// check the CRL is still current
		if crl.HasExpired(time.Now()) {
			fmt.Printf("crl has expired\n")
		}

		var signer *x509.Certificate
		if nil != roots {
			signer = findSigningCert(roots, crl)
			if nil == signer {
				fmt.Printf("Not signed by a root; trying known intermediates\n")
				if nil != intermediates {
					signer = findSigningCert(intermediates, crl)
				}
			}
		}

		if nil != signer {
			fmt.Printf("found signer! %v\n", signer.Subject)
			opts := x509.VerifyOptions{
				Roots:         rootPool,
				Intermediates: intermediatePool,
			}

			if _, err := signer.Verify(opts); err != nil {
				fmt.Println("Warning! Can't verify signer!")
			}
		}

		issuerData, err := asn1.Marshal(crl.TBSCertList.Issuer)
		if nil == err {
			issuerString := base64.StdEncoding.EncodeToString(issuerData)
			fmt.Printf("%v\n", issuerString)
		}
		for revoked := range crl.TBSCertList.RevokedCertificates {
			cert := crl.TBSCertList.RevokedCertificates[revoked]
			fmt.Printf(" %v\n",
				base64.StdEncoding.EncodeToString(cert.SerialNumber.Bytes()))
		}
	}
}
Beispiel #15
0
//isChainValid creates the valid certificate chains by combining the chain retrieved with the provided truststore.
//It return true if it finds at least on validation chain or false if no valid chain of trust can be created.
//It also updates the certificate map which gets pushed at the end of each iteration.
func isChainValid(endEntity *x509.Certificate, intermediates []*x509.Certificate, truststore *certificate.TrustStore, domain, IP string, certmap map[string]certificate.Certificate) bool {
	valInfo := &certificate.ValidationInfo{
		IsValid: true,
	}

	// build a CA verification pool from the list of cacerts
	interPool := x509.NewCertPool()
	for _, entity := range intermediates {
		interPool.AddCert(entity)
	}

	// get a list of domains this certificate is supposedly valid for
	// if the end entity is a CA, use its common name
	dnsName := domain
	if endEntity.IsCA {
		dnsName = endEntity.Subject.CommonName
	}

	// configure the verification logic to use the current trustore
	opts := x509.VerifyOptions{
		DNSName:       dnsName,
		Intermediates: interPool,
		Roots:         truststore.Certs,
	}

	// Verify attempts to build all the path between the end entity and the
	// root in the truststore that validate the certificate
	// If no valid path is found, err is not nil and the certificate is not trusted
	chains, err := endEntity.Verify(opts)

	if err == nil {
		// the end entity is trusted, we need to go through each
		// chain of trust and store them in database
		for i, chain := range chains {
			log.WithFields(logrus.Fields{
				"trust chain no": i,
				"path len":       len(chain),
			}).Debug("domain: " + domain)
			// loop through each certificate in the chain and
			for _, cert := range chain {
				parentSignature := ""
				parentCert := getFirstParent(cert, chain)
				if parentCert != nil {
					parentSignature = certificate.SHA256Hash(parentCert.Raw)
				} else {
					log.Println("could not retrieve parent for " + dnsName)
				}
				updateCert(cert, parentSignature, domain, IP, truststore.Name, valInfo, certmap)
			}
		}
		return true
	}

	// the certificate is not trusted.
	// we store the cert in DB with its validation error
	if len(chains) > 0 {
		log.WithFields(logrus.Fields{
			"domain": domain,
		}).Warning("Got validation error but chains are populated")
	}

	valInfo.ValidationError = err.Error()
	valInfo.IsValid = false

	parentSignature := ""
	c := getFirstParent(endEntity, intermediates)

	if c != nil {
		parentSignature = certificate.SHA256Hash(c.Raw)
	} else {
		log.WithFields(logrus.Fields{
			"domain":     domain,
			"servercert": certificate.SHA256Hash(endEntity.Raw),
		}).Info("Could not get parent")
	}

	updateCert(endEntity, parentSignature, domain, IP, truststore.Name, valInfo, certmap)

	return false

}
Beispiel #16
0
func (conf *config) validCert(cert *x509.Certificate, intermediates []*x509.Certificate) bool {
	pool := certPoolWith(intermediates)
	_, err := cert.Verify(x509.VerifyOptions{Intermediates: pool})
	if err == nil {
		return true
	}
	if _, ok := err.(x509.UnknownAuthorityError); !ok {
		// There was an error, but not because the certificate wasn't signed
		// by a recognized CA. So we go ahead and use the cert and let
		// the client experience the same error.
		return true
	}

	if conf.ExtraRootCerts != nil {
		_, err = cert.Verify(x509.VerifyOptions{Roots: conf.ExtraRootCerts, Intermediates: pool})
		if err == nil {
			return true
		}
		if _, ok := err.(x509.UnknownAuthorityError); !ok {
			return true
		}
	}

	// Before we give up, we'll try fetching some intermediate certificates.
	if len(cert.IssuingCertificateURL) == 0 {
		return false
	}

	toFetch := cert.IssuingCertificateURL
	fetched := make(map[string]bool)

	for i := 0; i < len(toFetch); i++ {
		certURL := toFetch[i]
		if fetched[certURL] {
			continue
		}
		resp, err := http.Get(certURL)
		if err == nil {
			defer resp.Body.Close()
		}
		if err != nil || resp.StatusCode != 200 {
			continue
		}
		fetchedCert, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			continue
		}

		// The fetched certificate might be in either DER or PEM format.
		if bytes.Contains(fetchedCert, []byte("-----BEGIN CERTIFICATE-----")) {
			// It's PEM.
			var certDER *pem.Block
			for {
				certDER, fetchedCert = pem.Decode(fetchedCert)
				if certDER == nil {
					break
				}
				if certDER.Type != "CERTIFICATE" {
					continue
				}
				thisCert, err := x509.ParseCertificate(certDER.Bytes)
				if err != nil {
					continue
				}
				pool.AddCert(thisCert)
				toFetch = append(toFetch, thisCert.IssuingCertificateURL...)
			}
		} else {
			// Hopefully it's DER.
			thisCert, err := x509.ParseCertificate(fetchedCert)
			if err != nil {
				continue
			}
			pool.AddCert(thisCert)
			toFetch = append(toFetch, thisCert.IssuingCertificateURL...)
		}
	}

	_, err = cert.Verify(x509.VerifyOptions{Intermediates: pool})
	if err == nil {
		return true
	}
	if _, ok := err.(x509.UnknownAuthorityError); !ok {
		// There was an error, but not because the certificate wasn't signed
		// by a recognized CA. So we go ahead and use the cert and let
		// the client experience the same error.
		return true
	}
	return false
}
Beispiel #17
0
func (hs *clientHandshakeState) doFullHandshake() error {
	c := hs.c

	var leaf *x509.Certificate
	if hs.suite.flags&suitePSK == 0 {
		msg, err := c.readHandshake()
		if err != nil {
			return err
		}

		certMsg, ok := msg.(*certificateMsg)
		if !ok || len(certMsg.certificates) == 0 {
			c.sendAlert(alertUnexpectedMessage)
			return unexpectedMessageError(certMsg, msg)
		}
		hs.writeServerHash(certMsg.marshal())

		certs := make([]*x509.Certificate, len(certMsg.certificates))
		for i, asn1Data := range certMsg.certificates {
			cert, err := x509.ParseCertificate(asn1Data)
			if err != nil {
				c.sendAlert(alertBadCertificate)
				return errors.New("tls: failed to parse certificate from server: " + err.Error())
			}
			certs[i] = cert
		}
		leaf = certs[0]

		if !c.config.InsecureSkipVerify {
			opts := x509.VerifyOptions{
				Roots:         c.config.RootCAs,
				CurrentTime:   c.config.time(),
				DNSName:       c.config.ServerName,
				Intermediates: x509.NewCertPool(),
			}

			for i, cert := range certs {
				if i == 0 {
					continue
				}
				opts.Intermediates.AddCert(cert)
			}
			c.verifiedChains, err = leaf.Verify(opts)
			if err != nil {
				c.sendAlert(alertBadCertificate)
				return err
			}
		}

		switch leaf.PublicKey.(type) {
		case *rsa.PublicKey, *ecdsa.PublicKey:
			break
		default:
			c.sendAlert(alertUnsupportedCertificate)
			return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", leaf.PublicKey)
		}

		c.peerCertificates = certs
	}

	if hs.serverHello.ocspStapling {
		msg, err := c.readHandshake()
		if err != nil {
			return err
		}
		cs, ok := msg.(*certificateStatusMsg)
		if !ok {
			c.sendAlert(alertUnexpectedMessage)
			return unexpectedMessageError(cs, msg)
		}
		hs.writeServerHash(cs.marshal())

		if cs.statusType == statusTypeOCSP {
			c.ocspResponse = cs.response
		}
	}

	msg, err := c.readHandshake()
	if err != nil {
		return err
	}

	keyAgreement := hs.suite.ka(c.vers)

	skx, ok := msg.(*serverKeyExchangeMsg)
	if ok {
		hs.writeServerHash(skx.marshal())
		err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, leaf, skx)
		if err != nil {
			c.sendAlert(alertUnexpectedMessage)
			return err
		}

		msg, err = c.readHandshake()
		if err != nil {
			return err
		}
	}

	var chainToSend *Certificate
	var certRequested bool
	certReq, ok := msg.(*certificateRequestMsg)
	if ok {
		certRequested = true

		// RFC 4346 on the certificateAuthorities field:
		// A list of the distinguished names of acceptable certificate
		// authorities. These distinguished names may specify a desired
		// distinguished name for a root CA or for a subordinate CA;
		// thus, this message can be used to describe both known roots
		// and a desired authorization space. If the
		// certificate_authorities list is empty then the client MAY
		// send any certificate of the appropriate
		// ClientCertificateType, unless there is some external
		// arrangement to the contrary.

		hs.writeServerHash(certReq.marshal())

		var rsaAvail, ecdsaAvail bool
		for _, certType := range certReq.certificateTypes {
			switch certType {
			case CertTypeRSASign:
				rsaAvail = true
			case CertTypeECDSASign:
				ecdsaAvail = true
			}
		}

		// We need to search our list of client certs for one
		// where SignatureAlgorithm is RSA and the Issuer is in
		// certReq.certificateAuthorities
	findCert:
		for i, chain := range c.config.Certificates {
			if !rsaAvail && !ecdsaAvail {
				continue
			}

			for j, cert := range chain.Certificate {
				x509Cert := chain.Leaf
				// parse the certificate if this isn't the leaf
				// node, or if chain.Leaf was nil
				if j != 0 || x509Cert == nil {
					if x509Cert, err = x509.ParseCertificate(cert); err != nil {
						c.sendAlert(alertInternalError)
						return errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error())
					}
				}

				switch {
				case rsaAvail && x509Cert.PublicKeyAlgorithm == x509.RSA:
				case ecdsaAvail && x509Cert.PublicKeyAlgorithm == x509.ECDSA:
				default:
					continue findCert
				}

				if len(certReq.certificateAuthorities) == 0 {
					// they gave us an empty list, so just take the
					// first RSA cert from c.config.Certificates
					chainToSend = &chain
					break findCert
				}

				for _, ca := range certReq.certificateAuthorities {
					if bytes.Equal(x509Cert.RawIssuer, ca) {
						chainToSend = &chain
						break findCert
					}
				}
			}
		}

		msg, err = c.readHandshake()
		if err != nil {
			return err
		}
	}

	shd, ok := msg.(*serverHelloDoneMsg)
	if !ok {
		c.sendAlert(alertUnexpectedMessage)
		return unexpectedMessageError(shd, msg)
	}
	hs.writeServerHash(shd.marshal())

	// If the server requested a certificate then we have to send a
	// Certificate message, even if it's empty because we don't have a
	// certificate to send.
	if certRequested {
		certMsg := new(certificateMsg)
		if chainToSend != nil {
			certMsg.certificates = chainToSend.Certificate
		}
		hs.writeClientHash(certMsg.marshal())
		c.writeRecord(recordTypeHandshake, certMsg.marshal())
	}

	preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, leaf)
	if err != nil {
		c.sendAlert(alertInternalError)
		return err
	}
	if ckx != nil {
		if c.config.Bugs.EarlyChangeCipherSpec < 2 {
			hs.writeClientHash(ckx.marshal())
		}
		c.writeRecord(recordTypeHandshake, ckx.marshal())
	}

	if hs.serverHello.extendedMasterSecret && c.vers >= VersionTLS10 {
		hs.masterSecret = extendedMasterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.finishedHash)
		c.extendedMasterSecret = true
	} else {
		if c.config.Bugs.RequireExtendedMasterSecret {
			return errors.New("tls: extended master secret required but not supported by peer")
		}
		hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random)
	}

	if chainToSend != nil {
		var signed []byte
		certVerify := &certificateVerifyMsg{
			hasSignatureAndHash: c.vers >= VersionTLS12,
		}

		switch key := c.config.Certificates[0].PrivateKey.(type) {
		case *ecdsa.PrivateKey:
			certVerify.signatureAndHash, err = hs.finishedHash.selectClientCertSignatureAlgorithm(certReq.signatureAndHashes, signatureECDSA)
			if err != nil {
				break
			}
			var digest []byte
			digest, _, err = hs.finishedHash.hashForClientCertificate(certVerify.signatureAndHash, hs.masterSecret)
			if err != nil {
				break
			}
			var r, s *big.Int
			r, s, err = ecdsa.Sign(c.config.rand(), key, digest)
			if err == nil {
				signed, err = asn1.Marshal(ecdsaSignature{r, s})
			}
		case *rsa.PrivateKey:
			certVerify.signatureAndHash, err = hs.finishedHash.selectClientCertSignatureAlgorithm(certReq.signatureAndHashes, signatureRSA)
			if err != nil {
				break
			}
			var digest []byte
			var hashFunc crypto.Hash
			digest, hashFunc, err = hs.finishedHash.hashForClientCertificate(certVerify.signatureAndHash, hs.masterSecret)
			if err != nil {
				break
			}
			signed, err = rsa.SignPKCS1v15(c.config.rand(), key, hashFunc, digest)
		default:
			err = errors.New("unknown private key type")
		}
		if err != nil {
			c.sendAlert(alertInternalError)
			return errors.New("tls: failed to sign handshake with client certificate: " + err.Error())
		}
		certVerify.signature = signed

		hs.writeClientHash(certVerify.marshal())
		c.writeRecord(recordTypeHandshake, certVerify.marshal())
	}
	c.dtlsFlushHandshake()

	hs.finishedHash.discardHandshakeBuffer()

	return nil
}
Beispiel #18
-1
func CheckCertAgainRoot(x509Cert *x509.Certificate, certPool *x509.CertPool) ([][]*x509.Certificate, error) {
	opts := x509.VerifyOptions{
		// TODO		DNSName: "test.example.com",
		Roots: certPool,
	}

	return x509Cert.Verify(opts)
}