github.com/trustbloc/kms-go@v1.1.2/crypto/tinkcrypto/primitive/composite/ecdh/ecdh_nistpkw_public_key_manager_test.go (about)

     1  /*
     2  Copyright SecureKey Technologies Inc. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package ecdh
     8  
     9  import (
    10  	"crypto/elliptic"
    11  	"crypto/rand"
    12  	"strings"
    13  	"testing"
    14  
    15  	"github.com/golang/protobuf/proto"
    16  	"github.com/google/tink/go/aead"
    17  	hybrid "github.com/google/tink/go/hybrid/subtle"
    18  	gcmpb "github.com/google/tink/go/proto/aes_gcm_go_proto"
    19  	commonpb "github.com/google/tink/go/proto/common_go_proto"
    20  	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
    21  	"github.com/stretchr/testify/require"
    22  
    23  	cbcaead "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/aead"
    24  	"github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/composite"
    25  	ecdhpb "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/proto/ecdh_aead_go_proto"
    26  )
    27  
    28  func TestECDHNISTPAESPublicKeyManager_Primitive(t *testing.T) {
    29  	km := newECDHNISTPAESPublicKeyManager()
    30  
    31  	t.Run("Test public key manager Primitive() with empty serialized key", func(t *testing.T) {
    32  		p, err := km.Primitive([]byte(""))
    33  		require.EqualError(t, err, errInvalidNISTPECDHKWPublicKey.Error(),
    34  			"newECDHNISTPAESPublicKeyManager primitive from empty serialized key must fail")
    35  		require.Empty(t, p)
    36  	})
    37  
    38  	t.Run("Test public key manager Primitive() with bad serialize key", func(t *testing.T) {
    39  		p, err := km.Primitive([]byte("bad.data"))
    40  		require.EqualError(t, err, errInvalidNISTPECDHKWPublicKey.Error(),
    41  			"newECDHNISTPAESPublicKeyManager primitive from bad serialized key must fail")
    42  		require.Empty(t, p)
    43  	})
    44  
    45  	format := &gcmpb.AesGcmKeyFormat{
    46  		KeySize: 32,
    47  	}
    48  	serializedFormat, err := proto.Marshal(format)
    49  	require.NoError(t, err)
    50  
    51  	format = &gcmpb.AesGcmKeyFormat{
    52  		KeySize: 99, // bad AES128GCM size
    53  	}
    54  
    55  	badSerializedFormat, err := proto.Marshal(format)
    56  	require.NoError(t, err)
    57  
    58  	flagTests := []struct {
    59  		tcName    string
    60  		version   uint32
    61  		curveType commonpb.EllipticCurveType
    62  		ecPtFmt   commonpb.EcPointFormat
    63  		encTmp    *tinkpb.KeyTemplate
    64  	}{
    65  		{
    66  			tcName:    "public key manager Primitive() using key with bad version",
    67  			version:   9999,
    68  			curveType: commonpb.EllipticCurveType_NIST_P256,
    69  			ecPtFmt:   commonpb.EcPointFormat_COMPRESSED,
    70  			encTmp:    aead.AES128GCMKeyTemplate(),
    71  		},
    72  		{
    73  			tcName:    "public key manager Primitive() using key with bad curve",
    74  			version:   0,
    75  			curveType: commonpb.EllipticCurveType_UNKNOWN_CURVE,
    76  			ecPtFmt:   commonpb.EcPointFormat_COMPRESSED,
    77  			encTmp:    aead.AES128GCMKeyTemplate(),
    78  		},
    79  		{
    80  			tcName:    "success public key manager Primitive()",
    81  			version:   0,
    82  			curveType: commonpb.EllipticCurveType_NIST_P256,
    83  			ecPtFmt:   commonpb.EcPointFormat_UNCOMPRESSED,
    84  			encTmp:    aead.AES128GCMKeyTemplate(),
    85  		},
    86  		{
    87  			tcName:    "public key manager Primitive() using key with bad key template URL",
    88  			version:   0,
    89  			curveType: commonpb.EllipticCurveType_NIST_P256,
    90  			ecPtFmt:   commonpb.EcPointFormat_COMPRESSED,
    91  			encTmp: &tinkpb.KeyTemplate{
    92  				TypeUrl:          "bad.type/url/value",
    93  				Value:            serializedFormat,
    94  				OutputPrefixType: tinkpb.OutputPrefixType_RAW,
    95  			},
    96  		},
    97  		{
    98  			tcName:    "public key manager Primitive() using key with bad content encryption key size",
    99  			version:   0,
   100  			curveType: commonpb.EllipticCurveType_NIST_P256,
   101  			ecPtFmt:   commonpb.EcPointFormat_COMPRESSED,
   102  			encTmp: &tinkpb.KeyTemplate{
   103  				TypeUrl:          composite.AESGCMTypeURL,
   104  				Value:            badSerializedFormat,
   105  				OutputPrefixType: tinkpb.OutputPrefixType_RAW,
   106  			},
   107  		},
   108  		{
   109  			tcName:    "success public key manager Primitive() with AES-CBC+HMAC encTmp",
   110  			version:   0,
   111  			curveType: commonpb.EllipticCurveType_NIST_P256,
   112  			ecPtFmt:   commonpb.EcPointFormat_UNCOMPRESSED,
   113  			encTmp:    cbcaead.AES128CBCHMACSHA256KeyTemplate(),
   114  		},
   115  	}
   116  
   117  	for _, tc := range flagTests {
   118  		tt := tc
   119  		t.Run("Test "+tt.tcName, func(t *testing.T) {
   120  			c := tt.curveType
   121  			encT := tt.encTmp
   122  			ptFmt := tt.ecPtFmt
   123  			v := tt.version
   124  
   125  			// temporarily reset curvType if its unknown type so subtle.GetCurve() below doesn't fail
   126  			if tt.curveType.String() == commonpb.EllipticCurveType_UNKNOWN_CURVE.String() {
   127  				c = commonpb.EllipticCurveType_NIST_P256
   128  			}
   129  
   130  			crv, err := hybrid.GetCurve(c.String())
   131  			require.NoError(t, err)
   132  			_, x, y, err := elliptic.GenerateKey(crv, rand.Reader)
   133  			require.NoError(t, err)
   134  
   135  			// set back curvType if it was unknown to proceed with the test
   136  			if tt.curveType.String() == commonpb.EllipticCurveType_UNKNOWN_CURVE.String() {
   137  				c = tt.curveType
   138  			}
   139  
   140  			pubKeyProto := &ecdhpb.EcdhAeadPublicKey{
   141  				Version: v, // if v > 0  to force an error when calling km.Primitive()
   142  				Params: &ecdhpb.EcdhAeadParams{
   143  					KwParams: &ecdhpb.EcdhKwParams{
   144  						CurveType: c, // unknown curve type to force an error when calling km.Primitive()
   145  						KeyType:   ecdhpb.KeyType_EC,
   146  					},
   147  					EncParams: &ecdhpb.EcdhAeadEncParams{
   148  						AeadEnc: encT, // invalid data enc key template to force an error when calling km.Primitive()
   149  					},
   150  					EcPointFormat: ptFmt, // unknown EC Point format type to force an error when calling km.Primitive()
   151  				},
   152  				X: x.Bytes(),
   153  				Y: y.Bytes(),
   154  			}
   155  
   156  			sPubKey, err := proto.Marshal(pubKeyProto)
   157  			require.NoError(t, err)
   158  
   159  			p, err := km.Primitive(sPubKey)
   160  			if strings.Contains(tt.tcName, "with bad content encryption key size") {
   161  				require.EqualError(t, err, errInvalidNISTPECDHKWPublicKey.Error(),
   162  					"newECDHNISTPAESPublicKeyManager primitive from serialized key with invalid serialized key")
   163  				require.Empty(t, p)
   164  
   165  				return
   166  			}
   167  
   168  			if strings.Contains(tt.tcName, "success") {
   169  				require.NoError(t, err)
   170  				require.NotEmpty(t, p)
   171  				return
   172  			}
   173  
   174  			require.Errorf(t, err, tt.tcName)
   175  			require.Empty(t, p)
   176  		})
   177  	}
   178  }
   179  
   180  func TestEcdhNISTPAESPublicKeyManager_DoesSupport(t *testing.T) {
   181  	km := newECDHNISTPAESPublicKeyManager()
   182  	require.False(t, km.DoesSupport("bad/url"))
   183  	require.True(t, km.DoesSupport(nistpECDHKWPublicKeyTypeURL))
   184  }
   185  
   186  func TestEcdhNISTPAESPublicKeyManager_NewKeyAndNewKeyData(t *testing.T) {
   187  	km := newECDHNISTPAESPublicKeyManager()
   188  
   189  	t.Run("Test public key manager NewKey()", func(t *testing.T) {
   190  		k, err := km.NewKey(nil)
   191  		require.EqualError(t, err, "nistpkw_ecdh_public_key_manager: NewKey not implemented")
   192  		require.Empty(t, k)
   193  	})
   194  
   195  	t.Run("Test private key manager NewKeyData()", func(t *testing.T) {
   196  		p, err := km.NewKeyData(nil)
   197  		require.EqualError(t, err, "nistpkw_ecdh_public_key_manager: NewKeyData not implemented")
   198  		require.Empty(t, p)
   199  	})
   200  }