/***********************************************************************
 *
 * J S S _ O c t e t S t r i n g T o B y t e A r r a y
 *
 * Converts a representation of an integer as a big-endian octet string
 * stored in a SECItem (as used by the low-level crypto functions) to a
 * representation of an integer as a big-endian Java byte array. Prepends
 * a zero byte to force it to be positive. Returns NULL if an exception
 * occurred.
 *
 */
jbyteArray
JSS_OctetStringToByteArray(JNIEnv *env, SECItem *item)
{
    jbyteArray array;
    jbyte *bytes;
    int size;    /* size of the resulting byte array */

    PR_ASSERT(env != NULL && item->len>0);

    /* allow space for extra zero byte */
    size = item->len+1;

    array = (*env)->NewByteArray(env, size);
    if(array == NULL) {
        ASSERT_OUTOFMEM(env);
        return NULL;
    }

    bytes = (*env)->GetByteArrayElements(env, array, NULL);
    if(bytes == NULL) {
        ASSERT_OUTOFMEM(env);
        return NULL;
    }

    /* insert a 0 as the MSByte to force the string to be positive */
    bytes[0] = 0;

    /* now insert the rest of the bytes */
    memcpy(bytes+1, item->data, size-1);

    (*env)->ReleaseByteArrayElements(env, array, bytes, 0);

    return array;
}
Ejemplo n.º 2
0
JNIEXPORT jintArray JNICALL
Java_org_mozilla_jss_ssl_SSLSocket_getImplementedCipherSuites
    (JNIEnv *env, jclass clazz)
{
    jintArray ciphArray = NULL;
    jint* arrayRegion = NULL;
    int i;

    ciphArray = (*env)->NewIntArray(env, SSL_NumImplementedCiphers);
    if( ciphArray == NULL ) {
        ASSERT_OUTOFMEM(env);
        goto finish;
    }

    arrayRegion = (*env)->GetIntArrayElements(env, ciphArray, NULL/*isCopy*/);
    if( arrayRegion == NULL ) {
        ASSERT_OUTOFMEM(env);
        goto finish;
    }

    for( i=0; i < SSL_NumImplementedCiphers; ++i) {
        arrayRegion[i] = SSL_ImplementedCiphers[i];
    }

finish:
    if( arrayRegion != NULL ) {
        (*env)->ReleaseIntArrayElements(env, ciphArray, arrayRegion, 0);
    }
    return ciphArray;
}
Ejemplo n.º 3
0
/***********************************************************************
 *
 * J S S _ P K 1 1 _ w r a p P r i v K e y
 * privk: will be stored in a Java wrapper.
 * Returns: a new PK11PrivKey, or NULL if an exception occurred.
 */
