Beispiel #1
0
        /// <summary>
        /// Verify signatures of certificates in the certificate chain. On return, the
        /// certificate chain contains a list of certificates successfully verified by
        /// trustedCertificate.
        /// When the certificate chain cannot be verified, this method will call
        /// fail() with the INVALID_SIGNATURE error code and the appropriate message.
        /// This is only called by the Validator class.
        /// </summary>
        ///
        /// <returns>The certificate to validate the original data packet, either the
        /// last entry in the certificate chain or trustedCertificate if the
        /// certificate chain is empty. However, return null if the signature of at
        /// least one certificate in the chain is invalid, in which case all unverified
        /// certificates have been removed from the certificate chain.</returns>
        public CertificateV2 verifyCertificateChain_(
            CertificateV2 trustedCertificate)
        {
            CertificateV2 validatedCertificate = trustedCertificate;

            for (int i = 0; i < certificateChain_.Count; ++i)
            {
                CertificateV2 certificateToValidate = certificateChain_[i];

                if (!net.named_data.jndn.security.VerificationHelpers.verifyDataSignature(certificateToValidate,
                                                                                          validatedCertificate))
                {
                    fail(new ValidationError(net.named_data.jndn.security.v2.ValidationError.INVALID_SIGNATURE,
                                             "Invalid signature of certificate `"
                                             + certificateToValidate.getName().toUri() + "`"));
                    // Remove this and remaining certificates in the chain.
                    while (certificateChain_.Count > i)
                    {
                        ILOG.J2CsMapping.Collections.Collections.RemoveAt(certificateChain_, i);
                    }

                    return(null);
                }
                else
                {
                    logger_.log(ILOG.J2CsMapping.Util.Logging.Level.FINE, "OK signature for certificate `{0}`",
                                certificateToValidate.getName().toUri());
                    validatedCertificate = certificateToValidate;
                }
            }

            return(validatedCertificate);
        }
Beispiel #2
0
        /// <summary>
        /// Insert the certificate into the cache. The inserted certificate will be
        /// removed no later than its NotAfter time, or maxLifetimeMilliseconds given
        /// to the constructor.
        /// </summary>
        ///
        /// <param name="certificate">The certificate object, which is copied.</param>
        public void insert(CertificateV2 certificate)
        {
            double notAfterTime = certificate.getValidityPeriod().getNotAfter();
            // nowOffsetMilliseconds_ is only used for testing.
            double now = net.named_data.jndn.util.Common.getNowMilliseconds() + nowOffsetMilliseconds_;

            if (notAfterTime < now)
            {
                logger_.log(
                    ILOG.J2CsMapping.Util.Logging.Level.FINE,
                    "Not adding {0}: already expired at {1}",
                    new Object[] { certificate.getName().toUri(),
                                   net.named_data.jndn.encrypt.Schedule.toIsoString(notAfterTime) });
                return;
            }

            double removalTime = Math.Min(notAfterTime, now
                                          + maxLifetimeMilliseconds_);

            if (removalTime < nextRefreshTime_)
            {
                // We need to run refresh() sooner.)
                nextRefreshTime_ = removalTime;
            }

            double removalHours = (removalTime - now) / (3600 * 1000.0d);

            logger_.log(ILOG.J2CsMapping.Util.Logging.Level.FINE, "Adding {0}, will remove in {1} hours",
                        new Object[] { certificate.getName().toUri(), removalHours });
            CertificateV2 certificateCopy = new CertificateV2(certificate);

            ILOG.J2CsMapping.Collections.Collections.Put(certificatesByName_, certificateCopy.getName(), new CertificateCacheV2.Entry(
                                                             certificateCopy, removalTime));
        }
        /// <summary>
        /// Load the static anchor certificate. If a certificate with the name is
        /// already added, do nothing.
        /// </summary>
        ///
        /// <param name="certificate">The certificate to add, which is copied.</param>
        public void add(CertificateV2 certificate)
        {
            if (ILOG.J2CsMapping.Collections.Collections.Contains(certificate.getName(), anchorNames_))
            {
                return;
            }

            // Copy the certificate name.
            ILOG.J2CsMapping.Collections.Collections.Add(anchorNames_, new Name(certificate.getName()));
            // This copies the certificate.
            certificates_.add(certificate);
        }
