/*
 * Class:     org_opensc_pkcs11_wrap_PKCS11Session
 * Method:    verifyUpdateNative
 * Signature: (JJJ[BII)V
 */
JNIEXPORT void JNICALL JNIX_FUNC_NAME(Java_org_opensc_pkcs11_wrap_PKCS11Session_verifyUpdateNative)
  (JNIEnv *env, jclass cls, jlong mh, jlong shandle, jlong hsession, jbyteArray data, jint off, jint len)
{
  int rv;
  CK_BYTE_PTR pPart;
  pkcs11_slot_t *slot;
  pkcs11_module_t *mod =  pkcs11_module_from_jhandle(env,mh);
  if (!mod) return;

  slot = pkcs11_slot_from_jhandle(env,shandle);
  if (!slot) return;

  if (len < 0)
    {
      jnixThrowException(env,"org/opensc/pkcs11/wrap/PKCS11Exception",
                         "Invalid data length %d.",(int)len);
      return;
    }

  if (data == NULL)
    {
      jnixThrowException(env,"org/opensc/pkcs11/wrap/PKCS11Exception",
                         "NULL input data.");
      return;
    }

  if (off < 0 || off > len)
    {
      jnixThrowException(env,"org/opensc/pkcs11/wrap/PKCS11Exception",
                         "Invalid input offset %d.",(int)off);
      return;
    }


  allocaCArrayFromJByteArrayOffLen(pPart,env,data,off,len);

  rv = mod->method->C_VerifyUpdate(hsession,pPart,len);

  if (rv  != CKR_OK)
    {
      jnixThrowExceptionI(env,"org/opensc/pkcs11/wrap/PKCS11Exception",rv,
                          "C_VerifyUpdate failed for slot %d.",
                          (int)slot->id);
      return;
    }
}
예제 #2
0
pkcs11_slot_t *pkcs11_slot_from_jhandle(JNIEnv *env, jlong handle)
{
  pkcs11_slot_t *slot = (pkcs11_slot_t *)(size_t)handle;

  if (!slot || slot->_magic != PKCS11_SLOT_MAGIC)
    {
      jnixThrowException(env,"org/opensc/pkcs11/wrap/PKCS11Exception",
                         "Invalid PKCS11 slot handle %p.",(void*)slot);
      return 0;
    }
  
  return slot;
}
/*
 * Class:     org_opensc_pkcs11_wrap_PKCS11Session
 * Method:    verifyFinalNative
 * Signature: (JJJ[B)Z
 */
JNIEXPORT jboolean JNICALL JNIX_FUNC_NAME(Java_org_opensc_pkcs11_wrap_PKCS11Session_verifyFinalNative)
  (JNIEnv *env, jclass cls, jlong mh, jlong shandle, jlong hsession, jbyteArray data)
{
  int rv;
  CK_BYTE_PTR pSignature;
  CK_ULONG    ulSignatureLen;
  pkcs11_slot_t *slot;
  pkcs11_module_t *mod =  pkcs11_module_from_jhandle(env,mh);
  if (!mod) return JNI_FALSE;

  slot = pkcs11_slot_from_jhandle(env,shandle);
  if (!slot) return JNI_FALSE;

  if (data == NULL)
    {
      jnixThrowException(env,"org/opensc/pkcs11/wrap/PKCS11Exception",
                         "NULL input data.");
      return JNI_FALSE;
    }

  allocaCArrayFromJByteArray(pSignature,ulSignatureLen,env,data);

  rv = mod->method->C_VerifyFinal(hsession,pSignature,ulSignatureLen);

  switch (rv)
    {
    case CKR_SIGNATURE_INVALID:
      return JNI_FALSE;

    case CKR_OK:
      return JNI_TRUE;

    default:
      jnixThrowExceptionI(env,"org/opensc/pkcs11/wrap/PKCS11Exception",rv,
                          "C_VerifyFinal failed for slot %d.",
                          (int)slot->id);
      return JNI_FALSE;
    }
}
/*
 * Class:     org_opensc_pkcs11_wrap_PKCS11Slot
 * Method:    getTokenMaxPinLenNative
 * Signature: (JJ)I
 */
