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