Skip to content

Commit b14310d

Browse files
authored
Merge branch 'master' into ckozak/gh1170_reentrant_locks
2 parents 3dde52e + bc1a34b commit b14310d

29 files changed

Lines changed: 1670 additions & 858 deletions

common/src/jni/main/cpp/conscrypt/jniutil.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,12 @@ int throwInvalidKeyException(JNIEnv* env, const char* message) {
254254
return conscrypt::jniutil::throwException(env, "java/security/InvalidKeyException", message);
255255
}
256256

257+
int throwIllegalArgumentException(JNIEnv* env, const char* message) {
258+
JNI_TRACE("throwIllegalArgumentException %s", message);
259+
return conscrypt::jniutil::throwException(
260+
env, "java/lang/IllegalArgumentException", message);
261+
}
262+
257263
int throwIllegalBlockSizeException(JNIEnv* env, const char* message) {
258264
JNI_TRACE("throwIllegalBlockSizeException %s", message);
259265
return conscrypt::jniutil::throwException(
@@ -344,11 +350,16 @@ int throwForEvpError(JNIEnv* env, int reason, const char* message,
344350
int (*defaultThrow)(JNIEnv*, const char*)) {
345351
switch (reason) {
346352
case EVP_R_MISSING_PARAMETERS:
353+
case EVP_R_INVALID_PEER_KEY:
354+
case EVP_R_DECODE_ERROR:
347355
return throwInvalidKeyException(env, message);
348356
break;
349357
case EVP_R_UNSUPPORTED_ALGORITHM:
350358
return throwNoSuchAlgorithmException(env, message);
351359
break;
360+
case EVP_R_INVALID_BUFFER_SIZE:
361+
return throwIllegalArgumentException(env, message);
362+
break;
352363
default:
353364
return defaultThrow(env, message);
354365
break;

common/src/jni/main/cpp/conscrypt/native_crypto.cc

Lines changed: 34 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -4007,11 +4007,12 @@ const EVP_HPKE_KEM* getHpkeKem(JNIEnv* env, jint kemValue) {
40074007
}
40084008
}
40094009

4010-
static jobject NativeCrypto_EVP_HPKE_CTX_setup_recipient(JNIEnv* env, jclass, jint kemValue,
4011-
jint kdfValue, jint aeadValue,
4012-
jbyteArray privateKeyArray,
4013-
jbyteArray encArray,
4014-
jbyteArray infoArray) {
4010+
static jobject NativeCrypto_EVP_HPKE_CTX_setup_base_mode_recipient(JNIEnv* env, jclass,
4011+
jint kemValue,jint kdfValue,
4012+
jint aeadValue,
4013+
jbyteArray privateKeyArray,
4014+
jbyteArray encArray,
4015+
jbyteArray infoArray) {
40154016
CHECK_ERROR_QUEUE_ON_RETURN;
40164017
JNI_TRACE("EVP_HPKE_CTX_setup_recipient(%d, %d, %d, %p, %p, %p)", kemValue, kdfValue, aeadValue,
40174018
privateKeyArray, encArray, infoArray);
@@ -4082,10 +4083,11 @@ static jobject NativeCrypto_EVP_HPKE_CTX_setup_recipient(JNIEnv* env, jclass, ji
40824083
return ctxObject.release();
40834084
}
40844085

4085-
static jobjectArray NativeCrypto_EVP_HPKE_CTX_setup_sender(JNIEnv* env, jclass, jint kemValue,
4086-
jint kdfValue, jint aeadValue,
4087-
jbyteArray publicKeyArray,
4088-
jbyteArray infoArray) {
4086+
static jobjectArray NativeCrypto_EVP_HPKE_CTX_setup_base_mode_sender(JNIEnv* env, jclass,
4087+
jint kemValue,jint kdfValue,
4088+
jint aeadValue,
4089+
jbyteArray publicKeyArray,
4090+
jbyteArray infoArray) {
40894091
CHECK_ERROR_QUEUE_ON_RETURN;
40904092
JNI_TRACE("EVP_HPKE_CTX_setup_sender(%d, %d, %d, %p, %p)", kemValue, kdfValue, aeadValue,
40914093
publicKeyArray, infoArray);
@@ -4165,7 +4167,7 @@ static jobjectArray NativeCrypto_EVP_HPKE_CTX_setup_sender(JNIEnv* env, jclass,
41654167
return result.release();
41664168
}
41674169

4168-
static jobjectArray NativeCrypto_EVP_HPKE_CTX_setup_sender_with_seed_for_testing(
4170+
static jobjectArray NativeCrypto_EVP_HPKE_CTX_setup_base_mode_sender_with_seed_for_testing(
41694171
JNIEnv* env, jclass, jint kemValue, jint kdfValue, jint aeadValue,
41704172
jbyteArray publicKeyArray, jbyteArray infoArray, jbyteArray seedArray) {
41714173
CHECK_ERROR_QUEUE_ON_RETURN;
@@ -4861,6 +4863,20 @@ static jobjectArray NativeCrypto_get_X509_GENERAL_NAME_stack(JNIEnv* env, jclass
48614863
return joa.release();
48624864
}
48634865

4866+
/*
4867+
* Converts an ASN1_TIME to epoch time in milliseconds.
4868+
*/
4869+
static jlong ASN1_TIME_convert_to_posix(JNIEnv* env, const ASN1_TIME* time) {
4870+
int64_t retval;
4871+
if (!ASN1_TIME_to_posix(time, &retval)) {
4872+
JNI_TRACE("ASN1_TIME_convert_to_posix(%p) => Invalid date value", time);
4873+
conscrypt::jniutil::throwParsingException(env, "Invalid date value");
4874+
return 0;
4875+
}
4876+
// ASN1_TIME_to_posix can only return years from 0000 to 9999, so this won't overflow.
4877+
return static_cast<jlong>(retval * 1000);
4878+
}
4879+
48644880
static jlong NativeCrypto_X509_get_notBefore(JNIEnv* env, jclass, jlong x509Ref,
48654881
CONSCRYPT_UNUSED jobject holder) {
48664882
CHECK_ERROR_QUEUE_ON_RETURN;
@@ -4875,7 +4891,7 @@ static jlong NativeCrypto_X509_get_notBefore(JNIEnv* env, jclass, jlong x509Ref,
48754891

48764892
ASN1_TIME* notBefore = X509_get_notBefore(x509);
48774893
JNI_TRACE("X509_get_notBefore(%p) => %p", x509, notBefore);
4878-
return reinterpret_cast<uintptr_t>(notBefore);
4894+
return ASN1_TIME_convert_to_posix(env, notBefore);
48794895
}
48804896

48814897
static jlong NativeCrypto_X509_get_notAfter(JNIEnv* env, jclass, jlong x509Ref,
@@ -4892,7 +4908,7 @@ static jlong NativeCrypto_X509_get_notAfter(JNIEnv* env, jclass, jlong x509Ref,
48924908

48934909
ASN1_TIME* notAfter = X509_get_notAfter(x509);
48944910
JNI_TRACE("X509_get_notAfter(%p) => %p", x509, notAfter);
4895-
return reinterpret_cast<uintptr_t>(notAfter);
4911+
return ASN1_TIME_convert_to_posix(env, notAfter);
48964912
}
48974913

48984914
// NOLINTNEXTLINE(runtime/int)
@@ -5528,7 +5544,7 @@ static jlong NativeCrypto_get_X509_REVOKED_revocationDate(JNIEnv* env, jclass,
55285544

55295545
JNI_TRACE("get_X509_REVOKED_revocationDate(%p) => %p", revoked,
55305546
X509_REVOKED_get0_revocationDate(revoked));
5531-
return reinterpret_cast<uintptr_t>(X509_REVOKED_get0_revocationDate(revoked));
5547+
return ASN1_TIME_convert_to_posix(env, X509_REVOKED_get0_revocationDate(revoked));
55325548
}
55335549

55345550
#ifdef __GNUC__
@@ -5622,7 +5638,7 @@ static jlong NativeCrypto_X509_CRL_get_lastUpdate(JNIEnv* env, jclass, jlong x50
56225638

56235639
ASN1_TIME* lastUpdate = X509_CRL_get_lastUpdate(crl);
56245640
JNI_TRACE("X509_CRL_get_lastUpdate(%p) => %p", crl, lastUpdate);
5625-
return reinterpret_cast<uintptr_t>(lastUpdate);
5641+
return ASN1_TIME_convert_to_posix(env, lastUpdate);
56265642
}
56275643

56285644
static jlong NativeCrypto_X509_CRL_get_nextUpdate(JNIEnv* env, jclass, jlong x509CrlRef,
@@ -5639,7 +5655,7 @@ static jlong NativeCrypto_X509_CRL_get_nextUpdate(JNIEnv* env, jclass, jlong x50
56395655

56405656
ASN1_TIME* nextUpdate = X509_CRL_get_nextUpdate(crl);
56415657
JNI_TRACE("X509_CRL_get_nextUpdate(%p) => %p", crl, nextUpdate);
5642-
return reinterpret_cast<uintptr_t>(nextUpdate);
5658+
return ASN1_TIME_convert_to_posix(env, nextUpdate);
56435659
}
56445660

56455661
static jbyteArray NativeCrypto_i2d_X509_REVOKED(JNIEnv* env, jclass, jlong x509RevokedRef) {
@@ -5663,63 +5679,6 @@ static jint NativeCrypto_X509_supported_extension(JNIEnv* env, jclass, jlong x50
56635679
return X509_supported_extension(ext);
56645680
}
56655681

5666-
static inline bool decimal_to_integer(const char* data, size_t len, int* out) {
5667-
int ret = 0;
5668-
for (size_t i = 0; i < len; i++) {
5669-
ret *= 10;
5670-
if (data[i] < '0' || data[i] > '9') {
5671-
return false;
5672-
}
5673-
ret += data[i] - '0';
5674-
}
5675-
*out = ret;
5676-
return true;
5677-
}
5678-
5679-
static void NativeCrypto_ASN1_TIME_to_Calendar(JNIEnv* env, jclass, jlong asn1TimeRef,
5680-
jobject calendar) {
5681-
CHECK_ERROR_QUEUE_ON_RETURN;
5682-
ASN1_TIME* asn1Time = reinterpret_cast<ASN1_TIME*>(static_cast<uintptr_t>(asn1TimeRef));
5683-
JNI_TRACE("ASN1_TIME_to_Calendar(%p, %p)", asn1Time, calendar);
5684-
5685-
if (asn1Time == nullptr) {
5686-
conscrypt::jniutil::throwNullPointerException(env, "asn1Time == null");
5687-
return;
5688-
}
5689-
5690-
if (!ASN1_TIME_check(asn1Time)) {
5691-
conscrypt::jniutil::throwParsingException(env, "Invalid date format");
5692-
return;
5693-
}
5694-
5695-
bssl::UniquePtr<ASN1_GENERALIZEDTIME> gen(ASN1_TIME_to_generalizedtime(asn1Time, nullptr));
5696-
if (gen.get() == nullptr) {
5697-
conscrypt::jniutil::throwParsingException(env,
5698-
"ASN1_TIME_to_generalizedtime returned null");
5699-
return;
5700-
}
5701-
5702-
if (ASN1_STRING_length(gen.get()) < 14 || ASN1_STRING_get0_data(gen.get()) == nullptr) {
5703-
conscrypt::jniutil::throwNullPointerException(env, "gen->length < 14 || gen->data == null");
5704-
return;
5705-
}
5706-
5707-
int year, mon, mday, hour, min, sec;
5708-
const char* data = reinterpret_cast<const char*>(ASN1_STRING_get0_data(gen.get()));
5709-
if (!decimal_to_integer(data, 4, &year) ||
5710-
!decimal_to_integer(data + 4, 2, &mon) ||
5711-
!decimal_to_integer(data + 6, 2, &mday) ||
5712-
!decimal_to_integer(data + 8, 2, &hour) ||
5713-
!decimal_to_integer(data + 10, 2, &min) ||
5714-
!decimal_to_integer(data + 12, 2, &sec)) {
5715-
conscrypt::jniutil::throwParsingException(env, "Invalid date format");
5716-
return;
5717-
}
5718-
5719-
env->CallVoidMethod(calendar, conscrypt::jniutil::calendar_setMethod, year, mon - 1, mday, hour,
5720-
min, sec);
5721-
}
5722-
57235682
// A CbsHandle is a structure used to manage resources allocated by asn1_read-*
57245683
// functions so that they can be freed properly when finished. This struct owns
57255684
// all objects pointed to by its members.
@@ -11135,9 +11094,9 @@ static JNINativeMethod sNativeCryptoMethods[] = {
1113511094
CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_free, "(J)V"),
1113611095
CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_open, "(" REF_EVP_HPKE_CTX "[B[B)[B"),
1113711096
CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_seal, "(" REF_EVP_HPKE_CTX "[B[B)[B"),
11138-
CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_setup_recipient, "(III[B[B[B)Ljava/lang/Object;"),
11139-
CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_setup_sender, "(III[B[B)[Ljava/lang/Object;"),
11140-
CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_setup_sender_with_seed_for_testing,
11097+
CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_setup_base_mode_recipient, "(III[B[B[B)Ljava/lang/Object;"),
11098+
CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_setup_base_mode_sender, "(III[B[B)[Ljava/lang/Object;"),
11099+
CONSCRYPT_NATIVE_METHOD(EVP_HPKE_CTX_setup_base_mode_sender_with_seed_for_testing,
1114111100
"(III[B[B[B)[Ljava/lang/Object;"),
1114211101
CONSCRYPT_NATIVE_METHOD(HMAC_CTX_new, "()J"),
1114311102
CONSCRYPT_NATIVE_METHOD(HMAC_CTX_free, "(J)V"),
@@ -11218,7 +11177,6 @@ static JNINativeMethod sNativeCryptoMethods[] = {
1121811177
CONSCRYPT_NATIVE_METHOD(X509_REVOKED_dup, "(J)J"),
1121911178
CONSCRYPT_NATIVE_METHOD(i2d_X509_REVOKED, "(J)[B"),
1122011179
CONSCRYPT_NATIVE_METHOD(X509_supported_extension, "(J)I"),
11221-
CONSCRYPT_NATIVE_METHOD(ASN1_TIME_to_Calendar, "(JLjava/util/Calendar;)V"),
1122211180
CONSCRYPT_NATIVE_METHOD(asn1_read_init, "([B)J"),
1122311181
CONSCRYPT_NATIVE_METHOD(asn1_read_sequence, "(J)J"),
1122411182
CONSCRYPT_NATIVE_METHOD(asn1_read_next_tag_is, "(JI)Z"),
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/*
2+
* Copyright (C) 2023 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+
package org.conscrypt;
18+
19+
import java.lang.reflect.InvocationTargetException;
20+
import java.lang.reflect.Method;
21+
import java.security.GeneralSecurityException;
22+
import java.security.InvalidKeyException;
23+
import java.security.PrivateKey;
24+
import java.security.PublicKey;
25+
import java.util.HashMap;
26+
import java.util.Map;
27+
28+
/**
29+
* Duck typed implementation of {@link HpkeSpi}.
30+
* <p>
31+
* Will wrap any Object which implements all of the methods in HpkeSpi and delegate to them
32+
* by reflection.
33+
*/
34+
@Internal
35+
public class DuckTypedHpkeSpi implements HpkeSpi {
36+
private final Object delegate;
37+
private final Map<String, Method> methods = new HashMap<>();
38+
39+
private DuckTypedHpkeSpi(Object delegate) throws NoSuchMethodException {
40+
this.delegate = delegate;
41+
42+
Class<?> sourceClass = delegate.getClass();
43+
for (Method targetMethod : HpkeSpi.class.getMethods()) {
44+
if (targetMethod.isSynthetic()) {
45+
continue;
46+
}
47+
48+
Method sourceMethod =
49+
sourceClass.getMethod(targetMethod.getName(), targetMethod.getParameterTypes());
50+
// Check that the return types match too.
51+
Class<?> sourceReturnType = sourceMethod.getReturnType();
52+
Class<?> targetReturnType = targetMethod.getReturnType();
53+
if (!targetReturnType.isAssignableFrom(sourceReturnType)) {
54+
throw new NoSuchMethodException(sourceMethod + " return value (" + sourceReturnType
55+
+ ") incompatible with target return value (" + targetReturnType + ")");
56+
}
57+
methods.put(sourceMethod.getName(), sourceMethod);
58+
}
59+
}
60+
61+
public static DuckTypedHpkeSpi newInstance(Object delegate) {
62+
try {
63+
return new DuckTypedHpkeSpi(delegate);
64+
} catch (Exception ignored) {
65+
return null;
66+
}
67+
}
68+
69+
private Object invoke(String methodName, Object... args) {
70+
Method method = methods.get(methodName);
71+
if (method == null) {
72+
throw new IllegalStateException("DuckTypedHpkSpi internal error");
73+
}
74+
try {
75+
return method.invoke(delegate, args);
76+
} catch (InvocationTargetException | IllegalAccessException e) {
77+
throw new IllegalStateException("DuckTypedHpkSpi internal error", e);
78+
}
79+
}
80+
81+
// Visible for testing
82+
public Object getDelegate() {
83+
return delegate;
84+
}
85+
86+
@Override
87+
public void engineInitSender(
88+
PublicKey recipientKey, byte[] info, PrivateKey senderKey, byte[] psk, byte[] psk_id)
89+
throws InvalidKeyException {
90+
invoke("engineInitSender", recipientKey, info, senderKey, psk, psk_id);
91+
}
92+
93+
@Override
94+
public void engineInitSenderForTesting(PublicKey recipientKey, byte[] info, PrivateKey senderKey,
95+
byte[] psk, byte[] psk_id, byte[] sKe) throws InvalidKeyException {
96+
invoke("engineInitSenderForTesting",
97+
recipientKey, info, senderKey, psk, psk_id, sKe);
98+
}
99+
100+
@Override
101+
public void engineInitRecipient(byte[] encapsulated, PrivateKey key, byte[] info,
102+
PublicKey senderKey, byte[] psk, byte[] psk_id) throws InvalidKeyException {
103+
invoke("engineInitRecipient", encapsulated, key, info, senderKey, psk, psk_id);
104+
}
105+
106+
@Override
107+
public byte[] engineSeal(byte[] plaintext, byte[] aad) {
108+
return (byte[]) invoke("engineSeal", plaintext, aad);
109+
}
110+
111+
@Override
112+
public byte[] engineExport(int length, byte[] exporterContext) {
113+
return (byte[]) invoke("engineExport", length, exporterContext);
114+
}
115+
116+
@Override
117+
public byte[] engineOpen(byte[] ciphertext, byte[] aad) throws GeneralSecurityException {
118+
return (byte[]) invoke("engineOpen", ciphertext, aad);
119+
}
120+
121+
@Override
122+
public byte[] getEncapsulated() {
123+
return (byte[]) invoke("getEncapsulated");
124+
}
125+
}

0 commit comments

Comments
 (0)