jint JNICALL JNIX_FUNC_NAME(Java_org_opensc_pkcs11_wrap_PKCS11Slot_getTokenMaxPinLenNative)
  (JNIEnv *env, jobject jslot, jlong mh, jlong handle)
{
  pkcs11_slot_t *slot;
  pkcs11_module_t *mod =  pkcs11_module_from_jhandle(env,mh);
  if (!mod) return JNI_FALSE;

  slot = pkcs11_slot_from_jhandle(env,handle);
  if (!slot) return JNI_FALSE;

  if ((slot->ck_slot_info.flags & CKF_TOKEN_PRESENT) == 0)
    jnixThrowExceptionI(env,"org/opensc/pkcs11/wrap/PKCS11Exception",CKR_TOKEN_NOT_PRESENT,
                        "No token present in slot %d.",
                        (int)slot->id);

  if (slot->ck_token_info.ulMaxPinLen > 0x7fffffff ||
      slot->ck_token_info.ulMinPinLen > slot->ck_token_info.ulMaxPinLen )
    jnixThrowException(env,"org/opensc/pkcs11/wrap/PKCS11Exception",
                       "Invalid value %u for ulMaxPinLen of token in slot %d.",
                       (unsigned)slot->ck_token_info.ulMaxPinLen,(int)slot->id);

  return slot->ck_token_info.ulMaxPinLen;
}
예제 #5
0
pkcs11_slot_t *new_pkcs11_slot(JNIEnv *env,  pkcs11_module_t *mod, CK_SLOT_ID id)
{
  int rv;
  pkcs11_slot_t *slot = (pkcs11_slot_t *) malloc(sizeof(pkcs11_slot_t));

  if (!slot)
    {
      jnixThrowException(env,"org/opensc/pkcs11/wrap/PKCS11Exception",
                         "Out of memory allocating PKCS11 slot.");
      return 0;
    }

  memset(slot, 0, sizeof(pkcs11_slot_t));

  slot->_magic = PKCS11_SLOT_MAGIC;
  slot->id = id;

  rv = mod->method->C_GetSlotInfo(id,&slot->ck_slot_info);
  if (rv != CKR_OK)
    {
      jnixThrowExceptionI(env,"org/opensc/pkcs11/wrap/PKCS11Exception",rv,
                          "C_GetSlotInfo for PKCS11 slot %d failed.",(int)id);
      goto failed;
    }

#ifdef DEBUG_PKCS11_SLOT
  fprintf(stderr,"Loaded slot: %d.\n",(int)id);
  fprintf(stderr,"handle= %p.\n",slot);
  fprintf(stderr,"description= %.64s.\n",slot->ck_slot_info.slotDescription);
  fprintf(stderr,"manufacturer= %.32s.\n",slot->ck_slot_info.manufacturerID);
  fprintf(stderr,"flags= %x.\n",(unsigned)slot->ck_slot_info.flags);
  fprintf(stderr,"hardwareVersion= %d.%d.\n",
          (int)slot->ck_slot_info.hardwareVersion.major,
          (int)slot->ck_slot_info.hardwareVersion.minor );
  fprintf(stderr,"firmwareVersion= %d.%d.\n",
          (int)slot->ck_slot_info.firmwareVersion.major,
          (int)slot->ck_slot_info.firmwareVersion.minor );
#endif

  if (slot->ck_slot_info.flags & CKF_TOKEN_PRESENT)
    {
      rv = mod->method->C_GetTokenInfo(id,&slot->ck_token_info);
      if (rv != CKR_OK)
        {
          jnixThrowExceptionI(env,"org/opensc/pkcs11/wrap/PKCS11Exception",rv,
                              "C_GetTokenInfo for PKCS11 slot %d failed.",(int)id);
          goto failed;
        }

#ifdef DEBUG_PKCS11_SLOT
      fprintf(stderr,"token.label= %.32s.\n",slot->ck_token_info.label);
      fprintf(stderr,"token.manufacturer= %.32s.\n",slot->ck_token_info.manufacturerID);
      fprintf(stderr,"token.model= %.16s.\n",slot->ck_token_info.model);
      fprintf(stderr,"token.serialNumber= %.16s.\n",slot->ck_token_info.serialNumber);
      fprintf(stderr,"token.flags= %x.\n",(unsigned)slot->ck_token_info.flags);
      fprintf(stderr,"token.ulMaxSessionCount= %u.\n",
              (unsigned)slot->ck_token_info.ulMaxSessionCount);
      fprintf(stderr,"token.ulMaxPinLen= %u.\n",
              (unsigned)slot->ck_token_info.ulMaxPinLen);
      fprintf(stderr,"token.ulMinPinLen= %u.\n",
              (unsigned)slot->ck_token_info.ulMinPinLen);
#endif
    }
    
  return slot;

failed:
  free(slot);
  return 0;
}
/*
 * Class:     org_opensc_pkcs11_wrap_PKCS11Object
 * Method:    enumObjectsNative
 * Signature: (JJJ[Lorg/opensc/pkcs11/wrap/PKCS11Attribute;)[J
 */
