bool NSSCryptoSymmetricKey::encryptInit()

in xsec/enc/NSS/NSSCryptoSymmetricKey.cpp [381:530]


bool NSSCryptoSymmetricKey::encryptInit(bool doPad, 
											SymmetricKeyMode mode, 
											const unsigned char * iv) {

	if (m_initialised == true)
		return true;

	m_doPad = doPad;
	m_keyMode = mode;
	
	if (mp_k == 0) {
		throw XSECCryptoException(XSECCryptoException::SymmetricError,
			"NSS:SymmetricKey - Cannot initialise without key"); 
	}
    else if (m_keyMode == MODE_NONE) {
		throw XSECCryptoException(XSECCryptoException::SymmetricError,
			"NSS:SymmetricKey - Cannot initialise without mode"); 
    }

	// Do some parameter initialisation
	m_initialised = true;

	// Set up the context according to the required cipher type

	const unsigned char * usedIV = NULL;
	unsigned char genIV[256];

	// Tell the library that the IV still has to be sent

	m_ivSent = false;

	switch (m_keyType) {

	case (XSECCryptoSymmetricKey::KEY_3DES_192) :

		// A 3DES key

		if (m_keyMode == MODE_CBC) {

		    if (iv == NULL) {
				
                SECStatus s = PK11_GenerateRandom(genIV, 8);

                if (s != SECSuccess) {

					throw XSECCryptoException(XSECCryptoException::SymmetricError,
						"NSS:SymmetricKey - Error generating random IV");

                }

				usedIV = genIV;

		    }
		    else
				usedIV = iv;

            SECItem ivItem;
            ivItem.data = (unsigned char*)usedIV;
            ivItem.len = 8;
	        int encryptAlg = (m_doPad == true ? CKM_DES3_CBC_PAD : CKM_DES3_CBC);

            SECItem * secParam = PK11_ParamFromIV(encryptAlg, &ivItem);
            mp_ctx = PK11_CreateContextBySymKey(encryptAlg, CKA_ENCRYPT, mp_k, secParam);

            if (secParam)
                SECITEM_FreeItem(secParam, PR_TRUE);

            m_ivSize = 8;
	    }
		else if (m_keyMode == MODE_ECB) {
            mp_ctx = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, mp_k, NULL);

            m_ivSize = 0;
		}
        else {
		    throw XSECCryptoException(XSECCryptoException::SymmetricError,
			        "NSS:SymmetricKey - Unsupported DES3 cipher mode");
        }

		break;

	case (XSECCryptoSymmetricKey::KEY_AES_128) :
    case (XSECCryptoSymmetricKey::KEY_AES_192) :
    case (XSECCryptoSymmetricKey::KEY_AES_256) :

		// An AES key

		if (m_keyMode == MODE_CBC) {

			if (iv == NULL) {
				
				SECStatus s = PK11_GenerateRandom(genIV, 16);
				
                if (s != SECSuccess) {

					throw XSECCryptoException(XSECCryptoException::SymmetricError,
						"NSS:SymmetricKey - Error generating random IV");

                }

				usedIV = genIV;

			}
			else
				usedIV = iv;

			SECItem ivItem;
            ivItem.data = (unsigned char*)usedIV;
            ivItem.len = 16;

            SECItem * secParam = PK11_ParamFromIV(CKM_AES_CBC_PAD, &ivItem);
            mp_ctx = PK11_CreateContextBySymKey(CKM_AES_CBC_PAD, CKA_ENCRYPT, mp_k, secParam);

            if (secParam)
                SECITEM_FreeItem(secParam, PR_TRUE);

            m_ivSize = 16;
		}
		else if (m_keyMode == MODE_ECB) {
			SECItem * secParam = PK11_ParamFromIV(CKM_AES_ECB, NULL);
			mp_ctx = PK11_CreateContextBySymKey(CKM_AES_ECB, CKA_ENCRYPT, mp_k, secParam);
			if (secParam)
				SECITEM_FreeItem(secParam, PR_TRUE);

            m_ivSize = 0;
		}
        else {
		    throw XSECCryptoException(XSECCryptoException::SymmetricError,
			        "NSS:SymmetricKey - Unsupported AES cipher mode");
        }

		break;

	default :

		throw XSECCryptoException(XSECCryptoException::SymmetricError,
			"NSS:SymmetricKey - Unknown key type"); 

	}

	// Add IV
	if (m_keyMode == MODE_CBC || m_keyMode == MODE_GCM) {

		memcpy(m_lastBlock, usedIV, m_ivSize);

	}

	return true;

}