15
15
};
16
16
17
17
// javax/net/ssl/SSLEngineResult$Status
18
+ // Android API 24+
18
19
enum
19
20
{
20
21
STATUS__BUFFER_UNDERFLOW = 0 ,
23
24
STATUS__CLOSED = 3 ,
24
25
};
25
26
27
+ // javax/net/ssl/SSLEngineResult$Status
28
+ // Android API 21-23
29
+ enum
30
+ {
31
+ LEGACY__STATUS__BUFFER_OVERFLOW = 0 ,
32
+ LEGACY__STATUS__BUFFER_UNDERFLOW = 1 ,
33
+ LEGACY__STATUS__OK = 3 ,
34
+ LEGACY__STATUS__CLOSED = 2 ,
35
+ };
36
+
26
37
struct ApplicationProtocolData_t
27
38
{
28
39
uint8_t * data ;
@@ -115,6 +126,25 @@ ARGS_NON_NULL_ALL static jobject EnsureRemaining(JNIEnv* env, jobject oldBuffer,
115
126
}
116
127
}
117
128
129
+ // There has been a change in the SSLEngineResult.Status enum between API 23 and 24 that changed
130
+ // the order/interger values of the enum options.
131
+ static int MapLegacySSLEngineResultStatus (int legacyStatus ) {
132
+ switch (legacyStatus ) {
133
+ case LEGACY__STATUS__BUFFER_OVERFLOW :
134
+ return STATUS__BUFFER_OVERFLOW ;
135
+ case LEGACY__STATUS__BUFFER_UNDERFLOW :
136
+ return STATUS__BUFFER_UNDERFLOW ;
137
+ case LEGACY__STATUS__CLOSED :
138
+ return STATUS__CLOSED ;
139
+ case LEGACY__STATUS__OK :
140
+ return STATUS__OK ;
141
+ default :
142
+ LOG_ERROR ("Unknown legacy SSLEngineResult status: %d" , legacyStatus );
143
+ assert (false && "Unknown SSLEngineResult status" );
144
+ return -1 ;
145
+ }
146
+ }
147
+
118
148
ARGS_NON_NULL_ALL static PAL_SSLStreamStatus DoWrap (JNIEnv * env , SSLStream * sslStream , int * handshakeStatus )
119
149
{
120
150
// appOutBuffer.flip();
@@ -134,6 +164,10 @@ ARGS_NON_NULL_ALL static PAL_SSLStreamStatus DoWrap(JNIEnv* env, SSLStream* sslS
134
164
int status = GetEnumAsInt (env , (* env )-> CallObjectMethod (env , result , g_SSLEngineResultGetStatus ));
135
165
(* env )-> DeleteLocalRef (env , result );
136
166
167
+ if (g_SSLEngineResultStatusLegacyOrder ) {
168
+ status = MapLegacySSLEngineResultStatus (status );
169
+ }
170
+
137
171
switch (status )
138
172
{
139
173
case STATUS__OK :
@@ -208,6 +242,11 @@ ARGS_NON_NULL_ALL static PAL_SSLStreamStatus DoUnwrap(JNIEnv* env, SSLStream* ss
208
242
* handshakeStatus = GetEnumAsInt (env , (* env )-> CallObjectMethod (env , result , g_SSLEngineResultGetHandshakeStatus ));
209
243
int status = GetEnumAsInt (env , (* env )-> CallObjectMethod (env , result , g_SSLEngineResultGetStatus ));
210
244
(* env )-> DeleteLocalRef (env , result );
245
+
246
+ if (g_SSLEngineResultStatusLegacyOrder ) {
247
+ status = MapLegacySSLEngineResultStatus (status );
248
+ }
249
+
211
250
switch (status )
212
251
{
213
252
case STATUS__OK :
@@ -425,7 +464,7 @@ SSLStream* AndroidCryptoNative_SSLStreamCreateWithCertificates(uint8_t* pkcs8Pri
425
464
}
426
465
427
466
int32_t AndroidCryptoNative_SSLStreamInitialize (
428
- SSLStream * sslStream , bool isServer , ManagedContextHandle managedContextHandle , STREAM_READER streamReader , STREAM_WRITER streamWriter , int32_t appBufferSize )
467
+ SSLStream * sslStream , bool isServer , ManagedContextHandle managedContextHandle , STREAM_READER streamReader , STREAM_WRITER streamWriter , int32_t appBufferSize , char * peerHost )
429
468
{
430
469
abort_if_invalid_pointer_argument (sslStream );
431
470
abort_unless (sslStream -> sslContext != NULL , "sslContext is NULL in SSL stream" );
@@ -435,10 +474,23 @@ int32_t AndroidCryptoNative_SSLStreamInitialize(
435
474
int32_t ret = FAIL ;
436
475
JNIEnv * env = GetJNIEnv ();
437
476
438
- // SSLEngine sslEngine = sslContext.createSSLEngine();
477
+ jobject sslEngine = NULL ;
478
+ if (peerHost )
479
+ {
480
+ // SSLEngine sslEngine = sslContext.createSSLEngine(peerHost, -1);
481
+ jstring peerHostStr = make_java_string (env , peerHost );
482
+ sslEngine = (* env )-> CallObjectMethod (env , sslStream -> sslContext , g_SSLContextCreateSSLEngineMethodWithHostAndPort , peerHostStr , -1 );
483
+ ReleaseLRef (env , peerHostStr );
484
+ ON_EXCEPTION_PRINT_AND_GOTO (exit );
485
+ }
486
+ else
487
+ {
488
+ // SSLEngine sslEngine = sslContext.createSSLEngine();
489
+ sslEngine = (* env )-> CallObjectMethod (env , sslStream -> sslContext , g_SSLContextCreateSSLEngineMethod );
490
+ ON_EXCEPTION_PRINT_AND_GOTO (exit );
491
+ }
492
+
439
493
// sslEngine.setUseClientMode(!isServer);
440
- jobject sslEngine = (* env )-> CallObjectMethod (env , sslStream -> sslContext , g_SSLContextCreateSSLEngineMethod );
441
- ON_EXCEPTION_PRINT_AND_GOTO (exit );
442
494
sslStream -> sslEngine = ToGRef (env , sslEngine );
443
495
(* env )-> CallVoidMethod (env , sslStream -> sslEngine , g_SSLEngineSetUseClientMode , !isServer );
444
496
ON_EXCEPTION_PRINT_AND_GOTO (exit );
@@ -476,19 +528,48 @@ int32_t AndroidCryptoNative_SSLStreamInitialize(
476
528
return ret ;
477
529
}
478
530
531
+ // This method calls internal Android APIs that are specific to Android API 21-23 and it won't work
532
+ // on newer API levels. By calling the sslEngine.sslParameters.useSni(true) method, the SSLEngine
533
+ // will include the peerHost that was passed in to the SSLEngine factory method in the client hello
534
+ // message.
535
+ ARGS_NON_NULL_ALL static int32_t ApplyLegacyAndroidSNIWorkaround (JNIEnv * env , SSLStream * sslStream )
536
+ {
537
+ if (g_ConscryptOpenSSLEngineImplClass == NULL || !(* env )-> IsInstanceOf (env , sslStream -> sslEngine , g_ConscryptOpenSSLEngineImplClass ))
538
+ return FAIL ;
539
+
540
+ int32_t ret = FAIL ;
541
+ INIT_LOCALS (loc , sslParameters );
542
+
543
+ loc [sslParameters ] = (* env )-> GetObjectField (env , sslStream -> sslEngine , g_ConscryptOpenSSLEngineImplSslParametersField );
544
+ ON_EXCEPTION_PRINT_AND_GOTO (cleanup );
545
+
546
+ if (!loc [sslParameters ])
547
+ goto cleanup ;
548
+
549
+ (* env )-> CallVoidMethod (env , loc [sslParameters ], g_ConscryptSSLParametersImplSetUseSni , true);
550
+ ON_EXCEPTION_PRINT_AND_GOTO (cleanup );
551
+
552
+ ret = SUCCESS ;
553
+
554
+ cleanup :
555
+ RELEASE_LOCALS (loc , env );
556
+ return ret ;
557
+ }
558
+
479
559
int32_t AndroidCryptoNative_SSLStreamSetTargetHost (SSLStream * sslStream , char * targetHost )
480
560
{
481
561
abort_if_invalid_pointer_argument (sslStream );
482
562
abort_if_invalid_pointer_argument (targetHost );
483
563
564
+ JNIEnv * env = GetJNIEnv ();
565
+
484
566
if (g_SNIHostName == NULL || g_SSLParametersSetServerNames == NULL )
485
567
{
486
- // SSL not supported below API Level 24
487
- return UNSUPPORTED_API_LEVEL ;
568
+ // SNIHostName is only available since API 24
569
+ // on APIs 21-23 we use a workaround to force the SSLEngine to use SNI
570
+ return ApplyLegacyAndroidSNIWorkaround (env , sslStream );
488
571
}
489
572
490
- JNIEnv * env = GetJNIEnv ();
491
-
492
573
int32_t ret = FAIL ;
493
574
INIT_LOCALS (loc , hostStr , nameList , hostName , params );
494
575
0 commit comments