JNIEXPORT jlong JNICALL Java_com_intel_chimera_cipher_OpensslNative_init (JNIEnv *env, jclass clazz, jlong ctx, jint mode, jint alg, jint padding, jbyteArray key, jbyteArray iv) { int jKeyLen = (*env)->GetArrayLength(env, key); int jIvLen = (*env)->GetArrayLength(env, iv); if (jKeyLen != KEY_LENGTH_128 && jKeyLen != KEY_LENGTH_192 && jKeyLen != KEY_LENGTH_256) { THROW(env, "java/lang/IllegalArgumentException", "Invalid key length."); return (jlong)0; } if (jIvLen != IV_LENGTH) { THROW(env, "java/lang/IllegalArgumentException", "Invalid iv length."); return (jlong)0; } EVP_CIPHER_CTX *context = CONTEXT(ctx); if (context == 0) { // Create and initialize a EVP_CIPHER_CTX context = dlsym_EVP_CIPHER_CTX_new(); if (!context) { THROW(env, "java/lang/OutOfMemoryError", NULL); return (jlong)0; } } jbyte *jKey = (*env)->GetByteArrayElements(env, key, NULL); if (jKey == NULL) { THROW(env, "java/lang/InternalError", "Cannot get bytes array for key."); return (jlong)0; } jbyte *jIv = (*env)->GetByteArrayElements(env, iv, NULL); if (jIv == NULL) { (*env)->ReleaseByteArrayElements(env, key, jKey, 0); THROW(env, "java/lang/InternalError", "Cannot get bytes array for iv."); return (jlong)0; } int rc = dlsym_EVP_CipherInit_ex(context, getEvpCipher(alg, jKeyLen), \ NULL, (unsigned char *)jKey, (unsigned char *)jIv, mode == ENCRYPT_MODE); (*env)->ReleaseByteArrayElements(env, key, jKey, 0); (*env)->ReleaseByteArrayElements(env, iv, jIv, 0); if (rc == 0) { dlsym_EVP_CIPHER_CTX_cleanup(context); THROW(env, "java/lang/InternalError", "Error in EVP_CipherInit_ex."); return (jlong)0; } if (padding == NOPADDING) { dlsym_EVP_CIPHER_CTX_set_padding(context, 0); } else if (padding == PKCS5PADDING) { dlsym_EVP_CIPHER_CTX_set_padding(context, 1); } return JLONG(context); }
/** * Create an 256 bit key and IV using the supplied key_data. salt can be added for taste. * Fills in the encryption and decryption ctx objects and returns 0 on success **/ bool OpensslAES::init(const QByteArray &keyData, const QByteArray &saltData) { int i, nrounds = 5; unsigned char key[32], iv[32]; const EVP_CIPHER *evpCipher = getEvpCipher(); if (evpCipher == 0) return false; /* 8 bytes (required EVP_BytesToKey) to salt the key_data during key generation. */ unsigned char salt[8] = {0xAD, 0x7E, 0xF8, 0x14, 0x92, 0x31,0x2B, 0x3F}; QByteArray saltDataHash = QCryptographicHash::hash(saltData, QCryptographicHash::Md5); memcpy(salt, saltDataHash.constData(), 8); /* * Gen key & IV for choosen algoritm. A SHA1 digest is used to hash the supplied key material. * nrounds is the number of times the we hash the material. More rounds are more secure but * slower. */ i = EVP_BytesToKey(evpCipher, EVP_sha1(), salt, (const unsigned char*) keyData.constData(), keyData.size(), nrounds, key, iv); if (i*8 != m_blockSize) { // i*8 = blocksize in bits printf("Key size is %d bytes - should be %d bits\n", i, m_blockSize); return false; } EVP_CIPHER_CTX_init(&m_encoder); EVP_EncryptInit_ex(&m_encoder, evpCipher, 0, key, iv); EVP_CIPHER_CTX_init(&m_decoder); EVP_DecryptInit_ex(&m_decoder, evpCipher, 0, key, iv); return true; }
JNIEXPORT jlong JNICALL Java_org_apache_commons_crypto_cipher_OpenSslNative_init (JNIEnv *env, jclass clazz, jlong ctx, jint mode, jint alg, jint padding, jbyteArray key, jbyteArray iv) { jlong result = 0L; EVP_CIPHER_CTX *context = CONTEXT(ctx); jbyte *jKey = NULL; jbyte *jIv = NULL; int jKeyLen = (*env)->GetArrayLength(env, key); int jIvLen = (*env)->GetArrayLength(env, iv); if (jKeyLen != KEY_LENGTH_128 && jKeyLen != KEY_LENGTH_192 && jKeyLen != KEY_LENGTH_256) { char str[64] = {0}; snprintf(str, sizeof(str), "Invalid AES key length: %d bytes", jKeyLen); THROW(env, "java/security/InvalidKeyException", str); goto cleanup; } if (jIvLen != IV_LENGTH) { THROW(env, "java/security/InvalidAlgorithmParameterException", "Wrong IV length: must be 16 bytes long"); goto cleanup; } if (context == 0) { // Create and initialize a EVP_CIPHER_CTX context = dlsym_EVP_CIPHER_CTX_new(); if (!context) { THROW(env, "java/lang/OutOfMemoryError", NULL); return (jlong)0; } } jKey = (*env)->GetByteArrayElements(env, key, NULL); if (jKey == NULL) { THROW(env, "java/lang/InternalError", "Cannot get bytes array for key."); goto cleanup; } jIv = (*env)->GetByteArrayElements(env, iv, NULL); if (jIv == NULL) { THROW(env, "java/lang/InternalError", "Cannot get bytes array for iv."); goto cleanup; } if (!(alg == AES_CTR || alg == AES_CBC)) { THROW(env, "java/security/NoSuchAlgorithmException", "The algorithm is not supported."); goto cleanup; } int rc = dlsym_EVP_CipherInit_ex(context, getEvpCipher(alg, jKeyLen), \ NULL, (unsigned char *)jKey, (unsigned char *)jIv, mode == ENCRYPT_MODE); if (rc == 0) { THROW(env, "java/lang/InternalError", "Error in EVP_CipherInit_ex."); goto cleanup; } if (padding == NOPADDING) { dlsym_EVP_CIPHER_CTX_set_padding(context, 0); } else if (padding == PKCS5PADDING) { dlsym_EVP_CIPHER_CTX_set_padding(context, 1); } // everything is OK, result = JLONG(context); cleanup: if (result == 0 && context != NULL) { if (CONTEXT(ctx) != NULL) { dlsym_EVP_CIPHER_CTX_cleanup(context); } else { dlsym_EVP_CIPHER_CTX_free(context); } } if (jKey != NULL) { (*env)->ReleaseByteArrayElements(env, key, jKey, 0); } if (jIv != NULL) { (*env)->ReleaseByteArrayElements(env, iv, jIv, 0); } return result; }