key_registry.go 13 KB

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