2 * fips186prf.c An implementation of the FIPS-186-2 SHA1-based PRF.
4 * The development of the EAP/SIM support was funded by Internet Foundation
5 * Austria (http://www.nic.at/ipa).
7 * This code was written from scratch by Michael Richardson, and it is
8 * dual licensed under both GPL and BSD.
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 * 3. Neither the name of The NetBSD Foundation nor the names of its
39 * contributors may be used to endorse or promote products derived
40 * from this software without specific prior written permission.
42 * Copyright 2003 Michael Richardson <mcr@sandelman.ottawa.on.ca>
52 #ifdef HAVE_SYS_TYPES_H
53 #include <sys/types.h>
60 #ifdef HAVE_INTTYPES_H
64 #include <rad_assert.h>
69 * we do it in 8-bit chunks, because we have to keep the numbers
70 * in network byte order (i.e. MSB)
72 * make it a structure so that we can do structure assignments.
74 typedef struct onesixty {
78 static void onesixty_add_mod(onesixty *sum, onesixty *a, onesixty *b)
84 for(i=19; i>=0; i--) {
85 /* for(i=0; i<20; i++) { */
86 s = a->p[i] + b->p[i] + carry;
93 * run the FIPS-186-2 PRF on the given Master Key (160 bits)
94 * in order to derive 1280 bits (160 bytes) of keying data from
97 * Given that in EAP-SIM, this is coming from a 64-bit Kc it seems
98 * like an awful lot of "randomness" to pull out.. (MCR)
101 void fips186_2prf(uint8_t mk[20], uint8_t finalkey[160])
105 onesixty xval, xkey, w_0, w_1, sum, one;
112 * Step 3: For j = 0 to 3 do
114 * b. w_0 = SHA1(XVAL)
115 * c. XKEY = (1 + XKEY + w_0) mod 2^160
117 * e. w_1 = SHA1(XVAL)
118 * f. XKEY = (1 + XKEY + w_1) mod 2^160
122 memcpy(&xkey, mk, sizeof(xkey));
124 /* make the value 1 */
125 memset(&one, 0, sizeof(one));
134 /* b. w_0 = SHA1(XVAL) */
137 memset(zeros, 0, sizeof(zeros));
138 memcpy(zeros, xval.p, 20);
139 SHA1Transform(context.state, zeros);
140 SHA1FinalNoLen(w_0.p, &context);
142 /* c. XKEY = (1 + XKEY + w_0) mod 2^160 */
143 onesixty_add_mod(&sum, &xkey, &w_0);
144 onesixty_add_mod(&xkey, &sum, &one);
149 /* e. w_1 = SHA1(XVAL) */
152 memset(zeros, 0, sizeof(zeros));
153 memcpy(zeros, xval.p, 20);
154 SHA1Transform(context.state, zeros);
155 SHA1FinalNoLen(w_1.p, &context);
157 /* f. XKEY = (1 + XKEY + w_1) mod 2^160 */
158 onesixty_add_mod(&sum, &xkey, &w_1);
159 onesixty_add_mod(&xkey, &sum, &one);
161 /* now store it away */
172 * from http://csrc.nist.gov/CryptoToolkit/dss/Examples-1024bit.pdf
176 * XKEY= bd029bbe 7f51960b cf9edb2b 61f06f0f eb5a38b6
177 * XSEED= 00000000 00000000 00000000 00000000 00000000
180 * The first loop through step 3.2 provides:
182 * XVAL= bd029bbe 7f51960b cf9edb2b 61f06f0f eb5a38b6
184 * Using the routine in Appendix 3.3, Constructing The Function G From SHA-1,
185 * in step 3.2.b of the Change Notice algorithm for computing values of x
188 * w[0]= 2070b322 3dba372f de1c0ffc 7b2e3b49 8b260614
191 * The following value is the updated XKEY value from step 3.2.c:
193 * XKEY= dd734ee0 bd0bcd3b adbaeb27 dd1eaa59 76803ecb
195 * The second loop through step 3.2 provides:
197 * XVAL= dd734ee0 bd0bcd3b adbaeb27 dd1eaa59 76803ecb
199 * Using the routine in Appendix 3.3, Constructing The Function G From SHA-1,
200 * in step 3.2.b of the Change Notice algorithm for computing values of x
203 * w[1]= 3c6c18ba cb0f6c55 babb1378 8e20d737 a3275116
205 * The following value is the updated XKEY value from step 3.2.c:
208 * XKEY= 19df679b 881b3991 6875fea0 6b3f8191 19a78fe2
210 * Step 3.3 provides the following values:
212 * w[0] || w[1]= 2070b322 3dba372f de1c0ffc 7b2e3b49 8b260614
213 * 3c6c18ba cb0f6c55 babb1378 8e20d737 a3275116
221 uint8_t mk[20]={ 0xbd, 0x02, 0x9b, 0xbe, 0x7f, 0x51, 0x96, 0x0b,
222 0xcf, 0x9e, 0xdb, 0x2b, 0x61, 0xf0, 0x6f, 0x0f,
223 0xeb, 0x5a, 0x38, 0xb6 };
225 main(int argc, char *argv[])
227 uint8_t finalkey[160];
230 fips186_2prf(mk, finalkey);
232 printf("Input was: |");
234 for (i = 0; i < 20; i++) {
241 printf("%02x", mk[i]);
244 printf("|\nOutput was: ");
246 for (i = 0; i < 160; i++) {
259 printf("%02x", finalkey[i]);
269 * Revision 1.3 2004-02-26 19:04:30 aland
270 * perl -i -npe "s/[ \t]+$//g" `find src -name "*.[ch]" -print`
272 * Whitespace changes only, from a fresh checkout.
276 * Revision 1.2 2003/11/06 15:37:24 aland
277 * Update includes to work a little better
279 * Revision 1.1 2003/10/29 02:49:19 mcr
280 * initial commit of eap-sim