Beispiel #4
0
        /// <summary>
        /// Find the certificate by the given key name.
        /// </summary>
        ///
        /// <param name="certificatePrefix"></param>
        /// <returns>The found certificate, or null if not found. You must not modify
        /// the returned object. If you need to modify it, then make a copy.</returns>
        public CertificateV2 find(Name certificatePrefix)
        {
            if (certificatePrefix.size() > 0 &&
                certificatePrefix.get(-1).isImplicitSha256Digest())
            {
                logger_.log(ILOG.J2CsMapping.Util.Logging.Level.FINE,
                            "Certificate search using a name with an implicit digest is not yet supported");
            }

            refresh();

            Name entryKey = (Name)certificatesByName_
                            .ceilingKey(certificatePrefix);

            if (entryKey == null)
            {
                return(null);
            }

            CertificateV2 certificate = ((CertificateCacheV2.Entry)certificatesByName_[entryKey]).certificate_;

            if (!certificatePrefix.isPrefixOf(certificate.getName()))
            {
                return(null);
            }
            return(certificate);
        }
        /// <summary>
        /// Asynchronously fetch a certificate. setCertificateStorage must have been
        /// called first.
        /// If the requested certificate exists in the storage, then this method will
        /// immediately call continueValidation with the certificate. If certificate is
        /// not available, then the implementation-specific doFetch will be called to
        /// asynchronously fetch the certificate. The successfully-retrieved
        /// certificate will be automatically added to the unverified cache of the
        /// certificate storage.
        /// When the requested certificate is retrieved, continueValidation is called.
        /// Otherwise, the fetcher implementation calls state.failed() with the
        /// appropriate error code and diagnostic message.
        /// </summary>
        ///
        /// <param name="certificateRequest"></param>
        /// <param name="state">The validation state.</param>
        /// <param name="continueValidation">is the fetched certificate and state is the ValidationState.</param>
        public void fetch(CertificateRequest certificateRequest,
                          ValidationState state, CertificateFetcher.ValidationContinuation continueValidation)
        {
            if (certificateStorage_ == null)
            {
                throw new Exception(
                          "CertificateFetcher.fetch: You must first call setCertificateStorage");
            }

            CertificateV2 certificate = certificateStorage_
                                        .getUnverifiedCertificateCache().find(
                certificateRequest.interest_);

            if (certificate != null)
            {
                logger_.log(ILOG.J2CsMapping.Util.Logging.Level.FINE,
                            "Found certificate in **un**verified key cache {0}",
                            certificate.getName().toUri());
                continueValidation.continueValidation(certificate, state);
                return;
            }

            // Rename continueValidation to avoid a loop.
            CertificateFetcher.ValidationContinuation outerContinueValidation_0 = continueValidation;
            // Fetch asynchronously.
            doFetch(certificateRequest, state, new CertificateFetcher.Anonymous_C0(this, outerContinueValidation_0));
        }
Beispiel #6
0
        /// <summary>
        /// Find a certificate for the given interest.
        /// </summary>
        ///
        /// <param name="interest">The input interest packet.</param>
        /// <returns>The found certificate, or null if not found.</returns>
        /// @note Interest with implicit digest is not supported.
        /// @note ChildSelector is not supported.
        public CertificateV2 find(Interest interest)
        {
            refresh();

            Name firstKey = (Name)anchors_.anchorsByName_.ceilingKey(interest
                                                                     .getName());

            if (firstKey == null)
            {
                return(null);
            }

            /* foreach */
            foreach (Object key  in  anchors_.anchorsByName_.navigableKeySet().tailSet(
                         firstKey))
            {
                CertificateV2 certificate = (CertificateV2)anchors_.anchorsByName_[(Name)key];
                if (!interest.getName().isPrefixOf(certificate.getName()))
                {
                    break;
                }

                try {
                    if (interest.matchesData(certificate))
                    {
                        return(certificate);
                    }
                } catch (EncodingException ex) {
                    // We don't expect this to happen.
                    throw new Exception("Error in matchesData: " + ex);
                }
            }

            return(null);
        }
