Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 
 

155 Zeilen
3.0 KiB

  1. // This is initial implementation of CTR_DRBG with AES-256. Code is tested
  2. // and functionaly correct. Nevertheless it will be changed
  3. //
  4. // TODO: Following things still need to be done
  5. // * Add other AES key lengts
  6. // * Validate sizes from table 3 of SP800-90A
  7. // * Improve reseeding so that code returns an error when reseed is needed
  8. // * Add case with derivation function (maybe)
  9. // * Code cleanup
  10. // * Implement benchmark
  11. // * Add rest of the test vectors from CAVP
  12. package drbg
  13. import (
  14. "crypto/aes"
  15. )
  16. // Constants below correspond to AES-256, which is currently
  17. // the only block cipher supported.
  18. const (
  19. BlockLen = 16
  20. KeyLen = 32
  21. SeedLen = BlockLen + KeyLen
  22. )
  23. type CtrDrbg struct {
  24. v []byte
  25. key []byte
  26. counter uint
  27. strength uint
  28. resistance bool
  29. }
  30. func NewCtrDrbg() *CtrDrbg {
  31. var c = new(CtrDrbg)
  32. return c
  33. }
  34. func (c *CtrDrbg) inc() {
  35. for i := BlockLen - 1; i >= 0; i-- {
  36. if c.v[i] == 0xff {
  37. c.v[i] = 0x00
  38. } else {
  39. c.v[i]++
  40. break
  41. }
  42. }
  43. }
  44. func (c *CtrDrbg) Init(entropy, personalization []byte) bool {
  45. var lsz int
  46. var seedBuf [SeedLen]byte
  47. // Minimum entropy input (SP800-90A, 10.2.1)
  48. if len(entropy) < int(c.strength/8) {
  49. return false
  50. }
  51. // Security strength for AES-256 as per SP800-57, 5.6.1
  52. c.strength = 256
  53. lsz = len(entropy)
  54. if lsz > SeedLen {
  55. lsz = SeedLen
  56. }
  57. copy(seedBuf[:], entropy[:lsz])
  58. lsz = len(personalization)
  59. if lsz > SeedLen {
  60. lsz = SeedLen
  61. }
  62. for i := 0; i < lsz; i++ {
  63. seedBuf[i] ^= personalization[i]
  64. }
  65. c.key = make([]byte, KeyLen)
  66. c.v = make([]byte, BlockLen)
  67. c.update(seedBuf[:])
  68. c.counter = 1
  69. return true
  70. }
  71. func (c *CtrDrbg) update(data []byte) {
  72. var buf [3 * BlockLen]byte
  73. if len(data) != SeedLen {
  74. // OZAPTF: panic?
  75. panic("Provided data is not equal to strength/8")
  76. }
  77. for i := 0; i < 3*BlockLen; i += BlockLen {
  78. c.inc()
  79. // Ignore error => NewCipher returns error when c.key has unexpected size
  80. encBlock, _ := aes.NewCipher(c.key)
  81. encBlock.Encrypt(buf[i:], c.v)
  82. }
  83. for i := 0; i < len(buf); i++ {
  84. buf[i] ^= data[i]
  85. }
  86. copy(c.key, buf[:KeyLen])
  87. copy(c.v, buf[KeyLen:])
  88. }
  89. func (c *CtrDrbg) Reseed(entropy, data []byte) {
  90. var seedBuf [SeedLen]byte
  91. var lsz int
  92. lsz = len(entropy)
  93. if lsz > SeedLen {
  94. lsz = SeedLen
  95. }
  96. copy(seedBuf[:], entropy[:lsz])
  97. lsz = len(data)
  98. if lsz > SeedLen {
  99. lsz = SeedLen
  100. }
  101. for i := 0; i < lsz; i++ {
  102. seedBuf[i] ^= data[i]
  103. }
  104. c.update(seedBuf[:])
  105. c.counter = 1
  106. }
  107. func (c *CtrDrbg) Read(b, ad []byte) (n int, err error) {
  108. var seedBuf [SeedLen]byte
  109. // TODO: check reseed_counter > reseed_interval
  110. if len(ad) > 0 {
  111. // pad additional data with zeros if needed
  112. copy(seedBuf[:], ad)
  113. c.update(seedBuf[:])
  114. }
  115. // OZAPTF: would be better not need to allocate that
  116. buf := make([]byte, ((len(b)+BlockLen)/BlockLen)*BlockLen)
  117. for i := 0; i < len(b); i += BlockLen {
  118. c.inc()
  119. // Ignore error => NewCipher returns error when c.key has unexpected size
  120. encBlock, _ := aes.NewCipher(c.key)
  121. encBlock.Encrypt(buf[i:], c.v)
  122. }
  123. copy(b, buf[:len(b)])
  124. c.update(seedBuf[:])
  125. c.counter += 1
  126. return len(b), nil
  127. }