Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/native/sun/security/mscapi/security.cpp
32288 views
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
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
*/
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
2603