aa10925e41d093e43bea010c98cca905c41a1ba7
[platform/core/security/cert-svc.git] / vcore / src / vcore / OCSPCertMgrUtil.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 /*
17  * @author      Michal Ciepielski(m.ciepielski@samsung.com)
18  * @version     0.3
19  * @brief
20  */
21
22 #include <vcore/OCSPCertMgrUtil.h>
23 #include <vcore/SSLContainers.h>
24
25 #include <openssl/pem.h>
26 #include <openssl/x509.h>
27 #include <dpl/assert.h>
28 #include <dpl/log/log.h>
29 #include <dpl/scoped_resource.h>
30 #include <string.h>
31 #include <iostream>
32 #include <string>
33
34 #include <cert-service.h>
35
36 namespace {
37 const int MAX_BUF = 1024;
38
39 struct ContextDeleter
40 {
41     typedef CERT_CONTEXT* Type;
42     static Type NullValue()
43     {
44         return NULL;
45     }
46     static void Destroy(Type context)
47     {
48         if (context) {
49             cert_svc_cert_context_final(context);
50         }
51     }
52 };
53 }
54
55 namespace ValidationCore {
56 namespace OCSPCertMgrUtil {
57 /*
58  * TODO This API function should be changed to:
59  * CertifiatePtr getCertFromStore(const std::string &subject);
60  *
61  * All of cert_svc function could return error because input
62  * data are corruped. That's why I dont want to throw exceptions
63  * in this function.
64  */
65 void getCertFromStore(X509_NAME *subject,
66         X509 **xcert)
67 {
68     if (!xcert || *xcert || !subject) {
69         LogError("Invalid input!");
70         return;
71     }
72
73     typedef VcoreDPL::ScopedResource<ContextDeleter> ScopedContext;
74
75     int result;
76     char buffer[MAX_BUF];
77     const unsigned char* ptr = NULL;
78     X509 *pCertificate = NULL;
79     cert_svc_filename_list *fileList = NULL;
80
81     X509_NAME_oneline(subject, buffer, MAX_BUF);
82
83     ScopedContext ctx(cert_svc_cert_context_init());
84     if (ctx.Get() == NULL) {
85         LogWarning("Error in cert_svc_cert_context_init.");
86         return;
87     }
88
89     LogDebug("Search certificate with subject: " << buffer);
90     result = cert_svc_search_certificate(ctx.Get(), SUBJECT_STR, buffer);
91     LogDebug("Search finished!");
92
93     if (CERT_SVC_ERR_NO_ERROR != result) {
94         LogWarning("Error during certificate search");
95         return;
96     }
97
98     fileList = ctx.Get()->fileNames;
99
100     if (fileList == NULL) {
101         LogDebug("No certificate found");
102         return;
103     }
104
105     if (fileList->filename == NULL) {
106         LogWarning("Empty filename");
107         return;
108     }
109
110     LogDebug("Found cert file: " << fileList->filename);
111     ScopedContext ctx2(cert_svc_cert_context_init());
112
113     if (ctx2.Get() == NULL) {
114         LogWarning("Error in cert_svc_cert_context_init.");
115         return;
116     }
117
118     // TODO add read_certifcate_from_file function to Certificate.h
119     if (CERT_SVC_ERR_NO_ERROR !=
120         cert_svc_load_file_to_context(ctx2.Get(), fileList->filename)) {
121         LogWarning("Error in cert_svc_load_file_to_context");
122         return;
123     }
124
125     ptr = ctx2.Get()->certBuf->data;
126     // create a certificate from mem buff
127     pCertificate = d2i_X509(NULL, &ptr, ctx2.Get()->certBuf->size);
128
129     if (pCertificate == NULL) {
130         LogWarning("Error during certificate conversion in d2i_X509");
131         return;
132     }
133
134     *xcert = pCertificate;
135     if (fileList->next != NULL) {
136         LogError("There is more then one certificate with same subject :/");
137         // TODO Implement me.
138         for (fileList = fileList->next;
139              fileList != NULL;
140              fileList = fileList->next) {
141             LogError("Additional certificate with same subject: " << fileList->filename);
142         }
143     }
144 }
145
146 CertificatePtr getParentFromStore(const CertificatePtr &certificate)
147 {
148     Assert(certificate.get());
149     X509* rawPtr = certificate->getX509();
150
151     /* TODO Add getIssuerName function to Certificate.h */
152     X509_NAME *name = X509_get_issuer_name(rawPtr);
153
154     X509* rawTemp = NULL;
155     getCertFromStore(name, &rawTemp);
156
157     if (rawTemp == NULL) {
158         return CertificatePtr();
159     }
160     SSLSmartContainer<X509> scope(rawTemp);
161     return CertificatePtr(new Certificate(rawTemp));
162 }
163
164 CertificateList completeCertificateChain(const CertificateList &certificateList)
165 {
166     CertificateList result = certificateList;
167     CertificatePtr last = result.back();
168     if (last->isSignedBy(last)) {
169         return result;
170     }
171     CertificatePtr parent = getParentFromStore(last);
172     if (parent.get()) {
173         result.push_back(parent);
174     }
175     return result;
176 }
177 } // namespace OCSPCertMgrUtil
178 } // namespace ValidationCore