Open danielweck opened 5 years ago
Context: LCP-compliant applications ship with ECDSA
(LCP 1.0 / production profile) and/or RSA
(LCP basic / test profile) "Root" certificate issued by the CA (Certificate Authority) of the LCP ecosystem, which are used to validate the Provider Certificates shipped in individual licenses (using the public key of the Root Cert). In the case of LCP 1.0, this "Root" cert is actually an intermediate certificate, as there is in fact a proper "root" T-Systems ECDSA cert above in the chain ... but let's called this one the "Master" LCP ecosystem cert, instead of "root", to avoid confusion.
Readium2 implementation:
1) Check signature of Provider Certificate using Public Key from Root Certificate.
2) Check Provider Certificate against the CRL (Certificate Revocation List) which was obtained from the CRL Distribution Point URL - http://crl.edrlab.telesec.de/rl/EDRLab_CA.crl - which itself can be hard-coded, or available directly from the Provider Cert.
3) Check that the License issued
/updated
dates are within the validity range of the Provider Certificate (in other words, check the Cert's expiry)
4) Check that the signature contained in the License matches the signature generated by signing the Canonical License with the Public Key from the Provider Certificate.
5) Check that the provided User Key (derived from the User Passphrase) correctly decrypts the License KeyCheck as the License Identifier.
6) Check that the "now" date is within the License's start
and end
range of dates (if these are specified in the License, which in practice is the case with a "loan", but not with a "buy" kind of License).
Side note about CRL: for optimum User eXperience, there should be a caching/update mechanism to ensure the CRL is refreshed regularly from its Distribution Point URL, without causing UX delays due to HTTP latency and network timeouts.
Readium1 implementation:
Code path: OpenLicense
> VerifyNode
(root) > VerifyLicense
> VerifyCertificate
> CheckRevokation
> VerifySignature
> verify cert expiry date
> VerifyNode(s)
(crypto, links, user, rights) > DecryptContentKey
https://github.com/readium/readium-lcp-client/blob/e4c02fdd396157062b80dcd6b787a2c6a72a0da0/src/lcp-client-lib/LcpService.cpp#L138 => https://github.com/readium/readium-lcp-client/blob/e4c02fdd396157062b80dcd6b787a2c6a72a0da0/src/lcp-client-lib/LcpService.cpp#L194 => https://github.com/readium/readium-lcp-client/blob/e4c02fdd396157062b80dcd6b787a2c6a72a0da0/src/lcp-client-lib/RootLcpNode.cpp#L177 => https://github.com/readium/readium-lcp-client/blob/e4c02fdd396157062b80dcd6b787a2c6a72a0da0/src/lcp-client-lib/CryptoppCryptoProvider.cpp#L166 => https://github.com/readium/readium-lcp-client/blob/e4c02fdd396157062b80dcd6b787a2c6a72a0da0/src/lcp-client-lib/CryptoppCryptoProvider.cpp#L172 => https://github.com/readium/readium-lcp-client/blob/e4c02fdd396157062b80dcd6b787a2c6a72a0da0/src/lcp-client-lib/CryptoppCryptoProvider.cpp#L181 => https://github.com/readium/readium-lcp-client/blob/e4c02fdd396157062b80dcd6b787a2c6a72a0da0/src/lcp-client-lib/CryptoppCryptoProvider.cpp#L186 => https://github.com/readium/readium-lcp-client/blob/e4c02fdd396157062b80dcd6b787a2c6a72a0da0/src/lcp-client-lib/CryptoppCryptoProvider.cpp#L124 => https://github.com/readium/readium-lcp-client/blob/e4c02fdd396157062b80dcd6b787a2c6a72a0da0/src/lcp-client-lib/CryptoLcpNode.cpp#L97 => https://github.com/readium/readium-lcp-client/blob/e4c02fdd396157062b80dcd6b787a2c6a72a0da0/src/lcp-client-lib/LinksLcpNode.cpp#L179 => https://github.com/readium/readium-lcp-client/blob/e4c02fdd396157062b80dcd6b787a2c6a72a0da0/src/lcp-client-lib/UserLcpNode.cpp#L74 => https://github.com/readium/readium-lcp-client/blob/e4c02fdd396157062b80dcd6b787a2c6a72a0da0/src/lcp-client-lib/RightsLcpNode.cpp#L68 => https://github.com/readium/readium-lcp-client/blob/cbcc44390f7f2100093c0e082acb1e4cb7ab9b0a/src/lcp-client-lib/CryptoppCryptoProvider.cpp#L285
1) Same as Readium2 (1) 2) Same as Readium2 (2) 3) Same as Readium2 (4) NOTE: inverted 3-4 4) Same as Readium2 (3) NOTE: inverted 4-3 5) Same as Readium2 (6) NOTE: inverted 5-6 6) Same as Readium2 (5) NOTE: inverted 6-5
Recap/repeat of Readium2 implementation (to compare with above):
1) Check signature of Provider Certificate using Public Key from Root Certificate.
2) Check Provider Certificate against the CRL (Certificate Revocation List) which was obtained from the CRL Distribution Point URL - http://crl.edrlab.telesec.de/rl/EDRLab_CA.crl - which itself can be hard-coded, or available directly from the Provider Cert.
3) Check that the License issued
/updated
dates are within the validity range of the Provider Certificate (in other words, check the Cert's expiry)
4) Check that the signature contained in the License matches the signature generated by signing the Canonical License with the Public Key from the Provider Certificate.
5) Check that the provided User Key (derived from the User Passphrase) correctly decrypts the License KeyCheck as the License Identifier.
6) Check that the "now" date is within the License's start
and end
range of dates (if these are specified in the License, which in practice is the case with a "loan", but not with a "buy" kind of License).
Related issue: https://github.com/readium/lcp-specs/issues/25
Example: https://github.com/readium/lcp-specs/blob/master/releases/lcp/latest.md#55-validating-the-certificate-and-signature (this is just a particular example, in the specification there are other disconnected / isolated fragments of conformance definitions)
...versus an "algorithm" (written in prose) for reading system implementors, such as: https://github.com/readium/architecture/tree/master/other/lcp#6-validate-the-license-integrity