Move the TLS Pseudo Random Function (PRF) and the HMAC algorithm from

softoken to freebl.  Bug 303316. r=wtchang (with suggested changes)
Modified Files:
	freebl/blapi.h freebl/ldvector.c freebl/loader.c
	freebl/loader.h freebl/manifest.mn softoken/lowpbe.c
	softoken/manifest.mn softoken/pkcs11c.c softoken/pkcs11i.h
	softoken/tlsprf.c
Added Files:
	freebl/alghmac.c freebl/alghmac.h freebl/rawhash.c
	freebl/tlsprfalg.c
Removed Files:
	softoken/alghmac.c softoken/alghmac.h softoken/rawhash.c
This commit is contained in:
nelsonb%netscape.com 2005-08-06 09:27:28 +00:00
parent 9a8510d59b
commit 1f607bc371
14 changed files with 306 additions and 145 deletions

View File

@ -37,13 +37,14 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: blapi.h,v 1.19 2005/08/06 07:24:21 nelsonb%netscape.com Exp $ */
/* $Id: blapi.h,v 1.20 2005/08/06 09:27:28 nelsonb%netscape.com Exp $ */
#ifndef _BLAPI_H_
#define _BLAPI_H_
#include "blapit.h"
#include "hasht.h"
#include "alghmac.h"
SEC_BEGIN_PROTOS
@ -939,6 +940,14 @@ extern SECStatus SHA384_Flatten(SHA384Context *cx,unsigned char *space);
extern SHA384Context * SHA384_Resurrect(unsigned char *space, void *arg);
extern void SHA384_Clone(SHA384Context *dest, SHA384Context *src);
/****************************************
* implement TLS Pseudo Random Function (PRF)
*/
extern SECStatus
TLS_PRF(const SECItem *secret, const char *label, SECItem *seed,
SECItem *result, PRBool isFIPS);
/******************************************/
/*
** Pseudo Random Number Generation. FIPS compliance desirable.
@ -1044,6 +1053,9 @@ PRBool BLAPI_SHVerify(const char *name, PRFuncPtr addr);
**************************************************************************/
PRBool BLAPI_VerifySelf(const char *name);
/*********************************************************************/
extern const SECHashObject * SEC_GetRawHashObject(HASH_HashType hashType);
SEC_END_PROTOS
#endif /* _BLAPI_H_ */

View File

@ -37,9 +37,10 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: ldvector.c,v 1.9 2005/08/06 07:24:21 nelsonb%netscape.com Exp $ */
/* $Id: ldvector.c,v 1.10 2005/08/06 09:27:28 nelsonb%netscape.com Exp $ */
#include "loader.h"
#include "alghmac.h"
static const struct FREEBLVectorStr vector =
{
@ -207,6 +208,17 @@ static const struct FREEBLVectorStr vector =
SHA384_Clone,
SHA512_Clone,
TLS_PRF,
SEC_GetRawHashObject,
HMAC_Destroy,
HMAC_Create,
HMAC_Init,
HMAC_Begin,
HMAC_Update,
HMAC_Finish,
HMAC_Clone,
/* End of Version 3.008. */
};

View File

@ -37,7 +37,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: loader.c,v 1.19 2005/08/06 07:24:21 nelsonb%netscape.com Exp $ */
/* $Id: loader.c,v 1.20 2005/08/06 09:27:28 nelsonb%netscape.com Exp $ */
#include "loader.h"
#include "prmem.h"
@ -1489,3 +1489,81 @@ SHA512_Clone(SHA512Context *dest, SHA512Context *src)
return;
(vector->p_SHA512_Clone)(dest, src);
}
SECStatus
TLS_PRF(const SECItem *secret, const char *label,
SECItem *seed, SECItem *result, PRBool isFIPS)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return SECFailure;
return (vector->p_TLS_PRF)(secret, label, seed, result, isFIPS);
}
const SECHashObject *
SEC_GetRawHashObject(HASH_HashType hashType)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return NULL;
return (vector->p_SEC_GetRawHashObject)(hashType);
}
void
HMAC_Destroy(HMACContext *cx)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return;
(vector->p_HMAC_Destroy)(cx);
}
HMACContext *
HMAC_Create(const SECHashObject *hashObj, const unsigned char *secret,
unsigned int secret_len, PRBool isFIPS)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return NULL;
return (vector->p_HMAC_Create)(hashObj, secret, secret_len, isFIPS);
}
SECStatus
HMAC_Init(HMACContext *cx, const SECHashObject *hashObj,
const unsigned char *secret, unsigned int secret_len, PRBool isFIPS)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return NULL;
return (vector->p_HMAC_Init)(cx, hashObj, secret, secret_len, isFIPS);
}
void
HMAC_Begin(HMACContext *cx)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return;
(vector->p_HMAC_Begin)(cx);
}
void
HMAC_Update(HMACContext *cx, const unsigned char *data, unsigned int data_len)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return;
(vector->p_HMAC_Update)(cx, data, data_len);
}
SECStatus
HMAC_Finish(HMACContext *cx, unsigned char *result, unsigned int *result_len,
unsigned int max_result_len)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return SECFailure;
return (vector->p_HMAC_Finish)(cx, result, result_len, max_result_len);
}
HMACContext *
HMAC_Clone(HMACContext *cx)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return NULL;
return (vector->p_HMAC_Clone)(cx);
}

