1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/freebl/rsapkcs.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1380 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +/* 1.9 + * RSA PKCS#1 v2.1 (RFC 3447) operations 1.10 + */ 1.11 + 1.12 +#ifdef FREEBL_NO_DEPEND 1.13 +#include "stubs.h" 1.14 +#endif 1.15 + 1.16 +#include "secerr.h" 1.17 + 1.18 +#include "blapi.h" 1.19 +#include "secitem.h" 1.20 +#include "blapii.h" 1.21 + 1.22 +#define RSA_BLOCK_MIN_PAD_LEN 8 1.23 +#define RSA_BLOCK_FIRST_OCTET 0x00 1.24 +#define RSA_BLOCK_PRIVATE_PAD_OCTET 0xff 1.25 +#define RSA_BLOCK_AFTER_PAD_OCTET 0x00 1.26 + 1.27 +/* 1.28 + * RSA block types 1.29 + * 1.30 + * The values of RSA_BlockPrivate and RSA_BlockPublic are fixed. 1.31 + * The value of RSA_BlockRaw isn't fixed by definition, but we are keeping 1.32 + * the value that NSS has been using in the past. 1.33 + */ 1.34 +typedef enum { 1.35 + RSA_BlockPrivate = 1, /* pad for a private-key operation */ 1.36 + RSA_BlockPublic = 2, /* pad for a public-key operation */ 1.37 + RSA_BlockRaw = 4 /* simply justify the block appropriately */ 1.38 +} RSA_BlockType; 1.39 + 1.40 +/* Needed for RSA-PSS functions */ 1.41 +static const unsigned char eightZeros[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 1.42 + 1.43 +/* Constant time comparison of a single byte. 1.44 + * Returns 1 iff a == b, otherwise returns 0. 1.45 + * Note: For ranges of bytes, use constantTimeCompare. 1.46 + */ 1.47 +static unsigned char constantTimeEQ8(unsigned char a, unsigned char b) { 1.48 + unsigned char c = ~((a - b) | (b - a)); 1.49 + c >>= 7; 1.50 + return c; 1.51 +} 1.52 + 1.53 +/* Constant time comparison of a range of bytes. 1.54 + * Returns 1 iff len bytes of a are identical to len bytes of b, otherwise 1.55 + * returns 0. 1.56 + */ 1.57 +static unsigned char constantTimeCompare(const unsigned char *a, 1.58 + const unsigned char *b, 1.59 + unsigned int len) { 1.60 + unsigned char tmp = 0; 1.61 + unsigned int i; 1.62 + for (i = 0; i < len; ++i, ++a, ++b) 1.63 + tmp |= *a ^ *b; 1.64 + return constantTimeEQ8(0x00, tmp); 1.65 +} 1.66 + 1.67 +/* Constant time conditional. 1.68 + * Returns a if c is 1, or b if c is 0. The result is undefined if c is 1.69 + * not 0 or 1. 1.70 + */ 1.71 +static unsigned int constantTimeCondition(unsigned int c, 1.72 + unsigned int a, 1.73 + unsigned int b) 1.74 +{ 1.75 + return (~(c - 1) & a) | ((c - 1) & b); 1.76 +} 1.77 + 1.78 +static unsigned int 1.79 +rsa_modulusLen(SECItem * modulus) 1.80 +{ 1.81 + unsigned char byteZero = modulus->data[0]; 1.82 + unsigned int modLen = modulus->len - !byteZero; 1.83 + return modLen; 1.84 +} 1.85 + 1.86 +/* 1.87 + * Format one block of data for public/private key encryption using 1.88 + * the rules defined in PKCS #1. 1.89 + */ 1.90 +static unsigned char * 1.91 +rsa_FormatOneBlock(unsigned modulusLen, 1.92 + RSA_BlockType blockType, 1.93 + SECItem * data) 1.94 +{ 1.95 + unsigned char *block; 1.96 + unsigned char *bp; 1.97 + int padLen; 1.98 + int i, j; 1.99 + SECStatus rv; 1.100 + 1.101 + block = (unsigned char *) PORT_Alloc(modulusLen); 1.102 + if (block == NULL) 1.103 + return NULL; 1.104 + 1.105 + bp = block; 1.106 + 1.107 + /* 1.108 + * All RSA blocks start with two octets: 1.109 + * 0x00 || BlockType 1.110 + */ 1.111 + *bp++ = RSA_BLOCK_FIRST_OCTET; 1.112 + *bp++ = (unsigned char) blockType; 1.113 + 1.114 + switch (blockType) { 1.115 + 1.116 + /* 1.117 + * Blocks intended for private-key operation. 1.118 + */ 1.119 + case RSA_BlockPrivate: /* preferred method */ 1.120 + /* 1.121 + * 0x00 || BT || Pad || 0x00 || ActualData 1.122 + * 1 1 padLen 1 data->len 1.123 + * Pad is either all 0x00 or all 0xff bytes, depending on blockType. 1.124 + */ 1.125 + padLen = modulusLen - data->len - 3; 1.126 + PORT_Assert(padLen >= RSA_BLOCK_MIN_PAD_LEN); 1.127 + if (padLen < RSA_BLOCK_MIN_PAD_LEN) { 1.128 + PORT_Free(block); 1.129 + return NULL; 1.130 + } 1.131 + PORT_Memset(bp, RSA_BLOCK_PRIVATE_PAD_OCTET, padLen); 1.132 + bp += padLen; 1.133 + *bp++ = RSA_BLOCK_AFTER_PAD_OCTET; 1.134 + PORT_Memcpy(bp, data->data, data->len); 1.135 + break; 1.136 + 1.137 + /* 1.138 + * Blocks intended for public-key operation. 1.139 + */ 1.140 + case RSA_BlockPublic: 1.141 + /* 1.142 + * 0x00 || BT || Pad || 0x00 || ActualData 1.143 + * 1 1 padLen 1 data->len 1.144 + * Pad is all non-zero random bytes. 1.145 + * 1.146 + * Build the block left to right. 1.147 + * Fill the entire block from Pad to the end with random bytes. 1.148 + * Use the bytes after Pad as a supply of extra random bytes from 1.149 + * which to find replacements for the zero bytes in Pad. 1.150 + * If we need more than that, refill the bytes after Pad with 1.151 + * new random bytes as necessary. 1.152 + */ 1.153 + padLen = modulusLen - (data->len + 3); 1.154 + PORT_Assert(padLen >= RSA_BLOCK_MIN_PAD_LEN); 1.155 + if (padLen < RSA_BLOCK_MIN_PAD_LEN) { 1.156 + PORT_Free(block); 1.157 + return NULL; 1.158 + } 1.159 + j = modulusLen - 2; 1.160 + rv = RNG_GenerateGlobalRandomBytes(bp, j); 1.161 + if (rv == SECSuccess) { 1.162 + for (i = 0; i < padLen; ) { 1.163 + unsigned char repl; 1.164 + /* Pad with non-zero random data. */ 1.165 + if (bp[i] != RSA_BLOCK_AFTER_PAD_OCTET) { 1.166 + ++i; 1.167 + continue; 1.168 + } 1.169 + if (j <= padLen) { 1.170 + rv = RNG_GenerateGlobalRandomBytes(bp + padLen, 1.171 + modulusLen - (2 + padLen)); 1.172 + if (rv != SECSuccess) 1.173 + break; 1.174 + j = modulusLen - 2; 1.175 + } 1.176 + do { 1.177 + repl = bp[--j]; 1.178 + } while (repl == RSA_BLOCK_AFTER_PAD_OCTET && j > padLen); 1.179 + if (repl != RSA_BLOCK_AFTER_PAD_OCTET) { 1.180 + bp[i++] = repl; 1.181 + } 1.182 + } 1.183 + } 1.184 + if (rv != SECSuccess) { 1.185 + PORT_Free(block); 1.186 + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 1.187 + return NULL; 1.188 + } 1.189 + bp += padLen; 1.190 + *bp++ = RSA_BLOCK_AFTER_PAD_OCTET; 1.191 + PORT_Memcpy(bp, data->data, data->len); 1.192 + break; 1.193 + 1.194 + default: 1.195 + PORT_Assert(0); 1.196 + PORT_Free(block); 1.197 + return NULL; 1.198 + } 1.199 + 1.200 + return block; 1.201 +} 1.202 + 1.203 +static SECStatus 1.204 +rsa_FormatBlock(SECItem * result, 1.205 + unsigned modulusLen, 1.206 + RSA_BlockType blockType, 1.207 + SECItem * data) 1.208 +{ 1.209 + switch (blockType) { 1.210 + case RSA_BlockPrivate: 1.211 + case RSA_BlockPublic: 1.212 + /* 1.213 + * 0x00 || BT || Pad || 0x00 || ActualData 1.214 + * 1.215 + * The "3" below is the first octet + the second octet + the 0x00 1.216 + * octet that always comes just before the ActualData. 1.217 + */ 1.218 + PORT_Assert(data->len <= (modulusLen - (3 + RSA_BLOCK_MIN_PAD_LEN))); 1.219 + 1.220 + result->data = rsa_FormatOneBlock(modulusLen, blockType, data); 1.221 + if (result->data == NULL) { 1.222 + result->len = 0; 1.223 + return SECFailure; 1.224 + } 1.225 + result->len = modulusLen; 1.226 + 1.227 + break; 1.228 + 1.229 + case RSA_BlockRaw: 1.230 + /* 1.231 + * Pad || ActualData 1.232 + * Pad is zeros. The application is responsible for recovering 1.233 + * the actual data. 1.234 + */ 1.235 + if (data->len > modulusLen ) { 1.236 + return SECFailure; 1.237 + } 1.238 + result->data = (unsigned char*)PORT_ZAlloc(modulusLen); 1.239 + result->len = modulusLen; 1.240 + PORT_Memcpy(result->data + (modulusLen - data->len), 1.241 + data->data, data->len); 1.242 + break; 1.243 + 1.244 + default: 1.245 + PORT_Assert(0); 1.246 + result->data = NULL; 1.247 + result->len = 0; 1.248 + return SECFailure; 1.249 + } 1.250 + 1.251 + return SECSuccess; 1.252 +} 1.253 + 1.254 +/* 1.255 + * Mask generation function MGF1 as defined in PKCS #1 v2.1 / RFC 3447. 1.256 + */ 1.257 +static SECStatus 1.258 +MGF1(HASH_HashType hashAlg, 1.259 + unsigned char * mask, 1.260 + unsigned int maskLen, 1.261 + const unsigned char * mgfSeed, 1.262 + unsigned int mgfSeedLen) 1.263 +{ 1.264 + unsigned int digestLen; 1.265 + PRUint32 counter; 1.266 + PRUint32 rounds; 1.267 + unsigned char * tempHash; 1.268 + unsigned char * temp; 1.269 + const SECHashObject * hash; 1.270 + void * hashContext; 1.271 + unsigned char C[4]; 1.272 + 1.273 + hash = HASH_GetRawHashObject(hashAlg); 1.274 + if (hash == NULL) 1.275 + return SECFailure; 1.276 + 1.277 + hashContext = (*hash->create)(); 1.278 + rounds = (maskLen + hash->length - 1) / hash->length; 1.279 + for (counter = 0; counter < rounds; counter++) { 1.280 + C[0] = (unsigned char)((counter >> 24) & 0xff); 1.281 + C[1] = (unsigned char)((counter >> 16) & 0xff); 1.282 + C[2] = (unsigned char)((counter >> 8) & 0xff); 1.283 + C[3] = (unsigned char)(counter & 0xff); 1.284 + 1.285 + /* This could be optimized when the clone functions in 1.286 + * rawhash.c are implemented. */ 1.287 + (*hash->begin)(hashContext); 1.288 + (*hash->update)(hashContext, mgfSeed, mgfSeedLen); 1.289 + (*hash->update)(hashContext, C, sizeof C); 1.290 + 1.291 + tempHash = mask + counter * hash->length; 1.292 + if (counter != (rounds - 1)) { 1.293 + (*hash->end)(hashContext, tempHash, &digestLen, hash->length); 1.294 + } else { /* we're in the last round and need to cut the hash */ 1.295 + temp = (unsigned char *)PORT_Alloc(hash->length); 1.296 + (*hash->end)(hashContext, temp, &digestLen, hash->length); 1.297 + PORT_Memcpy(tempHash, temp, maskLen - counter * hash->length); 1.298 + PORT_Free(temp); 1.299 + } 1.300 + } 1.301 + (*hash->destroy)(hashContext, PR_TRUE); 1.302 + 1.303 + return SECSuccess; 1.304 +} 1.305 + 1.306 +/* XXX Doesn't set error code */ 1.307 +SECStatus 1.308 +RSA_SignRaw(RSAPrivateKey * key, 1.309 + unsigned char * output, 1.310 + unsigned int * outputLen, 1.311 + unsigned int maxOutputLen, 1.312 + const unsigned char * data, 1.313 + unsigned int dataLen) 1.314 +{ 1.315 + SECStatus rv = SECSuccess; 1.316 + unsigned int modulusLen = rsa_modulusLen(&key->modulus); 1.317 + SECItem formatted; 1.318 + SECItem unformatted; 1.319 + 1.320 + if (maxOutputLen < modulusLen) 1.321 + return SECFailure; 1.322 + 1.323 + unformatted.len = dataLen; 1.324 + unformatted.data = (unsigned char*)data; 1.325 + formatted.data = NULL; 1.326 + rv = rsa_FormatBlock(&formatted, modulusLen, RSA_BlockRaw, &unformatted); 1.327 + if (rv != SECSuccess) 1.328 + goto done; 1.329 + 1.330 + rv = RSA_PrivateKeyOpDoubleChecked(key, output, formatted.data); 1.331 + *outputLen = modulusLen; 1.332 + 1.333 +done: 1.334 + if (formatted.data != NULL) 1.335 + PORT_ZFree(formatted.data, modulusLen); 1.336 + return rv; 1.337 +} 1.338 + 1.339 +/* XXX Doesn't set error code */ 1.340 +SECStatus 1.341 +RSA_CheckSignRaw(RSAPublicKey * key, 1.342 + const unsigned char * sig, 1.343 + unsigned int sigLen, 1.344 + const unsigned char * hash, 1.345 + unsigned int hashLen) 1.346 +{ 1.347 + SECStatus rv; 1.348 + unsigned int modulusLen = rsa_modulusLen(&key->modulus); 1.349 + unsigned char * buffer; 1.350 + 1.351 + if (sigLen != modulusLen) 1.352 + goto failure; 1.353 + if (hashLen > modulusLen) 1.354 + goto failure; 1.355 + 1.356 + buffer = (unsigned char *)PORT_Alloc(modulusLen + 1); 1.357 + if (!buffer) 1.358 + goto failure; 1.359 + 1.360 + rv = RSA_PublicKeyOp(key, buffer, sig); 1.361 + if (rv != SECSuccess) 1.362 + goto loser; 1.363 + 1.364 + /* 1.365 + * make sure we get the same results 1.366 + */ 1.367 + /* XXX(rsleevi): Constant time */ 1.368 + /* NOTE: should we verify the leading zeros? */ 1.369 + if (PORT_Memcmp(buffer + (modulusLen - hashLen), hash, hashLen) != 0) 1.370 + goto loser; 1.371 + 1.372 + PORT_Free(buffer); 1.373 + return SECSuccess; 1.374 + 1.375 +loser: 1.376 + PORT_Free(buffer); 1.377 +failure: 1.378 + return SECFailure; 1.379 +} 1.380 + 1.381 +/* XXX Doesn't set error code */ 1.382 +SECStatus 1.383 +RSA_CheckSignRecoverRaw(RSAPublicKey * key, 1.384 + unsigned char * data, 1.385 + unsigned int * dataLen, 1.386 + unsigned int maxDataLen, 1.387 + const unsigned char * sig, 1.388 + unsigned int sigLen) 1.389 +{ 1.390 + SECStatus rv; 1.391 + unsigned int modulusLen = rsa_modulusLen(&key->modulus); 1.392 + 1.393 + if (sigLen != modulusLen) 1.394 + goto failure; 1.395 + if (maxDataLen < modulusLen) 1.396 + goto failure; 1.397 + 1.398 + rv = RSA_PublicKeyOp(key, data, sig); 1.399 + if (rv != SECSuccess) 1.400 + goto failure; 1.401 + 1.402 + *dataLen = modulusLen; 1.403 + return SECSuccess; 1.404 + 1.405 +failure: 1.406 + return SECFailure; 1.407 +} 1.408 + 1.409 +/* XXX Doesn't set error code */ 1.410 +SECStatus 1.411 +RSA_EncryptRaw(RSAPublicKey * key, 1.412 + unsigned char * output, 1.413 + unsigned int * outputLen, 1.414 + unsigned int maxOutputLen, 1.415 + const unsigned char * input, 1.416 + unsigned int inputLen) 1.417 +{ 1.418 + SECStatus rv; 1.419 + unsigned int modulusLen = rsa_modulusLen(&key->modulus); 1.420 + SECItem formatted; 1.421 + SECItem unformatted; 1.422 + 1.423 + formatted.data = NULL; 1.424 + if (maxOutputLen < modulusLen) 1.425 + goto failure; 1.426 + 1.427 + unformatted.len = inputLen; 1.428 + unformatted.data = (unsigned char*)input; 1.429 + formatted.data = NULL; 1.430 + rv = rsa_FormatBlock(&formatted, modulusLen, RSA_BlockRaw, &unformatted); 1.431 + if (rv != SECSuccess) 1.432 + goto failure; 1.433 + 1.434 + rv = RSA_PublicKeyOp(key, output, formatted.data); 1.435 + if (rv != SECSuccess) 1.436 + goto failure; 1.437 + 1.438 + PORT_ZFree(formatted.data, modulusLen); 1.439 + *outputLen = modulusLen; 1.440 + return SECSuccess; 1.441 + 1.442 +failure: 1.443 + if (formatted.data != NULL) 1.444 + PORT_ZFree(formatted.data, modulusLen); 1.445 + return SECFailure; 1.446 +} 1.447 + 1.448 +/* XXX Doesn't set error code */ 1.449 +SECStatus 1.450 +RSA_DecryptRaw(RSAPrivateKey * key, 1.451 + unsigned char * output, 1.452 + unsigned int * outputLen, 1.453 + unsigned int maxOutputLen, 1.454 + const unsigned char * input, 1.455 + unsigned int inputLen) 1.456 +{ 1.457 + SECStatus rv; 1.458 + unsigned int modulusLen = rsa_modulusLen(&key->modulus); 1.459 + 1.460 + if (modulusLen > maxOutputLen) 1.461 + goto failure; 1.462 + if (inputLen != modulusLen) 1.463 + goto failure; 1.464 + 1.465 + rv = RSA_PrivateKeyOp(key, output, input); 1.466 + if (rv != SECSuccess) 1.467 + goto failure; 1.468 + 1.469 + *outputLen = modulusLen; 1.470 + return SECSuccess; 1.471 + 1.472 +failure: 1.473 + return SECFailure; 1.474 +} 1.475 + 1.476 +/* 1.477 + * Decodes an EME-OAEP encoded block, validating the encoding in constant 1.478 + * time. 1.479 + * Described in RFC 3447, section 7.1.2. 1.480 + * input contains the encoded block, after decryption. 1.481 + * label is the optional value L that was associated with the message. 1.482 + * On success, the original message and message length will be stored in 1.483 + * output and outputLen. 1.484 + */ 1.485 +static SECStatus 1.486 +eme_oaep_decode(unsigned char * output, 1.487 + unsigned int * outputLen, 1.488 + unsigned int maxOutputLen, 1.489 + const unsigned char * input, 1.490 + unsigned int inputLen, 1.491 + HASH_HashType hashAlg, 1.492 + HASH_HashType maskHashAlg, 1.493 + const unsigned char * label, 1.494 + unsigned int labelLen) 1.495 +{ 1.496 + const SECHashObject * hash; 1.497 + void * hashContext; 1.498 + SECStatus rv = SECFailure; 1.499 + unsigned char labelHash[HASH_LENGTH_MAX]; 1.500 + unsigned int i; 1.501 + unsigned int maskLen; 1.502 + unsigned int paddingOffset; 1.503 + unsigned char * mask = NULL; 1.504 + unsigned char * tmpOutput = NULL; 1.505 + unsigned char isGood; 1.506 + unsigned char foundPaddingEnd; 1.507 + 1.508 + hash = HASH_GetRawHashObject(hashAlg); 1.509 + 1.510 + /* 1.c */ 1.511 + if (inputLen < (hash->length * 2) + 2) { 1.512 + PORT_SetError(SEC_ERROR_INPUT_LEN); 1.513 + return SECFailure; 1.514 + } 1.515 + 1.516 + /* Step 3.a - Generate lHash */ 1.517 + hashContext = (*hash->create)(); 1.518 + if (hashContext == NULL) { 1.519 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.520 + return SECFailure; 1.521 + } 1.522 + (*hash->begin)(hashContext); 1.523 + if (labelLen > 0) 1.524 + (*hash->update)(hashContext, label, labelLen); 1.525 + (*hash->end)(hashContext, labelHash, &i, sizeof(labelHash)); 1.526 + (*hash->destroy)(hashContext, PR_TRUE); 1.527 + 1.528 + tmpOutput = (unsigned char*)PORT_Alloc(inputLen); 1.529 + if (tmpOutput == NULL) { 1.530 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.531 + goto done; 1.532 + } 1.533 + 1.534 + maskLen = inputLen - hash->length - 1; 1.535 + mask = (unsigned char*)PORT_Alloc(maskLen); 1.536 + if (mask == NULL) { 1.537 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.538 + goto done; 1.539 + } 1.540 + 1.541 + PORT_Memcpy(tmpOutput, input, inputLen); 1.542 + 1.543 + /* 3.c - Generate seedMask */ 1.544 + MGF1(maskHashAlg, mask, hash->length, &tmpOutput[1 + hash->length], 1.545 + inputLen - hash->length - 1); 1.546 + /* 3.d - Unmask seed */ 1.547 + for (i = 0; i < hash->length; ++i) 1.548 + tmpOutput[1 + i] ^= mask[i]; 1.549 + 1.550 + /* 3.e - Generate dbMask */ 1.551 + MGF1(maskHashAlg, mask, maskLen, &tmpOutput[1], hash->length); 1.552 + /* 3.f - Unmask DB */ 1.553 + for (i = 0; i < maskLen; ++i) 1.554 + tmpOutput[1 + hash->length + i] ^= mask[i]; 1.555 + 1.556 + /* 3.g - Compare Y, lHash, and PS in constant time 1.557 + * Warning: This code is timing dependent and must not disclose which of 1.558 + * these were invalid. 1.559 + */ 1.560 + paddingOffset = 0; 1.561 + isGood = 1; 1.562 + foundPaddingEnd = 0; 1.563 + 1.564 + /* Compare Y */ 1.565 + isGood &= constantTimeEQ8(0x00, tmpOutput[0]); 1.566 + 1.567 + /* Compare lHash and lHash' */ 1.568 + isGood &= constantTimeCompare(&labelHash[0], 1.569 + &tmpOutput[1 + hash->length], 1.570 + hash->length); 1.571 + 1.572 + /* Compare that the padding is zero or more zero octets, followed by a 1.573 + * 0x01 octet */ 1.574 + for (i = 1 + (hash->length * 2); i < inputLen; ++i) { 1.575 + unsigned char isZero = constantTimeEQ8(0x00, tmpOutput[i]); 1.576 + unsigned char isOne = constantTimeEQ8(0x01, tmpOutput[i]); 1.577 + /* non-constant time equivalent: 1.578 + * if (tmpOutput[i] == 0x01 && !foundPaddingEnd) 1.579 + * paddingOffset = i; 1.580 + */ 1.581 + paddingOffset = constantTimeCondition(isOne & ~foundPaddingEnd, i, 1.582 + paddingOffset); 1.583 + /* non-constant time equivalent: 1.584 + * if (tmpOutput[i] == 0x01) 1.585 + * foundPaddingEnd = true; 1.586 + * 1.587 + * Note: This may yield false positives, as it will be set whenever 1.588 + * a 0x01 byte is encountered. If there was bad padding (eg: 1.589 + * 0x03 0x02 0x01), foundPaddingEnd will still be set to true, and 1.590 + * paddingOffset will still be set to 2. 1.591 + */ 1.592 + foundPaddingEnd = constantTimeCondition(isOne, 1, foundPaddingEnd); 1.593 + /* non-constant time equivalent: 1.594 + * if (tmpOutput[i] != 0x00 && tmpOutput[i] != 0x01 && 1.595 + * !foundPaddingEnd) { 1.596 + * isGood = false; 1.597 + * } 1.598 + * 1.599 + * Note: This may yield false positives, as a message (and padding) 1.600 + * that is entirely zeros will result in isGood still being true. Thus 1.601 + * it's necessary to check foundPaddingEnd is positive below. 1.602 + */ 1.603 + isGood = constantTimeCondition(~foundPaddingEnd & ~isZero, 0, isGood); 1.604 + } 1.605 + 1.606 + /* While both isGood and foundPaddingEnd may have false positives, they 1.607 + * cannot BOTH have false positives. If both are not true, then an invalid 1.608 + * message was received. Note, this comparison must still be done in constant 1.609 + * time so as not to leak either condition. 1.610 + */ 1.611 + if (!(isGood & foundPaddingEnd)) { 1.612 + PORT_SetError(SEC_ERROR_BAD_DATA); 1.613 + goto done; 1.614 + } 1.615 + 1.616 + /* End timing dependent code */ 1.617 + 1.618 + ++paddingOffset; /* Skip the 0x01 following the end of PS */ 1.619 + 1.620 + *outputLen = inputLen - paddingOffset; 1.621 + if (*outputLen > maxOutputLen) { 1.622 + PORT_SetError(SEC_ERROR_OUTPUT_LEN); 1.623 + goto done; 1.624 + } 1.625 + 1.626 + if (*outputLen) 1.627 + PORT_Memcpy(output, &tmpOutput[paddingOffset], *outputLen); 1.628 + rv = SECSuccess; 1.629 + 1.630 +done: 1.631 + if (mask) 1.632 + PORT_ZFree(mask, maskLen); 1.633 + if (tmpOutput) 1.634 + PORT_ZFree(tmpOutput, inputLen); 1.635 + return rv; 1.636 +} 1.637 + 1.638 +/* 1.639 + * Generate an EME-OAEP encoded block for encryption 1.640 + * Described in RFC 3447, section 7.1.1 1.641 + * We use input instead of M for the message to be encrypted 1.642 + * label is the optional value L to be associated with the message. 1.643 + */ 1.644 +static SECStatus 1.645 +eme_oaep_encode(unsigned char * em, 1.646 + unsigned int emLen, 1.647 + const unsigned char * input, 1.648 + unsigned int inputLen, 1.649 + HASH_HashType hashAlg, 1.650 + HASH_HashType maskHashAlg, 1.651 + const unsigned char * label, 1.652 + unsigned int labelLen, 1.653 + const unsigned char * seed, 1.654 + unsigned int seedLen) 1.655 +{ 1.656 + const SECHashObject * hash; 1.657 + void * hashContext; 1.658 + SECStatus rv; 1.659 + unsigned char * mask; 1.660 + unsigned int reservedLen; 1.661 + unsigned int dbMaskLen; 1.662 + unsigned int i; 1.663 + 1.664 + hash = HASH_GetRawHashObject(hashAlg); 1.665 + PORT_Assert(seed == NULL || seedLen == hash->length); 1.666 + 1.667 + /* Step 1.b */ 1.668 + reservedLen = (2 * hash->length) + 2; 1.669 + if (emLen < reservedLen || inputLen > (emLen - reservedLen)) { 1.670 + PORT_SetError(SEC_ERROR_INPUT_LEN); 1.671 + return SECFailure; 1.672 + } 1.673 + 1.674 + /* 1.675 + * From RFC 3447, Section 7.1 1.676 + * +----------+---------+-------+ 1.677 + * DB = | lHash | PS | M | 1.678 + * +----------+---------+-------+ 1.679 + * | 1.680 + * +----------+ V 1.681 + * | seed |--> MGF ---> xor 1.682 + * +----------+ | 1.683 + * | | 1.684 + * +--+ V | 1.685 + * |00| xor <----- MGF <-----| 1.686 + * +--+ | | 1.687 + * | | | 1.688 + * V V V 1.689 + * +--+----------+----------------------------+ 1.690 + * EM = |00|maskedSeed| maskedDB | 1.691 + * +--+----------+----------------------------+ 1.692 + * 1.693 + * We use mask to hold the result of the MGF functions, and all other 1.694 + * values are generated in their final resting place. 1.695 + */ 1.696 + *em = 0x00; 1.697 + 1.698 + /* Step 2.a - Generate lHash */ 1.699 + hashContext = (*hash->create)(); 1.700 + if (hashContext == NULL) { 1.701 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.702 + return SECFailure; 1.703 + } 1.704 + (*hash->begin)(hashContext); 1.705 + if (labelLen > 0) 1.706 + (*hash->update)(hashContext, label, labelLen); 1.707 + (*hash->end)(hashContext, &em[1 + hash->length], &i, hash->length); 1.708 + (*hash->destroy)(hashContext, PR_TRUE); 1.709 + 1.710 + /* Step 2.b - Generate PS */ 1.711 + if (emLen - reservedLen - inputLen > 0) { 1.712 + PORT_Memset(em + 1 + (hash->length * 2), 0x00, 1.713 + emLen - reservedLen - inputLen); 1.714 + } 1.715 + 1.716 + /* Step 2.c. - Generate DB 1.717 + * DB = lHash || PS || 0x01 || M 1.718 + * Note that PS and lHash have already been placed into em at their 1.719 + * appropriate offsets. This just copies M into place 1.720 + */ 1.721 + em[emLen - inputLen - 1] = 0x01; 1.722 + if (inputLen) 1.723 + PORT_Memcpy(em + emLen - inputLen, input, inputLen); 1.724 + 1.725 + if (seed == NULL) { 1.726 + /* Step 2.d - Generate seed */ 1.727 + rv = RNG_GenerateGlobalRandomBytes(em + 1, hash->length); 1.728 + if (rv != SECSuccess) { 1.729 + return rv; 1.730 + } 1.731 + } else { 1.732 + /* For Known Answer Tests, copy the supplied seed. */ 1.733 + PORT_Memcpy(em + 1, seed, seedLen); 1.734 + } 1.735 + 1.736 + /* Step 2.e - Generate dbMask*/ 1.737 + dbMaskLen = emLen - hash->length - 1; 1.738 + mask = (unsigned char*)PORT_Alloc(dbMaskLen); 1.739 + if (mask == NULL) { 1.740 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.741 + return SECFailure; 1.742 + } 1.743 + MGF1(maskHashAlg, mask, dbMaskLen, em + 1, hash->length); 1.744 + /* Step 2.f - Compute maskedDB*/ 1.745 + for (i = 0; i < dbMaskLen; ++i) 1.746 + em[1 + hash->length + i] ^= mask[i]; 1.747 + 1.748 + /* Step 2.g - Generate seedMask */ 1.749 + MGF1(maskHashAlg, mask, hash->length, &em[1 + hash->length], dbMaskLen); 1.750 + /* Step 2.h - Compute maskedSeed */ 1.751 + for (i = 0; i < hash->length; ++i) 1.752 + em[1 + i] ^= mask[i]; 1.753 + 1.754 + PORT_ZFree(mask, dbMaskLen); 1.755 + return SECSuccess; 1.756 +} 1.757 + 1.758 +SECStatus 1.759 +RSA_EncryptOAEP(RSAPublicKey * key, 1.760 + HASH_HashType hashAlg, 1.761 + HASH_HashType maskHashAlg, 1.762 + const unsigned char * label, 1.763 + unsigned int labelLen, 1.764 + const unsigned char * seed, 1.765 + unsigned int seedLen, 1.766 + unsigned char * output, 1.767 + unsigned int * outputLen, 1.768 + unsigned int maxOutputLen, 1.769 + const unsigned char * input, 1.770 + unsigned int inputLen) 1.771 +{ 1.772 + SECStatus rv = SECFailure; 1.773 + unsigned int modulusLen = rsa_modulusLen(&key->modulus); 1.774 + unsigned char * oaepEncoded = NULL; 1.775 + 1.776 + if (maxOutputLen < modulusLen) { 1.777 + PORT_SetError(SEC_ERROR_OUTPUT_LEN); 1.778 + return SECFailure; 1.779 + } 1.780 + 1.781 + if ((hashAlg == HASH_AlgNULL) || (maskHashAlg == HASH_AlgNULL)) { 1.782 + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); 1.783 + return SECFailure; 1.784 + } 1.785 + 1.786 + if ((labelLen == 0 && label != NULL) || 1.787 + (labelLen > 0 && label == NULL)) { 1.788 + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); 1.789 + return SECFailure; 1.790 + } 1.791 + 1.792 + oaepEncoded = (unsigned char *)PORT_Alloc(modulusLen); 1.793 + if (oaepEncoded == NULL) { 1.794 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.795 + return SECFailure; 1.796 + } 1.797 + rv = eme_oaep_encode(oaepEncoded, modulusLen, input, inputLen, 1.798 + hashAlg, maskHashAlg, label, labelLen, seed, seedLen); 1.799 + if (rv != SECSuccess) 1.800 + goto done; 1.801 + 1.802 + rv = RSA_PublicKeyOp(key, output, oaepEncoded); 1.803 + if (rv != SECSuccess) 1.804 + goto done; 1.805 + *outputLen = modulusLen; 1.806 + 1.807 +done: 1.808 + PORT_Free(oaepEncoded); 1.809 + return rv; 1.810 +} 1.811 + 1.812 +SECStatus 1.813 +RSA_DecryptOAEP(RSAPrivateKey * key, 1.814 + HASH_HashType hashAlg, 1.815 + HASH_HashType maskHashAlg, 1.816 + const unsigned char * label, 1.817 + unsigned int labelLen, 1.818 + unsigned char * output, 1.819 + unsigned int * outputLen, 1.820 + unsigned int maxOutputLen, 1.821 + const unsigned char * input, 1.822 + unsigned int inputLen) 1.823 +{ 1.824 + SECStatus rv = SECFailure; 1.825 + unsigned int modulusLen = rsa_modulusLen(&key->modulus); 1.826 + unsigned char * oaepEncoded = NULL; 1.827 + 1.828 + if ((hashAlg == HASH_AlgNULL) || (maskHashAlg == HASH_AlgNULL)) { 1.829 + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); 1.830 + return SECFailure; 1.831 + } 1.832 + 1.833 + if (inputLen != modulusLen) { 1.834 + PORT_SetError(SEC_ERROR_INPUT_LEN); 1.835 + return SECFailure; 1.836 + } 1.837 + 1.838 + if ((labelLen == 0 && label != NULL) || 1.839 + (labelLen > 0 && label == NULL)) { 1.840 + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); 1.841 + return SECFailure; 1.842 + } 1.843 + 1.844 + oaepEncoded = (unsigned char *)PORT_Alloc(modulusLen); 1.845 + if (oaepEncoded == NULL) { 1.846 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.847 + return SECFailure; 1.848 + } 1.849 + 1.850 + rv = RSA_PrivateKeyOpDoubleChecked(key, oaepEncoded, input); 1.851 + if (rv != SECSuccess) { 1.852 + goto done; 1.853 + } 1.854 + rv = eme_oaep_decode(output, outputLen, maxOutputLen, oaepEncoded, 1.855 + modulusLen, hashAlg, maskHashAlg, label, 1.856 + labelLen); 1.857 + 1.858 +done: 1.859 + if (oaepEncoded) 1.860 + PORT_ZFree(oaepEncoded, modulusLen); 1.861 + return rv; 1.862 +} 1.863 + 1.864 +/* XXX Doesn't set error code */ 1.865 +SECStatus 1.866 +RSA_EncryptBlock(RSAPublicKey * key, 1.867 + unsigned char * output, 1.868 + unsigned int * outputLen, 1.869 + unsigned int maxOutputLen, 1.870 + const unsigned char * input, 1.871 + unsigned int inputLen) 1.872 +{ 1.873 + SECStatus rv; 1.874 + unsigned int modulusLen = rsa_modulusLen(&key->modulus); 1.875 + SECItem formatted; 1.876 + SECItem unformatted; 1.877 + 1.878 + formatted.data = NULL; 1.879 + if (maxOutputLen < modulusLen) 1.880 + goto failure; 1.881 + 1.882 + unformatted.len = inputLen; 1.883 + unformatted.data = (unsigned char*)input; 1.884 + formatted.data = NULL; 1.885 + rv = rsa_FormatBlock(&formatted, modulusLen, RSA_BlockPublic, 1.886 + &unformatted); 1.887 + if (rv != SECSuccess) 1.888 + goto failure; 1.889 + 1.890 + rv = RSA_PublicKeyOp(key, output, formatted.data); 1.891 + if (rv != SECSuccess) 1.892 + goto failure; 1.893 + 1.894 + PORT_ZFree(formatted.data, modulusLen); 1.895 + *outputLen = modulusLen; 1.896 + return SECSuccess; 1.897 + 1.898 +failure: 1.899 + if (formatted.data != NULL) 1.900 + PORT_ZFree(formatted.data, modulusLen); 1.901 + return SECFailure; 1.902 +} 1.903 + 1.904 +/* XXX Doesn't set error code */ 1.905 +SECStatus 1.906 +RSA_DecryptBlock(RSAPrivateKey * key, 1.907 + unsigned char * output, 1.908 + unsigned int * outputLen, 1.909 + unsigned int maxOutputLen, 1.910 + const unsigned char * input, 1.911 + unsigned int inputLen) 1.912 +{ 1.913 + SECStatus rv; 1.914 + unsigned int modulusLen = rsa_modulusLen(&key->modulus); 1.915 + unsigned int i; 1.916 + unsigned char * buffer; 1.917 + 1.918 + if (inputLen != modulusLen) 1.919 + goto failure; 1.920 + 1.921 + buffer = (unsigned char *)PORT_Alloc(modulusLen + 1); 1.922 + if (!buffer) 1.923 + goto failure; 1.924 + 1.925 + rv = RSA_PrivateKeyOp(key, buffer, input); 1.926 + if (rv != SECSuccess) 1.927 + goto loser; 1.928 + 1.929 + /* XXX(rsleevi): Constant time */ 1.930 + if (buffer[0] != RSA_BLOCK_FIRST_OCTET || 1.931 + buffer[1] != (unsigned char)RSA_BlockPublic) { 1.932 + goto loser; 1.933 + } 1.934 + *outputLen = 0; 1.935 + for (i = 2; i < modulusLen; i++) { 1.936 + if (buffer[i] == RSA_BLOCK_AFTER_PAD_OCTET) { 1.937 + *outputLen = modulusLen - i - 1; 1.938 + break; 1.939 + } 1.940 + } 1.941 + if (*outputLen == 0) 1.942 + goto loser; 1.943 + if (*outputLen > maxOutputLen) 1.944 + goto loser; 1.945 + 1.946 + PORT_Memcpy(output, buffer + modulusLen - *outputLen, *outputLen); 1.947 + 1.948 + PORT_Free(buffer); 1.949 + return SECSuccess; 1.950 + 1.951 +loser: 1.952 + PORT_Free(buffer); 1.953 +failure: 1.954 + return SECFailure; 1.955 +} 1.956 + 1.957 +/* 1.958 + * Encode a RSA-PSS signature. 1.959 + * Described in RFC 3447, section 9.1.1. 1.960 + * We use mHash instead of M as input. 1.961 + * emBits from the RFC is just modBits - 1, see section 8.1.1. 1.962 + * We only support MGF1 as the MGF. 1.963 + * 1.964 + * NOTE: this code assumes modBits is a multiple of 8. 1.965 + */ 1.966 +static SECStatus 1.967 +emsa_pss_encode(unsigned char * em, 1.968 + unsigned int emLen, 1.969 + const unsigned char * mHash, 1.970 + HASH_HashType hashAlg, 1.971 + HASH_HashType maskHashAlg, 1.972 + const unsigned char * salt, 1.973 + unsigned int saltLen) 1.974 +{ 1.975 + const SECHashObject * hash; 1.976 + void * hash_context; 1.977 + unsigned char * dbMask; 1.978 + unsigned int dbMaskLen; 1.979 + unsigned int i; 1.980 + SECStatus rv; 1.981 + 1.982 + hash = HASH_GetRawHashObject(hashAlg); 1.983 + dbMaskLen = emLen - hash->length - 1; 1.984 + 1.985 + /* Step 3 */ 1.986 + if (emLen < hash->length + saltLen + 2) { 1.987 + PORT_SetError(SEC_ERROR_OUTPUT_LEN); 1.988 + return SECFailure; 1.989 + } 1.990 + 1.991 + /* Step 4 */ 1.992 + if (salt == NULL) { 1.993 + rv = RNG_GenerateGlobalRandomBytes(&em[dbMaskLen - saltLen], saltLen); 1.994 + if (rv != SECSuccess) { 1.995 + return rv; 1.996 + } 1.997 + } else { 1.998 + PORT_Memcpy(&em[dbMaskLen - saltLen], salt, saltLen); 1.999 + } 1.1000 + 1.1001 + /* Step 5 + 6 */ 1.1002 + /* Compute H and store it at its final location &em[dbMaskLen]. */ 1.1003 + hash_context = (*hash->create)(); 1.1004 + if (hash_context == NULL) { 1.1005 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.1006 + return SECFailure; 1.1007 + } 1.1008 + (*hash->begin)(hash_context); 1.1009 + (*hash->update)(hash_context, eightZeros, 8); 1.1010 + (*hash->update)(hash_context, mHash, hash->length); 1.1011 + (*hash->update)(hash_context, &em[dbMaskLen - saltLen], saltLen); 1.1012 + (*hash->end)(hash_context, &em[dbMaskLen], &i, hash->length); 1.1013 + (*hash->destroy)(hash_context, PR_TRUE); 1.1014 + 1.1015 + /* Step 7 + 8 */ 1.1016 + PORT_Memset(em, 0, dbMaskLen - saltLen - 1); 1.1017 + em[dbMaskLen - saltLen - 1] = 0x01; 1.1018 + 1.1019 + /* Step 9 */ 1.1020 + dbMask = (unsigned char *)PORT_Alloc(dbMaskLen); 1.1021 + if (dbMask == NULL) { 1.1022 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.1023 + return SECFailure; 1.1024 + } 1.1025 + MGF1(maskHashAlg, dbMask, dbMaskLen, &em[dbMaskLen], hash->length); 1.1026 + 1.1027 + /* Step 10 */ 1.1028 + for (i = 0; i < dbMaskLen; i++) 1.1029 + em[i] ^= dbMask[i]; 1.1030 + PORT_Free(dbMask); 1.1031 + 1.1032 + /* Step 11 */ 1.1033 + em[0] &= 0x7f; 1.1034 + 1.1035 + /* Step 12 */ 1.1036 + em[emLen - 1] = 0xbc; 1.1037 + 1.1038 + return SECSuccess; 1.1039 +} 1.1040 + 1.1041 +/* 1.1042 + * Verify a RSA-PSS signature. 1.1043 + * Described in RFC 3447, section 9.1.2. 1.1044 + * We use mHash instead of M as input. 1.1045 + * emBits from the RFC is just modBits - 1, see section 8.1.2. 1.1046 + * We only support MGF1 as the MGF. 1.1047 + * 1.1048 + * NOTE: this code assumes modBits is a multiple of 8. 1.1049 + */ 1.1050 +static SECStatus 1.1051 +emsa_pss_verify(const unsigned char * mHash, 1.1052 + const unsigned char * em, 1.1053 + unsigned int emLen, 1.1054 + HASH_HashType hashAlg, 1.1055 + HASH_HashType maskHashAlg, 1.1056 + unsigned int saltLen) 1.1057 +{ 1.1058 + const SECHashObject * hash; 1.1059 + void * hash_context; 1.1060 + unsigned char * db; 1.1061 + unsigned char * H_; /* H' from the RFC */ 1.1062 + unsigned int i; 1.1063 + unsigned int dbMaskLen; 1.1064 + SECStatus rv; 1.1065 + 1.1066 + hash = HASH_GetRawHashObject(hashAlg); 1.1067 + dbMaskLen = emLen - hash->length - 1; 1.1068 + 1.1069 + /* Step 3 + 4 + 6 */ 1.1070 + if ((emLen < (hash->length + saltLen + 2)) || 1.1071 + (em[emLen - 1] != 0xbc) || 1.1072 + ((em[0] & 0x80) != 0)) { 1.1073 + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); 1.1074 + return SECFailure; 1.1075 + } 1.1076 + 1.1077 + /* Step 7 */ 1.1078 + db = (unsigned char *)PORT_Alloc(dbMaskLen); 1.1079 + if (db == NULL) { 1.1080 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.1081 + return SECFailure; 1.1082 + } 1.1083 + /* &em[dbMaskLen] points to H, used as mgfSeed */ 1.1084 + MGF1(maskHashAlg, db, dbMaskLen, &em[dbMaskLen], hash->length); 1.1085 + 1.1086 + /* Step 8 */ 1.1087 + for (i = 0; i < dbMaskLen; i++) { 1.1088 + db[i] ^= em[i]; 1.1089 + } 1.1090 + 1.1091 + /* Step 9 */ 1.1092 + db[0] &= 0x7f; 1.1093 + 1.1094 + /* Step 10 */ 1.1095 + for (i = 0; i < (dbMaskLen - saltLen - 1); i++) { 1.1096 + if (db[i] != 0) { 1.1097 + PORT_Free(db); 1.1098 + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); 1.1099 + return SECFailure; 1.1100 + } 1.1101 + } 1.1102 + if (db[dbMaskLen - saltLen - 1] != 0x01) { 1.1103 + PORT_Free(db); 1.1104 + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); 1.1105 + return SECFailure; 1.1106 + } 1.1107 + 1.1108 + /* Step 12 + 13 */ 1.1109 + H_ = (unsigned char *)PORT_Alloc(hash->length); 1.1110 + if (H_ == NULL) { 1.1111 + PORT_Free(db); 1.1112 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.1113 + return SECFailure; 1.1114 + } 1.1115 + hash_context = (*hash->create)(); 1.1116 + if (hash_context == NULL) { 1.1117 + PORT_Free(db); 1.1118 + PORT_Free(H_); 1.1119 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.1120 + return SECFailure; 1.1121 + } 1.1122 + (*hash->begin)(hash_context); 1.1123 + (*hash->update)(hash_context, eightZeros, 8); 1.1124 + (*hash->update)(hash_context, mHash, hash->length); 1.1125 + (*hash->update)(hash_context, &db[dbMaskLen - saltLen], saltLen); 1.1126 + (*hash->end)(hash_context, H_, &i, hash->length); 1.1127 + (*hash->destroy)(hash_context, PR_TRUE); 1.1128 + 1.1129 + PORT_Free(db); 1.1130 + 1.1131 + /* Step 14 */ 1.1132 + if (PORT_Memcmp(H_, &em[dbMaskLen], hash->length) != 0) { 1.1133 + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); 1.1134 + rv = SECFailure; 1.1135 + } else { 1.1136 + rv = SECSuccess; 1.1137 + } 1.1138 + 1.1139 + PORT_Free(H_); 1.1140 + return rv; 1.1141 +} 1.1142 + 1.1143 +SECStatus 1.1144 +RSA_SignPSS(RSAPrivateKey * key, 1.1145 + HASH_HashType hashAlg, 1.1146 + HASH_HashType maskHashAlg, 1.1147 + const unsigned char * salt, 1.1148 + unsigned int saltLength, 1.1149 + unsigned char * output, 1.1150 + unsigned int * outputLen, 1.1151 + unsigned int maxOutputLen, 1.1152 + const unsigned char * input, 1.1153 + unsigned int inputLen) 1.1154 +{ 1.1155 + SECStatus rv = SECSuccess; 1.1156 + unsigned int modulusLen = rsa_modulusLen(&key->modulus); 1.1157 + unsigned char *pssEncoded = NULL; 1.1158 + 1.1159 + if (maxOutputLen < modulusLen) { 1.1160 + PORT_SetError(SEC_ERROR_OUTPUT_LEN); 1.1161 + return SECFailure; 1.1162 + } 1.1163 + 1.1164 + if ((hashAlg == HASH_AlgNULL) || (maskHashAlg == HASH_AlgNULL)) { 1.1165 + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); 1.1166 + return SECFailure; 1.1167 + } 1.1168 + 1.1169 + pssEncoded = (unsigned char *)PORT_Alloc(modulusLen); 1.1170 + if (pssEncoded == NULL) { 1.1171 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.1172 + return SECFailure; 1.1173 + } 1.1174 + rv = emsa_pss_encode(pssEncoded, modulusLen, input, hashAlg, 1.1175 + maskHashAlg, salt, saltLength); 1.1176 + if (rv != SECSuccess) 1.1177 + goto done; 1.1178 + 1.1179 + rv = RSA_PrivateKeyOpDoubleChecked(key, output, pssEncoded); 1.1180 + *outputLen = modulusLen; 1.1181 + 1.1182 +done: 1.1183 + PORT_Free(pssEncoded); 1.1184 + return rv; 1.1185 +} 1.1186 + 1.1187 +SECStatus 1.1188 +RSA_CheckSignPSS(RSAPublicKey * key, 1.1189 + HASH_HashType hashAlg, 1.1190 + HASH_HashType maskHashAlg, 1.1191 + unsigned int saltLength, 1.1192 + const unsigned char * sig, 1.1193 + unsigned int sigLen, 1.1194 + const unsigned char * hash, 1.1195 + unsigned int hashLen) 1.1196 +{ 1.1197 + SECStatus rv; 1.1198 + unsigned int modulusLen = rsa_modulusLen(&key->modulus); 1.1199 + unsigned char * buffer; 1.1200 + 1.1201 + if (sigLen != modulusLen) { 1.1202 + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); 1.1203 + return SECFailure; 1.1204 + } 1.1205 + 1.1206 + if ((hashAlg == HASH_AlgNULL) || (maskHashAlg == HASH_AlgNULL)) { 1.1207 + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); 1.1208 + return SECFailure; 1.1209 + } 1.1210 + 1.1211 + buffer = (unsigned char *)PORT_Alloc(modulusLen); 1.1212 + if (!buffer) { 1.1213 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.1214 + return SECFailure; 1.1215 + } 1.1216 + 1.1217 + rv = RSA_PublicKeyOp(key, buffer, sig); 1.1218 + if (rv != SECSuccess) { 1.1219 + PORT_Free(buffer); 1.1220 + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); 1.1221 + return SECFailure; 1.1222 + } 1.1223 + 1.1224 + rv = emsa_pss_verify(hash, buffer, modulusLen, hashAlg, 1.1225 + maskHashAlg, saltLength); 1.1226 + PORT_Free(buffer); 1.1227 + 1.1228 + return rv; 1.1229 +} 1.1230 + 1.1231 +/* XXX Doesn't set error code */ 1.1232 +SECStatus 1.1233 +RSA_Sign(RSAPrivateKey * key, 1.1234 + unsigned char * output, 1.1235 + unsigned int * outputLen, 1.1236 + unsigned int maxOutputLen, 1.1237 + const unsigned char * input, 1.1238 + unsigned int inputLen) 1.1239 +{ 1.1240 + SECStatus rv = SECSuccess; 1.1241 + unsigned int modulusLen = rsa_modulusLen(&key->modulus); 1.1242 + SECItem formatted; 1.1243 + SECItem unformatted; 1.1244 + 1.1245 + if (maxOutputLen < modulusLen) 1.1246 + return SECFailure; 1.1247 + 1.1248 + unformatted.len = inputLen; 1.1249 + unformatted.data = (unsigned char*)input; 1.1250 + formatted.data = NULL; 1.1251 + rv = rsa_FormatBlock(&formatted, modulusLen, RSA_BlockPrivate, 1.1252 + &unformatted); 1.1253 + if (rv != SECSuccess) 1.1254 + goto done; 1.1255 + 1.1256 + rv = RSA_PrivateKeyOpDoubleChecked(key, output, formatted.data); 1.1257 + *outputLen = modulusLen; 1.1258 + 1.1259 + goto done; 1.1260 + 1.1261 +done: 1.1262 + if (formatted.data != NULL) 1.1263 + PORT_ZFree(formatted.data, modulusLen); 1.1264 + return rv; 1.1265 +} 1.1266 + 1.1267 +/* XXX Doesn't set error code */ 1.1268 +SECStatus 1.1269 +RSA_CheckSign(RSAPublicKey * key, 1.1270 + const unsigned char * sig, 1.1271 + unsigned int sigLen, 1.1272 + const unsigned char * data, 1.1273 + unsigned int dataLen) 1.1274 +{ 1.1275 + SECStatus rv; 1.1276 + unsigned int modulusLen = rsa_modulusLen(&key->modulus); 1.1277 + unsigned int i; 1.1278 + unsigned char * buffer; 1.1279 + 1.1280 + if (sigLen != modulusLen) 1.1281 + goto failure; 1.1282 + /* 1.1283 + * 0x00 || BT || Pad || 0x00 || ActualData 1.1284 + * 1.1285 + * The "3" below is the first octet + the second octet + the 0x00 1.1286 + * octet that always comes just before the ActualData. 1.1287 + */ 1.1288 + if (dataLen > modulusLen - (3 + RSA_BLOCK_MIN_PAD_LEN)) 1.1289 + goto failure; 1.1290 + 1.1291 + buffer = (unsigned char *)PORT_Alloc(modulusLen + 1); 1.1292 + if (!buffer) 1.1293 + goto failure; 1.1294 + 1.1295 + rv = RSA_PublicKeyOp(key, buffer, sig); 1.1296 + if (rv != SECSuccess) 1.1297 + goto loser; 1.1298 + 1.1299 + /* 1.1300 + * check the padding that was used 1.1301 + */ 1.1302 + if (buffer[0] != RSA_BLOCK_FIRST_OCTET || 1.1303 + buffer[1] != (unsigned char)RSA_BlockPrivate) { 1.1304 + goto loser; 1.1305 + } 1.1306 + for (i = 2; i < modulusLen - dataLen - 1; i++) { 1.1307 + if (buffer[i] != RSA_BLOCK_PRIVATE_PAD_OCTET) 1.1308 + goto loser; 1.1309 + } 1.1310 + if (buffer[i] != RSA_BLOCK_AFTER_PAD_OCTET) 1.1311 + goto loser; 1.1312 + 1.1313 + /* 1.1314 + * make sure we get the same results 1.1315 + */ 1.1316 + if (PORT_Memcmp(buffer + modulusLen - dataLen, data, dataLen) != 0) 1.1317 + goto loser; 1.1318 + 1.1319 + PORT_Free(buffer); 1.1320 + return SECSuccess; 1.1321 + 1.1322 +loser: 1.1323 + PORT_Free(buffer); 1.1324 +failure: 1.1325 + return SECFailure; 1.1326 +} 1.1327 + 1.1328 +/* XXX Doesn't set error code */ 1.1329 +SECStatus 1.1330 +RSA_CheckSignRecover(RSAPublicKey * key, 1.1331 + unsigned char * output, 1.1332 + unsigned int * outputLen, 1.1333 + unsigned int maxOutputLen, 1.1334 + const unsigned char * sig, 1.1335 + unsigned int sigLen) 1.1336 +{ 1.1337 + SECStatus rv; 1.1338 + unsigned int modulusLen = rsa_modulusLen(&key->modulus); 1.1339 + unsigned int i; 1.1340 + unsigned char * buffer; 1.1341 + 1.1342 + if (sigLen != modulusLen) 1.1343 + goto failure; 1.1344 + 1.1345 + buffer = (unsigned char *)PORT_Alloc(modulusLen + 1); 1.1346 + if (!buffer) 1.1347 + goto failure; 1.1348 + 1.1349 + rv = RSA_PublicKeyOp(key, buffer, sig); 1.1350 + if (rv != SECSuccess) 1.1351 + goto loser; 1.1352 + *outputLen = 0; 1.1353 + 1.1354 + /* 1.1355 + * check the padding that was used 1.1356 + */ 1.1357 + if (buffer[0] != RSA_BLOCK_FIRST_OCTET || 1.1358 + buffer[1] != (unsigned char)RSA_BlockPrivate) { 1.1359 + goto loser; 1.1360 + } 1.1361 + for (i = 2; i < modulusLen; i++) { 1.1362 + if (buffer[i] == RSA_BLOCK_AFTER_PAD_OCTET) { 1.1363 + *outputLen = modulusLen - i - 1; 1.1364 + break; 1.1365 + } 1.1366 + if (buffer[i] != RSA_BLOCK_PRIVATE_PAD_OCTET) 1.1367 + goto loser; 1.1368 + } 1.1369 + if (*outputLen == 0) 1.1370 + goto loser; 1.1371 + if (*outputLen > maxOutputLen) 1.1372 + goto loser; 1.1373 + 1.1374 + PORT_Memcpy(output, buffer + modulusLen - *outputLen, *outputLen); 1.1375 + 1.1376 + PORT_Free(buffer); 1.1377 + return SECSuccess; 1.1378 + 1.1379 +loser: 1.1380 + PORT_Free(buffer); 1.1381 +failure: 1.1382 + return SECFailure; 1.1383 +}