github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/libkb/passphrase_stream_cache.go (about)

     1  // Copyright 2015 Keybase, Inc. All rights reserved. Use of
     2  // this source code is governed by the included BSD license.
     3  
     4  package libkb
     5  
     6  import (
     7  	"fmt"
     8  	"sync"
     9  )
    10  
    11  type PassphraseStreamCache struct {
    12  	sync.Mutex
    13  	tsec             *LockedTriplesec
    14  	passphraseStream *PassphraseStream
    15  }
    16  
    17  // LockedTriplesec is a wrapper around a Triplesec interface,
    18  // which allows multiple goroutines to handle the same underlying
    19  // Triplesec at the same time. The mechanism is simply a mutex
    20  // wrapping all accesses.
    21  type LockedTriplesec struct {
    22  	sync.Mutex
    23  	t Triplesec
    24  }
    25  
    26  func (t *LockedTriplesec) DeriveKey(l int) ([]byte, []byte, error) {
    27  	t.Lock()
    28  	defer t.Unlock()
    29  	return t.t.DeriveKey(l)
    30  }
    31  
    32  func (t *LockedTriplesec) Decrypt(b []byte) ([]byte, error) {
    33  	t.Lock()
    34  	defer t.Unlock()
    35  	return t.t.Decrypt(b)
    36  }
    37  
    38  func (t *LockedTriplesec) Encrypt(b []byte) ([]byte, error) {
    39  	t.Lock()
    40  	defer t.Unlock()
    41  	return t.t.Encrypt(b)
    42  }
    43  
    44  func (t *LockedTriplesec) Scrub() {
    45  	t.Lock()
    46  	defer t.Unlock()
    47  	t.t.Scrub()
    48  }
    49  
    50  func NewLockedTriplesec(t Triplesec) *LockedTriplesec {
    51  	if t == nil {
    52  		return nil
    53  	}
    54  	return &LockedTriplesec{t: t}
    55  }
    56  
    57  var _ Triplesec = (*LockedTriplesec)(nil)
    58  
    59  func NewPassphraseStreamCache(tsec Triplesec, ps *PassphraseStream) *PassphraseStreamCache {
    60  	return &PassphraseStreamCache{
    61  		tsec:             NewLockedTriplesec(tsec),
    62  		passphraseStream: ps,
    63  	}
    64  }
    65  
    66  func (s *PassphraseStreamCache) TriplesecAndGeneration() (Triplesec, PassphraseGeneration) {
    67  	var zed PassphraseGeneration
    68  	if s == nil {
    69  		return nil, zed
    70  	}
    71  	s.Lock()
    72  	defer s.Unlock()
    73  
    74  	// Beware the classic Go `nil` interface bug...
    75  	if s.tsec == nil {
    76  		return nil, zed
    77  	}
    78  	if s.passphraseStream == nil {
    79  		return nil, zed
    80  	}
    81  	ppgen := s.passphraseStream.Generation()
    82  	if ppgen.IsNil() {
    83  		return nil, zed
    84  	}
    85  
    86  	return s.tsec, ppgen
    87  }
    88  
    89  func (s *PassphraseStreamCache) PassphraseStreamAndTriplesec() (pps *PassphraseStream, tsec Triplesec) {
    90  
    91  	if s == nil {
    92  		return nil, nil
    93  	}
    94  
    95  	s.Lock()
    96  	defer s.Unlock()
    97  
    98  	// Beware the classic Go `nil` interface bug...
    99  	if s.tsec != nil {
   100  		tsec = s.tsec
   101  	}
   102  
   103  	if s.passphraseStream != nil {
   104  		pps = s.passphraseStream.Clone()
   105  	}
   106  
   107  	return pps, tsec
   108  }
   109  
   110  // PassphraseStream returns a copy of the currently cached passphrase stream,
   111  // or nil if none exists.
   112  func (s *PassphraseStreamCache) PassphraseStream() *PassphraseStream {
   113  	if s == nil {
   114  		return nil
   115  	}
   116  	s.Lock()
   117  	defer s.Unlock()
   118  	return s.passphraseStream.Clone()
   119  }
   120  
   121  func (s *PassphraseStreamCache) MutatePassphraseStream(f func(*PassphraseStream)) bool {
   122  	if s == nil {
   123  		return false
   124  	}
   125  	s.Lock()
   126  	defer s.Unlock()
   127  	if s.passphraseStream == nil {
   128  		return false
   129  	}
   130  	f(s.passphraseStream)
   131  	return true
   132  }
   133  
   134  func (s *PassphraseStreamCache) Valid() bool {
   135  	if s == nil {
   136  		return false
   137  	}
   138  	s.Lock()
   139  	defer s.Unlock()
   140  	return s.passphraseStream != nil && s.tsec != nil
   141  }
   142  
   143  func (s *PassphraseStreamCache) ValidPassphraseStream() bool {
   144  	if s == nil {
   145  		return false
   146  	}
   147  	s.Lock()
   148  	defer s.Unlock()
   149  	return s.passphraseStream != nil
   150  }
   151  
   152  func (s *PassphraseStreamCache) ValidTsec() bool {
   153  	if s == nil {
   154  		return false
   155  	}
   156  	s.Lock()
   157  	defer s.Unlock()
   158  	return s.tsec != nil
   159  }
   160  
   161  func (s *PassphraseStreamCache) Clear() {
   162  	if s == nil {
   163  		return
   164  	}
   165  	s.Lock()
   166  	defer s.Unlock()
   167  	if s.tsec != nil {
   168  		s.tsec.Scrub()
   169  		s.tsec = nil
   170  	}
   171  	s.passphraseStream = nil
   172  }
   173  
   174  func (s *PassphraseStreamCache) Dump() {
   175  	fmt.Printf("PassphraseStreamCache:\n")
   176  	if s == nil {
   177  		fmt.Printf("nil\n")
   178  		return
   179  	}
   180  	s.Lock()
   181  	defer s.Unlock()
   182  	fmt.Printf("PassphraseStreamCache:\n")
   183  	fmt.Printf("Valid: %v\n", s.Valid())
   184  	fmt.Printf("\n")
   185  }