open-vault/builtin/logical/pki/path_sign_issuers.go
Alexander Scheel 8acbf7f480
Add PSS support to PKI Secrets Engine (#16519)
* Add PSS signature support to Vault PKI engine

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Use issuer's RevocationSigAlg for CRL signing

We introduce a new parameter on issuers, revocation_signature_algorithm
to control the signature algorithm used during CRL signing. This is
because the SignatureAlgorithm value from the certificate itself is
incorrect for this purpose: a RSA root could sign an ECDSA intermediate
with say, SHA256WithRSA, but when the intermediate goes to sign a CRL,
it must use ECDSAWithSHA256 or equivalent instead of SHA256WithRSA. When
coupled with support for PSS-only keys, allowing the user to set the
signature algorithm value as desired seems like the best approach.

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Add use_pss, revocation_signature_algorithm docs

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Add PSS to signature role issuance test matrix

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Add changelog

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Allow roots to self-identify revocation alg

When using PSS support with a managed key, sometimes the underlying
device will not support PKCS#1v1.5 signatures. This results in CRL
building failing, unless we update the entry's signature algorithm
prior to building the CRL for the new root.

With a RSA-type key and use_pss=true, we use the signature bits value to
decide which hash function to use for PSS support.

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Add clearer error message on failed import

When CRL building fails during cert/key import, due to PSS failures,
give a better indication to the user that import succeeded its just CRL
building that failed. This tells them the parameter to adjust on the
issuer and warns that CRL building will fail until this is fixed.

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Add case insensitive SigAlgo matching

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Convert UsePSS back to regular bool

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Refactor PSS->certTemplate into helper function

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Proper string output on rev_sig_alg display

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>

* Copy root's SignatureAlgorithm for CRL building

Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
2022-08-03 12:42:24 -04:00

176 lines
5.9 KiB
Go

package pki
import (
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/logical"
)
func pathIssuerSignIntermediate(b *backend) *framework.Path {
pattern := "issuer/" + framework.GenericNameRegex(issuerRefParam) + "/sign-intermediate"
return buildPathIssuerSignIntermediateRaw(b, pattern)
}
func pathSignIntermediate(b *backend) *framework.Path {
pattern := "root/sign-intermediate"
return buildPathIssuerSignIntermediateRaw(b, pattern)
}
func buildPathIssuerSignIntermediateRaw(b *backend, pattern string) *framework.Path {
fields := addIssuerRefField(map[string]*framework.FieldSchema{})
path := &framework.Path{
Pattern: pattern,
Fields: fields,
Operations: map[logical.Operation]framework.OperationHandler{
logical.UpdateOperation: &framework.PathOperation{
Callback: b.pathIssuerSignIntermediate,
},
},
HelpSynopsis: pathIssuerSignIntermediateHelpSyn,
HelpDescription: pathIssuerSignIntermediateHelpDesc,
}
path.Fields = addCACommonFields(path.Fields)
path.Fields = addCAIssueFields(path.Fields)
path.Fields["csr"] = &framework.FieldSchema{
Type: framework.TypeString,
Default: "",
Description: `PEM-format CSR to be signed.`,
}
path.Fields["use_csr_values"] = &framework.FieldSchema{
Type: framework.TypeBool,
Default: false,
Description: `If true, then:
1) Subject information, including names and alternate
names, will be preserved from the CSR rather than
using values provided in the other parameters to
this path;
2) Any key usages requested in the CSR will be
added to the basic set of key usages used for CA
certs signed by this path; for instance,
the non-repudiation flag;
3) Extensions requested in the CSR will be copied
into the issued certificate.`,
}
fields["signature_bits"] = &framework.FieldSchema{
Type: framework.TypeInt,
Default: 0,
Description: `The number of bits to use in the signature
algorithm; accepts 256 for SHA-2-256, 384 for SHA-2-384, and 512 for
SHA-2-512. Defaults to 0 to automatically detect based on key length
(SHA-2-256 for RSA keys, and matching the curve size for NIST P-Curves).`,
DisplayAttrs: &framework.DisplayAttributes{
Value: 0,
},
}
fields["skid"] = &framework.FieldSchema{
Type: framework.TypeString,
Default: "",
Description: `Value for the Subject Key Identifier field
(RFC 5280 Section 4.2.1.2). This value should ONLY be used when
cross-signing to mimic the existing certificate's SKID value; this
is necessary to allow certain TLS implementations (such as OpenSSL)
which use SKID/AKID matches in chain building to restrict possible
valid chains.
Specified as a string in hex format. Default is empty, allowing
Vault to automatically calculate the SKID according to method one
in the above RFC section.`,
DisplayAttrs: &framework.DisplayAttributes{
Value: "",
},
}
fields["use_pss"] = &framework.FieldSchema{
Type: framework.TypeBool,
Default: false,
Description: `Whether or not to use PSS signatures when using a
RSA key-type issuer. Defaults to false.`,
}
return path
}
const (
pathIssuerSignIntermediateHelpSyn = `Issue an intermediate CA certificate based on the provided CSR.`
pathIssuerSignIntermediateHelpDesc = `
This API endpoint allows for signing the specified CSR, adding to it a basic
constraint for IsCA=True. This allows the issued certificate to issue its own
leaf certificates.
Note that the resulting certificate is not imported as an issuer in this PKI
mount. This means that you can use the resulting certificate in another Vault
PKI mount point or to issue an external intermediate (e.g., for use with
another X.509 CA).
See the API documentation for more information about required parameters.
`
)
func pathIssuerSignSelfIssued(b *backend) *framework.Path {
pattern := "issuer/" + framework.GenericNameRegex(issuerRefParam) + "/sign-self-issued"
return buildPathIssuerSignSelfIssued(b, pattern)
}
func pathSignSelfIssued(b *backend) *framework.Path {
pattern := "root/sign-self-issued"
return buildPathIssuerSignSelfIssued(b, pattern)
}
func buildPathIssuerSignSelfIssued(b *backend, pattern string) *framework.Path {
fields := map[string]*framework.FieldSchema{
"certificate": {
Type: framework.TypeString,
Description: `PEM-format self-issued certificate to be signed.`,
},
"require_matching_certificate_algorithms": {
Type: framework.TypeBool,
Default: false,
Description: `If true, require the public key algorithm of the signer to match that of the self issued certificate.`,
},
}
fields = addIssuerRefField(fields)
path := &framework.Path{
Pattern: pattern,
Fields: fields,
Operations: map[logical.Operation]framework.OperationHandler{
logical.UpdateOperation: &framework.PathOperation{
Callback: b.pathIssuerSignSelfIssued,
},
},
HelpSynopsis: pathIssuerSignSelfIssuedHelpSyn,
HelpDescription: pathIssuerSignSelfIssuedHelpDesc,
}
return path
}
const (
pathIssuerSignSelfIssuedHelpSyn = `Re-issue a self-signed certificate based on the provided certificate.`
pathIssuerSignSelfIssuedHelpDesc = `
This API endpoint allows for signing the specified self-signed certificate,
effectively allowing cross-signing of external root CAs. This allows for an
alternative validation path, chaining back through this PKI mount. This
endpoint is also useful in a rolling-root scenario, allowing devices to trust
and validate later (or earlier) root certificates and their issued leaves.
Usually the sign-intermediate operation is preferred to this operation.
Note that this is a very privileged operation and should be extremely
restricted in terms of who is allowed to use it. All values will be taken
directly from the incoming certificate and only verification that it is
self-issued will be performed.
Configured URLs for CRLs/OCSP/etc. will be copied over and the issuer will
be this mount's CA cert. Other than that, all other values will be used
verbatim from the given certificate.
See the API documentation for more information about required parameters.
`
)