def __init__(self,
                     nca3,
                     section_header,
                     verify=False,
                     ifo=0,
                     buffer=65536):
            self.nca = nca3
            self.section_header = section_header

            self.key = self.nca.body_key
            self.nonce = pk_u64(self.section_header.section_ctr,
                                endianness='>')

            self.section_offset = self.section_header.offset
            self.section_size = self.section_header.size
            self.fs_type = self.section_header.fs_type
            self.crypto = self.section_header.crypto_type
            self.ifo = ifo
            self.buffer = buffer

            if self.crypto in ('BTKR', 'XTS'):
                raise NotImplementedError('BTKR/XTS not implemented')

            super(NCA3.SectionInNCA3,
                  self).__init__(self.nca.f, self.section_offset,
                                 self.section_size)

            self.is_exefs = False
            if self.fs_type == 'PFS0':
                self.cont_offset = self.section_header.superblock.offset
                self.cont_size = self.section_header.superblock.size
                self.fs = HashTableWrappedPFS0(self.section_header.superblock,
                                               self,
                                               verify=verify)
                if 'main.npdm' in self.fs.files:
                    self.is_exefs = True
            elif self.fs_type == 'RomFS':
                self.cont_offset = self.section_header.superblock.lvls[
                    IVFCSuperblock.IVFC_MAX_LEVEL - 1].offset
                self.cont_size = self.section_header.superblock.lvls[
                    IVFCSuperblock.IVFC_MAX_LEVEL - 1].size
                self.fs = HashTreeWrappedRomFS(self.section_header.superblock,
                                               self,
                                               verify=verify)
    class SectionInNCA3(FileInContainer):
        def __init__(self,
                     nca3,
                     section_header,
                     verify=False,
                     ifo=0,
                     buffer=65536):
            self.nca = nca3
            self.section_header = section_header

            self.key = self.nca.body_key
            self.nonce = pk_u64(self.section_header.section_ctr,
                                endianness='>')

            self.section_offset = self.section_header.offset
            self.section_size = self.section_header.size
            self.fs_type = self.section_header.fs_type
            self.crypto = self.section_header.crypto_type
            self.ifo = ifo
            self.buffer = buffer

            if self.crypto in ('BTKR', 'XTS'):
                raise NotImplementedError('BTKR/XTS not implemented')

            super(NCA3.SectionInNCA3,
                  self).__init__(self.nca.f, self.section_offset,
                                 self.section_size)

            self.is_exefs = False
            if self.fs_type == 'PFS0':
                self.cont_offset = self.section_header.superblock.offset
                self.cont_size = self.section_header.superblock.size
                self.fs = HashTableWrappedPFS0(self.section_header.superblock,
                                               self,
                                               verify=verify)
                if 'main.npdm' in self.fs.files:
                    self.is_exefs = True
            elif self.fs_type == 'RomFS':
                self.cont_offset = self.section_header.superblock.lvls[
                    IVFCSuperblock.IVFC_MAX_LEVEL - 1].offset
                self.cont_size = self.section_header.superblock.lvls[
                    IVFCSuperblock.IVFC_MAX_LEVEL - 1].size
                self.fs = HashTreeWrappedRomFS(self.section_header.superblock,
                                               self,
                                               verify=verify)

        def update_ctr(self, off):
            self.ctr = Counter.new(
                64,
                prefix=self.nonce,
                initial_value=((self.section_offset + off) >> 4))
            self.cipher = AES.new(self.key, AES.MODE_CTR, counter=self.ctr)

        def seek(self, off):
            if self.crypto == 'None' or self.crypto == 'BTKR' or self.crypto == 'XTS':
                super(NCA3.SectionInNCA3, self).seek(self.ifo + off)
            elif self.crypto == 'CTR':
                block_offset = off & ~0xF
                self.sector_offset = off & 0xF
                super(NCA3.SectionInNCA3, self).seek(self.ifo + block_offset)
                self.update_ctr(block_offset)

        def read(self, length=None):
            if self.crypto == 'None' or self.crypto == 'BTKR' or self.crypto == 'XTS':
                data = super(NCA3.SectionInNCA3, self).read(length)
                return data
            elif self.crypto == 'CTR':
                aligned_length = align_to(length + self.sector_offset, 0x10)
                dec_data = self.cipher.decrypt(
                    super(NCA3.SectionInNCA3, self).read(aligned_length))
                if aligned_length != length:
                    try:
                        return dec_data[self.sector_offset:length +
                                        self.sector_offset]
                    finally:  # Seek to what the offset should be if not for the crypto
                        self.seek(self.ifo + self.tell() - aligned_length +
                                  length)
                else:
                    return dec_data[:length]

        def _decrypt_from_offset(self, off, size=None):
            self.seek(off + self.ifo)
            read = 0
            while True:
                buf = self.read(self.buffer)
                if not buf:
                    break
                if size and (read + len(buf) >= size):
                    yield buf[:size - read]
                    break
                yield buf
                read += len(buf)

        def decrypt_raw(self):
            for buf in self._decrypt_from_offset(0):
                yield buf

        def decrypt_raw_cont(self):
            for buf in self._decrypt_from_offset(self.cont_offset,
                                                 self.cont_size):
                yield buf

        def extract_cont(self, dest=None):
            self.fs.extract(dest, disp=False)