1 /* 2 * Copyright (C) 2008, Damien Miller 3 * Copyright (C) 2011, Alex Hornung 4 * 5 * Permission to use, copy, and modify this software with or without fee 6 * is hereby granted, provided that this entire notice is included in 7 * all copies of any software which is or includes a copy or 8 * modification of this software. 9 * You may use this code under the GNU public license if you so wish. Please 10 * contribute changes back to the authors under this freer than GPL license 11 * so that we may further the use of strong encryption without limitations to 12 * all. 13 * 14 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR 15 * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY 16 * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE 17 * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR 18 * PURPOSE. 19 */ 20 21 #include <stdio.h> 22 #include <string.h> 23 #include <stdlib.h> 24 #include <unistd.h> 25 #include <inttypes.h> 26 27 #include "tcplay.h" 28 #include "generic_xts.h" 29 30 31 32 static int 33 xts_reinit(struct xts_ctx *ctx, u_int64_t blocknum) 34 { 35 u_int i; 36 37 /* 38 * Prepare tweak as E_k2(IV). IV is specified as LE representation 39 * of a 64-bit block number which we allow to be passed in directly. 40 */ 41 for (i = 0; i < XTS_IVSIZE; i++) { 42 ctx->tweak[i] = blocknum & 0xff; 43 blocknum >>= 8; 44 } 45 /* Last 64 bits of IV are always zero */ 46 bzero(ctx->tweak + XTS_IVSIZE, XTS_IVSIZE); 47 48 return ctx->encrypt_fn(ctx->ctx2, ctx->blk_sz, ctx->tweak, ctx->tweak); 49 } 50 51 static int 52 xts_crypt(struct xts_ctx *ctx, u_int8_t *data, u_int do_encrypt) 53 { 54 u_int8_t block[XTS_MAX_BLOCKSIZE]; 55 u_int i, carry_in, carry_out; 56 int err; 57 58 for (i = 0; i < ctx->blk_sz; i++) 59 block[i] = data[i] ^ ctx->tweak[i]; 60 61 if (do_encrypt) 62 err = ctx->encrypt_fn(ctx->ctx1, ctx->blk_sz, block, data); 63 else 64 err = ctx->decrypt_fn(ctx->ctx1, ctx->blk_sz, block, data); 65 66 if (err) 67 goto out; 68 69 for (i = 0; i < ctx->blk_sz; i++) 70 data[i] ^= ctx->tweak[i]; 71 72 /* Exponentiate tweak */ 73 carry_in = 0; 74 for (i = 0; i < ctx->blk_sz; i++) { 75 carry_out = ctx->tweak[i] & 0x80; 76 ctx->tweak[i] = (ctx->tweak[i] << 1) | (carry_in ? 1 : 0); 77 carry_in = carry_out; 78 } 79 if (carry_in) 80 ctx->tweak[0] ^= XTS_ALPHA; 81 82 out: 83 bzero(block, sizeof(block)); 84 return err; 85 } 86 87 int 88 xts_init(struct xts_ctx *ctx, void *arg1, void *arg2, set_key_fn _set_key_fn, 89 zero_key_fn _zero_key_fn, encrypt_decrypt_fn _encrypt_fn, 90 encrypt_decrypt_fn _decrypt_fn, u_int blk_sz, u_int8_t *key, int len) 91 { 92 int err; 93 94 if (len != 32 && len != 64) 95 return -1; 96 97 ctx->blk_sz = blk_sz; 98 ctx->encrypt_fn = _encrypt_fn; 99 ctx->decrypt_fn = _decrypt_fn; 100 ctx->set_key_fn = _set_key_fn; 101 ctx->zero_key_fn = _zero_key_fn; 102 103 err = ctx->set_key_fn(&ctx->ctx1, arg1, arg2, key, len * 4); 104 if (err) 105 return -1; 106 107 err = ctx->set_key_fn(&ctx->ctx2, arg1, arg2, key + (len / 2), 108 len * 4); 109 if (err) { 110 ctx->zero_key_fn(&ctx->ctx1); 111 return -1; 112 } 113 114 return 0; 115 } 116 117 int 118 xts_encrypt(struct xts_ctx *ctx, u_int8_t *data, size_t len, uint8_t *iv) 119 { 120 uint64_t sector = *((uint64_t *)iv); 121 int err; 122 123 if ((len % ctx->blk_sz) != 0) 124 return -1; 125 126 err = xts_reinit(ctx, sector); 127 if (err) 128 return err; 129 130 while (len > 0) { 131 err = xts_crypt(ctx, data, 1); 132 if (err) 133 return -1; 134 135 data += ctx->blk_sz; 136 len -= ctx->blk_sz; 137 } 138 139 return err; 140 } 141 142 int 143 xts_decrypt(struct xts_ctx *ctx, u_int8_t *data, size_t len, uint8_t *iv) 144 { 145 uint64_t sector = *((uint64_t *)iv); 146 int err; 147 148 if ((len % ctx->blk_sz) != 0) 149 return -1; 150 151 err = xts_reinit(ctx, sector); 152 if (err) 153 return err; 154 155 while (len > 0) { 156 err = xts_crypt(ctx, data, 0); 157 if (err) 158 return -1; 159 160 data += ctx->blk_sz; 161 len -= ctx->blk_sz; 162 } 163 164 return err; 165 } 166 167 int 168 xts_uninit(struct xts_ctx *ctx) 169 { 170 ctx->zero_key_fn(&ctx->ctx1); 171 ctx->zero_key_fn(&ctx->ctx2); 172 173 return 0; 174 } 175 176