1 /*
2  * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 //=--------------------------------------------------------------------------=
27 // security.cpp    by Stanley Man-Kit Ho
28 //=--------------------------------------------------------------------------=
29 //
30 
31 #include <jni.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <windows.h>
35 #include <BaseTsd.h>
36 #include <wincrypt.h>
37 #include <stdio.h>
38 #include <memory>
39 #include "sun_security_mscapi_CKey.h"
40 #include "sun_security_mscapi_CKeyStore.h"
41 #include "sun_security_mscapi_CRSACipher.h"
42 #include "sun_security_mscapi_CKeyPairGenerator_RSA.h"
43 #include "sun_security_mscapi_CPublicKey.h"
44 #include "sun_security_mscapi_CPublicKey_CRSAPublicKey.h"
45 #include "sun_security_mscapi_CSignature.h"
46 #include "sun_security_mscapi_CSignature_RSA.h"
47 
48 
49 #define OID_EKU_ANY         "2.5.29.37.0"
50 
51 #define CERTIFICATE_PARSING_EXCEPTION \
52                             "java/security/cert/CertificateParsingException"
53 #define INVALID_KEY_EXCEPTION \
54                             "java/security/InvalidKeyException"
55 #define KEY_EXCEPTION       "java/security/KeyException"
56 #define KEYSTORE_EXCEPTION  "java/security/KeyStoreException"
57 #define PROVIDER_EXCEPTION  "java/security/ProviderException"
58 #define SIGNATURE_EXCEPTION "java/security/SignatureException"
59 #define OUT_OF_MEMORY_ERROR "java/lang/OutOfMemoryError"
60 
61 #define SS_CHECK(Status) \
62         if (Status != ERROR_SUCCESS) { \
63             ThrowException(env, SIGNATURE_EXCEPTION, Status); \
64             __leave; \
65         }
66 
67 #define PP(fmt, ...) \
68         if (trace) { \
69             fprintf(stdout, "MSCAPI (%ld): ", __LINE__); \
70             fprintf(stdout, fmt, ##__VA_ARGS__); \
71             fprintf(stdout, "\n"); \
72             fflush(stdout); \
73         }
74 
75 extern "C" {
76 
77 char* trace = getenv("CAPI_TRACE");
78 
79 void showProperty(NCRYPT_HANDLE hKey);
80 
dump(LPSTR title,PBYTE data,DWORD len)81 void dump(LPSTR title, PBYTE data, DWORD len)
82 {
83     if (trace) {
84         printf("==== %s ====\n", title);
85         for (DWORD i = 0; i < len; i+=16) {
86             printf("%04x: ", i);
87             for (int j = 0; j < 16; j++) {
88                 if (j == 8) {
89                     printf("  ");
90                 }
91                 if (i + j < len) {
92                     printf("%02X ", *(data + i + j) & 0xff);
93                 } else {
94                     printf("   ");
95                 }
96             }
97             for (int j = 0; j < 16; j++) {
98                 if (i + j < len) {
99                     int k = *(data + i + j) & 0xff;
100                     if (k < 32 || k > 127) printf(".");
101                     else printf("%c", (char)k);
102                 }
103             }
104             printf("\n");
105         }
106         fflush(stdout);
107     }
108 }
109 
110 /*
111  * Throws an arbitrary Java exception with the given message.
112  */
ThrowExceptionWithMessage(JNIEnv * env,const char * exceptionName,const char * szMessage)113 void ThrowExceptionWithMessage(JNIEnv *env, const char *exceptionName,
114                                const char *szMessage)
115 {
116     jclass exceptionClazz = env->FindClass(exceptionName);
117     if (exceptionClazz != NULL) {
118         env->ThrowNew(exceptionClazz, szMessage);
119     }
120 }
121 
122 /*
123  * Throws an arbitrary Java exception.
124  * The exception message is a Windows system error message.
125  */
ThrowException(JNIEnv * env,const char * exceptionName,DWORD dwError)126 void ThrowException(JNIEnv *env, const char *exceptionName, DWORD dwError)
127 {
128     char szMessage[1024];
129     szMessage[0] = '\0';
130 
131     DWORD res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError,
132         NULL, szMessage, sizeof(szMessage), NULL);
133     if (res == 0) {
134         strcpy(szMessage, "Unknown error");
135     }
136 
137     ThrowExceptionWithMessage(env, exceptionName, szMessage);
138 }
139 
140 /*
141  * Overloaded 'operator new[]' variant, which will raise Java's
142  * OutOfMemoryError in the case of a failure.
143  */
operator new[](std::size_t size,JNIEnv * env)144 void* operator new[](std::size_t size, JNIEnv *env)
145 {
146     void* buf = ::operator new[](size, std::nothrow);
147     if (buf == NULL) {
148         ThrowExceptionWithMessage(env, OUT_OF_MEMORY_ERROR,
149                 "Native memory allocation failed");
150     }
151     return buf;
152 }
153 
154 /*
155  * Maps the name of a hash algorithm to an algorithm identifier.
156  */
MapHashAlgorithm(JNIEnv * env,jstring jHashAlgorithm)157 ALG_ID MapHashAlgorithm(JNIEnv *env, jstring jHashAlgorithm) {
158 
159     const char* pszHashAlgorithm = NULL;
160     ALG_ID algId = 0;
161 
162     if ((pszHashAlgorithm = env->GetStringUTFChars(jHashAlgorithm, NULL))
163         == NULL) {
164         return algId;
165     }
166 
167     if ((strcmp("SHA", pszHashAlgorithm) == 0) ||
168         (strcmp("SHA1", pszHashAlgorithm) == 0) ||
169         (strcmp("SHA-1", pszHashAlgorithm) == 0)) {
170 
171         algId = CALG_SHA1;
172     } else if (strcmp("SHA1+MD5", pszHashAlgorithm) == 0) {
173         algId = CALG_SSL3_SHAMD5; // a 36-byte concatenation of SHA-1 and MD5
174     } else if (strcmp("SHA-256", pszHashAlgorithm) == 0) {
175         algId = CALG_SHA_256;
176     } else if (strcmp("SHA-384", pszHashAlgorithm) == 0) {
177         algId = CALG_SHA_384;
178     } else if (strcmp("SHA-512", pszHashAlgorithm) == 0) {
179         algId = CALG_SHA_512;
180     } else if (strcmp("MD5", pszHashAlgorithm) == 0) {
181         algId = CALG_MD5;
182     } else if (strcmp("MD2", pszHashAlgorithm) == 0) {
183         algId = CALG_MD2;
184     }
185 
186     if (pszHashAlgorithm)
187         env->ReleaseStringUTFChars(jHashAlgorithm, pszHashAlgorithm);
188 
189    return algId;
190 }
191 
192 /*
193  * Maps the name of a hash algorithm to a CNG Algorithm Identifier.
194  */
MapHashIdentifier(JNIEnv * env,jstring jHashAlgorithm)195 LPCWSTR MapHashIdentifier(JNIEnv *env, jstring jHashAlgorithm) {
196 
197     const char* pszHashAlgorithm = NULL;
198     LPCWSTR id = NULL;
199 
200     if ((pszHashAlgorithm = env->GetStringUTFChars(jHashAlgorithm, NULL))
201             == NULL) {
202         return id;
203     }
204 
205     if ((strcmp("SHA", pszHashAlgorithm) == 0) ||
206         (strcmp("SHA1", pszHashAlgorithm) == 0) ||
207         (strcmp("SHA-1", pszHashAlgorithm) == 0)) {
208 
209         id = BCRYPT_SHA1_ALGORITHM;
210     } else if (strcmp("SHA-256", pszHashAlgorithm) == 0) {
211         id = BCRYPT_SHA256_ALGORITHM;
212     } else if (strcmp("SHA-384", pszHashAlgorithm) == 0) {
213         id = BCRYPT_SHA384_ALGORITHM;
214     } else if (strcmp("SHA-512", pszHashAlgorithm) == 0) {
215         id = BCRYPT_SHA512_ALGORITHM;
216     }
217 
218     if (pszHashAlgorithm)
219         env->ReleaseStringUTFChars(jHashAlgorithm, pszHashAlgorithm);
220 
221     return id;
222 }
223 
224 /*
225  * Returns a certificate chain context given a certificate context and key
226  * usage identifier.
227  */
GetCertificateChain(LPSTR lpszKeyUsageIdentifier,PCCERT_CONTEXT pCertContext,PCCERT_CHAIN_CONTEXT * ppChainContext)228 bool GetCertificateChain(LPSTR lpszKeyUsageIdentifier, PCCERT_CONTEXT pCertContext, PCCERT_CHAIN_CONTEXT* ppChainContext)
229 {
230     CERT_ENHKEY_USAGE        EnhkeyUsage;
231     CERT_USAGE_MATCH         CertUsage;
232     CERT_CHAIN_PARA          ChainPara;
233     DWORD                    dwFlags = 0;
234     LPSTR                    szUsageIdentifierArray[1];
235 
236     szUsageIdentifierArray[0] = lpszKeyUsageIdentifier;
237     EnhkeyUsage.cUsageIdentifier = 1;
238     EnhkeyUsage.rgpszUsageIdentifier = szUsageIdentifierArray;
239     CertUsage.dwType = USAGE_MATCH_TYPE_AND;
240     CertUsage.Usage  = EnhkeyUsage;
241     ChainPara.cbSize = sizeof(CERT_CHAIN_PARA);
242     ChainPara.RequestedUsage=CertUsage;
243 
244     // Build a chain using CertGetCertificateChain
245     // and the certificate retrieved.
246     return (::CertGetCertificateChain(NULL,     // use the default chain engine
247                 pCertContext,   // pointer to the end certificate
248                 NULL,           // use the default time
249                 NULL,           // search no additional stores
250                 &ChainPara,     // use AND logic and enhanced key usage
251                                 //  as indicated in the ChainPara
252                                 //  data structure
253                 dwFlags,
254                 NULL,           // currently reserved
255                 ppChainContext) == TRUE);       // return a pointer to the chain created
256 }
257 
258 
259 /////////////////////////////////////////////////////////////////////////////
260 //
261 
262 /*
263  * Class:     sun_security_mscapi_PRNG
264  * Method:    generateSeed
265  * Signature: (I[B)[B
266  */
Java_sun_security_mscapi_PRNG_generateSeed(JNIEnv * env,jclass clazz,jint length,jbyteArray seed)267 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_PRNG_generateSeed
268   (JNIEnv *env, jclass clazz, jint length, jbyteArray seed)
269 {
270 
271     HCRYPTPROV hCryptProv = NULL;
272     jbyte*     reseedBytes = NULL;
273     jbyte*     seedBytes = NULL;
274     jbyteArray result = NULL;
275 
276     __try
277     {
278         //  Acquire a CSP context.
279         if(::CryptAcquireContext( //deprecated
280            &hCryptProv,
281            NULL,
282            NULL,
283            PROV_RSA_FULL,
284            CRYPT_VERIFYCONTEXT) == FALSE)
285         {
286             ThrowException(env, PROVIDER_EXCEPTION, GetLastError());
287             __leave;
288         }
289 
290         /*
291          * If length is negative and a seed is supplied, use it to re-seed the
292          * generator. Return null whether a seed is supplied or not.
293          * If length is non-zero then generate a new seed according to the
294          * requested length and return the new seed.
295          * If length is zero then overwrite the supplied seed with a new
296          * seed of the same length and return the seed.
297          */
298         if (length < 0) {
299             if (seed == NULL) {
300                 __leave;
301             }
302             length = env->GetArrayLength(seed);
303             if ((reseedBytes = env->GetByteArrayElements(seed, 0)) == NULL) {
304                 __leave;
305             }
306 
307             if (::CryptGenRandom( //deprecated
308                 hCryptProv,
309                 length,
310                 (BYTE *) reseedBytes) == FALSE) {
311 
312                 ThrowException(env, PROVIDER_EXCEPTION, GetLastError());
313                 __leave;
314             }
315 
316             result = NULL;
317 
318         } else {
319 
320             if (length > 0) {
321                 seed = env->NewByteArray(length);
322                 if (seed == NULL) {
323                     __leave;
324                 }
325             } else {
326                 length = env->GetArrayLength(seed);
327             }
328 
329             if ((seedBytes = env->GetByteArrayElements(seed, 0)) == NULL) {
330                 __leave;
331             }
332 
333             if (::CryptGenRandom( //deprecated
334                 hCryptProv,
335                 length,
336                 (BYTE *) seedBytes) == FALSE) {
337 
338                 ThrowException(env, PROVIDER_EXCEPTION, GetLastError());
339                 __leave;
340             }
341 
342             result = seed; // seed will be updated when seedBytes gets released
343         }
344     }
345     __finally
346     {
347         //--------------------------------------------------------------------
348         // Clean up.
349 
350         if (reseedBytes)
351             env->ReleaseByteArrayElements(seed, reseedBytes, JNI_ABORT);
352 
353         if (seedBytes)
354             env->ReleaseByteArrayElements(seed, seedBytes, 0); // update orig
355 
356         if (hCryptProv)
357             ::CryptReleaseContext(hCryptProv, 0); //deprecated
358     }
359 
360     return result;
361 }
362 
363 
364 /*
365  * Class:     sun_security_mscapi_CKeyStore
366  * Method:    loadKeysOrCertificateChains
367  * Signature: (Ljava/lang/String;)V
368  */
Java_sun_security_mscapi_CKeyStore_loadKeysOrCertificateChains(JNIEnv * env,jobject obj,jstring jCertStoreName)369 JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_loadKeysOrCertificateChains
370   (JNIEnv *env, jobject obj, jstring jCertStoreName)
371 {
372     /**
373      * Certificate in cert store has enhanced key usage extension
374      * property (or EKU property) that is not part of the certificate itself. To determine
375      * if the certificate should be returned, both the enhanced key usage in certificate
376      * extension block and the extension property stored along with the certificate in
377      * certificate store should be examined. Otherwise, we won't be able to determine
378      * the proper key usage from the Java side because the information is not stored as
379      * part of the encoded certificate.
380      */
381 
382     const char* pszCertStoreName = NULL;
383     HCERTSTORE hCertStore = NULL;
384     PCCERT_CONTEXT pCertContext = NULL;
385     char* pszNameString = NULL; // certificate's friendly name
386     DWORD cchNameString = 0;
387 
388 
389     __try
390     {
391         // Open a system certificate store.
392         if ((pszCertStoreName = env->GetStringUTFChars(jCertStoreName, NULL))
393             == NULL) {
394             __leave;
395         }
396         if ((hCertStore = ::CertOpenSystemStore(NULL, pszCertStoreName))
397             == NULL) {
398 
399             ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
400             __leave;
401         }
402 
403         // Determine clazz and method ID to generate certificate
404         jclass clazzArrayList = env->FindClass("java/util/ArrayList");
405         if (clazzArrayList == NULL) {
406             __leave;
407         }
408 
409         jmethodID mNewArrayList = env->GetMethodID(clazzArrayList, "<init>", "()V");
410         if (mNewArrayList == NULL) {
411             __leave;
412         }
413 
414         jclass clazzOfThis = env->GetObjectClass(obj);
415         if (clazzOfThis == NULL) {
416             __leave;
417         }
418 
419         jmethodID mGenCert = env->GetMethodID(clazzOfThis,
420                                               "generateCertificate",
421                                               "([BLjava/util/Collection;)V");
422         if (mGenCert == NULL) {
423             __leave;
424         }
425 
426         // Determine method ID to generate certificate chain
427         jmethodID mGenCertChain = env->GetMethodID(clazzOfThis,
428                                                    "generateCertificateChain",
429                                                    "(Ljava/lang/String;Ljava/util/Collection;)V");
430         if (mGenCertChain == NULL) {
431             __leave;
432         }
433 
434         // Determine method ID to generate RSA certificate chain
435         jmethodID mGenKeyAndCertChain = env->GetMethodID(clazzOfThis,
436                                                    "generateKeyAndCertificateChain",
437                                                    "(ZLjava/lang/String;JJILjava/util/Collection;)V");
438         if (mGenKeyAndCertChain == NULL) {
439             __leave;
440         }
441 
442         // Use CertEnumCertificatesInStore to get the certificates
443         // from the open store. pCertContext must be reset to
444         // NULL to retrieve the first certificate in the store.
445         while (pCertContext = ::CertEnumCertificatesInStore(hCertStore, pCertContext))
446         {
447             PP("--------------------------");
448             // Check if private key available - client authentication certificate
449             // must have private key available.
450             HCRYPTPROV hCryptProv = NULL;
451             DWORD dwKeySpec = 0;
452             HCRYPTKEY hUserKey = NULL;
453             BOOL bCallerFreeProv = FALSE;
454             BOOL bHasNoPrivateKey = FALSE;
455             DWORD dwPublicKeyLength = 0;
456 
457             // First, probe it silently
458             if (::CryptAcquireCertificatePrivateKey(pCertContext,
459                     CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG | CRYPT_ACQUIRE_SILENT_FLAG, NULL,
460                     &hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE
461                 && GetLastError() != NTE_SILENT_CONTEXT)
462             {
463                 PP("bHasNoPrivateKey = TRUE!");
464                 bHasNoPrivateKey = TRUE;
465             }
466             else
467             {
468                 if (bCallerFreeProv == TRUE) {
469                     ::CryptReleaseContext(hCryptProv, NULL); // deprecated
470                     bCallerFreeProv = FALSE;
471                 }
472 
473                 // Second, acquire the key normally (not silently)
474                 if (::CryptAcquireCertificatePrivateKey(pCertContext, CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG, NULL,
475                         &hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE)
476                 {
477                     PP("bHasNoPrivateKey = TRUE!!");
478                     bHasNoPrivateKey = TRUE;
479                 }
480                 else
481                 {
482                     if ((dwKeySpec & CERT_NCRYPT_KEY_SPEC) == CERT_NCRYPT_KEY_SPEC) {
483                         PP("CNG %I64d", (__int64)hCryptProv);
484                     } else {
485                         // Private key is available
486                         BOOL bGetUserKey = ::CryptGetUserKey(hCryptProv, dwKeySpec, &hUserKey); //deprecated
487 
488                         // Skip certificate if cannot find private key
489                         if (bGetUserKey == FALSE) {
490                             if (bCallerFreeProv)
491                                 ::CryptReleaseContext(hCryptProv, NULL); // deprecated
492                             continue;
493                         }
494 
495                         // Set cipher mode to ECB
496                         DWORD dwCipherMode = CRYPT_MODE_ECB;
497                         ::CryptSetKeyParam(hUserKey, KP_MODE, (BYTE*)&dwCipherMode, NULL); //deprecated
498                         PP("CAPI %I64d %I64d", (__int64)hCryptProv, (__int64)hUserKey);
499                     }
500                     // If the private key is present in smart card, we may not be able to
501                     // determine the key length by using the private key handle. However,
502                     // since public/private key pairs must have the same length, we could
503                     // determine the key length of the private key by using the public key
504                     // in the certificate.
505                     dwPublicKeyLength = ::CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
506                             &(pCertContext->pCertInfo->SubjectPublicKeyInfo));
507                 }
508             }
509             PCCERT_CHAIN_CONTEXT pCertChainContext = NULL;
510 
511             // Build certificate chain by using system certificate store.
512             // Add cert chain into collection for any key usage.
513             //
514             if (GetCertificateChain(OID_EKU_ANY, pCertContext, &pCertChainContext))
515             {
516                 for (DWORD i = 0; i < pCertChainContext->cChain; i++)
517                 {
518                     // Found cert chain
519                     PCERT_SIMPLE_CHAIN rgpChain =
520                         pCertChainContext->rgpChain[i];
521 
522                     // Create ArrayList to store certs in each chain
523                     jobject jArrayList =
524                         env->NewObject(clazzArrayList, mNewArrayList);
525                     if (jArrayList == NULL) {
526                         __leave;
527                     }
528 
529                     // Cleanup the previous allocated name
530                     if (pszNameString) {
531                         delete [] pszNameString;
532                         pszNameString = NULL;
533                     }
534 
535                     for (unsigned int j=0; j < rgpChain->cElement; j++)
536                     {
537                         PCERT_CHAIN_ELEMENT rgpElement =
538                             rgpChain->rgpElement[j];
539                         PCCERT_CONTEXT pc = rgpElement->pCertContext;
540 
541                         // Retrieve the friendly name of the first certificate
542                         // in the chain
543                         if (j == 0) {
544 
545                             // If the cert's name cannot be retrieved then
546                             // pszNameString remains set to NULL.
547                             // (An alias name will be generated automatically
548                             // when storing this cert in the keystore.)
549 
550                             // Get length of friendly name
551                             if ((cchNameString = CertGetNameString(pc,
552                                 CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL,
553                                 NULL, 0)) > 1) {
554 
555                                 // Found friendly name
556                                 pszNameString = new (env) char[cchNameString];
557                                 if (pszNameString == NULL) {
558                                     __leave;
559                                 }
560 
561                                 CertGetNameString(pc,
562                                     CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL,
563                                     pszNameString, cchNameString);
564                             }
565                         }
566 
567                         BYTE* pbCertEncoded = pc->pbCertEncoded;
568                         DWORD cbCertEncoded = pc->cbCertEncoded;
569 
570                         // Allocate and populate byte array
571                         jbyteArray byteArray = env->NewByteArray(cbCertEncoded);
572                         if (byteArray == NULL) {
573                             __leave;
574                         }
575                         env->SetByteArrayRegion(byteArray, 0, cbCertEncoded,
576                             (jbyte*) pbCertEncoded);
577 
578                         // Generate certificate from byte array and store into
579                         // cert collection
580                         env->CallVoidMethod(obj, mGenCert, byteArray, jArrayList);
581                     }
582 
583                     // Usually pszNameString should be non-NULL. It's either
584                     // the friendly name or an element from the subject name
585                     // or SAN.
586                     if (pszNameString)
587                     {
588                         PP("%s: %s", pszNameString,
589                             pCertContext->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
590                         if (bHasNoPrivateKey)
591                         {
592                             // Generate certificate chain and store into cert chain
593                             // collection
594                             jstring name = env->NewStringUTF(pszNameString);
595                             if (name == NULL) {
596                                 __leave;
597                             }
598                             env->CallVoidMethod(obj, mGenCertChain,
599                                 name,
600                                 jArrayList);
601                         }
602                         else
603                         {
604                             if (hUserKey) {
605                                 // Only accept RSA for CAPI
606                                 DWORD dwData = CALG_RSA_KEYX;
607                                 DWORD dwSize = sizeof(DWORD);
608                                 ::CryptGetKeyParam(hUserKey, KP_ALGID, (BYTE*)&dwData, //deprecated
609                                         &dwSize, NULL);
610                                 if ((dwData & ALG_TYPE_RSA) == ALG_TYPE_RSA)
611                                 {
612                                     // Generate RSA certificate chain and store into cert
613                                     // chain collection
614                                     jstring name = env->NewStringUTF(pszNameString);
615                                     if (name == NULL) {
616                                         __leave;
617                                     }
618                                     env->CallVoidMethod(obj, mGenKeyAndCertChain,
619                                             1,
620                                             name,
621                                             (jlong) hCryptProv, (jlong) hUserKey,
622                                             dwPublicKeyLength, jArrayList);
623                                 }
624                             } else {
625                                 // Only accept EC for CNG
626                                 BYTE buffer[32];
627                                 DWORD len = 0;
628                                 if (::NCryptGetProperty(
629                                         hCryptProv, NCRYPT_ALGORITHM_PROPERTY,
630                                         (PBYTE)buffer, 32, &len, NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) {
631                                     jstring name = env->NewStringUTF(pszNameString);
632                                     if (name == NULL) {
633                                         __leave;
634                                     }
635                                     if (buffer[0] == 'E' && buffer[2] == 'C'
636                                             && (dwPublicKeyLength == 256
637                                                     || dwPublicKeyLength == 384
638                                                     || dwPublicKeyLength == 521)) {
639                                         env->CallVoidMethod(obj, mGenKeyAndCertChain,
640                                             0,
641                                             name,
642                                             (jlong) hCryptProv, (jlong) 0,
643                                             dwPublicKeyLength, jArrayList);
644                                     } else if (buffer[0] == 'R' && buffer[2] == 'S'
645                                             && buffer[4] == 'A') {
646                                         env->CallVoidMethod(obj, mGenKeyAndCertChain,
647                                             1,
648                                             name,
649                                             (jlong) hCryptProv, (jlong) 0,
650                                             dwPublicKeyLength, jArrayList);
651                                     } else {
652                                         dump("Unknown NCRYPT_ALGORITHM_PROPERTY", buffer, len);
653                                     }
654                                 }
655                             }
656                         }
657                     }
658                 }
659 
660                 // Free cert chain
661                 if (pCertChainContext)
662                     ::CertFreeCertificateChain(pCertChainContext);
663             } else {
664                 PP("GetCertificateChain failed %d", GetLastError());
665             }
666         }
667     }
668     __finally
669     {
670         if (hCertStore)
671             ::CertCloseStore(hCertStore, 0);
672 
673         if (pszCertStoreName)
674             env->ReleaseStringUTFChars(jCertStoreName, pszCertStoreName);
675 
676         if (pszNameString)
677             delete [] pszNameString;
678     }
679 }
680 
681 
682 /*
683  * Class:     sun_security_mscapi_CKey
684  * Method:    cleanUp
685  * Signature: (JJ)V
686  */
Java_sun_security_mscapi_CKey_cleanUp(JNIEnv * env,jclass clazz,jlong hCryptProv,jlong hCryptKey)687 JNIEXPORT void JNICALL Java_sun_security_mscapi_CKey_cleanUp
688   (JNIEnv *env, jclass clazz, jlong hCryptProv, jlong hCryptKey)
689 {
690     if (hCryptKey == NULL && hCryptProv != NULL) {
691         NCryptFreeObject((NCRYPT_HANDLE)hCryptProv);
692     } else {
693         if (hCryptKey != NULL)
694             ::CryptDestroyKey((HCRYPTKEY) hCryptKey); // deprecated
695 
696         if (hCryptProv != NULL)
697             ::CryptReleaseContext((HCRYPTPROV) hCryptProv, NULL); // deprecated
698     }
699 }
700 
701 /*
702  * Class:     sun_security_mscapi_CSignature
703  * Method:    signHash
704  * Signature: (Z[BILjava/lang/String;JJ)[B
705  */
Java_sun_security_mscapi_CSignature_signHash(JNIEnv * env,jclass clazz,jboolean noHashOID,jbyteArray jHash,jint jHashSize,jstring jHashAlgorithm,jlong hCryptProv,jlong hCryptKey)706 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CSignature_signHash
707   (JNIEnv *env, jclass clazz, jboolean noHashOID, jbyteArray jHash,
708         jint jHashSize, jstring jHashAlgorithm, jlong hCryptProv,
709         jlong hCryptKey)
710 {
711     HCRYPTHASH hHash = NULL;
712     jbyte* pHashBuffer = NULL;
713     jbyte* pSignedHashBuffer = NULL;
714     jbyteArray jSignedHash = NULL;
715     HCRYPTPROV hCryptProvAlt = NULL;
716 
717     __try
718     {
719         // Map hash algorithm
720         ALG_ID algId = MapHashAlgorithm(env, jHashAlgorithm);
721 
722         // Acquire a hash object handle.
723         if (::CryptCreateHash(HCRYPTPROV(hCryptProv), algId, 0, 0, &hHash) == FALSE) //deprecated
724         {
725             // Failover to using the PROV_RSA_AES CSP
726 
727             DWORD cbData = 256;
728             BYTE pbData[256];
729             pbData[0] = '\0';
730 
731             // Get name of the key container
732             ::CryptGetProvParam((HCRYPTPROV)hCryptProv, PP_CONTAINER, //deprecated
733                 (BYTE *)pbData, &cbData, 0);
734 
735             // Acquire an alternative CSP handle
736             if (::CryptAcquireContext(&hCryptProvAlt, LPCSTR(pbData), NULL, //deprecated
737                 PROV_RSA_AES, 0) == FALSE)
738             {
739 
740                 ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
741                 __leave;
742             }
743 
744             // Acquire a hash object handle.
745             if (::CryptCreateHash(HCRYPTPROV(hCryptProvAlt), algId, 0, 0, //deprecated
746                 &hHash) == FALSE)
747             {
748                 ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
749                 __leave;
750             }
751         }
752 
753         // Copy hash from Java to native buffer
754         pHashBuffer = new (env) jbyte[jHashSize];
755         if (pHashBuffer == NULL) {
756             __leave;
757         }
758         env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);
759 
760         // Set hash value in the hash object
761         if (::CryptSetHashParam(hHash, HP_HASHVAL, (BYTE*)pHashBuffer, NULL) == FALSE) //deprecated
762         {
763             ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
764             __leave;
765         }
766 
767         // Determine key spec.
768         DWORD dwKeySpec = AT_SIGNATURE;
769         ALG_ID dwAlgId;
770         DWORD dwAlgIdLen = sizeof(ALG_ID);
771 
772         if (! ::CryptGetKeyParam((HCRYPTKEY) hCryptKey, KP_ALGID, (BYTE*)&dwAlgId, &dwAlgIdLen, 0)) { //deprecated
773             ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
774             __leave;
775 
776         }
777         if (CALG_RSA_KEYX == dwAlgId) {
778             dwKeySpec = AT_KEYEXCHANGE;
779         }
780 
781         // Determine size of buffer
782         DWORD dwBufLen = 0;
783         DWORD dwFlags = 0;
784 
785         if (noHashOID == JNI_TRUE) {
786             dwFlags = CRYPT_NOHASHOID; // omit hash OID in NONEwithRSA signature
787         }
788 
789         if (::CryptSignHash(hHash, dwKeySpec, NULL, dwFlags, NULL, &dwBufLen) == FALSE) //deprecated
790         {
791             ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
792             __leave;
793         }
794 
795         pSignedHashBuffer = new (env) jbyte[dwBufLen];
796         if (pSignedHashBuffer == NULL) {
797             __leave;
798         }
799         if (::CryptSignHash(hHash, dwKeySpec, NULL, dwFlags, (BYTE*)pSignedHashBuffer, &dwBufLen) == FALSE) //deprecated
800         {
801             ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
802             __leave;
803         }
804 
805         // Create new byte array
806         jbyteArray temp = env->NewByteArray(dwBufLen);
807         if (temp == NULL) {
808             __leave;
809         }
810 
811         // Copy data from native buffer
812         env->SetByteArrayRegion(temp, 0, dwBufLen, pSignedHashBuffer);
813 
814         jSignedHash = temp;
815     }
816     __finally
817     {
818         if (pSignedHashBuffer)
819             delete [] pSignedHashBuffer;
820 
821         if (pHashBuffer)
822             delete [] pHashBuffer;
823 
824         if (hHash)
825             ::CryptDestroyHash(hHash); //deprecated
826 
827         if (hCryptProvAlt)
828             ::CryptReleaseContext(hCryptProvAlt, 0); // deprecated
829     }
830 
831     return jSignedHash;
832 }
833 
834 /*
835  * Class:     sun_security_mscapi_CSignature
836  * Method:    signCngHash
837  * Signature: (I[BIILjava/lang/String;JJ)[B
838  */
Java_sun_security_mscapi_CSignature_signCngHash(JNIEnv * env,jclass clazz,jint type,jbyteArray jHash,jint jHashSize,jint saltLen,jstring jHashAlgorithm,jlong hCryptProv,jlong hCryptKey)839 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CSignature_signCngHash
840   (JNIEnv *env, jclass clazz, jint type, jbyteArray jHash,
841         jint jHashSize, jint saltLen, jstring jHashAlgorithm, jlong hCryptProv,
842         jlong hCryptKey)
843 {
844     jbyteArray jSignedHash = NULL;
845 
846     jbyte* pHashBuffer = NULL;
847     jbyte* pSignedHashBuffer = NULL;
848     NCRYPT_KEY_HANDLE hk = NULL;
849 
850     __try
851     {
852         if (hCryptKey == 0) {
853             hk = (NCRYPT_KEY_HANDLE)hCryptProv;
854         } else {
855             SS_CHECK(::NCryptTranslateHandle(
856                 NULL,
857                 &hk,
858                 (HCRYPTPROV)hCryptProv,
859                 (HCRYPTKEY)hCryptKey,
860                 NULL,
861                 0));
862         }
863 
864         // Copy hash from Java to native buffer
865         pHashBuffer = new (env) jbyte[jHashSize];
866         if (pHashBuffer == NULL) {
867             __leave;
868         }
869         env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);
870 
871         VOID* param;
872         DWORD dwFlags;
873 
874         switch (type) {
875         case 0:
876             param = NULL;
877             dwFlags = 0;
878             break;
879         case 1:
880             BCRYPT_PKCS1_PADDING_INFO pkcs1Info;
881             if (jHashAlgorithm) {
882                 pkcs1Info.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);
883                 if (pkcs1Info.pszAlgId == NULL) {
884                     ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,
885                             "Unrecognised hash algorithm");
886                     __leave;
887                 }
888             } else {
889                 pkcs1Info.pszAlgId = NULL;
890             }
891             param = &pkcs1Info;
892             dwFlags = BCRYPT_PAD_PKCS1;
893             break;
894         case 2:
895             BCRYPT_PSS_PADDING_INFO pssInfo;
896             pssInfo.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);
897             pssInfo.cbSalt = saltLen;
898             if (pssInfo.pszAlgId == NULL) {
899                 ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,
900                         "Unrecognised hash algorithm");
901                 __leave;
902             }
903             param = &pssInfo;
904             dwFlags = BCRYPT_PAD_PSS;
905             break;
906         }
907 
908         DWORD jSignedHashSize = 0;
909         SS_CHECK(::NCryptSignHash(
910                 hk,
911                 param,
912                 (BYTE*)pHashBuffer, jHashSize,
913                 NULL, 0, &jSignedHashSize,
914                 dwFlags
915                 ));
916 
917         pSignedHashBuffer = new (env) jbyte[jSignedHashSize];
918         if (pSignedHashBuffer == NULL) {
919             __leave;
920         }
921 
922         SS_CHECK(::NCryptSignHash(
923                 hk,
924                 param,
925                 (BYTE*)pHashBuffer, jHashSize,
926                 (BYTE*)pSignedHashBuffer, jSignedHashSize, &jSignedHashSize,
927                 dwFlags
928                 ));
929 
930         // Create new byte array
931         jbyteArray temp = env->NewByteArray(jSignedHashSize);
932         if (temp == NULL) {
933             __leave;
934         }
935 
936         // Copy data from native buffer
937         env->SetByteArrayRegion(temp, 0, jSignedHashSize, pSignedHashBuffer);
938 
939         jSignedHash = temp;
940     }
941     __finally
942     {
943         if (pSignedHashBuffer)
944             delete [] pSignedHashBuffer;
945 
946         if (pHashBuffer)
947             delete [] pHashBuffer;
948 
949         if (hCryptKey != 0 && hk != NULL)
950             ::NCryptFreeObject(hk);
951     }
952 
953     return jSignedHash;
954 }
955 
956 /*
957  * Class:     sun_security_mscapi_CSignature
958  * Method:    verifySignedHash
959  * Signature: ([BIL/java/lang/String;[BIJJ)Z
960  */
Java_sun_security_mscapi_CSignature_verifySignedHash(JNIEnv * env,jclass clazz,jbyteArray jHash,jint jHashSize,jstring jHashAlgorithm,jbyteArray jSignedHash,jint jSignedHashSize,jlong hCryptProv,jlong hCryptKey)961 JNIEXPORT jboolean JNICALL Java_sun_security_mscapi_CSignature_verifySignedHash
962   (JNIEnv *env, jclass clazz, jbyteArray jHash, jint jHashSize,
963         jstring jHashAlgorithm, jbyteArray jSignedHash, jint jSignedHashSize,
964         jlong hCryptProv, jlong hCryptKey)
965 {
966     HCRYPTHASH hHash = NULL;
967     jbyte* pHashBuffer = NULL;
968     jbyte* pSignedHashBuffer = NULL;
969     DWORD dwSignedHashBufferLen = jSignedHashSize;
970     jboolean result = JNI_FALSE;
971     HCRYPTPROV hCryptProvAlt = NULL;
972 
973     __try
974     {
975         // Map hash algorithm
976         ALG_ID algId = MapHashAlgorithm(env, jHashAlgorithm);
977 
978         // Acquire a hash object handle.
979         if (::CryptCreateHash(HCRYPTPROV(hCryptProv), algId, 0, 0, &hHash)
980             == FALSE)
981         {
982             // Failover to using the PROV_RSA_AES CSP
983 
984             DWORD cbData = 256;
985             BYTE pbData[256];
986             pbData[0] = '\0';
987 
988             // Get name of the key container
989             ::CryptGetProvParam((HCRYPTPROV)hCryptProv, PP_CONTAINER, //deprecated
990                 (BYTE *)pbData, &cbData, 0);
991 
992             // Acquire an alternative CSP handle
993             if (::CryptAcquireContext(&hCryptProvAlt, LPCSTR(pbData), NULL, //deprecated
994                 PROV_RSA_AES, 0) == FALSE)
995             {
996 
997                 ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
998                 __leave;
999             }
1000 
1001             // Acquire a hash object handle.
1002             if (::CryptCreateHash(HCRYPTPROV(hCryptProvAlt), algId, 0, 0,
1003                 &hHash) == FALSE)
1004             {
1005                 ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
1006                 __leave;
1007             }
1008         }
1009 
1010         // Copy hash and signedHash from Java to native buffer
1011         pHashBuffer = new (env) jbyte[jHashSize];
1012         if (pHashBuffer == NULL) {
1013             __leave;
1014         }
1015         env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);
1016 
1017         pSignedHashBuffer = new (env) jbyte[jSignedHashSize];
1018         if (pSignedHashBuffer == NULL) {
1019             __leave;
1020         }
1021         env->GetByteArrayRegion(jSignedHash, 0, jSignedHashSize,
1022             pSignedHashBuffer);
1023 
1024         // Set hash value in the hash object
1025         if (::CryptSetHashParam(hHash, HP_HASHVAL, (BYTE*) pHashBuffer, NULL) //deprecated
1026             == FALSE)
1027         {
1028             ThrowException(env, SIGNATURE_EXCEPTION, GetLastError());
1029             __leave;
1030         }
1031 
1032         // For RSA, the hash encryption algorithm is normally the same as the
1033         // public key algorithm, so AT_SIGNATURE is used.
1034 
1035         // Verify the signature
1036         if (::CryptVerifySignatureA(hHash, (BYTE *) pSignedHashBuffer, //deprecated
1037             dwSignedHashBufferLen, (HCRYPTKEY) hCryptKey, NULL, 0) == TRUE)
1038         {
1039             result = JNI_TRUE;
1040         }
1041     }
1042 
1043     __finally
1044     {
1045         if (pSignedHashBuffer)
1046             delete [] pSignedHashBuffer;
1047 
1048         if (pHashBuffer)
1049             delete [] pHashBuffer;
1050 
1051         if (hHash)
1052             ::CryptDestroyHash(hHash); //deprecated
1053 
1054         if (hCryptProvAlt)
1055             ::CryptReleaseContext(hCryptProvAlt, 0); // deprecated
1056     }
1057 
1058     return result;
1059 }
1060 
1061 /*
1062  * Class:     sun_security_mscapi_CSignature
1063  * Method:    verifyCngSignedHash
1064  * Signature: (I[BI[BIILjava/lang/String;JJ)Z
1065  */
Java_sun_security_mscapi_CSignature_verifyCngSignedHash(JNIEnv * env,jclass clazz,jint type,jbyteArray jHash,jint jHashSize,jbyteArray jSignedHash,jint jSignedHashSize,jint saltLen,jstring jHashAlgorithm,jlong hCryptProv,jlong hCryptKey)1066 JNIEXPORT jboolean JNICALL Java_sun_security_mscapi_CSignature_verifyCngSignedHash
1067   (JNIEnv *env, jclass clazz, jint type,
1068         jbyteArray jHash, jint jHashSize,
1069         jbyteArray jSignedHash, jint jSignedHashSize,
1070         jint saltLen, jstring jHashAlgorithm,
1071         jlong hCryptProv, jlong hCryptKey)
1072 {
1073     jbyte* pHashBuffer = NULL;
1074     jbyte* pSignedHashBuffer = NULL;
1075     jboolean result = JNI_FALSE;
1076     NCRYPT_KEY_HANDLE hk = NULL;
1077 
1078     __try
1079     {
1080         if (hCryptKey == 0) {
1081             hk = (NCRYPT_KEY_HANDLE)hCryptProv;
1082         } else {
1083             SS_CHECK(::NCryptTranslateHandle(
1084                 NULL,
1085                 &hk,
1086                 (HCRYPTPROV)hCryptProv,
1087                 (HCRYPTKEY)hCryptKey,
1088                 NULL,
1089                 0));
1090         }
1091 
1092         // Copy hash and signedHash from Java to native buffer
1093         pHashBuffer = new (env) jbyte[jHashSize];
1094         if (pHashBuffer == NULL) {
1095             __leave;
1096         }
1097         env->GetByteArrayRegion(jHash, 0, jHashSize, pHashBuffer);
1098 
1099         pSignedHashBuffer = new (env) jbyte[jSignedHashSize];
1100         if (pSignedHashBuffer == NULL) {
1101             __leave;
1102         }
1103         env->GetByteArrayRegion(jSignedHash, 0, jSignedHashSize,
1104             pSignedHashBuffer);
1105 
1106         VOID* param;
1107         DWORD dwFlags;
1108 
1109         switch (type) {
1110         case 0:
1111             param = NULL;
1112             dwFlags = 0;
1113             break;
1114         case 1:
1115             BCRYPT_PKCS1_PADDING_INFO pkcs1Info;
1116             if (jHashAlgorithm) {
1117                 pkcs1Info.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);
1118                 if (pkcs1Info.pszAlgId == NULL) {
1119                     ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,
1120                             "Unrecognised hash algorithm");
1121                     __leave;
1122                 }
1123             } else {
1124                 pkcs1Info.pszAlgId = NULL;
1125             }
1126             param = &pkcs1Info;
1127             dwFlags = NCRYPT_PAD_PKCS1_FLAG;
1128             break;
1129         case 2:
1130             BCRYPT_PSS_PADDING_INFO pssInfo;
1131             pssInfo.pszAlgId = MapHashIdentifier(env, jHashAlgorithm);
1132             pssInfo.cbSalt = saltLen;
1133             if (pssInfo.pszAlgId == NULL) {
1134                 ThrowExceptionWithMessage(env, SIGNATURE_EXCEPTION,
1135                         "Unrecognised hash algorithm");
1136                 __leave;
1137             }
1138             param = &pssInfo;
1139             dwFlags = NCRYPT_PAD_PSS_FLAG;
1140             break;
1141         }
1142 
1143         if (::NCryptVerifySignature(hk, param,
1144                 (BYTE *) pHashBuffer, jHashSize,
1145                 (BYTE *) pSignedHashBuffer, jSignedHashSize,
1146                 dwFlags) == ERROR_SUCCESS)
1147         {
1148             result = JNI_TRUE;
1149         }
1150     }
1151 
1152     __finally
1153     {
1154         if (pSignedHashBuffer)
1155             delete [] pSignedHashBuffer;
1156 
1157         if (pHashBuffer)
1158             delete [] pHashBuffer;
1159 
1160         if (hCryptKey != 0 && hk != NULL)
1161             ::NCryptFreeObject(hk);
1162     }
1163 
1164     return result;
1165 }
1166 
1167 #define DUMP_PROP(p) \
1168     if (::NCryptGetProperty(hKey, p, (PBYTE)buffer, 8192, &len, NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) { \
1169         sprintf(header, "%s %ls", #p, p); \
1170         dump(header, buffer, len); \
1171     }
1172 
1173 #define EXPORT_BLOB(p) \
1174     desc.cBuffers = 0; \
1175     if (::NCryptExportKey(hKey, NULL, p, &desc, (PBYTE)buffer, 8192, &len, NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) { \
1176         sprintf(header, "%s %ls (%ld)", #p, p, desc.cBuffers); \
1177         dump(header, buffer, len); \
1178         for (int i = 0; i < (int)desc.cBuffers; i++) { \
1179             sprintf(header, "desc %ld", desc.pBuffers[i].BufferType); \
1180             dump(header, (PBYTE)desc.pBuffers[i].pvBuffer, desc.pBuffers[i].cbBuffer); \
1181         } \
1182     }
1183 
showProperty(NCRYPT_HANDLE hKey)1184 void showProperty(NCRYPT_HANDLE hKey) {
1185     char header[100];
1186     BYTE buffer[8192];
1187     DWORD len = 9;
1188     NCryptBufferDesc desc;
1189     DUMP_PROP(NCRYPT_ALGORITHM_GROUP_PROPERTY);
1190     DUMP_PROP(NCRYPT_ALGORITHM_PROPERTY);
1191     DUMP_PROP(NCRYPT_ASSOCIATED_ECDH_KEY);
1192     DUMP_PROP(NCRYPT_BLOCK_LENGTH_PROPERTY);
1193     DUMP_PROP(NCRYPT_CERTIFICATE_PROPERTY);
1194     DUMP_PROP(NCRYPT_DH_PARAMETERS_PROPERTY);
1195     DUMP_PROP(NCRYPT_EXPORT_POLICY_PROPERTY);
1196     DUMP_PROP(NCRYPT_IMPL_TYPE_PROPERTY);
1197     DUMP_PROP(NCRYPT_KEY_TYPE_PROPERTY);
1198     DUMP_PROP(NCRYPT_KEY_USAGE_PROPERTY);
1199     DUMP_PROP(NCRYPT_LAST_MODIFIED_PROPERTY);
1200     DUMP_PROP(NCRYPT_LENGTH_PROPERTY);
1201     DUMP_PROP(NCRYPT_LENGTHS_PROPERTY);
1202     DUMP_PROP(NCRYPT_MAX_NAME_LENGTH_PROPERTY);
1203     DUMP_PROP(NCRYPT_NAME_PROPERTY);
1204     DUMP_PROP(NCRYPT_PIN_PROMPT_PROPERTY);
1205     DUMP_PROP(NCRYPT_PIN_PROPERTY);
1206     DUMP_PROP(NCRYPT_PROVIDER_HANDLE_PROPERTY);
1207     DUMP_PROP(NCRYPT_READER_PROPERTY);
1208     DUMP_PROP(NCRYPT_ROOT_CERTSTORE_PROPERTY);
1209     DUMP_PROP(NCRYPT_SCARD_PIN_ID);
1210     DUMP_PROP(NCRYPT_SCARD_PIN_INFO);
1211     DUMP_PROP(NCRYPT_SECURE_PIN_PROPERTY);
1212     DUMP_PROP(NCRYPT_SECURITY_DESCR_PROPERTY);
1213     DUMP_PROP(NCRYPT_SECURITY_DESCR_SUPPORT_PROPERTY);
1214     DUMP_PROP(NCRYPT_SMARTCARD_GUID_PROPERTY);
1215     DUMP_PROP(NCRYPT_UI_POLICY_PROPERTY);
1216     DUMP_PROP(NCRYPT_UNIQUE_NAME_PROPERTY);
1217     DUMP_PROP(NCRYPT_USE_CONTEXT_PROPERTY);
1218     DUMP_PROP(NCRYPT_USE_COUNT_ENABLED_PROPERTY);
1219     DUMP_PROP(NCRYPT_USE_COUNT_PROPERTY);
1220     DUMP_PROP(NCRYPT_USER_CERTSTORE_PROPERTY);
1221     DUMP_PROP(NCRYPT_VERSION_PROPERTY);
1222     DUMP_PROP(NCRYPT_WINDOW_HANDLE_PROPERTY);
1223 
1224     EXPORT_BLOB(BCRYPT_DH_PRIVATE_BLOB);
1225     EXPORT_BLOB(BCRYPT_DH_PUBLIC_BLOB);
1226     EXPORT_BLOB(BCRYPT_DSA_PRIVATE_BLOB);
1227     EXPORT_BLOB(BCRYPT_DSA_PUBLIC_BLOB);
1228     EXPORT_BLOB(BCRYPT_ECCPRIVATE_BLOB);
1229     EXPORT_BLOB(BCRYPT_ECCPUBLIC_BLOB);
1230     EXPORT_BLOB(BCRYPT_PUBLIC_KEY_BLOB);
1231     EXPORT_BLOB(BCRYPT_PRIVATE_KEY_BLOB);
1232     EXPORT_BLOB(BCRYPT_RSAFULLPRIVATE_BLOB);
1233     EXPORT_BLOB(BCRYPT_RSAPRIVATE_BLOB);
1234     EXPORT_BLOB(BCRYPT_RSAPUBLIC_BLOB);
1235     EXPORT_BLOB(LEGACY_DH_PRIVATE_BLOB);
1236     EXPORT_BLOB(LEGACY_DH_PUBLIC_BLOB);
1237     EXPORT_BLOB(LEGACY_DSA_PRIVATE_BLOB);
1238     EXPORT_BLOB(LEGACY_DSA_PUBLIC_BLOB);
1239     EXPORT_BLOB(LEGACY_RSAPRIVATE_BLOB);
1240     EXPORT_BLOB(LEGACY_RSAPUBLIC_BLOB);
1241     // Support starts from Windows 8 and Windows Server 2012
1242     //EXPORT_BLOB(NCRYPT_CIPHER_KEY_BLOB);
1243     EXPORT_BLOB(NCRYPT_OPAQUETRANSPORT_BLOB);
1244     EXPORT_BLOB(NCRYPT_PKCS7_ENVELOPE_BLOB);
1245     //EXPORT_BLOB(NCRYPTBUFFER_CERT_BLOB);
1246     //EXPORT_BLOB(NCRYPT_PKCS8_PRIVATE_KEY_BLOB);
1247     BCryptBuffer bb;
1248     bb.BufferType = NCRYPTBUFFER_PKCS_SECRET;
1249     bb.cbBuffer = 18;
1250     bb.pvBuffer = L"changeit";
1251     BCryptBufferDesc bbd;
1252     bbd.ulVersion = 0;
1253     bbd.cBuffers = 1;
1254     bbd.pBuffers = &bb;
1255     if(::NCryptExportKey(hKey, NULL, NCRYPT_PKCS8_PRIVATE_KEY_BLOB, NULL,
1256             (PBYTE)buffer, 8192, &len, NCRYPT_SILENT_FLAG) == ERROR_SUCCESS) {
1257         sprintf(header, "NCRYPT_PKCS8_PRIVATE_KEY_BLOB %ls", NCRYPT_PKCS8_PRIVATE_KEY_BLOB);
1258         dump(header, buffer, len);
1259     }
1260     // Support starts from Windows 8 and Windows Server 2012
1261     //EXPORT_BLOB(NCRYPT_PROTECTED_KEY_BLOB);
1262 }
1263 
1264 /*
1265  * Class:     sun_security_mscapi_CKeyPairGenerator_RSA
1266  * Method:    generateCKeyPair
1267  * Signature: (Ljava/lang/String;ILjava/lang/String;)Lsun/security/mscapi/CKeyPair;
1268  */
Java_sun_security_mscapi_CKeyPairGenerator_00024RSA_generateCKeyPair(JNIEnv * env,jclass clazz,jstring alg,jint keySize,jstring keyContainerName)1269 JNIEXPORT jobject JNICALL Java_sun_security_mscapi_CKeyPairGenerator_00024RSA_generateCKeyPair
1270   (JNIEnv *env, jclass clazz, jstring alg, jint keySize, jstring keyContainerName)
1271 {
1272     HCRYPTPROV hCryptProv = NULL;
1273     HCRYPTKEY hKeyPair;
1274     DWORD dwFlags = (keySize << 16) | CRYPT_EXPORTABLE;
1275     jobject keypair = NULL;
1276     const char* pszKeyContainerName = NULL; // UUID
1277 
1278     __try
1279     {
1280         if ((pszKeyContainerName =
1281             env->GetStringUTFChars(keyContainerName, NULL)) == NULL) {
1282             __leave;
1283         }
1284 
1285         // Acquire a CSP context (create a new key container).
1286         // Prefer a PROV_RSA_AES CSP, when available, due to its support
1287         // for SHA-2-based signatures.
1288         if (::CryptAcquireContext( //deprecated
1289             &hCryptProv,
1290             pszKeyContainerName,
1291             NULL,
1292             PROV_RSA_AES,
1293             CRYPT_NEWKEYSET) == FALSE)
1294         {
1295             // Failover to using the default CSP (PROV_RSA_FULL)
1296 
1297             if (::CryptAcquireContext( //deprecated
1298                 &hCryptProv,
1299                 pszKeyContainerName,
1300                 NULL,
1301                 PROV_RSA_FULL,
1302                 CRYPT_NEWKEYSET) == FALSE)
1303             {
1304                 ThrowException(env, KEY_EXCEPTION, GetLastError());
1305                 __leave;
1306             }
1307         }
1308 
1309         // Generate an keypair
1310         if(::CryptGenKey( //deprecated
1311            hCryptProv,
1312            AT_KEYEXCHANGE,
1313            dwFlags,
1314            &hKeyPair) == FALSE)
1315         {
1316             ThrowException(env, KEY_EXCEPTION, GetLastError());
1317             __leave;
1318         }
1319 
1320         // Get the method ID for the CKeyPair constructor
1321         jclass clazzCKeyPair =
1322             env->FindClass("sun/security/mscapi/CKeyPair");
1323         if (clazzCKeyPair == NULL) {
1324             __leave;
1325         }
1326 
1327         jmethodID mNewCKeyPair =
1328             env->GetMethodID(clazzCKeyPair, "<init>", "(Ljava/lang/String;JJI)V");
1329         if (mNewCKeyPair == NULL) {
1330             __leave;
1331         }
1332 
1333         // Create a new keypair
1334         keypair = env->NewObject(clazzCKeyPair, mNewCKeyPair,
1335             alg, (jlong) hCryptProv, (jlong) hKeyPair, keySize);
1336 
1337     }
1338     __finally
1339     {
1340         //--------------------------------------------------------------------
1341         // Clean up.
1342 
1343         if (pszKeyContainerName)
1344             env->ReleaseStringUTFChars(keyContainerName, pszKeyContainerName);
1345     }
1346 
1347     return keypair;
1348 }
1349 
1350 /*
1351  * Class:     sun_security_mscapi_CKey
1352  * Method:    getContainerName
1353  * Signature: (J)Ljava/lang/String;
1354  */
Java_sun_security_mscapi_CKey_getContainerName(JNIEnv * env,jclass jclazz,jlong hCryptProv)1355 JNIEXPORT jstring JNICALL Java_sun_security_mscapi_CKey_getContainerName
1356   (JNIEnv *env, jclass jclazz, jlong hCryptProv)
1357 {
1358     DWORD cbData = 256;
1359     BYTE pbData[256];
1360     pbData[0] = '\0';
1361 
1362     ::CryptGetProvParam( //deprecated
1363         (HCRYPTPROV)hCryptProv,
1364         PP_CONTAINER,
1365         (BYTE *)pbData,
1366         &cbData,
1367         0);
1368 
1369     return env->NewStringUTF((const char*)pbData);
1370 }
1371 
1372 /*
1373  * Class:     sun_security_mscapi_CKey
1374  * Method:    getKeyType
1375  * Signature: (J)Ljava/lang/String;
1376  */
Java_sun_security_mscapi_CKey_getKeyType(JNIEnv * env,jclass jclazz,jlong hCryptKey)1377 JNIEXPORT jstring JNICALL Java_sun_security_mscapi_CKey_getKeyType
1378   (JNIEnv *env, jclass jclazz, jlong hCryptKey)
1379 {
1380     ALG_ID dwAlgId;
1381     DWORD dwAlgIdLen = sizeof(ALG_ID);
1382 
1383     if (::CryptGetKeyParam((HCRYPTKEY) hCryptKey, KP_ALGID, (BYTE*)&dwAlgId, &dwAlgIdLen, 0)) { //deprecated
1384 
1385         if (CALG_RSA_SIGN == dwAlgId) {
1386             return env->NewStringUTF("Signature");
1387 
1388         } else if (CALG_RSA_KEYX == dwAlgId) {
1389             return env->NewStringUTF("Exchange");
1390 
1391         } else {
1392             char buffer[64];
1393             if (sprintf(buffer, "%lu", dwAlgId)) {
1394                 return env->NewStringUTF(buffer);
1395             }
1396         }
1397     }
1398 
1399     return env->NewStringUTF("<Unknown>");
1400 }
1401 
1402 /*
1403  * Class:     sun_security_mscapi_CKeyStore
1404  * Method:    storeCertificate
1405  * Signature: (Ljava/lang/String;Ljava/lang/String;[BIJJ)V
1406  */
Java_sun_security_mscapi_CKeyStore_storeCertificate(JNIEnv * env,jobject obj,jstring jCertStoreName,jstring jCertAliasName,jbyteArray jCertEncoding,jint jCertEncodingSize,jlong hCryptProv,jlong hCryptKey)1407 JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_storeCertificate
1408   (JNIEnv *env, jobject obj, jstring jCertStoreName, jstring jCertAliasName,
1409         jbyteArray jCertEncoding, jint jCertEncodingSize, jlong hCryptProv,
1410         jlong hCryptKey)
1411 {
1412     const char* pszCertStoreName = NULL;
1413     HCERTSTORE hCertStore = NULL;
1414     PCCERT_CONTEXT pCertContext = NULL;
1415     PWCHAR pszCertAliasName = NULL;
1416     jbyte* pbCertEncoding = NULL;
1417     const jchar* jCertAliasChars = NULL;
1418     const char* pszContainerName = NULL;
1419     const char* pszProviderName = NULL;
1420     WCHAR * pwszContainerName = NULL;
1421     WCHAR * pwszProviderName = NULL;
1422 
1423     __try
1424     {
1425         // Open a system certificate store.
1426         if ((pszCertStoreName = env->GetStringUTFChars(jCertStoreName, NULL))
1427             == NULL) {
1428             __leave;
1429         }
1430         if ((hCertStore = ::CertOpenSystemStore(NULL, pszCertStoreName)) == NULL) {
1431             ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1432             __leave;
1433         }
1434 
1435         // Copy encoding from Java to native buffer
1436         pbCertEncoding = new (env) jbyte[jCertEncodingSize];
1437         if (pbCertEncoding == NULL) {
1438             __leave;
1439         }
1440         env->GetByteArrayRegion(jCertEncoding, 0, jCertEncodingSize, pbCertEncoding);
1441 
1442         // Create a certificate context from the encoded cert
1443         if (!(pCertContext = ::CertCreateCertificateContext(X509_ASN_ENCODING,
1444             (BYTE*) pbCertEncoding, jCertEncodingSize))) {
1445 
1446             ThrowException(env, CERTIFICATE_PARSING_EXCEPTION, GetLastError());
1447             __leave;
1448         }
1449 
1450         // Set the certificate's friendly name
1451         int size = env->GetStringLength(jCertAliasName);
1452         pszCertAliasName = new (env) WCHAR[size + 1];
1453         if (pszCertAliasName == NULL) {
1454             __leave;
1455         }
1456 
1457         jCertAliasChars = env->GetStringChars(jCertAliasName, NULL);
1458         if (jCertAliasChars == NULL) {
1459             __leave;
1460         }
1461         memcpy(pszCertAliasName, jCertAliasChars, size * sizeof(WCHAR));
1462         pszCertAliasName[size] = 0; // append the string terminator
1463 
1464         CRYPT_DATA_BLOB friendlyName = {
1465             sizeof(WCHAR) * (size + 1),
1466             (BYTE *) pszCertAliasName
1467         };
1468 
1469         env->ReleaseStringChars(jCertAliasName, jCertAliasChars);
1470 
1471         if (! ::CertSetCertificateContextProperty(pCertContext,
1472             CERT_FRIENDLY_NAME_PROP_ID, 0, &friendlyName)) {
1473 
1474             ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1475             __leave;
1476         }
1477 
1478         // Attach the certificate's private key (if supplied)
1479         if (hCryptProv != 0 && hCryptKey != 0) {
1480 
1481             CRYPT_KEY_PROV_INFO keyProviderInfo;
1482             DWORD dwDataLen;
1483 
1484             // Get the name of the key container
1485             if (! ::CryptGetProvParam( //deprecated
1486                 (HCRYPTPROV) hCryptProv,
1487                 PP_CONTAINER,
1488                 NULL,
1489                 &dwDataLen,
1490                 0)) {
1491 
1492                 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1493                 __leave;
1494             }
1495 
1496             pszContainerName = new (env) char[dwDataLen];
1497             if (pszContainerName == NULL) {
1498                 __leave;
1499             }
1500 
1501             if (! ::CryptGetProvParam( //deprecated
1502                 (HCRYPTPROV) hCryptProv,
1503                 PP_CONTAINER,
1504                 (BYTE *) pszContainerName,
1505                 &dwDataLen,
1506                 0)) {
1507 
1508                 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1509                 __leave;
1510             }
1511 
1512             // Convert to a wide char string
1513             pwszContainerName = new (env) WCHAR[dwDataLen];
1514             if (pwszContainerName == NULL) {
1515                 __leave;
1516             }
1517 
1518             if (mbstowcs(pwszContainerName, pszContainerName, dwDataLen) == 0) {
1519                 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1520                 __leave;
1521             }
1522 
1523             // Set the name of the key container
1524             keyProviderInfo.pwszContainerName = pwszContainerName;
1525 
1526 
1527             // Get the name of the provider
1528             if (! ::CryptGetProvParam( //deprecated
1529                 (HCRYPTPROV) hCryptProv,
1530                 PP_NAME,
1531                 NULL,
1532                 &dwDataLen,
1533                 0)) {
1534 
1535                 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1536                 __leave;
1537             }
1538 
1539             pszProviderName = new (env) char[dwDataLen];
1540             if (pszProviderName == NULL) {
1541                 __leave;
1542             }
1543 
1544             if (! ::CryptGetProvParam( //deprecated
1545                 (HCRYPTPROV) hCryptProv,
1546                 PP_NAME,
1547                 (BYTE *) pszProviderName,
1548                 &dwDataLen,
1549                 0)) {
1550 
1551                 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1552                 __leave;
1553             }
1554 
1555             // Convert to a wide char string
1556             pwszProviderName = new (env) WCHAR[dwDataLen];
1557             if (pwszProviderName == NULL) {
1558                 __leave;
1559             }
1560 
1561             if (mbstowcs(pwszProviderName, pszProviderName, dwDataLen) == 0) {
1562                 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1563                 __leave;
1564             }
1565 
1566             // Set the name of the provider
1567             keyProviderInfo.pwszProvName = pwszProviderName;
1568 
1569             // Get and set the type of the provider
1570             if (! ::CryptGetProvParam( //deprecated
1571                 (HCRYPTPROV) hCryptProv,
1572                 PP_PROVTYPE,
1573                 (LPBYTE) &keyProviderInfo.dwProvType,
1574                 &dwDataLen,
1575                 0)) {
1576 
1577                 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1578                 __leave;
1579             }
1580 
1581             // Set no provider flags
1582             keyProviderInfo.dwFlags = 0;
1583 
1584             // Set no provider parameters
1585             keyProviderInfo.cProvParam = 0;
1586             keyProviderInfo.rgProvParam = NULL;
1587 
1588             // Get the key's algorithm ID
1589             if (! ::CryptGetKeyParam( //deprecated
1590                 (HCRYPTKEY) hCryptKey,
1591                 KP_ALGID,
1592                 (LPBYTE) &keyProviderInfo.dwKeySpec,
1593                 &dwDataLen,
1594                 0)) {
1595 
1596                 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1597                 __leave;
1598             }
1599             // Set the key spec (using the algorithm ID).
1600             switch (keyProviderInfo.dwKeySpec) {
1601             case CALG_RSA_KEYX:
1602             case CALG_DH_SF:
1603                 keyProviderInfo.dwKeySpec = AT_KEYEXCHANGE;
1604                 break;
1605 
1606             case CALG_RSA_SIGN:
1607             case CALG_DSS_SIGN:
1608                 keyProviderInfo.dwKeySpec = AT_SIGNATURE;
1609                 break;
1610 
1611             default:
1612                 ThrowException(env, KEYSTORE_EXCEPTION, NTE_BAD_ALGID);
1613                 __leave;
1614             }
1615 
1616             if (! ::CertSetCertificateContextProperty(pCertContext,
1617                 CERT_KEY_PROV_INFO_PROP_ID, 0, &keyProviderInfo)) {
1618 
1619                 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1620                 __leave;
1621             }
1622         }
1623 
1624         // Import encoded certificate
1625         if (!::CertAddCertificateContextToStore(hCertStore, pCertContext,
1626             CERT_STORE_ADD_REPLACE_EXISTING, NULL))
1627         {
1628             ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1629             __leave;
1630         }
1631 
1632     }
1633     __finally
1634     {
1635         //--------------------------------------------------------------------
1636         // Clean up.
1637 
1638         if (hCertStore)
1639             ::CertCloseStore(hCertStore, 0);
1640 
1641         if (pszCertStoreName)
1642             env->ReleaseStringUTFChars(jCertStoreName, pszCertStoreName);
1643 
1644         if (pbCertEncoding)
1645             delete [] pbCertEncoding;
1646 
1647         if (pszCertAliasName)
1648             delete [] pszCertAliasName;
1649 
1650         if (pszContainerName)
1651             delete [] pszContainerName;
1652 
1653         if (pwszContainerName)
1654             delete [] pwszContainerName;
1655 
1656         if (pszProviderName)
1657             delete [] pszProviderName;
1658 
1659         if (pwszProviderName)
1660             delete [] pwszProviderName;
1661 
1662         if (pCertContext)
1663             ::CertFreeCertificateContext(pCertContext);
1664     }
1665 }
1666 
1667 /*
1668  * Class:     sun_security_mscapi_CKeyStore
1669  * Method:    removeCertificate
1670  * Signature: (Ljava/lang/String;Ljava/lang/String;[BI)V
1671  */
Java_sun_security_mscapi_CKeyStore_removeCertificate(JNIEnv * env,jobject obj,jstring jCertStoreName,jstring jCertAliasName,jbyteArray jCertEncoding,jint jCertEncodingSize)1672 JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_removeCertificate
1673   (JNIEnv *env, jobject obj, jstring jCertStoreName, jstring jCertAliasName,
1674   jbyteArray jCertEncoding, jint jCertEncodingSize) {
1675 
1676     const char* pszCertStoreName = NULL;
1677     const char* pszCertAliasName = NULL;
1678     HCERTSTORE hCertStore = NULL;
1679     PCCERT_CONTEXT pCertContext = NULL;
1680     PCCERT_CONTEXT pTBDCertContext = NULL;
1681     jbyte* pbCertEncoding = NULL;
1682     DWORD cchNameString = 0;
1683     char* pszNameString = NULL; // certificate's friendly name
1684     BOOL bDeleteAttempted = FALSE;
1685 
1686     __try
1687     {
1688         // Open a system certificate store.
1689         if ((pszCertStoreName = env->GetStringUTFChars(jCertStoreName, NULL))
1690             == NULL) {
1691             __leave;
1692         }
1693         if ((hCertStore = ::CertOpenSystemStore(NULL, pszCertStoreName)) == NULL) {
1694             ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1695             __leave;
1696         }
1697 
1698         // Copy encoding from Java to native buffer
1699         pbCertEncoding = new (env) jbyte[jCertEncodingSize];
1700         if (pbCertEncoding == NULL) {
1701             __leave;
1702         }
1703         env->GetByteArrayRegion(jCertEncoding, 0, jCertEncodingSize, pbCertEncoding);
1704 
1705         // Create a certificate context from the encoded cert
1706         if (!(pCertContext = ::CertCreateCertificateContext(X509_ASN_ENCODING,
1707             (BYTE*) pbCertEncoding, jCertEncodingSize))) {
1708 
1709             ThrowException(env, CERTIFICATE_PARSING_EXCEPTION, GetLastError());
1710             __leave;
1711         }
1712 
1713         // Find the certificate to be deleted
1714         if (!(pTBDCertContext = ::CertFindCertificateInStore(hCertStore,
1715             X509_ASN_ENCODING, 0, CERT_FIND_EXISTING, pCertContext, NULL))) {
1716 
1717             ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1718             __leave;
1719         }
1720 
1721         // Check that its friendly name matches the supplied alias
1722         if ((cchNameString = ::CertGetNameString(pTBDCertContext,
1723                 CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, NULL, 0)) > 1) {
1724 
1725             pszNameString = new (env) char[cchNameString];
1726             if (pszNameString == NULL) {
1727                 __leave;
1728             }
1729 
1730             ::CertGetNameString(pTBDCertContext,
1731                 CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, pszNameString,
1732                 cchNameString);
1733 
1734             // Compare the certificate's friendly name with supplied alias name
1735             if ((pszCertAliasName = env->GetStringUTFChars(jCertAliasName, NULL))
1736                 == NULL) {
1737                 __leave;
1738             }
1739             if (strcmp(pszCertAliasName, pszNameString) == 0) {
1740 
1741                 // Only delete the certificate if the alias names matches
1742                 if (! ::CertDeleteCertificateFromStore(pTBDCertContext)) {
1743 
1744                     // pTBDCertContext is always freed by the
1745                     //  CertDeleteCertificateFromStore method
1746                     bDeleteAttempted = TRUE;
1747 
1748                     ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1749                     __leave;
1750                 }
1751             }
1752         }
1753 
1754     }
1755     __finally
1756     {
1757         //--------------------------------------------------------------------
1758         // Clean up.
1759 
1760         if (hCertStore)
1761             ::CertCloseStore(hCertStore, 0);
1762 
1763         if (pszCertStoreName)
1764             env->ReleaseStringUTFChars(jCertStoreName, pszCertStoreName);
1765 
1766         if (pszCertAliasName)
1767             env->ReleaseStringUTFChars(jCertAliasName, pszCertAliasName);
1768 
1769         if (pbCertEncoding)
1770             delete [] pbCertEncoding;
1771 
1772         if (pszNameString)
1773             delete [] pszNameString;
1774 
1775         if (pCertContext)
1776             ::CertFreeCertificateContext(pCertContext);
1777 
1778         if (bDeleteAttempted && pTBDCertContext)
1779             ::CertFreeCertificateContext(pTBDCertContext);
1780     }
1781 }
1782 
1783 /*
1784  * Class:     sun_security_mscapi_CKeyStore
1785  * Method:    destroyKeyContainer
1786  * Signature: (Ljava/lang/String;)V
1787  */
Java_sun_security_mscapi_CKeyStore_destroyKeyContainer(JNIEnv * env,jobject clazz,jstring keyContainerName)1788 JNIEXPORT void JNICALL Java_sun_security_mscapi_CKeyStore_destroyKeyContainer
1789   (JNIEnv *env, jobject clazz, jstring keyContainerName)
1790 {
1791     HCRYPTPROV hCryptProv = NULL;
1792     const char* pszKeyContainerName = NULL;
1793 
1794     __try
1795     {
1796         if ((pszKeyContainerName =
1797             env->GetStringUTFChars(keyContainerName, NULL)) == NULL) {
1798             __leave;
1799         }
1800 
1801         // Destroying the default key container is not permitted
1802         // (because it may contain more one keypair).
1803         if (pszKeyContainerName == NULL) {
1804 
1805             ThrowException(env, KEYSTORE_EXCEPTION, NTE_BAD_KEYSET_PARAM);
1806             __leave;
1807         }
1808 
1809         // Acquire a CSP context (to the key container).
1810         if (::CryptAcquireContext( //deprecated
1811             &hCryptProv,
1812             pszKeyContainerName,
1813             NULL,
1814             PROV_RSA_FULL,
1815             CRYPT_DELETEKEYSET) == FALSE)
1816         {
1817             ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
1818             __leave;
1819         }
1820 
1821     }
1822     __finally
1823     {
1824         //--------------------------------------------------------------------
1825         // Clean up.
1826 
1827         if (pszKeyContainerName)
1828             env->ReleaseStringUTFChars(keyContainerName, pszKeyContainerName);
1829     }
1830 }
1831 
1832 /*
1833  * Class:     sun_security_mscapi_CRSACipher
1834  * Method:    encryptDecrypt
1835  * Signature: ([BIJZ)[B
1836  */
Java_sun_security_mscapi_CRSACipher_encryptDecrypt(JNIEnv * env,jclass clazz,jbyteArray jData,jint jDataSize,jlong hKey,jboolean doEncrypt)1837 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CRSACipher_encryptDecrypt
1838   (JNIEnv *env, jclass clazz, jbyteArray jData, jint jDataSize, jlong hKey,
1839    jboolean doEncrypt)
1840 {
1841     jbyteArray result = NULL;
1842     jbyte* pData = NULL;
1843     DWORD dwDataLen = jDataSize;
1844     DWORD dwBufLen = env->GetArrayLength(jData);
1845     DWORD i;
1846     BYTE tmp;
1847 
1848     __try
1849     {
1850         // Copy data from Java buffer to native buffer
1851         pData = new (env) jbyte[dwBufLen];
1852         if (pData == NULL) {
1853             __leave;
1854         }
1855         env->GetByteArrayRegion(jData, 0, dwBufLen, pData);
1856 
1857         if (doEncrypt == JNI_TRUE) {
1858             // encrypt
1859             if (! ::CryptEncrypt((HCRYPTKEY) hKey, 0, TRUE, 0, (BYTE *)pData, //deprecated
1860                 &dwDataLen, dwBufLen)) {
1861 
1862                 ThrowException(env, KEY_EXCEPTION, GetLastError());
1863                 __leave;
1864             }
1865             dwBufLen = dwDataLen;
1866 
1867             // convert from little-endian
1868             for (i = 0; i < dwBufLen / 2; i++) {
1869                 tmp = pData[i];
1870                 pData[i] = pData[dwBufLen - i -1];
1871                 pData[dwBufLen - i - 1] = tmp;
1872             }
1873         } else {
1874             // convert to little-endian
1875             for (i = 0; i < dwBufLen / 2; i++) {
1876                 tmp = pData[i];
1877                 pData[i] = pData[dwBufLen - i -1];
1878                 pData[dwBufLen - i - 1] = tmp;
1879             }
1880 
1881             // decrypt
1882             if (! ::CryptDecrypt((HCRYPTKEY) hKey, 0, TRUE, 0, (BYTE *)pData, //deprecated
1883                 &dwBufLen)) {
1884 
1885                 ThrowException(env, KEY_EXCEPTION, GetLastError());
1886                 __leave;
1887             }
1888         }
1889 
1890         // Create new byte array
1891         if ((result = env->NewByteArray(dwBufLen)) == NULL) {
1892             __leave;
1893         }
1894 
1895         // Copy data from native buffer to Java buffer
1896         env->SetByteArrayRegion(result, 0, dwBufLen, (jbyte*) pData);
1897     }
1898     __finally
1899     {
1900         if (pData)
1901             delete [] pData;
1902     }
1903 
1904     return result;
1905 }
1906 
1907 /*
1908  * Class:     sun_security_mscapi_CPublicKey
1909  * Method:    getPublicKeyBlob
1910  * Signature: (JJ)[B
1911  */
Java_sun_security_mscapi_CPublicKey_getPublicKeyBlob(JNIEnv * env,jobject clazz,jlong hCryptProv,jlong hCryptKey)1912 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CPublicKey_getPublicKeyBlob
1913     (JNIEnv *env, jobject clazz, jlong hCryptProv, jlong hCryptKey) {
1914 
1915     jbyteArray blob = NULL;
1916     DWORD dwBlobLen;
1917     BYTE* pbKeyBlob = NULL;
1918 
1919     __try
1920     {
1921 
1922         // Determine the size of the blob
1923         if (hCryptKey == 0) {
1924             SS_CHECK(::NCryptExportKey(
1925                 (NCRYPT_KEY_HANDLE)hCryptProv, NULL, BCRYPT_ECCPUBLIC_BLOB,
1926                 NULL, NULL, 0, &dwBlobLen, NCRYPT_SILENT_FLAG));
1927         } else {
1928             if (! ::CryptExportKey((HCRYPTKEY) hCryptKey, 0, PUBLICKEYBLOB, 0, NULL, //deprecated
1929                 &dwBlobLen)) {
1930 
1931                 ThrowException(env, KEY_EXCEPTION, GetLastError());
1932                 __leave;
1933             }
1934         }
1935 
1936         pbKeyBlob = new (env) BYTE[dwBlobLen];
1937         if (pbKeyBlob == NULL) {
1938             __leave;
1939         }
1940 
1941         // Generate key blob
1942         if (hCryptKey == 0) {
1943             SS_CHECK(::NCryptExportKey(
1944                 (NCRYPT_KEY_HANDLE)hCryptProv, NULL, BCRYPT_ECCPUBLIC_BLOB,
1945                 NULL, pbKeyBlob, dwBlobLen, &dwBlobLen, NCRYPT_SILENT_FLAG));
1946         } else {
1947             if (! ::CryptExportKey((HCRYPTKEY) hCryptKey, 0, PUBLICKEYBLOB, 0, //deprecated
1948                 pbKeyBlob, &dwBlobLen)) {
1949 
1950                 ThrowException(env, KEY_EXCEPTION, GetLastError());
1951                 __leave;
1952             }
1953         }
1954 
1955         // Create new byte array
1956         if ((blob = env->NewByteArray(dwBlobLen)) == NULL) {
1957             __leave;
1958         }
1959 
1960         // Copy data from native buffer to Java buffer
1961         env->SetByteArrayRegion(blob, 0, dwBlobLen, (jbyte*) pbKeyBlob);
1962     }
1963     __finally
1964     {
1965         if (pbKeyBlob)
1966             delete [] pbKeyBlob;
1967     }
1968 
1969     return blob;
1970 }
1971 
1972 /*
1973  * Class:     sun_security_mscapi_CPublicKey_CRSAPublicKey
1974  * Method:    getExponent
1975  * Signature: ([B)[B
1976  */
Java_sun_security_mscapi_CPublicKey_00024CRSAPublicKey_getExponent(JNIEnv * env,jobject clazz,jbyteArray jKeyBlob)1977 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CPublicKey_00024CRSAPublicKey_getExponent
1978     (JNIEnv *env, jobject clazz, jbyteArray jKeyBlob) {
1979 
1980     jbyteArray exponent = NULL;
1981     jbyte*     exponentBytes = NULL;
1982     jbyte*     keyBlob = NULL;
1983 
1984     __try {
1985 
1986         jsize length = env->GetArrayLength(jKeyBlob);
1987         jsize headerLength = sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY);
1988 
1989         if (length < headerLength) {
1990             ThrowExceptionWithMessage(env, KEY_EXCEPTION, "Invalid BLOB");
1991             __leave;
1992         }
1993 
1994         if ((keyBlob = env->GetByteArrayElements(jKeyBlob, 0)) == NULL) {
1995             __leave;
1996         }
1997 
1998         PUBLICKEYSTRUC* pPublicKeyStruc = (PUBLICKEYSTRUC *) keyBlob;
1999 
2000         // Check BLOB type
2001         if (pPublicKeyStruc->bType != PUBLICKEYBLOB) {
2002             ThrowException(env, KEY_EXCEPTION, NTE_BAD_TYPE);
2003             __leave;
2004         }
2005 
2006         RSAPUBKEY* pRsaPubKey =
2007             (RSAPUBKEY *) (keyBlob + sizeof(PUBLICKEYSTRUC));
2008 
2009         int len = sizeof(pRsaPubKey->pubexp);
2010         exponentBytes = new (env) jbyte[len];
2011         if (exponentBytes == NULL) {
2012             __leave;
2013         }
2014 
2015         // convert from little-endian while copying from blob
2016         for (int i = 0, j = len - 1; i < len; i++, j--) {
2017             exponentBytes[i] = ((BYTE*) &pRsaPubKey->pubexp)[j];
2018         }
2019 
2020         if ((exponent = env->NewByteArray(len)) == NULL) {
2021             __leave;
2022         }
2023         env->SetByteArrayRegion(exponent, 0, len, exponentBytes);
2024     }
2025     __finally
2026     {
2027         if (keyBlob)
2028             env->ReleaseByteArrayElements(jKeyBlob, keyBlob, JNI_ABORT);
2029 
2030         if (exponentBytes)
2031             delete [] exponentBytes;
2032     }
2033 
2034     return exponent;
2035 }
2036 
2037 /*
2038  * Class:     sun_security_mscapi_CPublicKey_CRSAPublicKey
2039  * Method:    getModulus
2040  * Signature: ([B)[B
2041  */
Java_sun_security_mscapi_CPublicKey_00024CRSAPublicKey_getModulus(JNIEnv * env,jobject clazz,jbyteArray jKeyBlob)2042 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CPublicKey_00024CRSAPublicKey_getModulus
2043     (JNIEnv *env, jobject clazz, jbyteArray jKeyBlob) {
2044 
2045     jbyteArray modulus = NULL;
2046     jbyte*     modulusBytes = NULL;
2047     jbyte*     keyBlob = NULL;
2048 
2049     __try {
2050 
2051         jsize length = env->GetArrayLength(jKeyBlob);
2052         jsize headerLength = sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY);
2053 
2054         if (length < headerLength) {
2055             ThrowExceptionWithMessage(env, KEY_EXCEPTION, "Invalid BLOB");
2056             __leave;
2057         }
2058 
2059         if ((keyBlob = env->GetByteArrayElements(jKeyBlob, 0)) == NULL) {
2060             __leave;
2061         }
2062 
2063         PUBLICKEYSTRUC* pPublicKeyStruc = (PUBLICKEYSTRUC *) keyBlob;
2064 
2065         // Check BLOB type
2066         if (pPublicKeyStruc->bType != PUBLICKEYBLOB) {
2067             ThrowException(env, KEY_EXCEPTION, NTE_BAD_TYPE);
2068             __leave;
2069         }
2070 
2071         RSAPUBKEY* pRsaPubKey =
2072             (RSAPUBKEY *) (keyBlob + sizeof(PUBLICKEYSTRUC));
2073 
2074         int len = pRsaPubKey->bitlen / 8;
2075         if (len < 0 || len > length - headerLength) {
2076             ThrowExceptionWithMessage(env, KEY_EXCEPTION, "Invalid key length");
2077             __leave;
2078         }
2079 
2080         modulusBytes = new (env) jbyte[len];
2081         if (modulusBytes == NULL) {
2082             __leave;
2083         }
2084         BYTE * pbModulus = (BYTE *) (keyBlob + headerLength);
2085 
2086         // convert from little-endian while copying from blob
2087         for (int i = 0, j = len - 1; i < len; i++, j--) {
2088             modulusBytes[i] = pbModulus[j];
2089         }
2090 
2091         if ((modulus = env->NewByteArray(len)) == NULL) {
2092             __leave;
2093         }
2094         env->SetByteArrayRegion(modulus, 0, len, modulusBytes);
2095     }
2096     __finally
2097     {
2098         if (keyBlob)
2099             env->ReleaseByteArrayElements(jKeyBlob, keyBlob, JNI_ABORT);
2100 
2101         if (modulusBytes)
2102             delete [] modulusBytes;
2103     }
2104 
2105     return modulus;
2106 }
2107 
2108 /*
2109  * Convert an array in big-endian byte order into little-endian byte order.
2110  */
convertToLittleEndian(JNIEnv * env,jbyteArray source,jbyte * destination,int destinationLength)2111 int convertToLittleEndian(JNIEnv *env, jbyteArray source, jbyte* destination,
2112         int destinationLength) {
2113 
2114     int result = -1;
2115     jbyte* sourceBytes = NULL;
2116 
2117     __try {
2118         int sourceLength = env->GetArrayLength(source);
2119 
2120         sourceBytes = env->GetByteArrayElements(source, 0);
2121         if (sourceBytes == NULL) {
2122             __leave;
2123         }
2124 
2125         int copyLen = sourceLength;
2126         if (sourceLength > destinationLength) {
2127             // source might include an extra sign byte
2128             if (sourceLength == destinationLength + 1 && sourceBytes[0] == 0) {
2129                 copyLen--;
2130             } else {
2131                 __leave;
2132             }
2133         }
2134 
2135         // Copy bytes from the end of the source array to the beginning of the
2136         // destination array (until the destination array is full).
2137         // This ensures that the sign byte from the source array will be excluded.
2138         for (int i = 0; i < copyLen; i++) {
2139             destination[i] = sourceBytes[sourceLength - 1 - i];
2140         }
2141         if (copyLen < destinationLength) {
2142             memset(destination + copyLen, 0, destinationLength - copyLen);
2143         }
2144         result = destinationLength;
2145     } __finally {
2146         // Clean up.
2147         if (sourceBytes) {
2148             env->ReleaseByteArrayElements(source, sourceBytes, JNI_ABORT);
2149         }
2150     }
2151 
2152     return result;
2153 }
2154 
2155 /*
2156  * The Microsoft Base Cryptographic Provider supports public-key BLOBs
2157  * that have the following format:
2158  *
2159  *     PUBLICKEYSTRUC publickeystruc;
2160  *     RSAPUBKEY rsapubkey;
2161  *     BYTE modulus[rsapubkey.bitlen/8];
2162  *
2163  * and private-key BLOBs that have the following format:
2164  *
2165  *     PUBLICKEYSTRUC publickeystruc;
2166  *     RSAPUBKEY rsapubkey;
2167  *     BYTE modulus[rsapubkey.bitlen/8];
2168  *     BYTE prime1[rsapubkey.bitlen/16];
2169  *     BYTE prime2[rsapubkey.bitlen/16];
2170  *     BYTE exponent1[rsapubkey.bitlen/16];
2171  *     BYTE exponent2[rsapubkey.bitlen/16];
2172  *     BYTE coefficient[rsapubkey.bitlen/16];
2173  *     BYTE privateExponent[rsapubkey.bitlen/8];
2174  *
2175  * This method generates such BLOBs from the key elements supplied.
2176  */
generateKeyBlob(JNIEnv * env,jint jKeyBitLength,jbyteArray jModulus,jbyteArray jPublicExponent,jbyteArray jPrivateExponent,jbyteArray jPrimeP,jbyteArray jPrimeQ,jbyteArray jExponentP,jbyteArray jExponentQ,jbyteArray jCrtCoefficient)2177 jbyteArray generateKeyBlob(
2178         JNIEnv *env,
2179         jint jKeyBitLength,
2180         jbyteArray jModulus,
2181         jbyteArray jPublicExponent,
2182         jbyteArray jPrivateExponent,
2183         jbyteArray jPrimeP,
2184         jbyteArray jPrimeQ,
2185         jbyteArray jExponentP,
2186         jbyteArray jExponentQ,
2187         jbyteArray jCrtCoefficient)
2188 {
2189     jsize jKeyByteLength = jKeyBitLength / 8;
2190     jsize jBlobLength;
2191     BOOL bGeneratePrivateKeyBlob;
2192 
2193     // Determine whether to generate a public-key or a private-key BLOB
2194     if (jPrivateExponent != NULL &&
2195         jPrimeP != NULL &&
2196         jPrimeQ != NULL &&
2197         jExponentP != NULL &&
2198         jExponentQ != NULL &&
2199         jCrtCoefficient != NULL) {
2200 
2201         bGeneratePrivateKeyBlob = TRUE;
2202         jBlobLength = sizeof(BLOBHEADER) +
2203                         sizeof(RSAPUBKEY) +
2204                         ((jKeyBitLength / 8) * 4) +
2205                         (jKeyBitLength / 16);
2206 
2207     } else {
2208         bGeneratePrivateKeyBlob = FALSE;
2209         jBlobLength = sizeof(BLOBHEADER) +
2210                         sizeof(RSAPUBKEY) +
2211                         (jKeyBitLength / 8);
2212     }
2213 
2214     jbyte* jBlobBytes = NULL;
2215     jbyte* jBlobElement;
2216     jbyteArray jBlob = NULL;
2217     jsize  jElementLength;
2218 
2219     __try {
2220         jBlobBytes = new (env) jbyte[jBlobLength];
2221         if (jBlobBytes == NULL) {
2222             __leave;
2223         }
2224 
2225         BLOBHEADER *pBlobHeader = (BLOBHEADER *) jBlobBytes;
2226         if (bGeneratePrivateKeyBlob) {
2227             pBlobHeader->bType = PRIVATEKEYBLOB;  // 0x07
2228         } else {
2229             pBlobHeader->bType = PUBLICKEYBLOB;   // 0x06
2230         }
2231         pBlobHeader->bVersion = CUR_BLOB_VERSION; // 0x02
2232         pBlobHeader->reserved = 0;                // 0x0000
2233         pBlobHeader->aiKeyAlg = CALG_RSA_KEYX;    // 0x0000a400
2234 
2235         RSAPUBKEY *pRsaPubKey =
2236             (RSAPUBKEY *) (jBlobBytes + sizeof(PUBLICKEYSTRUC));
2237         if (bGeneratePrivateKeyBlob) {
2238             pRsaPubKey->magic = 0x32415352;       // "RSA2"
2239         } else {
2240             pRsaPubKey->magic = 0x31415352;       // "RSA1"
2241         }
2242         pRsaPubKey->bitlen = jKeyBitLength;
2243         pRsaPubKey->pubexp = 0; // init
2244 
2245         // Sanity check
2246         jsize jPublicExponentLength = env->GetArrayLength(jPublicExponent);
2247         if (jPublicExponentLength > sizeof(pRsaPubKey->pubexp)) {
2248             ThrowException(env, INVALID_KEY_EXCEPTION, NTE_BAD_TYPE);
2249             __leave;
2250         }
2251         // The length argument must be the smaller of jPublicExponentLength
2252         // and sizeof(pRsaPubKey->pubkey)
2253         if ((jElementLength = convertToLittleEndian(env, jPublicExponent,
2254             (jbyte *) &(pRsaPubKey->pubexp), jPublicExponentLength)) < 0) {
2255             __leave;
2256         }
2257 
2258         // Modulus n
2259         jBlobElement =
2260             (jbyte *) (jBlobBytes + sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY));
2261         if ((jElementLength = convertToLittleEndian(env, jModulus, jBlobElement,
2262             jKeyByteLength)) < 0) {
2263             __leave;
2264         }
2265 
2266         if (bGeneratePrivateKeyBlob) {
2267             // Prime p
2268             jBlobElement += jElementLength;
2269             if ((jElementLength = convertToLittleEndian(env, jPrimeP,
2270                 jBlobElement, jKeyByteLength / 2)) < 0) {
2271                 __leave;
2272             }
2273 
2274             // Prime q
2275             jBlobElement += jElementLength;
2276             if ((jElementLength = convertToLittleEndian(env, jPrimeQ,
2277                 jBlobElement, jKeyByteLength / 2)) < 0) {
2278                 __leave;
2279             }
2280 
2281             // Prime exponent p
2282             jBlobElement += jElementLength;
2283             if ((jElementLength = convertToLittleEndian(env, jExponentP,
2284                 jBlobElement, jKeyByteLength / 2)) < 0) {
2285                 __leave;
2286             }
2287 
2288             // Prime exponent q
2289             jBlobElement += jElementLength;
2290             if ((jElementLength = convertToLittleEndian(env, jExponentQ,
2291                 jBlobElement, jKeyByteLength / 2)) < 0) {
2292                 __leave;
2293             }
2294 
2295             // CRT coefficient
2296             jBlobElement += jElementLength;
2297             if ((jElementLength = convertToLittleEndian(env, jCrtCoefficient,
2298                 jBlobElement, jKeyByteLength / 2)) < 0) {
2299                 __leave;
2300             }
2301 
2302             // Private exponent
2303             jBlobElement += jElementLength;
2304             if ((jElementLength = convertToLittleEndian(env, jPrivateExponent,
2305                 jBlobElement, jKeyByteLength)) < 0) {
2306                 __leave;
2307             }
2308         }
2309 
2310         if ((jBlob = env->NewByteArray(jBlobLength)) == NULL) {
2311             __leave;
2312         }
2313         env->SetByteArrayRegion(jBlob, 0, jBlobLength, jBlobBytes);
2314 
2315     }
2316     __finally
2317     {
2318         if (jBlobBytes)
2319             delete [] jBlobBytes;
2320     }
2321 
2322     return jBlob;
2323 }
2324 
2325 /*
2326  * Class:     sun_security_mscapi_CKeyStore
2327  * Method:    generateRSAPrivateKeyBlob
2328  * Signature: (I[B[B[B[B[B[B[B[B)[B
2329  */
Java_sun_security_mscapi_CKeyStore_generateRSAPrivateKeyBlob(JNIEnv * env,jobject clazz,jint jKeyBitLength,jbyteArray jModulus,jbyteArray jPublicExponent,jbyteArray jPrivateExponent,jbyteArray jPrimeP,jbyteArray jPrimeQ,jbyteArray jExponentP,jbyteArray jExponentQ,jbyteArray jCrtCoefficient)2330 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CKeyStore_generateRSAPrivateKeyBlob
2331     (JNIEnv *env, jobject clazz,
2332         jint jKeyBitLength,
2333         jbyteArray jModulus,
2334         jbyteArray jPublicExponent,
2335         jbyteArray jPrivateExponent,
2336         jbyteArray jPrimeP,
2337         jbyteArray jPrimeQ,
2338         jbyteArray jExponentP,
2339         jbyteArray jExponentQ,
2340         jbyteArray jCrtCoefficient)
2341 {
2342     return generateKeyBlob(env, jKeyBitLength, jModulus, jPublicExponent,
2343         jPrivateExponent, jPrimeP, jPrimeQ, jExponentP, jExponentQ,
2344         jCrtCoefficient);
2345 }
2346 
2347 /*
2348  * Class:     sun_security_mscapi_CSignature_RSA
2349  * Method:    generatePublicKeyBlob
2350  * Signature: (I[B[B)[B
2351  */
Java_sun_security_mscapi_CSignature_00024RSA_generatePublicKeyBlob(JNIEnv * env,jclass clazz,jint jKeyBitLength,jbyteArray jModulus,jbyteArray jPublicExponent)2352 JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_CSignature_00024RSA_generatePublicKeyBlob
2353     (JNIEnv *env, jclass clazz,
2354         jint jKeyBitLength,
2355         jbyteArray jModulus,
2356         jbyteArray jPublicExponent)
2357 {
2358     return generateKeyBlob(env, jKeyBitLength, jModulus, jPublicExponent,
2359         NULL, NULL, NULL, NULL, NULL, NULL);
2360 }
2361 
2362 /*
2363  * Class:     sun_security_mscapi_CKeyStore
2364  * Method:    storePrivateKey
2365  * Signature: (Ljava/lang/String;[BLjava/lang/String;I)Lsun/security/mscapi/CPrivateKey;
2366  */
Java_sun_security_mscapi_CKeyStore_storePrivateKey(JNIEnv * env,jobject clazz,jstring alg,jbyteArray keyBlob,jstring keyContainerName,jint keySize)2367 JNIEXPORT jobject JNICALL Java_sun_security_mscapi_CKeyStore_storePrivateKey
2368     (JNIEnv *env, jobject clazz, jstring alg, jbyteArray keyBlob,
2369      jstring keyContainerName, jint keySize)
2370 {
2371     HCRYPTPROV hCryptProv = NULL;
2372     HCRYPTKEY hKey = NULL;
2373     DWORD dwBlobLen;
2374     BYTE * pbKeyBlob = NULL;
2375     const char* pszKeyContainerName = NULL; // UUID
2376     jobject privateKey = NULL;
2377 
2378     __try
2379     {
2380         if ((pszKeyContainerName =
2381             env->GetStringUTFChars(keyContainerName, NULL)) == NULL) {
2382             __leave;
2383         }
2384         dwBlobLen = env->GetArrayLength(keyBlob);
2385         if ((pbKeyBlob = (BYTE *) env->GetByteArrayElements(keyBlob, 0))
2386             == NULL) {
2387             __leave;
2388         }
2389 
2390         // Acquire a CSP context (create a new key container).
2391         if (::CryptAcquireContext( //deprecated
2392             &hCryptProv,
2393             pszKeyContainerName,
2394             NULL,
2395             PROV_RSA_FULL,
2396             CRYPT_NEWKEYSET) == FALSE)
2397         {
2398             ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
2399             __leave;
2400         }
2401 
2402         // Import the private key
2403         if (::CryptImportKey( //deprecated
2404             hCryptProv,
2405             pbKeyBlob,
2406             dwBlobLen,
2407             0,
2408             CRYPT_EXPORTABLE,
2409             &hKey) == FALSE)
2410         {
2411             ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
2412             __leave;
2413         }
2414 
2415         // Get the method ID for the CPrivateKey constructor
2416         jclass clazzCPrivateKey =
2417             env->FindClass("sun/security/mscapi/CPrivateKey");
2418         if (clazzCPrivateKey == NULL) {
2419             __leave;
2420         }
2421 
2422         jmethodID mNewCPrivateKey =
2423             env->GetStaticMethodID(clazzCPrivateKey, "of",
2424             "(Ljava/lang/String;JJI)Lsun/security/mscapi/CPrivateKey;");
2425         if (mNewCPrivateKey == NULL) {
2426             __leave;
2427         }
2428 
2429         // Create a new private key
2430         privateKey = env->CallStaticObjectMethod(clazzCPrivateKey, mNewCPrivateKey,
2431             alg, (jlong) hCryptProv, (jlong) hKey, keySize);
2432 
2433     }
2434     __finally
2435     {
2436         //--------------------------------------------------------------------
2437         // Clean up.
2438 
2439         if (pszKeyContainerName)
2440             env->ReleaseStringUTFChars(keyContainerName, pszKeyContainerName);
2441 
2442         if (pbKeyBlob)
2443             env->ReleaseByteArrayElements(keyBlob, (jbyte *) pbKeyBlob,
2444                 JNI_ABORT);
2445     }
2446 
2447     return privateKey;
2448 }
2449 
2450 /*
2451  * Class:     sun_security_mscapi_CSignature
2452  * Method:    importECPublicKey
2453  * Signature: (Ljava/lang/String;[BI)Lsun/security/mscapi/CPublicKey;
2454  */
Java_sun_security_mscapi_CSignature_importECPublicKey(JNIEnv * env,jclass clazz,jstring alg,jbyteArray keyBlob,jint keySize)2455 JNIEXPORT jobject JNICALL Java_sun_security_mscapi_CSignature_importECPublicKey
2456     (JNIEnv *env, jclass clazz, jstring alg, jbyteArray keyBlob, jint keySize)
2457 {
2458     BCRYPT_ALG_HANDLE hSignAlg = NULL;
2459     NCRYPT_KEY_HANDLE       hTmpKey         = NULL;
2460     DWORD dwBlobLen;
2461     BYTE * pbKeyBlob = NULL;
2462     jobject publicKey = NULL;
2463 
2464     __try
2465     {
2466         dwBlobLen = env->GetArrayLength(keyBlob);
2467         if ((pbKeyBlob = (BYTE *) env->GetByteArrayElements(keyBlob, 0))
2468             == NULL) {
2469             __leave;
2470         }
2471         dump("NCryptImportKey", pbKeyBlob, dwBlobLen);
2472         NCRYPT_PROV_HANDLE hProv;
2473         SS_CHECK(NCryptOpenStorageProvider(
2474                 &hProv, L"Microsoft Software Key Storage Provider", 0 ));
2475         SS_CHECK(NCryptImportKey(
2476                                                     hProv,
2477                                                     NULL,
2478                                                     BCRYPT_ECCPUBLIC_BLOB,
2479                                                     NULL,
2480                                                     &hTmpKey,
2481                                                     pbKeyBlob,
2482                                                     dwBlobLen,
2483                                                     0));
2484         NCryptFreeObject( hProv );
2485         // Get the method ID for the CPublicKey constructor
2486         jclass clazzCPublicKey =
2487             env->FindClass("sun/security/mscapi/CPublicKey");
2488         if (clazzCPublicKey == NULL) {
2489             __leave;
2490         }
2491 
2492         jmethodID mNewCPublicKey =
2493             env->GetStaticMethodID(clazzCPublicKey, "of",
2494             "(Ljava/lang/String;JJI)Lsun/security/mscapi/CPublicKey;");
2495         if (mNewCPublicKey == NULL) {
2496             __leave;
2497         }
2498 
2499         // Create a new public key
2500         publicKey = env->CallStaticObjectMethod(clazzCPublicKey, mNewCPublicKey,
2501             alg, (jlong) hTmpKey, (jlong) 0, keySize);
2502     }
2503     __finally
2504     {
2505     }
2506 
2507     return publicKey;
2508 }
2509 
2510 /*
2511  * Class:     sun_security_mscapi_CSignature
2512  * Method:    importPublicKey
2513  * Signature: (Ljava/lang/String;[BI)Lsun/security/mscapi/CPublicKey;
2514  */
Java_sun_security_mscapi_CSignature_importPublicKey(JNIEnv * env,jclass clazz,jstring alg,jbyteArray keyBlob,jint keySize)2515 JNIEXPORT jobject JNICALL Java_sun_security_mscapi_CSignature_importPublicKey
2516     (JNIEnv *env, jclass clazz, jstring alg, jbyteArray keyBlob, jint keySize)
2517 {
2518     HCRYPTPROV hCryptProv = NULL;
2519     HCRYPTKEY hKey = NULL;
2520     DWORD dwBlobLen;
2521     BYTE * pbKeyBlob = NULL;
2522     jobject publicKey = NULL;
2523 
2524     __try
2525     {
2526         dwBlobLen = env->GetArrayLength(keyBlob);
2527         if ((pbKeyBlob = (BYTE *) env->GetByteArrayElements(keyBlob, 0))
2528             == NULL) {
2529             __leave;
2530         }
2531 
2532         // Acquire a CSP context (create a new key container).
2533         // Prefer a PROV_RSA_AES CSP, when available, due to its support
2534         // for SHA-2-based signatures.
2535         if (::CryptAcquireContext( //deprecated
2536             &hCryptProv,
2537             NULL,
2538             NULL,
2539             PROV_RSA_AES,
2540             CRYPT_VERIFYCONTEXT) == FALSE)
2541         {
2542             // Failover to using the default CSP (PROV_RSA_FULL)
2543 
2544             if (::CryptAcquireContext( //deprecated
2545                 &hCryptProv,
2546                 NULL,
2547                 NULL,
2548                 PROV_RSA_FULL,
2549                 CRYPT_VERIFYCONTEXT) == FALSE)
2550             {
2551                 ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
2552                 __leave;
2553             }
2554         }
2555 
2556         // Import the public key
2557         if (::CryptImportKey( //deprecated
2558             hCryptProv,
2559             pbKeyBlob,
2560             dwBlobLen,
2561             0,
2562             CRYPT_EXPORTABLE,
2563             &hKey) == FALSE)
2564         {
2565             ThrowException(env, KEYSTORE_EXCEPTION, GetLastError());
2566             __leave;
2567         }
2568 
2569         // Get the method ID for the CPublicKey constructor
2570         jclass clazzCPublicKey =
2571             env->FindClass("sun/security/mscapi/CPublicKey");
2572         if (clazzCPublicKey == NULL) {
2573             __leave;
2574         }
2575 
2576         jmethodID mNewCPublicKey =
2577             env->GetStaticMethodID(clazzCPublicKey, "of",
2578             "(Ljava/lang/String;JJI)Lsun/security/mscapi/CPublicKey;");
2579         if (mNewCPublicKey == NULL) {
2580             __leave;
2581         }
2582 
2583         // Create a new public key
2584         publicKey = env->CallStaticObjectMethod(clazzCPublicKey, mNewCPublicKey,
2585             alg, (jlong) hCryptProv, (jlong) hKey, keySize);
2586 
2587     }
2588     __finally
2589     {
2590         //--------------------------------------------------------------------
2591         // Clean up.
2592 
2593         if (pbKeyBlob)
2594             env->ReleaseByteArrayElements(keyBlob, (jbyte *) pbKeyBlob,
2595                 JNI_ABORT);
2596     }
2597 
2598     return publicKey;
2599 }
2600 
2601 } /* extern "C" */
2602