LCOV - code coverage report
Current view: top level - security/pkix/lib - pkixnss.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 15 56 26.8 %
Date: 2017-07-14 16:53:18 Functions: 2 7 28.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*- *- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This code is made available to you under your choice of the following sets
       4             :  * of licensing terms:
       5             :  */
       6             : /* This Source Code Form is subject to the terms of the Mozilla Public
       7             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       8             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       9             :  */
      10             : /* Copyright 2013 Mozilla Contributors
      11             :  *
      12             :  * Licensed under the Apache License, Version 2.0 (the "License");
      13             :  * you may not use this file except in compliance with the License.
      14             :  * You may obtain a copy of the License at
      15             :  *
      16             :  *     http://www.apache.org/licenses/LICENSE-2.0
      17             :  *
      18             :  * Unless required by applicable law or agreed to in writing, software
      19             :  * distributed under the License is distributed on an "AS IS" BASIS,
      20             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      21             :  * See the License for the specific language governing permissions and
      22             :  * limitations under the License.
      23             :  */
      24             : 
      25             : #include "pkix/pkixnss.h"
      26             : 
      27             : #include <limits>
      28             : 
      29             : #include "cryptohi.h"
      30             : #include "keyhi.h"
      31             : #include "pk11pub.h"
      32             : #include "pkix/pkix.h"
      33             : #include "pkixutil.h"
      34             : #include "ScopedPtr.h"
      35             : #include "secerr.h"
      36             : #include "sslerr.h"
      37             : 
      38             : namespace mozilla { namespace pkix {
      39             : 
      40             : namespace {
      41             : 
      42             : Result
      43           0 : VerifySignedDigest(const SignedDigest& sd,
      44             :                    Input subjectPublicKeyInfo,
      45             :                    SECOidTag pubKeyAlg,
      46             :                    void* pkcs11PinArg)
      47             : {
      48             :   SECOidTag digestAlg;
      49           0 :   switch (sd.digestAlgorithm) {
      50           0 :     case DigestAlgorithm::sha512: digestAlg = SEC_OID_SHA512; break;
      51           0 :     case DigestAlgorithm::sha384: digestAlg = SEC_OID_SHA384; break;
      52           0 :     case DigestAlgorithm::sha256: digestAlg = SEC_OID_SHA256; break;
      53           0 :     case DigestAlgorithm::sha1: digestAlg = SEC_OID_SHA1; break;
      54           0 :     MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM
      55             :   }
      56             : 
      57             :   SECItem subjectPublicKeyInfoSECItem =
      58           0 :     UnsafeMapInputToSECItem(subjectPublicKeyInfo);
      59             :   ScopedPtr<CERTSubjectPublicKeyInfo, SECKEY_DestroySubjectPublicKeyInfo>
      60           0 :     spki(SECKEY_DecodeDERSubjectPublicKeyInfo(&subjectPublicKeyInfoSECItem));
      61           0 :   if (!spki) {
      62           0 :     return MapPRErrorCodeToResult(PR_GetError());
      63             :   }
      64             :   ScopedPtr<SECKEYPublicKey, SECKEY_DestroyPublicKey>
      65           0 :     pubKey(SECKEY_ExtractPublicKey(spki.get()));
      66           0 :   if (!pubKey) {
      67           0 :     return MapPRErrorCodeToResult(PR_GetError());
      68             :   }
      69             : 
      70           0 :   SECItem digestSECItem(UnsafeMapInputToSECItem(sd.digest));
      71           0 :   SECItem signatureSECItem(UnsafeMapInputToSECItem(sd.signature));
      72           0 :   SECStatus srv = VFY_VerifyDigestDirect(&digestSECItem, pubKey.get(),
      73             :                                          &signatureSECItem, pubKeyAlg,
      74           0 :                                          digestAlg, pkcs11PinArg);
      75           0 :   if (srv != SECSuccess) {
      76           0 :     return MapPRErrorCodeToResult(PR_GetError());
      77             :   }
      78             : 
      79           0 :   return Success;
      80             : }
      81             : 
      82             : } // namespace
      83             : 
      84             : Result
      85           0 : VerifyRSAPKCS1SignedDigestNSS(const SignedDigest& sd,
      86             :                               Input subjectPublicKeyInfo,
      87             :                               void* pkcs11PinArg)
      88             : {
      89             :   return VerifySignedDigest(sd, subjectPublicKeyInfo,
      90           0 :                             SEC_OID_PKCS1_RSA_ENCRYPTION, pkcs11PinArg);
      91             : }
      92             : 
      93             : Result
      94           0 : VerifyECDSASignedDigestNSS(const SignedDigest& sd,
      95             :                            Input subjectPublicKeyInfo,
      96             :                            void* pkcs11PinArg)
      97             : {
      98             :   return VerifySignedDigest(sd, subjectPublicKeyInfo,
      99           0 :                             SEC_OID_ANSIX962_EC_PUBLIC_KEY, pkcs11PinArg);
     100             : }
     101             : 
     102             : Result
     103          15 : DigestBufNSS(Input item,
     104             :              DigestAlgorithm digestAlg,
     105             :              /*out*/ uint8_t* digestBuf,
     106             :              size_t digestBufLen)
     107             : {
     108             :   SECOidTag oid;
     109             :   size_t bits;
     110          15 :   switch (digestAlg) {
     111           0 :     case DigestAlgorithm::sha512: oid = SEC_OID_SHA512; bits = 512; break;
     112           0 :     case DigestAlgorithm::sha384: oid = SEC_OID_SHA384; bits = 384; break;
     113          15 :     case DigestAlgorithm::sha256: oid = SEC_OID_SHA256; bits = 256; break;
     114           0 :     case DigestAlgorithm::sha1: oid = SEC_OID_SHA1; bits = 160; break;
     115           0 :     MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM
     116             :   }
     117          15 :   if (digestBufLen != bits / 8) {
     118           0 :     return Result::FATAL_ERROR_INVALID_ARGS;
     119             :   }
     120             : 
     121          15 :   SECItem itemSECItem = UnsafeMapInputToSECItem(item);
     122          30 :   if (itemSECItem.len >
     123          15 :         static_cast<decltype(itemSECItem.len)>(
     124          15 :           std::numeric_limits<int32_t>::max())) {
     125           0 :     PR_NOT_REACHED("large items should not be possible here");
     126           0 :     return Result::FATAL_ERROR_INVALID_ARGS;
     127             :   }
     128          15 :   SECStatus srv = PK11_HashBuf(oid, digestBuf, itemSECItem.data,
     129          30 :                                static_cast<int32_t>(itemSECItem.len));
     130          15 :   if (srv != SECSuccess) {
     131           0 :     return MapPRErrorCodeToResult(PR_GetError());
     132             :   }
     133          15 :   return Success;
     134             : }
     135             : 
     136             : Result
     137           0 : MapPRErrorCodeToResult(PRErrorCode error)
     138             : {
     139           0 :   switch (error)
     140             :   {
     141             : #define MOZILLA_PKIX_MAP(mozilla_pkix_result, value, nss_result) \
     142             :     case nss_result: return Result::mozilla_pkix_result;
     143             : 
     144           0 :     MOZILLA_PKIX_MAP_LIST
     145             : 
     146             : #undef MOZILLA_PKIX_MAP
     147             : 
     148             :     default:
     149           0 :       return Result::ERROR_UNKNOWN_ERROR;
     150             :   }
     151             : }
     152             : 
     153             : PRErrorCode
     154           0 : MapResultToPRErrorCode(Result result)
     155             : {
     156           0 :   switch (result)
     157             :   {
     158             : #define MOZILLA_PKIX_MAP(mozilla_pkix_result, value, nss_result) \
     159             :     case Result::mozilla_pkix_result: return nss_result;
     160             : 
     161           0 :     MOZILLA_PKIX_MAP_LIST
     162             : 
     163             : #undef MOZILLA_PKIX_MAP
     164             : 
     165           0 :     MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM
     166             :   }
     167             : }
     168             : 
     169             : void
     170           1 : RegisterErrorTable()
     171             : {
     172             :   // Note that these error strings are not localizable.
     173             :   // When these strings change, update the localization information too.
     174             :   static const PRErrorMessage ErrorTableText[] = {
     175             :     { "MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE",
     176             :       "The server uses key pinning (HPKP) but no trusted certificate chain "
     177             :       "could be constructed that matches the pinset. Key pinning violations "
     178             :       "cannot be overridden." },
     179             :     { "MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY",
     180             :       "The server uses a certificate with a basic constraints extension "
     181             :       "identifying it as a certificate authority. For a properly-issued "
     182             :       "certificate, this should not be the case." },
     183             :     { "MOZILLA_PKIX_ERROR_INADEQUATE_KEY_SIZE",
     184             :       "The server presented a certificate with a key size that is too small "
     185             :       "to establish a secure connection." },
     186             :     { "MOZILLA_PKIX_ERROR_V1_CERT_USED_AS_CA",
     187             :       "An X.509 version 1 certificate that is not a trust anchor was used to "
     188             :       "issue the server's certificate. X.509 version 1 certificates are "
     189             :       "deprecated and should not be used to sign other certificates." },
     190             :     { "MOZILLA_PKIX_ERROR_NO_RFC822NAME_MATCH",
     191             :       "The certificate is not valid for the given email address." },
     192             :     { "MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE",
     193             :       "The server presented a certificate that is not yet valid." },
     194             :     { "MOZILLA_PKIX_ERROR_NOT_YET_VALID_ISSUER_CERTIFICATE",
     195             :       "A certificate that is not yet valid was used to issue the server's "
     196             :       "certificate." },
     197             :     { "MOZILLA_PKIX_ERROR_SIGNATURE_ALGORITHM_MISMATCH",
     198             :       "The signature algorithm in the signature field of the certificate does "
     199             :       "not match the algorithm in its signatureAlgorithm field." },
     200             :     { "MOZILLA_PKIX_ERROR_OCSP_RESPONSE_FOR_CERT_MISSING",
     201             :       "The OCSP response does not include a status for the certificate being "
     202             :       "verified." },
     203             :     { "MOZILLA_PKIX_ERROR_VALIDITY_TOO_LONG",
     204             :       "The server presented a certificate that is valid for too long." },
     205             :     { "MOZILLA_PKIX_ERROR_REQUIRED_TLS_FEATURE_MISSING",
     206             :       "A required TLS feature is missing." },
     207             :     { "MOZILLA_PKIX_ERROR_INVALID_INTEGER_ENCODING",
     208             :       "The server presented a certificate that contains an invalid encoding of "
     209             :       "an integer. Common causes include negative serial numbers, negative RSA "
     210             :       "moduli, and encodings that are longer than necessary." },
     211             :     { "MOZILLA_PKIX_ERROR_EMPTY_ISSUER_NAME",
     212             :       "The server presented a certificate with an empty issuer distinguished "
     213             :       "name." },
     214             :   };
     215             :   // Note that these error strings are not localizable.
     216             :   // When these strings change, update the localization information too.
     217             : 
     218             :   static const PRErrorTable ErrorTable = {
     219             :     ErrorTableText,
     220             :     "pkixerrors",
     221             :     ERROR_BASE,
     222             :     PR_ARRAY_SIZE(ErrorTableText)
     223             :   };
     224             : 
     225           1 :   (void) PR_ErrorInstallTable(&ErrorTable);
     226           1 : }
     227             : 
     228             : } } // namespace mozilla::pkix

Generated by: LCOV version 1.13