From eeb4029eb146a91f12f91844addb9ccdb21d26d5 Mon Sep 17 00:00:00 2001 From: Alexander Scheel Date: Thu, 23 Jun 2022 14:07:27 -0400 Subject: [PATCH] Add signature_bits to sign-intermediate, sign-verbatim (#16124) * Add signature_bits to sign-intermediate This endpoint was lacking the signature_bits field like all the other endpoints. Notably, in #15478, the ability to customize the intermediate CSR's signature bits was removed without checking for the ability to customize the final (root-signed) intermediate certificate's value. This adds in that missing ability, bringing us parity with root generation and role-based signing. Signed-off-by: Alexander Scheel * Add signature_bits to sign-verbatim This endpoint was also lacking the signature_bits field, preventing other signature hash functions from being utilized here. Signed-off-by: Alexander Scheel * Add changelog Signed-off-by: Alexander Scheel --- builtin/logical/pki/backend_test.go | 27 +++++++++++++++--------- builtin/logical/pki/path_issue_sign.go | 13 ++++++++++++ builtin/logical/pki/path_root.go | 1 + builtin/logical/pki/path_sign_issuers.go | 12 +++++++++++ changelog/16124.txt | 3 +++ website/content/api-docs/secret/pki.mdx | 20 ++++++++++++++++++ 6 files changed, 66 insertions(+), 10 deletions(-) create mode 100644 changelog/16124.txt diff --git a/builtin/logical/pki/backend_test.go b/builtin/logical/pki/backend_test.go index c5778f74c..86ec12130 100644 --- a/builtin/logical/pki/backend_test.go +++ b/builtin/logical/pki/backend_test.go @@ -574,6 +574,7 @@ func generateURLSteps(t *testing.T, caCert, caKey string, intdata, reqdata map[s Data: map[string]interface{}{ "common_name": "intermediate.cert.com", "csr": csrPem2048, + "signature_bits": 512, "format": "der", "not_before_duration": "2h", }, @@ -597,13 +598,15 @@ func generateURLSteps(t *testing.T, caCert, caKey string, intdata, reqdata map[s switch { case !reflect.DeepEqual(expected.IssuingCertificates, cert.IssuingCertificateURL): - return fmt.Errorf("expected\n%#v\ngot\n%#v\n", expected.IssuingCertificates, cert.IssuingCertificateURL) + return fmt.Errorf("IssuingCertificateURL:\nexpected\n%#v\ngot\n%#v\n", expected.IssuingCertificates, cert.IssuingCertificateURL) case !reflect.DeepEqual(expected.CRLDistributionPoints, cert.CRLDistributionPoints): - return fmt.Errorf("expected\n%#v\ngot\n%#v\n", expected.CRLDistributionPoints, cert.CRLDistributionPoints) + return fmt.Errorf("CRLDistributionPoints:\nexpected\n%#v\ngot\n%#v\n", expected.CRLDistributionPoints, cert.CRLDistributionPoints) case !reflect.DeepEqual(expected.OCSPServers, cert.OCSPServer): - return fmt.Errorf("expected\n%#v\ngot\n%#v\n", expected.OCSPServers, cert.OCSPServer) + return fmt.Errorf("OCSPServer:\nexpected\n%#v\ngot\n%#v\n", expected.OCSPServers, cert.OCSPServer) case !reflect.DeepEqual([]string{"intermediate.cert.com"}, cert.DNSNames): - return fmt.Errorf("expected\n%#v\ngot\n%#v\n", []string{"intermediate.cert.com"}, cert.DNSNames) + return fmt.Errorf("DNSNames\nexpected\n%#v\ngot\n%#v\n", []string{"intermediate.cert.com"}, cert.DNSNames) + case !reflect.DeepEqual(x509.SHA512WithRSA, cert.SignatureAlgorithm): + return fmt.Errorf("Signature Algorithm:\nexpected\n%#v\ngot\n%#v\n", x509.SHA512WithRSA, cert.SignatureAlgorithm) } if math.Abs(float64(time.Now().Add(-2*time.Hour).Unix()-cert.NotBefore.Unix())) > 10 { @@ -2129,13 +2132,17 @@ func runTestSignVerbatim(t *testing.T, keyType string) { t.Fatal("pem csr is empty") } + signVerbatimData := map[string]interface{}{ + "csr": pemCSR, + } + if keyType == "rsa" { + signVerbatimData["signature_bits"] = 512 + } resp, err = b.HandleRequest(context.Background(), &logical.Request{ - Operation: logical.UpdateOperation, - Path: "sign-verbatim", - Storage: storage, - Data: map[string]interface{}{ - "csr": pemCSR, - }, + Operation: logical.UpdateOperation, + Path: "sign-verbatim", + Storage: storage, + Data: signVerbatimData, MountPoint: "pki/", }) if resp != nil && resp.IsError() { diff --git a/builtin/logical/pki/path_issue_sign.go b/builtin/logical/pki/path_issue_sign.go index 6f2f7cf51..8aa1f5300 100644 --- a/builtin/logical/pki/path_issue_sign.go +++ b/builtin/logical/pki/path_issue_sign.go @@ -139,6 +139,18 @@ this value to an empty list.`, Description: `A comma-separated string or list of extended key usage oids.`, } + ret.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, + }, + } + return ret } @@ -198,6 +210,7 @@ func (b *backend) pathSignVerbatim(ctx context.Context, req *logical.Request, da KeyUsage: data.Get("key_usage").([]string), ExtKeyUsage: data.Get("ext_key_usage").([]string), ExtKeyUsageOIDs: data.Get("ext_key_usage_oids").([]string), + SignatureBits: data.Get("signature_bits").(int), } *entry.AllowWildcardCertificates = true diff --git a/builtin/logical/pki/path_root.go b/builtin/logical/pki/path_root.go index dd42c457a..e5ce5b50f 100644 --- a/builtin/logical/pki/path_root.go +++ b/builtin/logical/pki/path_root.go @@ -286,6 +286,7 @@ func (b *backend) pathIssuerSignIntermediate(ctx context.Context, req *logical.R AllowWildcardCertificates: new(bool), EnforceHostnames: false, KeyType: "any", + SignatureBits: data.Get("signature_bits").(int), AllowedOtherSANs: []string{"*"}, AllowedSerialNumbers: []string{"*"}, AllowedURISANs: []string{"*"}, diff --git a/builtin/logical/pki/path_sign_issuers.go b/builtin/logical/pki/path_sign_issuers.go index 96b766606..75e2d7395 100644 --- a/builtin/logical/pki/path_sign_issuers.go +++ b/builtin/logical/pki/path_sign_issuers.go @@ -55,6 +55,18 @@ the non-repudiation flag; 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, + }, + } + return path } diff --git a/changelog/16124.txt b/changelog/16124.txt new file mode 100644 index 000000000..38eca2af9 --- /dev/null +++ b/changelog/16124.txt @@ -0,0 +1,3 @@ +```release-note:improvement +secret/pki: Add signature_bits to sign-intermediate, sign-verbatim endpoints +``` diff --git a/website/content/api-docs/secret/pki.mdx b/website/content/api-docs/secret/pki.mdx index 88f8e029a..a30c42f19 100644 --- a/website/content/api-docs/secret/pki.mdx +++ b/website/content/api-docs/secret/pki.mdx @@ -561,6 +561,16 @@ when signing an externally-owned intermediate. `YYYY-MM-ddTHH:MM:SSZ`. Supports the Y10K end date for IEEE 802.1AR-2018 standard devices, `9999-12-31T23:59:59Z`. +- `signature_bits` `(int: 0)` - Specifies 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). + +~> **Note**: ECDSA and Ed25519 issuers do not follow configuration of the + `signature_bits` value; only RSA issuers will change signature types + based on this parameter. + #### Sample Payload ```json @@ -741,6 +751,16 @@ have access.** `YYYY-MM-ddTHH:MM:SSZ`. Supports the Y10K end date for IEEE 802.1AR-2018 standard devices, `9999-12-31T23:59:59Z`. +- `signature_bits` `(int: 0)` - Specifies 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). + +~> **Note**: ECDSA and Ed25519 issuers do not follow configuration of the + `signature_bits` value; only RSA issuers will change signature types + based on this parameter. + #### Sample Payload ```json