• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 
17 #include <conscrypt/jniutil.h>
18 
19 #include <conscrypt/compat.h>
20 #include <conscrypt/trace.h>
21 #include <cstdlib>
22 #include <errno.h>
23 
24 namespace conscrypt {
25 namespace jniutil {
26 
27 JavaVM *gJavaVM;
28 jclass cryptoUpcallsClass;
29 jclass openSslInputStreamClass;
30 jclass nativeRefClass;
31 
32 jclass byteArrayClass;
33 jclass calendarClass;
34 jclass objectClass;
35 jclass objectArrayClass;
36 jclass integerClass;
37 jclass inputStreamClass;
38 jclass outputStreamClass;
39 jclass stringClass;
40 
41 jfieldID nativeRef_address;
42 
43 jmethodID calendar_setMethod;
44 jmethodID inputStream_readMethod;
45 jmethodID integer_valueOfMethod;
46 jmethodID openSslInputStream_readLineMethod;
47 jmethodID outputStream_writeMethod;
48 jmethodID outputStream_flushMethod;
49 
init(JavaVM * vm,JNIEnv * env)50 void init(JavaVM* vm, JNIEnv* env) {
51     gJavaVM = vm;
52 
53     byteArrayClass = findClass(env, "[B");
54     calendarClass = findClass(env, "java/util/Calendar");
55     inputStreamClass = findClass(env, "java/io/InputStream");
56     integerClass = findClass(env, "java/lang/Integer");
57     objectClass = findClass(env, "java/lang/Object");
58     objectArrayClass = findClass(env, "[Ljava/lang/Object;");
59     outputStreamClass = findClass(env, "java/io/OutputStream");
60     stringClass = findClass(env, "java/lang/String");
61 
62     cryptoUpcallsClass = getGlobalRefToClass(
63             env, TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/CryptoUpcalls");
64     nativeRefClass = getGlobalRefToClass(
65             env, TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeRef");
66     openSslInputStreamClass = getGlobalRefToClass(
67             env, TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLBIOInputStream");
68 
69     nativeRef_address = getFieldRef(env, nativeRefClass, "address", "J");
70 
71     calendar_setMethod = getMethodRef(env, calendarClass, "set", "(IIIIII)V");
72     inputStream_readMethod = getMethodRef(env, inputStreamClass, "read", "([B)I");
73     integer_valueOfMethod =
74             env->GetStaticMethodID(integerClass, "valueOf", "(I)Ljava/lang/Integer;");
75     openSslInputStream_readLineMethod =
76             getMethodRef(env, openSslInputStreamClass, "gets", "([B)I");
77     outputStream_writeMethod = getMethodRef(env, outputStreamClass, "write", "([B)V");
78     outputStream_flushMethod = getMethodRef(env, outputStreamClass, "flush", "()V");
79 }
80 
jniRegisterNativeMethods(JNIEnv * env,const char * className,const JNINativeMethod * gMethods,int numMethods)81 void jniRegisterNativeMethods(JNIEnv* env, const char* className, const JNINativeMethod* gMethods,
82                               int numMethods) {
83     CONSCRYPT_LOG_VERBOSE("Registering %s's %d native methods...", className, numMethods);
84 
85     ScopedLocalRef<jclass> c(env, env->FindClass(className));
86     if (c.get() == nullptr) {
87         char* msg;
88         (void)asprintf(&msg, "Native registration unable to find class '%s'; aborting...",
89                        className);
90         env->FatalError(msg);
91     }
92 
93     if (env->RegisterNatives(c.get(), gMethods, numMethods) < 0) {
94         char* msg;
95         (void)asprintf(&msg, "RegisterNatives failed for '%s'; aborting...", className);
96         env->FatalError(msg);
97     }
98 }
99 
jniGetFDFromFileDescriptor(JNIEnv * env,jobject fileDescriptor)100 int jniGetFDFromFileDescriptor(JNIEnv* env, jobject fileDescriptor) {
101     ScopedLocalRef<jclass> localClass(env, env->FindClass("java/io/FileDescriptor"));
102 #if defined(ANDROID) && !defined(CONSCRYPT_OPENJDK)
103     static jfieldID fid = env->GetFieldID(localClass.get(), "descriptor", "I");
104 #else /* !ANDROID || CONSCRYPT_OPENJDK */
105     static jfieldID fid = env->GetFieldID(localClass.get(), "fd", "I");
106 #endif
107     if (fileDescriptor != nullptr) {
108         return env->GetIntField(fileDescriptor, fid);
109     } else {
110         return -1;
111     }
112 }
113 
isGetByteArrayElementsLikelyToReturnACopy(size_t size)114 bool isGetByteArrayElementsLikelyToReturnACopy(size_t size) {
115 #if defined(ANDROID) && !defined(CONSCRYPT_OPENJDK)
116     // ART's GetByteArrayElements creates copies only for arrays smaller than 12 kB.
117     return size <= 12 * 1024;
118 #else
119     (void)size;
120     // On OpenJDK based VMs GetByteArrayElements appears to always create a copy.
121     return true;
122 #endif
123 }
124 
throwException(JNIEnv * env,const char * className,const char * msg)125 int throwException(JNIEnv* env, const char* className, const char* msg) {
126     jclass exceptionClass = env->FindClass(className);
127 
128     if (exceptionClass == nullptr) {
129         CONSCRYPT_LOG_ERROR("Unable to find exception class %s", className);
130         /* ClassNotFoundException now pending */
131         return -1;
132     }
133 
134     if (env->ThrowNew(exceptionClass, msg) != JNI_OK) {
135         CONSCRYPT_LOG_ERROR("Failed throwing '%s' '%s'", className, msg);
136         /* an exception, most likely OOM, will now be pending */
137         return -1;
138     }
139 
140     env->DeleteLocalRef(exceptionClass);
141     return 0;
142 }
143 
throwRuntimeException(JNIEnv * env,const char * msg)144 int throwRuntimeException(JNIEnv* env, const char* msg) {
145     return conscrypt::jniutil::throwException(env, "java/lang/RuntimeException", msg);
146 }
147 
throwAssertionError(JNIEnv * env,const char * msg)148 int throwAssertionError(JNIEnv* env, const char* msg) {
149     return conscrypt::jniutil::throwException(env, "java/lang/AssertionError", msg);
150 }
151 
throwNullPointerException(JNIEnv * env,const char * msg)152 int throwNullPointerException(JNIEnv* env, const char* msg) {
153     return conscrypt::jniutil::throwException(env, "java/lang/NullPointerException", msg);
154 }
155 
throwOutOfMemory(JNIEnv * env,const char * message)156 int throwOutOfMemory(JNIEnv* env, const char* message) {
157     return conscrypt::jniutil::throwException(env, "java/lang/OutOfMemoryError", message);
158 }
159 
throwBadPaddingException(JNIEnv * env,const char * message)160 int throwBadPaddingException(JNIEnv* env, const char* message) {
161     JNI_TRACE("throwBadPaddingException %s", message);
162     return conscrypt::jniutil::throwException(env, "javax/crypto/BadPaddingException", message);
163 }
164 
throwSignatureException(JNIEnv * env,const char * message)165 int throwSignatureException(JNIEnv* env, const char* message) {
166     JNI_TRACE("throwSignatureException %s", message);
167     return conscrypt::jniutil::throwException(env, "java/security/SignatureException", message);
168 }
169 
throwInvalidKeyException(JNIEnv * env,const char * message)170 int throwInvalidKeyException(JNIEnv* env, const char* message) {
171     JNI_TRACE("throwInvalidKeyException %s", message);
172     return conscrypt::jniutil::throwException(env, "java/security/InvalidKeyException", message);
173 }
174 
throwIllegalBlockSizeException(JNIEnv * env,const char * message)175 int throwIllegalBlockSizeException(JNIEnv* env, const char* message) {
176     JNI_TRACE("throwIllegalBlockSizeException %s", message);
177     return conscrypt::jniutil::throwException(
178             env, "javax/crypto/IllegalBlockSizeException", message);
179 }
180 
throwShortBufferException(JNIEnv * env,const char * message)181 int throwShortBufferException(JNIEnv* env, const char* message) {
182     JNI_TRACE("throwShortBufferException %s", message);
183     return conscrypt::jniutil::throwException(
184             env, "javax/crypto/ShortBufferException", message);
185 }
186 
throwNoSuchAlgorithmException(JNIEnv * env,const char * message)187 int throwNoSuchAlgorithmException(JNIEnv* env, const char* message) {
188     JNI_TRACE("throwUnknownAlgorithmException %s", message);
189     return conscrypt::jniutil::throwException(
190             env, "java/security/NoSuchAlgorithmException", message);
191 }
192 
throwIOException(JNIEnv * env,const char * message)193 int throwIOException(JNIEnv* env, const char* message) {
194     JNI_TRACE("throwIOException %s", message);
195     return conscrypt::jniutil::throwException(env, "java/io/IOException", message);
196 }
197 
throwCertificateException(JNIEnv * env,const char * message)198 int throwCertificateException(JNIEnv* env, const char* message) {
199     JNI_TRACE("throwCertificateException %s", message);
200     return conscrypt::jniutil::throwException(
201             env, "java/security/cert/CertificateException", message);
202 }
203 
throwParsingException(JNIEnv * env,const char * message)204 int throwParsingException(JNIEnv* env, const char* message) {
205     return conscrypt::jniutil::throwException(env, TO_STRING(JNI_JARJAR_PREFIX)
206                             "org/conscrypt/OpenSSLX509CertificateFactory$ParsingException",
207                             message);
208 }
209 
throwInvalidAlgorithmParameterException(JNIEnv * env,const char * message)210 int throwInvalidAlgorithmParameterException(JNIEnv* env, const char* message) {
211     JNI_TRACE("throwInvalidAlgorithmParameterException %s", message);
212     return conscrypt::jniutil::throwException(
213             env, "java/security/InvalidAlgorithmParameterException", message);
214 }
215 
throwForAsn1Error(JNIEnv * env,int reason,const char * message,int (* defaultThrow)(JNIEnv *,const char *))216 int throwForAsn1Error(JNIEnv* env, int reason, const char* message,
217                       int (*defaultThrow)(JNIEnv*, const char*)) {
218     switch (reason) {
219         case ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE:
220 #if defined(ASN1_R_UNABLE_TO_DECODE_RSA_KEY)
221         case ASN1_R_UNABLE_TO_DECODE_RSA_KEY:
222 #endif
223 #if defined(ASN1_R_WRONG_PUBLIC_KEY_TYPE)
224         case ASN1_R_WRONG_PUBLIC_KEY_TYPE:
225 #endif
226 #if defined(ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY)
227         case ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY:
228 #endif
229 #if defined(ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE)
230         case ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE:
231 #endif
232             return throwInvalidKeyException(env, message);
233             break;
234         case ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM:
235         case ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM:
236             return throwNoSuchAlgorithmException(env, message);
237             break;
238     }
239     return defaultThrow(env, message);
240 }
241 
throwForCipherError(JNIEnv * env,int reason,const char * message,int (* defaultThrow)(JNIEnv *,const char *))242 int throwForCipherError(JNIEnv* env, int reason, const char* message,
243                         int (*defaultThrow)(JNIEnv*, const char*)) {
244     switch (reason) {
245         case CIPHER_R_BAD_DECRYPT:
246             return throwBadPaddingException(env, message);
247             break;
248         case CIPHER_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH:
249         case CIPHER_R_WRONG_FINAL_BLOCK_LENGTH:
250             return throwIllegalBlockSizeException(env, message);
251             break;
252         case CIPHER_R_AES_KEY_SETUP_FAILED:
253         case CIPHER_R_BAD_KEY_LENGTH:
254         case CIPHER_R_UNSUPPORTED_KEY_SIZE:
255             return throwInvalidKeyException(env, message);
256             break;
257         case CIPHER_R_BUFFER_TOO_SMALL:
258             return throwShortBufferException(env, message);
259             break;
260     }
261     return defaultThrow(env, message);
262 }
263 
throwForEvpError(JNIEnv * env,int reason,const char * message,int (* defaultThrow)(JNIEnv *,const char *))264 int throwForEvpError(JNIEnv* env, int reason, const char* message,
265                      int (*defaultThrow)(JNIEnv*, const char*)) {
266     switch (reason) {
267         case EVP_R_MISSING_PARAMETERS:
268             return throwInvalidKeyException(env, message);
269             break;
270         case EVP_R_UNSUPPORTED_ALGORITHM:
271 #if defined(EVP_R_X931_UNSUPPORTED)
272         case EVP_R_X931_UNSUPPORTED:
273 #endif
274             return throwNoSuchAlgorithmException(env, message);
275             break;
276 #if defined(EVP_R_WRONG_PUBLIC_KEY_TYPE)
277         case EVP_R_WRONG_PUBLIC_KEY_TYPE:
278             return throwInvalidKeyException(env, message);
279             break;
280 #endif
281 #if defined(EVP_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM)
282         case EVP_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM:
283             return throwNoSuchAlgorithmException(env, message);
284             break;
285 #endif
286         default:
287             return defaultThrow(env, message);
288             break;
289     }
290 }
291 
throwForRsaError(JNIEnv * env,int reason,const char * message,int (* defaultThrow)(JNIEnv *,const char *))292 int throwForRsaError(JNIEnv* env, int reason, const char* message,
293                      int (*defaultThrow)(JNIEnv*, const char*)) {
294     switch (reason) {
295         case RSA_R_BLOCK_TYPE_IS_NOT_01:
296         case RSA_R_PKCS_DECODING_ERROR:
297 #if defined(RSA_R_BLOCK_TYPE_IS_NOT_02)
298         case RSA_R_BLOCK_TYPE_IS_NOT_02:
299 #endif
300             return throwBadPaddingException(env, message);
301             break;
302         case RSA_R_BAD_SIGNATURE:
303         case RSA_R_INVALID_MESSAGE_LENGTH:
304         case RSA_R_WRONG_SIGNATURE_LENGTH:
305             return throwSignatureException(env, message);
306             break;
307         case RSA_R_UNKNOWN_ALGORITHM_TYPE:
308             return throwNoSuchAlgorithmException(env, message);
309             break;
310         case RSA_R_MODULUS_TOO_LARGE:
311         case RSA_R_NO_PUBLIC_EXPONENT:
312             return throwInvalidKeyException(env, message);
313             break;
314         case RSA_R_DATA_TOO_LARGE:
315         case RSA_R_DATA_TOO_LARGE_FOR_MODULUS:
316         case RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE:
317             return throwIllegalBlockSizeException(env, message);
318             break;
319     }
320     return defaultThrow(env, message);
321 }
322 
throwForX509Error(JNIEnv * env,int reason,const char * message,int (* defaultThrow)(JNIEnv *,const char *))323 int throwForX509Error(JNIEnv* env, int reason, const char* message,
324                       int (*defaultThrow)(JNIEnv*, const char*)) {
325     switch (reason) {
326         case X509_R_UNSUPPORTED_ALGORITHM:
327             return throwNoSuchAlgorithmException(env, message);
328             break;
329         default:
330             return defaultThrow(env, message);
331             break;
332     }
333 }
334 
throwExceptionFromBoringSSLError(JNIEnv * env,CONSCRYPT_UNUSED const char * location,int (* defaultThrow)(JNIEnv *,const char *))335 void throwExceptionFromBoringSSLError(JNIEnv* env, CONSCRYPT_UNUSED const char* location,
336                                       int (*defaultThrow)(JNIEnv*, const char*)) {
337     const char* file;
338     int line;
339     const char* data;
340     int flags;
341     // NOLINTNEXTLINE(runtime/int)
342     unsigned long error = ERR_get_error_line_data(&file, &line, &data, &flags);
343 
344     if (error == 0) {
345         defaultThrow(env, "Unknown BoringSSL error");
346         return;
347     }
348 
349     // If there's an error from BoringSSL it may have been caused by an exception in Java code, so
350     // ensure there isn't a pending exception before we throw a new one.
351     if (!env->ExceptionCheck()) {
352         char message[256];
353         ERR_error_string_n(error, message, sizeof(message));
354         int library = ERR_GET_LIB(error);
355         int reason = ERR_GET_REASON(error);
356         JNI_TRACE("BoringSSL error in %s error=%lx library=%x reason=%x (%s:%d): %s %s", location,
357                   error, library, reason, file, line, message,
358                   (flags & ERR_TXT_STRING) ? data : "(no data)");
359         switch (library) {
360             case ERR_LIB_RSA:
361                 throwForRsaError(env, reason, message, defaultThrow);
362                 break;
363             case ERR_LIB_ASN1:
364                 throwForAsn1Error(env, reason, message, defaultThrow);
365                 break;
366             case ERR_LIB_CIPHER:
367                 throwForCipherError(env, reason, message, defaultThrow);
368                 break;
369             case ERR_LIB_EVP:
370                 throwForEvpError(env, reason, message, defaultThrow);
371                 break;
372             case ERR_LIB_X509:
373                 throwForX509Error(env, reason, message, defaultThrow);
374                 break;
375             case ERR_LIB_DSA:
376                 throwInvalidKeyException(env, message);
377                 break;
378             default:
379                 defaultThrow(env, message);
380                 break;
381         }
382     }
383 
384     ERR_clear_error();
385 }
386 
throwSocketTimeoutException(JNIEnv * env,const char * message)387 int throwSocketTimeoutException(JNIEnv* env, const char* message) {
388     JNI_TRACE("throwSocketTimeoutException %s", message);
389     return conscrypt::jniutil::throwException(env, "java/net/SocketTimeoutException", message);
390 }
391 
throwSSLHandshakeExceptionStr(JNIEnv * env,const char * message)392 int throwSSLHandshakeExceptionStr(JNIEnv* env, const char* message) {
393     JNI_TRACE("throwSSLExceptionStr %s", message);
394     return conscrypt::jniutil::throwException(
395             env, "javax/net/ssl/SSLHandshakeException", message);
396 }
397 
throwSSLExceptionStr(JNIEnv * env,const char * message)398 int throwSSLExceptionStr(JNIEnv* env, const char* message) {
399     JNI_TRACE("throwSSLExceptionStr %s", message);
400     return conscrypt::jniutil::throwException(env, "javax/net/ssl/SSLException", message);
401 }
402 
throwSSLProtocolExceptionStr(JNIEnv * env,const char * message)403 int throwSSLProtocolExceptionStr(JNIEnv* env, const char* message) {
404     JNI_TRACE("throwSSLProtocolExceptionStr %s", message);
405     return conscrypt::jniutil::throwException(
406             env, "javax/net/ssl/SSLProtocolException", message);
407 }
408 
throwSSLExceptionWithSslErrors(JNIEnv * env,SSL * ssl,int sslErrorCode,const char * message,int (* actualThrow)(JNIEnv *,const char *))409 int throwSSLExceptionWithSslErrors(JNIEnv* env, SSL* ssl, int sslErrorCode, const char* message,
410                                    int (*actualThrow)(JNIEnv*, const char*)) {
411     if (message == nullptr) {
412         message = "SSL error";
413     }
414 
415     // First consult the SSL error code for the general message.
416     const char* sslErrorStr = nullptr;
417     switch (sslErrorCode) {
418         case SSL_ERROR_NONE:
419             if (ERR_peek_error() == 0) {
420                 sslErrorStr = "OK";
421             } else {
422                 sslErrorStr = "";
423             }
424             break;
425         case SSL_ERROR_SSL:
426             sslErrorStr = "Failure in SSL library, usually a protocol error";
427             break;
428         case SSL_ERROR_WANT_READ:
429             sslErrorStr = "SSL_ERROR_WANT_READ occurred. You should never see this.";
430             break;
431         case SSL_ERROR_WANT_WRITE:
432             sslErrorStr = "SSL_ERROR_WANT_WRITE occurred. You should never see this.";
433             break;
434         case SSL_ERROR_WANT_X509_LOOKUP:
435             sslErrorStr = "SSL_ERROR_WANT_X509_LOOKUP occurred. You should never see this.";
436             break;
437         case SSL_ERROR_SYSCALL:
438             sslErrorStr = "I/O error during system call";
439             break;
440         case SSL_ERROR_ZERO_RETURN:
441             sslErrorStr = "SSL_ERROR_ZERO_RETURN occurred. You should never see this.";
442             break;
443         case SSL_ERROR_WANT_CONNECT:
444             sslErrorStr = "SSL_ERROR_WANT_CONNECT occurred. You should never see this.";
445             break;
446         case SSL_ERROR_WANT_ACCEPT:
447             sslErrorStr = "SSL_ERROR_WANT_ACCEPT occurred. You should never see this.";
448             break;
449         default:
450             sslErrorStr = "Unknown SSL error";
451     }
452 
453     // Prepend either our explicit message or a default one.
454     char* str;
455     if (asprintf(&str, "%s: ssl=%p: %s", message, ssl, sslErrorStr) <= 0) {
456         // problem with asprintf, just throw argument message, log everything
457         int ret = actualThrow(env, message);
458         CONSCRYPT_LOG_VERBOSE("%s: ssl=%p: %s", message, ssl, sslErrorStr);
459         ERR_clear_error();
460         return ret;
461     }
462 
463     char* allocStr = str;
464 
465     // For protocol errors, SSL might have more information.
466     if (sslErrorCode == SSL_ERROR_NONE || sslErrorCode == SSL_ERROR_SSL) {
467         // Append each error as an additional line to the message.
468         for (;;) {
469             char errStr[256];
470             const char* file;
471             int line;
472             const char* data;
473             int flags;
474             // NOLINTNEXTLINE(runtime/int)
475             unsigned long err = ERR_get_error_line_data(&file, &line, &data, &flags);
476             if (err == 0) {
477                 break;
478             }
479 
480             ERR_error_string_n(err, errStr, sizeof(errStr));
481 
482             int ret = asprintf(&str, "%s\n%s (%s:%d %p:0x%08x)",
483                                (allocStr == nullptr) ? "" : allocStr, errStr, file, line,
484                                (flags & ERR_TXT_STRING) ? data : "(no data)", flags);
485 
486             if (ret < 0) {
487                 break;
488             }
489 
490             free(allocStr);
491             allocStr = str;
492         }
493         // For errors during system calls, errno might be our friend.
494     } else if (sslErrorCode == SSL_ERROR_SYSCALL) {
495         if (asprintf(&str, "%s, %s", allocStr, strerror(errno)) >= 0) {
496             free(allocStr);
497             allocStr = str;
498         }
499         // If the error code is invalid, print it.
500     } else if (sslErrorCode > SSL_ERROR_WANT_ACCEPT) {
501         if (asprintf(&str, ", error code is %d", sslErrorCode) >= 0) {
502             free(allocStr);
503             allocStr = str;
504         }
505     }
506 
507     int ret;
508     if (sslErrorCode == SSL_ERROR_SSL) {
509         ret = throwSSLProtocolExceptionStr(env, allocStr);
510     } else {
511         ret = actualThrow(env, allocStr);
512     }
513 
514     CONSCRYPT_LOG_VERBOSE("%s", allocStr);
515     free(allocStr);
516     ERR_clear_error();
517     return ret;
518 }
519 
520 }  // namespace jniutil
521 }  // namespace conscrypt
522