security/nss/lib/freebl/rsapkcs.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 /*
     6  * RSA PKCS#1 v2.1 (RFC 3447) operations
     7  */
     9 #ifdef FREEBL_NO_DEPEND
    10 #include "stubs.h"
    11 #endif
    13 #include "secerr.h"
    15 #include "blapi.h"
    16 #include "secitem.h"
    17 #include "blapii.h"
    19 #define RSA_BLOCK_MIN_PAD_LEN            8
    20 #define RSA_BLOCK_FIRST_OCTET            0x00
    21 #define RSA_BLOCK_PRIVATE_PAD_OCTET      0xff
    22 #define RSA_BLOCK_AFTER_PAD_OCTET        0x00
    24 /*
    25  * RSA block types
    26  *
    27  * The values of RSA_BlockPrivate and RSA_BlockPublic are fixed.
    28  * The value of RSA_BlockRaw isn't fixed by definition, but we are keeping
    29  * the value that NSS has been using in the past.
    30  */
    31 typedef enum {
    32     RSA_BlockPrivate = 1,   /* pad for a private-key operation */
    33     RSA_BlockPublic = 2,    /* pad for a public-key operation */
    34     RSA_BlockRaw = 4        /* simply justify the block appropriately */
    35 } RSA_BlockType;
    37 /* Needed for RSA-PSS functions */
    38 static const unsigned char eightZeros[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
    40 /* Constant time comparison of a single byte.
    41  * Returns 1 iff a == b, otherwise returns 0.
    42  * Note: For ranges of bytes, use constantTimeCompare.
    43  */
    44 static unsigned char constantTimeEQ8(unsigned char a, unsigned char b) {
    45     unsigned char c = ~((a - b) | (b - a));
    46     c >>= 7;
    47     return c;
    48 }
    50 /* Constant time comparison of a range of bytes.
    51  * Returns 1 iff len bytes of a are identical to len bytes of b, otherwise
    52  * returns 0.
    53  */
    54 static unsigned char constantTimeCompare(const unsigned char *a,
    55                                          const unsigned char *b,
    56                                          unsigned int len) {
    57     unsigned char tmp = 0;
    58     unsigned int i;
    59     for (i = 0; i < len; ++i, ++a, ++b)
    60         tmp |= *a ^ *b;
    61     return constantTimeEQ8(0x00, tmp);
    62 }
    64 /* Constant time conditional.
    65  * Returns a if c is 1, or b if c is 0. The result is undefined if c is
    66  * not 0 or 1.
    67  */
    68 static unsigned int constantTimeCondition(unsigned int c,
    69                                           unsigned int a,
    70                                           unsigned int b)
    71 {
    72     return (~(c - 1) & a) | ((c - 1) & b);
    73 }
    75 static unsigned int
    76 rsa_modulusLen(SECItem * modulus)
    77 {
    78     unsigned char byteZero = modulus->data[0];
    79     unsigned int modLen = modulus->len - !byteZero;
    80     return modLen;
    81 }
    83 /*
    84  * Format one block of data for public/private key encryption using
    85  * the rules defined in PKCS #1.
    86  */
    87 static unsigned char *
    88 rsa_FormatOneBlock(unsigned modulusLen,
    89                    RSA_BlockType blockType,
    90                    SECItem * data)
    91 {
    92     unsigned char *block;
    93     unsigned char *bp;
    94     int padLen;
    95     int i, j;
    96     SECStatus rv;
    98     block = (unsigned char *) PORT_Alloc(modulusLen);
    99     if (block == NULL)
   100         return NULL;
   102     bp = block;
   104     /*
   105      * All RSA blocks start with two octets:
   106      *	0x00 || BlockType
   107      */
   108     *bp++ = RSA_BLOCK_FIRST_OCTET;
   109     *bp++ = (unsigned char) blockType;
   111     switch (blockType) {
   113       /*
   114        * Blocks intended for private-key operation.
   115        */
   116       case RSA_BlockPrivate:	 /* preferred method */
   117         /*
   118          * 0x00 || BT || Pad || 0x00 || ActualData
   119          *   1      1   padLen    1      data->len
   120          * Pad is either all 0x00 or all 0xff bytes, depending on blockType.
   121          */
   122         padLen = modulusLen - data->len - 3;
   123         PORT_Assert(padLen >= RSA_BLOCK_MIN_PAD_LEN);
   124         if (padLen < RSA_BLOCK_MIN_PAD_LEN) {
   125             PORT_Free(block);
   126             return NULL;
   127         }
   128         PORT_Memset(bp, RSA_BLOCK_PRIVATE_PAD_OCTET, padLen);
   129         bp += padLen;
   130         *bp++ = RSA_BLOCK_AFTER_PAD_OCTET;
   131         PORT_Memcpy(bp, data->data, data->len);
   132         break;
   134       /*
   135        * Blocks intended for public-key operation.
   136        */
   137       case RSA_BlockPublic:
   138         /*
   139          * 0x00 || BT || Pad || 0x00 || ActualData
   140          *   1      1   padLen    1      data->len
   141          * Pad is all non-zero random bytes.
   142          *
   143          * Build the block left to right.
   144          * Fill the entire block from Pad to the end with random bytes.
   145          * Use the bytes after Pad as a supply of extra random bytes from
   146          * which to find replacements for the zero bytes in Pad.
   147          * If we need more than that, refill the bytes after Pad with
   148          * new random bytes as necessary.
   149          */
   150         padLen = modulusLen - (data->len + 3);
   151         PORT_Assert(padLen >= RSA_BLOCK_MIN_PAD_LEN);
   152         if (padLen < RSA_BLOCK_MIN_PAD_LEN) {
   153             PORT_Free(block);
   154             return NULL;
   155         }
   156         j = modulusLen - 2;
   157         rv = RNG_GenerateGlobalRandomBytes(bp, j);
   158         if (rv == SECSuccess) {
   159             for (i = 0; i < padLen; ) {
   160                 unsigned char repl;
   161                 /* Pad with non-zero random data. */
   162                 if (bp[i] != RSA_BLOCK_AFTER_PAD_OCTET) {
   163                     ++i;
   164                     continue;
   165                 }
   166                 if (j <= padLen) {
   167                     rv = RNG_GenerateGlobalRandomBytes(bp + padLen,
   168                                           modulusLen - (2 + padLen));
   169                     if (rv != SECSuccess)
   170                         break;
   171                     j = modulusLen - 2;
   172                 }
   173                 do {
   174                     repl = bp[--j];
   175                 } while (repl == RSA_BLOCK_AFTER_PAD_OCTET && j > padLen);
   176                 if (repl != RSA_BLOCK_AFTER_PAD_OCTET) {
   177                     bp[i++] = repl;
   178                 }
   179             }
   180         }
   181         if (rv != SECSuccess) {
   182             PORT_Free(block);
   183             PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   184             return NULL;
   185         }
   186         bp += padLen;
   187         *bp++ = RSA_BLOCK_AFTER_PAD_OCTET;
   188         PORT_Memcpy(bp, data->data, data->len);
   189         break;
   191       default:
   192         PORT_Assert(0);
   193         PORT_Free(block);
   194         return NULL;
   195     }
   197     return block;
   198 }
   200 static SECStatus
   201 rsa_FormatBlock(SECItem * result,
   202                 unsigned modulusLen,
   203                 RSA_BlockType blockType,
   204                 SECItem * data)
   205 {
   206     switch (blockType) {
   207       case RSA_BlockPrivate:
   208       case RSA_BlockPublic:
   209         /*
   210          * 0x00 || BT || Pad || 0x00 || ActualData
   211          *
   212          * The "3" below is the first octet + the second octet + the 0x00
   213          * octet that always comes just before the ActualData.
   214          */
   215         PORT_Assert(data->len <= (modulusLen - (3 + RSA_BLOCK_MIN_PAD_LEN)));
   217         result->data = rsa_FormatOneBlock(modulusLen, blockType, data);
   218         if (result->data == NULL) {
   219             result->len = 0;
   220             return SECFailure;
   221         }
   222         result->len = modulusLen;
   224         break;
   226       case RSA_BlockRaw:
   227         /*
   228          * Pad || ActualData
   229          * Pad is zeros. The application is responsible for recovering
   230          * the actual data.
   231          */
   232         if (data->len > modulusLen ) {
   233             return SECFailure;
   234         }
   235         result->data = (unsigned char*)PORT_ZAlloc(modulusLen);
   236         result->len = modulusLen;
   237         PORT_Memcpy(result->data + (modulusLen - data->len),
   238                     data->data, data->len);
   239         break;
   241       default:
   242         PORT_Assert(0);
   243         result->data = NULL;
   244         result->len = 0;
   245         return SECFailure;
   246     }
   248     return SECSuccess;
   249 }
   251 /*
   252  * Mask generation function MGF1 as defined in PKCS #1 v2.1 / RFC 3447.
   253  */
   254 static SECStatus
   255 MGF1(HASH_HashType hashAlg,
   256      unsigned char * mask,
   257      unsigned int maskLen,
   258      const unsigned char * mgfSeed,
   259      unsigned int mgfSeedLen)
   260 {
   261     unsigned int digestLen;
   262     PRUint32 counter;
   263     PRUint32 rounds;
   264     unsigned char * tempHash;
   265     unsigned char * temp;
   266     const SECHashObject * hash;
   267     void * hashContext;
   268     unsigned char C[4];
   270     hash = HASH_GetRawHashObject(hashAlg);
   271     if (hash == NULL)
   272         return SECFailure;
   274     hashContext = (*hash->create)();
   275     rounds = (maskLen + hash->length - 1) / hash->length;
   276     for (counter = 0; counter < rounds; counter++) {
   277         C[0] = (unsigned char)((counter >> 24) & 0xff);
   278         C[1] = (unsigned char)((counter >> 16) & 0xff);
   279         C[2] = (unsigned char)((counter >> 8) & 0xff);
   280         C[3] = (unsigned char)(counter & 0xff);
   282         /* This could be optimized when the clone functions in
   283          * rawhash.c are implemented. */
   284         (*hash->begin)(hashContext);
   285         (*hash->update)(hashContext, mgfSeed, mgfSeedLen);
   286         (*hash->update)(hashContext, C, sizeof C);
   288         tempHash = mask + counter * hash->length;
   289         if (counter != (rounds - 1)) {
   290             (*hash->end)(hashContext, tempHash, &digestLen, hash->length);
   291         } else { /* we're in the last round and need to cut the hash */
   292             temp = (unsigned char *)PORT_Alloc(hash->length);
   293             (*hash->end)(hashContext, temp, &digestLen, hash->length);
   294             PORT_Memcpy(tempHash, temp, maskLen - counter * hash->length);
   295             PORT_Free(temp);
   296         }
   297     }
   298     (*hash->destroy)(hashContext, PR_TRUE);
   300     return SECSuccess;
   301 }
   303 /* XXX Doesn't set error code */
   304 SECStatus
   305 RSA_SignRaw(RSAPrivateKey * key,
   306             unsigned char * output,
   307             unsigned int * outputLen,
   308             unsigned int maxOutputLen,
   309             const unsigned char * data,
   310             unsigned int dataLen)
   311 {
   312     SECStatus rv = SECSuccess;
   313     unsigned int modulusLen = rsa_modulusLen(&key->modulus);
   314     SECItem formatted;
   315     SECItem unformatted;
   317     if (maxOutputLen < modulusLen)
   318         return SECFailure;
   320     unformatted.len  = dataLen;
   321     unformatted.data = (unsigned char*)data;
   322     formatted.data   = NULL;
   323     rv = rsa_FormatBlock(&formatted, modulusLen, RSA_BlockRaw, &unformatted);
   324     if (rv != SECSuccess)
   325         goto done;
   327     rv = RSA_PrivateKeyOpDoubleChecked(key, output, formatted.data);
   328     *outputLen = modulusLen;
   330 done:
   331     if (formatted.data != NULL)
   332         PORT_ZFree(formatted.data, modulusLen);
   333     return rv;
   334 }
   336 /* XXX Doesn't set error code */
   337 SECStatus
   338 RSA_CheckSignRaw(RSAPublicKey * key,
   339                  const unsigned char * sig,
   340                  unsigned int sigLen,
   341                  const unsigned char * hash,
   342                  unsigned int hashLen)
   343 {
   344     SECStatus rv;
   345     unsigned int modulusLen = rsa_modulusLen(&key->modulus);
   346     unsigned char * buffer;
   348     if (sigLen != modulusLen)
   349         goto failure;
   350     if (hashLen > modulusLen)
   351         goto failure;
   353     buffer = (unsigned char *)PORT_Alloc(modulusLen + 1);
   354     if (!buffer)
   355         goto failure;
   357     rv = RSA_PublicKeyOp(key, buffer, sig);
   358     if (rv != SECSuccess)
   359         goto loser;
   361     /*
   362      * make sure we get the same results
   363      */
   364     /* XXX(rsleevi): Constant time */
   365     /* NOTE: should we verify the leading zeros? */
   366     if (PORT_Memcmp(buffer + (modulusLen - hashLen), hash, hashLen) != 0)
   367         goto loser;
   369     PORT_Free(buffer);
   370     return SECSuccess;
   372 loser:
   373     PORT_Free(buffer);
   374 failure:
   375     return SECFailure;
   376 }
   378 /* XXX Doesn't set error code */
   379 SECStatus
   380 RSA_CheckSignRecoverRaw(RSAPublicKey * key,
   381                         unsigned char * data,
   382                         unsigned int * dataLen,
   383                         unsigned int maxDataLen,
   384                         const unsigned char * sig,
   385                         unsigned int sigLen)
   386 {
   387     SECStatus rv;
   388     unsigned int modulusLen = rsa_modulusLen(&key->modulus);
   390     if (sigLen != modulusLen)
   391         goto failure;
   392     if (maxDataLen < modulusLen)
   393         goto failure;
   395     rv = RSA_PublicKeyOp(key, data, sig);
   396     if (rv != SECSuccess)
   397         goto failure;
   399     *dataLen = modulusLen;
   400     return SECSuccess;
   402 failure:
   403     return SECFailure;
   404 }
   406 /* XXX Doesn't set error code */
   407 SECStatus
   408 RSA_EncryptRaw(RSAPublicKey * key,
   409                unsigned char * output,
   410                unsigned int * outputLen,
   411                unsigned int maxOutputLen,
   412                const unsigned char * input,
   413                unsigned int inputLen)
   414 {
   415     SECStatus rv;
   416     unsigned int modulusLen = rsa_modulusLen(&key->modulus);
   417     SECItem formatted;
   418     SECItem unformatted;
   420     formatted.data = NULL;
   421     if (maxOutputLen < modulusLen)
   422         goto failure;
   424     unformatted.len  = inputLen;
   425     unformatted.data = (unsigned char*)input;
   426     formatted.data   = NULL;
   427     rv = rsa_FormatBlock(&formatted, modulusLen, RSA_BlockRaw, &unformatted);
   428     if (rv != SECSuccess)
   429         goto failure;
   431     rv = RSA_PublicKeyOp(key, output, formatted.data);
   432     if (rv != SECSuccess)
   433         goto failure;
   435     PORT_ZFree(formatted.data, modulusLen);
   436     *outputLen = modulusLen;
   437     return SECSuccess;
   439 failure:
   440     if (formatted.data != NULL)
   441         PORT_ZFree(formatted.data, modulusLen);
   442     return SECFailure;
   443 }
   445 /* XXX Doesn't set error code */
   446 SECStatus
   447 RSA_DecryptRaw(RSAPrivateKey * key,
   448                unsigned char * output,
   449                unsigned int * outputLen,
   450                unsigned int maxOutputLen,
   451                const unsigned char * input,
   452                unsigned int inputLen)
   453 {
   454     SECStatus rv;
   455     unsigned int modulusLen = rsa_modulusLen(&key->modulus);
   457     if (modulusLen > maxOutputLen)
   458         goto failure;
   459     if (inputLen != modulusLen)
   460         goto failure;
   462     rv = RSA_PrivateKeyOp(key, output, input);
   463     if (rv != SECSuccess)
   464         goto failure;
   466     *outputLen = modulusLen;
   467     return SECSuccess;
   469 failure:
   470     return SECFailure;
   471 }
   473 /*
   474  * Decodes an EME-OAEP encoded block, validating the encoding in constant
   475  * time.
   476  * Described in RFC 3447, section 7.1.2.
   477  * input contains the encoded block, after decryption.
   478  * label is the optional value L that was associated with the message.
   479  * On success, the original message and message length will be stored in
   480  * output and outputLen.
   481  */
   482 static SECStatus
   483 eme_oaep_decode(unsigned char * output,
   484                 unsigned int * outputLen,
   485                 unsigned int maxOutputLen,
   486                 const unsigned char * input,
   487                 unsigned int inputLen,
   488                 HASH_HashType hashAlg,
   489                 HASH_HashType maskHashAlg,
   490                 const unsigned char * label,
   491                 unsigned int labelLen)
   492 {
   493     const SECHashObject * hash;
   494     void * hashContext;
   495     SECStatus rv = SECFailure;
   496     unsigned char labelHash[HASH_LENGTH_MAX];
   497     unsigned int i;
   498     unsigned int maskLen;
   499     unsigned int paddingOffset;
   500     unsigned char * mask = NULL;
   501     unsigned char * tmpOutput = NULL;
   502     unsigned char isGood;
   503     unsigned char foundPaddingEnd;
   505     hash = HASH_GetRawHashObject(hashAlg);
   507     /* 1.c */
   508     if (inputLen < (hash->length * 2) + 2) {
   509         PORT_SetError(SEC_ERROR_INPUT_LEN);
   510         return SECFailure;
   511     }
   513     /* Step 3.a - Generate lHash */
   514     hashContext = (*hash->create)();
   515     if (hashContext == NULL) {
   516         PORT_SetError(SEC_ERROR_NO_MEMORY);
   517         return SECFailure;
   518     }
   519     (*hash->begin)(hashContext);
   520     if (labelLen > 0)
   521         (*hash->update)(hashContext, label, labelLen);
   522     (*hash->end)(hashContext, labelHash, &i, sizeof(labelHash));
   523     (*hash->destroy)(hashContext, PR_TRUE);
   525     tmpOutput = (unsigned char*)PORT_Alloc(inputLen);
   526     if (tmpOutput == NULL) {
   527         PORT_SetError(SEC_ERROR_NO_MEMORY);
   528         goto done;
   529     }
   531     maskLen = inputLen - hash->length - 1;
   532     mask = (unsigned char*)PORT_Alloc(maskLen);
   533     if (mask == NULL) {
   534         PORT_SetError(SEC_ERROR_NO_MEMORY);
   535         goto done;
   536     }
   538     PORT_Memcpy(tmpOutput, input, inputLen);
   540     /* 3.c - Generate seedMask */
   541     MGF1(maskHashAlg, mask, hash->length, &tmpOutput[1 + hash->length],
   542          inputLen - hash->length - 1);
   543     /* 3.d - Unmask seed */
   544     for (i = 0; i < hash->length; ++i)
   545         tmpOutput[1 + i] ^= mask[i];
   547     /* 3.e - Generate dbMask */
   548     MGF1(maskHashAlg, mask, maskLen, &tmpOutput[1], hash->length);
   549     /* 3.f - Unmask DB */
   550     for (i = 0; i < maskLen; ++i)
   551         tmpOutput[1 + hash->length + i] ^= mask[i];
   553     /* 3.g - Compare Y, lHash, and PS in constant time
   554      * Warning: This code is timing dependent and must not disclose which of
   555      * these were invalid.
   556      */
   557     paddingOffset = 0;
   558     isGood = 1;
   559     foundPaddingEnd = 0;
   561     /* Compare Y */
   562     isGood &= constantTimeEQ8(0x00, tmpOutput[0]);
   564     /* Compare lHash and lHash' */
   565     isGood &= constantTimeCompare(&labelHash[0],
   566                                   &tmpOutput[1 + hash->length],
   567                                   hash->length);
   569     /* Compare that the padding is zero or more zero octets, followed by a
   570      * 0x01 octet */
   571     for (i = 1 + (hash->length * 2); i < inputLen; ++i) {
   572         unsigned char isZero = constantTimeEQ8(0x00, tmpOutput[i]);
   573         unsigned char isOne = constantTimeEQ8(0x01, tmpOutput[i]);
   574         /* non-constant time equivalent:
   575          * if (tmpOutput[i] == 0x01 && !foundPaddingEnd)
   576          *     paddingOffset = i;
   577          */
   578         paddingOffset = constantTimeCondition(isOne & ~foundPaddingEnd, i,
   579                                               paddingOffset);
   580         /* non-constant time equivalent:
   581          * if (tmpOutput[i] == 0x01)
   582          *    foundPaddingEnd = true;
   583          *
   584          * Note: This may yield false positives, as it will be set whenever
   585          * a 0x01 byte is encountered. If there was bad padding (eg:
   586          * 0x03 0x02 0x01), foundPaddingEnd will still be set to true, and
   587          * paddingOffset will still be set to 2.
   588          */
   589         foundPaddingEnd = constantTimeCondition(isOne, 1, foundPaddingEnd);
   590         /* non-constant time equivalent:
   591          * if (tmpOutput[i] != 0x00 && tmpOutput[i] != 0x01 &&
   592          *     !foundPaddingEnd) {
   593          *    isGood = false;
   594          * }
   595          *
   596          * Note: This may yield false positives, as a message (and padding)
   597          * that is entirely zeros will result in isGood still being true. Thus
   598          * it's necessary to check foundPaddingEnd is positive below.
   599          */
   600         isGood = constantTimeCondition(~foundPaddingEnd & ~isZero, 0, isGood);
   601     }
   603     /* While both isGood and foundPaddingEnd may have false positives, they
   604      * cannot BOTH have false positives. If both are not true, then an invalid
   605      * message was received. Note, this comparison must still be done in constant
   606      * time so as not to leak either condition.
   607      */
   608     if (!(isGood & foundPaddingEnd)) {
   609         PORT_SetError(SEC_ERROR_BAD_DATA);
   610         goto done;
   611     }
   613     /* End timing dependent code */
   615     ++paddingOffset; /* Skip the 0x01 following the end of PS */
   617     *outputLen = inputLen - paddingOffset;
   618     if (*outputLen > maxOutputLen) {
   619         PORT_SetError(SEC_ERROR_OUTPUT_LEN);
   620         goto done;
   621     }
   623     if (*outputLen)
   624         PORT_Memcpy(output, &tmpOutput[paddingOffset], *outputLen);
   625     rv = SECSuccess;
   627 done:
   628     if (mask)
   629         PORT_ZFree(mask, maskLen);
   630     if (tmpOutput)
   631         PORT_ZFree(tmpOutput, inputLen);
   632     return rv;
   633 }
   635 /*
   636  * Generate an EME-OAEP encoded block for encryption
   637  * Described in RFC 3447, section 7.1.1
   638  * We use input instead of M for the message to be encrypted
   639  * label is the optional value L to be associated with the message.
   640  */
   641 static SECStatus
   642 eme_oaep_encode(unsigned char * em,
   643                 unsigned int emLen,
   644                 const unsigned char * input,
   645                 unsigned int inputLen,
   646                 HASH_HashType hashAlg,
   647                 HASH_HashType maskHashAlg,
   648                 const unsigned char * label,
   649                 unsigned int labelLen,
   650                 const unsigned char * seed,
   651                 unsigned int seedLen)
   652 {
   653     const SECHashObject * hash;
   654     void * hashContext;
   655     SECStatus rv;
   656     unsigned char * mask;
   657     unsigned int reservedLen;
   658     unsigned int dbMaskLen;
   659     unsigned int i;
   661     hash = HASH_GetRawHashObject(hashAlg);
   662     PORT_Assert(seed == NULL || seedLen == hash->length);
   664     /* Step 1.b */
   665     reservedLen = (2 * hash->length) + 2;
   666     if (emLen < reservedLen || inputLen > (emLen - reservedLen)) {
   667         PORT_SetError(SEC_ERROR_INPUT_LEN);
   668         return SECFailure;
   669     }
   671     /*
   672      * From RFC 3447, Section 7.1
   673      *                      +----------+---------+-------+
   674      *                 DB = |  lHash   |    PS   |   M   |
   675      *                      +----------+---------+-------+
   676      *                                     |
   677      *           +----------+              V
   678      *           |   seed   |--> MGF ---> xor
   679      *           +----------+              |
   680      *                 |                   |
   681      *        +--+     V                   |
   682      *        |00|    xor <----- MGF <-----|
   683      *        +--+     |                   |
   684      *          |      |                   |
   685      *          V      V                   V
   686      *        +--+----------+----------------------------+
   687      *  EM =  |00|maskedSeed|          maskedDB          |
   688      *        +--+----------+----------------------------+
   689      *
   690      * We use mask to hold the result of the MGF functions, and all other
   691      * values are generated in their final resting place.
   692      */
   693     *em = 0x00;
   695     /* Step 2.a - Generate lHash */
   696     hashContext = (*hash->create)();
   697     if (hashContext == NULL) {
   698         PORT_SetError(SEC_ERROR_NO_MEMORY);
   699         return SECFailure;
   700     }
   701     (*hash->begin)(hashContext);
   702     if (labelLen > 0)
   703         (*hash->update)(hashContext, label, labelLen);
   704     (*hash->end)(hashContext, &em[1 + hash->length], &i, hash->length);
   705     (*hash->destroy)(hashContext, PR_TRUE);
   707     /* Step 2.b - Generate PS */
   708     if (emLen - reservedLen - inputLen > 0) {
   709         PORT_Memset(em + 1 + (hash->length * 2), 0x00,
   710                     emLen - reservedLen - inputLen);
   711     }
   713     /* Step 2.c. - Generate DB
   714      * DB = lHash || PS || 0x01 || M
   715      * Note that PS and lHash have already been placed into em at their
   716      * appropriate offsets. This just copies M into place
   717      */
   718     em[emLen - inputLen - 1] = 0x01;
   719     if (inputLen)
   720         PORT_Memcpy(em + emLen - inputLen, input, inputLen);
   722     if (seed == NULL) {
   723         /* Step 2.d - Generate seed */
   724         rv = RNG_GenerateGlobalRandomBytes(em + 1, hash->length);
   725         if (rv != SECSuccess) {
   726             return rv;
   727         }
   728     } else {
   729         /* For Known Answer Tests, copy the supplied seed. */
   730         PORT_Memcpy(em + 1, seed, seedLen);
   731     }
   733     /* Step 2.e - Generate dbMask*/
   734     dbMaskLen = emLen - hash->length - 1;
   735     mask = (unsigned char*)PORT_Alloc(dbMaskLen);
   736     if (mask == NULL) {
   737         PORT_SetError(SEC_ERROR_NO_MEMORY);
   738         return SECFailure;
   739     }
   740     MGF1(maskHashAlg, mask, dbMaskLen, em + 1, hash->length);
   741     /* Step 2.f - Compute maskedDB*/
   742     for (i = 0; i < dbMaskLen; ++i)
   743         em[1 + hash->length + i] ^= mask[i];
   745     /* Step 2.g - Generate seedMask */
   746     MGF1(maskHashAlg, mask, hash->length, &em[1 + hash->length], dbMaskLen);
   747     /* Step 2.h - Compute maskedSeed */
   748     for (i = 0; i < hash->length; ++i)
   749         em[1 + i] ^= mask[i];
   751     PORT_ZFree(mask, dbMaskLen);
   752     return SECSuccess;
   753 }
   755 SECStatus
   756 RSA_EncryptOAEP(RSAPublicKey * key,
   757                 HASH_HashType hashAlg,
   758                 HASH_HashType maskHashAlg,
   759                 const unsigned char * label,
   760                 unsigned int labelLen,
   761                 const unsigned char * seed,
   762                 unsigned int seedLen,
   763                 unsigned char * output,
   764                 unsigned int * outputLen,
   765                 unsigned int maxOutputLen,
   766                 const unsigned char * input,
   767                 unsigned int inputLen)
   768 {
   769     SECStatus rv = SECFailure;
   770     unsigned int modulusLen = rsa_modulusLen(&key->modulus);
   771     unsigned char * oaepEncoded = NULL;
   773     if (maxOutputLen < modulusLen) {
   774         PORT_SetError(SEC_ERROR_OUTPUT_LEN);
   775         return SECFailure;
   776     }
   778     if ((hashAlg == HASH_AlgNULL) || (maskHashAlg == HASH_AlgNULL)) {
   779         PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
   780         return SECFailure;
   781     }
   783     if ((labelLen == 0 && label != NULL) ||
   784         (labelLen > 0 && label == NULL)) {
   785         PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
   786         return SECFailure;
   787     }
   789     oaepEncoded = (unsigned char *)PORT_Alloc(modulusLen);
   790     if (oaepEncoded == NULL) {
   791         PORT_SetError(SEC_ERROR_NO_MEMORY);
   792         return SECFailure;
   793     }
   794     rv = eme_oaep_encode(oaepEncoded, modulusLen, input, inputLen,
   795                          hashAlg, maskHashAlg, label, labelLen, seed, seedLen);
   796     if (rv != SECSuccess)
   797         goto done;
   799     rv = RSA_PublicKeyOp(key, output, oaepEncoded);
   800     if (rv != SECSuccess)
   801         goto done;
   802     *outputLen = modulusLen;
   804 done:
   805     PORT_Free(oaepEncoded);
   806     return rv;
   807 }
   809 SECStatus
   810 RSA_DecryptOAEP(RSAPrivateKey * key,
   811                 HASH_HashType hashAlg,
   812                 HASH_HashType maskHashAlg,
   813                 const unsigned char * label,
   814                 unsigned int labelLen,
   815                 unsigned char * output,
   816                 unsigned int * outputLen,
   817                 unsigned int maxOutputLen,
   818                 const unsigned char * input,
   819                 unsigned int inputLen)
   820 {
   821     SECStatus rv = SECFailure;
   822     unsigned int modulusLen = rsa_modulusLen(&key->modulus);
   823     unsigned char * oaepEncoded = NULL;
   825     if ((hashAlg == HASH_AlgNULL) || (maskHashAlg == HASH_AlgNULL)) {
   826         PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
   827         return SECFailure;
   828     }
   830     if (inputLen != modulusLen) {
   831         PORT_SetError(SEC_ERROR_INPUT_LEN);
   832         return SECFailure;
   833     }
   835     if ((labelLen == 0 && label != NULL) ||
   836         (labelLen > 0 && label == NULL)) {
   837         PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
   838         return SECFailure;
   839     }
   841     oaepEncoded = (unsigned char *)PORT_Alloc(modulusLen);
   842     if (oaepEncoded == NULL) {
   843         PORT_SetError(SEC_ERROR_NO_MEMORY);
   844         return SECFailure;
   845     }
   847     rv = RSA_PrivateKeyOpDoubleChecked(key, oaepEncoded, input);
   848     if (rv != SECSuccess) {
   849         goto done;
   850     }
   851     rv = eme_oaep_decode(output, outputLen, maxOutputLen, oaepEncoded,
   852                          modulusLen, hashAlg, maskHashAlg, label,
   853                          labelLen);
   855 done:
   856     if (oaepEncoded)
   857         PORT_ZFree(oaepEncoded, modulusLen);
   858     return rv;
   859 }
   861 /* XXX Doesn't set error code */
   862 SECStatus
   863 RSA_EncryptBlock(RSAPublicKey * key,
   864                  unsigned char * output,
   865                  unsigned int * outputLen,
   866                  unsigned int maxOutputLen,
   867                  const unsigned char * input,
   868                  unsigned int inputLen)
   869 {
   870     SECStatus rv;
   871     unsigned int modulusLen = rsa_modulusLen(&key->modulus);
   872     SECItem formatted;
   873     SECItem unformatted;
   875     formatted.data = NULL;
   876     if (maxOutputLen < modulusLen)
   877         goto failure;
   879     unformatted.len  = inputLen;
   880     unformatted.data = (unsigned char*)input;
   881     formatted.data   = NULL;
   882     rv = rsa_FormatBlock(&formatted, modulusLen, RSA_BlockPublic,
   883                          &unformatted);
   884     if (rv != SECSuccess)
   885         goto failure;
   887     rv = RSA_PublicKeyOp(key, output, formatted.data);
   888     if (rv != SECSuccess)
   889         goto failure;
   891     PORT_ZFree(formatted.data, modulusLen);
   892     *outputLen = modulusLen;
   893     return SECSuccess;
   895 failure:
   896     if (formatted.data != NULL)
   897         PORT_ZFree(formatted.data, modulusLen);
   898     return SECFailure;
   899 }
   901 /* XXX Doesn't set error code */
   902 SECStatus
   903 RSA_DecryptBlock(RSAPrivateKey * key,
   904                  unsigned char * output,
   905                  unsigned int * outputLen,
   906                  unsigned int maxOutputLen,
   907                  const unsigned char * input,
   908                  unsigned int inputLen)
   909 {
   910     SECStatus rv;
   911     unsigned int modulusLen = rsa_modulusLen(&key->modulus);
   912     unsigned int i;
   913     unsigned char * buffer;
   915     if (inputLen != modulusLen)
   916         goto failure;
   918     buffer = (unsigned char *)PORT_Alloc(modulusLen + 1);
   919     if (!buffer)
   920         goto failure;
   922     rv = RSA_PrivateKeyOp(key, buffer, input);
   923     if (rv != SECSuccess)
   924         goto loser;
   926     /* XXX(rsleevi): Constant time */
   927     if (buffer[0] != RSA_BLOCK_FIRST_OCTET ||
   928         buffer[1] != (unsigned char)RSA_BlockPublic) {
   929         goto loser;
   930     }
   931     *outputLen = 0;
   932     for (i = 2; i < modulusLen; i++) {
   933         if (buffer[i] == RSA_BLOCK_AFTER_PAD_OCTET) {
   934             *outputLen = modulusLen - i - 1;
   935             break;
   936         }
   937     }
   938     if (*outputLen == 0)
   939         goto loser;
   940     if (*outputLen > maxOutputLen)
   941         goto loser;
   943     PORT_Memcpy(output, buffer + modulusLen - *outputLen, *outputLen);
   945     PORT_Free(buffer);
   946     return SECSuccess;
   948 loser:
   949     PORT_Free(buffer);
   950 failure:
   951     return SECFailure;
   952 }
   954 /*
   955  * Encode a RSA-PSS signature.
   956  * Described in RFC 3447, section 9.1.1.
   957  * We use mHash instead of M as input.
   958  * emBits from the RFC is just modBits - 1, see section 8.1.1.
   959  * We only support MGF1 as the MGF.
   960  *
   961  * NOTE: this code assumes modBits is a multiple of 8.
   962  */
   963 static SECStatus
   964 emsa_pss_encode(unsigned char * em,
   965                 unsigned int emLen,
   966                 const unsigned char * mHash,
   967                 HASH_HashType hashAlg,
   968                 HASH_HashType maskHashAlg,
   969                 const unsigned char * salt,
   970                 unsigned int saltLen)
   971 {
   972     const SECHashObject * hash;
   973     void * hash_context;
   974     unsigned char * dbMask;
   975     unsigned int dbMaskLen;
   976     unsigned int i;
   977     SECStatus rv;
   979     hash = HASH_GetRawHashObject(hashAlg);
   980     dbMaskLen = emLen - hash->length - 1;
   982     /* Step 3 */
   983     if (emLen < hash->length + saltLen + 2) {
   984         PORT_SetError(SEC_ERROR_OUTPUT_LEN);
   985         return SECFailure;
   986     }
   988     /* Step 4 */
   989     if (salt == NULL) {
   990         rv = RNG_GenerateGlobalRandomBytes(&em[dbMaskLen - saltLen], saltLen);
   991         if (rv != SECSuccess) {
   992             return rv;
   993         }
   994     } else {
   995         PORT_Memcpy(&em[dbMaskLen - saltLen], salt, saltLen);
   996     }
   998     /* Step 5 + 6 */
   999     /* Compute H and store it at its final location &em[dbMaskLen]. */
  1000     hash_context = (*hash->create)();
  1001     if (hash_context == NULL) {
  1002         PORT_SetError(SEC_ERROR_NO_MEMORY);
  1003         return SECFailure;
  1005     (*hash->begin)(hash_context);
  1006     (*hash->update)(hash_context, eightZeros, 8);
  1007     (*hash->update)(hash_context, mHash, hash->length);
  1008     (*hash->update)(hash_context, &em[dbMaskLen - saltLen], saltLen);
  1009     (*hash->end)(hash_context, &em[dbMaskLen], &i, hash->length);
  1010     (*hash->destroy)(hash_context, PR_TRUE);
  1012     /* Step 7 + 8 */
  1013     PORT_Memset(em, 0, dbMaskLen - saltLen - 1);
  1014     em[dbMaskLen - saltLen - 1] = 0x01;
  1016     /* Step 9 */
  1017     dbMask = (unsigned char *)PORT_Alloc(dbMaskLen);
  1018     if (dbMask == NULL) {
  1019         PORT_SetError(SEC_ERROR_NO_MEMORY);
  1020         return SECFailure;
  1022     MGF1(maskHashAlg, dbMask, dbMaskLen, &em[dbMaskLen], hash->length);
  1024     /* Step 10 */
  1025     for (i = 0; i < dbMaskLen; i++)
  1026         em[i] ^= dbMask[i];
  1027     PORT_Free(dbMask);
  1029     /* Step 11 */
  1030     em[0] &= 0x7f;
  1032     /* Step 12 */
  1033     em[emLen - 1] = 0xbc;
  1035     return SECSuccess;
  1038 /*
  1039  * Verify a RSA-PSS signature.
  1040  * Described in RFC 3447, section 9.1.2.
  1041  * We use mHash instead of M as input.
  1042  * emBits from the RFC is just modBits - 1, see section 8.1.2.
  1043  * We only support MGF1 as the MGF.
  1045  * NOTE: this code assumes modBits is a multiple of 8.
  1046  */
  1047 static SECStatus
  1048 emsa_pss_verify(const unsigned char * mHash,
  1049                 const unsigned char * em,
  1050                 unsigned int emLen,
  1051                 HASH_HashType hashAlg,
  1052                 HASH_HashType maskHashAlg,
  1053                 unsigned int saltLen)
  1055     const SECHashObject * hash;
  1056     void * hash_context;
  1057     unsigned char * db;
  1058     unsigned char * H_;  /* H' from the RFC */
  1059     unsigned int i;
  1060     unsigned int dbMaskLen;
  1061     SECStatus rv;
  1063     hash = HASH_GetRawHashObject(hashAlg);
  1064     dbMaskLen = emLen - hash->length - 1;
  1066     /* Step 3 + 4 + 6 */
  1067     if ((emLen < (hash->length + saltLen + 2)) ||
  1068         (em[emLen - 1] != 0xbc) ||
  1069         ((em[0] & 0x80) != 0)) {
  1070         PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
  1071         return SECFailure;
  1074     /* Step 7 */
  1075     db = (unsigned char *)PORT_Alloc(dbMaskLen);
  1076     if (db == NULL) {
  1077         PORT_SetError(SEC_ERROR_NO_MEMORY);
  1078         return SECFailure;
  1080     /* &em[dbMaskLen] points to H, used as mgfSeed */
  1081     MGF1(maskHashAlg, db, dbMaskLen, &em[dbMaskLen], hash->length);
  1083     /* Step 8 */
  1084     for (i = 0; i < dbMaskLen; i++) {
  1085         db[i] ^= em[i];
  1088     /* Step 9 */
  1089     db[0] &= 0x7f;
  1091     /* Step 10 */
  1092     for (i = 0; i < (dbMaskLen - saltLen - 1); i++) {
  1093         if (db[i] != 0) {
  1094             PORT_Free(db);
  1095             PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
  1096             return SECFailure;
  1099     if (db[dbMaskLen - saltLen - 1] != 0x01) {
  1100         PORT_Free(db);
  1101         PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
  1102         return SECFailure;
  1105     /* Step 12 + 13 */
  1106     H_ = (unsigned char *)PORT_Alloc(hash->length);
  1107     if (H_ == NULL) {
  1108         PORT_Free(db);
  1109         PORT_SetError(SEC_ERROR_NO_MEMORY);
  1110         return SECFailure;
  1112     hash_context = (*hash->create)();
  1113     if (hash_context == NULL) {
  1114         PORT_Free(db);
  1115         PORT_Free(H_);
  1116         PORT_SetError(SEC_ERROR_NO_MEMORY);
  1117         return SECFailure;
  1119     (*hash->begin)(hash_context);
  1120     (*hash->update)(hash_context, eightZeros, 8);
  1121     (*hash->update)(hash_context, mHash, hash->length);
  1122     (*hash->update)(hash_context, &db[dbMaskLen - saltLen], saltLen);
  1123     (*hash->end)(hash_context, H_, &i, hash->length);
  1124     (*hash->destroy)(hash_context, PR_TRUE);
  1126     PORT_Free(db);
  1128     /* Step 14 */
  1129     if (PORT_Memcmp(H_, &em[dbMaskLen], hash->length) != 0) {
  1130         PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
  1131         rv = SECFailure;
  1132     } else {
  1133         rv = SECSuccess;
  1136     PORT_Free(H_);
  1137     return rv;
  1140 SECStatus
  1141 RSA_SignPSS(RSAPrivateKey * key,
  1142             HASH_HashType hashAlg,
  1143             HASH_HashType maskHashAlg,
  1144             const unsigned char * salt,
  1145             unsigned int saltLength,
  1146             unsigned char * output,
  1147             unsigned int * outputLen,
  1148             unsigned int maxOutputLen,
  1149             const unsigned char * input,
  1150             unsigned int inputLen)
  1152     SECStatus rv = SECSuccess;
  1153     unsigned int modulusLen = rsa_modulusLen(&key->modulus);
  1154     unsigned char *pssEncoded = NULL;
  1156     if (maxOutputLen < modulusLen) {
  1157         PORT_SetError(SEC_ERROR_OUTPUT_LEN);
  1158         return SECFailure;
  1161     if ((hashAlg == HASH_AlgNULL) || (maskHashAlg == HASH_AlgNULL)) {
  1162         PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
  1163         return SECFailure;
  1166     pssEncoded = (unsigned char *)PORT_Alloc(modulusLen);
  1167     if (pssEncoded == NULL) {
  1168         PORT_SetError(SEC_ERROR_NO_MEMORY);
  1169         return SECFailure;
  1171     rv = emsa_pss_encode(pssEncoded, modulusLen, input, hashAlg,
  1172                          maskHashAlg, salt, saltLength);
  1173     if (rv != SECSuccess)
  1174         goto done;
  1176     rv = RSA_PrivateKeyOpDoubleChecked(key, output, pssEncoded);
  1177     *outputLen = modulusLen;
  1179 done:
  1180     PORT_Free(pssEncoded);
  1181     return rv;
  1184 SECStatus
  1185 RSA_CheckSignPSS(RSAPublicKey * key,
  1186                  HASH_HashType hashAlg,
  1187                  HASH_HashType maskHashAlg,
  1188                  unsigned int saltLength,
  1189                  const unsigned char * sig,
  1190                  unsigned int sigLen,
  1191                  const unsigned char * hash,
  1192                  unsigned int hashLen)
  1194     SECStatus rv;
  1195     unsigned int modulusLen = rsa_modulusLen(&key->modulus);
  1196     unsigned char * buffer;
  1198     if (sigLen != modulusLen) {
  1199         PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
  1200         return SECFailure;
  1203     if ((hashAlg == HASH_AlgNULL) || (maskHashAlg == HASH_AlgNULL)) {
  1204         PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
  1205         return SECFailure;
  1208     buffer = (unsigned char *)PORT_Alloc(modulusLen);
  1209     if (!buffer) {
  1210         PORT_SetError(SEC_ERROR_NO_MEMORY);
  1211         return SECFailure;
  1214     rv = RSA_PublicKeyOp(key, buffer, sig);
  1215     if (rv != SECSuccess) {
  1216         PORT_Free(buffer);
  1217         PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
  1218         return SECFailure;
  1221     rv = emsa_pss_verify(hash, buffer, modulusLen, hashAlg,
  1222                          maskHashAlg, saltLength);
  1223     PORT_Free(buffer);
  1225     return rv;
  1228 /* XXX Doesn't set error code */
  1229 SECStatus
  1230 RSA_Sign(RSAPrivateKey * key,
  1231          unsigned char * output,
  1232          unsigned int * outputLen,
  1233          unsigned int maxOutputLen,
  1234          const unsigned char * input,
  1235          unsigned int inputLen)
  1237     SECStatus rv = SECSuccess;
  1238     unsigned int modulusLen = rsa_modulusLen(&key->modulus);
  1239     SECItem formatted;
  1240     SECItem unformatted;
  1242     if (maxOutputLen < modulusLen)
  1243         return SECFailure;
  1245     unformatted.len  = inputLen;
  1246     unformatted.data = (unsigned char*)input;
  1247     formatted.data   = NULL;
  1248     rv = rsa_FormatBlock(&formatted, modulusLen, RSA_BlockPrivate,
  1249                          &unformatted);
  1250     if (rv != SECSuccess)
  1251         goto done;
  1253     rv = RSA_PrivateKeyOpDoubleChecked(key, output, formatted.data);
  1254     *outputLen = modulusLen;
  1256     goto done;
  1258 done:
  1259     if (formatted.data != NULL)
  1260         PORT_ZFree(formatted.data, modulusLen);
  1261     return rv;
  1264 /* XXX Doesn't set error code */
  1265 SECStatus
  1266 RSA_CheckSign(RSAPublicKey * key,
  1267               const unsigned char * sig,
  1268               unsigned int sigLen,
  1269               const unsigned char * data,
  1270               unsigned int dataLen)
  1272     SECStatus rv;
  1273     unsigned int modulusLen = rsa_modulusLen(&key->modulus);
  1274     unsigned int i;
  1275     unsigned char * buffer;
  1277     if (sigLen != modulusLen)
  1278         goto failure;
  1279     /*
  1280      * 0x00 || BT || Pad || 0x00 || ActualData
  1282      * The "3" below is the first octet + the second octet + the 0x00
  1283      * octet that always comes just before the ActualData.
  1284      */
  1285     if (dataLen > modulusLen - (3 + RSA_BLOCK_MIN_PAD_LEN))
  1286         goto failure;
  1288     buffer = (unsigned char *)PORT_Alloc(modulusLen + 1);
  1289     if (!buffer)
  1290         goto failure;
  1292     rv = RSA_PublicKeyOp(key, buffer, sig);
  1293     if (rv != SECSuccess)
  1294         goto loser;
  1296     /*
  1297      * check the padding that was used
  1298      */
  1299     if (buffer[0] != RSA_BLOCK_FIRST_OCTET ||
  1300         buffer[1] != (unsigned char)RSA_BlockPrivate) {
  1301         goto loser;
  1303     for (i = 2; i < modulusLen - dataLen - 1; i++) {
  1304         if (buffer[i] != RSA_BLOCK_PRIVATE_PAD_OCTET)
  1305             goto loser;
  1307     if (buffer[i] != RSA_BLOCK_AFTER_PAD_OCTET)
  1308         goto loser;
  1310     /*
  1311      * make sure we get the same results
  1312      */
  1313     if (PORT_Memcmp(buffer + modulusLen - dataLen, data, dataLen) != 0)
  1314         goto loser;
  1316     PORT_Free(buffer);
  1317     return SECSuccess;
  1319 loser:
  1320     PORT_Free(buffer);
  1321 failure:
  1322     return SECFailure;
  1325 /* XXX Doesn't set error code */
  1326 SECStatus
  1327 RSA_CheckSignRecover(RSAPublicKey * key,
  1328                      unsigned char * output,
  1329                      unsigned int * outputLen,
  1330                      unsigned int maxOutputLen,
  1331                      const unsigned char * sig,
  1332                      unsigned int sigLen)
  1334     SECStatus rv;
  1335     unsigned int modulusLen = rsa_modulusLen(&key->modulus);
  1336     unsigned int i;
  1337     unsigned char * buffer;
  1339     if (sigLen != modulusLen)
  1340         goto failure;
  1342     buffer = (unsigned char *)PORT_Alloc(modulusLen + 1);
  1343     if (!buffer)
  1344         goto failure;
  1346     rv = RSA_PublicKeyOp(key, buffer, sig);
  1347     if (rv != SECSuccess)
  1348         goto loser;
  1349     *outputLen = 0;
  1351     /*
  1352      * check the padding that was used
  1353      */
  1354     if (buffer[0] != RSA_BLOCK_FIRST_OCTET ||
  1355         buffer[1] != (unsigned char)RSA_BlockPrivate) {
  1356         goto loser;
  1358     for (i = 2; i < modulusLen; i++) {
  1359         if (buffer[i] == RSA_BLOCK_AFTER_PAD_OCTET) {
  1360             *outputLen = modulusLen - i - 1;
  1361             break;
  1363         if (buffer[i] != RSA_BLOCK_PRIVATE_PAD_OCTET)
  1364             goto loser;
  1366     if (*outputLen == 0)
  1367         goto loser;
  1368     if (*outputLen > maxOutputLen)
  1369         goto loser;
  1371     PORT_Memcpy(output, buffer + modulusLen - *outputLen, *outputLen);
  1373     PORT_Free(buffer);
  1374     return SECSuccess;
  1376 loser:
  1377     PORT_Free(buffer);
  1378 failure:
  1379     return SECFailure;

mercurial