xbsconst.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  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. * X.509 v3 Basic Constraints Extension
  6. */
  7. #include "prtypes.h"
  8. #include <limits.h> /* for LONG_MAX */
  9. #include "seccomon.h"
  10. #include "secdert.h"
  11. #include "secoidt.h"
  12. #include "secasn1t.h"
  13. #include "secasn1.h"
  14. #include "certt.h"
  15. #include "secder.h"
  16. #include "prprf.h"
  17. #include "secerr.h"
  18. typedef struct EncodedContext {
  19. SECItem isCA;
  20. SECItem pathLenConstraint;
  21. SECItem encodedValue;
  22. PLArenaPool *arena;
  23. } EncodedContext;
  24. static const SEC_ASN1Template CERTBasicConstraintsTemplate[] = {
  25. { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(EncodedContext) },
  26. { SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN, /* XXX DER_DEFAULT */
  27. offsetof(EncodedContext, isCA) },
  28. { SEC_ASN1_OPTIONAL | SEC_ASN1_INTEGER,
  29. offsetof(EncodedContext, pathLenConstraint) },
  30. { 0 }
  31. };
  32. static unsigned char hexTrue = 0xff;
  33. static unsigned char hexFalse = 0x00;
  34. #define GEN_BREAK(status) \
  35. rv = status; \
  36. break;
  37. SECStatus
  38. CERT_EncodeBasicConstraintValue(PLArenaPool *arena, CERTBasicConstraints *value,
  39. SECItem *encodedValue)
  40. {
  41. EncodedContext encodeContext;
  42. PLArenaPool *our_pool = NULL;
  43. SECStatus rv = SECSuccess;
  44. do {
  45. PORT_Memset(&encodeContext, 0, sizeof(encodeContext));
  46. if (!value->isCA && value->pathLenConstraint >= 0) {
  47. PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID);
  48. GEN_BREAK(SECFailure);
  49. }
  50. encodeContext.arena = arena;
  51. if (value->isCA == PR_TRUE) {
  52. encodeContext.isCA.data = &hexTrue;
  53. encodeContext.isCA.len = 1;
  54. }
  55. /* If the pathLenConstraint is less than 0, then it should be
  56. * omitted from the encoding.
  57. */
  58. if (value->isCA && value->pathLenConstraint >= 0) {
  59. our_pool = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
  60. if (our_pool == NULL) {
  61. PORT_SetError(SEC_ERROR_NO_MEMORY);
  62. GEN_BREAK(SECFailure);
  63. }
  64. if (SEC_ASN1EncodeUnsignedInteger(
  65. our_pool, &encodeContext.pathLenConstraint,
  66. (unsigned long)value->pathLenConstraint) == NULL) {
  67. PORT_SetError(SEC_ERROR_NO_MEMORY);
  68. GEN_BREAK(SECFailure);
  69. }
  70. }
  71. if (SEC_ASN1EncodeItem(arena, encodedValue, &encodeContext,
  72. CERTBasicConstraintsTemplate) == NULL) {
  73. GEN_BREAK(SECFailure);
  74. }
  75. } while (0);
  76. if (our_pool)
  77. PORT_FreeArena(our_pool, PR_FALSE);
  78. return (rv);
  79. }
  80. SECStatus
  81. CERT_DecodeBasicConstraintValue(CERTBasicConstraints *value,
  82. const SECItem *encodedValue)
  83. {
  84. EncodedContext decodeContext;
  85. PORTCheapArenaPool tmpArena;
  86. SECStatus rv = SECSuccess;
  87. do {
  88. PORT_Memset(&decodeContext, 0, sizeof(decodeContext));
  89. /* initialize the value just in case we got "0x30 00", or when the
  90. pathLenConstraint is omitted.
  91. */
  92. decodeContext.isCA.data = &hexFalse;
  93. decodeContext.isCA.len = 1;
  94. PORT_InitCheapArena(&tmpArena, SEC_ASN1_DEFAULT_ARENA_SIZE);
  95. rv = SEC_QuickDERDecodeItem(&tmpArena.arena, &decodeContext,
  96. CERTBasicConstraintsTemplate, encodedValue);
  97. if (rv == SECFailure)
  98. break;
  99. value->isCA = decodeContext.isCA.data
  100. ? (PRBool)(decodeContext.isCA.data[0] != 0)
  101. : PR_FALSE;
  102. if (decodeContext.pathLenConstraint.data == NULL) {
  103. /* if the pathLenConstraint is not encoded, and the current setting
  104. is CA, then the pathLenConstraint should be set to a negative
  105. number
  106. for unlimited certificate path.
  107. */
  108. if (value->isCA)
  109. value->pathLenConstraint = CERT_UNLIMITED_PATH_CONSTRAINT;
  110. } else if (value->isCA) {
  111. long len = DER_GetInteger(&decodeContext.pathLenConstraint);
  112. if (len < 0 || len == LONG_MAX) {
  113. PORT_SetError(SEC_ERROR_BAD_DER);
  114. GEN_BREAK(SECFailure);
  115. }
  116. value->pathLenConstraint = len;
  117. } else {
  118. /* here we get an error where the subject is not a CA, but
  119. the pathLenConstraint is set */
  120. PORT_SetError(SEC_ERROR_BAD_DER);
  121. GEN_BREAK(SECFailure);
  122. break;
  123. }
  124. } while (0);
  125. PORT_DestroyCheapArena(&tmpArena);
  126. return (rv);
  127. }