improvement: add signature_bits field to CA and signers (#11245)
This change adds the ability to set the signature algorithm of the CAs that Vault generates and any certificates it signs. This is a potentially useful stepping stone for a SHA3 transition down the line. Summary: * Adds the field "signature_bits" to CA and Sign endpoints * Adds support for SHA256, SHA384 and SHA512 signatures on EC and RSA keytypes.
This commit is contained in:
parent
22c9be3835
commit
fa1611f427
|
@ -683,6 +683,7 @@ func generateRoleSteps(t *testing.T, useCSRs bool) []logicaltest.TestStep {
|
|||
KeyType: "rsa",
|
||||
KeyBits: 2048,
|
||||
RequireCN: true,
|
||||
SignatureBits: 256,
|
||||
}
|
||||
issueVals := certutil.IssueData{}
|
||||
ret := []logicaltest.TestStep{}
|
||||
|
|
|
@ -33,6 +33,7 @@ func (b *backend) getGenerationParams(
|
|||
TTL: time.Duration(data.Get("ttl").(int)) * time.Second,
|
||||
KeyType: data.Get("key_type").(string),
|
||||
KeyBits: data.Get("key_bits").(int),
|
||||
SignatureBits: data.Get("signature_bits").(int),
|
||||
AllowLocalhost: true,
|
||||
AllowAnyName: true,
|
||||
AllowIPSANs: true,
|
||||
|
@ -58,5 +59,10 @@ func (b *backend) getGenerationParams(
|
|||
errorResp = logical.ErrorResponse(err.Error())
|
||||
}
|
||||
|
||||
if err := certutil.ValidateSignatureLength(role.SignatureBits); err != nil {
|
||||
errorResp = logical.ErrorResponse(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1060,6 +1060,7 @@ func generateCreationBundle(b *backend, data *inputBundle, caSign *certutil.CAIn
|
|||
OtherSANs: otherSANs,
|
||||
KeyType: data.role.KeyType,
|
||||
KeyBits: data.role.KeyBits,
|
||||
SignatureBits: data.role.SignatureBits,
|
||||
NotAfter: notAfter,
|
||||
KeyUsage: x509.KeyUsage(parseKeyUsages(data.role.KeyUsage)),
|
||||
ExtKeyUsage: parseExtKeyUsages(data.role),
|
||||
|
|
|
@ -254,6 +254,18 @@ the key_type.`,
|
|||
},
|
||||
}
|
||||
|
||||
fields["signature_bits"] = &framework.FieldSchema{
|
||||
Type: framework.TypeInt,
|
||||
Default: 256,
|
||||
Description: `The number of bits to use in the signature
|
||||
algorithm. Defaults to 256 for SHA256.
|
||||
Set to 384 for SHA384 and 512 for SHA512.
|
||||
`,
|
||||
DisplayAttrs: &framework.DisplayAttributes{
|
||||
Value: 256,
|
||||
},
|
||||
}
|
||||
|
||||
fields["key_type"] = &framework.FieldSchema{
|
||||
Type: framework.TypeString,
|
||||
Default: "rsa",
|
||||
|
|
|
@ -205,7 +205,15 @@ certainly want to change this if you adjust
|
|||
the key_type.`,
|
||||
},
|
||||
|
||||
"key_usage": {
|
||||
"signature_bits": &framework.FieldSchema{
|
||||
Type: framework.TypeInt,
|
||||
Default: 256,
|
||||
Description: `The number of bits to use in the signature
|
||||
algorithm. Defaults to 256 for SHA256.
|
||||
Set to 384 for SHA384 and 512 for SHA512.`,
|
||||
},
|
||||
|
||||
"key_usage": &framework.FieldSchema{
|
||||
Type: framework.TypeCommaStringSlice,
|
||||
Default: []string{"DigitalSignature", "KeyAgreement", "KeyEncipherment"},
|
||||
Description: `A comma-separated string or list of key usages (not extended
|
||||
|
@ -559,6 +567,7 @@ func (b *backend) pathRoleCreate(ctx context.Context, req *logical.Request, data
|
|||
EmailProtectionFlag: data.Get("email_protection_flag").(bool),
|
||||
KeyType: data.Get("key_type").(string),
|
||||
KeyBits: data.Get("key_bits").(int),
|
||||
SignatureBits: data.Get("signature_bits").(int),
|
||||
UseCSRCommonName: data.Get("use_csr_common_name").(bool),
|
||||
UseCSRSANs: data.Get("use_csr_sans").(bool),
|
||||
KeyUsage: data.Get("key_usage").([]string),
|
||||
|
@ -613,6 +622,10 @@ func (b *backend) pathRoleCreate(ctx context.Context, req *logical.Request, data
|
|||
return logical.ErrorResponse(err.Error()), nil
|
||||
}
|
||||
|
||||
if err := certutil.ValidateSignatureLength(entry.SignatureBits); err != nil {
|
||||
return logical.ErrorResponse(err.Error()), nil
|
||||
}
|
||||
|
||||
if len(entry.ExtKeyUsageOIDs) > 0 {
|
||||
for _, oidstr := range entry.ExtKeyUsageOIDs {
|
||||
_, err := certutil.StringToOid(oidstr)
|
||||
|
@ -750,6 +763,7 @@ type roleEntry struct {
|
|||
UseCSRSANs bool `json:"use_csr_sans" mapstructure:"use_csr_sans"`
|
||||
KeyType string `json:"key_type" mapstructure:"key_type"`
|
||||
KeyBits int `json:"key_bits" mapstructure:"key_bits"`
|
||||
SignatureBits int `json:"signature_bits" mapstructure:"signature_bits"`
|
||||
MaxPathLength *int `json:",omitempty" mapstructure:"max_path_length"`
|
||||
KeyUsageOld string `json:"key_usage,omitempty"`
|
||||
KeyUsage []string `json:"key_usage_list" mapstructure:"key_usage"`
|
||||
|
@ -800,6 +814,7 @@ func (r *roleEntry) ToResponseData() map[string]interface{} {
|
|||
"use_csr_sans": r.UseCSRSANs,
|
||||
"key_type": r.KeyType,
|
||||
"key_bits": r.KeyBits,
|
||||
"signature_bits": r.SignatureBits,
|
||||
"key_usage": r.KeyUsage,
|
||||
"ext_key_usage": r.ExtKeyUsage,
|
||||
"ext_key_usage_oids": r.ExtKeyUsageOIDs,
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
```release-note:improvement
|
||||
pki: adds signature_bits field to customize signature algorithm on CAs and certs signed by Vault
|
||||
```
|
|
@ -490,6 +490,17 @@ func StringToOid(in string) (asn1.ObjectIdentifier, error) {
|
|||
return asn1.ObjectIdentifier(ret), nil
|
||||
}
|
||||
|
||||
func ValidateSignatureLength(keyBits int) error {
|
||||
switch keyBits {
|
||||
case 256:
|
||||
case 384:
|
||||
case 512:
|
||||
default:
|
||||
return fmt.Errorf("unsupported signature algorithm: %d", keyBits)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ValidateKeyTypeLength(keyType string, keyBits int) error {
|
||||
switch keyType {
|
||||
case "rsa":
|
||||
|
@ -598,9 +609,23 @@ func createCertificate(data *CreationBundle, randReader io.Reader) (*ParsedCertB
|
|||
if data.SigningBundle != nil {
|
||||
switch data.SigningBundle.PrivateKeyType {
|
||||
case RSAPrivateKey:
|
||||
certTemplate.SignatureAlgorithm = x509.SHA256WithRSA
|
||||
switch data.Params.SignatureBits {
|
||||
case 256:
|
||||
certTemplate.SignatureAlgorithm = x509.SHA256WithRSA
|
||||
case 384:
|
||||
certTemplate.SignatureAlgorithm = x509.SHA384WithRSA
|
||||
case 512:
|
||||
certTemplate.SignatureAlgorithm = x509.SHA512WithRSA
|
||||
}
|
||||
case ECPrivateKey:
|
||||
certTemplate.SignatureAlgorithm = x509.ECDSAWithSHA256
|
||||
switch data.Params.SignatureBits {
|
||||
case 256:
|
||||
certTemplate.SignatureAlgorithm = x509.ECDSAWithSHA256
|
||||
case 384:
|
||||
certTemplate.SignatureAlgorithm = x509.ECDSAWithSHA384
|
||||
case 512:
|
||||
certTemplate.SignatureAlgorithm = x509.ECDSAWithSHA512
|
||||
}
|
||||
}
|
||||
|
||||
caCert := data.SigningBundle.Certificate
|
||||
|
@ -618,9 +643,23 @@ func createCertificate(data *CreationBundle, randReader io.Reader) (*ParsedCertB
|
|||
|
||||
switch data.Params.KeyType {
|
||||
case "rsa":
|
||||
certTemplate.SignatureAlgorithm = x509.SHA256WithRSA
|
||||
switch data.Params.SignatureBits {
|
||||
case 256:
|
||||
certTemplate.SignatureAlgorithm = x509.SHA256WithRSA
|
||||
case 384:
|
||||
certTemplate.SignatureAlgorithm = x509.SHA384WithRSA
|
||||
case 512:
|
||||
certTemplate.SignatureAlgorithm = x509.SHA512WithRSA
|
||||
}
|
||||
case "ec":
|
||||
certTemplate.SignatureAlgorithm = x509.ECDSAWithSHA256
|
||||
switch data.Params.SignatureBits {
|
||||
case 256:
|
||||
certTemplate.SignatureAlgorithm = x509.ECDSAWithSHA256
|
||||
case 384:
|
||||
certTemplate.SignatureAlgorithm = x509.ECDSAWithSHA384
|
||||
case 512:
|
||||
certTemplate.SignatureAlgorithm = x509.ECDSAWithSHA512
|
||||
}
|
||||
}
|
||||
|
||||
certTemplate.AuthorityKeyId = subjKeyID
|
||||
|
@ -791,9 +830,23 @@ func signCertificate(data *CreationBundle, randReader io.Reader) (*ParsedCertBun
|
|||
|
||||
switch data.SigningBundle.PrivateKeyType {
|
||||
case RSAPrivateKey:
|
||||
certTemplate.SignatureAlgorithm = x509.SHA256WithRSA
|
||||
switch data.Params.SignatureBits {
|
||||
case 256:
|
||||
certTemplate.SignatureAlgorithm = x509.SHA256WithRSA
|
||||
case 384:
|
||||
certTemplate.SignatureAlgorithm = x509.SHA384WithRSA
|
||||
case 512:
|
||||
certTemplate.SignatureAlgorithm = x509.SHA512WithRSA
|
||||
}
|
||||
case ECPrivateKey:
|
||||
certTemplate.SignatureAlgorithm = x509.ECDSAWithSHA256
|
||||
switch data.Params.SignatureBits {
|
||||
case 256:
|
||||
certTemplate.SignatureAlgorithm = x509.ECDSAWithSHA256
|
||||
case 384:
|
||||
certTemplate.SignatureAlgorithm = x509.ECDSAWithSHA384
|
||||
case 512:
|
||||
certTemplate.SignatureAlgorithm = x509.ECDSAWithSHA512
|
||||
}
|
||||
}
|
||||
|
||||
if data.Params.UseCSRValues {
|
||||
|
|
|
@ -677,6 +677,7 @@ type CreationParameters struct {
|
|||
ExtKeyUsageOIDs []string
|
||||
PolicyIdentifiers []string
|
||||
BasicConstraintsValidForNonCA bool
|
||||
SignatureBits int
|
||||
|
||||
// Only used when signing a CA cert
|
||||
UseCSRValues bool
|
||||
|
|
Loading…
Reference in New Issue