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