| /* |
| * NSS utility functions |
| * |
| * This Source Code Form is subject to the terms of the Mozilla Public |
| * License, v. 2.0. If a copy of the MPL was not distributed with this |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| |
| #include "net/third_party/nss/ssl/cmpcert.h" |
| |
| #include <secder.h> |
| #include <secitem.h> |
| |
| #include "base/strings/string_piece.h" |
| #include "net/cert/internal/parse_certificate.h" |
| #include "net/cert/x509_certificate.h" |
| #include "net/cert/x509_util.h" |
| #include "net/der/parser.h" |
| #include "starboard/types.h" |
| #include "third_party/boringssl/src/include/openssl/pool.h" |
| |
| namespace net { |
| |
| namespace { |
| |
| bool GetIssuerAndSubject(CERTCertificate* cert, |
| der::Input* issuer, |
| der::Input* subject) { |
| *issuer = der::Input(cert->derIssuer.data, cert->derIssuer.len); |
| *subject = der::Input(cert->derSubject.data, cert->derSubject.len); |
| return true; |
| } |
| |
| bool GetIssuerAndSubject(X509Certificate* cert, |
| der::Input* issuer, |
| der::Input* subject) { |
| der::Input tbs_certificate_tlv; |
| der::Input signature_algorithm_tlv; |
| der::BitString signature_value; |
| if (!ParseCertificate(der::Input(CRYPTO_BUFFER_data(cert->cert_buffer()), |
| CRYPTO_BUFFER_len(cert->cert_buffer())), |
| &tbs_certificate_tlv, &signature_algorithm_tlv, |
| &signature_value, nullptr)) { |
| return false; |
| } |
| ParsedTbsCertificate tbs; |
| if (!ParseTbsCertificate(tbs_certificate_tlv, |
| x509_util::DefaultParseCertificateOptions(), &tbs, |
| nullptr)) { |
| return false; |
| } |
| |
| *issuer = tbs.issuer_tlv; |
| *subject = tbs.subject_tlv; |
| return true; |
| } |
| |
| } // namespace |
| |
| bool MatchClientCertificateIssuers( |
| X509Certificate* cert, |
| const std::vector<std::string>& cert_authorities, |
| ScopedCERTCertificateList* intermediates) { |
| // Bound how many iterations to try. |
| static const int kMaxDepth = 20; |
| |
| intermediates->clear(); |
| |
| // If no authorities are supplied, everything matches. |
| if (cert_authorities.empty()) |
| return true; |
| |
| // DER encoded issuer and subject name of current certificate. |
| der::Input issuer; |
| der::Input subject; |
| |
| if (!GetIssuerAndSubject(cert, &issuer, &subject)) |
| return false; |
| |
| while (intermediates->size() < kMaxDepth) { |
| // Check if current cert is issued by a valid CA. |
| for (const std::string& ca : cert_authorities) { |
| if (issuer == der::Input(&ca)) |
| return true; |
| } |
| |
| // Stop at self-issued certificates. |
| if (issuer == subject) |
| return false; |
| |
| // Look the parent up in the database and keep searching. |
| SECItem issuer_item; |
| issuer_item.len = issuer.Length(); |
| issuer_item.data = const_cast<unsigned char*>(issuer.UnsafeData()); |
| ScopedCERTCertificate nextcert( |
| CERT_FindCertByName(CERT_GetDefaultCertDB(), &issuer_item)); |
| if (!nextcert) |
| return false; |
| |
| if (!GetIssuerAndSubject(nextcert.get(), &issuer, &subject)) |
| return false; |
| |
| intermediates->push_back(std::move(nextcert)); |
| } |
| |
| return false; |
| } |
| |
| } // namespace net |