Prototype implementation of IKE key exchange via NTRU encryption
[strongswan.git] / src / libstrongswan / plugins / ntru / ntru_crypto / ntru_crypto_ntru_mgf1.c
1 /******************************************************************************
2 * NTRU Cryptography Reference Source Code
3 * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
4 *
5 * ntru_crypto_ntru_mgf1.c is a component of ntru-crypto.
6 *
7 * Copyright (C) 2009-2013 Security Innovation
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 *
23 *****************************************************************************/
24
25 /******************************************************************************
26 *
27 * File: ntru_crypto_ntru_mgf1.c
28 *
29 * Contents: Routines implementing MGF-TP-1 and MGF-1.
30 *
31 *****************************************************************************/
32
33
34 #include <stdlib.h>
35 #include <string.h>
36 #include <assert.h>
37 #include "ntru_crypto_ntru_mgf1.h"
38 #include "ntru_crypto_ntru_convert.h"
39
40
41 /* ntru_mgf1
42 *
43 * Implements a basic mask-generation function, generating an arbitrary
44 * number of octets based on hashing a digest-length string concatenated
45 * with a 4-octet counter.
46 *
47 * The state (string and counter) is initialized when a seed is present.
48 *
49 * Returns NTRU_OK if successful.
50 * Returns NTRU_CRYPTO_HASH_ errors if they occur.
51 *
52 */
53
54 uint32_t
55 ntru_mgf1(
56 uint8_t *state, /* in/out - pointer to the state */
57 NTRU_CRYPTO_HASH_ALGID algid, /* in - hash algorithm ID */
58 uint8_t md_len, /* in - no. of octets in digest */
59 uint8_t num_calls, /* in - no. of hash calls */
60 uint16_t seed_len, /* in - no. of octets in seed */
61 uint8_t const *seed, /* in - pointer to seed */
62 uint8_t *out) /* out - address for output */
63 {
64 uint8_t *ctr = state + md_len;
65 uint32_t retcode;
66
67 assert(state);
68 assert(out);
69
70 /* if seed present, init state */
71
72 if (seed) {
73 if ((retcode = ntru_crypto_hash_digest(algid, seed, seed_len, state)) !=
74 NTRU_CRYPTO_HASH_OK)
75 return retcode;
76 memset(ctr, 0, 4);
77 }
78
79 /* generate output */
80
81 while (num_calls-- > 0) {
82 if ((retcode = ntru_crypto_hash_digest(algid, state, md_len + 4,
83 out)) !=
84 NTRU_CRYPTO_HASH_OK)
85 return retcode;
86 out += md_len;
87
88 /* increment counter */
89
90 if (++ctr[3] == 0)
91 if (++ctr[2] == 0)
92 if (++ctr[1] == 0)
93 ++ctr[0];
94 }
95
96 NTRU_RET(NTRU_OK);
97 }
98
99
100 /* ntru_mgftp1
101 *
102 * Implements a mask-generation function for trinary polynomials,
103 * MGF-TP-1, generating an arbitrary number of octets based on hashing
104 * a digest-length string concatenated with a 4-octet counter. From
105 * these octets, N trits are derived.
106 *
107 * The state (string and counter) is initialized when a seed is present.
108 *
109 * Returns NTRU_OK if successful.
110 * Returns NTRU_CRYPTO_HASH_ errors if they occur.
111 *
112 */
113
114 uint32_t
115 ntru_mgftp1(
116 NTRU_CRYPTO_HASH_ALGID hash_algid, /* in - hash alg ID for
117 MGF-TP-1 */
118 uint8_t md_len, /* in - no. of octets in
119 digest */
120 uint8_t min_calls, /* in - minimum no. of hash
121 calls */
122 uint16_t seed_len, /* in - no. of octets in seed */
123 uint8_t *seed, /* in - pointer to seed */
124 uint8_t *buf, /* in - pointer to working
125 buffer */
126 uint16_t num_trits_needed, /* in - no. of trits in mask */
127 uint8_t *mask) /* out - address for mask trits */
128 {
129 uint8_t *mgf_out;
130 uint8_t *octets;
131 uint16_t octets_available;
132 uint32_t retcode;
133
134 assert(seed);
135 assert(buf);
136 assert(mask);
137
138 /* generate minimum MGF1 output */
139
140 mgf_out = buf + md_len + 4;
141 if ((retcode = ntru_mgf1(buf, hash_algid, md_len, min_calls,
142 seed_len, seed, mgf_out)) != NTRU_OK)
143 return retcode;
144 octets = mgf_out;
145 octets_available = min_calls * md_len;
146
147 /* get trits for mask */
148
149 while (num_trits_needed >= 5) {
150
151 /* get another octet and convert it to 5 trits */
152
153 if (octets_available == 0) {
154 if ((retcode = ntru_mgf1(buf, hash_algid, md_len, 1,
155 0, NULL, mgf_out)) != NTRU_OK)
156 return retcode;
157 octets = mgf_out;
158 octets_available = md_len;
159 }
160
161 if (*octets < 243) {
162 ntru_octet_2_trits(*octets, mask);
163 mask += 5;
164 num_trits_needed -= 5;
165 }
166 octets++;
167 --octets_available;
168 }
169
170 /* get any remaining trits */
171
172 while (num_trits_needed) {
173 uint8_t trits[5];
174
175 /* get another octet and convert it to remaining trits */
176
177 if (octets_available == 0) {
178 if ((retcode = ntru_mgf1(buf, hash_algid, md_len, 1,
179 0, NULL, mgf_out)) != NTRU_OK)
180 return retcode;
181 octets = mgf_out;
182 octets_available = md_len;
183 }
184 if (*octets < 243) {
185 ntru_octet_2_trits(*octets, trits);
186 memcpy(mask, trits, num_trits_needed);
187 num_trits_needed = 0;
188 } else {
189 octets++;
190 --octets_available;
191 }
192 }
193
194 NTRU_RET(NTRU_OK);
195 }
196
197