2 * Copyright (C) 2007 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #define LOG_TAG "OpenSSLSessionImpl"
19 #include "AndroidSystemNatives.h"
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <arpa/inet.h>
29 #include <netinet/in.h>
34 #include <openssl/err.h>
35 #include <openssl/rand.h>
36 #include <openssl/ssl.h>
38 #include "org_apache_harmony_xnet_provider_jsse_common.h"
40 static jfieldID field_session;
42 static SSL_SESSION* getSslSessionPointer(JNIEnv* env, jobject object) {
43 return reinterpret_cast<SSL_SESSION*>(env->GetIntField(object, field_session));
46 // Fills a byte[][] with the peer certificates in the chain.
47 static jobjectArray OpenSSLSessionImpl_getPeerCertificatesImpl(JNIEnv* env,
48 jobject object, jint jssl)
50 SSL_SESSION* ssl_session = getSslSessionPointer(env, object);
51 SSL_CTX* ssl_ctx = SSL_CTX_new(SSLv23_client_method());
52 SSL* ssl = SSL_new(ssl_ctx);
54 SSL_set_session(ssl, ssl_session);
56 STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl);
57 jobjectArray objectArray = getcertificatebytes(env, chain);
60 SSL_CTX_free(ssl_ctx);
65 * Serializes the native state of the session (ID, cipher, and keys but
66 * not certificates). Returns a byte[] containing the DER-encoded state.
69 static jbyteArray OpenSSLSessionImpl_getEncoded(JNIEnv* env, jobject object) {
70 SSL_SESSION* ssl_session = getSslSessionPointer(env, object);
71 if (ssl_session == NULL) {
75 // Compute the size of the DER data
76 int size = i2d_SSL_SESSION(ssl_session, NULL);
81 jbyteArray bytes = env->NewByteArray(size);
83 jbyte* tmp = env->GetByteArrayElements(bytes, NULL);
84 unsigned char* ucp = reinterpret_cast<unsigned char*>(tmp);
85 i2d_SSL_SESSION(ssl_session, &ucp);
86 env->ReleaseByteArrayElements(bytes, tmp, 0);
93 * Deserialize the session.
95 static jint OpenSSLSessionImpl_initializeNativeImpl(JNIEnv* env, jobject object, jbyteArray bytes, jint size) {
100 jbyte* tmp = env->GetByteArrayElements(bytes, NULL);
101 const unsigned char* ucp = reinterpret_cast<const unsigned char*>(tmp);
102 SSL_SESSION* ssl_session = d2i_SSL_SESSION(NULL, &ucp, size);
103 env->ReleaseByteArrayElements(bytes, tmp, 0);
105 return static_cast<jint>(reinterpret_cast<uintptr_t>(ssl_session));
109 * Gets and returns in a byte array the ID of the actual SSL session.
111 static jbyteArray OpenSSLSessionImpl_getId(JNIEnv* env, jobject object) {
112 SSL_SESSION* ssl_session = getSslSessionPointer(env, object);
114 jbyteArray result = env->NewByteArray(ssl_session->session_id_length);
115 if (result != NULL) {
116 jbyte* src = reinterpret_cast<jbyte*>(ssl_session->session_id);
117 env->SetByteArrayRegion(result, 0, ssl_session->session_id_length, src);
124 * Gets and returns in a long integer the creation's time of the
125 * actual SSL session.
127 static jlong OpenSSLSessionImpl_getCreationTime(JNIEnv* env, jobject object) {
128 SSL_SESSION* ssl_session = getSslSessionPointer(env, object);
129 jlong result = SSL_SESSION_get_time(ssl_session);
130 result *= 1000; // OpenSSL uses seconds, Java uses milliseconds.
135 * Gets and returns in a string the version of the SSL protocol. If it
136 * returns the string "unknown" it means that no connection is established.
138 static jstring OpenSSLSessionImpl_getProtocol(JNIEnv* env, jobject object) {
139 SSL_SESSION* ssl_session = getSslSessionPointer(env, object);
140 SSL_CTX* ssl_ctx = SSL_CTX_new(SSLv23_client_method());
141 SSL* ssl = SSL_new(ssl_ctx);
143 SSL_set_session(ssl, ssl_session);
145 const char* protocol = SSL_get_version(ssl);
146 jstring result = env->NewStringUTF(protocol);
149 SSL_CTX_free(ssl_ctx);
154 * Gets and returns in a string the set of ciphers the actual SSL session uses.
156 static jstring OpenSSLSessionImpl_getCipherSuite(JNIEnv* env, jobject object) {
157 SSL_SESSION* ssl_session = getSslSessionPointer(env, object);
158 SSL_CTX* ssl_ctx = SSL_CTX_new(SSLv23_client_method());
159 SSL* ssl = SSL_new(ssl_ctx);
161 SSL_set_session(ssl, ssl_session);
163 SSL_CIPHER* cipher = SSL_get_current_cipher(ssl);
164 jstring result = env->NewStringUTF(SSL_CIPHER_get_name(cipher));
167 SSL_CTX_free(ssl_ctx);
172 * Frees the SSL session.
174 static void OpenSSLSessionImpl_freeImpl(JNIEnv* env, jobject object, jint session) {
175 LOGD("Freeing OpenSSL session");
176 SSL_SESSION* ssl_session = reinterpret_cast<SSL_SESSION*>(session);
177 SSL_SESSION_free(ssl_session);
180 static JNINativeMethod sMethods[] = {
181 { "freeImpl", "(I)V", (void*) OpenSSLSessionImpl_freeImpl },
182 { "getCipherSuite", "()Ljava/lang/String;", (void*) OpenSSLSessionImpl_getCipherSuite },
183 { "getCreationTime", "()J", (void*) OpenSSLSessionImpl_getCreationTime },
184 { "getEncoded", "()[B", (void*) OpenSSLSessionImpl_getEncoded },
185 { "getId", "()[B", (void*) OpenSSLSessionImpl_getId },
186 { "getPeerCertificatesImpl", "()[[B", (void*) OpenSSLSessionImpl_getPeerCertificatesImpl },
187 { "getProtocol", "()Ljava/lang/String;", (void*) OpenSSLSessionImpl_getProtocol },
188 { "initializeNativeImpl", "([BI)I", (void*) OpenSSLSessionImpl_initializeNativeImpl }
191 int register_org_apache_harmony_xnet_provider_jsse_OpenSSLSessionImpl(JNIEnv* env) {
192 jclass clazz = env->FindClass("org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl");
197 field_session = env->GetFieldID(clazz, "session", "I");
199 return jniRegisterNativeMethods(env, "org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl",
200 sMethods, NELEM(sMethods));