jobject
JSS_PK11_wrapPrivKey(JNIEnv *env, SECKEYPrivateKey **privk)
{
	jclass keyClass;
	jmethodID constructor;
	jbyteArray ptrArray;
	jobject Key=NULL;
    const char *className = NULL;

	PR_ASSERT(env!=NULL && privk!=NULL && *privk!=NULL);

	/* Find the class */
    switch( (*privk)->keyType ) {
      case rsaKey:
        className = "org/mozilla/jss/pkcs11/PK11RSAPrivateKey";
        break;
      case dsaKey:
        className = "org/mozilla/jss/pkcs11/PK11DSAPrivateKey";
        break;
      case ecKey:
        className = "org/mozilla/jss/pkcs11/PK11ECPrivateKey";
        break;
      default:
        className = "org/mozilla/jss/pkcs11/PK11PrivKey";
        break;
    }
      
	keyClass = (*env)->FindClass(env, className);
	if(keyClass == NULL) {
		ASSERT_OUTOFMEM(env);
		goto finish;
	}

	/* find the constructor */
	constructor = (*env)->GetMethodID(env, keyClass, "<init>", "([B)V");
	if(constructor == NULL) {
		ASSERT_OUTOFMEM(env);
		goto finish;
	}

	/* convert the pointer to a byte array */
	ptrArray = JSS_ptrToByteArray(env, (void*)*privk);
	if(ptrArray == NULL) {
		goto finish;
	}
	/* call the constructor */
    Key = (*env)->NewObject(env, keyClass, constructor, ptrArray);

finish:
	if(Key == NULL) {
		SECKEY_DestroyPrivateKey(*privk);
	}
	*privk = NULL;
	return Key;
}
/***********************************************************************
**
** J S S _ g e t P t r F r o m P r o x y
**
** Given a NativeProxy, extract the pointer and store it at the given
** address.
**
** nativeProxy: a JNI reference to a NativeProxy.
** ptr: address of a void* that will receive the pointer extracted from
**      the NativeProxy.
** Returns: PR_SUCCESS on success, PR_FAILURE if an exception was thrown.
**
** Example:
**  DataStructure *recovered;
**  jobject proxy;
**  JNIEnv *env;
**  [...]
**  if(JSS_getPtrFromProxy(env, proxy, (void**)&recovered) != PR_SUCCESS) {
**      return;  // exception was thrown!
**  }
*/
PRStatus
JSS_getPtrFromProxy(JNIEnv *env, jobject nativeProxy, void **ptr)
{
    jclass nativeProxyClass;
	jclass proxyClass;
    jfieldID byteArrayField;
    jbyteArray byteArray;
    int size;

    PR_ASSERT(env!=NULL && nativeProxy != NULL && ptr != NULL);
    if( nativeProxy == NULL ) {
        JSS_throw(env, NULL_POINTER_EXCEPTION);
        return PR_FAILURE;
    }

	proxyClass = (*env)->GetObjectClass(env, nativeProxy);
	PR_ASSERT(proxyClass != NULL);

#ifdef DEBUG
    nativeProxyClass = (*env)->FindClass(
								env,
								NATIVE_PROXY_CLASS_NAME);
    if(nativeProxyClass == NULL) {
        ASSERT_OUTOFMEM(env);
        return PR_FAILURE;
    }

    /* make sure what we got was really a NativeProxy object */
    PR_ASSERT( (*env)->IsInstanceOf(env, nativeProxy, nativeProxyClass) );
#endif

    byteArrayField = (*env)->GetFieldID(
								env,
								proxyClass,
								NATIVE_PROXY_POINTER_FIELD,
						        NATIVE_PROXY_POINTER_SIG);
    if(byteArrayField==NULL) {
        ASSERT_OUTOFMEM(env);
        return PR_FAILURE;
    }

    byteArray = (jbyteArray) (*env)->GetObjectField(env, nativeProxy,
                        byteArrayField);
    PR_ASSERT(byteArray != NULL);

    size = sizeof(*ptr);
    PR_ASSERT((*env)->GetArrayLength(env, byteArray) == size);
    (*env)->GetByteArrayRegion(env, byteArray, 0, size, (void*)ptr);
    if( (*env)->ExceptionOccurred(env) ) {
        PR_ASSERT(PR_FALSE);
        return PR_FAILURE;
    } else {
        return PR_SUCCESS;
    }
}
Ejemplo n.º 5
0
/***********************************************************************
 *
 * J S S _ P K 1 1 _ w r a p P K 1 1 T o k e n
 *
 * Create a PK11Token object from a PKCS #11 slot.
 *
 * slot is a pointer to a PKCS #11 slot, which must not be NULL.  It will
 *  be eaten by the wrapper, so you can't use it after you call this.
 *
 * Returns a new PK11Token object, or NULL if an exception was thrown.
 */
jobject
JSS_PK11_wrapPK11Token(JNIEnv *env, PK11SlotInfo **slot)
{
    jclass tokenClass;
    jmethodID constructor;
    jbyteArray byteArray;
    jobject Token=NULL;
    jboolean internal;
    jboolean keyStorage;

    PR_ASSERT(env!=NULL && slot!=NULL && *slot!=NULL);

    internal = (*slot == PK11_GetInternalSlot());
    keyStorage = (*slot == PK11_GetInternalKeySlot());

    byteArray = JSS_ptrToByteArray(env, (void*)*slot);

    /*
     * Lookup the class and constructor
     */
    tokenClass = (*env)->FindClass(env, PK11TOKEN_CLASS_NAME);
    if(tokenClass == NULL) {
        ASSERT_OUTOFMEM(env);
        goto finish;
    }

    constructor = (*env)->GetMethodID(
                      env,
                      tokenClass,
                      PK11TOKEN_CONSTRUCTOR_NAME,
                      PK11TOKEN_CONSTRUCTOR_SIG);
    if(constructor == NULL) {
        ASSERT_OUTOFMEM(env);
        goto finish;
    }

    /* Call the constructor */
    Token = (*env)->NewObject(env,
                              tokenClass,
                              constructor,
                              byteArray,
                              internal,
                              keyStorage);

finish:
    if(Token==NULL) {
        PK11_FreeSlot(*slot);
    }
    *slot = NULL;
    return Token;
}
/***********************************************************************
 *
 * PK11MessageDigest.update
 *
 */