View File

@ -37,7 +37,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: loader.h,v 1.13 2005/08/06 07:24:21 nelsonb%netscape.com Exp $ */
/* $Id: loader.h,v 1.14 2005/08/06 09:27:28 nelsonb%netscape.com Exp $ */
#ifndef _LOADER_H_
#define _LOADER_H_ 1
@ -426,6 +426,26 @@ struct FREEBLVectorStr {
void (* p_SHA384_Clone)(SHA384Context *dest, SHA384Context *src);
void (* p_SHA512_Clone)(SHA512Context *dest, SHA512Context *src);
SECStatus (* p_TLS_PRF)(const SECItem *secret, const char *label,
SECItem *seed, SECItem *result, PRBool isFIPS);
const SECHashObject *(* p_SEC_GetRawHashObject)(HASH_HashType hashType);
void (* p_HMAC_Destroy)(HMACContext *cx);
HMACContext * (* p_HMAC_Create)(const SECHashObject *hashObj,
const unsigned char *secret,
unsigned int secret_len, PRBool isFIPS);
SECStatus (* p_HMAC_Init)(HMACContext *cx, const SECHashObject *hash_obj,
const unsigned char *secret,
unsigned int secret_len, PRBool isFIPS);
void (* p_HMAC_Begin)(HMACContext *cx);
void (* p_HMAC_Update)(HMACContext *cx, const unsigned char *data,
unsigned int data_len);
SECStatus (* p_HMAC_Finish)(HMACContext *cx, unsigned char *result,
unsigned int *result_len,
unsigned int max_result_len);
HMACContext * (* p_HMAC_Clone)(HMACContext *cx);
/* Version 3.008 came to here */
};

View File

@ -21,8 +21,7 @@
#
# Contributor(s):
# Dr Vipul Gupta <vipul.gupta@sun.com> and
# Douglas Stebila <douglas@stebila.ca>, Sun Microsystems
# Laboratories
# Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
@ -66,6 +65,7 @@ EXPORTS = \
$(NULL)
PRIVATE_EXPORTS = \
alghmac.h \
blapi.h \
secmpi.h \
secrng.h \
@ -96,6 +96,8 @@ CSRCS = \
md2.c \
md5.c \
sha512.c \
alghmac.c \
rawhash.c \
alg2268.c \
arcfour.c \
arcfive.c \
@ -109,6 +111,7 @@ CSRCS = \
dsa.c \
rsa.c \
shvfy.c \
tlsprfalg.c \
$(MPI_SRCS) \
$(ECL_SRCS) \
$(NULL)
@ -116,6 +119,7 @@ CSRCS = \
ALL_CSRCS := $(CSRCS)
ALL_HDRS = \
alghmac.h \
blapi.h \
blapit.h \
des.h \

View File

