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 }