JNIEXPORT void JNICALL
Java_org_mozilla_jss_pkcs11_PK11MessageDigest_update
    (JNIEnv *env, jclass clazz, jobject proxyObj, jbyteArray inbufBA,
        jint offset, jint len)
{

    PK11Context *context = NULL;
    jbyte* bytes = NULL;

    if( JSS_PK11_getCipherContext(env, proxyObj, &context) != PR_SUCCESS ) {
        /* exception was thrown */
        goto finish;
    }

    PR_ASSERT( (*env)->GetArrayLength(env, inbufBA) >= offset+len );
    bytes = (*env)->GetByteArrayElements(env, inbufBA, NULL);
    if( bytes == NULL ) {
        ASSERT_OUTOFMEM(env);
        goto finish;
    }

    if( PK11_DigestOp(context, (unsigned char*)(bytes+offset), len)
            != SECSuccess )
    {
        JSS_throwMsg(env, DIGEST_EXCEPTION, "Digest operation failed");
        goto finish;
    }

finish:
    if(bytes) {
        (*env)->ReleaseByteArrayElements(env, inbufBA, bytes, JNI_ABORT);
    }
}
/***********************************************************************
**
** J S S _ t h r o w
**
** Throw an exception in native code.  You should return right after
** calling this function.
**
** throwableClassName is the name of the throwable you are throwing in
** JNI class name format (xxx/xx/xxx/xxx). It must not be NULL.
**
** Example:
**      JSS_throw(env, ILLEGAL_ARGUMENT_EXCEPTION);
**      return -1;
*/
void
JSS_throw(JNIEnv *env, char *throwableClassName)
{
    jclass throwableClass;
    jobject throwable;
    jmethodID constructor;
    jint result;
    
    PR_ASSERT( (*env)->ExceptionOccurred(env) == NULL );

    /* Lookup the class */
    throwableClass = NULL;
    if(throwableClassName) {
        throwableClass = (*env)->FindClass(env, throwableClassName);

        /* make sure the class was found */
        PR_ASSERT(throwableClass != NULL);
    }
    if(throwableClass == NULL) {
        throwableClass = (*env)->FindClass(env, GENERIC_EXCEPTION);
    }
    PR_ASSERT(throwableClass != NULL);

    /* Lookup up the plain vanilla constructor */
    constructor = (*env)->GetMethodID(
									env,
									throwableClass,
									PLAIN_CONSTRUCTOR,
									PLAIN_CONSTRUCTOR_SIG);
    if(constructor == NULL) {
        /* Anything other than OutOfMemory is a bug */
        ASSERT_OUTOFMEM(env);
        return;
    }

    /* Create an instance of the throwable */
    throwable = (*env)->NewObject(env, throwableClass, constructor);
    if(throwable == NULL) {
        /* Anything other than OutOfMemory is a bug */
        ASSERT_OUTOFMEM(env);
        return;
    }

    /* Throw the new instance */
    result = (*env)->Throw(env, throwable);
    PR_ASSERT(result == 0);
}
Ejemplo n.º 8
0
/***********************************************************************
 *
 * J S S _ P K 1 1 _ w r a p S y m K e y

 * Puts a Symmetric Key into a Java object.
 * (Does NOT perform a cryptographic "wrap" operation.)
 * symKey: will be stored in a Java wrapper.
 * Returns: a new PK11SymKey, or NULL if an exception occurred.
 */
jobject
JSS_PK11_wrapSymKey(JNIEnv *env, PK11SymKey **symKey)
{
    jclass keyClass;
    jmethodID constructor;
    jbyteArray ptrArray;
    jobject Key=NULL;

    PR_ASSERT(env!=NULL && symKey!=NULL && *symKey!=NULL);

    /* find the class */
    keyClass = (*env)->FindClass(env, PK11SYMKEY_CLASS_NAME);
    if( keyClass == NULL ) {
        ASSERT_OUTOFMEM(env);
        goto finish;
    }

    /* find the constructor */
    constructor = (*env)->GetMethodID(env, keyClass,
                                      PLAIN_CONSTRUCTOR,
                                      PK11SYMKEY_CONSTRUCTOR_SIG);
    if(constructor == NULL) {
        ASSERT_OUTOFMEM(env);
        goto finish;
    }

    /* convert the pointer to a byte array */
    ptrArray = JSS_ptrToByteArray(env, (void*)*symKey);
    if( ptrArray == NULL ) {
        goto finish;
    }
    /* call the constructor */
    Key = (*env)->NewObject(env, keyClass, constructor, ptrArray);

finish:
    if(Key == NULL) {
        PK11_FreeSymKey(*symKey);
    }
    *symKey = NULL;
    return Key;
}
/***********************************************************************
 * Copies the contents of a SECItem into a new Java byte array.
 *
 * item
 *      A SECItem. Must not be NULL.
 * RETURNS
 *      A Java byte array. NULL will be returned if an exception was
 *      thrown.
 */
