Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect LCP Certificate Revocation List URL (Distribution Point) #218

Closed
danielweck opened this issue Dec 19, 2018 · 7 comments
Closed

Comments

@danielweck
Copy link
Member

@llemeurfr @aferditamuriqi @clebeaupin

In R2 test apps, the URL is currently hard-coded as:
http://crl.edrlab.telesec.de/rl/EDRLab_CA.crl.

However, the "official" CRL Distribution Point embedded inside the app-provided ECDSA certificate for LCP 1.0-production profile is:
http://crl.edrlab.telesec.de/rl/Readium_LCP_Root_CA.crl

openssl x509 -noout -text -in cert.pem | grep -A 4 'CRL Distribution Points'
==>

X509v3 CRL Distribution Points: 

Full Name:
URI:http://crl.edrlab.telesec.de/rl/Readium_LCP_Root_CA.crl

There are three possible options:

  1. Change nothing. However, because of the URL inconsistency, there is a possibility that implementations in the LCP ecosystem rely on two different Certificate Revocation Lists, so it is crucial that both URL endpoints return the exact same payload. Laurent, does EDRLab directly control this, or is there an intermediary operator?
  2. Modify the CRL URL inside the certificate, so it matches the hard-coded URL inside R2 test apps. However, this would require re-compiling R1 and R2 apps (including the R2 native C++ LCP lib) in order to ship the updated cert PEM => this is a deployment nightmare, because vendors in the ecosystem will be very reluctant to do so, and it would be hard to enforce / check anyway.
  3. Modify the CRL URL that is currently hard-coded in R2 apps, so it matches the embedded Distribution Points URL inside the certificate => that is also a deployment headache, because there might be vendors who are already using a hard-coded URL, and it will hard to enforce that everything is up to date.

So, quite clearly, the most realistic option with the least overhead is number 1. In fact, this may already be solved, for example is one URL is just a redirect to the other! (Laurent?) :)

Note that Readium1 implementations (i.e. based on readium-lcp-client lib) extract the CRL Distribution Point URLs directly from the shipped certificate, so they use the "official" URL instead of an arbitrary hard-coded one. Code reference:

https://github.com/readium/readium-lcp-client/blob/e4c02fdd396157062b80dcd6b787a2c6a72a0da0/src/lcp-client-lib/Certificate.cpp#L134

Note that the RSA certificate for LCP basic-test profile does not contain any CRL Dsitribution Points.

Note that in Readium2 apps, the Base64-encoded certificate PEM is shipped as hard-coded data inside the native C++ LCP lib, whereas in Readium1 apps it is shipped at the app level / inside the app bundle, as a separate text resource.

Code references:

iOS-Swift:
https://github.com/readium/r2-testapp-swift/blob/0fe5624fa6134a17ef5ed320575b547433d9f16a/r2-testapp-swift/AppDelegate.swift#L469

Android-Kotlin:
https://github.com/readium/r2-testapp-kotlin/blob/7adfc5c42a0d6b1e8ada7f11e79f11ccaaecf9b6/r2-testapp/src/withlcp/java/org/readium/r2/testapp/CatalogActivity.kt#L208

Electron-NodeJS:
https://github.com/readium/r2-lcp-js/blob/0ddb51b46ae8d2233394f7ede46ee8f93c6a2851/src/parser/epub/lcp-certificate.ts#L8

(as you can see, I decided to align with iOS/Android apps, but I do reference the alternative URL as well .. just in case we need a reminder of it later)

@llemeurfr
Copy link
Contributor

llemeurfr commented Jan 8, 2019

Readium_LCP_Root_CA.crl is the Authority Revocation List (ARL) and EDRLab_CA.crl is the Certificate Revocation List (CRL). Both are managed by a tier, not EDRLab.
If a license provider stop being part of the LCP Network, its provider certificate is added to the CRL. This is the file which has to be looked at by the reading application.
Only if EDRLab was not managing anymore the LCP Network, then its certificate (which is used as root certificate in our app but is in fact an intermediate certificate) would be added to the ARL.
A change in managing authority is something to study in the future, just in case, but I think that no modification is needed in our R2 code for the time being.
But please look again at the R1 codebase because I can't believe we grab the ARL instead of the CRL there.

