| 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 | |
| 7 #ifdef FREEBL_NO_DEPEND | |
| 8 #include "stubs.h" | |
| 9 #endif | |
| 10 | |
| 11 #include "blapi.h" | |
| 12 #include "hasht.h" | |
| 13 #include "alghmac.h" | |
| 14 | |
| 15 | |
| 16 #define PHASH_STATE_MAX_LEN HASH_LENGTH_MAX | |
| 17 | |
| 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); | |
| 32 | |
| 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)); | |
| 36 | |
| 37 remaining = result->len; | |
| 38 res = result->data; | |
| 39 | |
| 40 if (label != NULL) | |
| 41 label_len = PORT_Strlen(label); | |
| 42 | |
| 43 cx = HMAC_Create(hashObj, secret->data, secret->len, isFIPS); | |
| 44 if (cx == NULL) | |
| 45 goto loser; | |
| 46 | |
| 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; | |
| 54 | |
| 55 /* generate a block at a time until we're done */ | |
| 56 while (remaining > 0) { | |
| 57 | |
| 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; | |
| 66 | |
| 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; | |
| 73 | |
| 74 chunk_size = PR_MIN(outbuf_len, remaining); | |
| 75 PORT_Memcpy(res, &outbuf, chunk_size); | |
| 76 res += chunk_size; | |
| 77 remaining -= chunk_size; | |
| 78 } | |
| 79 | |
| 80 rv = SECSuccess; | |
| 81 | |
| 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 } | |
| 90 | |
| 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; | |
| 100 | |
| 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)); | |
| 104 | |
| 105 S1.type = siBuffer; | |
| 106 S1.len = (secret->len / 2) + (secret->len & 1); | |
| 107 S1.data = secret->data; | |
| 108 | |
| 109 S2.type = siBuffer; | |
| 110 S2.len = S1.len; | |
| 111 S2.data = secret->data + (secret->len - S2.len); | |
| 112 | |
| 113 tmp.data = (unsigned char*)PORT_Alloc(result->len); | |
| 114 if (tmp.data == NULL) | |
| 115 goto loser; | |
| 116 tmp.len = result->len; | |
| 117 | |
| 118 status = TLS_P_hash(HASH_AlgMD5, &S1, label, seed, result, isFIPS); | |
| 119 if (status != SECSuccess) | |
| 120 goto loser; | |
| 121 | |
| 122 status = TLS_P_hash(HASH_AlgSHA1, &S2, label, seed, &tmp, isFIPS); | |
| 123 if (status != SECSuccess) | |
| 124 goto loser; | |
| 125 | |
| 126 for (i = 0; i < result->len; i++) | |
| 127 result->data[i] ^= tmp.data[i]; | |
| 128 | |
| 129 rv = SECSuccess; | |
| 130 | |
| 131 loser: | |
| 132 if (tmp.data != NULL) | |
| 133 PORT_ZFree(tmp.data, tmp.len); | |
| 134 return rv; | |
| 135 } | |
| 136 | |
| OLD | NEW |