EncryptionEngine.go 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. package crypto
  2. import (
  3. "bytes"
  4. "crypto/hmac"
  5. "encoding/binary"
  6. "encoding/hex"
  7. "errors"
  8. "fmt"
  9. "github.com/jcmturner/gokrb5/keytab"
  10. "github.com/jcmturner/gokrb5/types"
  11. "hash"
  12. )
  13. type EType interface {
  14. GetETypeID() int
  15. GetKeyByteSize() int // See "protocol key format" for defined values
  16. GetKeySeedBitLength() int // key-generation seed length, k
  17. GetDefaultStringToKeyParams() string // default string-to-key parameters (s2kparams)
  18. StringToKey(string, salt, s2kparams string) ([]byte, error) // string-to-key (UTF-8 string, UTF-8 string, opaque)->(protocol-key)
  19. RandomToKey(b []byte) []byte // random-to-key (bitstring[K])->(protocol-key)
  20. GetHMACBitLength() int // HMAC output size, h
  21. GetMessageBlockByteSize() int // message block size, m
  22. Encrypt(key, message []byte) ([]byte, []byte, error) // E function - encrypt (specific-key, state, octet string)->(state, octet string)
  23. Decrypt(key, ciphertext []byte) ([]byte, error) // D function
  24. GetCypherBlockBitLength() int // cipher block size, c
  25. GetConfounderByteSize() int // This is the same as the cipher block size but in bytes.
  26. DeriveKey(protocolKey, usage []byte) ([]byte, error) // DK key-derivation (protocol-key, integer)->(specific-key)
  27. DeriveRandom(protocolKey, usage []byte) ([]byte, error) // DR pseudo-random (protocol-key, octet-string)->(octet-string)
  28. VerifyChecksum(protocolKey, ct, pt []byte, usage int) bool
  29. GetHash() hash.Hash
  30. }
  31. func GetEtype(id int) (EType, error) {
  32. switch id {
  33. case 17:
  34. var et Aes128CtsHmacSha96
  35. return et, nil
  36. case 18:
  37. var et Aes256CtsHmacSha96
  38. return et, nil
  39. default:
  40. return nil, fmt.Errorf("Unknown or unsupported EType: %d", id)
  41. }
  42. }
  43. // RFC3961: DR(Key, Constant) = k-truncate(E(Key, Constant, initial-cipher-state))
  44. // key - base key or protocol key. Likely to be a key from a keytab file
  45. // TODO usage - a constant
  46. // n - block size in bits (not bytes) - note if you use something like aes.BlockSize this is in bytes.
  47. // k - key length / key seed length in bits. Eg. for AES256 this value is 256
  48. // encrypt - the encryption function to use
  49. func deriveRandom(key, usage []byte, n, k int, e EType) ([]byte, error) {
  50. //Ensure the usage constant is at least the size of the cypher block size. Pass it through the nfold algorithm that will "stretch" it if needs be.
  51. nFoldUsage := Nfold(usage, n)
  52. //k-truncate implemented by creating a byte array the size of k (k is in bits hence /8)
  53. out := make([]byte, k/8)
  54. /*If the output of E is shorter than k bits, it is fed back into the encryption as many times as necessary.
  55. The construct is as follows (where | indicates concatentation):
  56. K1 = E(Key, n-fold(Constant), initial-cipher-state)
  57. K2 = E(Key, K1, initial-cipher-state)
  58. K3 = E(Key, K2, initial-cipher-state)
  59. K4 = ...
  60. DR(Key, Constant) = k-truncate(K1 | K2 | K3 | K4 ...)*/
  61. _, K, err := e.Encrypt(key, nFoldUsage)
  62. if err != nil {
  63. return out, err
  64. }
  65. for i := copy(out, K); i < len(out); {
  66. _, K, _ = e.Encrypt(key, K)
  67. i = i + copy(out[i:], K)
  68. }
  69. return out, nil
  70. }
  71. func zeroPad(b []byte, m int) ([]byte, error) {
  72. if m <= 0 {
  73. return nil, errors.New("Invalid message block size when padding")
  74. }
  75. if b == nil || len(b) == 0 {
  76. return nil, errors.New("Data not valid to pad: Zero size")
  77. }
  78. if l := len(b) % m; l != 0 {
  79. n := m - l
  80. z := make([]byte, n)
  81. b = append(b, z...)
  82. }
  83. return b, nil
  84. }
  85. func pkcs7Pad(b []byte, m int) ([]byte, error) {
  86. if m <= 0 {
  87. return nil, errors.New("Invalid message block size when padding")
  88. }
  89. if b == nil || len(b) == 0 {
  90. return nil, errors.New("Data not valid to pad: Zero size")
  91. }
  92. n := m - (len(b) % m)
  93. pb := make([]byte, len(b)+n)
  94. copy(pb, b)
  95. copy(pb[len(b):], bytes.Repeat([]byte{byte(n)}, n))
  96. return pb, nil
  97. }
  98. func pkcs7Unpad(b []byte, m int) ([]byte, error) {
  99. if m <= 0 {
  100. return nil, errors.New("Invalid message block size when unpadding")
  101. }
  102. if b == nil || len(b) == 0 {
  103. return nil, errors.New("Padded data not valid: Zero size")
  104. }
  105. if len(b)%m != 0 {
  106. return nil, errors.New("Padded data not valid: Not multiple of message block size")
  107. }
  108. c := b[len(b)-1]
  109. n := int(c)
  110. if n == 0 || n > len(b) {
  111. return nil, errors.New("Padded data not valid: Data may not have been padded")
  112. }
  113. for i := 0; i < n; i++ {
  114. if b[len(b)-n+i] != c {
  115. return nil, errors.New("Padded data not valid")
  116. }
  117. }
  118. return b[:len(b)-n], nil
  119. }
  120. func DecryptEncPart(key []byte, pe types.EncryptedData, etype EType, usage uint32) ([]byte, error) {
  121. //Derive the key
  122. //TODO need to consider PAdata for deriving key
  123. k, err := etype.DeriveKey(key, GetUsageKe(usage))
  124. if err != nil {
  125. return nil, fmt.Errorf("Error deriving key: %v", err)
  126. }
  127. // Strip off the checksum from the end
  128. b, err := etype.Decrypt(k, pe.Cipher[:len(pe.Cipher)-etype.GetHMACBitLength()/8])
  129. if err != nil {
  130. return nil, fmt.Errorf("Error decrypting: %v", err)
  131. }
  132. //Verify checksum
  133. if !etype.VerifyChecksum(key, pe.Cipher, b, int(usage)) {
  134. return nil, errors.New("Error decrypting encrypted part: checksum verification failed")
  135. }
  136. //Remove the confounder bytes
  137. b = b[etype.GetConfounderByteSize():]
  138. if err != nil {
  139. return nil, fmt.Errorf("Error decrypting encrypted part: %v", err)
  140. }
  141. return b, nil
  142. }
  143. func GetKeyFromPassword(passwd string, cn types.PrincipalName, realm string, etypeId int, pas types.PADataSequence) ([]byte, EType, error) {
  144. var key []byte
  145. etype, err := GetEtype(etypeId)
  146. if err != nil {
  147. return key, etype, fmt.Errorf("Error getting encryption type: %v", err)
  148. }
  149. sk2p := etype.GetDefaultStringToKeyParams()
  150. var salt string
  151. var patype int
  152. for _, pa := range pas {
  153. switch pa.PADataType {
  154. case types.PA_PW_SALT:
  155. if patype > pa.PADataType {
  156. continue
  157. }
  158. salt = string(pa.PADataValue)
  159. case types.PA_ETYPE_INFO:
  160. if patype > pa.PADataType {
  161. continue
  162. }
  163. var et types.ETypeInfo
  164. err := et.Unmarshal(pa.PADataValue)
  165. if err != nil {
  166. return key, etype, fmt.Errorf("Error unmashalling PA Data to PA-ETYPE-INFO2: %v", err)
  167. }
  168. if etypeId != et[0].EType {
  169. etype, err = GetEtype(et[0].EType)
  170. if err != nil {
  171. return key, etype, fmt.Errorf("Error getting encryption type: %v", err)
  172. }
  173. }
  174. salt = string(et[0].Salt)
  175. case types.PA_ETYPE_INFO2:
  176. if patype > pa.PADataType {
  177. continue
  178. }
  179. var et2 types.ETypeInfo2
  180. err := et2.Unmarshal(pa.PADataValue)
  181. if err != nil {
  182. return key, etype, fmt.Errorf("Error unmashalling PA Data to PA-ETYPE-INFO2: %v", err)
  183. }
  184. if etypeId != et2[0].EType {
  185. etype, err = GetEtype(et2[0].EType)
  186. if err != nil {
  187. return key, etype, fmt.Errorf("Error getting encryption type: %v", err)
  188. }
  189. }
  190. if len(et2[0].S2KParams) == 8 {
  191. sk2p = hex.EncodeToString(et2[0].S2KParams)
  192. }
  193. salt = et2[0].Salt
  194. }
  195. }
  196. if salt == "" {
  197. salt = cn.GetSalt(realm)
  198. }
  199. key, err = etype.StringToKey(passwd, salt, sk2p)
  200. if err != nil {
  201. return key, etype, fmt.Errorf("Error deriving key from string: %+v", err)
  202. }
  203. return key, etype, nil
  204. }
  205. func GetChecksum(pt, key []byte, usage int, etype EType) ([]byte, error) {
  206. k, err := etype.DeriveKey(key, GetUsageKi(uint32(usage)))
  207. if err != nil {
  208. return nil, fmt.Errorf("Unable to derive key for checksum: %v", err)
  209. }
  210. mac := hmac.New(etype.GetHash, k)
  211. //TODO do I need to append the ivz before taking the hash?
  212. //ivz := make([]byte, etype.GetConfounderByteSize())
  213. //pt = append(ivz, pt...)
  214. //if r := len(pt)%etype.GetMessageBlockByteSize(); r != 0 {
  215. // t := make([]byte, etype.GetMessageBlockByteSize() - r)
  216. // pt = append(pt, t...)
  217. //}
  218. mac.Write(pt)
  219. return mac.Sum(nil), nil
  220. }
  221. func VerifyChecksum(key, ct, pt []byte, usage int, etype EType) bool {
  222. //The ciphertext output is the concatenation of the output of the basic
  223. //encryption function E and a (possibly truncated) HMAC using the
  224. //specified hash function H, both applied to the plaintext with a
  225. //random confounder prefix and sufficient padding to bring it to a
  226. //multiple of the message block size. When the HMAC is computed, the
  227. //key is used in the protocol key form.
  228. h := ct[len(ct)-etype.GetHMACBitLength()/8+1:]
  229. expectedMAC, _ := GetChecksum(pt, key, usage, etype)
  230. return hmac.Equal(h, expectedMAC[1:etype.GetHMACBitLength()/8])
  231. }
  232. /*
  233. Key Usage Numbers
  234. RFC 3961: The "well-known constant" used for the DK function is the key usage number, expressed as four octets in big-endian order, followed by one octet indicated below.
  235. Kc = DK(base-key, usage | 0x99);
  236. Ke = DK(base-key, usage | 0xAA);
  237. Ki = DK(base-key, usage | 0x55);
  238. */
  239. // un - usage number
  240. func GetUsageKc(un uint32) []byte {
  241. return getUsage(un, 0x99)
  242. }
  243. // un - usage number
  244. func GetUsageKe(un uint32) []byte {
  245. return getUsage(un, 0xAA)
  246. }
  247. // un - usage number
  248. func GetUsageKi(un uint32) []byte {
  249. return getUsage(un, 0x55)
  250. }
  251. func getUsage(un uint32, o byte) []byte {
  252. var buf bytes.Buffer
  253. binary.Write(&buf, binary.BigEndian, un)
  254. return append(buf.Bytes(), o)
  255. }
  256. func GetEncryptedData(b []byte, etype EType, crealm, username string, kt keytab.Keytab, kvno int) ([]byte, error) {
  257. key, err := kt.GetKey(username, crealm, kvno, etype.GetETypeID())
  258. _, cb, err := etype.Encrypt(key, b)
  259. if err != nil {
  260. return b, fmt.Errorf("Error encrypting data to form EncryptedData: %v", err)
  261. }
  262. ed := types.EncryptedData{
  263. KVNO: kvno,
  264. EType: etype.GetETypeID(),
  265. Cipher: cb,
  266. }
  267. return ed.Marshal()
  268. }