Beispiel #7
0
        private void loadCertificate(String file, HashedSet <Name> oldAnchorNames)
        {
            CertificateV2 certificate = net.named_data.jndn.security.v2.TrustAnchorGroup.readCertificate(file);

            if (certificate != null)
            {
                if (!ILOG.J2CsMapping.Collections.Collections.Contains(certificate.getName(), anchorNames_))
                {
                    ILOG.J2CsMapping.Collections.Collections.Add(anchorNames_, certificate.getName());
                    certificates_.add(certificate);
                }
                else
                {
                    ILOG.J2CsMapping.Collections.Collections.Remove(oldAnchorNames, certificate.getName());
                }
            }
        }
Beispiel #8
0
            /// <summary>
            /// Add the certificate to the container.
            /// </summary>
            ///
            /// <param name="certificate">The certificate to add, which is copied.</param>
            public override void add(CertificateV2 certificate)
            {
                CertificateV2 certificateCopy;

                try {
                    certificateCopy = new CertificateV2(certificate);
                } catch (CertificateV2.Error ex) {
                    // We don't expect this from the copy constructor.
                    throw new Exception(
                              "Error in CertificateV2 copy constructor: " + ex);
                }
                ILOG.J2CsMapping.Collections.Collections.Put(anchorsByName_, certificateCopy.getName(), certificateCopy);
            }
Beispiel #9
0
        /// <summary>
        /// Find the certificate by the given interest.
        /// </summary>
        ///
        /// <param name="interest">The input interest object.</param>
        /// <returns>The found certificate which matches the interest, or null if not
        /// found. You must not modify the returned object. If you need to modify it,
        /// then make a copy.</returns>
        /// @note ChildSelector is not supported.
        public CertificateV2 find(Interest interest)
        {
            if (interest.getChildSelector() >= 0)
            {
                logger_.log(
                    ILOG.J2CsMapping.Util.Logging.Level.FINE,
                    "Certificate search using a ChildSelector is not supported. Searching as if this selector not specified");
            }

            if (interest.getName().size() > 0 &&
                interest.getName().get(-1).isImplicitSha256Digest())
            {
                logger_.log(ILOG.J2CsMapping.Util.Logging.Level.FINE,
                            "Certificate search using a name with an implicit digest is not yet supported");
            }

            refresh();

            Name firstKey = (Name)certificatesByName_.ceilingKey(interest
                                                                 .getName());

            if (firstKey == null)
            {
                return(null);
            }

            /* foreach */
            foreach (Object key  in  certificatesByName_.navigableKeySet().tailSet(
                         firstKey))
            {
                CertificateV2 certificate = ((CertificateCacheV2.Entry)certificatesByName_[(Name)key]).certificate_;
                if (!interest.getName().isPrefixOf(certificate.getName()))
                {
                    break;
                }

                try {
                    if (interest.matchesData(certificate))
                    {
                        return(certificate);
                    }
                } catch (EncodingException ex) {
                    // We don't expect this. Promote to Error.
                    throw new Exception("Error in Interest.matchesData: " + ex);
                }
            }

            return(null);
        }
