bool OpenSSLCryptoSymmetricKey::encryptInit()

in xsec/enc/OpenSSL/OpenSSLCryptoSymmetricKey.cpp [603:891]


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

	if (m_initialised == true)
		return true;

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

	// Do some parameter initialisation
	m_initialised = true;
	m_bytesInLastBlock = 0;

	// 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) {
				
				bool res = ((RAND_status() == 1) && (RAND_bytes(genIV, 8) == 1));
				if (res == false) {
					throw XSECCryptoException(XSECCryptoException::SymmetricError,
						"OpenSSL:SymmetricKey - Error generating random IV");
				}

				usedIV = genIV;

			}
			else {
				usedIV = iv;
            }

#if defined (XSEC_OPENSSL_CONST_BUFFERS)
			EVP_EncryptInit(mp_ctx, EVP_des_ede3_cbc(), m_keyBuf.rawBuffer(), usedIV);
#else
			EVP_EncryptInit(mp_ctx, EVP_des_ede3_cbc(), (unsigned char *) m_keyBuf.rawBuffer(), (unsigned char *) usedIV);
#endif
		}
		else if (m_keyMode == MODE_ECB) {
#if defined (XSEC_OPENSSL_CONST_BUFFERS)
			EVP_EncryptInit(mp_ctx, EVP_des_ede3_ecb(), m_keyBuf.rawBuffer(), NULL);
#else
			EVP_EncryptInit(mp_ctx, EVP_des_ede3(), (unsigned char *) m_keyBuf.rawBuffer(), NULL);
#endif
		}
        else {
		    throw XSECCryptoException(XSECCryptoException::SymmetricError,
			    "OpenSSL:SymmetricKey - Unsupported DES3 cipher mode"); 
        }


		m_blockSize = 8;
		break;

#if defined (XSEC_OPENSSL_HAVE_AES)

	case (XSECCryptoSymmetricKey::KEY_AES_128) :

		// An AES key

		if (m_keyMode == MODE_CBC) {

			if (iv == NULL) {
				
				bool res = ((RAND_status() == 1) && (RAND_bytes(genIV, 16) == 1));
				if (res == false) {
					throw XSECCryptoException(XSECCryptoException::SymmetricError,
						"OpenSSL:SymmetricKey - Error generating random IV");
				}

				usedIV = genIV;

			}
			else
				usedIV = iv;

			EVP_EncryptInit_ex(mp_ctx, EVP_aes_128_cbc(), NULL, m_keyBuf.rawBuffer(), usedIV);
		}
		else if (m_keyMode == MODE_ECB) {

			EVP_EncryptInit_ex(mp_ctx, EVP_aes_128_ecb(), NULL, m_keyBuf.rawBuffer(), NULL);

		}
#ifdef XSEC_OPENSSL_HAVE_GCM
		else if (m_keyMode == MODE_GCM) {

			if (iv == NULL) {
				
				bool res = ((RAND_status() == 1) && (RAND_bytes(genIV, 12) == 1));
				if (res == false) {
					throw XSECCryptoException(XSECCryptoException::SymmetricError,
						"OpenSSL:SymmetricKey - Error generating random IV");
				}

				usedIV = genIV;

			}
			else
				usedIV = iv;

			EVP_EncryptInit_ex(mp_ctx, EVP_aes_128_gcm(), NULL, m_keyBuf.rawBuffer(), usedIV);
		}
#endif
        else {
		    throw XSECCryptoException(XSECCryptoException::SymmetricError,
			    "OpenSSL:SymmetricKey - Unsupported AES cipher mode");
        }

		m_blockSize = 16;
		break;

	case (XSECCryptoSymmetricKey::KEY_AES_192) :

		// An AES key

		if (m_keyMode == MODE_CBC) {

			if (iv == NULL) {
				
				bool res = ((RAND_status() == 1) && (RAND_bytes(genIV, 16) == 1));
				if (res == false) {
					throw XSECCryptoException(XSECCryptoException::SymmetricError,
						"OpenSSL:SymmetricKey - Error generating random IV");
				}

				usedIV = genIV;

			}
			else
				usedIV = iv;

			EVP_EncryptInit_ex(mp_ctx, EVP_aes_192_cbc(), NULL, m_keyBuf.rawBuffer(), usedIV);

		}
