security/nss/lib/softoken/tlsprf.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* tlsprf.c - TLS Pseudo Random Function (PRF) implementation
michael@0 2 *
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "pkcs11i.h"
michael@0 8 #include "blapi.h"
michael@0 9
michael@0 10 #define SFTK_OFFSETOF(str, memb) ((PRPtrdiff)(&(((str *)0)->memb)))
michael@0 11
michael@0 12 static void sftk_TLSPRFNull(void *data, PRBool freeit)
michael@0 13 {
michael@0 14 return;
michael@0 15 }
michael@0 16
michael@0 17 typedef struct {
michael@0 18 PRUint32 cxSize; /* size of allocated block, in bytes. */
michael@0 19 PRUint32 cxBufSize; /* sizeof buffer at cxBufPtr. */
michael@0 20 unsigned char *cxBufPtr; /* points to real buffer, may be cxBuf. */
michael@0 21 PRUint32 cxKeyLen; /* bytes of cxBufPtr containing key. */
michael@0 22 PRUint32 cxDataLen; /* bytes of cxBufPtr containing data. */
michael@0 23 SECStatus cxRv; /* records failure of void functions. */
michael@0 24 PRBool cxIsFIPS; /* true if conforming to FIPS 198. */
michael@0 25 HASH_HashType cxHashAlg; /* hash algorithm to use for TLS 1.2+ */
michael@0 26 unsigned char cxBuf[512]; /* actual size may be larger than 512. */
michael@0 27 } TLSPRFContext;
michael@0 28
michael@0 29 static void
michael@0 30 sftk_TLSPRFHashUpdate(TLSPRFContext *cx, const unsigned char *data,
michael@0 31 unsigned int data_len)
michael@0 32 {
michael@0 33 PRUint32 bytesUsed = cx->cxKeyLen + cx->cxDataLen;
michael@0 34
michael@0 35 if (cx->cxRv != SECSuccess) /* function has previously failed. */
michael@0 36 return;
michael@0 37 if (bytesUsed + data_len > cx->cxBufSize) {
michael@0 38 /* We don't use realloc here because
michael@0 39 ** (a) realloc doesn't zero out the old block, and
michael@0 40 ** (b) if realloc fails, we lose the old block.
michael@0 41 */
michael@0 42 PRUint32 newBufSize = bytesUsed + data_len + 512;
michael@0 43 unsigned char * newBuf = (unsigned char *)PORT_Alloc(newBufSize);
michael@0 44 if (!newBuf) {
michael@0 45 cx->cxRv = SECFailure;
michael@0 46 return;
michael@0 47 }
michael@0 48 PORT_Memcpy(newBuf, cx->cxBufPtr, bytesUsed);
michael@0 49 if (cx->cxBufPtr != cx->cxBuf) {
michael@0 50 PORT_ZFree(cx->cxBufPtr, bytesUsed);
michael@0 51 }
michael@0 52 cx->cxBufPtr = newBuf;
michael@0 53 cx->cxBufSize = newBufSize;
michael@0 54 }
michael@0 55 PORT_Memcpy(cx->cxBufPtr + bytesUsed, data, data_len);
michael@0 56 cx->cxDataLen += data_len;
michael@0 57 }
michael@0 58
michael@0 59 static void
michael@0 60 sftk_TLSPRFEnd(TLSPRFContext *ctx, unsigned char *hashout,
michael@0 61 unsigned int *pDigestLen, unsigned int maxDigestLen)
michael@0 62 {
michael@0 63 *pDigestLen = 0; /* tells Verify that no data has been input yet. */
michael@0 64 }
michael@0 65
michael@0 66 /* Compute the PRF values from the data previously input. */
michael@0 67 static SECStatus
michael@0 68 sftk_TLSPRFUpdate(TLSPRFContext *cx,
michael@0 69 unsigned char *sig, /* output goes here. */
michael@0 70 unsigned int * sigLen, /* how much output. */
michael@0 71 unsigned int maxLen, /* output buffer size */
michael@0 72 unsigned char *hash, /* unused. */
michael@0 73 unsigned int hashLen) /* unused. */
michael@0 74 {
michael@0 75 SECStatus rv;
michael@0 76 SECItem sigItem;
michael@0 77 SECItem seedItem;
michael@0 78 SECItem secretItem;
michael@0 79
michael@0 80 if (cx->cxRv != SECSuccess)
michael@0 81 return cx->cxRv;
michael@0 82
michael@0 83 secretItem.data = cx->cxBufPtr;
michael@0 84 secretItem.len = cx->cxKeyLen;
michael@0 85
michael@0 86 seedItem.data = cx->cxBufPtr + cx->cxKeyLen;
michael@0 87 seedItem.len = cx->cxDataLen;
michael@0 88
michael@0 89 sigItem.data = sig;
michael@0 90 sigItem.len = maxLen;
michael@0 91
michael@0 92 if (cx->cxHashAlg != HASH_AlgNULL) {
michael@0 93 rv = TLS_P_hash(cx->cxHashAlg, &secretItem, NULL, &seedItem, &sigItem,
michael@0 94 cx->cxIsFIPS);
michael@0 95 } else {
michael@0 96 rv = TLS_PRF(&secretItem, NULL, &seedItem, &sigItem, cx->cxIsFIPS);
michael@0 97 }
michael@0 98 if (rv == SECSuccess && sigLen != NULL)
michael@0 99 *sigLen = sigItem.len;
michael@0 100 return rv;
michael@0 101
michael@0 102 }
michael@0 103
michael@0 104 static SECStatus
michael@0 105 sftk_TLSPRFVerify(TLSPRFContext *cx,
michael@0 106 unsigned char *sig, /* input, for comparison. */
michael@0 107 unsigned int sigLen, /* length of sig. */
michael@0 108 unsigned char *hash, /* data to be verified. */
michael@0 109 unsigned int hashLen) /* size of hash data. */
michael@0 110 {
michael@0 111 unsigned char * tmp = (unsigned char *)PORT_Alloc(sigLen);
michael@0 112 unsigned int tmpLen = sigLen;
michael@0 113 SECStatus rv;
michael@0 114
michael@0 115 if (!tmp)
michael@0 116 return SECFailure;
michael@0 117 if (hashLen) {
michael@0 118 /* hashLen is non-zero when the user does a one-step verify.
michael@0 119 ** In this case, none of the data has been input yet.
michael@0 120 */
michael@0 121 sftk_TLSPRFHashUpdate(cx, hash, hashLen);
michael@0 122 }
michael@0 123 rv = sftk_TLSPRFUpdate(cx, tmp, &tmpLen, sigLen, NULL, 0);
michael@0 124 if (rv == SECSuccess) {
michael@0 125 rv = (SECStatus)(1 - !PORT_Memcmp(tmp, sig, sigLen));
michael@0 126 }
michael@0 127 PORT_ZFree(tmp, sigLen);
michael@0 128 return rv;
michael@0 129 }
michael@0 130
michael@0 131 static void
michael@0 132 sftk_TLSPRFHashDestroy(TLSPRFContext *cx, PRBool freeit)
michael@0 133 {
michael@0 134 if (freeit) {
michael@0 135 if (cx->cxBufPtr != cx->cxBuf)
michael@0 136 PORT_ZFree(cx->cxBufPtr, cx->cxBufSize);
michael@0 137 PORT_ZFree(cx, cx->cxSize);
michael@0 138 }
michael@0 139 }
michael@0 140
michael@0 141 CK_RV
michael@0 142 sftk_TLSPRFInit(SFTKSessionContext *context,
michael@0 143 SFTKObject * key,
michael@0 144 CK_KEY_TYPE key_type,
michael@0 145 HASH_HashType hash_alg)
michael@0 146 {
michael@0 147 SFTKAttribute * keyVal;
michael@0 148 TLSPRFContext * prf_cx;
michael@0 149 CK_RV crv = CKR_HOST_MEMORY;
michael@0 150 PRUint32 keySize;
michael@0 151 PRUint32 blockSize;
michael@0 152
michael@0 153 if (key_type != CKK_GENERIC_SECRET)
michael@0 154 return CKR_KEY_TYPE_INCONSISTENT; /* CKR_KEY_FUNCTION_NOT_PERMITTED */
michael@0 155
michael@0 156 context->multi = PR_TRUE;
michael@0 157
michael@0 158 keyVal = sftk_FindAttribute(key, CKA_VALUE);
michael@0 159 keySize = (!keyVal) ? 0 : keyVal->attrib.ulValueLen;
michael@0 160 blockSize = keySize + sizeof(TLSPRFContext);
michael@0 161 prf_cx = (TLSPRFContext *)PORT_Alloc(blockSize);
michael@0 162 if (!prf_cx)
michael@0 163 goto done;
michael@0 164 prf_cx->cxSize = blockSize;
michael@0 165 prf_cx->cxKeyLen = keySize;
michael@0 166 prf_cx->cxDataLen = 0;
michael@0 167 prf_cx->cxBufSize = blockSize - SFTK_OFFSETOF(TLSPRFContext, cxBuf);
michael@0 168 prf_cx->cxRv = SECSuccess;
michael@0 169 prf_cx->cxIsFIPS = (key->slot->slotID == FIPS_SLOT_ID);
michael@0 170 prf_cx->cxBufPtr = prf_cx->cxBuf;
michael@0 171 prf_cx->cxHashAlg = hash_alg;
michael@0 172 if (keySize)
michael@0 173 PORT_Memcpy(prf_cx->cxBufPtr, keyVal->attrib.pValue, keySize);
michael@0 174
michael@0 175 context->hashInfo = (void *) prf_cx;
michael@0 176 context->cipherInfo = (void *) prf_cx;
michael@0 177 context->hashUpdate = (SFTKHash) sftk_TLSPRFHashUpdate;
michael@0 178 context->end = (SFTKEnd) sftk_TLSPRFEnd;
michael@0 179 context->update = (SFTKCipher) sftk_TLSPRFUpdate;
michael@0 180 context->verify = (SFTKVerify) sftk_TLSPRFVerify;
michael@0 181 context->destroy = (SFTKDestroy) sftk_TLSPRFNull;
michael@0 182 context->hashdestroy = (SFTKDestroy) sftk_TLSPRFHashDestroy;
michael@0 183 crv = CKR_OK;
michael@0 184
michael@0 185 done:
michael@0 186 if (keyVal)
michael@0 187 sftk_FreeAttribute(keyVal);
michael@0 188 return crv;
michael@0 189 }
michael@0 190

mercurial