JNIEXPORT jlongArray JNICALL JNIX_FUNC_NAME(Java_org_opensc_pkcs11_wrap_PKCS11Object_enumObjectsNative)
  (JNIEnv *env, jclass jp11obj, jlong mh, jlong shandle, jlong hsession, jobjectArray attrs)
{
  jclass clazz;
  jmethodID getKindID,getDataID;
  CK_ULONG ulAttributeCount;
  CK_ATTRIBUTE_PTR pAttributes;
  CK_ULONG i,count;
  int nobjs,rv;
  CK_ULONG obj_ids[ENUM_HANDLES_BLOCK_SZ];
  size_t ret_obj_ids_sz;
  jlong *ret_obj_ids;
  jlongArray ret;
  pkcs11_slot_t *slot;

  pkcs11_module_t *mod =  pkcs11_module_from_jhandle(env,mh);
  if (!mod) return 0;

  slot = pkcs11_slot_from_jhandle(env,shandle);
  if (!slot) return 0;

  clazz = (*env)->FindClass(env,"org/opensc/pkcs11/wrap/PKCS11Attribute");

  if (!clazz) return 0;

  getKindID = (*env)->GetMethodID(env,clazz,"getKind","()I");

  if (!getKindID) return 0;

  getDataID = (*env)->GetMethodID(env,clazz,"getData","()[B");

  if (!getDataID) return 0;

  ulAttributeCount = (*env)->GetArrayLength(env,attrs);
  pAttributes = alloca(ulAttributeCount * sizeof(CK_ATTRIBUTE));

  for (i=0;i<ulAttributeCount;++i)
    {
      jbyteArray data;
      jobject jattr = (*env)->GetObjectArrayElement(env,attrs,i);
      if (!jattr) return 0;

      pAttributes[i].type = (*env)->CallIntMethod(env,jattr,getKindID);

      data = (jbyteArray)(*env)->CallObjectMethod(env,jattr,getDataID);

      allocaCArrayFromJByteArray(pAttributes[i].pValue,pAttributes[i].ulValueLen,env,data);
    }

  ret_obj_ids_sz = ENUM_HANDLES_BLOCK_SZ;
  nobjs = 0;
  ret_obj_ids=(jlong*)malloc(ret_obj_ids_sz * sizeof(jlong));

  if (!ret_obj_ids)
    {
      jnixThrowException(env,"org/opensc/pkcs11/wrap/PKCS11Exception",
                         "Out of memory during object enumeration for slot number %d.",
                         (int)slot->id);
      goto failed;
    }

  rv = mod->method->C_FindObjectsInit(hsession,pAttributes,ulAttributeCount);

  if (rv  != CKR_OK)
    {
      jnixThrowExceptionI(env,"org/opensc/pkcs11/wrap/PKCS11Exception",rv,
                          "C_FindObjectsInit failed for slot number %d.",
                          (int)slot->id);
      goto failed;
    }

  count = 0;

  rv = mod->method->C_FindObjects(hsession,obj_ids, ENUM_HANDLES_BLOCK_SZ, &count);

  if (rv  != CKR_OK)
    {
      jnixThrowExceptionI(env,"org/opensc/pkcs11/wrap/PKCS11Exception",rv,
                          "C_FindObjects failed for slot number %d.",
                          (int)slot->id);
      goto failed;
    }

  for (i=0; i<count ;++i)
    {
      jlong id = (jlong)obj_ids[i];
      ret_obj_ids[nobjs] = id;
      ++nobjs;
    }

  while (count == ENUM_HANDLES_BLOCK_SZ)
    {
      jlong *new_obj_ids;
      ret_obj_ids_sz += ENUM_HANDLES_BLOCK_SZ;

      new_obj_ids=(jlong*)realloc(ret_obj_ids,ret_obj_ids_sz * sizeof(jlong));
     
      if (!new_obj_ids)
        {
          jnixThrowException(env,"org/opensc/pkcs11/wrap/PKCS11Exception",
                             "Out of memory during object enumeration for slot number %d.",
                             (int)slot->id);
          goto failed;
        }

      ret_obj_ids=new_obj_ids;

      rv = mod->method->C_FindObjects(hsession,obj_ids,ENUM_HANDLES_BLOCK_SZ, &count);
      
      if (rv  != CKR_OK)
        {
          jnixThrowExceptionI(env,"org/opensc/pkcs11/wrap/PKCS11Exception",rv,
                              "C_FindObjects failed for slot number %d.",
                              (int)slot->id);
          goto failed;
        }

      for (i=0; i<count ;++i)
        {
          jlong id = (jlong)obj_ids[i];
          ret_obj_ids[nobjs] = id;
          ++nobjs;
        }
    }

  rv = mod->method->C_FindObjectsFinal(hsession);
  if (rv  != CKR_OK)
    {
      jnixThrowExceptionI(env,"org/opensc/pkcs11/wrap/PKCS11Exception",rv,
                          "C_FindObjectsFinal failed for slot number %d.",
                          (int)slot->id);
      goto failed;
    }

  /* OK, akc it into JAVA's realm. */
  ret = (*env)->NewLongArray(env,nobjs);
  (*env)->SetLongArrayRegion(env,ret,0,nobjs,ret_obj_ids);

  free(ret_obj_ids);
  return ret;

 failed:
  free(ret_obj_ids);
  return 0;
}
/*
 * Class:     org_opensc_pkcs11_spi_PKCS11CipherSpi
 * Method:    updateDecryptNative
 * Signature: (JJJJ[BII)[B
 */
