aboutsummaryrefslogtreecommitdiff
path: root/rpkid/rpki/x509.py
diff options
context:
space:
mode:
Diffstat (limited to 'rpkid/rpki/x509.py')
-rw-r--r--rpkid/rpki/x509.py144
1 files changed, 89 insertions, 55 deletions
diff --git a/rpkid/rpki/x509.py b/rpkid/rpki/x509.py
index 99350ce7..30e32aa8 100644
--- a/rpkid/rpki/x509.py
+++ b/rpkid/rpki/x509.py
@@ -890,22 +890,19 @@ class PKCS10(DER_object):
"""
return self.getPublicKey().get_SKI()
- def check_valid_rpki(self, kind = "ca"):
+
+ def check_valid_request_common(self):
"""
- Check this certification request to see whether it's a valid
- request for an RPKI certificate. This is broken out of the
- up-down protocol code because it's somewhat involved and the
- up-down code doesn't need to know the details.
+ Common code for checking this certification requests to see
+ whether they conform to the RPKI certificate profile.
Throws an exception if the request isn't valid, so if this method
returns at all, the request is ok.
- This needs refactoring, as the nested conditionals to handle the
- different kinds of certificates have gotten rather nasty.
+ You probably don't want to call this directly, as it only performs
+ the checks that are common to all RPKI certificates.
"""
- assert kind in ("ca", "ee", "router")
-
if not self.get_POW().verify():
raise rpki.exceptions.BadPKCS10("PKCS #10 signature check failed")
@@ -914,73 +911,110 @@ class PKCS10(DER_object):
if ver != 0:
raise rpki.exceptions.BadPKCS10("PKCS #10 request has bad version number %s" % ver)
- alg = self.get_POW().getSignatureAlgorithm()
+ ku = self.get_POW().getKeyUsage()
- if alg != (rpki.oids.ecdsa_with_SHA256 if kind == "router" else rpki.oids.sha256WithRSAEncryption):
- raise rpki.exceptions.BadPKCS10("PKCS #10 request has bad signature algorithm %s" % alg)
+ if ku is not None and self.expected_ca_keyUsage != ku:
+ raise rpki.exceptions.BadPKCS10("PKCS #10 keyUsage doesn't match profile: %r" % ku)
- bc = self.get_POW().getBasicConstraints()
-
- if kind == "ca":
- if bc is None or not bc[0]:
- raise rpki.exceptions.BadPKCS10("Request for EE certificate not allowed here")
- else:
- if bc is not None and bc[0]:
- raise rpki.exceptions.BadPKCS10("Request for CA certificate not allowed here")
-
- if bc is not None and bc[1] is not None:
- raise rpki.exceptions.BadPKCS10("PKCS #10 basicConstraints must not specify Path Length")
+ forbidden_extensions = self.get_POW().getExtensionOIDs() - self.allowed_extensions
- ku = self.get_POW().getKeyUsage()
+ if forbidden_extensions:
+ raise rpki.exceptions.BadExtension("Forbidden extension%s in PKCS #10 certificate request: %s" % (
+ "" if len(forbidden_extensions) == 1 else "s",
+ ", ".join(forbidden_extensions)))
- if ku is not None and self.expected_ca_keyUsage != ku:
- raise rpki.exceptions.BadPKCS10("PKCS #10 keyUsage doesn't match basicConstraints: %r" % ku)
- eku = self.get_POW().getEKU()
+ def check_valid_request_ca(self):
+ """
+ Check this certification request to see whether it's a valid
+ request for an RPKI certificate. This is broken out of the
+ up-down protocol code because it's somewhat involved and the
+ up-down code doesn't need to know the details.
- if kind == "ca" and eku is not None:
- raise rpki.exceptions.BadPKCS10("EKU not allowed in CA certificate PKCS #10")
- elif kind == "router" and (eku is None or rpki.oids.id_kp_bgpsec_router not in eku):
- raise rpki.exceptions.BadPKCS10("EKU required for router certificate PKCS #10")
+ Throws an exception if the request isn't valid, so if this method
+ returns at all, the request is ok.
- if any(oid not in self.allowed_extensions
- for oid in self.get_POW().getExtensionOIDs()):
- raise rpki.exceptions.BadExtension("Forbidden extension(s) in PKCS #10 certificate request")
+ This needs refactoring, as the nested conditionals to handle the
+ different kinds of certificates have gotten rather nasty.
+ """
+ self.check_valid_request_common()
+
+ alg = self.get_POW().getSignatureAlgorithm()
+ bc = self.get_POW().getBasicConstraints()
+ eku = self.get_POW().getEKU()
sias = self.get_POW().getSIA()
- if kind == "router":
+ if alg != rpki.oids.sha256WithRSAEncryption:
+ raise rpki.exceptions.BadPKCS10("PKCS #10 request has bad signature algorithm %s" % alg)
+
+ if bc is None or not bc[0] or bc[1] is not None:
+ raise rpki.exceptions.BadPKCS10("PKCS #10 bad basicConstraints")
- if sias is not None:
- raise rpki.exceptions.BadPKCS10("router certificate PKCS #10 must not contain SIA extension")
+ if eku is not None:
+ raise rpki.exceptions.BadPKCS10("EKU not allowed in CA certificate PKCS #10")
+
+ if sias is None:
+ raise rpki.exceptions.BadPKCS10("PKCS #10 is missing SIA extension")
+
+ caRepository, rpkiManifest, signedObject = sias
- elif kind == "ca":
+ if signedObject:
+ raise rpki.exceptions.BadPKCS10("PKCS #10 CA certificate request has SIA id-ad-signedObject")
- if sias is None:
- raise rpki.exceptions.BadPKCS10("PKCS #10 is missing SIA extension")
+ if not caRepository:
+ raise rpki.exceptions.BadPKCS10("PKCS #10 CA certificate request is missing SIA id-ad-caRepository")
- caRepository, rpkiManifest, signedObject = sias
+ if not any(uri.startswith("rsync://") for uri in caRepository):
+ raise rpki.exceptions.BadPKCS10("PKCS #10 CA certificate request SIA id-ad-caRepository contains no rsync URIs")
- if signedObject:
- raise rpki.exceptions.BadPKCS10("PKCS #10 CA certificate request has SIA id-ad-signedObject")
+ if not rpkiManifest:
+ raise rpki.exceptions.BadPKCS10("PKCS #10 CA certificate request is missing SIA id-ad-rpkiManifest")
- if not caRepository:
- raise rpki.exceptions.BadPKCS10("PKCS #10 CA certificate request is missing SIA id-ad-caRepository")
+ if not any(uri.startswith("rsync://") for uri in rpkiManifest):
+ raise rpki.exceptions.BadPKCS10("PKCS #10 CA certificate request SIA id-ad-rpkiManifest contains no rsync URIs")
- if not any(uri.startswith("rsync://") for uri in caRepository):
- raise rpki.exceptions.BadPKCS10("PKCS #10 CA certificate request SIA id-ad-caRepository contains no rsync URIs")
+ if any(uri.startswith("rsync://") and not uri.endswith("/") for uri in caRepository):
+ raise rpki.exceptions.BadPKCS10("PKCS #10 CA certificate request SIA id-ad-caRepository does not end with slash")
- if not rpkiManifest:
- raise rpki.exceptions.BadPKCS10("PKCS #10 CA certificate request is missing SIA id-ad-rpkiManifest")
+ if any(uri.startswith("rsync://") and uri.endswith("/") for uri in rpkiManifest):
+ raise rpki.exceptions.BadPKCS10("PKCS #10 CA certificate request SIA id-ad-rpkiManifest ends with slash")
+
+
+ def check_valid_request_router(self):
+ """
+ Check this certification request to see whether it's a valid
+ request for a BGPSEC router certificate.
+
+ Throws an exception if the request isn't valid, so if this method
+ returns at all, the request is ok.
+
+ draft-ietf-sidr-bgpsec-pki-profiles 3.2 says follow RFC 6487 3
+ except where explicitly overriden, and does not override for SIA.
+ But draft-ietf-sidr-bgpsec-pki-profiles also says that router
+ certificates don't get SIA, while RFC 6487 requires SIA. So what
+ do we do with SIA in PKCS #10 for router certificates?
+
+ For the moment, ignore it, but make sure we don't include it in
+ the certificate when we get to the code that generates that.
+ """
+
+ self.check_valid_request_common()
+
+ alg = self.get_POW().getSignatureAlgorithm()
+ bc = self.get_POW().getBasicConstraints()
+ eku = self.get_POW().getEKU()
+ #sia = self.get_POW().getSIA()
+
+ if alg != rpki.oids.ecdsa_with_SHA256:
+ raise rpki.exceptions.BadPKCS10("PKCS #10 request has bad signature algorithm %s" % alg)
- if not any(uri.startswith("rsync://") for uri in rpkiManifest):
- raise rpki.exceptions.BadPKCS10("PKCS #10 CA certificate request SIA id-ad-rpkiManifest contains no rsync URIs")
+ if bc is not None and (bc[0] or bc[1] is not None):
+ raise rpki.exceptions.BadPKCS10("PKCS #10 has bad basicConstraints for router")
- if any(uri.startswith("rsync://") and not uri.endswith("/") for uri in caRepository):
- raise rpki.exceptions.BadPKCS10("PKCS #10 CA certificate request SIA id-ad-caRepository does not end with slash")
+ if eku is None or rpki.oids.id_kp_bgpsec_router not in eku:
+ raise rpki.exceptions.BadPKCS10("PKCS #10 for router requires EKU")
- if any(uri.startswith("rsync://") and uri.endswith("/") for uri in rpkiManifest):
- raise rpki.exceptions.BadPKCS10("PKCS #10 CA certificate request SIA id-ad-rpkiManifest ends with slash")
@classmethod
def create(cls, keypair, exts = None, is_ca = False,