@danielweck
Copy link
Member Author

danielweck commented Jan 9, 2019

Oh I see, so the fact that Readium_LCP_Root_CA.crl is referenced from the certificate that "ships" with the apps (i.e. plain text cert file in Readium1, but binary-encoded inside the Readium2 lib) is normal, right?
I imagine that EDRLab_CA.crl is referenced from the certificate that comes within individual LCP licenses, right? (I will test this)
If both statements above are true, then I think that the Readium1 readium-lcp-client C++ lib indeed fetches the correct CRL URL for revocation of provider certs specific to individually-issued LCP licenses (in fact, I believe you did run a live test with one of the LCP vendors, right?) Additionally, if I am not mistaken, the Readium1 implementation also checks the CRL URL for revocation of the "root" EDRLab cert common to all apps. This is something the Readium2 implementations don't do.

@danielweck
Copy link
Member Author

What is strange is that the ARL should not be advertised as a CRL ... unless maybe this is normal procedure in x509 certs (I am no expert in this field).

@danielweck
Copy link
Member Author

danielweck commented Jan 9, 2019

Regarding Readium1 / readium-lcp-client: Laurent, could you please confirm that wasteland-from-revoked-provider.lcp.epub was successfully tested? (iOS / Android apps)

Just to verify my assumptions in r2-lcp-js, I added code to extract the CRL/ARL URLs from both types of certificates (i.e. app-shipped "root" cert (RSA key) + license-bundled "provider" cert (ECDSA key)), instead of using hard-coded ones. I can indeed see the correct URLs. I added code comments to record this conversation:
readium/r2-lcp-js@c84fbc6

Naturally, I double-checked (once again) that the existing r2-lcp-js CRL implementation works against Laurent's sample test file ("wasteland-from-revoked-provider.lcp.epub") => indeed, the revoked provider certificate is correctly handled (i.e. the native LCP lib returns an error message, and the app informs the user that the publication cannot be opened).

lcp_revoked-provider-certificate_r2-testapp-js

@llemeurfr
Copy link
Contributor

Yes, Readium_LCP_Root_CA.crl is referenced from the certificate that "ships" with the apps (the EDRLab "root" certificate). And EDRLab_CA.crl is referenced from each provider certificate.

The CRL control is still not ready on the iOS R2 Reader test app, but it should be ok on the Android R2 Reader, Aferdita is checking that.

@danielweck
Copy link
Member Author

danielweck commented Feb 26, 2019

Resolution:
Right now, the Android, iOS and NodeJS implementations of LCP (i.e. r2-lcp-[kotlin|swift|js]) all implement the same hard-coded URL for the CRL "Distribution Point", instead of extracting it dynamically from the provider certificate stored in the LCP license. This is fine I think, because the URL is "stable".

However, if the URL changes in the future, the implementations will break, because even though newly-generated LCP licenses will contain provider certificates with the correct updated CRL "Distribution Point" URL, implementations will continue to use the old one which may resolve in error (in which case: CRL ignored, dummy used instead), or success (in which case: probably outdated list of revoked certs).

@danielweck
Copy link
Member Author

The other CRL "Distribution Point" URL supplied by the "root" certificate that shipped with the app (in Readium1, via the app bundle itself, in Readium2, hard-coded into the native r2-lcp-client lib for both LCP 1.0-prod and basic-test profiles) ... this one is not used anywhere. I guess this is okay, because CRL is critical for revoking provider certs, not root.

Closing this issue now (and the other platforms too).

@mickael-menu mickael-menu transferred this issue from readium/r2-testapp-swift Aug 12, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants