1 /*
2 * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 //=--------------------------------------------------------------------------=
27 // security.cpp by Stanley Man-Kit Ho
28 //=--------------------------------------------------------------------------=
29 //
30
31 #include <jni.h>
32 #include "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, (jlong) 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, (jlong) 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