common.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // Package common provides encryption methods common across encryption types
  2. package common
  3. import (
  4. "bytes"
  5. "crypto/hmac"
  6. "encoding/binary"
  7. "encoding/hex"
  8. "errors"
  9. "fmt"
  10. "github.com/jcmturner/gokrb5/v8/crypto/etype"
  11. )
  12. // ZeroPad pads bytes with zeros to nearest multiple of message size m.
  13. func ZeroPad(b []byte, m int) ([]byte, error) {
  14. if m <= 0 {
  15. return nil, errors.New("Invalid message block size when padding")
  16. }
  17. if b == nil || len(b) == 0 {
  18. return nil, errors.New("Data not valid to pad: Zero size")
  19. }
  20. if l := len(b) % m; l != 0 {
  21. n := m - l
  22. z := make([]byte, n)
  23. b = append(b, z...)
  24. }
  25. return b, nil
  26. }
  27. // PKCS7Pad pads bytes according to RFC 2315 to nearest multiple of message size m.
  28. func PKCS7Pad(b []byte, m int) ([]byte, error) {
  29. if m <= 0 {
  30. return nil, errors.New("Invalid message block size when padding")
  31. }
  32. if b == nil || len(b) == 0 {
  33. return nil, errors.New("Data not valid to pad: Zero size")
  34. }
  35. n := m - (len(b) % m)
  36. pb := make([]byte, len(b)+n)
  37. copy(pb, b)
  38. copy(pb[len(b):], bytes.Repeat([]byte{byte(n)}, n))
  39. return pb, nil
  40. }
  41. // PKCS7Unpad removes RFC 2315 padding from byes where message size is m.
  42. func PKCS7Unpad(b []byte, m int) ([]byte, error) {
  43. if m <= 0 {
  44. return nil, errors.New("invalid message block size when unpadding")
  45. }
  46. if b == nil || len(b) == 0 {
  47. return nil, errors.New("padded data not valid: Zero size")
  48. }
  49. if len(b)%m != 0 {
  50. return nil, errors.New("padded data not valid: Not multiple of message block size")
  51. }
  52. c := b[len(b)-1]
  53. n := int(c)
  54. if n == 0 || n > len(b) {
  55. return nil, errors.New("padded data not valid: Data may not have been padded")
  56. }
  57. for i := 0; i < n; i++ {
  58. if b[len(b)-n+i] != c {
  59. return nil, errors.New("padded data not valid")
  60. }
  61. }
  62. return b[:len(b)-n], nil
  63. }
  64. // GetHash generates the keyed hash value according to the etype's hash function.
  65. func GetHash(pt, key []byte, usage []byte, etype etype.EType) ([]byte, error) {
  66. k, err := etype.DeriveKey(key, usage)
  67. if err != nil {
  68. return nil, fmt.Errorf("unable to derive key for checksum: %v", err)
  69. }
  70. mac := hmac.New(etype.GetHashFunc(), k)
  71. p := make([]byte, len(pt))
  72. copy(p, pt)
  73. mac.Write(p)
  74. return mac.Sum(nil)[:etype.GetHMACBitLength()/8], nil
  75. }
  76. // GetChecksumHash returns a keyed checksum hash of the bytes provided.
  77. func GetChecksumHash(b, key []byte, usage uint32, etype etype.EType) ([]byte, error) {
  78. return GetHash(b, key, GetUsageKc(usage), etype)
  79. }
  80. // GetIntegrityHash returns a keyed integrity hash of the bytes provided.
  81. func GetIntegrityHash(b, key []byte, usage uint32, etype etype.EType) ([]byte, error) {
  82. return GetHash(b, key, GetUsageKi(usage), etype)
  83. }
  84. // VerifyChecksum compares the checksum of the msg bytes is the same as the checksum provided.
  85. func VerifyChecksum(key, chksum, msg []byte, usage uint32, etype etype.EType) bool {
  86. //The encrypted message is a concatenation of the encrypted output and the hash HMAC.
  87. expectedMAC, _ := GetChecksumHash(msg, key, usage, etype)
  88. return hmac.Equal(chksum, expectedMAC)
  89. }
  90. // GetUsageKc returns the checksum key usage value for the usage number un.
  91. //
  92. // See RFC 3961 5.3 key-derivation function definition.
  93. func GetUsageKc(un uint32) []byte {
  94. return getUsage(un, 0x99)
  95. }
  96. // GetUsageKe returns the encryption key usage value for the usage number un
  97. //
  98. // See RFC 3961 5.3 key-derivation function definition.
  99. func GetUsageKe(un uint32) []byte {
  100. return getUsage(un, 0xAA)
  101. }
  102. // GetUsageKi returns the integrity key usage value for the usage number un
  103. //
  104. // See RFC 3961 5.3 key-derivation function definition.
  105. func GetUsageKi(un uint32) []byte {
  106. return getUsage(un, 0x55)
  107. }
  108. func getUsage(un uint32, o byte) []byte {
  109. var buf bytes.Buffer
  110. binary.Write(&buf, binary.BigEndian, un)
  111. return append(buf.Bytes(), o)
  112. }
  113. // IterationsToS2Kparams converts the number of iterations as an integer to a string representation.
  114. func IterationsToS2Kparams(i uint32) string {
  115. b := make([]byte, 4, 4)
  116. binary.BigEndian.PutUint32(b, i)
  117. return hex.EncodeToString(b)
  118. }