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 }