security/nss/lib/util/pkcs1sig.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/.
     4  */
     6 #include "pkcs1sig.h"
     7 #include "hasht.h"
     8 #include "secerr.h"
     9 #include "secasn1t.h"
    10 #include "secoid.h"
    12 typedef struct pkcs1PrefixStr pkcs1Prefix;
    13 struct pkcs1PrefixStr {
    14     unsigned int len;
    15     PRUint8 *data;
    16 };
    18 typedef struct pkcs1PrefixesStr pkcs1Prefixes;
    19 struct pkcs1PrefixesStr {
    20     unsigned int digestLen;
    21     pkcs1Prefix prefixWithParams;
    22     pkcs1Prefix prefixWithoutParams;
    23 };
    25 /* The value for SGN_PKCS1_DIGESTINFO_MAX_PREFIX_LEN_EXCLUDING_OID is based on
    26  * the possible prefix encodings as explained below.
    27  */
    28 #define MAX_PREFIX_LEN_EXCLUDING_OID 10
    30 static SECStatus
    31 encodePrefix(const SECOidData *hashOid, unsigned int digestLen,
    32              pkcs1Prefix *prefix, PRBool withParams)
    33 {
    34     /* with params coding is:
    35      *  Sequence (2 bytes) {
    36      *      Sequence (2 bytes) {
    37      *               Oid (2 bytes)  {
    38      *                   Oid value (derOid->oid.len)
    39      *               }
    40      *               NULL (2 bytes)
    41      *      }
    42      *      OCTECT (2 bytes);
    43      *
    44      * without params coding is:
    45      *  Sequence (2 bytes) {
    46      *      Sequence (2 bytes) {
    47      *               Oid (2 bytes)  {
    48      *                   Oid value (derOid->oid.len)
    49      *               }
    50      *      }
    51      *      OCTECT (2 bytes);
    52      */
    54     unsigned int innerSeqLen = 2 + hashOid->oid.len;
    55     unsigned int outerSeqLen = 2 + innerSeqLen + 2 + digestLen;
    56     unsigned int extra = 0;
    58     if (withParams) {
    59         innerSeqLen += 2;
    60         outerSeqLen += 2;
    61         extra = 2;
    62     }
    64     if (innerSeqLen >= 128 ||
    65         outerSeqLen >= 128 ||
    66         (outerSeqLen + 2 - digestLen) >
    67             (MAX_PREFIX_LEN_EXCLUDING_OID + hashOid->oid.len)) {
    68         /* this is actually a library failure, It shouldn't happen */
    69         PORT_SetError(SEC_ERROR_INVALID_ARGS);
    70         return SECFailure;
    71     }
    73     prefix->len = 6 + hashOid->oid.len + extra + 2;
    74     prefix->data = PORT_Alloc(prefix->len);
    75     if (!prefix->data) {
    76         PORT_SetError(SEC_ERROR_NO_MEMORY);
    77         return SECFailure;
    78     }
    80     prefix->data[0] = SEC_ASN1_SEQUENCE|SEC_ASN1_CONSTRUCTED;
    81     prefix->data[1] = outerSeqLen;
    82     prefix->data[2] = SEC_ASN1_SEQUENCE|SEC_ASN1_CONSTRUCTED;
    83     prefix->data[3] = innerSeqLen;
    84     prefix->data[4] = SEC_ASN1_OBJECT_ID;
    85     prefix->data[5] = hashOid->oid.len;
    86     PORT_Memcpy(&prefix->data[6], hashOid->oid.data, hashOid->oid.len);
    87     if (withParams) {
    88         prefix->data[6 + hashOid->oid.len] = SEC_ASN1_NULL;
    89         prefix->data[6 + hashOid->oid.len + 1] = 0;
    90     }
    91     prefix->data[6 + hashOid->oid.len + extra] = SEC_ASN1_OCTET_STRING;
    92     prefix->data[6 + hashOid->oid.len + extra + 1] = digestLen;
    94     return SECSuccess;
    95 }
    97 SECStatus
    98 _SGN_VerifyPKCS1DigestInfo(SECOidTag digestAlg,
    99                            const SECItem* digest,
   100                            const SECItem* dataRecoveredFromSignature,
   101                            PRBool unsafeAllowMissingParameters)
   102 {
   103     SECOidData *hashOid;
   104     pkcs1Prefixes pp;
   105     const pkcs1Prefix* expectedPrefix;
   106     SECStatus rv, rv2, rv3;
   108     if (!digest || !digest->data ||
   109         !dataRecoveredFromSignature || !dataRecoveredFromSignature->data) {
   110         PORT_SetError(SEC_ERROR_INVALID_ARGS);
   111         return SECFailure;
   112     }
   114     hashOid = SECOID_FindOIDByTag(digestAlg);
   115     if (hashOid == NULL) {
   116         PORT_SetError(SEC_ERROR_INVALID_ARGS);
   117         return SECFailure;
   118     }
   120     pp.digestLen = digest->len;
   121     pp.prefixWithParams.data = NULL;
   122     pp.prefixWithoutParams.data = NULL;
   124     rv2 = encodePrefix(hashOid, pp.digestLen, &pp.prefixWithParams, PR_TRUE);
   125     rv3 = encodePrefix(hashOid, pp.digestLen, &pp.prefixWithoutParams, PR_FALSE);
   127     rv = SECSuccess;
   128     if (rv2 != SECSuccess || rv3 != SECSuccess) {
   129         rv = SECFailure;
   130     }
   132     if (rv == SECSuccess) {
   133         /* We don't attempt to avoid timing attacks on these comparisons because
   134          * signature verification is a public key operation, not a private key
   135          * operation.
   136          */
   138         if (dataRecoveredFromSignature->len ==
   139                 pp.prefixWithParams.len + pp.digestLen) {
   140             expectedPrefix = &pp.prefixWithParams;
   141         } else if (unsafeAllowMissingParameters &&
   142                    dataRecoveredFromSignature->len ==
   143                       pp.prefixWithoutParams.len + pp.digestLen) {
   144             expectedPrefix = &pp.prefixWithoutParams;
   145         } else {
   146             PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
   147             rv = SECFailure;
   148         }
   149     }
   151     if (rv == SECSuccess) {
   152         if (memcmp(dataRecoveredFromSignature->data, expectedPrefix->data,
   153                    expectedPrefix->len) ||
   154             memcmp(dataRecoveredFromSignature->data + expectedPrefix->len,
   155                    digest->data, digest->len)) {
   156             PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
   157             rv = SECFailure;
   158         }
   159     }
   161     if (pp.prefixWithParams.data) {
   162         PORT_Free(pp.prefixWithParams.data);
   163     }
   164     if (pp.prefixWithoutParams.data) {
   165         PORT_Free(pp.prefixWithoutParams.data);
   166     }
   168     return rv;
   169 }

mercurial