annotate src/jdk.crypto.mscapi/windows/native/libsunmscapi/security.cpp @ 51349:46492a773912

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