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