bencrypt.c - dedup - deduplicating backup program
 (HTM) git clone git://bitreich.org/dedup/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/dedup/
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Tags
 (DIR) README
 (DIR) LICENSE
       ---
       bencrypt.c (7144B)
       ---
            1 /* Encryption layer implementation */
            2 #include <sys/types.h>
            3 #include <sys/stat.h>
            4 
            5 #include <assert.h>
            6 #include <fcntl.h>
            7 #include <stdint.h>
            8 #include <stdio.h>
            9 #include <stdlib.h>
           10 #include <string.h>
           11 #include <strings.h>
           12 #include <unistd.h>
           13 
           14 #include <sodium.h>
           15 
           16 #include "block.h"
           17 #include "config.h"
           18 #include "misc.h"
           19 #include "state.h"
           20 
           21 extern struct param param;
           22 
           23 #define EDNONETYPE        0x300
           24 #define EDCHACHATYPE        0x301
           25 #define NONCESIZE        crypto_aead_xchacha20poly1305_ietf_NPUBBYTES
           26 #define EDSIZE                (8 + 8 + NONCESIZE)
           27 
           28 extern int pack(unsigned char *, char *, ...);
           29 extern int unpack(unsigned char *, char *, ...);
           30 
           31 static int becreat(struct bctx *bctx, char *path, int mode);
           32 static int beopen(struct bctx *bctx, char *path, int flags, int mode);
           33 static int beput(struct bctx *bctx, void *buf, size_t n, unsigned char *md);
           34 static int beget(struct bctx *bctx, unsigned char *md, void *buf, size_t *n);
           35 static int berm(struct bctx *bctx, unsigned char *md);
           36 static int begc(struct bctx *bctx);
           37 static int besync(struct bctx *bctx);
           38 static int beclose(struct bctx *bctx);
           39 
           40 static struct bops bops = {
           41         .creat = becreat,
           42         .open = beopen,
           43         .put = beput,
           44         .get = beget,
           45         .rm = berm,
           46         .gc = begc,
           47         .sync = besync,
           48         .close = beclose,
           49 };
           50 
           51 /* Encryption layer context */
           52 struct ectx {
           53         int type;                /* encryption algorithm type for new blocks */
           54 };
           55 
           56 /* Encryption descriptor */
           57 struct ed {
           58         uint16_t type;                        /* encryption algorithm type */
           59         unsigned char reserved[6];        /* should be set to 0 when writing */
           60         uint64_t size;                        /* size of encrypted block */
           61         unsigned char nonce[NONCESIZE];        /* unpredictable nonce used when encrypting */
           62 };
           63 
           64 /* Unpack encryption descriptor */
           65 static int
           66 unpacked(unsigned char *buf, struct ed *ed)
           67 {
           68         char fmt[BUFSIZ];
           69         int n;
           70 
           71         snprintf(fmt, sizeof(fmt), "s'6q'%d", NONCESIZE);
           72         n = unpack(buf, fmt,
           73                    &ed->type,
           74                    ed->reserved,
           75                    &ed->size,
           76                    ed->nonce);
           77 
           78         assert(n == EDSIZE);
           79         return n;
           80 }
           81 
           82 /* Pack encryption descriptor */
           83 static int
           84 packed(unsigned char *buf, struct ed *ed)
           85 {
           86         char fmt[BUFSIZ];
           87         int n;
           88 
           89         snprintf(fmt, sizeof(fmt), "s'6q'%d", NONCESIZE);
           90         n = pack(buf, fmt,
           91                  ed->type,
           92                  ed->reserved,
           93                  ed->size,
           94                  ed->nonce);
           95 
           96         assert(n == EDSIZE);
           97         return n;
           98 }
           99 
          100 static int
          101 becreat(struct bctx *bctx, char *path, int mode)
          102 {
          103         struct ectx *ectx;
          104         int type;
          105 
          106         /* Determine algorithm type */
          107         if (strcasecmp(param.ealgo, "none") == 0) {
          108                 type = EDNONETYPE;
          109         } else if (strcasecmp(param.ealgo, "XChaCha20-Poly1305") == 0) {
          110                 type = EDCHACHATYPE;
          111         } else {
          112                 seterr("invalid encryption type: %s", param.ealgo);
          113                 return -1;
          114         }
          115 
          116         /* Ensure a key has been provided if caller requested encryption */
          117         if (type != EDNONETYPE && !param.keyloaded) {
          118                 seterr("expected encryption key");
          119                 return -1;
          120         }
          121 
          122         if (sodium_init() < 0) {
          123                 seterr("sodium_init: failed");
          124                 return -1;
          125         }
          126 
          127         bctx->ectx = calloc(1, sizeof(struct ectx));
          128         if (bctx->ectx == NULL) {
          129                 seterr("calloc: out of memory");
          130                 return -1;
          131         }
          132         ectx = bctx->ectx;
          133         ectx->type = type;
          134 
          135         if (bstorageops()->creat(bctx, path, mode) < 0) {
          136                 free(ectx);
          137                 return -1;
          138         }
          139         return 0;
          140 }
          141 
          142 static int
          143 beopen(struct bctx *bctx, char *path, int flags, int mode)
          144 {
          145         struct ectx *ectx;
          146         int type;
          147 
          148         /* Determine algorithm type */
          149         if (strcasecmp(param.ealgo, "none") == 0) {
          150                 type = EDNONETYPE;
          151         } else if (strcasecmp(param.ealgo, "XChaCha20-Poly1305") == 0) {
          152                 type = EDCHACHATYPE;
          153         } else {
          154                 seterr("invalid encryption type: %s", param.ealgo);
          155                 return -1;
          156         }
          157 
          158         /* Ensure a key has been provided if caller requested encryption */
          159         if (type != EDNONETYPE && !param.keyloaded) {
          160                 seterr("expected encryption key");
          161                 return -1;
          162         }
          163 
          164         if (sodium_init() < 0) {
          165                 seterr("sodium_init: failed");
          166                 return -1;
          167         }
          168 
          169         bctx->ectx = calloc(1, sizeof(struct ectx));
          170         if (bctx->ectx == NULL) {
          171                 seterr("calloc: out of memory");
          172                 return -1;
          173         }
          174         ectx = bctx->ectx;
          175         ectx->type = type;
          176 
          177         if (bstorageops()->open(bctx, path, flags, mode) < 0) {
          178                 free(ectx);
          179                 return -1;
          180         }
          181         return 0;
          182 }
          183 
          184 static int
          185 beput(struct bctx *bctx, void *buf, size_t n, unsigned char *md)
          186 {
          187         struct ectx *ectx;
          188         struct ed ed;
          189         unsigned char *ebuf;
          190         unsigned long long elen;
          191         size_t en;
          192 
          193         /* Calculate size of encrypted block */
          194         ectx = bctx->ectx;
          195         switch (ectx->type) {
          196         case EDNONETYPE:
          197                 en = n;
          198                 break;
          199         case EDCHACHATYPE:
          200                 en = n + crypto_aead_xchacha20poly1305_ietf_ABYTES;
          201                 break;
          202         }
          203 
          204         ebuf = malloc(EDSIZE + en);
          205         if (ebuf == NULL) {
          206                 seterr("malloc: out of memory");
          207                 return -1;
          208         }
          209 
          210         /* Prepare encryption descriptor */
          211         ed.type = ectx->type;
          212         memset(ed.reserved, 0, sizeof(ed.reserved));
          213         ed.size = en;
          214 
          215         /* Fill nonce buffer */
          216         switch (ectx->type) {
          217         case EDNONETYPE:
          218                 memset(ed.nonce, 0, sizeof(ed.nonce));
          219                 break;
          220         case EDCHACHATYPE:
          221                 randombytes_buf(ed.nonce, sizeof(ed.nonce));
          222                 break;
          223         }
          224 
          225         /* Prepend encryption descriptor */
          226         packed(ebuf, &ed);
          227 
          228         /* Encrypt block */
          229         switch (ectx->type) {
          230         case EDNONETYPE:
          231                 memcpy(&ebuf[EDSIZE], buf, en);
          232                 break;
          233         case EDCHACHATYPE:
          234                 crypto_aead_xchacha20poly1305_ietf_encrypt(&ebuf[EDSIZE], &elen,
          235                                                            buf, n, ebuf, EDSIZE, NULL,
          236                                                            ed.nonce, param.key);
          237                 assert(elen == en);
          238                 break;
          239         }
          240 
          241         if (bstorageops()->put(bctx, ebuf, EDSIZE + en, md) < 0) {
          242                 free(ebuf);
          243                 return -1;
          244         }
          245 
          246         free(ebuf);
          247         return ed.size;
          248 }
          249 
          250 static int
          251 beget(struct bctx *bctx, unsigned char *md, void *buf, size_t *n)
          252 {
          253         struct ed ed;
          254         struct ectx *ectx;
          255         unsigned char *ebuf;
          256         unsigned long long dlen;
          257         size_t dn, size;
          258 
          259         /* Calculate maximum size of encrypted block */
          260         size = EDSIZE + *n + crypto_aead_xchacha20poly1305_ietf_ABYTES;
          261 
          262         ebuf = malloc(size);
          263         if (ebuf == NULL) {
          264                 seterr("malloc: out of memory");
          265                 return -1;
          266         }
          267 
          268         if (bstorageops()->get(bctx, md, ebuf, &size) < 0) {
          269                 free(ebuf);
          270                 return -1;
          271         }
          272 
          273         unpacked(ebuf, &ed);
          274 
          275         /* Decrypt block */
          276         ectx = bctx->ectx;
          277         switch (ed.type) {
          278         case EDNONETYPE:
          279                 dn = ed.size;
          280                 if (*n < dn) {
          281                         free(ebuf);
          282                         seterr("buffer too small");
          283                         return -1;
          284                 }
          285                 memcpy(buf, &ebuf[EDSIZE], dn);
          286                 break;
          287         case EDCHACHATYPE:
          288                 dn = ed.size - crypto_aead_xchacha20poly1305_ietf_ABYTES;
          289                 if (*n < dn) {
          290                         free(ebuf);
          291                         seterr("buffer too small");
          292                         return -1;
          293                 }
          294 
          295                 if (crypto_aead_xchacha20poly1305_ietf_decrypt(buf, &dlen,
          296                                                                NULL,
          297                                                                &ebuf[EDSIZE], ed.size,
          298                                                                ebuf, EDSIZE,
          299                                                                ed.nonce, param.key) < 0) {
          300                         free(ebuf);
          301                         seterr("authentication failed");
          302                         return -1;
          303                 }
          304 
          305                 assert(dn == dlen);
          306                 break;
          307         }
          308 
          309         free(ebuf);
          310         *n = dn;
          311         return 0;
          312 }
          313 
          314 static int
          315 berm(struct bctx *bctx, unsigned char *md)
          316 {
          317         return bstorageops()->rm(bctx, md);
          318 }
          319 
          320 static int
          321 begc(struct bctx *bctx)
          322 {
          323         return bstorageops()->gc(bctx);
          324 }
          325 
          326 static int
          327 besync(struct bctx *bctx)
          328 {
          329         return bstorageops()->sync(bctx);
          330 }
          331 
          332 static int
          333 beclose(struct bctx *bctx)
          334 {
          335         struct ectx *ectx = bctx->ectx;
          336 
          337         free(ectx);
          338         return bstorageops()->close(bctx);
          339 }
          340 
          341 struct bops *
          342 bencryptops(void)
          343 {
          344         return &bops;
          345 }