@ -0,0 +1,163 @@
/* tlsprfalg.c - TLS Pseudo Random Function (PRF) implementation
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape security libraries.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1994-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: tlsprfalg.c,v 1.2 2005/08/06 09:27:28 nelsonb%netscape.com Exp $ */
#include "sechash.h"
#include "alghmac.h"
#include "blapi.h"
#define PHASH_STATE_MAX_LEN 20
/* TLS P_hash function */
static SECStatus
sftk_P_hash(HASH_HashType hashType, const SECItem *secret, const char *label,
SECItem *seed, SECItem *result, PRBool isFIPS)
{
unsigned char state[PHASH_STATE_MAX_LEN];
unsigned char outbuf[PHASH_STATE_MAX_LEN];
unsigned int state_len = 0, label_len = 0, outbuf_len = 0, chunk_size;
unsigned int remaining;
unsigned char *res;
SECStatus status;
HMACContext *cx;
SECStatus rv = SECFailure;
const SECHashObject *hashObj = SEC_GetRawHashObject(hashType);
PORT_Assert((secret != NULL) && (secret->data != NULL || !secret->len));
PORT_Assert((seed != NULL) && (seed->data != NULL));
PORT_Assert((result != NULL) && (result->data != NULL));
remaining = result->len;
res = result->data;
if (label != NULL)
label_len = PORT_Strlen(label);
cx = HMAC_Create(hashObj, secret->data, secret->len, isFIPS);
if (cx == NULL)
goto loser;
/* initialize the state = A(1) = HMAC_hash(secret, seed) */
HMAC_Begin(cx);
HMAC_Update(cx, (unsigned char *)label, label_len);
HMAC_Update(cx, seed->data, seed->len);
status = HMAC_Finish(cx, state, &state_len, PHASH_STATE_MAX_LEN);
if (status != SECSuccess)
goto loser;
/* generate a block at a time until we're done */
while (remaining > 0) {
HMAC_Begin(cx);
HMAC_Update(cx, state, state_len);
if (label_len)
HMAC_Update(cx, (unsigned char *)label, label_len);
HMAC_Update(cx, seed->data, seed->len);
status = HMAC_Finish(cx, outbuf, &outbuf_len, PHASH_STATE_MAX_LEN);
if (status != SECSuccess)
goto loser;
/* Update the state = A(i) = HMAC_hash(secret, A(i-1)) */
HMAC_Begin(cx);
HMAC_Update(cx, state, state_len);
status = HMAC_Finish(cx, state, &state_len, PHASH_STATE_MAX_LEN);
if (status != SECSuccess)
goto loser;
chunk_size = PR_MIN(outbuf_len, remaining);
PORT_Memcpy(res, &outbuf, chunk_size);
res += chunk_size;
remaining -= chunk_size;
}
rv = SECSuccess;
loser:
/* clear out state so it's not left on the stack */
if (cx) HMAC_Destroy(cx);
PORT_Memset(state, 0, sizeof(state));
PORT_Memset(outbuf, 0, sizeof(outbuf));
return rv;
}
SECStatus
TLS_PRF(const SECItem *secret, const char *label, SECItem *seed,
SECItem *result, PRBool isFIPS)
{
SECStatus rv = SECFailure, status;
unsigned int i;
SECItem tmp = { siBuffer, NULL, 0};
SECItem S1;
SECItem S2;
PORT_Assert((secret != NULL) && (secret->data != NULL || !secret->len));
PORT_Assert((seed != NULL) && (seed->data != NULL));
PORT_Assert((result != NULL) && (result->data != NULL));
S1.type = siBuffer;
S1.len = (secret->len / 2) + (secret->len & 1);
S1.data = secret->data;
S2.type = siBuffer;
S2.len = S1.len;
S2.data = secret->data + (secret->len - S2.len);
tmp.data = (unsigned char*)PORT_Alloc(result->len);
if (tmp.data == NULL)
goto loser;
tmp.len = result->len;
status = sftk_P_hash(HASH_AlgMD5, &S1, label, seed, result, isFIPS);
if (status != SECSuccess)
goto loser;
status = sftk_P_hash(HASH_AlgSHA1, &S2, label, seed, &tmp, isFIPS);
if (status != SECSuccess)
goto loser;
for (i = 0; i < result->len; i++)
result->data[i] ^= tmp.data[i];
rv = SECSuccess;
loser:
if (tmp.data != NULL)
PORT_ZFree(tmp.data, tmp.len);
return rv;
}

View File

