| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * PKCS#1 encoding and decoding functions. | |
| 3 * This file is believed to contain no code licensed from other parties. | |
| 4 * | |
| 5 * This Source Code Form is subject to the terms of the Mozilla Public | |
| 6 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
| 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
| 8 /* $Id: rsawrapr.c,v 1.22 2013/02/05 02:19:52 ryan.sleevi%gmail.com Exp $ */ | |
| 9 | |
| 10 #include "blapi.h" | |
| 11 #include "softoken.h" | |
| 12 | |
| 13 #include "lowkeyi.h" | |
| 14 #include "secerr.h" | |
| 15 | |
| 16 #define RSA_BLOCK_MIN_PAD_LEN 8 | |
| 17 #define RSA_BLOCK_FIRST_OCTET 0x00 | |
| 18 #define RSA_BLOCK_PRIVATE0_PAD_OCTET 0x00 | |
| 19 #define RSA_BLOCK_PRIVATE_PAD_OCTET 0xff | |
| 20 #define RSA_BLOCK_AFTER_PAD_OCTET 0x00 | |
| 21 | |
| 22 /* Needed for RSA-PSS functions */ | |
| 23 static const unsigned char eightZeros[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | |
| 24 | |
| 25 /* Constant time comparison of a single byte. | |
| 26 * Returns 1 iff a == b, otherwise returns 0. | |
| 27 * Note: For ranges of bytes, use constantTimeCompare. | |
| 28 */ | |
| 29 static unsigned char constantTimeEQ8(unsigned char a, unsigned char b) { | |
| 30 unsigned char c = ~(a - b | b - a); | |
| 31 c >>= 7; | |
| 32 return c; | |
| 33 } | |
| 34 | |
| 35 /* Constant time comparison of a range of bytes. | |
| 36 * Returns 1 iff len bytes of a are identical to len bytes of b, otherwise | |
| 37 * returns 0. | |
| 38 */ | |
| 39 static unsigned char constantTimeCompare(const unsigned char *a, | |
| 40 const unsigned char *b, | |
| 41 unsigned int len) { | |
| 42 unsigned char tmp = 0; | |
| 43 unsigned int i; | |
| 44 for (i = 0; i < len; ++i, ++a, ++b) | |
| 45 tmp |= *a ^ *b; | |
| 46 return constantTimeEQ8(0x00, tmp); | |
| 47 } | |
| 48 | |
| 49 /* Constant time conditional. | |
| 50 * Returns a if c is 1, or b if c is 0. The result is undefined if c is | |
| 51 * not 0 or 1. | |
| 52 */ | |
| 53 static unsigned int constantTimeCondition(unsigned int c, | |
| 54 unsigned int a, | |
| 55 unsigned int b) | |
| 56 { | |
| 57 return (~(c - 1) & a) | ((c - 1) & b); | |
| 58 } | |
| 59 | |
| 60 /* | |
| 61 * Format one block of data for public/private key encryption using | |
| 62 * the rules defined in PKCS #1. | |
| 63 */ | |
| 64 static unsigned char * | |
| 65 rsa_FormatOneBlock(unsigned modulusLen, RSA_BlockType blockType, | |
| 66 SECItem *data) | |
| 67 { | |
| 68 unsigned char *block; | |
| 69 unsigned char *bp; | |
| 70 int padLen; | |
| 71 int i, j; | |
| 72 SECStatus rv; | |
| 73 | |
| 74 block = (unsigned char *) PORT_Alloc(modulusLen); | |
| 75 if (block == NULL) | |
| 76 return NULL; | |
| 77 | |
| 78 bp = block; | |
| 79 | |
| 80 /* | |
| 81 * All RSA blocks start with two octets: | |
| 82 * 0x00 || BlockType | |
| 83 */ | |
| 84 *bp++ = RSA_BLOCK_FIRST_OCTET; | |
| 85 *bp++ = (unsigned char) blockType; | |
| 86 | |
| 87 switch (blockType) { | |
| 88 | |
| 89 /* | |
| 90 * Blocks intended for private-key operation. | |
| 91 */ | |
| 92 case RSA_BlockPrivate0: /* essentially unused */ | |
| 93 case RSA_BlockPrivate: /* preferred method */ | |
| 94 /* | |
| 95 * 0x00 || BT || Pad || 0x00 || ActualData | |
| 96 * 1 1 padLen 1 data->len | |
| 97 * Pad is either all 0x00 or all 0xff bytes, depending on blockType. | |
| 98 */ | |
| 99 padLen = modulusLen - data->len - 3; | |
| 100 PORT_Assert (padLen >= RSA_BLOCK_MIN_PAD_LEN); | |
| 101 if (padLen < RSA_BLOCK_MIN_PAD_LEN) { | |
| 102 PORT_Free (block); | |
| 103 return NULL; | |
| 104 } | |
| 105 PORT_Memset (bp, | |
| 106 blockType == RSA_BlockPrivate0 | |
| 107 ? RSA_BLOCK_PRIVATE0_PAD_OCTET | |
| 108 : RSA_BLOCK_PRIVATE_PAD_OCTET, | |
| 109 padLen); | |
| 110 bp += padLen; | |
| 111 *bp++ = RSA_BLOCK_AFTER_PAD_OCTET; | |
| 112 PORT_Memcpy (bp, data->data, data->len); | |
| 113 break; | |
| 114 | |
| 115 /* | |
| 116 * Blocks intended for public-key operation. | |
| 117 */ | |
| 118 case RSA_BlockPublic: | |
| 119 | |
| 120 /* | |
| 121 * 0x00 || BT || Pad || 0x00 || ActualData | |
| 122 * 1 1 padLen 1 data->len | |
| 123 * Pad is all non-zero random bytes. | |
| 124 * | |
| 125 * Build the block left to right. | |
| 126 * Fill the entire block from Pad to the end with random bytes. | |
| 127 * Use the bytes after Pad as a supply of extra random bytes from | |
| 128 * which to find replacements for the zero bytes in Pad. | |
| 129 * If we need more than that, refill the bytes after Pad with | |
| 130 * new random bytes as necessary. | |
| 131 */ | |
| 132 padLen = modulusLen - (data->len + 3); | |
| 133 PORT_Assert (padLen >= RSA_BLOCK_MIN_PAD_LEN); | |
| 134 if (padLen < RSA_BLOCK_MIN_PAD_LEN) { | |
| 135 PORT_Free (block); | |
| 136 return NULL; | |
| 137 } | |
| 138 j = modulusLen - 2; | |
| 139 rv = RNG_GenerateGlobalRandomBytes(bp, j); | |
| 140 if (rv == SECSuccess) { | |
| 141 for (i = 0; i < padLen; ) { | |
| 142 unsigned char repl; | |
| 143 /* Pad with non-zero random data. */ | |
| 144 if (bp[i] != RSA_BLOCK_AFTER_PAD_OCTET) { | |
| 145 ++i; | |
| 146 continue; | |
| 147 } | |
| 148 if (j <= padLen) { | |
| 149 rv = RNG_GenerateGlobalRandomBytes(bp + padLen, | |
| 150 modulusLen - (2 + padLen)); | |
| 151 if (rv != SECSuccess) | |
| 152 break; | |
| 153 j = modulusLen - 2; | |
| 154 } | |
| 155 do { | |
| 156 repl = bp[--j]; | |
| 157 } while (repl == RSA_BLOCK_AFTER_PAD_OCTET && j > padLen); | |
| 158 if (repl != RSA_BLOCK_AFTER_PAD_OCTET) { | |
| 159 bp[i++] = repl; | |
| 160 } | |
| 161 } | |
| 162 } | |
| 163 if (rv != SECSuccess) { | |
| 164 sftk_fatalError = PR_TRUE; | |
| 165 PORT_Free (block); | |
| 166 return NULL; | |
| 167 } | |
| 168 bp += padLen; | |
| 169 *bp++ = RSA_BLOCK_AFTER_PAD_OCTET; | |
| 170 PORT_Memcpy (bp, data->data, data->len); | |
| 171 break; | |
| 172 | |
| 173 default: | |
| 174 PORT_Assert (0); | |
| 175 PORT_Free (block); | |
| 176 return NULL; | |
| 177 } | |
| 178 | |
| 179 return block; | |
| 180 } | |
| 181 | |
| 182 static SECStatus | |
| 183 rsa_FormatBlock(SECItem *result, unsigned modulusLen, | |
| 184 RSA_BlockType blockType, SECItem *data) | |
| 185 { | |
| 186 /* | |
| 187 * XXX For now assume that the data length fits in a single | |
| 188 * XXX encryption block; the ASSERTs below force this. | |
| 189 * XXX To fix it, each case will have to loop over chunks whose | |
| 190 * XXX lengths satisfy the assertions, until all data is handled. | |
| 191 * XXX (Unless RSA has more to say about how to handle data | |
| 192 * XXX which does not fit in a single encryption block?) | |
| 193 * XXX And I do not know what the result is supposed to be, | |
| 194 * XXX so the interface to this function may need to change | |
| 195 * XXX to allow for returning multiple blocks, if they are | |
| 196 * XXX not wanted simply concatenated one after the other. | |
| 197 */ | |
| 198 | |
| 199 switch (blockType) { | |
| 200 case RSA_BlockPrivate0: | |
| 201 case RSA_BlockPrivate: | |
| 202 case RSA_BlockPublic: | |
| 203 /* | |
| 204 * 0x00 || BT || Pad || 0x00 || ActualData | |
| 205 * | |
| 206 * The "3" below is the first octet + the second octet + the 0x00 | |
| 207 * octet that always comes just before the ActualData. | |
| 208 */ | |
| 209 PORT_Assert (data->len <= (modulusLen - (3 + RSA_BLOCK_MIN_PAD_LEN))); | |
| 210 | |
| 211 result->data = rsa_FormatOneBlock(modulusLen, blockType, data); | |
| 212 if (result->data == NULL) { | |
| 213 result->len = 0; | |
| 214 return SECFailure; | |
| 215 } | |
| 216 result->len = modulusLen; | |
| 217 | |
| 218 break; | |
| 219 | |
| 220 case RSA_BlockRaw: | |
| 221 /* | |
| 222 * Pad || ActualData | |
| 223 * Pad is zeros. The application is responsible for recovering | |
| 224 * the actual data. | |
| 225 */ | |
| 226 if (data->len > modulusLen ) { | |
| 227 return SECFailure; | |
| 228 } | |
| 229 result->data = (unsigned char*)PORT_ZAlloc(modulusLen); | |
| 230 result->len = modulusLen; | |
| 231 PORT_Memcpy(result->data+(modulusLen-data->len),data->data,data->len); | |
| 232 break; | |
| 233 | |
| 234 default: | |
| 235 PORT_Assert (0); | |
| 236 result->data = NULL; | |
| 237 result->len = 0; | |
| 238 return SECFailure; | |
| 239 } | |
| 240 | |
| 241 return SECSuccess; | |
| 242 } | |
| 243 | |
| 244 /* XXX Doesn't set error code */ | |
| 245 SECStatus | |
| 246 RSA_Sign(NSSLOWKEYPrivateKey *key, | |
| 247 unsigned char * output, | |
| 248 unsigned int * output_len, | |
| 249 unsigned int maxOutputLen, | |
| 250 unsigned char * input, | |
| 251 unsigned int input_len) | |
| 252 { | |
| 253 SECStatus rv = SECSuccess; | |
| 254 unsigned int modulus_len = nsslowkey_PrivateModulusLen(key); | |
| 255 SECItem formatted; | |
| 256 SECItem unformatted; | |
| 257 | |
| 258 if (maxOutputLen < modulus_len) | |
| 259 return SECFailure; | |
| 260 PORT_Assert(key->keyType == NSSLOWKEYRSAKey); | |
| 261 if (key->keyType != NSSLOWKEYRSAKey) | |
| 262 return SECFailure; | |
| 263 | |
| 264 unformatted.len = input_len; | |
| 265 unformatted.data = input; | |
| 266 formatted.data = NULL; | |
| 267 rv = rsa_FormatBlock(&formatted, modulus_len, RSA_BlockPrivate, | |
| 268 &unformatted); | |
| 269 if (rv != SECSuccess) | |
| 270 goto done; | |
| 271 | |
| 272 rv = RSA_PrivateKeyOpDoubleChecked(&key->u.rsa, output, formatted.data); | |
| 273 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { | |
| 274 sftk_fatalError = PR_TRUE; | |
| 275 } | |
| 276 *output_len = modulus_len; | |
| 277 | |
| 278 goto done; | |
| 279 | |
| 280 done: | |
| 281 if (formatted.data != NULL) | |
| 282 PORT_ZFree(formatted.data, modulus_len); | |
| 283 return rv; | |
| 284 } | |
| 285 | |
| 286 /* XXX Doesn't set error code */ | |
| 287 SECStatus | |
| 288 RSA_CheckSign(NSSLOWKEYPublicKey *key, | |
| 289 unsigned char * sign, | |
| 290 unsigned int sign_len, | |
| 291 unsigned char * hash, | |
| 292 unsigned int hash_len) | |
| 293 { | |
| 294 SECStatus rv; | |
| 295 unsigned int modulus_len = nsslowkey_PublicModulusLen(key); | |
| 296 unsigned int i; | |
| 297 unsigned char * buffer; | |
| 298 | |
| 299 modulus_len = nsslowkey_PublicModulusLen(key); | |
| 300 if (sign_len != modulus_len) | |
| 301 goto failure; | |
| 302 /* | |
| 303 * 0x00 || BT || Pad || 0x00 || ActualData | |
| 304 * | |
| 305 * The "3" below is the first octet + the second octet + the 0x00 | |
| 306 * octet that always comes just before the ActualData. | |
| 307 */ | |
| 308 if (hash_len > modulus_len - (3 + RSA_BLOCK_MIN_PAD_LEN)) | |
| 309 goto failure; | |
| 310 PORT_Assert(key->keyType == NSSLOWKEYRSAKey); | |
| 311 if (key->keyType != NSSLOWKEYRSAKey) | |
| 312 goto failure; | |
| 313 | |
| 314 buffer = (unsigned char *)PORT_Alloc(modulus_len + 1); | |
| 315 if (!buffer) | |
| 316 goto failure; | |
| 317 | |
| 318 rv = RSA_PublicKeyOp(&key->u.rsa, buffer, sign); | |
| 319 if (rv != SECSuccess) | |
| 320 goto loser; | |
| 321 | |
| 322 /* | |
| 323 * check the padding that was used | |
| 324 */ | |
| 325 if (buffer[0] != 0 || buffer[1] != 1) | |
| 326 goto loser; | |
| 327 for (i = 2; i < modulus_len - hash_len - 1; i++) { | |
| 328 if (buffer[i] != 0xff) | |
| 329 goto loser; | |
| 330 } | |
| 331 if (buffer[i] != 0) | |
| 332 goto loser; | |
| 333 | |
| 334 /* | |
| 335 * make sure we get the same results | |
| 336 */ | |
| 337 if (PORT_Memcmp(buffer + modulus_len - hash_len, hash, hash_len) != 0) | |
| 338 goto loser; | |
| 339 | |
| 340 PORT_Free(buffer); | |
| 341 return SECSuccess; | |
| 342 | |
| 343 loser: | |
| 344 PORT_Free(buffer); | |
| 345 failure: | |
| 346 return SECFailure; | |
| 347 } | |
| 348 | |
| 349 /* XXX Doesn't set error code */ | |
| 350 SECStatus | |
| 351 RSA_CheckSignRecover(NSSLOWKEYPublicKey *key, | |
| 352 unsigned char * data, | |
| 353 unsigned int * data_len, | |
| 354 unsigned int max_output_len, | |
| 355 unsigned char * sign, | |
| 356 unsigned int sign_len) | |
| 357 { | |
| 358 SECStatus rv; | |
| 359 unsigned int modulus_len = nsslowkey_PublicModulusLen(key); | |
| 360 unsigned int i; | |
| 361 unsigned char * buffer; | |
| 362 | |
| 363 if (sign_len != modulus_len) | |
| 364 goto failure; | |
| 365 PORT_Assert(key->keyType == NSSLOWKEYRSAKey); | |
| 366 if (key->keyType != NSSLOWKEYRSAKey) | |
| 367 goto failure; | |
| 368 | |
| 369 buffer = (unsigned char *)PORT_Alloc(modulus_len + 1); | |
| 370 if (!buffer) | |
| 371 goto failure; | |
| 372 | |
| 373 rv = RSA_PublicKeyOp(&key->u.rsa, buffer, sign); | |
| 374 if (rv != SECSuccess) | |
| 375 goto loser; | |
| 376 *data_len = 0; | |
| 377 | |
| 378 /* | |
| 379 * check the padding that was used | |
| 380 */ | |
| 381 if (buffer[0] != 0 || buffer[1] != 1) | |
| 382 goto loser; | |
| 383 for (i = 2; i < modulus_len; i++) { | |
| 384 if (buffer[i] == 0) { | |
| 385 *data_len = modulus_len - i - 1; | |
| 386 break; | |
| 387 } | |
| 388 if (buffer[i] != 0xff) | |
| 389 goto loser; | |
| 390 } | |
| 391 if (*data_len == 0) | |
| 392 goto loser; | |
| 393 if (*data_len > max_output_len) | |
| 394 goto loser; | |
| 395 | |
| 396 /* | |
| 397 * make sure we get the same results | |
| 398 */ | |
| 399 PORT_Memcpy(data,buffer + modulus_len - *data_len, *data_len); | |
| 400 | |
| 401 PORT_Free(buffer); | |
| 402 return SECSuccess; | |
| 403 | |
| 404 loser: | |
| 405 PORT_Free(buffer); | |
| 406 failure: | |
| 407 return SECFailure; | |
| 408 } | |
| 409 | |
| 410 /* XXX Doesn't set error code */ | |
| 411 SECStatus | |
| 412 RSA_EncryptBlock(NSSLOWKEYPublicKey *key, | |
| 413 unsigned char * output, | |
| 414 unsigned int * output_len, | |
| 415 unsigned int max_output_len, | |
| 416 unsigned char * input, | |
| 417 unsigned int input_len) | |
| 418 { | |
| 419 SECStatus rv; | |
| 420 unsigned int modulus_len = nsslowkey_PublicModulusLen(key); | |
| 421 SECItem formatted; | |
| 422 SECItem unformatted; | |
| 423 | |
| 424 formatted.data = NULL; | |
| 425 if (max_output_len < modulus_len) | |
| 426 goto failure; | |
| 427 PORT_Assert(key->keyType == NSSLOWKEYRSAKey); | |
| 428 if (key->keyType != NSSLOWKEYRSAKey) | |
| 429 goto failure; | |
| 430 | |
| 431 unformatted.len = input_len; | |
| 432 unformatted.data = input; | |
| 433 formatted.data = NULL; | |
| 434 rv = rsa_FormatBlock(&formatted, modulus_len, RSA_BlockPublic, | |
| 435 &unformatted); | |
| 436 if (rv != SECSuccess) | |
| 437 goto failure; | |
| 438 | |
| 439 rv = RSA_PublicKeyOp(&key->u.rsa, output, formatted.data); | |
| 440 if (rv != SECSuccess) | |
| 441 goto failure; | |
| 442 | |
| 443 PORT_ZFree(formatted.data, modulus_len); | |
| 444 *output_len = modulus_len; | |
| 445 return SECSuccess; | |
| 446 | |
| 447 failure: | |
| 448 if (formatted.data != NULL) | |
| 449 PORT_ZFree(formatted.data, modulus_len); | |
| 450 return SECFailure; | |
| 451 } | |
| 452 | |
| 453 /* XXX Doesn't set error code */ | |
| 454 SECStatus | |
| 455 RSA_DecryptBlock(NSSLOWKEYPrivateKey *key, | |
| 456 unsigned char * output, | |
| 457 unsigned int * output_len, | |
| 458 unsigned int max_output_len, | |
| 459 unsigned char * input, | |
| 460 unsigned int input_len) | |
| 461 { | |
| 462 SECStatus rv; | |
| 463 unsigned int modulus_len = nsslowkey_PrivateModulusLen(key); | |
| 464 unsigned int i; | |
| 465 unsigned char * buffer; | |
| 466 | |
| 467 PORT_Assert(key->keyType == NSSLOWKEYRSAKey); | |
| 468 if (key->keyType != NSSLOWKEYRSAKey) | |
| 469 goto failure; | |
| 470 if (input_len != modulus_len) | |
| 471 goto failure; | |
| 472 | |
| 473 buffer = (unsigned char *)PORT_Alloc(modulus_len + 1); | |
| 474 if (!buffer) | |
| 475 goto failure; | |
| 476 | |
| 477 rv = RSA_PrivateKeyOp(&key->u.rsa, buffer, input); | |
| 478 if (rv != SECSuccess) { | |
| 479 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { | |
| 480 sftk_fatalError = PR_TRUE; | |
| 481 } | |
| 482 goto loser; | |
| 483 } | |
| 484 | |
| 485 if (buffer[0] != 0 || buffer[1] != 2) | |
| 486 goto loser; | |
| 487 *output_len = 0; | |
| 488 for (i = 2; i < modulus_len; i++) { | |
| 489 if (buffer[i] == 0) { | |
| 490 *output_len = modulus_len - i - 1; | |
| 491 break; | |
| 492 } | |
| 493 } | |
| 494 if (*output_len == 0) | |
| 495 goto loser; | |
| 496 if (*output_len > max_output_len) | |
| 497 goto loser; | |
| 498 | |
| 499 PORT_Memcpy(output, buffer + modulus_len - *output_len, *output_len); | |
| 500 | |
| 501 PORT_Free(buffer); | |
| 502 return SECSuccess; | |
| 503 | |
| 504 loser: | |
| 505 PORT_Free(buffer); | |
| 506 failure: | |
| 507 return SECFailure; | |
| 508 } | |
| 509 | |
| 510 /* XXX Doesn't set error code */ | |
| 511 /* | |
| 512 * added to make pkcs #11 happy | |
| 513 * RAW is RSA_X_509 | |
| 514 */ | |
| 515 SECStatus | |
| 516 RSA_SignRaw(NSSLOWKEYPrivateKey *key, | |
| 517 unsigned char * output, | |
| 518 unsigned int * output_len, | |
| 519 unsigned int maxOutputLen, | |
| 520 unsigned char * input, | |
| 521 unsigned int input_len) | |
| 522 { | |
| 523 SECStatus rv = SECSuccess; | |
| 524 unsigned int modulus_len = nsslowkey_PrivateModulusLen(key); | |
| 525 SECItem formatted; | |
| 526 SECItem unformatted; | |
| 527 | |
| 528 if (maxOutputLen < modulus_len) | |
| 529 return SECFailure; | |
| 530 PORT_Assert(key->keyType == NSSLOWKEYRSAKey); | |
| 531 if (key->keyType != NSSLOWKEYRSAKey) | |
| 532 return SECFailure; | |
| 533 | |
| 534 unformatted.len = input_len; | |
| 535 unformatted.data = input; | |
| 536 formatted.data = NULL; | |
| 537 rv = rsa_FormatBlock(&formatted, modulus_len, RSA_BlockRaw, &unformatted); | |
| 538 if (rv != SECSuccess) | |
| 539 goto done; | |
| 540 | |
| 541 rv = RSA_PrivateKeyOpDoubleChecked(&key->u.rsa, output, formatted.data); | |
| 542 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { | |
| 543 sftk_fatalError = PR_TRUE; | |
| 544 } | |
| 545 *output_len = modulus_len; | |
| 546 | |
| 547 done: | |
| 548 if (formatted.data != NULL) | |
| 549 PORT_ZFree(formatted.data, modulus_len); | |
| 550 return rv; | |
| 551 } | |
| 552 | |
| 553 /* XXX Doesn't set error code */ | |
| 554 SECStatus | |
| 555 RSA_CheckSignRaw(NSSLOWKEYPublicKey *key, | |
| 556 unsigned char * sign, | |
| 557 unsigned int sign_len, | |
| 558 unsigned char * hash, | |
| 559 unsigned int hash_len) | |
| 560 { | |
| 561 SECStatus rv; | |
| 562 unsigned int modulus_len = nsslowkey_PublicModulusLen(key); | |
| 563 unsigned char * buffer; | |
| 564 | |
| 565 if (sign_len != modulus_len) | |
| 566 goto failure; | |
| 567 if (hash_len > modulus_len) | |
| 568 goto failure; | |
| 569 PORT_Assert(key->keyType == NSSLOWKEYRSAKey); | |
| 570 if (key->keyType != NSSLOWKEYRSAKey) | |
| 571 goto failure; | |
| 572 | |
| 573 buffer = (unsigned char *)PORT_Alloc(modulus_len + 1); | |
| 574 if (!buffer) | |
| 575 goto failure; | |
| 576 | |
| 577 rv = RSA_PublicKeyOp(&key->u.rsa, buffer, sign); | |
| 578 if (rv != SECSuccess) | |
| 579 goto loser; | |
| 580 | |
| 581 /* | |
| 582 * make sure we get the same results | |
| 583 */ | |
| 584 /* NOTE: should we verify the leading zeros? */ | |
| 585 if (PORT_Memcmp(buffer + (modulus_len-hash_len), hash, hash_len) != 0) | |
| 586 goto loser; | |
| 587 | |
| 588 PORT_Free(buffer); | |
| 589 return SECSuccess; | |
| 590 | |
| 591 loser: | |
| 592 PORT_Free(buffer); | |
| 593 failure: | |
| 594 return SECFailure; | |
| 595 } | |
| 596 | |
| 597 /* XXX Doesn't set error code */ | |
| 598 SECStatus | |
| 599 RSA_CheckSignRecoverRaw(NSSLOWKEYPublicKey *key, | |
| 600 unsigned char * data, | |
| 601 unsigned int * data_len, | |
| 602 unsigned int max_output_len, | |
| 603 unsigned char * sign, | |
| 604 unsigned int sign_len) | |
| 605 { | |
| 606 SECStatus rv; | |
| 607 unsigned int modulus_len = nsslowkey_PublicModulusLen(key); | |
| 608 | |
| 609 if (sign_len != modulus_len) | |
| 610 goto failure; | |
| 611 if (max_output_len < modulus_len) | |
| 612 goto failure; | |
| 613 PORT_Assert(key->keyType == NSSLOWKEYRSAKey); | |
| 614 if (key->keyType != NSSLOWKEYRSAKey) | |
| 615 goto failure; | |
| 616 | |
| 617 rv = RSA_PublicKeyOp(&key->u.rsa, data, sign); | |
| 618 if (rv != SECSuccess) | |
| 619 goto failure; | |
| 620 | |
| 621 *data_len = modulus_len; | |
| 622 return SECSuccess; | |
| 623 | |
| 624 failure: | |
| 625 return SECFailure; | |
| 626 } | |
| 627 | |
| 628 | |
| 629 /* XXX Doesn't set error code */ | |
| 630 SECStatus | |
| 631 RSA_EncryptRaw(NSSLOWKEYPublicKey *key, | |
| 632 unsigned char * output, | |
| 633 unsigned int * output_len, | |
| 634 unsigned int max_output_len, | |
| 635 unsigned char * input, | |
| 636 unsigned int input_len) | |
| 637 { | |
| 638 SECStatus rv; | |
| 639 unsigned int modulus_len = nsslowkey_PublicModulusLen(key); | |
| 640 SECItem formatted; | |
| 641 SECItem unformatted; | |
| 642 | |
| 643 formatted.data = NULL; | |
| 644 if (max_output_len < modulus_len) | |
| 645 goto failure; | |
| 646 PORT_Assert(key->keyType == NSSLOWKEYRSAKey); | |
| 647 if (key->keyType != NSSLOWKEYRSAKey) | |
| 648 goto failure; | |
| 649 | |
| 650 unformatted.len = input_len; | |
| 651 unformatted.data = input; | |
| 652 formatted.data = NULL; | |
| 653 rv = rsa_FormatBlock(&formatted, modulus_len, RSA_BlockRaw, &unformatted); | |
| 654 if (rv != SECSuccess) | |
| 655 goto failure; | |
| 656 | |
| 657 rv = RSA_PublicKeyOp(&key->u.rsa, output, formatted.data); | |
| 658 if (rv != SECSuccess) | |
| 659 goto failure; | |
| 660 | |
| 661 PORT_ZFree(formatted.data, modulus_len); | |
| 662 *output_len = modulus_len; | |
| 663 return SECSuccess; | |
| 664 | |
| 665 failure: | |
| 666 if (formatted.data != NULL) | |
| 667 PORT_ZFree(formatted.data, modulus_len); | |
| 668 return SECFailure; | |
| 669 } | |
| 670 | |
| 671 /* XXX Doesn't set error code */ | |
| 672 SECStatus | |
| 673 RSA_DecryptRaw(NSSLOWKEYPrivateKey *key, | |
| 674 unsigned char * output, | |
| 675 unsigned int * output_len, | |
| 676 unsigned int max_output_len, | |
| 677 unsigned char * input, | |
| 678 unsigned int input_len) | |
| 679 { | |
| 680 SECStatus rv; | |
| 681 unsigned int modulus_len = nsslowkey_PrivateModulusLen(key); | |
| 682 | |
| 683 if (modulus_len <= 0) | |
| 684 goto failure; | |
| 685 if (modulus_len > max_output_len) | |
| 686 goto failure; | |
| 687 PORT_Assert(key->keyType == NSSLOWKEYRSAKey); | |
| 688 if (key->keyType != NSSLOWKEYRSAKey) | |
| 689 goto failure; | |
| 690 if (input_len != modulus_len) | |
| 691 goto failure; | |
| 692 | |
| 693 rv = RSA_PrivateKeyOp(&key->u.rsa, output, input); | |
| 694 if (rv != SECSuccess) { | |
| 695 if (PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { | |
| 696 sftk_fatalError = PR_TRUE; | |
| 697 } | |
| 698 goto failure; | |
| 699 } | |
| 700 | |
| 701 *output_len = modulus_len; | |
| 702 return SECSuccess; | |
| 703 | |
| 704 failure: | |
| 705 return SECFailure; | |
| 706 } | |
| 707 | |
| 708 /* | |
| 709 * Mask generation function MGF1 as defined in PKCS #1 v2.1 / RFC 3447. | |
| 710 */ | |
| 711 static SECStatus | |
| 712 MGF1(HASH_HashType hashAlg, unsigned char *mask, unsigned int maskLen, | |
| 713 const unsigned char *mgfSeed, unsigned int mgfSeedLen) | |
| 714 { | |
| 715 unsigned int digestLen; | |
| 716 PRUint32 counter, rounds; | |
| 717 unsigned char *tempHash, *temp; | |
| 718 const SECHashObject *hash; | |
| 719 void *hashContext; | |
| 720 unsigned char C[4]; | |
| 721 | |
| 722 hash = HASH_GetRawHashObject(hashAlg); | |
| 723 if (hash == NULL) | |
| 724 return SECFailure; | |
| 725 | |
| 726 hashContext = (*hash->create)(); | |
| 727 rounds = (maskLen + hash->length - 1) / hash->length; | |
| 728 for (counter = 0; counter < rounds; counter++) { | |
| 729 C[0] = (unsigned char)((counter >> 24) & 0xff); | |
| 730 C[1] = (unsigned char)((counter >> 16) & 0xff); | |
| 731 C[2] = (unsigned char)((counter >> 8) & 0xff); | |
| 732 C[3] = (unsigned char)(counter & 0xff); | |
| 733 | |
| 734 /* This could be optimized when the clone functions in | |
| 735 * rawhash.c are implemented. */ | |
| 736 (*hash->begin)(hashContext); | |
| 737 (*hash->update)(hashContext, mgfSeed, mgfSeedLen); | |
| 738 (*hash->update)(hashContext, C, sizeof C); | |
| 739 | |
| 740 tempHash = mask + counter * hash->length; | |
| 741 if (counter != (rounds-1)) { | |
| 742 (*hash->end)(hashContext, tempHash, &digestLen, hash->length); | |
| 743 } else { /* we're in the last round and need to cut the hash */ | |
| 744 temp = PORT_Alloc(hash->length); | |
| 745 (*hash->end)(hashContext, temp, &digestLen, hash->length); | |
| 746 PORT_Memcpy(tempHash, temp, maskLen - counter * hash->length); | |
| 747 PORT_Free(temp); | |
| 748 } | |
| 749 } | |
| 750 (*hash->destroy)(hashContext, PR_TRUE); | |
| 751 | |
| 752 return SECSuccess; | |
| 753 } | |
| 754 | |
| 755 /* | |
| 756 * Decodes an EME-OAEP encoded block, validating the encoding in constant | |
| 757 * time. | |
| 758 * Described in RFC 3447, section 7.1.2. | |
| 759 * input contains the encoded block, after decryption. | |
| 760 * label is the optional value L that was associated with the message. | |
| 761 * On success, the original message and message length will be stored in | |
| 762 * output and outputLen. | |
| 763 */ | |
| 764 static SECStatus | |
| 765 eme_oaep_decode(unsigned char *output, unsigned int *outputLen, | |
| 766 unsigned int maxOutputLen, | |
| 767 const unsigned char *input, unsigned int inputLen, | |
| 768 HASH_HashType hashAlg, HASH_HashType maskHashAlg, | |
| 769 const unsigned char *label, unsigned int labelLen) | |
| 770 { | |
| 771 const SECHashObject *hash; | |
| 772 void *hashContext; | |
| 773 SECStatus rv = SECFailure; | |
| 774 unsigned char labelHash[HASH_LENGTH_MAX]; | |
| 775 unsigned int i, maskLen, paddingOffset; | |
| 776 unsigned char *mask = NULL, *tmpOutput = NULL; | |
| 777 unsigned char isGood, foundPaddingEnd; | |
| 778 | |
| 779 hash = HASH_GetRawHashObject(hashAlg); | |
| 780 | |
| 781 /* 1.c */ | |
| 782 if (inputLen < (hash->length * 2) + 2) { | |
| 783 PORT_SetError(SEC_ERROR_INPUT_LEN); | |
| 784 return SECFailure; | |
| 785 } | |
| 786 | |
| 787 /* Step 3.a - Generate lHash */ | |
| 788 hashContext = (*hash->create)(); | |
| 789 if (hashContext == NULL) { | |
| 790 PORT_SetError(SEC_ERROR_NO_MEMORY); | |
| 791 return SECFailure; | |
| 792 } | |
| 793 (*hash->begin)(hashContext); | |
| 794 if (labelLen > 0) | |
| 795 (*hash->update)(hashContext, label, labelLen); | |
| 796 (*hash->end)(hashContext, labelHash, &i, sizeof(labelHash)); | |
| 797 (*hash->destroy)(hashContext, PR_TRUE); | |
| 798 | |
| 799 tmpOutput = (unsigned char*)PORT_Alloc(inputLen); | |
| 800 if (tmpOutput == NULL) { | |
| 801 PORT_SetError(SEC_ERROR_NO_MEMORY); | |
| 802 goto done; | |
| 803 } | |
| 804 | |
| 805 maskLen = inputLen - hash->length - 1; | |
| 806 mask = (unsigned char*)PORT_Alloc(maskLen); | |
| 807 if (mask == NULL) { | |
| 808 PORT_SetError(SEC_ERROR_NO_MEMORY); | |
| 809 goto done; | |
| 810 } | |
| 811 | |
| 812 PORT_Memcpy(tmpOutput, input, inputLen); | |
| 813 | |
| 814 /* 3.c - Generate seedMask */ | |
| 815 MGF1(maskHashAlg, mask, hash->length, &tmpOutput[1 + hash->length], | |
| 816 inputLen - hash->length - 1); | |
| 817 /* 3.d - Unmask seed */ | |
| 818 for (i = 0; i < hash->length; ++i) | |
| 819 tmpOutput[1 + i] ^= mask[i]; | |
| 820 | |
| 821 /* 3.e - Generate dbMask */ | |
| 822 MGF1(maskHashAlg, mask, maskLen, &tmpOutput[1], hash->length); | |
| 823 /* 3.f - Unmask DB */ | |
| 824 for (i = 0; i < maskLen; ++i) | |
| 825 tmpOutput[1 + hash->length + i] ^= mask[i]; | |
| 826 | |
| 827 /* 3.g - Compare Y, lHash, and PS in constant time | |
| 828 * Warning: This code is timing dependent and must not disclose which of | |
| 829 * these were invalid. | |
| 830 */ | |
| 831 paddingOffset = 0; | |
| 832 isGood = 1; | |
| 833 foundPaddingEnd = 0; | |
| 834 | |
| 835 /* Compare Y */ | |
| 836 isGood &= constantTimeEQ8(0x00, tmpOutput[0]); | |
| 837 | |
| 838 /* Compare lHash and lHash' */ | |
| 839 isGood &= constantTimeCompare(&labelHash[0], | |
| 840 &tmpOutput[1 + hash->length], | |
| 841 hash->length); | |
| 842 | |
| 843 /* Compare that the padding is zero or more zero octets, followed by a | |
| 844 * 0x01 octet */ | |
| 845 for (i = 1 + (hash->length * 2); i < inputLen; ++i) { | |
| 846 unsigned char isZero = constantTimeEQ8(0x00, tmpOutput[i]); | |
| 847 unsigned char isOne = constantTimeEQ8(0x01, tmpOutput[i]); | |
| 848 /* non-constant time equivalent: | |
| 849 * if (tmpOutput[i] == 0x01 && !foundPaddingEnd) | |
| 850 * paddingOffset = i; | |
| 851 */ | |
| 852 paddingOffset = constantTimeCondition(isOne & ~foundPaddingEnd, i, | |
| 853 paddingOffset); | |
| 854 /* non-constant time equivalent: | |
| 855 * if (tmpOutput[i] == 0x01) | |
| 856 * foundPaddingEnd = true; | |
| 857 * | |
| 858 * Note: This may yield false positives, as it will be set whenever | |
| 859 * a 0x01 byte is encountered. If there was bad padding (eg: | |
| 860 * 0x03 0x02 0x01), foundPaddingEnd will still be set to true, and | |
| 861 * paddingOffset will still be set to 2. | |
| 862 */ | |
| 863 foundPaddingEnd = constantTimeCondition(isOne, 1, foundPaddingEnd); | |
| 864 /* non-constant time equivalent: | |
| 865 * if (tmpOutput[i] != 0x00 && tmpOutput[i] != 0x01 && | |
| 866 * !foundPaddingEnd) { | |
| 867 * isGood = false; | |
| 868 * } | |
| 869 * | |
| 870 * Note: This may yield false positives, as a message (and padding) | |
| 871 * that is entirely zeros will result in isGood still being true. Thus | |
| 872 * it's necessary to check foundPaddingEnd is positive below. | |
| 873 */ | |
| 874 isGood = constantTimeCondition(~foundPaddingEnd & ~isZero, 0, isGood); | |
| 875 } | |
| 876 | |
| 877 /* While both isGood and foundPaddingEnd may have false positives, they | |
| 878 * cannot BOTH have false positives. If both are not true, then an invalid | |
| 879 * message was received. Note, this comparison must still be done in constan
t | |
| 880 * time so as not to leak either condition. | |
| 881 */ | |
| 882 if (!(isGood & foundPaddingEnd)) { | |
| 883 PORT_SetError(SEC_ERROR_BAD_DATA); | |
| 884 goto done; | |
| 885 } | |
| 886 | |
| 887 /* End timing dependent code */ | |
| 888 | |
| 889 ++paddingOffset; /* Skip the 0x01 following the end of PS */ | |
| 890 | |
| 891 *outputLen = inputLen - paddingOffset; | |
| 892 if (*outputLen > maxOutputLen) { | |
| 893 PORT_SetError(SEC_ERROR_OUTPUT_LEN); | |
| 894 goto done; | |
| 895 } | |
| 896 | |
| 897 if (*outputLen) | |
| 898 PORT_Memcpy(output, &tmpOutput[paddingOffset], *outputLen); | |
| 899 rv = SECSuccess; | |
| 900 | |
| 901 done: | |
| 902 if (mask) | |
| 903 PORT_ZFree(mask, maskLen); | |
| 904 if (tmpOutput) | |
| 905 PORT_ZFree(tmpOutput, inputLen); | |
| 906 return rv; | |
| 907 } | |
| 908 | |
| 909 /* | |
| 910 * Generate an EME-OAEP encoded block for encryption | |
| 911 * Described in RFC 3447, section 7.1.1 | |
| 912 * We use input instead of M for the message to be encrypted | |
| 913 * label is the optional value L to be associated with the message. | |
| 914 */ | |
| 915 static SECStatus | |
| 916 eme_oaep_encode(unsigned char *em, unsigned int emLen, | |
| 917 const unsigned char *input, unsigned int inputLen, | |
| 918 HASH_HashType hashAlg, HASH_HashType maskHashAlg, | |
| 919 const unsigned char *label, unsigned int labelLen) | |
| 920 { | |
| 921 const SECHashObject *hash; | |
| 922 void *hashContext; | |
| 923 SECStatus rv; | |
| 924 unsigned char *mask; | |
| 925 unsigned int reservedLen, dbMaskLen, i; | |
| 926 | |
| 927 hash = HASH_GetRawHashObject(hashAlg); | |
| 928 | |
| 929 /* Step 1.b */ | |
| 930 reservedLen = (2 * hash->length) + 2; | |
| 931 if (emLen < reservedLen || inputLen > (emLen - reservedLen)) { | |
| 932 PORT_SetError(SEC_ERROR_INPUT_LEN); | |
| 933 return SECFailure; | |
| 934 } | |
| 935 | |
| 936 /* | |
| 937 * From RFC 3447, Section 7.1 | |
| 938 * +----------+---------+-------+ | |
| 939 * DB = | lHash | PS | M | | |
| 940 * +----------+---------+-------+ | |
| 941 * | | |
| 942 * +----------+ V | |
| 943 * | seed |--> MGF ---> xor | |
| 944 * +----------+ | | |
| 945 * | | | |
| 946 * +--+ V | | |
| 947 * |00| xor <----- MGF <-----| | |
| 948 * +--+ | | | |
| 949 * | | | | |
| 950 * V V V | |
| 951 * +--+----------+----------------------------+ | |
| 952 * EM = |00|maskedSeed| maskedDB | | |
| 953 * +--+----------+----------------------------+ | |
| 954 * | |
| 955 * We use mask to hold the result of the MGF functions, and all other | |
| 956 * values are generated in their final resting place. | |
| 957 */ | |
| 958 *em = 0x00; | |
| 959 | |
| 960 /* Step 2.a - Generate lHash */ | |
| 961 hashContext = (*hash->create)(); | |
| 962 if (hashContext == NULL) { | |
| 963 PORT_SetError(SEC_ERROR_NO_MEMORY); | |
| 964 return SECFailure; | |
| 965 } | |
| 966 (*hash->begin)(hashContext); | |
| 967 if (labelLen > 0) | |
| 968 (*hash->update)(hashContext, label, labelLen); | |
| 969 (*hash->end)(hashContext, &em[1 + hash->length], &i, hash->length); | |
| 970 (*hash->destroy)(hashContext, PR_TRUE); | |
| 971 | |
| 972 /* Step 2.b - Generate PS */ | |
| 973 if (emLen - reservedLen - inputLen > 0) { | |
| 974 PORT_Memset(em + 1 + (hash->length * 2), 0x00, | |
| 975 emLen - reservedLen - inputLen); | |
| 976 } | |
| 977 | |
| 978 /* Step 2.c. - Generate DB | |
| 979 * DB = lHash || PS || 0x01 || M | |
| 980 * Note that PS and lHash have already been placed into em at their | |
| 981 * appropriate offsets. This just copies M into place | |
| 982 */ | |
| 983 em[emLen - inputLen - 1] = 0x01; | |
| 984 if (inputLen) | |
| 985 PORT_Memcpy(em + emLen - inputLen, input, inputLen); | |
| 986 | |
| 987 /* Step 2.d - Generate seed */ | |
| 988 rv = RNG_GenerateGlobalRandomBytes(em + 1, hash->length); | |
| 989 if (rv != SECSuccess) { | |
| 990 return rv; | |
| 991 } | |
| 992 | |
| 993 /* Step 2.e - Generate dbMask*/ | |
| 994 dbMaskLen = emLen - hash->length - 1; | |
| 995 mask = (unsigned char*)PORT_Alloc(dbMaskLen); | |
| 996 if (mask == NULL) { | |
| 997 PORT_SetError(SEC_ERROR_NO_MEMORY); | |
| 998 return SECFailure; | |
| 999 } | |
| 1000 MGF1(maskHashAlg, mask, dbMaskLen, em + 1, hash->length); | |
| 1001 /* Step 2.f - Compute maskedDB*/ | |
| 1002 for (i = 0; i < dbMaskLen; ++i) | |
| 1003 em[1 + hash->length + i] ^= mask[i]; | |
| 1004 | |
| 1005 /* Step 2.g - Generate seedMask */ | |
| 1006 MGF1(maskHashAlg, mask, hash->length, &em[1 + hash->length], dbMaskLen); | |
| 1007 /* Step 2.h - Compute maskedSeed */ | |
| 1008 for (i = 0; i < hash->length; ++i) | |
| 1009 em[1 + i] ^= mask[i]; | |
| 1010 | |
| 1011 PORT_ZFree(mask, dbMaskLen); | |
| 1012 return SECSuccess; | |
| 1013 } | |
| 1014 | |
| 1015 /* | |
| 1016 * Encode a RSA-PSS signature. | |
| 1017 * Described in RFC 3447, section 9.1.1. | |
| 1018 * We use mHash instead of M as input. | |
| 1019 * emBits from the RFC is just modBits - 1, see section 8.1.1. | |
| 1020 * We only support MGF1 as the MGF. | |
| 1021 * | |
| 1022 * NOTE: this code assumes modBits is a multiple of 8. | |
| 1023 */ | |
| 1024 static SECStatus | |
| 1025 emsa_pss_encode(unsigned char *em, unsigned int emLen, | |
| 1026 const unsigned char *mHash, HASH_HashType hashAlg, | |
| 1027 HASH_HashType maskHashAlg, unsigned int sLen) | |
| 1028 { | |
| 1029 const SECHashObject *hash; | |
| 1030 void *hash_context; | |
| 1031 unsigned char *dbMask; | |
| 1032 unsigned int dbMaskLen, i; | |
| 1033 SECStatus rv; | |
| 1034 | |
| 1035 hash = HASH_GetRawHashObject(hashAlg); | |
| 1036 dbMaskLen = emLen - hash->length - 1; | |
| 1037 | |
| 1038 /* Step 3 */ | |
| 1039 if (emLen < hash->length + sLen + 2) { | |
| 1040 PORT_SetError(SEC_ERROR_OUTPUT_LEN); | |
| 1041 return SECFailure; | |
| 1042 } | |
| 1043 | |
| 1044 /* Step 4 */ | |
| 1045 rv = RNG_GenerateGlobalRandomBytes(&em[dbMaskLen - sLen], sLen); | |
| 1046 if (rv != SECSuccess) { | |
| 1047 return rv; | |
| 1048 } | |
| 1049 | |
| 1050 /* Step 5 + 6 */ | |
| 1051 /* Compute H and store it at its final location &em[dbMaskLen]. */ | |
| 1052 hash_context = (*hash->create)(); | |
| 1053 if (hash_context == NULL) { | |
| 1054 PORT_SetError(SEC_ERROR_NO_MEMORY); | |
| 1055 return SECFailure; | |
| 1056 } | |
| 1057 (*hash->begin)(hash_context); | |
| 1058 (*hash->update)(hash_context, eightZeros, 8); | |
| 1059 (*hash->update)(hash_context, mHash, hash->length); | |
| 1060 (*hash->update)(hash_context, &em[dbMaskLen - sLen], sLen); | |
| 1061 (*hash->end)(hash_context, &em[dbMaskLen], &i, hash->length); | |
| 1062 (*hash->destroy)(hash_context, PR_TRUE); | |
| 1063 | |
| 1064 /* Step 7 + 8 */ | |
| 1065 PORT_Memset(em, 0, dbMaskLen - sLen - 1); | |
| 1066 em[dbMaskLen - sLen - 1] = 0x01; | |
| 1067 | |
| 1068 /* Step 9 */ | |
| 1069 dbMask = (unsigned char *)PORT_Alloc(dbMaskLen); | |
| 1070 if (dbMask == NULL) { | |
| 1071 PORT_SetError(SEC_ERROR_NO_MEMORY); | |
| 1072 return SECFailure; | |
| 1073 } | |
| 1074 MGF1(maskHashAlg, dbMask, dbMaskLen, &em[dbMaskLen], hash->length); | |
| 1075 | |
| 1076 /* Step 10 */ | |
| 1077 for (i = 0; i < dbMaskLen; i++) | |
| 1078 em[i] ^= dbMask[i]; | |
| 1079 PORT_Free(dbMask); | |
| 1080 | |
| 1081 /* Step 11 */ | |
| 1082 em[0] &= 0x7f; | |
| 1083 | |
| 1084 /* Step 12 */ | |
| 1085 em[emLen - 1] = 0xbc; | |
| 1086 | |
| 1087 return SECSuccess; | |
| 1088 } | |
| 1089 | |
| 1090 /* | |
| 1091 * Verify a RSA-PSS signature. | |
| 1092 * Described in RFC 3447, section 9.1.2. | |
| 1093 * We use mHash instead of M as input. | |
| 1094 * emBits from the RFC is just modBits - 1, see section 8.1.2. | |
| 1095 * We only support MGF1 as the MGF. | |
| 1096 * | |
| 1097 * NOTE: this code assumes modBits is a multiple of 8. | |
| 1098 */ | |
| 1099 static SECStatus | |
| 1100 emsa_pss_verify(const unsigned char *mHash, | |
| 1101 const unsigned char *em, unsigned int emLen, | |
| 1102 HASH_HashType hashAlg, HASH_HashType maskHashAlg, | |
| 1103 unsigned int sLen) | |
| 1104 { | |
| 1105 const SECHashObject *hash; | |
| 1106 void *hash_context; | |
| 1107 unsigned char *db; | |
| 1108 unsigned char *H_; /* H' from the RFC */ | |
| 1109 unsigned int i, dbMaskLen; | |
| 1110 SECStatus rv; | |
| 1111 | |
| 1112 hash = HASH_GetRawHashObject(hashAlg); | |
| 1113 dbMaskLen = emLen - hash->length - 1; | |
| 1114 | |
| 1115 /* Step 3 + 4 + 6 */ | |
| 1116 if ((emLen < (hash->length + sLen + 2)) || | |
| 1117 (em[emLen - 1] != 0xbc) || | |
| 1118 ((em[0] & 0x80) != 0)) { | |
| 1119 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); | |
| 1120 return SECFailure; | |
| 1121 } | |
| 1122 | |
| 1123 /* Step 7 */ | |
| 1124 db = (unsigned char *)PORT_Alloc(dbMaskLen); | |
| 1125 if (db == NULL) { | |
| 1126 PORT_SetError(SEC_ERROR_NO_MEMORY); | |
| 1127 return SECFailure; | |
| 1128 } | |
| 1129 /* &em[dbMaskLen] points to H, used as mgfSeed */ | |
| 1130 MGF1(maskHashAlg, db, dbMaskLen, &em[dbMaskLen], hash->length); | |
| 1131 | |
| 1132 /* Step 8 */ | |
| 1133 for (i = 0; i < dbMaskLen; i++) { | |
| 1134 db[i] ^= em[i]; | |
| 1135 } | |
| 1136 | |
| 1137 /* Step 9 */ | |
| 1138 db[0] &= 0x7f; | |
| 1139 | |
| 1140 /* Step 10 */ | |
| 1141 for (i = 0; i < (dbMaskLen - sLen - 1); i++) { | |
| 1142 if (db[i] != 0) { | |
| 1143 PORT_Free(db); | |
| 1144 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); | |
| 1145 return SECFailure; | |
| 1146 } | |
| 1147 } | |
| 1148 if (db[dbMaskLen - sLen - 1] != 0x01) { | |
| 1149 PORT_Free(db); | |
| 1150 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); | |
| 1151 return SECFailure; | |
| 1152 } | |
| 1153 | |
| 1154 /* Step 12 + 13 */ | |
| 1155 H_ = (unsigned char *)PORT_Alloc(hash->length); | |
| 1156 if (H_ == NULL) { | |
| 1157 PORT_Free(db); | |
| 1158 PORT_SetError(SEC_ERROR_NO_MEMORY); | |
| 1159 return SECFailure; | |
| 1160 } | |
| 1161 hash_context = (*hash->create)(); | |
| 1162 if (hash_context == NULL) { | |
| 1163 PORT_Free(db); | |
| 1164 PORT_Free(H_); | |
| 1165 PORT_SetError(SEC_ERROR_NO_MEMORY); | |
| 1166 return SECFailure; | |
| 1167 } | |
| 1168 (*hash->begin)(hash_context); | |
| 1169 (*hash->update)(hash_context, eightZeros, 8); | |
| 1170 (*hash->update)(hash_context, mHash, hash->length); | |
| 1171 (*hash->update)(hash_context, &db[dbMaskLen - sLen], sLen); | |
| 1172 (*hash->end)(hash_context, H_, &i, hash->length); | |
| 1173 (*hash->destroy)(hash_context, PR_TRUE); | |
| 1174 | |
| 1175 PORT_Free(db); | |
| 1176 | |
| 1177 /* Step 14 */ | |
| 1178 if (PORT_Memcmp(H_, &em[dbMaskLen], hash->length) != 0) { | |
| 1179 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); | |
| 1180 rv = SECFailure; | |
| 1181 } else { | |
| 1182 rv = SECSuccess; | |
| 1183 } | |
| 1184 | |
| 1185 PORT_Free(H_); | |
| 1186 return rv; | |
| 1187 } | |
| 1188 | |
| 1189 static HASH_HashType | |
| 1190 GetHashTypeFromMechanism(CK_MECHANISM_TYPE mech) | |
| 1191 { | |
| 1192 switch (mech) { | |
| 1193 case CKM_SHA_1: | |
| 1194 case CKG_MGF1_SHA1: | |
| 1195 return HASH_AlgSHA1; | |
| 1196 case CKM_SHA224: | |
| 1197 case CKG_MGF1_SHA224: | |
| 1198 return HASH_AlgSHA224; | |
| 1199 case CKM_SHA256: | |
| 1200 case CKG_MGF1_SHA256: | |
| 1201 return HASH_AlgSHA256; | |
| 1202 case CKM_SHA384: | |
| 1203 case CKG_MGF1_SHA384: | |
| 1204 return HASH_AlgSHA384; | |
| 1205 case CKM_SHA512: | |
| 1206 case CKG_MGF1_SHA512: | |
| 1207 return HASH_AlgSHA512; | |
| 1208 default: | |
| 1209 return HASH_AlgNULL; | |
| 1210 } | |
| 1211 } | |
| 1212 | |
| 1213 /* MGF1 is the only supported MGF. */ | |
| 1214 SECStatus | |
| 1215 RSA_CheckSignPSS(CK_RSA_PKCS_PSS_PARAMS *pss_params, | |
| 1216 NSSLOWKEYPublicKey *key, | |
| 1217 const unsigned char *sign, unsigned int sign_len, | |
| 1218 const unsigned char *hash, unsigned int hash_len) | |
| 1219 { | |
| 1220 HASH_HashType hashAlg; | |
| 1221 HASH_HashType maskHashAlg; | |
| 1222 SECStatus rv; | |
| 1223 unsigned int modulus_len = nsslowkey_PublicModulusLen(key); | |
| 1224 unsigned char *buffer; | |
| 1225 | |
| 1226 if (sign_len != modulus_len) { | |
| 1227 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); | |
| 1228 return SECFailure; | |
| 1229 } | |
| 1230 | |
| 1231 hashAlg = GetHashTypeFromMechanism(pss_params->hashAlg); | |
| 1232 maskHashAlg = GetHashTypeFromMechanism(pss_params->mgf); | |
| 1233 if ((hashAlg == HASH_AlgNULL) || (maskHashAlg == HASH_AlgNULL)) { | |
| 1234 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | |
| 1235 return SECFailure; | |
| 1236 } | |
| 1237 | |
| 1238 buffer = (unsigned char *)PORT_Alloc(modulus_len); | |
| 1239 if (!buffer) { | |
| 1240 PORT_SetError(SEC_ERROR_NO_MEMORY); | |
| 1241 return SECFailure; | |
| 1242 } | |
| 1243 | |
| 1244 rv = RSA_PublicKeyOp(&key->u.rsa, buffer, sign); | |
| 1245 if (rv != SECSuccess) { | |
| 1246 PORT_Free(buffer); | |
| 1247 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); | |
| 1248 return SECFailure; | |
| 1249 } | |
| 1250 | |
| 1251 rv = emsa_pss_verify(hash, buffer, modulus_len, hashAlg, | |
| 1252 maskHashAlg, pss_params->sLen); | |
| 1253 PORT_Free(buffer); | |
| 1254 | |
| 1255 return rv; | |
| 1256 } | |
| 1257 | |
| 1258 /* MGF1 is the only supported MGF. */ | |
| 1259 SECStatus | |
| 1260 RSA_SignPSS(CK_RSA_PKCS_PSS_PARAMS *pss_params, NSSLOWKEYPrivateKey *key, | |
| 1261 unsigned char *output, unsigned int *output_len, | |
| 1262 unsigned int max_output_len, | |
| 1263 const unsigned char *input, unsigned int input_len) | |
| 1264 { | |
| 1265 SECStatus rv = SECSuccess; | |
| 1266 unsigned int modulus_len = nsslowkey_PrivateModulusLen(key); | |
| 1267 unsigned char *pss_encoded = NULL; | |
| 1268 HASH_HashType hashAlg; | |
| 1269 HASH_HashType maskHashAlg; | |
| 1270 | |
| 1271 if (max_output_len < modulus_len) { | |
| 1272 PORT_SetError(SEC_ERROR_OUTPUT_LEN); | |
| 1273 return SECFailure; | |
| 1274 } | |
| 1275 PORT_Assert(key->keyType == NSSLOWKEYRSAKey); | |
| 1276 if (key->keyType != NSSLOWKEYRSAKey) { | |
| 1277 PORT_SetError(SEC_ERROR_INVALID_KEY); | |
| 1278 return SECFailure; | |
| 1279 } | |
| 1280 | |
| 1281 hashAlg = GetHashTypeFromMechanism(pss_params->hashAlg); | |
| 1282 maskHashAlg = GetHashTypeFromMechanism(pss_params->mgf); | |
| 1283 if ((hashAlg == HASH_AlgNULL) || (maskHashAlg == HASH_AlgNULL)) { | |
| 1284 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | |
| 1285 return SECFailure; | |
| 1286 } | |
| 1287 | |
| 1288 pss_encoded = (unsigned char *)PORT_Alloc(modulus_len); | |
| 1289 if (pss_encoded == NULL) { | |
| 1290 PORT_SetError(SEC_ERROR_NO_MEMORY); | |
| 1291 return SECFailure; | |
| 1292 } | |
| 1293 rv = emsa_pss_encode(pss_encoded, modulus_len, input, hashAlg, | |
| 1294 maskHashAlg, pss_params->sLen); | |
| 1295 if (rv != SECSuccess) | |
| 1296 goto done; | |
| 1297 | |
| 1298 rv = RSA_PrivateKeyOpDoubleChecked(&key->u.rsa, output, pss_encoded); | |
| 1299 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { | |
| 1300 sftk_fatalError = PR_TRUE; | |
| 1301 } | |
| 1302 *output_len = modulus_len; | |
| 1303 | |
| 1304 done: | |
| 1305 PORT_Free(pss_encoded); | |
| 1306 return rv; | |
| 1307 } | |
| 1308 | |
| 1309 /* MGF1 is the only supported MGF. */ | |
| 1310 SECStatus | |
| 1311 RSA_EncryptOAEP(CK_RSA_PKCS_OAEP_PARAMS *oaepParams, | |
| 1312 NSSLOWKEYPublicKey *key, | |
| 1313 unsigned char *output, unsigned int *outputLen, | |
| 1314 unsigned int maxOutputLen, | |
| 1315 const unsigned char *input, unsigned int inputLen) | |
| 1316 { | |
| 1317 SECStatus rv = SECFailure; | |
| 1318 unsigned int modulusLen = nsslowkey_PublicModulusLen(key); | |
| 1319 unsigned char *oaepEncoded = NULL; | |
| 1320 unsigned char *sourceData = NULL; | |
| 1321 unsigned int sourceDataLen = 0; | |
| 1322 | |
| 1323 HASH_HashType hashAlg; | |
| 1324 HASH_HashType maskHashAlg; | |
| 1325 | |
| 1326 if (maxOutputLen < modulusLen) { | |
| 1327 PORT_SetError(SEC_ERROR_OUTPUT_LEN); | |
| 1328 return SECFailure; | |
| 1329 } | |
| 1330 PORT_Assert(key->keyType == NSSLOWKEYRSAKey); | |
| 1331 if (key->keyType != NSSLOWKEYRSAKey) { | |
| 1332 PORT_SetError(SEC_ERROR_INVALID_KEY); | |
| 1333 return SECFailure; | |
| 1334 } | |
| 1335 | |
| 1336 hashAlg = GetHashTypeFromMechanism(oaepParams->hashAlg); | |
| 1337 maskHashAlg = GetHashTypeFromMechanism(oaepParams->mgf); | |
| 1338 if ((hashAlg == HASH_AlgNULL) || (maskHashAlg == HASH_AlgNULL)) { | |
| 1339 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | |
| 1340 return SECFailure; | |
| 1341 } | |
| 1342 | |
| 1343 /* The PKCS#11 source parameter is the "source" of the label parameter. | |
| 1344 * The only defined source is explicitly specified, in which case, the | |
| 1345 * label is an optional byte string in pSourceData. If ulSourceDataLen is | |
| 1346 * zero, then pSourceData MUST be NULL - otherwise, it must be non-NULL. | |
| 1347 */ | |
| 1348 if (oaepParams->source != CKZ_DATA_SPECIFIED) { | |
| 1349 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | |
| 1350 return SECFailure; | |
| 1351 } | |
| 1352 sourceData = (unsigned char*)oaepParams->pSourceData; | |
| 1353 sourceDataLen = oaepParams->ulSourceDataLen; | |
| 1354 if ((sourceDataLen == 0 && sourceData != NULL) || | |
| 1355 (sourceDataLen > 0 && sourceData == NULL)) { | |
| 1356 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | |
| 1357 return SECFailure; | |
| 1358 } | |
| 1359 | |
| 1360 oaepEncoded = (unsigned char *)PORT_Alloc(modulusLen); | |
| 1361 if (oaepEncoded == NULL) { | |
| 1362 PORT_SetError(SEC_ERROR_NO_MEMORY); | |
| 1363 return SECFailure; | |
| 1364 } | |
| 1365 rv = eme_oaep_encode(oaepEncoded, modulusLen, input, inputLen, | |
| 1366 hashAlg, maskHashAlg, sourceData, sourceDataLen); | |
| 1367 if (rv != SECSuccess) | |
| 1368 goto done; | |
| 1369 | |
| 1370 rv = RSA_PublicKeyOp(&key->u.rsa, output, oaepEncoded); | |
| 1371 if (rv != SECSuccess) | |
| 1372 goto done; | |
| 1373 *outputLen = modulusLen; | |
| 1374 | |
| 1375 done: | |
| 1376 PORT_Free(oaepEncoded); | |
| 1377 return rv; | |
| 1378 } | |
| 1379 | |
| 1380 /* MGF1 is the only supported MGF. */ | |
| 1381 SECStatus | |
| 1382 RSA_DecryptOAEP(CK_RSA_PKCS_OAEP_PARAMS *oaepParams, | |
| 1383 NSSLOWKEYPrivateKey *key, | |
| 1384 unsigned char *output, unsigned int *outputLen, | |
| 1385 unsigned int maxOutputLen, | |
| 1386 const unsigned char *input, unsigned int inputLen) | |
| 1387 { | |
| 1388 SECStatus rv = SECFailure; | |
| 1389 unsigned int modulusLen = nsslowkey_PrivateModulusLen(key); | |
| 1390 unsigned char *oaepEncoded = NULL; | |
| 1391 unsigned char *sourceData = NULL; | |
| 1392 unsigned int sourceDataLen = 0; | |
| 1393 | |
| 1394 HASH_HashType hashAlg = GetHashTypeFromMechanism(oaepParams->hashAlg); | |
| 1395 HASH_HashType maskHashAlg = GetHashTypeFromMechanism(oaepParams->mgf); | |
| 1396 | |
| 1397 if ((hashAlg == HASH_AlgNULL) || (maskHashAlg == HASH_AlgNULL)) { | |
| 1398 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | |
| 1399 return SECFailure; | |
| 1400 } | |
| 1401 | |
| 1402 if (inputLen != modulusLen) { | |
| 1403 PORT_SetError(SEC_ERROR_INPUT_LEN); | |
| 1404 return SECFailure; | |
| 1405 } | |
| 1406 PORT_Assert(key->keyType == NSSLOWKEYRSAKey); | |
| 1407 if (key->keyType != NSSLOWKEYRSAKey) { | |
| 1408 PORT_SetError(SEC_ERROR_INVALID_KEY); | |
| 1409 return SECFailure; | |
| 1410 } | |
| 1411 | |
| 1412 /* The PKCS#11 source parameter is the "source" of the label parameter. | |
| 1413 * The only defined source is explicitly specified, in which case, the | |
| 1414 * label is an optional byte string in pSourceData. If ulSourceDataLen is | |
| 1415 * zero, then pSourceData MUST be NULL - otherwise, it must be non-NULL. | |
| 1416 */ | |
| 1417 if (oaepParams->source != CKZ_DATA_SPECIFIED) { | |
| 1418 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | |
| 1419 return SECFailure; | |
| 1420 } | |
| 1421 sourceData = (unsigned char*)oaepParams->pSourceData; | |
| 1422 sourceDataLen = oaepParams->ulSourceDataLen; | |
| 1423 if ((sourceDataLen == 0 && sourceData != NULL) || | |
| 1424 (sourceDataLen > 0 && sourceData == NULL)) { | |
| 1425 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | |
| 1426 return SECFailure; | |
| 1427 } | |
| 1428 | |
| 1429 oaepEncoded = (unsigned char *)PORT_Alloc(modulusLen); | |
| 1430 if (oaepEncoded == NULL) { | |
| 1431 PORT_SetError(SEC_ERROR_NO_MEMORY); | |
| 1432 return SECFailure; | |
| 1433 } | |
| 1434 | |
| 1435 rv = RSA_PrivateKeyOpDoubleChecked(&key->u.rsa, oaepEncoded, input); | |
| 1436 if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_LIBRARY_FAILURE) { | |
| 1437 sftk_fatalError = PR_TRUE; | |
| 1438 goto done; | |
| 1439 } | |
| 1440 | |
| 1441 rv = eme_oaep_decode(output, outputLen, maxOutputLen, oaepEncoded, | |
| 1442 modulusLen, hashAlg, maskHashAlg, sourceData, | |
| 1443 sourceDataLen); | |
| 1444 | |
| 1445 done: | |
| 1446 if (oaepEncoded) | |
| 1447 PORT_ZFree(oaepEncoded, modulusLen); | |
| 1448 return rv; | |
| 1449 } | |
| OLD | NEW |