Return to gcm_aead.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / gcm |
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 "gcm_aead.h" 17: 18: #include <limits.h> 19: #include <crypto/iv/iv_gen_seq.h> 20: 21: #define BLOCK_SIZE 16 22: #define NONCE_SIZE 12 23: #define IV_SIZE 8 24: #define SALT_SIZE (NONCE_SIZE - IV_SIZE) 25: 26: typedef struct private_gcm_aead_t private_gcm_aead_t; 27: 28: /** 29: * Private data of an gcm_aead_t object. 30: */ 31: struct private_gcm_aead_t { 32: 33: /** 34: * Public gcm_aead_t interface. 35: */ 36: gcm_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: * Size of the integrity check value 50: */ 51: size_t icv_size; 52: 53: /** 54: * Salt value 55: */ 56: char salt[SALT_SIZE]; 57: 58: /** 59: * GHASH subkey H 60: */ 61: char h[BLOCK_SIZE]; 62: }; 63: 64: /** 65: * Find a suitable word size and network order conversion functions 66: */ 67: #if ULONG_MAX == 18446744073709551615UL && defined(htobe64) 68: # define htobeword htobe64 69: # define bewordtoh be64toh 70: # define SHIFT_WORD_TYPE uint64_t 71: #else 72: # define htobeword htonl 73: # define bewordtoh ntohl 74: # define SHIFT_WORD_TYPE uint32_t 75: #endif 76: 77: /** 78: * Bitshift a block right by one bit 79: */ 80: static void sr_block(char *block) 81: { 82: int i; 83: SHIFT_WORD_TYPE *word = (SHIFT_WORD_TYPE*)block; 84: 85: for (i = 0; i < BLOCK_SIZE / sizeof(*word); i++) 86: { 87: word[i] = bewordtoh(word[i]); 88: } 89: for (i = BLOCK_SIZE / sizeof(*word) - 1; i >= 0; i--) 90: { 91: word[i] >>= 1; 92: if (i != 0) 93: { 94: word[i] |= word[i - 1] << (sizeof(*word) * 8 - 1); 95: } 96: } 97: for (i = 0; i < BLOCK_SIZE / sizeof(*word); i++) 98: { 99: word[i] = htobeword(word[i]); 100: } 101: } 102: 103: /** 104: * Naive implementation of block multiplication in GF128, no tables 105: */ 106: static void mult_block(char *x, char *y, char *res) 107: { 108: char z[BLOCK_SIZE], v[BLOCK_SIZE], r; 109: int bit, byte; 110: 111: r = 0xE1; 112: memset(z, 0, BLOCK_SIZE); 113: memcpy(v, y, BLOCK_SIZE); 114: 115: for (byte = 0; byte < BLOCK_SIZE; byte++) 116: { 117: for (bit = 7; bit >= 0; bit--) 118: { 119: if (x[byte] & (1 << bit)) 120: { 121: memxor(z, v, BLOCK_SIZE); 122: } 123: if (v[BLOCK_SIZE - 1] & 0x01) 124: { 125: sr_block(v); 126: v[0] ^= r; 127: } 128: else 129: { 130: sr_block(v); 131: } 132: } 133: } 134: memcpy(res, z, BLOCK_SIZE); 135: } 136: 137: /** 138: * GHASH function 139: */ 140: static void ghash(private_gcm_aead_t *this, chunk_t x, char *res) 141: { 142: char y[BLOCK_SIZE]; 143: 144: memset(y, 0, BLOCK_SIZE); 145: 146: while (x.len) 147: { 148: memxor(y, x.ptr, BLOCK_SIZE); 149: mult_block(y, this->h, y); 150: x = chunk_skip(x, BLOCK_SIZE); 151: } 152: memcpy(res, y, BLOCK_SIZE); 153: } 154: 155: /** 156: * GCTR function, en-/decrypts x inline 157: */ 158: static bool gctr(private_gcm_aead_t *this, char *icb, chunk_t x) 159: { 160: char cb[BLOCK_SIZE], iv[BLOCK_SIZE], tmp[BLOCK_SIZE]; 161: 162: memset(iv, 0, BLOCK_SIZE); 163: memcpy(cb, icb, BLOCK_SIZE); 164: 165: while (x.len) 166: { 167: memcpy(tmp, cb, BLOCK_SIZE); 168: if (!this->crypter->encrypt(this->crypter, chunk_from_thing(tmp), 169: chunk_from_thing(iv), NULL)) 170: { 171: return FALSE; 172: } 173: memxor(x.ptr, tmp, min(BLOCK_SIZE, x.len)); 174: chunk_increment(chunk_from_thing(cb)); 175: x = chunk_skip(x, BLOCK_SIZE); 176: } 177: return TRUE; 178: } 179: 180: /** 181: * Generate the block J0 182: */ 183: static void create_j(private_gcm_aead_t *this, char *iv, char *j) 184: { 185: memcpy(j, this->salt, SALT_SIZE); 186: memcpy(j + SALT_SIZE, iv, IV_SIZE); 187: htoun32(j + SALT_SIZE + IV_SIZE, 1); 188: } 189: 190: /** 191: * Create GHASH subkey H 192: */ 193: static bool create_h(private_gcm_aead_t *this, char *h) 194: { 195: char zero[BLOCK_SIZE]; 196: 197: memset(zero, 0, BLOCK_SIZE); 198: memset(h, 0, BLOCK_SIZE); 199: 200: return this->crypter->encrypt(this->crypter, chunk_create(h, BLOCK_SIZE), 201: chunk_from_thing(zero), NULL); 202: } 203: 204: /** 205: * Encrypt/decrypt 206: */ 207: static bool crypt(private_gcm_aead_t *this, char *j, chunk_t in, chunk_t out) 208: { 209: char icb[BLOCK_SIZE]; 210: 211: memcpy(icb, j, BLOCK_SIZE); 212: chunk_increment(chunk_from_thing(icb)); 213: 214: out.len = in.len; 215: if (in.ptr != out.ptr) 216: { 217: memcpy(out.ptr, in.ptr, in.len); 218: } 219: return gctr(this, icb, out); 220: } 221: 222: /** 223: * Create ICV 224: */ 225: static bool create_icv(private_gcm_aead_t *this, chunk_t assoc, chunk_t crypt, 226: char *j, char *icv) 227: { 228: size_t assoc_pad, crypt_pad; 229: chunk_t chunk; 230: char s[BLOCK_SIZE], *pos; 231: 232: assoc_pad = (BLOCK_SIZE - (assoc.len % BLOCK_SIZE)) % BLOCK_SIZE; 233: crypt_pad = (BLOCK_SIZE - (crypt.len % BLOCK_SIZE)) % BLOCK_SIZE; 234: 235: /* concatenate data to a new chunk */ 236: chunk = chunk_alloc(assoc.len + assoc_pad + 237: crypt.len + crypt_pad + BLOCK_SIZE); 238: pos = chunk.ptr; 239: /* add associated data */ 240: memcpy(pos, assoc.ptr, assoc.len); 241: pos += assoc.len; 242: memset(pos, 0, assoc_pad); 243: pos += assoc_pad; 244: /* add encrypted data */ 245: memcpy(pos, crypt.ptr, crypt.len); 246: pos += crypt.len; 247: memset(pos, 0, crypt_pad); 248: pos += crypt_pad; 249: /* write associated len */ 250: memset(pos, 0, 4); 251: pos += 4; 252: htoun32(pos, assoc.len * 8); 253: pos += 4; 254: /* write encrypted length */ 255: memset(pos, 0, 4); 256: pos += 4; 257: htoun32(pos, crypt.len * 8); 258: pos += 4; 259: 260: ghash(this, chunk, s); 261: free(chunk.ptr); 262: if (!gctr(this, j, chunk_from_thing(s))) 263: { 264: return FALSE; 265: } 266: memcpy(icv, s, this->icv_size); 267: return TRUE; 268: } 269: 270: /** 271: * Verify the ICV value 272: */ 273: static bool verify_icv(private_gcm_aead_t *this, chunk_t assoc, chunk_t crypt, 274: char *j, char *icv) 275: { 276: char tmp[this->icv_size]; 277: 278: return create_icv(this, assoc, crypt, j, tmp) && 279: memeq_const(tmp, icv, this->icv_size); 280: } 281: 282: METHOD(aead_t, encrypt, bool, 283: private_gcm_aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv, 284: chunk_t *encrypted) 285: { 286: char j[BLOCK_SIZE]; 287: 288: create_j(this, iv.ptr, j); 289: 290: if (encrypted) 291: { 292: *encrypted = chunk_alloc(plain.len + this->icv_size); 293: return crypt(this, j, plain, *encrypted) && 294: create_icv(this, assoc, 295: chunk_create(encrypted->ptr, encrypted->len - this->icv_size), 296: j, encrypted->ptr + encrypted->len - this->icv_size); 297: } 298: return crypt(this, j, plain, plain) && 299: create_icv(this, assoc, plain, j, plain.ptr + plain.len); 300: } 301: 302: METHOD(aead_t, decrypt, bool, 303: private_gcm_aead_t *this, chunk_t encrypted, chunk_t assoc, chunk_t iv, 304: chunk_t *plain) 305: { 306: char j[BLOCK_SIZE]; 307: 308: if (encrypted.len < this->icv_size) 309: { 310: return FALSE; 311: } 312: 313: create_j(this, iv.ptr, j); 314: 315: encrypted.len -= this->icv_size; 316: if (!verify_icv(this, assoc, encrypted, j, encrypted.ptr + encrypted.len)) 317: { 318: return FALSE; 319: } 320: if (plain) 321: { 322: *plain = chunk_alloc(encrypted.len); 323: return crypt(this, j, encrypted, *plain); 324: } 325: return crypt(this, j, encrypted, encrypted); 326: } 327: 328: METHOD(aead_t, get_block_size, size_t, 329: private_gcm_aead_t *this) 330: { 331: return 1; 332: } 333: 334: METHOD(aead_t, get_icv_size, size_t, 335: private_gcm_aead_t *this) 336: { 337: return this->icv_size; 338: } 339: 340: METHOD(aead_t, get_iv_size, size_t, 341: private_gcm_aead_t *this) 342: { 343: return IV_SIZE; 344: } 345: 346: METHOD(aead_t, get_iv_gen, iv_gen_t*, 347: private_gcm_aead_t *this) 348: { 349: return this->iv_gen; 350: } 351: 352: METHOD(aead_t, get_key_size, size_t, 353: private_gcm_aead_t *this) 354: { 355: return this->crypter->get_key_size(this->crypter) + SALT_SIZE; 356: } 357: 358: METHOD(aead_t, set_key, bool, 359: private_gcm_aead_t *this, chunk_t key) 360: { 361: memcpy(this->salt, key.ptr + key.len - SALT_SIZE, SALT_SIZE); 362: key.len -= SALT_SIZE; 363: return this->crypter->set_key(this->crypter, key) && 364: create_h(this, this->h); 365: } 366: 367: METHOD(aead_t, destroy, void, 368: private_gcm_aead_t *this) 369: { 370: this->crypter->destroy(this->crypter); 371: this->iv_gen->destroy(this->iv_gen); 372: free(this); 373: } 374: 375: /** 376: * See header 377: */ 378: gcm_aead_t *gcm_aead_create(encryption_algorithm_t algo, 379: size_t key_size, size_t salt_size) 380: { 381: private_gcm_aead_t *this; 382: size_t icv_size; 383: 384: switch (key_size) 385: { 386: case 0: 387: key_size = 16; 388: break; 389: case 16: 390: case 24: 391: case 32: 392: break; 393: default: 394: return NULL; 395: } 396: if (salt_size && salt_size != SALT_SIZE) 397: { 398: /* currently not supported */ 399: return NULL; 400: } 401: switch (algo) 402: { 403: case ENCR_AES_GCM_ICV8: 404: algo = ENCR_AES_CBC; 405: icv_size = 8; 406: break; 407: case ENCR_AES_GCM_ICV12: 408: algo = ENCR_AES_CBC; 409: icv_size = 12; 410: break; 411: case ENCR_AES_GCM_ICV16: 412: algo = ENCR_AES_CBC; 413: icv_size = 16; 414: break; 415: default: 416: return NULL; 417: } 418: 419: INIT(this, 420: .public = { 421: .aead = { 422: .encrypt = _encrypt, 423: .decrypt = _decrypt, 424: .get_block_size = _get_block_size, 425: .get_icv_size = _get_icv_size, 426: .get_iv_size = _get_iv_size, 427: .get_iv_gen = _get_iv_gen, 428: .get_key_size = _get_key_size, 429: .set_key = _set_key, 430: .destroy = _destroy, 431: }, 432: }, 433: .crypter = lib->crypto->create_crypter(lib->crypto, algo, key_size), 434: .iv_gen = iv_gen_seq_create(), 435: .icv_size = icv_size, 436: ); 437: 438: if (!this->crypter) 439: { 440: free(this); 441: return NULL; 442: } 443: 444: return &this->public; 445: }