jbyteArray
JSS_SECItemToByteArray(JNIEnv *env, SECItem *item)
{
    jbyteArray array=NULL;

    PR_ASSERT(env!=NULL && item!=NULL);
    PR_ASSERT(item->len >= 0);
    PR_ASSERT(item->len == 0 || item->data != NULL);

    array = (*env)->NewByteArray(env, item->len);
    if( array == NULL ) {
        ASSERT_OUTOFMEM(env);
        goto finish;
    }

    (*env)->SetByteArrayRegion(env, array, 0, item->len, item->data);

finish:
    return array;
}
/***********************************************************************
 *
 * J S S _ B y t e A r r a y T o O c t e t S t r i n g
 *
 * Converts an integer represented as a big-endian Java byte array to
 * an integer represented as a big-endian octet string in a SECItem.
 *
 * INPUTS
 *      byteArray
 *          A Java byte array containing an integer represented in
 *          big-endian format.  Must not be NULL.
 *      item
 *          Pointer to a SECItem that will be filled with the integer
 *          from the byte array, in big-endian format.
 * RETURNS
 *      PR_SUCCESS if the operation was successful, PR_FAILURE if an exception
 *      was thrown.
 */
PRStatus
JSS_ByteArrayToOctetString(JNIEnv *env, jbyteArray byteArray, SECItem *item)
{
    jbyte *bytes=NULL;
    PRStatus status=PR_FAILURE;
    jsize size;

    PR_ASSERT(env!=NULL && byteArray!=NULL && item!=NULL);

    ZERO_SECITEM(*item);

    size = (*env)->GetArrayLength(env, byteArray);
    PR_ASSERT(size > 0);

    bytes = (*env)->GetByteArrayElements(env, byteArray, NULL);
    if(bytes==NULL) {
        ASSERT_OUTOFMEM(env);
        goto finish;
    }

    item->data = (unsigned char*) PR_Malloc(size);
    if(item->data == NULL) {
        JSS_throw(env, OUT_OF_MEMORY_ERROR);
        goto finish;
    }
    item->len = size;

    memcpy(item->data, bytes, size);

    status = PR_SUCCESS;

finish:
    if(bytes) {
        (*env)->ReleaseByteArrayElements(env, byteArray, bytes, JNI_ABORT);
    }
    if(status != PR_SUCCESS) {
        SECITEM_FreeItem(item, PR_FALSE);
    }
    return status;
}
/***********************************************************************
 *
 * PK11MessageDigest.digest
 *
 */
JNIEXPORT jint JNICALL
Java_org_mozilla_jss_pkcs11_PK11MessageDigest_digest
    (JNIEnv *env, jclass clazz, jobject proxyObj, jbyteArray outbuf,
        jint offset, jint len)
{
    PK11Context *context=NULL;
    jbyte *bytes=NULL;
    SECStatus status;
    unsigned int outLen;

    if( JSS_PK11_getCipherContext(env, proxyObj, &context) != PR_SUCCESS) {
        /* exception was thrown */
        goto finish;
    }

    PR_ASSERT( (*env)->GetArrayLength(env, outbuf) >= offset+len );
    bytes = (*env)->GetByteArrayElements(env, outbuf, NULL);
    if( bytes == NULL ) {
        ASSERT_OUTOFMEM(env);
        goto finish;
    }

    status = PK11_DigestFinal(context, (unsigned char*)(bytes+offset),
                    &outLen, len);
    if( status != SECSuccess ) {
        JSS_throwMsg(env, DIGEST_EXCEPTION, "Error occurred while performing"
            " digest operation");
        goto finish;
    }

finish:
    if(bytes) {
        (*env)->ReleaseByteArrayElements(env, outbuf, bytes, 0);
    }
    return outLen;
}
Ejemplo n.º 12
0
JNIEXPORT void JNICALL
Java_org_mozilla_jss_ssl_SSLSocket_socketConnect
    (JNIEnv *env, jobject self, jbyteArray addrBA, jstring hostname, jint port)
{
    JSSL_SocketData *sock;
    PRNetAddr addr;
    jbyte *addrBAelems = NULL;
    PRStatus status;
    int stat;
    const char *hostnameStr=NULL;

    if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS) {
        /* exception was thrown */
        goto finish;
    }

    /*
     * setup the PRNetAddr structure
     */
    addr.inet.family = AF_INET;
    addr.inet.port = htons(port);
    PR_ASSERT(sizeof(addr.inet.ip) == 4);
    PR_ASSERT( (*env)->GetArrayLength(env, addrBA) == 4);
    addrBAelems = (*env)->GetByteArrayElements(env, addrBA, NULL);
    if( addrBAelems == NULL ) {
        ASSERT_OUTOFMEM(env);
        goto finish;
    }
    memcpy(&addr.inet.ip, addrBAelems, 4);

    /*
     * Tell SSL the URL we think we want to connect to.
     * This prevents man-in-the-middle attacks.
     */
    hostnameStr = (*env)->GetStringUTFChars(env, hostname, NULL);
    if( hostnameStr == NULL ) goto finish;
    stat = SSL_SetURL(sock->fd, (char*)hostnameStr);
    if( stat != 0 ) {
        JSSL_throwSSLSocketException(env, "Failed to set the SSL URL");
        goto finish;
    }

    /*
     * make the connect call
     */
    status = PR_Connect(sock->fd, &addr, PR_INTERVAL_NO_TIMEOUT);
    if( status != PR_SUCCESS) {
        JSSL_throwSSLSocketException(env, "Unable to connect");
        goto finish;
    }

