PageRenderTime 58ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 0ms

/cert-svc/vcore/src/vcore/SignatureValidator.cpp

https://review.tizen.org/git/
C++ | 265 lines | 187 code | 43 blank | 35 comment | 38 complexity | 7aa206c55e053154db228332de22b943 MD5 | raw file
Possible License(s): GPL-3.0, AGPL-3.0, GPL-2.0, MPL-2.0, JSON, WTFPL, CC-BY-SA-4.0, CC-BY-3.0, BSD-3-Clause, LGPL-2.0, MPL-2.0-no-copyleft-exception, AGPL-1.0, 0BSD, Zlib, Unlicense, BSD-2-Clause, Apache-2.0, LGPL-3.0, ISC, MIT, CC-BY-SA-3.0, CC0-1.0, LGPL-2.1
  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. #include <libxml/parser.h>
  17. #include <libxml/c14n.h>
  18. #include <openssl/asn1.h>
  19. #include <dpl/log/log.h>
  20. #include "CertificateVerifier.h"
  21. #include "OCSPCertMgrUtil.h"
  22. #include "Certificate.h"
  23. #include "ReferenceValidator.h"
  24. #include "SignatureValidator.h"
  25. #include "SSLContainers.h"
  26. #include "ValidatorCommon.h"
  27. #include "ValidatorFactories.h"
  28. #include "XmlsecAdapter.h"
  29. namespace {
  30. const time_t TIMET_DAY = 60 * 60 * 24;
  31. const std::string TOKEN_ROLE_AUTHOR_URI =
  32. "http://www.w3.org/ns/widgets-digsig#role-author";
  33. const std::string TOKEN_ROLE_DISTRIBUTOR_URI =
  34. "http://www.w3.org/ns/widgets-digsig#role-distributor";
  35. const std::string TOKEN_PROFILE_URI =
  36. "http://www.w3.org/ns/widgets-digsig#profile";
  37. } // namespace anonymouse
  38. namespace ValidationCore {
  39. SignatureValidator::SignatureValidator(bool ocspEnable,
  40. bool crlEnable,
  41. bool complianceMode) :
  42. m_ocspEnable(ocspEnable),
  43. m_crlEnable(crlEnable),
  44. m_complianceModeEnabled(complianceMode)
  45. {
  46. }
  47. SignatureValidator::~SignatureValidator()
  48. {
  49. }
  50. bool SignatureValidator::checkRoleURI(const SignatureData &data)
  51. {
  52. std::string roleURI = data.getRoleURI();
  53. if (roleURI.empty()) {
  54. LogWarning("URI attribute in Role tag couldn't be empty.");
  55. return false;
  56. }
  57. if (roleURI != TOKEN_ROLE_AUTHOR_URI && data.isAuthorSignature()) {
  58. LogWarning("URI attribute in Role tag does not "
  59. "match with signature filename.");
  60. return false;
  61. }
  62. if (roleURI != TOKEN_ROLE_DISTRIBUTOR_URI && !data.isAuthorSignature()) {
  63. LogWarning("URI attribute in Role tag does not "
  64. "match with signature filename.");
  65. return false;
  66. }
  67. return true;
  68. }
  69. bool SignatureValidator::checkProfileURI(const SignatureData &data)
  70. {
  71. if (TOKEN_PROFILE_URI != data.getProfileURI()) {
  72. LogWarning(
  73. "Profile tag contains unsupported value in URI attribute(" <<
  74. data.getProfileURI() << ").");
  75. return false;
  76. }
  77. return true;
  78. }
  79. bool SignatureValidator::checkObjectReferences(const SignatureData &data)
  80. {
  81. ObjectList objectList = data.getObjectList();
  82. ObjectList::const_iterator iter;
  83. for (iter = objectList.begin(); iter != objectList.end(); ++iter) {
  84. if (!data.containObjectReference(*iter)) {
  85. LogWarning("Signature does not contain reference for object " <<
  86. *iter);
  87. return false;
  88. }
  89. }
  90. return true;
  91. }
  92. SignatureValidator::Result SignatureValidator::check(
  93. SignatureData &data,
  94. const std::string &widgetContentPath)
  95. {
  96. bool disregard = false;
  97. if (!checkRoleURI(data)) {
  98. return SIGNATURE_INVALID;
  99. }
  100. if (!checkProfileURI(data)) {
  101. return SIGNATURE_INVALID;
  102. }
  103. // CertificateList sortedCertificateList = data.getCertList();
  104. CertificateCollection collection;
  105. collection.load(data.getCertList());
  106. // First step - sort certificate
  107. if (!collection.sort()) {
  108. LogWarning("Certificates do not form valid chain.");
  109. return SIGNATURE_INVALID;
  110. }
  111. // Check for error
  112. if (collection.empty()) {
  113. LogWarning("Certificate list in signature is empty.");
  114. return SIGNATURE_INVALID;
  115. }
  116. CertificateList sortedCertificateList = collection.getChain();
  117. // TODO move it to CertificateCollection
  118. // Add root CA and CA certificates (if chain is incomplete)
  119. sortedCertificateList =
  120. OCSPCertMgrUtil::completeCertificateChain(sortedCertificateList);
  121. CertificatePtr root = sortedCertificateList.back();
  122. // Is Root CA certificate trusted?
  123. CertStoreId::Set storeIdSet = createCertificateIdentifier().find(root);
  124. // WAC chapter 3.2.1 - verified definition
  125. if (data.isAuthorSignature()) {
  126. if (!storeIdSet.contains(CertStoreId::WAC_PUBLISHER)) {
  127. LogWarning("Author signature has got unrecognized Root CA "
  128. "certificate. Signature will be disregarded.");
  129. disregard = true;
  130. }
  131. LogDebug("Root CA for author signature is correct.");
  132. } else {
  133. if (!storeIdSet.contains(CertStoreId::DEVELOPER) &&
  134. !storeIdSet.contains(CertStoreId::WAC_ROOT) &&
  135. !storeIdSet.contains(CertStoreId::WAC_MEMBER))
  136. {
  137. LogWarning("Distiributor signature has got unrecognized Root CA "
  138. "certificate. Signature will be disregarded.");
  139. disregard = true;
  140. }
  141. LogDebug("Root CA for distributor signature is correct.");
  142. }
  143. data.setStorageType(storeIdSet);
  144. data.setSortedCertificateList(sortedCertificateList);
  145. // We add only Root CA certificate because WAC ensure that the rest
  146. // of certificates are present in signature files ;-)
  147. XmlSec::XmlSecContext context;
  148. context.signatureFile = data.getSignatureFileName();
  149. context.certificatePtr = root;
  150. // Now we should have full certificate chain.
  151. // If the end certificate is not ROOT CA we should disregard signature
  152. // but still signature must be valid... Aaaaaa it's so stupid...
  153. if (!(root->isSignedBy(root))) {
  154. LogWarning("Root CA certificate not found. Chain is incomplete.");
  155. context.allowBrokenChain = true;
  156. }
  157. // WAC 2.0 SP-2066 The wrt must not block widget installation
  158. // due to expiration of the author certificate.
  159. time_t notAfter = data.getEndEntityCertificatePtr()->getNotAfter();
  160. bool expired = notAfter < time(NULL);
  161. if (data.isAuthorSignature() && expired) {
  162. context.validationTime = notAfter - TIMET_DAY;
  163. }
  164. // end
  165. if (XmlSec::NO_ERROR != XmlSecSingleton::Instance().validate(&context)) {
  166. LogWarning("Installation break - invalid package!");
  167. return SIGNATURE_INVALID;
  168. }
  169. data.setReference(context.referenceSet);
  170. if (!checkObjectReferences(data)) {
  171. return SIGNATURE_INVALID;
  172. }
  173. ReferenceValidator fileValidator(widgetContentPath);
  174. if (ReferenceValidator::NO_ERROR != fileValidator.checkReferences(data)) {
  175. LogWarning("Invalid package - file references broken");
  176. return SIGNATURE_INVALID;
  177. }
  178. // It is good time to do OCSP check
  179. // ocspCheck will throw an exception on any error.
  180. // TODO Probably we should catch this exception and add
  181. // some information to SignatureData.
  182. if (!m_complianceModeEnabled && !data.isAuthorSignature()) {
  183. CertificateCollection coll;
  184. coll.load(sortedCertificateList);
  185. if (!coll.sort()) {
  186. LogDebug("Collection does not contain chain!");
  187. return SIGNATURE_INVALID;
  188. }
  189. CertificateVerifier verificator(m_ocspEnable, m_crlEnable);
  190. VerificationStatus result = verificator.check(coll);
  191. if (result == VERIFICATION_STATUS_REVOKED) {
  192. return SIGNATURE_REVOKED;
  193. }
  194. if (result == VERIFICATION_STATUS_UNKNOWN ||
  195. result == VERIFICATION_STATUS_ERROR)
  196. {
  197. disregard = true;
  198. }
  199. }
  200. if (disregard) {
  201. LogWarning("Signature is disregard.");
  202. return SIGNATURE_DISREGARD;
  203. }
  204. return SIGNATURE_VERIFIED;
  205. }
  206. std::string SignatureValidator::FingerprintToColonHex(
  207. const Certificate::Fingerprint &fingerprint)
  208. {
  209. std::string outString;
  210. char buff[8];
  211. for (size_t i = 0; i < fingerprint.size(); ++i) {
  212. snprintf(buff,
  213. sizeof(buff),
  214. "%02X:",
  215. static_cast<unsigned int>(fingerprint[i]));
  216. outString += buff;
  217. }
  218. // remove trailing ":"
  219. outString.erase(outString.end() - 1);
  220. return outString;
  221. }
  222. } // namespace ValidationCore