File Coverage

inc/matrixssl-3-9-3-open/matrixssl/prf.c
Criterion Covered Total %
statement 40 124 32.2
branch 24 80 30.0
condition n/a
subroutine n/a
pod n/a
total 64 204 31.3


line stmt bran cond sub pod time code
1             /**
2             * @file prf.c
3             * @version 950bba4 (HEAD -> master)
4             *
5             * "Native" Pseudo Random Function.
6             */
7             /*
8             * Copyright (c) 2013-2017 INSIDE Secure Corporation
9             * Copyright (c) PeerSec Networks, 2002-2011
10             * All Rights Reserved
11             *
12             * The latest version of this code is available at http://www.matrixssl.org
13             *
14             * This software is open source; 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 General Public License does NOT permit incorporating this software
20             * into proprietary programs. If you are unable to comply with the GPL, a
21             * commercial license for this software may be purchased from INSIDE at
22             * http://www.insidesecure.com/
23             *
24             * This program is distributed in WITHOUT ANY WARRANTY; without even the
25             * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
26             * See the GNU General Public License for more details.
27             *
28             * You should have received a copy of the GNU General Public License
29             * along with this program; if not, write to the Free Software
30             * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31             * http://www.gnu.org/copyleft/gpl.html
32             */
33             /******************************************************************************/
34              
35             #include "matrixsslImpl.h"
36              
37             #if defined(USE_TLS_PRF) || defined(USE_TLS_PRF2)
38              
39             # ifdef USE_TLS_PRF
40             int32_t prf(const unsigned char *sec, psSize_t secLen,
41             const unsigned char *seed, psSize_t seedLen,
42             unsigned char *out, psSize_t outLen)
43             {
44             return psPrf(sec, secLen, seed, seedLen, out, outLen);
45             }
46             # endif
47              
48             # ifdef USE_TLS_PRF2
49             int32_t prf2(const unsigned char *sec, psSize_t secLen,
50             const unsigned char *seed, psSize_t seedLen,
51             unsigned char *out, psSize_t outLen, uint32_t flags)
52             {
53             return psPrf2(sec, secLen, seed, seedLen, out, outLen,
54             (flags & CRYPTO_FLAGS_SHA3) ?
55             SHA384_HASH_SIZE : SHA256_HASH_SIZE);
56             }
57             # endif
58              
59             #else
60              
61             # if defined(USE_NATIVE_TLS_ALGS) || defined(USE_NATIVE_TLS_HS_HASH)
62             # ifdef USE_TLS
63             # ifndef USE_ONLY_TLS_1_2
64             /******************************************************************************/
65             /*
66             MD5 portions of the prf
67             */
68 0           __inline static int32_t pMd5(const unsigned char *key, psSize_t keyLen,
69             const unsigned char *text, psSize_t textLen,
70             unsigned char *out, psSize_t outLen)
71             {
72             psHmacMd5_t ctx;
73             unsigned char a[MD5_HASH_SIZE];
74             unsigned char mac[MD5_HASH_SIZE];
75             unsigned char hmacKey[MD5_HASH_SIZE];
76 0           int32_t rc = PS_FAIL;
77             psSize_t hmacKeyLen, i, keyIter;
78              
79 0 0         for (keyIter = 1; (uint16_t) (MD5_HASH_SIZE * keyIter) < outLen; )
80             {
81 0           keyIter++;
82             }
83 0 0         if ((rc = psHmacMd5(key, keyLen, text, textLen, a,
84             hmacKey, &hmacKeyLen)) < 0)
85             {
86 0           goto L_RETURN;
87             }
88 0 0         if (hmacKeyLen != keyLen)
89             {
90             /*
91             Support for keys larger than 64 bytes. Must take the hash of
92             the original key in these cases which is indicated by different
93             outgoing values from the passed in key and keyLen values
94             */
95 0 0         psAssert(keyLen > 64);
96             /* Typecast is OK, we don't update key below */
97 0           key = (const unsigned char *) hmacKey;
98 0           keyLen = hmacKeyLen;
99             }
100 0 0         for (i = 0; i < keyIter; i++)
101             {
102 0 0         if ((rc = psHmacMd5Init(&ctx, key, keyLen)) < 0)
103             {
104 0           goto L_RETURN;
105             }
106 0           psHmacMd5Update(&ctx, a, MD5_HASH_SIZE);
107 0           psHmacMd5Update(&ctx, text, textLen);
108 0           psHmacMd5Final(&ctx, mac);
109 0 0         if (i == keyIter - 1)
110             {
111 0           memcpy(out + (MD5_HASH_SIZE * i), mac, outLen - (MD5_HASH_SIZE * i));
112             }
113             else
114             {
115 0           memcpy(out + (MD5_HASH_SIZE * i), mac, MD5_HASH_SIZE);
116 0 0         if ((rc = psHmacMd5(key, keyLen, a, MD5_HASH_SIZE, a,
117             hmacKey, &hmacKeyLen)) < 0)
118             {
119 0           goto L_RETURN;
120             }
121             }
122             }
123 0           rc = PS_SUCCESS;
124             L_RETURN:
125 0           memzero_s(a, MD5_HASH_SIZE);
126 0           memzero_s(mac, MD5_HASH_SIZE);
127 0           memzero_s(hmacKey, MD5_HASH_SIZE);
128 0 0         if (rc < 0)
129             {
130 0           memzero_s(out, outLen); /* zero any partial result on error */
131             }
132 0           return rc;
133             }
134              
135             /******************************************************************************/
136             /*
137             SHA1 portion of the prf
138             */
139 0           __inline static int32_t pSha1(const unsigned char *key, psSize_t keyLen,
140             const unsigned char *text, psSize_t textLen,
141             unsigned char *out, psSize_t outLen)
142             {
143             psHmacSha1_t ctx;
144             unsigned char a[SHA1_HASH_SIZE];
145             unsigned char mac[SHA1_HASH_SIZE];
146             unsigned char hmacKey[SHA1_HASH_SIZE];
147 0           int32_t rc = PS_FAIL;
148             psSize_t hmacKeyLen, i, keyIter;
149              
150 0 0         for (keyIter = 1; (uint16_t) (SHA1_HASH_SIZE * keyIter) < outLen; )
151             {
152 0           keyIter++;
153             }
154 0 0         if ((rc = psHmacSha1(key, keyLen, text, textLen, a,
155             hmacKey, &hmacKeyLen)) < 0)
156             {
157 0           goto L_RETURN;
158             }
159 0 0         if (hmacKeyLen != keyLen)
160             {
161             /*
162             Support for keys larger than 64 bytes. Must take the hash of
163             the original key in these cases which is indicated by different
164             outgoing values from the passed in key and keyLen values
165             */
166 0 0         psAssert(keyLen > 64);
167             /* Typecast is OK, we don't update key below */
168 0           key = (const unsigned char *) hmacKey;
169 0           keyLen = hmacKeyLen;
170             }
171 0 0         for (i = 0; i < keyIter; i++)
172             {
173 0 0         if ((rc = psHmacSha1Init(&ctx, key, keyLen)) < 0)
174             {
175 0           goto L_RETURN;
176             }
177 0           psHmacSha1Update(&ctx, a, SHA1_HASH_SIZE);
178 0           psHmacSha1Update(&ctx, text, textLen);
179 0           psHmacSha1Final(&ctx, mac);
180 0 0         if (i == keyIter - 1)
181             {
182 0           memcpy(out + (SHA1_HASH_SIZE * i), mac,
183 0           outLen - (SHA1_HASH_SIZE * i));
184             }
185             else
186             {
187 0           memcpy(out + (SHA1_HASH_SIZE * i), mac, SHA1_HASH_SIZE);
188 0 0         if ((rc = psHmacSha1(key, keyLen, a, SHA1_HASH_SIZE, a,
189             hmacKey, &hmacKeyLen)) < 0)
190             {
191 0           goto L_RETURN;
192             }
193             }
194             }
195 0           rc = PS_SUCCESS;
196             L_RETURN:
197 0           memzero_s(a, SHA1_HASH_SIZE);
198 0           memzero_s(mac, SHA1_HASH_SIZE);
199 0           memzero_s(hmacKey, SHA1_HASH_SIZE);
200 0 0         if (rc < 0)
201             {
202 0           memzero_s(out, outLen); /* zero any partial result on error */
203             }
204 0           return rc;
205             }
206              
207             /******************************************************************************/
208             /*
209             Psuedo-random function. TLS uses this for key generation and hashing
210             */
211 0           int32_t prf(const unsigned char *sec, psSize_t secLen,
212             const unsigned char *seed, psSize_t seedLen,
213             unsigned char *out, psSize_t outLen)
214             {
215             const unsigned char *s1, *s2;
216             unsigned char md5out[SSL_MAX_KEY_BLOCK_SIZE];
217             unsigned char sha1out[SSL_MAX_KEY_BLOCK_SIZE];
218 0           int32_t rc = PS_FAIL;
219             psSize_t sLen, i;
220              
221 0 0         psAssert(outLen <= SSL_MAX_KEY_BLOCK_SIZE);
222              
223 0           sLen = (secLen / 2) + (secLen % 2);
224 0           s1 = sec;
225 0           s2 = (sec + sLen) - (secLen % 2);
226 0 0         if ((rc = pMd5(s1, sLen, seed, seedLen, md5out, outLen)) < 0)
227             {
228 0           goto L_RETURN;
229             }
230 0 0         if ((rc = pSha1(s2, sLen, seed, seedLen, sha1out, outLen)) < 0)
231             {
232 0           goto L_RETURN;
233             }
234 0 0         for (i = 0; i < outLen; i++)
235             {
236 0           out[i] = md5out[i] ^ sha1out[i];
237             }
238 0           rc = outLen;
239             L_RETURN:
240 0           memzero_s(md5out, SSL_MAX_KEY_BLOCK_SIZE);
241 0           memzero_s(sha1out, SSL_MAX_KEY_BLOCK_SIZE);
242 0           return rc;
243             }
244              
245             # endif /* !USE_ONLY_TLS_1_2 */
246              
247             # ifdef USE_TLS_1_2
248             /******************************************************************************/
249             /*
250             SHA2 prf
251             */
252 8472           __inline static int32_t pSha2(const unsigned char *key, psSize_t keyLen,
253             const unsigned char *text, psSize_t textLen,
254             unsigned char *out, psSize_t outLen, uint32_t flags)
255             {
256             /* Use a union to save a bit of stack space */
257             union
258             {
259             # ifdef USE_SHA384
260             psHmacSha384_t sha384;
261             # endif
262             psHmacSha256_t sha256;
263             } u;
264             unsigned char a[SHA384_HASH_SIZE];
265             unsigned char mac[SHA384_HASH_SIZE];
266             unsigned char hmacKey[SHA384_HASH_SIZE];
267 8472           int32_t rc = PS_FAIL;
268             psSize_t hashSize, hmacKeyLen, i, keyIter;
269              
270             # ifdef USE_SHA384
271 8472 100         if (flags & CRYPTO_FLAGS_SHA3)
272             {
273 8460           hashSize = SHA384_HASH_SIZE;
274 8460 50         if ((rc = psHmacSha384(key, keyLen, text, textLen, a,
275             hmacKey, &hmacKeyLen)) < 0)
276             {
277 0           goto L_RETURN;
278             }
279             }
280             else
281             # endif
282             {
283              
284 12           hashSize = SHA256_HASH_SIZE;
285 12 50         if ((rc = psHmacSha256(key, keyLen, text, textLen, a,
286             hmacKey, &hmacKeyLen)) < 0)
287             {
288 0           goto L_RETURN;
289             }
290             }
291 10600 100         for (keyIter = 1; (uint16_t) (hashSize * keyIter) < outLen; )
292             {
293 2128           keyIter++;
294             }
295 8472 50         if (hmacKeyLen != keyLen)
296             {
297             /*
298             Support for keys larger than 64 bytes. Must take the hash of
299             the original key in these cases which is indicated by different
300             outgoing values from the passed in key and keyLen values
301             */
302 0 0         psAssert(keyLen > 64);
303             /* Typecast is OK, we don't update key below */
304 0           key = (const unsigned char *) hmacKey;
305 0           keyLen = hmacKeyLen;
306             }
307 19072 100         for (i = 0; i < keyIter; i++)
308             {
309             # ifdef USE_SHA384
310 10600 100         if (flags & CRYPTO_FLAGS_SHA3)
311             {
312 10576 50         if ((rc = psHmacSha384Init(&u.sha384, key, keyLen)) < 0)
313             {
314 0           goto L_RETURN;
315             }
316 10576           psHmacSha384Update(&u.sha384, a, hashSize);
317 10576           psHmacSha384Update(&u.sha384, text, textLen);
318 10576           psHmacSha384Final(&u.sha384, mac);
319             }
320             else
321             # endif
322             {
323 24 50         if ((rc = psHmacSha256Init(&u.sha256, key, keyLen)) < 0)
324             {
325 0           goto L_RETURN;
326             }
327 24           psHmacSha256Update(&u.sha256, a, hashSize);
328 24           psHmacSha256Update(&u.sha256, text, textLen);
329 24           psHmacSha256Final(&u.sha256, mac);
330             }
331 10600 100         if (i == keyIter - 1)
332             {
333 8472           memcpy(out + (hashSize * i), mac,
334 8472           outLen - ((uint32_t) hashSize * i));
335             }
336             else
337             {
338 2128           memcpy(out + ((uint32_t) hashSize * i), mac, hashSize);
339             # ifdef USE_SHA384
340 2128 100         if (flags & CRYPTO_FLAGS_SHA3)
341             {
342 2116 50         if ((rc = psHmacSha384(key, keyLen, a, hashSize, a,
343             hmacKey, &hmacKeyLen)) < 0)
344             {
345 0           goto L_RETURN;
346             }
347             }
348             else
349             # endif
350             {
351 12 50         if ((rc = psHmacSha256(key, keyLen, a, hashSize, a,
352             hmacKey, &hmacKeyLen)) < 0)
353             {
354 0           goto L_RETURN;
355             }
356             }
357             }
358             }
359 8472           rc = PS_SUCCESS;
360             L_RETURN:
361 8472           memzero_s(a, SHA384_HASH_SIZE);
362 8472           memzero_s(mac, SHA384_HASH_SIZE);
363 8472           memzero_s(hmacKey, SHA384_HASH_SIZE);
364 8472 50         if (rc < 0)
365             {
366 0           memzero_s(out, outLen); /* zero any partial result on error */
367             }
368 8472           return rc;
369             }
370              
371             /******************************************************************************/
372             /*
373             Psuedo-random function. TLS uses this for key generation and hashing
374             */
375 8472           int32_t prf2(const unsigned char *sec, psSize_t secLen,
376             const unsigned char *seed, psSize_t seedLen,
377             unsigned char *out, psSize_t outLen, uint32_t flags)
378             {
379             unsigned char sha2out[SSL_MAX_KEY_BLOCK_SIZE];
380             int32_t rc;
381             uint16_t i;
382              
383 8472 50         psAssert(outLen <= SSL_MAX_KEY_BLOCK_SIZE);
384              
385 8472 50         if ((rc = pSha2(sec, secLen, seed, seedLen, sha2out, outLen, flags)) < 0)
386             {
387 0           return rc;
388             }
389             /* Copy out of tmp buffer because outLen typically less than multiple of
390             prf block size */
391 313512 100         for (i = 0; i < outLen; i++)
392             {
393 305040           out[i] = sha2out[i];
394             }
395 8472           memzero_s(sha2out, SSL_MAX_KEY_BLOCK_SIZE);
396 8472           return outLen;
397             }
398             # endif /* USE_TLS_1_2 */
399              
400             # ifdef USE_EAP_FAST
401             /******************************************************************************/
402             /**
403             EAP-FAST T-PRF function.
404             This proprietary EAP protocol uses TLS to establish a session, but
405             defines a modified SessionTicket mechansism that alters the generation
406             of the TLS master secret.
407             @see https://tools.ietf.org/html/rfc4851#section-5.5
408              
409             @param[in] key The PAC-Key, a shared secret provisioned out of band.
410             @param[in] keyLen The length in bytes of PAC-Key.
411             @param[in] seed The seed used for TLS master_secret generation.
412             @param[in] seedLen For TLS this is always 64 bytes (server_random[32]
413             + client_random[32])
414             @param[out] out The derived master_secret.
415             @return < on error. SSL_HS_MASTER_SIZE on success.
416              
417             */
418             int32_t tprf(const unsigned char *key, psSize_t keyLen,
419             const unsigned char *seed, psSize_t seedLen,
420             unsigned char out[SSL_HS_MASTER_SIZE])
421             {
422             /** @note The 32 byte label includes the null terminator byte */
423             static const unsigned char TPRF_LABEL[32] =
424             "PAC to master secret label hash";
425              
426             psHmacSha1_t ctx;
427             int32_t rc = PS_FAIL;
428             unsigned char sha1out[SHA1_HASH_SIZE];
429             unsigned char olen_iter[3]; /* outputlength[2] + iteration[1] */
430              
431             psAssert(seedLen == (SSL_HS_RANDOM_SIZE * 2));
432              
433             /**
434             The first 20 bytes are generated as follows.
435             T1 = HMAC-SHA1 (key, S + outputlength + 0x01)
436             S = label + 0x00 + seed
437             'label' is 31 bytes of [PAC to master secret label hash] and a
438             null byte (32 bytes total)
439             'seed' as provided is server_random[32] + client_random[32]
440             outputlength is a 2 byte big endian length of the output,
441             always 48 bytes in TLS case.
442             For our use, we simplify the above as:
443             T1 = HMAC-SHA1 (key, label_with_0x0 + seed + 0x00 + 0x30 + 0x01
444             */
445             olen_iter[0] = 0x0; /* = ((outputlength >> 8) & 0xFF); */
446             olen_iter[1] = SSL_HS_MASTER_SIZE; /* = (outputlength & 0xFF); */
447             olen_iter[2] = 0x01;
448             if ((rc = psHmacSha1Init(&ctx, key, keyLen)) < 0)
449             {
450             goto L_RETURN;
451             }
452             psHmacSha1Update(&ctx, TPRF_LABEL, sizeof(TPRF_LABEL)); /* Includes 0x00 byte */
453             psHmacSha1Update(&ctx, seed, seedLen);
454             psHmacSha1Update(&ctx, olen_iter, sizeof(olen_iter));
455             psHmacSha1Final(&ctx, out);
456              
457             /* T2 = HMAC-SHA1 (key, T1 + S + outputlength + 0x02) */
458             olen_iter[2] = 0x02;
459             if ((rc = psHmacSha1Init(&ctx, key, keyLen)) < 0)
460             {
461             goto L_RETURN;
462             }
463             psHmacSha1Update(&ctx, out, SHA1_HASH_SIZE);
464             psHmacSha1Update(&ctx, TPRF_LABEL, sizeof(TPRF_LABEL));
465             psHmacSha1Update(&ctx, seed, seedLen);
466             psHmacSha1Update(&ctx, olen_iter, sizeof(olen_iter));
467             psHmacSha1Final(&ctx, out + SHA1_HASH_SIZE);
468              
469             /* T3 = HMAC-SHA1 (key, T2 + S + outputlength + 0x03) */
470             olen_iter[2] = 0x03;
471             if ((rc = psHmacSha1Init(&ctx, key, keyLen)) < 0)
472             {
473             goto L_RETURN;
474             }
475             psHmacSha1Update(&ctx, out + SHA1_HASH_SIZE, SHA1_HASH_SIZE);
476             psHmacSha1Update(&ctx, TPRF_LABEL, sizeof(TPRF_LABEL));
477             psHmacSha1Update(&ctx, seed, seedLen);
478             psHmacSha1Update(&ctx, olen_iter, sizeof(olen_iter));
479             psHmacSha1Final(&ctx, sha1out);
480              
481             /* Copy the first 8 bytes from T3 to out, making 48 bytes total */
482             memcpy(out + (2 * SHA1_HASH_SIZE), sha1out, 8);
483             rc = SSL_HS_MASTER_SIZE;
484             L_RETURN:
485             memzero_s(sha1out, sizeof(sha1out));
486             if (rc < 0)
487             {
488             memzero_s(out, SSL_HS_MASTER_SIZE); /* zero any partial result on error */
489             }
490             return rc;
491             }
492             # endif /* USE_EAP_FAST */
493             # endif /* USE_TLS */
494             # endif /* USE_NATIVE_TLS_ALGS || USE_NATIVE_TLS_HS_HASH */
495             #endif /* USE_TLS_PRF || USE_TLS_PRF2 */
496             /******************************************************************************/
497