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.

475 lines
11 KiB

  1. package rardecode
  2. import (
  3. "bufio"
  4. "bytes"
  5. "crypto/hmac"
  6. "crypto/sha256"
  7. "errors"
  8. "hash"
  9. "hash/crc32"
  10. "io"
  11. "io/ioutil"
  12. "time"
  13. )
  14. const (
  15. // block types
  16. block5Arc = 1
  17. block5File = 2
  18. block5Service = 3
  19. block5Encrypt = 4
  20. block5End = 5
  21. // block flags
  22. block5HasExtra = 0x0001
  23. block5HasData = 0x0002
  24. block5DataNotFirst = 0x0008
  25. block5DataNotLast = 0x0010
  26. // end block flags
  27. endArc5NotLast = 0x0001
  28. // archive encryption block flags
  29. enc5CheckPresent = 0x0001 // password check data is present
  30. // main archive block flags
  31. arc5MultiVol = 0x0001
  32. arc5Solid = 0x0004
  33. // file block flags
  34. file5IsDir = 0x0001
  35. file5HasUnixMtime = 0x0002
  36. file5HasCRC32 = 0x0004
  37. file5UnpSizeUnknown = 0x0008
  38. // file encryption record flags
  39. file5EncCheckPresent = 0x0001 // password check data is present
  40. file5EncUseMac = 0x0002 // use MAC instead of plain checksum
  41. cacheSize50 = 4
  42. maxPbkdf2Salt = 64
  43. pwCheckSize = 8
  44. maxKdfCount = 24
  45. minHeaderSize = 7
  46. )
  47. var (
  48. errBadPassword = errors.New("rardecode: incorrect password")
  49. errCorruptEncrypt = errors.New("rardecode: corrupt encryption data")
  50. errUnknownEncMethod = errors.New("rardecode: unknown encryption method")
  51. )
  52. type extra struct {
  53. ftype uint64 // field type
  54. data readBuf // field data
  55. }
  56. type blockHeader50 struct {
  57. htype uint64 // block type
  58. flags uint64
  59. data readBuf // block header data
  60. extra []extra // extra fields
  61. dataSize int64 // size of block data
  62. }
  63. // leHash32 wraps a hash.Hash32 to return the result of Sum in little
  64. // endian format.
  65. type leHash32 struct {
  66. hash.Hash32
  67. }
  68. func (h leHash32) Sum(b []byte) []byte {
  69. s := h.Sum32()
  70. return append(b, byte(s), byte(s>>8), byte(s>>16), byte(s>>24))
  71. }
  72. func newLittleEndianCRC32() hash.Hash32 {
  73. return leHash32{crc32.NewIEEE()}
  74. }
  75. // hash50 implements fileChecksum for RAR 5 archives
  76. type hash50 struct {
  77. hash.Hash // hash file data is written to
  78. sum []byte // file checksum
  79. key []byte // if present used with hmac in calculating checksum from hash
  80. }
  81. func (h *hash50) valid() bool {
  82. sum := h.Sum(nil)
  83. if len(h.key) > 0 {
  84. mac := hmac.New(sha256.New, h.key)
  85. mac.Write(sum)
  86. sum = mac.Sum(sum[:0])
  87. if len(h.sum) == 4 {
  88. // CRC32
  89. for i, v := range sum[4:] {
  90. sum[i&3] ^= v
  91. }
  92. sum = sum[:4]
  93. }
  94. }
  95. return bytes.Equal(sum, h.sum)
  96. }
  97. // archive50 implements fileBlockReader for RAR 5 file format archives
  98. type archive50 struct {
  99. byteReader // reader for current block data
  100. v *bufio.Reader // reader for current archive volume
  101. pass []byte
  102. blockKey []byte // key used to encrypt blocks
  103. multi bool // archive is multi-volume
  104. solid bool // is a solid archive
  105. checksum hash50 // file checksum
  106. dec decoder // optional decoder used to unpack file
  107. buf readBuf // temporary buffer
  108. keyCache [cacheSize50]struct { // encryption key cache
  109. kdfCount int
  110. salt []byte
  111. keys [][]byte
  112. }
  113. }
  114. // calcKeys50 calculates the keys used in RAR 5 archive processing.
  115. // The returned slice of byte slices contains 3 keys.
  116. // Key 0 is used for block or file decryption.
  117. // Key 1 is optionally used for file checksum calculation.
  118. // Key 2 is optionally used for password checking.
  119. func calcKeys50(pass, salt []byte, kdfCount int) [][]byte {
  120. if len(salt) > maxPbkdf2Salt {
  121. salt = salt[:maxPbkdf2Salt]
  122. }
  123. keys := make([][]byte, 3)
  124. if len(keys) == 0 {
  125. return keys
  126. }
  127. prf := hmac.New(sha256.New, pass)
  128. prf.Write(salt)
  129. prf.Write([]byte{0, 0, 0, 1})
  130. t := prf.Sum(nil)
  131. u := append([]byte(nil), t...)
  132. kdfCount--
  133. for i, iter := range []int{kdfCount, 16, 16} {
  134. for iter > 0 {
  135. prf.Reset()
  136. prf.Write(u)
  137. u = prf.Sum(u[:0])
  138. for j := range u {
  139. t[j] ^= u[j]
  140. }
  141. iter--
  142. }
  143. keys[i] = append([]byte(nil), t...)
  144. }
  145. pwcheck := keys[2]
  146. for i, v := range pwcheck[pwCheckSize:] {
  147. pwcheck[i&(pwCheckSize-1)] ^= v
  148. }
  149. keys[2] = pwcheck[:pwCheckSize]
  150. return keys
  151. }
  152. // getKeys reads kdfcount and salt from b and returns the corresponding encryption keys.
  153. func (a *archive50) getKeys(b *readBuf) (keys [][]byte, err error) {
  154. if len(*b) < 17 {
  155. return nil, errCorruptEncrypt
  156. }
  157. // read kdf count and salt
  158. kdfCount := int(b.byte())
  159. if kdfCount > maxKdfCount {
  160. return nil, errCorruptEncrypt
  161. }
  162. kdfCount = 1 << uint(kdfCount)
  163. salt := b.bytes(16)
  164. // check cache of keys for match
  165. for _, v := range a.keyCache {
  166. if kdfCount == v.kdfCount && bytes.Equal(salt, v.salt) {
  167. return v.keys, nil
  168. }
  169. }
  170. // not found, calculate keys
  171. keys = calcKeys50(a.pass, salt, kdfCount)
  172. // store in cache
  173. copy(a.keyCache[1:], a.keyCache[:])
  174. a.keyCache[0].kdfCount = kdfCount
  175. a.keyCache[0].salt = append([]byte(nil), salt...)
  176. a.keyCache[0].keys = keys
  177. return keys, nil
  178. }
  179. // checkPassword calculates if a password is correct given password check data and keys.
  180. func checkPassword(b *readBuf, keys [][]byte) error {
  181. if len(*b) < 12 {
  182. return nil // not enough bytes, ignore for the moment
  183. }
  184. pwcheck := b.bytes(8)
  185. sum := b.bytes(4)
  186. csum := sha256.Sum256(pwcheck)
  187. if bytes.Equal(sum, csum[:len(sum)]) && !bytes.Equal(pwcheck, keys[2]) {
  188. return errBadPassword
  189. }
  190. return nil
  191. }
  192. // parseFileEncryptionRecord processes the optional file encryption record from a file header.
  193. func (a *archive50) parseFileEncryptionRecord(b readBuf, f *fileBlockHeader) error {
  194. if ver := b.uvarint(); ver != 0 {
  195. return errUnknownEncMethod
  196. }
  197. flags := b.uvarint()
  198. keys, err := a.getKeys(&b)
  199. if err != nil {
  200. return err
  201. }
  202. f.key = keys[0]
  203. if len(b) < 16 {
  204. return errCorruptEncrypt
  205. }
  206. f.iv = b.bytes(16)
  207. if flags&file5EncCheckPresent > 0 {
  208. if err := checkPassword(&b, keys); err != nil {
  209. return err
  210. }
  211. }
  212. if flags&file5EncUseMac > 0 {
  213. a.checksum.key = keys[1]
  214. }
  215. return nil
  216. }
  217. func (a *archive50) parseFileHeader(h *blockHeader50) (*fileBlockHeader, error) {
  218. a.checksum.sum = nil
  219. a.checksum.key = nil
  220. f := new(fileBlockHeader)
  221. f.first = h.flags&block5DataNotFirst == 0
  222. f.last = h.flags&block5DataNotLast == 0
  223. flags := h.data.uvarint() // file flags
  224. f.IsDir = flags&file5IsDir > 0
  225. f.UnKnownSize = flags&file5UnpSizeUnknown > 0
  226. f.UnPackedSize = int64(h.data.uvarint())
  227. f.PackedSize = h.dataSize
  228. f.Attributes = int64(h.data.uvarint())
  229. if flags&file5HasUnixMtime > 0 {
  230. if len(h.data) < 4 {
  231. return nil, errCorruptFileHeader
  232. }
  233. f.ModificationTime = time.Unix(int64(h.data.uint32()), 0)
  234. }
  235. if flags&file5HasCRC32 > 0 {
  236. if len(h.data) < 4 {
  237. return nil, errCorruptFileHeader
  238. }
  239. a.checksum.sum = append([]byte(nil), h.data.bytes(4)...)
  240. if f.first {
  241. a.checksum.Hash = newLittleEndianCRC32()
  242. f.cksum = &a.checksum
  243. }
  244. }
  245. flags = h.data.uvarint() // compression flags
  246. f.solid = flags&0x0040 > 0
  247. f.winSize = uint(flags&0x3C00)>>10 + 17
  248. method := (flags >> 7) & 7 // compression method (0 == none)
  249. if f.first && method != 0 {
  250. unpackver := flags & 0x003f
  251. if unpackver != 0 {
  252. return nil, errUnknownDecoder
  253. }
  254. if a.dec == nil {
  255. a.dec = new(decoder50)
  256. }
  257. f.decoder = a.dec
  258. }
  259. switch h.data.uvarint() {
  260. case 0:
  261. f.HostOS = HostOSWindows
  262. case 1:
  263. f.HostOS = HostOSUnix
  264. default:
  265. f.HostOS = HostOSUnknown
  266. }
  267. nlen := int(h.data.uvarint())
  268. if len(h.data) < nlen {
  269. return nil, errCorruptFileHeader
  270. }
  271. f.Name = string(h.data.bytes(nlen))
  272. // parse optional extra records
  273. for _, e := range h.extra {
  274. var err error
  275. switch e.ftype {
  276. case 1: // encryption
  277. err = a.parseFileEncryptionRecord(e.data, f)
  278. case 2:
  279. // TODO: hash
  280. case 3:
  281. // TODO: time
  282. case 4: // version
  283. _ = e.data.uvarint() // ignore flags field
  284. f.Version = int(e.data.uvarint())
  285. case 5:
  286. // TODO: redirection
  287. case 6:
  288. // TODO: owner
  289. }
  290. if err != nil {
  291. return nil, err
  292. }
  293. }
  294. return f, nil
  295. }
  296. // parseEncryptionBlock calculates the key for block encryption.
  297. func (a *archive50) parseEncryptionBlock(b readBuf) error {
  298. if ver := b.uvarint(); ver != 0 {
  299. return errUnknownEncMethod
  300. }
  301. flags := b.uvarint()
  302. keys, err := a.getKeys(&b)
  303. if err != nil {
  304. return err
  305. }
  306. if flags&enc5CheckPresent > 0 {
  307. if err := checkPassword(&b, keys); err != nil {
  308. return err
  309. }
  310. }
  311. a.blockKey = keys[0]
  312. return nil
  313. }
  314. func (a *archive50) readBlockHeader() (*blockHeader50, error) {
  315. r := io.Reader(a.v)
  316. if a.blockKey != nil {
  317. // block is encrypted
  318. iv := a.buf[:16]
  319. if err := readFull(r, iv); err != nil {
  320. return nil, err
  321. }
  322. r = newAesDecryptReader(r, a.blockKey, iv)
  323. }
  324. b := a.buf[:minHeaderSize]
  325. if err := readFull(r, b); err != nil {
  326. return nil, err
  327. }
  328. crc := b.uint32()
  329. hash := crc32.NewIEEE()
  330. hash.Write(b)
  331. size := int(b.uvarint()) // header size
  332. if size > cap(a.buf) {
  333. a.buf = readBuf(make([]byte, size))
  334. } else {
  335. a.buf = a.buf[:size]
  336. }
  337. n := copy(a.buf, b) // copy left over bytes
  338. if err := readFull(r, a.buf[n:]); err != nil { // read rest of header
  339. return nil, err
  340. }
  341. // check header crc
  342. hash.Write(a.buf[n:])
  343. if crc != hash.Sum32() {
  344. return nil, errBadHeaderCrc
  345. }
  346. b = a.buf
  347. h := new(blockHeader50)
  348. h.htype = b.uvarint()
  349. h.flags = b.uvarint()
  350. var extraSize int
  351. if h.flags&block5HasExtra > 0 {
  352. extraSize = int(b.uvarint())
  353. }
  354. if h.flags&block5HasData > 0 {
  355. h.dataSize = int64(b.uvarint())
  356. }
  357. if len(b) < extraSize {
  358. return nil, errCorruptHeader
  359. }
  360. h.data = b.bytes(len(b) - extraSize)
  361. // read header extra records
  362. for len(b) > 0 {
  363. size = int(b.uvarint())
  364. if len(b) < size {
  365. return nil, errCorruptHeader
  366. }
  367. data := readBuf(b.bytes(size))
  368. ftype := data.uvarint()
  369. h.extra = append(h.extra, extra{ftype, data})
  370. }
  371. return h, nil
  372. }
  373. // next advances to the next file block in the archive
  374. func (a *archive50) next() (*fileBlockHeader, error) {
  375. for {
  376. h, err := a.readBlockHeader()
  377. if err != nil {
  378. return nil, err
  379. }
  380. a.byteReader = limitByteReader(a.v, h.dataSize)
  381. switch h.htype {
  382. case block5File:
  383. return a.parseFileHeader(h)
  384. case block5Arc:
  385. flags := h.data.uvarint()
  386. a.multi = flags&arc5MultiVol > 0
  387. a.solid = flags&arc5Solid > 0
  388. case block5Encrypt:
  389. err = a.parseEncryptionBlock(h.data)
  390. case block5End:
  391. flags := h.data.uvarint()
  392. if flags&endArc5NotLast == 0 || !a.multi {
  393. return nil, errArchiveEnd
  394. }
  395. return nil, errArchiveContinues
  396. default:
  397. // discard block data
  398. _, err = io.Copy(ioutil.Discard, a.byteReader)
  399. }
  400. if err != nil {
  401. return nil, err
  402. }
  403. }
  404. }
  405. func (a *archive50) version() int { return fileFmt50 }
  406. func (a *archive50) reset() {
  407. a.blockKey = nil // reset encryption when opening new volume file
  408. }
  409. func (a *archive50) isSolid() bool {
  410. return a.solid
  411. }
  412. // newArchive50 creates a new fileBlockReader for a Version 5 archive.
  413. func newArchive50(r *bufio.Reader, password string) fileBlockReader {
  414. a := new(archive50)
  415. a.v = r
  416. a.pass = []byte(password)
  417. a.buf = make([]byte, 100)
  418. return a
  419. }