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 #ifndef CONSCRYPT_ERRORS_H_ 18 #define CONSCRYPT_ERRORS_H_ 19 20 #include "compat.h" 21 #include "Trace.h" 22 23 #include <errno.h> 24 #include <jni.h> 25 #include <openssl/ssl.h> 26 27 namespace conscrypt { 28 29 /** 30 * Utility methods for throwing JNI errors. 31 */ 32 class Errors { 33 private: Errors()34 Errors() {} ~Errors()35 ~Errors() {} 36 37 public: 38 /** 39 * Throw an exception with the specified class and an optional message. 40 * 41 * The "className" argument will be passed directly to FindClass, which 42 * takes strings with slashes (e.g. "java/lang/Object"). 43 * 44 * If an exception is currently pending, we log a warning message and 45 * clear it. 46 * 47 * Returns 0 on success, nonzero if something failed (e.g. the exception 48 * class couldn't be found, so *an* exception will still be pending). 49 * 50 * Currently aborts the VM if it can't throw the exception. 51 */ jniThrowException(JNIEnv * env,const char * className,const char * msg)52 static int jniThrowException(JNIEnv* env, const char* className, const char* msg) { 53 jclass exceptionClass = env->FindClass(className); 54 55 if (exceptionClass == nullptr) { 56 ALOGD("Unable to find exception class %s", className); 57 /* ClassNotFoundException now pending */ 58 return -1; 59 } 60 61 if (env->ThrowNew(exceptionClass, msg) != JNI_OK) { 62 ALOGD("Failed throwing '%s' '%s'", className, msg); 63 /* an exception, most likely OOM, will now be pending */ 64 return -1; 65 } 66 67 env->DeleteLocalRef(exceptionClass); 68 return 0; 69 } 70 71 /** 72 * Throw a java.lang.RuntimeException, with an optional message. 73 */ jniThrowRuntimeException(JNIEnv * env,const char * msg)74 static int jniThrowRuntimeException(JNIEnv* env, const char* msg) { 75 return jniThrowException(env, "java/lang/RuntimeException", msg); 76 } 77 78 /* 79 * Throw a java.lang.NullPointerException, with an optional message. 80 */ jniThrowNullPointerException(JNIEnv * env,const char * msg)81 static int jniThrowNullPointerException(JNIEnv* env, const char* msg) { 82 return jniThrowException(env, "java/lang/NullPointerException", msg); 83 } 84 85 /** 86 * Throws a OutOfMemoryError with the given string as a message. 87 */ jniThrowOutOfMemory(JNIEnv * env,const char * message)88 static int jniThrowOutOfMemory(JNIEnv* env, const char* message) { 89 return jniThrowException(env, "java/lang/OutOfMemoryError", message); 90 } 91 92 /** 93 * Throws a BadPaddingException with the given string as a message. 94 */ throwBadPaddingException(JNIEnv * env,const char * message)95 static int throwBadPaddingException(JNIEnv* env, const char* message) { 96 JNI_TRACE("throwBadPaddingException %s", message); 97 return jniThrowException(env, "javax/crypto/BadPaddingException", message); 98 } 99 100 /** 101 * Throws a SignatureException with the given string as a message. 102 */ throwSignatureException(JNIEnv * env,const char * message)103 static int throwSignatureException(JNIEnv* env, const char* message) { 104 JNI_TRACE("throwSignatureException %s", message); 105 return jniThrowException(env, "java/security/SignatureException", message); 106 } 107 108 /** 109 * Throws a InvalidKeyException with the given string as a message. 110 */ throwInvalidKeyException(JNIEnv * env,const char * message)111 static int throwInvalidKeyException(JNIEnv* env, const char* message) { 112 JNI_TRACE("throwInvalidKeyException %s", message); 113 return jniThrowException(env, "java/security/InvalidKeyException", message); 114 } 115 116 /** 117 * Throws a SignatureException with the given string as a message. 118 */ throwIllegalBlockSizeException(JNIEnv * env,const char * message)119 static int throwIllegalBlockSizeException(JNIEnv* env, const char* message) { 120 JNI_TRACE("throwIllegalBlockSizeException %s", message); 121 return jniThrowException(env, "javax/crypto/IllegalBlockSizeException", message); 122 } 123 124 /** 125 * Throws a NoSuchAlgorithmException with the given string as a message. 126 */ throwNoSuchAlgorithmException(JNIEnv * env,const char * message)127 static int throwNoSuchAlgorithmException(JNIEnv* env, const char* message) { 128 JNI_TRACE("throwUnknownAlgorithmException %s", message); 129 return jniThrowException(env, "java/security/NoSuchAlgorithmException", message); 130 } 131 132 /** 133 * Throws an IOException with the given string as a message. 134 */ throwIOException(JNIEnv * env,const char * message)135 static int throwIOException(JNIEnv* env, const char* message) { 136 JNI_TRACE("throwIOException %s", message); 137 return jniThrowException(env, "java/io/IOException", message); 138 } 139 140 /** 141 * Throws a ParsingException with the given string as a message. 142 */ throwParsingException(JNIEnv * env,const char * message)143 static int throwParsingException(JNIEnv* env, const char* message) { 144 return jniThrowException(env, TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLX509CertificateFactory$ParsingException", 145 message); 146 } 147 throwInvalidAlgorithmParameterException(JNIEnv * env,const char * message)148 static int throwInvalidAlgorithmParameterException(JNIEnv* env, const char* message) { 149 JNI_TRACE("throwInvalidAlgorithmParameterException %s", message); 150 return jniThrowException(env, "java/security/InvalidAlgorithmParameterException", message); 151 } 152 throwForAsn1Error(JNIEnv * env,int reason,const char * message,int (* defaultThrow)(JNIEnv *,const char *))153 static int throwForAsn1Error(JNIEnv* env, int reason, const char* message, 154 int (*defaultThrow)(JNIEnv*, const char*)) { 155 switch (reason) { 156 case ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE: 157 #if defined(ASN1_R_UNABLE_TO_DECODE_RSA_KEY) 158 case ASN1_R_UNABLE_TO_DECODE_RSA_KEY: 159 #endif 160 #if defined(ASN1_R_WRONG_PUBLIC_KEY_TYPE) 161 case ASN1_R_WRONG_PUBLIC_KEY_TYPE: 162 #endif 163 #if defined(ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY) 164 case ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY: 165 #endif 166 #if defined(ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE) 167 case ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE: 168 #endif 169 return throwInvalidKeyException(env, message); 170 break; 171 case ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM: 172 case ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM: 173 return throwNoSuchAlgorithmException(env, message); 174 break; 175 } 176 return defaultThrow(env, message); 177 } 178 throwForCipherError(JNIEnv * env,int reason,const char * message,int (* defaultThrow)(JNIEnv *,const char *))179 static int throwForCipherError(JNIEnv* env, int reason, const char* message, 180 int (*defaultThrow)(JNIEnv*, const char*)) { 181 switch (reason) { 182 case CIPHER_R_BAD_DECRYPT: 183 return throwBadPaddingException(env, message); 184 break; 185 case CIPHER_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH: 186 case CIPHER_R_WRONG_FINAL_BLOCK_LENGTH: 187 return throwIllegalBlockSizeException(env, message); 188 break; 189 case CIPHER_R_AES_KEY_SETUP_FAILED: 190 case CIPHER_R_BAD_KEY_LENGTH: 191 case CIPHER_R_UNSUPPORTED_KEY_SIZE: 192 return throwInvalidKeyException(env, message); 193 break; 194 } 195 return defaultThrow(env, message); 196 } 197 throwForEvpError(JNIEnv * env,int reason,const char * message,int (* defaultThrow)(JNIEnv *,const char *))198 static int throwForEvpError(JNIEnv* env, int reason, const char* message, 199 int (*defaultThrow)(JNIEnv*, const char*)) { 200 switch (reason) { 201 case EVP_R_MISSING_PARAMETERS: 202 return throwInvalidKeyException(env, message); 203 break; 204 case EVP_R_UNSUPPORTED_ALGORITHM: 205 #if defined(EVP_R_X931_UNSUPPORTED) 206 case EVP_R_X931_UNSUPPORTED: 207 #endif 208 return throwNoSuchAlgorithmException(env, message); 209 break; 210 #if defined(EVP_R_WRONG_PUBLIC_KEY_TYPE) 211 case EVP_R_WRONG_PUBLIC_KEY_TYPE: 212 return throwInvalidKeyException(env, message); 213 break; 214 #endif 215 #if defined(EVP_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM) 216 case EVP_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM: 217 return throwNoSuchAlgorithmException(env, message); 218 break; 219 #endif 220 default: 221 return defaultThrow(env, message); 222 break; 223 } 224 } 225 throwForRsaError(JNIEnv * env,int reason,const char * message,int (* defaultThrow)(JNIEnv *,const char *))226 static int throwForRsaError(JNIEnv* env, int reason, const char* message, 227 int (*defaultThrow)(JNIEnv*, const char*)) { 228 switch (reason) { 229 case RSA_R_BLOCK_TYPE_IS_NOT_01: 230 case RSA_R_PKCS_DECODING_ERROR: 231 #if defined(RSA_R_BLOCK_TYPE_IS_NOT_02) 232 case RSA_R_BLOCK_TYPE_IS_NOT_02: 233 #endif 234 return throwBadPaddingException(env, message); 235 break; 236 case RSA_R_BAD_SIGNATURE: 237 case RSA_R_DATA_TOO_LARGE_FOR_MODULUS: 238 case RSA_R_INVALID_MESSAGE_LENGTH: 239 case RSA_R_WRONG_SIGNATURE_LENGTH: 240 return throwSignatureException(env, message); 241 break; 242 case RSA_R_UNKNOWN_ALGORITHM_TYPE: 243 return throwNoSuchAlgorithmException(env, message); 244 break; 245 case RSA_R_MODULUS_TOO_LARGE: 246 case RSA_R_NO_PUBLIC_EXPONENT: 247 return throwInvalidKeyException(env, message); 248 break; 249 case RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE: 250 return throwIllegalBlockSizeException(env, message); 251 break; 252 } 253 return defaultThrow(env, message); 254 } 255 throwForX509Error(JNIEnv * env,int reason,const char * message,int (* defaultThrow)(JNIEnv *,const char *))256 static int throwForX509Error(JNIEnv* env, int reason, const char* message, 257 int (*defaultThrow)(JNIEnv*, const char*)) { 258 switch (reason) { 259 case X509_R_UNSUPPORTED_ALGORITHM: 260 return throwNoSuchAlgorithmException(env, message); 261 break; 262 default: 263 return defaultThrow(env, message); 264 break; 265 } 266 } 267 268 /* 269 * Checks this thread's OpenSSL error queue and throws a RuntimeException if 270 * necessary. 271 * 272 * @return true if an exception was thrown, false if not. 273 */ 274 static bool throwExceptionIfNecessary( 275 JNIEnv* env, CONSCRYPT_UNUSED const char* location, 276 int (*defaultThrow)(JNIEnv*, const char*) = jniThrowRuntimeException) { 277 const char* file; 278 int line; 279 const char* data; 280 int flags; 281 unsigned long error = ERR_get_error_line_data(&file, &line, &data, &flags); 282 bool result = false; 283 284 if (error != 0) { 285 char message[256]; 286 ERR_error_string_n(error, message, sizeof(message)); 287 int library = ERR_GET_LIB(error); 288 int reason = ERR_GET_REASON(error); 289 JNI_TRACE("OpenSSL error in %s error=%lx library=%x reason=%x (%s:%d): %s %s", location, 290 error, library, reason, file, line, message, 291 (flags & ERR_TXT_STRING) ? data : "(no data)"); 292 switch (library) { 293 case ERR_LIB_RSA: 294 throwForRsaError(env, reason, message, defaultThrow); 295 break; 296 case ERR_LIB_ASN1: 297 throwForAsn1Error(env, reason, message, defaultThrow); 298 break; 299 case ERR_LIB_CIPHER: 300 throwForCipherError(env, reason, message, defaultThrow); 301 break; 302 case ERR_LIB_EVP: 303 throwForEvpError(env, reason, message, defaultThrow); 304 break; 305 case ERR_LIB_X509: 306 throwForX509Error(env, reason, message, defaultThrow); 307 break; 308 case ERR_LIB_DSA: 309 throwInvalidKeyException(env, message); 310 break; 311 default: 312 defaultThrow(env, message); 313 break; 314 } 315 result = true; 316 } 317 318 ERR_clear_error(); 319 return result; 320 } 321 322 /** 323 * Throws an SocketTimeoutException with the given string as a message. 324 */ throwSocketTimeoutException(JNIEnv * env,const char * message)325 static int throwSocketTimeoutException(JNIEnv* env, const char* message) { 326 JNI_TRACE("throwSocketTimeoutException %s", message); 327 return jniThrowException(env, "java/net/SocketTimeoutException", message); 328 } 329 330 /** 331 * Throws a javax.net.ssl.SSLException with the given string as a message. 332 */ throwSSLHandshakeExceptionStr(JNIEnv * env,const char * message)333 static int throwSSLHandshakeExceptionStr(JNIEnv* env, const char* message) { 334 JNI_TRACE("throwSSLExceptionStr %s", message); 335 return jniThrowException(env, "javax/net/ssl/SSLHandshakeException", message); 336 } 337 338 /** 339 * Throws a javax.net.ssl.SSLException with the given string as a message. 340 */ throwSSLExceptionStr(JNIEnv * env,const char * message)341 static int throwSSLExceptionStr(JNIEnv* env, const char* message) { 342 JNI_TRACE("throwSSLExceptionStr %s", message); 343 return jniThrowException(env, "javax/net/ssl/SSLException", message); 344 } 345 346 /** 347 * Throws a javax.net.ssl.SSLProcotolException with the given string as a message. 348 */ throwSSLProtocolExceptionStr(JNIEnv * env,const char * message)349 static int throwSSLProtocolExceptionStr(JNIEnv* env, const char* message) { 350 JNI_TRACE("throwSSLProtocolExceptionStr %s", message); 351 return jniThrowException(env, "javax/net/ssl/SSLProtocolException", message); 352 } 353 354 /** 355 * Throws an SSLException with a message constructed from the current 356 * SSL errors. This will also log the errors. 357 * 358 * @param env the JNI environment 359 * @param ssl the possibly null SSL 360 * @param sslErrorCode error code returned from SSL_get_error() or 361 * SSL_ERROR_NONE to probe with ERR_get_error 362 * @param message null-ok; general error message 363 */ 364 static int throwSSLExceptionWithSslErrors( 365 JNIEnv* env, SSL* ssl, int sslErrorCode, const char* message, 366 int (*actualThrow)(JNIEnv*, const char*) = throwSSLExceptionStr) { 367 if (message == nullptr) { 368 message = "SSL error"; 369 } 370 371 // First consult the SSL error code for the general message. 372 const char* sslErrorStr = nullptr; 373 switch (sslErrorCode) { 374 case SSL_ERROR_NONE: 375 if (ERR_peek_error() == 0) { 376 sslErrorStr = "OK"; 377 } else { 378 sslErrorStr = ""; 379 } 380 break; 381 case SSL_ERROR_SSL: 382 sslErrorStr = "Failure in SSL library, usually a protocol error"; 383 break; 384 case SSL_ERROR_WANT_READ: 385 sslErrorStr = "SSL_ERROR_WANT_READ occurred. You should never see this."; 386 break; 387 case SSL_ERROR_WANT_WRITE: 388 sslErrorStr = "SSL_ERROR_WANT_WRITE occurred. You should never see this."; 389 break; 390 case SSL_ERROR_WANT_X509_LOOKUP: 391 sslErrorStr = "SSL_ERROR_WANT_X509_LOOKUP occurred. You should never see this."; 392 break; 393 case SSL_ERROR_SYSCALL: 394 sslErrorStr = "I/O error during system call"; 395 break; 396 case SSL_ERROR_ZERO_RETURN: 397 sslErrorStr = "SSL_ERROR_ZERO_RETURN occurred. You should never see this."; 398 break; 399 case SSL_ERROR_WANT_CONNECT: 400 sslErrorStr = "SSL_ERROR_WANT_CONNECT occurred. You should never see this."; 401 break; 402 case SSL_ERROR_WANT_ACCEPT: 403 sslErrorStr = "SSL_ERROR_WANT_ACCEPT occurred. You should never see this."; 404 break; 405 default: 406 sslErrorStr = "Unknown SSL error"; 407 } 408 409 // Prepend either our explicit message or a default one. 410 char* str; 411 if (asprintf(&str, "%s: ssl=%p: %s", message, ssl, sslErrorStr) <= 0) { 412 // problem with asprintf, just throw argument message, log everything 413 int ret = actualThrow(env, message); 414 ALOGV("%s: ssl=%p: %s", message, ssl, sslErrorStr); 415 ERR_clear_error(); 416 return ret; 417 } 418 419 char* allocStr = str; 420 421 // For protocol errors, SSL might have more information. 422 if (sslErrorCode == SSL_ERROR_NONE || sslErrorCode == SSL_ERROR_SSL) { 423 // Append each error as an additional line to the message. 424 for (;;) { 425 char errStr[256]; 426 const char* file; 427 int line; 428 const char* data; 429 int flags; 430 unsigned long err = ERR_get_error_line_data(&file, &line, &data, &flags); 431 if (err == 0) { 432 break; 433 } 434 435 ERR_error_string_n(err, errStr, sizeof(errStr)); 436 437 int ret = asprintf(&str, "%s\n%s (%s:%d %p:0x%08x)", 438 (allocStr == nullptr) ? "" : allocStr, errStr, file, line, 439 (flags & ERR_TXT_STRING) ? data : "(no data)", flags); 440 441 if (ret < 0) { 442 break; 443 } 444 445 free(allocStr); 446 allocStr = str; 447 } 448 // For errors during system calls, errno might be our friend. 449 } else if (sslErrorCode == SSL_ERROR_SYSCALL) { 450 if (asprintf(&str, "%s, %s", allocStr, strerror(errno)) >= 0) { 451 free(allocStr); 452 allocStr = str; 453 } 454 // If the error code is invalid, print it. 455 } else if (sslErrorCode > SSL_ERROR_WANT_ACCEPT) { 456 if (asprintf(&str, ", error code is %d", sslErrorCode) >= 0) { 457 free(allocStr); 458 allocStr = str; 459 } 460 } 461 462 int ret; 463 if (sslErrorCode == SSL_ERROR_SSL) { 464 ret = throwSSLProtocolExceptionStr(env, allocStr); 465 } else { 466 ret = actualThrow(env, allocStr); 467 } 468 469 ALOGV("%s", allocStr); 470 free(allocStr); 471 ERR_clear_error(); 472 return ret; 473 } 474 }; 475 476 } // namespace conscrypt 477 478 #endif // CONSCRYPT_ERRORS_H_ 479