scrypt_jni.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. // Copyright (C) 2011 - Will Glozer. All rights reserved.
  2. #include <errno.h>
  3. #include <stdlib.h>
  4. #include <inttypes.h>
  5. #include <jni.h>
  6. #include "crypto_scrypt.h"
  7. #ifdef ANDROID
  8. #include <android/log.h>
  9. #include <stdint.h>
  10. #define ANDROID_LOG_TAG "ScryptLog"
  11. #define ALOG(msg, ...) __android_log_print(ANDROID_LOG_VERBOSE, ANDROID_LOG_TAG, msg, ##__VA_ARGS__)
  12. #define STR1(x) #x
  13. #define STR(x) STR1(x)
  14. void log_basic_info();
  15. #endif
  16. jbyteArray JNICALL scryptN(JNIEnv *env, jclass cls, jbyteArray passwd, jbyteArray salt,
  17. jint N, jint r, jint p, jint dkLen)
  18. {
  19. #ifdef ANDROID
  20. log_basic_info();
  21. #endif
  22. jint Plen = (*env)->GetArrayLength(env, passwd);
  23. jint Slen = (*env)->GetArrayLength(env, salt);
  24. jbyte *P = (*env)->GetByteArrayElements(env, passwd, NULL);
  25. jbyte *S = (*env)->GetByteArrayElements(env, salt, NULL);
  26. uint8_t *buf = malloc(sizeof(uint8_t) * dkLen);
  27. jbyteArray DK = NULL;
  28. if (P == NULL || S == NULL || buf == NULL) goto cleanup;
  29. if (crypto_scrypt((uint8_t *) P, Plen, (uint8_t *) S, Slen, N, r, p, buf, dkLen)) {
  30. jclass e = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
  31. char *msg;
  32. switch (errno) {
  33. case EINVAL:
  34. msg = "N must be a power of 2 greater than 1";
  35. break;
  36. case EFBIG:
  37. case ENOMEM:
  38. msg = "Insufficient memory available";
  39. break;
  40. default:
  41. msg = "Memory allocation failed";
  42. }
  43. (*env)->ThrowNew(env, e, msg);
  44. goto cleanup;
  45. }
  46. DK = (*env)->NewByteArray(env, dkLen);
  47. if (DK == NULL) goto cleanup;
  48. (*env)->SetByteArrayRegion(env, DK, 0, dkLen, (jbyte *) buf);
  49. cleanup:
  50. if (P) (*env)->ReleaseByteArrayElements(env, passwd, P, JNI_ABORT);
  51. if (S) (*env)->ReleaseByteArrayElements(env, salt, S, JNI_ABORT);
  52. if (buf) free(buf);
  53. return DK;
  54. }
  55. #ifdef ANDROID
  56. char *get_byte_array_summary(JNIEnv *env, jbyteArray jarray) {
  57. int len = (*env)->GetArrayLength(env, jarray);
  58. jbyte *bytes = (*env)->GetByteArrayElements(env, jarray, NULL);
  59. static char buff[10240];
  60. int i;
  61. for (i = 0; i < len; ++i) {
  62. buff[i] = bytes[i] % 32 + 'a';
  63. }
  64. buff[i] = '\0';
  65. if (bytes) (*env)->ReleaseByteArrayElements(env, jarray, bytes, JNI_ABORT);
  66. return buff;
  67. }
  68. void log_basic_info() {
  69. ALOG("Basic info for native scrypt run:");
  70. ALOG("Native library targeting arch: %s", STR(ANDROID_TARGET_ARCH));
  71. }
  72. #endif
  73. static const JNINativeMethod methods[] = {
  74. { "scryptN", "([B[BIIII)[B", (void *) scryptN }
  75. };
  76. jint JNI_OnLoad(JavaVM *vm, void *reserved) {
  77. JNIEnv *env;
  78. if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6) != JNI_OK) {
  79. return -1;
  80. }
  81. jclass cls = (*env)->FindClass(env, "com/lambdaworks/crypto/SCrypt");
  82. int r = (*env)->RegisterNatives(env, cls, methods, 1);
  83. return (r == JNI_OK) ? JNI_VERSION_1_6 : -1;
  84. }