Open
Bug 1294897
Opened 9 years ago
Updated 2 years ago
track implementing and using js certificate decoder
Categories
(Core :: Security: PSM, defect, P3)
Core
Security: PSM
Tracking
()
NEW
Tracking | Status | |
---|---|---|
firefox51 | --- | affected |
People
(Reporter: keeler, Unassigned)
References
Details
(Whiteboard: [psm-tracking])
Attachments
(1 obsolete file)
This is a tracking bug for implementing an x509 certificate decoder in JS. Doing so will allow us to remove large sections of poorly-tested C++ and replace them with memory-safe code. Furthermore, we will be able to re-use this component to provide a more informational experience to users when certificate decoding or verification fails.
Comment hidden (mozreview-request) |
![]() |
Reporter | |
Comment 2•9 years ago
|
||
Comment on attachment 8780751 [details]
bug 1294897 - initial lintx509 implementation and demonstration of use
This is the initial proof-of-concept of the JS certificate decoder. In this patch it replaces much of the implementation of the certificate viewer (it's not complete yet). This is just a request for feedback to see if this seems like a good approach or if there's something I can do to simplify this work and/or make it easier to review (I'm intending to break this up into a number of sub-bugs to do the actual implementation work).
Attachment #8780751 -
Flags: feedback?(jjones)
Attachment #8780751 -
Flags: feedback?(cykesiopka.bmo)
![]() |
||
Comment 3•9 years ago
|
||
mozreview-review |
Comment on attachment 8780751 [details]
bug 1294897 - initial lintx509 implementation and demonstration of use
https://reviewboard.mozilla.org/r/71392/#review69516
Great stuff! The general approach here seems good to me.
The only suggestion I have for making this easier to review is to try and split up the implementation of lintx509.jsm into separate sub-bugs if possible (if you weren't planning to already) - I don't think I can effectively review 1.5k lines in one go.
::: security/manager/pki/resources/content/viewCertDetails.js:9
(Diff revision 1)
> "use strict";
>
> const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
> const { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
> +const { lintx509 } = Cu.import("resource://gre/modules/psm/lintx509.jsm", {});
> +const { console } = Cu.import("resource://gre/modules/Console.jsm", {});
Just as a reminder, we'll need to remove the ESLint rule we have enabled that forbids use of ```console```.
::: security/manager/pki/resources/content/viewCertDetails.js:799
(Diff revision 1)
> + return ava.value.toString();
> + }
> + }
> + }
> + } catch (e) {
> + console.log(e);
Nit: ```console.error(e);``` might be more appropriate.
::: security/manager/pki/resources/lintx509.jsm:47
(Diff revision 1)
> +const ERROR_UNSUPPORTED_GENERAL_NAME_TYPE = "error: unsupported GeneralName type";
> +
> +const X509v3 = 2;
> +const EC_UNCOMPRESSED_FORM = 4;
> +
> +class LintX509Error {
We should add ```extends Error``` and ```this.name = "LintX509Error";``` to take advantage of better exception handling and error output in some cases.
::: security/manager/pki/resources/lintx509.jsm:125
(Diff revision 1)
> + readBytes(length) {
> + if (this._cursor > this._bytes.length - length) {
> + throw new LintX509Error(ERROR_DATA_TRUNCATED);
> + }
> + let contents = this._bytes.slice(this._cursor, this._cursor + length);
> + this._cursor += length;
> + return contents;
> + }
I kinda feel like it would be better to just make this call readByte() in a loop so there are less places that mess with ```this._cursor``` directly, but I dunno if it's worth it.
If not, maybe it's a good idea to check that ```length``` is greater than 0, so we don't trigger the negative end index behaviour of ```slice()``` and get weird results back.
::: security/manager/pki/resources/lintx509.jsm:263
(Diff revision 1)
> + }
> +}
> +
> +class OID {
> + constructor(bytes) {
> + this._values = [];
Nit: This line is indented wrong.
::: security/manager/pki/resources/lintx509.jsm:363
(Diff revision 1)
> + parse() {
> + try {
> + this.parseOverride();
> + } catch (e) {
> + this._error = e;
> + }
> + }
Hmm, I'm not sure why we would want to eat exceptions here and in this manner.
It looks like nothing in this patch ever checks ```.error``` either.
If we end up keeping this exception eating behaviour, it seems less error prone to just have ```parse()``` return the success or error status directly.
::: security/manager/pki/resources/lintx509.jsm:710
(Diff revision 1)
> + result += String.fromCharCode(byte1);
> + } else if ((byte1 >> 5) == 6) {
> + // If the next byte is of the form 110xxxxx, this codepoint consists of
> + // two bytes. The other byte must be of the form 10xxxxxx.
> + if (i >= bytes.length) {
> + throw new LintX509Error(ERROR_INVALID_UTF8_ENCODING);
ERROR_INVALID_UTF8_ENCODING isn't defined anywhere.
::: security/manager/pki/resources/moz.build:8
(Diff revision 1)
> # This Source Code Form is subject to the terms of the Mozilla Public
> # License, v. 2.0. If a copy of the MPL was not distributed with this
> # file, You can obtain one at http://mozilla.org/MPL/2.0/.
>
> +EXTRA_JS_MODULES.psm += [
> + 'lintx509.jsm'
Commence the bikeshedding I guess. I think we should avoid "lint", since this module does more than that, but I struggle to think of a decent name right now.
Maybe just "X509.jsm"?
![]() |
||
Updated•9 years ago
|
Attachment #8780751 -
Flags: feedback?(cykesiopka.bmo) → feedback+
Comment 4•9 years ago
|
||
mozreview-review |
Comment on attachment 8780751 [details]
bug 1294897 - initial lintx509 implementation and demonstration of use
https://reviewboard.mozilla.org/r/71392/#review70774
This is quite a body of work already. :)
I provided a couple comments as well, but I know what you're really looking for is architectural. This may be your plan already, but my main suggestion is to build yourself a mechanism for your parser to accumulate errors in some structure, and those errors should have enough context to be able to eventually drive the UI - reference to the object itself, byte offsets, whatever else is handy.
Then, when possible, instead of throwing exceptions, log the error and continue. The time classes are great examples; there's so much that can go wrong there.
IMO, the Lint exception you throw should just be for cases where the ASN.1 format has failed and we can't continue processing -- this isn't security-critical code, after all, and we want it to be error-tolerant so the UI can populate even when things are weird.
::: security/manager/pki/resources/lintx509.jsm:125
(Diff revision 1)
> + readBytes(length) {
> + if (this._cursor > this._bytes.length - length) {
> + throw new LintX509Error(ERROR_DATA_TRUNCATED);
> + }
> + let contents = this._bytes.slice(this._cursor, this._cursor + length);
> + this._cursor += length;
> + return contents;
> + }
Agree with Cykesiopka: definitely check `length` is non-negative.
::: security/manager/pki/resources/lintx509.jsm:180
(Diff revision 1)
> + }
> +
> + assertAtEnd() {
> + if (this._cursor != this._bytes.length) {
> + throw new LintX509Error(ERROR_EXTRA_DATA);
> + }
Nit: Why not check `!atEnd()`?
::: security/manager/pki/resources/lintx509.jsm:1152
(Diff revision 1)
> + }
> + } else {
> + this._cA = false;
> + }
> +
> + if (contents.peekTag(INTEGER)) {
Is it actually allowed to have a `pathLen` when the cA flag is not set?
::: security/manager/pki/resources/lintx509.jsm:1410
(Diff revision 1)
> + parseOverride() {
> + let contents = this._der.readSEQUENCE();
> + this._features = [];
> + while (!contents.atEnd()) {
> + this._features.push(new ByteArray(contents.readINTEGER(), ":"));
> + }
You should assertEnd here, too, as you do for other loops even when the test is `atEnd()`. (See line 1304.)
Updated•8 years ago
|
Attachment #8780751 -
Flags: feedback?(jjones) → feedback+
![]() |
Reporter | |
Comment 5•8 years ago
|
||
Thank you both for the feedback. I've been working on decomposing this project into reviewable pieces. The first will be available in bug 1299676 shortly.
![]() |
Reporter | |
Updated•8 years ago
|
Attachment #8780751 -
Attachment is obsolete: true
Updated•2 years ago
|
Severity: normal → S3
You need to log in
before you can comment on or make changes to this bug.
Description
•