0N/A/*
2928N/A * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
0N/A */
0N/A
0N/A/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
0N/A *
0N/A * Redistribution and use in source and binary forms, with or without
0N/A * modification, are permitted provided that the following conditions are met:
0N/A *
0N/A * 1. Redistributions of source code must retain the above copyright notice,
0N/A * this list of conditions and the following disclaimer.
0N/A *
0N/A * 2. Redistributions in binary form must reproduce the above copyright notice,
0N/A * this list of conditions and the following disclaimer in the documentation
0N/A * and/or other materials provided with the distribution.
0N/A *
0N/A * 3. The end-user documentation included with the redistribution, if any, must
0N/A * include the following acknowledgment:
0N/A *
0N/A * "This product includes software developed by IAIK of Graz University of
0N/A * Technology."
0N/A *
0N/A * Alternately, this acknowledgment may appear in the software itself, if
0N/A * and wherever such third-party acknowledgments normally appear.
0N/A *
0N/A * 4. The names "Graz University of Technology" and "IAIK of Graz University of
0N/A * Technology" must not be used to endorse or promote products derived from
0N/A * this software without prior written permission.
0N/A *
0N/A * 5. Products derived from this software may not be called
0N/A * "IAIK PKCS Wrapper", nor may "IAIK" appear in their name, without prior
0N/A * written permission of Graz University of Technology.
0N/A *
0N/A * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
0N/A * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
0N/A * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
0N/A * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE LICENSOR BE
0N/A * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
0N/A * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
0N/A * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
0N/A * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
0N/A * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0N/A * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
0N/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0N/A * POSSIBILITY OF SUCH DAMAGE.
0N/A * ===========================================================================
0N/A */
0N/A
0N/A#include "pkcs11wrapper.h"
0N/A
0N/A#include <stdio.h>
0N/A#include <stdlib.h>
0N/A#include <string.h>
0N/A#include <assert.h>
0N/A
0N/A#include "sun_security_pkcs11_wrapper_PKCS11.h"
0N/A
0N/A#ifdef P11_ENABLE_C_ENCRYPTINIT
0N/A/*
0N/A * Class: sun_security_pkcs11_wrapper_PKCS11
0N/A * Method: C_EncryptInit
0N/A * Signature: (JLsun/security/pkcs11/wrapper/CK_MECHANISM;J)V
0N/A * Parametermapping: *PKCS11*
0N/A * @param jlong jSessionHandle CK_SESSION_HANDLE hSession
0N/A * @param jobject jMechanism CK_MECHANISM_PTR pMechanism
0N/A * @param jlong jKeyHandle CK_OBJECT_HANDLE hKey
0N/A */
0N/AJNIEXPORT void JNICALL
0N/AJava_sun_security_pkcs11_wrapper_PKCS11_C_1EncryptInit
0N/A(JNIEnv *env, jobject obj, jlong jSessionHandle,
0N/A jobject jMechanism, jlong jKeyHandle)
0N/A{
0N/A CK_SESSION_HANDLE ckSessionHandle;
0N/A CK_MECHANISM ckMechanism;
0N/A CK_OBJECT_HANDLE ckKeyHandle;
0N/A CK_RV rv;
0N/A
0N/A CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
0N/A if (ckpFunctions == NULL) { return; }
0N/A
0N/A ckSessionHandle = jLongToCKULong(jSessionHandle);
0N/A ckKeyHandle = jLongToCKULong(jKeyHandle);
0N/A jMechanismToCKMechanism(env, jMechanism, &ckMechanism);
936N/A if ((*env)->ExceptionCheck(env)) { return; }
0N/A
0N/A rv = (*ckpFunctions->C_EncryptInit)(ckSessionHandle, &ckMechanism,
0N/A ckKeyHandle);
0N/A
0N/A if (ckMechanism.pParameter != NULL_PTR) {
0N/A free(ckMechanism.pParameter);
0N/A }
0N/A
0N/A if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; }
0N/A}
0N/A#endif
0N/A
0N/A#ifdef P11_ENABLE_C_ENCRYPT
0N/A/*
0N/A * Class: sun_security_pkcs11_wrapper_PKCS11
0N/A * Method: C_Encrypt
0N/A * Signature: (J[BII[BII)I
0N/A * Parametermapping: *PKCS11*
0N/A * @param jlong jSessionHandle CK_SESSION_HANDLE hSession
0N/A * @param jbyteArray jData CK_BYTE_PTR pData
0N/A * CK_ULONG ulDataLen
0N/A * @return jbyteArray jEncryptedData CK_BYTE_PTR pEncryptedData
0N/A * CK_ULONG_PTR pulEncryptedDataLen
0N/A */
0N/AJNIEXPORT jint JNICALL
0N/AJava_sun_security_pkcs11_wrapper_PKCS11_C_1Encrypt
0N/A(JNIEnv *env, jobject obj, jlong jSessionHandle,
0N/A jbyteArray jIn, jint jInOfs, jint jInLen,
0N/A jbyteArray jOut, jint jOutOfs, jint jOutLen)
0N/A{
0N/A CK_SESSION_HANDLE ckSessionHandle;
0N/A CK_RV rv;
2928N/A
0N/A CK_BYTE_PTR inBufP;
0N/A CK_BYTE_PTR outBufP;
0N/A CK_ULONG ckEncryptedPartLen;
0N/A
0N/A CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
0N/A if (ckpFunctions == NULL) { return 0; }
0N/A
0N/A ckSessionHandle = jLongToCKULong(jSessionHandle);
0N/A
2928N/A inBufP = (*env)->GetPrimitiveArrayCritical(env, jIn, NULL);
2928N/A if (inBufP == NULL) { return 0; }
2928N/A
2928N/A outBufP = (*env)->GetPrimitiveArrayCritical(env, jOut, NULL);
2928N/A if (outBufP == NULL) {
2928N/A // Make sure to release inBufP
2928N/A (*env)->ReleasePrimitiveArrayCritical(env, jIn, inBufP, JNI_ABORT);
936N/A return 0;
936N/A }
0N/A
0N/A ckEncryptedPartLen = jOutLen;
0N/A
2928N/A rv = (*ckpFunctions->C_Encrypt)(ckSessionHandle,
2928N/A (CK_BYTE_PTR)(inBufP + jInOfs), jInLen,
2928N/A (CK_BYTE_PTR)(outBufP + jOutOfs),
2928N/A &ckEncryptedPartLen);
0N/A
2928N/A (*env)->ReleasePrimitiveArrayCritical(env, jOut, outBufP, JNI_ABORT);
2928N/A (*env)->ReleasePrimitiveArrayCritical(env, jIn, inBufP, JNI_ABORT);
2928N/A
2928N/A ckAssertReturnValueOK(env, rv);
0N/A return ckEncryptedPartLen;
0N/A}
0N/A#endif
0N/A
0N/A#ifdef P11_ENABLE_C_ENCRYPTUPDATE
0N/A/*
0N/A * Class: sun_security_pkcs11_wrapper_PKCS11
0N/A * Method: C_EncryptUpdate
0N/A * Signature: (J[BII[BII)I
0N/A * Parametermapping: *PKCS11*
0N/A * @param jlong jSessionHandle CK_SESSION_HANDLE hSession
0N/A * @param jbyteArray jPart CK_BYTE_PTR pPart
0N/A * CK_ULONG ulPartLen
0N/A * @return jbyteArray jEncryptedPart CK_BYTE_PTR pEncryptedPart
0N/A * CK_ULONG_PTR pulEncryptedPartLen
0N/A */
0N/AJNIEXPORT jint JNICALL
0N/AJava_sun_security_pkcs11_wrapper_PKCS11_C_1EncryptUpdate
0N/A(JNIEnv *env, jobject obj, jlong jSessionHandle,
0N/A jlong directIn, jbyteArray jIn, jint jInOfs, jint jInLen,
0N/A jlong directOut, jbyteArray jOut, jint jOutOfs, jint jOutLen)
0N/A{
0N/A CK_SESSION_HANDLE ckSessionHandle;
0N/A CK_RV rv;
2928N/A
0N/A CK_BYTE_PTR inBufP;
0N/A CK_BYTE_PTR outBufP;
0N/A CK_ULONG ckEncryptedPartLen;
0N/A
0N/A CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
0N/A if (ckpFunctions == NULL) { return 0; }
0N/A
0N/A ckSessionHandle = jLongToCKULong(jSessionHandle);
0N/A
0N/A if (directIn != 0) {
2928N/A inBufP = (CK_BYTE_PTR) directIn;
0N/A } else {
2928N/A inBufP = (*env)->GetPrimitiveArrayCritical(env, jIn, NULL);
2928N/A if (inBufP == NULL) { return 0; }
2928N/A }
2928N/A
2928N/A if (directOut != 0) {
2928N/A outBufP = (CK_BYTE_PTR) directOut;
2928N/A } else {
2928N/A outBufP = (*env)->GetPrimitiveArrayCritical(env, jOut, NULL);
2928N/A if (outBufP == NULL) {
2928N/A // Make sure to release inBufP
2928N/A (*env)->ReleasePrimitiveArrayCritical(env, jIn, inBufP, JNI_ABORT);
936N/A return 0;
936N/A }
0N/A }
0N/A
0N/A ckEncryptedPartLen = jOutLen;
0N/A
0N/A //printf("EU: inBufP=%i, jInOfs=%i, jInLen=%i, outBufP=%i\n",
0N/A // inBufP, jInOfs, jInLen, outBufP);
0N/A
0N/A rv = (*ckpFunctions->C_EncryptUpdate)(ckSessionHandle,
2928N/A (CK_BYTE_PTR)(inBufP + jInOfs), jInLen,
2928N/A (CK_BYTE_PTR)(outBufP + jOutOfs),
2928N/A &ckEncryptedPartLen);
0N/A
0N/A //printf("EU: ckEncryptedPartLen=%i\n", ckEncryptedPartLen);
0N/A
2928N/A if (directIn == 0) {
2928N/A (*env)->ReleasePrimitiveArrayCritical(env, jIn, inBufP, JNI_ABORT);
0N/A }
0N/A
2928N/A if (directOut == 0) {
2928N/A (*env)->ReleasePrimitiveArrayCritical(env, jOut, outBufP, JNI_ABORT);
0N/A }
2928N/A
2928N/A ckAssertReturnValueOK(env, rv);
2928N/A
0N/A return ckEncryptedPartLen;
0N/A}
0N/A#endif
0N/A
0N/A#ifdef P11_ENABLE_C_ENCRYPTFINAL
0N/A/*
0N/A * Class: sun_security_pkcs11_wrapper_PKCS11
0N/A * Method: C_EncryptFinal
0N/A * Signature: (J[BII)I
0N/A * Parametermapping: *PKCS11*
0N/A * @param jlong jSessionHandle CK_SESSION_HANDLE hSession
0N/A * @return jbyteArray jLastEncryptedPart CK_BYTE_PTR pLastEncryptedDataPart
0N/A * CK_ULONG_PTR pulLastEncryptedDataPartLen
0N/A */
0N/AJNIEXPORT jint JNICALL
0N/AJava_sun_security_pkcs11_wrapper_PKCS11_C_1EncryptFinal
0N/A(JNIEnv *env, jobject obj, jlong jSessionHandle,
0N/A jlong directOut, jbyteArray jOut, jint jOutOfs, jint jOutLen)
0N/A{
0N/A CK_SESSION_HANDLE ckSessionHandle;
0N/A CK_RV rv;
0N/A CK_BYTE_PTR outBufP;
0N/A CK_ULONG ckLastEncryptedPartLen;
0N/A
0N/A CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
0N/A if (ckpFunctions == NULL) { return 0; }
0N/A
0N/A ckSessionHandle = jLongToCKULong(jSessionHandle);
0N/A
0N/A if (directOut != 0) {
2928N/A outBufP = (CK_BYTE_PTR) directOut;
0N/A } else {
2928N/A outBufP = (*env)->GetPrimitiveArrayCritical(env, jOut, NULL);
2928N/A if (outBufP == NULL) { return 0; }
0N/A }
0N/A
2928N/A ckLastEncryptedPartLen = jOutLen;
2928N/A
0N/A //printf("EF: outBufP=%i\n", outBufP);
0N/A
2928N/A rv = (*ckpFunctions->C_EncryptFinal)(ckSessionHandle,
2928N/A (CK_BYTE_PTR)(outBufP + jOutOfs),
0N/A &ckLastEncryptedPartLen);
0N/A
0N/A //printf("EF: ckLastEncryptedPartLen=%i", ckLastEncryptedPartLen);
0N/A
2928N/A if (directOut == 0) {
2928N/A (*env)->ReleasePrimitiveArrayCritical(env, jOut, outBufP, JNI_ABORT);
0N/A }
0N/A
2928N/A ckAssertReturnValueOK(env, rv);
2928N/A
0N/A return ckLastEncryptedPartLen;
0N/A}
0N/A#endif
0N/A
0N/A#ifdef P11_ENABLE_C_DECRYPTINIT
0N/A/*
0N/A * Class: sun_security_pkcs11_wrapper_PKCS11
0N/A * Method: C_DecryptInit
0N/A * Signature: (JLsun/security/pkcs11/wrapper/CK_MECHANISM;J)V
0N/A * Parametermapping: *PKCS11*
0N/A * @param jlong jSessionHandle CK_SESSION_HANDLE hSession
0N/A * @param jobject jMechanism CK_MECHANISM_PTR pMechanism
0N/A * @param jlong jKeyHandle CK_OBJECT_HANDLE hKey
0N/A */
0N/AJNIEXPORT void JNICALL
0N/AJava_sun_security_pkcs11_wrapper_PKCS11_C_1DecryptInit
0N/A(JNIEnv *env, jobject obj, jlong jSessionHandle,
0N/A jobject jMechanism, jlong jKeyHandle)
0N/A{
0N/A CK_SESSION_HANDLE ckSessionHandle;
0N/A CK_MECHANISM ckMechanism;
0N/A CK_OBJECT_HANDLE ckKeyHandle;
0N/A CK_RV rv;
0N/A
0N/A CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
0N/A if (ckpFunctions == NULL) { return; }
0N/A
0N/A ckSessionHandle = jLongToCKULong(jSessionHandle);
0N/A ckKeyHandle = jLongToCKULong(jKeyHandle);
0N/A jMechanismToCKMechanism(env, jMechanism, &ckMechanism);
936N/A if ((*env)->ExceptionCheck(env)) { return; }
0N/A
0N/A rv = (*ckpFunctions->C_DecryptInit)(ckSessionHandle, &ckMechanism,
0N/A ckKeyHandle);
0N/A
0N/A if (ckMechanism.pParameter != NULL_PTR) {
0N/A free(ckMechanism.pParameter);
0N/A }
0N/A
0N/A if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; }
0N/A}
0N/A#endif
0N/A
0N/A#ifdef P11_ENABLE_C_DECRYPT
0N/A/*
0N/A * Class: sun_security_pkcs11_wrapper_PKCS11
0N/A * Method: C_Decrypt
0N/A * Signature: (J[BII[BII)I
0N/A * Parametermapping: *PKCS11*
0N/A * @param jlong jSessionHandle CK_SESSION_HANDLE hSession
0N/A * @param jbyteArray jEncryptedData CK_BYTE_PTR pEncryptedData
0N/A * CK_ULONG ulEncryptedDataLen
0N/A * @return jbyteArray jData CK_BYTE_PTR pData
0N/A * CK_ULONG_PTR pulDataLen
0N/A */
0N/AJNIEXPORT jint JNICALL
0N/AJava_sun_security_pkcs11_wrapper_PKCS11_C_1Decrypt
0N/A(JNIEnv *env, jobject obj, jlong jSessionHandle,
0N/A jbyteArray jIn, jint jInOfs, jint jInLen,
0N/A jbyteArray jOut, jint jOutOfs, jint jOutLen)
0N/A{
0N/A CK_SESSION_HANDLE ckSessionHandle;
0N/A CK_RV rv;
2928N/A
0N/A CK_BYTE_PTR inBufP;
0N/A CK_BYTE_PTR outBufP;
0N/A CK_ULONG ckPartLen;
0N/A
0N/A CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
0N/A if (ckpFunctions == NULL) { return 0; }
0N/A
0N/A ckSessionHandle = jLongToCKULong(jSessionHandle);
0N/A
2928N/A inBufP = (*env)->GetPrimitiveArrayCritical(env, jIn, NULL);
2928N/A if (inBufP == NULL) { return 0; }
2928N/A
2928N/A outBufP = (*env)->GetPrimitiveArrayCritical(env, jOut, NULL);
2928N/A if (outBufP == NULL) {
2928N/A // Make sure to release inBufP
2928N/A (*env)->ReleasePrimitiveArrayCritical(env, jIn, inBufP, JNI_ABORT);
936N/A return 0;
936N/A }
0N/A
0N/A ckPartLen = jOutLen;
0N/A
2928N/A rv = (*ckpFunctions->C_Decrypt)(ckSessionHandle,
2928N/A (CK_BYTE_PTR)(inBufP + jInOfs), jInLen,
2928N/A (CK_BYTE_PTR)(outBufP + jOutOfs),
2928N/A &ckPartLen);
2928N/A
2928N/A (*env)->ReleasePrimitiveArrayCritical(env, jOut, outBufP, JNI_ABORT);
2928N/A (*env)->ReleasePrimitiveArrayCritical(env, jIn, inBufP, JNI_ABORT);
2928N/A
2928N/A ckAssertReturnValueOK(env, rv);
0N/A
0N/A return ckPartLen;
0N/A}
0N/A#endif
0N/A
0N/A#ifdef P11_ENABLE_C_DECRYPTUPDATE
0N/A/*
0N/A * Class: sun_security_pkcs11_wrapper_PKCS11
0N/A * Method: C_DecryptUpdate
0N/A * Signature: (J[BII[BII)I
0N/A * Parametermapping: *PKCS11*
0N/A * @param jlong jSessionHandle CK_SESSION_HANDLE hSession
0N/A * @param jbyteArray jEncryptedPart CK_BYTE_PTR pEncryptedPart
0N/A * CK_ULONG ulEncryptedPartLen
0N/A * @return jbyteArray jPart CK_BYTE_PTR pPart
0N/A * CK_ULONG_PTR pulPartLen
0N/A */
0N/AJNIEXPORT jint JNICALL
0N/AJava_sun_security_pkcs11_wrapper_PKCS11_C_1DecryptUpdate
0N/A(JNIEnv *env, jobject obj, jlong jSessionHandle,
0N/A jlong directIn, jbyteArray jIn, jint jInOfs, jint jInLen,
0N/A jlong directOut, jbyteArray jOut, jint jOutOfs, jint jOutLen)
0N/A{
0N/A CK_SESSION_HANDLE ckSessionHandle;
0N/A CK_RV rv;
2928N/A
0N/A CK_BYTE_PTR inBufP;
0N/A CK_BYTE_PTR outBufP;
0N/A CK_ULONG ckDecryptedPartLen;
0N/A
0N/A CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
0N/A if (ckpFunctions == NULL) { return 0; }
0N/A
0N/A ckSessionHandle = jLongToCKULong(jSessionHandle);
0N/A
0N/A if (directIn != 0) {
2928N/A inBufP = (CK_BYTE_PTR) directIn;
0N/A } else {
2928N/A inBufP = (*env)->GetPrimitiveArrayCritical(env, jIn, NULL);
2928N/A if (inBufP == NULL) { return 0; }
2928N/A }
2928N/A
2928N/A if (directOut != 0) {
2928N/A outBufP = (CK_BYTE_PTR) directOut;
2928N/A } else {
2928N/A outBufP = (*env)->GetPrimitiveArrayCritical(env, jOut, NULL);
2928N/A if (outBufP == NULL) {
2928N/A // Make sure to release inBufP
2928N/A (*env)->ReleasePrimitiveArrayCritical(env, jIn, inBufP, JNI_ABORT);
936N/A return 0;
936N/A }
0N/A }
0N/A
0N/A ckDecryptedPartLen = jOutLen;
2928N/A
2928N/A rv = (*ckpFunctions->C_DecryptUpdate)(ckSessionHandle,
2928N/A (CK_BYTE_PTR)(inBufP + jInOfs), jInLen,
2928N/A (CK_BYTE_PTR)(outBufP + jOutOfs),
2928N/A &ckDecryptedPartLen);
2928N/A if (directIn == 0) {
2928N/A (*env)->ReleasePrimitiveArrayCritical(env, jIn, inBufP, JNI_ABORT);
0N/A }
0N/A
2928N/A if (directOut == 0) {
2928N/A (*env)->ReleasePrimitiveArrayCritical(env, jOut, outBufP, JNI_ABORT);
0N/A }
0N/A
2928N/A ckAssertReturnValueOK(env, rv);
0N/A
0N/A return ckDecryptedPartLen;
0N/A}
0N/A
0N/A#endif
0N/A
0N/A#ifdef P11_ENABLE_C_DECRYPTFINAL
0N/A/*
0N/A * Class: sun_security_pkcs11_wrapper_PKCS11
0N/A * Method: C_DecryptFinal
0N/A * Signature: (J[BII)I
0N/A * Parametermapping: *PKCS11*
0N/A * @param jlong jSessionHandle CK_SESSION_HANDLE hSession
0N/A * @return jbyteArray jLastPart CK_BYTE_PTR pLastPart
0N/A * CK_ULONG_PTR pulLastPartLen
0N/A */
0N/AJNIEXPORT jint JNICALL
0N/AJava_sun_security_pkcs11_wrapper_PKCS11_C_1DecryptFinal
0N/A(JNIEnv *env, jobject obj, jlong jSessionHandle,
0N/A jlong directOut, jbyteArray jOut, jint jOutOfs, jint jOutLen)
0N/A{
0N/A CK_SESSION_HANDLE ckSessionHandle;
0N/A CK_RV rv;
0N/A CK_BYTE_PTR outBufP;
0N/A CK_ULONG ckLastPartLen;
0N/A
0N/A CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
0N/A if (ckpFunctions == NULL) { return 0; }
0N/A
0N/A ckSessionHandle = jLongToCKULong(jSessionHandle);
0N/A
0N/A if (directOut != 0) {
2928N/A outBufP = (CK_BYTE_PTR) directOut;
0N/A } else {
2928N/A outBufP = (*env)->GetPrimitiveArrayCritical(env, jOut, NULL);
2928N/A if (outBufP == NULL) { return 0; }
0N/A }
0N/A
2928N/A ckLastPartLen = jOutLen;
2928N/A
2928N/A rv = (*ckpFunctions->C_DecryptFinal)(ckSessionHandle,
2928N/A (CK_BYTE_PTR)(outBufP + jOutOfs),
0N/A &ckLastPartLen);
0N/A
2928N/A if (directOut == 0) {
2928N/A (*env)->ReleasePrimitiveArrayCritical(env, jOut, outBufP, JNI_ABORT);
2928N/A
0N/A }
0N/A
2928N/A ckAssertReturnValueOK(env, rv);
2928N/A
0N/A return ckLastPartLen;
0N/A}
0N/A#endif