Back to index

lightning-sunbird  0.9+nobinonly
tlsprf.c
Go to the documentation of this file.
00001 /* tlsprf.c - TLS Pseudo Random Function (PRF) implementation
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is the Netscape security libraries.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 /* $Id: tlsprf.c,v 1.6 2005/08/06 09:27:28 nelsonb%netscape.com Exp $ */
00039 
00040 #include "pkcs11i.h"
00041 #include "blapi.h"
00042 
00043 #define SFTK_OFFSETOF(str, memb) ((PRPtrdiff)(&(((str *)0)->memb)))
00044 
00045 static void sftk_TLSPRFNull(void *data, PRBool freeit)
00046 {
00047     return;
00048 } 
00049 
00050 typedef struct {
00051     PRUint32     cxSize;    /* size of allocated block, in bytes.        */
00052     PRUint32       cxBufSize;   /* sizeof buffer at cxBufPtr.                */
00053     unsigned char *cxBufPtr;       /* points to real buffer, may be cxBuf.      */
00054     PRUint32     cxKeyLen;  /* bytes of cxBufPtr containing key.         */
00055     PRUint32     cxDataLen; /* bytes of cxBufPtr containing data.        */
00056     SECStatus    cxRv;      /* records failure of void functions.        */
00057     PRBool       cxIsFIPS;  /* true if conforming to FIPS 198.           */
00058     unsigned char  cxBuf[512];     /* actual size may be larger than 512.       */
00059 } TLSPRFContext;
00060 
00061 static void
00062 sftk_TLSPRFHashUpdate(TLSPRFContext *cx, const unsigned char *data, 
00063                         unsigned int data_len)
00064 {
00065     PRUint32 bytesUsed = cx->cxKeyLen + cx->cxDataLen;
00066 
00067     if (cx->cxRv != SECSuccess)    /* function has previously failed. */
00068        return;
00069     if (bytesUsed + data_len > cx->cxBufSize) {
00070        /* We don't use realloc here because 
00071        ** (a) realloc doesn't zero out the old block, and 
00072        ** (b) if realloc fails, we lose the old block.
00073        */
00074        PRUint32 newBufSize = bytesUsed + data_len + 512;
00075        unsigned char * newBuf = (unsigned char *)PORT_Alloc(newBufSize);
00076        if (!newBuf) {
00077           cx->cxRv = SECFailure;
00078           return;
00079        }
00080        PORT_Memcpy(newBuf, cx->cxBufPtr, bytesUsed);
00081        if (cx->cxBufPtr != cx->cxBuf) {
00082            PORT_ZFree(cx->cxBufPtr, bytesUsed);
00083        }
00084        cx->cxBufPtr  = newBuf;
00085        cx->cxBufSize = newBufSize;
00086     }
00087     PORT_Memcpy(cx->cxBufPtr + bytesUsed, data, data_len);
00088     cx->cxDataLen += data_len;
00089 }
00090 
00091 static void 
00092 sftk_TLSPRFEnd(TLSPRFContext *ctx, unsigned char *hashout,
00093         unsigned int *pDigestLen, unsigned int maxDigestLen)
00094 {
00095     *pDigestLen = 0; /* tells Verify that no data has been input yet. */
00096 }
00097 
00098 /* Compute the PRF values from the data previously input. */
00099 static SECStatus
00100 sftk_TLSPRFUpdate(TLSPRFContext *cx, 
00101                   unsigned char *sig,            /* output goes here. */
00102                 unsigned int * sigLen,    /* how much output.  */
00103                 unsigned int   maxLen,    /* output buffer size */
00104                 unsigned char *hash,             /* unused. */
00105                 unsigned int   hashLen)   /* unused. */
00106 {
00107     SECStatus rv;
00108     SECItem sigItem;
00109     SECItem seedItem;
00110     SECItem secretItem;
00111 
00112     if (cx->cxRv != SECSuccess)
00113        return cx->cxRv;
00114 
00115     secretItem.data = cx->cxBufPtr;
00116     secretItem.len  = cx->cxKeyLen;
00117 
00118     seedItem.data = cx->cxBufPtr + cx->cxKeyLen;
00119     seedItem.len  = cx->cxDataLen;
00120 
00121     sigItem.data = sig;
00122     sigItem.len  = maxLen;
00123 
00124     rv = TLS_PRF(&secretItem, NULL, &seedItem, &sigItem, cx->cxIsFIPS);
00125     if (rv == SECSuccess && sigLen != NULL)
00126        *sigLen = sigItem.len;
00127     return rv;
00128 
00129 }
00130 
00131 static SECStatus
00132 sftk_TLSPRFVerify(TLSPRFContext *cx, 
00133                   unsigned char *sig,            /* input, for comparison. */
00134                 unsigned int   sigLen,    /* length of sig.         */
00135                 unsigned char *hash,             /* data to be verified.   */
00136                 unsigned int   hashLen)   /* size of hash data.     */
00137 {
00138     unsigned char * tmp    = (unsigned char *)PORT_Alloc(sigLen);
00139     unsigned int    tmpLen = sigLen;
00140     SECStatus       rv;
00141 
00142     if (!tmp)
00143        return SECFailure;
00144     if (hashLen) {
00145        /* hashLen is non-zero when the user does a one-step verify.
00146        ** In this case, none of the data has been input yet.
00147        */
00148        sftk_TLSPRFHashUpdate(cx, hash, hashLen);
00149     }
00150     rv = sftk_TLSPRFUpdate(cx, tmp, &tmpLen, sigLen, NULL, 0);
00151     if (rv == SECSuccess) {
00152        rv = (SECStatus)(1 - !PORT_Memcmp(tmp, sig, sigLen));
00153     }
00154     PORT_ZFree(tmp, sigLen);
00155     return rv;
00156 }
00157 
00158 static void
00159 sftk_TLSPRFHashDestroy(TLSPRFContext *cx, PRBool freeit)
00160 {
00161     if (freeit) {
00162        if (cx->cxBufPtr != cx->cxBuf) 
00163            PORT_ZFree(cx->cxBufPtr, cx->cxBufSize);
00164        PORT_ZFree(cx, cx->cxSize);
00165     }
00166 }
00167 
00168 CK_RV
00169 sftk_TLSPRFInit(SFTKSessionContext *context, 
00170                 SFTKObject *        key, 
00171                 CK_KEY_TYPE         key_type)
00172 {
00173     SFTKAttribute * keyVal;
00174     TLSPRFContext * prf_cx;
00175     CK_RV           crv = CKR_HOST_MEMORY;
00176     PRUint32        keySize;
00177     PRUint32        blockSize;
00178 
00179     if (key_type != CKK_GENERIC_SECRET)
00180        return CKR_KEY_TYPE_INCONSISTENT; /* CKR_KEY_FUNCTION_NOT_PERMITTED */
00181 
00182     context->multi = PR_TRUE;
00183 
00184     keyVal = sftk_FindAttribute(key, CKA_VALUE);
00185     keySize = (!keyVal) ? 0 : keyVal->attrib.ulValueLen;
00186     blockSize = keySize + sizeof(TLSPRFContext);
00187     prf_cx = (TLSPRFContext *)PORT_Alloc(blockSize);
00188     if (!prf_cx) 
00189        goto done;
00190     prf_cx->cxSize    = blockSize;
00191     prf_cx->cxKeyLen  = keySize;
00192     prf_cx->cxDataLen = 0;
00193     prf_cx->cxBufSize = blockSize - SFTK_OFFSETOF(TLSPRFContext, cxBuf);
00194     prf_cx->cxRv      = SECSuccess;
00195     prf_cx->cxIsFIPS  = (key->slot->slotID == FIPS_SLOT_ID);
00196     prf_cx->cxBufPtr  = prf_cx->cxBuf;
00197     if (keySize)
00198        PORT_Memcpy(prf_cx->cxBufPtr, keyVal->attrib.pValue, keySize);
00199 
00200     context->hashInfo    = (void *) prf_cx;
00201     context->cipherInfo  = (void *) prf_cx;
00202     context->hashUpdate  = (SFTKHash)    sftk_TLSPRFHashUpdate;
00203     context->end         = (SFTKEnd)     sftk_TLSPRFEnd;
00204     context->update      = (SFTKCipher)  sftk_TLSPRFUpdate;
00205     context->verify      = (SFTKVerify)  sftk_TLSPRFVerify;
00206     context->destroy     = (SFTKDestroy) sftk_TLSPRFNull;
00207     context->hashdestroy = (SFTKDestroy) sftk_TLSPRFHashDestroy;
00208     crv = CKR_OK;
00209 
00210 done:
00211     if (keyVal) 
00212        sftk_FreeAttribute(keyVal);
00213     return crv;
00214 }
00215