pkcs11c.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 2,203 行 · 第 1/5 页

C
2,203
字号
/* NSC_Digest digests data in a single part. */CK_RV NSC_Digest(CK_SESSION_HANDLE hSession,    CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest,    						CK_ULONG_PTR pulDigestLen){    PK11Session *session;    PK11SessionContext *context;    unsigned int digestLen;    unsigned int maxout = *pulDigestLen;    CK_RV crv;    /* make sure we're legal */    crv = pk11_GetContext(hSession,&context,PK11_HASH,PR_FALSE,&session);    if (crv != CKR_OK) return crv;    /* do it: */    (*context->hashUpdate)(context->cipherInfo, pData, ulDataLen);    /*  NOTE: this assumes buf size is bigenough for the algorithm */    (*context->end)(context->cipherInfo, pDigest, &digestLen,maxout);    *pulDigestLen = digestLen;    pk11_SetContextByType(session, PK11_HASH, NULL);    pk11_FreeContext(context);    pk11_FreeSession(session);    return CKR_OK;}/* NSC_DigestUpdate continues a multiple-part message-digesting operation. */CK_RV NSC_DigestUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,					    CK_ULONG ulPartLen){    PK11SessionContext *context;    CK_RV crv;    /* make sure we're legal */    crv = pk11_GetContext(hSession,&context,PK11_HASH,PR_TRUE,NULL);    if (crv != CKR_OK) return crv;    /* do it: */    (*context->hashUpdate)(context->cipherInfo, pPart, ulPartLen);    return CKR_OK;}/* NSC_DigestFinal finishes a multiple-part message-digesting operation. */CK_RV NSC_DigestFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pDigest,    						CK_ULONG_PTR pulDigestLen){    PK11Session *session;    PK11SessionContext *context;    unsigned int maxout = *pulDigestLen;    unsigned int digestLen;    CK_RV crv;    /* make sure we're legal */    crv = pk11_GetContext(hSession, &context, PK11_HASH, PR_TRUE, &session);    if (crv != CKR_OK) return crv;    if (pDigest != NULL) {        (*context->end)(context->cipherInfo, pDigest, &digestLen, maxout);        *pulDigestLen = digestLen;    } else {	*pulDigestLen = 0;    }    pk11_SetContextByType(session, PK11_HASH, NULL);    pk11_FreeContext(context);    pk11_FreeSession(session);    return CKR_OK;}/* * this helper functions are used by Generic Macing and Signing functions * that use hashes as part of their operations.  */static CK_RVpk11_doSubMD2(PK11SessionContext *context) {	MD2Context *md2_context = MD2_NewContext();	context->hashInfo = (void *)md2_context;        if (context->hashInfo == NULL) {	    return CKR_HOST_MEMORY;	}	context->hashUpdate = (PK11Hash) MD2_Update;	context->end = (PK11End) MD2_End;	context->hashdestroy = (PK11Destroy) MD2_DestroyContext;	MD2_Begin(md2_context);	return CKR_OK;}static CK_RVpk11_doSubMD5(PK11SessionContext *context) {	MD5Context *md5_context = MD5_NewContext();	context->hashInfo = (void *)md5_context;        if (context->hashInfo == NULL) {	    return CKR_HOST_MEMORY;	}	context->hashUpdate = (PK11Hash) MD5_Update;	context->end = (PK11End) MD5_End;	context->hashdestroy = (PK11Destroy) MD5_DestroyContext;	MD5_Begin(md5_context);	return CKR_OK;}static CK_RVpk11_doSubSHA1(PK11SessionContext *context) {	SHA1Context *sha1_context = SHA1_NewContext();	context->hashInfo = (void *)sha1_context;        if (context->hashInfo == NULL) {	    return CKR_HOST_MEMORY;	}	context->hashUpdate = (PK11Hash) SHA1_Update;	context->end = (PK11End) SHA1_End;	context->hashdestroy = (PK11Destroy) SHA1_DestroyContext;	SHA1_Begin(sha1_context);	return CKR_OK;}/* * HMAC General copies only a portion of the result. This update routine likes * the final HMAC output with the signature. */static SECStatuspk11_HMACCopy(CK_ULONG *copyLen,unsigned char *sig,unsigned int *sigLen,		unsigned int maxLen,unsigned char *hash, unsigned int hashLen){    if (maxLen < *copyLen) return SECFailure;    PORT_Memcpy(sig,hash,*copyLen);    *sigLen = *copyLen;    return SECSuccess;}/* Verify is just a compare for HMAC */static SECStatuspk11_HMACCmp(CK_ULONG *copyLen,unsigned char *sig,unsigned int sigLen,				unsigned char *hash, unsigned int hashLen){    return PORT_Memcmp(sig,hash,*copyLen) ? SECSuccess : SECFailure ;}/* * common HMAC initalization routine */static CK_RVpk11_doHMACInit(PK11SessionContext *context,SECOidTag oid,					PK11Object *key, CK_ULONG mac_size){    PK11Attribute *keyval;    HMACContext *HMACcontext;    CK_ULONG *intpointer;    keyval = pk11_FindAttribute(key,CKA_VALUE);    if (keyval == NULL) return CKR_KEY_SIZE_RANGE;    HMACcontext = HMAC_Create(oid, (const unsigned char*)keyval->attrib.pValue,						 keyval->attrib.ulValueLen);    context->hashInfo = HMACcontext;    context->multi = PR_TRUE;    pk11_FreeAttribute(keyval);    if (context->hashInfo == NULL) {	return CKR_HOST_MEMORY;    }    context->hashUpdate = (PK11Hash) HMAC_Update;    context->end = (PK11End) HMAC_Finish;    context->hashdestroy = (PK11Destroy) pk11_HMAC_Destroy;    intpointer = (CK_ULONG *) PORT_Alloc(sizeof(CK_ULONG));    if (intpointer == NULL) {	return CKR_HOST_MEMORY;    }    *intpointer = mac_size;    context->cipherInfo = (void *) intpointer;    context->destroy = (PK11Destroy) pk11_Space;    context->update = (PK11Cipher) pk11_HMACCopy;    context->verify = (PK11Verify) pk11_HMACCmp;    HMAC_Begin(HMACcontext);    return CKR_OK;}/* *  SSL Macing support. SSL Macs are inited, then update with the base * hashing algorithm, then finalized in sign and verify *//* * FROM SSL: * 60 bytes is 3 times the maximum length MAC size that is supported. * We probably should have one copy of this table. We still need this table * in ssl to 'sign' the handshake hashes. */static unsigned char ssl_pad_1 [60] = {    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,    0x36, 0x36, 0x36, 0x36};static unsigned char ssl_pad_2 [60] = {    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,    0x5c, 0x5c, 0x5c, 0x5c};static SECStatuspk11_SSLMACSign(PK11SSLMACInfo *info,unsigned char *sig,unsigned int *sigLen,		unsigned int maxLen,unsigned char *hash, unsigned int hashLen){    unsigned char tmpBuf[PK11_MAX_MAC_LENGTH];    unsigned int out;    info->begin(info->hashContext);    info->update(info->hashContext,info->key,info->keySize);    info->update(info->hashContext,ssl_pad_2,info->padSize);    info->update(info->hashContext,hash,hashLen);    info->end(info->hashContext,tmpBuf,&out,PK11_MAX_MAC_LENGTH);    PORT_Memcpy(sig,tmpBuf,info->macSize);    *sigLen = info->macSize;    return SECSuccess;}static SECStatuspk11_SSLMACVerify(PK11SSLMACInfo *info,unsigned char *sig,unsigned int sigLen,		unsigned char *hash, unsigned int hashLen){    unsigned char tmpBuf[PK11_MAX_MAC_LENGTH];    unsigned int out;    info->begin(info->hashContext);    info->update(info->hashContext,info->key,info->keySize);    info->update(info->hashContext,ssl_pad_2,info->padSize);    info->update(info->hashContext,hash,hashLen);    info->end(info->hashContext,tmpBuf,&out,PK11_MAX_MAC_LENGTH);    return (PORT_Memcmp(sig,tmpBuf,info->macSize) == 0) ? 						SECSuccess : SECFailure;}/* * common HMAC initalization routine */static CK_RVpk11_doSSLMACInit(PK11SessionContext *context,SECOidTag oid,					PK11Object *key, CK_ULONG mac_size){    PK11Attribute *keyval;    PK11Begin begin;    int padSize;    PK11SSLMACInfo *sslmacinfo;    CK_RV crv = CKR_MECHANISM_INVALID;    if (oid == SEC_OID_SHA1) {	crv = pk11_doSubSHA1(context);	begin = (PK11Begin) SHA1_Begin;	if (crv != CKR_OK) return crv;	padSize = 40;    } else {	crv = pk11_doSubMD5(context);	if (crv != CKR_OK) return crv;	begin = (PK11Begin) MD5_Begin;	padSize = 48;    }    context->multi = PR_TRUE;    keyval = pk11_FindAttribute(key,CKA_VALUE);    if (keyval == NULL) return CKR_KEY_SIZE_RANGE;    context->hashUpdate(context->hashInfo,keyval->attrib.pValue,						 keyval->attrib.ulValueLen);    context->hashUpdate(context->hashInfo,ssl_pad_1,padSize);    sslmacinfo = (PK11SSLMACInfo *) PORT_Alloc(sizeof(PK11SSLMACInfo));    if (sslmacinfo == NULL) {        pk11_FreeAttribute(keyval);	return CKR_HOST_MEMORY;    }    sslmacinfo->macSize = mac_size;    sslmacinfo->hashContext = context->hashInfo;    PORT_Memcpy(sslmacinfo->key,keyval->attrib.pValue,					keyval->attrib.ulValueLen);    sslmacinfo->keySize = keyval->attrib.ulValueLen;    sslmacinfo->begin = begin;    sslmacinfo->end = context->end;    sslmacinfo->update = context->hashUpdate;    sslmacinfo->padSize = padSize;    pk11_FreeAttribute(keyval);    context->cipherInfo = (void *) sslmacinfo;    context->destroy = (PK11Destroy) pk11_Space;    context->update = (PK11Cipher) pk11_SSLMACSign;    context->verify = (PK11Verify) pk11_SSLMACVerify;    return CKR_OK;}typedef struct {    PRUint32	cxSize;		/* size of allocated block, in bytes.        */    PRUint32	cxKeyLen;	/* number of bytes of cxBuf containing key.  */    PRUint32	cxDataLen;	/* number of bytes of cxBuf containing data. */    SECStatus	cxRv;		/* records failure of void functions.        */    unsigned char cxBuf[512];	/* actual size may be larger than 512.       */} TLSPRFContext;static voidpk11_TLSPRFHashUpdate(TLSPRFContext *cx, const unsigned char *data,                         unsigned int data_len){    PRUint32 bytesUsed = PK11_OFFSETOF(TLSPRFContext, cxBuf) +                          cx->cxKeyLen + cx->cxDataLen;    if (cx->cxRv != SECSuccess)	/* function has previously failed. */    	return;    if (bytesUsed + data_len > cx->cxSize) {	/* We don't use realloc here because 	** (a) realloc doesn't zero out the old block, and 	** (b) if realloc fails, we lose the old block.	*/	PRUint32 blockSize = bytesUsed + data_len + 512;    	TLSPRFContext *new_cx = (TLSPRFContext *)PORT_Alloc(blockSize);	if (!new_cx) {	   cx->cxRv = SECFailure;	   return;	}	PORT_Memcpy(new_cx, cx, cx->cxSize);	new_cx->cxSize = blockSize;	PORT_ZFree(cx, cx->cxSize);	cx = new_cx;    }    PORT_Memcpy(cx->cxBuf + cx->cxKeyLen + cx->cxDataLen, data, data_len);    cx->cxDataLen += data_len;}static void pk11_TLSPRFEnd(TLSPRFContext *ctx, unsigned char *hashout,	 unsigned int *pDigestLen, unsigned int maxDigestLen){    *pDigestLen = 0; /* tells Verify that no data has been input yet. */}/* Compute the PRF values from the data previously input. */static SECStatuspk11_TLSPRFUpdate(TLSPRFContext *cx,                   unsigned char *sig,		/* output goes here. */		  unsigned int * sigLen, 	/* how much output.  */		  unsigned int   maxLen, 	/* output buffer size */		  unsigned char *hash, 		/* unused. */		  unsigned int   hashLen)	/* unused. */{    SECStatus rv;    SECItem sigItem;    SECItem seedItem;    SECItem secretItem;    if (cx->cxRv != SECSuccess)    	return cx->cxRv;    secretItem.data = cx->cxBuf;    secretItem.len  = cx->cxKeyLen;    seedItem.data = cx->cxBuf + cx->cxKeyLen;    seedItem.len  = cx->cxDataLen;    sigItem.data = sig;    sigItem.len  = maxLen;    rv = pk11_PRF(&secretItem, NULL, &seedItem, &sigItem);    if (rv == SECSuccess && sigLen != NULL)    	*sigLen = sigItem.len;    return rv;}static SECStatuspk11_TLSPRFVerify(TLSPRFContext *cx,                   unsigned char *sig, 		/* input, for comparison. */		  unsigned int   sigLen,	/* length of sig.         */		  unsigned char *hash, 		/* data to be verified.   */		  unsigned int   hashLen)	/* size of hash data.     */{    unsigned char * tmp    = (unsigned char *)PORT_Alloc(sigLen);    unsigned int    tmpLen = sigLen;    SECStatus       rv;    if (!tmp)    	return SECFailure;    if (hashLen) {    	/* hashLen is non-zero when the user does a one-step verify.	** In this case, none of the data has been input yet.	*/    	pk11_TLSPRFHashUpdate(cx, hash, hashLen);    }    rv = pk11_TLSPRFUpdate(cx, tmp, &tmpLen, sigLen, NULL, 0);    if (rv == SECSuccess) {    	rv = (SECStatus)(1 - !PORT_Memcmp(tmp, sig, sigLen));    }    PORT_ZFree(tmp, sigLen);    return rv;}static voidpk11_TLSPRFHashDestroy(TLSPRFContext *cx, PRBool freeit){    if (freeit)	PORT_ZFree(cx, cx->cxSize);}static CK_RVpk11_TLSPRFInit(PK11SessionContext *context, 		  PK11Object *        key, 		  CK_KEY_TYPE         key_type){    PK11Attribute * keyVal;    TLSPRFContext * prf_cx;    CK_RV           crv = CKR_HOST_MEMORY;    PRUint32        keySize;    PRUint32        blockSize;    if (key_type != CKK_GENERIC_SECRET)    	return CKR_KEY_TYPE_INCONSISTENT; /* CKR_KEY_FUNCTION_NOT_PERMITTED */    context->multi = PR_TRUE;    keyVal = pk11_FindAttribute(key, CKA_VALUE);    keySize = (!keyVal) ? 0 : keyVal->attrib.ulValueLen;    blockSize = keySize + sizeof(TLSPRFContext);    prf_cx = (TLSPRFContext *)PORT_Alloc(blockSize);    if (!prf_cx)     	goto done;    prf_cx->cxSize    = blockSize;    prf_cx->cxKeyLen  = keySize;    prf_cx->cxDataLen = 0;    prf_cx->cxRv        = SECSuccess;    if (keySize)	PORT_Memcpy(prf_cx->cxBuf, keyVal->attrib.pValue, keySize);    context->hashInfo    = (void *) prf_cx;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?