Return to xcbc.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / xcbc |
1.1 misho 1: /* 2: * Copyright (C) 2012 Tobias Brunner 3: * Copyright (C) 2008 Martin Willi 4: * HSR Hochschule fuer Technik Rapperswil 5: * 6: * This program is free software; you can redistribute it and/or modify it 7: * under the terms of the GNU General Public License as published by the 8: * Free Software Foundation; either version 2 of the License, or (at your 9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. 10: * 11: * This program is distributed in the hope that it will be useful, but 12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14: * for more details. 15: */ 16: 17: #include <string.h> 18: 19: #include "xcbc.h" 20: 21: #include <utils/debug.h> 22: #include <crypto/mac.h> 23: #include <crypto/prfs/mac_prf.h> 24: #include <crypto/signers/mac_signer.h> 25: 26: typedef struct private_mac_t private_mac_t; 27: 28: /** 29: * Private data of a mac_t object. 30: * 31: * The variable names are the same as in the RFC. 32: */ 33: struct private_mac_t { 34: 35: /** 36: * Public mac_t interface. 37: */ 38: mac_t public; 39: 40: /** 41: * Block size, in bytes 42: */ 43: uint8_t b; 44: 45: /** 46: * crypter using k1 47: */ 48: crypter_t *k1; 49: 50: /** 51: * k2 52: */ 53: uint8_t *k2; 54: 55: /** 56: * k3 57: */ 58: uint8_t *k3; 59: 60: /** 61: * E 62: */ 63: uint8_t *e; 64: 65: /** 66: * remaining, unprocessed bytes in append mode 67: */ 68: uint8_t *remaining; 69: 70: /** 71: * number of bytes in remaining 72: */ 73: int remaining_bytes; 74: 75: /** 76: * TRUE if we have zero bytes to xcbc in final() 77: */ 78: bool zero; 79: }; 80: 81: /** 82: * xcbc supplied data, but do not run final operation 83: */ 84: static bool update(private_mac_t *this, chunk_t data) 85: { 86: chunk_t iv; 87: 88: if (data.len) 89: { 90: this->zero = FALSE; 91: } 92: 93: if (this->remaining_bytes + data.len <= this->b) 94: { /* no complete block, just copy into remaining */ 95: memcpy(this->remaining + this->remaining_bytes, data.ptr, data.len); 96: this->remaining_bytes += data.len; 97: return TRUE; 98: } 99: 100: iv = chunk_alloca(this->b); 101: memset(iv.ptr, 0, iv.len); 102: 103: /* (3) For each block M[i], where i = 1 ... n-1: 104: * XOR M[i] with E[i-1], then encrypt the result with Key K1, 105: * yielding E[i]. 106: */ 107: 108: /* append data to remaining bytes, process block M[1] */ 109: memcpy(this->remaining + this->remaining_bytes, data.ptr, 110: this->b - this->remaining_bytes); 111: data = chunk_skip(data, this->b - this->remaining_bytes); 112: memxor(this->e, this->remaining, this->b); 113: if (!this->k1->encrypt(this->k1, chunk_create(this->e, this->b), iv, NULL)) 114: { 115: return FALSE; 116: } 117: 118: /* process blocks M[2] ... M[n-1] */ 119: while (data.len > this->b) 120: { 121: memcpy(this->remaining, data.ptr, this->b); 122: data = chunk_skip(data, this->b); 123: memxor(this->e, this->remaining, this->b); 124: if (!this->k1->encrypt(this->k1, chunk_create(this->e, this->b), 125: iv, NULL)) 126: { 127: return FALSE; 128: } 129: } 130: 131: /* store remaining bytes of block M[n] */ 132: memcpy(this->remaining, data.ptr, data.len); 133: this->remaining_bytes = data.len; 134: 135: return TRUE; 136: } 137: 138: /** 139: * run last round, data is in this->e 140: */ 141: static bool final(private_mac_t *this, uint8_t *out) 142: { 143: chunk_t iv; 144: 145: iv = chunk_alloca(this->b); 146: memset(iv.ptr, 0, iv.len); 147: 148: /* (4) For block M[n]: */ 149: if (this->remaining_bytes == this->b && !this->zero) 150: { 151: /* a) If the blocksize of M[n] is 128 bits: 152: * XOR M[n] with E[n-1] and Key K2, then encrypt the result with 153: * Key K1, yielding E[n]. 154: */ 155: memxor(this->e, this->remaining, this->b); 156: memxor(this->e, this->k2, this->b); 157: } 158: else 159: { 160: /* b) If the blocksize of M[n] is less than 128 bits: 161: * 162: * i) Pad M[n] with a single "1" bit, followed by the number of 163: * "0" bits (possibly none) required to increase M[n]'s 164: * blocksize to 128 bits. 165: */ 166: if (this->remaining_bytes < this->b) 167: { 168: this->remaining[this->remaining_bytes] = 0x80; 169: while (++this->remaining_bytes < this->b) 170: { 171: this->remaining[this->remaining_bytes] = 0x00; 172: } 173: } 174: /* ii) XOR M[n] with E[n-1] and Key K3, then encrypt the result 175: * with Key K1, yielding E[n]. 176: */ 177: memxor(this->e, this->remaining, this->b); 178: memxor(this->e, this->k3, this->b); 179: } 180: if (!this->k1->encrypt(this->k1, chunk_create(this->e, this->b), iv, NULL)) 181: { 182: return FALSE; 183: } 184: 185: memcpy(out, this->e, this->b); 186: 187: /* (2) Define E[0] = 0x00000000000000000000000000000000 */ 188: memset(this->e, 0, this->b); 189: this->remaining_bytes = 0; 190: this->zero = TRUE; 191: 192: return TRUE; 193: } 194: 195: METHOD(mac_t, get_mac, bool, 196: private_mac_t *this, chunk_t data, uint8_t *out) 197: { 198: /* update E, do not process last block */ 199: if (!update(this, data)) 200: { 201: return FALSE; 202: } 203: 204: if (out) 205: { /* if not in append mode, process last block and output result */ 206: return final(this, out); 207: } 208: return TRUE; 209: } 210: 211: METHOD(mac_t, get_mac_size, size_t, 212: private_mac_t *this) 213: { 214: return this->b; 215: } 216: 217: METHOD(mac_t, set_key, bool, 218: private_mac_t *this, chunk_t key) 219: { 220: chunk_t iv, k1, lengthened; 221: 222: memset(this->e, 0, this->b); 223: this->remaining_bytes = 0; 224: this->zero = TRUE; 225: 226: /* we support variable keys from RFC4434 */ 227: if (key.len == this->b) 228: { 229: lengthened = key; 230: } 231: else if (key.len < this->b) 232: { /* pad short keys */ 233: lengthened = chunk_alloca(this->b); 234: memset(lengthened.ptr, 0, lengthened.len); 235: memcpy(lengthened.ptr, key.ptr, key.len); 236: } 237: else 238: { /* shorten key using xcbc */ 239: lengthened = chunk_alloca(this->b); 240: memset(lengthened.ptr, 0, lengthened.len); 241: if (!set_key(this, lengthened) || 242: !get_mac(this, key, lengthened.ptr)) 243: { 244: return FALSE; 245: } 246: } 247: 248: k1 = chunk_alloca(this->b); 249: iv = chunk_alloca(this->b); 250: memset(iv.ptr, 0, iv.len); 251: 252: /* 253: * (1) Derive 3 128-bit keys (K1, K2 and K3) from the 128-bit secret 254: * key K, as follows: 255: * K1 = 0x01010101010101010101010101010101 encrypted with Key K 256: * K2 = 0x02020202020202020202020202020202 encrypted with Key K 257: * K3 = 0x03030303030303030303030303030303 encrypted with Key K 258: */ 259: 260: memset(k1.ptr, 0x01, this->b); 261: memset(this->k2, 0x02, this->b); 262: memset(this->k3, 0x03, this->b); 263: 264: if (!this->k1->set_key(this->k1, lengthened) || 265: !this->k1->encrypt(this->k1, chunk_create(this->k2, this->b), iv, NULL) || 266: !this->k1->encrypt(this->k1, chunk_create(this->k3, this->b), iv, NULL) || 267: !this->k1->encrypt(this->k1, k1, iv, NULL) || 268: !this->k1->set_key(this->k1, k1)) 269: { 270: memwipe(k1.ptr, k1.len); 271: return FALSE; 272: } 273: memwipe(k1.ptr, k1.len); 274: return TRUE; 275: } 276: 277: METHOD(mac_t, destroy, void, 278: private_mac_t *this) 279: { 280: this->k1->destroy(this->k1); 281: memwipe(this->k2, this->b); 282: free(this->k2); 283: memwipe(this->k3, this->b); 284: free(this->k3); 285: free(this->e); 286: free(this->remaining); 287: free(this); 288: } 289: 290: /* 291: * Described in header 292: */ 293: static mac_t *xcbc_create(encryption_algorithm_t algo, size_t key_size) 294: { 295: private_mac_t *this; 296: crypter_t *crypter; 297: uint8_t b; 298: 299: crypter = lib->crypto->create_crypter(lib->crypto, algo, key_size); 300: if (!crypter) 301: { 302: return NULL; 303: } 304: b = crypter->get_block_size(crypter); 305: /* input and output of crypter must be equal for xcbc */ 306: if (b != key_size) 307: { 308: crypter->destroy(crypter); 309: return NULL; 310: } 311: 312: INIT(this, 313: .public = { 314: .get_mac = _get_mac, 315: .get_mac_size = _get_mac_size, 316: .set_key = _set_key, 317: .destroy = _destroy, 318: }, 319: .b = b, 320: .k1 = crypter, 321: .k2 = malloc(b), 322: .k3 = malloc(b), 323: .e = malloc(b), 324: .remaining = malloc(b), 325: .zero = TRUE, 326: ); 327: memset(this->e, 0, b); 328: 329: return &this->public; 330: } 331: 332: /* 333: * Described in header. 334: */ 335: prf_t *xcbc_prf_create(pseudo_random_function_t algo) 336: { 337: mac_t *xcbc; 338: 339: switch (algo) 340: { 341: case PRF_AES128_XCBC: 342: xcbc = xcbc_create(ENCR_AES_CBC, 16); 343: break; 344: case PRF_CAMELLIA128_XCBC: 345: xcbc = xcbc_create(ENCR_CAMELLIA_CBC, 16); 346: break; 347: default: 348: return NULL; 349: } 350: if (xcbc) 351: { 352: return mac_prf_create(xcbc); 353: } 354: return NULL; 355: } 356: 357: /* 358: * Described in header 359: */ 360: signer_t *xcbc_signer_create(integrity_algorithm_t algo) 361: { 362: size_t trunc; 363: mac_t *xcbc; 364: 365: switch (algo) 366: { 367: case AUTH_AES_XCBC_96: 368: xcbc = xcbc_create(ENCR_AES_CBC, 16); 369: trunc = 12; 370: break; 371: case AUTH_CAMELLIA_XCBC_96: 372: xcbc = xcbc_create(ENCR_CAMELLIA_CBC, 16); 373: trunc = 12; 374: break; 375: default: 376: return NULL; 377: } 378: if (xcbc) 379: { 380: return mac_signer_create(xcbc, trunc); 381: } 382: return NULL; 383: }