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

Add support for ed25519 #11780

Merged
merged 22 commits into from Oct 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
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
53 changes: 52 additions & 1 deletion builtin/logical/pki/backend_test.go
Expand Up @@ -5,6 +5,7 @@ import (
"context"
"crypto"
"crypto/ecdsa"
"crypto/ed25519"
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
Expand Down Expand Up @@ -211,6 +212,8 @@ func TestBackend_Roles(t *testing.T) {
{"RSACSR", &rsaCAKey, &rsaCACert, true},
{"EC", &ecCAKey, &ecCACert, false},
{"ECCSR", &ecCAKey, &ecCACert, true},
{"ED", &edCAKey, &edCACert, false},
{"EDCSR", &edCAKey, &edCACert, true},
}

for _, tc := range cases {
Expand Down Expand Up @@ -309,6 +312,13 @@ func checkCertsAndPrivateKey(keyType string, key crypto.Signer, usage x509.KeyUs
if err != nil {
return nil, fmt.Errorf("error parsing EC key: %s", err)
}
case "ed25519":
parsedCertBundle.PrivateKeyType = certutil.Ed25519PrivateKey
parsedCertBundle.PrivateKey = key
parsedCertBundle.PrivateKeyBytes, err = x509.MarshalPKCS8PrivateKey(key.(ed25519.PrivateKey))
if err != nil {
return nil, fmt.Errorf("error parsing Ed25519 key: %s", err)
}
}
}

Expand All @@ -324,6 +334,8 @@ func checkCertsAndPrivateKey(keyType string, key crypto.Signer, usage x509.KeyUs
}

switch {
case parsedCertBundle.PrivateKeyType == certutil.Ed25519PrivateKey && keyType != "ed25519":
fallthrough
case parsedCertBundle.PrivateKeyType == certutil.RSAPrivateKey && keyType != "rsa":
fallthrough
case parsedCertBundle.PrivateKeyType == certutil.ECPrivateKey && keyType != "ec":
Expand Down Expand Up @@ -707,7 +719,7 @@ func generateRoleSteps(t *testing.T, useCSRs bool) []logicaltest.TestStep {

generatedRSAKeys := map[int]crypto.Signer{}
generatedECKeys := map[int]crypto.Signer{}

generatedEdKeys := map[int]crypto.Signer{}
/*
// For the number of tests being run, a seed of 1 has been tested
// to hit all of the various values below. However, for normal
Expand Down Expand Up @@ -1017,6 +1029,13 @@ func generateRoleSteps(t *testing.T, useCSRs bool) []logicaltest.TestStep {
generatedECKeys[keyBits] = privKey
}

case "ed25519":
privKey, ok = generatedEdKeys[keyBits]
if !ok {
_, privKey, _ = ed25519.GenerateKey(rand.Reader)
generatedEdKeys[keyBits] = privKey
}

default:
panic("invalid key type: " + keyType)
}
Expand Down Expand Up @@ -3095,6 +3114,36 @@ func setCerts() {
Bytes: caBytes,
}
rsaCACert = strings.TrimSpace(string(pem.EncodeToMemory(caCertPEMBlock)))

_, edk, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
panic(err)
}
marshaledKey, err = x509.MarshalPKCS8PrivateKey(edk)
if err != nil {
panic(err)
}
keyPEMBlock = &pem.Block{
Type: "PRIVATE KEY",
Bytes: marshaledKey,
}
edCAKey = strings.TrimSpace(string(pem.EncodeToMemory(keyPEMBlock)))
if err != nil {
panic(err)
}
subjKeyID, err = certutil.GetSubjKeyID(edk)
if err != nil {
panic(err)
}
caBytes, err = x509.CreateCertificate(rand.Reader, caCertTemplate, caCertTemplate, edk.Public(), edk)
if err != nil {
panic(err)
}
caCertPEMBlock = &pem.Block{
Type: "CERTIFICATE",
Bytes: caBytes,
}
edCACert = strings.TrimSpace(string(pem.EncodeToMemory(caCertPEMBlock)))
}

func TestBackend_RevokePlusTidy_Intermediate(t *testing.T) {
Expand Down Expand Up @@ -3281,4 +3330,6 @@ var (
rsaCACert string
ecCAKey string
ecCACert string
edCAKey string
edCACert string
)
66 changes: 64 additions & 2 deletions builtin/logical/pki/ca_test.go
Expand Up @@ -3,6 +3,7 @@ package pki
import (
"context"
"crypto/ecdsa"
"crypto/ed25519"
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
Expand Down Expand Up @@ -49,7 +50,7 @@ func TestBackend_CA_Steps(t *testing.T) {
client := cluster.Cores[0].Client

// Set RSA/EC CA certificates
var rsaCAKey, rsaCACert, ecCAKey, ecCACert string
var rsaCAKey, rsaCACert, ecCAKey, ecCACert, edCAKey, edCACert string
{
cak, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
Expand Down Expand Up @@ -119,10 +120,40 @@ func TestBackend_CA_Steps(t *testing.T) {
Bytes: caBytes,
}
rsaCACert = strings.TrimSpace(string(pem.EncodeToMemory(caCertPEMBlock)))

_, edk, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
panic(err)
}
marshaledKey, err = x509.MarshalPKCS8PrivateKey(edk)
if err != nil {
panic(err)
}
keyPEMBlock = &pem.Block{
Type: "PRIVATE KEY",
Bytes: marshaledKey,
}
edCAKey = strings.TrimSpace(string(pem.EncodeToMemory(keyPEMBlock)))
if err != nil {
panic(err)
}
_, err = certutil.GetSubjKeyID(edk)
if err != nil {
panic(err)
}
caBytes, err = x509.CreateCertificate(rand.Reader, caCertTemplate, caCertTemplate, edk.Public(), edk)
if err != nil {
panic(err)
}
caCertPEMBlock = &pem.Block{
Type: "CERTIFICATE",
Bytes: caBytes,
}
edCACert = strings.TrimSpace(string(pem.EncodeToMemory(caCertPEMBlock)))
}

// Setup backends
var rsaRoot, rsaInt, ecRoot, ecInt *backend
var rsaRoot, rsaInt, ecRoot, ecInt, edRoot, edInt *backend
{
if err := client.Sys().Mount("rsaroot", &api.MountInput{
Type: "pki",
Expand Down Expand Up @@ -167,6 +198,28 @@ func TestBackend_CA_Steps(t *testing.T) {
t.Fatal(err)
}
ecInt = b

if err := client.Sys().Mount("ed25519root", &api.MountInput{
Type: "pki",
Config: api.MountConfigInput{
DefaultLeaseTTL: "16h",
MaxLeaseTTL: "60h",
},
}); err != nil {
t.Fatal(err)
}
edRoot = b

if err := client.Sys().Mount("ed25519int", &api.MountInput{
Type: "pki",
Config: api.MountConfigInput{
DefaultLeaseTTL: "16h",
MaxLeaseTTL: "60h",
},
}); err != nil {
t.Fatal(err)
}
edInt = b
}

t.Run("teststeps", func(t *testing.T) {
Expand All @@ -188,6 +241,15 @@ func TestBackend_CA_Steps(t *testing.T) {
subClient.SetToken(client.Token())
runSteps(t, ecRoot, ecInt, subClient, "ecroot/", "ecint/", ecCACert, ecCAKey)
})
t.Run("ed25519", func(t *testing.T) {
t.Parallel()
subClient, err := client.Clone()
if err != nil {
t.Fatal(err)
}
subClient.SetToken(client.Token())
runSteps(t, edRoot, edInt, subClient, "ed25519root/", "ed25519int/", edCACert, edCAKey)
})
})
}

Expand Down
13 changes: 13 additions & 0 deletions builtin/logical/pki/cert_util.go
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"crypto"
"crypto/ecdsa"
"crypto/ed25519"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
Expand Down Expand Up @@ -595,6 +596,18 @@ func signCert(b *backend,
pubKey.Params().BitSize)}
}

case "ed25519":
// Verify that the key matches the role type
if csr.PublicKeyAlgorithm != x509.PublicKeyAlgorithm(x509.Ed25519) {
return nil, errutil.UserError{Err: fmt.Sprintf(
"role requires keys of type %s",
data.role.KeyType)}
}
_, ok := csr.PublicKey.(ed25519.PublicKey)
if !ok {
return nil, errutil.UserError{Err: "could not parse CSR's public key"}
}

case "any":
// We only care about running RSA < 2048 bit checks, so if not RSA
// break out
Expand Down
4 changes: 2 additions & 2 deletions builtin/logical/pki/fields.go
Expand Up @@ -270,8 +270,8 @@ Set to 384 for SHA384 and 512 for SHA512.
Type: framework.TypeString,
Default: "rsa",
Description: `The type of key to use; defaults to RSA. "rsa"
and "ec" are the only valid values.`,
AllowedValues: []interface{}{"rsa", "ec"},
"ec" and "ed25519" are the only valid values.`,
AllowedValues: []interface{}{"rsa", "ec", "ed25519"},
DisplayAttrs: &framework.DisplayAttributes{
Value: "rsa",
},
Expand Down
4 changes: 2 additions & 2 deletions builtin/logical/pki/path_roles.go
Expand Up @@ -193,8 +193,8 @@ protection use. Defaults to false.`,
Type: framework.TypeString,
Default: "rsa",
Description: `The type of key to use; defaults to RSA. "rsa"
and "ec" are the only valid values.`,
AllowedValues: []interface{}{"rsa", "ec"},
"ec" and "ed25519" are the only valid values.`,
AllowedValues: []interface{}{"rsa", "ec", "ed25519"},
},

"key_bits": {
Expand Down
3 changes: 3 additions & 0 deletions changelog/11780.txt
@@ -0,0 +1,3 @@
```release-note:feature
pki: Support ed25519 as a key for the pki backend
```