finish:
    /* This method should never be called on a Java socket wrapper. */
    PR_ASSERT( sock==NULL || sock->jsockPriv==NULL);

    if( hostnameStr != NULL ) {
        (*env)->ReleaseStringUTFChars(env, hostname, hostnameStr);
    }
    if( addrBAelems != NULL ) {
        (*env)->ReleaseByteArrayElements(env, addrBA, addrBAelems, JNI_ABORT);
    }
}
/***********************************************************************
 * Class:     org_mozilla_jss_util_Password
 * Method:    readPasswordFromConsole
 * Signature: ()Lorg/mozilla/jss/util/Password;
 */
JNIEXPORT jobject JNICALL Java_org_mozilla_jss_util_Password_readPasswordFromConsole
  (JNIEnv *env, jclass clazz)
{
    char *pw=NULL;
    int pwlen;
    jclass pwClass;
    jmethodID pwConstructor;
    jcharArray pwCharArray=NULL;
    jchar *pwChars=NULL;
    jobject password=NULL;
    jboolean pwIsCopy;
    int i;

    /***************************************************
     * Get JNI IDs
     ***************************************************/
    pwClass = (*env)->FindClass(env, PASSWORD_CLASS_NAME);
    if(pwClass == NULL) {
        ASSERT_OUTOFMEM(env);
        goto finish;
    }
    pwConstructor = (*env)->GetMethodID(env,
                                        pwClass,
                                        PLAIN_CONSTRUCTOR,
                                        PASSWORD_CONSTRUCTOR_SIG);
    if(pwConstructor == NULL) {
        ASSERT_OUTOFMEM(env);
        goto finish;
    }

    /***************************************************
     * Get the password from the console
     ***************************************************/
    pw = getPWFromConsole();

    if(pw == NULL) {
        JSS_throw(env, GIVE_UP_EXCEPTION);
        goto finish;
    }
    pwlen = strlen(pw);
    PR_ASSERT(pwlen > 0);

    /***************************************************
     * Put the password into a char array
     ***************************************************/
    pwCharArray = (*env)->NewCharArray(env, pwlen);
    if(pwCharArray == NULL) {
        ASSERT_OUTOFMEM(env);
        goto finish;
    }
    pwChars = (*env)->GetCharArrayElements(env, pwCharArray, &pwIsCopy);
    if(pwChars == NULL) {
        ASSERT_OUTOFMEM(env);
        goto finish;
    }
    for(i=0; i < pwlen; i++) {
        /* YUK! Only works for ASCII. */
        pwChars[i] = pw[i];
    }

    if( pwIsCopy ) {
        /* copy back the changes */
        (*env)->ReleaseCharArrayElements(env, pwCharArray, pwChars, JNI_COMMIT);
        /* clear the copy */
        memset(pwChars, 0, pwlen);
        /* release the copy */
        (*env)->ReleaseCharArrayElements(env, pwCharArray, pwChars, JNI_ABORT);
    } else {
        /* pwChars is not a copy, so this should be a no-op, but we include
         * it anyway */
        (*env)->ReleaseCharArrayElements(env, pwCharArray, pwChars, 0);
    }
    pwChars = NULL;

    /***************************************************
     * Construct a new Password from the char array
     ***************************************************/
    password = (*env)->NewObject(env, pwClass, pwConstructor, pwCharArray);
    if(password == NULL) {
        ASSERT_OUTOFMEM(env);
        goto finish;
    }

finish:
    if(pw != NULL) {
        memset(pw, 0, strlen(pw));
        PR_Free(pw);
    }
    return password;
}