EncryptionEngine.go 11 KB

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