security/nss/lib/certdb/xbsconst.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial