Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump github.com/hashicorp/vault/sdk from 0.4.1 to 0.5.0 #1926

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ require (
github.com/hashicorp/go-version v1.5.0
github.com/hashicorp/golang-lru v0.5.4
github.com/hashicorp/hcl v1.0.0
github.com/hashicorp/vault/sdk v0.4.1
github.com/hashicorp/vault/sdk v0.5.0
github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87
github.com/in-toto/in-toto-golang v0.3.4-0.20211211042327-af1f9fb822bf
github.com/kelseyhightower/envconfig v1.4.0
Expand Down
3 changes: 2 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1388,8 +1388,9 @@ github.com/hashicorp/vault/api v1.3.1/go.mod h1:QeJoWxMFt+MsuWcYhmwRLwKEXrjwAFFy
github.com/hashicorp/vault/api v1.5.0 h1:Bp6yc2bn7CWkOrVIzFT/Qurzx528bdavF3nz590eu28=
github.com/hashicorp/vault/api v1.5.0/go.mod h1:LkMdrZnWNrFaQyYYazWVn7KshilfDidgVBq6YiTq/bM=
github.com/hashicorp/vault/sdk v0.3.0/go.mod h1:aZ3fNuL5VNydQk8GcLJ2TV8YCRVvyaakYkhZRoVuhj0=
github.com/hashicorp/vault/sdk v0.4.1 h1:3SaHOJY687jY1fnB61PtL0cOkKItphrbLmux7T92HBo=
github.com/hashicorp/vault/sdk v0.4.1/go.mod h1:aZ3fNuL5VNydQk8GcLJ2TV8YCRVvyaakYkhZRoVuhj0=
github.com/hashicorp/vault/sdk v0.5.0 h1:EED7p0OCU3OY5SAqJwSANofY1YKMytm+jDHDQ2EzGVQ=
github.com/hashicorp/vault/sdk v0.5.0/go.mod h1:UJZHlfwj7qUJG8g22CuxUgkdJouFrBNvBHCyx8XAPdo=
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 h1:xixZ2bWeofWV68J+x6AzmKuVM/JWCQwkWm6GW/MUR6I=
github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,46 @@ func ParsePKIJSON(input []byte) (*ParsedCertBundle, error) {
return nil, errutil.UserError{Err: "unable to parse out of either secret data or a secret object"}
}

func ParseDERKey(privateKeyBytes []byte) (signer crypto.Signer, format BlockType, err error) {
if signer, err = x509.ParseECPrivateKey(privateKeyBytes); err == nil {
format = ECBlock
return
}

if signer, err = x509.ParsePKCS1PrivateKey(privateKeyBytes); err == nil {
format = PKCS1Block
return
}

var rawKey interface{}
if rawKey, err = x509.ParsePKCS8PrivateKey(privateKeyBytes); err == nil {
switch rawSigner := rawKey.(type) {
case *rsa.PrivateKey:
signer = rawSigner
case *ecdsa.PrivateKey:
signer = rawSigner
case ed25519.PrivateKey:
signer = rawSigner
default:
return nil, UnknownBlock, errutil.InternalError{Err: "unknown type for parsed PKCS8 Private Key"}
}

format = PKCS8Block
return
}

return nil, UnknownBlock, err
}

func ParsePEMKey(keyPem string) (crypto.Signer, BlockType, error) {
pemBlock, _ := pem.Decode([]byte(keyPem))
if pemBlock == nil {
return nil, UnknownBlock, errutil.UserError{Err: "no data found in PEM block"}
}

return ParseDERKey(pemBlock.Bytes)
}

// ParsePEMBundle takes a string of concatenated PEM-format certificate
// and private key values and decodes/parses them, checking validity along
// the way. The first certificate must be the subject certificate and issuing
Expand All @@ -170,43 +210,19 @@ func ParsePEMBundle(pemBundle string) (*ParsedCertBundle, error) {
return nil, errutil.UserError{Err: "no data found in PEM block"}
}

if signer, err := x509.ParseECPrivateKey(pemBlock.Bytes); err == nil {
if signer, format, err := ParseDERKey(pemBlock.Bytes); err == nil {
if parsedBundle.PrivateKeyType != UnknownPrivateKey {
return nil, errutil.UserError{Err: "more than one private key given; provide only one private key in the bundle"}
}
parsedBundle.PrivateKeyFormat = ECBlock
parsedBundle.PrivateKeyType = ECPrivateKey
parsedBundle.PrivateKeyBytes = pemBlock.Bytes
parsedBundle.PrivateKey = signer

} else if signer, err := x509.ParsePKCS1PrivateKey(pemBlock.Bytes); err == nil {
if parsedBundle.PrivateKeyType != UnknownPrivateKey {
return nil, errutil.UserError{Err: "more than one private key given; provide only one private key in the bundle"}
parsedBundle.PrivateKeyFormat = format
parsedBundle.PrivateKeyType = GetPrivateKeyTypeFromSigner(signer)
if parsedBundle.PrivateKeyType == UnknownPrivateKey {
return nil, errutil.UserError{Err: "Unknown type of private key included in the bundle: %v"}
}
parsedBundle.PrivateKeyType = RSAPrivateKey
parsedBundle.PrivateKeyFormat = PKCS1Block

parsedBundle.PrivateKeyBytes = pemBlock.Bytes
parsedBundle.PrivateKey = signer
} else if signer, err := x509.ParsePKCS8PrivateKey(pemBlock.Bytes); err == nil {
parsedBundle.PrivateKeyFormat = PKCS8Block

if parsedBundle.PrivateKeyType != UnknownPrivateKey {
return nil, errutil.UserError{Err: "More than one private key given; provide only one private key in the bundle"}
}
switch signer := signer.(type) {
case *rsa.PrivateKey:
parsedBundle.PrivateKey = signer
parsedBundle.PrivateKeyType = RSAPrivateKey
parsedBundle.PrivateKeyBytes = pemBlock.Bytes
case *ecdsa.PrivateKey:
parsedBundle.PrivateKey = signer
parsedBundle.PrivateKeyType = ECPrivateKey
parsedBundle.PrivateKeyBytes = pemBlock.Bytes
case ed25519.PrivateKey:
parsedBundle.PrivateKey = signer
parsedBundle.PrivateKeyType = Ed25519PrivateKey
parsedBundle.PrivateKeyBytes = pemBlock.Bytes
}
} else if certificates, err := x509.ParseCertificates(pemBlock.Bytes); err == nil {
certPath = append(certPath, &CertBlock{
Certificate: certificates[0],
Expand Down Expand Up @@ -336,7 +352,21 @@ func generateSerialNumber(randReader io.Reader) (*big.Int, error) {
return serial, nil
}

// ComparePublicKeys compares two public keys and returns true if they match
// ComparePublicKeysAndType compares two public keys and returns true if they match,
// false if their types or contents differ, and an error on unsupported key types.
func ComparePublicKeysAndType(key1Iface, key2Iface crypto.PublicKey) (bool, error) {
equal, err := ComparePublicKeys(key1Iface, key2Iface)
if err != nil {
if strings.Contains(err.Error(), "key types do not match:") {
return false, nil
}
}

return equal, err
}

// ComparePublicKeys compares two public keys and returns true if they match,
// returns an error if public key types are mismatched, or they are an unsupported key type.
func ComparePublicKeys(key1Iface, key2Iface crypto.PublicKey) (bool, error) {
switch key1Iface.(type) {
case *rsa.PublicKey:
Expand Down Expand Up @@ -585,25 +615,17 @@ func DefaultOrValueKeyBits(keyType string, keyBits int) (int, error) {
// certain internal circumstances.
func DefaultOrValueHashBits(keyType string, keyBits int, hashBits int) (int, error) {
if keyType == "ec" {
// To comply with BSI recommendations Section 4.2 and Mozilla root
// store policy section 5.1.2, enforce that NIST P-curves use a hash
// length corresponding to curve length. Note that ed25519 does not
// the "ec" key type.
expectedHashBits := expectedNISTPCurveHashBits[keyBits]

if expectedHashBits != hashBits && hashBits != 0 {
return hashBits, fmt.Errorf("unsupported signature hash algorithm length (%d) for NIST P-%d", hashBits, keyBits)
} else if hashBits == 0 {
hashBits = expectedHashBits
}
// Enforcement of curve moved to selectSignatureAlgorithmForECDSA. See
// note there about why.
} else if keyType == "rsa" && hashBits == 0 {
// To match previous behavior (and ignoring NIST's recommendations for
// hash size to align with RSA key sizes), default to SHA-2-256.
hashBits = 256
} else if keyType == "ed25519" || keyType == "ed448" {
} else if keyType == "ed25519" || keyType == "ed448" || keyType == "any" {
// No-op; ed25519 and ed448 internally specify their own hash and
// we do not need to select one. Double hashing isn't supported in
// certificate signing and we must
// certificate signing. Additionally, the any key type can't know
// what hash algorithm to use yet, so default to zero.
return 0, nil
}

Expand Down Expand Up @@ -642,7 +664,7 @@ func ValidateDefaultOrValueKeyTypeSignatureLength(keyType string, keyBits int, h
// Validates that the length of the hash (in bits) used in the signature
// calculation is a known, approved value.
func ValidateSignatureLength(keyType string, hashBits int) error {
if keyType == "ed25519" || keyType == "ed448" {
if keyType == "any" || keyType == "ec" || keyType == "ed25519" || keyType == "ed448" {
// ed25519 and ed448 include built-in hashing and is not externally
// configurable. There are three modes for each of these schemes:
//
Expand All @@ -654,6 +676,13 @@ func ValidateSignatureLength(keyType string, hashBits int) error {
//
// In all cases, we won't have a hash algorithm to validate here, so
// return nil.
//
// Additionally, when KeyType is any, we can't yet validate the
// signature algorithm size, so it takes the default zero value.
//
// When KeyType is ec, we also can't validate this value as we're
// forcefully ignoring the users' choice and specifying a value based
// on issuer type.
return nil
}

Expand Down Expand Up @@ -842,33 +871,51 @@ func createCertificate(data *CreationBundle, randReader io.Reader, privateKeyGen
}

if data.SigningBundle != nil {
if len(data.SigningBundle.Certificate.AuthorityKeyId) > 0 &&
!bytes.Equal(data.SigningBundle.Certificate.AuthorityKeyId, data.SigningBundle.Certificate.SubjectKeyId) {

result.CAChain = []*CertBlock{
{
if (len(data.SigningBundle.Certificate.AuthorityKeyId) > 0 &&
!bytes.Equal(data.SigningBundle.Certificate.AuthorityKeyId, data.SigningBundle.Certificate.SubjectKeyId)) ||
data.Params.ForceAppendCaChain {
var chain []*CertBlock

signingChain := data.SigningBundle.CAChain
// Some bundles already include the root included in the chain, so don't include it twice.
if len(signingChain) == 0 || !bytes.Equal(signingChain[0].Bytes, data.SigningBundle.CertificateBytes) {
chain = append(chain, &CertBlock{
Certificate: data.SigningBundle.Certificate,
Bytes: data.SigningBundle.CertificateBytes,
},
})
}

if len(signingChain) > 0 {
chain = append(chain, signingChain...)
}
result.CAChain = append(result.CAChain, data.SigningBundle.CAChain...)

result.CAChain = chain
}
}

return result, nil
}

func selectSignatureAlgorithmForECDSA(pub crypto.PublicKey, signatureBits int) x509.SignatureAlgorithm {
// If signature bits are configured, prefer them to the default choice.
switch signatureBits {
case 256:
return x509.ECDSAWithSHA256
case 384:
return x509.ECDSAWithSHA384
case 512:
return x509.ECDSAWithSHA512
}

// Previously we preferred the user-specified signature bits for ECDSA
// keys. However, this could result in using a longer hash function than
// the underlying NIST P-curve will encode (e.g., a SHA-512 hash with a
// P-256 key). This isn't ideal: the hash is implicitly truncated
// (effectively turning it into SHA-512/256) and we then need to rely
// on the prefix security of the hash. Since both NIST and Mozilla guidance
// suggest instead using the correct hash function, we should prefer that
// over the operator-specified signatureBits.
//
// Lastly, note that pub above needs to be the _signer's_ public key;
// the issue with DefaultOrValueHashBits is that it is called at role
// configuration time, which might _precede_ issuer generation. Thus
// it only has access to the desired key type and not the actual issuer.
// The reference from that function is reproduced below:
//
// > To comply with BSI recommendations Section 4.2 and Mozilla root
// > store policy section 5.1.2, enforce that NIST P-curves use a hash
// > length corresponding to curve length. Note that ed25519 does not
// > implement the "ec" key type.
key, ok := pub.(*ecdsa.PublicKey)
if !ok {
return x509.ECDSAWithSHA256
Expand Down Expand Up @@ -1120,7 +1167,7 @@ func signCertificate(data *CreationBundle, randReader io.Reader) (*ParsedCertBun
return nil, errutil.InternalError{Err: fmt.Sprintf("unable to parse created certificate: %s", err)}
}

result.CAChain = data.SigningBundle.GetCAChain()
result.CAChain = data.SigningBundle.GetFullChain()

return result, nil
}
Expand Down Expand Up @@ -1190,3 +1237,20 @@ func GetPublicKeySize(key crypto.PublicKey) int {

return -1
}

// CreateKeyBundle create a KeyBundle struct object which includes a generated key
// of keyType with keyBits leveraging the randomness from randReader.
func CreateKeyBundle(keyType string, keyBits int, randReader io.Reader) (KeyBundle, error) {
return CreateKeyBundleWithKeyGenerator(keyType, keyBits, randReader, generatePrivateKey)
}

// CreateKeyBundleWithKeyGenerator create a KeyBundle struct object which includes
// a generated key of keyType with keyBits leveraging the randomness from randReader and
// delegates the actual key generation to keyGenerator
func CreateKeyBundleWithKeyGenerator(keyType string, keyBits int, randReader io.Reader, keyGenerator KeyGenerator) (KeyBundle, error) {
result := KeyBundle{}
if err := keyGenerator(keyType, keyBits, &result, randReader); err != nil {
return result, err
}
return result, nil
}
Loading