| OLD | NEW |
| (Empty) |
| 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/. */ | |
| 6 /* $Id: tlsprfalg.c,v 1.9 2012/06/26 22:27:29 rrelyea%redhat.com Exp $ */ | |
| 7 | |
| 8 #ifdef FREEBL_NO_DEPEND | |
| 9 #include "stubs.h" | |
| 10 #endif | |
| 11 | |
| 12 #include "blapi.h" | |
| 13 #include "hasht.h" | |
| 14 #include "alghmac.h" | |
| 15 | |
| 16 | |
| 17 #define PHASH_STATE_MAX_LEN HASH_LENGTH_MAX | |
| 18 | |
| 19 /* TLS P_hash function */ | |
| 20 SECStatus | |
| 21 TLS_P_hash(HASH_HashType hashType, const SECItem *secret, const char *label, | |
| 22 SECItem *seed, SECItem *result, PRBool isFIPS) | |
| 23 { | |
| 24 unsigned char state[PHASH_STATE_MAX_LEN]; | |
| 25 unsigned char outbuf[PHASH_STATE_MAX_LEN]; | |
| 26 unsigned int state_len = 0, label_len = 0, outbuf_len = 0, chunk_size; | |
| 27 unsigned int remaining; | |
| 28 unsigned char *res; | |
| 29 SECStatus status; | |
| 30 HMACContext *cx; | |
| 31 SECStatus rv = SECFailure; | |
| 32 const SECHashObject *hashObj = HASH_GetRawHashObject(hashType); | |
| 33 | |
| 34 PORT_Assert((secret != NULL) && (secret->data != NULL || !secret->len)); | |
| 35 PORT_Assert((seed != NULL) && (seed->data != NULL)); | |
| 36 PORT_Assert((result != NULL) && (result->data != NULL)); | |
| 37 | |
| 38 remaining = result->len; | |
| 39 res = result->data; | |
| 40 | |
| 41 if (label != NULL) | |
| 42 label_len = PORT_Strlen(label); | |
| 43 | |
| 44 cx = HMAC_Create(hashObj, secret->data, secret->len, isFIPS); | |
| 45 if (cx == NULL) | |
| 46 goto loser; | |
| 47 | |
| 48 /* initialize the state = A(1) = HMAC_hash(secret, seed) */ | |
| 49 HMAC_Begin(cx); | |
| 50 HMAC_Update(cx, (unsigned char *)label, label_len); | |
| 51 HMAC_Update(cx, seed->data, seed->len); | |
| 52 status = HMAC_Finish(cx, state, &state_len, sizeof(state)); | |
| 53 if (status != SECSuccess) | |
| 54 goto loser; | |
| 55 | |
| 56 /* generate a block at a time until we're done */ | |
| 57 while (remaining > 0) { | |
| 58 | |
| 59 HMAC_Begin(cx); | |
| 60 HMAC_Update(cx, state, state_len); | |
| 61 if (label_len) | |
| 62 HMAC_Update(cx, (unsigned char *)label, label_len); | |
| 63 HMAC_Update(cx, seed->data, seed->len); | |
| 64 status = HMAC_Finish(cx, outbuf, &outbuf_len, sizeof(outbuf)); | |
| 65 if (status != SECSuccess) | |
| 66 goto loser; | |
| 67 | |
| 68 /* Update the state = A(i) = HMAC_hash(secret, A(i-1)) */ | |
| 69 HMAC_Begin(cx); | |
| 70 HMAC_Update(cx, state, state_len); | |
| 71 status = HMAC_Finish(cx, state, &state_len, sizeof(state)); | |
| 72 if (status != SECSuccess) | |
| 73 goto loser; | |
| 74 | |
| 75 chunk_size = PR_MIN(outbuf_len, remaining); | |
| 76 PORT_Memcpy(res, &outbuf, chunk_size); | |
| 77 res += chunk_size; | |
| 78 remaining -= chunk_size; | |
| 79 } | |
| 80 | |
| 81 rv = SECSuccess; | |
| 82 | |
| 83 loser: | |
| 84 /* clear out state so it's not left on the stack */ | |
| 85 if (cx) | |
| 86 HMAC_Destroy(cx, PR_TRUE); | |
| 87 PORT_Memset(state, 0, sizeof(state)); | |
| 88 PORT_Memset(outbuf, 0, sizeof(outbuf)); | |
| 89 return rv; | |
| 90 } | |
| 91 | |
| 92 SECStatus | |
| 93 TLS_PRF(const SECItem *secret, const char *label, SECItem *seed, | |
| 94 SECItem *result, PRBool isFIPS) | |
| 95 { | |
| 96 SECStatus rv = SECFailure, status; | |
| 97 unsigned int i; | |
| 98 SECItem tmp = { siBuffer, NULL, 0}; | |
| 99 SECItem S1; | |
| 100 SECItem S2; | |
| 101 | |
| 102 PORT_Assert((secret != NULL) && (secret->data != NULL || !secret->len)); | |
| 103 PORT_Assert((seed != NULL) && (seed->data != NULL)); | |
| 104 PORT_Assert((result != NULL) && (result->data != NULL)); | |
| 105 | |
| 106 S1.type = siBuffer; | |
| 107 S1.len = (secret->len / 2) + (secret->len & 1); | |
| 108 S1.data = secret->data; | |
| 109 | |
| 110 S2.type = siBuffer; | |
| 111 S2.len = S1.len; | |
| 112 S2.data = secret->data + (secret->len - S2.len); | |
| 113 | |
| 114 tmp.data = (unsigned char*)PORT_Alloc(result->len); | |
| 115 if (tmp.data == NULL) | |
| 116 goto loser; | |
| 117 tmp.len = result->len; | |
| 118 | |
| 119 status = TLS_P_hash(HASH_AlgMD5, &S1, label, seed, result, isFIPS); | |
| 120 if (status != SECSuccess) | |
| 121 goto loser; | |
| 122 | |
| 123 status = TLS_P_hash(HASH_AlgSHA1, &S2, label, seed, &tmp, isFIPS); | |
| 124 if (status != SECSuccess) | |
| 125 goto loser; | |
| 126 | |
| 127 for (i = 0; i < result->len; i++) | |
| 128 result->data[i] ^= tmp.data[i]; | |
| 129 | |
| 130 rv = SECSuccess; | |
| 131 | |
| 132 loser: | |
| 133 if (tmp.data != NULL) | |
| 134 PORT_ZFree(tmp.data, tmp.len); | |
| 135 return rv; | |
| 136 } | |
| 137 | |
| OLD | NEW |