Annotation of embedaddon/strongswan/src/libstrongswan/crypto/prf_plus.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2005-2006 Martin Willi
! 3: * Copyright (C) 2005 Jan Hutter
! 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 "prf_plus.h"
! 20:
! 21: typedef struct private_prf_plus_t private_prf_plus_t;
! 22:
! 23: typedef bool (*apply_prf_t)(private_prf_plus_t *this);
! 24:
! 25: /**
! 26: * Private data of an prf_plus_t object.
! 27: *
! 28: */
! 29: struct private_prf_plus_t {
! 30:
! 31: /**
! 32: * Public interface of prf_plus_t.
! 33: */
! 34: prf_plus_t public;
! 35:
! 36: /**
! 37: * PRF to use.
! 38: */
! 39: prf_t *prf;
! 40:
! 41: /**
! 42: * Initial seed.
! 43: */
! 44: chunk_t seed;
! 45:
! 46: /**
! 47: * Octet which will be appended to the seed if a counter is used.
! 48: */
! 49: uint8_t counter;
! 50:
! 51: /**
! 52: * Already given out bytes in current buffer.
! 53: */
! 54: size_t used;
! 55:
! 56: /**
! 57: * Buffer to store current PRF result.
! 58: */
! 59: chunk_t buffer;
! 60:
! 61: /**
! 62: * The prf application method depending on whether a counter is used.
! 63: */
! 64: apply_prf_t apply_prf;
! 65: };
! 66:
! 67: /**
! 68: * Apply the PRF using the running counter
! 69: */
! 70: static bool apply_prf_counter(private_prf_plus_t *this)
! 71: {
! 72: if (!this->prf->get_bytes(this->prf, this->seed, NULL) ||
! 73: !this->prf->get_bytes(this->prf, chunk_from_thing(this->counter),
! 74: this->buffer.ptr))
! 75: {
! 76: return FALSE;
! 77: }
! 78: this->counter++;
! 79: if (!this->counter)
! 80: { /* according to RFC 7296, section 2.13, prf+ is undefined once the
! 81: * counter wrapped, so let's fail for future calls */
! 82: this->apply_prf = (void*)return_false;
! 83: }
! 84: return TRUE;
! 85: }
! 86:
! 87: /**
! 88: * Apply the PRF using the running counter
! 89: */
! 90: static bool apply_prf(private_prf_plus_t *this)
! 91: {
! 92: return this->prf->get_bytes(this->prf, this->seed, this->buffer.ptr);
! 93: }
! 94:
! 95: METHOD(prf_plus_t, get_bytes, bool,
! 96: private_prf_plus_t *this, size_t length, uint8_t *buffer)
! 97: {
! 98: size_t round, written = 0;
! 99:
! 100: while (length > 0)
! 101: {
! 102: if (this->buffer.len == this->used)
! 103: { /* buffer used, get next round */
! 104: if (!this->prf->get_bytes(this->prf, this->buffer, NULL))
! 105: {
! 106: return FALSE;
! 107: }
! 108: if (!this->apply_prf(this))
! 109: {
! 110: return FALSE;
! 111: }
! 112: this->used = 0;
! 113: }
! 114: round = min(length, this->buffer.len - this->used);
! 115: memcpy(buffer + written, this->buffer.ptr + this->used, round);
! 116:
! 117: length -= round;
! 118: this->used += round;
! 119: written += round;
! 120: }
! 121: return TRUE;
! 122: }
! 123:
! 124: METHOD(prf_plus_t, allocate_bytes, bool,
! 125: private_prf_plus_t *this, size_t length, chunk_t *chunk)
! 126: {
! 127: *chunk = chunk_alloc(length);
! 128: if (!get_bytes(this, length, chunk->ptr))
! 129: {
! 130: chunk_free(chunk);
! 131: return FALSE;
! 132: }
! 133: return TRUE;
! 134: }
! 135:
! 136: METHOD(prf_plus_t, destroy, void,
! 137: private_prf_plus_t *this)
! 138: {
! 139: chunk_clear(&this->buffer);
! 140: chunk_clear(&this->seed);
! 141: free(this);
! 142: }
! 143:
! 144: /*
! 145: * Description in header.
! 146: */
! 147: prf_plus_t *prf_plus_create(prf_t *prf, bool counter, chunk_t seed)
! 148: {
! 149: private_prf_plus_t *this;
! 150:
! 151: INIT(this,
! 152: .public = {
! 153: .get_bytes = _get_bytes,
! 154: .allocate_bytes = _allocate_bytes,
! 155: .destroy = _destroy,
! 156: },
! 157: .prf = prf,
! 158: .seed = chunk_clone(seed),
! 159: .buffer = chunk_alloc(prf->get_block_size(prf)),
! 160: .apply_prf = counter ? apply_prf_counter : apply_prf,
! 161: .counter = 0x01,
! 162: );
! 163:
! 164: if (!this->apply_prf(this))
! 165: {
! 166: destroy(this);
! 167: return NULL;
! 168: }
! 169: return &this->public;
! 170: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>