/* turn a PKCS #11 parameter into a DER Encoded Algorithm ID */ SECStatus PK11_ParamToAlgid(SECOidTag algTag, SECItem *param, PRArenaPool *arena, SECAlgorithmID *algid) { CK_RC2_CBC_PARAMS *rc2_params; sec_rc2cbcParameter rc2; CK_RC5_CBC_PARAMS *rc5_params; sec_rc5cbcParameter rc5; CK_MECHANISM_TYPE type = PK11_AlgtagToMechanism(algTag); SECItem *newParams = NULL; SECStatus rv = SECFailure; unsigned long rc2version; switch (type) { case CKM_RC4: case CKM_SEED_ECB: case CKM_CAMELLIA_ECB: case CKM_AES_ECB: case CKM_DES_ECB: case CKM_DES3_ECB: case CKM_IDEA_ECB: case CKM_CDMF_ECB: case CKM_CAST_ECB: case CKM_CAST3_ECB: case CKM_CAST5_ECB: newParams = NULL; rv = SECSuccess; break; case CKM_RC2_ECB: break; case CKM_RC2_CBC: case CKM_RC2_CBC_PAD: rc2_params = (CK_RC2_CBC_PARAMS *)param->data; rc2version = rc2_unmap(rc2_params->ulEffectiveBits); if (SEC_ASN1EncodeUnsignedInteger (NULL, &(rc2.rc2ParameterVersion), rc2version) == NULL) break; rc2.iv.data = rc2_params->iv; rc2.iv.len = sizeof(rc2_params->iv); newParams = SEC_ASN1EncodeItem (NULL, NULL, &rc2, sec_rc2cbc_parameter_template); PORT_Free(rc2.rc2ParameterVersion.data); if (newParams == NULL) break; rv = SECSuccess; break; case CKM_RC5_ECB: /* well not really... */ break; case CKM_RC5_CBC: case CKM_RC5_CBC_PAD: rc5_params = (CK_RC5_CBC_PARAMS *)param->data; if (SEC_ASN1EncodeUnsignedInteger (NULL, &rc5.version, RC5_V10) == NULL) break; if (SEC_ASN1EncodeUnsignedInteger (NULL, &rc5.blockSizeInBits, rc5_params->ulWordsize*8) == NULL) { PORT_Free(rc5.version.data); break; } if (SEC_ASN1EncodeUnsignedInteger (NULL, &rc5.rounds, rc5_params->ulWordsize*8) == NULL) { PORT_Free(rc5.blockSizeInBits.data); PORT_Free(rc5.version.data); break; } rc5.iv.data = rc5_params->pIv; rc5.iv.len = rc5_params->ulIvLen; newParams = SEC_ASN1EncodeItem (NULL, NULL, &rc5, sec_rc5cbc_parameter_template); PORT_Free(rc5.version.data); PORT_Free(rc5.blockSizeInBits.data); PORT_Free(rc5.rounds.data); if (newParams == NULL) break; rv = SECSuccess; break; case CKM_PBE_MD2_DES_CBC: case CKM_PBE_MD5_DES_CBC: case CKM_NETSCAPE_PBE_SHA1_DES_CBC: case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC: case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC: case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC: case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC: case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4: case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4: case CKM_PBE_SHA1_DES3_EDE_CBC: case CKM_PBE_SHA1_DES2_EDE_CBC: case CKM_PBE_SHA1_RC2_40_CBC: case CKM_PBE_SHA1_RC2_128_CBC: case CKM_PBE_SHA1_RC4_40: case CKM_PBE_SHA1_RC4_128: return PBE_PK11ParamToAlgid(algTag, param, arena, algid); default: if (pk11_lookup(type)->iv == 0) { rv = SECSuccess; newParams = NULL; break; } case CKM_SEED_CBC: case CKM_CAMELLIA_CBC: case CKM_AES_CBC: case CKM_DES_CBC: case CKM_DES3_CBC: case CKM_IDEA_CBC: case CKM_CDMF_CBC: case CKM_CAST_CBC: case CKM_CAST3_CBC: case CKM_CAST5_CBC: case CKM_DES_CBC_PAD: case CKM_DES3_CBC_PAD: case CKM_IDEA_CBC_PAD: case CKM_CDMF_CBC_PAD: case CKM_CAST_CBC_PAD: case CKM_CAST3_CBC_PAD: case CKM_CAST5_CBC_PAD: case CKM_SKIPJACK_CBC64: case CKM_SKIPJACK_ECB64: case CKM_SKIPJACK_OFB64: case CKM_SKIPJACK_CFB64: case CKM_SKIPJACK_CFB32: case CKM_SKIPJACK_CFB16: case CKM_SKIPJACK_CFB8: case CKM_BATON_ECB128: case CKM_BATON_ECB96: case CKM_BATON_CBC128: case CKM_BATON_COUNTER: case CKM_BATON_SHUFFLE: case CKM_JUNIPER_ECB128: case CKM_JUNIPER_CBC128: case CKM_JUNIPER_COUNTER: case CKM_JUNIPER_SHUFFLE: newParams = SEC_ASN1EncodeItem(NULL,NULL,param, SEC_ASN1_GET(SEC_OctetStringTemplate) ); if (newParams == NULL) break; rv = SECSuccess; break; } if (rv != SECSuccess) { if (newParams) SECITEM_FreeItem(newParams,PR_TRUE); return rv; } rv = SECOID_SetAlgorithmID(arena, algid, algTag, newParams); SECITEM_FreeItem(newParams,PR_TRUE); return rv; }
static SecCmsCipherContext * SecCmsCipherContextStart(PRArenaPool *poolp, SecSymmetricKeyRef key, SECAlgorithmID *algid, PRBool encrypt) { SecCmsCipherContext *cc; CSSM_CC_HANDLE ciphercc = 0; SECOidData *oidData; SECOidTag algtag; CSSM_ALGORITHMS algorithm; CSSM_PADDING padding = CSSM_PADDING_PKCS7; CSSM_ENCRYPT_MODE mode; CSSM_CSP_HANDLE cspHandle; const CSSM_KEY *cssmKey; OSStatus rv; uint8 ivbuf[8]; CSSM_DATA initVector = { sizeof(ivbuf), ivbuf }; //CSSM_CONTEXT_ATTRIBUTE contextAttribute = { CSSM_ATTRIBUTE_ALG_PARAMS, sizeof(CSSM_DATA_PTR) }; rv = SecKeyGetCSPHandle(key, &cspHandle); if (rv) goto loser; rv = SecKeyGetCSSMKey(key, &cssmKey); if (rv) goto loser; // @@@ Add support for PBE based stuff oidData = SECOID_FindOID(&algid->algorithm); if (!oidData) goto loser; algtag = oidData->offset; algorithm = oidData->cssmAlgorithm; if (!algorithm) goto loser; switch (algtag) { case SEC_OID_RC2_CBC: case SEC_OID_RC4: case SEC_OID_DES_EDE3_CBC: case SEC_OID_DES_EDE: case SEC_OID_DES_CBC: case SEC_OID_RC5_CBC_PAD: case SEC_OID_AES_128_CBC: case SEC_OID_AES_192_CBC: case SEC_OID_AES_256_CBC: case SEC_OID_FORTEZZA_SKIPJACK: mode = CSSM_ALGMODE_CBCPadIV8; break; case SEC_OID_DES_ECB: case SEC_OID_AES_128_ECB: case SEC_OID_AES_192_ECB: case SEC_OID_AES_256_ECB: mode = CSSM_ALGMODE_ECBPad; break; case SEC_OID_DES_OFB: mode = CSSM_ALGMODE_OFBPadIV8; break; case SEC_OID_DES_CFB: mode = CSSM_ALGMODE_CFBPadIV8; break; default: goto loser; } if (encrypt) { CSSM_CC_HANDLE randomcc; //SECItem *parameters; // Generate random initVector if (CSSM_CSP_CreateRandomGenContext(cspHandle, CSSM_ALGID_APPLE_YARROW, NULL, /* seed*/ initVector.Length, &randomcc)) goto loser; if (CSSM_GenerateRandom(randomcc, &initVector)) goto loser; CSSM_DeleteContext(randomcc); // Put IV into algid.parameters switch (algtag) { case SEC_OID_RC4: case SEC_OID_DES_EDE3_CBC: case SEC_OID_DES_EDE: case SEC_OID_DES_CBC: case SEC_OID_AES_128_CBC: case SEC_OID_AES_192_CBC: case SEC_OID_AES_256_CBC: case SEC_OID_FORTEZZA_SKIPJACK: case SEC_OID_DES_ECB: case SEC_OID_AES_128_ECB: case SEC_OID_AES_192_ECB: case SEC_OID_AES_256_ECB: case SEC_OID_DES_OFB: case SEC_OID_DES_CFB: /* Just encode the initVector as an octet string. */ if (!SEC_ASN1EncodeItem(poolp, &algid->parameters, &initVector, SEC_OctetStringTemplate)) goto loser; break; case SEC_OID_RC2_CBC: { sec_rc2cbcParameter rc2 = {}; unsigned long rc2version; SECItem *newParams; rc2.iv = initVector; rc2version = rc2_unmap(cssmKey->KeyHeader.LogicalKeySizeInBits); if (!SEC_ASN1EncodeUnsignedInteger (NULL, &(rc2.rc2ParameterVersion), rc2version)) goto loser; newParams = SEC_ASN1EncodeItem (poolp, &algid->parameters, &rc2, sec_rc2cbc_parameter_template); PORT_Free(rc2.rc2ParameterVersion.Data); if (newParams == NULL) goto loser; break; } case SEC_OID_RC5_CBC_PAD: default: // @@@ Implement rc5 params stuff. goto loser; break; } } else { // Extract IV from algid.parameters // Put IV into algid.parameters switch (algtag) { case SEC_OID_RC4: case SEC_OID_DES_EDE3_CBC: case SEC_OID_DES_EDE: case SEC_OID_DES_CBC: case SEC_OID_AES_128_CBC: case SEC_OID_AES_192_CBC: case SEC_OID_AES_256_CBC: case SEC_OID_FORTEZZA_SKIPJACK: case SEC_OID_DES_ECB: case SEC_OID_AES_128_ECB: case SEC_OID_AES_192_ECB: case SEC_OID_AES_256_ECB: case SEC_OID_DES_OFB: case SEC_OID_DES_CFB: { CSSM_DATA iv = {}; /* Just decode the initVector from an octet string. */ rv = SEC_ASN1DecodeItem(NULL, &iv, SEC_OctetStringTemplate, &(algid->parameters)); if (rv) goto loser; if (initVector.Length != iv.Length) { PORT_Free(iv.Data); goto loser; } memcpy(initVector.Data, iv.Data, initVector.Length); PORT_Free(iv.Data); break; } case SEC_OID_RC2_CBC: { sec_rc2cbcParameter rc2 = {}; unsigned long ulEffectiveBits; rv = SEC_ASN1DecodeItem(NULL, &rc2 ,sec_rc2cbc_parameter_template, &(algid->parameters)); if (rv) goto loser; if (initVector.Length != rc2.iv.Length) { PORT_Free(rc2.iv.Data); PORT_Free(rc2.rc2ParameterVersion.Data); goto loser; } memcpy(initVector.Data, rc2.iv.Data, initVector.Length); PORT_Free(rc2.iv.Data); ulEffectiveBits = rc2_map(&rc2.rc2ParameterVersion); PORT_Free(rc2.rc2ParameterVersion.Data); if (ulEffectiveBits != cssmKey->KeyHeader.LogicalKeySizeInBits) goto loser; break; } case SEC_OID_RC5_CBC_PAD: default: // @@@ Implement rc5 params stuff. goto loser; break; } } if (CSSM_CSP_CreateSymmetricContext(cspHandle, algorithm, mode, NULL, /* accessCred */ cssmKey, &initVector, padding, NULL, /* reserved */ &ciphercc)) goto loser; if (encrypt) rv = CSSM_EncryptDataInit(ciphercc); else rv = CSSM_DecryptDataInit(ciphercc); if (rv) goto loser; cc = (SecCmsCipherContext *)PORT_ZAlloc(sizeof(SecCmsCipherContext)); if (cc == NULL) goto loser; cc->cc = ciphercc; cc->encrypt = encrypt; return cc; loser: if (ciphercc) CSSM_DeleteContext(ciphercc); return NULL; }