github.com/trustbloc/kms-go@v1.1.2/crypto/tinkcrypto/key_wrapper.go (about)

     1  /*
     2  Copyright SecureKey Technologies Inc. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package tinkcrypto
     8  
     9  import (
    10  	"crypto/ecdsa"
    11  	"crypto/elliptic"
    12  	"encoding/base64"
    13  	"errors"
    14  	"fmt"
    15  	"math/big"
    16  
    17  	josecipher "github.com/go-jose/go-jose/v3/cipher"
    18  	hybrid "github.com/google/tink/go/hybrid/subtle"
    19  	"github.com/google/tink/go/keyset"
    20  	"golang.org/x/crypto/chacha20poly1305"
    21  	"golang.org/x/crypto/curve25519"
    22  
    23  	"github.com/trustbloc/kms-go/util/cryptoutil"
    24  
    25  	cryptoapi "github.com/trustbloc/kms-go/spi/crypto"
    26  
    27  	"github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/aead/subtle"
    28  	"github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/composite/keyio"
    29  	ecdhpb "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/proto/ecdh_aead_go_proto"
    30  )
    31  
    32  const defKeySize = 32
    33  
    34  // deriveKEKAndWrap is the entry point for Crypto.WrapKey().
    35  func (t *Crypto) deriveKEKAndWrap(cek, apu, apv, tag []byte, senderKH interface{}, recPubKey *cryptoapi.PublicKey,
    36  	epkPrv *cryptoapi.PrivateKey, useXC20PKW bool) (*cryptoapi.RecipientWrappedKey, error) {
    37  	var (
    38  		kek         []byte
    39  		epk         *cryptoapi.PublicKey
    40  		wrappingAlg string
    41  		err         error
    42  	)
    43  
    44  	if senderKH != nil { // ecdh1pu
    45  		wrappingAlg, kek, epk, apu, err = t.derive1PUKEK(len(cek), apu, apv, tag, senderKH, recPubKey, epkPrv,
    46  			useXC20PKW)
    47  		if err != nil {
    48  			return nil, fmt.Errorf("deriveKEKAndWrap: error ECDH-1PU kek derivation: %w", err)
    49  		}
    50  	} else { // ecdhes
    51  		wrappingAlg, kek, epk, apu, err = t.deriveESKEK(apu, apv, recPubKey, useXC20PKW)
    52  		if err != nil {
    53  			return nil, fmt.Errorf("deriveKEKAndWrap: error ECDH-ES kek derivation: %w", err)
    54  		}
    55  	}
    56  
    57  	return t.wrapRaw(kek, cek, apu, apv, wrappingAlg, recPubKey.KID, epk, useXC20PKW)
    58  }
    59  
    60  func (t *Crypto) wrapRaw(kek, cek, apu, apv []byte, alg, kid string, epk *cryptoapi.PublicKey,
    61  	useXC20PKW bool) (*cryptoapi.RecipientWrappedKey, error) {
    62  	var wk []byte
    63  
    64  	if useXC20PKW { // nolint: nestif // XC20P key wrap
    65  		aead, err := t.okpKW.createPrimitive(kek)
    66  		if err != nil {
    67  			return nil, fmt.Errorf("deriveKEKAndWrap: failed to create new XC20P primitive: %w", err)
    68  		}
    69  
    70  		wk, err = t.okpKW.wrap(aead, cek)
    71  		if err != nil {
    72  			return nil, fmt.Errorf("deriveKEKAndWrap: failed to XC20P wrap key: %w", err)
    73  		}
    74  	} else { // A256GCM key wrap
    75  		block, err := t.ecKW.createPrimitive(kek)
    76  		if err != nil {
    77  			return nil, fmt.Errorf("deriveKEKAndWrap: failed to create new AES Cipher: %w", err)
    78  		}
    79  
    80  		wk, err = t.ecKW.wrap(block, cek)
    81  		if err != nil {
    82  			return nil, fmt.Errorf("deriveKEKAndWrap: failed to AES wrap key: %w", err)
    83  		}
    84  	}
    85  
    86  	return &cryptoapi.RecipientWrappedKey{
    87  		KID:          kid,
    88  		EncryptedCEK: wk,
    89  		EPK:          *epk,
    90  		APU:          apu,
    91  		APV:          apv,
    92  		Alg:          alg,
    93  	}, nil
    94  }
    95  
    96  // deriveKEKAndUnwrap is the entry point for Crypto.UnwrapKey().
    97  func (t *Crypto) deriveKEKAndUnwrap(alg string, encCEK, apu, apv, tag []byte, epk *cryptoapi.PublicKey, senderKH,
    98  	recKH interface{}) ([]byte, error) {
    99  	var (
   100  		kek []byte
   101  		err error
   102  	)
   103  
   104  	recPrivKH, ok := recKH.(*keyset.Handle)
   105  	if !ok {
   106  		return nil, fmt.Errorf("deriveKEKAndUnwrap: %w", errBadKeyHandleFormat)
   107  	}
   108  
   109  	recipientPrivateKey, err := extractPrivKey(recPrivKH)
   110  	if err != nil {
   111  		return nil, fmt.Errorf("deriveKEKAndUnwrap: %w", err)
   112  	}
   113  
   114  	switch alg {
   115  	case ECDH1PUA128KWAlg, ECDH1PUA192KWAlg, ECDH1PUA256KWAlg, ECDH1PUXC20PKWAlg:
   116  		kek, err = t.derive1PUKEKForUnwrap(alg, apu, apv, tag, epk, senderKH, recipientPrivateKey)
   117  		if err != nil {
   118  			return nil, fmt.Errorf("deriveKEKAndUnwrap: error ECDH-1PU kek derivation: %w", err)
   119  		}
   120  	case ECDHESA256KWAlg, ECDHESXC20PKWAlg:
   121  		kek, err = t.deriveESKEKForUnwrap(alg, apu, apv, epk, recipientPrivateKey)
   122  		if err != nil {
   123  			return nil, fmt.Errorf("deriveKEKAndUnwrap: error ECDH-ES kek derivation: %w", err)
   124  		}
   125  	default:
   126  		return nil, fmt.Errorf("deriveKEKAndUnwrap: unsupported JWE KW Alg '%s'", alg)
   127  	}
   128  
   129  	return t.unwrapRaw(alg, kek, encCEK)
   130  }
   131  
   132  func (t *Crypto) unwrapRaw(alg string, kek, encCEK []byte) ([]byte, error) {
   133  	var wk []byte
   134  
   135  	// key unwrapping does not depend on an option (like key wrapping), because kw primitive can be detected from alg.
   136  	switch alg {
   137  	case ECDHESXC20PKWAlg, ECDH1PUXC20PKWAlg: // XC20P key unwrap
   138  		aead, err := t.okpKW.createPrimitive(kek)
   139  		if err != nil {
   140  			return nil, fmt.Errorf("deriveKEKAndUnwrap: failed to create new XC20P primitive: %w", err)
   141  		}
   142  
   143  		wk, err = t.okpKW.unwrap(aead, encCEK)
   144  		if err != nil {
   145  			return nil, fmt.Errorf("deriveKEKAndUnwrap: failed to XC20P unwrap key: %w", err)
   146  		}
   147  	case ECDHESA256KWAlg, ECDH1PUA128KWAlg, ECDH1PUA192KWAlg, ECDH1PUA256KWAlg:
   148  		// A256GCM key (ES) unwrap or CBC+HMAC (1PU)
   149  		block, err := t.ecKW.createPrimitive(kek)
   150  		if err != nil {
   151  			return nil, fmt.Errorf("deriveKEKAndUnwrap: failed to create new AES Cipher: %w", err)
   152  		}
   153  
   154  		wk, err = t.ecKW.unwrap(block, encCEK)
   155  		if err != nil {
   156  			return nil, fmt.Errorf("deriveKEKAndUnwrap: failed to AES unwrap key: %w", err)
   157  		}
   158  	default:
   159  		return nil, fmt.Errorf("deriveKEKAndUnwrap: cannot unwrap with bad kw alg: '%s'", alg)
   160  	}
   161  
   162  	return wk, nil
   163  }
   164  
   165  func (t *Crypto) derive1PUKEK(cekSize int, apu, apv, tag []byte, senderKH interface{}, recPubKey *cryptoapi.PublicKey,
   166  	epkPrv *cryptoapi.PrivateKey, useXC20PKW bool) (string, []byte, *cryptoapi.PublicKey, []byte, error) {
   167  	var (
   168  		kek         []byte
   169  		epk         *cryptoapi.PublicKey
   170  		err         error
   171  		wrappingAlg string
   172  	)
   173  
   174  	two := 2
   175  
   176  	if useXC20PKW {
   177  		wrappingAlg = ECDH1PUXC20PKWAlg
   178  	} else {
   179  		switch cekSize {
   180  		case subtle.AES128Size * two:
   181  			wrappingAlg = ECDH1PUA128KWAlg
   182  		case subtle.AES192Size * two:
   183  			wrappingAlg = ECDH1PUA192KWAlg
   184  		case subtle.AES256Size * two:
   185  			wrappingAlg = ECDH1PUA256KWAlg
   186  		default:
   187  			return "", nil, nil, nil, fmt.Errorf("derive1PUKEK: invalid CBC-HMAC key size %d", cekSize)
   188  		}
   189  	}
   190  
   191  	switch recPubKey.Type {
   192  	case ecdhpb.KeyType_EC.String():
   193  		wrappingAlg, kek, epk, apu, err = t.derive1PUWithECKey(wrappingAlg, apu, apv, tag, senderKH, recPubKey, epkPrv)
   194  		if err != nil {
   195  			return "", nil, nil, nil, fmt.Errorf("derive1PUKEK: EC key derivation error %w", err)
   196  		}
   197  	case ecdhpb.KeyType_OKP.String():
   198  		wrappingAlg, kek, epk, apu, err = t.derive1PUWithOKPKey(wrappingAlg, apu, apv, tag, senderKH, recPubKey, epkPrv)
   199  		if err != nil {
   200  			return "", nil, nil, nil, fmt.Errorf("derive1PUKEK: OKP key derivation error %w", err)
   201  		}
   202  	default:
   203  		return "", nil, nil, nil, errors.New("derive1PUKEK: invalid recipient key type for ECDH-1PU")
   204  	}
   205  
   206  	return wrappingAlg, kek, epk, apu, nil
   207  }
   208  
   209  func (t *Crypto) derive1PUKEKForUnwrap(alg string, apu, apv, tag []byte, epk *cryptoapi.PublicKey, senderKH interface{},
   210  	recipientPrivateKey interface{}) ([]byte, error) {
   211  	var (
   212  		kek []byte
   213  		err error
   214  	)
   215  
   216  	if senderKH == nil {
   217  		return nil, fmt.Errorf("derive1PUKEKForUnwrap: sender's public keyset handle option is required for '%s'",
   218  			ECDH1PUA256KWAlg)
   219  	}
   220  
   221  	switch epk.Type {
   222  	case ecdhpb.KeyType_EC.String():
   223  		kek, err = t.derive1PUWithECKeyForUnwrap(alg, apu, apv, tag, epk, senderKH, recipientPrivateKey)
   224  		if err != nil {
   225  			return nil, fmt.Errorf("derive1PUKEKForUnwrap: EC key derivation error %w", err)
   226  		}
   227  	case ecdhpb.KeyType_OKP.String():
   228  		kek, err = t.derive1PUWithOKPKeyForUnwrap(alg, apu, apv, tag, epk, senderKH, recipientPrivateKey)
   229  		if err != nil {
   230  			return nil, fmt.Errorf("derive1PUKEKForUnwrap: OKP key derivation error %w", err)
   231  		}
   232  	default:
   233  		return nil, errors.New("derive1PUKEKForUnwrap: invalid EPK key type for ECDH-1PU")
   234  	}
   235  
   236  	return kek, nil
   237  }
   238  
   239  func (t *Crypto) deriveESKEK(apu, apv []byte, recPubKey *cryptoapi.PublicKey,
   240  	useXC20PKW bool) (string, []byte, *cryptoapi.PublicKey, []byte, error) {
   241  	var (
   242  		kek         []byte
   243  		epk         *cryptoapi.PublicKey
   244  		wrappingAlg string
   245  		err         error
   246  	)
   247  
   248  	switch recPubKey.Type {
   249  	case ecdhpb.KeyType_EC.String():
   250  		wrappingAlg, kek, epk, apu, err = t.deriveESWithECKey(apu, apv, recPubKey, useXC20PKW)
   251  		if err != nil {
   252  			return "", nil, nil, nil, fmt.Errorf("deriveESKEK: error %w", err)
   253  		}
   254  	case ecdhpb.KeyType_OKP.String():
   255  		wrappingAlg, kek, epk, apu, err = t.deriveESWithOKPKey(apu, apv, recPubKey, useXC20PKW)
   256  		if err != nil {
   257  			return "", nil, nil, nil, fmt.Errorf("deriveESKEK: error %w", err)
   258  		}
   259  	default:
   260  		return "", nil, nil, nil, errors.New("deriveESKEK: invalid recipient key type for ECDH-ES")
   261  	}
   262  
   263  	return wrappingAlg, kek, epk, apu, nil
   264  }
   265  
   266  func (t *Crypto) deriveESKEKForUnwrap(alg string, apu, apv []byte, epk *cryptoapi.PublicKey,
   267  	recipientPrivateKey interface{}) ([]byte, error) {
   268  	var (
   269  		kek []byte
   270  		err error
   271  	)
   272  
   273  	switch epk.Type {
   274  	case ecdhpb.KeyType_EC.String():
   275  		kek, err = t.deriveESWithECKeyForUnwrap(alg, apu, apv, epk, recipientPrivateKey)
   276  		if err != nil {
   277  			return nil, fmt.Errorf("deriveESKEKForUnwrap: error: %w", err)
   278  		}
   279  	case ecdhpb.KeyType_OKP.String():
   280  		kek, err = t.deriveESWithOKPKeyForUnwrap(alg, apu, apv, epk, recipientPrivateKey)
   281  		if err != nil {
   282  			return nil, fmt.Errorf("deriveESKEKForUnwrap: error: %w", err)
   283  		}
   284  	default:
   285  		return nil, errors.New("deriveESKEKForUnwrap: invalid EPK key type for ECDH-ES")
   286  	}
   287  
   288  	return kek, nil
   289  }
   290  
   291  func (t *Crypto) derive1PUWithECKey(wrappingAlg string, apu, apv, tag []byte, senderKH interface{},
   292  	recPubKey *cryptoapi.PublicKey, epkPrv *cryptoapi.PrivateKey) (string, []byte, *cryptoapi.PublicKey, []byte, error) {
   293  	senderPrivKey, err := ksToPrivateECDSAKey(senderKH)
   294  	if err != nil {
   295  		return "", nil, nil, nil, fmt.Errorf("derive1PUWithECKey: failed to retrieve sender key: %w", err)
   296  	}
   297  
   298  	pubKey, ephemeralPrivKey, err := t.convertRecKeyAndGenOrGetEPKEC(recPubKey, epkPrv)
   299  	if err != nil {
   300  		return "", nil, nil, nil, err
   301  	}
   302  
   303  	ephemeralXBytes := ephemeralPrivKey.PublicKey.X.Bytes()
   304  
   305  	if len(apu) == 0 {
   306  		apu = make([]byte, base64.RawURLEncoding.EncodedLen(len(ephemeralXBytes)))
   307  		base64.RawURLEncoding.Encode(apu, ephemeralXBytes)
   308  	}
   309  
   310  	keySize := aesCEKSize1PU(wrappingAlg)
   311  
   312  	kek, err := t.ecKW.deriveSender1Pu(wrappingAlg, apu, apv, tag, ephemeralPrivKey, senderPrivKey, pubKey, keySize)
   313  	if err != nil {
   314  		return "", nil, nil, nil, fmt.Errorf("derive1PUWithECKey: failed to derive key: %w", err)
   315  	}
   316  
   317  	epk := &cryptoapi.PublicKey{
   318  		X:     ephemeralXBytes,
   319  		Y:     ephemeralPrivKey.PublicKey.Y.Bytes(),
   320  		Curve: ephemeralPrivKey.PublicKey.Curve.Params().Name,
   321  		Type:  recPubKey.Type,
   322  	}
   323  
   324  	return wrappingAlg, kek, epk, apu, nil
   325  }
   326  
   327  func (t *Crypto) derive1PUWithECKeyForUnwrap(alg string, apu, apv, tag []byte, epk *cryptoapi.PublicKey,
   328  	senderKH interface{}, recipientPrivateKey interface{}) ([]byte, error) {
   329  	var (
   330  		senderPubKey *ecdsa.PublicKey
   331  		epkCurve     elliptic.Curve
   332  		err          error
   333  	)
   334  
   335  	senderPubKey, err = ksToPublicECDSAKey(senderKH, t.ecKW)
   336  	if err != nil {
   337  		return nil, fmt.Errorf("derive1PUWithECKeyForUnwrap: failed to retrieve sender key: %w", err)
   338  	}
   339  
   340  	epkCurve, err = t.ecKW.getCurve(epk.Curve)
   341  	if err != nil {
   342  		return nil, fmt.Errorf("derive1PUWithECKeyForUnwrap: failed to GetCurve: %w", err)
   343  	}
   344  
   345  	epkPubKey := &ecdsa.PublicKey{
   346  		Curve: epkCurve,
   347  		X:     new(big.Int).SetBytes(epk.X),
   348  		Y:     new(big.Int).SetBytes(epk.Y),
   349  	}
   350  
   351  	recPrivECKey, ok := recipientPrivateKey.(*hybrid.ECPrivateKey)
   352  	if !ok {
   353  		return nil, errors.New("derive1PUWithECKeyForUnwrap: recipient key is not an EC key")
   354  	}
   355  
   356  	recPrivKey := hybridECPrivToECDSAKey(recPrivECKey)
   357  
   358  	keySize := aesCEKSize1PU(alg)
   359  
   360  	kek, err := t.ecKW.deriveRecipient1Pu(alg, apu, apv, tag, epkPubKey, senderPubKey, recPrivKey, keySize)
   361  	if err != nil {
   362  		return nil, fmt.Errorf("derive1PUWithECKeyForUnwrap: failed to derive kek: %w", err)
   363  	}
   364  
   365  	return kek, nil
   366  }
   367  
   368  func aesCEKSize1PU(alg string) int {
   369  	keySize := defKeySize
   370  	two := 2
   371  
   372  	switch alg {
   373  	case ECDH1PUA128KWAlg:
   374  		keySize = subtle.AES128Size * two
   375  	case ECDH1PUA192KWAlg:
   376  		keySize = subtle.AES192Size * two
   377  	case ECDH1PUA256KWAlg:
   378  		keySize = subtle.AES256Size * two
   379  	}
   380  
   381  	return keySize
   382  }
   383  
   384  func (t *Crypto) deriveESWithECKeyForUnwrap(alg string, apu, apv []byte, epk *cryptoapi.PublicKey,
   385  	recipientPrivateKey interface{}) ([]byte, error) {
   386  	var (
   387  		epkCurve elliptic.Curve
   388  		err      error
   389  	)
   390  
   391  	epkCurve, err = t.ecKW.getCurve(epk.Curve)
   392  	if err != nil {
   393  		return nil, fmt.Errorf("deriveESWithECKeyForUnwrap: failed to GetCurve: %w", err)
   394  	}
   395  
   396  	epkPubKey := &ecdsa.PublicKey{
   397  		Curve: epkCurve,
   398  		X:     new(big.Int).SetBytes(epk.X),
   399  		Y:     new(big.Int).SetBytes(epk.Y),
   400  	}
   401  
   402  	recPrivECKey, ok := recipientPrivateKey.(*hybrid.ECPrivateKey)
   403  	if !ok {
   404  		return nil, errors.New("deriveESWithECKeyForUnwrap: recipient key is not an EC key")
   405  	}
   406  
   407  	recPrivKey := hybridECPrivToECDSAKey(recPrivECKey)
   408  
   409  	if recPrivKey.Curve != epkPubKey.Curve {
   410  		return nil, errors.New("deriveESWithECKeyForUnwrap: recipient and ephemeral keys are not on the same curve")
   411  	}
   412  
   413  	return josecipher.DeriveECDHES(alg, apu, apv, recPrivKey, epkPubKey, defKeySize), nil
   414  }
   415  
   416  func (t *Crypto) deriveESWithECKey(apu, apv []byte, recPubKey *cryptoapi.PublicKey,
   417  	useXC20PKW bool) (string, []byte, *cryptoapi.PublicKey, []byte, error) {
   418  	wrappingAlg := ECDHESA256KWAlg
   419  
   420  	if useXC20PKW {
   421  		wrappingAlg = ECDHESXC20PKWAlg
   422  	}
   423  
   424  	recECPubKey, ephemeralPrivKey, err := t.convertRecKeyAndGenOrGetEPKEC(recPubKey, nil)
   425  	if err != nil {
   426  		return "", nil, nil, nil, fmt.Errorf("deriveESWithECKey: failed to generate ephemeral key: %w", err)
   427  	}
   428  
   429  	ephemeralXBytes := ephemeralPrivKey.PublicKey.X.Bytes()
   430  
   431  	if len(apu) == 0 {
   432  		apu = make([]byte, base64.RawURLEncoding.EncodedLen(len(ephemeralXBytes)))
   433  		base64.RawURLEncoding.Encode(apu, ephemeralXBytes)
   434  	}
   435  
   436  	kek := josecipher.DeriveECDHES(wrappingAlg, apu, apv, ephemeralPrivKey, recECPubKey, defKeySize)
   437  	epk := &cryptoapi.PublicKey{
   438  		X:     ephemeralXBytes,
   439  		Y:     ephemeralPrivKey.PublicKey.Y.Bytes(),
   440  		Curve: ephemeralPrivKey.PublicKey.Curve.Params().Name,
   441  		Type:  recPubKey.Type,
   442  	}
   443  
   444  	return wrappingAlg, kek, epk, apu, nil
   445  }
   446  
   447  func (t *Crypto) derive1PUWithOKPKey(wrappingAlg string, apu, apv, tag []byte, senderKH interface{},
   448  	recPubKey *cryptoapi.PublicKey, epkPrv *cryptoapi.PrivateKey) (string, []byte, *cryptoapi.PublicKey, []byte, error) {
   449  	senderPrivKey, err := ksToPrivateX25519Key(senderKH)
   450  	if err != nil {
   451  		return "", nil, nil, nil, fmt.Errorf("derive1PUWithOKPKey: failed to retrieve sender key: %w", err)
   452  	}
   453  
   454  	ephemeralPubKey, ephemeralPrivKey, err := t.generateOrGetEphemeralOKPKey(epkPrv)
   455  	if err != nil {
   456  		return "", nil, nil, nil, fmt.Errorf("derive1PUWithOKPKey: failed to generate ephemeral key: %w", err)
   457  	}
   458  
   459  	if len(apu) == 0 {
   460  		apu = make([]byte, base64.RawURLEncoding.EncodedLen(len(ephemeralPubKey)))
   461  		base64.RawURLEncoding.Encode(apu, ephemeralPubKey)
   462  	}
   463  
   464  	kek, err := t.okpKW.deriveSender1Pu(wrappingAlg, apu, apv, tag, ephemeralPrivKey, senderPrivKey, recPubKey.X,
   465  		defKeySize)
   466  	if err != nil {
   467  		return "", nil, nil, nil, fmt.Errorf("derive1PUWithOKPKey: failed to derive key: %w", err)
   468  	}
   469  
   470  	epk := &cryptoapi.PublicKey{
   471  		X:     ephemeralPubKey,
   472  		Curve: "X25519",
   473  		Type:  recPubKey.Type,
   474  	}
   475  
   476  	return wrappingAlg, kek, epk, apu, nil
   477  }
   478  
   479  func (t *Crypto) derive1PUWithOKPKeyForUnwrap(alg string, apu, apv, tag []byte, epk *cryptoapi.PublicKey,
   480  	senderKH interface{}, recipientPrivateKey interface{}) ([]byte, error) {
   481  	senderPubKey, err := ksToPublicX25519Key(senderKH)
   482  	if err != nil {
   483  		return nil, fmt.Errorf("derive1PUWithOKPKeyForUnwrap: failed to retrieve sender key: %w", err)
   484  	}
   485  
   486  	recPrivOKPKey, ok := recipientPrivateKey.([]byte)
   487  	if !ok {
   488  		return nil, errors.New("derive1PUWithOKPKeyForUnwrap: recipient key is not an OKP key")
   489  	}
   490  
   491  	kek, err := t.okpKW.deriveRecipient1Pu(alg, apu, apv, tag, epk.X, senderPubKey, recPrivOKPKey, defKeySize)
   492  	if err != nil {
   493  		return nil, fmt.Errorf("derive1PUWithOKPKeyForUnwrap: failed to derive kek: %w", err)
   494  	}
   495  
   496  	return kek, nil
   497  }
   498  
   499  func (t *Crypto) deriveESWithOKPKey(apu, apv []byte, recPubKey *cryptoapi.PublicKey,
   500  	useXC20PKW bool) (string, []byte, *cryptoapi.PublicKey, []byte, error) {
   501  	wrappingAlg := ECDHESA256KWAlg
   502  
   503  	if useXC20PKW {
   504  		wrappingAlg = ECDHESXC20PKWAlg
   505  	}
   506  
   507  	ephemeralPubKey, ephemeralPrivKey, err := t.generateOrGetEphemeralOKPKey(nil)
   508  	if err != nil {
   509  		return "", nil, nil, nil, fmt.Errorf("deriveESWithOKPKey: failed to generate ephemeral key: %w", err)
   510  	}
   511  
   512  	ephemeralPrivChacha := new([chacha20poly1305.KeySize]byte)
   513  	copy(ephemeralPrivChacha[:], ephemeralPrivKey)
   514  
   515  	recPubKeyChacha := new([chacha20poly1305.KeySize]byte)
   516  	copy(recPubKeyChacha[:], recPubKey.X)
   517  
   518  	if len(apu) == 0 {
   519  		apu = make([]byte, base64.RawURLEncoding.EncodedLen(len(ephemeralPubKey)))
   520  		base64.RawURLEncoding.Encode(apu, ephemeralPubKey)
   521  	}
   522  
   523  	z, err := cryptoutil.DeriveECDHX25519(ephemeralPrivChacha, recPubKeyChacha)
   524  	if err != nil {
   525  		return "", nil, nil, nil, fmt.Errorf("deriveESWithOKPKey: failed to derive 25519 kek: %w", err)
   526  	}
   527  
   528  	kek := kdf(wrappingAlg, z, apu, apv, chacha20poly1305.KeySize)
   529  
   530  	epk := &cryptoapi.PublicKey{
   531  		X:     ephemeralPubKey,
   532  		Curve: "X25519",
   533  		Type:  recPubKey.Type,
   534  	}
   535  
   536  	return wrappingAlg, kek, epk, apu, nil
   537  }
   538  
   539  func (t *Crypto) deriveESWithOKPKeyForUnwrap(alg string, apu, apv []byte, epk *cryptoapi.PublicKey,
   540  	recipientPrivateKey interface{}) ([]byte, error) {
   541  	recPrivOKPKey, ok := recipientPrivateKey.([]byte)
   542  	if !ok {
   543  		return nil, errors.New("deriveESWithOKPKeyForUnwrap: recipient key is not an OKP key")
   544  	}
   545  
   546  	recPrivKeyChacha := new([chacha20poly1305.KeySize]byte)
   547  	copy(recPrivKeyChacha[:], recPrivOKPKey)
   548  
   549  	epkChacha := new([chacha20poly1305.KeySize]byte)
   550  	copy(epkChacha[:], epk.X)
   551  
   552  	z, err := cryptoutil.DeriveECDHX25519(recPrivKeyChacha, epkChacha)
   553  	if err != nil {
   554  		return nil, fmt.Errorf("deriveESWithOKPKeyForUnwrap: %w", err)
   555  	}
   556  
   557  	return kdf(alg, z, apu, apv, chacha20poly1305.KeySize), nil
   558  }
   559  
   560  // convertRecKeyAndGenOrGetEPKEC converts recPubKey into *ecdsa.PublicKey and generates an ephemeral EC private key
   561  // as *ecdsa.PrivateKey.
   562  func (t *Crypto) convertRecKeyAndGenOrGetEPKEC(recPubKey *cryptoapi.PublicKey,
   563  	prvEPK *cryptoapi.PrivateKey) (*ecdsa.PublicKey, *ecdsa.PrivateKey,
   564  	error) {
   565  	c, err := t.ecKW.getCurve(recPubKey.Curve)
   566  	if err != nil {
   567  		return nil, nil, fmt.Errorf("convertRecKeyAndGenOrGetEPKEC: failed to get curve of recipient key: %w",
   568  			err)
   569  	}
   570  
   571  	recECPubKey := &ecdsa.PublicKey{
   572  		Curve: c,
   573  		X:     new(big.Int).SetBytes(recPubKey.X),
   574  		Y:     new(big.Int).SetBytes(recPubKey.Y),
   575  	}
   576  
   577  	if prvEPK == nil {
   578  		ephemeralPrivKey, err := t.ecKW.generateKey(recECPubKey.Curve)
   579  		if err != nil {
   580  			return nil, nil, fmt.Errorf("convertRecKeyAndGenOrGetEPKEC: failed to generate EPK: %w", err)
   581  		}
   582  
   583  		return recECPubKey, ephemeralPrivKey.(*ecdsa.PrivateKey), nil
   584  	}
   585  
   586  	return recECPubKey, &ecdsa.PrivateKey{
   587  		PublicKey: ecdsa.PublicKey{
   588  			Curve: c,
   589  			X:     new(big.Int).SetBytes(prvEPK.PublicKey.X),
   590  			Y:     new(big.Int).SetBytes(prvEPK.PublicKey.Y),
   591  		},
   592  		D: new(big.Int).SetBytes(prvEPK.D),
   593  	}, nil
   594  }
   595  
   596  func (t *Crypto) generateOrGetEphemeralOKPKey(epkPrv *cryptoapi.PrivateKey) ([]byte, []byte, error) {
   597  	if epkPrv == nil {
   598  		ephemeralPrivKey, err := t.okpKW.generateKey(nil)
   599  		if err != nil {
   600  			return nil, nil, err
   601  		}
   602  
   603  		ephemeralPrivKeyByte, ok := ephemeralPrivKey.([]byte)
   604  		if !ok {
   605  			return nil, nil, errors.New("invalid ephemeral key type, not OKP, want []byte for OKP")
   606  		}
   607  
   608  		ephemeralPubKey, err := curve25519.X25519(ephemeralPrivKeyByte, curve25519.Basepoint)
   609  		if err != nil {
   610  			return nil, nil, err
   611  		}
   612  
   613  		return ephemeralPubKey, ephemeralPrivKeyByte, nil
   614  	}
   615  
   616  	return epkPrv.PublicKey.X, epkPrv.D, nil
   617  }
   618  
   619  func ksToPrivateECDSAKey(ks interface{}) (*ecdsa.PrivateKey, error) {
   620  	senderKH, ok := ks.(*keyset.Handle)
   621  	if !ok {
   622  		return nil, fmt.Errorf("ksToPrivateECDSAKey: %w", errBadKeyHandleFormat)
   623  	}
   624  
   625  	senderHPrivKey, err := extractPrivKey(senderKH)
   626  	if err != nil {
   627  		return nil, fmt.Errorf("ksToPrivateECDSAKey: failed to extract sender key: %w", err)
   628  	}
   629  
   630  	prvKey, ok := senderHPrivKey.(*hybrid.ECPrivateKey)
   631  	if !ok {
   632  		return nil, errors.New("ksToPrivateECDSAKey: not an EC key")
   633  	}
   634  
   635  	return hybridECPrivToECDSAKey(prvKey), nil
   636  }
   637  
   638  func ksToPrivateX25519Key(ks interface{}) ([]byte, error) {
   639  	senderKH, ok := ks.(*keyset.Handle)
   640  	if !ok {
   641  		return nil, fmt.Errorf("ksToPrivateX25519Key: %w", errBadKeyHandleFormat)
   642  	}
   643  
   644  	senderPrivKey, err := extractPrivKey(senderKH)
   645  	if err != nil {
   646  		return nil, fmt.Errorf("ksToPrivateX25519Key: failed to extract sender key: %w", err)
   647  	}
   648  
   649  	prvKey, ok := senderPrivKey.([]byte)
   650  	if !ok {
   651  		return nil, errors.New("ksToPrivateX25519Key: not an OKP key")
   652  	}
   653  
   654  	return prvKey, nil
   655  }
   656  
   657  func ksToPublicECDSAKey(ks interface{}, kw keyWrapper) (*ecdsa.PublicKey, error) {
   658  	switch kst := ks.(type) {
   659  	case *keyset.Handle:
   660  		sPubKey, err := keyio.ExtractPrimaryPublicKey(kst)
   661  		if err != nil {
   662  			return nil, fmt.Errorf("ksToPublicECDSAKey: failed to extract public key from keyset handle: %w", err)
   663  		}
   664  
   665  		sCurve, err := kw.getCurve(sPubKey.Curve)
   666  		if err != nil {
   667  			return nil, fmt.Errorf("ksToPublicECDSAKey: failed to GetCurve: %w", err)
   668  		}
   669  
   670  		return &ecdsa.PublicKey{
   671  			Curve: sCurve,
   672  			X:     new(big.Int).SetBytes(sPubKey.X),
   673  			Y:     new(big.Int).SetBytes(sPubKey.Y),
   674  		}, nil
   675  	case *cryptoapi.PublicKey:
   676  		sCurve, err := kw.getCurve(kst.Curve)
   677  		if err != nil {
   678  			return nil, fmt.Errorf("ksToPublicECDSAKey: failed to GetCurve: %w", err)
   679  		}
   680  
   681  		return &ecdsa.PublicKey{
   682  			Curve: sCurve,
   683  			X:     new(big.Int).SetBytes(kst.X),
   684  			Y:     new(big.Int).SetBytes(kst.Y),
   685  		}, nil
   686  	case *ecdsa.PublicKey:
   687  		return kst, nil
   688  	default:
   689  		return nil, fmt.Errorf("ksToPublicECDSAKey: unsupported keyset type %+v", kst)
   690  	}
   691  }
   692  
   693  func ksToPublicX25519Key(ks interface{}) ([]byte, error) {
   694  	switch kst := ks.(type) {
   695  	case *keyset.Handle:
   696  		sPubKey, err := keyio.ExtractPrimaryPublicKey(kst)
   697  		if err != nil {
   698  			return nil, fmt.Errorf("ksToPublicX25519Key: failed to extract public key from keyset handle: %w", err)
   699  		}
   700  
   701  		return sPubKey.X, nil
   702  	case *cryptoapi.PublicKey:
   703  		return kst.X, nil
   704  	default:
   705  		return nil, fmt.Errorf("ksToPublicX25519Key: unsupported keyset type %+v", kst)
   706  	}
   707  }