JNIEXPORT jbyteArray JNICALL JNIX_FUNC_NAME(Java_org_opensc_pkcs11_spi_PKCS11CipherSpi_updateDecryptNative)
  (JNIEnv *env, jobject jciph, jlong mh, jlong shandle, jlong hsession, jlong hkey, jbyteArray input, jint off, jint len)
{
  int rv;
  CK_BYTE_PTR pInputPart;
  CK_BYTE_PTR pOutputPart = 0;
  CK_ULONG ulOutputLen = 0;
  jbyteArray ret;
  pkcs11_slot_t *slot;

  pkcs11_module_t *mod =  pkcs11_module_from_jhandle(env,mh);
  if (!mod) return 0;

  slot = pkcs11_slot_from_jhandle(env,shandle);
  if (!slot) return 0;

  if (len < 0)
    {
      jnixThrowException(env,"org/opensc/pkcs11/wrap/PKCS11Exception",
                         "Invalid data length %d.",(int)len);
      return 0;
    }

  if (input == NULL)
    {
      jnixThrowException(env,"org/opensc/pkcs11/wrap/PKCS11Exception",
                         "NULL input data.");
      return 0;
    }

  if (off < 0 || off > len)
    {
      jnixThrowException(env,"org/opensc/pkcs11/wrap/PKCS11Exception",
                         "Invalid input offset %d.",(int)off);
      return 0;
    }

  allocaCArrayFromJByteArrayOffLen(pInputPart,env,input,off,len);

  rv = mod->method->C_DecryptUpdate(hsession,pInputPart,len,pOutputPart,&ulOutputLen);

  if (rv  != CKR_OK)
    {
      jnixThrowExceptionI(env,"org/opensc/pkcs11/wrap/PKCS11Exception",rv,
                          "C_DecryptUpdate failed for slot %d.",
                          (int)slot->id);
      return 0;
    }

  pOutputPart=alloca(ulOutputLen);

  rv = mod->method->C_DecryptUpdate(hsession,pInputPart,len,pOutputPart,&ulOutputLen);

  if (rv  != CKR_OK)
    {
      jnixThrowExceptionI(env,"org/opensc/pkcs11/wrap/PKCS11Exception",rv,
                          "C_DecryptUpdate failed for slot %d.",
                          (int)slot->id);
      return 0;
    }

  ret = (*env)->NewByteArray(env,ulOutputLen);
  if (ret)
    (*env)->SetByteArrayRegion(env,ret,0,ulOutputLen,(jbyte*)pOutputPart);
  
  return ret;
}
/*
 * Class:     org_opensc_pkcs11_spi_PKCS11CipherSpi
 * Method:    doFinalEncryptNativeOff
 * Signature: (JJJJ[BII[BI)I
 */
