Vendor cfssl and cfssljson
This commit is contained in:
33
vendor/github.com/cloudflare/cfssl/ubiquity/BUILD
generated
vendored
Normal file
33
vendor/github.com/cloudflare/cfssl/ubiquity/BUILD
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"filter.go",
|
||||
"performance.go",
|
||||
"sha1.go",
|
||||
"ubiquity_crypto.go",
|
||||
"ubiquity_platform.go",
|
||||
],
|
||||
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/ubiquity",
|
||||
importpath = "github.com/cloudflare/cfssl/ubiquity",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//vendor/github.com/cloudflare/cfssl/helpers:go_default_library",
|
||||
"//vendor/github.com/cloudflare/cfssl/log:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
36
vendor/github.com/cloudflare/cfssl/ubiquity/filter.go
generated
vendored
Normal file
36
vendor/github.com/cloudflare/cfssl/ubiquity/filter.go
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
// Package ubiquity contains the ubiquity scoring logic for CFSSL bundling.
|
||||
package ubiquity
|
||||
|
||||
// Ubiquity is addressed as selecting the chains that are most likely being accepted for different client systems.
|
||||
// To select, we decide to do multi-round filtering from different ranking perpectives.
|
||||
import (
|
||||
"crypto/x509"
|
||||
)
|
||||
|
||||
// RankingFunc returns the relative rank between chain1 and chain2.
|
||||
// Return value:
|
||||
// positive integer if rank(chain1) > rank(chain2),
|
||||
// negative integer if rank(chain1) < rank(chain2),
|
||||
// 0 if rank(chain1) == (chain2).
|
||||
type RankingFunc func(chain1, chain2 []*x509.Certificate) int
|
||||
|
||||
// Filter filters out the chains with highest rank according to the ranking function f.
|
||||
func Filter(chains [][]*x509.Certificate, f RankingFunc) [][]*x509.Certificate {
|
||||
// If there are no chain or only 1 chain, we are done.
|
||||
if len(chains) <= 1 {
|
||||
return chains
|
||||
}
|
||||
|
||||
bestChain := chains[0]
|
||||
var candidateChains [][]*x509.Certificate
|
||||
for _, chain := range chains {
|
||||
r := f(bestChain, chain)
|
||||
if r < 0 {
|
||||
bestChain = chain
|
||||
candidateChains = [][]*x509.Certificate{chain}
|
||||
} else if r == 0 {
|
||||
candidateChains = append(candidateChains, chain)
|
||||
}
|
||||
}
|
||||
return candidateChains
|
||||
}
|
126
vendor/github.com/cloudflare/cfssl/ubiquity/performance.go
generated
vendored
Normal file
126
vendor/github.com/cloudflare/cfssl/ubiquity/performance.go
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
package ubiquity
|
||||
|
||||
// In this file, we include chain ranking functions based on security and performance
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"time"
|
||||
|
||||
"github.com/cloudflare/cfssl/helpers"
|
||||
)
|
||||
|
||||
// Compute the priority of different hash algorithm based on security
|
||||
// SHA2 > SHA1 >> MD = Others = Unknown
|
||||
func hashPriority(cert *x509.Certificate) int {
|
||||
switch cert.SignatureAlgorithm {
|
||||
case x509.ECDSAWithSHA1, x509.DSAWithSHA1, x509.SHA1WithRSA:
|
||||
return 10
|
||||
case x509.ECDSAWithSHA256, x509.ECDSAWithSHA384, x509.ECDSAWithSHA512,
|
||||
x509.DSAWithSHA256, x509.SHA256WithRSA, x509.SHA384WithRSA,
|
||||
x509.SHA512WithRSA:
|
||||
return 100
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the priority of different key algorithm based performance and security
|
||||
// ECDSA>RSA>DSA>Unknown
|
||||
func keyAlgoPriority(cert *x509.Certificate) int {
|
||||
switch cert.PublicKeyAlgorithm {
|
||||
case x509.ECDSA:
|
||||
switch cert.PublicKey.(*ecdsa.PublicKey).Curve {
|
||||
case elliptic.P256():
|
||||
return 100
|
||||
case elliptic.P384():
|
||||
return 120
|
||||
case elliptic.P521():
|
||||
return 140
|
||||
default:
|
||||
return 100
|
||||
}
|
||||
case x509.RSA:
|
||||
switch cert.PublicKey.(*rsa.PublicKey).N.BitLen() {
|
||||
case 4096:
|
||||
return 70
|
||||
case 3072:
|
||||
return 50
|
||||
case 2048:
|
||||
return 30
|
||||
// key size <= 1024 are discouraged.
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
// we do not want to bundle a DSA cert.
|
||||
case x509.DSA:
|
||||
return 0
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
// HashPriority returns the hash priority of the chain as the average of hash priority of certs in it.
|
||||
func HashPriority(certs []*x509.Certificate) int {
|
||||
ret := 0.0
|
||||
for i, cert := range certs {
|
||||
f1 := 1.0 / (float64(i) + 1.0)
|
||||
f2 := 1.0 - f1
|
||||
ret = ret*f2 + float64(hashPriority(cert))*f1
|
||||
}
|
||||
return int(ret)
|
||||
}
|
||||
|
||||
// KeyAlgoPriority returns the key algorithm priority of the chain as the average of key algorithm priority of certs in it.
|
||||
func KeyAlgoPriority(certs []*x509.Certificate) int {
|
||||
ret := 0.0
|
||||
for i, cert := range certs {
|
||||
f1 := 1.0 / (float64(i) + 1.0)
|
||||
f2 := 1.0 - f1
|
||||
ret = float64(keyAlgoPriority(cert))*f1 + ret*f2
|
||||
}
|
||||
return int(ret)
|
||||
}
|
||||
|
||||
// CompareChainHashPriority ranks chains with more current hash functions higher.
|
||||
func CompareChainHashPriority(chain1, chain2 []*x509.Certificate) int {
|
||||
hp1 := HashPriority(chain1)
|
||||
hp2 := HashPriority(chain2)
|
||||
return hp1 - hp2
|
||||
}
|
||||
|
||||
// CompareChainKeyAlgoPriority ranks chains with more current key algorithm higher.
|
||||
func CompareChainKeyAlgoPriority(chain1, chain2 []*x509.Certificate) int {
|
||||
kap1 := KeyAlgoPriority(chain1)
|
||||
kap2 := KeyAlgoPriority(chain2)
|
||||
return kap1 - kap2
|
||||
}
|
||||
|
||||
// CompareChainCryptoSuite ranks chains with more current crypto suite higher.
|
||||
func CompareChainCryptoSuite(chain1, chain2 []*x509.Certificate) int {
|
||||
cs1 := HashPriority(chain1) + KeyAlgoPriority(chain1)
|
||||
cs2 := HashPriority(chain2) + KeyAlgoPriority(chain2)
|
||||
return cs1 - cs2
|
||||
}
|
||||
|
||||
// CompareChainLength ranks shorter chain higher.
|
||||
func CompareChainLength(chain1, chain2 []*x509.Certificate) int {
|
||||
return len(chain2) - len(chain1)
|
||||
}
|
||||
|
||||
func compareTime(t1, t2 time.Time) int {
|
||||
if t1.After(t2) {
|
||||
return 1
|
||||
} else if t1.Before(t2) {
|
||||
return -1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// CompareChainExpiry ranks chain that lasts longer higher.
|
||||
func CompareChainExpiry(chain1, chain2 []*x509.Certificate) int {
|
||||
t1 := helpers.ExpiryTime(chain1)
|
||||
t2 := helpers.ExpiryTime(chain2)
|
||||
return compareTime(t1, t2)
|
||||
}
|
153
vendor/github.com/cloudflare/cfssl/ubiquity/sha1.go
generated
vendored
Normal file
153
vendor/github.com/cloudflare/cfssl/ubiquity/sha1.go
generated
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
package ubiquity
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/cloudflare/cfssl/helpers"
|
||||
)
|
||||
|
||||
// DeprecationSeverity encodes the severity of a deprecation policy
|
||||
type DeprecationSeverity int
|
||||
|
||||
const (
|
||||
// None indicates there is no deprecation
|
||||
None DeprecationSeverity = iota
|
||||
// Low indicates the deprecation policy won't affect user experience
|
||||
Low
|
||||
// Medium indicates the deprecation policy will affect user experience
|
||||
// either in a minor way or for a limited scope of users.
|
||||
Medium
|
||||
// High indicates the deprecation policy will strongly affect user experience
|
||||
High
|
||||
)
|
||||
|
||||
// SHA1DeprecationPolicy encodes how a platform deprecates the support of SHA1
|
||||
type SHA1DeprecationPolicy struct {
|
||||
// the name of platform
|
||||
Platform string `json:"platform"`
|
||||
// policy severity, policies of the same platform will only trigger the one of highest severity
|
||||
Severity DeprecationSeverity `json:"severity"`
|
||||
// a human readable message describing the deprecation effects
|
||||
Description string `json:"description"`
|
||||
// the date when the policy is effective. zero value means effective immediately
|
||||
EffectiveDate time.Time `json:"effective_date"`
|
||||
// the expiry deadline indicates the latest date which a end-entity
|
||||
// certificate with SHA1 can be valid through.
|
||||
ExpiryDeadline time.Time `json:"expiry_deadline"`
|
||||
// the date beyond which SHA1 cert should not be issued.
|
||||
NeverIssueAfter time.Time `json:"never_issue_after"`
|
||||
}
|
||||
|
||||
// SHA1DeprecationPolicys ia a list of various SHA1DeprecationPolicy's
|
||||
// proposed by major browser producers
|
||||
var SHA1DeprecationPolicys = []SHA1DeprecationPolicy{
|
||||
// Chrome:
|
||||
// if the leaf certificate expires between 01-01-2016 and 01-01-2017
|
||||
// and the chain (excluding root) contains SHA-1 cert, show "minor errors".
|
||||
{
|
||||
Platform: "Google Chrome",
|
||||
Description: "shows the SSL connection has minor problems",
|
||||
Severity: Medium,
|
||||
ExpiryDeadline: time.Date(2016, time.January, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
// Chrome:
|
||||
// if the leaf certificate expires after Jan. 1st 2017
|
||||
// and the chain (excluding root) contains SHA-1 cert, show "untrusted SSL".
|
||||
{
|
||||
Platform: "Google Chrome",
|
||||
Description: "shows the SSL connection is untrusted",
|
||||
Severity: High,
|
||||
ExpiryDeadline: time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
// Mozilla Firefox:
|
||||
// if the leaf certificate expires after Jan. 1st 2017, and
|
||||
// the chain (excluding root) contains SHA-1 cert, show a warning in the developer console.
|
||||
{
|
||||
Platform: "Mozilla Firefox",
|
||||
Description: "gives warning in the developer console",
|
||||
Severity: Low,
|
||||
ExpiryDeadline: time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
// Mozilla Firefox:
|
||||
// if a new certificate is issued after Jan. 1st 2016, and
|
||||
// it is a SHA-1 cert, reject it.
|
||||
{
|
||||
Platform: "Mozilla Firefox",
|
||||
Description: "shows the SSL connection is untrusted",
|
||||
Severity: Medium,
|
||||
EffectiveDate: time.Date(2016, time.January, 1, 0, 0, 0, 0, time.UTC),
|
||||
NeverIssueAfter: time.Date(2016, time.January, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
// Mozilla Firefox:
|
||||
// deprecate all valid SHA-1 cert chain on Jan. 1st 2017
|
||||
{
|
||||
Platform: "Mozilla Firefox",
|
||||
Description: "shows the SSL connection is untrusted",
|
||||
Severity: High,
|
||||
EffectiveDate: time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC),
|
||||
ExpiryDeadline: time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
// Microsoft Windows:
|
||||
// deprecate all valid SHA-1 cert chain on Jan. 1st 2017
|
||||
{
|
||||
Platform: "Microsoft Windows Vista and later",
|
||||
Description: "shows the SSL connection is untrusted",
|
||||
Severity: High,
|
||||
EffectiveDate: time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC),
|
||||
ExpiryDeadline: time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
}
|
||||
|
||||
// Flag returns whether the policy flags the cert chain as deprecated for matching its deprecation criteria
|
||||
func (p SHA1DeprecationPolicy) Flag(chain []*x509.Certificate) bool {
|
||||
leaf := chain[0]
|
||||
if time.Now().After(p.EffectiveDate) {
|
||||
|
||||
// Reject newly issued leaf certificate with SHA-1 after the specified deadline.
|
||||
if !p.NeverIssueAfter.IsZero() && leaf.NotBefore.After(p.NeverIssueAfter) {
|
||||
// Check hash algorithm of non-root leaf cert.
|
||||
if len(chain) > 1 && helpers.HashAlgoString(leaf.SignatureAlgorithm) == "SHA1" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// Reject certificate chain with SHA-1 that are still valid after expiry deadline.
|
||||
if !p.ExpiryDeadline.IsZero() && leaf.NotAfter.After(p.ExpiryDeadline) {
|
||||
// Check hash algorithm of non-root certs.
|
||||
for i, cert := range chain {
|
||||
if i < len(chain)-1 {
|
||||
if helpers.HashAlgoString(cert.SignatureAlgorithm) == "SHA1" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// SHA1DeprecationMessages returns a list of human-readable messages. Each message describes
|
||||
// how one platform rejects the chain based on SHA1 deprecation policies.
|
||||
func SHA1DeprecationMessages(chain []*x509.Certificate) []string {
|
||||
// record the most severe deprecation policy by each platform
|
||||
selectedPolicies := map[string]SHA1DeprecationPolicy{}
|
||||
for _, policy := range SHA1DeprecationPolicys {
|
||||
if policy.Flag(chain) {
|
||||
// only keep the policy with highest severity
|
||||
if selectedPolicies[policy.Platform].Severity < policy.Severity {
|
||||
selectedPolicies[policy.Platform] = policy
|
||||
}
|
||||
}
|
||||
}
|
||||
// build the message list
|
||||
list := []string{}
|
||||
for _, policy := range selectedPolicies {
|
||||
if policy.Severity > None {
|
||||
list = append(list, fmt.Sprintf("%s %s due to SHA-1 deprecation", policy.Platform, policy.Description))
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
166
vendor/github.com/cloudflare/cfssl/ubiquity/ubiquity_crypto.go
generated
vendored
Normal file
166
vendor/github.com/cloudflare/cfssl/ubiquity/ubiquity_crypto.go
generated
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
package ubiquity
|
||||
|
||||
// In this file, we mainly cover crypto ubiquity.
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"github.com/cloudflare/cfssl/helpers"
|
||||
"math"
|
||||
)
|
||||
|
||||
// HashUbiquity represents a score for how ubiquitous a given hash
|
||||
// algorithm is; the higher the score, the more preferable the algorithm
|
||||
// is.
|
||||
type HashUbiquity int
|
||||
|
||||
// KeyAlgoUbiquity represents a score for how ubiquitous a given
|
||||
// public-key algorithm is; the higher the score, the more preferable
|
||||
// the algorithm is.
|
||||
type KeyAlgoUbiquity int
|
||||
|
||||
// SHA1 is ubiquitous. SHA2 is not supported on some legacy platforms.
|
||||
// We consider MD2/MD5 is harmful and thus assign them lowest ubiquity.
|
||||
const (
|
||||
UnknownHashUbiquity HashUbiquity = 0
|
||||
SHA2Ubiquity HashUbiquity = 70
|
||||
SHA1Ubiquity HashUbiquity = 100
|
||||
MD5Ubiquity HashUbiquity = 0
|
||||
MD2Ubiquity HashUbiquity = 0
|
||||
)
|
||||
|
||||
// RSA and DSA are considered ubiquitous. ECDSA256 and ECDSA384 should be
|
||||
// supported by TLS 1.2 and have limited support from TLS 1.0 and
|
||||
// 1.1, based on RFC6460, but ECDSA521 is less well-supported as
|
||||
// a standard.
|
||||
const (
|
||||
RSAUbiquity KeyAlgoUbiquity = 100
|
||||
DSAUbiquity KeyAlgoUbiquity = 100
|
||||
ECDSA256Ubiquity KeyAlgoUbiquity = 70
|
||||
ECDSA384Ubiquity KeyAlgoUbiquity = 70
|
||||
ECDSA521Ubiquity KeyAlgoUbiquity = 30
|
||||
UnknownAlgoUbiquity KeyAlgoUbiquity = 0
|
||||
)
|
||||
|
||||
// hashUbiquity computes the ubiquity of the hash algorithm in the
|
||||
// signature algorithm of a cert.
|
||||
// SHA1 > SHA2 > MD > Others
|
||||
func hashUbiquity(cert *x509.Certificate) HashUbiquity {
|
||||
switch cert.SignatureAlgorithm {
|
||||
case x509.ECDSAWithSHA1, x509.DSAWithSHA1, x509.SHA1WithRSA:
|
||||
return SHA1Ubiquity
|
||||
case x509.ECDSAWithSHA256, x509.ECDSAWithSHA384, x509.ECDSAWithSHA512,
|
||||
x509.DSAWithSHA256, x509.SHA256WithRSA, x509.SHA384WithRSA,
|
||||
x509.SHA512WithRSA:
|
||||
return SHA2Ubiquity
|
||||
case x509.MD5WithRSA, x509.MD2WithRSA:
|
||||
return MD5Ubiquity
|
||||
default:
|
||||
return UnknownHashUbiquity
|
||||
}
|
||||
}
|
||||
|
||||
// keyAlgoUbiquity compute the ubiquity of the cert's public key algorithm
|
||||
// RSA, DSA>ECDSA>Unknown
|
||||
func keyAlgoUbiquity(cert *x509.Certificate) KeyAlgoUbiquity {
|
||||
switch cert.PublicKeyAlgorithm {
|
||||
case x509.ECDSA:
|
||||
switch cert.PublicKey.(*ecdsa.PublicKey).Curve {
|
||||
case elliptic.P256():
|
||||
return ECDSA256Ubiquity
|
||||
case elliptic.P384():
|
||||
return ECDSA384Ubiquity
|
||||
case elliptic.P521():
|
||||
return ECDSA521Ubiquity
|
||||
default:
|
||||
return UnknownAlgoUbiquity
|
||||
}
|
||||
case x509.RSA:
|
||||
if cert.PublicKey.(*rsa.PublicKey).N.BitLen() >= 1024 {
|
||||
return RSAUbiquity
|
||||
}
|
||||
return UnknownAlgoUbiquity
|
||||
case x509.DSA:
|
||||
return DSAUbiquity
|
||||
default:
|
||||
return UnknownAlgoUbiquity
|
||||
}
|
||||
}
|
||||
|
||||
// ChainHashUbiquity scores a chain based on the hash algorithms used
|
||||
// by the certificates in the chain.
|
||||
func ChainHashUbiquity(chain []*x509.Certificate) HashUbiquity {
|
||||
ret := math.MaxInt32
|
||||
for _, cert := range chain {
|
||||
uscore := int(hashUbiquity(cert))
|
||||
if ret > uscore {
|
||||
ret = uscore
|
||||
}
|
||||
}
|
||||
return HashUbiquity(ret)
|
||||
}
|
||||
|
||||
// ChainKeyAlgoUbiquity scores a chain based on the public-key algorithms
|
||||
// used by the certificates in the chain.
|
||||
func ChainKeyAlgoUbiquity(chain []*x509.Certificate) KeyAlgoUbiquity {
|
||||
ret := math.MaxInt32
|
||||
for _, cert := range chain {
|
||||
uscore := int(keyAlgoUbiquity(cert))
|
||||
if ret > uscore {
|
||||
ret = uscore
|
||||
}
|
||||
}
|
||||
return KeyAlgoUbiquity(ret)
|
||||
}
|
||||
|
||||
// CompareChainHashUbiquity returns a positive, zero, or negative value
|
||||
// if the hash ubiquity of the first chain is greater, equal, or less
|
||||
// than the second chain.
|
||||
func CompareChainHashUbiquity(chain1, chain2 []*x509.Certificate) int {
|
||||
hu1 := ChainHashUbiquity(chain1)
|
||||
hu2 := ChainHashUbiquity(chain2)
|
||||
return int(hu1) - int(hu2)
|
||||
}
|
||||
|
||||
// CompareChainKeyAlgoUbiquity returns a positive, zero, or negative value
|
||||
// if the public-key ubiquity of the first chain is greater, equal,
|
||||
// or less than the second chain.
|
||||
func CompareChainKeyAlgoUbiquity(chain1, chain2 []*x509.Certificate) int {
|
||||
kau1 := ChainKeyAlgoUbiquity(chain1)
|
||||
kau2 := ChainKeyAlgoUbiquity(chain2)
|
||||
return int(kau1) - int(kau2)
|
||||
}
|
||||
|
||||
// CompareExpiryUbiquity ranks two certificate chains based on the exiry dates of intermediates and roots.
|
||||
// Certs expire later are ranked higher than ones expire earlier. The ranking between chains are determined by
|
||||
// the first pair of intermediates, scanned from the root level, that ar ranked differently.
|
||||
func CompareExpiryUbiquity(chain1, chain2 []*x509.Certificate) int {
|
||||
for i := 0; ; i++ {
|
||||
if i >= len(chain1) || i >= len(chain2) {
|
||||
break
|
||||
}
|
||||
c1 := chain1[len(chain1)-1-i]
|
||||
c2 := chain2[len(chain2)-1-i]
|
||||
t1 := c1.NotAfter
|
||||
t2 := c2.NotAfter
|
||||
|
||||
// Check if expiry dates valid. Return if one or other is invalid.
|
||||
// Otherwise rank by expiry date. Later is ranked higher.
|
||||
c1Valid := helpers.ValidExpiry(c1)
|
||||
c2Valid := helpers.ValidExpiry(c2)
|
||||
if c1Valid && !c2Valid {
|
||||
return 1
|
||||
}
|
||||
if !c1Valid && c2Valid {
|
||||
return -1
|
||||
}
|
||||
|
||||
r := compareTime(t1, t2)
|
||||
// Return when we find rank difference.
|
||||
if r != 0 {
|
||||
return r
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
230
vendor/github.com/cloudflare/cfssl/ubiquity/ubiquity_platform.go
generated
vendored
Normal file
230
vendor/github.com/cloudflare/cfssl/ubiquity/ubiquity_platform.go
generated
vendored
Normal file
@@ -0,0 +1,230 @@
|
||||
package ubiquity
|
||||
|
||||
// This is for cross-platform ubiquity. Basically, here we deal with issues about whether a cert chain
|
||||
// is acceptable for different platforms, including desktop and mobile ones., and about how to compare
|
||||
// two chains under the context of cross-platform ubiquity.
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/cloudflare/cfssl/helpers"
|
||||
"github.com/cloudflare/cfssl/log"
|
||||
)
|
||||
|
||||
// SHA1RawPublicKey returns a SHA1 hash of the raw certificate public key
|
||||
func SHA1RawPublicKey(cert *x509.Certificate) string {
|
||||
return fmt.Sprintf("%x", sha1.Sum(cert.RawSubjectPublicKeyInfo))
|
||||
}
|
||||
|
||||
// CertSet is a succint set of x509 certificates which only stores certificates' SHA1 hashes.
|
||||
type CertSet map[string]bool
|
||||
|
||||
// Lookup returns whether a certificate is stored in the set.
|
||||
func (s CertSet) Lookup(cert *x509.Certificate) bool {
|
||||
return s[SHA1RawPublicKey(cert)]
|
||||
}
|
||||
|
||||
// Add adds a certificate to the set.
|
||||
func (s CertSet) Add(cert *x509.Certificate) {
|
||||
s[SHA1RawPublicKey(cert)] = true
|
||||
}
|
||||
|
||||
// A Platform contains ubiquity information on supported crypto algorithms and root certificate store name.
|
||||
type Platform struct {
|
||||
Name string `json:"name"`
|
||||
Weight int `json:"weight"`
|
||||
HashAlgo string `json:"hash_algo"`
|
||||
KeyAlgo string `json:"key_algo"`
|
||||
KeyStoreFile string `json:"keystore"`
|
||||
KeyStore CertSet
|
||||
HashUbiquity HashUbiquity
|
||||
KeyAlgoUbiquity KeyAlgoUbiquity
|
||||
}
|
||||
|
||||
// Trust returns whether the platform has the root cert in the trusted store.
|
||||
func (p Platform) Trust(root *x509.Certificate) bool {
|
||||
// the key store is empty iff the platform doesn't carry a root store and trust whatever root store
|
||||
// is supplied. An example is Chrome. Such platforms should not show up in the untrusted platform
|
||||
// list. So always return true here. Also this won't hurt ubiquity scoring because such platforms give
|
||||
// no differentiation on root cert selection.
|
||||
if len(p.KeyStore) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
return p.KeyStore.Lookup(root)
|
||||
}
|
||||
|
||||
func (p Platform) hashUbiquity() HashUbiquity {
|
||||
switch p.HashAlgo {
|
||||
case "SHA1":
|
||||
return SHA1Ubiquity
|
||||
case "SHA2":
|
||||
return SHA2Ubiquity
|
||||
default:
|
||||
return UnknownHashUbiquity
|
||||
}
|
||||
}
|
||||
|
||||
func (p Platform) keyAlgoUbiquity() KeyAlgoUbiquity {
|
||||
switch p.KeyAlgo {
|
||||
case "RSA":
|
||||
return RSAUbiquity
|
||||
case "ECDSA256":
|
||||
return ECDSA256Ubiquity
|
||||
case "ECDSA384":
|
||||
return ECDSA384Ubiquity
|
||||
case "ECDSA521":
|
||||
return ECDSA521Ubiquity
|
||||
default:
|
||||
return UnknownAlgoUbiquity
|
||||
}
|
||||
}
|
||||
|
||||
// ParseAndLoad converts HashAlgo and KeyAlgo to corresponding ubiquity value and load
|
||||
// certificates into internal KeyStore from KeyStoreFiles
|
||||
func (p *Platform) ParseAndLoad() (ok bool) {
|
||||
p.HashUbiquity = p.hashUbiquity()
|
||||
p.KeyAlgoUbiquity = p.keyAlgoUbiquity()
|
||||
p.KeyStore = map[string]bool{}
|
||||
if p.KeyStoreFile != "" {
|
||||
pemBytes, err := ioutil.ReadFile(p.KeyStoreFile)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return false
|
||||
}
|
||||
// Best effort parsing the PEMs such that ignore all borken pem,
|
||||
// since some of CA certs have negative serial number which trigger errors.
|
||||
for len(pemBytes) > 0 {
|
||||
var certs []*x509.Certificate
|
||||
certs, rest, err := helpers.ParseOneCertificateFromPEM(pemBytes)
|
||||
// If one certificate object is parsed, possibly a PKCS#7
|
||||
// structure containing multiple certs, record the raw SHA1 hash(es).
|
||||
if err == nil && certs != nil {
|
||||
for _, cert := range certs {
|
||||
p.KeyStore.Add(cert)
|
||||
}
|
||||
}
|
||||
|
||||
if len(rest) < len(pemBytes) {
|
||||
pemBytes = rest
|
||||
} else {
|
||||
// No progress in bytes parsing, bail out.
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if p.HashUbiquity <= UnknownHashUbiquity ||
|
||||
p.KeyAlgoUbiquity <= UnknownAlgoUbiquity {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Platforms is the list of platforms against which ubiquity bundling will be optimized.
|
||||
var Platforms []Platform
|
||||
|
||||
// LoadPlatforms reads the file content as a json object array and convert it
|
||||
// to Platforms.
|
||||
func LoadPlatforms(filename string) error {
|
||||
// if filename is empty, skip the metadata loading
|
||||
if filename == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
relativePath := filepath.Dir(filename)
|
||||
// Attempt to load root certificate metadata
|
||||
log.Debug("Loading platform metadata: ", filename)
|
||||
bytes, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return fmt.Errorf("platform metadata failed to load: %v", err)
|
||||
}
|
||||
var rawPlatforms []Platform
|
||||
if bytes != nil {
|
||||
err = json.Unmarshal(bytes, &rawPlatforms)
|
||||
if err != nil {
|
||||
return fmt.Errorf("platform metadata failed to parse: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, platform := range rawPlatforms {
|
||||
if platform.KeyStoreFile != "" {
|
||||
platform.KeyStoreFile = path.Join(relativePath, platform.KeyStoreFile)
|
||||
}
|
||||
ok := platform.ParseAndLoad()
|
||||
if !ok {
|
||||
// erase all loaded platforms
|
||||
Platforms = nil
|
||||
return fmt.Errorf("fail to finalize the parsing of platform metadata: %v", platform)
|
||||
}
|
||||
|
||||
log.Infof("Platform metadata is loaded: %v %v", platform.Name, len(platform.KeyStore))
|
||||
Platforms = append(Platforms, platform)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UntrustedPlatforms returns a list of platforms which don't trust the root certificate.
|
||||
func UntrustedPlatforms(root *x509.Certificate) []string {
|
||||
ret := []string{}
|
||||
for _, platform := range Platforms {
|
||||
if !platform.Trust(root) {
|
||||
ret = append(ret, platform.Name)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// CrossPlatformUbiquity returns a ubiquity score (persumably relecting the market share in percentage)
|
||||
// based on whether the given chain can be verified with the different platforms' root certificate stores.
|
||||
func CrossPlatformUbiquity(chain []*x509.Certificate) int {
|
||||
// There is no root store info, every chain is equal weighted as 0.
|
||||
if len(Platforms) == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
totalWeight := 0
|
||||
// A chain is viable with the platform if
|
||||
// 1. the root is in the platform's root store
|
||||
// 2. the chain satisfy the minimal constraints on hash function and key algorithm.
|
||||
root := chain[len(chain)-1]
|
||||
for _, platform := range Platforms {
|
||||
if platform.Trust(root) {
|
||||
switch {
|
||||
case platform.HashUbiquity <= ChainHashUbiquity(chain) && platform.KeyAlgoUbiquity <= ChainKeyAlgoUbiquity(chain):
|
||||
totalWeight += platform.Weight
|
||||
}
|
||||
}
|
||||
}
|
||||
return totalWeight
|
||||
}
|
||||
|
||||
// ComparePlatformUbiquity compares the cross-platform ubiquity between chain1 and chain2.
|
||||
func ComparePlatformUbiquity(chain1, chain2 []*x509.Certificate) int {
|
||||
w1 := CrossPlatformUbiquity(chain1)
|
||||
w2 := CrossPlatformUbiquity(chain2)
|
||||
return w1 - w2
|
||||
}
|
||||
|
||||
// SHA2Homogeneity returns 1 if the chain contains only SHA-2 certs (excluding root). Otherwise it returns 0.
|
||||
func SHA2Homogeneity(chain []*x509.Certificate) int {
|
||||
for i := 0; i < len(chain)-1; i++ {
|
||||
if hashUbiquity(chain[i]) != SHA2Ubiquity {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
// CompareSHA2Homogeneity compares the chains based on SHA2 homogeneity. Full SHA-2 chain (excluding root) is rated higher that the rest.
|
||||
func CompareSHA2Homogeneity(chain1, chain2 []*x509.Certificate) int {
|
||||
w1 := SHA2Homogeneity(chain1)
|
||||
w2 := SHA2Homogeneity(chain2)
|
||||
return w1 - w2
|
||||
}
|
Reference in New Issue
Block a user