1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/pkix/lib/pkixkey.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,89 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ 1.6 +/* Copyright 2013 Mozilla Foundation 1.7 + * 1.8 + * Licensed under the Apache License, Version 2.0 (the "License"); 1.9 + * you may not use this file except in compliance with the License. 1.10 + * You may obtain a copy of the License at 1.11 + * 1.12 + * http://www.apache.org/licenses/LICENSE-2.0 1.13 + * 1.14 + * Unless required by applicable law or agreed to in writing, software 1.15 + * distributed under the License is distributed on an "AS IS" BASIS, 1.16 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.17 + * See the License for the specific language governing permissions and 1.18 + * limitations under the License. 1.19 + */ 1.20 + 1.21 +#include "pkix/pkix.h" 1.22 + 1.23 +#include <limits> 1.24 +#include <stdint.h> 1.25 + 1.26 +#include "cert.h" 1.27 +#include "cryptohi.h" 1.28 +#include "prerror.h" 1.29 +#include "secerr.h" 1.30 + 1.31 +namespace mozilla { namespace pkix { 1.32 + 1.33 +SECStatus 1.34 +VerifySignedData(const CERTSignedData* sd, const CERTCertificate* cert, 1.35 + void* pkcs11PinArg) 1.36 +{ 1.37 + if (!sd || !sd->data.data || !sd->signatureAlgorithm.algorithm.data || 1.38 + !sd->signature.data || !cert) { 1.39 + PR_NOT_REACHED("invalid args to VerifySignedData"); 1.40 + PR_SetError(SEC_ERROR_INVALID_ARGS, 0); 1.41 + return SECFailure; 1.42 + } 1.43 + 1.44 + // See bug 921585. 1.45 + if (sd->data.len > static_cast<unsigned int>(std::numeric_limits<int>::max())) { 1.46 + PR_SetError(SEC_ERROR_INVALID_ARGS, 0); 1.47 + return SECFailure; 1.48 + } 1.49 + 1.50 + // convert sig->len from bit counts to byte count. 1.51 + SECItem sig = sd->signature; 1.52 + DER_ConvertBitString(&sig); 1.53 + 1.54 + // Use SECKEY_ExtractPublicKey instead of CERT_ExtractPublicKey because 1.55 + // CERT_ExtractPublicKey would try to do (EC)DSA parameter inheritance, using 1.56 + // the classic (wrong) NSS path building logic. We intentionally do not 1.57 + // support parameter inheritance. 1.58 + ScopedSECKEYPublicKey 1.59 + pubKey(SECKEY_ExtractPublicKey(&cert->subjectPublicKeyInfo)); 1.60 + if (!pubKey) { 1.61 + return SECFailure; 1.62 + } 1.63 + 1.64 + SECOidTag hashAlg; 1.65 + if (VFY_VerifyDataWithAlgorithmID(sd->data.data, static_cast<int>(sd->data.len), 1.66 + pubKey.get(), &sig, &sd->signatureAlgorithm, 1.67 + &hashAlg, pkcs11PinArg) != SECSuccess) { 1.68 + return SECFailure; 1.69 + } 1.70 + 1.71 + // TODO: Ideally, we would do this check before we call 1.72 + // VFY_VerifyDataWithAlgorithmID. But, VFY_VerifyDataWithAlgorithmID gives us 1.73 + // the hash algorithm so it is more convenient to do things in this order. 1.74 + uint32_t policy; 1.75 + if (NSS_GetAlgorithmPolicy(hashAlg, &policy) != SECSuccess) { 1.76 + return SECFailure; 1.77 + } 1.78 + 1.79 + // XXX: I'm not sure why there isn't NSS_USE_ALG_IN_SSL_SIGNATURE, but there 1.80 + // isn't. Since we don't know the context in which we're being called, be as 1.81 + // strict as we can be given the NSS API that is available. 1.82 + static const uint32_t requiredPolicy = NSS_USE_ALG_IN_CERT_SIGNATURE | 1.83 + NSS_USE_ALG_IN_CMS_SIGNATURE; 1.84 + if ((policy & requiredPolicy) != requiredPolicy) { 1.85 + PR_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED, 0); 1.86 + return SECFailure; 1.87 + } 1.88 + 1.89 + return SECSuccess; 1.90 +} 1.91 + 1.92 +} } // namespace mozilla::pkix