JNIEXPORT jint JNICALL JNIX_FUNC_NAME(Java_org_opensc_pkcs11_spi_PKCS11CipherSpi_doFinalEncryptNativeOff)
  (JNIEnv *env, jobject jciph, jlong mh, jlong shandle, jlong hsession, jlong hkey, jbyteArray input, jint off, jint len, jbyteArray output, jint output_off)
{
  int rv;
  CK_BYTE_PTR pOutputPart;
  CK_ULONG ulOutputLen,ulOutputLen0,ulOutputLen1;
  CK_BYTE_PTR pInputPart;
  pkcs11_slot_t *slot;
  pkcs11_module_t *mod =  pkcs11_module_from_jhandle(env,mh);

  if (!mod) return 0;

  slot = pkcs11_slot_from_jhandle(env,shandle);
  if (!slot) return 0;

  if (len < 0)
    {
      jnixThrowException(env,"org/opensc/pkcs11/wrap/PKCS11Exception",
                         "Invalid data length %d.",(int)len);
      return 0;
    }

  if (input == NULL)
    {
      jnixThrowException(env,"org/opensc/pkcs11/wrap/PKCS11Exception",
                         "NULL input data.");
      return 0;
    }

  if (off < 0 || off > len)
    {
      jnixThrowException(env,"org/opensc/pkcs11/wrap/PKCS11Exception",
                         "Invalid input offset %d.",(int)off);
      return 0;
    }

  ulOutputLen = (*env)->GetArrayLength(env,output);
  
  if (output_off < 0 || output_off > ulOutputLen)
    {
      jnixThrowException(env,"org/opensc/pkcs11/wrap/PKCS11Exception",
                         "Invalid output offset %d.",(int)output_off);
      return 0;
    }
 
  ulOutputLen -= output_off;
  pOutputPart = alloca(ulOutputLen);
  ulOutputLen0 = ulOutputLen;

  allocaCArrayFromJByteArrayOffLen(pInputPart,env,input,off,len);

  rv = mod->method->C_EncryptUpdate(hsession,pInputPart,len,pOutputPart,&ulOutputLen0);

  if (rv  != CKR_OK)
    {
      jnixThrowExceptionI(env,"org/opensc/pkcs11/wrap/PKCS11Exception",rv,
                          "C_EncryptUpdate failed for slot %d.",
                          (int)slot->id);
      return 0;
    }

  ulOutputLen1 = ulOutputLen - ulOutputLen0;

  rv = mod->method->C_EncryptFinal(hsession,pOutputPart+ulOutputLen0,&ulOutputLen1);

  if (rv  != CKR_OK)
    {
      jnixThrowExceptionI(env,"org/opensc/pkcs11/wrap/PKCS11Exception",rv,
                          "C_EncryptFinal failed for slot %d.",
                          (int)slot->id);
      return 0;
    }

  ulOutputLen = ulOutputLen0+ulOutputLen1;

  (*env)->SetByteArrayRegion(env,output,output_off,ulOutputLen,(jbyte*)pOutputPart);
  
  return ulOutputLen;
}
/*
 * Class:     org_opensc_pkcs11_wrap_PKCS11Session
 * Method:    signNative
 * Signature: (JJJ[BII)[B
 */
