security/nss/lib/ckfw/capi/crsa.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 #include "ckcapi.h"
michael@0 6 #include "secdert.h"
michael@0 7
michael@0 8 #define SSL3_SHAMD5_HASH_SIZE 36 /* LEN_MD5 (16) + LEN_SHA1 (20) */
michael@0 9
michael@0 10 /*
michael@0 11 * ckcapi/crsa.c
michael@0 12 *
michael@0 13 * This file implements the NSSCKMDMechnaism and NSSCKMDCryptoOperation objects
michael@0 14 * for the RSA operation on the CAPI cryptoki module.
michael@0 15 */
michael@0 16
michael@0 17 /*
michael@0 18 * write a Decimal value to a string
michael@0 19 */
michael@0 20
michael@0 21 static char *
michael@0 22 putDecimalString(char *cstr, unsigned long value)
michael@0 23 {
michael@0 24 unsigned long tenpower;
michael@0 25 int first = 1;
michael@0 26
michael@0 27 for (tenpower=10000000; tenpower; tenpower /= 10) {
michael@0 28 unsigned char digit = (unsigned char )(value/tenpower);
michael@0 29 value = value % tenpower;
michael@0 30
michael@0 31 /* drop leading zeros */
michael@0 32 if (first && (0 == digit)) {
michael@0 33 continue;
michael@0 34 }
michael@0 35 first = 0;
michael@0 36 *cstr++ = digit + '0';
michael@0 37 }
michael@0 38
michael@0 39 /* if value was zero, put one of them out */
michael@0 40 if (first) {
michael@0 41 *cstr++ = '0';
michael@0 42 }
michael@0 43 return cstr;
michael@0 44 }
michael@0 45
michael@0 46
michael@0 47 /*
michael@0 48 * Create a Capi OID string value from a DER OID
michael@0 49 */
michael@0 50 static char *
michael@0 51 nss_ckcapi_GetOidString
michael@0 52 (
michael@0 53 unsigned char *oidTag,
michael@0 54 unsigned int oidTagSize,
michael@0 55 CK_RV *pError
michael@0 56 )
michael@0 57 {
michael@0 58 unsigned char *oid;
michael@0 59 char *oidStr;
michael@0 60 char *cstr;
michael@0 61 unsigned long value;
michael@0 62 unsigned int oidSize;
michael@0 63
michael@0 64 if (DER_OBJECT_ID != *oidTag) {
michael@0 65 /* wasn't an oid */
michael@0 66 *pError = CKR_DATA_INVALID;
michael@0 67 return NULL;
michael@0 68 }
michael@0 69 oid = nss_ckcapi_DERUnwrap(oidTag, oidTagSize, &oidSize, NULL);
michael@0 70
michael@0 71 if (oidSize < 2) {
michael@0 72 *pError = CKR_DATA_INVALID;
michael@0 73 return NULL;
michael@0 74 }
michael@0 75
michael@0 76 oidStr = nss_ZNEWARRAY( NULL, char, oidSize*4 );
michael@0 77 if ((char *)NULL == oidStr) {
michael@0 78 *pError = CKR_HOST_MEMORY;
michael@0 79 return NULL;
michael@0 80 }
michael@0 81 cstr = oidStr;
michael@0 82 cstr = putDecimalString(cstr, (*oid) / 40);
michael@0 83 *cstr++ = '.';
michael@0 84 cstr = putDecimalString(cstr, (*oid) % 40);
michael@0 85 oidSize--;
michael@0 86
michael@0 87 value = 0;
michael@0 88 while (oidSize--) {
michael@0 89 oid++;
michael@0 90 value = (value << 7) + (*oid & 0x7f);
michael@0 91 if (0 == (*oid & 0x80)) {
michael@0 92 *cstr++ = '.';
michael@0 93 cstr = putDecimalString(cstr, value);
michael@0 94 value = 0;
michael@0 95 }
michael@0 96 }
michael@0 97
michael@0 98 *cstr = 0; /* NULL terminate */
michael@0 99
michael@0 100 if (value != 0) {
michael@0 101 nss_ZFreeIf(oidStr);
michael@0 102 *pError = CKR_DATA_INVALID;
michael@0 103 return NULL;
michael@0 104 }
michael@0 105 return oidStr;
michael@0 106 }
michael@0 107
michael@0 108
michael@0 109 /*
michael@0 110 * PKCS #11 sign for RSA expects to take a fully DER-encoded hash value,
michael@0 111 * which includes the hash OID. CAPI expects to take a Hash Context. While
michael@0 112 * CAPI does have the capability of setting a raw hash value, it does not
michael@0 113 * have the ability to sign an arbitrary value. This function tries to
michael@0 114 * reduce the passed in data into something that CAPI could actually sign.
michael@0 115 */
michael@0 116 static CK_RV
michael@0 117 ckcapi_GetRawHash
michael@0 118 (
michael@0 119 const NSSItem *input,
michael@0 120 NSSItem *hash,
michael@0 121 ALG_ID *hashAlg
michael@0 122 )
michael@0 123 {
michael@0 124 unsigned char *current;
michael@0 125 unsigned char *algid;
michael@0 126 unsigned char *oid;
michael@0 127 unsigned char *hashData;
michael@0 128 char *oidStr;
michael@0 129 CK_RV error;
michael@0 130 unsigned int oidSize;
michael@0 131 unsigned int size;
michael@0 132 /*
michael@0 133 * there are 2 types of hashes NSS typically tries to sign, regular
michael@0 134 * RSA signature format (with encoded DER_OIDS), and SSL3 Signed hashes.
michael@0 135 * CAPI knows not to add any oids to SSL3_Signed hashes, so if we have any
michael@0 136 * random hash that is exactly the same size as an SSL3 hash, then we can
michael@0 137 * just pass the data through. CAPI has know way of knowing if the value
michael@0 138 * is really a combined hash or some other arbitrary data, so it's safe to
michael@0 139 * handle this case first.
michael@0 140 */
michael@0 141 if (SSL3_SHAMD5_HASH_SIZE == input->size) {
michael@0 142 hash->data = input->data;
michael@0 143 hash->size = input->size;
michael@0 144 *hashAlg = CALG_SSL3_SHAMD5;
michael@0 145 return CKR_OK;
michael@0 146 }
michael@0 147
michael@0 148 current = (unsigned char *)input->data;
michael@0 149
michael@0 150 /* make sure we have a sequence tag */
michael@0 151 if ((DER_SEQUENCE|DER_CONSTRUCTED) != *current) {
michael@0 152 return CKR_DATA_INVALID;
michael@0 153 }
michael@0 154
michael@0 155 /* parse the input block to get 1) the hash oid, and 2) the raw hash value.
michael@0 156 * unfortunatly CAPI doesn't have a builtin function to do this work, so
michael@0 157 * we go ahead and do it by hand here.
michael@0 158 *
michael@0 159 * format is:
michael@0 160 * SEQUENCE {
michael@0 161 * SECQUENCE { // algid
michael@0 162 * OID {} // oid
michael@0 163 * ANY {} // optional params
michael@0 164 * }
michael@0 165 * OCTECT {} // hash
michael@0 166 */
michael@0 167
michael@0 168 /* unwrap */
michael@0 169 algid = nss_ckcapi_DERUnwrap(current,input->size, &size, NULL);
michael@0 170
michael@0 171 if (algid+size != current+input->size) {
michael@0 172 /* make sure there is not extra data at the end */
michael@0 173 return CKR_DATA_INVALID;
michael@0 174 }
michael@0 175
michael@0 176 if ((DER_SEQUENCE|DER_CONSTRUCTED) != *algid) {
michael@0 177 /* wasn't an algid */
michael@0 178 return CKR_DATA_INVALID;
michael@0 179 }
michael@0 180 oid = nss_ckcapi_DERUnwrap(algid, size, &oidSize, &hashData);
michael@0 181
michael@0 182 if (DER_OCTET_STRING != *hashData) {
michael@0 183 /* wasn't a hash */
michael@0 184 return CKR_DATA_INVALID;
michael@0 185 }
michael@0 186
michael@0 187 /* get the real hash */
michael@0 188 current = hashData;
michael@0 189 size = size - (hashData-algid);
michael@0 190 hash->data = nss_ckcapi_DERUnwrap(current, size, &hash->size, NULL);
michael@0 191
michael@0 192 /* get the real oid as a string. Again, Microsoft does not
michael@0 193 * export anything that does this for us */
michael@0 194 oidStr = nss_ckcapi_GetOidString(oid, oidSize, &error);
michael@0 195 if ((char *)NULL == oidStr ) {
michael@0 196 return error;
michael@0 197 }
michael@0 198
michael@0 199 /* look up the hash alg from the oid (fortunately CAPI does to this) */
michael@0 200 *hashAlg = CertOIDToAlgId(oidStr);
michael@0 201 nss_ZFreeIf(oidStr);
michael@0 202 if (0 == *hashAlg) {
michael@0 203 return CKR_HOST_MEMORY;
michael@0 204 }
michael@0 205
michael@0 206 /* hash looks reasonably consistent, we should be able to sign it now */
michael@0 207 return CKR_OK;
michael@0 208 }
michael@0 209
michael@0 210 /*
michael@0 211 * So everyone else in the worlds stores their bignum data MSB first, but not
michael@0 212 * Microsoft, we need to byte swap everything coming into and out of CAPI.
michael@0 213 */
michael@0 214 void
michael@0 215 ckcapi_ReverseData(NSSItem *item)
michael@0 216 {
michael@0 217 int end = (item->size)-1;
michael@0 218 int middle = (item->size)/2;
michael@0 219 unsigned char *buf = item->data;
michael@0 220 int i;
michael@0 221
michael@0 222 for (i=0; i < middle; i++) {
michael@0 223 unsigned char tmp = buf[i];
michael@0 224 buf[i] = buf[end-i];
michael@0 225 buf[end-i] = tmp;
michael@0 226 }
michael@0 227 return;
michael@0 228 }
michael@0 229
michael@0 230 typedef struct ckcapiInternalCryptoOperationRSAPrivStr
michael@0 231 ckcapiInternalCryptoOperationRSAPriv;
michael@0 232 struct ckcapiInternalCryptoOperationRSAPrivStr
michael@0 233 {
michael@0 234 NSSCKMDCryptoOperation mdOperation;
michael@0 235 NSSCKMDMechanism *mdMechanism;
michael@0 236 ckcapiInternalObject *iKey;
michael@0 237 HCRYPTPROV hProv;
michael@0 238 DWORD keySpec;
michael@0 239 HCRYPTKEY hKey;
michael@0 240 NSSItem *buffer;
michael@0 241 };
michael@0 242
michael@0 243 /*
michael@0 244 * ckcapi_mdCryptoOperationRSAPriv_Create
michael@0 245 */
michael@0 246 static NSSCKMDCryptoOperation *
michael@0 247 ckcapi_mdCryptoOperationRSAPriv_Create
michael@0 248 (
michael@0 249 const NSSCKMDCryptoOperation *proto,
michael@0 250 NSSCKMDMechanism *mdMechanism,
michael@0 251 NSSCKMDObject *mdKey,
michael@0 252 CK_RV *pError
michael@0 253 )
michael@0 254 {
michael@0 255 ckcapiInternalObject *iKey = (ckcapiInternalObject *)mdKey->etc;
michael@0 256 const NSSItem *classItem = nss_ckcapi_FetchAttribute(iKey, CKA_CLASS);
michael@0 257 const NSSItem *keyType = nss_ckcapi_FetchAttribute(iKey, CKA_KEY_TYPE);
michael@0 258 ckcapiInternalCryptoOperationRSAPriv *iOperation;
michael@0 259 CK_RV error;
michael@0 260 HCRYPTPROV hProv;
michael@0 261 DWORD keySpec;
michael@0 262 HCRYPTKEY hKey;
michael@0 263
michael@0 264 /* make sure we have the right objects */
michael@0 265 if (((const NSSItem *)NULL == classItem) ||
michael@0 266 (sizeof(CK_OBJECT_CLASS) != classItem->size) ||
michael@0 267 (CKO_PRIVATE_KEY != *(CK_OBJECT_CLASS *)classItem->data) ||
michael@0 268 ((const NSSItem *)NULL == keyType) ||
michael@0 269 (sizeof(CK_KEY_TYPE) != keyType->size) ||
michael@0 270 (CKK_RSA != *(CK_KEY_TYPE *)keyType->data)) {
michael@0 271 *pError = CKR_KEY_TYPE_INCONSISTENT;
michael@0 272 return (NSSCKMDCryptoOperation *)NULL;
michael@0 273 }
michael@0 274
michael@0 275 error = nss_ckcapi_FetchKeyContainer(iKey, &hProv, &keySpec, &hKey);
michael@0 276 if (error != CKR_OK) {
michael@0 277 *pError = error;
michael@0 278 return (NSSCKMDCryptoOperation *)NULL;
michael@0 279 }
michael@0 280
michael@0 281 iOperation = nss_ZNEW(NULL, ckcapiInternalCryptoOperationRSAPriv);
michael@0 282 if ((ckcapiInternalCryptoOperationRSAPriv *)NULL == iOperation) {
michael@0 283 *pError = CKR_HOST_MEMORY;
michael@0 284 return (NSSCKMDCryptoOperation *)NULL;
michael@0 285 }
michael@0 286 iOperation->mdMechanism = mdMechanism;
michael@0 287 iOperation->iKey = iKey;
michael@0 288 iOperation->hProv = hProv;
michael@0 289 iOperation->keySpec = keySpec;
michael@0 290 iOperation->hKey = hKey;
michael@0 291
michael@0 292 nsslibc_memcpy(&iOperation->mdOperation,
michael@0 293 proto, sizeof(NSSCKMDCryptoOperation));
michael@0 294 iOperation->mdOperation.etc = iOperation;
michael@0 295
michael@0 296 return &iOperation->mdOperation;
michael@0 297 }
michael@0 298
michael@0 299 static CK_RV
michael@0 300 ckcapi_mdCryptoOperationRSAPriv_Destroy
michael@0 301 (
michael@0 302 NSSCKMDCryptoOperation *mdOperation,
michael@0 303 NSSCKFWCryptoOperation *fwOperation,
michael@0 304 NSSCKMDInstance *mdInstance,
michael@0 305 NSSCKFWInstance *fwInstance
michael@0 306 )
michael@0 307 {
michael@0 308 ckcapiInternalCryptoOperationRSAPriv *iOperation =
michael@0 309 (ckcapiInternalCryptoOperationRSAPriv *)mdOperation->etc;
michael@0 310
michael@0 311 if (iOperation->hKey) {
michael@0 312 CryptDestroyKey(iOperation->hKey);
michael@0 313 }
michael@0 314 if (iOperation->buffer) {
michael@0 315 nssItem_Destroy(iOperation->buffer);
michael@0 316 }
michael@0 317 nss_ZFreeIf(iOperation);
michael@0 318 return CKR_OK;
michael@0 319 }
michael@0 320
michael@0 321 static CK_ULONG
michael@0 322 ckcapi_mdCryptoOperationRSA_GetFinalLength
michael@0 323 (
michael@0 324 NSSCKMDCryptoOperation *mdOperation,
michael@0 325 NSSCKFWCryptoOperation *fwOperation,
michael@0 326 NSSCKMDSession *mdSession,
michael@0 327 NSSCKFWSession *fwSession,
michael@0 328 NSSCKMDToken *mdToken,
michael@0 329 NSSCKFWToken *fwToken,
michael@0 330 NSSCKMDInstance *mdInstance,
michael@0 331 NSSCKFWInstance *fwInstance,
michael@0 332 CK_RV *pError
michael@0 333 )
michael@0 334 {
michael@0 335 ckcapiInternalCryptoOperationRSAPriv *iOperation =
michael@0 336 (ckcapiInternalCryptoOperationRSAPriv *)mdOperation->etc;
michael@0 337 const NSSItem *modulus =
michael@0 338 nss_ckcapi_FetchAttribute(iOperation->iKey, CKA_MODULUS);
michael@0 339
michael@0 340 return modulus->size;
michael@0 341 }
michael@0 342
michael@0 343
michael@0 344 /*
michael@0 345 * ckcapi_mdCryptoOperationRSADecrypt_GetOperationLength
michael@0 346 * we won't know the length until we actually decrypt the
michael@0 347 * input block. Since we go to all the work to decrypt the
michael@0 348 * the block, we'll save if for when the block is asked for
michael@0 349 */
michael@0 350 static CK_ULONG
michael@0 351 ckcapi_mdCryptoOperationRSADecrypt_GetOperationLength
michael@0 352 (
michael@0 353 NSSCKMDCryptoOperation *mdOperation,
michael@0 354 NSSCKFWCryptoOperation *fwOperation,
michael@0 355 NSSCKMDSession *mdSession,
michael@0 356 NSSCKFWSession *fwSession,
michael@0 357 NSSCKMDToken *mdToken,
michael@0 358 NSSCKFWToken *fwToken,
michael@0 359 NSSCKMDInstance *mdInstance,
michael@0 360 NSSCKFWInstance *fwInstance,
michael@0 361 const NSSItem *input,
michael@0 362 CK_RV *pError
michael@0 363 )
michael@0 364 {
michael@0 365 ckcapiInternalCryptoOperationRSAPriv *iOperation =
michael@0 366 (ckcapiInternalCryptoOperationRSAPriv *)mdOperation->etc;
michael@0 367 BOOL rc;
michael@0 368
michael@0 369 /* Microsoft's Decrypt operation works in place. Since we don't want
michael@0 370 * to trash our input buffer, we make a copy of it */
michael@0 371 iOperation->buffer = nssItem_Duplicate((NSSItem *)input, NULL, NULL);
michael@0 372 if ((NSSItem *) NULL == iOperation->buffer) {
michael@0 373 *pError = CKR_HOST_MEMORY;
michael@0 374 return 0;
michael@0 375 }
michael@0 376 /* Sigh, reverse it */
michael@0 377 ckcapi_ReverseData(iOperation->buffer);
michael@0 378
michael@0 379 rc = CryptDecrypt(iOperation->hKey, 0, TRUE, 0,
michael@0 380 iOperation->buffer->data, &iOperation->buffer->size);
michael@0 381 if (!rc) {
michael@0 382 DWORD msError = GetLastError();
michael@0 383 switch (msError) {
michael@0 384 case NTE_BAD_DATA:
michael@0 385 *pError = CKR_ENCRYPTED_DATA_INVALID;
michael@0 386 break;
michael@0 387 case NTE_FAIL:
michael@0 388 case NTE_BAD_UID:
michael@0 389 *pError = CKR_DEVICE_ERROR;
michael@0 390 break;
michael@0 391 default:
michael@0 392 *pError = CKR_GENERAL_ERROR;
michael@0 393 }
michael@0 394 return 0;
michael@0 395 }
michael@0 396
michael@0 397 return iOperation->buffer->size;
michael@0 398 }
michael@0 399
michael@0 400 /*
michael@0 401 * ckcapi_mdCryptoOperationRSADecrypt_UpdateFinal
michael@0 402 *
michael@0 403 * NOTE: ckcapi_mdCryptoOperationRSADecrypt_GetOperationLength is presumed to
michael@0 404 * have been called previously.
michael@0 405 */
michael@0 406 static CK_RV
michael@0 407 ckcapi_mdCryptoOperationRSADecrypt_UpdateFinal
michael@0 408 (
michael@0 409 NSSCKMDCryptoOperation *mdOperation,
michael@0 410 NSSCKFWCryptoOperation *fwOperation,
michael@0 411 NSSCKMDSession *mdSession,
michael@0 412 NSSCKFWSession *fwSession,
michael@0 413 NSSCKMDToken *mdToken,
michael@0 414 NSSCKFWToken *fwToken,
michael@0 415 NSSCKMDInstance *mdInstance,
michael@0 416 NSSCKFWInstance *fwInstance,
michael@0 417 const NSSItem *input,
michael@0 418 NSSItem *output
michael@0 419 )
michael@0 420 {
michael@0 421 ckcapiInternalCryptoOperationRSAPriv *iOperation =
michael@0 422 (ckcapiInternalCryptoOperationRSAPriv *)mdOperation->etc;
michael@0 423 NSSItem *buffer = iOperation->buffer;
michael@0 424
michael@0 425 if ((NSSItem *)NULL == buffer) {
michael@0 426 return CKR_GENERAL_ERROR;
michael@0 427 }
michael@0 428 nsslibc_memcpy(output->data, buffer->data, buffer->size);
michael@0 429 output->size = buffer->size;
michael@0 430 return CKR_OK;
michael@0 431 }
michael@0 432
michael@0 433 /*
michael@0 434 * ckcapi_mdCryptoOperationRSASign_UpdateFinal
michael@0 435 *
michael@0 436 */
michael@0 437 static CK_RV
michael@0 438 ckcapi_mdCryptoOperationRSASign_UpdateFinal
michael@0 439 (
michael@0 440 NSSCKMDCryptoOperation *mdOperation,
michael@0 441 NSSCKFWCryptoOperation *fwOperation,
michael@0 442 NSSCKMDSession *mdSession,
michael@0 443 NSSCKFWSession *fwSession,
michael@0 444 NSSCKMDToken *mdToken,
michael@0 445 NSSCKFWToken *fwToken,
michael@0 446 NSSCKMDInstance *mdInstance,
michael@0 447 NSSCKFWInstance *fwInstance,
michael@0 448 const NSSItem *input,
michael@0 449 NSSItem *output
michael@0 450 )
michael@0 451 {
michael@0 452 ckcapiInternalCryptoOperationRSAPriv *iOperation =
michael@0 453 (ckcapiInternalCryptoOperationRSAPriv *)mdOperation->etc;
michael@0 454 CK_RV error = CKR_OK;
michael@0 455 DWORD msError;
michael@0 456 NSSItem hash;
michael@0 457 HCRYPTHASH hHash = 0;
michael@0 458 ALG_ID hashAlg;
michael@0 459 DWORD hashSize;
michael@0 460 DWORD len; /* temp length value we throw away */
michael@0 461 BOOL rc;
michael@0 462
michael@0 463 /*
michael@0 464 * PKCS #11 sign for RSA expects to take a fully DER-encoded hash value,
michael@0 465 * which includes the hash OID. CAPI expects to take a Hash Context. While
michael@0 466 * CAPI does have the capability of setting a raw hash value, it does not
michael@0 467 * have the ability to sign an arbitrary value. This function tries to
michael@0 468 * reduce the passed in data into something that CAPI could actually sign.
michael@0 469 */
michael@0 470 error = ckcapi_GetRawHash(input, &hash, &hashAlg);
michael@0 471 if (CKR_OK != error) {
michael@0 472 goto loser;
michael@0 473 }
michael@0 474
michael@0 475 rc = CryptCreateHash(iOperation->hProv, hashAlg, 0, 0, &hHash);
michael@0 476 if (!rc) {
michael@0 477 goto loser;
michael@0 478 }
michael@0 479
michael@0 480 /* make sure the hash lens match before we set it */
michael@0 481 len = sizeof(DWORD);
michael@0 482 rc = CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE *)&hashSize, &len, 0);
michael@0 483 if (!rc) {
michael@0 484 goto loser;
michael@0 485 }
michael@0 486
michael@0 487 if (hash.size != hashSize) {
michael@0 488 /* The input must have been bad for this to happen */
michael@0 489 error = CKR_DATA_INVALID;
michael@0 490 goto loser;
michael@0 491 }
michael@0 492
michael@0 493 /* we have an explicit hash, set it, note that the length is
michael@0 494 * implicit by the hashAlg used in create */
michael@0 495 rc = CryptSetHashParam(hHash, HP_HASHVAL, hash.data, 0);
michael@0 496 if (!rc) {
michael@0 497 goto loser;
michael@0 498 }
michael@0 499
michael@0 500 /* OK, we have the data in a hash structure, sign it! */
michael@0 501 rc = CryptSignHash(hHash, iOperation->keySpec, NULL, 0,
michael@0 502 output->data, &output->size);
michael@0 503 if (!rc) {
michael@0 504 goto loser;
michael@0 505 }
michael@0 506
michael@0 507 /* Don't return a signature that might have been broken because of a cosmic
michael@0 508 * ray, or a broken processor, verify that it is valid... */
michael@0 509 rc = CryptVerifySignature(hHash, output->data, output->size,
michael@0 510 iOperation->hKey, NULL, 0);
michael@0 511 if (!rc) {
michael@0 512 goto loser;
michael@0 513 }
michael@0 514
michael@0 515 /* OK, Microsoft likes to do things completely differently than anyone
michael@0 516 * else. We need to reverse the data we received here */
michael@0 517 ckcapi_ReverseData(output);
michael@0 518 CryptDestroyHash(hHash);
michael@0 519 return CKR_OK;
michael@0 520
michael@0 521 loser:
michael@0 522 /* map the microsoft error */
michael@0 523 if (CKR_OK == error) {
michael@0 524 msError = GetLastError();
michael@0 525 switch (msError) {
michael@0 526 case ERROR_NOT_ENOUGH_MEMORY:
michael@0 527 error = CKR_HOST_MEMORY;
michael@0 528 break;
michael@0 529 case NTE_NO_MEMORY:
michael@0 530 error = CKR_DEVICE_MEMORY;
michael@0 531 break;
michael@0 532 case ERROR_MORE_DATA:
michael@0 533 return CKR_BUFFER_TOO_SMALL;
michael@0 534 case ERROR_INVALID_PARAMETER: /* these params were derived from the */
michael@0 535 case ERROR_INVALID_HANDLE: /* inputs, so if they are bad, the input */
michael@0 536 case NTE_BAD_ALGID: /* data is bad */
michael@0 537 case NTE_BAD_HASH:
michael@0 538 error = CKR_DATA_INVALID;
michael@0 539 break;
michael@0 540 case ERROR_BUSY:
michael@0 541 case NTE_FAIL:
michael@0 542 case NTE_BAD_UID:
michael@0 543 error = CKR_DEVICE_ERROR;
michael@0 544 break;
michael@0 545 default:
michael@0 546 error = CKR_GENERAL_ERROR;
michael@0 547 break;
michael@0 548 }
michael@0 549 }
michael@0 550 if (hHash) {
michael@0 551 CryptDestroyHash(hHash);
michael@0 552 }
michael@0 553 return error;
michael@0 554 }
michael@0 555
michael@0 556
michael@0 557 NSS_IMPLEMENT_DATA const NSSCKMDCryptoOperation
michael@0 558 ckcapi_mdCryptoOperationRSADecrypt_proto = {
michael@0 559 NULL, /* etc */
michael@0 560 ckcapi_mdCryptoOperationRSAPriv_Destroy,
michael@0 561 NULL, /* GetFinalLengh - not needed for one shot Decrypt/Encrypt */
michael@0 562 ckcapi_mdCryptoOperationRSADecrypt_GetOperationLength,
michael@0 563 NULL, /* Final - not needed for one shot operation */
michael@0 564 NULL, /* Update - not needed for one shot operation */
michael@0 565 NULL, /* DigetUpdate - not needed for one shot operation */
michael@0 566 ckcapi_mdCryptoOperationRSADecrypt_UpdateFinal,
michael@0 567 NULL, /* UpdateCombo - not needed for one shot operation */
michael@0 568 NULL, /* DigetKey - not needed for one shot operation */
michael@0 569 (void *)NULL /* null terminator */
michael@0 570 };
michael@0 571
michael@0 572 NSS_IMPLEMENT_DATA const NSSCKMDCryptoOperation
michael@0 573 ckcapi_mdCryptoOperationRSASign_proto = {
michael@0 574 NULL, /* etc */
michael@0 575 ckcapi_mdCryptoOperationRSAPriv_Destroy,
michael@0 576 ckcapi_mdCryptoOperationRSA_GetFinalLength,
michael@0 577 NULL, /* GetOperationLengh - not needed for one shot Sign/Verify */
michael@0 578 NULL, /* Final - not needed for one shot operation */
michael@0 579 NULL, /* Update - not needed for one shot operation */
michael@0 580 NULL, /* DigetUpdate - not needed for one shot operation */
michael@0 581 ckcapi_mdCryptoOperationRSASign_UpdateFinal,
michael@0 582 NULL, /* UpdateCombo - not needed for one shot operation */
michael@0 583 NULL, /* DigetKey - not needed for one shot operation */
michael@0 584 (void *)NULL /* null terminator */
michael@0 585 };
michael@0 586
michael@0 587 /********** NSSCKMDMechansim functions ***********************/
michael@0 588 /*
michael@0 589 * ckcapi_mdMechanismRSA_Destroy
michael@0 590 */
michael@0 591 static void
michael@0 592 ckcapi_mdMechanismRSA_Destroy
michael@0 593 (
michael@0 594 NSSCKMDMechanism *mdMechanism,
michael@0 595 NSSCKFWMechanism *fwMechanism,
michael@0 596 NSSCKMDInstance *mdInstance,
michael@0 597 NSSCKFWInstance *fwInstance
michael@0 598 )
michael@0 599 {
michael@0 600 nss_ZFreeIf(fwMechanism);
michael@0 601 }
michael@0 602
michael@0 603 /*
michael@0 604 * ckcapi_mdMechanismRSA_GetMinKeySize
michael@0 605 */
michael@0 606 static CK_ULONG
michael@0 607 ckcapi_mdMechanismRSA_GetMinKeySize
michael@0 608 (
michael@0 609 NSSCKMDMechanism *mdMechanism,
michael@0 610 NSSCKFWMechanism *fwMechanism,
michael@0 611 NSSCKMDToken *mdToken,
michael@0 612 NSSCKFWToken *fwToken,
michael@0 613 NSSCKMDInstance *mdInstance,
michael@0 614 NSSCKFWInstance *fwInstance,
michael@0 615 CK_RV *pError
michael@0 616 )
michael@0 617 {
michael@0 618 return 384;
michael@0 619 }
michael@0 620
michael@0 621 /*
michael@0 622 * ckcapi_mdMechanismRSA_GetMaxKeySize
michael@0 623 */
michael@0 624 static CK_ULONG
michael@0 625 ckcapi_mdMechanismRSA_GetMaxKeySize
michael@0 626 (
michael@0 627 NSSCKMDMechanism *mdMechanism,
michael@0 628 NSSCKFWMechanism *fwMechanism,
michael@0 629 NSSCKMDToken *mdToken,
michael@0 630 NSSCKFWToken *fwToken,
michael@0 631 NSSCKMDInstance *mdInstance,
michael@0 632 NSSCKFWInstance *fwInstance,
michael@0 633 CK_RV *pError
michael@0 634 )
michael@0 635 {
michael@0 636 return 16384;
michael@0 637 }
michael@0 638
michael@0 639 /*
michael@0 640 * ckcapi_mdMechanismRSA_DecryptInit
michael@0 641 */
michael@0 642 static NSSCKMDCryptoOperation *
michael@0 643 ckcapi_mdMechanismRSA_DecryptInit
michael@0 644 (
michael@0 645 NSSCKMDMechanism *mdMechanism,
michael@0 646 NSSCKFWMechanism *fwMechanism,
michael@0 647 CK_MECHANISM *pMechanism,
michael@0 648 NSSCKMDSession *mdSession,
michael@0 649 NSSCKFWSession *fwSession,
michael@0 650 NSSCKMDToken *mdToken,
michael@0 651 NSSCKFWToken *fwToken,
michael@0 652 NSSCKMDInstance *mdInstance,
michael@0 653 NSSCKFWInstance *fwInstance,
michael@0 654 NSSCKMDObject *mdKey,
michael@0 655 NSSCKFWObject *fwKey,
michael@0 656 CK_RV *pError
michael@0 657 )
michael@0 658 {
michael@0 659 return ckcapi_mdCryptoOperationRSAPriv_Create(
michael@0 660 &ckcapi_mdCryptoOperationRSADecrypt_proto,
michael@0 661 mdMechanism, mdKey, pError);
michael@0 662 }
michael@0 663
michael@0 664 /*
michael@0 665 * ckcapi_mdMechanismRSA_SignInit
michael@0 666 */
michael@0 667 static NSSCKMDCryptoOperation *
michael@0 668 ckcapi_mdMechanismRSA_SignInit
michael@0 669 (
michael@0 670 NSSCKMDMechanism *mdMechanism,
michael@0 671 NSSCKFWMechanism *fwMechanism,
michael@0 672 CK_MECHANISM *pMechanism,
michael@0 673 NSSCKMDSession *mdSession,
michael@0 674 NSSCKFWSession *fwSession,
michael@0 675 NSSCKMDToken *mdToken,
michael@0 676 NSSCKFWToken *fwToken,
michael@0 677 NSSCKMDInstance *mdInstance,
michael@0 678 NSSCKFWInstance *fwInstance,
michael@0 679 NSSCKMDObject *mdKey,
michael@0 680 NSSCKFWObject *fwKey,
michael@0 681 CK_RV *pError
michael@0 682 )
michael@0 683 {
michael@0 684 return ckcapi_mdCryptoOperationRSAPriv_Create(
michael@0 685 &ckcapi_mdCryptoOperationRSASign_proto,
michael@0 686 mdMechanism, mdKey, pError);
michael@0 687 }
michael@0 688
michael@0 689
michael@0 690 NSS_IMPLEMENT_DATA const NSSCKMDMechanism
michael@0 691 nss_ckcapi_mdMechanismRSA = {
michael@0 692 (void *)NULL, /* etc */
michael@0 693 ckcapi_mdMechanismRSA_Destroy,
michael@0 694 ckcapi_mdMechanismRSA_GetMinKeySize,
michael@0 695 ckcapi_mdMechanismRSA_GetMaxKeySize,
michael@0 696 NULL, /* GetInHardware - default false */
michael@0 697 NULL, /* EncryptInit - default errs */
michael@0 698 ckcapi_mdMechanismRSA_DecryptInit,
michael@0 699 NULL, /* DigestInit - default errs*/
michael@0 700 ckcapi_mdMechanismRSA_SignInit,
michael@0 701 NULL, /* VerifyInit - default errs */
michael@0 702 ckcapi_mdMechanismRSA_SignInit, /* SignRecoverInit */
michael@0 703 NULL, /* VerifyRecoverInit - default errs */
michael@0 704 NULL, /* GenerateKey - default errs */
michael@0 705 NULL, /* GenerateKeyPair - default errs */
michael@0 706 NULL, /* GetWrapKeyLength - default errs */
michael@0 707 NULL, /* WrapKey - default errs */
michael@0 708 NULL, /* UnwrapKey - default errs */
michael@0 709 NULL, /* DeriveKey - default errs */
michael@0 710 (void *)NULL /* null terminator */
michael@0 711 };

mercurial