ua_pki_default.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
  2. * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
  3. *
  4. * Copyright 2018 (c) Mark Giraud, Fraunhofer IOSB
  5. * Copyright 2019 (c) Kalycito Infotech Private Limited
  6. */
  7. #include <open62541/plugin/pki_default.h>
  8. #ifdef UA_ENABLE_ENCRYPTION
  9. #include <mbedtls/x509.h>
  10. #include <mbedtls/x509_crt.h>
  11. #endif
  12. /************/
  13. /* AllowAll */
  14. /************/
  15. static UA_StatusCode
  16. verifyCertificateAllowAll(void *verificationContext,
  17. const UA_ByteString *certificate) {
  18. return UA_STATUSCODE_GOOD;
  19. }
  20. static UA_StatusCode
  21. verifyApplicationURIAllowAll(void *verificationContext,
  22. const UA_ByteString *certificate,
  23. const UA_String *applicationURI) {
  24. return UA_STATUSCODE_GOOD;
  25. }
  26. static void
  27. deleteVerifyAllowAll(UA_CertificateVerification *cv) {
  28. }
  29. void UA_CertificateVerification_AcceptAll(UA_CertificateVerification *cv) {
  30. cv->verifyCertificate = verifyCertificateAllowAll;
  31. cv->verifyApplicationURI = verifyApplicationURIAllowAll;
  32. cv->deleteMembers = deleteVerifyAllowAll;
  33. }
  34. #ifdef UA_ENABLE_ENCRYPTION
  35. typedef struct {
  36. mbedtls_x509_crt certificateTrustList;
  37. mbedtls_x509_crt certificateIssuerList;
  38. mbedtls_x509_crl certificateRevocationList;
  39. } CertInfo;
  40. static UA_StatusCode
  41. certificateVerification_verify(void *verificationContext,
  42. const UA_ByteString *certificate) {
  43. CertInfo *ci = (CertInfo*)verificationContext;
  44. if(!ci)
  45. return UA_STATUSCODE_BADINTERNALERROR;
  46. /* Parse the certificate */
  47. mbedtls_x509_crt remoteCertificate;
  48. /* Temporary Object to parse the trustList */
  49. mbedtls_x509_crt *tempCert;
  50. mbedtls_x509_crt_init(&remoteCertificate);
  51. int mbedErr = mbedtls_x509_crt_parse(&remoteCertificate, certificate->data,
  52. certificate->length);
  53. if(mbedErr) {
  54. /* char errBuff[300]; */
  55. /* mbedtls_strerror(mbedErr, errBuff, 300); */
  56. /* UA_LOG_WARNING(data->policyContext->securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, */
  57. /* "Could not parse the remote certificate with error: %s", errBuff); */
  58. return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
  59. }
  60. /* Verify */
  61. mbedtls_x509_crt_profile crtProfile = {
  62. MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256),
  63. 0xFFFFFF, 0x000000, 128 * 8 // in bits
  64. }; // TODO: remove magic numbers
  65. uint32_t flags = 0;
  66. mbedErr = mbedtls_x509_crt_verify_with_profile(&remoteCertificate,
  67. &ci->certificateTrustList,
  68. &ci->certificateRevocationList,
  69. &crtProfile, NULL, &flags, NULL, NULL);
  70. /* Flag to check if the remote certificate is trusted or not */
  71. int TRUSTED = 0;
  72. /* Check if the remoteCertificate is present in the trustList while mbedErr value is not zero */
  73. if(mbedErr && !(flags & MBEDTLS_X509_BADCERT_EXPIRED) && !(flags & MBEDTLS_X509_BADCERT_FUTURE)) {
  74. for(tempCert = &ci->certificateTrustList; tempCert != NULL; tempCert = tempCert->next) {
  75. if(remoteCertificate.raw.len == tempCert->raw.len &&
  76. memcmp(remoteCertificate.raw.p, tempCert->raw.p, remoteCertificate.raw.len) == 0) {
  77. TRUSTED = 1;
  78. break;
  79. }
  80. }
  81. }
  82. /* If the remote certificate is present in the trustList then check if the issuer certificate
  83. * of remoteCertificate is present in issuerList */
  84. if(TRUSTED && mbedErr) {
  85. mbedErr = mbedtls_x509_crt_verify_with_profile(&remoteCertificate,
  86. &ci->certificateIssuerList,
  87. &ci->certificateRevocationList,
  88. &crtProfile, NULL, &flags, NULL, NULL);
  89. }
  90. // TODO: Extend verification
  91. /* This condition will check whether the certificate is a User certificate
  92. * or a CA certificate. If the MBEDTLS_X509_KU_KEY_CERT_SIGN and
  93. * MBEDTLS_X509_KU_CRL_SIGN of key_usage are set, then the certificate
  94. * shall be condidered as CA Certificate and cannot be used to establish a
  95. * connection. Refer the test case CTT/Security/Security Certificate Validation/029.js
  96. * for more details */
  97. if((remoteCertificate.key_usage & MBEDTLS_X509_KU_KEY_CERT_SIGN) &&
  98. (remoteCertificate.key_usage & MBEDTLS_X509_KU_CRL_SIGN)) {
  99. return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED;
  100. }
  101. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  102. if(mbedErr) {
  103. /* char buff[100]; */
  104. /* mbedtls_x509_crt_verify_info(buff, 100, "", flags); */
  105. /* UA_LOG_ERROR(channelContextData->policyContext->securityPolicy->logger, */
  106. /* UA_LOGCATEGORY_SECURITYPOLICY, */
  107. /* "Verifying the certificate failed with error: %s", buff); */
  108. if(flags & (uint32_t)MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
  109. retval = UA_STATUSCODE_BADCERTIFICATEUNTRUSTED;
  110. } else if(flags & (uint32_t)MBEDTLS_X509_BADCERT_FUTURE ||
  111. flags & (uint32_t)MBEDTLS_X509_BADCERT_EXPIRED) {
  112. retval = UA_STATUSCODE_BADCERTIFICATETIMEINVALID;
  113. } else if(flags & (uint32_t)MBEDTLS_X509_BADCERT_REVOKED ||
  114. flags & (uint32_t)MBEDTLS_X509_BADCRL_EXPIRED) {
  115. retval = UA_STATUSCODE_BADCERTIFICATEREVOKED;
  116. } else {
  117. retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
  118. }
  119. }
  120. mbedtls_x509_crt_free(&remoteCertificate);
  121. return retval;
  122. }
  123. /* Find binary substring. Taken and adjusted from
  124. * http://tungchingkai.blogspot.com/2011/07/binary-strstr.html */
  125. static const unsigned char *
  126. bstrchr(const unsigned char *s, const unsigned char ch, size_t l) {
  127. /* find first occurrence of c in char s[] for length l*/
  128. /* handle special case */
  129. if(l == 0)
  130. return (NULL);
  131. for(; *s != ch; ++s, --l)
  132. if(l == 0)
  133. return (NULL);
  134. return s;
  135. }
  136. static const unsigned char *
  137. bstrstr(const unsigned char *s1, size_t l1, const unsigned char *s2, size_t l2) {
  138. /* find first occurrence of s2[] in s1[] for length l1*/
  139. const unsigned char *ss1 = s1;
  140. const unsigned char *ss2 = s2;
  141. /* handle special case */
  142. if(l1 == 0)
  143. return (NULL);
  144. if(l2 == 0)
  145. return s1;
  146. /* match prefix */
  147. for (; (s1 = bstrchr(s1, *s2, (uintptr_t)ss1-(uintptr_t)s1+(uintptr_t)l1)) != NULL &&
  148. (uintptr_t)ss1-(uintptr_t)s1+(uintptr_t)l1 != 0; ++s1) {
  149. /* match rest of prefix */
  150. const unsigned char *sc1, *sc2;
  151. for (sc1 = s1, sc2 = s2; ;)
  152. if (++sc2 >= ss2+l2)
  153. return s1;
  154. else if (*++sc1 != *sc2)
  155. break;
  156. }
  157. return NULL;
  158. }
  159. static UA_StatusCode
  160. certificateVerification_verifyApplicationURI(void *verificationContext,
  161. const UA_ByteString *certificate,
  162. const UA_String *applicationURI) {
  163. CertInfo *ci = (CertInfo*)verificationContext;
  164. if(!ci)
  165. return UA_STATUSCODE_BADINTERNALERROR;
  166. /* Parse the certificate */
  167. mbedtls_x509_crt remoteCertificate;
  168. mbedtls_x509_crt_init(&remoteCertificate);
  169. int mbedErr = mbedtls_x509_crt_parse(&remoteCertificate, certificate->data,
  170. certificate->length);
  171. if(mbedErr)
  172. return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
  173. /* Poor man's ApplicationUri verification. mbedTLS does not parse all fields
  174. * of the Alternative Subject Name. Instead test whether the URI-string is
  175. * present in the v3_ext field in general.
  176. *
  177. * TODO: Improve parsing of the Alternative Subject Name */
  178. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  179. if(bstrstr(remoteCertificate.v3_ext.p, remoteCertificate.v3_ext.len,
  180. applicationURI->data, applicationURI->length) == NULL)
  181. retval = UA_STATUSCODE_BADCERTIFICATEURIINVALID;
  182. mbedtls_x509_crt_free(&remoteCertificate);
  183. return retval;
  184. }
  185. static void
  186. certificateVerification_deleteMembers(UA_CertificateVerification *cv) {
  187. CertInfo *ci = (CertInfo*)cv->context;
  188. if(!ci)
  189. return;
  190. mbedtls_x509_crt_free(&ci->certificateTrustList);
  191. mbedtls_x509_crl_free(&ci->certificateRevocationList);
  192. UA_free(ci);
  193. cv->context = NULL;
  194. }
  195. UA_StatusCode
  196. UA_CertificateVerification_Trustlist(UA_CertificateVerification *cv,
  197. const UA_ByteString *certificateTrustList,
  198. size_t certificateTrustListSize,
  199. const UA_ByteString *certificateIssuerList,
  200. size_t certificateIssuerListSize,
  201. const UA_ByteString *certificateRevocationList,
  202. size_t certificateRevocationListSize) {
  203. CertInfo *ci = (CertInfo*)UA_malloc(sizeof(CertInfo));
  204. if(!ci)
  205. return UA_STATUSCODE_BADOUTOFMEMORY;
  206. mbedtls_x509_crt_init(&ci->certificateTrustList);
  207. mbedtls_x509_crl_init(&ci->certificateRevocationList);
  208. mbedtls_x509_crt_init(&ci->certificateIssuerList);
  209. cv->context = (void*)ci;
  210. if(certificateTrustListSize > 0)
  211. cv->verifyCertificate = certificateVerification_verify;
  212. else
  213. cv->verifyCertificate = verifyCertificateAllowAll;
  214. cv->deleteMembers = certificateVerification_deleteMembers;
  215. cv->verifyApplicationURI = certificateVerification_verifyApplicationURI;
  216. int err = 0;
  217. for(size_t i = 0; i < certificateTrustListSize; i++) {
  218. err = mbedtls_x509_crt_parse(&ci->certificateTrustList,
  219. certificateTrustList[i].data,
  220. certificateTrustList[i].length);
  221. if(err)
  222. goto error;
  223. }
  224. for(size_t i = 0; i < certificateIssuerListSize; i++) {
  225. err = mbedtls_x509_crt_parse(&ci->certificateIssuerList,
  226. certificateIssuerList[i].data,
  227. certificateIssuerList[i].length);
  228. if(err)
  229. goto error;
  230. }
  231. for(size_t i = 0; i < certificateRevocationListSize; i++) {
  232. err = mbedtls_x509_crl_parse(&ci->certificateRevocationList,
  233. certificateRevocationList[i].data,
  234. certificateRevocationList[i].length);
  235. if(err)
  236. goto error;
  237. }
  238. return UA_STATUSCODE_GOOD;
  239. error:
  240. certificateVerification_deleteMembers(cv);
  241. return UA_STATUSCODE_BADINTERNALERROR;
  242. }
  243. #endif