2121extern " C" jstring Java_de_blinkt_openvpn_core_NativeUtils_getOpenSSLVersionString (JNIEnv *env, jclass jo)
2222{
2323 return env->NewStringUTF (OPENSSL_VERSION_TEXT );
24- }
25-
26- static const unsigned char zeroes[] = {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 };
27-
28- static char opensslerr[1024 ];
29- extern " C" jbyteArray Java_de_blinkt_openvpn_core_NativeUtils_rsapss (JNIEnv *env,
30- jclass,
31- jint hashtype,
32- jint MSBits,
33- jint rsa_size,
34- jbyteArray from) {
35-
36- /*
37- unsigned char *EM,
38- const unsigned char *mHash,
39- const EVP_MD *Hash, const EVP_MD *mgf1Hash,
40- int sLen)
41- */
42-
43- jbyte *data = env->GetByteArrayElements (from, nullptr );
44- int datalen = env->GetArrayLength (from);
45-
46- const auto *mHash = reinterpret_cast <const unsigned char *>(data);
47-
48- const EVP_MD *Hash;
49-
50- if (hashtype == 0 ) {
51- Hash = EVP_md5 ();
52- } else if (hashtype == 1 ) {
53- Hash = EVP_sha1 ();
54- } else if (hashtype == 2 ) {
55- Hash = EVP_sha224 ();
56- } else if (hashtype == 3 ) {
57- Hash = EVP_sha256 ();
58- } else if (hashtype == 4 ) {
59- Hash = EVP_sha384 ();
60- } else if (hashtype == 5 ) {
61- Hash = EVP_sha512 ();
62- }
63-
64- const EVP_MD *mgf1Hash = Hash;
65-
66- int ret = 0 ;
67- int maskedDBLen, emLen;
68- unsigned char *H, *salt = nullptr , *p;
69- EVP_MD_CTX *ctx = nullptr ;
70-
71- int hLen = EVP_MD_get_size (Hash);
72- int sLen = hLen; /* RSA_PSS_SALTLEN_DIGEST */
73-
74- std::array<unsigned char , 2048 > buf{};
75- unsigned char *EM = buf.data ();
76-
77- if (hLen < 0 )
78- goto err;
79-
80- emLen = rsa_size;
81- if (MSBits == 0 ) {
82- *EM ++ = 0 ;
83- emLen--;
84- }
85- if (emLen < hLen + 2 ) {
86- goto err;
87- }
88- if (sLen == RSA_PSS_SALTLEN_MAX ) {
89- sLen = emLen - hLen - 2 ;
90- } else if (sLen > emLen - hLen - 2 ) {
91- goto err;
92- }
93-
94- if (sLen > 0 ) {
95- salt = (unsigned char *) OPENSSL_malloc (sLen );
96- if (salt == nullptr ) {
97- goto err;
98- }
99- if (RAND_bytes_ex (nullptr , salt, sLen , 0 ) <= 0 )
100- goto err;
101- }
102- maskedDBLen = emLen - hLen - 1 ;
103- H = EM + maskedDBLen;
104- ctx = EVP_MD_CTX_new ();
105- if (ctx == nullptr )
106- goto err;
107- if (!EVP_DigestInit_ex (ctx, Hash, nullptr )
108- || !EVP_DigestUpdate (ctx, zeroes, sizeof (zeroes))
109- || !EVP_DigestUpdate (ctx, mHash , hLen))
110- goto err;
111- if (sLen && !EVP_DigestUpdate (ctx, salt, sLen ))
112- goto err;
113- if (!EVP_DigestFinal_ex (ctx, H, nullptr ))
114- goto err;
115-
116- #pragma clang diagnostic push
117- #pragma clang diagnostic ignored "-Wdeprecated-declarations"
118- /* Generate dbMask in place then perform XOR on it */
119- if (PKCS1_MGF1 (EM , maskedDBLen, H, hLen, mgf1Hash))
120- goto err;
121- #pragma clang diagnostic pop
122-
123- p = EM ;
124-
125- /*
126- * Initial PS XORs with all zeroes which is a NOP so just update pointer.
127- * Note from a test above this value is guaranteed to be non-negative.
128- */
129- p += emLen - sLen - hLen - 2 ;
130- *p++ ^= 0x1 ;
131- if (sLen > 0 ) {
132- for (int i = 0 ; i < sLen ; i++)
133- *p++ ^= salt[i];
134- }
135- if (MSBits)
136- EM [0 ] &= 0xFF >> (8 - MSBits);
137-
138- /* H is already in place so just set final 0xbc */
139-
140- EM [emLen - 1 ] = 0xbc ;
141-
142- ret = 1 ;
143-
144- err:
145- EVP_MD_CTX_free (ctx);
146- OPENSSL_clear_free (salt, (size_t ) sLen ); /* salt != NULL implies sLen > 0 */
147-
148-
149- jbyteArray jb;
150-
151- jb = env->NewByteArray (emLen);
152-
153- env->SetByteArrayRegion (jb, 0 , emLen, (jbyte *) EM );
154-
155- return jb;
15624}
0 commit comments