@ -587,7 +587,7 @@ nsspkcs5_ComputeKeyAndIV(NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem,
iv->len = pbe_param->ivLen;
}
hashObj = &SECRawHashObjects[pbe_param->hashType];
hashObj = SEC_GetRawHashObject(pbe_param->hashType);
switch (pbe_param->pbeType) {
case NSSPKCS5_PBKDF1:
hash = nsspkcs5_PBKDF1Extended(hashObj,pbe_param,pwitem,faulty3DES);

View File

@ -61,7 +61,6 @@ PRIVATE_EXPORTS = \
$(NULL)
CSRCS = \
alghmac.c \
dbinit.c \
dbmshim.c \
ecdecode.c \
@ -77,7 +76,6 @@ CSRCS = \
pkcs11.c \
pkcs11c.c \
pkcs11u.c \
rawhash.c \
rsawrapr.c \
softkver.c \
tlsprf.c \

View File

@ -1266,7 +1266,7 @@ sftk_doHMACInit(SFTKSessionContext *context,HASH_HashType hash,
SFTKAttribute *keyval;
HMACContext *HMACcontext;
CK_ULONG *intpointer;
const SECHashObject *hashObj = &SECRawHashObjects[hash];
const SECHashObject *hashObj = SEC_GetRawHashObject(hash);
PRBool isFIPS = (key->slot->slotID == FIPS_SLOT_ID);
/* required by FIPS 198 Section 4 */
@ -4705,7 +4705,7 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession,
PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH,
ssl3_master->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH);
status = sftk_PRF(&pms, "master secret", &crsr, &master, isFIPS);
status = TLS_PRF(&pms, "master secret", &crsr, &master, isFIPS);
if (status != SECSuccess) {
crv = CKR_FUNCTION_FAILED;
break;
@ -4836,7 +4836,7 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession,
ssl3_keys->RandomInfo.pClientRandom,
SSL3_RANDOM_LENGTH);
status = sftk_PRF(&master, "key expansion", &srcr, &keyblk,
status = TLS_PRF(&master, "key expansion", &srcr, &keyblk,
isFIPS);
if (status != SECSuccess) {
goto key_and_mac_derive_fail;
@ -5043,7 +5043,7 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession,
i += effKeySize;
keyblk.data = key_block2;
keyblk.len = sizeof key_block2;
status = sftk_PRF(&secret, "client write key", &crsr, &keyblk,
status = TLS_PRF(&secret, "client write key", &crsr, &keyblk,
isFIPS);
if (status != SECSuccess) {
goto key_and_mac_derive_fail;
@ -5065,7 +5065,7 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession,
i += effKeySize;
keyblk.data = key_block2;
keyblk.len = sizeof key_block2;
status = sftk_PRF(&secret, "server write key", &crsr, &keyblk,
status = TLS_PRF(&secret, "server write key", &crsr, &keyblk,
isFIPS);
if (status != SECSuccess) {
goto key_and_mac_derive_fail;
@ -5087,7 +5087,7 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession,
secret.len = 0;
keyblk.data = &key_block[i];
keyblk.len = 2 * IVSize;
status = sftk_PRF(&secret, "IV block", &crsr, &keyblk,
status = TLS_PRF(&secret, "IV block", &crsr, &keyblk,
isFIPS);
if (status != SECSuccess) {
goto key_and_mac_derive_fail;

View File

@ -683,10 +683,6 @@ SFTKTokenObject *sftk_convertSessionToToken(SFTKObject *so);
* implement TLS Pseudo Random Function (PRF)
*/
extern SECStatus
sftk_PRF(const SECItem *secret, const char *label, SECItem *seed,
SECItem *result, PRBool isFIPS);
extern CK_RV
sftk_TLSPRFInit(SFTKSessionContext *context,
SFTKObject * key,

View File

@ -35,135 +35,13 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: tlsprf.c,v 1.5 2005/03/29 18:21:18 nelsonb%netscape.com Exp $ */
/* $Id: tlsprf.c,v 1.6 2005/08/06 09:27:28 nelsonb%netscape.com Exp $ */
#include "pkcs11i.h"
#include "sechash.h"
#include "alghmac.h"
#include "blapi.h"
#define SFTK_OFFSETOF(str, memb) ((PRPtrdiff)(&(((str *)0)->memb)))
#define PHASH_STATE_MAX_LEN 20
/* TLS P_hash function */
static SECStatus
sftk_P_hash(HASH_HashType hashType, const SECItem *secret, const char *label,
SECItem *seed, SECItem *result, PRBool isFIPS)
{
unsigned char state[PHASH_STATE_MAX_LEN];
unsigned char outbuf[PHASH_STATE_MAX_LEN];
unsigned int state_len = 0, label_len = 0, outbuf_len = 0, chunk_size;
unsigned int remaining;
unsigned char *res;
SECStatus status;
HMACContext *cx;
SECStatus rv = SECFailure;
const SECHashObject *hashObj = &SECRawHashObjects[hashType];
PORT_Assert((secret != NULL) && (secret->data != NULL || !secret->len));
PORT_Assert((seed != NULL) && (seed->data != NULL));
PORT_Assert((result != NULL) && (result->data != NULL));
remaining = result->len;
res = result->data;
if (label != NULL)
label_len = PORT_Strlen(label);
cx = HMAC_Create(hashObj, secret->data, secret->len, isFIPS);
if (cx == NULL)
goto loser;
/* initialize the state = A(1) = HMAC_hash(secret, seed) */
HMAC_Begin(cx);
HMAC_Update(cx, (unsigned char *)label, label_len);
HMAC_Update(cx, seed->data, seed->len);
status = HMAC_Finish(cx, state, &state_len, PHASH_STATE_MAX_LEN);
if (status != SECSuccess)
goto loser;
/* generate a block at a time until we're done */
while (remaining > 0) {
HMAC_Begin(cx);
HMAC_Update(cx, state, state_len);
if (label_len)
HMAC_Update(cx, (unsigned char *)label, label_len);
HMAC_Update(cx, seed->data, seed->len);
status = HMAC_Finish(cx, outbuf, &outbuf_len, PHASH_STATE_MAX_LEN);
if (status != SECSuccess)
goto loser;
/* Update the state = A(i) = HMAC_hash(secret, A(i-1)) */
HMAC_Begin(cx);
HMAC_Update(cx, state, state_len);
status = HMAC_Finish(cx, state, &state_len, PHASH_STATE_MAX_LEN);
if (status != SECSuccess)
goto loser;
chunk_size = PR_MIN(outbuf_len, remaining);
PORT_Memcpy(res, &outbuf, chunk_size);
res += chunk_size;
remaining -= chunk_size;
}
rv = SECSuccess;
loser:
/* if (cx) HMAC_Destroy(cx); */
/* clear out state so it's not left on the stack */
if (cx) HMAC_Destroy(cx);
PORT_Memset(state, 0, sizeof(state));
PORT_Memset(outbuf, 0, sizeof(outbuf));
return rv;
}
SECStatus
sftk_PRF(const SECItem *secret, const char *label, SECItem *seed,
SECItem *result, PRBool isFIPS)
{
SECStatus rv = SECFailure, status;
unsigned int i;
SECItem tmp = { siBuffer, NULL, 0};
SECItem S1;
SECItem S2;
PORT_Assert((secret != NULL) && (secret->data != NULL || !secret->len));
PORT_Assert((seed != NULL) && (seed->data != NULL));
PORT_Assert((result != NULL) && (result->data != NULL));
S1.type = siBuffer;
S1.len = (secret->len / 2) + (secret->len & 1);
S1.data = secret->data;
S2.type = siBuffer;
S2.len = S1.len;
S2.data = secret->data + (secret->len - S2.len);
tmp.data = (unsigned char*)PORT_Alloc(result->len);
if (tmp.data == NULL)
goto loser;
tmp.len = result->len;
status = sftk_P_hash(HASH_AlgMD5, &S1, label, seed, result, isFIPS);
if (status != SECSuccess)
goto loser;
status = sftk_P_hash(HASH_AlgSHA1, &S2, label, seed, &tmp, isFIPS);
if (status != SECSuccess)
goto loser;
for (i = 0; i < result->len; i++)
result->data[i] ^= tmp.data[i];
rv = SECSuccess;
loser:
if (tmp.data != NULL)
PORT_ZFree(tmp.data, tmp.len);
return rv;
}
static void sftk_TLSPRFNull(void *data, PRBool freeit)
{
return;
@ -243,7 +121,7 @@ sftk_TLSPRFUpdate(TLSPRFContext *cx,
sigItem.data = sig;
sigItem.len = maxLen;
rv = sftk_PRF(&secretItem, NULL, &seedItem, &sigItem, cx->cxIsFIPS);
rv = TLS_PRF(&secretItem, NULL, &seedItem, &sigItem, cx->cxIsFIPS);
if (rv == SECSuccess && sigLen != NULL)
*sigLen = sigItem.len;
return rv;