JNIEXPORT jbyteArray JNICALL JNIX_FUNC_NAME(Java_org_opensc_pkcs11_wrap_PKCS11Session_signNative)
  (JNIEnv *env, jclass cls, jlong mh, jlong shandle, jlong hsession, jbyteArray ba, jint off, jint len)
{
  int rv;
  CK_BYTE_PTR pMessage = NULL;
  CK_BYTE_PTR pSignature = NULL;
  CK_ULONG    ulSignatureLen = 0;
  jbyteArray ret;
  pkcs11_slot_t *slot;
  pkcs11_module_t *mod =  pkcs11_module_from_jhandle(env,mh);
  if (!mod) return 0;

  slot = pkcs11_slot_from_jhandle(env,shandle);
  if (!slot) return 0;

  if (len < 0)
    {
      jnixThrowException(env,"org/opensc/pkcs11/wrap/PKCS11Exception",
                         "Invalid data length %d.",(int)len);
      return NULL;
    }

  if (ba == NULL)
    {
      jnixThrowException(env,"org/opensc/pkcs11/wrap/PKCS11Exception",
                         "NULL input data.");
      return NULL;
    }

  if (off < 0)
    {
      jnixThrowException(env,"org/opensc/pkcs11/wrap/PKCS11Exception",
                         "Invalid input offset %d.",(int)off);
      return NULL;
    }

  allocaCArrayFromJByteArrayOffLen(pMessage,env,ba,off,len);

  rv = mod->method->C_Sign(hsession,pMessage,len,pSignature,&ulSignatureLen);

  if (rv  != CKR_OK)
    {
      jnixThrowExceptionI(env,"org/opensc/pkcs11/wrap/PKCS11Exception",rv,
                          "C_Sign failed for slot %d.",
                          (int)slot->id);
      return NULL;
    }

  pSignature = (CK_BYTE_PTR)alloca(ulSignatureLen);

  rv = mod->method->C_Sign(hsession,pMessage,len,pSignature,&ulSignatureLen);

  if (rv  != CKR_OK)
    {
      jnixThrowExceptionI(env,"org/opensc/pkcs11/wrap/PKCS11Exception",rv,
                          "C_SignFinal failed for slot %d.",
                          (int)slot->id);
      return NULL;
    }

  ret = (*env)->NewByteArray(env,ulSignatureLen);
  if (ret)
    (*env)->SetByteArrayRegion(env,ret,0,ulSignatureLen,(jbyte*)pSignature);

  return ret;
}