Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions lib/ocrypto/asym_decryption.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@ type PrivateKeyDecryptor interface {

// FromPrivatePEM creates and returns a new AsymDecryption.
func FromPrivatePEM(privateKeyInPem string) (PrivateKeyDecryptor, error) {
// TK Move salt and info out of library, into API option functions
digest := sha256.New()
digest.Write([]byte("TDF"))
salt := digest.Sum(nil)

return FromPrivatePEMWithSalt(privateKeyInPem, salt, nil)
}

func FromPrivatePEMWithSalt(privateKeyInPem string, salt, info []byte) (PrivateKeyDecryptor, error) {
block, _ := pem.Decode([]byte(privateKeyInPem))
if block == nil {
return AsymDecryption{}, errors.New("failed to parse PEM formatted private key")
Expand Down Expand Up @@ -59,9 +68,9 @@ func FromPrivatePEM(privateKeyInPem string) (PrivateKeyDecryptor, error) {
if err != nil {
return nil, fmt.Errorf("unable to create ECDH key: %w", err)
}
return NewECDecryptor(sk)
return NewSaltedECDecryptor(sk, salt, info)
case *ecdh.PrivateKey:
return NewECDecryptor(privateKey)
return NewSaltedECDecryptor(privateKey, salt, info)
case *rsa.PrivateKey:
return AsymDecryption{privateKey}, nil
default:
Expand All @@ -72,7 +81,7 @@ func FromPrivatePEM(privateKeyInPem string) (PrivateKeyDecryptor, error) {
}

func NewAsymDecryption(privateKeyInPem string) (AsymDecryption, error) {
d, err := FromPrivatePEM(privateKeyInPem)
d, err := FromPrivatePEMWithSalt(privateKeyInPem, nil, nil)
if err != nil {
return AsymDecryption{}, err
}
Expand Down Expand Up @@ -114,6 +123,9 @@ func NewECDecryptor(sk *ecdh.PrivateKey) (ECDecryptor, error) {

return ECDecryptor{sk, salt, nil}, nil
}
func NewSaltedECDecryptor(sk *ecdh.PrivateKey, salt, info []byte) (ECDecryptor, error) {
return ECDecryptor{sk, salt, info}, nil
}

func (e ECDecryptor) Decrypt(_ []byte) ([]byte, error) {
// TK How to get the ephmeral key into here?
Expand Down
26 changes: 23 additions & 3 deletions lib/ocrypto/asym_encrypt_decrypt_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
package ocrypto

import (
"crypto/sha256"
"testing"
)

func salty(s string) []byte {
digest := sha256.New()
digest.Write([]byte(s))
return digest.Sum(nil)
}

func TestAsymEncryptionAndDecryption(t *testing.T) {
var keypairs = []struct {
privateKey string
publicKey string
salt []byte
info []byte
}{
{ // Test 2048 key
`-----BEGIN PRIVATE KEY-----
Expand Down Expand Up @@ -47,6 +56,8 @@ GBKh0CWGAXWRmphzGj7kFpkAxT1b827MrQMYxkn4w2WB8B/bGKz0+dWyqnnzGYAS
hVJ0rIiNE8dDWzQCRBfivLemXhX8UFICyoS5i0IwenFvTr6T85EvMxK3aSAlGya3
3wIDAQAB
-----END PUBLIC KEY-----`,
salty("L1L"),
nil,
},
{ // Test 3072 key
`-----BEGIN PRIVATE KEY-----
Expand Down Expand Up @@ -100,6 +111,8 @@ KdheIKdUG+Ouv+vMTeAYOw9+5OGainDWFJA3LZHid3qbX85Y0as9n1nSKoYXMMQT
88Nx+U7Vv8fTudHUgueYGy7WtE6URRIkI5W94u5jDpcb9DZ90Wv5XhaJdRmQ2BhZ
pCVg892PjJwMcTWhIKJgX+9QEL2bSb2VY3yEpEa2b2LhAgMBAAE=
-----END PUBLIC KEY-----`,
salty("L1L"),
nil,
},
{ // Test 4096 key
`-----BEGIN PRIVATE KEY-----
Expand Down Expand Up @@ -168,6 +181,8 @@ Td+sCeVX1dczquJziOvYwCyC4nM7pY+13+DXgszMydj/jdSshM4p2GRQu/JYDJf+
EfNOjyrEL5+gjYgiQzVVbYkRhr2ZNeNvzdQsM8j+I20ObCNY1RFCmp9//8xNbi1k
ufgiB73q6Fnh5QHf1HNAeMUCAwEAAQ==
-----END PUBLIC KEY-----`,
salty("TDF"),
nil,
},
{ // Test certificate
`-----BEGIN PRIVATE KEY-----
Expand Down Expand Up @@ -214,6 +229,8 @@ I099IoRfC5djHUYYLMU/VkOIHuPC3sb7J65pSN26eR8bTMVNagk187V/xNwUuvkf
+NUxDO615/5BwQKnAu5xiIVagYnDZqKCOtYS5qhxF33Nlnwlm7hH8iVZ1RI+n52l
wVyElqp317Ksz+GtTIc+DE6oryxK3tZd4hrj9fXT4KiJvQ4pcRjpePgH7B8=
-----END CERTIFICATE-----`,
salty("L1L"),
nil,
},
{`-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgwQlQvwfqC0sEaPVi
Expand All @@ -229,11 +246,14 @@ KVoSgWSEfXZpk5Cr+xiup+ndMhXhszsqge5fSzszsJQg3ZvZNIwUAcOfew8suykM
A1UdIwQYMBaAFCAo/c694aHwmw/0kUTKuFvAQ4OcMA8GA1UdEwEB/wQFMAMBAf8w
CgYIKoZIzj0EAwIDSAAwRQIgUzKsJS6Pcu2aZ6BFfuqob552Ebdel4uFGZMqWrwW
bW0CIQDT5QED+8mHFot9JXSx2q1c5mnRvl4yElK0fiHeatBdqw==
-----END CERTIFICATE-----`},
-----END CERTIFICATE-----`,
salty("L1L"),
nil,
},
}

for _, test := range keypairs {
asymEncryptor, err := FromPublicPEM(test.publicKey)
asymEncryptor, err := FromPublicPEMWithSalt(test.publicKey, test.salt, test.info)
if err != nil {
t.Fatalf("NewAsymEncryption - failed: %v", err)
}
Expand All @@ -244,7 +264,7 @@ bW0CIQDT5QED+8mHFot9JXSx2q1c5mnRvl4yElK0fiHeatBdqw==
t.Fatalf("AsymEncryption encrypt failed: %v", err)
}

asymDecryptor, err := FromPrivatePEM(test.privateKey)
asymDecryptor, err := FromPrivatePEMWithSalt(test.privateKey, test.salt, test.info)
if err != nil {
t.Fatalf("NewAsymDecryption - failed: %v", err)
}
Expand Down
20 changes: 12 additions & 8 deletions lib/ocrypto/asym_encryption.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ type ECEncryptor struct {
}

func FromPublicPEM(publicKeyInPem string) (PublicKeyEncryptor, error) {
// TK Move salt and info out of library, into API option functions
digest := sha256.New()
digest.Write([]byte("TDF"))
salt := digest.Sum(nil)

return FromPublicPEMWithSalt(publicKeyInPem, salt, nil)
}
func FromPublicPEMWithSalt(publicKeyInPem string, salt, info []byte) (PublicKeyEncryptor, error) {
pub, err := getPublicPart(publicKeyInPem)
if err != nil {
return nil, err
Expand All @@ -69,23 +77,19 @@ func FromPublicPEM(publicKeyInPem string) (PublicKeyEncryptor, error) {
if err != nil {
return nil, err
}
return newECIES(e)
return newECIES(e, salt, info)
case *ecdh.PublicKey:
return newECIES(pub)
return newECIES(pub, salt, info)
default:
break
}

return nil, errors.New("not an supported type of public key")
}

func newECIES(pub *ecdh.PublicKey) (ECEncryptor, error) {
func newECIES(pub *ecdh.PublicKey, salt, info []byte) (ECEncryptor, error) {
ek, err := pub.Curve().GenerateKey(rand.Reader)
// TK Move salt and info out of library, into API option functions
digest := sha256.New()
digest.Write([]byte("TDF"))
salt := digest.Sum(nil)
return ECEncryptor{pub, ek, salt, nil}, err
return ECEncryptor{pub, ek, salt, info}, err
}

// NewAsymEncryption creates and returns a new AsymEncryption.
Expand Down
11 changes: 8 additions & 3 deletions sdk/tdf.go
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,13 @@ func createKeyAccess(tdfConfig TDFConfig, kasInfo KASInfo, symKey []byte, policy
return keyAccess, nil
}

func tdfSalt() []byte {
digest := sha256.New()
digest.Write([]byte("TDF"))
salt := digest.Sum(nil)
return salt
}

func generateWrapKeyWithEC(mode ocrypto.ECCMode, kasPublicKey string, symKey []byte) (ecKeyWrappedKeyInfo, error) {
ecKeyPair, err := ocrypto.NewECKeyPair(mode)
if err != nil {
Expand All @@ -591,9 +598,7 @@ func generateWrapKeyWithEC(mode ocrypto.ECCMode, kasPublicKey string, symKey []b
return ecKeyWrappedKeyInfo{}, fmt.Errorf("ocrypto.ComputeECDHKey failed:%w", err)
}

digest := sha256.New()
digest.Write([]byte("TDF"))
salt := digest.Sum(nil)
salt := tdfSalt()
sessionKey, err := ocrypto.CalculateHKDF(salt, ecdhKey)
if err != nil {
return ecKeyWrappedKeyInfo{}, fmt.Errorf("ocrypto.CalculateHKDF failed:%w", err)
Expand Down
6 changes: 3 additions & 3 deletions sdk/tdf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2103,14 +2103,14 @@ func (f *FakeKas) getRewrapResponse(rewrapRequest string) *kaspb.RewrapResponse
privateKey, err := ocrypto.ECPrivateKeyFromPem([]byte(kasPrivateKey))
f.s.Require().NoError(err, "failed to extract private key from PEM")

ed, err := ocrypto.NewECDecryptor(privateKey)
ed, err := ocrypto.NewSaltedECDecryptor(privateKey, tdfSalt(), nil)
f.s.Require().NoError(err, "failed to create EC decryptor")

symmetricKey, err := ed.DecryptWithEphemeralKey(wrappedKey, compressedKey)
f.s.Require().NoError(err, "failed to decrypt")

asymEncrypt, err := ocrypto.FromPublicPEM(bodyData.GetClientPublicKey())
f.s.Require().NoError(err, "ocrypto.FromPublicPEM failed")
asymEncrypt, err := ocrypto.FromPublicPEMWithSalt(bodyData.GetClientPublicKey(), tdfSalt(), nil)
f.s.Require().NoError(err, "ocrypto.FromPublicPEMWithSalt failed")

var sessionKey string
if e, found := asymEncrypt.(ocrypto.ECEncryptor); found {
Expand Down
9 changes: 8 additions & 1 deletion service/internal/security/standard_crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,13 @@ func (s StandardCrypto) GenerateNanoTDFSessionKey(privateKey any, ephemeralPubli
func (s StandardCrypto) Close() {
}

func TDFSalt() []byte {
digest := sha256.New()
digest.Write([]byte("TDF"))
salt := digest.Sum(nil)
return salt
}

func versionSalt() []byte {
digest := sha256.New()
digest.Write([]byte(kNanoTDFMagicStringAndVersion))
Expand All @@ -451,7 +458,7 @@ func (s *StandardCrypto) ECDecrypt(keyID string, ephemeralPublicKey, ciphertext
sk.sk = loaded
}

ed, err := ocrypto.NewECDecryptor(sk.sk)
ed, err := ocrypto.NewSaltedECDecryptor(sk.sk, TDFSalt(), nil)
if err != nil {
return nil, fmt.Errorf("failed to create EC decryptor: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion service/kas/access/rewrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ func (p *Provider) tdf3Rewrap(ctx context.Context, requests []*kaspb.UnsignedRew
return "", results
}

asymEncrypt, err := ocrypto.FromPublicPEM(clientPublicKey)
asymEncrypt, err := ocrypto.FromPublicPEMWithSalt(clientPublicKey, security.TDFSalt(), nil)
if err != nil {
p.Logger.WarnContext(ctx, "ocrypto.NewAsymEncryption:", "err", err)
failAllKaos(requests, results, err400("invalid request"))
Expand Down
Loading