From 0b02c5d56cd820954e02ebbaa31af8417a15076d Mon Sep 17 00:00:00 2001 From: Rachel Culpepper <84159930+rculpepper@users.noreply.github.com> Date: Wed, 22 May 2024 09:27:45 -0500 Subject: [PATCH] Fix ed25519 key type in ca_util (#27093) * fix ed25519 key type * add changelog * fix other case and add tests * add other test * add headers --- builtin/logical/pki/ca_util.go | 2 +- builtin/logical/pki/ca_util_test.go | 82 +++++++++++++++++++++++++++++ changelog/27093.txt | 3 ++ sdk/helper/certutil/types.go | 2 +- sdk/helper/certutil/types_test.go | 63 ++++++++++++++++++++++ 5 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 builtin/logical/pki/ca_util_test.go create mode 100644 changelog/27093.txt create mode 100644 sdk/helper/certutil/types_test.go diff --git a/builtin/logical/pki/ca_util.go b/builtin/logical/pki/ca_util.go index 6f2f005217be..364bed9958d1 100644 --- a/builtin/logical/pki/ca_util.go +++ b/builtin/logical/pki/ca_util.go @@ -235,7 +235,7 @@ func getKeyTypeAndBitsFromPublicKeyForRole(pubKey crypto.PublicKey) (certutil.Pr keyBits = certutil.GetPublicKeySize(pubKey) case *ecdsa.PublicKey: keyType = certutil.ECPrivateKey - case *ed25519.PublicKey: + case ed25519.PublicKey: keyType = certutil.Ed25519PrivateKey default: return certutil.UnknownPrivateKey, 0, fmt.Errorf("unsupported public key: %#v", pubKey) diff --git a/builtin/logical/pki/ca_util_test.go b/builtin/logical/pki/ca_util_test.go new file mode 100644 index 000000000000..d4ef64e68fe1 --- /dev/null +++ b/builtin/logical/pki/ca_util_test.go @@ -0,0 +1,82 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package pki + +import ( + "crypto" + "crypto/ecdsa" + "crypto/ed25519" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + "testing" + + "github.com/hashicorp/vault/sdk/helper/certutil" +) + +func TestGetKeyTypeAndBitsFromPublicKeyForRole(t *testing.T) { + rsaKey, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + t.Fatalf("error generating rsa key: %s", err) + } + + ecdsaKey, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader) + if err != nil { + t.Fatalf("error generating ecdsa key: %s", err) + } + + publicKey, _, err := ed25519.GenerateKey(rand.Reader) + if err != nil { + t.Fatalf("error generating ed25519 key: %s", err) + } + + testCases := map[string]struct { + publicKey crypto.PublicKey + expectedKeyType certutil.PrivateKeyType + expectedKeyBits int + expectError bool + }{ + "rsa": { + publicKey: rsaKey.Public(), + expectedKeyType: certutil.RSAPrivateKey, + expectedKeyBits: 2048, + }, + "ecdsa": { + publicKey: ecdsaKey.Public(), + expectedKeyType: certutil.ECPrivateKey, + expectedKeyBits: 0, + }, + "ed25519": { + publicKey: publicKey, + expectedKeyType: certutil.Ed25519PrivateKey, + expectedKeyBits: 0, + }, + "bad key type": { + publicKey: []byte{}, + expectedKeyType: certutil.UnknownPrivateKey, + expectedKeyBits: 0, + expectError: true, + }, + } + + for name, tt := range testCases { + t.Run(name, func(t *testing.T) { + keyType, keyBits, err := getKeyTypeAndBitsFromPublicKeyForRole(tt.publicKey) + if err != nil && !tt.expectError { + t.Fatalf("unexpected error: %s", err) + } + if err == nil && tt.expectError { + t.Fatal("expected error, got nil") + } + + if keyType != tt.expectedKeyType { + t.Fatalf("key type mismatch: expected %s, got %s", tt.expectedKeyType, keyType) + } + + if keyBits != tt.expectedKeyBits { + t.Fatalf("key bits mismatch: expected %d, got %d", tt.expectedKeyBits, keyBits) + } + }) + } +} diff --git a/changelog/27093.txt b/changelog/27093.txt new file mode 100644 index 000000000000..a24becec3eac --- /dev/null +++ b/changelog/27093.txt @@ -0,0 +1,3 @@ +```release-note:bug +pki: Fix error in cross-signing using ed25519 keys +``` diff --git a/sdk/helper/certutil/types.go b/sdk/helper/certutil/types.go index ca245d7d4208..bfdc153c4852 100644 --- a/sdk/helper/certutil/types.go +++ b/sdk/helper/certutil/types.go @@ -171,7 +171,7 @@ func GetPrivateKeyTypeFromPublicKey(pubKey crypto.PublicKey) PrivateKeyType { return RSAPrivateKey case *ecdsa.PublicKey: return ECPrivateKey - case *ed25519.PublicKey: + case ed25519.PublicKey: return Ed25519PrivateKey default: return UnknownPrivateKey diff --git a/sdk/helper/certutil/types_test.go b/sdk/helper/certutil/types_test.go new file mode 100644 index 000000000000..2cf383afaa02 --- /dev/null +++ b/sdk/helper/certutil/types_test.go @@ -0,0 +1,63 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package certutil + +import ( + "crypto" + "crypto/ecdsa" + "crypto/ed25519" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + "testing" +) + +func TestGetPrivateKeyTypeFromPublicKey(t *testing.T) { + rsaKey, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + t.Fatalf("error generating rsa key: %s", err) + } + + ecdsaKey, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader) + if err != nil { + t.Fatalf("error generating ecdsa key: %s", err) + } + + publicKey, _, err := ed25519.GenerateKey(rand.Reader) + if err != nil { + t.Fatalf("error generating ed25519 key: %s", err) + } + + testCases := map[string]struct { + publicKey crypto.PublicKey + expectedKeyType PrivateKeyType + }{ + "rsa": { + publicKey: rsaKey.Public(), + expectedKeyType: RSAPrivateKey, + }, + "ecdsa": { + publicKey: ecdsaKey.Public(), + expectedKeyType: ECPrivateKey, + }, + "ed25519": { + publicKey: publicKey, + expectedKeyType: Ed25519PrivateKey, + }, + "bad key type": { + publicKey: []byte{}, + expectedKeyType: UnknownPrivateKey, + }, + } + + for name, tt := range testCases { + t.Run(name, func(t *testing.T) { + keyType := GetPrivateKeyTypeFromPublicKey(tt.publicKey) + + if keyType != tt.expectedKeyType { + t.Fatalf("key type mismatch: expected %s, got %s", tt.expectedKeyType, keyType) + } + }) + } +}