Skip to content

Commit

Permalink
Merge pull request #412 from Venafi/modern-encryption-for-pkcs12
Browse files Browse the repository at this point in the history
Use PBES2 with PBKDF2 and AES-256-CBC for PKCS#12 keystores
  • Loading branch information
luispresuelVenafi authored Dec 20, 2023
2 parents c1cae18 + ccb55c4 commit d5b37ae
Show file tree
Hide file tree
Showing 18 changed files with 587 additions and 292 deletions.
194 changes: 97 additions & 97 deletions README-CLI-CLOUD.md

Large diffs are not rendered by default.

64 changes: 32 additions & 32 deletions README-CLI-FIREFLY.md

Large diffs are not rendered by default.

276 changes: 138 additions & 138 deletions README-CLI-PLATFORM.md

Large diffs are not rendered by default.

35 changes: 35 additions & 0 deletions aruba/features/format/pkcs12.feature
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,26 @@ Feature: PKCS#12 format output
| endpoint |
| Cloud |

Scenario Outline: where all objects are written to one PKCS#12 legacy archive with key password
When I enroll random certificate in <endpoint> with -format legacy-pkcs12 -file all.p12 -key-password newPassw0rd!
Then the exit status should be 0
And "all.p12" should be PKCS#12 archive in legacy mode with password "newPassw0rd!"

@FAKE
Examples:
| endpoint |
| test-mode |

@TPP
Examples:
| endpoint |
| TPP |

@VAAS
Examples:
| endpoint |
| Cloud |

Scenario Outline: where it outputs error when trying to pickup local-generated certificate and output it in PKCS#12 format
When I enroll random certificate using <endpoint> with -no-prompt -no-pickup
And I retrieve the certificate using <endpoint> using the same Pickup ID with -timeout 180 -no-prompt -file all.p12 -format pkcs12
Expand Down Expand Up @@ -159,6 +179,21 @@ Feature: PKCS#12 format output
| endpoint |
| TPP |

Scenario Outline: where it pickups up service-generated certificate and outputs it in PKCS#12 legacy format
When I enroll random certificate using <endpoint> with -no-prompt -no-pickup -csr service
And I retrieve the certificate using <endpoint> using the same Pickup ID with -timeout 180 -key-password newPassw0rd! -file all.p12 -format legacy-pkcs12
And "all.p12" should be PKCS#12 archive in legacy mode with password "newPassw0rd!"

@FAKE
Examples:
| endpoint |
| test-mode |

@TPP
Examples:
| endpoint |
| TPP |

# TODO: Now VaaS supports CSR, but we need to verify this behavior for this test
# @VAAS
# Examples:
Expand Down
2 changes: 1 addition & 1 deletion aruba/features/playbook/steps_definitions/my_steps.rb
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@
cert_path = Dir.pwd + $path_separator + $temp_path + $path_separator + filename

steps %{
Then I try to run `openssl pkcs12 -in "#{cert_path}" -legacy -passin pass:#{password} -noout`
Then I try to run `openssl pkcs12 -in "#{cert_path}" -passin pass:#{password} -noout`
And the exit status should be 0
}
end
Expand Down
20 changes: 20 additions & 0 deletions aruba/features/renew/renew-with-csr-local.feature
Original file line number Diff line number Diff line change
Expand Up @@ -84,5 +84,25 @@ Feature: renew action with -csr local (default) option
| endpoint |
| Cloud |

Scenario Outline: renew certificate using -id using `-csr local` with PKCS12 legacy flag
Given I enroll random certificate using <endpoint> with -key-password Passcode123! -key-file k.pem -cert-file c.pem -csr local
And it should write private key to the file "k.pem"
And it should write certificate to the file "c.pem"
And it should output Pickup ID
And I decode certificate from file "c.pem"
Then I renew the certificate in <endpoint> using the same Pickup ID with flags -key-password Passcode123! -file all.p12 -format legacy-pkcs12
And it should retrieve certificate
And "all.p12" should be PKCS#12 archive in legacy mode with password "Passcode123!"

@TPP
Examples:
| endpoint |
| TPP |

@VAAS
Examples:
| endpoint |
| Cloud |

Scenario: where renewed certificate may have new -key-size, -san-dns
Given I implement that later
9 changes: 9 additions & 0 deletions aruba/features/renew/renew-with-csr-service.feature
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,12 @@ Feature: renew action with `-csr service` option
When I renew the certificate in TPP using the same Pickup ID with flags -csr service -key-password Passcode123! -file all.p12 -format pkcs12
Then it should retrieve certificate
And "all.p12" should be PKCS#12 archive with password "Passcode123!"

Scenario: renew service-generated-CSR certificate in TPP with `-csr service` option with PKCS12 legacy flag
Given I enroll random certificate using TPP with -csr service -key-password Passcode123! -key-file k.pem -cert-file c.pem
And it should write private key to the file "k.pem"
And it should write certificate to the file "c.pem"
And it should output Pickup ID
When I renew the certificate in TPP using the same Pickup ID with flags -csr service -key-password Passcode123! -file all.p12 -format legacy-pkcs12
Then it should retrieve certificate
And "all.p12" should be PKCS#12 archive in legacy mode with password "Passcode123!"
13 changes: 13 additions & 0 deletions aruba/features/step_definitions/openssl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,19 @@
end