#ifdef XSEC_OPENSSL_HAVE_GCM
		else if (m_keyMode == MODE_GCM) {

			if (iv == NULL) {
				
				bool res = ((RAND_status() == 1) && (RAND_bytes(genIV, 12) == 1));
				if (res == false) {
					throw XSECCryptoException(XSECCryptoException::SymmetricError,
						"OpenSSL:SymmetricKey - Error generating random IV");
				}

				usedIV = genIV;

			}
			else
				usedIV = iv;

			EVP_EncryptInit_ex(mp_ctx, EVP_aes_192_gcm(), NULL, m_keyBuf.rawBuffer(), usedIV);
		}
#endif
		else if (m_keyMode == MODE_ECB) {

			EVP_EncryptInit_ex(mp_ctx, EVP_aes_192_ecb(), NULL, m_keyBuf.rawBuffer(), NULL);
		}
        else {
		    throw XSECCryptoException(XSECCryptoException::SymmetricError,
			    "OpenSSL:SymmetricKey - Unsupported AES cipher mode");
        }

		m_blockSize = 16;
		break;

	case (XSECCryptoSymmetricKey::KEY_AES_256) :

		// An AES key

		if (m_keyMode == MODE_CBC) {
			if (iv == NULL) {
				
				bool res = ((RAND_status() == 1) && (RAND_bytes(genIV, 16) == 1));
				if (res == false) {
					throw XSECCryptoException(XSECCryptoException::SymmetricError,
						"OpenSSL:SymmetricKey - Error generating random IV");
				}

				usedIV = genIV;

			}
			else
				usedIV = iv;

			EVP_EncryptInit_ex(mp_ctx, EVP_aes_256_cbc(), NULL, m_keyBuf.rawBuffer(), usedIV);

		}
#ifdef XSEC_OPENSSL_HAVE_GCM
		else if (m_keyMode == MODE_GCM) {

			if (iv == NULL) {
				
				bool res = ((RAND_status() == 1) && (RAND_bytes(genIV, 12) == 1));
				if (res == false) {
					throw XSECCryptoException(XSECCryptoException::SymmetricError,
						"OpenSSL:SymmetricKey - Error generating random IV");
				}

				usedIV = genIV;

			}
			else
				usedIV = iv;

			EVP_EncryptInit_ex(mp_ctx, EVP_aes_256_gcm(), NULL, m_keyBuf.rawBuffer(), usedIV);
		}
#endif
		else if (m_keyMode == MODE_ECB) {

			EVP_EncryptInit_ex(mp_ctx, EVP_aes_256_ecb(), NULL, m_keyBuf.rawBuffer(), NULL);

		}
        else {
		    throw XSECCryptoException(XSECCryptoException::SymmetricError,
			    "OpenSSL:SymmetricKey - Unsupported AES cipher mode");
        }

		m_blockSize = 16;
		break;

#else 

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

		throw XSECCryptoException(XSECCryptoException::UnsupportedAlgorithm,
			 "OpenSSL:SymmetricKey - AES not supported in this version of OpenSSL");

#endif /* XSEC_OPENSSL_HAVE_AES */

	default :

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

	}

	// Clear up any read padding

	if (m_keyMode == MODE_CBC) {
		m_ivSize = m_blockSize;
		memcpy(m_lastBlock, usedIV, m_ivSize);
	}
    else if (m_keyMode == MODE_GCM) {
        m_ivSize = 12;
        memcpy(m_lastBlock, usedIV, m_ivSize);
    }
	else {
		m_ivSize = 0;
    }

#if defined (XSEC_OPENSSL_CANSET_PADDING)
	// Setup padding
	if (m_doPad) {
		EVP_CIPHER_CTX_set_padding(mp_ctx, 1);
	}
	else {
		EVP_CIPHER_CTX_set_padding(mp_ctx, 0);
	}
#endif

	return true;

}