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