When(/^"([^"]*)" should be PKCS#12 archive with password "([^"]*)"$/) do |filename, password|
steps %{
Then I try to run `openssl pkcs12 -in "#{filename}" -passin pass:#{password} -noout`
And the exit status should be 0
}
# -nokeys Don't output private keys
# -nocerts Don't output certificates
# -clcerts Only output client certificates
# -cacerts Only output CA certificates
# -noout Don't output anything, just verify
# -nodes Don't encrypt private keys
end

When(/^"([^"]*)" should be PKCS#12 archive in legacy mode with password "([^"]*)"$/) do |filename, password|
steps %{
Then I try to run `openssl pkcs12 -in "#{filename}" -legacy -passin pass:#{password} -noout`
And the exit status should be 0
Expand Down
16 changes: 8 additions & 8 deletions cmd/vcert/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ func doCommandEnroll1(c *cli.Context) error {
req.KeyPassword = flags.keyPassword

// Creates a temporary password for service generated csr if following validation is fulfilled.
// Analyzing validation assuming that pkcs12, jks and service flags are true
// Analyzing validation assuming that pkcs12, legacy-pkcs12, jks and service flags are true
//+-------------+----------------+----------------------------------------------------------------------+
//| --no-prompt | --key-password | What happens in validation? |
//|-------------|----------------|----------------------------------------------------------------------|
Expand All @@ -385,7 +385,7 @@ func doCommandEnroll1(c *cli.Context) error {
//| false | false |VCert will prompt to enter password and process will not be completed |
//| | |until password is provided by user |
//+-------------+----------------+----------------------------------------------------------------------+
if flags.noPrompt && flags.keyPassword == "" && flags.format != "pkcs12" && flags.format != "jks" && flags.csrOption == "service" {
if flags.noPrompt && flags.keyPassword == "" && flags.format != P12Format && flags.format != LegacyP12Format && flags.format != JKSFormat && flags.csrOption == "service" {
flags.keyPassword = fmt.Sprintf("t%d-%s.tem.pwd", time.Now().Unix(), randRunes(4))
req.KeyPassword = flags.keyPassword
passwordAutogenerated = true
Expand All @@ -408,7 +408,7 @@ func doCommandEnroll1(c *cli.Context) error {
}
}

if (pcc.PrivateKey != "" && (flags.format == Pkcs12 || flags.format == JKSFormat)) || (flags.format == util.LegacyPem && flags.csrOption == "service") || flags.noPrompt && passwordAutogenerated {
if (pcc.PrivateKey != "" && (flags.format == P12Format || flags.format == LegacyP12Format || flags.format == JKSFormat)) || (flags.format == util.LegacyPem && flags.csrOption == "service") || flags.noPrompt && passwordAutogenerated {
privKey, err := util.DecryptPkcs8PrivateKey(pcc.PrivateKey, flags.keyPassword)
if err != nil {
if err.Error() == "pkcs8: only PBES2 supported" && connector.GetType() == endpoint.ConnectorTypeTPP {
Expand Down Expand Up @@ -934,7 +934,7 @@ func doCommandPickup1(c *cli.Context) error {

isServiceGen := IsCSRServiceVaaSGenerated(c.Command.Name)
wasPasswordEmpty := false
if flags.noPrompt && flags.keyPassword == "" && flags.format != "pkcs12" && flags.format != "jks" && (isServiceGen || isTppConnector(c.Command.Name)) {
if flags.noPrompt && flags.keyPassword == "" && flags.format != P12Format && flags.format != LegacyP12Format && flags.format != JKSFormat && (isServiceGen || isTppConnector(c.Command.Name)) {
flags.keyPassword = fmt.Sprintf("t%d-%s.tem.pwd", time.Now().Unix(), randRunes(4))
wasPasswordEmpty = true
}
Expand Down Expand Up @@ -998,7 +998,7 @@ func doCommandPickup1(c *cli.Context) error {
}
logf("Successfully retrieved request for %s", flags.pickupID)

if pcc.PrivateKey != "" && (flags.format == Pkcs12 || flags.format == JKSFormat || flags.format == util.LegacyPem) || (flags.noPrompt && wasPasswordEmpty && pcc.PrivateKey != "") {
if pcc.PrivateKey != "" && (flags.format == P12Format || flags.format == LegacyP12Format || flags.format == JKSFormat || flags.format == util.LegacyPem) || (flags.noPrompt && wasPasswordEmpty && pcc.PrivateKey != "") {
privKey, err := util.DecryptPkcs8PrivateKey(pcc.PrivateKey, flags.keyPassword)
if err != nil {
if err.Error() == "pkcs8: only PBES2 supported" && connector.GetType() == endpoint.ConnectorTypeTPP {
Expand Down Expand Up @@ -1421,7 +1421,7 @@ func doCommandRenew1(c *cli.Context) error {
req.ChainOption = certificate.ChainOptionFromString(flags.chainOption)
req.KeyPassword = flags.keyPassword

if flags.noPrompt && flags.keyPassword == "" && flags.format != "pkcs12" && flags.format != "jks" && flags.csrOption == "service" {
if flags.noPrompt && flags.keyPassword == "" && flags.format != P12Format && flags.format != LegacyP12Format && flags.format != JKSFormat && flags.csrOption == "service" {
flags.keyPassword = fmt.Sprintf("t%d-%s.tem.pwd", time.Now().Unix(), randRunes(4))
req.KeyPassword = flags.keyPassword
passwordAutogenerated = true
Expand All @@ -1444,7 +1444,7 @@ func doCommandRenew1(c *cli.Context) error {
}

// Creates a temporary password for service generated csr if following validation is fulfilled.
// Analyzing validation assuming that pkcs12, jks and service flags are true
// Analyzing validation assuming that pkcs12, legacy-pkcs12, jks and service flags are true
//+-------------+----------------+----------------------------------------------------------------------+
//| --no-prompt | --key-password | What happens in validation? |
//|-------------|----------------|----------------------------------------------------------------------|
Expand All @@ -1457,7 +1457,7 @@ func doCommandRenew1(c *cli.Context) error {
//| false | false |VCert will prompt to enter password and process will not be completed |
//| | |until password is provided by user |
//+-------------+----------------+----------------------------------------------------------------------+
if (pcc.PrivateKey != "" && (flags.format == Pkcs12 || flags.format == JKSFormat)) || (flags.format == util.LegacyPem && flags.csrOption == "service") || flags.noPrompt && passwordAutogenerated {
if (pcc.PrivateKey != "" && (flags.format == P12Format || flags.format == LegacyP12Format || flags.format == JKSFormat)) || (flags.format == util.LegacyPem && flags.csrOption == "service") || flags.noPrompt && passwordAutogenerated {
privKey, err := util.DecryptPkcs8PrivateKey(pcc.PrivateKey, flags.keyPassword)
if err != nil {
if err.Error() == "pkcs8: only PBES2 supported" && connector.GetType() == endpoint.ConnectorTypeTPP {
Expand Down
2 changes: 1 addition & 1 deletion cmd/vcert/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ var (

flagFormat = &cli.StringFlag{
Name: "format",
Usage: "Use to specify the output format. Options include: pem | json | pkcs12 | jks." +
Usage: "Use to specify the output format. Options include: pem | json | pkcs12 | jks | legacy-pem | legacy-pkcs12." +
" If PKCS#12 or JKS formats are specified, the --file parameter is required." +
" For JKS format, the --jks-alias parameter is required and a password must be provided (see --key-password and --jks-password).",
Destination: &flags.format,
Expand Down
4 changes: 3 additions & 1 deletion cmd/vcert/passwords.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ func readPasswordsFromInputFlags(commandName string, cf *commandFlags) error {

cloudSerViceGenerated := IsCSRServiceVaaSGenerated(commandName)

if commandName == commandSshPickupName || commandName == commandSshEnrollName || commandName == commandEnrollName || commandName == commandGenCSRName || commandName == commandRenewName || commandName == commandPickupName && (cf.format == "pkcs12" || cf.format == JKSFormat || cloudSerViceGenerated) {
if commandName == commandSshPickupName || commandName == commandSshEnrollName || commandName == commandEnrollName ||
commandName == commandGenCSRName || commandName == commandRenewName || commandName == commandPickupName &&
(cf.format == P12Format || cf.format == LegacyP12Format || cf.format == JKSFormat || cloudSerViceGenerated) {
var keyPasswordNotNeeded = false

keyPasswordNotNeeded = keyPasswordNotNeeded || (cf.csrOption == "service" && cf.noPickup)
Expand Down
9 changes: 6 additions & 3 deletions cmd/vcert/result_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package main

import (
"bytes"
"crypto/rand"
"crypto/x509"
"encoding/json"
"encoding/pem"
Expand Down Expand Up @@ -122,7 +121,11 @@ func (o *Output) AsPKCS12(c *Config) ([]byte, error) {
return nil, fmt.Errorf("private key error(3): %s", err)
}

bytes, err := pkcs12.Encode(rand.Reader, privKey, cert, chain_list, c.KeyPassword)
encoder := pkcs12.Modern2023
if c.Format == LegacyP12Format {
encoder = pkcs12.LegacyRC2
}
bytes, err := encoder.Encode(privKey, cert, chain_list, c.KeyPassword)
if err != nil {
return nil, fmt.Errorf("encode error: %s", err)
}
Expand Down Expand Up @@ -313,7 +316,7 @@ func (r *Result) Flush() error {
allFileOutput.CSR = r.Pcc.CSR

var bytes []byte
if r.Config.Format == "pkcs12" {
if r.Config.Format == P12Format || r.Config.Format == LegacyP12Format {
bytes, err = allFileOutput.AsPKCS12(r.Config)
if err != nil {
return fmt.Errorf("failed to encode pkcs12: %s", err)
Expand Down
Loading

0 comments on commit d5b37ae

Please sign in to comment.