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

improvement: add signature_bits field to CA and signers #11245

Merged
merged 1 commit into from Sep 10, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions builtin/logical/pki/backend_test.go
Expand Up @@ -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{}
Expand Down
6 changes: 6 additions & 0 deletions builtin/logical/pki/ca_util.go
Expand Up @@ -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,
Expand All @@ -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
}
1 change: 1 addition & 0 deletions builtin/logical/pki/cert_util.go
Expand Up @@ -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),
Expand Down
12 changes: 12 additions & 0 deletions builtin/logical/pki/fields.go
Expand Up @@ -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",
Expand Down
17 changes: 16 additions & 1 deletion builtin/logical/pki/path_roles.go
Expand Up @@ -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
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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"`
Expand Down Expand Up @@ -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,
Expand Down
3 changes: 3 additions & 0 deletions changelog/11245.txt
@@ -0,0 +1,3 @@
```release-note:improvement
pki: adds signature_bits field to customize signature algorithm on CAs and certs signed by Vault
```
65 changes: 59 additions & 6 deletions sdk/helper/certutil/helpers.go
Expand Up @@ -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":
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
1 change: 1 addition & 0 deletions sdk/helper/certutil/types.go
Expand Up @@ -677,6 +677,7 @@ type CreationParameters struct {
ExtKeyUsageOIDs []string
PolicyIdentifiers []string
BasicConstraintsValidForNonCA bool
SignatureBits int

// Only used when signing a CA cert
UseCSRValues bool
Expand Down