Return to hmac.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / hmac |
1.1 misho 1: /* 2: * Copyright (C) 2012 Tobias Brunner 3: * Copyright (C) 2005-2006 Martin Willi 4: * Copyright (C) 2005 Jan Hutter 5: * HSR Hochschule fuer Technik Rapperswil 6: * 7: * This program is free software; you can redistribute it and/or modify it 8: * under the terms of the GNU General Public License as published by the 9: * Free Software Foundation; either version 2 of the License, or (at your 10: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. 11: * 12: * This program is distributed in the hope that it will be useful, but 13: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15: * for more details. 16: */ 17: 18: #include "hmac.h" 19: 20: #include <crypto/mac.h> 21: #include <crypto/prfs/mac_prf.h> 22: #include <crypto/signers/mac_signer.h> 23: 24: typedef struct private_mac_t private_mac_t; 25: 26: /** 27: * Private data of a mac_t object. 28: * 29: * The variable names are the same as in the RFC. 30: */ 31: struct private_mac_t { 32: 33: /** 34: * Implements mac_t interface 35: */ 36: mac_t public; 37: 38: /** 39: * Block size, as in RFC. 40: */ 41: uint8_t b; 42: 43: /** 44: * Hash function. 45: */ 46: hasher_t *h; 47: 48: /** 49: * Previously xor'ed key using opad. 50: */ 51: chunk_t opaded_key; 52: 53: /** 54: * Previously xor'ed key using ipad. 55: */ 56: chunk_t ipaded_key; 57: }; 58: 59: METHOD(mac_t, get_mac, bool, 60: private_mac_t *this, chunk_t data, uint8_t *out) 61: { 62: /* H(K XOR opad, H(K XOR ipad, text)) 63: * 64: * if out is NULL, we append text to the inner hash. 65: * else, we complete the inner and do the outer. 66: * 67: */ 68: 69: uint8_t buffer[this->h->get_hash_size(this->h)]; 70: chunk_t inner; 71: 72: if (out == NULL) 73: { 74: /* append data to inner */ 75: return this->h->get_hash(this->h, data, NULL); 76: } 77: 78: /* append and do outer hash */ 79: inner.ptr = buffer; 80: inner.len = this->h->get_hash_size(this->h); 81: 82: /* complete inner, do outer and reinit for next call */ 83: return this->h->get_hash(this->h, data, buffer) && 84: this->h->get_hash(this->h, this->opaded_key, NULL) && 85: this->h->get_hash(this->h, inner, out) && 86: this->h->get_hash(this->h, this->ipaded_key, NULL); 87: } 88: 89: METHOD(mac_t, get_mac_size, size_t, 90: private_mac_t *this) 91: { 92: return this->h->get_hash_size(this->h); 93: } 94: 95: METHOD(mac_t, set_key, bool, 96: private_mac_t *this, chunk_t key) 97: { 98: int i; 99: uint8_t buffer[this->b]; 100: 101: memset(buffer, 0, this->b); 102: 103: if (key.len > this->b) 104: { 105: /* if key is too long, it will be hashed */ 106: if (!this->h->reset(this->h) || 107: !this->h->get_hash(this->h, key, buffer)) 108: { 109: return FALSE; 110: } 111: } 112: else 113: { 114: /* if not, just copy it in our pre-padded k */ 115: memcpy(buffer, key.ptr, key.len); 116: } 117: 118: /* apply ipad and opad to key */ 119: for (i = 0; i < this->b; i++) 120: { 121: this->ipaded_key.ptr[i] = buffer[i] ^ 0x36; 122: this->opaded_key.ptr[i] = buffer[i] ^ 0x5C; 123: } 124: 125: /* begin hashing of inner pad */ 126: return this->h->reset(this->h) && 127: this->h->get_hash(this->h, this->ipaded_key, NULL); 128: } 129: 130: METHOD(mac_t, destroy, void, 131: private_mac_t *this) 132: { 133: this->h->destroy(this->h); 134: chunk_clear(&this->opaded_key); 135: chunk_clear(&this->ipaded_key); 136: free(this); 137: } 138: 139: /* 140: * Creates an mac_t object 141: */ 142: static mac_t *hmac_create(hash_algorithm_t hash_algorithm) 143: { 144: private_mac_t *this; 145: 146: INIT(this, 147: .public = { 148: .get_mac = _get_mac, 149: .get_mac_size = _get_mac_size, 150: .set_key = _set_key, 151: .destroy = _destroy, 152: }, 153: ); 154: 155: /* set b, according to hasher */ 156: switch (hash_algorithm) 157: { 158: case HASH_SHA1: 159: case HASH_MD5: 160: case HASH_SHA256: 161: this->b = 64; 162: break; 163: case HASH_SHA384: 164: case HASH_SHA512: 165: this->b = 128; 166: break; 167: default: 168: free(this); 169: return NULL; 170: } 171: 172: this->h = lib->crypto->create_hasher(lib->crypto, hash_algorithm); 173: if (this->h == NULL) 174: { 175: free(this); 176: return NULL; 177: } 178: 179: /* build ipad and opad */ 180: this->opaded_key.ptr = malloc(this->b); 181: this->opaded_key.len = this->b; 182: 183: this->ipaded_key.ptr = malloc(this->b); 184: this->ipaded_key.len = this->b; 185: 186: return &this->public; 187: } 188: 189: /* 190: * Described in header 191: */ 192: prf_t *hmac_prf_create(pseudo_random_function_t algo) 193: { 194: mac_t *hmac; 195: 196: hmac = hmac_create(hasher_algorithm_from_prf(algo)); 197: if (hmac) 198: { 199: return mac_prf_create(hmac); 200: } 201: return NULL; 202: } 203: 204: /* 205: * Described in header 206: */ 207: signer_t *hmac_signer_create(integrity_algorithm_t algo) 208: { 209: mac_t *hmac; 210: size_t trunc; 211: 212: hmac = hmac_create(hasher_algorithm_from_integrity(algo, &trunc)); 213: if (hmac) 214: { 215: return mac_signer_create(hmac, trunc); 216: } 217: return NULL; 218: }