key_package_crypto.mx raw

   1  package mls
   2  
   3  // MLS key package crypto operations (RFC 9420 ยง10).
   4  
   5  import "errors"
   6  
   7  var (
   8  	errKeyPackageVersionMismatch = errors.New("mls: key package version mismatch")
   9  	errKeyPackageSuiteMismatch   = errors.New("mls: key package cipher suite mismatch")
  10  	errKeyPackageBadSource       = errors.New("mls: key package leaf node invalid source")
  11  	errKeyPackageBadSignature    = errors.New("mls: invalid key package signature")
  12  	errKeyPackageKeysMatch       = errors.New("mls: key package init key equals encryption key")
  13  )
  14  
  15  func (pkg *KeyPackage) sign(signerPriv signaturePrivateKey) error {
  16  	var w Writer
  17  	pkg.marshalTBS(&w)
  18  	rawTBS, err := w.bytes()
  19  	if err != nil {
  20  		return err
  21  	}
  22  	sig, err := pkg.cipherSuite.signWithLabel(signerPriv, []byte("KeyPackageTBS"), rawTBS)
  23  	if err != nil {
  24  		return err
  25  	}
  26  	pkg.signature = sig
  27  	return nil
  28  }
  29  
  30  func (pkg *KeyPackage) verifySignature() bool {
  31  	var w Writer
  32  	pkg.marshalTBS(&w)
  33  	rawTBS, err := w.bytes()
  34  	if err != nil {
  35  		return false
  36  	}
  37  	return pkg.cipherSuite.verifyWithLabel(pkg.leafNode.signatureKey, []byte("KeyPackageTBS"), rawTBS, pkg.signature)
  38  }
  39  
  40  func (pkg *KeyPackage) verify(ctx *groupContext) error {
  41  	if pkg.version != ctx.version {
  42  		return errKeyPackageVersionMismatch
  43  	}
  44  	if pkg.cipherSuite != ctx.cipherSuite {
  45  		return errKeyPackageSuiteMismatch
  46  	}
  47  	if pkg.leafNode.leafNodeSource != leafNodeSourceKeyPackage {
  48  		return errKeyPackageBadSource
  49  	}
  50  	if !pkg.verifySignature() {
  51  		return errKeyPackageBadSignature
  52  	}
  53  	if bytesEqual(pkg.leafNode.encryptionKey, pkg.initKey) {
  54  		return errKeyPackageKeysMatch
  55  	}
  56  	return nil
  57  }
  58  
  59  func (pkg *KeyPackage) GenerateRef() (KeyPackageRef, error) {
  60  	var w Writer
  61  	pkg.marshal(&w)
  62  	raw, err := w.bytes()
  63  	if err != nil {
  64  		return nil, err
  65  	}
  66  	h, err := pkg.cipherSuite.refHash([]byte("MLS 1.0 KeyPackage Reference"), raw)
  67  	if err != nil {
  68  		return nil, err
  69  	}
  70  	return KeyPackageRef(h), nil
  71  }
  72  
  73  // GenerateKeyPairPackage creates a new key pair package for suite 0x0003.
  74  // nowUnix is the current time as Unix seconds (caller provides from DOM/SW context).
  75  func GenerateKeyPairPackage(cs CipherSuite, credential *Credential, nowUnix int64) (*KeyPairPackage, error) {
  76  	return GenerateKeyPairPackageWithOptions(cs, credential, nil, nowUnix)
  77  }
  78  
  79  // GenerateKeyPairPackageWithOptions creates a key pair package with options.
  80  func GenerateKeyPairPackageWithOptions(cs CipherSuite, credential *Credential, opts *KeyPackageOptions, nowUnix int64) (*KeyPairPackage, error) {
  81  	initPub, initPriv, err := cs.generateEncryptionKeyPair()
  82  	if err != nil {
  83  		return nil, err
  84  	}
  85  	encPub, encPriv, err := cs.generateEncryptionKeyPair()
  86  	if err != nil {
  87  		return nil, err
  88  	}
  89  	sigPub, sigPriv, err := cs.generateSignatureKeyPair()
  90  	if err != nil {
  91  		return nil, err
  92  	}
  93  
  94  	var capExts []extensionType
  95  	var leafExts []extension
  96  	var kpExts []extension
  97  	if opts != nil {
  98  		capExts = opts.CapabilityExtensions
  99  		leafExts = opts.LeafExtensions
 100  		kpExts = opts.KeyPackageExtensions
 101  	}
 102  	if capExts == nil {
 103  		capExts = []extensionType{extensionTypeRatchetTree}
 104  	}
 105  
 106  	// Lifetime: now - 1h to now + 84 days
 107  	notBefore := nowUnix - 3600
 108  	notAfter := nowUnix + 84*24*3600
 109  
 110  	keyPkg := KeyPackage{
 111  		version:     protocolVersionMLS10,
 112  		cipherSuite: cs,
 113  		initKey:     initPub,
 114  		leafNode: leafNode{
 115  			encryptionKey:  encPub,
 116  			signatureKey:   sigPub,
 117  			leafNodeSource: leafNodeSourceKeyPackage,
 118  			credential:     *credential,
 119  			capabilities: capabilities{
 120  				versions:     []protocolVersion{protocolVersionMLS10},
 121  				cipherSuites: []CipherSuite{cs},
 122  				extensions:   capExts,
 123  				proposals:    []proposalType{proposalTypeAdd, proposalTypeUpdate, proposalTypeRemove},
 124  				credentials:  []credentialType{credentialTypeBasic},
 125  			},
 126  			lifetime:   &lifetime{notBefore: uint64(notBefore), notAfter: uint64(notAfter)},
 127  			extensions: leafExts,
 128  		},
 129  		extensions: kpExts,
 130  	}
 131  
 132  	if err := keyPkg.leafNode.sign(cs, nil, 0, sigPriv); err != nil {
 133  		return nil, err
 134  	}
 135  	if err := keyPkg.sign(sigPriv); err != nil {
 136  		return nil, err
 137  	}
 138  
 139  	return &KeyPairPackage{
 140  		Public: keyPkg,
 141  		Private: PrivateKeyPackage{
 142  			InitKey:       initPriv,
 143  			EncryptionKey: encPriv,
 144  			SignatureKey:  sigPriv,
 145  		},
 146  	}, nil
 147  }
 148