Plan 9 from Bell Labs’s /usr/web/sources/contrib/mospak/tls-1.2/libsec-x509-extension-framework.diff

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


--- sys/src/libsec/port/x509.c
+++ sys/src/libsec/port/x509.c
@@ -1562,6 +1562,14 @@ freevalfields(Value* v)
  *           revocationDate UTCTime}
  */
 
+typedef struct CertExtension CertExtension;
+struct CertExtension {
+	CertExtension*	next;
+	Ints*		oid;
+	int		critical;
+	Bytes*		value;		/* extnValue OCTET STRING contents */
+};
+
 typedef struct CertX509 {
 	int	serial;
 	char*	issuer;
@@ -1574,6 +1582,8 @@ typedef struct CertX509 {
 	int	signature_alg;
 	Bytes*	signature;
 	Bytes*	ext;		/* raw extensions SEQUENCE (opaque); nil if cert has none */
+	CertExtension* extensions;	/* parsed list, nil if no extensions or unparseable */
+	int	unrecognizedCritical;	/* RFC 5280 Section 4.2 flag, checked by validator */
 } CertX509;
 
 /* Algorithm object-ids */
@@ -1678,6 +1688,9 @@ static void (*namedcurves[NUMCURVES])(mpint*, mpint*, 
 	secp384r1,
 };
 
+static void	freecertextensions(CertExtension* e);
+static void	parse_extensions(CertX509* c);
+
 static void
 freecert(CertX509* c)
 {
@@ -1693,10 +1706,108 @@ freecert(CertX509* c)
 	freebytes(c->publickey);
 	freebytes(c->signature);
 	freebytes(c->ext);
+	freecertextensions(c->extensions);
 	free(c);
 }
 
+static void
+freecertextensions(CertExtension *e)
+{
+	CertExtension *n;
+
+	while(e != nil){
+		n = e->next;
+		freeints(e->oid);
+		freebytes(e->value);
+		free(e);
+		e = n;
+	}
+}
+
 /*
+ * Parse one TBSCertificate extension element per RFC 5280 Section 4.2:
+ *   Extension ::= SEQUENCE { extnID OBJECT IDENTIFIER,
+ *                            critical BOOLEAN DEFAULT FALSE,
+ *                            extnValue OCTET STRING }
+ * Returns nil on parse failure (caller skips the entry).
+ */
+static CertExtension*
+parse_one_extension(Elem *e, int *critical_out)
+{
+	Elist *l;
+	Ints *oid;
+	Bytes *val;
+	CertExtension *ext;
+	int critical;
+
+	*critical_out = -1;
+	if(!is_seq(e, &l) || elistlen(l) < 2)
+		return nil;
+	if(!is_oid(&l->hd, &oid))
+		return nil;
+	l = l->tl;
+	critical = 0;
+	if(l != nil && l->hd.val.tag == VBool){
+		critical = l->hd.val.u.boolval;
+		l = l->tl;
+	}
+	/* Critical determined (explicit BOOLEAN or DEFAULT FALSE).
+	 * Set the out-param now so caller can apply RFC 5280 Section 4.2
+	 * even if the extnValue parse below fails. */
+	*critical_out = critical;
+	if(l == nil || !is_octetstring(&l->hd, &val))
+		return nil;
+
+	ext = (CertExtension*)emalloc(sizeof(CertExtension));
+	ext->oid = makeints(oid->data, oid->len);
+	ext->critical = critical;
+	ext->value = makebytes(val->data, val->len);
+	ext->next = nil;
+	return ext;
+}
+
+/*
+ * Walk c->ext (raw SEQUENCE OF Extension) and build the c->extensions
+ * list.  Sets c->unrecognizedCritical if any critical extension is
+ * encountered (refined by per-OID recognition in libsec-x509-rfc5280-
+ * constraints).  Silent on parse failure: c->extensions stays nil.
+ */
+static void
+parse_extensions(CertX509 *c)
+{
+	Elem eext;
+	Elist *el;
+	CertExtension *ext, **tail;
+	int critical;
+
+	if(c->ext == nil)
+		return;
+	if(decode(c->ext->data, c->ext->len, &eext) != ASN_OK)
+		return;
+	if(!is_seq(&eext, &el)){
+		freevalfields(&eext.val);
+		return;
+	}
+
+	tail = &c->extensions;
+	for(; el != nil; el = el->tl){
+		ext = parse_one_extension(&el->hd, &critical);
+		/* RFC 5280 Section 4.2: MUST reject a critical extension
+		 * we cannot process.  Malformed extnValue with a
+		 * determinable critical flag falls under "cannot process". */
+		if(ext == nil && critical == 1)
+			c->unrecognizedCritical = 1;
+		if(ext == nil)
+			continue;
+		*tail = ext;
+		tail = &ext->next;
+		if(ext->critical)
+			c->unrecognizedCritical = 1;
+	}
+	freevalfields(&eext.val);
+}
+
+/*
  * Parse the Name ASN1 type.
  * The sequence of RelativeDistinguishedName's gives a sort of pathname,
  * from most general to most specific.  Each element of the path can be
@@ -1925,6 +2036,7 @@ decode_cert(Bytes* a)
 		}
 		el = el->tl;
 	}
+	parse_extensions(c);
 
 	/*resume Certificate */
 	if(c->signature_alg < 0)

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.