You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

143 lines
3.6 KiB

  1. // Copyright 2010 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // OpenPGP CFB Mode. http://tools.ietf.org/html/rfc4880#section-13.9
  5. package packet
  6. import (
  7. "crypto/cipher"
  8. )
  9. type ocfbEncrypter struct {
  10. b cipher.Block
  11. fre []byte
  12. outUsed int
  13. }
  14. // An OCFBResyncOption determines if the "resynchronization step" of OCFB is
  15. // performed.
  16. type OCFBResyncOption bool
  17. const (
  18. OCFBResync OCFBResyncOption = true
  19. OCFBNoResync OCFBResyncOption = false
  20. )
  21. // NewOCFBEncrypter returns a cipher.Stream which encrypts data with OpenPGP's
  22. // cipher feedback mode using the given cipher.Block, and an initial amount of
  23. // ciphertext. randData must be random bytes and be the same length as the
  24. // cipher.Block's block size. Resync determines if the "resynchronization step"
  25. // from RFC 4880, 13.9 step 7 is performed. Different parts of OpenPGP vary on
  26. // this point.
  27. func NewOCFBEncrypter(block cipher.Block, randData []byte, resync OCFBResyncOption) (cipher.Stream, []byte) {
  28. blockSize := block.BlockSize()
  29. if len(randData) != blockSize {
  30. return nil, nil
  31. }
  32. x := &ocfbEncrypter{
  33. b: block,
  34. fre: make([]byte, blockSize),
  35. outUsed: 0,
  36. }
  37. prefix := make([]byte, blockSize+2)
  38. block.Encrypt(x.fre, x.fre)
  39. for i := 0; i < blockSize; i++ {
  40. prefix[i] = randData[i] ^ x.fre[i]
  41. }
  42. block.Encrypt(x.fre, prefix[:blockSize])
  43. prefix[blockSize] = x.fre[0] ^ randData[blockSize-2]
  44. prefix[blockSize+1] = x.fre[1] ^ randData[blockSize-1]
  45. if resync {
  46. block.Encrypt(x.fre, prefix[2:])
  47. } else {
  48. x.fre[0] = prefix[blockSize]
  49. x.fre[1] = prefix[blockSize+1]
  50. x.outUsed = 2
  51. }
  52. return x, prefix
  53. }
  54. func (x *ocfbEncrypter) XORKeyStream(dst, src []byte) {
  55. for i := 0; i < len(src); i++ {
  56. if x.outUsed == len(x.fre) {
  57. x.b.Encrypt(x.fre, x.fre)
  58. x.outUsed = 0
  59. }
  60. x.fre[x.outUsed] ^= src[i]
  61. dst[i] = x.fre[x.outUsed]
  62. x.outUsed++
  63. }
  64. }
  65. type ocfbDecrypter struct {
  66. b cipher.Block
  67. fre []byte
  68. outUsed int
  69. }
  70. // NewOCFBDecrypter returns a cipher.Stream which decrypts data with OpenPGP's
  71. // cipher feedback mode using the given cipher.Block. Prefix must be the first
  72. // blockSize + 2 bytes of the ciphertext, where blockSize is the cipher.Block's
  73. // block size. If an incorrect key is detected then nil is returned. On
  74. // successful exit, blockSize+2 bytes of decrypted data are written into
  75. // prefix. Resync determines if the "resynchronization step" from RFC 4880,
  76. // 13.9 step 7 is performed. Different parts of OpenPGP vary on this point.
  77. func NewOCFBDecrypter(block cipher.Block, prefix []byte, resync OCFBResyncOption) cipher.Stream {
  78. blockSize := block.BlockSize()
  79. if len(prefix) != blockSize+2 {
  80. return nil
  81. }
  82. x := &ocfbDecrypter{
  83. b: block,
  84. fre: make([]byte, blockSize),
  85. outUsed: 0,
  86. }
  87. prefixCopy := make([]byte, len(prefix))
  88. copy(prefixCopy, prefix)
  89. block.Encrypt(x.fre, x.fre)
  90. for i := 0; i < blockSize; i++ {
  91. prefixCopy[i] ^= x.fre[i]
  92. }
  93. block.Encrypt(x.fre, prefix[:blockSize])
  94. prefixCopy[blockSize] ^= x.fre[0]
  95. prefixCopy[blockSize+1] ^= x.fre[1]
  96. if prefixCopy[blockSize-2] != prefixCopy[blockSize] ||
  97. prefixCopy[blockSize-1] != prefixCopy[blockSize+1] {
  98. return nil
  99. }
  100. if resync {
  101. block.Encrypt(x.fre, prefix[2:])
  102. } else {
  103. x.fre[0] = prefix[blockSize]
  104. x.fre[1] = prefix[blockSize+1]
  105. x.outUsed = 2
  106. }
  107. copy(prefix, prefixCopy)
  108. return x
  109. }
  110. func (x *ocfbDecrypter) XORKeyStream(dst, src []byte) {
  111. for i := 0; i < len(src); i++ {
  112. if x.outUsed == len(x.fre) {
  113. x.b.Encrypt(x.fre, x.fre)
  114. x.outUsed = 0
  115. }
  116. c := src[i]
  117. dst[i] = x.fre[x.outUsed] ^ src[i]
  118. x.fre[x.outUsed] = c
  119. x.outUsed++
  120. }
  121. }