comparison src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp @ 51349:46492a773912

8205445: Add RSASSA-PSS Signature support to SunMSCAPI Reviewed-by: xuelei
author weijun
date Fri, 22 Jun 2018 21:42:00 +0800
parents f0aeede1b855
children c31b6e1c4383
comparison
equal deleted inserted replaced
4:0030f995a3d9 5:fff7909fe212
55 #define KEYSTORE_EXCEPTION "java/security/KeyStoreException" 55 #define KEYSTORE_EXCEPTION "java/security/KeyStoreException"
56 #define PROVIDER_EXCEPTION "java/security/ProviderException" 56 #define PROVIDER_EXCEPTION "java/security/ProviderException"
57 #define SIGNATURE_EXCEPTION "java/security/SignatureException" 57 #define SIGNATURE_EXCEPTION "java/security/SignatureException"
58 #define OUT_OF_MEMORY_ERROR "java/lang/OutOfMemoryError" 58 #define OUT_OF_MEMORY_ERROR "java/lang/OutOfMemoryError"
59 59
60 #define SS_CHECK(Status) \
61 if (Status != ERROR_SUCCESS) { \
62 ThrowException(env, SIGNATURE_EXCEPTION, Status); \
63 __leave; \
64 }
65
66 //#define PP(fmt, ...) \
67 // fprintf(stdout, "SSPI (%ld): ", __LINE__); \
68 // fprintf(stdout, fmt, ##__VA_ARGS__); \
69 // fprintf(stdout, "\n"); \
70 // fflush(stdout)
71
60 extern "C" { 72 extern "C" {
61 73
62 /* 74 /*
63 * Declare library specific JNI_Onload entry if static build 75 * Declare library specific JNI_Onload entry if static build
64 */ 76 */
65 DEF_STATIC_JNI_OnLoad 77 DEF_STATIC_JNI_OnLoad
78
79 //void dump(LPSTR title, PBYTE data, DWORD len)
80 //{
81 // printf("==== %s ====\n", title);
82 // for (DWORD i = 0; i < len; i++) {
83 // if (i != 0 && i % 16 == 0) {
84 // printf("\n");
85 // }
86 // printf("%02X ", *(data + i) & 0xff);
87 // }
88 // printf("\n");
89 //}
66 90
67 /* 91 /*
68 * Throws an arbitrary Java exception with the given message. 92 * Throws an arbitrary Java exception with the given message.
69 */ 93 */
70 void ThrowExceptionWithMessage(JNIEnv *env, const char *exceptionName, 94 void ThrowExceptionWithMessage(JNIEnv *env, const char *exceptionName,
144 env->ReleaseStringUTFChars(jHashAlgorithm, pszHashAlgorithm); 168 env->ReleaseStringUTFChars(jHashAlgorithm, pszHashAlgorithm);
145 169
146 return algId; 170 return algId;
147 } 171 }
148 172
173 /*
174 * Maps the name of a hash algorithm to a CNG Algorithm Identifier.
175 */
176 LPCWSTR MapHashIdentifier(JNIEnv *env, jstring jHashAlgorithm) {
177
178 const char* pszHashAlgorithm = NULL;
179 LPCWSTR id = NULL;
180
181 if ((pszHashAlgorithm = env->GetStringUTFChars(jHashAlgorithm, NULL))
182 == NULL) {
183 return id;
184 }
185
186 if ((strcmp("SHA", pszHashAlgorithm) == 0) ||
187 (strcmp("SHA1", pszHashAlgorithm) == 0) ||
188 (strcmp("SHA-1", pszHashAlgorithm) == 0)) {
189
190 id = BCRYPT_SHA1_ALGORITHM;
191 } else if (strcmp("SHA-256", pszHashAlgorithm) == 0) {
192 id = BCRYPT_SHA256_ALGORITHM;
193 } else if (strcmp("SHA-384", pszHashAlgorithm) == 0) {
194 id = BCRYPT_SHA384_ALGORITHM;
195 } else if (strcmp("SHA-512", pszHashAlgorithm) == 0) {
196 id = BCRYPT_SHA512_ALGORITHM;
197 }
198
199 if (pszHashAlgorithm)
200 env->ReleaseStringUTFChars(jHashAlgorithm, pszHashAlgorithm);
201
202 return id;
203 }
149 204
150 /* 205 /*
151 * Returns a certificate chain context given a certificate context and key 206 * Returns a certificate chain context given a certificate context and key
152 * usage identifier. 207 * usage identifier.
153 */ 208 */
559 614
560 if (hCryptProv != NULL) 615 if (hCryptProv != NULL)
561 ::CryptReleaseContext((HCRYPTPROV) hCryptProv, NULL); 616 ::CryptReleaseContext((HCRYPTPROV) hCryptProv, NULL);
562 } 617 }
563 618
564
565 /* 619 /*
566 * Class: sun_security_mscapi_RSASignature 620 * Class: sun_security_mscapi_RSASignature
567 * Method: signHash 621 * Method: signHash
568 * Signature: (Z[BILjava/lang/String;JJ)[B 622 * Signature: (Z[BILjava/lang/String;JJ)[B
569 */ 623 */
685 if (hHash) 739 if (hHash)
686 ::CryptDestroyHash(hHash); 740 ::CryptDestroyHash(hHash);
687 741
688 if (hCryptProvAlt) 742 if (hCryptProvAlt)
689 ::CryptReleaseContext(hCryptProvAlt, 0); 743 ::CryptReleaseContext(hCryptProvAlt, 0);
744 }
745
746 return jSignedHash;
747 }
748
749 /*
750 * Class: sun_security_mscapi_RSASignature_PSS
751 * Method: signPssHash
752 * Signature: ([BIILjava/lang/String;JJ)[B
753 */
754 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_RSASignature_00024PSS_signPssHash
755 (JNIEnv *env, jclass clazz, jbyteArray jHash,
756 jint jHashSize, jint saltLen, jstring jHashAlgorithm, jlong hCryptProv,
757 jlong hCryptKey)
758 {
759 jbyteArray jSignedHash = NULL;
760
761 jbyte* pHashBuffer = NULL;
762 jbyte* pSignedHashBuffer = NULL;
763 NCRYPT_KEY_HANDLE hk = NULL;
764
765 __try
766 {
767 SS_CHECK(::NCryptTranslateHandle(
768 NULL,
769 &hk,
770 hCryptProv,
771 hCryptKey,
772 NULL,
773 0));
774
775 // Copy hash from Java to native buffer
776 pHashBuffer = new (env) jbyte[jHashSize];
777 if (pHashBuffer == NULL) {
778 __leave;
779 }
780 env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);
781
782 BCRYPT_PSS_PADDING_INFO pssInfo;
783 pssInfo.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);
784 pssInfo.cbSalt = saltLen;
785
786 if (pssInfo.pszAlgId == NULL) {
787 ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,
788 "Unrecognised hash algorithm");
789 __leave;
790 }
791
792 DWORD dwBufLen = 0;
793 SS_CHECK(::NCryptSignHash(
794 hk,
795 &pssInfo,
796 (BYTE*)pHashBuffer, jHashSize,
797 NULL, 0, &dwBufLen,
798 BCRYPT_PAD_PSS
799 ));
800
801 pSignedHashBuffer = new (env) jbyte[dwBufLen];
802 if (pSignedHashBuffer == NULL) {
803 __leave;
804 }
805
806 SS_CHECK(::NCryptSignHash(
807 hk,
808 &pssInfo,
809 (BYTE*)pHashBuffer, jHashSize,
810 (BYTE*)pSignedHashBuffer, dwBufLen, &dwBufLen,
811 BCRYPT_PAD_PSS
812 ));
813
814 // Create new byte array
815 jbyteArray temp = env->NewByteArray(dwBufLen);
816
817 // Copy data from native buffer
818 env->SetByteArrayRegion(temp, 0, dwBufLen, pSignedHashBuffer);
819
820 jSignedHash = temp;
821 }
822 __finally
823 {
824 if (pSignedHashBuffer)
825 delete [] pSignedHashBuffer;
826
827 if (pHashBuffer)
828 delete [] pHashBuffer;
829
830 if (hk != NULL)
831 ::NCryptFreeObject(hk);
690 } 832 }
691 833
692 return jSignedHash; 834 return jSignedHash;
693 } 835 }
694 836
790 if (hHash) 932 if (hHash)
791 ::CryptDestroyHash(hHash); 933 ::CryptDestroyHash(hHash);
792 934
793 if (hCryptProvAlt) 935 if (hCryptProvAlt)
794 ::CryptReleaseContext(hCryptProvAlt, 0); 936 ::CryptReleaseContext(hCryptProvAlt, 0);
937 }
938
939 return result;
940 }
941
942 /*
943 * Class: sun_security_mscapi_RSASignature_PSS
944 * Method: verifyPssSignedHash
945 * Signature: ([BI[BIILjava/lang/String;JJ)Z
946 */
947 JNIEXPORT jboolean JNICALL Java_sun_security_mscapi_RSASignature_00024PSS_verifyPssSignedHash
948 (JNIEnv *env, jclass clazz,
949 jbyteArray jHash, jint jHashSize,
950 jbyteArray jSignedHash, jint jSignedHashSize,
951 jint saltLen, jstring jHashAlgorithm,
952 jlong hCryptProv, jlong hKey)
953 {
954 jbyte* pHashBuffer = NULL;
955 jbyte* pSignedHashBuffer = NULL;
956 jboolean result = JNI_FALSE;
957 NCRYPT_KEY_HANDLE hk = NULL;
958
959 __try
960 {
961 SS_CHECK(::NCryptTranslateHandle(
962 NULL,
963 &hk,
964 hCryptProv,
965 hKey,
966 NULL,
967 0));
968
969 // Copy hash and signedHash from Java to native buffer
970 pHashBuffer = new (env) jbyte[jHashSize];
971 if (pHashBuffer == NULL) {
972 __leave;
973 }
974 env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);
975
976 pSignedHashBuffer = new (env) jbyte[jSignedHashSize];
977 if (pSignedHashBuffer == NULL) {
978 __leave;
979 }
980 env->GetByteArrayRegion(jSignedHash, 0, jSignedHashSize,
981 pSignedHashBuffer);
982
983 BCRYPT_PSS_PADDING_INFO pssInfo;
984 pssInfo.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);
985 pssInfo.cbSalt = saltLen;
986
987 if (pssInfo.pszAlgId == NULL) {
988 ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,
989 "Unrecognised hash algorithm");
990 __leave;
991 }
992
993 // For RSA, the hash encryption algorithm is normally the same as the
994 // public key algorithm, so AT_SIGNATURE is used.
995
996 // Verify the signature
997 if (::NCryptVerifySignature(hk, &pssInfo,
998 (BYTE *) pHashBuffer, jHashSize,
999 (BYTE *) pSignedHashBuffer, jSignedHashSize,
1000 NCRYPT_PAD_PSS_FLAG) == ERROR_SUCCESS)
1001 {
1002 result = JNI_TRUE;
1003 }
1004 }
1005
1006 __finally
1007 {
1008 if (pSignedHashBuffer)
1009 delete [] pSignedHashBuffer;
1010
1011 if (pHashBuffer)
1012 delete [] pHashBuffer;
1013
1014 if (hk != NULL)
1015 ::NCryptFreeObject(hk);
795 } 1016 }
796 1017
797 return result; 1018 return result;
798 } 1019 }
799 1020