All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
fips186prf.c
Go to the documentation of this file.
1 /*
2  * fips186prf.c An implementation of the FIPS-186-2 SHA1-based PRF.
3  *
4  * The development of the EAP/SIM support was funded by Internet Foundation
5  * Austria (http://www.nic.at/ipa).
6  *
7  * This code was written from scratch by Michael Richardson, and it is
8  * dual licensed under both GPL and BSD.
9  *
10  * Version: $Id: 2002c62ccffcd8282ab023f02bbd665e42770b47 $
11  *
12  * GPL notice:
13  *
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.
18  *
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.
23  *
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27  *
28  * BSD notice:
29  *
30  * Redistribution and use in source and binary forms, with or without
31  * modification, are permitted provided that the following conditions
32  * are met:
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.
41  *
42  * Copyright 2003 Michael Richardson <mcr@sandelman.ottawa.on.ca>
43  * Copyright 2006 The FreeRADIUS server project
44  *
45  */
46 
47 RCSID("$Id: 2002c62ccffcd8282ab023f02bbd665e42770b47 $")
48 
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52 
53 #ifdef HAVE_SYS_TYPES_H
54 #include <sys/types.h>
55 #endif
56 
57 #ifdef HAVE_STDINT_H
58 #include <stdint.h>
59 #endif
60 
61 #ifdef HAVE_INTTYPES_H
62 #include <inttypes.h>
63 #endif
64 
65 #include <freeradius-devel/sha1.h>
66 
67 /*
68  * we do it in 8-bit chunks, because we have to keep the numbers
69  * in network byte order (i.e. MSB)
70  *
71  * make it a structure so that we can do structure assignments.
72  */
73 typedef struct onesixty {
74  uint8_t p[20];
75 } onesixty;
76 
77 static void onesixty_add_mod(onesixty *sum, onesixty *a, onesixty *b)
78 {
79  uint32_t s;
80  int i, carry;
81 
82  carry = 0;
83  for(i=19; i>=0; i--) {
84 /* for(i=0; i<20; i++) { */
85  s = a->p[i] + b->p[i] + carry;
86  sum->p[i] = s & 0xff;
87  carry = s >> 8;
88  }
89 }
90 
91 /*
92  * run the FIPS-186-2 PRF on the given Master Key (160 bits)
93  * in order to derive 1280 bits (160 bytes) of keying data from
94  * it.
95  *
96  * Given that in EAP-SIM, this is coming from a 64-bit Kc it seems
97  * like an awful lot of "randomness" to pull out.. (MCR)
98  *
99  */
100 void fips186_2prf(uint8_t mk[20], uint8_t finalkey[160])
101 {
102  fr_sha1_ctx context;
103  int j;
104  onesixty xval, xkey, w_0, w_1, sum, one;
105  uint8_t *f;
106  uint8_t zeros[64];
107 
108  /*
109  * let XKEY := MK,
110  *
111  * Step 3: For j = 0 to 3 do
112  * a. XVAL = XKEY
113  * b. w_0 = SHA1(XVAL)
114  * c. XKEY = (1 + XKEY + w_0) mod 2^160
115  * d. XVAL = XKEY
116  * e. w_1 = SHA1(XVAL)
117  * f. XKEY = (1 + XKEY + w_1) mod 2^160
118  * 3.3 x_j = w_0|w_1
119  *
120  */
121  memcpy(&xkey, mk, sizeof(xkey));
122 
123  /* make the value 1 */
124  memset(&one, 0, sizeof(one));
125  one.p[19]=1;
126 
127  f=finalkey;
128 
129  for(j=0; j<4; j++) {
130  /* a. XVAL = XKEY */
131  xval = xkey;
132 
133  /* b. w_0 = SHA1(XVAL) */
134  fr_sha1_init(&context);
135 
136  memset(zeros + 20, 0, sizeof(zeros) - 20);
137  memcpy(zeros, xval.p, 20);
138 #ifndef WITH_OPENSSL_SHA1
139  fr_sha1_transform(context.state, zeros);
140 #else
141  fr_sha1_transform(&context, zeros);
142 #endif
143  fr_sha1_final_no_len(w_0.p, &context);
144 
145  /* c. XKEY = (1 + XKEY + w_0) mod 2^160 */
146  onesixty_add_mod(&sum, &xkey, &w_0);
147  onesixty_add_mod(&xkey, &sum, &one);
148 
149  /* d. XVAL = XKEY */
150  xval = xkey;
151 
152  /* e. w_1 = SHA1(XVAL) */
153  fr_sha1_init(&context);
154 
155  memset(zeros + 20, 0, sizeof(zeros) - 20);
156  memcpy(zeros, xval.p, 20);
157 #ifndef WITH_OPENSSL_SHA1
158  fr_sha1_transform(context.state, zeros);
159 #else
160  fr_sha1_transform(&context, zeros);
161 #endif
162  fr_sha1_final_no_len(w_1.p, &context);
163 
164  /* f. XKEY = (1 + XKEY + w_1) mod 2^160 */
165  onesixty_add_mod(&sum, &xkey, &w_1);
166  onesixty_add_mod(&xkey, &sum, &one);
167 
168  /* now store it away */
169  memcpy(f, &w_0, 20);
170  f += 20;
171 
172  memcpy(f, &w_1, 20);
173  f += 20;
174  }
175 }
176 
177 /*
178  * test vectors
179  * from http://csrc.nist.gov/CryptoToolkit/dss/Examples-1024bit.pdf
180  *
181  * page 5
182  *
183  * XKEY= bd029bbe 7f51960b cf9edb2b 61f06f0f eb5a38b6
184  * XSEED= 00000000 00000000 00000000 00000000 00000000
185  *
186  *
187  * The first loop through step 3.2 provides:
188  *
189  * XVAL= bd029bbe 7f51960b cf9edb2b 61f06f0f eb5a38b6
190  *
191  * Using the routine in Appendix 3.3, Constructing The Function G From SHA-1,
192  * in step 3.2.b of the Change Notice algorithm for computing values of x
193  * provides:
194  *
195  * w[0]= 2070b322 3dba372f de1c0ffc 7b2e3b49 8b260614
196  *
197  *
198  * The following value is the updated XKEY value from step 3.2.c:
199  *
200  * XKEY= dd734ee0 bd0bcd3b adbaeb27 dd1eaa59 76803ecb
201  *
202  * The second loop through step 3.2 provides:
203  *
204  * XVAL= dd734ee0 bd0bcd3b adbaeb27 dd1eaa59 76803ecb
205  *
206  * Using the routine in Appendix 3.3, Constructing The Function G From SHA-1,
207  * in step 3.2.b of the Change Notice algorithm for computing values of x
208  * provides:
209  *
210  * w[1]= 3c6c18ba cb0f6c55 babb1378 8e20d737 a3275116
211  *
212  * The following value is the updated XKEY value from step 3.2.c:
213  *
214  *
215  * XKEY= 19df679b 881b3991 6875fea0 6b3f8191 19a78fe2
216  *
217  * Step 3.3 provides the following values:
218  *
219  * w[0] || w[1]= 2070b322 3dba372f de1c0ffc 7b2e3b49 8b260614
220  * 3c6c18ba cb0f6c55 babb1378 8e20d737 a3275116
221  *
222  */
223 
224 #ifdef TEST_CASE
225 
226 #include <assert.h>
227 
228 uint8_t mk[20]={ 0xbd, 0x02, 0x9b, 0xbe, 0x7f, 0x51, 0x96, 0x0b,
229  0xcf, 0x9e, 0xdb, 0x2b, 0x61, 0xf0, 0x6f, 0x0f,
230  0xeb, 0x5a, 0x38, 0xb6 };
231 
232 main(int argc, char *argv[])
233 {
234  uint8_t finalkey[160];
235  int i, j, k;
236 
237  fips186_2prf(mk, finalkey);
238 
239  printf("Input was: |");
240  j=0;
241  for (i = 0; i < 20; i++) {
242  if(j==4) {
243  printf("_");
244  j=0;
245  }
246  j++;
247 
248  printf("%02x", mk[i]);
249  }
250 
251  printf("|\nOutput was: ");
252  j=0; k=0;
253  for (i = 0; i < 160; i++) {
254  if(k==20) {
255  printf("\n ");
256  k=0;
257  j=0;
258  }
259  if(j==4) {
260  printf("_");
261  j=0;
262  }
263  k++;
264  j++;
265 
266  printf("%02x", finalkey[i]);
267  }
268  printf("\n");
269 }
270 #endif
static void onesixty_add_mod(onesixty *sum, onesixty *a, onesixty *b)
Definition: fips186prf.c:77
uint32_t state[5]
Definition: sha1.h:23
void fr_sha1_init(fr_sha1_ctx *context)
Definition: sha1.c:94
void fips186_2prf(uint8_t mk[20], uint8_t finalkey[160])
Definition: fips186prf.c:100
uint8_t p[20]
Definition: fips186prf.c:74
struct onesixty onesixty
int main(int argc, char *argv[])
Definition: radattr.c:959
#define RCSID(id)
Definition: build.h:135
void fr_sha1_final_no_len(uint8_t digest[20], fr_sha1_ctx *context)
Definition: sha1.c:165
void fr_sha1_transform(uint32_t state[5], uint8_t const buffer[64])
Definition: sha1.c:36