Implemented bitspender based on the MGF1 mask generator function
[strongswan.git] / src / libstrongswan / crypto / mgf1 / mgf1_bitspender.c
1 /*
2 * Copyright (C) 2014 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
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 "mgf1_bitspender.h"
17
18 #include <crypto/mgf1/mgf1.h>
19
20 typedef struct private_mgf1_bitspender_t private_mgf1_bitspender_t;
21
22 /**
23 * Private data structure for mgf1_bitspender_t object
24 */
25 struct private_mgf1_bitspender_t {
26 /**
27 * Public interface.
28 */
29 mgf1_bitspender_t public;
30
31 /**
32 * MGF1 bit mask generator
33 */
34 mgf1_t *mgf1;
35
36 /**
37 * Octet storage (accommodates up to 64 octets)
38 */
39 uint8_t octets[HASH_SIZE_SHA512];
40
41 /**
42 * Length of the returned hash value in octets
43 */
44 int hash_len;
45
46 /**
47 * Number of generated octets
48 */
49 int octets_count;
50
51 /**
52 * Number of available octets
53 */
54 int octets_left;
55
56 /**
57 * Bit storage (accomodates up to 32 bits)
58 */
59 uint32_t bits;
60
61 /**
62 * Number of available bits
63 */
64 int bits_left;
65 };
66
67 METHOD(mgf1_bitspender_t, get_bits, uint32_t,
68 private_mgf1_bitspender_t *this, int bits_needed)
69 {
70 uint32_t bits = 0x00000000;
71 int bits_now;
72
73 if (bits_needed > 31)
74 {
75 /* too many bits requested */
76 return MGF1_BITSPENDER_ERROR;
77 }
78
79 while (bits_needed)
80 {
81 if (this->bits_left == 0)
82 {
83 if (this->octets_left == 0)
84 {
85 /* get another block from MGF1 */
86 if (!this->mgf1->get_mask(this->mgf1, this->hash_len,
87 this->octets))
88 {
89 /* no block available */
90 return MGF1_BITSPENDER_ERROR;
91 }
92 this->octets_left = this->hash_len;
93 this->octets_count += this->hash_len;
94 }
95 this->bits = untoh32(this->octets + this->hash_len -
96 this->octets_left);
97 this->bits_left = 32;
98 this->octets_left -= 4;
99 }
100 if (bits_needed > this->bits_left)
101 {
102 bits_now = this->bits_left;
103 this->bits_left = 0;
104 bits_needed -= bits_now;
105 bits <<= bits_now;
106 bits |= this->bits;
107 }
108 else
109 {
110 bits_now = bits_needed;
111 this->bits_left -= bits_needed;
112 bits_needed = 0;
113 bits <<= bits_now;
114 bits |= this->bits >> this->bits_left;
115 this->bits &= 0xffffffff >> (32 - this->bits_left);
116 }
117 }
118 return bits;
119 }
120
121
122 METHOD(mgf1_bitspender_t, destroy, void,
123 private_mgf1_bitspender_t *this)
124 {
125 DBG2(DBG_LIB, "mgf1 generated %u octets", this->octets_count);
126 memwipe(this->octets, sizeof(this->octets));
127 this->mgf1->destroy(this->mgf1);
128 free(this);
129 }
130
131 /**
132 * See header.
133 */
134 mgf1_bitspender_t *mgf1_bitspender_create(hash_algorithm_t alg, chunk_t seed,
135 bool hash_seed)
136 {
137 private_mgf1_bitspender_t *this;
138 mgf1_t *mgf1;
139
140 mgf1 = mgf1_create(alg, seed, hash_seed);
141 if (!mgf1)
142 {
143 return NULL;
144 }
145 DBG2(DBG_LIB, "mgf1 based on %N is seeded with %u octets",
146 hash_algorithm_short_names, alg, seed.len);
147
148 INIT(this,
149 .public = {
150 .get_bits = _get_bits,
151 .destroy = _destroy,
152 },
153 .mgf1 = mgf1,
154 .hash_len = mgf1->get_hash_size(mgf1),
155 );
156
157 return &this->public;
158 }