Return to ccm_aead.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / ccm |
1.1 misho 1: /* 2: * Copyright (C) 2010 Martin Willi 3: * Copyright (C) 2010 revosec AG 4: * 5: * This program is free software; you can redistribute it and/or modify it 6: * under the terms of the GNU General Public License as published by the 7: * Free Software Foundation; either version 2 of the License, or (at your 8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. 9: * 10: * This program is distributed in the hope that it will be useful, but 11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13: * for more details. 14: */ 15: 16: #include "ccm_aead.h" 17: 18: #include <crypto/iv/iv_gen_seq.h> 19: 20: #define BLOCK_SIZE 16 21: #define SALT_SIZE 3 22: #define IV_SIZE 8 23: #define NONCE_SIZE (SALT_SIZE + IV_SIZE) /* 11 */ 24: #define Q_SIZE (BLOCK_SIZE - NONCE_SIZE - 1) /* 4 */ 25: 26: typedef struct private_ccm_aead_t private_ccm_aead_t; 27: 28: /** 29: * Private data of an ccm_aead_t object. 30: */ 31: struct private_ccm_aead_t { 32: 33: /** 34: * Public ccm_aead_t interface. 35: */ 36: ccm_aead_t public; 37: 38: /** 39: * Underlying CBC crypter. 40: */ 41: crypter_t *crypter; 42: 43: /** 44: * IV generator. 45: */ 46: iv_gen_t *iv_gen; 47: 48: /** 49: * Length of the integrity check value 50: */ 51: size_t icv_size; 52: 53: /** 54: * salt to add to nonce 55: */ 56: u_char salt[SALT_SIZE]; 57: }; 58: 59: /** 60: * First block with control information 61: */ 62: typedef struct __attribute__((packed)) { 63: BITFIELD4(uint8_t, 64: /* size of p length field q, as q-1 */ 65: q_len: 3, 66: /* size of our ICV t, as (t-2)/2 */ 67: t_len: 3, 68: /* do we have associated data */ 69: assoc: 1, 70: reserved: 1, 71: ) flags; 72: /* nonce value */ 73: struct __attribute__((packed)) { 74: u_char salt[SALT_SIZE]; 75: u_char iv[IV_SIZE]; 76: } nonce; 77: /* length of plain text, q */ 78: u_char q[Q_SIZE]; 79: } b0_t; 80: 81: /** 82: * Counter block 83: */ 84: typedef struct __attribute__((packed)) { 85: BITFIELD3(uint8_t, 86: /* size of p length field q, as q-1 */ 87: q_len: 3, 88: zero: 3, 89: reserved: 2, 90: ) flags; 91: /* nonce value */ 92: struct __attribute__((packed)) { 93: u_char salt[SALT_SIZE]; 94: u_char iv[IV_SIZE]; 95: } nonce; 96: /* counter value */ 97: u_char i[Q_SIZE]; 98: } ctr_t; 99: 100: /** 101: * Build the first block B0 102: */ 103: static void build_b0(private_ccm_aead_t *this, chunk_t plain, chunk_t assoc, 104: chunk_t iv, char *out) 105: { 106: b0_t *block = (b0_t*)out; 107: 108: block->flags.reserved = 0; 109: block->flags.assoc = assoc.len ? 1 : 0; 110: block->flags.t_len = (this->icv_size - 2) / 2; 111: block->flags.q_len = Q_SIZE - 1; 112: memcpy(block->nonce.salt, this->salt, SALT_SIZE); 113: memcpy(block->nonce.iv, iv.ptr, IV_SIZE); 114: htoun32(block->q, plain.len); 115: } 116: 117: /** 118: * Build a counter block for counter i 119: */ 120: static void build_ctr(private_ccm_aead_t *this, uint32_t i, chunk_t iv, 121: char *out) 122: { 123: ctr_t *ctr = (ctr_t*)out; 124: 125: ctr->flags.reserved = 0; 126: ctr->flags.zero = 0; 127: ctr->flags.q_len = Q_SIZE - 1; 128: memcpy(ctr->nonce.salt, this->salt, SALT_SIZE); 129: memcpy(ctr->nonce.iv, iv.ptr, IV_SIZE); 130: htoun32(ctr->i, i); 131: } 132: 133: /** 134: * En-/Decrypt data 135: */ 136: static bool crypt_data(private_ccm_aead_t *this, chunk_t iv, 137: chunk_t in, chunk_t out) 138: { 139: char ctr[BLOCK_SIZE]; 140: char zero[BLOCK_SIZE]; 141: char block[BLOCK_SIZE]; 142: 143: build_ctr(this, 1, iv, ctr); 144: memset(zero, 0, BLOCK_SIZE); 145: 146: while (in.len > 0) 147: { 148: memcpy(block, ctr, BLOCK_SIZE); 149: if (!this->crypter->encrypt(this->crypter, chunk_from_thing(block), 150: chunk_from_thing(zero), NULL)) 151: { 152: return FALSE; 153: } 154: chunk_increment(chunk_from_thing(ctr)); 155: 156: if (in.ptr != out.ptr) 157: { 158: memcpy(out.ptr, in.ptr, min(in.len, BLOCK_SIZE)); 159: } 160: memxor(out.ptr, block, min(in.len, BLOCK_SIZE)); 161: in = chunk_skip(in, BLOCK_SIZE); 162: out = chunk_skip(out, BLOCK_SIZE); 163: } 164: return TRUE; 165: } 166: 167: /** 168: * En-/Decrypt the ICV 169: */ 170: static bool crypt_icv(private_ccm_aead_t *this, chunk_t iv, char *icv) 171: { 172: char ctr[BLOCK_SIZE]; 173: char zero[BLOCK_SIZE]; 174: 175: build_ctr(this, 0, iv, ctr); 176: memset(zero, 0, BLOCK_SIZE); 177: 178: if (!this->crypter->encrypt(this->crypter, chunk_from_thing(ctr), 179: chunk_from_thing(zero), NULL)) 180: { 181: return FALSE; 182: } 183: memxor(icv, ctr, this->icv_size); 184: return TRUE; 185: } 186: 187: /** 188: * Create the ICV 189: */ 190: static bool create_icv(private_ccm_aead_t *this, chunk_t plain, chunk_t assoc, 191: chunk_t iv, char *icv) 192: { 193: char zero[BLOCK_SIZE]; 194: chunk_t chunk; 195: char *pos; 196: int r, len; 197: 198: memset(zero, 0, BLOCK_SIZE); 199: 200: /* calculate number of blocks, including b0 */ 201: r = 1; 202: if (assoc.len) 203: { /* assoc gets a 2 byte length header, gets padded to BLOCK_SIZE */ 204: r += (2 + assoc.len + BLOCK_SIZE - 1) / BLOCK_SIZE; 205: } 206: /* plain text gets padded to BLOCK_SIZE */ 207: r += (plain.len + BLOCK_SIZE - 1) / BLOCK_SIZE; 208: 209: /* concatenate data to a new chunk */ 210: chunk = chunk_alloc(r * BLOCK_SIZE); 211: /* write control block */ 212: build_b0(this, plain, assoc, iv, chunk.ptr); 213: pos = chunk.ptr + BLOCK_SIZE; 214: /* append associated data, with length header */ 215: if (assoc.len) 216: { 217: /* currently we support two byte headers only (up to 2^16-2^8 bytes) */ 218: htoun16(pos, assoc.len); 219: memcpy(pos + 2, assoc.ptr, assoc.len); 220: pos += 2 + assoc.len; 221: /* padding */ 222: len = (BLOCK_SIZE - ((2 + assoc.len) % BLOCK_SIZE)) % BLOCK_SIZE; 223: memset(pos, 0, len); 224: pos += len; 225: } 226: /* write plain data */ 227: memcpy(pos, plain.ptr, plain.len); 228: pos += plain.len; 229: /* padding */ 230: len = (BLOCK_SIZE - (plain.len % BLOCK_SIZE)) % BLOCK_SIZE; 231: 232: memset(pos, 0, len); 233: 234: /* encrypt inline with CBC, zero IV */ 235: if (!this->crypter->encrypt(this->crypter, chunk, 236: chunk_from_thing(zero), NULL)) 237: { 238: free(chunk.ptr); 239: return FALSE; 240: } 241: /* copy last icv_size bytes as ICV to output */ 242: memcpy(icv, chunk.ptr + chunk.len - BLOCK_SIZE, this->icv_size); 243: 244: free(chunk.ptr); 245: 246: /* encrypt the ICV value */ 247: return crypt_icv(this, iv, icv); 248: } 249: 250: /** 251: * Verify the ICV 252: */ 253: static bool verify_icv(private_ccm_aead_t *this, chunk_t plain, chunk_t assoc, 254: chunk_t iv, char *icv) 255: { 256: char buf[this->icv_size]; 257: 258: return create_icv(this, plain, assoc, iv, buf) && 259: memeq_const(buf, icv, this->icv_size); 260: } 261: 262: METHOD(aead_t, encrypt, bool, 263: private_ccm_aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv, 264: chunk_t *encrypted) 265: { 266: if (encrypted) 267: { 268: *encrypted = chunk_alloc(plain.len + this->icv_size); 269: return create_icv(this, plain, assoc, iv, encrypted->ptr + plain.len) && 270: crypt_data(this, iv, plain, *encrypted); 271: } 272: return create_icv(this, plain, assoc, iv, plain.ptr + plain.len) && 273: crypt_data(this, iv, plain, plain); 274: } 275: 276: METHOD(aead_t, decrypt, bool, 277: private_ccm_aead_t *this, chunk_t encrypted, chunk_t assoc, chunk_t iv, 278: chunk_t *plain) 279: { 280: if (encrypted.len < this->icv_size) 281: { 282: return FALSE; 283: } 284: encrypted.len -= this->icv_size; 285: if (plain) 286: { 287: *plain = chunk_alloc(encrypted.len); 288: return crypt_data(this, iv, encrypted, *plain) && 289: verify_icv(this, *plain, assoc, iv, 290: encrypted.ptr + encrypted.len); 291: } 292: return crypt_data(this, iv, encrypted, encrypted) && 293: verify_icv(this, encrypted, assoc, iv, 294: encrypted.ptr + encrypted.len); 295: } 296: 297: METHOD(aead_t, get_block_size, size_t, 298: private_ccm_aead_t *this) 299: { 300: return 1; 301: } 302: 303: METHOD(aead_t, get_icv_size, size_t, 304: private_ccm_aead_t *this) 305: { 306: return this->icv_size; 307: } 308: 309: METHOD(aead_t, get_iv_size, size_t, 310: private_ccm_aead_t *this) 311: { 312: return IV_SIZE; 313: } 314: 315: METHOD(aead_t, get_iv_gen, iv_gen_t*, 316: private_ccm_aead_t *this) 317: { 318: return this->iv_gen; 319: } 320: 321: METHOD(aead_t, get_key_size, size_t, 322: private_ccm_aead_t *this) 323: { 324: return this->crypter->get_key_size(this->crypter) + SALT_SIZE; 325: } 326: 327: METHOD(aead_t, set_key, bool, 328: private_ccm_aead_t *this, chunk_t key) 329: { 330: memcpy(this->salt, key.ptr + key.len - SALT_SIZE, SALT_SIZE); 331: key.len -= SALT_SIZE; 332: return this->crypter->set_key(this->crypter, key); 333: } 334: 335: METHOD(aead_t, destroy, void, 336: private_ccm_aead_t *this) 337: { 338: this->crypter->destroy(this->crypter); 339: this->iv_gen->destroy(this->iv_gen); 340: free(this); 341: } 342: 343: /** 344: * See header 345: */ 346: ccm_aead_t *ccm_aead_create(encryption_algorithm_t algo, 347: size_t key_size, size_t salt_size) 348: { 349: private_ccm_aead_t *this; 350: size_t icv_size; 351: 352: switch (key_size) 353: { 354: case 0: 355: key_size = 16; 356: break; 357: case 16: 358: case 24: 359: case 32: 360: break; 361: default: 362: return NULL; 363: } 364: if (salt_size && salt_size != SALT_SIZE) 365: { 366: /* currently not supported */ 367: return NULL; 368: } 369: switch (algo) 370: { 371: case ENCR_AES_CCM_ICV8: 372: algo = ENCR_AES_CBC; 373: icv_size = 8; 374: break; 375: case ENCR_AES_CCM_ICV12: 376: algo = ENCR_AES_CBC; 377: icv_size = 12; 378: break; 379: case ENCR_AES_CCM_ICV16: 380: algo = ENCR_AES_CBC; 381: icv_size = 16; 382: break; 383: case ENCR_CAMELLIA_CCM_ICV8: 384: algo = ENCR_CAMELLIA_CBC; 385: icv_size = 8; 386: break; 387: case ENCR_CAMELLIA_CCM_ICV12: 388: algo = ENCR_CAMELLIA_CBC; 389: icv_size = 12; 390: break; 391: case ENCR_CAMELLIA_CCM_ICV16: 392: algo = ENCR_CAMELLIA_CBC; 393: icv_size = 16; 394: break; 395: default: 396: return NULL; 397: } 398: 399: INIT(this, 400: .public = { 401: .aead = { 402: .encrypt = _encrypt, 403: .decrypt = _decrypt, 404: .get_block_size = _get_block_size, 405: .get_icv_size = _get_icv_size, 406: .get_iv_size = _get_iv_size, 407: .get_iv_gen = _get_iv_gen, 408: .get_key_size = _get_key_size, 409: .set_key = _set_key, 410: .destroy = _destroy, 411: }, 412: }, 413: .crypter = lib->crypto->create_crypter(lib->crypto, algo, key_size), 414: .iv_gen = iv_gen_seq_create(), 415: .icv_size = icv_size, 416: ); 417: 418: if (!this->crypter) 419: { 420: free(this); 421: return NULL; 422: } 423: 424: return &this->public; 425: }