security/nss/lib/freebl/tlsprfalg.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* tlsprfalg.c - TLS Pseudo Random Function (PRF) implementation
     2  *
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #ifdef FREEBL_NO_DEPEND
     8 #include "stubs.h"
     9 #endif
    11 #include "blapi.h"
    12 #include "hasht.h"
    13 #include "alghmac.h"
    16 #define PHASH_STATE_MAX_LEN HASH_LENGTH_MAX
    18 /* TLS P_hash function */
    19 SECStatus
    20 TLS_P_hash(HASH_HashType hashType, const SECItem *secret, const char *label, 
    21 	SECItem *seed, SECItem *result, PRBool isFIPS)
    22 {
    23     unsigned char state[PHASH_STATE_MAX_LEN];
    24     unsigned char outbuf[PHASH_STATE_MAX_LEN];
    25     unsigned int state_len = 0, label_len = 0, outbuf_len = 0, chunk_size;
    26     unsigned int remaining;
    27     unsigned char *res;
    28     SECStatus status;
    29     HMACContext *cx;
    30     SECStatus rv = SECFailure;
    31     const SECHashObject *hashObj = HASH_GetRawHashObject(hashType);
    33     PORT_Assert((secret != NULL) && (secret->data != NULL || !secret->len));
    34     PORT_Assert((seed != NULL) && (seed->data != NULL));
    35     PORT_Assert((result != NULL) && (result->data != NULL));
    37     remaining = result->len;
    38     res = result->data;
    40     if (label != NULL)
    41 	label_len = PORT_Strlen(label);
    43     cx = HMAC_Create(hashObj, secret->data, secret->len, isFIPS);
    44     if (cx == NULL)
    45 	goto loser;
    47     /* initialize the state = A(1) = HMAC_hash(secret, seed) */
    48     HMAC_Begin(cx);
    49     HMAC_Update(cx, (unsigned char *)label, label_len);
    50     HMAC_Update(cx, seed->data, seed->len);
    51     status = HMAC_Finish(cx, state, &state_len, sizeof(state));
    52     if (status != SECSuccess)
    53 	goto loser;
    55     /* generate a block at a time until we're done */
    56     while (remaining > 0) {
    58 	HMAC_Begin(cx);
    59 	HMAC_Update(cx, state, state_len);
    60 	if (label_len)
    61 	    HMAC_Update(cx, (unsigned char *)label, label_len);
    62 	HMAC_Update(cx, seed->data, seed->len);
    63 	status = HMAC_Finish(cx, outbuf, &outbuf_len, sizeof(outbuf));
    64 	if (status != SECSuccess)
    65 	    goto loser;
    67         /* Update the state = A(i) = HMAC_hash(secret, A(i-1)) */
    68 	HMAC_Begin(cx); 
    69 	HMAC_Update(cx, state, state_len); 
    70 	status = HMAC_Finish(cx, state, &state_len, sizeof(state));
    71 	if (status != SECSuccess)
    72 	    goto loser;
    74 	chunk_size = PR_MIN(outbuf_len, remaining);
    75 	PORT_Memcpy(res, &outbuf, chunk_size);
    76 	res += chunk_size;
    77 	remaining -= chunk_size;
    78     }
    80     rv = SECSuccess;
    82 loser:
    83     /* clear out state so it's not left on the stack */
    84     if (cx) 
    85     	HMAC_Destroy(cx, PR_TRUE);
    86     PORT_Memset(state, 0, sizeof(state));
    87     PORT_Memset(outbuf, 0, sizeof(outbuf));
    88     return rv;
    89 }
    91 SECStatus
    92 TLS_PRF(const SECItem *secret, const char *label, SECItem *seed, 
    93          SECItem *result, PRBool isFIPS)
    94 {
    95     SECStatus rv = SECFailure, status;
    96     unsigned int i;
    97     SECItem tmp = { siBuffer, NULL, 0};
    98     SECItem S1;
    99     SECItem S2;
   101     PORT_Assert((secret != NULL) && (secret->data != NULL || !secret->len));
   102     PORT_Assert((seed != NULL) && (seed->data != NULL));
   103     PORT_Assert((result != NULL) && (result->data != NULL));
   105     S1.type = siBuffer;
   106     S1.len  = (secret->len / 2) + (secret->len & 1);
   107     S1.data = secret->data;
   109     S2.type = siBuffer;
   110     S2.len  = S1.len;
   111     S2.data = secret->data + (secret->len - S2.len);
   113     tmp.data = (unsigned char*)PORT_Alloc(result->len);
   114     if (tmp.data == NULL)
   115 	goto loser;
   116     tmp.len = result->len;
   118     status = TLS_P_hash(HASH_AlgMD5, &S1, label, seed, result, isFIPS);
   119     if (status != SECSuccess)
   120 	goto loser;
   122     status = TLS_P_hash(HASH_AlgSHA1, &S2, label, seed, &tmp, isFIPS);
   123     if (status != SECSuccess)
   124 	goto loser;
   126     for (i = 0; i < result->len; i++)
   127 	result->data[i] ^= tmp.data[i];
   129     rv = SECSuccess;
   131 loser:
   132     if (tmp.data != NULL)
   133 	PORT_ZFree(tmp.data, tmp.len);
   134     return rv;
   135 }

mercurial