certv3.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. /*
  5. * Code for dealing with X509.V3 extensions.
  6. */
  7. #include "cert.h"
  8. #include "secitem.h"
  9. #include "secoid.h"
  10. #include "secder.h"
  11. #include "secasn1.h"
  12. #include "certxutl.h"
  13. #include "secerr.h"
  14. SECStatus
  15. CERT_FindCertExtensionByOID(CERTCertificate *cert, SECItem *oid, SECItem *value)
  16. {
  17. return (cert_FindExtensionByOID(cert->extensions, oid, value));
  18. }
  19. SECStatus
  20. CERT_FindCertExtension(const CERTCertificate *cert, int tag, SECItem *value)
  21. {
  22. return (cert_FindExtension(cert->extensions, tag, value));
  23. }
  24. static void
  25. SetExts(void *object, CERTCertExtension **exts)
  26. {
  27. CERTCertificate *cert = (CERTCertificate *)object;
  28. cert->extensions = exts;
  29. DER_SetUInteger(cert->arena, &(cert->version), SEC_CERTIFICATE_VERSION_3);
  30. }
  31. void *
  32. CERT_StartCertExtensions(CERTCertificate *cert)
  33. {
  34. return (cert_StartExtensions((void *)cert, cert->arena, SetExts));
  35. }
  36. /*
  37. * get the value of the Netscape Certificate Type Extension
  38. */
  39. SECStatus
  40. CERT_FindNSCertTypeExtension(CERTCertificate *cert, SECItem *retItem)
  41. {
  42. return (CERT_FindBitStringExtension(
  43. cert->extensions, SEC_OID_NS_CERT_EXT_CERT_TYPE, retItem));
  44. }
  45. /*
  46. * get the value of a string type extension
  47. */
  48. char *
  49. CERT_FindNSStringExtension(CERTCertificate *cert, int oidtag)
  50. {
  51. SECItem wrapperItem, tmpItem = { siBuffer, 0 };
  52. SECStatus rv;
  53. PLArenaPool *arena = NULL;
  54. char *retstring = NULL;
  55. wrapperItem.data = NULL;
  56. tmpItem.data = NULL;
  57. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  58. if (!arena) {
  59. goto loser;
  60. }
  61. rv = cert_FindExtension(cert->extensions, oidtag, &wrapperItem);
  62. if (rv != SECSuccess) {
  63. goto loser;
  64. }
  65. rv = SEC_QuickDERDecodeItem(
  66. arena, &tmpItem, SEC_ASN1_GET(SEC_IA5StringTemplate), &wrapperItem);
  67. if (rv != SECSuccess) {
  68. goto loser;
  69. }
  70. retstring = (char *)PORT_Alloc(tmpItem.len + 1);
  71. if (retstring == NULL) {
  72. goto loser;
  73. }
  74. PORT_Memcpy(retstring, tmpItem.data, tmpItem.len);
  75. retstring[tmpItem.len] = '\0';
  76. loser:
  77. if (arena) {
  78. PORT_FreeArena(arena, PR_FALSE);
  79. }
  80. if (wrapperItem.data) {
  81. PORT_Free(wrapperItem.data);
  82. }
  83. return (retstring);
  84. }
  85. /*
  86. * get the value of the X.509 v3 Key Usage Extension
  87. */
  88. SECStatus
  89. CERT_FindKeyUsageExtension(CERTCertificate *cert, SECItem *retItem)
  90. {
  91. return (CERT_FindBitStringExtension(cert->extensions,
  92. SEC_OID_X509_KEY_USAGE, retItem));
  93. }
  94. /*
  95. * get the value of the X.509 v3 Key Usage Extension
  96. */
  97. SECStatus
  98. CERT_FindSubjectKeyIDExtension(CERTCertificate *cert, SECItem *retItem)
  99. {
  100. SECStatus rv;
  101. SECItem encodedValue = { siBuffer, NULL, 0 };
  102. SECItem decodedValue = { siBuffer, NULL, 0 };
  103. rv = cert_FindExtension(cert->extensions, SEC_OID_X509_SUBJECT_KEY_ID,
  104. &encodedValue);
  105. if (rv == SECSuccess) {
  106. PORTCheapArenaPool tmpArena;
  107. PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE);
  108. rv = SEC_QuickDERDecodeItem(&tmpArena.arena, &decodedValue,
  109. SEC_ASN1_GET(SEC_OctetStringTemplate),
  110. &encodedValue);
  111. if (rv == SECSuccess) {
  112. rv = SECITEM_CopyItem(NULL, retItem, &decodedValue);
  113. }
  114. PORT_DestroyCheapArena(&tmpArena);
  115. }
  116. SECITEM_FreeItem(&encodedValue, PR_FALSE);
  117. return rv;
  118. }
  119. SECStatus
  120. CERT_FindBasicConstraintExten(CERTCertificate *cert,
  121. CERTBasicConstraints *value)
  122. {
  123. SECItem encodedExtenValue;
  124. SECStatus rv;
  125. encodedExtenValue.data = NULL;
  126. encodedExtenValue.len = 0;
  127. rv = cert_FindExtension(cert->extensions, SEC_OID_X509_BASIC_CONSTRAINTS,
  128. &encodedExtenValue);
  129. if (rv != SECSuccess) {
  130. return (rv);
  131. }
  132. rv = CERT_DecodeBasicConstraintValue(value, &encodedExtenValue);
  133. /* free the raw extension data */
  134. PORT_Free(encodedExtenValue.data);
  135. encodedExtenValue.data = NULL;
  136. return (rv);
  137. }
  138. CERTAuthKeyID *
  139. CERT_FindAuthKeyIDExten(PLArenaPool *arena, CERTCertificate *cert)
  140. {
  141. SECItem encodedExtenValue;
  142. SECStatus rv;
  143. CERTAuthKeyID *ret;
  144. encodedExtenValue.data = NULL;
  145. encodedExtenValue.len = 0;
  146. rv = cert_FindExtension(cert->extensions, SEC_OID_X509_AUTH_KEY_ID,
  147. &encodedExtenValue);
  148. if (rv != SECSuccess) {
  149. return (NULL);
  150. }
  151. ret = CERT_DecodeAuthKeyID(arena, &encodedExtenValue);
  152. PORT_Free(encodedExtenValue.data);
  153. encodedExtenValue.data = NULL;
  154. return (ret);
  155. }
  156. SECStatus
  157. CERT_CheckCertUsage(CERTCertificate *cert, unsigned char usage)
  158. {
  159. SECItem keyUsage;
  160. SECStatus rv;
  161. /* There is no extension, v1 or v2 certificate */
  162. if (cert->extensions == NULL) {
  163. return (SECSuccess);
  164. }
  165. keyUsage.data = NULL;
  166. /* This code formerly ignored the Key Usage extension if it was
  167. ** marked non-critical. That was wrong. Since we do understand it,
  168. ** we are obligated to honor it, whether or not it is critical.
  169. */
  170. rv = CERT_FindKeyUsageExtension(cert, &keyUsage);
  171. if (rv == SECFailure) {
  172. rv = (PORT_GetError() == SEC_ERROR_EXTENSION_NOT_FOUND) ? SECSuccess
  173. : SECFailure;
  174. } else if (!keyUsage.data || !(keyUsage.data[0] & usage)) {
  175. PORT_SetError(SEC_ERROR_CERT_USAGES_INVALID);
  176. rv = SECFailure;
  177. }
  178. PORT_Free(keyUsage.data);
  179. return (rv);
  180. }