Beispiel #10
0
        /// <summary>
        /// Request a certificate for further validation.
        /// </summary>
        ///
        /// <param name="certificateRequest">The certificate request.</param>
        /// <param name="state">The current validation state.</param>
        internal void requestCertificate(CertificateRequest certificateRequest,
                                         ValidationState state)
        {
            if (state.getDepth() >= maxDepth_)
            {
                state.fail(new ValidationError(
                               net.named_data.jndn.security.v2.ValidationError.EXCEEDED_DEPTH_LIMIT,
                               "Exceeded validation depth limit"));
                return;
            }

            if (state
                .hasSeenCertificateName(certificateRequest.interest_.getName()))
            {
                state.fail(new ValidationError(net.named_data.jndn.security.v2.ValidationError.LOOP_DETECTED,
                                               "Validation loop detected for certificate `"
                                               + certificateRequest.interest_.getName().toUri()
                                               + "`"));
                return;
            }

            logger_.log(ILOG.J2CsMapping.Util.Logging.Level.FINE, "Retrieving {0}", certificateRequest.interest_
                        .getName().toUri());

            CertificateV2 certificate_0 = findTrustedCertificate(certificateRequest.interest_);

            if (certificate_0 != null)
            {
                logger_.log(ILOG.J2CsMapping.Util.Logging.Level.FINE, "Found trusted certificate {0}",
                            certificate_0.getName().toUri());

                certificate_0 = state.verifyCertificateChain_(certificate_0);
                if (certificate_0 != null)
                {
                    state.verifyOriginalPacket_(certificate_0);
                }

                for (int i = 0; i < state.getCertificateChain_().Count; ++i)
                {
                    cacheVerifiedCertificate(state.getCertificateChain_()[i]);
                }

                return;
            }

            certificateFetcher_.fetch(certificateRequest, state,
                                      new Validator.Anonymous_C0(this));
        }
Beispiel #11
0
        /// <summary>
        /// Recursively validate the certificates in the certification chain.
        /// </summary>
        ///
        /// <param name="certificate_0">The certificate to check.</param>
        /// <param name="state">The current validation state.</param>
        internal void validateCertificate(CertificateV2 certificate_0,
                                          ValidationState state)
        {
            logger_.log(ILOG.J2CsMapping.Util.Logging.Level.FINE, "Start validating certificate {0}", certificate_0
                        .getName().toUri());

            if (!certificate_0.isValid())
            {
                state.fail(new ValidationError(net.named_data.jndn.security.v2.ValidationError.EXPIRED_CERTIFICATE,
                                               "Retrieved certificate is not yet valid or expired `"
                                               + certificate_0.getName().toUri() + "`"));
                return;
            }

            policy_.checkCertificatePolicy(certificate_0, state,
                                           new Validator.Anonymous_C1(this, certificate_0));
        }
Beispiel #12
0
        /// <summary>
        /// Search for a certificate across all groups (longest prefix match).
        /// </summary>
        ///
        /// <param name="keyName">The key name prefix for searching for the certificate.</param>
        /// <returns>The found certificate, or null if not found.</returns>
        public CertificateV2 find(Name keyName)
        {
            refresh();

            Name nameKey = (Name)anchors_.anchorsByName_.ceilingKey(keyName);

            if (nameKey == null)
            {
                return(null);
            }
            CertificateV2 certificate = (CertificateV2)anchors_.anchorsByName_[nameKey];

            if (!keyName.isPrefixOf(certificate.getName()))
            {
                return(null);
            }
            return(certificate);
        }
Beispiel #13
0
 public void continueValidation(
     CertificateRequest certificateRequest,
     ValidationState state)
 {
     if (certificateRequest == null)
     {
         state.fail(new ValidationError(
                        net.named_data.jndn.security.v2.ValidationError.POLICY_ERROR,
                        "Validation policy is not allowed to designate `"
                        + certificate.getName().toUri()
                        + "` as a trust anchor"));
     }
     else
     {
         // We need to fetch the key and validate it.
         state.addCertificate(certificate);
         outer_Validator.requestCertificate(certificateRequest, state);
     }
 }