istate.c - dedup - deduplicating backup program Err bitreich.org 70 hgit clone git://bitreich.org/dedup/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/dedup/ URL:git://bitreich.org/dedup/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/dedup/ bitreich.org 70 1Log /scm/dedup/log.gph bitreich.org 70 1Files /scm/dedup/files.gph bitreich.org 70 1Refs /scm/dedup/refs.gph bitreich.org 70 1Tags /scm/dedup/tag bitreich.org 70 1README /scm/dedup/file/README.gph bitreich.org 70 1LICENSE /scm/dedup/file/LICENSE.gph bitreich.org 70 i--- Err bitreich.org 70 istate.c (5150B) Err bitreich.org 70 i--- Err bitreich.org 70 i 1 /* Routines to read and write repository parameters */ Err bitreich.org 70 i 2 #include Err bitreich.org 70 i 3 #include Err bitreich.org 70 i 4 #include Err bitreich.org 70 i 5 #include Err bitreich.org 70 i 6 #include Err bitreich.org 70 i 7 #include Err bitreich.org 70 i 8 Err bitreich.org 70 i 9 #include Err bitreich.org 70 i 10 Err bitreich.org 70 i 11 #include "config.h" Err bitreich.org 70 i 12 #include "misc.h" Err bitreich.org 70 i 13 #include "state.h" Err bitreich.org 70 i 14 Err bitreich.org 70 i 15 #define VMIN 0 Err bitreich.org 70 i 16 #define VMAJ 1 Err bitreich.org 70 i 17 #define VMINMASK 0xff Err bitreich.org 70 i 18 #define VMAJSHIFT 8 Err bitreich.org 70 i 19 #define VMAJMASK 0xff Err bitreich.org 70 i 20 Err bitreich.org 70 i 21 #define CALGOSHIFT 16 Err bitreich.org 70 i 22 #define CALGOMASK 0x7 Err bitreich.org 70 i 23 #define CNONETYPE 0 Err bitreich.org 70 i 24 #define CSNAPPYTYPE 1 Err bitreich.org 70 i 25 #define CLZ4TYPE 2 Err bitreich.org 70 i 26 Err bitreich.org 70 i 27 #define EALGOSHIFT 19 Err bitreich.org 70 i 28 #define EALGOMASK 0x7 Err bitreich.org 70 i 29 #define ENONETYPE 0 Err bitreich.org 70 i 30 #define ECHACHATYPE 1 Err bitreich.org 70 i 31 Err bitreich.org 70 i 32 #define NONCESIZE crypto_aead_xchacha20poly1305_ietf_NPUBBYTES Err bitreich.org 70 i 33 #define MSEEDSIZE 4 Err bitreich.org 70 i 34 #define CSEEDSIZE (MSEEDSIZE + crypto_aead_xchacha20poly1305_ietf_ABYTES) Err bitreich.org 70 i 35 #define SHDRSIZE (8 + NONCESIZE + CSEEDSIZE) Err bitreich.org 70 i 36 Err bitreich.org 70 i 37 /* misc helpers */ Err bitreich.org 70 i 38 extern int pack(unsigned char *, char *, ...); Err bitreich.org 70 i 39 extern int unpack(unsigned char *, char *, ...); Err bitreich.org 70 i 40 Err bitreich.org 70 i 41 struct shdr { Err bitreich.org 70 i 42 uint64_t flags; Err bitreich.org 70 i 43 unsigned char nonce[NONCESIZE]; Err bitreich.org 70 i 44 unsigned char seed[CSEEDSIZE]; Err bitreich.org 70 i 45 }; Err bitreich.org 70 i 46 Err bitreich.org 70 i 47 /* Unpack state header */ Err bitreich.org 70 i 48 static int Err bitreich.org 70 i 49 unpackshdr(unsigned char *buf, struct shdr *shdr) Err bitreich.org 70 i 50 { Err bitreich.org 70 i 51 char fmt[BUFSIZ]; Err bitreich.org 70 i 52 int n; Err bitreich.org 70 i 53 Err bitreich.org 70 i 54 snprintf(fmt, sizeof(fmt), "q'%d'%d", NONCESIZE, CSEEDSIZE); Err bitreich.org 70 i 55 n = unpack(buf, fmt, Err bitreich.org 70 i 56 &shdr->flags, Err bitreich.org 70 i 57 shdr->nonce, Err bitreich.org 70 i 58 shdr->seed); Err bitreich.org 70 i 59 assert(n == SHDRSIZE); Err bitreich.org 70 i 60 return n; Err bitreich.org 70 i 61 } Err bitreich.org 70 i 62 Err bitreich.org 70 i 63 /* Pack state header */ Err bitreich.org 70 i 64 static int Err bitreich.org 70 i 65 packshdr(unsigned char *buf, struct shdr *shdr) Err bitreich.org 70 i 66 { Err bitreich.org 70 i 67 char fmt[BUFSIZ]; Err bitreich.org 70 i 68 int n; Err bitreich.org 70 i 69 Err bitreich.org 70 i 70 snprintf(fmt, sizeof(fmt), "q'%d'%d", NONCESIZE, CSEEDSIZE); Err bitreich.org 70 i 71 n = pack(buf, fmt, Err bitreich.org 70 i 72 shdr->flags, Err bitreich.org 70 i 73 shdr->nonce, Err bitreich.org 70 i 74 shdr->seed); Err bitreich.org 70 i 75 assert(n == SHDRSIZE); Err bitreich.org 70 i 76 return n; Err bitreich.org 70 i 77 } Err bitreich.org 70 i 78 Err bitreich.org 70 i 79 int Err bitreich.org 70 i 80 writestate(int fd, struct param *par) Err bitreich.org 70 i 81 { Err bitreich.org 70 i 82 unsigned char buf[SHDRSIZE]; Err bitreich.org 70 i 83 struct shdr shdr; Err bitreich.org 70 i 84 Err bitreich.org 70 i 85 if (sodium_init() < 0) { Err bitreich.org 70 i 86 seterr("sodium_init: failed"); Err bitreich.org 70 i 87 return -1; Err bitreich.org 70 i 88 } Err bitreich.org 70 i 89 Err bitreich.org 70 i 90 /* Set version */ Err bitreich.org 70 i 91 shdr.flags = (VMAJ << VMAJSHIFT) | VMIN; Err bitreich.org 70 i 92 Err bitreich.org 70 i 93 /* Set compression type */ Err bitreich.org 70 i 94 if (strcasecmp(par->calgo, "none") == 0) { Err bitreich.org 70 i 95 shdr.flags |= CNONETYPE << CALGOSHIFT; Err bitreich.org 70 i 96 } else if (strcasecmp(par->calgo, "snappy") == 0) { Err bitreich.org 70 i 97 shdr.flags |= CSNAPPYTYPE << CALGOSHIFT; Err bitreich.org 70 i 98 } else if (strcasecmp(par->calgo, "lz4") == 0) { Err bitreich.org 70 i 99 shdr.flags |= CLZ4TYPE << CALGOSHIFT; Err bitreich.org 70 i 100 } else { Err bitreich.org 70 i 101 seterr("invalid compression type: %s", par->calgo); Err bitreich.org 70 i 102 return -1; Err bitreich.org 70 i 103 } Err bitreich.org 70 i 104 Err bitreich.org 70 i 105 /* Clear seed + authentication tag */ Err bitreich.org 70 i 106 memset(shdr.seed, 0, sizeof(shdr.seed)); Err bitreich.org 70 i 107 Err bitreich.org 70 i 108 /* Pack seed */ Err bitreich.org 70 i 109 shdr.seed[0] = par->seed; Err bitreich.org 70 i 110 shdr.seed[1] = par->seed >> 8; Err bitreich.org 70 i 111 shdr.seed[2] = par->seed >> 16; Err bitreich.org 70 i 112 shdr.seed[3] = par->seed >> 24; Err bitreich.org 70 i 113 Err bitreich.org 70 i 114 /* Set encryption type */ Err bitreich.org 70 i 115 if (strcasecmp(par->ealgo, "none") == 0) { Err bitreich.org 70 i 116 shdr.flags |= ENONETYPE << EALGOSHIFT; Err bitreich.org 70 i 117 memset(shdr.nonce, 0, sizeof(shdr.nonce)); Err bitreich.org 70 i 118 } else if (strcasecmp(par->ealgo, "XChaCha20-Poly1305") == 0) { Err bitreich.org 70 i 119 unsigned long long elen; Err bitreich.org 70 i 120 Err bitreich.org 70 i 121 shdr.flags |= ECHACHATYPE << EALGOSHIFT; Err bitreich.org 70 i 122 randombytes_buf(shdr.nonce, sizeof(shdr.nonce)); Err bitreich.org 70 i 123 crypto_aead_xchacha20poly1305_ietf_encrypt(shdr.seed, &elen, Err bitreich.org 70 i 124 shdr.seed, MSEEDSIZE, Err bitreich.org 70 i 125 NULL, 0, NULL, Err bitreich.org 70 i 126 shdr.nonce, par->key); Err bitreich.org 70 i 127 assert(elen == CSEEDSIZE); Err bitreich.org 70 i 128 } else { Err bitreich.org 70 i 129 seterr("invalid encryption type: %s", par->ealgo); Err bitreich.org 70 i 130 return -1; Err bitreich.org 70 i 131 } Err bitreich.org 70 i 132 Err bitreich.org 70 i 133 packshdr(buf, &shdr); Err bitreich.org 70 i 134 if (xwrite(fd, buf, SHDRSIZE) != SHDRSIZE) { Err bitreich.org 70 i 135 seterr("failed to write state header: %s", strerror(errno)); Err bitreich.org 70 i 136 return -1; Err bitreich.org 70 i 137 } Err bitreich.org 70 i 138 return 0; Err bitreich.org 70 i 139 } Err bitreich.org 70 i 140 Err bitreich.org 70 i 141 int Err bitreich.org 70 i 142 readstate(int fd, struct param *par) Err bitreich.org 70 i 143 { Err bitreich.org 70 i 144 unsigned char buf[SHDRSIZE]; Err bitreich.org 70 i 145 struct shdr shdr; Err bitreich.org 70 i 146 unsigned long long dlen; Err bitreich.org 70 i 147 int algo; Err bitreich.org 70 i 148 Err bitreich.org 70 i 149 if (sodium_init() < 0) { Err bitreich.org 70 i 150 seterr("sodium_init: failed"); Err bitreich.org 70 i 151 return -1; Err bitreich.org 70 i 152 } Err bitreich.org 70 i 153 Err bitreich.org 70 i 154 if (xread(fd, buf, SHDRSIZE) != SHDRSIZE) { Err bitreich.org 70 i 155 seterr("failed to read state header: %s", strerror(errno)); Err bitreich.org 70 i 156 return -1; Err bitreich.org 70 i 157 } Err bitreich.org 70 i 158 unpackshdr(buf, &shdr); Err bitreich.org 70 i 159 Err bitreich.org 70 i 160 /* If the major version is different, the format is incompatible */ Err bitreich.org 70 i 161 if (((shdr.flags >> VMAJSHIFT) & VMAJMASK) != VMAJ) { Err bitreich.org 70 i 162 seterr("state header version mismatch"); Err bitreich.org 70 i 163 return -1; Err bitreich.org 70 i 164 } Err bitreich.org 70 i 165 Err bitreich.org 70 i 166 /* Populate param compression algo */ Err bitreich.org 70 i 167 algo = (shdr.flags >> CALGOSHIFT) & CALGOMASK; Err bitreich.org 70 i 168 switch (algo) { Err bitreich.org 70 i 169 case CNONETYPE: Err bitreich.org 70 i 170 par->calgo = "none"; Err bitreich.org 70 i 171 break; Err bitreich.org 70 i 172 case CSNAPPYTYPE: Err bitreich.org 70 i 173 par->calgo = "snappy"; Err bitreich.org 70 i 174 break; Err bitreich.org 70 i 175 case CLZ4TYPE: Err bitreich.org 70 i 176 par->calgo = "lz4"; Err bitreich.org 70 i 177 break; Err bitreich.org 70 i 178 default: Err bitreich.org 70 i 179 seterr("invalid compression type: %d", algo); Err bitreich.org 70 i 180 return -1; Err bitreich.org 70 i 181 } Err bitreich.org 70 i 182 Err bitreich.org 70 i 183 /* Populate param encryption algo */ Err bitreich.org 70 i 184 algo = (shdr.flags >> EALGOSHIFT) & EALGOMASK; Err bitreich.org 70 i 185 switch (algo) { Err bitreich.org 70 i 186 case ENONETYPE: Err bitreich.org 70 i 187 par->ealgo = "none"; Err bitreich.org 70 i 188 break; Err bitreich.org 70 i 189 case ECHACHATYPE: Err bitreich.org 70 i 190 par->ealgo = "XChaCha20-Poly1305"; Err bitreich.org 70 i 191 if (crypto_aead_xchacha20poly1305_ietf_decrypt(shdr.seed, &dlen, Err bitreich.org 70 i 192 NULL, Err bitreich.org 70 i 193 shdr.seed, CSEEDSIZE, Err bitreich.org 70 i 194 NULL, 0, Err bitreich.org 70 i 195 shdr.nonce, par->key) < 0) { Err bitreich.org 70 i 196 seterr("authentication failed"); Err bitreich.org 70 i 197 return -1; Err bitreich.org 70 i 198 } Err bitreich.org 70 i 199 assert(dlen == MSEEDSIZE); Err bitreich.org 70 i 200 break; Err bitreich.org 70 i 201 default: Err bitreich.org 70 i 202 seterr("invalid encryption type: %d", algo); Err bitreich.org 70 i 203 return -1; Err bitreich.org 70 i 204 } Err bitreich.org 70 i 205 Err bitreich.org 70 i 206 /* Unpack seed */ Err bitreich.org 70 i 207 par->seed = (uint32_t)shdr.seed[0]; Err bitreich.org 70 i 208 par->seed |= (uint32_t)shdr.seed[1] << 8; Err bitreich.org 70 i 209 par->seed |= (uint32_t)shdr.seed[2] << 16; Err bitreich.org 70 i 210 par->seed |= (uint32_t)shdr.seed[3] << 24; Err bitreich.org 70 i 211 Err bitreich.org 70 i 212 return 0; Err bitreich.org 70 i 213 } Err bitreich.org 70 .