Exemple #1
0
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;
}