Annotation of embedaddon/strongswan/src/libstrongswan/plugins/hmac/hmac.c, revision 1.1
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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>