2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * @file CachedOCSP.cpp
19 * @author Tomasz Swierczek (t.swierczek@samsung.com)
21 * @brief Cached OCSP class implementation
27 #include <dpl/foreach.h>
28 #include <dpl/log/log.h>
29 #include <dpl/foreach.h>
32 #include "CachedOCSP.h"
33 #include "Certificate.h"
34 #include "CertificateCacheDAO.h"
36 namespace ValidationCore {
38 const time_t CachedOCSP::OCSP_minTimeValid = 3600; // one hour in seconds
40 const time_t CachedOCSP::OCSP_maxTimeValid =
41 3600 * 24 * 7; // one week in seconds
43 const time_t CachedOCSP::OCSP_refreshBefore = 3600; // one hour in seconds
45 VerificationStatus CachedOCSP::check(const CertificateCollection &certs)
47 OCSPCachedStatus db_status;
51 db_status.cert_chain = certs.toBase64String();
52 db_status.end_entity_check = false;
54 if (CertificateCacheDAO::getOCSPStatus(&db_status)) {
55 LogDebug("Found cache entry for OCSP");
56 if (now < db_status.next_update_time) {
57 LogDebug("Cache response valid");
58 return db_status.ocsp_status;
62 // here we need to get OCSP result and add/update cache
64 CertificateList list = certs.getChain();
65 ocsp.setTrustedStore(list);
67 VerificationStatusSet statusSet = ocsp.validateCertificateList(list);
68 db_status.ocsp_status = statusSet.convertToStatus();
69 db_status.next_update_time = ocsp.getResponseValidity();
70 CertificateCacheDAO::setOCSPStatus(db_status.cert_chain,
71 db_status.ocsp_status,
72 db_status.end_entity_check,
75 db_status.next_update_time));
76 return db_status.ocsp_status;
79 VerificationStatus CachedOCSP::checkEndEntity(CertificateCollection &certs)
81 OCSPCachedStatus db_status;
85 db_status.cert_chain = certs.toBase64String();
86 db_status.end_entity_check = true;
88 if (CertificateCacheDAO::getOCSPStatus(&db_status)) {
89 LogDebug("Found cache entry for OCSP");
90 if (now < db_status.next_update_time) {
91 LogDebug("Cache response valid");
92 return db_status.ocsp_status;
96 // here we need to send request via OCSP and add/update cache
98 getCertsForEndEntity(certs, &clst);
101 ocsp.setTrustedStore(certs.getCertificateList());
103 const char *defResponderURI = getenv(OCSP::DEFAULT_RESPONDER_URI_ENV);
105 if (defResponderURI) {
106 ocsp.setUseDefaultResponder(true);
107 ocsp.setDefaultResponder(defResponderURI);
110 VerificationStatusSet statusSet = ocsp.validateCertificateList(clst);
111 db_status.ocsp_status = statusSet.convertToStatus();
112 db_status.next_update_time = ocsp.getResponseValidity();
114 CertificateCacheDAO::setOCSPStatus(db_status.cert_chain,
115 db_status.ocsp_status,
116 db_status.end_entity_check,
119 db_status.next_update_time));
121 return db_status.ocsp_status;
124 void CachedOCSP::updateCache()
128 now += OCSP_refreshBefore;
129 OCSPCachedStatusList list;
130 CertificateCacheDAO::getOCSPStatusList(&list);
131 FOREACH(db_status, list) {
132 if (now >= db_status->next_update_time) {
133 // this response needs to be refreshed
134 // TODO: check result? update even errors? need to check RFC
135 CertificateCollection col;
136 col.load(db_status->cert_chain);
139 CertificateList chain = col.getChain();
140 ocsp.setTrustedStore(chain);
142 VerificationStatusSet statusSet;
144 if (db_status->end_entity_check) {
145 CertificateList clst;
146 getCertsForEndEntity(col, &clst);
147 statusSet = ocsp.validateCertificateList(clst);
149 statusSet = ocsp.validateCertificateList(chain);
152 db_status->ocsp_status = statusSet.convertToStatus();
153 db_status->next_update_time = ocsp.getResponseValidity();
155 CertificateCacheDAO::setOCSPStatus(db_status->cert_chain,
156 db_status->ocsp_status,
157 db_status->end_entity_check,
158 db_status->next_update_time);
163 void CachedOCSP::getCertsForEndEntity(
164 const CertificateCollection &certs, CertificateList* clst)
167 LogError("NULL pointer");
171 if (certs.isChain() && certs.size() >= 2) {
172 CertificateList::const_iterator icert = certs.begin();
173 clst->push_back(*icert);
175 clst->push_back(*icert);
179 time_t CachedOCSP::getNextUpdateTime(time_t now, time_t response_validity)
181 long min = now + OCSP_minTimeValid;
182 long max = now + OCSP_maxTimeValid;
183 if (response_validity < min) {
186 if (response_validity > max) {
189 return response_validity;
192 } // namespace ValidationCore