key_registry.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. /*
  2. * SPDX-FileCopyrightText: © Hypermode Inc. <hello@hypermode.com>
  3. * SPDX-License-Identifier: Apache-2.0
  4. */
  5. package badger
  6. import (
  7. "bytes"
  8. "crypto/aes"
  9. "crypto/rand"
  10. "encoding/binary"
  11. "hash/crc32"
  12. "io"
  13. "os"
  14. "path/filepath"
  15. "sync"
  16. "time"
  17. "github.com/dgraph-io/badger/v4/pb"
  18. "github.com/dgraph-io/badger/v4/y"
  19. "google.golang.org/protobuf/proto"
  20. )
  21. const (
  22. // KeyRegistryFileName is the file name for the key registry file.
  23. KeyRegistryFileName = "KEYREGISTRY"
  24. // KeyRegistryRewriteFileName is the file name for the rewrite key registry file.
  25. KeyRegistryRewriteFileName = "REWRITE-KEYREGISTRY"
  26. )
  27. // SanityText is used to check whether the given user provided storage key is valid or not
  28. var sanityText = []byte("Hello Badger")
  29. // KeyRegistry used to maintain all the data keys.
  30. type KeyRegistry struct {
  31. sync.RWMutex
  32. dataKeys map[uint64]*pb.DataKey
  33. lastCreated int64 //lastCreated is the timestamp(seconds) of the last data key generated.
  34. nextKeyID uint64
  35. fp *os.File
  36. opt KeyRegistryOptions
  37. }
  38. type KeyRegistryOptions struct {
  39. Dir string
  40. ReadOnly bool
  41. EncryptionKey []byte
  42. EncryptionKeyRotationDuration time.Duration
  43. InMemory bool
  44. }
  45. // newKeyRegistry returns KeyRegistry.
  46. func newKeyRegistry(opt KeyRegistryOptions) *KeyRegistry {
  47. return &KeyRegistry{
  48. dataKeys: make(map[uint64]*pb.DataKey),
  49. nextKeyID: 0,
  50. opt: opt,
  51. }
  52. }
  53. // OpenKeyRegistry opens key registry if it exists, otherwise it'll create key registry
  54. // and returns key registry.
  55. func OpenKeyRegistry(opt KeyRegistryOptions) (*KeyRegistry, error) {
  56. // sanity check the encryption key length.
  57. if len(opt.EncryptionKey) > 0 {
  58. switch len(opt.EncryptionKey) {
  59. default:
  60. return nil, y.Wrapf(ErrInvalidEncryptionKey, "During OpenKeyRegistry")
  61. case 16, 24, 32:
  62. break
  63. }
  64. }
  65. // If db is opened in InMemory mode, we don't need to write key registry to the disk.
  66. if opt.InMemory {
  67. return newKeyRegistry(opt), nil
  68. }
  69. path := filepath.Join(opt.Dir, KeyRegistryFileName)
  70. var flags y.Flags
  71. if opt.ReadOnly {
  72. flags |= y.ReadOnly
  73. } else {
  74. flags |= y.Sync
  75. }
  76. fp, err := y.OpenExistingFile(path, flags)
  77. // OpenExistingFile just open file.
  78. // So checking whether the file exist or not. If not
  79. // We'll create new keyregistry.
  80. if os.IsNotExist(err) {
  81. // Creating new registry file if not exist.
  82. kr := newKeyRegistry(opt)
  83. if opt.ReadOnly {
  84. return kr, nil
  85. }
  86. // Writing the key registry to the file.
  87. if err := WriteKeyRegistry(kr, opt); err != nil {
  88. return nil, y.Wrapf(err, "Error while writing key registry.")
  89. }
  90. fp, err = y.OpenExistingFile(path, flags)
  91. if err != nil {
  92. return nil, y.Wrapf(err, "Error while opening newly created key registry.")
  93. }
  94. } else if err != nil {
  95. return nil, y.Wrapf(err, "Error while opening key registry.")
  96. }
  97. kr, err := readKeyRegistry(fp, opt)
  98. if err != nil {
  99. // This case happens only if the file is opened properly and
  100. // not able to read.
  101. fp.Close()
  102. return nil, err
  103. }
  104. if opt.ReadOnly {
  105. // We'll close the file in readonly mode.
  106. return kr, fp.Close()
  107. }
  108. kr.fp = fp
  109. return kr, nil
  110. }
  111. // keyRegistryIterator reads all the datakey from the key registry
  112. type keyRegistryIterator struct {
  113. encryptionKey []byte
  114. fp *os.File
  115. // lenCrcBuf contains crc buf and data length to move forward.
  116. lenCrcBuf [8]byte
  117. }
  118. // newKeyRegistryIterator returns iterator which will allow you to iterate
  119. // over the data key of the key registry.
  120. func newKeyRegistryIterator(fp *os.File, encryptionKey []byte) (*keyRegistryIterator, error) {
  121. return &keyRegistryIterator{
  122. encryptionKey: encryptionKey,
  123. fp: fp,
  124. lenCrcBuf: [8]byte{},
  125. }, validRegistry(fp, encryptionKey)
  126. }
  127. // validRegistry checks that given encryption key is valid or not.
  128. func validRegistry(fp *os.File, encryptionKey []byte) error {
  129. iv := make([]byte, aes.BlockSize)
  130. var err error
  131. if _, err = fp.Read(iv); err != nil {
  132. return y.Wrapf(err, "Error while reading IV for key registry.")
  133. }
  134. eSanityText := make([]byte, len(sanityText))
  135. if _, err = fp.Read(eSanityText); err != nil {
  136. return y.Wrapf(err, "Error while reading sanity text.")
  137. }
  138. if len(encryptionKey) > 0 {
  139. // Decrypting sanity text.
  140. if eSanityText, err = y.XORBlockAllocate(eSanityText, encryptionKey, iv); err != nil {
  141. return y.Wrapf(err, "During validRegistry")
  142. }
  143. }
  144. // Check the given key is valid or not.
  145. if !bytes.Equal(eSanityText, sanityText) {
  146. return ErrEncryptionKeyMismatch
  147. }
  148. return nil
  149. }
  150. func (kri *keyRegistryIterator) next() (*pb.DataKey, error) {
  151. var err error
  152. // Read crc buf and data length.
  153. if _, err = kri.fp.Read(kri.lenCrcBuf[:]); err != nil {
  154. // EOF means end of the iteration.
  155. if err != io.EOF {
  156. return nil, y.Wrapf(err, "While reading crc in keyRegistryIterator.next")
  157. }
  158. return nil, err
  159. }
  160. l := int64(binary.BigEndian.Uint32(kri.lenCrcBuf[0:4]))
  161. // Read protobuf data.
  162. data := make([]byte, l)
  163. if _, err = kri.fp.Read(data); err != nil {
  164. // EOF means end of the iteration.
  165. if err != io.EOF {
  166. return nil, y.Wrapf(err, "While reading protobuf in keyRegistryIterator.next")
  167. }
  168. return nil, err
  169. }
  170. // Check checksum.
  171. if crc32.Checksum(data, y.CastagnoliCrcTable) != binary.BigEndian.Uint32(kri.lenCrcBuf[4:]) {
  172. return nil, y.Wrapf(y.ErrChecksumMismatch, "Error while checking checksum for data key.")
  173. }
  174. dataKey := &pb.DataKey{}
  175. if err = proto.Unmarshal(data, dataKey); err != nil {
  176. return nil, y.Wrapf(err, "While unmarshal of datakey in keyRegistryIterator.next")
  177. }
  178. if len(kri.encryptionKey) > 0 {
  179. // Decrypt the key if the storage key exists.
  180. if dataKey.Data, err = y.XORBlockAllocate(dataKey.Data, kri.encryptionKey, dataKey.Iv); err != nil {
  181. return nil, y.Wrapf(err, "While decrypting datakey in keyRegistryIterator.next")
  182. }
  183. }
  184. return dataKey, nil
  185. }
  186. // readKeyRegistry will read the key registry file and build the key registry struct.
  187. func readKeyRegistry(fp *os.File, opt KeyRegistryOptions) (*KeyRegistry, error) {
  188. itr, err := newKeyRegistryIterator(fp, opt.EncryptionKey)
  189. if err != nil {
  190. return nil, err
  191. }
  192. kr := newKeyRegistry(opt)
  193. var dk *pb.DataKey
  194. dk, err = itr.next()
  195. for err == nil && dk != nil {
  196. if dk.KeyId > kr.nextKeyID {
  197. // Set the maximum key ID for next key ID generation.
  198. kr.nextKeyID = dk.KeyId
  199. }
  200. if dk.CreatedAt > kr.lastCreated {
  201. // Set the last generated key timestamp.
  202. kr.lastCreated = dk.CreatedAt
  203. }
  204. // No need to lock since we are building the initial state.
  205. kr.dataKeys[dk.KeyId] = dk
  206. // Forward the iterator.
  207. dk, err = itr.next()
  208. }
  209. // We read all the key. So, Ignoring this error.
  210. if err == io.EOF {
  211. err = nil
  212. }
  213. return kr, err
  214. }
  215. /*
  216. Structure of Key Registry.
  217. +-------------------+---------------------+--------------------+--------------+------------------+
  218. | IV | Sanity Text | DataKey1 | DataKey2 | ... |
  219. +-------------------+---------------------+--------------------+--------------+------------------+
  220. */
  221. // WriteKeyRegistry will rewrite the existing key registry file with new one.
  222. // It is okay to give closed key registry. Since, it's using only the datakey.
  223. func WriteKeyRegistry(reg *KeyRegistry, opt KeyRegistryOptions) error {
  224. buf := &bytes.Buffer{}
  225. iv, err := y.GenerateIV()
  226. y.Check(err)
  227. // Encrypt sanity text if the encryption key is presents.
  228. eSanity := sanityText
  229. if len(opt.EncryptionKey) > 0 {
  230. var err error
  231. eSanity, err = y.XORBlockAllocate(eSanity, opt.EncryptionKey, iv)
  232. if err != nil {
  233. return y.Wrapf(err, "Error while encrpting sanity text in WriteKeyRegistry")
  234. }
  235. }
  236. y.Check2(buf.Write(iv))
  237. y.Check2(buf.Write(eSanity))
  238. // Write all the datakeys to the buf.
  239. for _, k := range reg.dataKeys {
  240. // Writing the datakey to the given buffer.
  241. if err := storeDataKey(buf, opt.EncryptionKey, k); err != nil {
  242. return y.Wrapf(err, "Error while storing datakey in WriteKeyRegistry")
  243. }
  244. }
  245. tmpPath := filepath.Join(opt.Dir, KeyRegistryRewriteFileName)
  246. // Open temporary file to write the data and do atomic rename.
  247. fp, err := y.OpenTruncFile(tmpPath, true)
  248. if err != nil {
  249. return y.Wrapf(err, "Error while opening tmp file in WriteKeyRegistry")
  250. }
  251. // Write buf to the disk.
  252. if _, err = fp.Write(buf.Bytes()); err != nil {
  253. // close the fd before returning error. We're not using defer
  254. // because, for windows we need to close the fd explicitly before
  255. // renaming.
  256. fp.Close()
  257. return y.Wrapf(err, "Error while writing buf in WriteKeyRegistry")
  258. }
  259. // In Windows the files should be closed before doing a Rename.
  260. if err = fp.Close(); err != nil {
  261. return y.Wrapf(err, "Error while closing tmp file in WriteKeyRegistry")
  262. }
  263. // Rename to the original file.
  264. if err = os.Rename(tmpPath, filepath.Join(opt.Dir, KeyRegistryFileName)); err != nil {
  265. return y.Wrapf(err, "Error while renaming file in WriteKeyRegistry")
  266. }
  267. // Sync Dir.
  268. return syncDir(opt.Dir)
  269. }
  270. // DataKey returns datakey of the given key id.
  271. func (kr *KeyRegistry) DataKey(id uint64) (*pb.DataKey, error) {
  272. kr.RLock()
  273. defer kr.RUnlock()
  274. if id == 0 {
  275. // nil represent plain text.
  276. return nil, nil
  277. }
  278. dk, ok := kr.dataKeys[id]
  279. if !ok {
  280. return nil, y.Wrapf(ErrInvalidDataKeyID, "Error for the KEY ID %d", id)
  281. }
  282. return dk, nil
  283. }
  284. // LatestDataKey will give you the latest generated datakey based on the rotation
  285. // period. If the last generated datakey lifetime exceeds the rotation period.
  286. // It'll create new datakey.
  287. func (kr *KeyRegistry) LatestDataKey() (*pb.DataKey, error) {
  288. if len(kr.opt.EncryptionKey) == 0 {
  289. // nil is for no encryption.
  290. return nil, nil
  291. }
  292. // validKey return datakey if the last generated key duration less than
  293. // rotation duration.
  294. validKey := func() (*pb.DataKey, bool) {
  295. // Time diffrence from the last generated time.
  296. diff := time.Since(time.Unix(kr.lastCreated, 0))
  297. if diff < kr.opt.EncryptionKeyRotationDuration {
  298. return kr.dataKeys[kr.nextKeyID], true
  299. }
  300. return nil, false
  301. }
  302. kr.RLock()
  303. key, valid := validKey()
  304. kr.RUnlock()
  305. if valid {
  306. // If less than EncryptionKeyRotationDuration, returns the last generated key.
  307. return key, nil
  308. }
  309. kr.Lock()
  310. defer kr.Unlock()
  311. // Key might have generated by another go routine. So,
  312. // checking once again.
  313. key, valid = validKey()
  314. if valid {
  315. return key, nil
  316. }
  317. k := make([]byte, len(kr.opt.EncryptionKey))
  318. iv, err := y.GenerateIV()
  319. if err != nil {
  320. return nil, err
  321. }
  322. _, err = rand.Read(k)
  323. if err != nil {
  324. return nil, err
  325. }
  326. // Otherwise Increment the KeyID and generate new datakey.
  327. kr.nextKeyID++
  328. dk := &pb.DataKey{
  329. KeyId: kr.nextKeyID,
  330. Data: k,
  331. CreatedAt: time.Now().Unix(),
  332. Iv: iv,
  333. }
  334. // Don't store the datakey on file if badger is running in InMemory mode.
  335. if !kr.opt.InMemory {
  336. // Store the datekey.
  337. buf := &bytes.Buffer{}
  338. if err = storeDataKey(buf, kr.opt.EncryptionKey, dk); err != nil {
  339. return nil, err
  340. }
  341. // Persist the datakey to the disk
  342. if _, err = kr.fp.Write(buf.Bytes()); err != nil {
  343. return nil, err
  344. }
  345. }
  346. // storeDatakey encrypts the datakey So, placing un-encrypted key in the memory.
  347. dk.Data = k
  348. kr.lastCreated = dk.CreatedAt
  349. kr.dataKeys[kr.nextKeyID] = dk
  350. return dk, nil
  351. }
  352. // Close closes the key registry.
  353. func (kr *KeyRegistry) Close() error {
  354. if !(kr.opt.ReadOnly || kr.opt.InMemory) {
  355. return kr.fp.Close()
  356. }
  357. return nil
  358. }
  359. // storeDataKey stores datakey in an encrypted format in the given buffer. If storage key preset.
  360. func storeDataKey(buf *bytes.Buffer, storageKey []byte, k *pb.DataKey) error {
  361. // xor will encrypt the IV and xor with the given data.
  362. // It'll used for both encryption and decryption.
  363. xor := func() error {
  364. if len(storageKey) == 0 {
  365. return nil
  366. }
  367. var err error
  368. k.Data, err = y.XORBlockAllocate(k.Data, storageKey, k.Iv)
  369. return err
  370. }
  371. // In memory datakey will be plain text so encrypting before storing to the disk.
  372. var err error
  373. if err = xor(); err != nil {
  374. return y.Wrapf(err, "Error while encrypting datakey in storeDataKey")
  375. }
  376. var data []byte
  377. if data, err = proto.Marshal(k); err != nil {
  378. err = y.Wrapf(err, "Error while marshaling datakey in storeDataKey")
  379. var err2 error
  380. // decrypting the datakey back.
  381. if err2 = xor(); err2 != nil {
  382. return y.Wrapf(err,
  383. y.Wrapf(err2, "Error while decrypting datakey in storeDataKey").Error())
  384. }
  385. return err
  386. }
  387. var lenCrcBuf [8]byte
  388. binary.BigEndian.PutUint32(lenCrcBuf[0:4], uint32(len(data)))
  389. binary.BigEndian.PutUint32(lenCrcBuf[4:8], crc32.Checksum(data, y.CastagnoliCrcTable))
  390. y.Check2(buf.Write(lenCrcBuf[:]))
  391. y.Check2(buf.Write(data))
  392. // Decrypting the datakey back since we're using the pointer.
  393. return xor()
  394. }