├── fat16gen-master ├── testdir │ ├── TOOLONGNAME.TXT │ ├── a.b.c.d.txt │ ├── bar │ │ ├── hello.txt │ │ └── FAT.H │ ├── hello.txt │ ├── a really long file name test.txt │ └── fatty.h ├── Makefile ├── testmain.c ├── .gitignore ├── LICENSE ├── fat.c ├── fat.h ├── fatname.py ├── README.md └── genfs.py ├── source.cpp ├── source1.cpp ├── gui.cpp ├── .gitattributes ├── README.md.txt ├── README.md ├── main.cu ├── DEBUG.cu └── .gitignore /fat16gen-master/testdir/TOOLONGNAME.TXT: -------------------------------------------------------------------------------- 1 | too long 2 | -------------------------------------------------------------------------------- /fat16gen-master/testdir/a.b.c.d.txt: -------------------------------------------------------------------------------- 1 | a.b.c.d.txt 2 | -------------------------------------------------------------------------------- /fat16gen-master/testdir/bar/hello.txt: -------------------------------------------------------------------------------- 1 | hello also 2 | -------------------------------------------------------------------------------- /fat16gen-master/testdir/hello.txt: -------------------------------------------------------------------------------- 1 | hello world 2 | -------------------------------------------------------------------------------- /fat16gen-master/testdir/a really long file name test.txt: -------------------------------------------------------------------------------- 1 | a long name 2 | -------------------------------------------------------------------------------- /source.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wynneyin/ZKPFILESYSTEM/HEAD/source.cpp -------------------------------------------------------------------------------- /source1.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wynneyin/ZKPFILESYSTEM/HEAD/source1.cpp -------------------------------------------------------------------------------- /fat16gen-master/Makefile: -------------------------------------------------------------------------------- 1 | test.img: fatgen 2 | ./fatgen > test.img 3 | 4 | fatgen : fat.c fs.c testmain.c fat.h 5 | gcc -g fat.c fs.c testmain.c -o fatgen 6 | 7 | fs.c : genfs.py fatname.py testdir 8 | python genfs.py > fs.c 9 | 10 | clean : 11 | rm -rf *.pyc fatgen test.img *.dSYM 12 | -------------------------------------------------------------------------------- /fat16gen-master/testdir/bar/FAT.H: -------------------------------------------------------------------------------- 1 | #ifndef _FAT_H 2 | #define _FAT_H 3 | 4 | typedef struct __attribute__ ((packed)) { 5 | char name[8]; 6 | char extn[3]; 7 | uint8_t attr; 8 | uint8_t reserved; 9 | uint8_t crt_time_tenth; 10 | uint16_t crt_time; 11 | uint16_t crt_date; 12 | uint16_t lst_access_date; 13 | uint16_t strt_clus_hword; 14 | uint16_t lst_mod_time; 15 | uint16_t lst_mod_date; 16 | uint16_t strt_clus_lword; 17 | uint32_t size; 18 | } dir_entry; 19 | 20 | typedef struct __attribute__ ((packed)) { 21 | uint8_t ord_field; 22 | uint8_t fname0_4[10]; 23 | uint8_t flag; 24 | uint8_t reserved; 25 | uint8_t ch -------------------------------------------------------------------------------- /fat16gen-master/testmain.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "fat.h" 6 | 7 | int vfile_1(uint32_t blknum, uint8_t *buf, const vfile_t *filesys, uint32_t index) { 8 | int i; 9 | char f; 10 | 11 | if (blknum == 0) 12 | f = '0'; 13 | else 14 | f = '1'; 15 | if (blknum < 2) 16 | for (i = 0; i < BLOCKSIZE; i++) 17 | buf[i] = f; 18 | return 0; 19 | } 20 | 21 | extern const vfile_t filesys; 22 | 23 | int main() { 24 | uint8_t buf[BLOCKSIZE]; 25 | int i; 26 | int limit = filesys.clusterstart + filesys.maxcluster*filesys.blocks_per_cluster; 27 | for (i = 0; i < limit; i++) { 28 | read_vdisk(&filesys, i, buf, 1); 29 | write(STDOUT_FILENO, buf, BLOCKSIZE); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /fat16gen-master/.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | # generated files 54 | fatgen 55 | fatname.pyc 56 | fs.c 57 | test.img 58 | *~ 59 | \#* 60 | *.pyc 61 | -------------------------------------------------------------------------------- /fat16gen-master/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Geoffrey Brown 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /gui.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class FileSystemExplorer : public QWidget { 10 | public: 11 | FileSystemExplorer(QWidget *parent = nullptr) : QWidget(parent) { 12 | // Layout 13 | QVBoxLayout *layout = new QVBoxLayout(this); 14 | 15 | // Label to show current directory 16 | QLabel *directoryLabel = new QLabel("Current Directory:", this); 17 | layout->addWidget(directoryLabel); 18 | 19 | // File system model to handle file browsing 20 | QFileSystemModel *model = new QFileSystemModel(this); 21 | model->setRootPath(QDir::rootPath()); 22 | 23 | // Tree view to display the file system 24 | QTreeView *treeView = new QTreeView(this); 25 | treeView->setModel(model); 26 | treeView->setRootIndex(model->index(QDir::rootPath())); 27 | treeView->setSortingEnabled(true); // Enable sorting by name, size, etc. 28 | 29 | // Add the tree view to the layout 30 | layout->addWidget(treeView); 31 | 32 | // Button to open a selected file (dummy action for now) 33 | QPushButton *openButton = new QPushButton("Open File", this); 34 | layout->addWidget(openButton); 35 | 36 | connect(openButton, &QPushButton::clicked, [=]() { 37 | QModelIndex index = treeView->currentIndex(); 38 | if (index.isValid()) { 39 | QString filePath = model->filePath(index); 40 | // You can handle opening the file here (e.g., using QFile or QProcess) 41 | directoryLabel->setText("Selected File: " + filePath); 42 | } 43 | }); 44 | 45 | setLayout(layout); 46 | setWindowTitle("Simple File Explorer"); 47 | resize(600, 400); // Set initial window size 48 | } 49 | }; 50 | 51 | int main(int argc, char *argv[]) { 52 | QApplication app(argc, argv); 53 | 54 | FileSystemExplorer explorer; 55 | explorer.show(); 56 | 57 | return app.exec(); 58 | } 59 | -------------------------------------------------------------------------------- /fat16gen-master/fat.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "fat.h" 6 | 7 | 8 | int datagen(uint32_t blknum, uint8_t *buf, const vfile_t *filesys, 9 | uint32_t index) { 10 | const uint8_t *data = (const uint8_t *) filesys->table[index].data; 11 | uint32_t len = filesys->table[index].len; 12 | 13 | for (int i = 0; (i < BLOCKSIZE) && (i + blknum*BLOCKSIZE < len); i++) 14 | buf[i] = data[i+blknum*BLOCKSIZE]; 15 | return 0; 16 | } 17 | 18 | /* 19 | * Separate code to compute fat entry for a given cluster from code that 20 | * writes the fat table entry. This should make it easier to support fat12 or fat32 if 21 | * needed. 22 | */ 23 | 24 | // compute the correct fat entry 25 | // returns a value suitable for fat12,fat16, and fat32 26 | 27 | static inline uint32_t fatentry(const vfile_t *filesys, uint32_t cluster, uint32_t *index){ 28 | 29 | if (cluster == 0) 30 | return 0x0FFFFFF8; 31 | 32 | if (cluster == 1) 33 | return 0x0FFFFFFF; 34 | 35 | // Bad cluster ? 36 | 37 | if (cluster >= filesys->maxcluster) 38 | return 0x0FFFFFF7; 39 | 40 | // Find the correct table entry 41 | 42 | if (cluster < filesys->table[*index].start_cluster) 43 | *index = 0; 44 | 45 | while (cluster >= filesys->table[*index+1].start_cluster) 46 | *index = *index + 1; 47 | 48 | // compute entry 49 | 50 | int cmp = (filesys->table[*index].start_cluster + 51 | filesys->table[*index].len/(BLOCKSIZE*filesys->blocks_per_cluster)) - cluster; 52 | if (cmp == 0) // last cluster in file 53 | return 0x0FFFFFF8; 54 | if (cmp > 0) // not last 55 | return cluster + 1; 56 | return 0; // after last -- mark as empty 57 | } 58 | 59 | int fat16(uint32_t blknum, uint8_t *buf, const vfile_t *filesys, uint32_t idx) { 60 | (void) idx; 61 | uint32_t cluster = blknum * 256; 62 | uint32_t lastcluster = cluster + 256; 63 | uint32_t index = 0; // starting point of table search 64 | for (; cluster < lastcluster; cluster++) { 65 | uint32_t val = fatentry(filesys, cluster, &index); 66 | *buf++ = (val & 0xff); 67 | *buf++ = (val >> 8) & 0xff; 68 | } 69 | return 0; 70 | } 71 | 72 | int read_vdisk(const void *instance, uint32_t startblk, uint8_t *buf, uint32_t n) { 73 | const vfile_t *ft = (vfile_t *) instance; 74 | int index = 0; 75 | while (n--) { 76 | bzero(buf,BLOCKSIZE); 77 | while (ft->table[index + 1].start_block <= startblk) index++; 78 | if (startblk < UINT32_MAX) { 79 | if (ft->table[index].fun) { 80 | ft->table[index].fun(startblk - ft->table[index].start_block, buf, ft, index); 81 | } 82 | startblk++; 83 | } 84 | buf += BLOCKSIZE; 85 | } 86 | return 0; 87 | } 88 | 89 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /fat16gen-master/testdir/fatty.h: -------------------------------------------------------------------------------- 1 | #ifndef _FAT_H 2 | #define _FAT_H 3 | 4 | typedef struct __attribute__ ((packed)) { 5 | char name[8]; 6 | char extn[3]; 7 | uint8_t attr; 8 | uint8_t reserved; 9 | uint8_t crt_time_tenth; 10 | uint16_t crt_time; 11 | uint16_t crt_date; 12 | uint16_t lst_access_date; 13 | uint16_t strt_clus_hword; 14 | uint16_t lst_mod_time; 15 | uint16_t lst_mod_date; 16 | uint16_t strt_clus_lword; 17 | uint32_t size; 18 | } dir_entry; 19 | 20 | typedef struct __attribute__ ((packed)) { 21 | uint8_t ord_field; 22 | uint8_t fname0_4[10]; 23 | uint8_t flag; 24 | uint8_t reserved; 25 | uint8_t chksum; 26 | uint8_t fname6_11[12]; 27 | uint8_t empty[2]; 28 | uint8_t fname12_13[4]; 29 | } lfn_entry; 30 | 31 | typedef union { 32 | dir_entry d; 33 | lfn_entry l; 34 | } dir_lfn; 35 | 36 | #define CRTTIME(hour,min,sec) ((hour)<<11 | (min) << 5 | ((sec)/2)) 37 | #define CRTDATE(year,mon,day) ((year)-1980)<<9 |(mon) << 5 | (day) 38 | 39 | #define DIR_ENTRY(nm,e, at, year,month,day,hour,min,sec,clust,s) \ 40 | { .name = nm, .extn = e, .attr = at, \ 41 | .crt_time = CRTTIME(hour,min,sec), \ 42 | .crt_date = CRTDATE(year,month,day), \ 43 | .lst_mod_time = CRTTIME(hour,min,sec), \ 44 | .lst_mod_date = CRTDATE(year,month,day), \ 45 | .strt_clus_lword = clust, \ 46 | .size = s } 47 | 48 | typedef struct __attribute__ ((packed)) { 49 | uint8_t jump_code[3]; 50 | uint8_t oem_name[8]; 51 | uint16_t bytes_per_sector; 52 | uint8_t cluster_size; 53 | uint16_t reserved_sectors; 54 | uint8_t fat_copies; 55 | uint16_t max_root_dir; 56 | uint16_t sectors_per_partition; 57 | uint8_t media_descriptor; 58 | uint16_t sectors_per_fat; 59 | uint16_t sectors_per_track; 60 | uint16_t heads; 61 | uint32_t hidden; 62 | uint32_t sectors_per_partition_large; 63 | uint16_t logical_drive; 64 | uint8_t signature; 65 | uint32_t serial_number; 66 | uint8_t volume[11]; 67 | uint8_t fatname[8]; 68 | uint8_t code[448]; 69 | uint8_t marker[2]; 70 | } bootrecord; 71 | 72 | typedef struct filetab_s filetab_t; 73 | typedef struct vfile_s vfile_t; 74 | 75 | typedef int datagen_t(uint32_t blknum, uint8_t *buf, const vfile_t *filesys, uint32_t index); 76 | 77 | extern datagen_t datagen; 78 | extern datagen_t fatgen; 79 | 80 | struct filetab_s { 81 | uint32_t start_block; // UINT32_MAX for end 82 | uint32_t len; 83 | datagen_t *fun; 84 | const void *data; 85 | }; 86 | 87 | struct vfile_s { 88 | uint32_t maxblock; 89 | uint32_t clusters_per_block; 90 | uint32_t maxcluster; 91 | uint32_t clusterstart; 92 | uint32_t total_sectors; 93 | filetab_t table[]; 94 | }; 95 | 96 | extern int read_vdisk(const void *instance, uint32_t startblk, uint8_t *buf, uint32_t n); 97 | 98 | #endif 99 | 100 | 101 | -------------------------------------------------------------------------------- /fat16gen-master/fat.h: -------------------------------------------------------------------------------- 1 | #ifndef _FAT_H 2 | #define _FAT_H 3 | 4 | #include 5 | 6 | #define BLOCKSIZE 512 7 | 8 | #define CRTTIME(hour,min,sec) ((hour)<<11 | (min) << 5 | ((sec)/2)) 9 | #define CRTDATE(year,mon,day) ((year)-1980)<<9 |(mon) << 5 | (day) 10 | 11 | #define DIR_ENTRY(nm,e, at, year,month,day,hour,min,sec,clust,s) \ 12 | { .name = nm, .extn = e, .attr = at, \ 13 | .crt_time = CRTTIME(hour,min,sec), \ 14 | .crt_date = CRTDATE(year,month,day), \ 15 | .lst_mod_time = CRTTIME(hour,min,sec), \ 16 | .lst_mod_date = CRTDATE(year,month,day), \ 17 | .lst_access_date = CRTDATE(year,month,day), \ 18 | .strt_clus_lword = clust, \ 19 | .size = s } 20 | 21 | typedef struct __attribute__ ((packed)) { 22 | char name[8]; 23 | char extn[3]; 24 | uint8_t attr; 25 | uint8_t reserved; 26 | uint8_t crt_time_tenth; 27 | uint16_t crt_time; 28 | uint16_t crt_date; 29 | uint16_t lst_access_date; 30 | uint16_t strt_clus_hword; 31 | uint16_t lst_mod_time; 32 | uint16_t lst_mod_date; 33 | uint16_t strt_clus_lword; 34 | uint32_t size; 35 | } dir_entry; 36 | 37 | typedef struct __attribute__ ((packed)) { 38 | uint8_t ord; 39 | uint16_t fname1_5[5]; 40 | uint8_t flag; 41 | uint8_t reserved; 42 | uint8_t chksum; 43 | uint16_t fname6_11[6]; 44 | uint8_t empty[2]; 45 | uint16_t fname12_13[2]; 46 | } lfn_entry; 47 | 48 | typedef union { 49 | dir_entry d; 50 | lfn_entry l; 51 | } dir_lfn; 52 | 53 | typedef struct __attribute__ ((packed)) { 54 | uint8_t jump_code[3]; 55 | uint8_t oem_name[8]; 56 | uint16_t bytes_per_sector; 57 | uint8_t cluster_size; 58 | uint16_t reserved_sectors; 59 | uint8_t fat_copies; 60 | uint16_t max_root_dir; 61 | uint16_t sectors_per_partition; 62 | uint8_t media_descriptor; 63 | uint16_t sectors_per_fat; 64 | uint16_t sectors_per_track; 65 | uint16_t heads; 66 | uint32_t hidden; 67 | uint32_t sectors_per_partition_large; 68 | uint16_t logical_drive; 69 | uint8_t signature; 70 | uint32_t serial_number; 71 | uint8_t volume[11]; 72 | uint8_t fatname[8]; 73 | uint8_t code[448]; 74 | uint8_t marker[2]; 75 | } bootrecord; 76 | 77 | typedef struct filetab_s filetab_t; 78 | typedef struct vfile_s vfile_t; 79 | 80 | typedef int datagen_t(uint32_t blknum, uint8_t *buf, const vfile_t *filesys, uint32_t index); 81 | 82 | struct filetab_s { 83 | uint32_t start_block; // UINT32_MAX for end 84 | uint32_t start_cluster; 85 | uint32_t len; 86 | datagen_t *fun; 87 | const void *data; 88 | }; 89 | 90 | struct vfile_s { 91 | uint32_t maxblock; 92 | uint32_t maxcluster; 93 | uint32_t blocks_per_cluster; 94 | uint32_t clusterstart; 95 | uint32_t total_sectors; 96 | filetab_t table[]; 97 | }; 98 | 99 | extern datagen_t datagen; 100 | extern datagen_t fat16; 101 | extern int read_vdisk(const void *instance, uint32_t startblk, uint8_t *buf, uint32_t n); 102 | 103 | #endif 104 | 105 | 106 | -------------------------------------------------------------------------------- /README.md.txt: -------------------------------------------------------------------------------- 1 | # ZKP-Based FAT16 File System 2 | 3 | This project enhances the traditional FAT16 file system by integrating zero-knowledge proof (ZKP) techniques for secure file ownership, integrity verification, and privacy-preserving access control. It allows users to store encrypted files and verify their ownership and integrity without revealing the file's content. This system ensures robust data security, prevents unauthorized access, and counters tampering using cryptographic proofs. 4 | 5 | ## Features 6 | 7 | - **File Encryption**: All files are encrypted using a symmetric encryption algorithm (AES). The user retains control of the encryption key. 8 | - **Zero-Knowledge Proof (ZKP) Ownership**: Users can prove ownership of files without exposing sensitive keys or file content. 9 | - **Integrity Verification**: File integrity is verified using cryptographic hashes (SHA-256). Users can prove that a file has not been tampered with using ZKP-based verification. 10 | - **ZKP-Based Access Control**: Permission management is handled using ZKP to prove access rights without revealing credentials. 11 | - **Tamper Resistance**: ZKP mechanisms ensure that any changes or unauthorized file modifications are detected without revealing the file content. 12 | - **Compatibility**: The system is built on top of the FAT16 file system, ensuring compatibility with the original structure while adding cryptographic enhancements. 13 | 14 | ## Architecture Overview 15 | 16 | 1. Encryption Layer 17 | 18 | : 19 | 20 | - Before writing to the FAT16 file system, all file data is encrypted using AES encryption. The encryption key is held by the user and not stored in the file system. 21 | 22 | 2. Proof Generation 23 | 24 | : 25 | 26 | - When accessing a file, the user generates a zero-knowledge proof to show they have the decryption key without revealing the key itself. 27 | 28 | 3. Integrity Layer 29 | 30 | : 31 | 32 | - Each file’s hash is computed and stored. Users can prove file integrity without accessing the actual file data through a ZKP protocol. 33 | 34 | 4. Access Control 35 | 36 | : 37 | 38 | - Permissions to read/write files are checked using zero-knowledge proofs. Users prove they have access rights, verified by the system without revealing their credentials. 39 | 40 | 5. Tamper Detection 41 | 42 | : 43 | 44 | - Any modification to the encrypted file will result in a different hash. ZKP can verify the file’s original hash, allowing detection of tampering without accessing the file’s content. 45 | 46 | ## Requirements 47 | 48 | - **FAT16 File System**: The system works on top of FAT16, so the base storage format is FAT16-compliant. 49 | 50 | - Cryptographic Libraries 51 | 52 | : 53 | 54 | - AES encryption/decryption library. 55 | - SHA-256 hash function. 56 | - Zero-knowledge proof protocols (e.g., Schnorr, Bulletproofs). 57 | 58 | ## Usage 59 | 60 | 1. **Initializing the File System**: 61 | - Initialize the FAT16 file system if not already available. All files will be handled in an encrypted format on top of this. 62 | 2. **Adding Files**: 63 | - Files can be added to the system, and they will automatically be encrypted. 64 | - An integrity hash will be generated, and a ZKP proof will be created for ownership and integrity verification. 65 | 3. **Verifying Files**: 66 | - Users can verify that they own a file and prove its integrity without accessing the raw data. 67 | 4. **Accessing Files**: 68 | - When a user tries to access a file, they will generate a ZKP to verify their access rights. Once verified, the file is decrypted for the user. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ZKP-Based FAT16 File System 2 | 3 | This project enhances the traditional FAT16 file system by integrating zero-knowledge proof (ZKP) techniques for secure file ownership, integrity verification, and privacy-preserving access control. It allows users to store encrypted files and verify their ownership and integrity without revealing the file's content. This system ensures robust data security, prevents unauthorized access, and counters tampering using cryptographic proofs. 4 | 5 | ## Features 6 | 7 | - **File Encryption**: All files are encrypted using a symmetric encryption algorithm (AES). The user retains control of the encryption key. 8 | - **Zero-Knowledge Proof (ZKP) Ownership**: Users can prove ownership of files without exposing sensitive keys or file content. 9 | - **Integrity Verification**: File integrity is verified using cryptographic hashes (SHA-256). Users can prove that a file has not been tampered with using ZKP-based verification. 10 | - **ZKP-Based Access Control**: Permission management is handled using ZKP to prove access rights without revealing credentials. 11 | - **Tamper Resistance**: ZKP mechanisms ensure that any changes or unauthorized file modifications are detected without revealing the file content. 12 | - **Compatibility**: The system is built on top of the FAT16 file system, ensuring compatibility with the original structure while adding cryptographic enhancements. 13 | 14 | ## Architecture Overview 15 | 16 | 1. Encryption Layer 17 | 18 | : 19 | 20 | - Before writing to the FAT16 file system, all file data is encrypted using AES encryption. The encryption key is held by the user and not stored in the file system. 21 | 22 | 2. Proof Generation 23 | 24 | : 25 | 26 | - When accessing a file, the user generates a zero-knowledge proof to show they have the decryption key without revealing the key itself. 27 | 28 | 3. Integrity Layer 29 | 30 | : 31 | 32 | - Each file’s hash is computed and stored. Users can prove file integrity without accessing the actual file data through a ZKP protocol. 33 | 34 | 4. Access Control 35 | 36 | : 37 | 38 | - Permissions to read/write files are checked using zero-knowledge proofs. Users prove they have access rights, verified by the system without revealing their credentials. 39 | 40 | 5. Tamper Detection 41 | 42 | : 43 | 44 | - Any modification to the encrypted file will result in a different hash. ZKP can verify the file’s original hash, allowing detection of tampering without accessing the file’s content. 45 | 46 | ## Requirements 47 | 48 | - **FAT16 File System**: The system works on top of FAT16, so the base storage format is FAT16-compliant. 49 | 50 | - Cryptographic Libraries 51 | 52 | : 53 | 54 | - AES encryption/decryption library. 55 | - SHA-256 hash function. 56 | - Zero-knowledge proof protocols (e.g., Schnorr, Bulletproofs). 57 | 58 | ## Usage 59 | 60 | 1. **Initializing the File System**: 61 | - Initialize the FAT16 file system if not already available. All files will be handled in an encrypted format on top of this. 62 | 2. **Adding Files**: 63 | - Files can be added to the system, and they will automatically be encrypted. 64 | - An integrity hash will be generated, and a ZKP proof will be created for ownership and integrity verification. 65 | 3. **Verifying Files**: 66 | - Users can verify that they own a file and prove its integrity without accessing the raw data. 67 | 4. **Accessing Files**: 68 | - When a user tries to access a file, they will generate a ZKP to verify their access rights. Once verified, the file is decrypted for the user. 69 | -------------------------------------------------------------------------------- /fat16gen-master/fatname.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import os 4 | import re 5 | import sys 6 | 7 | def chksum(nm,ext): 8 | name = "%-8s%-3s"%(nm,ext) 9 | if len(name) != 11: 10 | print >> sys.stderr, "unexpected name length in checksum %d %s"%(len(name),name) 11 | sum = 0 12 | for c in name: 13 | sum = ((((sum & 1) << 7) | ((sum & 0xfe) >> 1)) + ord(c)) 14 | return sum & 0xff 15 | 16 | def shortname(nm,num): 17 | nm = re.sub('^[\.]*','',nm) # strip leading dots 18 | nm = re.sub(' ','',nm) # strip spaces 19 | nm = re.sub('[ "*+,/:;<=>?\\\[\]\|]',"_",nm).upper() # replace illegal dos chars 20 | parts = nm.rsplit('.',1) # split on last dot 21 | head = re.sub('\.','',parts[0])[:8] # remove extra dots and trim 22 | if len(parts) > 1: 23 | tail = parts[1][:3] 24 | else: 25 | tail = "" 26 | # if shortname == longname, return original 27 | if (head + '.' + tail) == nm: 28 | return (head,tail) 29 | # create numbered version 30 | if num < 10: 31 | return ("%s~%1d"%(head[:6],num),tail[:3]) 32 | elif num < 100: 33 | return ("%s~%2d"%(head[:5],num),tail[:3]) 34 | else: 35 | print >> sys.stderr, "Too many identical shortnames" 36 | raise 37 | 38 | def longname(nm): 39 | nm = re.sub('^[\. ]*','',nm) # strip leading dots and spaces 40 | nm = re.sub('[^\w \.-]',"_",nm) # replace illegal characters 41 | parts = nm.rsplit('.',1) # split on last dot 42 | if len(parts) > 1: 43 | parts[0] = re.sub('\.','',parts[0]) 44 | nm = ".".join(parts) 45 | return nm 46 | 47 | class FatName: 48 | def __init__(self,path,shortdict): 49 | self._path = path 50 | self._longname = longname(os.path.basename(path)) 51 | dirname = os.path.dirname(path) 52 | if not dirname in shortdict: 53 | shortdict[dirname] = {} 54 | 55 | success = False 56 | for i in range(99)[1:]: 57 | nm = shortname(self._longname,i) 58 | if not nm in shortdict[dirname]: 59 | shortdict[dirname][nm] = True 60 | success = True 61 | break 62 | if success: 63 | self._name = nm[0] 64 | self._ext = nm[1] 65 | self._checksum = chksum(nm[0],nm[1]) 66 | else: 67 | raise Exception("too many similar file names") 68 | 69 | @property 70 | def path(self): 71 | return self._path 72 | 73 | @property 74 | def longname(self): 75 | return self._longname 76 | 77 | @property 78 | def name(self): 79 | return self._name 80 | 81 | @property 82 | def ext(self): 83 | return self._ext 84 | 85 | @property 86 | def checksum(self): 87 | return self._checksum 88 | 89 | def needlfn(self): 90 | return '.'.join([self._name,self._ext]) != self._longname 91 | 92 | 93 | def test(nm,sortdict): 94 | print "trying %s"%(nm) 95 | f = FatName(nm,shortdict) 96 | print "\tpath %s"%(f.path) 97 | print "\tlongname %s"%(f.longname) 98 | print "\tname %s ext %s checksum 0x%x"%(f.name,f.ext,f.checksum) 99 | 100 | 101 | if __name__ == "__main__": 102 | shortdict = {} 103 | test("./a",shortdict) 104 | test("./b/a",shortdict) 105 | test("./ABCDEFG.x",shortdict) 106 | test("./",shortdict) 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /fat16gen-master/README.md: -------------------------------------------------------------------------------- 1 | # Generates a fat16 file system 2 | 3 | While this is intended for use in embedded devices, the test code provided will generate a static image. In the dynamic 4 | case, the file system consists of a constant table driven file system with a few built-in functions to generate 5 | content on demand. This content includes the fat16 boot record and fat tables as well as directories and static files. 6 | The code also provides a hook for dynamic file content. 7 | 8 | ## How this works 9 | 10 | The main module, gensys, takes as input a root directory (containing static files and directories) and a list 11 | of "virtual file" definitions (where they go in the file hierarchy, their size, a generator function name, 12 | and a (void *) operand). The code below (in gensys.py) generates an example file system definition on *stdout*. 13 | 14 | ````c 15 | volume_name = 'Test Volume' # fat16 volume name 16 | table_name = 'filesys' # C name of file system table 17 | fdout = sys.stdout # output file 18 | rootdir = 'testdir' # path to root file system 19 | 20 | vfiles = [{'path' : os.path.join(rootdir,'a virtual file.txt'), 21 | 'size' : 1024, 22 | 'func' : 'vfile_1', 23 | 'operand' : '(void *) 0' 24 | } 25 | ] 26 | 27 | fs = vFileSystem(rootdir,vfiles) 28 | fs.gensys(fdout,table_name,volume_name) 29 | ```` 30 | 31 | It doesn't appear (easily) feasible to generate a file system that the host can modify; thankfully that wasn't necessary for 32 | our application -- an embedded data logger with a large flash (2Gbit) chip. We wanted an easy way to 33 | access that data and perhaps a bit of status information (through a virtual file). 34 | 35 | To test this, you don't need an embedded device. The Makefile will generate an image -- 36 | execute **make** to generate test image _test.img_ that can be mounted. This image 37 | contains the files and directories in _testdir_ along with one virtual file _a virtual file.txt_. The contents of this 38 | file are generated by the procedure *vfile_1* in *testmain.c* 39 | 40 | ## Implementation Notes 41 | 42 | The other major module is *fatname.py*. This is where all the conversion from host file system names to Microsoft long and 43 | short file names occurs. It's somewhat hard to be sure that all possible cases are accounted for (the available fat file 44 | system documentation leaves a bit too much as an exercise to the reader). If there's a case that doesn't work, perhaps the 45 | best thing is to rename your static files; alternatively, suggest a patch. 46 | 47 | The code also doesn't check for "long name" collisions -- cases where two 48 | long names are rewritten (to meet windows requirements) to the same string. 49 | 50 | This was implemented using the gcc compiler; _fat.h_ uses attributes to define packed data structures for key components of the 51 | fat16 file system. This is an area of risk if you move to a different compiler. 52 | 53 | I did look at emfat (see below) but decided that I wanted to pursue a different direction. In particular, fat16gen uses a python script to generate information that is similar to what emfat requires as input. Another essential difference is that the fat16gen generates static directory "files". This greatly simplified the necessary runtime and made it easier to support the rather complex issues related to long file names. 54 | 55 | ## Links 56 | 57 | * [link to fat documentation](http://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/fatgen103.doc) 58 | * [link to emfat](https://github.com/fetisov/emfat) 59 | -------------------------------------------------------------------------------- /main.cu: -------------------------------------------------------------------------------- 1 | // author bufanzhen 2 | // date 20240506 3 | // barrett reduction: 4 | // for input z(128bit),p(64bit) 5 | // output z mod p 6 | 7 | 8 | #include 9 | using namespace std; 10 | #include "cuda_runtime.h" 11 | #include "device_launch_parameters.h" 12 | #include "cuda.h" 13 | #include 14 | 15 | 16 | 17 | 18 | 19 | // compute miu = floor(b**2k/p) 20 | // __device__ void preCompute(uint32_t P[n],uint32_t miu[2]){ 21 | // return ; 22 | // } 23 | 24 | __device__ __forceinline__ void MULT(uint32_t a[],uint32_t b[],uint32_t alen,uint32_t blen,uint32_t res[]){ 25 | uint32_t reslen = alen + blen; 26 | 27 | res[reslen-1] = 0; 28 | asm("mul.lo.u32 %0, %2, %3; mul.hi.u32 %1, %2, %3;" 29 | : "=r"(res[0]), "=r"(res[1]) 30 | : "r"(a[0]), "r"(b[0])); 31 | asm("mul.lo.u32 %0, %2, %3; mul.hi.u32 %1, %2, %3;" 32 | : "=r"(res[2]), "=r"(res[3]) 33 | : "r"(a[1]), "r"(b[1])); 34 | asm("mad.lo.cc.u32 %0, %2, %3, %0; madc.hi.cc.u32 %1, %2, %3, %1;" 35 | : "+r"(res[1]), "+r"(res[2]) 36 | : "r"(a[1]), "r"(b[0])); 37 | asm("addc.u32 %0, %0, 0;" : "+r"(res[3])); 38 | asm("mad.lo.cc.u32 %0, %2, %3, %0; madc.hi.cc.u32 %1, %2, %3, %1;" 39 | : "+r"(res[1]), "+r"(res[2]) 40 | : "r"(a[0]), "r"(b[1])); 41 | asm("addc.u32 %0, %0, 0;" : "+r"(res[3])); 42 | asm("mad.lo.u32.cc %0, %2, %3, %0; madc.hi.cc.u32 %1, %2, %3, %1;" 43 | : "+r"(res[2]), "+r"(res[3]) 44 | : "r"(a[2]), "r"(b[0])); 45 | asm("addc.u32 %0, %0, 0;" : "+r"(res[4])); 46 | asm("mad.lo.cc.u32 %0, %2, %3, %0; madc.hi.u32 %1, %2, %3, %1;" 47 | : "=r"(res[3]), "+r"(res[4]) 48 | : "r"(a[2]), "r"(b[1])); 49 | return ; 50 | } 51 | 52 | 53 | __device__ __forceinline__ void computeQhat(uint32_t Z[],uint32_t miu[],uint32_t Qhat[]){ 54 | uint32_t tmpZ[3] = {0,0,0}; 55 | tmpZ[0] = Z[2]<<1|Z[1]>>31; 56 | tmpZ[1] = Z[3]<<1|Z[2]>>31; 57 | tmpZ[2] = Z[3]>>31; 58 | uint32_t tmpQhat[4] = {0,0,0,0}; 59 | asm("mul.hi.u32 %0, %1, %2;": "=r"(tmpQhat[0]): "r"(tmpZ[0]), "r"(miu[0])); 60 | asm("mul.lo.u32 %0, %2, %3; mul.hi.u32 %1, %2, %3;" 61 | : "=r"(tmpQhat[1]), "=r"(tmpQhat[2]) 62 | : "r"(tmpZ[1]), "r"(miu[1])); 63 | asm("mad.lo.cc.u32 %0, %2, %3, %0; madc.hi.cc.u32 %1, %2, %3, %1;" 64 | : "+r"(tmpQhat[0]), "+r"(tmpQhat[1]) 65 | : "r"(tmpZ[1]), "r"(miu[0])); 66 | asm("addc.cc.u32 %0, %0, 0;" : "+r"(tmpQhat[2])); 67 | asm("addc.u32 %0, %0, 0;" : "+r"(tmpQhat[3])); 68 | asm("mad.lo.cc.u32 %0, %2, %3, %0; madc.hi.cc.u32 %1, %2, %3, %1;" 69 | : "+r"(tmpQhat[0]), "+r"(tmpQhat[1]) 70 | : "r"(tmpZ[0]), "r"(miu[1])); 71 | asm("addc.cc.u32 %0, %0, 0;" : "+r"(tmpQhat[2])); 72 | asm("addc.u32 %0, %0, 0;" : "+r"(tmpQhat[3])); 73 | asm("mad.lo.u32.cc %0, %2, %3, %0; madc.lo.cc.u32 %1, %2, %4, %1;" 74 | : "+r"(tmpQhat[1]), "+r"(tmpQhat[2]) 75 | : "r"(tmpZ[2]), "r"(miu[0]), "r"(miu[1])); 76 | asm("addc.u32 %0, %0, 0;" : "+r"(tmpQhat[3])); 77 | asm("mad.lo.cc.u32 %0, %2, %3, %0; madc.lo.cc.u32 %1, %2, %4, %1;" 78 | : "+r"(tmpQhat[1]), "+r"(tmpQhat[2]) 79 | : "r"(miu[2]), "r"(tmpZ[0]), "r"(tmpZ[1])); 80 | asm("addc.u32 %0, %0, 0;" : "+r"(tmpQhat[3])); 81 | asm("mad.lo.u32 %0, %1, %2, %0;" 82 | : "+r"(tmpQhat[3]) 83 | : "r"(miu[2]), "r"(tmpZ[2])); 84 | Qhat[0] = tmpQhat[1]>>1|tmpQhat[2]<<31; 85 | Qhat[1] = tmpQhat[2]>>1|tmpQhat[3]<<31; 86 | Qhat[2] = tmpQhat[3]>>1; 87 | return ; 88 | } 89 | 90 | __device__ __forceinline__ void computeR2(uint32_t r2[], uint32_t qHat[],uint32_t p[]){ 91 | asm("mul.lo.u32 %0, %2, %3; mul.hi.u32 %1, %2, %3;" 92 | : "=r"(r2[0]), "=r"(r2[1]) 93 | : "r"(qHat[0]), "r"(p[0])); 94 | asm("mul.lo.u32 %0, %1, %2;" 95 | : "=r"(r2[2]) 96 | : "r"(qHat[1]), "r"(p[1])); 97 | asm("mad.lo.u32.cc %0, %2, %3, %0; madc.hi.u32 %1, %2, %3, %1;" 98 | : "+r"(r2[1]), "+r"(r2[2]) 99 | : "r"(qHat[1]), "r"(p[0])); 100 | asm("mad.lo.u32.cc %0, %2, %3, %0; madc.hi.u32 %1, %2, %3, %1;" 101 | : "+r"(r2[1]), "+r"(r2[2]) 102 | : "r"(qHat[0]), "r"(p[1])); 103 | asm("mul.lo.u32 %0, %1, %2;" 104 | : "+r"(r2[2]) 105 | : "r"(qHat[2]), "r"(p[0])); 106 | r2[2] = r2[2]&0x1; 107 | return ; 108 | } 109 | 110 | 111 | __device__ void BarrettRedc(uint32_t Z[],uint32_t p[],uint32_t miu[],uint32_t res[]){ 112 | // compute q_hat 113 | uint32_t qHat[3] = {0,0,0}; 114 | computeQhat(Z,miu,qHat); 115 | 116 | // compute r 117 | uint32_t r1[3] = {Z[0],Z[1],Z[2]&0x1}; 118 | uint32_t r2[3] = {0,0,0}; 119 | computeR2(r2,qHat,p); 120 | 121 | 122 | // compare R1 and R2 compute r=R1-R2 123 | // if r10)||(r1[1]>p[1])||((r1[1]==p[1])&&(r1[0]>=p[0]))){ 133 | asm("sub.cc.u32 %0, %0, %1;" : "+r"(r1[0]) : "r"(p[0])); 134 | asm("subc.cc.u32 %0, %0, %1;" : "+r"(r1[1]) : "r"(p[1])); 135 | asm("subc.cc.u32 %0, %0, 0;" : "+r"(r1[2])); 136 | } 137 | res[1] = r1[1]; 138 | res[0] = r1[0]; 139 | return ; 140 | 141 | } 142 | 143 | __global__ void func1(uint32_t Z[],uint32_t P[],uint32_t res[]){ 144 | 145 | uint32_t miu[3] = {0x708a9a6b,0xb1dbb0f0,0x1}; 146 | BarrettRedc(Z,P,miu,res); 147 | return ; 148 | } 149 | 150 | 151 | int main(){ 152 | 153 | uint32_t Plen = 64; 154 | uint32_t P[2] = {0x34f7fbb5,0x970dd129}; 155 | uint32_t Z[4] = {0xb694bf5b,0xe90cbb0e,0xf6b92885,0xde43d922}; 156 | 157 | 158 | 159 | uint32_t *d_Z,*d_P,*d_res; 160 | uint32_t *res = new uint32_t[2]; 161 | cudaMalloc((void**)&d_P , sizeof(uint32_t) * 2); 162 | cudaMalloc((void**)&d_Z , sizeof(uint32_t) * 4); 163 | cudaMalloc((void**)&d_res , sizeof(uint32_t) * 2); 164 | cudaMemcpy( d_P,P , sizeof(uint32_t) * 2, cudaMemcpyHostToDevice); 165 | cudaMemcpy( d_Z,Z , sizeof(uint32_t) * 4, cudaMemcpyHostToDevice); 166 | 167 | 168 | func1<<<1,32>>>(d_Z,d_P,d_res); 169 | 170 | 171 | cudaMemcpy( res, d_res, sizeof(uint32_t) * 2, cudaMemcpyDeviceToHost); 172 | for(int i = 0;i<2;i++){ 173 | cout< 9 | using namespace std; 10 | #include "cuda_runtime.h" 11 | #include "device_launch_parameters.h" 12 | #include "cuda.h" 13 | #include 14 | 15 | 16 | 17 | 18 | 19 | // compute miu = floor(b**2k/p) 20 | // __device__ void preCompute(uint32_t P[n],uint32_t miu[2]){ 21 | // return ; 22 | // } 23 | 24 | __device__ __forceinline__ void MULT(uint32_t a[],uint32_t b[],uint32_t alen,uint32_t blen,uint32_t res[]){ 25 | uint32_t reslen = alen + blen; 26 | 27 | res[reslen-1] = 0; 28 | asm("mul.lo.u32 %0, %2, %3; mul.hi.u32 %1, %2, %3;" 29 | : "=r"(res[0]), "=r"(res[1]) 30 | : "r"(a[0]), "r"(b[0])); 31 | asm("mul.lo.u32 %0, %2, %3; mul.hi.u32 %1, %2, %3;" 32 | : "=r"(res[2]), "=r"(res[3]) 33 | : "r"(a[1]), "r"(b[1])); 34 | asm("mad.lo.cc.u32 %0, %2, %3, %0; madc.hi.cc.u32 %1, %2, %3, %1;" 35 | : "+r"(res[1]), "+r"(res[2]) 36 | : "r"(a[1]), "r"(b[0])); 37 | asm("addc.u32 %0, %0, 0;" : "+r"(res[3])); 38 | asm("mad.lo.cc.u32 %0, %2, %3, %0; madc.hi.cc.u32 %1, %2, %3, %1;" 39 | : "+r"(res[1]), "+r"(res[2]) 40 | : "r"(a[0]), "r"(b[1])); 41 | asm("addc.u32 %0, %0, 0;" : "+r"(res[3])); 42 | asm("mad.lo.u32.cc %0, %2, %3, %0; madc.hi.cc.u32 %1, %2, %3, %1;" 43 | : "+r"(res[2]), "+r"(res[3]) 44 | : "r"(a[2]), "r"(b[0])); 45 | asm("addc.u32 %0, %0, 0;" : "+r"(res[4])); 46 | asm("mad.lo.cc.u32 %0, %2, %3, %0; madc.hi.u32 %1, %2, %3, %1;" 47 | : "=r"(res[3]), "+r"(res[4]) 48 | : "r"(a[2]), "r"(b[1])); 49 | return ; 50 | } 51 | 52 | 53 | __device__ __forceinline__ void computeQhat(uint32_t Z[],uint32_t miu[],uint32_t Qhat[]){ 54 | uint32_t tmpZ[3] = {0,0,0}; 55 | tmpZ[0] = Z[2]<<1|Z[1]>>31; 56 | tmpZ[1] = Z[3]<<1|Z[2]>>31; 57 | tmpZ[2] = Z[3]>>31; 58 | uint32_t tmpQhat[4] = {0,0,0,0}; 59 | asm("mul.hi.u32 %0, %1, %2;": "=r"(tmpQhat[0]): "r"(tmpZ[0]), "r"(miu[0])); 60 | asm("mul.lo.u32 %0, %2, %3; mul.hi.u32 %1, %2, %3;" 61 | : "=r"(tmpQhat[1]), "=r"(tmpQhat[2]) 62 | : "r"(tmpZ[1]), "r"(miu[1])); 63 | asm("mad.lo.cc.u32 %0, %2, %3, %0; madc.hi.cc.u32 %1, %2, %3, %1;" 64 | : "+r"(tmpQhat[0]), "+r"(tmpQhat[1]) 65 | : "r"(tmpZ[1]), "r"(miu[0])); 66 | asm("addc.cc.u32 %0, %0, 0;" : "+r"(tmpQhat[2])); 67 | asm("addc.u32 %0, %0, 0;" : "+r"(tmpQhat[3])); 68 | asm("mad.lo.cc.u32 %0, %2, %3, %0; madc.hi.cc.u32 %1, %2, %3, %1;" 69 | : "+r"(tmpQhat[0]), "+r"(tmpQhat[1]) 70 | : "r"(tmpZ[0]), "r"(miu[1])); 71 | asm("addc.cc.u32 %0, %0, 0;" : "+r"(tmpQhat[2])); 72 | asm("addc.u32 %0, %0, 0;" : "+r"(tmpQhat[3])); 73 | asm("mad.lo.u32.cc %0, %2, %3, %0; madc.lo.cc.u32 %1, %2, %4, %1;" 74 | : "+r"(tmpQhat[1]), "+r"(tmpQhat[2]) 75 | : "r"(tmpZ[2]), "r"(miu[0]), "r"(miu[1])); 76 | asm("addc.u32 %0, %0, 0;" : "+r"(tmpQhat[3])); 77 | asm("mad.lo.cc.u32 %0, %2, %3, %0; madc.lo.cc.u32 %1, %2, %4, %1;" 78 | : "+r"(tmpQhat[1]), "+r"(tmpQhat[2]) 79 | : "r"(miu[2]), "r"(tmpZ[0]), "r"(tmpZ[1])); 80 | asm("addc.u32 %0, %0, 0;" : "+r"(tmpQhat[3])); 81 | asm("mad.lo.u32 %0, %1, %2, %0;" 82 | : "+r"(tmpQhat[3]) 83 | : "r"(miu[2]), "r"(tmpZ[2])); 84 | Qhat[0] = tmpQhat[1]>>1|tmpQhat[2]<<31; 85 | Qhat[1] = tmpQhat[2]>>1|tmpQhat[3]<<31; 86 | Qhat[2] = tmpQhat[3]>>1; 87 | return ; 88 | } 89 | 90 | __device__ __forceinline__ void computeR2(uint32_t r2[], uint32_t qHat[],uint32_t p[]){ 91 | asm("mul.lo.u32 %0, %2, %3; mul.hi.u32 %1, %2, %3;" 92 | : "=r"(r2[0]), "=r"(r2[1]) 93 | : "r"(qHat[0]), "r"(p[0])); 94 | asm("mul.lo.u32 %0, %1, %2;" 95 | : "=r"(r2[2]) 96 | : "r"(qHat[1]), "r"(p[1])); 97 | asm("mad.lo.u32.cc %0, %2, %3, %0; madc.hi.u32 %1, %2, %3, %1;" 98 | : "+r"(r2[1]), "+r"(r2[2]) 99 | : "r"(qHat[1]), "r"(p[0])); 100 | asm("mad.lo.u32.cc %0, %2, %3, %0; madc.hi.u32 %1, %2, %3, %1;" 101 | : "+r"(r2[1]), "+r"(r2[2]) 102 | : "r"(qHat[0]), "r"(p[1])); 103 | asm("mul.lo.u32 %0, %1, %2;" 104 | : "+r"(r2[2]) 105 | : "r"(qHat[2]), "r"(p[0])); 106 | r2[2] = r2[2]&0x1; 107 | return ; 108 | } 109 | 110 | 111 | __device__ void BarrettRedc(uint32_t Z[],uint32_t p[],uint32_t miu[],uint32_t res[],uint32_t qHat[],uint32_t r[]){ 112 | // compute q_hat 113 | // uint32_t qHat[3] = {0,0,0}; 114 | computeQhat(Z,miu,qHat); 115 | 116 | // compute r 117 | uint32_t r1[3] = {Z[0],Z[1],Z[2]&0x1}; 118 | uint32_t r2[3] = {0,0,0}; 119 | computeR2(r2,qHat,p); 120 | 121 | 122 | // compare R1 and R2 compute r=R1-R2 123 | // if r10)||(r1[1]>p[1])||((r1[1]==p[1])&&(r1[0]>=p[0]))){ 137 | asm("sub.cc.u32 %0, %0, %1;" : "+r"(r1[0]) : "r"(p[0])); 138 | asm("subc.cc.u32 %0, %0, %1;" : "+r"(r1[1]) : "r"(p[1])); 139 | asm("subc.cc.u32 %0, %0, 0;" : "+r"(r1[2])); 140 | } 141 | res[1] = r1[1]; 142 | res[0] = r1[0]; 143 | return ; 144 | 145 | } 146 | 147 | __global__ void func1(uint32_t Z[],uint32_t P[],uint32_t res[],uint32_t qHat[],uint32_t r[]){ 148 | 149 | uint32_t miu[3] = {0x708a9a6b,0xb1dbb0f0,0x1}; 150 | BarrettRedc(Z,P,miu,res,qHat,r); 151 | return ; 152 | } 153 | 154 | 155 | int main(){ 156 | 157 | uint32_t Plen = 64; 158 | uint32_t n = Plen/32; 159 | uint32_t P[2] = {0x34f7fbb5,0x970dd129}; 160 | 161 | uint32_t Z[4] = {0xb694bf5b,0xe90cbb0e,0xf6b92885,0xde43d922}; 162 | 163 | uint32_t a[3] = {0x11223344,0x55667788,0x1}; 164 | uint32_t qHat[3] = {0x0,0x0,0x0}; 165 | uint32_t r[3] = {0x0,0x0,0x0}; 166 | uint32_t b[2] = {0x55ff7788,0x99aabbcc}; 167 | uint32_t *d_Z,*d_P,*d_res,*d_qHat,*d_r; 168 | uint32_t *res = new uint32_t[2]; 169 | cudaMalloc((void**)&d_P , sizeof(uint32_t) * 2); 170 | cudaMalloc((void**)&d_Z , sizeof(uint32_t) * 4); 171 | cudaMalloc((void**)&d_res , sizeof(uint32_t) * 2); 172 | cudaMalloc((void**)&d_qHat , sizeof(uint32_t) * 3); 173 | cudaMalloc((void**)&d_r , sizeof(uint32_t) * 3); 174 | cudaMemcpy( d_P,P , sizeof(uint32_t) * 2, cudaMemcpyHostToDevice); 175 | cudaMemcpy( d_Z,Z , sizeof(uint32_t) * 4, cudaMemcpyHostToDevice); 176 | func1<<<1,32>>>(d_Z,d_P,d_res,d_qHat,d_r); 177 | cudaMemcpy( res, d_res, sizeof(uint32_t) * 2, cudaMemcpyDeviceToHost); 178 | cudaMemcpy( r, d_r, sizeof(uint32_t) * 3, cudaMemcpyDeviceToHost); 179 | cudaMemcpy( qHat, d_qHat, sizeof(uint32_t) * 3, cudaMemcpyDeviceToHost); 180 | for(int i = 0;i<2;i++){ 181 | cout< 13: 11 | gen_lfn(DF,checksum,name[13:],seq+1) 12 | else: 13 | seq = seq | 0x40 14 | a = [hex(ord(x)) for x in name] 15 | if len(a) < 13: 16 | a.extend(['0x0000']) # null terminate 17 | a.extend(['0xffff']*12) # pad with 0xffff 18 | namea = ",".join(a[0:5]) 19 | nameb = ",".join(a[5:11]) 20 | namec = ",".join(a[11:13]) 21 | DF(' {.l = {0x%x, {%s}, 0xf, 0, 0x%x, {%s}, {0, 0}, {%s}}},'%(seq, namea, 22 | checksum,nameb,namec)) 23 | 24 | # 25 | # Dump Boot Record 26 | # 27 | 28 | def boot_record(DF,sectors, fat_sectors, cluster_size, root_dir_size, vname): 29 | DF('static const bootrecord br = {') 30 | DF('\t.jump_code = {0xEB,0x3C,0x90},') 31 | DF('\t.oem_name = "MSDOS5.0",') 32 | DF('\t.bytes_per_sector = BLOCKSIZE,') 33 | DF('\t.cluster_size = %d, '%(cluster_size)) 34 | DF('\t.reserved_sectors = 1,') 35 | DF('\t.fat_copies = 2,') 36 | DF('\t.max_root_dir = %d,'%((root_dir_size+31)//32)) 37 | if sectors < 64*1024: 38 | DF('\t.sectors_per_partition = %d,'%(sectors)) 39 | else: 40 | DF('\t.sectors_per_partition_large = %d,'%(sectors)) 41 | DF('\t.media_descriptor = 0xF8,') 42 | DF('\t.sectors_per_fat = %d,'%(fat_sectors)) 43 | DF('\t.logical_drive = 0x80,') 44 | DF('\t.signature = 0x29,') 45 | DF('\t.serial_number = %d,'%(time.time())) 46 | DF('\t.volume = "%-011s",'%(vname)) 47 | DF('\t.fatname = "FAT16 ",') 48 | DF('\t.marker = {0x55, 0xAA},') 49 | DF('};') 50 | 51 | # 52 | # Dump Static File 53 | # 54 | 55 | def dumpfile(DF,path,index): 56 | with open(path, 'rb') as fin: 57 | fin.seek(0,2) 58 | size = fin.tell() 59 | fin.seek(0,0) 60 | if size > 0: 61 | DF("static const uint8_t file_%d[%d] = { /* %s */"%(index,size,path)) 62 | i = 0 63 | for chunk in iter((lambda:fin.read(10)),''): 64 | DF('\t',','.join('0x%02x'%(ord(x)) for x in chunk),',') 65 | i = i + 1 66 | DF("\n};") 67 | fin.close() 68 | 69 | # 70 | # Dump Static Directory 71 | # 72 | 73 | def dirstring(name,ext,attr,epoch,clust,size): 74 | dirtmpl= " {.d=DIR_ENTRY(\"%-8s\",\"%-3s\",%d,%d,%d,%d,%d,%d,%d,%d,%d)}," 75 | tmstamp = time.gmtime(epoch) 76 | year = tmstamp.tm_year 77 | mon = tmstamp.tm_mon 78 | day = tmstamp.tm_mday 79 | hour = tmstamp.tm_hour 80 | min = tmstamp.tm_min 81 | sec = tmstamp.tm_sec // 2 82 | return dirtmpl%(name,ext,attr,year,mon,day,hour,min,sec,clust,size) 83 | 84 | def dumpdir(DF, filedict, elem, index, vname): 85 | dirsize = elem['size']//32 86 | DF("static const dir_lfn dir_%d[%d] = {/* %s */"%(index,dirsize+1,elem['fatname'].path)) 87 | if index > 0: 88 | DF(dirstring('.','', 0x11,time.time(),elem['cluster'],0)) 89 | DF(dirstring('..','',0x11,time.time(),filedict[elem['parent']]['cluster'],0)) 90 | else: 91 | DF(dirstring(vname[0:8],vname[8:11],0x8,time.time(),0,0)) 92 | for e in elem['children']: 93 | child = filedict[e] 94 | fatname = child['fatname'] 95 | path = child['fatname'].path 96 | if child['type'] == 'vfile': 97 | epoch = time.time() 98 | else: 99 | epoch = os.path.getmtime(path) 100 | if child['type'] == 'dir': 101 | attr = 0x11 102 | size = 0 103 | else: 104 | size = child['size'] 105 | attr = 0x1 106 | if fatname.needlfn(): 107 | gen_lfn(DF,fatname.checksum,fatname.longname,1) 108 | DF(dirstring(fatname.name,fatname.ext,attr,epoch,child['cluster'],size)) 109 | DF(" {.l={0}}\n};\n") 110 | 111 | # 112 | # Walk static tree and gather info 113 | # 114 | 115 | def walk_rootfs(root,filedict,shortdict): 116 | i = 0 117 | parent = [0] 118 | 119 | for dirpath, dirs, files in os.walk(root): 120 | p = parent[-1] 121 | if i == 0: 122 | p = -1 123 | filedict.append( { 124 | 'fatname' : FatName(dirpath,shortdict), 125 | 'parent' : p, 126 | 'type' : 'dir', 127 | 'children' : [] 128 | }) 129 | if i != 0: 130 | filedict[p]['children'].append(i) 131 | parent.append(i) 132 | i = i+1 133 | 134 | for file in files: 135 | pathname = os.path.join(dirpath,file) 136 | p = parent[-1] 137 | filedict.append( { 138 | 'fatname' : FatName(pathname,shortdict), 139 | 'parent' : p, 140 | 'type' : 'file', 141 | }) 142 | filedict[p]['children'].append(i) 143 | i = i+1 144 | parent.pop() 145 | 146 | # 147 | # Class to wrap parsed file system 148 | # 149 | 150 | class vFileSystem: 151 | def __init__(self,root,vfiles): 152 | self.filedict = [] 153 | self.shortdict = {} 154 | walk_rootfs(root,self.filedict,self.shortdict) 155 | for f in vfiles : 156 | dirpath = os.path.dirname(f['path']) 157 | size = f['size'] 158 | func = f['func'] 159 | operand = f['operand'] 160 | found = False 161 | for index, elem in enumerate(self.filedict): 162 | if dirpath == elem['fatname'].path: 163 | 164 | found = True 165 | break 166 | if found: 167 | this = len(self.filedict) 168 | self.filedict.append( { 169 | 'fatname' : FatName(f['path'],self.shortdict), 170 | 'parent' : index, 171 | 'type' : 'vfile', 172 | 'func' : func, 173 | 'operand' : operand, 174 | 'size' : size, 175 | }) 176 | elem['children'].append(this) 177 | 178 | else: 179 | print >> sys.stderr, "path not found vfile %s fun %s"%(dirpath,func) 180 | 181 | def sz(self,elem,index): 182 | if elem['type'] == 'dir': 183 | size = 1 184 | for f in elem['children']: 185 | size = size + 1 186 | fatname = (self.filedict[f])['fatname'] 187 | if fatname.needlfn(): 188 | nmlen = (len(fatname.longname) + 12 )// 13 189 | size = size + nmlen 190 | if index > 0: 191 | size = size + 1 192 | size = size*32 193 | elif elem['type'] == 'file': 194 | with open(elem['fatname'].path) as f: 195 | f.seek(0,2) 196 | size = f.tell() 197 | f.close() 198 | elif elem['type'] == 'vfile': 199 | size = elem['size'] 200 | return size 201 | 202 | def gensys(self,out,name,vname): 203 | def DF(*args): 204 | print >> out, " ".join(map(str,args)) 205 | 206 | cluster = 2 207 | sectors_per_cluster = 4 208 | 209 | # edit volume label 210 | 211 | vname = re.sub('^[\. ]*','',vname).upper()# strip leading dots and spaces 212 | vname = re.sub('[^\w -]',"_",vname)[0:11] # replace illegal characters 213 | 214 | # compute sizes, 215 | 216 | for index, elem in enumerate(self.filedict): 217 | elem['size'] = self.sz(elem,index) 218 | if index > 0: 219 | elem['cluster'] = cluster 220 | cluster = cluster + (elem['size'] + 512*sectors_per_cluster-1)//(512*sectors_per_cluster) 221 | else: 222 | elem['cluster'] = 0 223 | 224 | # 225 | # Generate output 226 | # 227 | 228 | DF("#include ") 229 | DF("#include \"fat.h\"\n") 230 | 231 | # 232 | # Dump directories 233 | # 234 | 235 | for index, elem in enumerate(self.filedict): 236 | if elem['type'] == 'dir': 237 | dumpdir(DF,self.filedict,elem,index,vname) 238 | 239 | # Dump files, virtual files 240 | 241 | for index,elem in enumerate(self.filedict): 242 | if elem['type'] == 'file': 243 | path = elem['fatname'].path 244 | dumpfile(DF,path,index) 245 | elif elem['type'] == 'vfile': 246 | DF("\nextern datagen_t %s;\n"%(elem['func'])) 247 | 248 | # dump boot record 249 | 250 | DF("") 251 | 252 | # compute sector and cluster counts 253 | # sectors per fat 254 | 255 | fat_sectors = 1 + cluster // 256 256 | 257 | # force this to be at least mimimum size fat 16 table 258 | 259 | if fat_sectors < 16: 260 | fat_sectors = 16 261 | rootdirlen = (self.filedict[0])['size'] 262 | 263 | # sectors in root dir 264 | 265 | rootdirsectors = (rootdirlen + 511)//512 266 | 267 | # sector of cluster 2 268 | 269 | cluster_start = 1 + rootdirsectors + 2*fat_sectors 270 | total_sectors = cluster_start + (cluster-2)*sectors_per_cluster 271 | 272 | # force minimum sectors for fat16 273 | # See "Microsoft Extensible Firmware Inititive FAT32 File System Specification" 274 | 275 | if total_sectors < 4085*4 + cluster_start: 276 | total_sectors = 4085*4 + cluster_start 277 | 278 | # generate boot record 279 | 280 | boot_record(DF,total_sectors ,fat_sectors,sectors_per_cluster, 281 | rootdirsectors*512,"volume") 282 | DF("") 283 | 284 | # dump file table 285 | 286 | DF("const vfile_t %s = {"%(name)) 287 | DF(" .blocks_per_cluster = %d,"%(sectors_per_cluster)) 288 | DF(" .maxcluster = %d,"%(cluster)) 289 | DF(" .clusterstart = %d,"%(cluster_start)) 290 | DF(" .total_sectors = %d,"%(total_sectors)) 291 | 292 | DF(" .table = {") 293 | # boot record 294 | DF("\t{0,0,512,datagen,&br},") 295 | # fat tables (2) 296 | DF("\t{1,0,%d,fat16,0},"%(fat_sectors*512)) 297 | DF("\t{%d,0,%d,fat16,0},"%(1+fat_sectors,fat_sectors*512)) 298 | # root dirctory 299 | DF("\t{%d,0,%d,datagen,dir_0},"%(1+2*fat_sectors,rootdirlen)) 300 | 301 | for index, elem in enumerate(self.filedict): 302 | elem_sector = (elem['cluster']-2)*sectors_per_cluster + cluster_start 303 | if index > 0: 304 | size = elem['size'] 305 | elem_cluster = 2+(elem_sector - cluster_start)//sectors_per_cluster 306 | if size > 0: 307 | path = elem['fatname'].path 308 | if elem['type'] == 'dir': 309 | DF("\t{%4d,%4d,%4d,datagen,dir_%d}, /* %s */"%(elem_sector, 310 | elem_cluster, 311 | size,index,path)) 312 | elif elem['type'] == 'file': 313 | DF("\t{%4d,%4d,%4d,datagen,file_%d}, /* %s */"%(elem_sector, 314 | elem_cluster, 315 | size,index,path)) 316 | else: 317 | DF("\t{%4d,%4d,%4d,%s,%s}, /* %s */"%(elem_sector, 318 | elem_cluster, 319 | size,elem['func'], elem['operand'], 320 | path)) 321 | else: 322 | size = 1 323 | DF("\t{%4d,%4d,%4d,datagen,0}, /* %s */ "%(elem_sector, 324 | elem_cluster, 325 | size,path)) 326 | 327 | 328 | DF("\t{UINT32_MAX,%d,0,0,0}\n}};"%(cluster)) 329 | 330 | if __name__ == "__main__": 331 | volume_name = 'Test Volume' # fat16 volume name 332 | table_name = 'filesys' # C name of file system table 333 | fdout = sys.stdout # output file 334 | rootdir = 'testdir' # path to root file system 335 | 336 | vfiles = [{'path' : os.path.join(rootdir,'a virtual file.txt'), 337 | 'size' : 1024, 338 | 'func' : 'vfile_1', 339 | 'operand' : '(void *) 0' 340 | } 341 | ] 342 | 343 | fs = vFileSystem(rootdir,vfiles) 344 | fs.gensys(fdout,table_name,volume_name) 345 | --------------------------------------------------------------------------------