From 8514aeee347fdbde555b47d16e9cc96b6b8fdc9b Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 25 Sep 2024 10:33:52 -0700 Subject: [PATCH] Add support for new RSA key sizes in YubiKey 5.7.x This commit adds support for new RSA key sizes, 3072 and 4096 bits, available in YubiKeys with a 5.7.x firmware. --- kms/yubikey/yubikey.go | 8 +++++ kms/yubikey/yubikey_test.go | 61 ++++++++++++++++++++++++++++++++----- 2 files changed, 62 insertions(+), 7 deletions(-) diff --git a/kms/yubikey/yubikey.go b/kms/yubikey/yubikey.go index 97c36001..68260566 100644 --- a/kms/yubikey/yubikey.go +++ b/kms/yubikey/yubikey.go @@ -403,21 +403,29 @@ var signatureAlgorithmMapping = map[apiv1.SignatureAlgorithm]interface{}{ 0: piv.AlgorithmRSA2048, 1024: piv.AlgorithmRSA1024, 2048: piv.AlgorithmRSA2048, + 3072: piv.AlgorithmRSA3072, + 4096: piv.AlgorithmRSA4096, }, apiv1.SHA512WithRSA: map[int]piv.Algorithm{ 0: piv.AlgorithmRSA2048, 1024: piv.AlgorithmRSA1024, 2048: piv.AlgorithmRSA2048, + 3072: piv.AlgorithmRSA3072, + 4096: piv.AlgorithmRSA4096, }, apiv1.SHA256WithRSAPSS: map[int]piv.Algorithm{ 0: piv.AlgorithmRSA2048, 1024: piv.AlgorithmRSA1024, 2048: piv.AlgorithmRSA2048, + 3072: piv.AlgorithmRSA3072, + 4096: piv.AlgorithmRSA4096, }, apiv1.SHA512WithRSAPSS: map[int]piv.Algorithm{ 0: piv.AlgorithmRSA2048, 1024: piv.AlgorithmRSA1024, 2048: piv.AlgorithmRSA2048, + 3072: piv.AlgorithmRSA3072, + 4096: piv.AlgorithmRSA4096, }, apiv1.ECDSAWithSHA256: piv.AlgorithmEC256, apiv1.ECDSAWithSHA384: piv.AlgorithmEC384, diff --git a/kms/yubikey/yubikey_test.go b/kms/yubikey/yubikey_test.go index 71107924..c9265d84 100644 --- a/kms/yubikey/yubikey_test.go +++ b/kms/yubikey/yubikey_test.go @@ -193,6 +193,18 @@ func (s *stubPivKey) GenerateKey(key []byte, slot piv.Slot, opts piv.Key) (crypt return nil, err } signer = key + case piv.AlgorithmRSA3072: + key, err := rsa.GenerateKey(rand.Reader, 3072) + if err != nil { + return nil, err + } + signer = key + case piv.AlgorithmRSA4096: + key, err := rsa.GenerateKey(rand.Reader, 4096) + if err != nil { + return nil, err + } + signer = key default: return nil, errors.New("unsupported algorithm") } @@ -298,6 +310,7 @@ func TestNew(t *testing.T) { wantErr bool }{ {"ok", args{ctx, apiv1.Options{}}, func() { + pivMap = sync.Map{} pivCards = okPivCards pivOpen = okPivOpen }, &YubiKey{yk: yk, pin: "123456", card: "Yubico YubiKey OTP+FIDO+CCID", managementKey: piv.DefaultManagementKey}, false}, @@ -654,6 +667,32 @@ func TestYubiKey_CreateKey(t *testing.T) { }, } }, false}, + {"ok rsa 3072", fields{yk, "123456", piv.DefaultManagementKey}, args{&apiv1.CreateKeyRequest{ + Name: "yubikey:slot-id=82", + SignatureAlgorithm: apiv1.SHA256WithRSAPSS, + Bits: 3072, + }}, func() *apiv1.CreateKeyResponse { + return &apiv1.CreateKeyResponse{ + Name: "yubikey:slot-id=82", + PublicKey: yk.signerMap[slotMapping["82"]].(crypto.Signer).Public(), + CreateSignerRequest: apiv1.CreateSignerRequest{ + SigningKey: "yubikey:slot-id=82", + }, + } + }, false}, + {"ok rsa 4096", fields{yk, "123456", piv.DefaultManagementKey}, args{&apiv1.CreateKeyRequest{ + Name: "yubikey:slot-id=82", + SignatureAlgorithm: apiv1.SHA512WithRSAPSS, + Bits: 4096, + }}, func() *apiv1.CreateKeyResponse { + return &apiv1.CreateKeyResponse{ + Name: "yubikey:slot-id=82", + PublicKey: yk.signerMap[slotMapping["82"]].(crypto.Signer).Public(), + CreateSignerRequest: apiv1.CreateSignerRequest{ + SigningKey: "yubikey:slot-id=82", + }, + } + }, false}, {"ok with policies", fields{yk, "123456", piv.DefaultManagementKey}, args{&apiv1.CreateKeyRequest{ Name: "yubikey:slot-id=82", SignatureAlgorithm: apiv1.ECDSAWithSHA256, @@ -668,10 +707,10 @@ func TestYubiKey_CreateKey(t *testing.T) { }, } }, false}, - {"fail rsa 4096", fields{yk, "123456", piv.DefaultManagementKey}, args{&apiv1.CreateKeyRequest{ + {"fail rsa 512", fields{yk, "123456", piv.DefaultManagementKey}, args{&apiv1.CreateKeyRequest{ Name: "yubikey:slot-id=82", SignatureAlgorithm: apiv1.SHA256WithRSA, - Bits: 4096, + Bits: 512, }}, func() *apiv1.CreateKeyResponse { return nil }, true}, {"fail getSignatureAlgorithm", fields{yk, "123456", piv.DefaultManagementKey}, args{&apiv1.CreateKeyRequest{ Name: "yubikey:slot-id=82", @@ -1182,15 +1221,23 @@ func Test_getSignatureAlgorithm(t *testing.T) { {"ECDSAWithSHA256", args{apiv1.ECDSAWithSHA256, 0}, piv.AlgorithmEC256, false}, {"ECDSAWithSHA384", args{apiv1.ECDSAWithSHA384, 0}, piv.AlgorithmEC384, false}, {"PureEd25519", args{apiv1.PureEd25519, 0}, piv.AlgorithmEd25519, false}, - {"SHA256WithRSA 2048", args{apiv1.SHA256WithRSA, 2048}, piv.AlgorithmRSA2048, false}, - {"SHA512WithRSA 2048", args{apiv1.SHA512WithRSA, 2048}, piv.AlgorithmRSA2048, false}, - {"SHA256WithRSAPSS 2048", args{apiv1.SHA256WithRSAPSS, 2048}, piv.AlgorithmRSA2048, false}, - {"SHA512WithRSAPSS 2048", args{apiv1.SHA512WithRSAPSS, 2048}, piv.AlgorithmRSA2048, false}, {"SHA256WithRSA 1024", args{apiv1.SHA256WithRSA, 1024}, piv.AlgorithmRSA1024, false}, {"SHA512WithRSA 1024", args{apiv1.SHA512WithRSA, 1024}, piv.AlgorithmRSA1024, false}, {"SHA256WithRSAPSS 1024", args{apiv1.SHA256WithRSAPSS, 1024}, piv.AlgorithmRSA1024, false}, {"SHA512WithRSAPSS 1024", args{apiv1.SHA512WithRSAPSS, 1024}, piv.AlgorithmRSA1024, false}, - {"fail 4096", args{apiv1.SHA256WithRSA, 4096}, 0, true}, + {"SHA256WithRSA 2048", args{apiv1.SHA256WithRSA, 2048}, piv.AlgorithmRSA2048, false}, + {"SHA512WithRSA 2048", args{apiv1.SHA512WithRSA, 2048}, piv.AlgorithmRSA2048, false}, + {"SHA256WithRSAPSS 2048", args{apiv1.SHA256WithRSAPSS, 2048}, piv.AlgorithmRSA2048, false}, + {"SHA512WithRSAPSS 2048", args{apiv1.SHA512WithRSAPSS, 2048}, piv.AlgorithmRSA2048, false}, + {"SHA256WithRSA 3072", args{apiv1.SHA256WithRSA, 3072}, piv.AlgorithmRSA3072, false}, + {"SHA512WithRSA 3072", args{apiv1.SHA512WithRSA, 3072}, piv.AlgorithmRSA3072, false}, + {"SHA256WithRSAPSS 3072", args{apiv1.SHA256WithRSAPSS, 3072}, piv.AlgorithmRSA3072, false}, + {"SHA512WithRSAPSS 3072", args{apiv1.SHA512WithRSAPSS, 3072}, piv.AlgorithmRSA3072, false}, + {"SHA256WithRSA 4096", args{apiv1.SHA256WithRSA, 4096}, piv.AlgorithmRSA4096, false}, + {"SHA512WithRSA 4096", args{apiv1.SHA512WithRSA, 4096}, piv.AlgorithmRSA4096, false}, + {"SHA256WithRSAPSS 4096", args{apiv1.SHA256WithRSAPSS, 4096}, piv.AlgorithmRSA4096, false}, + {"SHA512WithRSAPSS 4096", args{apiv1.SHA512WithRSAPSS, 4096}, piv.AlgorithmRSA4096, false}, + {"fail 512", args{apiv1.SHA256WithRSA, 512}, 0, true}, {"fail unknown", args{apiv1.SignatureAlgorithm(100), 0}, 0, true}, {"fail default case", args{apiv1.SignatureAlgorithm(1000), 0}, 0, true}, }