/// <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); }
/// <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); }
/// <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)); }
/// <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); }
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()); } } }
/// <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); }
/// <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); }
/// <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)); }
/// <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)); }
/// <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); }
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); } }