pkcs11c.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 2,203 行 · 第 1/5 页
C
2,203 行
context->cipherInfo = (void *) prf_cx; context->hashUpdate = (PK11Hash) pk11_TLSPRFHashUpdate; context->end = (PK11End) pk11_TLSPRFEnd; context->update = (PK11Cipher) pk11_TLSPRFUpdate; context->verify = (PK11Verify) pk11_TLSPRFVerify; context->destroy = (PK11Destroy) pk11_Null; context->hashdestroy = (PK11Destroy) pk11_TLSPRFHashDestroy; crv = CKR_OK;done: if (keyVal) pk11_FreeAttribute(keyVal); return crv;}/* ************** Crypto Functions: Sign ************************ *//* * Check if We're using CBCMacing and initialize the session context if we are. */static CK_RVpk11_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE keyUsage, PK11ContextType contextType) { CK_MECHANISM cbc_mechanism; CK_ULONG mac_bytes = PK11_INVALID_MAC_SIZE; CK_RC2_CBC_PARAMS rc2_params;#if NSS_SOFTOKEN_DOES_RC5 CK_RC5_CBC_PARAMS rc5_params; CK_RC5_MAC_GENERAL_PARAMS *rc5_mac;#endif unsigned char ivBlock[PK11_MAX_BLOCK_SIZE]; PK11SessionContext *context; CK_RV crv; int blockSize; switch (pMechanism->mechanism) { case CKM_RC2_MAC_GENERAL: mac_bytes = ((CK_RC2_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength; /* fall through */ case CKM_RC2_MAC: /* this works because ulEffectiveBits is in the same place in both the * CK_RC2_MAC_GENERAL_PARAMS and CK_RC2_CBC_PARAMS */ rc2_params.ulEffectiveBits = ((CK_RC2_MAC_GENERAL_PARAMS *) pMechanism->pParameter)->ulEffectiveBits; PORT_Memset(rc2_params.iv,0,sizeof(rc2_params.iv)); cbc_mechanism.mechanism = CKM_RC2_CBC; cbc_mechanism.pParameter = &rc2_params; cbc_mechanism.ulParameterLen = sizeof(rc2_params); blockSize = 8; break;#if NSS_SOFTOKEN_DOES_RC5 case CKM_RC5_MAC_GENERAL: mac_bytes = ((CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength; /* fall through */ case CKM_RC5_MAC: /* this works because ulEffectiveBits is in the same place in both the * CK_RC5_MAC_GENERAL_PARAMS and CK_RC5_CBC_PARAMS */ rc5_mac = (CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter; rc5_params.ulWordsize = rc5_mac->ulWordsize; rc5_params.ulRounds = rc5_mac->ulRounds; rc5_params.pIv = ivBlock; blockSize = rc5_mac->ulWordsize*2; rc5_params.ulIvLen = blockSize; PORT_Memset(ivBlock,0,blockSize); cbc_mechanism.mechanism = CKM_RC5_CBC; cbc_mechanism.pParameter = &rc5_params; cbc_mechanism.ulParameterLen = sizeof(rc5_params); break;#endif /* add cast and idea later */ case CKM_DES_MAC_GENERAL: mac_bytes = *(CK_ULONG *)pMechanism->pParameter; /* fall through */ case CKM_DES_MAC: blockSize = 8; PORT_Memset(ivBlock,0,blockSize); cbc_mechanism.mechanism = CKM_DES_CBC; cbc_mechanism.pParameter = &ivBlock; cbc_mechanism.ulParameterLen = blockSize; break; case CKM_DES3_MAC_GENERAL: mac_bytes = *(CK_ULONG *)pMechanism->pParameter; /* fall through */ case CKM_DES3_MAC: blockSize = 8; PORT_Memset(ivBlock,0,blockSize); cbc_mechanism.mechanism = CKM_DES3_CBC; cbc_mechanism.pParameter = &ivBlock; cbc_mechanism.ulParameterLen = blockSize; break; case CKM_CDMF_MAC_GENERAL: mac_bytes = *(CK_ULONG *)pMechanism->pParameter; /* fall through */ case CKM_CDMF_MAC: blockSize = 8; PORT_Memset(ivBlock,0,blockSize); cbc_mechanism.mechanism = CKM_CDMF_CBC; cbc_mechanism.pParameter = &ivBlock; cbc_mechanism.ulParameterLen = blockSize; break; default: return CKR_FUNCTION_NOT_SUPPORTED; } crv = pk11_EncryptInit(hSession, &cbc_mechanism, hKey, keyUsage, contextType); if (crv != CKR_OK) return crv; crv = pk11_GetContext(hSession,&context,contextType,PR_TRUE,NULL); /* this shouldn't happen! */ PORT_Assert(crv == CKR_OK); if (crv != CKR_OK) return crv; context->blockSize = blockSize; if (mac_bytes == PK11_INVALID_MAC_SIZE) mac_bytes = blockSize/2; context->macSize = mac_bytes; return CKR_OK;}/* * encode RSA PKCS #1 Signature data before signing... */static SECStatuspk11_HashSign(PK11HashSignInfo *info,unsigned char *sig,unsigned int *sigLen, unsigned int maxLen,unsigned char *hash, unsigned int hashLen){ SECStatus rv = SECFailure; SECItem digder; PLArenaPool *arena = NULL; SGNDigestInfo *di = NULL; digder.data = NULL; arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if ( !arena ) { goto loser; } /* Construct digest info */ di = SGN_CreateDigestInfo(info->hashOid, hash, hashLen); if (!di) { goto loser; } /* Der encode the digest as a DigestInfo */ rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, di); if (rv != SECSuccess) { goto loser; } /* ** Encrypt signature after constructing appropriate PKCS#1 signature ** block */ rv = RSA_Sign(info->key,sig,sigLen,maxLen,digder.data,digder.len); loser: SGN_DestroyDigestInfo(di); if (arena != NULL) { PORT_FreeArena(arena, PR_FALSE); } return rv;}static SECStatusnsc_DSA_Verify_Stub(void *ctx, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG ulDataLen){ SECItem signature, digest; signature.data = pSignature; signature.len = ulSignatureLen; digest.data = pData; digest.len = ulDataLen; return DSA_VerifyDigest((DSAPublicKey *)ctx, &signature, &digest);}static SECStatusnsc_DSA_Sign_Stub(void *ctx, CK_BYTE_PTR pSignature, CK_ULONG_PTR ulSignatureLen, CK_ULONG maxulSignatureLen, CK_BYTE_PTR pData, CK_ULONG ulDataLen){ SECItem signature = { 0 }, digest; SECStatus rv; (void)SECITEM_AllocItem(NULL, &signature, maxulSignatureLen); digest.data = pData; digest.len = ulDataLen; rv = DSA_SignDigest((DSAPrivateKey *)ctx, &signature, &digest); *ulSignatureLen = signature.len; PORT_Memcpy(pSignature, signature.data, signature.len); SECITEM_FreeItem(&signature, PR_FALSE); return rv;}/* NSC_SignInit setups up the signing operations. There are three basic * types of signing: * (1) the tradition single part, where "Raw RSA" or "Raw DSA" is applied * to data in a single Sign operation (which often looks a lot like an * encrypt, with data coming in and data going out). * (2) Hash based signing, where we continually hash the data, then apply * some sort of signature to the end. * (3) Block Encryption CBC MAC's, where the Data is encrypted with a key, * and only the final block is part of the mac. * * For case number 3, we initialize a context much like the Encryption Context * (in fact we share code). We detect case 3 in C_SignUpdate, C_Sign, and * C_Final by the following method... if it's not multi-part, and it's doesn't * have a hash context, it must be a block Encryption CBC MAC. * * For case number 2, we initialize a hash structure, as well as make it * multi-part. Updates are simple calls to the hash update function. Final * calls the hashend, then passes the result to the 'update' function (which * operates as a final signature function). In some hash based MAC'ing (as * opposed to hash base signatures), the update function is can be simply a * copy (as is the case with HMAC). */CK_RV NSC_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey){ PK11Session *session; PK11Object *key; PK11SessionContext *context; CK_KEY_TYPE key_type; CK_RV crv = CKR_OK; SECKEYLowPrivateKey *privKey; PK11HashSignInfo *info = NULL; /* Block Cipher MACing Algorithms use a different Context init method..*/ crv = pk11_InitCBCMac(hSession, pMechanism, hKey, CKA_SIGN, PK11_SIGN); if (crv != CKR_FUNCTION_NOT_SUPPORTED) return crv; /* we're not using a block cipher mac */ session = pk11_SessionFromHandle(hSession); if (session == NULL) return CKR_SESSION_HANDLE_INVALID; crv = pk11_InitGeneric(session,&context,PK11_SIGN,&key,hKey,&key_type, CKO_PRIVATE_KEY,CKA_SIGN); if (crv != CKR_OK) { pk11_FreeSession(session); return crv; } context->multi = PR_FALSE; switch(pMechanism->mechanism) { case CKM_MD5_RSA_PKCS: context->multi = PR_TRUE; crv = pk11_doSubMD2(context); if (crv != CKR_OK) break; context->update = (PK11Cipher) pk11_HashSign; info = (PK11HashSignInfo *)PORT_Alloc(sizeof(PK11HashSignInfo)); if (info == NULL) { crv = CKR_HOST_MEMORY; break; } info->hashOid = SEC_OID_MD5; goto finish_rsa; case CKM_MD2_RSA_PKCS: context->multi = PR_TRUE; crv = pk11_doSubMD2(context); if (crv != CKR_OK) break; context->update = (PK11Cipher) pk11_HashSign; info = (PK11HashSignInfo *)PORT_Alloc(sizeof(PK11HashSignInfo)); if (info == NULL) { crv = CKR_HOST_MEMORY; break; } info->hashOid = SEC_OID_MD2; goto finish_rsa; case CKM_SHA1_RSA_PKCS: context->multi = PR_TRUE; crv = pk11_doSubSHA1(context); if (crv != CKR_OK) break; context->update = (PK11Cipher) pk11_HashSign; info = (PK11HashSignInfo *)PORT_Alloc(sizeof(PK11HashSignInfo)); if (info == NULL) { crv = CKR_HOST_MEMORY; break; } info->hashOid = SEC_OID_SHA1; goto finish_rsa; case CKM_RSA_PKCS: context->update = (PK11Cipher) RSA_Sign; goto finish_rsa; case CKM_RSA_X_509: context->update = (PK11Cipher) RSA_SignRaw;finish_rsa: if (key_type != CKK_RSA) { if (info) PORT_Free(info); crv = CKR_KEY_TYPE_INCONSISTENT; break; } context->multi = PR_FALSE; privKey = pk11_GetPrivKey(key,CKK_RSA); if (privKey == NULL) { if (info) PORT_Free(info); crv = CKR_HOST_MEMORY; break; } /* OK, info is allocated only if we're doing hash and sign mechanism. * It's necessary to be able to set the correct OID in the final * signature. * Second, what's special about privKey == key->objectInfo? * Well we don't 'cache' token versions * of private keys because (1) it's sensitive data, and (2) it never * gets destroyed. Instead we grab the key out of the database as * necessary, but now the key is our context, and we need to free * it when we are done. Non-token private keys will get freed when * the user destroys the session object (or the session the session * object lives in) */ if (info) { info->key = privKey; context->cipherInfo = info; context->destroy = (privKey == key->objectInfo) ? (PK11Destroy)pk11_Space:(PK11Destroy)pk11_FreeSignInfo; } else { context->cipherInfo = privKey; context->destroy = (privKey == key->objectInfo) ? (PK11Destroy)pk11_Null:(PK11Destroy)pk11_FreePrivKey; } break; case CKM_DSA_SHA1: context->multi = PR_TRUE; crv = pk11_doSubSHA1(context); if (crv != CKR_OK) break; /* fall through */ case CKM_DSA: if (key_type != CKK_DSA) { crv = CKR_KEY_TYPE_INCONSISTENT; break; } privKey = pk11_GetPrivKey(key,CKK_DSA); if (privKey == NULL) { crv = CKR_HOST_MEMORY; break; } context->cipherInfo = &(privKey->u.dsa); context->update = (PK11Cipher) nsc_DSA_Sign_Stub; context->destroy = pk11_Null; if (key->objectInfo != privKey) SECKEY_LowDestroyPrivateKey(privKey); break; case CKM_MD2_HMAC_GENERAL: crv = pk11_doHMACInit(context,SEC_OID_MD2,key, *(CK_ULONG *)pMechanism->pParameter); break; case CKM_MD2_HMAC: crv = pk11_doHMACInit(context,SEC_OID_MD2,key,MD2_LENGTH); break; case CKM_MD5_HMAC_GENERAL: crv = pk11_doHMACInit(context,SEC_OID_MD5,key, *(CK_ULONG *)pMechanism->pParameter); break; case CKM_MD5_HMAC: crv = pk11_doHMACInit(context,SEC_OID_MD5,key,MD5_LENGTH); break; case CKM_SHA_1_HMAC_GENERAL: crv = pk11_doHMACInit(context,SEC_OID_SHA1,key, *(CK_ULONG *)pMechanism->pParameter); break; case CKM_SHA_1_HMAC: crv = pk11_doHMACInit(context,SEC_OID_SHA1,key,SHA1_LENGTH); break; case CKM_SSL3_MD5_MAC: crv = pk11_doSSLMACInit(context,SEC_OID_MD5,key, *(CK_ULONG *)pMechanism->pParameter); break; case CKM_SSL3_SHA1_MAC: crv = pk11_doSSLMACInit(context,SEC_OID_SHA1,key, *(CK_ULONG *)pMechanism->pParameter); break; case CKM_TLS_PRF_GENERAL: crv = pk11_TLSPRFInit(context, key, key_type); break; default: crv = CKR_MECHANISM_INVALID; break; } pk11_FreeObject(key); if (crv != CKR_OK) { PORT_Free(context); pk11_FreeSession(session); return crv; } pk11_SetContextByType(session, PK11_SIGN, context); pk11_FreeSession(session); return CKR_OK;}/* MACUpdate is the common implementation for SignUpdate and VerifyUpdate. * (sign and verify only very in their setup and final operations) */static CK_RV pk11_MACUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart, CK_ULONG ulPartLen,PK11ContextType type){ unsigned int outlen; PK11SessionContext *context; CK_RV crv; SECStatus rv; /* make sure we're legal */ crv = pk11_GetContext(hSession,&context,type,PR_FALSE,NULL); if (crv != CKR_OK) return crv; if (context->hashInfo) { (*context->hashUpdate)(context->hashInfo, pPart, ulPartLen); return CKR_OK; } /* must be block cipher macing */ /* deal with previous buffered data */ if (context->padDataLength != 0) { int i; /* fill in the padded to a full block size */ for (i=context->padDataLength; (ulPartLen != 0) && i < (int)context->blockSize; i++) { context->padBuf[i] = *pPart++; ulPartLen--; context->padDataLength++; } /* not enough data to encrypt yet? then return */ if (context->padDataLength != context->blockSize) return CKR_OK; /* encrypt the current padded data */ rv = (*context->update)(context->cipherInfo,context->macBuf,&outlen, PK11_MAX_BLOCK_SIZE,context->padBuf,context->blockSize); if (rv != SECSuccess) return CKR_DEVICE_ERROR; } /* save the residual */ context->padDataLength = ulPartLen % context->blockSize; if (co
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?