Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/native/sun/security/smartcardio/pcsc.c
38918 views
/*1* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/* disable asserts in product mode */26#ifndef DEBUG27#ifndef NDEBUG28#define NDEBUG29#endif30#endif3132#include <stdio.h>33#include <stdlib.h>34#include <string.h>35#include <assert.h>3637#include <winscard.h>3839// #define J2PCSC_DEBUG4041#ifdef J2PCSC_DEBUG42#define dprintf(s) printf(s)43#define dprintf1(s, p1) printf(s, p1)44#define dprintf2(s, p1, p2) printf(s, p1, p2)45#define dprintf3(s, p1, p2, p3) printf(s, p1, p2, p3)46#else47#define dprintf(s)48#define dprintf1(s, p1)49#define dprintf2(s, p1, p2)50#define dprintf3(s, p1, p2, p3)51#endif5253#include "sun_security_smartcardio_PCSC.h"5455#include "pcsc_md.h"5657#define MAX_STACK_BUFFER_SIZE 81925859// make the buffers larger than what should be necessary, just in case60#define ATR_BUFFER_SIZE 12861#define READERNAME_BUFFER_SIZE 12862#define RECEIVE_BUFFER_SIZE MAX_STACK_BUFFER_SIZE6364#define J2PCSC_EXCEPTION_NAME "sun/security/smartcardio/PCSCException"6566void throwOutOfMemoryError(JNIEnv *env, const char *msg) {67jclass cls = (*env)->FindClass(env, "java/lang/OutOfMemoryError");6869if (cls != NULL) /* Otherwise an exception has already been thrown */70(*env)->ThrowNew(env, cls, msg);7172}7374void throwPCSCException(JNIEnv* env, LONG code) {75jclass pcscClass;76jmethodID constructor;77jthrowable pcscException;7879pcscClass = (*env)->FindClass(env, J2PCSC_EXCEPTION_NAME);80if (pcscClass == NULL) {81return;82}83constructor = (*env)->GetMethodID(env, pcscClass, "<init>", "(I)V");84if (constructor == NULL) {85return;86}87pcscException = (jthrowable) (*env)->NewObject(env, pcscClass,88constructor, (jint)code);89if (pcscException != NULL) {90(*env)->Throw(env, pcscException);91}92}9394jboolean handleRV(JNIEnv* env, LONG code) {95if (code == SCARD_S_SUCCESS) {96return JNI_FALSE;97} else {98throwPCSCException(env, code);99return JNI_TRUE;100}101}102103JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {104return JNI_VERSION_1_4;105}106107JNIEXPORT jlong JNICALL Java_sun_security_smartcardio_PCSC_SCardEstablishContext108(JNIEnv *env, jclass thisClass, jint dwScope)109{110SCARDCONTEXT context = 0;111LONG rv;112dprintf("-establishContext\n");113rv = CALL_SCardEstablishContext(dwScope, NULL, NULL, &context);114if (handleRV(env, rv)) {115return 0;116}117// note: SCARDCONTEXT is typedef'd as long, so this works118return (jlong)context;119}120121/**122* Convert a multi string to a java string array,123*/124jobjectArray pcsc_multi2jstring(JNIEnv *env, char *spec) {125jobjectArray result;126jclass stringClass;127char *cp, **tab = NULL;128jstring js;129int cnt = 0;130131cp = spec;132while (*cp != 0) {133cp += (strlen(cp) + 1);134++cnt;135}136137tab = (char **)malloc(cnt * sizeof(char *));138if (tab == NULL) {139throwOutOfMemoryError(env, NULL);140return NULL;141}142143cnt = 0;144cp = spec;145while (*cp != 0) {146tab[cnt++] = cp;147cp += (strlen(cp) + 1);148}149150stringClass = (*env)->FindClass(env, "java/lang/String");151if (stringClass == NULL) {152free(tab);153return NULL;154}155156result = (*env)->NewObjectArray(env, cnt, stringClass, NULL);157if (result != NULL) {158while (cnt-- > 0) {159js = (*env)->NewStringUTF(env, tab[cnt]);160if ((*env)->ExceptionCheck(env)) {161free(tab);162return NULL;163}164(*env)->SetObjectArrayElement(env, result, cnt, js);165if ((*env)->ExceptionCheck(env)) {166free(tab);167return NULL;168}169(*env)->DeleteLocalRef(env, js);170}171}172free(tab);173return result;174}175176JNIEXPORT jobjectArray JNICALL Java_sun_security_smartcardio_PCSC_SCardListReaders177(JNIEnv *env, jclass thisClass, jlong jContext)178{179SCARDCONTEXT context = (SCARDCONTEXT)jContext;180LONG rv;181LPSTR mszReaders = NULL;182DWORD size = 0;183jobjectArray result;184185dprintf1("-context: %x\n", context);186rv = CALL_SCardListReaders(context, NULL, NULL, &size);187if (handleRV(env, rv)) {188return NULL;189}190dprintf1("-size: %d\n", size);191192if (size) {193mszReaders = malloc(size);194if (mszReaders == NULL) {195throwOutOfMemoryError(env, NULL);196return NULL;197}198199rv = CALL_SCardListReaders(context, NULL, mszReaders, &size);200if (handleRV(env, rv)) {201free(mszReaders);202return NULL;203}204dprintf1("-String: %s\n", mszReaders);205}206207result = pcsc_multi2jstring(env, mszReaders);208free(mszReaders);209return result;210}211212JNIEXPORT jlong JNICALL Java_sun_security_smartcardio_PCSC_SCardConnect213(JNIEnv *env, jclass thisClass, jlong jContext, jstring jReaderName,214jint jShareMode, jint jPreferredProtocols)215{216SCARDCONTEXT context = (SCARDCONTEXT)jContext;217LONG rv;218LPCSTR readerName;219SCARDHANDLE card = 0;220DWORD proto = 0;221222readerName = (*env)->GetStringUTFChars(env, jReaderName, NULL);223if (readerName == NULL) {224return 0;225}226rv = CALL_SCardConnect(context, readerName, jShareMode, jPreferredProtocols, &card, &proto);227(*env)->ReleaseStringUTFChars(env, jReaderName, readerName);228dprintf1("-cardhandle: %x\n", card);229dprintf1("-protocol: %d\n", proto);230if (handleRV(env, rv)) {231return 0;232}233234return (jlong)card;235}236237JNIEXPORT jbyteArray JNICALL Java_sun_security_smartcardio_PCSC_SCardTransmit238(JNIEnv *env, jclass thisClass, jlong jCard, jint protocol,239jbyteArray jBuf, jint jOfs, jint jLen)240{241SCARDHANDLE card = (SCARDHANDLE)jCard;242LONG rv;243SCARD_IO_REQUEST sendPci;244unsigned char *sbuf;245unsigned char rbuf[RECEIVE_BUFFER_SIZE];246DWORD rlen = RECEIVE_BUFFER_SIZE;247int ofs = (int)jOfs;248int len = (int)jLen;249jbyteArray jOut;250251sendPci.dwProtocol = protocol;252sendPci.cbPciLength = sizeof(SCARD_IO_REQUEST);253254sbuf = (unsigned char *) ((*env)->GetByteArrayElements(env, jBuf, NULL));255if (sbuf == NULL) {256return NULL;257}258rv = CALL_SCardTransmit(card, &sendPci, sbuf + ofs, len, NULL, rbuf, &rlen);259(*env)->ReleaseByteArrayElements(env, jBuf, (jbyte *)sbuf, JNI_ABORT);260261if (handleRV(env, rv)) {262return NULL;263}264265jOut = (*env)->NewByteArray(env, rlen);266if (jOut != NULL) {267(*env)->SetByteArrayRegion(env, jOut, 0, rlen, (jbyte *)rbuf);268if ((*env)->ExceptionCheck(env)) {269return NULL;270}271}272return jOut;273}274275JNIEXPORT jbyteArray JNICALL Java_sun_security_smartcardio_PCSC_SCardStatus276(JNIEnv *env, jclass thisClass, jlong jCard, jbyteArray jStatus)277{278SCARDHANDLE card = (SCARDHANDLE)jCard;279LONG rv;280char readerName[READERNAME_BUFFER_SIZE];281DWORD readerLen = READERNAME_BUFFER_SIZE;282unsigned char atr[ATR_BUFFER_SIZE];283DWORD atrLen = ATR_BUFFER_SIZE;284DWORD state = 0;285DWORD protocol = 0;286jbyteArray jArray;287jbyte status[2];288289rv = CALL_SCardStatus(card, readerName, &readerLen, &state, &protocol, atr, &atrLen);290if (handleRV(env, rv)) {291return NULL;292}293dprintf1("-reader: %s\n", readerName);294dprintf1("-status: %d\n", state);295dprintf1("-protocol: %d\n", protocol);296297jArray = (*env)->NewByteArray(env, atrLen);298if (jArray == NULL) {299return NULL;300}301(*env)->SetByteArrayRegion(env, jArray, 0, atrLen, (jbyte *)atr);302if ((*env)->ExceptionCheck(env)) {303return NULL;304}305status[0] = (jbyte) state;306status[1] = (jbyte) protocol;307(*env)->SetByteArrayRegion(env, jStatus, 0, 2, status);308if ((*env)->ExceptionCheck(env)) {309return NULL;310}311return jArray;312}313314JNIEXPORT void JNICALL Java_sun_security_smartcardio_PCSC_SCardDisconnect315(JNIEnv *env, jclass thisClass, jlong jCard, jint jDisposition)316{317SCARDHANDLE card = (SCARDHANDLE)jCard;318LONG rv;319320rv = CALL_SCardDisconnect(card, jDisposition);321dprintf1("-disconnect: 0x%X\n", rv);322handleRV(env, rv);323return;324}325326JNIEXPORT jintArray JNICALL Java_sun_security_smartcardio_PCSC_SCardGetStatusChange327(JNIEnv *env, jclass thisClass, jlong jContext, jlong jTimeout,328jintArray jCurrentState, jobjectArray jReaderNames)329{330SCARDCONTEXT context = (SCARDCONTEXT)jContext;331LONG rv;332int readers = (*env)->GetArrayLength(env, jReaderNames);333SCARD_READERSTATE *readerState;334int i;335jintArray jEventState = NULL;336int *currentState = NULL;337const char *readerName;338339readerState = calloc(readers, sizeof(SCARD_READERSTATE));340if (readerState == NULL && readers > 0) {341throwOutOfMemoryError(env, NULL);342return NULL;343}344345currentState = (*env)->GetIntArrayElements(env, jCurrentState, NULL);346if (currentState == NULL) {347free(readerState);348return NULL;349}350351for (i = 0; i < readers; i++) {352readerState[i].szReader = NULL;353}354355for (i = 0; i < readers; i++) {356jobject jReaderName = (*env)->GetObjectArrayElement(env, jReaderNames, i);357if ((*env)->ExceptionCheck(env)) {358goto cleanup;359}360readerName = (*env)->GetStringUTFChars(env, jReaderName, NULL);361if (readerName == NULL) {362goto cleanup;363}364readerState[i].szReader = strdup(readerName);365(*env)->ReleaseStringUTFChars(env, jReaderName, readerName);366if (readerState[i].szReader == NULL) {367throwOutOfMemoryError(env, NULL);368goto cleanup;369}370readerState[i].pvUserData = NULL;371readerState[i].dwCurrentState = currentState[i];372readerState[i].dwEventState = SCARD_STATE_UNAWARE;373readerState[i].cbAtr = 0;374(*env)->DeleteLocalRef(env, jReaderName);375}376377if (readers > 0) {378rv = CALL_SCardGetStatusChange(context, (DWORD)jTimeout, readerState, readers);379if (handleRV(env, rv)) {380goto cleanup;381}382}383384jEventState = (*env)->NewIntArray(env, readers);385if (jEventState == NULL) {386goto cleanup;387}388for (i = 0; i < readers; i++) {389jint eventStateTmp;390dprintf3("-reader status %s: 0x%X, 0x%X\n", readerState[i].szReader,391readerState[i].dwCurrentState, readerState[i].dwEventState);392eventStateTmp = (jint)readerState[i].dwEventState;393(*env)->SetIntArrayRegion(env, jEventState, i, 1, &eventStateTmp);394if ((*env)->ExceptionCheck(env)) {395jEventState = NULL;396goto cleanup;397}398}399cleanup:400(*env)->ReleaseIntArrayElements(env, jCurrentState, currentState, JNI_ABORT);401for (i = 0; i < readers; i++) {402free((char *)readerState[i].szReader);403}404free(readerState);405return jEventState;406}407408JNIEXPORT void JNICALL Java_sun_security_smartcardio_PCSC_SCardBeginTransaction409(JNIEnv *env, jclass thisClass, jlong jCard)410{411SCARDHANDLE card = (SCARDHANDLE)jCard;412LONG rv;413414rv = CALL_SCardBeginTransaction(card);415dprintf1("-beginTransaction: 0x%X\n", rv);416handleRV(env, rv);417return;418}419420JNIEXPORT void JNICALL Java_sun_security_smartcardio_PCSC_SCardEndTransaction421(JNIEnv *env, jclass thisClass, jlong jCard, jint jDisposition)422{423SCARDHANDLE card = (SCARDHANDLE)jCard;424LONG rv;425426rv = CALL_SCardEndTransaction(card, jDisposition);427dprintf1("-endTransaction: 0x%X\n", rv);428handleRV(env, rv);429return;430}431432JNIEXPORT jbyteArray JNICALL Java_sun_security_smartcardio_PCSC_SCardControl433(JNIEnv *env, jclass thisClass, jlong jCard, jint jControlCode, jbyteArray jSendBuffer)434{435SCARDHANDLE card = (SCARDHANDLE)jCard;436LONG rv;437jbyte* sendBuffer;438jint sendBufferLength = (*env)->GetArrayLength(env, jSendBuffer);439jbyte receiveBuffer[MAX_STACK_BUFFER_SIZE];440jint receiveBufferLength = MAX_STACK_BUFFER_SIZE;441ULONG returnedLength = 0;442jbyteArray jReceiveBuffer;443444sendBuffer = (*env)->GetByteArrayElements(env, jSendBuffer, NULL);445if (sendBuffer == NULL) {446return NULL;447}448449#ifdef J2PCSC_DEBUG450{451int k;452printf("-control: 0x%X\n", jControlCode);453printf("-send: ");454for (k = 0; k < sendBufferLength; k++) {455printf("%02x ", sendBuffer[k]);456}457printf("\n");458}459#endif460461rv = CALL_SCardControl(card, jControlCode, sendBuffer, sendBufferLength,462receiveBuffer, receiveBufferLength, &returnedLength);463464(*env)->ReleaseByteArrayElements(env, jSendBuffer, sendBuffer, JNI_ABORT);465if (handleRV(env, rv)) {466return NULL;467}468469#ifdef J2PCSC_DEBUG470{471int k;472printf("-recv: ");473for (k = 0; k < returnedLength; k++) {474printf("%02x ", receiveBuffer[k]);475}476printf("\n");477}478#endif479480jReceiveBuffer = (*env)->NewByteArray(env, returnedLength);481if (jReceiveBuffer == NULL) {482return NULL;483}484(*env)->SetByteArrayRegion(env, jReceiveBuffer, 0, returnedLength, receiveBuffer);485if ((*env)->ExceptionCheck(env)) {486return NULL;487}488return jReceiveBuffer;489}490491492